uboot/cmd/usb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2001
   4 * Denis Peter, MPL AG Switzerland
   5 *
   6 * Adapted for U-Boot driver model
   7 * (C) Copyright 2015 Google, Inc
   8 *
   9 * Most of this source has been derived from the Linux USB
  10 * project.
  11 */
  12
  13#include <common.h>
  14#include <command.h>
  15#include <console.h>
  16#include <dm.h>
  17#include <dm/uclass-internal.h>
  18#include <memalign.h>
  19#include <asm/byteorder.h>
  20#include <asm/unaligned.h>
  21#include <part.h>
  22#include <usb.h>
  23
  24#ifdef CONFIG_USB_STORAGE
  25static int usb_stor_curr_dev = -1; /* current device */
  26#endif
  27#if defined(CONFIG_USB_HOST_ETHER) && !defined(CONFIG_DM_ETH)
  28static int __maybe_unused usb_ether_curr_dev = -1; /* current ethernet device */
  29#endif
  30
  31/* some display routines (info command) */
  32static char *usb_get_class_desc(unsigned char dclass)
  33{
  34        switch (dclass) {
  35        case USB_CLASS_PER_INTERFACE:
  36                return "See Interface";
  37        case USB_CLASS_AUDIO:
  38                return "Audio";
  39        case USB_CLASS_COMM:
  40                return "Communication";
  41        case USB_CLASS_HID:
  42                return "Human Interface";
  43        case USB_CLASS_PRINTER:
  44                return "Printer";
  45        case USB_CLASS_MASS_STORAGE:
  46                return "Mass Storage";
  47        case USB_CLASS_HUB:
  48                return "Hub";
  49        case USB_CLASS_DATA:
  50                return "CDC Data";
  51        case USB_CLASS_VENDOR_SPEC:
  52                return "Vendor specific";
  53        default:
  54                return "";
  55        }
  56}
  57
  58static void usb_display_class_sub(unsigned char dclass, unsigned char subclass,
  59                                  unsigned char proto)
  60{
  61        switch (dclass) {
  62        case USB_CLASS_PER_INTERFACE:
  63                printf("See Interface");
  64                break;
  65        case USB_CLASS_HID:
  66                printf("Human Interface, Subclass: ");
  67                switch (subclass) {
  68                case USB_SUB_HID_NONE:
  69                        printf("None");
  70                        break;
  71                case USB_SUB_HID_BOOT:
  72                        printf("Boot ");
  73                        switch (proto) {
  74                        case USB_PROT_HID_NONE:
  75                                printf("None");
  76                                break;
  77                        case USB_PROT_HID_KEYBOARD:
  78                                printf("Keyboard");
  79                                break;
  80                        case USB_PROT_HID_MOUSE:
  81                                printf("Mouse");
  82                                break;
  83                        default:
  84                                printf("reserved");
  85                                break;
  86                        }
  87                        break;
  88                default:
  89                        printf("reserved");
  90                        break;
  91                }
  92                break;
  93        case USB_CLASS_MASS_STORAGE:
  94                printf("Mass Storage, ");
  95                switch (subclass) {
  96                case US_SC_RBC:
  97                        printf("RBC ");
  98                        break;
  99                case US_SC_8020:
 100                        printf("SFF-8020i (ATAPI)");
 101                        break;
 102                case US_SC_QIC:
 103                        printf("QIC-157 (Tape)");
 104                        break;
 105                case US_SC_UFI:
 106                        printf("UFI");
 107                        break;
 108                case US_SC_8070:
 109                        printf("SFF-8070");
 110                        break;
 111                case US_SC_SCSI:
 112                        printf("Transp. SCSI");
 113                        break;
 114                default:
 115                        printf("reserved");
 116                        break;
 117                }
 118                printf(", ");
 119                switch (proto) {
 120                case US_PR_CB:
 121                        printf("Command/Bulk");
 122                        break;
 123                case US_PR_CBI:
 124                        printf("Command/Bulk/Int");
 125                        break;
 126                case US_PR_BULK:
 127                        printf("Bulk only");
 128                        break;
 129                default:
 130                        printf("reserved");
 131                        break;
 132                }
 133                break;
 134        default:
 135                printf("%s", usb_get_class_desc(dclass));
 136                break;
 137        }
 138}
 139
 140static void usb_display_string(struct usb_device *dev, int index)
 141{
 142        ALLOC_CACHE_ALIGN_BUFFER(char, buffer, 256);
 143
 144        if (index != 0) {
 145                if (usb_string(dev, index, &buffer[0], 256) > 0)
 146                        printf("String: \"%s\"", buffer);
 147        }
 148}
 149
 150static void usb_display_desc(struct usb_device *dev)
 151{
 152        uint packet_size = dev->descriptor.bMaxPacketSize0;
 153
 154        if (dev->descriptor.bDescriptorType == USB_DT_DEVICE) {
 155                printf("%d: %s,  USB Revision %x.%x\n", dev->devnum,
 156                usb_get_class_desc(dev->config.if_desc[0].desc.bInterfaceClass),
 157                                   (dev->descriptor.bcdUSB>>8) & 0xff,
 158                                   dev->descriptor.bcdUSB & 0xff);
 159
 160                if (strlen(dev->mf) || strlen(dev->prod) ||
 161                    strlen(dev->serial))
 162                        printf(" - %s %s %s\n", dev->mf, dev->prod,
 163                                dev->serial);
 164                if (dev->descriptor.bDeviceClass) {
 165                        printf(" - Class: ");
 166                        usb_display_class_sub(dev->descriptor.bDeviceClass,
 167                                              dev->descriptor.bDeviceSubClass,
 168                                              dev->descriptor.bDeviceProtocol);
 169                        printf("\n");
 170                } else {
 171                        printf(" - Class: (from Interface) %s\n",
 172                               usb_get_class_desc(
 173                                dev->config.if_desc[0].desc.bInterfaceClass));
 174                }
 175                if (dev->descriptor.bcdUSB >= cpu_to_le16(0x0300))
 176                        packet_size = 1 << packet_size;
 177                printf(" - PacketSize: %d  Configurations: %d\n",
 178                        packet_size, dev->descriptor.bNumConfigurations);
 179                printf(" - Vendor: 0x%04x  Product 0x%04x Version %d.%d\n",
 180                        dev->descriptor.idVendor, dev->descriptor.idProduct,
 181                        (dev->descriptor.bcdDevice>>8) & 0xff,
 182                        dev->descriptor.bcdDevice & 0xff);
 183        }
 184
 185}
 186
 187static void usb_display_conf_desc(struct usb_config_descriptor *config,
 188                                  struct usb_device *dev)
 189{
 190        printf("   Configuration: %d\n", config->bConfigurationValue);
 191        printf("   - Interfaces: %d %s%s%dmA\n", config->bNumInterfaces,
 192               (config->bmAttributes & 0x40) ? "Self Powered " : "Bus Powered ",
 193               (config->bmAttributes & 0x20) ? "Remote Wakeup " : "",
 194                config->bMaxPower*2);
 195        if (config->iConfiguration) {
 196                printf("   - ");
 197                usb_display_string(dev, config->iConfiguration);
 198                printf("\n");
 199        }
 200}
 201
 202static void usb_display_if_desc(struct usb_interface_descriptor *ifdesc,
 203                                struct usb_device *dev)
 204{
 205        printf("     Interface: %d\n", ifdesc->bInterfaceNumber);
 206        printf("     - Alternate Setting %d, Endpoints: %d\n",
 207                ifdesc->bAlternateSetting, ifdesc->bNumEndpoints);
 208        printf("     - Class ");
 209        usb_display_class_sub(ifdesc->bInterfaceClass,
 210                ifdesc->bInterfaceSubClass, ifdesc->bInterfaceProtocol);
 211        printf("\n");
 212        if (ifdesc->iInterface) {
 213                printf("     - ");
 214                usb_display_string(dev, ifdesc->iInterface);
 215                printf("\n");
 216        }
 217}
 218
 219static void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc)
 220{
 221        printf("     - Endpoint %d %s ", epdesc->bEndpointAddress & 0xf,
 222                (epdesc->bEndpointAddress & 0x80) ? "In" : "Out");
 223        switch ((epdesc->bmAttributes & 0x03)) {
 224        case 0:
 225                printf("Control");
 226                break;
 227        case 1:
 228                printf("Isochronous");
 229                break;
 230        case 2:
 231                printf("Bulk");
 232                break;
 233        case 3:
 234                printf("Interrupt");
 235                break;
 236        }
 237        printf(" MaxPacket %d", get_unaligned(&epdesc->wMaxPacketSize));
 238        if ((epdesc->bmAttributes & 0x03) == 0x3)
 239                printf(" Interval %dms", epdesc->bInterval);
 240        printf("\n");
 241}
 242
 243/* main routine to diasplay the configs, interfaces and endpoints */
 244static void usb_display_config(struct usb_device *dev)
 245{
 246        struct usb_config *config;
 247        struct usb_interface *ifdesc;
 248        struct usb_endpoint_descriptor *epdesc;
 249        int i, ii;
 250
 251        config = &dev->config;
 252        usb_display_conf_desc(&config->desc, dev);
 253        for (i = 0; i < config->no_of_if; i++) {
 254                ifdesc = &config->if_desc[i];
 255                usb_display_if_desc(&ifdesc->desc, dev);
 256                for (ii = 0; ii < ifdesc->no_of_ep; ii++) {
 257                        epdesc = &ifdesc->ep_desc[ii];
 258                        usb_display_ep_desc(epdesc);
 259                }
 260        }
 261        printf("\n");
 262}
 263
 264/*
 265 * With driver model this isn't right since we can have multiple controllers
 266 * and the device numbering starts at 1 on each bus.
 267 * TODO(sjg@chromium.org): Add a way to specify the controller/bus.
 268 */
 269static struct usb_device *usb_find_device(int devnum)
 270{
 271#ifdef CONFIG_DM_USB
 272        struct usb_device *udev;
 273        struct udevice *hub;
 274        struct uclass *uc;
 275        int ret;
 276
 277        /* Device addresses start at 1 */
 278        devnum++;
 279        ret = uclass_get(UCLASS_USB_HUB, &uc);
 280        if (ret)
 281                return NULL;
 282
 283        uclass_foreach_dev(hub, uc) {
 284                struct udevice *dev;
 285
 286                if (!device_active(hub))
 287                        continue;
 288                udev = dev_get_parent_priv(hub);
 289                if (udev->devnum == devnum)
 290                        return udev;
 291
 292                for (device_find_first_child(hub, &dev);
 293                     dev;
 294                     device_find_next_child(&dev)) {
 295                        if (!device_active(hub))
 296                                continue;
 297
 298                        udev = dev_get_parent_priv(dev);
 299                        if (udev->devnum == devnum)
 300                                return udev;
 301                }
 302        }
 303#else
 304        struct usb_device *udev;
 305        int d;
 306
 307        for (d = 0; d < USB_MAX_DEVICE; d++) {
 308                udev = usb_get_dev_index(d);
 309                if (udev == NULL)
 310                        return NULL;
 311                if (udev->devnum == devnum)
 312                        return udev;
 313        }
 314#endif
 315
 316        return NULL;
 317}
 318
 319static inline const char *portspeed(int speed)
 320{
 321        switch (speed) {
 322        case USB_SPEED_SUPER:
 323                return "5 Gb/s";
 324        case USB_SPEED_HIGH:
 325                return "480 Mb/s";
 326        case USB_SPEED_LOW:
 327                return "1.5 Mb/s";
 328        default:
 329                return "12 Mb/s";
 330        }
 331}
 332
 333/* shows the device tree recursively */
 334static void usb_show_tree_graph(struct usb_device *dev, char *pre)
 335{
 336        int index;
 337        int has_child, last_child;
 338
 339        index = strlen(pre);
 340        printf(" %s", pre);
 341#ifdef CONFIG_DM_USB
 342        has_child = device_has_active_children(dev->dev);
 343        if (device_get_uclass_id(dev->dev) == UCLASS_MASS_STORAGE) {
 344                struct udevice *child;
 345
 346                for (device_find_first_child(dev->dev, &child);
 347                     child;
 348                     device_find_next_child(&child)) {
 349                        if (device_get_uclass_id(child) == UCLASS_BLK)
 350                                has_child = 0;
 351                }
 352        }
 353#else
 354        /* check if the device has connected children */
 355        int i;
 356
 357        has_child = 0;
 358        for (i = 0; i < dev->maxchild; i++) {
 359                if (dev->children[i] != NULL)
 360                        has_child = 1;
 361        }
 362#endif
 363        /* check if we are the last one */
 364#ifdef CONFIG_DM_USB
 365        /* Not the root of the usb tree? */
 366        if (device_get_uclass_id(dev->dev->parent) != UCLASS_USB) {
 367                last_child = device_is_last_sibling(dev->dev);
 368#else
 369        if (dev->parent != NULL) { /* not root? */
 370                last_child = 1;
 371                for (i = 0; i < dev->parent->maxchild; i++) {
 372                        /* search for children */
 373                        if (dev->parent->children[i] == dev) {
 374                                /* found our pointer, see if we have a
 375                                 * little sister
 376                                 */
 377                                while (i++ < dev->parent->maxchild) {
 378                                        if (dev->parent->children[i] != NULL) {
 379                                                /* found a sister */
 380                                                last_child = 0;
 381                                                break;
 382                                        } /* if */
 383                                } /* while */
 384                        } /* device found */
 385                } /* for all children of the parent */
 386#endif
 387                printf("\b+-");
 388                /* correct last child */
 389                if (last_child && index)
 390                        pre[index-1] = ' ';
 391        } /* if not root hub */
 392        else
 393                printf(" ");
 394        printf("%d ", dev->devnum);
 395        pre[index++] = ' ';
 396        pre[index++] = has_child ? '|' : ' ';
 397        pre[index] = 0;
 398        printf(" %s (%s, %dmA)\n", usb_get_class_desc(
 399                                        dev->config.if_desc[0].desc.bInterfaceClass),
 400                                        portspeed(dev->speed),
 401                                        dev->config.desc.bMaxPower * 2);
 402        if (strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial))
 403                printf(" %s  %s %s %s\n", pre, dev->mf, dev->prod, dev->serial);
 404        printf(" %s\n", pre);
 405#ifdef CONFIG_DM_USB
 406        struct udevice *child;
 407
 408        for (device_find_first_child(dev->dev, &child);
 409             child;
 410             device_find_next_child(&child)) {
 411                struct usb_device *udev;
 412
 413                if (!device_active(child))
 414                        continue;
 415
 416                udev = dev_get_parent_priv(child);
 417
 418                /*
 419                 * Ignore emulators and block child devices, we only want
 420                 * real devices
 421                 */
 422                if ((device_get_uclass_id(child) != UCLASS_USB_EMUL) &&
 423                    (device_get_uclass_id(child) != UCLASS_BLK)) {
 424                        usb_show_tree_graph(udev, pre);
 425                        pre[index] = 0;
 426                }
 427        }
 428#else
 429        if (dev->maxchild > 0) {
 430                for (i = 0; i < dev->maxchild; i++) {
 431                        if (dev->children[i] != NULL) {
 432                                usb_show_tree_graph(dev->children[i], pre);
 433                                pre[index] = 0;
 434                        }
 435                }
 436        }
 437#endif
 438}
 439
 440/* main routine for the tree command */
 441static void usb_show_subtree(struct usb_device *dev)
 442{
 443        char preamble[32];
 444
 445        memset(preamble, '\0', sizeof(preamble));
 446        usb_show_tree_graph(dev, &preamble[0]);
 447}
 448
 449#ifdef CONFIG_DM_USB
 450typedef void (*usb_dev_func_t)(struct usb_device *udev);
 451
 452static void usb_for_each_root_dev(usb_dev_func_t func)
 453{
 454        struct udevice *bus;
 455
 456        for (uclass_find_first_device(UCLASS_USB, &bus);
 457                bus;
 458                uclass_find_next_device(&bus)) {
 459                struct usb_device *udev;
 460                struct udevice *dev;
 461
 462                if (!device_active(bus))
 463                        continue;
 464
 465                device_find_first_child(bus, &dev);
 466                if (dev && device_active(dev)) {
 467                        udev = dev_get_parent_priv(dev);
 468                        func(udev);
 469                }
 470        }
 471}
 472#endif
 473
 474void usb_show_tree(void)
 475{
 476#ifdef CONFIG_DM_USB
 477        usb_for_each_root_dev(usb_show_subtree);
 478#else
 479        struct usb_device *udev;
 480        int i;
 481
 482        for (i = 0; i < USB_MAX_DEVICE; i++) {
 483                udev = usb_get_dev_index(i);
 484                if (udev == NULL)
 485                        break;
 486                if (udev->parent == NULL)
 487                        usb_show_subtree(udev);
 488        }
 489#endif
 490}
 491
 492static int usb_test(struct usb_device *dev, int port, char* arg)
 493{
 494        int mode;
 495
 496        if (port > dev->maxchild) {
 497                printf("Device is no hub or does not have %d ports.\n", port);
 498                return 1;
 499        }
 500
 501        switch (arg[0]) {
 502        case 'J':
 503        case 'j':
 504                printf("Setting Test_J mode");
 505                mode = USB_TEST_MODE_J;
 506                break;
 507        case 'K':
 508        case 'k':
 509                printf("Setting Test_K mode");
 510                mode = USB_TEST_MODE_K;
 511                break;
 512        case 'S':
 513        case 's':
 514                printf("Setting Test_SE0_NAK mode");
 515                mode = USB_TEST_MODE_SE0_NAK;
 516                break;
 517        case 'P':
 518        case 'p':
 519                printf("Setting Test_Packet mode");
 520                mode = USB_TEST_MODE_PACKET;
 521                break;
 522        case 'F':
 523        case 'f':
 524                printf("Setting Test_Force_Enable mode");
 525                mode = USB_TEST_MODE_FORCE_ENABLE;
 526                break;
 527        default:
 528                printf("Unrecognized test mode: %s\nAvailable modes: "
 529                       "J, K, S[E0_NAK], P[acket], F[orce_Enable]\n", arg);
 530                return 1;
 531        }
 532
 533        if (port)
 534                printf(" on downstream facing port %d...\n", port);
 535        else
 536                printf(" on upstream facing port...\n");
 537
 538        if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_FEATURE,
 539                            port ? USB_RT_PORT : USB_RECIP_DEVICE,
 540                            port ? USB_PORT_FEAT_TEST : USB_FEAT_TEST,
 541                            (mode << 8) | port,
 542                            NULL, 0, USB_CNTL_TIMEOUT) == -1) {
 543                printf("Error during SET_FEATURE.\n");
 544                return 1;
 545        } else {
 546                printf("Test mode successfully set. Use 'usb start' "
 547                       "to return to normal operation.\n");
 548                return 0;
 549        }
 550}
 551
 552
 553/******************************************************************************
 554 * usb boot command intepreter. Derived from diskboot
 555 */
 556#ifdef CONFIG_USB_STORAGE
 557static int do_usbboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 558{
 559        return common_diskboot(cmdtp, "usb", argc, argv);
 560}
 561#endif /* CONFIG_USB_STORAGE */
 562
 563static int do_usb_stop_keyboard(int force)
 564{
 565#if !defined CONFIG_DM_USB && defined CONFIG_USB_KEYBOARD
 566        if (usb_kbd_deregister(force) != 0) {
 567                printf("USB not stopped: usbkbd still using USB\n");
 568                return 1;
 569        }
 570#endif
 571        return 0;
 572}
 573
 574static void do_usb_start(void)
 575{
 576        bootstage_mark_name(BOOTSTAGE_ID_USB_START, "usb_start");
 577
 578        if (usb_init() < 0)
 579                return;
 580
 581        /* Driver model will probe the devices as they are found */
 582# ifdef CONFIG_USB_STORAGE
 583        /* try to recognize storage devices immediately */
 584        usb_stor_curr_dev = usb_stor_scan(1);
 585# endif
 586#ifndef CONFIG_DM_USB
 587# ifdef CONFIG_USB_KEYBOARD
 588        drv_usb_kbd_init();
 589# endif
 590#endif /* !CONFIG_DM_USB */
 591#ifdef CONFIG_USB_HOST_ETHER
 592# ifdef CONFIG_DM_ETH
 593#  ifndef CONFIG_DM_USB
 594#   error "You must use CONFIG_DM_USB if you want to use CONFIG_USB_HOST_ETHER with CONFIG_DM_ETH"
 595#  endif
 596# else
 597        /* try to recognize ethernet devices immediately */
 598        usb_ether_curr_dev = usb_host_eth_scan(1);
 599# endif
 600#endif
 601}
 602
 603#ifdef CONFIG_DM_USB
 604static void usb_show_info(struct usb_device *udev)
 605{
 606        struct udevice *child;
 607
 608        usb_display_desc(udev);
 609        usb_display_config(udev);
 610        for (device_find_first_child(udev->dev, &child);
 611             child;
 612             device_find_next_child(&child)) {
 613                if (device_active(child) &&
 614                    (device_get_uclass_id(child) != UCLASS_USB_EMUL) &&
 615                    (device_get_uclass_id(child) != UCLASS_BLK)) {
 616                        udev = dev_get_parent_priv(child);
 617                        usb_show_info(udev);
 618                }
 619        }
 620}
 621#endif
 622
 623/******************************************************************************
 624 * usb command intepreter
 625 */
 626static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 627{
 628        struct usb_device *udev = NULL;
 629        int i;
 630        extern char usb_started;
 631
 632        if (argc < 2)
 633                return CMD_RET_USAGE;
 634
 635        if (strncmp(argv[1], "start", 5) == 0) {
 636                if (usb_started)
 637                        return 0; /* Already started */
 638                printf("starting USB...\n");
 639                do_usb_start();
 640                return 0;
 641        }
 642
 643        if (strncmp(argv[1], "reset", 5) == 0) {
 644                printf("resetting USB...\n");
 645                if (do_usb_stop_keyboard(1) != 0)
 646                        return 1;
 647                usb_stop();
 648                do_usb_start();
 649                return 0;
 650        }
 651        if (strncmp(argv[1], "stop", 4) == 0) {
 652                if (argc != 2)
 653                        console_assign(stdin, "serial");
 654                if (do_usb_stop_keyboard(0) != 0)
 655                        return 1;
 656                printf("stopping USB..\n");
 657                usb_stop();
 658                return 0;
 659        }
 660        if (!usb_started) {
 661                printf("USB is stopped. Please issue 'usb start' first.\n");
 662                return 1;
 663        }
 664        if (strncmp(argv[1], "tree", 4) == 0) {
 665                puts("USB device tree:\n");
 666                usb_show_tree();
 667                return 0;
 668        }
 669        if (strncmp(argv[1], "inf", 3) == 0) {
 670                if (argc == 2) {
 671#ifdef CONFIG_DM_USB
 672                        usb_for_each_root_dev(usb_show_info);
 673#else
 674                        int d;
 675                        for (d = 0; d < USB_MAX_DEVICE; d++) {
 676                                udev = usb_get_dev_index(d);
 677                                if (udev == NULL)
 678                                        break;
 679                                usb_display_desc(udev);
 680                                usb_display_config(udev);
 681                        }
 682#endif
 683                        return 0;
 684                } else {
 685                        /*
 686                         * With driver model this isn't right since we can
 687                         * have multiple controllers and the device numbering
 688                         * starts at 1 on each bus.
 689                         */
 690                        i = simple_strtoul(argv[2], NULL, 10);
 691                        printf("config for device %d\n", i);
 692                        udev = usb_find_device(i);
 693                        if (udev == NULL) {
 694                                printf("*** No device available ***\n");
 695                                return 0;
 696                        } else {
 697                                usb_display_desc(udev);
 698                                usb_display_config(udev);
 699                        }
 700                }
 701                return 0;
 702        }
 703        if (strncmp(argv[1], "test", 4) == 0) {
 704                if (argc < 5)
 705                        return CMD_RET_USAGE;
 706                i = simple_strtoul(argv[2], NULL, 10);
 707                udev = usb_find_device(i);
 708                if (udev == NULL) {
 709                        printf("Device %d does not exist.\n", i);
 710                        return 1;
 711                }
 712                i = simple_strtoul(argv[3], NULL, 10);
 713                return usb_test(udev, i, argv[4]);
 714        }
 715#ifdef CONFIG_USB_STORAGE
 716        if (strncmp(argv[1], "stor", 4) == 0)
 717                return usb_stor_info();
 718
 719        return blk_common_cmd(argc, argv, IF_TYPE_USB, &usb_stor_curr_dev);
 720#else
 721        return CMD_RET_USAGE;
 722#endif /* CONFIG_USB_STORAGE */
 723}
 724
 725U_BOOT_CMD(
 726        usb,    5,      1,      do_usb,
 727        "USB sub-system",
 728        "start - start (scan) USB controller\n"
 729        "usb reset - reset (rescan) USB controller\n"
 730        "usb stop [f] - stop USB [f]=force stop\n"
 731        "usb tree - show USB device tree\n"
 732        "usb info [dev] - show available USB devices\n"
 733        "usb test [dev] [port] [mode] - set USB 2.0 test mode\n"
 734        "    (specify port 0 to indicate the device's upstream port)\n"
 735        "    Available modes: J, K, S[E0_NAK], P[acket], F[orce_Enable]\n"
 736#ifdef CONFIG_USB_STORAGE
 737        "usb storage - show details of USB storage devices\n"
 738        "usb dev [dev] - show or set current USB storage device\n"
 739        "usb part [dev] - print partition table of one or all USB storage"
 740        "    devices\n"
 741        "usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"
 742        "    to memory address `addr'\n"
 743        "usb write addr blk# cnt - write `cnt' blocks starting at block `blk#'\n"
 744        "    from memory address `addr'"
 745#endif /* CONFIG_USB_STORAGE */
 746);
 747
 748
 749#ifdef CONFIG_USB_STORAGE
 750U_BOOT_CMD(
 751        usbboot,        3,      1,      do_usbboot,
 752        "boot from USB device",
 753        "loadAddr dev:part"
 754);
 755#endif /* CONFIG_USB_STORAGE */
 756