1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * dummy_hcd.c -- Dummy/Loopback USB host and device emulator driver.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Maintainer: Alan Stern <stern@rowland.harvard.edu>
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright (C) 2003 David Brownell
8*4882a593Smuzhiyun * Copyright (C) 2003-2005 Alan Stern
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun /*
13*4882a593Smuzhiyun * This exposes a device side "USB gadget" API, driven by requests to a
14*4882a593Smuzhiyun * Linux-USB host controller driver. USB traffic is simulated; there's
15*4882a593Smuzhiyun * no need for USB hardware. Use this with two other drivers:
16*4882a593Smuzhiyun *
17*4882a593Smuzhiyun * - Gadget driver, responding to requests (device);
18*4882a593Smuzhiyun * - Host-side device driver, as already familiar in Linux.
19*4882a593Smuzhiyun *
20*4882a593Smuzhiyun * Having this all in one kernel can help some stages of development,
21*4882a593Smuzhiyun * bypassing some hardware (and driver) issues. UML could help too.
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun * Note: The emulation does not include isochronous transfers!
24*4882a593Smuzhiyun */
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #include <linux/module.h>
27*4882a593Smuzhiyun #include <linux/kernel.h>
28*4882a593Smuzhiyun #include <linux/delay.h>
29*4882a593Smuzhiyun #include <linux/ioport.h>
30*4882a593Smuzhiyun #include <linux/slab.h>
31*4882a593Smuzhiyun #include <linux/errno.h>
32*4882a593Smuzhiyun #include <linux/init.h>
33*4882a593Smuzhiyun #include <linux/timer.h>
34*4882a593Smuzhiyun #include <linux/list.h>
35*4882a593Smuzhiyun #include <linux/interrupt.h>
36*4882a593Smuzhiyun #include <linux/platform_device.h>
37*4882a593Smuzhiyun #include <linux/usb.h>
38*4882a593Smuzhiyun #include <linux/usb/gadget.h>
39*4882a593Smuzhiyun #include <linux/usb/hcd.h>
40*4882a593Smuzhiyun #include <linux/scatterlist.h>
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun #include <asm/byteorder.h>
43*4882a593Smuzhiyun #include <linux/io.h>
44*4882a593Smuzhiyun #include <asm/irq.h>
45*4882a593Smuzhiyun #include <asm/unaligned.h>
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun #define DRIVER_DESC "USB Host+Gadget Emulator"
48*4882a593Smuzhiyun #define DRIVER_VERSION "02 May 2005"
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun #define POWER_BUDGET 500 /* in mA; use 8 for low-power port testing */
51*4882a593Smuzhiyun #define POWER_BUDGET_3 900 /* in mA */
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun static const char driver_name[] = "dummy_hcd";
54*4882a593Smuzhiyun static const char driver_desc[] = "USB Host+Gadget Emulator";
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun static const char gadget_name[] = "dummy_udc";
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun MODULE_DESCRIPTION(DRIVER_DESC);
59*4882a593Smuzhiyun MODULE_AUTHOR("David Brownell");
60*4882a593Smuzhiyun MODULE_LICENSE("GPL");
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun struct dummy_hcd_module_parameters {
63*4882a593Smuzhiyun bool is_super_speed;
64*4882a593Smuzhiyun bool is_high_speed;
65*4882a593Smuzhiyun unsigned int num;
66*4882a593Smuzhiyun };
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun static struct dummy_hcd_module_parameters mod_data = {
69*4882a593Smuzhiyun .is_super_speed = false,
70*4882a593Smuzhiyun .is_high_speed = true,
71*4882a593Smuzhiyun .num = 1,
72*4882a593Smuzhiyun };
73*4882a593Smuzhiyun module_param_named(is_super_speed, mod_data.is_super_speed, bool, S_IRUGO);
74*4882a593Smuzhiyun MODULE_PARM_DESC(is_super_speed, "true to simulate SuperSpeed connection");
75*4882a593Smuzhiyun module_param_named(is_high_speed, mod_data.is_high_speed, bool, S_IRUGO);
76*4882a593Smuzhiyun MODULE_PARM_DESC(is_high_speed, "true to simulate HighSpeed connection");
77*4882a593Smuzhiyun module_param_named(num, mod_data.num, uint, S_IRUGO);
78*4882a593Smuzhiyun MODULE_PARM_DESC(num, "number of emulated controllers");
79*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun /* gadget side driver data structres */
82*4882a593Smuzhiyun struct dummy_ep {
83*4882a593Smuzhiyun struct list_head queue;
84*4882a593Smuzhiyun unsigned long last_io; /* jiffies timestamp */
85*4882a593Smuzhiyun struct usb_gadget *gadget;
86*4882a593Smuzhiyun const struct usb_endpoint_descriptor *desc;
87*4882a593Smuzhiyun struct usb_ep ep;
88*4882a593Smuzhiyun unsigned halted:1;
89*4882a593Smuzhiyun unsigned wedged:1;
90*4882a593Smuzhiyun unsigned already_seen:1;
91*4882a593Smuzhiyun unsigned setup_stage:1;
92*4882a593Smuzhiyun unsigned stream_en:1;
93*4882a593Smuzhiyun };
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun struct dummy_request {
96*4882a593Smuzhiyun struct list_head queue; /* ep's requests */
97*4882a593Smuzhiyun struct usb_request req;
98*4882a593Smuzhiyun };
99*4882a593Smuzhiyun
usb_ep_to_dummy_ep(struct usb_ep * _ep)100*4882a593Smuzhiyun static inline struct dummy_ep *usb_ep_to_dummy_ep(struct usb_ep *_ep)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun return container_of(_ep, struct dummy_ep, ep);
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
usb_request_to_dummy_request(struct usb_request * _req)105*4882a593Smuzhiyun static inline struct dummy_request *usb_request_to_dummy_request
106*4882a593Smuzhiyun (struct usb_request *_req)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun return container_of(_req, struct dummy_request, req);
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun /*
114*4882a593Smuzhiyun * Every device has ep0 for control requests, plus up to 30 more endpoints,
115*4882a593Smuzhiyun * in one of two types:
116*4882a593Smuzhiyun *
117*4882a593Smuzhiyun * - Configurable: direction (in/out), type (bulk, iso, etc), and endpoint
118*4882a593Smuzhiyun * number can be changed. Names like "ep-a" are used for this type.
119*4882a593Smuzhiyun *
120*4882a593Smuzhiyun * - Fixed Function: in other cases. some characteristics may be mutable;
121*4882a593Smuzhiyun * that'd be hardware-specific. Names like "ep12out-bulk" are used.
122*4882a593Smuzhiyun *
123*4882a593Smuzhiyun * Gadget drivers are responsible for not setting up conflicting endpoint
124*4882a593Smuzhiyun * configurations, illegal or unsupported packet lengths, and so on.
125*4882a593Smuzhiyun */
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun static const char ep0name[] = "ep0";
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun static const struct {
130*4882a593Smuzhiyun const char *name;
131*4882a593Smuzhiyun const struct usb_ep_caps caps;
132*4882a593Smuzhiyun } ep_info[] = {
133*4882a593Smuzhiyun #define EP_INFO(_name, _caps) \
134*4882a593Smuzhiyun { \
135*4882a593Smuzhiyun .name = _name, \
136*4882a593Smuzhiyun .caps = _caps, \
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun /* we don't provide isochronous endpoints since we don't support them */
140*4882a593Smuzhiyun #define TYPE_BULK_OR_INT (USB_EP_CAPS_TYPE_BULK | USB_EP_CAPS_TYPE_INT)
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun /* everyone has ep0 */
143*4882a593Smuzhiyun EP_INFO(ep0name,
144*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
145*4882a593Smuzhiyun /* act like a pxa250: fifteen fixed function endpoints */
146*4882a593Smuzhiyun EP_INFO("ep1in-bulk",
147*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
148*4882a593Smuzhiyun EP_INFO("ep2out-bulk",
149*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
150*4882a593Smuzhiyun /*
151*4882a593Smuzhiyun EP_INFO("ep3in-iso",
152*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
153*4882a593Smuzhiyun EP_INFO("ep4out-iso",
154*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
155*4882a593Smuzhiyun */
156*4882a593Smuzhiyun EP_INFO("ep5in-int",
157*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
158*4882a593Smuzhiyun EP_INFO("ep6in-bulk",
159*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
160*4882a593Smuzhiyun EP_INFO("ep7out-bulk",
161*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
162*4882a593Smuzhiyun /*
163*4882a593Smuzhiyun EP_INFO("ep8in-iso",
164*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
165*4882a593Smuzhiyun EP_INFO("ep9out-iso",
166*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
167*4882a593Smuzhiyun */
168*4882a593Smuzhiyun EP_INFO("ep10in-int",
169*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
170*4882a593Smuzhiyun EP_INFO("ep11in-bulk",
171*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
172*4882a593Smuzhiyun EP_INFO("ep12out-bulk",
173*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
174*4882a593Smuzhiyun /*
175*4882a593Smuzhiyun EP_INFO("ep13in-iso",
176*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
177*4882a593Smuzhiyun EP_INFO("ep14out-iso",
178*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
179*4882a593Smuzhiyun */
180*4882a593Smuzhiyun EP_INFO("ep15in-int",
181*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun /* or like sa1100: two fixed function endpoints */
184*4882a593Smuzhiyun EP_INFO("ep1out-bulk",
185*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
186*4882a593Smuzhiyun EP_INFO("ep2in-bulk",
187*4882a593Smuzhiyun USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun /* and now some generic EPs so we have enough in multi config */
190*4882a593Smuzhiyun EP_INFO("ep-aout",
191*4882a593Smuzhiyun USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
192*4882a593Smuzhiyun EP_INFO("ep-bin",
193*4882a593Smuzhiyun USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_IN)),
194*4882a593Smuzhiyun EP_INFO("ep-cout",
195*4882a593Smuzhiyun USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
196*4882a593Smuzhiyun EP_INFO("ep-dout",
197*4882a593Smuzhiyun USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
198*4882a593Smuzhiyun EP_INFO("ep-ein",
199*4882a593Smuzhiyun USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_IN)),
200*4882a593Smuzhiyun EP_INFO("ep-fout",
201*4882a593Smuzhiyun USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
202*4882a593Smuzhiyun EP_INFO("ep-gin",
203*4882a593Smuzhiyun USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_IN)),
204*4882a593Smuzhiyun EP_INFO("ep-hout",
205*4882a593Smuzhiyun USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
206*4882a593Smuzhiyun EP_INFO("ep-iout",
207*4882a593Smuzhiyun USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
208*4882a593Smuzhiyun EP_INFO("ep-jin",
209*4882a593Smuzhiyun USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_IN)),
210*4882a593Smuzhiyun EP_INFO("ep-kout",
211*4882a593Smuzhiyun USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
212*4882a593Smuzhiyun EP_INFO("ep-lin",
213*4882a593Smuzhiyun USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_IN)),
214*4882a593Smuzhiyun EP_INFO("ep-mout",
215*4882a593Smuzhiyun USB_EP_CAPS(TYPE_BULK_OR_INT, USB_EP_CAPS_DIR_OUT)),
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun #undef EP_INFO
218*4882a593Smuzhiyun };
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun #define DUMMY_ENDPOINTS ARRAY_SIZE(ep_info)
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun #define FIFO_SIZE 64
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun struct urbp {
227*4882a593Smuzhiyun struct urb *urb;
228*4882a593Smuzhiyun struct list_head urbp_list;
229*4882a593Smuzhiyun struct sg_mapping_iter miter;
230*4882a593Smuzhiyun u32 miter_started;
231*4882a593Smuzhiyun };
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun enum dummy_rh_state {
235*4882a593Smuzhiyun DUMMY_RH_RESET,
236*4882a593Smuzhiyun DUMMY_RH_SUSPENDED,
237*4882a593Smuzhiyun DUMMY_RH_RUNNING
238*4882a593Smuzhiyun };
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun struct dummy_hcd {
241*4882a593Smuzhiyun struct dummy *dum;
242*4882a593Smuzhiyun enum dummy_rh_state rh_state;
243*4882a593Smuzhiyun struct timer_list timer;
244*4882a593Smuzhiyun u32 port_status;
245*4882a593Smuzhiyun u32 old_status;
246*4882a593Smuzhiyun unsigned long re_timeout;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun struct usb_device *udev;
249*4882a593Smuzhiyun struct list_head urbp_list;
250*4882a593Smuzhiyun struct urbp *next_frame_urbp;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun u32 stream_en_ep;
253*4882a593Smuzhiyun u8 num_stream[30 / 2];
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun unsigned active:1;
256*4882a593Smuzhiyun unsigned old_active:1;
257*4882a593Smuzhiyun unsigned resuming:1;
258*4882a593Smuzhiyun };
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun struct dummy {
261*4882a593Smuzhiyun spinlock_t lock;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun /*
264*4882a593Smuzhiyun * DEVICE/GADGET side support
265*4882a593Smuzhiyun */
266*4882a593Smuzhiyun struct dummy_ep ep[DUMMY_ENDPOINTS];
267*4882a593Smuzhiyun int address;
268*4882a593Smuzhiyun int callback_usage;
269*4882a593Smuzhiyun struct usb_gadget gadget;
270*4882a593Smuzhiyun struct usb_gadget_driver *driver;
271*4882a593Smuzhiyun struct dummy_request fifo_req;
272*4882a593Smuzhiyun u8 fifo_buf[FIFO_SIZE];
273*4882a593Smuzhiyun u16 devstatus;
274*4882a593Smuzhiyun unsigned ints_enabled:1;
275*4882a593Smuzhiyun unsigned udc_suspended:1;
276*4882a593Smuzhiyun unsigned pullup:1;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun /*
279*4882a593Smuzhiyun * HOST side support
280*4882a593Smuzhiyun */
281*4882a593Smuzhiyun struct dummy_hcd *hs_hcd;
282*4882a593Smuzhiyun struct dummy_hcd *ss_hcd;
283*4882a593Smuzhiyun };
284*4882a593Smuzhiyun
hcd_to_dummy_hcd(struct usb_hcd * hcd)285*4882a593Smuzhiyun static inline struct dummy_hcd *hcd_to_dummy_hcd(struct usb_hcd *hcd)
286*4882a593Smuzhiyun {
287*4882a593Smuzhiyun return (struct dummy_hcd *) (hcd->hcd_priv);
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun
dummy_hcd_to_hcd(struct dummy_hcd * dum)290*4882a593Smuzhiyun static inline struct usb_hcd *dummy_hcd_to_hcd(struct dummy_hcd *dum)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun return container_of((void *) dum, struct usb_hcd, hcd_priv);
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun
dummy_dev(struct dummy_hcd * dum)295*4882a593Smuzhiyun static inline struct device *dummy_dev(struct dummy_hcd *dum)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun return dummy_hcd_to_hcd(dum)->self.controller;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun
udc_dev(struct dummy * dum)300*4882a593Smuzhiyun static inline struct device *udc_dev(struct dummy *dum)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun return dum->gadget.dev.parent;
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun
ep_to_dummy(struct dummy_ep * ep)305*4882a593Smuzhiyun static inline struct dummy *ep_to_dummy(struct dummy_ep *ep)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun return container_of(ep->gadget, struct dummy, gadget);
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun
gadget_to_dummy_hcd(struct usb_gadget * gadget)310*4882a593Smuzhiyun static inline struct dummy_hcd *gadget_to_dummy_hcd(struct usb_gadget *gadget)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun struct dummy *dum = container_of(gadget, struct dummy, gadget);
313*4882a593Smuzhiyun if (dum->gadget.speed == USB_SPEED_SUPER)
314*4882a593Smuzhiyun return dum->ss_hcd;
315*4882a593Smuzhiyun else
316*4882a593Smuzhiyun return dum->hs_hcd;
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun
gadget_dev_to_dummy(struct device * dev)319*4882a593Smuzhiyun static inline struct dummy *gadget_dev_to_dummy(struct device *dev)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun return container_of(dev, struct dummy, gadget.dev);
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun /* DEVICE/GADGET SIDE UTILITY ROUTINES */
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun /* called with spinlock held */
nuke(struct dummy * dum,struct dummy_ep * ep)329*4882a593Smuzhiyun static void nuke(struct dummy *dum, struct dummy_ep *ep)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun while (!list_empty(&ep->queue)) {
332*4882a593Smuzhiyun struct dummy_request *req;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun req = list_entry(ep->queue.next, struct dummy_request, queue);
335*4882a593Smuzhiyun list_del_init(&req->queue);
336*4882a593Smuzhiyun req->req.status = -ESHUTDOWN;
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun spin_unlock(&dum->lock);
339*4882a593Smuzhiyun usb_gadget_giveback_request(&ep->ep, &req->req);
340*4882a593Smuzhiyun spin_lock(&dum->lock);
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun /* caller must hold lock */
stop_activity(struct dummy * dum)345*4882a593Smuzhiyun static void stop_activity(struct dummy *dum)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun int i;
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun /* prevent any more requests */
350*4882a593Smuzhiyun dum->address = 0;
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun /* The timer is left running so that outstanding URBs can fail */
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun /* nuke any pending requests first, so driver i/o is quiesced */
355*4882a593Smuzhiyun for (i = 0; i < DUMMY_ENDPOINTS; ++i)
356*4882a593Smuzhiyun nuke(dum, &dum->ep[i]);
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun /* driver now does any non-usb quiescing necessary */
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun /**
362*4882a593Smuzhiyun * set_link_state_by_speed() - Sets the current state of the link according to
363*4882a593Smuzhiyun * the hcd speed
364*4882a593Smuzhiyun * @dum_hcd: pointer to the dummy_hcd structure to update the link state for
365*4882a593Smuzhiyun *
366*4882a593Smuzhiyun * This function updates the port_status according to the link state and the
367*4882a593Smuzhiyun * speed of the hcd.
368*4882a593Smuzhiyun */
set_link_state_by_speed(struct dummy_hcd * dum_hcd)369*4882a593Smuzhiyun static void set_link_state_by_speed(struct dummy_hcd *dum_hcd)
370*4882a593Smuzhiyun {
371*4882a593Smuzhiyun struct dummy *dum = dum_hcd->dum;
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun if (dummy_hcd_to_hcd(dum_hcd)->speed == HCD_USB3) {
374*4882a593Smuzhiyun if ((dum_hcd->port_status & USB_SS_PORT_STAT_POWER) == 0) {
375*4882a593Smuzhiyun dum_hcd->port_status = 0;
376*4882a593Smuzhiyun } else if (!dum->pullup || dum->udc_suspended) {
377*4882a593Smuzhiyun /* UDC suspend must cause a disconnect */
378*4882a593Smuzhiyun dum_hcd->port_status &= ~(USB_PORT_STAT_CONNECTION |
379*4882a593Smuzhiyun USB_PORT_STAT_ENABLE);
380*4882a593Smuzhiyun if ((dum_hcd->old_status &
381*4882a593Smuzhiyun USB_PORT_STAT_CONNECTION) != 0)
382*4882a593Smuzhiyun dum_hcd->port_status |=
383*4882a593Smuzhiyun (USB_PORT_STAT_C_CONNECTION << 16);
384*4882a593Smuzhiyun } else {
385*4882a593Smuzhiyun /* device is connected and not suspended */
386*4882a593Smuzhiyun dum_hcd->port_status |= (USB_PORT_STAT_CONNECTION |
387*4882a593Smuzhiyun USB_PORT_STAT_SPEED_5GBPS) ;
388*4882a593Smuzhiyun if ((dum_hcd->old_status &
389*4882a593Smuzhiyun USB_PORT_STAT_CONNECTION) == 0)
390*4882a593Smuzhiyun dum_hcd->port_status |=
391*4882a593Smuzhiyun (USB_PORT_STAT_C_CONNECTION << 16);
392*4882a593Smuzhiyun if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) &&
393*4882a593Smuzhiyun (dum_hcd->port_status &
394*4882a593Smuzhiyun USB_PORT_STAT_LINK_STATE) == USB_SS_PORT_LS_U0 &&
395*4882a593Smuzhiyun dum_hcd->rh_state != DUMMY_RH_SUSPENDED)
396*4882a593Smuzhiyun dum_hcd->active = 1;
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun } else {
399*4882a593Smuzhiyun if ((dum_hcd->port_status & USB_PORT_STAT_POWER) == 0) {
400*4882a593Smuzhiyun dum_hcd->port_status = 0;
401*4882a593Smuzhiyun } else if (!dum->pullup || dum->udc_suspended) {
402*4882a593Smuzhiyun /* UDC suspend must cause a disconnect */
403*4882a593Smuzhiyun dum_hcd->port_status &= ~(USB_PORT_STAT_CONNECTION |
404*4882a593Smuzhiyun USB_PORT_STAT_ENABLE |
405*4882a593Smuzhiyun USB_PORT_STAT_LOW_SPEED |
406*4882a593Smuzhiyun USB_PORT_STAT_HIGH_SPEED |
407*4882a593Smuzhiyun USB_PORT_STAT_SUSPEND);
408*4882a593Smuzhiyun if ((dum_hcd->old_status &
409*4882a593Smuzhiyun USB_PORT_STAT_CONNECTION) != 0)
410*4882a593Smuzhiyun dum_hcd->port_status |=
411*4882a593Smuzhiyun (USB_PORT_STAT_C_CONNECTION << 16);
412*4882a593Smuzhiyun } else {
413*4882a593Smuzhiyun dum_hcd->port_status |= USB_PORT_STAT_CONNECTION;
414*4882a593Smuzhiyun if ((dum_hcd->old_status &
415*4882a593Smuzhiyun USB_PORT_STAT_CONNECTION) == 0)
416*4882a593Smuzhiyun dum_hcd->port_status |=
417*4882a593Smuzhiyun (USB_PORT_STAT_C_CONNECTION << 16);
418*4882a593Smuzhiyun if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) == 0)
419*4882a593Smuzhiyun dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND;
420*4882a593Smuzhiyun else if ((dum_hcd->port_status &
421*4882a593Smuzhiyun USB_PORT_STAT_SUSPEND) == 0 &&
422*4882a593Smuzhiyun dum_hcd->rh_state != DUMMY_RH_SUSPENDED)
423*4882a593Smuzhiyun dum_hcd->active = 1;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun }
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun /* caller must hold lock */
set_link_state(struct dummy_hcd * dum_hcd)429*4882a593Smuzhiyun static void set_link_state(struct dummy_hcd *dum_hcd)
430*4882a593Smuzhiyun __must_hold(&dum->lock)
431*4882a593Smuzhiyun {
432*4882a593Smuzhiyun struct dummy *dum = dum_hcd->dum;
433*4882a593Smuzhiyun unsigned int power_bit;
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun dum_hcd->active = 0;
436*4882a593Smuzhiyun if (dum->pullup)
437*4882a593Smuzhiyun if ((dummy_hcd_to_hcd(dum_hcd)->speed == HCD_USB3 &&
438*4882a593Smuzhiyun dum->gadget.speed != USB_SPEED_SUPER) ||
439*4882a593Smuzhiyun (dummy_hcd_to_hcd(dum_hcd)->speed != HCD_USB3 &&
440*4882a593Smuzhiyun dum->gadget.speed == USB_SPEED_SUPER))
441*4882a593Smuzhiyun return;
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun set_link_state_by_speed(dum_hcd);
444*4882a593Smuzhiyun power_bit = (dummy_hcd_to_hcd(dum_hcd)->speed == HCD_USB3 ?
445*4882a593Smuzhiyun USB_SS_PORT_STAT_POWER : USB_PORT_STAT_POWER);
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) == 0 ||
448*4882a593Smuzhiyun dum_hcd->active)
449*4882a593Smuzhiyun dum_hcd->resuming = 0;
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun /* Currently !connected or in reset */
452*4882a593Smuzhiyun if ((dum_hcd->port_status & power_bit) == 0 ||
453*4882a593Smuzhiyun (dum_hcd->port_status & USB_PORT_STAT_RESET) != 0) {
454*4882a593Smuzhiyun unsigned int disconnect = power_bit &
455*4882a593Smuzhiyun dum_hcd->old_status & (~dum_hcd->port_status);
456*4882a593Smuzhiyun unsigned int reset = USB_PORT_STAT_RESET &
457*4882a593Smuzhiyun (~dum_hcd->old_status) & dum_hcd->port_status;
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun /* Report reset and disconnect events to the driver */
460*4882a593Smuzhiyun if (dum->ints_enabled && (disconnect || reset)) {
461*4882a593Smuzhiyun stop_activity(dum);
462*4882a593Smuzhiyun ++dum->callback_usage;
463*4882a593Smuzhiyun spin_unlock(&dum->lock);
464*4882a593Smuzhiyun if (reset)
465*4882a593Smuzhiyun usb_gadget_udc_reset(&dum->gadget, dum->driver);
466*4882a593Smuzhiyun else
467*4882a593Smuzhiyun dum->driver->disconnect(&dum->gadget);
468*4882a593Smuzhiyun spin_lock(&dum->lock);
469*4882a593Smuzhiyun --dum->callback_usage;
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun } else if (dum_hcd->active != dum_hcd->old_active &&
472*4882a593Smuzhiyun dum->ints_enabled) {
473*4882a593Smuzhiyun ++dum->callback_usage;
474*4882a593Smuzhiyun spin_unlock(&dum->lock);
475*4882a593Smuzhiyun if (dum_hcd->old_active && dum->driver->suspend)
476*4882a593Smuzhiyun dum->driver->suspend(&dum->gadget);
477*4882a593Smuzhiyun else if (!dum_hcd->old_active && dum->driver->resume)
478*4882a593Smuzhiyun dum->driver->resume(&dum->gadget);
479*4882a593Smuzhiyun spin_lock(&dum->lock);
480*4882a593Smuzhiyun --dum->callback_usage;
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun dum_hcd->old_status = dum_hcd->port_status;
484*4882a593Smuzhiyun dum_hcd->old_active = dum_hcd->active;
485*4882a593Smuzhiyun }
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun /* DEVICE/GADGET SIDE DRIVER
490*4882a593Smuzhiyun *
491*4882a593Smuzhiyun * This only tracks gadget state. All the work is done when the host
492*4882a593Smuzhiyun * side tries some (emulated) i/o operation. Real device controller
493*4882a593Smuzhiyun * drivers would do real i/o using dma, fifos, irqs, timers, etc.
494*4882a593Smuzhiyun */
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun #define is_enabled(dum) \
497*4882a593Smuzhiyun (dum->port_status & USB_PORT_STAT_ENABLE)
498*4882a593Smuzhiyun
dummy_enable(struct usb_ep * _ep,const struct usb_endpoint_descriptor * desc)499*4882a593Smuzhiyun static int dummy_enable(struct usb_ep *_ep,
500*4882a593Smuzhiyun const struct usb_endpoint_descriptor *desc)
501*4882a593Smuzhiyun {
502*4882a593Smuzhiyun struct dummy *dum;
503*4882a593Smuzhiyun struct dummy_hcd *dum_hcd;
504*4882a593Smuzhiyun struct dummy_ep *ep;
505*4882a593Smuzhiyun unsigned max;
506*4882a593Smuzhiyun int retval;
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun ep = usb_ep_to_dummy_ep(_ep);
509*4882a593Smuzhiyun if (!_ep || !desc || ep->desc || _ep->name == ep0name
510*4882a593Smuzhiyun || desc->bDescriptorType != USB_DT_ENDPOINT)
511*4882a593Smuzhiyun return -EINVAL;
512*4882a593Smuzhiyun dum = ep_to_dummy(ep);
513*4882a593Smuzhiyun if (!dum->driver)
514*4882a593Smuzhiyun return -ESHUTDOWN;
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
517*4882a593Smuzhiyun if (!is_enabled(dum_hcd))
518*4882a593Smuzhiyun return -ESHUTDOWN;
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun /*
521*4882a593Smuzhiyun * For HS/FS devices only bits 0..10 of the wMaxPacketSize represent the
522*4882a593Smuzhiyun * maximum packet size.
523*4882a593Smuzhiyun * For SS devices the wMaxPacketSize is limited by 1024.
524*4882a593Smuzhiyun */
525*4882a593Smuzhiyun max = usb_endpoint_maxp(desc);
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun /* drivers must not request bad settings, since lower levels
528*4882a593Smuzhiyun * (hardware or its drivers) may not check. some endpoints
529*4882a593Smuzhiyun * can't do iso, many have maxpacket limitations, etc.
530*4882a593Smuzhiyun *
531*4882a593Smuzhiyun * since this "hardware" driver is here to help debugging, we
532*4882a593Smuzhiyun * have some extra sanity checks. (there could be more though,
533*4882a593Smuzhiyun * especially for "ep9out" style fixed function ones.)
534*4882a593Smuzhiyun */
535*4882a593Smuzhiyun retval = -EINVAL;
536*4882a593Smuzhiyun switch (usb_endpoint_type(desc)) {
537*4882a593Smuzhiyun case USB_ENDPOINT_XFER_BULK:
538*4882a593Smuzhiyun if (strstr(ep->ep.name, "-iso")
539*4882a593Smuzhiyun || strstr(ep->ep.name, "-int")) {
540*4882a593Smuzhiyun goto done;
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun switch (dum->gadget.speed) {
543*4882a593Smuzhiyun case USB_SPEED_SUPER:
544*4882a593Smuzhiyun if (max == 1024)
545*4882a593Smuzhiyun break;
546*4882a593Smuzhiyun goto done;
547*4882a593Smuzhiyun case USB_SPEED_HIGH:
548*4882a593Smuzhiyun if (max == 512)
549*4882a593Smuzhiyun break;
550*4882a593Smuzhiyun goto done;
551*4882a593Smuzhiyun case USB_SPEED_FULL:
552*4882a593Smuzhiyun if (max == 8 || max == 16 || max == 32 || max == 64)
553*4882a593Smuzhiyun /* we'll fake any legal size */
554*4882a593Smuzhiyun break;
555*4882a593Smuzhiyun /* save a return statement */
556*4882a593Smuzhiyun default:
557*4882a593Smuzhiyun goto done;
558*4882a593Smuzhiyun }
559*4882a593Smuzhiyun break;
560*4882a593Smuzhiyun case USB_ENDPOINT_XFER_INT:
561*4882a593Smuzhiyun if (strstr(ep->ep.name, "-iso")) /* bulk is ok */
562*4882a593Smuzhiyun goto done;
563*4882a593Smuzhiyun /* real hardware might not handle all packet sizes */
564*4882a593Smuzhiyun switch (dum->gadget.speed) {
565*4882a593Smuzhiyun case USB_SPEED_SUPER:
566*4882a593Smuzhiyun case USB_SPEED_HIGH:
567*4882a593Smuzhiyun if (max <= 1024)
568*4882a593Smuzhiyun break;
569*4882a593Smuzhiyun /* save a return statement */
570*4882a593Smuzhiyun fallthrough;
571*4882a593Smuzhiyun case USB_SPEED_FULL:
572*4882a593Smuzhiyun if (max <= 64)
573*4882a593Smuzhiyun break;
574*4882a593Smuzhiyun /* save a return statement */
575*4882a593Smuzhiyun fallthrough;
576*4882a593Smuzhiyun default:
577*4882a593Smuzhiyun if (max <= 8)
578*4882a593Smuzhiyun break;
579*4882a593Smuzhiyun goto done;
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun break;
582*4882a593Smuzhiyun case USB_ENDPOINT_XFER_ISOC:
583*4882a593Smuzhiyun if (strstr(ep->ep.name, "-bulk")
584*4882a593Smuzhiyun || strstr(ep->ep.name, "-int"))
585*4882a593Smuzhiyun goto done;
586*4882a593Smuzhiyun /* real hardware might not handle all packet sizes */
587*4882a593Smuzhiyun switch (dum->gadget.speed) {
588*4882a593Smuzhiyun case USB_SPEED_SUPER:
589*4882a593Smuzhiyun case USB_SPEED_HIGH:
590*4882a593Smuzhiyun if (max <= 1024)
591*4882a593Smuzhiyun break;
592*4882a593Smuzhiyun /* save a return statement */
593*4882a593Smuzhiyun fallthrough;
594*4882a593Smuzhiyun case USB_SPEED_FULL:
595*4882a593Smuzhiyun if (max <= 1023)
596*4882a593Smuzhiyun break;
597*4882a593Smuzhiyun /* save a return statement */
598*4882a593Smuzhiyun default:
599*4882a593Smuzhiyun goto done;
600*4882a593Smuzhiyun }
601*4882a593Smuzhiyun break;
602*4882a593Smuzhiyun default:
603*4882a593Smuzhiyun /* few chips support control except on ep0 */
604*4882a593Smuzhiyun goto done;
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun _ep->maxpacket = max;
608*4882a593Smuzhiyun if (usb_ss_max_streams(_ep->comp_desc)) {
609*4882a593Smuzhiyun if (!usb_endpoint_xfer_bulk(desc)) {
610*4882a593Smuzhiyun dev_err(udc_dev(dum), "Can't enable stream support on "
611*4882a593Smuzhiyun "non-bulk ep %s\n", _ep->name);
612*4882a593Smuzhiyun return -EINVAL;
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun ep->stream_en = 1;
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun ep->desc = desc;
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun dev_dbg(udc_dev(dum), "enabled %s (ep%d%s-%s) maxpacket %d stream %s\n",
619*4882a593Smuzhiyun _ep->name,
620*4882a593Smuzhiyun desc->bEndpointAddress & 0x0f,
621*4882a593Smuzhiyun (desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
622*4882a593Smuzhiyun usb_ep_type_string(usb_endpoint_type(desc)),
623*4882a593Smuzhiyun max, ep->stream_en ? "enabled" : "disabled");
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun /* at this point real hardware should be NAKing transfers
626*4882a593Smuzhiyun * to that endpoint, until a buffer is queued to it.
627*4882a593Smuzhiyun */
628*4882a593Smuzhiyun ep->halted = ep->wedged = 0;
629*4882a593Smuzhiyun retval = 0;
630*4882a593Smuzhiyun done:
631*4882a593Smuzhiyun return retval;
632*4882a593Smuzhiyun }
633*4882a593Smuzhiyun
dummy_disable(struct usb_ep * _ep)634*4882a593Smuzhiyun static int dummy_disable(struct usb_ep *_ep)
635*4882a593Smuzhiyun {
636*4882a593Smuzhiyun struct dummy_ep *ep;
637*4882a593Smuzhiyun struct dummy *dum;
638*4882a593Smuzhiyun unsigned long flags;
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun ep = usb_ep_to_dummy_ep(_ep);
641*4882a593Smuzhiyun if (!_ep || !ep->desc || _ep->name == ep0name)
642*4882a593Smuzhiyun return -EINVAL;
643*4882a593Smuzhiyun dum = ep_to_dummy(ep);
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun spin_lock_irqsave(&dum->lock, flags);
646*4882a593Smuzhiyun ep->desc = NULL;
647*4882a593Smuzhiyun ep->stream_en = 0;
648*4882a593Smuzhiyun nuke(dum, ep);
649*4882a593Smuzhiyun spin_unlock_irqrestore(&dum->lock, flags);
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun dev_dbg(udc_dev(dum), "disabled %s\n", _ep->name);
652*4882a593Smuzhiyun return 0;
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun
dummy_alloc_request(struct usb_ep * _ep,gfp_t mem_flags)655*4882a593Smuzhiyun static struct usb_request *dummy_alloc_request(struct usb_ep *_ep,
656*4882a593Smuzhiyun gfp_t mem_flags)
657*4882a593Smuzhiyun {
658*4882a593Smuzhiyun struct dummy_request *req;
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun if (!_ep)
661*4882a593Smuzhiyun return NULL;
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun req = kzalloc(sizeof(*req), mem_flags);
664*4882a593Smuzhiyun if (!req)
665*4882a593Smuzhiyun return NULL;
666*4882a593Smuzhiyun INIT_LIST_HEAD(&req->queue);
667*4882a593Smuzhiyun return &req->req;
668*4882a593Smuzhiyun }
669*4882a593Smuzhiyun
dummy_free_request(struct usb_ep * _ep,struct usb_request * _req)670*4882a593Smuzhiyun static void dummy_free_request(struct usb_ep *_ep, struct usb_request *_req)
671*4882a593Smuzhiyun {
672*4882a593Smuzhiyun struct dummy_request *req;
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun if (!_ep || !_req) {
675*4882a593Smuzhiyun WARN_ON(1);
676*4882a593Smuzhiyun return;
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun req = usb_request_to_dummy_request(_req);
680*4882a593Smuzhiyun WARN_ON(!list_empty(&req->queue));
681*4882a593Smuzhiyun kfree(req);
682*4882a593Smuzhiyun }
683*4882a593Smuzhiyun
fifo_complete(struct usb_ep * ep,struct usb_request * req)684*4882a593Smuzhiyun static void fifo_complete(struct usb_ep *ep, struct usb_request *req)
685*4882a593Smuzhiyun {
686*4882a593Smuzhiyun }
687*4882a593Smuzhiyun
dummy_queue(struct usb_ep * _ep,struct usb_request * _req,gfp_t mem_flags)688*4882a593Smuzhiyun static int dummy_queue(struct usb_ep *_ep, struct usb_request *_req,
689*4882a593Smuzhiyun gfp_t mem_flags)
690*4882a593Smuzhiyun {
691*4882a593Smuzhiyun struct dummy_ep *ep;
692*4882a593Smuzhiyun struct dummy_request *req;
693*4882a593Smuzhiyun struct dummy *dum;
694*4882a593Smuzhiyun struct dummy_hcd *dum_hcd;
695*4882a593Smuzhiyun unsigned long flags;
696*4882a593Smuzhiyun
697*4882a593Smuzhiyun req = usb_request_to_dummy_request(_req);
698*4882a593Smuzhiyun if (!_req || !list_empty(&req->queue) || !_req->complete)
699*4882a593Smuzhiyun return -EINVAL;
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun ep = usb_ep_to_dummy_ep(_ep);
702*4882a593Smuzhiyun if (!_ep || (!ep->desc && _ep->name != ep0name))
703*4882a593Smuzhiyun return -EINVAL;
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun dum = ep_to_dummy(ep);
706*4882a593Smuzhiyun dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
707*4882a593Smuzhiyun if (!dum->driver || !is_enabled(dum_hcd))
708*4882a593Smuzhiyun return -ESHUTDOWN;
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun #if 0
711*4882a593Smuzhiyun dev_dbg(udc_dev(dum), "ep %p queue req %p to %s, len %d buf %p\n",
712*4882a593Smuzhiyun ep, _req, _ep->name, _req->length, _req->buf);
713*4882a593Smuzhiyun #endif
714*4882a593Smuzhiyun _req->status = -EINPROGRESS;
715*4882a593Smuzhiyun _req->actual = 0;
716*4882a593Smuzhiyun spin_lock_irqsave(&dum->lock, flags);
717*4882a593Smuzhiyun
718*4882a593Smuzhiyun /* implement an emulated single-request FIFO */
719*4882a593Smuzhiyun if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) &&
720*4882a593Smuzhiyun list_empty(&dum->fifo_req.queue) &&
721*4882a593Smuzhiyun list_empty(&ep->queue) &&
722*4882a593Smuzhiyun _req->length <= FIFO_SIZE) {
723*4882a593Smuzhiyun req = &dum->fifo_req;
724*4882a593Smuzhiyun req->req = *_req;
725*4882a593Smuzhiyun req->req.buf = dum->fifo_buf;
726*4882a593Smuzhiyun memcpy(dum->fifo_buf, _req->buf, _req->length);
727*4882a593Smuzhiyun req->req.context = dum;
728*4882a593Smuzhiyun req->req.complete = fifo_complete;
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun list_add_tail(&req->queue, &ep->queue);
731*4882a593Smuzhiyun spin_unlock(&dum->lock);
732*4882a593Smuzhiyun _req->actual = _req->length;
733*4882a593Smuzhiyun _req->status = 0;
734*4882a593Smuzhiyun usb_gadget_giveback_request(_ep, _req);
735*4882a593Smuzhiyun spin_lock(&dum->lock);
736*4882a593Smuzhiyun } else
737*4882a593Smuzhiyun list_add_tail(&req->queue, &ep->queue);
738*4882a593Smuzhiyun spin_unlock_irqrestore(&dum->lock, flags);
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun /* real hardware would likely enable transfers here, in case
741*4882a593Smuzhiyun * it'd been left NAKing.
742*4882a593Smuzhiyun */
743*4882a593Smuzhiyun return 0;
744*4882a593Smuzhiyun }
745*4882a593Smuzhiyun
dummy_dequeue(struct usb_ep * _ep,struct usb_request * _req)746*4882a593Smuzhiyun static int dummy_dequeue(struct usb_ep *_ep, struct usb_request *_req)
747*4882a593Smuzhiyun {
748*4882a593Smuzhiyun struct dummy_ep *ep;
749*4882a593Smuzhiyun struct dummy *dum;
750*4882a593Smuzhiyun int retval = -EINVAL;
751*4882a593Smuzhiyun unsigned long flags;
752*4882a593Smuzhiyun struct dummy_request *req = NULL;
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun if (!_ep || !_req)
755*4882a593Smuzhiyun return retval;
756*4882a593Smuzhiyun ep = usb_ep_to_dummy_ep(_ep);
757*4882a593Smuzhiyun dum = ep_to_dummy(ep);
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun if (!dum->driver)
760*4882a593Smuzhiyun return -ESHUTDOWN;
761*4882a593Smuzhiyun
762*4882a593Smuzhiyun local_irq_save(flags);
763*4882a593Smuzhiyun spin_lock(&dum->lock);
764*4882a593Smuzhiyun list_for_each_entry(req, &ep->queue, queue) {
765*4882a593Smuzhiyun if (&req->req == _req) {
766*4882a593Smuzhiyun list_del_init(&req->queue);
767*4882a593Smuzhiyun _req->status = -ECONNRESET;
768*4882a593Smuzhiyun retval = 0;
769*4882a593Smuzhiyun break;
770*4882a593Smuzhiyun }
771*4882a593Smuzhiyun }
772*4882a593Smuzhiyun spin_unlock(&dum->lock);
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun if (retval == 0) {
775*4882a593Smuzhiyun dev_dbg(udc_dev(dum),
776*4882a593Smuzhiyun "dequeued req %p from %s, len %d buf %p\n",
777*4882a593Smuzhiyun req, _ep->name, _req->length, _req->buf);
778*4882a593Smuzhiyun usb_gadget_giveback_request(_ep, _req);
779*4882a593Smuzhiyun }
780*4882a593Smuzhiyun local_irq_restore(flags);
781*4882a593Smuzhiyun return retval;
782*4882a593Smuzhiyun }
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun static int
dummy_set_halt_and_wedge(struct usb_ep * _ep,int value,int wedged)785*4882a593Smuzhiyun dummy_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
786*4882a593Smuzhiyun {
787*4882a593Smuzhiyun struct dummy_ep *ep;
788*4882a593Smuzhiyun struct dummy *dum;
789*4882a593Smuzhiyun
790*4882a593Smuzhiyun if (!_ep)
791*4882a593Smuzhiyun return -EINVAL;
792*4882a593Smuzhiyun ep = usb_ep_to_dummy_ep(_ep);
793*4882a593Smuzhiyun dum = ep_to_dummy(ep);
794*4882a593Smuzhiyun if (!dum->driver)
795*4882a593Smuzhiyun return -ESHUTDOWN;
796*4882a593Smuzhiyun if (!value)
797*4882a593Smuzhiyun ep->halted = ep->wedged = 0;
798*4882a593Smuzhiyun else if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) &&
799*4882a593Smuzhiyun !list_empty(&ep->queue))
800*4882a593Smuzhiyun return -EAGAIN;
801*4882a593Smuzhiyun else {
802*4882a593Smuzhiyun ep->halted = 1;
803*4882a593Smuzhiyun if (wedged)
804*4882a593Smuzhiyun ep->wedged = 1;
805*4882a593Smuzhiyun }
806*4882a593Smuzhiyun /* FIXME clear emulated data toggle too */
807*4882a593Smuzhiyun return 0;
808*4882a593Smuzhiyun }
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun static int
dummy_set_halt(struct usb_ep * _ep,int value)811*4882a593Smuzhiyun dummy_set_halt(struct usb_ep *_ep, int value)
812*4882a593Smuzhiyun {
813*4882a593Smuzhiyun return dummy_set_halt_and_wedge(_ep, value, 0);
814*4882a593Smuzhiyun }
815*4882a593Smuzhiyun
dummy_set_wedge(struct usb_ep * _ep)816*4882a593Smuzhiyun static int dummy_set_wedge(struct usb_ep *_ep)
817*4882a593Smuzhiyun {
818*4882a593Smuzhiyun if (!_ep || _ep->name == ep0name)
819*4882a593Smuzhiyun return -EINVAL;
820*4882a593Smuzhiyun return dummy_set_halt_and_wedge(_ep, 1, 1);
821*4882a593Smuzhiyun }
822*4882a593Smuzhiyun
823*4882a593Smuzhiyun static const struct usb_ep_ops dummy_ep_ops = {
824*4882a593Smuzhiyun .enable = dummy_enable,
825*4882a593Smuzhiyun .disable = dummy_disable,
826*4882a593Smuzhiyun
827*4882a593Smuzhiyun .alloc_request = dummy_alloc_request,
828*4882a593Smuzhiyun .free_request = dummy_free_request,
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun .queue = dummy_queue,
831*4882a593Smuzhiyun .dequeue = dummy_dequeue,
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun .set_halt = dummy_set_halt,
834*4882a593Smuzhiyun .set_wedge = dummy_set_wedge,
835*4882a593Smuzhiyun };
836*4882a593Smuzhiyun
837*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun /* there are both host and device side versions of this call ... */
dummy_g_get_frame(struct usb_gadget * _gadget)840*4882a593Smuzhiyun static int dummy_g_get_frame(struct usb_gadget *_gadget)
841*4882a593Smuzhiyun {
842*4882a593Smuzhiyun struct timespec64 ts64;
843*4882a593Smuzhiyun
844*4882a593Smuzhiyun ktime_get_ts64(&ts64);
845*4882a593Smuzhiyun return ts64.tv_nsec / NSEC_PER_MSEC;
846*4882a593Smuzhiyun }
847*4882a593Smuzhiyun
dummy_wakeup(struct usb_gadget * _gadget)848*4882a593Smuzhiyun static int dummy_wakeup(struct usb_gadget *_gadget)
849*4882a593Smuzhiyun {
850*4882a593Smuzhiyun struct dummy_hcd *dum_hcd;
851*4882a593Smuzhiyun
852*4882a593Smuzhiyun dum_hcd = gadget_to_dummy_hcd(_gadget);
853*4882a593Smuzhiyun if (!(dum_hcd->dum->devstatus & ((1 << USB_DEVICE_B_HNP_ENABLE)
854*4882a593Smuzhiyun | (1 << USB_DEVICE_REMOTE_WAKEUP))))
855*4882a593Smuzhiyun return -EINVAL;
856*4882a593Smuzhiyun if ((dum_hcd->port_status & USB_PORT_STAT_CONNECTION) == 0)
857*4882a593Smuzhiyun return -ENOLINK;
858*4882a593Smuzhiyun if ((dum_hcd->port_status & USB_PORT_STAT_SUSPEND) == 0 &&
859*4882a593Smuzhiyun dum_hcd->rh_state != DUMMY_RH_SUSPENDED)
860*4882a593Smuzhiyun return -EIO;
861*4882a593Smuzhiyun
862*4882a593Smuzhiyun /* FIXME: What if the root hub is suspended but the port isn't? */
863*4882a593Smuzhiyun
864*4882a593Smuzhiyun /* hub notices our request, issues downstream resume, etc */
865*4882a593Smuzhiyun dum_hcd->resuming = 1;
866*4882a593Smuzhiyun dum_hcd->re_timeout = jiffies + msecs_to_jiffies(20);
867*4882a593Smuzhiyun mod_timer(&dummy_hcd_to_hcd(dum_hcd)->rh_timer, dum_hcd->re_timeout);
868*4882a593Smuzhiyun return 0;
869*4882a593Smuzhiyun }
870*4882a593Smuzhiyun
dummy_set_selfpowered(struct usb_gadget * _gadget,int value)871*4882a593Smuzhiyun static int dummy_set_selfpowered(struct usb_gadget *_gadget, int value)
872*4882a593Smuzhiyun {
873*4882a593Smuzhiyun struct dummy *dum;
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun _gadget->is_selfpowered = (value != 0);
876*4882a593Smuzhiyun dum = gadget_to_dummy_hcd(_gadget)->dum;
877*4882a593Smuzhiyun if (value)
878*4882a593Smuzhiyun dum->devstatus |= (1 << USB_DEVICE_SELF_POWERED);
879*4882a593Smuzhiyun else
880*4882a593Smuzhiyun dum->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED);
881*4882a593Smuzhiyun return 0;
882*4882a593Smuzhiyun }
883*4882a593Smuzhiyun
dummy_udc_update_ep0(struct dummy * dum)884*4882a593Smuzhiyun static void dummy_udc_update_ep0(struct dummy *dum)
885*4882a593Smuzhiyun {
886*4882a593Smuzhiyun if (dum->gadget.speed == USB_SPEED_SUPER)
887*4882a593Smuzhiyun dum->ep[0].ep.maxpacket = 9;
888*4882a593Smuzhiyun else
889*4882a593Smuzhiyun dum->ep[0].ep.maxpacket = 64;
890*4882a593Smuzhiyun }
891*4882a593Smuzhiyun
dummy_pullup(struct usb_gadget * _gadget,int value)892*4882a593Smuzhiyun static int dummy_pullup(struct usb_gadget *_gadget, int value)
893*4882a593Smuzhiyun {
894*4882a593Smuzhiyun struct dummy_hcd *dum_hcd;
895*4882a593Smuzhiyun struct dummy *dum;
896*4882a593Smuzhiyun unsigned long flags;
897*4882a593Smuzhiyun
898*4882a593Smuzhiyun dum = gadget_dev_to_dummy(&_gadget->dev);
899*4882a593Smuzhiyun dum_hcd = gadget_to_dummy_hcd(_gadget);
900*4882a593Smuzhiyun
901*4882a593Smuzhiyun spin_lock_irqsave(&dum->lock, flags);
902*4882a593Smuzhiyun dum->pullup = (value != 0);
903*4882a593Smuzhiyun set_link_state(dum_hcd);
904*4882a593Smuzhiyun if (value == 0) {
905*4882a593Smuzhiyun /*
906*4882a593Smuzhiyun * Emulate synchronize_irq(): wait for callbacks to finish.
907*4882a593Smuzhiyun * This seems to be the best place to emulate the call to
908*4882a593Smuzhiyun * synchronize_irq() that's in usb_gadget_remove_driver().
909*4882a593Smuzhiyun * Doing it in dummy_udc_stop() would be too late since it
910*4882a593Smuzhiyun * is called after the unbind callback and unbind shouldn't
911*4882a593Smuzhiyun * be invoked until all the other callbacks are finished.
912*4882a593Smuzhiyun */
913*4882a593Smuzhiyun while (dum->callback_usage > 0) {
914*4882a593Smuzhiyun spin_unlock_irqrestore(&dum->lock, flags);
915*4882a593Smuzhiyun usleep_range(1000, 2000);
916*4882a593Smuzhiyun spin_lock_irqsave(&dum->lock, flags);
917*4882a593Smuzhiyun }
918*4882a593Smuzhiyun }
919*4882a593Smuzhiyun spin_unlock_irqrestore(&dum->lock, flags);
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd));
922*4882a593Smuzhiyun return 0;
923*4882a593Smuzhiyun }
924*4882a593Smuzhiyun
dummy_udc_set_speed(struct usb_gadget * _gadget,enum usb_device_speed speed)925*4882a593Smuzhiyun static void dummy_udc_set_speed(struct usb_gadget *_gadget,
926*4882a593Smuzhiyun enum usb_device_speed speed)
927*4882a593Smuzhiyun {
928*4882a593Smuzhiyun struct dummy *dum;
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun dum = gadget_dev_to_dummy(&_gadget->dev);
931*4882a593Smuzhiyun dum->gadget.speed = speed;
932*4882a593Smuzhiyun dummy_udc_update_ep0(dum);
933*4882a593Smuzhiyun }
934*4882a593Smuzhiyun
935*4882a593Smuzhiyun static int dummy_udc_start(struct usb_gadget *g,
936*4882a593Smuzhiyun struct usb_gadget_driver *driver);
937*4882a593Smuzhiyun static int dummy_udc_stop(struct usb_gadget *g);
938*4882a593Smuzhiyun
939*4882a593Smuzhiyun static const struct usb_gadget_ops dummy_ops = {
940*4882a593Smuzhiyun .get_frame = dummy_g_get_frame,
941*4882a593Smuzhiyun .wakeup = dummy_wakeup,
942*4882a593Smuzhiyun .set_selfpowered = dummy_set_selfpowered,
943*4882a593Smuzhiyun .pullup = dummy_pullup,
944*4882a593Smuzhiyun .udc_start = dummy_udc_start,
945*4882a593Smuzhiyun .udc_stop = dummy_udc_stop,
946*4882a593Smuzhiyun .udc_set_speed = dummy_udc_set_speed,
947*4882a593Smuzhiyun };
948*4882a593Smuzhiyun
949*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
950*4882a593Smuzhiyun
951*4882a593Smuzhiyun /* "function" sysfs attribute */
function_show(struct device * dev,struct device_attribute * attr,char * buf)952*4882a593Smuzhiyun static ssize_t function_show(struct device *dev, struct device_attribute *attr,
953*4882a593Smuzhiyun char *buf)
954*4882a593Smuzhiyun {
955*4882a593Smuzhiyun struct dummy *dum = gadget_dev_to_dummy(dev);
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun if (!dum->driver || !dum->driver->function)
958*4882a593Smuzhiyun return 0;
959*4882a593Smuzhiyun return scnprintf(buf, PAGE_SIZE, "%s\n", dum->driver->function);
960*4882a593Smuzhiyun }
961*4882a593Smuzhiyun static DEVICE_ATTR_RO(function);
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
964*4882a593Smuzhiyun
965*4882a593Smuzhiyun /*
966*4882a593Smuzhiyun * Driver registration/unregistration.
967*4882a593Smuzhiyun *
968*4882a593Smuzhiyun * This is basically hardware-specific; there's usually only one real USB
969*4882a593Smuzhiyun * device (not host) controller since that's how USB devices are intended
970*4882a593Smuzhiyun * to work. So most implementations of these api calls will rely on the
971*4882a593Smuzhiyun * fact that only one driver will ever bind to the hardware. But curious
972*4882a593Smuzhiyun * hardware can be built with discrete components, so the gadget API doesn't
973*4882a593Smuzhiyun * require that assumption.
974*4882a593Smuzhiyun *
975*4882a593Smuzhiyun * For this emulator, it might be convenient to create a usb device
976*4882a593Smuzhiyun * for each driver that registers: just add to a big root hub.
977*4882a593Smuzhiyun */
978*4882a593Smuzhiyun
dummy_udc_start(struct usb_gadget * g,struct usb_gadget_driver * driver)979*4882a593Smuzhiyun static int dummy_udc_start(struct usb_gadget *g,
980*4882a593Smuzhiyun struct usb_gadget_driver *driver)
981*4882a593Smuzhiyun {
982*4882a593Smuzhiyun struct dummy_hcd *dum_hcd = gadget_to_dummy_hcd(g);
983*4882a593Smuzhiyun struct dummy *dum = dum_hcd->dum;
984*4882a593Smuzhiyun
985*4882a593Smuzhiyun switch (g->speed) {
986*4882a593Smuzhiyun /* All the speeds we support */
987*4882a593Smuzhiyun case USB_SPEED_LOW:
988*4882a593Smuzhiyun case USB_SPEED_FULL:
989*4882a593Smuzhiyun case USB_SPEED_HIGH:
990*4882a593Smuzhiyun case USB_SPEED_SUPER:
991*4882a593Smuzhiyun break;
992*4882a593Smuzhiyun default:
993*4882a593Smuzhiyun dev_err(dummy_dev(dum_hcd), "Unsupported driver max speed %d\n",
994*4882a593Smuzhiyun driver->max_speed);
995*4882a593Smuzhiyun return -EINVAL;
996*4882a593Smuzhiyun }
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun /*
999*4882a593Smuzhiyun * DEVICE side init ... the layer above hardware, which
1000*4882a593Smuzhiyun * can't enumerate without help from the driver we're binding.
1001*4882a593Smuzhiyun */
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun spin_lock_irq(&dum->lock);
1004*4882a593Smuzhiyun dum->devstatus = 0;
1005*4882a593Smuzhiyun dum->driver = driver;
1006*4882a593Smuzhiyun dum->ints_enabled = 1;
1007*4882a593Smuzhiyun spin_unlock_irq(&dum->lock);
1008*4882a593Smuzhiyun
1009*4882a593Smuzhiyun return 0;
1010*4882a593Smuzhiyun }
1011*4882a593Smuzhiyun
dummy_udc_stop(struct usb_gadget * g)1012*4882a593Smuzhiyun static int dummy_udc_stop(struct usb_gadget *g)
1013*4882a593Smuzhiyun {
1014*4882a593Smuzhiyun struct dummy_hcd *dum_hcd = gadget_to_dummy_hcd(g);
1015*4882a593Smuzhiyun struct dummy *dum = dum_hcd->dum;
1016*4882a593Smuzhiyun
1017*4882a593Smuzhiyun spin_lock_irq(&dum->lock);
1018*4882a593Smuzhiyun dum->ints_enabled = 0;
1019*4882a593Smuzhiyun stop_activity(dum);
1020*4882a593Smuzhiyun dum->driver = NULL;
1021*4882a593Smuzhiyun spin_unlock_irq(&dum->lock);
1022*4882a593Smuzhiyun
1023*4882a593Smuzhiyun return 0;
1024*4882a593Smuzhiyun }
1025*4882a593Smuzhiyun
1026*4882a593Smuzhiyun #undef is_enabled
1027*4882a593Smuzhiyun
1028*4882a593Smuzhiyun /* The gadget structure is stored inside the hcd structure and will be
1029*4882a593Smuzhiyun * released along with it. */
init_dummy_udc_hw(struct dummy * dum)1030*4882a593Smuzhiyun static void init_dummy_udc_hw(struct dummy *dum)
1031*4882a593Smuzhiyun {
1032*4882a593Smuzhiyun int i;
1033*4882a593Smuzhiyun
1034*4882a593Smuzhiyun INIT_LIST_HEAD(&dum->gadget.ep_list);
1035*4882a593Smuzhiyun for (i = 0; i < DUMMY_ENDPOINTS; i++) {
1036*4882a593Smuzhiyun struct dummy_ep *ep = &dum->ep[i];
1037*4882a593Smuzhiyun
1038*4882a593Smuzhiyun if (!ep_info[i].name)
1039*4882a593Smuzhiyun break;
1040*4882a593Smuzhiyun ep->ep.name = ep_info[i].name;
1041*4882a593Smuzhiyun ep->ep.caps = ep_info[i].caps;
1042*4882a593Smuzhiyun ep->ep.ops = &dummy_ep_ops;
1043*4882a593Smuzhiyun list_add_tail(&ep->ep.ep_list, &dum->gadget.ep_list);
1044*4882a593Smuzhiyun ep->halted = ep->wedged = ep->already_seen =
1045*4882a593Smuzhiyun ep->setup_stage = 0;
1046*4882a593Smuzhiyun usb_ep_set_maxpacket_limit(&ep->ep, ~0);
1047*4882a593Smuzhiyun ep->ep.max_streams = 16;
1048*4882a593Smuzhiyun ep->last_io = jiffies;
1049*4882a593Smuzhiyun ep->gadget = &dum->gadget;
1050*4882a593Smuzhiyun ep->desc = NULL;
1051*4882a593Smuzhiyun INIT_LIST_HEAD(&ep->queue);
1052*4882a593Smuzhiyun }
1053*4882a593Smuzhiyun
1054*4882a593Smuzhiyun dum->gadget.ep0 = &dum->ep[0].ep;
1055*4882a593Smuzhiyun list_del_init(&dum->ep[0].ep.ep_list);
1056*4882a593Smuzhiyun INIT_LIST_HEAD(&dum->fifo_req.queue);
1057*4882a593Smuzhiyun
1058*4882a593Smuzhiyun #ifdef CONFIG_USB_OTG
1059*4882a593Smuzhiyun dum->gadget.is_otg = 1;
1060*4882a593Smuzhiyun #endif
1061*4882a593Smuzhiyun }
1062*4882a593Smuzhiyun
dummy_udc_probe(struct platform_device * pdev)1063*4882a593Smuzhiyun static int dummy_udc_probe(struct platform_device *pdev)
1064*4882a593Smuzhiyun {
1065*4882a593Smuzhiyun struct dummy *dum;
1066*4882a593Smuzhiyun int rc;
1067*4882a593Smuzhiyun
1068*4882a593Smuzhiyun dum = *((void **)dev_get_platdata(&pdev->dev));
1069*4882a593Smuzhiyun /* Clear usb_gadget region for new registration to udc-core */
1070*4882a593Smuzhiyun memzero_explicit(&dum->gadget, sizeof(struct usb_gadget));
1071*4882a593Smuzhiyun dum->gadget.name = gadget_name;
1072*4882a593Smuzhiyun dum->gadget.ops = &dummy_ops;
1073*4882a593Smuzhiyun if (mod_data.is_super_speed)
1074*4882a593Smuzhiyun dum->gadget.max_speed = USB_SPEED_SUPER;
1075*4882a593Smuzhiyun else if (mod_data.is_high_speed)
1076*4882a593Smuzhiyun dum->gadget.max_speed = USB_SPEED_HIGH;
1077*4882a593Smuzhiyun else
1078*4882a593Smuzhiyun dum->gadget.max_speed = USB_SPEED_FULL;
1079*4882a593Smuzhiyun
1080*4882a593Smuzhiyun dum->gadget.dev.parent = &pdev->dev;
1081*4882a593Smuzhiyun init_dummy_udc_hw(dum);
1082*4882a593Smuzhiyun
1083*4882a593Smuzhiyun rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget);
1084*4882a593Smuzhiyun if (rc < 0)
1085*4882a593Smuzhiyun goto err_udc;
1086*4882a593Smuzhiyun
1087*4882a593Smuzhiyun rc = device_create_file(&dum->gadget.dev, &dev_attr_function);
1088*4882a593Smuzhiyun if (rc < 0)
1089*4882a593Smuzhiyun goto err_dev;
1090*4882a593Smuzhiyun platform_set_drvdata(pdev, dum);
1091*4882a593Smuzhiyun return rc;
1092*4882a593Smuzhiyun
1093*4882a593Smuzhiyun err_dev:
1094*4882a593Smuzhiyun usb_del_gadget_udc(&dum->gadget);
1095*4882a593Smuzhiyun err_udc:
1096*4882a593Smuzhiyun return rc;
1097*4882a593Smuzhiyun }
1098*4882a593Smuzhiyun
dummy_udc_remove(struct platform_device * pdev)1099*4882a593Smuzhiyun static int dummy_udc_remove(struct platform_device *pdev)
1100*4882a593Smuzhiyun {
1101*4882a593Smuzhiyun struct dummy *dum = platform_get_drvdata(pdev);
1102*4882a593Smuzhiyun
1103*4882a593Smuzhiyun device_remove_file(&dum->gadget.dev, &dev_attr_function);
1104*4882a593Smuzhiyun usb_del_gadget_udc(&dum->gadget);
1105*4882a593Smuzhiyun return 0;
1106*4882a593Smuzhiyun }
1107*4882a593Smuzhiyun
dummy_udc_pm(struct dummy * dum,struct dummy_hcd * dum_hcd,int suspend)1108*4882a593Smuzhiyun static void dummy_udc_pm(struct dummy *dum, struct dummy_hcd *dum_hcd,
1109*4882a593Smuzhiyun int suspend)
1110*4882a593Smuzhiyun {
1111*4882a593Smuzhiyun spin_lock_irq(&dum->lock);
1112*4882a593Smuzhiyun dum->udc_suspended = suspend;
1113*4882a593Smuzhiyun set_link_state(dum_hcd);
1114*4882a593Smuzhiyun spin_unlock_irq(&dum->lock);
1115*4882a593Smuzhiyun }
1116*4882a593Smuzhiyun
dummy_udc_suspend(struct platform_device * pdev,pm_message_t state)1117*4882a593Smuzhiyun static int dummy_udc_suspend(struct platform_device *pdev, pm_message_t state)
1118*4882a593Smuzhiyun {
1119*4882a593Smuzhiyun struct dummy *dum = platform_get_drvdata(pdev);
1120*4882a593Smuzhiyun struct dummy_hcd *dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
1121*4882a593Smuzhiyun
1122*4882a593Smuzhiyun dev_dbg(&pdev->dev, "%s\n", __func__);
1123*4882a593Smuzhiyun dummy_udc_pm(dum, dum_hcd, 1);
1124*4882a593Smuzhiyun usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd));
1125*4882a593Smuzhiyun return 0;
1126*4882a593Smuzhiyun }
1127*4882a593Smuzhiyun
dummy_udc_resume(struct platform_device * pdev)1128*4882a593Smuzhiyun static int dummy_udc_resume(struct platform_device *pdev)
1129*4882a593Smuzhiyun {
1130*4882a593Smuzhiyun struct dummy *dum = platform_get_drvdata(pdev);
1131*4882a593Smuzhiyun struct dummy_hcd *dum_hcd = gadget_to_dummy_hcd(&dum->gadget);
1132*4882a593Smuzhiyun
1133*4882a593Smuzhiyun dev_dbg(&pdev->dev, "%s\n", __func__);
1134*4882a593Smuzhiyun dummy_udc_pm(dum, dum_hcd, 0);
1135*4882a593Smuzhiyun usb_hcd_poll_rh_status(dummy_hcd_to_hcd(dum_hcd));
1136*4882a593Smuzhiyun return 0;
1137*4882a593Smuzhiyun }
1138*4882a593Smuzhiyun
1139*4882a593Smuzhiyun static struct platform_driver dummy_udc_driver = {
1140*4882a593Smuzhiyun .probe = dummy_udc_probe,
1141*4882a593Smuzhiyun .remove = dummy_udc_remove,
1142*4882a593Smuzhiyun .suspend = dummy_udc_suspend,
1143*4882a593Smuzhiyun .resume = dummy_udc_resume,
1144*4882a593Smuzhiyun .driver = {
1145*4882a593Smuzhiyun .name = gadget_name,
1146*4882a593Smuzhiyun },
1147*4882a593Smuzhiyun };
1148*4882a593Smuzhiyun
1149*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
1150*4882a593Smuzhiyun
dummy_get_ep_idx(const struct usb_endpoint_descriptor * desc)1151*4882a593Smuzhiyun static unsigned int dummy_get_ep_idx(const struct usb_endpoint_descriptor *desc)
1152*4882a593Smuzhiyun {
1153*4882a593Smuzhiyun unsigned int index;
1154*4882a593Smuzhiyun
1155*4882a593Smuzhiyun index = usb_endpoint_num(desc) << 1;
1156*4882a593Smuzhiyun if (usb_endpoint_dir_in(desc))
1157*4882a593Smuzhiyun index |= 1;
1158*4882a593Smuzhiyun return index;
1159*4882a593Smuzhiyun }
1160*4882a593Smuzhiyun
1161*4882a593Smuzhiyun /* HOST SIDE DRIVER
1162*4882a593Smuzhiyun *
1163*4882a593Smuzhiyun * this uses the hcd framework to hook up to host side drivers.
1164*4882a593Smuzhiyun * its root hub will only have one device, otherwise it acts like
1165*4882a593Smuzhiyun * a normal host controller.
1166*4882a593Smuzhiyun *
1167*4882a593Smuzhiyun * when urbs are queued, they're just stuck on a list that we
1168*4882a593Smuzhiyun * scan in a timer callback. that callback connects writes from
1169*4882a593Smuzhiyun * the host with reads from the device, and so on, based on the
1170*4882a593Smuzhiyun * usb 2.0 rules.
1171*4882a593Smuzhiyun */
1172*4882a593Smuzhiyun
dummy_ep_stream_en(struct dummy_hcd * dum_hcd,struct urb * urb)1173*4882a593Smuzhiyun static int dummy_ep_stream_en(struct dummy_hcd *dum_hcd, struct urb *urb)
1174*4882a593Smuzhiyun {
1175*4882a593Smuzhiyun const struct usb_endpoint_descriptor *desc = &urb->ep->desc;
1176*4882a593Smuzhiyun u32 index;
1177*4882a593Smuzhiyun
1178*4882a593Smuzhiyun if (!usb_endpoint_xfer_bulk(desc))
1179*4882a593Smuzhiyun return 0;
1180*4882a593Smuzhiyun
1181*4882a593Smuzhiyun index = dummy_get_ep_idx(desc);
1182*4882a593Smuzhiyun return (1 << index) & dum_hcd->stream_en_ep;
1183*4882a593Smuzhiyun }
1184*4882a593Smuzhiyun
1185*4882a593Smuzhiyun /*
1186*4882a593Smuzhiyun * The max stream number is saved as a nibble so for the 30 possible endpoints
1187*4882a593Smuzhiyun * we only 15 bytes of memory. Therefore we are limited to max 16 streams (0
1188*4882a593Smuzhiyun * means we use only 1 stream). The maximum according to the spec is 16bit so
1189*4882a593Smuzhiyun * if the 16 stream limit is about to go, the array size should be incremented
1190*4882a593Smuzhiyun * to 30 elements of type u16.
1191*4882a593Smuzhiyun */
get_max_streams_for_pipe(struct dummy_hcd * dum_hcd,unsigned int pipe)1192*4882a593Smuzhiyun static int get_max_streams_for_pipe(struct dummy_hcd *dum_hcd,
1193*4882a593Smuzhiyun unsigned int pipe)
1194*4882a593Smuzhiyun {
1195*4882a593Smuzhiyun int max_streams;
1196*4882a593Smuzhiyun
1197*4882a593Smuzhiyun max_streams = dum_hcd->num_stream[usb_pipeendpoint(pipe)];
1198*4882a593Smuzhiyun if (usb_pipeout(pipe))
1199*4882a593Smuzhiyun max_streams >>= 4;
1200*4882a593Smuzhiyun else
1201*4882a593Smuzhiyun max_streams &= 0xf;
1202*4882a593Smuzhiyun max_streams++;
1203*4882a593Smuzhiyun return max_streams;
1204*4882a593Smuzhiyun }
1205*4882a593Smuzhiyun
set_max_streams_for_pipe(struct dummy_hcd * dum_hcd,unsigned int pipe,unsigned int streams)1206*4882a593Smuzhiyun static void set_max_streams_for_pipe(struct dummy_hcd *dum_hcd,
1207*4882a593Smuzhiyun unsigned int pipe, unsigned int streams)
1208*4882a593Smuzhiyun {
1209*4882a593Smuzhiyun int max_streams;
1210*4882a593Smuzhiyun
1211*4882a593Smuzhiyun streams--;
1212*4882a593Smuzhiyun max_streams = dum_hcd->num_stream[usb_pipeendpoint(pipe)];
1213*4882a593Smuzhiyun if (usb_pipeout(pipe)) {
1214*4882a593Smuzhiyun streams <<= 4;
1215*4882a593Smuzhiyun max_streams &= 0xf;
1216*4882a593Smuzhiyun } else {
1217*4882a593Smuzhiyun max_streams &= 0xf0;
1218*4882a593Smuzhiyun }
1219*4882a593Smuzhiyun max_streams |= streams;
1220*4882a593Smuzhiyun dum_hcd->num_stream[usb_pipeendpoint(pipe)] = max_streams;
1221*4882a593Smuzhiyun }
1222*4882a593Smuzhiyun
dummy_validate_stream(struct dummy_hcd * dum_hcd,struct urb * urb)1223*4882a593Smuzhiyun static int dummy_validate_stream(struct dummy_hcd *dum_hcd, struct urb *urb)
1224*4882a593Smuzhiyun {
1225*4882a593Smuzhiyun unsigned int max_streams;
1226*4882a593Smuzhiyun int enabled;
1227*4882a593Smuzhiyun
1228*4882a593Smuzhiyun enabled = dummy_ep_stream_en(dum_hcd, urb);
1229*4882a593Smuzhiyun if (!urb->stream_id) {
1230*4882a593Smuzhiyun if (enabled)
1231*4882a593Smuzhiyun return -EINVAL;
1232*4882a593Smuzhiyun return 0;
1233*4882a593Smuzhiyun }
1234*4882a593Smuzhiyun if (!enabled)
1235*4882a593Smuzhiyun return -EINVAL;
1236*4882a593Smuzhiyun
1237*4882a593Smuzhiyun max_streams = get_max_streams_for_pipe(dum_hcd,
1238*4882a593Smuzhiyun usb_pipeendpoint(urb->pipe));
1239*4882a593Smuzhiyun if (urb->stream_id > max_streams) {
1240*4882a593Smuzhiyun dev_err(dummy_dev(dum_hcd), "Stream id %d is out of range.\n",
1241*4882a593Smuzhiyun urb->stream_id);
1242*4882a593Smuzhiyun BUG();
1243*4882a593Smuzhiyun return -EINVAL;
1244*4882a593Smuzhiyun }
1245*4882a593Smuzhiyun return 0;
1246*4882a593Smuzhiyun }
1247*4882a593Smuzhiyun
dummy_urb_enqueue(struct usb_hcd * hcd,struct urb * urb,gfp_t mem_flags)1248*4882a593Smuzhiyun static int dummy_urb_enqueue(
1249*4882a593Smuzhiyun struct usb_hcd *hcd,
1250*4882a593Smuzhiyun struct urb *urb,
1251*4882a593Smuzhiyun gfp_t mem_flags
1252*4882a593Smuzhiyun ) {
1253*4882a593Smuzhiyun struct dummy_hcd *dum_hcd;
1254*4882a593Smuzhiyun struct urbp *urbp;
1255*4882a593Smuzhiyun unsigned long flags;
1256*4882a593Smuzhiyun int rc;
1257*4882a593Smuzhiyun
1258*4882a593Smuzhiyun urbp = kmalloc(sizeof *urbp, mem_flags);
1259*4882a593Smuzhiyun if (!urbp)
1260*4882a593Smuzhiyun return -ENOMEM;
1261*4882a593Smuzhiyun urbp->urb = urb;
1262*4882a593Smuzhiyun urbp->miter_started = 0;
1263*4882a593Smuzhiyun
1264*4882a593Smuzhiyun dum_hcd = hcd_to_dummy_hcd(hcd);
1265*4882a593Smuzhiyun spin_lock_irqsave(&dum_hcd->dum->lock, flags);
1266*4882a593Smuzhiyun
1267*4882a593Smuzhiyun rc = dummy_validate_stream(dum_hcd, urb);
1268*4882a593Smuzhiyun if (rc) {
1269*4882a593Smuzhiyun kfree(urbp);
1270*4882a593Smuzhiyun goto done;
1271*4882a593Smuzhiyun }
1272*4882a593Smuzhiyun
1273*4882a593Smuzhiyun rc = usb_hcd_link_urb_to_ep(hcd, urb);
1274*4882a593Smuzhiyun if (rc) {
1275*4882a593Smuzhiyun kfree(urbp);
1276*4882a593Smuzhiyun goto done;
1277*4882a593Smuzhiyun }
1278*4882a593Smuzhiyun
1279*4882a593Smuzhiyun if (!dum_hcd->udev) {
1280*4882a593Smuzhiyun dum_hcd->udev = urb->dev;
1281*4882a593Smuzhiyun usb_get_dev(dum_hcd->udev);
1282*4882a593Smuzhiyun } else if (unlikely(dum_hcd->udev != urb->dev))
1283*4882a593Smuzhiyun dev_err(dummy_dev(dum_hcd), "usb_device address has changed!\n");
1284*4882a593Smuzhiyun
1285*4882a593Smuzhiyun list_add_tail(&urbp->urbp_list, &dum_hcd->urbp_list);
1286*4882a593Smuzhiyun urb->hcpriv = urbp;
1287*4882a593Smuzhiyun if (!dum_hcd->next_frame_urbp)
1288*4882a593Smuzhiyun dum_hcd->next_frame_urbp = urbp;
1289*4882a593Smuzhiyun if (usb_pipetype(urb->pipe) == PIPE_CONTROL)
1290*4882a593Smuzhiyun urb->error_count = 1; /* mark as a new urb */
1291*4882a593Smuzhiyun
1292*4882a593Smuzhiyun /* kick the scheduler, it'll do the rest */
1293*4882a593Smuzhiyun if (!timer_pending(&dum_hcd->timer))
1294*4882a593Smuzhiyun mod_timer(&dum_hcd->timer, jiffies + 1);
1295*4882a593Smuzhiyun
1296*4882a593Smuzhiyun done:
1297*4882a593Smuzhiyun spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
1298*4882a593Smuzhiyun return rc;
1299*4882a593Smuzhiyun }
1300*4882a593Smuzhiyun
dummy_urb_dequeue(struct usb_hcd * hcd,struct urb * urb,int status)1301*4882a593Smuzhiyun static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
1302*4882a593Smuzhiyun {
1303*4882a593Smuzhiyun struct dummy_hcd *dum_hcd;
1304*4882a593Smuzhiyun unsigned long flags;
1305*4882a593Smuzhiyun int rc;
1306*4882a593Smuzhiyun
1307*4882a593Smuzhiyun /* giveback happens automatically in timer callback,
1308*4882a593Smuzhiyun * so make sure the callback happens */
1309*4882a593Smuzhiyun dum_hcd = hcd_to_dummy_hcd(hcd);
1310*4882a593Smuzhiyun spin_lock_irqsave(&dum_hcd->dum->lock, flags);
1311*4882a593Smuzhiyun
1312*4882a593Smuzhiyun rc = usb_hcd_check_unlink_urb(hcd, urb, status);
1313*4882a593Smuzhiyun if (!rc && dum_hcd->rh_state != DUMMY_RH_RUNNING &&
1314*4882a593Smuzhiyun !list_empty(&dum_hcd->urbp_list))
1315*4882a593Smuzhiyun mod_timer(&dum_hcd->timer, jiffies);
1316*4882a593Smuzhiyun
1317*4882a593Smuzhiyun spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
1318*4882a593Smuzhiyun return rc;
1319*4882a593Smuzhiyun }
1320*4882a593Smuzhiyun
dummy_perform_transfer(struct urb * urb,struct dummy_request * req,u32 len)1321*4882a593Smuzhiyun static int dummy_perform_transfer(struct urb *urb, struct dummy_request *req,
1322*4882a593Smuzhiyun u32 len)
1323*4882a593Smuzhiyun {
1324*4882a593Smuzhiyun void *ubuf, *rbuf;
1325*4882a593Smuzhiyun struct urbp *urbp = urb->hcpriv;
1326*4882a593Smuzhiyun int to_host;
1327*4882a593Smuzhiyun struct sg_mapping_iter *miter = &urbp->miter;
1328*4882a593Smuzhiyun u32 trans = 0;
1329*4882a593Smuzhiyun u32 this_sg;
1330*4882a593Smuzhiyun bool next_sg;
1331*4882a593Smuzhiyun
1332*4882a593Smuzhiyun to_host = usb_urb_dir_in(urb);
1333*4882a593Smuzhiyun rbuf = req->req.buf + req->req.actual;
1334*4882a593Smuzhiyun
1335*4882a593Smuzhiyun if (!urb->num_sgs) {
1336*4882a593Smuzhiyun ubuf = urb->transfer_buffer + urb->actual_length;
1337*4882a593Smuzhiyun if (to_host)
1338*4882a593Smuzhiyun memcpy(ubuf, rbuf, len);
1339*4882a593Smuzhiyun else
1340*4882a593Smuzhiyun memcpy(rbuf, ubuf, len);
1341*4882a593Smuzhiyun return len;
1342*4882a593Smuzhiyun }
1343*4882a593Smuzhiyun
1344*4882a593Smuzhiyun if (!urbp->miter_started) {
1345*4882a593Smuzhiyun u32 flags = SG_MITER_ATOMIC;
1346*4882a593Smuzhiyun
1347*4882a593Smuzhiyun if (to_host)
1348*4882a593Smuzhiyun flags |= SG_MITER_TO_SG;
1349*4882a593Smuzhiyun else
1350*4882a593Smuzhiyun flags |= SG_MITER_FROM_SG;
1351*4882a593Smuzhiyun
1352*4882a593Smuzhiyun sg_miter_start(miter, urb->sg, urb->num_sgs, flags);
1353*4882a593Smuzhiyun urbp->miter_started = 1;
1354*4882a593Smuzhiyun }
1355*4882a593Smuzhiyun next_sg = sg_miter_next(miter);
1356*4882a593Smuzhiyun if (next_sg == false) {
1357*4882a593Smuzhiyun WARN_ON_ONCE(1);
1358*4882a593Smuzhiyun return -EINVAL;
1359*4882a593Smuzhiyun }
1360*4882a593Smuzhiyun do {
1361*4882a593Smuzhiyun ubuf = miter->addr;
1362*4882a593Smuzhiyun this_sg = min_t(u32, len, miter->length);
1363*4882a593Smuzhiyun miter->consumed = this_sg;
1364*4882a593Smuzhiyun trans += this_sg;
1365*4882a593Smuzhiyun
1366*4882a593Smuzhiyun if (to_host)
1367*4882a593Smuzhiyun memcpy(ubuf, rbuf, this_sg);
1368*4882a593Smuzhiyun else
1369*4882a593Smuzhiyun memcpy(rbuf, ubuf, this_sg);
1370*4882a593Smuzhiyun len -= this_sg;
1371*4882a593Smuzhiyun
1372*4882a593Smuzhiyun if (!len)
1373*4882a593Smuzhiyun break;
1374*4882a593Smuzhiyun next_sg = sg_miter_next(miter);
1375*4882a593Smuzhiyun if (next_sg == false) {
1376*4882a593Smuzhiyun WARN_ON_ONCE(1);
1377*4882a593Smuzhiyun return -EINVAL;
1378*4882a593Smuzhiyun }
1379*4882a593Smuzhiyun
1380*4882a593Smuzhiyun rbuf += this_sg;
1381*4882a593Smuzhiyun } while (1);
1382*4882a593Smuzhiyun
1383*4882a593Smuzhiyun sg_miter_stop(miter);
1384*4882a593Smuzhiyun return trans;
1385*4882a593Smuzhiyun }
1386*4882a593Smuzhiyun
1387*4882a593Smuzhiyun /* transfer up to a frame's worth; caller must own lock */
transfer(struct dummy_hcd * dum_hcd,struct urb * urb,struct dummy_ep * ep,int limit,int * status)1388*4882a593Smuzhiyun static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb,
1389*4882a593Smuzhiyun struct dummy_ep *ep, int limit, int *status)
1390*4882a593Smuzhiyun {
1391*4882a593Smuzhiyun struct dummy *dum = dum_hcd->dum;
1392*4882a593Smuzhiyun struct dummy_request *req;
1393*4882a593Smuzhiyun int sent = 0;
1394*4882a593Smuzhiyun
1395*4882a593Smuzhiyun top:
1396*4882a593Smuzhiyun /* if there's no request queued, the device is NAKing; return */
1397*4882a593Smuzhiyun list_for_each_entry(req, &ep->queue, queue) {
1398*4882a593Smuzhiyun unsigned host_len, dev_len, len;
1399*4882a593Smuzhiyun int is_short, to_host;
1400*4882a593Smuzhiyun int rescan = 0;
1401*4882a593Smuzhiyun
1402*4882a593Smuzhiyun if (dummy_ep_stream_en(dum_hcd, urb)) {
1403*4882a593Smuzhiyun if ((urb->stream_id != req->req.stream_id))
1404*4882a593Smuzhiyun continue;
1405*4882a593Smuzhiyun }
1406*4882a593Smuzhiyun
1407*4882a593Smuzhiyun /* 1..N packets of ep->ep.maxpacket each ... the last one
1408*4882a593Smuzhiyun * may be short (including zero length).
1409*4882a593Smuzhiyun *
1410*4882a593Smuzhiyun * writer can send a zlp explicitly (length 0) or implicitly
1411*4882a593Smuzhiyun * (length mod maxpacket zero, and 'zero' flag); they always
1412*4882a593Smuzhiyun * terminate reads.
1413*4882a593Smuzhiyun */
1414*4882a593Smuzhiyun host_len = urb->transfer_buffer_length - urb->actual_length;
1415*4882a593Smuzhiyun dev_len = req->req.length - req->req.actual;
1416*4882a593Smuzhiyun len = min(host_len, dev_len);
1417*4882a593Smuzhiyun
1418*4882a593Smuzhiyun /* FIXME update emulated data toggle too */
1419*4882a593Smuzhiyun
1420*4882a593Smuzhiyun to_host = usb_urb_dir_in(urb);
1421*4882a593Smuzhiyun if (unlikely(len == 0))
1422*4882a593Smuzhiyun is_short = 1;
1423*4882a593Smuzhiyun else {
1424*4882a593Smuzhiyun /* not enough bandwidth left? */
1425*4882a593Smuzhiyun if (limit < ep->ep.maxpacket && limit < len)
1426*4882a593Smuzhiyun break;
1427*4882a593Smuzhiyun len = min_t(unsigned, len, limit);
1428*4882a593Smuzhiyun if (len == 0)
1429*4882a593Smuzhiyun break;
1430*4882a593Smuzhiyun
1431*4882a593Smuzhiyun /* send multiple of maxpacket first, then remainder */
1432*4882a593Smuzhiyun if (len >= ep->ep.maxpacket) {
1433*4882a593Smuzhiyun is_short = 0;
1434*4882a593Smuzhiyun if (len % ep->ep.maxpacket)
1435*4882a593Smuzhiyun rescan = 1;
1436*4882a593Smuzhiyun len -= len % ep->ep.maxpacket;
1437*4882a593Smuzhiyun } else {
1438*4882a593Smuzhiyun is_short = 1;
1439*4882a593Smuzhiyun }
1440*4882a593Smuzhiyun
1441*4882a593Smuzhiyun len = dummy_perform_transfer(urb, req, len);
1442*4882a593Smuzhiyun
1443*4882a593Smuzhiyun ep->last_io = jiffies;
1444*4882a593Smuzhiyun if ((int)len < 0) {
1445*4882a593Smuzhiyun req->req.status = len;
1446*4882a593Smuzhiyun } else {
1447*4882a593Smuzhiyun limit -= len;
1448*4882a593Smuzhiyun sent += len;
1449*4882a593Smuzhiyun urb->actual_length += len;
1450*4882a593Smuzhiyun req->req.actual += len;
1451*4882a593Smuzhiyun }
1452*4882a593Smuzhiyun }
1453*4882a593Smuzhiyun
1454*4882a593Smuzhiyun /* short packets terminate, maybe with overflow/underflow.
1455*4882a593Smuzhiyun * it's only really an error to write too much.
1456*4882a593Smuzhiyun *
1457*4882a593Smuzhiyun * partially filling a buffer optionally blocks queue advances
1458*4882a593Smuzhiyun * (so completion handlers can clean up the queue) but we don't
1459*4882a593Smuzhiyun * need to emulate such data-in-flight.
1460*4882a593Smuzhiyun */
1461*4882a593Smuzhiyun if (is_short) {
1462*4882a593Smuzhiyun if (host_len == dev_len) {
1463*4882a593Smuzhiyun req->req.status = 0;
1464*4882a593Smuzhiyun *status = 0;
1465*4882a593Smuzhiyun } else if (to_host) {
1466*4882a593Smuzhiyun req->req.status = 0;
1467*4882a593Smuzhiyun if (dev_len > host_len)
1468*4882a593Smuzhiyun *status = -EOVERFLOW;
1469*4882a593Smuzhiyun else
1470*4882a593Smuzhiyun *status = 0;
1471*4882a593Smuzhiyun } else {
1472*4882a593Smuzhiyun *status = 0;
1473*4882a593Smuzhiyun if (host_len > dev_len)
1474*4882a593Smuzhiyun req->req.status = -EOVERFLOW;
1475*4882a593Smuzhiyun else
1476*4882a593Smuzhiyun req->req.status = 0;
1477*4882a593Smuzhiyun }
1478*4882a593Smuzhiyun
1479*4882a593Smuzhiyun /*
1480*4882a593Smuzhiyun * many requests terminate without a short packet.
1481*4882a593Smuzhiyun * send a zlp if demanded by flags.
1482*4882a593Smuzhiyun */
1483*4882a593Smuzhiyun } else {
1484*4882a593Smuzhiyun if (req->req.length == req->req.actual) {
1485*4882a593Smuzhiyun if (req->req.zero && to_host)
1486*4882a593Smuzhiyun rescan = 1;
1487*4882a593Smuzhiyun else
1488*4882a593Smuzhiyun req->req.status = 0;
1489*4882a593Smuzhiyun }
1490*4882a593Smuzhiyun if (urb->transfer_buffer_length == urb->actual_length) {
1491*4882a593Smuzhiyun if (urb->transfer_flags & URB_ZERO_PACKET &&
1492*4882a593Smuzhiyun !to_host)
1493*4882a593Smuzhiyun rescan = 1;
1494*4882a593Smuzhiyun else
1495*4882a593Smuzhiyun *status = 0;
1496*4882a593Smuzhiyun }
1497*4882a593Smuzhiyun }
1498*4882a593Smuzhiyun
1499*4882a593Smuzhiyun /* device side completion --> continuable */
1500*4882a593Smuzhiyun if (req->req.status != -EINPROGRESS) {
1501*4882a593Smuzhiyun list_del_init(&req->queue);
1502*4882a593Smuzhiyun
1503*4882a593Smuzhiyun spin_unlock(&dum->lock);
1504*4882a593Smuzhiyun usb_gadget_giveback_request(&ep->ep, &req->req);
1505*4882a593Smuzhiyun spin_lock(&dum->lock);
1506*4882a593Smuzhiyun
1507*4882a593Smuzhiyun /* requests might have been unlinked... */
1508*4882a593Smuzhiyun rescan = 1;
1509*4882a593Smuzhiyun }
1510*4882a593Smuzhiyun
1511*4882a593Smuzhiyun /* host side completion --> terminate */
1512*4882a593Smuzhiyun if (*status != -EINPROGRESS)
1513*4882a593Smuzhiyun break;
1514*4882a593Smuzhiyun
1515*4882a593Smuzhiyun /* rescan to continue with any other queued i/o */
1516*4882a593Smuzhiyun if (rescan)
1517*4882a593Smuzhiyun goto top;
1518*4882a593Smuzhiyun }
1519*4882a593Smuzhiyun return sent;
1520*4882a593Smuzhiyun }
1521*4882a593Smuzhiyun
periodic_bytes(struct dummy * dum,struct dummy_ep * ep)1522*4882a593Smuzhiyun static int periodic_bytes(struct dummy *dum, struct dummy_ep *ep)
1523*4882a593Smuzhiyun {
1524*4882a593Smuzhiyun int limit = ep->ep.maxpacket;
1525*4882a593Smuzhiyun
1526*4882a593Smuzhiyun if (dum->gadget.speed == USB_SPEED_HIGH) {
1527*4882a593Smuzhiyun int tmp;
1528*4882a593Smuzhiyun
1529*4882a593Smuzhiyun /* high bandwidth mode */
1530*4882a593Smuzhiyun tmp = usb_endpoint_maxp_mult(ep->desc);
1531*4882a593Smuzhiyun tmp *= 8 /* applies to entire frame */;
1532*4882a593Smuzhiyun limit += limit * tmp;
1533*4882a593Smuzhiyun }
1534*4882a593Smuzhiyun if (dum->gadget.speed == USB_SPEED_SUPER) {
1535*4882a593Smuzhiyun switch (usb_endpoint_type(ep->desc)) {
1536*4882a593Smuzhiyun case USB_ENDPOINT_XFER_ISOC:
1537*4882a593Smuzhiyun /* Sec. 4.4.8.2 USB3.0 Spec */
1538*4882a593Smuzhiyun limit = 3 * 16 * 1024 * 8;
1539*4882a593Smuzhiyun break;
1540*4882a593Smuzhiyun case USB_ENDPOINT_XFER_INT:
1541*4882a593Smuzhiyun /* Sec. 4.4.7.2 USB3.0 Spec */
1542*4882a593Smuzhiyun limit = 3 * 1024 * 8;
1543*4882a593Smuzhiyun break;
1544*4882a593Smuzhiyun case USB_ENDPOINT_XFER_BULK:
1545*4882a593Smuzhiyun default:
1546*4882a593Smuzhiyun break;
1547*4882a593Smuzhiyun }
1548*4882a593Smuzhiyun }
1549*4882a593Smuzhiyun return limit;
1550*4882a593Smuzhiyun }
1551*4882a593Smuzhiyun
1552*4882a593Smuzhiyun #define is_active(dum_hcd) ((dum_hcd->port_status & \
1553*4882a593Smuzhiyun (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE | \
1554*4882a593Smuzhiyun USB_PORT_STAT_SUSPEND)) \
1555*4882a593Smuzhiyun == (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE))
1556*4882a593Smuzhiyun
find_endpoint(struct dummy * dum,u8 address)1557*4882a593Smuzhiyun static struct dummy_ep *find_endpoint(struct dummy *dum, u8 address)
1558*4882a593Smuzhiyun {
1559*4882a593Smuzhiyun int i;
1560*4882a593Smuzhiyun
1561*4882a593Smuzhiyun if (!is_active((dum->gadget.speed == USB_SPEED_SUPER ?
1562*4882a593Smuzhiyun dum->ss_hcd : dum->hs_hcd)))
1563*4882a593Smuzhiyun return NULL;
1564*4882a593Smuzhiyun if (!dum->ints_enabled)
1565*4882a593Smuzhiyun return NULL;
1566*4882a593Smuzhiyun if ((address & ~USB_DIR_IN) == 0)
1567*4882a593Smuzhiyun return &dum->ep[0];
1568*4882a593Smuzhiyun for (i = 1; i < DUMMY_ENDPOINTS; i++) {
1569*4882a593Smuzhiyun struct dummy_ep *ep = &dum->ep[i];
1570*4882a593Smuzhiyun
1571*4882a593Smuzhiyun if (!ep->desc)
1572*4882a593Smuzhiyun continue;
1573*4882a593Smuzhiyun if (ep->desc->bEndpointAddress == address)
1574*4882a593Smuzhiyun return ep;
1575*4882a593Smuzhiyun }
1576*4882a593Smuzhiyun return NULL;
1577*4882a593Smuzhiyun }
1578*4882a593Smuzhiyun
1579*4882a593Smuzhiyun #undef is_active
1580*4882a593Smuzhiyun
1581*4882a593Smuzhiyun #define Dev_Request (USB_TYPE_STANDARD | USB_RECIP_DEVICE)
1582*4882a593Smuzhiyun #define Dev_InRequest (Dev_Request | USB_DIR_IN)
1583*4882a593Smuzhiyun #define Intf_Request (USB_TYPE_STANDARD | USB_RECIP_INTERFACE)
1584*4882a593Smuzhiyun #define Intf_InRequest (Intf_Request | USB_DIR_IN)
1585*4882a593Smuzhiyun #define Ep_Request (USB_TYPE_STANDARD | USB_RECIP_ENDPOINT)
1586*4882a593Smuzhiyun #define Ep_InRequest (Ep_Request | USB_DIR_IN)
1587*4882a593Smuzhiyun
1588*4882a593Smuzhiyun
1589*4882a593Smuzhiyun /**
1590*4882a593Smuzhiyun * handle_control_request() - handles all control transfers
1591*4882a593Smuzhiyun * @dum_hcd: pointer to dummy (the_controller)
1592*4882a593Smuzhiyun * @urb: the urb request to handle
1593*4882a593Smuzhiyun * @setup: pointer to the setup data for a USB device control
1594*4882a593Smuzhiyun * request
1595*4882a593Smuzhiyun * @status: pointer to request handling status
1596*4882a593Smuzhiyun *
1597*4882a593Smuzhiyun * Return 0 - if the request was handled
1598*4882a593Smuzhiyun * 1 - if the request wasn't handles
1599*4882a593Smuzhiyun * error code on error
1600*4882a593Smuzhiyun */
handle_control_request(struct dummy_hcd * dum_hcd,struct urb * urb,struct usb_ctrlrequest * setup,int * status)1601*4882a593Smuzhiyun static int handle_control_request(struct dummy_hcd *dum_hcd, struct urb *urb,
1602*4882a593Smuzhiyun struct usb_ctrlrequest *setup,
1603*4882a593Smuzhiyun int *status)
1604*4882a593Smuzhiyun {
1605*4882a593Smuzhiyun struct dummy_ep *ep2;
1606*4882a593Smuzhiyun struct dummy *dum = dum_hcd->dum;
1607*4882a593Smuzhiyun int ret_val = 1;
1608*4882a593Smuzhiyun unsigned w_index;
1609*4882a593Smuzhiyun unsigned w_value;
1610*4882a593Smuzhiyun
1611*4882a593Smuzhiyun w_index = le16_to_cpu(setup->wIndex);
1612*4882a593Smuzhiyun w_value = le16_to_cpu(setup->wValue);
1613*4882a593Smuzhiyun switch (setup->bRequest) {
1614*4882a593Smuzhiyun case USB_REQ_SET_ADDRESS:
1615*4882a593Smuzhiyun if (setup->bRequestType != Dev_Request)
1616*4882a593Smuzhiyun break;
1617*4882a593Smuzhiyun dum->address = w_value;
1618*4882a593Smuzhiyun *status = 0;
1619*4882a593Smuzhiyun dev_dbg(udc_dev(dum), "set_address = %d\n",
1620*4882a593Smuzhiyun w_value);
1621*4882a593Smuzhiyun ret_val = 0;
1622*4882a593Smuzhiyun break;
1623*4882a593Smuzhiyun case USB_REQ_SET_FEATURE:
1624*4882a593Smuzhiyun if (setup->bRequestType == Dev_Request) {
1625*4882a593Smuzhiyun ret_val = 0;
1626*4882a593Smuzhiyun switch (w_value) {
1627*4882a593Smuzhiyun case USB_DEVICE_REMOTE_WAKEUP:
1628*4882a593Smuzhiyun break;
1629*4882a593Smuzhiyun case USB_DEVICE_B_HNP_ENABLE:
1630*4882a593Smuzhiyun dum->gadget.b_hnp_enable = 1;
1631*4882a593Smuzhiyun break;
1632*4882a593Smuzhiyun case USB_DEVICE_A_HNP_SUPPORT:
1633*4882a593Smuzhiyun dum->gadget.a_hnp_support = 1;
1634*4882a593Smuzhiyun break;
1635*4882a593Smuzhiyun case USB_DEVICE_A_ALT_HNP_SUPPORT:
1636*4882a593Smuzhiyun dum->gadget.a_alt_hnp_support = 1;
1637*4882a593Smuzhiyun break;
1638*4882a593Smuzhiyun case USB_DEVICE_U1_ENABLE:
1639*4882a593Smuzhiyun if (dummy_hcd_to_hcd(dum_hcd)->speed ==
1640*4882a593Smuzhiyun HCD_USB3)
1641*4882a593Smuzhiyun w_value = USB_DEV_STAT_U1_ENABLED;
1642*4882a593Smuzhiyun else
1643*4882a593Smuzhiyun ret_val = -EOPNOTSUPP;
1644*4882a593Smuzhiyun break;
1645*4882a593Smuzhiyun case USB_DEVICE_U2_ENABLE:
1646*4882a593Smuzhiyun if (dummy_hcd_to_hcd(dum_hcd)->speed ==
1647*4882a593Smuzhiyun HCD_USB3)
1648*4882a593Smuzhiyun w_value = USB_DEV_STAT_U2_ENABLED;
1649*4882a593Smuzhiyun else
1650*4882a593Smuzhiyun ret_val = -EOPNOTSUPP;
1651*4882a593Smuzhiyun break;
1652*4882a593Smuzhiyun case USB_DEVICE_LTM_ENABLE:
1653*4882a593Smuzhiyun if (dummy_hcd_to_hcd(dum_hcd)->speed ==
1654*4882a593Smuzhiyun HCD_USB3)
1655*4882a593Smuzhiyun w_value = USB_DEV_STAT_LTM_ENABLED;
1656*4882a593Smuzhiyun else
1657*4882a593Smuzhiyun ret_val = -EOPNOTSUPP;
1658*4882a593Smuzhiyun break;
1659*4882a593Smuzhiyun default:
1660*4882a593Smuzhiyun ret_val = -EOPNOTSUPP;
1661*4882a593Smuzhiyun }
1662*4882a593Smuzhiyun if (ret_val == 0) {
1663*4882a593Smuzhiyun dum->devstatus |= (1 << w_value);
1664*4882a593Smuzhiyun *status = 0;
1665*4882a593Smuzhiyun }
1666*4882a593Smuzhiyun } else if (setup->bRequestType == Ep_Request) {
1667*4882a593Smuzhiyun /* endpoint halt */
1668*4882a593Smuzhiyun ep2 = find_endpoint(dum, w_index);
1669*4882a593Smuzhiyun if (!ep2 || ep2->ep.name == ep0name) {
1670*4882a593Smuzhiyun ret_val = -EOPNOTSUPP;
1671*4882a593Smuzhiyun break;
1672*4882a593Smuzhiyun }
1673*4882a593Smuzhiyun ep2->halted = 1;
1674*4882a593Smuzhiyun ret_val = 0;
1675*4882a593Smuzhiyun *status = 0;
1676*4882a593Smuzhiyun }
1677*4882a593Smuzhiyun break;
1678*4882a593Smuzhiyun case USB_REQ_CLEAR_FEATURE:
1679*4882a593Smuzhiyun if (setup->bRequestType == Dev_Request) {
1680*4882a593Smuzhiyun ret_val = 0;
1681*4882a593Smuzhiyun switch (w_value) {
1682*4882a593Smuzhiyun case USB_DEVICE_REMOTE_WAKEUP:
1683*4882a593Smuzhiyun w_value = USB_DEVICE_REMOTE_WAKEUP;
1684*4882a593Smuzhiyun break;
1685*4882a593Smuzhiyun case USB_DEVICE_U1_ENABLE:
1686*4882a593Smuzhiyun if (dummy_hcd_to_hcd(dum_hcd)->speed ==
1687*4882a593Smuzhiyun HCD_USB3)
1688*4882a593Smuzhiyun w_value = USB_DEV_STAT_U1_ENABLED;
1689*4882a593Smuzhiyun else
1690*4882a593Smuzhiyun ret_val = -EOPNOTSUPP;
1691*4882a593Smuzhiyun break;
1692*4882a593Smuzhiyun case USB_DEVICE_U2_ENABLE:
1693*4882a593Smuzhiyun if (dummy_hcd_to_hcd(dum_hcd)->speed ==
1694*4882a593Smuzhiyun HCD_USB3)
1695*4882a593Smuzhiyun w_value = USB_DEV_STAT_U2_ENABLED;
1696*4882a593Smuzhiyun else
1697*4882a593Smuzhiyun ret_val = -EOPNOTSUPP;
1698*4882a593Smuzhiyun break;
1699*4882a593Smuzhiyun case USB_DEVICE_LTM_ENABLE:
1700*4882a593Smuzhiyun if (dummy_hcd_to_hcd(dum_hcd)->speed ==
1701*4882a593Smuzhiyun HCD_USB3)
1702*4882a593Smuzhiyun w_value = USB_DEV_STAT_LTM_ENABLED;
1703*4882a593Smuzhiyun else
1704*4882a593Smuzhiyun ret_val = -EOPNOTSUPP;
1705*4882a593Smuzhiyun break;
1706*4882a593Smuzhiyun default:
1707*4882a593Smuzhiyun ret_val = -EOPNOTSUPP;
1708*4882a593Smuzhiyun break;
1709*4882a593Smuzhiyun }
1710*4882a593Smuzhiyun if (ret_val == 0) {
1711*4882a593Smuzhiyun dum->devstatus &= ~(1 << w_value);
1712*4882a593Smuzhiyun *status = 0;
1713*4882a593Smuzhiyun }
1714*4882a593Smuzhiyun } else if (setup->bRequestType == Ep_Request) {
1715*4882a593Smuzhiyun /* endpoint halt */
1716*4882a593Smuzhiyun ep2 = find_endpoint(dum, w_index);
1717*4882a593Smuzhiyun if (!ep2) {
1718*4882a593Smuzhiyun ret_val = -EOPNOTSUPP;
1719*4882a593Smuzhiyun break;
1720*4882a593Smuzhiyun }
1721*4882a593Smuzhiyun if (!ep2->wedged)
1722*4882a593Smuzhiyun ep2->halted = 0;
1723*4882a593Smuzhiyun ret_val = 0;
1724*4882a593Smuzhiyun *status = 0;
1725*4882a593Smuzhiyun }
1726*4882a593Smuzhiyun break;
1727*4882a593Smuzhiyun case USB_REQ_GET_STATUS:
1728*4882a593Smuzhiyun if (setup->bRequestType == Dev_InRequest
1729*4882a593Smuzhiyun || setup->bRequestType == Intf_InRequest
1730*4882a593Smuzhiyun || setup->bRequestType == Ep_InRequest) {
1731*4882a593Smuzhiyun char *buf;
1732*4882a593Smuzhiyun /*
1733*4882a593Smuzhiyun * device: remote wakeup, selfpowered
1734*4882a593Smuzhiyun * interface: nothing
1735*4882a593Smuzhiyun * endpoint: halt
1736*4882a593Smuzhiyun */
1737*4882a593Smuzhiyun buf = (char *)urb->transfer_buffer;
1738*4882a593Smuzhiyun if (urb->transfer_buffer_length > 0) {
1739*4882a593Smuzhiyun if (setup->bRequestType == Ep_InRequest) {
1740*4882a593Smuzhiyun ep2 = find_endpoint(dum, w_index);
1741*4882a593Smuzhiyun if (!ep2) {
1742*4882a593Smuzhiyun ret_val = -EOPNOTSUPP;
1743*4882a593Smuzhiyun break;
1744*4882a593Smuzhiyun }
1745*4882a593Smuzhiyun buf[0] = ep2->halted;
1746*4882a593Smuzhiyun } else if (setup->bRequestType ==
1747*4882a593Smuzhiyun Dev_InRequest) {
1748*4882a593Smuzhiyun buf[0] = (u8)dum->devstatus;
1749*4882a593Smuzhiyun } else
1750*4882a593Smuzhiyun buf[0] = 0;
1751*4882a593Smuzhiyun }
1752*4882a593Smuzhiyun if (urb->transfer_buffer_length > 1)
1753*4882a593Smuzhiyun buf[1] = 0;
1754*4882a593Smuzhiyun urb->actual_length = min_t(u32, 2,
1755*4882a593Smuzhiyun urb->transfer_buffer_length);
1756*4882a593Smuzhiyun ret_val = 0;
1757*4882a593Smuzhiyun *status = 0;
1758*4882a593Smuzhiyun }
1759*4882a593Smuzhiyun break;
1760*4882a593Smuzhiyun }
1761*4882a593Smuzhiyun return ret_val;
1762*4882a593Smuzhiyun }
1763*4882a593Smuzhiyun
1764*4882a593Smuzhiyun /* drive both sides of the transfers; looks like irq handlers to
1765*4882a593Smuzhiyun * both drivers except the callbacks aren't in_irq().
1766*4882a593Smuzhiyun */
dummy_timer(struct timer_list * t)1767*4882a593Smuzhiyun static void dummy_timer(struct timer_list *t)
1768*4882a593Smuzhiyun {
1769*4882a593Smuzhiyun struct dummy_hcd *dum_hcd = from_timer(dum_hcd, t, timer);
1770*4882a593Smuzhiyun struct dummy *dum = dum_hcd->dum;
1771*4882a593Smuzhiyun struct urbp *urbp, *tmp;
1772*4882a593Smuzhiyun unsigned long flags;
1773*4882a593Smuzhiyun int limit, total;
1774*4882a593Smuzhiyun int i;
1775*4882a593Smuzhiyun
1776*4882a593Smuzhiyun /* simplistic model for one frame's bandwidth */
1777*4882a593Smuzhiyun /* FIXME: account for transaction and packet overhead */
1778*4882a593Smuzhiyun switch (dum->gadget.speed) {
1779*4882a593Smuzhiyun case USB_SPEED_LOW:
1780*4882a593Smuzhiyun total = 8/*bytes*/ * 12/*packets*/;
1781*4882a593Smuzhiyun break;
1782*4882a593Smuzhiyun case USB_SPEED_FULL:
1783*4882a593Smuzhiyun total = 64/*bytes*/ * 19/*packets*/;
1784*4882a593Smuzhiyun break;
1785*4882a593Smuzhiyun case USB_SPEED_HIGH:
1786*4882a593Smuzhiyun total = 512/*bytes*/ * 13/*packets*/ * 8/*uframes*/;
1787*4882a593Smuzhiyun break;
1788*4882a593Smuzhiyun case USB_SPEED_SUPER:
1789*4882a593Smuzhiyun /* Bus speed is 500000 bytes/ms, so use a little less */
1790*4882a593Smuzhiyun total = 490000;
1791*4882a593Smuzhiyun break;
1792*4882a593Smuzhiyun default: /* Can't happen */
1793*4882a593Smuzhiyun dev_err(dummy_dev(dum_hcd), "bogus device speed\n");
1794*4882a593Smuzhiyun total = 0;
1795*4882a593Smuzhiyun break;
1796*4882a593Smuzhiyun }
1797*4882a593Smuzhiyun
1798*4882a593Smuzhiyun /* FIXME if HZ != 1000 this will probably misbehave ... */
1799*4882a593Smuzhiyun
1800*4882a593Smuzhiyun /* look at each urb queued by the host side driver */
1801*4882a593Smuzhiyun spin_lock_irqsave(&dum->lock, flags);
1802*4882a593Smuzhiyun
1803*4882a593Smuzhiyun if (!dum_hcd->udev) {
1804*4882a593Smuzhiyun dev_err(dummy_dev(dum_hcd),
1805*4882a593Smuzhiyun "timer fired with no URBs pending?\n");
1806*4882a593Smuzhiyun spin_unlock_irqrestore(&dum->lock, flags);
1807*4882a593Smuzhiyun return;
1808*4882a593Smuzhiyun }
1809*4882a593Smuzhiyun dum_hcd->next_frame_urbp = NULL;
1810*4882a593Smuzhiyun
1811*4882a593Smuzhiyun for (i = 0; i < DUMMY_ENDPOINTS; i++) {
1812*4882a593Smuzhiyun if (!ep_info[i].name)
1813*4882a593Smuzhiyun break;
1814*4882a593Smuzhiyun dum->ep[i].already_seen = 0;
1815*4882a593Smuzhiyun }
1816*4882a593Smuzhiyun
1817*4882a593Smuzhiyun restart:
1818*4882a593Smuzhiyun list_for_each_entry_safe(urbp, tmp, &dum_hcd->urbp_list, urbp_list) {
1819*4882a593Smuzhiyun struct urb *urb;
1820*4882a593Smuzhiyun struct dummy_request *req;
1821*4882a593Smuzhiyun u8 address;
1822*4882a593Smuzhiyun struct dummy_ep *ep = NULL;
1823*4882a593Smuzhiyun int status = -EINPROGRESS;
1824*4882a593Smuzhiyun
1825*4882a593Smuzhiyun /* stop when we reach URBs queued after the timer interrupt */
1826*4882a593Smuzhiyun if (urbp == dum_hcd->next_frame_urbp)
1827*4882a593Smuzhiyun break;
1828*4882a593Smuzhiyun
1829*4882a593Smuzhiyun urb = urbp->urb;
1830*4882a593Smuzhiyun if (urb->unlinked)
1831*4882a593Smuzhiyun goto return_urb;
1832*4882a593Smuzhiyun else if (dum_hcd->rh_state != DUMMY_RH_RUNNING)
1833*4882a593Smuzhiyun continue;
1834*4882a593Smuzhiyun
1835*4882a593Smuzhiyun /* Used up this frame's bandwidth? */
1836*4882a593Smuzhiyun if (total <= 0)
1837*4882a593Smuzhiyun continue;
1838*4882a593Smuzhiyun
1839*4882a593Smuzhiyun /* find the gadget's ep for this request (if configured) */
1840*4882a593Smuzhiyun address = usb_pipeendpoint (urb->pipe);
1841*4882a593Smuzhiyun if (usb_urb_dir_in(urb))
1842*4882a593Smuzhiyun address |= USB_DIR_IN;
1843*4882a593Smuzhiyun ep = find_endpoint(dum, address);
1844*4882a593Smuzhiyun if (!ep) {
1845*4882a593Smuzhiyun /* set_configuration() disagreement */
1846*4882a593Smuzhiyun dev_dbg(dummy_dev(dum_hcd),
1847*4882a593Smuzhiyun "no ep configured for urb %p\n",
1848*4882a593Smuzhiyun urb);
1849*4882a593Smuzhiyun status = -EPROTO;
1850*4882a593Smuzhiyun goto return_urb;
1851*4882a593Smuzhiyun }
1852*4882a593Smuzhiyun
1853*4882a593Smuzhiyun if (ep->already_seen)
1854*4882a593Smuzhiyun continue;
1855*4882a593Smuzhiyun ep->already_seen = 1;
1856*4882a593Smuzhiyun if (ep == &dum->ep[0] && urb->error_count) {
1857*4882a593Smuzhiyun ep->setup_stage = 1; /* a new urb */
1858*4882a593Smuzhiyun urb->error_count = 0;
1859*4882a593Smuzhiyun }
1860*4882a593Smuzhiyun if (ep->halted && !ep->setup_stage) {
1861*4882a593Smuzhiyun /* NOTE: must not be iso! */
1862*4882a593Smuzhiyun dev_dbg(dummy_dev(dum_hcd), "ep %s halted, urb %p\n",
1863*4882a593Smuzhiyun ep->ep.name, urb);
1864*4882a593Smuzhiyun status = -EPIPE;
1865*4882a593Smuzhiyun goto return_urb;
1866*4882a593Smuzhiyun }
1867*4882a593Smuzhiyun /* FIXME make sure both ends agree on maxpacket */
1868*4882a593Smuzhiyun
1869*4882a593Smuzhiyun /* handle control requests */
1870*4882a593Smuzhiyun if (ep == &dum->ep[0] && ep->setup_stage) {
1871*4882a593Smuzhiyun struct usb_ctrlrequest setup;
1872*4882a593Smuzhiyun int value = 1;
1873*4882a593Smuzhiyun
1874*4882a593Smuzhiyun setup = *(struct usb_ctrlrequest *) urb->setup_packet;
1875*4882a593Smuzhiyun /* paranoia, in case of stale queued data */
1876*4882a593Smuzhiyun list_for_each_entry(req, &ep->queue, queue) {
1877*4882a593Smuzhiyun list_del_init(&req->queue);
1878*4882a593Smuzhiyun req->req.status = -EOVERFLOW;
1879*4882a593Smuzhiyun dev_dbg(udc_dev(dum), "stale req = %p\n",
1880*4882a593Smuzhiyun req);
1881*4882a593Smuzhiyun
1882*4882a593Smuzhiyun spin_unlock(&dum->lock);
1883*4882a593Smuzhiyun usb_gadget_giveback_request(&ep->ep, &req->req);
1884*4882a593Smuzhiyun spin_lock(&dum->lock);
1885*4882a593Smuzhiyun ep->already_seen = 0;
1886*4882a593Smuzhiyun goto restart;
1887*4882a593Smuzhiyun }
1888*4882a593Smuzhiyun
1889*4882a593Smuzhiyun /* gadget driver never sees set_address or operations
1890*4882a593Smuzhiyun * on standard feature flags. some hardware doesn't
1891*4882a593Smuzhiyun * even expose them.
1892*4882a593Smuzhiyun */
1893*4882a593Smuzhiyun ep->last_io = jiffies;
1894*4882a593Smuzhiyun ep->setup_stage = 0;
1895*4882a593Smuzhiyun ep->halted = 0;
1896*4882a593Smuzhiyun
1897*4882a593Smuzhiyun value = handle_control_request(dum_hcd, urb, &setup,
1898*4882a593Smuzhiyun &status);
1899*4882a593Smuzhiyun
1900*4882a593Smuzhiyun /* gadget driver handles all other requests. block
1901*4882a593Smuzhiyun * until setup() returns; no reentrancy issues etc.
1902*4882a593Smuzhiyun */
1903*4882a593Smuzhiyun if (value > 0) {
1904*4882a593Smuzhiyun ++dum->callback_usage;
1905*4882a593Smuzhiyun spin_unlock(&dum->lock);
1906*4882a593Smuzhiyun value = dum->driver->setup(&dum->gadget,
1907*4882a593Smuzhiyun &setup);
1908*4882a593Smuzhiyun spin_lock(&dum->lock);
1909*4882a593Smuzhiyun --dum->callback_usage;
1910*4882a593Smuzhiyun
1911*4882a593Smuzhiyun if (value >= 0) {
1912*4882a593Smuzhiyun /* no delays (max 64KB data stage) */
1913*4882a593Smuzhiyun limit = 64*1024;
1914*4882a593Smuzhiyun goto treat_control_like_bulk;
1915*4882a593Smuzhiyun }
1916*4882a593Smuzhiyun /* error, see below */
1917*4882a593Smuzhiyun }
1918*4882a593Smuzhiyun
1919*4882a593Smuzhiyun if (value < 0) {
1920*4882a593Smuzhiyun if (value != -EOPNOTSUPP)
1921*4882a593Smuzhiyun dev_dbg(udc_dev(dum),
1922*4882a593Smuzhiyun "setup --> %d\n",
1923*4882a593Smuzhiyun value);
1924*4882a593Smuzhiyun status = -EPIPE;
1925*4882a593Smuzhiyun urb->actual_length = 0;
1926*4882a593Smuzhiyun }
1927*4882a593Smuzhiyun
1928*4882a593Smuzhiyun goto return_urb;
1929*4882a593Smuzhiyun }
1930*4882a593Smuzhiyun
1931*4882a593Smuzhiyun /* non-control requests */
1932*4882a593Smuzhiyun limit = total;
1933*4882a593Smuzhiyun switch (usb_pipetype(urb->pipe)) {
1934*4882a593Smuzhiyun case PIPE_ISOCHRONOUS:
1935*4882a593Smuzhiyun /*
1936*4882a593Smuzhiyun * We don't support isochronous. But if we did,
1937*4882a593Smuzhiyun * here are some of the issues we'd have to face:
1938*4882a593Smuzhiyun *
1939*4882a593Smuzhiyun * Is it urb->interval since the last xfer?
1940*4882a593Smuzhiyun * Use urb->iso_frame_desc[i].
1941*4882a593Smuzhiyun * Complete whether or not ep has requests queued.
1942*4882a593Smuzhiyun * Report random errors, to debug drivers.
1943*4882a593Smuzhiyun */
1944*4882a593Smuzhiyun limit = max(limit, periodic_bytes(dum, ep));
1945*4882a593Smuzhiyun status = -EINVAL; /* fail all xfers */
1946*4882a593Smuzhiyun break;
1947*4882a593Smuzhiyun
1948*4882a593Smuzhiyun case PIPE_INTERRUPT:
1949*4882a593Smuzhiyun /* FIXME is it urb->interval since the last xfer?
1950*4882a593Smuzhiyun * this almost certainly polls too fast.
1951*4882a593Smuzhiyun */
1952*4882a593Smuzhiyun limit = max(limit, periodic_bytes(dum, ep));
1953*4882a593Smuzhiyun fallthrough;
1954*4882a593Smuzhiyun
1955*4882a593Smuzhiyun default:
1956*4882a593Smuzhiyun treat_control_like_bulk:
1957*4882a593Smuzhiyun ep->last_io = jiffies;
1958*4882a593Smuzhiyun total -= transfer(dum_hcd, urb, ep, limit, &status);
1959*4882a593Smuzhiyun break;
1960*4882a593Smuzhiyun }
1961*4882a593Smuzhiyun
1962*4882a593Smuzhiyun /* incomplete transfer? */
1963*4882a593Smuzhiyun if (status == -EINPROGRESS)
1964*4882a593Smuzhiyun continue;
1965*4882a593Smuzhiyun
1966*4882a593Smuzhiyun return_urb:
1967*4882a593Smuzhiyun list_del(&urbp->urbp_list);
1968*4882a593Smuzhiyun kfree(urbp);
1969*4882a593Smuzhiyun if (ep)
1970*4882a593Smuzhiyun ep->already_seen = ep->setup_stage = 0;
1971*4882a593Smuzhiyun
1972*4882a593Smuzhiyun usb_hcd_unlink_urb_from_ep(dummy_hcd_to_hcd(dum_hcd), urb);
1973*4882a593Smuzhiyun spin_unlock(&dum->lock);
1974*4882a593Smuzhiyun usb_hcd_giveback_urb(dummy_hcd_to_hcd(dum_hcd), urb, status);
1975*4882a593Smuzhiyun spin_lock(&dum->lock);
1976*4882a593Smuzhiyun
1977*4882a593Smuzhiyun goto restart;
1978*4882a593Smuzhiyun }
1979*4882a593Smuzhiyun
1980*4882a593Smuzhiyun if (list_empty(&dum_hcd->urbp_list)) {
1981*4882a593Smuzhiyun usb_put_dev(dum_hcd->udev);
1982*4882a593Smuzhiyun dum_hcd->udev = NULL;
1983*4882a593Smuzhiyun } else if (dum_hcd->rh_state == DUMMY_RH_RUNNING) {
1984*4882a593Smuzhiyun /* want a 1 msec delay here */
1985*4882a593Smuzhiyun mod_timer(&dum_hcd->timer, jiffies + msecs_to_jiffies(1));
1986*4882a593Smuzhiyun }
1987*4882a593Smuzhiyun
1988*4882a593Smuzhiyun spin_unlock_irqrestore(&dum->lock, flags);
1989*4882a593Smuzhiyun }
1990*4882a593Smuzhiyun
1991*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
1992*4882a593Smuzhiyun
1993*4882a593Smuzhiyun #define PORT_C_MASK \
1994*4882a593Smuzhiyun ((USB_PORT_STAT_C_CONNECTION \
1995*4882a593Smuzhiyun | USB_PORT_STAT_C_ENABLE \
1996*4882a593Smuzhiyun | USB_PORT_STAT_C_SUSPEND \
1997*4882a593Smuzhiyun | USB_PORT_STAT_C_OVERCURRENT \
1998*4882a593Smuzhiyun | USB_PORT_STAT_C_RESET) << 16)
1999*4882a593Smuzhiyun
dummy_hub_status(struct usb_hcd * hcd,char * buf)2000*4882a593Smuzhiyun static int dummy_hub_status(struct usb_hcd *hcd, char *buf)
2001*4882a593Smuzhiyun {
2002*4882a593Smuzhiyun struct dummy_hcd *dum_hcd;
2003*4882a593Smuzhiyun unsigned long flags;
2004*4882a593Smuzhiyun int retval = 0;
2005*4882a593Smuzhiyun
2006*4882a593Smuzhiyun dum_hcd = hcd_to_dummy_hcd(hcd);
2007*4882a593Smuzhiyun
2008*4882a593Smuzhiyun spin_lock_irqsave(&dum_hcd->dum->lock, flags);
2009*4882a593Smuzhiyun if (!HCD_HW_ACCESSIBLE(hcd))
2010*4882a593Smuzhiyun goto done;
2011*4882a593Smuzhiyun
2012*4882a593Smuzhiyun if (dum_hcd->resuming && time_after_eq(jiffies, dum_hcd->re_timeout)) {
2013*4882a593Smuzhiyun dum_hcd->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);
2014*4882a593Smuzhiyun dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND;
2015*4882a593Smuzhiyun set_link_state(dum_hcd);
2016*4882a593Smuzhiyun }
2017*4882a593Smuzhiyun
2018*4882a593Smuzhiyun if ((dum_hcd->port_status & PORT_C_MASK) != 0) {
2019*4882a593Smuzhiyun *buf = (1 << 1);
2020*4882a593Smuzhiyun dev_dbg(dummy_dev(dum_hcd), "port status 0x%08x has changes\n",
2021*4882a593Smuzhiyun dum_hcd->port_status);
2022*4882a593Smuzhiyun retval = 1;
2023*4882a593Smuzhiyun if (dum_hcd->rh_state == DUMMY_RH_SUSPENDED)
2024*4882a593Smuzhiyun usb_hcd_resume_root_hub(hcd);
2025*4882a593Smuzhiyun }
2026*4882a593Smuzhiyun done:
2027*4882a593Smuzhiyun spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
2028*4882a593Smuzhiyun return retval;
2029*4882a593Smuzhiyun }
2030*4882a593Smuzhiyun
2031*4882a593Smuzhiyun /* usb 3.0 root hub device descriptor */
2032*4882a593Smuzhiyun static struct {
2033*4882a593Smuzhiyun struct usb_bos_descriptor bos;
2034*4882a593Smuzhiyun struct usb_ss_cap_descriptor ss_cap;
2035*4882a593Smuzhiyun } __packed usb3_bos_desc = {
2036*4882a593Smuzhiyun
2037*4882a593Smuzhiyun .bos = {
2038*4882a593Smuzhiyun .bLength = USB_DT_BOS_SIZE,
2039*4882a593Smuzhiyun .bDescriptorType = USB_DT_BOS,
2040*4882a593Smuzhiyun .wTotalLength = cpu_to_le16(sizeof(usb3_bos_desc)),
2041*4882a593Smuzhiyun .bNumDeviceCaps = 1,
2042*4882a593Smuzhiyun },
2043*4882a593Smuzhiyun .ss_cap = {
2044*4882a593Smuzhiyun .bLength = USB_DT_USB_SS_CAP_SIZE,
2045*4882a593Smuzhiyun .bDescriptorType = USB_DT_DEVICE_CAPABILITY,
2046*4882a593Smuzhiyun .bDevCapabilityType = USB_SS_CAP_TYPE,
2047*4882a593Smuzhiyun .wSpeedSupported = cpu_to_le16(USB_5GBPS_OPERATION),
2048*4882a593Smuzhiyun .bFunctionalitySupport = ilog2(USB_5GBPS_OPERATION),
2049*4882a593Smuzhiyun },
2050*4882a593Smuzhiyun };
2051*4882a593Smuzhiyun
2052*4882a593Smuzhiyun static inline void
ss_hub_descriptor(struct usb_hub_descriptor * desc)2053*4882a593Smuzhiyun ss_hub_descriptor(struct usb_hub_descriptor *desc)
2054*4882a593Smuzhiyun {
2055*4882a593Smuzhiyun memset(desc, 0, sizeof *desc);
2056*4882a593Smuzhiyun desc->bDescriptorType = USB_DT_SS_HUB;
2057*4882a593Smuzhiyun desc->bDescLength = 12;
2058*4882a593Smuzhiyun desc->wHubCharacteristics = cpu_to_le16(
2059*4882a593Smuzhiyun HUB_CHAR_INDV_PORT_LPSM |
2060*4882a593Smuzhiyun HUB_CHAR_COMMON_OCPM);
2061*4882a593Smuzhiyun desc->bNbrPorts = 1;
2062*4882a593Smuzhiyun desc->u.ss.bHubHdrDecLat = 0x04; /* Worst case: 0.4 micro sec*/
2063*4882a593Smuzhiyun desc->u.ss.DeviceRemovable = 0;
2064*4882a593Smuzhiyun }
2065*4882a593Smuzhiyun
hub_descriptor(struct usb_hub_descriptor * desc)2066*4882a593Smuzhiyun static inline void hub_descriptor(struct usb_hub_descriptor *desc)
2067*4882a593Smuzhiyun {
2068*4882a593Smuzhiyun memset(desc, 0, sizeof *desc);
2069*4882a593Smuzhiyun desc->bDescriptorType = USB_DT_HUB;
2070*4882a593Smuzhiyun desc->bDescLength = 9;
2071*4882a593Smuzhiyun desc->wHubCharacteristics = cpu_to_le16(
2072*4882a593Smuzhiyun HUB_CHAR_INDV_PORT_LPSM |
2073*4882a593Smuzhiyun HUB_CHAR_COMMON_OCPM);
2074*4882a593Smuzhiyun desc->bNbrPorts = 1;
2075*4882a593Smuzhiyun desc->u.hs.DeviceRemovable[0] = 0;
2076*4882a593Smuzhiyun desc->u.hs.DeviceRemovable[1] = 0xff; /* PortPwrCtrlMask */
2077*4882a593Smuzhiyun }
2078*4882a593Smuzhiyun
dummy_hub_control(struct usb_hcd * hcd,u16 typeReq,u16 wValue,u16 wIndex,char * buf,u16 wLength)2079*4882a593Smuzhiyun static int dummy_hub_control(
2080*4882a593Smuzhiyun struct usb_hcd *hcd,
2081*4882a593Smuzhiyun u16 typeReq,
2082*4882a593Smuzhiyun u16 wValue,
2083*4882a593Smuzhiyun u16 wIndex,
2084*4882a593Smuzhiyun char *buf,
2085*4882a593Smuzhiyun u16 wLength
2086*4882a593Smuzhiyun ) {
2087*4882a593Smuzhiyun struct dummy_hcd *dum_hcd;
2088*4882a593Smuzhiyun int retval = 0;
2089*4882a593Smuzhiyun unsigned long flags;
2090*4882a593Smuzhiyun
2091*4882a593Smuzhiyun if (!HCD_HW_ACCESSIBLE(hcd))
2092*4882a593Smuzhiyun return -ETIMEDOUT;
2093*4882a593Smuzhiyun
2094*4882a593Smuzhiyun dum_hcd = hcd_to_dummy_hcd(hcd);
2095*4882a593Smuzhiyun
2096*4882a593Smuzhiyun spin_lock_irqsave(&dum_hcd->dum->lock, flags);
2097*4882a593Smuzhiyun switch (typeReq) {
2098*4882a593Smuzhiyun case ClearHubFeature:
2099*4882a593Smuzhiyun break;
2100*4882a593Smuzhiyun case ClearPortFeature:
2101*4882a593Smuzhiyun switch (wValue) {
2102*4882a593Smuzhiyun case USB_PORT_FEAT_SUSPEND:
2103*4882a593Smuzhiyun if (hcd->speed == HCD_USB3) {
2104*4882a593Smuzhiyun dev_dbg(dummy_dev(dum_hcd),
2105*4882a593Smuzhiyun "USB_PORT_FEAT_SUSPEND req not "
2106*4882a593Smuzhiyun "supported for USB 3.0 roothub\n");
2107*4882a593Smuzhiyun goto error;
2108*4882a593Smuzhiyun }
2109*4882a593Smuzhiyun if (dum_hcd->port_status & USB_PORT_STAT_SUSPEND) {
2110*4882a593Smuzhiyun /* 20msec resume signaling */
2111*4882a593Smuzhiyun dum_hcd->resuming = 1;
2112*4882a593Smuzhiyun dum_hcd->re_timeout = jiffies +
2113*4882a593Smuzhiyun msecs_to_jiffies(20);
2114*4882a593Smuzhiyun }
2115*4882a593Smuzhiyun break;
2116*4882a593Smuzhiyun case USB_PORT_FEAT_POWER:
2117*4882a593Smuzhiyun dev_dbg(dummy_dev(dum_hcd), "power-off\n");
2118*4882a593Smuzhiyun if (hcd->speed == HCD_USB3)
2119*4882a593Smuzhiyun dum_hcd->port_status &= ~USB_SS_PORT_STAT_POWER;
2120*4882a593Smuzhiyun else
2121*4882a593Smuzhiyun dum_hcd->port_status &= ~USB_PORT_STAT_POWER;
2122*4882a593Smuzhiyun set_link_state(dum_hcd);
2123*4882a593Smuzhiyun break;
2124*4882a593Smuzhiyun case USB_PORT_FEAT_ENABLE:
2125*4882a593Smuzhiyun case USB_PORT_FEAT_C_ENABLE:
2126*4882a593Smuzhiyun case USB_PORT_FEAT_C_SUSPEND:
2127*4882a593Smuzhiyun /* Not allowed for USB-3 */
2128*4882a593Smuzhiyun if (hcd->speed == HCD_USB3)
2129*4882a593Smuzhiyun goto error;
2130*4882a593Smuzhiyun fallthrough;
2131*4882a593Smuzhiyun case USB_PORT_FEAT_C_CONNECTION:
2132*4882a593Smuzhiyun case USB_PORT_FEAT_C_RESET:
2133*4882a593Smuzhiyun dum_hcd->port_status &= ~(1 << wValue);
2134*4882a593Smuzhiyun set_link_state(dum_hcd);
2135*4882a593Smuzhiyun break;
2136*4882a593Smuzhiyun default:
2137*4882a593Smuzhiyun /* Disallow INDICATOR and C_OVER_CURRENT */
2138*4882a593Smuzhiyun goto error;
2139*4882a593Smuzhiyun }
2140*4882a593Smuzhiyun break;
2141*4882a593Smuzhiyun case GetHubDescriptor:
2142*4882a593Smuzhiyun if (hcd->speed == HCD_USB3 &&
2143*4882a593Smuzhiyun (wLength < USB_DT_SS_HUB_SIZE ||
2144*4882a593Smuzhiyun wValue != (USB_DT_SS_HUB << 8))) {
2145*4882a593Smuzhiyun dev_dbg(dummy_dev(dum_hcd),
2146*4882a593Smuzhiyun "Wrong hub descriptor type for "
2147*4882a593Smuzhiyun "USB 3.0 roothub.\n");
2148*4882a593Smuzhiyun goto error;
2149*4882a593Smuzhiyun }
2150*4882a593Smuzhiyun if (hcd->speed == HCD_USB3)
2151*4882a593Smuzhiyun ss_hub_descriptor((struct usb_hub_descriptor *) buf);
2152*4882a593Smuzhiyun else
2153*4882a593Smuzhiyun hub_descriptor((struct usb_hub_descriptor *) buf);
2154*4882a593Smuzhiyun break;
2155*4882a593Smuzhiyun
2156*4882a593Smuzhiyun case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
2157*4882a593Smuzhiyun if (hcd->speed != HCD_USB3)
2158*4882a593Smuzhiyun goto error;
2159*4882a593Smuzhiyun
2160*4882a593Smuzhiyun if ((wValue >> 8) != USB_DT_BOS)
2161*4882a593Smuzhiyun goto error;
2162*4882a593Smuzhiyun
2163*4882a593Smuzhiyun memcpy(buf, &usb3_bos_desc, sizeof(usb3_bos_desc));
2164*4882a593Smuzhiyun retval = sizeof(usb3_bos_desc);
2165*4882a593Smuzhiyun break;
2166*4882a593Smuzhiyun
2167*4882a593Smuzhiyun case GetHubStatus:
2168*4882a593Smuzhiyun *(__le32 *) buf = cpu_to_le32(0);
2169*4882a593Smuzhiyun break;
2170*4882a593Smuzhiyun case GetPortStatus:
2171*4882a593Smuzhiyun if (wIndex != 1)
2172*4882a593Smuzhiyun retval = -EPIPE;
2173*4882a593Smuzhiyun
2174*4882a593Smuzhiyun /* whoever resets or resumes must GetPortStatus to
2175*4882a593Smuzhiyun * complete it!!
2176*4882a593Smuzhiyun */
2177*4882a593Smuzhiyun if (dum_hcd->resuming &&
2178*4882a593Smuzhiyun time_after_eq(jiffies, dum_hcd->re_timeout)) {
2179*4882a593Smuzhiyun dum_hcd->port_status |= (USB_PORT_STAT_C_SUSPEND << 16);
2180*4882a593Smuzhiyun dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND;
2181*4882a593Smuzhiyun }
2182*4882a593Smuzhiyun if ((dum_hcd->port_status & USB_PORT_STAT_RESET) != 0 &&
2183*4882a593Smuzhiyun time_after_eq(jiffies, dum_hcd->re_timeout)) {
2184*4882a593Smuzhiyun dum_hcd->port_status |= (USB_PORT_STAT_C_RESET << 16);
2185*4882a593Smuzhiyun dum_hcd->port_status &= ~USB_PORT_STAT_RESET;
2186*4882a593Smuzhiyun if (dum_hcd->dum->pullup) {
2187*4882a593Smuzhiyun dum_hcd->port_status |= USB_PORT_STAT_ENABLE;
2188*4882a593Smuzhiyun
2189*4882a593Smuzhiyun if (hcd->speed < HCD_USB3) {
2190*4882a593Smuzhiyun switch (dum_hcd->dum->gadget.speed) {
2191*4882a593Smuzhiyun case USB_SPEED_HIGH:
2192*4882a593Smuzhiyun dum_hcd->port_status |=
2193*4882a593Smuzhiyun USB_PORT_STAT_HIGH_SPEED;
2194*4882a593Smuzhiyun break;
2195*4882a593Smuzhiyun case USB_SPEED_LOW:
2196*4882a593Smuzhiyun dum_hcd->dum->gadget.ep0->
2197*4882a593Smuzhiyun maxpacket = 8;
2198*4882a593Smuzhiyun dum_hcd->port_status |=
2199*4882a593Smuzhiyun USB_PORT_STAT_LOW_SPEED;
2200*4882a593Smuzhiyun break;
2201*4882a593Smuzhiyun default:
2202*4882a593Smuzhiyun break;
2203*4882a593Smuzhiyun }
2204*4882a593Smuzhiyun }
2205*4882a593Smuzhiyun }
2206*4882a593Smuzhiyun }
2207*4882a593Smuzhiyun set_link_state(dum_hcd);
2208*4882a593Smuzhiyun ((__le16 *) buf)[0] = cpu_to_le16(dum_hcd->port_status);
2209*4882a593Smuzhiyun ((__le16 *) buf)[1] = cpu_to_le16(dum_hcd->port_status >> 16);
2210*4882a593Smuzhiyun break;
2211*4882a593Smuzhiyun case SetHubFeature:
2212*4882a593Smuzhiyun retval = -EPIPE;
2213*4882a593Smuzhiyun break;
2214*4882a593Smuzhiyun case SetPortFeature:
2215*4882a593Smuzhiyun switch (wValue) {
2216*4882a593Smuzhiyun case USB_PORT_FEAT_LINK_STATE:
2217*4882a593Smuzhiyun if (hcd->speed != HCD_USB3) {
2218*4882a593Smuzhiyun dev_dbg(dummy_dev(dum_hcd),
2219*4882a593Smuzhiyun "USB_PORT_FEAT_LINK_STATE req not "
2220*4882a593Smuzhiyun "supported for USB 2.0 roothub\n");
2221*4882a593Smuzhiyun goto error;
2222*4882a593Smuzhiyun }
2223*4882a593Smuzhiyun /*
2224*4882a593Smuzhiyun * Since this is dummy we don't have an actual link so
2225*4882a593Smuzhiyun * there is nothing to do for the SET_LINK_STATE cmd
2226*4882a593Smuzhiyun */
2227*4882a593Smuzhiyun break;
2228*4882a593Smuzhiyun case USB_PORT_FEAT_U1_TIMEOUT:
2229*4882a593Smuzhiyun case USB_PORT_FEAT_U2_TIMEOUT:
2230*4882a593Smuzhiyun /* TODO: add suspend/resume support! */
2231*4882a593Smuzhiyun if (hcd->speed != HCD_USB3) {
2232*4882a593Smuzhiyun dev_dbg(dummy_dev(dum_hcd),
2233*4882a593Smuzhiyun "USB_PORT_FEAT_U1/2_TIMEOUT req not "
2234*4882a593Smuzhiyun "supported for USB 2.0 roothub\n");
2235*4882a593Smuzhiyun goto error;
2236*4882a593Smuzhiyun }
2237*4882a593Smuzhiyun break;
2238*4882a593Smuzhiyun case USB_PORT_FEAT_SUSPEND:
2239*4882a593Smuzhiyun /* Applicable only for USB2.0 hub */
2240*4882a593Smuzhiyun if (hcd->speed == HCD_USB3) {
2241*4882a593Smuzhiyun dev_dbg(dummy_dev(dum_hcd),
2242*4882a593Smuzhiyun "USB_PORT_FEAT_SUSPEND req not "
2243*4882a593Smuzhiyun "supported for USB 3.0 roothub\n");
2244*4882a593Smuzhiyun goto error;
2245*4882a593Smuzhiyun }
2246*4882a593Smuzhiyun if (dum_hcd->active) {
2247*4882a593Smuzhiyun dum_hcd->port_status |= USB_PORT_STAT_SUSPEND;
2248*4882a593Smuzhiyun
2249*4882a593Smuzhiyun /* HNP would happen here; for now we
2250*4882a593Smuzhiyun * assume b_bus_req is always true.
2251*4882a593Smuzhiyun */
2252*4882a593Smuzhiyun set_link_state(dum_hcd);
2253*4882a593Smuzhiyun if (((1 << USB_DEVICE_B_HNP_ENABLE)
2254*4882a593Smuzhiyun & dum_hcd->dum->devstatus) != 0)
2255*4882a593Smuzhiyun dev_dbg(dummy_dev(dum_hcd),
2256*4882a593Smuzhiyun "no HNP yet!\n");
2257*4882a593Smuzhiyun }
2258*4882a593Smuzhiyun break;
2259*4882a593Smuzhiyun case USB_PORT_FEAT_POWER:
2260*4882a593Smuzhiyun if (hcd->speed == HCD_USB3)
2261*4882a593Smuzhiyun dum_hcd->port_status |= USB_SS_PORT_STAT_POWER;
2262*4882a593Smuzhiyun else
2263*4882a593Smuzhiyun dum_hcd->port_status |= USB_PORT_STAT_POWER;
2264*4882a593Smuzhiyun set_link_state(dum_hcd);
2265*4882a593Smuzhiyun break;
2266*4882a593Smuzhiyun case USB_PORT_FEAT_BH_PORT_RESET:
2267*4882a593Smuzhiyun /* Applicable only for USB3.0 hub */
2268*4882a593Smuzhiyun if (hcd->speed != HCD_USB3) {
2269*4882a593Smuzhiyun dev_dbg(dummy_dev(dum_hcd),
2270*4882a593Smuzhiyun "USB_PORT_FEAT_BH_PORT_RESET req not "
2271*4882a593Smuzhiyun "supported for USB 2.0 roothub\n");
2272*4882a593Smuzhiyun goto error;
2273*4882a593Smuzhiyun }
2274*4882a593Smuzhiyun fallthrough;
2275*4882a593Smuzhiyun case USB_PORT_FEAT_RESET:
2276*4882a593Smuzhiyun if (!(dum_hcd->port_status & USB_PORT_STAT_CONNECTION))
2277*4882a593Smuzhiyun break;
2278*4882a593Smuzhiyun /* if it's already enabled, disable */
2279*4882a593Smuzhiyun if (hcd->speed == HCD_USB3) {
2280*4882a593Smuzhiyun dum_hcd->port_status =
2281*4882a593Smuzhiyun (USB_SS_PORT_STAT_POWER |
2282*4882a593Smuzhiyun USB_PORT_STAT_CONNECTION |
2283*4882a593Smuzhiyun USB_PORT_STAT_RESET);
2284*4882a593Smuzhiyun } else {
2285*4882a593Smuzhiyun dum_hcd->port_status &= ~(USB_PORT_STAT_ENABLE
2286*4882a593Smuzhiyun | USB_PORT_STAT_LOW_SPEED
2287*4882a593Smuzhiyun | USB_PORT_STAT_HIGH_SPEED);
2288*4882a593Smuzhiyun dum_hcd->port_status |= USB_PORT_STAT_RESET;
2289*4882a593Smuzhiyun }
2290*4882a593Smuzhiyun /*
2291*4882a593Smuzhiyun * We want to reset device status. All but the
2292*4882a593Smuzhiyun * Self powered feature
2293*4882a593Smuzhiyun */
2294*4882a593Smuzhiyun dum_hcd->dum->devstatus &=
2295*4882a593Smuzhiyun (1 << USB_DEVICE_SELF_POWERED);
2296*4882a593Smuzhiyun /*
2297*4882a593Smuzhiyun * FIXME USB3.0: what is the correct reset signaling
2298*4882a593Smuzhiyun * interval? Is it still 50msec as for HS?
2299*4882a593Smuzhiyun */
2300*4882a593Smuzhiyun dum_hcd->re_timeout = jiffies + msecs_to_jiffies(50);
2301*4882a593Smuzhiyun set_link_state(dum_hcd);
2302*4882a593Smuzhiyun break;
2303*4882a593Smuzhiyun case USB_PORT_FEAT_C_CONNECTION:
2304*4882a593Smuzhiyun case USB_PORT_FEAT_C_RESET:
2305*4882a593Smuzhiyun case USB_PORT_FEAT_C_ENABLE:
2306*4882a593Smuzhiyun case USB_PORT_FEAT_C_SUSPEND:
2307*4882a593Smuzhiyun /* Not allowed for USB-3, and ignored for USB-2 */
2308*4882a593Smuzhiyun if (hcd->speed == HCD_USB3)
2309*4882a593Smuzhiyun goto error;
2310*4882a593Smuzhiyun break;
2311*4882a593Smuzhiyun default:
2312*4882a593Smuzhiyun /* Disallow TEST, INDICATOR, and C_OVER_CURRENT */
2313*4882a593Smuzhiyun goto error;
2314*4882a593Smuzhiyun }
2315*4882a593Smuzhiyun break;
2316*4882a593Smuzhiyun case GetPortErrorCount:
2317*4882a593Smuzhiyun if (hcd->speed != HCD_USB3) {
2318*4882a593Smuzhiyun dev_dbg(dummy_dev(dum_hcd),
2319*4882a593Smuzhiyun "GetPortErrorCount req not "
2320*4882a593Smuzhiyun "supported for USB 2.0 roothub\n");
2321*4882a593Smuzhiyun goto error;
2322*4882a593Smuzhiyun }
2323*4882a593Smuzhiyun /* We'll always return 0 since this is a dummy hub */
2324*4882a593Smuzhiyun *(__le32 *) buf = cpu_to_le32(0);
2325*4882a593Smuzhiyun break;
2326*4882a593Smuzhiyun case SetHubDepth:
2327*4882a593Smuzhiyun if (hcd->speed != HCD_USB3) {
2328*4882a593Smuzhiyun dev_dbg(dummy_dev(dum_hcd),
2329*4882a593Smuzhiyun "SetHubDepth req not supported for "
2330*4882a593Smuzhiyun "USB 2.0 roothub\n");
2331*4882a593Smuzhiyun goto error;
2332*4882a593Smuzhiyun }
2333*4882a593Smuzhiyun break;
2334*4882a593Smuzhiyun default:
2335*4882a593Smuzhiyun dev_dbg(dummy_dev(dum_hcd),
2336*4882a593Smuzhiyun "hub control req%04x v%04x i%04x l%d\n",
2337*4882a593Smuzhiyun typeReq, wValue, wIndex, wLength);
2338*4882a593Smuzhiyun error:
2339*4882a593Smuzhiyun /* "protocol stall" on error */
2340*4882a593Smuzhiyun retval = -EPIPE;
2341*4882a593Smuzhiyun }
2342*4882a593Smuzhiyun spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
2343*4882a593Smuzhiyun
2344*4882a593Smuzhiyun if ((dum_hcd->port_status & PORT_C_MASK) != 0)
2345*4882a593Smuzhiyun usb_hcd_poll_rh_status(hcd);
2346*4882a593Smuzhiyun return retval;
2347*4882a593Smuzhiyun }
2348*4882a593Smuzhiyun
dummy_bus_suspend(struct usb_hcd * hcd)2349*4882a593Smuzhiyun static int dummy_bus_suspend(struct usb_hcd *hcd)
2350*4882a593Smuzhiyun {
2351*4882a593Smuzhiyun struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
2352*4882a593Smuzhiyun
2353*4882a593Smuzhiyun dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
2354*4882a593Smuzhiyun
2355*4882a593Smuzhiyun spin_lock_irq(&dum_hcd->dum->lock);
2356*4882a593Smuzhiyun dum_hcd->rh_state = DUMMY_RH_SUSPENDED;
2357*4882a593Smuzhiyun set_link_state(dum_hcd);
2358*4882a593Smuzhiyun hcd->state = HC_STATE_SUSPENDED;
2359*4882a593Smuzhiyun spin_unlock_irq(&dum_hcd->dum->lock);
2360*4882a593Smuzhiyun return 0;
2361*4882a593Smuzhiyun }
2362*4882a593Smuzhiyun
dummy_bus_resume(struct usb_hcd * hcd)2363*4882a593Smuzhiyun static int dummy_bus_resume(struct usb_hcd *hcd)
2364*4882a593Smuzhiyun {
2365*4882a593Smuzhiyun struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
2366*4882a593Smuzhiyun int rc = 0;
2367*4882a593Smuzhiyun
2368*4882a593Smuzhiyun dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
2369*4882a593Smuzhiyun
2370*4882a593Smuzhiyun spin_lock_irq(&dum_hcd->dum->lock);
2371*4882a593Smuzhiyun if (!HCD_HW_ACCESSIBLE(hcd)) {
2372*4882a593Smuzhiyun rc = -ESHUTDOWN;
2373*4882a593Smuzhiyun } else {
2374*4882a593Smuzhiyun dum_hcd->rh_state = DUMMY_RH_RUNNING;
2375*4882a593Smuzhiyun set_link_state(dum_hcd);
2376*4882a593Smuzhiyun if (!list_empty(&dum_hcd->urbp_list))
2377*4882a593Smuzhiyun mod_timer(&dum_hcd->timer, jiffies);
2378*4882a593Smuzhiyun hcd->state = HC_STATE_RUNNING;
2379*4882a593Smuzhiyun }
2380*4882a593Smuzhiyun spin_unlock_irq(&dum_hcd->dum->lock);
2381*4882a593Smuzhiyun return rc;
2382*4882a593Smuzhiyun }
2383*4882a593Smuzhiyun
2384*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
2385*4882a593Smuzhiyun
show_urb(char * buf,size_t size,struct urb * urb)2386*4882a593Smuzhiyun static inline ssize_t show_urb(char *buf, size_t size, struct urb *urb)
2387*4882a593Smuzhiyun {
2388*4882a593Smuzhiyun int ep = usb_pipeendpoint(urb->pipe);
2389*4882a593Smuzhiyun
2390*4882a593Smuzhiyun return scnprintf(buf, size,
2391*4882a593Smuzhiyun "urb/%p %s ep%d%s%s len %d/%d\n",
2392*4882a593Smuzhiyun urb,
2393*4882a593Smuzhiyun ({ char *s;
2394*4882a593Smuzhiyun switch (urb->dev->speed) {
2395*4882a593Smuzhiyun case USB_SPEED_LOW:
2396*4882a593Smuzhiyun s = "ls";
2397*4882a593Smuzhiyun break;
2398*4882a593Smuzhiyun case USB_SPEED_FULL:
2399*4882a593Smuzhiyun s = "fs";
2400*4882a593Smuzhiyun break;
2401*4882a593Smuzhiyun case USB_SPEED_HIGH:
2402*4882a593Smuzhiyun s = "hs";
2403*4882a593Smuzhiyun break;
2404*4882a593Smuzhiyun case USB_SPEED_SUPER:
2405*4882a593Smuzhiyun s = "ss";
2406*4882a593Smuzhiyun break;
2407*4882a593Smuzhiyun default:
2408*4882a593Smuzhiyun s = "?";
2409*4882a593Smuzhiyun break;
2410*4882a593Smuzhiyun } s; }),
2411*4882a593Smuzhiyun ep, ep ? (usb_urb_dir_in(urb) ? "in" : "out") : "",
2412*4882a593Smuzhiyun ({ char *s; \
2413*4882a593Smuzhiyun switch (usb_pipetype(urb->pipe)) { \
2414*4882a593Smuzhiyun case PIPE_CONTROL: \
2415*4882a593Smuzhiyun s = ""; \
2416*4882a593Smuzhiyun break; \
2417*4882a593Smuzhiyun case PIPE_BULK: \
2418*4882a593Smuzhiyun s = "-bulk"; \
2419*4882a593Smuzhiyun break; \
2420*4882a593Smuzhiyun case PIPE_INTERRUPT: \
2421*4882a593Smuzhiyun s = "-int"; \
2422*4882a593Smuzhiyun break; \
2423*4882a593Smuzhiyun default: \
2424*4882a593Smuzhiyun s = "-iso"; \
2425*4882a593Smuzhiyun break; \
2426*4882a593Smuzhiyun } s; }),
2427*4882a593Smuzhiyun urb->actual_length, urb->transfer_buffer_length);
2428*4882a593Smuzhiyun }
2429*4882a593Smuzhiyun
urbs_show(struct device * dev,struct device_attribute * attr,char * buf)2430*4882a593Smuzhiyun static ssize_t urbs_show(struct device *dev, struct device_attribute *attr,
2431*4882a593Smuzhiyun char *buf)
2432*4882a593Smuzhiyun {
2433*4882a593Smuzhiyun struct usb_hcd *hcd = dev_get_drvdata(dev);
2434*4882a593Smuzhiyun struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
2435*4882a593Smuzhiyun struct urbp *urbp;
2436*4882a593Smuzhiyun size_t size = 0;
2437*4882a593Smuzhiyun unsigned long flags;
2438*4882a593Smuzhiyun
2439*4882a593Smuzhiyun spin_lock_irqsave(&dum_hcd->dum->lock, flags);
2440*4882a593Smuzhiyun list_for_each_entry(urbp, &dum_hcd->urbp_list, urbp_list) {
2441*4882a593Smuzhiyun size_t temp;
2442*4882a593Smuzhiyun
2443*4882a593Smuzhiyun temp = show_urb(buf, PAGE_SIZE - size, urbp->urb);
2444*4882a593Smuzhiyun buf += temp;
2445*4882a593Smuzhiyun size += temp;
2446*4882a593Smuzhiyun }
2447*4882a593Smuzhiyun spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
2448*4882a593Smuzhiyun
2449*4882a593Smuzhiyun return size;
2450*4882a593Smuzhiyun }
2451*4882a593Smuzhiyun static DEVICE_ATTR_RO(urbs);
2452*4882a593Smuzhiyun
dummy_start_ss(struct dummy_hcd * dum_hcd)2453*4882a593Smuzhiyun static int dummy_start_ss(struct dummy_hcd *dum_hcd)
2454*4882a593Smuzhiyun {
2455*4882a593Smuzhiyun timer_setup(&dum_hcd->timer, dummy_timer, 0);
2456*4882a593Smuzhiyun dum_hcd->rh_state = DUMMY_RH_RUNNING;
2457*4882a593Smuzhiyun dum_hcd->stream_en_ep = 0;
2458*4882a593Smuzhiyun INIT_LIST_HEAD(&dum_hcd->urbp_list);
2459*4882a593Smuzhiyun dummy_hcd_to_hcd(dum_hcd)->power_budget = POWER_BUDGET_3;
2460*4882a593Smuzhiyun dummy_hcd_to_hcd(dum_hcd)->state = HC_STATE_RUNNING;
2461*4882a593Smuzhiyun dummy_hcd_to_hcd(dum_hcd)->uses_new_polling = 1;
2462*4882a593Smuzhiyun #ifdef CONFIG_USB_OTG
2463*4882a593Smuzhiyun dummy_hcd_to_hcd(dum_hcd)->self.otg_port = 1;
2464*4882a593Smuzhiyun #endif
2465*4882a593Smuzhiyun return 0;
2466*4882a593Smuzhiyun
2467*4882a593Smuzhiyun /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
2468*4882a593Smuzhiyun return device_create_file(dummy_dev(dum_hcd), &dev_attr_urbs);
2469*4882a593Smuzhiyun }
2470*4882a593Smuzhiyun
dummy_start(struct usb_hcd * hcd)2471*4882a593Smuzhiyun static int dummy_start(struct usb_hcd *hcd)
2472*4882a593Smuzhiyun {
2473*4882a593Smuzhiyun struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
2474*4882a593Smuzhiyun
2475*4882a593Smuzhiyun /*
2476*4882a593Smuzhiyun * HOST side init ... we emulate a root hub that'll only ever
2477*4882a593Smuzhiyun * talk to one device (the gadget side). Also appears in sysfs,
2478*4882a593Smuzhiyun * just like more familiar pci-based HCDs.
2479*4882a593Smuzhiyun */
2480*4882a593Smuzhiyun if (!usb_hcd_is_primary_hcd(hcd))
2481*4882a593Smuzhiyun return dummy_start_ss(dum_hcd);
2482*4882a593Smuzhiyun
2483*4882a593Smuzhiyun spin_lock_init(&dum_hcd->dum->lock);
2484*4882a593Smuzhiyun timer_setup(&dum_hcd->timer, dummy_timer, 0);
2485*4882a593Smuzhiyun dum_hcd->rh_state = DUMMY_RH_RUNNING;
2486*4882a593Smuzhiyun
2487*4882a593Smuzhiyun INIT_LIST_HEAD(&dum_hcd->urbp_list);
2488*4882a593Smuzhiyun
2489*4882a593Smuzhiyun hcd->power_budget = POWER_BUDGET;
2490*4882a593Smuzhiyun hcd->state = HC_STATE_RUNNING;
2491*4882a593Smuzhiyun hcd->uses_new_polling = 1;
2492*4882a593Smuzhiyun
2493*4882a593Smuzhiyun #ifdef CONFIG_USB_OTG
2494*4882a593Smuzhiyun hcd->self.otg_port = 1;
2495*4882a593Smuzhiyun #endif
2496*4882a593Smuzhiyun
2497*4882a593Smuzhiyun /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
2498*4882a593Smuzhiyun return device_create_file(dummy_dev(dum_hcd), &dev_attr_urbs);
2499*4882a593Smuzhiyun }
2500*4882a593Smuzhiyun
dummy_stop(struct usb_hcd * hcd)2501*4882a593Smuzhiyun static void dummy_stop(struct usb_hcd *hcd)
2502*4882a593Smuzhiyun {
2503*4882a593Smuzhiyun device_remove_file(dummy_dev(hcd_to_dummy_hcd(hcd)), &dev_attr_urbs);
2504*4882a593Smuzhiyun dev_info(dummy_dev(hcd_to_dummy_hcd(hcd)), "stopped\n");
2505*4882a593Smuzhiyun }
2506*4882a593Smuzhiyun
2507*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
2508*4882a593Smuzhiyun
dummy_h_get_frame(struct usb_hcd * hcd)2509*4882a593Smuzhiyun static int dummy_h_get_frame(struct usb_hcd *hcd)
2510*4882a593Smuzhiyun {
2511*4882a593Smuzhiyun return dummy_g_get_frame(NULL);
2512*4882a593Smuzhiyun }
2513*4882a593Smuzhiyun
dummy_setup(struct usb_hcd * hcd)2514*4882a593Smuzhiyun static int dummy_setup(struct usb_hcd *hcd)
2515*4882a593Smuzhiyun {
2516*4882a593Smuzhiyun struct dummy *dum;
2517*4882a593Smuzhiyun
2518*4882a593Smuzhiyun dum = *((void **)dev_get_platdata(hcd->self.controller));
2519*4882a593Smuzhiyun hcd->self.sg_tablesize = ~0;
2520*4882a593Smuzhiyun if (usb_hcd_is_primary_hcd(hcd)) {
2521*4882a593Smuzhiyun dum->hs_hcd = hcd_to_dummy_hcd(hcd);
2522*4882a593Smuzhiyun dum->hs_hcd->dum = dum;
2523*4882a593Smuzhiyun /*
2524*4882a593Smuzhiyun * Mark the first roothub as being USB 2.0.
2525*4882a593Smuzhiyun * The USB 3.0 roothub will be registered later by
2526*4882a593Smuzhiyun * dummy_hcd_probe()
2527*4882a593Smuzhiyun */
2528*4882a593Smuzhiyun hcd->speed = HCD_USB2;
2529*4882a593Smuzhiyun hcd->self.root_hub->speed = USB_SPEED_HIGH;
2530*4882a593Smuzhiyun } else {
2531*4882a593Smuzhiyun dum->ss_hcd = hcd_to_dummy_hcd(hcd);
2532*4882a593Smuzhiyun dum->ss_hcd->dum = dum;
2533*4882a593Smuzhiyun hcd->speed = HCD_USB3;
2534*4882a593Smuzhiyun hcd->self.root_hub->speed = USB_SPEED_SUPER;
2535*4882a593Smuzhiyun }
2536*4882a593Smuzhiyun return 0;
2537*4882a593Smuzhiyun }
2538*4882a593Smuzhiyun
2539*4882a593Smuzhiyun /* Change a group of bulk endpoints to support multiple stream IDs */
dummy_alloc_streams(struct usb_hcd * hcd,struct usb_device * udev,struct usb_host_endpoint ** eps,unsigned int num_eps,unsigned int num_streams,gfp_t mem_flags)2540*4882a593Smuzhiyun static int dummy_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev,
2541*4882a593Smuzhiyun struct usb_host_endpoint **eps, unsigned int num_eps,
2542*4882a593Smuzhiyun unsigned int num_streams, gfp_t mem_flags)
2543*4882a593Smuzhiyun {
2544*4882a593Smuzhiyun struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
2545*4882a593Smuzhiyun unsigned long flags;
2546*4882a593Smuzhiyun int max_stream;
2547*4882a593Smuzhiyun int ret_streams = num_streams;
2548*4882a593Smuzhiyun unsigned int index;
2549*4882a593Smuzhiyun unsigned int i;
2550*4882a593Smuzhiyun
2551*4882a593Smuzhiyun if (!num_eps)
2552*4882a593Smuzhiyun return -EINVAL;
2553*4882a593Smuzhiyun
2554*4882a593Smuzhiyun spin_lock_irqsave(&dum_hcd->dum->lock, flags);
2555*4882a593Smuzhiyun for (i = 0; i < num_eps; i++) {
2556*4882a593Smuzhiyun index = dummy_get_ep_idx(&eps[i]->desc);
2557*4882a593Smuzhiyun if ((1 << index) & dum_hcd->stream_en_ep) {
2558*4882a593Smuzhiyun ret_streams = -EINVAL;
2559*4882a593Smuzhiyun goto out;
2560*4882a593Smuzhiyun }
2561*4882a593Smuzhiyun max_stream = usb_ss_max_streams(&eps[i]->ss_ep_comp);
2562*4882a593Smuzhiyun if (!max_stream) {
2563*4882a593Smuzhiyun ret_streams = -EINVAL;
2564*4882a593Smuzhiyun goto out;
2565*4882a593Smuzhiyun }
2566*4882a593Smuzhiyun if (max_stream < ret_streams) {
2567*4882a593Smuzhiyun dev_dbg(dummy_dev(dum_hcd), "Ep 0x%x only supports %u "
2568*4882a593Smuzhiyun "stream IDs.\n",
2569*4882a593Smuzhiyun eps[i]->desc.bEndpointAddress,
2570*4882a593Smuzhiyun max_stream);
2571*4882a593Smuzhiyun ret_streams = max_stream;
2572*4882a593Smuzhiyun }
2573*4882a593Smuzhiyun }
2574*4882a593Smuzhiyun
2575*4882a593Smuzhiyun for (i = 0; i < num_eps; i++) {
2576*4882a593Smuzhiyun index = dummy_get_ep_idx(&eps[i]->desc);
2577*4882a593Smuzhiyun dum_hcd->stream_en_ep |= 1 << index;
2578*4882a593Smuzhiyun set_max_streams_for_pipe(dum_hcd,
2579*4882a593Smuzhiyun usb_endpoint_num(&eps[i]->desc), ret_streams);
2580*4882a593Smuzhiyun }
2581*4882a593Smuzhiyun out:
2582*4882a593Smuzhiyun spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
2583*4882a593Smuzhiyun return ret_streams;
2584*4882a593Smuzhiyun }
2585*4882a593Smuzhiyun
2586*4882a593Smuzhiyun /* Reverts a group of bulk endpoints back to not using stream IDs. */
dummy_free_streams(struct usb_hcd * hcd,struct usb_device * udev,struct usb_host_endpoint ** eps,unsigned int num_eps,gfp_t mem_flags)2587*4882a593Smuzhiyun static int dummy_free_streams(struct usb_hcd *hcd, struct usb_device *udev,
2588*4882a593Smuzhiyun struct usb_host_endpoint **eps, unsigned int num_eps,
2589*4882a593Smuzhiyun gfp_t mem_flags)
2590*4882a593Smuzhiyun {
2591*4882a593Smuzhiyun struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
2592*4882a593Smuzhiyun unsigned long flags;
2593*4882a593Smuzhiyun int ret;
2594*4882a593Smuzhiyun unsigned int index;
2595*4882a593Smuzhiyun unsigned int i;
2596*4882a593Smuzhiyun
2597*4882a593Smuzhiyun spin_lock_irqsave(&dum_hcd->dum->lock, flags);
2598*4882a593Smuzhiyun for (i = 0; i < num_eps; i++) {
2599*4882a593Smuzhiyun index = dummy_get_ep_idx(&eps[i]->desc);
2600*4882a593Smuzhiyun if (!((1 << index) & dum_hcd->stream_en_ep)) {
2601*4882a593Smuzhiyun ret = -EINVAL;
2602*4882a593Smuzhiyun goto out;
2603*4882a593Smuzhiyun }
2604*4882a593Smuzhiyun }
2605*4882a593Smuzhiyun
2606*4882a593Smuzhiyun for (i = 0; i < num_eps; i++) {
2607*4882a593Smuzhiyun index = dummy_get_ep_idx(&eps[i]->desc);
2608*4882a593Smuzhiyun dum_hcd->stream_en_ep &= ~(1 << index);
2609*4882a593Smuzhiyun set_max_streams_for_pipe(dum_hcd,
2610*4882a593Smuzhiyun usb_endpoint_num(&eps[i]->desc), 0);
2611*4882a593Smuzhiyun }
2612*4882a593Smuzhiyun ret = 0;
2613*4882a593Smuzhiyun out:
2614*4882a593Smuzhiyun spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
2615*4882a593Smuzhiyun return ret;
2616*4882a593Smuzhiyun }
2617*4882a593Smuzhiyun
2618*4882a593Smuzhiyun static struct hc_driver dummy_hcd = {
2619*4882a593Smuzhiyun .description = (char *) driver_name,
2620*4882a593Smuzhiyun .product_desc = "Dummy host controller",
2621*4882a593Smuzhiyun .hcd_priv_size = sizeof(struct dummy_hcd),
2622*4882a593Smuzhiyun
2623*4882a593Smuzhiyun .reset = dummy_setup,
2624*4882a593Smuzhiyun .start = dummy_start,
2625*4882a593Smuzhiyun .stop = dummy_stop,
2626*4882a593Smuzhiyun
2627*4882a593Smuzhiyun .urb_enqueue = dummy_urb_enqueue,
2628*4882a593Smuzhiyun .urb_dequeue = dummy_urb_dequeue,
2629*4882a593Smuzhiyun
2630*4882a593Smuzhiyun .get_frame_number = dummy_h_get_frame,
2631*4882a593Smuzhiyun
2632*4882a593Smuzhiyun .hub_status_data = dummy_hub_status,
2633*4882a593Smuzhiyun .hub_control = dummy_hub_control,
2634*4882a593Smuzhiyun .bus_suspend = dummy_bus_suspend,
2635*4882a593Smuzhiyun .bus_resume = dummy_bus_resume,
2636*4882a593Smuzhiyun
2637*4882a593Smuzhiyun .alloc_streams = dummy_alloc_streams,
2638*4882a593Smuzhiyun .free_streams = dummy_free_streams,
2639*4882a593Smuzhiyun };
2640*4882a593Smuzhiyun
dummy_hcd_probe(struct platform_device * pdev)2641*4882a593Smuzhiyun static int dummy_hcd_probe(struct platform_device *pdev)
2642*4882a593Smuzhiyun {
2643*4882a593Smuzhiyun struct dummy *dum;
2644*4882a593Smuzhiyun struct usb_hcd *hs_hcd;
2645*4882a593Smuzhiyun struct usb_hcd *ss_hcd;
2646*4882a593Smuzhiyun int retval;
2647*4882a593Smuzhiyun
2648*4882a593Smuzhiyun dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
2649*4882a593Smuzhiyun dum = *((void **)dev_get_platdata(&pdev->dev));
2650*4882a593Smuzhiyun
2651*4882a593Smuzhiyun if (mod_data.is_super_speed)
2652*4882a593Smuzhiyun dummy_hcd.flags = HCD_USB3 | HCD_SHARED;
2653*4882a593Smuzhiyun else if (mod_data.is_high_speed)
2654*4882a593Smuzhiyun dummy_hcd.flags = HCD_USB2;
2655*4882a593Smuzhiyun else
2656*4882a593Smuzhiyun dummy_hcd.flags = HCD_USB11;
2657*4882a593Smuzhiyun hs_hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev));
2658*4882a593Smuzhiyun if (!hs_hcd)
2659*4882a593Smuzhiyun return -ENOMEM;
2660*4882a593Smuzhiyun hs_hcd->has_tt = 1;
2661*4882a593Smuzhiyun
2662*4882a593Smuzhiyun retval = usb_add_hcd(hs_hcd, 0, 0);
2663*4882a593Smuzhiyun if (retval)
2664*4882a593Smuzhiyun goto put_usb2_hcd;
2665*4882a593Smuzhiyun
2666*4882a593Smuzhiyun if (mod_data.is_super_speed) {
2667*4882a593Smuzhiyun ss_hcd = usb_create_shared_hcd(&dummy_hcd, &pdev->dev,
2668*4882a593Smuzhiyun dev_name(&pdev->dev), hs_hcd);
2669*4882a593Smuzhiyun if (!ss_hcd) {
2670*4882a593Smuzhiyun retval = -ENOMEM;
2671*4882a593Smuzhiyun goto dealloc_usb2_hcd;
2672*4882a593Smuzhiyun }
2673*4882a593Smuzhiyun
2674*4882a593Smuzhiyun retval = usb_add_hcd(ss_hcd, 0, 0);
2675*4882a593Smuzhiyun if (retval)
2676*4882a593Smuzhiyun goto put_usb3_hcd;
2677*4882a593Smuzhiyun }
2678*4882a593Smuzhiyun return 0;
2679*4882a593Smuzhiyun
2680*4882a593Smuzhiyun put_usb3_hcd:
2681*4882a593Smuzhiyun usb_put_hcd(ss_hcd);
2682*4882a593Smuzhiyun dealloc_usb2_hcd:
2683*4882a593Smuzhiyun usb_remove_hcd(hs_hcd);
2684*4882a593Smuzhiyun put_usb2_hcd:
2685*4882a593Smuzhiyun usb_put_hcd(hs_hcd);
2686*4882a593Smuzhiyun dum->hs_hcd = dum->ss_hcd = NULL;
2687*4882a593Smuzhiyun return retval;
2688*4882a593Smuzhiyun }
2689*4882a593Smuzhiyun
dummy_hcd_remove(struct platform_device * pdev)2690*4882a593Smuzhiyun static int dummy_hcd_remove(struct platform_device *pdev)
2691*4882a593Smuzhiyun {
2692*4882a593Smuzhiyun struct dummy *dum;
2693*4882a593Smuzhiyun
2694*4882a593Smuzhiyun dum = hcd_to_dummy_hcd(platform_get_drvdata(pdev))->dum;
2695*4882a593Smuzhiyun
2696*4882a593Smuzhiyun if (dum->ss_hcd) {
2697*4882a593Smuzhiyun usb_remove_hcd(dummy_hcd_to_hcd(dum->ss_hcd));
2698*4882a593Smuzhiyun usb_put_hcd(dummy_hcd_to_hcd(dum->ss_hcd));
2699*4882a593Smuzhiyun }
2700*4882a593Smuzhiyun
2701*4882a593Smuzhiyun usb_remove_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
2702*4882a593Smuzhiyun usb_put_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
2703*4882a593Smuzhiyun
2704*4882a593Smuzhiyun dum->hs_hcd = NULL;
2705*4882a593Smuzhiyun dum->ss_hcd = NULL;
2706*4882a593Smuzhiyun
2707*4882a593Smuzhiyun return 0;
2708*4882a593Smuzhiyun }
2709*4882a593Smuzhiyun
dummy_hcd_suspend(struct platform_device * pdev,pm_message_t state)2710*4882a593Smuzhiyun static int dummy_hcd_suspend(struct platform_device *pdev, pm_message_t state)
2711*4882a593Smuzhiyun {
2712*4882a593Smuzhiyun struct usb_hcd *hcd;
2713*4882a593Smuzhiyun struct dummy_hcd *dum_hcd;
2714*4882a593Smuzhiyun int rc = 0;
2715*4882a593Smuzhiyun
2716*4882a593Smuzhiyun dev_dbg(&pdev->dev, "%s\n", __func__);
2717*4882a593Smuzhiyun
2718*4882a593Smuzhiyun hcd = platform_get_drvdata(pdev);
2719*4882a593Smuzhiyun dum_hcd = hcd_to_dummy_hcd(hcd);
2720*4882a593Smuzhiyun if (dum_hcd->rh_state == DUMMY_RH_RUNNING) {
2721*4882a593Smuzhiyun dev_warn(&pdev->dev, "Root hub isn't suspended!\n");
2722*4882a593Smuzhiyun rc = -EBUSY;
2723*4882a593Smuzhiyun } else
2724*4882a593Smuzhiyun clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
2725*4882a593Smuzhiyun return rc;
2726*4882a593Smuzhiyun }
2727*4882a593Smuzhiyun
dummy_hcd_resume(struct platform_device * pdev)2728*4882a593Smuzhiyun static int dummy_hcd_resume(struct platform_device *pdev)
2729*4882a593Smuzhiyun {
2730*4882a593Smuzhiyun struct usb_hcd *hcd;
2731*4882a593Smuzhiyun
2732*4882a593Smuzhiyun dev_dbg(&pdev->dev, "%s\n", __func__);
2733*4882a593Smuzhiyun
2734*4882a593Smuzhiyun hcd = platform_get_drvdata(pdev);
2735*4882a593Smuzhiyun set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
2736*4882a593Smuzhiyun usb_hcd_poll_rh_status(hcd);
2737*4882a593Smuzhiyun return 0;
2738*4882a593Smuzhiyun }
2739*4882a593Smuzhiyun
2740*4882a593Smuzhiyun static struct platform_driver dummy_hcd_driver = {
2741*4882a593Smuzhiyun .probe = dummy_hcd_probe,
2742*4882a593Smuzhiyun .remove = dummy_hcd_remove,
2743*4882a593Smuzhiyun .suspend = dummy_hcd_suspend,
2744*4882a593Smuzhiyun .resume = dummy_hcd_resume,
2745*4882a593Smuzhiyun .driver = {
2746*4882a593Smuzhiyun .name = driver_name,
2747*4882a593Smuzhiyun },
2748*4882a593Smuzhiyun };
2749*4882a593Smuzhiyun
2750*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
2751*4882a593Smuzhiyun #define MAX_NUM_UDC 32
2752*4882a593Smuzhiyun static struct platform_device *the_udc_pdev[MAX_NUM_UDC];
2753*4882a593Smuzhiyun static struct platform_device *the_hcd_pdev[MAX_NUM_UDC];
2754*4882a593Smuzhiyun
init(void)2755*4882a593Smuzhiyun static int __init init(void)
2756*4882a593Smuzhiyun {
2757*4882a593Smuzhiyun int retval = -ENOMEM;
2758*4882a593Smuzhiyun int i;
2759*4882a593Smuzhiyun struct dummy *dum[MAX_NUM_UDC] = {};
2760*4882a593Smuzhiyun
2761*4882a593Smuzhiyun if (usb_disabled())
2762*4882a593Smuzhiyun return -ENODEV;
2763*4882a593Smuzhiyun
2764*4882a593Smuzhiyun if (!mod_data.is_high_speed && mod_data.is_super_speed)
2765*4882a593Smuzhiyun return -EINVAL;
2766*4882a593Smuzhiyun
2767*4882a593Smuzhiyun if (mod_data.num < 1 || mod_data.num > MAX_NUM_UDC) {
2768*4882a593Smuzhiyun pr_err("Number of emulated UDC must be in range of 1...%d\n",
2769*4882a593Smuzhiyun MAX_NUM_UDC);
2770*4882a593Smuzhiyun return -EINVAL;
2771*4882a593Smuzhiyun }
2772*4882a593Smuzhiyun
2773*4882a593Smuzhiyun for (i = 0; i < mod_data.num; i++) {
2774*4882a593Smuzhiyun the_hcd_pdev[i] = platform_device_alloc(driver_name, i);
2775*4882a593Smuzhiyun if (!the_hcd_pdev[i]) {
2776*4882a593Smuzhiyun i--;
2777*4882a593Smuzhiyun while (i >= 0)
2778*4882a593Smuzhiyun platform_device_put(the_hcd_pdev[i--]);
2779*4882a593Smuzhiyun return retval;
2780*4882a593Smuzhiyun }
2781*4882a593Smuzhiyun }
2782*4882a593Smuzhiyun for (i = 0; i < mod_data.num; i++) {
2783*4882a593Smuzhiyun the_udc_pdev[i] = platform_device_alloc(gadget_name, i);
2784*4882a593Smuzhiyun if (!the_udc_pdev[i]) {
2785*4882a593Smuzhiyun i--;
2786*4882a593Smuzhiyun while (i >= 0)
2787*4882a593Smuzhiyun platform_device_put(the_udc_pdev[i--]);
2788*4882a593Smuzhiyun goto err_alloc_udc;
2789*4882a593Smuzhiyun }
2790*4882a593Smuzhiyun }
2791*4882a593Smuzhiyun for (i = 0; i < mod_data.num; i++) {
2792*4882a593Smuzhiyun dum[i] = kzalloc(sizeof(struct dummy), GFP_KERNEL);
2793*4882a593Smuzhiyun if (!dum[i]) {
2794*4882a593Smuzhiyun retval = -ENOMEM;
2795*4882a593Smuzhiyun goto err_add_pdata;
2796*4882a593Smuzhiyun }
2797*4882a593Smuzhiyun retval = platform_device_add_data(the_hcd_pdev[i], &dum[i],
2798*4882a593Smuzhiyun sizeof(void *));
2799*4882a593Smuzhiyun if (retval)
2800*4882a593Smuzhiyun goto err_add_pdata;
2801*4882a593Smuzhiyun retval = platform_device_add_data(the_udc_pdev[i], &dum[i],
2802*4882a593Smuzhiyun sizeof(void *));
2803*4882a593Smuzhiyun if (retval)
2804*4882a593Smuzhiyun goto err_add_pdata;
2805*4882a593Smuzhiyun }
2806*4882a593Smuzhiyun
2807*4882a593Smuzhiyun retval = platform_driver_register(&dummy_hcd_driver);
2808*4882a593Smuzhiyun if (retval < 0)
2809*4882a593Smuzhiyun goto err_add_pdata;
2810*4882a593Smuzhiyun retval = platform_driver_register(&dummy_udc_driver);
2811*4882a593Smuzhiyun if (retval < 0)
2812*4882a593Smuzhiyun goto err_register_udc_driver;
2813*4882a593Smuzhiyun
2814*4882a593Smuzhiyun for (i = 0; i < mod_data.num; i++) {
2815*4882a593Smuzhiyun retval = platform_device_add(the_hcd_pdev[i]);
2816*4882a593Smuzhiyun if (retval < 0) {
2817*4882a593Smuzhiyun i--;
2818*4882a593Smuzhiyun while (i >= 0)
2819*4882a593Smuzhiyun platform_device_del(the_hcd_pdev[i--]);
2820*4882a593Smuzhiyun goto err_add_hcd;
2821*4882a593Smuzhiyun }
2822*4882a593Smuzhiyun }
2823*4882a593Smuzhiyun for (i = 0; i < mod_data.num; i++) {
2824*4882a593Smuzhiyun if (!dum[i]->hs_hcd ||
2825*4882a593Smuzhiyun (!dum[i]->ss_hcd && mod_data.is_super_speed)) {
2826*4882a593Smuzhiyun /*
2827*4882a593Smuzhiyun * The hcd was added successfully but its probe
2828*4882a593Smuzhiyun * function failed for some reason.
2829*4882a593Smuzhiyun */
2830*4882a593Smuzhiyun retval = -EINVAL;
2831*4882a593Smuzhiyun goto err_add_udc;
2832*4882a593Smuzhiyun }
2833*4882a593Smuzhiyun }
2834*4882a593Smuzhiyun
2835*4882a593Smuzhiyun for (i = 0; i < mod_data.num; i++) {
2836*4882a593Smuzhiyun retval = platform_device_add(the_udc_pdev[i]);
2837*4882a593Smuzhiyun if (retval < 0) {
2838*4882a593Smuzhiyun i--;
2839*4882a593Smuzhiyun while (i >= 0)
2840*4882a593Smuzhiyun platform_device_del(the_udc_pdev[i--]);
2841*4882a593Smuzhiyun goto err_add_udc;
2842*4882a593Smuzhiyun }
2843*4882a593Smuzhiyun }
2844*4882a593Smuzhiyun
2845*4882a593Smuzhiyun for (i = 0; i < mod_data.num; i++) {
2846*4882a593Smuzhiyun if (!platform_get_drvdata(the_udc_pdev[i])) {
2847*4882a593Smuzhiyun /*
2848*4882a593Smuzhiyun * The udc was added successfully but its probe
2849*4882a593Smuzhiyun * function failed for some reason.
2850*4882a593Smuzhiyun */
2851*4882a593Smuzhiyun retval = -EINVAL;
2852*4882a593Smuzhiyun goto err_probe_udc;
2853*4882a593Smuzhiyun }
2854*4882a593Smuzhiyun }
2855*4882a593Smuzhiyun return retval;
2856*4882a593Smuzhiyun
2857*4882a593Smuzhiyun err_probe_udc:
2858*4882a593Smuzhiyun for (i = 0; i < mod_data.num; i++)
2859*4882a593Smuzhiyun platform_device_del(the_udc_pdev[i]);
2860*4882a593Smuzhiyun err_add_udc:
2861*4882a593Smuzhiyun for (i = 0; i < mod_data.num; i++)
2862*4882a593Smuzhiyun platform_device_del(the_hcd_pdev[i]);
2863*4882a593Smuzhiyun err_add_hcd:
2864*4882a593Smuzhiyun platform_driver_unregister(&dummy_udc_driver);
2865*4882a593Smuzhiyun err_register_udc_driver:
2866*4882a593Smuzhiyun platform_driver_unregister(&dummy_hcd_driver);
2867*4882a593Smuzhiyun err_add_pdata:
2868*4882a593Smuzhiyun for (i = 0; i < mod_data.num; i++)
2869*4882a593Smuzhiyun kfree(dum[i]);
2870*4882a593Smuzhiyun for (i = 0; i < mod_data.num; i++)
2871*4882a593Smuzhiyun platform_device_put(the_udc_pdev[i]);
2872*4882a593Smuzhiyun err_alloc_udc:
2873*4882a593Smuzhiyun for (i = 0; i < mod_data.num; i++)
2874*4882a593Smuzhiyun platform_device_put(the_hcd_pdev[i]);
2875*4882a593Smuzhiyun return retval;
2876*4882a593Smuzhiyun }
2877*4882a593Smuzhiyun module_init(init);
2878*4882a593Smuzhiyun
cleanup(void)2879*4882a593Smuzhiyun static void __exit cleanup(void)
2880*4882a593Smuzhiyun {
2881*4882a593Smuzhiyun int i;
2882*4882a593Smuzhiyun
2883*4882a593Smuzhiyun for (i = 0; i < mod_data.num; i++) {
2884*4882a593Smuzhiyun struct dummy *dum;
2885*4882a593Smuzhiyun
2886*4882a593Smuzhiyun dum = *((void **)dev_get_platdata(&the_udc_pdev[i]->dev));
2887*4882a593Smuzhiyun
2888*4882a593Smuzhiyun platform_device_unregister(the_udc_pdev[i]);
2889*4882a593Smuzhiyun platform_device_unregister(the_hcd_pdev[i]);
2890*4882a593Smuzhiyun kfree(dum);
2891*4882a593Smuzhiyun }
2892*4882a593Smuzhiyun platform_driver_unregister(&dummy_udc_driver);
2893*4882a593Smuzhiyun platform_driver_unregister(&dummy_hcd_driver);
2894*4882a593Smuzhiyun }
2895*4882a593Smuzhiyun module_exit(cleanup);
2896