This is an automated email from the ASF dual-hosted git repository. janc pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git
commit 6f34f7c923edc0c0a30037f8cfa7c85098657ed9 Author: Krzysztof Kopyściński <[email protected]> AuthorDate: Tue Jul 11 13:45:55 2023 +0200 apps/bttester: refactor GATT service Accomodated to new API. --- apps/bttester/src/btp/btp_gatt.h | 5 +- apps/bttester/src/btp/bttester.h | 3 - apps/bttester/src/btp_gatt.c | 805 +++++++++++++++++++++------------------ 3 files changed, 443 insertions(+), 370 deletions(-) diff --git a/apps/bttester/src/btp/btp_gatt.h b/apps/bttester/src/btp/btp_gatt.h index 41f5ae7ec..88f2e62a9 100644 --- a/apps/bttester/src/btp/btp_gatt.h +++ b/apps/bttester/src/btp/btp_gatt.h @@ -128,6 +128,9 @@ struct btp_gatt_descriptor { } __packed; #define BTP_GATT_EXCHANGE_MTU 0x0a +struct btp_gatt_exchange_mtu_cmd { + ble_addr_t address; +} __packed; #define BTP_GATT_DISC_ALL_PRIM_SVCS 0x0b struct btp_gatt_disc_all_prim_svcs_cmd { @@ -305,7 +308,7 @@ struct btp_gatt_get_attribute_value_rp { } __packed; #define BTP_GATT_CHANGE_DATABASE 0x1e -struct btp_gatt_change_database { +struct btp_gatt_change_database_cmd { uint16_t start_handle; uint16_t end_handle; uint8_t visibility; diff --git a/apps/bttester/src/btp/bttester.h b/apps/bttester/src/btp/bttester.h index ea24600c1..9d66cd946 100644 --- a/apps/bttester/src/btp/bttester.h +++ b/apps/bttester/src/btp/bttester.h @@ -101,9 +101,6 @@ tester_init_gatt(void); uint8_t tester_unregister_gatt(void); void -tester_handle_gatt(uint8_t opcode, uint8_t *data, - uint16_t len); -void tester_handle_gattc(uint8_t opcode, uint8_t *data, uint16_t len); int diff --git a/apps/bttester/src/btp_gatt.c b/apps/bttester/src/btp_gatt.c index ef6a805b7..09bd8d723 100644 --- a/apps/bttester/src/btp_gatt.c +++ b/apps/bttester/src/btp_gatt.c @@ -571,10 +571,11 @@ gatt_svr_rel_write_test(uint16_t conn_handle, uint16_t attr_handle, } } -static void -start_server(uint8_t *data, uint16_t len) +static uint8_t +start_server(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - struct btp_gatt_start_server_rp rp; + struct btp_gatt_start_server_rp *rp = rsp; SYS_LOG_DBG(""); @@ -582,11 +583,12 @@ start_server(uint8_t *data, uint16_t len) ble_svc_gatt_changed(0x0001, 0xffff); - rp.db_attr_off = 0; - rp.db_attr_cnt = 0; + rp->db_attr_off = 0; + rp->db_attr_cnt = 0; + + *rsp_len = sizeof(*rp); - tester_send(BTP_SERVICE_ID_GATT, BTP_GATT_START_SERVER, - (uint8_t *) &rp, sizeof(rp)); + return BTP_STATUS_SUCCESS; } /* Convert UUID from BTP command to bt_uuid */ @@ -702,37 +704,35 @@ read_cb(uint16_t conn_handle, return 0; } -static void -read(uint8_t *data, uint16_t len) +static uint8_t +read_data(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - const struct btp_gatt_read_cmd *cmd = (void *) data; + const struct btp_gatt_read_cmd *cp = cmd; struct ble_gap_conn_desc conn; int rc; SYS_LOG_DBG(""); - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); + rc = ble_gap_conn_find_by_addr(&cp->address, &conn); if (rc) { - goto fail; + return BTP_STATUS_FAILED; } /* Clear buffer */ read_destroy(); if (!gatt_buf_reserve(sizeof(struct btp_gatt_read_rp))) { - goto fail; + return BTP_STATUS_FAILED; } - if (ble_gattc_read(conn.conn_handle, le16toh(cmd->handle), + if (ble_gattc_read(conn.conn_handle, le16toh(cp->handle), read_cb, (void *) BTP_GATT_READ)) { read_destroy(); - goto fail; + return BTP_STATUS_FAILED; } - return; - -fail: - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_READ, BTP_STATUS_FAILED); + return BTP_STATUS_SUCCESS; } static int @@ -773,104 +773,103 @@ read_long_cb(uint16_t conn_handle, return 0; } -static void -read_long(uint8_t *data, uint16_t len) +static uint8_t +read_long(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - const struct btp_gatt_read_long_cmd *cmd = (void *) data; + const struct btp_gatt_read_long_cmd *cp = cmd; struct ble_gap_conn_desc conn; int rc; SYS_LOG_DBG(""); - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); + rc = ble_gap_conn_find_by_addr(&cp->address, &conn); if (rc) { - goto fail; + return BTP_STATUS_FAILED; } /* Clear buffer */ read_destroy(); if (!gatt_buf_reserve(sizeof(struct btp_gatt_read_rp))) { - goto fail; + return BTP_STATUS_FAILED; } if (ble_gattc_read_long(conn.conn_handle, - le16toh(cmd->handle), - le16toh(cmd->offset), + le16toh(cp->handle), + le16toh(cp->offset), read_long_cb, (void *) BTP_GATT_READ_LONG)) { read_destroy(); - goto fail; + return BTP_STATUS_FAILED; } - return; - -fail: - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_READ_LONG, BTP_STATUS_FAILED); + return BTP_STATUS_SUCCESS; } -static void -read_multiple(uint8_t *data, uint16_t len) +static uint8_t +read_multiple(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - const struct btp_gatt_read_multiple_cmd *cmd = (void *) data; - uint16_t handles[cmd->handles_count]; + const struct btp_gatt_read_multiple_cmd *cp = cmd; + uint16_t handles[cp->handles_count]; struct ble_gap_conn_desc conn; int rc, i; SYS_LOG_DBG(""); for (i = 0; i < ARRAY_SIZE(handles); i++) { - handles[i] = le16toh(cmd->handles[i]); + handles[i] = le16toh(cp->handles[i]); } - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); + rc = ble_gap_conn_find_by_addr(&cp->address, &conn); if (rc) { - goto fail; + return BTP_STATUS_FAILED; } /* Clear buffer */ read_destroy(); if (!gatt_buf_reserve(sizeof(struct btp_gatt_read_rp))) { - goto fail; + return BTP_STATUS_FAILED; } if (ble_gattc_read_mult(conn.conn_handle, handles, - cmd->handles_count, read_cb, + cp->handles_count, read_cb, (void *) BTP_GATT_READ_MULTIPLE)) { read_destroy(); - goto fail; + return BTP_STATUS_FAILED; } - return; - -fail: - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_READ_MULTIPLE, BTP_STATUS_FAILED); + return BTP_STATUS_SUCCESS; } -static void -write_without_rsp(uint8_t *data, uint16_t len, uint8_t op, bool sign) +static uint8_t +write_without_rsp(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - const struct btp_gatt_write_without_rsp_cmd *cmd = (void *) data; + const struct btp_gatt_write_without_rsp_cmd *cp = cmd; struct ble_gap_conn_desc conn; - uint8_t status = BTP_STATUS_SUCCESS; int rc; SYS_LOG_DBG(""); - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); + if (cmd_len < sizeof(*cp) || + cmd_len != sizeof(*cp) + le16toh(cp->data_length)) { + return BTP_STATUS_FAILED; + } + + rc = ble_gap_conn_find_by_addr(&cp->address, &conn); if (rc) { - status = BTP_STATUS_FAILED; - goto rsp; + return BTP_STATUS_FAILED; } if (ble_gattc_write_no_rsp_flat(conn.conn_handle, - le16toh(cmd->handle), cmd->data, - le16toh(cmd->data_length))) { - status = BTP_STATUS_FAILED; + le16toh(cp->handle), cp->data, + le16toh(cp->data_length))) { + return BTP_STATUS_FAILED; } -rsp: - tester_rsp(BTP_SERVICE_ID_GATT, op, status); + return BTP_STATUS_SUCCESS; } static int @@ -888,66 +887,75 @@ write_rsp(uint16_t conn_handle, const struct ble_gatt_error *error, return 0; } -static void -write(uint8_t *data, uint16_t len) +static uint8_t +write_data(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - const struct btp_gatt_write_cmd *cmd = (void *) data; + const struct btp_gatt_write_cmd *cp = cmd; struct ble_gap_conn_desc conn; int rc; SYS_LOG_DBG(""); - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); + if (cmd_len < sizeof(*cp) || + cmd_len != sizeof(*cp) + le16toh(cp->data_length)) { + return BTP_STATUS_FAILED; + } + + rc = ble_gap_conn_find_by_addr(&cp->address, &conn); if (rc) { - goto fail; + return BTP_STATUS_FAILED; } - if (ble_gattc_write_flat(conn.conn_handle, le16toh(cmd->handle), - cmd->data, le16toh(cmd->data_length), + if (ble_gattc_write_flat(conn.conn_handle, le16toh(cp->handle), + cp->data, le16toh(cp->data_length), write_rsp, (void *) BTP_GATT_WRITE)) { - goto fail; + return BTP_STATUS_FAILED; } - return; - -fail: - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_WRITE, BTP_STATUS_FAILED); + return BTP_STATUS_DELAY_REPLY; } -static void -write_long(uint8_t *data, uint16_t len) +static uint8_t +write_long(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - const struct btp_gatt_write_long_cmd *cmd = (void *) data; + const struct btp_gatt_write_long_cmd *cp = cmd; struct ble_gap_conn_desc conn; struct os_mbuf *om = NULL; int rc = 0; SYS_LOG_DBG(""); - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); + if (cmd_len < sizeof(*cp) || + cmd_len != sizeof(*cp) + le16toh(cp->data_length)) { + goto fail; + } + + rc = ble_gap_conn_find_by_addr(&cp->address, &conn); if (rc) { goto fail; } - om = ble_hs_mbuf_from_flat(cmd->data, le16toh(cmd->data_length)); + om = ble_hs_mbuf_from_flat(cp->data, le16toh(cp->data_length)); if (!om) { SYS_LOG_ERR("Insufficient resources"); goto fail; } rc = ble_gattc_write_long(conn.conn_handle, - le16toh(cmd->handle), - le16toh(cmd->offset), + le16toh(cp->handle), + le16toh(cp->offset), om, write_rsp, (void *) BTP_GATT_WRITE_LONG); if (!rc) { - return; + return BTP_STATUS_DELAY_REPLY; } fail: SYS_LOG_ERR("Failed to send Write Long request, rc=%d", rc); os_mbuf_free_chain(om); - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_WRITE_LONG, BTP_STATUS_FAILED); + return BTP_STATUS_FAILED; } static int @@ -966,10 +974,11 @@ reliable_write_rsp(uint16_t conn_handle, return 0; } -static void -reliable_write(uint8_t *data, uint16_t len) +static uint8_t +reliable_write(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - const struct btp_gatt_reliable_write_cmd *cmd = (void *) data; + const struct btp_gatt_reliable_write_cmd *cp = cmd; struct ble_gap_conn_desc conn; struct ble_gatt_attr attr; struct os_mbuf *om = NULL; @@ -977,21 +986,21 @@ reliable_write(uint8_t *data, uint16_t len) SYS_LOG_DBG(""); - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); + rc = ble_gap_conn_find_by_addr(&cp->address, &conn); if (rc) { goto fail; } - om = ble_hs_mbuf_from_flat(cmd->data, le16toh(cmd->data_length)); + om = ble_hs_mbuf_from_flat(cp->data, le16toh(cp->data_length)); /* This is required, because Nimble checks if * the data is longer than offset */ - if (os_mbuf_extend(om, le16toh(cmd->offset) + 1) == NULL) { + if (os_mbuf_extend(om, le16toh(cp->offset) + 1) == NULL) { goto fail; } - attr.handle = le16toh(cmd->handle); - attr.offset = le16toh(cmd->offset); + attr.handle = le16toh(cp->handle); + attr.offset = le16toh(cp->offset); attr.om = om; if (ble_gattc_write_reliable(conn.conn_handle, &attr, 1, @@ -999,12 +1008,12 @@ reliable_write(uint8_t *data, uint16_t len) goto fail; } - return; + return BTP_STATUS_SUCCESS; fail: os_mbuf_free_chain(om); - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_WRITE_LONG, BTP_STATUS_FAILED); + return BTP_STATUS_FAILED; } static struct bt_gatt_subscribe_params { @@ -1013,44 +1022,42 @@ static struct bt_gatt_subscribe_params { uint16_t value_handle; } subscribe_params; -static void -read_uuid(uint8_t *data, uint16_t len) +static uint8_t +read_uuid(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - const struct btp_gatt_read_uuid_cmd *cmd = (void *) data; + const struct btp_gatt_read_uuid_cmd *cp = cmd; struct ble_gap_conn_desc conn; ble_uuid_any_t uuid; int rc; SYS_LOG_DBG(""); - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); + rc = ble_gap_conn_find_by_addr(&cp->address, &conn); if (rc) { - goto fail; + return BTP_STATUS_FAILED; } - if (btp2bt_uuid(cmd->uuid, cmd->uuid_length, &uuid)) { - goto fail; + if (btp2bt_uuid(cp->uuid, cp->uuid_length, &uuid)) { + return BTP_STATUS_FAILED; } /* Clear buffer */ read_destroy(); if (!gatt_buf_reserve(sizeof(struct btp_gatt_read_rp))) { - goto fail; + return BTP_STATUS_FAILED; } if (ble_gattc_read_by_uuid(conn.conn_handle, - le16toh(cmd->start_handle), - le16toh(cmd->end_handle), &uuid.u, + le16toh(cp->start_handle), + le16toh(cp->end_handle), &uuid.u, read_long_cb, (void *) BTP_GATT_READ_UUID)) { read_destroy(); - goto fail; + return BTP_STATUS_FAILED; } - return; - -fail: - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_READ, BTP_STATUS_FAILED); + return BTP_STATUS_SUCCESS; } static int @@ -1161,57 +1168,56 @@ disc_all_desc_cb(uint16_t conn_handle, return 0; } -static void -disc_all_prim_svcs(uint8_t *data, uint16_t len) +static uint8_t +disc_all_prim_svcs(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { + const struct btp_gatt_disc_all_prim_svcs_cmd *cp = cmd; struct ble_gap_conn_desc conn; int rc; SYS_LOG_DBG(""); - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); + rc = ble_gap_conn_find_by_addr(&cp->address, &conn); if (rc) { - goto fail; + return BTP_STATUS_FAILED; } if (!gatt_buf_reserve(sizeof(struct btp_gatt_disc_all_prim_svcs_rp))) { - goto fail; + return BTP_STATUS_FAILED; } if (ble_gattc_disc_all_svcs(conn.conn_handle, disc_prim_uuid_cb, (void *) BTP_GATT_DISC_ALL_PRIM_SVCS)) { discover_destroy(); - goto fail; + return BTP_STATUS_FAILED; } - return; - -fail: - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_DISC_ALL_PRIM_SVCS, - BTP_STATUS_FAILED); + return BTP_STATUS_DELAY_REPLY; } -static void -disc_all_desc(uint8_t *data, uint16_t len) +static uint8_t +disc_all_desc(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - const struct btp_gatt_disc_all_desc_cmd *cmd = (void *) data; + const struct btp_gatt_disc_all_desc_cmd *cp = cmd; struct ble_gap_conn_desc conn; uint16_t start_handle, end_handle; int rc; SYS_LOG_DBG(""); - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); + rc = ble_gap_conn_find_by_addr(&cp->address, &conn); if (rc) { - goto fail; + return BTP_STATUS_FAILED; } if (!gatt_buf_reserve(sizeof(struct btp_gatt_disc_all_desc_rp))) { - goto fail; + return BTP_STATUS_FAILED; } - start_handle = le16toh(cmd->start_handle) - 1; - end_handle = le16toh(cmd->end_handle); + start_handle = le16toh(cp->start_handle) - 1; + end_handle = le16toh(cp->end_handle); rc = ble_gattc_disc_all_dscs(conn.conn_handle, start_handle, end_handle, disc_all_desc_cb, NULL); @@ -1220,13 +1226,10 @@ disc_all_desc(uint8_t *data, uint16_t len) if (rc) { discover_destroy(); - goto fail; + return BTP_STATUS_FAILED; } - return; - -fail: - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_DISC_ALL_DESC, BTP_STATUS_FAILED); + return BTP_STATUS_DELAY_REPLY; } static int @@ -1251,7 +1254,7 @@ find_included_cb(uint16_t conn_handle, if (error->status == BLE_HS_EDONE) { tester_send(BTP_SERVICE_ID_GATT, BTP_GATT_FIND_INCLUDED, gatt_buf - .buf, gatt_buf.len); + .buf, gatt_buf.len); discover_destroy(); return 0; } @@ -1267,9 +1270,8 @@ find_included_cb(uint16_t conn_handle, return BLE_HS_ENOMEM; } - /* FIXME */ included->included_handle = htole16(service_handle + 1 + - rp->services_count); + rp->services_count); included->service.start_handle = htole16(gatt_svc->start_handle); included->service.end_handle = htole16(gatt_svc->end_handle); included->service.uuid_length = uuid_length; @@ -1292,7 +1294,7 @@ disc_chrc_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_chr *gatt_chr, void *arg) { - struct btp_gatt_disc_chrc_rp *rp = (void *) gatt_buf.buf; + struct btp_gatt_disc_chrc_rp *rp = (void *) gatt_buf.buf; struct btp_gatt_characteristic *chrc; const ble_uuid_any_t *uuid; uint8_t btp_opcode = (uint8_t) (int) arg; @@ -1309,7 +1311,7 @@ disc_chrc_cb(uint16_t conn_handle, if (error->status == BLE_HS_EDONE) { tester_send(BTP_SERVICE_ID_GATT, btp_opcode, gatt_buf.buf, gatt_buf - .len); + .len); discover_destroy(); return 0; } @@ -1343,10 +1345,11 @@ disc_chrc_cb(uint16_t conn_handle, return 0; } -static void -disc_chrc_uuid(uint8_t *data, uint16_t len) +static uint8_t +disc_chrc_uuid(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - const struct btp_gatt_disc_chrc_uuid_cmd *cmd = (void *) data; + const struct btp_gatt_disc_chrc_uuid_cmd *cp = cmd; struct ble_gap_conn_desc conn; uint16_t start_handle, end_handle; ble_uuid_any_t uuid; @@ -1354,114 +1357,111 @@ disc_chrc_uuid(uint8_t *data, uint16_t len) SYS_LOG_DBG(""); - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); + rc = ble_gap_conn_find_by_addr(&cp->address, &conn); if (rc) { - goto fail; + return BTP_STATUS_FAILED; } - if (btp2bt_uuid(cmd->uuid, cmd->uuid_length, &uuid)) { - goto fail; + if (btp2bt_uuid(cp->uuid, cp->uuid_length, &uuid)) { + return BTP_STATUS_FAILED; } if (!gatt_buf_reserve(sizeof(struct btp_gatt_disc_chrc_rp))) { - goto fail; + return BTP_STATUS_FAILED; } - start_handle = le16toh(cmd->start_handle); - end_handle = le16toh(cmd->end_handle); + start_handle = le16toh(cp->start_handle); + end_handle = le16toh(cp->end_handle); if (ble_gattc_disc_chrs_by_uuid(conn.conn_handle, start_handle, end_handle, &uuid.u, disc_chrc_cb, (void *) BTP_GATT_DISC_CHRC_UUID)) { discover_destroy(); - goto fail; + return BTP_STATUS_FAILED; } - return; - -fail: - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_DISC_CHRC_UUID, - BTP_STATUS_FAILED); + return BTP_STATUS_DELAY_REPLY; } -static void -disc_prim_uuid(uint8_t *data, uint16_t len) +static uint8_t +disc_prim_uuid(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - const struct btp_gatt_disc_prim_uuid_cmd *cmd = (void *) data; + const struct btp_gatt_disc_prim_uuid_cmd *cp = cmd; struct ble_gap_conn_desc conn; ble_uuid_any_t uuid; int rc; SYS_LOG_DBG(""); - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); + if ((cmd_len < sizeof(*cp)) || + (cmd_len != sizeof(*cp) + cp->uuid_length)) { + return BTP_STATUS_FAILED; + } + + rc = ble_gap_conn_find_by_addr(&cp->address, &conn); if (rc) { - goto fail; + return BTP_STATUS_FAILED; } - if (btp2bt_uuid(cmd->uuid, cmd->uuid_length, &uuid)) { - goto fail; + if (btp2bt_uuid(cp->uuid, cp->uuid_length, &uuid)) { + return BTP_STATUS_FAILED; } if (!gatt_buf_reserve(sizeof(struct btp_gatt_disc_prim_uuid_rp))) { - goto fail; + return BTP_STATUS_FAILED; } if (ble_gattc_disc_svc_by_uuid(conn.conn_handle, &uuid.u, disc_prim_uuid_cb, (void *) BTP_GATT_DISC_PRIM_UUID)) { discover_destroy(); - goto fail; + return BTP_STATUS_FAILED; } - return; - -fail: - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_DISC_PRIM_UUID, - BTP_STATUS_FAILED); + return BTP_STATUS_DELAY_REPLY; } -static void -disc_all_chrc(uint8_t *data, uint16_t len) +static uint8_t +disc_all_chrc(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - const struct btp_gatt_disc_all_chrc_cmd *cmd = (void *) data; - struct ble_gap_conn_desc conn; + const struct btp_gatt_disc_all_chrc_cmd *cp = cmd; + struct ble_gap_conn_desc conn; uint16_t start_handle, end_handle; int rc; SYS_LOG_DBG(""); - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); + rc = ble_gap_conn_find_by_addr(&cp->address, &conn); if (rc) { SYS_LOG_DBG("Conn find failed"); - goto fail; + return BTP_STATUS_FAILED; } if (!gatt_buf_reserve(sizeof(struct btp_gatt_disc_chrc_rp))) { SYS_LOG_DBG("Buf reserve failed"); - goto fail; + return BTP_STATUS_FAILED; } - start_handle = le16toh(cmd->start_handle); - end_handle = le16toh(cmd->end_handle); + start_handle = le16toh(cp->start_handle); + end_handle = le16toh(cp->end_handle); rc = ble_gattc_disc_all_chrs(conn.conn_handle, start_handle, end_handle, disc_chrc_cb, (void *) BTP_GATT_DISC_ALL_CHRC); if (rc) { discover_destroy(); - goto fail; + return BTP_STATUS_FAILED; } - return; - -fail: - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_DISC_ALL_CHRC, BTP_STATUS_FAILED); + return BTP_STATUS_DELAY_REPLY; } -static void -find_included(uint8_t *data, uint16_t len) +static uint8_t +find_included(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - const struct btp_gatt_find_included_cmd *cmd = (void *) data; + const struct btp_gatt_find_included_cmd *cp = cmd; struct ble_gap_conn_desc conn; uint16_t start_handle, end_handle; int service_handle_arg; @@ -1469,30 +1469,27 @@ find_included(uint8_t *data, uint16_t len) SYS_LOG_DBG(""); - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); + rc = ble_gap_conn_find_by_addr(&cp->address, &conn); if (rc) { - goto fail; + return BTP_STATUS_FAILED; } if (!gatt_buf_reserve(sizeof(struct btp_gatt_find_included_rp))) { - goto fail; + return BTP_STATUS_FAILED; } - start_handle = le16toh(cmd->start_handle); - end_handle = le16toh(cmd->end_handle); + start_handle = le16toh(cp->start_handle); + end_handle = le16toh(cp->end_handle); service_handle_arg = start_handle; if (ble_gattc_find_inc_svcs(conn.conn_handle, start_handle, end_handle, find_included_cb, (void *) service_handle_arg)) { discover_destroy(); - goto fail; + return BTP_STATUS_FAILED; } - return; - -fail: - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_FIND_INCLUDED, BTP_STATUS_FAILED); + return BTP_STATUS_DELAY_REPLY; } static int @@ -1503,38 +1500,39 @@ exchange_func(uint16_t conn_handle, SYS_LOG_DBG(""); if (error->status) { - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_EXCHANGE_MTU, - BTP_STATUS_FAILED); + SYS_LOG_DBG("MTU exchange failed"); return 0; } - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_EXCHANGE_MTU, BTP_STATUS_SUCCESS); + SYS_LOG_DBG("MTU exchange succeed"); return 0; } -static void -exchange_mtu(uint8_t *data, uint16_t len) +static uint8_t +exchange_mtu(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { + const struct btp_gatt_exchange_mtu_cmd *cp = cmd; struct ble_gap_conn_desc conn; int rc; SYS_LOG_DBG(""); - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); + rc = ble_gap_conn_find_by_addr(&cp->address, &conn); if (rc) { - goto fail; + return BTP_STATUS_FAILED; } if (ble_gattc_exchange_mtu(conn.conn_handle, exchange_func, NULL)) { - goto fail; + return BTP_STATUS_FAILED; } - return; -fail: - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_EXCHANGE_MTU, - BTP_STATUS_FAILED); + /* this BTP command is about initiating MTU exchange, no need to wait + * for procedure to complete. + */ + return BTP_STATUS_SUCCESS; } static int @@ -1580,36 +1578,64 @@ disable_subscription(uint16_t conn_handle, uint16_t ccc_handle) return 0; } -static void -config_subscription(uint8_t *data, uint16_t len, uint8_t op) +static uint8_t +config_subscription_notif(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - const struct btp_gatt_cfg_notify_cmd *cmd = (void *) data; + const struct btp_gatt_cfg_notify_cmd *cp = cmd; struct ble_gap_conn_desc conn; - uint16_t ccc_handle = le16toh(cmd->ccc_handle); + uint16_t ccc_handle = le16toh(cp->ccc_handle); uint8_t status; int rc; SYS_LOG_DBG(""); - rc = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); + rc = ble_gap_conn_find_by_addr(&cp->address, &conn); if (rc) { - tester_rsp(BTP_SERVICE_ID_GATT, op, BTP_STATUS_FAILED); - return; + return BTP_STATUS_FAILED; } - if (cmd->enable) { - uint16_t value; + if (cp->enable) { + /* on success response will be sent from callback */ + if (enable_subscription(conn.conn_handle, + ccc_handle, 0x0001) == 0) { + return BTP_STATUS_DELAY_REPLY; + } - if (op == BTP_GATT_CFG_NOTIFY) { - value = 0x0001; + status = BTP_STATUS_FAILED; + } else { + if (disable_subscription(conn.conn_handle, ccc_handle) < 0) { + status = BTP_STATUS_FAILED; } else { - value = 0x0002; + status = BTP_STATUS_SUCCESS; } + } + + return status; +} + +static uint8_t +config_subscription_ind(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + const struct btp_gatt_cfg_notify_cmd *cp = cmd; + struct ble_gap_conn_desc conn; + uint16_t ccc_handle = le16toh(cp->ccc_handle); + uint8_t status; + int rc; + + SYS_LOG_DBG(""); + + rc = ble_gap_conn_find_by_addr(&cp->address, &conn); + if (rc) { + return BTP_STATUS_FAILED; + } + if (cp->enable) { /* on success response will be sent from callback */ if (enable_subscription(conn.conn_handle, - ccc_handle, value) == 0) { - return; + ccc_handle, 0x0002) == 0) { + return BTP_STATUS_DELAY_REPLY; } status = BTP_STATUS_FAILED; @@ -1621,9 +1647,7 @@ config_subscription(uint8_t *data, uint16_t len, uint8_t op) } } - SYS_LOG_DBG("Config subscription (op %u) status %u", op, status); - - tester_rsp(BTP_SERVICE_ID_GATT, op, status); + return status; } #define BTP_PERM_F_READ 0x01 @@ -1661,11 +1685,12 @@ flags_hs2btp(uint8_t flags) return ret; } -static void -get_attrs(uint8_t *data, uint16_t len) +static uint8_t +get_attrs(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - const struct btp_gatt_get_attributes_cmd *cmd = (void *) data; - struct btp_gatt_get_attributes_rp *rp; + const struct btp_gatt_get_attributes_cmd *cp = cmd; + struct btp_gatt_get_attributes_rp *rp = rsp; struct btp_gatt_attr *gatt_attr; struct os_mbuf *buf = os_msys_get(0, 0); uint16_t start_handle, end_handle; @@ -1674,17 +1699,19 @@ get_attrs(uint8_t *data, uint16_t len) ble_uuid_t *uuid_ptr = NULL; uint8_t count = 0; char str[BLE_UUID_STR_LEN]; + uint8_t status = BTP_STATUS_SUCCESS; SYS_LOG_DBG(""); memset(str, 0, sizeof(str)); memset(&uuid, 0, sizeof(uuid)); - start_handle = le16toh(cmd->start_handle); - end_handle = le16toh(cmd->end_handle); + start_handle = le16toh(cp->start_handle); + end_handle = le16toh(cp->end_handle); - if (cmd->type_length) { - if (btp2bt_uuid(cmd->type, cmd->type_length, &uuid)) { - goto fail; + if (cp->type_length) { + if (btp2bt_uuid(cp->type, cp->type_length, &uuid)) { + status = BTP_STATUS_FAILED; + goto free; } ble_uuid_to_str(&uuid.u, str); @@ -1698,7 +1725,8 @@ get_attrs(uint8_t *data, uint16_t len) rp = os_mbuf_extend(buf, sizeof(*rp)); if (!rp) { - goto fail; + status = BTP_STATUS_FAILED; + goto free; } entry = ble_att_svr_find_by_uuid(entry, uuid_ptr, end_handle); @@ -1712,7 +1740,8 @@ get_attrs(uint8_t *data, uint16_t len) gatt_attr = os_mbuf_extend(buf, sizeof(*gatt_attr)); if (!gatt_attr) { - goto fail; + status = BTP_STATUS_FAILED; + goto free; } gatt_attr->handle = htole16(entry->ha_handle_id); gatt_attr->permission = flags_hs2btp(entry->ha_flags); @@ -1736,33 +1765,32 @@ get_attrs(uint8_t *data, uint16_t len) rp->attrs_count = count; - tester_send_buf(BTP_SERVICE_ID_GATT, BTP_GATT_GET_ATTRIBUTES, - CONTROLLER_INDEX, buf); + *rsp_len = sizeof(*rp) + buf->om_len; - goto free; -fail: - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_GET_ATTRIBUTES, - BTP_STATUS_FAILED); free: os_mbuf_free_chain(buf); + return status; } -static void -get_attr_val(uint8_t *data, uint16_t len) +static uint8_t +get_attr_val(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - const struct btp_gatt_get_attribute_value_cmd *cmd = (void *) data; + const struct btp_gatt_get_attribute_value_cmd *cp = cmd; struct btp_gatt_get_attribute_value_rp *rp; struct ble_gap_conn_desc conn; struct os_mbuf *buf = os_msys_get(0, 0); - uint16_t handle = le16toh(cmd->handle); + uint16_t handle = le16toh(cp->handle); uint8_t out_att_err = 0; int conn_status; + uint8_t status = BTP_STATUS_SUCCESS; - conn_status = ble_gap_conn_find_by_addr((ble_addr_t *) data, &conn); + conn_status = ble_gap_conn_find_by_addr(&cp->address, &conn); if (conn_status) { rp = os_mbuf_extend(buf, sizeof(*rp)); if (!rp) { + status = BTP_STATUS_FAILED; goto free; } @@ -1773,13 +1801,14 @@ get_attr_val(uint8_t *data, uint16_t len) rp->att_response = out_att_err; rp->value_length = os_mbuf_len(buf) - sizeof(*rp); - tester_send_buf(BTP_SERVICE_ID_GATT, BTP_GATT_GET_ATTRIBUTE_VALUE, - CONTROLLER_INDEX, buf); + (void)memcpy(rsp, buf->om_data, buf->om_len); + *rsp_len = buf->om_len; goto free; } else { rp = os_mbuf_extend(buf, sizeof(*rp)); if (!rp) { + status = BTP_STATUS_FAILED; goto free; } @@ -1790,69 +1819,72 @@ get_attr_val(uint8_t *data, uint16_t len) rp->att_response = out_att_err; rp->value_length = os_mbuf_len(buf) - sizeof(*rp); - tester_send_buf(BTP_SERVICE_ID_GATT, BTP_GATT_GET_ATTRIBUTE_VALUE, - CONTROLLER_INDEX, buf); + (void)memcpy(rsp, buf->om_data, buf->om_len); + *rsp_len = buf->om_len; goto free; } free: os_mbuf_free_chain(buf); + return status; } -static void -change_database(uint8_t *data, uint16_t len) +static uint8_t +change_database(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - const struct btp_gatt_change_database *cmd = (void *) data; + const struct btp_gatt_change_database_cmd *cp = cmd; SYS_LOG_DBG("") ble_gatts_show_local(); - ble_svc_gatt_changed(cmd->start_handle, cmd->end_handle); - - tester_rsp(BTP_SERVICE_ID_GATT, BTP_GATT_CHANGE_DATABASE, - BTP_STATUS_SUCCESS); + ble_svc_gatt_changed(cp->start_handle, cp->end_handle); - return; + return BTP_STATUS_SUCCESS; } -static void -supported_commands(uint8_t *data, uint16_t len) +static uint8_t +supported_commands(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) { - uint8_t cmds[4]; - struct btp_gatt_read_supported_commands_rp *rp = (void *) cmds; - - SYS_LOG_DBG(""); - - memset(cmds, 0, sizeof(cmds)); - - tester_set_bit(cmds, BTP_GATT_READ_SUPPORTED_COMMANDS); - tester_set_bit(cmds, BTP_GATT_START_SERVER); - tester_set_bit(cmds, BTP_GATT_EXCHANGE_MTU); - tester_set_bit(cmds, BTP_GATT_DISC_ALL_PRIM_SVCS); - tester_set_bit(cmds, BTP_GATT_DISC_PRIM_UUID); - tester_set_bit(cmds, BTP_GATT_FIND_INCLUDED); - tester_set_bit(cmds, BTP_GATT_DISC_ALL_CHRC); - tester_set_bit(cmds, BTP_GATT_DISC_CHRC_UUID); - tester_set_bit(cmds, BTP_GATT_DISC_ALL_DESC); - tester_set_bit(cmds, BTP_GATT_READ); - tester_set_bit(cmds, BTP_GATT_READ_LONG); - tester_set_bit(cmds, BTP_GATT_READ_MULTIPLE); - tester_set_bit(cmds, BTP_GATT_WRITE_WITHOUT_RSP); + struct btp_gatt_read_supported_commands_rp *rp = rsp; + + /* octet 0 */ + tester_set_bit(rp->data, BTP_GATT_READ_SUPPORTED_COMMANDS); + tester_set_bit(rp->data, BTP_GATT_START_SERVER); + + /* octet 1 */ + tester_set_bit(rp->data, BTP_GATT_EXCHANGE_MTU); + tester_set_bit(rp->data, BTP_GATT_DISC_ALL_PRIM_SVCS); + tester_set_bit(rp->data, BTP_GATT_DISC_PRIM_UUID); + tester_set_bit(rp->data, BTP_GATT_FIND_INCLUDED); + tester_set_bit(rp->data, BTP_GATT_DISC_ALL_CHRC); + tester_set_bit(rp->data, BTP_GATT_DISC_CHRC_UUID); + + /* octet 2 */ + tester_set_bit(rp->data, BTP_GATT_DISC_ALL_DESC); + tester_set_bit(rp->data, BTP_GATT_READ); + tester_set_bit(rp->data, BTP_GATT_READ_LONG); + tester_set_bit(rp->data, BTP_GATT_READ_MULTIPLE); + tester_set_bit(rp->data, BTP_GATT_WRITE_WITHOUT_RSP); #if 0 - tester_set_bit(cmds, BTP_GATT_SIGNED_WRITE_WITHOUT_RSP); + tester_set_bit(rp->data, BTP_GATT_SIGNED_WRITE_WITHOUT_RSP); #endif - tester_set_bit(cmds, BTP_GATT_WRITE); - tester_set_bit(cmds, BTP_GATT_WRITE_LONG); - tester_set_bit(cmds, BTP_GATT_CFG_NOTIFY); - tester_set_bit(cmds, BTP_GATT_CFG_INDICATE); - tester_set_bit(cmds, BTP_GATT_GET_ATTRIBUTES); - tester_set_bit(cmds, BTP_GATT_GET_ATTRIBUTE_VALUE); - tester_set_bit(cmds, BTP_GATT_CHANGE_DATABASE); - - tester_send(BTP_SERVICE_ID_GATT, BTP_GATT_READ_SUPPORTED_COMMANDS, - (uint8_t *) rp, sizeof(cmds)); + tester_set_bit(rp->data, BTP_GATT_WRITE); + + /* octet 3 */ + tester_set_bit(rp->data, BTP_GATT_WRITE_LONG); + tester_set_bit(rp->data, BTP_GATT_CFG_NOTIFY); + tester_set_bit(rp->data, BTP_GATT_CFG_INDICATE); + tester_set_bit(rp->data, BTP_GATT_GET_ATTRIBUTES); + tester_set_bit(rp->data, BTP_GATT_GET_ATTRIBUTE_VALUE); + tester_set_bit(rp->data, BTP_GATT_CHANGE_DATABASE); + + *rsp_len = sizeof(*rp) + 4; + + return BTP_STATUS_SUCCESS; } enum attr_type { @@ -1861,88 +1893,126 @@ enum attr_type { BLE_GATT_ATTR_DSC, }; -void -tester_handle_gatt(uint8_t opcode, uint8_t *data, - uint16_t len) -{ - switch (opcode) { - case BTP_GATT_READ_SUPPORTED_COMMANDS: - supported_commands(data, len); - return; - case BTP_GATT_START_SERVER: - start_server(data, len); - return; - case BTP_GATT_EXCHANGE_MTU: - exchange_mtu(data, len); - return; - case BTP_GATT_DISC_ALL_PRIM_SVCS: - disc_all_prim_svcs(data, len); - return; - case BTP_GATT_DISC_PRIM_UUID: - disc_prim_uuid(data, len); - return; - case BTP_GATT_FIND_INCLUDED: - find_included(data, len); - return; - case BTP_GATT_DISC_ALL_CHRC: - disc_all_chrc(data, len); - return; - case BTP_GATT_DISC_CHRC_UUID: - disc_chrc_uuid(data, len); - return; - case BTP_GATT_DISC_ALL_DESC: - disc_all_desc(data, len); - return; - case BTP_GATT_CHANGE_DATABASE: - change_database(data, len); - return; - case BTP_GATT_READ: - read(data, len); - return; - case BTP_GATT_READ_UUID: - read_uuid(data, len); - return; - case BTP_GATT_READ_LONG: - read_long(data, len); - return; - case BTP_GATT_READ_MULTIPLE: - read_multiple(data, len); - return; - case BTP_GATT_WRITE_WITHOUT_RSP: - write_without_rsp(data, - len, - opcode, - false); - return; +static const struct btp_handler handlers[] = { + { + .opcode = BTP_GATT_READ_SUPPORTED_COMMANDS, + .index = BTP_INDEX_NONE, + .expect_len = 0, + .func = supported_commands, + }, + { + .opcode = BTP_GATT_START_SERVER, + .expect_len = 0, + .func = start_server, + }, + { + .opcode = BTP_GATT_EXCHANGE_MTU, + .expect_len = sizeof(struct btp_gatt_exchange_mtu_cmd), + .func = exchange_mtu, + }, + { + .opcode = BTP_GATT_DISC_ALL_PRIM_SVCS, + .expect_len = sizeof(struct btp_gatt_disc_all_prim_svcs_cmd), + .func = disc_all_prim_svcs, + }, + { + .opcode = BTP_GATT_DISC_PRIM_UUID, + .expect_len = -1, + .func = disc_prim_uuid, + }, + { + .opcode = BTP_GATT_FIND_INCLUDED, + .expect_len = sizeof(struct btp_gatt_find_included_cmd), + .func = find_included, + }, + { + .opcode = BTP_GATT_DISC_ALL_CHRC, + .expect_len = sizeof(struct btp_gatt_disc_all_chrc_cmd), + .func = disc_all_chrc, + }, + { + .opcode = BTP_GATT_DISC_CHRC_UUID, + .expect_len = -1, + .func = disc_chrc_uuid, + }, + { + .opcode = BTP_GATT_DISC_ALL_DESC, + .expect_len = sizeof(struct btp_gatt_disc_all_desc_cmd), + .func = disc_all_desc, + }, + { + .opcode = BTP_GATT_CHANGE_DATABASE, + .expect_len = sizeof(struct btp_gatt_change_database_cmd), + .func = change_database, + }, + { + .opcode = BTP_GATT_READ, + .expect_len = sizeof(struct btp_gatt_read_cmd), + .func = read_data, + }, + { + .opcode = BTP_GATT_READ_UUID, + .expect_len = -1, + .func = read_uuid, + }, + { + .opcode = BTP_GATT_READ_LONG, + .expect_len = sizeof(struct btp_gatt_read_long_cmd), + .func = read_long, + }, + { + .opcode = BTP_GATT_READ_MULTIPLE, + .expect_len = -1, + .func = read_multiple, + }, + { + .opcode = BTP_GATT_WRITE_WITHOUT_RSP, + .expect_len = -1, + .func = write_without_rsp, + }, #if 0 - case BTP_GATT_SIGNED_WRITE_WITHOUT_RSP: - write_without_rsp(data, len, opcode, true); - return; + { + .opcode = BTP_GATT_SIGNED_WRITE_WITHOUT_RSP, + .expect_len = -1, + .func = write_signed_without_rsp, + }, #endif - case BTP_GATT_WRITE: - write(data, len); - return; - case BTP_GATT_WRITE_LONG: - write_long(data, len); - return; - case BTP_GATT_RELIABLE_WRITE: - reliable_write(data, len); - return; - case BTP_GATT_CFG_NOTIFY: - case BTP_GATT_CFG_INDICATE: - config_subscription(data, len, opcode); - return; - case BTP_GATT_GET_ATTRIBUTES: - get_attrs(data, len); - return; - case BTP_GATT_GET_ATTRIBUTE_VALUE: - get_attr_val(data, len); - return; - default: - tester_rsp(BTP_SERVICE_ID_GATT, opcode, BTP_STATUS_UNKNOWN_CMD); - return; - } -} + { + .opcode = BTP_GATT_WRITE, + .expect_len = -1, + .func = write_data, + }, + { + .opcode = BTP_GATT_WRITE_LONG, + .expect_len = -1, + .func = write_long, + }, + { + .opcode = BTP_GATT_RELIABLE_WRITE, + .expect_len = -1, + .func = reliable_write, + }, + { + .opcode = BTP_GATT_CFG_NOTIFY, + .expect_len = sizeof(struct btp_gatt_cfg_notify_cmd), + .func = config_subscription_notif, + }, + { + .opcode = BTP_GATT_CFG_INDICATE, + .expect_len = sizeof(struct btp_gatt_cfg_notify_cmd), + .func = config_subscription_ind, + }, + { + .opcode = BTP_GATT_GET_ATTRIBUTES, + .expect_len = -1, + .func = get_attrs, + }, + { + .opcode = BTP_GATT_GET_ATTRIBUTE_VALUE, + .expect_len = sizeof(struct btp_gatt_get_attribute_value_cmd), + .func = get_attr_val, + }, +}; int tester_gatt_notify_rx_ev(uint16_t conn_handle, uint16_t attr_handle, @@ -2148,6 +2218,9 @@ tester_init_gatt(void) os_callout_init(¬ify_tx_timer, os_eventq_dflt_get(), notify_test, NULL); + tester_register_command_handlers(BTP_SERVICE_ID_GATT, handlers, + ARRAY_SIZE(handlers)); + return BTP_STATUS_SUCCESS; }
