Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Cypress APA touchpad with I2C interface | 2 * Cypress APA touchpad with I2C interface |
| 3 * | 3 * |
| 4 * Copyright (C) 2009 Compulab, Ltd. | 4 * Copyright (C) 2009 Compulab, Ltd. |
| 5 * Dudley Du <dudl@cypress.com> | 5 * Dudley Du <dudl@cypress.com> |
| 6 * | 6 * |
| 7 * This file is subject to the terms and conditions of the GNU General Public | 7 * This file is subject to the terms and conditions of the GNU General Public |
| 8 * License. See the file COPYING in the main directory of this archive for | 8 * License. See the file COPYING in the main directory of this archive for |
| 9 * more details. | 9 * more details. |
| 10 */ | 10 */ |
| 11 | 11 |
| 12 | 12 |
| 13 #include <linux/module.h> | 13 #include <linux/module.h> |
| 14 #include <linux/init.h> | |
| 15 #include <linux/kernel.h> | |
| 14 #include <linux/i2c.h> | 16 #include <linux/i2c.h> |
| 15 #include <linux/irq.h> | 17 #include <linux/irq.h> |
| 16 #include <linux/interrupt.h> | 18 #include <linux/interrupt.h> |
| 17 #include <linux/input.h> | 19 #include <linux/input.h> |
| 18 #include <linux/delay.h> | 20 #include <linux/delay.h> |
| 19 #include <linux/workqueue.h> | 21 #include <linux/workqueue.h> |
| 20 #include <linux/slab.h> | 22 #include <linux/slab.h> |
| 21 #include <linux/gpio.h> | 23 #include <linux/gpio.h> |
| 24 #include <linux/spinlock.h> | |
| 25 #include <linux/mutex.h> | |
| 26 #include <linux/uaccess.h> | |
| 27 #include <linux/miscdevice.h> | |
| 28 #include <linux/fs.h> | |
| 22 | 29 |
| 23 #include <linux/cyapa.h> | 30 #include <linux/cyapa.h> |
| 24 | 31 |
| 25 | 32 |
| 26 /* Debug macro */ | 33 /* DEBUG: debug switch macro */ |
| 27 //#define CYAPA_DBG | 34 #define CYAPA_DBG 0 |
| 28 #ifdef CYAPA_DBG | 35 #if CYAPA_DBG |
| 29 #define DBGPRINTK(x) printk x | 36 #define DBGPRINTK(x) printk x |
| 30 #define DBG_CYAPA_READ_BLOCK_DATA | 37 #define DBG_CYAPA_READ_BLOCK_DATA |
| 31 #else | 38 #else |
| 32 #define DBGPRINTK(x) | 39 #define DBGPRINTK(x) |
| 33 #endif | 40 #endif |
| 34 | 41 |
| 35 | 42 |
| 36 /* Cypress I2C APA trackpad driver version is defined as bellow: | 43 /* Cypress I2C APA trackpad driver version is defined as bellow: |
|
Daniel Kurtz
2011/05/01 23:44:09
s/bellow/below
| |
| 37 ** CYAPA_MAJOR_VER.CYAPA_MINOR_VER.CYAPA_REVISIOIN_VER . */ | 44 ** 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
| |
| 38 #define CYAPA_MAJOR_VER 0 | 45 #define CYAPA_MAJOR_VER 0 |
| 39 #define CYAPA_MINOR_VER 9 | 46 #define CYAPA_MINOR_VER 9 |
| 40 #define CYAPA_REVISIOIN_VER» 2 | 47 #define CYAPA_REVISION_VER» » 7 |
|
Daniel Kurtz
2011/05/01 23:44:09
Just one tab
| |
| 41 | 48 |
| 42 /* macro definication for gestures. */ | 49 /* macro definication for gestures. */ |
| 43 /* --------------------------------------------------------------- */ | 50 /* --------------------------------------------------------------- */ |
| 44 /* |- bit 7 - 5 -|- bit 4 -0 -| */ | 51 /* |- bit 7 - 5 -|- bit 4 -0 -| */ |
| 45 /* |------------------------------|----------------------------- | */ | 52 /* |------------------------------|----------------------------- | */ |
| 46 /* |- finger number -|- gesture id -| */ | 53 /* |- finger number -|- gesture id -| */ |
| 47 /* --------------------------------------------------------------- */ | 54 /* --------------------------------------------------------------- */ |
| 48 #define GESTURE_FINGERS(x) ((((x) & 0x07) << 5) & 0xE0) | 55 #define GESTURE_FINGERS(x) ((((x) & 0x07) << 5) & 0xE0) |
| 49 #define GESTURE_INDEX(x) ((x) & 0x1F) | 56 #define GESTURE_INDEX(x) (((x) & 0x1F)) |
| 50 #define GESTURE_ID_CODE(finger, index) (GESTURE_FINGERS(finger) | GESTURE_INDEX( index)) | 57 #define GESTURE_ID_CODE(finger, index) \ |
| 58 » » (GESTURE_FINGERS(finger) | GESTURE_INDEX(index)) | |
| 59 #define GESTURE_DECODE_FINGERS(x)» (((x) >> 5) & 0x07) | |
| 60 #define GESTURE_DECODE_INDEX(x)»((x) & 0x1F) | |
|
Daniel Kurtz
2011/05/01 23:44:09
two tabs
| |
| 51 | 61 |
| 52 #define GESTURE_NONE 0x00 | 62 #define GESTURE_NONE 0x00 |
| 53 /* 0-finger gestures. */ | 63 /* 0-finger gestures. */ |
| 54 #define GESTURE_PALM_REJECTIOIN» GESTURE_ID_CODE(0, 1) | 64 #define GESTURE_PALM_REJECTIOIN»GESTURE_ID_CODE(0, 1) |
|
Daniel Kurtz
2011/05/01 23:44:09
2 tabs
| |
| 55 /* 1-finger gestures. */ | 65 /* 1-finger gestures. */ |
| 56 #define GESTURE_SINGLE_TAP» » GESTURE_ID_CODE(1, 0) | 66 #define GESTURE_SINGLE_TAP» » GESTURE_ID_CODE(1, 0) |
| 57 #define GESTURE_DOUBLE_TAP» » GESTURE_ID_CODE(1, 1) | 67 #define GESTURE_DOUBLE_TAP» » GESTURE_ID_CODE(1, 1) |
| 58 /* one finger click and hold for more than definitioin time, then to do somethin g. */ | 68 /* |
| 59 #define GESTURE_TAP_AND_HOLD» GESTURE_ID_CODE(1, 2) | 69 ** one finger click and hold for more than definitioin time, |
|
Daniel Kurtz
2011/05/01 23:44:09
s/definitioin/defined
s/**/ *
| |
| 60 #define GESTURE_EDGE_MOTION» » GESTURE_ID_CODE(1, 3) | 70 ** then to do something. |
| 61 #define GESTURE_FLICK» » » GESTURE_ID_CODE(1, 4) | 71 */ |
| 72 #define GESTURE_TAP_AND_HOLD» » GESTURE_ID_CODE(1, 2) | |
| 73 #define GESTURE_EDGE_MOTION» » GESTURE_ID_CODE(1, 3) | |
| 74 #define GESTURE_FLICK» » » GESTURE_ID_CODE(1, 4) | |
| 62 /* GESTURE_DRAG : double click and hold, then move for drag.*/ | 75 /* GESTURE_DRAG : double click and hold, then move for drag.*/ |
| 63 #define GESTURE_DRAG» » » GESTURE_ID_CODE(1, 5) | 76 #define GESTURE_DRAG» » » GESTURE_ID_CODE(1, 5) |
| 64 /* Depending on PSOC user module, it will give four different ID when scroll.*/ | 77 /* Depending on PSOC user module, it will give four different ID when scroll.*/ |
| 65 #define GESTURE_SCROLL_UP» » GESTURE_ID_CODE(1, 6) | 78 #define GESTURE_SCROLL_UP» » GESTURE_ID_CODE(1, 6) |
| 66 #define GESTURE_SCROLL_DOWN» » GESTURE_ID_CODE(1, 7) | 79 #define GESTURE_SCROLL_DOWN» » GESTURE_ID_CODE(1, 7) |
| 67 #define GESTURE_SCROLL_LEFT» » GESTURE_ID_CODE(1, 8) | 80 #define GESTURE_SCROLL_LEFT» » GESTURE_ID_CODE(1, 8) |
| 68 #define GESTURE_SCROLL_RIGHT GESTURE_ID_CODE(1, 9) | 81 #define GESTURE_SCROLL_RIGHT GESTURE_ID_CODE(1, 9) |
| 69 | 82 |
| 70 /* 2-finger gestures */ | 83 /* 2-finger gestures */ |
| 71 #define GESTURE_2F_ZOOM_IN» » GESTURE_ID_CODE(2, 0) | 84 #define GESTURE_2F_ZOOM_IN» » GESTURE_ID_CODE(2, 0) |
| 72 #define GESTURE_2F_ZOOM_OUT» » GESTURE_ID_CODE(2, 1) | 85 #define GESTURE_2F_ZOOM_OUT» » GESTURE_ID_CODE(2, 1) |
| 73 #define GESTURE_2F_SCROLL_UP GESTURE_ID_CODE(2, 2) | 86 #define GESTURE_2F_SCROLL_UP GESTURE_ID_CODE(2, 2) |
| 74 #define GESTURE_2F_SCROLL_DOWN» GESTURE_ID_CODE(2, 3) | 87 #define GESTURE_2F_SCROLL_DOWN» GESTURE_ID_CODE(2, 3) |
|
Daniel Kurtz
2011/05/01 23:44:09
next three lines:
two tabs
| |
| 75 #define GESTURE_2F_SCROLL_LEFT» GESTURE_ID_CODE(2, 4) | 88 #define GESTURE_2F_SCROLL_LEFT» GESTURE_ID_CODE(2, 4) |
| 76 #define GESTURE_2F_SCROLL_RIGHT» GESTURE_ID_CODE(2, 5) | 89 #define GESTURE_2F_SCROLL_RIGHT»GESTURE_ID_CODE(2, 5) |
| 77 #define GESTURE_2F_ROTATE» » GESTURE_ID_CODE(2, 6) | 90 #define GESTURE_2F_ROTATE» » GESTURE_ID_CODE(2, 6) |
| 78 #define GESTURE_2F_PINCH» » GESTURE_ID_CODE(2, 7) | 91 #define GESTURE_2F_PINCH» » GESTURE_ID_CODE(2, 7) |
| 79 /* Activates the Right Click action */ | 92 /* Activates the Right Click action */ |
| 80 #define GESTURE_2F_TAP» » » GESTURE_ID_CODE(2, 8) | 93 #define GESTURE_2F_TAP» » » GESTURE_ID_CODE(2, 8) |
| 81 /* Single-Finger click and hold while a second finger is moving for dragging. */ | 94 /* Single-Finger click and hold while a second finger is moving for dragging. */ |
| 82 #define GESTURE_2F_DRAG»» » GESTURE_ID_CODE(2, 9) | 95 #define GESTURE_2F_DRAG»» GESTURE_ID_CODE(2, 9) |
|
Daniel Kurtz
2011/05/01 23:44:09
2 tabs
| |
| 83 #define GESTURE_2F_FLICK» » » GESTURE_ID_CODE(2, 10) | 96 #define GESTURE_2F_FLICK» » GESTURE_ID_CODE(2, 10) |
| 84 | 97 |
| 85 /* 3-finger gestures */ | 98 /* 3-finger gestures */ |
| 86 #define GESTURE_3F_FLICK» » GESTURE_ID_CODE(3, 0) | 99 #define GESTURE_3F_FLICK» » GESTURE_ID_CODE(3, 0) |
| 87 | 100 |
| 88 /* 4-finger gestures */ | 101 /* 4-finger gestures */ |
| 89 #define GESTURE_4F_FLICK» » GESTURE_ID_CODE(4, 0) | 102 #define GESTURE_4F_FLICK» » GESTURE_ID_CODE(4, 0) |
| 90 | 103 |
| 91 /* 5-finger gestures */ | 104 /* 5-finger gestures */ |
| 92 #define GESTURE_5F_FLICK» » GESTURE_ID_CODE(5, 0) | 105 #define GESTURE_5F_FLICK» » GESTURE_ID_CODE(5, 0) |
| 93 | 106 |
| 94 /* swith of the gesture, */ | 107 #define CYAPA_MT_MAX_TOUCH 255 |
| 95 #define GESTURE_MULTI_TOUCH_ONE_CLICK 0 | 108 #define CYAPA_MT_MAX_WIDTH 255 |
| 96 | |
| 97 #define GESTURE_DECODE_FINGERS(x)» (((x) >> 5) & 0x07) | |
| 98 #define GESTURE_DECODE_INDEX(x)»((x) & 0x1F ) | |
| 99 | 109 |
| 100 /* max gesture index value for each fingers type is 31. 0~21.*/ | 110 /* max gesture index value for each fingers type is 31. 0~21.*/ |
| 101 #define MAX_FINGERS 5 | 111 #define MAX_FINGERS 5 |
| 102 | |
| 103 | |
| 104 /* parameter value for input_report_key(BTN_TOOL_WIDTH) */ | 112 /* parameter value for input_report_key(BTN_TOOL_WIDTH) */ |
| 105 #define CYAPA_TOOL_WIDTH 50 | 113 #define CYAPA_TOOL_WIDTH 50 |
| 114 #define CYAPA_DEFAULT_TOUCH_PRESSURE 50 | |
| 115 #define CYAPA_MT_TOUCH_MAJOR 50 | |
| 106 | 116 |
| 107 /* When in IRQ mode read the device every THREAD_IRQ_SLEEP_SECS */ | 117 /* When in IRQ mode read the device every THREAD_IRQ_SLEEP_SECS */ |
| 108 #define CYAPA_THREAD_IRQ_SLEEP_SECS 2 | 118 #define CYAPA_THREAD_IRQ_SLEEP_SECS 2 |
| 109 #define CYAPA_THREAD_IRQ_SLEEP_MSECS (CYAPA_THREAD_IRQ_SLEEP_SECS * MSEC_PER_SE C) | 119 #define CYAPA_THREAD_IRQ_SLEEP_MSECS \ |
| 110 | 120 » » » (CYAPA_THREAD_IRQ_SLEEP_SECS * MSEC_PER_SEC) |
| 111 /* | 121 /* |
| 112 * When in Polling mode and no data received for CYAPA_NO_DATA_THRES msecs | 122 * When in Polling mode and no data received for CYAPA_NO_DATA_THRES msecs |
| 113 * reduce the polling rate to CYAPA_NO_DATA_SLEEP_MSECS | 123 * reduce the polling rate to CYAPA_NO_DATA_SLEEP_MSECS |
| 114 */ | 124 */ |
| 115 #define CYAPA_NO_DATA_THRES» » » (MSEC_PER_SEC) | 125 #define CYAPA_NO_DATA_THRES» » (MSEC_PER_SEC) |
| 116 #define CYAPA_NO_DATA_SLEEP_MSECS (MSEC_PER_SEC / 4) | 126 #define CYAPA_NO_DATA_SLEEP_MSECS (MSEC_PER_SEC / 4) |
| 117 | 127 |
| 118 /* report data start reg offset address. */ | 128 /* report data start reg offset address. */ |
| 119 #define DATA_REG_START_OFFSET 0x0000 | 129 #define DATA_REG_START_OFFSET 0x0000 |
| 120 /* relative data report data size. */ | 130 /* relative data report data size. */ |
| 121 #define CYAPA_REL_REG_DATA_SIZE 5 | 131 #define CYAPA_REL_REG_DATA_SIZE 5 |
| 122 | 132 |
| 123 | |
| 124 /* Device Sleep Modes */ | 133 /* Device Sleep Modes */ |
| 125 #define DEV_POWER_REG 0x0009 | 134 #define DEV_POWER_REG 0x0009 |
| 126 #define INTERRUPT_MODE_MASK 0x01 | 135 #define INTERRUPT_MODE_MASK 0x01 |
| 127 #define PWR_LEVEL_MASK 0x06 | 136 #define PWR_LEVEL_MASK 0x06 |
| 128 #define PWR_BITS_SHITF 1 | 137 #define PWR_BITS_SHITF 1 |
| 129 #define GET_PWR_LEVEL(reg) ((((unsigned char)(reg))&PWR_LEVEL_MASK)>>PWR_BITS_SH ITF) | 138 #define GET_PWR_LEVEL(reg) \ |
| 130 | 139 » ((((unsigned char)(reg))&PWR_LEVEL_MASK)>>PWR_BITS_SHITF) |
| 131 // protocol V1. | |
| 132 #define REG_GESTURES 0x0B | |
| 133 | |
| 134 /* definition to store platfrom data. */ | |
| 135 static struct cyapa_platform_data cyapa_i2c_platform_data = { | |
| 136 » .flag = 0, | |
| 137 » .gen = CYAPA_GEN2, | |
| 138 » .power_state = CYAPA_PWR_ACTIVE, | |
| 139 » .use_absolute_mode = true, | |
| 140 » .use_polling_mode = false, | |
| 141 » .polling_interval_time_active = CYAPA_ACTIVE_POLLING_INTVAL_TIME, | |
| 142 » .polling_interval_time_lowpower = CYAPA_LOWPOWER_POLLING_INTVAL_TIME, | |
| 143 » .active_touch_timeout = CYAPA_ACTIVE_TOUCH_TIMEOUT, | |
| 144 » .name = CYAPA_I2C_NAME, | |
| 145 » .irq_gpio = -1, | |
| 146 » .report_rate = CYAPA_REPORT_RATE, | |
| 147 }; | |
| 148 | |
| 149 | 140 |
| 150 /* | 141 /* |
| 151 ** APA trackpad device states. | 142 ** APA trackpad device states. |
| 152 ** Used in register 0x00, bit1-0, DeviceStatus field. | 143 ** Used in register 0x00, bit1-0, DeviceStatus field. |
| 153 */ | 144 */ |
| 154 enum cyapa_devicestate | 145 enum cyapa_devicestate { |
| 155 { | |
| 156 CYAPA_DEV_NORNAL = 0x03, | 146 CYAPA_DEV_NORNAL = 0x03, |
| 157 /* | 147 /* |
| 158 ** After trackpad booted, and can report data, it should set this value. | 148 ** After trackpad booted, and can report data, it should set this value. |
| 159 ** 0ther values stand for trackpad device is in abnormal state. | 149 ** 0ther values stand for trackpad device is in abnormal state. |
| 160 ** maybe need to do reset operation to it. | 150 ** maybe need to do reset operation to it. |
| 161 ** Other values are defined later if needed. | 151 ** Other values are defined later if needed. |
| 162 */ | 152 */ |
| 163 }; | 153 }; |
| 164 | 154 |
| 165 #define CYAPA_MAX_TOUCHS (MAX_FINGERS) | 155 #define CYAPA_MAX_TOUCHS (MAX_FINGERS) |
| 166 #define CYAPA_ONE_TIME_GESTURES (1) //only 1 gesture can be reported one time right now. | 156 #define CYAPA_ONE_TIME_GESTURES (1) |
| 167 struct cyapa_touch_gen1 | 157 struct cyapa_touch_gen1 { |
| 168 { | |
| 169 u8 rel_xy; | 158 u8 rel_xy; |
| 170 u8 rel_x; | 159 u8 rel_x; |
| 171 u8 rel_y; | 160 u8 rel_y; |
| 172 }; | 161 }; |
| 173 | 162 |
| 174 struct cyapa_reg_data_gen1 | 163 struct cyapa_reg_data_gen1 { |
| 175 { | |
| 176 u8 tap_motion; | 164 u8 tap_motion; |
| 177 s8 deltax; | 165 s8 deltax; |
| 178 s8 deltay; | 166 s8 deltay; |
| 179 u8 reserved1; | 167 u8 reserved1; |
| 180 u8 reserved2; | 168 u8 reserved2; |
| 181 » | 169 |
| 182 struct cyapa_touch_gen1 touch1; | 170 struct cyapa_touch_gen1 touch1; |
| 183 u8 touch_fingers; | 171 u8 touch_fingers; |
| 184 u8 feature_config; | 172 u8 feature_config; |
| 185 u8 avg_pressure; /* average of all touched fingers. */ | 173 u8 avg_pressure; /* average of all touched fingers. */ |
| 186 u8 gesture_status; | 174 u8 gesture_status; |
| 187 struct cyapa_touch_gen1 touchs[CYAPA_MAX_TOUCHS-1]; | 175 struct cyapa_touch_gen1 touchs[CYAPA_MAX_TOUCHS-1]; |
| 188 }; | 176 }; |
| 189 | 177 |
| 190 struct cyapa_touch_gen2 | 178 struct cyapa_touch_gen2 { |
| 191 { | |
| 192 u8 xy; | 179 u8 xy; |
| 193 u8 x; | 180 u8 x; |
| 194 u8 y; | 181 u8 y; |
| 195 » u8 id; | 182 » u8 pressure; |
| 196 }; | 183 }; |
| 197 | 184 |
| 198 struct cyapa_gesture | 185 struct cyapa_touch { |
| 199 { | 186 » int x; |
| 187 » int y; | |
| 188 » int pressure; | |
| 189 }; | |
| 190 | |
| 191 struct cyapa_gesture { | |
| 200 u8 id; | 192 u8 id; |
| 201 u8 param1; | 193 u8 param1; |
| 202 u8 param2; | 194 u8 param2; |
| 203 }; | 195 }; |
| 204 | 196 |
| 205 struct cyapa_reg_data_gen2 | 197 struct cyapa_reg_data_gen2 { |
| 206 { | |
| 207 u8 device_status; | 198 u8 device_status; |
| 208 u8 relative_flags; | 199 u8 relative_flags; |
| 209 s8 deltax; | 200 s8 deltax; |
| 210 s8 deltay; | 201 s8 deltay; |
| 211 u8 avg_pressure; | 202 u8 avg_pressure; |
| 212 u8 touch_fingers; | 203 u8 touch_fingers; |
| 213 u8 reserved1; | 204 u8 reserved1; |
| 214 u8 reserved2; | 205 u8 reserved2; |
| 215 struct cyapa_touch_gen2 touchs[CYAPA_MAX_TOUCHS]; | 206 struct cyapa_touch_gen2 touchs[CYAPA_MAX_TOUCHS]; |
| 216 u8 gesture_count; | 207 u8 gesture_count; |
| 217 struct cyapa_gesture gesture[CYAPA_ONE_TIME_GESTURES]; | 208 struct cyapa_gesture gesture[CYAPA_ONE_TIME_GESTURES]; |
| 218 }; | 209 }; |
| 219 | 210 |
| 220 union cyapa_reg_data | 211 union cyapa_reg_data { |
| 221 { | |
| 222 struct cyapa_reg_data_gen1 gen1_data; | 212 struct cyapa_reg_data_gen1 gen1_data; |
| 223 struct cyapa_reg_data_gen2 gen2_data; | 213 struct cyapa_reg_data_gen2 gen2_data; |
| 224 }; | 214 }; |
| 225 | 215 |
| 226 struct cyapa_touch | 216 struct cyapa_report_data { |
| 227 { | |
| 228 » int x; | |
| 229 » int y; | |
| 230 » int id; | |
| 231 }; | |
| 232 | |
| 233 struct cyapa_report_data | |
| 234 { | |
| 235 u8 button; | 217 u8 button; |
| 236 u8 reserved1; | 218 u8 reserved1; |
| 237 u8 reserved2; | 219 u8 reserved2; |
| 238 u8 avg_pressure; | 220 u8 avg_pressure; |
| 239 int rel_deltaX; | 221 int rel_deltaX; |
| 240 int rel_deltaY; | 222 int rel_deltaY; |
| 241 | 223 |
| 242 int touch_fingers; | 224 int touch_fingers; |
| 243 struct cyapa_touch touchs[CYAPA_MAX_TOUCHS]; | 225 struct cyapa_touch touchs[CYAPA_MAX_TOUCHS]; |
| 244 » | 226 |
| 245 » int gestures_count; /* in gen1 and gen2, only 1 gesture one time suppor ted. */ | 227 » /* in gen1 and gen2, only 1 gesture one time supported. */ |
|
Olof Johansson
2011/05/02 05:47:12
"only 1 gesture at a time"?
| |
| 228 » int gestures_count; | |
| 246 struct cyapa_gesture gestures[CYAPA_ONE_TIME_GESTURES]; | 229 struct cyapa_gesture gestures[CYAPA_ONE_TIME_GESTURES]; |
| 247 }; | 230 }; |
| 248 | 231 |
| 249 struct scroll_preferences { | |
| 250 int default_threshold; /* small scroll speed threshold. */ | |
| 251 int middle_threshold; | |
| 252 int fast_threshold; | |
| 253 }; | |
| 254 | |
| 255 struct cyapa_preferences { | |
| 256 struct scroll_preferences vscroll; | |
| 257 struct scroll_preferences hscroll; | |
| 258 }; | |
| 259 | |
| 260 /* The main device structure */ | 232 /* The main device structure */ |
| 261 struct cyapa_i2c { | 233 struct cyapa_i2c { |
| 234 struct semaphore misc_sem; | |
| 235 spinlock_t misc_spinlock; | |
| 236 struct mutex misc_mutex; | |
|
Olof Johansson
2011/05/02 05:47:12
You now have three new locking primitives. Please
| |
| 237 int misc_open_count; | |
| 238 enum cyapa_work_mode fw_work_mode; | |
| 239 | |
| 262 struct i2c_client *client; | 240 struct i2c_client *client; |
| 263 struct input_dev *input; | 241 struct input_dev *input; |
| 264 struct input_dev *input_wheel; | |
| 265 struct input_dev *input_kbd; | |
| 266 struct delayed_work dwork; | 242 struct delayed_work dwork; |
| 267 spinlock_t lock; | 243 spinlock_t lock; |
| 268 int no_data_count; | 244 int no_data_count; |
| 269 int scan_ms; | 245 int scan_ms; |
| 270 int read_pending; | |
| 271 int open_count; | 246 int open_count; |
| 272 | 247 |
| 273 int irq; | 248 int irq; |
| 249 int down_to_polling_mode; | |
| 274 struct cyapa_platform_data *platform_data; | 250 struct cyapa_platform_data *platform_data; |
| 275 unsigned short data_base_offset; | 251 unsigned short data_base_offset; |
| 276 unsigned short control_base_offset; | 252 unsigned short control_base_offset; |
| 277 unsigned short command_base_offset; | 253 unsigned short command_base_offset; |
| 278 unsigned short query_base_offset; | 254 unsigned short query_base_offset; |
| 279 | 255 |
| 280 struct cyapa_preferences preferences; | |
| 281 | |
| 282 int zoomin_delta; | |
| 283 int zoomout_delta; | |
| 284 int hscroll_left; | |
| 285 int hscroll_right; | |
| 286 int delta_scroll_up; | |
| 287 int delta_scroll_down; | |
| 288 int delta_scroll_left; | |
| 289 int delta_scroll_right; | |
| 290 | |
| 291 int abs_x; | |
| 292 int abs_y; | |
| 293 int prev_abs_x; | |
| 294 int prev_abs_y; | |
| 295 unsigned char xy_touchs_included_bits; | |
| 296 unsigned char gesture_2F_drag_started; | |
| 297 | |
| 298 unsigned long cur_active_gestures[MAX_FINGERS]; | |
| 299 unsigned long prev_active_gestures[MAX_FINGERS]; | |
| 300 | |
| 301 int prev_touch_fingers; | 256 int prev_touch_fingers; |
| 302 | 257 |
| 303 /* read from query data region. */ | 258 /* read from query data region. */ |
| 304 char product_id[16]; | 259 char product_id[16]; |
| 305 unsigned char capability[14]; | 260 unsigned char capability[14]; |
| 306 » unsigned char fm_maj_ver; //firmware major version. | 261 » unsigned char fm_maj_ver; /* firmware major version. */ |
| 307 » unsigned char fm_min_ver; //firmware minor version. | 262 » unsigned char fm_min_ver; /* firmware minor version. */ |
| 308 » unsigned char hw_maj_ver; //hardware major version. | 263 » unsigned char hw_maj_ver; /* hardware major version. */ |
| 309 » unsigned char hw_min_ver; //hardware minor version. | 264 » unsigned char hw_min_ver; /* hardware minor version. */ |
| 310 int max_absolution_x; | 265 int max_absolution_x; |
| 311 int max_absolution_y; | 266 int max_absolution_y; |
|
Daniel Kurtz
2011/05/02 12:43:47
max_abs_x / max_abs_y
absolution means something
| |
| 312 int physical_size_x; | 267 int physical_size_x; |
| 313 int physical_size_y; | 268 int physical_size_y; |
| 314 }; | 269 }; |
| 315 | 270 |
| 316 | 271 |
| 272 /* definition to store platfrom data. */ | |
| 273 static struct cyapa_platform_data cyapa_i2c_platform_data = { | |
| 274 .flag = 0, | |
| 275 .gen = CYAPA_GEN2, | |
| 276 .power_state = CYAPA_PWR_ACTIVE, | |
| 277 .polling_interval_time_active = CYAPA_ACTIVE_POLLING_INTVAL_TIME, | |
| 278 .polling_interval_time_lowpower = CYAPA_LOWPOWER_POLLING_INTVAL_TIME, | |
| 279 .active_touch_timeout = CYAPA_ACTIVE_TOUCH_TIMEOUT, | |
| 280 .name = CYAPA_I2C_NAME, | |
| 281 .irq_gpio = -1, | |
| 282 .report_rate = CYAPA_REPORT_RATE, | |
| 283 }; | |
| 284 | |
| 285 | |
| 286 /* global pointer to trackpad touch data structure. */ | |
| 287 static struct cyapa_i2c *global_touch; | |
| 288 | |
| 289 static void cyapa_get_query_data(struct cyapa_i2c *touch); | |
| 290 | |
| 291 | |
| 317 #ifdef DBG_CYAPA_READ_BLOCK_DATA | 292 #ifdef DBG_CYAPA_READ_BLOCK_DATA |
| 318 void cyapa_print_data_block(const char *func, u8 reg, u8 length, void *data) | 293 void cyapa_dump_data_block(const char *func, u8 reg, u8 length, void *data) |
| 319 { | 294 { |
| 320 » char buf[1024]; | 295 » char buf[512]; |
| 321 unsigned buf_len = sizeof(buf); | 296 unsigned buf_len = sizeof(buf); |
| 322 char *p = buf; | 297 char *p = buf; |
| 323 int i; | 298 int i; |
| 324 int l; | 299 int l; |
| 325 | 300 |
| 326 l = snprintf(p, buf_len, "reg 0x%04x: ", reg); | 301 l = snprintf(p, buf_len, "reg 0x%04x: ", reg); |
| 327 buf_len -= l; | 302 buf_len -= l; |
| 328 p += l; | 303 p += l; |
| 329 for (i = 0; i < length && buf_len; i++, p += l, buf_len -= l) | 304 for (i = 0; i < length && buf_len; i++, p += l, buf_len -= l) |
| 330 l = snprintf(p, buf_len, "%02x ", *((char *)data + i)); | 305 l = snprintf(p, buf_len, "%02x ", *((char *)data + i)); |
| 331 » printk("%s: data block length = %d\n", func, length); | 306 » printk(KERN_INFO "%s: data block length = %d\n", func, length); |
| 332 » printk("%s: %s\n", func, buf); | 307 » printk(KERN_INFO "%s: %s\n", func, buf); |
| 333 } | 308 } |
| 334 | 309 |
| 335 void cyapa_print_report_data(const char *func, | 310 void cyapa_dump_report_data(const char *func, |
| 336 struct cyapa_report_data *report_data) | 311 struct cyapa_report_data *report_data) |
| 337 { | 312 { |
| 338 int i; | 313 int i; |
| 339 | 314 |
| 340 » printk("%s: -----------------------------------------\n", func); | 315 » 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.
| |
| 341 » printk("%s: report_data.button = 0x%02x\n", func, report_data->button); | 316 » printk(KERN_INFO "%s: report_data.button = 0x%02x\n", |
| 342 » printk("%s: report_data.avg_pressure = %d\n", func, report_data->avg_pre ssure); | 317 » » » func, report_data->button); |
| 343 » printk("%s: report_data.touch_fingers = %d\n", func, report_data->touch_ fingers); | 318 » printk(KERN_INFO "%s: report_data.avg_pressure = %d\n", |
| 344 » for (i=0; i<report_data->touch_fingers; i++) { | 319 » » » func, report_data->avg_pressure); |
| 345 » » printk("%s: report_data.touchs[%d].x = %d\n", func, i, report_da ta->touchs[i].x); | 320 » printk(KERN_INFO "%s: report_data.touch_fingers = %d\n", |
| 346 » » printk("%s: report_data.touchs[%d].y = %d\n", func, i, report_da ta->touchs[i].y); | 321 » » » func, report_data->touch_fingers); |
| 347 » » printk("%s: report_data.touchs[%d].id = %d\n", | 322 » for (i = 0; i < report_data->touch_fingers; i++) { |
| 348 » » » » » » » func, i, report_data->to uchs[i].id); | 323 » » printk(KERN_INFO "%s: report_data.touchs[%d].x = %d\n", |
| 324 » » » » func, i, report_data->touchs[i].x); | |
| 325 » » printk(KERN_INFO "%s: report_data.touchs[%d].y = %d\n", | |
| 326 » » » » func, i, report_data->touchs[i].y); | |
| 327 » » printk(KERN_INFO "%s: report_data.touchs[%d].pressure = %d\n", | |
| 328 » » » » func, i, report_data->touchs[i].pressure); | |
| 349 } | 329 } |
| 350 » printk("%s: report_data.gestures_count = %d\n", func, report_data->gestu res_count); | 330 » printk(KERN_INFO "%s: report_data.gestures_count = %d\n", |
| 351 » for (i=0; i<report_data->gestures_count; i++) { | 331 » » » func, report_data->gestures_count); |
| 352 » » printk("%s: report_data.gestures[%d].id = 0x%02x\n", | 332 » for (i = 0; i < report_data->gestures_count; i++) { |
| 353 » » » » » » » func, i, report_data->ge stures[i].id); | 333 » » printk(KERN_INFO "%s: report_data.gestures[%d].id = 0x%02x\n", |
| 354 » » printk("%s: report_data.gestures[%d].param1 = 0x%02x\n", | 334 » » » func, i, report_data->gestures[i].id); |
| 355 » » » » » » » func, i, report_data->ge stures[i].param1); | 335 » » printk(KERN_INFO "%s: report_data.gestures[%d].param1 = 0x%02x\n ", |
| 356 » » printk("%s: report_data.gestures[%d].param2 = 0x%02x\n", | 336 » » » func, i, report_data->gestures[i].param1); |
| 357 » » » » » » » func, i, report_data->ge stures[i].param2); | 337 » » printk(KERN_INFO "%s: report_data.gestures[%d].param2 = 0x%02x\n ", |
| 338 » » » func, i, report_data->gestures[i].param2); | |
| 358 } | 339 } |
| 359 » printk("%s: -----------------------------------------\n", func); | 340 » printk(KERN_INFO "%s: -------------------------------------\n", func); |
| 360 } | 341 } |
| 361 | 342 #else |
| 362 void cyapa_print_paltform_data(const char *func, | 343 void cyapa_dump_data_block(const char *func, u8 reg, u8 length, void *data) {} |
| 363 » » struct cyapa_platform_data *cyapa_i2c_platform_data) | 344 void cyapa_dump_report_data(const char *func, |
| 364 { | 345 » » struct cyapa_report_data *report_data) {} |
| 365 » printk("%s: -----------------------------------------\n", func); | |
| 366 » printk("%s: cyapa_i2c_platform_data.max_touchpad_x = %d\n", func, | |
| 367 » » cyapa_i2c_platform_data->max_touchpad_x); | |
| 368 » printk("%s: cyapa_i2c_platform_data.max_touchpad_y = %d\n", func, | |
| 369 » » cyapa_i2c_platform_data->max_touchpad_y); | |
| 370 » printk("%s: cyapa_i2c_platform_data.min_touchpad_x = %d\n", func, | |
| 371 » » cyapa_i2c_platform_data->min_touchpad_x); | |
| 372 » printk("%s: cyapa_i2c_platform_data.min_touchpad_y = %d\n", func, | |
| 373 » » cyapa_i2c_platform_data->min_touchpad_y); | |
| 374 » printk("%s: cyapa_i2c_platform_data.flag = 0x%08x\n", func, | |
| 375 » » cyapa_i2c_platform_data->flag); | |
| 376 » printk("%s: cyapa_i2c_platform_data.gen = 0x%02x\n", func, | |
| 377 » » cyapa_i2c_platform_data->gen); | |
| 378 » printk("%s: cyapa_i2c_platform_data.power_state = 0x%02x\n", func, | |
| 379 » » cyapa_i2c_platform_data->power_state); | |
| 380 » printk("%s: cyapa_i2c_platform_data.use_absolute_mode = %s\n", func, | |
| 381 » » cyapa_i2c_platform_data->use_absolute_mode?"true":"false"); | |
| 382 » printk("%s: cyapa_i2c_platform_data.use_polling_mode = %s\n", func, | |
| 383 » » cyapa_i2c_platform_data->use_polling_mode?"true":"false"); | |
| 384 » printk("%s: cyapa_i2c_platform_data.polling_interval_time_active = %d\n" , | |
| 385 » » func, cyapa_i2c_platform_data->polling_interval_time_active); | |
| 386 » printk("%s: cyapa_i2c_platform_data.polling_interval_time_lowpower = %d\ n", | |
| 387 » » func, cyapa_i2c_platform_data->polling_interval_time_lowpower); | |
| 388 » printk("%s: cyapa_i2c_platform_data.active_touch_timeout = %d\n", func, | |
| 389 » » cyapa_i2c_platform_data->active_touch_timeout); | |
| 390 » printk("%s: cyapa_i2c_platform_data.name = %s\n", func, | |
| 391 » » cyapa_i2c_platform_data->name); | |
| 392 » printk("%s: cyapa_i2c_platform_data.irq_gpio = %d\n", func, | |
| 393 » » cyapa_i2c_platform_data->irq_gpio); | |
| 394 » printk("%s: cyapa_i2c_platform_data.report_rate = %d\n", func, | |
| 395 » » cyapa_i2c_platform_data->report_rate); | |
| 396 » printk("%s: cyapa_i2c_platform_data.init = %s%p\n", func, | |
| 397 » » cyapa_i2c_platform_data->init?"0x":"", cyapa_i2c_platform_data-> init); | |
| 398 » printk("%s: cyapa_i2c_platform_data.wakeup = %s%p\n", func, | |
| 399 » » cyapa_i2c_platform_data->wakeup?"0x":"", cyapa_i2c_platform_data ->wakeup); | |
| 400 » printk("%s: -----------------------------------------\n", func); | |
| 401 } | |
| 402 #endif | 346 #endif |
| 403 | 347 |
| 404 | 348 |
| 405 /* | 349 /* |
| 406 * Driver's initial design makes no race condition possible on i2c bus, | 350 ** when the irq number is set in system for trackpad, |
| 407 * so there is no need in any locking. | 351 ** but the request irq failed, |
| 408 * Keep it in mind, while playing with the code. | 352 ** so trackpad driver will down to polling mode, |
| 409 */ | 353 ** in this case, do not need and unable to enable/disable this irq. |
| 410 static s32 cyapa_i2c_reg_read_byte(struct i2c_client *client, u16 reg) | 354 */ |
|
Olof Johansson
2011/05/02 05:47:12
This comment was changed away from kernel comment
| |
| 355 static inline void cyapa_enable_irq(struct cyapa_i2c *touch) | |
| 356 { | |
| 357 » if (touch->down_to_polling_mode == false) | |
| 358 » » enable_irq(touch->irq); | |
| 359 } | |
| 360 | |
| 361 static inline void cyapa_disable_irq(struct cyapa_i2c *touch) | |
| 362 { | |
| 363 » if (touch->down_to_polling_mode == false) | |
| 364 » » disable_irq(touch->irq); | |
| 365 } | |
| 366 | |
| 367 static s32 cyapa_i2c_reg_read_byte(struct cyapa_i2c *touch, u16 reg) | |
| 411 { | 368 { |
| 412 int ret; | 369 int ret; |
| 413 | 370 |
| 414 » ret = i2c_smbus_read_byte_data(client, (u8)reg & 0xff); | 371 » /* disable interrupt, and wait I2C bus is read to be operational. */ |
| 372 » cyapa_disable_irq(touch); | |
| 373 » if (down_interruptible(&touch->misc_sem)) { | |
| 374 » » cyapa_enable_irq(touch); | |
| 375 » » pr_err("ERROR: %s: altered by system.\n", __func__); | |
| 376 » » return -ERESTARTSYS; | |
| 377 » } | |
| 378 | |
| 379 » ret = i2c_smbus_read_byte_data(touch->client, (u8)reg & 0xff); | |
| 380 | |
| 381 » /* release semaphore and reenable interrupt. */ | |
| 382 » up(&touch->misc_sem); | |
| 383 » cyapa_enable_irq(touch); | |
| 415 | 384 |
| 416 return ((ret < 0) ? 0 : ret); | 385 return ((ret < 0) ? 0 : ret); |
| 417 } | 386 } |
| 418 | 387 |
| 419 static s32 cyapa_i2c_reg_write_byte(struct i2c_client *client, u16 reg, u8 val) | 388 static s32 cyapa_i2c_reg_write_byte(struct cyapa_i2c *touch, u16 reg, u8 val) |
| 420 { | 389 { |
| 421 int ret; | 390 int ret; |
| 422 | 391 |
| 423 » ret = i2c_smbus_write_byte_data(client, (u8)reg & 0xff, val); | 392 » /* disable interrupt, and wait I2C bus is read to be operational. */ |
| 393 » cyapa_disable_irq(touch); | |
| 394 » if (down_interruptible(&touch->misc_sem)) { | |
| 395 » » cyapa_enable_irq(touch); | |
| 396 » » pr_err("ERROR: %s: altered by system.\n", __func__); | |
| 397 » » return -ERESTARTSYS; | |
| 398 » } | |
| 399 | |
| 400 » ret = i2c_smbus_write_byte_data(touch->client, (u8)reg & 0xff, val); | |
| 401 | |
| 402 » /* release semaphore and reenable interrupt. */ | |
| 403 » up(&touch->misc_sem); | |
| 404 » cyapa_enable_irq(touch); | |
| 424 | 405 |
| 425 return ((ret < 0) ? 0 : ret); | 406 return ((ret < 0) ? 0 : ret); |
| 426 } | 407 } |
| 427 | 408 |
| 428 static s32 cyapa_i2c_reg_read_block(struct i2c_client *client, u16 reg, | 409 static s32 cyapa_i2c_reg_read_block(struct cyapa_i2c *touch, u16 reg, |
| 429 int length, u8 *values) | 410 int length, u8 *values) |
| 430 { | 411 { |
| 431 int retval; | 412 int retval; |
| 432 u8 buf[1]; | 413 u8 buf[1]; |
| 433 » | 414 |
| 415 » /* disable interrupt, and wait I2C bus is read to be operational. */ | |
| 416 » cyapa_disable_irq(touch); | |
| 417 » if (down_interruptible(&touch->misc_sem)) { | |
| 418 » » cyapa_enable_irq(touch); | |
| 419 » » pr_err("ERROR: %s: altered by system.\n", __func__); | |
| 420 » » return -ERESTARTSYS; | |
| 421 » } | |
| 422 | |
| 434 /* | 423 /* |
| 435 ** depending on PSOC easy I2C read operations. | 424 ** depending on PSOC easy I2C read operations. |
| 436 ** step1: set read pointer of easy I2C. | 425 ** step1: set read pointer of easy I2C. |
| 437 ** step2: read data. | 426 ** step2: read data. |
| 438 */ | 427 */ |
| 439 » // step1: set read pointer of easy I2C. | 428 » /* step1: set read pointer of easy I2C. */ |
| 440 memset(buf, 0, 1); | 429 memset(buf, 0, 1); |
| 441 buf[0] = (u8)(((u8)reg) & 0xff); | 430 buf[0] = (u8)(((u8)reg) & 0xff); |
| 442 » retval = i2c_master_send(client, buf, 1); | 431 » retval = i2c_master_send(touch->client, buf, 1); |
| 443 if (retval < 0) { | 432 if (retval < 0) { |
| 444 » » DBGPRINTK(("%s: i2c_master_send error, retval=%d\n", __func__, r etval)); | 433 » » DBGPRINTK(("%s: i2c_master_send error, retval=%d\n", |
|
Olof Johansson
2011/05/02 05:47:12
pr_debug instead?
| |
| 445 » » return retval; | 434 » » » __func__, retval)); |
| 446 » } | 435 |
| 447 » | 436 » » /* release semaphore and reenable interrupt. */ |
| 448 » //step2: read data. | 437 » » up(&touch->misc_sem); |
| 449 » retval = i2c_master_recv(client, values, length); | 438 » » cyapa_enable_irq(touch); |
| 450 » if (retval < 0) { | |
| 451 » » DBGPRINTK(("%s: i2c_master_recv error, retval=%d\n", __func__, r etval)); | |
| 452 return retval; | 439 return retval; |
| 453 } | 440 } |
| 454 | 441 |
| 455 #ifdef DBG_CYAPA_READ_BLOCK_DATA | 442 » /* step2: read data. */ |
| 456 » /* debug message */ | 443 » retval = i2c_master_recv(touch->client, values, length); |
| 457 » cyapa_print_data_block(__func__, (u8)reg, retval, values); | 444 » /* release semaphore and reenable interrupt. */ |
| 458 #endif | 445 » up(&touch->misc_sem); |
| 446 » cyapa_enable_irq(touch); | |
| 447 » if (retval < 0) { | |
| 448 » » DBGPRINTK(("%s: i2c_master_recv error, retval=%d\n", | |
| 449 » » » __func__, retval)); | |
| 450 » » return retval; | |
| 451 » } | |
| 459 | 452 |
| 460 if (retval != length) { | 453 if (retval != length) { |
| 461 » » dev_warn(&client->dev, | 454 » » dev_warn(&touch->client->dev, |
| 462 » » » "%s: warning I2C block read bytes [%d] not equal to requ ired bytes [%d].\n", | 455 » » » "%s: warning I2C block read bytes \ |
| 456 » » » [%d] not equal to required bytes [%d].\n", | |
| 463 __func__, retval, length); | 457 __func__, retval, length); |
| 464 } | 458 } |
| 465 | 459 |
| 460 /* DEBUG: dump readed block data */ | |
| 461 cyapa_dump_data_block(__func__, (u8)reg, retval, values); | |
| 462 | |
| 466 return retval; | 463 return retval; |
| 467 } | 464 } |
| 468 | 465 |
| 469 static s32 cyapa_i2c_reg_write_block(struct i2c_client *client, u16 reg, | 466 static s32 cyapa_i2c_reg_write_block(struct cyapa_i2c *touch, u16 reg, |
| 470 u8 length, const u8 *values) | 467 u8 length, const u8 *values) |
| 471 | 468 |
| 472 { | 469 { |
| 473 int retval; | 470 int retval; |
| 474 int i; | 471 int i; |
| 475 u8 buf[256]; | 472 u8 buf[256]; |
| 476 | 473 |
| 477 » if ((length+1) > 256) { | 474 » if ((length+1) > 256) { |
| 478 » » DBGPRINTK(("%s: invalid write data length, length=%d\n", __func_ _, length)); | 475 » » DBGPRINTK(("%s: invalid write data length, length=%d\n", |
| 479 » » return -EINVAL; | 476 » » » __func__, length)); |
| 477 » » return -EINVAL; | |
| 478 » } | |
| 479 | |
| 480 » /* disable interrupt, and wait I2C bus is read to be operational. */ | |
| 481 » cyapa_disable_irq(touch); | |
| 482 » if (down_interruptible(&touch->misc_sem)) { | |
| 483 » » cyapa_enable_irq(touch); | |
| 484 » » pr_err("ERROR: %s: altered by system.\n", __func__); | |
| 485 » » return -ERESTARTSYS; | |
| 480 } | 486 } |
| 481 | 487 |
| 482 /* | 488 /* |
| 483 ** depending on PSOC easy I2C read operations. | 489 ** depending on PSOC easy I2C read operations. |
| 484 ** step1: write data to easy I2C in one command. | 490 ** step1: write data to easy I2C in one command. |
| 485 */ | 491 */ |
| 486 » // step1: write data to easy I2C in one command. | 492 » /* step1: write data to easy I2C in one command. */ |
| 487 memset(buf, 0, 256); | 493 memset(buf, 0, 256); |
| 488 buf[0] = (u8)(((u8)reg) & 0xff); | 494 buf[0] = (u8)(((u8)reg) & 0xff); |
| 489 /* move data shoud be write to I2C slave device. */ | 495 /* move data shoud be write to I2C slave device. */ |
| 490 » for (i=1; i<length; i++) | 496 » for (i = 1; i < length+1; i++) |
| 491 » { | |
| 492 buf[i] = values[i-1]; | 497 buf[i] = values[i-1]; |
| 493 » } | 498 |
| 494 » retval = i2c_master_send(client, buf, length+1); | 499 » retval = i2c_master_send(touch->client, buf, length+1); |
| 500 » /* release semaphore and reenable interrupt. */ | |
| 501 » up(&touch->misc_sem); | |
| 502 » cyapa_enable_irq(touch); | |
| 495 if (retval < 0) { | 503 if (retval < 0) { |
| 496 » » DBGPRINTK(("%s: i2c_master_send error, retval=%d\n", __func__, r etval)); | 504 » » DBGPRINTK(("%s: i2c_master_send error, retval=%d\n", |
| 505 » » » __func__, retval)); | |
| 497 return retval; | 506 return retval; |
| 498 } | 507 } |
| 499 | 508 |
| 500 » if (retval != (length+1)) { | 509 » /* one additional writen byte is register offset. */ |
| 501 » » dev_warn(&client->dev, | 510 » if ((retval-1) != length) { |
| 502 » » » "%s: warning I2C block write bytes [%d] not equal to req uired bytes [%d].\n", | 511 » » dev_warn(&touch->client->dev, |
| 512 » » » "%s: warning I2C block write bytes \ | |
| 513 » » » [%d] not equal to required bytes [%d].\n", | |
| 503 __func__, retval, length); | 514 __func__, retval, length); |
| 504 } | 515 } |
| 505 | 516 |
| 506 » return retval; | 517 » return retval - 1; |
| 507 } | 518 } |
| 519 | |
| 520 | |
| 521 /* | |
| 522 *************************************************************** | |
| 523 ** misc deivce for trackpad firmware update, | |
| 524 ** and for raw read/wtite operations. | |
| 525 ** Bellow program may open and use cyaya_misc_dev. | |
| 526 ** 1. synaptics X Driver. | |
| 527 ** 2. trackpad firmware update program. | |
| 528 *************************************************************** | |
| 529 */ | |
| 530 static int cyapa_misc_open(struct inode *inode, struct file *file) | |
| 531 { | |
| 532 » int count = 0; | |
|
Olof Johansson
2011/05/02 05:47:12
This assignment is unneeded.
| |
| 533 | |
| 534 » file->private_data = (void *)global_touch; | |
| 535 | |
| 536 » spin_lock(&global_touch->misc_spinlock); | |
| 537 » if (global_touch->misc_open_count) { | |
| 538 » » spin_unlock(&global_touch->misc_spinlock); | |
| 539 » » pr_debug("DEBUG: %s, misc device busy.\n", __func__); | |
| 540 » » return -EBUSY; | |
| 541 » } | |
| 542 » count = ++global_touch->misc_open_count; | |
| 543 » spin_unlock(&global_touch->misc_spinlock); | |
| 544 | |
| 545 » pr_debug("DEBUG: enter %s, misc device open count = %d\n", | |
| 546 » » __func__, count); | |
| 547 | |
| 548 » return 0; | |
| 549 } | |
| 550 | |
| 551 static int cyapa_misc_close(struct inode *inode, struct file *file) | |
| 552 { | |
| 553 » int count = 0; | |
|
Olof Johansson
2011/05/02 05:47:12
This assignment is unneeded.
| |
| 554 | |
| 555 » spin_lock(&global_touch->misc_spinlock); | |
| 556 » count = --global_touch->misc_open_count; | |
| 557 » spin_unlock(&global_touch->misc_spinlock); | |
| 558 | |
| 559 » pr_debug("DEBUG: enter %s, misc device open count = %d\n", | |
| 560 » » __func__, count); | |
| 561 | |
| 562 » return 0; | |
| 563 } | |
| 564 | |
| 565 static loff_t cyapa_misc_llseek(struct file *file, loff_t offset, int origin) | |
| 566 { | |
| 567 » loff_t ret = 0; | |
| 568 » struct cyapa_i2c *touch = NULL; | |
|
Olof Johansson
2011/05/02 05:47:12
Assignment to NULL not needed, or just assign to f
| |
| 569 | |
| 570 » pr_info("INFO: enter %s, offset=%d, origin=%d\n", | |
| 571 » » __func__, (int)offset, (int)origin); | |
| 572 | |
| 573 » if (file->private_data == NULL) { | |
| 574 » » pr_err("ERROR: %s: cypress trackpad device does not exit.\n", | |
| 575 » » » __func__); | |
| 576 » » return -ENODEV; | |
| 577 » } | |
| 578 » touch = (struct cyapa_i2c *)file->private_data; | |
| 579 | |
| 580 » mutex_lock(&touch->misc_mutex); | |
| 581 » switch (origin) { | |
| 582 » case SEEK_SET: | |
| 583 » » if (offset < 0 || (unsigned int)offset > 256) { | |
| 584 » » » ret = -EINVAL; | |
| 585 » » » break; | |
| 586 » » } | |
| 587 | |
| 588 » » file->f_pos = offset; | |
| 589 » » ret = file->f_pos; | |
| 590 » » break; | |
| 591 | |
| 592 » case SEEK_CUR: | |
| 593 » » if ((file->f_pos + offset) > 256 | |
| 594 » » » || (file->f_pos + offset) < 0) { | |
| 595 » » » ret = -EINVAL; | |
| 596 » » » break; | |
| 597 » » } | |
| 598 | |
| 599 » » file->f_pos += offset; | |
| 600 » » ret = file->f_pos; | |
| 601 » » break; | |
| 602 | |
| 603 » case SEEK_END: | |
| 604 » » if ((256 + offset) > 256 || (256 + offset) < 0) { | |
| 605 » » » ret = -EINVAL; | |
| 606 » » » break; | |
| 607 » » } | |
| 608 | |
| 609 » » file->f_pos = (256 + offset); | |
| 610 » » ret = file->f_pos; | |
| 611 » » break; | |
| 612 | |
| 613 » default: | |
| 614 » » ret = -EINVAL; | |
| 615 » » break; | |
| 616 » } | |
| 617 » mutex_unlock(&touch->misc_mutex); | |
| 618 | |
| 619 » pr_info("INFO %s: f_pos=%lld, exit code = %lld.\n", | |
| 620 » » __func__, (long long)file->f_pos, (long long)ret); | |
| 621 | |
| 622 » return ret; | |
| 623 } | |
| 624 | |
| 625 static ssize_t cyapa_misc_read(struct file *file, char __user *usr_buf, | |
| 626 » » size_t count, loff_t *offset) | |
| 627 { | |
| 628 » int ret = 0; | |
| 629 » unsigned int reg_len = 256; | |
| 630 » unsigned long reg_offset = *offset; | |
| 631 » unsigned char reg_buf[256]; | |
| 632 » struct cyapa_i2c *touch = NULL; | |
|
Olof Johansson
2011/05/02 05:47:12
Assignment to NULL not needed -- or just assign to
| |
| 633 | |
| 634 » pr_info("INFO: enter %s, count=%d, offset=%d\n", | |
| 635 » » __func__, (int)count, (int)*offset); | |
|
Olof Johansson
2011/05/02 05:47:12
Printing this on every call is too verbose. pr_deb
| |
| 636 | |
| 637 » if (file->private_data == NULL) { | |
| 638 » » pr_err("ERROR: %s: cypress trackpad device does not exit.\n", | |
| 639 » » » __func__); | |
| 640 » » return -ENODEV; | |
| 641 » } | |
| 642 » touch = (struct cyapa_i2c *)file->private_data; | |
| 643 » /* max registers contained in one register map in bytes in 256. */ | |
| 644 » if (reg_offset > 255 || count > 256 | |
| 645 » » || (reg_offset + count) > 256 || (reg_offset + count) < 0) | |
| 646 » » return -EINVAL; | |
| 647 » reg_len = (count < reg_len) ? count : reg_len; | |
| 648 | |
| 649 » /* read I2C registers. */ | |
| 650 » ret = cyapa_i2c_reg_read_block(touch, (u16)reg_offset, | |
| 651 » » » » » reg_len, (u8 *)reg_buf); | |
| 652 » if (ret < 0) { | |
| 653 » » pr_err("ERROR: %s: cypress trackpad I2C read FAILED.\n", | |
| 654 » » » __func__); | |
| 655 » » return ret; | |
| 656 » } | |
| 657 | |
| 658 » if (ret < reg_len) | |
| 659 » » pr_err("WARNING: %s: Execped %d bytes, read %d bytes.\n", | |
| 660 » » » __func__, reg_len, ret); | |
| 661 » reg_len = ret; | |
| 662 | |
| 663 » /* copy to user space. */ | |
| 664 » if (copy_to_user(usr_buf, reg_buf, reg_len)) { | |
| 665 » » ret = -EFAULT; | |
| 666 » } else { | |
| 667 » » *offset += reg_len; | |
| 668 » » ret = reg_len; | |
| 669 | |
| 670 » » pr_info("INFO: %s: read %d bytes from offset %d\n", | |
| 671 » » » __func__, (int)reg_len, (int)reg_offset); | |
| 672 » } | |
| 673 | |
| 674 » return ret; | |
| 675 } | |
| 676 | |
| 677 static ssize_t cyapa_misc_write(struct file *file, const char __user *usr_buf, | |
| 678 » » size_t count, loff_t *offset) | |
| 679 { | |
| 680 » int ret = 0; | |
| 681 » unsigned int reg_len = 256; | |
| 682 » unsigned long reg_offset = *offset; | |
| 683 » unsigned char reg_buf[256]; | |
| 684 » struct cyapa_i2c *touch = NULL; | |
|
Olof Johansson
2011/05/02 05:47:12
Again, this can be assigned to file->private_data
| |
| 685 | |
| 686 » pr_info("INFO: enter %s, count=%d, offset=%d\n", | |
| 687 » » __func__, (int)count, (int)*offset); | |
|
Olof Johansson
2011/05/02 05:47:12
pr_debug()
| |
| 688 | |
| 689 » if (file->private_data == NULL) { | |
| 690 » » pr_err("ERROR: %s: cypress trackpad device does not exit.\n", | |
| 691 » » » __func__); | |
| 692 » » return -ENODEV; | |
| 693 » } | |
| 694 » touch = (struct cyapa_i2c *)file->private_data; | |
| 695 » if (reg_offset > 255 || count > 256 | |
| 696 » » || (reg_offset + count) > 256 || (reg_offset + count) < 0) | |
| 697 » » return -EINVAL; | |
|
Olof Johansson
2011/05/02 05:47:12
This code is duplicated with the read function. Br
| |
| 698 » reg_len = (count < reg_len) ? count : reg_len; | |
| 699 | |
| 700 » /* copy to kernel space. */ | |
| 701 » if (copy_from_user(reg_buf, usr_buf, reg_len)) { | |
| 702 » » pr_err("ERROR: %s: copy data from user space failed.\n", | |
| 703 » » » __func__); | |
| 704 » » return -EINVAL; | |
| 705 » } | |
| 706 | |
| 707 » /* write I2C registers. */ | |
| 708 » ret = cyapa_i2c_reg_write_block(touch, | |
| 709 » » » » » (u16)reg_offset, | |
| 710 » » » » » (u8)reg_len, | |
| 711 » » » » » (u8 *)reg_buf); | |
| 712 » if (ret < 0) { | |
|
Olof Johansson
2011/05/02 05:47:12
Braces not needed
| |
| 713 » » pr_err("ERROR: %s: cypress trackpad I2C write FAILED.\n", | |
| 714 » » » __func__); | |
| 715 » } | |
| 716 | |
| 717 » *offset = (ret < 0) ? reg_offset : (reg_offset + ret); | |
| 718 » pr_info("INFO: %s, write %d bytes to offset %d\n", | |
| 719 » » » __func__, ret, (int)reg_offset); | |
| 720 | |
| 721 » return ret; | |
| 722 } | |
| 723 | |
| 724 static long cyapa_misc_ioctl(struct file *file, unsigned int cmd, | |
| 725 » » unsigned long arg) | |
| 726 { | |
| 727 » int ret = 0; | |
| 728 » struct cyapa_i2c *touch = NULL; | |
|
Olof Johansson
2011/05/02 05:47:12
Again, can be assigned directly.
| |
| 729 » struct cyapa_misc_ioctl_data ioctl_data; | |
| 730 | |
| 731 » pr_debug("INFO: enter %s, ioctl cmd=0x%02x, arg=0x%02lx\n", | |
| 732 » » __func__, cmd, arg); | |
| 733 | |
| 734 » if (file->private_data == NULL) { | |
| 735 » » pr_err("ERROR: %s: cypress trackpad device does not exit.\n", | |
| 736 » » » __func__); | |
| 737 » » return -ENODEV; | |
| 738 » } | |
| 739 » touch = (struct cyapa_i2c *)file->private_data; | |
| 740 | |
| 741 » /* copy to kernel space. */ | |
| 742 » if (copy_from_user(&ioctl_data, (u8 *)arg, | |
| 743 » » sizeof(struct cyapa_misc_ioctl_data))) | |
| 744 » » return -EINVAL; | |
|
Olof Johansson
2011/05/02 05:47:12
The above is a little hard to read. Making the if(
| |
| 745 | |
| 746 » switch (cmd) { | |
| 747 » case CYAPA_GET_PRODUCT_ID: | |
| 748 » » if (!ioctl_data.buf || ioctl_data.len < 16) | |
| 749 » » » return -EINVAL; | |
| 750 | |
| 751 » » cyapa_get_query_data(touch); | |
| 752 » » ioctl_data.len = 16; | |
| 753 » » if (copy_to_user(ioctl_data.buf, touch->product_id, 16)) | |
| 754 » » » » return -ENODEV; | |
| 755 » » if (copy_to_user((void *)arg, &ioctl_data, | |
| 756 » » » sizeof(struct cyapa_misc_ioctl_data))) | |
| 757 » » » return -ENODEV; | |
| 758 » » return ioctl_data.len; | |
| 759 | |
| 760 » case CYAPA_GET_DRIVER_VER: | |
| 761 » » if (!ioctl_data.buf || ioctl_data.len < 3) | |
| 762 » » » return -EINVAL; | |
| 763 | |
| 764 » » cyapa_get_query_data(touch); | |
| 765 » » ioctl_data.len = 3; | |
| 766 » » if (put_user((unsigned char)CYAPA_MAJOR_VER, ioctl_data.buf) | |
| 767 » » » || put_user((unsigned char)CYAPA_MINOR_VER, | |
| 768 » » » » ioctl_data.buf + 1) | |
| 769 » » » || put_user((unsigned char)CYAPA_REVISION_VER, | |
| 770 » » » » ioctl_data.buf + 2)) | |
|
Olof Johansson
2011/05/02 05:47:12
The above is hard to read. Since it's just 3 bytes
| |
| 771 » » » return -EINVAL; | |
| 772 » » if (copy_to_user((void *)arg, &ioctl_data, | |
| 773 » » » sizeof(struct cyapa_misc_ioctl_data))) | |
| 774 » » » return -ENODEV; | |
| 775 » » return ioctl_data.len; | |
| 776 | |
| 777 » case CYAPA_GET_FIRMWARE_VER: | |
| 778 » » if (!ioctl_data.buf || ioctl_data.len < 2) | |
| 779 » » » return -EINVAL; | |
| 780 | |
| 781 » » cyapa_get_query_data(touch); | |
| 782 » » ioctl_data.len = 2; | |
| 783 » » if (put_user(touch->fm_maj_ver, ioctl_data.buf) | |
| 784 » » » || put_user(touch->fm_min_ver, ioctl_data.buf + 1)) | |
| 785 » » » return -EINVAL; | |
| 786 » » if (copy_to_user((void *)arg, &ioctl_data, | |
| 787 » » » sizeof(struct cyapa_misc_ioctl_data))) | |
| 788 » » » return -ENODEV; | |
| 789 » » return ioctl_data.len; | |
| 790 | |
| 791 » case CYAPA_GET_HARDWARE_VER: | |
| 792 » » if (!ioctl_data.buf || ioctl_data.len < 2) | |
| 793 » » » return -EINVAL; | |
| 794 | |
| 795 » » cyapa_get_query_data(touch); | |
| 796 » » ioctl_data.len = 2; | |
| 797 » » if (put_user(touch->hw_maj_ver, ioctl_data.buf) | |
| 798 » » » || put_user(touch->hw_min_ver, ioctl_data.buf + 1)) | |
| 799 » » » return -EINVAL; | |
| 800 » » if (copy_to_user((void *)arg, &ioctl_data, | |
| 801 » » » sizeof(struct cyapa_misc_ioctl_data))) | |
| 802 » » » return -ENODEV; | |
| 803 » » return ioctl_data.len; | |
| 804 | |
| 805 » case CYAPA_SET_BOOTLOADER_MODE: | |
| 806 » » return ret; | |
| 807 | |
| 808 » case CYAPA_SET_STREAM_MODE: | |
| 809 » » break; | |
| 810 | |
| 811 » default: | |
| 812 » » ret = -EINVAL; | |
| 813 » » break; | |
| 814 » } | |
| 815 | |
| 816 » return ret; | |
| 817 } | |
| 818 | |
| 819 static const struct file_operations cyapa_misc_fops = { | |
| 820 » .owner = THIS_MODULE, | |
| 821 » .open = cyapa_misc_open, | |
| 822 » .release = cyapa_misc_close, | |
| 823 » .unlocked_ioctl = cyapa_misc_ioctl, | |
| 824 » .llseek = cyapa_misc_llseek, | |
| 825 » .read = cyapa_misc_read, | |
| 826 » .write = cyapa_misc_write, | |
| 827 }; | |
| 828 | |
| 829 static struct miscdevice cyapa_misc_dev = { | |
| 830 » .name = CYAPA_MISC_NAME, | |
| 831 » .fops = &cyapa_misc_fops, | |
| 832 » .minor = MISC_DYNAMIC_MINOR, | |
| 833 }; | |
| 834 | |
| 835 static int __init cyapa_misc_init(void) | |
| 836 { | |
| 837 » int ret = 0; | |
|
Olof Johansson
2011/05/02 05:47:12
No need to initialize.
| |
| 838 | |
| 839 » pr_info("INFO: enter %s\n", __func__); | |
| 840 » ret = misc_register(&cyapa_misc_dev); | |
| 841 » if (ret) { | |
|
Olof Johansson
2011/05/02 05:47:12
No need for braces.
| |
| 842 » » pr_err("ERROR: %s: cyapa misc device register FAILED.\n", | |
| 843 » » » __func__); | |
| 844 » } | |
| 845 | |
| 846 » return ret; | |
| 847 } | |
| 848 | |
| 849 static void __exit cyapa_misc_exit(void) | |
| 850 { | |
| 851 » pr_info("INFO: enter %s\n", __func__); | |
| 852 » misc_deregister(&cyapa_misc_dev); | |
| 853 } | |
| 854 | |
| 855 static void cyapa_update_firmware_dispatch(struct cyapa_i2c *touch) | |
| 856 { | |
| 857 » /* do something here to update trackpad firmware. */ | |
| 858 } | |
| 859 | |
| 860 /* | |
| 861 **************************************************************** | |
| 862 ** Cypress i2c trackpad input device driver. | |
| 863 **************************************************************** | |
| 864 */ | |
| 508 | 865 |
| 509 #define REG_OFFSET_DATA_BASE 0x0000 | 866 #define REG_OFFSET_DATA_BASE 0x0000 |
| 510 #define REG_OFFSET_CONTROL_BASE 0x0029 | 867 #define REG_OFFSET_CONTROL_BASE 0x0029 |
| 511 #define REG_OFFSET_COMMAND_BASE 0x0049 | 868 #define REG_OFFSET_COMMAND_BASE 0x0049 |
| 512 #define REG_OFFSET_QUERY_BASE 0x004B | 869 #define REG_OFFSET_QUERY_BASE 0x004B |
| 513 static void cyapa_get_reg_offset(struct cyapa_i2c *touch) | 870 static void cyapa_get_reg_offset(struct cyapa_i2c *touch) |
| 514 { | 871 { |
| 515 touch->data_base_offset = REG_OFFSET_DATA_BASE; | 872 touch->data_base_offset = REG_OFFSET_DATA_BASE; |
| 516 touch->control_base_offset = REG_OFFSET_CONTROL_BASE; | 873 touch->control_base_offset = REG_OFFSET_CONTROL_BASE; |
| 517 touch->command_base_offset = REG_OFFSET_COMMAND_BASE; | 874 touch->command_base_offset = REG_OFFSET_COMMAND_BASE; |
| 518 touch->query_base_offset = REG_OFFSET_QUERY_BASE; | 875 touch->query_base_offset = REG_OFFSET_QUERY_BASE; |
| 519 | 876 |
| 520 /* this function will be updated later depending firmware support. */ | 877 /* this function will be updated later depending firmware support. */ |
| 521 } | 878 } |
| 522 | 879 |
| 523 static void cyapa_get_query_data(struct cyapa_i2c *touch) | 880 static void cyapa_get_query_data(struct cyapa_i2c *touch) |
| 524 { | 881 { |
| 525 unsigned char query_data[40]; | 882 unsigned char query_data[40]; |
| 526 int ret_read_size = 0; | 883 int ret_read_size = 0; |
| 527 int i; | 884 int i; |
| 528 | 885 |
| 529 /* query data has been supported in GEN1 protocol.*/ | 886 /* query data has been supported in GEN1 protocol.*/ |
| 530 » if (touch->platform_data->gen == CYAPA_GEN2) | 887 » if (touch->platform_data->gen == CYAPA_GEN2) { |
| 531 » { | |
| 532 memset(query_data, 0, 40); | 888 memset(query_data, 0, 40); |
| 533 » » ret_read_size = cyapa_i2c_reg_read_block(touch->client, | 889 » » ret_read_size = cyapa_i2c_reg_read_block(touch, |
| 534 touch->query_base_offset, | 890 touch->query_base_offset, |
| 535 38, | 891 38, |
| 536 (u8 *)&query_data); | 892 (u8 *)&query_data); |
| 537 | 893 |
| 538 touch->product_id[0] = query_data[0]; | 894 touch->product_id[0] = query_data[0]; |
| 539 touch->product_id[1] = query_data[1]; | 895 touch->product_id[1] = query_data[1]; |
| 540 touch->product_id[2] = query_data[2]; | 896 touch->product_id[2] = query_data[2]; |
| 541 touch->product_id[3] = query_data[3]; | 897 touch->product_id[3] = query_data[3]; |
| 542 touch->product_id[4] = query_data[4]; | 898 touch->product_id[4] = query_data[4]; |
| 543 touch->product_id[5] = '-'; | 899 touch->product_id[5] = '-'; |
| 544 touch->product_id[6] = query_data[5]; | 900 touch->product_id[6] = query_data[5]; |
| 545 touch->product_id[7] = query_data[6]; | 901 touch->product_id[7] = query_data[6]; |
| 546 touch->product_id[8] = query_data[7]; | 902 touch->product_id[8] = query_data[7]; |
| 547 touch->product_id[9] = query_data[8]; | 903 touch->product_id[9] = query_data[8]; |
| 548 touch->product_id[10] = query_data[9]; | 904 touch->product_id[10] = query_data[9]; |
| 549 touch->product_id[11] = query_data[10]; | 905 touch->product_id[11] = query_data[10]; |
| 550 touch->product_id[12] = '-'; | 906 touch->product_id[12] = '-'; |
| 551 touch->product_id[13] = query_data[11]; | 907 touch->product_id[13] = query_data[11]; |
| 552 touch->product_id[14] = query_data[12]; | 908 touch->product_id[14] = query_data[12]; |
| 553 touch->product_id[15] = '\0'; | 909 touch->product_id[15] = '\0'; |
| 554 | 910 |
| 555 touch->fm_maj_ver = query_data[15]; | 911 touch->fm_maj_ver = query_data[15]; |
| 556 touch->fm_min_ver = query_data[16]; | 912 touch->fm_min_ver = query_data[16]; |
| 557 touch->hw_maj_ver = query_data[17]; | 913 touch->hw_maj_ver = query_data[17]; |
| 558 touch->hw_min_ver = query_data[18]; | 914 touch->hw_min_ver = query_data[18]; |
| 559 | 915 |
| 560 » » for (i=0; i<13; i++) { | 916 » » for (i = 0; i < 13; i++) |
| 561 touch->capability[i] = query_data[19+i]; | 917 touch->capability[i] = query_data[19+i]; |
| 562 } | |
| 563 | 918 |
| 564 » » touch->max_absolution_x = (((query_data[32] & 0xF0) << 4) | quer y_data[33]); | 919 » » touch->max_absolution_x = |
| 565 » » touch->max_absolution_y = (((query_data[32] & 0x0F) << 8) | quer y_data[34]); | 920 » » » (((query_data[32] & 0xF0) << 4) | query_data[33]); |
| 566 » » if (!touch->max_absolution_x || !touch->max_absolution_y) { | 921 » » touch->max_absolution_y = |
| 567 » » » if (!strcmp(touch->product_id, "CYTRA-014001-00")) { | 922 » » » (((query_data[32] & 0x0F) << 8) | query_data[34]); |
| 568 » » » » touch->max_absolution_x = 1600; | |
| 569 » » » » touch->max_absolution_y = 900; | |
| 570 » » » } else { | |
| 571 » » » » touch->max_absolution_x = 1200; | |
| 572 » » » » touch->max_absolution_y = 600; | |
| 573 » » » } | |
| 574 » » } | |
| 575 | 923 |
| 576 » » touch->physical_size_x = (((query_data[35] & 0xF0) << 4) | query _data[36]); | 924 » » touch->physical_size_x = |
| 577 » » touch->physical_size_y = (((query_data[35] & 0x0F) << 8) | query _data[37]); | 925 » » » (((query_data[35] & 0xF0) << 4) | query_data[36]); |
| 926 » » touch->physical_size_y = | |
| 927 » » » (((query_data[35] & 0x0F) << 8) | query_data[37]); | |
| 578 if (!touch->physical_size_x || !touch->physical_size_y) { | 928 if (!touch->physical_size_x || !touch->physical_size_y) { |
| 579 touch->physical_size_x = 105; | 929 touch->physical_size_x = 105; |
| 580 touch->physical_size_y = 60; | 930 touch->physical_size_y = 60; |
| 581 } | 931 } |
| 582 | |
| 583 printk("Cypress Trackpad Information:\n"); | |
| 584 printk("\t\t\tProduction ID: %s\n", touch->product_id); | |
| 585 printk("\t\t\tFirmware version: %d.%d\n", touch->fm_maj_ver, to uch->fm_min_ver); | |
| 586 printk("\t\t\tHardware version: %d.%d\n", touch->hw_maj_ver, to uch->hw_min_ver); | |
| 587 printk("\t\t\tResolution X,Y: %d,%d\n", touch->max_absolution_ x, touch->max_absolution_y); | |
| 588 printk("\t\t\tPhysical Size X,Y: %d,%d\n", touch->physical_siz e_x, touch->physical_size_y); | |
| 589 } | 932 } |
| 590 } | 933 } |
| 591 | 934 |
| 592 static int cyapa_i2c_reconfig(struct cyapa_i2c *touch) | 935 static int cyapa_i2c_reconfig(struct cyapa_i2c *touch) |
| 593 { | 936 { |
| 594 struct i2c_client *client = touch->client; | |
| 595 int regval = 0; | 937 int regval = 0; |
| 596 int retval = 0; | 938 int retval = 0; |
| 597 | 939 |
| 598 if (touch->platform_data->gen == CYAPA_GEN1) { | 940 if (touch->platform_data->gen == CYAPA_GEN1) { |
| 599 /* trackpad gen1 firmware. */ | 941 /* trackpad gen1 firmware. */ |
| 600 » » DBGPRINTK(("%s: trackpad support gen1 firmware. \n", __func__)); | 942 » » DBGPRINTK(("%s: trackpad support gen1 firmware.\n", __func__)); |
| 601 » » | 943 |
| 602 » » regval = cyapa_i2c_reg_read_byte(client, DEV_POWER_REG); | 944 » » regval = cyapa_i2c_reg_read_byte(touch, DEV_POWER_REG); |
| 603 » » DBGPRINTK(("%s: read trackpad interrupt bit = 0x%02x \n", | 945 » » DBGPRINTK(("%s: read trackpad interrupt bit = 0x%02x\n", |
| 604 __func__, regval&INTERRUPT_MODE_MASK)); | 946 __func__, regval&INTERRUPT_MODE_MASK)); |
| 605 | 947 |
| 606 » » if ( (touch->platform_data->use_polling_mode == true) && | 948 » » if ((touch->down_to_polling_mode == true) |
| 607 » » » ((regval & INTERRUPT_MODE_MASK) == INTERRUPT_MODE_MASK) ) | 949 » » » && ((regval & INTERRUPT_MODE_MASK) |
| 608 » » { | 950 » » » » == INTERRUPT_MODE_MASK)) { |
| 609 /* reset trackpad to polling mode. */ | 951 /* reset trackpad to polling mode. */ |
| 610 regval &= (~INTERRUPT_MODE_MASK); | 952 regval &= (~INTERRUPT_MODE_MASK); |
| 611 » » » retval = cyapa_i2c_reg_write_byte(client, DEV_POWER_REG, (u8)(regval & 0xff)); | 953 » » » retval = cyapa_i2c_reg_write_byte(touch, DEV_POWER_REG, |
| 612 » » » if (retval) { | 954 » » » » » » (u8)(regval & 0xff)); |
| 613 » » » » DBGPRINTK(("%s: set to polliing mode failed, ret val=%d.\n", __func__, retval)); | 955 » » » /* |
| 614 » » » » /* | 956 » » » * Wether reset interrupt mode bit sucess or failed. |
| 615 » » » » * Though firmware has set interrupt mode bit. | 957 » » » * because platfrom doesn't support interrupt mode, |
| 616 » » » » * but since platfrom doesn't support interrupt mode, | 958 » » » * so driver will just use polling mode. |
| 617 » » » » * so also use polling mode here. | 959 » » » */ |
| 618 » » » » * do nothing. | 960 » » } else if ((touch->down_to_polling_mode == false) |
| 619 » » » » */ | 961 » » » && ((regval & INTERRUPT_MODE_MASK) |
| 620 » » » } | 962 » » » » != INTERRUPT_MODE_MASK)) { |
| 621 » » } | |
| 622 » » else if ( (touch->platform_data->use_polling_mode == false) && | |
| 623 » » » ((regval & INTERRUPT_MODE_MASK) != INTERRUPT_MODE_MASK) ) | |
| 624 » » { | |
| 625 /* reset trackpad to interrupt mode. */ | 963 /* reset trackpad to interrupt mode. */ |
| 626 regval |= INTERRUPT_MODE_MASK; | 964 regval |= INTERRUPT_MODE_MASK; |
| 627 » » » retval = cyapa_i2c_reg_write_byte(client, DEV_POWER_REG, (u8)(regval & 0xff)); | 965 » » » retval = cyapa_i2c_reg_write_byte(touch, DEV_POWER_REG, |
| 628 » » » if (retval) { | 966 » » » » » » (u8)(regval & 0xff)); |
| 629 » » » » DBGPRINTK(("%s: set to interrup mode failed, ret val=%d.\n", __func__, retval)); | 967 » » » if (retval) |
| 630 » » » » touch->platform_data->use_polling_mode = true; | 968 » » » » touch->down_to_polling_mode = true; |
| 631 » » » } | |
| 632 } | 969 } |
| 633 | 970 |
| 634 » » DBGPRINTK(("%s: trackpad interrupt bit = 0x%02x \n", __func__, | 971 » » DBGPRINTK(("%s: trackpad interrupt bit = 0x%02x\n", __func__, |
| 635 » » » » (u8)cyapa_i2c_reg_read_byte(client, DEV_POWER_RE G))); | 972 » » » (u8)cyapa_i2c_reg_read_byte(touch, DEV_POWER_REG))); |
| 636 } else { | 973 } else { |
| 637 /* trackpad gen2 firmware. default is interrupt mode. */ | 974 /* trackpad gen2 firmware. default is interrupt mode. */ |
| 638 DBGPRINTK(("%s: trackpad support gen2 firmware.\n", __func__)); | 975 DBGPRINTK(("%s: trackpad support gen2 firmware.\n", __func__)); |
| 639 | 976 |
| 640 cyapa_get_reg_offset(touch); | 977 cyapa_get_reg_offset(touch); |
| 641 cyapa_get_query_data(touch); | 978 cyapa_get_query_data(touch); |
| 979 | |
| 980 printk(KERN_INFO "Cypress Trackpad Information:\n"); | |
|
Olof Johansson
2011/05/02 05:47:12
pr_info(), please.
| |
| 981 printk(KERN_INFO "\t\t\tProduction ID: %s\n", | |
| 982 touch->product_id); | |
| 983 printk(KERN_INFO "\t\t\tFirmware version: %d.%d\n", | |
| 984 touch->fm_maj_ver, touch->fm_min_ver); | |
| 985 printk(KERN_INFO "\t\t\tHardware version: %d.%d\n", | |
| 986 touch->hw_maj_ver, touch->hw_min_ver); | |
| 987 printk(KERN_INFO "\t\t\tDriver Version: %d.%d.%d\n", | |
| 988 CYAPA_MAJOR_VER, CYAPA_MINOR_VER, CYAPA_REVISION_VER); | |
| 989 printk(KERN_INFO "\t\t\tResolution X,Y: %d,%d\n", | |
| 990 touch->max_absolution_x, touch->max_absolution_y); | |
| 991 printk(KERN_INFO "\t\t\tPhysical Size X,Y: %d,%d\n", | |
| 992 touch->physical_size_x, touch->physical_size_y); | |
| 642 } | 993 } |
| 643 | 994 |
| 644 DBGPRINTK(("%s: use %s mode.\n", __func__, | 995 DBGPRINTK(("%s: use %s mode.\n", __func__, |
| 645 » » » ((touch->platform_data->use_polling_mode == true)?"polli ng":"interrupt"))); | 996 » » » ((touch->down_to_polling_mode == true) |
| 997 » » » ? "polling" : "interrupt"))); | |
| 646 return retval; | 998 return retval; |
| 647 } | 999 } |
| 648 | 1000 |
| 649 static int cyapa_i2c_reset_config(struct cyapa_i2c *touch) | 1001 static int cyapa_i2c_reset_config(struct cyapa_i2c *touch) |
| 650 { | 1002 { |
| 651 int ret = 0; | 1003 int ret = 0; |
| 652 | 1004 |
| 653 » DBGPRINTK(("%s: ... \n", __func__)); | 1005 » DBGPRINTK(("%s: ...\n", __func__)); |
| 654 » | 1006 |
| 655 return ret; | 1007 return ret; |
| 656 } | 1008 } |
| 657 | 1009 |
| 658 static int cyapa_verify_data_device(struct cyapa_i2c *touch, | 1010 static int cyapa_verify_data_device(struct cyapa_i2c *touch, |
| 659 union cyapa_reg_data *reg_data) | 1011 union cyapa_reg_data *reg_data) |
| 660 { | 1012 { |
| 661 struct cyapa_reg_data_gen1 *data_gen1 = NULL; | 1013 struct cyapa_reg_data_gen1 *data_gen1 = NULL; |
| 662 struct cyapa_reg_data_gen2 *data_gen2 = NULL; | 1014 struct cyapa_reg_data_gen2 *data_gen2 = NULL; |
| 663 | 1015 |
| 664 if (touch->platform_data->gen == CYAPA_GEN1) { | 1016 if (touch->platform_data->gen == CYAPA_GEN1) { |
| 665 data_gen1 = ®_data->gen1_data; | 1017 data_gen1 = ®_data->gen1_data; |
| 666 if ((data_gen1->tap_motion & 0x08) != 0x08) { | 1018 if ((data_gen1->tap_motion & 0x08) != 0x08) { |
| 667 /* invalid data. */ | 1019 /* invalid data. */ |
| 668 » » » DBGPRINTK(("%s: invalid data reg address 0x00, bit3 is n ot set. \n", __func__)); | 1020 » » » DBGPRINTK(("%s: invalid data reg address 0x00, \ |
| 1021 » » » » bit3 is not set.\n", __func__)); | |
| 669 return -EINVAL; | 1022 return -EINVAL; |
| 670 } | 1023 } |
| 671 } else { | 1024 } else { |
| 672 data_gen2 = ®_data->gen2_data; | 1025 data_gen2 = ®_data->gen2_data; |
| 673 if ((data_gen2->device_status & 0x80) != 0x80) { | 1026 if ((data_gen2->device_status & 0x80) != 0x80) { |
| 674 /* invalid data. */ | 1027 /* invalid data. */ |
| 675 » » » DBGPRINTK(("%s: invalid data reg address 0x00, bit7 is n ot set. \n", __func__)); | 1028 » » » DBGPRINTK(("%s: invalid data reg address 0x00, \ |
| 1029 » » » » bit7 is not set.\n", __func__)); | |
| 676 return -EINVAL; | 1030 return -EINVAL; |
| 677 } | 1031 } |
| 678 | 1032 |
| 679 if ((data_gen2->device_status & 0x03) != CYAPA_DEV_NORNAL) { | 1033 if ((data_gen2->device_status & 0x03) != CYAPA_DEV_NORNAL) { |
| 680 » » » DBGPRINTK(("%s: invalid device status = 0x%02x, wait for device ready. \n", | 1034 » » » DBGPRINTK(("%s: invalid device status = 0x%02x, \ |
| 681 » » » » » __func__, (data_gen2->device_status & 0x 03))); | 1035 » » » » wait for device ready.\n", |
| 1036 » » » » __func__, (data_gen2->device_status & 0x03))); | |
| 682 return -EBUSY; | 1037 return -EBUSY; |
| 683 } | 1038 } |
| 684 } | 1039 } |
| 685 | 1040 |
| 686 return 0; | 1041 return 0; |
| 687 } | 1042 } |
| 688 | 1043 |
| 689 static inline void cyapa_calculate_abs_xy(struct cyapa_i2c *touch, | 1044 static inline void cyapa_report_fingers(struct input_dev *input, int fingers) |
| 690 » » » » » struct cyapa_report_data *report_data) | |
| 691 { | 1045 { |
| 692 » int i; | 1046 » input_report_key(input, BTN_TOOL_FINGER, (fingers == 1)); |
| 693 » int sum_x = 0, sum_y = 0; | 1047 » input_report_key(input, BTN_TOOL_DOUBLETAP, (fingers == 2)); |
| 694 | 1048 » input_report_key(input, BTN_TOOL_TRIPLETAP, (fingers == 3)); |
| 695 » /* invalid input data. */ | 1049 » input_report_key(input, BTN_TOOL_QUADTAP, (fingers > 3)); |
| 696 » if (!touch->xy_touchs_included_bits || !report_data->touch_fingers) { | |
| 697 » » touch->prev_abs_x = -1; | |
| 698 » » touch->prev_abs_y = -1; | |
| 699 » » return; | |
| 700 » } | |
| 701 | |
| 702 » for (i=0; i<CYAPA_MAX_TOUCHS; i++) { | |
| 703 » » if (touch->xy_touchs_included_bits & (0x01 << i)) { | |
| 704 » » » sum_x += report_data->touchs[i].x; | |
| 705 » » » sum_y += report_data->touchs[i].y; | |
| 706 » » } | |
| 707 » } | |
| 708 | |
| 709 » touch->abs_x = sum_x / report_data->touch_fingers; | |
| 710 » touch->abs_y = sum_y / report_data->touch_fingers; | |
| 711 » /* x, y directory of Cypress trackpad is in negative direction of screen . | |
| 712 » ** for some platform it maybe different. */ | |
| 713 » //touch->abs_x = touch->platform_data->max_touchpad_x - touch->abs_x; | |
| 714 » //touch->abs_y = touch->platform_data->max_touchpad_y - touch->abs_y; | |
| 715 | |
| 716 » /* use simple filtr to make cursor move smoother. */ | |
| 717 » if (touch->prev_abs_x != -1) { | |
| 718 » » touch->abs_x = (touch->abs_x * 3 + touch->prev_abs_x) >> 2; | |
| 719 » » touch->abs_y = (touch->abs_y * 3 + touch->prev_abs_y) >> 2; | |
| 720 » } | |
| 721 | |
| 722 » touch->prev_abs_x = touch->abs_x; | |
| 723 » touch->prev_abs_y = touch->abs_y; | |
| 724 } | |
| 725 | |
| 726 static inline int cyapa_sqrt(int delta_x, int delta_y) | |
| 727 { | |
| 728 » int Xk0 = 0; | |
| 729 » int Xk1; | |
| 730 » int multi; | |
| 731 | |
| 732 » multi = Xk1 = delta_x*delta_x + delta_y*delta_y; | |
| 733 | |
| 734 » while( abs(Xk0 - Xk1) > 1) | |
| 735 » { | |
| 736 » » Xk0 = Xk1; | |
| 737 » » Xk1 = (Xk0 + (multi / Xk0) ) / 2; | |
| 738 » } | |
| 739 | |
| 740 » return Xk1; | |
| 741 } | 1050 } |
| 742 | 1051 |
| 743 static void cyapa_parse_gen1_data(struct cyapa_i2c *touch, | 1052 static void cyapa_parse_gen1_data(struct cyapa_i2c *touch, |
| 744 » » » struct cyapa_reg_data_gen1 *reg_data, | 1053 » » struct cyapa_reg_data_gen1 *reg_data, |
| 745 » » » struct cyapa_report_data *report_data) | 1054 » » struct cyapa_report_data *report_data) |
| 746 { | 1055 { |
| 747 int i; | 1056 int i; |
| 748 int gesture_report_index = 0; | 1057 int gesture_report_index = 0; |
| 749 int gesture_fingers = 0; | |
| 750 int gesture_index = 0; | |
| 751 | 1058 |
| 752 /* parse gestures and button data */ | 1059 /* parse gestures and button data */ |
| 753 report_data->button = reg_data->tap_motion & 0x01; | 1060 report_data->button = reg_data->tap_motion & 0x01; |
| 754 | 1061 |
| 755 /* get relative delta X and delta Y. */ | 1062 /* get relative delta X and delta Y. */ |
| 756 report_data->rel_deltaX = reg_data->deltax; | 1063 report_data->rel_deltaX = reg_data->deltax; |
| 757 /* The Y directory of trackpad is the oppsite of Screen. */ | 1064 /* The Y directory of trackpad is the oppsite of Screen. */ |
| 758 report_data->rel_deltaY = -reg_data->deltay; | 1065 report_data->rel_deltaY = -reg_data->deltay; |
| 759 | 1066 |
| 760 if (reg_data->tap_motion & 0x02) { | 1067 if (reg_data->tap_motion & 0x02) { |
| 761 » » report_data->gestures[gesture_report_index++].id = GESTURE_SINGL E_TAP; | 1068 » » report_data->gestures[gesture_report_index++].id |
| 762 » » | 1069 » » » = GESTURE_SINGLE_TAP; |
| 763 » » gesture_fingers = GESTURE_DECODE_FINGERS(GESTURE_SINGLE_TAP); | |
| 764 » » gesture_index = GESTURE_DECODE_INDEX(GESTURE_SINGLE_TAP); | |
| 765 » » touch->cur_active_gestures[gesture_fingers] |= (1UL << gesture_i ndex); | |
| 766 } | 1070 } |
| 767 | 1071 |
| 768 if (reg_data->tap_motion & 0x04) { | 1072 if (reg_data->tap_motion & 0x04) { |
| 769 » » report_data->gestures[gesture_report_index++].id = GESTURE_DOUBL E_TAP; | 1073 » » report_data->gestures[gesture_report_index++].id |
| 770 » » | 1074 » » » = GESTURE_DOUBLE_TAP; |
| 771 » » gesture_fingers = GESTURE_DECODE_FINGERS(GESTURE_DOUBLE_TAP); | |
| 772 » » gesture_index = GESTURE_DECODE_INDEX(GESTURE_DOUBLE_TAP); | |
| 773 » » touch->cur_active_gestures[gesture_fingers] |= (1UL << gesture_i ndex); | |
| 774 } | 1075 } |
| 775 | 1076 |
| 776 report_data->gestures_count = gesture_report_index; | 1077 report_data->gestures_count = gesture_report_index; |
| 777 | 1078 |
| 778 /* pase fingers touch data */ | 1079 /* pase fingers touch data */ |
| 779 » report_data->touch_fingers = ((reg_data->touch_fingers > CYAPA_MAX_TOUCH S) ? | 1080 » report_data->touch_fingers |
| 1081 » » = ((reg_data->touch_fingers > CYAPA_MAX_TOUCHS) ? | |
| 780 (CYAPA_MAX_TOUCHS) : (reg_data->touch_fingers)); | 1082 (CYAPA_MAX_TOUCHS) : (reg_data->touch_fingers)); |
| 781 report_data->avg_pressure = reg_data->avg_pressure; | 1083 report_data->avg_pressure = reg_data->avg_pressure; |
| 782 report_data->touchs[0].x = | 1084 report_data->touchs[0].x = |
| 783 » » » ((reg_data->touch1.rel_xy & 0xF0) << 4) | reg_data->touc h1.rel_x; | 1085 » » ((reg_data->touch1.rel_xy & 0xF0) << 4) |
| 1086 » » » | reg_data->touch1.rel_x; | |
| 784 report_data->touchs[0].y = | 1087 report_data->touchs[0].y = |
| 785 » » » ((reg_data->touch1.rel_xy & 0x0F) << 8) | reg_data->touc h1.rel_y; | 1088 » » ((reg_data->touch1.rel_xy & 0x0F) << 8) |
| 786 » report_data->touchs[0].id = 0; | 1089 » » » | reg_data->touch1.rel_y; |
| 1090 » report_data->touchs[0].pressure = CYAPA_DEFAULT_TOUCH_PRESSURE; | |
| 787 | 1091 |
| 788 » for (i=0; i<(CYAPA_MAX_TOUCHS-1); i++) { | 1092 » for (i = 0; i < (CYAPA_MAX_TOUCHS-1); i++) { |
| 789 report_data->touchs[i+1].x = | 1093 report_data->touchs[i+1].x = |
| 790 » » » » ((reg_data->touchs[i].rel_xy & 0xF0) << 4) | reg _data->touchs[i].rel_x; | 1094 » » » » ((reg_data->touchs[i].rel_xy & 0xF0) << 4) |
| 1095 » » » » | reg_data->touchs[i].rel_x; | |
| 791 report_data->touchs[i+1].y = | 1096 report_data->touchs[i+1].y = |
| 792 » » » » ((reg_data->touchs[i].rel_xy & 0x0F) << 8) | reg _data->touchs[i].rel_y; | 1097 » » » » ((reg_data->touchs[i].rel_xy & 0x0F) << 8) |
| 793 » » report_data->touchs[i+1].id = i+1; | 1098 » » » » | reg_data->touchs[i].rel_y; |
| 1099 » » report_data->touchs[i+1].pressure = | |
| 1100 » » » CYAPA_DEFAULT_TOUCH_PRESSURE; | |
| 794 } | 1101 } |
| 795 | 1102 |
| 796 » #ifdef DBG_CYAPA_READ_BLOCK_DATA | 1103 » /* DEBUG: dump parsed report data */ |
| 797 » cyapa_print_report_data(__func__, report_data); | 1104 » cyapa_dump_report_data(__func__, report_data); |
| 798 » #endif | |
| 799 } | 1105 } |
| 800 | 1106 |
| 801 static void cyapa_parse_gen2_data(struct cyapa_i2c *touch, | 1107 static void cyapa_parse_gen2_data(struct cyapa_i2c *touch, |
| 802 » » » struct cyapa_reg_data_gen2 *reg_data, | 1108 » » struct cyapa_reg_data_gen2 *reg_data, |
| 803 » » » struct cyapa_report_data *report_data) | 1109 » » struct cyapa_report_data *report_data) |
| 804 { | 1110 { |
| 805 int i; | 1111 int i; |
| 806 int gesture_fingers = 0; | |
| 807 int gesture_index = 0; | |
| 808 | 1112 |
| 809 /* bit2-middle button; bit1-right button; bit0-left buttom. */ | 1113 /* bit2-middle button; bit1-right button; bit0-left buttom. */ |
| 810 report_data->button = reg_data->relative_flags & 0x07; | 1114 report_data->button = reg_data->relative_flags & 0x07; |
| 811 | 1115 |
| 812 /* get relative delta X and delta Y. */ | 1116 /* get relative delta X and delta Y. */ |
| 813 report_data->rel_deltaX = reg_data->deltax; | 1117 report_data->rel_deltaX = reg_data->deltax; |
| 814 /* The Y directory of trackpad is the oppsite of Screen. */ | 1118 /* The Y directory of trackpad is the oppsite of Screen. */ |
| 815 report_data->rel_deltaY = -reg_data->deltay; | 1119 report_data->rel_deltaY = -reg_data->deltay; |
| 816 | 1120 |
| 817 /* copy fingers touch data */ | 1121 /* copy fingers touch data */ |
| 818 report_data->avg_pressure = reg_data->avg_pressure; | 1122 report_data->avg_pressure = reg_data->avg_pressure; |
| 819 » report_data->touch_fingers = ((reg_data->touch_fingers > CYAPA_MAX_TOUCH S) ? | 1123 » report_data->touch_fingers |
| 1124 » » = ((reg_data->touch_fingers > CYAPA_MAX_TOUCHS) ? | |
| 820 (CYAPA_MAX_TOUCHS) : (reg_data->touch_fingers)); | 1125 (CYAPA_MAX_TOUCHS) : (reg_data->touch_fingers)); |
| 821 » for (i=0; i<report_data->touch_fingers; i++) { | 1126 » for (i = 0; i < report_data->touch_fingers; i++) { |
| 822 report_data->touchs[i].x = | 1127 report_data->touchs[i].x = |
| 823 » » » » ((reg_data->touchs[i].xy & 0xF0) << 4) | reg_dat a->touchs[i].x; | 1128 » » » ((reg_data->touchs[i].xy & 0xF0) << 4) |
| 1129 » » » » | reg_data->touchs[i].x; | |
| 824 report_data->touchs[i].y = | 1130 report_data->touchs[i].y = |
| 825 » » » » ((reg_data->touchs[i].xy & 0x0F) << 8) | reg_dat a->touchs[i].y; | 1131 » » » ((reg_data->touchs[i].xy & 0x0F) << 8) |
| 826 » » report_data->touchs[i].id = reg_data->touchs[i].id; | 1132 » » » » | reg_data->touchs[i].y; |
| 1133 » » report_data->touchs[i].pressure = reg_data->touchs[i].pressure; | |
| 827 } | 1134 } |
| 828 | 1135 |
| 829 /* parse gestures */ | 1136 /* parse gestures */ |
| 830 report_data->gestures_count = | 1137 report_data->gestures_count = |
| 831 » » » (((reg_data->gesture_count) > CYAPA_ONE_TIME_GESTURES) ? | 1138 » » (((reg_data->gesture_count) > CYAPA_ONE_TIME_GESTURES) ? |
| 832 » » » » CYAPA_ONE_TIME_GESTURES : reg_data->gesture_coun t); | 1139 » » » CYAPA_ONE_TIME_GESTURES : reg_data->gesture_count); |
| 833 » for (i=0; i<report_data->gestures_count; i++) { | 1140 » for (i = 0; i < report_data->gestures_count; i++) { |
| 834 report_data->gestures[i].id = reg_data->gesture[i].id; | 1141 report_data->gestures[i].id = reg_data->gesture[i].id; |
| 835 report_data->gestures[i].param1 = reg_data->gesture[i].param1; | 1142 report_data->gestures[i].param1 = reg_data->gesture[i].param1; |
| 836 report_data->gestures[i].param2 = reg_data->gesture[i].param2; | 1143 report_data->gestures[i].param2 = reg_data->gesture[i].param2; |
| 837 | |
| 838 gesture_fingers = GESTURE_DECODE_FINGERS(report_data->gestures[i ].id); | |
| 839 gesture_index = GESTURE_DECODE_INDEX(report_data->gestures[i].id ); | |
| 840 touch->cur_active_gestures[gesture_fingers] |= (1UL << gesture_i ndex); | |
| 841 } | 1144 } |
| 842 | 1145 |
| 843 » #ifdef DBG_CYAPA_READ_BLOCK_DATA | 1146 » /* DEBUG: dump parsed report data */ |
| 844 » cyapa_print_report_data(__func__, report_data); | 1147 » cyapa_dump_report_data(__func__, report_data); |
| 845 » #endif | |
| 846 } | 1148 } |
| 847 | 1149 |
| 848 static inline void cyapa_report_fingers(struct input_dev *input, int fingers) | 1150 static int cyapa_handle_input_report_data(struct cyapa_i2c *touch, |
| 849 { | 1151 struct cyapa_report_data *report_data) |
| 850 if (fingers) { | |
| 851 input_report_key(input, BTN_TOOL_FINGER, (fingers == 1)); | |
| 852 input_report_key(input, BTN_TOOL_DOUBLETAP, (fingers == 2)); | |
| 853 input_report_key(input, BTN_TOOL_TRIPLETAP, (fingers == 3)); | |
| 854 input_report_key(input, BTN_TOOL_QUADTAP, (fingers > 3)); | |
| 855 } else { | |
| 856 input_report_key(input, BTN_TOOL_FINGER, 0); | |
| 857 input_report_key(input, BTN_TOOL_DOUBLETAP, 0); | |
| 858 input_report_key(input, BTN_TOOL_TRIPLETAP, 0); | |
| 859 input_report_key(input, BTN_TOOL_QUADTAP, 0); | |
| 860 } | |
| 861 } | |
| 862 | |
| 863 static void cyapa_process_prev_gesture_report(struct cyapa_i2c *touch, | |
| 864 struct cyapa_report_data *report_data) | |
| 865 { | |
| 866 int i, j; | |
| 867 unsigned long gesture_diff; | |
| 868 struct input_dev *input = touch->input; | |
| 869 struct input_dev *input_kbd = touch->input_kbd; | |
| 870 | |
| 871 for (i=0; i<MAX_FINGERS; i++) { | |
| 872 /* get all diffenent gestures in prev and cur. */ | |
| 873 gesture_diff = touch->prev_active_gestures[i] ^ touch->cur_activ e_gestures[i]; | |
| 874 /* get all prev gestures that has been canceled in cur. */ | |
| 875 gesture_diff = gesture_diff & touch->prev_active_gestures[i]; | |
| 876 if (gesture_diff) { | |
| 877 for (j=0; j<(sizeof(unsigned long)*8); j++) { | |
| 878 /* cancel previous exists gesture. */ | |
| 879 if ((gesture_diff >> j) && 1UL) { | |
| 880 switch (GESTURE_ID_CODE(i, j)) { | |
| 881 case GESTURE_PALM_REJECTIOIN: | |
| 882 break; | |
| 883 case GESTURE_SINGLE_TAP : | |
| 884 break; | |
| 885 case GESTURE_DOUBLE_TAP: | |
| 886 break; | |
| 887 case GESTURE_TAP_AND_HOLD: | |
| 888 break; | |
| 889 case GESTURE_EDGE_MOTION: | |
| 890 break; | |
| 891 case GESTURE_DRAG: | |
| 892 touch->prev_abs_x = -1; | |
| 893 touch->prev_abs_y = -1; | |
| 894 | |
| 895 if (touch->platform_data->use_ab solute_mode) { | |
| 896 input_report_key(input, BTN_TOUCH, 0); | |
| 897 input_report_abs(input, ABS_PRESSURE, 0); | |
| 898 cyapa_report_fingers(inp ut, 0); | |
| 899 input_report_key(input, BTN_LEFT, 0); | |
| 900 input_sync(input); | |
| 901 } | |
| 902 break; | |
| 903 case GESTURE_2F_ZOOM_IN: | |
| 904 touch->zoomin_delta = 0; | |
| 905 break; | |
| 906 case GESTURE_2F_ZOOM_OUT: | |
| 907 touch->zoomout_delta = 0; | |
| 908 break; | |
| 909 case GESTURE_SCROLL_UP: | |
| 910 case GESTURE_2F_SCROLL_UP: | |
| 911 touch->delta_scroll_up = 0; | |
| 912 break; | |
| 913 case GESTURE_SCROLL_DOWN: | |
| 914 case GESTURE_2F_SCROLL_DOWN: | |
| 915 touch->delta_scroll_down = 0; | |
| 916 break; | |
| 917 case GESTURE_SCROLL_LEFT: | |
| 918 case GESTURE_2F_SCROLL_LEFT: | |
| 919 input_report_key(input_kbd, KEY_ LEFTSHIFT, 0); | |
| 920 input_sync(input_kbd); | |
| 921 touch->hscroll_left = 0; | |
| 922 touch->delta_scroll_left = 0; | |
| 923 break; | |
| 924 case GESTURE_SCROLL_RIGHT: | |
| 925 case GESTURE_2F_SCROLL_RIGHT: | |
| 926 input_report_key(input_kbd, KEY_ LEFTSHIFT, 0); | |
| 927 input_sync(input_kbd); | |
| 928 touch->hscroll_right = 0; | |
| 929 touch->delta_scroll_right = 0; | |
| 930 break; | |
| 931 case GESTURE_2F_ROTATE: | |
| 932 break; | |
| 933 case GESTURE_2F_PINCH: | |
| 934 break; | |
| 935 case GESTURE_2F_TAP: | |
| 936 break; | |
| 937 case GESTURE_2F_DRAG: | |
| 938 if (touch->platform_data->use_ab solute_mode) { | |
| 939 input_report_key(input, BTN_TOUCH, 0); | |
| 940 input_report_abs(input, ABS_PRESSURE, 0); | |
| 941 input_report_key(input, BTN_LEFT, 0); | |
| 942 cyapa_report_fingers(inp ut, 0); | |
| 943 input_sync(input); | |
| 944 } | |
| 945 | |
| 946 touch->gesture_2F_drag_started = 0; | |
| 947 touch->prev_abs_x = -1; | |
| 948 touch->prev_abs_y = -1; | |
| 949 break; | |
| 950 case GESTURE_FLICK: | |
| 951 case GESTURE_2F_FLICK: | |
| 952 case GESTURE_3F_FLICK: | |
| 953 case GESTURE_4F_FLICK: | |
| 954 case GESTURE_5F_FLICK: | |
| 955 break; | |
| 956 default: | |
| 957 break; | |
| 958 } | |
| 959 } | |
| 960 } | |
| 961 } | |
| 962 } | |
| 963 } | |
| 964 | |
| 965 static void cyapa_gesture_report(struct cyapa_i2c *touch, | |
| 966 struct cyapa_report_data *report_data, | |
| 967 struct cyapa_gesture *gesture) | |
| 968 { | |
| 969 struct input_dev *input = touch->input; | |
| 970 struct input_dev *input_wheel = touch->input_wheel; | |
| 971 struct input_dev *input_kbd = touch->input_kbd; | |
| 972 int delta = 0; | |
| 973 struct cyapa_preferences *preferences = &touch->preferences; | |
| 974 int threshold = 0; | |
| 975 int value = 0; | |
| 976 | |
| 977 switch (gesture->id) { | |
| 978 case GESTURE_PALM_REJECTIOIN: | |
| 979 /* when palm rejection gesture is trigged, do not move c ursor any more, | |
| 980 ** just operation as no finger touched on trackpad. | |
| 981 */ | |
| 982 if (touch->platform_data->use_absolute_mode) { | |
| 983 input_report_key(input, BTN_TOUCH, 0); | |
| 984 input_report_abs(input, ABS_PRESSURE, 0); | |
| 985 input_report_abs(input, ABS_TOOL_WIDTH, 0); | |
| 986 cyapa_report_fingers(input, 0); | |
| 987 } | |
| 988 | |
| 989 touch->prev_abs_x = -1; | |
| 990 touch->prev_abs_y = -1; | |
| 991 | |
| 992 input_report_key(input, BTN_LEFT, report_data->button & 0x01); | |
| 993 input_report_key(input, BTN_RIGHT, report_data->button & 0x02); | |
| 994 input_report_key(input, BTN_MIDDLE, report_data->button & 0x04); | |
| 995 | |
| 996 input_sync(input); | |
| 997 | |
| 998 DBGPRINTK(("%s: report palm rejection\n", __func__)); | |
| 999 break; | |
| 1000 case GESTURE_SINGLE_TAP : | |
| 1001 if (touch->platform_data->use_absolute_mode) { | |
| 1002 input_report_key(input, BTN_TOUCH, 0); | |
| 1003 input_report_abs(input, ABS_PRESSURE, 0); | |
| 1004 input_report_key(input, BTN_LEFT, 0); | |
| 1005 input_sync(input); | |
| 1006 | |
| 1007 /* in absolute mode use BTN_FINGER to trigger click. */ | |
| 1008 break; | |
| 1009 } | |
| 1010 | |
| 1011 input_report_key(input, BTN_LEFT, 1); | |
| 1012 input_sync(input); | |
| 1013 | |
| 1014 input_report_key(input, BTN_LEFT, 0); | |
| 1015 input_sync(input); | |
| 1016 | |
| 1017 DBGPRINTK(("%s: report single tap\n", __func__)); | |
| 1018 break; | |
| 1019 case GESTURE_DOUBLE_TAP: | |
| 1020 if (touch->platform_data->use_absolute_mode) { | |
| 1021 input_report_key(input, BTN_TOUCH, 0); | |
| 1022 input_report_abs(input, ABS_PRESSURE, 0); | |
| 1023 input_report_key(input, BTN_LEFT, 0); | |
| 1024 input_report_key(input, BTN_RIGHT, 0); | |
| 1025 input_sync(input); | |
| 1026 } | |
| 1027 | |
| 1028 input_report_key(input, BTN_LEFT, 1); | |
| 1029 input_sync(input); | |
| 1030 | |
| 1031 input_report_key(input, BTN_LEFT, 0); | |
| 1032 input_sync(input); | |
| 1033 | |
| 1034 input_report_key(input, BTN_LEFT, 1); | |
| 1035 input_sync(input); | |
| 1036 | |
| 1037 input_report_key(input, BTN_LEFT, 0); | |
| 1038 input_sync(input); | |
| 1039 | |
| 1040 DBGPRINTK(("%s: report double tap\n", __func__)); | |
| 1041 break; | |
| 1042 case GESTURE_TAP_AND_HOLD: | |
| 1043 /* one finger click and hold for more than definitioin t ime, then to do something. */ | |
| 1044 DBGPRINTK(("%s: no gesture for Tap and hold yet.\n", __f unc__)); | |
| 1045 break; | |
| 1046 case GESTURE_EDGE_MOTION: | |
| 1047 DBGPRINTK(("%s: no gesture for edge motion yet.\n", __fu nc__)); | |
| 1048 break; | |
| 1049 case GESTURE_DRAG: | |
| 1050 /* 1-finger drag. 1-finger double click and hold, then m ove the finger. */ | |
| 1051 if (touch->platform_data->use_absolute_mode) { | |
| 1052 touch->xy_touchs_included_bits = 0x01; | |
| 1053 cyapa_calculate_abs_xy(touch, report_data); | |
| 1054 | |
| 1055 input_report_key(input, BTN_TOUCH, 1); | |
| 1056 input_report_abs(input, ABS_X, touch->abs_x); | |
| 1057 input_report_abs(input, ABS_Y, touch->abs_y); | |
| 1058 input_report_abs(input, ABS_PRESSURE, report_dat a->avg_pressure); | |
| 1059 cyapa_report_fingers(input, 1); | |
| 1060 input_report_key(input, BTN_LEFT, 1); | |
| 1061 input_sync(input); | |
| 1062 } else { | |
| 1063 input_report_rel(input, REL_X, report_data->rel_ deltaX); | |
| 1064 input_report_rel(input, REL_Y, report_data->rel_ deltaY); | |
| 1065 input_report_key(input, BTN_LEFT, 1); | |
| 1066 input_sync(input); | |
| 1067 } | |
| 1068 | |
| 1069 DBGPRINTK(("%s: 1 finger drag. \n", __func__)); | |
| 1070 break; | |
| 1071 case GESTURE_2F_ZOOM_IN: | |
| 1072 delta = gesture->param2; | |
| 1073 touch->zoomin_delta += delta; | |
| 1074 while (touch->zoomin_delta > 0) { | |
| 1075 input_report_key(input_kbd, KEY_LEFTCTRL, 1); | |
| 1076 input_report_key(input_kbd, KEY_KPPLUS, 1); | |
| 1077 input_sync(input_kbd); | |
| 1078 | |
| 1079 input_report_key(input_kbd, KEY_LEFTCTRL, 0); | |
| 1080 input_report_key(input_kbd, KEY_KPPLUS, 0); | |
| 1081 input_sync(input_kbd); | |
| 1082 | |
| 1083 touch->zoomin_delta -= 1; | |
| 1084 } | |
| 1085 | |
| 1086 DBGPRINTK(("%s: 2F zoom in \n", __func__)); | |
| 1087 break; | |
| 1088 case GESTURE_2F_ZOOM_OUT: | |
| 1089 delta = gesture->param2; | |
| 1090 touch->zoomout_delta += delta; | |
| 1091 while (touch->zoomout_delta > 0) { | |
| 1092 input_report_key(input_kbd, KEY_LEFTCTRL, 1); | |
| 1093 input_report_key(input_kbd, KEY_KPMINUS, 1); | |
| 1094 input_sync(input_kbd); | |
| 1095 | |
| 1096 input_report_key(input_kbd, KEY_LEFTCTRL, 0); | |
| 1097 input_report_key(input_kbd, KEY_KPMINUS, 0); | |
| 1098 input_sync(input_kbd); | |
| 1099 | |
| 1100 touch->zoomout_delta -= 1; | |
| 1101 } | |
| 1102 | |
| 1103 DBGPRINTK(("%s: 2F zoom out \n", __func__)); | |
| 1104 break; | |
| 1105 case GESTURE_SCROLL_UP: | |
| 1106 case GESTURE_2F_SCROLL_UP: | |
| 1107 delta = gesture->param2; | |
| 1108 | |
| 1109 threshold = preferences->vscroll.default_threshold; | |
| 1110 value = 1; | |
| 1111 touch->delta_scroll_up += delta; | |
| 1112 | |
| 1113 if (touch->delta_scroll_up < threshold) { | |
| 1114 /* keep small movement also can work. */ | |
| 1115 input_report_rel(input_wheel, REL_WHEEL, value); | |
| 1116 input_sync(input_wheel); | |
| 1117 | |
| 1118 touch->delta_scroll_up = 0; | |
| 1119 break; | |
| 1120 } | |
| 1121 | |
| 1122 if (touch->delta_scroll_up > preferences->vscroll.fast_t hreshold) { | |
| 1123 /* fast scroll, reset threshold value. */ | |
| 1124 threshold = 1; | |
| 1125 value = 16; | |
| 1126 } else { | |
| 1127 /* middle scroll speed. */ | |
| 1128 threshold = 2; | |
| 1129 value = 2; | |
| 1130 } | |
| 1131 | |
| 1132 while (touch->delta_scroll_up >= threshold) { | |
| 1133 input_report_rel(input_wheel, REL_WHEEL, value*2 /threshold); | |
| 1134 input_sync(input_wheel); | |
| 1135 | |
| 1136 touch->delta_scroll_up -= threshold*value; | |
| 1137 } | |
| 1138 | |
| 1139 DBGPRINTK(("%s: scroll up, fingers=%d\n", | |
| 1140 __func__, report_data->touch_fin gers)); | |
| 1141 break; | |
| 1142 case GESTURE_SCROLL_DOWN: | |
| 1143 case GESTURE_2F_SCROLL_DOWN: | |
| 1144 delta = gesture->param2; | |
| 1145 threshold = preferences->vscroll.default_threshold; | |
| 1146 value = 1; | |
| 1147 touch->delta_scroll_down += delta; | |
| 1148 | |
| 1149 if (touch->delta_scroll_down < threshold) { | |
| 1150 /* keep small movement also can work. */ | |
| 1151 input_report_rel(input_wheel, REL_WHEEL, -value) ; | |
| 1152 input_sync(input_wheel); | |
| 1153 | |
| 1154 touch->delta_scroll_down = 0; | |
| 1155 break; | |
| 1156 } | |
| 1157 | |
| 1158 if (touch->delta_scroll_down > preferences->hscroll.fast _threshold) { | |
| 1159 /* fast scroll, reset threshold value. */ | |
| 1160 threshold = 1; | |
| 1161 value = 16; | |
| 1162 } else { | |
| 1163 /* middle scroll speed. */ | |
| 1164 threshold = 2; | |
| 1165 value = 2; | |
| 1166 } | |
| 1167 | |
| 1168 while (touch->delta_scroll_down >= threshold) { | |
| 1169 input_report_rel(input_wheel, REL_WHEEL, -value* 2/threshold); | |
| 1170 input_sync(input_wheel); | |
| 1171 | |
| 1172 touch->delta_scroll_down -= threshold*value; | |
| 1173 } | |
| 1174 | |
| 1175 DBGPRINTK(("%s: scroll down, finger=%d\n", | |
| 1176 __func__, report_data->touch_fin gers)); | |
| 1177 break; | |
| 1178 case GESTURE_SCROLL_LEFT: | |
| 1179 case GESTURE_2F_SCROLL_LEFT: | |
| 1180 delta = gesture->param2; | |
| 1181 #if 1 | |
| 1182 while (delta > 0) { | |
| 1183 input_report_key(input_kbd, KEY_LEFT, 1); | |
| 1184 input_sync(input_kbd); | |
| 1185 | |
| 1186 input_report_key(input_kbd, KEY_LEFT, 0); | |
| 1187 input_sync(input_kbd); | |
| 1188 | |
| 1189 delta -= 4; | |
| 1190 } | |
| 1191 #else | |
| 1192 if (0 == touch->hscroll_left) { | |
| 1193 /* Don't why, when report kbd and mouse/wheel ev ent | |
| 1194 ** in the same routine, kbd event will be delaye d to take effect. | |
| 1195 ** that is when kbd and wheel events are reporte d at same time, | |
| 1196 ** wheel event will take effect immediatelly, bu t kdb event will be | |
| 1197 ** delayed some time to take effect, so the comb ination of kbd and | |
| 1198 ** wheel won't take effect any more here when kb d is delayed. | |
| 1199 ** horizontal scroll won't take effect for some time. | |
| 1200 ** So, we delay some time to report wheel event also, here. | |
| 1201 ** but it still not accurate enouch, so horizont al scroll will also miss, | |
| 1202 ** and become a vertical scroll. | |
| 1203 */ | |
| 1204 input_report_key(input_kbd, KEY_LEFTSHIFT, 1); | |
| 1205 input_sync(input_kbd); | |
| 1206 touch->hscroll_left = delta; | |
| 1207 } else { | |
| 1208 while (delta > 0) { | |
| 1209 input_report_rel(input_wheel, REL_WHEEL, 1); | |
| 1210 input_sync(input_wheel); | |
| 1211 | |
| 1212 delta -= 1; | |
| 1213 } | |
| 1214 } | |
| 1215 #endif | |
| 1216 DBGPRINTK(("%s: scroll left, finger=%d\n", | |
| 1217 __func__, report_data->touch_fin gers)); | |
| 1218 break; | |
| 1219 case GESTURE_SCROLL_RIGHT: | |
| 1220 case GESTURE_2F_SCROLL_RIGHT: | |
| 1221 delta = gesture->param2; | |
| 1222 #if 1 | |
| 1223 while (delta > 0) { | |
| 1224 input_report_key(input_kbd, KEY_RIGHT, 1); | |
| 1225 input_sync(input_kbd); | |
| 1226 | |
| 1227 input_report_key(input_kbd, KEY_RIGHT, 0); | |
| 1228 input_sync(input_kbd); | |
| 1229 | |
| 1230 delta -= 4; | |
| 1231 } | |
| 1232 #else | |
| 1233 if (0 == touch->hscroll_right) { | |
| 1234 /* Don't why, when report kbd and mouse/wheel ev ent | |
| 1235 ** in the same routine, kbd event will be delaye d to take effect. | |
| 1236 ** that is when kbd and wheel events are reporte d at same time, | |
| 1237 ** wheel event will take effect immediatelly, bu t kdb event will be | |
| 1238 ** delayed some time to take effect, so the comb ination of kbd and | |
| 1239 ** wheel won't take effect any more here when kb d is delayed. | |
| 1240 ** horizontal scroll won't take effect for some time. | |
| 1241 ** So, we delay some time to report wheel event also, here. | |
| 1242 ** but it still not accurate enouch, so horizont al scroll will also miss, | |
| 1243 ** and become a vertical scroll. | |
| 1244 */ | |
| 1245 input_report_key(input_kbd, KEY_LEFTSHIFT, 1); | |
| 1246 input_sync(input_kbd); | |
| 1247 touch->hscroll_right = delta; | |
| 1248 } else { | |
| 1249 while (delta > 0) { | |
| 1250 input_report_rel(input_wheel, REL_WHEEL, -1); | |
| 1251 input_sync(input_wheel); | |
| 1252 | |
| 1253 delta -= 1; | |
| 1254 } | |
| 1255 } | |
| 1256 #endif | |
| 1257 DBGPRINTK(("%s: scroll right, finger=%d\n", | |
| 1258 __func__, report_data->touch_fin gers)); | |
| 1259 break; | |
| 1260 case GESTURE_2F_ROTATE: | |
| 1261 DBGPRINTK(("%s: 2 finger rotate \n", __func__)); | |
| 1262 break; | |
| 1263 case GESTURE_2F_PINCH: | |
| 1264 DBGPRINTK(("%s: 2 finger pinch\n", __func__)); | |
| 1265 break; | |
| 1266 case GESTURE_2F_TAP: | |
| 1267 /* 2-finger tap, active like right button press and rela se. */ | |
| 1268 if (touch->platform_data->use_absolute_mode) { | |
| 1269 input_report_key(input, BTN_TOUCH, 0); | |
| 1270 input_report_abs(input, ABS_PRESSURE, 0); | |
| 1271 input_report_key(input, BTN_LEFT, 0); | |
| 1272 input_report_key(input, BTN_RIGHT, 0); | |
| 1273 input_sync(input); | |
| 1274 } | |
| 1275 | |
| 1276 input_report_key(input, BTN_RIGHT, 1); | |
| 1277 input_sync(input); | |
| 1278 | |
| 1279 input_report_key(input, BTN_RIGHT, 0); | |
| 1280 input_sync(input); | |
| 1281 | |
| 1282 DBGPRINTK(("%s: report 2 fingers tap, active like right button.\n", __func__)); | |
| 1283 break; | |
| 1284 case GESTURE_2F_DRAG: | |
| 1285 /* first finger click and hold, and second finger moving for dragging. */ | |
| 1286 if (touch->gesture_2F_drag_started == 0) { | |
| 1287 touch->xy_touchs_included_bits = 0x01; | |
| 1288 touch->prev_abs_x = -1; | |
| 1289 touch->prev_abs_y = -1; | |
| 1290 cyapa_calculate_abs_xy(touch, report_data); | |
| 1291 | |
| 1292 /* firstly, move move cursor to the target for d rag. */ | |
| 1293 input_report_key(input, BTN_TOUCH, 1); | |
| 1294 if (touch->platform_data->use_absolute_mode) { | |
| 1295 input_report_abs(input, ABS_X, touch->ab s_x); | |
| 1296 input_report_abs(input, ABS_Y, touch->ab s_y); | |
| 1297 input_report_abs(input, ABS_PRESSURE, re port_data->avg_pressure); | |
| 1298 cyapa_report_fingers(input, 1); | |
| 1299 } | |
| 1300 input_report_key(input, BTN_LEFT, 0); | |
| 1301 input_report_key(input, BTN_RIGHT, 0); | |
| 1302 input_sync(input); | |
| 1303 | |
| 1304 /* second, stop cursor on the target for drag. * / | |
| 1305 touch->prev_abs_x = -1; | |
| 1306 touch->prev_abs_y = -1; | |
| 1307 if (touch->platform_data->use_absolute_mode) { | |
| 1308 input_report_key(input, BTN_TOUCH, 0); | |
| 1309 input_report_abs(input, ABS_PRESSURE, 0) ; | |
| 1310 input_sync(input); | |
| 1311 } | |
| 1312 | |
| 1313 /* third, select the target for drag. */ | |
| 1314 input_report_key(input, BTN_LEFT, 1); | |
| 1315 input_sync(input); | |
| 1316 | |
| 1317 /* go to step four. */ | |
| 1318 touch->gesture_2F_drag_started = 1; | |
| 1319 } | |
| 1320 | |
| 1321 /* fourth, move cursor for dragging. */ | |
| 1322 touch->xy_touchs_included_bits = 0x02; | |
| 1323 cyapa_calculate_abs_xy(touch, report_data); | |
| 1324 | |
| 1325 if (touch->platform_data->use_absolute_mode) { | |
| 1326 input_report_key(input, BTN_TOUCH, 1); | |
| 1327 input_report_abs(input, ABS_X, touch->abs_x); | |
| 1328 input_report_abs(input, ABS_Y, touch->abs_y); | |
| 1329 input_report_abs(input, ABS_PRESSURE, report_dat a->avg_pressure); | |
| 1330 cyapa_report_fingers(input, 1); | |
| 1331 } else { | |
| 1332 input_report_rel(input, REL_X, report_data->rel_ deltaX); | |
| 1333 input_report_rel(input, REL_Y, report_data->rel_ deltaY); | |
| 1334 input_sync(input); | |
| 1335 } | |
| 1336 input_report_key(input, BTN_LEFT, 1); | |
| 1337 input_sync(input); | |
| 1338 | |
| 1339 DBGPRINTK(("%s: report 2 fingers drag\n", __func__)); | |
| 1340 break; | |
| 1341 case GESTURE_FLICK: | |
| 1342 case GESTURE_2F_FLICK: | |
| 1343 case GESTURE_3F_FLICK: | |
| 1344 case GESTURE_4F_FLICK: | |
| 1345 case GESTURE_5F_FLICK: | |
| 1346 touch->xy_touchs_included_bits = report_data->touch_fing ers; | |
| 1347 DBGPRINTK(("%s: no flick gesture supported yet, , finger =%d\n", | |
| 1348 __func__, report_data->touch_fin gers)); | |
| 1349 break; | |
| 1350 default: | |
| 1351 DBGPRINTK(("%s: default, unknown gesture for reporting.\ n", __func__)); | |
| 1352 break; | |
| 1353 } | |
| 1354 } | |
| 1355 | |
| 1356 static int cyapa_rel_input_report_data(struct cyapa_i2c *touch, struct cyapa_rep ort_data *report_data) | |
| 1357 { | 1152 { |
| 1358 int i; | 1153 int i; |
| 1359 struct input_dev *input = touch->input; | 1154 struct input_dev *input = touch->input; |
| 1360 | 1155 |
| 1361 » /* step 1: process gestures firstly if trigged. */ | 1156 » /* report raw trackpad data. */ |
| 1362 » cyapa_process_prev_gesture_report(touch, report_data); | 1157 » for (i = 0; i < report_data->touch_fingers; i++) { |
| 1363 » if (report_data->gestures_count > 0) { | 1158 » » input_report_abs(input, ABS_MT_POSITION_X, |
| 1364 » » DBGPRINTK(("%s: do gesture report, gestures_count = %d\n", | 1159 » » » report_data->touchs[i].x); |
| 1365 » » » » __func__, report_data->gestures_count)); | 1160 » » input_report_abs(input, ABS_MT_POSITION_Y, |
| 1366 » » /* gesture trigged */ | 1161 » » » report_data->touchs[i].y); |
| 1367 » » for (i=0; i<report_data->gestures_count; i++) { | 1162 » » input_report_abs(input, ABS_MT_TOUCH_MAJOR, |
| 1368 » » » cyapa_gesture_report(touch, report_data, &report_data->g estures[i]); | 1163 » » » report_data->touchs[i].pressure > 0 ? |
| 1369 » » } | 1164 » » » » CYAPA_MT_TOUCH_MAJOR : 0); |
| 1370 | 1165 » » input_report_abs(input, ABS_MT_PRESSURE, |
| 1371 » » /* when gestures are trigged, cursor should be fixed. */ | 1166 » » » report_data->touchs[i].pressure); |
| 1372 » » return report_data->gestures_count; | 1167 » » input_mt_sync(input); |
| 1373 } | 1168 } |
| 1374 | 1169 |
| 1375 » /* when multi-fingers touched, cursour should also be fixed. */ | 1170 » /* |
| 1376 » if (report_data->touch_fingers == 1) { | 1171 » * report mouse device data. |
| 1377 » » /* Report the deltas */ | 1172 » * always track the first finger. |
| 1378 » » input_report_rel(input, REL_X, report_data->rel_deltaX); | 1173 » * when detached, start over |
| 1379 » » input_report_rel(input, REL_Y, report_data->rel_deltaY); | 1174 » */ |
| 1380 » } | 1175 » input_report_key(input, BTN_TOUCH, (report_data->touch_fingers > 0)); |
| 1176 » cyapa_report_fingers(input, report_data->touch_fingers); | |
| 1381 | 1177 |
| 1382 » /* Report the button event */ | 1178 » input_report_abs(input, ABS_TOOL_WIDTH, 15); |
| 1383 » input_report_key(input, BTN_LEFT, (report_data->button & 0x01)); | 1179 » input_report_abs(input, ABS_X, report_data->touchs[0].x); |
| 1384 » input_report_key(input, BTN_RIGHT, (report_data->button & 0x02)); | 1180 » input_report_abs(input, ABS_Y, report_data->touchs[0].y); |
| 1385 » input_report_key(input, BTN_MIDDLE, (report_data->button & 0x04)); | 1181 » input_report_abs(input, ABS_PRESSURE, report_data->touchs[0].pressure); |
| 1182 | |
| 1183 » input_report_key(input, BTN_LEFT, report_data->button & 0x01); | |
| 1184 | |
| 1386 input_sync(input); | 1185 input_sync(input); |
| 1387 | 1186 |
| 1388 » DBGPRINTK(("%s: deltax = %d \n", __func__, report_data->rel_deltaX)); | 1187 » return report_data->touch_fingers | (report_data->button & 0x01); |
| 1389 » DBGPRINTK(("%s: deltay = %d \n", __func__, report_data->rel_deltaY)); | |
| 1390 » DBGPRINTK(("%s: left_btn = %d \n", __func__, report_data->button & 0x01) ); | |
| 1391 » DBGPRINTK(("%s: right_btn = %d \n", __func__, report_data->button & 0x02 )); | |
| 1392 » DBGPRINTK(("%s: middle_btn = %d \n", __func__, report_data->button & 0x0 4)); | |
| 1393 » | |
| 1394 » return report_data->rel_deltaX |report_data->rel_deltaY | report_data->b utton; | |
| 1395 } | |
| 1396 | |
| 1397 static int cyapa_abs_input_report_data(struct cyapa_i2c *touch, struct cyapa_rep ort_data *report_data) | |
| 1398 { | |
| 1399 » int i; | |
| 1400 » int have_data = 0; | |
| 1401 » struct input_dev *input = touch->input; | |
| 1402 | |
| 1403 » DBGPRINTK(("%s: ... \n", __func__)); | |
| 1404 | |
| 1405 » cyapa_process_prev_gesture_report(touch, report_data); | |
| 1406 » if (report_data->gestures_count > 0) { | |
| 1407 » » DBGPRINTK(("%s: do gesture report, gestures_count = %d\n", | |
| 1408 » » » __func__, report_data->gestures_count)); | |
| 1409 » » /* gesture trigged */ | |
| 1410 » » for (i=0; i<report_data->gestures_count; i++) { | |
| 1411 » » » cyapa_gesture_report(touch, report_data, &report_data->g estures[i]); | |
| 1412 » » } | |
| 1413 » } else if (report_data->touch_fingers) { | |
| 1414 » » /* no gesture trigged, report touchs move data. */ | |
| 1415 » » if (report_data->touch_fingers > 1) { | |
| 1416 » » » DBGPRINTK(("%s: more then 1 finger touch, touch_fingers = %d\n", | |
| 1417 » » » » __func__, report_data->touch_fingers)); | |
| 1418 » » » /* | |
| 1419 » » » ** two and much more finger on trackpad are used for ges ture only, | |
| 1420 » » » ** so even no gesture are trigged, do not make cursor mo ve also. | |
| 1421 » » » ** Here, must keep on report finger touched, otherwise, when multi-finger | |
| 1422 » » » ** touch not in same time will triiged clikc. | |
| 1423 » » » */ | |
| 1424 » » » input_report_key(input, BTN_TOUCH, 1); | |
| 1425 » » » input_report_abs(input, ABS_PRESSURE, report_data->avg_p ressure); | |
| 1426 » » » input_report_abs(input, ABS_TOOL_WIDTH, CYAPA_TOOL_WIDTH ); | |
| 1427 » » » #if GESTURE_MULTI_TOUCH_ONE_CLICK | |
| 1428 » » » cyapa_report_fingers(input, report_data->touch_fingers); | |
| 1429 » » » #else | |
| 1430 » » » cyapa_report_fingers(input, 1); | |
| 1431 » » » #endif | |
| 1432 » » » | |
| 1433 » » » touch->prev_abs_x = -1; | |
| 1434 » » » touch->prev_abs_y = -1; | |
| 1435 | |
| 1436 » » » input_report_key(input, BTN_LEFT, report_data->button & 0x01); | |
| 1437 » » » input_report_key(input, BTN_RIGHT, report_data->button & 0x02); | |
| 1438 » » » input_report_key(input, BTN_MIDDLE, report_data->button & 0x04); | |
| 1439 | |
| 1440 » » » input_sync(input); | |
| 1441 » » } else { | |
| 1442 » » » DBGPRINTK(("%s: 1 finger touch, make cursor move\n", __f unc__)); | |
| 1443 » » » /* avoid cursor jump, when touched finger changed from m ulti-touch | |
| 1444 » » » ** to one finger touch. */ | |
| 1445 » » » if (touch->prev_touch_fingers > 1) { | |
| 1446 » » » » /* cheat system or application that no finger ha s touched to may | |
| 1447 » » » » ** them lock the cursor when later only one fing er touched on trackpad. */ | |
| 1448 » » » » input_report_key(input, BTN_TOUCH, 0); | |
| 1449 » » » » input_report_abs(input, ABS_PRESSURE, 0); | |
| 1450 » » » » input_report_abs(input, ABS_TOOL_WIDTH, 0); | |
| 1451 » » » » cyapa_report_fingers(input, 0); | |
| 1452 » » » » touch->prev_abs_x = -1; | |
| 1453 » » » » touch->prev_abs_y = -1; | |
| 1454 » » » » input_report_key(input, BTN_LEFT, report_data->b utton & 0x01); | |
| 1455 » » » » input_report_key(input, BTN_RIGHT, report_data-> button & 0x02); | |
| 1456 » » » » input_report_key(input, BTN_MIDDLE, report_data- >button & 0x04); | |
| 1457 » » » » input_sync(input); | |
| 1458 » » » } else { | |
| 1459 » » » » /* only 1 finger can make cursor move. */ | |
| 1460 » » » » touch->xy_touchs_included_bits = 0x01; | |
| 1461 » » » » cyapa_calculate_abs_xy(touch, report_data); | |
| 1462 | |
| 1463 » » » » input_report_key(input, BTN_TOUCH, 1); | |
| 1464 » » » » input_report_abs(input, ABS_X, touch->abs_x); | |
| 1465 » » » » input_report_abs(input, ABS_Y, touch->abs_y); | |
| 1466 » » » » input_report_abs(input, ABS_PRESSURE, report_dat a->avg_pressure); | |
| 1467 » » » » input_report_abs(input, ABS_TOOL_WIDTH, CYAPA_TO OL_WIDTH); | |
| 1468 | |
| 1469 » » » » cyapa_report_fingers(input, report_data->touch_f ingers); | |
| 1470 | |
| 1471 » » » » input_report_key(input, BTN_LEFT, report_data->b utton & 0x01); | |
| 1472 » » » » input_report_key(input, BTN_RIGHT, report_data-> button & 0x02); | |
| 1473 » » » » input_report_key(input, BTN_MIDDLE, report_data- >button & 0x04); | |
| 1474 | |
| 1475 » » » » input_sync(input); | |
| 1476 » » » } | |
| 1477 » » } | |
| 1478 » } else { | |
| 1479 » » /* | |
| 1480 » » ** 1. two or more fingers on trackpad are used for gesture only, | |
| 1481 » » ** so even no gesture are trigged, do not make cursor move a lso. | |
| 1482 » » ** 2. no gesture and no touch on trackpad. | |
| 1483 » » */ | |
| 1484 » » DBGPRINTK(("%s: no finger touch.\n", __func__)); | |
| 1485 | |
| 1486 » » input_report_key(input, BTN_TOUCH, 0); | |
| 1487 » » input_report_abs(input, ABS_PRESSURE, 0); | |
| 1488 » » input_report_abs(input, ABS_TOOL_WIDTH, 0); | |
| 1489 » » cyapa_report_fingers(input, 0); | |
| 1490 | |
| 1491 » » touch->prev_abs_x = -1; | |
| 1492 » » touch->prev_abs_y = -1; | |
| 1493 | |
| 1494 » » input_report_key(input, BTN_LEFT, report_data->button & 0x01); | |
| 1495 » » input_report_key(input, BTN_RIGHT, report_data->button & 0x02); | |
| 1496 » » input_report_key(input, BTN_MIDDLE, report_data->button & 0x04); | |
| 1497 | |
| 1498 » » input_sync(input); | |
| 1499 » } | |
| 1500 | |
| 1501 » /* store current active gestures array into prev active gesture array. * / | |
| 1502 » for (i=0; i<MAX_FINGERS; i++) { | |
| 1503 » » touch->prev_active_gestures[i] = touch->cur_active_gestures[i]; | |
| 1504 » } | |
| 1505 » touch->prev_touch_fingers = report_data->touch_fingers; | |
| 1506 | |
| 1507 » have_data = (report_data->gestures_count + | |
| 1508 » » » » report_data->touch_fingers + report_data->button ); | |
| 1509 | |
| 1510 » DBGPRINTK(("%s: gesture count = %d, touch finger =%d, button = 0x%02x\n" , | |
| 1511 » » » » __func__, report_data->gestures_count, | |
| 1512 » » » » report_data->touch_fingers, report_data->button) ); | |
| 1513 » return have_data; | |
| 1514 } | 1188 } |
| 1515 | 1189 |
| 1516 static bool cyapa_i2c_get_input(struct cyapa_i2c *touch) | 1190 static bool cyapa_i2c_get_input(struct cyapa_i2c *touch) |
| 1517 { | 1191 { |
| 1518 int i; | |
| 1519 int ret_read_size = -1; | 1192 int ret_read_size = -1; |
| 1520 int read_length = 0; | 1193 int read_length = 0; |
| 1521 union cyapa_reg_data reg_data; | 1194 union cyapa_reg_data reg_data; |
| 1522 struct cyapa_reg_data_gen1 *gen1_data; | 1195 struct cyapa_reg_data_gen1 *gen1_data; |
| 1523 struct cyapa_reg_data_gen2 *gen2_data; | 1196 struct cyapa_reg_data_gen2 *gen2_data; |
| 1524 struct cyapa_report_data report_data; | 1197 struct cyapa_report_data report_data; |
| 1525 | 1198 |
| 1526 » DBGPRINTK(("%s: start ... \n", __func__)); | 1199 » DBGPRINTK(("%s: start ...\n", __func__)); |
| 1527 | 1200 |
| 1528 memset(®_data, 0, sizeof(union cyapa_reg_data)); | 1201 memset(®_data, 0, sizeof(union cyapa_reg_data)); |
| 1529 | 1202 |
| 1530 /* read register data from trackpad. */ | 1203 /* read register data from trackpad. */ |
| 1531 gen1_data = ®_data.gen1_data; | 1204 gen1_data = ®_data.gen1_data; |
| 1532 gen2_data = ®_data.gen2_data; | 1205 gen2_data = ®_data.gen2_data; |
| 1533 read_length = CYAPA_REL_REG_DATA_SIZE; | 1206 read_length = CYAPA_REL_REG_DATA_SIZE; |
| 1534 if (touch->platform_data->gen == CYAPA_GEN1) | 1207 if (touch->platform_data->gen == CYAPA_GEN1) |
| 1535 read_length = (int)sizeof(struct cyapa_reg_data_gen1); | 1208 read_length = (int)sizeof(struct cyapa_reg_data_gen1); |
| 1536 else | 1209 else |
| 1537 read_length = (int)sizeof(struct cyapa_reg_data_gen2); | 1210 read_length = (int)sizeof(struct cyapa_reg_data_gen2); |
| 1538 » DBGPRINTK(("%s: read gen%d data, read length=%d \n", __func__, | 1211 » DBGPRINTK(("%s: read gen%d data, read length=%d\n", __func__, |
| 1539 » » ((touch->platform_data->gen == CYAPA_GEN1)?1:2), read_length)); | 1212 » » » ((touch->platform_data->gen == CYAPA_GEN1) ? 1 : 2), |
| 1540 » ret_read_size = cyapa_i2c_reg_read_block(touch->client, | 1213 » » » read_length)); |
| 1214 » ret_read_size = cyapa_i2c_reg_read_block(touch, | |
| 1541 DATA_REG_START_OFFSET, | 1215 DATA_REG_START_OFFSET, |
| 1542 read_length, | 1216 read_length, |
| 1543 (u8 *)®_data); | 1217 (u8 *)®_data); |
| 1544 if (ret_read_size < 0) { | 1218 if (ret_read_size < 0) { |
| 1545 » » DBGPRINTK(("%s: I2C read data from trackpad error = %d \n", | 1219 » » DBGPRINTK(("%s: I2C read data from trackpad error = %d\n", |
| 1546 __func__, ret_read_size)); | 1220 __func__, ret_read_size)); |
| 1547 return 0; | 1221 return 0; |
| 1548 } | 1222 } |
| 1549 | 1223 |
| 1550 if (cyapa_verify_data_device(touch, ®_data)) { | 1224 if (cyapa_verify_data_device(touch, ®_data)) { |
| 1551 » » DBGPRINTK(("%s: verify data device failed, invalid data, skip.\n ", __func__)); | 1225 » » DBGPRINTK(("%s: verify data device failed, \ |
| 1226 » » » invalid data, skip.\n", __func__)); | |
| 1552 return 0; | 1227 return 0; |
| 1553 } | 1228 } |
| 1554 | 1229 |
| 1555 /* process and parse raw data that read from Trackpad. */ | 1230 /* process and parse raw data that read from Trackpad. */ |
| 1556 memset(&report_data, 0, sizeof(struct cyapa_report_data)); | 1231 memset(&report_data, 0, sizeof(struct cyapa_report_data)); |
| 1557 » touch->xy_touchs_included_bits = 0; | 1232 » if (touch->platform_data->gen == CYAPA_GEN1) |
| 1558 » /* initialize current active gestures array. */ | |
| 1559 » for (i=0; i<MAX_FINGERS; i++) { | |
| 1560 » » touch->cur_active_gestures[i] = 0; | |
| 1561 » } | |
| 1562 » | |
| 1563 » if (touch->platform_data->gen == CYAPA_GEN1) { | |
| 1564 cyapa_parse_gen1_data(touch, gen1_data, &report_data); | 1233 cyapa_parse_gen1_data(touch, gen1_data, &report_data); |
| 1565 » } else { | 1234 » else |
| 1566 cyapa_parse_gen2_data(touch, gen2_data, &report_data); | 1235 cyapa_parse_gen2_data(touch, gen2_data, &report_data); |
| 1567 } | |
| 1568 | 1236 |
| 1569 /* report data to input subsystem. */ | 1237 /* report data to input subsystem. */ |
| 1570 » if (touch->platform_data->use_absolute_mode == false) { | 1238 » return cyapa_handle_input_report_data(touch, &report_data); |
| 1571 » » return cyapa_rel_input_report_data(touch, &report_data); | |
| 1572 » } else { | |
| 1573 » » return cyapa_abs_input_report_data(touch, &report_data); | |
| 1574 » } | |
| 1575 } | |
| 1576 | |
| 1577 static void cyapa_i2c_reschedule_work(struct cyapa_i2c *touch, unsigned long del ay) | |
| 1578 { | |
| 1579 » unsigned long flags; | |
| 1580 | |
| 1581 » spin_lock_irqsave(&touch->lock, flags); | |
| 1582 | |
| 1583 » /* | |
| 1584 » * If work is already scheduled then subsequent schedules will not | |
| 1585 » * change the scheduled time that's why we have to cancel it first. | |
| 1586 » */ | |
| 1587 » __cancel_delayed_work(&touch->dwork); | |
| 1588 » schedule_delayed_work(&touch->dwork, delay); | |
| 1589 | |
| 1590 » spin_unlock_irqrestore(&touch->lock, flags); | |
| 1591 } | |
| 1592 | |
| 1593 static irqreturn_t cyapa_i2c_irq(int irq, void *dev_id) | |
| 1594 { | |
| 1595 » struct cyapa_i2c *touch = dev_id; | |
| 1596 | |
| 1597 » DBGPRINTK(("%s: trackpad interrupt captured. report_rate=%d; read_pendin g=%d\n", | |
| 1598 » » __func__, touch->platform_data->report_rate, touch->read_pending )); | |
| 1599 | |
| 1600 » if (touch->platform_data->report_rate == 0) { | |
| 1601 » » /* | |
| 1602 » » ** no limitatioin for data reporting. | |
| 1603 » » ** the report rate depending on trackpad max report rate. | |
| 1604 » » ** this is the default report mode. | |
| 1605 » » */ | |
| 1606 » » cyapa_i2c_reschedule_work(touch, 0); | |
| 1607 » } else { | |
| 1608 » » /* | |
| 1609 » » ** when use limited report rate, some important data packages ma y be lost. | |
| 1610 » » ** Such as a tap or double tap gesture may be lost. | |
| 1611 » » ** So firmware need to keep this data until there data is read. | |
| 1612 » » */ | |
| 1613 » » if (!touch->read_pending) { | |
| 1614 » » » touch->read_pending = 1; | |
| 1615 » » » cyapa_i2c_reschedule_work(touch, touch->scan_ms); | |
| 1616 » » } | |
| 1617 » } | |
| 1618 | |
| 1619 » return IRQ_HANDLED; | |
| 1620 } | 1239 } |
| 1621 | 1240 |
| 1622 /* Control the Device polling rate / Work Handler sleep time */ | 1241 /* Control the Device polling rate / Work Handler sleep time */ |
| 1623 static unsigned long cyapa_i2c_adjust_delay(struct cyapa_i2c *touch, bool have_d ata) | 1242 static unsigned long cyapa_i2c_adjust_delay(struct cyapa_i2c *touch, |
| 1243 » » » bool have_data) | |
| 1624 { | 1244 { |
| 1625 unsigned long delay, nodata_count_thres; | 1245 unsigned long delay, nodata_count_thres; |
| 1626 | 1246 |
| 1627 » if (touch->platform_data->use_polling_mode) { | 1247 » if (touch->down_to_polling_mode == true) { |
| 1628 » » delay =touch->platform_data->polling_interval_time_active; | 1248 » » delay = touch->platform_data->polling_interval_time_active; |
| 1629 if (have_data) { | 1249 if (have_data) { |
| 1630 touch->no_data_count = 0; | 1250 touch->no_data_count = 0; |
| 1631 } else { | 1251 } else { |
| 1632 » » » nodata_count_thres = CYAPA_NO_DATA_THRES / touch->scan_m s; | 1252 » » » nodata_count_thres = |
| 1253 » » » » CYAPA_NO_DATA_THRES / touch->scan_ms; | |
| 1633 if (touch->no_data_count < nodata_count_thres) | 1254 if (touch->no_data_count < nodata_count_thres) |
| 1634 touch->no_data_count++; | 1255 touch->no_data_count++; |
| 1635 else | 1256 else |
| 1636 delay = CYAPA_NO_DATA_SLEEP_MSECS; | 1257 delay = CYAPA_NO_DATA_SLEEP_MSECS; |
| 1637 } | 1258 } |
| 1638 return msecs_to_jiffies(delay); | 1259 return msecs_to_jiffies(delay); |
| 1639 } else { | 1260 } else { |
| 1640 delay = msecs_to_jiffies(CYAPA_THREAD_IRQ_SLEEP_MSECS); | 1261 delay = msecs_to_jiffies(CYAPA_THREAD_IRQ_SLEEP_MSECS); |
| 1641 return round_jiffies_relative(delay); | 1262 return round_jiffies_relative(delay); |
| 1642 } | 1263 } |
| 1643 } | 1264 } |
| 1644 | 1265 |
| 1645 /* Work Handler */ | 1266 /* Work Handler */ |
| 1646 static void cyapa_i2c_work_handler(struct work_struct *work) | 1267 static void cyapa_i2c_work_handler(struct work_struct *work) |
| 1647 { | 1268 { |
| 1648 bool have_data; | 1269 bool have_data; |
| 1649 » struct cyapa_i2c *touch = container_of(work, struct cyapa_i2c, dwork.wor k); | 1270 » struct cyapa_i2c *touch = |
| 1271 » » container_of(work, struct cyapa_i2c, dwork.work); | |
| 1650 unsigned long delay; | 1272 unsigned long delay; |
| 1651 | 1273 |
| 1652 » DBGPRINTK(("%s: start ... \n", __func__)); | 1274 » spin_lock(&touch->misc_spinlock); |
| 1275 » if (touch->fw_work_mode == CYAPA_BOOTLOAD_MODE) { | |
| 1276 » » spin_unlock(&touch->misc_spinlock); | |
| 1277 » » 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
| |
| 1278 » } else { | |
| 1279 » » spin_unlock(&touch->misc_spinlock); | |
| 1653 | 1280 |
| 1654 » have_data = cyapa_i2c_get_input(touch); | 1281 » » have_data = cyapa_i2c_get_input(touch); |
| 1282 » » /* | |
| 1283 » » * While interrupt driven, there is no real need to poll the | |
| 1284 » » * device. But touchpads are very sensitive, so there could be | |
| 1285 » » * errors related to physical environment and the attention | |
| 1286 » » * line isn'tneccesarily asserted. In such case we can lose | |
| 1287 » » * the touchpad. We poll the device once in | |
| 1288 » » * CYAPA_THREAD_IRQ_SLEEP_SECS and if error is detected, | |
| 1289 » » * we try to reset and reconfigure the touchpad. | |
| 1290 » » */ | |
| 1291 » » delay = cyapa_i2c_adjust_delay(touch, have_data); | |
| 1292 » » /* if needs fixed interval time trackpad scan, open it. | |
| 1293 » » cyapa_i2c_reschedule_work(touch, delay); | |
| 1294 » » */ | |
|
Olof Johansson
2011/05/02 05:47:12
Please don't add dead code.
| |
| 1295 » } | |
| 1296 } | |
| 1297 | |
| 1298 static void cyapa_i2c_reschedule_work(struct cyapa_i2c *touch, | |
| 1299 » » unsigned long delay) | |
| 1300 { | |
| 1301 » unsigned long flags; | |
| 1302 | |
| 1303 » spin_lock_irqsave(&touch->lock, flags); | |
| 1655 | 1304 |
| 1656 /* | 1305 /* |
| 1657 » * While interrupt driven, there is no real need to poll the device. | 1306 » * If work is already scheduled then subsequent schedules will not |
| 1658 » * But touchpads are very sensitive, so there could be errors | 1307 » * change the scheduled time that's why we have to cancel it first. |
| 1659 » * related to physical environment and the attention line isn't | |
| 1660 » * neccesarily asserted. In such case we can lose the touchpad. | |
| 1661 » * We poll the device once in CYAPA_THREAD_IRQ_SLEEP_SECS and | |
| 1662 » * if error is detected, we try to reset and reconfigure the touchpad. | |
| 1663 */ | 1308 */ |
| 1664 » delay = cyapa_i2c_adjust_delay(touch, have_data); | 1309 » __cancel_delayed_work(&touch->dwork); |
| 1665 » //cyapa_i2c_reschedule_work(touch, delay); | 1310 » schedule_delayed_work(&touch->dwork, delay); |
| 1666 | 1311 |
| 1667 » touch->read_pending = 0; | 1312 » spin_unlock_irqrestore(&touch->lock, flags); |
| 1668 » | 1313 } |
| 1669 » DBGPRINTK(("%s: done ... \n", __func__)); | 1314 |
| 1315 static irqreturn_t cyapa_i2c_irq(int irq, void *dev_id) | |
| 1316 { | |
| 1317 » struct cyapa_i2c *touch = dev_id; | |
| 1318 | |
| 1319 » cyapa_i2c_reschedule_work(touch, 0); | |
| 1320 | |
| 1321 » return IRQ_HANDLED; | |
| 1670 } | 1322 } |
| 1671 | 1323 |
| 1672 static int cyapa_i2c_open(struct input_dev *input) | 1324 static int cyapa_i2c_open(struct input_dev *input) |
| 1673 { | 1325 { |
| 1674 struct cyapa_i2c *touch = input_get_drvdata(input); | 1326 struct cyapa_i2c *touch = input_get_drvdata(input); |
| 1675 int retval; | 1327 int retval; |
| 1676 | 1328 |
| 1677 if (0 == touch->open_count) { | 1329 if (0 == touch->open_count) { |
| 1678 /* Since input_dev mouse, wheel, and kbd will all use same open and close routines. | |
| 1679 ** But indeed, reset config to trackpad once is enought, | |
| 1680 ** So when trackpad is open for the first time, reset it. | |
| 1681 ** for other time not do it. | |
| 1682 */ | |
| 1683 retval = cyapa_i2c_reset_config(touch); | 1330 retval = cyapa_i2c_reset_config(touch); |
| 1684 if (retval) { | 1331 if (retval) { |
| 1685 » » » DBGPRINTK(("%s: failed to reset i2c trackpad. error = %d \n", __func__, retval)); | 1332 » » » DBGPRINTK(("%s: failed to reset i2c trackpad. \ |
| 1333 » » » » error = %d\n", __func__, retval)); | |
| 1686 return retval; | 1334 return retval; |
| 1687 } | 1335 } |
| 1688 } | 1336 } |
| 1689 touch->open_count++; | 1337 touch->open_count++; |
| 1690 | 1338 |
| 1691 » if (touch->platform_data->use_polling_mode) { | 1339 » if (touch->down_to_polling_mode == true) { |
| 1692 /* | 1340 /* |
| 1693 » » ** for the firstly time, it is set to CYAPA_NO_DATA_SLEEP_MSECS, | 1341 » » ** At firstly time, it is set to CYAPA_NO_DATA_SLEEP_MSECS, |
| 1694 ** when data is read from trackpad, the read speed will | 1342 ** when data is read from trackpad, the read speed will |
| 1695 ** be pull up. | 1343 ** be pull up. |
|
Daniel Kurtz
2011/05/02 12:43:47
I'm not sure what this comment means.
Perhaps:
/*
| |
| 1696 */ | 1344 */ |
| 1697 » » cyapa_i2c_reschedule_work(touch, msecs_to_jiffies(CYAPA_NO_DATA_ SLEEP_MSECS)); | 1345 » » cyapa_i2c_reschedule_work(touch, |
| 1346 » » » » msecs_to_jiffies(CYAPA_NO_DATA_SLEEP_MSECS)); | |
| 1698 } | 1347 } |
| 1699 | 1348 |
| 1700 » DBGPRINTK(("%s: touch->open_count = %d ... \n", __func__, touch->open_co unt)); | 1349 » DBGPRINTK(("%s: touch->open_count = %d ...\n", |
| 1350 » » » __func__, touch->open_count)); | |
| 1701 | 1351 |
| 1702 return 0; | 1352 return 0; |
| 1703 } | 1353 } |
| 1704 | 1354 |
| 1705 static void cyapa_i2c_close(struct input_dev *input) | 1355 static void cyapa_i2c_close(struct input_dev *input) |
| 1706 { | 1356 { |
| 1707 struct cyapa_i2c *touch = input_get_drvdata(input); | 1357 struct cyapa_i2c *touch = input_get_drvdata(input); |
| 1708 | 1358 |
| 1709 touch->open_count--; | 1359 touch->open_count--; |
| 1710 | 1360 |
| 1711 if (0 == touch->open_count) { | 1361 if (0 == touch->open_count) { |
| 1712 » » /* Since input_dev mouse, wheel, and kbd will all use same open and close routines. | 1362 » » /* Since input_dev mouse, wheel, and kbd will all use same open |
| 1363 » » ** and close routines. | |
| 1713 ** so when all mouse, wheel and kbd input_dev is closed, | 1364 ** so when all mouse, wheel and kbd input_dev is closed, |
| 1714 ** then cancel the delayed work routine. | 1365 ** then cancel the delayed work routine. |
|
Daniel Kurtz
2011/05/02 12:43:47
/*
* Since the mouse, wheel and kbd input_dev all
| |
| 1715 */ | 1366 */ |
| 1716 cancel_delayed_work_sync(&touch->dwork); | 1367 cancel_delayed_work_sync(&touch->dwork); |
| 1717 } | 1368 } |
| 1718 | 1369 |
| 1719 » DBGPRINTK(("%s: touch->open_count ... \n", __func__, touch->open_count)) ; | 1370 » DBGPRINTK(("%s: touch->open_count=%d\n", __func__, touch->open_count)); |
| 1720 } | |
| 1721 | |
| 1722 void cyapa_set_preferences(struct cyapa_preferences *preferences) | |
| 1723 { | |
| 1724 » /* set default setting for hscroll. */ | |
| 1725 » preferences->vscroll.default_threshold = 4; | |
| 1726 » preferences->vscroll.middle_threshold = 8; | |
| 1727 » preferences->vscroll.fast_threshold = 16; | |
| 1728 | |
| 1729 » /* set default setting for vscroll. */ | |
| 1730 » preferences->hscroll.default_threshold = 4; | |
| 1731 » preferences->hscroll.middle_threshold = 8; | |
| 1732 » preferences->hscroll.fast_threshold = 16; | |
| 1733 } | 1371 } |
| 1734 | 1372 |
| 1735 static struct cyapa_i2c *cyapa_i2c_touch_create(struct i2c_client *client) | 1373 static struct cyapa_i2c *cyapa_i2c_touch_create(struct i2c_client *client) |
| 1736 { | 1374 { |
| 1737 struct cyapa_i2c *touch; | 1375 struct cyapa_i2c *touch; |
| 1738 | 1376 |
| 1739 touch = kzalloc(sizeof(struct cyapa_i2c), GFP_KERNEL); | 1377 touch = kzalloc(sizeof(struct cyapa_i2c), GFP_KERNEL); |
| 1740 if (!touch) | 1378 if (!touch) |
| 1741 return NULL; | 1379 return NULL; |
| 1742 | 1380 |
| 1743 DBGPRINTK(("%s: client=0x%p, allocate memory for touch successfully.\n", | |
| 1744 __func__, client)); | |
| 1745 | |
| 1746 touch->platform_data = &cyapa_i2c_platform_data; | 1381 touch->platform_data = &cyapa_i2c_platform_data; |
| 1747 if (client->dev.platform_data) { | 1382 if (client->dev.platform_data) { |
| 1748 » » DBGPRINTK(("%s: client->dev.platform_data is set, copy it.\n", _ _func__)); | 1383 » » *touch->platform_data = |
| 1749 » » *touch->platform_data = *(struct cyapa_platform_data *)client->d ev.platform_data; | 1384 » » » *(struct cyapa_platform_data *) |
| 1385 » » » » client->dev.platform_data; | |
| 1750 } | 1386 } |
| 1751 | 1387 |
| 1752 » #ifdef DBG_CYAPA_READ_BLOCK_DATA | 1388 » touch->scan_ms = touch->platform_data->report_rate |
| 1753 » cyapa_print_paltform_data(__func__, touch->platform_data); | 1389 » » ? (1000»/ touch->platform_data->report_rate) : 0; |
| 1754 » #endif | |
| 1755 | |
| 1756 » if (touch->platform_data->use_polling_mode && | |
| 1757 » » (touch->platform_data->report_rate == 0)) { | |
| 1758 » » /* when user miss setting platform data, | |
| 1759 » » ** ensure that system is robust. | |
| 1760 » » ** no divid zero error. */ | |
| 1761 » » touch->platform_data->report_rate = CYAPA_POLLING_REPORTRATE_DEF AULT; | |
| 1762 » } | |
| 1763 » touch->scan_ms = touch->platform_data->report_rate?(1000 / touch->platfo rm_data->report_rate):0; | |
| 1764 touch->open_count = 0; | 1390 touch->open_count = 0; |
| 1765 touch->prev_abs_x = -1; | |
| 1766 touch->prev_abs_y = -1; | |
| 1767 touch->client = client; | 1391 touch->client = client; |
| 1768 » touch->zoomin_delta = 0; | 1392 » touch->down_to_polling_mode = false; |
| 1769 » touch->zoomout_delta = 0; | 1393 » global_touch = touch; |
| 1770 » touch->hscroll_left = 0; | 1394 » touch->fw_work_mode = CYAPA_STREAM_MODE; |
| 1771 » touch->hscroll_right = 0; | 1395 » touch->misc_open_count = 0; |
| 1772 » touch->prev_touch_fingers = 0; | 1396 » sema_init(&touch->misc_sem, 1); |
| 1773 | 1397 » spin_lock_init(&touch->misc_spinlock); |
| 1774 » cyapa_set_preferences(&touch->preferences); | 1398 » mutex_init(&touch->misc_mutex); |
| 1775 | 1399 |
| 1776 INIT_DELAYED_WORK(&touch->dwork, cyapa_i2c_work_handler); | 1400 INIT_DELAYED_WORK(&touch->dwork, cyapa_i2c_work_handler); |
| 1777 spin_lock_init(&touch->lock); | 1401 spin_lock_init(&touch->lock); |
| 1778 | 1402 |
| 1779 return touch; | 1403 return touch; |
| 1780 } | 1404 } |
| 1781 | 1405 |
| 1782 static int cyapa_create_input_dev_mouse(struct cyapa_i2c *touch) | 1406 static int cyapa_create_input_dev(struct cyapa_i2c *touch) |
| 1783 { | 1407 { |
| 1784 int retval = 0; | 1408 int retval = 0; |
| 1785 struct input_dev *input = NULL; | 1409 struct input_dev *input = NULL; |
| 1786 | 1410 |
| 1787 input = touch->input = input_allocate_device(); | 1411 input = touch->input = input_allocate_device(); |
| 1788 if (!touch->input) { | 1412 if (!touch->input) { |
| 1789 » » dev_err(&touch->client->dev, "%s: Allocate memory for Input devi ce failed: %d\n", | 1413 » » dev_err(&touch->client->dev, |
| 1790 » » » » » __func__, retval); | 1414 » » » "%s: Allocate memory for Input device failed: %d\n", |
| 1415 » » » __func__, retval); | |
| 1791 return -ENOMEM; | 1416 return -ENOMEM; |
| 1792 } | 1417 } |
| 1793 | 1418 |
| 1794 input->name = "cyapa_i2c_trackpad"; | 1419 input->name = "cyapa_i2c_trackpad"; |
| 1795 input->phys = touch->client->adapter->name; | 1420 input->phys = touch->client->adapter->name; |
| 1796 input->id.bustype = BUS_I2C; | 1421 input->id.bustype = BUS_I2C; |
| 1797 input->id.version = 1; | 1422 input->id.version = 1; |
| 1423 input->id.product = 0; /* means any product in eventcomm. */ | |
| 1798 input->dev.parent = &touch->client->dev; | 1424 input->dev.parent = &touch->client->dev; |
| 1799 | 1425 |
| 1800 input->open = cyapa_i2c_open; | 1426 input->open = cyapa_i2c_open; |
| 1801 input->close = cyapa_i2c_close; | 1427 input->close = cyapa_i2c_close; |
| 1802 input_set_drvdata(input, touch); | 1428 input_set_drvdata(input, touch); |
| 1803 | 1429 |
| 1804 » if (touch->platform_data->use_absolute_mode) | 1430 » __set_bit(EV_ABS, input->evbit); |
| 1805 » { | |
| 1806 » » /* absolution data report mode. */ | |
| 1807 » » __set_bit(EV_ABS, input->evbit); | |
| 1808 » » __set_bit(EV_KEY, input->evbit); | |
| 1809 » » | |
| 1810 » » input_set_abs_params(input, ABS_X, touch->max_absolution_x/10, | |
| 1811 » » » » » » touch->max_absolution_x/2, 0, 0) ; | |
| 1812 » » input_set_abs_params(input, ABS_Y, touch->max_absolution_y/10, | |
| 1813 » » » » » » touch->max_absolution_y/2, 0, 0) ; | |
| 1814 » » input_set_abs_params(input, ABS_PRESSURE, 0, 255, 0, 0); | |
| 1815 » » input_set_abs_params(input, ABS_TOOL_WIDTH, 0, 255, 0, 0); | |
| 1816 » » | |
| 1817 » » __set_bit(BTN_TOUCH, input->keybit); | |
| 1818 » » __set_bit(BTN_TOOL_FINGER, input->keybit); | |
| 1819 » » __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); | |
| 1820 » » __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); | |
| 1821 » » __set_bit(BTN_TOOL_QUADTAP, input->keybit); | |
| 1822 | 1431 |
| 1823 » » __set_bit(BTN_LEFT, input->keybit); | 1432 » input_set_abs_params(input, ABS_X, 0, touch->max_absolution_x, 0, 0); |
| 1824 » » __set_bit(BTN_RIGHT, input->keybit); | 1433 » 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
| |
| 1825 » » __set_bit(BTN_MIDDLE, input->keybit); | 1434 » input_set_abs_params(input, ABS_PRESSURE, 0, 255, 0, 0); |
| 1435 » input_set_abs_params(input, ABS_TOOL_WIDTH, 0, 255, 0, 0); | |
| 1826 | 1436 |
| 1827 » » __clear_bit(EV_REL, input->evbit); | 1437 » /* finger touch area */ |
| 1828 » » __clear_bit(REL_X, input->relbit); | 1438 » input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, |
| 1829 » » __clear_bit(REL_Y, input->relbit); | 1439 » » 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
| |
| 1830 » » __clear_bit(BTN_TRIGGER, input->keybit); | 1440 » input_set_abs_params(input, ABS_MT_TOUCH_MINOR, |
| 1441 » » 0, CYAPA_MT_MAX_TOUCH, 0, 0); | |
| 1442 » /* finger approach area */ | |
| 1443 » input_set_abs_params(input, ABS_MT_WIDTH_MAJOR, | |
| 1444 » » 0, CYAPA_MT_MAX_WIDTH, 0, 0); | |
| 1445 » input_set_abs_params(input, ABS_MT_WIDTH_MINOR, | |
| 1446 » » 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
| |
| 1447 » /* finger orientation */ | |
| 1448 » input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0); | |
| 1449 » /* finger position */ | |
| 1450 » input_set_abs_params(input, ABS_MT_POSITION_X, | |
| 1451 » » 0, touch->max_absolution_x, 0, 0); | |
|
Daniel Kurtz
2011/05/02 12:43:47
absolution and absolute have completely different
| |
| 1452 » input_set_abs_params(input, ABS_MT_POSITION_Y, | |
| 1453 » » 0, touch->max_absolution_y, 0, 0); | |
| 1831 | 1454 |
| 1832 » » input_abs_set_res(input, ABS_X, touch->max_absolution_x/touch->p hysical_size_x); | 1455 » __set_bit(EV_KEY, input->evbit); |
| 1833 » » input_abs_set_res(input, ABS_Y, touch->max_absolution_y/touch->p hysical_size_y); | 1456 » __set_bit(BTN_TOUCH, input->keybit); |
| 1457 » __set_bit(BTN_TOOL_FINGER, input->keybit); | |
| 1458 » __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); | |
| 1459 » __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); | |
| 1460 » __set_bit(BTN_TOOL_QUADTAP, input->keybit); | |
| 1834 | 1461 |
| 1835 » » DBGPRINTK(("%s: Use absolute data reporting mode. \n", __func__) ); | 1462 » __set_bit(BTN_LEFT, input->keybit); |
| 1836 » } | |
| 1837 » else | |
| 1838 » { | |
| 1839 » » /* relative data reporting mode. */ | |
| 1840 » » __set_bit(EV_REL, input->evbit); | |
| 1841 » » __set_bit(REL_X, input->relbit); | |
| 1842 » » __set_bit(REL_Y, input->relbit); | |
| 1843 | 1463 |
| 1844 » » __set_bit(EV_KEY, input->evbit); | 1464 » input_set_events_per_packet(input, 60); |
| 1845 » » __set_bit(BTN_LEFT, input->keybit); | |
| 1846 » » __set_bit(BTN_RIGHT, input->keybit); | |
| 1847 » » __set_bit(BTN_MIDDLE, input->keybit); | |
| 1848 | |
| 1849 » » __clear_bit(EV_ABS, input->evbit); | |
| 1850 | |
| 1851 » » DBGPRINTK(("%s: Use relative data reporting mode. \n", __func__) ); | |
| 1852 » } | |
| 1853 | 1465 |
| 1854 /* Register the device in input subsystem */ | 1466 /* Register the device in input subsystem */ |
| 1855 retval = input_register_device(touch->input); | 1467 retval = input_register_device(touch->input); |
| 1856 if (retval) { | 1468 if (retval) { |
| 1857 » » dev_err(&touch->client->dev, "%s: Input device register failed: %d\n", __func__, retval); | 1469 » » dev_err(&touch->client->dev, |
| 1470 » » » "%s: Input device register failed: %d\n", | |
| 1471 » » » __func__, retval); | |
| 1858 | 1472 |
| 1859 input_free_device(input); | 1473 input_free_device(input); |
| 1860 return retval; | 1474 return retval; |
|
Olof Johansson
2011/05/02 05:47:12
No need to return this here, just change the code
| |
| 1861 } | 1475 } |
| 1862 | 1476 |
| 1863 return 0; | 1477 return 0; |
| 1864 } | 1478 } |
| 1865 | 1479 |
| 1866 static int cyapa_create_input_dev_wheel(struct cyapa_i2c *touch) | |
| 1867 { | |
| 1868 int retval =0; | |
| 1869 struct input_dev *input_wheel = NULL; | |
| 1870 | |
| 1871 input_wheel = touch->input_wheel = input_allocate_device(); | |
| 1872 if (!touch->input_wheel) { | |
| 1873 dev_err(&touch->client->dev, "%s: Allocate memory for Input devi ce failed: %d\n", | |
| 1874 __func__, retval); | |
| 1875 return -ENOMEM; | |
| 1876 } | |
| 1877 | |
| 1878 input_wheel->name = "cyapa_i2c_wheel"; | |
| 1879 input_wheel->phys = touch->client->adapter->name; | |
| 1880 input_wheel->id.bustype = BUS_I2C; | |
| 1881 input_wheel->id.version = 1; | |
| 1882 input_wheel->dev.parent = &touch->client->dev; | |
| 1883 input_wheel->open = cyapa_i2c_open; | |
| 1884 input_wheel->close = cyapa_i2c_close; | |
| 1885 input_set_drvdata(input_wheel, touch); | |
| 1886 | |
| 1887 __set_bit(EV_KEY, input_wheel->evbit); | |
| 1888 __set_bit(EV_REL, input_wheel->evbit); | |
| 1889 __set_bit(REL_WHEEL, input_wheel->relbit); | |
| 1890 | |
| 1891 retval = input_register_device(touch->input_wheel); | |
| 1892 if (retval) { | |
| 1893 dev_err(&touch->client->dev, "%s: Input device register failed: %d\n", __func__, retval); | |
| 1894 | |
| 1895 input_free_device(input_wheel); | |
| 1896 return retval; | |
| 1897 } | |
| 1898 | |
| 1899 return 0; | |
| 1900 } | |
| 1901 | |
| 1902 #define MAX_NR_SCANCODES 128 | |
| 1903 | |
| 1904 static unsigned char cyapa_virtual_keycode[MAX_NR_SCANCODES] = { | |
| 1905 /* Bellow keys are supported. | |
| 1906 KEY_ENTER 28 | |
| 1907 KEY_LEFTCTRL 29 | |
| 1908 KEY_LEFTSHIFT 42 | |
| 1909 KEY_RIGHTSHIFT 54 | |
| 1910 KEY_LEFTALT 56 | |
| 1911 KEY_KPMINUS 74 | |
| 1912 KEY_KPPLUS 78 | |
| 1913 KEY_RIGHTCTRL 97 | |
| 1914 KEY_RIGHTALT 100 | |
| 1915 KEY_HOME 102 | |
| 1916 KEY_UP 103 | |
| 1917 KEY_PAGEUP 104 | |
| 1918 KEY_LEFT 105 | |
| 1919 KEY_RIGHT 106 | |
| 1920 KEY_END 107 | |
| 1921 KEY_DOWN 108 | |
| 1922 KEY_PAGEDOWN 109 | |
| 1923 */ | |
| 1924 28, 29, 42, 54, 56, 74, 78, 97, 100, 102, 103, 104, 105, 106, 107, 108, 109 | |
| 1925 }; | |
| 1926 | |
| 1927 static int cyapa_create_input_dev_kbd(struct cyapa_i2c *touch) | |
| 1928 { | |
| 1929 int retval =0; | |
| 1930 int i; | |
| 1931 struct input_dev *input_kbd = NULL; | |
| 1932 | |
| 1933 input_kbd = touch->input_kbd = input_allocate_device(); | |
| 1934 if (!touch->input_kbd) { | |
| 1935 dev_err(&touch->client->dev, "%s: Allocate memory for Input devi ce failed: %d\n", | |
| 1936 __func__, retval); | |
| 1937 return -ENOMEM; | |
| 1938 } | |
| 1939 | |
| 1940 input_kbd->name = "cyapa_i2c_virtual_kbd"; | |
| 1941 input_kbd->phys = touch->client->adapter->name; | |
| 1942 input_kbd->id.bustype = BUS_I2C; | |
| 1943 input_kbd->id.version = 1; | |
| 1944 input_kbd->dev.parent = &touch->client->dev; | |
| 1945 input_kbd->open = cyapa_i2c_open; | |
| 1946 input_kbd->close = cyapa_i2c_close; | |
| 1947 input_set_drvdata(input_kbd, touch); | |
| 1948 | |
| 1949 input_kbd->keycode = &cyapa_virtual_keycode; | |
| 1950 input_kbd->keycodesize = sizeof(unsigned char); | |
| 1951 input_kbd->keycodemax = ARRAY_SIZE(cyapa_virtual_keycode); | |
| 1952 | |
| 1953 __set_bit(EV_KEY, input_kbd->evbit); | |
| 1954 __set_bit(EV_REP, input_kbd->evbit); | |
| 1955 | |
| 1956 for (i = 0; i < ARRAY_SIZE(cyapa_virtual_keycode); i++) { | |
| 1957 __set_bit(cyapa_virtual_keycode[i], input_kbd->keybit); | |
| 1958 } | |
| 1959 __clear_bit(KEY_RESERVED, input_kbd->keybit); | |
| 1960 | |
| 1961 retval = input_register_device(touch->input_kbd); | |
| 1962 if (retval) { | |
| 1963 dev_err(&touch->client->dev, "%s: Input device register failed: %d\n", __func__, retval); | |
| 1964 | |
| 1965 input_free_device(input_kbd); | |
| 1966 return retval; | |
| 1967 } | |
| 1968 | |
| 1969 return 0; | |
| 1970 } | |
| 1971 | |
| 1972 static int __devinit cyapa_i2c_probe(struct i2c_client *client, | 1480 static int __devinit cyapa_i2c_probe(struct i2c_client *client, |
| 1973 const struct i2c_device_id *dev_id) | 1481 const struct i2c_device_id *dev_id) |
| 1974 { | 1482 { |
| 1975 int retval = 0; | 1483 int retval = 0; |
| 1976 struct cyapa_i2c *touch; | 1484 struct cyapa_i2c *touch; |
| 1977 | 1485 |
| 1978 » DBGPRINTK(("%s: start ... \n", __func__)); | 1486 » if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) |
| 1487 » » return -EIO; | |
| 1488 | |
| 1979 touch = cyapa_i2c_touch_create(client); | 1489 touch = cyapa_i2c_touch_create(client); |
| 1980 if (!touch) | 1490 if (!touch) |
| 1981 return -ENOMEM; | 1491 return -ENOMEM; |
| 1982 | 1492 |
| 1983 /* do platfrom initialize firstly. */ | 1493 /* do platfrom initialize firstly. */ |
|
Daniel Kurtz
2011/05/02 12:43:47
/* First, initialize platform_data */
| |
| 1984 » if (touch->platform_data->init) | 1494 » if (touch->platform_data->init) { |
| 1985 retval = touch->platform_data->init(); | 1495 retval = touch->platform_data->init(); |
| 1986 if (retval) | |
| 1987 goto err_mem_free; | |
| 1988 | |
| 1989 /* set irq number if not using polling mode. */ | |
| 1990 if (touch->platform_data->use_polling_mode == true) { | |
| 1991 touch->irq = -1; | |
| 1992 } else { | |
| 1993 if (touch->platform_data->irq_gpio == -1) { | |
| 1994 if (client->irq) { | |
| 1995 touch->irq = client->irq; | |
| 1996 } else { | |
| 1997 /* irq mode is not supported by system. */ | |
| 1998 touch->platform_data->use_polling_mode = true; | |
| 1999 touch->irq = -1; | |
| 2000 } | |
| 2001 } else { | |
| 2002 touch->irq = gpio_to_irq(touch->platform_data->irq_gpio) ; | |
| 2003 } | |
| 2004 } | |
| 2005 DBGPRINTK(("%s: irq=%d, client->irq=%d\n", __func__, touch->irq, client- >irq)); | |
| 2006 | |
| 2007 if (touch->platform_data->use_polling_mode == false) { | |
| 2008 DBGPRINTK(("%s: request interrupt riq. \n", __func__)); | |
| 2009 | |
| 2010 set_irq_type(touch->irq, IRQF_TRIGGER_FALLING); | |
| 2011 retval = request_irq(touch->irq, | |
| 2012 cyapa_i2c_irq, | |
| 2013 0, | |
| 2014 CYAPA_I2C_NAME, | |
| 2015 touch); | |
| 2016 if (retval) { | 1496 if (retval) { |
| 2017 » » » dev_warn(&touch->client->dev, | 1497 » » » dev_err(&client->dev, |
| 2018 » » » » » "%s: IRQ request failed: %d, falling bac k to polling mode. \n", | 1498 » » » » "%s: Error: board init failed: %d\n", |
| 2019 » » » » » __func__, retval); | 1499 » » » » __func__, retval); |
| 2020 | 1500 » » » goto err_mem_free; |
| 2021 » » » touch->platform_data->use_polling_mode = true; | |
| 2022 } | 1501 } |
| 2023 } | 1502 } |
| 2024 | 1503 |
| 2025 » /* reconfig trackpad depending on platfrom setting. */ | 1504 » /* set irq number for interrupt mode. |
| 2026 » /* Should disable interrupt to protect this polling read operation. | 1505 » * normallly, polling mode only will be used |
| 2027 » ** Ohterwise, this I2C read will be interrupt by other reading, and fail ed. */ | 1506 » * when special paltfrom that do not support slave interrupt. |
|
Daniel Kurtz
2011/05/02 12:43:47
s/normallly/normally
s/paltfrom/platform
'platfor
| |
| 2028 » disable_irq(touch->irq); | 1507 » * or allocate irq number to it failed. */ |
| 2029 » cyapa_i2c_reconfig(touch); | 1508 » if (touch->platform_data->irq_gpio <= 0) { |
| 2030 » enable_irq(touch->irq); | 1509 » » if (client->irq) { |
| 1510 » » » touch->irq = client->irq; | |
| 1511 » » } else { | |
| 1512 » » » /* irq mode is not supported by platfrom. */ | |
| 1513 » » » touch->irq = -1; | |
| 1514 » » } | |
| 1515 » } else { | |
| 1516 » » touch->irq = gpio_to_irq(touch->platform_data->irq_gpio); | |
| 1517 » } | |
| 2031 | 1518 |
| 2032 » /* create an input_dev instance for virtual mouse trackpad. */ | 1519 » if (touch->irq <= 0) { |
| 2033 » if ((retval = cyapa_create_input_dev_mouse(touch))) { | 1520 » » dev_err(&client->dev, |
| 2034 » » DBGPRINTK(("%s: create input_dev instance for mouse trackpad fil ed. \n", __func__)); | 1521 » » » "%s: Error, failed to allocate irq\n", __func__); |
| 2035 goto err_mem_free; | 1522 goto err_mem_free; |
| 2036 } | 1523 } |
| 1524 DBGPRINTK(("%s: irq=%d, client->irq=%d\n", | |
| 1525 __func__, touch->irq, client->irq)); | |
| 2037 | 1526 |
| 2038 » /* create an input_dev instances for virtual wheel device and virtual ke yboard device. */ | 1527 » set_irq_type(touch->irq, IRQF_TRIGGER_FALLING); |
| 2039 » if ((retval = cyapa_create_input_dev_wheel(touch))) { | 1528 » retval = request_irq(touch->irq, |
| 2040 » » DBGPRINTK(("%s: create input_dev instance for wheel filed. \n", __func__)); | 1529 » » » cyapa_i2c_irq, |
| 2041 » » goto err_mem_free; | 1530 » » » 0, |
| 1531 » » » CYAPA_I2C_NAME, | |
| 1532 » » » touch); | |
| 1533 » if (retval) { | |
| 1534 » » dev_warn(&touch->client->dev, | |
| 1535 » » » » "%s: IRQ request failed: \ | |
| 1536 » » » » %d, falling back to polling mode.\n", | |
| 1537 » » » » __func__, retval); | |
| 1538 | |
| 1539 » » touch->down_to_polling_mode = true; | |
| 2042 } | 1540 } |
| 2043 | 1541 |
| 2044 » if ((retval = cyapa_create_input_dev_kbd(touch))) { | 1542 » /* reconfig trackpad depending on platfrom setting. */ |
| 2045 » » DBGPRINTK(("%s: create input_dev instance for virtual keyboad fi led. \n", __func__)); | 1543 » cyapa_i2c_reconfig(touch); |
| 1544 | |
| 1545 » /* create an input_dev instance for trackpad device. */ | |
| 1546 » retval = cyapa_create_input_dev(touch); | |
| 1547 » if (retval) { | |
| 1548 » » free_irq(touch->irq, touch); | |
| 1549 » » DBGPRINTK(("%s: create mouse input_dev instance filed.\n", | |
| 1550 » » » » » __func__)); | |
| 2046 goto err_mem_free; | 1551 goto err_mem_free; |
| 2047 } | 1552 } |
| 2048 | 1553 |
| 2049 i2c_set_clientdata(client, touch); | 1554 i2c_set_clientdata(client, touch); |
| 2050 | 1555 |
| 2051 » DBGPRINTK(("%s: Done successfully. \n", __func__)); | 1556 » DBGPRINTK(("%s: Done successfully.\n", __func__)); |
| 1557 » dev_info(&touch->client->dev, | |
| 1558 » » "cypress_i2c: Cypress trackpad initialized successfully.\n"); | |
| 2052 | 1559 |
| 2053 return 0; | 1560 return 0; |
| 2054 | 1561 |
| 2055 err_mem_free: | 1562 err_mem_free: |
| 2056 /* release previous allocated input_dev instances. */ | 1563 /* release previous allocated input_dev instances. */ |
| 2057 if (touch->input) { | 1564 if (touch->input) { |
| 2058 input_free_device(touch->input); | 1565 input_free_device(touch->input); |
| 2059 touch->input = NULL; | 1566 touch->input = NULL; |
| 2060 } | 1567 } |
| 2061 | 1568 |
| 2062 » if (touch->input_wheel) { | 1569 » kfree(touch); |
| 2063 » » input_free_device(touch->input_wheel); | |
| 2064 » » touch->input_wheel = NULL; | |
| 2065 » } | |
| 2066 | 1570 |
| 2067 » if (touch->input_kbd) { | 1571 » DBGPRINTK(("%s: exist with error %d.\n", __func__, retval)); |
| 2068 » » input_free_device(touch->input_kbd); | |
| 2069 » » touch->input_kbd = NULL; | |
| 2070 » } | |
| 2071 | |
| 2072 » if (touch) { | |
| 2073 » » kfree(touch); | |
| 2074 » » touch = NULL; | |
| 2075 » } | |
| 2076 » DBGPRINTK(("%s: exist with error %d. \n", __func__, retval)); | |
| 2077 return retval; | 1572 return retval; |
| 2078 } | 1573 } |
| 2079 | 1574 |
| 2080 static int __devexit cyapa_i2c_remove(struct i2c_client *client) | 1575 static int __devexit cyapa_i2c_remove(struct i2c_client *client) |
| 2081 { | 1576 { |
| 2082 struct cyapa_i2c *touch = i2c_get_clientdata(client); | 1577 struct cyapa_i2c *touch = i2c_get_clientdata(client); |
| 2083 | 1578 |
| 2084 » if (!touch->platform_data->use_polling_mode) | 1579 » if (touch->down_to_polling_mode == false) |
| 2085 free_irq(client->irq, touch); | 1580 free_irq(client->irq, touch); |
| 2086 | 1581 |
| 2087 if (touch->input) | 1582 if (touch->input) |
| 2088 input_unregister_device(touch->input); | 1583 input_unregister_device(touch->input); |
| 2089 » if (touch->input_wheel) | 1584 » kfree(touch); |
| 2090 » » input_unregister_device(touch->input); | 1585 » global_touch = NULL; |
| 2091 » if (touch->input_kbd) | |
| 2092 » » input_unregister_device(touch->input); | |
| 2093 » if (touch) | |
| 2094 » » kfree(touch); | |
| 2095 | |
| 2096 » DBGPRINTK(("%s: ... \n", __func__)); | |
| 2097 | 1586 |
| 2098 return 0; | 1587 return 0; |
| 2099 } | 1588 } |
| 2100 | 1589 |
| 2101 #ifdef CONFIG_PM | 1590 #ifdef CONFIG_PM |
| 2102 static int cyapa_i2c_suspend(struct i2c_client *client, pm_message_t mesg) | 1591 static int cyapa_i2c_suspend(struct i2c_client *client, pm_message_t mesg) |
| 2103 { | 1592 { |
| 2104 struct cyapa_i2c *touch = i2c_get_clientdata(client); | 1593 struct cyapa_i2c *touch = i2c_get_clientdata(client); |
| 2105 | 1594 |
| 2106 DBGPRINTK(("%s: ... \n", __func__)); | |
| 2107 cancel_delayed_work_sync(&touch->dwork); | 1595 cancel_delayed_work_sync(&touch->dwork); |
| 2108 | 1596 |
| 2109 return 0; | 1597 return 0; |
| 2110 } | 1598 } |
| 2111 | 1599 |
| 2112 static int cyapa_i2c_resume(struct i2c_client *client) | 1600 static int cyapa_i2c_resume(struct i2c_client *client) |
| 2113 { | 1601 { |
| 2114 int ret; | 1602 int ret; |
| 2115 struct cyapa_i2c *touch = i2c_get_clientdata(client); | 1603 struct cyapa_i2c *touch = i2c_get_clientdata(client); |
| 2116 | 1604 |
| 1605 if (touch->platform_data->wakeup) { | |
| 1606 ret = touch->platform_data->wakeup(); | |
| 1607 if (ret) { | |
| 1608 dev_err(&client->dev, "%s: Error: wakeup failed: %d\n", | |
| 1609 __func__, ret); | |
| 1610 return ret; | |
| 1611 } | |
| 1612 } | |
| 1613 | |
| 2117 ret = cyapa_i2c_reset_config(touch); | 1614 ret = cyapa_i2c_reset_config(touch); |
| 2118 » DBGPRINTK(("%s: ... \n", __func__)); | 1615 » if (ret) { |
| 2119 » if (ret) | 1616 » » dev_err(&client->dev, "%s: Error: reset config failed: %d\n", |
| 1617 » » » __func__, ret); | |
| 2120 return ret; | 1618 return ret; |
| 1619 } | |
| 2121 | 1620 |
| 2122 » cyapa_i2c_reschedule_work(touch, msecs_to_jiffies(CYAPA_NO_DATA_SLEEP_MS ECS)); | 1621 » cyapa_i2c_reschedule_work(touch, |
| 1622 » » » msecs_to_jiffies(CYAPA_NO_DATA_SLEEP_MSECS)); | |
| 2123 | 1623 |
| 2124 return 0; | 1624 return 0; |
| 2125 } | 1625 } |
| 2126 #else | 1626 #else |
| 2127 #define cyapa_i2c_suspend NULL | 1627 #define cyapa_i2c_suspend NULL |
| 2128 #define cyapa_i2c_resume NULL | 1628 #define cyapa_i2c_resume NULL |
| 2129 #endif | 1629 #endif |
| 2130 | 1630 |
| 2131 static const struct i2c_device_id cypress_i2c_id_table[] = { | 1631 static const struct i2c_device_id cypress_i2c_id_table[] = { |
| 2132 { CYAPA_I2C_NAME, 0 }, | 1632 { CYAPA_I2C_NAME, 0 }, |
| 2133 { }, | 1633 { }, |
| 2134 }; | 1634 }; |
| 2135 MODULE_DEVICE_TABLE(i2c, cypress_i2c_id_table); | 1635 MODULE_DEVICE_TABLE(i2c, cypress_i2c_id_table); |
| 2136 | 1636 |
| 2137 static struct i2c_driver cypress_i2c_driver = { | 1637 static struct i2c_driver cypress_i2c_driver = { |
| 2138 .driver = { | 1638 .driver = { |
| 2139 » » .name» = CYAPA_I2C_NAME, | 1639 » » .name = CYAPA_I2C_NAME, |
| 2140 » » .owner» = THIS_MODULE, | 1640 » » .owner = THIS_MODULE, |
| 2141 }, | 1641 }, |
| 2142 | 1642 |
| 2143 » .probe» » = cyapa_i2c_probe, | 1643 » .probe = cyapa_i2c_probe, |
| 2144 » .remove»» = __devexit_p(cyapa_i2c_remove), | 1644 » .remove = __devexit_p(cyapa_i2c_remove), |
| 2145 | 1645 |
| 2146 .suspend = cyapa_i2c_suspend, | 1646 .suspend = cyapa_i2c_suspend, |
| 2147 » .resume»» = cyapa_i2c_resume, | 1647 » .resume = cyapa_i2c_resume, |
|
Daniel Kurtz
2011/05/01 23:44:09
align
| |
| 2148 .id_table = cypress_i2c_id_table, | 1648 .id_table = cypress_i2c_id_table, |
| 2149 }; | 1649 }; |
| 2150 | 1650 |
| 2151 static int __init cyapa_i2c_init(void) | 1651 static int __init cyapa_i2c_init(void) |
| 2152 { | 1652 { |
| 2153 » DBGPRINTK(("%s: start ... \n", __func__)); | 1653 » int ret; |
| 2154 » return i2c_add_driver(&cypress_i2c_driver); | 1654 |
| 1655 » printk(KERN_INFO | |
| 1656 » » "cypress_i2c: Initialize Cypress multi-touch trackpad.\n"); | |
|
Olof Johansson
2011/05/02 05:47:12
pr_info()
| |
| 1657 | |
| 1658 » ret = i2c_add_driver(&cypress_i2c_driver); | |
| 1659 » if (ret) { | |
| 1660 » » pr_err("ERROR: %s: cypress i2c driver register FAILED.\n", | |
| 1661 » » » __func__); | |
| 1662 » » return ret; | |
| 1663 » } | |
| 1664 | |
| 1665 » ret = cyapa_misc_init(); | |
| 1666 » if (ret) { | |
| 1667 » » i2c_del_driver(&cypress_i2c_driver); | |
| 1668 » » pr_err("ERROR: %s: cyapa misc device register FAILED.\n", | |
| 1669 » » » __func__); | |
| 1670 » » return ret; | |
| 1671 » } | |
| 1672 | |
| 1673 » return ret; | |
| 2155 } | 1674 } |
| 2156 | 1675 |
| 2157 static void __exit cyapa_i2c_exit(void) | 1676 static void __exit cyapa_i2c_exit(void) |
| 2158 { | 1677 { |
| 2159 » DBGPRINTK(("%s: exit ... \n", __func__)); | 1678 » cyapa_misc_exit(); |
| 1679 | |
| 2160 i2c_del_driver(&cypress_i2c_driver); | 1680 i2c_del_driver(&cypress_i2c_driver); |
| 1681 | |
| 1682 printk(KERN_INFO | |
| 1683 "cypress_i2c: Cypress multi-touch trackpad driver exited.\n"); | |
|
Olof Johansson
2011/05/02 05:47:12
pr_info().
| |
| 2161 } | 1684 } |
| 2162 | 1685 |
| 2163 module_init(cyapa_i2c_init); | 1686 module_init(cyapa_i2c_init); |
| 2164 module_exit(cyapa_i2c_exit); | 1687 module_exit(cyapa_i2c_exit); |
| 2165 | 1688 |
| 2166 MODULE_DESCRIPTION("Cypress I2C Trackpad Driver"); | 1689 MODULE_DESCRIPTION("Cypress I2C Trackpad Driver"); |
| 2167 MODULE_AUTHOR("Dudley Du <dudl@cypress.com>"); | 1690 MODULE_AUTHOR("Dudley Du <dudl@cypress.com>"); |
| 2168 MODULE_LICENSE("GPL"); | 1691 MODULE_LICENSE("GPL"); |
| 2169 | |
| OLD | NEW |