Using HTC Touch Diamond's Accelerometer/Sensor SDK from Managed Code

When I first got my HTC Touch Diamond a while ago, one of the first things I tried to do was reverse engineer the Sensor API found in HTCSensorSDK.dll. However, anyone who has tried to reverse engineer DLL arguments knows how tedious and painful it can be to create a dummy DLL to intercept valid arguments, parse through assembly, and inspect random memory pointers. Luckily, I did discover a registry key: HKEY_LOCAL_MACHINE\Software\HTC\HTCSensor\GSensor\EventChanged which let me figure out what the general orientation of the device was; and that was good enough for what I was trying to do.

However Scott, from scottandmichelle.net, successfully reverse engineered the HTCSensorSDK.dll. This allows developers to use the g-sensor that is available on the device. Very impressive work on the part of Scott!

Anyhow, I spent a portion of today writing a managed wrapper for HTC's Sensor API. You can download it here. The code also includes a sample Teeter-esque type application which allows you to roll a ball around the screen.

The managed API contains the IGSensor interface which allows you to hook to query the state of the g-sensor on the device. You can create it using the GSensorFactory.CreateGSensor method. It exposes the following methods, properties, and events:

GetGVector

Returns a vector that desribes the direction of gravity/acceleration in relation to the device screen.
When the device is face up on a flat surface, this method would return 0, 0, -9.8.
The Z value of -9.8 would mean that the acceleration in the opposite direction of the orientation of the screen.
When the device is held standing up, this method would return 0, -9.8, 0.
The Y value of -9.8 would mean that the device is accelerating in the direction of the bottom of the screen.
Conversely, if the device is held upside down, this method would return 0, 9.8, 0.
The vector returned will have a length measured in the unit meters per second square.
Ideally the when the device is in a motionless state, the vector would be of length 9.8 (the gravitational constant). However, the sensor is not extremely accurate, so this almost never the case.

faceup portrait

Orientation

Retrieves the current orientation of the device, returning one of the following enums: Landscape, ReverseLandscape, Portrait, ReversePortrait, FaceDown, FaceUp.

OrientationChanged

This event fires whenever the device's orientation changes.

Enjoy, and let me know if you find any bugs!


Update:

I have updated the SDK to include the Nav Sensor and the Light Sensor. All the sensors are now accessible!

Update #2:

The GSensor API now supports the Samsung Instinct/Omnia!

32 comments:

Anonymous said...

Hi I am trying to install the sensors on my HTC Diamond. I have downloaded them onto my internal storage but when I try to install or run them I get an error that says "There is no application associated with "HTCGSensor". Run the application first, then open this file from within the application. I am obviously doing something wrong here. Any tips?

Unknown said...

did you copy the sensors.dll to the same folder then the programs?

Any way im doing a program in Vb code on VS for my Diamond, could some one explain how can i use the sensors.dll on my program to show the Gsensor in a label? i dont understand much of VB.net only make forms calculation etc.

Anonymous said...

Can you make this in VB.NET ?

Greats

Codemaster

Koush said...

No, but you can add a reference to it from your VB.NET project.

Anonymous said...

Hi Koush

How do calculate the GVector x,y,z from the data in the SENSORDATA struct?

I guess somewhere the G data must exist before it's turned into angles. Seems a bit of a waste to have to reverse the calculation...

Thanks!

Koush said...

Why not just call GetGVector?

Anonymous said...

Because I wanted to do a native build. I don't get on with this new fangled .net stuff! :-p

Anonymous said...

Hi Koushik, thanks a lot for this!

One question: have you ever noticed than you cannot get values from the G-sensor more than 25 times per second? If you try with a higher frequency, the values are not changing (??)

I've seen that you have chosen a 40ms timer interval in your examples, so i wonder if this value was chosen randomly or not :)

Unknown said...

You can change the acc capture time in the registry, but i dint test to see if affects the readings.

Koush said...

I did notice that if I polled more than ~25 times per second, the operating seemed to hang a bit while doing other operations, such as painting.

Anonymous said...

Hi Koush, I highly appreciate your work and I was thinking about giving you an idea for expanding its capabilities regarding the Samsung Omnia.
I was thinking if it could be possible to modify the Light sensor API to support the light sensor in the Omnia too.
That could be a great step forward for implementations.
Keep it up the good work!

Koush said...

The Omnia does not have a light sensor.

Anonymous said...

Yes it has one, it's left of the front camera. In fact you have the option in the backlight settings to set it to automatic andit shows you the actual brightness of the environment. Just checked. :)

Koush said...

Oh, you're right! I'll investigate this and see what I find.

