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 devnum = ir->devnum;
213 d = ir->d;
214
215 if (!d) {
216 dev_err(&ir->usbdev->dev,
217 "%s: called with NULL lirc driver struct!\n", __func__);
218 return -EINVAL;
219 }
220
221 dev_dbg(&ir->usbdev->dev, "calling lirc_unregister_driver\n");
222 lirc_unregister_driver(d->minor);
223
224 return devnum;
225}
226
227static int set_use_inc(void *data)
228{
229 struct igorplug *ir = data;
230
231 if (!ir) {
232 printk(DRIVER_NAME "[?]: set_use_inc called with no context\n");
233 return -EIO;
234 }
235
236 dev_dbg(&ir->usbdev->dev, "set use inc\n");
237
238 if (!ir->usbdev)
239 return -ENODEV;
240
241 return 0;
242}
243
244static void set_use_dec(void *data)
245{
246 struct igorplug *ir = data;
247
248 if (!ir) {
249 printk(DRIVER_NAME "[?]: set_use_dec called with no context\n");
250 return;
251 }
252
253 dev_dbg(&ir->usbdev->dev, "set use dec\n");
254}
255
256static void send_fragment(struct igorplug *ir, struct lirc_buffer *buf,
257 int i, int max)
258{
259 int code;
260
261
262 while (i < max) {
263
264 code = (unsigned int)ir->buf_in[i] * 85 +
265 (unsigned int)ir->buf_in[i] / 3;
266 ir->last_time.tv_usec += code;
267 if (ir->in_space)
268 code |= PULSE_BIT;
269 lirc_buffer_write(buf, (unsigned char *)&code);
270
271 ir->in_space ^= 1;
272 ++i;
273 }
274}
275
276
277
278
279
280
281
282static int igorplugusb_remote_poll(void *data, struct lirc_buffer *buf)
283{
284 int ret;
285 struct igorplug *ir = (struct igorplug *)data;
286
287 if (!ir || !ir->usbdev)
288 return -ENODEV;
289
290 memset(ir->buf_in, 0, ir->len_in);
291
292 ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
293 GET_INFRACODE, USB_TYPE_VENDOR | USB_DIR_IN,
294 0, 0,
295 ir->buf_in, ir->len_in,
296 HZ * USB_CTRL_GET_TIMEOUT);
297 if (ret > 0) {
298 int code, timediff;
299 struct timeval now;
300
301
302 if (ret < DEVICE_HEADERLEN)
303 return -ENODATA;
304
305 dev_dbg(&ir->usbdev->dev, "Got %d bytes. Header: %*ph\n",
306 ret, 3, ir->buf_in);
307
308 do_gettimeofday(&now);
309 timediff = now.tv_sec - ir->last_time.tv_sec;
310 if (timediff + 1 > PULSE_MASK / 1000000)
311 timediff = PULSE_MASK;
312 else {
313 timediff *= 1000000;
314 timediff += now.tv_usec - ir->last_time.tv_usec;
315 }
316 ir->last_time.tv_sec = now.tv_sec;
317 ir->last_time.tv_usec = now.tv_usec;
318
319
320 code = timediff;
321 lirc_buffer_write(buf, (unsigned char *)&code);
322 ir->in_space = 1;
323
324 if (ir->buf_in[2] == 0)
325 send_fragment(ir, buf, DEVICE_HEADERLEN, ret);
326 else {
327 dev_warn(&ir->usbdev->dev,
328 "[%d]: Device buffer overrun.\n", ir->devnum);
329
330
331
332 ir->buf_in[2] %= ret - DEVICE_HEADERLEN;
333
334 send_fragment(ir, buf, DEVICE_HEADERLEN +
335 ir->buf_in[2] - (ir->buf_in[2] & 1), ret);
336 send_fragment(ir, buf, DEVICE_HEADERLEN,
337 DEVICE_HEADERLEN + ir->buf_in[2]);
338 }
339
340 ret = usb_control_msg(
341 ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
342 SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN,
343 0, 0,
344 ir->buf_in, ir->len_in,
345 HZ * USB_CTRL_GET_TIMEOUT);
346 if (ret < 0)
347 printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: error %d\n",
348 ir->devnum, ret);
349 return 0;
350 } else if (ret < 0)
351 printk(DRIVER_NAME "[%d]: GET_INFRACODE: error %d\n",
352 ir->devnum, ret);
353
354 return -ENODATA;
355}
356
357static int igorplugusb_remote_probe(struct usb_interface *intf,
358 const struct usb_device_id *id)
359{
360 struct usb_device *dev;
361 struct usb_host_interface *idesc = NULL;
362 struct usb_endpoint_descriptor *ep;
363 struct igorplug *ir = NULL;
364 struct lirc_driver *driver = NULL;
365 int devnum, pipe, maxp;
366 char buf[63], name[128] = "";
367 int ret;
368
369 dev_dbg(&intf->dev, "%s: usb probe called.\n", __func__);
370
371 dev = interface_to_usbdev(intf);
372
373 idesc = intf->cur_altsetting;
374
375 if (idesc->desc.bNumEndpoints != 1)
376 return -ENODEV;
377
378 ep = &idesc->endpoint->desc;
379 if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
380 != USB_DIR_IN)
381 || (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
382 != USB_ENDPOINT_XFER_CONTROL)
383 return -ENODEV;
384
385 pipe = usb_rcvctrlpipe(dev, ep->bEndpointAddress);
386 devnum = dev->devnum;
387 maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
388
389 dev_dbg(&intf->dev, "%s: bytes_in_key=%zu maxp=%d\n",
390 __func__, CODE_LENGTH, maxp);
391
392 ir = devm_kzalloc(&intf->dev, sizeof(*ir), GFP_KERNEL);
393 if (!ir)
394 return -ENOMEM;
395
396 driver = devm_kzalloc(&intf->dev, sizeof(*driver), GFP_KERNEL);
397 if (!driver)
398 return -ENOMEM;
399
400 ir->buf_in = usb_alloc_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN,
401 GFP_ATOMIC, &ir->dma_in);
402 if (!ir->buf_in)
403 return -ENOMEM;
404
405 strcpy(driver->name, DRIVER_NAME " ");
406 driver->minor = -1;
407 driver->code_length = CODE_LENGTH * 8;
408 driver->features = LIRC_CAN_REC_MODE2;
409 driver->data = ir;
410 driver->chunk_size = CODE_LENGTH;
411 driver->buffer_size = DEVICE_BUFLEN + ADDITIONAL_LIRC_BYTES;
412 driver->set_use_inc = &set_use_inc;
413 driver->set_use_dec = &set_use_dec;
414 driver->sample_rate = sample_rate;
415 driver->add_to_buf = &igorplugusb_remote_poll;
416 driver->dev = &intf->dev;
417 driver->owner = THIS_MODULE;
418
419 ret = lirc_register_driver(driver);
420 if (ret < 0) {
421 usb_free_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN,
422 ir->buf_in, ir->dma_in);
423 return ret;
424 }
425
426 driver->minor = ret;
427 ir->d = driver;
428 ir->devnum = devnum;
429 ir->usbdev = dev;
430 ir->len_in = DEVICE_BUFLEN + DEVICE_HEADERLEN;
431 ir->in_space = 1;
432 do_gettimeofday(&ir->last_time);
433
434 if (dev->descriptor.iManufacturer
435 && usb_string(dev, dev->descriptor.iManufacturer,
436 buf, sizeof(buf)) > 0)
437 strlcpy(name, buf, sizeof(name));
438 if (dev->descriptor.iProduct
439 && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0)
440 snprintf(name + strlen(name), sizeof(name) - strlen(name),
441 " %s", buf);
442 printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", devnum, name,
443 dev->bus->busnum, devnum);
444
445
446 ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
447 SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN,
448 0, 0,
449 ir->buf_in, ir->len_in,
450 HZ * USB_CTRL_GET_TIMEOUT);
451 if (ret < 0)
452 printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: error %d\n",
453 devnum, ret);
454
455 usb_set_intfdata(intf, ir);
456 return 0;
457}
458
459static void igorplugusb_remote_disconnect(struct usb_interface *intf)
460{
461 struct usb_device *usbdev = interface_to_usbdev(intf);
462 struct igorplug *ir = usb_get_intfdata(intf);
463 struct device *dev = &intf->dev;
464 int devnum;
465
466 usb_set_intfdata(intf, NULL);
467
468 if (!ir || !ir->d)
469 return;
470
471 ir->usbdev = NULL;
472
473 usb_free_coherent(usbdev, ir->len_in, ir->buf_in, ir->dma_in);
474
475 devnum = unregister_from_lirc(ir);
476
477 dev_info(dev, DRIVER_NAME "[%d]: %s done\n", devnum, __func__);
478}
479
480static struct usb_device_id igorplugusb_remote_id_table[] = {
481
482 { USB_DEVICE(0x03eb, 0x0002) },
483
484 { USB_DEVICE(0x03eb, 0x21fe) },
485
486
487 { }
488};
489
490static struct usb_driver igorplugusb_remote_driver = {
491 .name = DRIVER_NAME,
492 .probe = igorplugusb_remote_probe,
493 .disconnect = igorplugusb_remote_disconnect,
494 .id_table = igorplugusb_remote_id_table
495};
496
497module_usb_driver(igorplugusb_remote_driver);
498
499#include <linux/vermagic.h>
500MODULE_INFO(vermagic, VERMAGIC_STRING);
501
502MODULE_DESCRIPTION(DRIVER_DESC);
503MODULE_AUTHOR(DRIVER_AUTHOR);
504MODULE_LICENSE("GPL");
505MODULE_DEVICE_TABLE(usb, igorplugusb_remote_id_table);
506
507module_param(sample_rate, int, S_IRUGO | S_IWUSR);
508MODULE_PARM_DESC(sample_rate, "Sampling rate in Hz (default: 100)");
509