USB-Wii Classic Controller (17 / 18 steg)
USB-Combo enhet
Jag vet hur man skriver de deskriptor och datastrukturer för en USB-kombination enhet (allt-i-ett tangentbord-mus-gamepad) men prestanda är ganska dåligt. Dock fungerar det slags.
Tricket är att använda "Rapport-ID" inuti samlingar av deskriptor. Varje samling representerar en annan enhet med ett unikt ID. Överst i varje rapport skickas den-ID. Så deskriptorn ser ut så här (verkligen länge):
PROGMEM char usbHidReportDescriptor [176] = {
kontrollera storlek matchar USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH i usbconfig.h
start av tangentbord rapport deskriptor
0x05, 0x01, / / USAGE_PAGE (generiska skrivbordet)
0x09, 0x06, / / användning (tangentbord)
0xa1, 0x01, / / samling (ansökan)
0X85, 0X01, / / REPORT_ID (1)
0x05, 0x07, / / USAGE_PAGE (tangentbord)
0x19, 0xe0, / / USAGE_MINIMUM (tangentbord LeftControl)
0x29, 0xe7, / / USAGE_MAXIMUM (tangentbord höger GUI)
0X15, 0X00, / / LOGICAL_MINIMUM (0)
0X25, 0X01, / / LOGICAL_MAXIMUM (1)
0X75, 0X01, / / REPORT_SIZE (1)
0X95, 0X08, / / REPORT_COUNT (8)
0x81, 0x02, / / ingång (Data, Var, Abs)
0X95, 0X01, / / REPORT_COUNT (1)
0X75, 0X08, / / REPORT_SIZE (8)
0x81, 0x03, / / ingång (Cnst, Var, Abs)
0X95, 0X05, / / REPORT_COUNT (5)
0X75, 0X01, / / REPORT_SIZE (1)
0x05, 0x08, / / USAGE_PAGE (LED)
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 (tangentbord)
0x19, 0x00, / / USAGE_MINIMUM (reserverat (inga omständigheter anges))
0x29, 0x65, / / USAGE_MAXIMUM (tangentbord)
0x81, 0x00, / / ingång (Data, Ary, Abs)
0XC0, / / END_COLLECTION
start av musen rapport deskriptor
0x05, 0x01, / / USAGE_PAGE (generiska skrivbordet)
0x09, 0x02, / / användning (mus)
0xa1, 0x01, / / samling (ansökan)
0x09, 0x01, / / användning (pekare)
0xa1, 0x00, / / samling (fysiska)
0X85, 0X02, / / REPORT_ID (2)
0x05, 0x09, / / USAGE_PAGE (knapp)
0x19, 0x01, / / USAGE_MINIMUM (knappen 1)
0x29, 0x03, / / USAGE_MAXIMUM (knappen 3)
0X15, 0X00, / / LOGICAL_MINIMUM (0)
0X25, 0X01, / / LOGICAL_MAXIMUM (1)
0X95, 0X03, / / REPORT_COUNT (3)
0X75, 0X01, / / REPORT_SIZE (1)
0x81, 0x02, / / ingång (Data, Var, Abs)
0X95, 0X01, / / REPORT_COUNT (1)
0X75, 0X05, / / REPORT_SIZE (5)
0x81, 0x03, / / ingång (Cnst, Var, Abs)
0x05, 0x01, / / USAGE_PAGE (generiska skrivbordet)
0X09, 0X30, / / ANVÄNDNING (X)
0X09, 0X31, / / ANVÄNDNING (Y)
0x09, 0x38, / / användning (hjul)
0X15, 0X81, / / LOGICAL_MINIMUM (-127)
0X25, 0X7F, / / LOGICAL_MAXIMUM (127)
0X75, 0X08, / / REPORT_SIZE (8)
0X95, 0X03, / / REPORT_COUNT (3)
0x81, 0x06, / / ingång (Data, Var, Rel)
0x05, 0x0c, / / USAGE_PAGE (konsumentenheter)
0x0A, 0x38, 0x02, / / användning (Undefined)
0X95, 0X01, / / REPORT_COUNT (1)
0x81, 0x06, / / ingång (Data, Var, Rel)
0XC0, / / END_COLLECTION
0XC0, / / END_COLLECTION
start av gamepad rapport deskriptor
0x05, 0x01, / / USAGE_PAGE (generiska skrivbordet)
0x09, 0x05, / / användning (spelkontroll)
0xa1, 0x01, / / samling (ansökan)
0xa1, 0x00, / / samling (fysiska)
0X85, 0X03, / / REPORT_ID (3)
0x05, 0x09, / / USAGE_PAGE (knapp)
0x19, 0x01, / / USAGE_MINIMUM (knappen 1)
0x29, 0x10, / / USAGE_MAXIMUM (knappen 16)
0X15, 0X00, / / LOGICAL_MINIMUM (0)
0X25, 0X01, / / LOGICAL_MAXIMUM (1)
0X95, 0X10, / / REPORT_COUNT (16)
0X75, 0X01, / / REPORT_SIZE (1)
0x81, 0x02, / / ingång (Data, Var, Abs)
0x05, 0x01, / / USAGE_PAGE (generiska skrivbordet)
0x09, 0x30, / / användning (X) / / vänster X
0x09, 0x31, / / användning (Y) / / vänster Y
0x09, 0x32, / / användning (Z) / / just X
0x09, 0x33, / / användning (Rx) / / höger Y
0X15, 0X81, / / LOGICAL_MINIMUM (-127)
0X25, 0X7F, / / LOGICAL_MAXIMUM (127)
0X75, 0X08, / / REPORT_SIZE (8)
0X95, 0X04, / / REPORT_COUNT (4)
0x81, 0x02, / / ingång (Data, Var, Abs)
0XC0, / / END_COLLECTION
0XC0 / / END_COLLECTION
};
Och strukturer inkluderar nu en rapport-ID:
statiska struct keyboard_report_t
{
uint8_t report_id;
uint8_t modifierare; Bitflaggor som skift, ctrl, alt och andra saker
uint8_t reserverade; värdelös för nu
uint8_t nyckel [6]. HID nyckelkoderna
} keyboard_report;
statiska struct mouse_report_t
{
uint8_t report_id;
uint8_t knappar; knappen mask (..... M L R)
int8_t x; mus x rörelse
int8_t y; y musrörelse
int8_t v_wheel; musen hjulet rörelse
int8_t h_wheel; musen hjulet rörelse
} mouse_report;
statiska struct gamepad_report_t
{
uint8_t report_id;
uint16_t knappar.
int8_t left_x;
int8_t left_y;
int8_t right_x;
int8_t right_y;
} gamepad_report;
Inne i "usbFunctionSetup" måste vi kontrollera vilka rapporter begärs genom att kontrollera "wValue" rapport-ID:
Markera rapport-ID efterfrågades
om (rq -> wValue.bytes[0] == 1)
{
usbMsgPtr = & keyboard_report;
återvända sizeof(keyboard_report);
}
annars om (rq -> wValue.bytes[0] == 2)
{
usbMsgPtr = & mouse_report;
återvända sizeof(mouse_report);
}
annars om (rq -> wValue.bytes[0] == 3)
{
usbMsgPtr = & gamepad_report;
återvända sizeof(gamepad_report);
}
Innan du skickar varje rapport, ligger rapport-ID i datastrukturen.
keyboard_report.report_id = 1; Ange rapport-ID så vet datorn vad data struct skickas
vänta tills det att skicka och sedan skicka den
samtidigt (1) {
usbPoll();
om (usbInterruptIsReady()) {
usbSetInterrupt ((unsigned char *)(&keyboard_report), sizeof(keyboard_report));
bryta;
}
}
Och till slut windows känner igen enheten som en kombination enhet.