blob: 6624f61b763c46ffa3fe304064bfe597f84c1955 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenk232c1502004-03-12 00:14:09 +00002/*
3 * (C) Copyright 2003
4 * Gerry Hamel, geh@ti.com, Texas Instruments
5 *
Wolfgang Denk16c8d5e2006-06-14 17:45:53 +02006 * (C) Copyright 2006
7 * Bryan O'Donoghue, deckard@CodeHermit.ie
8 *
wdenk232c1502004-03-12 00:14:09 +00009 * Based on
10 * linux/drivers/usbd/ep0.c
11 *
12 * Copyright (c) 2000, 2001, 2002 Lineo
13 * Copyright (c) 2001 Hewlett Packard
14 *
15 * By:
16 * Stuart Lynne <sl@lineo.com>,
17 * Tom Rushworth <tbr@lineo.com>,
18 * Bruce Balden <balden@lineo.com>
wdenk232c1502004-03-12 00:14:09 +000019 */
20
21/*
22 * This is the builtin ep0 control function. It implements all required functionality
23 * for responding to control requests (SETUP packets).
24 *
25 * XXX
26 *
27 * Currently we do not pass any SETUP packets (or other) to the configured
28 * function driver. This may need to change.
29 *
30 * XXX
Wolfgang Denk16c8d5e2006-06-14 17:45:53 +020031 *
32 * As alluded to above, a simple callback cdc_recv_setup has been implemented
Wolfgang Denk386eda02006-06-14 18:14:56 +020033 * in the usb_device data structure to facilicate passing
Wolfgang Denk16c8d5e2006-06-14 17:45:53 +020034 * Common Device Class packets to a function driver.
35 *
36 * XXX
wdenk232c1502004-03-12 00:14:09 +000037 */
38
39#include <common.h>
Simon Glassf516fd92019-11-14 12:57:23 -070040#include <serial.h>
Jean-Christophe PLAGNIOL-VILLARD2731b9a2009-04-03 12:46:58 +020041#include <usbdevice.h>
wdenk232c1502004-03-12 00:14:09 +000042
43#if 0
44#define dbg_ep0(lvl,fmt,args...) serial_printf("[%s] %s:%d: "fmt"\n",__FILE__,__FUNCTION__,__LINE__,##args)
45#else
46#define dbg_ep0(lvl,fmt,args...)
47#endif
48
Pali Rohárf2fa4992020-12-26 19:12:11 +010049__maybe_unused static char *usbd_device_descriptors[] = {
50 "UNKNOWN", /* 0 */
51 "DEVICE", /* 1 */
52 "CONFIG", /* 2 */
53 "STRING", /* 3 */
54 "INTERFACE", /* 4 */
55 "ENDPOINT", /* 5 */
56 "DEVICE QUALIFIER", /* 6 */
57 "OTHER SPEED", /* 7 */
58 "INTERFACE POWER", /* 8 */
59};
60
61#define USBD_DEVICE_DESCRIPTORS(x) (((unsigned int)x <= USB_DESCRIPTOR_TYPE_INTERFACE_POWER) ? \
62 usbd_device_descriptors[x] : "UNKNOWN")
63
64__maybe_unused static char *usbd_device_states[] = {
65 "STATE_INIT",
66 "STATE_CREATED",
67 "STATE_ATTACHED",
68 "STATE_POWERED",
69 "STATE_DEFAULT",
70 "STATE_ADDRESSED",
71 "STATE_CONFIGURED",
72 "STATE_UNKNOWN",
73};
74
75#define USBD_DEVICE_STATE(x) (((unsigned int)x <= STATE_UNKNOWN) ? usbd_device_states[x] : "UNKNOWN")
76
77__maybe_unused static char *usbd_device_requests[] = {
78 "GET STATUS", /* 0 */
79 "CLEAR FEATURE", /* 1 */
80 "RESERVED", /* 2 */
81 "SET FEATURE", /* 3 */
82 "RESERVED", /* 4 */
83 "SET ADDRESS", /* 5 */
84 "GET DESCRIPTOR", /* 6 */
85 "SET DESCRIPTOR", /* 7 */
86 "GET CONFIGURATION", /* 8 */
87 "SET CONFIGURATION", /* 9 */
88 "GET INTERFACE", /* 10 */
89 "SET INTERFACE", /* 11 */
90 "SYNC FRAME", /* 12 */
91};
92
93#define USBD_DEVICE_REQUESTS(x) (((unsigned int)x <= USB_REQ_SYNCH_FRAME) ? usbd_device_requests[x] : "UNKNOWN")
94
wdenk232c1502004-03-12 00:14:09 +000095/* EP0 Configuration Set ********************************************************************* */
96
97
98/**
99 * ep0_get_status - fill in URB data with appropriate status
100 * @device:
101 * @urb:
102 * @index:
103 * @requesttype:
104 *
105 */
106static int ep0_get_status (struct usb_device_instance *device,
107 struct urb *urb, int index, int requesttype)
108{
109 char *cp;
110
111 urb->actual_length = 2;
Wolfgang Denk16c8d5e2006-06-14 17:45:53 +0200112 cp = (char*)urb->buffer;
wdenk232c1502004-03-12 00:14:09 +0000113 cp[0] = cp[1] = 0;
114
115 switch (requesttype) {
116 case USB_REQ_RECIPIENT_DEVICE:
117 cp[0] = USB_STATUS_SELFPOWERED;
118 break;
119 case USB_REQ_RECIPIENT_INTERFACE:
120 break;
121 case USB_REQ_RECIPIENT_ENDPOINT:
122 cp[0] = usbd_endpoint_halted (device, index);
123 break;
124 case USB_REQ_RECIPIENT_OTHER:
125 urb->actual_length = 0;
126 default:
127 break;
128 }
129 dbg_ep0 (2, "%02x %02x", cp[0], cp[1]);
130 return 0;
131}
132
133/**
134 * ep0_get_one
135 * @device:
136 * @urb:
137 * @result:
138 *
139 * Set a single byte value in the urb send buffer. Return non-zero to signal
140 * a request error.
141 */
142static int ep0_get_one (struct usb_device_instance *device, struct urb *urb,
143 __u8 result)
144{
145 urb->actual_length = 1; /* XXX 2? */
146 ((char *) urb->buffer)[0] = result;
147 return 0;
148}
149
150/**
151 * copy_config
152 * @urb: pointer to urb
153 * @data: pointer to configuration data
154 * @length: length of data
155 *
156 * Copy configuration data to urb transfer buffer if there is room for it.
157 */
Wolfgang Denk16c8d5e2006-06-14 17:45:53 +0200158void copy_config (struct urb *urb, void *data, int max_length,
wdenk232c1502004-03-12 00:14:09 +0000159 int max_buf)
160{
161 int available;
162 int length;
163
164 /*dbg_ep0(3, "-> actual: %d buf: %d max_buf: %d max_length: %d data: %p", */
165 /* urb->actual_length, urb->buffer_length, max_buf, max_length, data); */
166
167 if (!data) {
168 dbg_ep0 (1, "data is NULL");
169 return;
170 }
Wolfgang Denk16c8d5e2006-06-14 17:45:53 +0200171 length = max_length;
wdenk232c1502004-03-12 00:14:09 +0000172
173 if (length > max_length) {
174 dbg_ep0 (1, "length: %d >= max_length: %d", length,
175 max_length);
176 return;
177 }
178 /*dbg_ep0(1, " actual: %d buf: %d max_buf: %d max_length: %d length: %d", */
179 /* urb->actual_length, urb->buffer_length, max_buf, max_length, length); */
180
181 if ((available =
182 /*urb->buffer_length */ max_buf - urb->actual_length) <= 0) {
183 return;
184 }
185 /*dbg_ep0(1, "actual: %d buf: %d max_buf: %d length: %d available: %d", */
186 /* urb->actual_length, urb->buffer_length, max_buf, length, available); */
187
188 if (length > available) {
189 length = available;
190 }
191 /*dbg_ep0(1, "actual: %d buf: %d max_buf: %d length: %d available: %d", */
192 /* urb->actual_length, urb->buffer_length, max_buf, length, available); */
193
194 memcpy (urb->buffer + urb->actual_length, data, length);
195 urb->actual_length += length;
196
197 dbg_ep0 (3,
198 "copy_config: <- actual: %d buf: %d max_buf: %d max_length: %d available: %d",
199 urb->actual_length, urb->buffer_length, max_buf, max_length,
200 available);
201}
202
203/**
204 * ep0_get_descriptor
205 * @device:
206 * @urb:
207 * @max:
208 * @descriptor_type:
209 * @index:
210 *
211 * Called by ep0_rx_process for a get descriptor device command. Determine what
212 * descriptor is being requested, copy to send buffer. Return zero if ok to send,
213 * return non-zero to signal a request error.
214 */
215static int ep0_get_descriptor (struct usb_device_instance *device,
216 struct urb *urb, int max, int descriptor_type,
217 int index)
218{
219 int port = 0; /* XXX compound device */
wdenk232c1502004-03-12 00:14:09 +0000220
221 /*dbg_ep0(3, "max: %x type: %x index: %x", max, descriptor_type, index); */
222
223 if (!urb || !urb->buffer || !urb->buffer_length
224 || (urb->buffer_length < 255)) {
225 dbg_ep0 (2, "invalid urb %p", urb);
226 return -1L;
227 }
228
229 /* setup tx urb */
230 urb->actual_length = 0;
wdenk232c1502004-03-12 00:14:09 +0000231
232 dbg_ep0 (2, "%s", USBD_DEVICE_DESCRIPTORS (descriptor_type));
233
234 switch (descriptor_type) {
235 case USB_DESCRIPTOR_TYPE_DEVICE:
236 {
237 struct usb_device_descriptor *device_descriptor;
wdenk232c1502004-03-12 00:14:09 +0000238 if (!
239 (device_descriptor =
240 usbd_device_device_descriptor (device, port))) {
241 return -1;
242 }
243 /* copy descriptor for this device */
244 copy_config (urb, device_descriptor,
245 sizeof (struct usb_device_descriptor),
246 max);
247
248 /* correct the correct control endpoint 0 max packet size into the descriptor */
249 device_descriptor =
250 (struct usb_device_descriptor *) urb->buffer;
wdenk232c1502004-03-12 00:14:09 +0000251
252 }
Wolfgang Denk386eda02006-06-14 18:14:56 +0200253 dbg_ep0(3, "copied device configuration, actual_length: 0x%x", urb->actual_length);
wdenk232c1502004-03-12 00:14:09 +0000254 break;
255
256 case USB_DESCRIPTOR_TYPE_CONFIGURATION:
257 {
wdenk232c1502004-03-12 00:14:09 +0000258 struct usb_configuration_descriptor
259 *configuration_descriptor;
260 struct usb_device_descriptor *device_descriptor;
wdenk232c1502004-03-12 00:14:09 +0000261 if (!
262 (device_descriptor =
263 usbd_device_device_descriptor (device, port))) {
264 return -1;
265 }
266 /*dbg_ep0(2, "%d %d", index, device_descriptor->bNumConfigurations); */
Harald Weltee73b5212008-07-07 00:58:05 +0800267 if (index >= device_descriptor->bNumConfigurations) {
268 dbg_ep0 (0, "index too large: %d >= %d", index,
wdenk232c1502004-03-12 00:14:09 +0000269 device_descriptor->
270 bNumConfigurations);
271 return -1;
272 }
273
274 if (!
275 (configuration_descriptor =
276 usbd_device_configuration_descriptor (device,
277 port,
278 index))) {
279 dbg_ep0 (0,
280 "usbd_device_configuration_descriptor failed: %d",
281 index);
282 return -1;
283 }
Wolfgang Denk16c8d5e2006-06-14 17:45:53 +0200284 dbg_ep0(0, "attempt to copy %d bytes to urb\n",cpu_to_le16(configuration_descriptor->wTotalLength));
wdenk232c1502004-03-12 00:14:09 +0000285 copy_config (urb, configuration_descriptor,
Wolfgang Denk16c8d5e2006-06-14 17:45:53 +0200286
287 cpu_to_le16(configuration_descriptor->wTotalLength),
wdenk232c1502004-03-12 00:14:09 +0000288 max);
wdenk232c1502004-03-12 00:14:09 +0000289 }
Wolfgang Denk16c8d5e2006-06-14 17:45:53 +0200290
wdenk232c1502004-03-12 00:14:09 +0000291 break;
292
293 case USB_DESCRIPTOR_TYPE_STRING:
294 {
295 struct usb_string_descriptor *string_descriptor;
wdenk232c1502004-03-12 00:14:09 +0000296 if (!(string_descriptor = usbd_get_string (index))) {
Pali Rohár7f985752021-02-07 14:50:11 +0100297 dbg_ep0(0, "Invalid string index %d\n", index);
wdenk232c1502004-03-12 00:14:09 +0000298 return -1;
299 }
Wolfgang Denk386eda02006-06-14 18:14:56 +0200300 dbg_ep0(3, "string_descriptor: %p length %d", string_descriptor, string_descriptor->bLength);
wdenk232c1502004-03-12 00:14:09 +0000301 copy_config (urb, string_descriptor, string_descriptor->bLength, max);
302 }
303 break;
304 case USB_DESCRIPTOR_TYPE_INTERFACE:
Pali Rohár7f985752021-02-07 14:50:11 +0100305 dbg_ep0(2, "USB_DESCRIPTOR_TYPE_INTERFACE - error not implemented\n");
wdenk232c1502004-03-12 00:14:09 +0000306 return -1;
307 case USB_DESCRIPTOR_TYPE_ENDPOINT:
Pali Rohár7f985752021-02-07 14:50:11 +0100308 dbg_ep0(2, "USB_DESCRIPTOR_TYPE_ENDPOINT - error not implemented\n");
wdenk232c1502004-03-12 00:14:09 +0000309 return -1;
310 case USB_DESCRIPTOR_TYPE_HID:
311 {
Pali Rohár7f985752021-02-07 14:50:11 +0100312 dbg_ep0(2, "USB_DESCRIPTOR_TYPE_HID - error not implemented\n");
wdenk232c1502004-03-12 00:14:09 +0000313 return -1; /* unsupported at this time */
314#if 0
315 int bNumInterface =
316 le16_to_cpu (urb->device_request.wIndex);
317 int bAlternateSetting = 0;
318 int class = 0;
319 struct usb_class_descriptor *class_descriptor;
320
321 if (!(class_descriptor =
322 usbd_device_class_descriptor_index (device,
323 port, 0,
324 bNumInterface,
325 bAlternateSetting,
326 class))
327 || class_descriptor->descriptor.hid.bDescriptorType != USB_DT_HID) {
328 dbg_ep0 (3, "[%d] interface is not HID",
329 bNumInterface);
330 return -1;
331 }
332 /* copy descriptor for this class */
333 copy_config (urb, class_descriptor,
334 class_descriptor->descriptor.hid.bLength,
335 max);
336#endif
337 }
338 break;
339 case USB_DESCRIPTOR_TYPE_REPORT:
340 {
Pali Rohár7f985752021-02-07 14:50:11 +0100341 dbg_ep0(2, "USB_DESCRIPTOR_TYPE_REPORT - error not implemented\n");
wdenk232c1502004-03-12 00:14:09 +0000342 return -1; /* unsupported at this time */
343#if 0
344 int bNumInterface =
345 le16_to_cpu (urb->device_request.wIndex);
346 int bAlternateSetting = 0;
347 int class = 0;
348 struct usb_class_report_descriptor *report_descriptor;
349
350 if (!(report_descriptor =
351 usbd_device_class_report_descriptor_index
352 (device, port, 0, bNumInterface,
353 bAlternateSetting, class))
354 || report_descriptor->bDescriptorType !=
355 USB_DT_REPORT) {
356 dbg_ep0 (3, "[%d] descriptor is not REPORT",
357 bNumInterface);
358 return -1;
359 }
360 /* copy report descriptor for this class */
361 /*copy_config(urb, &report_descriptor->bData[0], report_descriptor->wLength, max); */
362 if (max - urb->actual_length > 0) {
363 int length =
Masahiro Yamadac79cba32014-09-18 13:28:06 +0900364 min(report_descriptor->wLength,
wdenk232c1502004-03-12 00:14:09 +0000365 max - urb->actual_length);
366 memcpy (urb->buffer + urb->actual_length,
367 &report_descriptor->bData[0], length);
368 urb->actual_length += length;
369 }
370#endif
371 }
372 break;
Wolfgang Denk16c8d5e2006-06-14 17:45:53 +0200373 case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
Vipin KUMARf9da0f82012-03-26 15:38:06 +0530374#if defined(CONFIG_USBD_HS)
Wolfgang Denk16c8d5e2006-06-14 17:45:53 +0200375 {
Vipin KUMARf9da0f82012-03-26 15:38:06 +0530376 struct usb_qualifier_descriptor *qualifier_descriptor =
377 device->qualifier_descriptor;
378
379 if (!qualifier_descriptor)
380 return -1;
381
382 /* copy descriptor for this device */
383 copy_config(urb, qualifier_descriptor,
384 sizeof(struct usb_qualifier_descriptor),
385 max);
386
Wolfgang Denk16c8d5e2006-06-14 17:45:53 +0200387 }
Vipin KUMARf9da0f82012-03-26 15:38:06 +0530388 dbg_ep0(3, "copied qualifier descriptor, actual_length: 0x%x",
389 urb->actual_length);
390#else
391 return -1;
392#endif
393 break;
394
wdenk232c1502004-03-12 00:14:09 +0000395 default:
396 return -1;
397 }
398
399
Wolfgang Denk16c8d5e2006-06-14 17:45:53 +0200400 dbg_ep0 (1, "urb: buffer: %p buffer_length: %2d actual_length: %2d tx_packetSize: %2d",
wdenk232c1502004-03-12 00:14:09 +0000401 urb->buffer, urb->buffer_length, urb->actual_length,
402 device->bus->endpoint_array[0].tx_packetSize);
403/*
404 if ((urb->actual_length < max) && !(urb->actual_length % device->bus->endpoint_array[0].tx_packetSize)) {
405 dbg_ep0(0, "adding null byte");
406 urb->buffer[urb->actual_length++] = 0;
407 dbg_ep0(0, "urb: buffer_length: %2d actual_length: %2d packet size: %2d",
408 urb->buffer_length, urb->actual_length device->bus->endpoint_array[0].tx_packetSize);
409 }
410*/
411 return 0;
412
413}
414
415/**
416 * ep0_recv_setup - called to indicate URB has been received
417 * @urb: pointer to struct urb
418 *
419 * Check if this is a setup packet, process the device request, put results
420 * back into the urb and return zero or non-zero to indicate success (DATA)
421 * or failure (STALL).
422 *
423 */
424int ep0_recv_setup (struct urb *urb)
425{
426 /*struct usb_device_request *request = urb->buffer; */
427 /*struct usb_device_instance *device = urb->device; */
428
429 struct usb_device_request *request;
430 struct usb_device_instance *device;
431 int address;
432
433 dbg_ep0 (0, "entering ep0_recv_setup()");
434 if (!urb || !urb->device) {
435 dbg_ep0 (3, "invalid URB %p", urb);
436 return -1;
437 }
438
439 request = &urb->device_request;
440 device = urb->device;
441
442 dbg_ep0 (3, "urb: %p device: %p", urb, urb->device);
443
444
445 /*dbg_ep0(2, "- - - - - - - - - -"); */
446
447 dbg_ep0 (2,
448 "bmRequestType:%02x bRequest:%02x wValue:%04x wIndex:%04x wLength:%04x %s",
449 request->bmRequestType, request->bRequest,
450 le16_to_cpu (request->wValue), le16_to_cpu (request->wIndex),
451 le16_to_cpu (request->wLength),
452 USBD_DEVICE_REQUESTS (request->bRequest));
453
454 /* handle USB Standard Request (c.f. USB Spec table 9-2) */
455 if ((request->bmRequestType & USB_REQ_TYPE_MASK) != 0) {
Wolfgang Denk16c8d5e2006-06-14 17:45:53 +0200456 if(device->device_state <= STATE_CONFIGURED){
457 /* Attempt to handle a CDC specific request if we are
458 * in the configured state.
459 */
460 return device->cdc_recv_setup(request,urb);
461 }
wdenk232c1502004-03-12 00:14:09 +0000462 dbg_ep0 (1, "non standard request: %x",
463 request->bmRequestType & USB_REQ_TYPE_MASK);
464 return -1; /* Stall here */
465 }
466
467 switch (device->device_state) {
468 case STATE_CREATED:
469 case STATE_ATTACHED:
470 case STATE_POWERED:
471 /* It actually is important to allow requests in these states,
472 * Windows will request descriptors before assigning an
473 * address to the client.
474 */
475
476 /*dbg_ep0 (1, "request %s not allowed in this state: %s", */
477 /* USBD_DEVICE_REQUESTS(request->bRequest), */
478 /* usbd_device_states[device->device_state]); */
479 /*return -1; */
480 break;
481
482 case STATE_INIT:
483 case STATE_DEFAULT:
484 switch (request->bRequest) {
485 case USB_REQ_GET_STATUS:
486 case USB_REQ_GET_INTERFACE:
487 case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */
488 case USB_REQ_CLEAR_FEATURE:
489 case USB_REQ_SET_FEATURE:
490 case USB_REQ_SET_DESCRIPTOR:
491 /* case USB_REQ_SET_CONFIGURATION: */
492 case USB_REQ_SET_INTERFACE:
493 dbg_ep0 (1,
494 "request %s not allowed in DEFAULT state: %s",
495 USBD_DEVICE_REQUESTS (request->bRequest),
496 usbd_device_states[device->device_state]);
497 return -1;
498
499 case USB_REQ_SET_CONFIGURATION:
500 case USB_REQ_SET_ADDRESS:
501 case USB_REQ_GET_DESCRIPTOR:
502 case USB_REQ_GET_CONFIGURATION:
503 break;
504 }
505 case STATE_ADDRESSED:
506 case STATE_CONFIGURED:
507 break;
508 case STATE_UNKNOWN:
509 dbg_ep0 (1, "request %s not allowed in UNKNOWN state: %s",
510 USBD_DEVICE_REQUESTS (request->bRequest),
511 usbd_device_states[device->device_state]);
512 return -1;
513 }
514
515 /* handle all requests that return data (direction bit set on bm RequestType) */
516 if ((request->bmRequestType & USB_REQ_DIRECTION_MASK)) {
517
518 dbg_ep0 (3, "Device-to-Host");
519
520 switch (request->bRequest) {
521
522 case USB_REQ_GET_STATUS:
523 return ep0_get_status (device, urb, request->wIndex,
524 request->bmRequestType &
525 USB_REQ_RECIPIENT_MASK);
526
527 case USB_REQ_GET_DESCRIPTOR:
528 return ep0_get_descriptor (device, urb,
529 le16_to_cpu (request->wLength),
530 le16_to_cpu (request->wValue) >> 8,
531 le16_to_cpu (request->wValue) & 0xff);
532
533 case USB_REQ_GET_CONFIGURATION:
Pali Rohár7f985752021-02-07 14:50:11 +0100534 dbg_ep0(2, "get config %d\n", device->configuration);
wdenk232c1502004-03-12 00:14:09 +0000535 return ep0_get_one (device, urb,
536 device->configuration);
537
538 case USB_REQ_GET_INTERFACE:
539 return ep0_get_one (device, urb, device->alternate);
540
541 case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */
542 return -1;
543
544 case USB_REQ_CLEAR_FEATURE:
545 case USB_REQ_SET_FEATURE:
546 case USB_REQ_SET_ADDRESS:
547 case USB_REQ_SET_DESCRIPTOR:
548 case USB_REQ_SET_CONFIGURATION:
549 case USB_REQ_SET_INTERFACE:
550 return -1;
551 }
552 }
553 /* handle the requests that do not return data */
554 else {
555
556
557 /*dbg_ep0(3, "Host-to-Device"); */
558 switch (request->bRequest) {
559
560 case USB_REQ_CLEAR_FEATURE:
561 case USB_REQ_SET_FEATURE:
562 dbg_ep0 (0, "Host-to-Device");
563 switch (request->
564 bmRequestType & USB_REQ_RECIPIENT_MASK) {
565 case USB_REQ_RECIPIENT_DEVICE:
566 /* XXX DEVICE_REMOTE_WAKEUP or TEST_MODE would be added here */
567 /* XXX fall through for now as we do not support either */
568 case USB_REQ_RECIPIENT_INTERFACE:
569 case USB_REQ_RECIPIENT_OTHER:
570 dbg_ep0 (0, "request %s not",
571 USBD_DEVICE_REQUESTS (request->bRequest));
572 default:
573 return -1;
574
575 case USB_REQ_RECIPIENT_ENDPOINT:
576 dbg_ep0 (0, "ENDPOINT: %x", le16_to_cpu (request->wValue));
577 if (le16_to_cpu (request->wValue) == USB_ENDPOINT_HALT) {
578 /*return usbd_device_feature (device, le16_to_cpu (request->wIndex), */
579 /* request->bRequest == USB_REQ_SET_FEATURE); */
580 /* NEED TO IMPLEMENT THIS!!! */
581 return -1;
582 } else {
583 dbg_ep0 (1, "request %s bad wValue: %04x",
584 USBD_DEVICE_REQUESTS
585 (request->bRequest),
586 le16_to_cpu (request->wValue));
587 return -1;
588 }
589 }
590
591 case USB_REQ_SET_ADDRESS:
592 /* check if this is a re-address, reset first if it is (this shouldn't be possible) */
593 if (device->device_state != STATE_DEFAULT) {
594 dbg_ep0 (1, "set_address: %02x state: %s",
595 le16_to_cpu (request->wValue),
596 usbd_device_states[device->device_state]);
597 return -1;
598 }
599 address = le16_to_cpu (request->wValue);
600 if ((address & 0x7f) != address) {
601 dbg_ep0 (1, "invalid address %04x %04x",
602 address, address & 0x7f);
603 return -1;
604 }
605 device->address = address;
606
607 /*dbg_ep0(2, "address: %d %d %d", */
608 /* request->wValue, le16_to_cpu(request->wValue), device->address); */
609
wdenk232c1502004-03-12 00:14:09 +0000610 return 0;
611
612 case USB_REQ_SET_DESCRIPTOR: /* XXX should we support this? */
613 dbg_ep0 (0, "set descriptor: NOT SUPPORTED");
614 return -1;
615
616 case USB_REQ_SET_CONFIGURATION:
617 /* c.f. 9.4.7 - the top half of wValue is reserved */
Harald Weltee73b5212008-07-07 00:58:05 +0800618 device->configuration = le16_to_cpu(request->wValue) & 0xff;
619
wdenk232c1502004-03-12 00:14:09 +0000620 /* reset interface and alternate settings */
621 device->interface = device->alternate = 0;
622
623 /*dbg_ep0(2, "set configuration: %d", device->configuration); */
Pali Rohár7f985752021-02-07 14:50:11 +0100624 /*dbg_ep0(2, "DEVICE_CONFIGURED.. event?\n"); */
wdenk232c1502004-03-12 00:14:09 +0000625 return 0;
626
627 case USB_REQ_SET_INTERFACE:
628 device->interface = le16_to_cpu (request->wIndex);
629 device->alternate = le16_to_cpu (request->wValue);
630 /*dbg_ep0(2, "set interface: %d alternate: %d", device->interface, device->alternate); */
Pali Rohár7f985752021-02-07 14:50:11 +0100631 dbg_ep0(2, "DEVICE_SET_INTERFACE.. event?\n");
wdenk232c1502004-03-12 00:14:09 +0000632 return 0;
633
634 case USB_REQ_GET_STATUS:
635 case USB_REQ_GET_DESCRIPTOR:
636 case USB_REQ_GET_CONFIGURATION:
637 case USB_REQ_GET_INTERFACE:
638 case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */
639 return -1;
640 }
641 }
642 return -1;
643}