ユーザーがデバイスのボタンを押しても、デバイス通知は作成されません。これがAppleがドライバを持っているデバイスでない限り(この場合、NSEventなどの入力イベントを受け取る可能性があります)、デバイスインターフェイスを取得し、そのインターフェイスを介してそのデバイスと通信する必要があります。たとえば、USBデバイスにはインターフェイスがあり、各インターフェイスにはエンドポイントがあり、それらのエンドポイントへの接続にはパイプラインというラベルが付いています。発信パイプラインと着信パイプラインがあり、それらのパイプラインにデータを送信したり、それらのパイプラインからデータを読み取ったりできます。パイプラインには、バルクパイプライン、アイソクロナスパイプライン、割り込みパイプラインなど、さまざまな種類があります。さらに、すべてのデバイスには制御パイプがあります。これは、双方向で使用できる唯一のパイプラインです。
AppleはXcode付きのUSBProberという名前のツールを出荷しています。それを使ってUSBデバイスを見てください。たとえば、同じくUSB経由で接続されている私のApple Cinema Displayは、次のように報告します。
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
このデバイスには1つのインターフェイス、インターフェイス#0があり、このインターフェイス(0x81)には1つのエンドポイントがあり、割り込みパイプラインを介して接続され、16ミリ秒ごとに最大8バイトのサイズのパケットを転送できます。そのパイプラインと通信する場合は、デバイスのUSBドライバーインターフェイスを取得する必要があります。このインターフェイスは、同期または非同期で問題のパイプラインと通信するための関数を提供します。これはすべてネットワークコードと非常によく似ています。
そもそもこのパイプラインがモニターで何に適しているかを自問すると、モニターがボタンの押下をシステムに伝達する方法です。AppleのCinemaDisplayには、明るさを表す「+」と「-」の3つのボタンと、電源ボタンがあります。電源ボタンの機能は、システム設定で構成できます。たとえば、必要に応じてMac全体をスリープ状態にすることができます。これらのボタンの1つを押すと、割り込みイベントが作成され、このUSBパイプを介してシステムに送信されます(実際には、システムは16ミリ秒ごとにそのようなイベントをポーリングする必要がありますが、システムはそれを行います-コードはイベントはモニターによってプッシュされました)。
IOUSBDeviceInterface197を見てください。これは、IOUSBDeviceInterface187を継承します。IOUSBDeviceInterface187はIOUSBDeviceInterface182を継承し、IOUSBDeviceInterface182は再びIOUSBDeviceInterfaceを継承します。つまり、インターフェイスの197バージョンを取得すると、継承元のインターフェイスのすべてのメソッドがこのインターフェイスでも使用できるようになります(これらはページに再度表示されません)。Appleは、古いコードとの互換性を維持するために、名前に含まれるバージョンのインターフェイスを使用する必要があります。Appleは時間の経過とともにUSBインターフェイスを拡張し(たとえば、新しいOS Xリリースで)、古いコードが引き続き実行されるようにするために、常に新しいインターフェイスを追加しました。そうしないと、既存のコードが破損します。
ここに、これらすべてのインターフェースのリストが表示されます。はい、ドキュメントはひどいです。tryおよび/またはサンプルコードで学習する必要があります。DeviceInterfacesとInterfaceInterfacesがあることに注意してください。それは同じことではありません。DeviceInterfaceはデバイス自体へのドライバーインターフェイスであり、すべてのデバイスは複数の「USBインターフェイス」(これはUSB標準の用語です)を持つことができ、そのような「usbインターフェイス」へのインターフェイスは「InterfaceInterface」と呼ばれます。ただし、上記のモニターのような単純なデバイスには、単一のインターフェースしかありません。
これは非常に複雑だと思いますか?さて、他のプラットフォームのほとんどの開発者は、これらすべてがどのように機能するかを理解したら、USBパイプへの生のアクセスが必要な場合はMacOSがすべてのプラットフォームの中で最も簡単だと言います。ただし、さらに悪化します。すべてのインターフェイスは複数の構成を持つことができ、パイプラインを変更する可能性のある構成をインターフェイスに設定できます(たとえば、ある構成ではパイプはバルクパイプであり、別の構成ではまったく同じパイプがアイソクロナスになります)パイプ)。これはすべて、USB Proberアプリケーションで確認できます(代替構成が表示されます)。また、USBデバイスは、速度ごとに完全に異なるインターフェイス、パイプライン、構成のセットを持つことができることに注意してください(たとえば、1つはUSB 1.2、別名低速+フルスピード、もう1つはUSB 2、別名高速)。
Appleは、このページでコードを書き始める前に知っておくべきUSBの基本のほとんどを説明しようとしています。また、「USBデバイスインターフェイスの操作」をクリックすると、Appleには、インターフェイスインターフェイスの取得に使用できるDeviceInterfaceの取得方法に関するサンプルコードがたくさんあります。
私はあなたにいくつかのポインタと読むためのいくつかの興味深いリンクを手に入れることができればと思います。それはあなたの質問に対する答えではありませんが、良いスタートです。もちろん、カーネルドライバー(カーネル拡張)を記述して、デバイスのサポートをシステムに追加することもできます。これにより、ボタンを押すと、IOKitをまったく使用せずに任意のソフトウェアで処理できるイベントが生成されます...しかし、どういうわけかあなたがそこに行きたいのではないかと疑う。