mirror of https://github.com/google/pebble
249 lines
12 KiB
C
249 lines
12 KiB
C
/*
|
||
* Copyright 2024 Google LLC
|
||
*
|
||
* 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.
|
||
*/
|
||
|
||
#pragma once
|
||
|
||
#include "util/attributes.h"
|
||
#include <bluetooth/pebble_bt.h>
|
||
#include <bluetooth/responsiveness.h>
|
||
|
||
#define PEBBLE_BT_PAIRING_SERVICE_CONNECTION_STATUS_UUID PEBBLE_BT_UUID_EXPAND(1)
|
||
#define PEBBLE_BT_PAIRING_SERVICE_TRIGGER_PAIRING_UUID PEBBLE_BT_UUID_EXPAND(2)
|
||
#define PEBBLE_BT_PAIRING_SERVICE_GATT_MTU_UUID PEBBLE_BT_UUID_EXPAND(3)
|
||
// Note: UUID 4 was used by the 3.14-rc Android App for V0 of the Connection Param characteristic
|
||
// but never shipped externally
|
||
#define PEBBLE_BT_PAIRING_SERVICE_CONNECTION_PARAMETERS_UUID PEBBLE_BT_UUID_EXPAND(5)
|
||
|
||
typedef enum {
|
||
PebblePairingServiceGATTError_UnknownCommandID =
|
||
BLEGATTErrorApplicationSpecificErrorStart,
|
||
PebblePairingServiceGATTError_ConnParamsInvalidRemoteDesiredState,
|
||
PebblePairingServiceGATTError_ConnParamsMinSlotsTooSmall,
|
||
PebblePairingServiceGATTError_ConnParamsMinSlotsTooLarge,
|
||
PebblePairingServiceGATTError_ConnParamsMaxSlotsTooLarge,
|
||
PebblePairingServiceGATTError_ConnParamsSupervisionTimeoutTooSmall,
|
||
PebblePairingServiceGATTError_DeviceDoesNotSupportPLE,
|
||
} PebblePairingServiceGATTError;
|
||
|
||
//! The connectivity status, with respect to the device reading it.
|
||
typedef struct PACKED {
|
||
union {
|
||
struct {
|
||
//! true if the device that is reading the status is connected (always true)
|
||
bool ble_is_connected:1;
|
||
//! true if the device that is reading the status is bonded, false if not
|
||
bool ble_is_bonded:1;
|
||
//! true if the current LE link is encrypted, false if not
|
||
bool ble_is_encrypted:1;
|
||
//! true if the watch has a bonding to a gateway (LE-based).
|
||
bool has_bonded_gateway:1;
|
||
//! true if the watch supports writing the "Don't send slave security request" bit.
|
||
//! See https://pebbletechnology.atlassian.net/wiki/display/DEV/Pebble+GATT+Services
|
||
bool supports_pinning_without_security_request:1;
|
||
//! true if the reversed ppogatt was enabled at the time of bonding
|
||
bool is_reversed_ppogatt_enabled:1;
|
||
|
||
//! Reserved, leave zero for future use.
|
||
uint32_t rsvd:18;
|
||
|
||
//! The error of the last pairing process or all zeroes, if no pairing process has completed
|
||
//! or when there were no errors. Also see BT Spec 4.2, Vol 3, Part H, 3.5.5 Pairing Failed.
|
||
uint8_t last_pairing_result;
|
||
};
|
||
uint8_t bytes[4];
|
||
};
|
||
} PebblePairingServiceConnectivityStatus;
|
||
|
||
_Static_assert(sizeof(PebblePairingServiceConnectivityStatus) == 4, "");
|
||
|
||
typedef struct PACKED {
|
||
bool should_pin_address:1;
|
||
|
||
//! @note Not available in Bluetopia/cc2564x implementation
|
||
//! This flag and should_force_slave_security_request are mutually exclusive!
|
||
bool no_slave_security_request:1;
|
||
|
||
//! @note Not available in Bluetopia/cc2564x implementation
|
||
//! This flag and no_slave_security_request are mutually exclusive!
|
||
bool should_force_slave_security_request:1;
|
||
|
||
//! @note Not available in Bluetopia/cc2564x implementation
|
||
//! Flag to indicate that when re-pairing this device, the re-pairing should be accepted
|
||
//! automatically for this remote device (matching IRK or matching identity address).
|
||
//! @note This is a workaround for an Android 4.4.x bug. This opens up a security hole :( where
|
||
//! a phone could pretend to be the "trusted" phone and pair w/o the user even knowing about it.
|
||
//! @see https://pebbletechnology.atlassian.net/browse/PBL-39369
|
||
bool should_auto_accept_re_pairing:1;
|
||
|
||
//! @note Not available in Bluetopia/cc2564x implementation
|
||
//! Flag to indicate that the PPoGATT server/client roles should be reversed to support the
|
||
//! connected phone. Some older Android phones' GATT service API is completely busted. For those
|
||
//! poor phones, this bit is set before pairing. The Pebble includes a "reversed" PPoGATT service
|
||
//! that the phone app can connect to as GATT client, but this service only works if this bit
|
||
//! gets set *before pairing*. This is a security measure: 1. to prevent non-paired devices from
|
||
//! talking to the "reversed" PPoGATT service. 2. to prevent non-Pebble apps on paired phone that
|
||
//! does support normal PPoGATT from connecting to the "reversed" PPoGATT service.
|
||
//! @see ppogatt_emulated_server_wa.c
|
||
//! @see https://pebbletechnology.atlassian.net/browse/PBL-39634
|
||
bool is_reversed_ppogatt_enabled:1;
|
||
} PairingTriggerRequestData;
|
||
|
||
typedef struct PACKED {
|
||
//! interval_min_ms / 1.25 msec – valid range: 7.5 msec to 4 seconds
|
||
uint16_t interval_min_1_25ms;
|
||
|
||
//! (interval_max_ms - interval_min_ms) / 1.25 msec
|
||
//! @note To fit the parent struct in the minimum GATT MTU, this field is a delta and only one
|
||
//! byte instead of the uint16_t that the BT spec uses.
|
||
uint8_t interval_max_delta_1_25ms;
|
||
|
||
//! Slave latency (in number of connection events)
|
||
//! @note To fit the parent struct in the minimum GATT MTU, this field is only one byte instead
|
||
//! of the uint16_t that the BT spec uses.
|
||
uint8_t slave_latency_events;
|
||
|
||
//! Supervision Timeout / 30 msec – valid range: 100 msec to 32 seconds. To fit this into one
|
||
//! byte and to fit the parent struct in the minimum GATT MTU, the increments is not the standard
|
||
//! 10msec!
|
||
uint8_t supervision_timeout_30ms;
|
||
} PebblePairingServiceConnParamSet;
|
||
|
||
//! The connection parameters settings, with respect to connection to the device reading them.
|
||
typedef struct PACKED PebblePairingServiceConnParamsReadNotif {
|
||
//! Capability bits. Reserved for future use.
|
||
uint8_t packet_length_extension_supported:1;
|
||
uint8_t rsvd:7;
|
||
|
||
//! Current interval / 1.25 msec – valid range: 7.5 msec to 4 seconds
|
||
uint16_t current_interval_1_25ms;
|
||
|
||
//! Current Slave latency (in number of connection events) – actual max is 0x01F3, but in
|
||
//! practice values are much lower.
|
||
uint16_t current_slave_latency_events;
|
||
|
||
//! Current Supervision Timeout / 10 msec – valid range: 100 msec to 32 seconds.
|
||
uint16_t current_supervision_timeout_10ms;
|
||
} PebblePairingServiceConnParamsReadNotif;
|
||
|
||
typedef enum PebblePairingServiceConnParamsWriteCmd {
|
||
//! Allows phone to change connection parameter set and take over control of parameter management
|
||
PebblePairingServiceConnParamsWriteCmd_SetRemoteParamMgmtSettings = 0x00,
|
||
//! Issues a connection parameter change request if the watch is not in the desired state
|
||
PebblePairingServiceConnParamsWriteCmd_SetRemoteDesiredState = 0x01,
|
||
//! Controls settings for BLE 4.2 Packet Length Extension feature
|
||
PebblePairingServiceConnParamsWriteCmd_EnablePacketLengthExtension = 0x02,
|
||
//! If written to disables Dialog BLE sleep mode (safeguard against PBL-39777 in case it affects
|
||
//! more watches in the future)
|
||
PebblePairingServiceConnParamsWriteCmd_InhibitBLESleep = 0x03,
|
||
PebblePairingServiceConnParamsWriteCmdCount,
|
||
} PebblePairingServiceConnParamsWriteCmd;
|
||
|
||
typedef struct PACKED PebblePairingServiceRemoteParamMgmtSettings {
|
||
//! If false/zero, Pebble should manage the connection parameters. If true/one, Pebble should
|
||
//! NOT manage the connection parameters. In this mode, Pebble will never request a
|
||
//! connection parameter change.
|
||
bool is_remote_device_managing_connection_parameters:1;
|
||
uint8_t rsvd:7;
|
||
//! Optional. Current parameters sets used by Pebble's Connection Parameter manager.
|
||
PebblePairingServiceConnParamSet connection_parameter_sets[];
|
||
} PebblePairingServiceRemoteParamMgmtSettings;
|
||
|
||
typedef struct PACKED PebblePairingServiceRemoteDesiredState {
|
||
//! The desired ResponseTime as desired by the remote device. The remote end can set this
|
||
//! value to a faster mode when it's about to transfer/receive a lot of data. For example,
|
||
//! when a lot of BlobDB operations are queued up, the watch doesn't know how much data is
|
||
//! queued up on the remote end. In this case, the remote could write "ResponseTimeMin" so
|
||
//! increase the speed temporarily. It's the remote end's responsibility to reset this to
|
||
//! ResponseTimeMax when the bulk transfer is done. As a safety measure, the watch is will
|
||
//! reset it back to ResponseTimeMax after 5 minutes. In case the phone app still wants to
|
||
//! keep a particular desired ResponseTime, the phone app is responsible for making sure to
|
||
//! write the value again before the 5 minute timer expires.
|
||
uint8_t state:2;
|
||
|
||
uint8_t rsvd:6;
|
||
} PebblePairingServiceRemoteDesiredState;
|
||
|
||
typedef struct PACKED PebblePairingServicePacketLengthExtension {
|
||
uint8_t trigger_ll_length_req:1;
|
||
uint8_t rsvd:7;
|
||
} PebblePairingServicePacketLengthExtension;
|
||
|
||
typedef struct PACKED PebblePairingServiceInhibitBLESleep {
|
||
uint8_t rsvd; // for future use
|
||
} PebblePairingServiceInhibitBLESleep;
|
||
|
||
//! The connection parameters settings, with respect to connection to the device writing them.
|
||
typedef struct PACKED PebblePairingServiceConnParamsWrite {
|
||
PebblePairingServiceConnParamsWriteCmd cmd:8;
|
||
union PACKED {
|
||
//! Valid iff cmd == PebblePairingServiceConnParamsWriteCmd_SetRemoteParamMgmtSettings
|
||
PebblePairingServiceRemoteParamMgmtSettings remote_param_mgmt_settings;
|
||
|
||
//! Valid iff cmd == PebblePairingServiceConnParamsWriteCmd_SetRemoteDesiredState
|
||
PebblePairingServiceRemoteDesiredState remote_desired_state;
|
||
|
||
//! Valid iff cmd == PebblePairingServiceConnParamsWriteCmd_EnablePacketLengthExtension
|
||
PebblePairingServicePacketLengthExtension ple_req;
|
||
|
||
//! Valid iff cmd == PebblePairingServiceConnParamsWriteCmd_InhibitBLESleep
|
||
PebblePairingServiceInhibitBLESleep ble_sleep;
|
||
};
|
||
} PebblePairingServiceConnParamsWrite;
|
||
|
||
#define PEBBLE_PAIRING_SERVICE_REMOTE_PARAM_MGTM_SETTINGS_SIZE_WITH_PARAM_SETS \
|
||
(sizeof(PebblePairingServiceRemoteParamMgmtSettings) + \
|
||
(sizeof(PebblePairingServiceConnParamSet) * NumResponseTimeState))
|
||
|
||
#define PEBBLE_PAIRING_SERVICE_CONN_PARAMS_WRITE_SIZE_WITH_PARAM_SETS \
|
||
(offsetof(PebblePairingServiceConnParamsWrite, remote_param_mgmt_settings) + \
|
||
PEBBLE_PAIRING_SERVICE_REMOTE_PARAM_MGTM_SETTINGS_SIZE_WITH_PARAM_SETS)
|
||
|
||
_Static_assert(NumResponseTimeState == 3, "");
|
||
_Static_assert(sizeof(PebblePairingServiceConnParamsReadNotif) <= 20, "Larger than minimum MTU!");
|
||
_Static_assert(PEBBLE_PAIRING_SERVICE_CONN_PARAMS_WRITE_SIZE_WITH_PARAM_SETS <= 20,
|
||
"Larger than minimum MTU!");
|
||
_Static_assert(sizeof(PebblePairingServiceConnParamsWrite) <= 20, "Larger than minimum MTU!");
|
||
_Static_assert(sizeof(PebblePairingServiceConnectivityStatus) <= 20, "Larger than minimum MTU!");
|
||
|
||
typedef struct GAPLEConnection GAPLEConnection;
|
||
|
||
//! Signals to the Pebble GATT service that status change has occurred (pairing, encryption, ...),
|
||
//! allowing it to notify any BLE devices that are subscribed to connectivity status updates of the
|
||
//! change.
|
||
//! @param connection The connection for which the status was changed.
|
||
void bt_driver_pebble_pairing_service_handle_status_change(const GAPLEConnection *connection);
|
||
|
||
//! Signals to the Pebble GATT service the GATT MTU has changed, allowing it to notify any BLE
|
||
//! devices that are subscribed to GATT MTU characteristic.
|
||
//! @param connection The connection for which the GATT MTU has changed.
|
||
//! @note the caller is responsible for taking bt_lock!
|
||
void bt_driver_pebble_pairing_service_handle_gatt_mtu_change(const GAPLEConnection *connection);
|
||
|
||
//! Indicate to the FW that Connectivity Status characteristic has been unsubscribed from.
|
||
//! This is used to detect that the Pebble iOS app has been terminated.
|
||
extern void bt_driver_cb_pebble_pairing_service_handle_ios_app_termination_detected(void);
|
||
|
||
//! Indicate to the FW that the Connection Parameters characteristic has been written to with a new
|
||
//! values.
|
||
//! @param conn_params The value as written to the Connection Parameters characteristic. The BT
|
||
//! driver lib is expected to validate any written values and only call this function with valid
|
||
//! values.
|
||
//! @param conn_params_length The length of conn_params in bytes.
|
||
extern void bt_driver_cb_pebble_pairing_service_handle_connection_parameter_write(
|
||
const BTDeviceInternal *device,
|
||
const PebblePairingServiceConnParamsWrite *conn_params,
|
||
size_t conn_params_length);
|