+
+
+
+/* --------------------------------------------------------------------------------------------------- */
+
+
+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);
+}