]> Git Repo - J-u-boot.git/blob - cmd/usb_mass_storage.c
net: wget: integrate struct wget_info into legacy wget code
[J-u-boot.git] / cmd / usb_mass_storage.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2011 Samsung Electronics
4  * Lukasz Majewski <[email protected]>
5  *
6  * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
7  */
8
9 #include <blk.h>
10 #include <command.h>
11 #include <console.h>
12 #include <errno.h>
13 #include <g_dnl.h>
14 #include <malloc.h>
15 #include <part.h>
16 #include <usb.h>
17 #include <usb_mass_storage.h>
18 #include <watchdog.h>
19 #include <linux/delay.h>
20 #include <linux/printk.h>
21
22 static int ums_read_sector(struct ums *ums_dev,
23                            ulong start, lbaint_t blkcnt, void *buf)
24 {
25         struct blk_desc *block_dev = &ums_dev->block_dev;
26         lbaint_t blkstart = start + ums_dev->start_sector;
27
28         return blk_dread(block_dev, blkstart, blkcnt, buf);
29 }
30
31 static int ums_write_sector(struct ums *ums_dev,
32                             ulong start, lbaint_t blkcnt, const void *buf)
33 {
34         struct blk_desc *block_dev = &ums_dev->block_dev;
35         lbaint_t blkstart = start + ums_dev->start_sector;
36
37         return blk_dwrite(block_dev, blkstart, blkcnt, buf);
38 }
39
40 static struct ums *ums;
41 static int ums_count;
42
43 static void ums_fini(void)
44 {
45         int i;
46
47         for (i = 0; i < ums_count; i++)
48                 free((void *)ums[i].name);
49         free(ums);
50         ums = NULL;
51         ums_count = 0;
52 }
53
54 #define UMS_NAME_LEN 16
55
56 static int ums_init(const char *devtype, const char *devnums_part_str)
57 {
58         char *s, *t, *devnum_part_str, *name;
59         struct blk_desc *block_dev;
60         struct disk_partition info;
61         int partnum;
62         int ret = -1;
63         struct ums *ums_new;
64
65         s = strdup(devnums_part_str);
66         if (!s)
67                 return -1;
68
69         t = s;
70         ums_count = 0;
71
72         for (;;) {
73                 devnum_part_str = strsep(&t, ",");
74                 if (!devnum_part_str)
75                         break;
76
77                 partnum = part_get_info_by_dev_and_name_or_num(devtype, devnum_part_str,
78                                                                &block_dev, &info, 1);
79
80                 if (partnum < 0)
81                         goto cleanup;
82
83                 /* Check if the argument is in legacy format. If yes,
84                  * expose all partitions by setting the partnum = 0
85                  * e.g. ums 0 mmc 0
86                  */
87                 if (!strchr(devnum_part_str, ':'))
88                         partnum = 0;
89
90                 ums_new = realloc(ums, (ums_count + 1) * sizeof(*ums));
91                 if (!ums_new)
92                         goto cleanup;
93                 ums = ums_new;
94
95                 /* if partnum = 0, expose all partitions */
96                 if (partnum == 0) {
97                         ums[ums_count].start_sector = 0;
98                         ums[ums_count].num_sectors = block_dev->lba;
99                 } else {
100                         ums[ums_count].start_sector = info.start;
101                         ums[ums_count].num_sectors = info.size;
102                 }
103
104                 ums[ums_count].read_sector = ums_read_sector;
105                 ums[ums_count].write_sector = ums_write_sector;
106
107                 name = malloc(UMS_NAME_LEN);
108                 if (!name)
109                         goto cleanup;
110                 snprintf(name, UMS_NAME_LEN, "UMS disk %d", ums_count);
111                 ums[ums_count].name = name;
112                 ums[ums_count].block_dev = *block_dev;
113
114                 printf("UMS: LUN %d, dev %s %d, hwpart %d, sector %#x, count %#x\n",
115                        ums_count, devtype, ums[ums_count].block_dev.devnum,
116                        ums[ums_count].block_dev.hwpart,
117                        ums[ums_count].start_sector,
118                        ums[ums_count].num_sectors);
119
120                 ums_count++;
121         }
122
123         if (ums_count)
124                 ret = 0;
125
126 cleanup:
127         free(s);
128
129         if (ret < 0)
130                 ums_fini();
131
132         return ret;
133 }
134
135 static int do_usb_mass_storage(struct cmd_tbl *cmdtp, int flag,
136                                int argc, char *const argv[])
137 {
138         const char *usb_controller;
139         const char *devtype;
140         const char *devnum;
141         unsigned int controller_index;
142         struct udevice *udc;
143         int rc;
144         int cable_ready_timeout __maybe_unused;
145
146         if (argc < 3)
147                 return CMD_RET_USAGE;
148
149         usb_controller = argv[1];
150         if (argc >= 4) {
151                 devtype = argv[2];
152                 devnum  = argv[3];
153         } else {
154                 devtype = "mmc";
155                 devnum  = argv[2];
156         }
157
158         rc = ums_init(devtype, devnum);
159         if (rc < 0)
160                 return CMD_RET_FAILURE;
161
162         controller_index = (unsigned int)(simple_strtoul(
163                                 usb_controller, NULL, 0));
164         rc = udc_device_get_by_index(controller_index, &udc);
165         if (rc) {
166                 pr_err("Couldn't init USB controller.\n");
167                 rc = CMD_RET_FAILURE;
168                 goto cleanup_ums_init;
169         }
170
171         rc = fsg_init(ums, ums_count, udc);
172         if (rc) {
173                 pr_err("fsg_init failed\n");
174                 rc = CMD_RET_FAILURE;
175                 goto cleanup_board;
176         }
177
178         rc = g_dnl_register("usb_dnl_ums");
179         if (rc) {
180                 pr_err("g_dnl_register failed\n");
181                 rc = CMD_RET_FAILURE;
182                 goto cleanup_board;
183         }
184
185         /* Timeout unit: seconds */
186         cable_ready_timeout = UMS_CABLE_READY_TIMEOUT;
187
188         if (!g_dnl_board_usb_cable_connected()) {
189                 /*
190                  * Won't execute if we don't know whether the cable is
191                  * connected.
192                  */
193                 puts("Please connect USB cable.\n");
194
195                 while (!g_dnl_board_usb_cable_connected()) {
196                         if (ctrlc()) {
197                                 puts("\rCTRL+C - Operation aborted.\n");
198                                 rc = CMD_RET_SUCCESS;
199                                 goto cleanup_register;
200                         }
201                         if (!cable_ready_timeout) {
202                                 puts("\rUSB cable not detected.\n" \
203                                      "Command exit.\n");
204                                 rc = CMD_RET_SUCCESS;
205                                 goto cleanup_register;
206                         }
207
208                         printf("\rAuto exit in: %.2d s.", cable_ready_timeout);
209                         mdelay(1000);
210                         cable_ready_timeout--;
211                 }
212                 puts("\r\n");
213         }
214
215         while (1) {
216                 dm_usb_gadget_handle_interrupts(udc);
217
218                 rc = fsg_main_thread(NULL);
219                 if (rc) {
220                         /* Check I/O error */
221                         if (rc == -EIO)
222                                 printf("\rCheck USB cable connection\n");
223
224                         /* Check CTRL+C */
225                         if (rc == -EPIPE)
226                                 printf("\rCTRL+C - Operation aborted\n");
227
228                         rc = CMD_RET_SUCCESS;
229                         goto cleanup_register;
230                 }
231
232                 if (IS_ENABLED(CONFIG_CMD_UMS_ABORT_KEYED)) {
233                         /* Abort by pressing any key */
234                         if (tstc()) {
235                                 getchar();
236                                 printf("\rOperation aborted.\n");
237                                 rc = CMD_RET_SUCCESS;
238                                 goto cleanup_register;
239                         }
240                 }
241
242                 schedule();
243         }
244
245 cleanup_register:
246         g_dnl_unregister();
247 cleanup_board:
248         udc_device_put(udc);
249 cleanup_ums_init:
250         ums_fini();
251
252         return rc;
253 }
254
255 U_BOOT_CMD(ums, 4, 1, do_usb_mass_storage,
256         "Use the UMS [USB Mass Storage]",
257         "<USB_controller> [<devtype>] <dev[:part]>  e.g. ums 0 mmc 0\n"
258         "    devtype defaults to mmc"
259 );
This page took 0.041672 seconds and 4 git commands to generate.