Android Pseudo Accelerator Sensor
想知道在 Android 上如何產生一個虛擬的 GSENSOR, 並透過程式控制這個 GSENSOR 產生你想要的資料? 看這篇文章就對了.
Step 1: Cross-compile the given psensor.c to Android kernel
//#include <linux/mysyscall.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <linux/miscdevice.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/pm.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/hwmon.h>
#include <linux/input-polldev.h>
#include <linux/random.h>
#include <linux/string.h>
///////////////////////////////////////////////////////////
//
#define BUILD_UINT16(loByte, hiByte) \
((unsigned short)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8)))
#define BUILD_UINT32(Byte0, Byte1, Byte2, Byte3) \
((unsigned int)((unsigned int)((Byte0) & 0x00FF) + ((unsigned int)((Byte1) & 0x00FF) << 8) \
+ ((unsigned int)((Byte2) & 0x00FF) << 16) + ((unsigned int)((Byte3) & 0x00FF) << 24)))
#define HI_UINT16(a) (((a) >> 8) & 0xFF)
#define LO_UINT16(a) ((a) & 0xFF)
#define BUILD_UINT8(hiByte, loByte) \
((unsigned char)(((loByte) & 0x0F) + (((hiByte) & 0x0F) << 4)))
#define HI_UINT8(a) (((a) >> 4) & 0x0F)
#define LO_UINT8(a) ((a) & 0x0F)
#define BREAK_UINT32(var, ByteNum) \
(unsigned char)((unsigned int)(((var) >>((ByteNum) * 8)) & 0x00FF))
///////////////////////////////////////////////////////////
//
#define POLL_INTERVAL_MIN 1
#define POLL_INTERVAL_MAX 500
#define POLL_INTERVAL 100 /* msecs */
#define POLL_STOP_TIME 200
///////////////////////////////////////////////////////////
//
#define PS_BUF_SIZE (6+1)
#define PSIO 'P'
#define PS_IOCTL_GETDATA _IOR(PSIO, 0, int)
#define PS_IOCTL_SETDATA _IOW(PSIO, 1, int)
#define PS_IOCTL_GETPOS _IOR(PSIO, 2, int)
#define PS_IOCTL_SETPOS _IOW(PSIO, 3, int)
///////////////////////////////////////////////////////////
//
static ssize_t ps_enable_show(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t ps_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
static ssize_t ps_position_show(struct device *dev, struct device_attribute *attr, char *buf);
static ssize_t ps_position_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO, ps_enable_show, ps_enable_store);
static DEVICE_ATTR(position, S_IWUSR | S_IRUGO, ps_position_show, ps_position_store);
static struct attribute *ps_attributes[] = {
&dev_attr_enable.attr,
&dev_attr_position.attr,
NULL
};
static const struct attribute_group ps_attr_group = {
.attrs = ps_attributes,
};
///////////////////////////////////////////////////////////
//
enum {
MODE_2G = 0,
MODE_4G,
MODE_8G,
};
enum {
PS_STANDBY = 0,
PS_ACTIVED,
};
struct ps_data_axis {
short x;
short y;
short z;
};
struct ps_data {
struct input_polled_dev *poll_dev;
struct mutex data_lock;
int active;
int position;
int mode;
};
///////////////////////////////////////////////////////////
//
// SCALER 1640
//X=1040 Y=-176 Z=16120
//struct ps_data_axis ps_axis = {-900, 600, 16300};
struct ps_data_axis ps_axis = {0, 0, 16300};
static u8 tmp_data[PS_BUF_SIZE];
static struct ps_data psensor_data;
static int sensor_position_setting[8][3][3] = {
{ { 0, -1, 0 }, { 1, 0, 0 }, { 0, 0, 1 } },
{ { -1, 0, 0 }, { 0, -1, 0 }, { 0, 0, 1 } },
{ { 0, 1, 0 }, { -1, 0, 0 }, { 0, 0, 1 } },
{ { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } },
{ { 0, -1, 0 }, { -1, 0, 0 }, { 0, 0, -1 } },
{ { -1, 0, 0 }, { 0, 1, 0 }, { 0, 0, -1 } },
{ { 0, 1, 0 }, { 1, 0, 0 }, { 0, 0, -1 } },
{ { 1, 0, 0 }, { 0, -1, 0 }, { 0, 0, -1 } },
};
///////////////////////////////////////////////////////////
//
#define MAX_REMAINDER (240 - 1)
static struct input_polled_dev *sensor_poll_dev = 0;
static int ps_data_convert(struct ps_data *pdata, struct ps_data_axis *axis_data) {
struct input_polled_dev *poll_dev = pdata->poll_dev;
short x, y, z;
short rawdata[3]={0,0,0}, data[3]={0,0,0};
int i, j;
int position = pdata->position;
char rand_x = 0, rand_y = 0, rand_z = 0;
get_random_bytes(&rand_x, sizeof(char));
get_random_bytes(&rand_y, sizeof(char));
get_random_bytes(&rand_z, sizeof(char));
//rand_x /= MAX_REMAINDER; rand_y /= MAX_REMAINDER; rand_z /= MAX_REMAINDER;
if (position < 0 || position > 7)
position = 0;
rawdata[0] = axis_data->x;
rawdata[1] = axis_data->y;
rawdata[2] = axis_data->z;
for (i = 0; i < 3; i++) {
data[i] = 0;
for (j = 0; j < 3; j++)
data[i] += rawdata[j] * sensor_position_setting[position][i][j];
}
axis_data->x = data[0];
axis_data->y = data[1];
axis_data->z = data[2];
x = data[0]; y = data[1]; z = data[2];
ps_axis.x = x;
ps_axis.y = y;
ps_axis.z = z;
input_report_abs(poll_dev->input, ABS_X, ps_axis.x + (short)rand_x);
input_report_abs(poll_dev->input, ABS_Y, ps_axis.y + (short)rand_y);
input_report_abs(poll_dev->input, ABS_Z, ps_axis.z + (short)rand_z);
input_sync(poll_dev->input);
//printk("JC NOTE, %s %s(%d), x=%d y=%d z=%d\n", __FILE__, __func__, __LINE__, x, y, z);
return 0;
}
static int ps_read_data(struct i2c_client *client, struct ps_data_axis *axis_data) {
short x, y, z;
if (0 != client) {
printk("JC NOTE, %s %s(%d), error\n", __FILE__, __func__, __LINE__);
return -1;
}
memcpy(&axis_data->x, &tmp_data[0], sizeof(unsigned short));
memcpy(&axis_data->y, &tmp_data[2], sizeof(unsigned short));
memcpy(&axis_data->z, &tmp_data[4], sizeof(unsigned short));
//axis_data->x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1];
//axis_data->y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3];
//axis_data->z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5];
x = axis_data->x; y = axis_data->y; z = axis_data->z;
//printk("JC NOTE, %s %s(%d), x=%d y=%d z=%d\n", __FILE__, __func__, __LINE__, x, y, z);
return 0;
}
static void ps_report_data(struct ps_data *pdata) {
struct input_polled_dev *poll_dev = pdata->poll_dev;
struct ps_data_axis data;
if (pdata->active == PS_STANDBY) {
poll_dev->poll_interval = POLL_STOP_TIME;
//printk("JC NOTE, %s %s(%d), PS_STANDBY\n", __FILE__, __func__, __LINE__);
return;
}
else if (poll_dev->poll_interval == POLL_STOP_TIME) {
poll_dev->poll_interval = POLL_INTERVAL;
}
ps_read_data(0, &data);
ps_data_convert(pdata, &data);
//printk("JC NOTE, %s %s(%d)\n", __FILE__, __func__, __LINE__);
/*
ps_axis.x = data.x;
ps_axis.y = data.y;
ps_axis.z = data.z;
input_report_abs(poll_dev->input, ABS_X, data.x);
input_report_abs(poll_dev->input, ABS_Y, data.y);
input_report_abs(poll_dev->input, ABS_Z, data.z);
input_sync(poll_dev->input);
*/
}
static void ps_dev_poll(struct input_polled_dev *dev) {
struct ps_data *pdata = &psensor_data;
ps_report_data(pdata);
}
static ssize_t ps_enable_show(struct device *dev, struct device_attribute *attr, char *buf) {
struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
struct ps_data *pdata = (struct ps_data *)(poll_dev->private);
int enable;
if (pdata->active == PS_ACTIVED) enable = 1;
else enable = 0;
return sprintf(buf, "%d\n", enable);
}
static ssize_t ps_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
struct ps_data *pdata = (struct ps_data *)(poll_dev->private);
//int ret;
unsigned long enable = 0;
enable = simple_strtoul(buf, NULL, 10);
enable = (enable > 0) ? 1 : 0;
if (enable && pdata->active == PS_STANDBY) pdata->active = PS_ACTIVED;
else if (enable == 0 && pdata->active == PS_ACTIVED) pdata->active = PS_STANDBY;
return count;
}
static ssize_t ps_position_show(struct device *dev, struct device_attribute *attr, char *buf) {
struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
struct ps_data *pdata = (struct ps_data *)(poll_dev->private);
int position = 0;
position = pdata->position;
return sprintf(buf, "%d\n", position);
}
static ssize_t ps_position_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
struct ps_data *pdata = (struct ps_data *)(poll_dev->private);
int position;
position = simple_strtoul(buf, NULL, 10);
pdata->position = position;
return count;
}
static int ps_device_init(void) {
//int result;
struct ps_data *pdata = &psensor_data;
memset(&ps_axis, 0, sizeof(struct ps_data_axis));
ps_axis.z = 16300;
memcpy(&tmp_data[4], &ps_axis.z, sizeof(short));
//tmp_data[4] = HI_UINT16(ps_axis.z);
//tmp_data[5] = LO_UINT16(ps_axis.z);
pdata->mode = MODE_2G;
pdata->position = 0;//*(int *)client->dev.platform_data;
pdata->active = PS_STANDBY;
return 0;
}
static int ps_device_stop(void) {
struct ps_data *pdata = &psensor_data;
pdata->active = PS_STANDBY;
return 0;
}
////////////////////////////////////////////////////////////////////
//
static int registered_polled_device = 0;
static long ps_ioctl( struct file *file, unsigned int cmd, unsigned long arg) {
int position = 0;
struct ps_data_axis data;
struct ps_data *pdata = &psensor_data;
if (0 == arg) return -EFAULT;
if (0 == registered_polled_device) return -EFAULT;
switch (cmd) {
case PS_IOCTL_GETPOS:
if (pdata->position < 0 || pdata->position > 7) pdata->position = 0;
position = pdata->position;
if (copy_to_user((void *)arg, (void *)&position, sizeof(int)) )
return -EFAULT;
break;
case PS_IOCTL_SETPOS:
if (copy_from_user((void *)&position, (void *)arg, sizeof(int)))
return -EFAULT;
if (position < 0 || position > 7) position = 0;
pdata->position = position;
//ps_read_data(0, &data);
//ps_data_convert(pdata, &data);
break;
case PS_IOCTL_GETDATA:
if (pdata->active != PS_ACTIVED) return -EFAULT;
memcpy(&data.x, &tmp_data[0], sizeof(short));
memcpy(&data.y, &tmp_data[2], sizeof(short));
memcpy(&data.z, &tmp_data[4], sizeof(short));
//data.x = ps_axis.x;
//data.y = ps_axis.y;
//data.z = ps_axis.z;
if (copy_to_user((void *)arg, (void *)&data, sizeof(struct ps_data_axis)) ) return -EFAULT;
break;
case PS_IOCTL_SETDATA:
if (pdata->active != PS_ACTIVED) return -EFAULT;
if (copy_from_user((void *)&data, (void *)arg, sizeof(struct ps_data_axis))) return -EFAULT;
memcpy(&tmp_data[0], &data.x, sizeof(short));
memcpy(&tmp_data[2], &data.y, sizeof(short));
memcpy(&tmp_data[4], &data.z, sizeof(short));
//tmp_data[0] = HI_UINT16(data.x); tmp_data[1] = LO_UINT16(data.x);
//tmp_data[2] = HI_UINT16(data.y); tmp_data[3] = LO_UINT16(data.y);
//tmp_data[4] = HI_UINT16(data.z); tmp_data[5] = LO_UINT16(data.z);
//ps_report_data(pdata);
//ps_read_data(0, &data);
//ps_data_convert(pdata, &data);
break;
default:
printk("JC NOTE, %s %s(%d), error,cmd=%x\n\n", __FILE__, __func__, __LINE__, cmd);
return -EPERM;
}
return 0;
}
static int ps_open(struct inode *inode, struct file *file) {
//printk("%s\n",__FUNCTION__);
return 0;
}
static int ps_release(struct inode *inode, struct file *file) {
//printk("%s\n",__FUNCTION__);
return 0;
}
static struct file_operations ps_fops = {
.owner = THIS_MODULE,
.open = ps_open,
.release = ps_release,
.unlocked_ioctl = ps_ioctl,
//.compat_ioctl = ps_ioctl,
};
static struct miscdevice ps_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = "psensor",
.fops = &ps_fops,
};
static int __init ps_init(void) {
int error;
struct input_dev *idev;
struct ps_data *pdata = &psensor_data;
//mutex_init(&pdata->data_lock);
ps_device_init();
sensor_poll_dev = input_allocate_polled_device();
if (!sensor_poll_dev) {
error = -ENOMEM;
printk("JC NOTE, %s %s(%d), alloc poll device failed!\n\n", __FILE__, __func__, __LINE__);
goto err_alloc_poll_device;
}
sensor_poll_dev->poll = ps_dev_poll;
sensor_poll_dev->poll_interval = POLL_STOP_TIME;
sensor_poll_dev->poll_interval_min = POLL_INTERVAL_MIN;
sensor_poll_dev->poll_interval_max = POLL_INTERVAL_MAX;
sensor_poll_dev->private = pdata;
idev = sensor_poll_dev->input;
//idev->name = "PseudoAccelerometer";
idev->name = "FreescaleAccelerometer";
idev->uniq = 0;//0X5F;
#if 1
idev->id.bustype = BUS_VIRTUAL;
#else
idev->id.bustype = BUS_I2C;
#endif // 0
idev->evbit[0] = BIT_MASK(EV_ABS);
input_set_abs_params(idev, ABS_X, -0x7fff, 0x7fff, 0, 0);
input_set_abs_params(idev, ABS_Y, -0x7fff, 0x7fff, 0, 0);
input_set_abs_params(idev, ABS_Z, -0x7fff, 0x7fff, 0, 0);
//printk("JC NOTE, %s %s(%d), kobj.name='%s'\n", __FILE__, __func__, __LINE__, idev->dev.kobj.name);
pdata->poll_dev = sensor_poll_dev;
error = input_register_polled_device(pdata->poll_dev);
if (error) {
printk("JC NOTE, %s %s(%d), register poll device failed!\n", __FILE__, __func__, __LINE__);
goto err_register_polled_device;
}
registered_polled_device = 1;
error = sysfs_create_group(&idev->dev.kobj, &ps_attr_group);
if (error) {
printk("JC NOTE, %s %s(%d), ERROR ON sysfs_create_group() !\n", __FILE__, __func__, __LINE__);
error = -EINVAL;
goto err_create_sysfs;
}
misc_register(&ps_device);
pdata->active = PS_ACTIVED;
sensor_poll_dev->poll_interval = POLL_INTERVAL;
printk("JC NOTE, %s %s(%d), pseudo sensor device driver init successfully!\n", __FILE__, __func__, __LINE__);
return 0;
err_create_sysfs:
input_unregister_polled_device(pdata->poll_dev);
registered_polled_device = 0;
err_register_polled_device:
input_free_polled_device(sensor_poll_dev);
err_alloc_poll_device:
//kfree(pdata);
return error;
}
static void __exit ps_exit(void) {
struct ps_data *pdata = &psensor_data;
ps_device_stop();
if (0 == sensor_poll_dev)
return;
if (registered_polled_device) {
registered_polled_device = 0;
if (pdata->poll_dev)
input_unregister_polled_device(pdata->poll_dev);
}
input_free_polled_device(sensor_poll_dev);
misc_deregister(&ps_device);
}
module_init(ps_init);
module_exit(ps_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("jasonc@mail2000.com.tw");
Step 2: Modify the Android HAL & Rebuild Project
root@monta:~/myandroid# vi hardware/imx/libsensors/AccelSensor.cpp
/*
* Copyright (C) 2012-2013 Freescale Semiconductor, Inc.
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <stdlib.h>
#include <poll.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/select.h>
#include <dlfcn.h>
#include <cutils/log.h>
#include <cutils/properties.h>
#include "AccelSensor.h"
#define ACC_DATA_NAME "FreescaleAccelerometer"
#define ACC_SYSFS_PATH "/sys/class/input"
#define ACC_SYSFS_DELAY "poll"
#define ACC_SYSFS_ENABLE "enable"
#define ACC_EVENT_X ABS_X
#define ACC_EVENT_Y ABS_Y
#define ACC_EVENT_Z ABS_Z
#define ACC_DATA_CONVERSION(value) (float)((float)((int)value) * (GRAVITY_EARTH / (0x4000)))
AccelSensor::AccelSensor()
: SensorBase(NULL, ACC_DATA_NAME),
mEnabled(0),
mPendingMask(0),
mInputReader(4),
mDelay(0) {
memset(&mPendingEvent, 0, sizeof(mPendingEvent));
memset(mClassPath, '\0', sizeof(mClassPath));
mPendingEvent.version = sizeof(sensors_event_t);
mPendingEvent.sensor = ID_A;
mPendingEvent.type = SENSOR_TYPE_ACCELEROMETER;
mPendingEvent.acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
mUser = 0;
if(sensor_get_class_path(mClassPath)) {
ALOGE("Can`t find the Acc sensor!");
}
}
AccelSensor::~AccelSensor() {
}
int AccelSensor::setEnable(int32_t handle, int en) {
int err = 0;
uint32_t newState = en;
if(handle != ID_A && handle != ID_O && handle != ID_M)
return -1;
if(en)
mUser++;
else{
mUser--;
if(mUser < 0)
mUser = 0;
}
if(mUser > 0)
err = enable_sensor();
else
err = disable_sensor();
if(handle == ID_A ) {
if(en)
mEnabled++;
else
mEnabled--;
if(mEnabled < 0)
mEnabled = 0;
}
update_delay();
ALOGD("AccelSensor enable %d ,usercount %d, handle %d ,mEnabled %d",en ,mUser, handle ,mEnabled);
return err;
}
int AccelSensor::setDelay(int32_t handle, int64_t ns) {
if (ns < 0)
return -EINVAL;
mDelay = ns;
return update_delay();
}
int AccelSensor::update_delay() {
return set_delay(mDelay);
}
int AccelSensor::readEvents(sensors_event_t* data, int count) {
if (count < 1)
return -EINVAL;
ssize_t n = mInputReader.fill(data_fd);
if (n < 0)
return n;
int numEventReceived = 0;
input_event const* event;
while (count && mInputReader.readEvent(&event)) {
int type = event->type;
if ((type == EV_ABS) || (type == EV_REL) || (type == EV_KEY)) {
processEvent(event->code, event->value);
mInputReader.next();
} else if (type == EV_SYN) {
int64_t time = timevalToNano(event->time);
if (mPendingMask) {
mPendingMask = 0;
mPendingEvent.timestamp = time;
if (mEnabled) {
*data++ = mPendingEvent;
count--;
numEventReceived++;
}
}
if (!mPendingMask) {
mInputReader.next();
}
} else {
ALOGE("AccelSensor: unknown event (type=%d, code=%d)",
type, event->code);
mInputReader.next();
}
}
return numEventReceived;
}
void AccelSensor::processEvent(int code, int value) {
switch (code) {
case ACC_EVENT_X :
mPendingMask = 1;
mPendingEvent.acceleration.x = ACC_DATA_CONVERSION(value);
break;
case ACC_EVENT_Y :
mPendingMask = 1;
mPendingEvent.acceleration.y = ACC_DATA_CONVERSION(value);
break;
case ACC_EVENT_Z :
mPendingMask = 1;
mPendingEvent.acceleration.z = ACC_DATA_CONVERSION(value);
break;
}
}
int AccelSensor::writeEnable(int isEnable) {
char attr[PATH_MAX] = {'\0'};
if(mClassPath[0] == '\0')
return -1;
strcpy(attr, mClassPath);
strcat(attr,"/");
strcat(attr,ACC_SYSFS_ENABLE);
int fd = open(attr, O_RDWR);
if (0 > fd) {
ALOGE("Could not open (write-only) SysFs attribute \"%s\" (%s).", attr, strerror(errno));
return -errno;
}
char buf[2];
if (isEnable) {
buf[0] = '1';
} else {
buf[0] = '0';
}
buf[1] = '\0';
int err = 0;
err = write(fd, buf, sizeof(buf));
if (0 > err) {
err = -errno;
ALOGE("Could not write SysFs attribute \"%s\" (%s).", attr, strerror(errno));
} else {
err = 0;
}
close(fd);
return err;
}
int AccelSensor::writeDelay(int64_t ns) {
char attr[PATH_MAX] = {'\0'};
if(mClassPath[0] == '\0')
return -1;
strcpy(attr, mClassPath);
strcat(attr,"/");
strcat(attr,ACC_SYSFS_DELAY);
int fd = open(attr, O_RDWR);
if (0 > fd) {
ALOGE("Could not open (write-only) SysFs attribute \"%s\" (%s).", attr, strerror(errno));
return -errno;
}
if (ns > 10240000000LL) {
ns = 10240000000LL; /* maximum delay in nano second. */
}
if (ns < 312500LL) {
ns = 312500LL; /* minimum delay in nano second. */
}
char buf[80];
sprintf(buf, "%lld", ns/1000/1000);
write(fd, buf, strlen(buf)+1);
close(fd);
return 0;
}
int AccelSensor::enable_sensor() {
return writeEnable(1);
}
int AccelSensor::disable_sensor() {
return writeEnable(0);
}
int AccelSensor::set_delay(int64_t ns) {
return writeDelay(ns);
}
int AccelSensor::getEnable(int32_t handle) {
return (handle == ID_A) ? mEnabled : 0;
}
int AccelSensor::sensor_get_class_path(char *class_path) {
char dirname[] = ACC_SYSFS_PATH;
char buf[256];
int res;
DIR *dir;
struct dirent *de;
int fd = -1;
int found = 0;
dir = opendir(dirname);
if (dir == NULL)
return -1;
while((de = readdir(dir))) {
if (strncmp(de->d_name, "input", strlen("input")) != 0) {
continue;
}
sprintf(class_path, "%s/%s", dirname, de->d_name);
snprintf(buf, sizeof(buf), "%s/name", class_path);
fd = open(buf, O_RDONLY);
if (fd < 0) {
continue;
}
if ((res = read(fd, buf, sizeof(buf))) < 0) {
close(fd);
continue;
}
buf[res - 1] = '\0';
if (strcmp(buf, ACC_DATA_NAME) == 0) {
found = 1;
close(fd);
break;
}
close(fd);
fd = -1;
}
closedir(dir);
//ALOGE("the G sensor dir is %s",class_path);
if (found) {
return 0;
}else {
*class_path = '\0';
return -1;
}
}
/*****************************************************************************/
Step 3: Cross-compile User Mode Test Routine
... #include <sys/ioctl.h> #include <fcntl.h> ... #define PSIO 'P' #define PS_IOCTL_GETDATA _IOR(PSIO, 0, int) #define PS_IOCTL_SETDATA _IOW(PSIO, 1, int) #define PS_IOCTL_GETPOS _IOR(PSIO, 2, int) #define PS_IOCTL_SETPOS _IOW(PSIO, 3, int) struct ps_data_axis{ short x; short y; short z; }; ... int main(int argc, char *argv[]) { struct ps_data_axis data; ... fd = open("/dev/psensor", O_RDWR); data.x = 0; data.y = 0; data.z = 16400; ioctl(fd, PS_IOCTL_SETDATA, &data); .... close(fd); ... }
Step 4: Test
root@android:/system/bin # dumpsys sensorservice Sensor List: Freescale 3-axis Accelerometer | Freescale Semiconductor Inc. | 0x00000000 | maxRate= 50.00Hz | last=< -5.9, 6.1, 0.0> Freescale 3-axis Magnetic field sensor | Freescale Semiconductor Inc. | 0x00000001 | maxRate= 10.00Hz | last=< 0.0, 0.0, 0.0> Freescale Orientation sensor | Freescale Semiconductor Inc. | 0x00000002 | maxRate= 10.00Hz | last=< 0.0, 0.0, 0.0> MPL3115 Temperature sensor | Freescale Semiconductor Inc. | 0x00000006 | maxRate= 0.00Hz | last=< 0.0, 0.0, 0.0> ISL29023 Light sensor | Intersil | 0x00000004 | maxRate= 0.00Hz | last=< 0.0, 0.0, 0.0> 9-axis fusion disabled (0 clients), gyro-rate= 0.00Hz, q=< 0, 0, 0, 0 > (0), b=< 0, 0, 0 > 5 h/w sensors: handle=0x00000000, active-count=1, rates(ms)={ 66.7 }, selected=66.7 ms handle=0x00000001, active-count=0, rates(ms)={ }, selected= 0.0 ms handle=0x00000002, active-count=0, rates(ms)={ }, selected= 0.0 ms handle=0x00000006, active-count=0, rates(ms)={ }, selected= 0.0 ms handle=0x00000004, active-count=0, rates(ms)={ }, selected= 0.0 ms 1 active connections Active sensors: Freescale 3-axis Accelerometer (handle=0x00000000, connections=1)
root@android:/system/bin/ # psensor_setdata -x1000 -y0 -z16400 PSENSOR_SETDATA, X=1000 Y=0 Z=16400 ... root@android:/system/bin # ./psensor_setdata -x50 -y10 -z10 PSENSOR_SETDATA, X=-10 Y=50 Z=10 root@android:/system/bin # ./psensor_setdata -x50 -y10 -z10 PSENSOR_SETDATA, X=-10 Y=50 Z=10
root@android:/ # find /sys -name position /sys/devices/virtual/input/input3/position root@android:/ # cat /sys/devices/virtual/input/input3/position 0 root@android:/ # root@android:/ # echo 1 > /sys/devices/virtual/input/input3/enable root@android:/ #
Psensor_getdata.c / Psensor_setdata.c
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdarg.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <signal.h>
#include <termios.h>
#include <netinet/tcp.h>
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
#include <sys/ioctl.h>
#include <fcntl.h>
/////////////////////////////////////////////////////////////////////////////////////////
//
#define PSIO 'P'
#define PS_IOCTL_GETDATA _IOR(PSIO, 0, int)
#define PS_IOCTL_SETDATA _IOW(PSIO, 1, int)
#define PS_IOCTL_GETPOS _IOR(PSIO, 2, int)
#define PS_IOCTL_SETPOS _IOW(PSIO, 3, int)
/////////////////////////////////////////////////////////////////////////////////////////
//
#define BUILD_UINT16(loByte, hiByte) \
((unsigned short)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8)))
#define BUILD_UINT32(Byte0, Byte1, Byte2, Byte3) \
((unsigned int)((unsigned int)((Byte0) & 0x00FF) + ((unsigned int)((Byte1) & 0x00FF) << 8) \
+ ((unsigned int)((Byte2) & 0x00FF) << 16) + ((unsigned int)((Byte3) & 0x00FF) << 24)))
#define HI_UINT16(a) (((a) >> 8) & 0xFF)
#define LO_UINT16(a) ((a) & 0xFF)
/////////////////////////////////////////////////////////////////////////////////////////
//
struct ps_data_axis {
short x;
short y;
short z;
};
void PrintUsage(void) {
char file[128];
int i = 0;
memset(file, 0, sizeof(file));
strcpy(file, __FILE__);
for (i = 0; i <128; i++)
if ('.' == file[i]) file[i] = 0;
printf("Example Usage: %s\n", file), exit(1);
}
int main(int argc, char *argv[]) {
struct ps_data_axis data;
int fd = -1;
int c;
setbuf(stdout, 0);
//if (argc < 3) PrintUsage();
while ((c = getopt(argc, argv, "x:y:z:")) != -1) {
switch (c) {
default:
break;
case '?':
PrintUsage();
break;
#if 0
case '?':
PrintUsage();
break;
case 'x':
if (strlen(optarg) > 0) {
x = atoi(optarg);
break;
}
PrintUsage();
break;
case 'y':
if (strlen(optarg) > 0) {
y = atoi(optarg);
break;
}
PrintUsage();
break;
case 'z':
if (strlen(optarg) > 0) {
z = atoi(optarg);
break;
}
PrintUsage();
break;
#endif
}
}
if ((fd = open("/dev/psensor", O_RDWR)) < 0) {
printf("(%s %d) OPEN /dev/psensor FAIL, EXIT !\n", __FILE__, __LINE__), exit(1);
return 1;
}
data.x = -101; data.y = -101; data.z = -101;
if(ioctl(fd, PS_IOCTL_GETDATA, &data) < 0) {
printf("(%s %d) PS_IOCTL_GETDATA FAIL, EXIT !\n", __FILE__, __LINE__), close(fd), exit(2);
return 1;
}
printf("PSENSOR_GETDATA, X=%d Y=%d Z=%d\n", data.x, data.y, data.z);
close(fd);
return 0;
}
#include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #include <stdarg.h> #include <stdlib.h> #include <time.h> #include <fcntl.h> #include <signal.h> #include <termios.h> #include <netinet/tcp.h> #include <string.h> #include <stdint.h> #include <inttypes.h> #include <sys/ioctl.h> #include <fcntl.h> //#include "list.h" ///////////////////////////////////////////////////////////////////////////////////////// // #define PSIO 'P' #define PS_IOCTL_GETDATA _IOR(PSIO, 0, int) #define PS_IOCTL_SETDATA _IOW(PSIO, 1, int) #define PS_IOCTL_GETPOS _IOR(PSIO, 2, int) #define PS_IOCTL_SETPOS _IOW(PSIO, 3, int) ///////////////////////////////////////////////////////////////////////////////////////// // #define BUILD_UINT16(loByte, hiByte) \ ((unsigned short)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8))) #define BUILD_UINT32(Byte0, Byte1, Byte2, Byte3) \ ((unsigned int)((unsigned int)((Byte0) & 0x00FF) + ((unsigned int)((Byte1) & 0x00FF) << 8) \ + ((unsigned int)((Byte2) & 0x00FF) << 16) + ((unsigned int)((Byte3) & 0x00FF) << 24))) #define HI_UINT16(a) (((a) >> 8) & 0xFF) #define LO_UINT16(a) ((a) & 0xFF) ///////////////////////////////////////////////////////////////////////////////////////// // struct ps_data_axis { short x; short y; short z; }; void PrintUsage(void) { char file[128]; int i = 0; memset(file, 0, sizeof(file)); strcpy(file, __FILE__); for (i = 0; i <128; i++) if ('.' == file[i]) file[i] = 0; printf("Example Usage: %s -x 100 -y 100 -z 100\n", file), exit(1); } int main(int argc, char *argv[]) { struct ps_data_axis data; int fd = -1; int c = 0; int x = 0, y = 0, z = 0; setbuf(stdout, 0); while ((c = getopt(argc, argv, "x:y:z:X:Y:Z:")) != -1) { switch (c) { default: break; case '?': PrintUsage(); break; case 'X': case 'x': if (strlen(optarg) > 0) { x = atoi(optarg); break; } PrintUsage(); break; case 'Y': case 'y': if (strlen(optarg) > 0) { y = atoi(optarg); break; } PrintUsage(); break; case 'Z': case 'z': if (strlen(optarg) > 0) { z = atoi(optarg); break; } PrintUsage(); break; } } if ((fd = open("/dev/psensor", O_RDWR)) < 0) { printf("(%s %d) OPEN /dev/psensor FAIL, EXIT !\n", __FILE__, __LINE__), exit(1); return 1; } data.x = x; data.y = y; data.z = z; if(ioctl(fd, PS_IOCTL_SETDATA, &data) < 0) { printf("(%s %d) PS_IOCTL_SETDATA FAIL, EXIT !\n", __FILE__, __LINE__), close(fd), exit(2); return 1; } data.x = -101; data.y = -101; data.z = -101; if(ioctl(fd, PS_IOCTL_GETDATA, &data) < 0) { printf("(%s %d) PS_IOCTL_GETDATA FAIL, EXIT !\n", __FILE__, __LINE__), close(fd), exit(2); return 1; } printf("PSENSOR_GETDATA, X=%d Y=%d Z=%d\n", data.x, data.y, data.z); close(fd); return 0; }
如果你覺得這篇文章對你有幫助, 請於留言板留個言, 以茲鼓勵. 謝謝! Email: jasonc@mail2000.com.tw
文章標籤
全站熱搜
留言列表