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 = &reg;
+       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

Reply via email to