Skip to content

Commit ccde002

Browse files
laurensvalkjaguilar
andcommitted
pbio/drv/bluetooth: Implement inquiry scan.
This adds a handler for Bluetooth classic tasks to the Bluetooth driver. Co-authored-by: James Aguilar <aguilar.james@gmail.com>
1 parent 499f729 commit ccde002

11 files changed

Lines changed: 199 additions & 18 deletions

File tree

lib/pbio/drv/bluetooth/bluetooth.c

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include <pbio/busy_count.h>
1515
#include <pbio/error.h>
16+
#include <pbio/int_math.h>
1617
#include <pbio/os.h>
1718
#include <pbio/protocol.h>
1819

@@ -303,15 +304,6 @@ pbio_error_t pbdrv_bluetooth_await_peripheral_command(pbio_os_state_t *state, vo
303304
return peri->err;
304305
}
305306

306-
void pbdrv_bluetooth_cancel_operation_request(void) {
307-
// Only some peripheral actions support cancellation.
308-
DEBUG_PRINT("Bluetooth operation cancel requested.\n");
309-
for (uint8_t i = 0; i < PBDRV_CONFIG_BLUETOOTH_NUM_PERIPHERALS; i++) {
310-
pbdrv_bluetooth_peripheral_t *peri = pbdrv_bluetooth_peripheral_get_by_index(i);
311-
peri->cancel = true;
312-
}
313-
}
314-
315307
//
316308
// Functions related to advertising and scanning.
317309
//
@@ -505,6 +497,60 @@ static bool update_and_get_event_buffer(uint8_t **buf, uint32_t **len) {
505497
return false;
506498
}
507499

500+
#if PBDRV_CONFIG_BLUETOOTH_NUM_CLASSIC_CONNECTIONS
501+
static pbdrv_bluetooth_classic_task_context_t pbdrv_bluetooth_classic_task_context;
502+
503+
pbio_error_t pbdrv_bluetooth_start_inquiry_scan(pbdrv_bluetooth_inquiry_result_t *results, uint32_t *results_count, uint32_t *results_count_max, uint32_t duration_ms) {
504+
505+
if (!pbdrv_bluetooth_is_connected(PBDRV_BLUETOOTH_CONNECTION_HCI)) {
506+
return PBIO_ERROR_INVALID_OP;
507+
}
508+
509+
pbdrv_bluetooth_classic_task_context_t *task = &pbdrv_bluetooth_classic_task_context;
510+
511+
if (task->func) {
512+
return PBIO_ERROR_BUSY;
513+
}
514+
515+
// Initialize newly given task.
516+
task->inq_results = results;
517+
task->inq_count = results_count;
518+
task->inq_count_max = results_count_max;
519+
task->inq_duration = pbio_int_math_bind((duration_ms + 640) / 1280, 1, 255);
520+
521+
// Request handling on the main loop.
522+
task->err = PBIO_ERROR_AGAIN;
523+
task->func = pbdrv_bluetooth_inquiry_scan_func;
524+
task->cancel = false;
525+
pbio_os_request_poll();
526+
return PBIO_SUCCESS;
527+
}
528+
529+
pbio_error_t pbdrv_bluetooth_await_classic_task(pbio_os_state_t *state, void *context) {
530+
531+
pbdrv_bluetooth_classic_task_context_t *task = &pbdrv_bluetooth_classic_task_context;
532+
533+
// If the user is no longer calling this then the operation is no longer
534+
// of interest and will be cancelled if the active function supports it.
535+
pbio_os_timer_set(&task->watchdog, 10);
536+
537+
return task->err;
538+
}
539+
#endif // PBDRV_CONFIG_BLUETOOTH_NUM_CLASSIC_CONNECTIONS
540+
541+
void pbdrv_bluetooth_cancel_operation_request(void) {
542+
// Only some peripheral actions support cancellation.
543+
DEBUG_PRINT("Bluetooth operation cancel requested.\n");
544+
for (uint8_t i = 0; i < PBDRV_CONFIG_BLUETOOTH_NUM_PERIPHERALS; i++) {
545+
pbdrv_bluetooth_peripheral_t *peri = pbdrv_bluetooth_peripheral_get_by_index(i);
546+
peri->cancel = true;
547+
}
548+
#if PBDRV_CONFIG_BLUETOOTH_NUM_CLASSIC_CONNECTIONS
549+
// Revisit: Cancel all.
550+
pbdrv_bluetooth_classic_task_context.cancel = true;
551+
#endif // PBDRV_CONFIG_BLUETOOTH_NUM_CLASSIC_CONNECTIONS
552+
}
553+
508554
static bool shutting_down;
509555

