1 /* 2 * (C) Copyright 2015 Google, Inc 3 * Written by Simon Glass <sjg@chromium.org> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <dm.h> 10 #include <usb.h> 11 #include <dm/root.h> 12 13 DECLARE_GLOBAL_DATA_PTR; 14 15 struct sandbox_usb_ctrl { 16 int rootdev; 17 }; 18 19 static void usbmon_trace(struct udevice *bus, ulong pipe, 20 struct devrequest *setup, struct udevice *emul) 21 { 22 static const char types[] = "ZICB"; 23 int type; 24 25 type = (pipe & USB_PIPE_TYPE_MASK) >> USB_PIPE_TYPE_SHIFT; 26 debug("0 0 S %c%c:%d:%03ld:%ld", types[type], 27 pipe & USB_DIR_IN ? 'i' : 'o', 28 bus->seq, 29 (pipe & USB_PIPE_DEV_MASK) >> USB_PIPE_DEV_SHIFT, 30 (pipe & USB_PIPE_EP_MASK) >> USB_PIPE_EP_SHIFT); 31 if (setup) { 32 debug(" s %02x %02x %04x %04x %04x", setup->requesttype, 33 setup->request, setup->value, setup->index, 34 setup->length); 35 } 36 debug(" %s", emul ? emul->name : "(no emul found)"); 37 38 debug("\n"); 39 } 40 41 static int sandbox_submit_control(struct udevice *bus, 42 struct usb_device *udev, 43 unsigned long pipe, 44 void *buffer, int length, 45 struct devrequest *setup) 46 { 47 struct sandbox_usb_ctrl *ctrl = dev_get_priv(bus); 48 struct udevice *emul; 49 int ret; 50 51 /* Just use child of dev as emulator? */ 52 debug("%s: bus=%s\n", __func__, bus->name); 53 ret = usb_emul_find(bus, pipe, udev->portnr, &emul); 54 usbmon_trace(bus, pipe, setup, emul); 55 if (ret) 56 return ret; 57 58 if (usb_pipedevice(pipe) == ctrl->rootdev) { 59 if (setup->request == USB_REQ_SET_ADDRESS) { 60 debug("%s: Set root hub's USB address\n", __func__); 61 ctrl->rootdev = le16_to_cpu(setup->value); 62 } 63 } 64 65 ret = usb_emul_control(emul, udev, pipe, buffer, length, setup); 66 if (ret < 0) { 67 debug("ret=%d\n", ret); 68 udev->status = ret; 69 udev->act_len = 0; 70 } else { 71 udev->status = 0; 72 udev->act_len = ret; 73 } 74 75 return ret; 76 } 77 78 static int sandbox_submit_bulk(struct udevice *bus, struct usb_device *udev, 79 unsigned long pipe, void *buffer, int length) 80 { 81 struct udevice *emul; 82 int ret; 83 84 /* Just use child of dev as emulator? */ 85 debug("%s: bus=%s\n", __func__, bus->name); 86 ret = usb_emul_find(bus, pipe, udev->portnr, &emul); 87 usbmon_trace(bus, pipe, NULL, emul); 88 if (ret) 89 return ret; 90 ret = usb_emul_bulk(emul, udev, pipe, buffer, length); 91 if (ret < 0) { 92 debug("ret=%d\n", ret); 93 udev->status = ret; 94 udev->act_len = 0; 95 } else { 96 udev->status = 0; 97 udev->act_len = ret; 98 } 99 100 return ret; 101 } 102 103 static int sandbox_submit_int(struct udevice *bus, struct usb_device *udev, 104 unsigned long pipe, void *buffer, int length, 105 int interval) 106 { 107 struct udevice *emul; 108 int ret; 109 110 /* Just use child of dev as emulator? */ 111 debug("%s: bus=%s\n", __func__, bus->name); 112 ret = usb_emul_find(bus, pipe, udev->portnr, &emul); 113 usbmon_trace(bus, pipe, NULL, emul); 114 if (ret) 115 return ret; 116 ret = usb_emul_int(emul, udev, pipe, buffer, length, interval); 117 118 return ret; 119 } 120 121 static int sandbox_alloc_device(struct udevice *dev, struct usb_device *udev) 122 { 123 struct sandbox_usb_ctrl *ctrl = dev_get_priv(dev); 124 125 /* 126 * Root hub will be the first device to be initailized. 127 * If this device is a root hub, initialize its device speed 128 * to high speed as we are a USB 2.0 controller. 129 */ 130 if (ctrl->rootdev == 0) 131 udev->speed = USB_SPEED_HIGH; 132 133 return 0; 134 } 135 136 static int sandbox_usb_probe(struct udevice *dev) 137 { 138 return 0; 139 } 140 141 static const struct dm_usb_ops sandbox_usb_ops = { 142 .control = sandbox_submit_control, 143 .bulk = sandbox_submit_bulk, 144 .interrupt = sandbox_submit_int, 145 .alloc_device = sandbox_alloc_device, 146 }; 147 148 static const struct udevice_id sandbox_usb_ids[] = { 149 { .compatible = "sandbox,usb" }, 150 { } 151 }; 152 153 U_BOOT_DRIVER(usb_sandbox) = { 154 .name = "usb_sandbox", 155 .id = UCLASS_USB, 156 .of_match = sandbox_usb_ids, 157 .probe = sandbox_usb_probe, 158 .ops = &sandbox_usb_ops, 159 .priv_auto_alloc_size = sizeof(struct sandbox_usb_ctrl), 160 }; 161