最近,我做了一个HID项目,发现其他蓝牙设备可以根据连接的主机是IOS还是Android发送不同的报告描述符。
最近,我做了一个HID项目,发现其他蓝牙设备可以根据连接的主机是IOS还是Android发送不同的报告描述符。
Hello,
I don't know if there are any time constraints on HID Report characteristic read, but you could delay the response after you're done checking Manufacturer Name String characteristic.
Do something like that:
1. When you receive connection indication, initiate service discovery from your HID side. You're only interested in Device Information service (0x180A), so discover by service UUID to make it faster.
2. If you'd get Report char read request, wait a bit until you know the type of the connected device.
3. When Device Information service is found, discover Manufacturer Name String characteristic inside (0x2A29).
4. Read this characteristic. All Apple devices will return "Apple Inc.".
Only when 1, 3 or 4 fail you may assume it's not an iDevice and you may return the Report char value.
Android devices don't have Device Information service natively, but any app could create such service in its GATT service configuration. It may also decide to return "Apple Inc.", but there's nothing you can do about it. That would have to be intentional.
Seems like you'll have to modify the default behavior to be able to postpone Report read request. I don't know if that's possible from API or spec perspective. Anyway, that's an idea.
ok,I'll try this method
This product is designed to control the phone's self timer, Tiktok and sliding up and down. It can only run smoothly on a specific operating system version, because it needs to be compatible with two operating systems on one product
Android 报告描述符 0x05, 0x0D, // Usage Page (Digitizer) 0x09, 0x04, // Usage (Touch Screen) 0xA1, 0x01, // Collection (Application) 0x85, 0x01, // Report ID (1) 0x09, 0x22, // Usage (Finger) 0xA1, 0x02, // Collection (Logical) 0x09, 0x42, // Usage (Tip Switch) 0x09, 0x32, // Usage (In Range) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x75, 0x01, // Report Size (1) 0x95, 0x02, // Report Count (2) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x75, 0x01, // Report Size (1) 0x95, 0x06, // Report Count (6) 0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x30, // Usage (X) 0x09, 0x31, // Usage (Y) 0x15, 0x00, // Logical Minimum (0) 0x26, 0xE8, 0x03, // Logical Maximum (1000) 0x35, 0x00, // Physical Minimum (0) 0x45, 0x00, // Physical Maximum (0) 0x55, 0x00, // Unit Exponent (0) 0x65, 0x00, // Unit (None) 0x75, 0x10, // Report Size (16) 0x95, 0x02, // Report Count (2) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0xC0, // End Collection 0xC0, // End Collection 0x05, 0x0C, // Usage Page (Consumer) 0x09, 0x01, // Usage (Consumer Control) 0xA1, 0x01, // Collection (Application) 0x85, 0x02, // Report ID (2) 0x75, 0x10, // Report Size (16) 0x95, 0x01, // Report Count (1) 0x15, 0x01, // Logical Minimum (1) 0x26, 0x8C, 0x02, // Logical Maximum (652) 0x19, 0x01, // Usage Minimum (Consumer Control) 0x2A, 0x8C, 0x02, // Usage Maximum (AC Send) 0x81, 0x60, // Input (Data,Array,Abs,No Wrap,Linear,No Preferred State,Null State) 0xC0, // End Collection 0x05, 0x0C, // Usage Page (Consumer) 0x09, 0x01, // Usage (Consumer Control) 0xA1, 0x01, // Collection (Application) 0x85, 0x03, // Report ID (3) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x75, 0x01, // Report Size (1) 0x95, 0x18, // Report Count (24) 0x0A, 0x40, 0x00, // Usage (Menu) 0x0A, 0x92, 0x01, // Usage (AL Calculator) 0x0A, 0x83, 0x01, // Usage (AL Consumer Control Configuration) 0x0A, 0x23, 0x02, // Usage (AC Home) 0x0A, 0x8A, 0x01, // Usage (AL Email Reader) 0x0A, 0x82, 0x01, // Usage (AL Programmable Button Configuration) 0x0A, 0x21, 0x02, // Usage (AC Search) 0x0A, 0x24, 0x02, // Usage (AC Back) 0x0A, 0x25, 0x02, // Usage (AC Forward) 0x0A, 0x26, 0x02, // Usage (AC Stop) 0x0A, 0x27, 0x02, // Usage (AC Refresh) 0x09, 0xB6, // Usage (Scan Previous Track) 0x09, 0xB5, // Usage (Scan Next Track) 0x09, 0xB7, // Usage (Stop) 0x09, 0xCD, // Usage (Play/Pause) 0x09, 0xE9, // Usage (Volume Increment) 0x09, 0xEA, // Usage (Volume Decrement) 0x09, 0xE2, // Usage (Mute) 0x09, 0xB8, // Usage (Eject) 0x09, 0x30, // Usage (Power) 0x09, 0xCF, // Usage (0xCF) 0x09, 0xB9, // Usage (Random Play) 0x0A, 0xB1, 0x01, // Usage (AL Screen Saver) 0x0A, 0x04, 0x02, // Usage (AC Exit) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0xC0, // End Collection 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x06, // Usage (Keyboard) 0xA1, 0x01, // Collection (Application) 0x85, 0x04, // Report ID (4) 0x05, 0x07, // Usage Page (Kbrd/Keypad) 0x19, 0xE0, // Usage Minimum (0xE0) 0x29, 0xE7, // Usage Maximum (0xE7) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x75, 0x01, // Report Size (1) 0x95, 0x08, // Report Count (8) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x95, 0x01, // Report Count (1) 0x75, 0x08, // Report Size (8) 0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x95, 0x05, // Report Count (5) 0x75, 0x01, // Report Size (1) 0x05, 0x08, // Usage Page (LEDs) 0x19, 0x01, // Usage Minimum (Num Lock) 0x29, 0x05, // Usage Maximum (Kana) 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0x95, 0x01, // Report Count (1) 0x75, 0x03, // Report Size (3) 0x91, 0x01, // Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0x95, 0x06, // Report Count (6) 0x75, 0x08, // Report Size (8) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x65, // Logical Maximum (101) 0x05, 0x07, // Usage Page (Kbrd/Keypad) 0x19, 0x00, // Usage Minimum (0x00) 0x29, 0x65, // Usage Maximum (0x65) 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) 0xC0, // End Collection 0x05, 0x0C, // Usage Page (Consumer) 0x09, 0x01, // Usage (Consumer Control) 0xA1, 0x01, // Collection (Application) 0x85, 0x05, // Report ID (5) 0x75, 0x10, // Report Size (16) 0x95, 0x01, // Report Count (1) 0x15, 0x01, // Logical Minimum (1) 0x26, 0x8C, 0x02, // Logical Maximum (652) 0x19, 0x01, // Usage Minimum (Consumer Control) 0x2A, 0x8C, 0x02, // Usage Maximum (AC Send) 0x81, 0x60, // Input (Data,Array,Abs,No Wrap,Linear,No Preferred State,Null State) 0xC0, // End Collection IOS 报告描述符 05 01 09 06 a1 01 85 04 05 07 19 e0 29 e7 15 00 25 01 75 01 95 08 81 02 95 01 75 08 81 01 95 05 75 01 05 08 19 01 29 05 91 02 95 01 75 03 91 01 95 06 75 08 15 00 25 65 05 07 19 00 29 65 81 00 c0 05 0c 09 01 a1 01 85 05 75 10 95 01 15 01 26 8c 02 19 01 2a 8c 02 81 60 c0 05 01 09 02 a1 01 85 01 09 01 a1 00 75 08 95 01 05 01 09 38 15 81 25 7f 81 06 05 0c 0a 38 02 95 01 81 06 c0 85 02 09 01 a1 00 95 03 75 01 05 09 19 01 29 03 15 00 25 01 81 02 95 01 75 01 81 03 75 0e 95 02 05 01 09 30 09 31 16 01 e0 26 ff 1f 81 06 c0 c0 05 0c 09 01 a1 01 85 03 15 00 25 01 75 01 95 18 0a 40 00 0a 92 01 0a 83 01 0a 23 02 0a 8a 01 0a 82 01 0a 21 02 0a 24 02 0a 25 02 0a 26 02 0a 27 02 09 b6 09 b5 09 b7 09 cd 09 e9 09 ea 09 e2 09 b8 09 30 09 cf 09 b9 0a b1 01 0a 04 02 81 02 c0 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x06, // Usage (Keyboard) 0xA1, 0x01, // Collection (Application) 0x85, 0x04, // Report ID (4) 0x05, 0x07, // Usage Page (Kbrd/Keypad) 0x19, 0xE0, // Usage Minimum (0xE0) 0x29, 0xE7, // Usage Maximum (0xE7) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x75, 0x01, // Report Size (1) 0x95, 0x08, // Report Count (8) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x95, 0x01, // Report Count (1) 0x75, 0x08, // Report Size (8) 0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x95, 0x05, // Report Count (5) 0x75, 0x01, // Report Size (1) 0x05, 0x08, // Usage Page (LEDs) 0x19, 0x01, // Usage Minimum (Num Lock) 0x29, 0x05, // Usage Maximum (Kana) 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0x95, 0x01, // Report Count (1) 0x75, 0x03, // Report Size (3) 0x91, 0x01, // Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0x95, 0x06, // Report Count (6) 0x75, 0x08, // Report Size (8) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x65, // Logical Maximum (101) 0x05, 0x07, // Usage Page (Kbrd/Keypad) 0x19, 0x00, // Usage Minimum (0x00) 0x29, 0x65, // Usage Maximum (0x65) 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) 0xC0, // End Collection 0x05, 0x0C, // Usage Page (Consumer) 0x09, 0x01, // Usage (Consumer Control) 0xA1, 0x01, // Collection (Application) 0x85, 0x05, // Report ID (5) 0x75, 0x10, // Report Size (16) 0x95, 0x01, // Report Count (1) 0x15, 0x01, // Logical Minimum (1) 0x26, 0x8C, 0x02, // Logical Maximum (652) 0x19, 0x01, // Usage Minimum (Consumer Control) 0x2A, 0x8C, 0x02, // Usage Maximum (AC Send) 0x81, 0x60, // Input (Data,Array,Abs,No Wrap,Linear,No Preferred State,Null State) 0xC0, // End Collection 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x02, // Usage (Mouse) 0xA1, 0x01, // Collection (Application) 0x85, 0x01, // Report ID (1) 0x09, 0x01, // Usage (Pointer) 0xA1, 0x00, // Collection (Physical) 0x75, 0x08, // Report Size (8) 0x95, 0x01, // Report Count (1) 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x38, // Usage (Wheel) 0x15, 0x81, // Logical Minimum (-127) 0x25, 0x7F, // Logical Maximum (127) 0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) 0x05, 0x0C, // Usage Page (Consumer) 0x0A, 0x38, 0x02, // Usage (AC Pan) 0x95, 0x01, // Report Count (1) 0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) 0xC0, // End Collection 0x85, 0x02, // Report ID (2) 0x09, 0x01, // Usage (Consumer Control) 0xA1, 0x00, // Collection (Physical) 0x95, 0x03, // Report Count (3) 0x75, 0x01, // Report Size (1) 0x05, 0x09, // Usage Page (Button) 0x19, 0x01, // Usage Minimum (0x01) 0x29, 0x03, // Usage Maximum (0x03) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x95, 0x01, // Report Count (1) 0x75, 0x01, // Report Size (1) 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x75, 0x0E, // Report Size (14) 0x95, 0x02, // Report Count (2) 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x30, // Usage (X) 0x09, 0x31, // Usage (Y) 0x16, 0x01, 0xE0, // Logical Minimum (-8191) 0x26, 0xFF, 0x1F, // Logical Maximum (8191) 0x81, 0x06, // Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position) 0xC0, // End Collection 0xC0, // End Collection 0x05, 0x0C, // Usage Page (Consumer) 0x09, 0x01, // Usage (Consumer Control) 0xA1, 0x01, // Collection (Application) 0x85, 0x03, // Report ID (3) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x75, 0x01, // Report Size (1) 0x95, 0x18, // Report Count (24) 0x0A, 0x40, 0x00, // Usage (Menu) 0x0A, 0x92, 0x01, // Usage (AL Calculator) 0x0A, 0x83, 0x01, // Usage (AL Consumer Control Configuration) 0x0A, 0x23, 0x02, // Usage (AC Home) 0x0A, 0x8A, 0x01, // Usage (AL Email Reader) 0x0A, 0x82, 0x01, // Usage (AL Programmable Button Configuration) 0x0A, 0x21, 0x02, // Usage (AC Search) 0x0A, 0x24, 0x02, // Usage (AC Back) 0x0A, 0x25, 0x02, // Usage (AC Forward) 0x0A, 0x26, 0x02, // Usage (AC Stop) 0x0A, 0x27, 0x02, // Usage (AC Refresh) 0x09, 0xB6, // Usage (Scan Previous Track) 0x09, 0xB5, // Usage (Scan Next Track) 0x09, 0xB7, // Usage (Stop) 0x09, 0xCD, // Usage (Play/Pause) 0x09, 0xE9, // Usage (Volume Increment) 0x09, 0xEA, // Usage (Volume Decrement) 0x09, 0xE2, // Usage (Mute) 0x09, 0xB8, // Usage (Eject) 0x09, 0x30, // Usage (Power) 0x09, 0xCF, // Usage (0xCF) 0x09, 0xB9, // Usage (Random Play) 0x0A, 0xB1, 0x01, // Usage (AL Screen Saver) 0x0A, 0x04, 0x02, // Usage (AC Exit) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0xC0, // End Collection 10 00 fe 7f 01 00 c8 00 01 00 c8 00 00 00 00 00 10 00 fe 7f 10 00 fe 7f 10 00 fe 7f 20 03 70 fe 20 03 70 fe 01 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 10 00 fe 7f 10 00 fe 7f 10 00 fe 7f e0 01 70 fe e0 01 70 fe 01 00 c8 00 01 00 c8 00 01 00 c8 00 00 00 00 00 10 00 fe 7f 10 00 fe 7f 10 00 fe 7f e0 01 70 fe e0 01 70 fe 01 00 c8 00 01 00 c8 00 01 00 c8 00 00 00 00 00 10 00 fe 7f 10 00 fe 7f 10 00 fe 7f 10 00 fe 7f e0 01 70 fe e0 01 70 fe 01 00 c8 00 01 00 c8 00 10 00 fe 7f 10 00 fe 7f 10 00 fe 7f e0 01 70 fe e0 01 70 fe 10 00 fe 7f 10 00 fe 7f 10 00 fe 7f 10 00 fe 7f e0 01 70 fe e0 01 70 fe 01 00 c8 00 01 00 c8 00 01 00 c8 00 00 00 00 00 10 00 fe 7f 10 00 fe 7f 10 00 fe 7f 10 00 fe 7f e0 01 c0 fe 01 00 38 ff 01 00 38 ff 01 00 38 ff 00 00 00 00 10 00 fe 7f 10 00 fe 7f 10 00 fe 7f 10 00 fe 7f e0 01 c0 fe e0 01 c0 fe 01 00 38 ff 00 00 00 00 10 00 fe 7f 10 00 fe 7f 10 00 fe 7f 10 00 fe 7f e0 01 c0 fe e0 01 c0 fe 01 00 38 ff 01 00 38 ff 01 00 38 ff 00 00 00 00 10 00 fe 7f
At present, I just don't know how it distinguishes between IOS and Android. Maybe we can see his solution in the packet capture information, but I still can't know his method