1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2015 Google, Inc
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <console.h>
9*4882a593Smuzhiyun #include <dm.h>
10*4882a593Smuzhiyun #include <usb.h>
11*4882a593Smuzhiyun #include <asm/io.h>
12*4882a593Smuzhiyun #include <asm/state.h>
13*4882a593Smuzhiyun #include <asm/test.h>
14*4882a593Smuzhiyun #include <dm/device-internal.h>
15*4882a593Smuzhiyun #include <dm/test.h>
16*4882a593Smuzhiyun #include <dm/uclass-internal.h>
17*4882a593Smuzhiyun #include <test/ut.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun /* Test that sandbox USB works correctly */
dm_test_usb_base(struct unit_test_state * uts)22*4882a593Smuzhiyun static int dm_test_usb_base(struct unit_test_state *uts)
23*4882a593Smuzhiyun {
24*4882a593Smuzhiyun struct udevice *bus;
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_USB, 0, &bus));
27*4882a593Smuzhiyun ut_assertok(uclass_get_device(UCLASS_USB, 0, &bus));
28*4882a593Smuzhiyun ut_asserteq(-ENODEV, uclass_get_device_by_seq(UCLASS_USB, 2, &bus));
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun return 0;
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun DM_TEST(dm_test_usb_base, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun /*
35*4882a593Smuzhiyun * Test that we can use the flash stick. This is more of a functional test. It
36*4882a593Smuzhiyun * covers scanning the bug, setting up a hub and a flash stick and reading
37*4882a593Smuzhiyun * data from the flash stick.
38*4882a593Smuzhiyun */
dm_test_usb_flash(struct unit_test_state * uts)39*4882a593Smuzhiyun static int dm_test_usb_flash(struct unit_test_state *uts)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun struct udevice *dev;
42*4882a593Smuzhiyun struct blk_desc *dev_desc;
43*4882a593Smuzhiyun char cmp[1024];
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun state_set_skip_delays(true);
46*4882a593Smuzhiyun ut_assertok(usb_init());
47*4882a593Smuzhiyun ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
48*4882a593Smuzhiyun ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc));
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun /* Read a few blocks and look for the string we expect */
51*4882a593Smuzhiyun ut_asserteq(512, dev_desc->blksz);
52*4882a593Smuzhiyun memset(cmp, '\0', sizeof(cmp));
53*4882a593Smuzhiyun ut_asserteq(2, blk_dread(dev_desc, 0, 2, cmp));
54*4882a593Smuzhiyun ut_assertok(strcmp(cmp, "this is a test"));
55*4882a593Smuzhiyun ut_assertok(usb_stop());
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun return 0;
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun DM_TEST(dm_test_usb_flash, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun /* test that we can handle multiple storage devices */
dm_test_usb_multi(struct unit_test_state * uts)62*4882a593Smuzhiyun static int dm_test_usb_multi(struct unit_test_state *uts)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun struct udevice *dev;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun state_set_skip_delays(true);
67*4882a593Smuzhiyun ut_assertok(usb_init());
68*4882a593Smuzhiyun ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
69*4882a593Smuzhiyun ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev));
70*4882a593Smuzhiyun ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev));
71*4882a593Smuzhiyun ut_assertok(usb_stop());
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun return 0;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun DM_TEST(dm_test_usb_multi, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
76*4882a593Smuzhiyun
count_usb_devices(void)77*4882a593Smuzhiyun static int count_usb_devices(void)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun struct udevice *hub;
80*4882a593Smuzhiyun struct uclass *uc;
81*4882a593Smuzhiyun int count = 0;
82*4882a593Smuzhiyun int ret;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun ret = uclass_get(UCLASS_USB_HUB, &uc);
85*4882a593Smuzhiyun if (ret)
86*4882a593Smuzhiyun return ret;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun uclass_foreach_dev(hub, uc) {
89*4882a593Smuzhiyun struct udevice *dev;
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun count++;
92*4882a593Smuzhiyun for (device_find_first_child(hub, &dev);
93*4882a593Smuzhiyun dev;
94*4882a593Smuzhiyun device_find_next_child(&dev)) {
95*4882a593Smuzhiyun count++;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun return count;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun /* test that we can remove an emulated device and it is then not found */
dm_test_usb_remove(struct unit_test_state * uts)103*4882a593Smuzhiyun static int dm_test_usb_remove(struct unit_test_state *uts)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun struct udevice *dev, *emul;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun /* Scan and check that all devices are present */
108*4882a593Smuzhiyun state_set_skip_delays(true);
109*4882a593Smuzhiyun ut_assertok(usb_init());
110*4882a593Smuzhiyun ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
111*4882a593Smuzhiyun ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev));
112*4882a593Smuzhiyun ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev));
113*4882a593Smuzhiyun ut_asserteq(6, count_usb_devices());
114*4882a593Smuzhiyun ut_assertok(usb_stop());
115*4882a593Smuzhiyun ut_asserteq(6, count_usb_devices());
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun /* Remove the second emulation device */
118*4882a593Smuzhiyun ut_assertok(uclass_find_device_by_name(UCLASS_USB_EMUL, "flash-stick@1",
119*4882a593Smuzhiyun &dev));
120*4882a593Smuzhiyun ut_assertok(device_unbind(dev));
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun /* Rescan - only the first and third should be present */
123*4882a593Smuzhiyun ut_assertok(usb_init());
124*4882a593Smuzhiyun ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &dev));
125*4882a593Smuzhiyun ut_assertok(usb_emul_find_for_dev(dev, &emul));
126*4882a593Smuzhiyun ut_asserteq_str("flash-stick@0", emul->name);
127*4882a593Smuzhiyun ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 1, &dev));
128*4882a593Smuzhiyun ut_assertok(usb_emul_find_for_dev(dev, &emul));
129*4882a593Smuzhiyun ut_asserteq_str("flash-stick@2", emul->name);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun ut_asserteq(-ENODEV, uclass_get_device(UCLASS_MASS_STORAGE, 2, &dev));
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun ut_asserteq(5, count_usb_devices());
134*4882a593Smuzhiyun ut_assertok(usb_stop());
135*4882a593Smuzhiyun ut_asserteq(5, count_usb_devices());
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun return 0;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun DM_TEST(dm_test_usb_remove, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun const char usb_tree_base[] =
142*4882a593Smuzhiyun " 1 Hub (12 Mb/s, 100mA)\n"
143*4882a593Smuzhiyun " | sandbox hub 2345\n"
144*4882a593Smuzhiyun " |\n"
145*4882a593Smuzhiyun " |\b+-2 Mass Storage (12 Mb/s, 100mA)\n"
146*4882a593Smuzhiyun " | sandbox flash flash-stick@0\n"
147*4882a593Smuzhiyun " | \n"
148*4882a593Smuzhiyun " |\b+-3 Mass Storage (12 Mb/s, 100mA)\n"
149*4882a593Smuzhiyun " | sandbox flash flash-stick@1\n"
150*4882a593Smuzhiyun " | \n"
151*4882a593Smuzhiyun " |\b+-4 Mass Storage (12 Mb/s, 100mA)\n"
152*4882a593Smuzhiyun " | sandbox flash flash-stick@2\n"
153*4882a593Smuzhiyun " | \n"
154*4882a593Smuzhiyun " |\b+-5 Human Interface (12 Mb/s, 100mA)\n"
155*4882a593Smuzhiyun " sandbox keyboard keyb@3\n"
156*4882a593Smuzhiyun " \n";
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun /* test that the 'usb tree' command output looks correct */
dm_test_usb_tree(struct unit_test_state * uts)159*4882a593Smuzhiyun static int dm_test_usb_tree(struct unit_test_state *uts)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun char *data;
162*4882a593Smuzhiyun int len;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun state_set_skip_delays(true);
165*4882a593Smuzhiyun ut_assertok(usb_init());
166*4882a593Smuzhiyun console_record_reset_enable();
167*4882a593Smuzhiyun usb_show_tree();
168*4882a593Smuzhiyun len = membuff_getraw(&gd->console_out, -1, true, &data);
169*4882a593Smuzhiyun if (len)
170*4882a593Smuzhiyun data[len] = '\0';
171*4882a593Smuzhiyun ut_asserteq_str(usb_tree_base, data);
172*4882a593Smuzhiyun ut_assertok(usb_stop());
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun return 0;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun DM_TEST(dm_test_usb_tree, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun const char usb_tree_remove[] =
179*4882a593Smuzhiyun " 1 Hub (12 Mb/s, 100mA)\n"
180*4882a593Smuzhiyun " | sandbox hub 2345\n"
181*4882a593Smuzhiyun " |\n"
182*4882a593Smuzhiyun " |\b+-2 Mass Storage (12 Mb/s, 100mA)\n"
183*4882a593Smuzhiyun " | sandbox flash flash-stick@0\n"
184*4882a593Smuzhiyun " | \n"
185*4882a593Smuzhiyun " |\b+-3 Mass Storage (12 Mb/s, 100mA)\n"
186*4882a593Smuzhiyun " | sandbox flash flash-stick@2\n"
187*4882a593Smuzhiyun " | \n"
188*4882a593Smuzhiyun " |\b+-4 Human Interface (12 Mb/s, 100mA)\n"
189*4882a593Smuzhiyun " sandbox keyboard keyb@3\n"
190*4882a593Smuzhiyun " \n";
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun /*
193*4882a593Smuzhiyun * test that the 'usb tree' command output looks correct when we remove a
194*4882a593Smuzhiyun * device
195*4882a593Smuzhiyun */
dm_test_usb_tree_remove(struct unit_test_state * uts)196*4882a593Smuzhiyun static int dm_test_usb_tree_remove(struct unit_test_state *uts)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun struct udevice *dev;
199*4882a593Smuzhiyun char *data;
200*4882a593Smuzhiyun int len;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun /* Remove the second emulation device */
203*4882a593Smuzhiyun ut_assertok(uclass_find_device_by_name(UCLASS_USB_EMUL, "flash-stick@1",
204*4882a593Smuzhiyun &dev));
205*4882a593Smuzhiyun ut_assertok(device_unbind(dev));
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun state_set_skip_delays(true);
208*4882a593Smuzhiyun ut_assertok(usb_init());
209*4882a593Smuzhiyun console_record_reset_enable();
210*4882a593Smuzhiyun usb_show_tree();
211*4882a593Smuzhiyun len = membuff_getraw(&gd->console_out, -1, true, &data);
212*4882a593Smuzhiyun if (len)
213*4882a593Smuzhiyun data[len] = '\0';
214*4882a593Smuzhiyun ut_asserteq_str(usb_tree_remove, data);
215*4882a593Smuzhiyun ut_assertok(usb_stop());
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun return 0;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun DM_TEST(dm_test_usb_tree_remove, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun const char usb_tree_reorder[] =
222*4882a593Smuzhiyun " 1 Hub (12 Mb/s, 100mA)\n"
223*4882a593Smuzhiyun " | sandbox hub 2345\n"
224*4882a593Smuzhiyun " |\n"
225*4882a593Smuzhiyun " |\b+-2 Mass Storage (12 Mb/s, 100mA)\n"
226*4882a593Smuzhiyun " | sandbox flash flash-stick@0\n"
227*4882a593Smuzhiyun " | \n"
228*4882a593Smuzhiyun " |\b+-3 Mass Storage (12 Mb/s, 100mA)\n"
229*4882a593Smuzhiyun " | sandbox flash flash-stick@2\n"
230*4882a593Smuzhiyun " | \n"
231*4882a593Smuzhiyun " |\b+-4 Human Interface (12 Mb/s, 100mA)\n"
232*4882a593Smuzhiyun " | sandbox keyboard keyb@3\n"
233*4882a593Smuzhiyun " | \n"
234*4882a593Smuzhiyun " |\b+-5 Mass Storage (12 Mb/s, 100mA)\n"
235*4882a593Smuzhiyun " sandbox flash flash-stick@1\n"
236*4882a593Smuzhiyun " \n";
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun /*
239*4882a593Smuzhiyun * test that the 'usb tree' command output looks correct when we reorder two
240*4882a593Smuzhiyun * devices.
241*4882a593Smuzhiyun */
dm_test_usb_tree_reorder(struct unit_test_state * uts)242*4882a593Smuzhiyun static int dm_test_usb_tree_reorder(struct unit_test_state *uts)
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun struct udevice *dev, *parent;
245*4882a593Smuzhiyun char *data;
246*4882a593Smuzhiyun int len;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun /* Remove the second emulation device */
249*4882a593Smuzhiyun ut_assertok(uclass_find_device_by_name(UCLASS_USB_EMUL, "flash-stick@1",
250*4882a593Smuzhiyun &dev));
251*4882a593Smuzhiyun parent = dev->parent;
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun /* Reorder the devices in the parent list and uclass list */
254*4882a593Smuzhiyun list_del(&dev->sibling_node);
255*4882a593Smuzhiyun list_add_tail(&dev->sibling_node, &parent->child_head);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun list_del(&dev->uclass_node);
258*4882a593Smuzhiyun list_add_tail(&dev->uclass_node, &dev->uclass->dev_head);
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun state_set_skip_delays(true);
261*4882a593Smuzhiyun ut_assertok(usb_init());
262*4882a593Smuzhiyun console_record_reset_enable();
263*4882a593Smuzhiyun usb_show_tree();
264*4882a593Smuzhiyun len = membuff_getraw(&gd->console_out, -1, true, &data);
265*4882a593Smuzhiyun if (len)
266*4882a593Smuzhiyun data[len] = '\0';
267*4882a593Smuzhiyun ut_asserteq_str(usb_tree_reorder, data);
268*4882a593Smuzhiyun ut_assertok(usb_stop());
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun return 0;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun DM_TEST(dm_test_usb_tree_reorder, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
273*4882a593Smuzhiyun
dm_test_usb_keyb(struct unit_test_state * uts)274*4882a593Smuzhiyun static int dm_test_usb_keyb(struct unit_test_state *uts)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun struct udevice *dev;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun state_set_skip_delays(true);
279*4882a593Smuzhiyun ut_assertok(usb_init());
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun /* Initially there should be no characters */
282*4882a593Smuzhiyun ut_asserteq(0, tstc());
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun ut_assertok(uclass_get_device_by_name(UCLASS_USB_EMUL, "keyb",
285*4882a593Smuzhiyun &dev));
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun /*
288*4882a593Smuzhiyun * Add a string to the USB keyboard buffer - it should appear in
289*4882a593Smuzhiyun * stdin
290*4882a593Smuzhiyun */
291*4882a593Smuzhiyun ut_assertok(sandbox_usb_keyb_add_string(dev, "ab"));
292*4882a593Smuzhiyun ut_asserteq(1, tstc());
293*4882a593Smuzhiyun ut_asserteq('a', getc());
294*4882a593Smuzhiyun ut_asserteq(1, tstc());
295*4882a593Smuzhiyun ut_asserteq('b', getc());
296*4882a593Smuzhiyun ut_asserteq(0, tstc());
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun ut_assertok(usb_stop());
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun return 0;
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun DM_TEST(dm_test_usb_keyb, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
303