Mac IOKit USB信号检测

发布于 2024-10-22 23:34:10 字数 902 浏览 8 评论 0原文

 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 电脑时处理通知是可以的,但是当用户按下 USB 设备上的按钮时我可以收到信号吗?

谢谢大家!

 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);

For handle the notification while add the usb device to Mac pc is ok, but can i getting the signal while user press the button on the usb device?

Thanks ALL!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

荒岛晴空 2024-10-29 23:34:10

如果用户按下设备上的按钮,则不会创建设备通知。除非这是 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 Displays 有 3 个按钮,“+”和“-”用于调节亮度,还有一个电源按钮。电源按钮的功能可以在系统首选项中进行配置,例如,如果我愿意,它可以让整个 Mac 进入睡眠状态。每当我按下其中一个按钮时,就会创建一个中断事件并通过此 USB 管道发送到系统(实际上系统必须每 16 毫秒轮询一次此类事件,但系统会为您执行此操作 - 您的代码可以假装事件由监视器推送)。

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

在这里您可以获得所有这些的列表接口。是的,文档太糟糕了。您必须通过尝试和/或示例代码来学习。请注意有DeviceInterfaces和InterfaceInterfaces;那不是一回事。 DeviceInterface是设备本身的驱动程序接口,每个设备可以有多个“USB接口”(这是USB标准的术语),并且这种“USB接口”的接口被命名为“InterfaceInterface”。不过,简单的设备(如上面所示的显示器)只有一个接口。

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

Apple 试图解释您在开始编写任何代码之前应该了解的大部分 USB 基础知识 此页面。如果您单击“使用 USB 设备接口”,Apple 甚至提供了大量示例代码来教您如何获取 DeviceInterface,您可以使用它来获取 InterfaceInterface。

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

If a user presses a button on a device, this will not create a device notification. Unless this is a device Apple has a driver for (in which case you may receive an input event, e.g. an NSEvent), you will have to get the device interface and talk to that device through its interface. E.g. USB devices have interfaces, each interface has endpoints and the connections to those endpoints are labeled pipelines. There are outgoing and incoming pipelines and you can send data to or read data from those pipelines. Different kind of pipelines exist, bulk, isochronous and interrupt pipelines. Further every device has a control pipe, the only pipeline you can use bidirectionally.

Apple ships a tool named USB Prober with Xcode, have a look at your USB devices with it. E.g. my Apple Cinema Display, also connected via USB, reports the following:

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

This device has one Interface, Interface #0 and there exist one endpoint on this interface (0x81), which is connected through an interrupt pipeline, that can transfer packets up to 8 bytes in size every 16 ms. If you'd now want to communicate with that pipeline, you'll have to get the USB driver interface of the device and this interface offers functions to communicate with the pipeline in question, synchronously or asynchronously, it's all pretty similar to network code.

If you now ask yourself, what this pipeline is good for at a monitor in the first place, it's how the monitor communicates button presses to the system. Apple's Cinema Displays have 3 buttons, "+" and "-" for brightness and a power button. The functionality of the power button is configurable in the system prefs, e.g. it can send the whole Mac to sleep if I want that. Whenever I hit one of those button, an interrupt event is created and sent via this USB pipe to the system (actually the system has to poll for such an event every 16 ms, but the system does that for you - your code can pretend the event was pushed by the monitor).

Have a look at the IOUSBDeviceInterface197, and please note, that it inherits of IOUSBDeviceInterface187, which inherits of IOUSBDeviceInterface182, which again inherits of IOUSBDeviceInterface. That means if you retrieve a 197 version of the interface, all methods of the interfaces it inherits from are available for this interface as well (they are just not listed again on the page). Apple has to use interface with versions in the name to stay compatible with older code. Apple extended the USB interfaces over the time (e.g. with new OS X releases) and to be sure that old code still runs, they always added a new interfaces, otherwise they'd break existing code.

Here you get a list of all these interfaces. Yes, the documentation is horrible. You have to learn by try and and/or and sample code. Please note there are DeviceInterfaces and InterfaceInterfaces; that's not the same thing. A DeviceInterface is the driver interface to a device itself, every device can have multiple "USB interfaces" (this is a term of the USB standard) and the interface to such an "usb interface" is named an "InterfaceInterface". Simple devices, as the monitor shown above, only have a single interface, though.

You think that this is darn complicated? Well, most developers from other platforms say, that once they figured out how all this stuff works, Mac OS is the easiest of all platforms if you need raw access to USB pipes. However, it gets even worse: Every interface can have multiple configurations and you can set a configuration on the interface which might change the pipelines (e.g. in one configuration a pipe is a bulk pipe and in another one the very same pipe is now an isochronous pipe). You can see all this in the USB Prober application (it shows alternative configuration). And please note, that an USB device can have a completely different set of interfaces, pipelines and configurations for different speeds (e.g. one for USB 1.2, aka low + full speed, and one for USB 2, aka hi-speed).

Apple tries to explain most of the USB basics you should know before you start writing any code on this page. And if you click on "Working With USB Device Interfaces", Apple even has plenty of sample code for you how to get a DeviceInterface, which you can use to get InterfaceInterfaces.

I hope I could get you some pointers and some interesting links for reading. It's not really the answer to your question, but it is a good start. Of course, you could also write a kernel driver (kernel extension) to add support for your device to the system, so that pressing the button generates an event that any software can handle without having to use IOKit at all... but I somehow doubt you want to go there.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文