]> rtime.felk.cvut.cz Git - lincan.git/blobdiff - lincan/src/usbcan.c
Unoptimized usb extension, adds proc and devfs entry removing function, changed proc...
[lincan.git] / lincan / src / usbcan.c
index aff02d3095df5414ce537d9fe46d3083505b46f5..ad79d58510d5b7b021b6c1fa3f6c785ff9375e8a 100644 (file)
@@ -1133,3 +1133,228 @@ int usbcan_fill_chipspecops(struct canchip_t *chip)
 {
        return 0;
 }
+
+
+
+/* --------------------------------------------------------------------------------------------------- */
+
+
+static void ul_usb1_irq(struct urb *urb)
+{
+       struct usb_ul_usb1 *dev = urb->context;
+       struct ul_usb1_combo devc;
+       int retval;
+
+       CANMSG("Interrupt poll\n");
+
+       switch (urb->status) {
+       case 0:
+               /* success */
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               CANMSG("%s - urb shutting down with status: %d\n", __FUNCTION__, urb->status);
+               return;
+       default:
+               CANMSG("%s - nonzero urb status received: %d\n", __FUNCTION__, urb->status);
+               goto exit;
+       }
+
+       devc.dev = dev;
+       devc.urb = urb;
+
+       dev->candev->chip[0]->chipspecops->irq_handler(0,dev->candev->chip[0]);
+       CANMSG("Interrupt caught\n");
+
+ exit:
+       retval = usb_submit_urb (urb, GFP_ATOMIC);
+       if (retval)
+               CANMSG("%s - usb_submit_urb failed with result %d\n",
+                    __FUNCTION__, retval);
+}
+
+static void ul_usb1_delete(struct usb_ul_usb1 *dev)
+{
+       usb_put_dev(dev->udev);
+       usb_kill_urb(dev->irq);
+       usb_free_urb(dev->irq);
+       kfree(dev->bulk_in_buffer);
+       kfree(dev->int_in_buffer);
+       if (dev->candev){
+               dev->candev->sysdevptr.anydev=NULL;
+               cleanup_usbdev(dev->candev);
+       }
+       kfree(dev);
+}
+
+static int ul_usb1_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+       struct usb_ul_usb1 *dev;
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       struct candevice_t *candev;
+       size_t buffer_size;
+       int i;
+       int retval = -ENOMEM;
+
+       /* allocate memory for our device state and initialize it */
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev) {
+               err("Out of memory");
+               goto error;
+       }
+       sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
+       mutex_init(&dev->io_mutex);
+       spin_lock_init(&dev->err_lock);
+       init_usb_anchor(&dev->submitted);
+
+//     dev->udev = usb_get_dev(interface_to_usbdev(interface));
+       dev->udev = interface_to_usbdev(interface);
+       dev->interface = interface;
+
+       /* set up the endpoint information */
+       /* use only the first bulk-in and bulk-out endpoints */
+       iface_desc = interface->cur_altsetting;
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+               endpoint = &iface_desc->endpoint[i].desc;
+
+               if (!dev->bulk_in_endpointAddr &&
+                   usb_endpoint_is_bulk_in(endpoint)) {
+                       /* we found a bulk in endpoint */
+                       buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+                       dev->bulk_in_size = buffer_size;
+                       dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
+                       dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+                       if (!dev->bulk_in_buffer) {
+                               err("Could not allocate bulk_in_buffer");
+                               goto error;
+                       }
+               }
+
+               if (!dev->bulk_out_endpointAddr &&
+                   usb_endpoint_is_bulk_out(endpoint)) {
+                       /* we found a bulk out endpoint */
+                               dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
+               }
+
+               if (!dev->int_in_endpointAddr &&
+                   usb_endpoint_is_int_in(endpoint)) {
+                       /* we found an interrupt in endpoint */
+                       buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+                       dev->int_in_size = buffer_size;
+                       dev->int_in_endpointAddr = endpoint->bEndpointAddress;
+                       dev->int_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+                       dev->int_in_interval = endpoint->bInterval;
+                       if (!dev->int_in_buffer) {
+                               err("Could not allocate int_in_buffer");
+                               goto error;
+                       }
+               }
+       }
+       if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr && dev->int_in_endpointAddr)) {
+               err("Could not find all bulk-in, bulk-out and interrupt endpoints");
+               goto error;
+       }
+
+       /* save our data pointer in this interface device */
+       usb_set_intfdata(interface, dev);
+
+       if (main_init_done==1)
+               register_usbdev("ul_usb1",(void *) dev);
+       else {
+               mutex_lock(&usbdev_reg_mutex);
+               if (main_init_done==1)
+                       register_usbdev("ul_usb1",(void *) dev);
+               else {
+                       for (i=0;i<MAX_HW_CARDS;i++){
+                               if (usbregq[i]==NULL){
+                                       usbregq[i]=(struct usbdev_reg_query *)can_checked_malloc(sizeof(struct usbdev_reg_query));
+                                       if (!usbregq[i]){
+                                               CANMSG("Error allocating usbdev_reg_query");
+                                               mutex_unlock(&usbdev_reg_mutex);
+                                               goto error;
+                                       }
+                                       sprintf (usbregq[i]->hwname,"ul_usb1");
+                                       usbregq[i]->anydev=(void *) dev;
+                                       break;
+                               }
+                       }
+                       if (i==MAX_HW_CARDS){
+                               CANMSG("No free space to register new card");
+                               mutex_unlock(&usbdev_reg_mutex);
+                               goto error;
+                       }
+               }
+               mutex_unlock(&usbdev_reg_mutex);
+       }
+
+       dev->irq = usb_alloc_urb(0, GFP_KERNEL);
+       if (!dev->irq){
+               CANMSG("Error allocating usb urb\n");
+               goto error;
+       }
+       dev->irq->dev = dev->udev;
+       usb_fill_int_urb(dev->irq, dev->udev,
+                        usb_rcvintpipe(dev->udev, dev->int_in_endpointAddr),
+                        dev->int_in_buffer, dev->int_in_size,
+                        ul_usb1_irq, dev, dev->int_in_interval);
+/*     usb_fill_bulk_urb(dev->irq, dev->udev,
+                        usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
+                        dev->int_in_buffer, dev->int_in_size,
+                        ul_usb1_irq, dev);*/
+
+/*     dev->irq->transfer_dma = wacom->data_dma;
+       dev->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;*/
+       retval=usb_submit_urb(dev->irq, GFP_KERNEL);
+       if (retval){
+               CANMSG("INT URB %d\n",retval);
+               return -EIO;
+       }else
+               CANMSG("INT URB SUCCCESS\n");
+
+       /* let the user know what node this device is now attached to */
+       info("USB Skeleton device now attached");
+       return 0;
+
+error:
+               ul_usb1_delete(dev);
+       return retval;
+}
+
+static void ul_usb1_disconnect(struct usb_interface *interface)
+{
+       struct usb_ul_usb1 *dev;
+       int minor = interface->minor;
+
+       dev = usb_get_intfdata(interface);
+       usb_set_intfdata(interface, NULL);
+
+       /* prevent more I/O from starting */
+       mutex_lock(&dev->io_mutex);
+       dev->interface = NULL;
+       mutex_unlock(&dev->io_mutex);
+
+       //usb_kill_anchored_urbs(&dev->submitted);
+
+       ul_usb1_delete(dev);
+
+       info("USB Skeleton now disconnected");
+}
+
+static struct usb_driver ul_usb1_driver = {
+       .name =         "ul_usb1-can",
+       .id_table = ul_usb1_table,
+       .probe =        ul_usb1_probe,
+       .disconnect =   ul_usb1_disconnect,
+       .id_table =     ul_usb1_table,
+};
+
+int ul_usb1_init(void){
+       return usb_register(&ul_usb1_driver);
+}
+
+void ul_usb1_exit(void){
+       usb_deregister(&ul_usb1_driver);
+}