1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43#include <linux/module.h>
44#include <linux/kernel.h>
45#include <linux/kmod.h>
46#include <linux/sched.h>
47#include <linux/errno.h>
48#include <linux/fs.h>
49#include <linux/usb.h>
50#include <linux/time.h>
51
52#include <media/lirc.h>
53#include <media/lirc_dev.h>
54
55
56
57#define DRIVER_VERSION "0.2"
58#define DRIVER_AUTHOR \
59 "Jan M. Hochstein <hochstein@algo.informatik.tu-darmstadt.de>"
60#define DRIVER_DESC "Igorplug USB remote driver for LIRC"
61#define DRIVER_NAME "lirc_igorplugusb"
62
63
64#ifdef CONFIG_USB_DEBUG
65static bool debug = 1;
66#else
67static bool debug;
68#endif
69
70#define dprintk(fmt, args...) \
71 do { \
72 if (debug) \
73 printk(KERN_DEBUG fmt, ## args); \
74 } while (0)
75
76
77#define CODE_LENGTH sizeof(int)
78
79
80#define DEVICE_BUFLEN 36
81
82
83
84
85
86
87
88#define DEVICE_HEADERLEN 3
89
90
91#define ADDITIONAL_LIRC_BYTES 2
92
93
94#define SAMPLE_RATE 100
95static int sample_rate = SAMPLE_RATE;
96
97
98
99
100#define SET_INFRABUFFER_EMPTY 1
101
102
103
104
105
106#define GET_INFRACODE 2
107
108
109
110
111
112
113
114#define SET_DATAPORT_DIRECTION 3
115
116
117
118
119
120
121
122#define GET_DATAPORT_DIRECTION 4
123
124
125
126
127
128
129#define SET_OUT_DATAPORT 5
130
131
132
133
134
135
136
137#define GET_OUT_DATAPORT 6
138
139
140
141
142
143
144#define GET_IN_DATAPORT 7
145
146
147
148
149
150
151#define READ_EEPROM 8
152
153
154
155
156
157
158
159#define WRITE_EEPROM 9
160
161
162
163
164
165
166
167
168#define SEND_RS232 10
169
170
171
172
173
174
175
176#define RECV_RS232 11
177
178
179
180
181
182
183#define SET_RS232_BAUD 12
184
185
186
187
188
189
190
191#define GET_RS232_BAUD 13
192
193
194
195
196
197
198
199
200struct igorplug {
201
202
203 struct usb_device *usbdev;
204 int devnum;
205
206 unsigned char *buf_in;
207 unsigned int len_in;
208 int in_space;
209 struct timeval last_time;
210
211 dma_addr_t dma_in;
212
213
214 struct lirc_driver *d;
215
216
217 int send_flags;
218};
219
220static int unregister_from_lirc(struct igorplug *ir)
221{
222 struct lirc_driver *d;
223 int devnum;
224
225 if (!ir) {
226 dev_err(&ir->usbdev->dev,
227 "%s: called with NULL device struct!\n", __func__);
228 return -EINVAL;
229 }
230
231 devnum = ir->devnum;
232 d = ir->d;
233
234 if (!d) {
235 dev_err(&ir->usbdev->dev,
236 "%s: called with NULL lirc driver struct!\n", __func__);
237 return -EINVAL;
238 }
239
240 dprintk(DRIVER_NAME "[%d]: calling lirc_unregister_driver\n", devnum);
241 lirc_unregister_driver(d->minor);
242
243 kfree(d);
244 ir->d = NULL;
245 kfree(ir);
246
247 return devnum;
248}
249
250static int set_use_inc(void *data)
251{
252 struct igorplug *ir = data;
253
254 if (!ir) {
255 printk(DRIVER_NAME "[?]: set_use_inc called with no context\n");
256 return -EIO;
257 }
258
259 dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum);
260
261 if (!ir->usbdev)
262 return -ENODEV;
263
264 return 0;
265}
266
267static void set_use_dec(void *data)
268{
269 struct igorplug *ir = data;
270
271 if (!ir) {
272 printk(DRIVER_NAME "[?]: set_use_dec called with no context\n");
273 return;
274 }
275
276 dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum);
277}
278
279static void send_fragment(struct igorplug *ir, struct lirc_buffer *buf,
280 int i, int max)
281{
282 int code;
283
284
285 while (i < max) {
286
287 code = (unsigned int)ir->buf_in[i] * 85 +
288 (unsigned int)ir->buf_in[i] / 3;
289 ir->last_time.tv_usec += code;
290 if (ir->in_space)
291 code |= PULSE_BIT;
292 lirc_buffer_write(buf, (unsigned char *)&code);
293
294 ir->in_space ^= 1;
295 ++i;
296 }
297}
298
299
300
301
302
303
304
305static int igorplugusb_remote_poll(void *data, struct lirc_buffer *buf)
306{
307 int ret;
308 struct igorplug *ir = (struct igorplug *)data;
309
310 if (!ir || !ir->usbdev)
311 return -ENODEV;
312
313 memset(ir->buf_in, 0, ir->len_in);
314
315 ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
316 GET_INFRACODE, USB_TYPE_VENDOR | USB_DIR_IN,
317 0, 0,
318 ir->buf_in, ir->len_in,
319 HZ * USB_CTRL_GET_TIMEOUT);
320 if (ret > 0) {
321 int code, timediff;
322 struct timeval now;
323
324
325 if (ret < DEVICE_HEADERLEN)
326 return -ENODATA;
327
328 dprintk(DRIVER_NAME ": Got %d bytes. Header: %*ph\n",
329 ret, 3, ir->buf_in);
330
331 do_gettimeofday(&now);
332 timediff = now.tv_sec - ir->last_time.tv_sec;
333 if (timediff + 1 > PULSE_MASK / 1000000)
334 timediff = PULSE_MASK;
335 else {
336 timediff *= 1000000;
337 timediff += now.tv_usec - ir->last_time.tv_usec;
338 }
339 ir->last_time.tv_sec = now.tv_sec;
340 ir->last_time.tv_usec = now.tv_usec;
341
342
343 code = timediff;
344 lirc_buffer_write(buf, (unsigned char *)&code);
345 ir->in_space = 1;
346
347 if (ir->buf_in[2] == 0)
348 send_fragment(ir, buf, DEVICE_HEADERLEN, ret);
349 else {
350 dev_warn(&ir->usbdev->dev,
351 "[%d]: Device buffer overrun.\n", ir->devnum);
352
353
354
355 ir->buf_in[2] %= ret - DEVICE_HEADERLEN;
356
357 send_fragment(ir, buf, DEVICE_HEADERLEN +
358 ir->buf_in[2] - (ir->buf_in[2] & 1), ret);
359 send_fragment(ir, buf, DEVICE_HEADERLEN,
360 DEVICE_HEADERLEN + ir->buf_in[2]);
361 }
362
363 ret = usb_control_msg(
364 ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
365 SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN,
366 0, 0,
367 ir->buf_in, ir->len_in,
368 HZ * USB_CTRL_GET_TIMEOUT);
369 if (ret < 0)
370 printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: "
371 "error %d\n", ir->devnum, ret);
372 return 0;
373 } else if (ret < 0)
374 printk(DRIVER_NAME "[%d]: GET_INFRACODE: error %d\n",
375 ir->devnum, ret);
376
377 return -ENODATA;
378}
379
380
381
382static int igorplugusb_remote_probe(struct usb_interface *intf,
383 const struct usb_device_id *id)
384{
385 struct usb_device *dev = NULL;
386 struct usb_host_interface *idesc = NULL;
387 struct usb_endpoint_descriptor *ep;
388 struct igorplug *ir = NULL;
389 struct lirc_driver *driver = NULL;
390 int devnum, pipe, maxp;
391 int minor = 0;
392 char buf[63], name[128] = "";
393 int mem_failure = 0;
394 int ret;
395
396 dprintk(DRIVER_NAME ": usb probe called.\n");
397
398 dev = interface_to_usbdev(intf);
399
400 idesc = intf->cur_altsetting;
401
402 if (idesc->desc.bNumEndpoints != 1)
403 return -ENODEV;
404
405 ep = &idesc->endpoint->desc;
406 if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
407 != USB_DIR_IN)
408 || (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
409 != USB_ENDPOINT_XFER_CONTROL)
410 return -ENODEV;
411
412 pipe = usb_rcvctrlpipe(dev, ep->bEndpointAddress);
413 devnum = dev->devnum;
414 maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
415
416 dprintk(DRIVER_NAME "[%d]: bytes_in_key=%zu maxp=%d\n",
417 devnum, CODE_LENGTH, maxp);
418
419 mem_failure = 0;
420 ir = kzalloc(sizeof(struct igorplug), GFP_KERNEL);
421 if (!ir) {
422 mem_failure = 1;
423 goto mem_failure_switch;
424 }
425 driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
426 if (!driver) {
427 mem_failure = 2;
428 goto mem_failure_switch;
429 }
430
431 ir->buf_in = usb_alloc_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN,
432 GFP_ATOMIC, &ir->dma_in);
433 if (!ir->buf_in) {
434 mem_failure = 3;
435 goto mem_failure_switch;
436 }
437
438 strcpy(driver->name, DRIVER_NAME " ");
439 driver->minor = -1;
440 driver->code_length = CODE_LENGTH * 8;
441 driver->features = LIRC_CAN_REC_MODE2;
442 driver->data = ir;
443 driver->chunk_size = CODE_LENGTH;
444 driver->buffer_size = DEVICE_BUFLEN + ADDITIONAL_LIRC_BYTES;
445 driver->set_use_inc = &set_use_inc;
446 driver->set_use_dec = &set_use_dec;
447 driver->sample_rate = sample_rate;
448 driver->add_to_buf = &igorplugusb_remote_poll;
449 driver->dev = &intf->dev;
450 driver->owner = THIS_MODULE;
451
452 minor = lirc_register_driver(driver);
453 if (minor < 0)
454 mem_failure = 9;
455
456mem_failure_switch:
457
458 switch (mem_failure) {
459 case 9:
460 usb_free_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN,
461 ir->buf_in, ir->dma_in);
462 case 3:
463 kfree(driver);
464 case 2:
465 kfree(ir);
466 case 1:
467 printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n",
468 devnum, mem_failure);
469 return -ENOMEM;
470 }
471
472 driver->minor = minor;
473 ir->d = driver;
474 ir->devnum = devnum;
475 ir->usbdev = dev;
476 ir->len_in = DEVICE_BUFLEN + DEVICE_HEADERLEN;
477 ir->in_space = 1;
478 do_gettimeofday(&ir->last_time);
479
480 if (dev->descriptor.iManufacturer
481 && usb_string(dev, dev->descriptor.iManufacturer,
482 buf, sizeof(buf)) > 0)
483 strlcpy(name, buf, sizeof(name));
484 if (dev->descriptor.iProduct
485 && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0)
486 snprintf(name + strlen(name), sizeof(name) - strlen(name),
487 " %s", buf);
488 printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", devnum, name,
489 dev->bus->busnum, devnum);
490
491
492 ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
493 SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN,
494 0, 0,
495 ir->buf_in, ir->len_in,
496 HZ * USB_CTRL_GET_TIMEOUT);
497 if (ret < 0)
498 printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: error %d\n",
499 devnum, ret);
500
501 usb_set_intfdata(intf, ir);
502 return 0;
503}
504
505
506static void igorplugusb_remote_disconnect(struct usb_interface *intf)
507{
508 struct usb_device *usbdev = interface_to_usbdev(intf);
509 struct igorplug *ir = usb_get_intfdata(intf);
510 struct device *dev = &intf->dev;
511 int devnum;
512
513 usb_set_intfdata(intf, NULL);
514
515 if (!ir || !ir->d)
516 return;
517
518 ir->usbdev = NULL;
519
520 usb_free_coherent(usbdev, ir->len_in, ir->buf_in, ir->dma_in);
521
522 devnum = unregister_from_lirc(ir);
523
524 dev_info(dev, DRIVER_NAME "[%d]: %s done\n", devnum, __func__);
525}
526
527static struct usb_device_id igorplugusb_remote_id_table[] = {
528
529 { USB_DEVICE(0x03eb, 0x0002) },
530
531 { USB_DEVICE(0x03eb, 0x21fe) },
532
533
534 { }
535};
536
537static struct usb_driver igorplugusb_remote_driver = {
538 .name = DRIVER_NAME,
539 .probe = igorplugusb_remote_probe,
540 .disconnect = igorplugusb_remote_disconnect,
541 .id_table = igorplugusb_remote_id_table
542};
543
544module_usb_driver(igorplugusb_remote_driver);
545
546#include <linux/vermagic.h>
547MODULE_INFO(vermagic, VERMAGIC_STRING);
548
549MODULE_DESCRIPTION(DRIVER_DESC);
550MODULE_AUTHOR(DRIVER_AUTHOR);
551MODULE_LICENSE("GPL");
552MODULE_DEVICE_TABLE(usb, igorplugusb_remote_id_table);
553
554module_param(sample_rate, int, S_IRUGO | S_IWUSR);
555MODULE_PARM_DESC(sample_rate, "Sampling rate in Hz (default: 100)");
556
557module_param(debug, bool, S_IRUGO | S_IWUSR);
558MODULE_PARM_DESC(debug, "Debug enabled or not");
559