Re: [WISHLIST] IBM HD Shock detection in Linux

From: Niel Lambrechts
Date: Sun Dec 12 2004 - 17:02:10 EST


I picked this up from somewhere on the net, pity that it is not c
code...

The code apparently can display the horizon, but cannot prevent
shocks :(

--
Niel Lambrechts <antispam@xxxxxxxxxxxx>
using System;
using System.IO;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;

public sealed class Accelerometer : IDisposable
{
private const uint GENERIC_READ = 0x80000000;
private const uint FILE_SHARE_READ = 1;
private const uint FILE_SHARE_WRITE = 2;
private const uint OPEN_EXISTING = 3;
private readonly static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
private const uint IOCTL_SHOCKMGR_READ_ACCELEROMETER_DATA = 0x733fc;
private const int FACILITY_WIN32 = unchecked((int)0x80070000);
private IntPtr handle = INVALID_HANDLE_VALUE;
private AccelerometerData sample;

private static int HRESULT_FROM_WIN32(int x)
{
return x <= 0 ? x : ((x & 0x0000FFFF) | FACILITY_WIN32);
}

private struct AccelerometerData
{
internal int status;
internal short x0;
internal short y0;
short x1;
short y1;
short x2;
short y2;
short x3;
short y3;
short x4;
short y4;
short x5;
short y5;
short x6;
short y6;
short x7;
short y7;
short x8;
short y8;
short x9;
short y9;
short x10;
short y10;
short x11;
short y11;
short x12;
short y12;
short x13;
short y13;
short unknown0;
short unknown1;
}

[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);

[DllImport("kernel32.dll")]
private static extern void CloseHandle(IntPtr handle);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, ref AccelerometerData lpOutBuffer, uint nOutBufferSize, ref uint lpBytesReturned, IntPtr lpOverlapped);

public Accelerometer()
{
handle = CreateFile(@"\\.\ShockMgr", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
if(handle == INVALID_HANDLE_VALUE)
{
GC.SuppressFinalize(this);
Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(Marshal.GetLastWin32Error()));
}
}

~Accelerometer()
{
CloseImpl();
}

private void CloseImpl()
{
IntPtr h = handle;
if(h != INVALID_HANDLE_VALUE)
{
handle = INVALID_HANDLE_VALUE;
CloseHandle(h);
}
}

public void ReadSample()
{
uint dwRead = 0;
if(!DeviceIoControl(handle, IOCTL_SHOCKMGR_READ_ACCELEROMETER_DATA, IntPtr.Zero, 0, ref sample, 0x24, ref dwRead, IntPtr.Zero))
{
Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(Marshal.GetLastWin32Error()));
}
}

public int Status
{
get
{
return sample.status;
}
}

public int X
{
get
{
return sample.x0;
}
}

public int Y
{
get
{
return sample.y0;
}
}

public void Dispose()
{
CloseImpl();
GC.SuppressFinalize(this);
}
}

namespace Horizon
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.ComponentModel.IContainer components;
private System.Windows.Forms.Timer timer1;
private Accelerometer sensor = new Accelerometer();

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//

}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.timer1 = new System.Windows.Forms.Timer(this.components);
//
// timer1
//
this.timer1.Enabled = true;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Name = "Form1";
this.Text = "Form1";

}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void timer1_Tick(object sender, System.EventArgs e)
{
sensor.ReadSample();
Invalidate();
}

protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
float horizontal = 640;
float vertical = 800;
float y = sensor.Y;
float angle = 90 * (y - horizontal) / (vertical - horizontal);
e.Graphics.DrawString(angle.ToString(), Font, Brushes.Black, 0, 0);
e.Graphics.TranslateTransform(ClientRectangle.Width / 2, ClientRectangle.Height / 2);
e.Graphics.RotateTransform(- angle);
e.Graphics.DrawLine(Pens.Black, - ClientRectangle.Width / 2, 0, ClientRectangle.Width / 2, 0);
}
}
}