From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx> This uses 5 seconds timeout for EATT bearers since it maybe possible that other channels can be used so the operation can be resend. --- src/shared/att.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/shared/att.c b/src/shared/att.c index 85feead77d0f..b8fc44b16b20 100644 --- a/src/shared/att.c +++ b/src/shared/att.c @@ -30,6 +30,7 @@ #define ATT_OP_CMD_MASK 0x40 #define ATT_OP_SIGNED_MASK 0x80 #define ATT_TIMEOUT_INTERVAL 30000 /* 30000 ms */ +#define EATT_TIMEOUT_INTERVAL 5000 /* 5000 ms */ /* Length of signature in write signed packet */ #define BT_ATT_SIGNATURE_LEN 12 @@ -42,6 +43,7 @@ struct bt_att_chan { struct io *io; uint8_t type; int sec_level; /* Only used for non-L2CAP */ + int timeout; struct queue *queue; /* Channel dedicated queue */ @@ -470,6 +472,8 @@ struct timeout_data { unsigned int id; }; +static void wakeup_writer(struct bt_att *att); + static bool timeout_cb(void *user_data) { struct timeout_data *timeout = user_data; @@ -495,7 +499,16 @@ static bool timeout_cb(void *user_data) att->timeout_callback(op->id, op->opcode, att->timeout_data); op->timeout_id = 0; - disc_att_send_op(op); + + /* Resend op if it is using EATT bearer and there are more channels + * left that could be used since there maybe a problem with the channel + * e.g. not enough credits to send the entire packet. + */ + if (chan->type == BT_ATT_EATT && queue_length(att->chans) > 1) { + queue_push_tail(att->req_queue, op); + wakeup_writer(att); + } else + disc_att_send_op(op); /* * Directly terminate the connection as required by the ATT protocol. @@ -585,8 +598,7 @@ static bool can_write_data(struct io *io, void *user_data) timeout = new0(struct timeout_data, 1); timeout->chan = chan; timeout->id = op->id; - op->timeout_id = timeout_add(ATT_TIMEOUT_INTERVAL, timeout_cb, - timeout, free); + op->timeout_id = timeout_add(chan->timeout, timeout_cb, timeout, free); /* Return true as there may be more operations ready to write. */ return true; @@ -1204,9 +1216,16 @@ static struct bt_att_chan *bt_att_chan_new(int fd, uint8_t type) /* fall through */ case BT_ATT_LE: chan->mtu = BT_ATT_DEFAULT_LE_MTU; + chan->timeout = ATT_TIMEOUT_INTERVAL; break; - default: + case BT_ATT_BREDR: chan->mtu = io_get_mtu(chan->fd); + chan->timeout = ATT_TIMEOUT_INTERVAL; + break; + case BT_ATT_EATT: + chan->mtu = io_get_mtu(chan->fd); + chan->timeout = EATT_TIMEOUT_INTERVAL; + break; } if (chan->mtu < BT_ATT_DEFAULT_LE_MTU) -- 2.39.2