ble nano hid over gatt

Dependencies:   BLE_API mbed-dev nRF51822

Revision:
7:b9270a37345b
Parent:
6:f1c3ea8bc850
Child:
9:d1daefbf1fbd
--- a/KeyboardService.h	Thu Jul 21 01:25:31 2016 +0900
+++ b/KeyboardService.h	Thu Jul 21 07:56:04 2016 +0900
@@ -16,6 +16,7 @@
 
 #include "HIDServiceBase.h"
 #include "keyboard.h"
+#include "CircularBuffer.h"
 
 /**
  * Report descriptor for a standard 101 keys keyboard, following the HID specification example:
@@ -58,19 +59,25 @@
 };
 
 class KeyboardService : public HIDServiceBase {
-	union {
+	union InputReportData {
 		uint8_t raw[8];
 		struct {
 			uint8_t modifier;
 			uint8_t padding;
 			uint8_t keycode[6];
 		} data;
-	} inputReportData;
+	};
+
+	InputReportData inputReportData;
 
 	union {
 		uint8_t raw[1];
 	} outputReportData;
 
+	CircularBuffer<InputReportData, 32, uint8_t> inputReportBuffer;
+	InputReportData inputReportDataSending;
+	bool isSending;
+
 	static const uint8_t MODIFIER_LEFT_CONTROL = 1<<0;
 	static const uint8_t MODIFIER_LEFT_SHIFT = 1<<1;
 	static const uint8_t MODIFIER_LEFT_ALT = 1<<2;
@@ -80,6 +87,11 @@
 	static const uint8_t MODIFIER_RIGHT_ALT = 1<<6;
 	static const uint8_t MODIFIER_RIGHT_GUI = 1<<7;
 
+	void queueCurrentReportData() {
+		inputReportBuffer.push(inputReportData);
+		startReportTicker();
+	}
+
 public:
 	KeyboardService(BLE& _ble) :
 		HIDServiceBase(
@@ -93,19 +105,22 @@
 			outputReportLength  = sizeof(outputReportData),
 			featureReportLength = 0,
 			reportTickerDelay   = 24
-		)
+		),
+		isSending(false)
 	{
 		for (int i = 0; i < 8; i++) {
 			inputReportData.raw[i] = 0;
 		}
 		outputReportData.raw[0] = 0;
+
+		inputReportBuffer.reset();
 	}
 
 	void appendReportData(uint8_t keycode) {
 		uint8_t modifier = toModifierBit(keycode);
 		if (modifier) {
 			inputReportData.data.modifier |= modifier;
-			startReportTicker();
+			queueCurrentReportData();
 			return;
 		}
 
@@ -113,7 +128,7 @@
 		for (int i = 0; i < 6; i++) {
 			if (inputReportData.data.keycode[i] == 0) {
 				inputReportData.data.keycode[i] = keycode;
-				startReportTicker();
+				queueCurrentReportData();
 				return;
 			}
 		}
@@ -125,14 +140,14 @@
 		uint8_t modifier = toModifierBit(keycode);
 		if (modifier) {
 			inputReportData.data.modifier &= ~modifier;
-			startReportTicker();
+			queueCurrentReportData();
 			return;
 		}
 
 		for (int i = 0; i < 6; i++) {
 			if (inputReportData.data.keycode[i] == keycode) {
 				inputReportData.data.keycode[i] = 0;
-				startReportTicker();
+				queueCurrentReportData();
 				return;
 			}
 		}
@@ -162,15 +177,40 @@
 	}
 
 	virtual void sendCallback(void) {
-		ble_error_t error = HIDServiceBase::send(inputReportData.raw);
+		// do not call printf in this function... it cause BLE_STACK_BUSY
+
+		InputReportData data;
+		if (isSending) {
+			data = inputReportDataSending;
+		} else {
+			if (!inputReportBuffer.pop(data)) {
+				if (isKeyPressed()) {
+					data = inputReportData;
+				} else {
+					stopReportTicker();
+					return;
+				}
+			}
+		}
+
+		static uint8_t busyCount = 0;
+		isSending = true;
+		ble_error_t error = HIDServiceBase::send(data.raw);
 		if (error == BLE_STACK_BUSY) {
+			if (busyCount++ > 10) {
+				busyCount = 0;
+				printf("BLE_STACK_BUSY is over 10-times stop\r\n");
+				stopReportTicker();
+			}
+			inputReportDataSending = data;
 			// retry after
 			return;
 		}
+		isSending = false;
+	}
 
-		if (!isKeyPressed()) {
-			stopReportTicker();
-		}
+	virtual void onDataSent(unsigned int count) {
+		startReportTicker();
 	}
 };