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;
}

 

 

 

 

 

 

z.png
如果你覺得這篇文章對你有幫助, 請於留言板留個言, 以茲鼓勵. 謝謝! Email: jasonc@mail2000.com.tw

 

 

 

 

 

arrow
arrow
    創作者介紹
    創作者 Lexra 的頭像
    Lexra

    Lexra Pixnet

    Lexra 發表在 痞客邦 留言(0) 人氣()