#define DRIVER_NAME "ttusbir" #define DRIVER_DESC "TechnoTrend USB IR Receiver" /* * The Windows driver uses 8 URBS, the original lirc drivers has a * configurable amount (2 default, 4 max). This device generates about 125 * messages per second (!), whether IR is idle or not.
*/ #define NUM_URBS 4 #define US_PER_BYTE 62 #define US_PER_BIT (US_PER_BYTE / 8)
/* * The urb cannot be reused until the urb completes
*/ staticvoid ttusbir_bulk_complete(struct urb *urb)
{ struct ttusbir *tt = urb->context;
atomic_dec(&tt->led_complete);
switch (urb->status) { case 0: break; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: return; case -EPIPE: default:
dev_dbg(tt->dev, "Error: urb status = %d\n", urb->status); break;
}
ttusbir_set_led(tt);
}
/* * The data is one bit per sample, a set bit signifying silence and samples * being MSB first. Bit 0 can contain garbage so take it to be whatever * bit 1 is, so we don't have unexpected edges.
*/ staticvoid ttusbir_process_ir_data(struct ttusbir *tt, uint8_t *buf)
{ struct ir_raw_event rawir = {}; unsigned i, v, b; bool event = false;
for (i = 0; i < 128; i++) {
v = buf[i] & 0xfe; switch (v) { case 0xfe:
rawir.pulse = false;
rawir.duration = US_PER_BYTE; if (ir_raw_event_store_with_filter(tt->rc, &rawir))
event = true; break; case 0:
rawir.pulse = true;
rawir.duration = US_PER_BYTE; if (ir_raw_event_store_with_filter(tt->rc, &rawir))
event = true; break; default: /* one edge per byte */ if (v & 2) {
b = ffz(v | 1);
rawir.pulse = true;
} else {
b = ffs(v) - 1;
rawir.pulse = false;
}
switch (urb->status) { case 0:
ttusbir_process_ir_data(tt, urb->transfer_buffer); break; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: return; case -EPIPE: default:
dev_dbg(tt->dev, "Error: urb status = %d\n", urb->status); break;
}
rc = usb_submit_urb(urb, GFP_ATOMIC); if (rc && rc != -ENODEV)
dev_warn(tt->dev, "failed to resubmit urb: %d\n", rc);
}
staticint ttusbir_probe(struct usb_interface *intf, conststruct usb_device_id *id)
{ struct ttusbir *tt; struct usb_interface_descriptor *idesc; struct usb_endpoint_descriptor *desc; struct rc_dev *rc; int i, j, ret; int altsetting = -1;
tt = kzalloc(sizeof(*tt), GFP_KERNEL);
rc = rc_allocate_device(RC_DRIVER_IR_RAW); if (!tt || !rc) {
ret = -ENOMEM; goto out;
}
/* find the correct alt setting */ for (i = 0; i < intf->num_altsetting && altsetting == -1; i++) { int max_packet, bulk_out_endp = -1, iso_in_endp = -1;
/* * The precision is US_PER_BIT, but since every 8th bit can be * overwritten with garbage the accuracy is at best 2 * US_PER_BIT.
*/
rc->rx_resolution = 2 * US_PER_BIT;
ret = rc_register_device(rc); if (ret) {
dev_err(&intf->dev, "failed to register rc device %d\n", ret); goto out2;
}
usb_set_intfdata(intf, tt);
for (i = 0; i < NUM_URBS; i++) {
ret = usb_submit_urb(tt->urb[i], GFP_KERNEL); if (ret) {
dev_err(tt->dev, "failed to submit urb %d\n", ret); goto out3;
}
}
return 0;
out3:
rc_unregister_device(rc);
rc = NULL;
out2:
led_classdev_unregister(&tt->led);
out: if (tt) { for (i = 0; i < NUM_URBS && tt->urb[i]; i++) { struct urb *urb = tt->urb[i];
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.