horatio.cs said...

I converted this solution to VS2005. Then I build and deploy GSensorTestForm in Diamond. It runs fine, but I can not debug...
The breakpoint will not be hit.
Please help, thanks.

Anonymous said...

Hello,
I have found other interesting signals in the Omnia acc sensor driver to get data.

#define IOCTL_ACS_READ1 0x3f3 // reads an integer x ?
#define IOCTL_ACS_READ2 0x3f4 // reads an integer y ?
#define IOCTL_ACS_READ3 0x3f5 // reads an integer z ?
#define IOCTL_ACS_READ4 0x3f6 // reads a vector (x/y/z ?)

I have not been able to fully understand the meaning of the values, and hope you will be able to do something with it.

Anonymous said...

To read the light sensor, use this :
const LPCWSTR pLightSensorName = L"BKL1:";
#define IOCTL_LIGHT_GET 0x220004
Values range from 0 (dark) to 15 (max light).
There are other signals I have not investigated these.

Anonymous said...

Diamond's Accelermeter return the vector which contains gravity...
But I don't care about the rotate, I wish to know the displacement.
I can't separate gravity from the vector. Can it return the vector without gravity?

Unknown said...

Hi Kaushik!

First of all...I have to say that your site and work is awesome. I am a big fan of your work.

I was trying your IGsensor interface and copied the code from your sensortest (teeterish) app, but I noticed that the orientationchanged event never fires.
IGSensor myGensor (class variable)

Form_Load()
------------ myGSensor = GSensorFactory.CreateGSensor();
myGSensor.OrientationChanged += new OrientationChangedHandler(mySensor_OrientationChanged);

Event Handler
------
void mySensor_OrientationChanged(IGSensor sender)

I noticed in Klaxon and Gsensor test app that you are actually using a timer to inspect the orientation...and not using the event at all.

Kaaustubh said...

Hi kaushik,
nice work dude.
But tell me one thing, when the Gvector changes if we get some event or we have to keep checking every time to know GVector is changed or not?
Like Orientation change event there must be some event to notify tha the GVector of device is changed.

Anonymous said...

how can i install these sensors.?

Anonymous said...

How can we change this application to carpenter's bubble level, inch ruler, and centimeter ruler? If its possible can you give us a sample code?

Regards.

Anonymous said...

Hi Kaushik,

Do you have a version of your sample code that does not use .net?

My project is in unmanaged, standard win32, and want to access the capacitive touch area at the bottom of my htc.

Thanks

Anonymous said...

Hello, first of all: Many thanks for for your work developing such a nice piece of software.
But, do you know whether it is possibble to access Diamonds GPS receiver via C#.
And is it possible to access phone functions like sending an SMS via C# as well?
Regards,
Michael

Anonymous said...

Nice work! Using this I managed to abuse my Touch HD as motion input device ala the Wiimote, but over WLAN and with on-screen feedback :D

Anonymous said...

Hey Koush,

Thanks a lot for this wonderful managed code for sensor. Due to this code I am able to develop G-Trigger, shake and launch application :)

Thanks Again :)

Cheer!
Krupal

Krups said...

Hi Koush,

While using it with Samsung's omnia, getvector throws error "Unable to perform operation." when device is made lock and unlock again. It works fine until device is made lock and unlock.

Issue is not found with HTC code.

Any clues?

Thanks,
Krupal

Alireza said...

There were some questions previously raised about the Accelerometer polling frequency limited at 25hz (both here and at scottandmichelle.net), but without any solution. Has anyone come across ways to increase this number?

Ricardo Sampaio: Have you investigated modifying the accel capture time in the registry? I'd appreciate hearing what you have learned, or even advice on how I can investigate this myself.

Lorenzo said...

hello. i think this is a great work, i can actually interact with the accelerometer and the light sensor. but if i would like to interact with camera, microphone, GPS and so on how can i do? i saw for example that the code to get light from the light sensor is 0x220004, used in NativeMethods.DeviceIoControl. i'd like to know if there are other similar hex for other sensors.
thank you very much

lollo_ai@hotmail.com

Josef said...

Although I appreciate your work on the API, I dont see any use (except for automatic screen rotation) in using sensors in serious applications.
See my post at http://www.hjgode.de/wp/2009/06/20/itc-cn50-sensors-looking-for-usefull-applications/

regards

Josef

Joshua Smith said...

Thanks for useful information. For industry solutions it is the right way to get outsource software development.

Joshua Smith said...

A lot of thanks for this great tips. Casino partners always look for best casino affiliate programs to increase their revenue income from best casinos or poker rooms.