【问题标题】:Mac IOKit USB signal detectionMac IOKit USB 信号检测
【发布时间】:2011-07-17 03:26:03
【问题描述】:
 matchingDict = IOServiceMatching(kIOUSBDeviceClassName); 

 numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendorId);  
 CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef);  
 CFRelease(numberRef);  

 numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &deviceProductId);  
 CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), numberRef);  
 CFRelease(numberRef);  
 numberRef = NULL;  

 kr = IOServiceAddMatchingNotification(gNotifyPort,   
                                       kIOFirstMatchNotification,   
                                       matchingDict,   
                                       DeviceAdded,   
                                       NULL,  
                                       &gAddedIter);

在将 USB 设备添加到 Mac pc 时处理通知是可以的,但是当用户按下 USB 设备上的按钮时我可以收到信号吗?

谢谢大家!

【问题讨论】:

  • 这和 Cocoa 无关,是 IOKit 的问题。重新标记。

标签: macos usb core-foundation iokit


【解决方案1】:

如果用户按下设备上的按钮,则不会创建设备通知。除非这是 Apple 有驱动程序的设备(在这种情况下,您可能会收到输入事件,例如 NSEvent),否则您必须获取设备接口并通过其接口与该设备通信。例如。 USB 设备有接口,每个接口都有端点,到这些端点的连接被标记为管道。有传出和传入管道,您可以向这些管道发送数据或从这些管道读取数据。存在不同类型的流水线,批量流水线、同步流水线和中断流水线。此外,每个设备都有一个控制管道,这是唯一可以双向使用的管道。

Apple 在 Xcode 中附带了一个名为 USB Prober 的工具,用它来检查你的 USB 设备。例如。我的 Apple Cinema Display 也通过 USB 连接,报告如下:

Full Speed device @ 3 (0xFD520000): .............................................   Composite device: "Apple Cinema HD Display"
    Port Information:   0x0019
           Captive
           External Device
           Connected
           Enabled
    Device Descriptor   
        Descriptor Version Number:   0x0110
        Device Class:   0   (Composite)
        Device Subclass:   0
        Device Protocol:   0
        Device MaxPacketSize:   8
        Device VendorID/ProductID:   0x05AC/0x9223   (Apple Inc.)
        Device Version Number:   0x0114
        Number of Configurations:   1
        Manufacturer String:   1 "Apple Computer, Inc."
        Product String:   2 "Apple Cinema HD Display"
        Serial Number String:   0 (none)
    Configuration Descriptor   
        Length (and contents):   34
            Raw Descriptor (hex)    0000: 09 02 22 00 01 01 00 E0  01 09 04 00 00 01 03 00  
            Raw Descriptor (hex)    0010: 00 00 09 21 11 01 00 01  22 37 00 07 05 81 03 08  
            Raw Descriptor (hex)    0020: 00 10 
        Number of Interfaces:   1
        Configuration Value:   1
        Attributes:   0xE0 (self-powered, remote wakeup)
        MaxPower:   2 ma
        Interface #0 - HID   
            Alternate Setting   0
            Number of Endpoints   1
            Interface Class:   3   (HID)
            Interface Subclass;   0
            Interface Protocol:   0
            HID Descriptor   
                Descriptor Version Number:   0x0111
                Country Code:   0
                Descriptor Count:   1
                Descriptor 1   
                    Type:   0x22  (Report Descriptor)
                    Length (and contents):   55
                        Raw Descriptor (hex)    0000: 05 80 09 01 A1 01 15 00  26 FF 00 75 08 85 02 96  
                        Raw Descriptor (hex)    0010: 01 01 09 02 B2 02 01 05  82 95 02 85 10 09 10 B1  
                        Raw Descriptor (hex)    0020: 02 25 04 85 D6 09 D6 B1  02 25 07 85 E7 B1 02 26  
                        Raw Descriptor (hex)    0030: FF 00 85 E4 81 02 C0 
                    Parsed Report Descriptor:   
                          Usage Page    (Monitor) 
                          Usage 1 (0x1)    
                              Collection (Application)    
                                Logical Minimum.........    (0)  
                                Logical Maximum.........    (255)  
                                Report Size.............    (8)  
                                ReportID................    (2)  
                                Report Count............    (257)  
                                Usage 2 (0x2)    
                                Feature.................   (Data, Variable, Absolute, No Wrap, Linear, Preferred State, No Null Position, Nonvolatile, Buffered bytes) 
                                Usage Page    (VESA Virtual Controls) 
                                Report Count............    (2)  
                                ReportID................    (16)  
                                Usage 16 (0x10)    
                                Feature.................   (Data, Variable, Absolute, No Wrap, Linear, Preferred State, No Null Position, Nonvolatile, Bitfield) 
                                Logical Maximum.........    (4)  
                                ReportID................    (214)  
                                Usage 214 (0xd6)    
                                Feature.................   (Data, Variable, Absolute, No Wrap, Linear, Preferred State, No Null Position, Nonvolatile, Bitfield) 
                                Logical Maximum.........    (7)  
                                ReportID................    (231)  
                                Feature.................   (Data, Variable, Absolute, No Wrap, Linear, Preferred State, No Null Position, Nonvolatile, Bitfield) 
                                Logical Maximum.........    (255)  
                                ReportID................    (228)  
                                Input...................   (Data, Variable, Absolute, No Wrap, Linear, Preferred State, No Null Position, Bitfield) 
                              End Collection     
            Endpoint 0x81 - Interrupt Input   
                Address:   0x81  (IN)
                Attributes:   0x03  (Interrupt no synchronization data endpoint)
                Max Packet Size:   8
                Polling Interval:   16 ms

这个设备有一个接口,接口#0,并且在这个接口(0x81)上有一个端点,它通过中断管道连接,每16毫秒可以传输最大8字节的数据包。如果您现在想与该管道通信,则必须获取设备的 USB 驱动程序接口,该接口提供与相关管道进行同步或异步通信的功能,这与网络代码非常相似。

如果您现在问自己,这个管道首先对监视器有什么好处,那就是监视器如何将按钮按下传达给系统。 Apple 的 Cinema Display 有 3 个按钮,“+”和“-”用于亮度和一个电源按钮。电源按钮的功能可在系统首选项中配置,例如如果我愿意,它可以让整个 Mac 进入睡眠状态。每当我点击其中一个按钮时,都会创建一个中断事件并通过此 USB 管道发送到系统(实际上系统必须每 16 毫秒轮询一次此类事件,但系统会为您执行此操作 - 您的代码可以假装事件被监视器推送)。

查看IOUSBDeviceInterface197,请注意,它继承了 IOUSBDeviceInterface187,后者继承了 IOUSBDeviceInterface182,后者又继承了 IOUSBDeviceInterface。这意味着如果您检索 197 版本的接口,它继承的接口的所有方法也可用于该接口(它们只是没有在页面上再次列出)。 Apple 必须使用名称中带有版本的接口才能与旧代码保持兼容。随着时间的推移,Apple 扩展了 USB 接口(例如,随着新的 OS X 版本),为了确保旧代码仍然可以运行,他们总是添加新接口,否则他们会破坏现有代码。

Here you get a list 所有这些接口。是的,文档很糟糕。您必须通过尝试和/或示例代码来学习。请注意有 DeviceInterfaces 和 InterfaceInterfaces;那不是一回事。 DeviceInterface 是设备本身的驱动接口,每个设备可以有多个“USB 接口”(这是 USB 标准的一个术语),这样一个“usb 接口”的接口被命名为“InterfaceInterface”。不过,简单的设备(如上图所示的监视器)只有一个接口。

你认为这很复杂吗?好吧,大多数来自其他平台的开发人员说,一旦他们弄清楚所有这些东西是如何工作的,如果您需要对 USB 管道的原始访问,Mac OS 是所有平台中最简单的。然而,情况变得更糟:每个接口都可以有多个配置,您可以在接口上设置可能会更改管道的配置(例如,在一种配置中,管道是大容量管道,而在另一种配置中,相同的管道现在是等时的管道)。您可以在 USB Prober 应用程序中看到所有这些(它显示了替代配置)。请注意,USB 设备可以有一组完全不同的接口、管道和配置,用于不同的速度(例如,一个用于 USB 1.2,即低速 + 全速,一个用于 USB 2,即高速)。

在您开始在this page 上编写任何代码之前,Apple 会尝试解释您应该了解的大部分 USB 基础知识。如果你点击“Working With USB Device Interfaces”,Apple 甚至有大量的示例代码教你如何获取 DeviceInterface,你可以使用它来获取 InterfaceInterfaces。

我希望我能给你一些建议和一些有趣的阅读链接。这不是您问题的真正答案,但它是一个好的开始。当然,您也可以编写一个内核驱动程序(内核扩展)来为您的设备添加对系统的支持,以便按下按钮会生成一个任何软件都可以处理的事件,而无需使用 IOKit……但我不知何故怀疑你想去那里。

【讨论】:

  • 现在我可以得到接口了,但是如何在用户按下按钮时从设备读取信号?
  • @rocksing:由于我不知道您的设备有哪些接口和管道,所以我无法真正回答这个问题。您如何使用 USB Prober 创建有问题的设备的转储,就像我在答案中包含的设备一样,并将其添加到您的原始问题中?有了这些信息,我也许可以为您编写一些代码,可以将设备发送到系统的所有原始数据转储到控制台,然后我们可以看到当您按下按钮时会发生什么。
  • 在USB Prober中创建转储是什么意思?
  • USB Prober 是 Apple 开发者工具的一个应用程序,我在回复中引用了一个 Dump,从“全速设备”等开始。设备转储包含有关此设备接口、配置和管道的信息。没有它,我无法告诉你如何与设备对话,因为它取决于所有这些信息。
  • 如果设备不是“全速设备”,“高速设备”有问题吗??
猜你喜欢
  • 2013-06-22
  • 2015-04-02
  • 1970-01-01
  • 1970-01-01
  • 2019-07-07
  • 2012-02-08
  • 1970-01-01
  • 1970-01-01
  • 2012-04-24
相关资源
最近更新 更多