[RFC 1/11] Linux FF: Joystick control panel program

Elias Vanderstuyft elias.vds at gmail.com
Tue Mar 4 13:19:16 CST 2014


a)  When unloading conditional effects in joy.cpl, the program crashes:
        When unloading the conditional effect array entries,
        Wine tries to access an invalid (high) address because
        dieffect.lpvTypeSpecificParams was not set at the time the
effect was created.
        So declare a valid 'standard' (maxed out) conditional effect.
        For other unknown effects:
            - The same can happen when CustomForce effects are available,
                but because Wine's FF dinput->linux translation does
not support this yet,
                we simply print a FIXME to indicate a possible cause
if a crash would happen.
            - The same for other (unsupported) effects (this is
probably not safe?),
                but then we print a WARN.
            => This is probably not safe, but these effects won't be unloaded,
                because they will never be allowed to be created:
                I tested this by using a dummy FF device that
advertised to support CustomForce,
                but because JoystickAImpl_EnumEffects() does not
handle CustomForce,
                no CustomForce entry was generated in the joy.cpl application,
                and there was no crash at exit.

    Solution: After the code of joy.cpl/main.c:766 :
        else if (IsEqualGUID(&pdei->guid, &GUID_Sine) ||
                IsEqualGUID(&pdei->guid, &GUID_Square) ||
                IsEqualGUID(&pdei->guid, &GUID_Triangle) ||
                IsEqualGUID(&pdei->guid, &GUID_SawtoothUp) ||
                IsEqualGUID(&pdei->guid, &GUID_SawtoothDown))
        {
            DIPERIODIC pforce;

            pforce.dwMagnitude = DI_FFNOMINALMAX;
            pforce.lOffset = 0;
            pforce.dwPhase = 0;
            pforce.dwPeriod = FF_PERIOD_TIME;

            dieffect.cbTypeSpecificParams = sizeof(pforce);
            dieffect.lpvTypeSpecificParams = &pforce;
            dieffect.dwFlags |= DIEP_TYPESPECIFICPARAMS;
        }
    add the following code :
        else if (IsEqualGUID(&pdei->guid, &GUID_Spring) ||
                IsEqualGUID(&pdei->guid, &GUID_Damper) ||
                IsEqualGUID(&pdei->guid, &GUID_Inertia) ||
                IsEqualGUID(&pdei->guid, &GUID_Friction))
        {
            DICONDITION cxyforce[2];

            int i;
            for (i = 0; i < 2; ++i) {
                cxyforce[i].lOffset = 0;
                cxyforce[i].lPositiveCoefficient = DI_FFNOMINALMAX;
                cxyforce[i].lNegativeCoefficient = DI_FFNOMINALMAX;
                cxyforce[i].dwPositiveSaturation = DI_FFNOMINALMAX;
                cxyforce[i].dwNegativeSaturation = DI_FFNOMINALMAX;
                cxyforce[i].lDeadBand = 0;
            }

            dieffect.cbTypeSpecificParams = sizeof(cxyforce);
            dieffect.lpvTypeSpecificParams = cxyforce;
            dieffect.dwFlags |= DIEP_TYPESPECIFICPARAMS;
        }
        else if (IsEqualGUID(&pdei->guid, &GUID_CustomForce))
        {
            FIXME("Unhandled type specific parameters of CustomForce
effect, this may lead to memory errors later on.\n");
        }
        else
            WARN("Possibly unhandled type specific parameters of
effect with guid %x.\n", pdei->guid);


b)  Weirdly, I had to add these commands that evaluates the DIEFFECT
pointers at the end of each if-case,
    otherwise the pointers seemed to point to other address or data on
that address was getting overwritten:
        TRACE("&rforce=0x%x\n", &rforce);
        TRACE("&cforce=0x%x\n", &cforce);
        TRACE("&pforce=0x%x\n", &pforce);
        TRACE("&cxyforce[0]=0x%x; &cxyforce[1]=0x%x\n",
&(cxyforce[0]), &(cxyforce[1]));


Elias
-------------- next part --------------
/////////////////////////////    Joystick control panel program    /////////////////////////////

a)  When unloading conditional effects in joy.cpl, the program crashes:
        When unloading the conditional effect array entries,
        Wine tries to access an invalid (high) address because
        dieffect.lpvTypeSpecificParams was not set at the time the effect was created.
        So declare a valid 'standard' (maxed out) conditional effect.
        For other unknown effects:
            - The same can happen when CustomForce effects are available,
                but because Wine's FF dinput->linux translation does not support this yet,
                we simply print a FIXME to indicate a possible cause if a crash would happen.
            - The same for other (unsupported) effects (this is probably not safe?),
                but then we print a WARN.
            => This is probably not safe, but these effects won't be unloaded,
                because they will never be allowed to be created:
                I tested this by using a dummy FF device that advertised to support CustomForce,
                but because JoystickAImpl_EnumEffects() does not handle CustomForce,
                no CustomForce entry was generated in the joy.cpl application,
                and there was no crash at exit.
    
    Solution: After the code of joy.cpl/main.c:766 :
        else if (IsEqualGUID(&pdei->guid, &GUID_Sine) ||
                IsEqualGUID(&pdei->guid, &GUID_Square) ||
                IsEqualGUID(&pdei->guid, &GUID_Triangle) ||
                IsEqualGUID(&pdei->guid, &GUID_SawtoothUp) ||
                IsEqualGUID(&pdei->guid, &GUID_SawtoothDown))
        {
            DIPERIODIC pforce;

            pforce.dwMagnitude = DI_FFNOMINALMAX;
            pforce.lOffset = 0;
            pforce.dwPhase = 0;
            pforce.dwPeriod = FF_PERIOD_TIME;

            dieffect.cbTypeSpecificParams = sizeof(pforce);
            dieffect.lpvTypeSpecificParams = &pforce;
            dieffect.dwFlags |= DIEP_TYPESPECIFICPARAMS;
        }
    add the following code :
        else if (IsEqualGUID(&pdei->guid, &GUID_Spring) ||
                IsEqualGUID(&pdei->guid, &GUID_Damper) ||
                IsEqualGUID(&pdei->guid, &GUID_Inertia) ||
                IsEqualGUID(&pdei->guid, &GUID_Friction))
        {
            DICONDITION cxyforce[2];

            int i;
            for (i = 0; i < 2; ++i) {
                cxyforce[i].lOffset = 0;
                cxyforce[i].lPositiveCoefficient = DI_FFNOMINALMAX;
                cxyforce[i].lNegativeCoefficient = DI_FFNOMINALMAX;
                cxyforce[i].dwPositiveSaturation = DI_FFNOMINALMAX;
                cxyforce[i].dwNegativeSaturation = DI_FFNOMINALMAX;
                cxyforce[i].lDeadBand = 0;
            }

            dieffect.cbTypeSpecificParams = sizeof(cxyforce);
            dieffect.lpvTypeSpecificParams = cxyforce;
            dieffect.dwFlags |= DIEP_TYPESPECIFICPARAMS;
        }
        else if (IsEqualGUID(&pdei->guid, &GUID_CustomForce))
        {
            FIXME("Unhandled type specific parameters of CustomForce effect, this may lead to memory errors later on.\n");
        }
        else
            WARN("Possibly unhandled type specific parameters of effect with guid %x.\n", pdei->guid);


b)  Weirdly, I had to add these commands that evaluates the DIEFFECT pointers at the end of each if-case,
    otherwise the pointers seemed to point to other address or data on that address was getting overwritten:
        TRACE("&rforce=0x%x\n", &rforce);
        TRACE("&cforce=0x%x\n", &cforce);
        TRACE("&pforce=0x%x\n", &pforce);
        TRACE("&cxyforce[0]=0x%x; &cxyforce[1]=0x%x\n", &(cxyforce[0]), &(cxyforce[1]));


More information about the wine-devel mailing list