Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(694)

Side by Side Diff: drivers/input/mouse/cypress_i2c.c

Issue 6905092: cyapa: support MT-A protocol, and add cyapa_misc_dev interface Base URL: http://git.chromium.org/git/kernel-next.git@chromeos-2.6.38
Patch Set: Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | include/linux/cyapa.h » ('j') | include/linux/cyapa.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 = &reg_data->gen1_data; 1017 data_gen1 = &reg_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 = &reg_data->gen2_data; 1025 data_gen2 = &reg_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(&reg_data, 0, sizeof(union cyapa_reg_data)); 1201 memset(&reg_data, 0, sizeof(union cyapa_reg_data));
1529 1202
1530 /* read register data from trackpad. */ 1203 /* read register data from trackpad. */
1531 gen1_data = &reg_data.gen1_data; 1204 gen1_data = &reg_data.gen1_data;
1532 gen2_data = &reg_data.gen2_data; 1205 gen2_data = &reg_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 *)&reg_data); 1217 (u8 *)&reg_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, &reg_data)) { 1224 if (cyapa_verify_data_device(touch, &reg_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
OLDNEW
« no previous file with comments | « no previous file | include/linux/cyapa.h » ('j') | include/linux/cyapa.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698