// Copyright 2017 Paul Nettle.
//
// This file is part of Gobbledegook.
//
// Gobbledegook is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Gobbledegook is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Gobbledegook. If not, see .
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// >>
// >>> INSIDE THIS FILE
// >>
//
// This file contains various functions for interacting with Bluetooth Management interface, which provides adapter configuration.
//
// >>
// >>> DISCUSSION
// >>
//
// We only cover the basics here. If there are configuration features you need that aren't supported (such as configuring BR/EDR),
// then this would be a good place for them.
//
// Note that this class relies on the `HciAdapter`, which is a very primitive implementation. Use with caution.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#pragma once
#include
#include
#include "HciAdapter.h"
#include "Utils.h"
namespace ggk {
struct Mgmt
{
//
// Constants
//
// The length of the controller's name (not including null terminator)
static const int kMaxNameLength = 248;
// The length of the controller's short name (not including null terminator)
static const int kMaxShortNameLength = 10;
//
// Types
//
// HCI Controller Settings
enum EHciControllerSettings
{
EHciPowered = (1<<0),
EHciConnectable = (1<<1),
EHciFastConnectable = (1<<2),
EHciDiscoverable = (1<<3),
EHciBondable = (1<<4),
EHciLinkLevelSecurity = (1<<5),
EHciSecureSimplePairing = (1<<6),
EHciBasicRate_EnhancedDataRate = (1<<7),
EHciHighSpeed = (1<<8),
EHciLowEnergy = (1<<9),
EHciAdvertising = (1<<10),
EHciSecureConnections = (1<<11),
EHciDebugKeys = (1<<12),
EHciPrivacy = (1<<13),
EHciControllerConfiguration = (1<<14),
EHciStaticAddress = (1<<15)
};
// The comments documenting these fields are very high level. There is a lot of detailed information not present, for example
// some values are not available at all times. This is fully documented in:
//
// https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/mgmt-api.txt
struct ControllerInformation
{
uint8_t address[6]; // The Bluetooth address
uint8_t bluetoothVersion; // Bluetooth version
uint16_t manufacturer; // The manufacturer
uint32_t supportedSettings; // Bits for various supported settings (see EHciControllerSettings)
uint32_t currentSettings; // Bits for various currently configured settings (see EHciControllerSettings)
uint8_t classOfDevice[3]; // Um, yeah. That.
char name[249]; // Null terminated name
char shortName[11]; // Null terminated short name
void toHost()
{
manufacturer = Utils::endianToHost(manufacturer);
supportedSettings = Utils::endianToHost(supportedSettings);
currentSettings = Utils::endianToHost(currentSettings);
}
} __attribute__((packed));
// Construct the Mgmt device
//
// Set `controllerIndex` to the zero-based index of the device as recognized by the OS. If this parameter is omitted, the index
// of the first device (0) will be used.
Mgmt(uint16_t controllerIndex = kDefaultControllerIndex);
// Returns the version information:
//
// bits 0-15 = revision
// bits 16-23 = version
//
// ... or -1 on error
int getVersion();
// Returns information about the controller (address, name, current settings, etc.)
//
// See the definition for MgmtControllerInformation for details.
//
// ... or nullptr on error
ControllerInformation *getControllerInformation();
// Set the adapter name and short name
//
// The inputs `name` and `shortName` may be truncated prior to setting them on the adapter. To ensure that `name` and
// `shortName` conform to length specifications prior to calling this method, see the constants `kMaxNameLength` and
// `kMaxShortNameLength`. In addition, the static methods `truncateName()` and `truncateShortName()` may be helpful.
//
// Returns true on success, otherwise false
bool setName(std::string name, std::string shortName);
// Set a setting state to 'newState'
//
// Many settings are set the same way, this is just a convenience routine to handle them all
//
// Returns true on success, otherwise false
bool setState(const char *pSettingName, uint16_t commandCode, uint16_t controllerId, uint8_t newState);
// Set the powered state to `newState` (true = powered on, false = powered off)
//
// Returns true on success, otherwise false
bool setPowered(bool newState);
// Set the BR/EDR state to `newState` (true = enabled, false = disabled)
//
// Returns true on success, otherwise false
bool setBredr(bool newState);
// Set the Secure Connection state (0 = disabled, 1 = enabled, 2 = secure connections only mode)
//
// Returns true on success, otherwise false
bool setSecureConnections(uint8_t newState);
// Set the bondable state to `newState` (true = enabled, false = disabled)
//
// Returns true on success, otherwise false
bool setBondable(bool newState);
// Set the connectable state to `newState` (true = enabled, false = disabled)
//
// Returns true on success, otherwise false
bool setConnectable(bool newState);
// Set the LE state to `newState` (true = enabled, false = disabled)
//
// Returns true on success, otherwise false
bool setLE(bool newState);
// Set the advertising state to `newState` (0 = disabled, 1 = enabled (with consideration towards the connectable setting),
// 2 = enabled in connectable mode).
//
// Returns true on success, otherwise false
bool setAdvertising(uint8_t newState);
//
// Utilitarian
//
// Transforms a "Current_Settings" value (4 octets as defined by the Bluetooth Management API specification) into a human-
// readable string of flags and settings.
static std::string controllerSettingsString(uint32_t bits);
// Truncates the string `name` to the maximum allowed length for an adapter name. If `name` needs no truncation, a copy of
// `name` is returned.
static std::string truncateName(const std::string &name);
// Truncates the string `name` to the maximum allowed length for an adapter short-name. If `name` needs no truncation, a copy
// of `name` is returned.
static std::string truncateShortName(const std::string &name);
private:
//
// Data members
//
// Our adapter - we use this to connect to the HCI socket to talk to the adapter
HciAdapter hciAdapter;
// Our controller information, updated each time the controller information is received
ControllerInformation controllerInfo;
// The default controller index (the first device)
uint16_t controllerIndex;
// Default controller index
static const uint16_t kDefaultControllerIndex = 0;
// A constant referring to a 'non-controller' (for commands that do not require a controller index)
static const uint16_t kNonController = 0xffff;
};
}; // namespace ggk