00001 #include "devices/usb.h"
00002
00003 #include "devices/usb_hub.h"
00004 #include "threads/synch.h"
00005 #include "threads/malloc.h"
00006 #include "devices/timer.h"
00007 #include <kernel/bitmap.h>
00008 #include <string.h>
00009 #include <stdio.h>
00010
00011 #define ADDRS_PER_HOST 127
00012 #define ADDR_DEFAULT 0
00013 #define ADDR_FIRST 1
00014
00016
00017 #define SETUP_DESC_DEVICE 1
00018 #define SETUP_DESC_CONFIG 2
00019 #define SETUP_DESC_STRING 3
00020 #define SETUP_DESC_IFACE 4
00021 #define SETUP_DESC_ENDPOINT 5
00022 #define SETUP_DESC_DEVQUAL 6
00023 #define SETUP_DESC_SPDCONFIG 7
00024 #define SETUP_DESC_IFACEPWR 8
00025
00026 #pragma pack(1)
00027 struct desc_header
00028 {
00029 uint8_t length;
00030 uint8_t type;
00031 };
00032
00037 struct device_descriptor
00038 {
00039 struct desc_header hdr;
00040 uint16_t usb_spec;
00041 uint8_t dev_class;
00042 uint8_t dev_subclass;
00043 uint8_t dev_proto;
00044 uint8_t max_pktsz;
00045
00046 uint16_t vendor_id;
00047 uint16_t product_id;
00048 uint16_t device_id;
00049 uint8_t manufacturer;
00050 uint8_t product;
00051 uint8_t serial;
00052 uint8_t num_configs;
00053 };
00054
00055 struct device_qualifier
00056 {
00057 uint16_t usb_spec;
00058 uint8_t dev_class;
00059 uint8_t dev_subclass;
00060 uint8_t dev_proto;
00061 uint8_t max_pktsz;
00062 uint8_t num_configs;
00063 uint8_t resv;
00064 };
00065
00066 struct config_descriptor
00067 {
00068 struct desc_header hdr;
00069 uint16_t total_length;
00070 uint8_t num_ifaces;
00071 uint8_t config_val;
00072 uint8_t config_desc;
00073 uint8_t attributes;
00074 uint8_t max_power;
00075 };
00076
00077 struct interface_descriptor
00078 {
00079 struct desc_header hdr;
00080 uint8_t iface_num;
00081 uint8_t alt_setting;
00082 uint8_t num_endpoints;
00083 uint8_t iface_class;
00084 uint8_t iface_subclass;
00085 uint8_t iface_proto;
00086 uint8_t iface_desc;
00087 };
00088
00089 struct endpoint_descriptor
00090 {
00091 struct desc_header hdr;
00092
00093 uint8_t endpoint_num:4;
00094 uint8_t resv1:3;
00095 uint8_t direction:1;
00096
00097
00098 uint8_t transfer:2;
00099 uint8_t synch:2;
00100 uint8_t usage:2;
00101 uint8_t resv2:2;
00102
00103 uint16_t max_pktsz;
00104 uint8_t interval;
00105
00106 };
00107
00108 #pragma pack()
00109
00110 #define USB_CLASS_HUB 0x09
00111 struct host
00112 {
00113 struct usb_host *dev;
00114 host_info info;
00115 struct bitmap *usb_dev_addrs;
00116 struct list host_usb_devs;
00117 struct list_elem peers;
00118 };
00119
00120 struct class
00121 {
00122 struct usb_class *dev;
00123 struct list usb_ifaces;
00124 struct list_elem peers;
00125 };
00126
00127 static struct list usb_dev_list;
00128 static struct list class_list;
00129 static struct list host_list;
00130 static struct lock usb_sys_lock;
00131
00132 #define usb_lock() lock_acquire(&usb_sys_lock)
00133 #define usb_unlock() lock_release(&usb_sys_lock)
00134
00135 static void usb_scan_devices (struct host *h);
00136 static struct usb_dev *usb_configure_default (struct host *h);
00137 static char *usb_get_string (struct usb_dev *d, int ndx);
00138 static struct class *usb_get_class_by_id (int id);
00139 static void usb_setup_dev_addr (struct usb_dev *dev);
00140 static void usb_config_dev (struct usb_dev *dev, int config_val);
00141 static int usb_load_config (struct usb_dev *dev, int idx, void *data,
00142 int dsz);
00143 static int usb_tx_all (struct usb_endpoint *eop, void *buf,
00144 int max_bytes, int bailout, bool in);
00145 static void usb_attach_interfaces (struct usb_dev *dev);
00146 static void usb_apply_class_to_interfaces (struct class *c);
00147 static size_t wchar_to_ascii (char *dst, const char *src);
00148
00149 extern void uhci_init (void);
00150 extern void ehci_init (void);
00151
00152 void
00153 usb_init (void)
00154 {
00155 list_init (&host_list);
00156 list_init (&class_list);
00157 list_init (&usb_dev_list);
00158 lock_init (&usb_sys_lock);
00159
00160 usb_hub_init ();
00161
00162
00163 printf ("Initializing EHCI\n");
00164 ehci_init ();
00165 printf ("Initializing UHCI\n");
00166 uhci_init ();
00167 }
00168
00169
00170 void
00171 usb_register_host (struct usb_host *uh, host_info info)
00172 {
00173 struct host *h;
00174
00175 h = malloc (sizeof (struct host));
00176 h->dev = uh;
00177 h->info = info;
00178 h->usb_dev_addrs = bitmap_create (ADDRS_PER_HOST);
00179 list_init (&h->host_usb_devs);
00180
00181 usb_lock ();
00182 list_push_back (&host_list, &h->peers);
00183 usb_unlock ();
00184
00185 usb_scan_devices (h);
00186 }
00187
00188 int
00189 usb_register_class (struct usb_class *uc)
00190 {
00191 struct class *c;
00192
00193 usb_lock ();
00194
00195
00196 if (usb_get_class_by_id (uc->class_id) != NULL)
00197 {
00198 usb_unlock ();
00199 return -1;
00200 }
00201
00202
00203
00204 c = malloc (sizeof (struct class));
00205 c->dev = uc;
00206 list_init (&c->usb_ifaces);
00207 list_push_back (&class_list, &c->peers);
00208
00209 usb_apply_class_to_interfaces (c);
00210
00211 usb_unlock ();
00212
00213 return 0;
00214 }
00215
00216 static void
00217 usb_scan_devices (struct host *h)
00218 {
00219
00220
00221 printf ("USB: scanning devices...\n");
00222 while (1)
00223 {
00224 struct usb_dev *dev;
00225
00226 dev = usb_configure_default (h);
00227 if (dev == NULL)
00228 break;
00229
00230 if (dev->ignore_device == false)
00231 printf ("USB Device %d: %s (%s)\n",
00232 dev->addr, dev->product, dev->manufacturer);
00233
00234 list_push_back (&h->host_usb_devs, &dev->host_peers);
00235 list_push_back (&usb_dev_list, &dev->sys_peers);
00236 usb_attach_interfaces (dev);
00237 }
00238 }
00239
00240 static int
00241 send_status (struct host *h, host_eop_info cfg_eop)
00242 {
00243 int sz;
00244 int err;
00245
00246 h->dev->set_toggle (cfg_eop, 1);
00247 sz = 0;
00248 err = h->dev->tx_pkt (cfg_eop, USB_TOKEN_OUT, NULL, 0, 0, &sz, true);
00249 if (err)
00250 printf ("error %d in status transaction\n", err);
00251 return err;
00252 }
00253
00254 static struct usb_dev *
00255 usb_configure_default (struct host *h)
00256 {
00257 struct usb_dev *dev;
00258 struct usb_setup_pkt sp;
00259 char data[256];
00260 struct device_descriptor *dd;
00261 host_dev_info hi;
00262 host_eop_info cfg_eop;
00263 bool ignore_device = false;
00264 int err, sz;
00265 unsigned txed;
00266 int config_val;
00267
00268 hi = h->dev->create_dev_channel (h->info, ADDR_DEFAULT, USB_VERSION_1_1);
00269 cfg_eop = h->dev->create_eop (hi, 0, 64);
00270
00271
00272 sp.recipient = USB_SETUP_RECIP_DEV;
00273 sp.type = USB_SETUP_TYPE_STD;
00274 sp.direction = 1;
00275 sp.request = REQ_STD_GET_DESC;
00276 sp.value = SETUP_DESC_DEVICE << 8;
00277 sp.index = 0;
00278 sp.length = 8;
00279
00280 err =
00281 h->dev->tx_pkt (cfg_eop, USB_TOKEN_SETUP, &sp, 0, sizeof (sp), NULL,
00282 true);
00283 if (err != USB_HOST_ERR_NONE)
00284 goto error;
00285
00286 dd = (void *) &data;
00287 memset (dd, 0, sizeof (data));
00288 txed = 0;
00289 err = h->dev->tx_pkt (cfg_eop, USB_TOKEN_IN, data, 0, 8, &sz, true);
00290 if (err != USB_HOST_ERR_NONE)
00291 goto error;
00292
00293 err = send_status (h, cfg_eop);
00294 if (err != USB_HOST_ERR_NONE)
00295 return NULL;
00296
00297 #if 0
00298 if (dd->usb_spec == USB_VERSION_1_0)
00299 {
00300
00301 printf ("USB 1.0 device detected - skipping\n");
00302 goto error;
00303 }
00304 #endif
00305
00306
00307 if (dd->max_pktsz != 8 && dd->max_pktsz != 16
00308 && dd->max_pktsz != 32 && dd->max_pktsz != 64)
00309 goto error;
00310
00311 h->dev->remove_eop (cfg_eop);
00312 cfg_eop = h->dev->create_eop (hi, 0, dd->max_pktsz);
00313
00314
00315 sp.length = sizeof *dd;
00316 err =
00317 h->dev->tx_pkt (cfg_eop, USB_TOKEN_SETUP, &sp, 0, sizeof (sp), NULL,
00318 true);
00319 if (err != USB_HOST_ERR_NONE)
00320 goto error;
00321
00322 txed = 0;
00323 while (txed < sizeof *dd)
00324 {
00325 err = h->dev->tx_pkt (cfg_eop, USB_TOKEN_IN, data + txed, 0,
00326 sizeof *dd - txed, &sz, true);
00327 if (err)
00328 goto error;
00329 txed += sz;
00330 }
00331
00332 err = send_status (h, cfg_eop);
00333 if (err != USB_HOST_ERR_NONE)
00334 return NULL;
00335
00336 if (dd->num_configs == 0)
00337 ignore_device = true;
00338
00339
00340 dev = malloc (sizeof (struct usb_dev));
00341 memset (dev, 0, sizeof (struct usb_dev));
00342 list_init (&dev->interfaces);
00343
00344 dev->ignore_device = ignore_device;
00345 dev->h_dev = hi;
00346 dev->h_cfg_eop = cfg_eop;
00347
00348 dev->cfg_eop.h_eop = cfg_eop;
00349
00350 dev->usb_version = dd->usb_spec;
00351 dev->default_iface.class_id = dd->dev_class;
00352 dev->default_iface.subclass_id = dd->dev_subclass;
00353 dev->default_iface.iface_num = 0;
00354 dev->default_iface.proto = dd->dev_proto;
00355 dev->default_iface.class = NULL;
00356 dev->default_iface.c_info = NULL;
00357 dev->default_iface.dev = dev;
00358
00359 dev->cfg_eop.iface = &dev->default_iface;
00360 dev->cfg_eop.max_pkt = dd->max_pktsz;
00361 dev->cfg_eop.eop = 0;
00362
00363 dev->host = h;
00364
00365 dev->vendor_id = dd->vendor_id;
00366 dev->product_id = dd->product_id;
00367 dev->device_id = dd->device_id;
00368
00369 if (ignore_device == false)
00370 {
00371 dev->product = usb_get_string (dev, dd->product);
00372 dev->manufacturer = usb_get_string (dev, dd->manufacturer);
00373 }
00374
00375 config_val = -123;
00376
00377
00378 if (dd->num_configs > 0 && ignore_device == false)
00379 {
00380 config_val = usb_load_config (dev, 0, data, sizeof (data));
00381 if (config_val < 0)
00382 {
00383 printf
00384 ("USB: Invalid configuration value %d on '%s (%s)' (%x,%x,%x)\n",
00385 config_val, dev->product, dev->manufacturer, dev->vendor_id,
00386 dev->product_id, dev->device_id);
00387 }
00388 }
00389
00390 usb_setup_dev_addr (dev);
00391
00392 usb_config_dev (dev, (config_val < 0) ? 1 : config_val);
00393
00394 return dev;
00395
00396 error:
00397 h->dev->remove_eop (cfg_eop);
00398 h->dev->remove_dev_channel (hi);
00399 return NULL;
00400 }
00401
00406 static int
00407 usb_load_config (struct usb_dev *dev, int idx, void *data, int dsz)
00408 {
00409 struct usb_setup_pkt sp;
00410 struct config_descriptor *cd;
00411 struct host *h;
00412 host_eop_info cfg;
00413 void *ptr;
00414 int config_val, err, sz;
00415 int i;
00416
00417 h = dev->host;
00418 cfg = dev->h_cfg_eop;
00419
00420 sp.recipient = USB_SETUP_RECIP_DEV;
00421 sp.type = USB_SETUP_TYPE_STD;
00422 sp.direction = 1;
00423 sp.request = REQ_STD_GET_DESC;
00424 sp.value = SETUP_DESC_CONFIG << 8 | idx;
00425 sp.index = 0;
00426 sp.length = dsz;
00427 cd = data;
00428
00429 err = h->dev->tx_pkt (cfg, USB_TOKEN_SETUP, &sp, 0, sizeof (sp), &sz, true);
00430 if (err != USB_HOST_ERR_NONE)
00431 {
00432 printf ("USB: Could not setup GET descriptor\n");
00433 return -err;
00434 }
00435
00436 sz = usb_tx_all (&dev->cfg_eop, cd, dsz,
00437 sizeof (struct config_descriptor), true);
00438 if (sz < (int) sizeof (struct config_descriptor))
00439 {
00440 printf ("USB: Did not rx GET descriptor (%d bytes, expected %d)\n", sz,
00441 sizeof (struct config_descriptor));
00442 return -err;
00443 }
00444
00445 if (sz == 0 || cd->hdr.type != SETUP_DESC_CONFIG)
00446 {
00447 printf ("USB: Invalid descriptor\n");
00448 return -1;
00449 }
00450
00451 if (sz < cd->total_length)
00452 sz += usb_tx_all (&dev->cfg_eop, data+sz, dsz, cd->total_length - sz, true);
00453
00454 send_status (h, cfg);
00455
00456 dev->pwr = cd->max_power;
00457
00458
00459
00460 ptr = data + sizeof (struct config_descriptor);
00461
00462 for (i = 0; i < cd->num_ifaces; i++)
00463 {
00464 struct interface_descriptor *iface;
00465 struct usb_iface *ui;
00466 int j;
00467
00468 iface = ptr;
00469 if (iface->hdr.type != SETUP_DESC_IFACE)
00470 {
00471 hex_dump (0, iface, 64, false);
00472 PANIC ("Expected %d, found %d\n", SETUP_DESC_IFACE,
00473 iface->hdr.type);
00474 }
00475
00476 ui = malloc (sizeof (struct usb_iface));
00477 ui->class_id = iface->iface_class;
00478 ui->subclass_id = iface->iface_subclass;
00479 ui->iface_num = iface->iface_num;
00480 ui->proto = iface->iface_proto;
00481 ui->class = NULL;
00482 ui->c_info = NULL;
00483 ui->dev = dev;
00484 list_init (&ui->endpoints);
00485
00486
00487
00488 ptr += sizeof (struct interface_descriptor);
00489 for (j = 0; j < iface->num_endpoints;
00490 j++, ptr += sizeof (struct endpoint_descriptor))
00491 {
00492 struct usb_endpoint *ue;
00493 struct endpoint_descriptor *ed;
00494
00495 ed = ptr;
00496
00497 ue = malloc (sizeof (struct usb_endpoint));
00498 ue->eop = ed->endpoint_num;
00499 ue->direction = ed->direction;
00500 ue->attr = ed->transfer;
00501 ue->max_pkt = ed->max_pktsz;
00502 ue->interval = ed->interval;
00503 ue->iface = ui;
00504 ue->h_eop = h->dev->create_eop (dev->h_dev, ue->eop, ue->max_pkt);
00505
00506 list_push_back (&ui->endpoints, &ue->peers);
00507 }
00508
00509 list_push_back (&dev->interfaces, &ui->peers);
00510 }
00511
00512 config_val = cd->config_val;
00513
00514 return config_val;
00515 }
00516
00520 static void
00521 usb_config_dev (struct usb_dev *dev, int config_val)
00522 {
00523 struct usb_setup_pkt sp;
00524 struct host *h;
00525 host_eop_info cfg;
00526 int err;
00527
00528 h = dev->host;
00529 cfg = dev->h_cfg_eop;
00530
00531 sp.recipient = USB_SETUP_RECIP_DEV;
00532 sp.type = USB_SETUP_TYPE_STD;
00533 sp.direction = 0;
00534 sp.request = REQ_STD_SET_CONFIG;
00535 sp.value = config_val;
00536 sp.index = 0;
00537 sp.length = 0;
00538 err = h->dev->tx_pkt (cfg, USB_TOKEN_SETUP, &sp, 0, sizeof (sp), NULL, true);
00539 if (err != USB_HOST_ERR_NONE)
00540 PANIC ("USB: Config setup packet did not tx\n");
00541
00542 err = h->dev->tx_pkt (cfg, USB_TOKEN_IN, NULL, 0, 0, NULL, true);
00543 if (err != USB_HOST_ERR_NONE)
00544 PANIC ("USB: Could not configure device!\n");
00545 }
00546
00550 static void
00551 usb_setup_dev_addr (struct usb_dev *dev)
00552 {
00553 struct usb_setup_pkt sp;
00554 struct host *h;
00555 host_eop_info cfg;
00556 int err;
00557
00558 ASSERT (dev->addr == 0);
00559
00560 h = dev->host;
00561 cfg = dev->h_cfg_eop;
00562
00563 dev->addr = bitmap_scan_and_flip (h->usb_dev_addrs, 1, 1, false);
00564
00565 sp.recipient = USB_SETUP_RECIP_DEV;
00566 sp.type = USB_SETUP_TYPE_STD;
00567 sp.direction = 0;
00568 sp.request = REQ_STD_SET_ADDRESS;
00569 sp.value = dev->addr;
00570 sp.index = 0;
00571 sp.length = 0;
00572 err =
00573 h->dev->tx_pkt (cfg, USB_TOKEN_SETUP, &sp, 0, sizeof (sp), NULL, true);
00574 if (err != USB_HOST_ERR_NONE)
00575 {
00576 PANIC ("USB: WHOOPS!!!!!!!\n");
00577 }
00578 err = h->dev->tx_pkt (cfg, USB_TOKEN_IN, NULL, 0, 0, NULL, true);
00579 if (err != USB_HOST_ERR_NONE)
00580 {
00581 PANIC ("USB: Error on setting device address (err = %d)\n", err);
00582 }
00583
00584 h->dev->modify_dev_channel (dev->h_dev, dev->addr, dev->usb_version);
00585 }
00586
00587 #define MAX_USB_STR 128
00588
00589 static char *
00590 usb_get_string (struct usb_dev *udev, int ndx)
00591 {
00592 struct usb_setup_pkt sp;
00593 char str[MAX_USB_STR];
00594 char *ret;
00595 int sz;
00596
00597 sp.recipient = USB_SETUP_RECIP_DEV;
00598 sp.type = USB_SETUP_TYPE_STD;
00599 sp.direction = 1;
00600 sp.request = REQ_STD_GET_DESC;
00601 sp.value = (SETUP_DESC_STRING << 8) | ndx;
00602 sp.index = 0;
00603 sp.length = MAX_USB_STR;
00604
00605 if (udev->host->dev->tx_pkt (udev->h_cfg_eop, USB_TOKEN_SETUP,
00606 &sp, 0, sizeof (sp), NULL, true)
00607 != USB_HOST_ERR_NONE)
00608 return NULL;
00609
00610 sz = usb_tx_all (&udev->cfg_eop, &str, MAX_USB_STR, 2, true);
00611 sz +=
00612 usb_tx_all (&udev->cfg_eop, str + sz, (uint8_t) (str[0]) - sz, 0, true);
00613
00614
00615 if (sz == 0)
00616 return NULL;
00617
00618 send_status (udev->host, udev->h_cfg_eop);
00619
00620
00621
00622
00623 str[(sz < (MAX_USB_STR - 1)) ? (sz) : (MAX_USB_STR - 1)] = '\0';
00624
00625
00626 wchar_to_ascii (str, str + 2);
00627 ret = malloc (strlen (str) + 1);
00628 strlcpy (ret, str, MAX_USB_STR);
00629 return ret;
00630 }
00631
00632 static struct class *
00633 usb_get_class_by_id (int id)
00634 {
00635 struct list_elem *li;
00636
00637 li = list_begin (&class_list);
00638 while (li != list_end (&class_list))
00639 {
00640 struct class *c;
00641 c = list_entry (li, struct class, peers);
00642 if (c->dev->class_id == id)
00643 return c;
00644 li = list_next (li);
00645 }
00646
00647 return NULL;
00648 }
00649
00653 static void
00654 usb_attach_interfaces (struct usb_dev *dev)
00655 {
00656
00657 struct list_elem *li;
00658 li = list_begin (&dev->interfaces);
00659 while (li != list_end (&dev->interfaces))
00660 {
00661 struct class *cl;
00662 struct usb_iface *ui;
00663
00664 ui = list_entry (li, struct usb_iface, peers);
00665 li = list_next (li);
00666 cl = usb_get_class_by_id (ui->class_id);
00667
00668
00669 if (cl == NULL)
00670 continue;
00671
00672 ui->c_info = cl->dev->attached (ui);
00673
00674 if (ui->c_info != NULL)
00675 {
00676
00677 list_push_back (&cl->usb_ifaces, &ui->class_peers);
00678 ui->class = cl;
00679 }
00680 }
00681 }
00682
00687 static void
00688 usb_apply_class_to_interfaces (struct class *c)
00689 {
00690 struct list_elem *li;
00691
00692 li = list_begin (&usb_dev_list);
00693 while (li != list_end (&usb_dev_list))
00694 {
00695 struct usb_dev *ud;
00696 struct list_elem *lii;
00697
00698 ud = list_entry (li, struct usb_dev, sys_peers);
00699
00700 lii = list_begin (&ud->interfaces);
00701 while (lii != list_end (&ud->interfaces))
00702 {
00703 struct usb_iface *ui;
00704
00705 ui = list_entry (lii, struct usb_iface, peers);
00706
00707 lii = list_next (lii);
00708 if (ui->class_id != c->dev->class_id)
00709 continue;
00710
00711 ui->c_info = c->dev->attached (ui);
00712 if (ui->c_info == NULL)
00713 continue;
00714
00715 list_push_back (&c->usb_ifaces, &ui->class_peers);
00716 ui->class = c;
00717 }
00718
00719 li = list_next (li);
00720 }
00721 }
00722
00723 int
00724 usb_dev_bulk (struct usb_endpoint *eop, void *buf, int sz, int *tx)
00725 {
00726 struct host *h;
00727 int err;
00728 int token;
00729
00730 ASSERT (eop != NULL);
00731 h = eop->iface->dev->host;
00732
00733 if (eop->direction == 0)
00734 token = USB_TOKEN_OUT;
00735 else
00736 token = USB_TOKEN_IN;
00737
00738 err = h->dev->tx_pkt (eop->h_eop, token, buf, sz, sz, tx, true);
00739
00740 return err;
00741 }
00742
00743 int
00744 usb_dev_setup (struct usb_endpoint *eop, bool in,
00745 struct usb_setup_pkt *s, void *buf, int sz)
00746 {
00747 struct host *h;
00748 int err;
00749
00750 ASSERT (eop != NULL);
00751 h = eop->iface->dev->host;
00752
00753 err = h->dev->tx_pkt (eop->h_eop, USB_TOKEN_SETUP, s,
00754 0, sizeof (struct usb_setup_pkt), NULL, true);
00755 if (err != USB_HOST_ERR_NONE)
00756 {
00757 printf ("usb_dev_setup: failed\n");
00758 return 0;
00759 }
00760
00761 err = h->dev->tx_pkt (eop->h_eop, (in) ? USB_TOKEN_IN : USB_TOKEN_OUT,
00762 buf, 0, sz, &sz, true);
00763
00764 return sz;
00765 }
00766
00768 static size_t
00769 wchar_to_ascii (char *dst, const char *src)
00770 {
00771 size_t sz = 0;
00772 for (sz = 0; src[sz * 2] != '\0'; sz++)
00773 {
00774 dst[sz] = src[sz * 2];
00775 }
00776 dst[sz] = '\0';
00777 return sz;
00778 }
00779
00780
00781
00782
00783
00784 static int
00785 usb_tx_all (struct usb_endpoint *eop, void *buf,
00786 int max_bytes, int bailout, bool in)
00787 {
00788 int txed;
00789 int token;
00790 int prev_sz = 0;
00791 struct host *h;
00792
00793 if (max_bytes <= 0)
00794 return 0;
00795
00796 if (bailout == 0)
00797 bailout = 512;
00798
00799 txed = 0;
00800 token = (in) ? USB_TOKEN_IN : USB_TOKEN_OUT;
00801 h = eop->iface->dev->host;
00802 while (txed < max_bytes && txed < bailout)
00803 {
00804 int sz, err;
00805 sz = 0;
00806 err = h->dev->tx_pkt (eop->h_eop, token,
00807 buf + txed, 0, max_bytes - txed, &sz, true);
00808 if (prev_sz == 0)
00809 prev_sz = sz;
00810 txed += sz;
00811
00812 if (err != USB_HOST_ERR_NONE || sz != prev_sz || sz == 0)
00813 {
00814 return txed;
00815 }
00816 }
00817 return txed;
00818 }