Skip to content

Commit 0e4eef9

Browse files
laurensvalkjuagol
andcommitted
pbio/drv/bluetooth: Implement rfcomm_scan.
This adds a handler for Bluetooth classic tasks to the Bluetooth driver. Co-authored-by: James Aguilar <[email protected]>
1 parent 05065ff commit 0e4eef9

File tree

11 files changed

+198
-11
lines changed

11 files changed

+198
-11
lines changed

lib/pbio/drv/bluetooth/bluetooth.c

Lines changed: 65 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

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

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

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

509554
/**
@@ -594,6 +639,17 @@ pbio_error_t pbdrv_bluetooth_process_thread(pbio_os_state_t *state, void *contex
594639
PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_start_observing_func(&sub, NULL));
595640
observe_restart_requested = false;
596641
}
642+
643+
#if PBDRV_CONFIG_BLUETOOTH_CLASSIC
644+
// Handle pending Bluetooth classic task, if any.
645+
static pbdrv_bluetooth_classic_task_context_t *task;
646+
task = &pbdrv_bluetooth_classic_task_context;
647+
if (task->func) {
648+
PBIO_OS_AWAIT(state, &sub, task->err = task->func(&sub, task));
649+
task->func = NULL;
650+
task->cancel = false;
651+
}
652+
#endif // PBDRV_CONFIG_BLUETOOTH_CLASSIC
597653
}
598654

599655
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
@@ -63,6 +63,48 @@ extern pbdrv_bluetooth_start_observing_callback_t pbdrv_bluetooth_observe_callba
6363

6464
pbio_error_t pbdrv_bluetooth_process_thread(pbio_os_state_t *state, void *context);
6565

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

68110
#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>
@@ -1098,6 +1099,64 @@ pbio_error_t pbdrv_bluetooth_stop_observing_func(pbio_os_state_t *state, void *c
10981099
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
10991100
}
11001101

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

lib/pbio/include/pbdrv/bluetooth.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,30 @@ typedef struct {
561561
uint32_t class_of_device;
562562
} pbdrv_bluetooth_inquiry_result_t;
563563

564+
/**
565+
* Starts a classic Bluetooth inquiry scan.
566+
*
567+
* @param [in] results Array to store results.
568+
* @param [in] results_count Number of results found.
569+
* @param [in] results_count_max Maximum number of results to find. Will
570+
* stop if externally reset to 0.
571+
* @param [in] duration_ms Duration of the inquiry scan in milliseconds.
572+
* It will be internally rounded to the nearest
573+
* supported nonzero value.
574+
*/
575+
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);
576+
577+
/**
578+
* Awaits for the classic Bluetooth inquiry scan to complete.
579+
*
580+
* @param [in] state Protothread state.
581+
* @param [in] context Not used.
582+
* @return ::PBIO_SUCCESS on completion.
583+
* ::PBIO_ERROR_AGAIN while awaiting.
584+
* or an thread specific error code if the operation failed.
585+
*/
586+
pbio_error_t pbdrv_bluetooth_await_classic_task(pbio_os_state_t *state, void *context);
587+
564588
#else // PBDRV_CONFIG_BLUETOOTH
565589

566590
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_CLASSIC (1)
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_CLASSIC (1)
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_CLASSIC (1)
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_CLASSIC (1)
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)