510556
/**
@@ -595,6 +641,17 @@ pbio_error_t pbdrv_bluetooth_process_thread(pbio_os_state_t *state, void *contex
595641
PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_start_observing_func(&sub, NULL));
596642
observe_restart_requested = false;
597643
}
644+
645+
#if PBDRV_CONFIG_BLUETOOTH_NUM_CLASSIC_CONNECTIONS
646+
// Handle pending Bluetooth classic task, if any.
647+
static pbdrv_bluetooth_classic_task_context_t *task;
648+
task = &pbdrv_bluetooth_classic_task_context;
649+
if (task->func) {
650+
PBIO_OS_AWAIT(state, &sub, task->err = task->func(&sub, task));
651+
task->func = NULL;
652+
task->cancel = false;
653+
}
654+
#endif // PBDRV_CONFIG_BLUETOOTH_NUM_CLASSIC_CONNECTIONS
598655
}
599656

600657
DEBUG_PRINT("Shutdown requested.\n");

lib/pbio/drv/bluetooth/bluetooth.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,48 @@ extern pbdrv_bluetooth_start_observing_callback_t pbdrv_bluetooth_observe_callba
5555

5656
pbio_error_t pbdrv_bluetooth_process_thread(pbio_os_state_t *state, void *context);
5757

58+
/**
59+
* Context for an ongoing classic Bluetooth task.
60+
*
61+
* Not all fields are used by all functions. Only one function runs at a time.
62+
*/
63+
typedef struct {
64+
/**
65+
* The currently active function.
66+
*/
67+
pbio_os_process_func_t func;
68+
/**
69+
* The most recent result of calling above function from main process.
70+
*/
71+
pbio_error_t err;
72+
/**
73+
* Cancellation requested.
74+
*/
75+
bool cancel;
76+
/**
77+
* Watchdog for above operation so it can be cancelled on inactivity.
78+
*/
79+
pbio_os_timer_t watchdog;
80+
/**
81+
* Inquiry scan results.
82+
*/
83+
pbdrv_bluetooth_inquiry_result_t *inq_results;
84+
/**
85+
* Number of scan results found so far.
86+
*/
87+
uint32_t *inq_count;
88+
/**
89+
* Maximum number of scan results to find.
90+
*/
91+
uint32_t *inq_count_max;
92+
/**
93+
* Inquiry duration in units of 1.28 seconds.
94+
*/
95+
uint8_t inq_duration;
96+
} pbdrv_bluetooth_classic_task_context_t;
97+
98+
pbio_error_t pbdrv_bluetooth_inquiry_scan_func(pbio_os_state_t *state, void *context);
99+
58100
#endif // PBDRV_CONFIG_BLUETOOTH
59101

60102
#endif // _INTERNAL_PBDRV_BLUETOOTH_H_

lib/pbio/drv/bluetooth/bluetooth_btstack.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <assert.h>
1111
#include <inttypes.h>
12+
#include <stdio.h>
1213

1314
#include <ble/gatt-service/device_information_service_server.h>
1415
#include <ble/gatt-service/nordic_spp_service_server.h>
@@ -1094,6 +1095,64 @@ pbio_error_t pbdrv_bluetooth_stop_observing_func(pbio_os_state_t *state, void *c
10941095
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
10951096
}
10961097

