ble nano hid over gatt

Dependencies:   BLE_API mbed-dev nRF51822

Files at this revision

API Documentation at this revision

Comitter:
cho45
Date:
Thu Sep 15 09:31:05 2016 +0900
Parent:
85:e526a89a0674
Commit message:
support consumer keys

Changed in this revision

HIDController_BLE.cpp Show annotated file Show diff for this revision Revisions of this file
HIDController_BLE.h Show annotated file Show diff for this revision Revisions of this file
HIDServiceBase.cpp Show annotated file Show diff for this revision Revisions of this file
KeyboardService.h Show annotated file Show diff for this revision Revisions of this file
keymap.h Show annotated file Show diff for this revision Revisions of this file
--- a/HIDController_BLE.cpp	Thu Sep 15 08:48:57 2016 +0900
+++ b/HIDController_BLE.cpp	Thu Sep 15 09:31:05 2016 +0900
@@ -350,6 +350,18 @@
 	}
 }
 
+void HIDController::pressConsumerKey(const uint16_t key) {
+	if (keyboardService) {
+		keyboardService->pressConsumerKey(key);
+	}
+}
+
+void HIDController::releaseConsumerKey() {
+	if (keyboardService) {
+		keyboardService->releaseConsumerKey();
+	}
+}
+
 void HIDController::queueCurrentReportData() {
 	if (!connected()) return;
 	if (keyboardService) {
--- a/HIDController_BLE.h	Thu Sep 15 08:48:57 2016 +0900
+++ b/HIDController_BLE.h	Thu Sep 15 09:31:05 2016 +0900
@@ -20,6 +20,8 @@
 
 	static void appendReportData(const uint8_t key);
 	static void deleteReportData(const uint8_t key);
+	static void pressConsumerKey(const uint16_t key);
+	static void releaseConsumerKey();
 	static void queueCurrentReportData();
 	static void updateBatteryLevel(const uint8_t percentage, const uint16_t voltage);
 	static void initializeConnection(const bool ignoreWhiteList);
--- a/HIDServiceBase.cpp	Thu Sep 15 08:48:57 2016 +0900
+++ b/HIDServiceBase.cpp	Thu Sep 15 09:31:05 2016 +0900
@@ -18,20 +18,20 @@
 #include "config.h"
 #include "HIDServiceBase.h"
 
-static const report_reference_t inputReportReferenceData = { 0, INPUT_REPORT };
+static const report_reference_t inputReportReferenceData = { 1, INPUT_REPORT };
 static const GattAttribute inputReportReferenceDescriptor(BLE_UUID_DESCRIPTOR_REPORT_REFERENCE, (uint8_t *)&inputReportReferenceData, 2, 2, false);
 static const GattAttribute * inputReportDescriptors[] = {
 	&inputReportReferenceDescriptor,
 };
 
-static const report_reference_t outputReportReferenceData = { 0, OUTPUT_REPORT };
+static const report_reference_t outputReportReferenceData = { 1, OUTPUT_REPORT };
 static const GattAttribute outputReportReferenceDescriptor(BLE_UUID_DESCRIPTOR_REPORT_REFERENCE, (uint8_t *)&outputReportReferenceData, 2, 2, false);
 static const GattAttribute * outputReportDescriptors[] = {
 	&outputReportReferenceDescriptor,
 };
 
 
-static const report_reference_t featureReportReferenceData = { 0, FEATURE_REPORT };
+static const report_reference_t featureReportReferenceData = { 1, FEATURE_REPORT };
 static const GattAttribute featureReportReferenceDescriptor(BLE_UUID_DESCRIPTOR_REPORT_REFERENCE, (uint8_t *)&featureReportReferenceData, 2, 2, false);
 static const GattAttribute * featureReportDescriptors[] = {
 	&featureReportReferenceDescriptor,
--- a/KeyboardService.h	Thu Sep 15 08:48:57 2016 +0900
+++ b/KeyboardService.h	Thu Sep 15 09:31:05 2016 +0900
@@ -28,6 +28,7 @@
 	USAGE_PAGE(1),      0x01,       // Generic Desktop Ctrls
 	USAGE(1),           0x06,       // Keyboard
 	COLLECTION(1),      0x01,       // Application
+		REPORT_ID(1),       0x01,
 		USAGE_PAGE(1),      0x07,       //   Kbrd/Keypad
 		USAGE_MINIMUM(1),   0xE0,
 		USAGE_MAXIMUM(1),   0xE7,
@@ -61,13 +62,36 @@
 		USAGE_MAXIMUM(1),   0x65,
 		INPUT(1),           0x00,       //   Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position
 
-		USAGE_PAGE(1),      0x00,       //   Undefined
-		USAGE_MINIMUM(1),   0x00,
-		USAGE_MAXIMUM(1),   0xFF,
-		REPORT_COUNT(1),    0x01,       //   1 byte 
-		REPORT_SIZE(1),     0x08,
-		FEATURE(1),         0x02,       //   Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile
+		USAGE_PAGE(1),      0x0C,       //   Consumer
+		USAGE(1),           0x00,
+		COLLECTION(1),      0x02,       // Logical
+			REPORT_ID(1),       0x01,
+			USAGE_MINIMUM(1),   0x00,
+			USAGE_MAXIMUM(1),   0xFF,
+			REPORT_COUNT(1),    0x01,       //   1 byte 
+			REPORT_SIZE(1),     0x08,
+			FEATURE(1),         0x02,       //   Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile
+		END_COLLECTION(0),
 	END_COLLECTION(0),
+
+	USAGE_PAGE(1),      0x0C,
+	USAGE(1),           0x01,
+	COLLECTION(1),      0x01,
+		REPORT_ID(1),       0x03,
+		REPORT_SIZE(1), 0x10,
+		REPORT_COUNT(1), 0x01,
+		LOGICAL_MINIMUM(1), 1,
+		LOGICAL_MAXIMUM(2), 0xFF, 0x03,
+		USAGE_MINIMUM(1), 1,
+		USAGE_MAXIMUM(2), 0xFF, 0x03,
+		INPUT(1), 0x60,
+	END_COLLECTION(0),
+};
+
+static const report_reference_t consumerInputReportReferenceData = { 3, INPUT_REPORT };
+static const GattAttribute consumerInputReportReferenceDescriptor(BLE_UUID_DESCRIPTOR_REPORT_REFERENCE, (uint8_t *)&consumerInputReportReferenceData, 2, 2, false);
+static const GattAttribute * consumerInputReportDescriptors[] = {
+	&consumerInputReportReferenceDescriptor,
 };
 
 class KeyboardService : public HIDServiceBase {
@@ -89,12 +113,18 @@
 		uint8_t raw[1];
 	};
 
+	union ConsumerInputReportData {
+		uint8_t raw[2];
+		uint16_t key;
+	};
+
 	/**
 	 * Boot Protocol
 	 * Share input/output report with Report Protocol for memmory saving
 	 */
 	GattCharacteristic bootKeyboardInputReportCharacteristic;
 	GattCharacteristic bootKeyboardOutputReportCharacteristic;
+	GattCharacteristic consumerInputReportCharacteristic;
 
 	InputReportData inputReportDataPublished;
 	InputReportData inputReportData;
@@ -110,6 +140,9 @@
 	FeatureReportData featureReportData;
 	bool isSending;
 
+	ConsumerInputReportData consumerInputReportData;
+	bool hasPendingConsumerInputReport;
+
 	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;
@@ -149,7 +182,16 @@
 			| GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE
 			| GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE
 		),
+		consumerInputReportCharacteristic(
+			GattCharacteristic::UUID_REPORT_CHAR,
+			(uint8_t *)&consumerInputReportData, sizeof(consumerInputReportData), sizeof(consumerInputReportData),
+			GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ
+			| GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY
+			| GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE,
+			const_cast<GattAttribute**>(consumerInputReportDescriptors), 1
+		),
 		isSending(false),
+		hasPendingConsumerInputReport(false),
 		sendAvailable(false),
 		bufferCount(0)
 	{
@@ -165,6 +207,7 @@
 		DEBUG_PRINTF_BLE("addExtraCharacteristics %d\r\n", charIndex);
 		characteristics[charIndex++] = &bootKeyboardInputReportCharacteristic;
 		characteristics[charIndex++] = &bootKeyboardOutputReportCharacteristic;
+		characteristics[charIndex++] = &consumerInputReportCharacteristic;
 	}
 
 	virtual ble_error_t send(const report_t report) {
@@ -216,6 +259,18 @@
 		}
 	}
 
