Try and get shutdown to work

This commit is contained in:
Philip Gladstone 2021-10-18 02:22:10 +00:00
parent 0a4253aa91
commit 06becd1e8a
2 changed files with 62 additions and 50 deletions

View File

@ -187,7 +187,7 @@ static int
lble_access_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { lble_access_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) {
// Actually the only thing we care about is the arg and the ctxt // Actually the only thing we care about is the arg and the ctxt
printf("access_cb called with op %d\n", ctxt->op); MODLOG_DFLT(INFO, "access_cb called with op %d\n", ctxt->op);
size_t task_block_size = sizeof(task_block_t); size_t task_block_size = sizeof(task_block_t);
@ -215,7 +215,7 @@ lble_access_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_acces
} }
} }
printf("ABout to task_post\n"); MODLOG_DFLT(INFO, "ABout to task_post\n");
if (!task_post(TASK_PRIORITY_HIGH, task_handle, (task_param_t) task_block)) { if (!task_post(TASK_PRIORITY_HIGH, task_handle, (task_param_t) task_block)) {
free(task_block); free(task_block);
@ -225,7 +225,7 @@ lble_access_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_acces
response_message_t message; response_message_t message;
while (1) { while (1) {
printf("About to receive\n"); MODLOG_DFLT(INFO, "About to receive\n");
if (xQueueReceive(response_queue, &message, (TickType_t) (10000/portTICK_PERIOD_MS) ) != pdPASS) { if (xQueueReceive(response_queue, &message, (TickType_t) (10000/portTICK_PERIOD_MS) ) != pdPASS) {
free(task_block); free(task_block);
@ -289,14 +289,12 @@ lble_task_cb(task_param_t param, task_prio_t prio) {
// Now we have the value (-1), struct (-2), table (-3) // Now we have the value (-1), struct (-2), table (-3)
if (!lua_isnoneornil(L, -2)) { if (!lua_isnoneornil(L, -2)) {
// need to convert value // need to convert value
printf("About to convert vaclue for read\n");
if (!lua_istable(L, -1)) { if (!lua_istable(L, -1)) {
// wrap it in a table // wrap it in a table
lua_createtable(L, 1, 0); lua_createtable(L, 1, 0);
lua_pushvalue(L, -2); // Now have value, table, value, struct, table lua_pushvalue(L, -2); // Now have value, table, value, struct, table
lua_rawseti(L, -2, 1); lua_rawseti(L, -2, 1);
lua_remove(L, -2); // now have table, struct, chr table lua_remove(L, -2); // now have table, struct, chr table
printf("wrapped in table\n");
} }
// Now call struct.pack // Now call struct.pack
@ -349,7 +347,6 @@ lble_task_cb(task_param_t param, task_prio_t prio) {
goto cleanup; goto cleanup;
} }
int vals = lua_gettop(L) - stack_size; int vals = lua_gettop(L) - stack_size;
printf("unpacked %d vals\n", vals - 1);
// Note that the last entry is actually the string offset // Note that the last entry is actually the string offset
for (int i = 1; i < vals; i++) { for (int i = 1; i < vals; i++) {
@ -367,6 +364,15 @@ lble_task_cb(task_param_t param, task_prio_t prio) {
lua_remove(L, -2); // and throw away the table lua_remove(L, -2); // and throw away the table
} }
// value, struct, chr table // value, struct, chr table
// save to `value` if present
lua_getfield(L, -3, "value");
if (!lua_isnoneornil(L, -1)) {
lua_pop(L, 1);
lua_pushvalue(L, -1);
lua_setfield(L, -4, "value");
} else {
lua_pop(L, 1);
}
lua_getfield(L, -3, "write"); lua_getfield(L, -3, "write");
if (!lua_isnoneornil(L, -1)) { if (!lua_isnoneornil(L, -1)) {
lua_pushvalue(L, -4); // the characterstics table lua_pushvalue(L, -4); // the characterstics table
@ -379,14 +385,11 @@ lble_task_cb(task_param_t param, task_prio_t prio) {
} }
} else { } else {
lua_pop(L, 1); // Throw away the null write pointer lua_pop(L, 1); // Throw away the null write pointer
// just save the result in the value
lua_setfield(L, -3, "value");
message.errcode = 0;
} }
lua_pop(L, 1); // THrow away the value
} }
cleanup: cleanup:
printf("Returning code %d\n", message.errcode);
lua_pop(L, 2); lua_pop(L, 2);
message.seqno = task_block->seqno; message.seqno = task_block->seqno;
@ -400,8 +403,6 @@ lble_build_gatt_svcs(lua_State *L, struct ble_gatt_svc_def **resultp) {
// + number of characteristics (nc) + ns * sizeof(ble_gatt_chr_def) // + number of characteristics (nc) + ns * sizeof(ble_gatt_chr_def)
// + ns + nc * sizeof(ble_uuid_any_t) // + ns + nc * sizeof(ble_uuid_any_t)
printf("build_gatt_svcs\n");
lua_getfield(L, 1, "services"); lua_getfield(L, 1, "services");
if (!lua_istable(L, -1)) { if (!lua_istable(L, -1)) {
return luaL_error(L, "services entry must be a table"); return luaL_error(L, "services entry must be a table");
@ -428,7 +429,6 @@ lble_build_gatt_svcs(lua_State *L, struct ble_gatt_svc_def **resultp) {
int size = (ns + 1) * sizeof(struct ble_gatt_svc_def) + (nc + ns) * sizeof(struct ble_gatt_chr_def) + (ns + nc) * sizeof(ble_uuid_any_t); int size = (ns + 1) * sizeof(struct ble_gatt_svc_def) + (nc + ns) * sizeof(struct ble_gatt_chr_def) + (ns + nc) * sizeof(ble_uuid_any_t);
printf("Computed size: %d (nc %d, ns %d)\n", size, nc, ns);
struct ble_gatt_svc_def *svcs = malloc(size); struct ble_gatt_svc_def *svcs = malloc(size);
if (!svcs) { if (!svcs) {
@ -520,12 +520,6 @@ static int
gatt_svr_init(lua_State *L) { gatt_svr_init(lua_State *L) {
int rc; int rc;
printf("about to call gap_init\n");
ble_svc_gap_init();
printf("about to call gatt_init\n");
ble_svc_gatt_init();
// Now we have to build the gatt_svr_svcs data structure // Now we have to build the gatt_svr_svcs data structure
@ -534,8 +528,6 @@ gatt_svr_init(lua_State *L) {
free_gatt_svcs(L, gatt_svr_svcs); free_gatt_svcs(L, gatt_svr_svcs);
gatt_svr_svcs = svcs; gatt_svr_svcs = svcs;
printf("about to call count_cfg\n");
rc = ble_gatts_count_cfg(gatt_svr_svcs); rc = ble_gatts_count_cfg(gatt_svr_svcs);
if (rc != 0) { if (rc != 0) {
return luaL_error(L, "Failed to count gatts: %d", rc); return luaL_error(L, "Failed to count gatts: %d", rc);
@ -607,30 +599,39 @@ lble_host_task(void *param)
static void static void
lble_init_stack(lua_State *L) { lble_init_stack(lua_State *L) {
int ret = esp_nimble_hci_and_controller_init(); static char stack_inited;
if (ret != ESP_OK) { if (!stack_inited) {
luaL_error(L, "esp_nimble_hci_and_controller_init() failed with error: %d", ret); stack_inited = 1;
return; int ret = esp_nimble_hci_and_controller_init();
if (ret != ESP_OK) {
luaL_error(L, "esp_nimble_hci_and_controller_init() failed with error: %d", ret);
return;
}
nimble_port_init();
//Initialize the NimBLE Host configuration
nimble_port_freertos_init(lble_host_task);
printf("about to call gap_init\n");
ble_svc_gap_init();
printf("about to call gatt_init\n");
ble_svc_gatt_init();
} }
nimble_port_init();
//Initialize the NimBLE Host configuration
nimble_port_freertos_init(lble_host_task);
} }
static int static int
lble_gap_event(struct ble_gap_event *event, void *arg) lble_gap_event(struct ble_gap_event *event, void *arg)
{ {
printf("GAP event %d\n", event->type);
struct ble_gap_conn_desc desc; struct ble_gap_conn_desc desc;
int rc; int rc;
switch (event->type) { switch (event->type) {
case BLE_GAP_EVENT_CONNECT: case BLE_GAP_EVENT_CONNECT:
/* A new connection was established or a connection attempt failed. */ /* A new connection was established or a connection attempt failed. */
printf("connection %s; status=%d ", MODLOG_DFLT(INFO, "connection %s; status=%d ",
event->connect.status == 0 ? "established" : "failed", event->connect.status == 0 ? "established" : "failed",
event->connect.status); event->connect.status);
if (event->connect.status == 0) { if (event->connect.status == 0) {
@ -639,7 +640,7 @@ lble_gap_event(struct ble_gap_event *event, void *arg)
lble_print_conn_desc(&desc); lble_print_conn_desc(&desc);
} }
printf("\n"); MODLOG_DFLT(INFO, "\n");
if (event->connect.status != 0) { if (event->connect.status != 0) {
/* Connection failed; resume advertising. */ /* Connection failed; resume advertising. */
@ -648,9 +649,9 @@ lble_gap_event(struct ble_gap_event *event, void *arg)
return 0; return 0;
case BLE_GAP_EVENT_DISCONNECT: case BLE_GAP_EVENT_DISCONNECT:
printf("disconnect; reason=%d ", event->disconnect.reason); MODLOG_DFLT(INFO, "disconnect; reason=%d ", event->disconnect.reason);
lble_print_conn_desc(&event->disconnect.conn); lble_print_conn_desc(&event->disconnect.conn);
printf("\n"); MODLOG_DFLT(INFO, "\n");
/* Connection terminated; resume advertising. */ /* Connection terminated; resume advertising. */
lble_start_advertising(); lble_start_advertising();
@ -732,7 +733,7 @@ lble_start_advertising() {
/* Figure out address to use while advertising (no privacy for now) */ /* Figure out address to use while advertising (no privacy for now) */
rc = ble_hs_id_infer_auto(0, &own_addr_type); rc = ble_hs_id_infer_auto(0, &own_addr_type);
if (rc != 0) { if (rc != 0) {
return printf("error determining address type; rc=%d", rc); return MODLOG_DFLT(INFO, "error determining address type; rc=%d", rc);
} }
/** /**
@ -779,13 +780,13 @@ lble_start_advertising() {
scan_response_fields.name_is_complete = 1; scan_response_fields.name_is_complete = 1;
rc = ble_gap_adv_rsp_set_fields(&scan_response_fields); rc = ble_gap_adv_rsp_set_fields(&scan_response_fields);
if (rc) { if (rc) {
return printf("gap_adv_rsp_set_fields failed: %d", rc); return MODLOG_DFLT(INFO, "gap_adv_rsp_set_fields failed: %d", rc);
} }
} }
rc = ble_gap_adv_set_fields(&fields); rc = ble_gap_adv_set_fields(&fields);
if (rc != 0) { if (rc != 0) {
return printf("error setting advertisement data; rc=%d", rc); return MODLOG_DFLT(INFO, "error setting advertisement data; rc=%d", rc);
} }
/* Begin advertising. */ /* Begin advertising. */
@ -795,7 +796,7 @@ lble_start_advertising() {
rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER, rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER,
&adv_params, lble_gap_event, NULL); &adv_params, lble_gap_event, NULL);
if (rc != 0) { if (rc != 0) {
return printf("error enabling advertisement; rc=%d", rc); return MODLOG_DFLT(INFO, "error enabling advertisement; rc=%d", rc);
} }
return 0; return 0;
@ -857,7 +858,6 @@ static int lble_init(lua_State *L) {
// Passed the config table // Passed the config table
luaL_checktype(L, 1, LUA_TTABLE); luaL_checktype(L, 1, LUA_TTABLE);
printf("About to init_stack");
lble_init_stack(L); lble_init_stack(L);
lua_getfield(L, 1, "name"); lua_getfield(L, 1, "name");
@ -899,6 +899,16 @@ static int lble_init(lua_State *L) {
} }
static int lble_shutdown(lua_State *L) { static int lble_shutdown(lua_State *L) {
if (nimble_port_stop()) {
return luaL_error(L, "Failed to stop the NIMBLE task");
}
nimble_port_deinit();
if (ESP_OK != esp_nimble_hci_and_controller_deinit()) {
return luaL_error(L, "Failed to shutdown the BLE controller");
}
return 0; return 0;
} }

View File

@ -9,7 +9,10 @@ This allows you to build simple gadgets that can be interrogated and controlled
## ble.init(configuration) ## ble.init(configuration)
This initializes the BlueTooth stack and starts advertising according to the data in the This initializes the BlueTooth stack and starts advertising according to the data in the
configuration table. See below for a detailed description of this table. configuration table. See below for a detailed description of this table.
Once the stack is initialized, another `init` can be performed and it will switch over to using
the new config.
#### Syntax #### Syntax
`ble.init(ble_config)` `ble.init(ble_config)`
@ -26,23 +29,19 @@ local config = {name="MyGadget=", services={{uuid="0123456789abcdef0123456789abc
ble.init(config) ble.init(config)
``` ```
## bthci.shutdown(callback) ## ble.shutdown()
Shuts down the BlueTooth controller and returns it to the state where another `init` can be performed. Shuts down the BlueTooth controller and returns it to the state where another `init` can be performed.
#### Syntax #### Syntax
`ble.shutdown([callback])` `ble.shutdown()`
#### Parameters
- `callback` optional function to be invoked when the shutdown completes. Its
only argument is an error code, or `nil` on success.
#### Returns #### Returns
`nil` `nil`
#### Example #### Example
```lua ```lua
ble.shutdown(function(err) print(err or "Ok!") end) ble.shutdown()
``` ```
## Conventions ## Conventions
@ -82,7 +81,10 @@ The characteristics are treated as read/write unless only one of the `read` or `
The calling conventions for these functions are as follows: The calling conventions for these functions are as follows:
- `read` This is invoked with the charactersitic table as its only argument. - `read` This is invoked with the characteristic table as its only argument.
- `write` This is invoked with two arguments, the characteristic table and the data to be written (after conversion by `type`) - `write` This is invoked with two arguments, the characteristic table and the data to be written (after conversion by `type`)
### Type conversions
If the `type` value converts a single item, then that will be the value that is placed into the `value` element. If it converts multiple elements, then the elements will be placed into an array that that will be plaed into the `value` element.