usb: Add mutex to usb_enable
The purpose of this commit is to prevent user from
calling usb_enable() twice from different contexes.
If for example user configures composite device with hid
and USB uart console (CONFIG_USB_UART_CONSOLE=y)
then introduced mutex will prevent from calling
usb_enable twice and thus lead to undefined behaviour of
usb driver controller.
usb_enable shall always be called once as it refers to usb driver
and for now only one USB driver instance is supported in Zephyr.
This mechanism ensures that.
Signed-off-by: Emil Obalski <emil.obalski@nordicsemi.no>
diff --git a/subsys/usb/usb_device.c b/subsys/usb/usb_device.c
index 0a7fba6..6cbda2c 100644
--- a/subsys/usb/usb_device.c
+++ b/subsys/usb/usb_device.c
@@ -110,6 +110,8 @@
extern struct usb_cfg_data __usb_data_start[];
extern struct usb_cfg_data __usb_data_end[];
+K_MUTEX_DEFINE(usb_enable_lock);
+
struct usb_transfer_data {
/** endpoint associated to the transfer */
u8_t ep;
@@ -1537,14 +1539,21 @@
u32_t i;
struct usb_dc_ep_cfg_data ep0_cfg;
+ /* Prevent from calling usb_enable form different contex.
+ * This should only be called once.
+ */
+ LOG_DBG("lock usb_enable_lock mutex");
+ k_mutex_lock(&usb_enable_lock, K_FOREVER);
+
if (usb_dev.enabled == true) {
- return 0;
+ ret = 0;
+ goto out;
}
/* Enable VBUS if needed */
ret = usb_vbus_set(true);
if (ret < 0) {
- return ret;
+ goto out;
}
usb_register_status_callback(forward_status_cb);
@@ -1552,7 +1561,7 @@
ret = usb_dc_attach();
if (ret < 0) {
- return ret;
+ goto out;
}
/* Configure control EP */
@@ -1562,32 +1571,32 @@
ep0_cfg.ep_addr = USB_CONTROL_OUT_EP0;
ret = usb_dc_ep_configure(&ep0_cfg);
if (ret < 0) {
- return ret;
+ goto out;
}
ep0_cfg.ep_addr = USB_CONTROL_IN_EP0;
ret = usb_dc_ep_configure(&ep0_cfg);
if (ret < 0) {
- return ret;
+ goto out;
}
/* Register endpoint 0 handlers*/
ret = usb_dc_ep_set_callback(USB_CONTROL_OUT_EP0,
usb_handle_control_transfer);
if (ret < 0) {
- return ret;
+ goto out;
}
ret = usb_dc_ep_set_callback(USB_CONTROL_IN_EP0,
usb_handle_control_transfer);
if (ret < 0) {
- return ret;
+ goto out;
}
/* Register endpoint handlers*/
ret = composite_setup_ep_cb();
if (ret < 0) {
- return ret;
+ goto out;
}
/* Init transfer slots */
@@ -1599,17 +1608,20 @@
/* Enable control EP */
ret = usb_dc_ep_enable(USB_CONTROL_OUT_EP0);
if (ret < 0) {
- return ret;
+ goto out;
}
ret = usb_dc_ep_enable(USB_CONTROL_IN_EP0);
if (ret < 0) {
- return ret;
+ goto out;
}
usb_dev.enabled = true;
-
- return 0;
+ ret = 0;
+out:
+ LOG_DBG("unlock usb_enable_lock mutex");
+ k_mutex_unlock(&usb_enable_lock);
+ return ret;
}
/*