VirtualBox

Changeset 81214 in vbox


Ignore:
Timestamp:
Oct 10, 2019 1:20:41 PM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
133878
Message:

Input: Added support for translating USB HID usage page 12 (Consumer Control) codes to PS/2 scan codes.

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

Legend:

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

    r79675 r81214  
    2727#include "VBoxDD.h"
    2828
     29
     30/*********************************************************************************************************************************
     31*   Defined Constants And Macros                                                                                                 *
     32*********************************************************************************************************************************/
     33/** Keyboard usage page bits to be OR-ed into the code. */
     34#define HID_PG_KB_BITS  0x070000
    2935
    3036
     
    156162        } else {
    157163            usage = aScancode2Hid[scanCode & 0x7F];
    158             *pUsage = usage | keyUp;
     164            *pUsage = usage | keyUp | HID_PG_KB_BITS;
    159165            /* Remain in SS_IDLE state. */
    160166        }
     
    162168    case SS_EXT:
    163169        usage = aExtScan2Hid[scanCode & 0x7F];
    164         *pUsage = usage | keyUp;
     170        *pUsage = usage | keyUp | HID_PG_KB_BITS;
    165171        state = SS_IDLE;
    166172        break;
     
    170176         */
    171177        if ((scanCode & 0x7F) == 0x45) {
    172             *pUsage = 0x48;
     178            *pUsage = 0x48 | HID_PG_KB_BITS;
    173179            if (scanCode == 0xC5)
    174180                *pUsage |= keyUp;
  • trunk/src/VBox/Devices/Input/PS2K.cpp

    r76553 r81214  
    9898/** The size of an array needed to store all USB usage codes */
    9999#define VBOX_USB_USAGE_ARRAY_SIZE   (VBOX_USB_MAX_USAGE_CODE + 1)
     100/** USB HID Keyboard Usage Page. */
     101#define USB_HID_KB_PAGE             7
     102/** USB HID Consumer Control Usage Page. */
     103#define USB_HID_CC_PAGE             12
    100104/** @} */
    101105
     
    158162{
    159163    /** Pointer to parent device (keyboard controller). */
    160     R3PTRTYPE(void *)     pParent;
     164    R3PTRTYPE(void *)   pParent;
    161165    /** Set if keyboard is enabled ('scans' for input). */
    162166    bool                fScanning;
     
    174178    uint8_t             u8TypematicCfg;
    175179    /** Usage code of current typematic key, if any. */
    176     uint8_t             u8TypematicKey;
     180    uint32_t            u32TypematicKey;
    177181    /** Current typematic repeat state. */
    178182    tmatic_state_t      enmTypematicState;
     
    277281*********************************************************************************************************************************/
    278282#ifdef IN_RING3
    279 /* USB to PS/2 conversion table for regular keys. */
     283/* USB to PS/2 conversion table for regular keys (HID Usage Page 7). */
    280284static const   key_def   aPS2Keys[] = {
    281285    /* 00 */ {NONE, NONE, NONE, KF_NB, T_U }, /* Key N/A: No Event */
     
    459463 */
    460464
    461 /* USB to PS/2 conversion table for modifier keys. */
     465/* USB to PS/2 conversion table for modifier keys (HID Usage Page 7). */
    462466static const   key_def   aPS2ModKeys[] = {
    463467    /* E0 */ {0x1D, 0x14, 0x11,     0, T_B }, /* Key  58: Left Control */
     
    471475};
    472476
     477/* Extended key definition for sparse mapping. */
     478typedef struct {
     479    uint16_t    usageId;
     480    key_def     kdef;
     481} ext_key_def;
     482
     483
     484/* USB to PS/2 conversion table for consumer control keys (HID Usage Page 12). */
     485/* This usage page is very sparse so we'll just search through it. */
     486static const   ext_key_def  aPS2CCKeys[] = {
     487    0x00B5, {0x19, 0x4D, UNKN, KF_E0, T_U }, /* Scan Next Track */
     488    0x00B6, {0x10, 0x15, UNKN, KF_E0, T_U }, /* Scan Previous Track */
     489    0x00B7, {0x24, 0x3B, UNKN, KF_E0, T_U }, /* Stop */
     490    0x00CD, {0x22, 0x34, UNKN, KF_E0, T_U }, /* Play/Pause */
     491    0x00E2, {0x20, 0x23, UNKN, KF_E0, T_U }, /* Mute */
     492    0x00E5, {UNAS, UNAS, UNAS,     0, T_U }, /* Bass Boost */
     493    0x00E7, {UNAS, UNAS, UNAS,     0, T_U }, /* Loudness */
     494    0x00E9, {0x30, 0x32, UNKN, KF_E0, T_U }, /* Volume Up */
     495    0x00EA, {0x2E, 0x21, UNKN, KF_E0, T_U }, /* Volume Down */
     496    0x0152, {UNAS, UNAS, UNAS,     0, T_U }, /* Bass Up */
     497    0x0153, {UNAS, UNAS, UNAS,     0, T_U }, /* Bass Down */
     498    0x0154, {UNAS, UNAS, UNAS,     0, T_U }, /* Treble Up */
     499    0x0155, {UNAS, UNAS, UNAS,     0, T_U }, /* Treble Down */
     500    0x0183, {0x6D, 0x50, UNKN, KF_E0, T_U }, /* Media Select  */
     501    0x018A, {0x6C, 0x48, UNKN, KF_E0, T_U }, /* Mail */
     502    0x0192, {0x21, 0x2B, UNKN, KF_E0, T_U }, /* Calculator */
     503    0x0194, {0x6B, 0x40, UNKN, KF_E0, T_U }, /* My Computer */
     504    0x0221, {0x65, 0x10, UNKN, KF_E0, T_U }, /* WWW Search */
     505    0x0223, {0x32, 0x3A, UNKN, KF_E0, T_U }, /* WWW Home */
     506    0x0224, {0x6A, 0x38, UNKN, KF_E0, T_U }, /* WWW Back */
     507    0x0225, {0x69, 0x30, UNKN, KF_E0, T_U }, /* WWW Forward */
     508    0x0226, {0x68, 0x28, UNKN, KF_E0, T_U }, /* WWW Stop */
     509    0x0227, {0x67, 0x20, UNKN, KF_E0, T_U }, /* WWW Refresh */
     510    0x022A, {0x66, 0x18, UNKN, KF_E0, T_U }, /* WWW Favorites */
     511};
     512
    473513#endif /* IN_RING3 */
    474514
     
    661701static void ps2kStopTypematicRepeat(PPS2K pThis)
    662702{
    663     if (pThis->u8TypematicKey)
    664     {
    665         LogFunc(("Typematic key %02X\n", pThis->u8TypematicKey));
     703    if (pThis->u32TypematicKey)
     704    {
     705        LogFunc(("Typematic key %08X\n", pThis->u32TypematicKey));
    666706        pThis->enmTypematicState = KBD_TMS_IDLE;
    667         pThis->u8TypematicKey = 0;
     707        pThis->u32TypematicKey = 0;
    668708        TMTimerStop(pThis->CTX_SUFF(pKbdTypematicTimer));
    669709    }
     
    866906#ifdef IN_RING3
    867907
    868 static int ps2kProcessKeyEvent(PPS2K pThis, uint8_t u8HidCode, bool fKeyDown)
     908static int ps2kProcessKeyEvent(PPS2K pThis, uint32_t u32HidCode, bool fKeyDown)
    869909{
    870910    key_def const   *pKeyDef;
     
    873913    size_t          cbLeft;
    874914    uint8_t         abScan[2];
    875 
    876     LogFlowFunc(("key %s: 0x%02x (set %d)\n", fKeyDown ? "down" : "up", u8HidCode, pThis->u8ScanSet));
     915    uint8_t         u8HidPage;
     916    uint8_t         u8HidCode;
     917    uint16_t        u16HidUsage;
     918
     919    u8HidPage   = RT_LOBYTE(RT_HIWORD(u32HidCode));
     920    u16HidUsage = RT_LOWORD(u32HidCode);
     921    /* For the keyboard usage page (7) we use a 8-bit code. For other pages we use the full 16-bit ID. */
     922    u8HidCode   = (u8HidPage == USB_HID_KB_PAGE) ? RT_LOBYTE(u32HidCode) : 0;
     923
     924    LogFlowFunc(("key %s: page 0x%02x ID 0x%04x (set %d)\n", fKeyDown ? "down" : "up", u8HidPage, u16HidUsage, pThis->u8ScanSet));
    877925
    878926    /* Find the key definition in somewhat sparse storage. */
    879     pKeyDef = u8HidCode >= HID_MODIFIER_FIRST ? &aPS2ModKeys[u8HidCode - HID_MODIFIER_FIRST] : &aPS2Keys[u8HidCode];
     927    if (u8HidPage == USB_HID_KB_PAGE)
     928        /* For the standard keyboard usage page, thre are just two arrays. */
     929        pKeyDef = u8HidCode >= HID_MODIFIER_FIRST ? &aPS2ModKeys[u8HidCode - HID_MODIFIER_FIRST] : &aPS2Keys[u8HidCode];
     930    else if (u8HidPage == USB_HID_CC_PAGE)
     931    {
     932        /* For the consumer control usage page, we need to search. */
     933        int     i;
     934
     935        pKeyDef = &aPS2Keys[0]; /* Dummy no-event key. */
     936        for (i = 0; i < RT_ELEMENTS(aPS2CCKeys); ++i)
     937        {
     938            if (aPS2CCKeys[i].usageId == u16HidUsage)
     939            {
     940                pKeyDef = &aPS2CCKeys[i].kdef;
     941                break;
     942            }
     943        }
     944    }
     945    else
     946    {
     947        LogFlow(("Unsupported HID usage page, ignoring key.\n"));
     948        return VINF_SUCCESS;
     949    }
    880950
    881951    /* Some keys are not processed at all; early return. */
     
    893963        unsigned    mod_bit = 1 << (u8HidCode - HID_MODIFIER_FIRST);
    894964
     965        Assert((u8HidPage == USB_HID_KB_PAGE));
    895966        Assert((u8HidCode <= HID_MODIFIER_LAST));
    896967        if (fKeyDown)
     
    10601131    }
    10611132
    1062     /* Set up or cancel typematic key repeat. */
    1063     if (fKeyDown)
    1064     {
    1065         if (pThis->u8TypematicKey != u8HidCode)
     1133    /* Set up or cancel typematic key repeat. For keyboard usage page only. */
     1134    if (u8HidPage == USB_HID_KB_PAGE)
     1135    {
     1136        if (fKeyDown)
    10661137        {
    1067             pThis->enmTypematicState = KBD_TMS_DELAY;
    1068             pThis->u8TypematicKey    = u8HidCode;
    1069             TMTimerSetMillies(pThis->CTX_SUFF(pKbdTypematicTimer), pThis->uTypematicDelay);
    1070             Log(("Typematic delay %u ms, key %02X\n", pThis->uTypematicDelay, u8HidCode));
     1138            if (pThis->u32TypematicKey != u32HidCode)
     1139            {
     1140                pThis->enmTypematicState = KBD_TMS_DELAY;
     1141                pThis->u32TypematicKey   = u32HidCode;
     1142                TMTimerSetMillies(pThis->CTX_SUFF(pKbdTypematicTimer), pThis->uTypematicDelay);
     1143                Log(("Typematic delay %u ms, key %08X\n", pThis->uTypematicDelay, u32HidCode));
     1144            }
    10711145        }
    1072     }
    1073     else
    1074     {
    1075         /* "Typematic operation stops when the last key pressed is released, even
    1076          * if other keys are still held down." (IBM PS/2 Tech Ref). The last key pressed
    1077          * is the one that's being repeated.
    1078          */
    1079         if (pThis->u8TypematicKey == u8HidCode)
     1146        else
    10801147        {
    1081             /* This disables the typematic repeat. */
    1082             pThis->u8TypematicKey    = 0;
    1083             pThis->enmTypematicState = KBD_TMS_IDLE;
    1084             /* For good measure, we cancel the timer, too. */
    1085             TMTimerStop(pThis->CTX_SUFF(pKbdTypematicTimer));
    1086             Log(("Typematic action cleared for key %02X\n", u8HidCode));
     1148            /* "Typematic operation stops when the last key pressed is released, even
     1149             * if other keys are still held down." (IBM PS/2 Tech Ref). The last key pressed
     1150             * is the one that's being repeated.
     1151             */
     1152            if (pThis->u32TypematicKey == u32HidCode)
     1153            {
     1154                /* This disables the typematic repeat. */
     1155                pThis->u32TypematicKey   = 0;
     1156                pThis->enmTypematicState = KBD_TMS_IDLE;
     1157                /* For good measure, we cancel the timer, too. */
     1158                TMTimerStop(pThis->CTX_SUFF(pKbdTypematicTimer));
     1159                Log(("Typematic action cleared for key %08X\n", u32HidCode));
     1160            }
    10871161        }
    10881162    }
     
    11341208    RT_NOREF2(pDevIns, pTimer);
    11351209    PPS2K pThis = (PS2K *)pvUser;
    1136     LogFlowFunc(("Typematic state=%d, key %02X\n", pThis->enmTypematicState, pThis->u8TypematicKey));
     1210    LogFlowFunc(("Typematic state=%d, key %08X\n", pThis->enmTypematicState, pThis->u32TypematicKey));
    11371211
    11381212    /* If the current typematic key is zero, the repeat was canceled just when
    11391213     * the timer was about to run. In that case, do nothing.
    11401214     */
    1141     if (pThis->u8TypematicKey)
     1215    if (pThis->u32TypematicKey)
    11421216    {
    11431217        if (pThis->enmTypematicState == KBD_TMS_DELAY)
     
    11461220        if (pThis->enmTypematicState == KBD_TMS_REPEAT)
    11471221        {
    1148             ps2kProcessKeyEvent(pThis, pThis->u8TypematicKey, true /* Key down */ );
     1222            ps2kProcessKeyEvent(pThis, pThis->u32TypematicKey, true /* Key down */ );
    11491223            TMTimerSetMillies(pThis->CTX_SUFF(pKbdTypematicTimer), pThis->uTypematicRepeat);
    11501224        }
     
    11831257        if (pThis->abDepressedKeys[uKey])
    11841258        {
    1185             ps2kProcessKeyEvent(pThis, uKey, false /* key up */);
     1259            ps2kProcessKeyEvent(pThis, RT_MAKE_U32(USB_HID_KB_PAGE, uKey), false /* key up */);
    11861260            pThis->abDepressedKeys[uKey] = 0;
    11871261        }
     
    12141288                    pThis->keyQ.cUsed, pThis->keyQ.cSize);
    12151289    if (pThis->enmTypematicState != KBD_TMS_IDLE)
    1216         pHlp->pfnPrintf(pHlp, "Active typematic key %02X (%s)\n", pThis->u8TypematicKey,
     1290        pHlp->pfnPrintf(pHlp, "Active typematic key %08X (%s)\n", pThis->u32TypematicKey,
    12171291                        pThis->enmTypematicState == KBD_TMS_DELAY ? "delay" : "repeat");
    12181292}
     
    12441318static int ps2kPutEventWorker(PPS2K pThis, uint32_t u32Usage)
    12451319{
    1246     uint8_t         u8HidCode;
     1320    uint32_t        u32HidCode;
     1321    uint8_t         u8KeyCode;
     1322    uint8_t         u8HidPage;
    12471323    bool            fKeyDown;
    12481324    bool            fHaveEvent = true;
    12491325    int             rc = VINF_SUCCESS;
    12501326
    1251     /* Extract the usage code and ensure it's valid. */
    1252     fKeyDown = !(u32Usage & 0x80000000);
    1253     u8HidCode = u32Usage & 0xFF;
    1254     AssertReturn(u8HidCode <= VBOX_USB_MAX_USAGE_CODE, VERR_INTERNAL_ERROR);
     1327    /* Extract the usage page and ID and ensure it's valid. */
     1328    fKeyDown   = !(u32Usage & 0x80000000);
     1329    u32HidCode = u32Usage & 0xFFFFFF;
     1330    u8HidPage  = RT_LOBYTE(RT_HIWORD(u32Usage));
     1331    u8KeyCode  = RT_LOBYTE(u32Usage);
     1332    if (u8HidPage == USB_HID_KB_PAGE)
     1333        AssertReturn(u8KeyCode <= VBOX_USB_MAX_USAGE_CODE, VERR_INTERNAL_ERROR);
     1334    else
     1335        AssertReturn(u8HidPage == USB_HID_CC_PAGE, VERR_INTERNAL_ERROR);
    12551336
    12561337    if (fKeyDown)
     
    12581339        /* Due to host key repeat, we can get key events for keys which are
    12591340         * already depressed. We need to ignore those. */
    1260         if (pThis->abDepressedKeys[u8HidCode])
     1341        if (pThis->abDepressedKeys[u8KeyCode])
    12611342            fHaveEvent = false;
    1262         pThis->abDepressedKeys[u8HidCode] = 1;
     1343        pThis->abDepressedKeys[u8KeyCode] = 1;
    12631344    }
    12641345    else
     
    12671348         * That is unlikely to happen and should not cause trouble.
    12681349         */
    1269         pThis->abDepressedKeys[u8HidCode] = 0;
     1350        pThis->abDepressedKeys[u8KeyCode] = 0;
    12701351    }
    12711352
     
    12761357        AssertReleaseRC(rc);
    12771358
    1278         rc = ps2kProcessKeyEvent(pThis, u8HidCode, fKeyDown);
     1359        rc = ps2kProcessKeyEvent(pThis, u32HidCode, fKeyDown);
    12791360
    12801361        PDMCritSectLeave(pThis->pCritSectR3);
     
    13711452    SSMR3PutU8(pSSM, pThis->u8LEDs);
    13721453    SSMR3PutU8(pSSM, pThis->u8TypematicCfg);
    1373     SSMR3PutU8(pSSM, pThis->u8TypematicKey);
     1454    SSMR3PutU8(pSSM, (uint8_t)pThis->u32TypematicKey);
    13741455    SSMR3PutU8(pSSM, pThis->u8Modifiers);
    13751456    SSMR3PutU8(pSSM, pThis->u8ScanSet);
     
    14191500    SSMR3GetU8(pSSM, &pThis->u8LEDs);
    14201501    SSMR3GetU8(pSSM, &pThis->u8TypematicCfg);
    1421     SSMR3GetU8(pSSM, &pThis->u8TypematicKey);
     1502    SSMR3GetU8(pSSM, &u8);
     1503    /* Reconstruct the 32-bit code from the 8-bit value in saved state. */
     1504    pThis->u32TypematicKey = u8 ? RT_MAKE_U32(USB_HID_KB_PAGE, u8) : 0;
    14221505    SSMR3GetU8(pSSM, &pThis->u8Modifiers);
    14231506    SSMR3GetU8(pSSM, &pThis->u8ScanSet);
     
    14891572    pThis->u8CurrCmd         = 0;
    14901573    pThis->u8Modifiers       = 0;
    1491     pThis->u8TypematicKey    = 0;
     1574    pThis->u32TypematicKey   = 0;
    14921575    pThis->enmTypematicState = KBD_TMS_IDLE;
    14931576
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