ble nano hid over gatt

Dependencies:   BLE_API mbed-dev nRF51822

HIDServiceBase.cpp

Committer:
cho45
Date:
2016-09-03
Revision:
82:af52d37b1946
Parent:
79:0095bfb18c57
Child:
83:2e940d154f8b

File content as of revision 82:af52d37b1946:

/* 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 HID_information_t HID_information = {HID_VERSION_1_11, 0x00, 0x03};

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,
            NULL, 0),

    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[] = {
		&HIDInformationCharacteristic,
		&reportMapCharacteristic,
		&protocolModeCharacteristic,
		&HIDControlPointCharacteristic,
		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;
}