00001
00041 #include <byteorder.h>
00042 #include <debug.h>
00043 #include <usb/dev.h>
00044 #include <usb/udc.h>
00045 #include <usb/udc_lib.h>
00046 #include <usb/usb_protocol.h>
00047
00062 static status_t udc_lib_standard_request(struct udc *udc,
00063 struct usb_setup_req *req)
00064 {
00065 uint16_t value = le16_to_cpu(req->wValue);
00066 uint16_t index = le16_to_cpu(req->wIndex);
00067 uint16_t len = le16_to_cpu(req->wLength);
00068
00069 switch (req->bRequest) {
00070 case USB_REQ_GET_STATUS: {
00071 le16_t status = LE16(0);
00072 status_t ret;
00073
00074 if (len != sizeof(status) || usb_setup_is_out(req))
00075 return -1;
00076
00077 switch (usb_setup_recipient(req)) {
00078 case USB_RECIP_DEVICE:
00079 status = LE16(1U << USB_DEV_STATUS_SELF_POWERED);
00080 break;
00081 case USB_RECIP_ENDPOINT:
00082 ret = udc_ep_is_halted(udc, index & USB_EP_ADDR_MASK);
00083 if (ret < 0)
00084 return -1;
00085
00086 status = cpu_to_le16(ret);
00087 break;
00088 default:
00089 break;
00090 }
00091
00092 udc_ep0_write_sync(udc, &status, sizeof(status));
00093 udc_ep0_expect_status(udc);
00094 break;
00095 }
00096
00097 case USB_REQ_CLEAR_FEATURE:
00098 if (len != 0 || usb_setup_is_in(req))
00099 return -1;
00100
00101 if (usb_setup_recipient(req) == USB_RECIP_DEVICE
00102 && value == USB_DEV_FEATURE_REMOTE_WAKEUP) {
00103
00104 } else if (usb_setup_recipient(req) == USB_RECIP_ENDPOINT
00105 && value == USB_EP_FEATURE_HALT) {
00106 if (udc_ep_clear_halt(udc, index & USB_EP_ADDR_MASK))
00107 return -1;
00108 } else {
00109 return -1;
00110 }
00111
00112 udc_ep0_send_status(udc);
00113 break;
00114
00115 case USB_REQ_SET_FEATURE:
00116 if (len != 0 || usb_setup_is_in(req))
00117 return -1;
00118 if (udc_is_high_speed(udc)
00119 && usb_setup_recipient(req) == USB_RECIP_DEVICE
00120 && value == USB_DEV_FEATURE_TEST_MODE) {
00121 if (index & 0xff)
00122 return -1;
00123
00124
00125
00126
00127
00128 usb_dev_set_configuration(udc, 0);
00129
00130 if (udc_enter_test_mode(udc, index >> 8))
00131 return -1;
00132 } else if (usb_setup_recipient(req) == USB_RECIP_ENDPOINT
00133 && value == USB_EP_FEATURE_HALT) {
00134 if (udc_ep_set_halt(udc, index & USB_EP_ADDR_MASK))
00135 return -1;
00136 } else {
00137 return -1;
00138 }
00139
00140 udc_ep0_send_status(udc);
00141 break;
00142
00143 case USB_REQ_SET_ADDRESS:
00144 if (len != 0 || usb_setup_is_in(req) || value > 127)
00145 return -1;
00146
00147
00148
00149
00150
00151
00152 udc_set_address(udc, value);
00153 udc_ep0_send_status(udc);
00154 break;
00155
00156 case USB_REQ_GET_DESCRIPTOR:
00157 if (usb_setup_is_out(req))
00158 return -1;
00159
00160 if (usb_dev_get_descriptor(udc, value, index, len) < 0)
00161 return -1;
00162 break;
00163
00164 case USB_REQ_SET_DESCRIPTOR:
00165
00166 return -1;
00167
00168 case USB_REQ_GET_CONFIGURATION:
00169 build_assert(sizeof(udc->config) == 1);
00170
00171 if (len != 1 || usb_setup_is_out(req))
00172 return -1;
00173
00174 udc_ep0_write_sync(udc, &udc->config, 1);
00175 udc_ep0_expect_status(udc);
00176 break;
00177
00178 case USB_REQ_SET_CONFIGURATION:
00179 if (len != 0 || usb_setup_is_in(req) || !udc->address)
00180 return -1;
00181
00182 if (usb_dev_set_configuration(udc, value) < 0)
00183 return -1;
00184
00185 udc_ep0_send_status(udc);
00186 break;
00187
00188 case USB_REQ_GET_INTERFACE:
00189 if (len != 1 || usb_setup_is_out(req) || !udc->config)
00190 return -1;
00191
00192 if (usb_dev_get_interface(udc, index) < 0)
00193 return -1;
00194 break;
00195
00196 case USB_REQ_SET_INTERFACE:
00197 if (len != 0 || usb_setup_is_in(req) || !udc->config)
00198 return -1;
00199
00200 if (usb_dev_set_interface(udc, index, value) < 0)
00201 return -1;
00202
00203 udc_ep0_send_status(udc);
00204 break;
00205
00206 default:
00207 return -1;
00208 }
00209
00210 return 0;
00211 }
00212
00230 status_t udc_lib_process_setup_request(struct udc *udc,
00231 struct usb_setup_req *req)
00232 {
00233 dbg_verbose("req %02x: t%02x v%04x i%04x l%04x\n",
00234 req->bRequest, req->bmRequestType,
00235 le16_to_cpu(req->wValue), le16_to_cpu(req->wIndex),
00236 le16_to_cpu(req->wLength));
00237
00238 if (usb_setup_type(req) == USB_REQTYPE_STANDARD)
00239 return udc_lib_standard_request(udc, req);
00240 else
00241 return usb_dev_process_setup_request(udc, req);
00242 }
00243