2012-07-24 105 views
3

我一直试图在添加或删除特定USB设备时得到通知。我已阅读“从应用程序访问硬件”文档,并有一个基本上以该文档中提供的代码为基础的简单演示应用程序。IOKit设备添加/删除通知 - 只能触发一次?

它第一次添加或删除设备,但在此之后我的回调永远不会被调用。我无法解决为什么?任何人都可以发现我要去哪里吗?

(如果你想测试xcode项目) http://monkeyfood.com/testIOKitNOtificaiton.zip

感谢。

// 
// AppDelegate.m 
// testIOKitNotification 
// 
// Created by Diggory Laycock on 23/07/2012. 
// Copyright (c) 2012 MonkeyFood.com. All rights reserved. 
// 

#import "AppDelegate.h" 

@implementation AppDelegate 


//   Arduino USB info 
#define  matchVendorID   0x2341  
#define  matchProductID   0x0043 


#pragma mark - 
#pragma mark C Callback functions 
#pragma mark - 

void usbDeviceAppeared(void *refCon, io_iterator_t iterator){ 
    NSLog(@"Matching USB device appeared"); 
} 
void usbDeviceDisappeared(void *refCon, io_iterator_t iterator){ 
    NSLog(@"Matching USB device disappeared"); 
} 


@synthesize window = _window; 


#pragma mark - 
#pragma mark Application Methods 
#pragma mark - 



- (void)applicationDidFinishLaunching:(NSNotification *)aNotification 
{ 
    io_iterator_t newDevicesIterator; 
    io_iterator_t lostDevicesIterator; 

    newDevicesIterator = 0; 
    lostDevicesIterator = 0; 
    NSLog(@" "); 

    NSMutableDictionary *matchingDict = (__bridge NSMutableDictionary *)IOServiceMatching(kIOUSBDeviceClassName); 

    if (matchingDict == nil){ 
     NSLog(@"Could not create matching dictionary"); 
     return; 
    } 
    [matchingDict setObject:[NSNumber numberWithShort:matchVendorID] forKey:(NSString *)CFSTR(kUSBVendorID)]; 
    [matchingDict setObject:[NSNumber numberWithShort:matchProductID] forKey:(NSString *)CFSTR(kUSBProductID)]; 

    // Add notification ports to runloop 
    IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault); 
    CFRunLoopSourceRef notificationRunLoopSource = IONotificationPortGetRunLoopSource(notificationPort); 
    CFRunLoopAddSource([[NSRunLoop currentRunLoop] getCFRunLoop], notificationRunLoopSource, kCFRunLoopDefaultMode); 

    kern_return_t err; 
    err = IOServiceAddMatchingNotification(notificationPort, 
              kIOMatchedNotification, 
              (__bridge CFDictionaryRef)matchingDict, 
              usbDeviceAppeared, 
              (__bridge void *)self, 
              &newDevicesIterator); 
    if (err) 
    { 
     NSLog(@"error adding publish notification"); 
    } 
    [self matchingDevicesAdded: newDevicesIterator]; 


    NSMutableDictionary *matchingDictRemoved = (__bridge NSMutableDictionary *)IOServiceMatching(kIOUSBDeviceClassName); 

    if (matchingDictRemoved == nil){ 
     NSLog(@"Could not create matching dictionary"); 
     return; 
    } 
    [matchingDictRemoved setObject:[NSNumber numberWithShort:matchVendorID] forKey:(NSString *)CFSTR(kUSBVendorID)]; 
    [matchingDictRemoved setObject:[NSNumber numberWithShort:matchProductID] forKey:(NSString *)CFSTR(kUSBProductID)]; 


    err = IOServiceAddMatchingNotification(notificationPort, 
              kIOTerminatedNotification, 
              (__bridge CFDictionaryRef)matchingDictRemoved, 
              usbDeviceDisappeared, 
              (__bridge void *)self, 
              &lostDevicesIterator); 
    if (err) 
    { 
     NSLog(@"error adding removed notification"); 
    } 
    [self matchingDevicesRemoved: lostDevicesIterator]; 


    //  CFRunLoopRun(); 
    //  [[NSRunLoop currentRunLoop] run]; 

} 

#pragma mark - 
#pragma mark ObjC Callback functions 
#pragma mark - 

- (void)matchingDevicesAdded:(io_iterator_t)devices 
{ 
    io_object_t thisObject; 
    while ((thisObject = IOIteratorNext(devices))) { 
     NSLog(@"new Matching device added "); 
     IOObjectRelease(thisObject); 
    } 

} 


- (void)matchingDevicesRemoved:(io_iterator_t)devices 
{ 
    io_object_t thisObject; 
    while ((thisObject = IOIteratorNext(devices))) { 
     NSLog(@"A matching device was removed "); 
     IOObjectRelease(thisObject); 
    } 

} 


@end 

回答

1

我弄清楚了什么是错的 - 我没有对C回调中的迭代器做任何事情。一个愚蠢的错误!

+0

你应该将此标记为已解决! – tjarratt 2013-10-11 07:06:04

1

我有点迟,因为有一个公认的答案,但要解决这个问题,您需要在回调中迭代匹配的设备迭代器。但是这样做并不是微不足道的,因此下面是实现这一点的代码,因为回调函数是一个C函数,您希望将它与您的Objective C方法连接起来。

void usbDeviceAppeared(void *refCon, io_iterator_t iterator){ 
    NSLog(@"Matching USB device appeared"); 
    SerialMonitor *monitor = (__bridge SerialMonitor *)refCon; 
    [monitor matchingDevicesAdded:iterator]; 
    [monitor reload]; 
} 

void usbDeviceDisappeared(void *refCon, io_iterator_t iterator){ 
    NSLog(@"Matching USB device disappeared"); 
    SerialMonitor *monitor = (__bridge SerialMonitor *)refCon; 
    [monitor matchingDevicesRemoved:iterator]; 
    [monitor reload]; 
} 

SerialMonitor是我的USB设备管理器类,并reload是,做适当的USB设备初始化(获得专题报道和交换数据)的方法。