static void hid_irq_in(struct urb *urb) { struct hid_device *hid = urb->context; struct usbhid_device *usbhid = hid->driver_data; int status; switch (urb->status) { case 0: /* success */ usbhid_mark_busy(usbhid); usbhid->retry_delay = 0; hid_input_report(urb->context, HID_INPUT_REPORT, urb->transfer_buffer, urb->actual_length, 1); /* * autosuspend refused while keys are pressed * because most keyboards don't wake up when * a key is released */ if (hid_check_keys_pressed(hid)) set_bit(HID_KEYS_PRESSED, &usbhid->iofl); else clear_bit(HID_KEYS_PRESSED, &usbhid->iofl); break; case -EOVERFLOW: case -EPIPE: /* stall */ usbhid_mark_busy(usbhid); clear_bit(HID_IN_RUNNING, &usbhid->iofl); set_bit((urb->status == -EPIPE)? HID_CLEAR_HALT:HID_RESET_PENDING, &usbhid->iofl); schedule_work(&usbhid->reset_work); return; case -ECONNRESET: /* unlink */ case -ENOENT: case -ESHUTDOWN: /* unplug */ clear_bit(HID_IN_RUNNING, &usbhid->iofl); return; case -EILSEQ: /* protocol error or unplug */ case -EPROTO: /* protocol error or unplug */ case -ETIME: /* protocol error or unplug */ case -ETIMEDOUT: /* Should never happen, but... */ usbhid_mark_busy(usbhid); clear_bit(HID_IN_RUNNING, &usbhid->iofl); hid_io_error(hid); return; default: /* error */ dev_warn(&urb->dev->dev, "input irq status %d " "received\n", urb->status); } status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { clear_bit(HID_IN_RUNNING, &usbhid->iofl); if (status != -EPERM) { err_hid("can't resubmit intr, %s-%s/input%d, status %d", hid_to_usb_dev(hid)->bus->bus_name, hid_to_usb_dev(hid)->devpath, usbhid->ifnum, status); hid_io_error(hid); } } }
static int __init hid_accel_init(void) { int retval = 0; retval = hid_register_driver(&accel_driver); if (retval) err_hid("hid_register failed. Error number %d", retval); return retval; }
static void hid_irq_in(struct urb *urb) { struct hid_device *hid = urb->context; struct usbhid_device *usbhid = hid->driver_data; int status; switch (urb->status) { case 0: usbhid_mark_busy(usbhid); usbhid->retry_delay = 0; hid_input_report(urb->context, HID_INPUT_REPORT, urb->transfer_buffer, urb->actual_length, 1); if (hid_check_keys_pressed(hid)) set_bit(HID_KEYS_PRESSED, &usbhid->iofl); else clear_bit(HID_KEYS_PRESSED, &usbhid->iofl); break; case -EPIPE: usbhid_mark_busy(usbhid); clear_bit(HID_IN_RUNNING, &usbhid->iofl); set_bit(HID_CLEAR_HALT, &usbhid->iofl); schedule_work(&usbhid->reset_work); return; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: clear_bit(HID_IN_RUNNING, &usbhid->iofl); return; case -EILSEQ: case -EPROTO: case -ETIME: case -ETIMEDOUT: usbhid_mark_busy(usbhid); clear_bit(HID_IN_RUNNING, &usbhid->iofl); hid_io_error(hid); return; default: dev_warn(&urb->dev->dev, "input irq status %d " "received\n", urb->status); } status = usb_submit_urb(urb, GFP_ATOMIC); if (status) { clear_bit(HID_IN_RUNNING, &usbhid->iofl); if (status != -EPERM) { err_hid("can't resubmit intr, %s-%s/input%d, status %d", hid_to_usb_dev(hid)->bus->bus_name, hid_to_usb_dev(hid)->devpath, usbhid->ifnum, status); hid_io_error(hid); } } }
static int accel_probe(struct hid_device *dev, const struct hid_device_id *id) { //struct hid_accel *data = NULL; int retval = -ENOMEM; printk(KERN_INFO "Probing device\n"); dev_info(&dev->dev, "Found USB Accelerometer\n"); // Set up HID Report Parser retval = hid_parse(dev); if (retval) goto error; //data = kzalloc(sizeof(struct hid_accel), GFP_KERNEL); //if (data == NULL) { // dev_err(&dev->dev, "Out of memory\n"); // goto error_mem; //} retval = device_create_file(&dev->dev, &dev_attr_position); if (retval) goto error; retval = device_create_file(&dev->dev, &dev_attr_calibrate); if (retval) goto error; retval = device_create_file(&dev->dev, &dev_attr_recalibrate); if (retval) goto error; read_position(&dev->dev, &rest_x, &rest_y, &rest_z); dev_info(&dev->dev, "USB Accelerometer device now attached\n"); return 0; error: err_hid("There was an error\n"); device_remove_file(&dev->dev, &dev_attr_position); device_remove_file(&dev->dev, &dev_attr_calibrate); device_remove_file(&dev->dev, &dev_attr_recalibrate); // kfree(dev); error_mem: return retval; }
/* Workqueue routine to reset the device or clear a halt */ static void hid_reset(struct work_struct *work) { struct usbhid_device *usbhid = container_of(work, struct usbhid_device, reset_work); struct hid_device *hid = usbhid->hid; int rc = 0; if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) { dev_dbg(&usbhid->intf->dev, "clear halt\n"); rc = usb_clear_halt(hid_to_usb_dev(hid), usbhid->urbin->pipe); clear_bit(HID_CLEAR_HALT, &usbhid->iofl); hid_start_in(hid); } else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) { dev_dbg(&usbhid->intf->dev, "resetting device\n"); rc = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf); if (rc == 0) { rc = usb_reset_device(hid_to_usb_dev(hid)); usb_unlock_device(hid_to_usb_dev(hid)); } clear_bit(HID_RESET_PENDING, &usbhid->iofl); } switch (rc) { case 0: if (!test_bit(HID_IN_RUNNING, &usbhid->iofl)) hid_io_error(hid); break; default: err_hid("can't reset device, %s-%s/input%d, status %d", hid_to_usb_dev(hid)->bus->bus_name, hid_to_usb_dev(hid)->devpath, usbhid->ifnum, rc); /* FALLTHROUGH */ case -EHOSTUNREACH: case -ENODEV: case -EINTR: break; } }
static int hid_submit_out(struct hid_device *hid) { struct hid_report *report; char *raw_report; struct usbhid_device *usbhid = hid->driver_data; report = usbhid->out[usbhid->outtail].report; raw_report = usbhid->out[usbhid->outtail].raw_report; if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) { usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0); usbhid->urbout->dev = hid_to_usb_dev(hid); memcpy(usbhid->outbuf, raw_report, usbhid->urbout->transfer_buffer_length); kfree(raw_report); dbg_hid("submitting out urb\n"); if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) { err_hid("usb_submit_urb(out) failed"); return -1; } } else {