uboot/common/cmd_usb.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2001
   3 * Denis Peter, MPL AG Switzerland
   4 *
   5 * Most of this source has been derived from the Linux USB
   6 * project.
   7 *
   8 * See file CREDITS for list of people who contributed to this
   9 * project.
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License as
  13 * published by the Free Software Foundation; either version 2 of
  14 * the License, or (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  24 * MA 02111-1307 USA
  25 *
  26 */
  27
  28#include <common.h>
  29#include <command.h>
  30#include <asm/byteorder.h>
  31#include <part.h>
  32#include <usb.h>
  33
  34#ifdef CONFIG_USB_STORAGE
  35static int usb_stor_curr_dev = -1; /* current device */
  36#endif
  37
  38/* some display routines (info command) */
  39char *usb_get_class_desc(unsigned char dclass)
  40{
  41        switch (dclass) {
  42        case USB_CLASS_PER_INTERFACE:
  43                return "See Interface";
  44        case USB_CLASS_AUDIO:
  45                return "Audio";
  46        case USB_CLASS_COMM:
  47                return "Communication";
  48        case USB_CLASS_HID:
  49                return "Human Interface";
  50        case USB_CLASS_PRINTER:
  51                return "Printer";
  52        case USB_CLASS_MASS_STORAGE:
  53                return "Mass Storage";
  54        case USB_CLASS_HUB:
  55                return "Hub";
  56        case USB_CLASS_DATA:
  57                return "CDC Data";
  58        case USB_CLASS_VENDOR_SPEC:
  59                return "Vendor specific";
  60        default:
  61                return "";
  62        }
  63}
  64
  65void usb_display_class_sub(unsigned char dclass, unsigned char subclass,
  66                           unsigned char proto)
  67{
  68        switch (dclass) {
  69        case USB_CLASS_PER_INTERFACE:
  70                printf("See Interface");
  71                break;
  72        case USB_CLASS_HID:
  73                printf("Human Interface, Subclass: ");
  74                switch (subclass) {
  75                case USB_SUB_HID_NONE:
  76                        printf("None");
  77                        break;
  78                case USB_SUB_HID_BOOT:
  79                        printf("Boot ");
  80                        switch (proto) {
  81                        case USB_PROT_HID_NONE:
  82                                printf("None");
  83                                break;
  84                        case USB_PROT_HID_KEYBOARD:
  85                                printf("Keyboard");
  86                                break;
  87                        case USB_PROT_HID_MOUSE:
  88                                printf("Mouse");
  89                                break;
  90                        default:
  91                                printf("reserved");
  92                                break;
  93                        }
  94                        break;
  95                default:
  96                        printf("reserved");
  97                        break;
  98                }
  99                break;
 100        case USB_CLASS_MASS_STORAGE:
 101                printf("Mass Storage, ");
 102                switch (subclass) {
 103                case US_SC_RBC:
 104                        printf("RBC ");
 105                        break;
 106                case US_SC_8020:
 107                        printf("SFF-8020i (ATAPI)");
 108                        break;
 109                case US_SC_QIC:
 110                        printf("QIC-157 (Tape)");
 111                        break;
 112                case US_SC_UFI:
 113                        printf("UFI");
 114                        break;
 115                case US_SC_8070:
 116                        printf("SFF-8070");
 117                        break;
 118                case US_SC_SCSI:
 119                        printf("Transp. SCSI");
 120                        break;
 121                default:
 122                        printf("reserved");
 123                        break;
 124                }
 125                printf(", ");
 126                switch (proto) {
 127                case US_PR_CB:
 128                        printf("Command/Bulk");
 129                        break;
 130                case US_PR_CBI:
 131                        printf("Command/Bulk/Int");
 132                        break;
 133                case US_PR_BULK:
 134                        printf("Bulk only");
 135                        break;
 136                default:
 137                        printf("reserved");
 138                        break;
 139                }
 140                break;
 141        default:
 142                printf("%s", usb_get_class_desc(dclass));
 143                break;
 144        }
 145}
 146
 147void usb_display_string(struct usb_device *dev, int index)
 148{
 149        char buffer[256];
 150        if (index != 0) {
 151                if (usb_string(dev, index, &buffer[0], 256) > 0)
 152                        printf("String: \"%s\"", buffer);
 153        }
 154}
 155
 156void usb_display_desc(struct usb_device *dev)
 157{
 158        if (dev->descriptor.bDescriptorType == USB_DT_DEVICE) {
 159                printf("%d: %s,  USB Revision %x.%x\n", dev->devnum,
 160                usb_get_class_desc(dev->config.if_desc[0].bInterfaceClass),
 161                                   (dev->descriptor.bcdUSB>>8) & 0xff,
 162                                   dev->descriptor.bcdUSB & 0xff);
 163
 164                if (strlen(dev->mf) || strlen(dev->prod) ||
 165                    strlen(dev->serial))
 166                        printf(" - %s %s %s\n", dev->mf, dev->prod,
 167                                dev->serial);
 168                if (dev->descriptor.bDeviceClass) {
 169                        printf(" - Class: ");
 170                        usb_display_class_sub(dev->descriptor.bDeviceClass,
 171                                              dev->descriptor.bDeviceSubClass,
 172                                              dev->descriptor.bDeviceProtocol);
 173                        printf("\n");
 174                } else {
 175                        printf(" - Class: (from Interface) %s\n",
 176                               usb_get_class_desc(
 177                                dev->config.if_desc[0].bInterfaceClass));
 178                }
 179                printf(" - PacketSize: %d  Configurations: %d\n",
 180                        dev->descriptor.bMaxPacketSize0,
 181                        dev->descriptor.bNumConfigurations);
 182                printf(" - Vendor: 0x%04x  Product 0x%04x Version %d.%d\n",
 183                        dev->descriptor.idVendor, dev->descriptor.idProduct,
 184                        (dev->descriptor.bcdDevice>>8) & 0xff,
 185                        dev->descriptor.bcdDevice & 0xff);
 186        }
 187
 188}
 189
 190void usb_display_conf_desc(struct usb_config_descriptor *config,
 191                           struct usb_device *dev)
 192{
 193        printf("   Configuration: %d\n", config->bConfigurationValue);
 194        printf("   - Interfaces: %d %s%s%dmA\n", config->bNumInterfaces,
 195               (config->bmAttributes & 0x40) ? "Self Powered " : "Bus Powered ",
 196               (config->bmAttributes & 0x20) ? "Remote Wakeup " : "",
 197                config->MaxPower*2);
 198        if (config->iConfiguration) {
 199                printf("   - ");
 200                usb_display_string(dev, config->iConfiguration);
 201                printf("\n");
 202        }
 203}
 204
 205void usb_display_if_desc(struct usb_interface_descriptor *ifdesc,
 206                         struct usb_device *dev)
 207{
 208        printf("     Interface: %d\n", ifdesc->bInterfaceNumber);
 209        printf("     - Alternate Setting %d, Endpoints: %d\n",
 210                ifdesc->bAlternateSetting, ifdesc->bNumEndpoints);
 211        printf("     - Class ");
 212        usb_display_class_sub(ifdesc->bInterfaceClass,
 213                ifdesc->bInterfaceSubClass, ifdesc->bInterfaceProtocol);
 214        printf("\n");
 215        if (ifdesc->iInterface) {
 216                printf("     - ");
 217                usb_display_string(dev, ifdesc->iInterface);
 218                printf("\n");
 219        }
 220}
 221
 222void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc)
 223{
 224        printf("     - Endpoint %d %s ", epdesc->bEndpointAddress & 0xf,
 225                (epdesc->bEndpointAddress & 0x80) ? "In" : "Out");
 226        switch ((epdesc->bmAttributes & 0x03)) {
 227        case 0:
 228                printf("Control");
 229                break;
 230        case 1:
 231                printf("Isochronous");
 232                break;
 233        case 2:
 234                printf("Bulk");
 235                break;
 236        case 3:
 237                printf("Interrupt");
 238                break;
 239        }
 240        printf(" MaxPacket %d", epdesc->wMaxPacketSize);
 241        if ((epdesc->bmAttributes & 0x03) == 0x3)
 242                printf(" Interval %dms", epdesc->bInterval);
 243        printf("\n");
 244}
 245
 246/* main routine to diasplay the configs, interfaces and endpoints */
 247void usb_display_config(struct usb_device *dev)
 248{
 249        struct usb_config_descriptor *config;
 250        struct usb_interface_descriptor *ifdesc;
 251        struct usb_endpoint_descriptor *epdesc;
 252        int i, ii;
 253
 254        config = &dev->config;
 255        usb_display_conf_desc(config, dev);
 256        for (i = 0; i < config->no_of_if; i++) {
 257                ifdesc = &config->if_desc[i];
 258                usb_display_if_desc(ifdesc, dev);
 259                for (ii = 0; ii < ifdesc->no_of_ep; ii++) {
 260                        epdesc = &ifdesc->ep_desc[ii];
 261                        usb_display_ep_desc(epdesc);
 262                }
 263        }
 264        printf("\n");
 265}
 266
 267static inline char *portspeed(int speed)
 268{
 269        if (speed == USB_SPEED_HIGH)
 270                return "480 Mb/s";
 271        else if (speed == USB_SPEED_LOW)
 272                return "1.5 Mb/s";
 273        else
 274                return "12 Mb/s";
 275}
 276
 277/* shows the device tree recursively */
 278void usb_show_tree_graph(struct usb_device *dev, char *pre)
 279{
 280        int i, index;
 281        int has_child, last_child, port;
 282
 283        index = strlen(pre);
 284        printf(" %s", pre);
 285        /* check if the device has connected children */
 286        has_child = 0;
 287        for (i = 0; i < dev->maxchild; i++) {
 288                if (dev->children[i] != NULL)
 289                        has_child = 1;
 290        }
 291        /* check if we are the last one */
 292        last_child = 1;
 293        if (dev->parent != NULL) {
 294                for (i = 0; i < dev->parent->maxchild; i++) {
 295                        /* search for children */
 296                        if (dev->parent->children[i] == dev) {
 297                                /* found our pointer, see if we have a
 298                                 * little sister
 299                                 */
 300                                port = i;
 301                                while (i++ < dev->parent->maxchild) {
 302                                        if (dev->parent->children[i] != NULL) {
 303                                                /* found a sister */
 304                                                last_child = 0;
 305                                                break;
 306                                        } /* if */
 307                                } /* while */
 308                        } /* device found */
 309                } /* for all children of the parent */
 310                printf("\b+-");
 311                /* correct last child */
 312                if (last_child)
 313                        pre[index-1] = ' ';
 314        } /* if not root hub */
 315        else
 316                printf(" ");
 317        printf("%d ", dev->devnum);
 318        pre[index++] = ' ';
 319        pre[index++] = has_child ? '|' : ' ';
 320        pre[index] = 0;
 321        printf(" %s (%s, %dmA)\n", usb_get_class_desc(
 322                                        dev->config.if_desc[0].bInterfaceClass),
 323                                        portspeed(dev->speed),
 324                                        dev->config.MaxPower * 2);
 325        if (strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial))
 326                printf(" %s  %s %s %s\n", pre, dev->mf, dev->prod, dev->serial);
 327        printf(" %s\n", pre);
 328        if (dev->maxchild > 0) {
 329                for (i = 0; i < dev->maxchild; i++) {
 330                        if (dev->children[i] != NULL) {
 331                                usb_show_tree_graph(dev->children[i], pre);
 332                                pre[index] = 0;
 333                        }
 334                }
 335        }
 336}
 337
 338/* main routine for the tree command */
 339void usb_show_tree(struct usb_device *dev)
 340{
 341        char preamble[32];
 342
 343        memset(preamble, 0, 32);
 344        usb_show_tree_graph(dev, &preamble[0]);
 345}
 346
 347
 348/******************************************************************************
 349 * usb boot command intepreter. Derived from diskboot
 350 */
 351#ifdef CONFIG_USB_STORAGE
 352int do_usbboot(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 353{
 354        char *boot_device = NULL;
 355        char *ep;
 356        int dev, part = 1, rcode;
 357        ulong addr, cnt;
 358        disk_partition_t info;
 359        image_header_t *hdr;
 360        block_dev_desc_t *stor_dev;
 361#if defined(CONFIG_FIT)
 362        const void *fit_hdr = NULL;
 363#endif
 364
 365        switch (argc) {
 366        case 1:
 367                addr = CONFIG_SYS_LOAD_ADDR;
 368                boot_device = getenv("bootdevice");
 369                break;
 370        case 2:
 371                addr = simple_strtoul(argv[1], NULL, 16);
 372                boot_device = getenv("bootdevice");
 373                break;
 374        case 3:
 375                addr = simple_strtoul(argv[1], NULL, 16);
 376                boot_device = argv[2];
 377                break;
 378        default:
 379                cmd_usage(cmdtp);
 380                return 1;
 381        }
 382
 383        if (!boot_device) {
 384                puts("\n** No boot device **\n");
 385                return 1;
 386        }
 387
 388        dev = simple_strtoul(boot_device, &ep, 16);
 389        stor_dev = usb_stor_get_dev(dev);
 390        if (stor_dev->type == DEV_TYPE_UNKNOWN) {
 391                printf("\n** Device %d not available\n", dev);
 392                return 1;
 393        }
 394        if (stor_dev->block_read == NULL) {
 395                printf("storage device not initialized. Use usb scan\n");
 396                return 1;
 397        }
 398        if (*ep) {
 399                if (*ep != ':') {
 400                        puts("\n** Invalid boot device, use `dev[:part]' **\n");
 401                        return 1;
 402                }
 403                part = simple_strtoul(++ep, NULL, 16);
 404        }
 405
 406        if (get_partition_info(stor_dev, part, &info)) {
 407                /* try to boot raw .... */
 408                strncpy((char *)&info.type[0], BOOT_PART_TYPE,
 409                        sizeof(BOOT_PART_TYPE));
 410                strncpy((char *)&info.name[0], "Raw", 4);
 411                info.start = 0;
 412                info.blksz = 0x200;
 413                info.size = 2880;
 414                printf("error reading partinfo...try to boot raw\n");
 415        }
 416        if ((strncmp((char *)info.type, BOOT_PART_TYPE,
 417            sizeof(info.type)) != 0) &&
 418            (strncmp((char *)info.type, BOOT_PART_COMP,
 419            sizeof(info.type)) != 0)) {
 420                printf("\n** Invalid partition type \"%.32s\""
 421                        " (expect \"" BOOT_PART_TYPE "\")\n",
 422                        info.type);
 423                return 1;
 424        }
 425        printf("\nLoading from USB device %d, partition %d: "
 426                "Name: %.32s  Type: %.32s\n",
 427                dev, part, info.name, info.type);
 428
 429        debug("First Block: %ld,  # of blocks: %ld, Block Size: %ld\n",
 430                info.start, info.size, info.blksz);
 431
 432        if (stor_dev->block_read(dev, info.start, 1, (ulong *)addr) != 1) {
 433                printf("** Read error on %d:%d\n", dev, part);
 434                return 1;
 435        }
 436
 437        switch (genimg_get_format((void *)addr)) {
 438        case IMAGE_FORMAT_LEGACY:
 439                hdr = (image_header_t *)addr;
 440
 441                if (!image_check_hcrc(hdr)) {
 442                        puts("\n** Bad Header Checksum **\n");
 443                        return 1;
 444                }
 445
 446                image_print_contents(hdr);
 447
 448                cnt = image_get_image_size(hdr);
 449                break;
 450#if defined(CONFIG_FIT)
 451        case IMAGE_FORMAT_FIT:
 452                fit_hdr = (const void *)addr;
 453                puts("Fit image detected...\n");
 454
 455                cnt = fit_get_size(fit_hdr);
 456                break;
 457#endif
 458        default:
 459                puts("** Unknown image type\n");
 460                return 1;
 461        }
 462
 463        cnt += info.blksz - 1;
 464        cnt /= info.blksz;
 465        cnt -= 1;
 466
 467        if (stor_dev->block_read(dev, info.start+1, cnt,
 468                      (ulong *)(addr+info.blksz)) != cnt) {
 469                printf("\n** Read error on %d:%d\n", dev, part);
 470                return 1;
 471        }
 472
 473#if defined(CONFIG_FIT)
 474        /* This cannot be done earlier, we need complete FIT image in RAM
 475         * first
 476         */
 477        if (genimg_get_format((void *)addr) == IMAGE_FORMAT_FIT) {
 478                if (!fit_check_format(fit_hdr)) {
 479                        puts("** Bad FIT image format\n");
 480                        return 1;
 481                }
 482                fit_print_contents(fit_hdr);
 483        }
 484#endif
 485
 486        /* Loading ok, update default load address */
 487        load_addr = addr;
 488
 489        flush_cache(addr, (cnt+1)*info.blksz);
 490
 491        /* Check if we should attempt an auto-start */
 492        if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) {
 493                char *local_args[2];
 494                extern int do_bootm(cmd_tbl_t *, int, int, char *[]);
 495                local_args[0] = argv[0];
 496                local_args[1] = NULL;
 497                printf("Automatic boot of image at addr 0x%08lX ...\n", addr);
 498                rcode = do_bootm(cmdtp, 0, 1, local_args);
 499                return rcode;
 500        }
 501        return 0;
 502}
 503#endif /* CONFIG_USB_STORAGE */
 504
 505
 506/******************************************************************************
 507 * usb command intepreter
 508 */
 509int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 510{
 511
 512        int i;
 513        struct usb_device *dev = NULL;
 514        extern char usb_started;
 515#ifdef CONFIG_USB_STORAGE
 516        block_dev_desc_t *stor_dev;
 517#endif
 518
 519        if ((strncmp(argv[1], "reset", 5) == 0) ||
 520                 (strncmp(argv[1], "start", 5) == 0)) {
 521                usb_stop();
 522                printf("(Re)start USB...\n");
 523                i = usb_init();
 524#ifdef CONFIG_USB_STORAGE
 525                /* try to recognize storage devices immediately */
 526                if (i >= 0)
 527                        usb_stor_curr_dev = usb_stor_scan(1);
 528#endif
 529                return 0;
 530        }
 531        if (strncmp(argv[1], "stop", 4) == 0) {
 532#ifdef CONFIG_USB_KEYBOARD
 533                if (argc == 2) {
 534                        if (usb_kbd_deregister() != 0) {
 535                                printf("USB not stopped: usbkbd still"
 536                                        " using USB\n");
 537                                return 1;
 538                        }
 539                } else {
 540                        /* forced stop, switch console in to serial */
 541                        console_assign(stdin, "serial");
 542                        usb_kbd_deregister();
 543                }
 544#endif
 545                printf("stopping USB..\n");
 546                usb_stop();
 547                return 0;
 548        }
 549        if (!usb_started) {
 550                printf("USB is stopped. Please issue 'usb start' first.\n");
 551                return 1;
 552        }
 553        if (strncmp(argv[1], "tree", 4) == 0) {
 554                printf("\nDevice Tree:\n");
 555                usb_show_tree(usb_get_dev_index(0));
 556                return 0;
 557        }
 558        if (strncmp(argv[1], "inf", 3) == 0) {
 559                int d;
 560                if (argc == 2) {
 561                        for (d = 0; d < USB_MAX_DEVICE; d++) {
 562                                dev = usb_get_dev_index(d);
 563                                if (dev == NULL)
 564                                        break;
 565                                usb_display_desc(dev);
 566                                usb_display_config(dev);
 567                        }
 568                        return 0;
 569                } else {
 570                        int d;
 571
 572                        i = simple_strtoul(argv[2], NULL, 16);
 573                        printf("config for device %d\n", i);
 574                        for (d = 0; d < USB_MAX_DEVICE; d++) {
 575                                dev = usb_get_dev_index(d);
 576                                if (dev == NULL)
 577                                        break;
 578                                if (dev->devnum == i)
 579                                        break;
 580                        }
 581                        if (dev == NULL) {
 582                                printf("*** NO Device avaiable ***\n");
 583                                return 0;
 584                        } else {
 585                                usb_display_desc(dev);
 586                                usb_display_config(dev);
 587                        }
 588                }
 589                return 0;
 590        }
 591#ifdef CONFIG_USB_STORAGE
 592        if (strncmp(argv[1], "stor", 4) == 0)
 593                return usb_stor_info();
 594
 595        if (strncmp(argv[1], "part", 4) == 0) {
 596                int devno, ok = 0;
 597                if (argc == 2) {
 598                        for (devno = 0; devno < USB_MAX_STOR_DEV; ++devno) {
 599                                stor_dev = usb_stor_get_dev(devno);
 600                                if (stor_dev->type != DEV_TYPE_UNKNOWN) {
 601                                        ok++;
 602                                        if (devno)
 603                                                printf("\n");
 604                                        printf("print_part of %x\n", devno);
 605                                        print_part(stor_dev);
 606                                }
 607                        }
 608                } else {
 609                        devno = simple_strtoul(argv[2], NULL, 16);
 610                        stor_dev = usb_stor_get_dev(devno);
 611                        if (stor_dev->type != DEV_TYPE_UNKNOWN) {
 612                                ok++;
 613                                printf("print_part of %x\n", devno);
 614                                print_part(stor_dev);
 615                        }
 616                }
 617                if (!ok) {
 618                        printf("\nno USB devices available\n");
 619                        return 1;
 620                }
 621                return 0;
 622        }
 623        if (strcmp(argv[1], "read") == 0) {
 624                if (usb_stor_curr_dev < 0) {
 625                        printf("no current device selected\n");
 626                        return 1;
 627                }
 628                if (argc == 5) {
 629                        unsigned long addr = simple_strtoul(argv[2], NULL, 16);
 630                        unsigned long blk  = simple_strtoul(argv[3], NULL, 16);
 631                        unsigned long cnt  = simple_strtoul(argv[4], NULL, 16);
 632                        unsigned long n;
 633                        printf("\nUSB read: device %d block # %ld, count %ld"
 634                                " ... ", usb_stor_curr_dev, blk, cnt);
 635                        stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
 636                        n = stor_dev->block_read(usb_stor_curr_dev, blk, cnt,
 637                                                 (ulong *)addr);
 638                        printf("%ld blocks read: %s\n", n,
 639                                (n == cnt) ? "OK" : "ERROR");
 640                        if (n == cnt)
 641                                return 0;
 642                        return 1;
 643                }
 644        }
 645        if (strncmp(argv[1], "dev", 3) == 0) {
 646                if (argc == 3) {
 647                        int dev = (int)simple_strtoul(argv[2], NULL, 10);
 648                        printf("\nUSB device %d: ", dev);
 649                        if (dev >= USB_MAX_STOR_DEV) {
 650                                printf("unknown device\n");
 651                                return 1;
 652                        }
 653                        printf("\n    Device %d: ", dev);
 654                        stor_dev = usb_stor_get_dev(dev);
 655                        dev_print(stor_dev);
 656                        if (stor_dev->type == DEV_TYPE_UNKNOWN)
 657                                return 1;
 658                        usb_stor_curr_dev = dev;
 659                        printf("... is now current device\n");
 660                        return 0;
 661                } else {
 662                        printf("\nUSB device %d: ", usb_stor_curr_dev);
 663                        stor_dev = usb_stor_get_dev(usb_stor_curr_dev);
 664                        dev_print(stor_dev);
 665                        if (stor_dev->type == DEV_TYPE_UNKNOWN)
 666                                return 1;
 667                        return 0;
 668                }
 669                return 0;
 670        }
 671#endif /* CONFIG_USB_STORAGE */
 672        cmd_usage(cmdtp);
 673        return 1;
 674}
 675
 676#ifdef CONFIG_USB_STORAGE
 677U_BOOT_CMD(
 678        usb,    5,      1,      do_usb,
 679        "USB sub-system",
 680        "reset - reset (rescan) USB controller\n"
 681        "usb stop [f]  - stop USB [f]=force stop\n"
 682        "usb tree  - show USB device tree\n"
 683        "usb info [dev] - show available USB devices\n"
 684        "usb storage  - show details of USB storage devices\n"
 685        "usb dev [dev] - show or set current USB storage device\n"
 686        "usb part [dev] - print partition table of one or all USB storage"
 687        " devices\n"
 688        "usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"
 689        "    to memory address `addr'\n"
 690);
 691
 692
 693U_BOOT_CMD(
 694        usbboot,        3,      1,      do_usbboot,
 695        "boot from USB device",
 696        "loadAddr dev:part\n"
 697);
 698
 699#else
 700U_BOOT_CMD(
 701        usb,    5,      1,      do_usb,
 702        "USB sub-system",
 703        "reset - reset (rescan) USB controller\n"
 704        "usb  tree  - show USB device tree\n"
 705        "usb  info [dev] - show available USB devices\n"
 706);
 707#endif
 708