You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2022/04/19 06:22:40 UTC
[GitHub] [mynewt-nimble] utzig commented on pull request #1096: apps/bttester: handle options of created L2CAP server
utzig commented on PR #1096:
URL: https://github.com/apache/mynewt-nimble/pull/1096#issuecomment-1102137785
<!-- style-bot -->
## Style check summary
### Our coding style is [here!](https://github.com/apache/mynewt-core/blob/master/CODING_STANDARDS.md)
#### apps/bttester/src/bttester.h
<details>
```diff
@@ -716,92 +716,94 @@
} __packed;
/* GATT events */
-#define GATT_EV_NOTIFICATION 0x80
+#define GATT_EV_NOTIFICATION 0x80
struct gatt_notification_ev {
- uint8_t address_type;
- uint8_t address[6];
- uint8_t type;
- uint16_t handle;
- uint16_t data_length;
- uint8_t data[0];
-} __packed;
-
-#define GATT_EV_ATTR_VALUE_CHANGED 0x81
+ uint8_t address_type;
+ uint8_t address[6];
+ uint8_t type;
+ uint16_t handle;
+ uint16_t data_length;
+ uint8_t data[0];
+} __packed;
+
+#define GATT_EV_ATTR_VALUE_CHANGED 0x81
struct gatt_attr_value_changed_ev {
- uint16_t handle;
- uint16_t data_length;
- uint8_t data[0];
-} __packed;
-
-static inline void tester_set_bit(uint8_t *addr, unsigned int bit)
+ uint16_t handle;
+ uint16_t data_length;
+ uint8_t data[0];
+} __packed;
+
+static inline void
+tester_set_bit(uint8_t *addr, unsigned int bit)
{
- uint8_t *p = addr + (bit / 8);
-
- *p |= BIT(bit % 8);
+ uint8_t *p = addr + (bit / 8);
+
+ *p |= BIT(bit % 8);
}
-static inline uint8_t tester_test_bit(const uint8_t *addr, unsigned int bit)
+static inline uint8_t
+tester_test_bit(const uint8_t *addr, unsigned int bit)
{
- const uint8_t *p = addr + (bit / 8);
-
- return *p & BIT(bit % 8);
+ const uint8_t *p = addr + (bit / 8);
+
+ return *p & BIT(bit % 8);
}
/* L2CAP Service */
/* commands */
-#define L2CAP_READ_SUPPORTED_COMMANDS 0x01
+#define L2CAP_READ_SUPPORTED_COMMANDS 0x01
struct l2cap_read_supported_commands_rp {
- uint8_t data[0];
-} __packed;
-
-#define L2CAP_CONNECT_OPT_ECFC 0x01
-#define L2CAP_CONNECT_OPT_HOLD_CREDIT 0x02
-
-#define L2CAP_CONNECT 0x02
+ uint8_t data[0];
+} __packed;
+
+#define L2CAP_CONNECT_OPT_ECFC 0x01
+#define L2CAP_CONNECT_OPT_HOLD_CREDIT 0x02
+
+#define L2CAP_CONNECT 0x02
struct l2cap_connect_cmd {
- uint8_t address_type;
- uint8_t address[6];
- uint16_t psm;
- uint16_t mtu;
- uint8_t num;
- uint8_t options;
+ uint8_t address_type;
+ uint8_t address[6];
+ uint16_t psm;
+ uint16_t mtu;
+ uint8_t num;
+ uint8_t options;
} __packed;
struct l2cap_connect_rp {
- uint8_t num;
- uint8_t chan_ids[0];
-} __packed;
-
-#define L2CAP_DISCONNECT 0x03
+ uint8_t num;
+ uint8_t chan_ids[0];
+} __packed;
+
+#define L2CAP_DISCONNECT 0x03
struct l2cap_disconnect_cmd {
- uint8_t chan_id;
-} __packed;
-
-#define L2CAP_SEND_DATA 0x04
+ uint8_t chan_id;
+} __packed;
+
+#define L2CAP_SEND_DATA 0x04
struct l2cap_send_data_cmd {
- uint8_t chan_id;
- uint16_t data_len;
- uint8_t data[];
-} __packed;
-
-#define L2CAP_TRANSPORT_BREDR 0x00
-#define L2CAP_TRANSPORT_LE 0x01
-
-#define L2CAP_LISTEN 0x05
+ uint8_t chan_id;
+ uint16_t data_len;
+ uint8_t data[];
+} __packed;
+
+#define L2CAP_TRANSPORT_BREDR 0x00
+#define L2CAP_TRANSPORT_LE 0x01
+
+#define L2CAP_LISTEN 0x05
struct l2cap_listen_cmd {
- uint16_t psm;
- uint8_t transport;
- uint16_t mtu;
- uint16_t response;
-} __packed;
-
-#define L2CAP_ACCEPT_CONNECTION 0x06
+ uint16_t psm;
+ uint8_t transport;
+ uint16_t mtu;
+ uint16_t response;
+} __packed;
+
+#define L2CAP_ACCEPT_CONNECTION 0x06
struct l2cap_accept_connection_cmd {
- uint8_t chan_id;
- uint16_t result;
-} __packed;
-
-#define L2CAP_RECONFIGURE 0x07
+ uint8_t chan_id;
+ uint16_t result;
+} __packed;
+
+#define L2CAP_RECONFIGURE 0x07
struct l2cap_reconfigure_cmd {
uint8_t address_type;
uint8_t address[6];
@@ -810,215 +812,215 @@
uint8_t idxs[];
} __packed;
-#define L2CAP_CREDITS 0x08
+#define L2CAP_CREDITS 0x08
struct l2cap_credits_cmd {
uint8_t chan_id;
} __packed;
/* events */
-#define L2CAP_EV_CONNECTION_REQ 0x80
+#define L2CAP_EV_CONNECTION_REQ 0x80
struct l2cap_connection_req_ev {
- uint8_t chan_id;
- uint16_t psm;
- uint8_t address_type;
- uint8_t address[6];
-} __packed;
-
-#define L2CAP_EV_CONNECTED 0x81
+ uint8_t chan_id;
+ uint16_t psm;
+ uint8_t address_type;
+ uint8_t address[6];
+} __packed;
+
+#define L2CAP_EV_CONNECTED 0x81
struct l2cap_connected_ev {
- uint8_t chan_id;
- uint16_t psm;
- uint16_t peer_mtu;
- uint16_t peer_mps;
- uint16_t our_mtu;
- uint16_t our_mps;
- uint8_t address_type;
- uint8_t address[6];
-} __packed;
-
-#define L2CAP_EV_DISCONNECTED 0x82
+ uint8_t chan_id;
+ uint16_t psm;
+ uint16_t peer_mtu;
+ uint16_t peer_mps;
+ uint16_t our_mtu;
+ uint16_t our_mps;
+ uint8_t address_type;
+ uint8_t address[6];
+} __packed;
+
+#define L2CAP_EV_DISCONNECTED 0x82
struct l2cap_disconnected_ev {
- uint16_t result;
- uint8_t chan_id;
- uint16_t psm;
- uint8_t address_type;
- uint8_t address[6];
-} __packed;
-
-#define L2CAP_EV_DATA_RECEIVED 0x83
+ uint16_t result;
+ uint8_t chan_id;
+ uint16_t psm;
+ uint8_t address_type;
+ uint8_t address[6];
+} __packed;
+
+#define L2CAP_EV_DATA_RECEIVED 0x83
struct l2cap_data_received_ev {
- uint8_t chan_id;
- uint16_t data_length;
- uint8_t data[0];
-} __packed;
-
-#define L2CAP_EV_RECONFIGURED 0x84
+ uint8_t chan_id;
+ uint16_t data_length;
+ uint8_t data[0];
+} __packed;
+
+#define L2CAP_EV_RECONFIGURED 0x84
struct l2cap_reconfigured_ev {
- uint8_t chan_id;
- uint16_t peer_mtu;
- uint16_t peer_mps;
- uint16_t our_mtu;
- uint16_t our_mps;
+ uint8_t chan_id;
+ uint16_t peer_mtu;
+ uint16_t peer_mps;
+ uint16_t our_mtu;
+ uint16_t our_mps;
} __packed;
/* MESH Service */
/* commands */
-#define MESH_READ_SUPPORTED_COMMANDS 0x01
+#define MESH_READ_SUPPORTED_COMMANDS 0x01
struct mesh_read_supported_commands_rp {
- uint8_t data[0];
-} __packed;
-
-#define MESH_OUT_BLINK BIT(0)
-#define MESH_OUT_BEEP BIT(1)
-#define MESH_OUT_VIBRATE BIT(2)
-#define MESH_OUT_DISPLAY_NUMBER BIT(3)
-#define MESH_OUT_DISPLAY_STRING BIT(4)
-
-#define MESH_IN_PUSH BIT(0)
-#define MESH_IN_TWIST BIT(1)
-#define MESH_IN_ENTER_NUMBER BIT(2)
-#define MESH_IN_ENTER_STRING BIT(3)
-
-#define MESH_CONFIG_PROVISIONING 0x02
+ uint8_t data[0];
+} __packed;
+
+#define MESH_OUT_BLINK BIT(0)
+#define MESH_OUT_BEEP BIT(1)
+#define MESH_OUT_VIBRATE BIT(2)
+#define MESH_OUT_DISPLAY_NUMBER BIT(3)
+#define MESH_OUT_DISPLAY_STRING BIT(4)
+
+#define MESH_IN_PUSH BIT(0)
+#define MESH_IN_TWIST BIT(1)
+#define MESH_IN_ENTER_NUMBER BIT(2)
+#define MESH_IN_ENTER_STRING BIT(3)
+
+#define MESH_CONFIG_PROVISIONING 0x02
struct mesh_config_provisioning_cmd {
- uint8_t uuid[16];
- uint8_t static_auth[16];
- uint8_t out_size;
- uint16_t out_actions;
- uint8_t in_size;
- uint16_t in_actions;
-} __packed;
-
-#define MESH_PROVISION_NODE 0x03
+ uint8_t uuid[16];
+ uint8_t static_auth[16];
+ uint8_t out_size;
+ uint16_t out_actions;
+ uint8_t in_size;
+ uint16_t in_actions;
+} __packed;
+
+#define MESH_PROVISION_NODE 0x03
struct mesh_provision_node_cmd {
- uint8_t net_key[16];
- uint16_t net_key_idx;
- uint8_t flags;
- uint32_t iv_index;
- uint32_t seq_num;
- uint16_t addr;
- uint8_t dev_key[16];
-} __packed;
-
-#define MESH_INIT 0x04
-#define MESH_RESET 0x05
-#define MESH_INPUT_NUMBER 0x06
+ uint8_t net_key[16];
+ uint16_t net_key_idx;
+ uint8_t flags;
+ uint32_t iv_index;
+ uint32_t seq_num;
+ uint16_t addr;
+ uint8_t dev_key[16];
+} __packed;
+
+#define MESH_INIT 0x04
+#define MESH_RESET 0x05
+#define MESH_INPUT_NUMBER 0x06
struct mesh_input_number_cmd {
- uint32_t number;
-} __packed;
-
-#define MESH_INPUT_STRING 0x07
+ uint32_t number;
+} __packed;
+
+#define MESH_INPUT_STRING 0x07
struct mesh_input_string_cmd {
- uint8_t string_len;
- uint8_t string[0];
-} __packed;
-
-#define MESH_IVU_TEST_MODE 0x08
+ uint8_t string_len;
+ uint8_t string[0];
+} __packed;
+
+#define MESH_IVU_TEST_MODE 0x08
struct mesh_ivu_test_mode_cmd {
- uint8_t enable;
-} __packed;
-
-#define MESH_IVU_TOGGLE_STATE 0x09
-
-#define MESH_NET_SEND 0x0a
+ uint8_t enable;
+} __packed;
+
+#define MESH_IVU_TOGGLE_STATE 0x09
+
+#define MESH_NET_SEND 0x0a
struct mesh_net_send_cmd {
- uint8_t ttl;
- uint16_t src;
- uint16_t dst;
- uint8_t payload_len;
- uint8_t payload[0];
-} __packed;
-
-#define MESH_HEALTH_GENERATE_FAULTS 0x0b
+ uint8_t ttl;
+ uint16_t src;
+ uint16_t dst;
+ uint8_t payload_len;
+ uint8_t payload[0];
+} __packed;
+
+#define MESH_HEALTH_GENERATE_FAULTS 0x0b
struct mesh_health_generate_faults_rp {
- uint8_t test_id;
- uint8_t cur_faults_count;
- uint8_t reg_faults_count;
- uint8_t current_faults[0];
- uint8_t registered_faults[0];
-} __packed;
-
-#define MESH_HEALTH_CLEAR_FAULTS 0x0c
-
-#define MESH_LPN 0x0d
+ uint8_t test_id;
+ uint8_t cur_faults_count;
+ uint8_t reg_faults_count;
+ uint8_t current_faults[0];
+ uint8_t registered_faults[0];
+} __packed;
+
+#define MESH_HEALTH_CLEAR_FAULTS 0x0c
+
+#define MESH_LPN 0x0d
struct mesh_lpn_set_cmd {
- uint8_t enable;
-} __packed;
-
-#define MESH_LPN_POLL 0x0e
-
-#define MESH_MODEL_SEND 0x0f
+ uint8_t enable;
+} __packed;
+
+#define MESH_LPN_POLL 0x0e
+
+#define MESH_MODEL_SEND 0x0f
struct mesh_model_send_cmd {
- uint16_t src;
- uint16_t dst;
- uint8_t payload_len;
- uint8_t payload[0];
-} __packed;
-
-#define MESH_LPN_SUBSCRIBE 0x10
+ uint16_t src;
+ uint16_t dst;
+ uint8_t payload_len;
+ uint8_t payload[0];
+} __packed;
+
+#define MESH_LPN_SUBSCRIBE 0x10
struct mesh_lpn_subscribe_cmd {
- uint16_t address;
-} __packed;
-
-#define MESH_LPN_UNSUBSCRIBE 0x11
+ uint16_t address;
+} __packed;
+
+#define MESH_LPN_UNSUBSCRIBE 0x11
struct mesh_lpn_unsubscribe_cmd {
- uint16_t address;
-} __packed;
-
-#define MESH_RPL_CLEAR 0x12
-#define MESH_PROXY_IDENTITY 0x13
+ uint16_t address;
+} __packed;
+
+#define MESH_RPL_CLEAR 0x12
+#define MESH_PROXY_IDENTITY 0x13
/* events */
-#define MESH_EV_OUT_NUMBER_ACTION 0x80
+#define MESH_EV_OUT_NUMBER_ACTION 0x80
struct mesh_out_number_action_ev {
- uint16_t action;
- uint32_t number;
-} __packed;
-
-#define MESH_EV_OUT_STRING_ACTION 0x81
+ uint16_t action;
+ uint32_t number;
+} __packed;
+
+#define MESH_EV_OUT_STRING_ACTION 0x81
struct mesh_out_string_action_ev {
- uint8_t string_len;
- uint8_t string[0];
-} __packed;
-
-#define MESH_EV_IN_ACTION 0x82
+ uint8_t string_len;
+ uint8_t string[0];
+} __packed;
+
+#define MESH_EV_IN_ACTION 0x82
struct mesh_in_action_ev {
- uint16_t action;
- uint8_t size;
-} __packed;
-
-#define MESH_EV_PROVISIONED 0x83
-
-#define MESH_PROV_BEARER_PB_ADV 0x00
-#define MESH_PROV_BEARER_PB_GATT 0x01
-#define MESH_EV_PROV_LINK_OPEN 0x84
+ uint16_t action;
+ uint8_t size;
+} __packed;
+
+#define MESH_EV_PROVISIONED 0x83
+
+#define MESH_PROV_BEARER_PB_ADV 0x00
+#define MESH_PROV_BEARER_PB_GATT 0x01
+#define MESH_EV_PROV_LINK_OPEN 0x84
struct mesh_prov_link_open_ev {
- uint8_t bearer;
-} __packed;
-
-#define MESH_EV_PROV_LINK_CLOSED 0x85
+ uint8_t bearer;
+} __packed;
+
+#define MESH_EV_PROV_LINK_CLOSED 0x85
struct mesh_prov_link_closed_ev {
- uint8_t bearer;
-} __packed;
-
-#define MESH_EV_NET_RECV 0x86
+ uint8_t bearer;
+} __packed;
+
+#define MESH_EV_NET_RECV 0x86
struct mesh_net_recv_ev {
- uint8_t ttl;
- uint8_t ctl;
- uint16_t src;
- uint16_t dst;
- uint8_t payload_len;
- uint8_t payload[0];
-} __packed;
-
-#define MESH_EV_INVALID_BEARER 0x87
+ uint8_t ttl;
+ uint8_t ctl;
+ uint16_t src;
+ uint16_t dst;
+ uint8_t payload_len;
+ uint8_t payload[0];
+} __packed;
+
+#define MESH_EV_INVALID_BEARER 0x87
struct mesh_invalid_bearer_ev {
- uint8_t opcode;
-} __packed;
-
-#define MESH_EV_INCOMP_TIMER_EXP 0x88
-
-#define MESH_EV_LPN_ESTABLISHED 0x8b
+ uint8_t opcode;
+} __packed;
+
+#define MESH_EV_INCOMP_TIMER_EXP 0x88
+
+#define MESH_EV_LPN_ESTABLISHED 0x8b
struct mesh_lpn_established_ev {
uint16_t net_idx;
uint16_t friend_addr;
```
</details>
#### apps/bttester/src/l2cap.c
<details>
```diff
@@ -51,572 +51,586 @@
static bool hold_credit = false;
static struct channel {
- uint8_t chan_id; /* Internal number that identifies L2CAP channel. */
- uint8_t state;
- struct ble_l2cap_chan *chan;
+ uint8_t chan_id; /* Internal number that identifies L2CAP channel. */
+ uint8_t state;
+ struct ble_l2cap_chan *chan;
} channels[CHANNELS];
static uint8_t recv_cb_buf[TESTER_COC_MTU + sizeof(struct l2cap_data_received_ev)];
-static struct channel *get_free_channel(void)
-{
- uint8_t i;
- struct channel *chan;
-
- for (i = 0; i < CHANNELS; i++) {
- if (channels[i].state) {
- continue;
- }
-
- chan = &channels[i];
- chan->chan_id = i;
-
- return chan;
- }
-
- return NULL;
-}
-
-struct channel *find_channel(struct ble_l2cap_chan *chan)
-{
- int i;
-
- for (i = 0; i < CHANNELS; ++i) {
- if (channels[i].chan == chan) {
- return &channels[i];
- }
- }
-
- return NULL;
-}
-
-struct channel *get_channel(uint8_t chan_id)
-{
- if (chan_id >= CHANNELS) {
- return NULL;
- }
-
- return &channels[chan_id];
+static struct channel *
+get_free_channel(void)
+{
+ uint8_t i;
+ struct channel *chan;
+
+ for (i = 0; i < CHANNELS; i++) {
+ if (channels[i].state) {
+ continue;
+ }
+
+ chan = &channels[i];
+ chan->chan_id = i;
+
+ return chan;
+ }
+
+ return NULL;
+}
+
+struct channel *
+find_channel(struct ble_l2cap_chan *chan)
+{
+ int i;
+
+ for (i = 0; i < CHANNELS; ++i) {
+ if (channels[i].chan == chan) {
+ return &channels[i];
+ }
+ }
+
+ return NULL;
+}
+
+struct channel *
+get_channel(uint8_t chan_id)
+{
+ if (chan_id >= CHANNELS) {
+ return NULL;
+ }
+
+ return &channels[chan_id];
}
static void
tester_l2cap_coc_recv(struct ble_l2cap_chan *chan, struct os_mbuf *sdu)
{
- SYS_LOG_DBG("LE CoC SDU received, chan: 0x%08lx, data len %d",
- (uint32_t) chan, OS_MBUF_PKTLEN(sdu));
-
- os_mbuf_free_chain(sdu);
- if (!hold_credit) {
- sdu = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
- assert(sdu != NULL);
-
-
- ble_l2cap_recv_ready(chan, sdu);
- }
-}
-
-static void recv_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
- struct os_mbuf *buf, void *arg)
-{
- struct l2cap_data_received_ev *ev = (void *) recv_cb_buf;
- struct channel *channel = find_channel(chan);
- assert(channel != NULL);
-
- ev->chan_id = channel->chan_id;
- ev->data_length = OS_MBUF_PKTLEN(buf);
-
- if (ev->data_length > TESTER_COC_MTU) {
- SYS_LOG_ERR("Too large sdu received, truncating data");
- ev->data_length = TESTER_COC_MTU;
- }
- os_mbuf_copydata(buf, 0, ev->data_length, ev->data);
-
- tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_DATA_RECEIVED,
- CONTROLLER_INDEX, recv_cb_buf, sizeof(*ev) + ev->data_length);
-
- tester_l2cap_coc_recv(chan, buf);
-}
-
-static void unstalled_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
- int status, void *arg)
-{
- if (status) {
- tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_SEND_DATA,
- CONTROLLER_INDEX, BTP_STATUS_FAILED);
- } else {
- tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_SEND_DATA,
- CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
- }
-}
-
-static void reconfigured_ev(uint16_t conn_handle, struct ble_l2cap_chan *chan,
- struct ble_l2cap_chan_info *chan_info,
- int status)
-{
- struct l2cap_reconfigured_ev ev;
- struct channel *channel;
-
- if (status != 0) {
- return;
- }
-
- channel = find_channel(chan);
- assert(channel != NULL);
-
- ev.chan_id = channel->chan_id;
- ev.peer_mtu = chan_info->peer_coc_mtu;
- ev.peer_mps = chan_info->peer_l2cap_mtu;
- ev.our_mtu = chan_info->our_coc_mtu;
- ev.our_mps = chan_info->our_l2cap_mtu;
-
- tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_RECONFIGURED,
- CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
-}
-
-static void connected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
- struct ble_l2cap_chan_info *chan_info, void *arg)
-{
- struct l2cap_connected_ev ev;
- struct ble_gap_conn_desc desc;
- struct channel *channel = find_channel(chan);
-
- if (channel == NULL) {
- channel = get_free_channel();
- }
-
- ev.chan_id = channel->chan_id;
- ev.psm = chan_info->psm;
- ev.peer_mtu = chan_info->peer_coc_mtu;
- ev.peer_mps = chan_info->peer_l2cap_mtu;
- ev.our_mtu = chan_info->our_coc_mtu;
- ev.our_mps = chan_info->our_l2cap_mtu;
- channel->state = 1;
- channel->chan = chan;
-
- if (!ble_gap_conn_find(conn_handle, &desc)) {
- ev.address_type = desc.peer_ota_addr.type;
- memcpy(ev.address, desc.peer_ota_addr.val,
- sizeof(ev.address));
- }
-
- tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_CONNECTED, CONTROLLER_INDEX,
- (uint8_t *) &ev, sizeof(ev));
-}
-
-static void disconnected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
- struct ble_l2cap_chan_info *chan_info, void *arg)
-{
- struct l2cap_disconnected_ev ev;
- struct ble_gap_conn_desc desc;
- struct channel *channel;
-
- memset(&ev, 0, sizeof(struct l2cap_disconnected_ev));
-
- channel = find_channel(chan);
- assert(channel != NULL);
-
- channel->state = 0;
- channel->chan = chan;
- ev.chan_id = channel->chan_id;
- ev.psm = chan_info->psm;
-
- if (!ble_gap_conn_find(conn_handle, &desc)) {
- ev.address_type = desc.peer_ota_addr.type;
- memcpy(ev.address, desc.peer_ota_addr.val,
- sizeof(ev.address));
- }
-
- tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_DISCONNECTED,
- CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
-}
-
-static int accept_cb(uint16_t conn_handle, uint16_t peer_mtu,
- struct ble_l2cap_chan *chan)
-{
- struct os_mbuf *sdu_rx;
-
- SYS_LOG_DBG("LE CoC accepting, chan: 0x%08lx, peer_mtu %d",
- (uint32_t) chan, peer_mtu);
-
- sdu_rx = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
- if (!sdu_rx) {
- return BLE_HS_ENOMEM;
- }
-
- ble_l2cap_recv_ready(chan, sdu_rx);
-
- return 0;
+ SYS_LOG_DBG("LE CoC SDU received, chan: 0x%08lx, data len %d",
+ (uint32_t) chan, OS_MBUF_PKTLEN(sdu));
+
+ os_mbuf_free_chain(sdu);
+ if (!hold_credit) {
+ sdu = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
+ assert(sdu != NULL);
+
+
+ ble_l2cap_recv_ready(chan, sdu);
+ }
+}
+
+static void
+recv_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
+ struct os_mbuf *buf, void *arg)
+{
+ struct l2cap_data_received_ev *ev = (void *) recv_cb_buf;
+ struct channel *channel = find_channel(chan);
+ assert(channel != NULL);
+
+ ev->chan_id = channel->chan_id;
+ ev->data_length = OS_MBUF_PKTLEN(buf);
+
+ if (ev->data_length > TESTER_COC_MTU) {
+ SYS_LOG_ERR("Too large sdu received, truncating data");
+ ev->data_length = TESTER_COC_MTU;
+ }
+ os_mbuf_copydata(buf, 0, ev->data_length, ev->data);
+
+ tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_DATA_RECEIVED,
+ CONTROLLER_INDEX, recv_cb_buf, sizeof(*ev) + ev->data_length);
+
+ tester_l2cap_coc_recv(chan, buf);
+}
+
+static void
+unstalled_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
+ int status, void *arg)
+{
+ if (status) {
+ tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_SEND_DATA,
+ CONTROLLER_INDEX, BTP_STATUS_FAILED);
+ } else {
+ tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_SEND_DATA,
+ CONTROLLER_INDEX, BTP_STATUS_SUCCESS);
+ }
+}
+
+static void
+reconfigured_ev(uint16_t conn_handle, struct ble_l2cap_chan *chan,
+ struct ble_l2cap_chan_info *chan_info,
+ int status)
+{
+ struct l2cap_reconfigured_ev ev;
+ struct channel *channel;
+
+ if (status != 0) {
+ return;
+ }
+
+ channel = find_channel(chan);
+ assert(channel != NULL);
+
+ ev.chan_id = channel->chan_id;
+ ev.peer_mtu = chan_info->peer_coc_mtu;
+ ev.peer_mps = chan_info->peer_l2cap_mtu;
+ ev.our_mtu = chan_info->our_coc_mtu;
+ ev.our_mps = chan_info->our_l2cap_mtu;
+
+ tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_RECONFIGURED,
+ CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
+}
+
+static void
+connected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
+ struct ble_l2cap_chan_info *chan_info, void *arg)
+{
+ struct l2cap_connected_ev ev;
+ struct ble_gap_conn_desc desc;
+ struct channel *channel = find_channel(chan);
+
+ if (channel == NULL) {
+ channel = get_free_channel();
+ }
+
+ ev.chan_id = channel->chan_id;
+ ev.psm = chan_info->psm;
+ ev.peer_mtu = chan_info->peer_coc_mtu;
+ ev.peer_mps = chan_info->peer_l2cap_mtu;
+ ev.our_mtu = chan_info->our_coc_mtu;
+ ev.our_mps = chan_info->our_l2cap_mtu;
+ channel->state = 1;
+ channel->chan = chan;
+
+ if (!ble_gap_conn_find(conn_handle, &desc)) {
+ ev.address_type = desc.peer_ota_addr.type;
+ memcpy(ev.address, desc.peer_ota_addr.val,
+ sizeof(ev.address));
+ }
+
+ tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_CONNECTED, CONTROLLER_INDEX,
+ (uint8_t *) &ev, sizeof(ev));
+}
+
+static void
+disconnected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan,
+ struct ble_l2cap_chan_info *chan_info, void *arg)
+{
+ struct l2cap_disconnected_ev ev;
+ struct ble_gap_conn_desc desc;
+ struct channel *channel;
+
+ memset(&ev, 0, sizeof(struct l2cap_disconnected_ev));
+
+ channel = find_channel(chan);
+ assert(channel != NULL);
+
+ channel->state = 0;
+ channel->chan = chan;
+ ev.chan_id = channel->chan_id;
+ ev.psm = chan_info->psm;
+
+ if (!ble_gap_conn_find(conn_handle, &desc)) {
+ ev.address_type = desc.peer_ota_addr.type;
+ memcpy(ev.address, desc.peer_ota_addr.val,
+ sizeof(ev.address));
+ }
+
+ tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_DISCONNECTED,
+ CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
+}
+
+static int
+accept_cb(uint16_t conn_handle, uint16_t peer_mtu,
+ struct ble_l2cap_chan *chan)
+{
+ struct os_mbuf *sdu_rx;
+
+ SYS_LOG_DBG("LE CoC accepting, chan: 0x%08lx, peer_mtu %d",
+ (uint32_t) chan, peer_mtu);
+
+ sdu_rx = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
+ if (!sdu_rx) {
+ return BLE_HS_ENOMEM;
+ }
+
+ ble_l2cap_recv_ready(chan, sdu_rx);
+
+ return 0;
}
static int
tester_l2cap_event(struct ble_l2cap_event *event, void *arg)
{
- struct ble_l2cap_chan_info chan_info;
- int accept_response;
- struct ble_gap_conn_desc conn;
-
- switch (event->type) {
- case BLE_L2CAP_EVENT_COC_CONNECTED:
- if (ble_l2cap_get_chan_info(event->connect.chan, &chan_info)) {
- assert(0);
- }
-
- 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, "
- "psm: 0x%02x, scid: 0x%04x, dcid: 0x%04x, "
- "our_mps: %d, our_mtu: %d, peer_mps: %d, "
- "peer_mtu: %d\n", event->connect.conn_handle,
- (uint32_t) event->connect.chan, chan_info.psm,
- chan_info.scid, chan_info.dcid,
- chan_info.our_l2cap_mtu, chan_info.our_coc_mtu,
- chan_info.peer_l2cap_mtu, chan_info.peer_coc_mtu);
-
- connected_cb(event->connect.conn_handle,
- event->connect.chan, &chan_info, arg);
-
- return 0;
- case BLE_L2CAP_EVENT_COC_DISCONNECTED:
- if (ble_l2cap_get_chan_info(event->disconnect.chan,
- &chan_info)) {
- assert(0);
- }
- console_printf("LE CoC disconnected, chan: 0x%08lx\n",
- (uint32_t) event->disconnect.chan);
-
- disconnected_cb(event->disconnect.conn_handle,
- event->disconnect.chan, &chan_info, arg);
- return 0;
- case BLE_L2CAP_EVENT_COC_ACCEPT:
- ble_l2cap_get_chan_info(event->accept.chan, &chan_info);
- if (chan_info.psm == 0x00F2) {
- /* TSPX_psm_authentication_required */
- ble_gap_conn_find(event->accept.conn_handle, &conn);
- if (!conn.sec_state.authenticated) {
- return BLE_HS_EAUTHEN;
- }
- } else if (chan_info.psm == 0x00F3) {
- /* TSPX_psm_authorization_required */
- ble_gap_conn_find(event->accept.conn_handle, &conn);
- if (!conn.sec_state.encrypted) {
- return BLE_HS_EAUTHOR;
- }
- return BLE_HS_EAUTHOR;
- } else if (chan_info.psm == 0x00F4) {
- /* TSPX_psm_encryption_key_size_required */
- ble_gap_conn_find(event->accept.conn_handle, &conn);
- if (conn.sec_state.key_size < 16) {
- return BLE_HS_EENCRYPT_KEY_SZ;
- }
- }
-
- accept_response = POINTER_TO_INT(arg);
- if (accept_response) {
- return accept_response;
- }
-
- console_printf("LE CoC accept, chan: 0x%08lx, handle: %u, sdu_size: %u\n",
- (uint32_t) event->accept.chan,
- event->accept.conn_handle,
- event->accept.peer_sdu_size);
-
- return accept_cb(event->accept.conn_handle,
- event->accept.peer_sdu_size,
- event->accept.chan);
-
- case BLE_L2CAP_EVENT_COC_DATA_RECEIVED:
- console_printf("LE CoC data received, chan: 0x%08lx, handle: %u, sdu_len: %u\n",
- (uint32_t) event->receive.chan,
- event->receive.conn_handle,
- OS_MBUF_PKTLEN(event->receive.sdu_rx));
-
- recv_cb(event->receive.conn_handle, event->receive.chan,
- event->receive.sdu_rx, arg);
- return 0;
- case BLE_L2CAP_EVENT_COC_TX_UNSTALLED:
- console_printf("LE CoC tx unstalled, chan: 0x%08lx, handle: %u, status: %d\n",
- (uint32_t) event->tx_unstalled.chan,
- event->tx_unstalled.conn_handle,
- event->tx_unstalled.status);
-
- unstalled_cb(event->tx_unstalled.conn_handle,
- event->tx_unstalled.chan,
- event->tx_unstalled.status, arg);
- return 0;
- case BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED:
- if (ble_l2cap_get_chan_info(event->reconfigured.chan,
- &chan_info)) {
- assert(0);
- }
- console_printf("LE CoC reconfigure completed status 0x%02x, "
- "chan: 0x%08lx\n", event->reconfigured.status,
- (uint32_t) event->reconfigured.chan);
-
- if (event->reconfigured.status == 0) {
- console_printf("\t our_mps: %d our_mtu %d\n",
- chan_info.our_l2cap_mtu, chan_info.our_coc_mtu);
- }
-
- reconfigured_ev(event->reconfigured.conn_handle,
- event->reconfigured.chan,
- &chan_info,
- event->reconfigured.status);
- return 0;
- case BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED:
- if (ble_l2cap_get_chan_info(event->reconfigured.chan,
- &chan_info)) {
- assert(0);
- }
- console_printf("LE CoC peer reconfigured status 0x%02x, "
- "chan: 0x%08lx\n", event->reconfigured.status,
- (uint32_t) event->reconfigured.chan);
-
- if (event->reconfigured.status == 0) {
- console_printf("\t peer_mps: %d peer_mtu %d\n",
- chan_info.peer_l2cap_mtu, chan_info.peer_coc_mtu);
- }
-
- reconfigured_ev(event->reconfigured.conn_handle,
- event->reconfigured.chan,
- &chan_info,
- event->reconfigured.status);
- return 0;
- default:
- return 0;
- }
-}
-
-static void connect(uint8_t *data, uint16_t len)
-{
- const struct l2cap_connect_cmd *cmd = (void *) data;
- uint8_t rp_buf[sizeof(struct l2cap_connect_rp) + cmd->num];
- struct l2cap_connect_rp *rp = (void *) rp_buf;
- struct ble_gap_conn_desc desc;
- struct channel *chan;
- struct os_mbuf *sdu_rx[cmd->num];
- ble_addr_t *addr = (void *) data;
- uint16_t mtu = htole16(cmd->mtu);
- int rc;
- int i, j;
- bool ecfc = cmd->options & L2CAP_CONNECT_OPT_ECFC;
- hold_credit = cmd->options & L2CAP_CONNECT_OPT_HOLD_CREDIT;
-
- SYS_LOG_DBG("connect: type: %d addr: %s", addr->type, bt_hex(addr->val, 6));
-
- if (mtu == 0 || mtu > TESTER_COC_MTU) {
- mtu = TESTER_COC_MTU;
- }
-
- rc = ble_gap_conn_find_by_addr(addr, &desc);
- if (rc) {
- SYS_LOG_ERR("GAP conn find failed");
- goto fail;
- }
-
- rp->num = cmd->num;
-
- for (i = 0; i < cmd->num; i++) {
- chan = get_free_channel();
- if (!chan) {
- SYS_LOG_ERR("No free channels");
- goto fail;
- }
- /* temporarily mark channel as used to select next one */
+ struct ble_l2cap_chan_info chan_info;
+ int accept_response;
+ struct ble_gap_conn_desc conn;
+
+ switch (event->type) {
+ case BLE_L2CAP_EVENT_COC_CONNECTED:
+ if (ble_l2cap_get_chan_info(event->connect.chan, &chan_info)) {
+ assert(0);
+ }
+
+ 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, "
+ "psm: 0x%02x, scid: 0x%04x, dcid: 0x%04x, "
+ "our_mps: %d, our_mtu: %d, peer_mps: %d, "
+ "peer_mtu: %d\n", event->connect.conn_handle,
+ (uint32_t) event->connect.chan, chan_info.psm,
+ chan_info.scid, chan_info.dcid,
+ chan_info.our_l2cap_mtu, chan_info.our_coc_mtu,
+ chan_info.peer_l2cap_mtu, chan_info.peer_coc_mtu);
+
+ connected_cb(event->connect.conn_handle,
+ event->connect.chan, &chan_info, arg);
+
+ return 0;
+ case BLE_L2CAP_EVENT_COC_DISCONNECTED:
+ if (ble_l2cap_get_chan_info(event->disconnect.chan,
+ &chan_info)) {
+ assert(0);
+ }
+ console_printf("LE CoC disconnected, chan: 0x%08lx\n",
+ (uint32_t) event->disconnect.chan);
+
+ disconnected_cb(event->disconnect.conn_handle,
+ event->disconnect.chan, &chan_info, arg);
+ return 0;
+ case BLE_L2CAP_EVENT_COC_ACCEPT:
+ ble_l2cap_get_chan_info(event->accept.chan, &chan_info);
+ if (chan_info.psm == 0x00F2) {
+ /* TSPX_psm_authentication_required */
+ ble_gap_conn_find(event->accept.conn_handle, &conn);
+ if (!conn.sec_state.authenticated) {
+ return BLE_HS_EAUTHEN;
+ }
+ } else if (chan_info.psm == 0x00F3) {
+ /* TSPX_psm_authorization_required */
+ ble_gap_conn_find(event->accept.conn_handle, &conn);
+ if (!conn.sec_state.encrypted) {
+ return BLE_HS_EAUTHOR;
+ }
+ return BLE_HS_EAUTHOR;
+ } else if (chan_info.psm == 0x00F4) {
+ /* TSPX_psm_encryption_key_size_required */
+ ble_gap_conn_find(event->accept.conn_handle, &conn);
+ if (conn.sec_state.key_size < 16) {
+ return BLE_HS_EENCRYPT_KEY_SZ;
+ }
+ }
+
+ accept_response = POINTER_TO_INT(arg);
+ if (accept_response) {
+ return accept_response;
+ }
+
+ console_printf("LE CoC accept, chan: 0x%08lx, handle: %u, sdu_size: %u\n",
+ (uint32_t) event->accept.chan,
+ event->accept.conn_handle,
+ event->accept.peer_sdu_size);
+
+ return accept_cb(event->accept.conn_handle,
+ event->accept.peer_sdu_size,
+ event->accept.chan);
+
+ case BLE_L2CAP_EVENT_COC_DATA_RECEIVED:
+ console_printf("LE CoC data received, chan: 0x%08lx, handle: %u, sdu_len: %u\n",
+ (uint32_t) event->receive.chan,
+ event->receive.conn_handle,
+ OS_MBUF_PKTLEN(event->receive.sdu_rx));
+
+ recv_cb(event->receive.conn_handle, event->receive.chan,
+ event->receive.sdu_rx, arg);
+ return 0;
+ case BLE_L2CAP_EVENT_COC_TX_UNSTALLED:
+ console_printf("LE CoC tx unstalled, chan: 0x%08lx, handle: %u, status: %d\n",
+ (uint32_t) event->tx_unstalled.chan,
+ event->tx_unstalled.conn_handle,
+ event->tx_unstalled.status);
+
+ unstalled_cb(event->tx_unstalled.conn_handle,
+ event->tx_unstalled.chan,
+ event->tx_unstalled.status, arg);
+ return 0;
+ case BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED:
+ if (ble_l2cap_get_chan_info(event->reconfigured.chan,
+ &chan_info)) {
+ assert(0);
+ }
+ console_printf("LE CoC reconfigure completed status 0x%02x, "
+ "chan: 0x%08lx\n", event->reconfigured.status,
+ (uint32_t) event->reconfigured.chan);
+
+ if (event->reconfigured.status == 0) {
+ console_printf("\t our_mps: %d our_mtu %d\n",
+ chan_info.our_l2cap_mtu, chan_info.our_coc_mtu);
+ }
+
+ reconfigured_ev(event->reconfigured.conn_handle,
+ event->reconfigured.chan,
+ &chan_info,
+ event->reconfigured.status);
+ return 0;
+ case BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED:
+ if (ble_l2cap_get_chan_info(event->reconfigured.chan,
+ &chan_info)) {
+ assert(0);
+ }
+ console_printf("LE CoC peer reconfigured status 0x%02x, "
+ "chan: 0x%08lx\n", event->reconfigured.status,
+ (uint32_t) event->reconfigured.chan);
+
+ if (event->reconfigured.status == 0) {
+ console_printf("\t peer_mps: %d peer_mtu %d\n",
+ chan_info.peer_l2cap_mtu, chan_info.peer_coc_mtu);
+ }
+
+ reconfigured_ev(event->reconfigured.conn_handle,
+ event->reconfigured.chan,
+ &chan_info,
+ event->reconfigured.status);
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+static void
+connect(uint8_t *data, uint16_t len)
+{
+ const struct l2cap_connect_cmd *cmd = (void *) data;
+ uint8_t rp_buf[sizeof(struct l2cap_connect_rp) + cmd->num];
+ struct l2cap_connect_rp *rp = (void *) rp_buf;
+ struct ble_gap_conn_desc desc;
+ struct channel *chan;
+ struct os_mbuf *sdu_rx[cmd->num];
+ ble_addr_t *addr = (void *) data;
+ uint16_t mtu = htole16(cmd->mtu);
+ int rc;
+ int i, j;
+ bool ecfc = cmd->options & L2CAP_CONNECT_OPT_ECFC;
+ hold_credit = cmd->options & L2CAP_CONNECT_OPT_HOLD_CREDIT;
+
+ SYS_LOG_DBG("connect: type: %d addr: %s", addr->type, bt_hex(addr->val, 6));
+
+ if (mtu == 0 || mtu > TESTER_COC_MTU) {
+ mtu = TESTER_COC_MTU;
+ }
+
+ rc = ble_gap_conn_find_by_addr(addr, &desc);
+ if (rc) {
+ SYS_LOG_ERR("GAP conn find failed");
+ goto fail;
+ }
+
+ rp->num = cmd->num;
+
+ for (i = 0; i < cmd->num; i++) {
+ chan = get_free_channel();
+ if (!chan) {
+ SYS_LOG_ERR("No free channels");
+ goto fail;
+ }
+ /* temporarily mark channel as used to select next one */
chan->state = 1;
- rp->chan_ids[i] = chan->chan_id;
-
- sdu_rx[i] = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
- if (sdu_rx[i] == NULL) {
- SYS_LOG_ERR("Failed to alloc buf");
- goto fail;
- }
- }
-
- /* mark selected channels as unused again */
- for (i = 0; i < cmd->num; i++) {
- for (j = 0; j < CHANNELS; j++) {
- if (rp->chan_ids[i] == channels[j].chan_id) {
- channels[j].state = 0;
- }
- }
- }
-
- if (cmd->num == 1 && !ecfc) {
- rc = ble_l2cap_connect(desc.conn_handle, htole16(cmd->psm),
- mtu, sdu_rx[0],
- tester_l2cap_event, NULL);
- } else if (ecfc) {
- rc = ble_l2cap_enhanced_connect(desc.conn_handle,
- htole16(cmd->psm), mtu,
- cmd->num, sdu_rx,
- tester_l2cap_event, NULL);
- } else {
- SYS_LOG_ERR("Invalid 'num' parameter value");
- goto fail;
- }
-
- if (rc) {
- SYS_LOG_ERR("L2CAP connect failed\n");
- goto fail;
- }
-
- tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_CONNECT, CONTROLLER_INDEX,
- (uint8_t *) rp, sizeof(rp_buf));
-
- return;
+ rp->chan_ids[i] = chan->chan_id;
+
+ sdu_rx[i] = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
+ if (sdu_rx[i] == NULL) {
+ SYS_LOG_ERR("Failed to alloc buf");
+ goto fail;
+ }
+ }
+
+ /* mark selected channels as unused again */
+ for (i = 0; i < cmd->num; i++) {
+ for (j = 0; j < CHANNELS; j++) {
+ if (rp->chan_ids[i] == channels[j].chan_id) {
+ channels[j].state = 0;
+ }
+ }
+ }
+
+ if (cmd->num == 1 && !ecfc) {
+ rc = ble_l2cap_connect(desc.conn_handle, htole16(cmd->psm),
+ mtu, sdu_rx[0],
+ tester_l2cap_event, NULL);
+ } else if (ecfc) {
+ rc = ble_l2cap_enhanced_connect(desc.conn_handle,
+ htole16(cmd->psm), mtu,
+ cmd->num, sdu_rx,
+ tester_l2cap_event, NULL);
+ } else {
+ SYS_LOG_ERR("Invalid 'num' parameter value");
+ goto fail;
+ }
+
+ if (rc) {
+ SYS_LOG_ERR("L2CAP connect failed\n");
+ goto fail;
+ }
+
+ tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_CONNECT, CONTROLLER_INDEX,
+ (uint8_t *) rp, sizeof(rp_buf));
+
+ return;
fail:
- tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_CONNECT, CONTROLLER_INDEX,
- BTP_STATUS_FAILED);
-}
-
-static void disconnect(const uint8_t *data, uint16_t len)
-{
- const struct l2cap_disconnect_cmd *cmd = (void *) data;
- struct channel *chan;
- uint8_t status;
- int err;
-
- SYS_LOG_DBG("");
-
- chan = get_channel(cmd->chan_id);
- assert(chan != NULL);
-
- err = ble_l2cap_disconnect(chan->chan);
- if (err) {
- status = BTP_STATUS_FAILED;
- goto rsp;
- }
-
- status = BTP_STATUS_SUCCESS;
+ tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_CONNECT, CONTROLLER_INDEX,
+ BTP_STATUS_FAILED);
+}
+
+static void
+disconnect(const uint8_t *data, uint16_t len)
+{
+ const struct l2cap_disconnect_cmd *cmd = (void *) data;
+ struct channel *chan;
+ uint8_t status;
+ int err;
+
+ SYS_LOG_DBG("");
+
+ chan = get_channel(cmd->chan_id);
+ assert(chan != NULL);
+
+ err = ble_l2cap_disconnect(chan->chan);
+ if (err) {
+ status = BTP_STATUS_FAILED;
+ goto rsp;
+ }
+
+ status = BTP_STATUS_SUCCESS;
rsp:
- tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_DISCONNECT, CONTROLLER_INDEX,
- status);
-}
-
-static void send_data(const uint8_t *data, uint16_t len)
-{
- const struct l2cap_send_data_cmd *cmd = (void *) data;
- struct os_mbuf *sdu_tx = NULL;
- int rc;
- uint16_t data_len = sys_le16_to_cpu(cmd->data_len);
- struct channel *chan = get_channel(cmd->chan_id);
-
- SYS_LOG_DBG("cmd->chan_id=%d", cmd->chan_id);
-
- if (!chan) {
- SYS_LOG_ERR("Invalid channel\n");
- goto fail;
- }
-
- /* FIXME: For now, fail if data length exceeds buffer length */
- if (data_len > TESTER_COC_MTU) {
- SYS_LOG_ERR("Data length exceeds buffer length");
- goto fail;
- }
-
- sdu_tx = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
- if (sdu_tx == NULL) {
- SYS_LOG_ERR("No memory in the test sdu pool\n");
- goto fail;
- }
-
- os_mbuf_append(sdu_tx, cmd->data, data_len);
-
- /* ble_l2cap_send takes ownership of the sdu */
- rc = ble_l2cap_send(chan->chan, sdu_tx);
- if (rc == 0 || rc == BLE_HS_ESTALLED) {
- tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_SEND_DATA, CONTROLLER_INDEX,
- BTP_STATUS_SUCCESS);
- return;
- }
-
- SYS_LOG_ERR("Unable to send data: %d", rc);
- os_mbuf_free_chain(sdu_tx);
+ tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_DISCONNECT, CONTROLLER_INDEX,
+ status);
+}
+
+static void
+send_data(const uint8_t *data, uint16_t len)
+{
+ const struct l2cap_send_data_cmd *cmd = (void *) data;
+ struct os_mbuf *sdu_tx = NULL;
+ int rc;
+ uint16_t data_len = sys_le16_to_cpu(cmd->data_len);
+ struct channel *chan = get_channel(cmd->chan_id);
+
+ SYS_LOG_DBG("cmd->chan_id=%d", cmd->chan_id);
+
+ if (!chan) {
+ SYS_LOG_ERR("Invalid channel\n");
+ goto fail;
+ }
+
+ /* FIXME: For now, fail if data length exceeds buffer length */
+ if (data_len > TESTER_COC_MTU) {
+ SYS_LOG_ERR("Data length exceeds buffer length");
+ goto fail;
+ }
+
+ sdu_tx = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
+ if (sdu_tx == NULL) {
+ SYS_LOG_ERR("No memory in the test sdu pool\n");
+ goto fail;
+ }
+
+ os_mbuf_append(sdu_tx, cmd->data, data_len);
+
+ /* ble_l2cap_send takes ownership of the sdu */
+ rc = ble_l2cap_send(chan->chan, sdu_tx);
+ if (rc == 0 || rc == BLE_HS_ESTALLED) {
+ tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_SEND_DATA, CONTROLLER_INDEX,
+ BTP_STATUS_SUCCESS);
+ return;
+ }
+
+ SYS_LOG_ERR("Unable to send data: %d", rc);
+ os_mbuf_free_chain(sdu_tx);
fail:
- tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_SEND_DATA, CONTROLLER_INDEX,
- BTP_STATUS_FAILED);
+ tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_SEND_DATA, CONTROLLER_INDEX,
+ BTP_STATUS_FAILED);
}
static int
l2cap_coc_err2hs_err(uint16_t coc_err)
{
- switch (coc_err) {
- case BLE_L2CAP_COC_ERR_UNKNOWN_LE_PSM:
- return BLE_HS_ENOTSUP;
- case BLE_L2CAP_COC_ERR_NO_RESOURCES:
- return BLE_HS_ENOMEM;
- case BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHEN:
- return BLE_HS_EAUTHEN;
- case BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHOR:
- return BLE_HS_EAUTHOR;
- case BLE_L2CAP_COC_ERR_INSUFFICIENT_ENC:
- return BLE_HS_EENCRYPT;
- case BLE_L2CAP_COC_ERR_INSUFFICIENT_KEY_SZ:
- return BLE_HS_EENCRYPT_KEY_SZ;
- case BLE_L2CAP_COC_ERR_UNACCEPTABLE_PARAMETERS:
- return BLE_HS_EINVAL;
- default:
- return 0;
- }
+ switch (coc_err) {
+ case BLE_L2CAP_COC_ERR_UNKNOWN_LE_PSM:
+ return BLE_HS_ENOTSUP;
+ case BLE_L2CAP_COC_ERR_NO_RESOURCES:
+ return BLE_HS_ENOMEM;
+ case BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHEN:
+ return BLE_HS_EAUTHEN;
+ case BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHOR:
+ return BLE_HS_EAUTHOR;
+ case BLE_L2CAP_COC_ERR_INSUFFICIENT_ENC:
+ return BLE_HS_EENCRYPT;
+ case BLE_L2CAP_COC_ERR_INSUFFICIENT_KEY_SZ:
+ return BLE_HS_EENCRYPT_KEY_SZ;
+ case BLE_L2CAP_COC_ERR_UNACCEPTABLE_PARAMETERS:
+ return BLE_HS_EINVAL;
+ default:
+ return 0;
+ }
}
static int
l2cap_btp_listen_err2coc_err(uint16_t coc_err)
{
switch (coc_err) {
- case 0x01:
- return BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHEN;
- case 0x02:
- return BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHOR;
- case 0x03:
- return BLE_L2CAP_COC_ERR_INSUFFICIENT_KEY_SZ;
- case 0x04:
- return BLE_L2CAP_COC_ERR_INSUFFICIENT_ENC;
- default:
- return 0;
- }
-}
-
-static void listen(const uint8_t *data, uint16_t len)
-{
- const struct l2cap_listen_cmd *cmd = (void *) data;
- uint16_t mtu = htole16(cmd->mtu);
- uint16_t rsp = htole16(cmd->response);
- int rc;
-
- SYS_LOG_DBG("");
-
- if (mtu == 0 || mtu > TESTER_COC_MTU) {
- mtu = TESTER_COC_MTU;
- }
-
- rsp = l2cap_btp_listen_err2coc_err(rsp);
- rsp = l2cap_coc_err2hs_err(rsp);
-
- /* TODO: Handle cmd->transport flag */
- rc = ble_l2cap_create_server(cmd->psm, mtu, tester_l2cap_event,
- INT_TO_POINTER(rsp));
- if (rc) {
- goto fail;
- }
-
- tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_LISTEN, CONTROLLER_INDEX,
- BTP_STATUS_SUCCESS);
- return;
+ case 0x01:
+ return BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHEN;
+ case 0x02:
+ return BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHOR;
+ case 0x03:
+ return BLE_L2CAP_COC_ERR_INSUFFICIENT_KEY_SZ;
+ case 0x04:
+ return BLE_L2CAP_COC_ERR_INSUFFICIENT_ENC;
+ default:
+ return 0;
+ }
+}
+
+static void
+listen(const uint8_t *data, uint16_t len)
+{
+ const struct l2cap_listen_cmd *cmd = (void *) data;
+ uint16_t mtu = htole16(cmd->mtu);
+ uint16_t rsp = htole16(cmd->response);
+ int rc;
+
+ SYS_LOG_DBG("");
+
+ if (mtu == 0 || mtu > TESTER_COC_MTU) {
+ mtu = TESTER_COC_MTU;
+ }
+
+ rsp = l2cap_btp_listen_err2coc_err(rsp);
+ rsp = l2cap_coc_err2hs_err(rsp);
+
+ /* TODO: Handle cmd->transport flag */
+ rc = ble_l2cap_create_server(cmd->psm, mtu, tester_l2cap_event,
+ INT_TO_POINTER(rsp));
+ if (rc) {
+ goto fail;
+ }
+
+ tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_LISTEN, CONTROLLER_INDEX,
+ BTP_STATUS_SUCCESS);
+ return;
fail:
- tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_LISTEN, CONTROLLER_INDEX,
- BTP_STATUS_FAILED);
-}
-
-static void credits(uint8_t *data, uint16_t len)
+ tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_LISTEN, CONTROLLER_INDEX,
+ BTP_STATUS_FAILED);
+}
+
+static void
+credits(uint8_t *data, uint16_t len)
{
const struct l2cap_credits_cmd *cmd = (void *)data;
struct os_mbuf *sdu;
@@ -645,121 +659,126 @@
BTP_STATUS_FAILED);
}
-static void reconfigure(const uint8_t *data, uint16_t len)
-{
- const struct l2cap_reconfigure_cmd *cmd = (void *) data;
- uint16_t mtu = htole16(cmd->mtu);
- struct ble_gap_conn_desc desc;
- ble_addr_t *addr = (void *) data;
- struct ble_l2cap_chan *chans[cmd->num];
- struct channel *channel;
- int rc;
- int i;
-
- SYS_LOG_DBG("");
-
- if (mtu == 0 || mtu > TESTER_COC_MTU) {
- mtu = TESTER_COC_MTU;
- }
-
- rc = ble_gap_conn_find_by_addr(addr, &desc);
- if (rc) {
- SYS_LOG_ERR("GAP conn find failed");
- goto fail;
- }
-
- for (i = 0; i < cmd->num; ++i) {
- channel = get_channel(cmd->idxs[i]);
- if (channel == NULL) {
- goto fail;
- }
- chans[i] = channel->chan;
- }
-
- rc = ble_l2cap_reconfig(chans, cmd->num, mtu);
- if (rc) {
- goto fail;
- }
-
- tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_RECONFIGURE, CONTROLLER_INDEX,
- BTP_STATUS_SUCCESS);
- return;
+static void
+reconfigure(const uint8_t *data, uint16_t len)
+{
+ const struct l2cap_reconfigure_cmd *cmd = (void *) data;
+ uint16_t mtu = htole16(cmd->mtu);
+ struct ble_gap_conn_desc desc;
+ ble_addr_t *addr = (void *) data;
+ struct ble_l2cap_chan *chans[cmd->num];
+ struct channel *channel;
+ int rc;
+ int i;
+
+ SYS_LOG_DBG("");
+
+ if (mtu == 0 || mtu > TESTER_COC_MTU) {
+ mtu = TESTER_COC_MTU;
+ }
+
+ rc = ble_gap_conn_find_by_addr(addr, &desc);
+ if (rc) {
+ SYS_LOG_ERR("GAP conn find failed");
+ goto fail;
+ }
+
+ for (i = 0; i < cmd->num; ++i) {
+ channel = get_channel(cmd->idxs[i]);
+ if (channel == NULL) {
+ goto fail;
+ }
+ chans[i] = channel->chan;
+ }
+
+ rc = ble_l2cap_reconfig(chans, cmd->num, mtu);
+ if (rc) {
+ goto fail;
+ }
+
+ tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_RECONFIGURE, CONTROLLER_INDEX,
+ BTP_STATUS_SUCCESS);
+ return;
fail:
- tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_RECONFIGURE, CONTROLLER_INDEX,
- BTP_STATUS_FAILED);
-}
-
-static void supported_commands(uint8_t *data, uint16_t len)
-{
- uint8_t cmds[1];
- struct l2cap_read_supported_commands_rp *rp = (void *) cmds;
-
- memset(cmds, 0, sizeof(cmds));
-
- tester_set_bit(cmds, L2CAP_READ_SUPPORTED_COMMANDS);
- tester_set_bit(cmds, L2CAP_CONNECT);
- tester_set_bit(cmds, L2CAP_DISCONNECT);
- tester_set_bit(cmds, L2CAP_LISTEN);
- tester_set_bit(cmds, L2CAP_SEND_DATA);
- tester_set_bit(cmds, L2CAP_RECONFIGURE);
-
- tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_READ_SUPPORTED_COMMANDS,
- CONTROLLER_INDEX, (uint8_t *) rp, sizeof(cmds));
-}
-
-void tester_handle_l2cap(uint8_t opcode, uint8_t index, uint8_t *data,
- uint16_t len)
-{
- switch (opcode) {
- case L2CAP_READ_SUPPORTED_COMMANDS:
- supported_commands(data, len);
- return;
- case L2CAP_CONNECT:
- connect(data, len);
- return;
- case L2CAP_DISCONNECT:
- disconnect(data, len);
- return;
- case L2CAP_SEND_DATA:
- send_data(data, len);
- return;
- case L2CAP_LISTEN:
- listen(data, len);
- return;
- case L2CAP_RECONFIGURE:
- reconfigure(data, len);
- return;
- case L2CAP_CREDITS:
- credits(data, len);
- return;
- default:
- tester_rsp(BTP_SERVICE_ID_L2CAP, opcode, index,
- BTP_STATUS_UNKNOWN_CMD);
- return;
- }
-}
-
-uint8_t tester_init_l2cap(void)
-{
- int rc;
-
- /* For testing we want to support all the available channels */
- rc = os_mempool_init(&sdu_coc_mbuf_mempool, TESTER_COC_BUF_COUNT,
- TESTER_COC_MTU, tester_sdu_coc_mem,
- "tester_coc_sdu_pool");
- assert(rc == 0);
-
- rc = os_mbuf_pool_init(&sdu_os_mbuf_pool, &sdu_coc_mbuf_mempool,
- TESTER_COC_MTU, TESTER_COC_BUF_COUNT);
- assert(rc == 0);
-
- return BTP_STATUS_SUCCESS;
-}
-
-uint8_t tester_unregister_l2cap(void)
-{
- return BTP_STATUS_SUCCESS;
+ tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_RECONFIGURE, CONTROLLER_INDEX,
+ BTP_STATUS_FAILED);
+}
+
+static void
+supported_commands(uint8_t *data, uint16_t len)
+{
+ uint8_t cmds[1];
+ struct l2cap_read_supported_commands_rp *rp = (void *) cmds;
+
+ memset(cmds, 0, sizeof(cmds));
+
+ tester_set_bit(cmds, L2CAP_READ_SUPPORTED_COMMANDS);
+ tester_set_bit(cmds, L2CAP_CONNECT);
+ tester_set_bit(cmds, L2CAP_DISCONNECT);
+ tester_set_bit(cmds, L2CAP_LISTEN);
+ tester_set_bit(cmds, L2CAP_SEND_DATA);
+ tester_set_bit(cmds, L2CAP_RECONFIGURE);
+
+ tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_READ_SUPPORTED_COMMANDS,
+ CONTROLLER_INDEX, (uint8_t *) rp, sizeof(cmds));
+}
+
+void
+tester_handle_l2cap(uint8_t opcode, uint8_t index, uint8_t *data,
+ uint16_t len)
+{
+ switch (opcode) {
+ case L2CAP_READ_SUPPORTED_COMMANDS:
+ supported_commands(data, len);
+ return;
+ case L2CAP_CONNECT:
+ connect(data, len);
+ return;
+ case L2CAP_DISCONNECT:
+ disconnect(data, len);
+ return;
+ case L2CAP_SEND_DATA:
+ send_data(data, len);
+ return;
+ case L2CAP_LISTEN:
+ listen(data, len);
+ return;
+ case L2CAP_RECONFIGURE:
+ reconfigure(data, len);
+ return;
+ case L2CAP_CREDITS:
+ credits(data, len);
+ return;
+ default:
+ tester_rsp(BTP_SERVICE_ID_L2CAP, opcode, index,
+ BTP_STATUS_UNKNOWN_CMD);
+ return;
+ }
+}
+
+uint8_t
+tester_init_l2cap(void)
+{
+ int rc;
+
+ /* For testing we want to support all the available channels */
+ rc = os_mempool_init(&sdu_coc_mbuf_mempool, TESTER_COC_BUF_COUNT,
+ TESTER_COC_MTU, tester_sdu_coc_mem,
+ "tester_coc_sdu_pool");
+ assert(rc == 0);
+
+ rc = os_mbuf_pool_init(&sdu_os_mbuf_pool, &sdu_coc_mbuf_mempool,
+ TESTER_COC_MTU, TESTER_COC_BUF_COUNT);
+ assert(rc == 0);
+
+ return BTP_STATUS_SUCCESS;
+}
+
+uint8_t
+tester_unregister_l2cap(void)
+{
+ return BTP_STATUS_SUCCESS;
}
#endif
```
</details>
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@mynewt.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org