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