Skip to content

Commit 26a3874

Browse files
committed
Bluetooth: Classic: add page scan param update
add BR/EDR page scan param update Signed-off-by: Kai Cheng <[email protected]>
1 parent c87436e commit 26a3874

File tree

3 files changed

+275
-0
lines changed

3 files changed

+275
-0
lines changed

include/zephyr/bluetooth/classic/classic.h

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,191 @@ int bt_br_set_discoverable(bool enable, bool limited);
204204
*/
205205
int bt_br_set_connectable(bool enable);
206206

207+
/**
208+
* @name Defined BR Page Scan timers
209+
* @{
210+
*/
211+
#define BT_BR_PAGE_SCAN_INTERVAL_R0 0x0800 /* 0x0800, 1.280s, U:0.625 */
212+
#define BT_BR_PAGE_SCAN_WINDOW_R0 0x0800 /* 0x0800, 1.280s, U:0.625 */
213+
214+
#define BT_BR_PAGE_SCAN_FAST_INTERVAL_R1 0x00a0 /* 0x00a0, 100.0ms, U:0.625 */
215+
#define BT_BR_PAGE_SCAN_FAST_WINDOW_R1 0x4000 /* 0x4000, 10.240s, U:0.625 */
216+
217+
#define BT_BR_PAGE_SCAN_MEDIUM_INTERVAL_R1 0x0800 /* 0x0800, 1.280s, U:0.625 */
218+
#define BT_BR_PAGE_SCAN_MEDIUM_WINDOW_R1 0x4000 /* 0x4000, 10.240s, U:0.625 */
219+
220+
#define BT_BR_PAGE_SCAN_SLOW_INTERVAL_R1 0x0800 /* 0x0800, 1.280s, U:0.625 */
221+
#define BT_BR_PAGE_SCAN_SLOW_WINDOW_R1 0x4000 /* 0x4000, 10.240s, U:0.625 */
222+
223+
#define BT_BR_PAGE_SCAN_FAST_INTERVAL_R2 0x1000 /* 0x1000, 2.560s, U:0.625 */
224+
#define BT_BR_PAGE_SCAN_FAST_WINDOW_R2 0x4000 /* 0x4000, 10.240s, U:0.625 */
225+
226+
#define BT_BR_PAGE_SCAN_SLOW_INTERVAL_R2 0x1000 /* 0x1000, 2.560s, U:0.625 */
227+
#define BT_BR_PAGE_SCAN_SLOW_WINDOW_R2 0x4000 /* 0x4000, 10.240s, U:0.625 */
228+
229+
/** Page scan type. */
230+
enum bt_br_scan_type {
231+
/** Standard scan (default) */
232+
BT_BR_SCAN_TYPE_STANDARD = 0,
233+
234+
/** Interlaced scan (1.2 devices only) */
235+
BT_BR_SCAN_TYPE_INTERLACED = 1,
236+
};
237+
238+
struct bt_br_page_scan_param {
239+
/** Page scan interval in 0.625 ms units
240+
* Range: 0x0012 to 0x1000; only even values are valid.
241+
*/
242+
uint16_t interval;
243+
244+
/** Page scan window in 0.625 ms units
245+
* Range: 0x0011 to 0x1000.
246+
*/
247+
uint16_t window;
248+
249+
/** Page scan type. */
250+
enum bt_br_scan_type type;
251+
};
252+
253+
/**
254+
* @brief Initialize BR Scan parameters
255+
*
256+
* @param _interval Scan interval
257+
* @param _window Scan window
258+
* @param _type Scan type
259+
*/
260+
261+
#define BT_BR_SCAN_INIT(_interval, _window, _type) \
262+
{ \
263+
.interval = (_interval), \
264+
.window = (_window), \
265+
.type = (_type) \
266+
}
267+
268+
/**
269+
* Helper to declare BR/EDR page scan parameters inline
270+
*
271+
* @param _interval page scan interval, N * 0.625 milliseconds
272+
* @param _window page scan window, N * 0.625 milliseconds
273+
* @param _type BT_BR_SCAN_TYPE_STANDARD or BT_BR_SCAN_TYPE_INTERLACED
274+
*/
275+
276+
#define BT_BR_PAGE_SCAN_PARAM(_interval, _window, _type) \
277+
((const struct bt_br_page_scan_param[]) { \
278+
BT_BR_SCAN_INIT(_interval, _window, _type) \
279+
})
280+
281+
/**
282+
* @brief Default page scan parameters for R0
283+
*
284+
* Page scan interval and window are set to 1.280 seconds (0x0800 in 0.625 ms units).
285+
* The scan type is set to standard.
286+
*/
287+
#define BT_BR_PAGE_SCAN_PARAM_R0 BT_BR_PAGE_SCAN_PARAM(BT_BR_PAGE_SCAN_INTERVAL_R0, \
288+
BT_BR_PAGE_SCAN_WINDOW_R0, \
289+
BT_BR_SCAN_TYPE_STANDARD)
290+
291+
/**
292+
* @brief Fast page scan parameters for R1
293+
*
294+
* Page scan interval is set to 100 ms (0x00A0 in 0.625 ms units), and the
295+
* page scan window is set to 10.240 seconds (0x27FF in 1 ms units).
296+
* The scan type is set to interlaced.
297+
*/
298+
#define BT_BR_PAGE_SCAN_PARAM_FAST_R1 \
299+
BT_BR_PAGE_SCAN_PARAM(BT_BR_PAGE_SCAN_FAST_INTERVAL_R1, \
300+
BT_BR_PAGE_SCAN_FAST_WINDOW_R1, \
301+
BT_BR_SCAN_TYPE_INTERLACED)
302+
303+
/**
304+
* @brief Medium page scan parameters for R1
305+
*
306+
* Page scan interval and window are set to 1.280 seconds (0x0800 in 0.625 ms units).
307+
* The scan type is set to standard.
308+
*/
309+
#define BT_BR_PAGE_SCAN_PARAM_MEDIUM_R1 \
310+
BT_BR_PAGE_SCAN_PARAM( \
311+
BT_BR_PAGE_SCAN_MEDIUM_INTERVAL_R1, \
312+
BT_BR_PAGE_SCAN_MEDIUM_WINDOW_R1, \
313+
BT_BR_SCAN_TYPE_INTERLACED)
314+
315+
/**
316+
* @brief Slow page scan parameters for R1
317+
*
318+
* Page scan interval and window are set to 1.280 seconds (0x0800 in 0.625 ms units).
319+
* The scan type is set to standard.
320+
*/
321+
#define BT_BR_PAGE_SCAN_PARAM_SLOW_R1 \
322+
BT_BR_PAGE_SCAN_PARAM( \
323+
BT_BR_PAGE_SCAN_SLOW_INTERVAL_R1, \
324+
BT_BR_PAGE_SCAN_SLOW_WINDOW_R1, \
325+
BT_BR_SCAN_TYPE_STANDARD)
326+
327+
/**
328+
* @brief Fast page scan parameters for R2
329+
*
330+
* Page scan interval is set to 2.560 seconds (0x1000 in 0.625 ms units), and the
331+
* page scan window is set to 10.240 seconds (0x27FF in 1 ms units).
332+
* The scan type is set to standard.
333+
*/
334+
#define BT_BR_PAGE_SCAN_PARAM_FAST_R2 \
335+
BT_BR_PAGE_SCAN_PARAM( \
336+
BT_BR_PAGE_SCAN_FAST_INTERVAL_R2, \
337+
BT_BR_PAGE_SCAN_FAST_WINDOW_R2, \
338+
BT_BR_SCAN_TYPE_INTERLACED)
339+
340+
/**
341+
* @brief Slow page scan parameters for R2
342+
*
343+
* Page scan interval and window are set to 2.560 seconds (0x1000 in 0.625 ms units).
344+
* The scan type is set to standard.
345+
*/
346+
#define BT_BR_PAGE_SCAN_PARAM_SLOW_R2 \
347+
BT_BR_PAGE_SCAN_PARAM( \
348+
BT_BR_PAGE_SCAN_SLOW_INTERVAL_R2, \
349+
BT_BR_PAGE_SCAN_SLOW_WINDOW_R2, \
350+
BT_BR_SCAN_TYPE_STANDARD)
351+
352+
/**
353+
* @brief Update BR/EDR page scan parameters.
354+
*
355+
* This function updates the page scan parameters of the local BR/EDR controller.
356+
* Page scan parameters determine how the controller listens for incoming
357+
* connection requests from remote devices.
358+
*
359+
* The function validates the provided parameters, including the interval,
360+
* window, and scan type, and sends the appropriate HCI commands to update
361+
* the controller's page scan activity and scan type.
362+
*
363+
* The user can set custom page scan parameters using the helper macro
364+
* `BT_BR_PAGE_SCAN_PARAM(interval, window, type)` to define their own values.
365+
* Alternatively, the user can use predefined standard parameters as defined
366+
* in the Bluetooth specification:
367+
* - `BT_BR_PAGE_SCAN_PARAM_R0`: Default page scan parameters.
368+
* - `BT_BR_PAGE_SCAN_PARAM_FAST_R1`: Fast page scan parameters for R1.
369+
* - `BT_BR_PAGE_SCAN_PARAM_MEDIUM_R1`: Medium page scan parameters for R1.
370+
* - `BT_BR_PAGE_SCAN_PARAM_SLOW_R1`: Slow page scan parameters for R1.
371+
* - `BT_BR_PAGE_SCAN_PARAM_FAST_R2`: Fast page scan parameters for R2.
372+
* - `BT_BR_PAGE_SCAN_PARAM_SLOW_R2`: Slow page scan parameters for R2.
373+
*
374+
* These predefined parameters are designed to meet common use cases and
375+
* ensure compliance with the Bluetooth specification.
376+
*
377+
* @param param Page scan parameters, including:
378+
* - interval: Time between consecutive page scans (in 0.625 ms units).
379+
* Must be in the range [0x0012, 0x1000].
380+
* - window: Duration of a single page scan (in 0.625 ms units).
381+
* Must be in the range [0x0011, 0x1000].
382+
* - type: Page scan type (e.g., standard or interlaced).
383+
*
384+
* @return 0 on success.
385+
* @return -EINVAL if the provided parameters are invalid.
386+
* @return -EAGAIN if the device is not ready.
387+
* @return -ENOBUFS if memory allocation for HCI commands fails.
388+
* @return Other negative error codes for internal failures.
389+
*/
390+
int bt_br_page_scan_update_param(const struct bt_br_page_scan_param *param);
391+
207392
/**
208393
* @brief Set the Class of Device configuration parameter of the local
209394
* BR/EDR Controller.

include/zephyr/bluetooth/hci_types.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,12 @@ struct bt_hci_rp_write_conn_accept_timeout {
636636
#define BT_BREDR_SCAN_INQUIRY 0x01
637637
#define BT_BREDR_SCAN_PAGE 0x02
638638

639+
#define BT_HCI_OP_WRITE_PAGE_SCAN_ACTIVITY BT_OP(BT_OGF_BASEBAND, 0x001c) /* 0x0c1c */
640+
struct bt_hci_cp_write_scan_activity {
641+
uint16_t interval;
642+
uint16_t window;
643+
} __packed;
644+
639645
#define BT_HCI_OP_READ_CLASS_OF_DEVICE BT_OP(BT_OGF_BASEBAND, 0x0023) /* 0x0c23 */
640646
struct bt_hci_rp_read_class_of_device {
641647
uint8_t status;
@@ -842,6 +848,11 @@ struct bt_hci_cp_write_inquiry_mode {
842848
uint8_t mode;
843849
} __packed;
844850

851+
#define BT_HCI_OP_WRITE_PAGE_SCAN_TYPE BT_OP(BT_OGF_BASEBAND, 0x0047) /* 0x0c47 */
852+
struct bt_hci_cp_write_scan_type {
853+
uint8_t type;
854+
} __packed;
855+
845856
#define BT_HCI_OP_WRITE_SSP_MODE BT_OP(BT_OGF_BASEBAND, 0x0056) /* 0x0c56 */
846857
struct bt_hci_cp_write_ssp_mode {
847858
uint8_t mode;

subsys/bluetooth/host/classic/br.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,6 +1296,85 @@ int bt_br_set_discoverable(bool enable, bool limited)
12961296
return 0;
12971297
}
12981298

1299+
static int bt_br_write_scan_activity(uint16_t opcode, uint16_t interval, uint16_t window)
1300+
{
1301+
struct bt_hci_cp_write_scan_activity *cp;
1302+
struct net_buf *buf;
1303+
1304+
if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
1305+
return -EAGAIN;
1306+
}
1307+
1308+
buf = bt_hci_cmd_alloc(K_FOREVER);
1309+
if (!buf) {
1310+
return -ENOBUFS;
1311+
}
1312+
1313+
cp = net_buf_add(buf, sizeof(*cp));
1314+
cp->interval = sys_cpu_to_le16(interval);
1315+
cp->window = sys_cpu_to_le16(window);
1316+
1317+
return bt_hci_cmd_send_sync(opcode, buf, NULL);
1318+
}
1319+
1320+
static int bt_br_write_scan_type(uint16_t opcode, uint8_t type)
1321+
{
1322+
struct bt_hci_cp_write_scan_type *cp;
1323+
struct net_buf *buf;
1324+
int err;
1325+
1326+
if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
1327+
return -EAGAIN;
1328+
}
1329+
1330+
buf = bt_hci_cmd_alloc(K_FOREVER);
1331+
if (!buf) {
1332+
return -ENOBUFS;
1333+
}
1334+
1335+
cp = net_buf_add(buf, sizeof(*cp));
1336+
cp->type = type;
1337+
1338+
err = bt_hci_cmd_send_sync(opcode, buf, NULL);
1339+
if (err) {
1340+
return err;
1341+
}
1342+
1343+
return 0;
1344+
}
1345+
1346+
int bt_br_page_scan_update_param(const struct bt_br_page_scan_param *param)
1347+
{
1348+
int err;
1349+
1350+
if (param->interval < 0x0012 || param->interval > 0x1000) {
1351+
return -EINVAL;
1352+
}
1353+
1354+
if (param->window < 0x0011 || param->window > 0x1000) {
1355+
return -EINVAL;
1356+
}
1357+
1358+
if (param->interval < param->window) {
1359+
return -EINVAL;
1360+
}
1361+
1362+
err = bt_br_write_scan_activity(BT_HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1363+
param->interval, param->window);
1364+
if (err) {
1365+
LOG_ERR("write page scan activity failed (err %d)", err);
1366+
return err;
1367+
}
1368+
1369+
err = bt_br_write_scan_type(BT_HCI_OP_WRITE_PAGE_SCAN_TYPE, param->type);
1370+
if (err) {
1371+
LOG_ERR("write page scan type failed (err %d)", err);
1372+
return err;
1373+
}
1374+
1375+
return 0;
1376+
}
1377+
12991378
int bt_br_set_class_of_device(uint32_t cod)
13001379
{
13011380
int err;

0 commit comments

Comments
 (0)