Index: linux-2.6.35/drivers/misc/mpu3050/mpu-i2c.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.35/drivers/misc/mpu3050/mpu-i2c.c 2010-12-24
11:43:59.000000000 +0800
@@ -0,0 +1,187 @@
+/*
+ $License:
+ Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+ 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, see
<http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/i2c.h>
+#include "mpu.h"
+
+int sensor_i2c_write(struct i2c_adapter *i2c_adap,
+ unsigned char address,
+ unsigned int len, unsigned char const *data)
+{
+ struct i2c_msg msgs[1];
+ int res;
+
+ if (NULL == data || NULL == i2c_adap)
+ return -EINVAL;
+
+ msgs[0].addr = address;
+ msgs[0].flags = 0; /* write */
+ msgs[0].buf = (unsigned char *) data;
+ msgs[0].len = len;
+
+ res = i2c_transfer(i2c_adap, msgs, 1);
+ if (res < 1)
+ return res;
+ else
+ return 0;
+}
+
+int sensor_i2c_write_register(struct i2c_adapter *i2c_adap,
+ unsigned char address,
+ unsigned char reg, unsigned char value)
+{
+ unsigned char data[2];
+
+ data[0] = reg;
+ data[1] = value;
+ return sensor_i2c_write(i2c_adap, address, 2, data);
+}
+
+int sensor_i2c_read(struct i2c_adapter *i2c_adap,
+ unsigned char address,
+ unsigned char reg,
+ unsigned int len, unsigned char *data)
+{
+ struct i2c_msg msgs[2];
+ int res;
+
+ if (NULL == data || NULL == i2c_adap)
+ return -EINVAL;
+
+ msgs[0].addr = address;
+ msgs[0].flags = 0; /* write */
+ msgs[0].buf = ®
+ msgs[0].len = 1;
+
+ msgs[1].addr = address;
+ msgs[1].flags = I2C_M_RD;
+ msgs[1].buf = data;
+ msgs[1].len = len;
+
+ res = i2c_transfer(i2c_adap, msgs, 2);
+ if (res < 2)
+ return res;
+ else
+ return 0;
+}
+
+int mpu_memory_read(struct i2c_adapter *i2c_adap,
+ unsigned char mpu_addr,
+ unsigned short mem_addr,
+ unsigned int len, unsigned char *data)
+{
+ unsigned char bank[2];
+ unsigned char addr[2];
+ unsigned char buf;
+
+ struct i2c_msg msgs[1];
+ int ret;
+
+ if (NULL == data || NULL == i2c_adap)
+ return -EINVAL;
+
+ bank[0] = MPUREG_BANK_SEL;
+ bank[1] = mem_addr >> 8;
+
+ addr[0] = MPUREG_MEM_START_ADDR;
+ addr[1] = mem_addr & 0xFF;
+
+ buf = MPUREG_MEM_R_W;
+
+ /* Write Message */
+ msgs[0].addr = mpu_addr;
+ msgs[0].flags = 0;
+ msgs[0].buf = bank;
+ msgs[0].len = sizeof(bank);
+ ret = i2c_transfer(i2c_adap, msgs, 1);
+
+ msgs[0].addr = mpu_addr;
+ msgs[0].flags = 0;
+ msgs[0].buf = addr;
+ msgs[0].len = sizeof(addr);
+ ret = i2c_transfer(i2c_adap, msgs, 1);
+
+ msgs[0].addr = mpu_addr;
+ msgs[0].flags = 0;
+ msgs[0].buf = &buf;
+ msgs[0].len = 1;
+ ret = i2c_transfer(i2c_adap, msgs, 1);
+
+ msgs[0].addr = mpu_addr;
+ msgs[0].flags = I2C_M_RD;
+ msgs[0].buf = data;
+ msgs[0].len = len;
+
+ ret = i2c_transfer(i2c_adap, msgs, 1);
+ if (ret != 1)
+ return ret;
+ else
+ return 0;
+}
+
+int mpu_memory_write(struct i2c_adapter *i2c_adap,
+ unsigned char mpu_addr,
+ unsigned short mem_addr,
+ unsigned int len, unsigned char const *data)
+{
+ unsigned char bank[2];
+ unsigned char addr[2];
+ unsigned char buf[513];
+
+ struct i2c_msg msgs[1];
+ int ret;
+
+ if (NULL == data || NULL == i2c_adap)
+ return -EINVAL;
+ if (len >= (sizeof(buf) - 1))
+ return -ENOMEM;
+
+ bank[0] = MPUREG_BANK_SEL;
+ bank[1] = mem_addr >> 8;
+
+ addr[0] = MPUREG_MEM_START_ADDR;
+ addr[1] = mem_addr & 0xFF;
+
+ buf[0] = MPUREG_MEM_R_W;
+
+ memcpy(buf + 1, data, len);
+
+ /* Write Message */
+ msgs[0].addr = mpu_addr;
+ msgs[0].flags = 0;
+ msgs[0].buf = bank;
+ msgs[0].len = sizeof(bank);
+ ret = i2c_transfer(i2c_adap, msgs, 1);
+
+ msgs[0].addr = mpu_addr;
+ msgs[0].flags = 0;
+ msgs[0].buf = addr;
+ msgs[0].len = sizeof(addr);
+ ret = i2c_transfer(i2c_adap, msgs, 1);
+
+ msgs[0].addr = mpu_addr;
+ msgs[0].flags = 0;
+ msgs[0].buf = (unsigned char *) buf;
+ msgs[0].len = len + 1;
+
+ ret = i2c_transfer(i2c_adap, msgs, 1);
+ if (ret != 1)
+ return ret;
+ else
+ return 0;
+}
Index: linux-2.6.35/drivers/misc/mpu3050/mpuirq.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.35/drivers/misc/mpu3050/mpuirq.c 2010-12-24
11:45:22.000000000 +0800
@@ -0,0 +1,459 @@
+/*
+ $License:
+ Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+ 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, see
<http://www.gnu.org/licenses/>.
+ */
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/stat.h>
+#include <linux/irq.h>
+#include <linux/signal.h>
+#include <linux/miscdevice.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/workqueue.h>
+#include <linux/poll.h>
+#include <linux/input.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#include "mpu.h"
+#include "mpuirq.h"
+#include "mldl_cfg.h"
+#include "mlsl.h"
+#include "mpu-i2c.h"
+#include "accel/bma023.h"
+
+#define MPUIRQ_NAME "mpuirq"
+
+/* function which gets accel data and sends it to MPU */
+
+DECLARE_WAIT_QUEUE_HEAD(mpuirq_wait);
+DECLARE_WAIT_QUEUE_HEAD(accelirq_wait);
+
+static DEFINE_SPINLOCK(accel_lock);
+
+struct mpuirq_dev_data {
+ struct work_struct work;
+ struct i2c_client *mpu_client;
+ struct miscdevice *dev;
+ int irq;
+ int pid;
+ int accel_divider;
+ int data_ready;
+ int timeout;
+};
+
+struct accelirq_dev_data {
+ struct work_struct work;
+ struct i2c_client *mpu_client;
+ struct input_dev *accel_input;
+ int irq;
+ int data_ready;
+ int timeout;
+ int freq;
+};
+
+static struct mpuirq_dev_data mpuirq_dev_data;
+static struct accelirq_dev_data accelirq_dev_data;
+static struct mpuirq_data mpuirq_data;
+static char *interface = MPUIRQ_NAME;
+
+static void mpu_accel_data_work_fcn(struct work_struct *work);
+static void accel_data_work_fcn(struct work_struct *work);
+
+static int accel_input_open(struct input_dev *input){
+ struct mldl_cfg *mldl_cfg = (struct mldl_cfg *)
i2c_get_clientdata(accelirq_dev_data.mpu_client);
+ struct accel_config *aconfig = accel_get_config();
+ aconfig->enable_count_hg_lg = 0x02;
+ mpu3050_suspend(mldl_cfg, accelirq_dev_data.mpu_client->adapter,
+
i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num),
+
i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num),
+ 1, 1);
+ mldl_cfg->accel->resume(accelirq_dev_data.mpu_client->adapter,
+ mldl_cfg->accel,
+
&mldl_cfg->pdata->accel);
+ aconfig->enable_count_hg_lg = 0x00;
+ return 0;
+}
+
+static void accel_input_close(struct input_dev *input){
+ struct mldl_cfg *mldl_cfg = (struct mldl_cfg *)
i2c_get_clientdata(accelirq_dev_data.mpu_client);
+ mpu3050_suspend(mldl_cfg, accelirq_dev_data.mpu_client->adapter,
+
i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num),
+
i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num),
+ 1, 0);
+}
+
+static int accel_input_init(void){
+ int res = 0;
+ accelirq_dev_data.accel_input = input_allocate_device();
+ if(!accelirq_dev_data.accel_input){
+ res = -ENOMEM;
+ printk(KERN_ERR "%s: accel input device memory alloc
failed\n",__func__);
+ goto error;
+ }
+ set_bit(EV_ABS, accelirq_dev_data.accel_input->evbit);
+ accelirq_dev_data.accel_input->name = "bma023_accel";
+ accelirq_dev_data.accel_input->id.bustype = BUS_I2C;
+ accelirq_dev_data.accel_input->id.product = 0x69;
+ accelirq_dev_data.accel_input->open = accel_input_open;
+ accelirq_dev_data.accel_input->close = accel_input_close;
+// accelirq_dev_data.accel_input->phys = "accel/input0";
+ input_set_abs_params(accelirq_dev_data.accel_input, ABS_X, -255,
255, 0, 0);
+ input_set_abs_params(accelirq_dev_data.accel_input, ABS_Y, -255,
255, 0, 0);
+ input_set_abs_params(accelirq_dev_data.accel_input, ABS_Z, -255,
255, 0, 0);
+
+ res = input_register_device(accelirq_dev_data.accel_input);
+ if(res){
+ printk(KERN_ERR "%s: accel input device register
failed\n",__func__);
+ goto reg_fail;
+ }
+ return res;
+reg_fail:
+ input_unregister_device(accelirq_dev_data.accel_input);
+error:
+ return res;
+}
+
+
+static int mpuirq_open(struct inode *inode, struct file *file)
+{
+ dev_dbg(mpuirq_dev_data.dev->this_device,
+ "%s current->pid %d\n", __func__, current->pid);
+ mpuirq_dev_data.pid = current->pid;
+ file->private_data = &mpuirq_dev_data;
+ /* we could do some checking on the flags supplied by "open" */
+ /* i.e. O_NONBLOCK */
+ /* -> set some flag to disable interruptible_sleep_on in
mpuirq_read */
+ return 0;
+}
+
+/* close function - called when the "file" /dev/mpuirq is closed in
userspace */
+static int mpuirq_release(struct inode *inode, struct file *file)
+{
+ dev_dbg(mpuirq_dev_data.dev->this_device, "mpuirq_release\n");
+ return 0;
+}
+
+/* read function called when from /dev/mpuirq is read */
+static ssize_t mpuirq_read(struct file *file,
+ char *buf, size_t count, loff_t * ppos)
+{
+ int len, err;
+ struct mpuirq_dev_data *p_mpuirq_dev_data = file->private_data;
+
+ if (!mpuirq_dev_data.data_ready) {
+ wait_event_interruptible_timeout(mpuirq_wait,
+ mpuirq_dev_data.
+ data_ready,
+
mpuirq_dev_data.timeout);
+ }
+
+ if (mpuirq_dev_data.data_ready && NULL != buf
+ && count >= sizeof(mpuirq_data)) {
+ err = copy_to_user(buf, &mpuirq_data,
sizeof(mpuirq_data));
+ } else {
+ return 0;
+ }
+ if (err != 0) {
+ dev_err(p_mpuirq_dev_data->dev->this_device,
+ "Copy to user returned %d\n", err);
+ return -EFAULT;
+ }
+ mpuirq_dev_data.data_ready = 0;
+ len = sizeof(mpuirq_data);
+ return len;
+}
+
+unsigned int mpuirq_poll(struct file *file, struct poll_table_struct
*poll)
+{
+ int mask = 0;
+ struct mpuirq_dev_data *p_mpuirq_dev_data = file->private_data;
+
+ poll_wait(file, &mpuirq_wait, poll);
+ if (mpuirq_dev_data.data_ready)
+ mask |= POLLIN | POLLRDNORM;
+ dev_dbg(p_mpuirq_dev_data->dev->this_device,
+ "%s: returning %d\n", __func__, mask);
+ return mask;
+}
+
+/* ioctl - I/O control */
+static long mpuirq_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int retval = 0;
+ int data;
+
+ switch (cmd) {
+ case MPUIRQ_SET_TIMEOUT:
+ mpuirq_dev_data.timeout = arg;
+ break;
+
+ case MPUIRQ_GET_INTERRUPT_CNT:
+ data = mpuirq_data.interruptcount - 1;
+ if (mpuirq_data.interruptcount > 1)
+ mpuirq_data.interruptcount = 1;
+
+ if (copy_to_user((int *) arg, &data, sizeof(int)))
+ return -EFAULT;
+ break;
+ case MPUIRQ_GET_IRQ_TIME:
+ if (copy_to_user((int *) arg, &mpuirq_data.irqtime,
+ sizeof(mpuirq_data.irqtime)))
+ return -EFAULT;
+ mpuirq_data.irqtime = 0;
+ break;
+ case MPUIRQ_SET_FREQUENCY_DIVIDER:
+ mpuirq_dev_data.accel_divider = arg;
+ break;
+ default:
+ retval = -EINVAL;
+ }
+ return retval;
+}
+
+static void accel_data_work_fcn(struct work_struct *work){
+ signed short axis_data[3];
+ struct accelirq_dev_data *irq_dev_data =
+ (struct accelirq_dev_data *) work;
+ struct mldl_cfg *mldl_cfg = (struct mldl_cfg *)
+ i2c_get_clientdata(irq_dev_data->mpu_client);
+ struct i2c_adapter *accel_adapter;
+ accel_adapter =
i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
+ if(bma023_read_accel_xyz(accel_adapter, mldl_cfg, axis_data) <
0){
+ printk("accel work: read xyz of accel failed\n");
+ return;
+ }
+ input_event(irq_dev_data->accel_input, EV_ABS, ABS_X,
axis_data[0]);
+ input_event(irq_dev_data->accel_input, EV_ABS, ABS_Y,
axis_data[1]);
+ input_event(irq_dev_data->accel_input, EV_ABS, ABS_Z,
axis_data[2]);
+ input_sync(irq_dev_data->accel_input);
+}
+static void mpu_accel_data_work_fcn(struct work_struct *work)
+{
+ struct mpuirq_dev_data *mpuirq_dev_data =
+ (struct mpuirq_dev_data *) work;
+ struct mldl_cfg *mldl_cfg =
+ (struct mldl_cfg *)
+ i2c_get_clientdata(mpuirq_dev_data->mpu_client);
+ struct i2c_adapter *accel_adapter;
+ unsigned char wbuff[16];
+ unsigned char rbuff[16];
+ int ii;
+
+ accel_adapter =
i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
+ mldl_cfg->accel->read(accel_adapter,
+ mldl_cfg->accel,
+ &mldl_cfg->pdata->accel, rbuff);
+
+
+ /* @todo add other data formats here as well */
+ if (EXT_SLAVE_BIG_ENDIAN == mldl_cfg->accel->endian) {
+ for (ii = 0; ii < 3; ii++) {
+ wbuff[2 * ii + 1] = rbuff[2 * ii + 1];
+ wbuff[2 * ii + 2] = rbuff[2 * ii + 0];
+ }
+ } else {
+ memcpy(wbuff + 1, rbuff, mldl_cfg->accel->len);
+ }
+
+ wbuff[7] = 0;
+ wbuff[8] = 1; /*set semaphore */
+
+ mpu_memory_write(mpuirq_dev_data->mpu_client->adapter,
+ mldl_cfg->addr, 0x0108, 8, wbuff);
+}
+
+static irqreturn_t accelirq_handler(int irq, void *dev_id)
+{
+ static int accel_count;
+ static unsigned long flags;
+ accel_count++;
+ if(!(accelirq_dev_data.freq > 0))
+ return -1;
+ spin_lock_irqsave(&accel_lock, flags);
+ if(accel_count % accelirq_dev_data.freq == 0){
+ accel_count &= 0;
+ schedule_work((struct work_struct *)
(&accelirq_dev_data));
+ }
+ spin_unlock_irqrestore(&accel_lock, flags);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mpuirq_handler(int irq, void *dev_id)
+{
+ static int mycount;
+ struct timeval irqtime;
+ mycount++;
+
+ mpuirq_data.interruptcount++;
+
+ /* wake up (unblock) for reading data from userspace */
+ /* and ignore first interrupt generated in module init */
+ if (mpuirq_data.interruptcount > 1) {
+ mpuirq_dev_data.data_ready = 1;
+
+ do_gettimeofday(&irqtime);
+ mpuirq_data.irqtime = (((long long) irqtime.tv_sec) <<
32);
+ mpuirq_data.irqtime += irqtime.tv_usec;
+
+ if ((mpuirq_dev_data.accel_divider >= 0) &&
+ (0 ==
+ (mycount % (mpuirq_dev_data.accel_divider + 1)))) {
+ schedule_work((struct work_struct
+ *) (&mpuirq_dev_data));
+ }
+
+ wake_up_interruptible(&mpuirq_wait);
+ }
+
+ return IRQ_HANDLED;
+
+}
+
+/* define which file operations are supported */
+const struct file_operations mpuirq_fops = {
+ .owner = THIS_MODULE,
+ .read = mpuirq_read,
+ .poll = mpuirq_poll,
+ .compat_ioctl = mpuirq_ioctl,
+ .unlocked_ioctl = mpuirq_ioctl,
+ .open = mpuirq_open,
+ .release = mpuirq_release,
+};
+
+static struct miscdevice mpuirq_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = MPUIRQ_NAME,
+ .fops = &mpuirq_fops,
+};
+
+int mpuirq_init(struct i2c_client *mpu_client)
+{
+ int res;
+ struct mldl_cfg *mldl_cfg =
+ (struct mldl_cfg *) i2c_get_clientdata(mpu_client);
+
+ /* work_struct initialization */
+ INIT_WORK((struct work_struct *) &mpuirq_dev_data,
+ mpu_accel_data_work_fcn);
+ INIT_WORK((struct work_struct *) &accelirq_dev_data,
+ accel_data_work_fcn);
+
+ mpuirq_dev_data.mpu_client = mpu_client;
+ accelirq_dev_data.mpu_client = mpu_client;
+
+ dev_info(&mpu_client->adapter->dev,
+ "Module Param interface = %s\n", interface);
+
+ accelirq_dev_data.irq = 299;
+ accelirq_dev_data.data_ready = 0;
+ accelirq_dev_data.timeout = 0;
+ accelirq_dev_data.freq = 1;
+
+ if(mldl_cfg->accel){
+ if (accelirq_dev_data.irq) {
+ res = request_irq(accelirq_dev_data.irq,
+
accelirq_handler,
+
(IRQF_TRIGGER_RISING),
+ "accel_irq", &accelirq_dev_data.irq);
+ if (res) {
+ dev_err(&mpu_client->adapter->dev,
+ "accel: cannot register
IRQ %d\n", accelirq_dev_data.irq);
+ } else {
+ res = accel_input_init();
+ if(res)
+
dev_err(&mpu_client->adapter->dev,
+
"accel_input_register returned %d\n", res);
+ }
+ } else {
+ printk(KERN_ERR "accel irq: cannot regist irq
%d\n", accelirq_dev_data.irq);
+ res = 0;
+ }
+ } else {
+ printk(KERN_ERR "accel irq: No Accel\n");
+ res = 0;
+ }
+
+ mpuirq_dev_data.irq = mpu_client->irq;
+ mpuirq_dev_data.pid = 0;
+ mpuirq_dev_data.accel_divider = -1;
+ mpuirq_dev_data.data_ready = 0;
+ mpuirq_dev_data.timeout = 0;
+ mpuirq_dev_data.dev = &mpuirq_device;
+
+ if (mpuirq_dev_data.irq) {
+ unsigned long flags;
+ if (BIT_ACTL_LOW ==
+ ((mldl_cfg->pdata->int_config) & BIT_ACTL))
+ flags = IRQF_TRIGGER_FALLING;
+ else
+ flags = IRQF_TRIGGER_RISING;
+
+ res =
+ request_irq(mpuirq_dev_data.irq, mpuirq_handler,
flags,
+ interface, &mpuirq_dev_data.irq);
+ if (res) {
+ dev_err(&mpu_client->adapter->dev,
+ "myirqtest: cannot register IRQ %d\n",
+ mpuirq_dev_data.irq);
+ } else {
+ res = misc_register(&mpuirq_device);
+ if (res < 0) {
+ dev_err(&mpu_client->adapter->dev,
+ "misc_register returned %d\n",
+ res);
+ free_irq(mpuirq_dev_data.irq,
+ &mpuirq_dev_data.irq);
+ }
+ }
+ } else {
+ res = 0;
+ }
+ return res;
+}
+
+void mpuirq_exit(void)
+{
+ /* Free the IRQ first before flushing the work */
+ if (mpuirq_dev_data.irq > 0)
+ free_irq(mpuirq_dev_data.irq, &mpuirq_dev_data.irq);
+
+ if (accelirq_dev_data.irq > 0)
+ free_irq(accelirq_dev_data.irq, &accelirq_dev_data.irq);
+
+ flush_scheduled_work();
+ input_unregister_device(accelirq_dev_data.accel_input);
+
+ dev_info(mpuirq_device.this_device, "Unregistering %s\n",
+ MPUIRQ_NAME);
+ misc_deregister(&mpuirq_device);
+
+ return;
+}
+
+module_param(interface, charp, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(interface, "The Interface name");
Index: linux-2.6.35/drivers/misc/mpu3050/mpu-sysfs.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.35/drivers/misc/mpu3050/mpu-sysfs.c 2010-12-24
11:48:52.000000000 +0800
@@ -0,0 +1,352 @@
+/*
+ mpu-sysfs.c - mpu3050 sysfs interface
+
+ 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, see
<http://www.gnu.org/licenses/>.
+*/
+
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/ctype.h>
+
+#include "mpu-i2c.h"
+#include "mldl_cfg.h"
+#include "mpu.h"
+#include "accel/bma023.h"
+
+#include <linux/kobject.h>
+
+#define COMPASS_PWR_REG 0x1B
+
+static struct i2c_adapter *accel_adapter;
+static struct i2c_adapter *compass_adapter;
+static struct ext_slave_descr* accel_slave_descr;
+static const char *msg[] = {"off","on"};
+struct i2c_client *this_client;
+
+
+static ssize_t show_driver_version_value(struct device *dev, struct
device_attribute *attr, char *buf){
+ return sprintf(buf, "%s\n", DRIVER_VERSION);
+}
+static ssize_t show_gyro_data_value(struct device *dev, struct
device_attribute *attr, char *buf){
+ unsigned char data[6];
+ signed short x, y, z;
+ MLSLSerialRead(this_client->adapter, this_client->addr,
MPUREG_GYRO_XOUT_H, 6, data);
+ x = data[0];
+ x = x<<8 | data[1];
+ y = data[2];
+ y = y<<8 | data[3];
+ z = data[4];
+ z = z<<8 | data[5];
+ return sprintf(buf, "%d %d %d\n", x, y, z);
+}
+
+static ssize_t show_gyro_x_standby_value(struct device *dev, struct
device_attribute *attr, char *buf){
+ char data;
+ MLSLSerialRead(this_client->adapter, this_client->addr,
MPUREG_PWR_MGM, 1, &data);
+ return sprintf(buf, "%s\n", msg[(data&BIT_STBY_XG)?1:0]);
+}
+
+static ssize_t store_gyro_x_standby_value(struct device *dev, struct
device_attribute *attr, const char *buf, size_t count){
+ char data;
+ if(!count) return count;
+ MLSLSerialRead(this_client->adapter, this_client->addr,
MPUREG_PWR_MGM, 1, &data);
+ if(buf[0] == '1')
+ MLSLSerialWriteSingle( this_client->adapter,
this_client->addr, MPUREG_PWR_MGM, data | BIT_STBY_XG );
+ else if(buf[0] == '0')
+ MLSLSerialWriteSingle( this_client->adapter,
this_client->addr, MPUREG_PWR_MGM, data & ~BIT_STBY_XG);
+ else
+ printk("error: invalid command %s for
gyro_x_standby\n",buf);
+ return count;
+}
+
+static ssize_t show_gyro_y_standby_value(struct device *dev, struct
device_attribute *attr, char *buf){
+ char data;
+ MLSLSerialRead(this_client->adapter, this_client->addr,
MPUREG_PWR_MGM, 1, &data);
+ return sprintf(buf, "%s\n", msg[(data&BIT_STBY_YG)?1:0]);
+}
+
+static ssize_t store_gyro_y_standby_value(struct device *dev, struct
device_attribute *attr, const char *buf, size_t count){
+ char data;
+ if(!count) return count;
+ MLSLSerialRead(this_client->adapter, this_client->addr,
MPUREG_PWR_MGM, 1, &data);
+ if(buf[0] == '1')
+ MLSLSerialWriteSingle( this_client->adapter,
this_client->addr, MPUREG_PWR_MGM, data | BIT_STBY_YG );
+ else if(buf[0] == '0')
+ MLSLSerialWriteSingle( this_client->adapter,
this_client->addr, MPUREG_PWR_MGM, data & ~BIT_STBY_YG);
+ else
+ printk("error: invalid command %s for
gyro_y_standby\n",buf);
+ return count;
+}
+
+static ssize_t show_gyro_z_standby_value(struct device *dev, struct
device_attribute *attr, char *buf){
+ char data;
+ MLSLSerialRead(this_client->adapter, this_client->addr,
MPUREG_PWR_MGM, 1, &data);
+ return sprintf(buf, "%s\n", msg[(data&BIT_STBY_ZG)?1:0]);
+}
+
+static ssize_t store_gyro_z_standby_value(struct device *dev, struct
device_attribute *attr, const char *buf, size_t count){
+ char data;
+ if(!count) return count;
+ MLSLSerialRead(this_client->adapter, this_client->addr,
MPUREG_PWR_MGM, 1, &data);
+ if(buf[0] == '1')
+ MLSLSerialWriteSingle( this_client->adapter,
this_client->addr, MPUREG_PWR_MGM, data | BIT_STBY_ZG );
+ else if(buf[0] == '0')
+ MLSLSerialWriteSingle( this_client->adapter,
this_client->addr, MPUREG_PWR_MGM, data & ~BIT_STBY_ZG);
+ else
+ printk("error: invalid command %s for
gyro_z_standby\n",buf);
+ return count;
+}
+
+static ssize_t show_gyro_power_mode_value(struct device *dev, struct
device_attribute *attr, char *buf){
+ char data;
+ MLSLSerialRead(this_client->adapter, this_client->addr,
MPUREG_PWR_MGM, 1, &data);
+ data &= BIT_SLEEP;
+ return sprintf(buf, "%s\n", data? msg[0] : msg[1]);
+}
+
+static ssize_t store_gyro_power_mode_value(struct device *dev, struct
device_attribute *attr, const char *buf, size_t count){
+ struct mldl_cfg *mldl_cfg =
+ (struct mldl_cfg *) i2c_get_clientdata(this_client);
+ if(!count) return count;
+ if(buf[0] == '1')
+ mpu3050_resume(mldl_cfg, this_client->adapter,
accel_adapter, compass_adapter, 0, 0);
+ else if(buf[0] == '0')
+ mpu3050_suspend(mldl_cfg, this_client->adapter,
accel_adapter, compass_adapter, 0, 0);
+ else
+ printk("error: invalid command %s for
gyro_power_mode\n",buf);
+ return count;
+}
+
+#ifdef CONFIG_SENSORS_BMA023
+static ssize_t show_accel_name_value(struct device *dev, struct
device_attribute *attr, char *buf){
+ struct mldl_cfg *mldl_cfg =
+ (struct mldl_cfg *) i2c_get_clientdata(this_client);
+ return sprintf(buf, "%s\n", (mldl_cfg->accel) ?
mldl_cfg->accel->name : "No Accel");
+}
+
+static ssize_t show_accel_data_value(struct device *dev, struct
device_attribute *attr, char *buf){
+ signed short xyz_axes[3];
+ struct mldl_cfg *mldl_cfg =
+ (struct mldl_cfg *) i2c_get_clientdata(this_client);
+ if(!accel_adapter)
+ return sprintf(buf, "No Accel\n");
+ if(bma023_read_accel_xyz(accel_adapter, mldl_cfg, xyz_axes))
+ return sprintf(buf, "Can't get axes data\n");
+ return sprintf(buf, "%d,%d,%d\n", xyz_axes[0], xyz_axes[1],
xyz_axes[2]);
+}
+
+static ssize_t show_accel_power_mode_value(struct device *dev, struct
device_attribute *attr, char *buf){
+ struct mldl_cfg *mldl_cfg =
+ (struct mldl_cfg *) i2c_get_clientdata(this_client);
+ if(!accel_adapter)
+ return sprintf(buf, "No Accel\n");
+ return sprintf(buf, "%s\n", bma023_get_power_mode(accel_adapter,
mldl_cfg) ? msg[0] : msg[1]);
+}
+
+static ssize_t store_accel_power_mode_value(struct device *dev, struct
device_attribute *attr, const char *buf, size_t count){
+ struct mldl_cfg *mldl_cfg =
+ (struct mldl_cfg *) i2c_get_clientdata(this_client);
+ if(!count && !accel_adapter) return count;
+ if(buf[0] == '1')
+ mldl_cfg->accel->resume(accel_adapter, mldl_cfg->accel,
&mldl_cfg->pdata->accel);
+ else if(buf[0] == '0')
+ mldl_cfg->accel->suspend(accel_adapter, mldl_cfg->accel,
&mldl_cfg->pdata->accel);
+ else
+ printk("error: invalid command %s for
accel_power_mode\n",buf);
+ return count;
+}
+
+static ssize_t show_accel_bw_value(struct device *dev, struct
device_attribute *attr, char *buf){
+ if(!accel_adapter)
+ return sprintf(buf, "No Accel\n");
+ return sprintf(buf, "%d Hz\n", bma023_get_bandwidth());
+}
+
+static ssize_t store_accel_bw_value(struct device *dev, struct
device_attribute *attr, const char *buf, size_t count){
+ int ret;
+ if(!count && !accel_adapter) return count;
+ ret = bma023_set_bandwidth(accel_adapter, buf);
+ if(ret < 0)
+ printk("accel bw set failed\n");
+ return count;
+}
+
+static ssize_t show_accel_range_value(struct device *dev, struct
device_attribute *attr, char *buf){
+ if(!accel_adapter)
+ return sprintf(buf, "No Accel\n");
+ return sprintf(buf, "%d g\n", bma023_get_range());
+}
+
+static ssize_t store_accel_range_value(struct device *dev, struct
device_attribute *attr, const char *buf, size_t count){
+ int ret;
+ if(!count && !accel_adapter) return count;
+ ret = bma023_set_range(accel_adapter, buf);
+ if(ret < 0)
+ printk("accel range set failed\n");
+ return count;
+}
+
+static ssize_t show_accel_h_dur_value(struct device *dev, struct
device_attribute *ay25ttr, char *buf){
+ struct accel_config *aconfig = accel_get_config();
+ if(!accel_adapter)
+ return sprintf(buf, "No Accel\n");
+ return sprintf(buf, "%d\n", aconfig->hg_dur);
+}
+
+static ssize_t store_accel_h_dur_value(struct device *dev, struct
device_attribute *attr, const char *buf, size_t count){
+ if(!count && !accel_adapter) return count;
+ if(bma023_set_hg_duration(accel_adapter, buf) < 0)
+ printk("accel hg duration set failed\n");
+ return count;
+}
+
+static ssize_t show_accel_h_thres_value(struct device *dev, struct
device_attribute *attr, char *buf){
+ struct accel_config *aconfig = accel_get_config();
+ if(!accel_adapter)
+ return sprintf(buf, "No Accel\n");
+ return sprintf(buf, "%d\n", aconfig->hg_thres);
+}
+
+static ssize_t store_accel_h_thres_value(struct device *dev, struct
device_attribute *attr, const char *buf, size_t count){
+ if(!count && !accel_adapter) return count;
+ if(bma023_set_hg_threshold(accel_adapter, buf) < 0)
+ printk("accel hg threshold set failed\n");
+ return count;
+}
+
+static ssize_t show_accel_l_dur_value(struct device *dev, struct
device_attribute *ay25ttr, char *buf){
+ struct accel_config *aconfig = accel_get_config();
+ if(!accel_adapter)
+ return sprintf(buf, "No Accel\n");
+ return sprintf(buf, "%d\n", aconfig->lg_dur);
+}
+
+static ssize_t store_accel_l_dur_value(struct device *dev, struct
device_attribute *attr, const char *buf, size_t count){
+ if(!count && !accel_adapter) return count;
+ if(bma023_set_lg_duration(accel_adapter, buf) < 0)
+ printk("accel lg duration set failed\n");
+ return count;
+}
+
+static ssize_t show_accel_l_thres_value(struct device *dev, struct
device_attribute *attr, char *buf){
+ struct accel_config *aconfig = accel_get_config();
+ if(!accel_adapter)
+ return sprintf(buf, "No Accel\n");
+ return sprintf(buf, "%d\n", aconfig->lg_thres);
+}
+
+static ssize_t store_accel_l_thres_value(struct device *dev, struct
device_attribute *attr, const char *buf, size_t count){
+ if(!count && !accel_adapter) return count;
+ if(bma023_set_lg_threshold(accel_adapter, buf) < 0)
+ printk("accel lg threshold set failed\n");
+ return count;
+}
+#endif
+#ifndef CONFIG_SENSORS_COMPASS_NONE
+static ssize_t show_compass_name_value(struct device *dev, struct
device_attribute *attr, char *buf){
+ struct mldl_cfg *mldl_cfg =
+ (struct mldl_cfg *) i2c_get_clientdata(this_client);
+ return sprintf(buf, "%s\n", (mldl_cfg->compass) ?
mldl_cfg->compass->name : "No Compass");
+}
+
+static ssize_t store_compass_power_mode_value(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count){
+ struct mldl_cfg *mldl_cfg =
+ (struct mldl_cfg *) i2c_get_clientdata(this_client);
+ if(!count && !compass_adapter) return count;
+ if(buf[0] == '1')
+ mldl_cfg->compass->resume(compass_adapter,
mldl_cfg->compass, &mldl_cfg->pdata->compass);
+ else if(buf[0] == '0')
+ mldl_cfg->compass->suspend(compass_adapter,
mldl_cfg->compass, &mldl_cfg->pdata->compass);
+ else
+ printk("error: invalid command %s for
compass_power_mode\n",buf);
+ return count;
+}
+#endif
+
+static DEVICE_ATTR(version, S_IRUGO, show_driver_version_value, NULL);
+static DEVICE_ATTR(gyro_data, S_IRUGO, show_gyro_data_value, NULL);
+static DEVICE_ATTR(gyro_x_standby, S_IRUGO | S_IWUSR,
show_gyro_x_standby_value, store_gyro_x_standby_value );
+static DEVICE_ATTR(gyro_y_standby, S_IRUGO | S_IWUSR,
show_gyro_y_standby_value, store_gyro_y_standby_value );
+static DEVICE_ATTR(gyro_z_standby, S_IRUGO | S_IWUSR,
show_gyro_z_standby_value, store_gyro_z_standby_value );
+static DEVICE_ATTR(gyro_power_mode, S_IRUGO | S_IWUSR,
show_gyro_power_mode_value, store_gyro_power_mode_value );
+#ifdef CONFIG_SENSORS_BMA023
+static DEVICE_ATTR(accel_name, S_IRUGO, show_accel_name_value, NULL );
+static DEVICE_ATTR(accel_data, S_IRUGO, show_accel_data_value, NULL);
+static DEVICE_ATTR(accel_power_mode, S_IRUGO | S_IWUSR,
show_accel_power_mode_value, store_accel_power_mode_value );
+static DEVICE_ATTR(accel_bw, S_IRUGO | S_IWUSR, show_accel_bw_value,
store_accel_bw_value );
+static DEVICE_ATTR(accel_range, S_IRUGO | S_IWUSR,
show_accel_range_value, store_accel_range_value );
+static DEVICE_ATTR(accel_h_dur, S_IRUGO | S_IWUSR,
show_accel_h_dur_value, store_accel_h_dur_value );
+static DEVICE_ATTR(accel_h_thres, S_IRUGO | S_IWUSR,
show_accel_h_thres_value, store_accel_h_thres_value );
+static DEVICE_ATTR(accel_l_dur, S_IRUGO | S_IWUSR,
show_accel_l_dur_value, store_accel_l_dur_value );
+static DEVICE_ATTR(accel_l_thres, S_IRUGO | S_IWUSR,
show_accel_l_thres_value, store_accel_l_thres_value );
+#endif
+#ifndef CONFIG_SENSORS_COMPASS_NONE
+static DEVICE_ATTR(compass_name, S_IRUGO, show_compass_name_value, NULL
);
+static DEVICE_ATTR(compass_power_mode, S_IWUSR, NULL,
store_compass_power_mode_value );
+#endif
+
+static struct attribute *mpu3050_attributes[] = {
+ &dev_attr_version.attr,
+ &dev_attr_gyro_data.attr,
+ &dev_attr_gyro_x_standby.attr,
+ &dev_attr_gyro_y_standby.attr,
+ &dev_attr_gyro_z_standby.attr,
+ &dev_attr_gyro_power_mode.attr,
+#ifdef CONFIG_SENSORS_BMA023
+ &dev_attr_accel_name.attr,
+ &dev_attr_accel_data.attr,
+ &dev_attr_accel_power_mode.attr,
+ &dev_attr_accel_bw.attr,
+ &dev_attr_accel_range.attr,
+ &dev_attr_accel_h_dur.attr,
+ &dev_attr_accel_h_thres.attr,
+ &dev_attr_accel_l_dur.attr,
+ &dev_attr_accel_l_thres.attr,
+#endif
+#ifndef CONFIG_SENSORS_COMPASS_NONE
+ &dev_attr_compass_name.attr,
+ &dev_attr_compass_power_mode.attr,
+#endif
+ NULL
+};
+
+
+static struct attribute_group mpu3050_attribute_group = {
+ .attrs = mpu3050_attributes
+};
+
+int mpu_sysfs_init(struct i2c_client *client){
+ int res;
+ struct mldl_cfg *mldl_cfg =
+ (struct mldl_cfg *) i2c_get_clientdata(client);
+ this_client = client;
+ if(mldl_cfg->accel)
+ accel_adapter =
i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
+ if(mldl_cfg->compass)
+ compass_adapter =
i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
+
+ accel_slave_descr = get_accel_slave_descr();
+
+ res = sysfs_create_group(&client->dev.kobj,
&mpu3050_attribute_group);
+ if(res)
+ return -1;
+ return 0;
+}
+EXPORT_SYMBOL(mpu_sysfs_init);
+
+void mpu_sysfs_exit(void){
+ sysfs_remove_group(&this_client->dev.kobj,
&mpu3050_attribute_group);
+}
+EXPORT_SYMBOL(mpu_sysfs_exit);
+
Index: linux-2.6.35/drivers/misc/mpu3050/mlsl-kernel.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.35/drivers/misc/mpu3050/mlsl-kernel.c 2010-12-24
11:28:40.000000000 +0800
@@ -0,0 +1,328 @@
+/*
+ $License:
+ Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
+
+ 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, see
<http://www.gnu.org/licenses/>.
+ $
+ */
+
+#include "mlsl.h"
+#include "mpu-i2c.h"
+
+/* ------------ */
+/* - Defines. - */
+/* ------------ */
+
+/* ---------------------- */
+/* - Types definitions. - */
+/* ---------------------- */
+
+/* --------------------- */
+/* - Function p-types. - */
+/* --------------------- */
+
+/**
+ * @brief used to open the I2C or SPI serial port.
+ * This port is used to send and receive data to the MPU
device.
+ * @param portNum
+ * The COM port number associated with the device in use.
+ * @return ML_SUCCESS if successful, a non-zero error code otherwise.
+ */
+tMLError MLSLSerialOpen(char const *port, void ** sl_handle)
+{
+ return ML_SUCCESS;
+}
+
+/**
+ * @brief used to reset any buffering the driver may be doing
+ * @return ML_SUCCESS if successful, a non-zero error code otherwise.
+ */
+tMLError MLSLSerialReset(void *sl_handle)
+{
+ return ML_SUCCESS;
+}
+
+/**
+ * @brief used to close the I2C or SPI serial port.
+ * This port is used to send and receive data to the MPU
device.
+ * @return ML_SUCCESS if successful, a non-zero error code otherwise.
+ */
+tMLError MLSLSerialClose(void *sl_handle)
+{
+ return ML_SUCCESS;
+}
+
+/**
+ * @brief used to read a single byte of data.
+ * This should be sent by I2C or SPI.
+ *
+ * @param slaveAddr I2C slave address of device.
+ * @param registerAddr Register address to read.
+ * @param data Single byte of data to read.
+ *
+ * @return ML_SUCCESS if the command is successful, an error code
otherwise.
+ */
+tMLError MLSLSerialWriteSingle(void *sl_handle,
+ unsigned char slaveAddr,
+ unsigned char registerAddr,
+ unsigned char data)
+{
+ return sensor_i2c_write_register((struct i2c_adapter *)
sl_handle,
+ slaveAddr, registerAddr, data);
+}
+
+
+/**
+ * @brief used to write multiple bytes of data from registers.
+ * This should be sent by I2C.
+ *
+ * @param slaveAddr I2C slave address of device.
+ * @param registerAddr Register address to write.
+ * @param length Length of burst of data.
+ * @param data Pointer to block of data.
+ *
+ * @return ML_SUCCESS if successful, a non-zero error code otherwise.
+ */
+tMLError MLSLSerialWrite(void *sl_handle,
+ unsigned char slaveAddr,
+ unsigned short length, unsigned char const
*data)
+{
+ tMLError result;
+ const unsigned short dataLength = length - 1;
+ const unsigned char startRegAddr = data[0];
+ unsigned char i2cWrite[SERIAL_MAX_TRANSFER_SIZE + 1];
+ unsigned short bytesWritten = 0;
+
+ while (bytesWritten < dataLength) {
+ unsigned short thisLen = min(SERIAL_MAX_TRANSFER_SIZE,
+ dataLength - bytesWritten);
+ if (bytesWritten == 0) {
+ result = sensor_i2c_write((struct i2c_adapter *)
+ sl_handle, slaveAddr,
+ 1 + thisLen, data);
+ } else {
+ /* manually increment register addr between
chunks */
+ i2cWrite[0] = startRegAddr + bytesWritten;
+ memcpy(&i2cWrite[1], &data[1 + bytesWritten],
+ thisLen);
+ result = sensor_i2c_write((struct i2c_adapter *)
+ sl_handle, slaveAddr,
+ 1 + thisLen,
i2cWrite);
+ }
+ if (ML_SUCCESS != result)
+ return result;
+ bytesWritten += thisLen;
+ }
+ return ML_SUCCESS;
+}
+
+
+/**
+ * @brief used to read multiple bytes of data from registers.
+ * This should be sent by I2C.
+ *
+ * @param slaveAddr I2C slave address of device.
+ * @param registerAddr Register address to read.
+ * @param length Length of burst of data.
+ * @param data Pointer to block of data.
+ *
+ * @return Zero if successful; an error code otherwise
+ */
+tMLError MLSLSerialRead(void *sl_handle,
+ unsigned char slaveAddr,
+ unsigned char registerAddr,
+ unsigned short length, unsigned char *data)
+{
+ tMLError result;
+ unsigned short bytesRead = 0;
+
+ if (registerAddr == MPUREG_FIFO_R_W
+ || registerAddr == MPUREG_MEM_R_W) {
+ return ML_ERROR_INVALID_PARAMETER;
+ }
+ while (bytesRead < length) {
+ unsigned short thisLen =
+ min(SERIAL_MAX_TRANSFER_SIZE, length - bytesRead);
+ result =
+ sensor_i2c_read((struct i2c_adapter *) sl_handle,
+ slaveAddr, registerAddr + bytesRead,
+ thisLen, &data[bytesRead]);
+ if (ML_SUCCESS != result)
+ return result;
+ bytesRead += thisLen;
+ }
+ return ML_SUCCESS;
+}
+
+
+/**
+ * @brief used to write multiple bytes of data to the memory.
+ * This should be sent by I2C.
+ *
+ * @param slaveAddr I2C slave address of device.
+ * @param memAddr The location in the memory to write to.
+ * @param length Length of burst data.
+ * @param data Pointer to block of data.
+ *
+ * @return Zero if successful; an error code otherwise
+ */
+tMLError MLSLSerialWriteMem(void *sl_handle,
+ unsigned char slaveAddr,
+ unsigned short memAddr,
+ unsigned short length,
+ unsigned char const *data)
+{
+ tMLError result;
+ unsigned short bytesWritten = 0;
+
+ if ((memAddr & 0xFF) + length > MPU_MEM_BANK_SIZE) {
+ printk
+ ("memory read length (%d B) extends beyond its
limits (%d) "
+ "if started at location %d\n", length,
+ MPU_MEM_BANK_SIZE, memAddr & 0xFF);
+ return ML_ERROR_INVALID_PARAMETER;
+ }
+ while (bytesWritten < length) {
+ unsigned short thisLen =
+ min(SERIAL_MAX_TRANSFER_SIZE, length -
bytesWritten);
+ result =
+ mpu_memory_write((struct i2c_adapter *) sl_handle,
+ slaveAddr, memAddr + bytesWritten,
+ thisLen, &data[bytesWritten]);
+ if (ML_SUCCESS != result)
+ return result;
+ bytesWritten += thisLen;
+ }
+ return ML_SUCCESS;
+}
+
+
+/**
+ * @brief used to read multiple bytes of data from the memory.
+ * This should be sent by I2C.
+ *
+ * @param slaveAddr I2C slave address of device.
+ * @param memAddr The location in the memory to read from.
+ * @param length Length of burst data.
+ * @param data Pointer to block of data.
+ *
+ * @return Zero if successful; an error code otherwise
+ */
+tMLError MLSLSerialReadMem(void *sl_handle,
+ unsigned char slaveAddr,
+ unsigned short memAddr,
+ unsigned short length, unsigned char *data)
+{
+ tMLError result;
+ unsigned short bytesRead = 0;
+
+ if ((memAddr & 0xFF) + length > MPU_MEM_BANK_SIZE) {
+ printk
+ ("memory read length (%d B) extends beyond its
limits (%d) "
+ "if started at location %d\n", length,
+ MPU_MEM_BANK_SIZE, memAddr & 0xFF);
+ return ML_ERROR_INVALID_PARAMETER;
+ }
+ while (bytesRead < length) {
+ unsigned short thisLen =
+ min(SERIAL_MAX_TRANSFER_SIZE, length - bytesRead);
+ result =
+ mpu_memory_read((struct i2c_adapter *) sl_handle,
+ slaveAddr, memAddr + bytesRead,
+ thisLen, &data[bytesRead]);
+ if (ML_SUCCESS != result)
+ return result;
+ bytesRead += thisLen;
+ }
+ return ML_SUCCESS;
+}
+
+
+/**
+ * @brief used to write multiple bytes of data to the fifo.
+ * This should be sent by I2C.
+ *
+ * @param slaveAddr I2C slave address of device.
+ * @param length Length of burst of data.
+ * @param data Pointer to block of data.
+ *
+ * @return Zero if successful; an error code otherwise
+ */
+tMLError MLSLSerialWriteFifo(void *sl_handle,
+ unsigned char slaveAddr,
+ unsigned short length,
+ unsigned char const *data)
+{
+ tMLError result;
+ unsigned char i2cWrite[SERIAL_MAX_TRANSFER_SIZE + 1];
+ unsigned short bytesWritten = 0;
+
+ if (length > FIFO_HW_SIZE) {
+ printk(KERN_ERR
+ "maximum fifo write length is %d\n",
FIFO_HW_SIZE);
+ return ML_ERROR_INVALID_PARAMETER;
+ }
+ while (bytesWritten < length) {
+ unsigned short thisLen =
+ min(SERIAL_MAX_TRANSFER_SIZE, length -
bytesWritten);
+ i2cWrite[0] = MPUREG_FIFO_R_W;
+ memcpy(&i2cWrite[1], &data[bytesWritten], thisLen);
+ result = sensor_i2c_write((struct i2c_adapter *)
sl_handle,
+ slaveAddr, thisLen + 1,
+ i2cWrite);
+ if (ML_SUCCESS != result)
+ return result;
+ bytesWritten += thisLen;
+ }
+ return ML_SUCCESS;
+}
+
+
+/**
+ * @brief used to read multiple bytes of data from the fifo.
+ * This should be sent by I2C.
+ *
+ * @param slaveAddr I2C slave address of device.
+ * @param length Length of burst of data.
+ * @param data Pointer to block of data.
+ *
+ * @return Zero if successful; an error code otherwise
+ */
+tMLError MLSLSerialReadFifo(void *sl_handle,
+ unsigned char slaveAddr,
+ unsigned short length, unsigned char *data)
+{
+ tMLError result;
+ unsigned short bytesRead = 0;
+
+ if (length > FIFO_HW_SIZE) {
+ printk(KERN_ERR
+ "maximum fifo read length is %d\n",
FIFO_HW_SIZE);
+ return ML_ERROR_INVALID_PARAMETER;
+ }
+ while (bytesRead < length) {
+ unsigned short thisLen =
+ min(SERIAL_MAX_TRANSFER_SIZE, length - bytesRead);
+ result =
+ sensor_i2c_read((struct i2c_adapter *) sl_handle,
+ slaveAddr, MPUREG_FIFO_R_W, thisLen,
+ &data[bytesRead]);
+ if (ML_SUCCESS != result)
+ return result;
+ bytesRead += thisLen;
+ }
+
+ return ML_SUCCESS;
+}
+
_______________________________________________
MeeGo-kernel mailing list
[email protected]
http://lists.meego.com/listinfo/meego-kernel