diff mbox series

ATT: Error (0x01) - Error: Unlikely error (14) Prepare Write req (0x16)

Message ID SN4PR19MB54215EF3B4E7380A21387D2EE4DB2@SN4PR19MB5421.namprd19.prod.outlook.com
State New
Headers show
Series ATT: Error (0x01) - Error: Unlikely error (14) Prepare Write req (0x16) | expand

Commit Message

Ramsay, Trey July 9, 2024, 5:26 p.m. UTC
Bluez Maintainers,
Here is a fix for attribute writes not working in src/shared/gatt-db.c. The prep_write_complete_cb was not getting called. The attrib->write_func code block should not be called when len is 0

commit 5a9baa10d4fde7ca8ab88ecd68e17671c33cb587 (HEAD -> gat-db, master)
Author: Trey_Ramsay <trey_ramsay@dell.com>
Date:   Fri May 31 15:39:27 2024 -0500

    shared/gatt-db: Prepare Write req error BT_ATT_ERROR_UNLIKELY
    
    Fixes Prepare Write req error: BT_ATT_ERROR_UNLIKELY
    
        ATT: Error (0x01)
          Error: Unlikely error (14)
          Prepare Write req (0x16) on handle 0x0069
    
    The prep_write_complete_cb was not getting called
    The attrib->write_func code block does not need to be called when len is 0




-----Original Message-----
From: Ramsay, Trey <Trey.Ramsay@dell.com> 
Sent: Thursday, June 20, 2024 1:58 PM
To: linux-bluetooth@vger.kernel.org
Subject: [PATCH] ATT: Error (0x01) - Error: Unlikely error (14) Prepare Write req (0x16) 


Bluez Maintainers
Here is a fix for attribute writes not working in src/shared/gatt-db.c

https://urldefense.com/v3/__https://github.com/tramsay/bluez-tramsay/commit/246bc960629dff34e744c728f048e9f50f1a005d__;!!LpKI!jkJYamzU8bOdd1qt-sWpj6gy1YwS30UyamHLUJj9Uy0UecrB6QxvCdSWFAUH7Dvq2wVJqu1C5jjoX5amywJH$ [github[.]com]

shared/gatt-db: Prepare Write req error BT_ATT_ERROR_UNLIKELY Fixes Prepare Write req error: BT_ATT_ERROR_UNLIKELY

    ATT: Error (0x01)
      Error: Unlikely error (14)
      Prepare Write req (0x16) on handle 0x0069

The prep_write_complete_cb was not getting called The attrib->write_func code block should not be called when len is 0

Comments

Luiz Augusto von Dentz July 12, 2024, 5:41 p.m. UTC | #1
Hi Trey,

On Fri, Jul 12, 2024 at 12:42 PM Ramsay, Trey <Trey.Ramsay@dell.com> wrote:
>
> Hi Luiz,
> We use gatt-server for in house BMC daemon for BLE communication to and from the BMC via mobile device.  When we updated the bluez libriary, the attribute for setting the IPV4 settings failed because a response was never sent for prep_write_cb

Not familiar with the daemon, is that something open source?

> I believe prep_write_complete_cb should be called after prep_write_cb so the BT_ATT_OP_PREP_WRITE_RSP response is sent.

Not if you mark to authorize prepare write
https://github.com/bluez/bluez/blob/master/src/gatt-database.c#L3276:

    if (opcode == BT_ATT_OP_PREP_WRITE_REQ) {
        if (!btd_device_is_trusted(device) && !desc->prep_authorized &&
                        desc->req_prep_authorization)
            send_write(att, attrib, desc->proxy,
                    desc->pending_writes, id, value, len,
                    offset, false, true);
        else
            gatt_db_attribute_write_result(attrib, id, 0);

        return;
    }

Perhaps what you are not understanding is that this code is
asynchronous, it doesn't respond inline so prep_write_complete_cb will
only be called after the application authorizes/when
gatt_db_attribute_write_result is called to complete the operation.

