diff options
Diffstat (limited to 'drivers/isdn/gigaset/usb-gigaset.c')
-rw-r--r-- | drivers/isdn/gigaset/usb-gigaset.c | 92 |
1 files changed, 44 insertions, 48 deletions
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 0bd5d4ba11cd..d81c0e3f7702 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c | |||
@@ -104,6 +104,7 @@ MODULE_DEVICE_TABLE(usb, gigaset_table); | |||
104 | * flags per packet. | 104 | * flags per packet. |
105 | */ | 105 | */ |
106 | 106 | ||
107 | /* functions called if a device of this driver is connected/disconnected */ | ||
107 | static int gigaset_probe(struct usb_interface *interface, | 108 | static int gigaset_probe(struct usb_interface *interface, |
108 | const struct usb_device_id *id); | 109 | const struct usb_device_id *id); |
109 | static void gigaset_disconnect(struct usb_interface *interface); | 110 | static void gigaset_disconnect(struct usb_interface *interface); |
@@ -362,18 +363,12 @@ static void gigaset_read_int_callback(struct urb *urb) | |||
362 | struct inbuf_t *inbuf = urb->context; | 363 | struct inbuf_t *inbuf = urb->context; |
363 | struct cardstate *cs = inbuf->cs; | 364 | struct cardstate *cs = inbuf->cs; |
364 | int status = urb->status; | 365 | int status = urb->status; |
365 | int resubmit = 0; | ||
366 | int r; | 366 | int r; |
367 | unsigned numbytes; | 367 | unsigned numbytes; |
368 | unsigned char *src; | 368 | unsigned char *src; |
369 | unsigned long flags; | 369 | unsigned long flags; |
370 | 370 | ||
371 | if (!status) { | 371 | if (!status) { |
372 | if (!cs->connected) { | ||
373 | err("%s: disconnected", __func__); /* should never happen */ | ||
374 | return; | ||
375 | } | ||
376 | |||
377 | numbytes = urb->actual_length; | 372 | numbytes = urb->actual_length; |
378 | 373 | ||
379 | if (numbytes) { | 374 | if (numbytes) { |
@@ -390,28 +385,26 @@ static void gigaset_read_int_callback(struct urb *urb) | |||
390 | } | 385 | } |
391 | } else | 386 | } else |
392 | gig_dbg(DEBUG_INTR, "Received zero block length"); | 387 | gig_dbg(DEBUG_INTR, "Received zero block length"); |
393 | resubmit = 1; | ||
394 | } else { | 388 | } else { |
395 | /* The urb might have been killed. */ | 389 | /* The urb might have been killed. */ |
396 | gig_dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d", | 390 | gig_dbg(DEBUG_ANY, "%s - nonzero status received: %d", |
397 | __func__, status); | 391 | __func__, status); |
398 | if (status != -ENOENT) { /* not killed */ | 392 | if (status == -ENOENT || status == -ESHUTDOWN) |
399 | if (!cs->connected) { | 393 | /* killed or endpoint shutdown: don't resubmit */ |
400 | err("%s: disconnected", __func__); /* should never happen */ | 394 | return; |
401 | return; | ||
402 | } | ||
403 | resubmit = 1; | ||
404 | } | ||
405 | } | 395 | } |
406 | 396 | ||
407 | if (resubmit) { | 397 | /* resubmit URB */ |
408 | spin_lock_irqsave(&cs->lock, flags); | 398 | spin_lock_irqsave(&cs->lock, flags); |
409 | r = cs->connected ? usb_submit_urb(urb, GFP_ATOMIC) : -ENODEV; | 399 | if (!cs->connected) { |
410 | spin_unlock_irqrestore(&cs->lock, flags); | 400 | spin_unlock_irqrestore(&cs->lock, flags); |
411 | if (r) | 401 | err("%s: disconnected", __func__); |
412 | dev_err(cs->dev, "error %d when resubmitting urb.\n", | 402 | return; |
413 | -r); | ||
414 | } | 403 | } |
404 | r = usb_submit_urb(urb, GFP_ATOMIC); | ||
405 | spin_unlock_irqrestore(&cs->lock, flags); | ||
406 | if (r) | ||
407 | dev_err(cs->dev, "error %d resubmitting URB\n", -r); | ||
415 | } | 408 | } |
416 | 409 | ||
417 | 410 | ||
@@ -422,11 +415,19 @@ static void gigaset_write_bulk_callback(struct urb *urb) | |||
422 | int status = urb->status; | 415 | int status = urb->status; |
423 | unsigned long flags; | 416 | unsigned long flags; |
424 | 417 | ||
425 | if (status) | 418 | switch (status) { |
419 | case 0: /* normal completion */ | ||
420 | break; | ||
421 | case -ENOENT: /* killed */ | ||
422 | gig_dbg(DEBUG_ANY, "%s: killed", __func__); | ||
423 | atomic_set(&cs->hw.usb->busy, 0); | ||
424 | return; | ||
425 | default: | ||
426 | dev_err(cs->dev, "bulk transfer failed (status %d)\n", | 426 | dev_err(cs->dev, "bulk transfer failed (status %d)\n", |
427 | -status); | 427 | -status); |
428 | /* That's all we can do. Communication problems | 428 | /* That's all we can do. Communication problems |
429 | are handled by timeouts or network protocols. */ | 429 | are handled by timeouts or network protocols. */ |
430 | } | ||
430 | 431 | ||
431 | spin_lock_irqsave(&cs->lock, flags); | 432 | spin_lock_irqsave(&cs->lock, flags); |
432 | if (!cs->connected) { | 433 | if (!cs->connected) { |
@@ -682,43 +683,35 @@ static int gigaset_probe(struct usb_interface *interface, | |||
682 | { | 683 | { |
683 | int retval; | 684 | int retval; |
684 | struct usb_device *udev = interface_to_usbdev(interface); | 685 | struct usb_device *udev = interface_to_usbdev(interface); |
685 | unsigned int ifnum; | 686 | struct usb_host_interface *hostif = interface->cur_altsetting; |
686 | struct usb_host_interface *hostif; | ||
687 | struct cardstate *cs = NULL; | 687 | struct cardstate *cs = NULL; |
688 | struct usb_cardstate *ucs = NULL; | 688 | struct usb_cardstate *ucs = NULL; |
689 | struct usb_endpoint_descriptor *endpoint; | 689 | struct usb_endpoint_descriptor *endpoint; |
690 | int buffer_size; | 690 | int buffer_size; |
691 | int alt; | ||
692 | |||
693 | gig_dbg(DEBUG_ANY, | ||
694 | "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", | ||
695 | __func__, le16_to_cpu(udev->descriptor.idVendor), | ||
696 | le16_to_cpu(udev->descriptor.idProduct)); | ||
697 | 691 | ||
698 | retval = -ENODEV; //FIXME | 692 | gig_dbg(DEBUG_ANY, "%s: Check if device matches ...", __func__); |
699 | 693 | ||
700 | /* See if the device offered us matches what we can accept */ | 694 | /* See if the device offered us matches what we can accept */ |
701 | if ((le16_to_cpu(udev->descriptor.idVendor) != USB_M105_VENDOR_ID) || | 695 | if ((le16_to_cpu(udev->descriptor.idVendor) != USB_M105_VENDOR_ID) || |
702 | (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID)) | 696 | (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID)) { |
697 | gig_dbg(DEBUG_ANY, "device ID (0x%x, 0x%x) not for me - skip", | ||
698 | le16_to_cpu(udev->descriptor.idVendor), | ||
699 | le16_to_cpu(udev->descriptor.idProduct)); | ||
703 | return -ENODEV; | 700 | return -ENODEV; |
704 | 701 | } | |
705 | /* this starts to become ascii art... */ | 702 | if (hostif->desc.bInterfaceNumber != 0) { |
706 | hostif = interface->cur_altsetting; | 703 | gig_dbg(DEBUG_ANY, "interface %d not for me - skip", |
707 | alt = hostif->desc.bAlternateSetting; | 704 | hostif->desc.bInterfaceNumber); |
708 | ifnum = hostif->desc.bInterfaceNumber; // FIXME ? | 705 | return -ENODEV; |
709 | 706 | } | |
710 | if (alt != 0 || ifnum != 0) { | 707 | if (hostif->desc.bAlternateSetting != 0) { |
711 | dev_warn(&udev->dev, "ifnum %d, alt %d\n", ifnum, alt); | 708 | dev_notice(&udev->dev, "unsupported altsetting %d - skip", |
709 | hostif->desc.bAlternateSetting); | ||
712 | return -ENODEV; | 710 | return -ENODEV; |
713 | } | 711 | } |
714 | |||
715 | /* Reject application specific intefaces | ||
716 | * | ||
717 | */ | ||
718 | if (hostif->desc.bInterfaceClass != 255) { | 712 | if (hostif->desc.bInterfaceClass != 255) { |
719 | dev_info(&udev->dev, | 713 | dev_notice(&udev->dev, "unsupported interface class %d - skip", |
720 | "%s: Device matched but iface_desc[%d]->bInterfaceClass==%d!\n", | 714 | hostif->desc.bInterfaceClass); |
721 | __func__, ifnum, hostif->desc.bInterfaceClass); | ||
722 | return -ENODEV; | 715 | return -ENODEV; |
723 | } | 716 | } |
724 | 717 | ||
@@ -826,6 +819,9 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
826 | 819 | ||
827 | cs = usb_get_intfdata(interface); | 820 | cs = usb_get_intfdata(interface); |
828 | ucs = cs->hw.usb; | 821 | ucs = cs->hw.usb; |
822 | |||
823 | dev_info(cs->dev, "disconnecting Gigaset USB adapter\n"); | ||
824 | |||
829 | usb_kill_urb(ucs->read_urb); | 825 | usb_kill_urb(ucs->read_urb); |
830 | 826 | ||
831 | gigaset_stop(cs); | 827 | gigaset_stop(cs); |
@@ -833,7 +829,7 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
833 | usb_set_intfdata(interface, NULL); | 829 | usb_set_intfdata(interface, NULL); |
834 | tasklet_kill(&cs->write_tasklet); | 830 | tasklet_kill(&cs->write_tasklet); |
835 | 831 | ||
836 | usb_kill_urb(ucs->bulk_out_urb); /* FIXME: only if active? */ | 832 | usb_kill_urb(ucs->bulk_out_urb); |
837 | 833 | ||
838 | kfree(ucs->bulk_out_buffer); | 834 | kfree(ucs->bulk_out_buffer); |
839 | usb_free_urb(ucs->bulk_out_urb); | 835 | usb_free_urb(ucs->bulk_out_urb); |