1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /*
8  * USB device controller (UDC) driver skeleton
9  *
10  * This is a skeleton for a device controller driver using the UDC API.
11  * Please use it as a starting point for a driver implementation for your
12  * USB device controller. Maintaining a common style, terminology and
13  * abbreviations will allow us to speed up reviews and reduce maintenance.
14  * Copy UDC driver skeleton, remove all unrelated comments and replace the
15  * copyright notice with your own.
16  *
17  * Typically, a driver implementation contains only a single source file,
18  * but the large list of e.g. register definitions should be in a separate
19  * .h file.
20  *
21  * If you want to define a helper macro, check if there is something similar
22  * in include/zephyr/sys/util.h or include/zephyr/usb/usb_ch9.h that you can use.
23  * Please keep all identifiers and logging messages concise and clear.
24  */
25 
26 #include "udc_common.h"
27 
28 #include <string.h>
29 #include <stdio.h>
30 
31 #include <zephyr/kernel.h>
32 #include <zephyr/drivers/usb/udc.h>
33 
34 #include <zephyr/logging/log.h>
35 LOG_MODULE_REGISTER(udc_skeleton, CONFIG_UDC_DRIVER_LOG_LEVEL);
36 
37 /*
38  * Structure for holding controller configuration items that can remain in
39  * non-volatile memory. This is usually accessed as
40  *   const struct udc_skeleton_config *config = dev->config;
41  */
42 struct udc_skeleton_config {
43 	size_t num_of_eps;
44 	struct udc_ep_config *ep_cfg_in;
45 	struct udc_ep_config *ep_cfg_out;
46 	void (*make_thread)(const struct device *dev);
47 	int speed_idx;
48 };
49 
50 /*
51  * Structure to hold driver private data.
52  * Note that this is not accessible via dev->data, but as
53  *   struct udc_skeleton_data *priv = udc_get_private(dev);
54  */
55 struct udc_skeleton_data {
56 	struct k_thread thread_data;
57 };
58 
59 /*
60  * You can use one thread per driver instance model or UDC driver workqueue,
61  * whichever model suits your needs best. If you decide to use the UDC workqueue,
62  * enable Kconfig option UDC_WORKQUEUE and remove the handler below and
63  * caller from the UDC_SKELETON_DEVICE_DEFINE macro.
64  */
skeleton_thread_handler(void * const arg)65 static ALWAYS_INLINE void skeleton_thread_handler(void *const arg)
66 {
67 	const struct device *dev = (const struct device *)arg;
68 
69 	LOG_DBG("Driver %p thread started", dev);
70 	while (true) {
71 		k_msleep(1000);
72 	}
73 }
74 
75 /*
76  * This is called in the context of udc_ep_enqueue() and must
77  * not block. The driver can immediately claim the buffer if the queue is empty,
78  * but usually it is offloaded to a thread or workqueue to handle transfers
79  * in a single location. Please refer to existing driver implementations
80  * for examples.
81  */
udc_skeleton_ep_enqueue(const struct device * dev,struct udc_ep_config * const cfg,struct net_buf * buf)82 static int udc_skeleton_ep_enqueue(const struct device *dev,
83 				   struct udc_ep_config *const cfg,
84 				   struct net_buf *buf)
85 {
86 	LOG_DBG("%p enqueue %p", dev, buf);
87 	udc_buf_put(cfg, buf);
88 
89 	if (cfg->stat.halted) {
90 		/*
91 		 * It is fine to enqueue a transfer for a halted endpoint,
92 		 * you need to make sure that transfers are retriggered when
93 		 * the halt is cleared.
94 		 *
95 		 * Always use the abbreviation 'ep' for the endpoint address
96 		 * and 'ep_idx' or 'ep_num' for the endpoint number identifiers.
97 		 * Although struct udc_ep_config uses address to be unambiguous
98 		 * in its context.
99 		 */
100 		LOG_DBG("ep 0x%02x halted", cfg->addr);
101 		return 0;
102 	}
103 
104 	return 0;
105 }
106 
107 /*
108  * This is called in the context of udc_ep_dequeue()
109  * and must remove all requests from an endpoint queue
110  * Successful removal should be reported to the higher level with
111  * ECONNABORTED as the request result.
112  * It is up to the request owner to clean up or reuse the buffer.
113  */
udc_skeleton_ep_dequeue(const struct device * dev,struct udc_ep_config * const cfg)114 static int udc_skeleton_ep_dequeue(const struct device *dev,
115 				   struct udc_ep_config *const cfg)
116 {
117 	unsigned int lock_key;
118 	struct net_buf *buf;
119 
120 	lock_key = irq_lock();
121 
122 	buf = udc_buf_get_all(dev, cfg->addr);
123 	if (buf) {
124 		udc_submit_ep_event(dev, buf, -ECONNABORTED);
125 	}
126 
127 	irq_unlock(lock_key);
128 
129 	return 0;
130 }
131 
132 /*
133  * Configure and make an endpoint ready for use.
134  * This is called in the context of udc_ep_enable() or udc_ep_enable_internal(),
135  * the latter of which may be used by the driver to enable control endpoints.
136  */
udc_skeleton_ep_enable(const struct device * dev,struct udc_ep_config * const cfg)137 static int udc_skeleton_ep_enable(const struct device *dev,
138 				  struct udc_ep_config *const cfg)
139 {
140 	LOG_DBG("Enable ep 0x%02x", cfg->addr);
141 
142 	return 0;
143 }
144 
145 /*
146  * Opposite function to udc_skeleton_ep_enable(). udc_ep_disable_internal()
147  * may be used by the driver to disable control endpoints.
148  */
udc_skeleton_ep_disable(const struct device * dev,struct udc_ep_config * const cfg)149 static int udc_skeleton_ep_disable(const struct device *dev,
150 				   struct udc_ep_config *const cfg)
151 {
152 	LOG_DBG("Disable ep 0x%02x", cfg->addr);
153 
154 	return 0;
155 }
156 
157 /* Halt endpoint. Halted endpoint should respond with a STALL handshake. */
udc_skeleton_ep_set_halt(const struct device * dev,struct udc_ep_config * const cfg)158 static int udc_skeleton_ep_set_halt(const struct device *dev,
159 				    struct udc_ep_config *const cfg)
160 {
161 	LOG_DBG("Set halt ep 0x%02x", cfg->addr);
162 
163 	cfg->stat.halted = true;
164 
165 	return 0;
166 }
167 
168 /*
169  * Opposite to halt endpoint. If there are requests in the endpoint queue,
170  * the next transfer should be prepared.
171  */
udc_skeleton_ep_clear_halt(const struct device * dev,struct udc_ep_config * const cfg)172 static int udc_skeleton_ep_clear_halt(const struct device *dev,
173 				      struct udc_ep_config *const cfg)
174 {
175 	LOG_DBG("Clear halt ep 0x%02x", cfg->addr);
176 	cfg->stat.halted = false;
177 
178 	return 0;
179 }
180 
udc_skeleton_set_address(const struct device * dev,const uint8_t addr)181 static int udc_skeleton_set_address(const struct device *dev, const uint8_t addr)
182 {
183 	LOG_DBG("Set new address %u for %p", addr, dev);
184 
185 	return 0;
186 }
187 
udc_skeleton_host_wakeup(const struct device * dev)188 static int udc_skeleton_host_wakeup(const struct device *dev)
189 {
190 	LOG_DBG("Remote wakeup from %p", dev);
191 
192 	return 0;
193 }
194 
195 /* Return actual USB device speed */
udc_skeleton_device_speed(const struct device * dev)196 static enum udc_bus_speed udc_skeleton_device_speed(const struct device *dev)
197 {
198 	struct udc_data *data = dev->data;
199 
200 	return data->caps.hs ? UDC_BUS_SPEED_HS : UDC_BUS_SPEED_FS;
201 }
202 
udc_skeleton_enable(const struct device * dev)203 static int udc_skeleton_enable(const struct device *dev)
204 {
205 	LOG_DBG("Enable device %p", dev);
206 
207 	return 0;
208 }
209 
udc_skeleton_disable(const struct device * dev)210 static int udc_skeleton_disable(const struct device *dev)
211 {
212 	LOG_DBG("Enable device %p", dev);
213 
214 	return 0;
215 }
216 
217 /*
218  * Prepare and configure most of the parts, if the controller has a way
219  * of detecting VBUS activity it should be enabled here.
220  * Only udc_skeleton_enable() makes device visible to the host.
221  */
udc_skeleton_init(const struct device * dev)222 static int udc_skeleton_init(const struct device *dev)
223 {
224 	if (udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT,
225 				   USB_EP_TYPE_CONTROL, 64, 0)) {
226 		LOG_ERR("Failed to enable control endpoint");
227 		return -EIO;
228 	}
229 
230 	if (udc_ep_enable_internal(dev, USB_CONTROL_EP_IN,
231 				   USB_EP_TYPE_CONTROL, 64, 0)) {
232 		LOG_ERR("Failed to enable control endpoint");
233 		return -EIO;
234 	}
235 
236 	return 0;
237 }
238 
239 /* Shut down the controller completely */
udc_skeleton_shutdown(const struct device * dev)240 static int udc_skeleton_shutdown(const struct device *dev)
241 {
242 	if (udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT)) {
243 		LOG_ERR("Failed to disable control endpoint");
244 		return -EIO;
245 	}
246 
247 	if (udc_ep_disable_internal(dev, USB_CONTROL_EP_IN)) {
248 		LOG_ERR("Failed to disable control endpoint");
249 		return -EIO;
250 	}
251 
252 	return 0;
253 }
254 
255 /*
256  * This is called once to initialize the controller and endpoints
257  * capabilities, and register endpoint structures.
258  */
udc_skeleton_driver_preinit(const struct device * dev)259 static int udc_skeleton_driver_preinit(const struct device *dev)
260 {
261 	const struct udc_skeleton_config *config = dev->config;
262 	struct udc_data *data = dev->data;
263 	uint16_t mps = 1023;
264 	int err;
265 
266 	/*
267 	 * You do not need to initialize it if your driver does not use
268 	 * udc_lock_internal() / udc_unlock_internal(), but implements its
269 	 * own mechanism.
270 	 */
271 	k_mutex_init(&data->mutex);
272 
273 	data->caps.rwup = true;
274 	data->caps.mps0 = UDC_MPS0_64;
275 	if (config->speed_idx == 2) {
276 		data->caps.hs = true;
277 		mps = 1024;
278 	}
279 
280 	for (int i = 0; i < config->num_of_eps; i++) {
281 		config->ep_cfg_out[i].caps.out = 1;
282 		if (i == 0) {
283 			config->ep_cfg_out[i].caps.control = 1;
284 			config->ep_cfg_out[i].caps.mps = 64;
285 		} else {
286 			config->ep_cfg_out[i].caps.bulk = 1;
287 			config->ep_cfg_out[i].caps.interrupt = 1;
288 			config->ep_cfg_out[i].caps.iso = 1;
289 			config->ep_cfg_out[i].caps.mps = mps;
290 		}
291 
292 		config->ep_cfg_out[i].addr = USB_EP_DIR_OUT | i;
293 		err = udc_register_ep(dev, &config->ep_cfg_out[i]);
294 		if (err != 0) {
295 			LOG_ERR("Failed to register endpoint");
296 			return err;
297 		}
298 	}
299 
300 	for (int i = 0; i < config->num_of_eps; i++) {
301 		config->ep_cfg_in[i].caps.in = 1;
302 		if (i == 0) {
303 			config->ep_cfg_in[i].caps.control = 1;
304 			config->ep_cfg_in[i].caps.mps = 64;
305 		} else {
306 			config->ep_cfg_in[i].caps.bulk = 1;
307 			config->ep_cfg_in[i].caps.interrupt = 1;
308 			config->ep_cfg_in[i].caps.iso = 1;
309 			config->ep_cfg_in[i].caps.mps = mps;
310 		}
311 
312 		config->ep_cfg_in[i].addr = USB_EP_DIR_IN | i;
313 		err = udc_register_ep(dev, &config->ep_cfg_in[i]);
314 		if (err != 0) {
315 			LOG_ERR("Failed to register endpoint");
316 			return err;
317 		}
318 	}
319 
320 	config->make_thread(dev);
321 	LOG_INF("Device %p (max. speed %d)", dev, config->speed_idx);
322 
323 	return 0;
324 }
325 
udc_skeleton_lock(const struct device * dev)326 static int udc_skeleton_lock(const struct device *dev)
327 {
328 	return udc_lock_internal(dev, K_FOREVER);
329 }
330 
udc_skeleton_unlock(const struct device * dev)331 static int udc_skeleton_unlock(const struct device *dev)
332 {
333 	return udc_unlock_internal(dev);
334 }
335 
336 /*
337  * UDC API structure.
338  * Note, you do not need to implement basic checks, these are done by
339  * the UDC common layer udc_common.c
340  */
341 static const struct udc_api udc_skeleton_api = {
342 	.lock = udc_skeleton_lock,
343 	.unlock = udc_skeleton_unlock,
344 	.device_speed = udc_skeleton_device_speed,
345 	.init = udc_skeleton_init,
346 	.enable = udc_skeleton_enable,
347 	.disable = udc_skeleton_disable,
348 	.shutdown = udc_skeleton_shutdown,
349 	.set_address = udc_skeleton_set_address,
350 	.host_wakeup = udc_skeleton_host_wakeup,
351 	.ep_enable = udc_skeleton_ep_enable,
352 	.ep_disable = udc_skeleton_ep_disable,
353 	.ep_set_halt = udc_skeleton_ep_set_halt,
354 	.ep_clear_halt = udc_skeleton_ep_clear_halt,
355 	.ep_enqueue = udc_skeleton_ep_enqueue,
356 	.ep_dequeue = udc_skeleton_ep_dequeue,
357 };
358 
359 #define DT_DRV_COMPAT zephyr_udc_skeleton
360 
361 /*
362  * A UDC driver should always be implemented as a multi-instance
363  * driver, even if your platform does not require it.
364  */
365 #define UDC_SKELETON_DEVICE_DEFINE(n)						\
366 	K_THREAD_STACK_DEFINE(udc_skeleton_stack_##n, CONFIG_UDC_SKELETON);	\
367 										\
368 	static void udc_skeleton_thread_##n(void *dev, void *arg1, void *arg2)	\
369 	{									\
370 		skeleton_thread_handler(dev);					\
371 	}									\
372 										\
373 	static void udc_skeleton_make_thread_##n(const struct device *dev)	\
374 	{									\
375 		struct udc_skeleton_data *priv = udc_get_private(dev);		\
376 										\
377 		k_thread_create(&priv->thread_data,				\
378 				udc_skeleton_stack_##n,				\
379 				K_THREAD_STACK_SIZEOF(udc_skeleton_stack_##n),	\
380 				udc_skeleton_thread_##n,			\
381 				(void *)dev, NULL, NULL,			\
382 				K_PRIO_COOP(CONFIG_UDC_SKELETON_THREAD_PRIORITY),\
383 				K_ESSENTIAL,					\
384 				K_NO_WAIT);					\
385 		k_thread_name_set(&priv->thread_data, dev->name);		\
386 	}									\
387 										\
388 	static struct udc_ep_config						\
389 		ep_cfg_out[DT_INST_PROP(n, num_bidir_endpoints)];		\
390 	static struct udc_ep_config						\
391 		ep_cfg_in[DT_INST_PROP(n, num_bidir_endpoints)];		\
392 										\
393 	static const struct udc_skeleton_config udc_skeleton_config_##n = {	\
394 		.num_of_eps = DT_INST_PROP(n, num_bidir_endpoints),		\
395 		.ep_cfg_in = ep_cfg_out,					\
396 		.ep_cfg_out = ep_cfg_in,					\
397 		.make_thread = udc_skeleton_make_thread_##n,			\
398 		.speed_idx = DT_ENUM_IDX(DT_DRV_INST(n), maximum_speed),	\
399 	};									\
400 										\
401 	static struct udc_skeleton_data udc_priv_##n = {			\
402 	};									\
403 										\
404 	static struct udc_data udc_data_##n = {					\
405 		.mutex = Z_MUTEX_INITIALIZER(udc_data_##n.mutex),		\
406 		.priv = &udc_priv_##n,						\
407 	};									\
408 										\
409 	DEVICE_DT_INST_DEFINE(n, udc_skeleton_driver_preinit, NULL,		\
410 			      &udc_data_##n, &udc_skeleton_config_##n,		\
411 			      POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,	\
412 			      &udc_skeleton_api);
413 
414 DT_INST_FOREACH_STATUS_OKAY(UDC_SKELETON_DEVICE_DEFINE)
415