Index: drivers/input/mouse/cypress_i2c.c |
diff --git a/drivers/input/mouse/cypress_i2c.c b/drivers/input/mouse/cypress_i2c.c |
index 7bda162fef646251393a5c4e80cf781433f995a3..98d6dc94549144a62a2a058187b443a870fca824 100644 |
--- a/drivers/input/mouse/cypress_i2c.c |
+++ b/drivers/input/mouse/cypress_i2c.c |
@@ -11,6 +11,8 @@ |
#include <linux/module.h> |
+#include <linux/init.h> |
+#include <linux/kernel.h> |
#include <linux/i2c.h> |
#include <linux/irq.h> |
#include <linux/interrupt.h> |
@@ -19,13 +21,18 @@ |
#include <linux/workqueue.h> |
#include <linux/slab.h> |
#include <linux/gpio.h> |
+#include <linux/spinlock.h> |
+#include <linux/mutex.h> |
+#include <linux/uaccess.h> |
+#include <linux/miscdevice.h> |
+#include <linux/fs.h> |
#include <linux/cyapa.h> |
-/* Debug macro */ |
-//#define CYAPA_DBG |
-#ifdef CYAPA_DBG |
+/* DEBUG: debug switch macro */ |
+#define CYAPA_DBG 0 |
+#if CYAPA_DBG |
#define DBGPRINTK(x) printk x |
#define DBG_CYAPA_READ_BLOCK_DATA |
#else |
@@ -34,10 +41,10 @@ |
/* Cypress I2C APA trackpad driver version is defined as bellow: |
Daniel Kurtz
2011/05/01 23:44:09
s/bellow/below
|
-** CYAPA_MAJOR_VER.CYAPA_MINOR_VER.CYAPA_REVISIOIN_VER . */ |
+** CYAPA_MAJOR_VER.CYAPA_MINOR_VER.CYAPA_REVISION_VER . */ |
Daniel Kurtz
2011/05/01 23:44:09
IMHO, it sounds better as:
CYAPA_VER_MAJOR.CYAPA_V
|
#define CYAPA_MAJOR_VER 0 |
#define CYAPA_MINOR_VER 9 |
-#define CYAPA_REVISIOIN_VER 2 |
+#define CYAPA_REVISION_VER 7 |
Daniel Kurtz
2011/05/01 23:44:09
Just one tab
|
/* macro definication for gestures. */ |
/* --------------------------------------------------------------- */ |
@@ -46,73 +53,76 @@ |
/* |- finger number -|- gesture id -| */ |
/* --------------------------------------------------------------- */ |
#define GESTURE_FINGERS(x) ((((x) & 0x07) << 5) & 0xE0) |
-#define GESTURE_INDEX(x) ((x) & 0x1F) |
-#define GESTURE_ID_CODE(finger, index) (GESTURE_FINGERS(finger) | GESTURE_INDEX(index)) |
+#define GESTURE_INDEX(x) (((x) & 0x1F)) |
+#define GESTURE_ID_CODE(finger, index) \ |
+ (GESTURE_FINGERS(finger) | GESTURE_INDEX(index)) |
+#define GESTURE_DECODE_FINGERS(x) (((x) >> 5) & 0x07) |
+#define GESTURE_DECODE_INDEX(x) ((x) & 0x1F) |
Daniel Kurtz
2011/05/01 23:44:09
two tabs
|
#define GESTURE_NONE 0x00 |
/* 0-finger gestures. */ |
-#define GESTURE_PALM_REJECTIOIN GESTURE_ID_CODE(0, 1) |
+#define GESTURE_PALM_REJECTIOIN GESTURE_ID_CODE(0, 1) |
Daniel Kurtz
2011/05/01 23:44:09
2 tabs
|
/* 1-finger gestures. */ |
-#define GESTURE_SINGLE_TAP GESTURE_ID_CODE(1, 0) |
-#define GESTURE_DOUBLE_TAP GESTURE_ID_CODE(1, 1) |
-/* one finger click and hold for more than definitioin time, then to do something. */ |
-#define GESTURE_TAP_AND_HOLD GESTURE_ID_CODE(1, 2) |
-#define GESTURE_EDGE_MOTION GESTURE_ID_CODE(1, 3) |
-#define GESTURE_FLICK GESTURE_ID_CODE(1, 4) |
+#define GESTURE_SINGLE_TAP GESTURE_ID_CODE(1, 0) |
+#define GESTURE_DOUBLE_TAP GESTURE_ID_CODE(1, 1) |
+/* |
+** one finger click and hold for more than definitioin time, |
Daniel Kurtz
2011/05/01 23:44:09
s/definitioin/defined
s/**/ *
|
+** then to do something. |
+*/ |
+#define GESTURE_TAP_AND_HOLD GESTURE_ID_CODE(1, 2) |
+#define GESTURE_EDGE_MOTION GESTURE_ID_CODE(1, 3) |
+#define GESTURE_FLICK GESTURE_ID_CODE(1, 4) |
/* GESTURE_DRAG : double click and hold, then move for drag.*/ |
-#define GESTURE_DRAG GESTURE_ID_CODE(1, 5) |
+#define GESTURE_DRAG GESTURE_ID_CODE(1, 5) |
/* Depending on PSOC user module, it will give four different ID when scroll.*/ |
-#define GESTURE_SCROLL_UP GESTURE_ID_CODE(1, 6) |
-#define GESTURE_SCROLL_DOWN GESTURE_ID_CODE(1, 7) |
-#define GESTURE_SCROLL_LEFT GESTURE_ID_CODE(1, 8) |
+#define GESTURE_SCROLL_UP GESTURE_ID_CODE(1, 6) |
+#define GESTURE_SCROLL_DOWN GESTURE_ID_CODE(1, 7) |
+#define GESTURE_SCROLL_LEFT GESTURE_ID_CODE(1, 8) |
#define GESTURE_SCROLL_RIGHT GESTURE_ID_CODE(1, 9) |
/* 2-finger gestures */ |
-#define GESTURE_2F_ZOOM_IN GESTURE_ID_CODE(2, 0) |
-#define GESTURE_2F_ZOOM_OUT GESTURE_ID_CODE(2, 1) |
+#define GESTURE_2F_ZOOM_IN GESTURE_ID_CODE(2, 0) |
+#define GESTURE_2F_ZOOM_OUT GESTURE_ID_CODE(2, 1) |
#define GESTURE_2F_SCROLL_UP GESTURE_ID_CODE(2, 2) |
-#define GESTURE_2F_SCROLL_DOWN GESTURE_ID_CODE(2, 3) |
-#define GESTURE_2F_SCROLL_LEFT GESTURE_ID_CODE(2, 4) |
-#define GESTURE_2F_SCROLL_RIGHT GESTURE_ID_CODE(2, 5) |
-#define GESTURE_2F_ROTATE GESTURE_ID_CODE(2, 6) |
-#define GESTURE_2F_PINCH GESTURE_ID_CODE(2, 7) |
+#define GESTURE_2F_SCROLL_DOWN GESTURE_ID_CODE(2, 3) |
Daniel Kurtz
2011/05/01 23:44:09
next three lines:
two tabs
|
+#define GESTURE_2F_SCROLL_LEFT GESTURE_ID_CODE(2, 4) |
+#define GESTURE_2F_SCROLL_RIGHT GESTURE_ID_CODE(2, 5) |
+#define GESTURE_2F_ROTATE GESTURE_ID_CODE(2, 6) |
+#define GESTURE_2F_PINCH GESTURE_ID_CODE(2, 7) |
/* Activates the Right Click action */ |
-#define GESTURE_2F_TAP GESTURE_ID_CODE(2, 8) |
+#define GESTURE_2F_TAP GESTURE_ID_CODE(2, 8) |
/* Single-Finger click and hold while a second finger is moving for dragging. */ |
-#define GESTURE_2F_DRAG GESTURE_ID_CODE(2, 9) |
-#define GESTURE_2F_FLICK GESTURE_ID_CODE(2, 10) |
+#define GESTURE_2F_DRAG GESTURE_ID_CODE(2, 9) |
Daniel Kurtz
2011/05/01 23:44:09
2 tabs
|
+#define GESTURE_2F_FLICK GESTURE_ID_CODE(2, 10) |
/* 3-finger gestures */ |
-#define GESTURE_3F_FLICK GESTURE_ID_CODE(3, 0) |
+#define GESTURE_3F_FLICK GESTURE_ID_CODE(3, 0) |
/* 4-finger gestures */ |
-#define GESTURE_4F_FLICK GESTURE_ID_CODE(4, 0) |
+#define GESTURE_4F_FLICK GESTURE_ID_CODE(4, 0) |
/* 5-finger gestures */ |
-#define GESTURE_5F_FLICK GESTURE_ID_CODE(5, 0) |
- |
-/* swith of the gesture, */ |
-#define GESTURE_MULTI_TOUCH_ONE_CLICK 0 |
+#define GESTURE_5F_FLICK GESTURE_ID_CODE(5, 0) |
-#define GESTURE_DECODE_FINGERS(x) (((x) >> 5) & 0x07) |
-#define GESTURE_DECODE_INDEX(x) ((x) & 0x1F ) |
+#define CYAPA_MT_MAX_TOUCH 255 |
+#define CYAPA_MT_MAX_WIDTH 255 |
/* max gesture index value for each fingers type is 31. 0~21.*/ |
#define MAX_FINGERS 5 |
- |
- |
/* parameter value for input_report_key(BTN_TOOL_WIDTH) */ |
#define CYAPA_TOOL_WIDTH 50 |
+#define CYAPA_DEFAULT_TOUCH_PRESSURE 50 |
+#define CYAPA_MT_TOUCH_MAJOR 50 |
/* When in IRQ mode read the device every THREAD_IRQ_SLEEP_SECS */ |
#define CYAPA_THREAD_IRQ_SLEEP_SECS 2 |
-#define CYAPA_THREAD_IRQ_SLEEP_MSECS (CYAPA_THREAD_IRQ_SLEEP_SECS * MSEC_PER_SEC) |
- |
+#define CYAPA_THREAD_IRQ_SLEEP_MSECS \ |
+ (CYAPA_THREAD_IRQ_SLEEP_SECS * MSEC_PER_SEC) |
/* |
* When in Polling mode and no data received for CYAPA_NO_DATA_THRES msecs |
* reduce the polling rate to CYAPA_NO_DATA_SLEEP_MSECS |
*/ |
-#define CYAPA_NO_DATA_THRES (MSEC_PER_SEC) |
+#define CYAPA_NO_DATA_THRES (MSEC_PER_SEC) |
#define CYAPA_NO_DATA_SLEEP_MSECS (MSEC_PER_SEC / 4) |
/* report data start reg offset address. */ |
@@ -120,39 +130,19 @@ |
/* relative data report data size. */ |
#define CYAPA_REL_REG_DATA_SIZE 5 |
- |
/* Device Sleep Modes */ |
#define DEV_POWER_REG 0x0009 |
#define INTERRUPT_MODE_MASK 0x01 |
#define PWR_LEVEL_MASK 0x06 |
#define PWR_BITS_SHITF 1 |
-#define GET_PWR_LEVEL(reg) ((((unsigned char)(reg))&PWR_LEVEL_MASK)>>PWR_BITS_SHITF) |
- |
-// protocol V1. |
-#define REG_GESTURES 0x0B |
- |
-/* definition to store platfrom data. */ |
-static struct cyapa_platform_data cyapa_i2c_platform_data = { |
- .flag = 0, |
- .gen = CYAPA_GEN2, |
- .power_state = CYAPA_PWR_ACTIVE, |
- .use_absolute_mode = true, |
- .use_polling_mode = false, |
- .polling_interval_time_active = CYAPA_ACTIVE_POLLING_INTVAL_TIME, |
- .polling_interval_time_lowpower = CYAPA_LOWPOWER_POLLING_INTVAL_TIME, |
- .active_touch_timeout = CYAPA_ACTIVE_TOUCH_TIMEOUT, |
- .name = CYAPA_I2C_NAME, |
- .irq_gpio = -1, |
- .report_rate = CYAPA_REPORT_RATE, |
-}; |
- |
+#define GET_PWR_LEVEL(reg) \ |
+ ((((unsigned char)(reg))&PWR_LEVEL_MASK)>>PWR_BITS_SHITF) |
/* |
** APA trackpad device states. |
** Used in register 0x00, bit1-0, DeviceStatus field. |
*/ |
-enum cyapa_devicestate |
-{ |
+enum cyapa_devicestate { |
CYAPA_DEV_NORNAL = 0x03, |
/* |
** After trackpad booted, and can report data, it should set this value. |
@@ -163,22 +153,20 @@ enum cyapa_devicestate |
}; |
#define CYAPA_MAX_TOUCHS (MAX_FINGERS) |
-#define CYAPA_ONE_TIME_GESTURES (1) //only 1 gesture can be reported one time right now. |
-struct cyapa_touch_gen1 |
-{ |
+#define CYAPA_ONE_TIME_GESTURES (1) |
+struct cyapa_touch_gen1 { |
u8 rel_xy; |
u8 rel_x; |
u8 rel_y; |
}; |
-struct cyapa_reg_data_gen1 |
-{ |
+struct cyapa_reg_data_gen1 { |
u8 tap_motion; |
s8 deltax; |
s8 deltay; |
u8 reserved1; |
u8 reserved2; |
- |
+ |
struct cyapa_touch_gen1 touch1; |
u8 touch_fingers; |
u8 feature_config; |
@@ -187,23 +175,26 @@ struct cyapa_reg_data_gen1 |
struct cyapa_touch_gen1 touchs[CYAPA_MAX_TOUCHS-1]; |
}; |
-struct cyapa_touch_gen2 |
-{ |
+struct cyapa_touch_gen2 { |
u8 xy; |
u8 x; |
u8 y; |
- u8 id; |
+ u8 pressure; |
}; |
-struct cyapa_gesture |
-{ |
+struct cyapa_touch { |
+ int x; |
+ int y; |
+ int pressure; |
+}; |
+ |
+struct cyapa_gesture { |
u8 id; |
u8 param1; |
u8 param2; |
}; |
-struct cyapa_reg_data_gen2 |
-{ |
+struct cyapa_reg_data_gen2 { |
u8 device_status; |
u8 relative_flags; |
s8 deltax; |
@@ -217,21 +208,12 @@ struct cyapa_reg_data_gen2 |
struct cyapa_gesture gesture[CYAPA_ONE_TIME_GESTURES]; |
}; |
-union cyapa_reg_data |
-{ |
+union cyapa_reg_data { |
struct cyapa_reg_data_gen1 gen1_data; |
struct cyapa_reg_data_gen2 gen2_data; |
}; |
-struct cyapa_touch |
-{ |
- int x; |
- int y; |
- int id; |
-}; |
- |
-struct cyapa_report_data |
-{ |
+struct cyapa_report_data { |
u8 button; |
u8 reserved1; |
u8 reserved2; |
@@ -241,72 +223,45 @@ struct cyapa_report_data |
int touch_fingers; |
struct cyapa_touch touchs[CYAPA_MAX_TOUCHS]; |
- |
- int gestures_count; /* in gen1 and gen2, only 1 gesture one time supported. */ |
- struct cyapa_gesture gestures[CYAPA_ONE_TIME_GESTURES]; |
-}; |
- |
-struct scroll_preferences { |
- int default_threshold; /* small scroll speed threshold. */ |
- int middle_threshold; |
- int fast_threshold; |
-}; |
-struct cyapa_preferences { |
- struct scroll_preferences vscroll; |
- struct scroll_preferences hscroll; |
+ /* in gen1 and gen2, only 1 gesture one time supported. */ |
Olof Johansson
2011/05/02 05:47:12
"only 1 gesture at a time"?
|
+ int gestures_count; |
+ struct cyapa_gesture gestures[CYAPA_ONE_TIME_GESTURES]; |
}; |
/* The main device structure */ |
struct cyapa_i2c { |
+ struct semaphore misc_sem; |
+ spinlock_t misc_spinlock; |
+ struct mutex misc_mutex; |
Olof Johansson
2011/05/02 05:47:12
You now have three new locking primitives. Please
|
+ int misc_open_count; |
+ enum cyapa_work_mode fw_work_mode; |
+ |
struct i2c_client *client; |
struct input_dev *input; |
- struct input_dev *input_wheel; |
- struct input_dev *input_kbd; |
struct delayed_work dwork; |
spinlock_t lock; |
int no_data_count; |
int scan_ms; |
- int read_pending; |
int open_count; |
int irq; |
+ int down_to_polling_mode; |
struct cyapa_platform_data *platform_data; |
unsigned short data_base_offset; |
unsigned short control_base_offset; |
unsigned short command_base_offset; |
unsigned short query_base_offset; |
- struct cyapa_preferences preferences; |
- |
- int zoomin_delta; |
- int zoomout_delta; |
- int hscroll_left; |
- int hscroll_right; |
- int delta_scroll_up; |
- int delta_scroll_down; |
- int delta_scroll_left; |
- int delta_scroll_right; |
- |
- int abs_x; |
- int abs_y; |
- int prev_abs_x; |
- int prev_abs_y; |
- unsigned char xy_touchs_included_bits; |
- unsigned char gesture_2F_drag_started; |
- |
- unsigned long cur_active_gestures[MAX_FINGERS]; |
- unsigned long prev_active_gestures[MAX_FINGERS]; |
- |
int prev_touch_fingers; |
/* read from query data region. */ |
char product_id[16]; |
unsigned char capability[14]; |
- unsigned char fm_maj_ver; //firmware major version. |
- unsigned char fm_min_ver; //firmware minor version. |
- unsigned char hw_maj_ver; //hardware major version. |
- unsigned char hw_min_ver; //hardware minor version. |
+ unsigned char fm_maj_ver; /* firmware major version. */ |
+ unsigned char fm_min_ver; /* firmware minor version. */ |
+ unsigned char hw_maj_ver; /* hardware major version. */ |
+ unsigned char hw_min_ver; /* hardware minor version. */ |
int max_absolution_x; |
int max_absolution_y; |
Daniel Kurtz
2011/05/02 12:43:47
max_abs_x / max_abs_y
absolution means something
|
int physical_size_x; |
@@ -314,10 +269,30 @@ struct cyapa_i2c { |
}; |
+/* definition to store platfrom data. */ |
+static struct cyapa_platform_data cyapa_i2c_platform_data = { |
+ .flag = 0, |
+ .gen = CYAPA_GEN2, |
+ .power_state = CYAPA_PWR_ACTIVE, |
+ .polling_interval_time_active = CYAPA_ACTIVE_POLLING_INTVAL_TIME, |
+ .polling_interval_time_lowpower = CYAPA_LOWPOWER_POLLING_INTVAL_TIME, |
+ .active_touch_timeout = CYAPA_ACTIVE_TOUCH_TIMEOUT, |
+ .name = CYAPA_I2C_NAME, |
+ .irq_gpio = -1, |
+ .report_rate = CYAPA_REPORT_RATE, |
+}; |
+ |
+ |
+/* global pointer to trackpad touch data structure. */ |
+static struct cyapa_i2c *global_touch; |
+ |
+static void cyapa_get_query_data(struct cyapa_i2c *touch); |
+ |
+ |
#ifdef DBG_CYAPA_READ_BLOCK_DATA |
-void cyapa_print_data_block(const char *func, u8 reg, u8 length, void *data) |
+void cyapa_dump_data_block(const char *func, u8 reg, u8 length, void *data) |
{ |
- char buf[1024]; |
+ char buf[512]; |
unsigned buf_len = sizeof(buf); |
char *p = buf; |
int i; |
@@ -328,145 +303,167 @@ void cyapa_print_data_block(const char *func, u8 reg, u8 length, void *data) |
p += l; |
for (i = 0; i < length && buf_len; i++, p += l, buf_len -= l) |
l = snprintf(p, buf_len, "%02x ", *((char *)data + i)); |
- printk("%s: data block length = %d\n", func, length); |
- printk("%s: %s\n", func, buf); |
+ printk(KERN_INFO "%s: data block length = %d\n", func, length); |
+ printk(KERN_INFO "%s: %s\n", func, buf); |
} |
-void cyapa_print_report_data(const char *func, |
+void cyapa_dump_report_data(const char *func, |
struct cyapa_report_data *report_data) |
{ |
int i; |
- printk("%s: -----------------------------------------\n", func); |
- printk("%s: report_data.button = 0x%02x\n", func, report_data->button); |
- printk("%s: report_data.avg_pressure = %d\n", func, report_data->avg_pressure); |
- printk("%s: report_data.touch_fingers = %d\n", func, report_data->touch_fingers); |
- for (i=0; i<report_data->touch_fingers; i++) { |
- printk("%s: report_data.touchs[%d].x = %d\n", func, i, report_data->touchs[i].x); |
- printk("%s: report_data.touchs[%d].y = %d\n", func, i, report_data->touchs[i].y); |
- printk("%s: report_data.touchs[%d].id = %d\n", |
- func, i, report_data->touchs[i].id); |
+ printk(KERN_INFO "%s: ------------------------------------\n", func); |
Olof Johansson
2011/05/02 05:47:12
You can use pr_info here, it's a little shorter.
|
+ printk(KERN_INFO "%s: report_data.button = 0x%02x\n", |
+ func, report_data->button); |
+ printk(KERN_INFO "%s: report_data.avg_pressure = %d\n", |
+ func, report_data->avg_pressure); |
+ printk(KERN_INFO "%s: report_data.touch_fingers = %d\n", |
+ func, report_data->touch_fingers); |
+ for (i = 0; i < report_data->touch_fingers; i++) { |
+ printk(KERN_INFO "%s: report_data.touchs[%d].x = %d\n", |
+ func, i, report_data->touchs[i].x); |
+ printk(KERN_INFO "%s: report_data.touchs[%d].y = %d\n", |
+ func, i, report_data->touchs[i].y); |
+ printk(KERN_INFO "%s: report_data.touchs[%d].pressure = %d\n", |
+ func, i, report_data->touchs[i].pressure); |
} |
- printk("%s: report_data.gestures_count = %d\n", func, report_data->gestures_count); |
- for (i=0; i<report_data->gestures_count; i++) { |
- printk("%s: report_data.gestures[%d].id = 0x%02x\n", |
- func, i, report_data->gestures[i].id); |
- printk("%s: report_data.gestures[%d].param1 = 0x%02x\n", |
- func, i, report_data->gestures[i].param1); |
- printk("%s: report_data.gestures[%d].param2 = 0x%02x\n", |
- func, i, report_data->gestures[i].param2); |
+ printk(KERN_INFO "%s: report_data.gestures_count = %d\n", |
+ func, report_data->gestures_count); |
+ for (i = 0; i < report_data->gestures_count; i++) { |
+ printk(KERN_INFO "%s: report_data.gestures[%d].id = 0x%02x\n", |
+ func, i, report_data->gestures[i].id); |
+ printk(KERN_INFO "%s: report_data.gestures[%d].param1 = 0x%02x\n", |
+ func, i, report_data->gestures[i].param1); |
+ printk(KERN_INFO "%s: report_data.gestures[%d].param2 = 0x%02x\n", |
+ func, i, report_data->gestures[i].param2); |
} |
- printk("%s: -----------------------------------------\n", func); |
+ printk(KERN_INFO "%s: -------------------------------------\n", func); |
} |
+#else |
+void cyapa_dump_data_block(const char *func, u8 reg, u8 length, void *data) {} |
+void cyapa_dump_report_data(const char *func, |
+ struct cyapa_report_data *report_data) {} |
+#endif |
+ |
-void cyapa_print_paltform_data(const char *func, |
- struct cyapa_platform_data *cyapa_i2c_platform_data) |
+/* |
+** when the irq number is set in system for trackpad, |
+** but the request irq failed, |
+** so trackpad driver will down to polling mode, |
+** in this case, do not need and unable to enable/disable this irq. |
+*/ |
Olof Johansson
2011/05/02 05:47:12
This comment was changed away from kernel comment
|
+static inline void cyapa_enable_irq(struct cyapa_i2c *touch) |
{ |
- printk("%s: -----------------------------------------\n", func); |
- printk("%s: cyapa_i2c_platform_data.max_touchpad_x = %d\n", func, |
- cyapa_i2c_platform_data->max_touchpad_x); |
- printk("%s: cyapa_i2c_platform_data.max_touchpad_y = %d\n", func, |
- cyapa_i2c_platform_data->max_touchpad_y); |
- printk("%s: cyapa_i2c_platform_data.min_touchpad_x = %d\n", func, |
- cyapa_i2c_platform_data->min_touchpad_x); |
- printk("%s: cyapa_i2c_platform_data.min_touchpad_y = %d\n", func, |
- cyapa_i2c_platform_data->min_touchpad_y); |
- printk("%s: cyapa_i2c_platform_data.flag = 0x%08x\n", func, |
- cyapa_i2c_platform_data->flag); |
- printk("%s: cyapa_i2c_platform_data.gen = 0x%02x\n", func, |
- cyapa_i2c_platform_data->gen); |
- printk("%s: cyapa_i2c_platform_data.power_state = 0x%02x\n", func, |
- cyapa_i2c_platform_data->power_state); |
- printk("%s: cyapa_i2c_platform_data.use_absolute_mode = %s\n", func, |
- cyapa_i2c_platform_data->use_absolute_mode?"true":"false"); |
- printk("%s: cyapa_i2c_platform_data.use_polling_mode = %s\n", func, |
- cyapa_i2c_platform_data->use_polling_mode?"true":"false"); |
- printk("%s: cyapa_i2c_platform_data.polling_interval_time_active = %d\n", |
- func, cyapa_i2c_platform_data->polling_interval_time_active); |
- printk("%s: cyapa_i2c_platform_data.polling_interval_time_lowpower = %d\n", |
- func, cyapa_i2c_platform_data->polling_interval_time_lowpower); |
- printk("%s: cyapa_i2c_platform_data.active_touch_timeout = %d\n", func, |
- cyapa_i2c_platform_data->active_touch_timeout); |
- printk("%s: cyapa_i2c_platform_data.name = %s\n", func, |
- cyapa_i2c_platform_data->name); |
- printk("%s: cyapa_i2c_platform_data.irq_gpio = %d\n", func, |
- cyapa_i2c_platform_data->irq_gpio); |
- printk("%s: cyapa_i2c_platform_data.report_rate = %d\n", func, |
- cyapa_i2c_platform_data->report_rate); |
- printk("%s: cyapa_i2c_platform_data.init = %s%p\n", func, |
- cyapa_i2c_platform_data->init?"0x":"", cyapa_i2c_platform_data->init); |
- printk("%s: cyapa_i2c_platform_data.wakeup = %s%p\n", func, |
- cyapa_i2c_platform_data->wakeup?"0x":"", cyapa_i2c_platform_data->wakeup); |
- printk("%s: -----------------------------------------\n", func); |
+ if (touch->down_to_polling_mode == false) |
+ enable_irq(touch->irq); |
} |
-#endif |
+static inline void cyapa_disable_irq(struct cyapa_i2c *touch) |
+{ |
+ if (touch->down_to_polling_mode == false) |
+ disable_irq(touch->irq); |
+} |
-/* |
- * Driver's initial design makes no race condition possible on i2c bus, |
- * so there is no need in any locking. |
- * Keep it in mind, while playing with the code. |
- */ |
-static s32 cyapa_i2c_reg_read_byte(struct i2c_client *client, u16 reg) |
+static s32 cyapa_i2c_reg_read_byte(struct cyapa_i2c *touch, u16 reg) |
{ |
int ret; |
- ret = i2c_smbus_read_byte_data(client, (u8)reg & 0xff); |
+ /* disable interrupt, and wait I2C bus is read to be operational. */ |
+ cyapa_disable_irq(touch); |
+ if (down_interruptible(&touch->misc_sem)) { |
+ cyapa_enable_irq(touch); |
+ pr_err("ERROR: %s: altered by system.\n", __func__); |
+ return -ERESTARTSYS; |
+ } |
+ |
+ ret = i2c_smbus_read_byte_data(touch->client, (u8)reg & 0xff); |
+ |
+ /* release semaphore and reenable interrupt. */ |
+ up(&touch->misc_sem); |
+ cyapa_enable_irq(touch); |
return ((ret < 0) ? 0 : ret); |
} |
-static s32 cyapa_i2c_reg_write_byte(struct i2c_client *client, u16 reg, u8 val) |
+static s32 cyapa_i2c_reg_write_byte(struct cyapa_i2c *touch, u16 reg, u8 val) |
{ |
int ret; |
- ret = i2c_smbus_write_byte_data(client, (u8)reg & 0xff, val); |
+ /* disable interrupt, and wait I2C bus is read to be operational. */ |
+ cyapa_disable_irq(touch); |
+ if (down_interruptible(&touch->misc_sem)) { |
+ cyapa_enable_irq(touch); |
+ pr_err("ERROR: %s: altered by system.\n", __func__); |
+ return -ERESTARTSYS; |
+ } |
+ |
+ ret = i2c_smbus_write_byte_data(touch->client, (u8)reg & 0xff, val); |
+ |
+ /* release semaphore and reenable interrupt. */ |
+ up(&touch->misc_sem); |
+ cyapa_enable_irq(touch); |
return ((ret < 0) ? 0 : ret); |
} |
-static s32 cyapa_i2c_reg_read_block(struct i2c_client *client, u16 reg, |
+static s32 cyapa_i2c_reg_read_block(struct cyapa_i2c *touch, u16 reg, |
int length, u8 *values) |
{ |
int retval; |
u8 buf[1]; |
- |
+ |
+ /* disable interrupt, and wait I2C bus is read to be operational. */ |
+ cyapa_disable_irq(touch); |
+ if (down_interruptible(&touch->misc_sem)) { |
+ cyapa_enable_irq(touch); |
+ pr_err("ERROR: %s: altered by system.\n", __func__); |
+ return -ERESTARTSYS; |
+ } |
+ |
/* |
** depending on PSOC easy I2C read operations. |
** step1: set read pointer of easy I2C. |
** step2: read data. |
*/ |
- // step1: set read pointer of easy I2C. |
+ /* step1: set read pointer of easy I2C. */ |
memset(buf, 0, 1); |
buf[0] = (u8)(((u8)reg) & 0xff); |
- retval = i2c_master_send(client, buf, 1); |
+ retval = i2c_master_send(touch->client, buf, 1); |
if (retval < 0) { |
- DBGPRINTK(("%s: i2c_master_send error, retval=%d\n", __func__, retval)); |
+ DBGPRINTK(("%s: i2c_master_send error, retval=%d\n", |
Olof Johansson
2011/05/02 05:47:12
pr_debug instead?
|
+ __func__, retval)); |
+ |
+ /* release semaphore and reenable interrupt. */ |
+ up(&touch->misc_sem); |
+ cyapa_enable_irq(touch); |
return retval; |
} |
- |
- //step2: read data. |
- retval = i2c_master_recv(client, values, length); |
+ |
+ /* step2: read data. */ |
+ retval = i2c_master_recv(touch->client, values, length); |
+ /* release semaphore and reenable interrupt. */ |
+ up(&touch->misc_sem); |
+ cyapa_enable_irq(touch); |
if (retval < 0) { |
- DBGPRINTK(("%s: i2c_master_recv error, retval=%d\n", __func__, retval)); |
+ DBGPRINTK(("%s: i2c_master_recv error, retval=%d\n", |
+ __func__, retval)); |
return retval; |
} |
-#ifdef DBG_CYAPA_READ_BLOCK_DATA |
- /* debug message */ |
- cyapa_print_data_block(__func__, (u8)reg, retval, values); |
-#endif |
- |
if (retval != length) { |
- dev_warn(&client->dev, |
- "%s: warning I2C block read bytes [%d] not equal to required bytes [%d].\n", |
+ dev_warn(&touch->client->dev, |
+ "%s: warning I2C block read bytes \ |
+ [%d] not equal to required bytes [%d].\n", |
__func__, retval, length); |
} |
+ /* DEBUG: dump readed block data */ |
+ cyapa_dump_data_block(__func__, (u8)reg, retval, values); |
+ |
return retval; |
} |
-static s32 cyapa_i2c_reg_write_block(struct i2c_client *client, u16 reg, |
+static s32 cyapa_i2c_reg_write_block(struct cyapa_i2c *touch, u16 reg, |
u8 length, const u8 *values) |
{ |
@@ -474,38 +471,398 @@ static s32 cyapa_i2c_reg_write_block(struct i2c_client *client, u16 reg, |
int i; |
u8 buf[256]; |
- if ((length+1) > 256) { |
- DBGPRINTK(("%s: invalid write data length, length=%d\n", __func__, length)); |
+ if ((length+1) > 256) { |
+ DBGPRINTK(("%s: invalid write data length, length=%d\n", |
+ __func__, length)); |
return -EINVAL; |
} |
+ /* disable interrupt, and wait I2C bus is read to be operational. */ |
+ cyapa_disable_irq(touch); |
+ if (down_interruptible(&touch->misc_sem)) { |
+ cyapa_enable_irq(touch); |
+ pr_err("ERROR: %s: altered by system.\n", __func__); |
+ return -ERESTARTSYS; |
+ } |
+ |
/* |
** depending on PSOC easy I2C read operations. |
** step1: write data to easy I2C in one command. |
*/ |
- // step1: write data to easy I2C in one command. |
+ /* step1: write data to easy I2C in one command. */ |
memset(buf, 0, 256); |
buf[0] = (u8)(((u8)reg) & 0xff); |
/* move data shoud be write to I2C slave device. */ |
- for (i=1; i<length; i++) |
- { |
+ for (i = 1; i < length+1; i++) |
buf[i] = values[i-1]; |
- } |
- retval = i2c_master_send(client, buf, length+1); |
+ |
+ retval = i2c_master_send(touch->client, buf, length+1); |
+ /* release semaphore and reenable interrupt. */ |
+ up(&touch->misc_sem); |
+ cyapa_enable_irq(touch); |
if (retval < 0) { |
- DBGPRINTK(("%s: i2c_master_send error, retval=%d\n", __func__, retval)); |
+ DBGPRINTK(("%s: i2c_master_send error, retval=%d\n", |
+ __func__, retval)); |
return retval; |
} |
- if (retval != (length+1)) { |
- dev_warn(&client->dev, |
- "%s: warning I2C block write bytes [%d] not equal to required bytes [%d].\n", |
+ /* one additional writen byte is register offset. */ |
+ if ((retval-1) != length) { |
+ dev_warn(&touch->client->dev, |
+ "%s: warning I2C block write bytes \ |
+ [%d] not equal to required bytes [%d].\n", |
__func__, retval, length); |
} |
- return retval; |
+ return retval - 1; |
+} |
+ |
+ |
+/* |
+*************************************************************** |
+** misc deivce for trackpad firmware update, |
+** and for raw read/wtite operations. |
+** Bellow program may open and use cyaya_misc_dev. |
+** 1. synaptics X Driver. |
+** 2. trackpad firmware update program. |
+*************************************************************** |
+*/ |
+static int cyapa_misc_open(struct inode *inode, struct file *file) |
+{ |
+ int count = 0; |
Olof Johansson
2011/05/02 05:47:12
This assignment is unneeded.
|
+ |
+ file->private_data = (void *)global_touch; |
+ |
+ spin_lock(&global_touch->misc_spinlock); |
+ if (global_touch->misc_open_count) { |
+ spin_unlock(&global_touch->misc_spinlock); |
+ pr_debug("DEBUG: %s, misc device busy.\n", __func__); |
+ return -EBUSY; |
+ } |
+ count = ++global_touch->misc_open_count; |
+ spin_unlock(&global_touch->misc_spinlock); |
+ |
+ pr_debug("DEBUG: enter %s, misc device open count = %d\n", |
+ __func__, count); |
+ |
+ return 0; |
+} |
+ |
+static int cyapa_misc_close(struct inode *inode, struct file *file) |
+{ |
+ int count = 0; |
Olof Johansson
2011/05/02 05:47:12
This assignment is unneeded.
|
+ |
+ spin_lock(&global_touch->misc_spinlock); |
+ count = --global_touch->misc_open_count; |
+ spin_unlock(&global_touch->misc_spinlock); |
+ |
+ pr_debug("DEBUG: enter %s, misc device open count = %d\n", |
+ __func__, count); |
+ |
+ return 0; |
} |
+static loff_t cyapa_misc_llseek(struct file *file, loff_t offset, int origin) |
+{ |
+ loff_t ret = 0; |
+ struct cyapa_i2c *touch = NULL; |
Olof Johansson
2011/05/02 05:47:12
Assignment to NULL not needed, or just assign to f
|
+ |
+ pr_info("INFO: enter %s, offset=%d, origin=%d\n", |
+ __func__, (int)offset, (int)origin); |
+ |
+ if (file->private_data == NULL) { |
+ pr_err("ERROR: %s: cypress trackpad device does not exit.\n", |
+ __func__); |
+ return -ENODEV; |
+ } |
+ touch = (struct cyapa_i2c *)file->private_data; |
+ |
+ mutex_lock(&touch->misc_mutex); |
+ switch (origin) { |
+ case SEEK_SET: |
+ if (offset < 0 || (unsigned int)offset > 256) { |
+ ret = -EINVAL; |
+ break; |
+ } |
+ |
+ file->f_pos = offset; |
+ ret = file->f_pos; |
+ break; |
+ |
+ case SEEK_CUR: |
+ if ((file->f_pos + offset) > 256 |
+ || (file->f_pos + offset) < 0) { |
+ ret = -EINVAL; |
+ break; |
+ } |
+ |
+ file->f_pos += offset; |
+ ret = file->f_pos; |
+ break; |
+ |
+ case SEEK_END: |
+ if ((256 + offset) > 256 || (256 + offset) < 0) { |
+ ret = -EINVAL; |
+ break; |
+ } |
+ |
+ file->f_pos = (256 + offset); |
+ ret = file->f_pos; |
+ break; |
+ |
+ default: |
+ ret = -EINVAL; |
+ break; |
+ } |
+ mutex_unlock(&touch->misc_mutex); |
+ |
+ pr_info("INFO %s: f_pos=%lld, exit code = %lld.\n", |
+ __func__, (long long)file->f_pos, (long long)ret); |
+ |
+ return ret; |
+} |
+ |
+static ssize_t cyapa_misc_read(struct file *file, char __user *usr_buf, |
+ size_t count, loff_t *offset) |
+{ |
+ int ret = 0; |
+ unsigned int reg_len = 256; |
+ unsigned long reg_offset = *offset; |
+ unsigned char reg_buf[256]; |
+ struct cyapa_i2c *touch = NULL; |
Olof Johansson
2011/05/02 05:47:12
Assignment to NULL not needed -- or just assign to
|
+ |
+ pr_info("INFO: enter %s, count=%d, offset=%d\n", |
+ __func__, (int)count, (int)*offset); |
Olof Johansson
2011/05/02 05:47:12
Printing this on every call is too verbose. pr_deb
|
+ |
+ if (file->private_data == NULL) { |
+ pr_err("ERROR: %s: cypress trackpad device does not exit.\n", |
+ __func__); |
+ return -ENODEV; |
+ } |
+ touch = (struct cyapa_i2c *)file->private_data; |
+ /* max registers contained in one register map in bytes in 256. */ |
+ if (reg_offset > 255 || count > 256 |
+ || (reg_offset + count) > 256 || (reg_offset + count) < 0) |
+ return -EINVAL; |
+ reg_len = (count < reg_len) ? count : reg_len; |
+ |
+ /* read I2C registers. */ |
+ ret = cyapa_i2c_reg_read_block(touch, (u16)reg_offset, |
+ reg_len, (u8 *)reg_buf); |
+ if (ret < 0) { |
+ pr_err("ERROR: %s: cypress trackpad I2C read FAILED.\n", |
+ __func__); |
+ return ret; |
+ } |
+ |
+ if (ret < reg_len) |
+ pr_err("WARNING: %s: Execped %d bytes, read %d bytes.\n", |
+ __func__, reg_len, ret); |
+ reg_len = ret; |
+ |
+ /* copy to user space. */ |
+ if (copy_to_user(usr_buf, reg_buf, reg_len)) { |
+ ret = -EFAULT; |
+ } else { |
+ *offset += reg_len; |
+ ret = reg_len; |
+ |
+ pr_info("INFO: %s: read %d bytes from offset %d\n", |
+ __func__, (int)reg_len, (int)reg_offset); |
+ } |
+ |
+ return ret; |
+} |
+ |
+static ssize_t cyapa_misc_write(struct file *file, const char __user *usr_buf, |
+ size_t count, loff_t *offset) |
+{ |
+ int ret = 0; |
+ unsigned int reg_len = 256; |
+ unsigned long reg_offset = *offset; |
+ unsigned char reg_buf[256]; |
+ struct cyapa_i2c *touch = NULL; |
Olof Johansson
2011/05/02 05:47:12
Again, this can be assigned to file->private_data
|
+ |
+ pr_info("INFO: enter %s, count=%d, offset=%d\n", |
+ __func__, (int)count, (int)*offset); |
Olof Johansson
2011/05/02 05:47:12
pr_debug()
|
+ |
+ if (file->private_data == NULL) { |
+ pr_err("ERROR: %s: cypress trackpad device does not exit.\n", |
+ __func__); |
+ return -ENODEV; |
+ } |
+ touch = (struct cyapa_i2c *)file->private_data; |
+ if (reg_offset > 255 || count > 256 |
+ || (reg_offset + count) > 256 || (reg_offset + count) < 0) |
+ return -EINVAL; |
Olof Johansson
2011/05/02 05:47:12
This code is duplicated with the read function. Br
|
+ reg_len = (count < reg_len) ? count : reg_len; |
+ |
+ /* copy to kernel space. */ |
+ if (copy_from_user(reg_buf, usr_buf, reg_len)) { |
+ pr_err("ERROR: %s: copy data from user space failed.\n", |
+ __func__); |
+ return -EINVAL; |
+ } |
+ |
+ /* write I2C registers. */ |
+ ret = cyapa_i2c_reg_write_block(touch, |
+ (u16)reg_offset, |
+ (u8)reg_len, |
+ (u8 *)reg_buf); |
+ if (ret < 0) { |
Olof Johansson
2011/05/02 05:47:12
Braces not needed
|
+ pr_err("ERROR: %s: cypress trackpad I2C write FAILED.\n", |
+ __func__); |
+ } |
+ |
+ *offset = (ret < 0) ? reg_offset : (reg_offset + ret); |
+ pr_info("INFO: %s, write %d bytes to offset %d\n", |
+ __func__, ret, (int)reg_offset); |
+ |
+ return ret; |
+} |
+ |
+static long cyapa_misc_ioctl(struct file *file, unsigned int cmd, |
+ unsigned long arg) |
+{ |
+ int ret = 0; |
+ struct cyapa_i2c *touch = NULL; |
Olof Johansson
2011/05/02 05:47:12
Again, can be assigned directly.
|
+ struct cyapa_misc_ioctl_data ioctl_data; |
+ |
+ pr_debug("INFO: enter %s, ioctl cmd=0x%02x, arg=0x%02lx\n", |
+ __func__, cmd, arg); |
+ |
+ if (file->private_data == NULL) { |
+ pr_err("ERROR: %s: cypress trackpad device does not exit.\n", |
+ __func__); |
+ return -ENODEV; |
+ } |
+ touch = (struct cyapa_i2c *)file->private_data; |
+ |
+ /* copy to kernel space. */ |
+ if (copy_from_user(&ioctl_data, (u8 *)arg, |
+ sizeof(struct cyapa_misc_ioctl_data))) |
+ return -EINVAL; |
Olof Johansson
2011/05/02 05:47:12
The above is a little hard to read. Making the if(
|
+ |
+ switch (cmd) { |
+ case CYAPA_GET_PRODUCT_ID: |
+ if (!ioctl_data.buf || ioctl_data.len < 16) |
+ return -EINVAL; |
+ |
+ cyapa_get_query_data(touch); |
+ ioctl_data.len = 16; |
+ if (copy_to_user(ioctl_data.buf, touch->product_id, 16)) |
+ return -ENODEV; |
+ if (copy_to_user((void *)arg, &ioctl_data, |
+ sizeof(struct cyapa_misc_ioctl_data))) |
+ return -ENODEV; |
+ return ioctl_data.len; |
+ |
+ case CYAPA_GET_DRIVER_VER: |
+ if (!ioctl_data.buf || ioctl_data.len < 3) |
+ return -EINVAL; |
+ |
+ cyapa_get_query_data(touch); |
+ ioctl_data.len = 3; |
+ if (put_user((unsigned char)CYAPA_MAJOR_VER, ioctl_data.buf) |
+ || put_user((unsigned char)CYAPA_MINOR_VER, |
+ ioctl_data.buf + 1) |
+ || put_user((unsigned char)CYAPA_REVISION_VER, |
+ ioctl_data.buf + 2)) |
Olof Johansson
2011/05/02 05:47:12
The above is hard to read. Since it's just 3 bytes
|
+ return -EINVAL; |
+ if (copy_to_user((void *)arg, &ioctl_data, |
+ sizeof(struct cyapa_misc_ioctl_data))) |
+ return -ENODEV; |
+ return ioctl_data.len; |
+ |
+ case CYAPA_GET_FIRMWARE_VER: |
+ if (!ioctl_data.buf || ioctl_data.len < 2) |
+ return -EINVAL; |
+ |
+ cyapa_get_query_data(touch); |
+ ioctl_data.len = 2; |
+ if (put_user(touch->fm_maj_ver, ioctl_data.buf) |
+ || put_user(touch->fm_min_ver, ioctl_data.buf + 1)) |
+ return -EINVAL; |
+ if (copy_to_user((void *)arg, &ioctl_data, |
+ sizeof(struct cyapa_misc_ioctl_data))) |
+ return -ENODEV; |
+ return ioctl_data.len; |
+ |
+ case CYAPA_GET_HARDWARE_VER: |
+ if (!ioctl_data.buf || ioctl_data.len < 2) |
+ return -EINVAL; |
+ |
+ cyapa_get_query_data(touch); |
+ ioctl_data.len = 2; |
+ if (put_user(touch->hw_maj_ver, ioctl_data.buf) |
+ || put_user(touch->hw_min_ver, ioctl_data.buf + 1)) |
+ return -EINVAL; |
+ if (copy_to_user((void *)arg, &ioctl_data, |
+ sizeof(struct cyapa_misc_ioctl_data))) |
+ return -ENODEV; |
+ return ioctl_data.len; |
+ |
+ case CYAPA_SET_BOOTLOADER_MODE: |
+ return ret; |
+ |
+ case CYAPA_SET_STREAM_MODE: |
+ break; |
+ |
+ default: |
+ ret = -EINVAL; |
+ break; |
+ } |
+ |
+ return ret; |
+} |
+ |
+static const struct file_operations cyapa_misc_fops = { |
+ .owner = THIS_MODULE, |
+ .open = cyapa_misc_open, |
+ .release = cyapa_misc_close, |
+ .unlocked_ioctl = cyapa_misc_ioctl, |
+ .llseek = cyapa_misc_llseek, |
+ .read = cyapa_misc_read, |
+ .write = cyapa_misc_write, |
+}; |
+ |
+static struct miscdevice cyapa_misc_dev = { |
+ .name = CYAPA_MISC_NAME, |
+ .fops = &cyapa_misc_fops, |
+ .minor = MISC_DYNAMIC_MINOR, |
+}; |
+ |
+static int __init cyapa_misc_init(void) |
+{ |
+ int ret = 0; |
Olof Johansson
2011/05/02 05:47:12
No need to initialize.
|
+ |
+ pr_info("INFO: enter %s\n", __func__); |
+ ret = misc_register(&cyapa_misc_dev); |
+ if (ret) { |
Olof Johansson
2011/05/02 05:47:12
No need for braces.
|
+ pr_err("ERROR: %s: cyapa misc device register FAILED.\n", |
+ __func__); |
+ } |
+ |
+ return ret; |
+} |
+ |
+static void __exit cyapa_misc_exit(void) |
+{ |
+ pr_info("INFO: enter %s\n", __func__); |
+ misc_deregister(&cyapa_misc_dev); |
+} |
+ |
+static void cyapa_update_firmware_dispatch(struct cyapa_i2c *touch) |
+{ |
+ /* do something here to update trackpad firmware. */ |
+} |
+ |
+/* |
+**************************************************************** |
+** Cypress i2c trackpad input device driver. |
+**************************************************************** |
+*/ |
+ |
#define REG_OFFSET_DATA_BASE 0x0000 |
#define REG_OFFSET_CONTROL_BASE 0x0029 |
#define REG_OFFSET_COMMAND_BASE 0x0049 |
@@ -527,10 +884,9 @@ static void cyapa_get_query_data(struct cyapa_i2c *touch) |
int i; |
/* query data has been supported in GEN1 protocol.*/ |
- if (touch->platform_data->gen == CYAPA_GEN2) |
- { |
+ if (touch->platform_data->gen == CYAPA_GEN2) { |
memset(query_data, 0, 40); |
- ret_read_size = cyapa_i2c_reg_read_block(touch->client, |
+ ret_read_size = cyapa_i2c_reg_read_block(touch, |
touch->query_base_offset, |
38, |
(u8 *)&query_data); |
@@ -557,92 +913,88 @@ static void cyapa_get_query_data(struct cyapa_i2c *touch) |
touch->hw_maj_ver = query_data[17]; |
touch->hw_min_ver = query_data[18]; |
- for (i=0; i<13; i++) { |
+ for (i = 0; i < 13; i++) |
touch->capability[i] = query_data[19+i]; |
- } |
- touch->max_absolution_x = (((query_data[32] & 0xF0) << 4) | query_data[33]); |
- touch->max_absolution_y = (((query_data[32] & 0x0F) << 8) | query_data[34]); |
- if (!touch->max_absolution_x || !touch->max_absolution_y) { |
- if (!strcmp(touch->product_id, "CYTRA-014001-00")) { |
- touch->max_absolution_x = 1600; |
- touch->max_absolution_y = 900; |
- } else { |
- touch->max_absolution_x = 1200; |
- touch->max_absolution_y = 600; |
- } |
- } |
+ touch->max_absolution_x = |
+ (((query_data[32] & 0xF0) << 4) | query_data[33]); |
+ touch->max_absolution_y = |
+ (((query_data[32] & 0x0F) << 8) | query_data[34]); |
- touch->physical_size_x = (((query_data[35] & 0xF0) << 4) | query_data[36]); |
- touch->physical_size_y = (((query_data[35] & 0x0F) << 8) | query_data[37]); |
+ touch->physical_size_x = |
+ (((query_data[35] & 0xF0) << 4) | query_data[36]); |
+ touch->physical_size_y = |
+ (((query_data[35] & 0x0F) << 8) | query_data[37]); |
if (!touch->physical_size_x || !touch->physical_size_y) { |
touch->physical_size_x = 105; |
touch->physical_size_y = 60; |
} |
- |
- printk("Cypress Trackpad Information:\n"); |
- printk("\t\t\tProduction ID: %s\n", touch->product_id); |
- printk("\t\t\tFirmware version: %d.%d\n", touch->fm_maj_ver, touch->fm_min_ver); |
- printk("\t\t\tHardware version: %d.%d\n", touch->hw_maj_ver, touch->hw_min_ver); |
- printk("\t\t\tResolution X,Y: %d,%d\n", touch->max_absolution_x, touch->max_absolution_y); |
- printk("\t\t\tPhysical Size X,Y: %d,%d\n", touch->physical_size_x, touch->physical_size_y); |
} |
} |
static int cyapa_i2c_reconfig(struct cyapa_i2c *touch) |
{ |
- struct i2c_client *client = touch->client; |
int regval = 0; |
int retval = 0; |
if (touch->platform_data->gen == CYAPA_GEN1) { |
/* trackpad gen1 firmware. */ |
- DBGPRINTK(("%s: trackpad support gen1 firmware. \n", __func__)); |
- |
- regval = cyapa_i2c_reg_read_byte(client, DEV_POWER_REG); |
- DBGPRINTK(("%s: read trackpad interrupt bit = 0x%02x \n", |
+ DBGPRINTK(("%s: trackpad support gen1 firmware.\n", __func__)); |
+ |
+ regval = cyapa_i2c_reg_read_byte(touch, DEV_POWER_REG); |
+ DBGPRINTK(("%s: read trackpad interrupt bit = 0x%02x\n", |
__func__, regval&INTERRUPT_MODE_MASK)); |
- if ( (touch->platform_data->use_polling_mode == true) && |
- ((regval & INTERRUPT_MODE_MASK) == INTERRUPT_MODE_MASK) ) |
- { |
+ if ((touch->down_to_polling_mode == true) |
+ && ((regval & INTERRUPT_MODE_MASK) |
+ == INTERRUPT_MODE_MASK)) { |
/* reset trackpad to polling mode. */ |
regval &= (~INTERRUPT_MODE_MASK); |
- retval = cyapa_i2c_reg_write_byte(client, DEV_POWER_REG, (u8)(regval & 0xff)); |
- if (retval) { |
- DBGPRINTK(("%s: set to polliing mode failed, retval=%d.\n", __func__, retval)); |
- /* |
- * Though firmware has set interrupt mode bit. |
- * but since platfrom doesn't support interrupt mode, |
- * so also use polling mode here. |
- * do nothing. |
- */ |
- } |
- } |
- else if ( (touch->platform_data->use_polling_mode == false) && |
- ((regval & INTERRUPT_MODE_MASK) != INTERRUPT_MODE_MASK) ) |
- { |
+ retval = cyapa_i2c_reg_write_byte(touch, DEV_POWER_REG, |
+ (u8)(regval & 0xff)); |
+ /* |
+ * Wether reset interrupt mode bit sucess or failed. |
+ * because platfrom doesn't support interrupt mode, |
+ * so driver will just use polling mode. |
+ */ |
+ } else if ((touch->down_to_polling_mode == false) |
+ && ((regval & INTERRUPT_MODE_MASK) |
+ != INTERRUPT_MODE_MASK)) { |
/* reset trackpad to interrupt mode. */ |
regval |= INTERRUPT_MODE_MASK; |
- retval = cyapa_i2c_reg_write_byte(client, DEV_POWER_REG, (u8)(regval & 0xff)); |
- if (retval) { |
- DBGPRINTK(("%s: set to interrup mode failed, retval=%d.\n", __func__, retval)); |
- touch->platform_data->use_polling_mode = true; |
- } |
+ retval = cyapa_i2c_reg_write_byte(touch, DEV_POWER_REG, |
+ (u8)(regval & 0xff)); |
+ if (retval) |
+ touch->down_to_polling_mode = true; |
} |
- DBGPRINTK(("%s: trackpad interrupt bit = 0x%02x \n", __func__, |
- (u8)cyapa_i2c_reg_read_byte(client, DEV_POWER_REG))); |
+ DBGPRINTK(("%s: trackpad interrupt bit = 0x%02x\n", __func__, |
+ (u8)cyapa_i2c_reg_read_byte(touch, DEV_POWER_REG))); |
} else { |
/* trackpad gen2 firmware. default is interrupt mode. */ |
DBGPRINTK(("%s: trackpad support gen2 firmware.\n", __func__)); |
cyapa_get_reg_offset(touch); |
cyapa_get_query_data(touch); |
+ |
+ printk(KERN_INFO "Cypress Trackpad Information:\n"); |
Olof Johansson
2011/05/02 05:47:12
pr_info(), please.
|
+ printk(KERN_INFO "\t\t\tProduction ID: %s\n", |
+ touch->product_id); |
+ printk(KERN_INFO "\t\t\tFirmware version: %d.%d\n", |
+ touch->fm_maj_ver, touch->fm_min_ver); |
+ printk(KERN_INFO "\t\t\tHardware version: %d.%d\n", |
+ touch->hw_maj_ver, touch->hw_min_ver); |
+ printk(KERN_INFO "\t\t\tDriver Version: %d.%d.%d\n", |
+ CYAPA_MAJOR_VER, CYAPA_MINOR_VER, CYAPA_REVISION_VER); |
+ printk(KERN_INFO "\t\t\tResolution X,Y: %d,%d\n", |
+ touch->max_absolution_x, touch->max_absolution_y); |
+ printk(KERN_INFO "\t\t\tPhysical Size X,Y: %d,%d\n", |
+ touch->physical_size_x, touch->physical_size_y); |
} |
DBGPRINTK(("%s: use %s mode.\n", __func__, |
- ((touch->platform_data->use_polling_mode == true)?"polling":"interrupt"))); |
+ ((touch->down_to_polling_mode == true) |
+ ? "polling" : "interrupt"))); |
return retval; |
} |
@@ -650,8 +1002,8 @@ static int cyapa_i2c_reset_config(struct cyapa_i2c *touch) |
{ |
int ret = 0; |
- DBGPRINTK(("%s: ... \n", __func__)); |
- |
+ DBGPRINTK(("%s: ...\n", __func__)); |
+ |
return ret; |
} |
@@ -665,20 +1017,23 @@ static int cyapa_verify_data_device(struct cyapa_i2c *touch, |
data_gen1 = ®_data->gen1_data; |
if ((data_gen1->tap_motion & 0x08) != 0x08) { |
/* invalid data. */ |
- DBGPRINTK(("%s: invalid data reg address 0x00, bit3 is not set. \n", __func__)); |
+ DBGPRINTK(("%s: invalid data reg address 0x00, \ |
+ bit3 is not set.\n", __func__)); |
return -EINVAL; |
} |
} else { |
data_gen2 = ®_data->gen2_data; |
if ((data_gen2->device_status & 0x80) != 0x80) { |
/* invalid data. */ |
- DBGPRINTK(("%s: invalid data reg address 0x00, bit7 is not set. \n", __func__)); |
+ DBGPRINTK(("%s: invalid data reg address 0x00, \ |
+ bit7 is not set.\n", __func__)); |
return -EINVAL; |
} |
if ((data_gen2->device_status & 0x03) != CYAPA_DEV_NORNAL) { |
- DBGPRINTK(("%s: invalid device status = 0x%02x, wait for device ready. \n", |
- __func__, (data_gen2->device_status & 0x03))); |
+ DBGPRINTK(("%s: invalid device status = 0x%02x, \ |
+ wait for device ready.\n", |
+ __func__, (data_gen2->device_status & 0x03))); |
return -EBUSY; |
} |
} |
@@ -686,68 +1041,20 @@ static int cyapa_verify_data_device(struct cyapa_i2c *touch, |
return 0; |
} |
-static inline void cyapa_calculate_abs_xy(struct cyapa_i2c *touch, |
- struct cyapa_report_data *report_data) |
-{ |
- int i; |
- int sum_x = 0, sum_y = 0; |
- |
- /* invalid input data. */ |
- if (!touch->xy_touchs_included_bits || !report_data->touch_fingers) { |
- touch->prev_abs_x = -1; |
- touch->prev_abs_y = -1; |
- return; |
- } |
- |
- for (i=0; i<CYAPA_MAX_TOUCHS; i++) { |
- if (touch->xy_touchs_included_bits & (0x01 << i)) { |
- sum_x += report_data->touchs[i].x; |
- sum_y += report_data->touchs[i].y; |
- } |
- } |
- |
- touch->abs_x = sum_x / report_data->touch_fingers; |
- touch->abs_y = sum_y / report_data->touch_fingers; |
- /* x, y directory of Cypress trackpad is in negative direction of screen. |
- ** for some platform it maybe different. */ |
- //touch->abs_x = touch->platform_data->max_touchpad_x - touch->abs_x; |
- //touch->abs_y = touch->platform_data->max_touchpad_y - touch->abs_y; |
- |
- /* use simple filtr to make cursor move smoother. */ |
- if (touch->prev_abs_x != -1) { |
- touch->abs_x = (touch->abs_x * 3 + touch->prev_abs_x) >> 2; |
- touch->abs_y = (touch->abs_y * 3 + touch->prev_abs_y) >> 2; |
- } |
- |
- touch->prev_abs_x = touch->abs_x; |
- touch->prev_abs_y = touch->abs_y; |
-} |
- |
-static inline int cyapa_sqrt(int delta_x, int delta_y) |
+static inline void cyapa_report_fingers(struct input_dev *input, int fingers) |
{ |
- int Xk0 = 0; |
- int Xk1; |
- int multi; |
- |
- multi = Xk1 = delta_x*delta_x + delta_y*delta_y; |
- |
- while( abs(Xk0 - Xk1) > 1) |
- { |
- Xk0 = Xk1; |
- Xk1 = (Xk0 + (multi / Xk0) ) / 2; |
- } |
- |
- return Xk1; |
+ input_report_key(input, BTN_TOOL_FINGER, (fingers == 1)); |
+ input_report_key(input, BTN_TOOL_DOUBLETAP, (fingers == 2)); |
+ input_report_key(input, BTN_TOOL_TRIPLETAP, (fingers == 3)); |
+ input_report_key(input, BTN_TOOL_QUADTAP, (fingers > 3)); |
} |
static void cyapa_parse_gen1_data(struct cyapa_i2c *touch, |
- struct cyapa_reg_data_gen1 *reg_data, |
- struct cyapa_report_data *report_data) |
+ struct cyapa_reg_data_gen1 *reg_data, |
+ struct cyapa_report_data *report_data) |
{ |
int i; |
int gesture_report_index = 0; |
- int gesture_fingers = 0; |
- int gesture_index = 0; |
/* parse gestures and button data */ |
report_data->button = reg_data->tap_motion & 0x01; |
@@ -758,53 +1065,50 @@ static void cyapa_parse_gen1_data(struct cyapa_i2c *touch, |
report_data->rel_deltaY = -reg_data->deltay; |
if (reg_data->tap_motion & 0x02) { |
- report_data->gestures[gesture_report_index++].id = GESTURE_SINGLE_TAP; |
- |
- gesture_fingers = GESTURE_DECODE_FINGERS(GESTURE_SINGLE_TAP); |
- gesture_index = GESTURE_DECODE_INDEX(GESTURE_SINGLE_TAP); |
- touch->cur_active_gestures[gesture_fingers] |= (1UL << gesture_index); |
+ report_data->gestures[gesture_report_index++].id |
+ = GESTURE_SINGLE_TAP; |
} |
if (reg_data->tap_motion & 0x04) { |
- report_data->gestures[gesture_report_index++].id = GESTURE_DOUBLE_TAP; |
- |
- gesture_fingers = GESTURE_DECODE_FINGERS(GESTURE_DOUBLE_TAP); |
- gesture_index = GESTURE_DECODE_INDEX(GESTURE_DOUBLE_TAP); |
- touch->cur_active_gestures[gesture_fingers] |= (1UL << gesture_index); |
+ report_data->gestures[gesture_report_index++].id |
+ = GESTURE_DOUBLE_TAP; |
} |
report_data->gestures_count = gesture_report_index; |
/* pase fingers touch data */ |
- report_data->touch_fingers = ((reg_data->touch_fingers > CYAPA_MAX_TOUCHS) ? |
+ report_data->touch_fingers |
+ = ((reg_data->touch_fingers > CYAPA_MAX_TOUCHS) ? |
(CYAPA_MAX_TOUCHS) : (reg_data->touch_fingers)); |
report_data->avg_pressure = reg_data->avg_pressure; |
report_data->touchs[0].x = |
- ((reg_data->touch1.rel_xy & 0xF0) << 4) | reg_data->touch1.rel_x; |
+ ((reg_data->touch1.rel_xy & 0xF0) << 4) |
+ | reg_data->touch1.rel_x; |
report_data->touchs[0].y = |
- ((reg_data->touch1.rel_xy & 0x0F) << 8) | reg_data->touch1.rel_y; |
- report_data->touchs[0].id = 0; |
+ ((reg_data->touch1.rel_xy & 0x0F) << 8) |
+ | reg_data->touch1.rel_y; |
+ report_data->touchs[0].pressure = CYAPA_DEFAULT_TOUCH_PRESSURE; |
- for (i=0; i<(CYAPA_MAX_TOUCHS-1); i++) { |
+ for (i = 0; i < (CYAPA_MAX_TOUCHS-1); i++) { |
report_data->touchs[i+1].x = |
- ((reg_data->touchs[i].rel_xy & 0xF0) << 4) | reg_data->touchs[i].rel_x; |
+ ((reg_data->touchs[i].rel_xy & 0xF0) << 4) |
+ | reg_data->touchs[i].rel_x; |
report_data->touchs[i+1].y = |
- ((reg_data->touchs[i].rel_xy & 0x0F) << 8) | reg_data->touchs[i].rel_y; |
- report_data->touchs[i+1].id = i+1; |
+ ((reg_data->touchs[i].rel_xy & 0x0F) << 8) |
+ | reg_data->touchs[i].rel_y; |
+ report_data->touchs[i+1].pressure = |
+ CYAPA_DEFAULT_TOUCH_PRESSURE; |
} |
- #ifdef DBG_CYAPA_READ_BLOCK_DATA |
- cyapa_print_report_data(__func__, report_data); |
- #endif |
+ /* DEBUG: dump parsed report data */ |
+ cyapa_dump_report_data(__func__, report_data); |
} |
static void cyapa_parse_gen2_data(struct cyapa_i2c *touch, |
- struct cyapa_reg_data_gen2 *reg_data, |
- struct cyapa_report_data *report_data) |
+ struct cyapa_reg_data_gen2 *reg_data, |
+ struct cyapa_report_data *report_data) |
{ |
int i; |
- int gesture_fingers = 0; |
- int gesture_index = 0; |
/* bit2-middle button; bit1-right button; bit0-left buttom. */ |
report_data->button = reg_data->relative_flags & 0x07; |
@@ -816,706 +1120,75 @@ static void cyapa_parse_gen2_data(struct cyapa_i2c *touch, |
/* copy fingers touch data */ |
report_data->avg_pressure = reg_data->avg_pressure; |
- report_data->touch_fingers = ((reg_data->touch_fingers > CYAPA_MAX_TOUCHS) ? |
+ report_data->touch_fingers |
+ = ((reg_data->touch_fingers > CYAPA_MAX_TOUCHS) ? |
(CYAPA_MAX_TOUCHS) : (reg_data->touch_fingers)); |
- for (i=0; i<report_data->touch_fingers; i++) { |
+ for (i = 0; i < report_data->touch_fingers; i++) { |
report_data->touchs[i].x = |
- ((reg_data->touchs[i].xy & 0xF0) << 4) | reg_data->touchs[i].x; |
+ ((reg_data->touchs[i].xy & 0xF0) << 4) |
+ | reg_data->touchs[i].x; |
report_data->touchs[i].y = |
- ((reg_data->touchs[i].xy & 0x0F) << 8) | reg_data->touchs[i].y; |
- report_data->touchs[i].id = reg_data->touchs[i].id; |
+ ((reg_data->touchs[i].xy & 0x0F) << 8) |
+ | reg_data->touchs[i].y; |
+ report_data->touchs[i].pressure = reg_data->touchs[i].pressure; |
} |
/* parse gestures */ |
report_data->gestures_count = |
- (((reg_data->gesture_count) > CYAPA_ONE_TIME_GESTURES) ? |
- CYAPA_ONE_TIME_GESTURES : reg_data->gesture_count); |
- for (i=0; i<report_data->gestures_count; i++) { |
+ (((reg_data->gesture_count) > CYAPA_ONE_TIME_GESTURES) ? |
+ CYAPA_ONE_TIME_GESTURES : reg_data->gesture_count); |
+ for (i = 0; i < report_data->gestures_count; i++) { |
report_data->gestures[i].id = reg_data->gesture[i].id; |
report_data->gestures[i].param1 = reg_data->gesture[i].param1; |
report_data->gestures[i].param2 = reg_data->gesture[i].param2; |
- |
- gesture_fingers = GESTURE_DECODE_FINGERS(report_data->gestures[i].id); |
- gesture_index = GESTURE_DECODE_INDEX(report_data->gestures[i].id); |
- touch->cur_active_gestures[gesture_fingers] |= (1UL << gesture_index); |
- } |
- |
- #ifdef DBG_CYAPA_READ_BLOCK_DATA |
- cyapa_print_report_data(__func__, report_data); |
- #endif |
-} |
- |
-static inline void cyapa_report_fingers(struct input_dev *input, int fingers) |
-{ |
- if (fingers) { |
- input_report_key(input, BTN_TOOL_FINGER, (fingers == 1)); |
- input_report_key(input, BTN_TOOL_DOUBLETAP, (fingers == 2)); |
- input_report_key(input, BTN_TOOL_TRIPLETAP, (fingers == 3)); |
- input_report_key(input, BTN_TOOL_QUADTAP, (fingers > 3)); |
- } else { |
- input_report_key(input, BTN_TOOL_FINGER, 0); |
- input_report_key(input, BTN_TOOL_DOUBLETAP, 0); |
- input_report_key(input, BTN_TOOL_TRIPLETAP, 0); |
- input_report_key(input, BTN_TOOL_QUADTAP, 0); |
- } |
-} |
- |
-static void cyapa_process_prev_gesture_report(struct cyapa_i2c *touch, |
- struct cyapa_report_data *report_data) |
-{ |
- int i, j; |
- unsigned long gesture_diff; |
- struct input_dev *input = touch->input; |
- struct input_dev *input_kbd = touch->input_kbd; |
- |
- for (i=0; i<MAX_FINGERS; i++) { |
- /* get all diffenent gestures in prev and cur. */ |
- gesture_diff = touch->prev_active_gestures[i] ^ touch->cur_active_gestures[i]; |
- /* get all prev gestures that has been canceled in cur. */ |
- gesture_diff = gesture_diff & touch->prev_active_gestures[i]; |
- if (gesture_diff) { |
- for (j=0; j<(sizeof(unsigned long)*8); j++) { |
- /* cancel previous exists gesture. */ |
- if ((gesture_diff >> j) && 1UL) { |
- switch (GESTURE_ID_CODE(i, j)) { |
- case GESTURE_PALM_REJECTIOIN: |
- break; |
- case GESTURE_SINGLE_TAP : |
- break; |
- case GESTURE_DOUBLE_TAP: |
- break; |
- case GESTURE_TAP_AND_HOLD: |
- break; |
- case GESTURE_EDGE_MOTION: |
- break; |
- case GESTURE_DRAG: |
- touch->prev_abs_x = -1; |
- touch->prev_abs_y = -1; |
- |
- if (touch->platform_data->use_absolute_mode) { |
- input_report_key(input, BTN_TOUCH, 0); |
- input_report_abs(input, ABS_PRESSURE, 0); |
- cyapa_report_fingers(input, 0); |
- input_report_key(input, BTN_LEFT, 0); |
- input_sync(input); |
- } |
- break; |
- case GESTURE_2F_ZOOM_IN: |
- touch->zoomin_delta = 0; |
- break; |
- case GESTURE_2F_ZOOM_OUT: |
- touch->zoomout_delta = 0; |
- break; |
- case GESTURE_SCROLL_UP: |
- case GESTURE_2F_SCROLL_UP: |
- touch->delta_scroll_up = 0; |
- break; |
- case GESTURE_SCROLL_DOWN: |
- case GESTURE_2F_SCROLL_DOWN: |
- touch->delta_scroll_down = 0; |
- break; |
- case GESTURE_SCROLL_LEFT: |
- case GESTURE_2F_SCROLL_LEFT: |
- input_report_key(input_kbd, KEY_LEFTSHIFT, 0); |
- input_sync(input_kbd); |
- touch->hscroll_left = 0; |
- touch->delta_scroll_left = 0; |
- break; |
- case GESTURE_SCROLL_RIGHT: |
- case GESTURE_2F_SCROLL_RIGHT: |
- input_report_key(input_kbd, KEY_LEFTSHIFT, 0); |
- input_sync(input_kbd); |
- touch->hscroll_right = 0; |
- touch->delta_scroll_right = 0; |
- break; |
- case GESTURE_2F_ROTATE: |
- break; |
- case GESTURE_2F_PINCH: |
- break; |
- case GESTURE_2F_TAP: |
- break; |
- case GESTURE_2F_DRAG: |
- if (touch->platform_data->use_absolute_mode) { |
- input_report_key(input, BTN_TOUCH, 0); |
- input_report_abs(input, ABS_PRESSURE, 0); |
- input_report_key(input, BTN_LEFT, 0); |
- cyapa_report_fingers(input, 0); |
- input_sync(input); |
- } |
- |
- touch->gesture_2F_drag_started = 0; |
- touch->prev_abs_x = -1; |
- touch->prev_abs_y = -1; |
- break; |
- case GESTURE_FLICK: |
- case GESTURE_2F_FLICK: |
- case GESTURE_3F_FLICK: |
- case GESTURE_4F_FLICK: |
- case GESTURE_5F_FLICK: |
- break; |
- default: |
- break; |
- } |
- } |
- } |
- } |
} |
-} |
-static void cyapa_gesture_report(struct cyapa_i2c *touch, |
- struct cyapa_report_data *report_data, |
- struct cyapa_gesture *gesture) |
-{ |
- struct input_dev *input = touch->input; |
- struct input_dev *input_wheel = touch->input_wheel; |
- struct input_dev *input_kbd = touch->input_kbd; |
- int delta = 0; |
- struct cyapa_preferences *preferences = &touch->preferences; |
- int threshold = 0; |
- int value = 0; |
- |
- switch (gesture->id) { |
- case GESTURE_PALM_REJECTIOIN: |
- /* when palm rejection gesture is trigged, do not move cursor any more, |
- ** just operation as no finger touched on trackpad. |
- */ |
- if (touch->platform_data->use_absolute_mode) { |
- input_report_key(input, BTN_TOUCH, 0); |
- input_report_abs(input, ABS_PRESSURE, 0); |
- input_report_abs(input, ABS_TOOL_WIDTH, 0); |
- cyapa_report_fingers(input, 0); |
- } |
- |
- touch->prev_abs_x = -1; |
- touch->prev_abs_y = -1; |
- |
- input_report_key(input, BTN_LEFT, report_data->button & 0x01); |
- input_report_key(input, BTN_RIGHT, report_data->button & 0x02); |
- input_report_key(input, BTN_MIDDLE, report_data->button & 0x04); |
- |
- input_sync(input); |
- |
- DBGPRINTK(("%s: report palm rejection\n", __func__)); |
- break; |
- case GESTURE_SINGLE_TAP : |
- if (touch->platform_data->use_absolute_mode) { |
- input_report_key(input, BTN_TOUCH, 0); |
- input_report_abs(input, ABS_PRESSURE, 0); |
- input_report_key(input, BTN_LEFT, 0); |
- input_sync(input); |
- |
- /* in absolute mode use BTN_FINGER to trigger click. */ |
- break; |
- } |
- |
- input_report_key(input, BTN_LEFT, 1); |
- input_sync(input); |
- |
- input_report_key(input, BTN_LEFT, 0); |
- input_sync(input); |
- |
- DBGPRINTK(("%s: report single tap\n", __func__)); |
- break; |
- case GESTURE_DOUBLE_TAP: |
- if (touch->platform_data->use_absolute_mode) { |
- input_report_key(input, BTN_TOUCH, 0); |
- input_report_abs(input, ABS_PRESSURE, 0); |
- input_report_key(input, BTN_LEFT, 0); |
- input_report_key(input, BTN_RIGHT, 0); |
- input_sync(input); |
- } |
- |
- input_report_key(input, BTN_LEFT, 1); |
- input_sync(input); |
- |
- input_report_key(input, BTN_LEFT, 0); |
- input_sync(input); |
- |
- input_report_key(input, BTN_LEFT, 1); |
- input_sync(input); |
- |
- input_report_key(input, BTN_LEFT, 0); |
- input_sync(input); |
- |
- DBGPRINTK(("%s: report double tap\n", __func__)); |
- break; |
- case GESTURE_TAP_AND_HOLD: |
- /* one finger click and hold for more than definitioin time, then to do something. */ |
- DBGPRINTK(("%s: no gesture for Tap and hold yet.\n", __func__)); |
- break; |
- case GESTURE_EDGE_MOTION: |
- DBGPRINTK(("%s: no gesture for edge motion yet.\n", __func__)); |
- break; |
- case GESTURE_DRAG: |
- /* 1-finger drag. 1-finger double click and hold, then move the finger. */ |
- if (touch->platform_data->use_absolute_mode) { |
- touch->xy_touchs_included_bits = 0x01; |
- cyapa_calculate_abs_xy(touch, report_data); |
- |
- input_report_key(input, BTN_TOUCH, 1); |
- input_report_abs(input, ABS_X, touch->abs_x); |
- input_report_abs(input, ABS_Y, touch->abs_y); |
- input_report_abs(input, ABS_PRESSURE, report_data->avg_pressure); |
- cyapa_report_fingers(input, 1); |
- input_report_key(input, BTN_LEFT, 1); |
- input_sync(input); |
- } else { |
- input_report_rel(input, REL_X, report_data->rel_deltaX); |
- input_report_rel(input, REL_Y, report_data->rel_deltaY); |
- input_report_key(input, BTN_LEFT, 1); |
- input_sync(input); |
- } |
- |
- DBGPRINTK(("%s: 1 finger drag. \n", __func__)); |
- break; |
- case GESTURE_2F_ZOOM_IN: |
- delta = gesture->param2; |
- touch->zoomin_delta += delta; |
- while (touch->zoomin_delta > 0) { |
- input_report_key(input_kbd, KEY_LEFTCTRL, 1); |
- input_report_key(input_kbd, KEY_KPPLUS, 1); |
- input_sync(input_kbd); |
- |
- input_report_key(input_kbd, KEY_LEFTCTRL, 0); |
- input_report_key(input_kbd, KEY_KPPLUS, 0); |
- input_sync(input_kbd); |
- |
- touch->zoomin_delta -= 1; |
- } |
- |
- DBGPRINTK(("%s: 2F zoom in \n", __func__)); |
- break; |
- case GESTURE_2F_ZOOM_OUT: |
- delta = gesture->param2; |
- touch->zoomout_delta += delta; |
- while (touch->zoomout_delta > 0) { |
- input_report_key(input_kbd, KEY_LEFTCTRL, 1); |
- input_report_key(input_kbd, KEY_KPMINUS, 1); |
- input_sync(input_kbd); |
- |
- input_report_key(input_kbd, KEY_LEFTCTRL, 0); |
- input_report_key(input_kbd, KEY_KPMINUS, 0); |
- input_sync(input_kbd); |
- |
- touch->zoomout_delta -= 1; |
- } |
- |
- DBGPRINTK(("%s: 2F zoom out \n", __func__)); |
- break; |
- case GESTURE_SCROLL_UP: |
- case GESTURE_2F_SCROLL_UP: |
- delta = gesture->param2; |
- |
- threshold = preferences->vscroll.default_threshold; |
- value = 1; |
- touch->delta_scroll_up += delta; |
- |
- if (touch->delta_scroll_up < threshold) { |
- /* keep small movement also can work. */ |
- input_report_rel(input_wheel, REL_WHEEL, value); |
- input_sync(input_wheel); |
- |
- touch->delta_scroll_up = 0; |
- break; |
- } |
- |
- if (touch->delta_scroll_up > preferences->vscroll.fast_threshold) { |
- /* fast scroll, reset threshold value. */ |
- threshold = 1; |
- value = 16; |
- } else { |
- /* middle scroll speed. */ |
- threshold = 2; |
- value = 2; |
- } |
- |
- while (touch->delta_scroll_up >= threshold) { |
- input_report_rel(input_wheel, REL_WHEEL, value*2/threshold); |
- input_sync(input_wheel); |
- |
- touch->delta_scroll_up -= threshold*value; |
- } |
- |
- DBGPRINTK(("%s: scroll up, fingers=%d\n", |
- __func__, report_data->touch_fingers)); |
- break; |
- case GESTURE_SCROLL_DOWN: |
- case GESTURE_2F_SCROLL_DOWN: |
- delta = gesture->param2; |
- threshold = preferences->vscroll.default_threshold; |
- value = 1; |
- touch->delta_scroll_down += delta; |
- |
- if (touch->delta_scroll_down < threshold) { |
- /* keep small movement also can work. */ |
- input_report_rel(input_wheel, REL_WHEEL, -value); |
- input_sync(input_wheel); |
- |
- touch->delta_scroll_down = 0; |
- break; |
- } |
- |
- if (touch->delta_scroll_down > preferences->hscroll.fast_threshold) { |
- /* fast scroll, reset threshold value. */ |
- threshold = 1; |
- value = 16; |
- } else { |
- /* middle scroll speed. */ |
- threshold = 2; |
- value = 2; |
- } |
- |
- while (touch->delta_scroll_down >= threshold) { |
- input_report_rel(input_wheel, REL_WHEEL, -value*2/threshold); |
- input_sync(input_wheel); |
- |
- touch->delta_scroll_down -= threshold*value; |
- } |
- |
- DBGPRINTK(("%s: scroll down, finger=%d\n", |
- __func__, report_data->touch_fingers)); |
- break; |
- case GESTURE_SCROLL_LEFT: |
- case GESTURE_2F_SCROLL_LEFT: |
- delta = gesture->param2; |
- #if 1 |
- while (delta > 0) { |
- input_report_key(input_kbd, KEY_LEFT, 1); |
- input_sync(input_kbd); |
- |
- input_report_key(input_kbd, KEY_LEFT, 0); |
- input_sync(input_kbd); |
- |
- delta -= 4; |
- } |
- #else |
- if (0 == touch->hscroll_left) { |
- /* Don't why, when report kbd and mouse/wheel event |
- ** in the same routine, kbd event will be delayed to take effect. |
- ** that is when kbd and wheel events are reported at same time, |
- ** wheel event will take effect immediatelly, but kdb event will be |
- ** delayed some time to take effect, so the combination of kbd and |
- ** wheel won't take effect any more here when kbd is delayed. |
- ** horizontal scroll won't take effect for some time. |
- ** So, we delay some time to report wheel event also, here. |
- ** but it still not accurate enouch, so horizontal scroll will also miss, |
- ** and become a vertical scroll. |
- */ |
- input_report_key(input_kbd, KEY_LEFTSHIFT, 1); |
- input_sync(input_kbd); |
- touch->hscroll_left = delta; |
- } else { |
- while (delta > 0) { |
- input_report_rel(input_wheel, REL_WHEEL, 1); |
- input_sync(input_wheel); |
- |
- delta -= 1; |
- } |
- } |
- #endif |
- DBGPRINTK(("%s: scroll left, finger=%d\n", |
- __func__, report_data->touch_fingers)); |
- break; |
- case GESTURE_SCROLL_RIGHT: |
- case GESTURE_2F_SCROLL_RIGHT: |
- delta = gesture->param2; |
- #if 1 |
- while (delta > 0) { |
- input_report_key(input_kbd, KEY_RIGHT, 1); |
- input_sync(input_kbd); |
- |
- input_report_key(input_kbd, KEY_RIGHT, 0); |
- input_sync(input_kbd); |
- |
- delta -= 4; |
- } |
- #else |
- if (0 == touch->hscroll_right) { |
- /* Don't why, when report kbd and mouse/wheel event |
- ** in the same routine, kbd event will be delayed to take effect. |
- ** that is when kbd and wheel events are reported at same time, |
- ** wheel event will take effect immediatelly, but kdb event will be |
- ** delayed some time to take effect, so the combination of kbd and |
- ** wheel won't take effect any more here when kbd is delayed. |
- ** horizontal scroll won't take effect for some time. |
- ** So, we delay some time to report wheel event also, here. |
- ** but it still not accurate enouch, so horizontal scroll will also miss, |
- ** and become a vertical scroll. |
- */ |
- input_report_key(input_kbd, KEY_LEFTSHIFT, 1); |
- input_sync(input_kbd); |
- touch->hscroll_right = delta; |
- } else { |
- while (delta > 0) { |
- input_report_rel(input_wheel, REL_WHEEL, -1); |
- input_sync(input_wheel); |
- |
- delta -= 1; |
- } |
- } |
- #endif |
- DBGPRINTK(("%s: scroll right, finger=%d\n", |
- __func__, report_data->touch_fingers)); |
- break; |
- case GESTURE_2F_ROTATE: |
- DBGPRINTK(("%s: 2 finger rotate \n", __func__)); |
- break; |
- case GESTURE_2F_PINCH: |
- DBGPRINTK(("%s: 2 finger pinch\n", __func__)); |
- break; |
- case GESTURE_2F_TAP: |
- /* 2-finger tap, active like right button press and relase. */ |
- if (touch->platform_data->use_absolute_mode) { |
- input_report_key(input, BTN_TOUCH, 0); |
- input_report_abs(input, ABS_PRESSURE, 0); |
- input_report_key(input, BTN_LEFT, 0); |
- input_report_key(input, BTN_RIGHT, 0); |
- input_sync(input); |
- } |
- |
- input_report_key(input, BTN_RIGHT, 1); |
- input_sync(input); |
- |
- input_report_key(input, BTN_RIGHT, 0); |
- input_sync(input); |
- |
- DBGPRINTK(("%s: report 2 fingers tap, active like right button.\n", __func__)); |
- break; |
- case GESTURE_2F_DRAG: |
- /* first finger click and hold, and second finger moving for dragging. */ |
- if (touch->gesture_2F_drag_started == 0) { |
- touch->xy_touchs_included_bits = 0x01; |
- touch->prev_abs_x = -1; |
- touch->prev_abs_y = -1; |
- cyapa_calculate_abs_xy(touch, report_data); |
- |
- /* firstly, move move cursor to the target for drag. */ |
- input_report_key(input, BTN_TOUCH, 1); |
- if (touch->platform_data->use_absolute_mode) { |
- input_report_abs(input, ABS_X, touch->abs_x); |
- input_report_abs(input, ABS_Y, touch->abs_y); |
- input_report_abs(input, ABS_PRESSURE, report_data->avg_pressure); |
- cyapa_report_fingers(input, 1); |
- } |
- input_report_key(input, BTN_LEFT, 0); |
- input_report_key(input, BTN_RIGHT, 0); |
- input_sync(input); |
- |
- /* second, stop cursor on the target for drag. */ |
- touch->prev_abs_x = -1; |
- touch->prev_abs_y = -1; |
- if (touch->platform_data->use_absolute_mode) { |
- input_report_key(input, BTN_TOUCH, 0); |
- input_report_abs(input, ABS_PRESSURE, 0); |
- input_sync(input); |
- } |
- |
- /* third, select the target for drag. */ |
- input_report_key(input, BTN_LEFT, 1); |
- input_sync(input); |
- |
- /* go to step four. */ |
- touch->gesture_2F_drag_started = 1; |
- } |
- |
- /* fourth, move cursor for dragging. */ |
- touch->xy_touchs_included_bits = 0x02; |
- cyapa_calculate_abs_xy(touch, report_data); |
- |
- if (touch->platform_data->use_absolute_mode) { |
- input_report_key(input, BTN_TOUCH, 1); |
- input_report_abs(input, ABS_X, touch->abs_x); |
- input_report_abs(input, ABS_Y, touch->abs_y); |
- input_report_abs(input, ABS_PRESSURE, report_data->avg_pressure); |
- cyapa_report_fingers(input, 1); |
- } else { |
- input_report_rel(input, REL_X, report_data->rel_deltaX); |
- input_report_rel(input, REL_Y, report_data->rel_deltaY); |
- input_sync(input); |
- } |
- input_report_key(input, BTN_LEFT, 1); |
- input_sync(input); |
- |
- DBGPRINTK(("%s: report 2 fingers drag\n", __func__)); |
- break; |
- case GESTURE_FLICK: |
- case GESTURE_2F_FLICK: |
- case GESTURE_3F_FLICK: |
- case GESTURE_4F_FLICK: |
- case GESTURE_5F_FLICK: |
- touch->xy_touchs_included_bits = report_data->touch_fingers; |
- DBGPRINTK(("%s: no flick gesture supported yet, , finger=%d\n", |
- __func__, report_data->touch_fingers)); |
- break; |
- default: |
- DBGPRINTK(("%s: default, unknown gesture for reporting.\n", __func__)); |
- break; |
- } |
+ /* DEBUG: dump parsed report data */ |
+ cyapa_dump_report_data(__func__, report_data); |
} |
-static int cyapa_rel_input_report_data(struct cyapa_i2c *touch, struct cyapa_report_data *report_data) |
+static int cyapa_handle_input_report_data(struct cyapa_i2c *touch, |
+ struct cyapa_report_data *report_data) |
{ |
int i; |
struct input_dev *input = touch->input; |
- /* step 1: process gestures firstly if trigged. */ |
- cyapa_process_prev_gesture_report(touch, report_data); |
- if (report_data->gestures_count > 0) { |
- DBGPRINTK(("%s: do gesture report, gestures_count = %d\n", |
- __func__, report_data->gestures_count)); |
- /* gesture trigged */ |
- for (i=0; i<report_data->gestures_count; i++) { |
- cyapa_gesture_report(touch, report_data, &report_data->gestures[i]); |
- } |
- |
- /* when gestures are trigged, cursor should be fixed. */ |
- return report_data->gestures_count; |
+ /* report raw trackpad data. */ |
+ for (i = 0; i < report_data->touch_fingers; i++) { |
+ input_report_abs(input, ABS_MT_POSITION_X, |
+ report_data->touchs[i].x); |
+ input_report_abs(input, ABS_MT_POSITION_Y, |
+ report_data->touchs[i].y); |
+ input_report_abs(input, ABS_MT_TOUCH_MAJOR, |
+ report_data->touchs[i].pressure > 0 ? |
+ CYAPA_MT_TOUCH_MAJOR : 0); |
+ input_report_abs(input, ABS_MT_PRESSURE, |
+ report_data->touchs[i].pressure); |
+ input_mt_sync(input); |
} |
- /* when multi-fingers touched, cursour should also be fixed. */ |
- if (report_data->touch_fingers == 1) { |
- /* Report the deltas */ |
- input_report_rel(input, REL_X, report_data->rel_deltaX); |
- input_report_rel(input, REL_Y, report_data->rel_deltaY); |
- } |
- |
- /* Report the button event */ |
- input_report_key(input, BTN_LEFT, (report_data->button & 0x01)); |
- input_report_key(input, BTN_RIGHT, (report_data->button & 0x02)); |
- input_report_key(input, BTN_MIDDLE, (report_data->button & 0x04)); |
- input_sync(input); |
- |
- DBGPRINTK(("%s: deltax = %d \n", __func__, report_data->rel_deltaX)); |
- DBGPRINTK(("%s: deltay = %d \n", __func__, report_data->rel_deltaY)); |
- DBGPRINTK(("%s: left_btn = %d \n", __func__, report_data->button & 0x01)); |
- DBGPRINTK(("%s: right_btn = %d \n", __func__, report_data->button & 0x02)); |
- DBGPRINTK(("%s: middle_btn = %d \n", __func__, report_data->button & 0x04)); |
- |
- return report_data->rel_deltaX |report_data->rel_deltaY | report_data->button; |
-} |
- |
-static int cyapa_abs_input_report_data(struct cyapa_i2c *touch, struct cyapa_report_data *report_data) |
-{ |
- int i; |
- int have_data = 0; |
- struct input_dev *input = touch->input; |
- |
- DBGPRINTK(("%s: ... \n", __func__)); |
- |
- cyapa_process_prev_gesture_report(touch, report_data); |
- if (report_data->gestures_count > 0) { |
- DBGPRINTK(("%s: do gesture report, gestures_count = %d\n", |
- __func__, report_data->gestures_count)); |
- /* gesture trigged */ |
- for (i=0; i<report_data->gestures_count; i++) { |
- cyapa_gesture_report(touch, report_data, &report_data->gestures[i]); |
- } |
- } else if (report_data->touch_fingers) { |
- /* no gesture trigged, report touchs move data. */ |
- if (report_data->touch_fingers > 1) { |
- DBGPRINTK(("%s: more then 1 finger touch, touch_fingers = %d\n", |
- __func__, report_data->touch_fingers)); |
- /* |
- ** two and much more finger on trackpad are used for gesture only, |
- ** so even no gesture are trigged, do not make cursor move also. |
- ** Here, must keep on report finger touched, otherwise, when multi-finger |
- ** touch not in same time will triiged clikc. |
- */ |
- input_report_key(input, BTN_TOUCH, 1); |
- input_report_abs(input, ABS_PRESSURE, report_data->avg_pressure); |
- input_report_abs(input, ABS_TOOL_WIDTH, CYAPA_TOOL_WIDTH); |
- #if GESTURE_MULTI_TOUCH_ONE_CLICK |
- cyapa_report_fingers(input, report_data->touch_fingers); |
- #else |
- cyapa_report_fingers(input, 1); |
- #endif |
- |
- touch->prev_abs_x = -1; |
- touch->prev_abs_y = -1; |
- |
- input_report_key(input, BTN_LEFT, report_data->button & 0x01); |
- input_report_key(input, BTN_RIGHT, report_data->button & 0x02); |
- input_report_key(input, BTN_MIDDLE, report_data->button & 0x04); |
- |
- input_sync(input); |
- } else { |
- DBGPRINTK(("%s: 1 finger touch, make cursor move\n", __func__)); |
- /* avoid cursor jump, when touched finger changed from multi-touch |
- ** to one finger touch. */ |
- if (touch->prev_touch_fingers > 1) { |
- /* cheat system or application that no finger has touched to may |
- ** them lock the cursor when later only one finger touched on trackpad. */ |
- input_report_key(input, BTN_TOUCH, 0); |
- input_report_abs(input, ABS_PRESSURE, 0); |
- input_report_abs(input, ABS_TOOL_WIDTH, 0); |
- cyapa_report_fingers(input, 0); |
- touch->prev_abs_x = -1; |
- touch->prev_abs_y = -1; |
- input_report_key(input, BTN_LEFT, report_data->button & 0x01); |
- input_report_key(input, BTN_RIGHT, report_data->button & 0x02); |
- input_report_key(input, BTN_MIDDLE, report_data->button & 0x04); |
- input_sync(input); |
- } else { |
- /* only 1 finger can make cursor move. */ |
- touch->xy_touchs_included_bits = 0x01; |
- cyapa_calculate_abs_xy(touch, report_data); |
- |
- input_report_key(input, BTN_TOUCH, 1); |
- input_report_abs(input, ABS_X, touch->abs_x); |
- input_report_abs(input, ABS_Y, touch->abs_y); |
- input_report_abs(input, ABS_PRESSURE, report_data->avg_pressure); |
- input_report_abs(input, ABS_TOOL_WIDTH, CYAPA_TOOL_WIDTH); |
- |
- cyapa_report_fingers(input, report_data->touch_fingers); |
- |
- input_report_key(input, BTN_LEFT, report_data->button & 0x01); |
- input_report_key(input, BTN_RIGHT, report_data->button & 0x02); |
- input_report_key(input, BTN_MIDDLE, report_data->button & 0x04); |
- |
- input_sync(input); |
- } |
- } |
- } else { |
- /* |
- ** 1. two or more fingers on trackpad are used for gesture only, |
- ** so even no gesture are trigged, do not make cursor move also. |
- ** 2. no gesture and no touch on trackpad. |
- */ |
- DBGPRINTK(("%s: no finger touch.\n", __func__)); |
- |
- input_report_key(input, BTN_TOUCH, 0); |
- input_report_abs(input, ABS_PRESSURE, 0); |
- input_report_abs(input, ABS_TOOL_WIDTH, 0); |
- cyapa_report_fingers(input, 0); |
- |
- touch->prev_abs_x = -1; |
- touch->prev_abs_y = -1; |
+ /* |
+ * report mouse device data. |
+ * always track the first finger. |
+ * when detached, start over |
+ */ |
+ input_report_key(input, BTN_TOUCH, (report_data->touch_fingers > 0)); |
+ cyapa_report_fingers(input, report_data->touch_fingers); |
- input_report_key(input, BTN_LEFT, report_data->button & 0x01); |
- input_report_key(input, BTN_RIGHT, report_data->button & 0x02); |
- input_report_key(input, BTN_MIDDLE, report_data->button & 0x04); |
+ input_report_abs(input, ABS_TOOL_WIDTH, 15); |
+ input_report_abs(input, ABS_X, report_data->touchs[0].x); |
+ input_report_abs(input, ABS_Y, report_data->touchs[0].y); |
+ input_report_abs(input, ABS_PRESSURE, report_data->touchs[0].pressure); |
- input_sync(input); |
- } |
+ input_report_key(input, BTN_LEFT, report_data->button & 0x01); |
- /* store current active gestures array into prev active gesture array. */ |
- for (i=0; i<MAX_FINGERS; i++) { |
- touch->prev_active_gestures[i] = touch->cur_active_gestures[i]; |
- } |
- touch->prev_touch_fingers = report_data->touch_fingers; |
- |
- have_data = (report_data->gestures_count + |
- report_data->touch_fingers + report_data->button); |
+ input_sync(input); |
- DBGPRINTK(("%s: gesture count = %d, touch finger =%d, button = 0x%02x\n", |
- __func__, report_data->gestures_count, |
- report_data->touch_fingers, report_data->button)); |
- return have_data; |
+ return report_data->touch_fingers | (report_data->button & 0x01); |
} |
static bool cyapa_i2c_get_input(struct cyapa_i2c *touch) |
{ |
- int i; |
int ret_read_size = -1; |
int read_length = 0; |
union cyapa_reg_data reg_data; |
@@ -1523,7 +1196,7 @@ static bool cyapa_i2c_get_input(struct cyapa_i2c *touch) |
struct cyapa_reg_data_gen2 *gen2_data; |
struct cyapa_report_data report_data; |
- DBGPRINTK(("%s: start ... \n", __func__)); |
+ DBGPRINTK(("%s: start ...\n", __func__)); |
memset(®_data, 0, sizeof(union cyapa_reg_data)); |
@@ -1535,101 +1208,49 @@ static bool cyapa_i2c_get_input(struct cyapa_i2c *touch) |
read_length = (int)sizeof(struct cyapa_reg_data_gen1); |
else |
read_length = (int)sizeof(struct cyapa_reg_data_gen2); |
- DBGPRINTK(("%s: read gen%d data, read length=%d \n", __func__, |
- ((touch->platform_data->gen == CYAPA_GEN1)?1:2), read_length)); |
- ret_read_size = cyapa_i2c_reg_read_block(touch->client, |
+ DBGPRINTK(("%s: read gen%d data, read length=%d\n", __func__, |
+ ((touch->platform_data->gen == CYAPA_GEN1) ? 1 : 2), |
+ read_length)); |
+ ret_read_size = cyapa_i2c_reg_read_block(touch, |
DATA_REG_START_OFFSET, |
read_length, |
(u8 *)®_data); |
if (ret_read_size < 0) { |
- DBGPRINTK(("%s: I2C read data from trackpad error = %d \n", |
+ DBGPRINTK(("%s: I2C read data from trackpad error = %d\n", |
__func__, ret_read_size)); |
return 0; |
} |
if (cyapa_verify_data_device(touch, ®_data)) { |
- DBGPRINTK(("%s: verify data device failed, invalid data, skip.\n", __func__)); |
+ DBGPRINTK(("%s: verify data device failed, \ |
+ invalid data, skip.\n", __func__)); |
return 0; |
} |
/* process and parse raw data that read from Trackpad. */ |
memset(&report_data, 0, sizeof(struct cyapa_report_data)); |
- touch->xy_touchs_included_bits = 0; |
- /* initialize current active gestures array. */ |
- for (i=0; i<MAX_FINGERS; i++) { |
- touch->cur_active_gestures[i] = 0; |
- } |
- |
- if (touch->platform_data->gen == CYAPA_GEN1) { |
+ if (touch->platform_data->gen == CYAPA_GEN1) |
cyapa_parse_gen1_data(touch, gen1_data, &report_data); |
- } else { |
+ else |
cyapa_parse_gen2_data(touch, gen2_data, &report_data); |
- } |
/* report data to input subsystem. */ |
- if (touch->platform_data->use_absolute_mode == false) { |
- return cyapa_rel_input_report_data(touch, &report_data); |
- } else { |
- return cyapa_abs_input_report_data(touch, &report_data); |
- } |
-} |
- |
-static void cyapa_i2c_reschedule_work(struct cyapa_i2c *touch, unsigned long delay) |
-{ |
- unsigned long flags; |
- |
- spin_lock_irqsave(&touch->lock, flags); |
- |
- /* |
- * If work is already scheduled then subsequent schedules will not |
- * change the scheduled time that's why we have to cancel it first. |
- */ |
- __cancel_delayed_work(&touch->dwork); |
- schedule_delayed_work(&touch->dwork, delay); |
- |
- spin_unlock_irqrestore(&touch->lock, flags); |
-} |
- |
-static irqreturn_t cyapa_i2c_irq(int irq, void *dev_id) |
-{ |
- struct cyapa_i2c *touch = dev_id; |
- |
- DBGPRINTK(("%s: trackpad interrupt captured. report_rate=%d; read_pending=%d\n", |
- __func__, touch->platform_data->report_rate, touch->read_pending)); |
- |
- if (touch->platform_data->report_rate == 0) { |
- /* |
- ** no limitatioin for data reporting. |
- ** the report rate depending on trackpad max report rate. |
- ** this is the default report mode. |
- */ |
- cyapa_i2c_reschedule_work(touch, 0); |
- } else { |
- /* |
- ** when use limited report rate, some important data packages may be lost. |
- ** Such as a tap or double tap gesture may be lost. |
- ** So firmware need to keep this data until there data is read. |
- */ |
- if (!touch->read_pending) { |
- touch->read_pending = 1; |
- cyapa_i2c_reschedule_work(touch, touch->scan_ms); |
- } |
- } |
- |
- return IRQ_HANDLED; |
+ return cyapa_handle_input_report_data(touch, &report_data); |
} |
/* Control the Device polling rate / Work Handler sleep time */ |
-static unsigned long cyapa_i2c_adjust_delay(struct cyapa_i2c *touch, bool have_data) |
+static unsigned long cyapa_i2c_adjust_delay(struct cyapa_i2c *touch, |
+ bool have_data) |
{ |
unsigned long delay, nodata_count_thres; |
- if (touch->platform_data->use_polling_mode) { |
- delay =touch->platform_data->polling_interval_time_active; |
+ if (touch->down_to_polling_mode == true) { |
+ delay = touch->platform_data->polling_interval_time_active; |
if (have_data) { |
touch->no_data_count = 0; |
} else { |
- nodata_count_thres = CYAPA_NO_DATA_THRES / touch->scan_ms; |
+ nodata_count_thres = |
+ CYAPA_NO_DATA_THRES / touch->scan_ms; |
if (touch->no_data_count < nodata_count_thres) |
touch->no_data_count++; |
else |
@@ -1646,27 +1267,58 @@ static unsigned long cyapa_i2c_adjust_delay(struct cyapa_i2c *touch, bool have_d |
static void cyapa_i2c_work_handler(struct work_struct *work) |
{ |
bool have_data; |
- struct cyapa_i2c *touch = container_of(work, struct cyapa_i2c, dwork.work); |
+ struct cyapa_i2c *touch = |
+ container_of(work, struct cyapa_i2c, dwork.work); |
unsigned long delay; |
- DBGPRINTK(("%s: start ... \n", __func__)); |
+ spin_lock(&touch->misc_spinlock); |
+ if (touch->fw_work_mode == CYAPA_BOOTLOAD_MODE) { |
+ spin_unlock(&touch->misc_spinlock); |
+ cyapa_update_firmware_dispatch(touch); |
Olof Johansson
2011/05/02 05:47:12
The above would be better to be a return at the en
|
+ } else { |
+ spin_unlock(&touch->misc_spinlock); |
- have_data = cyapa_i2c_get_input(touch); |
+ have_data = cyapa_i2c_get_input(touch); |
+ /* |
+ * While interrupt driven, there is no real need to poll the |
+ * device. But touchpads are very sensitive, so there could be |
+ * errors related to physical environment and the attention |
+ * line isn'tneccesarily asserted. In such case we can lose |
+ * the touchpad. We poll the device once in |
+ * CYAPA_THREAD_IRQ_SLEEP_SECS and if error is detected, |
+ * we try to reset and reconfigure the touchpad. |
+ */ |
+ delay = cyapa_i2c_adjust_delay(touch, have_data); |
+ /* if needs fixed interval time trackpad scan, open it. |
+ cyapa_i2c_reschedule_work(touch, delay); |
+ */ |
Olof Johansson
2011/05/02 05:47:12
Please don't add dead code.
|
+ } |
+} |
+ |
+static void cyapa_i2c_reschedule_work(struct cyapa_i2c *touch, |
+ unsigned long delay) |
+{ |
+ unsigned long flags; |
+ |
+ spin_lock_irqsave(&touch->lock, flags); |
/* |
- * While interrupt driven, there is no real need to poll the device. |
- * But touchpads are very sensitive, so there could be errors |
- * related to physical environment and the attention line isn't |
- * neccesarily asserted. In such case we can lose the touchpad. |
- * We poll the device once in CYAPA_THREAD_IRQ_SLEEP_SECS and |
- * if error is detected, we try to reset and reconfigure the touchpad. |
+ * If work is already scheduled then subsequent schedules will not |
+ * change the scheduled time that's why we have to cancel it first. |
*/ |
- delay = cyapa_i2c_adjust_delay(touch, have_data); |
- //cyapa_i2c_reschedule_work(touch, delay); |
+ __cancel_delayed_work(&touch->dwork); |
+ schedule_delayed_work(&touch->dwork, delay); |
+ |
+ spin_unlock_irqrestore(&touch->lock, flags); |
+} |
+ |
+static irqreturn_t cyapa_i2c_irq(int irq, void *dev_id) |
+{ |
+ struct cyapa_i2c *touch = dev_id; |
+ |
+ cyapa_i2c_reschedule_work(touch, 0); |
- touch->read_pending = 0; |
- |
- DBGPRINTK(("%s: done ... \n", __func__)); |
+ return IRQ_HANDLED; |
} |
static int cyapa_i2c_open(struct input_dev *input) |
@@ -1675,29 +1327,27 @@ static int cyapa_i2c_open(struct input_dev *input) |
int retval; |
if (0 == touch->open_count) { |
- /* Since input_dev mouse, wheel, and kbd will all use same open and close routines. |
- ** But indeed, reset config to trackpad once is enought, |
- ** So when trackpad is open for the first time, reset it. |
- ** for other time not do it. |
- */ |
retval = cyapa_i2c_reset_config(touch); |
if (retval) { |
- DBGPRINTK(("%s: failed to reset i2c trackpad. error = %d \n", __func__, retval)); |
+ DBGPRINTK(("%s: failed to reset i2c trackpad. \ |
+ error = %d\n", __func__, retval)); |
return retval; |
} |
} |
touch->open_count++; |
- if (touch->platform_data->use_polling_mode) { |
+ if (touch->down_to_polling_mode == true) { |
/* |
- ** for the firstly time, it is set to CYAPA_NO_DATA_SLEEP_MSECS, |
+ ** At firstly time, it is set to CYAPA_NO_DATA_SLEEP_MSECS, |
** when data is read from trackpad, the read speed will |
** be pull up. |
Daniel Kurtz
2011/05/02 12:43:47
I'm not sure what this comment means.
Perhaps:
/*
|
*/ |
- cyapa_i2c_reschedule_work(touch, msecs_to_jiffies(CYAPA_NO_DATA_SLEEP_MSECS)); |
+ cyapa_i2c_reschedule_work(touch, |
+ msecs_to_jiffies(CYAPA_NO_DATA_SLEEP_MSECS)); |
} |
- DBGPRINTK(("%s: touch->open_count = %d ... \n", __func__, touch->open_count)); |
+ DBGPRINTK(("%s: touch->open_count = %d ...\n", |
+ __func__, touch->open_count)); |
return 0; |
} |
@@ -1709,27 +1359,15 @@ static void cyapa_i2c_close(struct input_dev *input) |
touch->open_count--; |
if (0 == touch->open_count) { |
- /* Since input_dev mouse, wheel, and kbd will all use same open and close routines. |
+ /* Since input_dev mouse, wheel, and kbd will all use same open |
+ ** and close routines. |
** so when all mouse, wheel and kbd input_dev is closed, |
** then cancel the delayed work routine. |
Daniel Kurtz
2011/05/02 12:43:47
/*
* Since the mouse, wheel and kbd input_dev all
|
*/ |
cancel_delayed_work_sync(&touch->dwork); |
} |
- DBGPRINTK(("%s: touch->open_count ... \n", __func__, touch->open_count)); |
-} |
- |
-void cyapa_set_preferences(struct cyapa_preferences *preferences) |
-{ |
- /* set default setting for hscroll. */ |
- preferences->vscroll.default_threshold = 4; |
- preferences->vscroll.middle_threshold = 8; |
- preferences->vscroll.fast_threshold = 16; |
- |
- /* set default setting for vscroll. */ |
- preferences->hscroll.default_threshold = 4; |
- preferences->hscroll.middle_threshold = 8; |
- preferences->hscroll.fast_threshold = 16; |
+ DBGPRINTK(("%s: touch->open_count=%d\n", __func__, touch->open_count)); |
} |
static struct cyapa_i2c *cyapa_i2c_touch_create(struct i2c_client *client) |
@@ -1740,38 +1378,24 @@ static struct cyapa_i2c *cyapa_i2c_touch_create(struct i2c_client *client) |
if (!touch) |
return NULL; |
- DBGPRINTK(("%s: client=0x%p, allocate memory for touch successfully.\n", |
- __func__, client)); |
- |
touch->platform_data = &cyapa_i2c_platform_data; |
if (client->dev.platform_data) { |
- DBGPRINTK(("%s: client->dev.platform_data is set, copy it.\n", __func__)); |
- *touch->platform_data = *(struct cyapa_platform_data *)client->dev.platform_data; |
+ *touch->platform_data = |
+ *(struct cyapa_platform_data *) |
+ client->dev.platform_data; |
} |
- #ifdef DBG_CYAPA_READ_BLOCK_DATA |
- cyapa_print_paltform_data(__func__, touch->platform_data); |
- #endif |
- |
- if (touch->platform_data->use_polling_mode && |
- (touch->platform_data->report_rate == 0)) { |
- /* when user miss setting platform data, |
- ** ensure that system is robust. |
- ** no divid zero error. */ |
- touch->platform_data->report_rate = CYAPA_POLLING_REPORTRATE_DEFAULT; |
- } |
- touch->scan_ms = touch->platform_data->report_rate?(1000 / touch->platform_data->report_rate):0; |
+ touch->scan_ms = touch->platform_data->report_rate |
+ ? (1000 / touch->platform_data->report_rate) : 0; |
touch->open_count = 0; |
- touch->prev_abs_x = -1; |
- touch->prev_abs_y = -1; |
touch->client = client; |
- touch->zoomin_delta = 0; |
- touch->zoomout_delta = 0; |
- touch->hscroll_left = 0; |
- touch->hscroll_right = 0; |
- touch->prev_touch_fingers = 0; |
- |
- cyapa_set_preferences(&touch->preferences); |
+ touch->down_to_polling_mode = false; |
+ global_touch = touch; |
+ touch->fw_work_mode = CYAPA_STREAM_MODE; |
+ touch->misc_open_count = 0; |
+ sema_init(&touch->misc_sem, 1); |
+ spin_lock_init(&touch->misc_spinlock); |
+ mutex_init(&touch->misc_mutex); |
INIT_DELAYED_WORK(&touch->dwork, cyapa_i2c_work_handler); |
spin_lock_init(&touch->lock); |
@@ -1779,15 +1403,16 @@ static struct cyapa_i2c *cyapa_i2c_touch_create(struct i2c_client *client) |
return touch; |
} |
-static int cyapa_create_input_dev_mouse(struct cyapa_i2c *touch) |
+static int cyapa_create_input_dev(struct cyapa_i2c *touch) |
{ |
int retval = 0; |
struct input_dev *input = NULL; |
input = touch->input = input_allocate_device(); |
if (!touch->input) { |
- dev_err(&touch->client->dev, "%s: Allocate memory for Input device failed: %d\n", |
- __func__, retval); |
+ dev_err(&touch->client->dev, |
+ "%s: Allocate memory for Input device failed: %d\n", |
+ __func__, retval); |
return -ENOMEM; |
} |
@@ -1795,66 +1420,55 @@ static int cyapa_create_input_dev_mouse(struct cyapa_i2c *touch) |
input->phys = touch->client->adapter->name; |
input->id.bustype = BUS_I2C; |
input->id.version = 1; |
+ input->id.product = 0; /* means any product in eventcomm. */ |
input->dev.parent = &touch->client->dev; |
input->open = cyapa_i2c_open; |
input->close = cyapa_i2c_close; |
input_set_drvdata(input, touch); |
- if (touch->platform_data->use_absolute_mode) |
- { |
- /* absolution data report mode. */ |
- __set_bit(EV_ABS, input->evbit); |
- __set_bit(EV_KEY, input->evbit); |
- |
- input_set_abs_params(input, ABS_X, touch->max_absolution_x/10, |
- touch->max_absolution_x/2, 0, 0); |
- input_set_abs_params(input, ABS_Y, touch->max_absolution_y/10, |
- touch->max_absolution_y/2, 0, 0); |
- input_set_abs_params(input, ABS_PRESSURE, 0, 255, 0, 0); |
- input_set_abs_params(input, ABS_TOOL_WIDTH, 0, 255, 0, 0); |
- |
- __set_bit(BTN_TOUCH, input->keybit); |
- __set_bit(BTN_TOOL_FINGER, input->keybit); |
- __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); |
- __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); |
- __set_bit(BTN_TOOL_QUADTAP, input->keybit); |
- |
- __set_bit(BTN_LEFT, input->keybit); |
- __set_bit(BTN_RIGHT, input->keybit); |
- __set_bit(BTN_MIDDLE, input->keybit); |
- |
- __clear_bit(EV_REL, input->evbit); |
- __clear_bit(REL_X, input->relbit); |
- __clear_bit(REL_Y, input->relbit); |
- __clear_bit(BTN_TRIGGER, input->keybit); |
- |
- input_abs_set_res(input, ABS_X, touch->max_absolution_x/touch->physical_size_x); |
- input_abs_set_res(input, ABS_Y, touch->max_absolution_y/touch->physical_size_y); |
- |
- DBGPRINTK(("%s: Use absolute data reporting mode. \n", __func__)); |
- } |
- else |
- { |
- /* relative data reporting mode. */ |
- __set_bit(EV_REL, input->evbit); |
- __set_bit(REL_X, input->relbit); |
- __set_bit(REL_Y, input->relbit); |
- |
- __set_bit(EV_KEY, input->evbit); |
- __set_bit(BTN_LEFT, input->keybit); |
- __set_bit(BTN_RIGHT, input->keybit); |
- __set_bit(BTN_MIDDLE, input->keybit); |
- |
- __clear_bit(EV_ABS, input->evbit); |
- |
- DBGPRINTK(("%s: Use relative data reporting mode. \n", __func__)); |
- } |
+ __set_bit(EV_ABS, input->evbit); |
+ |
+ input_set_abs_params(input, ABS_X, 0, touch->max_absolution_x, 0, 0); |
+ input_set_abs_params(input, ABS_Y, 0, touch->max_absolution_y, 0, 0); |
Daniel Kurtz
2011/05/02 12:43:47
Do you really still want to report non-MT axes in
|
+ input_set_abs_params(input, ABS_PRESSURE, 0, 255, 0, 0); |
+ input_set_abs_params(input, ABS_TOOL_WIDTH, 0, 255, 0, 0); |
+ |
+ /* finger touch area */ |
+ input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, |
+ 0, CYAPA_MT_MAX_TOUCH, 0, 0); |
Olof Johansson
2011/05/02 05:47:12
This is a typical case where it's OK to go avove 8
|
+ input_set_abs_params(input, ABS_MT_TOUCH_MINOR, |
+ 0, CYAPA_MT_MAX_TOUCH, 0, 0); |
+ /* finger approach area */ |
+ input_set_abs_params(input, ABS_MT_WIDTH_MAJOR, |
+ 0, CYAPA_MT_MAX_WIDTH, 0, 0); |
+ input_set_abs_params(input, ABS_MT_WIDTH_MINOR, |
+ 0, CYAPA_MT_MAX_WIDTH, 0, 0); |
Daniel Kurtz
2011/05/02 12:43:47
Do you really report both axes for both touch and
|
+ /* finger orientation */ |
+ input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0); |
+ /* finger position */ |
+ input_set_abs_params(input, ABS_MT_POSITION_X, |
+ 0, touch->max_absolution_x, 0, 0); |
Daniel Kurtz
2011/05/02 12:43:47
absolution and absolute have completely different
|
+ input_set_abs_params(input, ABS_MT_POSITION_Y, |
+ 0, touch->max_absolution_y, 0, 0); |
+ |
+ __set_bit(EV_KEY, input->evbit); |
+ __set_bit(BTN_TOUCH, input->keybit); |
+ __set_bit(BTN_TOOL_FINGER, input->keybit); |
+ __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); |
+ __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); |
+ __set_bit(BTN_TOOL_QUADTAP, input->keybit); |
+ |
+ __set_bit(BTN_LEFT, input->keybit); |
+ |
+ input_set_events_per_packet(input, 60); |
/* Register the device in input subsystem */ |
retval = input_register_device(touch->input); |
if (retval) { |
- dev_err(&touch->client->dev, "%s: Input device register failed: %d\n", __func__, retval); |
+ dev_err(&touch->client->dev, |
+ "%s: Input device register failed: %d\n", |
+ __func__, retval); |
input_free_device(input); |
return retval; |
Olof Johansson
2011/05/02 05:47:12
No need to return this here, just change the code
|
@@ -1863,192 +1477,85 @@ static int cyapa_create_input_dev_mouse(struct cyapa_i2c *touch) |
return 0; |
} |
-static int cyapa_create_input_dev_wheel(struct cyapa_i2c *touch) |
-{ |
- int retval =0; |
- struct input_dev *input_wheel = NULL; |
- |
- input_wheel = touch->input_wheel = input_allocate_device(); |
- if (!touch->input_wheel) { |
- dev_err(&touch->client->dev, "%s: Allocate memory for Input device failed: %d\n", |
- __func__, retval); |
- return -ENOMEM; |
- } |
- |
- input_wheel->name = "cyapa_i2c_wheel"; |
- input_wheel->phys = touch->client->adapter->name; |
- input_wheel->id.bustype = BUS_I2C; |
- input_wheel->id.version = 1; |
- input_wheel->dev.parent = &touch->client->dev; |
- input_wheel->open = cyapa_i2c_open; |
- input_wheel->close = cyapa_i2c_close; |
- input_set_drvdata(input_wheel, touch); |
- |
- __set_bit(EV_KEY, input_wheel->evbit); |
- __set_bit(EV_REL, input_wheel->evbit); |
- __set_bit(REL_WHEEL, input_wheel->relbit); |
- |
- retval = input_register_device(touch->input_wheel); |
- if (retval) { |
- dev_err(&touch->client->dev, "%s: Input device register failed: %d\n", __func__, retval); |
- |
- input_free_device(input_wheel); |
- return retval; |
- } |
- |
- return 0; |
-} |
- |
-#define MAX_NR_SCANCODES 128 |
- |
-static unsigned char cyapa_virtual_keycode[MAX_NR_SCANCODES] = { |
-/* Bellow keys are supported. |
-KEY_ENTER 28 |
-KEY_LEFTCTRL 29 |
-KEY_LEFTSHIFT 42 |
-KEY_RIGHTSHIFT 54 |
-KEY_LEFTALT 56 |
-KEY_KPMINUS 74 |
-KEY_KPPLUS 78 |
-KEY_RIGHTCTRL 97 |
-KEY_RIGHTALT 100 |
-KEY_HOME 102 |
-KEY_UP 103 |
-KEY_PAGEUP 104 |
-KEY_LEFT 105 |
-KEY_RIGHT 106 |
-KEY_END 107 |
-KEY_DOWN 108 |
-KEY_PAGEDOWN 109 |
-*/ |
- 28, 29, 42, 54, 56, 74, 78, 97, 100, 102, 103, 104, 105, 106, 107, 108, 109 |
-}; |
- |
-static int cyapa_create_input_dev_kbd(struct cyapa_i2c *touch) |
-{ |
- int retval =0; |
- int i; |
- struct input_dev *input_kbd = NULL; |
- |
- input_kbd = touch->input_kbd = input_allocate_device(); |
- if (!touch->input_kbd) { |
- dev_err(&touch->client->dev, "%s: Allocate memory for Input device failed: %d\n", |
- __func__, retval); |
- return -ENOMEM; |
- } |
- |
- input_kbd->name = "cyapa_i2c_virtual_kbd"; |
- input_kbd->phys = touch->client->adapter->name; |
- input_kbd->id.bustype = BUS_I2C; |
- input_kbd->id.version = 1; |
- input_kbd->dev.parent = &touch->client->dev; |
- input_kbd->open = cyapa_i2c_open; |
- input_kbd->close = cyapa_i2c_close; |
- input_set_drvdata(input_kbd, touch); |
- |
- input_kbd->keycode = &cyapa_virtual_keycode; |
- input_kbd->keycodesize = sizeof(unsigned char); |
- input_kbd->keycodemax = ARRAY_SIZE(cyapa_virtual_keycode); |
- |
- __set_bit(EV_KEY, input_kbd->evbit); |
- __set_bit(EV_REP, input_kbd->evbit); |
- |
- for (i = 0; i < ARRAY_SIZE(cyapa_virtual_keycode); i++) { |
- __set_bit(cyapa_virtual_keycode[i], input_kbd->keybit); |
- } |
- __clear_bit(KEY_RESERVED, input_kbd->keybit); |
- |
- retval = input_register_device(touch->input_kbd); |
- if (retval) { |
- dev_err(&touch->client->dev, "%s: Input device register failed: %d\n", __func__, retval); |
- |
- input_free_device(input_kbd); |
- return retval; |
- } |
- |
- return 0; |
-} |
- |
static int __devinit cyapa_i2c_probe(struct i2c_client *client, |
const struct i2c_device_id *dev_id) |
{ |
int retval = 0; |
struct cyapa_i2c *touch; |
- DBGPRINTK(("%s: start ... \n", __func__)); |
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) |
+ return -EIO; |
+ |
touch = cyapa_i2c_touch_create(client); |
if (!touch) |
return -ENOMEM; |
/* do platfrom initialize firstly. */ |
Daniel Kurtz
2011/05/02 12:43:47
/* First, initialize platform_data */
|
- if (touch->platform_data->init) |
+ if (touch->platform_data->init) { |
retval = touch->platform_data->init(); |
- if (retval) |
- goto err_mem_free; |
- |
- /* set irq number if not using polling mode. */ |
- if (touch->platform_data->use_polling_mode == true) { |
- touch->irq = -1; |
- } else { |
- if (touch->platform_data->irq_gpio == -1) { |
- if (client->irq) { |
- touch->irq = client->irq; |
- } else { |
- /* irq mode is not supported by system. */ |
- touch->platform_data->use_polling_mode = true; |
- touch->irq = -1; |
- } |
- } else { |
- touch->irq = gpio_to_irq(touch->platform_data->irq_gpio); |
+ if (retval) { |
+ dev_err(&client->dev, |
+ "%s: Error: board init failed: %d\n", |
+ __func__, retval); |
+ goto err_mem_free; |
} |
} |
- DBGPRINTK(("%s: irq=%d, client->irq=%d\n", __func__, touch->irq, client->irq)); |
- |
- if (touch->platform_data->use_polling_mode == false) { |
- DBGPRINTK(("%s: request interrupt riq. \n", __func__)); |
- |
- set_irq_type(touch->irq, IRQF_TRIGGER_FALLING); |
- retval = request_irq(touch->irq, |
- cyapa_i2c_irq, |
- 0, |
- CYAPA_I2C_NAME, |
- touch); |
- if (retval) { |
- dev_warn(&touch->client->dev, |
- "%s: IRQ request failed: %d, falling back to polling mode. \n", |
- __func__, retval); |
- touch->platform_data->use_polling_mode = true; |
+ /* set irq number for interrupt mode. |
+ * normallly, polling mode only will be used |
+ * when special paltfrom that do not support slave interrupt. |
Daniel Kurtz
2011/05/02 12:43:47
s/normallly/normally
s/paltfrom/platform
'platfor
|
+ * or allocate irq number to it failed. */ |
+ if (touch->platform_data->irq_gpio <= 0) { |
+ if (client->irq) { |
+ touch->irq = client->irq; |
+ } else { |
+ /* irq mode is not supported by platfrom. */ |
+ touch->irq = -1; |
} |
+ } else { |
+ touch->irq = gpio_to_irq(touch->platform_data->irq_gpio); |
} |
- /* reconfig trackpad depending on platfrom setting. */ |
- /* Should disable interrupt to protect this polling read operation. |
- ** Ohterwise, this I2C read will be interrupt by other reading, and failed. */ |
- disable_irq(touch->irq); |
- cyapa_i2c_reconfig(touch); |
- enable_irq(touch->irq); |
- |
- /* create an input_dev instance for virtual mouse trackpad. */ |
- if ((retval = cyapa_create_input_dev_mouse(touch))) { |
- DBGPRINTK(("%s: create input_dev instance for mouse trackpad filed. \n", __func__)); |
+ if (touch->irq <= 0) { |
+ dev_err(&client->dev, |
+ "%s: Error, failed to allocate irq\n", __func__); |
goto err_mem_free; |
} |
+ DBGPRINTK(("%s: irq=%d, client->irq=%d\n", |
+ __func__, touch->irq, client->irq)); |
+ |
+ set_irq_type(touch->irq, IRQF_TRIGGER_FALLING); |
+ retval = request_irq(touch->irq, |
+ cyapa_i2c_irq, |
+ 0, |
+ CYAPA_I2C_NAME, |
+ touch); |
+ if (retval) { |
+ dev_warn(&touch->client->dev, |
+ "%s: IRQ request failed: \ |
+ %d, falling back to polling mode.\n", |
+ __func__, retval); |
- /* create an input_dev instances for virtual wheel device and virtual keyboard device. */ |
- if ((retval = cyapa_create_input_dev_wheel(touch))) { |
- DBGPRINTK(("%s: create input_dev instance for wheel filed. \n", __func__)); |
- goto err_mem_free; |
+ touch->down_to_polling_mode = true; |
} |
- if ((retval = cyapa_create_input_dev_kbd(touch))) { |
- DBGPRINTK(("%s: create input_dev instance for virtual keyboad filed. \n", __func__)); |
+ /* reconfig trackpad depending on platfrom setting. */ |
+ cyapa_i2c_reconfig(touch); |
+ |
+ /* create an input_dev instance for trackpad device. */ |
+ retval = cyapa_create_input_dev(touch); |
+ if (retval) { |
+ free_irq(touch->irq, touch); |
+ DBGPRINTK(("%s: create mouse input_dev instance filed.\n", |
+ __func__)); |
goto err_mem_free; |
} |
i2c_set_clientdata(client, touch); |
- DBGPRINTK(("%s: Done successfully. \n", __func__)); |
+ DBGPRINTK(("%s: Done successfully.\n", __func__)); |
+ dev_info(&touch->client->dev, |
+ "cypress_i2c: Cypress trackpad initialized successfully.\n"); |
return 0; |
@@ -2059,21 +1566,9 @@ err_mem_free: |
touch->input = NULL; |
} |
- if (touch->input_wheel) { |
- input_free_device(touch->input_wheel); |
- touch->input_wheel = NULL; |
- } |
- |
- if (touch->input_kbd) { |
- input_free_device(touch->input_kbd); |
- touch->input_kbd = NULL; |
- } |
+ kfree(touch); |
- if (touch) { |
- kfree(touch); |
- touch = NULL; |
- } |
- DBGPRINTK(("%s: exist with error %d. \n", __func__, retval)); |
+ DBGPRINTK(("%s: exist with error %d.\n", __func__, retval)); |
return retval; |
} |
@@ -2081,19 +1576,13 @@ static int __devexit cyapa_i2c_remove(struct i2c_client *client) |
{ |
struct cyapa_i2c *touch = i2c_get_clientdata(client); |
- if (!touch->platform_data->use_polling_mode) |
+ if (touch->down_to_polling_mode == false) |
free_irq(client->irq, touch); |
if (touch->input) |
input_unregister_device(touch->input); |
- if (touch->input_wheel) |
- input_unregister_device(touch->input); |
- if (touch->input_kbd) |
- input_unregister_device(touch->input); |
- if (touch) |
- kfree(touch); |
- |
- DBGPRINTK(("%s: ... \n", __func__)); |
+ kfree(touch); |
+ global_touch = NULL; |
return 0; |
} |
@@ -2103,7 +1592,6 @@ static int cyapa_i2c_suspend(struct i2c_client *client, pm_message_t mesg) |
{ |
struct cyapa_i2c *touch = i2c_get_clientdata(client); |
- DBGPRINTK(("%s: ... \n", __func__)); |
cancel_delayed_work_sync(&touch->dwork); |
return 0; |
@@ -2114,12 +1602,24 @@ static int cyapa_i2c_resume(struct i2c_client *client) |
int ret; |
struct cyapa_i2c *touch = i2c_get_clientdata(client); |
+ if (touch->platform_data->wakeup) { |
+ ret = touch->platform_data->wakeup(); |
+ if (ret) { |
+ dev_err(&client->dev, "%s: Error: wakeup failed: %d\n", |
+ __func__, ret); |
+ return ret; |
+ } |
+ } |
+ |
ret = cyapa_i2c_reset_config(touch); |
- DBGPRINTK(("%s: ... \n", __func__)); |
- if (ret) |
+ if (ret) { |
+ dev_err(&client->dev, "%s: Error: reset config failed: %d\n", |
+ __func__, ret); |
return ret; |
+ } |
- cyapa_i2c_reschedule_work(touch, msecs_to_jiffies(CYAPA_NO_DATA_SLEEP_MSECS)); |
+ cyapa_i2c_reschedule_work(touch, |
+ msecs_to_jiffies(CYAPA_NO_DATA_SLEEP_MSECS)); |
return 0; |
} |
@@ -2136,28 +1636,51 @@ MODULE_DEVICE_TABLE(i2c, cypress_i2c_id_table); |
static struct i2c_driver cypress_i2c_driver = { |
.driver = { |
- .name = CYAPA_I2C_NAME, |
- .owner = THIS_MODULE, |
+ .name = CYAPA_I2C_NAME, |
+ .owner = THIS_MODULE, |
}, |
- .probe = cyapa_i2c_probe, |
- .remove = __devexit_p(cyapa_i2c_remove), |
+ .probe = cyapa_i2c_probe, |
+ .remove = __devexit_p(cyapa_i2c_remove), |
.suspend = cyapa_i2c_suspend, |
- .resume = cyapa_i2c_resume, |
+ .resume = cyapa_i2c_resume, |
Daniel Kurtz
2011/05/01 23:44:09
align
|
.id_table = cypress_i2c_id_table, |
}; |
static int __init cyapa_i2c_init(void) |
{ |
- DBGPRINTK(("%s: start ... \n", __func__)); |
- return i2c_add_driver(&cypress_i2c_driver); |
+ int ret; |
+ |
+ printk(KERN_INFO |
+ "cypress_i2c: Initialize Cypress multi-touch trackpad.\n"); |
Olof Johansson
2011/05/02 05:47:12
pr_info()
|
+ |
+ ret = i2c_add_driver(&cypress_i2c_driver); |
+ if (ret) { |
+ pr_err("ERROR: %s: cypress i2c driver register FAILED.\n", |
+ __func__); |
+ return ret; |
+ } |
+ |
+ ret = cyapa_misc_init(); |
+ if (ret) { |
+ i2c_del_driver(&cypress_i2c_driver); |
+ pr_err("ERROR: %s: cyapa misc device register FAILED.\n", |
+ __func__); |
+ return ret; |
+ } |
+ |
+ return ret; |
} |
static void __exit cyapa_i2c_exit(void) |
{ |
- DBGPRINTK(("%s: exit ... \n", __func__)); |
+ cyapa_misc_exit(); |
+ |
i2c_del_driver(&cypress_i2c_driver); |
+ |
+ printk(KERN_INFO |
+ "cypress_i2c: Cypress multi-touch trackpad driver exited.\n"); |
Olof Johansson
2011/05/02 05:47:12
pr_info().
|
} |
module_init(cyapa_i2c_init); |
@@ -2166,4 +1689,3 @@ module_exit(cyapa_i2c_exit); |
MODULE_DESCRIPTION("Cypress I2C Trackpad Driver"); |
MODULE_AUTHOR("Dudley Du <dudl@cypress.com>"); |
MODULE_LICENSE("GPL"); |
- |