【问题标题】:IOKit device adding/removal notifications - only fire once?IOKit 设备添加/删除通知 - 只触发一次?
【发布时间】:2012-07-24 09:45:09
【问题描述】:

我一直在尝试在添加或删除特定 USB 设备时收到通知。我已阅读“从应用程序访问硬件”文档并有一个简单的演示应用程序,主要基于该文档中提供的代码。

第一次添加或删除设备时它会起作用,但之后我的回调就不会被调用。我不知道为什么?谁能发现我哪里出错了?

(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

【问题讨论】:

    标签: macos cocoa iokit


    【解决方案1】:

    我已经找出了问题所在 - 我没有对 C 回调中的迭代器做任何事情。一个愚蠢的错误!

    【讨论】:

      【解决方案2】:

      我有点晚了,因为有一个可接受的答案,但要解决这个问题,您需要在回调中迭代匹配的设备迭代器。但这样做并非易事,所以这里是实现这一目标的代码,因为回调是一个 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 设备初始化(获取功能报告和交换数据)的方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-23
        • 1970-01-01
        • 1970-01-01
        • 2016-07-02
        • 2015-04-02
        • 1970-01-01
        相关资源
        最近更新 更多