diff --git a/apps/btshell/src/btshell.h b/apps/btshell/src/btshell.h index 595fd986e..f9ae0fdd3 100644 --- a/apps/btshell/src/btshell.h +++ b/apps/btshell/src/btshell.h @@ -120,10 +120,14 @@ int btshell_write_reliable(uint16_t conn_handle, int btshell_ext_adv_configure(uint8_t instance, const struct ble_gap_ext_adv_params *params, int8_t *selected_tx_power); +int btshell_ext_adv_start(uint8_t instance, int duration, + int max_events, bool restart); +int btshell_ext_adv_stop(uint8_t instance); #endif int btshell_adv_start(uint8_t own_addr_type, const ble_addr_t *direct_addr, int32_t duration_ms, - const struct ble_gap_adv_params *params); + const struct ble_gap_adv_params *params, + bool restart); int btshell_adv_stop(void); int btshell_conn_initiate(uint8_t own_addr_type, const ble_addr_t *peer_addr, int32_t duration_ms, diff --git a/apps/btshell/src/cmd.c b/apps/btshell/src/cmd.c index ff23eb9f5..0ad0e8a5f 100644 --- a/apps/btshell/src/cmd.c +++ b/apps/btshell/src/cmd.c @@ -338,6 +338,7 @@ cmd_advertise_start(int argc, char **argv) int max_events; uint8_t instance; int duration; + bool restart; int rc; rc = parse_arg_all(argc - 1, argv + 1); @@ -368,7 +369,13 @@ cmd_advertise_start(int argc, char **argv) return rc; } - rc = ble_gap_ext_adv_start(instance, duration, max_events); + restart = parse_arg_bool_dflt("restart", 0, &rc); + if (rc != 0) { + console_printf("invalid 'restart' parameter\n"); + return rc; + } + + rc = btshell_ext_adv_start(instance, duration, max_events, restart); if (rc) { console_printf("failed to start advertising instance\n"); return rc; @@ -399,7 +406,7 @@ cmd_advertise_stop(int argc, char **argv) return rc; } - rc = ble_gap_ext_adv_stop(instance); + rc = btshell_ext_adv_stop(instance); if (rc) { console_printf("failed to stop advertising instance\n"); return rc; @@ -488,6 +495,7 @@ static const struct shell_param advertise_start_params[] = { {"instance", "default: 0"}, {"duration", "advertising duration in 10ms units, default: 0 (forever)"}, {"max_events", "max number of advertising events, default: 0 (no limit)"}, + {"restart", "restart advertising after disconnect, usage: =[0-1], default: 0"}, {NULL, NULL} }; @@ -543,6 +551,7 @@ cmd_advertise(int argc, char **argv) ble_addr_t peer_addr; ble_addr_t *peer_addr_param = &peer_addr; uint8_t own_addr_type; + bool restart; int rc; rc = parse_arg_all(argc - 1, argv + 1); @@ -589,6 +598,12 @@ cmd_advertise(int argc, char **argv) return rc; } + restart = parse_arg_bool_dflt("restart", 0, &rc); + if (rc != 0) { + console_printf("invalid 'restart' parameter\n"); + return rc; + } + own_addr_type = parse_arg_kv_dflt("own_addr_type", cmd_own_addr_types, BLE_OWN_ADDR_PUBLIC, &rc); if (rc != 0) { @@ -635,7 +650,7 @@ cmd_advertise(int argc, char **argv) } rc = btshell_adv_start(own_addr_type, peer_addr_param, duration_ms, - ¶ms); + ¶ms, restart); if (rc != 0) { console_printf("advertise fail: %d\n", rc); return rc; @@ -658,6 +673,7 @@ static const struct shell_param advertise_params[] = { {"interval_max", "usage: =[0-UINT16_MAX], default: 0"}, {"high_duty", "usage: =[0-1], default: 0"}, {"duration", "usage: =[1-INT32_MAX], default: INT32_MAX"}, + {"restart", "restart advertising after disconnect, usage: =[0-1], default: 0"}, {NULL, NULL} }; diff --git a/apps/btshell/src/main.c b/apps/btshell/src/main.c index 9a6ddecbc..ab605273c 100644 --- a/apps/btshell/src/main.c +++ b/apps/btshell/src/main.c @@ -129,6 +129,21 @@ int btshell_full_disc_prev_chr_val; #define BTSHELL_AUTO_DEVICE_NAME "" #endif +#if MYNEWT_VAL(BLE_EXT_ADV) +struct { + bool restart; + uint16_t conn_handle; +} ext_adv_restart[BLE_ADV_INSTANCES]; +#endif + +static struct { + bool restart; + uint8_t own_addr_type; + ble_addr_t direct_addr; + int32_t duration_ms; + struct ble_gap_adv_params params; +} adv_params; + static void btshell_print_error(char *msg, uint16_t conn_handle, const struct ble_gatt_error *error) @@ -985,6 +1000,43 @@ common_data: } #endif +static int +btshell_gap_event(struct ble_gap_event *event, void *arg); + +static int +btshell_restart_adv(struct ble_gap_event *event) +{ + int rc = 0; +#if MYNEWT_VAL(BLE_EXT_ADV) + uint8_t i; +#endif + + if (event->type != BLE_GAP_EVENT_DISCONNECT) { + return -1; + } + +#if MYNEWT_VAL(BLE_EXT_ADV) + for (i = 0; i < BLE_ADV_INSTANCES; ++i) { + if (ext_adv_restart[i].restart && + (ext_adv_restart[i].conn_handle == + event->disconnect.conn.conn_handle)) { + rc = ble_gap_ext_adv_start(i, 0, 0); + break; + } + } +#else + if (!adv_params.restart) { + return 0; + } + + rc = ble_gap_adv_start(adv_params.own_addr_type, &adv_params.direct_addr, + adv_params.duration_ms, &adv_params.params, + btshell_gap_event, NULL); +#endif + + return rc; +} + static int btshell_gap_event(struct ble_gap_event *event, void *arg) { @@ -1014,7 +1066,8 @@ btshell_gap_event(struct ble_gap_event *event, void *arg) if (conn_idx != -1) { btshell_conn_delete_idx(conn_idx); } - return 0; + + return btshell_restart_adv(event); #if MYNEWT_VAL(BLE_EXT_ADV) case BLE_GAP_EVENT_EXT_DISC: btshell_decode_event_type(&event->ext_disc, arg); @@ -1074,6 +1127,9 @@ btshell_gap_event(struct ble_gap_event *event, void *arg) console_printf("advertise complete; reason=%d, instance=%u, handle=%d\n", event->adv_complete.reason, event->adv_complete.instance, event->adv_complete.conn_handle); + + ext_adv_restart[event->adv_complete.instance].conn_handle = + event->adv_complete.conn_handle; #else console_printf("advertise complete; reason=%d\n", event->adv_complete.reason); @@ -1439,6 +1495,36 @@ btshell_ext_adv_configure(uint8_t instance, return ble_gap_ext_adv_configure(instance, params, selected_tx_power, btshell_gap_event, NULL); } + +int +btshell_ext_adv_start(uint8_t instance, int duration, + int max_events, bool restart) +{ + int rc; + + /* Advertising restart doesn't make sense + * with limited duration or events + */ + if (restart && (duration == 0) && (max_events == 0)) { + ext_adv_restart[instance].restart = restart; + } + + rc = ble_gap_ext_adv_start(instance, duration, max_events); + + return rc; +} + +int +btshell_ext_adv_stop(uint8_t instance) +{ + int rc; + + ext_adv_restart[instance].restart = false; + + rc = ble_gap_ext_adv_stop(instance); + + return rc; +} #endif int @@ -1446,16 +1532,33 @@ btshell_adv_stop(void) { int rc; + adv_params.restart = false; + rc = ble_gap_adv_stop(); return rc; } int btshell_adv_start(uint8_t own_addr_type, const ble_addr_t *direct_addr, - int32_t duration_ms, const struct ble_gap_adv_params *params) + int32_t duration_ms, const struct ble_gap_adv_params *params, + bool restart) { int rc; + if (restart) { + adv_params.restart = restart; + adv_params.own_addr_type = own_addr_type; + adv_params.duration_ms = duration_ms; + + if (direct_addr) { + memcpy(&adv_params.direct_addr, direct_addr, sizeof(adv_params.direct_addr)); + } + + if (params) { + memcpy(&adv_params.params, params, sizeof(adv_params.params)); + } + } + rc = ble_gap_adv_start(own_addr_type, direct_addr, duration_ms, params, btshell_gap_event, NULL); return rc; @@ -2042,6 +2145,19 @@ btshell_l2cap_send(uint16_t conn_handle, uint16_t idx, uint16_t bytes) #endif } + +static void +btshell_init_ext_adv_restart(void) +{ +#if MYNEWT_VAL(BLE_EXT_ADV) + int i; + + for (i = 0; i < BLE_ADV_INSTANCES; ++i) { + ext_adv_restart[i].conn_handle = BLE_HS_CONN_HANDLE_NONE; + } +#endif +} + /** * main * @@ -2116,6 +2232,8 @@ main(int argc, char **argv) os_callout_init(&btshell_tx_timer, os_eventq_dflt_get(), btshell_tx_timer_cb, NULL); + btshell_init_ext_adv_restart(); + while (1) { os_eventq_run(os_eventq_dflt_get()); }