diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-26 02:08:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-26 02:08:32 -0400 |
commit | f549953c15deab4c54708b39af86d4edecc6cddc (patch) | |
tree | f0412f989b77cdceab34c18aa85a8a25d5942a1f /drivers/usb/gadget/f_eem.c | |
parent | f0deb97ab13ad1f89cd0993f7339655d59788405 (diff) | |
parent | e04f5f7e423018bcec84c11af2058cdce87816f3 (diff) |
Merge branch 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (115 commits)
EHCI: fix direction handling for interrupt data toggles
USB: serial: add IDs for WinChipHead USB->RS232 adapter
USB: OHCI: fix another regression for NVIDIA controllers
usb: gadget: m66592-udc: add pullup function
usb: gadget: m66592-udc: add function for external controller
usb: gadget: r8a66597-udc: add pullup function
usb: renesas_usbhs: support multi driver
usb: renesas_usbhs: inaccessible pipe is not an error
usb: renesas_usbhs: care buff alignment when dma handler
USB: PL2303: correctly handle baudrates above 115200
usb: r8a66597-hcd: fixup USB_PORT_STAT_C_SUSPEND shift
usb: renesas_usbhs: compile/config are rescued
usb: renesas_usbhs: fixup comment-out
usb: update email address in ohci-sh and r8a66597-hcd
usb: r8a66597-hcd: add function for external controller
EHCI: only power off port if over-current is active
USB: mon: Allow to use usbmon without debugfs
USB: EHCI: go back to using the system clock for QH unlinks
ehci: add pci quirk for Ordissimo and RM Slate 100 too
ehci: refactor pci quirk to use standard dmi_check_system method
...
Fix up trivial conflicts in Documentation/feature-removal-schedule.txt
Diffstat (limited to 'drivers/usb/gadget/f_eem.c')
-rw-r--r-- | drivers/usb/gadget/f_eem.c | 90 |
1 files changed, 66 insertions, 24 deletions
diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c index b3c304290150..046c6d0e6960 100644 --- a/drivers/usb/gadget/f_eem.c +++ b/drivers/usb/gadget/f_eem.c | |||
@@ -35,17 +35,9 @@ | |||
35 | * Ethernet link. | 35 | * Ethernet link. |
36 | */ | 36 | */ |
37 | 37 | ||
38 | struct eem_ep_descs { | ||
39 | struct usb_endpoint_descriptor *in; | ||
40 | struct usb_endpoint_descriptor *out; | ||
41 | }; | ||
42 | |||
43 | struct f_eem { | 38 | struct f_eem { |
44 | struct gether port; | 39 | struct gether port; |
45 | u8 ctrl_id; | 40 | u8 ctrl_id; |
46 | |||
47 | struct eem_ep_descs fs; | ||
48 | struct eem_ep_descs hs; | ||
49 | }; | 41 | }; |
50 | 42 | ||
51 | static inline struct f_eem *func_to_eem(struct usb_function *f) | 43 | static inline struct f_eem *func_to_eem(struct usb_function *f) |
@@ -123,6 +115,45 @@ static struct usb_descriptor_header *eem_hs_function[] __initdata = { | |||
123 | NULL, | 115 | NULL, |
124 | }; | 116 | }; |
125 | 117 | ||
118 | /* super speed support: */ | ||
119 | |||
120 | static struct usb_endpoint_descriptor eem_ss_in_desc __initdata = { | ||
121 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
122 | .bDescriptorType = USB_DT_ENDPOINT, | ||
123 | |||
124 | .bEndpointAddress = USB_DIR_IN, | ||
125 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
126 | .wMaxPacketSize = cpu_to_le16(1024), | ||
127 | }; | ||
128 | |||
129 | static struct usb_endpoint_descriptor eem_ss_out_desc __initdata = { | ||
130 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
131 | .bDescriptorType = USB_DT_ENDPOINT, | ||
132 | |||
133 | .bEndpointAddress = USB_DIR_OUT, | ||
134 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
135 | .wMaxPacketSize = cpu_to_le16(1024), | ||
136 | }; | ||
137 | |||
138 | static struct usb_ss_ep_comp_descriptor eem_ss_bulk_comp_desc __initdata = { | ||
139 | .bLength = sizeof eem_ss_bulk_comp_desc, | ||
140 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | ||
141 | |||
142 | /* the following 2 values can be tweaked if necessary */ | ||
143 | /* .bMaxBurst = 0, */ | ||
144 | /* .bmAttributes = 0, */ | ||
145 | }; | ||
146 | |||
147 | static struct usb_descriptor_header *eem_ss_function[] __initdata = { | ||
148 | /* CDC EEM control descriptors */ | ||
149 | (struct usb_descriptor_header *) &eem_intf, | ||
150 | (struct usb_descriptor_header *) &eem_ss_in_desc, | ||
151 | (struct usb_descriptor_header *) &eem_ss_bulk_comp_desc, | ||
152 | (struct usb_descriptor_header *) &eem_ss_out_desc, | ||
153 | (struct usb_descriptor_header *) &eem_ss_bulk_comp_desc, | ||
154 | NULL, | ||
155 | }; | ||
156 | |||
126 | /* string descriptors: */ | 157 | /* string descriptors: */ |
127 | 158 | ||
128 | static struct usb_string eem_string_defs[] = { | 159 | static struct usb_string eem_string_defs[] = { |
@@ -176,12 +207,16 @@ static int eem_set_alt(struct usb_function *f, unsigned intf, unsigned alt) | |||
176 | gether_disconnect(&eem->port); | 207 | gether_disconnect(&eem->port); |
177 | } | 208 | } |
178 | 209 | ||
179 | if (!eem->port.in) { | 210 | if (!eem->port.in_ep->desc || !eem->port.out_ep->desc) { |
180 | DBG(cdev, "init eem\n"); | 211 | DBG(cdev, "init eem\n"); |
181 | eem->port.in = ep_choose(cdev->gadget, | 212 | if (config_ep_by_speed(cdev->gadget, f, |
182 | eem->hs.in, eem->fs.in); | 213 | eem->port.in_ep) || |
183 | eem->port.out = ep_choose(cdev->gadget, | 214 | config_ep_by_speed(cdev->gadget, f, |
184 | eem->hs.out, eem->fs.out); | 215 | eem->port.out_ep)) { |
216 | eem->port.in_ep->desc = NULL; | ||
217 | eem->port.out_ep->desc = NULL; | ||
218 | goto fail; | ||
219 | } | ||
185 | } | 220 | } |
186 | 221 | ||
187 | /* zlps should not occur because zero-length EEM packets | 222 | /* zlps should not occur because zero-length EEM packets |
@@ -253,11 +288,6 @@ eem_bind(struct usb_configuration *c, struct usb_function *f) | |||
253 | if (!f->descriptors) | 288 | if (!f->descriptors) |
254 | goto fail; | 289 | goto fail; |
255 | 290 | ||
256 | eem->fs.in = usb_find_endpoint(eem_fs_function, | ||
257 | f->descriptors, &eem_fs_in_desc); | ||
258 | eem->fs.out = usb_find_endpoint(eem_fs_function, | ||
259 | f->descriptors, &eem_fs_out_desc); | ||
260 | |||
261 | /* support all relevant hardware speeds... we expect that when | 291 | /* support all relevant hardware speeds... we expect that when |
262 | * hardware is dual speed, all bulk-capable endpoints work at | 292 | * hardware is dual speed, all bulk-capable endpoints work at |
263 | * both speeds | 293 | * both speeds |
@@ -272,14 +302,22 @@ eem_bind(struct usb_configuration *c, struct usb_function *f) | |||
272 | f->hs_descriptors = usb_copy_descriptors(eem_hs_function); | 302 | f->hs_descriptors = usb_copy_descriptors(eem_hs_function); |
273 | if (!f->hs_descriptors) | 303 | if (!f->hs_descriptors) |
274 | goto fail; | 304 | goto fail; |
305 | } | ||
306 | |||
307 | if (gadget_is_superspeed(c->cdev->gadget)) { | ||
308 | eem_ss_in_desc.bEndpointAddress = | ||
309 | eem_fs_in_desc.bEndpointAddress; | ||
310 | eem_ss_out_desc.bEndpointAddress = | ||
311 | eem_fs_out_desc.bEndpointAddress; | ||
275 | 312 | ||
276 | eem->hs.in = usb_find_endpoint(eem_hs_function, | 313 | /* copy descriptors, and track endpoint copies */ |
277 | f->hs_descriptors, &eem_hs_in_desc); | 314 | f->ss_descriptors = usb_copy_descriptors(eem_ss_function); |
278 | eem->hs.out = usb_find_endpoint(eem_hs_function, | 315 | if (!f->ss_descriptors) |
279 | f->hs_descriptors, &eem_hs_out_desc); | 316 | goto fail; |
280 | } | 317 | } |
281 | 318 | ||
282 | DBG(cdev, "CDC Ethernet (EEM): %s speed IN/%s OUT/%s\n", | 319 | DBG(cdev, "CDC Ethernet (EEM): %s speed IN/%s OUT/%s\n", |
320 | gadget_is_superspeed(c->cdev->gadget) ? "super" : | ||
283 | gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", | 321 | gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", |
284 | eem->port.in_ep->name, eem->port.out_ep->name); | 322 | eem->port.in_ep->name, eem->port.out_ep->name); |
285 | return 0; | 323 | return 0; |
@@ -287,11 +325,13 @@ eem_bind(struct usb_configuration *c, struct usb_function *f) | |||
287 | fail: | 325 | fail: |
288 | if (f->descriptors) | 326 | if (f->descriptors) |
289 | usb_free_descriptors(f->descriptors); | 327 | usb_free_descriptors(f->descriptors); |
328 | if (f->hs_descriptors) | ||
329 | usb_free_descriptors(f->hs_descriptors); | ||
290 | 330 | ||
291 | /* we might as well release our claims on endpoints */ | 331 | /* we might as well release our claims on endpoints */ |
292 | if (eem->port.out) | 332 | if (eem->port.out_ep->desc) |
293 | eem->port.out_ep->driver_data = NULL; | 333 | eem->port.out_ep->driver_data = NULL; |
294 | if (eem->port.in) | 334 | if (eem->port.in_ep->desc) |
295 | eem->port.in_ep->driver_data = NULL; | 335 | eem->port.in_ep->driver_data = NULL; |
296 | 336 | ||
297 | ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); | 337 | ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); |
@@ -306,6 +346,8 @@ eem_unbind(struct usb_configuration *c, struct usb_function *f) | |||
306 | 346 | ||
307 | DBG(c->cdev, "eem unbind\n"); | 347 | DBG(c->cdev, "eem unbind\n"); |
308 | 348 | ||
349 | if (gadget_is_superspeed(c->cdev->gadget)) | ||
350 | usb_free_descriptors(f->ss_descriptors); | ||
309 | if (gadget_is_dualspeed(c->cdev->gadget)) | 351 | if (gadget_is_dualspeed(c->cdev->gadget)) |
310 | usb_free_descriptors(f->hs_descriptors); | 352 | usb_free_descriptors(f->hs_descriptors); |
311 | usb_free_descriptors(f->descriptors); | 353 | usb_free_descriptors(f->descriptors); |