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 |