1098+
static void pbdrv_bluetooth_inquiry_unpack_scan_event(uint8_t *event_packet, pbdrv_bluetooth_inquiry_result_t *result) {
1099+
1100+
gap_event_inquiry_result_get_bd_addr(event_packet, result->bdaddr);
1101+
if (gap_event_inquiry_result_get_rssi_available(event_packet)) {
1102+
result->rssi = gap_event_inquiry_result_get_rssi(event_packet);
1103+
}
1104+
1105+
if (gap_event_inquiry_result_get_name_available(event_packet)) {
1106+
const uint8_t *name = gap_event_inquiry_result_get_name(event_packet);
1107+
const size_t name_len = gap_event_inquiry_result_get_name_len(event_packet);
1108+
snprintf(result->name, sizeof(result->name), "%.*s", (int)name_len, name);
1109+
}
1110+
1111+
result->class_of_device = gap_event_inquiry_result_get_class_of_device(event_packet);
1112+
}
1113+
1114+
pbio_error_t pbdrv_bluetooth_inquiry_scan_func(pbio_os_state_t *state, void *context) {
1115+
1116+
pbdrv_bluetooth_classic_task_context_t *task = context;
1117+
1118+
if (!task->cancel) {
1119+
task->cancel = pbio_os_timer_is_expired(&task->watchdog);
1120+
}
1121+
1122+
PBIO_OS_ASYNC_BEGIN(state);
1123+
1124+
DEBUG_PRINT("Start inquiry scan.\n");
1125+
1126+
gap_inquiry_start(task->inq_duration);
1127+
1128+
// Wait until scan timeout or the number of devices are found.
1129+
PBIO_OS_AWAIT_UNTIL(state, (*task->inq_count == *task->inq_count_max) || ({
1130+
1131+
if (task->cancel || *task->inq_count_max == 0) {
1132+
// Cancelled or the external data no longer available. Stop
1133+
// scanning and don't write any more data.
1134+
DEBUG_PRINT("Inquiry scan canceled.\n");
1135+
gap_inquiry_stop();
1136+
return PBIO_ERROR_CANCELED;
1137+
}
1138+
1139+
// Process a scan result.
1140+
if (hci_event_is_type(event_packet, GAP_EVENT_INQUIRY_RESULT)) {
1141+
DEBUG_PRINT("Received scan result.\n");
1142+
pbdrv_bluetooth_inquiry_result_t *result = &task->inq_results[(*task->inq_count)++];
1143+
pbdrv_bluetooth_inquiry_unpack_scan_event(event_packet, result);
1144+
1145+
}
1146+
1147+
// The wait until condition: inquiry complete.
1148+
hci_event_is_type(event_packet, GAP_EVENT_INQUIRY_COMPLETE);
1149+
}));
1150+
1151+
DEBUG_PRINT("Inquiry scan ended with %d results.\n", *task->inq_count);
1152+
1153+
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
1154+
}
1155+
10971156
const char *pbdrv_bluetooth_get_hub_name(void) {
10981157
return pbdrv_bluetooth_hub_name;
10991158
}

lib/pbio/include/pbdrv/bluetooth.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,30 @@ typedef struct {
585585
uint32_t class_of_device;
586586
} pbdrv_bluetooth_inquiry_result_t;
587587

588+
/**
589+
* Starts a classic Bluetooth inquiry scan.
590+
*
591+
* @param [in] results Array to store results.
592+
* @param [in] results_count Number of results found.
593+
* @param [in] results_count_max Maximum number of results to find. Will
594+
* stop if externally reset to 0.
595+
* @param [in] duration_ms Duration of the inquiry scan in milliseconds.
596+
* It will be internally rounded to the nearest
597+
* supported nonzero value.
598+
*/
599+
pbio_error_t pbdrv_bluetooth_start_inquiry_scan(pbdrv_bluetooth_inquiry_result_t *results, uint32_t *results_count, uint32_t *results_count_max, uint32_t duration_ms);
600+
601+
/**
602+
* Awaits for the classic Bluetooth inquiry scan to complete.
603+
*
604+
* @param [in] state Protothread state.
605+
* @param [in] context Not used.
606+
* @return ::PBIO_SUCCESS on completion.
607+
* ::PBIO_ERROR_AGAIN while awaiting.
608+
* or an thread specific error code if the operation failed.
609+
*/
610+
pbio_error_t pbdrv_bluetooth_await_classic_task(pbio_os_state_t *state, void *context);
611+
588612
#else // PBDRV_CONFIG_BLUETOOTH
589613

