1aa1f3bb5SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * message.c - synchronous message handling
4b65fba3dSGreg Kroah-Hartman *
5b65fba3dSGreg Kroah-Hartman * Released under the GPLv2 only.
61da177e4SLinus Torvalds */
71da177e4SLinus Torvalds
8a599a0fbSAndy Shevchenko #include <linux/acpi.h>
91da177e4SLinus Torvalds #include <linux/pci.h> /* for scatterlist macros */
101da177e4SLinus Torvalds #include <linux/usb.h>
111da177e4SLinus Torvalds #include <linux/module.h>
12484468fbSRob Herring #include <linux/of.h>
131da177e4SLinus Torvalds #include <linux/slab.h>
141da177e4SLinus Torvalds #include <linux/mm.h>
151da177e4SLinus Torvalds #include <linux/timer.h>
161da177e4SLinus Torvalds #include <linux/ctype.h>
17a853a3d4SClemens Ladisch #include <linux/nls.h>
181da177e4SLinus Torvalds #include <linux/device.h>
1911763609SRalf Baechle #include <linux/scatterlist.h>
20e4c6fb77SOliver Neukum #include <linux/usb/cdc.h>
217ceec1f1SOliver Neukum #include <linux/usb/quirks.h>
2227729aadSEric Lescouet #include <linux/usb/hcd.h> /* for usbcore internals */
231a7e3948SJohan Hovold #include <linux/usb/of.h>
241da177e4SLinus Torvalds #include <asm/byteorder.h>
251da177e4SLinus Torvalds
261da177e4SLinus Torvalds #include "usb.h"
271da177e4SLinus Torvalds
28df718962SAlan Stern static void cancel_async_set_config(struct usb_device *udev);
29df718962SAlan Stern
3067f5dde3SAlan Stern struct api_context {
3167f5dde3SAlan Stern struct completion done;
3267f5dde3SAlan Stern int status;
3367f5dde3SAlan Stern };
3467f5dde3SAlan Stern
usb_api_blocking_completion(struct urb * urb)357d12e780SDavid Howells static void usb_api_blocking_completion(struct urb *urb)
361da177e4SLinus Torvalds {
3767f5dde3SAlan Stern struct api_context *ctx = urb->context;
3867f5dde3SAlan Stern
3967f5dde3SAlan Stern ctx->status = urb->status;
4067f5dde3SAlan Stern complete(&ctx->done);
411da177e4SLinus Torvalds }
421da177e4SLinus Torvalds
431da177e4SLinus Torvalds
44ecdc0a59SFranck Bui-Huu /*
45ecdc0a59SFranck Bui-Huu * Starts urb and waits for completion or timeout. Note that this call
46ecdc0a59SFranck Bui-Huu * is NOT interruptible. Many device driver i/o requests should be
47ecdc0a59SFranck Bui-Huu * interruptible and therefore these drivers should implement their
48ecdc0a59SFranck Bui-Huu * own interruptible routines.
49ecdc0a59SFranck Bui-Huu */
usb_start_wait_urb(struct urb * urb,int timeout,int * actual_length)501da177e4SLinus Torvalds static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
511da177e4SLinus Torvalds {
5267f5dde3SAlan Stern struct api_context ctx;
53ecdc0a59SFranck Bui-Huu unsigned long expire;
543fc3e826SGreg Kroah-Hartman int retval;
551da177e4SLinus Torvalds
5667f5dde3SAlan Stern init_completion(&ctx.done);
5767f5dde3SAlan Stern urb->context = &ctx;
581da177e4SLinus Torvalds urb->actual_length = 0;
593fc3e826SGreg Kroah-Hartman retval = usb_submit_urb(urb, GFP_NOIO);
603fc3e826SGreg Kroah-Hartman if (unlikely(retval))
61ecdc0a59SFranck Bui-Huu goto out;
621da177e4SLinus Torvalds
63ecdc0a59SFranck Bui-Huu expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
6467f5dde3SAlan Stern if (!wait_for_completion_timeout(&ctx.done, expire)) {
6567f5dde3SAlan Stern usb_kill_urb(urb);
6667f5dde3SAlan Stern retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status);
67ecdc0a59SFranck Bui-Huu
681da177e4SLinus Torvalds dev_dbg(&urb->dev->dev,
6971d2718fSRoel Kluin "%s timed out on ep%d%s len=%u/%u\n",
701da177e4SLinus Torvalds current->comm,
715e60a161SAlan Stern usb_endpoint_num(&urb->ep->desc),
725e60a161SAlan Stern usb_urb_dir_in(urb) ? "in" : "out",
731da177e4SLinus Torvalds urb->actual_length,
74ecdc0a59SFranck Bui-Huu urb->transfer_buffer_length);
75ecdc0a59SFranck Bui-Huu } else
7667f5dde3SAlan Stern retval = ctx.status;
77ecdc0a59SFranck Bui-Huu out:
781da177e4SLinus Torvalds if (actual_length)
791da177e4SLinus Torvalds *actual_length = urb->actual_length;
80ecdc0a59SFranck Bui-Huu
811da177e4SLinus Torvalds usb_free_urb(urb);
823fc3e826SGreg Kroah-Hartman return retval;
831da177e4SLinus Torvalds }
841da177e4SLinus Torvalds
851da177e4SLinus Torvalds /*-------------------------------------------------------------------*/
863e35bf39SGreg Kroah-Hartman /* returns status (negative) or length (positive) */
usb_internal_control_msg(struct usb_device * usb_dev,unsigned int pipe,struct usb_ctrlrequest * cmd,void * data,int len,int timeout)871da177e4SLinus Torvalds static int usb_internal_control_msg(struct usb_device *usb_dev,
881da177e4SLinus Torvalds unsigned int pipe,
891da177e4SLinus Torvalds struct usb_ctrlrequest *cmd,
901da177e4SLinus Torvalds void *data, int len, int timeout)
911da177e4SLinus Torvalds {
921da177e4SLinus Torvalds struct urb *urb;
931da177e4SLinus Torvalds int retv;
941da177e4SLinus Torvalds int length;
951da177e4SLinus Torvalds
961da177e4SLinus Torvalds urb = usb_alloc_urb(0, GFP_NOIO);
971da177e4SLinus Torvalds if (!urb)
981da177e4SLinus Torvalds return -ENOMEM;
991da177e4SLinus Torvalds
1001da177e4SLinus Torvalds usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data,
1011da177e4SLinus Torvalds len, usb_api_blocking_completion, NULL);
1021da177e4SLinus Torvalds
1031da177e4SLinus Torvalds retv = usb_start_wait_urb(urb, timeout, &length);
1041da177e4SLinus Torvalds if (retv < 0)
1051da177e4SLinus Torvalds return retv;
1061da177e4SLinus Torvalds else
1071da177e4SLinus Torvalds return length;
1081da177e4SLinus Torvalds }
1091da177e4SLinus Torvalds
1101da177e4SLinus Torvalds /**
1111da177e4SLinus Torvalds * usb_control_msg - Builds a control urb, sends it off and waits for completion
1121da177e4SLinus Torvalds * @dev: pointer to the usb device to send the message to
1131da177e4SLinus Torvalds * @pipe: endpoint "pipe" to send the message to
1141da177e4SLinus Torvalds * @request: USB message request value
1151da177e4SLinus Torvalds * @requesttype: USB message request type value
1161da177e4SLinus Torvalds * @value: USB message value
1171da177e4SLinus Torvalds * @index: USB message index value
1181da177e4SLinus Torvalds * @data: pointer to the data to send
1191da177e4SLinus Torvalds * @size: length in bytes of the data to send
1203e35bf39SGreg Kroah-Hartman * @timeout: time in msecs to wait for the message to complete before timing
1213e35bf39SGreg Kroah-Hartman * out (if 0 the wait is forever)
1223e35bf39SGreg Kroah-Hartman *
12341631d36SAhmed S. Darwish * Context: task context, might sleep.
1241da177e4SLinus Torvalds *
1253e35bf39SGreg Kroah-Hartman * This function sends a simple control message to a specified endpoint and
1263e35bf39SGreg Kroah-Hartman * waits for the message to complete, or timeout.
1271da177e4SLinus Torvalds *
128123b7b30SJaejoong Kim * Don't use this function from within an interrupt context. If you need
129123b7b30SJaejoong Kim * an asynchronous message, or need to send a message from within interrupt
130123b7b30SJaejoong Kim * context, use usb_submit_urb(). If a thread in your driver uses this call,
131123b7b30SJaejoong Kim * make sure your disconnect() method can wait for it to complete. Since you
132123b7b30SJaejoong Kim * don't have a handle on the URB used, you can't cancel the request.
133626f090cSYacine Belkadi *
134626f090cSYacine Belkadi * Return: If successful, the number of bytes transferred. Otherwise, a negative
135626f090cSYacine Belkadi * error number.
1361da177e4SLinus Torvalds */
usb_control_msg(struct usb_device * dev,unsigned int pipe,__u8 request,__u8 requesttype,__u16 value,__u16 index,void * data,__u16 size,int timeout)1373e35bf39SGreg Kroah-Hartman int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
1383e35bf39SGreg Kroah-Hartman __u8 requesttype, __u16 value, __u16 index, void *data,
1393e35bf39SGreg Kroah-Hartman __u16 size, int timeout)
1401da177e4SLinus Torvalds {
1413e35bf39SGreg Kroah-Hartman struct usb_ctrlrequest *dr;
1421da177e4SLinus Torvalds int ret;
1431da177e4SLinus Torvalds
1443e35bf39SGreg Kroah-Hartman dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
1451da177e4SLinus Torvalds if (!dr)
1461da177e4SLinus Torvalds return -ENOMEM;
1471da177e4SLinus Torvalds
1481da177e4SLinus Torvalds dr->bRequestType = requesttype;
1491da177e4SLinus Torvalds dr->bRequest = request;
150da2bbdccSHarvey Harrison dr->wValue = cpu_to_le16(value);
151da2bbdccSHarvey Harrison dr->wIndex = cpu_to_le16(index);
152da2bbdccSHarvey Harrison dr->wLength = cpu_to_le16(size);
1531da177e4SLinus Torvalds
1541da177e4SLinus Torvalds ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
1551da177e4SLinus Torvalds
156cb88a058SDanilo Krummrich /* Linger a bit, prior to the next control message. */
157cb88a058SDanilo Krummrich if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG)
158cb88a058SDanilo Krummrich msleep(200);
159cb88a058SDanilo Krummrich
1601da177e4SLinus Torvalds kfree(dr);
1611da177e4SLinus Torvalds
1621da177e4SLinus Torvalds return ret;
1631da177e4SLinus Torvalds }
164782e70c6SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(usb_control_msg);
1651da177e4SLinus Torvalds
1661da177e4SLinus Torvalds /**
167719b8f28SGreg Kroah-Hartman * usb_control_msg_send - Builds a control "send" message, sends it off and waits for completion
168719b8f28SGreg Kroah-Hartman * @dev: pointer to the usb device to send the message to
169719b8f28SGreg Kroah-Hartman * @endpoint: endpoint to send the message to
170719b8f28SGreg Kroah-Hartman * @request: USB message request value
171719b8f28SGreg Kroah-Hartman * @requesttype: USB message request type value
172719b8f28SGreg Kroah-Hartman * @value: USB message value
173719b8f28SGreg Kroah-Hartman * @index: USB message index value
174719b8f28SGreg Kroah-Hartman * @driver_data: pointer to the data to send
175719b8f28SGreg Kroah-Hartman * @size: length in bytes of the data to send
176719b8f28SGreg Kroah-Hartman * @timeout: time in msecs to wait for the message to complete before timing
177719b8f28SGreg Kroah-Hartman * out (if 0 the wait is forever)
178ddd1198eSOliver Neukum * @memflags: the flags for memory allocation for buffers
179719b8f28SGreg Kroah-Hartman *
180719b8f28SGreg Kroah-Hartman * Context: !in_interrupt ()
181719b8f28SGreg Kroah-Hartman *
182719b8f28SGreg Kroah-Hartman * This function sends a control message to a specified endpoint that is not
183719b8f28SGreg Kroah-Hartman * expected to fill in a response (i.e. a "send message") and waits for the
184719b8f28SGreg Kroah-Hartman * message to complete, or timeout.
185719b8f28SGreg Kroah-Hartman *
186719b8f28SGreg Kroah-Hartman * Do not use this function from within an interrupt context. If you need
187719b8f28SGreg Kroah-Hartman * an asynchronous message, or need to send a message from within interrupt
188719b8f28SGreg Kroah-Hartman * context, use usb_submit_urb(). If a thread in your driver uses this call,
189719b8f28SGreg Kroah-Hartman * make sure your disconnect() method can wait for it to complete. Since you
190719b8f28SGreg Kroah-Hartman * don't have a handle on the URB used, you can't cancel the request.
191719b8f28SGreg Kroah-Hartman *
192719b8f28SGreg Kroah-Hartman * The data pointer can be made to a reference on the stack, or anywhere else,
193719b8f28SGreg Kroah-Hartman * as it will not be modified at all. This does not have the restriction that
194719b8f28SGreg Kroah-Hartman * usb_control_msg() has where the data pointer must be to dynamically allocated
195719b8f28SGreg Kroah-Hartman * memory (i.e. memory that can be successfully DMAed to a device).
196719b8f28SGreg Kroah-Hartman *
197719b8f28SGreg Kroah-Hartman * Return: If successful, 0 is returned, Otherwise, a negative error number.
198719b8f28SGreg Kroah-Hartman */
usb_control_msg_send(struct usb_device * dev,__u8 endpoint,__u8 request,__u8 requesttype,__u16 value,__u16 index,const void * driver_data,__u16 size,int timeout,gfp_t memflags)199719b8f28SGreg Kroah-Hartman int usb_control_msg_send(struct usb_device *dev, __u8 endpoint, __u8 request,
200719b8f28SGreg Kroah-Hartman __u8 requesttype, __u16 value, __u16 index,
201ddd1198eSOliver Neukum const void *driver_data, __u16 size, int timeout,
202ddd1198eSOliver Neukum gfp_t memflags)
203719b8f28SGreg Kroah-Hartman {
204719b8f28SGreg Kroah-Hartman unsigned int pipe = usb_sndctrlpipe(dev, endpoint);
205719b8f28SGreg Kroah-Hartman int ret;
206719b8f28SGreg Kroah-Hartman u8 *data = NULL;
207719b8f28SGreg Kroah-Hartman
208719b8f28SGreg Kroah-Hartman if (size) {
209ddd1198eSOliver Neukum data = kmemdup(driver_data, size, memflags);
210719b8f28SGreg Kroah-Hartman if (!data)
211719b8f28SGreg Kroah-Hartman return -ENOMEM;
212719b8f28SGreg Kroah-Hartman }
213719b8f28SGreg Kroah-Hartman
214719b8f28SGreg Kroah-Hartman ret = usb_control_msg(dev, pipe, request, requesttype, value, index,
215719b8f28SGreg Kroah-Hartman data, size, timeout);
216719b8f28SGreg Kroah-Hartman kfree(data);
217719b8f28SGreg Kroah-Hartman
218719b8f28SGreg Kroah-Hartman if (ret < 0)
219719b8f28SGreg Kroah-Hartman return ret;
220baf7df45SJohan Hovold
221719b8f28SGreg Kroah-Hartman return 0;
222719b8f28SGreg Kroah-Hartman }
223719b8f28SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(usb_control_msg_send);
224719b8f28SGreg Kroah-Hartman
225719b8f28SGreg Kroah-Hartman /**
226719b8f28SGreg Kroah-Hartman * usb_control_msg_recv - Builds a control "receive" message, sends it off and waits for completion
227719b8f28SGreg Kroah-Hartman * @dev: pointer to the usb device to send the message to
228719b8f28SGreg Kroah-Hartman * @endpoint: endpoint to send the message to
229719b8f28SGreg Kroah-Hartman * @request: USB message request value
230719b8f28SGreg Kroah-Hartman * @requesttype: USB message request type value
231719b8f28SGreg Kroah-Hartman * @value: USB message value
232719b8f28SGreg Kroah-Hartman * @index: USB message index value
233719b8f28SGreg Kroah-Hartman * @driver_data: pointer to the data to be filled in by the message
234719b8f28SGreg Kroah-Hartman * @size: length in bytes of the data to be received
235719b8f28SGreg Kroah-Hartman * @timeout: time in msecs to wait for the message to complete before timing
236719b8f28SGreg Kroah-Hartman * out (if 0 the wait is forever)
237ddd1198eSOliver Neukum * @memflags: the flags for memory allocation for buffers
238719b8f28SGreg Kroah-Hartman *
239719b8f28SGreg Kroah-Hartman * Context: !in_interrupt ()
240719b8f28SGreg Kroah-Hartman *
241719b8f28SGreg Kroah-Hartman * This function sends a control message to a specified endpoint that is
242719b8f28SGreg Kroah-Hartman * expected to fill in a response (i.e. a "receive message") and waits for the
243719b8f28SGreg Kroah-Hartman * message to complete, or timeout.
244719b8f28SGreg Kroah-Hartman *
245719b8f28SGreg Kroah-Hartman * Do not use this function from within an interrupt context. If you need
246719b8f28SGreg Kroah-Hartman * an asynchronous message, or need to send a message from within interrupt
247719b8f28SGreg Kroah-Hartman * context, use usb_submit_urb(). If a thread in your driver uses this call,
248719b8f28SGreg Kroah-Hartman * make sure your disconnect() method can wait for it to complete. Since you
249719b8f28SGreg Kroah-Hartman * don't have a handle on the URB used, you can't cancel the request.
250719b8f28SGreg Kroah-Hartman *
251719b8f28SGreg Kroah-Hartman * The data pointer can be made to a reference on the stack, or anywhere else
252719b8f28SGreg Kroah-Hartman * that can be successfully written to. This function does not have the
253719b8f28SGreg Kroah-Hartman * restriction that usb_control_msg() has where the data pointer must be to
254719b8f28SGreg Kroah-Hartman * dynamically allocated memory (i.e. memory that can be successfully DMAed to a
255719b8f28SGreg Kroah-Hartman * device).
256719b8f28SGreg Kroah-Hartman *
257719b8f28SGreg Kroah-Hartman * The "whole" message must be properly received from the device in order for
258719b8f28SGreg Kroah-Hartman * this function to be successful. If a device returns less than the expected
259719b8f28SGreg Kroah-Hartman * amount of data, then the function will fail. Do not use this for messages
260719b8f28SGreg Kroah-Hartman * where a variable amount of data might be returned.
261719b8f28SGreg Kroah-Hartman *
262719b8f28SGreg Kroah-Hartman * Return: If successful, 0 is returned, Otherwise, a negative error number.
263719b8f28SGreg Kroah-Hartman */
usb_control_msg_recv(struct usb_device * dev,__u8 endpoint,__u8 request,__u8 requesttype,__u16 value,__u16 index,void * driver_data,__u16 size,int timeout,gfp_t memflags)264719b8f28SGreg Kroah-Hartman int usb_control_msg_recv(struct usb_device *dev, __u8 endpoint, __u8 request,
265719b8f28SGreg Kroah-Hartman __u8 requesttype, __u16 value, __u16 index,
266ddd1198eSOliver Neukum void *driver_data, __u16 size, int timeout,
267ddd1198eSOliver Neukum gfp_t memflags)
268719b8f28SGreg Kroah-Hartman {
269719b8f28SGreg Kroah-Hartman unsigned int pipe = usb_rcvctrlpipe(dev, endpoint);
270719b8f28SGreg Kroah-Hartman int ret;
271719b8f28SGreg Kroah-Hartman u8 *data;
272719b8f28SGreg Kroah-Hartman
2737fe53dcbSJohan Hovold if (!size || !driver_data)
274719b8f28SGreg Kroah-Hartman return -EINVAL;
275719b8f28SGreg Kroah-Hartman
276ddd1198eSOliver Neukum data = kmalloc(size, memflags);
277719b8f28SGreg Kroah-Hartman if (!data)
278719b8f28SGreg Kroah-Hartman return -ENOMEM;
279719b8f28SGreg Kroah-Hartman
280719b8f28SGreg Kroah-Hartman ret = usb_control_msg(dev, pipe, request, requesttype, value, index,
281719b8f28SGreg Kroah-Hartman data, size, timeout);
282719b8f28SGreg Kroah-Hartman
283719b8f28SGreg Kroah-Hartman if (ret < 0)
284719b8f28SGreg Kroah-Hartman goto exit;
285719b8f28SGreg Kroah-Hartman
286719b8f28SGreg Kroah-Hartman if (ret == size) {
287719b8f28SGreg Kroah-Hartman memcpy(driver_data, data, size);
288719b8f28SGreg Kroah-Hartman ret = 0;
289719b8f28SGreg Kroah-Hartman } else {
2909dc9c854SJohan Hovold ret = -EREMOTEIO;
291719b8f28SGreg Kroah-Hartman }
292719b8f28SGreg Kroah-Hartman
293719b8f28SGreg Kroah-Hartman exit:
294719b8f28SGreg Kroah-Hartman kfree(data);
295719b8f28SGreg Kroah-Hartman return ret;
296719b8f28SGreg Kroah-Hartman }
297719b8f28SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(usb_control_msg_recv);
298719b8f28SGreg Kroah-Hartman
299719b8f28SGreg Kroah-Hartman /**
300782a7a63SGreg Kroah-Hartman * usb_interrupt_msg - Builds an interrupt urb, sends it off and waits for completion
301782a7a63SGreg Kroah-Hartman * @usb_dev: pointer to the usb device to send the message to
302782a7a63SGreg Kroah-Hartman * @pipe: endpoint "pipe" to send the message to
303782a7a63SGreg Kroah-Hartman * @data: pointer to the data to send
304782a7a63SGreg Kroah-Hartman * @len: length in bytes of the data to send
3053e35bf39SGreg Kroah-Hartman * @actual_length: pointer to a location to put the actual length transferred
3063e35bf39SGreg Kroah-Hartman * in bytes
307782a7a63SGreg Kroah-Hartman * @timeout: time in msecs to wait for the message to complete before
308782a7a63SGreg Kroah-Hartman * timing out (if 0 the wait is forever)
3093e35bf39SGreg Kroah-Hartman *
31041631d36SAhmed S. Darwish * Context: task context, might sleep.
311782a7a63SGreg Kroah-Hartman *
312782a7a63SGreg Kroah-Hartman * This function sends a simple interrupt message to a specified endpoint and
313782a7a63SGreg Kroah-Hartman * waits for the message to complete, or timeout.
314782a7a63SGreg Kroah-Hartman *
315123b7b30SJaejoong Kim * Don't use this function from within an interrupt context. If you need
316123b7b30SJaejoong Kim * an asynchronous message, or need to send a message from within interrupt
317123b7b30SJaejoong Kim * context, use usb_submit_urb() If a thread in your driver uses this call,
318123b7b30SJaejoong Kim * make sure your disconnect() method can wait for it to complete. Since you
319123b7b30SJaejoong Kim * don't have a handle on the URB used, you can't cancel the request.
320626f090cSYacine Belkadi *
321626f090cSYacine Belkadi * Return:
322626f090cSYacine Belkadi * If successful, 0. Otherwise a negative error number. The number of actual
323e227867fSMasanari Iida * bytes transferred will be stored in the @actual_length parameter.
324782a7a63SGreg Kroah-Hartman */
usb_interrupt_msg(struct usb_device * usb_dev,unsigned int pipe,void * data,int len,int * actual_length,int timeout)325782a7a63SGreg Kroah-Hartman int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe,
326782a7a63SGreg Kroah-Hartman void *data, int len, int *actual_length, int timeout)
327782a7a63SGreg Kroah-Hartman {
328782a7a63SGreg Kroah-Hartman return usb_bulk_msg(usb_dev, pipe, data, len, actual_length, timeout);
329782a7a63SGreg Kroah-Hartman }
330782a7a63SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(usb_interrupt_msg);
331782a7a63SGreg Kroah-Hartman
332782a7a63SGreg Kroah-Hartman /**
3331da177e4SLinus Torvalds * usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
3341da177e4SLinus Torvalds * @usb_dev: pointer to the usb device to send the message to
3351da177e4SLinus Torvalds * @pipe: endpoint "pipe" to send the message to
3361da177e4SLinus Torvalds * @data: pointer to the data to send
3371da177e4SLinus Torvalds * @len: length in bytes of the data to send
3383e35bf39SGreg Kroah-Hartman * @actual_length: pointer to a location to put the actual length transferred
3393e35bf39SGreg Kroah-Hartman * in bytes
3401da177e4SLinus Torvalds * @timeout: time in msecs to wait for the message to complete before
3411da177e4SLinus Torvalds * timing out (if 0 the wait is forever)
3423e35bf39SGreg Kroah-Hartman *
34341631d36SAhmed S. Darwish * Context: task context, might sleep.
3441da177e4SLinus Torvalds *
3451da177e4SLinus Torvalds * This function sends a simple bulk message to a specified endpoint
3461da177e4SLinus Torvalds * and waits for the message to complete, or timeout.
3471da177e4SLinus Torvalds *
348123b7b30SJaejoong Kim * Don't use this function from within an interrupt context. If you need
349123b7b30SJaejoong Kim * an asynchronous message, or need to send a message from within interrupt
350123b7b30SJaejoong Kim * context, use usb_submit_urb() If a thread in your driver uses this call,
351123b7b30SJaejoong Kim * make sure your disconnect() method can wait for it to complete. Since you
352123b7b30SJaejoong Kim * don't have a handle on the URB used, you can't cancel the request.
353d09d36a9SAlan Stern *
3543e35bf39SGreg Kroah-Hartman * Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT ioctl,
3553e35bf39SGreg Kroah-Hartman * users are forced to abuse this routine by using it to submit URBs for
3563e35bf39SGreg Kroah-Hartman * interrupt endpoints. We will take the liberty of creating an interrupt URB
3573e35bf39SGreg Kroah-Hartman * (with the default interval) if the target is an interrupt endpoint.
358626f090cSYacine Belkadi *
359626f090cSYacine Belkadi * Return:
360626f090cSYacine Belkadi * If successful, 0. Otherwise a negative error number. The number of actual
361025d4430SRahul Bedarkar * bytes transferred will be stored in the @actual_length parameter.
362626f090cSYacine Belkadi *
3631da177e4SLinus Torvalds */
usb_bulk_msg(struct usb_device * usb_dev,unsigned int pipe,void * data,int len,int * actual_length,int timeout)3641da177e4SLinus Torvalds int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
3651da177e4SLinus Torvalds void *data, int len, int *actual_length, int timeout)
3661da177e4SLinus Torvalds {
3671da177e4SLinus Torvalds struct urb *urb;
368d09d36a9SAlan Stern struct usb_host_endpoint *ep;
3691da177e4SLinus Torvalds
370fe54b058SMatthew Wilcox ep = usb_pipe_endpoint(usb_dev, pipe);
371d09d36a9SAlan Stern if (!ep || len < 0)
3721da177e4SLinus Torvalds return -EINVAL;
3731da177e4SLinus Torvalds
3741da177e4SLinus Torvalds urb = usb_alloc_urb(0, GFP_KERNEL);
3751da177e4SLinus Torvalds if (!urb)
3761da177e4SLinus Torvalds return -ENOMEM;
3771da177e4SLinus Torvalds
378d09d36a9SAlan Stern if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
379d09d36a9SAlan Stern USB_ENDPOINT_XFER_INT) {
380d09d36a9SAlan Stern pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
381d09d36a9SAlan Stern usb_fill_int_urb(urb, usb_dev, pipe, data, len,
3828d062b9aSAlan Stern usb_api_blocking_completion, NULL,
3838d062b9aSAlan Stern ep->desc.bInterval);
384d09d36a9SAlan Stern } else
3851da177e4SLinus Torvalds usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
3861da177e4SLinus Torvalds usb_api_blocking_completion, NULL);
3871da177e4SLinus Torvalds
3881da177e4SLinus Torvalds return usb_start_wait_urb(urb, timeout, actual_length);
3891da177e4SLinus Torvalds }
390782e70c6SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(usb_bulk_msg);
3911da177e4SLinus Torvalds
3921da177e4SLinus Torvalds /*-------------------------------------------------------------------*/
3931da177e4SLinus Torvalds
sg_clean(struct usb_sg_request * io)3941da177e4SLinus Torvalds static void sg_clean(struct usb_sg_request *io)
3951da177e4SLinus Torvalds {
3961da177e4SLinus Torvalds if (io->urbs) {
3971da177e4SLinus Torvalds while (io->entries--)
3981da177e4SLinus Torvalds usb_free_urb(io->urbs[io->entries]);
3991da177e4SLinus Torvalds kfree(io->urbs);
4001da177e4SLinus Torvalds io->urbs = NULL;
4011da177e4SLinus Torvalds }
4021da177e4SLinus Torvalds io->dev = NULL;
4031da177e4SLinus Torvalds }
4041da177e4SLinus Torvalds
sg_complete(struct urb * urb)4057d12e780SDavid Howells static void sg_complete(struct urb *urb)
4061da177e4SLinus Torvalds {
40731adcb0aSSebastian Andrzej Siewior unsigned long flags;
408ec17cf1cSTobias Klauser struct usb_sg_request *io = urb->context;
4093fc3e826SGreg Kroah-Hartman int status = urb->status;
4101da177e4SLinus Torvalds
41131adcb0aSSebastian Andrzej Siewior spin_lock_irqsave(&io->lock, flags);
4121da177e4SLinus Torvalds
4131da177e4SLinus Torvalds /* In 2.5 we require hcds' endpoint queues not to progress after fault
4141da177e4SLinus Torvalds * reports, until the completion callback (this!) returns. That lets
4151da177e4SLinus Torvalds * device driver code (like this routine) unlink queued urbs first,
4161da177e4SLinus Torvalds * if it needs to, since the HC won't work on them at all. So it's
4171da177e4SLinus Torvalds * not possible for page N+1 to overwrite page N, and so on.
4181da177e4SLinus Torvalds *
4191da177e4SLinus Torvalds * That's only for "hard" faults; "soft" faults (unlinks) sometimes
4201da177e4SLinus Torvalds * complete before the HCD can get requests away from hardware,
4211da177e4SLinus Torvalds * though never during cleanup after a hard fault.
4221da177e4SLinus Torvalds */
4231da177e4SLinus Torvalds if (io->status
4241da177e4SLinus Torvalds && (io->status != -ECONNRESET
4253fc3e826SGreg Kroah-Hartman || status != -ECONNRESET)
4261da177e4SLinus Torvalds && urb->actual_length) {
4271da177e4SLinus Torvalds dev_err(io->dev->bus->controller,
4281da177e4SLinus Torvalds "dev %s ep%d%s scatterlist error %d/%d\n",
4291da177e4SLinus Torvalds io->dev->devpath,
4305e60a161SAlan Stern usb_endpoint_num(&urb->ep->desc),
4315e60a161SAlan Stern usb_urb_dir_in(urb) ? "in" : "out",
4323fc3e826SGreg Kroah-Hartman status, io->status);
4333e35bf39SGreg Kroah-Hartman /* BUG (); */
4341da177e4SLinus Torvalds }
4351da177e4SLinus Torvalds
4363fc3e826SGreg Kroah-Hartman if (io->status == 0 && status && status != -ECONNRESET) {
4373fc3e826SGreg Kroah-Hartman int i, found, retval;
4381da177e4SLinus Torvalds
4393fc3e826SGreg Kroah-Hartman io->status = status;
4401da177e4SLinus Torvalds
4411da177e4SLinus Torvalds /* the previous urbs, and this one, completed already.
4421da177e4SLinus Torvalds * unlink pending urbs so they won't rx/tx bad data.
4431da177e4SLinus Torvalds * careful: unlink can sometimes be synchronous...
4441da177e4SLinus Torvalds */
44531adcb0aSSebastian Andrzej Siewior spin_unlock_irqrestore(&io->lock, flags);
4461da177e4SLinus Torvalds for (i = 0, found = 0; i < io->entries; i++) {
44798b74b0eSDavid Mosberger if (!io->urbs[i])
4481da177e4SLinus Torvalds continue;
4491da177e4SLinus Torvalds if (found) {
45098b74b0eSDavid Mosberger usb_block_urb(io->urbs[i]);
4513fc3e826SGreg Kroah-Hartman retval = usb_unlink_urb(io->urbs[i]);
4523fc3e826SGreg Kroah-Hartman if (retval != -EINPROGRESS &&
4533fc3e826SGreg Kroah-Hartman retval != -ENODEV &&
454bcf39853SAlan Stern retval != -EBUSY &&
455bcf39853SAlan Stern retval != -EIDRM)
4561da177e4SLinus Torvalds dev_err(&io->dev->dev,
4571da177e4SLinus Torvalds "%s, unlink --> %d\n",
458441b62c1SHarvey Harrison __func__, retval);
4591da177e4SLinus Torvalds } else if (urb == io->urbs[i])
4601da177e4SLinus Torvalds found = 1;
4611da177e4SLinus Torvalds }
46231adcb0aSSebastian Andrzej Siewior spin_lock_irqsave(&io->lock, flags);
4631da177e4SLinus Torvalds }
4641da177e4SLinus Torvalds
4651da177e4SLinus Torvalds /* on the last completion, signal usb_sg_wait() */
4661da177e4SLinus Torvalds io->bytes += urb->actual_length;
4671da177e4SLinus Torvalds io->count--;
4681da177e4SLinus Torvalds if (!io->count)
4691da177e4SLinus Torvalds complete(&io->complete);
4701da177e4SLinus Torvalds
47131adcb0aSSebastian Andrzej Siewior spin_unlock_irqrestore(&io->lock, flags);
4721da177e4SLinus Torvalds }
4731da177e4SLinus Torvalds
4741da177e4SLinus Torvalds
4751da177e4SLinus Torvalds /**
4761da177e4SLinus Torvalds * usb_sg_init - initializes scatterlist-based bulk/interrupt I/O request
4771da177e4SLinus Torvalds * @io: request block being initialized. until usb_sg_wait() returns,
4781da177e4SLinus Torvalds * treat this as a pointer to an opaque block of memory,
4791da177e4SLinus Torvalds * @dev: the usb device that will send or receive the data
4801da177e4SLinus Torvalds * @pipe: endpoint "pipe" used to transfer the data
4811da177e4SLinus Torvalds * @period: polling rate for interrupt endpoints, in frames or
4821da177e4SLinus Torvalds * (for high speed endpoints) microframes; ignored for bulk
4831da177e4SLinus Torvalds * @sg: scatterlist entries
4841da177e4SLinus Torvalds * @nents: how many entries in the scatterlist
4851da177e4SLinus Torvalds * @length: how many bytes to send from the scatterlist, or zero to
4861da177e4SLinus Torvalds * send every byte identified in the list.
4871da177e4SLinus Torvalds * @mem_flags: SLAB_* flags affecting memory allocations in this call
4881da177e4SLinus Torvalds *
489626f090cSYacine Belkadi * This initializes a scatter/gather request, allocating resources such as
490626f090cSYacine Belkadi * I/O mappings and urb memory (except maybe memory used by USB controller
491626f090cSYacine Belkadi * drivers).
4921da177e4SLinus Torvalds *
4931da177e4SLinus Torvalds * The request must be issued using usb_sg_wait(), which waits for the I/O to
4941da177e4SLinus Torvalds * complete (or to be canceled) and then cleans up all resources allocated by
4951da177e4SLinus Torvalds * usb_sg_init().
4961da177e4SLinus Torvalds *
4971da177e4SLinus Torvalds * The request may be canceled with usb_sg_cancel(), either before or after
4981da177e4SLinus Torvalds * usb_sg_wait() is called.
499626f090cSYacine Belkadi *
500626f090cSYacine Belkadi * Return: Zero for success, else a negative errno value.
5011da177e4SLinus Torvalds */
usb_sg_init(struct usb_sg_request * io,struct usb_device * dev,unsigned pipe,unsigned period,struct scatterlist * sg,int nents,size_t length,gfp_t mem_flags)5023e35bf39SGreg Kroah-Hartman int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
5033e35bf39SGreg Kroah-Hartman unsigned pipe, unsigned period, struct scatterlist *sg,
5043e35bf39SGreg Kroah-Hartman int nents, size_t length, gfp_t mem_flags)
5051da177e4SLinus Torvalds {
5061da177e4SLinus Torvalds int i;
5071da177e4SLinus Torvalds int urb_flags;
508e04748e3SSarah Sharp int use_sg;
5091da177e4SLinus Torvalds
5101da177e4SLinus Torvalds if (!io || !dev || !sg
5111da177e4SLinus Torvalds || usb_pipecontrol(pipe)
5121da177e4SLinus Torvalds || usb_pipeisoc(pipe)
5131da177e4SLinus Torvalds || nents <= 0)
5141da177e4SLinus Torvalds return -EINVAL;
5151da177e4SLinus Torvalds
5161da177e4SLinus Torvalds spin_lock_init(&io->lock);
5171da177e4SLinus Torvalds io->dev = dev;
5181da177e4SLinus Torvalds io->pipe = pipe;
5190ba169afSAlan Stern
5200ba169afSAlan Stern if (dev->bus->sg_tablesize > 0) {
5210ba169afSAlan Stern use_sg = true;
5220ba169afSAlan Stern io->entries = 1;
5230ba169afSAlan Stern } else {
5240ba169afSAlan Stern use_sg = false;
5251da177e4SLinus Torvalds io->entries = nents;
5260ba169afSAlan Stern }
5271da177e4SLinus Torvalds
5281da177e4SLinus Torvalds /* initialize all the urbs we'll use */
5296da2ec56SKees Cook io->urbs = kmalloc_array(io->entries, sizeof(*io->urbs), mem_flags);
5301da177e4SLinus Torvalds if (!io->urbs)
5311da177e4SLinus Torvalds goto nomem;
5321da177e4SLinus Torvalds
5330ba169afSAlan Stern urb_flags = URB_NO_INTERRUPT;
5341da177e4SLinus Torvalds if (usb_pipein(pipe))
5351da177e4SLinus Torvalds urb_flags |= URB_SHORT_NOT_OK;
5361da177e4SLinus Torvalds
537e04748e3SSarah Sharp for_each_sg(sg, sg, io->entries, i) {
5380ba169afSAlan Stern struct urb *urb;
5391da177e4SLinus Torvalds unsigned len;
5401da177e4SLinus Torvalds
5410ba169afSAlan Stern urb = usb_alloc_urb(0, mem_flags);
5420ba169afSAlan Stern if (!urb) {
5431da177e4SLinus Torvalds io->entries = i;
5441da177e4SLinus Torvalds goto nomem;
5451da177e4SLinus Torvalds }
5460ba169afSAlan Stern io->urbs[i] = urb;
5471da177e4SLinus Torvalds
5480ba169afSAlan Stern urb->dev = NULL;
5490ba169afSAlan Stern urb->pipe = pipe;
5500ba169afSAlan Stern urb->interval = period;
5510ba169afSAlan Stern urb->transfer_flags = urb_flags;
5520ba169afSAlan Stern urb->complete = sg_complete;
5530ba169afSAlan Stern urb->context = io;
5540ba169afSAlan Stern urb->sg = sg;
5551da177e4SLinus Torvalds
5560ba169afSAlan Stern if (use_sg) {
5570ba169afSAlan Stern /* There is no single transfer buffer */
5580ba169afSAlan Stern urb->transfer_buffer = NULL;
5590ba169afSAlan Stern urb->num_sgs = nents;
5601da177e4SLinus Torvalds
5610ba169afSAlan Stern /* A length of zero means transfer the whole sg list */
5620ba169afSAlan Stern len = length;
5630ba169afSAlan Stern if (len == 0) {
56464d65872SAlan Stern struct scatterlist *sg2;
56564d65872SAlan Stern int j;
56664d65872SAlan Stern
56764d65872SAlan Stern for_each_sg(sg, sg2, nents, j)
56864d65872SAlan Stern len += sg2->length;
5690ba169afSAlan Stern }
5700ba169afSAlan Stern } else {
57135d07fd5STony Lindgren /*
572ff9c895fSAlan Stern * Some systems can't use DMA; they use PIO instead.
573ff9c895fSAlan Stern * For their sakes, transfer_buffer is set whenever
574ff9c895fSAlan Stern * possible.
57535d07fd5STony Lindgren */
576ff9c895fSAlan Stern if (!PageHighMem(sg_page(sg)))
5770ba169afSAlan Stern urb->transfer_buffer = sg_virt(sg);
57881bf46f3SPete Zaitcev else
5790ba169afSAlan Stern urb->transfer_buffer = NULL;
58081bf46f3SPete Zaitcev
5817c3e28bcSAlan Stern len = sg->length;
5821da177e4SLinus Torvalds if (length) {
583edb2b255SDan Carpenter len = min_t(size_t, len, length);
5841da177e4SLinus Torvalds length -= len;
5851da177e4SLinus Torvalds if (length == 0)
5861da177e4SLinus Torvalds io->entries = i + 1;
5871da177e4SLinus Torvalds }
5880ba169afSAlan Stern }
5890ba169afSAlan Stern urb->transfer_buffer_length = len;
5901da177e4SLinus Torvalds }
5911da177e4SLinus Torvalds io->urbs[--i]->transfer_flags &= ~URB_NO_INTERRUPT;
5921da177e4SLinus Torvalds
5931da177e4SLinus Torvalds /* transaction state */
594580da348SAlan Stern io->count = io->entries;
5951da177e4SLinus Torvalds io->status = 0;
5961da177e4SLinus Torvalds io->bytes = 0;
5971da177e4SLinus Torvalds init_completion(&io->complete);
5981da177e4SLinus Torvalds return 0;
5991da177e4SLinus Torvalds
6001da177e4SLinus Torvalds nomem:
6011da177e4SLinus Torvalds sg_clean(io);
6021da177e4SLinus Torvalds return -ENOMEM;
6031da177e4SLinus Torvalds }
604782e70c6SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(usb_sg_init);
6051da177e4SLinus Torvalds
6061da177e4SLinus Torvalds /**
6071da177e4SLinus Torvalds * usb_sg_wait - synchronously execute scatter/gather request
6081da177e4SLinus Torvalds * @io: request block handle, as initialized with usb_sg_init().
6091da177e4SLinus Torvalds * some fields become accessible when this call returns.
61041631d36SAhmed S. Darwish *
61141631d36SAhmed S. Darwish * Context: task context, might sleep.
6121da177e4SLinus Torvalds *
6131da177e4SLinus Torvalds * This function blocks until the specified I/O operation completes. It
6141da177e4SLinus Torvalds * leverages the grouping of the related I/O requests to get good transfer
6151da177e4SLinus Torvalds * rates, by queueing the requests. At higher speeds, such queuing can
6161da177e4SLinus Torvalds * significantly improve USB throughput.
6171da177e4SLinus Torvalds *
6181da177e4SLinus Torvalds * There are three kinds of completion for this function.
619e0c34e90SMauro Carvalho Chehab *
6201da177e4SLinus Torvalds * (1) success, where io->status is zero. The number of io->bytes
6211da177e4SLinus Torvalds * transferred is as requested.
6221da177e4SLinus Torvalds * (2) error, where io->status is a negative errno value. The number
6231da177e4SLinus Torvalds * of io->bytes transferred before the error is usually less
6241da177e4SLinus Torvalds * than requested, and can be nonzero.
625093cf723SSteven Cole * (3) cancellation, a type of error with status -ECONNRESET that
6261da177e4SLinus Torvalds * is initiated by usb_sg_cancel().
6271da177e4SLinus Torvalds *
6281da177e4SLinus Torvalds * When this function returns, all memory allocated through usb_sg_init() or
6291da177e4SLinus Torvalds * this call will have been freed. The request block parameter may still be
6301da177e4SLinus Torvalds * passed to usb_sg_cancel(), or it may be freed. It could also be
6311da177e4SLinus Torvalds * reinitialized and then reused.
6321da177e4SLinus Torvalds *
6331da177e4SLinus Torvalds * Data Transfer Rates:
6341da177e4SLinus Torvalds *
6351da177e4SLinus Torvalds * Bulk transfers are valid for full or high speed endpoints.
6361da177e4SLinus Torvalds * The best full speed data rate is 19 packets of 64 bytes each
6371da177e4SLinus Torvalds * per frame, or 1216 bytes per millisecond.
6381da177e4SLinus Torvalds * The best high speed data rate is 13 packets of 512 bytes each
6391da177e4SLinus Torvalds * per microframe, or 52 KBytes per millisecond.
6401da177e4SLinus Torvalds *
6411da177e4SLinus Torvalds * The reason to use interrupt transfers through this API would most likely
6421da177e4SLinus Torvalds * be to reserve high speed bandwidth, where up to 24 KBytes per millisecond
6431da177e4SLinus Torvalds * could be transferred. That capability is less useful for low or full
6441da177e4SLinus Torvalds * speed interrupt endpoints, which allow at most one packet per millisecond,
6451da177e4SLinus Torvalds * of at most 8 or 64 bytes (respectively).
64679abb1abSSarah Sharp *
64779abb1abSSarah Sharp * It is not necessary to call this function to reserve bandwidth for devices
64879abb1abSSarah Sharp * under an xHCI host controller, as the bandwidth is reserved when the
64979abb1abSSarah Sharp * configuration or interface alt setting is selected.
6501da177e4SLinus Torvalds */
usb_sg_wait(struct usb_sg_request * io)6511da177e4SLinus Torvalds void usb_sg_wait(struct usb_sg_request *io)
6521da177e4SLinus Torvalds {
6533e35bf39SGreg Kroah-Hartman int i;
6543e35bf39SGreg Kroah-Hartman int entries = io->entries;
6551da177e4SLinus Torvalds
6561da177e4SLinus Torvalds /* queue the urbs. */
6571da177e4SLinus Torvalds spin_lock_irq(&io->lock);
6588ccef0dfSAlan Stern i = 0;
6598ccef0dfSAlan Stern while (i < entries && !io->status) {
6601da177e4SLinus Torvalds int retval;
6611da177e4SLinus Torvalds
6621da177e4SLinus Torvalds io->urbs[i]->dev = io->dev;
6631da177e4SLinus Torvalds spin_unlock_irq(&io->lock);
66498b74b0eSDavid Mosberger
66598b74b0eSDavid Mosberger retval = usb_submit_urb(io->urbs[i], GFP_NOIO);
66698b74b0eSDavid Mosberger
6671da177e4SLinus Torvalds switch (retval) {
6681da177e4SLinus Torvalds /* maybe we retrying will recover */
6693e35bf39SGreg Kroah-Hartman case -ENXIO: /* hc didn't queue this one */
6701da177e4SLinus Torvalds case -EAGAIN:
6711da177e4SLinus Torvalds case -ENOMEM:
6721da177e4SLinus Torvalds retval = 0;
6731da177e4SLinus Torvalds yield();
6741da177e4SLinus Torvalds break;
6751da177e4SLinus Torvalds
6761da177e4SLinus Torvalds /* no error? continue immediately.
6771da177e4SLinus Torvalds *
6781da177e4SLinus Torvalds * NOTE: to work better with UHCI (4K I/O buffer may
6791da177e4SLinus Torvalds * need 3K of TDs) it may be good to limit how many
6801da177e4SLinus Torvalds * URBs are queued at once; N milliseconds?
6811da177e4SLinus Torvalds */
6821da177e4SLinus Torvalds case 0:
6838ccef0dfSAlan Stern ++i;
6841da177e4SLinus Torvalds cpu_relax();
6851da177e4SLinus Torvalds break;
6861da177e4SLinus Torvalds
6871da177e4SLinus Torvalds /* fail any uncompleted urbs */
6881da177e4SLinus Torvalds default:
6891da177e4SLinus Torvalds io->urbs[i]->status = retval;
6901da177e4SLinus Torvalds dev_dbg(&io->dev->dev, "%s, submit --> %d\n",
691441b62c1SHarvey Harrison __func__, retval);
6921da177e4SLinus Torvalds usb_sg_cancel(io);
6931da177e4SLinus Torvalds }
6941da177e4SLinus Torvalds spin_lock_irq(&io->lock);
6951da177e4SLinus Torvalds if (retval && (io->status == 0 || io->status == -ECONNRESET))
6961da177e4SLinus Torvalds io->status = retval;
6971da177e4SLinus Torvalds }
6981da177e4SLinus Torvalds io->count -= entries - i;
6991da177e4SLinus Torvalds if (io->count == 0)
7001da177e4SLinus Torvalds complete(&io->complete);
7011da177e4SLinus Torvalds spin_unlock_irq(&io->lock);
7021da177e4SLinus Torvalds
7031da177e4SLinus Torvalds /* OK, yes, this could be packaged as non-blocking.
7041da177e4SLinus Torvalds * So could the submit loop above ... but it's easier to
7051da177e4SLinus Torvalds * solve neither problem than to solve both!
7061da177e4SLinus Torvalds */
7071da177e4SLinus Torvalds wait_for_completion(&io->complete);
7081da177e4SLinus Torvalds
7091da177e4SLinus Torvalds sg_clean(io);
7101da177e4SLinus Torvalds }
711782e70c6SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(usb_sg_wait);
7121da177e4SLinus Torvalds
7131da177e4SLinus Torvalds /**
7141da177e4SLinus Torvalds * usb_sg_cancel - stop scatter/gather i/o issued by usb_sg_wait()
7151da177e4SLinus Torvalds * @io: request block, initialized with usb_sg_init()
7161da177e4SLinus Torvalds *
7171da177e4SLinus Torvalds * This stops a request after it has been started by usb_sg_wait().
7181da177e4SLinus Torvalds * It can also prevents one initialized by usb_sg_init() from starting,
7191da177e4SLinus Torvalds * so that call just frees resources allocated to the request.
7201da177e4SLinus Torvalds */
usb_sg_cancel(struct usb_sg_request * io)7211da177e4SLinus Torvalds void usb_sg_cancel(struct usb_sg_request *io)
7221da177e4SLinus Torvalds {
7231da177e4SLinus Torvalds unsigned long flags;
7245f2e5fb8SDavid Mosberger int i, retval;
7251da177e4SLinus Torvalds
7261da177e4SLinus Torvalds spin_lock_irqsave(&io->lock, flags);
727056ad39eSAlan Stern if (io->status || io->count == 0) {
7285f2e5fb8SDavid Mosberger spin_unlock_irqrestore(&io->lock, flags);
7295f2e5fb8SDavid Mosberger return;
7305f2e5fb8SDavid Mosberger }
7315f2e5fb8SDavid Mosberger /* shut everything down */
7321da177e4SLinus Torvalds io->status = -ECONNRESET;
733056ad39eSAlan Stern io->count++; /* Keep the request alive until we're done */
7345f2e5fb8SDavid Mosberger spin_unlock_irqrestore(&io->lock, flags);
7351da177e4SLinus Torvalds
7365f2e5fb8SDavid Mosberger for (i = io->entries - 1; i >= 0; --i) {
73798b74b0eSDavid Mosberger usb_block_urb(io->urbs[i]);
73898b74b0eSDavid Mosberger
7391da177e4SLinus Torvalds retval = usb_unlink_urb(io->urbs[i]);
740bcf39853SAlan Stern if (retval != -EINPROGRESS
741bcf39853SAlan Stern && retval != -ENODEV
742bcf39853SAlan Stern && retval != -EBUSY
743bcf39853SAlan Stern && retval != -EIDRM)
7441da177e4SLinus Torvalds dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
745441b62c1SHarvey Harrison __func__, retval);
7461da177e4SLinus Torvalds }
747056ad39eSAlan Stern
748056ad39eSAlan Stern spin_lock_irqsave(&io->lock, flags);
749056ad39eSAlan Stern io->count--;
750056ad39eSAlan Stern if (!io->count)
751056ad39eSAlan Stern complete(&io->complete);
752056ad39eSAlan Stern spin_unlock_irqrestore(&io->lock, flags);
7531da177e4SLinus Torvalds }
754782e70c6SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(usb_sg_cancel);
7551da177e4SLinus Torvalds
7561da177e4SLinus Torvalds /*-------------------------------------------------------------------*/
7571da177e4SLinus Torvalds
7581da177e4SLinus Torvalds /**
7591da177e4SLinus Torvalds * usb_get_descriptor - issues a generic GET_DESCRIPTOR request
7601da177e4SLinus Torvalds * @dev: the device whose descriptor is being retrieved
7611da177e4SLinus Torvalds * @type: the descriptor type (USB_DT_*)
7621da177e4SLinus Torvalds * @index: the number of the descriptor
7631da177e4SLinus Torvalds * @buf: where to put the descriptor
7641da177e4SLinus Torvalds * @size: how big is "buf"?
76541631d36SAhmed S. Darwish *
76641631d36SAhmed S. Darwish * Context: task context, might sleep.
7671da177e4SLinus Torvalds *
7681da177e4SLinus Torvalds * Gets a USB descriptor. Convenience functions exist to simplify
7691da177e4SLinus Torvalds * getting some types of descriptors. Use
7701da177e4SLinus Torvalds * usb_get_string() or usb_string() for USB_DT_STRING.
7711da177e4SLinus Torvalds * Device (USB_DT_DEVICE) and configuration descriptors (USB_DT_CONFIG)
7721da177e4SLinus Torvalds * are part of the device structure.
7731da177e4SLinus Torvalds * In addition to a number of USB-standard descriptors, some
7741da177e4SLinus Torvalds * devices also use class-specific or vendor-specific descriptors.
7751da177e4SLinus Torvalds *
7761da177e4SLinus Torvalds * This call is synchronous, and may not be used in an interrupt context.
7771da177e4SLinus Torvalds *
778626f090cSYacine Belkadi * Return: The number of bytes received on success, or else the status code
7791da177e4SLinus Torvalds * returned by the underlying usb_control_msg() call.
7801da177e4SLinus Torvalds */
usb_get_descriptor(struct usb_device * dev,unsigned char type,unsigned char index,void * buf,int size)7813e35bf39SGreg Kroah-Hartman int usb_get_descriptor(struct usb_device *dev, unsigned char type,
7823e35bf39SGreg Kroah-Hartman unsigned char index, void *buf, int size)
7831da177e4SLinus Torvalds {
7841da177e4SLinus Torvalds int i;
7851da177e4SLinus Torvalds int result;
7861da177e4SLinus Torvalds
78760dfe484SAlan Stern if (size <= 0) /* No point in asking for no data */
78860dfe484SAlan Stern return -EINVAL;
78960dfe484SAlan Stern
7903e35bf39SGreg Kroah-Hartman memset(buf, 0, size); /* Make sure we parse really received data */
7911da177e4SLinus Torvalds
7921da177e4SLinus Torvalds for (i = 0; i < 3; ++i) {
793c39772d8SAlan Stern /* retry on length 0 or error; some devices are flakey */
7941da177e4SLinus Torvalds result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
7951da177e4SLinus Torvalds USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
7961da177e4SLinus Torvalds (type << 8) + index, 0, buf, size,
7971da177e4SLinus Torvalds USB_CTRL_GET_TIMEOUT);
798c39772d8SAlan Stern if (result <= 0 && result != -ETIMEDOUT)
7991da177e4SLinus Torvalds continue;
8001da177e4SLinus Torvalds if (result > 1 && ((u8 *)buf)[1] != type) {
80167f5a4baSAlan Stern result = -ENODATA;
8021da177e4SLinus Torvalds continue;
8031da177e4SLinus Torvalds }
8041da177e4SLinus Torvalds break;
8051da177e4SLinus Torvalds }
8061da177e4SLinus Torvalds return result;
8071da177e4SLinus Torvalds }
808782e70c6SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(usb_get_descriptor);
8091da177e4SLinus Torvalds
8101da177e4SLinus Torvalds /**
8111da177e4SLinus Torvalds * usb_get_string - gets a string descriptor
8121da177e4SLinus Torvalds * @dev: the device whose string descriptor is being retrieved
8131da177e4SLinus Torvalds * @langid: code for language chosen (from string descriptor zero)
8141da177e4SLinus Torvalds * @index: the number of the descriptor
8151da177e4SLinus Torvalds * @buf: where to put the string
8161da177e4SLinus Torvalds * @size: how big is "buf"?
81741631d36SAhmed S. Darwish *
81841631d36SAhmed S. Darwish * Context: task context, might sleep.
8191da177e4SLinus Torvalds *
8201da177e4SLinus Torvalds * Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character,
8211da177e4SLinus Torvalds * in little-endian byte order).
8221da177e4SLinus Torvalds * The usb_string() function will often be a convenient way to turn
8231da177e4SLinus Torvalds * these strings into kernel-printable form.
8241da177e4SLinus Torvalds *
8251da177e4SLinus Torvalds * Strings may be referenced in device, configuration, interface, or other
8261da177e4SLinus Torvalds * descriptors, and could also be used in vendor-specific ways.
8271da177e4SLinus Torvalds *
8281da177e4SLinus Torvalds * This call is synchronous, and may not be used in an interrupt context.
8291da177e4SLinus Torvalds *
830626f090cSYacine Belkadi * Return: The number of bytes received on success, or else the status code
8311da177e4SLinus Torvalds * returned by the underlying usb_control_msg() call.
8321da177e4SLinus Torvalds */
usb_get_string(struct usb_device * dev,unsigned short langid,unsigned char index,void * buf,int size)833e266a124SAdrian Bunk static int usb_get_string(struct usb_device *dev, unsigned short langid,
8341da177e4SLinus Torvalds unsigned char index, void *buf, int size)
8351da177e4SLinus Torvalds {
8361da177e4SLinus Torvalds int i;
8371da177e4SLinus Torvalds int result;
8381da177e4SLinus Torvalds
83960dfe484SAlan Stern if (size <= 0) /* No point in asking for no data */
84060dfe484SAlan Stern return -EINVAL;
84160dfe484SAlan Stern
8421da177e4SLinus Torvalds for (i = 0; i < 3; ++i) {
8431da177e4SLinus Torvalds /* retry on length 0 or stall; some devices are flakey */
8441da177e4SLinus Torvalds result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
8451da177e4SLinus Torvalds USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
8461da177e4SLinus Torvalds (USB_DT_STRING << 8) + index, langid, buf, size,
8471da177e4SLinus Torvalds USB_CTRL_GET_TIMEOUT);
84867f5a4baSAlan Stern if (result == 0 || result == -EPIPE)
84967f5a4baSAlan Stern continue;
85067f5a4baSAlan Stern if (result > 1 && ((u8 *) buf)[1] != USB_DT_STRING) {
85167f5a4baSAlan Stern result = -ENODATA;
85267f5a4baSAlan Stern continue;
85367f5a4baSAlan Stern }
8541da177e4SLinus Torvalds break;
8551da177e4SLinus Torvalds }
8561da177e4SLinus Torvalds return result;
8571da177e4SLinus Torvalds }
8581da177e4SLinus Torvalds
usb_try_string_workarounds(unsigned char * buf,int * length)8591da177e4SLinus Torvalds static void usb_try_string_workarounds(unsigned char *buf, int *length)
8601da177e4SLinus Torvalds {
8611da177e4SLinus Torvalds int newlength, oldlength = *length;
8621da177e4SLinus Torvalds
8631da177e4SLinus Torvalds for (newlength = 2; newlength + 1 < oldlength; newlength += 2)
8641da177e4SLinus Torvalds if (!isprint(buf[newlength]) || buf[newlength + 1])
8651da177e4SLinus Torvalds break;
8661da177e4SLinus Torvalds
8671da177e4SLinus Torvalds if (newlength > 2) {
8681da177e4SLinus Torvalds buf[0] = newlength;
8691da177e4SLinus Torvalds *length = newlength;
8701da177e4SLinus Torvalds }
8711da177e4SLinus Torvalds }
8721da177e4SLinus Torvalds
usb_string_sub(struct usb_device * dev,unsigned int langid,unsigned int index,unsigned char * buf)8731da177e4SLinus Torvalds static int usb_string_sub(struct usb_device *dev, unsigned int langid,
8741da177e4SLinus Torvalds unsigned int index, unsigned char *buf)
8751da177e4SLinus Torvalds {
8761da177e4SLinus Torvalds int rc;
8771da177e4SLinus Torvalds
8781da177e4SLinus Torvalds /* Try to read the string descriptor by asking for the maximum
8791da177e4SLinus Torvalds * possible number of bytes */
8807ceec1f1SOliver Neukum if (dev->quirks & USB_QUIRK_STRING_FETCH_255)
8817ceec1f1SOliver Neukum rc = -EIO;
8827ceec1f1SOliver Neukum else
8831da177e4SLinus Torvalds rc = usb_get_string(dev, langid, index, buf, 255);
8841da177e4SLinus Torvalds
8851da177e4SLinus Torvalds /* If that failed try to read the descriptor length, then
8861da177e4SLinus Torvalds * ask for just that many bytes */
8871da177e4SLinus Torvalds if (rc < 2) {
8881da177e4SLinus Torvalds rc = usb_get_string(dev, langid, index, buf, 2);
8891da177e4SLinus Torvalds if (rc == 2)
8901da177e4SLinus Torvalds rc = usb_get_string(dev, langid, index, buf, buf[0]);
8911da177e4SLinus Torvalds }
8921da177e4SLinus Torvalds
8931da177e4SLinus Torvalds if (rc >= 2) {
8941da177e4SLinus Torvalds if (!buf[0] && !buf[1])
8951da177e4SLinus Torvalds usb_try_string_workarounds(buf, &rc);
8961da177e4SLinus Torvalds
8971da177e4SLinus Torvalds /* There might be extra junk at the end of the descriptor */
8981da177e4SLinus Torvalds if (buf[0] < rc)
8991da177e4SLinus Torvalds rc = buf[0];
9001da177e4SLinus Torvalds
9011da177e4SLinus Torvalds rc = rc - (rc & 1); /* force a multiple of two */
9021da177e4SLinus Torvalds }
9031da177e4SLinus Torvalds
9041da177e4SLinus Torvalds if (rc < 2)
9051da177e4SLinus Torvalds rc = (rc < 0 ? rc : -EINVAL);
9061da177e4SLinus Torvalds
9071da177e4SLinus Torvalds return rc;
9081da177e4SLinus Torvalds }
9091da177e4SLinus Torvalds
usb_get_langid(struct usb_device * dev,unsigned char * tbuf)9100cce2edaSDaniel Mack static int usb_get_langid(struct usb_device *dev, unsigned char *tbuf)
9110cce2edaSDaniel Mack {
9120cce2edaSDaniel Mack int err;
9130cce2edaSDaniel Mack
9140cce2edaSDaniel Mack if (dev->have_langid)
9150cce2edaSDaniel Mack return 0;
9160cce2edaSDaniel Mack
9170cce2edaSDaniel Mack if (dev->string_langid < 0)
9180cce2edaSDaniel Mack return -EPIPE;
9190cce2edaSDaniel Mack
9200cce2edaSDaniel Mack err = usb_string_sub(dev, 0, 0, tbuf);
9210cce2edaSDaniel Mack
9220cce2edaSDaniel Mack /* If the string was reported but is malformed, default to english
9230cce2edaSDaniel Mack * (0x0409) */
9240cce2edaSDaniel Mack if (err == -ENODATA || (err > 0 && err < 4)) {
9250cce2edaSDaniel Mack dev->string_langid = 0x0409;
9260cce2edaSDaniel Mack dev->have_langid = 1;
9270cce2edaSDaniel Mack dev_err(&dev->dev,
928586af079SScot Doyle "language id specifier not provided by device, defaulting to English\n");
9290cce2edaSDaniel Mack return 0;
9300cce2edaSDaniel Mack }
9310cce2edaSDaniel Mack
9320cce2edaSDaniel Mack /* In case of all other errors, we assume the device is not able to
9330cce2edaSDaniel Mack * deal with strings at all. Set string_langid to -1 in order to
9340cce2edaSDaniel Mack * prevent any string to be retrieved from the device */
9350cce2edaSDaniel Mack if (err < 0) {
9362124c888SKai-Heng Feng dev_info(&dev->dev, "string descriptor 0 read error: %d\n",
9370cce2edaSDaniel Mack err);
9380cce2edaSDaniel Mack dev->string_langid = -1;
9390cce2edaSDaniel Mack return -EPIPE;
9400cce2edaSDaniel Mack }
9410cce2edaSDaniel Mack
9420cce2edaSDaniel Mack /* always use the first langid listed */
9430cce2edaSDaniel Mack dev->string_langid = tbuf[2] | (tbuf[3] << 8);
9440cce2edaSDaniel Mack dev->have_langid = 1;
9450cce2edaSDaniel Mack dev_dbg(&dev->dev, "default language 0x%04x\n",
9460cce2edaSDaniel Mack dev->string_langid);
9470cce2edaSDaniel Mack return 0;
9480cce2edaSDaniel Mack }
9490cce2edaSDaniel Mack
9501da177e4SLinus Torvalds /**
951a853a3d4SClemens Ladisch * usb_string - returns UTF-8 version of a string descriptor
9521da177e4SLinus Torvalds * @dev: the device whose string descriptor is being retrieved
9531da177e4SLinus Torvalds * @index: the number of the descriptor
9541da177e4SLinus Torvalds * @buf: where to put the string
9551da177e4SLinus Torvalds * @size: how big is "buf"?
95641631d36SAhmed S. Darwish *
95741631d36SAhmed S. Darwish * Context: task context, might sleep.
9581da177e4SLinus Torvalds *
9591da177e4SLinus Torvalds * This converts the UTF-16LE encoded strings returned by devices, from
960a853a3d4SClemens Ladisch * usb_get_string_descriptor(), to null-terminated UTF-8 encoded ones
961a853a3d4SClemens Ladisch * that are more usable in most kernel contexts. Note that this function
9621da177e4SLinus Torvalds * chooses strings in the first language supported by the device.
9631da177e4SLinus Torvalds *
9641da177e4SLinus Torvalds * This call is synchronous, and may not be used in an interrupt context.
9651da177e4SLinus Torvalds *
966626f090cSYacine Belkadi * Return: length of the string (>= 0) or usb_control_msg status (< 0).
9671da177e4SLinus Torvalds */
usb_string(struct usb_device * dev,int index,char * buf,size_t size)9681da177e4SLinus Torvalds int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
9691da177e4SLinus Torvalds {
9701da177e4SLinus Torvalds unsigned char *tbuf;
9711da177e4SLinus Torvalds int err;
9721da177e4SLinus Torvalds
9731da177e4SLinus Torvalds if (dev->state == USB_STATE_SUSPENDED)
9741da177e4SLinus Torvalds return -EHOSTUNREACH;
975c01c348eSAlan Stern if (size <= 0 || !buf)
9761da177e4SLinus Torvalds return -EINVAL;
9771da177e4SLinus Torvalds buf[0] = 0;
978c01c348eSAlan Stern if (index <= 0 || index >= 256)
979c01c348eSAlan Stern return -EINVAL;
98074675a58SAlan Stern tbuf = kmalloc(256, GFP_NOIO);
9811da177e4SLinus Torvalds if (!tbuf)
9821da177e4SLinus Torvalds return -ENOMEM;
9831da177e4SLinus Torvalds
9840cce2edaSDaniel Mack err = usb_get_langid(dev, tbuf);
9850cce2edaSDaniel Mack if (err < 0)
9860cce2edaSDaniel Mack goto errout;
9871da177e4SLinus Torvalds
9881da177e4SLinus Torvalds err = usb_string_sub(dev, dev->string_langid, index, tbuf);
9891da177e4SLinus Torvalds if (err < 0)
9901da177e4SLinus Torvalds goto errout;
9911da177e4SLinus Torvalds
9921da177e4SLinus Torvalds size--; /* leave room for trailing NULL char in output buffer */
99374675a58SAlan Stern err = utf16s_to_utf8s((wchar_t *) &tbuf[2], (err - 2) / 2,
99474675a58SAlan Stern UTF16_LITTLE_ENDIAN, buf, size);
995a853a3d4SClemens Ladisch buf[err] = 0;
9961da177e4SLinus Torvalds
9971da177e4SLinus Torvalds if (tbuf[1] != USB_DT_STRING)
9983e35bf39SGreg Kroah-Hartman dev_dbg(&dev->dev,
9993e35bf39SGreg Kroah-Hartman "wrong descriptor type %02x for string %d (\"%s\")\n",
10003e35bf39SGreg Kroah-Hartman tbuf[1], index, buf);
10011da177e4SLinus Torvalds
10021da177e4SLinus Torvalds errout:
10031da177e4SLinus Torvalds kfree(tbuf);
10041da177e4SLinus Torvalds return err;
10051da177e4SLinus Torvalds }
1006782e70c6SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(usb_string);
10071da177e4SLinus Torvalds
1008a853a3d4SClemens Ladisch /* one UTF-8-encoded 16-bit character has at most three bytes */
1009a853a3d4SClemens Ladisch #define MAX_USB_STRING_SIZE (127 * 3 + 1)
1010a853a3d4SClemens Ladisch
10114f62efe6SAlan Stern /**
10124f62efe6SAlan Stern * usb_cache_string - read a string descriptor and cache it for later use
10134f62efe6SAlan Stern * @udev: the device whose string descriptor is being read
10144f62efe6SAlan Stern * @index: the descriptor index
10154f62efe6SAlan Stern *
1016626f090cSYacine Belkadi * Return: A pointer to a kmalloc'ed buffer containing the descriptor string,
1017626f090cSYacine Belkadi * or %NULL if the index is 0 or the string could not be read.
10184f62efe6SAlan Stern */
usb_cache_string(struct usb_device * udev,int index)10194f62efe6SAlan Stern char *usb_cache_string(struct usb_device *udev, int index)
10204f62efe6SAlan Stern {
10214f62efe6SAlan Stern char *buf;
10224f62efe6SAlan Stern char *smallbuf = NULL;
10234f62efe6SAlan Stern int len;
10244f62efe6SAlan Stern
10253e35bf39SGreg Kroah-Hartman if (index <= 0)
10263e35bf39SGreg Kroah-Hartman return NULL;
10273e35bf39SGreg Kroah-Hartman
1028acbe2febSOliver Neukum buf = kmalloc(MAX_USB_STRING_SIZE, GFP_NOIO);
10293e35bf39SGreg Kroah-Hartman if (buf) {
1030a853a3d4SClemens Ladisch len = usb_string(udev, index, buf, MAX_USB_STRING_SIZE);
10313e35bf39SGreg Kroah-Hartman if (len > 0) {
1032acbe2febSOliver Neukum smallbuf = kmalloc(++len, GFP_NOIO);
10333e35bf39SGreg Kroah-Hartman if (!smallbuf)
10344f62efe6SAlan Stern return buf;
10354f62efe6SAlan Stern memcpy(smallbuf, buf, len);
10364f62efe6SAlan Stern }
10374f62efe6SAlan Stern kfree(buf);
10384f62efe6SAlan Stern }
10394f62efe6SAlan Stern return smallbuf;
10404f62efe6SAlan Stern }
1041983055bfSVincent Mailhol EXPORT_SYMBOL_GPL(usb_cache_string);
10424f62efe6SAlan Stern
10431da177e4SLinus Torvalds /*
1044de28e469SAlan Stern * usb_get_device_descriptor - read the device descriptor
1045de28e469SAlan Stern * @udev: the device whose device descriptor should be read
104641631d36SAhmed S. Darwish *
104741631d36SAhmed S. Darwish * Context: task context, might sleep.
10481da177e4SLinus Torvalds *
10491da177e4SLinus Torvalds * Not exported, only for use by the core. If drivers really want to read
10501da177e4SLinus Torvalds * the device descriptor directly, they can call usb_get_descriptor() with
10511da177e4SLinus Torvalds * type = USB_DT_DEVICE and index = 0.
10521da177e4SLinus Torvalds *
1053de28e469SAlan Stern * Returns: a pointer to a dynamically allocated usb_device_descriptor
1054de28e469SAlan Stern * structure (which the caller must deallocate), or an ERR_PTR value.
10551da177e4SLinus Torvalds */
usb_get_device_descriptor(struct usb_device * udev)1056de28e469SAlan Stern struct usb_device_descriptor *usb_get_device_descriptor(struct usb_device *udev)
10571da177e4SLinus Torvalds {
10581da177e4SLinus Torvalds struct usb_device_descriptor *desc;
10591da177e4SLinus Torvalds int ret;
10601da177e4SLinus Torvalds
10611da177e4SLinus Torvalds desc = kmalloc(sizeof(*desc), GFP_NOIO);
10621da177e4SLinus Torvalds if (!desc)
1063de28e469SAlan Stern return ERR_PTR(-ENOMEM);
10641da177e4SLinus Torvalds
1065de28e469SAlan Stern ret = usb_get_descriptor(udev, USB_DT_DEVICE, 0, desc, sizeof(*desc));
1066de28e469SAlan Stern if (ret == sizeof(*desc))
1067de28e469SAlan Stern return desc;
1068de28e469SAlan Stern
10691da177e4SLinus Torvalds if (ret >= 0)
1070de28e469SAlan Stern ret = -EMSGSIZE;
10711da177e4SLinus Torvalds kfree(desc);
1072de28e469SAlan Stern return ERR_PTR(ret);
10731da177e4SLinus Torvalds }
10741da177e4SLinus Torvalds
1075886ee36eSFelipe Balbi /*
1076886ee36eSFelipe Balbi * usb_set_isoch_delay - informs the device of the packet transmit delay
1077886ee36eSFelipe Balbi * @dev: the device whose delay is to be informed
107841631d36SAhmed S. Darwish * Context: task context, might sleep
1079886ee36eSFelipe Balbi *
1080886ee36eSFelipe Balbi * Since this is an optional request, we don't bother if it fails.
1081886ee36eSFelipe Balbi */
usb_set_isoch_delay(struct usb_device * dev)1082886ee36eSFelipe Balbi int usb_set_isoch_delay(struct usb_device *dev)
1083886ee36eSFelipe Balbi {
1084886ee36eSFelipe Balbi /* skip hub devices */
1085886ee36eSFelipe Balbi if (dev->descriptor.bDeviceClass == USB_CLASS_HUB)
1086886ee36eSFelipe Balbi return 0;
1087886ee36eSFelipe Balbi
1088886ee36eSFelipe Balbi /* skip non-SS/non-SSP devices */
1089886ee36eSFelipe Balbi if (dev->speed < USB_SPEED_SUPER)
1090886ee36eSFelipe Balbi return 0;
1091886ee36eSFelipe Balbi
1092297e84c0SGreg Kroah-Hartman return usb_control_msg_send(dev, 0,
1093886ee36eSFelipe Balbi USB_REQ_SET_ISOCH_DELAY,
1094886ee36eSFelipe Balbi USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
109548b73d0fSRuslan Bilovol dev->hub_delay, 0, NULL, 0,
1096ddd1198eSOliver Neukum USB_CTRL_SET_TIMEOUT,
1097ddd1198eSOliver Neukum GFP_NOIO);
1098886ee36eSFelipe Balbi }
1099886ee36eSFelipe Balbi
11001da177e4SLinus Torvalds /**
11011da177e4SLinus Torvalds * usb_get_status - issues a GET_STATUS call
11021da177e4SLinus Torvalds * @dev: the device whose status is being checked
11033c377ef1SFelipe Balbi * @recip: USB_RECIP_*; for device, interface, or endpoint
11042e43f0feSFelipe Balbi * @type: USB_STATUS_TYPE_*; for standard or PTM status types
11051da177e4SLinus Torvalds * @target: zero (for device), else interface or endpoint number
11061da177e4SLinus Torvalds * @data: pointer to two bytes of bitmap data
110741631d36SAhmed S. Darwish *
110841631d36SAhmed S. Darwish * Context: task context, might sleep.
11091da177e4SLinus Torvalds *
11101da177e4SLinus Torvalds * Returns device, interface, or endpoint status. Normally only of
11111da177e4SLinus Torvalds * interest to see if the device is self powered, or has enabled the
11121da177e4SLinus Torvalds * remote wakeup facility; or whether a bulk or interrupt endpoint
11131da177e4SLinus Torvalds * is halted ("stalled").
11141da177e4SLinus Torvalds *
11151da177e4SLinus Torvalds * Bits in these status bitmaps are set using the SET_FEATURE request,
11161da177e4SLinus Torvalds * and cleared using the CLEAR_FEATURE request. The usb_clear_halt()
11171da177e4SLinus Torvalds * function should be used to clear halt ("stall") status.
11181da177e4SLinus Torvalds *
11191da177e4SLinus Torvalds * This call is synchronous, and may not be used in an interrupt context.
11201da177e4SLinus Torvalds *
112115b7336eSAlan Stern * Returns 0 and the status value in *@data (in host byte order) on success,
112215b7336eSAlan Stern * or else the status code from the underlying usb_control_msg() call.
11231da177e4SLinus Torvalds */
usb_get_status(struct usb_device * dev,int recip,int type,int target,void * data)11242e43f0feSFelipe Balbi int usb_get_status(struct usb_device *dev, int recip, int type, int target,
11252e43f0feSFelipe Balbi void *data)
11261da177e4SLinus Torvalds {
11271da177e4SLinus Torvalds int ret;
11282e43f0feSFelipe Balbi void *status;
11292e43f0feSFelipe Balbi int length;
11301da177e4SLinus Torvalds
11312e43f0feSFelipe Balbi switch (type) {
11322e43f0feSFelipe Balbi case USB_STATUS_TYPE_STANDARD:
11332e43f0feSFelipe Balbi length = 2;
11342e43f0feSFelipe Balbi break;
11352e43f0feSFelipe Balbi case USB_STATUS_TYPE_PTM:
11362e43f0feSFelipe Balbi if (recip != USB_RECIP_DEVICE)
11372e43f0feSFelipe Balbi return -EINVAL;
11382e43f0feSFelipe Balbi
11392e43f0feSFelipe Balbi length = 4;
11402e43f0feSFelipe Balbi break;
11412e43f0feSFelipe Balbi default:
11422e43f0feSFelipe Balbi return -EINVAL;
11432e43f0feSFelipe Balbi }
11442e43f0feSFelipe Balbi
11452e43f0feSFelipe Balbi status = kmalloc(length, GFP_KERNEL);
11461da177e4SLinus Torvalds if (!status)
11471da177e4SLinus Torvalds return -ENOMEM;
11481da177e4SLinus Torvalds
11491da177e4SLinus Torvalds ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
11503c377ef1SFelipe Balbi USB_REQ_GET_STATUS, USB_DIR_IN | recip, USB_STATUS_TYPE_STANDARD,
11512e43f0feSFelipe Balbi target, status, length, USB_CTRL_GET_TIMEOUT);
11521da177e4SLinus Torvalds
11532e43f0feSFelipe Balbi switch (ret) {
11542e43f0feSFelipe Balbi case 4:
11552e43f0feSFelipe Balbi if (type != USB_STATUS_TYPE_PTM) {
11562e43f0feSFelipe Balbi ret = -EIO;
11572e43f0feSFelipe Balbi break;
11582e43f0feSFelipe Balbi }
11592e43f0feSFelipe Balbi
11602e43f0feSFelipe Balbi *(u32 *) data = le32_to_cpu(*(__le32 *) status);
1161d656fa32SFelipe Balbi ret = 0;
11622e43f0feSFelipe Balbi break;
11632e43f0feSFelipe Balbi case 2:
11642e43f0feSFelipe Balbi if (type != USB_STATUS_TYPE_STANDARD) {
11652e43f0feSFelipe Balbi ret = -EIO;
11662e43f0feSFelipe Balbi break;
11672e43f0feSFelipe Balbi }
11682e43f0feSFelipe Balbi
11692e43f0feSFelipe Balbi *(u16 *) data = le16_to_cpu(*(__le16 *) status);
1170d656fa32SFelipe Balbi ret = 0;
11712e43f0feSFelipe Balbi break;
11722e43f0feSFelipe Balbi default:
117315b7336eSAlan Stern ret = -EIO;
117415b7336eSAlan Stern }
11752e43f0feSFelipe Balbi
11761da177e4SLinus Torvalds kfree(status);
11771da177e4SLinus Torvalds return ret;
11781da177e4SLinus Torvalds }
1179782e70c6SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(usb_get_status);
11801da177e4SLinus Torvalds
11811da177e4SLinus Torvalds /**
11821da177e4SLinus Torvalds * usb_clear_halt - tells device to clear endpoint halt/stall condition
11831da177e4SLinus Torvalds * @dev: device whose endpoint is halted
11841da177e4SLinus Torvalds * @pipe: endpoint "pipe" being cleared
118541631d36SAhmed S. Darwish *
118641631d36SAhmed S. Darwish * Context: task context, might sleep.
11871da177e4SLinus Torvalds *
11881da177e4SLinus Torvalds * This is used to clear halt conditions for bulk and interrupt endpoints,
11891da177e4SLinus Torvalds * as reported by URB completion status. Endpoints that are halted are
11901da177e4SLinus Torvalds * sometimes referred to as being "stalled". Such endpoints are unable
11911da177e4SLinus Torvalds * to transmit or receive data until the halt status is cleared. Any URBs
11921da177e4SLinus Torvalds * queued for such an endpoint should normally be unlinked by the driver
11931da177e4SLinus Torvalds * before clearing the halt condition, as described in sections 5.7.5
11941da177e4SLinus Torvalds * and 5.8.5 of the USB 2.0 spec.
11951da177e4SLinus Torvalds *
11961da177e4SLinus Torvalds * Note that control and isochronous endpoints don't halt, although control
11971da177e4SLinus Torvalds * endpoints report "protocol stall" (for unsupported requests) using the
11981da177e4SLinus Torvalds * same status code used to report a true stall.
11991da177e4SLinus Torvalds *
12001da177e4SLinus Torvalds * This call is synchronous, and may not be used in an interrupt context.
1201*9f2a3933SMichal Pecio * If a thread in your driver uses this call, make sure your disconnect()
1202*9f2a3933SMichal Pecio * method can wait for it to complete.
12031da177e4SLinus Torvalds *
1204626f090cSYacine Belkadi * Return: Zero on success, or else the status code returned by the
12051da177e4SLinus Torvalds * underlying usb_control_msg() call.
12061da177e4SLinus Torvalds */
usb_clear_halt(struct usb_device * dev,int pipe)12071da177e4SLinus Torvalds int usb_clear_halt(struct usb_device *dev, int pipe)
12081da177e4SLinus Torvalds {
12091da177e4SLinus Torvalds int result;
12101da177e4SLinus Torvalds int endp = usb_pipeendpoint(pipe);
12111da177e4SLinus Torvalds
12121da177e4SLinus Torvalds if (usb_pipein(pipe))
12131da177e4SLinus Torvalds endp |= USB_DIR_IN;
12141da177e4SLinus Torvalds
12151da177e4SLinus Torvalds /* we don't care if it wasn't halted first. in fact some devices
12161da177e4SLinus Torvalds * (like some ibmcam model 1 units) seem to expect hosts to make
12171da177e4SLinus Torvalds * this request for iso endpoints, which can't halt!
12181da177e4SLinus Torvalds */
1219297e84c0SGreg Kroah-Hartman result = usb_control_msg_send(dev, 0,
12201da177e4SLinus Torvalds USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
12211da177e4SLinus Torvalds USB_ENDPOINT_HALT, endp, NULL, 0,
1222ddd1198eSOliver Neukum USB_CTRL_SET_TIMEOUT, GFP_NOIO);
12231da177e4SLinus Torvalds
12241da177e4SLinus Torvalds /* don't un-halt or force to DATA0 except on success */
1225297e84c0SGreg Kroah-Hartman if (result)
12261da177e4SLinus Torvalds return result;
12271da177e4SLinus Torvalds
12281da177e4SLinus Torvalds /* NOTE: seems like Microsoft and Apple don't bother verifying
12291da177e4SLinus Torvalds * the clear "took", so some devices could lock up if you check...
12301da177e4SLinus Torvalds * such as the Hagiwara FlashGate DUAL. So we won't bother.
12311da177e4SLinus Torvalds *
12321da177e4SLinus Torvalds * NOTE: make sure the logic here doesn't diverge much from
12331da177e4SLinus Torvalds * the copy in usb-storage, for as long as we need two copies.
12341da177e4SLinus Torvalds */
12351da177e4SLinus Torvalds
12363444b26aSDavid Vrabel usb_reset_endpoint(dev, endp);
12371da177e4SLinus Torvalds
12381da177e4SLinus Torvalds return 0;
12391da177e4SLinus Torvalds }
1240782e70c6SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(usb_clear_halt);
12411da177e4SLinus Torvalds
create_intf_ep_devs(struct usb_interface * intf)12423b23dd6fSAlan Stern static int create_intf_ep_devs(struct usb_interface *intf)
12433b23dd6fSAlan Stern {
12443b23dd6fSAlan Stern struct usb_device *udev = interface_to_usbdev(intf);
12453b23dd6fSAlan Stern struct usb_host_interface *alt = intf->cur_altsetting;
12463b23dd6fSAlan Stern int i;
12473b23dd6fSAlan Stern
12483b23dd6fSAlan Stern if (intf->ep_devs_created || intf->unregistering)
12493b23dd6fSAlan Stern return 0;
12503b23dd6fSAlan Stern
12513b23dd6fSAlan Stern for (i = 0; i < alt->desc.bNumEndpoints; ++i)
12523b23dd6fSAlan Stern (void) usb_create_ep_devs(&intf->dev, &alt->endpoint[i], udev);
12533b23dd6fSAlan Stern intf->ep_devs_created = 1;
12543b23dd6fSAlan Stern return 0;
12553b23dd6fSAlan Stern }
12563b23dd6fSAlan Stern
remove_intf_ep_devs(struct usb_interface * intf)12573b23dd6fSAlan Stern static void remove_intf_ep_devs(struct usb_interface *intf)
12583b23dd6fSAlan Stern {
12593b23dd6fSAlan Stern struct usb_host_interface *alt = intf->cur_altsetting;
12603b23dd6fSAlan Stern int i;
12613b23dd6fSAlan Stern
12623b23dd6fSAlan Stern if (!intf->ep_devs_created)
12633b23dd6fSAlan Stern return;
12643b23dd6fSAlan Stern
12653b23dd6fSAlan Stern for (i = 0; i < alt->desc.bNumEndpoints; ++i)
12663b23dd6fSAlan Stern usb_remove_ep_devs(&alt->endpoint[i]);
12673b23dd6fSAlan Stern intf->ep_devs_created = 0;
12683b23dd6fSAlan Stern }
12693b23dd6fSAlan Stern
12701da177e4SLinus Torvalds /**
12711da177e4SLinus Torvalds * usb_disable_endpoint -- Disable an endpoint by address
12721da177e4SLinus Torvalds * @dev: the device whose endpoint is being disabled
12731da177e4SLinus Torvalds * @epaddr: the endpoint's address. Endpoint number for output,
12741da177e4SLinus Torvalds * endpoint number + USB_DIR_IN for input
1275ddeac4e7SAlan Stern * @reset_hardware: flag to erase any endpoint state stored in the
1276ddeac4e7SAlan Stern * controller hardware
12771da177e4SLinus Torvalds *
1278ddeac4e7SAlan Stern * Disables the endpoint for URB submission and nukes all pending URBs.
1279ddeac4e7SAlan Stern * If @reset_hardware is set then also deallocates hcd/hardware state
1280ddeac4e7SAlan Stern * for the endpoint.
12811da177e4SLinus Torvalds */
usb_disable_endpoint(struct usb_device * dev,unsigned int epaddr,bool reset_hardware)1282ddeac4e7SAlan Stern void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr,
1283ddeac4e7SAlan Stern bool reset_hardware)
12841da177e4SLinus Torvalds {
12851da177e4SLinus Torvalds unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
12861da177e4SLinus Torvalds struct usb_host_endpoint *ep;
12871da177e4SLinus Torvalds
12881da177e4SLinus Torvalds if (!dev)
12891da177e4SLinus Torvalds return;
12901da177e4SLinus Torvalds
12911da177e4SLinus Torvalds if (usb_endpoint_out(epaddr)) {
12921da177e4SLinus Torvalds ep = dev->ep_out[epnum];
1293ac854131SAlan Stern if (reset_hardware && epnum != 0)
12941da177e4SLinus Torvalds dev->ep_out[epnum] = NULL;
12951da177e4SLinus Torvalds } else {
12961da177e4SLinus Torvalds ep = dev->ep_in[epnum];
1297ac854131SAlan Stern if (reset_hardware && epnum != 0)
12981da177e4SLinus Torvalds dev->ep_in[epnum] = NULL;
12991da177e4SLinus Torvalds }
1300bdd016baSAlan Stern if (ep) {
1301bdd016baSAlan Stern ep->enabled = 0;
130295cf82f9SAlan Stern usb_hcd_flush_endpoint(dev, ep);
1303ddeac4e7SAlan Stern if (reset_hardware)
130495cf82f9SAlan Stern usb_hcd_disable_endpoint(dev, ep);
13051da177e4SLinus Torvalds }
1306bdd016baSAlan Stern }
13071da177e4SLinus Torvalds
13081da177e4SLinus Torvalds /**
13093444b26aSDavid Vrabel * usb_reset_endpoint - Reset an endpoint's state.
13103444b26aSDavid Vrabel * @dev: the device whose endpoint is to be reset
13113444b26aSDavid Vrabel * @epaddr: the endpoint's address. Endpoint number for output,
13123444b26aSDavid Vrabel * endpoint number + USB_DIR_IN for input
13133444b26aSDavid Vrabel *
13143444b26aSDavid Vrabel * Resets any host-side endpoint state such as the toggle bit,
13153444b26aSDavid Vrabel * sequence number or current window.
13163444b26aSDavid Vrabel */
usb_reset_endpoint(struct usb_device * dev,unsigned int epaddr)13173444b26aSDavid Vrabel void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr)
13183444b26aSDavid Vrabel {
13193444b26aSDavid Vrabel unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
13203444b26aSDavid Vrabel struct usb_host_endpoint *ep;
13213444b26aSDavid Vrabel
13223444b26aSDavid Vrabel if (usb_endpoint_out(epaddr))
13233444b26aSDavid Vrabel ep = dev->ep_out[epnum];
13243444b26aSDavid Vrabel else
13253444b26aSDavid Vrabel ep = dev->ep_in[epnum];
13263444b26aSDavid Vrabel if (ep)
13273444b26aSDavid Vrabel usb_hcd_reset_endpoint(dev, ep);
13283444b26aSDavid Vrabel }
13293444b26aSDavid Vrabel EXPORT_SYMBOL_GPL(usb_reset_endpoint);
13303444b26aSDavid Vrabel
13313444b26aSDavid Vrabel
13323444b26aSDavid Vrabel /**
13331da177e4SLinus Torvalds * usb_disable_interface -- Disable all endpoints for an interface
13341da177e4SLinus Torvalds * @dev: the device whose interface is being disabled
13351da177e4SLinus Torvalds * @intf: pointer to the interface descriptor
1336ddeac4e7SAlan Stern * @reset_hardware: flag to erase any endpoint state stored in the
1337ddeac4e7SAlan Stern * controller hardware
13381da177e4SLinus Torvalds *
13391da177e4SLinus Torvalds * Disables all the endpoints for the interface's current altsetting.
13401da177e4SLinus Torvalds */
usb_disable_interface(struct usb_device * dev,struct usb_interface * intf,bool reset_hardware)1341ddeac4e7SAlan Stern void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf,
1342ddeac4e7SAlan Stern bool reset_hardware)
13431da177e4SLinus Torvalds {
13441da177e4SLinus Torvalds struct usb_host_interface *alt = intf->cur_altsetting;
13451da177e4SLinus Torvalds int i;
13461da177e4SLinus Torvalds
13471da177e4SLinus Torvalds for (i = 0; i < alt->desc.bNumEndpoints; ++i) {
13481da177e4SLinus Torvalds usb_disable_endpoint(dev,
1349ddeac4e7SAlan Stern alt->endpoint[i].desc.bEndpointAddress,
1350ddeac4e7SAlan Stern reset_hardware);
13511da177e4SLinus Torvalds }
13521da177e4SLinus Torvalds }
13531da177e4SLinus Torvalds
1354cfd54fa8SMathias Nyman /*
1355cfd54fa8SMathias Nyman * usb_disable_device_endpoints -- Disable all endpoints for a device
1356cfd54fa8SMathias Nyman * @dev: the device whose endpoints are being disabled
1357cfd54fa8SMathias Nyman * @skip_ep0: 0 to disable endpoint 0, 1 to skip it.
1358cfd54fa8SMathias Nyman */
usb_disable_device_endpoints(struct usb_device * dev,int skip_ep0)1359cfd54fa8SMathias Nyman static void usb_disable_device_endpoints(struct usb_device *dev, int skip_ep0)
1360cfd54fa8SMathias Nyman {
1361cfd54fa8SMathias Nyman struct usb_hcd *hcd = bus_to_hcd(dev->bus);
1362cfd54fa8SMathias Nyman int i;
1363cfd54fa8SMathias Nyman
1364cfd54fa8SMathias Nyman if (hcd->driver->check_bandwidth) {
1365cfd54fa8SMathias Nyman /* First pass: Cancel URBs, leave endpoint pointers intact. */
1366cfd54fa8SMathias Nyman for (i = skip_ep0; i < 16; ++i) {
1367cfd54fa8SMathias Nyman usb_disable_endpoint(dev, i, false);
1368cfd54fa8SMathias Nyman usb_disable_endpoint(dev, i + USB_DIR_IN, false);
1369cfd54fa8SMathias Nyman }
1370cfd54fa8SMathias Nyman /* Remove endpoints from the host controller internal state */
1371cfd54fa8SMathias Nyman mutex_lock(hcd->bandwidth_mutex);
1372cfd54fa8SMathias Nyman usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
1373cfd54fa8SMathias Nyman mutex_unlock(hcd->bandwidth_mutex);
1374cfd54fa8SMathias Nyman }
1375cfd54fa8SMathias Nyman /* Second pass: remove endpoint pointers */
1376cfd54fa8SMathias Nyman for (i = skip_ep0; i < 16; ++i) {
1377cfd54fa8SMathias Nyman usb_disable_endpoint(dev, i, true);
1378cfd54fa8SMathias Nyman usb_disable_endpoint(dev, i + USB_DIR_IN, true);
1379cfd54fa8SMathias Nyman }
1380cfd54fa8SMathias Nyman }
1381cfd54fa8SMathias Nyman
13823e35bf39SGreg Kroah-Hartman /**
13831da177e4SLinus Torvalds * usb_disable_device - Disable all the endpoints for a USB device
13841da177e4SLinus Torvalds * @dev: the device whose endpoints are being disabled
13851da177e4SLinus Torvalds * @skip_ep0: 0 to disable endpoint 0, 1 to skip it.
13861da177e4SLinus Torvalds *
13871da177e4SLinus Torvalds * Disables all the device's endpoints, potentially including endpoint 0.
13881da177e4SLinus Torvalds * Deallocates hcd/hardware state for the endpoints (nuking all or most
13891da177e4SLinus Torvalds * pending urbs) and usbcore state for the interfaces, so that usbcore
13901da177e4SLinus Torvalds * must usb_set_configuration() before any interfaces could be used.
13911da177e4SLinus Torvalds */
usb_disable_device(struct usb_device * dev,int skip_ep0)13921da177e4SLinus Torvalds void usb_disable_device(struct usb_device *dev, int skip_ep0)
13931da177e4SLinus Torvalds {
13941da177e4SLinus Torvalds int i;
13951da177e4SLinus Torvalds
13961da177e4SLinus Torvalds /* getting rid of interfaces will disconnect
13971da177e4SLinus Torvalds * any drivers bound to them (a key side effect)
13981da177e4SLinus Torvalds */
13991da177e4SLinus Torvalds if (dev->actconfig) {
1400ca5c485fSAlan Stern /*
1401ca5c485fSAlan Stern * FIXME: In order to avoid self-deadlock involving the
1402ca5c485fSAlan Stern * bandwidth_mutex, we have to mark all the interfaces
1403ca5c485fSAlan Stern * before unregistering any of them.
1404ca5c485fSAlan Stern */
1405ca5c485fSAlan Stern for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++)
1406ca5c485fSAlan Stern dev->actconfig->interface[i]->unregistering = 1;
1407ca5c485fSAlan Stern
14081da177e4SLinus Torvalds for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
14091da177e4SLinus Torvalds struct usb_interface *interface;
14101da177e4SLinus Torvalds
141186d30741SAlan Stern /* remove this interface if it has been registered */
14121da177e4SLinus Torvalds interface = dev->actconfig->interface[i];
1413d305ef5dSDaniel Ritz if (!device_is_registered(&interface->dev))
141486d30741SAlan Stern continue;
14151da177e4SLinus Torvalds dev_dbg(&dev->dev, "unregistering interface %s\n",
14167071a3ceSKay Sievers dev_name(&interface->dev));
14173b23dd6fSAlan Stern remove_intf_ep_devs(interface);
14181a21175aSAlan Stern device_del(&interface->dev);
14191da177e4SLinus Torvalds }
14201da177e4SLinus Torvalds
14211da177e4SLinus Torvalds /* Now that the interfaces are unbound, nobody should
14221da177e4SLinus Torvalds * try to access them.
14231da177e4SLinus Torvalds */
14241da177e4SLinus Torvalds for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
14251da177e4SLinus Torvalds put_device(&dev->actconfig->interface[i]->dev);
14261da177e4SLinus Torvalds dev->actconfig->interface[i] = NULL;
14271da177e4SLinus Torvalds }
1428f468f7b9SSarah Sharp
14297529b257SKai-Heng Feng usb_disable_usb2_hardware_lpm(dev);
143024971912SSarah Sharp usb_unlocked_disable_lpm(dev);
1431f74631e3SSarah Sharp usb_disable_ltm(dev);
1432f468f7b9SSarah Sharp
14331da177e4SLinus Torvalds dev->actconfig = NULL;
14341da177e4SLinus Torvalds if (dev->state == USB_STATE_CONFIGURED)
14351da177e4SLinus Torvalds usb_set_device_state(dev, USB_STATE_ADDRESS);
14361da177e4SLinus Torvalds }
143780f0cf39SAlan Stern
143880f0cf39SAlan Stern dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
143980f0cf39SAlan Stern skip_ep0 ? "non-ep0" : "all");
1440cfd54fa8SMathias Nyman
1441cfd54fa8SMathias Nyman usb_disable_device_endpoints(dev, skip_ep0);
14421da177e4SLinus Torvalds }
14431da177e4SLinus Torvalds
14443e35bf39SGreg Kroah-Hartman /**
14451da177e4SLinus Torvalds * usb_enable_endpoint - Enable an endpoint for USB communications
14461da177e4SLinus Torvalds * @dev: the device whose interface is being enabled
14471da177e4SLinus Torvalds * @ep: the endpoint
14483444b26aSDavid Vrabel * @reset_ep: flag to reset the endpoint state
14491da177e4SLinus Torvalds *
14503444b26aSDavid Vrabel * Resets the endpoint state if asked, and sets dev->ep_{in,out} pointers.
14511da177e4SLinus Torvalds * For control endpoints, both the input and output sides are handled.
14521da177e4SLinus Torvalds */
usb_enable_endpoint(struct usb_device * dev,struct usb_host_endpoint * ep,bool reset_ep)14532caf7fcdSAlan Stern void usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep,
14543444b26aSDavid Vrabel bool reset_ep)
14551da177e4SLinus Torvalds {
1456bdd016baSAlan Stern int epnum = usb_endpoint_num(&ep->desc);
1457bdd016baSAlan Stern int is_out = usb_endpoint_dir_out(&ep->desc);
1458bdd016baSAlan Stern int is_control = usb_endpoint_xfer_control(&ep->desc);
14591da177e4SLinus Torvalds
14603444b26aSDavid Vrabel if (reset_ep)
14613444b26aSDavid Vrabel usb_hcd_reset_endpoint(dev, ep);
14623444b26aSDavid Vrabel if (is_out || is_control)
14631da177e4SLinus Torvalds dev->ep_out[epnum] = ep;
14643444b26aSDavid Vrabel if (!is_out || is_control)
14651da177e4SLinus Torvalds dev->ep_in[epnum] = ep;
1466bdd016baSAlan Stern ep->enabled = 1;
14671da177e4SLinus Torvalds }
14681da177e4SLinus Torvalds
14693e35bf39SGreg Kroah-Hartman /**
14701da177e4SLinus Torvalds * usb_enable_interface - Enable all the endpoints for an interface
14711da177e4SLinus Torvalds * @dev: the device whose interface is being enabled
14721da177e4SLinus Torvalds * @intf: pointer to the interface descriptor
14733444b26aSDavid Vrabel * @reset_eps: flag to reset the endpoints' state
14741da177e4SLinus Torvalds *
14751da177e4SLinus Torvalds * Enables all the endpoints for the interface's current altsetting.
14761da177e4SLinus Torvalds */
usb_enable_interface(struct usb_device * dev,struct usb_interface * intf,bool reset_eps)14772caf7fcdSAlan Stern void usb_enable_interface(struct usb_device *dev,
14783444b26aSDavid Vrabel struct usb_interface *intf, bool reset_eps)
14791da177e4SLinus Torvalds {
14801da177e4SLinus Torvalds struct usb_host_interface *alt = intf->cur_altsetting;
14811da177e4SLinus Torvalds int i;
14821da177e4SLinus Torvalds
14831da177e4SLinus Torvalds for (i = 0; i < alt->desc.bNumEndpoints; ++i)
14843444b26aSDavid Vrabel usb_enable_endpoint(dev, &alt->endpoint[i], reset_eps);
14851da177e4SLinus Torvalds }
14861da177e4SLinus Torvalds
14871da177e4SLinus Torvalds /**
14881da177e4SLinus Torvalds * usb_set_interface - Makes a particular alternate setting be current
14891da177e4SLinus Torvalds * @dev: the device whose interface is being updated
14901da177e4SLinus Torvalds * @interface: the interface being updated
14911da177e4SLinus Torvalds * @alternate: the setting being chosen.
149241631d36SAhmed S. Darwish *
149341631d36SAhmed S. Darwish * Context: task context, might sleep.
14941da177e4SLinus Torvalds *
14951da177e4SLinus Torvalds * This is used to enable data transfers on interfaces that may not
14961da177e4SLinus Torvalds * be enabled by default. Not all devices support such configurability.
14971da177e4SLinus Torvalds * Only the driver bound to an interface may change its setting.
14981da177e4SLinus Torvalds *
14991da177e4SLinus Torvalds * Within any given configuration, each interface may have several
15001da177e4SLinus Torvalds * alternative settings. These are often used to control levels of
15011da177e4SLinus Torvalds * bandwidth consumption. For example, the default setting for a high
15021da177e4SLinus Torvalds * speed interrupt endpoint may not send more than 64 bytes per microframe,
15031da177e4SLinus Torvalds * while interrupt transfers of up to 3KBytes per microframe are legal.
15041da177e4SLinus Torvalds * Also, isochronous endpoints may never be part of an
15051da177e4SLinus Torvalds * interface's default setting. To access such bandwidth, alternate
15061da177e4SLinus Torvalds * interface settings must be made current.
15071da177e4SLinus Torvalds *
15081da177e4SLinus Torvalds * Note that in the Linux USB subsystem, bandwidth associated with
15091da177e4SLinus Torvalds * an endpoint in a given alternate setting is not reserved until an URB
15101da177e4SLinus Torvalds * is submitted that needs that bandwidth. Some other operating systems
15111da177e4SLinus Torvalds * allocate bandwidth early, when a configuration is chosen.
15121da177e4SLinus Torvalds *
1513f9a5b4f5SMathias Nyman * xHCI reserves bandwidth and configures the alternate setting in
1514f9a5b4f5SMathias Nyman * usb_hcd_alloc_bandwidth(). If it fails the original interface altsetting
1515f9a5b4f5SMathias Nyman * may be disabled. Drivers cannot rely on any particular alternate
1516f9a5b4f5SMathias Nyman * setting being in effect after a failure.
1517f9a5b4f5SMathias Nyman *
15181da177e4SLinus Torvalds * This call is synchronous, and may not be used in an interrupt context.
15191da177e4SLinus Torvalds * Also, drivers must not change altsettings while urbs are scheduled for
15201da177e4SLinus Torvalds * endpoints in that interface; all such urbs must first be completed
1521*9f2a3933SMichal Pecio * (perhaps forced by unlinking). If a thread in your driver uses this call,
1522*9f2a3933SMichal Pecio * make sure your disconnect() method can wait for it to complete.
15231da177e4SLinus Torvalds *
1524626f090cSYacine Belkadi * Return: Zero on success, or else the status code returned by the
15251da177e4SLinus Torvalds * underlying usb_control_msg() call.
15261da177e4SLinus Torvalds */
usb_set_interface(struct usb_device * dev,int interface,int alternate)15271da177e4SLinus Torvalds int usb_set_interface(struct usb_device *dev, int interface, int alternate)
15281da177e4SLinus Torvalds {
15291da177e4SLinus Torvalds struct usb_interface *iface;
15301da177e4SLinus Torvalds struct usb_host_interface *alt;
15313f0479e0SSarah Sharp struct usb_hcd *hcd = bus_to_hcd(dev->bus);
15327a7b562dSHans de Goede int i, ret, manual = 0;
15333e35bf39SGreg Kroah-Hartman unsigned int epaddr;
15343e35bf39SGreg Kroah-Hartman unsigned int pipe;
15351da177e4SLinus Torvalds
15361da177e4SLinus Torvalds if (dev->state == USB_STATE_SUSPENDED)
15371da177e4SLinus Torvalds return -EHOSTUNREACH;
15381da177e4SLinus Torvalds
15391da177e4SLinus Torvalds iface = usb_ifnum_to_if(dev, interface);
15401da177e4SLinus Torvalds if (!iface) {
15411da177e4SLinus Torvalds dev_dbg(&dev->dev, "selecting invalid interface %d\n",
15421da177e4SLinus Torvalds interface);
15431da177e4SLinus Torvalds return -EINVAL;
15441da177e4SLinus Torvalds }
1545e534c5b8SAlan Stern if (iface->unregistering)
1546e534c5b8SAlan Stern return -ENODEV;
15471da177e4SLinus Torvalds
15481da177e4SLinus Torvalds alt = usb_altnum_to_altsetting(iface, alternate);
15491da177e4SLinus Torvalds if (!alt) {
1550385f690bSThadeu Lima de Souza Cascardo dev_warn(&dev->dev, "selecting invalid altsetting %d\n",
15513b6004f3SGreg Kroah-Hartman alternate);
15521da177e4SLinus Torvalds return -EINVAL;
15531da177e4SLinus Torvalds }
1554f9a5b4f5SMathias Nyman /*
1555f9a5b4f5SMathias Nyman * usb3 hosts configure the interface in usb_hcd_alloc_bandwidth,
1556f9a5b4f5SMathias Nyman * including freeing dropped endpoint ring buffers.
1557f9a5b4f5SMathias Nyman * Make sure the interface endpoints are flushed before that
1558f9a5b4f5SMathias Nyman */
1559f9a5b4f5SMathias Nyman usb_disable_interface(dev, iface, false);
15601da177e4SLinus Torvalds
15613f0479e0SSarah Sharp /* Make sure we have enough bandwidth for this alternate interface.
15623f0479e0SSarah Sharp * Remove the current alt setting and add the new alt setting.
15633f0479e0SSarah Sharp */
1564d673bfcbSSarah Sharp mutex_lock(hcd->bandwidth_mutex);
15658306095fSSarah Sharp /* Disable LPM, and re-enable it once the new alt setting is installed,
15668306095fSSarah Sharp * so that the xHCI driver can recalculate the U1/U2 timeouts.
15678306095fSSarah Sharp */
15688306095fSSarah Sharp if (usb_disable_lpm(dev)) {
15691ccc417eSJoe Perches dev_err(&iface->dev, "%s Failed to disable LPM\n", __func__);
15708306095fSSarah Sharp mutex_unlock(hcd->bandwidth_mutex);
15718306095fSSarah Sharp return -ENOMEM;
15728306095fSSarah Sharp }
15737a7b562dSHans de Goede /* Changing alt-setting also frees any allocated streams */
15747a7b562dSHans de Goede for (i = 0; i < iface->cur_altsetting->desc.bNumEndpoints; i++)
15757a7b562dSHans de Goede iface->cur_altsetting->endpoint[i].streams = 0;
15767a7b562dSHans de Goede
15773f0479e0SSarah Sharp ret = usb_hcd_alloc_bandwidth(dev, NULL, iface->cur_altsetting, alt);
15783f0479e0SSarah Sharp if (ret < 0) {
15793f0479e0SSarah Sharp dev_info(&dev->dev, "Not enough bandwidth for altsetting %d\n",
15803f0479e0SSarah Sharp alternate);
15818306095fSSarah Sharp usb_enable_lpm(dev);
1582d673bfcbSSarah Sharp mutex_unlock(hcd->bandwidth_mutex);
15833f0479e0SSarah Sharp return ret;
15843f0479e0SSarah Sharp }
15853f0479e0SSarah Sharp
1586392e1d98SAlan Stern if (dev->quirks & USB_QUIRK_NO_SET_INTF)
1587392e1d98SAlan Stern ret = -EPIPE;
1588392e1d98SAlan Stern else
1589297e84c0SGreg Kroah-Hartman ret = usb_control_msg_send(dev, 0,
1590297e84c0SGreg Kroah-Hartman USB_REQ_SET_INTERFACE,
1591297e84c0SGreg Kroah-Hartman USB_RECIP_INTERFACE, alternate,
1592ddd1198eSOliver Neukum interface, NULL, 0, 5000,
1593ddd1198eSOliver Neukum GFP_NOIO);
15941da177e4SLinus Torvalds
15951da177e4SLinus Torvalds /* 9.4.10 says devices don't need this and are free to STALL the
15961da177e4SLinus Torvalds * request if the interface only has one alternate setting.
15971da177e4SLinus Torvalds */
15981da177e4SLinus Torvalds if (ret == -EPIPE && iface->num_altsetting == 1) {
15991da177e4SLinus Torvalds dev_dbg(&dev->dev,
16001da177e4SLinus Torvalds "manual set_interface for iface %d, alt %d\n",
16011da177e4SLinus Torvalds interface, alternate);
16021da177e4SLinus Torvalds manual = 1;
1603297e84c0SGreg Kroah-Hartman } else if (ret) {
16043f0479e0SSarah Sharp /* Re-instate the old alt setting */
16053f0479e0SSarah Sharp usb_hcd_alloc_bandwidth(dev, NULL, alt, iface->cur_altsetting);
16068306095fSSarah Sharp usb_enable_lpm(dev);
1607d673bfcbSSarah Sharp mutex_unlock(hcd->bandwidth_mutex);
16081da177e4SLinus Torvalds return ret;
16093f0479e0SSarah Sharp }
1610d673bfcbSSarah Sharp mutex_unlock(hcd->bandwidth_mutex);
16111da177e4SLinus Torvalds
16121da177e4SLinus Torvalds /* FIXME drivers shouldn't need to replicate/bugfix the logic here
16131da177e4SLinus Torvalds * when they implement async or easily-killable versions of this or
16141da177e4SLinus Torvalds * other "should-be-internal" functions (like clear_halt).
16151da177e4SLinus Torvalds * should hcd+usbcore postprocess control requests?
16161da177e4SLinus Torvalds */
16171da177e4SLinus Torvalds
16181da177e4SLinus Torvalds /* prevent submissions using previous endpoint settings */
16193b23dd6fSAlan Stern if (iface->cur_altsetting != alt) {
16203b23dd6fSAlan Stern remove_intf_ep_devs(iface);
16210e6c8e8dSAlan Stern usb_remove_sysfs_intf_files(iface);
16223b23dd6fSAlan Stern }
1623ddeac4e7SAlan Stern usb_disable_interface(dev, iface, true);
16241da177e4SLinus Torvalds
16251da177e4SLinus Torvalds iface->cur_altsetting = alt;
16261da177e4SLinus Torvalds
16278306095fSSarah Sharp /* Now that the interface is installed, re-enable LPM. */
16288306095fSSarah Sharp usb_unlocked_enable_lpm(dev);
16298306095fSSarah Sharp
16301da177e4SLinus Torvalds /* If the interface only has one altsetting and the device didn't
1631a81e7eccSDavid Brownell * accept the request, we attempt to carry out the equivalent action
16321da177e4SLinus Torvalds * by manually clearing the HALT feature for each endpoint in the
16331da177e4SLinus Torvalds * new altsetting.
16341da177e4SLinus Torvalds */
16351da177e4SLinus Torvalds if (manual) {
16361da177e4SLinus Torvalds for (i = 0; i < alt->desc.bNumEndpoints; i++) {
16373e35bf39SGreg Kroah-Hartman epaddr = alt->endpoint[i].desc.bEndpointAddress;
16383e35bf39SGreg Kroah-Hartman pipe = __create_pipe(dev,
16393e35bf39SGreg Kroah-Hartman USB_ENDPOINT_NUMBER_MASK & epaddr) |
16403e35bf39SGreg Kroah-Hartman (usb_endpoint_out(epaddr) ?
16413e35bf39SGreg Kroah-Hartman USB_DIR_OUT : USB_DIR_IN);
16421da177e4SLinus Torvalds
16431da177e4SLinus Torvalds usb_clear_halt(dev, pipe);
16441da177e4SLinus Torvalds }
16451da177e4SLinus Torvalds }
16461da177e4SLinus Torvalds
16471da177e4SLinus Torvalds /* 9.1.1.5: reset toggles for all endpoints in the new altsetting
16481da177e4SLinus Torvalds *
16491da177e4SLinus Torvalds * Note:
16501da177e4SLinus Torvalds * Despite EP0 is always present in all interfaces/AS, the list of
16511da177e4SLinus Torvalds * endpoints from the descriptor does not contain EP0. Due to its
16521da177e4SLinus Torvalds * omnipresence one might expect EP0 being considered "affected" by
16531da177e4SLinus Torvalds * any SetInterface request and hence assume toggles need to be reset.
16541da177e4SLinus Torvalds * However, EP0 toggles are re-synced for every individual transfer
16551da177e4SLinus Torvalds * during the SETUP stage - hence EP0 toggles are "don't care" here.
16561da177e4SLinus Torvalds * (Likewise, EP0 never "halts" on well designed devices.)
16571da177e4SLinus Torvalds */
16582caf7fcdSAlan Stern usb_enable_interface(dev, iface, true);
16593b23dd6fSAlan Stern if (device_is_registered(&iface->dev)) {
16600e6c8e8dSAlan Stern usb_create_sysfs_intf_files(iface);
16613b23dd6fSAlan Stern create_intf_ep_devs(iface);
16623b23dd6fSAlan Stern }
16631da177e4SLinus Torvalds return 0;
16641da177e4SLinus Torvalds }
1665782e70c6SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(usb_set_interface);
16661da177e4SLinus Torvalds
16671da177e4SLinus Torvalds /**
16681da177e4SLinus Torvalds * usb_reset_configuration - lightweight device reset
16691da177e4SLinus Torvalds * @dev: the device whose configuration is being reset
16701da177e4SLinus Torvalds *
16711da177e4SLinus Torvalds * This issues a standard SET_CONFIGURATION request to the device using
16721da177e4SLinus Torvalds * the current configuration. The effect is to reset most USB-related
16731da177e4SLinus Torvalds * state in the device, including interface altsettings (reset to zero),
16743444b26aSDavid Vrabel * endpoint halts (cleared), and endpoint state (only for bulk and interrupt
16751da177e4SLinus Torvalds * endpoints). Other usbcore state is unchanged, including bindings of
16761da177e4SLinus Torvalds * usb device drivers to interfaces.
16771da177e4SLinus Torvalds *
16781da177e4SLinus Torvalds * Because this affects multiple interfaces, avoid using this with composite
16791da177e4SLinus Torvalds * (multi-interface) devices. Instead, the driver for each interface may
1680a81e7eccSDavid Brownell * use usb_set_interface() on the interfaces it claims. Be careful though;
1681a81e7eccSDavid Brownell * some devices don't support the SET_INTERFACE request, and others won't
16823444b26aSDavid Vrabel * reset all the interface state (notably endpoint state). Resetting the whole
16831da177e4SLinus Torvalds * configuration would affect other drivers' interfaces.
16841da177e4SLinus Torvalds *
16851da177e4SLinus Torvalds * The caller must own the device lock.
16861da177e4SLinus Torvalds *
1687626f090cSYacine Belkadi * Return: Zero on success, else a negative error code.
1688cfd54fa8SMathias Nyman *
1689cfd54fa8SMathias Nyman * If this routine fails the device will probably be in an unusable state
1690cfd54fa8SMathias Nyman * with endpoints disabled, and interfaces only partially enabled.
16911da177e4SLinus Torvalds */
usb_reset_configuration(struct usb_device * dev)16921da177e4SLinus Torvalds int usb_reset_configuration(struct usb_device *dev)
16931da177e4SLinus Torvalds {
16941da177e4SLinus Torvalds int i, retval;
16951da177e4SLinus Torvalds struct usb_host_config *config;
16963f0479e0SSarah Sharp struct usb_hcd *hcd = bus_to_hcd(dev->bus);
16971da177e4SLinus Torvalds
16981da177e4SLinus Torvalds if (dev->state == USB_STATE_SUSPENDED)
16991da177e4SLinus Torvalds return -EHOSTUNREACH;
17001da177e4SLinus Torvalds
17011da177e4SLinus Torvalds /* caller must have locked the device and must own
17021da177e4SLinus Torvalds * the usb bus readlock (so driver bindings are stable);
17031da177e4SLinus Torvalds * calls during probe() are fine
17041da177e4SLinus Torvalds */
17051da177e4SLinus Torvalds
1706cfd54fa8SMathias Nyman usb_disable_device_endpoints(dev, 1); /* skip ep0*/
17071da177e4SLinus Torvalds
17081da177e4SLinus Torvalds config = dev->actconfig;
17093f0479e0SSarah Sharp retval = 0;
1710d673bfcbSSarah Sharp mutex_lock(hcd->bandwidth_mutex);
17118306095fSSarah Sharp /* Disable LPM, and re-enable it once the configuration is reset, so
17128306095fSSarah Sharp * that the xHCI driver can recalculate the U1/U2 timeouts.
17138306095fSSarah Sharp */
17148306095fSSarah Sharp if (usb_disable_lpm(dev)) {
17151ccc417eSJoe Perches dev_err(&dev->dev, "%s Failed to disable LPM\n", __func__);
17168306095fSSarah Sharp mutex_unlock(hcd->bandwidth_mutex);
17178306095fSSarah Sharp return -ENOMEM;
17188306095fSSarah Sharp }
17193f0479e0SSarah Sharp
1720cfd54fa8SMathias Nyman /* xHCI adds all endpoints in usb_hcd_alloc_bandwidth */
1721cfd54fa8SMathias Nyman retval = usb_hcd_alloc_bandwidth(dev, config, NULL, NULL);
17223f0479e0SSarah Sharp if (retval < 0) {
17238306095fSSarah Sharp usb_enable_lpm(dev);
1724d673bfcbSSarah Sharp mutex_unlock(hcd->bandwidth_mutex);
17253f0479e0SSarah Sharp return retval;
17263f0479e0SSarah Sharp }
1727297e84c0SGreg Kroah-Hartman retval = usb_control_msg_send(dev, 0, USB_REQ_SET_CONFIGURATION, 0,
17281da177e4SLinus Torvalds config->desc.bConfigurationValue, 0,
1729ddd1198eSOliver Neukum NULL, 0, USB_CTRL_SET_TIMEOUT,
1730ddd1198eSOliver Neukum GFP_NOIO);
1731297e84c0SGreg Kroah-Hartman if (retval) {
1732cfd54fa8SMathias Nyman usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
1733cfd54fa8SMathias Nyman usb_enable_lpm(dev);
1734cfd54fa8SMathias Nyman mutex_unlock(hcd->bandwidth_mutex);
1735cfd54fa8SMathias Nyman return retval;
1736cfd54fa8SMathias Nyman }
1737d673bfcbSSarah Sharp mutex_unlock(hcd->bandwidth_mutex);
17381da177e4SLinus Torvalds
17391da177e4SLinus Torvalds /* re-init hc/hcd interface/endpoint state */
17401da177e4SLinus Torvalds for (i = 0; i < config->desc.bNumInterfaces; i++) {
17411da177e4SLinus Torvalds struct usb_interface *intf = config->interface[i];
17421da177e4SLinus Torvalds struct usb_host_interface *alt;
17431da177e4SLinus Torvalds
17441da177e4SLinus Torvalds alt = usb_altnum_to_altsetting(intf, 0);
17451da177e4SLinus Torvalds
17461da177e4SLinus Torvalds /* No altsetting 0? We'll assume the first altsetting.
17471da177e4SLinus Torvalds * We could use a GetInterface call, but if a device is
17481da177e4SLinus Torvalds * so non-compliant that it doesn't have altsetting 0
17491da177e4SLinus Torvalds * then I wouldn't trust its reply anyway.
17501da177e4SLinus Torvalds */
17511da177e4SLinus Torvalds if (!alt)
17521da177e4SLinus Torvalds alt = &intf->altsetting[0];
17531da177e4SLinus Torvalds
17543b23dd6fSAlan Stern if (alt != intf->cur_altsetting) {
17553b23dd6fSAlan Stern remove_intf_ep_devs(intf);
17563b23dd6fSAlan Stern usb_remove_sysfs_intf_files(intf);
17573b23dd6fSAlan Stern }
17581da177e4SLinus Torvalds intf->cur_altsetting = alt;
17592caf7fcdSAlan Stern usb_enable_interface(dev, intf, true);
17603b23dd6fSAlan Stern if (device_is_registered(&intf->dev)) {
17610e6c8e8dSAlan Stern usb_create_sysfs_intf_files(intf);
17623b23dd6fSAlan Stern create_intf_ep_devs(intf);
17633b23dd6fSAlan Stern }
17641da177e4SLinus Torvalds }
17658306095fSSarah Sharp /* Now that the interfaces are installed, re-enable LPM. */
17668306095fSSarah Sharp usb_unlocked_enable_lpm(dev);
17671da177e4SLinus Torvalds return 0;
17681da177e4SLinus Torvalds }
1769782e70c6SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(usb_reset_configuration);
17701da177e4SLinus Torvalds
usb_release_interface(struct device * dev)1771b0e396e3SGreg Kroah-Hartman static void usb_release_interface(struct device *dev)
17721da177e4SLinus Torvalds {
17731da177e4SLinus Torvalds struct usb_interface *intf = to_usb_interface(dev);
17741da177e4SLinus Torvalds struct usb_interface_cache *intfc =
17751da177e4SLinus Torvalds altsetting_to_usb_interface_cache(intf->altsetting);
17761da177e4SLinus Torvalds
17771da177e4SLinus Torvalds kref_put(&intfc->ref, usb_release_interface_cache);
1778524134d4SAlan Stern usb_put_dev(interface_to_usbdev(intf));
17791a7e3948SJohan Hovold of_node_put(dev->of_node);
17801da177e4SLinus Torvalds kfree(intf);
17811da177e4SLinus Torvalds }
17821da177e4SLinus Torvalds
1783b3910cefSStefan Koch /*
1784b3910cefSStefan Koch * usb_deauthorize_interface - deauthorize an USB interface
1785b3910cefSStefan Koch *
1786b3910cefSStefan Koch * @intf: USB interface structure
1787b3910cefSStefan Koch */
usb_deauthorize_interface(struct usb_interface * intf)1788b3910cefSStefan Koch void usb_deauthorize_interface(struct usb_interface *intf)
1789b3910cefSStefan Koch {
1790b3910cefSStefan Koch struct device *dev = &intf->dev;
1791b3910cefSStefan Koch
1792b3910cefSStefan Koch device_lock(dev->parent);
1793b3910cefSStefan Koch
1794b3910cefSStefan Koch if (intf->authorized) {
1795b3910cefSStefan Koch device_lock(dev);
1796b3910cefSStefan Koch intf->authorized = 0;
1797b3910cefSStefan Koch device_unlock(dev);
1798b3910cefSStefan Koch
1799b3910cefSStefan Koch usb_forced_unbind_intf(intf);
1800b3910cefSStefan Koch }
1801b3910cefSStefan Koch
1802b3910cefSStefan Koch device_unlock(dev->parent);
1803b3910cefSStefan Koch }
1804b3910cefSStefan Koch
1805b3910cefSStefan Koch /*
1806b3910cefSStefan Koch * usb_authorize_interface - authorize an USB interface
1807b3910cefSStefan Koch *
1808b3910cefSStefan Koch * @intf: USB interface structure
1809b3910cefSStefan Koch */
usb_authorize_interface(struct usb_interface * intf)1810b3910cefSStefan Koch void usb_authorize_interface(struct usb_interface *intf)
1811b3910cefSStefan Koch {
1812b3910cefSStefan Koch struct device *dev = &intf->dev;
1813b3910cefSStefan Koch
1814b3910cefSStefan Koch if (!intf->authorized) {
1815b3910cefSStefan Koch device_lock(dev);
1816b3910cefSStefan Koch intf->authorized = 1; /* authorize interface */
1817b3910cefSStefan Koch device_unlock(dev);
1818b3910cefSStefan Koch }
1819b3910cefSStefan Koch }
1820b3910cefSStefan Koch
usb_if_uevent(const struct device * dev,struct kobj_uevent_env * env)1821162736b0SGreg Kroah-Hartman static int usb_if_uevent(const struct device *dev, struct kobj_uevent_env *env)
18229f8b17e6SKay Sievers {
1823162736b0SGreg Kroah-Hartman const struct usb_device *usb_dev;
1824162736b0SGreg Kroah-Hartman const struct usb_interface *intf;
1825162736b0SGreg Kroah-Hartman const struct usb_host_interface *alt;
18269f8b17e6SKay Sievers
18279f8b17e6SKay Sievers intf = to_usb_interface(dev);
18289f8b17e6SKay Sievers usb_dev = interface_to_usbdev(intf);
18299f8b17e6SKay Sievers alt = intf->cur_altsetting;
18309f8b17e6SKay Sievers
18317eff2e7aSKay Sievers if (add_uevent_var(env, "INTERFACE=%d/%d/%d",
18329f8b17e6SKay Sievers alt->desc.bInterfaceClass,
18339f8b17e6SKay Sievers alt->desc.bInterfaceSubClass,
18349f8b17e6SKay Sievers alt->desc.bInterfaceProtocol))
18359f8b17e6SKay Sievers return -ENOMEM;
18369f8b17e6SKay Sievers
18377eff2e7aSKay Sievers if (add_uevent_var(env,
18383e35bf39SGreg Kroah-Hartman "MODALIAS=usb:"
183981df2d59SBjørn Mork "v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02Xin%02X",
18409f8b17e6SKay Sievers le16_to_cpu(usb_dev->descriptor.idVendor),
18419f8b17e6SKay Sievers le16_to_cpu(usb_dev->descriptor.idProduct),
18429f8b17e6SKay Sievers le16_to_cpu(usb_dev->descriptor.bcdDevice),
18439f8b17e6SKay Sievers usb_dev->descriptor.bDeviceClass,
18449f8b17e6SKay Sievers usb_dev->descriptor.bDeviceSubClass,
18459f8b17e6SKay Sievers usb_dev->descriptor.bDeviceProtocol,
18469f8b17e6SKay Sievers alt->desc.bInterfaceClass,
18479f8b17e6SKay Sievers alt->desc.bInterfaceSubClass,
184881df2d59SBjørn Mork alt->desc.bInterfaceProtocol,
184981df2d59SBjørn Mork alt->desc.bInterfaceNumber))
18509f8b17e6SKay Sievers return -ENOMEM;
18519f8b17e6SKay Sievers
18529f8b17e6SKay Sievers return 0;
18539f8b17e6SKay Sievers }
18549f8b17e6SKay Sievers
18551ab40abcSRicardo B. Marliere const struct device_type usb_if_device_type = {
18569f8b17e6SKay Sievers .name = "usb_interface",
18579f8b17e6SKay Sievers .release = usb_release_interface,
18589f8b17e6SKay Sievers .uevent = usb_if_uevent,
18599f8b17e6SKay Sievers };
18609f8b17e6SKay Sievers
find_iad(struct usb_device * dev,struct usb_host_config * config,u8 inum)1861165fe97eSCraig W. Nadler static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
1862165fe97eSCraig W. Nadler struct usb_host_config *config,
1863165fe97eSCraig W. Nadler u8 inum)
1864165fe97eSCraig W. Nadler {
1865165fe97eSCraig W. Nadler struct usb_interface_assoc_descriptor *retval = NULL;
1866165fe97eSCraig W. Nadler struct usb_interface_assoc_descriptor *intf_assoc;
1867165fe97eSCraig W. Nadler int first_intf;
1868165fe97eSCraig W. Nadler int last_intf;
1869165fe97eSCraig W. Nadler int i;
1870165fe97eSCraig W. Nadler
1871165fe97eSCraig W. Nadler for (i = 0; (i < USB_MAXIADS && config->intf_assoc[i]); i++) {
1872165fe97eSCraig W. Nadler intf_assoc = config->intf_assoc[i];
1873165fe97eSCraig W. Nadler if (intf_assoc->bInterfaceCount == 0)
1874165fe97eSCraig W. Nadler continue;
1875165fe97eSCraig W. Nadler
1876165fe97eSCraig W. Nadler first_intf = intf_assoc->bFirstInterface;
1877165fe97eSCraig W. Nadler last_intf = first_intf + (intf_assoc->bInterfaceCount - 1);
1878165fe97eSCraig W. Nadler if (inum >= first_intf && inum <= last_intf) {
1879165fe97eSCraig W. Nadler if (!retval)
1880165fe97eSCraig W. Nadler retval = intf_assoc;
1881165fe97eSCraig W. Nadler else
1882165fe97eSCraig W. Nadler dev_err(&dev->dev, "Interface #%d referenced"
1883165fe97eSCraig W. Nadler " by multiple IADs\n", inum);
1884165fe97eSCraig W. Nadler }
1885165fe97eSCraig W. Nadler }
1886165fe97eSCraig W. Nadler
1887165fe97eSCraig W. Nadler return retval;
1888165fe97eSCraig W. Nadler }
1889165fe97eSCraig W. Nadler
1890dc023dceSInaky Perez-Gonzalez
1891dc023dceSInaky Perez-Gonzalez /*
1892dc023dceSInaky Perez-Gonzalez * Internal function to queue a device reset
1893dc023dceSInaky Perez-Gonzalez * See usb_queue_reset_device() for more details
1894dc023dceSInaky Perez-Gonzalez */
__usb_queue_reset_device(struct work_struct * ws)189509e81f3dSFelipe Balbi static void __usb_queue_reset_device(struct work_struct *ws)
1896dc023dceSInaky Perez-Gonzalez {
1897dc023dceSInaky Perez-Gonzalez int rc;
1898dc023dceSInaky Perez-Gonzalez struct usb_interface *iface =
1899dc023dceSInaky Perez-Gonzalez container_of(ws, struct usb_interface, reset_ws);
1900dc023dceSInaky Perez-Gonzalez struct usb_device *udev = interface_to_usbdev(iface);
1901dc023dceSInaky Perez-Gonzalez
1902dc023dceSInaky Perez-Gonzalez rc = usb_lock_device_for_reset(udev, iface);
1903dc023dceSInaky Perez-Gonzalez if (rc >= 0) {
1904dc023dceSInaky Perez-Gonzalez usb_reset_device(udev);
1905dc023dceSInaky Perez-Gonzalez usb_unlock_device(udev);
1906dc023dceSInaky Perez-Gonzalez }
1907524134d4SAlan Stern usb_put_intf(iface); /* Undo _get_ in usb_queue_reset_device() */
1908dc023dceSInaky Perez-Gonzalez }
1909dc023dceSInaky Perez-Gonzalez
19100a4db185SBastien Nocera /*
19110a4db185SBastien Nocera * Internal function to set the wireless_status sysfs attribute
19120a4db185SBastien Nocera * See usb_set_wireless_status() for more details
19130a4db185SBastien Nocera */
__usb_wireless_status_intf(struct work_struct * ws)19140a4db185SBastien Nocera static void __usb_wireless_status_intf(struct work_struct *ws)
19150a4db185SBastien Nocera {
19160a4db185SBastien Nocera struct usb_interface *iface =
19170a4db185SBastien Nocera container_of(ws, struct usb_interface, wireless_status_work);
19180a4db185SBastien Nocera
19190a4db185SBastien Nocera device_lock(iface->dev.parent);
19200a4db185SBastien Nocera if (iface->sysfs_files_created)
19210a4db185SBastien Nocera usb_update_wireless_status_attr(iface);
19220a4db185SBastien Nocera device_unlock(iface->dev.parent);
19230a4db185SBastien Nocera usb_put_intf(iface); /* Undo _get_ in usb_set_wireless_status() */
19240a4db185SBastien Nocera }
19250a4db185SBastien Nocera
19260a4db185SBastien Nocera /**
19270a4db185SBastien Nocera * usb_set_wireless_status - sets the wireless_status struct member
1928539adfedSBastien Nocera * @iface: the interface to modify
19290a4db185SBastien Nocera * @status: the new wireless status
19300a4db185SBastien Nocera *
19310a4db185SBastien Nocera * Set the wireless_status struct member to the new value, and emit
19320a4db185SBastien Nocera * sysfs changes as necessary.
19330a4db185SBastien Nocera *
19340a4db185SBastien Nocera * Returns: 0 on success, -EALREADY if already set.
19350a4db185SBastien Nocera */
usb_set_wireless_status(struct usb_interface * iface,enum usb_wireless_status status)19360a4db185SBastien Nocera int usb_set_wireless_status(struct usb_interface *iface,
19370a4db185SBastien Nocera enum usb_wireless_status status)
19380a4db185SBastien Nocera {
19390a4db185SBastien Nocera if (iface->wireless_status == status)
19400a4db185SBastien Nocera return -EALREADY;
19410a4db185SBastien Nocera
19420a4db185SBastien Nocera usb_get_intf(iface);
19430a4db185SBastien Nocera iface->wireless_status = status;
19440a4db185SBastien Nocera schedule_work(&iface->wireless_status_work);
19450a4db185SBastien Nocera
19460a4db185SBastien Nocera return 0;
19470a4db185SBastien Nocera }
19480a4db185SBastien Nocera EXPORT_SYMBOL_GPL(usb_set_wireless_status);
1949dc023dceSInaky Perez-Gonzalez
19501da177e4SLinus Torvalds /*
19511da177e4SLinus Torvalds * usb_set_configuration - Makes a particular device setting be current
19521da177e4SLinus Torvalds * @dev: the device whose configuration is being updated
19531da177e4SLinus Torvalds * @configuration: the configuration being chosen.
195441631d36SAhmed S. Darwish *
195541631d36SAhmed S. Darwish * Context: task context, might sleep. Caller holds device lock.
19561da177e4SLinus Torvalds *
19571da177e4SLinus Torvalds * This is used to enable non-default device modes. Not all devices
19581da177e4SLinus Torvalds * use this kind of configurability; many devices only have one
19591da177e4SLinus Torvalds * configuration.
19601da177e4SLinus Torvalds *
19613f141e2aSAlan Stern * @configuration is the value of the configuration to be installed.
19623f141e2aSAlan Stern * According to the USB spec (e.g. section 9.1.1.5), configuration values
19633f141e2aSAlan Stern * must be non-zero; a value of zero indicates that the device in
19643f141e2aSAlan Stern * unconfigured. However some devices erroneously use 0 as one of their
19653f141e2aSAlan Stern * configuration values. To help manage such devices, this routine will
19663f141e2aSAlan Stern * accept @configuration = -1 as indicating the device should be put in
19673f141e2aSAlan Stern * an unconfigured state.
19683f141e2aSAlan Stern *
19691da177e4SLinus Torvalds * USB device configurations may affect Linux interoperability,
19701da177e4SLinus Torvalds * power consumption and the functionality available. For example,
19711da177e4SLinus Torvalds * the default configuration is limited to using 100mA of bus power,
19721da177e4SLinus Torvalds * so that when certain device functionality requires more power,
19731da177e4SLinus Torvalds * and the device is bus powered, that functionality should be in some
19741da177e4SLinus Torvalds * non-default device configuration. Other device modes may also be
19751da177e4SLinus Torvalds * reflected as configuration options, such as whether two ISDN
19761da177e4SLinus Torvalds * channels are available independently; and choosing between open
19771da177e4SLinus Torvalds * standard device protocols (like CDC) or proprietary ones.
19781da177e4SLinus Torvalds *
197916bbab29SInaky Perez-Gonzalez * Note that a non-authorized device (dev->authorized == 0) will only
198016bbab29SInaky Perez-Gonzalez * be put in unconfigured mode.
198116bbab29SInaky Perez-Gonzalez *
19821da177e4SLinus Torvalds * Note that USB has an additional level of device configurability,
19831da177e4SLinus Torvalds * associated with interfaces. That configurability is accessed using
19841da177e4SLinus Torvalds * usb_set_interface().
19851da177e4SLinus Torvalds *
19861da177e4SLinus Torvalds * This call is synchronous. The calling context must be able to sleep,
19871da177e4SLinus Torvalds * must own the device lock, and must not hold the driver model's USB
19886d243e5cSMing Lei * bus mutex; usb interface driver probe() methods cannot use this routine.
19891da177e4SLinus Torvalds *
19901da177e4SLinus Torvalds * Returns zero on success, or else the status code returned by the
1991093cf723SSteven Cole * underlying call that failed. On successful completion, each interface
19921da177e4SLinus Torvalds * in the original device configuration has been destroyed, and each one
19931da177e4SLinus Torvalds * in the new configuration has been probed by all relevant usb device
19941da177e4SLinus Torvalds * drivers currently known to the kernel.
19951da177e4SLinus Torvalds */
usb_set_configuration(struct usb_device * dev,int configuration)19961da177e4SLinus Torvalds int usb_set_configuration(struct usb_device *dev, int configuration)
19971da177e4SLinus Torvalds {
19981da177e4SLinus Torvalds int i, ret;
19991da177e4SLinus Torvalds struct usb_host_config *cp = NULL;
20001da177e4SLinus Torvalds struct usb_interface **new_interfaces = NULL;
20013f0479e0SSarah Sharp struct usb_hcd *hcd = bus_to_hcd(dev->bus);
20021da177e4SLinus Torvalds int n, nintf;
20031da177e4SLinus Torvalds
200416bbab29SInaky Perez-Gonzalez if (dev->authorized == 0 || configuration == -1)
20053f141e2aSAlan Stern configuration = 0;
20063f141e2aSAlan Stern else {
20071da177e4SLinus Torvalds for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
20083f141e2aSAlan Stern if (dev->config[i].desc.bConfigurationValue ==
20093f141e2aSAlan Stern configuration) {
20101da177e4SLinus Torvalds cp = &dev->config[i];
20111da177e4SLinus Torvalds break;
20121da177e4SLinus Torvalds }
20131da177e4SLinus Torvalds }
20143f141e2aSAlan Stern }
20151da177e4SLinus Torvalds if ((!cp && configuration != 0))
20161da177e4SLinus Torvalds return -EINVAL;
20171da177e4SLinus Torvalds
20181da177e4SLinus Torvalds /* The USB spec says configuration 0 means unconfigured.
20191da177e4SLinus Torvalds * But if a device includes a configuration numbered 0,
20201da177e4SLinus Torvalds * we will accept it as a correctly configured state.
20213f141e2aSAlan Stern * Use -1 if you really want to unconfigure the device.
20221da177e4SLinus Torvalds */
20231da177e4SLinus Torvalds if (cp && configuration == 0)
20241da177e4SLinus Torvalds dev_warn(&dev->dev, "config 0 descriptor??\n");
20251da177e4SLinus Torvalds
20261da177e4SLinus Torvalds /* Allocate memory for new interfaces before doing anything else,
20271da177e4SLinus Torvalds * so that if we run out then nothing will have changed. */
20281da177e4SLinus Torvalds n = nintf = 0;
20291da177e4SLinus Torvalds if (cp) {
20301da177e4SLinus Torvalds nintf = cp->desc.bNumInterfaces;
20316da2ec56SKees Cook new_interfaces = kmalloc_array(nintf, sizeof(*new_interfaces),
2032acbe2febSOliver Neukum GFP_NOIO);
203393fab795SWolfram Sang if (!new_interfaces)
20341da177e4SLinus Torvalds return -ENOMEM;
20351da177e4SLinus Torvalds
20361da177e4SLinus Torvalds for (; n < nintf; ++n) {
20370a1ef3b5SAlan Stern new_interfaces[n] = kzalloc(
20381da177e4SLinus Torvalds sizeof(struct usb_interface),
2039acbe2febSOliver Neukum GFP_NOIO);
20401da177e4SLinus Torvalds if (!new_interfaces[n]) {
20411da177e4SLinus Torvalds ret = -ENOMEM;
20421da177e4SLinus Torvalds free_interfaces:
20431da177e4SLinus Torvalds while (--n >= 0)
20441da177e4SLinus Torvalds kfree(new_interfaces[n]);
20451da177e4SLinus Torvalds kfree(new_interfaces);
20461da177e4SLinus Torvalds return ret;
20471da177e4SLinus Torvalds }
20481da177e4SLinus Torvalds }
20496ad07129SAlan Stern
20508d8479dbSSebastian Andrzej Siewior i = dev->bus_mA - usb_get_max_power(dev, cp);
20516ad07129SAlan Stern if (i < 0)
20526ad07129SAlan Stern dev_warn(&dev->dev, "new config #%d exceeds power "
20536ad07129SAlan Stern "limit by %dmA\n",
20546ad07129SAlan Stern configuration, -i);
20551da177e4SLinus Torvalds }
20561da177e4SLinus Torvalds
205701d883d4SAlan Stern /* Wake up the device so we can send it the Set-Config request */
205894fcda1fSAlan Stern ret = usb_autoresume_device(dev);
205901d883d4SAlan Stern if (ret)
206001d883d4SAlan Stern goto free_interfaces;
206101d883d4SAlan Stern
20620791971bSThadeu Lima de Souza Cascardo /* if it's already configured, clear out old state first.
20630791971bSThadeu Lima de Souza Cascardo * getting rid of old interfaces means unbinding their drivers.
20640791971bSThadeu Lima de Souza Cascardo */
20650791971bSThadeu Lima de Souza Cascardo if (dev->state != USB_STATE_ADDRESS)
20660791971bSThadeu Lima de Souza Cascardo usb_disable_device(dev, 1); /* Skip ep0 */
20670791971bSThadeu Lima de Souza Cascardo
20680791971bSThadeu Lima de Souza Cascardo /* Get rid of pending async Set-Config requests for this device */
20690791971bSThadeu Lima de Souza Cascardo cancel_async_set_config(dev);
20700791971bSThadeu Lima de Souza Cascardo
207179abb1abSSarah Sharp /* Make sure we have bandwidth (and available HCD resources) for this
207279abb1abSSarah Sharp * configuration. Remove endpoints from the schedule if we're dropping
207379abb1abSSarah Sharp * this configuration to set configuration 0. After this point, the
207479abb1abSSarah Sharp * host controller will not allow submissions to dropped endpoints. If
207579abb1abSSarah Sharp * this call fails, the device state is unchanged.
207679abb1abSSarah Sharp */
20778963c487SAlan Stern mutex_lock(hcd->bandwidth_mutex);
20788306095fSSarah Sharp /* Disable LPM, and re-enable it once the new configuration is
20798306095fSSarah Sharp * installed, so that the xHCI driver can recalculate the U1/U2
20808306095fSSarah Sharp * timeouts.
20818306095fSSarah Sharp */
20829cf65991SSarah Sharp if (dev->actconfig && usb_disable_lpm(dev)) {
20831ccc417eSJoe Perches dev_err(&dev->dev, "%s Failed to disable LPM\n", __func__);
20848306095fSSarah Sharp mutex_unlock(hcd->bandwidth_mutex);
2085c058f7abSSachin Kamat ret = -ENOMEM;
2086c058f7abSSachin Kamat goto free_interfaces;
20878306095fSSarah Sharp }
20883f0479e0SSarah Sharp ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);
208979abb1abSSarah Sharp if (ret < 0) {
20909cf65991SSarah Sharp if (dev->actconfig)
20918306095fSSarah Sharp usb_enable_lpm(dev);
2092d673bfcbSSarah Sharp mutex_unlock(hcd->bandwidth_mutex);
20930791971bSThadeu Lima de Souza Cascardo usb_autosuspend_device(dev);
209479abb1abSSarah Sharp goto free_interfaces;
209579abb1abSSarah Sharp }
209679abb1abSSarah Sharp
209736caff5dSAlan Stern /*
209836caff5dSAlan Stern * Initialize the new interface structures and the
20991da177e4SLinus Torvalds * hc/hcd/usbcore interface/endpoint state.
21001da177e4SLinus Torvalds */
21011da177e4SLinus Torvalds for (i = 0; i < nintf; ++i) {
21021da177e4SLinus Torvalds struct usb_interface_cache *intfc;
21031da177e4SLinus Torvalds struct usb_interface *intf;
21041da177e4SLinus Torvalds struct usb_host_interface *alt;
21051a7e3948SJohan Hovold u8 ifnum;
21061da177e4SLinus Torvalds
21071da177e4SLinus Torvalds cp->interface[i] = intf = new_interfaces[i];
21081da177e4SLinus Torvalds intfc = cp->intf_cache[i];
21091da177e4SLinus Torvalds intf->altsetting = intfc->altsetting;
21101da177e4SLinus Torvalds intf->num_altsetting = intfc->num_altsetting;
21116b2bd3c8SStefan Koch intf->authorized = !!HCD_INTF_AUTHORIZED(hcd);
21121da177e4SLinus Torvalds kref_get(&intfc->ref);
21131da177e4SLinus Torvalds
21141da177e4SLinus Torvalds alt = usb_altnum_to_altsetting(intf, 0);
21151da177e4SLinus Torvalds
21161da177e4SLinus Torvalds /* No altsetting 0? We'll assume the first altsetting.
21171da177e4SLinus Torvalds * We could use a GetInterface call, but if a device is
21181da177e4SLinus Torvalds * so non-compliant that it doesn't have altsetting 0
21191da177e4SLinus Torvalds * then I wouldn't trust its reply anyway.
21201da177e4SLinus Torvalds */
21211da177e4SLinus Torvalds if (!alt)
21221da177e4SLinus Torvalds alt = &intf->altsetting[0];
21231da177e4SLinus Torvalds
21241a7e3948SJohan Hovold ifnum = alt->desc.bInterfaceNumber;
21251a7e3948SJohan Hovold intf->intf_assoc = find_iad(dev, cp, ifnum);
21261da177e4SLinus Torvalds intf->cur_altsetting = alt;
21272caf7fcdSAlan Stern usb_enable_interface(dev, intf, true);
21281da177e4SLinus Torvalds intf->dev.parent = &dev->dev;
21291a7e3948SJohan Hovold if (usb_of_has_combined_node(dev)) {
21301a7e3948SJohan Hovold device_set_of_node_from_dev(&intf->dev, &dev->dev);
21311a7e3948SJohan Hovold } else {
21321a7e3948SJohan Hovold intf->dev.of_node = usb_of_get_interface_node(dev,
21331a7e3948SJohan Hovold configuration, ifnum);
21341a7e3948SJohan Hovold }
2135a599a0fbSAndy Shevchenko ACPI_COMPANION_SET(&intf->dev, ACPI_COMPANION(&dev->dev));
21361da177e4SLinus Torvalds intf->dev.driver = NULL;
21371da177e4SLinus Torvalds intf->dev.bus = &usb_bus_type;
21389f8b17e6SKay Sievers intf->dev.type = &usb_if_device_type;
21392e5f10e4SAlan Stern intf->dev.groups = usb_interface_groups;
2140dc023dceSInaky Perez-Gonzalez INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);
21410a4db185SBastien Nocera INIT_WORK(&intf->wireless_status_work, __usb_wireless_status_intf);
21420026e005SAlan Stern intf->minor = -1;
21431da177e4SLinus Torvalds device_initialize(&intf->dev);
214463defa73SMing Lei pm_runtime_no_callbacks(&intf->dev);
21451a7e3948SJohan Hovold dev_set_name(&intf->dev, "%d-%s:%d.%d", dev->bus->busnum,
21461a7e3948SJohan Hovold dev->devpath, configuration, ifnum);
2147524134d4SAlan Stern usb_get_dev(dev);
21481da177e4SLinus Torvalds }
21491da177e4SLinus Torvalds kfree(new_interfaces);
21501da177e4SLinus Torvalds
2151297e84c0SGreg Kroah-Hartman ret = usb_control_msg_send(dev, 0, USB_REQ_SET_CONFIGURATION, 0,
2152297e84c0SGreg Kroah-Hartman configuration, 0, NULL, 0,
2153ddd1198eSOliver Neukum USB_CTRL_SET_TIMEOUT, GFP_NOIO);
2154297e84c0SGreg Kroah-Hartman if (ret && cp) {
215536caff5dSAlan Stern /*
215636caff5dSAlan Stern * All the old state is gone, so what else can we do?
215736caff5dSAlan Stern * The device is probably useless now anyway.
215836caff5dSAlan Stern */
215936caff5dSAlan Stern usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
216036caff5dSAlan Stern for (i = 0; i < nintf; ++i) {
216136caff5dSAlan Stern usb_disable_interface(dev, cp->interface[i], true);
216236caff5dSAlan Stern put_device(&cp->interface[i]->dev);
216336caff5dSAlan Stern cp->interface[i] = NULL;
216436caff5dSAlan Stern }
216536caff5dSAlan Stern cp = NULL;
216636caff5dSAlan Stern }
216736caff5dSAlan Stern
216836caff5dSAlan Stern dev->actconfig = cp;
216936caff5dSAlan Stern mutex_unlock(hcd->bandwidth_mutex);
217036caff5dSAlan Stern
217136caff5dSAlan Stern if (!cp) {
217236caff5dSAlan Stern usb_set_device_state(dev, USB_STATE_ADDRESS);
217336caff5dSAlan Stern
217436caff5dSAlan Stern /* Leave LPM disabled while the device is unconfigured. */
217536caff5dSAlan Stern usb_autosuspend_device(dev);
217636caff5dSAlan Stern return ret;
217736caff5dSAlan Stern }
217836caff5dSAlan Stern usb_set_device_state(dev, USB_STATE_CONFIGURED);
217936caff5dSAlan Stern
21801662e3a7SAlan Stern if (cp->string == NULL &&
21811662e3a7SAlan Stern !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
21826ad07129SAlan Stern cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
21831da177e4SLinus Torvalds
21848306095fSSarah Sharp /* Now that the interfaces are installed, re-enable LPM. */
21858306095fSSarah Sharp usb_unlocked_enable_lpm(dev);
2186f74631e3SSarah Sharp /* Enable LTM if it was turned off by usb_disable_device. */
2187f74631e3SSarah Sharp usb_enable_ltm(dev);
21888306095fSSarah Sharp
21891da177e4SLinus Torvalds /* Now that all the interfaces are set up, register them
21901da177e4SLinus Torvalds * to trigger binding of drivers to interfaces. probe()
21911da177e4SLinus Torvalds * routines may install different altsettings and may
21921da177e4SLinus Torvalds * claim() any interfaces not yet bound. Many class drivers
21931da177e4SLinus Torvalds * need that: CDC, audio, video, etc.
21941da177e4SLinus Torvalds */
21951da177e4SLinus Torvalds for (i = 0; i < nintf; ++i) {
21961da177e4SLinus Torvalds struct usb_interface *intf = cp->interface[i];
21971da177e4SLinus Torvalds
219801fdf179SMans Rullgard if (intf->dev.of_node &&
219901fdf179SMans Rullgard !of_device_is_available(intf->dev.of_node)) {
220001fdf179SMans Rullgard dev_info(&dev->dev, "skipping disabled interface %d\n",
220101fdf179SMans Rullgard intf->cur_altsetting->desc.bInterfaceNumber);
220201fdf179SMans Rullgard continue;
220301fdf179SMans Rullgard }
220401fdf179SMans Rullgard
22051da177e4SLinus Torvalds dev_dbg(&dev->dev,
22061da177e4SLinus Torvalds "adding %s (config #%d, interface %d)\n",
22077071a3ceSKay Sievers dev_name(&intf->dev), configuration,
2208d4ece29dSDmitry Torokhov intf->cur_altsetting->desc.bInterfaceNumber);
2209927bc916SRafael J. Wysocki device_enable_async_suspend(&intf->dev);
22101da177e4SLinus Torvalds ret = device_add(&intf->dev);
22111da177e4SLinus Torvalds if (ret != 0) {
22126ad07129SAlan Stern dev_err(&dev->dev, "device_add(%s) --> %d\n",
22137071a3ceSKay Sievers dev_name(&intf->dev), ret);
22141da177e4SLinus Torvalds continue;
22151da177e4SLinus Torvalds }
22163b23dd6fSAlan Stern create_intf_ep_devs(intf);
22171da177e4SLinus Torvalds }
22181da177e4SLinus Torvalds
221994fcda1fSAlan Stern usb_autosuspend_device(dev);
222086d30741SAlan Stern return 0;
22211da177e4SLinus Torvalds }
2222b7945b77SValentina Manea EXPORT_SYMBOL_GPL(usb_set_configuration);
22231da177e4SLinus Torvalds
2224df718962SAlan Stern static LIST_HEAD(set_config_list);
2225df718962SAlan Stern static DEFINE_SPINLOCK(set_config_lock);
2226df718962SAlan Stern
2227088dc270SAlan Stern struct set_config_request {
2228088dc270SAlan Stern struct usb_device *udev;
2229088dc270SAlan Stern int config;
2230088dc270SAlan Stern struct work_struct work;
2231df718962SAlan Stern struct list_head node;
2232088dc270SAlan Stern };
2233088dc270SAlan Stern
2234088dc270SAlan Stern /* Worker routine for usb_driver_set_configuration() */
driver_set_config_work(struct work_struct * work)2235c4028958SDavid Howells static void driver_set_config_work(struct work_struct *work)
2236088dc270SAlan Stern {
2237c4028958SDavid Howells struct set_config_request *req =
2238c4028958SDavid Howells container_of(work, struct set_config_request, work);
2239df718962SAlan Stern struct usb_device *udev = req->udev;
2240088dc270SAlan Stern
2241df718962SAlan Stern usb_lock_device(udev);
2242df718962SAlan Stern spin_lock(&set_config_lock);
2243df718962SAlan Stern list_del(&req->node);
2244df718962SAlan Stern spin_unlock(&set_config_lock);
2245df718962SAlan Stern
2246df718962SAlan Stern if (req->config >= -1) /* Is req still valid? */
2247df718962SAlan Stern usb_set_configuration(udev, req->config);
2248df718962SAlan Stern usb_unlock_device(udev);
2249df718962SAlan Stern usb_put_dev(udev);
2250088dc270SAlan Stern kfree(req);
2251088dc270SAlan Stern }
2252088dc270SAlan Stern
2253df718962SAlan Stern /* Cancel pending Set-Config requests for a device whose configuration
2254df718962SAlan Stern * was just changed
2255df718962SAlan Stern */
cancel_async_set_config(struct usb_device * udev)2256df718962SAlan Stern static void cancel_async_set_config(struct usb_device *udev)
2257df718962SAlan Stern {
2258df718962SAlan Stern struct set_config_request *req;
2259df718962SAlan Stern
2260df718962SAlan Stern spin_lock(&set_config_lock);
2261df718962SAlan Stern list_for_each_entry(req, &set_config_list, node) {
2262df718962SAlan Stern if (req->udev == udev)
2263df718962SAlan Stern req->config = -999; /* Mark as cancelled */
2264df718962SAlan Stern }
2265df718962SAlan Stern spin_unlock(&set_config_lock);
2266df718962SAlan Stern }
2267df718962SAlan Stern
2268088dc270SAlan Stern /**
2269088dc270SAlan Stern * usb_driver_set_configuration - Provide a way for drivers to change device configurations
2270088dc270SAlan Stern * @udev: the device whose configuration is being updated
2271088dc270SAlan Stern * @config: the configuration being chosen.
2272088dc270SAlan Stern * Context: In process context, must be able to sleep
2273088dc270SAlan Stern *
2274088dc270SAlan Stern * Device interface drivers are not allowed to change device configurations.
2275088dc270SAlan Stern * This is because changing configurations will destroy the interface the
2276088dc270SAlan Stern * driver is bound to and create new ones; it would be like a floppy-disk
2277088dc270SAlan Stern * driver telling the computer to replace the floppy-disk drive with a
2278088dc270SAlan Stern * tape drive!
2279088dc270SAlan Stern *
2280088dc270SAlan Stern * Still, in certain specialized circumstances the need may arise. This
2281088dc270SAlan Stern * routine gets around the normal restrictions by using a work thread to
2282088dc270SAlan Stern * submit the change-config request.
2283088dc270SAlan Stern *
2284626f090cSYacine Belkadi * Return: 0 if the request was successfully queued, error code otherwise.
2285088dc270SAlan Stern * The caller has no way to know whether the queued request will eventually
2286088dc270SAlan Stern * succeed.
2287088dc270SAlan Stern */
usb_driver_set_configuration(struct usb_device * udev,int config)2288088dc270SAlan Stern int usb_driver_set_configuration(struct usb_device *udev, int config)
2289088dc270SAlan Stern {
2290088dc270SAlan Stern struct set_config_request *req;
2291088dc270SAlan Stern
2292088dc270SAlan Stern req = kmalloc(sizeof(*req), GFP_KERNEL);
2293088dc270SAlan Stern if (!req)
2294088dc270SAlan Stern return -ENOMEM;
2295088dc270SAlan Stern req->udev = udev;
2296088dc270SAlan Stern req->config = config;
2297c4028958SDavid Howells INIT_WORK(&req->work, driver_set_config_work);
2298088dc270SAlan Stern
2299df718962SAlan Stern spin_lock(&set_config_lock);
2300df718962SAlan Stern list_add(&req->node, &set_config_list);
2301df718962SAlan Stern spin_unlock(&set_config_lock);
2302df718962SAlan Stern
2303088dc270SAlan Stern usb_get_dev(udev);
23041737bf2cSAlan Stern schedule_work(&req->work);
2305088dc270SAlan Stern return 0;
2306088dc270SAlan Stern }
2307088dc270SAlan Stern EXPORT_SYMBOL_GPL(usb_driver_set_configuration);
2308e4c6fb77SOliver Neukum
2309e4c6fb77SOliver Neukum /**
2310e4c6fb77SOliver Neukum * cdc_parse_cdc_header - parse the extra headers present in CDC devices
2311e4c6fb77SOliver Neukum * @hdr: the place to put the results of the parsing
2312e4c6fb77SOliver Neukum * @intf: the interface for which parsing is requested
2313e4c6fb77SOliver Neukum * @buffer: pointer to the extra headers to be parsed
2314e4c6fb77SOliver Neukum * @buflen: length of the extra headers
2315e4c6fb77SOliver Neukum *
2316e4c6fb77SOliver Neukum * This evaluates the extra headers present in CDC devices which
2317e4c6fb77SOliver Neukum * bind the interfaces for data and control and provide details
2318e4c6fb77SOliver Neukum * about the capabilities of the device.
2319e4c6fb77SOliver Neukum *
2320e4c6fb77SOliver Neukum * Return: number of descriptors parsed or -EINVAL
2321e4c6fb77SOliver Neukum * if the header is contradictory beyond salvage
2322e4c6fb77SOliver Neukum */
2323e4c6fb77SOliver Neukum
cdc_parse_cdc_header(struct usb_cdc_parsed_header * hdr,struct usb_interface * intf,u8 * buffer,int buflen)2324e4c6fb77SOliver Neukum int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr,
2325e4c6fb77SOliver Neukum struct usb_interface *intf,
2326e4c6fb77SOliver Neukum u8 *buffer,
2327e4c6fb77SOliver Neukum int buflen)
2328e4c6fb77SOliver Neukum {
2329e4c6fb77SOliver Neukum /* duplicates are ignored */
2330e4c6fb77SOliver Neukum struct usb_cdc_union_desc *union_header = NULL;
2331e4c6fb77SOliver Neukum
2332e4c6fb77SOliver Neukum /* duplicates are not tolerated */
2333e4c6fb77SOliver Neukum struct usb_cdc_header_desc *header = NULL;
2334e4c6fb77SOliver Neukum struct usb_cdc_ether_desc *ether = NULL;
2335e4c6fb77SOliver Neukum struct usb_cdc_mdlm_detail_desc *detail = NULL;
2336e4c6fb77SOliver Neukum struct usb_cdc_mdlm_desc *desc = NULL;
2337e4c6fb77SOliver Neukum
2338e4c6fb77SOliver Neukum unsigned int elength;
2339e4c6fb77SOliver Neukum int cnt = 0;
2340e4c6fb77SOliver Neukum
2341e4c6fb77SOliver Neukum memset(hdr, 0x00, sizeof(struct usb_cdc_parsed_header));
2342e4c6fb77SOliver Neukum hdr->phonet_magic_present = false;
2343e4c6fb77SOliver Neukum while (buflen > 0) {
2344e4c6fb77SOliver Neukum elength = buffer[0];
2345e4c6fb77SOliver Neukum if (!elength) {
2346e4c6fb77SOliver Neukum dev_err(&intf->dev, "skipping garbage byte\n");
2347e4c6fb77SOliver Neukum elength = 1;
2348e4c6fb77SOliver Neukum goto next_desc;
2349e4c6fb77SOliver Neukum }
23502e1c4239SGreg Kroah-Hartman if ((buflen < elength) || (elength < 3)) {
23512e1c4239SGreg Kroah-Hartman dev_err(&intf->dev, "invalid descriptor buffer length\n");
23522e1c4239SGreg Kroah-Hartman break;
23532e1c4239SGreg Kroah-Hartman }
2354e4c6fb77SOliver Neukum if (buffer[1] != USB_DT_CS_INTERFACE) {
2355e4c6fb77SOliver Neukum dev_err(&intf->dev, "skipping garbage\n");
2356e4c6fb77SOliver Neukum goto next_desc;
2357e4c6fb77SOliver Neukum }
2358e4c6fb77SOliver Neukum
2359e4c6fb77SOliver Neukum switch (buffer[2]) {
2360e4c6fb77SOliver Neukum case USB_CDC_UNION_TYPE: /* we've found it */
2361e4c6fb77SOliver Neukum if (elength < sizeof(struct usb_cdc_union_desc))
2362e4c6fb77SOliver Neukum goto next_desc;
2363e4c6fb77SOliver Neukum if (union_header) {
2364e4c6fb77SOliver Neukum dev_err(&intf->dev, "More than one union descriptor, skipping ...\n");
2365e4c6fb77SOliver Neukum goto next_desc;
2366e4c6fb77SOliver Neukum }
2367e4c6fb77SOliver Neukum union_header = (struct usb_cdc_union_desc *)buffer;
2368e4c6fb77SOliver Neukum break;
2369e4c6fb77SOliver Neukum case USB_CDC_COUNTRY_TYPE:
2370e4c6fb77SOliver Neukum if (elength < sizeof(struct usb_cdc_country_functional_desc))
2371e4c6fb77SOliver Neukum goto next_desc;
2372e4c6fb77SOliver Neukum hdr->usb_cdc_country_functional_desc =
2373e4c6fb77SOliver Neukum (struct usb_cdc_country_functional_desc *)buffer;
2374e4c6fb77SOliver Neukum break;
2375e4c6fb77SOliver Neukum case USB_CDC_HEADER_TYPE:
2376e4c6fb77SOliver Neukum if (elength != sizeof(struct usb_cdc_header_desc))
2377e4c6fb77SOliver Neukum goto next_desc;
2378e4c6fb77SOliver Neukum if (header)
2379e4c6fb77SOliver Neukum return -EINVAL;
2380e4c6fb77SOliver Neukum header = (struct usb_cdc_header_desc *)buffer;
2381e4c6fb77SOliver Neukum break;
2382e4c6fb77SOliver Neukum case USB_CDC_ACM_TYPE:
2383e4c6fb77SOliver Neukum if (elength < sizeof(struct usb_cdc_acm_descriptor))
2384e4c6fb77SOliver Neukum goto next_desc;
2385e4c6fb77SOliver Neukum hdr->usb_cdc_acm_descriptor =
2386e4c6fb77SOliver Neukum (struct usb_cdc_acm_descriptor *)buffer;
2387e4c6fb77SOliver Neukum break;
2388e4c6fb77SOliver Neukum case USB_CDC_ETHERNET_TYPE:
2389e4c6fb77SOliver Neukum if (elength != sizeof(struct usb_cdc_ether_desc))
2390e4c6fb77SOliver Neukum goto next_desc;
2391e4c6fb77SOliver Neukum if (ether)
2392e4c6fb77SOliver Neukum return -EINVAL;
2393e4c6fb77SOliver Neukum ether = (struct usb_cdc_ether_desc *)buffer;
2394e4c6fb77SOliver Neukum break;
2395e4c6fb77SOliver Neukum case USB_CDC_CALL_MANAGEMENT_TYPE:
2396e4c6fb77SOliver Neukum if (elength < sizeof(struct usb_cdc_call_mgmt_descriptor))
2397e4c6fb77SOliver Neukum goto next_desc;
2398e4c6fb77SOliver Neukum hdr->usb_cdc_call_mgmt_descriptor =
2399e4c6fb77SOliver Neukum (struct usb_cdc_call_mgmt_descriptor *)buffer;
2400e4c6fb77SOliver Neukum break;
2401e4c6fb77SOliver Neukum case USB_CDC_DMM_TYPE:
2402e4c6fb77SOliver Neukum if (elength < sizeof(struct usb_cdc_dmm_desc))
2403e4c6fb77SOliver Neukum goto next_desc;
2404e4c6fb77SOliver Neukum hdr->usb_cdc_dmm_desc =
2405e4c6fb77SOliver Neukum (struct usb_cdc_dmm_desc *)buffer;
2406e4c6fb77SOliver Neukum break;
2407e4c6fb77SOliver Neukum case USB_CDC_MDLM_TYPE:
240854364278SOliver Neukum if (elength < sizeof(struct usb_cdc_mdlm_desc))
2409e4c6fb77SOliver Neukum goto next_desc;
2410e4c6fb77SOliver Neukum if (desc)
2411e4c6fb77SOliver Neukum return -EINVAL;
2412e4c6fb77SOliver Neukum desc = (struct usb_cdc_mdlm_desc *)buffer;
2413e4c6fb77SOliver Neukum break;
2414e4c6fb77SOliver Neukum case USB_CDC_MDLM_DETAIL_TYPE:
241554364278SOliver Neukum if (elength < sizeof(struct usb_cdc_mdlm_detail_desc))
2416e4c6fb77SOliver Neukum goto next_desc;
2417e4c6fb77SOliver Neukum if (detail)
2418e4c6fb77SOliver Neukum return -EINVAL;
2419e4c6fb77SOliver Neukum detail = (struct usb_cdc_mdlm_detail_desc *)buffer;
2420e4c6fb77SOliver Neukum break;
2421e4c6fb77SOliver Neukum case USB_CDC_NCM_TYPE:
2422e4c6fb77SOliver Neukum if (elength < sizeof(struct usb_cdc_ncm_desc))
2423e4c6fb77SOliver Neukum goto next_desc;
2424e4c6fb77SOliver Neukum hdr->usb_cdc_ncm_desc = (struct usb_cdc_ncm_desc *)buffer;
2425e4c6fb77SOliver Neukum break;
2426e4c6fb77SOliver Neukum case USB_CDC_MBIM_TYPE:
2427e4c6fb77SOliver Neukum if (elength < sizeof(struct usb_cdc_mbim_desc))
2428e4c6fb77SOliver Neukum goto next_desc;
2429e4c6fb77SOliver Neukum
2430e4c6fb77SOliver Neukum hdr->usb_cdc_mbim_desc = (struct usb_cdc_mbim_desc *)buffer;
2431e4c6fb77SOliver Neukum break;
2432e4c6fb77SOliver Neukum case USB_CDC_MBIM_EXTENDED_TYPE:
2433e4c6fb77SOliver Neukum if (elength < sizeof(struct usb_cdc_mbim_extended_desc))
2434e4c6fb77SOliver Neukum break;
2435e4c6fb77SOliver Neukum hdr->usb_cdc_mbim_extended_desc =
2436e4c6fb77SOliver Neukum (struct usb_cdc_mbim_extended_desc *)buffer;
2437e4c6fb77SOliver Neukum break;
2438e4c6fb77SOliver Neukum case CDC_PHONET_MAGIC_NUMBER:
2439e4c6fb77SOliver Neukum hdr->phonet_magic_present = true;
2440e4c6fb77SOliver Neukum break;
2441e4c6fb77SOliver Neukum default:
2442e4c6fb77SOliver Neukum /*
2443e4c6fb77SOliver Neukum * there are LOTS more CDC descriptors that
2444e4c6fb77SOliver Neukum * could legitimately be found here.
2445e4c6fb77SOliver Neukum */
2446e4c6fb77SOliver Neukum dev_dbg(&intf->dev, "Ignoring descriptor: type %02x, length %ud\n",
2447e4c6fb77SOliver Neukum buffer[2], elength);
2448e4c6fb77SOliver Neukum goto next_desc;
2449e4c6fb77SOliver Neukum }
2450e4c6fb77SOliver Neukum cnt++;
2451e4c6fb77SOliver Neukum next_desc:
2452e4c6fb77SOliver Neukum buflen -= elength;
2453e4c6fb77SOliver Neukum buffer += elength;
2454e4c6fb77SOliver Neukum }
2455e4c6fb77SOliver Neukum hdr->usb_cdc_union_desc = union_header;
2456e4c6fb77SOliver Neukum hdr->usb_cdc_header_desc = header;
2457e4c6fb77SOliver Neukum hdr->usb_cdc_mdlm_detail_desc = detail;
2458e4c6fb77SOliver Neukum hdr->usb_cdc_mdlm_desc = desc;
2459e4c6fb77SOliver Neukum hdr->usb_cdc_ether_desc = ether;
2460e4c6fb77SOliver Neukum return cnt;
2461e4c6fb77SOliver Neukum }
2462e4c6fb77SOliver Neukum
2463e4c6fb77SOliver Neukum EXPORT_SYMBOL(cdc_parse_cdc_header);
2464