2013-12-15 21 views
5

IOKitを把握しようとしていますが、私は近いと感じていますが、まだありません。だから私の混乱を許してください。割り込み入力エンドポイントを使用してIOKitを使用してコールバックを取得

私は自分のUSBデバイス(Windowsドライバを持っているが、Macドライバを持っていないUSBケーブルの端にある簡単なボタン)を検出するコードを書いています。

ボタンを押したときに何らかのコールバックを取得しようとしています。

私は、デバイスがUSBに接続されているか、または取り外されたときにコールバックを取得することができます。今、私はボタンが押されたときに情報を得る方法を見つけようとしていますが、私はそれを理解できません。 IOKitはあなたのアクセス方法(カーネルエクステンションやユーザースペースドライバなど)に応じて、IOKitがC++とcの両方で利用できるように思われるので、ドキュメントは非常に混乱しています。

私はコードに表示されるように割り込み値が変化したときにコールバックを取得する方法をいくつか追加しましたが、何も起こりません。 。デバイス

Low Speed device @ 5 (0x14100000): ............................................. Composite device: "DL100B Dream Cheeky Generic Controller" 
Port Information: 0x101a 
Number Of Endpoints (includes EP0): 
Device Descriptor 
Configuration Descriptor (current config) 
    Length (and contents): 34 
    Number of Interfaces: 1 
    Configuration Value: 1 
    Attributes: 0x80 (bus-powered) 
    MaxPower: 500 mA 
    Interface #0 - HID 
     Alternate Setting 0 
     Number of Endpoints 1 
     Interface Class: 3 (HID) 
     Interface Subclass; 0 
     Interface Protocol: 0 
     HID Descriptor 
     Endpoint 0x81 - Interrupt Input 
      Address: 0x81 (IN) 
      Attributes: 0x03 (Interrupt) 
      Max Packet Size: 8 
      Polling Interval: 10 ms 

のApp Delegate.mファイル:

// 
// USBHIDAppDelegate.m 
// USBHID 
// 
// Created by Michael Dolinar on 12-05-02. 
// Copyright (c) 2012 __MyCompanyName__. All rights reserved. 
// 

#import "USBHIDAppDelegate.h"  
#import "IOKit/hid/IOHIDManager.h" 
#include <IOKit/IOKitLib.h> 
#include <IOKit/IOCFPlugIn.h> 
#include <IOKit/usb/IOUSBLib.h> 
#include <IOKit/usb/USBSpec.h> 

@implementation USBHIDAppDelegate 

@synthesize window = _window; 

// New USB device specified in the matching dictionary has been added (callback function) 
static void Handle_DeviceMatchingCallback(void *inContext, 
              IOReturn inResult, 
              void *inSender, 
              IOHIDDeviceRef inIOHIDDeviceRef){ 

    // Retrieve the device name & serial number 
    NSString *devName = [NSString stringWithUTF8String: 
         CFStringGetCStringPtr(
               IOHIDDeviceGetProperty(inIOHIDDeviceRef, 
                     CFSTR("Product")), 
               kCFStringEncodingMacRoman)]; 

    UInt32 serialString = CFStringGetCStringPtr(
          IOHIDDeviceGetProperty(inIOHIDDeviceRef, 
               CFSTR("SerialNumber")), 
          kCFStringEncodingMacRoman); 
    NSString *devSerialNumber; 
    if (serialString == 0) { 
     devSerialNumber = @"No Serial Number"; 

    } else { 
     devSerialNumber = [NSString stringWithUTF8String:serialString]; 

    } 
    // Log the device reference, Name, Serial Number & device count 
    NSLog(@"\nDevice added: %p\nModel: %@\nSerial Number:%@\nDevice count: %ld", 
      inIOHIDDeviceRef, 
      devName, 
      devSerialNumber, 
      USBDeviceCount(inSender)); 

//Open the device (Was missing) 
IOReturn err = IOHIDDeviceOpen(inIOHIDDeviceRef, 0); 

// ...ここでエラーをチェックする必要があります

IOHIDDeviceRegisterInputValueCallback(inIOHIDDeviceRef, Handle_IOHIDDeviceInputValueCallback, NULL); 

//もまた IOHIDDeviceScheduleWithRunLoop(inIOHIDDeviceRef、CFRunLoopGetCurrent()、kCFRunLoopCommonModes)に欠落していた...ここで再び実行ループのために登録する必要があります。

私はどのようにすることができます...レベル7で、USBロガーを使用してログインしてみますが、唯一のボタンを押しても何も表示されていないようです...デバイスは何も送信されても​​わからないんだけど
} 

static void Handle_IOHIDDeviceInputValueCallback(void *inContext, 
               IOReturn inResult, 
                void *inSender, 
               IOHIDValueRef inIOHIDValueRef 
               ) 
{ 
    NSLog(@"Value changed"); 
} 


// USB device specified in the matching dictionary has been removed (callback function) 
static void Handle_DeviceRemovalCallback(void *inContext, 
             IOReturn inResult, 
             void *inSender, 
             IOHIDDeviceRef inIOHIDDeviceRef){ 

    // Log the device ID & device count 
    NSLog(@"\nDevice removed: %p\nDevice count: %ld", 
      (void *)inIOHIDDeviceRef, 
      USBDeviceCount(inSender)); 
    IOHIDDeviceRegisterInputValueCallback(inIOHIDDeviceRef, NULL, NULL); //Remove callback 

} 





