Changeset 90697 in vbox
- Timestamp:
- Aug 16, 2021 1:47:40 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Input/UsbKbd.cpp
r89941 r90697 39 39 * are processed as quickly as possible. 40 40 * 41 * A second interface with its own interrupt endpoint is used to deliver 42 * additional key events for media and system control keys. This adds 43 * considerable complexity to the emulated device, but unfortunately the 44 * keyboard boot interface is fixed and fairly limited. 45 * 46 * The second interface is only exposed if the device is configured in 47 * "extended" mode, with a different USB product ID and different 48 * descriptors. The "basic" mode should be indistinguishable from the original 49 * implementation. 50 * 51 * There are various options available for reporting media keys. We chose 52 * a very basic approach which reports system control keys as a bit-field 53 * (since there are only 3 keys defined) and consumer control keys as just 54 * a single 16-bit value. 55 * 56 * As a consequence, only one consumer control key can be reported as 57 * pressed at any one time. While this may seem limiting, the usefulness of 58 * being able to report e.g. volume-up at the same time as volume-down or 59 * mute is highly questionable. 60 * 61 * System control and consumer control keys are reported in a single 62 * 4-byte report in order to avoid sending multiple separate report types. 63 * 64 * There is a slight complication in that both interfaces are configured 65 * together, but a guest does not necessarily "listen" on both (e.g. EFI). 66 * Since all events come through a single queue, we can't just push back 67 * events for the secondary interface because the entire keyboard would be 68 * blocked. After the device is reset/configured, we drop any events destined 69 * for the secondary interface until a URB is actually queued on the second 70 * interrupt endpoint. Once that happens, we assume the guest will be 71 * receiving data on the second endpoint until the next reset/reconfig. 41 72 * 42 73 * References: … … 70 101 #define USBHID_STR_ID_MANUFACTURER 1 71 102 #define USBHID_STR_ID_PRODUCT 2 103 #define USBHID_STR_ID_IF_KBD 3 104 #define USBHID_STR_ID_IF_EXT 4 72 105 /** @} */ 73 106 … … 81 114 * @{ */ 82 115 #define VBOX_USB_VENDOR 0x80EE 83 #define USBHID_PID_KEYBOARD 0x0010 116 #define USBHID_PID_BAS_KEYBOARD 0x0010 117 #define USBHID_PID_EXT_KEYBOARD 0x0011 84 118 /** @} */ 85 119 … … 111 145 112 146 /** 147 * The device mode. 148 */ 149 typedef enum USBKBDMODE 150 { 151 /** Basic keyboard only, backward compatible. */ 152 USBKBDMODE_BASIC = 0, 153 /** Extended 2nd interface for consumer control and power. */ 154 USBKBDMODE_EXTENDED, 155 } USBKBDMODE; 156 157 158 /** 113 159 * The USB HID request state. 114 160 */ … … 129 175 130 176 /** 131 * Endpoint status data.132 */133 typedef struct USBHIDEP134 {135 bool fHalted;136 } USBHIDEP;137 /** Pointer to the endpoint status. */138 typedef USBHIDEP *PUSBHIDEP;139 140 141 /**142 177 * A URB queue. 143 178 */ … … 156 191 157 192 /** 193 * Endpoint state. 194 */ 195 typedef struct USBHIDEP 196 { 197 /** Endpoint halt flag.*/ 198 bool fHalted; 199 } USBHIDEP; 200 /** Pointer to the endpoint status. */ 201 typedef USBHIDEP *PUSBHIDEP; 202 203 204 /** 205 * Interface state. 206 */ 207 typedef struct USBHIDIF 208 { 209 /** If interface has pending changes. */ 210 bool fHasPendingChanges; 211 /** The state of the HID (state machine).*/ 212 USBHIDREQSTATE enmState; 213 /** Pending to-host queue. 214 * The URBs waiting here are waiting for data to become available. 215 */ 216 USBHIDURBQUEUE ToHostQueue; 217 } USBHIDIF; 218 /** Pointer to the endpoint status. */ 219 typedef USBHIDIF *PUSBHIDIF; 220 221 222 /** 158 223 * The USB HID report structure for regular keys. 159 224 */ … … 164 229 uint8_t aKeys[6]; /**< Normal keys */ 165 230 } USBHIDK_REPORT, *PUSBHIDK_REPORT; 231 232 /* Must match 8-byte packet size. */ 233 AssertCompile(sizeof(USBHIDK_REPORT) == 8); 234 235 236 /** 237 * The USB HID report structure for extra keys. 238 */ 239 typedef struct USBHIDX_REPORT 240 { 241 uint16_t uKeyCC; /**< Consumer Control key code */ 242 uint8_t uSCKeys; /**< System Control keys bit map */ 243 uint8_t Reserved; /**< Unused */ 244 } USBHIDX_REPORT, *PUSBHIDX_REPORT; 245 246 /* Must match 4-byte packet size. */ 247 AssertCompile(sizeof(USBHIDX_REPORT) == 4); 248 166 249 167 250 /** … … 181 264 * (0 - only report state change, !=0 - report in bIdle * 4ms intervals.) */ 182 265 uint8_t bIdle; 183 /** Endpoint 0 is the default control pipe, 1 is the dev->host interrupt one. */ 184 USBHIDEP aEps[2]; 185 /** The state of the HID (state machine).*/ 186 USBHIDREQSTATE enmState; 187 188 /** Pending to-host queue. 189 * The URBs waiting here are waiting for data to become available. 190 */ 191 USBHIDURBQUEUE ToHostQueue; 266 /** Is this a relative, absolute or multi-touch pointing device? */ 267 USBKBDMODE enmMode; 268 /** Endpoint 0 is the default control pipe, 1 is the dev->host interrupt one 269 * for standard keys, 1 is the interrupt EP for extra keys. */ 270 USBHIDEP aEps[3]; 271 /** Interface 0 is the standard keyboard interface, 1 is the additional 272 * control/media key interface. */ 273 USBHIDIF aIfs[2]; 192 274 193 275 /** Done queue … … 199 281 /** Someone is waiting on the done queue. */ 200 282 bool fHaveDoneQueueWaiter; 201 /** If device has pending changes. */202 bool f HasPendingChanges;283 /** The guest expects data coming over second endpoint/pipe. */ 284 bool fExtPipeActive; 203 285 /** Currently depressed keys */ 204 286 uint8_t abDepressedKeys[VBOX_USB_USAGE_ARRAY_SIZE]; … … 234 316 { USBHID_STR_ID_MANUFACTURER, "VirtualBox" }, 235 317 { USBHID_STR_ID_PRODUCT, "USB Keyboard" }, 318 { USBHID_STR_ID_IF_KBD, "Keyboard" }, 319 { USBHID_STR_ID_IF_EXT, "System Control"}, 236 320 }; 237 321 … … 241 325 }; 242 326 243 static const VUSBDESCENDPOINTEX g_aUsbHidEndpointDescs [] =327 static const VUSBDESCENDPOINTEX g_aUsbHidEndpointDescsKbd[] = 244 328 { 245 329 { … … 258 342 }; 259 343 260 /** HID report descriptor. */ 261 static const uint8_t g_UsbHidReportDesc[] = 344 static const VUSBDESCENDPOINTEX g_aUsbHidEndpointDescsExt[] = 345 { 346 { 347 { 348 /* .bLength = */ sizeof(VUSBDESCENDPOINT), 349 /* .bDescriptorType = */ VUSB_DT_ENDPOINT, 350 /* .bEndpointAddress = */ 0x82 /* ep=2, in */, 351 /* .bmAttributes = */ 3 /* interrupt */, 352 /* .wMaxPacketSize = */ 4, 353 /* .bInterval = */ 10, 354 }, 355 /* .pvMore = */ NULL, 356 /* .pvClass = */ NULL, 357 /* .cbClass = */ 0 358 }, 359 }; 360 361 /** HID report descriptor for standard keys. */ 362 static const uint8_t g_UsbHidReportDescKbd[] = 262 363 { 263 364 /* Usage Page */ 0x05, 0x01, /* Generic Desktop */ … … 280 381 /* Usage Minimum */ 0x19, 0x01, /* Num Lock */ 281 382 /* Usage Maximum */ 0x29, 0x05, /* Kana */ 282 /* Output */ 0x91, 0x02, /* Data, Value, Absolute, Non-volatile, Bit field */383 /* Output */ 0x91, 0x02, /* Data, Value, Absolute, Non-volatile, Bit field */ 283 384 /* Report Count */ 0x95, 0x01, /* 1 */ 284 385 /* Report Size */ 0x75, 0x03, /* 3 */ … … 295 396 }; 296 397 297 /** Additional HID class interface descriptor. */ 298 static const uint8_t g_UsbHidIfHidDesc[] = 398 /** HID report descriptor for extra multimedia/system keys. */ 399 static const uint8_t g_UsbHidReportDescExt[] = 400 { 401 /* Usage Page */ 0x05, 0x0C, /* Consumer */ 402 /* Usage */ 0x09, 0x01, /* Consumer Control */ 403 /* Collection */ 0xA1, 0x01, /* Application */ 404 405 /* Usage Page */ 0x05, 0x0C, /* Consumer */ 406 /* Usage Minimum */ 0x19, 0x00, /* 0 */ 407 /* Usage Maximum */ 0x2A, 0x3C, 0x02, /* 572 */ 408 /* Logical Minimum */ 0x15, 0x00, /* 0 */ 409 /* Logical Maximum */ 0x26, 0x3C, 0x02, /* 572 */ 410 /* Report Count */ 0x95, 0x01, /* 1 */ 411 /* Report Size */ 0x75, 0x10, /* 16 */ 412 /* Input */ 0x81, 0x80, /* Data, Array, Absolute, Bytes */ 413 414 /* Usage Page */ 0x05, 0x01, /* Generic Desktop */ 415 /* Usage Minimum */ 0x19, 0x81, /* 129 */ 416 /* Usage Maximum */ 0x29, 0x83, /* 131 */ 417 /* Logical Minimum */ 0x15, 0x00, /* 0 */ 418 /* Logical Maximum */ 0x25, 0x01, /* 1 */ 419 /* Report Size */ 0x75, 0x01, /* 1 */ 420 /* Report Count */ 0x95, 0x03, /* 3 */ 421 /* Input */ 0x81, 0x02, /* Data, Value, Absolute, Bit field */ 422 /* Report Count */ 0x95, 0x05, /* 5 */ 423 /* Input */ 0x81, 0x01, /* Constant, Array, Absolute, Bit field */ 424 /* Report Count */ 0x95, 0x01, /* 1 */ 425 /* Report Size */ 0x75, 0x08, /* 8 (padding bits) */ 426 /* Input */ 0x81, 0x01, /* Constant, Array, Absolute, Bit field */ 427 428 /* End Collection */ 0xC0, 429 }; 430 431 /** Additional HID class interface descriptor for standard keys. */ 432 static const uint8_t g_UsbHidIfHidDescKbd[] = 299 433 { 300 434 /* .bLength = */ 0x09, … … 304 438 /* .bNumDescriptors = */ 1, 305 439 /* .bDescriptorType = */ 0x22, /* Report */ 306 /* .wDescriptorLength = */ sizeof(g_UsbHidReportDesc), 0x00 307 }; 308 309 static const VUSBDESCINTERFACEEX g_UsbHidInterfaceDesc = 440 /* .wDescriptorLength = */ sizeof(g_UsbHidReportDescKbd), 0x00 441 }; 442 443 /** Additional HID class interface descriptor for extra keys. */ 444 static const uint8_t g_UsbHidIfHidDescExt[] = 445 { 446 /* .bLength = */ 0x09, 447 /* .bDescriptorType = */ 0x21, /* HID */ 448 /* .bcdHID = */ 0x10, 0x01, /* 1.1 */ 449 /* .bCountryCode = */ 0, 450 /* .bNumDescriptors = */ 1, 451 /* .bDescriptorType = */ 0x22, /* Report */ 452 /* .wDescriptorLength = */ sizeof(g_UsbHidReportDescExt), 0x00 453 }; 454 455 /** Standard keyboard interface. */ 456 static const VUSBDESCINTERFACEEX g_UsbHidInterfaceDescKbd = 310 457 { 311 458 { … … 318 465 /* .bInterfaceSubClass = */ 1 /* Boot Interface */, 319 466 /* .bInterfaceProtocol = */ 1 /* Keyboard */, 320 /* .iInterface = */ 0467 /* .iInterface = */ USBHID_STR_ID_IF_KBD 321 468 }, 322 469 /* .pvMore = */ NULL, 323 /* .pvClass = */ &g_UsbHidIfHidDesc ,324 /* .cbClass = */ sizeof(g_UsbHidIfHidDesc ),325 &g_aUsbHidEndpointDescs [0],470 /* .pvClass = */ &g_UsbHidIfHidDescKbd, 471 /* .cbClass = */ sizeof(g_UsbHidIfHidDescKbd), 472 &g_aUsbHidEndpointDescsKbd[0], 326 473 /* .pIAD = */ NULL, 327 474 /* .cbIAD = */ 0 328 475 }; 329 476 330 static const VUSBINTERFACE g_aUsbHidInterfaces[] = 331 { 332 { &g_UsbHidInterfaceDesc, /* .cSettings = */ 1 }, 333 }; 334 335 static const VUSBDESCCONFIGEX g_UsbHidConfigDesc = 477 /** Extra keys (multimedia/system) interface. */ 478 static const VUSBDESCINTERFACEEX g_UsbHidInterfaceDescExt = 479 { 480 { 481 /* .bLength = */ sizeof(VUSBDESCINTERFACE), 482 /* .bDescriptorType = */ VUSB_DT_INTERFACE, 483 /* .bInterfaceNumber = */ 1, 484 /* .bAlternateSetting = */ 0, 485 /* .bNumEndpoints = */ 1, 486 /* .bInterfaceClass = */ 3 /* HID */, 487 /* .bInterfaceSubClass = */ 0 /* None */, 488 /* .bInterfaceProtocol = */ 0 /* Unspecified */, 489 /* .iInterface = */ USBHID_STR_ID_IF_EXT 490 }, 491 /* .pvMore = */ NULL, 492 /* .pvClass = */ &g_UsbHidIfHidDescExt, 493 /* .cbClass = */ sizeof(g_UsbHidIfHidDescExt), 494 &g_aUsbHidEndpointDescsExt[0], 495 /* .pIAD = */ NULL, 496 /* .cbIAD = */ 0 497 }; 498 499 static const VUSBINTERFACE g_aUsbHidBasInterfaces[] = 500 { 501 { &g_UsbHidInterfaceDescKbd, /* .cSettings = */ 1 }, 502 }; 503 504 static const VUSBINTERFACE g_aUsbHidExtInterfaces[] = 505 { 506 { &g_UsbHidInterfaceDescKbd, /* .cSettings = */ 1 }, 507 { &g_UsbHidInterfaceDescExt, /* .cSettings = */ 1 }, 508 }; 509 510 static const VUSBDESCCONFIGEX g_UsbHidBasConfigDesc = 336 511 { 337 512 { … … 339 514 /* .bDescriptorType = */ VUSB_DT_CONFIG, 340 515 /* .wTotalLength = */ 0 /* recalculated on read */, 341 /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbHid Interfaces),516 /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbHidBasInterfaces), 342 517 /* .bConfigurationValue =*/ 1, 343 518 /* .iConfiguration = */ 0, 344 /* .bmAttributes = */ RT_BIT(7), 519 /* .bmAttributes = */ RT_BIT(7), /* bus-powered */ 345 520 /* .MaxPower = */ 50 /* 100mA */ 346 521 }, … … 348 523 NULL, /* pvClass */ 349 524 0, /* cbClass */ 350 &g_aUsbHid Interfaces[0],525 &g_aUsbHidBasInterfaces[0], 351 526 NULL /* pvOriginal */ 352 527 }; 353 528 354 static const VUSBDESCDEVICE g_UsbHidDeviceDesc = 355 { 356 /* .bLength = */ sizeof(g_UsbHidDeviceDesc), 529 static const VUSBDESCCONFIGEX g_UsbHidExtConfigDesc = 530 { 531 { 532 /* .bLength = */ sizeof(VUSBDESCCONFIG), 533 /* .bDescriptorType = */ VUSB_DT_CONFIG, 534 /* .wTotalLength = */ 0 /* recalculated on read */, 535 /* .bNumInterfaces = */ RT_ELEMENTS(g_aUsbHidExtInterfaces), 536 /* .bConfigurationValue =*/ 1, 537 /* .iConfiguration = */ 0, 538 /* .bmAttributes = */ RT_BIT(7), /* bus-powered */ 539 /* .MaxPower = */ 50 /* 100mA */ 540 }, 541 NULL, /* pvMore */ 542 NULL, /* pvClass */ 543 0, /* cbClass */ 544 &g_aUsbHidExtInterfaces[0], 545 NULL /* pvOriginal */ 546 }; 547 548 static const VUSBDESCDEVICE g_UsbHidBasDeviceDesc = 549 { 550 /* .bLength = */ sizeof(g_UsbHidBasDeviceDesc), 357 551 /* .bDescriptorType = */ VUSB_DT_DEVICE, 358 552 /* .bcdUsb = */ 0x110, /* 1.1 */ … … 362 556 /* .bMaxPacketSize0 = */ 8, 363 557 /* .idVendor = */ VBOX_USB_VENDOR, 364 /* .idProduct = */ USBHID_PID_ KEYBOARD,558 /* .idProduct = */ USBHID_PID_BAS_KEYBOARD, 365 559 /* .bcdDevice = */ 0x0100, /* 1.0 */ 366 560 /* .iManufacturer = */ USBHID_STR_ID_MANUFACTURER, … … 370 564 }; 371 565 372 static const PDMUSBDESCCACHE g_UsbHidDescCache = 373 { 374 /* .pDevice = */ &g_UsbHidDeviceDesc, 375 /* .paConfigs = */ &g_UsbHidConfigDesc, 566 static const VUSBDESCDEVICE g_UsbHidExtDeviceDesc = 567 { 568 /* .bLength = */ sizeof(g_UsbHidExtDeviceDesc), 569 /* .bDescriptorType = */ VUSB_DT_DEVICE, 570 /* .bcdUsb = */ 0x110, /* 1.1 */ 571 /* .bDeviceClass = */ 0 /* Class specified in the interface desc. */, 572 /* .bDeviceSubClass = */ 0 /* Subclass specified in the interface desc. */, 573 /* .bDeviceProtocol = */ 0 /* Protocol specified in the interface desc. */, 574 /* .bMaxPacketSize0 = */ 8, 575 /* .idVendor = */ VBOX_USB_VENDOR, 576 /* .idProduct = */ USBHID_PID_EXT_KEYBOARD, 577 /* .bcdDevice = */ 0x0100, /* 1.0 */ 578 /* .iManufacturer = */ USBHID_STR_ID_MANUFACTURER, 579 /* .iProduct = */ USBHID_STR_ID_PRODUCT, 580 /* .iSerialNumber = */ 0, 581 /* .bNumConfigurations = */ 1 582 }; 583 584 static const PDMUSBDESCCACHE g_UsbHidBasDescCache = 585 { 586 /* .pDevice = */ &g_UsbHidBasDeviceDesc, 587 /* .paConfigs = */ &g_UsbHidBasConfigDesc, 376 588 /* .paLanguages = */ g_aUsbHidLanguages, 377 589 /* .cLanguages = */ RT_ELEMENTS(g_aUsbHidLanguages), … … 380 592 }; 381 593 594 static const PDMUSBDESCCACHE g_UsbHidExtDescCache = 595 { 596 /* .pDevice = */ &g_UsbHidExtDeviceDesc, 597 /* .paConfigs = */ &g_UsbHidExtConfigDesc, 598 /* .paLanguages = */ g_aUsbHidLanguages, 599 /* .cLanguages = */ RT_ELEMENTS(g_aUsbHidLanguages), 600 /* .fUseCachedDescriptors = */ true, 601 /* .fUseCachedStringsDescriptors = */ true 602 }; 382 603 383 604 /** … … 473 694 { 474 695 for (unsigned i = 0; i < RT_ELEMENTS(aHidDCKeys); ++i) 475 if (aHid CCKeys[i] == u16HidUsage)696 if (aHidDCKeys[i] == u16HidUsage) 476 697 { 477 698 iKeyIndex = USBHID_PAGE_DC_START + i; … … 484 705 AssertMsgFailed(("Unsupported u8HidPage! (%02X)\n", u8HidPage)); 485 706 } 486 487 /** @todo We can currently only report the standard HID keyboard page.*/488 if (u8HidPage != USB_HID_KB_PAGE)489 return -1;490 707 491 708 return iKeyIndex; … … 584 801 PVUSBURB pCur = pQueue->pHead; 585 802 if (pCur == pUrb) 803 { 586 804 pQueue->pHead = pUrb->Dev.pNext; 805 if (!pUrb->Dev.pNext) 806 pQueue->ppTail = &pQueue->pHead; 807 } 587 808 else 588 809 { … … 598 819 if (!pCur) 599 820 return false; 600 } 601 if (!pUrb->Dev.pNext) 602 pQueue->ppTail = &pQueue->pHead; 821 if (!pUrb->Dev.pNext) 822 pQueue->ppTail = &pCur->Dev.pNext; 823 } 824 pUrb->Dev.pNext = NULL; 603 825 return true; 604 826 } … … 652 874 else 653 875 { 654 pThis->aEps[0].fHalted = true;655 pThis->aEps[1].fHalted = true;876 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aEps); i++) 877 pThis->aEps[i].fHalted = true; 656 878 } 657 879 … … 662 884 663 885 /** 664 * Completes the URB with a OK state. 665 */ 666 static int usbHidCompleteOk(PUSBHID pThis, PVUSBURB pUrb, size_t cbData) 667 { 668 Log(("usbHidCompleteOk/#%u: pUrb=%p:%s cbData=%#zx\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, cbData)); 886 * Completes the URB after device successfully processed it. Optionally copies data 887 * into the URB. May still generate an error if the URB is not big enough. 888 */ 889 static int usbHidCompleteOk(PUSBHID pThis, PVUSBURB pUrb, const void *pSrc, size_t cbSrc) 890 { 891 Log(("usbHidCompleteOk/#%u: pUrb=%p:%s (cbData=%#x) cbSrc=%#zx\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, pUrb->cbData, cbSrc)); 669 892 670 893 pUrb->enmStatus = VUSBSTATUS_OK; 671 pUrb->cbData = (uint32_t)cbData; 894 size_t cbCopy = 0; 895 size_t cbSetup = 0; 896 897 if (pSrc) /* Can be NULL if not copying anything. */ 898 { 899 Assert(cbSrc); 900 uint8_t *pDst = pUrb->abData; 901 902 /* Returned data is written after the setup message in control URBs. */ 903 if (pUrb->enmType == VUSBXFERTYPE_MSG) 904 cbSetup = sizeof(VUSBSETUP); 905 906 Assert(pUrb->cbData >= cbSetup); /* Only triggers if URB is corrupted. */ 907 908 if (pUrb->cbData > cbSetup) 909 { 910 /* There is at least one byte of room in the URB. */ 911 cbCopy = RT_MIN(pUrb->cbData - cbSetup, cbSrc); 912 memcpy(pDst + cbSetup, pSrc, cbCopy); 913 pUrb->cbData = (uint32_t)(cbCopy + cbSetup); 914 Log(("Copied %zu bytes to pUrb->abData[%zu], source had %zu bytes\n", cbCopy, cbSetup, cbSrc)); 915 } 916 917 /* Need to check length differences. If cbSrc is less than what 918 * the URB has space for, it'll be resolved as a short packet. But 919 * if cbSrc is bigger, there is a real problem and the host needs 920 * to see an overrun/babble error. 921 */ 922 if (RT_UNLIKELY(cbSrc > cbCopy)) 923 pUrb->enmStatus = VUSBSTATUS_DATA_OVERRUN; 924 } 925 else 926 Assert(cbSrc == 0); /* Make up your mind, caller! */ 672 927 673 928 usbHidLinkDone(pThis, pUrb); … … 697 952 * Reset the device state. 698 953 */ 699 pThis->enmState = USBHIDREQSTATE_READY;700 954 pThis->bIdle = 0; 701 pThis->f HasPendingChanges= false;955 pThis->fExtPipeActive = false; 702 956 703 957 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aEps); i++) 704 958 pThis->aEps[i].fHalted = false; 959 960 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aIfs); i++) 961 { 962 pThis->aIfs[i].fHasPendingChanges = false; 963 pThis->aIfs[i].enmState = USBHIDREQSTATE_READY; 964 } 705 965 706 966 if (!pUrb && !fSetConfig) /* (only device reset) */ … … 711 971 */ 712 972 PVUSBURB pCurUrb; 713 while ((pCurUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue)) != NULL) 714 { 715 pCurUrb->enmStatus = VUSBSTATUS_CRC; 716 usbHidLinkDone(pThis, pCurUrb); 717 } 973 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aIfs); i++) 974 while ((pCurUrb = usbHidQueueRemoveHead(&pThis->aIfs[i].ToHostQueue)) != NULL) 975 { 976 pCurUrb->enmStatus = VUSBSTATUS_CRC; 977 usbHidLinkDone(pThis, pCurUrb); 978 } 718 979 719 980 if (pUrb) 720 return usbHidCompleteOk(pThis, pUrb, 0);981 return usbHidCompleteOk(pThis, pUrb, NULL, 0); 721 982 return VINF_SUCCESS; 722 983 } … … 744 1005 745 1006 /** 1007 * Returns true if the usage code corresponds to a System Control key. 1008 * The usage codes for these keys are the range 0x81 to 0x83. 1009 */ 1010 static bool usbHidUsageCodeIsSCKey(uint16_t u16Usage) 1011 { 1012 return u16Usage >= 0x81 && u16Usage <= 0x83; 1013 } 1014 1015 /** 1016 * Convert a USB HID usage code to a system control key mask. The system control 1017 * keys have usage codes from 0x81 to 0x83, and the lower nibble is the bit 1018 * position plus one. 1019 */ 1020 static uint8_t usbHidSCKeyToMask(uint16_t u16Usage) 1021 { 1022 Assert(usbHidUsageCodeIsSCKey(u16Usage)); 1023 return RT_BIT((u16Usage & 0xf) - 1); 1024 } 1025 1026 /** 746 1027 * Create a USB HID keyboard report reflecting the current state of the 747 * keyboard (up/down keys).748 */ 749 static void usbHidBuildReport (PUSBHIDK_REPORT pReport, uint8_t *pabDepressedKeys)1028 * standard keyboard (up/down keys). 1029 */ 1030 static void usbHidBuildReportKbd(PUSBHIDK_REPORT pReport, uint8_t *pabDepressedKeys) 750 1031 { 751 1032 unsigned iBuf = 0; … … 772 1053 uint32_t u32HidCode = usbInternalCodeToHid(iKey); 773 1054 uint8_t u8HidPage = RT_LOBYTE(RT_HIWORD(u32HidCode)); 774 uint 8_tu16HidUsage = RT_LOWORD(u32HidCode);1055 uint16_t u16HidUsage = RT_LOWORD(u32HidCode); 775 1056 776 1057 if (u8HidPage == USB_HID_KB_PAGE) … … 785 1066 786 1067 /** 1068 * Create a USB HID keyboard report reflecting the current state of the 1069 * consumer control keys. This is very easy as we have a bit mask that fully 1070 * reflects the state of all defined system control keys. 1071 */ 1072 static void usbHidBuildReportExt(PUSBHIDX_REPORT pReport, uint8_t *pabDepressedKeys) 1073 { 1074 RT_ZERO(*pReport); 1075 1076 for (unsigned iKey = 0; iKey < VBOX_USB_USAGE_ARRAY_SIZE; ++iKey) 1077 { 1078 if (pabDepressedKeys[iKey]) 1079 { 1080 /* Key index back to 32-bit HID code. */ 1081 uint32_t u32HidCode = usbInternalCodeToHid(iKey); 1082 uint8_t u8HidPage = RT_LOBYTE(RT_HIWORD(u32HidCode)); 1083 uint16_t u16HidUsage = RT_LOWORD(u32HidCode); 1084 1085 if (u8HidPage == USB_HID_CC_PAGE) 1086 pReport->uKeyCC = u16HidUsage; 1087 else if (u8HidPage == USB_HID_DC_PAGE) 1088 if (usbHidUsageCodeIsSCKey(u16HidUsage)) 1089 pReport->uSCKeys |= usbHidSCKeyToMask(u16HidUsage); 1090 } 1091 } 1092 } 1093 1094 /** 787 1095 * Handles a SET_REPORT request sent to the default control pipe. Note 788 1096 * that unrecognized requests are ignored without reporting an error. … … 815 1123 * Sends a state report to the guest if there is a URB available. 816 1124 */ 817 static void usbHidSendReport(PUSBHID pThis )818 { 819 PVUSBURB pUrb = usbHidQueueRemoveHead(&p This->ToHostQueue);1125 static void usbHidSendReport(PUSBHID pThis, PUSBHIDIF pIf) 1126 { 1127 PVUSBURB pUrb = usbHidQueueRemoveHead(&pIf->ToHostQueue); 820 1128 if (pUrb) 821 1129 { 822 PUSBHIDK_REPORT pReport = (PUSBHIDK_REPORT)&pUrb->abData[0]; 823 824 usbHidBuildReport(pReport, pThis->abDepressedKeys); 825 pThis->fHasPendingChanges = false; 826 usbHidCompleteOk(pThis, pUrb, sizeof(*pReport)); 1130 pIf->fHasPendingChanges = false; 1131 if (pIf == &pThis->aIfs[0]) 1132 { 1133 USBHIDK_REPORT ReportKbd; 1134 1135 usbHidBuildReportKbd(&ReportKbd, pThis->abDepressedKeys); 1136 usbHidCompleteOk(pThis, pUrb, &ReportKbd, sizeof(ReportKbd)); 1137 } 1138 else 1139 { 1140 Assert(pIf == &pThis->aIfs[1]); 1141 USBHIDX_REPORT ReportExt; 1142 1143 usbHidBuildReportExt(&ReportExt, pThis->abDepressedKeys); 1144 usbHidCompleteOk(pThis, pUrb, &ReportExt, sizeof(ReportExt)); 1145 } 827 1146 } 828 1147 else 829 1148 { 830 1149 Log2(("No available URB for USB kbd\n")); 831 p This->fHasPendingChanges = true;1150 pIf->fHasPendingChanges = true; 832 1151 } 833 1152 } … … 849 1168 static DECLCALLBACK(int) usbHidKeyboardPutEvent(PPDMIKEYBOARDPORT pInterface, uint32_t idUsage) 850 1169 { 851 PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort); 1170 PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort); 1171 PUSBHIDIF pIf; 852 1172 bool fKeyDown; 853 1173 bool fHaveEvent = true; 854 1174 int rc = VINF_SUCCESS; 855 1175 int iKeyCode; 1176 uint8_t u8HidPage = RT_LOBYTE(RT_HIWORD(idUsage)); 856 1177 857 1178 /* Let's see what we got... */ 858 1179 fKeyDown = !(idUsage & PDMIKBDPORT_KEY_UP); 1180 1181 /* Always respond to USB_HID_KB_PAGE, but quietly drop USB_HID_CC_PAGE/USB_HID_DC_PAGE 1182 * events unless the device is in the extended mode. And drop anything else, too. 1183 */ 1184 if (u8HidPage == USB_HID_KB_PAGE) 1185 pIf = &pThis->aIfs[0]; 1186 else 1187 { 1188 if ( pThis->fExtPipeActive 1189 && ((u8HidPage == USB_HID_CC_PAGE) || (u8HidPage == USB_HID_DC_PAGE))) 1190 pIf = &pThis->aIfs[1]; 1191 else 1192 return VINF_SUCCESS; /* Must consume data to avoid blockage. */ 1193 } 859 1194 860 1195 iKeyCode = usbHidToInternalCode(idUsage); … … 873 1208 874 1209 /* If there is already a pending event, we won't accept a new one yet. */ 875 if (p This->fHasPendingChanges && fHaveEvent)1210 if (pIf->fHasPendingChanges && fHaveEvent) 876 1211 { 877 1212 rc = VERR_TRY_AGAIN; … … 889 1224 else 890 1225 { 891 /* Clear all currently depressed and unreportedkeys. */1226 /* Clear all currently depressed keys. */ 892 1227 RT_ZERO(pThis->abDepressedKeys); 893 1228 } … … 898 1233 * we will simply not accept any further events. 899 1234 */ 900 usbHidSendReport(pThis );1235 usbHidSendReport(pThis, pIf); 901 1236 } 902 1237 … … 960 1295 961 1296 /* 962 * Remove the URB from theto-host queue and move it onto the done queue.1297 * Remove the URB from its to-host queue and move it onto the done queue. 963 1298 */ 964 if (usbHidQueueRemove(&pThis->ToHostQueue, pUrb)) 965 usbHidLinkDone(pThis, pUrb); 1299 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aIfs); i++) 1300 if (usbHidQueueRemove(&pThis->aIfs[i].ToHostQueue, pUrb)) 1301 usbHidLinkDone(pThis, pUrb); 966 1302 967 1303 RTCritSectLeave(&pThis->CritSect); … … 975 1311 * after arbitrarily long time. 976 1312 */ 977 static int usbHidHandleIntrDevToHost(PUSBHID pThis, PUSBHIDEP pEp, P VUSBURB pUrb)1313 static int usbHidHandleIntrDevToHost(PUSBHID pThis, PUSBHIDEP pEp, PUSBHIDIF pIf, PVUSBURB pUrb) 978 1314 { 979 1315 /* … … 984 1320 985 1321 /* 986 * Deal with the URB according to the state.1322 * Deal with the URB according to the endpoint/interface state. 987 1323 */ 988 switch (p This->enmState)1324 switch (pIf->enmState) 989 1325 { 990 1326 /* … … 995 1331 AssertFailed(); 996 1332 Log(("usbHidHandleIntrDevToHost: Entering STATUS\n")); 997 return usbHidCompleteOk(pThis, pUrb, 0);1333 return usbHidCompleteOk(pThis, pUrb, NULL, 0); 998 1334 } 999 1335 … … 1005 1341 AssertFailed(); 1006 1342 Log(("usbHidHandleIntrDevToHost: Entering READY\n")); 1007 p This->enmState = USBHIDREQSTATE_READY;1008 return usbHidCompleteOk(pThis, pUrb, 0);1343 pIf->enmState = USBHIDREQSTATE_READY; 1344 return usbHidCompleteOk(pThis, pUrb, NULL, 0); 1009 1345 } 1010 1346 1011 1347 case USBHIDREQSTATE_READY: 1012 usbHidQueueAddTail(&p This->ToHostQueue, pUrb);1348 usbHidQueueAddTail(&pIf->ToHostQueue, pUrb); 1013 1349 /* If device was not set idle, send the current report right away. */ 1014 if (pThis->bIdle != 0 || p This->fHasPendingChanges)1350 if (pThis->bIdle != 0 || pIf->fHasPendingChanges) 1015 1351 { 1016 usbHidSendReport(pThis );1352 usbHidSendReport(pThis, pIf); 1017 1353 LogFlow(("usbHidHandleIntrDevToHost: Sent report via %p:%s\n", pUrb, pUrb->pszDesc)); 1018 Assert(!p This->fHasPendingChanges);/* Since we just got a URB... */1354 Assert(!pIf->fHasPendingChanges); /* Since we just got a URB... */ 1019 1355 /* There may be more input queued up. Ask for it now. */ 1020 1356 pThis->Lun0.pDrv->pfnFlushQueue(pThis->Lun0.pDrv); … … 1026 1362 */ 1027 1363 default: 1028 Log(("usbHidHandleIntrDevToHost: enmState=%d cbData=%#x\n", p This->enmState, pUrb->cbData));1364 Log(("usbHidHandleIntrDevToHost: enmState=%d cbData=%#x\n", pIf->enmState, pUrb->cbData)); 1029 1365 return usbHidCompleteStall(pThis, NULL, pUrb, "Really bad state (D2H)!"); 1030 1366 } … … 1070 1406 case DT_IF_HID_DESCRIPTOR: 1071 1407 { 1072 uint32_t cbCopy; 1073 1074 /* Returned data is written after the setup message. */ 1075 cbCopy = pUrb->cbData - sizeof(*pSetup); 1076 cbCopy = RT_MIN(cbCopy, sizeof(g_UsbHidIfHidDesc)); 1077 Log(("usbHidKbd: GET_DESCRIPTOR DT_IF_HID_DESCRIPTOR wValue=%#x wIndex=%#x cbCopy=%#x\n", pSetup->wValue, pSetup->wIndex, cbCopy)); 1078 memcpy(&pUrb->abData[sizeof(*pSetup)], &g_UsbHidIfHidDesc, cbCopy); 1079 return usbHidCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup)); 1408 uint32_t cbSrc; 1409 const void *pSrc; 1410 1411 if (pSetup->wIndex == 0) 1412 { 1413 cbSrc = RT_MIN(pSetup->wLength, sizeof(g_UsbHidIfHidDescKbd)); 1414 pSrc = &g_UsbHidIfHidDescKbd; 1415 } 1416 else 1417 { 1418 cbSrc = RT_MIN(pSetup->wLength, sizeof(g_UsbHidIfHidDescExt)); 1419 pSrc = &g_UsbHidIfHidDescExt; 1420 } 1421 Log(("usbHidKbd: GET_DESCRIPTOR DT_IF_HID_DESCRIPTOR wValue=%#x wIndex=%#x cbSrc=%#x\n", pSetup->wValue, pSetup->wIndex, cbSrc)); 1422 return usbHidCompleteOk(pThis, pUrb, pSrc, cbSrc); 1080 1423 } 1081 1424 1082 1425 case DT_IF_HID_REPORT: 1083 1426 { 1084 uint32_t cbCopy; 1427 uint32_t cbSrc; 1428 const void *pSrc; 1085 1429 1086 1430 /* Returned data is written after the setup message. */ 1087 cbCopy = pUrb->cbData - sizeof(*pSetup); 1088 cbCopy = RT_MIN(cbCopy, sizeof(g_UsbHidReportDesc)); 1089 Log(("usbHid: GET_DESCRIPTOR DT_IF_HID_REPORT wValue=%#x wIndex=%#x cbCopy=%#x\n", pSetup->wValue, pSetup->wIndex, cbCopy)); 1090 memcpy(&pUrb->abData[sizeof(*pSetup)], &g_UsbHidReportDesc, cbCopy); 1091 return usbHidCompleteOk(pThis, pUrb, cbCopy + sizeof(*pSetup)); 1431 if (pSetup->wIndex == 0) 1432 { 1433 cbSrc = RT_MIN(pSetup->wLength, sizeof(g_UsbHidReportDescKbd)); 1434 pSrc = &g_UsbHidReportDescKbd; 1435 } 1436 else 1437 { 1438 cbSrc = RT_MIN(pSetup->wLength, sizeof(g_UsbHidReportDescExt)); 1439 pSrc = &g_UsbHidReportDescExt; 1440 } 1441 1442 Log(("usbHid: GET_DESCRIPTOR DT_IF_HID_REPORT wValue=%#x wIndex=%#x cbSrc=%#x\n", pSetup->wValue, pSetup->wIndex, cbSrc)); 1443 return usbHidCompleteOk(pThis, pUrb, pSrc, cbSrc); 1092 1444 } 1093 1445 … … 1123 1475 Log(("usbHid: GET_STATUS (device)\n")); 1124 1476 wRet = 0; /* Not self-powered, no remote wakeup. */ 1125 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, sizeof(wRet)); 1126 return usbHidCompleteOk(pThis, pUrb, sizeof(wRet) + sizeof(*pSetup)); 1477 return usbHidCompleteOk(pThis, pUrb, &wRet, sizeof(wRet)); 1127 1478 } 1128 1479 … … 1131 1482 if (pSetup->wIndex == 0) 1132 1483 { 1133 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, sizeof(wRet)); 1134 return usbHidCompleteOk(pThis, pUrb, sizeof(wRet) + sizeof(*pSetup)); 1484 return usbHidCompleteOk(pThis, pUrb, &wRet, sizeof(wRet)); 1135 1485 } 1136 1486 Log(("usbHid: GET_STATUS (interface) invalid, wIndex=%#x\n", pSetup->wIndex)); … … 1143 1493 { 1144 1494 wRet = pThis->aEps[pSetup->wIndex].fHalted ? 1 : 0; 1145 memcpy(&pUrb->abData[sizeof(*pSetup)], &wRet, sizeof(wRet)); 1146 return usbHidCompleteOk(pThis, pUrb, sizeof(wRet) + sizeof(*pSetup)); 1495 return usbHidCompleteOk(pThis, pUrb, &wRet, sizeof(wRet)); 1147 1496 } 1148 1497 Log(("usbHid: GET_STATUS (endpoint) invalid, wIndex=%#x\n", pSetup->wIndex)); … … 1181 1530 /* Consider 24ms to mean zero for keyboards (see IOUSBHIDDriver) */ 1182 1531 if (pThis->bIdle == 6) pThis->bIdle = 0; 1183 return usbHidCompleteOk(pThis, pUrb, 0);1532 return usbHidCompleteOk(pThis, pUrb, NULL, 0); 1184 1533 } 1185 1534 break; … … 1194 1543 { 1195 1544 Log(("usbHid: GET_IDLE wValue=%#x wIndex=%#x, returning %#x\n", pSetup->wValue, pSetup->wIndex, pThis->bIdle)); 1196 pUrb->abData[sizeof(*pSetup)] = pThis->bIdle; 1197 return usbHidCompleteOk(pThis, pUrb, 1); 1545 return usbHidCompleteOk(pThis, pUrb, &pThis->bIdle, sizeof(pThis->bIdle)); 1198 1546 } 1199 1547 break; … … 1209 1557 Log(("usbHid: SET_REPORT wValue=%#x wIndex=%#x wLength=%#x\n", pSetup->wValue, pSetup->wIndex, pSetup->wLength)); 1210 1558 usbHidSetReport(pThis, pUrb); 1211 return usbHidCompleteOk(pThis, pUrb, 0);1559 return usbHidCompleteOk(pThis, pUrb, NULL, 0); 1212 1560 } 1213 1561 break; … … 1235 1583 * @interface_method_impl{PDMUSBREG,pfnUrbQueue} 1236 1584 */ 1237 static DECLCALLBACK(int) usbHidQueue (PPDMUSBINS pUsbIns, PVUSBURB pUrb)1585 static DECLCALLBACK(int) usbHidQueueUrb(PPDMUSBINS pUsbIns, PVUSBURB pUrb) 1238 1586 { 1239 1587 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID); … … 1242 1590 1243 1591 /* 1244 * Parse on a per end-point basis.1592 * Parse on a per-endpoint basis. 1245 1593 */ 1246 1594 int rc; … … 1251 1599 break; 1252 1600 1601 /* Standard keyboard interface. */ 1253 1602 case 0x81: 1254 1603 AssertFailed(); 1255 1604 RT_FALL_THRU(); 1256 1605 case 0x01: 1257 rc = usbHidHandleIntrDevToHost(pThis, &pThis->aEps[1], pUrb);1606 rc = usbHidHandleIntrDevToHost(pThis, &pThis->aEps[1], &pThis->aIfs[0], pUrb); 1258 1607 break; 1259 1608 1609 /* Extended multimedia/control keys interface. */ 1610 case 0x82: 1611 AssertFailed(); 1612 RT_FALL_THRU(); 1613 case 0x02: 1614 if (pThis->enmMode == USBKBDMODE_EXTENDED) 1615 { 1616 rc = usbHidHandleIntrDevToHost(pThis, &pThis->aEps[2], &pThis->aIfs[1], pUrb); 1617 pThis->fExtPipeActive = true; 1618 break; 1619 } 1620 RT_FALL_THRU(); 1260 1621 default: 1261 1622 AssertMsgFailed(("EndPt=%d\n", pUrb->EndPt)); … … 1335 1696 static DECLCALLBACK(PCPDMUSBDESCCACHE) usbHidUsbGetDescriptorCache(PPDMUSBINS pUsbIns) 1336 1697 { 1337 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID); RT_NOREF_PV(pThis); 1338 LogFlow(("usbHidUsbGetDescriptorCache/#%u:\n", pUsbIns->iInstance)); 1339 return &g_UsbHidDescCache; 1698 PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID); 1699 LogRelFlow(("usbHidUsbGetDescriptorCache/#%u:\n", pUsbIns->iInstance)); 1700 switch (pThis->enmMode) 1701 { 1702 case USBKBDMODE_BASIC: 1703 return &g_UsbHidBasDescCache; 1704 case USBKBDMODE_EXTENDED: 1705 return &g_UsbHidExtDescCache; 1706 default: 1707 return NULL; 1708 } 1340 1709 } 1341 1710 … … 1399 1768 pThis->pUsbIns = pUsbIns; 1400 1769 pThis->hEvtDoneQueue = NIL_RTSEMEVENT; 1401 usbHidQueueInit(&pThis->ToHostQueue);1402 1770 usbHidQueueInit(&pThis->DoneQueue); 1771 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aIfs); i++) 1772 usbHidQueueInit(&pThis->aIfs[i].ToHostQueue); 1403 1773 1404 1774 int rc = RTCritSectInit(&pThis->CritSect); … … 1411 1781 * Validate and read the configuration. 1412 1782 */ 1413 rc = CFGMR3ValidateConfig(pCfg, "/", " ", "", "UsbHid", iInstance);1783 rc = CFGMR3ValidateConfig(pCfg, "/", "Mode", "Config", "UsbHid", iInstance); 1414 1784 if (RT_FAILURE(rc)) 1415 1785 return rc; 1786 char szMode[64]; 1787 rc = CFGMR3QueryStringDef(pCfg, "Mode", szMode, sizeof(szMode), "extended"); 1788 if (RT_FAILURE(rc)) 1789 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, N_("HID failed to query settings")); 1790 if (!RTStrCmp(szMode, "basic")) 1791 pThis->enmMode = USBKBDMODE_BASIC; 1792 else if (!RTStrCmp(szMode, "extended")) 1793 pThis->enmMode = USBKBDMODE_EXTENDED; 1794 else 1795 return PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, 1796 N_("Invalid HID mode")); 1416 1797 1417 1798 pThis->Lun0.IBase.pfnQueryInterface = usbHidKeyboardQueryInterface; … … 1489 1870 NULL/*usbHidUrbNew*/, 1490 1871 /* pfnUrbQueue */ 1491 usbHidQueue ,1872 usbHidQueueUrb, 1492 1873 /* pfnUrbCancel */ 1493 1874 usbHidUrbCancel,
Note:
See TracChangeset
for help on using the changeset viewer.