Input: bf54x-keys - fix typo in warning
[linux-2.6] / drivers / input / joystick / walkera0701.c
1 /*
2  *  Parallel port to Walkera WK-0701 TX joystick
3  *
4  *  Copyright (c) 2008 Peter Popovec
5  *
6  *  More about driver:  <file:Documentation/input/walkera0701.txt>
7  */
8
9 /*
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License version 2 as published by
12  * the Free Software Foundation.
13 */
14
15 /* #define WK0701_DEBUG */
16
17 #define RESERVE 20000
18 #define SYNC_PULSE 1306000
19 #define BIN0_PULSE 288000
20 #define BIN1_PULSE 438000
21
22 #define ANALOG_MIN_PULSE 318000
23 #define ANALOG_MAX_PULSE 878000
24 #define ANALOG_DELTA 80000
25
26 #define BIN_SAMPLE ((BIN0_PULSE + BIN1_PULSE) / 2)
27
28 #define NO_SYNC 25
29
30 #include <linux/kernel.h>
31 #include <linux/module.h>
32 #include <linux/parport.h>
33 #include <linux/input.h>
34 #include <linux/hrtimer.h>
35
36 MODULE_AUTHOR("Peter Popovec <popovec@fei.tuke.sk>");
37 MODULE_DESCRIPTION("Walkera WK-0701 TX as joystick");
38 MODULE_LICENSE("GPL");
39
40 static unsigned int walkera0701_pp_no;
41 module_param_named(port, walkera0701_pp_no, int, 0);
42 MODULE_PARM_DESC(port,
43                  "Parallel port adapter for Walkera WK-0701 TX (default is 0)");
44
45 /*
46  * For now, only one device is supported, if somebody need more devices, code
47  * can be expanded, one struct walkera_dev per device must be allocated and
48  * set up by walkera0701_connect (release of device by walkera0701_disconnect)
49  */
50
51 struct walkera_dev {
52         unsigned char buf[25];
53         u64 irq_time, irq_lasttime;
54         int counter;
55         int ack;
56
57         struct input_dev *input_dev;
58         struct hrtimer timer;
59
60         struct parport *parport;
61         struct pardevice *pardevice;
62 };
63
64 static struct walkera_dev w_dev;
65
66 static inline void walkera0701_parse_frame(struct walkera_dev *w)
67 {
68         int i;
69         int val1, val2, val3, val4, val5, val6, val7, val8;
70         int crc1, crc2;
71
72         for (crc1 = crc2 = i = 0; i < 10; i++) {
73                 crc1 += w->buf[i] & 7;
74                 crc2 += (w->buf[i] & 8) >> 3;
75         }
76         if ((w->buf[10] & 7) != (crc1 & 7))
77                 return;
78         if (((w->buf[10] & 8) >> 3) != (((crc1 >> 3) + crc2) & 1))
79                 return;
80         for (crc1 = crc2 = 0, i = 11; i < 23; i++) {
81                 crc1 += w->buf[i] & 7;
82                 crc2 += (w->buf[i] & 8) >> 3;
83         }
84         if ((w->buf[23] & 7) != (crc1 & 7))
85                 return;
86         if (((w->buf[23] & 8) >> 3) != (((crc1 >> 3) + crc2) & 1))
87                 return;
88         val1 = ((w->buf[0] & 7) * 256 + w->buf[1] * 16 + w->buf[2]) >> 2;
89         val1 *= ((w->buf[0] >> 2) & 2) - 1;     /* sign */
90         val2 = (w->buf[2] & 1) << 8 | (w->buf[3] << 4) | w->buf[4];
91         val2 *= (w->buf[2] & 2) - 1;    /* sign */
92         val3 = ((w->buf[5] & 7) * 256 + w->buf[6] * 16 + w->buf[7]) >> 2;
93         val3 *= ((w->buf[5] >> 2) & 2) - 1;     /* sign */
94         val4 = (w->buf[7] & 1) << 8 | (w->buf[8] << 4) | w->buf[9];
95         val4 *= (w->buf[7] & 2) - 1;    /* sign */
96         val5 = ((w->buf[11] & 7) * 256 + w->buf[12] * 16 + w->buf[13]) >> 2;
97         val5 *= ((w->buf[11] >> 2) & 2) - 1;    /* sign */
98         val6 = (w->buf[13] & 1) << 8 | (w->buf[14] << 4) | w->buf[15];
99         val6 *= (w->buf[13] & 2) - 1;   /* sign */
100         val7 = ((w->buf[16] & 7) * 256 + w->buf[17] * 16 + w->buf[18]) >> 2;
101         val7 *= ((w->buf[16] >> 2) & 2) - 1;    /*sign */
102         val8 = (w->buf[18] & 1) << 8 | (w->buf[19] << 4) | w->buf[20];
103         val8 *= (w->buf[18] & 2) - 1;   /*sign */
104
105 #ifdef WK0701_DEBUG
106         {
107                 int magic, magic_bit;
108                 magic = (w->buf[21] << 4) | w->buf[22];
109                 magic_bit = (w->buf[24] & 8) >> 3;
110                 printk(KERN_DEBUG
111                        "walkera0701: %4d %4d %4d %4d  %4d %4d %4d %4d (magic %2x %d)\n",
112                        val1, val2, val3, val4, val5, val6, val7, val8, magic,
113                        magic_bit);
114         }
115 #endif
116         input_report_abs(w->input_dev, ABS_X, val2);
117         input_report_abs(w->input_dev, ABS_Y, val1);
118         input_report_abs(w->input_dev, ABS_Z, val6);
119         input_report_abs(w->input_dev, ABS_THROTTLE, val3);
120         input_report_abs(w->input_dev, ABS_RUDDER, val4);
121         input_report_abs(w->input_dev, ABS_MISC, val7);
122         input_report_key(w->input_dev, BTN_GEAR_DOWN, val5 > 0);
123 }
124
125 static inline int read_ack(struct pardevice *p)
126 {
127         return parport_read_status(p->port) & 0x40;
128 }
129
130 /* falling edge, prepare to BIN value calculation */
131 static void walkera0701_irq_handler(void *handler_data)
132 {
133         u64 pulse_time;
134         struct walkera_dev *w = handler_data;
135
136         w->irq_time = ktime_to_ns(ktime_get());
137         pulse_time = w->irq_time - w->irq_lasttime;
138         w->irq_lasttime = w->irq_time;
139
140         /* cancel timer, if in handler or active do resync */
141         if (unlikely(0 != hrtimer_try_to_cancel(&w->timer))) {
142                 w->counter = NO_SYNC;
143                 return;
144         }
145
146         if (w->counter < NO_SYNC) {
147                 if (w->ack) {
148                         pulse_time -= BIN1_PULSE;
149                         w->buf[w->counter] = 8;
150                 } else {
151                         pulse_time -= BIN0_PULSE;
152                         w->buf[w->counter] = 0;
153                 }
154                 if (w->counter == 24) { /* full frame */
155                         walkera0701_parse_frame(w);
156                         w->counter = NO_SYNC;
157                         if (abs(pulse_time - SYNC_PULSE) < RESERVE)     /* new frame sync */
158                                 w->counter = 0;
159                 } else {
160                         if ((pulse_time > (ANALOG_MIN_PULSE - RESERVE)
161                              && (pulse_time < (ANALOG_MAX_PULSE + RESERVE)))) {
162                                 pulse_time -= (ANALOG_MIN_PULSE - RESERVE);
163                                 pulse_time = (u32) pulse_time / ANALOG_DELTA;   /* overtiping is safe, pulsetime < s32.. */
164                                 w->buf[w->counter++] |= (pulse_time & 7);
165                         } else
166                                 w->counter = NO_SYNC;
167                 }
168         } else if (abs(pulse_time - SYNC_PULSE - BIN0_PULSE) <
169                                 RESERVE + BIN1_PULSE - BIN0_PULSE)      /* frame sync .. */
170                 w->counter = 0;
171
172         hrtimer_start(&w->timer, ktime_set(0, BIN_SAMPLE), HRTIMER_MODE_REL);
173 }
174
175 static enum hrtimer_restart timer_handler(struct hrtimer
176                                           *handle)
177 {
178         struct walkera_dev *w;
179
180         w = container_of(handle, struct walkera_dev, timer);
181         w->ack = read_ack(w->pardevice);
182
183         return HRTIMER_NORESTART;
184 }
185
186 static int walkera0701_open(struct input_dev *dev)
187 {
188         struct walkera_dev *w = input_get_drvdata(dev);
189
190         parport_enable_irq(w->parport);
191         return 0;
192 }
193
194 static void walkera0701_close(struct input_dev *dev)
195 {
196         struct walkera_dev *w = input_get_drvdata(dev);
197
198         parport_disable_irq(w->parport);
199 }
200
201 static int walkera0701_connect(struct walkera_dev *w, int parport)
202 {
203         int err = -ENODEV;
204
205         w->parport = parport_find_number(parport);
206         if (w->parport == NULL)
207                 return -ENODEV;
208
209         if (w->parport->irq == -1) {
210                 printk(KERN_ERR "walkera0701: parport without interrupt\n");
211                 goto init_err;
212         }
213
214         err = -EBUSY;
215         w->pardevice = parport_register_device(w->parport, "walkera0701",
216                                     NULL, NULL, walkera0701_irq_handler,
217                                     PARPORT_DEV_EXCL, w);
218         if (!w->pardevice)
219                 goto init_err;
220
221         if (parport_negotiate(w->pardevice->port, IEEE1284_MODE_COMPAT))
222                 goto init_err1;
223
224         if (parport_claim(w->pardevice))
225                 goto init_err1;
226
227         w->input_dev = input_allocate_device();
228         if (!w->input_dev)
229                 goto init_err2;
230
231         input_set_drvdata(w->input_dev, w);
232         w->input_dev->name = "Walkera WK-0701 TX";
233         w->input_dev->phys = w->parport->name;
234         w->input_dev->id.bustype = BUS_PARPORT;
235
236         /* TODO what id vendor/product/version ? */
237         w->input_dev->id.vendor = 0x0001;
238         w->input_dev->id.product = 0x0001;
239         w->input_dev->id.version = 0x0100;
240         w->input_dev->open = walkera0701_open;
241         w->input_dev->close = walkera0701_close;
242
243         w->input_dev->evbit[0] = BIT(EV_ABS) | BIT_MASK(EV_KEY);
244         w->input_dev->keybit[BIT_WORD(BTN_GEAR_DOWN)] = BIT_MASK(BTN_GEAR_DOWN);
245
246         input_set_abs_params(w->input_dev, ABS_X, -512, 512, 0, 0);
247         input_set_abs_params(w->input_dev, ABS_Y, -512, 512, 0, 0);
248         input_set_abs_params(w->input_dev, ABS_Z, -512, 512, 0, 0);
249         input_set_abs_params(w->input_dev, ABS_THROTTLE, -512, 512, 0, 0);
250         input_set_abs_params(w->input_dev, ABS_RUDDER, -512, 512, 0, 0);
251         input_set_abs_params(w->input_dev, ABS_MISC, -512, 512, 0, 0);
252
253         err = input_register_device(w->input_dev);
254         if (err)
255                 goto init_err3;
256
257         hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
258         w->timer.function = timer_handler;
259         return 0;
260
261  init_err3:
262         input_free_device(w->input_dev);
263  init_err2:
264         parport_release(w->pardevice);
265  init_err1:
266         parport_unregister_device(w->pardevice);
267  init_err:
268         parport_put_port(w->parport);
269         return err;
270 }
271
272 static void walkera0701_disconnect(struct walkera_dev *w)
273 {
274         hrtimer_cancel(&w->timer);
275         input_unregister_device(w->input_dev);
276         parport_release(w->pardevice);
277         parport_unregister_device(w->pardevice);
278         parport_put_port(w->parport);
279 }
280
281 static int __init walkera0701_init(void)
282 {
283         return walkera0701_connect(&w_dev, walkera0701_pp_no);
284 }
285
286 static void __exit walkera0701_exit(void)
287 {
288         walkera0701_disconnect(&w_dev);
289 }
290
291 module_init(walkera0701_init);
292 module_exit(walkera0701_exit);