From: Duncan Sands <baldrick@free.fr>
To: Greg KH <greg@kroah.com>
Cc: usbatm@lists.infradead.org,
linux-usb-devel@lists.sourceforge.net,
linux-kernel@vger.kernel.org
Subject: [PATCH 05/13] USBATM: xusbatm rewrite
Date: Fri, 13 Jan 2006 09:48:36 +0100 [thread overview]
Message-ID: <200601130948.36673.baldrick@free.fr> (raw)
In-Reply-To: <200601121729.52596.baldrick@free.fr>
[-- Attachment #1: Type: text/plain, Size: 384 bytes --]
The xusbatm driver is for otherwise unsupported modems.
All it does is grab hold of a user-specified set of
interfaces - the generic usbatm core methods (hopefully)
do the rest. As Aurelio Arroyo discovered when he tried
to use xusbatm (big mistake!), the interface grabbing logic
was completely borked. Here is a rewrite that works.
Signed-off-by: Duncan Sands <baldrick@free.fr>
[-- Attachment #2: 05-xusbatm --]
[-- Type: text/x-csrc, Size: 6645 bytes --]
Index: Linux/drivers/usb/atm/xusbatm.c
===================================================================
--- Linux.orig/drivers/usb/atm/xusbatm.c 2006-01-13 08:48:09.000000000 +0100
+++ Linux/drivers/usb/atm/xusbatm.c 2006-01-13 08:57:07.000000000 +0100
@@ -41,6 +41,8 @@
XUSBATM_PARM(tx_endpoint, unsigned char, byte, "tx endpoint number");
XUSBATM_PARM(rx_padding, unsigned char, byte, "rx padding (default 0)");
XUSBATM_PARM(tx_padding, unsigned char, byte, "tx padding (default 0)");
+XUSBATM_PARM(rx_altsetting, unsigned char, byte, "rx altsetting (default 0)");
+XUSBATM_PARM(tx_altsetting, unsigned char, byte, "rx altsetting (default 0)");
static const char xusbatm_driver_name[] = "xusbatm";
@@ -48,61 +50,94 @@
static struct usb_device_id xusbatm_usb_ids[XUSBATM_DRIVERS_MAX + 1];
static struct usb_driver xusbatm_usb_driver;
-static int usb_intf_has_ep(const struct usb_interface *intf, u8 ep)
+static struct usb_interface *xusbatm_find_intf (struct usb_device *usb_dev, int altsetting, u8 ep)
{
+ struct usb_host_interface *alt;
+ struct usb_interface *intf;
int i, j;
- for (i = 0; i < intf->num_altsetting; i++) {
- struct usb_host_interface *alt = intf->altsetting;
- for (j = 0; j < alt->desc.bNumEndpoints; j++)
- if ((alt->endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) == ep)
- return 1;
+ for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++)
+ if ((intf = usb_dev->actconfig->interface[i]) && (alt = usb_altnum_to_altsetting(intf, altsetting)))
+ for (j = 0; j < alt->desc.bNumEndpoints; j++)
+ if (alt->endpoint[j].desc.bEndpointAddress == ep)
+ return intf;
+ return NULL;
+}
+
+static int xusbatm_capture_intf (struct usbatm_data *usbatm, struct usb_device *usb_dev,
+ struct usb_interface *intf, int altsetting, int claim)
+{
+ int ifnum = intf->altsetting->desc.bInterfaceNumber;
+ int ret;
+
+ if (claim && (ret = usb_driver_claim_interface(&xusbatm_usb_driver, intf, usbatm))) {
+ usb_err(usbatm, "%s: failed to claim interface %2d (%d)!\n", __func__, ifnum, ret);
+ return ret;
+ }
+ if ((ret = usb_set_interface(usb_dev, ifnum, altsetting))) {
+ usb_err(usbatm, "%s: altsetting %2d for interface %2d failed (%d)!\n", __func__, altsetting, ifnum, ret);
+ return ret;
}
return 0;
}
+static void xusbatm_release_intf (struct usb_device *usb_dev, struct usb_interface *intf, int claimed)
+{
+ if (claimed) {
+ usb_set_intfdata(intf, NULL);
+ usb_driver_release_interface(&xusbatm_usb_driver, intf);
+ }
+}
+
static int xusbatm_bind(struct usbatm_data *usbatm,
struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *usb_dev = interface_to_usbdev(intf);
int drv_ix = id - xusbatm_usb_ids;
- int rx_ep_present = usb_intf_has_ep(intf, rx_endpoint[drv_ix]);
- int tx_ep_present = usb_intf_has_ep(intf, tx_endpoint[drv_ix]);
- u8 searched_ep = rx_ep_present ? tx_endpoint[drv_ix] : rx_endpoint[drv_ix];
- int i, ret;
+ int rx_alt = rx_altsetting[drv_ix];
+ int tx_alt = tx_altsetting[drv_ix];
+ struct usb_interface *rx_intf = xusbatm_find_intf(usb_dev, rx_alt, rx_endpoint[drv_ix]);
+ struct usb_interface *tx_intf = xusbatm_find_intf(usb_dev, tx_alt, tx_endpoint[drv_ix]);
+ int ret;
usb_dbg(usbatm, "%s: binding driver %d: vendor %04x product %04x"
- " rx: ep %02x padd %d tx: ep %02x padd %d\n",
+ " rx: ep %02x padd %d alt %2d tx: ep %02x padd %d alt %2d\n",
__func__, drv_ix, vendor[drv_ix], product[drv_ix],
- rx_endpoint[drv_ix], rx_padding[drv_ix],
- tx_endpoint[drv_ix], tx_padding[drv_ix]);
+ rx_endpoint[drv_ix], rx_padding[drv_ix], rx_alt,
+ tx_endpoint[drv_ix], tx_padding[drv_ix], tx_alt);
- if (!rx_ep_present && !tx_ep_present) {
- usb_dbg(usbatm, "%s: intf #%d has neither rx (%#x) nor tx (%#x) endpoint\n",
- __func__, intf->altsetting->desc.bInterfaceNumber,
- rx_endpoint[drv_ix], tx_endpoint[drv_ix]);
+ if (!rx_intf || !tx_intf) {
+ if (!rx_intf)
+ usb_dbg(usbatm, "%s: no interface contains endpoint %02x in altsetting %2d\n",
+ __func__, rx_endpoint[drv_ix], rx_alt);
+ if (!tx_intf)
+ usb_dbg(usbatm, "%s: no interface contains endpoint %02x in altsetting %2d\n",
+ __func__, tx_endpoint[drv_ix], tx_alt);
return -ENODEV;
}
- if (rx_ep_present && tx_ep_present)
- return 0;
+ if ((rx_intf != intf) && (tx_intf != intf))
+ return -ENODEV;
- for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) {
- struct usb_interface *cur_if = usb_dev->actconfig->interface[i];
+ if ((rx_intf == tx_intf) && (rx_alt != tx_alt)) {
+ usb_err(usbatm, "%s: altsettings clash on interface %2d (%2d vs %2d)!\n", __func__,
+ rx_intf->altsetting->desc.bInterfaceNumber, rx_alt, tx_alt);
+ return -EINVAL;
+ }
- if (cur_if != intf && usb_intf_has_ep(cur_if, searched_ep)) {
- ret = usb_driver_claim_interface(&xusbatm_usb_driver,
- cur_if, usbatm);
- if (!ret)
- usb_err(usbatm, "%s: failed to claim interface #%d (%d)\n",
- __func__, cur_if->altsetting->desc.bInterfaceNumber, ret);
- return ret;
- }
+ usb_dbg(usbatm, "%s: rx If#=%2d; tx If#=%2d\n", __func__,
+ rx_intf->altsetting->desc.bInterfaceNumber,
+ tx_intf->altsetting->desc.bInterfaceNumber);
+
+ if ((ret = xusbatm_capture_intf(usbatm, usb_dev, rx_intf, rx_alt, rx_intf != intf)))
+ return ret;
+
+ if ((tx_intf != rx_intf) && (ret = xusbatm_capture_intf(usbatm, usb_dev, tx_intf, tx_alt, tx_intf != intf))) {
+ xusbatm_release_intf(usb_dev, rx_intf, rx_intf != intf);
+ return ret;
}
- usb_err(usbatm, "%s: no interface has endpoint %#x\n",
- __func__, searched_ep);
- return -ENODEV;
+ return 0;
}
static void xusbatm_unbind(struct usbatm_data *usbatm,
@@ -114,9 +149,12 @@
usb_dbg(usbatm, "%s entered\n", __func__);
for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) {
- struct usb_interface *cur_if = usb_dev->actconfig->interface[i];
- usb_set_intfdata(cur_if, NULL);
- usb_driver_release_interface(&xusbatm_usb_driver, cur_if);
+ struct usb_interface *cur_intf = usb_dev->actconfig->interface[i];
+
+ if (cur_intf && (usb_get_intfdata(cur_intf) == usbatm)) {
+ usb_set_intfdata(cur_intf, NULL);
+ usb_driver_release_interface(&xusbatm_usb_driver, cur_intf);
+ }
}
}
@@ -161,11 +199,13 @@
}
for (i = 0; i < num_vendor; i++) {
+ rx_endpoint[i] |= USB_DIR_IN;
+ tx_endpoint[i] &= USB_ENDPOINT_NUMBER_MASK;
+
xusbatm_usb_ids[i].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
xusbatm_usb_ids[i].idVendor = vendor[i];
xusbatm_usb_ids[i].idProduct = product[i];
-
xusbatm_drivers[i].driver_name = xusbatm_driver_name;
xusbatm_drivers[i].bind = xusbatm_bind;
xusbatm_drivers[i].unbind = xusbatm_unbind;
next prev parent reply other threads:[~2006-01-13 8:48 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-01-12 16:29 [PATCH 00/13] USBATM: summary Duncan Sands
2006-01-12 16:43 ` [PATCH 01/13] USBATM: trivial modifications Duncan Sands
2006-01-12 17:40 ` Duncan Sands
2006-01-12 17:48 ` [PATCH 02/13] USBATM: add flags field Duncan Sands
2006-01-12 18:30 ` [PATCH 00/13] USBATM: summary Greg KH
2006-01-12 19:15 ` Duncan Sands
2006-01-13 10:30 ` [linux-usb-devel] " Duncan Sands
2006-01-13 8:36 ` [PATCH 03/13] USBATM: remove .owner Duncan Sands
2006-01-13 8:38 ` [PATCH 04/13] USBATM: kzalloc conversion Duncan Sands
2006-01-13 8:48 ` Duncan Sands [this message]
2006-01-13 9:05 ` [PATCH 06/13] USBATM: shutdown open connections when disconnected Duncan Sands
2006-08-18 19:40 ` R: " Giampaolo Tomassoni
2006-01-13 9:07 ` [PATCH 07/13] USBATM: return correct error code when out of memory Duncan Sands
2006-01-13 9:13 ` [PATCH 08/13] USBATM: use dev_kfree_skb_any rather than dev_kfree_skb Duncan Sands
2006-01-13 9:52 ` [PATCH 09/13] USBATM: measure buffer size in bytes; force valid sizes Duncan Sands
2006-01-13 9:59 ` [PATCH 10/13] USBATM: allow isochronous transfer Duncan Sands
2006-01-13 10:06 ` [PATCH 11/13] USBATM: handle urbs containing partial cells Duncan Sands
2006-01-13 10:08 ` [PATCH 12/13] USBATM: bump version numbers Duncan Sands
2006-01-13 10:12 ` [PATCH 13/13] USBATM: -EILSEQ workaround Duncan Sands
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200601130948.36673.baldrick@free.fr \
--to=baldrick@free.fr \
--cc=greg@kroah.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb-devel@lists.sourceforge.net \
--cc=usbatm@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox