1e00cb223SSimon Glass /*
2e00cb223SSimon Glass * Copyright (C) 2015 Google, Inc
3e00cb223SSimon Glass *
4e00cb223SSimon Glass * SPDX-License-Identifier: GPL-2.0+
5e00cb223SSimon Glass */
6e00cb223SSimon Glass
7e00cb223SSimon Glass #include <common.h>
824b852a7SSimon Glass #include <console.h>
9e00cb223SSimon Glass #include <dm.h>
10e00cb223SSimon Glass #include <usb.h>
11e00cb223SSimon Glass #include <asm/io.h>
123884c98cSSimon Glass #include <asm/state.h>
13bff1a71eSSimon Glass #include <asm/test.h>
143884c98cSSimon Glass #include <dm/device-internal.h>
15e00cb223SSimon Glass #include <dm/test.h>
16431cbd6dSSimon Glass #include <dm/uclass-internal.h>
17e721b882SJoe Hershberger #include <test/ut.h>
18e00cb223SSimon Glass
19431cbd6dSSimon Glass DECLARE_GLOBAL_DATA_PTR;
20431cbd6dSSimon Glass
21e00cb223SSimon Glass /* Test that sandbox USB works correctly */
dm_test_usb_base(struct unit_test_state * uts)22e721b882SJoe Hershberger static int dm_test_usb_base(struct unit_test_state *uts)
23e00cb223SSimon Glass {
24e00cb223SSimon Glass struct udevice *bus;
25e00cb223SSimon Glass
26e00cb223SSimon Glass ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_USB, 0, &bus));
27e00cb223SSimon Glass ut_assertok(uclass_get_device(UCLASS_USB, 0, &bus));
28e00cb223SSimon Glass ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_USB, 2, &bus));
29e00cb223SSimon Glass
30e00cb223SSimon Glass return 0;
31e00cb223SSimon Glass }
32e00cb223SSimon Glass DM_TEST(dm_test_usb_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
33e00cb223SSimon Glass
34e00cb223SSimon Glass /*
35e00cb223SSimon Glass * Test that we can use the flash stick. This is more of a functional test. It
36e00cb223SSimon Glass * covers scanning the bug, setting up a hub and a flash stick and reading
37e00cb223SSimon Glass * data from the flash stick.
38e00cb223SSimon Glass */
dm_test_usb_flash(struct unit_test_state * uts)39e721b882SJoe Hershberger static int dm_test_usb_flash(struct unit_test_state *uts)
40e00cb223SSimon Glass {
41e00cb223SSimon Glass struct udevice *dev;
424101f687SSimon Glass struct blk_desc *dev_desc;
43e00cb223SSimon Glass char cmp[1024];
44e00cb223SSimon Glass
453884c98cSSimon Glass state_set_skip_delays(true);
46e00cb223SSimon Glass ut_assertok(usb_init());
47e00cb223SSimon Glass ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
48ebac37cfSSimon Glass ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc));
49e00cb223SSimon Glass
50e00cb223SSimon Glass /* Read a few blocks and look for the string we expect */
51e00cb223SSimon Glass ut_asserteq(512, dev_desc->blksz);
52e00cb223SSimon Glass memset(cmp, '\0', sizeof(cmp));
532a981dc2SSimon Glass ut_asserteq(2, blk_dread(dev_desc, 0, 2, cmp));
54e00cb223SSimon Glass ut_assertok(strcmp(cmp, "this is a test"));
55*61ccd886SSimon Glass ut_assertok(usb_stop());
56e00cb223SSimon Glass
57e00cb223SSimon Glass return 0;
58e00cb223SSimon Glass }
59e00cb223SSimon Glass DM_TEST(dm_test_usb_flash, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
60431cbd6dSSimon Glass
61431cbd6dSSimon Glass /* test that we can handle multiple storage devices */
dm_test_usb_multi(struct unit_test_state * uts)62431cbd6dSSimon Glass static int dm_test_usb_multi(struct unit_test_state *uts)
63431cbd6dSSimon Glass {
64431cbd6dSSimon Glass struct udevice *dev;
65431cbd6dSSimon Glass
66431cbd6dSSimon Glass state_set_skip_delays(true);
67431cbd6dSSimon Glass ut_assertok(usb_init());
68431cbd6dSSimon Glass ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
69431cbd6dSSimon Glass ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev));
70431cbd6dSSimon Glass ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev));
71*61ccd886SSimon Glass ut_assertok(usb_stop());
72431cbd6dSSimon Glass
73431cbd6dSSimon Glass return 0;
74431cbd6dSSimon Glass }
75431cbd6dSSimon Glass DM_TEST(dm_test_usb_multi, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
76431cbd6dSSimon Glass
count_usb_devices(void)77431cbd6dSSimon Glass static int count_usb_devices(void)
78431cbd6dSSimon Glass {
79431cbd6dSSimon Glass struct udevice *hub;
80431cbd6dSSimon Glass struct uclass *uc;
81431cbd6dSSimon Glass int count = 0;
82431cbd6dSSimon Glass int ret;
83431cbd6dSSimon Glass
84431cbd6dSSimon Glass ret = uclass_get(UCLASS_USB_HUB, &uc);
85431cbd6dSSimon Glass if (ret)
86431cbd6dSSimon Glass return ret;
87431cbd6dSSimon Glass
88431cbd6dSSimon Glass uclass_foreach_dev(hub, uc) {
89431cbd6dSSimon Glass struct udevice *dev;
90431cbd6dSSimon Glass
91431cbd6dSSimon Glass count++;
92431cbd6dSSimon Glass for (device_find_first_child(hub, &dev);
93431cbd6dSSimon Glass dev;
94431cbd6dSSimon Glass device_find_next_child(&dev)) {
95431cbd6dSSimon Glass count++;
96431cbd6dSSimon Glass }
97431cbd6dSSimon Glass }
98431cbd6dSSimon Glass
99431cbd6dSSimon Glass return count;
100431cbd6dSSimon Glass }
101431cbd6dSSimon Glass
102431cbd6dSSimon Glass /* test that we can remove an emulated device and it is then not found */
dm_test_usb_remove(struct unit_test_state * uts)103431cbd6dSSimon Glass static int dm_test_usb_remove(struct unit_test_state *uts)
104431cbd6dSSimon Glass {
105431cbd6dSSimon Glass struct udevice *dev, *emul;
106431cbd6dSSimon Glass
107431cbd6dSSimon Glass /* Scan and check that all devices are present */
108431cbd6dSSimon Glass state_set_skip_delays(true);
109431cbd6dSSimon Glass ut_assertok(usb_init());
110431cbd6dSSimon Glass ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
111431cbd6dSSimon Glass ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev));
112431cbd6dSSimon Glass ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev));
113a57a8174SSimon Glass ut_asserteq(6, count_usb_devices());
114431cbd6dSSimon Glass ut_assertok(usb_stop());
115a57a8174SSimon Glass ut_asserteq(6, count_usb_devices());
116431cbd6dSSimon Glass
117431cbd6dSSimon Glass /* Remove the second emulation device */
118431cbd6dSSimon Glass ut_assertok(uclass_find_device_by_name(UCLASS_USB_EMUL, "flash-stick@1",
119431cbd6dSSimon Glass &dev));
120431cbd6dSSimon Glass ut_assertok(device_unbind(dev));
121431cbd6dSSimon Glass
122431cbd6dSSimon Glass /* Rescan - only the first and third should be present */
123431cbd6dSSimon Glass ut_assertok(usb_init());
124431cbd6dSSimon Glass ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
125431cbd6dSSimon Glass ut_assertok(usb_emul_find_for_dev(dev, &emul));
126431cbd6dSSimon Glass ut_asserteq_str("flash-stick@0", emul->name);
127431cbd6dSSimon Glass ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev));
128431cbd6dSSimon Glass ut_assertok(usb_emul_find_for_dev(dev, &emul));
129431cbd6dSSimon Glass ut_asserteq_str("flash-stick@2", emul->name);
130431cbd6dSSimon Glass
131431cbd6dSSimon Glass ut_asserteq(-ENODEV, uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev));
132431cbd6dSSimon Glass
133a57a8174SSimon Glass ut_asserteq(5, count_usb_devices());
134431cbd6dSSimon Glass ut_assertok(usb_stop());
135a57a8174SSimon Glass ut_asserteq(5, count_usb_devices());
136431cbd6dSSimon Glass
137431cbd6dSSimon Glass return 0;
138431cbd6dSSimon Glass }
139431cbd6dSSimon Glass DM_TEST(dm_test_usb_remove, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
140431cbd6dSSimon Glass
141431cbd6dSSimon Glass const char usb_tree_base[] =
142431cbd6dSSimon Glass " 1 Hub (12 Mb/s, 100mA)\n"
143431cbd6dSSimon Glass " | sandbox hub 2345\n"
144431cbd6dSSimon Glass " |\n"
145431cbd6dSSimon Glass " |\b+-2 Mass Storage (12 Mb/s, 100mA)\n"
146431cbd6dSSimon Glass " | sandbox flash flash-stick@0\n"
147431cbd6dSSimon Glass " | \n"
148431cbd6dSSimon Glass " |\b+-3 Mass Storage (12 Mb/s, 100mA)\n"
149431cbd6dSSimon Glass " | sandbox flash flash-stick@1\n"
150431cbd6dSSimon Glass " | \n"
151431cbd6dSSimon Glass " |\b+-4 Mass Storage (12 Mb/s, 100mA)\n"
152a57a8174SSimon Glass " | sandbox flash flash-stick@2\n"
153a57a8174SSimon Glass " | \n"
154a57a8174SSimon Glass " |\b+-5 Human Interface (12 Mb/s, 100mA)\n"
155a57a8174SSimon Glass " sandbox keyboard keyb@3\n"
156431cbd6dSSimon Glass " \n";
157431cbd6dSSimon Glass
158431cbd6dSSimon Glass /* test that the 'usb tree' command output looks correct */
dm_test_usb_tree(struct unit_test_state * uts)159431cbd6dSSimon Glass static int dm_test_usb_tree(struct unit_test_state *uts)
160431cbd6dSSimon Glass {
161431cbd6dSSimon Glass char *data;
162431cbd6dSSimon Glass int len;
163431cbd6dSSimon Glass
164431cbd6dSSimon Glass state_set_skip_delays(true);
165431cbd6dSSimon Glass ut_assertok(usb_init());
166431cbd6dSSimon Glass console_record_reset_enable();
167431cbd6dSSimon Glass usb_show_tree();
168431cbd6dSSimon Glass len = membuff_getraw(&gd->console_out, -1, true, &data);
169431cbd6dSSimon Glass if (len)
170431cbd6dSSimon Glass data[len] = '\0';
171431cbd6dSSimon Glass ut_asserteq_str(usb_tree_base, data);
172431cbd6dSSimon Glass ut_assertok(usb_stop());
173431cbd6dSSimon Glass
174431cbd6dSSimon Glass return 0;
175431cbd6dSSimon Glass }
176431cbd6dSSimon Glass DM_TEST(dm_test_usb_tree, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
177431cbd6dSSimon Glass
178431cbd6dSSimon Glass const char usb_tree_remove[] =
179431cbd6dSSimon Glass " 1 Hub (12 Mb/s, 100mA)\n"
180431cbd6dSSimon Glass " | sandbox hub 2345\n"
181431cbd6dSSimon Glass " |\n"
182431cbd6dSSimon Glass " |\b+-2 Mass Storage (12 Mb/s, 100mA)\n"
183431cbd6dSSimon Glass " | sandbox flash flash-stick@0\n"
184431cbd6dSSimon Glass " | \n"
185431cbd6dSSimon Glass " |\b+-3 Mass Storage (12 Mb/s, 100mA)\n"
186a57a8174SSimon Glass " | sandbox flash flash-stick@2\n"
187a57a8174SSimon Glass " | \n"
188a57a8174SSimon Glass " |\b+-4 Human Interface (12 Mb/s, 100mA)\n"
189a57a8174SSimon Glass " sandbox keyboard keyb@3\n"
190431cbd6dSSimon Glass " \n";
191431cbd6dSSimon Glass
192431cbd6dSSimon Glass /*
193431cbd6dSSimon Glass * test that the 'usb tree' command output looks correct when we remove a
194431cbd6dSSimon Glass * device
195431cbd6dSSimon Glass */
dm_test_usb_tree_remove(struct unit_test_state * uts)196431cbd6dSSimon Glass static int dm_test_usb_tree_remove(struct unit_test_state *uts)
197431cbd6dSSimon Glass {
198431cbd6dSSimon Glass struct udevice *dev;
199431cbd6dSSimon Glass char *data;
200431cbd6dSSimon Glass int len;
201431cbd6dSSimon Glass
202431cbd6dSSimon Glass /* Remove the second emulation device */
203431cbd6dSSimon Glass ut_assertok(uclass_find_device_by_name(UCLASS_USB_EMUL, "flash-stick@1",
204431cbd6dSSimon Glass &dev));
205431cbd6dSSimon Glass ut_assertok(device_unbind(dev));
206431cbd6dSSimon Glass
207431cbd6dSSimon Glass state_set_skip_delays(true);
208431cbd6dSSimon Glass ut_assertok(usb_init());
209431cbd6dSSimon Glass console_record_reset_enable();
210431cbd6dSSimon Glass usb_show_tree();
211431cbd6dSSimon Glass len = membuff_getraw(&gd->console_out, -1, true, &data);
212431cbd6dSSimon Glass if (len)
213431cbd6dSSimon Glass data[len] = '\0';
214431cbd6dSSimon Glass ut_asserteq_str(usb_tree_remove, data);
215431cbd6dSSimon Glass ut_assertok(usb_stop());
216431cbd6dSSimon Glass
217431cbd6dSSimon Glass return 0;
218431cbd6dSSimon Glass }
219431cbd6dSSimon Glass DM_TEST(dm_test_usb_tree_remove, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
220cd716372SSimon Glass
221cd716372SSimon Glass const char usb_tree_reorder[] =
222cd716372SSimon Glass " 1 Hub (12 Mb/s, 100mA)\n"
223cd716372SSimon Glass " | sandbox hub 2345\n"
224cd716372SSimon Glass " |\n"
225cd716372SSimon Glass " |\b+-2 Mass Storage (12 Mb/s, 100mA)\n"
226cd716372SSimon Glass " | sandbox flash flash-stick@0\n"
227cd716372SSimon Glass " | \n"
228cd716372SSimon Glass " |\b+-3 Mass Storage (12 Mb/s, 100mA)\n"
229cd716372SSimon Glass " | sandbox flash flash-stick@2\n"
230cd716372SSimon Glass " | \n"
231a57a8174SSimon Glass " |\b+-4 Human Interface (12 Mb/s, 100mA)\n"
232a57a8174SSimon Glass " | sandbox keyboard keyb@3\n"
233a57a8174SSimon Glass " | \n"
234a57a8174SSimon Glass " |\b+-5 Mass Storage (12 Mb/s, 100mA)\n"
235cd716372SSimon Glass " sandbox flash flash-stick@1\n"
236cd716372SSimon Glass " \n";
237cd716372SSimon Glass
238cd716372SSimon Glass /*
239cd716372SSimon Glass * test that the 'usb tree' command output looks correct when we reorder two
240cd716372SSimon Glass * devices.
241cd716372SSimon Glass */
dm_test_usb_tree_reorder(struct unit_test_state * uts)242cd716372SSimon Glass static int dm_test_usb_tree_reorder(struct unit_test_state *uts)
243cd716372SSimon Glass {
244cd716372SSimon Glass struct udevice *dev, *parent;
245cd716372SSimon Glass char *data;
246cd716372SSimon Glass int len;
247cd716372SSimon Glass
248cd716372SSimon Glass /* Remove the second emulation device */
249cd716372SSimon Glass ut_assertok(uclass_find_device_by_name(UCLASS_USB_EMUL, "flash-stick@1",
250cd716372SSimon Glass &dev));
251cd716372SSimon Glass parent = dev->parent;
252cd716372SSimon Glass
253cd716372SSimon Glass /* Reorder the devices in the parent list and uclass list */
254cd716372SSimon Glass list_del(&dev->sibling_node);
255cd716372SSimon Glass list_add_tail(&dev->sibling_node, &parent->child_head);
256cd716372SSimon Glass
257cd716372SSimon Glass list_del(&dev->uclass_node);
258cd716372SSimon Glass list_add_tail(&dev->uclass_node, &dev->uclass->dev_head);
259cd716372SSimon Glass
260cd716372SSimon Glass state_set_skip_delays(true);
261cd716372SSimon Glass ut_assertok(usb_init());
262cd716372SSimon Glass console_record_reset_enable();
263cd716372SSimon Glass usb_show_tree();
264cd716372SSimon Glass len = membuff_getraw(&gd->console_out, -1, true, &data);
265cd716372SSimon Glass if (len)
266cd716372SSimon Glass data[len] = '\0';
267cd716372SSimon Glass ut_asserteq_str(usb_tree_reorder, data);
268cd716372SSimon Glass ut_assertok(usb_stop());
269cd716372SSimon Glass
270cd716372SSimon Glass return 0;
271cd716372SSimon Glass }
272cd716372SSimon Glass DM_TEST(dm_test_usb_tree_reorder, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
273bff1a71eSSimon Glass
dm_test_usb_keyb(struct unit_test_state * uts)274bff1a71eSSimon Glass static int dm_test_usb_keyb(struct unit_test_state *uts)
275bff1a71eSSimon Glass {
276bff1a71eSSimon Glass struct udevice *dev;
277bff1a71eSSimon Glass
278bff1a71eSSimon Glass state_set_skip_delays(true);
279bff1a71eSSimon Glass ut_assertok(usb_init());
280bff1a71eSSimon Glass
281bff1a71eSSimon Glass /* Initially there should be no characters */
282bff1a71eSSimon Glass ut_asserteq(0, tstc());
283bff1a71eSSimon Glass
284bff1a71eSSimon Glass ut_assertok(uclass_get_device_by_name(UCLASS_USB_EMUL, "keyb",
285bff1a71eSSimon Glass &dev));
286bff1a71eSSimon Glass
287bff1a71eSSimon Glass /*
288bff1a71eSSimon Glass * Add a string to the USB keyboard buffer - it should appear in
289bff1a71eSSimon Glass * stdin
290bff1a71eSSimon Glass */
291bff1a71eSSimon Glass ut_assertok(sandbox_usb_keyb_add_string(dev, "ab"));
292bff1a71eSSimon Glass ut_asserteq(1, tstc());
293bff1a71eSSimon Glass ut_asserteq('a', getc());
294bff1a71eSSimon Glass ut_asserteq(1, tstc());
295bff1a71eSSimon Glass ut_asserteq('b', getc());
296bff1a71eSSimon Glass ut_asserteq(0, tstc());
297bff1a71eSSimon Glass
298bff1a71eSSimon Glass ut_assertok(usb_stop());
299bff1a71eSSimon Glass
300bff1a71eSSimon Glass return 0;
301bff1a71eSSimon Glass }
302bff1a71eSSimon Glass DM_TEST(dm_test_usb_keyb, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
303