lib: Add definitions for Enhanced Credits Based Mode
Subsystems (2)
Luiz Augusto von Dentz
maintainerPATCH v3 1/6 lib: Add definitions for Enhanced Credits Based Mode
From: Luiz Augusto von Dentz <[email protected]>
--- lib/bluetooth.h | 9 +++++++++ 1 file changed, 9 insertions(+)
lib/bluetooth.h +9 -0
@@ -141,6 +141,15 @@ struct bt_voice {#define BT_PHY_LE_CODED_TX 0x00002000#define BT_PHY_LE_CODED_RX 0x00004000 +#define BT_MODE 15 + +#define BT_MODE_BASIC 0x00 +#define BT_MODE_RETRANS 0x01 +#define BT_MODE_FLOWCTL 0x02 +#define BT_MODE_ERTM 0x03 +#define BT_MODE_STREAMING 0x04 +#define BT_MODE_EXT_FLOWCTL 0x05 +/* Connection and socket states */ enum {BT_CONNECTED =1 ,/* Equal to TCP_ESTABLISHED to make net code happy */
Signature · 1 line
2.21.1
Luiz Augusto von Dentz
maintainerPATCH v3 2/6 btio: Add mode to for Enhanced Credit Mode
From: Luiz Augusto von Dentz <[email protected]>
This adds BT_IO_MODE_EXT_FLOWCTL which directly maps to BT_MODE_EXT_FLOWCTL.
--- btio/btio.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++------ btio/btio.h | 3 ++- 2 files changed, 55 insertions(+), 7 deletions(-)
btio/btio.c +53 -6
@@ -630,18 +630,34 @@ static gboolean set_le_imtu(int sock, uint16_t imtu, GError **err)return TRUE; } +static gboolean set_le_mode (int sock,uint8_t mode,GError **err) +{ +if (setsockopt (sock,SOL_BLUETOOTH ,BT_MODE , &mode, +sizeof (mode)) <0 ) { +ERROR_FAILED (err,"setsockopt(BT_MODE)" , errno); +return FALSE; + } + +return TRUE; +} +static gboolean l2cap_set (int sock,uint8_t src_type,int sec_level,uint16_t imtu,uint16_t omtu,uint8_t mode,int master,int flushable,uint32_t priority,GError **err) {if (imtu || omtu || mode) { -gboolean ret; +gboolean ret = FALSE;if (src_type ==BDADDR_BREDR ) ret =set_l2opts (sock, imtu, omtu, mode, err); -else - ret =set_le_imtu (sock, imtu, err); +else { +if (imtu) + ret =set_le_imtu (sock, imtu, err); + +if (ret && mode) + ret =set_le_mode (sock, mode, err); + }if (!ret)return ret;
@@ -980,6 +996,30 @@ static int get_phy(int sock, uint32_t *phy)return 0 ; } +static int get_le_imtu (int sock,uint16_t *mtu) +{ +socklen_t len; + + len =sizeof (*mtu); + +if (getsockopt (sock,SOL_BLUETOOTH ,BT_RCVMTU , mtu, &len) <0 ) +return -errno; + +return 0 ; +} + +static int get_le_mode (int sock,uint8_t *mode) +{ +socklen_t len; + + len =sizeof (*mode); + +if (getsockopt (sock,SOL_BLUETOOTH ,BT_MODE , mode, &len) <0 ) +return -errno; + +return 0 ; +} +static gboolean l2cap_get (int sock,GError **err,BtIOOption opt1,va_list args) {
@@ -999,10 +1039,11 @@ static gboolean l2cap_get(int sock, GError **err, BtIOOption opt1,memset (&l2o,0 ,sizeof (l2o));if (src.l2_bdaddr_type !=BDADDR_BREDR ) { - len =sizeof (l2o.imtu); -if (getsockopt (sock,SOL_BLUETOOTH ,BT_RCVMTU , - &l2o.imtu, &len) ==0 ) +if (get_le_imtu (sock, &l2o.imtu) ==0 ) { +/* Older kernels may not support BT_MODE */ +get_le_mode (sock, &l2o.mode); goto parse_opts; + }/* Non-LE CoC enabled kernels will return one of these * in which case we need to fall back to L2CAP_OPTIONS.
@@ -1644,6 +1685,12 @@ GIOChannel *bt_io_connect(BtIOConnect connect, gpointer user_data, sock =g_io_channel_unix_get_fd (io); +/* Use DEFER_SETUP when connecting using Ext-Flowctl */ +if (opts.mode ==BT_IO_MODE_EXT_FLOWCTL && opts.defer) { +setsockopt (sock,SOL_BLUETOOTH ,BT_DEFER_SETUP , &opts.defer, +sizeof (opts.defer)); + } +switch (opts.type) {case BT_IO_L2CAP : err = l2cap_connect(sock, &opts.dst, opts.dst_type,
btio/btio.h +2 -1
@@ -71,7 +71,8 @@ typedef enum {BT_IO_MODE_RETRANS ,BT_IO_MODE_FLOWCTL ,BT_IO_MODE_ERTM , - BT_IO_MODE_STREAMING +BT_IO_MODE_STREAMING , + BT_IO_MODE_EXT_FLOWCTL } BtIOMode;typedef void (*BtIOConfirm )(GIOChannel *io,gpointer user_data);
Signature · 1 line
2.21.1
Luiz Augusto von Dentz
maintainerPATCH v3 3/6 l2test: Add support for BT_MODE_EXT_FLOWCTL
In reply to Luiz Augusto von DentzFrom: Luiz Augusto von Dentz <[email protected]>
This enables using l2test to connect or listen with BT_MODE_EXT_FLOWCTL.
--- tools/l2test.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
tools/l2test.c +14 -6
@@ -143,13 +143,14 @@ struct lookup_table { };static struct lookup_table l2cap_modes[] = { - {"basic" ,L2CAP_MODE_BASIC }, + {"basic" ,BT_MODE_BASIC },/* Not implemented -{ "flowctl", L2CAP_MODE_FLOWCTL }, -{ "retrans", L2CAP_MODE_RETRANS }, +{ "flowctl", BT_MODE_FLOWCTL }, +{ "retrans", BT_MODE_RETRANS }, */ - {"ertm" ,L2CAP_MODE_ERTM }, - {"streaming" ,L2CAP_MODE_STREAMING }, + {"ertm" ,BT_MODE_ERTM }, + {"streaming" ,BT_MODE_STREAMING }, + {"ext-flowctl" ,BT_MODE_EXT_FLOWCTL }, {0 } };
@@ -283,7 +284,7 @@ static int getopts(int sk, struct l2cap_options *opts, bool connected)memset (opts,0 ,sizeof (*opts)); -if (bdaddr_type ==BDADDR_BREDR ) { +if (bdaddr_type ==BDADDR_BREDR || rfcmode) { optlen =sizeof (*opts);return getsockopt (sk,SOL_L2CAP ,L2CAP_OPTIONS , opts, &optlen); }
@@ -303,6 +304,13 @@ static int setopts(int sk, struct l2cap_options *opts)return setsockopt (sk,SOL_L2CAP ,L2CAP_OPTIONS , opts,sizeof (*opts)); +if (opts->mode) { +if (setsockopt (sk,SOL_BLUETOOTH ,BT_MODE , &opts->mode, +sizeof (opts->mode)) <0 ) { +return -errno; + } + } +return setsockopt (sk,SOL_BLUETOOTH ,BT_RCVMTU , &opts->imtu,sizeof (opts->imtu)); }
Signature · 1 line
2.21.1
Luiz Augusto von Dentz
maintainerPATCH v3 4/6 emulator/bthost: Add support for ECRED Connection request/response
In reply to Luiz Augusto von DentzFrom: Luiz Augusto von Dentz <[email protected]>
This adds support for ECRED Connection request/response which will be used by l2cap-runner to test L2CAP_MODE_EXT_FLOWCTL mode.
--- emulator/bthost.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+)
emulator/bthost.c +72 -0
@@ -1773,6 +1773,69 @@ static bool l2cap_le_conn_rsp(struct bthost *bthost, struct btconn *conn,return true; } +static bool l2cap_ecred_conn_req (struct bthost *bthost,struct btconn *conn, +uint8_t ident,const void *data,uint16_t len) +{ +const struct bt_l2cap_pdu_ecred_conn_req *req = data; +struct { +struct bt_l2cap_pdu_ecred_conn_rsp pdu; +uint16_t dcid[5 ]; + } __attribute__ ((packed)) rsp; +uint16_t psm; +int num_scid, i =0 ; + +if (len <sizeof (*req)) +return false; + + psm =le16_to_cpu (req->psm); + +memset (&rsp,0 ,sizeof (rsp)); + + rsp.pdu.mtu =64 ; + rsp.pdu.mps =64 ; + rsp.pdu.credits =1 ; + +if (!bthost_find_l2cap_cb_by_psm (bthost, psm)) { + rsp.pdu.result =cpu_to_le16 (0x0002 );/* PSM Not Supported */ + goto respond; + } + + len -=sizeof (rsp.pdu); + num_scid = len /sizeof (*req->scid); + +for (; i < num_scid; i++) + rsp.dcid[i] =cpu_to_le16 (conn->next_cid++); + +respond: +l2cap_sig_send (bthost, conn,BT_L2CAP_PDU_ECRED_CONN_RSP , ident, &rsp, +sizeof (rsp.pdu) + i *sizeof (*rsp.dcid)); + +return true; +} + +static bool l2cap_ecred_conn_rsp (struct bthost *bthost,struct btconn *conn, +uint8_t ident,const void *data,uint16_t len) +{ +const struct { +const struct bt_l2cap_pdu_ecred_conn_rsp *pdu; +uint16_t scid[5 ]; + } __attribute__ ((packed)) *rsp = data; +int num_scid, i; + +if (len <sizeof (*rsp)) +return false; + + num_scid = len /sizeof (*rsp->scid); + +for (i =0 ; i < num_scid; i++) +/* TODO add L2CAP connection before with proper PSM */ +bthost_add_l2cap_conn (bthost, conn,0 , +le16_to_cpu (rsp->scid[i]),0 ); + + +return true; +} +static void l2cap_le_sig (struct bthost *bthost,struct btconn *conn,const void *data,uint16_t len) {
@@ -1819,6 +1882,15 @@ static void l2cap_le_sig(struct bthost *bthost, struct btconn *conn, ret =l2cap_le_conn_rsp (bthost, conn, hdr->ident, data +sizeof (*hdr), hdr_len);break ; +case BT_L2CAP_PDU_ECRED_CONN_REQ : + ret =l2cap_ecred_conn_req (bthost, conn, hdr->ident, + data +sizeof (*hdr), hdr_len); +break ; + +case BT_L2CAP_PDU_ECRED_CONN_RSP : + ret =l2cap_ecred_conn_rsp (bthost, conn, hdr->ident, + data +sizeof (*hdr), hdr_len); +break ;default :printf ("Unknown L2CAP code 0x%02x\n" , hdr->code);
Signature · 1 line
2.21.1
Luiz Augusto von Dentz
maintainerPATCH v3 5/6 tools/l2cap-tester: Add test for Ext-Flowctl mode
In reply to Luiz Augusto von DentzFrom: Luiz Augusto von Dentz <[email protected]>
This adds tests for Ext-Flowctl which uses ECRED PDUs.
--- tools/l2cap-tester.c | 174 +++++++++++++++++++++++++++++++++---------- 1 file changed, 136 insertions(+), 38 deletions(-)
tools/l2cap-tester.c +136 -38
@@ -61,6 +61,7 @@ struct l2cap_data {uint16_t client_psm;uint16_t server_psm;uint16_t cid; +uint8_t mode;int expect_err;uint8_t send_cmd_code;
@@ -91,7 +92,7 @@ struct l2cap_data {uint8_t *client_bdaddr;bool server_not_advertising;bool direct_advertising; -bool close_one_socket; +bool close_1; };static void mgmt_debug (const char *str,void *user_data)
@@ -474,17 +475,17 @@ static const struct l2cap_data le_client_close_socket_test_2 = { .server_not_advertising = true, }; -static const struct l2cap_data le_client_two_sockets_same_client = { +static const struct l2cap_data le_client_2_same_client = { .client_psm =0x0080 , .server_psm =0x0080 , .server_not_advertising = true, }; -static const struct l2cap_data le_client_two_sockets_close_one = { +static const struct l2cap_data le_client_2_close_1 = { .client_psm =0x0080 , .server_psm =0x0080 , .server_not_advertising = true, - .close_one_socket = true, + .close_1 = true, };static const struct l2cap_data le_client_connect_nval_psm_test = {
@@ -549,6 +550,49 @@ static const struct l2cap_data le_att_server_success_test_1 = { .cid = 0x0004, }; +static const struct l2cap_data ext_flowctl_client_connect_success_test_1 = { + .client_psm =0x0080 , + .server_psm =0x0080 , + .mode =BT_MODE_EXT_FLOWCTL , +}; + +static const struct l2cap_data ext_flowctl_client_connect_adv_success_test_1 = { + .client_psm =0x0080 , + .server_psm =0x0080 , + .mode =BT_MODE_EXT_FLOWCTL , + .direct_advertising = true, +}; + +static const struct l2cap_data ext_flowctl_client_connect_success_test_2 = { + .client_psm =0x0080 , + .server_psm =0x0080 , + .mode =BT_MODE_EXT_FLOWCTL , + .sec_level =BT_SECURITY_MEDIUM , +}; + +static const struct l2cap_data ext_flowctl_client_connect_reject_test_1 = { + .client_psm =0x0080 , + .mode =BT_MODE_EXT_FLOWCTL , + .send_cmd = cmd_reject_rsp, + .send_cmd_len =sizeof (cmd_reject_rsp), + .expect_err =ECONNREFUSED , +}; + +static const struct l2cap_data ext_flowctl_client_2 = { + .client_psm =0x0080 , + .server_psm =0x0080 , + .mode =BT_MODE_EXT_FLOWCTL , + .server_not_advertising = true, +}; + +static const struct l2cap_data ext_flowctl_client_2_close_1 = { + .client_psm =0x0080 , + .server_psm =0x0080 , + .mode =BT_MODE_EXT_FLOWCTL , + .server_not_advertising = true, + .close_1 = true, +}; +static void client_cmd_complete (uint16_t opcode,uint8_t status,const void *param,uint8_t len,void *user_data)
@@ -1031,7 +1075,7 @@ failed: }static int create_l2cap_sock (struct test_data *data,uint16_t psm, -uint16_t cid,int sec_level) +uint16_t cid,int sec_level,uint8_t mode) {const struct l2cap_data *l2data = data->test_data;const uint8_t *master_bdaddr;
@@ -1091,6 +1135,17 @@ static int create_l2cap_sock(struct test_data *data, uint16_t psm, } } +if (mode) { +if (setsockopt (sk,SOL_BLUETOOTH ,BT_MODE , &mode, +sizeof (mode)) <0 ) { + err = -errno; +tester_warn ("Can't set mode: %s (%d)" ,strerror (errno), + errno); +close (sk); +return err; + } + } +return sk; }
@@ -1212,7 +1267,8 @@ static void test_connect(const void *test_data)hciemu_add_master_post_command_hook (data->hciemu, direct_adv_cmd_complete,NULL ); - sk =create_l2cap_sock (data,0 , l2data->cid, l2data->sec_level); + sk =create_l2cap_sock (data,0 , l2data->cid, l2data->sec_level, + l2data->mode);if (sk <0 ) {tester_test_failed ();return ;
@@ -1241,7 +1297,8 @@ static void test_connect_reject(const void *test_data)const struct l2cap_data *l2data = data->test_data;int sk; - sk =create_l2cap_sock (data,0 , l2data->cid, l2data->sec_level); + sk =create_l2cap_sock (data,0 , l2data->cid, l2data->sec_level, + l2data->mode);if (sk <0 ) {tester_test_failed ();return ;
@@ -1256,29 +1313,40 @@ static void test_connect_reject(const void *test_data)close (sk); } -static void connect_socket (const uint8_t *client_bdaddr,int *sk_holder, -GIOFunc connect_cb) +static int connect_socket (const uint8_t *client_bdaddr,GIOFunc connect_cb, +bool defer) {struct test_data *data =tester_get_data ();const struct l2cap_data *l2data = data->test_data;GIOChannel *io;int sk; - sk =create_l2cap_sock (data,0 , l2data->cid, l2data->sec_level); + sk =create_l2cap_sock (data,0 , l2data->cid, l2data->sec_level, + l2data->mode);if (sk <0 ) {tester_print ("Error in create_l2cap_sock" );tester_test_failed (); -return ; +return -1 ; } - *sk_holder = sk; +if (defer) { +int opt =1 ; + +if (setsockopt (sk,SOL_BLUETOOTH ,BT_DEFER_SETUP , &opt, +sizeof (opt)) <0 ) { +tester_print ("Can't enable deferred setup: %s (%d)" , +strerror (errno), errno); +tester_test_failed (); +return -1 ; + } + }if (connect_l2cap_impl (sk, client_bdaddr,BDADDR_LE_PUBLIC , l2data->client_psm, l2data->cid) <0 ) {tester_print ("Error in connect_l2cap_sock" );close (sk);tester_test_failed (); -return ; +return -1 ; }if (connect_cb) {
@@ -1290,7 +1358,10 @@ static void connect_socket(const uint8_t *client_bdaddr, int *sk_holder,g_io_channel_unref (io); } -tester_print ("Connect in progress, sk = %d" , sk); +tester_print ("Connect in progress, sk = %d %s" , sk, + defer ?"(deferred)" :"" ); + +return -1 ; }static gboolean test_close_socket_1_part_3 (gpointer arg)
@@ -1457,11 +1528,11 @@ static void test_close_socket(const void *test_data)else client_bdaddr =hciemu_get_client_bdaddr (data->hciemu); -connect_socket (client_bdaddr, &data->sk,NULL ); + data->sk =connect_socket (client_bdaddr,NULL , false); } -static uint8_t test_two_sockets_connect_cb_cnt; -static gboolean test_two_sockets_connect_cb (GIOChannel *io,GIOCondition cond, +static uint8_t test_2_connect_cb_cnt; +static gboolean test_2_connect_cb (GIOChannel *io,GIOCondition cond,gpointer user_data) {struct test_data *data =tester_get_data ();
@@ -1485,15 +1556,15 @@ static gboolean test_two_sockets_connect_cb(GIOChannel *io, GIOCondition cond, }tester_print ("Successfully connected" ); - test_two_sockets_connect_cb_cnt++; + test_2_connect_cb_cnt++; -if (test_two_sockets_connect_cb_cnt ==2 ) { +if (test_2_connect_cb_cnt ==2 ) {close (data->sk);close (data->sk2);tester_test_passed (); } -if (l2data->close_one_socket && test_two_sockets_connect_cb_cnt ==1 ) { +if (l2data->close_1 && test_2_connect_cb_cnt ==1 ) {close (data->sk2);tester_test_passed (); }
@@ -1510,16 +1581,16 @@ static gboolean enable_advertising(gpointer args)return FALSE; } -static void test_connect_two_sockets_part_2 (void ) +static void test_connect_2_part_2 (void ) {struct test_data *data =tester_get_data ();const struct l2cap_data *l2data = data->test_data;const uint8_t *client_bdaddr; client_bdaddr =hciemu_get_client_bdaddr (data->hciemu); -connect_socket (client_bdaddr, &data->sk2, test_two_sockets_connect_cb); + data->sk2 =connect_socket (client_bdaddr, test_2_connect_cb, false); -if (l2data->close_one_socket) { +if (l2data->close_1) {tester_print ("Closing first socket! %d" , data->sk);close (data->sk); }
@@ -1528,7 +1599,7 @@ static void test_connect_two_sockets_part_2(void) }static uint8_t test_scan_enable_counter; -static void test_connect_two_sockets_router (uint16_t opcode,const void *param, +static void test_connect_2_router (uint16_t opcode,const void *param,uint8_t length,void *user_data) {const struct bt_hci_cmd_le_set_scan_enable *scan_params = param;
@@ -1538,23 +1609,24 @@ static void test_connect_two_sockets_router(uint16_t opcode, const void *param, scan_params->enable == true) { test_scan_enable_counter++;if (test_scan_enable_counter ==1 ) -test_connect_two_sockets_part_2 (); +test_connect_2_part_2 ();else if (test_scan_enable_counter ==2 )g_idle_add (enable_advertising,NULL ); } } -static void test_connect_two_sockets (const void *test_data) +static void test_connect_2 (const void *test_data) {struct test_data *data =tester_get_data ();const struct l2cap_data *l2data = data->test_data;const uint8_t *client_bdaddr; +bool defer; - test_two_sockets_connect_cb_cnt =0 ; + test_2_connect_cb_cnt =0 ; test_scan_enable_counter =0 ;hciemu_add_master_post_command_hook (data->hciemu, - test_connect_two_sockets_router, data); + test_connect_2_router, data);if (l2data->server_psm) {struct bthost *bthost =hciemu_client_get_host (data->hciemu);
@@ -1564,12 +1636,14 @@ static void test_connect_two_sockets(const void *test_data) NULL, NULL); } + defer = (l2data->mode ==BT_MODE_EXT_FLOWCTL ); + client_bdaddr =hciemu_get_client_bdaddr (data->hciemu); -if (l2data->close_one_socket) -connect_socket (client_bdaddr, &data->sk,NULL ); +if (l2data->close_1) + data->sk =connect_socket (client_bdaddr,NULL , defer);else -connect_socket (client_bdaddr, &data->sk, - test_two_sockets_connect_cb); + data->sk =connect_socket (client_bdaddr, test_2_connect_cb, + defer); } static gboolean l2cap_listen_cb(GIOChannel *io, GIOCondition cond,
@@ -1727,7 +1801,8 @@ static void test_server(const void *test_data)if (l2data->server_psm || l2data->cid) { sk =create_l2cap_sock (data, l2data->server_psm, - l2data->cid, l2data->sec_level); + l2data->cid, l2data->sec_level, + l2data->mode);if (sk <0 ) {tester_test_failed ();return ;
@@ -1776,7 +1851,7 @@ static void test_getpeername_not_connected(const void *test_data)socklen_t len;int sk; - sk =create_l2cap_sock (data,0 ,0 ,0 ); + sk =create_l2cap_sock (data,0 ,0 ,0 ,0 );if (sk <0 ) {tester_test_failed ();return ;
@@ -1902,14 +1977,14 @@ int main(int argc, char *argv[]) test_close_socket);test_l2cap_le ("L2CAP LE Client - Open two sockets" , - &le_client_two_sockets_same_client, + &le_client_2_same_client, setup_powered_client, - test_connect_two_sockets); + test_connect_2);test_l2cap_le ("L2CAP LE Client - Open two sockets close one" , - &le_client_two_sockets_close_one, + &le_client_2_close_1, setup_powered_client, - test_connect_two_sockets); + test_connect_2); test_l2cap_le("L2CAP LE Client - Invalid PSM", &le_client_connect_nval_psm_test,
@@ -1920,6 +1995,29 @@ int main(int argc, char *argv[]) setup_powered_server, test_server); +test_l2cap_le ("L2CAP Ext-Flowctl Client - Success" , + &ext_flowctl_client_connect_success_test_1, + setup_powered_client, test_connect); +test_l2cap_le ("L2CAP Ext-Flowctl Client, Direct Advertising - Success" , + &ext_flowctl_client_connect_adv_success_test_1, + setup_powered_client, test_connect); +test_l2cap_le ("L2CAP Ext-Flowctl Client SMP - Success" , + &ext_flowctl_client_connect_success_test_2, + setup_powered_client, test_connect); +test_l2cap_le ("L2CAP Ext-Flowctl Client - Command Reject" , + &ext_flowctl_client_connect_reject_test_1, + setup_powered_client, test_connect); + +test_l2cap_le ("L2CAP Ext-Flowctl Client - Open two sockets" , + &ext_flowctl_client_2, + setup_powered_client, + test_connect_2); + +test_l2cap_le ("L2CAP Ext-Flowctl Client - Open two sockets close one" , + &ext_flowctl_client_2_close_1, + setup_powered_client, + test_connect_2); +test_l2cap_le ("L2CAP LE ATT Client - Success" , &le_att_client_connect_success_test_1, setup_powered_client, test_connect);
Signature · 1 line
2.21.1
Luiz Augusto von Dentz
maintainerPATCH v3 6/6 gatt: Enable connecting to EATT channel using Ext-Flowctl mode
In reply to Luiz Augusto von DentzFrom: Luiz Augusto von Dentz <[email protected]>
This makes use of BT_IO_MODE_EXT_FLOWCTL to connect to EATT channels.
--- src/gatt-client.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-)
src/gatt-client.c +29 -5
@@ -2182,9 +2182,13 @@ static void eatt_connect(struct btd_gatt_client *client)ba2str (device_get_address (dev), addr); -DBG ("Connection attempt to: %s" , addr); -for (i =bt_att_get_channels (att); i < main_opts.gatt_channels; i++) { +int defer_timeout = i +1 < main_opts.gatt_channels ?1 :0 ; + +DBG ("Connection attempt to: %s defer %s" , addr, + defer_timeout ?"true" :"false" ); + +/* Attempt to connect using the Ext-Flowctl */ io = bt_io_connect(eatt_connect_cb, client, NULL, &gerr, BT_IO_OPT_SOURCE_BDADDR, btd_adapter_get_address(adapter),
@@ -2194,15 +2198,35 @@ static void eatt_connect(struct btd_gatt_client *client)device_get_address (dev),BT_IO_OPT_DEST_TYPE ,device_get_le_address_type (dev), +BT_IO_OPT_MODE ,BT_IO_MODE_EXT_FLOWCTL ,BT_IO_OPT_PSM ,BT_ATT_EATT_PSM ,BT_IO_OPT_SEC_LEVEL ,BT_IO_SEC_LOW ,BT_IO_OPT_MTU , main_opts.gatt_mtu, +BT_IO_OPT_DEFER_TIMEOUT , defer_timeout, BT_IO_OPT_INVALID);if (!io) { -error ("EATT bt_io_connect(%s): %s" , addr, - gerr->message);g_error_free (gerr); -return ; + gerr =NULL ; +/* Fallback to legacy LE Mode */ + io =bt_io_connect (eatt_connect_cb, client,NULL , &gerr, +BT_IO_OPT_SOURCE_BDADDR , +btd_adapter_get_address (adapter), +BT_IO_OPT_SOURCE_TYPE , +btd_adapter_get_address_type (adapter), +BT_IO_OPT_DEST_BDADDR , +device_get_address (dev), +BT_IO_OPT_DEST_TYPE , +device_get_le_address_type (dev), +BT_IO_OPT_PSM ,BT_ATT_EATT_PSM , +BT_IO_OPT_SEC_LEVEL ,BT_IO_SEC_LOW , +BT_IO_OPT_MTU , main_opts.gatt_mtu, +BT_IO_OPT_INVALID ); +if (!io) { +error ("EATT bt_io_connect(%s): %s" , addr, + gerr->message); +g_error_free (gerr); +return ; + } }g_io_channel_unref (io);
Signature · 1 line
2.21.1