我正在为Mac编写基础工具,并尝试检测Apple设备何时通过USB连接和断开连接。我在this post和USBPrivateDataSample中找到了一些帮助 - 但是如果我同时提供供应商ID和产品ID,它似乎才有效。我想消除产品ID并找到Apple设备上的所有USB事件(供应商ID 1452)。这里有什么帮助吗?
这是我的代码似乎没有检测到任何设备:
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOMessage.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/usb/IOUSBLib.h>
#define kMyVendorID 1452
int list_devices(void);
int list_devices(void){
CFMutableDictionaryRef matchingDict;
io_iterator_t iter;
kern_return_t kr;
io_service_t device;
CFNumberRef numberRef;
long usbVendor = kMyVendorID;
/* set up a matching dictionary for the class */
matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class
// IOUSBDevice and its subclasses
if (matchingDict == NULL) {
fprintf(stderr, "IOServiceMatching returned NULL.\n");
return -1;
}
// We are interested in all USB devices (as opposed to USB interfaces). The Common Class Specification
// tells us that we need to specify the idVendor, idProduct, and bcdDevice fields, or, if we're not interested
// in particular bcdDevices, just the idVendor and idProduct. Note that if we were trying to match an
// IOUSBInterface, we would need to set more values in the matching dictionary (e.g. idVendor, idProduct,
// bInterfaceNumber and bConfigurationValue.
// Create a CFNumber for the idVendor and set the value in the dictionary
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor);
CFDictionarySetValue(matchingDict,
CFSTR(kUSBVendorID),
numberRef);
CFRelease(numberRef);
numberRef = NULL;
/* Now we have a dictionary, get an iterator.*/
kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
if (kr != KERN_SUCCESS)
return -1;
/* iterate */
while ((device = IOIteratorNext(iter)))
{
io_name_t deviceName;
CFStringRef deviceNameAsCFString;
/* do something with device, eg. check properties */
/* ... */
/* And free the reference taken before continuing to the next item */
// Get the USB device's name.
kr = IORegistryEntryGetName(device, deviceName);
if (KERN_SUCCESS != kr) {
deviceName[0] = '\0';
}
deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, deviceName,
kCFStringEncodingASCII);
// Dump our data to stderr just to see what it looks like.
fprintf(stderr, "deviceName: ");
CFShow(deviceNameAsCFString);
IOObjectRelease(device);
}
/* Done, release the iterator */
IOObjectRelease(iter);
return 1;
}
int main(int argc, char* argv[])
{
while(1){
list_devices();
sleep(1);
}
return 0;
}
值得注意的是:如果我将产品ID添加到matchingDict并插入这样的设备,它将发现设备没有问题(不更改供应商ID)。但我无法单独使用供应商ID找到它。
答案 0 :(得分:4)
要获取属于特定供应商的所有产品的列表,您可以在产品ID字段中使用通配符。示例匹配条件如下:
long vid = 1452; //Apple vendor ID
CFNumberRef refVendorId = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &vid);
CFDictionarySetValue (matchingDict, CFSTR ("idVendor"), refVendorId);
CFRelease(refVendorId);
//all product by same vendor
CFDictionarySetValue (matchingDict, CFSTR ("idProduct"), CFSTR("*"));
答案 1 :(得分:1)
创建仅包含VID条目的字典过滤器应该与该供应商的所有PID匹配。我建议您注册设备插入回调,而不是在自己的代码中进行轮询。让操作系统处理检测并异步通知您的应用程序。
这段代码适合我:
#import "IOKit/hid/IOHIDManager.h"
#include <IOKit/usb/IOUSBLib.h>
@implementation MyApp
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
IOHIDManagerRef HIDManager = IOHIDManagerCreate(kCFAllocatorDefault,
kIOHIDOptionsTypeNone);
CFMutableDictionaryRef matchDict = CFDictionaryCreateMutable(
kCFAllocatorDefault,
2,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
int vid = 0x1234; // ToDo: Place your VID here
CFNumberRef vid_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &vid);
CFDictionarySetValue(matchDict, CFSTR(kUSBVendorID), vid_num);
CFRelease(vid_num);
IOHIDManagerSetDeviceMatching(HIDManager, matchDict);
// Here we use the same callback for insertion & removal.
// Use separate handlers if desired.
IOHIDManagerRegisterDeviceMatchingCallback(HIDManager, Handle_UsbDetectionCallback, (__bridge void*)self);
IOHIDManagerRegisterDeviceRemovalCallback(HIDManager, Handle_UsbDetectionCallback, (__bridge void*)self);
IOHIDManagerScheduleWithRunLoop(HIDManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
IOHIDManagerOpen(HIDManager, kIOHIDOptionsTypeNone);
}
// New USB device specified in the matching dictionary has been added (callback function)
static void Handle_UsbDetectionCallback(void *inContext, IOReturn inResult, void *inSender, IOHIDDeviceRef inIOHIDDeviceRef) {
//ToDo: Code for dealing with the USB device
}
@end