Making progress on ble

This commit is contained in:
Philip Gladstone 2021-10-19 22:14:32 +00:00
parent e80361061c
commit 28cb8981b2
3 changed files with 84 additions and 72 deletions

View File

@ -64,6 +64,8 @@ static QueueHandle_t response_queue;
static int struct_pack_index; static int struct_pack_index;
static int struct_unpack_index; static int struct_unpack_index;
static enum { STOPPED, RUNNING, SHUTTING } inited;
static int seqno; static int seqno;
// Note that the buffer should be freed // Note that the buffer should be freed
@ -490,7 +492,21 @@ lble_build_gatt_svcs(lua_State *L, struct ble_gatt_svc_def **resultp) {
if (lua_getfield(L, -1, "value") != LUA_TNIL) { if (lua_getfield(L, -1, "value") != LUA_TNIL) {
chr->flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE; chr->flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE;
lua_pop(L, 1); // pop off value
int flags = 0;
lua_getfield(L, -2, "read");
if (lua_isboolean(L, 1) && lua_toboolean(L, -1)) {
flags = BLE_GATT_CHR_F_READ;
}
lua_getfield(L, -3, "write");
if (lua_isboolean(L, 1) && lua_toboolean(L, -1)) {
flags |= BLE_GATT_CHR_F_WRITE;
}
if (flags) {
chr->flags = flags;
}
lua_pop(L, 3); // pop off value, read, write
} else { } else {
lua_getfield(L, -2, "read"); lua_getfield(L, -2, "read");
if (!lua_isnoneornil (L, -1)) { if (!lua_isnoneornil (L, -1)) {
@ -729,6 +745,10 @@ lble_start_advertising() {
const char *name = gadget_name; const char *name = gadget_name;
int rc; int rc;
if (inited != RUNNING) {
return 0;
}
/* 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) {
@ -850,6 +870,9 @@ gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
static int lble_init(lua_State *L) { static int lble_init(lua_State *L) {
if (inited != STOPPED) {
return luaL_error(L, "ble is already running");
}
if (!struct_pack_index) { if (!struct_pack_index) {
lua_getglobal(L, "struct"); lua_getglobal(L, "struct");
lua_getfield(L, -1, "pack"); lua_getfield(L, -1, "pack");
@ -924,10 +947,14 @@ static int lble_init(lua_State *L) {
synced = true; synced = true;
} }
inited = RUNNING;
return 0; return 0;
} }
static int lble_shutdown(lua_State *L) { static int lble_shutdown(lua_State *L) {
inited = SHUTTING;
if (nimble_port_stop()) { if (nimble_port_stop()) {
return luaL_error(L, "Failed to stop the NIMBLE task"); return luaL_error(L, "Failed to stop the NIMBLE task");
} }
@ -938,6 +965,8 @@ static int lble_shutdown(lua_State *L) {
return luaL_error(L, "Failed to shutdown the BLE controller"); return luaL_error(L, "Failed to shutdown the BLE controller");
} }
inited = STOPPED;
return 0; return 0;
} }

View File

@ -383,60 +383,40 @@ static int file_stat( lua_State* L )
// g_read() // g_read()
static int file_g_read( lua_State* L, int n, int16_t end_char, int fd ) static int file_g_read( lua_State* L, int n, int16_t end_char, int fd )
{ {
char *heap_mem = NULL; int i, j;
luaL_Buffer b;
if(n <= 0) char p[LUAL_BUFFERSIZE/2];
n = FILE_READ_CHUNK;
if(end_char < 0 || end_char >255)
end_char = EOF;
if(!fd) if(!fd)
return luaL_error(L, "open a file first"); return luaL_error(L, "open a file first");
char *p; luaL_buffinit(L, &b);
int i;
size_t bufsize = n;
if (n > LUAL_BUFFERSIZE) { for (j = 0; j < n; j += sizeof(p)) {
// get buffer from heap int nwanted = (n - j >= sizeof(p)) ? sizeof(p) : n - j;
p = heap_mem = luaM_malloc(L, bufsize); int nread = vfs_read(fd, p, nwanted);
} else {
// small chunks go onto the stack
p = alloca(bufsize);
}
n = vfs_read(fd, p, n); if (nread == VFS_RES_ERR || nread == 0) {
// bypass search if no end character provided if (j > 0) {
if (n > 0 && end_char != EOF) {
for (i = 0; i < n; ++i)
if (p[i] == end_char)
{
++i;
break; break;
} }
} else { lua_pushnil(L);
i = n; return 1;
}
for (i = 0; i < nread; ++i) {
luaL_addchar(&b, p[i]);
if (p[i] == end_char) {
vfs_lseek(fd, -nread + i + 1, VFS_SEEK_CUR); //reposition after end char found
nread = 0; // force break on outer loop
break;
}
}
if (nread < nwanted)
break;
} }
luaL_pushresult(&b);
int err = 0;
if (i == 0 || n == VFS_RES_ERR) {
lua_pushnil(L);
} else {
vfs_lseek(fd, -(n - i), VFS_SEEK_CUR);
err = luaX_pushlstring(L, p, i); // On error it will return nonzero and leave a message on top of the stack.
}
if (heap_mem) {
luaN_freearray(L, heap_mem, bufsize);
}
if (err){
lua_error(L); // luaX_pushlstring failed and the error message is on top of the stack. Throw it.
// never returns
}
return 1; return 1;
} }
@ -476,6 +456,29 @@ static int file_readline( lua_State* L )
return file_g_read(L, FILE_READ_CHUNK, '\n', fd); return file_g_read(L, FILE_READ_CHUNK, '\n', fd);
} }
// Lua: getfile(filename)
static int file_getfile( lua_State* L )
{
// Warning this code C calls other file_* routines to avoid duplication code. These
// use Lua stack addressing of arguments, so this does Lua stack maniplation to
// align these
int ret_cnt = 0;
lua_settop(L ,1);
// Stack [1] = FD
file_open(L);
// Stack [1] = filename; [2] = FD or nil
if (!lua_isnil(L, -1)) {
lua_remove(L, 1); // dump filename, so [1] = FD
file_fd_ud *ud = (file_fd_ud *)luaL_checkudata(L, 1, "file.obj");
ret_cnt = file_g_read(L, LUAI_MAXINT32, EOF, ud->fd);
// Stack [1] = FD; [2] = contents if ret_cnt = 1;
file_close(L); // leaves Stack unchanged if [1] = FD
lua_remove(L, 1); // Dump FD leaving contents as [1] / ToS
}
return ret_cnt;
}
// Lua: write("string") // Lua: write("string")
static int file_write( lua_State* L ) static int file_write( lua_State* L )
{ {
@ -534,28 +537,6 @@ static int file_fsinfo( lua_State* L )
return 3; return 3;
} }
// Lua: getfile(filename)
static int file_getfile( lua_State* L )
{
// Warning this code C calls other file_* routines to avoid duplication code. These
// use Lua stack addressing of arguments, so this does Lua stack maniplation to
// align these
int ret_cnt = 0;
lua_settop(L ,1);
// Stack [1] = FD
file_open(L);
// Stack [1] = filename; [2] = FD or nil
if (!lua_isnil(L, -1)) {
lua_remove(L, 1); // dump filename, so [1] = FD
file_fd_ud *ud = (file_fd_ud *)luaL_checkudata(L, 1, "file.obj");
ret_cnt = file_g_read(L, LUAI_MAXINT32, EOF, ud->fd);
// Stack [1] = FD; [2] = contents if ret_cnt = 1;
file_close(L); // leaves Stack unchanged if [1] = FD
lua_remove(L, 1); // Dump FD leaving contents as [1] / ToS
}
return ret_cnt;
}
// Lua: getfile(filename) // Lua: getfile(filename)
static int file_putfile( lua_State* L ) static int file_putfile( lua_State* L )
{ {
@ -622,8 +603,6 @@ LROT_BEGIN(file, NULL, 0)
LROT_FUNCENTRY( writeline, file_writeline ) LROT_FUNCENTRY( writeline, file_writeline )
LROT_FUNCENTRY( read, file_read ) LROT_FUNCENTRY( read, file_read )
LROT_FUNCENTRY( readline, file_readline ) LROT_FUNCENTRY( readline, file_readline )
LROT_FUNCENTRY( getcontents, file_getfile )
LROT_FUNCENTRY( putcontents, file_putfile )
#ifdef CONFIG_NODEMCU_BUILD_SPIFFS #ifdef CONFIG_NODEMCU_BUILD_SPIFFS
LROT_FUNCENTRY( format, file_format ) LROT_FUNCENTRY( format, file_format )
LROT_FUNCENTRY( fscfg, file_fscfg ) LROT_FUNCENTRY( fscfg, file_fscfg )
@ -633,6 +612,8 @@ LROT_BEGIN(file, NULL, 0)
LROT_FUNCENTRY( flush, file_flush ) LROT_FUNCENTRY( flush, file_flush )
LROT_FUNCENTRY( rename, file_rename ) LROT_FUNCENTRY( rename, file_rename )
LROT_FUNCENTRY( exists, file_exists ) LROT_FUNCENTRY( exists, file_exists )
LROT_FUNCENTRY( getcontents, file_getfile )
LROT_FUNCENTRY( putcontents, file_putfile )
LROT_FUNCENTRY( fsinfo, file_fsinfo ) LROT_FUNCENTRY( fsinfo, file_fsinfo )
LROT_FUNCENTRY( on, file_on ) LROT_FUNCENTRY( on, file_on )
LROT_FUNCENTRY( stat, file_stat ) LROT_FUNCENTRY( stat, file_stat )

View File

@ -74,10 +74,12 @@ The characteristic table contains the following keys:
- `uuid` The UUID of the characteristics. This can be either a 16 byte string or a 2 byte string that identifies the particular characteristic. Typically, 2 byte strings are used for well-known characteristics. - `uuid` The UUID of the characteristics. This can be either a 16 byte string or a 2 byte string that identifies the particular characteristic. Typically, 2 byte strings are used for well-known characteristics.
- `type` This is the optional type of the value. It has the same value as a unpack code in the `struct` module. - `type` This is the optional type of the value. It has the same value as a unpack code in the `struct` module.
- `value` This is the actual value of the characteristic. This will be a string of bytes unless a `type` value is set. - `value` This is the actual value of the characteristic. This will be a string of bytes unless a `type` value is set.
- `read` This is a function that will be invoked to read the value (and so does not need the `value` entry). It should return a string of bytes (unless `type` is set) - `read` This is a function that will be invoked to read the value (and so does not need the `value` entry). It should return a string of bytes (unless `type` is set).
- `write` This is a function that will be invoked to write the value (and so does not need the `value` entry). It is given a string of bytes (unless `type` is set) - `write` This is a function that will be invoked to write the value (and so does not need the `value` entry). It is given a string of bytes (unless `type` is set)
The characteristics are treated as read/write unless only one of the `read` or `write` keys is present and the `value` key is not specificed. If the `value` key is present, then the characteristic is read/write. However, if one or `read` or `write` is set to `true`, then it restricts access to that mode.
The characteristics are treated as read/write unless only one of the `read` or `write` keys is present and the `value` key is not specified.
The calling conventions for these functions are as follows: The calling conventions for these functions are as follows: