HID-over-GATT implementation with the BLE API. This library allows to create devices such as mouse, keyboard or joystick, over Bluetooth Low Energy.

Dependents:   BLENano_HID BLE_HID_MouseScrollDemo BLE_HID_KeyboardStreamDemo Shervs_TestKeyboard_TinyBLE ... more

The development repository is currently hosted on github. It contains examples and documentation. This is a snapshot of the library. The documentation can be read on github, or on docs.mbed.com.


Jean-Philippe Brucker

File content as of revision 0:cfd70fa91663:


#include "mbed.h"

#include "ble/BLE.h"
#include "HID_types.h"


typedef const uint8_t report_map_t[];
typedef const uint8_t * report_t;

typedef struct {
    uint16_t bcdHID;
    uint8_t  bCountryCode;
    uint8_t  flags;
} HID_information_t;

enum ReportType {
    INPUT_REPORT    = 0x1,
    OUTPUT_REPORT   = 0x2,
    FEATURE_REPORT  = 0x3,

enum ProtocolMode {
    BOOT_PROTOCOL   = 0x0,

typedef struct {
    uint8_t ID;
    uint8_t type;
} report_reference_t;

class HIDServiceBase {
     *  Constructor
     *  @param _ble
     *         BLE object to add this service to
     *  @param reportMap
     *         Byte array representing the input/output report formats. In USB HID jargon, it
     *         is called "HID report descriptor".
     *  @param reportMapLength 
     *         Size of the reportMap array
     *  @param outputReportLength
     *         Maximum length of a sent report (up to 64 bytes) (default: 64 bytes)
     *  @param inputReportLength
     *         Maximum length of a received report (up to 64 bytes) (default: 64 bytes)
     *  @param inputReportTickerDelay
     *         Delay between input report notifications, in ms. Acceptable values depend directly on
     *         GAP's connInterval parameter, so it shouldn't be less than 12ms
     *         Preferred GAP connection interval is set after this value, in order to send
     *         notifications as quick as possible: minimum connection interval will be set to
     *         (inputReportTickerDelay / 2)
    HIDServiceBase(BLE &_ble,
                   report_map_t reportMap,
                   uint8_t reportMapLength,
                   report_t inputReport,
                   report_t outputReport,
                   report_t featureReport,
                   uint8_t inputReportLength = 0,
                   uint8_t outputReportLength = 0,
                   uint8_t featureReportLength = 0,
                   uint8_t inputReportTickerDelay = 50);

     *  Send Report
     *  @param report   Report to send. Must be of size @ref inputReportLength
     *  @return         The write status
     *  @note Don't call send() directly for multiple reports! Use reportTicker for that, in order
     *  to avoid overloading the BLE stack, and let it handle events between each report.
    virtual ble_error_t send(const report_t report);

     *  Read Report
     *  @param report   Report to fill. Must be of size @ref outputReportLength
     *  @return         The read status
    virtual ble_error_t read(report_t report);

     * Set connection state.
     * BLE API doesn't allow to chain onConnection callbacks at the moment, so it is the
     * application's responsibility to use this method to update connection state.

     * TODO: This is temporary. Remove external calls to setConnected once connection callback
     * chaining is integrated into BLE API.
    virtual void setConnected(bool connected)
        this->connected = connected;

    virtual bool isConnected(void)
        return connected;

     * Called by BLE API when data has been successfully sent.
     * @param count     Number of reports sent
     * @note Subclasses can override this to avoid starting the report ticker when there is nothing
     * to send
    virtual void onDataSent(unsigned count);

     * Start the ticker that sends input reports at regular interval
     * @note reportTickerIsActive describes the state of the ticker and can be used by HIDS
     * implementations.
    virtual void startReportTicker(void);

     * Stop the input report ticker
    virtual void stopReportTicker(void);

     * Called by input report ticker at regular interval (reportTickerDelay). This must be
     * overriden by HIDS implementations to call the @ref send() with a report, if necessary.
    virtual void sendCallback(void) = 0;

     * Create the Gatt descriptor for a report characteristic
    GattAttribute** inputReportDescriptors();
    GattAttribute** outputReportDescriptors();
    GattAttribute** featureReportDescriptors();

     * Create the HID information structure
    HID_information_t* HIDInformation();

    BLE &ble;
    bool connected;

    int reportMapLength;

    report_t inputReport;
    report_t outputReport;
    report_t featureReport;

    uint8_t inputReportLength;
    uint8_t outputReportLength;
    uint8_t featureReportLength;

    uint8_t controlPointCommand;
    uint8_t protocolMode;

    report_reference_t inputReportReferenceData;
    report_reference_t outputReportReferenceData;
    report_reference_t featureReportReferenceData;

    GattAttribute inputReportReferenceDescriptor;
    GattAttribute outputReportReferenceDescriptor;
    GattAttribute featureReportReferenceDescriptor;

    // Optional gatt characteristics:
    GattCharacteristic protocolModeCharacteristic;

    // Report characteristics (each sort of optional)
    GattCharacteristic inputReportCharacteristic;
    GattCharacteristic outputReportCharacteristic;
    GattCharacteristic featureReportCharacteristic;

    // Required gatt characteristics: Report Map, Information, Control Point
    GattCharacteristic reportMapCharacteristic;
    ReadOnlyGattCharacteristic<HID_information_t> HIDInformationCharacteristic;
    GattCharacteristic HIDControlPointCharacteristic;

    Ticker reportTicker;
    uint32_t reportTickerDelay;
    bool reportTickerIsActive;

#endif /* !HID_SERVICE_BASE_H_ */