/* Called when the driver is unloaded or the device is unplugged */ static void disconnect(struct usb_interface *intf) { int i; struct ttusbir_device *ttusbir; DPRINTK("Module ttusbir disconnect\n"); ttusbir = (struct ttusbir_device *) usb_get_intfdata(intf); usb_set_intfdata(intf, NULL); lirc_unregister_plugin(ttusbir->minor); DPRINTK("unregistered\n"); for (i = 0; i < num_urbs; i++) { usb_kill_urb(ttusbir->urb[i]); usb_free_urb(ttusbir->urb[i]); } DPRINTK("URBs killed\n"); lirc_buffer_free(&ttusbir->rbuf); kfree(ttusbir); }
void __exit cleanup_module(void) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) lirc_serial_exit(); #endif #if defined(LIRC_ALLOW_MMAPPED_IO) if(iommap != 0) { release_mem_region(iommap, 8<<ioshift); } else { release_region(io, 8); } #else release_region(io, 8); #endif lirc_unregister_plugin(plugin.minor); dprintk("cleaned up module\n"); }
void cleanup_module(void) { lirc_unregister_plugin(plugin.minor); printk(KERN_INFO LIRC_DRIVER_NAME ": module removed\n"); }
/* Called whenever the USB subsystem thinks we could be the right driver to handle this device */ static int probe(struct usb_interface *intf, const struct usb_device_id *id) { int alt_set, endp; int found = 0; int i, j; int struct_size; struct usb_host_interface *host_interf; struct usb_interface_descriptor *interf_desc; struct usb_host_endpoint *host_endpoint; struct ttusbir_device *ttusbir; DPRINTK("Module ttusbir probe\n"); /* To reduce memory fragmentation we use only one allocation */ struct_size = sizeof(struct ttusbir_device) + (sizeof(struct urb *) * num_urbs) + (sizeof(char *) * num_urbs) + (num_urbs * 128); ttusbir = kmalloc(struct_size, GFP_KERNEL); if (!ttusbir) return -ENOMEM; memset(ttusbir, 0, struct_size); ttusbir->urb = (struct urb **)((char *)ttusbir + sizeof(struct ttusbir_device)); ttusbir->buffer = (char **)((char *)ttusbir->urb + (sizeof(struct urb *) * num_urbs)); for (i = 0; i < num_urbs; i++) ttusbir->buffer[i] = (char *)ttusbir->buffer + (sizeof(char *)*num_urbs) + (i * 128); ttusbir->driver = &driver; ttusbir->alt_setting = -1; /* @TODO check if error can be returned */ ttusbir->udev = usb_get_dev(interface_to_usbdev(intf)); ttusbir->interf = intf; ttusbir->last_pulse = 0x00; ttusbir->last_num = 0; /* Now look for interface setting we can handle We are searching for the alt setting where end point 0x82 has max packet size 16 */ for (alt_set = 0; alt_set < intf->num_altsetting && !found; alt_set++) { host_interf = &intf->altsetting[alt_set]; interf_desc = &host_interf->desc; for (endp = 0; endp < interf_desc->bNumEndpoints; endp++) { host_endpoint = &host_interf->endpoint[endp]; if ((host_endpoint->desc.bEndpointAddress == 0x82) && (host_endpoint->desc.wMaxPacketSize == 0x10)) { ttusbir->alt_setting = alt_set; ttusbir->endpoint = endp; found = 1; break; } } } if (ttusbir->alt_setting != -1) DPRINTK("alt setting: %d\n", ttusbir->alt_setting); else { err("Could not find alternate setting\n"); kfree(ttusbir); return -EINVAL; } /* OK lets setup this interface setting */ usb_set_interface(ttusbir->udev, 0, ttusbir->alt_setting); /* Store device info in interface structure */ usb_set_intfdata(intf, ttusbir); /* Register as a LIRC plugin */ if (lirc_buffer_init(&ttusbir->rbuf, sizeof(lirc_t), 256) < 0) { err("Could not get memory for LIRC data buffer\n"); usb_set_intfdata(intf, NULL); kfree(ttusbir); return -ENOMEM; } strcpy(ttusbir->plugin.name, "TTUSBIR"); ttusbir->plugin.minor = -1; ttusbir->plugin.code_length = 1; ttusbir->plugin.sample_rate = 0; ttusbir->plugin.data = ttusbir; ttusbir->plugin.add_to_buf = NULL; ttusbir->plugin.get_queue = NULL; ttusbir->plugin.rbuf = &ttusbir->rbuf; ttusbir->plugin.set_use_inc = set_use_inc; ttusbir->plugin.set_use_dec = set_use_dec; ttusbir->plugin.ioctl = NULL; ttusbir->plugin.fops = NULL; ttusbir->plugin.owner = THIS_MODULE; ttusbir->plugin.features = LIRC_CAN_REC_MODE2; ttusbir->minor = lirc_register_plugin(&ttusbir->plugin); if (ttusbir->minor < 0) { err("Error registering as LIRC plugin\n"); usb_set_intfdata(intf, NULL); lirc_buffer_free(&ttusbir->rbuf); kfree(ttusbir); return -EIO; } /* Allocate and setup the URB that we will use to talk to the device */ for (i = 0; i < num_urbs; i++) { ttusbir->urb[i] = usb_alloc_urb(8, GFP_KERNEL); if (!ttusbir->urb[i]) { err("Could not allocate memory for the URB\n"); for (j = i - 1; j >= 0; j--) kfree(ttusbir->urb[j]); lirc_buffer_free(&ttusbir->rbuf); lirc_unregister_plugin(ttusbir->minor); kfree(ttusbir); usb_set_intfdata(intf, NULL); return -ENOMEM; } ttusbir->urb[i]->dev = ttusbir->udev; ttusbir->urb[i]->context = ttusbir; ttusbir->urb[i]->pipe = usb_rcvisocpipe(ttusbir->udev, ttusbir->endpoint); ttusbir->urb[i]->interval = 1; ttusbir->urb[i]->transfer_flags = URB_ISO_ASAP; ttusbir->urb[i]->transfer_buffer = &ttusbir->buffer[i][0]; ttusbir->urb[i]->complete = urb_complete; ttusbir->urb[i]->number_of_packets = 8; ttusbir->urb[i]->transfer_buffer_length = 128; for (j = 0; j < 8; j++) { ttusbir->urb[i]->iso_frame_desc[j].offset = j*16; ttusbir->urb[i]->iso_frame_desc[j].length = 16; } } return 0; }