// Counts the number of devices in the device set (incudes all USB devices that match our dictionary) 
static long USBDeviceCount(IOHIDManagerRef HIDManager){ 

    // The device set includes all USB devices that match our matching dictionary. Fetch it. 
    CFSetRef devSet = IOHIDManagerCopyDevices(HIDManager); 

    // The devSet will be NULL if there are 0 devices, so only try to count the devices if devSet exists 
    if(devSet) return CFSetGetCount(devSet); 

    // There were no matching devices (devSet was NULL), so return a count of 0 
    return 0; 
} 


- (void)applicationDidFinishLaunching:(NSNotification *)aNotification 
{ 
    // Insert code here to initialize your application 
    SInt32 idVendor = 0x1D34;//0x062A;//0x1d34; //0x1AAD; //// set vendor id 
    SInt32 idProduct = 0x000D;//0x0000;//0x000d; //0x000F; //// set product id 

    // Create an HID Manager 
    IOHIDManagerRef HIDManager = IOHIDManagerCreate(kCFAllocatorDefault, 
                kIOHIDOptionsTypeNone); 

    // Create a Matching Dictionary 
    CFMutableDictionaryRef matchDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 
                   2, 
                   &kCFTypeDictionaryKeyCallBacks, 
                   &kCFTypeDictionaryValueCallBacks); 

    // Specify a device manufacturer in the Matching Dictionary 

    CFDictionarySetValue(matchDict, 
         CFSTR(kIOHIDVendorIDKey), 
         CFNumberCreate(kCFAllocatorDefault, 
             kCFNumberSInt32Type, &idVendor)); 
    CFDictionarySetValue(matchDict, 
         CFSTR(kIOHIDProductKey), 
         CFNumberCreate(kCFAllocatorDefault, 
             kCFNumberSInt32Type, &idProduct)); 


    // Register the Matching Dictionary to the HID Manager 
    IOHIDManagerSetDeviceMatching(HIDManager, matchDict); 

    // Register a callback for USB device detection with the HID Manager 
    IOHIDManagerRegisterDeviceMatchingCallback(HIDManager, &Handle_DeviceMatchingCallback, NULL); 
    // Register a callback fro USB device removal with the HID Manager 
    IOHIDManagerRegisterDeviceRemovalCallback(HIDManager, &Handle_DeviceRemovalCallback, NULL); 

    // Register the HID Manager on our app’s run loop 
    IOHIDManagerScheduleWithRunLoop(HIDManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode); 

    // Open the HID Manager 
    IOReturn IOReturn = IOHIDManagerOpen(HIDManager, kIOHIDOptionsTypeNone); 
    if(IOReturn) NSLog(@"IOHIDManagerOpen failed."); // Couldn't open the HID manager! TODO: proper error handling 
} 
@end 

それが実際に動作していることを確認しますか?

更新:私はこれを学ぶために使用しているBigRedButtonにthis Ruby Open Source projectを使用してボタンプレスを検出できました。だから私はそれが実際に動作することを知っている デバイスが実際に検出されたときにのみ値の変更を登録し、デバイスが取り外されたときに値を削除するようにコードを修正しました。この時点ではまだ何もありません。

更新2:これが動作するようにしました! 2つの問題...私は読書のために装置を開きませんでしたし、現在のRunLoopに必要な装置自体も登録していませんでした。 WWDC 2011からのUserlandデバイスアクセスに関する素晴らしいWWDCビデオが大きく貢献しました。私が使っていたBigRedBUttonはおそらく標準的なデバイスではなく、それは計画どおりに動作しなかったと言わざるを得ないが、私が魅力的な作品を使ってみたいと思っていた実際のデバイスは、 WWDCのビデオのおかげで、今それはすべて良いです!

+0

私は実際にMichael Dolinarsチュートリアルのコードと同じコードを使用しています。 HIDマネージャーだけでなく、デバイスを開いて実行ループに追加するコードを投稿したり、おそらく私に送ってもらえますか?これは私自身が今現在固執しているところです。 –

+0

実際に何が起こったのかを確認してください。コードブロックが壊れていて、その一部がテキストのように見えていました。 –

答えて

4

最後に、上記のコードは、デバイスを開いて現在のrunloopでデバイスをスケジュールしたところで動作します。また、デバイスを変更することで、別のデバイスで動作することが可能になりました。このデバイスは、値を変更するより予測可能なエクスペリエンスを提供するようです。私はこれを見て、WWDC 2011のUserland Device Accessビデオを見て、これがどのように働いているかをよく理解してください(ビデオの約30分)。

UPDATE:デバイスが異なる反応をする理由は少し複雑です。まず、各USB HIDデバイスは複数の「設定」を持つことができ、デフォルトのUSB HIDデバイスは有効になっていない可能性があります。これを明示的に行う必要があります。次に、2番目の部分はすべて、デバイスから送信された値を理解することです。これは、返される各種類の値(レポートと呼ばれる)とそのビットとバイトの配置方法を詳細に記述する「HID Device Report Descriptors」を理解することによって行われます。

OS Xについては、これについては、New HID Manager APIs for Mac OS X version 10.5 TechNoteをご覧ください。 10.5にもなりますが、これは最新バージョンであり、適切な呼び出しがすべて含まれており、これがどのように機能するかをよりよく理解することができます。

また、ディスクリプタについてはthis tutorialが役に立ちました。

関連する問題