1 // SPDX-License-Identifier: GPL-2.0-only
3 * Parallel port to Walkera WK-0701 TX joystick
5 * Copyright (c) 2008 Peter Popovec
7 * More about driver: <file:Documentation/input/devices/walkera0701.rst>
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14 #define SYNC_PULSE 1306000
15 #define BIN0_PULSE 288000
16 #define BIN1_PULSE 438000
18 #define ANALOG_MIN_PULSE 318000
19 #define ANALOG_MAX_PULSE 878000
20 #define ANALOG_DELTA 80000
22 #define BIN_SAMPLE ((BIN0_PULSE + BIN1_PULSE) / 2)
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/parport.h>
29 #include <linux/input.h>
30 #include <linux/hrtimer.h>
32 MODULE_AUTHOR("Peter Popovec <popovec@fei.tuke.sk>");
33 MODULE_DESCRIPTION("Walkera WK-0701 TX as joystick");
34 MODULE_LICENSE("GPL");
36 static unsigned int walkera0701_pp_no
;
37 module_param_named(port
, walkera0701_pp_no
, int, 0);
38 MODULE_PARM_DESC(port
,
39 "Parallel port adapter for Walkera WK-0701 TX (default is 0)");
42 * For now, only one device is supported, if somebody need more devices, code
43 * can be expanded, one struct walkera_dev per device must be allocated and
44 * set up by walkera0701_connect (release of device by walkera0701_disconnect)
48 unsigned char buf
[25];
49 u64 irq_time
, irq_lasttime
;
53 struct input_dev
*input_dev
;
56 struct parport
*parport
;
57 struct pardevice
*pardevice
;
60 static struct walkera_dev w_dev
;
62 static inline void walkera0701_parse_frame(struct walkera_dev
*w
)
65 int val1
, val2
, val3
, val4
, val5
, val6
, val7
, val8
;
69 for (crc1
= crc2
= i
= 0; i
< 10; i
++) {
70 crc1
+= w
->buf
[i
] & 7;
71 crc2
+= (w
->buf
[i
] & 8) >> 3;
73 if ((w
->buf
[10] & 7) != (crc1
& 7))
75 if (((w
->buf
[10] & 8) >> 3) != (((crc1
>> 3) + crc2
) & 1))
77 for (crc1
= crc2
= 0, i
= 11; i
< 23; i
++) {
78 crc1
+= w
->buf
[i
] & 7;
79 crc2
+= (w
->buf
[i
] & 8) >> 3;
81 if ((w
->buf
[23] & 7) != (crc1
& 7))
83 if (((w
->buf
[23] & 8) >> 3) != (((crc1
>> 3) + crc2
) & 1))
85 val1
= ((w
->buf
[0] & 7) * 256 + w
->buf
[1] * 16 + w
->buf
[2]) >> 2;
86 val1
*= ((w
->buf
[0] >> 2) & 2) - 1; /* sign */
87 val2
= (w
->buf
[2] & 1) << 8 | (w
->buf
[3] << 4) | w
->buf
[4];
88 val2
*= (w
->buf
[2] & 2) - 1; /* sign */
89 val3
= ((w
->buf
[5] & 7) * 256 + w
->buf
[6] * 16 + w
->buf
[7]) >> 2;
90 val3
*= ((w
->buf
[5] >> 2) & 2) - 1; /* sign */
91 val4
= (w
->buf
[7] & 1) << 8 | (w
->buf
[8] << 4) | w
->buf
[9];
92 val4
*= (w
->buf
[7] & 2) - 1; /* sign */
93 val5
= ((w
->buf
[11] & 7) * 256 + w
->buf
[12] * 16 + w
->buf
[13]) >> 2;
94 val5
*= ((w
->buf
[11] >> 2) & 2) - 1; /* sign */
95 val6
= (w
->buf
[13] & 1) << 8 | (w
->buf
[14] << 4) | w
->buf
[15];
96 val6
*= (w
->buf
[13] & 2) - 1; /* sign */
97 val7
= ((w
->buf
[16] & 7) * 256 + w
->buf
[17] * 16 + w
->buf
[18]) >> 2;
98 val7
*= ((w
->buf
[16] >> 2) & 2) - 1; /*sign */
99 val8
= (w
->buf
[18] & 1) << 8 | (w
->buf
[19] << 4) | w
->buf
[20];
100 val8
*= (w
->buf
[18] & 2) - 1; /*sign */
102 magic
= (w
->buf
[21] << 4) | w
->buf
[22];
103 magic_bit
= (w
->buf
[24] & 8) >> 3;
104 pr_debug("%4d %4d %4d %4d %4d %4d %4d %4d (magic %2x %d)\n",
105 val1
, val2
, val3
, val4
, val5
, val6
, val7
, val8
,
108 input_report_abs(w
->input_dev
, ABS_X
, val2
);
109 input_report_abs(w
->input_dev
, ABS_Y
, val1
);
110 input_report_abs(w
->input_dev
, ABS_Z
, val6
);
111 input_report_abs(w
->input_dev
, ABS_THROTTLE
, val3
);
112 input_report_abs(w
->input_dev
, ABS_RUDDER
, val4
);
113 input_report_abs(w
->input_dev
, ABS_MISC
, val7
);
114 input_report_key(w
->input_dev
, BTN_GEAR_DOWN
, val5
> 0);
117 static inline int read_ack(struct pardevice
*p
)
119 return parport_read_status(p
->port
) & 0x40;
122 /* falling edge, prepare to BIN value calculation */
123 static void walkera0701_irq_handler(void *handler_data
)
126 struct walkera_dev
*w
= handler_data
;
128 w
->irq_time
= ktime_to_ns(ktime_get());
129 pulse_time
= w
->irq_time
- w
->irq_lasttime
;
130 w
->irq_lasttime
= w
->irq_time
;
132 /* cancel timer, if in handler or active do resync */
133 if (unlikely(0 != hrtimer_try_to_cancel(&w
->timer
))) {
134 w
->counter
= NO_SYNC
;
138 if (w
->counter
< NO_SYNC
) {
140 pulse_time
-= BIN1_PULSE
;
141 w
->buf
[w
->counter
] = 8;
143 pulse_time
-= BIN0_PULSE
;
144 w
->buf
[w
->counter
] = 0;
146 if (w
->counter
== 24) { /* full frame */
147 walkera0701_parse_frame(w
);
148 w
->counter
= NO_SYNC
;
149 if (abs(pulse_time
- SYNC_PULSE
) < RESERVE
) /* new frame sync */
152 if ((pulse_time
> (ANALOG_MIN_PULSE
- RESERVE
)
153 && (pulse_time
< (ANALOG_MAX_PULSE
+ RESERVE
)))) {
154 pulse_time
-= (ANALOG_MIN_PULSE
- RESERVE
);
155 pulse_time
= (u32
) pulse_time
/ ANALOG_DELTA
; /* overtiping is safe, pulsetime < s32.. */
156 w
->buf
[w
->counter
++] |= (pulse_time
& 7);
158 w
->counter
= NO_SYNC
;
160 } else if (abs(pulse_time
- SYNC_PULSE
- BIN0_PULSE
) <
161 RESERVE
+ BIN1_PULSE
- BIN0_PULSE
) /* frame sync .. */
164 hrtimer_start(&w
->timer
, BIN_SAMPLE
, HRTIMER_MODE_REL
);
167 static enum hrtimer_restart
timer_handler(struct hrtimer
170 struct walkera_dev
*w
;
172 w
= container_of(handle
, struct walkera_dev
, timer
);
173 w
->ack
= read_ack(w
->pardevice
);
175 return HRTIMER_NORESTART
;
178 static int walkera0701_open(struct input_dev
*dev
)
180 struct walkera_dev
*w
= input_get_drvdata(dev
);
182 if (parport_claim(w
->pardevice
))
185 parport_enable_irq(w
->parport
);
189 static void walkera0701_close(struct input_dev
*dev
)
191 struct walkera_dev
*w
= input_get_drvdata(dev
);
193 parport_disable_irq(w
->parport
);
194 hrtimer_cancel(&w
->timer
);
196 parport_release(w
->pardevice
);
199 static void walkera0701_attach(struct parport
*pp
)
201 struct pardev_cb walkera0701_parport_cb
;
202 struct walkera_dev
*w
= &w_dev
;
204 if (pp
->number
!= walkera0701_pp_no
) {
205 pr_debug("Not using parport%d.\n", pp
->number
);
210 pr_err("parport %d does not have interrupt assigned\n",
217 memset(&walkera0701_parport_cb
, 0, sizeof(walkera0701_parport_cb
));
218 walkera0701_parport_cb
.flags
= PARPORT_FLAG_EXCL
;
219 walkera0701_parport_cb
.irq_func
= walkera0701_irq_handler
;
220 walkera0701_parport_cb
.private = w
;
222 w
->pardevice
= parport_register_dev_model(pp
, "walkera0701",
223 &walkera0701_parport_cb
, 0);
226 pr_err("failed to register parport device\n");
230 if (parport_negotiate(w
->pardevice
->port
, IEEE1284_MODE_COMPAT
)) {
231 pr_err("failed to negotiate parport mode\n");
232 goto err_unregister_device
;
235 hrtimer_init(&w
->timer
, CLOCK_MONOTONIC
, HRTIMER_MODE_REL
);
236 w
->timer
.function
= timer_handler
;
238 w
->input_dev
= input_allocate_device();
240 pr_err("failed to allocate input device\n");
241 goto err_unregister_device
;
244 input_set_drvdata(w
->input_dev
, w
);
245 w
->input_dev
->name
= "Walkera WK-0701 TX";
246 w
->input_dev
->phys
= w
->parport
->name
;
247 w
->input_dev
->id
.bustype
= BUS_PARPORT
;
249 /* TODO what id vendor/product/version ? */
250 w
->input_dev
->id
.vendor
= 0x0001;
251 w
->input_dev
->id
.product
= 0x0001;
252 w
->input_dev
->id
.version
= 0x0100;
253 w
->input_dev
->dev
.parent
= w
->parport
->dev
;
254 w
->input_dev
->open
= walkera0701_open
;
255 w
->input_dev
->close
= walkera0701_close
;
257 w
->input_dev
->evbit
[0] = BIT(EV_ABS
) | BIT_MASK(EV_KEY
);
258 w
->input_dev
->keybit
[BIT_WORD(BTN_GEAR_DOWN
)] = BIT_MASK(BTN_GEAR_DOWN
);
260 input_set_abs_params(w
->input_dev
, ABS_X
, -512, 512, 0, 0);
261 input_set_abs_params(w
->input_dev
, ABS_Y
, -512, 512, 0, 0);
262 input_set_abs_params(w
->input_dev
, ABS_Z
, -512, 512, 0, 0);
263 input_set_abs_params(w
->input_dev
, ABS_THROTTLE
, -512, 512, 0, 0);
264 input_set_abs_params(w
->input_dev
, ABS_RUDDER
, -512, 512, 0, 0);
265 input_set_abs_params(w
->input_dev
, ABS_MISC
, -512, 512, 0, 0);
267 if (input_register_device(w
->input_dev
)) {
268 pr_err("failed to register input device\n");
269 goto err_free_input_dev
;
275 input_free_device(w
->input_dev
);
276 err_unregister_device
:
277 parport_unregister_device(w
->pardevice
);
280 static void walkera0701_detach(struct parport
*port
)
282 struct walkera_dev
*w
= &w_dev
;
284 if (!w
->pardevice
|| w
->parport
->number
!= port
->number
)
287 input_unregister_device(w
->input_dev
);
288 parport_unregister_device(w
->pardevice
);
292 static struct parport_driver walkera0701_parport_driver
= {
293 .name
= "walkera0701",
294 .match_port
= walkera0701_attach
,
295 .detach
= walkera0701_detach
,
299 static int __init
walkera0701_init(void)
301 return parport_register_driver(&walkera0701_parport_driver
);
304 static void __exit
walkera0701_exit(void)
306 parport_unregister_driver(&walkera0701_parport_driver
);
309 module_init(walkera0701_init
);
310 module_exit(walkera0701_exit
);