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);
115 while (!wait.completed) {
116 cyg_drv_cond_wait(&wait.signal);
118 cyg_drv_dsr_unlock();
119 cyg_drv_mutex_unlock(&wait.lock);
120 if (wait.result < 0) {
121 result = wait.result;
126 cyg_drv_cond_destroy(&wait.signal);
127 cyg_drv_mutex_destroy(&wait.lock);
134 usbs_devtab_cread(cyg_io_handle_t handle, void* buf, cyg_uint32* size)
136 usbs_callback_data wait;
137 cyg_devtab_entry_t* devtab_entry;
138 usbs_rx_endpoint* endpoint;
141 CYG_REPORT_FUNCTION();
144 cyg_drv_mutex_init(&wait.lock);
145 cyg_drv_cond_init(&wait.signal, &wait.lock);
147 devtab_entry = (cyg_devtab_entry_t*) handle;
148 CYG_CHECK_DATA_PTR( devtab_entry, "A valid endpoint must be supplied");
149 endpoint = (usbs_rx_endpoint*) devtab_entry->priv;
151 CYG_CHECK_DATA_PTR( endpoint, "The handle must correspond to a USB endpoint");
152 CYG_CHECK_FUNC_PTR( endpoint->start_rx_fn, "The endpoint must have a start_rx function");
154 endpoint->buffer = (unsigned char*) buf;
155 endpoint->buffer_size = (int) *size;
156 endpoint->complete_fn = &usbs_devtab_callback;
157 endpoint->complete_data = (void*) &wait;
158 (*endpoint->start_rx_fn)(endpoint);
159 cyg_drv_mutex_lock(&wait.lock);
161 while (!wait.completed) {
162 cyg_drv_cond_wait(&wait.signal);
164 cyg_drv_dsr_unlock();
165 cyg_drv_mutex_unlock(&wait.lock);
166 if (wait.result < 0) {
167 result = wait.result;
172 cyg_drv_cond_destroy(&wait.signal);
173 cyg_drv_mutex_destroy(&wait.lock);
179 // ----------------------------------------------------------------------------
180 // More devtab functions, this time related to ioctl() style operations.
182 usbs_devtab_get_config(cyg_io_handle_t handle, cyg_uint32 code, void* buf, cyg_uint32* size)
188 usbs_devtab_set_config(cyg_io_handle_t handle, cyg_uint32 code, const void* buf, cyg_uint32* size)
195 // ----------------------------------------------------------------------------
196 // USB-specific functions that are useful for applications/packages which
197 // do not want to use the devtab interface. These may get called in DSR
201 usbs_start_rx(usbs_rx_endpoint* endpoint)
203 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
204 CYG_CHECK_FUNC_PTR( endpoint->start_rx_fn, "The USB endpoint must support receive operations");
205 (*endpoint->start_rx_fn)(endpoint);
209 usbs_start_rx_buffer(usbs_rx_endpoint* endpoint,
210 unsigned char* buf, int size,
211 void (*callback_fn)(void *, int), void* callback_arg)
213 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
214 CYG_CHECK_FUNC_PTR( endpoint->start_rx_fn, "The USB endpoint must support receive operations");
216 endpoint->buffer = buf;
217 endpoint->buffer_size = size;
218 endpoint->complete_fn = callback_fn;
219 endpoint->complete_data = callback_arg;
220 (*endpoint->start_rx_fn)(endpoint);
224 usbs_start_tx(usbs_tx_endpoint* endpoint)
226 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
227 CYG_CHECK_FUNC_PTR( endpoint->start_tx_fn, "The USB endpoint must support receive operations");
228 (*endpoint->start_tx_fn)(endpoint);
232 usbs_start_tx_buffer(usbs_tx_endpoint* endpoint,
233 const unsigned char* buf, int size,
234 void (*callback_fn)(void*, int), void *callback_arg)
236 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
237 CYG_CHECK_FUNC_PTR( endpoint->start_tx_fn, "The USB endpoint must support receive operations");
239 endpoint->buffer = buf;
240 endpoint->buffer_size = size;
241 endpoint->complete_fn = callback_fn;
242 endpoint->complete_data = callback_arg;
243 (*endpoint->start_tx_fn)(endpoint);
247 usbs_start(usbs_control_endpoint* endpoint)
249 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
250 CYG_CHECK_FUNC_PTR( endpoint->start_fn, "The USB endpoint should have a start function");
252 (*endpoint->start_fn)(endpoint);
256 usbs_rx_endpoint_halted(usbs_rx_endpoint* endpoint)
258 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
259 return endpoint->halted;
263 usbs_tx_endpoint_halted(usbs_tx_endpoint* endpoint)
265 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
266 return endpoint->halted;
270 usbs_set_rx_endpoint_halted(usbs_rx_endpoint* endpoint, cyg_bool halted)
272 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
273 CYG_CHECK_FUNC_PTR( endpoint->set_halted_fn, "The USB endpoint should have a set-halted function");
274 (*endpoint->set_halted_fn)(endpoint, halted);
278 usbs_set_tx_endpoint_halted(usbs_tx_endpoint* endpoint, cyg_bool halted)
280 CYG_CHECK_DATA_PTR( endpoint, "A valid USB endpoint must be supplied");
281 CYG_CHECK_FUNC_PTR( endpoint->set_halted_fn, "The USB endpoint should have a set-halted function");
282 (*endpoint->set_halted_fn)(endpoint, halted);
286 usbs_start_rx_endpoint_wait(usbs_rx_endpoint* endpoint, void (*callback_fn)(void*, int), void* callback_data)
288 endpoint->buffer = (unsigned char*) 0;
289 endpoint->buffer_size = 0;
290 endpoint->complete_fn = callback_fn;
291 endpoint->complete_data = callback_data;
292 (*endpoint->start_rx_fn)(endpoint);
296 usbs_start_tx_endpoint_wait(usbs_tx_endpoint* endpoint, void (*callback_fn)(void*, int), void* callback_data)
298 endpoint->buffer = (unsigned char*) 0;
299 endpoint->buffer_size = 0;
300 endpoint->complete_fn = callback_fn;
301 endpoint->complete_data = callback_data;
302 (*endpoint->start_tx_fn)(endpoint);
306 // ----------------------------------------------------------------------------
307 // Handling of standard control messages. This will be invoked by
308 // a USB device driver, usually at DSR level, to process any control
309 // messages that cannot be handled by the hardware itself and that
310 // have also not been handled by the application-specific handler
313 // Because this function can run at DSR level performance is important.
315 // The various standard control messages are affected as follows:
317 // clear-feature: nothing can be done here about device requests to
318 // disable remote-wakeup or about endpoint halt requests. It appears
319 // to be legal to clear no features on an interface.
321 // get-configuration: if the device is not configured a single byte 0
322 // should be returned. Otherwise this code assumes only one configuration
323 // is supported and its id can be extracted from the enumeration data.
324 // For more complicated devices get-configuration has to be handled
325 // at a higher-level.
327 // get-descriptor: this is the big one. It is used to obtain
328 // the enumeration data. An auxiliary refill function is needed.
330 // get-interface: this can be used to identify the current variant
331 // for a given interface within a configuration. For simple devices
332 // there will be only interface, 0. For anything more complicated
333 // higher level code will have to take care of the request.
335 // get-status. Much the same as clear-feature.
337 // set-address. Must be handled at the device driver level.
339 // set-configuration: a value of 0 is used to deconfigure the device,
340 // which can be handled here. Otherwise this code assumes that only
341 // a single configuration is supported and enables that. For anything
342 // more complicated higher-level code has to handle this request.
344 // set-descriptor: used to update the enumeration data. This is not
345 // supported here, although higher-level code can choose to do so.
347 // set-feature. See clear-feature and get-status.
349 // set-interface. Variant interfaces are not supported by the
350 // base code so this request has to be handled at a higher level.
352 // synch-frame. This is only relevant for isochronous transfers
353 // which are not yet supported, and anyway it is not clear what
354 // could be done about these requests here.
356 // This refill function handles GET_DESCRIPTOR requests for a
357 // configuration. For details of the control_buffer usage see
358 // the relevant code in the main callback.
360 usbs_configuration_descriptor_refill(usbs_control_endpoint* endpoint)
362 usb_devreq* req = (usb_devreq*) endpoint->control_buffer;
363 int length = (req->length_hi << 8) | req->length_lo;
364 int sent = (req->index_hi << 8) | req->index_lo;
365 int current_interface = req->type;
366 int last_interface = req->request;
367 int current_endpoint = req->value_lo;
368 int last_endpoint = req->value_hi;
369 cyg_bool done = false;
371 if (current_endpoint == last_endpoint) {
372 // The next transfer should be a single interface - unless we have already finished.
373 if (current_interface == last_interface) {
376 endpoint->buffer = (unsigned char*) &(endpoint->enumeration_data->interfaces[current_interface]);
377 if (USB_INTERFACE_DESCRIPTOR_LENGTH >= (length - sent)) {
378 endpoint->buffer_size = length - sent;
381 endpoint->buffer_size = USB_INTERFACE_DESCRIPTOR_LENGTH;
382 sent += USB_INTERFACE_DESCRIPTOR_LENGTH;
383 // Note that an interface with zero endpoints is ok. We'll just move
384 // to the next interface in the next call.
385 last_endpoint = current_endpoint +
386 endpoint->enumeration_data->interfaces[current_interface].number_endpoints;
391 // The next transfer should be a single endpoint. The
392 // endpoints are actually contiguous array elements
393 // but may not be packed, so they have to be transferred
395 endpoint->buffer = (unsigned char*) &(endpoint->enumeration_data->endpoints[current_endpoint]);
396 if ((sent + USB_ENDPOINT_DESCRIPTOR_LENGTH) >= length) {
397 endpoint->buffer_size = length - sent;
400 endpoint->buffer_size = USB_ENDPOINT_DESCRIPTOR_LENGTH;
406 endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
408 req->type = (unsigned char) current_interface;
409 req->value_lo = (unsigned char) current_endpoint;
410 req->value_hi = (unsigned char) last_endpoint;
411 req->index_hi = (unsigned char) (sent >> 8);
412 req->index_lo = (unsigned char) (sent & 0x00FF);
417 usbs_handle_standard_control(usbs_control_endpoint* endpoint)
419 usbs_control_return result = USBS_CONTROL_RETURN_UNKNOWN;
420 usb_devreq* req = (usb_devreq*) endpoint->control_buffer;
425 length = (req->length_hi << 8) | req->length_lo;
426 direction = req->type & USB_DEVREQ_DIRECTION_MASK;
427 recipient = req->type & USB_DEVREQ_RECIPIENT_MASK;
429 if (USB_DEVREQ_CLEAR_FEATURE == req->request) {
431 if (USB_DEVREQ_RECIPIENT_INTERFACE == recipient) {
432 // The host should expect no data back, the device must
433 // be configured, and there are no defined features to clear.
435 (USBS_STATE_CONFIGURED == (endpoint->state & USBS_STATE_MASK)) &&
436 (0 == req->value_lo)) {
438 int interface_id = req->index_lo;
439 CYG_ASSERT( 1 == endpoint->enumeration_data->total_number_interfaces, \
440 "Higher level code should have handled this request");
442 if (interface_id == endpoint->enumeration_data->interfaces[0].interface_id) {
443 result = USBS_CONTROL_RETURN_HANDLED;
445 result = USBS_CONTROL_RETURN_STALL;
449 result = USBS_CONTROL_RETURN_STALL;
453 } else if (USB_DEVREQ_GET_CONFIGURATION == req->request) {
455 // Return a single byte 0 if the device is not currently
456 // configured. Otherwise assume a single configuration
457 // in the enumeration data and return its id.
458 if ((1 == length) && (USB_DEVREQ_DIRECTION_IN == direction)) {
460 if (USBS_STATE_CONFIGURED == (endpoint->state & USBS_STATE_MASK)) {
461 CYG_ASSERT( 1 == endpoint->enumeration_data->device.number_configurations, \
462 "Higher level code should have handled this request");
463 endpoint->control_buffer[0] = endpoint->enumeration_data->configurations[0].configuration_id;
465 endpoint->control_buffer[0] = 0;
467 endpoint->buffer = endpoint->control_buffer;
468 endpoint->buffer_size = 1;
469 endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
470 endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
471 result = USBS_CONTROL_RETURN_HANDLED;
474 result = USBS_CONTROL_RETURN_STALL;
477 } else if (USB_DEVREQ_GET_DESCRIPTOR == req->request) {
479 // The descriptor type is in value_hi. The descriptor index
481 // The hsot must expect at least one byte of data.
482 if ((0 == length) || (USB_DEVREQ_DIRECTION_IN != direction)) {
484 result = USBS_CONTROL_RETURN_STALL;
486 } else if (USB_DEVREQ_DESCRIPTOR_TYPE_DEVICE == req->value_hi) {
488 // The device descriptor is easy, it is a single field in the
490 endpoint->buffer = (unsigned char*) &(endpoint->enumeration_data->device);
491 endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
492 endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
493 if (length < USB_DEVICE_DESCRIPTOR_LENGTH) {
494 endpoint->buffer_size = length;
496 endpoint->buffer_size = USB_DEVICE_DESCRIPTOR_LENGTH;
498 result = USBS_CONTROL_RETURN_HANDLED;
500 } else if (USB_DEVREQ_DESCRIPTOR_TYPE_CONFIGURATION == req->value_hi) {
502 // This is where things get messy. We need to supply the
503 // specified configuration data, followed by some number of
504 // interfaces and endpoints. Plus there are length limits
505 // to consider. First check that the specified index is valid.
506 if (req->value_lo >= endpoint->enumeration_data->device.number_configurations) {
507 result = USBS_CONTROL_RETURN_STALL;
509 // No such luck. OK, supplying the initial block is easy.
510 endpoint->buffer = (unsigned char*) &(endpoint->enumeration_data->configurations[req->value_lo]);
511 endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
513 // How much data was actually requested. If only the
514 // configuration itself is of interest then there is
515 // no need to worry about the rest.
516 if (length <= USB_CONFIGURATION_DESCRIPTOR_LENGTH) {
517 endpoint->buffer_size = length;
518 endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
523 endpoint->buffer_size = USB_CONFIGURATION_DESCRIPTOR_LENGTH;
524 endpoint->fill_buffer_fn = &usbs_configuration_descriptor_refill;
526 // The descriptor refill_fn needs to know what next to transfer.
527 // The desired interfaces and endpoints will be contiguous so
528 // we need to keep track of the following:
529 // 1) the current interface index being transferred.
530 // 2) the last interface that should be transferred.
531 // 3) the current endpoint index that should be transferred.
532 // 4) the last endpoint index. This marks interface/endpoint transitions.
533 // 5) how much has been transferred to date.
534 // This information can be held in the control_buffer,
535 // with the length field being preserved.
538 // For all configurations up to the desired one.
539 for (i = 0; i < req->value_lo; i++) {
540 int config_interfaces = endpoint->enumeration_data->configurations[i].number_interfaces;
542 // For all interfaces in this configuration.
543 for (j = 0; j < config_interfaces; j++) {
544 // Add the number of endpoints in this interface to the current count.
545 CYG_ASSERT( (j + start_interface) < endpoint->enumeration_data->total_number_interfaces, \
546 "Valid interface count in enumeration data");
547 start_endpoint += endpoint->enumeration_data->interfaces[j + start_interface].number_endpoints;
549 // And update the index for the starting interface.
550 start_interface += config_interfaces;
552 CYG_ASSERT( start_interface < endpoint->enumeration_data->total_number_interfaces, \
553 "Valid interface count in enumeration data");
554 CYG_ASSERT( ((0 == endpoint->enumeration_data->total_number_endpoints) && (0 == start_endpoint)) || \
555 (start_endpoint < endpoint->enumeration_data->total_number_endpoints), \
556 "Valid endpoint count in enumeration data");
558 req->type = (unsigned char) start_interface;
559 req->request = (unsigned char) (start_interface +
560 endpoint->enumeration_data->configurations[req->value_lo].number_interfaces
562 req->value_lo = (unsigned char) start_endpoint;
563 req->value_hi = (unsigned char) start_endpoint;
564 req->index_lo = USB_CONFIGURATION_DESCRIPTOR_LENGTH;
567 result = USBS_CONTROL_RETURN_HANDLED;
571 } else if (USB_DEVREQ_DESCRIPTOR_TYPE_STRING == req->value_hi) {
573 // As long as the index is valid, the rest is easy since
574 // the strings are just held in a simple array.
575 // NOTE: if multiple languages have to be supported
576 // then things get more difficult.
577 if (req->value_lo >= endpoint->enumeration_data->total_number_strings) {
578 result = USBS_CONTROL_RETURN_STALL;
580 endpoint->buffer = (unsigned char*) endpoint->enumeration_data->strings[req->value_lo];
581 endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
582 endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
584 if (length < endpoint->buffer[0]) {
585 endpoint->buffer_size = length;
587 endpoint->buffer_size = endpoint->buffer[0];
589 result = USBS_CONTROL_RETURN_HANDLED;
593 result = USBS_CONTROL_RETURN_STALL;
596 } else if (USB_DEVREQ_GET_INTERFACE == req->request) {
599 (USB_DEVREQ_DIRECTION_IN != direction) ||
600 (USBS_STATE_CONFIGURED != (endpoint->state & USBS_STATE_MASK))) {
602 result = USBS_CONTROL_RETURN_STALL;
607 CYG_ASSERT( (1 == endpoint->enumeration_data->device.number_configurations) && \
608 (1 == endpoint->enumeration_data->total_number_interfaces), \
609 "Higher level code should have handled this request");
611 interface_id = (req->index_hi << 8) | req->index_lo;
612 if (interface_id != endpoint->enumeration_data->interfaces[0].interface_id) {
613 result = USBS_CONTROL_RETURN_STALL;
615 endpoint->control_buffer[0] = endpoint->enumeration_data->interfaces[0].alternate_setting;
616 endpoint->buffer = endpoint->control_buffer;
617 endpoint->buffer_size = 1;
618 endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
619 endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
620 result = USBS_CONTROL_RETURN_HANDLED;
624 } else if (USB_DEVREQ_GET_STATUS == req->request) {
626 if (USB_DEVREQ_RECIPIENT_INTERFACE == recipient) {
627 // The host should expect two bytes back, the device must
628 // be configured, the interface number must be valid.
629 // The host should expect no data back, the device must
630 // be configured, and there are no defined features to clear.
632 (USB_DEVREQ_DIRECTION_IN == direction) &&
633 (USBS_STATE_CONFIGURED == (endpoint->state & USBS_STATE_MASK))) {
635 int interface_id = req->index_lo;
636 CYG_ASSERT( 1 == endpoint->enumeration_data->total_number_interfaces, \
637 "Higher level code should have handled this request");
639 if (interface_id == endpoint->enumeration_data->interfaces[0].interface_id) {
641 // The request is legit, but there are no defined features for an interface...
642 endpoint->control_buffer[0] = 0;
643 endpoint->control_buffer[1] = 0;
644 endpoint->buffer = endpoint->control_buffer;
645 endpoint->buffer_size = 2;
646 endpoint->fill_buffer_fn = (void (*)(usbs_control_endpoint*)) 0;
647 endpoint->complete_fn = (usbs_control_return (*)(usbs_control_endpoint*, cyg_bool)) 0;
648 result = USBS_CONTROL_RETURN_HANDLED;
651 result = USBS_CONTROL_RETURN_STALL;
654 result = USBS_CONTROL_RETURN_STALL;
658 } else if (USB_DEVREQ_SET_CONFIGURATION == req->request) {
660 // Changing to configuration 0 means a state change from
661 // configured to addressed. Changing to anything else means a
662 // state change to configured. Both involve invoking the
663 // state change callback. If there are multiple configurations
664 // to choose from then this request has to be handled at
666 int old_state = endpoint->state;
667 if (0 == req->value_lo) {
668 endpoint->state = USBS_STATE_ADDRESSED;
669 if ((void (*)(usbs_control_endpoint*, void*, usbs_state_change, int))0 != endpoint->state_change_fn) {
670 (*endpoint->state_change_fn)(endpoint, endpoint->state_change_data,
671 USBS_STATE_CHANGE_DECONFIGURED, old_state);
673 result = USBS_CONTROL_RETURN_HANDLED;
676 CYG_ASSERT(1 == endpoint->enumeration_data->device.number_configurations, \
677 "Higher level code should have handled this request");
678 if (req->value_lo == endpoint->enumeration_data->configurations[0].configuration_id) {
679 endpoint->state = USBS_STATE_CONFIGURED;
680 if ((void (*)(usbs_control_endpoint*, void*, usbs_state_change, int))0 != endpoint->state_change_fn) {
681 (*endpoint->state_change_fn)(endpoint, endpoint->state_change_data,
682 USBS_STATE_CHANGE_CONFIGURED, old_state);
684 result = USBS_CONTROL_RETURN_HANDLED;
686 result = USBS_CONTROL_RETURN_STALL;
690 } else if (USB_DEVREQ_SET_FEATURE == req->request) {
692 if (USB_DEVREQ_RECIPIENT_INTERFACE == recipient) {
693 // The host should expect no data back, the device must
694 // be configured, and there are no defined features to clear.
696 (USBS_STATE_CONFIGURED == (endpoint->state & USBS_STATE_MASK)) &&
697 (0 == req->value_lo)) {
699 int interface_id = req->index_lo;
700 CYG_ASSERT( 1 == endpoint->enumeration_data->total_number_interfaces, \
701 "Higher level code should have handled this request");
703 if (interface_id == endpoint->enumeration_data->interfaces[0].interface_id) {
704 result = USBS_CONTROL_RETURN_HANDLED;
706 result = USBS_CONTROL_RETURN_STALL;
710 result = USBS_CONTROL_RETURN_STALL;