USB-apparaat van de keuzelijst met invoervak
Ik weet hoe te schrijven van de descriptor en datastructuren voor een USB-apparaat voor combinatie (alles-in-één toetsenbord-muis-gamepad), maar de prestaties is soort van slecht. Nochtans, werkt het soort.
De truc is het gebruik van "Lijst-ID" binnen de collecties van de "descriptor". Elke collectie bevat een ander apparaat met een unieke ID. De ID wordt verzonden aan de bovenkant van elk rapport. Dus de "descriptor" (echt lang) ziet er als volgt:
PROGMEM char usbHidReportDescriptor[176] = { // make sure the size matches USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH in usbconfig.h // start of keyboard report descriptor 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x06, // USAGE (Keyboard) 0xa1, 0x01, // COLLECTION (Application) 0x85, 0x01, // REPORT_ID (1) 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) 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) 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x08, // REPORT_SIZE (8) 0x81, 0x03, // INPUT (Cnst,Var,Abs) 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) 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x03, // REPORT_SIZE (3) 0x91, 0x03, // OUTPUT (Cnst,Var,Abs) 0x95, 0x06, // REPORT_COUNT (6) 0x75, 0x08, // REPORT_SIZE (8) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x65, // LOGICAL_MAXIMUM (101) 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) 0x81, 0x00, // INPUT (Data,Ary,Abs) 0xc0, // END_COLLECTION // start of mouse report descriptor 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x02, // USAGE (Mouse) 0xa1, 0x01, // COLLECTION (Application) 0x09, 0x01, // USAGE (Pointer) 0xa1, 0x00, // COLLECTION (Physical) 0x85, 0x02, // REPORT_ID (2) 0x05, 0x09, // USAGE_PAGE (Button) 0x19, 0x01, // USAGE_MINIMUM (Button 1) 0x29, 0x03, // USAGE_MAXIMUM (Button 3) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x95, 0x03, // REPORT_COUNT (3) 0x75, 0x01, // REPORT_SIZE (1) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x05, // REPORT_SIZE (5) 0x81, 0x03, // INPUT (Cnst,Var,Abs) 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x30, // USAGE (X) 0x09, 0x31, // USAGE (Y) 0x09, 0x38, // USAGE (Wheel) 0x15, 0x81, // LOGICAL_MINIMUM (-127) 0x25, 0x7f, // LOGICAL_MAXIMUM (127) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x03, // REPORT_COUNT (3) 0x81, 0x06, // INPUT (Data,Var,Rel) 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) 0x0a, 0x38, 0x02, // USAGE (Undefined) 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x06, // INPUT (Data,Var,Rel) 0xc0, // END_COLLECTION 0xc0, // END_COLLECTION // start of gamepad report descriptor 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x05, // USAGE (Game Pad) 0xa1, 0x01, // COLLECTION (Application) 0xa1, 0x00, // COLLECTION (Physical) 0x85, 0x03, // REPORT_ID (3) 0x05, 0x09, // USAGE_PAGE (Button) 0x19, 0x01, // USAGE_MINIMUM (Button 1) 0x29, 0x10, // USAGE_MAXIMUM (Button 16) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x95, 0x10, // REPORT_COUNT (16) 0x75, 0x01, // REPORT_SIZE (1) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x30, // USAGE (X) // left X 0x09, 0x31, // USAGE (Y) // left Y 0x09, 0x32, // USAGE (Z) // right X 0x09, 0x33, // USAGE (Rx) // right Y 0x15, 0x81, // LOGICAL_MINIMUM (-127) 0x25, 0x7f, // LOGICAL_MAXIMUM (127) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x04, // REPORT_COUNT (4) 0x81, 0x02, // INPUT (Data,Var,Abs) 0xc0, // END_COLLECTION 0xc0 // END_COLLECTION };
En de structuren bevatten nu een lijst-ID:
static struct keyboard_report_t { uint8_t report_id; uint8_t modifier; // bit flags for shift, ctrl, and alt, and other stuff uint8_t reserved; // useless for now uint8_t key[6]; // HID keycodes } keyboard_report; static struct mouse_report_t { uint8_t report_id; uint8_t buttons; // button mask ( . . . . . M L R ) int8_t x; // mouse x movement int8_t y; // mouse y movement int8_t v_wheel; // mouse wheel movement int8_t h_wheel; // mouse wheel movement } mouse_report; static struct gamepad_report_t { uint8_t report_id; uint16_t buttons; int8_t left_x; int8_t left_y; int8_t right_x; int8_t right_y; } gamepad_report;
In "usbFunctionSetup" moeten we om te controleren welk rapport wordt aangevraagd door te controleren "wValue" voor de lijst-ID:
// check report ID requested if (rq->wValue.bytes[0] == 1) { usbMsgPtr = &keyboard_report; return sizeof(keyboard_report); } else if (rq->wValue.bytes[0] == 2) { usbMsgPtr = &mouse_report; return sizeof(mouse_report); } else if (rq->wValue.bytes[0] == 3) { usbMsgPtr = &gamepad_report; return sizeof(gamepad_report); }
Voordat u een rapport verzendt, is de lijst-ID ingesteld in de gegevensstructuur.
keyboard_report.report_id = 1; // set report ID so computer knows what data struct is sent // wait until ready to send, then send it while (1) { usbPoll(); if (usbInterruptIsReady()) { usbSetInterrupt((unsigned char *)(&keyboard_report), sizeof(keyboard_report)); break; } }
En in het einde, herkent windows dit apparaat als een combinatie-apparaat.