]>
Commit | Line | Data |
---|---|---|
232c150a WD |
1 | /* |
2 | * (C) Copyright 2003 | |
3 | * Gerry Hamel, geh@ti.com, Texas Instruments | |
4 | * | |
5 | * Based on | |
6 | * linux/drivers/usbd/ep0.c | |
7 | * | |
8 | * Copyright (c) 2000, 2001, 2002 Lineo | |
9 | * Copyright (c) 2001 Hewlett Packard | |
10 | * | |
11 | * By: | |
12 | * Stuart Lynne <sl@lineo.com>, | |
13 | * Tom Rushworth <tbr@lineo.com>, | |
14 | * Bruce Balden <balden@lineo.com> | |
15 | * | |
16 | * This program is free software; you can redistribute it and/or modify | |
17 | * it under the terms of the GNU General Public License as published by | |
18 | * the Free Software Foundation; either version 2 of the License, or | |
19 | * (at your option) any later version. | |
20 | * | |
21 | * This program is distributed in the hope that it will be useful, | |
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
24 | * GNU General Public License for more details. | |
25 | * | |
26 | * You should have received a copy of the GNU General Public License | |
27 | * along with this program; if not, write to the Free Software | |
28 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
29 | * | |
30 | */ | |
31 | ||
32 | /* | |
33 | * This is the builtin ep0 control function. It implements all required functionality | |
34 | * for responding to control requests (SETUP packets). | |
35 | * | |
36 | * XXX | |
37 | * | |
38 | * Currently we do not pass any SETUP packets (or other) to the configured | |
39 | * function driver. This may need to change. | |
40 | * | |
41 | * XXX | |
42 | */ | |
43 | ||
44 | #include <common.h> | |
45 | ||
46 | #if defined(CONFIG_OMAP1510) && defined(CONFIG_USB_DEVICE) | |
47 | #include "usbdcore.h" | |
48 | ||
49 | #if 0 | |
50 | #define dbg_ep0(lvl,fmt,args...) serial_printf("[%s] %s:%d: "fmt"\n",__FILE__,__FUNCTION__,__LINE__,##args) | |
51 | #else | |
52 | #define dbg_ep0(lvl,fmt,args...) | |
53 | #endif | |
54 | ||
55 | /* EP0 Configuration Set ********************************************************************* */ | |
56 | ||
57 | ||
58 | /** | |
59 | * ep0_get_status - fill in URB data with appropriate status | |
60 | * @device: | |
61 | * @urb: | |
62 | * @index: | |
63 | * @requesttype: | |
64 | * | |
65 | */ | |
66 | static int ep0_get_status (struct usb_device_instance *device, | |
67 | struct urb *urb, int index, int requesttype) | |
68 | { | |
69 | char *cp; | |
70 | ||
71 | urb->actual_length = 2; | |
72 | cp = urb->buffer; | |
73 | cp[0] = cp[1] = 0; | |
74 | ||
75 | switch (requesttype) { | |
76 | case USB_REQ_RECIPIENT_DEVICE: | |
77 | cp[0] = USB_STATUS_SELFPOWERED; | |
78 | break; | |
79 | case USB_REQ_RECIPIENT_INTERFACE: | |
80 | break; | |
81 | case USB_REQ_RECIPIENT_ENDPOINT: | |
82 | cp[0] = usbd_endpoint_halted (device, index); | |
83 | break; | |
84 | case USB_REQ_RECIPIENT_OTHER: | |
85 | urb->actual_length = 0; | |
86 | default: | |
87 | break; | |
88 | } | |
89 | dbg_ep0 (2, "%02x %02x", cp[0], cp[1]); | |
90 | return 0; | |
91 | } | |
92 | ||
93 | /** | |
94 | * ep0_get_one | |
95 | * @device: | |
96 | * @urb: | |
97 | * @result: | |
98 | * | |
99 | * Set a single byte value in the urb send buffer. Return non-zero to signal | |
100 | * a request error. | |
101 | */ | |
102 | static int ep0_get_one (struct usb_device_instance *device, struct urb *urb, | |
103 | __u8 result) | |
104 | { | |
105 | urb->actual_length = 1; /* XXX 2? */ | |
106 | ((char *) urb->buffer)[0] = result; | |
107 | return 0; | |
108 | } | |
109 | ||
110 | /** | |
111 | * copy_config | |
112 | * @urb: pointer to urb | |
113 | * @data: pointer to configuration data | |
114 | * @length: length of data | |
115 | * | |
116 | * Copy configuration data to urb transfer buffer if there is room for it. | |
117 | */ | |
118 | static void copy_config (struct urb *urb, void *data, int max_length, | |
119 | int max_buf) | |
120 | { | |
121 | int available; | |
122 | int length; | |
123 | ||
124 | /*dbg_ep0(3, "-> actual: %d buf: %d max_buf: %d max_length: %d data: %p", */ | |
125 | /* urb->actual_length, urb->buffer_length, max_buf, max_length, data); */ | |
126 | ||
127 | if (!data) { | |
128 | dbg_ep0 (1, "data is NULL"); | |
129 | return; | |
130 | } | |
131 | if (!(length = *(unsigned char *) data)) { | |
132 | dbg_ep0 (1, "length is zero"); | |
133 | return; | |
134 | } | |
135 | ||
136 | if (length > max_length) { | |
137 | dbg_ep0 (1, "length: %d >= max_length: %d", length, | |
138 | max_length); | |
139 | return; | |
140 | } | |
141 | /*dbg_ep0(1, " actual: %d buf: %d max_buf: %d max_length: %d length: %d", */ | |
142 | /* urb->actual_length, urb->buffer_length, max_buf, max_length, length); */ | |
143 | ||
144 | if ((available = | |
145 | /*urb->buffer_length */ max_buf - urb->actual_length) <= 0) { | |
146 | return; | |
147 | } | |
148 | /*dbg_ep0(1, "actual: %d buf: %d max_buf: %d length: %d available: %d", */ | |
149 | /* urb->actual_length, urb->buffer_length, max_buf, length, available); */ | |
150 | ||
151 | if (length > available) { | |
152 | length = available; | |
153 | } | |
154 | /*dbg_ep0(1, "actual: %d buf: %d max_buf: %d length: %d available: %d", */ | |
155 | /* urb->actual_length, urb->buffer_length, max_buf, length, available); */ | |
156 | ||
157 | memcpy (urb->buffer + urb->actual_length, data, length); | |
158 | urb->actual_length += length; | |
159 | ||
160 | dbg_ep0 (3, | |
161 | "copy_config: <- actual: %d buf: %d max_buf: %d max_length: %d available: %d", | |
162 | urb->actual_length, urb->buffer_length, max_buf, max_length, | |
163 | available); | |
164 | } | |
165 | ||
166 | /** | |
167 | * ep0_get_descriptor | |
168 | * @device: | |
169 | * @urb: | |
170 | * @max: | |
171 | * @descriptor_type: | |
172 | * @index: | |
173 | * | |
174 | * Called by ep0_rx_process for a get descriptor device command. Determine what | |
175 | * descriptor is being requested, copy to send buffer. Return zero if ok to send, | |
176 | * return non-zero to signal a request error. | |
177 | */ | |
178 | static int ep0_get_descriptor (struct usb_device_instance *device, | |
179 | struct urb *urb, int max, int descriptor_type, | |
180 | int index) | |
181 | { | |
182 | int port = 0; /* XXX compound device */ | |
183 | char *cp; | |
184 | ||
185 | /*dbg_ep0(3, "max: %x type: %x index: %x", max, descriptor_type, index); */ | |
186 | ||
187 | if (!urb || !urb->buffer || !urb->buffer_length | |
188 | || (urb->buffer_length < 255)) { | |
189 | dbg_ep0 (2, "invalid urb %p", urb); | |
190 | return -1L; | |
191 | } | |
192 | ||
193 | /* setup tx urb */ | |
194 | urb->actual_length = 0; | |
195 | cp = urb->buffer; | |
196 | ||
197 | dbg_ep0 (2, "%s", USBD_DEVICE_DESCRIPTORS (descriptor_type)); | |
198 | ||
199 | switch (descriptor_type) { | |
200 | case USB_DESCRIPTOR_TYPE_DEVICE: | |
201 | { | |
202 | struct usb_device_descriptor *device_descriptor; | |
203 | ||
204 | if (! | |
205 | (device_descriptor = | |
206 | usbd_device_device_descriptor (device, port))) { | |
207 | return -1; | |
208 | } | |
209 | /* copy descriptor for this device */ | |
210 | copy_config (urb, device_descriptor, | |
211 | sizeof (struct usb_device_descriptor), | |
212 | max); | |
213 | ||
214 | /* correct the correct control endpoint 0 max packet size into the descriptor */ | |
215 | device_descriptor = | |
216 | (struct usb_device_descriptor *) urb->buffer; | |
217 | device_descriptor->bMaxPacketSize0 = | |
218 | urb->device->bus->maxpacketsize; | |
219 | ||
220 | } | |
221 | /*dbg_ep0(3, "copied device configuration, actual_length: %x", urb->actual_length); */ | |
222 | break; | |
223 | ||
224 | case USB_DESCRIPTOR_TYPE_CONFIGURATION: | |
225 | { | |
226 | int bNumInterface; | |
227 | struct usb_configuration_descriptor | |
228 | *configuration_descriptor; | |
229 | struct usb_device_descriptor *device_descriptor; | |
230 | ||
231 | if (! | |
232 | (device_descriptor = | |
233 | usbd_device_device_descriptor (device, port))) { | |
234 | return -1; | |
235 | } | |
236 | /*dbg_ep0(2, "%d %d", index, device_descriptor->bNumConfigurations); */ | |
237 | if (index > device_descriptor->bNumConfigurations) { | |
238 | dbg_ep0 (0, "index too large: %d > %d", index, | |
239 | device_descriptor-> | |
240 | bNumConfigurations); | |
241 | return -1; | |
242 | } | |
243 | ||
244 | if (! | |
245 | (configuration_descriptor = | |
246 | usbd_device_configuration_descriptor (device, | |
247 | port, | |
248 | index))) { | |
249 | dbg_ep0 (0, | |
250 | "usbd_device_configuration_descriptor failed: %d", | |
251 | index); | |
252 | return -1; | |
253 | } | |
254 | copy_config (urb, configuration_descriptor, | |
255 | sizeof (struct | |
256 | usb_configuration_descriptor), | |
257 | max); | |
258 | ||
259 | ||
260 | /* iterate across interfaces for specified configuration */ | |
261 | dbg_ep0 (0, "bNumInterfaces: %d", | |
262 | configuration_descriptor->bNumInterfaces); | |
263 | for (bNumInterface = 0; | |
264 | bNumInterface < | |
265 | configuration_descriptor->bNumInterfaces; | |
266 | bNumInterface++) { | |
267 | ||
268 | int bAlternateSetting; | |
269 | struct usb_interface_instance | |
270 | *interface_instance; | |
271 | ||
272 | dbg_ep0 (3, "[%d] bNumInterfaces: %d", | |
273 | bNumInterface, | |
274 | configuration_descriptor->bNumInterfaces); | |
275 | ||
276 | if (! (interface_instance = usbd_device_interface_instance (device, | |
277 | port, index, bNumInterface))) | |
278 | { | |
279 | dbg_ep0 (3, "[%d] interface_instance NULL", | |
280 | bNumInterface); | |
281 | return -1; | |
282 | } | |
283 | /* iterate across interface alternates */ | |
284 | for (bAlternateSetting = 0; | |
285 | bAlternateSetting < interface_instance->alternates; | |
286 | bAlternateSetting++) { | |
287 | /*int class; */ | |
288 | int bNumEndpoint; | |
289 | struct usb_interface_descriptor *interface_descriptor; | |
290 | ||
291 | struct usb_alternate_instance *alternate_instance; | |
292 | ||
293 | dbg_ep0 (3, "[%d:%d] alternates: %d", | |
294 | bNumInterface, | |
295 | bAlternateSetting, | |
296 | interface_instance->alternates); | |
297 | ||
298 | if (! (alternate_instance = usbd_device_alternate_instance (device, port, index, bNumInterface, bAlternateSetting))) { | |
299 | dbg_ep0 (3, "[%d] alternate_instance NULL", | |
300 | bNumInterface); | |
301 | return -1; | |
302 | } | |
303 | /* copy descriptor for this interface */ | |
304 | copy_config (urb, alternate_instance->interface_descriptor, | |
305 | sizeof (struct usb_interface_descriptor), | |
306 | max); | |
307 | ||
308 | /*dbg_ep0(3, "[%d:%d] classes: %d endpoints: %d", bNumInterface, bAlternateSetting, */ | |
309 | /* alternate_instance->classes, alternate_instance->endpoints); */ | |
310 | ||
311 | /* iterate across classes for this alternate interface */ | |
312 | #if 0 | |
313 | for (class = 0; | |
314 | class < alternate_instance->classes; | |
315 | class++) { | |
316 | struct usb_class_descriptor *class_descriptor; | |
317 | /*dbg_ep0(3, "[%d:%d:%d] classes: %d", bNumInterface, bAlternateSetting, */ | |
318 | /* class, alternate_instance->classes); */ | |
319 | if (!(class_descriptor = usbd_device_class_descriptor_index (device, port, index, bNumInterface, bAlternateSetting, class))) { | |
320 | dbg_ep0 (3, "[%d] class NULL", | |
321 | class); | |
322 | return -1; | |
323 | } | |
324 | /* copy descriptor for this class */ | |
325 | copy_config (urb, class_descriptor, | |
326 | sizeof (struct usb_class_descriptor), | |
327 | max); | |
328 | } | |
329 | #endif | |
330 | ||
331 | /* iterate across endpoints for this alternate interface */ | |
332 | interface_descriptor = alternate_instance->interface_descriptor; | |
333 | for (bNumEndpoint = 0; | |
334 | bNumEndpoint < alternate_instance->endpoints; | |
335 | bNumEndpoint++) { | |
336 | struct usb_endpoint_descriptor *endpoint_descriptor; | |
337 | dbg_ep0 (3, "[%d:%d:%d] endpoint: %d", | |
338 | bNumInterface, | |
339 | bAlternateSetting, | |
340 | bNumEndpoint, | |
341 | interface_descriptor-> | |
342 | bNumEndpoints); | |
343 | if (!(endpoint_descriptor = usbd_device_endpoint_descriptor_index (device, port, index, bNumInterface, bAlternateSetting, bNumEndpoint))) { | |
344 | dbg_ep0 (3, "[%d] endpoint NULL", | |
345 | bNumEndpoint); | |
346 | return -1; | |
347 | } | |
348 | /* copy descriptor for this endpoint */ | |
349 | copy_config (urb, endpoint_descriptor, | |
350 | sizeof (struct usb_endpoint_descriptor), | |
351 | max); | |
352 | } | |
353 | } | |
354 | } | |
355 | dbg_ep0 (3, "lengths: %d %d", | |
356 | le16_to_cpu (configuration_descriptor->wTotalLength), | |
357 | urb->actual_length); | |
358 | } | |
359 | break; | |
360 | ||
361 | case USB_DESCRIPTOR_TYPE_STRING: | |
362 | { | |
363 | struct usb_string_descriptor *string_descriptor; | |
364 | ||
365 | if (!(string_descriptor = usbd_get_string (index))) { | |
366 | return -1; | |
367 | } | |
368 | /*dbg_ep0(3, "string_descriptor: %p", string_descriptor); */ | |
369 | copy_config (urb, string_descriptor, string_descriptor->bLength, max); | |
370 | } | |
371 | break; | |
372 | case USB_DESCRIPTOR_TYPE_INTERFACE: | |
373 | return -1; | |
374 | case USB_DESCRIPTOR_TYPE_ENDPOINT: | |
375 | return -1; | |
376 | case USB_DESCRIPTOR_TYPE_HID: | |
377 | { | |
378 | return -1; /* unsupported at this time */ | |
379 | #if 0 | |
380 | int bNumInterface = | |
381 | le16_to_cpu (urb->device_request.wIndex); | |
382 | int bAlternateSetting = 0; | |
383 | int class = 0; | |
384 | struct usb_class_descriptor *class_descriptor; | |
385 | ||
386 | if (!(class_descriptor = | |
387 | usbd_device_class_descriptor_index (device, | |
388 | port, 0, | |
389 | bNumInterface, | |
390 | bAlternateSetting, | |
391 | class)) | |
392 | || class_descriptor->descriptor.hid.bDescriptorType != USB_DT_HID) { | |
393 | dbg_ep0 (3, "[%d] interface is not HID", | |
394 | bNumInterface); | |
395 | return -1; | |
396 | } | |
397 | /* copy descriptor for this class */ | |
398 | copy_config (urb, class_descriptor, | |
399 | class_descriptor->descriptor.hid.bLength, | |
400 | max); | |
401 | #endif | |
402 | } | |
403 | break; | |
404 | case USB_DESCRIPTOR_TYPE_REPORT: | |
405 | { | |
406 | return -1; /* unsupported at this time */ | |
407 | #if 0 | |
408 | int bNumInterface = | |
409 | le16_to_cpu (urb->device_request.wIndex); | |
410 | int bAlternateSetting = 0; | |
411 | int class = 0; | |
412 | struct usb_class_report_descriptor *report_descriptor; | |
413 | ||
414 | if (!(report_descriptor = | |
415 | usbd_device_class_report_descriptor_index | |
416 | (device, port, 0, bNumInterface, | |
417 | bAlternateSetting, class)) | |
418 | || report_descriptor->bDescriptorType != | |
419 | USB_DT_REPORT) { | |
420 | dbg_ep0 (3, "[%d] descriptor is not REPORT", | |
421 | bNumInterface); | |
422 | return -1; | |
423 | } | |
424 | /* copy report descriptor for this class */ | |
425 | /*copy_config(urb, &report_descriptor->bData[0], report_descriptor->wLength, max); */ | |
426 | if (max - urb->actual_length > 0) { | |
427 | int length = | |
428 | MIN (report_descriptor->wLength, | |
429 | max - urb->actual_length); | |
430 | memcpy (urb->buffer + urb->actual_length, | |
431 | &report_descriptor->bData[0], length); | |
432 | urb->actual_length += length; | |
433 | } | |
434 | #endif | |
435 | } | |
436 | break; | |
437 | default: | |
438 | return -1; | |
439 | } | |
440 | ||
441 | ||
442 | dbg_ep0 (1, "urb: buffer: %p buffer_length: %2d actual_length: %2d packet size: %2d", | |
443 | urb->buffer, urb->buffer_length, urb->actual_length, | |
444 | device->bus->endpoint_array[0].tx_packetSize); | |
445 | /* | |
446 | if ((urb->actual_length < max) && !(urb->actual_length % device->bus->endpoint_array[0].tx_packetSize)) { | |
447 | dbg_ep0(0, "adding null byte"); | |
448 | urb->buffer[urb->actual_length++] = 0; | |
449 | dbg_ep0(0, "urb: buffer_length: %2d actual_length: %2d packet size: %2d", | |
450 | urb->buffer_length, urb->actual_length device->bus->endpoint_array[0].tx_packetSize); | |
451 | } | |
452 | */ | |
453 | return 0; | |
454 | ||
455 | } | |
456 | ||
457 | /** | |
458 | * ep0_recv_setup - called to indicate URB has been received | |
459 | * @urb: pointer to struct urb | |
460 | * | |
461 | * Check if this is a setup packet, process the device request, put results | |
462 | * back into the urb and return zero or non-zero to indicate success (DATA) | |
463 | * or failure (STALL). | |
464 | * | |
465 | */ | |
466 | int ep0_recv_setup (struct urb *urb) | |
467 | { | |
468 | /*struct usb_device_request *request = urb->buffer; */ | |
469 | /*struct usb_device_instance *device = urb->device; */ | |
470 | ||
471 | struct usb_device_request *request; | |
472 | struct usb_device_instance *device; | |
473 | int address; | |
474 | ||
475 | dbg_ep0 (0, "entering ep0_recv_setup()"); | |
476 | if (!urb || !urb->device) { | |
477 | dbg_ep0 (3, "invalid URB %p", urb); | |
478 | return -1; | |
479 | } | |
480 | ||
481 | request = &urb->device_request; | |
482 | device = urb->device; | |
483 | ||
484 | dbg_ep0 (3, "urb: %p device: %p", urb, urb->device); | |
485 | ||
486 | ||
487 | /*dbg_ep0(2, "- - - - - - - - - -"); */ | |
488 | ||
489 | dbg_ep0 (2, | |
490 | "bmRequestType:%02x bRequest:%02x wValue:%04x wIndex:%04x wLength:%04x %s", | |
491 | request->bmRequestType, request->bRequest, | |
492 | le16_to_cpu (request->wValue), le16_to_cpu (request->wIndex), | |
493 | le16_to_cpu (request->wLength), | |
494 | USBD_DEVICE_REQUESTS (request->bRequest)); | |
495 | ||
496 | /* handle USB Standard Request (c.f. USB Spec table 9-2) */ | |
497 | if ((request->bmRequestType & USB_REQ_TYPE_MASK) != 0) { | |
498 | dbg_ep0 (1, "non standard request: %x", | |
499 | request->bmRequestType & USB_REQ_TYPE_MASK); | |
500 | return -1; /* Stall here */ | |
501 | } | |
502 | ||
503 | switch (device->device_state) { | |
504 | case STATE_CREATED: | |
505 | case STATE_ATTACHED: | |
506 | case STATE_POWERED: | |
507 | /* It actually is important to allow requests in these states, | |
508 | * Windows will request descriptors before assigning an | |
509 | * address to the client. | |
510 | */ | |
511 | ||
512 | /*dbg_ep0 (1, "request %s not allowed in this state: %s", */ | |
513 | /* USBD_DEVICE_REQUESTS(request->bRequest), */ | |
514 | /* usbd_device_states[device->device_state]); */ | |
515 | /*return -1; */ | |
516 | break; | |
517 | ||
518 | case STATE_INIT: | |
519 | case STATE_DEFAULT: | |
520 | switch (request->bRequest) { | |
521 | case USB_REQ_GET_STATUS: | |
522 | case USB_REQ_GET_INTERFACE: | |
523 | case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */ | |
524 | case USB_REQ_CLEAR_FEATURE: | |
525 | case USB_REQ_SET_FEATURE: | |
526 | case USB_REQ_SET_DESCRIPTOR: | |
527 | /* case USB_REQ_SET_CONFIGURATION: */ | |
528 | case USB_REQ_SET_INTERFACE: | |
529 | dbg_ep0 (1, | |
530 | "request %s not allowed in DEFAULT state: %s", | |
531 | USBD_DEVICE_REQUESTS (request->bRequest), | |
532 | usbd_device_states[device->device_state]); | |
533 | return -1; | |
534 | ||
535 | case USB_REQ_SET_CONFIGURATION: | |
536 | case USB_REQ_SET_ADDRESS: | |
537 | case USB_REQ_GET_DESCRIPTOR: | |
538 | case USB_REQ_GET_CONFIGURATION: | |
539 | break; | |
540 | } | |
541 | case STATE_ADDRESSED: | |
542 | case STATE_CONFIGURED: | |
543 | break; | |
544 | case STATE_UNKNOWN: | |
545 | dbg_ep0 (1, "request %s not allowed in UNKNOWN state: %s", | |
546 | USBD_DEVICE_REQUESTS (request->bRequest), | |
547 | usbd_device_states[device->device_state]); | |
548 | return -1; | |
549 | } | |
550 | ||
551 | /* handle all requests that return data (direction bit set on bm RequestType) */ | |
552 | if ((request->bmRequestType & USB_REQ_DIRECTION_MASK)) { | |
553 | ||
554 | dbg_ep0 (3, "Device-to-Host"); | |
555 | ||
556 | switch (request->bRequest) { | |
557 | ||
558 | case USB_REQ_GET_STATUS: | |
559 | return ep0_get_status (device, urb, request->wIndex, | |
560 | request->bmRequestType & | |
561 | USB_REQ_RECIPIENT_MASK); | |
562 | ||
563 | case USB_REQ_GET_DESCRIPTOR: | |
564 | return ep0_get_descriptor (device, urb, | |
565 | le16_to_cpu (request->wLength), | |
566 | le16_to_cpu (request->wValue) >> 8, | |
567 | le16_to_cpu (request->wValue) & 0xff); | |
568 | ||
569 | case USB_REQ_GET_CONFIGURATION: | |
570 | return ep0_get_one (device, urb, | |
571 | device->configuration); | |
572 | ||
573 | case USB_REQ_GET_INTERFACE: | |
574 | return ep0_get_one (device, urb, device->alternate); | |
575 | ||
576 | case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */ | |
577 | return -1; | |
578 | ||
579 | case USB_REQ_CLEAR_FEATURE: | |
580 | case USB_REQ_SET_FEATURE: | |
581 | case USB_REQ_SET_ADDRESS: | |
582 | case USB_REQ_SET_DESCRIPTOR: | |
583 | case USB_REQ_SET_CONFIGURATION: | |
584 | case USB_REQ_SET_INTERFACE: | |
585 | return -1; | |
586 | } | |
587 | } | |
588 | /* handle the requests that do not return data */ | |
589 | else { | |
590 | ||
591 | ||
592 | /*dbg_ep0(3, "Host-to-Device"); */ | |
593 | switch (request->bRequest) { | |
594 | ||
595 | case USB_REQ_CLEAR_FEATURE: | |
596 | case USB_REQ_SET_FEATURE: | |
597 | dbg_ep0 (0, "Host-to-Device"); | |
598 | switch (request-> | |
599 | bmRequestType & USB_REQ_RECIPIENT_MASK) { | |
600 | case USB_REQ_RECIPIENT_DEVICE: | |
601 | /* XXX DEVICE_REMOTE_WAKEUP or TEST_MODE would be added here */ | |
602 | /* XXX fall through for now as we do not support either */ | |
603 | case USB_REQ_RECIPIENT_INTERFACE: | |
604 | case USB_REQ_RECIPIENT_OTHER: | |
605 | dbg_ep0 (0, "request %s not", | |
606 | USBD_DEVICE_REQUESTS (request->bRequest)); | |
607 | default: | |
608 | return -1; | |
609 | ||
610 | case USB_REQ_RECIPIENT_ENDPOINT: | |
611 | dbg_ep0 (0, "ENDPOINT: %x", le16_to_cpu (request->wValue)); | |
612 | if (le16_to_cpu (request->wValue) == USB_ENDPOINT_HALT) { | |
613 | /*return usbd_device_feature (device, le16_to_cpu (request->wIndex), */ | |
614 | /* request->bRequest == USB_REQ_SET_FEATURE); */ | |
615 | /* NEED TO IMPLEMENT THIS!!! */ | |
616 | return -1; | |
617 | } else { | |
618 | dbg_ep0 (1, "request %s bad wValue: %04x", | |
619 | USBD_DEVICE_REQUESTS | |
620 | (request->bRequest), | |
621 | le16_to_cpu (request->wValue)); | |
622 | return -1; | |
623 | } | |
624 | } | |
625 | ||
626 | case USB_REQ_SET_ADDRESS: | |
627 | /* check if this is a re-address, reset first if it is (this shouldn't be possible) */ | |
628 | if (device->device_state != STATE_DEFAULT) { | |
629 | dbg_ep0 (1, "set_address: %02x state: %s", | |
630 | le16_to_cpu (request->wValue), | |
631 | usbd_device_states[device->device_state]); | |
632 | return -1; | |
633 | } | |
634 | address = le16_to_cpu (request->wValue); | |
635 | if ((address & 0x7f) != address) { | |
636 | dbg_ep0 (1, "invalid address %04x %04x", | |
637 | address, address & 0x7f); | |
638 | return -1; | |
639 | } | |
640 | device->address = address; | |
641 | ||
642 | /*dbg_ep0(2, "address: %d %d %d", */ | |
643 | /* request->wValue, le16_to_cpu(request->wValue), device->address); */ | |
644 | ||
645 | serial_printf ("DEVICE_ADDRESS_ASSIGNED.. event?\n"); | |
646 | return 0; | |
647 | ||
648 | case USB_REQ_SET_DESCRIPTOR: /* XXX should we support this? */ | |
649 | dbg_ep0 (0, "set descriptor: NOT SUPPORTED"); | |
650 | return -1; | |
651 | ||
652 | case USB_REQ_SET_CONFIGURATION: | |
653 | /* c.f. 9.4.7 - the top half of wValue is reserved */ | |
654 | /* */ | |
655 | if ((device->configuration = | |
656 | le16_to_cpu (request->wValue) & 0x7f) != 0) { | |
657 | /* c.f. 9.4.7 - zero is the default or addressed state, in our case this */ | |
658 | /* is the same is configuration zero */ | |
659 | device->configuration = 0; /* TBR - ?????? */ | |
660 | } | |
661 | /* reset interface and alternate settings */ | |
662 | device->interface = device->alternate = 0; | |
663 | ||
664 | /*dbg_ep0(2, "set configuration: %d", device->configuration); */ | |
665 | /*serial_printf("DEVICE_CONFIGURED.. event?\n"); */ | |
666 | return 0; | |
667 | ||
668 | case USB_REQ_SET_INTERFACE: | |
669 | device->interface = le16_to_cpu (request->wIndex); | |
670 | device->alternate = le16_to_cpu (request->wValue); | |
671 | /*dbg_ep0(2, "set interface: %d alternate: %d", device->interface, device->alternate); */ | |
672 | serial_printf ("DEVICE_SET_INTERFACE.. event?\n"); | |
673 | return 0; | |
674 | ||
675 | case USB_REQ_GET_STATUS: | |
676 | case USB_REQ_GET_DESCRIPTOR: | |
677 | case USB_REQ_GET_CONFIGURATION: | |
678 | case USB_REQ_GET_INTERFACE: | |
679 | case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */ | |
680 | return -1; | |
681 | } | |
682 | } | |
683 | return -1; | |
684 | } | |
685 | ||
686 | #endif |