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