590614
static inline void pbdrv_bluetooth_init(void) {

lib/pbio/platform/essential_hub/btstack_config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
// BTstack features that can be enabled
1010
#define ENABLE_BLE
11+
#define ENABLE_CLASSIC
1112
// #define ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
1213
#define ENABLE_LE_CENTRAL
1314
#define ENABLE_LE_PERIPHERAL

lib/pbio/platform/essential_hub/pbdrvconfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#define PBDRV_CONFIG_BATTERY_ADC_TEMPERATURE_CH 2
2727

2828
#define PBDRV_CONFIG_BLUETOOTH (1)
29+
#define PBDRV_CONFIG_BLUETOOTH_NUM_CLASSIC_CONNECTIONS (2)
2930
#define PBDRV_CONFIG_BLUETOOTH_NUM_PERIPHERALS (2)
3031
#define PBDRV_CONFIG_BLUETOOTH_MAX_MTU_SIZE 515
3132
#define PBDRV_CONFIG_BLUETOOTH_BTSTACK (1)

lib/pbio/platform/ev3/pbdrvconfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#define PBDRV_CONFIG_I2C_EV3 (1)
4747

4848
#define PBDRV_CONFIG_BLUETOOTH (1)
49+
#define PBDRV_CONFIG_BLUETOOTH_NUM_CLASSIC_CONNECTIONS (2)
4950
#define PBDRV_CONFIG_BLUETOOTH_NUM_PERIPHERALS (2)
5051
#define PBDRV_CONFIG_BLUETOOTH_MAX_MTU_SIZE 515
5152
#define PBDRV_CONFIG_BLUETOOTH_BTSTACK (1)

lib/pbio/platform/prime_hub/btstack_config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
// BTstack features that can be enabled
1010
#define ENABLE_BLE
11+
#define ENABLE_CLASSIC
1112
// #define ENABLE_CC256X_BAUDRATE_CHANGE_FLOWCONTROL_BUG_WORKAROUND
1213
#define ENABLE_LE_CENTRAL
1314
#define ENABLE_LE_PERIPHERAL

lib/pbio/platform/prime_hub/pbdrvconfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#define PBDRV_CONFIG_BATTERY_ADC_TEMPERATURE_CH 2
2727

2828
#define PBDRV_CONFIG_BLUETOOTH (1)
29+
#define PBDRV_CONFIG_BLUETOOTH_NUM_CLASSIC_CONNECTIONS (2)
2930
#define PBDRV_CONFIG_BLUETOOTH_NUM_PERIPHERALS (2)
3031
#define PBDRV_CONFIG_BLUETOOTH_MAX_MTU_SIZE 515
3132
#define PBDRV_CONFIG_BLUETOOTH_BTSTACK (1)

lib/pbio/platform/virtual_hub/pbdrvconfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
// Use Bluetooth simulation locally.
1212
#ifndef PBDRV_CONFIG_RUN_ON_CI
1313
#define PBDRV_CONFIG_BLUETOOTH (1)
14+
#define PBDRV_CONFIG_BLUETOOTH_NUM_CLASSIC_CONNECTIONS (2)
1415
#define PBDRV_CONFIG_BLUETOOTH_NUM_PERIPHERALS (2)
1516
#define PBDRV_CONFIG_BLUETOOTH_BTSTACK (1)
1617
#define PBDRV_CONFIG_BLUETOOTH_BTSTACK_LE_SERVER (1)

0 commit comments

Comments
 (0)