Step-by-Step into the cloud

a blog of Dirk Eisenberg (>)
posts - 82 , comments - 19 , trackbacks - 17

IBM Active Protection und die Sensor.dll

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 


 

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

Feedback

Gravatar

# re: IBM Active Protection und die Sensor.dll

testing for school.
4/9/2007 3:42 AM | icefirester
Gravatar

# re: IBM Active Protection und die Sensor.dll

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
2/10/2008 1:05 PM | Matthias
Gravatar

# re: IBM Active Protection und die Sensor.dll

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

2/10/2008 5:50 PM | dirk Eisenberg
Gravatar

# re: IBM Active Protection und die Sensor.dll

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();
2/28/2008 9:37 PM | Julian
Gravatar

# re: IBM Active Protection und die Sensor.dll

SensorDllClass.ShockproofGetAccelerometerDataEx(ref D);
2/28/2008 9:38 PM | Julian
Gravatar

# re: IBM Active Protection und die Sensor.dll

ich hab versucht, das mit der tplhmm.dll nachzuvollziehen, da ich die darin enthaltenen Funktionen zur Steuerung des MasterVolume unter Vista/Seven verwenden will.
mangels assemblerkenntnissen konnte ich allerdings mit der ausgabe von bdasm nichts anfangen.
ich müsste wissen, welche parameter an die funktionen übergeben werden müssen und in welcher form die ergebnisse zurückgeliefert werden.
ob sich da jemand erbarmen und mal einen blick drauf werfen könnte?
11/7/2010 8:51 PM | Raik
Post A Comment
Title:
Name:
Email:
Comment:
Verification:
 

Powered by: