1 //==========================================================================
5 // Generic USB slave-side support
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: bartv
47 //####DESCRIPTIONEND####
49 //==========================================================================
51 #include <pkgconf/system.h>
52 #include <cyg/infra/cyg_type.h>
53 #include <cyg/infra/cyg_ass.h>
54 #include <cyg/infra/cyg_trac.h>
55 #include <cyg/infra/diag.h>
56 #include <cyg/io/usb/usbs.h>
57 #include <cyg/hal/drv_api.h>
59 // ----------------------------------------------------------------------------
60 // Devtab entry support. This code can be compiled with no overheads as
61 // long as the necessary support package is in place.
63 # include <cyg/io/io.h>
64 # include <cyg/io/devtab.h>
65 // ----------------------------------------------------------------------------
66 // read()/write() functions applied to USB endpoints. These just
67 // indirect via the usbs_endpoint structures and wait for the
68 // callback to happen.
70 typedef struct usbs_callback_data {
74 cyg_drv_cond_t signal;
78 usbs_devtab_callback(void* arg, int result)
80 usbs_callback_data* callback_data = (usbs_callback_data*) arg;
81 callback_data->result = result;
82 callback_data->completed = true;
83 cyg_drv_cond_signal(&(callback_data->signal));
87 usbs_devtab_cwrite(cyg_io_handle_t handle, const void* buf, cyg_uint32* size)
89 usbs_callback_data wait;
90 cyg_devtab_entry_t* devtab_entry;
91 usbs_tx_endpoint* endpoint;
94 CYG_REPORT_FUNCTION();
97 cyg_drv_mutex_init(&wait.lock);
98 cyg_drv_cond_init(&wait.signal, &wait.lock);
100 devtab_entry = (cyg_devtab_entry_t*) handle;
101 CYG_CHECK_DATA_PTR( devtab_entry, "A valid endpoint must be supplied");
102 endpoint = (usbs_tx_endpoint*) devtab_entry->priv;
104 CYG_CHECK_DATA_PTR( endpoint, "The handle must correspond to a USB endpoint");
105 CYG_CHECK_FUNC_PTR( endpoint->start_tx_fn, "The endpoint must have a start_tx function");
107 endpoint->buffer = (unsigned char*) buf;
108 endpoint->buffer_size = (int) *size;
109 endpoint->complete_fn = &usbs_devtab_callback;
110 endpoint->complete_data = (void*) &wait;
111 (*endpoint->start_tx_fn)(endpoint);
113 cyg_drv_mutex_lock(&wait.lock);
114 while (!wait.completed) {
115 cyg_drv_cond_wait(&wait.signal);
117 cyg_drv_mutex_unlock(&wait.lock);
118 if (wait.result < 0) {
119 result = wait.result;
124 cyg_drv_cond_destroy(&wait.signal);
125 cyg_drv_mutex_destroy(&wait.lock);
132 usbs_devtab_cread(cyg_io_handle_t handle, void* buf, cyg_uint32* size)
134 usbs_callback_data wait;
135 cyg_devtab_entry_t* devtab_entry;
136 usbs_rx_endpoint* endpoint;
139 CYG_REPORT_FUNCTION();
142 cyg_drv_mutex_init(&wait.lock);
143 cyg_drv_cond_init(&wait.signal, &wait.lock);
145 devtab_entry = (cyg_devtab_entry_t*) handle;
146 CYG_CHECK_DATA_PTR( devtab_entry, "A valid endpoint must be supplied");
147 endpoint = (usbs_rx_endpoint*) devtab_entry->priv;
149 CYG_CHECK_DATA_PTR( endpoint, "The handle must correspond to a USB endpoint");
150 CYG_CHECK_FUNC_PTR( endpoint->start_rx_fn, "The endpoint must have a start_rx function");
152 endpoint->buffer = (unsigned char*) buf;
153 endpoint->buffer_size = (int) *size;
154 endpoint->complete_fn = &usbs_devtab_callback;
155 endpoint->complete_data = (void*) &wait;
156 (*endpoint->start_rx_fn)(endpoint);
157 cyg_drv_mutex_lock(&wait.lock);
158 while (!wait.completed) {
159 cyg_drv_cond_wait(&wait.signal);
161 cyg_drv_mutex_unlock(&wait.lock);
162 if (wait.result < 0) {
163 result = wait.result;
168 cyg_drv_cond_destroy(&wait.signal);
169 cyg_drv_mutex_destroy(&wait.lock);
175 // ----------------------------------------------------------------------------
176 // More devtab functions, this time related to ioctl() style operations.
178 usbs_devtab_get_config(cyg_io_handle_t handle, cyg_uint32 code, void* buf, cyg_uint32* size)
184 usbs_devtab_set_config(cyg_io_handle_t handle, cyg_uint32 code, const void* buf, cyg_uint32* size)
191 // ----------------------------------------------------------------------------
192 // USB-specific functions that are useful for applications/packages which
193 // do not want to use the devtab interface. These may get called in DSR
197 usbs_start_rx(usbs_rx_endpoint* endpoint)
199 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
200 CYG_CHECK_FUNC_PTR( endpoint->start_rx_fn, "The USB endpoint must support receive operations");
201 (*endpoint->start_rx_fn)(endpoint);
205 usbs_start_rx_buffer(usbs_rx_endpoint* endpoint,
206 unsigned char* buf, int size,
207 void (*callback_fn)(void *, int), void* callback_arg)
209 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
210 CYG_CHECK_FUNC_PTR( endpoint->start_rx_fn, "The USB endpoint must support receive operations");
212 endpoint->buffer = buf;
213 endpoint->buffer_size = size;
214 endpoint->complete_fn = callback_fn;
215 endpoint->complete_data = callback_arg;
216 (*endpoint->start_rx_fn)(endpoint);
220 usbs_start_tx(usbs_tx_endpoint* endpoint)
222 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
223 CYG_CHECK_FUNC_PTR( endpoint->start_tx_fn, "The USB endpoint must support receive operations");
224 (*endpoint->start_tx_fn)(endpoint);
228 usbs_start_tx_buffer(usbs_tx_endpoint* endpoint,
229 const unsigned char* buf, int size,
230 void (*callback_fn)(void*, int), void *callback_arg)
232 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
233 CYG_CHECK_FUNC_PTR( endpoint->start_tx_fn, "The USB endpoint must support receive operations");
235 endpoint->buffer = buf;
236 endpoint->buffer_size = size;
237 endpoint->complete_fn = callback_fn;
238 endpoint->complete_data = callback_arg;
239 (*endpoint->start_tx_fn)(endpoint);
243 usbs_start(usbs_control_endpoint* endpoint)
245 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
246 CYG_CHECK_FUNC_PTR( endpoint->start_fn, "The USB endpoint should have a start function");
248 (*endpoint->start_fn)(endpoint);
252 usbs_rx_endpoint_halted(usbs_rx_endpoint* endpoint)
254 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
255 return endpoint->halted;
259 usbs_tx_endpoint_halted(usbs_tx_endpoint* endpoint)
261 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
262 return endpoint->halted;
266 usbs_set_rx_endpoint_halted(usbs_rx_endpoint* endpoint, cyg_bool halted)
268 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
269 CYG_CHECK_FUNC_PTR( endpoint->set_halted_fn, "The USB endpoint should have a set-halted function");
270 (*endpoint->set_halted_fn)(endpoint, halted);
274 usbs_set_tx_endpoint_halted(usbs_tx_endpoint* endpoint, cyg_bool halted)
276 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
277 CYG_CHECK_FUNC_PTR( endpoint->set_halted_fn, "The USB endpoint should have a set-halted function");
278 (*endpoint->set_halted_fn)(endpoint, halted);
282 usbs_start_rx_endpoint_wait(usbs_rx_endpoint* endpoint, void (*callback_fn)(void*, int), void* callback_data)
284 endpoint->buffer = (unsigned char*) 0;
285 endpoint->buffer_size = 0;
286 endpoint->complete_fn = callback_fn;
287 endpoint->complete_data = callback_data;
288 (*endpoint->start_rx_fn)(endpoint);
292 usbs_start_tx_endpoint_wait(usbs_tx_endpoint* endpoint, void (*callback_fn)(void*, int), void* callback_data)
294 endpoint->buffer = (unsigned char*) 0;
295 endpoint->buffer_size = 0;
296 endpoint->complete_fn = callback_fn;
297 endpoint->complete_data = callback_data;
298 (*endpoint->start_tx_fn)(endpoint);
302 // ----------------------------------------------------------------------------
303 // Handling of standard control messages. This will be invoked by
304 // a USB device driver, usually at DSR level, to process any control
305 // messages that cannot be handled by the hardware itself and that
306 // have also not been handled by the application-specific handler
309 // Because this function can run at DSR level performance is important.
311 // The various standard control messages are affected as follows:
313 // clear-feature: nothing can be done here about device requests to
314 // disable remote-wakeup or about endpoint halt requests. It appears
315 // to be legal to clear no features on an interface.
317 // get-configuration: if the device is not configured a single byte 0
318 // should be returned. Otherwise this code assumes only one configuration
319 // is supported and its id can be extracted from the enumeration data.
320 // For more complicated devices get-configuration has to be handled
321 // at a higher-level.
323 // get-descriptor: this is the big one. It is used to obtain
324 // the enumeration data. An auxiliary refill function is needed.
326 // get-interface: this can be used to identify the current variant
327 // for a given interface within a configuration. For simple devices
328 // there will be only interface, 0. For anything more complicated
329 // higher level code will have to take care of the request.
331 // get-status. Much the same as clear-feature.
333 // set-address. Must be handled at the device driver level.
335 // set-configuration: a value of 0 is used to deconfigure the device,
336 // which can be handled here. Otherwise this code assumes that only
337 // a single configuration is supported and enables that. For anything
338 // more complicated higher-level code has to handle this request.
340 // set-descriptor: used to update the enumeration data. This is not
341 // supported here, although higher-level code can choose to do so.
343 // set-feature. See clear-feature and get-status.
345 // set-interface. Variant interfaces are not supported by the
346 // base code so this request has to be handled at a higher level.
348 // synch-frame. This is only relevant for isochronous transfers
349 // which are not yet supported, and anyway it is not clear what
350 // could be done about these requests here.
352 // This refill function handles GET_DESCRIPTOR requests for a
353 // configuration. For details of the control_buffer usage see
354 // the relevant code in the main callback.
356 usbs_configuration_descriptor_refill(usbs_control_endpoint* endpoint)
358 usb_devreq* req = (usb_devreq*) endpoint->control_buffer;
359 int length = (req->length_hi << 8) | req->length_lo;
360 int sent = (req->index_hi << 8) | req->index_lo;
361 int current_interface = req->type;
362 int last_interface = req->request;
363 int current_endpoint = req->value_lo;
364 int last_endpoint = req->value_hi;
365 cyg_bool done = false;
367 if (current_endpoint == last_endpoint) {
368 // The next transfer should be a single interface - unless we have already finished.
369 if (current_interface == last_interface) {
372 endpoint->buffer = (unsigned char*) &(endpoint->enumeration_data->interfaces[current_interface]);
373 if (USB_INTERFACE_DESCRIPTOR_LENGTH >= (length - sent)) {
374 endpoint->buffer_size = length - sent;
377 endpoint->buffer_size = USB_INTERFACE_DESCRIPTOR_LENGTH;
378 sent += USB_INTERFACE_DESCRIPTOR_LENGTH;
379 // Note that an interface with zero endpoints is ok. We'll just move
380 // to the next interface in the next call.
381 last_endpoint = current_endpoint +
382 endpoint->enumeration_data->interfaces[current_interface].number_endpoints;
387 // The next transfer should be a single endpoint. The
388 // endpoints are actually contiguous array elements
389 // but may not be packed, so they have to be transferred
391 endpoint->buffer = (unsigned char*) &(endpoint->enumeration_data->endpoints[current_endpoint]);
392 if ((sent + USB_ENDPOINT_DESCRIPTOR_LENGTH) >= length) {
393 endpoint->buffer_size = length - sent;
396 endpoint->buffer_size = USB_ENDPOINT_DESCRIPTOR_LENGTH;
402 endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
404 req->type = (unsigned char) current_interface;
405 req->value_lo = (unsigned char) current_endpoint;
406 req->value_hi = (unsigned char) last_endpoint;
407 req->index_hi = (unsigned char) (sent >> 8);
408 req->index_lo = (unsigned char) (sent & 0x00FF);
413 usbs_handle_standard_control(usbs_control_endpoint* endpoint)
415 usbs_control_return result = USBS_CONTROL_RETURN_UNKNOWN;
416 usb_devreq* req = (usb_devreq*) endpoint->control_buffer;
421 length = (req->length_hi << 8) | req->length_lo;
422 direction = req->type & USB_DEVREQ_DIRECTION_MASK;
423 recipient = req->type & USB_DEVREQ_RECIPIENT_MASK;
425 if (USB_DEVREQ_CLEAR_FEATURE == req->request) {
427 if (USB_DEVREQ_RECIPIENT_INTERFACE == recipient) {
428 // The host should expect no data back, the device must
429 // be configured, and there are no defined features to clear.
431 (USBS_STATE_CONFIGURED == (endpoint->state & USBS_STATE_MASK)) &&
432 (0 == req->value_lo)) {
434 int interface_id = req->index_lo;
435 CYG_ASSERT( 1 == endpoint->enumeration_data->total_number_interfaces, \
436 "Higher level code should have handled this request");
438 if (interface_id == endpoint->enumeration_data->interfaces[0].interface_id) {
439 result = USBS_CONTROL_RETURN_HANDLED;
441 result = USBS_CONTROL_RETURN_STALL;
445 result = USBS_CONTROL_RETURN_STALL;
449 } else if (USB_DEVREQ_GET_CONFIGURATION == req->request) {
451 // Return a single byte 0 if the device is not currently
452 // configured. Otherwise assume a single configuration
453 // in the enumeration data and return its id.
454 if ((1 == length) && (USB_DEVREQ_DIRECTION_IN == direction)) {
456 if (USBS_STATE_CONFIGURED == (endpoint->state & USBS_STATE_MASK)) {
457 CYG_ASSERT( 1 == endpoint->enumeration_data->device.number_configurations, \
458 "Higher level code should have handled this request");
459 endpoint->control_buffer[0] = endpoint->enumeration_data->configurations[0].configuration_id;
461 endpoint->control_buffer[0] = 0;
463 endpoint->buffer = endpoint->control_buffer;
464 endpoint->buffer_size = 1;
465 endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
466 endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
467 result = USBS_CONTROL_RETURN_HANDLED;
470 result = USBS_CONTROL_RETURN_STALL;
473 } else if (USB_DEVREQ_GET_DESCRIPTOR == req->request) {
475 // The descriptor type is in value_hi. The descriptor index
477 // The hsot must expect at least one byte of data.
478 if ((0 == length) || (USB_DEVREQ_DIRECTION_IN != direction)) {
480 result = USBS_CONTROL_RETURN_STALL;
482 } else if (USB_DEVREQ_DESCRIPTOR_TYPE_DEVICE == req->value_hi) {
484 // The device descriptor is easy, it is a single field in the
486 endpoint->buffer = (unsigned char*) &(endpoint->enumeration_data->device);
487 endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
488 endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
489 if (length < USB_DEVICE_DESCRIPTOR_LENGTH) {
490 endpoint->buffer_size = length;
492 endpoint->buffer_size = USB_DEVICE_DESCRIPTOR_LENGTH;
494 result = USBS_CONTROL_RETURN_HANDLED;
496 } else if (USB_DEVREQ_DESCRIPTOR_TYPE_CONFIGURATION == req->value_hi) {
498 // This is where things get messy. We need to supply the
499 // specified configuration data, followed by some number of
500 // interfaces and endpoints. Plus there are length limits
501 // to consider. First check that the specified index is valid.
502 if (req->value_lo >= endpoint->enumeration_data->device.number_configurations) {
503 result = USBS_CONTROL_RETURN_STALL;
505 // No such luck. OK, supplying the initial block is easy.
506 endpoint->buffer = (unsigned char*) &(endpoint->enumeration_data->configurations[req->value_lo]);
507 endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
509 // How much data was actually requested. If only the
510 // configuration itself is of interest then there is
511 // no need to worry about the rest.
512 if (length <= USB_CONFIGURATION_DESCRIPTOR_LENGTH) {
513 endpoint->buffer_size = length;
514 endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
519 endpoint->buffer_size = USB_CONFIGURATION_DESCRIPTOR_LENGTH;
520 endpoint->fill_buffer_fn = &usbs_configuration_descriptor_refill;
522 // The descriptor refill_fn needs to know what next to transfer.
523 // The desired interfaces and endpoints will be contiguous so
524 // we need to keep track of the following:
525 // 1) the current interface index being transferred.
526 // 2) the last interface that should be transferred.
527 // 3) the current endpoint index that should be transferred.
528 // 4) the last endpoint index. This marks interface/endpoint transitions.
529 // 5) how much has been transferred to date.
530 // This information can be held in the control_buffer,
531 // with the length field being preserved.
534 // For all configurations up to the desired one.
535 for (i = 0; i < req->value_lo; i++) {
536 int config_interfaces = endpoint->enumeration_data->configurations[i].number_interfaces;
538 // For all interfaces in this configuration.
539 for (j = 0; j < config_interfaces; j++) {
540 // Add the number of endpoints in this interface to the current count.
541 CYG_ASSERT( (j + start_interface) < endpoint->enumeration_data->total_number_interfaces, \
542 "Valid interface count in enumeration data");
543 start_endpoint += endpoint->enumeration_data->interfaces[j + start_interface].number_endpoints;
545 // And update the index for the starting interface.
546 start_interface += config_interfaces;
548 CYG_ASSERT( start_interface < endpoint->enumeration_data->total_number_interfaces, \
549 "Valid interface count in enumeration data");
550 CYG_ASSERT( ((0 == endpoint->enumeration_data->total_number_endpoints) && (0 == start_endpoint)) || \
551 (start_endpoint < endpoint->enumeration_data->total_number_endpoints), \
552 "Valid endpoint count in enumeration data");
554 req->type = (unsigned char) start_interface;
555 req->request = (unsigned char) (start_interface +
556 endpoint->enumeration_data->configurations[req->value_lo].number_interfaces
558 req->value_lo = (unsigned char) start_endpoint;
559 req->value_hi = (unsigned char) start_endpoint;
560 req->index_lo = USB_CONFIGURATION_DESCRIPTOR_LENGTH;
563 result = USBS_CONTROL_RETURN_HANDLED;
567 } else if (USB_DEVREQ_DESCRIPTOR_TYPE_STRING == req->value_hi) {
569 // As long as the index is valid, the rest is easy since
570 // the strings are just held in a simple array.
571 // NOTE: if multiple languages have to be supported
572 // then things get more difficult.
573 if (req->value_lo >= endpoint->enumeration_data->total_number_strings) {
574 result = USBS_CONTROL_RETURN_STALL;
576 endpoint->buffer = (unsigned char*) endpoint->enumeration_data->strings[req->value_lo];
577 endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
578 endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
580 if (length < endpoint->buffer[0]) {
581 endpoint->buffer_size = length;
583 endpoint->buffer_size = endpoint->buffer[0];
585 result = USBS_CONTROL_RETURN_HANDLED;
589 result = USBS_CONTROL_RETURN_STALL;
592 } else if (USB_DEVREQ_GET_INTERFACE == req->request) {
595 (USB_DEVREQ_DIRECTION_IN != direction) ||
596 (USBS_STATE_CONFIGURED != (endpoint->state & USBS_STATE_MASK))) {
598 result = USBS_CONTROL_RETURN_STALL;
603 CYG_ASSERT( (1 == endpoint->enumeration_data->device.number_configurations) && \
604 (1 == endpoint->enumeration_data->total_number_interfaces), \
605 "Higher level code should have handled this request");
607 interface_id = (req->index_hi << 8) | req->index_lo;
608 if (interface_id != endpoint->enumeration_data->interfaces[0].interface_id) {
609 result = USBS_CONTROL_RETURN_STALL;
611 endpoint->control_buffer[0] = endpoint->enumeration_data->interfaces[0].alternate_setting;
612 endpoint->buffer = endpoint->control_buffer;
613 endpoint->buffer_size = 1;
614 endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
615 endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
616 result = USBS_CONTROL_RETURN_HANDLED;
620 } else if (USB_DEVREQ_GET_STATUS == req->request) {
622 if (USB_DEVREQ_RECIPIENT_INTERFACE == recipient) {
623 // The host should expect two bytes back, the device must
624 // be configured, the interface number must be valid.
625 // The host should expect no data back, the device must
626 // be configured, and there are no defined features to clear.
628 (USB_DEVREQ_DIRECTION_IN == direction) &&
629 (USBS_STATE_CONFIGURED == (endpoint->state & USBS_STATE_MASK))) {
631 int interface_id = req->index_lo;
632 CYG_ASSERT( 1 == endpoint->enumeration_data->total_number_interfaces, \
633 "Higher level code should have handled this request");
635 if (interface_id == endpoint->enumeration_data->interfaces[0].interface_id) {
637 // The request is legit, but there are no defined features for an interface...
638 endpoint->control_buffer[0] = 0;
639 endpoint->control_buffer[1] = 0;
640 endpoint->buffer = endpoint->control_buffer;
641 endpoint->buffer_size = 2;
642 endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
643 endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
644 result = USBS_CONTROL_RETURN_HANDLED;
647 result = USBS_CONTROL_RETURN_STALL;
650 result = USBS_CONTROL_RETURN_STALL;
654 } else if (USB_DEVREQ_SET_CONFIGURATION == req->request) {
656 // Changing to configuration 0 means a state change from
657 // configured to addressed. Changing to anything else means a
658 // state change to configured. Both involve invoking the
659 // state change callback. If there are multiple configurations
660 // to choose from then this request has to be handled at
662 int old_state = endpoint->state;
663 if (0 == req->value_lo) {
664 endpoint->state = USBS_STATE_ADDRESSED;
665 if ((void (*)(usbs_control_endpoint*, void*, usbs_state_change, int))0 != endpoint->state_change_fn) {
666 (*endpoint->state_change_fn)(endpoint, endpoint->state_change_data,
667 USBS_STATE_CHANGE_DECONFIGURED, old_state);
669 result = USBS_CONTROL_RETURN_HANDLED;
672 CYG_ASSERT(1 == endpoint->enumeration_data->device.number_configurations, \
673 "Higher level code should have handled this request");
674 if (req->value_lo == endpoint->enumeration_data->configurations[0].configuration_id) {
675 endpoint->state = USBS_STATE_CONFIGURED;
676 if ((void (*)(usbs_control_endpoint*, void*, usbs_state_change, int))0 != endpoint->state_change_fn) {
677 (*endpoint->state_change_fn)(endpoint, endpoint->state_change_data,
678 USBS_STATE_CHANGE_CONFIGURED, old_state);
680 result = USBS_CONTROL_RETURN_HANDLED;
682 result = USBS_CONTROL_RETURN_STALL;
686 } else if (USB_DEVREQ_SET_FEATURE == req->request) {
688 if (USB_DEVREQ_RECIPIENT_INTERFACE == recipient) {
689 // The host should expect no data back, the device must
690 // be configured, and there are no defined features to clear.
692 (USBS_STATE_CONFIGURED == (endpoint->state & USBS_STATE_MASK)) &&
693 (0 == req->value_lo)) {
695 int interface_id = req->index_lo;
696 CYG_ASSERT( 1 == endpoint->enumeration_data->total_number_interfaces, \
697 "Higher level code should have handled this request");
699 if (interface_id == endpoint->enumeration_data->interfaces[0].interface_id) {
700 result = USBS_CONTROL_RETURN_HANDLED;
702 result = USBS_CONTROL_RETURN_STALL;
706 result = USBS_CONTROL_RETURN_STALL;