X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fbt%2Fbt_bluez.c;h=52567f9e8b7a04d4cd1d3ca68c55960ed4b8684c;hb=2d8a50897614e097cffa36dd7a3acd7d9032a9a1;hp=e38727348a0ddaf574fc505e159c47170c1aa847;hpb=113de3a57290347b652c93eebc7ec0b32b1bea6d;p=libsigrok.git diff --git a/src/bt/bt_bluez.c b/src/bt/bt_bluez.c index e3872734..52567f9e 100644 --- a/src/bt/bt_bluez.c +++ b/src/bt/bt_bluez.c @@ -87,14 +87,15 @@ #include #include "libsigrok-internal.h" -/** @cond PRIVATE */ #define LOG_PREFIX "bt-bluez" -/** @endcond */ #define CONNECT_BLE_TIMEOUT 20 /* Connect timeout in seconds. */ #define STORE_MAC_REVERSE 1 #define ACCEPT_NONSEP_MAC 1 +#define CONNECT_RFCOMM_TRIES 3 +#define CONNECT_RFCOMM_RETRY_MS 100 + /* Silence warning about (currently) unused routine. */ #define WITH_WRITE_TYPE_HANDLE 0 @@ -797,7 +798,7 @@ SR_PRIV int sr_bt_connect_ble(struct sr_bt_desc *desc) SR_PRIV int sr_bt_connect_rfcomm(struct sr_bt_desc *desc) { struct sockaddr_rc addr; - int fd, rc; + int i, fd, rc; if (!desc) return -1; @@ -809,25 +810,40 @@ SR_PRIV int sr_bt_connect_rfcomm(struct sr_bt_desc *desc) if (!desc->rfcomm_channel) desc->rfcomm_channel = 1; - fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - if (fd < 0) { - perror("socket"); - return -1; - } - desc->fd = fd; - memset(&addr, 0, sizeof(addr)); addr.rc_family = AF_BLUETOOTH; str2ba(desc->remote_addr, &addr.rc_bdaddr); addr.rc_channel = desc->rfcomm_channel; - rc = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); - if (rc < 0) { - perror("connect"); - return -2; + + /* + * There are cases where connect returns EBUSY if we are re-connecting + * to a device. Try multiple times to work around this issue. + */ + for (i = 0; i < CONNECT_RFCOMM_TRIES; i++) { + fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + if (fd < 0) { + perror("socket"); + return -1; + } + + rc = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); + if (rc >= 0) { + sr_spew("connected"); + desc->fd = fd; + return 0; + } else if (rc < 0 && errno == EBUSY) { + close(fd); + g_usleep(CONNECT_RFCOMM_RETRY_MS * 1000); + } else { + close(fd); + perror("connect"); + return -2; + } } - sr_spew("connected"); - return 0; + sr_err("Connect failed, device busy."); + + return -2; } SR_PRIV void sr_bt_disconnect(struct sr_bt_desc *desc)