- Main Page
- Related Pages
- Data Structures
- Files

- File List
- Globals

# drivers/usb/udc_lib.c

Go to the documentation of this file.

    00001
    00044 #include <byteorder.h>
    00045 #include <debug.h>
    00046 #include <usb/function.h>
    00047 #include <usb/udc.h>
    00048 #include <usb/usb_protocol.h>
    00049
    00050 static int udc_lib_standard_request(struct udc *udc, struct usb_setup_req *req)
    00051 {
    00052         uint16_t        value = le16_to_cpu(req->wValue);
    00053         uint16_t        index = le16_to_cpu(req->wIndex);
    00054         uint16_t        len = le16_to_cpu(req->wLength);
    00055         uint8_t         byte;
    00056
    00057         switch (req->bRequest) {
    00058         case USB_REQ_GET_STATUS: {
    00059                 le16_t  status = LE16(0);
    00060                 int     ret;
    00061
    00062                 if (len != sizeof(status) || usb_req_is_out(req))
    00063                         return -1;
    00064
    00065                 switch (usb_req_recipient(req)) {
    00066                 case USB_RECIP_DEVICE:
    00067                         /*
    00068                          * Assuming that we are self-powered, although
    00069                          * we really don't know that...
    00070                          */
    00071                         status = LE16(0x0001);
    00072                         break;
    00073                 case USB_RECIP_ENDPOINT:
    00074                         ret = udc_ep_is_halted(udc, index & USB_EP_ADDR_MASK);
    00075                         if (ret < 0)
    00076                                 return -1;
    00077
    00078                         status = cpu_to_le16(ret);
    00079                         break;
    00080                 default:
    00081                         break;
    00082                 }
    00083
    00084                 udc_ep0_write_sync(udc, &status, sizeof(status));
    00085                 udc_ep0_expect_status(udc);
    00086                 break;
    00087         }
    00088
    00089         case USB_REQ_CLEAR_FEATURE:
    00090                 if (len != 0 || usb_req_is_in(req))
    00091                         return -1;
    00092
    00093                 if (usb_req_recipient(req) == USB_RECIP_DEVICE
    00094                                 && value == USB_DEV_FEATURE_REMOTE_WAKEUP) {
    00095                         /* do nothing */
    00096                 } else if (usb_req_recipient(req) == USB_RECIP_ENDPOINT
    00097                                 && value == USB_EP_FEATURE_HALT) {
    00098                         if (udc_ep_clear_halt(udc, index & USB_EP_ADDR_MASK))
    00099                                 return -1;
    00100                 } else {
    00101                         return -1;
    00102                 }
    00103
    00104                 udc_ep0_send_status(udc);
    00105                 break;
    00106
    00107         case USB_REQ_SET_FEATURE:
    00108                 if (len != 0 || usb_req_is_in(req))
    00109                         return -1;
    00110                 if (udc_is_high_speed(udc)
    00111                                 && usb_req_recipient(req) == USB_RECIP_DEVICE
    00112                                 && value == USB_DEV_FEATURE_TEST_MODE) {
    00113                         if (index & 0xff)
    00114                                 return -1;
    00115
    00116                         /*
    00117                          * Unconfigure the device, terminating all
    00118                          * ongoing requests.
    00119                          */
    00120                         usb_func_set_configuration(udc, 0);
    00121
    00122                         if (udc_enter_test_mode(udc, index >> 8))
    00123                                 return -1;
    00124                 } else if (usb_req_recipient(req) == USB_RECIP_ENDPOINT
    00125                                 && value == USB_EP_FEATURE_HALT) {
    00126                         if (udc_ep_set_halt(udc, index & USB_EP_ADDR_MASK))
    00127                                 return -1;
    00128                 } else {
    00129                         return -1;
    00130                 }
    00131
    00132                 udc_ep0_send_status(udc);
    00133                 break;
    00134
    00135         case USB_REQ_SET_ADDRESS:
    00136                 if (len != 0 || usb_req_is_in(req) || value > 127)
    00137                         return -1;
    00138
    00139                 /*
    00140                  * The address isn't actually changed until the status
    00141                  * stage is complete. Make sure we don't handle any
    00142                  * SETUP packets until then.
    00143                  */
    00144                 udc_set_address(udc, value);
    00145                 udc_ep0_send_status(udc);
    00146                 break;
    00147
    00148         case USB_REQ_GET_DESCRIPTOR:
    00149                 if (usb_req_is_out(req))
    00150                         return -1;
    00151
    00152                 if (usb_func_get_descriptor(udc, value, index, len) < 0)
    00153                         return -1;
    00154                 break;
    00155
    00156         case USB_REQ_SET_DESCRIPTOR:
    00157                 /* Not supported (defined as optional by the USB 2.0 spec) */
    00158                 return -1;
    00159
    00160         case USB_REQ_GET_CONFIGURATION:
    00161                 if (len != sizeof(byte) || usb_req_is_out(req))
    00162                         return -1;
    00163
    00164                 byte = 0;
    00165                 if (udc->config)
    00166                         byte = udc->config->bConfigurationValue;
    00167
    00168                 udc_ep0_write_sync(udc, &byte, sizeof(byte));
    00169                 udc_ep0_expect_status(udc);
    00170                 break;
    00171
    00172         case USB_REQ_SET_CONFIGURATION:
    00173                 if (len != 0 || usb_req_is_in(req) || !udc->address)
    00174                         return -1;
    00175
    00176                 if (usb_func_set_configuration(udc, value) < 0)
    00177                         return -1;
    00178
    00179                 udc_ep0_send_status(udc);
    00180                 break;
    00181
    00182         case USB_REQ_GET_INTERFACE:
    00183                 if (len != 1 || usb_req_is_out(req) || !udc->config)
    00184                         return -1;
    00185
    00186                 if (usb_func_get_interface(udc, index) < 0)
    00187                         return -1;
    00188                 break;
    00189
    00190         case USB_REQ_SET_INTERFACE:
    00191                 if (len != 0 || usb_req_is_in(req) || !udc->config)
    00192                         return -1;
    00193
    00194                 if (usb_func_set_interface(udc, index, value) < 0)
    00195                         return -1;
    00196
    00197                 udc_ep0_send_status(udc);
    00198                 break;
    00199
    00200         default:
    00201                 return -1;
    00202         }
    00203
    00204         return 0;
    00205 }
    00206
    00224 int udc_lib_process_setup_request(struct udc *udc, struct usb_setup_req *req)
    00225 {
    00226         dbg_printf("req %02x: t%02x v%04x i%04x l%04x\n",
    00227                    req->bRequest, req->bmRequestType,
    00228                    le16_to_cpu(req->wValue), le16_to_cpu(req->wIndex),
    00229                    le16_to_cpu(req->wLength));
    00230
    00231         if (usb_req_type(req) == USB_REQTYPE_STANDARD)
    00232                 return udc_lib_standard_request(udc, req);
    00233         else
    00234                 return usb_func_process_setup_request(udc, req);
    00235 }