Search code examples
device-driveraccelerometerdriverskmdf

Accessing a Toshiba Laptop Accelerometer Device Driver


I have a new Toshiba Satellite Pro S300 laptop (running Windows XP) which sports a 3D accelerometer for HDD protection. I'd like to tap into the data sent by this sensor. Older Toshiba laptop/Tablets had a DLL that could be accessed to extract the acceleration data. Unfortunately, the S300 does not seem to have this DLL (The DLL hack has been documented elsewhere, e.g. here).

The HDD Protection app (which has a cute 3D visualization of a rotating HDD that rotates in synch with the laptop's position and motion) doesn't seem to depend on any "non-standard"/custom DLLs (according to DependencyWalker). It seems that the data is accessed either through a service and/or through a .sys device driver. I think I managed to identify the relevant files, but I have no idea how to find, name, access, load (or "disassemble") the relevant functions.

How can I discover and use the accelerometer data?


Solution

  • I've been able to get it to work with this code (On a Toshiba Satellite Pro S300L-120, Windows 7):

    void ReadAccel(float a[3])
    {
        HANDLE h = CreateFile(L"\\\\.\\TVALZ", GENERIC_ALL, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
        struct dummy
        {
            unsigned long magic1; /* = 0x0000FE00 */
            unsigned long magic2; /* = 0x000000A6 */
            unsigned short x, y;
            unsigned long unknown, z;
            unsigned long direction;
        } d;
        memset(&d, 0, sizeof(d));
        unsigned long retlen;
        d.magic1 = 0x0000FE00;
        d.magic2 = 0xA6;
        d.direction = 0;
    
        DeviceIoControl(h, 0x222880, &d, sizeof(d), &d, sizeof(d), &retlen, NULL);
        d.magic1 = 0x0000FE00;
        d.direction = 1;
        Sleep(20); /* Doesn't seem to work without the wait */
        DeviceIoControl(h, 0x222880, &d, sizeof(d), &d, sizeof(d), &retlen, NULL);
        signed short x = (d.x & 0x7FFF) * (d.x & 0x8000?-1:1);
        signed short y = (d.y & 0x7FFF) * (d.y & 0x8000?-1:1);
        signed short z = (d.z & 0x7FFF) * (d.z & 0x8000?-1:1);
        a[2] = -(float)z * 9.8 / 205; /* this is just an estimate to go to SI units */
        a[1] = (float)y * 9.8 / 205;
        a[0] = (float)x * 9.8 / 205;
        CloseHandle(h);
    }
    

    It might not be very pretty yet, but we can start playing :)

    I used the TPCHCTL.dll that comes with the Toshiba Hardware monitor to figure this out, btw.