VirtualBox

Changeset 51539 in vbox for trunk/src/VBox/Devices/Input


Ignore:
Timestamp:
Jun 4, 2014 9:34:18 PM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
94184
Message:

Keyboard: Extended keyboard driver and reworked USB keyboard device emulation. See #7328.

Location:
trunk/src/VBox/Devices/Input
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Input/DrvKeyboardQueue.cpp

    r50962 r51539  
    228228        if (pItem)
    229229        {
     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
    230250            pItem->u32UsageCode = u32Usage;
    231251            PDMQueueInsert(pDrv->pQueue, &pItem->Core);
     252
    232253            return VINF_SUCCESS;
    233254        }
     
    270291    AssertPtr(pDrv->pDownConnector->pfnSetActive);
    271292    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 */
     300static DECLCALLBACK(void) drvKbdFlushQueue(PPDMIKEYBOARDCONNECTOR pInterface)
     301{
     302    PDRVKBDQUEUE pDrv = PPDMIKEYBOARDCONNECTOR_2_DRVKBDQUEUE(pInterface);
     303
     304    AssertPtr(pDrv->pQueue);
     305    PDMQueueFlushIfNecessary(pDrv->pQueue);
    272306}
    273307
     
    387421    pDrv->IConnector.pfnLedStatusChange     = drvKbdPassThruLedsChange;
    388422    pDrv->IConnector.pfnSetActive           = drvKbdPassThruSetActive;
     423    pDrv->IConnector.pfnFlushQueue          = drvKbdFlushQueue;
    389424    /* IKeyboardPort. */
    390425    pDrv->IPort.pfnPutEventScan             = drvKbdQueuePutEventScan;
  • trunk/src/VBox/Devices/Input/PS2K.cpp

    r50962 r51539  
    11661166    else
    11671167    {
    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 
    11721168        ps2kPutEventWorker(pThis, u32UsageCode);
    11731169    }
  • trunk/src/VBox/Devices/Input/UsbKbd.cpp

    r50962 r51539  
    169169    /** If device has pending changes. */
    170170    bool                fHasPendingChanges;
    171     /** Keypresses which have not yet been reported.  A workaround for the
    172      * problem of keys being released before the keypress could be reported. */
    173     uint8_t             abUnreportedKeys[VBOX_USB_USAGE_ARRAY_SIZE];
    174171    /** Currently depressed keys */
    175172    uint8_t             abDepressedKeys[VBOX_USB_USAGE_ARRAY_SIZE];
     
    463460
    464461
    465 
    466462/**
    467463 * Completes the URB with a stalled state, halting the pipe.
     
    548544}
    549545
    550 #ifdef DEBUG
    551 # 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_DIGIT
    571 #endif
    572 
    573546/**
    574547 * Returns true if the usage code corresponds to a keyboard modifier key
     
    593566
    594567/**
    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 */
     571static void usbHidBuildReport(PUSBHIDK_REPORT pReport, uint8_t *pabDepressedKeys)
     572{
    606573    unsigned iBuf = 0;
    607574    RT_ZERO(*pReport);
    608575    for (unsigned iKey = 0; iKey < VBOX_USB_USAGE_ARRAY_SIZE; ++iKey)
    609576    {
    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])
    613579        {
    614580            if (usbHidUsageCodeIsModifier(iKey))
     
    627593                pReport->aKeys[iBuf] = iKey;
    628594                ++iBuf;
    629                 /* More Korean keyboard hackery: Give the caller a hint that
    630                  * a key release event needs reporting.
    631                  */
    632                 if (iKey == 0x90 || iKey == 0x91)
    633                     rc = true;
    634595            }
    635             /* Avoid "hanging" keys: If a key is unreported but no longer
    636              * 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;
    642596        }
    643597    }
    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}
    747599
    748600/**
     
    775627
    776628/**
    777  * Sends a state report to the host if there is a pending URB.
    778  */
    779 static int usbHidSendReport(PUSBHID pThis)
     629 * Sends a state report to the guest if there is a URB available.
     630 */
     631static void usbHidSendReport(PUSBHID pThis)
    780632{
    781633    PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue);
     
    784636        PUSBHIDK_REPORT pReport = (PUSBHIDK_REPORT)&pUrb->abData[0];
    785637
    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));
    793641    }
    794642    else
     
    797645        pThis->fHasPendingChanges = true;
    798646    }
    799     return VINF_EOF;
    800647}
    801648
     
    825672    PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
    826673    uint8_t     u8HidCode;
    827     int         fKeyDown;
     674    bool        fKeyDown;
    828675    bool        fHaveEvent = true;
     676    int         rc = VINF_SUCCESS;
    829677
    830678    RTCritSectEnter(&pThis->CritSect);
    831679
    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))
    848703        {
    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);
    874706        }
    875707        else
    876708        {
    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;
    883714        }
    884715
    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);
    889722    }
    890723
    891724    RTCritSectLeave(&pThis->CritSect);
    892725
    893     return VINF_SUCCESS;
     726    return rc;
    894727}
    895728
     
    1001834            /* If device was not set idle, send the current report right away. */
    1002835            if (pThis->bIdle != 0 || pThis->fHasPendingChanges)
     836            {
    1003837                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            }
    1005843            return VINF_SUCCESS;
    1006844
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette