different minds about different platforms

a blog of Dirk Eisenberg (>)

  Home  |   Contact  |   Syndication    |   Login
  38 Posts | 4 Stories | 7 Comments | 18 Trackbacks

News

Ich hoffe das jeder Besucher in diesem Blog das ein oder andere interessante Thema findet. Als Autor der Beiträge freue ich mich besonders über Feedback in Form von Kommentaren oder auch persönlicher als E-Mail. Dankbar nehme ich Anregungen und Korrekturen von fehlerhaften Inhalten entgegen.

Article Categories

Archives

Post Categories

Image Galleries

Blogs

Links

IBM(jetzt ja nicht mehr) verbaut in seinen Thinkad-Laptops Vibrationssensoren. Darüber kann die räumliche Lage des Laptops als auch der Grad der Erschütterung gemessen werden. Diese Funktion wird genutzt um die Festplatten bei zu großer Erschütterung abzuschalten und damit vor der Zerstörung zu schützen. Prinzipiell dokumentiert IBM das System als solches in folgendem Dokument: http://pusa.uv.es/~ulisses/thinkpad/aps2mst.pdf . Meine erste Vermutung das es sich um einen Kernel-Mode-Treiber handeln muss der über einer User-Mode-Schnittstelle verwaltet wird, bestätigte sich. Leider gibt es von IBM keiner Header-Informationen um die Schnittstelle in Form der sensor.dll selbst zu verwenden. Will man also an die Vibrationsinformationen auf seinem Thinkpad kommen und in der eigenen Software verwenden, muss man sich was anderes überlegen. Es ist jedoch möglich mit geringem Wissen über das WDM-Device-Driver-Konzept und Assembler heraus zu bekommen wie die Kommunikation mit dem Treiber funktioniert

DeviceIoControl:

Microsoft stellt zur Kommunikation mit bestimmten Device-Treibern das API-DeviceIoControl zur Verfügung. Diesem API übergibt man einen IOControlCode sowie einen Input und Output buffer zur Kommunikation mit dem Treiber-Device. Das Handling des Buffers wird durch das Treiber-System übernommen. Nach erfolgreicher Abfrage steht uns ein Stück Speicher mit Informationen zu Verfügung die nur noch Inteprertiert werden mussen. Um festzulegen welches Gerät man abfragen will, wird ein FileHandle verwendet das mit der API CreateFile erzeugt werden muss. Zur Erzeugung eines File-Handles muss auch entsprechende Datei in Form eines Devices zur Verfügung stehen. Diese Geräte müssen sich in einem besonderen Kernel-Object-Name-Space befinden. Um einen Überblick über die Objekt-Struktur zu bekommen, hilft das Tool WinObj weiter.

Mit diesem Wissen kann man nun an die sensor.dll gehen, die ja von IBM als Benutzerschnittstellen ausgewiesen wird. Erste Überlegungen legen nahe das diese DLL nur ein schmaler Wrapper um die jeweiligen DeviceIoControl-Aufrufe ist. Wie bekommt man jetzt die benötigten Parameter heraus ?

Win32DAsm

Ich benutze das Tool Win32Dasm von URsoft um die Sensor.dll in ihrer vollen Assembler-Schönheit zu sehen. Es hat den Vorteil die Entrypoints der exportierten Funktionen mit Namen zu versehen und auch die bekannten Einsprungspunkte in die Win32-API in einem lesbaren Format darzustellen, so ist leichtes Navigieren möglich.

Entwurf des Prototypen

Nachdem das Funktionsprinzip der Software klar ist, kann man sich jetzt der Definition des Prototyps zuwenden und der Technik um alle benötigten Details zu finden. Dieser Prototyp soll sehr einfach gehalten werden und nicht die Original-APIs aus der sensor.dll aufrufen, sonder nur die DeviceIoControl-Calls ausführen. Ziel ist es ein Programm zu entwerfen, was die aktuelle Lage des Laptops ausgibt, nichts anderes macht die Control-Panel-Erweiterung mit etwas OpenGl verschönert.

Auswahl der Funktionen

Zur Auswahl der benötigten APIs kann man die sensor-DLL mit dem Dependency-Walker anschauen. Zum Glück sind auch alle Funktionen mit sprechenden Namen exportiert und so kann deren Bedeutung leicht erahnt werden. Ist das nicht möglich hilft manchmal auche die einfache Anwendung des in den Dependency Walker integrierten Profilers. So kann man z.B. erkennen das die Sensor.dll erst nach dem Programm-Start über LoadLibrary und GetProcAddress verwendet wird. Auch der WinObj hilft weiter und macht viele Synchronisations-Objekte sichtbar.

