From 66c4b7ebb0ec914089a8f08905d832b16493dd73 Mon Sep 17 00:00:00 2001
From: Pete Johanson <peter@peterjohanson.com>
Date: Mon, 17 Aug 2020 22:17:59 -0400
Subject: [PATCH] fix(usb): Restore write semaphore, release it on write
 failures.

---
 app/src/usb_hid.c | 36 ++++++++++++++++++++++++++++++------
 1 file changed, 30 insertions(+), 6 deletions(-)

diff --git a/app/src/usb_hid.c b/app/src/usb_hid.c
index 4c6dd4b2..784fc250 100644
--- a/app/src/usb_hid.c
+++ b/app/src/usb_hid.c
@@ -11,18 +11,42 @@
 
 LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
 
-static enum usb_dc_status_code usb_status;
+static enum usb_dc_status_code usb_status = USB_DC_UNKNOWN;
 
 static struct device *hid_dev;
 
+static K_SEM_DEFINE(hid_sem, 1, 1);
+
+static void in_ready_cb(void)
+{
+	k_sem_give(&hid_sem);
+}
+
+static const struct hid_ops ops =
+{
+	.int_in_ready = in_ready_cb,
+};
+
 int zmk_usb_hid_send_report(const u8_t *report, size_t len)
 {
-	if (usb_status == USB_DC_SUSPEND)
-	{
+	switch(usb_status) {
+	case USB_DC_SUSPEND:
 		return usb_wakeup_request();
-	}
+	case USB_DC_ERROR:
+	case USB_DC_RESET:
+	case USB_DC_DISCONNECTED:
+	case USB_DC_UNKNOWN:
+		return -ENODEV;
+	default:
+		k_sem_take(&hid_sem, K_MSEC(30));
+		int err = hid_int_ep_write(hid_dev, report, len, NULL);
 
-	return hid_int_ep_write(hid_dev, report, len, NULL);
+		if (err) {
+			k_sem_give(&hid_sem);
+		}
+
+		return err;
+	}
 }
 
 void usb_hid_status_cb(enum usb_dc_status_code status, const u8_t *params)
@@ -43,7 +67,7 @@ static int zmk_usb_hid_init(struct device *_arg)
 
 	usb_hid_register_device(hid_dev,
 							zmk_hid_report_desc, sizeof(zmk_hid_report_desc),
-							NULL);
+							&ops);
 
 	usb_hid_init(hid_dev);