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