+	void pressConsumerKey(const uint16_t key) {
+		consumerInputReportData.key = key;
+		hasPendingConsumerInputReport = true;
+		sendAvailable = true;
+	}
+
+	void releaseConsumerKey() {
+		consumerInputReportData.key = 0;
+		hasPendingConsumerInputReport = true;
+		sendAvailable = true;
+	}
+
 	void queueCurrentReportData() {
 		DEBUG_PRINTF_BLE("Q %d\r\n", bufferCount);
 		bufferCount++;
@@ -251,6 +306,15 @@
 			return;
 		}
 		sendAvailable = false;
+
+		if (hasPendingConsumerInputReport) {
+			ble.gattServer().write(
+				consumerInputReportCharacteristic.getValueHandle(),
+				(uint8_t*)&consumerInputReportData,
+				sizeof(consumerInputReportData)
+			);
+			hasPendingConsumerInputReport = false;
+		}
 		
 		// isSending の場合現在送信中の report があり、再送中である可能性がある
 		// そうではない場合のみ queue から pop して新しく send する
--- a/keymap.h	Thu Sep 15 08:48:57 2016 +0900
+++ b/keymap.h	Thu Sep 15 09:31:05 2016 +0900
@@ -38,6 +38,14 @@
 		DEBUG_PRINTF_KEYEVENT("LAYER->%d\r\n", keymap.layer);
 	}
 
+	static void consumer_play_pause(Keymap& keymap, const bool pressed) {
+		if (pressed) {
+			HIDController::pressConsumerKey(0x00cd);
+		} else {
+			HIDController::releaseConsumerKey();
+		}
+	}
+
 	void execute(const int row, const int col, const bool pressed) {
 		for (int i = 0; ; i++) {
 			const keyfunc_t& keyfunc = KEYMAP_FUNCTIONS[i];
@@ -100,6 +108,7 @@
 
 const keyfunc_t Keymap::KEYMAP_FUNCTIONS[] = {
 	{ 5, 14, &Keymap::switch_layer },
+	{ 5, 5, &Keymap::consumer_play_pause },
 	{ -1, -1, 0 } /* for iteration */
 };