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 <log.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 /**
160  * sandbox_usb_keyb_add_string() - provide a USB scancode buffer
161  *
162  * @dev:	the keyboard emulation device
163  * @scancode:	scancode buffer with USB_KBD_BOOT_REPORT_SIZE bytes
164  */
sandbox_usb_keyb_add_string(struct udevice * dev,const char scancode[USB_KBD_BOOT_REPORT_SIZE])165 int sandbox_usb_keyb_add_string(struct udevice *dev,
166 				const char scancode[USB_KBD_BOOT_REPORT_SIZE])
167 {
168 	struct sandbox_keyb_priv *priv = dev_get_priv(dev);
169 	int ret;
170 
171 	ret = membuff_put(&priv->in, scancode, USB_KBD_BOOT_REPORT_SIZE);
172 	if (ret != USB_KBD_BOOT_REPORT_SIZE)
173 		return -ENOSPC;
174 
175 	return 0;
176 }
177 
sandbox_keyb_control(struct udevice * dev,struct usb_device * udev,unsigned long pipe,void * buff,int len,struct devrequest * setup)178 static int sandbox_keyb_control(struct udevice *dev, struct usb_device *udev,
179 				unsigned long pipe, void *buff, int len,
180 				struct devrequest *setup)
181 {
182 	debug("pipe=%lx\n", pipe);
183 
184 	return -EIO;
185 }
186 
sandbox_keyb_interrupt(struct udevice * dev,struct usb_device * udev,unsigned long pipe,void * buffer,int length,int interval,bool nonblock)187 static int sandbox_keyb_interrupt(struct udevice *dev, struct usb_device *udev,
188 		unsigned long pipe, void *buffer, int length, int interval,
189 		bool nonblock)
190 {
191 	struct sandbox_keyb_priv *priv = dev_get_priv(dev);
192 	uint8_t *data = buffer;
193 
194 	memset(data, '\0', length);
195 	if (length < USB_KBD_BOOT_REPORT_SIZE)
196 		return 0;
197 
198 	membuff_get(&priv->in, buffer, USB_KBD_BOOT_REPORT_SIZE);
199 
200 	return 0;
201 }
202 
sandbox_keyb_bind(struct udevice * dev)203 static int sandbox_keyb_bind(struct udevice *dev)
204 {
205 	struct sandbox_keyb_plat *plat = dev_get_plat(dev);
206 	struct usb_string *fs;
207 
208 	fs = plat->keyb_strings;
209 	fs[0].id = STRINGID_MANUFACTURER;
210 	fs[0].s = "sandbox";
211 	fs[1].id = STRINGID_PRODUCT;
212 	fs[1].s = "keyboard";
213 	fs[2].id = STRINGID_SERIAL;
214 	fs[2].s = dev->name;
215 
216 	return usb_emul_setup_device(dev, plat->keyb_strings, keyb_desc_list);
217 }
218 
sandbox_keyb_probe(struct udevice * dev)219 static int sandbox_keyb_probe(struct udevice *dev)
220 {
221 	struct sandbox_keyb_priv *priv = dev_get_priv(dev);
222 
223 	/* Provide an 80 character keyboard buffer */
224 	return membuff_new(&priv->in, 80 * USB_KBD_BOOT_REPORT_SIZE);
225 }
226 
227 static const struct dm_usb_ops sandbox_usb_keyb_ops = {
228 	.control	= sandbox_keyb_control,
229 	.interrupt	= sandbox_keyb_interrupt,
230 };
231 
232 static const struct udevice_id sandbox_usb_keyb_ids[] = {
233 	{ .compatible = "sandbox,usb-keyb" },
234 	{ }
235 };
236 
237 U_BOOT_DRIVER(usb_sandbox_keyb) = {
238 	.name	= "usb_sandbox_keyb",
239 	.id	= UCLASS_USB_EMUL,
240 	.of_match = sandbox_usb_keyb_ids,
241 	.bind	= sandbox_keyb_bind,
242 	.probe	= sandbox_keyb_probe,
243 	.ops	= &sandbox_usb_keyb_ops,
244 	.priv_auto	= sizeof(struct sandbox_keyb_priv),
245 	.plat_auto	= sizeof(struct sandbox_keyb_plat),
246 };
247