import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / uibc / uibc.c
1 #define pr_fmt(fmt) "["KBUILD_MODNAME"]" fmt
2 #include <linux/printk.h>
3 #include <linux/init.h>
4 #include <linux/module.h>
5 #include <linux/kernel.h>
6 #include <linux/input.h>
7 #include <linux/workqueue.h>
8 #include <linux/timer.h>
9 #include <linux/interrupt.h>
10 #include <linux/fs.h>
11 #include <linux/miscdevice.h>
12 #include <linux/platform_device.h>
13 #include <linux/earlysuspend.h>
14 #include <linux/slab.h>
15
16 #include <linux/device.h>
17 #include <linux/errno.h>
18 #include <asm/atomic.h>
19 #include <asm/uaccess.h>
20 #include <linux/input/mt.h>
21 #include <linux/version.h>
22 #include <linux/slab.h>
23
24 #define UIBC_TAG "UIBC:"
25 #define MAX_POINTERS 5
26
27 #define idVal(_x) (_x * 3 + 1)
28 #define xVal(_x) (_x * 3 + 2)
29 #define yVal(_x) (_x * 3 + 3)
30
31 extern unsigned int DISP_GetScreenHeight(void);
32 extern unsigned int DISP_GetScreenWidth(void);
33
34 static unsigned short uibc_keycode[256] = {
35 KEY_RESERVED,
36 BTN_LEFT,
37 BTN_TOUCH,
38 KEY_BACKSPACE,
39 KEY_TAB,
40 KEY_LINEFEED,
41 KEY_PAGEDOWN,
42 KEY_ENTER,
43 KEY_LEFTSHIFT,
44 KEY_LEFTCTRL,
45 KEY_CANCEL,
46 KEY_BACK,
47 KEY_DELETE,
48 KEY_HOME,
49 KEY_VOLUMEDOWN,
50 KEY_VOLUMEUP,
51 };
52
53 static unsigned short uibc_keycode_chars[256] = {
54 KEY_A,
55 KEY_B,
56 KEY_C,
57 KEY_D,
58 KEY_E,
59 KEY_F,
60 KEY_G,
61 KEY_H,
62 KEY_I,
63 KEY_J,
64 KEY_K,
65 KEY_L,
66 KEY_M,
67 KEY_N,
68 KEY_O,
69 KEY_P,
70 KEY_Q,
71 KEY_R,
72 KEY_S,
73 KEY_T,
74 KEY_U,
75 KEY_V,
76 KEY_W,
77 KEY_X,
78 KEY_Y,
79 KEY_Z,
80 KEY_RESERVED,
81 BTN_LEFT,
82 BTN_TOUCH,
83 KEY_BACKSPACE,
84 KEY_TAB,
85 KEY_LINEFEED,
86 KEY_PAGEDOWN,
87 KEY_ENTER,
88 KEY_LEFTSHIFT,
89 KEY_LEFTCTRL,
90 KEY_CANCEL,
91 KEY_BACK,
92 KEY_DELETE,
93 };
94
95
96 #define UIBC_KBD_NAME "uibc"
97 #define UIBC_KEY_PRESS 1
98 #define UIBC_KEY_RELEASE 0
99 #define UIBC_KEY_RESERVE 2
100 #define UIBC_POINTER_X 3
101 #define UIBC_POINTER_Y 4
102 #define UIBC_KEYBOARD 5
103 #define UIBC_MOUSE 6
104 #define UIBC_TOUCH_DOWN 7
105 #define UIBC_TOUCH_UP 8
106 #define UIBC_TOUCH_MOVE 9
107 #define UIBC_KEYBOARD_MIRACAST 10
108
109 #define UIBC_MOUSE_INDEX 0
110 #define UIBC_GAMEPAD_INDEX 151
111
112
113 static struct input_dev *uibc_input_dev;
114
115 struct uibckeyboard {
116 struct input_dev *input;
117 unsigned short keymap[ARRAY_SIZE(uibc_keycode)];
118 };
119
120 struct uibckeyboard *uibckbd;
121 int uibc_registered = 0;
122
123 #ifdef CONFIG_COMPAT
124 static long uibc_compat_kbd_dev_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg) {
125 long ret = 0;
126
127 if (!pfile->f_op || !pfile->f_op->unlocked_ioctl) {
128 pr_debug("uibc_compat_kbd_dev_ioctl null pointer");
129 return -ENOTTY;
130 }
131
132 switch (cmd) {
133 case UIBC_KEYBOARD:
134 case UIBC_KEYBOARD_MIRACAST:
135 case UIBC_KEY_PRESS:
136 case UIBC_KEY_RELEASE:
137 case UIBC_POINTER_X:
138 case UIBC_POINTER_Y:
139 case UIBC_TOUCH_DOWN:
140 case UIBC_TOUCH_UP:
141 case UIBC_TOUCH_MOVE: {
142 ret = pfile->f_op->unlocked_ioctl(pfile, cmd, (unsigned long)compat_ptr(arg));
143 break;
144 }
145 default:
146 return -EINVAL;
147 }
148 return ret;
149 }
150 #endif
151
152 static long uibc_kbd_dev_ioctl(struct file * file, unsigned int cmd, unsigned long arg) {
153 void __user *uarg = (void __user *)arg;
154 static short XValue;
155 static short YValue;
156 short keycode;
157 short touchPosition[16];
158 int err, i;
159
160 pr_debug("uibc_kbd_dev_ioctl,cmd=%d\n", cmd);
161 switch (cmd) {
162 case UIBC_KEYBOARD: {
163 uibc_input_dev->keycodemax = ARRAY_SIZE(uibc_keycode);
164 for (i = 0; i < ARRAY_SIZE(uibckbd->keymap); i++)
165 __set_bit(uibckbd->keymap[i], uibc_input_dev->keybit);
166 err = input_register_device(uibc_input_dev);
167 if (err) {
168 pr_err("register input device failed (%d)\n", err);
169 input_free_device(uibc_input_dev);
170 return err;
171 }
172 uibc_registered = 1;
173 break;
174 }
175 case UIBC_KEYBOARD_MIRACAST: {
176 uibc_input_dev->keycodemax = ARRAY_SIZE(uibc_keycode_chars);
177 for (i = 0; i < ARRAY_SIZE(uibc_keycode_chars); i++)
178 __set_bit(uibc_keycode_chars[i], uibc_input_dev->keybit);
179 err = input_register_device(uibc_input_dev);
180 if (err) {
181 pr_err("register input device failed (%d)\n", err);
182 input_free_device(uibc_input_dev);
183 return err;
184 }
185 uibc_registered = 1;
186 break;
187 }
188 case UIBC_KEY_PRESS: {
189 if (copy_from_user(&keycode, uarg, sizeof(keycode)))
190 return -EFAULT;
191 pr_debug("uibc keycode %d\n", keycode);
192 input_report_key(uibc_input_dev, keycode, 1);
193 input_sync(uibc_input_dev);
194 break;
195 }
196 case UIBC_KEY_RELEASE: {
197 if (copy_from_user(&keycode, uarg, sizeof(keycode)))
198 return -EFAULT;
199 input_report_key(uibc_input_dev, keycode, 0);
200 input_sync(uibc_input_dev);
201 break;
202 }
203 case UIBC_POINTER_X: {
204 if (copy_from_user(&XValue, uarg, sizeof(XValue)))
205 return -EFAULT;
206 pr_debug("uibc pointer X %d\n", XValue);
207 break;
208 }
209 case UIBC_POINTER_Y: {
210 if (copy_from_user(&YValue, uarg, sizeof(YValue)))
211 return -EFAULT;
212 pr_debug("uibc pointer Y %d\n", YValue);
213 input_report_rel(uibc_input_dev, REL_X, XValue);
214 input_report_rel(uibc_input_dev, REL_Y, YValue);
215 input_sync(uibc_input_dev);
216 XValue = 0;
217 YValue = 0;
218 break;
219 }
220 case UIBC_TOUCH_DOWN: {
221 if (copy_from_user(&touchPosition, uarg, sizeof(touchPosition)))
222 return -EFAULT;
223 pr_debug("uibc UIBC_TOUCH_DOWN id=%d,(%d,%d)\n",
224 touchPosition[idVal(0)],
225 touchPosition[xVal(0)], touchPosition[yVal(0)]);
226 input_report_key(uibc_input_dev, BTN_TOUCH, 1);
227 input_report_abs(uibc_input_dev,
228 ABS_MT_TRACKING_ID, touchPosition[idVal(0)]);
229 input_report_abs(uibc_input_dev, ABS_MT_POSITION_X, touchPosition[xVal(0)]);
230 input_report_abs(uibc_input_dev, ABS_MT_POSITION_Y, touchPosition[yVal(0)]);
231 input_mt_sync(uibc_input_dev);
232 input_sync(uibc_input_dev);
233 break;
234 }
235 case UIBC_TOUCH_UP: {
236 if (copy_from_user(&touchPosition, uarg, sizeof(touchPosition)))
237 return -EFAULT;
238 pr_debug("uibc UIBC_TOUCH_UP");
239 input_report_key(uibc_input_dev, BTN_TOUCH, 0);
240 input_sync(uibc_input_dev);
241 break;
242 }
243 case UIBC_TOUCH_MOVE: {
244 if (copy_from_user(&touchPosition, uarg, sizeof(touchPosition)))
245 return -EFAULT;
246 for (i = 0; i < MAX_POINTERS; i++) {
247 if (touchPosition[xVal(i)] == 0 && touchPosition[yVal(i)] == 0)
248 continue;
249 input_report_abs(uibc_input_dev,
250 ABS_MT_TRACKING_ID, touchPosition[idVal(i)]);
251 input_report_abs(uibc_input_dev,
252 ABS_MT_POSITION_X, touchPosition[xVal(i)]);
253 input_report_abs(uibc_input_dev,
254 ABS_MT_POSITION_Y, touchPosition[yVal(i)]);
255 input_mt_sync(uibc_input_dev);
256 }
257 input_sync(uibc_input_dev);
258 break;
259 }
260 default:
261 return -EINVAL;
262 }
263 return 0;
264 }
265
266 static int uibc_kbd_dev_open(struct inode * inode, struct file * file) {
267 int TPD_RES_X, TPD_RES_Y;
268
269 pr_debug("*** uibckeyboard uibc_kbd_dev_open ***\n");
270
271 #ifdef LCM_ROTATE
272 TPD_RES_Y = DISP_GetScreenWidth();
273 TPD_RES_X = DISP_GetScreenHeight();
274 #else
275 TPD_RES_X = DISP_GetScreenWidth();
276 TPD_RES_Y = DISP_GetScreenHeight();
277 #endif
278
279 uibckbd = kzalloc(sizeof(struct uibckeyboard), GFP_KERNEL);
280 uibc_input_dev = input_allocate_device();
281 if (!uibckbd || !uibc_input_dev)
282 goto fail;
283
284 memcpy(uibckbd->keymap, uibc_keycode, sizeof(uibc_keycode));
285 uibckbd->input = uibc_input_dev;
286
287 set_bit(INPUT_PROP_DIRECT, uibc_input_dev->propbit);
288
289 set_bit(EV_ABS, uibc_input_dev->evbit);
290 set_bit(EV_KEY, uibc_input_dev->evbit);
291 set_bit(EV_REL, uibc_input_dev->evbit);
292
293 set_bit(REL_X, uibc_input_dev->relbit);
294 set_bit(REL_Y, uibc_input_dev->relbit);
295
296 set_bit(ABS_X, uibc_input_dev->absbit);
297 set_bit(ABS_Y, uibc_input_dev->absbit);
298 set_bit(ABS_MT_TRACKING_ID, uibc_input_dev->absbit);
299 set_bit(ABS_MT_POSITION_X, uibc_input_dev->absbit);
300 set_bit(ABS_MT_POSITION_Y, uibc_input_dev->absbit);
301
302 input_set_abs_params(uibc_input_dev, ABS_MT_POSITION_X, 0, TPD_RES_X, 0, 0);
303 input_set_abs_params(uibc_input_dev, ABS_MT_POSITION_Y, 0, TPD_RES_Y, 0, 0);
304 input_set_abs_params(uibc_input_dev, ABS_X, 0, TPD_RES_X, 0, 0);
305 input_set_abs_params(uibc_input_dev, ABS_Y, 0, TPD_RES_Y, 0, 0);
306
307 input_abs_set_res(uibc_input_dev, ABS_X, TPD_RES_X);
308 input_abs_set_res(uibc_input_dev, ABS_Y, TPD_RES_Y);
309
310 uibc_input_dev->name = UIBC_KBD_NAME;
311 uibc_input_dev->keycode = uibckbd->keymap;
312 uibc_input_dev->keycodesize = sizeof(unsigned short);
313 uibc_input_dev->id.bustype = BUS_HOST;
314
315 return 0;
316 fail:
317 input_free_device(uibc_input_dev);
318 kfree(uibckbd);
319
320 return -EINVAL;
321 }
322
323 static int uibc_kbd_dev_release(struct inode * inode, struct file * file) {
324 pr_debug("*** uibckeyboard uibc_kbd_dev_release ***\n");
325 if (uibc_registered == 1) {
326 input_unregister_device(uibc_input_dev);
327 uibc_registered = 0;
328 }
329 return 0;
330 }
331
332
333 static struct file_operations uibc_kbd_dev_fops = {
334 .owner = THIS_MODULE,
335 .unlocked_ioctl = uibc_kbd_dev_ioctl,
336 #ifdef CONFIG_COMPAT
337 .compat_ioctl = uibc_compat_kbd_dev_ioctl,
338 #endif
339 .open = uibc_kbd_dev_open,
340 .release = uibc_kbd_dev_release
341 };
342
343 static struct miscdevice uibc_kbd_dev = {
344 .minor = MISC_DYNAMIC_MINOR,
345 .name = UIBC_KBD_NAME,
346 .fops = &uibc_kbd_dev_fops,
347 };
348
349
350 static int uibc_keyboard_probe(struct platform_device * pdev) {
351
352 int i, err;
353
354 pr_debug("*** uibckeyboard probe ***\n");
355
356 uibckbd = kzalloc(sizeof(struct uibckeyboard), GFP_KERNEL);
357 uibc_input_dev = input_allocate_device();
358 if (!uibckbd || !uibc_input_dev)
359 goto fail;
360
361 memcpy(uibckbd->keymap, uibc_keycode, sizeof(uibc_keycode));
362 uibckbd->input = uibc_input_dev;
363 __set_bit(EV_KEY, uibc_input_dev->evbit);
364 platform_set_drvdata(pdev, uibckbd);
365
366 uibc_input_dev->name = UIBC_KBD_NAME;
367 uibc_input_dev->keycode = uibckbd->keymap;
368 uibc_input_dev->keycodesize = sizeof(unsigned short);
369 uibc_input_dev->keycodemax = ARRAY_SIZE(uibc_keycode);
370 uibc_input_dev->id.bustype = BUS_HOST;
371 uibc_input_dev->dev.parent = &pdev->dev;
372
373
374 for (i = 0; i < ARRAY_SIZE(uibckbd->keymap); i++)
375 __set_bit(uibckbd->keymap[i], uibc_input_dev->keybit);
376
377 input_set_capability(uibc_input_dev, EV_MSC, MSC_SCAN);
378
379 uibc_kbd_dev.parent = &pdev->dev;
380 err = misc_register(&uibc_kbd_dev);
381 if (err) {
382 pr_err("register device failed (%d)\n", err);
383 return err;
384 }
385
386 return 0;
387
388 fail:
389 platform_set_drvdata(pdev, NULL);
390 input_free_device(uibc_input_dev);
391 kfree(uibckbd);
392
393 return -EINVAL;
394 }
395
396 static const struct of_device_id uibc_of_ids[] = {
397 { .compatible = "mediatek,uibc", },
398 {}
399 };
400
401 static struct platform_driver uibc_keyboard_driver = {
402 .probe = uibc_keyboard_probe,
403 .driver = {
404 .name = UIBC_KBD_NAME,
405 .of_match_table = uibc_of_ids,
406 },
407 };
408
409
410 static int uibc_keyboard_init(void) {
411 pr_debug("uibc_keyboard_init OK\n");
412
413 return platform_driver_register(&uibc_keyboard_driver);
414 }
415
416
417 static void __exit uibc_keyboard_exit(void) {
418 }
419 module_init(uibc_keyboard_init);
420 module_exit(uibc_keyboard_exit);
421
422 MODULE_DESCRIPTION("uibc keyboard Device");
423 MODULE_LICENSE("GPL");