--- /dev/null
+/* --------------------------------------------------------------------------------------------------------\r
+ * Copyright(C), 2010-2011, Fuzhou Rockchip Co., Ltd. All Rights Reserved.\r
+ *\r
+ * File: custom_log.h \r
+ *\r
+ * Desc: ChenZhen Æ«ºÃµÄ log Êä³öµÄ¶¨ÖÆʵÏÖ. \r
+ *\r
+ * -----------------------------------------------------------------------------------\r
+ * < Ï°Óï ºÍ ËõÂÔÓï > : \r
+ *\r
+ * -----------------------------------------------------------------------------------\r
+ *\r
+ * Usage: µ÷Óñ¾ log »ú¹¹µÄ .c Îļþ, ÈôҪʹÄÜÕâÀïµÄ log »úÖÆ, \r
+ * Ôò±ØÐëÔÚ inclue ±¾Îļþ֮ǰ, "#define ENABLE_DEBUG_LOG" ÏÈ. \r
+ * Note:\r
+ *\r
+ * Author: ChenZhen\r
+ *\r
+ * --------------------------------------------------------------------------------------------------------\r
+ * Version:\r
+ * v1.0\r
+ * --------------------------------------------------------------------------------------------------------\r
+ * Log:\r
+ ----Fri Nov 19 15:20:28 2010 v1.0\r
+ * \r
+ * --------------------------------------------------------------------------------------------------------\r
+ */\r
+\r
+\r
+#ifndef __CUSTOM_LOG_H__\r
+#define __CUSTOM_LOG_H__\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/* ---------------------------------------------------------------------------------------------------------\r
+ * Include Files\r
+ * ---------------------------------------------------------------------------------------------------------\r
+ */\r
+#include <linux/kernel.h>\r
+\r
+\r
+/* ---------------------------------------------------------------------------------------------------------\r
+ * Macros Definition \r
+ * ---------------------------------------------------------------------------------------------------------\r
+ */\r
+ \r
+#ifdef ENABLE_DEBUG_LOG\r
+#define D(fmt, args...) \\r
+ { printk("[File]:%s; [Line]:%d; [Func]:%s(); " fmt "\n", __FILE__, __LINE__, __FUNCTION__, ## args); }\r
+#else\r
+#define D(...) ((void)0)\r
+#endif\r
+\r
+#define W(fmt, args...) \\r
+ { printk("WARNING :: [File]:%s; [Line]:%d; [Func]:%s() :: " fmt "\n", __FILE__, __LINE__, __FUNCTION__, ## args); }\r
+\r
+#define E(fmt, args...) \\r
+ { printk("ERROR :: [File]:%s; [Line]:%d; [Func]:%s() :: " fmt "\n", __FILE__, __LINE__, __FUNCTION__, ## args); }\r
+ \r
+\r
+\r
+/* ---------------------------------------------------------------------------------------------------------\r
+ * Types and Structures Definition\r
+ * --------------------------------------------------------------------------------------------------------- */\r
+\r
+\r
+/* ---------------------------------------------------------------------------------------------------------\r
+ * Global Functions' Prototype\r
+ * ---------------------------------------------------------------------------------------------------------\r
+ */\r
+\r
+\r
+/* ---------------------------------------------------------------------------------------------------------\r
+ * Inline Functions Implementation \r
+ * ---------------------------------------------------------------------------------------------------------\r
+ */\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* __CUSTOM_LOG_H__ */\r
+\r
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>
+#include <asm/atomic.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/workqueue.h>
#include <linux/earlysuspend.h>
#endif
-#if 0
-#define mmaprintk(x...) printk(x)
+// #define ENABLE_DEBUG_LOG
+#include <mach/custom_log.h>
+
+#if 1
+#define mmaprintk(x...) D(x)
#else
#define mmaprintk(x...)
#endif
+
+// #define ENABLE_VERBOSE_LOG
+#ifdef ENABLE_VERBOSE_LOG
+#define V(x...) D(x)
+#else
+#define V(x...)
+#endif
+
static int mma8452_probe(struct i2c_client *client, const struct i2c_device_id *id);
#define MMA8452_SPEED 200 * 1000
static struct early_suspend mma8452_early_suspend;
#endif
static int revision = -1;
+static const char* vendor = "Freescale Semiconductor";
+
+
+typedef char status_t;
+/*status*/
+#define MMA8452_OPEN 1
+#define MMA8452_CLOSE 0
+
+
+// .! : É豸ʵÀýÊý¾ÝÀàÐÍ.
+struct mma8452_data {
+ status_t status;
+ char curr_tate;
+ struct input_dev *input_dev;
+ struct i2c_client *client;
+ struct work_struct work;
+ struct delayed_work delaywork; /*report second event*/
+
+ /** »º´æ sensor Êý¾Ý. */
+ struct mma8452_axis sense_data;
+ /** ¶Ô "sense_data" µÄ»¥³â±£»¤. */
+ struct mutex sense_data_mutex;
+
+ /** ±êʶ "sense_data" ÖеÄÊý¾ÝÊÇ·ñÓÐЧ. */
+ atomic_t data_ready;
+ /** ÓÃÀ´µÈ´ý Êý¾Ý ready µÄµÈ´ý¶ÓÁÐÍ·. */
+ wait_queue_head_t data_ready_wq;
+
+ /** ±êʶ É豸±»ÒªÇó START ²É¼¯Êý¾ÝµÄ´ÎÊý, ¶ÔÓ¦ MMA_IOCTL_START ¿ÉÄܱ»µ÷Óöà´ÎµÄÇé¿ö. */
+ int start_count;
+ /** ¶Ô 'start_count' ºÍÏà¹Ø²Ù×÷µÄ»¥³â±£»¤. */
+ struct mutex operation_mutex;
+};
+
/* AKM HW info */
static ssize_t gsensor_vendor_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t ret = 0;
- sprintf(buf, "%#x\n", revision);
+ // sprintf(buf, "%#x\n", revision);
+ sprintf(buf, "%s.\n", vendor);
ret = strlen(buf) + 1;
return ret;
goto err;
}
- ret = sysfs_create_file(android_gsensor_kobj, &dev_attr_vendor.attr);
+ ret = sysfs_create_file(android_gsensor_kobj, &dev_attr_vendor.attr); // "vendor"
if (ret) {
mmaprintk(KERN_ERR
"MMA8452 gsensor_sysfs_init:"\
{
int ret = 0;
int tmp;
- struct mma8452_data *mma8452 = (struct mma8452_data *)i2c_get_clientdata(client);
+ struct mma8452_data *mma8452 = (struct mma8452_data *)i2c_get_clientdata(client); // mma8452_data ¶¨ÒåÔÚ mma8452.h ÖÐ.
mmaprintk("-------------------------mma8452 start ------------------------\n");
/* standby */
input_report_abs(mma8452->input_dev, ABS_Y, axis->y);
input_report_abs(mma8452->input_dev, ABS_Z, axis->z);
input_sync(mma8452->input_dev);
- mmaprintk("Gsensor x==%d y==%d z==%d\n",axis->x,axis->y,axis->z);
+ V("Gsensor x==%d y==%d z==%d\n",axis->x,axis->y,axis->z);
}
+/** ÔÚ µ×°ë²¿Ö´ÐÐ, ¾ßÌå»ñÈ¡ g sensor Êý¾Ý. */
static int mma8452_get_data(struct i2c_client *client)
{
+ struct mma8452_data* mma8452 = i2c_get_clientdata(client);
char buffer[6];
int ret;
struct mma8452_axis axis;
return ret;
} while (0);
- mmaprintk("0x%02x 0x%02x 0x%02x \n",buffer[0],buffer[1],buffer[2]);
+ V("0x%02x 0x%02x 0x%02x \n",buffer[0],buffer[1],buffer[2]);
axis.x = mma8452_convert_to_int(buffer[0]);
axis.y = mma8452_convert_to_int(buffer[1]);
swap(axis.x,axis.y);
}
- // mmaprintk( "%s: ------------------mma8452_GetData axis = %d %d %d--------------\n",
- // __func__, axis.x, axis.y, axis.z);
+ V( "%s: ------------------mma8452_GetData axis = %d %d %d--------------\n",
+ __func__, axis.x, axis.y, axis.z);
//memcpy(sense_data, &axis, sizeof(axis));
mma8452_report_value(client, &axis);
//atomic_set(&data_ready, 0);
//wake_up(&data_ready_wq);
+ /* »¥³âµØ»º´æÊý¾Ý. */
+ mutex_lock(&(mma8452->sense_data_mutex) );
+ mma8452->sense_data = axis;
+ mutex_unlock(&(mma8452->sense_data_mutex) );
+
+ /* ÖÃλ data_ready */
+ atomic_set(&(mma8452->data_ready), 1);
+ /* »½ÐÑ data_ready µÈ´ý¶ÓÁÐÍ·. */
+ wake_up(&(mma8452->data_ready_wq) );
+
return 0;
}
}
*/
+/**
+ * »ñÈ¡µ±Ç°ÒѾ cache Á赀 sensor Êý¾Ý.
+ * @param sense_data
+ * Ö¸Ïò·µ»ØÓà buffer.
+ * @param client
+ * µ±Ç° i2c client É豸ʵÀýÊý¾ÝµÄÖ¸Õë.
+ * @return
+ * Èô³É¹¦, ·µ»Ø 0; ·ñÔò, ·µ»ØÆäËü.
+ */
+static int mma8452_get_cached_data(struct i2c_client* client, struct mma8452_axis* sense_data)
+{
+ struct mma8452_data* this = (struct mma8452_data *)i2c_get_clientdata(client);
+
+ /* Óг¬Ê±µØ, µÈ´ýÊý¾Ý ready. */
+ wait_event_interruptible_timeout(this->data_ready_wq,
+ atomic_read(&(this->data_ready) ),
+ msecs_to_jiffies(1000) );
+ /* Èô³¬Ê±, ÇÒÊý¾ÝûÓÐ ready. */
+ if ( 0 == atomic_read(&(this->data_ready) ) ) {
+ E("waiting 'data_ready_wq' timed out.");
+ /* ·µ»Ø error. */
+ return -1;
+ }
+ /* Êý¾ÝÒѾ ready, »¥³âµØ·µ»ØÊý¾Ý. */
+ mutex_lock(&(this->sense_data_mutex) );
+ *sense_data = this->sense_data;
+ mutex_unlock(&(this->sense_data_mutex) );
+ /* ·µ»Ø. */
+ return 0;
+}
+
static int mma8452_open(struct inode *inode, struct file *file)
{
return 0;//nonseekable_open(inode, file);
{
void __user *argp = (void __user *)arg;
- char msg[RBUFF_SIZE + 1];
+ // char msg[RBUFF_SIZE + 1];
+ struct mma8452_axis sense_data = {0};
int ret = -1;
char rate;
struct i2c_client *client = container_of(mma8452_device.parent, struct i2c_client, dev);
+ struct mma8452_data* this = (struct mma8452_data *)i2c_get_clientdata(client); /* É豸Êý¾ÝʵÀýµÄÖ¸Õë. */
switch (cmd) {
- case ECS_IOCTL_APP_SET_RATE:
+ case MMA_IOCTL_APP_SET_RATE:
if (copy_from_user(&rate, argp, sizeof(rate)))
return -EFAULT;
break;
}
switch (cmd) {
- case ECS_IOCTL_START:
- ret = mma8452_start(client, MMA8452_RATE_12P5);
- if (ret < 0)
- return ret;
- break;
- case ECS_IOCTL_CLOSE:
- ret = mma8452_close(client);
- if (ret < 0)
- return ret;
- break;
- case ECS_IOCTL_APP_SET_RATE:
+ case MMA_IOCTL_START:
+ /* ÉÏËø. */
+ mutex_lock(&(this->operation_mutex) );
+ D("to perform 'MMA_IOCTL_START', former 'start_count' is %d.", this->start_count);
+ /* ¼ÇÊý ×Ô¼Ó. */
+ (this->start_count)++;
+ /* ÈôÊdzõ´Î start, Ôò... */
+ if ( 1 == this->start_count ) {
+ /* ¸´Î» data_ready. */
+ atomic_set(&(this->data_ready), 0);
+ /* Ö´ÐоßÌåµÄ¶ÔÓ²¼þµÄÆô¶¯²Ù×÷. */
+ if ( (ret = mma8452_start(client, MMA8452_RATE_12P5) ) < 0 ) {
+ mutex_unlock(&(this->operation_mutex) );
+ return ret;
+ }
+ }
+ /* ½âËø. */
+ mutex_unlock(&(this->operation_mutex) );
+ D("finish 'MMA_IOCTL_START', ret = %d.", ret);
+ /* ·µ»Ø. */
+ return 0;
+
+ case MMA_IOCTL_CLOSE:
+ /* ÉÏËø. */
+ mutex_lock(&(this->operation_mutex) );
+ D("to perform 'MMA_IOCTL_CLOSE', former 'start_count' is %d, PID : %d", this->start_count, get_current()->pid);
+ /* Èô¼ÇÊý×Ô¼õµ½ 0, Ôò... */
+ if ( 0 == (--(this->start_count) ) ) {
+ /* ¸´Î» data_ready. */
+ atomic_set(&(this->data_ready), 0);
+ /* Ö´ÐоßÌåµÄ¶ÔÓ²¼þµÄ stop ²Ù×÷. */
+ if ( (ret = mma8452_close(client) ) < 0 ) {
+ mutex_unlock(&(this->operation_mutex) );
+ return ret;
+ }
+ }
+ /* ½âËø. */
+ mutex_unlock(&(this->operation_mutex) );
+ /* ·µ»Ø. */
+ return 0;
+
+ case MMA_IOCTL_APP_SET_RATE:
ret = mma8452_reset_rate(client, rate);
if (ret < 0)
return ret;
break;
- /*
- case ECS_IOCTL_GETDATA:
- ret = mma8452_trans_buff(msg, RBUFF_SIZE);
- if (ret < 0)
+ case MMA_IOCTL_GETDATA:
+ // ret = mma8452_trans_buff(msg, RBUFF_SIZE);
+ if ( (ret = mma8452_get_cached_data(client, &sense_data) ) < 0 ) {
+ E("failed to get cached sense data, ret = %d.", ret);
return ret;
+ }
break;
- */
default:
return -ENOTTY;
}
switch (cmd) {
- case ECS_IOCTL_GETDATA:
+ case MMA_IOCTL_GETDATA:
+ /*
if (copy_to_user(argp, &msg, sizeof(msg)))
return -EFAULT;
+ */
+ if ( copy_to_user(argp, &sense_data, sizeof(sense_data) ) ) {
+ D("failed to copy sense data to user space.");
+ return -EFAULT;
+ }
break;
default:
break;
struct i2c_client *client = mma8452->client;
if (mma8452_get_data(client) < 0)
- mmaprintk(KERN_ERR "MMA8452 mma_work_func: Get data failed\n");
- mmaprintk("%s :int src:0x%02x\n",__FUNCTION__,mma845x_read_reg(mma8452->client,MMA8452_REG_INTSRC));
+ E(KERN_ERR "MMA8452 mma_work_func: Get data failed\n");
+ V("%s :int src:0x%02x\n",__FUNCTION__,mma845x_read_reg(mma8452->client,MMA8452_REG_INTSRC));
enable_irq(client->irq);
}
struct mma8452_data *mma8452 = (struct mma8452_data *)dev_id;
disable_irq_nosync(irq);
+ /* .! : ÑÓ³ÙµØÔÚ µ×°ë²¿ ·¢ÆðºóÐø²Ù×÷(¶ÁÈ¡¾ßÌåÊý¾Ý). */
schedule_delayed_work(&mma8452->delaywork, msecs_to_jiffies(30));
- mmaprintk("%s :enter\n",__FUNCTION__);
+ V("%s :enter\n",__FUNCTION__);
return IRQ_HANDLED;
}
.ioctl = mma8452_ioctl,
};
+/** ¿ØÖÆÉ豸. */
static struct miscdevice mma8452_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = "mma8452_daemon",//"mma8452_daemon",
{ }
};
+/** ±íÕ÷Çý¶¯µÄÊý¾ÝÀàÐͶ¨Òå. */
static struct i2c_driver mma8452_driver = {
.driver = {
.name = "gs_mma8452",
},
.id_table = mma8452_id,
- .probe = mma8452_probe,
+ .probe = mma8452_probe, // .!! : ¶Ô probe() µÄµ÷ÓÃ, ÈÔÊÇÓÉ ×¢²áÉ豸µÄ²Ù×÷´¥·¢µÄ,
+ // ¾ßÌå²Î¼û board-rk29sdk.c ÖÐµÄ board_i2c0_devices.
+ // ÔÚ board_i2c0_devices ÖÐÉùÃ÷ÁËÒ»¸ö¿ÉÒÔʹÓÃÃû³ÆÊÇ "gs_mma8452" Çý¶¯³ÌÐòµÄ I2C É豸.
+ // ͬʱҲÌåÏÖÁË I2C µØÖ· ºÍ Öն˺ŵÈÐÅÏ¢.
.remove = __devexit_p(mma8452_remove),
#ifndef CONFIG_HAS_EARLYSUSPEND
.suspend = &mma8452_suspend,
register_early_suspend(&mma8452_early_suspend);
#endif
- mma8452->status = -1;
printk(KERN_INFO "mma8452 probe ok\n");
+ memset(&(mma8452->sense_data), 0, sizeof(struct mma8452_axis) );
+ mutex_init(&(mma8452->sense_data_mutex) );
+
+ atomic_set(&(mma8452->data_ready), 0);
+ init_waitqueue_head(&(mma8452->data_ready_wq) );
+
+ mma8452->start_count = 0;
+ mutex_init(&(mma8452->operation_mutex) );
+
+ // mma8452->status = -1;
+ mma8452->status = MMA8452_CLOSE;
#if 0
// mma8452_start_test(this_client);
mma8452_start(client, MMA8452_RATE_12P5);
exit_alloc_data_failed:
;
mmaprintk("%s error\n",__FUNCTION__);
- return err;
+ return -1;
}
#include "ak8975.h"
#define AKM8975_DEBUG 1
-#define AKM8975_DEBUG_MSG 1
+#define AKM8975_DEBUG_MSG 0
#define AKM8975_DEBUG_FUNC 0
#define AKM8975_DEBUG_DATA 0
#define MAX_FAILURE_COUNT 3
{
char buffer[2];
+ AKMDBG("enter %s\n", __func__);
+
atomic_set(&data_ready, 0);
/* Set measure mode */
static int AKECS_SetMode_SelfTest(void)
{
char buffer[2];
+ AKMDBG("enter %s\n", __func__);
/* Set measure mode */
buffer[0] = AK8975_REG_CNTL;
static int AKECS_SetMode_FUSEAccess(void)
{
char buffer[2];
+ AKMDBG("enter %s\n", __func__);
/* Set measure mode */
buffer[0] = AK8975_REG_CNTL;
static int AKECS_SetMode_PowerDown(void)
{
char buffer[2];
+ AKMDBG("enter %s\n", __func__);
/* Set powerdown mode */
buffer[0] = AK8975_REG_CNTL;
static int AKECS_SetMode(char mode)
{
int ret;
+ AKMDBG("enter %s\n", __func__);
switch (mode) {
case AK8975_MODE_SNG_MEASURE:
{
char buffer[2];
int ret;
+ AKMDBG("enter %s\n", __func__);
/* Set measure mode */
buffer[0] = AK8975_REG_WIA;
return -EINVAL;
}
#endif
+ AKMDBG("enter %s\n", __func__);
wait_event_interruptible_timeout(data_ready_wq,
atomic_read(&data_ready), 1000);
if (!atomic_read(&data_ready)) {
printk(KERN_INFO " Geomagnetism[LSB]: %6d,%6d,%6d\n",
rbuf[9], rbuf[10], rbuf[11]);
#endif
+ AKMDBG("enter %s\n", __func__);
/* Report magnetic sensor information */
if (atomic_read(&m_flag)) {
input_report_abs(data->input_dev, ABS_RX, rbuf[0]);
static int AKECS_GetOpenStatus(void)
{
+ AKMDBG("enter %s\n", __func__);
wait_event_interruptible(open_wq, (atomic_read(&open_flag) != 0));
return atomic_read(&open_flag);
}
static int AKECS_GetCloseStatus(void)
{
+ AKMDBG("enter %s\n", __func__);
wait_event_interruptible(open_wq, (atomic_read(&open_flag) <= 0));
return atomic_read(&open_flag);
}
static void AKECS_CloseDone(void)
{
+ AKMDBG("enter %s\n", __func__);
atomic_set(&m_flag, 1);
atomic_set(&a_flag, 1);
atomic_set(&mv_flag, 1);
{
void __user *argp = (void __user *)arg;
short flag;
+ AKMDBG("enter %s\n", __func__);
switch (cmd) {
case ECS_IOCTL_APP_SET_MFLAG:
unsigned long arg)
{
void __user *argp = (void __user *)arg;
+ AKMDBG("enter %s\n", __func__);
/* NOTE: In this function the size of "char" should be 1-byte. */
char sData[SENSOR_DATA_SIZE];/* for GETDATA */
{
char buffer[SENSOR_DATA_SIZE];
int ret;
+ AKMDBG("enter %s\n", __func__);
memset(buffer, 0, SENSOR_DATA_SIZE);
buffer[0] = AK8975_REG_ST1;
{
struct akm8975_data *data = dev_id;
AKMFUNC("akm8975_interrupt");
- disable_irq(this_client->irq);
+ disable_irq_nosync(this_client->irq);
schedule_work(&data->work);
+ AKMDBG("exit %s\n", __func__);
return IRQ_HANDLED;
}
dev_dbg(&akm->client->dev, "no IRQ?\n");
return -ENODEV;
}else{
+ AKMDBG("gpio %d to irq %d\n", akm->eoc_irq, gpio_to_irq(akm->eoc_irq));
akm->eoc_irq = gpio_to_irq(akm->eoc_irq);
}
err = gpio_request(client->irq, "ak_8975");
if (err < 0) {
dev_err(&client->dev, "failed to request GPIO, error %d\n", err);
goto exit3;
- }
+ }
+
+ err = gpio_direction_input(client->irq);
+ if (err) {
+ dev_err(&client->dev, "failed to set GPIO direction, error %d\n", err);
+ goto exit3;
+ }
+ gpio_pull_updown(client->irq, GPIOPullDown);
+
/* IRQ */
err = request_irq(akm->eoc_irq, akm8975_interrupt, IRQ_TYPE_EDGE_RISING,
"akm8975_DRDY", akm);
goto exit4;
}
+ client->irq = akm->eoc_irq;
+
/* Declare input device */
akm->input_dev = input_allocate_device();
if (!akm->input_dev) {