Chromium Code Reviews| 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"); |
| - |