Porting a new Bluetooth stack into PebbleOS
Build notes
Unlike many other things in the build, a platform textually selects a
Bluetooth controller using the waf
environment variable,
conf.env.bt_controller
. This ends up pulling in a whole sublibrary
(essentially), in src/bluetooth-fw
. This is somewhat cleaner than the
rest of the driver stack, but it is a change from what you might expect from
the respect of PebbleOS!
API surface
A Bluetooth driver exports 70-ish APIs, and has a handful of callbacks that
it needs to trigger at appropriate times. I group these below in terms of
API families that one should implement, roughly in order of how critical it
is to implement them to get anything at all working.
Power and identity
- bt_driver_init
- bt_driver_start
- bt_driver_stop
- bt_driver_power_down_controller_on_boot
- bt_driver_id_set_local_device_name
- bt_driver_id_copy_local_identity_address
- bt_driver_id_copy_chip_info_string
- bt_driver_id_generate_private_resolvable_address
- bt_driver_supports_bt_classic
bt_driver_set_local_address
bt_driver_comm_schedule_send_next_job -- you probably just want to have
these run on KernelMain, unless you have your own thread that sends should
happen from. copy from qemu
bt_driver_comm_is_current_task_send_next_task
Advertising
- bt_driver_adv_reconnect_get_job_terms
- bt_driver_advert_advertising_disable
- bt_driver_advert_client_get_tx_power
- bt_driver_advert_set_advertising_data
- bt_driver_advert_advertising_enable
GAP
- bt_driver_gap_le_disconnect
- bt_driver_gap_le_device_name_request
- bt_driver_gap_le_device_name_request_all
- bt_driver_le_connection_parameter_update
- bt_driver_handle_le_connection_handle_update_address_and_irk
- bt_driver_handle_peer_version_info_event
- bt_driver_handle_le_connection_complete_event
- bt_driver_handle_le_disconnection_complete_event
- bt_driver_handle_le_encryption_change_event
- bt_driver_handle_le_conn_params_update_event
Pairing and pairing service
Bond database in-memory is managed by the controller. Bond database in
flash is managed by the OS.
- bt_driver_cb_pairing_confirm_handle_request -- a GAP LE connection wants
to bond, post message to UI to say so
- bt_driver_pairing_confirm -- UI agrees to do it
- bt_driver_cb_pairing_confirm_handle_completed -- bond is complete, from
BLE controller
- bt_driver_handle_host_added_bonding -- OS has booted, add bond from
in-flash database to in-controller database (make sure to kill these in
bt_driver_stop when reinitting)
- bt_driver_handle_host_removed_bonding -- user requested bond remove from
UI
- bt_driver_cb_handle_create_bonding -- controller has exchanged keys and
would like OS to store a bond in flash
Pebble Pairing Service
Pebble Pairing Service is an internal GATT service managed not by the OS but
by the controller (done in firmware on Dialog, obviously done as a Bluetopia
client on TI). Implicit in this API is an init that actually sets up the
Pebble Pairing Service, called within BLE stack!
See at least one implementation:
https://github.com/pebble-dev/RebbleOS/blob/master/hw/drivers/nrf52_bluetooth/nrf52_bluetooth_ppogatt.c#L352-L417
- bt_driver_pebble_pairing_service_handle_status_change
- bt_driver_cb_pebble_pairing_service_handle_connection_parameter_write
- bt_driver_cb_pebble_pairing_service_handle_ios_app_termination_detected
GATT server / client shim
- bt_driver_gatt_respond_read_subscription
- bt_driver_gatt_send_changed_indication
- bt_driver_gatt_start_discovery_range
- bt_driver_gatt_stop_discovery
- bt_driver_gatt_handle_discovery_abandoned
- bt_driver_cb_gatt_client_discovery_handle_indication
- bt_driver_cb_gatt_client_discovery_complete
- bt_driver_cb_gatt_client_operations_handle_response
- bt_driver_cb_gatt_service_changed_server_confirmation
- bt_driver_cb_gatt_service_changed_server_subscribe
- bt_driver_cb_gatt_service_changed_server_read_subscription
- bt_driver_cb_gatt_client_discovery_handle_service_changed
- bt_driver_gatt_write_without_response
- bt_driver_gatt_write
- bt_driver_gatt_read
- bt_driver_cb_gatt_handle_connect
- bt_driver_cb_gatt_handle_disconnect
- bt_driver_cb_gatt_handle_mtu_update
- bt_driver_cb_gatt_handle_notification
- bt_driver_cb_gatt_handle_indication
- bt_driver_cb_gatt_handle_buffer_empty
Heart rate monitor
The controller implements the GATT functionality for the heart rate monitor,
rather than the OS. Not implemented on TI.
- bt_driver_is_hrm_service_supported
- bt_driver_cb_hrm_service_update_subscription
- bt_driver_hrm_service_handle_measurement
Scanning
Scanning was only used by APIs that never became public.
- bt_driver_start_le_scan
- bt_driver_stop_le_scan
- bt_driver_cb_le_scan_handle_report
Bluetooth Classic
These apply only to Bluetooth Classic and are no-ops on BLE.
- bt_driver_classic_disconnect
- bt_driver_classic_is_connected
- bt_driver_classic_copy_connected_address
- bt_driver_classic_copy_connected_device_name
- bt_driver_classic_update_connectability
- bt_driver_reconnect_pause
- bt_driver_reconnect_resume
- bt_driver_reconnect_try_now
- bt_driver_reconnect_reset_interval
- bt_driver_reconnect_notify_platform_bitfield
- bt_driver_le_pairability_set_enabled -- not implemented even on Dialog
- bt_driver_classic_pairability_set_enabled
- sys_app_comm_get_sniff_interval
Analytics
- bt_driver_analytics_get_connection_quality
- bt_driver_analytics_collect_ble_parameters
- bt_driver_analytics_external_collect_chip_specific_parameters
- bt_driver_analytics_external_collect_bt_chip_heartbeat
- bt_driver_analytics_get_conn_event_stats
- bluetooth_analytics_handle_ble_pairing_request (callback)
Factory test mode / debugging.
Implemented both by classic and BLE. Used for factory test. Probably
needs to exist for production test in the future, but
- bt_driver_test_selftest -- implemented
- bt_driver_test_mfi_chip_selftest -- not implemented on LE-only
- hc_endpoint_logging_set_level -- not implemented on TI
- hc_endpoint_logging_get_level -- not implemented on TI
- bt_driver_core_dump -- not implemented on TI
- bt_driver_test_start
- bt_driver_test_enter_hci_passthrough
- bt_driver_test_handle_hci_passthrough_character
- bt_driver_test_enter_rf_test_mode
- bt_driver_test_set_spoof_address
- bt_driver_test_stop
Some drivers also have:
- bt_driver_start_unmodulated_tx
- bt_driver_stop_unmodulated_tx