G-SENSOR / ACCELEROMETER for the Acer 1825PT(Z) : Part I
(This should also works with some Dell machines, Samsung NB30, Acer1410, 1810TZ, 1810T (?), and some Packard Bell clones of the Acer Tablet PC laptops)
Here we go !!!
1° way :
The first code is based on i2c-gsensor and gsensor-joy-1.1, so you'll have to get the i2c-gsensor tar ball in order to use the i2c-dev.h and the Makefile, then replace the i2c-gsensor.c with the code below.
The gsensor-joy-1.1 is not needed unless you want to study it...
http://pof.eslack.org/blog/2008/06/0...hift-g-sensor/
Code:
/*
HTC Shift G-Sensor Reader
Reads data from i2c interface, chip STMicroelectronics LIS3LV02DL
Copyright (C) 2008 Esteve Espuna <esteve@eslack.org>
Pau Oliva <pof@eslack.org>
Based on i2cget.c:
Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
Based on i2cset.c, i2cbusses.c:
Copyright (C) 2001-2003 Frodo Looijaard <frodol@dds.nl>, and
Mark D. Studebaker <mdsxyz123@yahoo.com>
Copyright (C) 2004-2005 Jean Delvare <khali@linux-fr.org>
Modified by Arobase Chac (arobase40) and Imarune for the Acer 1825PT(Z).
May work with some Dell machine, Samsung NB30, Acer 1410, 1810TZ, 1810T and some Packard Bell clone of the Acer tablet pc laptops...
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301 USA.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include "i2c-dev.h"
#define WHO_AM_I 0x3b
int open_i2c_dev(const int i2cbus, char *filename, const int quiet)
{
int file;
sprintf(filename, "/dev/i2c/%d", i2cbus);
file = open(filename, O_RDWR);
if (file < 0 && errno == ENOENT) {
sprintf(filename, "/dev/i2c-%d", i2cbus);
file = open(filename, O_RDWR);
}
if (file < 0 && !quiet) {
if (errno == ENOENT) {
fprintf(stderr, "Error: Could not open file "
"`/dev/i2c-%d' or `/dev/i2c/%d': %s\n",
i2cbus, i2cbus, strerror(ENOENT));
} else {
fprintf(stderr, "Error: Could not open file "
"`%s': %s\n", filename, strerror(errno));
if (errno == EACCES)
fprintf(stderr, "Run as root?\n");
}
}
return file;
}
int main(int argc, char *argv[])
{
int res, i2cbus = 0, address, file, loop=0, dir=-1;
int xl,xh;
int yl,yh;
int zl,zh;
short x,y,z;
int magic;
char filename[20];
if ( argc >= 2 ) {
i2cbus = atoi(argv[1]);
if (argc == 3 && strcmp(argv[2], "loop") == 0)
loop = 1;
}
else {
fprintf(stderr, "Usage : %s i2cbus [loop]\n", argv[0]);
exit (1);
}
address = 0x1d;
file = open_i2c_dev(i2cbus, filename , 0);
ioctl(file, I2C_SLAVE, address);
i2c_smbus_write_byte_data(file, 0x20, 0x47);
i2c_smbus_write_byte_data(file, 0x21, 0x63);
magic = i2c_smbus_read_byte_data(file, 0xf);
if (magic != WHO_AM_I ) {
printf("Accelerometer not found\n");
exit(-1);
}
while (1)
{
sleep(2);
xh = i2c_smbus_read_byte_data(file, 0x28);
xl = i2c_smbus_read_byte_data(file, 0x29);
x = (xh<<8) | ( xl );
yh = i2c_smbus_read_byte_data(file, 0x2a);
yl = i2c_smbus_read_byte_data(file, 0x2b);
y = (yh<<8) | ( yl );
zh = i2c_smbus_read_byte_data(file, 0x2c);
zl = i2c_smbus_read_byte_data(file, 0x2d);
z = (zh<<8) | ( zl );
printf("x = %d y = %d z = %d", x, y, z);
if ( x < 128 ) {
/* printf("Normal orientation\n"); */
dir=0;
}
else
{
if ( y < 128 ) {
/* printf("Left orientation\n"); */
dir=1;
}
else
{
if ( z < 128 ) {
/* printf("Right orientation\n"); */
dir=2;
}
else {
/* printf("Inverted orientation\n"); */
dir=3;
}
}
}
if ( !loop )
break;
}
close(file);
exit(dir);
}
Just compile it and copy it somewhere in /usr/bin or /usr/local/bin.
Put "i2c-i801" and "i2c-dev" in your /etc/modules, then reboot.
Finally call i2c-gsensor as root or with sudo, passing 0 and optionally "loop" as parameter.
The loop parameter is just for testing mode (not needed in the script), while the i2cbus may vary from 0 to 7 depending of the linux distribution and the loading order of the previous modules (at boot time or loaded by the script).
With Ubuntu, the i2cbus parameter should be 0, but I can't guarantee this is always the case.
In Part II, you will find the script which use this pseudo-driver and which will rotate the display according to the return value of i2c-gsensor.
In the same script there will be an optional tip to find out the entry point to the i2c bus (for the i2cbus parameter)...
2° way :
Now, a patch to modify the kernel lis3lv02d_i2c module.
cd [dir_source_kernel]/drivers/hwmon; patch -p0 < [dir_patch]/lis3lv02d_i2c.patch)
Then recompile the whole kernel and when all is done, you just need to write down "lis3lv02d_i2c" in the /etc/modules file.
Code:
--- lis3lv02d_i2c_orig.c 2010-09-29 03:01:22.000000000 +0200
+++ lis3lv02d_i2c.c 2010-10-06 15:18:30.521867001 +0200
@@ -33,6 +33,9 @@
#define DRV_NAME "lis3lv02d_i2c"
+/* Addresses to scan */
+static const unsigned short normal_i2c[] = { 0x1d, I2C_CLIENT_END };
+
static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value)
{
struct i2c_client *c = lis3->bus_priv;
@@ -60,6 +63,26 @@
return lis3->write(lis3, CTRL_REG1, reg);
}
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int lis3lv02d_i2c_detect(struct i2c_client *client,
+ struct i2c_board_info *info)
+{
+ int val;
+ struct i2c_adapter *adapter = client->adapter;
+
+ if (!i2c_check_functionality(adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
+
+ val = i2c_smbus_read_byte_data(client, WHO_AM_I);
+ if (!((val & WAI_12B) || (val & WAI_8B)))
+ return -ENODEV;
+
+ strlcpy(info->type, "lis3lv02d", I2C_NAME_SIZE);
+
+ return 0;
+}
+
/* Default axis mapping but it can be overwritten by platform data */
static struct axis_conversion lis3lv02d_axis_map = { LIS3_DEV_X,
LIS3_DEV_Y,
@@ -157,12 +180,15 @@
.name = DRV_NAME,
.owner = THIS_MODULE,
},
+ .class = I2C_CLASS_HWMON,
.suspend = lis3lv02d_i2c_suspend,
.shutdown = lis3lv02d_i2c_shutdown,
.resume = lis3lv02d_i2c_resume,
.probe = lis3lv02d_i2c_probe,
.remove = __devexit_p(lis3lv02d_i2c_remove),
+ .detect = lis3lv02d_i2c_detect,
.id_table = lis3lv02d_id,
+ .address_list = normal_i2c,
};
static int __init lis3lv02d_init(void)
If everything is correctly initialized, you should see a new "p-data" platform here :
/sys/devices/platform/lis3lv02d
The "position" parameter contains the x, y, z axis coordinates...
Again, this is useless without a script to interpret theses values.
But again, you'll have to be patient...
3° way :
Here is the most fancy and weird way to initialize the lis3lv02d_i2c module and to initialize the gsensor/accelerometer for the 1825PT(Z) !!!
It is also the quickest, uncommon and shortest way to do it !!!
This is mostly an unknown workaround while this has been implemented for a while... ^^
This was implemented for development purposes so nobody can guarantee it will exist in this form in the future...
You will need a 2.6.35 or 2.6.36 kernel (no need for the source code). This should also work with kernel 2.6.34 even if of little interest as the touchscreen doesn't work fine with this latter version.
Finallly here is the workaround :
Load the standard and unmodified i2c-i801, i2c-dev and lis3lv02d_i2c modules in /etc/modules, then reboot...
If you can find i2c-0 in /sys/devices/pci0000:00/0000:00:1f.3 then apply as root :
#echo lis3lv02d 0x1d>/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/new_device
To verify if that works :
#cat /sys/devices/pci0000:00/0000:00:1f.3/i2c-0/0-001d/name
You should see :
#lis3lv02d
That's it !!!!
No need to recompile the whole kernel.
When you're sure that all is correct, put the line (echo lis3lv02d 0x1d>/sys/devices/pci0000:00/0000:00:1f.3/i2c-0/new_device) in your /etc/rc.local
To follow in part II, for the scripts...
Bookmarks