|
@@ -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);
|
|
|
|