VirtualBox

Changeset 88504 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Apr 14, 2021 12:24:41 PM (4 years ago)
Author:
vboxsync
Message:

DevHda: Changed codecLookup to binary search. Added a couple of more node ID validations. bugref:9890

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DevHdaCodec.cpp

    r88503 r88504  
    151151{
    152152    RT_NOREF(pszArgs);
    153     for (uint8_t i = 1; i < pThis->cTotalNodes; i++)
     153    uint8_t const cTotalNodes = RT_MIN(pThis->cTotalNodes, RT_ELEMENTS(pThis->aNodes));
     154    for (uint8_t i = 1; i < cTotalNodes; i++)
    154155    {
    155156        PCODECNODE pNode = &pThis->aNodes[i];
     
    754755    pThis->fInReset = true;
    755756
    756     for (uint8_t i = 0; i < pThis->cTotalNodes; i++)
     757    uint8_t const cTotalNodes = (uint8_t)RT_MIN(pThis->cTotalNodes, RT_ELEMENTS(pThis->aNodes));
     758    for (uint8_t i = 0; i < cTotalNodes; i++)
    757759        stac9220NodeReset(pThis, i, &pThis->aNodes[i]);
    758760
     
    792794#undef STAC9220WIDGET
    793795
     796    AssertCompile(STAC9221_NUM_NODES <= RT_ELEMENTS(pThis->aNodes));
    794797    pThis->cTotalNodes = STAC9221_NUM_NODES;
    795     Assert(pThis->cTotalNodes <= CODEC_NODES_MAX);
    796798
    797799    pThis->u8AdcVolsLineIn = STAC9220_NID_AMP_ADC0;
     
    805807     *       initialize the node default configuration values then!
    806808     */
    807     for (uint8_t i = 0; i < pThis->cTotalNodes; i++)
     809    for (uint8_t i = 0; i < STAC9221_NUM_NODES; i++)
    808810        stac9220NodeReset(pThis, i, &pThis->aNodes[i]);
    809811
     
    813815
    814816    /* Common AFG node initializers. */
    815     pThis->aNodes[STAC9220_NID_AFG].afg.node.au32F00_param[0x4] = CODEC_MAKE_F00_04(0x2, pThis->cTotalNodes - 2);
     817    pThis->aNodes[STAC9220_NID_AFG].afg.node.au32F00_param[0x4] = CODEC_MAKE_F00_04(0x2, STAC9221_NUM_NODES - 2);
    816818    pThis->aNodes[STAC9220_NID_AFG].afg.node.au32F00_param[0x5] = CODEC_MAKE_F00_05(1, CODEC_F00_05_AFG);
    817819    pThis->aNodes[STAC9220_NID_AFG].afg.node.au32F00_param[0xA] = CODEC_F00_0A_44_1KHZ | CODEC_F00_0A_16_BIT;
     
    12991301    RT_NOREF(pThisCC);
    13001302    Assert(CODEC_CAD(cmd) == pThis->id);
    1301     Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
    1302     if (CODEC_NID(cmd) >= pThis->cTotalNodes)
     1303    uint8_t const cTotalNodes = (uint8_t)RT_MIN(pThis->cTotalNodes, RT_ELEMENTS(pThis->aNodes));
     1304    Assert(CODEC_NID(cmd) < cTotalNodes);
     1305    if (CODEC_NID(cmd) >= cTotalNodes)
    13031306    {
    13041307        LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
     1308        *pResp = 0;
    13051309        return VINF_SUCCESS;
    13061310    }
     
    13151319{
    13161320    Assert(CODEC_CAD(cmd) == pThis->id);
    1317     Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
    1318     if (CODEC_NID(cmd) >= pThis->cTotalNodes)
     1321    uint8_t const cTotalNodes = (uint8_t)RT_MIN(pThis->cTotalNodes, RT_ELEMENTS(pThis->aNodes));
     1322    Assert(CODEC_NID(cmd) < cTotalNodes);
     1323    if (CODEC_NID(cmd) >= cTotalNodes)
    13191324    {
    13201325        LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
     
    15201525    RT_NOREF(pThisCC);
    15211526    Assert(CODEC_CAD(cmd) == pThis->id);
    1522     Assert(CODEC_NID(cmd) < pThis->cTotalNodes);
    1523     if (CODEC_NID(cmd) >= pThis->cTotalNodes)
    1524     {
     1527    uint8_t const cTotalNodes = (uint8_t)RT_MIN(pThis->cTotalNodes, RT_ELEMENTS(pThis->aNodes));
     1528    Assert(CODEC_NID(cmd) < cTotalNodes);
     1529    if (CODEC_NID(cmd) >= cTotalNodes)
     1530    {
     1531        *pResp = 0;
    15251532        LogFlowFunc(("invalid node address %d\n", CODEC_NID(cmd)));
    15261533        return VINF_SUCCESS;
     
    20442051 * HDA codec verb descriptors.
    20452052 *
    2046  * @todo Any reason not to use binary search here?
    2047  *      bird: because you'd need to sort the entries first...
     2053 * @note This must be ordered by uVerb so we can do a binary lookup.
    20482054 */
    20492055static const CODECVERB g_aCodecVerbs[] =
     
    20512057    /* Verb        Verb mask            Callback                                   Name
    20522058       ---------- --------------------- ------------------------------------------------------------------- */
    2053     { 0x000F0000, CODEC_VERB_8BIT_CMD , vrbProcGetParameter                      , "GetParameter          " },
    2054     { 0x000F0100, CODEC_VERB_8BIT_CMD , vrbProcGetConSelectCtrl                  , "GetConSelectCtrl      " },
     2059    { 0x00020000, CODEC_VERB_16BIT_CMD, vrbProcSetConverterFormat                , "SetConverterFormat    " },
     2060    { 0x00030000, CODEC_VERB_16BIT_CMD, CTX_EXPR(vrbProcR3SetAmplifier,NULL,NULL), "SetAmplifier          " },
    20552061    { 0x00070100, CODEC_VERB_8BIT_CMD , vrbProcSetConSelectCtrl                  , "SetConSelectCtrl      " },
    2056     { 0x000F0600, CODEC_VERB_8BIT_CMD , vrbProcGetStreamId                       , "GetStreamId           " },
     2062    { 0x00070300, CODEC_VERB_8BIT_CMD , vrbProcSetProcessingState                , "SetProcessingState    " },
     2063    { 0x00070400, CODEC_VERB_8BIT_CMD , vrbProcSetSDISelect                      , "SetSDISelect          " },
     2064    { 0x00070500, CODEC_VERB_8BIT_CMD , vrbProcSetPowerState                     , "SetPowerState         " },
    20572065    { 0x00070600, CODEC_VERB_8BIT_CMD , CTX_EXPR(vrbProcR3SetStreamId,NULL,NULL) , "SetStreamId           " },
    2058     { 0x000F0700, CODEC_VERB_8BIT_CMD , vrbProcGetPinCtrl                        , "GetPinCtrl            " },
    20592066    { 0x00070700, CODEC_VERB_8BIT_CMD , vrbProcSetPinCtrl                        , "SetPinCtrl            " },
    2060     { 0x000F0800, CODEC_VERB_8BIT_CMD , vrbProcGetUnsolicitedEnabled             , "GetUnsolicitedEnabled " },
    20612067    { 0x00070800, CODEC_VERB_8BIT_CMD , vrbProcSetUnsolicitedEnabled             , "SetUnsolicitedEnabled " },
    2062     { 0x000F0900, CODEC_VERB_8BIT_CMD , vrbProcGetPinSense                       , "GetPinSense           " },
    20632068    { 0x00070900, CODEC_VERB_8BIT_CMD , vrbProcSetPinSense                       , "SetPinSense           " },
    2064     { 0x000F0200, CODEC_VERB_8BIT_CMD , vrbProcGetConnectionListEntry            , "GetConnectionListEntry" },
    2065     { 0x000F0300, CODEC_VERB_8BIT_CMD , vrbProcGetProcessingState                , "GetProcessingState    " },
    2066     { 0x00070300, CODEC_VERB_8BIT_CMD , vrbProcSetProcessingState                , "SetProcessingState    " },
    2067     { 0x000F0D00, CODEC_VERB_8BIT_CMD , vrbProcGetDigitalConverter               , "GetDigitalConverter   " },
     2069    { 0x00070C00, CODEC_VERB_8BIT_CMD , vrbProcSetEAPD_BTLEnabled                , "SetEAPD_BTLEnabled    " },
    20682070    { 0x00070D00, CODEC_VERB_8BIT_CMD , vrbProcSetDigitalConverter1              , "SetDigitalConverter1  " },
    20692071    { 0x00070E00, CODEC_VERB_8BIT_CMD , vrbProcSetDigitalConverter2              , "SetDigitalConverter2  " },
    2070     { 0x000F2000, CODEC_VERB_8BIT_CMD , vrbProcGetSubId                          , "GetSubId              " },
     2072    { 0x00070F00, CODEC_VERB_8BIT_CMD , vrbProcSetVolumeKnobCtrl                 , "SetVolumeKnobCtrl     " },
     2073    { 0x00071500, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOData                       , "SetGPIOData           " },
     2074    { 0x00071600, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOEnableMask                 , "SetGPIOEnableMask     " },
     2075    { 0x00071700, CODEC_VERB_8BIT_CMD , vrbProcSetGPIODirection                  , "SetGPIODirection      " },
     2076    { 0x00071C00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig0                        , "SetConfig0            " },
     2077    { 0x00071D00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig1                        , "SetConfig1            " },
     2078    { 0x00071E00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig2                        , "SetConfig2            " },
     2079    { 0x00071F00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig3                        , "SetConfig3            " },
    20712080    { 0x00072000, CODEC_VERB_8BIT_CMD , vrbProcSetSubId0                         , "SetSubId0             " },
    20722081    { 0x00072100, CODEC_VERB_8BIT_CMD , vrbProcSetSubId1                         , "SetSubId1             " },
     
    20742083    { 0x00072300, CODEC_VERB_8BIT_CMD , vrbProcSetSubId3                         , "SetSubId3             " },
    20752084    { 0x0007FF00, CODEC_VERB_8BIT_CMD , vrbProcReset                             , "Reset                 " },
     2085    { 0x000A0000, CODEC_VERB_16BIT_CMD, vrbProcGetConverterFormat                , "GetConverterFormat    " },
     2086    { 0x000B0000, CODEC_VERB_16BIT_CMD, vrbProcGetAmplifier                      , "GetAmplifier          " },
     2087    { 0x000F0000, CODEC_VERB_8BIT_CMD , vrbProcGetParameter                      , "GetParameter          " },
     2088    { 0x000F0100, CODEC_VERB_8BIT_CMD , vrbProcGetConSelectCtrl                  , "GetConSelectCtrl      " },
     2089    { 0x000F0200, CODEC_VERB_8BIT_CMD , vrbProcGetConnectionListEntry            , "GetConnectionListEntry" },
     2090    { 0x000F0300, CODEC_VERB_8BIT_CMD , vrbProcGetProcessingState                , "GetProcessingState    " },
     2091    { 0x000F0400, CODEC_VERB_8BIT_CMD , vrbProcGetSDISelect                      , "GetSDISelect          " },
    20762092    { 0x000F0500, CODEC_VERB_8BIT_CMD , vrbProcGetPowerState                     , "GetPowerState         " },
    2077     { 0x00070500, CODEC_VERB_8BIT_CMD , vrbProcSetPowerState                     , "SetPowerState         " },
     2093    { 0x000F0600, CODEC_VERB_8BIT_CMD , vrbProcGetStreamId                       , "GetStreamId           " },
     2094    { 0x000F0700, CODEC_VERB_8BIT_CMD , vrbProcGetPinCtrl                        , "GetPinCtrl            " },
     2095    { 0x000F0800, CODEC_VERB_8BIT_CMD , vrbProcGetUnsolicitedEnabled             , "GetUnsolicitedEnabled " },
     2096    { 0x000F0900, CODEC_VERB_8BIT_CMD , vrbProcGetPinSense                       , "GetPinSense           " },
    20782097    { 0x000F0C00, CODEC_VERB_8BIT_CMD , vrbProcGetEAPD_BTLEnabled                , "GetEAPD_BTLEnabled    " },
    2079     { 0x00070C00, CODEC_VERB_8BIT_CMD , vrbProcSetEAPD_BTLEnabled                , "SetEAPD_BTLEnabled    " },
     2098    { 0x000F0D00, CODEC_VERB_8BIT_CMD , vrbProcGetDigitalConverter               , "GetDigitalConverter   " },
    20802099    { 0x000F0F00, CODEC_VERB_8BIT_CMD , vrbProcGetVolumeKnobCtrl                 , "GetVolumeKnobCtrl     " },
    2081     { 0x00070F00, CODEC_VERB_8BIT_CMD , vrbProcSetVolumeKnobCtrl                 , "SetVolumeKnobCtrl     " },
    20822100    { 0x000F1500, CODEC_VERB_8BIT_CMD , vrbProcGetGPIOData                       , "GetGPIOData           " },
    2083     { 0x00071500, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOData                       , "SetGPIOData           " },
    20842101    { 0x000F1600, CODEC_VERB_8BIT_CMD , vrbProcGetGPIOEnableMask                 , "GetGPIOEnableMask     " },
    2085     { 0x00071600, CODEC_VERB_8BIT_CMD , vrbProcSetGPIOEnableMask                 , "SetGPIOEnableMask     " },
    20862102    { 0x000F1700, CODEC_VERB_8BIT_CMD , vrbProcGetGPIODirection                  , "GetGPIODirection      " },
    2087     { 0x00071700, CODEC_VERB_8BIT_CMD , vrbProcSetGPIODirection                  , "SetGPIODirection      " },
    20882103    { 0x000F1C00, CODEC_VERB_8BIT_CMD , vrbProcGetConfig                         , "GetConfig             " },
    2089     { 0x00071C00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig0                        , "SetConfig0            " },
    2090     { 0x00071D00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig1                        , "SetConfig1            " },
    2091     { 0x00071E00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig2                        , "SetConfig2            " },
    2092     { 0x00071F00, CODEC_VERB_8BIT_CMD , vrbProcSetConfig3                        , "SetConfig3            " },
    2093     { 0x000A0000, CODEC_VERB_16BIT_CMD, vrbProcGetConverterFormat                , "GetConverterFormat    " },
    2094     { 0x00020000, CODEC_VERB_16BIT_CMD, vrbProcSetConverterFormat                , "SetConverterFormat    " },
    2095     { 0x000B0000, CODEC_VERB_16BIT_CMD, vrbProcGetAmplifier                      , "GetAmplifier          " },
    2096     { 0x00030000, CODEC_VERB_16BIT_CMD, CTX_EXPR(vrbProcR3SetAmplifier,NULL,NULL), "SetAmplifier          " },
    2097     { 0x000F0400, CODEC_VERB_8BIT_CMD , vrbProcGetSDISelect                      , "GetSDISelect          " },
    2098     { 0x00070400, CODEC_VERB_8BIT_CMD , vrbProcSetSDISelect                      , "SetSDISelect          " },
     2104    { 0x000F2000, CODEC_VERB_8BIT_CMD , vrbProcGetSubId                          , "GetSubId              " },
    20992105    /** @todo Implement 0x7e7: IDT Set GPIO (STAC922x only). */
    21002106};
     
    23552361                    ("Unknown codec address 0x%x\n", CODEC_CAD(uCmd)),
    23562362                    VERR_INVALID_PARAMETER);
    2357     AssertMsgReturn(   CODEC_VERBDATA(uCmd) != 0
    2358                     && CODEC_NID(uCmd) < pThis->cTotalNodes,
    2359                     ("[NID0x%02x] Unknown / invalid node or data (0x%x)\n", CODEC_NID(uCmd), CODEC_VERBDATA(uCmd)),
     2363    uint32_t const uCmdData = CODEC_VERBDATA(uCmd);
     2364    AssertMsgReturn(   uCmdData != 0
     2365                    && CODEC_NID(uCmd) < RT_MIN(pThis->cTotalNodes, RT_ELEMENTS(pThis->aNodes)),
     2366                    ("[NID0x%02x] Unknown / invalid node or data (0x%x)\n", CODEC_NID(uCmd), uCmdData),
    23602367                    VERR_INVALID_PARAMETER);
    23612368    STAM_COUNTER_INC(&pThis->CTX_SUFF(StatLookups));
    23622369
    23632370    /*
    2364      * Lookup the verb.
     2371     * Do a binary lookup of the verb.
    23652372     * Note! if we want other verb tables, add a table selector before the loop.
    23662373     */
    2367     for (size_t i = 0; i < RT_ELEMENTS(g_aCodecVerbs); i++)
    2368     {
    2369         if ((CODEC_VERBDATA(uCmd) & g_aCodecVerbs[i].fMask) == g_aCodecVerbs[i].uVerb)
    2370         {
     2374    size_t iFirst = 0;
     2375    size_t iEnd   = RT_ELEMENTS(g_aCodecVerbs);
     2376    for (;;)
     2377    {
     2378        size_t const   iCur  = iFirst + (iEnd - iFirst) / 2;
     2379        uint32_t const uVerb = g_aCodecVerbs[iCur].uVerb;
     2380        if (uCmdData < uVerb)
     2381        {
     2382            if (iCur > iFirst)
     2383                iEnd = iCur;
     2384            else
     2385                break;
     2386        }
     2387        else if ((uCmdData & g_aCodecVerbs[iCur].fMask) != uVerb)
     2388        {
     2389            if (iCur + 1 < iEnd)
     2390                iFirst = iCur + 1;
     2391            else
     2392                break;
     2393        }
     2394        else
     2395        {
     2396            /*
     2397             * Found it!  Run the callback and return.
     2398             */
    23712399#ifndef IN_RING3
    2372             if (!g_aCodecVerbs[i].pfn)
     2400            if (!g_aCodecVerbs[iCur].pfn)
    23732401            {
    23742402                Log3Func(("[NID0x%02x] (0x%x) %s: 0x%x -> VERR_INVALID_CONTEXT\n", /* -> ring-3 */
    2375                           CODEC_NID(uCmd), g_aCodecVerbs[i].uVerb, g_aCodecVerbs[i].pszName, CODEC_VERB_PAYLOAD8(uCmd)));
     2403                          CODEC_NID(uCmd), g_aCodecVerbs[iCur].uVerb, g_aCodecVerbs[iCur].pszName, CODEC_VERB_PAYLOAD8(uCmd)));
    23762404                return VERR_INVALID_CONTEXT;
    23772405            }
    23782406#endif
    2379             AssertPtrReturn(g_aCodecVerbs[i].pfn, VERR_INTERNAL_ERROR_5); /* Paranoia^2. */
    2380 
    2381             int rc = g_aCodecVerbs[i].pfn(pThis, pThisCC, uCmd, puResp);
     2407            AssertPtrReturn(g_aCodecVerbs[iCur].pfn, VERR_INTERNAL_ERROR_5); /* Paranoia^2. */
     2408
     2409            int rc = g_aCodecVerbs[iCur].pfn(pThis, pThisCC, uCmd, puResp);
    23822410            AssertRC(rc);
    23832411            Log3Func(("[NID0x%02x] (0x%x) %s: 0x%x -> 0x%x\n",
    2384                       CODEC_NID(uCmd), g_aCodecVerbs[i].uVerb, g_aCodecVerbs[i].pszName, CODEC_VERB_PAYLOAD8(uCmd), *puResp));
     2412                      CODEC_NID(uCmd), g_aCodecVerbs[iCur].uVerb, g_aCodecVerbs[iCur].pszName, CODEC_VERB_PAYLOAD8(uCmd), *puResp));
    23852413            return rc;
    23862414        }
    23872415    }
    23882416
     2417#ifdef VBOX_STRICT
     2418    for (size_t i = 0; i < RT_ELEMENTS(g_aCodecVerbs); i++)
     2419    {
     2420        AssertMsg(i == 0 || g_aCodecVerbs[i - 1].uVerb < g_aCodecVerbs[i].uVerb,
     2421                  ("i=%#x uVerb[-1]=%#x uVerb=%#x - buggy table!\n", i, g_aCodecVerbs[i - 1].uVerb, g_aCodecVerbs[i].uVerb));
     2422        AssertMsg((uCmdData & g_aCodecVerbs[i].fMask) != g_aCodecVerbs[i].uVerb,
     2423                  ("i=%#x uVerb=%#x uCmd=%#x - buggy binary search or table!\n", i, g_aCodecVerbs[i].uVerb, uCmd));
     2424    }
     2425#endif
    23892426    LogFunc(("[NID0x%02x] Callback for %x not found\n", CODEC_NID(uCmd), CODEC_VERBDATA(uCmd)));
    23902427    return VERR_NOT_FOUND;
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