1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/module.h>
18#include <linux/usb.h>
19#include <linux/usb/input.h>
20#include <linux/slab.h>
21#include <linux/leds.h>
22#include <media/rc-core.h>
23
24#define DRIVER_NAME "ttusbir"
25#define DRIVER_DESC "TechnoTrend USB IR Receiver"
26
27
28
29
30
31#define NUM_URBS 4
32#define NS_PER_BYTE 62500
33#define NS_PER_BIT (NS_PER_BYTE/8)
34
35struct ttusbir {
36 struct rc_dev *rc;
37 struct device *dev;
38 struct usb_device *udev;
39
40 struct urb *urb[NUM_URBS];
41
42 struct led_classdev led;
43 struct urb *bulk_urb;
44 uint8_t bulk_buffer[5];
45 int bulk_out_endp, iso_in_endp;
46 bool led_on, is_led_on;
47 atomic_t led_complete;
48
49 char phys[64];
50};
51
52static enum led_brightness ttusbir_brightness_get(struct led_classdev *led_dev)
53{
54 struct ttusbir *tt = container_of(led_dev, struct ttusbir, led);
55
56 return tt->led_on ? LED_FULL : LED_OFF;
57}
58
59static void ttusbir_set_led(struct ttusbir *tt)
60{
61 int ret;
62
63 smp_mb();
64
65 if (tt->led_on != tt->is_led_on && tt->udev &&
66 atomic_add_unless(&tt->led_complete, 1, 1)) {
67 tt->bulk_buffer[4] = tt->is_led_on = tt->led_on;
68 ret = usb_submit_urb(tt->bulk_urb, GFP_ATOMIC);
69 if (ret) {
70 dev_warn(tt->dev, "failed to submit bulk urb: %d\n",
71 ret);
72 atomic_dec(&tt->led_complete);
73 }
74 }
75}
76
77static void ttusbir_brightness_set(struct led_classdev *led_dev, enum
78 led_brightness brightness)
79{
80 struct ttusbir *tt = container_of(led_dev, struct ttusbir, led);
81
82 tt->led_on = brightness != LED_OFF;
83
84 ttusbir_set_led(tt);
85}
86
87
88
89
90static void ttusbir_bulk_complete(struct urb *urb)
91{
92 struct ttusbir *tt = urb->context;
93
94 atomic_dec(&tt->led_complete);
95
96 switch (urb->status) {
97 case 0:
98 break;
99 case -ECONNRESET:
100 case -ENOENT:
101 case -ESHUTDOWN:
102 usb_unlink_urb(urb);
103 return;
104 case -EPIPE:
105 default:
106 dev_dbg(tt->dev, "Error: urb status = %d\n", urb->status);
107 break;
108 }
109
110 ttusbir_set_led(tt);
111}
112
113
114
115
116
117
118static void ttusbir_process_ir_data(struct ttusbir *tt, uint8_t *buf)
119{
120 struct ir_raw_event rawir;
121 unsigned i, v, b;
122 bool event = false;
123
124 init_ir_raw_event(&rawir);
125
126 for (i = 0; i < 128; i++) {
127 v = buf[i] & 0xfe;
128 switch (v) {
129 case 0xfe:
130 rawir.pulse = false;
131 rawir.duration = NS_PER_BYTE;
132 if (ir_raw_event_store_with_filter(tt->rc, &rawir))
133 event = true;
134 break;
135 case 0:
136 rawir.pulse = true;
137 rawir.duration = NS_PER_BYTE;
138 if (ir_raw_event_store_with_filter(tt->rc, &rawir))
139 event = true;
140 break;
141 default:
142
143 if (v & 2) {
144 b = ffz(v | 1);
145 rawir.pulse = true;
146 } else {
147 b = ffs(v) - 1;
148 rawir.pulse = false;
149 }
150
151 rawir.duration = NS_PER_BIT * (8 - b);
152 if (ir_raw_event_store_with_filter(tt->rc, &rawir))
153 event = true;
154
155 rawir.pulse = !rawir.pulse;
156 rawir.duration = NS_PER_BIT * b;
157 if (ir_raw_event_store_with_filter(tt->rc, &rawir))
158 event = true;
159 break;
160 }
161 }
162
163
164 if (event)
165 ir_raw_event_handle(tt->rc);
166}
167
168static void ttusbir_urb_complete(struct urb *urb)
169{
170 struct ttusbir *tt = urb->context;
171 int rc;
172
173 switch (urb->status) {
174 case 0:
175 ttusbir_process_ir_data(tt, urb->transfer_buffer);
176 break;
177 case -ECONNRESET:
178 case -ENOENT:
179 case -ESHUTDOWN:
180 usb_unlink_urb(urb);
181 return;
182 case -EPIPE:
183 default:
184 dev_dbg(tt->dev, "Error: urb status = %d\n", urb->status);
185 break;
186 }
187
188 rc = usb_submit_urb(urb, GFP_ATOMIC);
189 if (rc && rc != -ENODEV)
190 dev_warn(tt->dev, "failed to resubmit urb: %d\n", rc);
191}
192
193static int ttusbir_probe(struct usb_interface *intf,
194 const struct usb_device_id *id)
195{
196 struct ttusbir *tt;
197 struct usb_interface_descriptor *idesc;
198 struct usb_endpoint_descriptor *desc;
199 struct rc_dev *rc;
200 int i, j, ret;
201 int altsetting = -1;
202
203 tt = kzalloc(sizeof(*tt), GFP_KERNEL);
204 rc = rc_allocate_device(RC_DRIVER_IR_RAW);
205 if (!tt || !rc) {
206 ret = -ENOMEM;
207 goto out;
208 }
209
210
211 for (i = 0; i < intf->num_altsetting && altsetting == -1; i++) {
212 int max_packet, bulk_out_endp = -1, iso_in_endp = -1;
213
214 idesc = &intf->altsetting[i].desc;
215
216 for (j = 0; j < idesc->bNumEndpoints; j++) {
217 desc = &intf->altsetting[i].endpoint[j].desc;
218 max_packet = le16_to_cpu(desc->wMaxPacketSize);
219 if (usb_endpoint_dir_in(desc) &&
220 usb_endpoint_xfer_isoc(desc) &&
221 max_packet == 0x10)
222 iso_in_endp = j;
223 else if (usb_endpoint_dir_out(desc) &&
224 usb_endpoint_xfer_bulk(desc) &&
225 max_packet == 0x20)
226 bulk_out_endp = j;
227
228 if (bulk_out_endp != -1 && iso_in_endp != -1) {
229 tt->bulk_out_endp = bulk_out_endp;
230 tt->iso_in_endp = iso_in_endp;
231 altsetting = i;
232 break;
233 }
234 }
235 }
236
237 if (altsetting == -1) {
238 dev_err(&intf->dev, "cannot find expected altsetting\n");
239 ret = -ENODEV;
240 goto out;
241 }
242
243 tt->dev = &intf->dev;
244 tt->udev = interface_to_usbdev(intf);
245 tt->rc = rc;
246
247 ret = usb_set_interface(tt->udev, 0, altsetting);
248 if (ret)
249 goto out;
250
251 for (i = 0; i < NUM_URBS; i++) {
252 struct urb *urb = usb_alloc_urb(8, GFP_KERNEL);
253 void *buffer;
254
255 if (!urb) {
256 ret = -ENOMEM;
257 goto out;
258 }
259
260 urb->dev = tt->udev;
261 urb->context = tt;
262 urb->pipe = usb_rcvisocpipe(tt->udev, tt->iso_in_endp);
263 urb->interval = 1;
264 buffer = usb_alloc_coherent(tt->udev, 128, GFP_KERNEL,
265 &urb->transfer_dma);
266 if (!buffer) {
267 usb_free_urb(urb);
268 ret = -ENOMEM;
269 goto out;
270 }
271 urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP | URB_ISO_ASAP;
272 urb->transfer_buffer = buffer;
273 urb->complete = ttusbir_urb_complete;
274 urb->number_of_packets = 8;
275 urb->transfer_buffer_length = 128;
276
277 for (j = 0; j < 8; j++) {
278 urb->iso_frame_desc[j].offset = j * 16;
279 urb->iso_frame_desc[j].length = 16;
280 }
281
282 tt->urb[i] = urb;
283 }
284
285 tt->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
286 if (!tt->bulk_urb) {
287 ret = -ENOMEM;
288 goto out;
289 }
290
291 tt->bulk_buffer[0] = 0xaa;
292 tt->bulk_buffer[1] = 0x01;
293 tt->bulk_buffer[2] = 0x05;
294 tt->bulk_buffer[3] = 0x01;
295
296 usb_fill_bulk_urb(tt->bulk_urb, tt->udev, usb_sndbulkpipe(tt->udev,
297 tt->bulk_out_endp), tt->bulk_buffer, sizeof(tt->bulk_buffer),
298 ttusbir_bulk_complete, tt);
299
300 tt->led.name = "ttusbir:green:power";
301 tt->led.default_trigger = "rc-feedback";
302 tt->led.brightness_set = ttusbir_brightness_set;
303 tt->led.brightness_get = ttusbir_brightness_get;
304 tt->is_led_on = tt->led_on = true;
305 atomic_set(&tt->led_complete, 0);
306 ret = led_classdev_register(&intf->dev, &tt->led);
307 if (ret)
308 goto out;
309
310 usb_make_path(tt->udev, tt->phys, sizeof(tt->phys));
311
312 rc->device_name = DRIVER_DESC;
313 rc->input_phys = tt->phys;
314 usb_to_input_id(tt->udev, &rc->input_id);
315 rc->dev.parent = &intf->dev;
316 rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
317 rc->priv = tt;
318 rc->driver_name = DRIVER_NAME;
319 rc->map_name = RC_MAP_TT_1500;
320 rc->min_timeout = 1;
321 rc->timeout = IR_DEFAULT_TIMEOUT;
322 rc->max_timeout = 10 * IR_DEFAULT_TIMEOUT;
323
324
325
326
327
328 rc->rx_resolution = NS_PER_BIT;
329
330 ret = rc_register_device(rc);
331 if (ret) {
332 dev_err(&intf->dev, "failed to register rc device %d\n", ret);
333 goto out2;
334 }
335
336 usb_set_intfdata(intf, tt);
337
338 for (i = 0; i < NUM_URBS; i++) {
339 ret = usb_submit_urb(tt->urb[i], GFP_KERNEL);
340 if (ret) {
341 dev_err(tt->dev, "failed to submit urb %d\n", ret);
342 goto out3;
343 }
344 }
345
346 return 0;
347out3:
348 rc_unregister_device(rc);
349 rc = NULL;
350out2:
351 led_classdev_unregister(&tt->led);
352out:
353 if (tt) {
354 for (i = 0; i < NUM_URBS && tt->urb[i]; i++) {
355 struct urb *urb = tt->urb[i];
356
357 usb_kill_urb(urb);
358 usb_free_coherent(tt->udev, 128, urb->transfer_buffer,
359 urb->transfer_dma);
360 usb_free_urb(urb);
361 }
362 usb_kill_urb(tt->bulk_urb);
363 usb_free_urb(tt->bulk_urb);
364 kfree(tt);
365 }
366 rc_free_device(rc);
367
368 return ret;
369}
370
371static void ttusbir_disconnect(struct usb_interface *intf)
372{
373 struct ttusbir *tt = usb_get_intfdata(intf);
374 struct usb_device *udev = tt->udev;
375 int i;
376
377 tt->udev = NULL;
378
379 rc_unregister_device(tt->rc);
380 led_classdev_unregister(&tt->led);
381 for (i = 0; i < NUM_URBS; i++) {
382 usb_kill_urb(tt->urb[i]);
383 usb_free_coherent(udev, 128, tt->urb[i]->transfer_buffer,
384 tt->urb[i]->transfer_dma);
385 usb_free_urb(tt->urb[i]);
386 }
387 usb_kill_urb(tt->bulk_urb);
388 usb_free_urb(tt->bulk_urb);
389 usb_set_intfdata(intf, NULL);
390 kfree(tt);
391}
392
393static int ttusbir_suspend(struct usb_interface *intf, pm_message_t message)
394{
395 struct ttusbir *tt = usb_get_intfdata(intf);
396 int i;
397
398 for (i = 0; i < NUM_URBS; i++)
399 usb_kill_urb(tt->urb[i]);
400
401 led_classdev_suspend(&tt->led);
402 usb_kill_urb(tt->bulk_urb);
403
404 return 0;
405}
406
407static int ttusbir_resume(struct usb_interface *intf)
408{
409 struct ttusbir *tt = usb_get_intfdata(intf);
410 int i, rc;
411
412 tt->is_led_on = true;
413 led_classdev_resume(&tt->led);
414
415 for (i = 0; i < NUM_URBS; i++) {
416 rc = usb_submit_urb(tt->urb[i], GFP_KERNEL);
417 if (rc) {
418 dev_warn(tt->dev, "failed to submit urb: %d\n", rc);
419 break;
420 }
421 }
422
423 return rc;
424}
425
426static const struct usb_device_id ttusbir_table[] = {
427 { USB_DEVICE(0x0b48, 0x2003) },
428 { }
429};
430
431static struct usb_driver ttusbir_driver = {
432 .name = DRIVER_NAME,
433 .id_table = ttusbir_table,
434 .probe = ttusbir_probe,
435 .suspend = ttusbir_suspend,
436 .resume = ttusbir_resume,
437 .reset_resume = ttusbir_resume,
438 .disconnect = ttusbir_disconnect,
439};
440
441module_usb_driver(ttusbir_driver);
442
443MODULE_DESCRIPTION(DRIVER_DESC);
444MODULE_AUTHOR("Sean Young <sean@mess.org>");
445MODULE_LICENSE("GPL");
446MODULE_DEVICE_TABLE(usb, ttusbir_table);
447
448