00001
00045 #include <assert.h>
00046 #include <byteorder.h>
00047 #include <debug.h>
00048 #include <dmapool.h>
00049 #include <malloc.h>
00050 #include <string.h>
00051 #include <util.h>
00052 #include <usb/function.h>
00053 #include <usb/function_core.h>
00054 #include <usb/request.h>
00055 #include <usb/udc.h>
00056
00057 #include <app/config_usb.h>
00058 #include <app/usb_strings.h>
00059
00060 static const struct usb_device_descriptor usb_func_device_desc = {
00061 .bLength = sizeof(struct usb_device_descriptor),
00062 .bDescriptorType = USB_DT_DEVICE,
00063 .bcdUSB = LE16(0x0200),
00064 .bDeviceClass = CONFIG_USB_FUNC_DEVICE_CLASS,
00065 .bDeviceSubClass = CONFIG_USB_FUNC_DEVICE_SUBCLASS,
00066 .bDeviceProtocol = CONFIG_USB_FUNC_DEVICE_PROTOCOL,
00067 .bMaxPacketSize0 = 64,
00068 .idVendor = LE16(CONFIG_USB_FUNC_VENDOR_ID),
00069 .idProduct = LE16(CONFIG_USB_FUNC_PRODUCT_ID),
00070 .bcdDevice = LE16((CONFIG_USB_FUNC_MAJOR_VERSION << 8)
00071 | CONFIG_USB_FUNC_MINOR_VERSION),
00072 .iManufacturer = USB_STRING_DEV_MANUFACTURER,
00073 .iProduct = USB_STRING_DEV_PRODUCT,
00074 .iSerialNumber = USB_STRING_DEV_SERIAL,
00075 .bNumConfigurations = CONFIG_USB_FUNC_NR_CONFIGURATIONS,
00076 };
00077
00078 #ifdef CONFIG_UDC_HIGH_SPEED
00079 static const struct usb_device_qualifier_descriptor usb_func_device_qual = {
00080 .bLength = sizeof(struct usb_device_qualifier_descriptor),
00081 .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
00082 .bcdUSB = LE16(0x0200),
00083 .bDeviceClass = CONFIG_USB_FUNC_DEVICE_CLASS,
00084 .bDeviceSubClass = CONFIG_USB_FUNC_DEVICE_SUBCLASS,
00085 .bDeviceProtocol = CONFIG_USB_FUNC_DEVICE_PROTOCOL,
00086 .bMaxPacketSize0 = 64,
00087 .bNumConfigurations = CONFIG_USB_FUNC_NR_CONFIGURATIONS,
00088 };
00089 #endif
00090
00091 static struct usb_func_config usb_func_config[CONFIG_USB_FUNC_NR_CONFIGURATIONS];
00092 static struct usb_request usb_func_control_req;
00093 static struct buffer usb_func_desc_buf;
00094
00095 static struct usb_func_config *usb_func_get_config(unsigned int id)
00096 {
00097 return &usb_func_config[id - 1];
00098 }
00099
00100 static struct usb_func_config *usb_func_get_current_config(struct udc *udc)
00101 {
00102 if (!udc->config)
00103 return NULL;
00104
00105 return usb_func_get_config(udc->config->bConfigurationValue);
00106 }
00107
00108 static unsigned int usb_func_nr_interfaces(struct usb_func_config *config)
00109 {
00110 return config->desc->bNumInterfaces;
00111 }
00112
00137 void usb_func_add_interface(struct usb_func_config *config,
00138 struct usb_func_iface *iface)
00139 {
00140 struct usb_func_iface_setting *setting;
00141 unsigned int id = iface->setting[0].fs_desc->bInterfaceNumber;
00142 unsigned int i;
00143
00144 assert(iface->nr_settings > 0);
00145 assert(id < usb_func_nr_interfaces(config));
00146 assert(!config->interface[id]);
00147
00148 config->interface[id] = iface;
00149
00150 for (i = 0; i < iface->nr_settings; i++) {
00151 setting = &iface->setting[i];
00152
00153 assert(setting->ops);
00154 assert(setting->fs_desc->bInterfaceNumber == id);
00155
00156 if (!setting->hs_desc) {
00157 setting->hs_desc = setting->fs_desc;
00158 setting->hs_desc_size = setting->fs_desc_size;
00159 } else {
00160 assert(setting->hs_desc->bInterfaceNumber == id);
00161 }
00162 }
00163
00164 dbg_printf("func-core: created interface %u with %zu settings\n",
00165 id, iface->nr_settings);
00166 }
00167
00185 struct usb_func_config *usb_func_add_config(
00186 struct usb_configuration_descriptor *desc)
00187 {
00188 struct usb_func_config *config;
00189 unsigned int id = desc->bConfigurationValue;
00190 unsigned int nr_interfaces = desc->bNumInterfaces;
00191
00192 config = usb_func_get_config(id);
00193
00194 assert(id <= CONFIG_USB_FUNC_NR_CONFIGURATIONS);
00195 assert(!config->desc);
00196
00197 config->desc = desc;
00198 config->interface = malloc(nr_interfaces * sizeof(*config->interface));
00199 assert(config->interface);
00200 memset(config->interface, 0,
00201 nr_interfaces * sizeof(*config->interface));
00202
00203 dbg_printf("func-core: created configuration %u with %u interfaces\n",
00204 id, nr_interfaces);
00205
00206 return config;
00207 }
00208
00209 static void usb_func_ctrl_in_done(struct udc *udc, struct usb_request *req)
00210 {
00211 dbg_printf("func-core: Control IN request done\n");
00212
00213 udc_ep0_expect_status(udc);
00214 }
00215
00216 static void usb_func_string_desc_in_done(struct udc *udc,
00217 struct usb_request *req)
00218 {
00219 struct buffer *buf;
00220
00221 dbg_printf("func-core: String IN descriptor done\n");
00222
00223 buf = usb_req_get_first_buffer(req);
00224 dma_free(buf->addr.ptr, USB_MAX_DESC_SIZE);
00225
00226 udc_ep0_expect_status(udc);
00227 }
00228
00229 static int ascii_to_usb_str(const char *src, le16_t *dest, size_t dest_len)
00230 {
00231 size_t len = 0;
00232 char c;
00233
00234 while (len < (dest_len - 1)) {
00235 c = *src++;
00236 if (!c)
00237 break;
00238 *dest++ = cpu_to_le16(c);
00239 len += 2;
00240 }
00241
00242 return len;
00243 }
00244
00245 static int usb_func_prep_config_desc(struct udc *udc,
00246 struct usb_func_config *config, struct usb_request *req,
00247 enum usb_device_speed speed, size_t max_len)
00248 {
00249 const struct usb_interface_descriptor *if_desc;
00250 struct usb_func_iface *iface;
00251 struct usb_func_iface_setting *setting;
00252 size_t buf_len;
00253 size_t total_len;
00254 size_t len;
00255 unsigned int i, j;
00256
00257 total_len = sizeof(*config->desc);
00258 len = min(max_len, total_len);
00259 buffer_init_tx(&usb_func_desc_buf, config->desc, len);
00260 usb_req_add_buffer(req, &usb_func_desc_buf);
00261
00262 for (i = 0; i < usb_func_nr_interfaces(config); i++) {
00263 iface = config->interface[i];
00264
00265 for (j = 0; j < iface->nr_settings; j++) {
00266 setting = &iface->setting[j];
00267
00268 switch (speed) {
00269 case USB_SPEED_FULL:
00270 if_desc = setting->fs_desc;
00271 buf_len = setting->fs_desc_size;
00272 break;
00273 case USB_SPEED_HIGH:
00274 if_desc = setting->hs_desc;
00275 buf_len = setting->hs_desc_size;
00276 break;
00277 default:
00278 return -1;
00279 }
00280
00281 total_len += buf_len;
00282 buf_len = min(buf_len, max_len - len);
00283 if (buf_len == 0)
00284 continue;
00285
00286 buffer_init_tx(&setting->desc_buf, if_desc, buf_len);
00287 usb_req_add_buffer(req, &setting->desc_buf);
00288 len += buf_len;
00289 }
00290 }
00291
00292 config->desc->wTotalLength = cpu_to_le16(total_len);
00293
00294 return len;
00295 }
00296
00297 static int usb_func_prep_string_desc(struct udc *udc,
00298 struct usb_request *req, uint8_t desc_index,
00299 uint16_t langid, uint16_t len)
00300 {
00301 struct usb_string_descriptor *desc;
00302 struct buffer *buf;
00303 const char *str;
00304 phys_addr_t desc_phys;
00305 int str_len;
00306
00307 if (desc_index >= USB_NR_STRINGS)
00308 return -1;
00309 if (desc_index != USB_STRING_LANGID && langid != USB_DEV_LANGID)
00310 return -1;
00311
00312 str = usb_dev_string_table[desc_index];
00313 if (!str)
00314 return -1;
00315
00316 desc = dma_alloc(&desc_phys, USB_MAX_DESC_SIZE);
00317 if (!desc)
00318 return -1;
00319
00320 desc->bDescriptorType = USB_DT_STRING;
00321 if (desc_index == USB_STRING_LANGID) {
00322 desc->bString[0] = LE16(USB_DEV_LANGID);
00323 desc->bLength = 4;
00324 } else {
00325 str_len = ascii_to_usb_str(str, desc->bString,
00326 USB_MAX_DESC_SIZE - 2);
00327 desc->bLength = str_len + 2;
00328 }
00329
00330 buf = &usb_func_desc_buf;
00331 buffer_init_tx_mapped(buf, desc, desc_phys, min(desc->bLength, len));
00332 usb_req_add_buffer(req, buf);
00333
00334 req->req_done = usb_func_string_desc_in_done;
00335
00336 return buf->len;
00337 }
00338
00339 int usb_func_get_descriptor(struct udc *udc, uint16_t value,
00340 uint16_t index, uint16_t len)
00341 {
00342 struct usb_func_config *config;
00343 struct usb_request *req = &usb_func_control_req;
00344 unsigned int desc_index;
00345 unsigned int desc_type;
00346 int buf_len = -1;
00347
00348 dbg_printf("func-core: get descriptor v%04x i%04x l%04x\n",
00349 value, index, len);
00350
00351 usb_req_init(req);
00352
00353 req->req_done = usb_func_ctrl_in_done;
00354
00355 desc_type = value >> 8;
00356 desc_index = value & 0xff;
00357
00358 switch (desc_type) {
00359 case USB_DT_DEVICE:
00360 buf_len = min(len, sizeof(usb_func_device_desc));
00361 buffer_init_tx(&usb_func_desc_buf, &usb_func_device_desc,
00362 buf_len);
00363 usb_req_add_buffer(req, &usb_func_desc_buf);
00364 break;
00365
00366 case USB_DT_CONFIGURATION:
00367 if (desc_index >= CONFIG_USB_FUNC_NR_CONFIGURATIONS)
00368 return -1;
00369
00370 config = &usb_func_config[desc_index];
00371 config->desc->bDescriptorType = desc_type;
00372
00373 buf_len = usb_func_prep_config_desc(udc, config, req,
00374 udc->speed, len);
00375 break;
00376
00377 #ifdef CONFIG_UDC_HIGH_SPEED
00378 case USB_DT_DEVICE_QUALIFIER:
00379 buf_len = min(len, sizeof(usb_func_device_qual));
00380 buffer_init_tx(&usb_func_desc_buf, &usb_func_device_qual,
00381 buf_len);
00382 usb_req_add_buffer(req, &usb_func_desc_buf);
00383 break;
00384
00385 case USB_DT_OTHER_SPEED_CONFIGURATION:
00386 if (desc_index >= CONFIG_USB_FUNC_NR_CONFIGURATIONS)
00387 return -1;
00388
00389 config = &usb_func_config[desc_index];
00390 config->desc->bDescriptorType = desc_type;
00391
00392 if (udc->speed == USB_SPEED_HIGH)
00393 buf_len = usb_func_prep_config_desc(udc, config,
00394 req, USB_SPEED_FULL, len);
00395 else
00396 buf_len = usb_func_prep_config_desc(udc, config,
00397 req, USB_SPEED_HIGH, len);
00398 break;
00399 #endif
00400
00401 case USB_DT_STRING:
00402 buf_len = usb_func_prep_string_desc(udc, req,
00403 desc_index, index, len);
00404 break;
00405 }
00406
00407 if (buf_len < 0)
00408 return -1;
00409
00410 if (buf_len < len)
00411 set_bit(USB_REQ_SHORT_PKT, &req->flags);
00412
00413 udc_ep0_submit_in_req(udc, req);
00414
00415 return 0;
00416 }
00417
00418 static int usb_config_enable(struct udc *udc, struct usb_func_config *config)
00419 {
00420 unsigned int nr_interfaces;
00421 unsigned int i;
00422
00423 nr_interfaces = usb_func_nr_interfaces(config);
00424 for (i = 0; i < nr_interfaces; i++) {
00425 struct usb_func_iface *iface;
00426
00427 iface = config->interface[i];
00428 dbg_printf("func-core: enabling interface %u...\n", i);
00429 if (iface->cur_setting->ops->enable(udc, iface))
00430 goto fail;
00431 }
00432
00433 return 0;
00434
00435 fail:
00436 dbg_printf("func-core: failed to enable config %u\n",
00437 config->desc->bConfigurationValue);
00438 while (i-- > 0) {
00439 struct usb_func_iface *iface;
00440
00441 iface = config->interface[i];
00442 iface->cur_setting->ops->disable(udc, iface);
00443 }
00444
00445 return -1;
00446 }
00447
00448 static void usb_config_disable(struct udc *udc, struct usb_func_config *config)
00449 {
00450 unsigned int nr_interfaces;
00451 unsigned int i;
00452
00453 if (!config)
00454 return;
00455
00456 dbg_printf("func-core: disabling config %u\n",
00457 config->desc->bConfigurationValue);
00458
00459 nr_interfaces = usb_func_nr_interfaces(config);
00460 for (i = 0; i < nr_interfaces; i++) {
00461 struct usb_func_iface *iface;
00462
00463 iface = config->interface[i];
00464 iface->cur_setting->ops->disable(udc, iface);
00465 }
00466 }
00467
00468 static void usb_config_init_iface_settings(struct usb_func_config *config)
00469 {
00470 unsigned int nr_interfaces;
00471 unsigned int i;
00472
00473 nr_interfaces = usb_func_nr_interfaces(config);
00474 for (i = 0; i < nr_interfaces; i++) {
00475 struct usb_func_iface *iface;
00476
00477 iface = config->interface[i];
00478 iface->cur_setting = &iface->setting[0];
00479 }
00480 }
00481
00482 int usb_func_set_configuration(struct udc *udc, uint16_t config_id)
00483 {
00484 struct usb_func_config *old;
00485 struct usb_func_config *new;
00486
00487 dbg_printf("func-core: set configuration %u\n", config_id);
00488
00489 if (config_id > CONFIG_USB_FUNC_NR_CONFIGURATIONS)
00490 return -1;
00491
00492
00493 old = usb_func_get_current_config(udc);
00494 udc->config = NULL;
00495 if (old)
00496 usb_config_disable(udc, old);
00497
00498 if (config_id == 0)
00499 return 0;
00500
00501 new = usb_func_get_config(config_id);
00502 usb_config_init_iface_settings(new);
00503 udc->config = new->desc;
00504 if (usb_config_enable(udc, new)) {
00505 dbg_printf("Failed to set new configuration\n");
00506 if (old) {
00507 udc->config = old->desc;
00508 if (usb_config_enable(udc, old))
00509 udc->config = NULL;
00510 } else {
00511 udc->config = NULL;
00512 }
00513 return -1;
00514 }
00515
00516 return 0;
00517 }
00518
00519 int usb_func_get_interface(struct udc *udc, uint16_t index)
00520 {
00521 struct usb_func_config *config;
00522 struct usb_func_iface *iface;
00523 struct usb_func_iface_setting *setting;
00524
00525 dbg_printf("func-core: get interface %u\n", index);
00526
00527 config = usb_func_get_current_config(udc);
00528 if (!config || index >= usb_func_nr_interfaces(config))
00529 return -1;
00530
00531 iface = config->interface[index];
00532 setting = iface->cur_setting;
00533
00534 udc_ep0_write_sync(udc, &setting->fs_desc->bAlternateSetting, 1);
00535 udc_ep0_expect_status(udc);
00536
00537 return 0;
00538 }
00539
00540 int usb_func_set_interface(struct udc *udc, uint16_t index, uint16_t altsetting)
00541 {
00542 struct usb_func_config *config;
00543 struct usb_func_iface *iface;
00544 struct usb_func_iface_setting *old;
00545 struct usb_func_iface_setting *new;
00546
00547 dbg_printf("func-core: set interface %u altsetting %u\n",
00548 index, altsetting);
00549
00550 config = usb_func_get_current_config(udc);
00551 if (!config || index >= usb_func_nr_interfaces(config))
00552 return -1;
00553
00554 iface = config->interface[index];
00555 if (altsetting >= iface->nr_settings)
00556 return -1;
00557
00558 old = iface->cur_setting;
00559 new = &iface->setting[altsetting];
00560
00561
00562
00563
00564
00565
00566
00567 old->ops->disable(udc, iface);
00568 iface->cur_setting = new;
00569 if (new->ops->enable(udc, iface)) {
00570 iface->cur_setting = old;
00571 old->ops->enable(udc, iface);
00572 return -1;
00573 }
00574
00575 return 0;
00576 }
00577
00578 void usb_func_reset(struct udc *udc)
00579 {
00580 dbg_printf("func-core: reset, speed=%u\n", udc->speed);
00581
00582 if (udc->config)
00583 usb_func_set_configuration(udc, 0);
00584 }
00585
00586 int usb_func_process_setup_request(struct udc *udc, struct usb_setup_req *req)
00587 {
00588 struct usb_func_config *config;
00589 struct usb_func_iface *iface;
00590 struct usb_func_iface_setting *setting;
00591 uint16_t index = le16_to_cpu(req->wIndex);
00592
00593 if (usb_req_recipient(req) != USB_RECIP_INTERFACE) {
00594 dbg_printf("func-core: bad request (bmRequestType: %u)\n",
00595 req->bmRequestType);
00596 return -1;
00597 }
00598
00599 config = usb_func_get_current_config(udc);
00600 if (!config || index >= usb_func_nr_interfaces(config))
00601 return -1;
00602
00603 iface = config->interface[index];
00604 setting = iface->cur_setting;
00605
00606 return setting->ops->setup(udc, iface, req);
00607 }