diff options
author | Holger Nelson <hnelson@hnelson.de> | 2011-12-28 18:55:41 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-01-06 11:37:07 -0200 |
commit | 8ab3362665a699bd54fc489ff7fb6372678b94c1 (patch) | |
tree | 05baa99a41717f5abdd9f690488d22ffe63c0833 /drivers/media/video/em28xx/em28xx-cards.c | |
parent | 4d28d3d9978b84326a4608c25bda484973bba0a6 (diff) |
[media] em28xx: Reworked probe code to get rid of some hacks
Reworked device probing to get rid of hacks to guess the maximum size of
dvb iso transfer packets. The new code also selects the first alternate
config which supports the largest possible iso transfers for dvb.
[mchehab@redhat.com: Fix a few checkpatch.pl CodingStyle compliants]
Signed-off-by: Holger Nelson <hnelson@hnelson.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-cards.c')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-cards.c | 148 |
1 files changed, 72 insertions, 76 deletions
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index b95e6614650..0adaf8402a8 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -3111,12 +3111,11 @@ unregister_dev: static int em28xx_usb_probe(struct usb_interface *interface, const struct usb_device_id *id) { - const struct usb_endpoint_descriptor *endpoint; struct usb_device *udev; struct em28xx *dev = NULL; int retval; - bool is_audio_only = false, has_audio = false; - int i, nr, isoc_pipe; + bool has_audio = false, has_video = false, has_dvb = false; + int i, nr; const int ifnum = interface->altsetting[0].desc.bInterfaceNumber; char *speed; char descr[255] = ""; @@ -3148,54 +3147,65 @@ static int em28xx_usb_probe(struct usb_interface *interface, goto err; } + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + em28xx_err(DRIVER_NAME ": out of memory!\n"); + retval = -ENOMEM; + goto err; + } + + /* compute alternate max packet sizes */ + dev->alt_max_pkt_size = kmalloc(sizeof(dev->alt_max_pkt_size[0]) * + interface->num_altsetting, GFP_KERNEL); + if (dev->alt_max_pkt_size == NULL) { + em28xx_errdev("out of memory!\n"); + kfree(dev); + retval = -ENOMEM; + goto err; + } + /* Get endpoints */ for (i = 0; i < interface->num_altsetting; i++) { int ep; for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) { - struct usb_host_endpoint *e; - e = &interface->altsetting[i].endpoint[ep]; - - if (e->desc.bEndpointAddress == 0x83) - has_audio = true; + const struct usb_endpoint_descriptor *e; + int sizedescr, size; + + e = &interface->altsetting[i].endpoint[ep].desc; + + sizedescr = le16_to_cpu(e->wMaxPacketSize); + size = sizedescr & 0x7ff; + + if (udev->speed == USB_SPEED_HIGH) + size = size * hb_mult(sizedescr); + + if (usb_endpoint_xfer_isoc(e) && + usb_endpoint_dir_in(e)) { + switch (e->bEndpointAddress) { + case EM28XX_EP_AUDIO: + has_audio = true; + break; + case EM28XX_EP_ANALOG: + has_video = true; + dev->alt_max_pkt_size[i] = size; + break; + case EM28XX_EP_DIGITAL: + has_dvb = true; + if (size > dev->dvb_max_pkt_size) { + dev->dvb_max_pkt_size = size; + dev->dvb_alt = i; + } + break; + } + } } } - endpoint = &interface->cur_altsetting->endpoint[0].desc; - - /* check if the device has the iso in endpoint at the correct place */ - if (usb_endpoint_xfer_isoc(endpoint) - && - (interface->altsetting[1].endpoint[0].desc.wMaxPacketSize == 940)) { - /* It's a newer em2874/em2875 device */ - isoc_pipe = 0; - } else { - int check_interface = 1; - isoc_pipe = 1; - endpoint = &interface->cur_altsetting->endpoint[1].desc; - if (!usb_endpoint_xfer_isoc(endpoint)) - check_interface = 0; - - if (usb_endpoint_dir_out(endpoint)) - check_interface = 0; - - if (!check_interface) { - if (has_audio) { - is_audio_only = true; - } else { - em28xx_err(DRIVER_NAME " video device (%04x:%04x): " - "interface %i, class %i found.\n", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), - ifnum, - interface->altsetting[0].desc.bInterfaceClass); - em28xx_err(DRIVER_NAME " This is an anciliary " - "interface not used by the driver\n"); - - retval = -ENODEV; - goto err; - } - } + if (!(has_audio || has_video || has_dvb)) { + retval = -ENODEV; + goto err_free; } switch (udev->speed) { @@ -3221,6 +3231,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, strlcat(descr, " ", sizeof(descr)); strlcat(descr, udev->product, sizeof(descr)); } + if (*descr) strlcat(descr, " ", sizeof(descr)); @@ -3237,6 +3248,14 @@ static int em28xx_usb_probe(struct usb_interface *interface, printk(KERN_INFO DRIVER_NAME ": Audio Vendor Class interface %i found\n", ifnum); + if (has_video) + printk(KERN_INFO DRIVER_NAME + ": Video interface %i found\n", + ifnum); + if (has_dvb) + printk(KERN_INFO DRIVER_NAME + ": DVB interface %i found\n", + ifnum); /* * Make sure we have 480 Mbps of bandwidth, otherwise things like @@ -3248,22 +3267,14 @@ static int em28xx_usb_probe(struct usb_interface *interface, printk(DRIVER_NAME ": Device must be connected to a high-speed" " USB 2.0 port.\n"); retval = -ENODEV; - goto err; - } - - /* allocate memory for our device state and initialize it */ - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - em28xx_err(DRIVER_NAME ": out of memory!\n"); - retval = -ENOMEM; - goto err; + goto err_free; } snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr); dev->devno = nr; dev->model = id->driver_info; dev->alt = -1; - dev->is_audio_only = is_audio_only; + dev->is_audio_only = has_audio && !(has_video || has_dvb); dev->has_alsa_audio = has_audio; dev->audio_ifnum = ifnum; @@ -3276,26 +3287,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, } } - /* compute alternate max packet sizes */ dev->num_alt = interface->num_altsetting; - dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL); - - if (dev->alt_max_pkt_size == NULL) { - em28xx_errdev("out of memory!\n"); - kfree(dev); - retval = -ENOMEM; - goto err; - } - - for (i = 0; i < dev->num_alt ; i++) { - u16 tmp = le16_to_cpu(interface->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize); - unsigned int size = tmp & 0x7ff; - - if (udev->speed == USB_SPEED_HIGH) - size = size * hb_mult(tmp); - - dev->alt_max_pkt_size[i] = size; - } if ((card[nr] >= 0) && (card[nr] < em28xx_bcount)) dev->model = card[nr]; @@ -3308,10 +3300,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, mutex_lock(&dev->lock); retval = em28xx_init_dev(&dev, udev, interface, nr); if (retval) { - mutex_unlock(&dev->lock); - kfree(dev->alt_max_pkt_size); - kfree(dev); - goto err; + goto unlock_and_free; } request_modules(dev); @@ -3330,6 +3319,13 @@ static int em28xx_usb_probe(struct usb_interface *interface, return 0; +unlock_and_free: + mutex_unlock(&dev->lock); + +err_free: + kfree(dev->alt_max_pkt_size); + kfree(dev); + err: clear_bit(nr, &em28xx_devused); |