1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2015 Google, Inc 4 * Written by Simon Glass <sjg@chromium.org> 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <os.h> 10 #include <scsi.h> 11 #include <usb.h> 12 13 /* 14 * This driver emulates a USB keyboard using the USB HID specification (boot 15 * protocol) 16 */ 17 18 enum { 19 SANDBOX_KEYB_EP_IN = 1, /* endpoints */ 20 }; 21 22 enum cmd_phase { 23 PHASE_START, 24 PHASE_DATA, 25 PHASE_STATUS, 26 }; 27 28 enum { 29 STRINGID_MANUFACTURER = 1, 30 STRINGID_PRODUCT, 31 STRINGID_SERIAL, 32 33 STRINGID_COUNT, 34 }; 35 36 /** 37 * struct sandbox_keyb_priv - private state for this driver 38 * 39 */ 40 struct sandbox_keyb_priv { 41 struct membuff in; 42 }; 43 44 struct sandbox_keyb_plat { 45 struct usb_string keyb_strings[STRINGID_COUNT]; 46 }; 47 48 static struct usb_device_descriptor keyb_device_desc = { 49 .bLength = sizeof(keyb_device_desc), 50 .bDescriptorType = USB_DT_DEVICE, 51 52 .bcdUSB = __constant_cpu_to_le16(0x0100), 53 54 .bDeviceClass = 0, 55 .bDeviceSubClass = 0, 56 .bDeviceProtocol = 0, 57 58 .idVendor = __constant_cpu_to_le16(0x1234), 59 .idProduct = __constant_cpu_to_le16(0x5679), 60 .iManufacturer = STRINGID_MANUFACTURER, 61 .iProduct = STRINGID_PRODUCT, 62 .iSerialNumber = STRINGID_SERIAL, 63 .bNumConfigurations = 1, 64 }; 65 66 static struct usb_config_descriptor keyb_config0 = { 67 .bLength = sizeof(keyb_config0), 68 .bDescriptorType = USB_DT_CONFIG, 69 70 /* wTotalLength is set up by usb-emul-uclass */ 71 .bNumInterfaces = 2, 72 .bConfigurationValue = 0, 73 .iConfiguration = 0, 74 .bmAttributes = 1 << 7 | 1 << 5, 75 .bMaxPower = 50, 76 }; 77 78 static struct usb_interface_descriptor keyb_interface0 = { 79 .bLength = sizeof(keyb_interface0), 80 .bDescriptorType = USB_DT_INTERFACE, 81 82 .bInterfaceNumber = 0, 83 .bAlternateSetting = 0, 84 .bNumEndpoints = 1, 85 .bInterfaceClass = USB_CLASS_HID, 86 .bInterfaceSubClass = USB_SUB_HID_BOOT, 87 .bInterfaceProtocol = USB_PROT_HID_KEYBOARD, 88 .iInterface = 0, 89 }; 90 91 static struct usb_class_hid_descriptor keyb_report0 = { 92 .bLength = sizeof(keyb_report0), 93 .bDescriptorType = USB_DT_HID, 94 .bcdCDC = 0x101, 95 .bCountryCode = 0, 96 .bNumDescriptors = 1, 97 .bDescriptorType0 = USB_DT_HID_REPORT, 98 .wDescriptorLength0 = 0x3f, 99 }; 100 101 static struct usb_endpoint_descriptor keyb_endpoint0_in = { 102 .bLength = USB_DT_ENDPOINT_SIZE, 103 .bDescriptorType = USB_DT_ENDPOINT, 104 105 .bEndpointAddress = SANDBOX_KEYB_EP_IN | USB_ENDPOINT_DIR_MASK, 106 .bmAttributes = USB_ENDPOINT_XFER_BULK | 107 USB_ENDPOINT_XFER_ISOC, 108 .wMaxPacketSize = __constant_cpu_to_le16(8), 109 .bInterval = 0xa, 110 }; 111 112 static struct usb_interface_descriptor keyb_interface1 = { 113 .bLength = sizeof(keyb_interface1), 114 .bDescriptorType = USB_DT_INTERFACE, 115 116 .bInterfaceNumber = 1, 117 .bAlternateSetting = 0, 118 .bNumEndpoints = 1, 119 .bInterfaceClass = USB_CLASS_HID, 120 .bInterfaceSubClass = USB_SUB_HID_BOOT, 121 .bInterfaceProtocol = USB_PROT_HID_MOUSE, 122 .iInterface = 0, 123 }; 124 125 static struct usb_class_hid_descriptor keyb_report1 = { 126 .bLength = sizeof(struct usb_class_hid_descriptor), 127 .bDescriptorType = USB_DT_HID, 128 .bcdCDC = 0x101, 129 .bCountryCode = 0, 130 .bNumDescriptors = 1, 131 .bDescriptorType0 = USB_DT_HID_REPORT, 132 .wDescriptorLength0 = 0x32, 133 }; 134 135 static struct usb_endpoint_descriptor keyb_endpoint1_in = { 136 .bLength = USB_DT_ENDPOINT_SIZE, 137 .bDescriptorType = USB_DT_ENDPOINT, 138 139 .bEndpointAddress = SANDBOX_KEYB_EP_IN | USB_ENDPOINT_DIR_MASK, 140 .bmAttributes = USB_ENDPOINT_XFER_BULK | 141 USB_ENDPOINT_XFER_ISOC, 142 .wMaxPacketSize = __constant_cpu_to_le16(8), 143 .bInterval = 0xa, 144 }; 145 146 static void *keyb_desc_list[] = { 147 &keyb_device_desc, 148 &keyb_config0, 149 &keyb_interface0, 150 &keyb_report0, 151 &keyb_endpoint0_in, 152 &keyb_interface1, 153 &keyb_report1, 154 &keyb_endpoint1_in, 155 NULL, 156 }; 157 158 int sandbox_usb_keyb_add_string(struct udevice *dev, const char *str) 159 { 160 struct sandbox_keyb_priv *priv = dev_get_priv(dev); 161 int len, ret; 162 163 len = strlen(str); 164 ret = membuff_put(&priv->in, str, len); 165 if (ret != len) 166 return -ENOSPC; 167 168 return 0; 169 } 170 171 static int sandbox_keyb_control(struct udevice *dev, struct usb_device *udev, 172 unsigned long pipe, void *buff, int len, 173 struct devrequest *setup) 174 { 175 debug("pipe=%lx\n", pipe); 176 177 return -EIO; 178 } 179 180 static int sandbox_keyb_interrupt(struct udevice *dev, struct usb_device *udev, 181 unsigned long pipe, void *buffer, int length, int interval) 182 { 183 struct sandbox_keyb_priv *priv = dev_get_priv(dev); 184 uint8_t *data = buffer; 185 int ch; 186 187 memset(data, '\0', length); 188 ch = membuff_getbyte(&priv->in); 189 if (ch != -1) 190 data[2] = 4 + ch - 'a'; 191 192 return 0; 193 } 194 195 static int sandbox_keyb_bind(struct udevice *dev) 196 { 197 struct sandbox_keyb_plat *plat = dev_get_platdata(dev); 198 struct usb_string *fs; 199 200 fs = plat->keyb_strings; 201 fs[0].id = STRINGID_MANUFACTURER; 202 fs[0].s = "sandbox"; 203 fs[1].id = STRINGID_PRODUCT; 204 fs[1].s = "keyboard"; 205 fs[2].id = STRINGID_SERIAL; 206 fs[2].s = dev->name; 207 208 return usb_emul_setup_device(dev, plat->keyb_strings, keyb_desc_list); 209 } 210 211 static int sandbox_keyb_probe(struct udevice *dev) 212 { 213 struct sandbox_keyb_priv *priv = dev_get_priv(dev); 214 215 return membuff_new(&priv->in, 256); 216 } 217 218 static const struct dm_usb_ops sandbox_usb_keyb_ops = { 219 .control = sandbox_keyb_control, 220 .interrupt = sandbox_keyb_interrupt, 221 }; 222 223 static const struct udevice_id sandbox_usb_keyb_ids[] = { 224 { .compatible = "sandbox,usb-keyb" }, 225 { } 226 }; 227 228 U_BOOT_DRIVER(usb_sandbox_keyb) = { 229 .name = "usb_sandbox_keyb", 230 .id = UCLASS_USB_EMUL, 231 .of_match = sandbox_usb_keyb_ids, 232 .bind = sandbox_keyb_bind, 233 .probe = sandbox_keyb_probe, 234 .ops = &sandbox_usb_keyb_ops, 235 .priv_auto_alloc_size = sizeof(struct sandbox_keyb_priv), 236 .platdata_auto_alloc_size = sizeof(struct sandbox_keyb_plat), 237 }; 238