ble nano hid over gatt

Dependencies:   BLE_API mbed-dev nRF51822

HIDServiceBase.cpp

Committer:
cho45
Date:
2016-09-15
Revision:
85:e526a89a0674
Parent:
83:2e940d154f8b
Child:
86:e0fab77e669d

File content as of revision 85:e526a89a0674:

/* mbed Microcontroller Library
 * Copyright (c) 2015 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mbed.h"
#include "config.h"
#include "HIDServiceBase.h"

static const report_reference_t inputReportReferenceData = { 0, 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 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 GattAttribute featureReportReferenceDescriptor(BLE_UUID_DESCRIPTOR_REPORT_REFERENCE, (uint8_t *)&featureReportReferenceData, 2, 2, false);
static const GattAttribute * featureReportDescriptors[] = {
	&featureReportReferenceDescriptor,
};

// static const uint16_t reportMapExternalReportReferenceData = GattCharacteristic::UUID_BATTERY_LEVEL_CHAR;
static const uint8_t reportMapExternalReportReferenceData[] = { 0x2A, 0x19 };
static const GattAttribute reportMapExternalReportReferenceDescriptor(BLE_UUID_DESCRIPTOR_EXTERNAL_REPORT_REFERENCE, (uint8_t *)&reportMapExternalReportReferenceData, 2, 2, false);
static const GattAttribute * reportMapDescriptors[] = {
	&reportMapExternalReportReferenceDescriptor,
};

#define HID_REMOTE_WAKE_Pos 0
#define HID_NORMALLY_CONNECTABLE_Pos 1
static const HID_information_t HID_information = {
	HID_VERSION_1_11,
	0x00,
	(1<<HID_REMOTE_WAKE_Pos) |
	(0<<HID_NORMALLY_CONNECTABLE_Pos)
};

HIDServiceBase::HIDServiceBase(
	BLE          &_ble,
	report_map_t reportMap,
	uint8_t      reportMapSize,
	report_t     inputReport,
	report_t     outputReport,
	report_t     featureReport,
	uint8_t      inputReportLength,
	uint8_t      outputReportLength,
	uint8_t      featureReportLength
) :

	ble(_ble),
	connected (false),
	reportMapLength(reportMapSize),

	inputReport(inputReport),
	outputReport(outputReport),
	featureReport(featureReport),

	inputReportLength(inputReportLength),
	outputReportLength(outputReportLength),
	featureReportLength(featureReportLength),

	protocolMode(REPORT_PROTOCOL),

	protocolModeCharacteristic(
		GattCharacteristic::UUID_PROTOCOL_MODE_CHAR, &protocolMode, 1, 1,
		GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ
		| GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE
	),

	inputReportCharacteristic(
		GattCharacteristic::UUID_REPORT_CHAR,
		(uint8_t *)inputReport, inputReportLength, inputReportLength,
		GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ
		| GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY
		| GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE,
		const_cast<GattAttribute**>(inputReportDescriptors), 1
	),

	outputReportCharacteristic(
		GattCharacteristic::UUID_REPORT_CHAR,
		(uint8_t *)outputReport, outputReportLength, outputReportLength,
		GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ
		| GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE
		| GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE,
		const_cast<GattAttribute**>(outputReportDescriptors), 1
	),

	featureReportCharacteristic(
		GattCharacteristic::UUID_REPORT_CHAR,
		(uint8_t *)featureReport, featureReportLength, featureReportLength,
		GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ
		| GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE,
		const_cast<GattAttribute**>(featureReportDescriptors), 1
	),

	/*
	 * We need to set reportMap content as const, in order to let the compiler put it into flash
	 * instead of RAM. The characteristic is read-only so it won't be written, but
	 * GattCharacteristic constructor takes non-const arguments only. Hence the cast.
	 */
	reportMapCharacteristic(
		GattCharacteristic::UUID_REPORT_MAP_CHAR,
		const_cast<uint8_t*>(reportMap), reportMapLength, reportMapLength,
		GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ,
		const_cast<GattAttribute**>(reportMapDescriptors), 1
	),

	HIDInformationCharacteristic(
		GattCharacteristic::UUID_HID_INFORMATION_CHAR,
		const_cast<HID_information_t*>(&HID_information)
	),

	HIDControlPointCharacteristic(
		GattCharacteristic::UUID_HID_CONTROL_POINT_CHAR,
		&controlPointCommand, 1, 1,
		GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE
	)
{
}

void HIDServiceBase::init(void) {
	static GattCharacteristic *characteristics[] = {
		&reportMapCharacteristic,
		&protocolModeCharacteristic,
		&HIDControlPointCharacteristic,
		&HIDInformationCharacteristic,
		NULL,
		NULL,
		NULL,
		NULL,
		NULL
	};

	uint8_t charIndex = 4;
	/*
	 * Report characteristics are optional, and depend on the reportMap descriptor
	 * Note: at least one should be present, but we don't check that at the moment.
	 */
	if (inputReportLength)
		characteristics[charIndex++] = &inputReportCharacteristic;
	if (outputReportLength)
		characteristics[charIndex++] = &outputReportCharacteristic;
	if (featureReportLength)
		characteristics[charIndex++] = &featureReportCharacteristic;

	addExtraCharacteristics(characteristics, charIndex);

	DEBUG_PRINTF_BLE("new GattService %d\r\n", charIndex);
	GattService service(GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE, characteristics, charIndex);

	ble.gattServer().addService(service);

	ble.gap().onConnection(this, &HIDServiceBase::onConnection);
	ble.gap().onDisconnection(this, &HIDServiceBase::onDisconnection);

	ble.gattServer().onDataSent(this, &HIDServiceBase::onDataSent);
	ble.gattServer().onDataWritten(this, &HIDServiceBase::onDataWritten);

	SecurityManager::SecurityMode_t securityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM;
	protocolModeCharacteristic.requireSecurity(securityMode);
	reportMapCharacteristic.requireSecurity(securityMode);
	inputReportCharacteristic.requireSecurity(securityMode);
	outputReportCharacteristic.requireSecurity(securityMode);
	featureReportCharacteristic.requireSecurity(securityMode);
}

void HIDServiceBase::onDataSent(unsigned count) {
}

void HIDServiceBase::onDataWritten(const GattWriteCallbackParams *params) {
}

void HIDServiceBase::addExtraCharacteristics(GattCharacteristic** characteristics, uint8_t& charIndex) {
}

ble_error_t HIDServiceBase::send(const report_t report) {
	return ble.gattServer().write(
		inputReportCharacteristic.getValueHandle(),
		report,
		inputReportLength
	);
}

ble_error_t HIDServiceBase::read(report_t report) {
	// TODO. For the time being, we'll just have HID input reports...
	return BLE_ERROR_NOT_IMPLEMENTED;
}

void HIDServiceBase::onConnection(const Gap::ConnectionCallbackParams_t *params) {
	this->connected = true;
}

void HIDServiceBase::onDisconnection(const Gap::DisconnectionCallbackParams_t *params) {
	this->connected = false;
}