aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/core/message.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/message.c')
-rw-r--r--drivers/usb/core/message.c78
1 files changed, 36 insertions, 42 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index d8f7b089a8f..c021af39037 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -59,8 +59,8 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
dev_dbg(&urb->dev->dev,
"%s timed out on ep%d%s len=%d/%d\n",
current->comm,
- usb_pipeendpoint(urb->pipe),
- usb_pipein(urb->pipe) ? "in" : "out",
+ usb_endpoint_num(&urb->ep->desc),
+ usb_urb_dir_in(urb) ? "in" : "out",
urb->actual_length,
urb->transfer_buffer_length);
} else
@@ -250,7 +250,8 @@ static void sg_clean (struct usb_sg_request *io)
io->urbs = NULL;
}
if (io->dev->dev.dma_mask != NULL)
- usb_buffer_unmap_sg (io->dev, io->pipe, io->sg, io->nents);
+ usb_buffer_unmap_sg (io->dev, usb_pipein(io->pipe),
+ io->sg, io->nents);
io->dev = NULL;
}
@@ -278,8 +279,8 @@ static void sg_complete (struct urb *urb)
dev_err (io->dev->bus->controller,
"dev %s ep%d%s scatterlist error %d/%d\n",
io->dev->devpath,
- usb_pipeendpoint (urb->pipe),
- usb_pipein (urb->pipe) ? "in" : "out",
+ usb_endpoint_num(&urb->ep->desc),
+ usb_urb_dir_in(urb) ? "in" : "out",
status, io->status);
// BUG ();
}
@@ -379,7 +380,8 @@ int usb_sg_init (
*/
dma = (dev->dev.dma_mask != NULL);
if (dma)
- io->entries = usb_buffer_map_sg (dev, pipe, sg, nents);
+ io->entries = usb_buffer_map_sg(dev, usb_pipein(pipe),
+ sg, nents);
else
io->entries = nents;
@@ -1013,8 +1015,11 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
ep = dev->ep_in[epnum];
dev->ep_in[epnum] = NULL;
}
- if (ep && dev->bus)
- usb_hcd_endpoint_disable(dev, ep);
+ if (ep) {
+ ep->enabled = 0;
+ usb_hcd_flush_endpoint(dev, ep);
+ usb_hcd_disable_endpoint(dev, ep);
+ }
}
/**
@@ -1096,23 +1101,21 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
* Resets the endpoint toggle, and sets dev->ep_{in,out} pointers.
* For control endpoints, both the input and output sides are handled.
*/
-static void
-usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep)
+void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep)
{
- unsigned int epaddr = ep->desc.bEndpointAddress;
- unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
- int is_control;
+ int epnum = usb_endpoint_num(&ep->desc);
+ int is_out = usb_endpoint_dir_out(&ep->desc);
+ int is_control = usb_endpoint_xfer_control(&ep->desc);
- is_control = ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
- == USB_ENDPOINT_XFER_CONTROL);
- if (usb_endpoint_out(epaddr) || is_control) {
+ if (is_out || is_control) {
usb_settoggle(dev, epnum, 1, 0);
dev->ep_out[epnum] = ep;
}
- if (!usb_endpoint_out(epaddr) || is_control) {
+ if (!is_out || is_control) {
usb_settoggle(dev, epnum, 0, 0);
dev->ep_in[epnum] = ep;
}
+ ep->enabled = 1;
}
/*
@@ -1171,6 +1174,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
struct usb_host_interface *alt;
int ret;
int manual = 0;
+ int changed;
if (dev->state == USB_STATE_SUSPENDED)
return -EHOSTUNREACH;
@@ -1210,7 +1214,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
*/
/* prevent submissions using previous endpoint settings */
- if (device_is_registered(&iface->dev))
+ changed = (iface->cur_altsetting != alt);
+ if (changed && device_is_registered(&iface->dev))
usb_remove_sysfs_intf_files(iface);
usb_disable_interface(dev, iface);
@@ -1247,7 +1252,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
* (Likewise, EP0 never "halts" on well designed devices.)
*/
usb_enable_interface(dev, iface);
- if (device_is_registered(&iface->dev))
+ if (changed && device_is_registered(&iface->dev))
usb_create_sysfs_intf_files(iface);
return 0;
@@ -1328,7 +1333,7 @@ int usb_reset_configuration(struct usb_device *dev)
return 0;
}
-void usb_release_interface(struct device *dev)
+static void usb_release_interface(struct device *dev)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usb_interface_cache *intfc =
@@ -1339,14 +1344,11 @@ void usb_release_interface(struct device *dev)
}
#ifdef CONFIG_HOTPLUG
-static int usb_if_uevent(struct device *dev, char **envp, int num_envp,
- char *buffer, int buffer_size)
+static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct usb_device *usb_dev;
struct usb_interface *intf;
struct usb_host_interface *alt;
- int i = 0;
- int length = 0;
if (!dev)
return -ENODEV;
@@ -1359,39 +1361,30 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp,
alt = intf->cur_altsetting;
#ifdef CONFIG_USB_DEVICEFS
- if (add_uevent_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "DEVICE=/proc/bus/usb/%03d/%03d",
+ if (add_uevent_var(env, "DEVICE=/proc/bus/usb/%03d/%03d",
usb_dev->bus->busnum, usb_dev->devnum))
return -ENOMEM;
#endif
- if (add_uevent_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "PRODUCT=%x/%x/%x",
+ if (add_uevent_var(env, "PRODUCT=%x/%x/%x",
le16_to_cpu(usb_dev->descriptor.idVendor),
le16_to_cpu(usb_dev->descriptor.idProduct),
le16_to_cpu(usb_dev->descriptor.bcdDevice)))
return -ENOMEM;
- if (add_uevent_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "TYPE=%d/%d/%d",
+ if (add_uevent_var(env, "TYPE=%d/%d/%d",
usb_dev->descriptor.bDeviceClass,
usb_dev->descriptor.bDeviceSubClass,
usb_dev->descriptor.bDeviceProtocol))
return -ENOMEM;
- if (add_uevent_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
- "INTERFACE=%d/%d/%d",
+ if (add_uevent_var(env, "INTERFACE=%d/%d/%d",
alt->desc.bInterfaceClass,
alt->desc.bInterfaceSubClass,
alt->desc.bInterfaceProtocol))
return -ENOMEM;
- if (add_uevent_var(envp, num_envp, &i,
- buffer, buffer_size, &length,
+ if (add_uevent_var(env,
"MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
le16_to_cpu(usb_dev->descriptor.idVendor),
le16_to_cpu(usb_dev->descriptor.idProduct),
@@ -1404,14 +1397,12 @@ static int usb_if_uevent(struct device *dev, char **envp, int num_envp,
alt->desc.bInterfaceProtocol))
return -ENOMEM;
- envp[i] = NULL;
return 0;
}
#else
-static int usb_if_uevent(struct device *dev, char **envp,
- int num_envp, char *buffer, int buffer_size)
+static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
{
return -ENODEV;
}
@@ -1481,6 +1472,9 @@ static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
* channels are available independently; and choosing between open
* standard device protocols (like CDC) or proprietary ones.
*
+ * Note that a non-authorized device (dev->authorized == 0) will only
+ * be put in unconfigured mode.
+ *
* Note that USB has an additional level of device configurability,
* associated with interfaces. That configurability is accessed using
* usb_set_interface().
@@ -1502,7 +1496,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
struct usb_interface **new_interfaces = NULL;
int n, nintf;
- if (configuration == -1)
+ if (dev->authorized == 0 || configuration == -1)
configuration = 0;
else {
for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {