VirtualBox

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


Ignore:
Timestamp:
Mar 31, 2010 12:57:26 PM (15 years ago)
Author:
vboxsync
Message:

USB keyboard: state machine refinements, locking, Caps Lock scancode bug

File:
1 edited

Legend:

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

    r27838 r27890  
    128128    PPDMUSBINS          pUsbIns;
    129129    /** Critical section protecting the device state. */
    130     RTCRITSECT          CritSect;
     130    RTCRITSECT          csLock;
    131131
    132132    /** The current configuration.
     
    162162    /** If no URB since last key press */
    163163    bool                fNoUrbSinceLastPress;
     164    /* If device has pending changes */
     165    bool                fHasPendingChanges;
    164166    /* Keys released since last URB */
    165167    uint8_t             aReleasedKeys[6];
     
    356358    0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
    357359    0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
    358     0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
     360    0xe2, 0x2c, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
    359361    0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
    360362    0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
     
    438440*******************************************************************************/
    439441
     442/* Everything happens in R3 */
     443/**
     444 * Lock device state mutex.
     445 */
     446DECLINLINE(int) usbKbdLock(PUSBHID pThis)
     447{
     448    return RTCritSectEnter(&pThis->csLock);
     449}
     450
     451/**
     452 * Unlock device state mutex.
     453 */
     454DECLINLINE(void) usbKbdUnlock(PUSBHID pThis)
     455{
     456    RTCritSectLeave(&pThis->csLock);
     457}
     458
    440459/**
    441460 * Initializes an URB queue.
     
    448467    pQueue->ppTail = &pQueue->pHead;
    449468}
    450 
    451 
    452469
    453470/**
     
    608625    memset(&pThis->Report, 0, sizeof(pThis->Report));
    609626    pThis->fNoUrbSinceLastPress = false;
    610     memset(&pThis->aReleasedKeys, 0, sizeof(pThis->aReleasedKeys));
     627    pThis->fHasPendingChanges = false;
     628    memset(&pThis->aReleasedKeys[0], 0, sizeof(pThis->aReleasedKeys));
    611629
    612630    for (unsigned i = 0; i < RT_ELEMENTS(pThis->aEps); i++)
     
    634652{
    635653    unsigned i;
    636    
     654
    637655    for (i = 0; i < RT_ELEMENTS(pThis->Report.aKeys); ++i)
    638656    {
    639657        if (pThis->Report.aKeys[i] == u8HidCode)
    640658        {
     659            /* Remove key down. */
    641660            pThis->Report.aKeys[i] = 0;
    642             break;                              /* Remove key down. */
    643661        }
    644662    }
    645663
     664#if 0
    646665    if (i == RT_ELEMENTS(pThis->Report.aKeys))
    647666    {
    648         //            AssertMsgFailed(("Key is up but was never down!?"));
    649     }
    650 }
     667        Log(("Key 0x%x is up but was never down!?", u8HidCode));
     668    }
     669#endif
     670}
     671
     672static void usbHidCommitReportReleased(PUSBHID pThis)
     673{
     674    unsigned i;
     675    for (i=0; i < RT_ELEMENTS(pThis->aReleasedKeys); ++i)
     676    {
     677        if (pThis->aReleasedKeys[i] != 0)
     678        {
     679            usbHidUpdateReportReleased(pThis, pThis->aReleasedKeys[i]);
     680            pThis->aReleasedKeys[i] = 0;
     681        }
     682    }
     683}
     684
     685#ifdef DEBUG
     686#define HEX_DIGIT(x) (((x) < 0xa) ? ((x) + '0') : ((x) - 0xa + 'a'))
     687static void usbHidComputePressed(PUSBHIDK_REPORT pReport, char* pszBuf, unsigned uBufLen)
     688{
     689    unsigned i, uBufPos = 0;
     690    for (i=0; i < RT_ELEMENTS(pReport->aKeys); ++i)
     691    {
     692        uint8_t uCode = pReport->aKeys[i];
     693        if (uCode != 0)
     694        {
     695            if (uBufPos + 4 >= uBufLen)
     696                break;
     697            pszBuf[uBufPos++] = HEX_DIGIT(uCode >> 4);
     698            pszBuf[uBufPos++] = HEX_DIGIT(uCode & 0xf);
     699            pszBuf[uBufPos++] = ' ';
     700        }
     701    }
     702    pszBuf[uBufPos++] = '\0';
     703}
     704#undef HEX_DIGIT
     705#endif
    651706
    652707/**
     
    662717        unsigned        i;
    663718
     719#ifdef DEBUG
     720        char            szActiveBuf[128];
     721        usbHidComputePressed(pReport, szActiveBuf, sizeof szActiveBuf);
     722        Log2(("Sending report with pressed keys: %s\n", szActiveBuf));
     723#endif
    664724        cbCopy = sizeof(*pReport);
    665725        memcpy(&pUrb->abData[0], pReport, cbCopy);
    666726        pThis->fNoUrbSinceLastPress = false;
    667         for (i=0; i < RT_ELEMENTS(pThis->aReleasedKeys); ++i)
    668         {
    669             if (pThis->aReleasedKeys[i] != 0)
    670             {
    671                 usbHidUpdateReportReleased(pThis, pThis->aReleasedKeys[i]);
    672                 pThis->aReleasedKeys[i] = 0;
    673             }
    674         }
     727        pThis->fHasPendingChanges = false;
     728        usbHidCommitReportReleased(pThis);
     729#ifdef DEBUG
     730        usbHidComputePressed(pReport, szActiveBuf, sizeof szActiveBuf);
     731        Log2(("New state: %s\n", szActiveBuf));
     732#endif
    675733//        LogRel(("Sent report: %x : %x %x, size %d\n", pReport->ShiftState, pReport->aKeys[0], pReport->aKeys[1], cbCopy));
    676734        return usbHidCompleteOk(pThis, pUrb, cbCopy);
     
    678736    else
    679737    {
    680         Log(("No available URB for USB kbd\n"));
     738        Log2(("No available URB for USB kbd\n"));
     739        pThis->fHasPendingChanges = true;
    681740    }
    682741    return VINF_EOF;
     
    705764    PUSBHID pThis = RT_FROM_MEMBER(pInterface, USBHID, Lun0.IPort);
    706765    PUSBHIDK_REPORT pReport = &pThis->Report;
    707     uint32_t    u32Usage;
     766    uint32_t    u32Usage = 0;
    708767    uint8_t     u8HidCode;
    709768    int         fKeyDown;
    710769    unsigned    i;
    711770
    712 //    int rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
    713 //    AssertReleaseRC(rc);
     771    usbKbdLock(pThis);
    714772
    715773    pThis->XlatState = ScancodeToHidUsage(pThis->XlatState, u8KeyCode, &u32Usage);
     
    721779        u8HidCode = u32Usage & 0xFF;
    722780
     781        Log(("key %s: 0x%x->0x%x\n",
     782             fKeyDown ? "down" : "up", u8KeyCode, u8HidCode));
     783
    723784        if (fKeyDown)
    724785        {
     786            bool fAlready = false;
    725787            for (i = 0; i < RT_ELEMENTS(pReport->aKeys); ++i)
    726788            {
    727789                if (pReport->aKeys[i] == u8HidCode)
    728                     break;                              /* Skip repeat events. */
    729                 if (pReport->aKeys[i] == 0)
    730790                {
    731                     pReport->aKeys[i] = u8HidCode;      /* Report key down. */
    732                     break;
     791                    /* Skip repeat events. */
     792                    fAlready = true;
     793                    break;                             
    733794                }
    734795            }
    735796
    736             pThis->fNoUrbSinceLastPress = true;
    737 
    738             if (i == RT_ELEMENTS(pReport->aKeys))
     797            if (!fAlready)
    739798            {
    740                 /* We ran out of room. Report error. */
    741                 Log(("no more room in usbHidKeyboardPutEvent\n"));
    742                 // @todo!!
     799                for (i = 0; i < RT_ELEMENTS(pReport->aKeys); ++i)
     800                {
     801                    if (pReport->aKeys[i] == 0)
     802                    {
     803                        pReport->aKeys[i] = u8HidCode;      /* Report key down. */
     804                        break;
     805                    }
     806                }
     807               
     808                pThis->fNoUrbSinceLastPress = true;
     809               
     810                if (i == RT_ELEMENTS(pReport->aKeys))
     811                {
     812                    /* We ran out of room. Report error. */
     813                    Log(("no more room in usbHidKeyboardPutEvent\n"));
     814                    // @todo!!
     815                }
    743816            }
    744817        }
    745818        else
    746819        {
    747             /* We have to avoid coalescing key presses and releases, so put all releases somewhere else */
     820            /*
     821             * We have to avoid coalescing key presses and releases,
     822             * so put all releases somewhere else if press wasn't seen
     823             * by the guest.
     824             */
    748825            if (pThis->fNoUrbSinceLastPress)
    749             {               
     826            {
    750827                for (i = 0; i < RT_ELEMENTS(pThis->aReleasedKeys); ++i)
    751828                {
     829                    if (pThis->aReleasedKeys[i] == u8HidCode)
     830                        break;
     831
    752832                    if (pThis->aReleasedKeys[i] == 0)
    753833                    {
     
    765845    }
    766846
    767 //    PDMCritSectLeave(&pThis->CritSect);
     847    usbKbdUnlock(pThis);
     848
    768849    return VINF_SUCCESS;
    769850}
     
    775856{
    776857    PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
    777     LogFlow(("usbHidUrbReap/#%u: cMillies=%u\n", pUsbIns->iInstance, cMillies));
    778 
    779     RTCritSectEnter(&pThis->CritSect);
     858    //LogFlow(("usbHidUrbReap/#%u: cMillies=%u\n", pUsbIns->iInstance, cMillies));
     859
     860    usbKbdLock(pThis);
    780861
    781862    PVUSBURB pUrb = usbHidQueueRemoveHead(&pThis->DoneQueue);
     
    784865        /* Wait */
    785866        pThis->fHaveDoneQueueWaiter = true;
    786         RTCritSectLeave(&pThis->CritSect);
     867        usbKbdUnlock(pThis);
    787868
    788869        RTSemEventWait(pThis->hEvtDoneQueue, cMillies);
    789870
    790         RTCritSectEnter(&pThis->CritSect);
     871        usbKbdLock(pThis);
    791872        pThis->fHaveDoneQueueWaiter = false;
    792873
     
    794875    }
    795876
    796     RTCritSectLeave(&pThis->CritSect);
     877    usbKbdUnlock(pThis);
    797878
    798879    if (pUrb)
     
    809890    PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
    810891    LogFlow(("usbHidUrbCancel/#%u: pUrb=%p:%s\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc));
    811     RTCritSectEnter(&pThis->CritSect);
     892    usbKbdLock(pThis);
    812893
    813894    /*
     
    817898        usbHidLinkDone(pThis, pUrb);
    818899
    819     RTCritSectLeave(&pThis->CritSect);
     900    usbKbdUnlock(pThis);
    820901    return VINF_SUCCESS;
    821902}
     
    864945            usbHidQueueAddTail(&pThis->ToHostQueue, pUrb);
    865946            /* If device was not set idle, sent the current report right away. */
    866             if (pThis->bIdle != 0)
     947            if (pThis->bIdle != 0 || pThis->fHasPendingChanges)
    867948                usbHidSendReport(pThis);
    868949            LogFlow(("usbHidHandleIntrDevToHost: Sent report via %p:%s\n", pUrb, pUrb->pszDesc));
     
    10631144    PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
    10641145    LogFlow(("usbHidQueue/#%u: pUrb=%p:%s EndPt=%#x\n", pUsbIns->iInstance, pUrb, pUrb->pszDesc, pUrb->EndPt));
    1065     RTCritSectEnter(&pThis->CritSect);
     1146    usbKbdLock(pThis);
    10661147
    10671148    /*
     
    10871168    }
    10881169
    1089     RTCritSectLeave(&pThis->CritSect);
     1170    usbKbdUnlock(pThis);
    10901171    return rc;
    10911172}
     
    11021183    if ((uEndpoint & ~0x80) < RT_ELEMENTS(pThis->aEps))
    11031184    {
    1104         RTCritSectEnter(&pThis->CritSect);
     1185        usbKbdLock(pThis);
    11051186        pThis->aEps[(uEndpoint & ~0x80)].fHalted = false;
    1106         RTCritSectLeave(&pThis->CritSect);
     1187        usbKbdUnlock(pThis);
    11071188    }
    11081189
     
    11311212    LogFlow(("usbHidUsbSetConfiguration/#%u: bConfigurationValue=%u\n", pUsbIns->iInstance, bConfigurationValue));
    11321213    Assert(bConfigurationValue == 1);
    1133     RTCritSectEnter(&pThis->CritSect);
     1214    usbKbdLock(pThis);
    11341215
    11351216    /*
     
    11401221    pThis->bConfigurationValue = bConfigurationValue;
    11411222
    1142     RTCritSectLeave(&pThis->CritSect);
     1223    usbKbdUnlock(pThis);
    11431224    return VINF_SUCCESS;
    11441225}
     
    11631244    PUSBHID pThis = PDMINS_2_DATA(pUsbIns, PUSBHID);
    11641245    LogFlow(("usbHidUsbReset/#%u:\n", pUsbIns->iInstance));
    1165     RTCritSectEnter(&pThis->CritSect);
     1246    usbKbdLock(pThis);
    11661247
    11671248    int rc = usbHidResetWorker(pThis, NULL, false /*fSetConfig*/);
    11681249
    1169     RTCritSectLeave(&pThis->CritSect);
     1250    usbKbdUnlock(pThis);
    11701251    return rc;
    11711252}
     
    11801261    LogFlow(("usbHidDestruct/#%u:\n", pUsbIns->iInstance));
    11811262
    1182     if (RTCritSectIsInitialized(&pThis->CritSect))
    1183     {
    1184         RTCritSectEnter(&pThis->CritSect);
    1185         RTCritSectLeave(&pThis->CritSect);
    1186         RTCritSectDelete(&pThis->CritSect);
     1263    if (RTCritSectIsInitialized(&pThis->csLock))
     1264    {
     1265        /* Let whoever runs in this critical section complete */
     1266        usbKbdLock(pThis);
     1267        usbKbdUnlock(pThis);
     1268        RTCritSectDelete(&pThis->csLock);
    11871269    }
    11881270
     
    12131295    usbHidQueueInit(&pThis->DoneQueue);
    12141296
    1215     int rc = RTCritSectInit(&pThis->CritSect);
     1297    int rc = RTCritSectInit(&pThis->csLock);
    12161298    AssertRCReturn(rc, rc);
    12171299
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