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 char *portspeed(int speed)
 320{
 321        char *speed_str;
 322
 323        switch (speed) {
 324        case USB_SPEED_SUPER:
 325                speed_str = "5 Gb/s";
 326                break;
 327        case USB_SPEED_HIGH:
 328                speed_str = "480 Mb/s";
 329                break;
 330        case USB_SPEED_LOW:
 331                speed_str = "1.5 Mb/s";
 332                break;
 333        default:
 334                speed_str = "12 Mb/s";
 335                break;
 336        }
 337
 338        return speed_str;
 339}
 340
 341/* shows the device tree recursively */
 342static void usb_show_tree_graph(struct usb_device *dev, char *pre)
 343{
 344        int index;
 345        int has_child, last_child;
 346
 347        index = strlen(pre);
 348        printf(" %s", pre);
 349#ifdef CONFIG_DM_USB
 350        has_child = device_has_active_children(dev->dev);
 351        if (device_get_uclass_id(dev->dev) == UCLASS_MASS_STORAGE) {
 352                struct udevice *child;
 353
 354                for (device_find_first_child(dev->dev, &child);
 355                     child;
 356                     device_find_next_child(&child)) {
 357                        if (device_get_uclass_id(child) == UCLASS_BLK)
 358                                has_child = 0;
 359                }
 360        }
 361#else
 362        /* check if the device has connected children */
 363        int i;
 364
 365        has_child = 0;
 366        for (i = 0; i < dev->maxchild; i++) {
 367                if (dev->children[i] != NULL)
 368                        has_child = 1;
 369        }
 370#endif
 371        /* check if we are the last one */
 372#ifdef CONFIG_DM_USB
 373        /* Not the root of the usb tree? */
 374        if (device_get_uclass_id(dev->dev->parent) != UCLASS_USB) {
 375                last_child = device_is_last_sibling(dev->dev);
 376#else
 377        if (dev->parent != NULL) { /* not root? */
 378                last_child = 1;
 379                for (i = 0; i < dev->parent->maxchild; i++) {
 380                        /* search for children */
 381                        if (dev->parent->children[i] == dev) {
 382                                /* found our pointer, see if we have a
 383                                 * little sister
 384                                 */
 385                                while (i++ < dev->parent->maxchild) {
 386                                        if (dev->parent->children[i] != NULL) {
 387                                                /* found a sister */
 388                                                last_child = 0;
 389                                                break;
 390                                        } /* if */
 391                                } /* while */
 392                        } /* device found */
 393                } /* for all children of the parent */
 394#endif
 395                printf("\b+-");
 396                /* correct last child */
 397                if (last_child && index)
 398                        pre[index-1] = ' ';
 399        } /* if not root hub */
 400        else
 401                printf(" ");
 402        printf("%d ", dev->devnum);
 403        pre[index++] = ' ';
 404        pre[index++] = has_child ? '|' : ' ';
 405        pre[index] = 0;
 406        printf(" %s (%s, %dmA)\n", usb_get_class_desc(
 407                                        dev->config.if_desc[0].desc.bInterfaceClass),
 408                                        portspeed(dev->speed),
 409                                        dev->config.desc.bMaxPower * 2);
 410        if (strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial))
 411                printf(" %s  %s %s %s\n", pre, dev->mf, dev->prod, dev->serial);
 412        printf(" %s\n", pre);
 413#ifdef CONFIG_DM_USB
 414        struct udevice *child;
 415
 416        for (device_find_first_child(dev->dev, &child);
 417             child;
 418             device_find_next_child(&child)) {
 419                struct usb_device *udev;
 420
 421                if (!device_active(child))
 422                        continue;
 423
 424                udev = dev_get_parent_priv(child);
 425
 426                /*
 427                 * Ignore emulators and block child devices, we only want
 428                 * real devices
 429                 */
 430                if ((device_get_uclass_id(child) != UCLASS_USB_EMUL) &&
 431                    (device_get_uclass_id(child) != UCLASS_BLK)) {
 432                        usb_show_tree_graph(udev, pre);
 433                        pre[index] = 0;
 434                }
 435        }
 436#else
 437        if (dev->maxchild > 0) {
 438                for (i = 0; i < dev->maxchild; i++) {
 439                        if (dev->children[i] != NULL) {
 440                                usb_show_tree_graph(dev->children[i], pre);
 441                                pre[index] = 0;
 442                        }
 443                }
 444        }
 445#endif
 446}
 447
 448/* main routine for the tree command */
 449static void usb_show_subtree(struct usb_device *dev)
 450{
 451        char preamble[32];
 452
 453        memset(preamble, '\0', sizeof(preamble));
 454        usb_show_tree_graph(dev, &preamble[0]);
 455}
 456
 457#ifdef CONFIG_DM_USB
 458typedef void (*usb_dev_func_t)(struct usb_device *udev);
 459
 460static void usb_for_each_root_dev(usb_dev_func_t func)
 461{
 462        struct udevice *bus;
 463
 464        for (uclass_find_first_device(UCLASS_USB, &bus);
 465                bus;
 466                uclass_find_next_device(&bus)) {
 467                struct usb_device *udev;
 468                struct udevice *dev;
 469
 470                if (!device_active(bus))
 471                        continue;
 472
 473                device_find_first_child(bus, &dev);
 474                if (dev && device_active(dev)) {
 475                        udev = dev_get_parent_priv(dev);
 476                        func(udev);
 477                }
 478        }
 479}
 480#endif
 481
 482void usb_show_tree(void)
 483{
 484#ifdef CONFIG_DM_USB
 485        usb_for_each_root_dev(usb_show_subtree);
 486#else
 487        struct usb_device *udev;
 488        int i;
 489
 490        for (i = 0; i < USB_MAX_DEVICE; i++) {
 491                udev = usb_get_dev_index(i);
 492                if (udev == NULL)
 493                        break;
 494                if (udev->parent == NULL)
 495                        usb_show_subtree(udev);
 496        }
 497#endif
 498}
 499
 500static int usb_test(struct usb_device *dev, int port, char* arg)
 501{
 502        int mode;
 503
 504        if (port > dev->maxchild) {
 505                printf("Device is no hub or does not have %d ports.\n", port);
 506                return 1;
 507        }
 508
 509        switch (arg[0]) {
 510        case 'J':
 511        case 'j':
 512                printf("Setting Test_J mode");
 513                mode = USB_TEST_MODE_J;
 514                break;
 515        case 'K':
 516        case 'k':
 517                printf("Setting Test_K mode");
 518                mode = USB_TEST_MODE_K;
 519                break;
 520        case 'S':
 521        case 's':
 522                printf("Setting Test_SE0_NAK mode");
 523                mode = USB_TEST_MODE_SE0_NAK;
 524                break;
 525        case 'P':
 526        case 'p':
 527                printf("Setting Test_Packet mode");
 528                mode = USB_TEST_MODE_PACKET;
 529                break;
 530        case 'F':
 531        case 'f':
 532                printf("Setting Test_Force_Enable mode");
 533                mode = USB_TEST_MODE_FORCE_ENABLE;
 534                break;
 535        default:
 536                printf("Unrecognized test mode: %s\nAvailable modes: "
 537                       "J, K, S[E0_NAK], P[acket], F[orce_Enable]\n", arg);
 538                return 1;
 539        }
 540
 541        if (port)
 542                printf(" on downstream facing port %d...\n", port);
 543        else
 544                printf(" on upstream facing port...\n");
 545
 546        if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_FEATURE,
 547                            port ? USB_RT_PORT : USB_RECIP_DEVICE,
 548                            port ? USB_PORT_FEAT_TEST : USB_FEAT_TEST,
 549                            (mode << 8) | port,
 550                            NULL, 0, USB_CNTL_TIMEOUT) == -1) {
 551                printf("Error during SET_FEATURE.\n");
 552                return 1;
 553        } else {
 554                printf("Test mode successfully set. Use 'usb start' "
 555                       "to return to normal operation.\n");
 556                return 0;
 557        }
 558}
 559
 560
 561/******************************************************************************
 562 * usb boot command intepreter. Derived from diskboot
 563 */
 564#ifdef CONFIG_USB_STORAGE
 565static int do_usbboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 566{
 567        return common_diskboot(cmdtp, "usb", argc, argv);
 568}
 569#endif /* CONFIG_USB_STORAGE */
 570
 571static int do_usb_stop_keyboard(int force)
 572{
 573#if !defined CONFIG_DM_USB && defined CONFIG_USB_KEYBOARD
 574        if (usb_kbd_deregister(force) != 0) {
 575                printf("USB not stopped: usbkbd still using USB\n");
 576                return 1;
 577        }
 578#endif
 579        return 0;
 580}
 581
 582static void do_usb_start(void)
 583{
 584        bootstage_mark_name(BOOTSTAGE_ID_USB_START, "usb_start");
 585
 586        if (usb_init() < 0)
 587                return;
 588
 589        /* Driver model will probe the devices as they are found */
 590# ifdef CONFIG_USB_STORAGE
 591        /* try to recognize storage devices immediately */
 592        usb_stor_curr_dev = usb_stor_scan(1);
 593# endif
 594#ifndef CONFIG_DM_USB
 595# ifdef CONFIG_USB_KEYBOARD
 596        drv_usb_kbd_init();
 597# endif
 598#endif /* !CONFIG_DM_USB */
 599#ifdef CONFIG_USB_HOST_ETHER
 600# ifdef CONFIG_DM_ETH
 601#  ifndef CONFIG_DM_USB
 602#   error "You must use CONFIG_DM_USB if you want to use CONFIG_USB_HOST_ETHER with CONFIG_DM_ETH"
 603#  endif
 604# else
 605        /* try to recognize ethernet devices immediately */
 606        usb_ether_curr_dev = usb_host_eth_scan(1);
 607# endif
 608#endif
 609}
 610
 611#ifdef CONFIG_DM_USB
 612static void usb_show_info(struct usb_device *udev)
 613{
 614        struct udevice *child;
 615
 616        usb_display_desc(udev);
 617        usb_display_config(udev);
 618        for (device_find_first_child(udev->dev, &child);
 619             child;
 620             device_find_next_child(&child)) {
 621                if (device_active(child) &&
 622                    (device_get_uclass_id(child) != UCLASS_USB_EMUL) &&
 623                    (device_get_uclass_id(child) != UCLASS_BLK)) {
 624                        udev = dev_get_parent_priv(child);
 625                        usb_show_info(udev);
 626                }
 627        }
 628}
 629#endif
 630
 631/******************************************************************************
 632 * usb command intepreter
 633 */
 634static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 635{
 636        struct usb_device *udev = NULL;
 637        int i;
 638        extern char usb_started;
 639
 640        if (argc < 2)
 641                return CMD_RET_USAGE;
 642
 643        if (strncmp(argv[1], "start", 5) == 0) {
 644                if (usb_started)
 645                        return 0; /* Already started */
 646                printf("starting USB...\n");
 647                do_usb_start();
 648                return 0;
 649        }
 650
 651        if (strncmp(argv[1], "reset", 5) == 0) {
 652                printf("resetting USB...\n");
 653                if (do_usb_stop_keyboard(1) != 0)
 654                        return 1;
 655                usb_stop();
 656                do_usb_start();
 657                return 0;
 658        }
 659        if (strncmp(argv[1], "stop", 4) == 0) {
 660                if (argc != 2)
 661                        console_assign(stdin, "serial");
 662                if (do_usb_stop_keyboard(0) != 0)
 663                        return 1;
 664                printf("stopping USB..\n");
 665                usb_stop();
 666                return 0;
 667        }
 668        if (!usb_started) {
 669                printf("USB is stopped. Please issue 'usb start' first.\n");
 670                return 1;
 671        }
 672        if (strncmp(argv[1], "tree", 4) == 0) {
 673                puts("USB device tree:\n");
 674                usb_show_tree();
 675                return 0;
 676        }
 677        if (strncmp(argv[1], "inf", 3) == 0) {
 678                if (argc == 2) {
 679#ifdef CONFIG_DM_USB
 680                        usb_for_each_root_dev(usb_show_info);
 681#else
 682                        int d;
 683                        for (d = 0; d < USB_MAX_DEVICE; d++) {
 684                                udev = usb_get_dev_index(d);
 685                                if (udev == NULL)
 686                                        break;
 687                                usb_display_desc(udev);
 688                                usb_display_config(udev);
 689                        }
 690#endif
 691                        return 0;
 692                } else {
 693                        /*
 694                         * With driver model this isn't right since we can
 695                         * have multiple controllers and the device numbering
 696                         * starts at 1 on each bus.
 697                         */
 698                        i = simple_strtoul(argv[2], NULL, 10);
 699                        printf("config for device %d\n", i);
 700                        udev = usb_find_device(i);
 701                        if (udev == NULL) {
 702                                printf("*** No device available ***\n");
 703                                return 0;
 704                        } else {
 705                                usb_display_desc(udev);
 706                                usb_display_config(udev);
 707                        }
 708                }
 709                return 0;
 710        }
 711        if (strncmp(argv[1], "test", 4) == 0) {
 712                if (argc < 5)
 713                        return CMD_RET_USAGE;
 714                i = simple_strtoul(argv[2], NULL, 10);
 715                udev = usb_find_device(i);
 716                if (udev == NULL) {
 717                        printf("Device %d does not exist.\n", i);
 718                        return 1;
 719                }
 720                i = simple_strtoul(argv[3], NULL, 10);
 721                return usb_test(udev, i, argv[4]);
 722        }
 723#ifdef CONFIG_USB_STORAGE
 724        if (strncmp(argv[1], "stor", 4) == 0)
 725                return usb_stor_info();
 726
 727        return blk_common_cmd(argc, argv, IF_TYPE_USB, &usb_stor_curr_dev);
 728#else
 729        return CMD_RET_USAGE;
 730#endif /* CONFIG_USB_STORAGE */
 731}
 732
 733U_BOOT_CMD(
 734        usb,    5,      1,      do_usb,
 735        "USB sub-system",
 736        "start - start (scan) USB controller\n"
 737        "usb reset - reset (rescan) USB controller\n"
 738        "usb stop [f] - stop USB [f]=force stop\n"
 739        "usb tree - show USB device tree\n"
 740        "usb info [dev] - show available USB devices\n"
 741        "usb test [dev] [port] [mode] - set USB 2.0 test mode\n"
 742        "    (specify port 0 to indicate the device's upstream port)\n"
 743        "    Available modes: J, K, S[E0_NAK], P[acket], F[orce_Enable]\n"
 744#ifdef CONFIG_USB_STORAGE
 745        "usb storage - show details of USB storage devices\n"
 746        "usb dev [dev] - show or set current USB storage device\n"
 747        "usb part [dev] - print partition table of one or all USB storage"
 748        "    devices\n"
 749        "usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"
 750        "    to memory address `addr'\n"
 751        "usb write addr blk# cnt - write `cnt' blocks starting at block `blk#'\n"
 752        "    from memory address `addr'"
 753#endif /* CONFIG_USB_STORAGE */
 754);
 755
 756
 757#ifdef CONFIG_USB_STORAGE
 758U_BOOT_CMD(
 759        usbboot,        3,      1,      do_usbboot,
 760        "boot from USB device",
 761        "loadAddr dev:part"
 762);
 763#endif /* CONFIG_USB_STORAGE */
 764