Repository: incubator-mynewt-core Updated Branches: refs/heads/develop 85638d22a -> 8b510e973
bletiny: Add support to connect/disconnect L2CAP LE COC With this patch bletiny gets support to test LE COC. In order to do this, new options to 'b l2cap' command has been added: * create_srv psm=<psm> * connect conn=<conn_handle> psm=<psm> * disconnect idx=<idx> In order to get 'idx' required to disconnect you should call "b show coc" Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/8b73a4d8 Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/8b73a4d8 Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/8b73a4d8 Branch: refs/heads/develop Commit: 8b73a4d81480d6753ff019cd26f89ef606b0b247 Parents: 2082dc6 Author: Åukasz Rymanowski <[email protected]> Authored: Tue Jan 31 01:28:20 2017 +0100 Committer: Åukasz Rymanowski <[email protected]> Committed: Thu Feb 2 12:59:59 2017 +0100 ---------------------------------------------------------------------- apps/bletiny/src/bletiny.h | 12 +- apps/bletiny/src/cmd.c | 145 ++++++++++++++++++++ apps/bletiny/src/main.c | 222 +++++++++++++++++++++++++++++++ net/nimble/host/src/ble_l2cap_sig.c | 5 +- 4 files changed, 381 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8b73a4d8/apps/bletiny/src/bletiny.h ---------------------------------------------------------------------- diff --git a/apps/bletiny/src/bletiny.h b/apps/bletiny/src/bletiny.h index 2ab696a..8d8ac64 100644 --- a/apps/bletiny/src/bletiny.h +++ b/apps/bletiny/src/bletiny.h @@ -78,9 +78,17 @@ struct bletiny_svc { SLIST_HEAD(bletiny_svc_list, bletiny_svc); +struct bletiny_l2cap_coc { + SLIST_ENTRY(bletiny_l2cap_coc) next; + struct ble_l2cap_chan *chan; +}; + +SLIST_HEAD(bletiny_l2cap_coc_list, bletiny_l2cap_coc); + struct bletiny_conn { uint16_t handle; struct bletiny_svc_list svcs; + struct bletiny_l2cap_coc_list coc_list; }; extern struct bletiny_conn bletiny_conns[MYNEWT_VAL(BLE_MAX_CONNECTIONS)]; @@ -182,7 +190,9 @@ int bletiny_sec_restart(uint16_t conn_handle, uint8_t *ltk, uint16_t ediv, int bletiny_tx_start(uint16_t handle, uint16_t len, uint16_t rate, uint16_t num); int bletiny_rssi(uint16_t conn_handle, int8_t *out_rssi); - +int bletiny_l2cap_create_srv(uint16_t psm); +int bletiny_l2cap_connect(uint16_t conn, uint16_t psm); +int bletiny_l2cap_disconnect(uint16_t conn, uint16_t idx); #define BLETINY_LOG_MODULE (LOG_MODULE_PERUSER + 0) #define BLETINY_LOG(lvl, ...) \ LOG_ ## lvl(&bletiny_log, BLETINY_LOG_MODULE, __VA_ARGS__) http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8b73a4d8/apps/bletiny/src/cmd.c ---------------------------------------------------------------------- diff --git a/apps/bletiny/src/cmd.c b/apps/bletiny/src/cmd.c index c5f4a55..8904ea2 100644 --- a/apps/bletiny/src/cmd.c +++ b/apps/bletiny/src/cmd.c @@ -1164,6 +1164,119 @@ cmd_l2cap_update(int argc, char **argv) return 0; } +static void +bletiny_l2cap_create_srv_help(void) +{ + console_printf("Available l2cap create_srv commands: \n"); + console_printf("\thelp\n"); + console_printf("Available l2cap create_srv params: \n"); + help_cmd_uint16("psm"); + help_cmd_uint16("mtu"); +} + +static int +cmd_l2cap_create_srv(int argc, char **argv) +{ + uint16_t psm = 0; + int rc; + + if (argc > 1 && strcmp(argv[1], "help") == 0) { + bletiny_l2cap_create_srv_help(); + return 0; + } + + psm = parse_arg_uint16("psm", &rc); + if (rc != 0) { + console_printf("invalid 'psm' parameter\n"); + help_cmd_uint16("psm"); + return rc; + } + + rc = bletiny_l2cap_create_srv(psm); + if (rc) { + console_printf("Server create error: 0x%02x", rc); + } + + return 0; +} + +static void +bletiny_l2cap_connect_help(void) +{ + console_printf("Available l2cap connect commands: \n"); + console_printf("\thelp\n"); + console_printf("Available l2cap connect params: \n"); + help_cmd_uint16("conn"); + help_cmd_uint16("psm"); +} + +static int +cmd_l2cap_connect(int argc, char **argv) +{ + uint16_t conn = 0; + uint16_t psm = 0; + int rc; + + if (argc > 1 && strcmp(argv[1], "help") == 0) { + bletiny_l2cap_connect_help(); + return 0; + } + + conn = parse_arg_uint16("conn", &rc); + if (rc != 0) { + console_printf("invalid 'conn' parameter\n"); + help_cmd_uint16("conn"); + } + + psm = parse_arg_uint16("psm", &rc); + if (rc != 0) { + console_printf("invalid 'psm' parameter\n"); + help_cmd_uint16("psm"); + return rc; + } + + return bletiny_l2cap_connect(conn, psm); +} + +static void +bletiny_l2cap_disconnect_help(void) +{ + console_printf("Available l2cap disconnect commands: \n"); + console_printf("\thelp\n"); + console_printf("Available l2cap disconnect params: \n"); + help_cmd_uint16("conn"); + help_cmd_uint16("idx"); + console_printf("\n Use 'b show coc' to get those parameters \n"); +} + +static int +cmd_l2cap_disconnect(int argc, char **argv) +{ + uint16_t conn; + uint16_t idx; + int rc; + + if (argc > 1 && strcmp(argv[1], "help") == 0) { + bletiny_l2cap_disconnect_help(); + return 0; + } + + conn = parse_arg_uint16("conn", &rc); + if (rc != 0) { + console_printf("invalid 'conn' parameter\n"); + help_cmd_uint16("conn"); + } + + idx = parse_arg_uint16("idx", &rc); + if (rc != 0) { + console_printf("invalid 'idx' parameter\n"); + help_cmd_uint16("idx"); + return 0; + } + + return bletiny_l2cap_disconnect(conn, idx); +} + static const struct cmd_entry cmd_l2cap_entries[]; static int @@ -1180,6 +1293,9 @@ cmd_l2cap_help(int argc, char **argv) static const struct cmd_entry cmd_l2cap_entries[] = { { "update", cmd_l2cap_update }, + { "create_srv", cmd_l2cap_create_srv }, + { "connect", cmd_l2cap_connect }, + { "disconnect", cmd_l2cap_disconnect }, { "help", cmd_l2cap_help }, { NULL, NULL } }; @@ -1608,6 +1724,34 @@ cmd_show_conn(int argc, char **argv) return 0; } +static int +cmd_show_coc(int argc, char **argv) +{ + struct bletiny_conn *conn = NULL; + struct bletiny_l2cap_coc *coc; + int i, j; + + for (i = 0; i < bletiny_num_conns; i++) { + conn = bletiny_conns + i; + if (!conn) { + break; + } + + if (SLIST_EMPTY(&conn->coc_list)) { + continue; + } + + console_printf("conn_handle: 0x%04x\n", conn->handle); + j = 0; + SLIST_FOREACH(coc, &conn->coc_list, next) { + console_printf(" idx: %i, chan pointer = 0x%08lx\n", j++, + (uint32_t)coc->chan); + } + } + + return 0; +} + static struct cmd_entry cmd_show_entries[]; static int @@ -1626,6 +1770,7 @@ static struct cmd_entry cmd_show_entries[] = { { "addr", cmd_show_addr }, { "chr", cmd_show_chr }, { "conn", cmd_show_conn }, + { "coc", cmd_show_coc }, { "help", cmd_show_help }, { NULL, NULL } }; http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8b73a4d8/apps/bletiny/src/main.c ---------------------------------------------------------------------- diff --git a/apps/bletiny/src/main.c b/apps/bletiny/src/main.c index e958da6..c468666 100755 --- a/apps/bletiny/src/main.c +++ b/apps/bletiny/src/main.c @@ -71,6 +71,10 @@ #define BLETINY_MAX_DSCS 1 #endif +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) +#define BLETINY_COC_MTU (256) +#endif + struct log bletiny_log; bssnz_t struct bletiny_conn bletiny_conns[MYNEWT_VAL(BLE_MAX_CONNECTIONS)]; @@ -85,6 +89,14 @@ static struct os_mempool bletiny_chr_pool; static void *bletiny_dsc_mem; static struct os_mempool bletiny_dsc_pool; +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) +static void *bletiny_coc_conn_mem; +static struct os_mempool bletiny_coc_conn_pool; + +static void *bletiny_sdu_coc_mem; +static struct os_mempool bletiny_sdu_coc_pool; +#endif + static struct os_callout bletiny_tx_timer; struct bletiny_tx_data_s { @@ -599,6 +611,7 @@ bletiny_conn_add(struct ble_gap_conn_desc *desc) conn->handle = desc->conn_handle; SLIST_INIT(&conn->svcs); + SLIST_INIT(&conn->coc_list); return conn; } @@ -1549,6 +1562,190 @@ bletiny_on_reset(int reason) console_printf("Error: Resetting state; reason=%d\n", reason); } +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 + +static int +bletiny_l2cap_coc_add(uint16_t conn_handle, struct ble_l2cap_chan *chan) +{ + struct bletiny_conn *conn; + struct bletiny_l2cap_coc *coc; + struct bletiny_l2cap_coc *prev, *cur; + + conn = bletiny_conn_find(conn_handle); + assert(conn != NULL); + + coc = os_memblock_get(&bletiny_coc_conn_pool); + if (!coc) { + return ENOMEM; + } + + coc->chan = chan; + + prev = NULL; + SLIST_FOREACH(cur, &conn->coc_list, next) { + prev = cur; + } + + if (prev == NULL) { + SLIST_INSERT_HEAD(&conn->coc_list, coc, next); + } else { + SLIST_INSERT_AFTER(prev, coc, next); + } + + return 0; +} + +static void +bletiny_l2cap_coc_remove(uint16_t conn_handle, struct ble_l2cap_chan *chan) +{ + struct bletiny_conn *conn; + struct bletiny_l2cap_coc *coc; + struct bletiny_l2cap_coc *cur; + + conn = bletiny_conn_find(conn_handle); + assert(conn != NULL); + + coc = NULL; + SLIST_FOREACH(cur, &conn->coc_list, next) { + if (cur->chan == chan) { + coc = cur; + break; + } + } + + if (!coc) { + return; + } + + SLIST_REMOVE(&conn->coc_list, coc, bletiny_l2cap_coc, next); + os_memblock_put(&bletiny_coc_conn_pool, coc); +} + +static void +bletiny_l2cap_coc_recv(struct ble_l2cap_chan *chan, struct os_mbuf *sdu) +{ + console_printf("LE CoC SDU received, chan: 0x%08lx\n", (uint32_t) chan); +} + +static int +bletiny_l2cap_coc_accept(uint16_t conn_handle, uint16_t peer_mtu, + struct ble_l2cap_chan *chan) +{ + struct os_mbuf *sdu_rx; + + sdu_rx = os_memblock_get(&bletiny_sdu_coc_pool); + if (!sdu_rx) { + return BLE_HS_ENOMEM; + } + + ble_l2cap_recv_ready(chan, sdu_rx); + + return 0; +} + +static int +bletiny_l2cap_event(struct ble_l2cap_event *event, void *arg) +{ + switch(event->type) { + case BLE_L2CAP_EVENT_COC_CONNECTED: + if (event->connect.status) { + console_printf("LE COC error: %d\n", event->connect.status); + return 0; + } + + console_printf("LE COC connected, conn: %d, chan: 0x%08lx\n", + event->connect.conn_handle, + (uint32_t) event->connect.chan); + + bletiny_l2cap_coc_add(event->connect.conn_handle, + event->connect.chan); + + return 0; + case BLE_L2CAP_EVENT_COC_DISCONNECTED: + console_printf("LE CoC disconnected, chan: 0x%08lx\n", + (uint32_t) event->disconnect.chan); + + bletiny_l2cap_coc_remove(event->disconnect.conn_handle, + event->disconnect.chan); + return 0; + case BLE_L2CAP_EVENT_COC_ACCEPT: + return bletiny_l2cap_coc_accept(event->accept.conn_handle, + event->accept.peer_sdu_size, + event->accept.chan); + + case BLE_L2CAP_EVENT_COC_DATA_RECEIVED: + bletiny_l2cap_coc_recv(event->receive.chan, event->receive.sdu_rx); + return 0; + default: + return 0; + } +} +#endif + +int +bletiny_l2cap_create_srv(uint16_t psm) +{ +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) == 0 + console_printf("BLE L2CAP LE COC not supported."); + console_printf(" Configure nimble host to enable it\n"); + return 0; +#else + + return ble_l2cap_create_server(psm, BLETINY_COC_MTU, bletiny_l2cap_event, + NULL); +#endif +} + +int +bletiny_l2cap_connect(uint16_t conn_handle, uint16_t psm) +{ +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) == 0 + console_printf("BLE L2CAP LE COC not supported."); + console_printf(" Configure nimble host to enable it\n"); + return 0; +#else + + struct os_mbuf *sdu_rx; + + sdu_rx = os_memblock_get(&bletiny_sdu_coc_pool); + assert(sdu_rx != NULL); + + return ble_l2cap_connect(conn_handle, psm, BLETINY_COC_MTU, sdu_rx, + bletiny_l2cap_event, NULL); +#endif +} + +int +bletiny_l2cap_disconnect(uint16_t conn_handle, uint16_t idx) +{ +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) == 0 + console_printf("BLE L2CAP LE COC not supported."); + console_printf(" Configure nimble host to enable it\n"); + return 0; +#else + + struct bletiny_conn *conn; + struct bletiny_l2cap_coc *coc; + int i; + + conn = bletiny_conn_find(conn_handle); + assert(conn != NULL); + + i = 0; + SLIST_FOREACH(coc, &conn->coc_list, next) { + if (i == idx) { + break; + } + i++; + } + assert(coc != NULL); + + ble_l2cap_disconnect(coc->chan); + + return 0; +#endif +} + /** * main * @@ -1593,6 +1790,31 @@ main(void) "bletiny_dsc_pool"); assert(rc == 0); +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 + /* For testing we want to support all the available channels */ + bletiny_sdu_coc_mem = malloc( + OS_MEMPOOL_BYTES(BLETINY_COC_MTU * MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM), + sizeof (struct os_mbuf))); + assert(bletiny_sdu_coc_mem != NULL); + + rc = os_mempool_init(&bletiny_sdu_coc_pool, + BLETINY_COC_MTU * MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM), + sizeof (struct os_mbuf), bletiny_sdu_coc_mem, + "bletiny_coc_sdu_pool"); + assert(rc == 0); + + bletiny_coc_conn_mem = malloc( + OS_MEMPOOL_BYTES(MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM), + sizeof (struct bletiny_l2cap_coc))); + assert(bletiny_coc_conn_mem != NULL); + + rc = os_mempool_init(&bletiny_coc_conn_pool, + MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM), + sizeof (struct bletiny_l2cap_coc), bletiny_coc_conn_mem, + "bletiny_coc_conn_pool"); + assert(rc == 0); +#endif + /* Initialize the logging system. */ log_register("bletiny", &bletiny_log, &log_console_handler, NULL, LOG_SYSLEVEL); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8b73a4d8/net/nimble/host/src/ble_l2cap_sig.c ---------------------------------------------------------------------- diff --git a/net/nimble/host/src/ble_l2cap_sig.c b/net/nimble/host/src/ble_l2cap_sig.c index fdaa408..40cda11 100644 --- a/net/nimble/host/src/ble_l2cap_sig.c +++ b/net/nimble/host/src/ble_l2cap_sig.c @@ -890,7 +890,8 @@ ble_l2cap_sig_disc_req_rx(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, ble_hs_conn_delete_chan(conn, chan); ble_hs_unlock(); - return ble_l2cap_sig_tx(conn_handle, txom); + ble_l2cap_sig_tx(conn_handle, txom); + return 0; } static void @@ -929,7 +930,7 @@ done: } static int -ble_l2cap_sig_disc_rsp_rx (uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, +ble_l2cap_sig_disc_rsp_rx(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, struct os_mbuf **om) { struct ble_l2cap_sig_disc_rsp *rsp;