> Thanks,
> Trey
>
> -----Original Message-----
> From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
> Sent: Thursday, July 11, 2024 3:53 PM
> To: Ramsay, Trey <Trey_Ramsay@Dell.com>
> Cc: linux-bluetooth@vger.kernel.org
> Subject: Re: [PATCH] ATT: Error (0x01) - Error: Unlikely error (14) Prepare Write req (0x16)
>
>
> [EXTERNAL EMAIL]
>
> Hi Trey,
>
> On Thu, Jul 11, 2024 at 4:14 PM Ramsay, Trey <Trey.Ramsay@dell.com> wrote:
> >
> > Thanks Luiz,
> > Maybe I don't understand. In bluez 5.39, prep_write_cb would send BT_ATT_OP_PREP_WRITE_RSP at the end of the function.  In the new code, prep_write_complete_cb is supposed to send BT_ATT_OP_PREP_WRITE_RSP  but prep_write_complete_cb  is never called from gatt_db_attribute_write.  Who is supposed to send the BT_ATT_OP_PREP_WRITE_RSP since prep_write_complete_cb  is not getting called?  With the patch, prep_write_complete_cb will get called.
> >
> >
> > From Bluez 5.39
> > static void prep_write_cb(uint8_t opcode, const void *pdu,
> >                                         uint16_t length, void
> > *user_data) {
> >         struct bt_gatt_server *server = user_data;
> >         uint16_t handle = 0;
> >         uint16_t offset;
> >         struct gatt_db_attribute *attr;
> >         uint8_t ecode;
> >
> >         if (length < 4) {
> >                 ecode = BT_ATT_ERROR_INVALID_PDU;
> >                 goto error;
> >         }
> >
> >         if (queue_length(server->prep_queue) >= server->max_prep_queue_len) {
> >                 ecode = BT_ATT_ERROR_PREPARE_QUEUE_FULL;
> >                 goto error;
> >         }
> >
> >         handle = get_le16(pdu);
> >         offset = get_le16(pdu + 2);
> >
> >         attr = gatt_db_get_attribute(server->db, handle);
> >         if (!attr) {
> >                 ecode = BT_ATT_ERROR_INVALID_HANDLE;
> >                 goto error;
> >         }
> >
> >         util_debug(server->debug_callback, server->debug_data,
> >                                 "Prep Write Req - handle: 0x%04x",
> > handle);
> >
> >         ecode = check_permissions(server, attr, BT_ATT_PERM_WRITE |
> >                                                 BT_ATT_PERM_WRITE_AUTHEN |
> >                                                 BT_ATT_PERM_WRITE_ENCRYPT);
> >         if (ecode)
> >                 goto error;
> >
> >         if (!store_prep_data(server, handle, offset, length - 4,
> >                                                 &((uint8_t *) pdu)[4])) {
> >                 ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
> >                 goto error;
> >         }
> >
> >         bt_att_send(server->att, BT_ATT_OP_PREP_WRITE_RSP, pdu, length, NULL,     <------------------------- Response is sent
> >                                                                 NULL, NULL);
> >         return;
> >
> > error:
> >         bt_att_send_error_rsp(server->att, opcode, handle, ecode); }
> >
> >
> > --------------------------------------------------------------------------------------------------------------------------------------
> > In Bluez master, the response is sent from prep_write_complete_cb but the call back is never called since gatt_db_attribute_write returns True before func is executed which is the function pointer to prep_write_complete_cb
> > static void prep_write_complete_cb(struct gatt_db_attribute *attr, int err,
> >                                                                 void *user_data)
> > {
> >         struct prep_write_complete_data *pwcd = user_data;
> >         uint16_t handle = 0;
> >         uint16_t offset;
> >
> >         handle = get_le16(pwcd->pdu);
> >
> >         if (err) {
> >                 bt_att_chan_send_error_rsp(pwcd->chan, BT_ATT_OP_PREP_WRITE_REQ,
> >                                                                 handle, err);
> >                 free(pwcd->pdu);
> >                 free(pwcd);
> >
> >                 return;
> >         }
> >
> >         offset = get_le16(pwcd->pdu + 2);
> >
> >         if (!store_prep_data(pwcd->server, handle, offset, pwcd->length - 4,
> >                                                 &((uint8_t *) pwcd->pdu)[4]))
> >                 bt_att_chan_send_error_rsp(pwcd->chan, BT_ATT_OP_PREP_WRITE_RSP,
> >                                         handle,
> >                                         BT_ATT_ERROR_INSUFFICIENT_RESOURCES);
> >
> >         bt_att_chan_send_rsp(pwcd->chan, BT_ATT_OP_PREP_WRITE_RSP, pwcd->pdu,  <-------------- Response is sent
> >                                                                 pwcd->length);
> >
> >         free(pwcd->pdu);
> >         free(pwcd);
> > }
>
> It might be because of:
>
> commit 1ebfc68ff53ea5ed5cb424df151bf413c7ffe9be
> Author: Grzegorz Kolodziejczyk <grzegorz.kolodziejczyk@codecoup.pl>
> Date:   Mon May 28 10:20:52 2018 +0200
>
>     shared/gatt-server: Request authorization for prepare writes
>
>     This patch adds gatt-server possibility to request authorization from
>     application if needed and previously wasn't authorized. Authorization is
>     requested by sending message with set prepare write authorization reqest
>     to client.
>
> Anyway we are talking about ancient changes here, what exactly is the
> attribute you are trying to use the so called long write procedure
> btw? Is that using bluetoothctl to register it or is some other
> application involved? Or is this some PTS test case that requires
> authorization? If you use bluetoothctl for that it might be prompting
> to authorize the request.
diff mbox series

Patch

diff --git a/src/shared/gatt-db.c b/src/shared/gatt-db.c
index 2c8e7d31e..678aef4cf 100644
--- a/src/shared/gatt-db.c
+++ b/src/shared/gatt-db.c
@@ -2127,6 +2127,10 @@  bool gatt_db_attribute_write(struct gatt_db_attribute *attrib, uint16_t offset,
     if (!attrib || (!func && attrib->write_func))
         return false;
 
+    /* Nothing to write just skip */
+    if (len == 0)
+        goto done;
+
     if (attrib->write_func) {
         struct pending_write *p;
 
@@ -2162,10 +2166,6 @@  bool gatt_db_attribute_write(struct gatt_db_attribute *attrib, uint16_t offset,
         return true;
     }
 
-    /* Nothing to write just skip */
-    if (len == 0)
-        goto done;
-
     /* For values stored in db allocate on demand */
     if (!attrib->value || offset >= attrib->value_len ||
                 len > (unsigned) (attrib->value_len - offset)) {