Diff between c54e30f3078c7f4054dd8822ba6f0dd70b92a3bf and 976cecb6b6f21724bb6d3e73f16a4f7d372e77f5

Changed Files

File Additions Deletions Status
profiles/input/hog.c +16 -5 modified

Full Patch

diff --git a/profiles/input/hog.c b/profiles/input/hog.c
index 9f10fa4..a6ffe79 100644
--- a/profiles/input/hog.c
+++ b/profiles/input/hog.c
@@ -112,6 +112,7 @@ static void report_value_cb(const guint8 *pdu, guint16 len, gpointer user_data)
 	struct uhid_event ev;
 	uint16_t report_size = len - 3;
 	uint8_t *buf;
+	ssize_t status;
 
 	if (len < 3) { /* 1-byte opcode + 2-byte handle */
 		error("Malformed ATT notification");
@@ -131,11 +132,21 @@ static void report_value_cb(const guint8 *pdu, guint16 len, gpointer user_data)
 
 	memcpy(buf, &pdu[3], MIN(report_size, UHID_DATA_MAX));
 
-	if (write(hogdev->uhid_fd, &ev, sizeof(ev)) < 0)
-		error("uHID write failed: %s", strerror(errno));
-	else
-		DBG("Report from HoG device 0x%04X written to uHID fd %d",
-						hogdev->id, hogdev->uhid_fd);
+	status = write(hogdev->uhid_fd, &ev, sizeof(ev));
+	if (status < 0) {
+		error("uHID dev write error: %s (%d)", strerror(errno), errno);
+		return;
+	}
+
+	/* uHID kernel driver does not handle partial writes */
+	if ((size_t) status < sizeof(ev)) {
+		error("uHID dev write error: partial write (%zd of %lu bytes)",
+							status, sizeof(ev));
+		return;
+	}
+
+	DBG("HoG report (%u bytes) -> uHID fd %d", ev.u.input.size,
+							hogdev->uhid_fd);
 }
 
 static void report_ccc_written_cb(guint8 status, const guint8 *pdu,