Um die Lage des Laptops heraus zu bekommen scheint die Funktione mit dem Namen GetAccelerometerData sehr vielversprechend. Also schauen wir uns den Assembler-Code an, der hinter dieser Funktion steckt. Jeder der jetzt den DASM aufmacht, wird sehen das eigentlich nur unwesentlich wichtiger Code vor dem eigentlichen Einsprung in die DeviceIOControl-Routine steht, somit sind für uns nur die genutzten Parameter wichtig. Die MSDN verrät das DeviceIOControl 8 Parameter benötigt. Diese werden in umgekehrter Reihenfolge auf den Stack gelegt. Dazu wird die push-Anweisung verwendet. Und siehe da, direkt vor dem Sprung finden sich 8 Push-Anweisungen mit den Parametern. Bis auf die Frage wo kommt das File-Handle her ist alles sehr durchsichtig und statisch. Es wird ein 36 Byte langer Output-Buffer übergeben und ein 0 Byte langer Input-Buffer. Das File-Handle kommt aus einem während der DLL-Initialisierung stattfindenden Aufruf von CreateFile. Daraus ergibt sich folgender Code für unseren Prototypen um den Lage des Laptops auszelesen:

HANDLE hShockMgr = CreateFile( "\\\\.\\ShockMgr", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );

DWORD dwOutLen = 0x24;
LPBYTE  lpOutput = (LPBYTE)LocalAlloc(LPTR, dwOutLen );
DWORD dwIOCode = 0x733FC;

DeviceIoControl( hSchockMgr, dwIOCode, NULL, 0, lpOutput, dwOutLen, &dwReturnedBytes , NULL );

Den entsprechenden Aufruf sollte man jetzt immer aufrufen wenn die neue Lage des Laptops abgefragt werden soll, natürlich sind alle Resourcen wie das geöffnete File-Handle wieder frei zu geben. Zusätzlich kommt noch einiges an Probier-Aufwand hinzu um die richtige Belegung der einzelnen Bytes im Rückgabewert zu verstehen. Hier hilft es seinen Laptop während des Auslesens in die entsprechenden Richtungen zu drehen und die Veränderungen zu notieren. Besonders Augenmerkt sollte auch noch auf die Funktion GetAccelerometerMutex gelegt werden, wenn dieser Code irgend parallel zu anderen Clients verwendet wird (und davon ist auszugehen). So lässt sich sehr leicht ein Tool entwerfen, das den Mouspointer über die Bewegung des Laptop steuert oder ähnliches.

Ich hoffe das dieser Artikel ein nützlicher Anfang für jeden ist, der den Vibrationssensor des Thinkpads für eigene Zwecke nutzen will. Als Autor kann ich weder für die Korrektheit aller Angaben garantieren noch irgendeine Form der Verantwortung an Beschädigungen des eigenen Gerätes übernehmen. 

Links:

Intel x86 Function-call Conventions - Assembly View 
http://www.online.ee/~andre/i80386/Opcodes/
http://pusa.uv.es/~ulisses/thinkpad/aps2mst.pdf 


 

posted on Sunday, September 25, 2005 4:44 PM

Feedback

# re: IBM Active Protection und die Sensor.dll 4/9/2007 3:42 AM icefirester
testing for school.

# Beschleunigungs Sensor auslesen, FSC Notebook 7/2/2007 9:19 PM Johannes Geiger
Moin hab eben auch eine bissel experimentiert und hab es mit meinem Fujitsu-Siemens Liefebook T4215 (Tablet) zum laufen bekommen. hier der Quelltext. viel Spass damit.
-------------------

/* Reads Acceleration Sensor Values out of FSC Liefebook T4215
and perhaps other FSC Notebooks that work with Shock Sensor
Utility ( FJSSGUI.exe + FJSSDMN.exe )
Sensor Description:
http://www.fujitsu.com/sg/services/computing/pc/einfo/shock-sensor/

Thanks to Nicholai Yu who did de reverse engineering:
http://nich.spaces.live.com/?_c11_BlogPart_BlogPart=blogview&_c=BlogPart&partqs=amonth%3d3%26ayear%3d2007
and MSDN for their example source which I've just modified a little bit.
http://msdn2.microsoft.com/En-US/library/aa363216.aspx

To Port this to other HDD Sensors try http://www.rohitab.com/apimonitor/ and monitor
the DeviceIoControl calls from an existing Sensor App.

Note: This code is only tested on one maschine.
!!!!!!Use it on your own risk!!!!!! and report if it works.
Sorry about my bad english, have fun with the app.
(I hope sombody built some nice tools or games like a port of this
http://www.weiblespiele.de/images/79050.jpg for tablet PC ;)

Some Keywords for Google:
Shock Sensor Utility, hdd, harddisk, shock, Fujitsu, source, c,
accelerometer, acceleration, motion, gyro, tilt, pan, protection
*/

#include <windows.h>
#include <winioctl.h>
#include <stdio.h>

