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