X-Git-Url: https://git.kernelconcepts.de/?a=blobdiff_plain;f=common%2Fcmd_usb.c;h=c192498257fe8f60fed0f41e4c4f97b8fcd0d986;hb=ff0960f9a018952cbaab59c0d87b6e0338c8f04c;hp=b04a8df764db9bde494ed42bbfd7cd279eeb856b;hpb=36ebb78779cb08b48672e0fa5cd891199cc0ee23;p=karo-tx-uboot.git diff --git a/common/cmd_usb.c b/common/cmd_usb.c index b04a8df764..c192498257 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -5,38 +5,25 @@ * Most of this source has been derived from the Linux USB * project. * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * + * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include +#include #include #include #ifdef CONFIG_USB_STORAGE static int usb_stor_curr_dev = -1; /* current device */ #endif +#ifdef CONFIG_USB_HOST_ETHER +static int usb_ether_curr_dev = -1; /* current ethernet device */ +#endif /* some display routines (info command) */ -char *usb_get_class_desc(unsigned char dclass) +static char *usb_get_class_desc(unsigned char dclass) { switch (dclass) { case USB_CLASS_PER_INTERFACE: @@ -62,8 +49,8 @@ char *usb_get_class_desc(unsigned char dclass) } } -void usb_display_class_sub(unsigned char dclass, unsigned char subclass, - unsigned char proto) +static void usb_display_class_sub(unsigned char dclass, unsigned char subclass, + unsigned char proto) { switch (dclass) { case USB_CLASS_PER_INTERFACE: @@ -144,16 +131,17 @@ void usb_display_class_sub(unsigned char dclass, unsigned char subclass, } } -void usb_display_string(struct usb_device *dev, int index) +static void usb_display_string(struct usb_device *dev, int index) { - char buffer[256]; + ALLOC_CACHE_ALIGN_BUFFER(char, buffer, 256); + if (index != 0) { if (usb_string(dev, index, &buffer[0], 256) > 0) printf("String: \"%s\"", buffer); } } -void usb_display_desc(struct usb_device *dev) +static void usb_display_desc(struct usb_device *dev) { if (dev->descriptor.bDescriptorType == USB_DT_DEVICE) { printf("%d: %s, USB Revision %x.%x\n", dev->devnum, @@ -187,8 +175,8 @@ void usb_display_desc(struct usb_device *dev) } -void usb_display_conf_desc(struct usb_configuration_descriptor *config, - struct usb_device *dev) +static void usb_display_conf_desc(struct usb_config_descriptor *config, + struct usb_device *dev) { printf(" Configuration: %d\n", config->bConfigurationValue); printf(" - Interfaces: %d %s%s%dmA\n", config->bNumInterfaces, @@ -202,8 +190,8 @@ void usb_display_conf_desc(struct usb_configuration_descriptor *config, } } -void usb_display_if_desc(struct usb_interface_descriptor *ifdesc, - struct usb_device *dev) +static void usb_display_if_desc(struct usb_interface_descriptor *ifdesc, + struct usb_device *dev) { printf(" Interface: %d\n", ifdesc->bInterfaceNumber); printf(" - Alternate Setting %d, Endpoints: %d\n", @@ -219,7 +207,7 @@ void usb_display_if_desc(struct usb_interface_descriptor *ifdesc, } } -void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc) +static void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc) { printf(" - Endpoint %d %s ", epdesc->bEndpointAddress & 0xf, (epdesc->bEndpointAddress & 0x80) ? "In" : "Out"); @@ -237,14 +225,14 @@ void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc) printf("Interrupt"); break; } - printf(" MaxPacket %d", epdesc->wMaxPacketSize); + printf(" MaxPacket %d", get_unaligned(&epdesc->wMaxPacketSize)); if ((epdesc->bmAttributes & 0x03) == 0x3) printf(" Interval %dms", epdesc->bInterval); printf("\n"); } /* main routine to diasplay the configs, interfaces and endpoints */ -void usb_display_config(struct usb_device *dev) +static void usb_display_config(struct usb_device *dev) { struct usb_config *config; struct usb_interface *ifdesc; @@ -264,21 +252,49 @@ void usb_display_config(struct usb_device *dev) printf("\n"); } +static struct usb_device *usb_find_device(int devnum) +{ + struct usb_device *dev; + int d; + + for (d = 0; d < USB_MAX_DEVICE; d++) { + dev = usb_get_dev_index(d); + if (dev == NULL) + return NULL; + if (dev->devnum == devnum) + return dev; + } + + return NULL; +} + static inline char *portspeed(int speed) { - if (speed == USB_SPEED_HIGH) - return "480 Mb/s"; - else if (speed == USB_SPEED_LOW) - return "1.5 Mb/s"; - else - return "12 Mb/s"; + char *speed_str; + + switch (speed) { + case USB_SPEED_SUPER: + speed_str = "5 Gb/s"; + break; + case USB_SPEED_HIGH: + speed_str = "480 Mb/s"; + break; + case USB_SPEED_LOW: + speed_str = "1.5 Mb/s"; + break; + default: + speed_str = "12 Mb/s"; + break; + } + + return speed_str; } /* shows the device tree recursively */ -void usb_show_tree_graph(struct usb_device *dev, char *pre) +static void usb_show_tree_graph(struct usb_device *dev, char *pre) { int i, index; - int has_child, last_child, port; + int has_child, last_child; index = strlen(pre); printf(" %s", pre); @@ -297,7 +313,6 @@ void usb_show_tree_graph(struct usb_device *dev, char *pre) /* found our pointer, see if we have a * little sister */ - port = i; while (i++ < dev->parent->maxchild) { if (dev->parent->children[i] != NULL) { /* found a sister */ @@ -336,7 +351,7 @@ void usb_show_tree_graph(struct usb_device *dev, char *pre) } /* main routine for the tree command */ -void usb_show_tree(struct usb_device *dev) +static void usb_show_tree(struct usb_device *dev) { char preamble[32]; @@ -344,167 +359,92 @@ void usb_show_tree(struct usb_device *dev) usb_show_tree_graph(dev, &preamble[0]); } - -/****************************************************************************** - * usb boot command intepreter. Derived from diskboot - */ -#ifdef CONFIG_USB_STORAGE -int do_usbboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +static int usb_test(struct usb_device *dev, int port, char* arg) { - char *boot_device = NULL; - char *ep; - int dev, part = 1, rcode; - ulong addr, cnt; - disk_partition_t info; - image_header_t *hdr; - block_dev_desc_t *stor_dev; -#if defined(CONFIG_FIT) - const void *fit_hdr = NULL; -#endif + int mode; - switch (argc) { - case 1: - addr = CONFIG_SYS_LOAD_ADDR; - boot_device = getenv("bootdevice"); - break; - case 2: - addr = simple_strtoul(argv[1], NULL, 16); - boot_device = getenv("bootdevice"); - break; - case 3: - addr = simple_strtoul(argv[1], NULL, 16); - boot_device = argv[2]; - break; - default: - return cmd_usage(cmdtp); - } - - if (!boot_device) { - puts("\n** No boot device **\n"); - return 1; - } - - dev = simple_strtoul(boot_device, &ep, 16); - stor_dev = usb_stor_get_dev(dev); - if (stor_dev == NULL || stor_dev->type == DEV_TYPE_UNKNOWN) { - printf("\n** Device %d not available\n", dev); - return 1; - } - if (stor_dev->block_read == NULL) { - printf("storage device not initialized. Use usb scan\n"); - return 1; - } - if (*ep) { - if (*ep != ':') { - puts("\n** Invalid boot device, use `dev[:part]' **\n"); - return 1; - } - part = simple_strtoul(++ep, NULL, 16); - } - - if (get_partition_info(stor_dev, part, &info)) { - /* try to boot raw .... */ - strncpy((char *)&info.type[0], BOOT_PART_TYPE, - sizeof(BOOT_PART_TYPE)); - strncpy((char *)&info.name[0], "Raw", 4); - info.start = 0; - info.blksz = 0x200; - info.size = 2880; - printf("error reading partinfo...try to boot raw\n"); - } - if ((strncmp((char *)info.type, BOOT_PART_TYPE, - sizeof(info.type)) != 0) && - (strncmp((char *)info.type, BOOT_PART_COMP, - sizeof(info.type)) != 0)) { - printf("\n** Invalid partition type \"%.32s\"" - " (expect \"" BOOT_PART_TYPE "\")\n", - info.type); - return 1; - } - printf("\nLoading from USB device %d, partition %d: " - "Name: %.32s Type: %.32s\n", - dev, part, info.name, info.type); - - debug("First Block: %ld, # of blocks: %ld, Block Size: %ld\n", - info.start, info.size, info.blksz); - - if (stor_dev->block_read(dev, info.start, 1, (ulong *)addr) != 1) { - printf("** Read error on %d:%d\n", dev, part); + if (port > dev->maxchild) { + printf("Device is no hub or does not have %d ports.\n", port); return 1; } - switch (genimg_get_format((void *)addr)) { - case IMAGE_FORMAT_LEGACY: - hdr = (image_header_t *)addr; - - if (!image_check_hcrc(hdr)) { - puts("\n** Bad Header Checksum **\n"); - return 1; - } - - image_print_contents(hdr); - - cnt = image_get_image_size(hdr); + switch (arg[0]) { + case 'J': + case 'j': + printf("Setting Test_J mode"); + mode = USB_TEST_MODE_J; break; -#if defined(CONFIG_FIT) - case IMAGE_FORMAT_FIT: - fit_hdr = (const void *)addr; - puts("Fit image detected...\n"); - - cnt = fit_get_size(fit_hdr); + case 'K': + case 'k': + printf("Setting Test_K mode"); + mode = USB_TEST_MODE_K; + break; + case 'S': + case 's': + printf("Setting Test_SE0_NAK mode"); + mode = USB_TEST_MODE_SE0_NAK; + break; + case 'P': + case 'p': + printf("Setting Test_Packet mode"); + mode = USB_TEST_MODE_PACKET; + break; + case 'F': + case 'f': + printf("Setting Test_Force_Enable mode"); + mode = USB_TEST_MODE_FORCE_ENABLE; break; -#endif default: - puts("** Unknown image type\n"); + printf("Unrecognized test mode: %s\nAvailable modes: " + "J, K, S[E0_NAK], P[acket], F[orce_Enable]\n", arg); return 1; } - cnt += info.blksz - 1; - cnt /= info.blksz; - cnt -= 1; - - if (stor_dev->block_read(dev, info.start+1, cnt, - (ulong *)(addr+info.blksz)) != cnt) { - printf("\n** Read error on %d:%d\n", dev, part); + if (port) + printf(" on downstream facing port %d...\n", port); + else + printf(" on upstream facing port...\n"); + + if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_FEATURE, + port ? USB_RT_PORT : USB_RECIP_DEVICE, + port ? USB_PORT_FEAT_TEST : USB_FEAT_TEST, + (mode << 8) | port, + NULL, 0, USB_CNTL_TIMEOUT) == -1) { + printf("Error during SET_FEATURE.\n"); return 1; + } else { + printf("Test mode successfully set. Use 'usb start' " + "to return to normal operation.\n"); + return 0; } +} -#if defined(CONFIG_FIT) - /* This cannot be done earlier, we need complete FIT image in RAM - * first - */ - if (genimg_get_format((void *)addr) == IMAGE_FORMAT_FIT) { - if (!fit_check_format(fit_hdr)) { - puts("** Bad FIT image format\n"); - return 1; - } - fit_print_contents(fit_hdr); - } -#endif - - /* Loading ok, update default load address */ - load_addr = addr; - flush_cache(addr, (cnt+1)*info.blksz); +/****************************************************************************** + * usb boot command intepreter. Derived from diskboot + */ +#ifdef CONFIG_USB_STORAGE +static int do_usbboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + return common_diskboot(cmdtp, "usb", argc, argv); +} +#endif /* CONFIG_USB_STORAGE */ - /* Check if we should attempt an auto-start */ - if (((ep = getenv("autostart")) != NULL) && (strcmp(ep, "yes") == 0)) { - char *local_args[2]; - local_args[0] = argv[0]; - local_args[1] = NULL; - printf("Automatic boot of image at addr 0x%08lX ...\n", addr); - rcode = do_bootm(cmdtp, 0, 1, local_args); - return rcode; +static int do_usb_stop_keyboard(int force) +{ +#ifdef CONFIG_USB_KEYBOARD + if (usb_kbd_deregister(force) != 0) { + printf("USB not stopped: usbkbd still using USB\n"); + return 1; } +#endif return 0; } -#endif /* CONFIG_USB_STORAGE */ - /****************************************************************************** * usb command intepreter */ -int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int i; @@ -515,34 +455,35 @@ int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #endif if (argc < 2) - return cmd_usage(cmdtp); + return CMD_RET_USAGE; if ((strncmp(argv[1], "reset", 5) == 0) || (strncmp(argv[1], "start", 5) == 0)) { + bootstage_mark_name(BOOTSTAGE_ID_USB_START, "usb_start"); + if (do_usb_stop_keyboard(1) != 0) + return 1; usb_stop(); printf("(Re)start USB...\n"); - i = usb_init(); + if (usb_init() >= 0) { #ifdef CONFIG_USB_STORAGE - /* try to recognize storage devices immediately */ - if (i >= 0) + /* try to recognize storage devices immediately */ usb_stor_curr_dev = usb_stor_scan(1); #endif +#ifdef CONFIG_USB_HOST_ETHER + /* try to recognize ethernet devices immediately */ + usb_ether_curr_dev = usb_host_eth_scan(1); +#endif +#ifdef CONFIG_USB_KEYBOARD + drv_usb_kbd_init(); +#endif + } return 0; } if (strncmp(argv[1], "stop", 4) == 0) { -#ifdef CONFIG_USB_KEYBOARD - if (argc == 2) { - if (usb_kbd_deregister() != 0) { - printf("USB not stopped: usbkbd still" - " using USB\n"); - return 1; - } - } else { - /* forced stop, switch console in to serial */ + if (argc != 2) console_assign(stdin, "serial"); - usb_kbd_deregister(); - } -#endif + if (do_usb_stop_keyboard(0) != 0) + return 1; printf("stopping USB..\n"); usb_stop(); return 0; @@ -552,8 +493,14 @@ int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 1; } if (strncmp(argv[1], "tree", 4) == 0) { - printf("\nDevice Tree:\n"); - usb_show_tree(usb_get_dev_index(0)); + puts("USB device tree:\n"); + for (i = 0; i < USB_MAX_DEVICE; i++) { + dev = usb_get_dev_index(i); + if (dev == NULL) + break; + if (dev->parent == NULL) + usb_show_tree(dev); + } return 0; } if (strncmp(argv[1], "inf", 3) == 0) { @@ -568,19 +515,11 @@ int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } return 0; } else { - int d; - - i = simple_strtoul(argv[2], NULL, 16); + i = simple_strtoul(argv[2], NULL, 10); printf("config for device %d\n", i); - for (d = 0; d < USB_MAX_DEVICE; d++) { - dev = usb_get_dev_index(d); - if (dev == NULL) - break; - if (dev->devnum == i) - break; - } + dev = usb_find_device(i); if (dev == NULL) { - printf("*** NO Device avaiable ***\n"); + printf("*** No device available ***\n"); return 0; } else { usb_display_desc(dev); @@ -589,6 +528,18 @@ int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } return 0; } + if (strncmp(argv[1], "test", 4) == 0) { + if (argc < 5) + return CMD_RET_USAGE; + i = simple_strtoul(argv[2], NULL, 10); + dev = usb_find_device(i); + if (dev == NULL) { + printf("Device %d does not exist.\n", i); + return 1; + } + i = simple_strtoul(argv[3], NULL, 10); + return usb_test(dev, i, argv[4]); + } #ifdef CONFIG_USB_STORAGE if (strncmp(argv[1], "stor", 4) == 0) return usb_stor_info(); @@ -695,40 +646,37 @@ int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } #endif /* CONFIG_USB_STORAGE */ - return cmd_usage(cmdtp); + return CMD_RET_USAGE; } -#ifdef CONFIG_USB_STORAGE U_BOOT_CMD( usb, 5, 1, do_usb, "USB sub-system", - "reset - reset (rescan) USB controller\n" - "usb stop [f] - stop USB [f]=force stop\n" - "usb tree - show USB device tree\n" + "start - start (scan) USB controller\n" + "usb reset - reset (rescan) USB controller\n" + "usb stop [f] - stop USB [f]=force stop\n" + "usb tree - show USB device tree\n" "usb info [dev] - show available USB devices\n" - "usb storage - show details of USB storage devices\n" + "usb test [dev] [port] [mode] - set USB 2.0 test mode\n" + " (specify port 0 to indicate the device's upstream port)\n" + " Available modes: J, K, S[E0_NAK], P[acket], F[orce_Enable]\n" +#ifdef CONFIG_USB_STORAGE + "usb storage - show details of USB storage devices\n" "usb dev [dev] - show or set current USB storage device\n" "usb part [dev] - print partition table of one or all USB storage" - " devices\n" + " devices\n" "usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n" " to memory address `addr'\n" "usb write addr blk# cnt - write `cnt' blocks starting at block `blk#'\n" " from memory address `addr'" +#endif /* CONFIG_USB_STORAGE */ ); +#ifdef CONFIG_USB_STORAGE U_BOOT_CMD( usbboot, 3, 1, do_usbboot, "boot from USB device", "loadAddr dev:part" ); - -#else -U_BOOT_CMD( - usb, 5, 1, do_usb, - "USB sub-system", - "reset - reset (rescan) USB controller\n" - "usb tree - show USB device tree\n" - "usb info [dev] - show available USB devices" -); -#endif +#endif /* CONFIG_USB_STORAGE */