BOOL GetAccel(char *AccValue)
{
HANDLE hDevice; // handle to the drive to be examined
BOOL bResult; // results flag
DWORD junk; // discard results

hDevice = CreateFile(TEXT("\\\\.\\PhysicalDrive0"), // drive
0, // no access to the drive
FILE_SHARE_READ | // share mode
FILE_SHARE_WRITE,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // do not copy file attributes

if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
return (FALSE);
}

bResult = DeviceIoControl(hDevice, // device to be queried
0x220208, // operation to perform <-- The interesting thing
NULL, 0, // no input buffer
AccValue, // output buffer
sizeof(*AccValue), //number of bytes to read
&junk, // # bytes returned
(LPOVERLAPPED) NULL); // synchronous I/O

CloseHandle(hDevice);

return (bResult);
}

int main(int argc, char *argv[])
{

char AccelerationValues[4]; // dByte Array for Acceleration Values
BOOL bResult; // generic results flag

for(int i=0;i<2000;i++){//Repeat a view times to see if the values change

bResult = GetAccel (&AccelerationValues[0]);

if (bResult)
{
printf("X-Value = %i\n", AccelerationValues[0]);
printf("Y-Value = %i\n", AccelerationValues[1]);
printf("Z-Value = %i\n", AccelerationValues[2]);
//4th Byte, always zero at my machine,
//don't know if it's important to read at all
printf("4th Byte = %i\n", AccelerationValues[3]);
printf("\nEnter to read again, Ctrl+C to exit\n------------------------------------");
}
else
{
printf ("GetAccel failed. Error %ld.\n", GetLastError ());
}
getchar();//
}
return ((int)bResult);
}//Ende




# re: IBM Active Protection und die Sensor.dll 2/10/2008 1:05 PM Matthias
Hallo, echt eine colle idee! ich hab ein LG-notebook (tx-adgeg), das ebenfalls einen schock-sensor hat. das läuft unter dem namen "G-Protector", und ist laut LG-Homepage ein "3D gravity accelerometer". Mehr infos konnte ich bisher aber leider nicht darüber herausfinden :-(

Habt ihr ne idee wie man diesen sensor auslesen kann?

Lg, Matthias

# re: IBM Active Protection und die Sensor.dll 2/10/2008 5:50 PM dirk Eisenberg
Hi,

also wenn es leider keine Dokumentation zu dieser Hardware gibt, würde ich mir als erste einen App suchen die irgend etwas mit dem Sensor macht. Damit bekommst du schonmal die betroffene DLL für die Sensor-Ansteuerung. Ist das geschafft musst du jetzt nur noch heraus finden wie die entsprechenden IOCtl-Codes sind. Dazu kannst du ja meinen Blog-Artikel hernehmen. Ich selbst arbeite leider nicht mehr so heufig an diesem Thema.

Grüße und Viel Glück
Dirk



# re: IBM Active Protection und die Sensor.dll 2/28/2008 9:37 PM Julian
Obwohl die sensor.dll nicht dokumentiert, kann man den richtigen Aufruf erraten. So funktioniert's mit C#:

public class SensorDllClass
{
//get all shock information
[DllImport("sensor.dll", CharSet = CharSet.Auto)]
public static extern int ShockproofGetAccelerometerDataEx(ref SensorData D);

//get Shock index only (but seems to be shifted)
[DllImport("sensor.dll", CharSet = CharSet.Auto)]
public static extern int ShockproofGetShockStatus(ref int x);

/// <summary>
/// int status: 0-4 hdd running; 8 hdd stopped; 12-13 repitive shocks (running); 14 sleeping (no shock detection, temporarily); 10 off (shock detection permanently disabled)
/// ushort x: resting position: x=~513
/// ushort y: resting position: y=~510
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct SensorData
{
//0-4 hdd running; 8 hdd stopped; 12-13 repeated shocks (running); 14 sleeping (no shock detection, temporarily); 10 off (shock detection permanently disabled)
public int status;
//resting position: x=~513
public ushort x;
//resting position: y=~510
public ushort y;


//there is more data: a lot of x and y values which hardly differ
//from first x and y values. but they don't seem to be mean values.
//also two bools which are always true.
public ushort x2;
public ushort y2;
public bool boolvalue1;
public bool boolvalue2;
public short x3;
public short x4;
public short y3;
public short y4;/*
public short y5;
public short x5;
public short x6;
public short y6;
*/
}
}


Der eigentliche Aufruf erfolgt dann mit:
SensorDllClass.SensorData D = new SensorDllClass.SensorData();

# re: IBM Active Protection und die Sensor.dll 2/28/2008 9:38 PM Julian
SensorDllClass.ShockproofGetAccelerometerDataEx(ref D);

Post Feedback

Title:
Name:
Email: (never displayed)
Url:
Comments: 
Please add 6 and 2 and type the answer here: