VirtualBox

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


Ignore:
Timestamp:
Feb 26, 2010 4:40:20 PM (15 years ago)
Author:
vboxsync
Message:

UsbKbd: Improved scancode to HID usage translation.

File:
1 edited

Legend:

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

    r26669 r26867  
    113113} USBHIDK_REPORT, *PUSBHIDK_REPORT;
    114114
     115/* Scancode translator state.  */
     116typedef enum {
     117    SS_IDLE,    /* Starting state. */
     118    SS_EXT,     /* E0 byte was received. */
     119    SS_EXT1,    /* E1 byte was received. */
     120} scan_state_t;
     121
    115122/**
    116123 * The USB HID instance data.
     
    134141    USBHIDREQSTATE      enmState;
    135142
     143    /** State of the scancode translation. */
     144    scan_state_t        XlatState;
     145
    136146    /** HID report reflecting the current keyboard state. */
    137147    USBHIDK_REPORT      Report;
     
    169179        R3PTRTYPE(PPDMIKEYBOARDCONNECTOR)   pDrv;
    170180    } Lun0;
    171 
    172181} USBHID;
    173182/** Pointer to the USB HID instance data. */
     
    323332
    324333
    325 /*******************************************************************************
    326 *   Internal Functions                                                         *
    327 *******************************************************************************/
    328 
    329 /**
    330  * Initializes an URB queue.
     334/*
     335 * Because of historical reasons and poor design, VirtualBox internally uses BIOS
     336 * PC/XT style scan codes to represent keyboard events. Each key press and release is
     337 * represented as a stream of bytes, typically only one byte but up to four-byte
     338 * sequences are possible. In the typical case, the GUI front end generates the stream
     339 * of scan codes which we need to translate back to a single up/down event.
    331340 *
    332  * @param   pQueue              The URB queue.
    333  */
    334 static void usbHidQueueInit(PUSBHIDURBQUEUE pQueue)
    335 {
    336     pQueue->pHead = NULL;
    337     pQueue->ppTail = &pQueue->pHead;
    338 }
    339 
    340 
    341 
    342 /**
    343  * Inserts an URB at the end of the queue.
    344  *
    345  * @param   pQueue              The URB queue.
    346  * @param   pUrb                The URB to insert.
    347  */
    348 DECLINLINE(void) usbHidQueueAddTail(PUSBHIDURBQUEUE pQueue, PVUSBURB pUrb)
    349 {
    350     pUrb->Dev.pNext = NULL;
    351     *pQueue->ppTail = pUrb;
    352     pQueue->ppTail  = &pUrb->Dev.pNext;
    353 }
    354 
    355 
    356 /**
    357  * Unlinks the head of the queue and returns it.
    358  *
    359  * @returns The head entry.
    360  * @param   pQueue              The URB queue.
    361  */
    362 DECLINLINE(PVUSBURB) usbHidQueueRemoveHead(PUSBHIDURBQUEUE pQueue)
    363 {
    364     PVUSBURB pUrb = pQueue->pHead;
    365     if (pUrb)
    366     {
    367         PVUSBURB pNext = pUrb->Dev.pNext;
    368         pQueue->pHead = pNext;
    369         if (!pNext)
    370             pQueue->ppTail = &pQueue->pHead;
    371         else
    372             pUrb->Dev.pNext = NULL;
    373     }
    374     return pUrb;
    375 }
    376 
    377 
    378 /**
    379  * Removes an URB from anywhere in the queue.
    380  *
    381  * @returns true if found, false if not.
    382  * @param   pQueue              The URB queue.
    383  * @param   pUrb                The URB to remove.
    384  */
    385 DECLINLINE(bool) usbHidQueueRemove(PUSBHIDURBQUEUE pQueue, PVUSBURB pUrb)
    386 {
    387     PVUSBURB pCur = pQueue->pHead;
    388     if (pCur == pUrb)
    389         pQueue->pHead = pUrb->Dev.pNext;
    390     else
    391     {
    392         while (pCur)
    393         {
    394             if (pCur->Dev.pNext == pUrb)
    395             {
    396                 pCur->Dev.pNext = pUrb->Dev.pNext;
    397                 break;
    398             }
    399             pCur = pCur->Dev.pNext;
    400         }
    401         if (!pCur)
    402             return false;
    403     }
    404     if (!pUrb->Dev.pNext)
    405         pQueue->ppTail = &pQueue->pHead;
    406     return true;
    407 }
    408 
    409 
    410 /**
    411  * Checks if the queue is empty or not.
    412  *
    413  * @returns true if it is, false if it isn't.
    414  * @param   pQueue              The URB queue.
    415  */
    416 DECLINLINE(bool) usbHidQueueIsEmpty(PCUSBHIDURBQUEUE pQueue)
    417 {
    418     return pQueue->pHead == NULL;
    419 }
    420 
    421 
    422 /**
    423  * Links an URB into the done queue.
    424  *
    425  * @param   pThis               The HID instance.
    426  * @param   pUrb                The URB.
    427  */
    428 static void usbHidLinkDone(PUSBHID pThis, PVUSBURB pUrb)
    429 {
    430     usbHidQueueAddTail(&pThis->DoneQueue, pUrb);
    431 
    432     if (pThis->fHaveDoneQueueWaiter)
    433     {
    434         int rc = RTSemEventSignal(pThis->hEvtDoneQueue);
    435         AssertRC(rc);
    436     }
    437 }
    438 
    439 
    440 
    441 /**
    442  * Completes the URB with a stalled state, halting the pipe.
    443  */
    444 static int usbHidCompleteStall(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb, const char *pszWhy)
    445 {
    446     Log(("usbHidCompleteStall/#%u: pUrb=%p:%s: %s\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, pszWhy));
    447 
    448     pUrb->enmStatus = VUSBSTATUS_STALL;
    449 
    450     /** @todo figure out if the stall is global or pipe-specific or both. */
    451     if (pEp)
    452         pEp->fHalted = true;
    453     else
    454     {
    455         pThis->aEps[1].fHalted = true;
    456         pThis->aEps[2].fHalted = true;
    457     }
    458 
    459     usbHidLinkDone(pThis, pUrb);
    460     return VINF_SUCCESS;
    461 }
    462 
    463 
    464 /**
    465  * Completes the URB with a OK state.
    466  */
    467 static int usbHidCompleteOk(PUSBHID pThis, PVUSBURB pUrb, size_t cbData)
    468 {
    469     Log(("usbHidCompleteOk/#%u: pUrb=%p:%s cbData=%#zx\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, cbData));
    470 
    471     pUrb->enmStatus = VUSBSTATUS_OK;
    472     pUrb->cbData    = cbData;
    473 
    474     usbHidLinkDone(pThis, pUrb);
    475     return VINF_SUCCESS;
    476 }
    477 
    478 
    479 /**
    480  * Reset worker for usbHidUsbReset, usbHidUsbSetConfiguration and
    481  * usbHidUrbHandleDefaultPipe.
    482  *
    483  * @returns VBox status code.
    484  * @param   pThis               The HID instance.
    485  * @param   pUrb                Set when usbHidUrbHandleDefaultPipe is the
    486  *                              caller.
    487  * @param   fSetConfig          Set when usbHidUsbSetConfiguration is the
    488  *                              caller.
    489  */
    490 static int usbHidResetWorker(PUSBHID pThis, PVUSBURB pUrb, bool fSetConfig)
    491 {
    492     /*
    493      * Reset the device state.
    494      */
    495     pThis->enmState = USBHIDREQSTATE_READY;
    496     pThis->bIdle = 0;
    497     memset(&pThis->Report, 0, sizeof(pThis->Report));
    498 
    499     for (unsigned i = 0; i < RT_ELEMENTS(pThis->aEps); i++)
    500         pThis->aEps[i].fHalted = false;
    501 
    502     if (!pUrb && !fSetConfig) /* (only device reset) */
    503         pThis->bConfigurationValue = 0; /* default */
    504 
    505     /*
    506      * Ditch all pending URBs.
    507      */
    508     PVUSBURB pCurUrb;
    509     while ((pCurUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue)) != NULL)
    510     {
    511         pCurUrb->enmStatus = VUSBSTATUS_CRC;
    512         usbHidLinkDone(pThis, pCurUrb);
    513     }
    514 
    515     if (pUrb)
    516         return usbHidCompleteOk(pThis, pUrb, 0);
    517     return VINF_SUCCESS;
    518 }
    519 
    520 
    521 /**
    522  * Sends a state report to the host if there is a pending URB.
    523  */
    524 static int usbHidSendReport(PUSBHID pThis)
    525 {
    526     PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue);
    527     if (pUrb)
    528     {
    529         PUSBHIDK_REPORT pReport = &pThis->Report;
    530         size_t          cbCopy;
    531 
    532         cbCopy = sizeof(*pReport);
    533         memcpy(&pUrb->abData[0], pReport, cbCopy);
    534 //        LogRel(("Sent report: %x : %x %x, size %d\n", pReport->ShiftState, pReport->aKeys[0], pReport->aKeys[1], cbCopy));
    535         return usbHidCompleteOk(pThis, pUrb, cbCopy);
    536     }
    537     return VINF_EOF;
    538 }
    539 
    540 /**
    541  * @interface_method_impl{PDMIBASE,pfnQueryInterface}
    542  */
    543 static DECLCALLBACK(void *) usbHidKeyboardQueryInterface(PPDMIBASE pInterface, const char *pszIID)
    544 {
    545     PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IBase);
    546     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->Lun0.IBase);
    547     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIKEYBOARDPORT, &pThis->Lun0.IPort);
    548     return NULL;
    549 }
    550 
    551 static int8_t clamp_i8(int32_t val)
    552 {
    553     if (val > 127)
    554         val = 127;
    555     else if (val < -127)
    556         val = -127;
    557     return val;
    558 }
    559 
    560 static uint8_t aKeycode2Hid[] =
     341 * This function could possibly live somewhere else.
     342 */
     343
     344/* Lookup table for converting PC/XT scan codes to USB HID usage codes. */
     345static uint8_t aScancode2Hid[] =
    561346{
    562347    0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
     
    575360    0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
    576361    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    577     0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
    578 };
     362    0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65
     363};
     364
     365/* Lookup table for extended scancodes (arrow keys etc.). */
     366static uint8_t aExtScan2Hid[] =
     367{
     368    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     369    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     370    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     371    0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
     372    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     373    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     374    0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
     375    0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     376    0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
     377    0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
     378    0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
     379    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     380    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     381    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     382    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     383    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     384};
     385
     386/**
     387 * Convert a PC scan code to a USB HID usage byte.
     388 *
     389 * @param state         Current state of the translator (scan_state_t).
     390 * @param scanCode      Incoming scan code.
     391 * @param pUsage        Pointer to usage; high bit set for key up events. The
     392 *                      contents are only valid if returned state is SS_IDLE.
     393 *
     394 * @return scan_state_t New state of the translator.
     395 */
     396static scan_state_t ScancodeToHidUsage(scan_state_t state, uint8_t scanCode, uint32_t *pUsage)
     397{
     398    uint32_t    keyUp;
     399    uint8_t     usage;
     400
     401    Assert(pUsage);
     402
     403    /* Isolate the scan code and key break flag. */
     404    keyUp = (scanCode & 0x80) << 24;
     405
     406    switch (state) {
     407    case SS_IDLE:
     408        if (scanCode == 0xE0) {
     409            state = SS_EXT;
     410        } else if (scanCode == 0xE1) {
     411            state = SS_EXT1;
     412        } else {
     413            usage = aScancode2Hid[scanCode & 0x7F];
     414            *pUsage = usage | keyUp;
     415        }
     416        break;
     417    case SS_EXT:
     418        usage = aExtScan2Hid[scanCode & 0x7F];
     419        *pUsage = usage | keyUp;
     420        state = SS_IDLE;
     421        break;
     422    }
     423    return state;
     424}
     425
     426/*******************************************************************************
     427*   Internal Functions                                                         *
     428*******************************************************************************/
     429
     430/**
     431 * Initializes an URB queue.
     432 *
     433 * @param   pQueue              The URB queue.
     434 */
     435static void usbHidQueueInit(PUSBHIDURBQUEUE pQueue)
     436{
     437    pQueue->pHead = NULL;
     438    pQueue->ppTail = &pQueue->pHead;
     439}
     440
     441
     442
     443/**
     444 * Inserts an URB at the end of the queue.
     445 *
     446 * @param   pQueue              The URB queue.
     447 * @param   pUrb                The URB to insert.
     448 */
     449DECLINLINE(void) usbHidQueueAddTail(PUSBHIDURBQUEUE pQueue, PVUSBURB pUrb)
     450{
     451    pUrb->Dev.pNext = NULL;
     452    *pQueue->ppTail = pUrb;
     453    pQueue->ppTail  = &pUrb->Dev.pNext;
     454}
     455
     456
     457/**
     458 * Unlinks the head of the queue and returns it.
     459 *
     460 * @returns The head entry.
     461 * @param   pQueue              The URB queue.
     462 */
     463DECLINLINE(PVUSBURB) usbHidQueueRemoveHead(PUSBHIDURBQUEUE pQueue)
     464{
     465    PVUSBURB pUrb = pQueue->pHead;
     466    if (pUrb)
     467    {
     468        PVUSBURB pNext = pUrb->Dev.pNext;
     469        pQueue->pHead = pNext;
     470        if (!pNext)
     471            pQueue->ppTail = &pQueue->pHead;
     472        else
     473            pUrb->Dev.pNext = NULL;
     474    }
     475    return pUrb;
     476}
     477
     478
     479/**
     480 * Removes an URB from anywhere in the queue.
     481 *
     482 * @returns true if found, false if not.
     483 * @param   pQueue              The URB queue.
     484 * @param   pUrb                The URB to remove.
     485 */
     486DECLINLINE(bool) usbHidQueueRemove(PUSBHIDURBQUEUE pQueue, PVUSBURB pUrb)
     487{
     488    PVUSBURB pCur = pQueue->pHead;
     489    if (pCur == pUrb)
     490        pQueue->pHead = pUrb->Dev.pNext;
     491    else
     492    {
     493        while (pCur)
     494        {
     495            if (pCur->Dev.pNext == pUrb)
     496            {
     497                pCur->Dev.pNext = pUrb->Dev.pNext;
     498                break;
     499            }
     500            pCur = pCur->Dev.pNext;
     501        }
     502        if (!pCur)
     503            return false;
     504    }
     505    if (!pUrb->Dev.pNext)
     506        pQueue->ppTail = &pQueue->pHead;
     507    return true;
     508}
     509
     510
     511/**
     512 * Checks if the queue is empty or not.
     513 *
     514 * @returns true if it is, false if it isn't.
     515 * @param   pQueue              The URB queue.
     516 */
     517DECLINLINE(bool) usbHidQueueIsEmpty(PCUSBHIDURBQUEUE pQueue)
     518{
     519    return pQueue->pHead == NULL;
     520}
     521
     522
     523/**
     524 * Links an URB into the done queue.
     525 *
     526 * @param   pThis               The HID instance.
     527 * @param   pUrb                The URB.
     528 */
     529static void usbHidLinkDone(PUSBHID pThis, PVUSBURB pUrb)
     530{
     531    usbHidQueueAddTail(&pThis->DoneQueue, pUrb);
     532
     533    if (pThis->fHaveDoneQueueWaiter)
     534    {
     535        int rc = RTSemEventSignal(pThis->hEvtDoneQueue);
     536        AssertRC(rc);
     537    }
     538}
     539
     540
     541
     542/**
     543 * Completes the URB with a stalled state, halting the pipe.
     544 */
     545static int usbHidCompleteStall(PUSBHID pThis, PUSBHIDEP pEp, PVUSBURB pUrb, const char *pszWhy)
     546{
     547    Log(("usbHidCompleteStall/#%u: pUrb=%p:%s: %s\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, pszWhy));
     548
     549    pUrb->enmStatus = VUSBSTATUS_STALL;
     550
     551    /** @todo figure out if the stall is global or pipe-specific or both. */
     552    if (pEp)
     553        pEp->fHalted = true;
     554    else
     555    {
     556        pThis->aEps[1].fHalted = true;
     557        pThis->aEps[2].fHalted = true;
     558    }
     559
     560    usbHidLinkDone(pThis, pUrb);
     561    return VINF_SUCCESS;
     562}
     563
     564
     565/**
     566 * Completes the URB with a OK state.
     567 */
     568static int usbHidCompleteOk(PUSBHID pThis, PVUSBURB pUrb, size_t cbData)
     569{
     570    Log(("usbHidCompleteOk/#%u: pUrb=%p:%s cbData=%#zx\n", pThis->pUsbIns->iInstance, pUrb, pUrb->pszDesc, cbData));
     571
     572    pUrb->enmStatus = VUSBSTATUS_OK;
     573    pUrb->cbData    = cbData;
     574
     575    usbHidLinkDone(pThis, pUrb);
     576    return VINF_SUCCESS;
     577}
     578
     579
     580/**
     581 * Reset worker for usbHidUsbReset, usbHidUsbSetConfiguration and
     582 * usbHidUrbHandleDefaultPipe.
     583 *
     584 * @returns VBox status code.
     585 * @param   pThis               The HID instance.
     586 * @param   pUrb                Set when usbHidUrbHandleDefaultPipe is the
     587 *                              caller.
     588 * @param   fSetConfig          Set when usbHidUsbSetConfiguration is the
     589 *                              caller.
     590 */
     591static int usbHidResetWorker(PUSBHID pThis, PVUSBURB pUrb, bool fSetConfig)
     592{
     593    /*
     594     * Reset the device state.
     595     */
     596    pThis->enmState = USBHIDREQSTATE_READY;
     597    pThis->bIdle = 0;
     598    memset(&pThis->Report, 0, sizeof(pThis->Report));
     599
     600    for (unsigned i = 0; i < RT_ELEMENTS(pThis->aEps); i++)
     601        pThis->aEps[i].fHalted = false;
     602
     603    if (!pUrb && !fSetConfig) /* (only device reset) */
     604        pThis->bConfigurationValue = 0; /* default */
     605
     606    /*
     607     * Ditch all pending URBs.
     608     */
     609    PVUSBURB pCurUrb;
     610    while ((pCurUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue)) != NULL)
     611    {
     612        pCurUrb->enmStatus = VUSBSTATUS_CRC;
     613        usbHidLinkDone(pThis, pCurUrb);
     614    }
     615
     616    if (pUrb)
     617        return usbHidCompleteOk(pThis, pUrb, 0);
     618    return VINF_SUCCESS;
     619}
     620
     621
     622/**
     623 * Sends a state report to the host if there is a pending URB.
     624 */
     625static int usbHidSendReport(PUSBHID pThis)
     626{
     627    PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->ToHostQueue);
     628    if (pUrb)
     629    {
     630        PUSBHIDK_REPORT pReport = &pThis->Report;
     631        size_t          cbCopy;
     632
     633        cbCopy = sizeof(*pReport);
     634        memcpy(&pUrb->abData[0], pReport, cbCopy);
     635//        LogRel(("Sent report: %x : %x %x, size %d\n", pReport->ShiftState, pReport->aKeys[0], pReport->aKeys[1], cbCopy));
     636        return usbHidCompleteOk(pThis, pUrb, cbCopy);
     637    }
     638    return VINF_EOF;
     639}
     640
     641/**
     642 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
     643 */
     644static DECLCALLBACK(void *) usbHidKeyboardQueryInterface(PPDMIBASE pInterface, const char *pszIID)
     645{
     646    PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IBase);
     647    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->Lun0.IBase);
     648    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIKEYBOARDPORT, &pThis->Lun0.IPort);
     649    return NULL;
     650}
    579651
    580652/**
     
    589661    PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
    590662    PUSBHIDK_REPORT pReport = &pThis->Report;
    591     uint8_t u8HidCode;
    592     int fKeyDown;
    593     unsigned i;
     663    uint32_t    u32Usage;
     664    uint8_t     u8HidCode;
     665    int         fKeyDown;
     666    unsigned    i;
    594667
    595668//    int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
    596669//    AssertReleaseRC(rc);
    597670
    598     /* Extract the key event. */
    599     u8HidCode = aKeycode2Hid[u8KeyCode & 0x7f];
    600     fKeyDown = !(u8KeyCode & 0x80);
    601 
    602     if (fKeyDown)
    603     {
    604         for (i = 0; i < RT_ELEMENTS(pReport->aKeys); ++i)
     671    pThis->XlatState = ScancodeToHidUsage(pThis->XlatState, u8KeyCode, &u32Usage);
     672
     673    if (pThis->XlatState == SS_IDLE)
     674    {
     675        /* The usage code is valid. */
     676        fKeyDown = !(u32Usage & 0x80000000);
     677        u8HidCode = u32Usage & 0xFF;
     678
     679        if (fKeyDown)
    605680        {
    606             if (pReport->aKeys[i] == u8HidCode)
    607                 break;                              /* Skip repeat events. */
    608             if (pReport->aKeys[i] == 0)
     681            for (i = 0; i < RT_ELEMENTS(pReport->aKeys); ++i)
    609682            {
    610                 pReport->aKeys[i] = u8HidCode;      /* Report key down. */
    611                 break;
     683                if (pReport->aKeys[i] == u8HidCode)
     684                    break;                              /* Skip repeat events. */
     685                if (pReport->aKeys[i] == 0)
     686                {
     687                    pReport->aKeys[i] = u8HidCode;      /* Report key down. */
     688                    break;
     689                }
     690            }
     691            if (i == RT_ELEMENTS(pReport->aKeys))
     692            {
     693                /* We ran out of room. Report error. */
     694                // @todo!!
    612695            }
    613696        }
    614         if (i == RT_ELEMENTS(pReport->aKeys))
     697        else
    615698        {
    616             /* We ran out of room. Report error. */
    617             // @todo!!
    618         }
    619     }
    620     else
    621     {
    622         for (i = 0; i < RT_ELEMENTS(pReport->aKeys); ++i)
    623         {
    624             if (pReport->aKeys[i] == u8HidCode)
     699            for (i = 0; i < RT_ELEMENTS(pReport->aKeys); ++i)
    625700            {
    626                 pReport->aKeys[i] = 0;
    627                 break;                              /* Remove key down. */
     701                if (pReport->aKeys[i] == u8HidCode)
     702                {
     703                    pReport->aKeys[i] = 0;
     704                    break;                              /* Remove key down. */
     705                }
     706            }
     707            if (i == RT_ELEMENTS(pReport->aKeys))
     708            {
     709    //            AssertMsgFailed(("Key is up but was never down!?"));
    628710            }
    629711        }
    630         if (i == RT_ELEMENTS(pReport->aKeys))
    631         {
    632 //            AssertMsgFailed(("Key is up but was never down!?"));
    633         }
    634     }
    635 
    636     /* Send a report if the host is already waiting for it. */
    637     usbHidSendReport(pThis);
     712
     713        /* Send a report if the host is already waiting for it. */
     714        usbHidSendReport(pThis);
     715    }
    638716
    639717//    PDMCritSectLeave(&pThis->CritSect);
     
    10221100    pThis->pUsbIns                                  = pUsbIns;
    10231101    pThis->hEvtDoneQueue                            = NIL_RTSEMEVENT;
     1102    pThis->XlatState                                = SS_IDLE;
    10241103    usbHidQueueInit(&pThis->ToHostQueue);
    10251104    usbHidQueueInit(&pThis->DoneQueue);
Note: See TracChangeset for help on using the changeset viewer.

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