Commit 7cf130fd authored by Marcel Holtmann's avatar Marcel Holtmann

[Bluetooth] Adapt changes for USB core altsettings

The USB core has changed its way the interfaces and the altsettings are
stored. The probe routines of the USB based Bluetooth drivers must be
changed and in some cases they are simplified.

Patch from Alan Stern <stern@rowland.harvard.edu>
parent f5174ca0
...@@ -174,7 +174,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id ...@@ -174,7 +174,7 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id
BT_DBG("intf %p id %p", intf, id); BT_DBG("intf %p id %p", intf, id);
if (intf->altsetting->desc.bInterfaceNumber != 0) if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
return -ENODEV; return -ENODEV;
data = kmalloc(sizeof(*data), GFP_KERNEL); data = kmalloc(sizeof(*data), GFP_KERNEL);
......
...@@ -661,11 +661,11 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i ...@@ -661,11 +661,11 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
BT_DBG("intf %p id %p", intf, id); BT_DBG("intf %p id %p", intf, id);
/* Check number of endpoints */ /* Check number of endpoints */
if (intf->altsetting[0].desc.bNumEndpoints < 2) if (intf->cur_altsetting->desc.bNumEndpoints < 2)
return -EIO; return -EIO;
bulk_out_ep = &intf->altsetting[0].endpoint[0]; bulk_out_ep = &intf->cur_altsetting->endpoint[0];
bulk_in_ep = &intf->altsetting[0].endpoint[1]; bulk_in_ep = &intf->cur_altsetting->endpoint[1];
if (!bulk_out_ep || !bulk_in_ep) { if (!bulk_out_ep || !bulk_in_ep) {
BT_ERR("Bulk endpoints not found"); BT_ERR("Bulk endpoints not found");
......
...@@ -795,17 +795,15 @@ static void hci_usb_destruct(struct hci_dev *hdev) ...@@ -795,17 +795,15 @@ static void hci_usb_destruct(struct hci_dev *hdev)
int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
{ {
struct usb_device *udev = interface_to_usbdev(intf); struct usb_device *udev = interface_to_usbdev(intf);
struct usb_host_endpoint *bulk_out_ep[HCI_MAX_IFACE_NUM]; struct usb_host_endpoint *bulk_out_ep = NULL;
struct usb_host_endpoint *isoc_out_ep[HCI_MAX_IFACE_NUM]; struct usb_host_endpoint *bulk_in_ep = NULL;
struct usb_host_endpoint *bulk_in_ep[HCI_MAX_IFACE_NUM]; struct usb_host_endpoint *intr_in_ep = NULL;
struct usb_host_endpoint *isoc_in_ep[HCI_MAX_IFACE_NUM];
struct usb_host_endpoint *intr_in_ep[HCI_MAX_IFACE_NUM];
struct usb_host_endpoint *ep; struct usb_host_endpoint *ep;
struct usb_host_interface *uif; struct usb_host_interface *uif;
struct usb_interface *iface, *isoc_iface; struct usb_interface *isoc_iface;
struct hci_usb *husb; struct hci_usb *husb;
struct hci_dev *hdev; struct hci_dev *hdev;
int i, a, e, size, ifn, isoc_ifnum, isoc_alts; int i, e, size, isoc_ifnum, isoc_alts;
BT_DBG("udev %p intf %p", udev, intf); BT_DBG("udev %p intf %p", udev, intf);
...@@ -816,84 +814,38 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -816,84 +814,38 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
id = match; id = match;
} }
iface = udev->actconfig->interface[0];
if (id->driver_info & HCI_IGNORE) if (id->driver_info & HCI_IGNORE)
return -ENODEV; return -ENODEV;
if (intf->altsetting->desc.bInterfaceNumber > 0) if (intf->cur_altsetting->desc.bInterfaceNumber > 0)
return -ENODEV; return -ENODEV;
/* Check number of endpoints */
if (intf->altsetting[0].desc.bNumEndpoints < 3)
return -EIO;
memset(bulk_out_ep, 0, sizeof(bulk_out_ep));
memset(isoc_out_ep, 0, sizeof(isoc_out_ep));
memset(bulk_in_ep, 0, sizeof(bulk_in_ep));
memset(isoc_in_ep, 0, sizeof(isoc_in_ep));
memset(intr_in_ep, 0, sizeof(intr_in_ep));
size = 0;
isoc_iface = NULL;
isoc_alts = isoc_ifnum = 0;
/* Find endpoints that we need */ /* Find endpoints that we need */
ifn = min_t(unsigned int, udev->actconfig->desc.bNumInterfaces, HCI_MAX_IFACE_NUM); uif = intf->cur_altsetting;
for (i = 0; i < ifn; i++) { for (e = 0; e < uif->desc.bNumEndpoints; e++) {
iface = udev->actconfig->interface[i]; ep = &uif->endpoint[e];
for (a = 0; a < iface->num_altsetting; a++) {
uif = &iface->altsetting[a]; switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
for (e = 0; e < uif->desc.bNumEndpoints; e++) { case USB_ENDPOINT_XFER_INT:
ep = &uif->endpoint[e]; if (ep->desc.bEndpointAddress & USB_DIR_IN)
intr_in_ep = ep;
switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { break;
case USB_ENDPOINT_XFER_INT:
if (ep->desc.bEndpointAddress & USB_DIR_IN) case USB_ENDPOINT_XFER_BULK:
intr_in_ep[i] = ep; if (ep->desc.bEndpointAddress & USB_DIR_IN)
break; bulk_in_ep = ep;
else
case USB_ENDPOINT_XFER_BULK: bulk_out_ep = ep;
if (ep->desc.bEndpointAddress & USB_DIR_IN) break;
bulk_in_ep[i] = ep;
else
bulk_out_ep[i] = ep;
break;
#ifdef CONFIG_BT_HCIUSB_SCO
case USB_ENDPOINT_XFER_ISOC:
if (ep->desc.wMaxPacketSize < size || a > 2)
break;
size = ep->desc.wMaxPacketSize;
isoc_iface = iface;
isoc_alts = a;
isoc_ifnum = i;
if (ep->desc.bEndpointAddress & USB_DIR_IN)
isoc_in_ep[i] = ep;
else
isoc_out_ep[i] = ep;
break;
#endif
}
}
} }
} }
if (!bulk_in_ep[0] || !bulk_out_ep[0] || !intr_in_ep[0]) { if (!bulk_in_ep || !bulk_out_ep || !intr_in_ep) {
BT_DBG("Bulk endpoints not found"); BT_DBG("Bulk endpoints not found");
goto done; goto done;
} }
#ifdef CONFIG_BT_HCIUSB_SCO
if (!isoc_in_ep[1] || !isoc_out_ep[1]) {
BT_DBG("Isoc endpoints not found");
isoc_iface = NULL;
}
#endif
if (!(husb = kmalloc(sizeof(struct hci_usb), GFP_KERNEL))) { if (!(husb = kmalloc(sizeof(struct hci_usb), GFP_KERNEL))) {
BT_ERR("Can't allocate: control structure"); BT_ERR("Can't allocate: control structure");
goto done; goto done;
...@@ -902,26 +854,67 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -902,26 +854,67 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
memset(husb, 0, sizeof(struct hci_usb)); memset(husb, 0, sizeof(struct hci_usb));
husb->udev = udev; husb->udev = udev;
husb->bulk_out_ep = bulk_out_ep[0]; husb->bulk_out_ep = bulk_out_ep;
husb->bulk_in_ep = bulk_in_ep[0]; husb->bulk_in_ep = bulk_in_ep;
husb->intr_in_ep = intr_in_ep[0]; husb->intr_in_ep = intr_in_ep;
if (id->driver_info & HCI_DIGIANSWER) if (id->driver_info & HCI_DIGIANSWER)
husb->ctrl_req = HCI_DIGI_REQ; husb->ctrl_req = HCI_DIGI_REQ;
else else
husb->ctrl_req = HCI_CTRL_REQ; husb->ctrl_req = HCI_CTRL_REQ;
/* Find isochronous endpoints that we can use */
size = 0;
isoc_iface = NULL;
isoc_alts = 0;
isoc_ifnum = 1;
#ifdef CONFIG_BT_HCIUSB_SCO #ifdef CONFIG_BT_HCIUSB_SCO
isoc_iface = usb_ifnum_to_if(udev, isoc_ifnum);
if (isoc_iface) { if (isoc_iface) {
BT_DBG("isoc ifnum %d alts %d", isoc_ifnum, isoc_alts); int a;
if (usb_set_interface(udev, isoc_ifnum, isoc_alts)) { struct usb_host_endpoint *isoc_out_ep = NULL;
BT_ERR("Can't set isoc interface settings"); struct usb_host_endpoint *isoc_in_ep = NULL;
isoc_iface = NULL;
for (a = 0; a < isoc_iface->num_altsetting; a++) {
uif = &isoc_iface->altsetting[a];
for (e = 0; e < uif->desc.bNumEndpoints; e++) {
ep = &uif->endpoint[e];
switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
case USB_ENDPOINT_XFER_ISOC:
if (ep->desc.wMaxPacketSize < size ||
uif->desc.bAlternateSetting > 2)
break;
size = ep->desc.wMaxPacketSize;
isoc_alts = uif->desc.bAlternateSetting;
if (ep->desc.bEndpointAddress & USB_DIR_IN)
isoc_in_ep = ep;
else
isoc_out_ep = ep;
break;
}
}
}
if (!isoc_in_ep || !isoc_out_ep)
BT_DBG("Isoc endpoints not found");
else {
BT_DBG("isoc ifnum %d alts %d", isoc_ifnum, isoc_alts);
if (usb_driver_claim_interface(&hci_usb_driver, isoc_iface, husb) != 0)
BT_ERR("Can't claim isoc interface");
else if (usb_set_interface(udev, isoc_ifnum, isoc_alts)) {
BT_ERR("Can't set isoc interface settings");
usb_driver_release_interface(&hci_usb_driver, isoc_iface);
} else {
husb->isoc_iface = isoc_iface;
husb->isoc_in_ep = isoc_in_ep;
husb->isoc_out_ep = isoc_out_ep;
}
} }
usb_driver_claim_interface(&hci_usb_driver, isoc_iface, husb);
husb->isoc_iface = isoc_iface;
husb->isoc_in_ep = isoc_in_ep[isoc_ifnum];
husb->isoc_out_ep = isoc_out_ep[isoc_ifnum];
} }
#endif #endif
...@@ -967,6 +960,8 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -967,6 +960,8 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
return 0; return 0;
probe_error: probe_error:
if (husb->isoc_iface)
usb_driver_release_interface(&hci_usb_driver, husb->isoc_iface);
kfree(husb); kfree(husb);
done: done:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment