Commit e3619d50 authored by Emil Obalski's avatar Emil Obalski Committed by Carles Cufi
Browse files

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: default avatarEmil Obalski <emil.obalski@nordicsemi.no>
parent bc2ecad3
Loading
Loading
Loading
Loading
+24 −12
Original line number Diff line number Diff line
@@ -110,6 +110,8 @@ LOG_MODULE_REGISTER(usb_device);
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 @@ int usb_enable(void)
	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 @@ int usb_enable(void)

	ret = usb_dc_attach();
	if (ret < 0) {
		return ret;
		goto out;
	}

	/* Configure control EP */
@@ -1562,32 +1571,32 @@ int usb_enable(void)
	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 @@ int usb_enable(void)
	/* 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;
}

/*