shared/att: Add bt_att_resend
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Mon, 4 Oct 2021 21:14:40 +0000 (14:14 -0700)
committerAyush Garg <ayush.garg@samsung.com>
Fri, 11 Mar 2022 13:38:37 +0000 (19:08 +0530)
This adds bt_att_resend which can be used with procedures that needs to
send multiple PDUs to complete (e.g. Read Long, Write Long, etc.) so
they are pushed to the head instead of the tail of the queue so one can
retain its position on the queue.

Signed-off-by: Anuj Jain <anuj01.jain@samsung.com>
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
src/shared/att.c
src/shared/att.h

index 5feb1e9bcda45b5b2d8e1d406d7a642af1852c1f..229897d2c39c4ad0a3a9b906cd65dfbbf84e433e 100755 (executable)
@@ -1637,6 +1637,65 @@ unsigned int bt_att_send(struct bt_att *att, uint8_t opcode,
        return op->id;
 }
 
+int bt_att_resend(struct bt_att *att, unsigned int id, uint8_t opcode,
+                               const void *pdu, uint16_t length,
+                               bt_att_response_func_t callback,
+                               void *user_data,
+                               bt_att_destroy_func_t destroy)
+{
+       const struct queue_entry *entry;
+       struct att_send_op *op;
+       bool result;
+
+       if (!att || !id)
+               return -EINVAL;
+
+       /* Lookup request on each channel */
+       for (entry = queue_get_entries(att->chans); entry;
+                                               entry = entry->next) {
+               struct bt_att_chan *chan = entry->data;
+
+               if (chan->pending_req && chan->pending_req->id == id)
+                       break;
+       }
+
+       if (!entry)
+               return -ENOENT;
+
+       /* Only allow requests to be resend */
+       if (get_op_type(opcode) != ATT_OP_TYPE_REQ)
+               return -EOPNOTSUPP;
+
+       op = create_att_send_op(att, opcode, pdu, length, callback, user_data,
+                                                               destroy);
+       if (!op)
+               return -ENOMEM;
+
+       op->id = id;
+
+       switch (opcode) {
+       /* Only prepend requests that could be a continuation */
+       case BT_ATT_OP_READ_BLOB_REQ:
+       case BT_ATT_OP_PREP_WRITE_REQ:
+       case BT_ATT_OP_EXEC_WRITE_REQ:
+               result = queue_push_head(att->req_queue, op);
+               break;
+       default:
+               result = queue_push_tail(att->req_queue, op);
+               break;
+       }
+
+       if (!result) {
+               free(op->pdu);
+               free(op);
+               return -ENOMEM;
+       }
+
+       wakeup_writer(att);
+
+       return 0;
+}
+
 unsigned int bt_att_chan_send(struct bt_att_chan *chan, uint8_t opcode,
                                const void *pdu, uint16_t len,
                                bt_att_response_func_t callback,
index 4b13fa5c620ded8cd7814c8f4a71f5361854cd95..4c3560894ceec9bb7eddfbb87d7d4c2397e95460 100755 (executable)
@@ -66,6 +66,11 @@ unsigned int bt_att_send(struct bt_att *att, uint8_t opcode,
                                        bt_att_response_func_t callback,
                                        void *user_data,
                                        bt_att_destroy_func_t destroy);
+int bt_att_resend(struct bt_att *att, unsigned int id, uint8_t opcode,
+                                       const void *pdu, uint16_t length,
+                                       bt_att_response_func_t callback,
+                                       void *user_data,
+                                       bt_att_destroy_func_t destroy);
 unsigned int bt_att_chan_send(struct bt_att_chan *chan, uint8_t opcode,
                                        const void *pdu, uint16_t len,
                                        bt_att_response_func_t callback,