diff options
author | Tatyana Brokhman <tlinder@codeaurora.org> | 2011-06-28 09:33:49 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-06-28 14:14:36 -0400 |
commit | 48767a4e8263620c347c3fa17812c943dd0fc2fa (patch) | |
tree | 2859b92667049c57cae1c6ca02fd7897d6f3534f /drivers/usb/gadget/composite.c | |
parent | 72c973dd2b01b212a159faa330a2bc641a3ed809 (diff) |
usb: gadget: configure endpoint according to gadget speed
Add config_ep_by_speed() to configure the endpoint
according to the gadget speed.
Using this function will spare the FDs from handling
the endpoint chosen descriptor.
Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget/composite.c')
-rw-r--r-- | drivers/usb/gadget/composite.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 5cbb1a41c223..1c6bd666150a 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c | |||
@@ -74,6 +74,91 @@ MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); | |||
74 | static char composite_manufacturer[50]; | 74 | static char composite_manufacturer[50]; |
75 | 75 | ||
76 | /*-------------------------------------------------------------------------*/ | 76 | /*-------------------------------------------------------------------------*/ |
77 | /** | ||
78 | * next_ep_desc() - advance to the next EP descriptor | ||
79 | * @t: currect pointer within descriptor array | ||
80 | * | ||
81 | * Return: next EP descriptor or NULL | ||
82 | * | ||
83 | * Iterate over @t until either EP descriptor found or | ||
84 | * NULL (that indicates end of list) encountered | ||
85 | */ | ||
86 | static struct usb_descriptor_header** | ||
87 | next_ep_desc(struct usb_descriptor_header **t) | ||
88 | { | ||
89 | for (; *t; t++) { | ||
90 | if ((*t)->bDescriptorType == USB_DT_ENDPOINT) | ||
91 | return t; | ||
92 | } | ||
93 | return NULL; | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * for_each_ep_desc()- iterate over endpoint descriptors in the | ||
98 | * descriptors list | ||
99 | * @start: pointer within descriptor array. | ||
100 | * @ep_desc: endpoint descriptor to use as the loop cursor | ||
101 | */ | ||
102 | #define for_each_ep_desc(start, ep_desc) \ | ||
103 | for (ep_desc = next_ep_desc(start); \ | ||
104 | ep_desc; ep_desc = next_ep_desc(ep_desc+1)) | ||
105 | |||
106 | /** | ||
107 | * config_ep_by_speed() - configures the given endpoint | ||
108 | * according to gadget speed. | ||
109 | * @g: pointer to the gadget | ||
110 | * @f: usb function | ||
111 | * @_ep: the endpoint to configure | ||
112 | * | ||
113 | * Return: error code, 0 on success | ||
114 | * | ||
115 | * This function chooses the right descriptors for a given | ||
116 | * endpoint according to gadget speed and saves it in the | ||
117 | * endpoint desc field. If the endpoint already has a descriptor | ||
118 | * assigned to it - overwrites it with currently corresponding | ||
119 | * descriptor. The endpoint maxpacket field is updated according | ||
120 | * to the chosen descriptor. | ||
121 | * Note: the supplied function should hold all the descriptors | ||
122 | * for supported speeds | ||
123 | */ | ||
124 | int config_ep_by_speed(struct usb_gadget *g, | ||
125 | struct usb_function *f, | ||
126 | struct usb_ep *_ep) | ||
127 | { | ||
128 | struct usb_endpoint_descriptor *chosen_desc = NULL; | ||
129 | struct usb_descriptor_header **speed_desc = NULL; | ||
130 | |||
131 | struct usb_descriptor_header **d_spd; /* cursor for speed desc */ | ||
132 | |||
133 | if (!g || !f || !_ep) | ||
134 | return -EIO; | ||
135 | |||
136 | /* select desired speed */ | ||
137 | switch (g->speed) { | ||
138 | case USB_SPEED_HIGH: | ||
139 | if (gadget_is_dualspeed(g)) { | ||
140 | speed_desc = f->hs_descriptors; | ||
141 | break; | ||
142 | } | ||
143 | /* else: fall through */ | ||
144 | default: | ||
145 | speed_desc = f->descriptors; | ||
146 | } | ||
147 | /* find descriptors */ | ||
148 | for_each_ep_desc(speed_desc, d_spd) { | ||
149 | chosen_desc = (struct usb_endpoint_descriptor *)*d_spd; | ||
150 | if (chosen_desc->bEndpointAddress == _ep->address) | ||
151 | goto ep_found; | ||
152 | } | ||
153 | return -EIO; | ||
154 | |||
155 | ep_found: | ||
156 | /* commit results */ | ||
157 | _ep->maxpacket = le16_to_cpu(chosen_desc->wMaxPacketSize); | ||
158 | _ep->desc = chosen_desc; | ||
159 | |||
160 | return 0; | ||
161 | } | ||
77 | 162 | ||
78 | /** | 163 | /** |
79 | * usb_add_function() - add a function to a configuration | 164 | * usb_add_function() - add a function to a configuration |