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
00069
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
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
00118
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
00141
00142
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
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 }