Changeset 51539 in vbox for trunk/src/VBox/Devices/Input
- Timestamp:
- Jun 4, 2014 9:34:18 PM (11 years ago)
- svn:sync-xref-src-repo-rev:
- 94184
- Location:
- trunk/src/VBox/Devices/Input
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Input/DrvKeyboardQueue.cpp
r50962 r51539 228 228 if (pItem) 229 229 { 230 /* 231 * Work around incredibly poorly desgined Korean keyboards which 232 * only send break events for Hangul/Hanja keys -- convert a lone 233 * key up into a key up/key down sequence. 234 */ 235 if (u32Usage == 0x80000090 || u32Usage == 0x80000091) 236 { 237 PDRVKBDQUEUEITEM pItem2 = (PDRVKBDQUEUEITEM)PDMQueueAlloc(pDrv->pQueue); 238 /* 239 * NB: If there's no room in the queue, we will drop the faked 240 * key down event. Probably less bad than the alternatives. 241 */ 242 if (pItem2) 243 { 244 /* Manufacture a key down event. */ 245 pItem2->u32UsageCode = u32Usage & ~0x80000000; 246 PDMQueueInsert(pDrv->pQueue, &pItem2->Core); 247 } 248 } 249 230 250 pItem->u32UsageCode = u32Usage; 231 251 PDMQueueInsert(pDrv->pQueue, &pItem->Core); 252 232 253 return VINF_SUCCESS; 233 254 } … … 270 291 AssertPtr(pDrv->pDownConnector->pfnSetActive); 271 292 pDrv->pDownConnector->pfnSetActive(pDrv->pDownConnector, fActive); 293 } 294 295 /** 296 * Flush the keyboard queue if there are pending events. 297 * 298 * @param pInterface Pointer to the keyboard connector interface structure. 299 */ 300 static DECLCALLBACK(void) drvKbdFlushQueue(PPDMIKEYBOARDCONNECTOR pInterface) 301 { 302 PDRVKBDQUEUE pDrv = PPDMIKEYBOARDCONNECTOR_2_DRVKBDQUEUE(pInterface); 303 304 AssertPtr(pDrv->pQueue); 305 PDMQueueFlushIfNecessary(pDrv->pQueue); 272 306 } 273 307 … … 387 421 pDrv->IConnector.pfnLedStatusChange = drvKbdPassThruLedsChange; 388 422 pDrv->IConnector.pfnSetActive = drvKbdPassThruSetActive; 423 pDrv->IConnector.pfnFlushQueue = drvKbdFlushQueue; 389 424 /* IKeyboardPort. */ 390 425 pDrv->IPort.pfnPutEventScan = drvKbdQueuePutEventScan; -
trunk/src/VBox/Devices/Input/PS2K.cpp
r50962 r51539 1166 1166 else 1167 1167 { 1168 /* Stupid Korean key hack: convert a lone break key into a press/release sequence. */1169 if (u32UsageCode == 0x80000090 || u32UsageCode == 0x80000091)1170 ps2kPutEventWorker(pThis, u32UsageCode & ~0x80000000);1171 1172 1168 ps2kPutEventWorker(pThis, u32UsageCode); 1173 1169 } -
trunk/src/VBox/Devices/Input/UsbKbd.cpp
r50962 r51539 169 169 /** If device has pending changes. */ 170 170 bool fHasPendingChanges; 171 /** Keypresses which have not yet been reported. A workaround for the172 * problem of keys being released before the keypress could be reported. */173 uint8_t abUnreportedKeys[VBOX_USB_USAGE_ARRAY_SIZE];174 171 /** Currently depressed keys */ 175 172 uint8_t abDepressedKeys[VBOX_USB_USAGE_ARRAY_SIZE]; … … 463 460 464 461 465 466 462 /** 467 463 * Completes the URB with a stalled state, halting the pipe. … … 548 544 } 549 545 550 #ifdef DEBUG551 # define HEX_DIGIT(x) (((x) < 0xa) ? ((x) + '0') : ((x) - 0xa + 'a'))552 static void usbHidComputePressed(PUSBHIDK_REPORT pReport, char* pszBuf, unsigned cbBuf)553 {554 unsigned offBuf = 0;555 unsigned i;556 for (i = 0; i < RT_ELEMENTS(pReport->aKeys); ++i)557 {558 uint8_t uCode = pReport->aKeys[i];559 if (uCode != 0)560 {561 if (offBuf + 4 >= cbBuf)562 break;563 pszBuf[offBuf++] = HEX_DIGIT(uCode >> 4);564 pszBuf[offBuf++] = HEX_DIGIT(uCode & 0xf);565 pszBuf[offBuf++] = ' ';566 }567 }568 pszBuf[offBuf++] = '\0';569 }570 # undef HEX_DIGIT571 #endif572 573 546 /** 574 547 * Returns true if the usage code corresponds to a keyboard modifier key … … 593 566 594 567 /** 595 * Create a USB HID keyboard report based on a vector of keys which have been 596 * pressed since the last report was created (so that we don't miss keys that 597 * are only pressed briefly) and a vector of currently depressed keys. 598 * The keys in the report aKeys array are in increasing order (important for 599 * the test case). 600 */ 601 static int usbHidFillReport(PUSBHIDK_REPORT pReport, 602 uint8_t *pabUnreportedKeys, 603 uint8_t *pabDepressedKeys) 604 { 605 int rc = false; 568 * Create a USB HID keyboard report reflecting the current state of the 569 * keyboard (up/down keys). 570 */ 571 static void usbHidBuildReport(PUSBHIDK_REPORT pReport, uint8_t *pabDepressedKeys) 572 { 606 573 unsigned iBuf = 0; 607 574 RT_ZERO(*pReport); 608 575 for (unsigned iKey = 0; iKey < VBOX_USB_USAGE_ARRAY_SIZE; ++iKey) 609 576 { 610 AssertReturn(iBuf <= RT_ELEMENTS(pReport->aKeys), 611 VERR_INTERNAL_ERROR); 612 if (pabUnreportedKeys[iKey] || pabDepressedKeys[iKey]) 577 Assert(iBuf <= RT_ELEMENTS(pReport->aKeys)); 578 if (pabDepressedKeys[iKey]) 613 579 { 614 580 if (usbHidUsageCodeIsModifier(iKey)) … … 627 593 pReport->aKeys[iBuf] = iKey; 628 594 ++iBuf; 629 /* More Korean keyboard hackery: Give the caller a hint that630 * a key release event needs reporting.631 */632 if (iKey == 0x90 || iKey == 0x91)633 rc = true;634 595 } 635 /* Avoid "hanging" keys: If a key is unreported but no longer636 * depressed, we'll need to report the key-up state, too.637 */638 if (pabUnreportedKeys[iKey] && !pabDepressedKeys[iKey])639 rc = true;640 641 pabUnreportedKeys[iKey] = 0;642 596 } 643 597 } 644 return rc; 645 } 646 647 #ifdef DEBUG 648 /** Test data for testing usbHidFillReport(). The format is: 649 * - Unreported keys (zero terminated array) 650 * - Depressed keys (zero terminated array) 651 * - Expected shift state in the report (single byte inside array) 652 * - Expected keys buffer contents (array of six bytes) 653 */ 654 static const uint8_t testUsbHidFillReportData[][4][10] = { 655 /* Just unreported, no modifiers */ 656 {{4, 9, 0}, {0}, {0}, {4, 9, 0, 0, 0, 0}}, 657 /* Just unreported, one modifier */ 658 {{4, 9, 0xe2, 0}, {0}, {4}, {4, 9, 0, 0, 0, 0}}, 659 /* Just unreported, two modifiers */ 660 {{4, 9, 0xe2, 0xe4, 0}, {0}, {20}, {4, 9, 0, 0, 0, 0}}, 661 /* Just depressed, no modifiers */ 662 {{0}, {7, 20, 0}, {0}, {7, 20, 0, 0, 0, 0}}, 663 /* Just depressed, one modifier */ 664 {{0}, {7, 20, 0xe3, 0}, {8}, {7, 20, 0, 0, 0, 0}}, 665 /* Just depressed, two modifiers */ 666 {{0}, {7, 20, 0xe3, 0xe6, 0}, {72}, {7, 20, 0, 0, 0, 0}}, 667 /* Unreported and depressed, no overlap, no modifiers */ 668 {{5, 10, 0}, {8, 21, 0}, {0}, {5, 8, 10, 21, 0, 0}}, 669 /* Unreported and depressed, one overlap, no modifiers */ 670 {{5, 10, 0}, {8, 10, 21, 0}, {0}, {5, 8, 10, 21, 0, 0}}, 671 /* Unreported and depressed, no overlap, non-overlapping modifiers */ 672 {{5, 10, 0xe2, 0xe4, 0}, {8, 21, 0xe3, 0xe6, 0}, {92}, 673 {5, 8, 10, 21, 0, 0}}, 674 /* Unreported and depressed, one overlap, non-overlapping modifiers */ 675 {{5, 10, 21, 0xe2, 0xe4, 0}, {8, 21, 0xe3, 0xe6, 0}, {92}, 676 {5, 8, 10, 21, 0, 0}}, 677 /* Unreported and depressed, no overlap, overlapping modifiers */ 678 {{5, 10, 0xe2, 0xe4, 0}, {8, 21, 0xe3, 0xe4, 0}, {28}, 679 {5, 8, 10, 21, 0, 0}}, 680 /* Unreported and depressed, one overlap, overlapping modifiers */ 681 {{5, 10, 0xe2, 0xe4, 0}, {5, 8, 21, 0xe3, 0xe4, 0}, {28}, 682 {5, 8, 10, 21, 0, 0}}, 683 /* Just too many unreported, no modifiers */ 684 {{4, 9, 11, 12, 16, 18, 20, 0}, {0}, {0}, {1, 1, 1, 1, 1, 1}}, 685 /* Just too many unreported, two modifiers */ 686 {{4, 9, 11, 12, 16, 18, 20, 0xe2, 0xe4, 0}, {0}, {20}, 687 {1, 1, 1, 1, 1, 1}}, 688 /* Just too many depressed, no modifiers */ 689 {{0}, {7, 20, 22, 25, 27, 29, 34, 0}, {0}, {1, 1, 1, 1, 1, 1}}, 690 /* Just too many depressed, two modifiers */ 691 {{0}, {7, 20, 22, 25, 27, 29, 34, 0xe3, 0xe5, 0}, {40}, 692 {1, 1, 1, 1, 1, 1}}, 693 /* Too many unreported and depressed, no overlap, no modifiers */ 694 {{5, 10, 12, 13, 0}, {8, 9, 21, 0}, {0}, {1, 1, 1, 1, 1, 1}}, 695 /* Eight unreported and depressed total, one overlap, no modifiers */ 696 {{5, 10, 12, 13, 0}, {8, 10, 21, 22, 0}, {0}, {1, 1, 1, 1, 1, 1}}, 697 /* Seven unreported and depressed total, one overlap, no modifiers */ 698 {{5, 10, 12, 13, 0}, {8, 10, 21, 0}, {0}, {5, 8, 10, 12, 13, 21}}, 699 /* Too many unreported and depressed, no overlap, two modifiers */ 700 {{5, 10, 12, 13, 0xe2, 0}, {8, 9, 21, 0xe4, 0}, {20}, 701 {1, 1, 1, 1, 1, 1}}, 702 /* Eight unreported and depressed total, one overlap, two modifiers */ 703 {{5, 10, 12, 13, 0xe1, 0}, {8, 10, 21, 22, 0xe2, 0}, {6}, 704 {1, 1, 1, 1, 1, 1}}, 705 /* Seven unreported and depressed total, one overlap, two modifiers */ 706 {{5, 10, 12, 13, 0xe2, 0}, {8, 10, 21, 0xe3, 0}, {12}, 707 {5, 8, 10, 12, 13, 21}} 708 }; 709 710 /** Test case for usbHidFillReport() */ 711 class testUsbHidFillReport 712 { 713 USBHIDK_REPORT mReport; 714 uint8_t mabUnreportedKeys[VBOX_USB_USAGE_ARRAY_SIZE]; 715 uint8_t mabDepressedKeys[VBOX_USB_USAGE_ARRAY_SIZE]; 716 const uint8_t (*mTests)[4][10]; 717 718 void doTest(unsigned cTest, const uint8_t *paiUnreportedKeys, 719 const uint8_t *paiDepressedKeys, uint8_t aExpShiftState, 720 const uint8_t *pabExpKeys) 721 { 722 RT_ZERO(mReport); 723 RT_ZERO(mabUnreportedKeys); 724 RT_ZERO(mabDepressedKeys); 725 for (unsigned i = 0; paiUnreportedKeys[i] != 0; ++i) 726 mabUnreportedKeys[paiUnreportedKeys[i]] = 1; 727 for (unsigned i = 0; paiDepressedKeys[i] != 0; ++i) 728 mabUnreportedKeys[paiDepressedKeys[i]] = 1; 729 int rc = usbHidFillReport(&mReport, mabUnreportedKeys, mabDepressedKeys); 730 AssertMsgRC(rc, ("test %u\n", cTest)); 731 AssertMsg(mReport.ShiftState == aExpShiftState, ("test %u\n", cTest)); 732 for (unsigned i = 0; i < RT_ELEMENTS(mReport.aKeys); ++i) 733 AssertMsg(mReport.aKeys[i] == pabExpKeys[i], ("test %u\n", cTest)); 734 } 735 736 public: 737 testUsbHidFillReport(void) : mTests(&testUsbHidFillReportData[0]) 738 { 739 for (unsigned i = 0; i < RT_ELEMENTS(testUsbHidFillReportData); ++i) 740 doTest(i, mTests[i][0], mTests[i][1], mTests[i][2][0], 741 mTests[i][3]); 742 } 743 }; 744 745 static testUsbHidFillReport gsTestUsbHidFillReport; 746 #endif 598 } 747 599 748 600 /** … … 775 627 776 628 /** 777 * Sends a state report to the host if there is a pending URB.778 */ 779 static intusbHidSendReport(PUSBHID pThis)629 * Sends a state report to the guest if there is a URB available. 630 */ 631 static void usbHidSendReport(PUSBHID pThis) 780 632 { 781 633 PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue); … … 784 636 PUSBHIDK_REPORT pReport = (PUSBHIDK_REPORT)&pUrb->abData[0]; 785 637 786 int again = usbHidFillReport(pReport, pThis->abUnreportedKeys, 787 pThis->abDepressedKeys); 788 if (again) 789 pThis->fHasPendingChanges = true; 790 else 791 pThis->fHasPendingChanges = false; 792 return usbHidCompleteOk(pThis, pUrb, sizeof(*pReport)); 638 usbHidBuildReport(pReport, pThis->abDepressedKeys); 639 pThis->fHasPendingChanges = false; 640 usbHidCompleteOk(pThis, pUrb, sizeof(*pReport)); 793 641 } 794 642 else … … 797 645 pThis->fHasPendingChanges = true; 798 646 } 799 return VINF_EOF;800 647 } 801 648 … … 825 672 PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort); 826 673 uint8_t u8HidCode; 827 intfKeyDown;674 bool fKeyDown; 828 675 bool fHaveEvent = true; 676 int rc = VINF_SUCCESS; 829 677 830 678 RTCritSectEnter(&pThis->CritSect); 831 679 832 if (RT_UNLIKELY(u32UsageCode == KRSP_BAT_FAIL)) 833 { 834 /* Clear all currently depressed and unreported keys. */ 835 RT_ZERO(pThis->abDepressedKeys); 836 RT_ZERO(pThis->abUnreportedKeys); 837 usbHidSendReport(pThis); 838 } 839 else 840 { 841 fKeyDown = !(u32UsageCode & 0x80000000); 842 u8HidCode = u32UsageCode & 0xFF; 843 AssertReturn(u8HidCode <= VBOX_USB_MAX_USAGE_CODE, VERR_INTERNAL_ERROR); 844 845 LogFlowFunc(("key %s: 0x%x\n", fKeyDown ? "down" : "up", u8HidCode)); 846 847 if (fKeyDown) 680 /* Let's see what we got... */ 681 fKeyDown = !(u32UsageCode & 0x80000000); 682 u8HidCode = u32UsageCode & 0xFF; 683 AssertReturn(u8HidCode <= VBOX_USB_MAX_USAGE_CODE, VERR_INTERNAL_ERROR); 684 685 LogFlowFunc(("key %s: 0x%x\n", fKeyDown ? "down" : "up", u8HidCode)); 686 687 /* 688 * Due to host key repeat, we can get key events for keys which are 689 * already depressed. Drop those right here. 690 */ 691 if (fKeyDown && pThis->abDepressedKeys[u8HidCode]) 692 fHaveEvent = false; 693 694 /* If there is already a pending event, we won't accept a new one yet. */ 695 if (pThis->fHasPendingChanges && fHaveEvent) 696 { 697 pThis->fHasPendingChanges = true; 698 rc = VERR_TRY_AGAIN; 699 } 700 else if (fHaveEvent) 701 { 702 if (RT_UNLIKELY(u32UsageCode == KRSP_BAT_FAIL)) 848 703 { 849 /* Due to host key repeat, we can get key events for keys which are 850 * already depressed. */ 851 if (!pThis->abDepressedKeys[u8HidCode]) 852 { 853 pThis->abUnreportedKeys[u8HidCode] = 1; 854 855 /* If a non-modifier key is being marked as unreported, also set 856 * all currently depressed modifer keys as unreported. This avoids 857 * problems where a simulated key sequence is sent too fast and 858 * by the time the key is reported, some previously reported 859 * modifiers are already released. This helps ensure that the guest 860 * sees the entire modifier(s)+key sequence in a single report. 861 */ 862 if (!usbHidUsageCodeIsModifier(u8HidCode)) 863 { 864 int iModKey; 865 866 for (iModKey = USBHID_MODIFIER_FIRST; iModKey <= USBHID_MODIFIER_LAST; ++iModKey) 867 if (pThis->abDepressedKeys[iModKey]) 868 pThis->abUnreportedKeys[iModKey] = 1; 869 } 870 } 871 else 872 fHaveEvent = false; 873 pThis->abDepressedKeys[u8HidCode] = 1; 704 /* Clear all currently depressed and unreported keys. */ 705 RT_ZERO(pThis->abDepressedKeys); 874 706 } 875 707 else 876 708 { 877 /* For stupid Korean keyboards, we have to fake a key up/down sequence 878 * because they only send break codes for Hangul/Hanja keys. 879 */ 880 if (u8HidCode == 0x90 || u8HidCode == 0x91) 881 pThis->abUnreportedKeys[u8HidCode] = 1; 882 pThis->abDepressedKeys[u8HidCode] = 0; 709 /* Regular key event - update keyboard state. */ 710 if (fKeyDown) 711 pThis->abDepressedKeys[u8HidCode] = 1; 712 else 713 pThis->abDepressedKeys[u8HidCode] = 0; 883 714 } 884 715 885 886 /* Send a report if the host is already waiting for it. */ 887 if (fHaveEvent) 888 usbHidSendReport(pThis); 716 /* 717 * Try sending a report. Note that we already decided to consume the 718 * event regardless of whether a URB is available or not. If it's not, 719 * we will simply not accept any further events. 720 */ 721 usbHidSendReport(pThis); 889 722 } 890 723 891 724 RTCritSectLeave(&pThis->CritSect); 892 725 893 return VINF_SUCCESS;726 return rc; 894 727 } 895 728 … … 1001 834 /* If device was not set idle, send the current report right away. */ 1002 835 if (pThis->bIdle != 0 || pThis->fHasPendingChanges) 836 { 1003 837 usbHidSendReport(pThis); 1004 LogFlow(("usbHidHandleIntrDevToHost: Sent report via %p:%s\n", pUrb, pUrb->pszDesc)); 838 LogFlow(("usbHidHandleIntrDevToHost: Sent report via %p:%s\n", pUrb, pUrb->pszDesc)); 839 Assert(!pThis->fHasPendingChanges); /* Since we just got a URB... */ 840 /* There may be more input queued up. Ask for it now. */ 841 pThis->Lun0.pDrv->pfnFlushQueue(pThis->Lun0.pDrv); 842 } 1005 843 return VINF_SUCCESS; 1006 844
Note:
See TracChangeset
for help on using the changeset viewer.