diff mbox series

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

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

Checks

Context Check Description
tedd_an/pre-ci_am fail error: patch failed: src/shared/gatt-db.c:2127 error: src/shared/gatt-db.c: patch does not apply hint: Use 'git am --show-current-patch' to see the failed patch

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

bluez.test.bot@gmail.com July 9, 2024, 5:36 p.m. UTC | #1
This is an automated email and please do not reply to this email.

Dear Submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
While preparing the CI tests, the patches you submitted couldn't be applied to the current HEAD of the repository.

----- Output -----

error: patch failed: src/shared/gatt-db.c:2127
error: src/shared/gatt-db.c: patch does not apply
hint: Use 'git am --show-current-patch' to see the failed patch

Please resolve the issue and submit the patches again.


---
Regards,
Linux Bluetooth
Luiz Augusto von Dentz July 9, 2024, 8:33 p.m. UTC | #2
Hi Trey,

On Tue, Jul 9, 2024 at 1:34 PM Ramsay, Trey <Trey.Ramsay@dell.com> wrote:
>
> 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

This doesn't sound quite right, 0 length still needs to be passed to
the attribute to confirm since we don't know if it could be a
procedure or not. Can you explain what attribute is being written and
if it could be due to the application not responding and the procedure
timing out (e.g. write_timeout is called?), perhaps if you can paste a
btmon trace as well that could help checking what attribute it is
trying to use prepare write.

> 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)) {
>
>
>
> -----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
>
Ramsay, Trey July 10, 2024, 7:55 p.m. UTC | #3
Hi Luis,
It is a Prepare Write Request but prep_write_complete_cb is never getting called. In gatt_db_attribute_write, the prep_write_complete_cb function is not getting called since "attribe->write_func" is not null and the function will return "True".  The prep_write_complete_cb is supposed to get called after "goto done;" but it's not getting called.  The prep_write_complete_cb is assigned to "func".    The patch checks to see if len is 0 and will goto done which will call prep_write_complete_cb.
 

> ACL data: handle 0 flags 0x01 dlen 3
    ATT: Prepare Write req (0x16)
      attr handle 0x0069, value offset 0x0000
      part attr value  0x80 0x02 0x00 0x01 0xaa 0xd3 0x81 0x51 0x54 0x5b 0xea 0xaf 0x68 0x0d 0xeb 0xe6 0x11 0x2d 0x63 0xb1 0x8e 0xbd 0xc4 0x63 0x8f 0xf6 0xb6 0x10 0x63 0xb5 0x54 0x3f 0x36 0x19 0x41 0x5b 0x25 0xcd 0xa7 0xe5 0x9d 0xc7 0x71 0x26 0x33 0x7c 0xe8 0x0e 0x67 0xd8 0x9a 0x0a 0xb5 0xe5 0x24 0x87 0x2d 0xcc 0x00 0xa9 0xc8 0xb8 0x95 0x76 0x75 0x9f 0x79 0x1f 0x94 0xe4 0xd9 0xbe 0xab 0x22 0xa3 0x33 0x18 0x28 0x57 0x26 0xae 0x6d 0x0a 0x9b 0x63 0xeb 0x10 0xf3 0xb5 0xea 0x64 0x4a 0x81 0x55 0xe0 0xa9 0x43 0x8c 0x87 0xb4 0x32 0x1c 0x79 0xd6 0x34 0x97 0xff 0xae 0x71 0x1e 0x50 0x7c 0xb6 0x72 0x7b 0x49 0x44 0xef 0xfe 0xe2 0x40 0xc7 0x3e 0x5e 0x42 0x9b 0xca 0xa4 0x61 0x66 0x72 0x0a 0x1d 0x5c 0xb0 0xdb 0xa1 0xbb 0xf7 0xb6 0x27 0xa0 0x67 0xde 0x69 0xd9 0x67 0xa7 0x09 0x58 0x71 0x37 0x99 0x95 0x5c 0x5d 0x10 0x4d 0xed 0x2f 0xe2 0x85 0x6c 0x03 0x60 0x80 0x67 0x25 0x1b 0x33 0x02 0x53 0xbe 0x67 0xdb 0xd4 0x2a 0x9e 0x8d 0x82 0xe2 0x9d 0xc4 0x86 0x08 0x84 0x2c 0xbf 0xa5 0xc5 0xd3 0x99 0xf1 0x02 0x09 0x80 0x0c 0xc5 0xf9 0x99 0x06 0x20 0x01 0x75 0xdb 0x0c 0x11 0x81 0x87 0x04 0x4d 0xf0 0xcc 0xf7 0x27 0x85 0xcd 0x22 0x84 0x85 0x04 0xb3 0xa2 0xa9 0xcc 0xe9 0x27 0x8b 0x67 0x02 0x1b 0xe0 0x8c 0xd7 0x8f 0x51 0x3a 0xa6 0x0c 0x23 0xa0 0x09 0x2b 0x4c 0xb0 0x80 0x34 0xf9 0x61 0xaa 0x72 0x90 0x3a 0x5e 0xb7 0x11 0xaf 0xc3 0xcd 0x78 0x4f 0xb6 0x1b 0xbb 0xb4 0xb2 0x42 0x9f 0x87 0xad 0xf6 0xa1 0xae 0xdd 0xde 0x38 0x09 0x7a 0xc5 0x7c 0xbd 0x98 0x89 0xae 0x49 0x98 0xe7 0xae 0x92 0x28 0x45 0x5a 0xbc 0x30 0x53 0xe5 0xc1 0x56 0xb3 0x9f 0x56 0x7b 0xa1 0x02 0xcd 0xc2 0x25 0x2a 0xb2 0xc5 0xc9 0x35 0xec 0xa7 0x26 0x79 0x97 0x2e 0x96 0x97 0x3e 0x5b 0x8f 0xc7 0x2f 0xa8 0x39 0x70 0xb1 0x22 0x5b 0x2c 0x15 0x41 0xec 0x6b 0xc4 0x1e 0x2d 0xc0 0x47 0x75 0x42 0x01 0x40 0xc5 0x17 0x69 0xf4 0x0a 0xcd 0x7e 0x62 0x25 0xec 0x1f 0x7c 0xae 0x7b 0xf9 0x1e 0x9f 0x98 0xbd 0xc7 0xc3 0x44 0x4c 0xe2 0x0a 0x8c 0xbe 0xeb 0x1e 0xae 0x7b 0xbc 0x49 0xfa 0x7d 0xa3 0xdf 0xb2 0xc0 0x69 0xf7 0x57 0x6b 0x6f 0xe7 0x2e 0x3c 0x90 0x0a 0x16 0xe8 0x03 0x0d 0xf1 0x9c 0x4c 0xa3 0x4b 0xcf 0x6d 0xc3 0x4a 0x69 0x25 0xc5 0xf6 0x9c 0x4b 0xb3 0x77 0x67 0x7b 0x00 0xbb 0x1f 0xcd 0x59 0xb0 0xe9 0xf6 0xbe 0xa3 0x41 0xd1 0x2c 0x1f 0x09 0x6b 0x4e 0x52 0x01 0x0c 0xe1 0x20 0x6c 0x76 0xfd 0xc9 0xb9 0xb4 0xd8 0xdf 0xcb 0xac 0x77 0x65 0xcd 0x98 0xe9 0x66 0x6c 0xc8 0x8f 0xfc 0xef 0x7e 0x48 0x9f 0xc8 0xd6 0x9c 0x72 0xac 0x44 0xa3 0x67 0xa3 0x6a 0xe3 0xde 0x3a 0xd5 0x21 0x94 0x29 0x94 0x3d 0x7b 0x88 0x29 0xc3 0xc2 0x7e 0x82 0x9d 0xe7 0x00 0x7c 0x96 0x28 0x1d 0x20 0xf8 0x81 0x02 0x7c 0xc2 0xb2 0xfa 0x43 0x90 0x6e
< ACL data: handle 0 flags 0x00 dlen 9
    ATT: Error (0x01)
      Error: Unlikely error (14)
      Prepare Write req (0x16) on handle 0x0069
> HCI Event: Number of Completed Packets (0x13) plen 5
    handle 0 packets 1
> ACL data: handle 0 flags 0x02 dlen 6
    ATT: Exec Write req (0x18)
      cancel all prepared writes (0x00)
< ACL data: handle 0 flags 0x00 dlen 5
    ATT: Exec Write resp (0x19)
> HCI Event: Number of Completed Packets (0x13) plen 5
    handle 0 packets 1

-----Original Message-----
From: Luiz Augusto von Dentz <luiz.dentz@gmail.com> 
Sent: Tuesday, July 9, 2024 3:34 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 Tue, Jul 9, 2024 at 1:34 PM Ramsay, Trey <Trey.Ramsay@dell.com> wrote:
>
> 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

This doesn't sound quite right, 0 length still needs to be passed to the attribute to confirm since we don't know if it could be a procedure or not. Can you explain what attribute is being written and if it could be due to the application not responding and the procedure timing out (e.g. write_timeout is called?), perhaps if you can paste a btmon trace as well that could help checking what attribute it is trying to use prepare write.

> 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)) {
>
>
>
> -----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/c
> ommit/246bc960629dff34e744c728f048e9f50f1a005d__;!!LpKI!jkJYamzU8bOdd1
> qt-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
>


--
Luiz Augusto von Dentz
Luiz Augusto von Dentz July 10, 2024, 9:13 p.m. UTC | #4
Hi Trey,

On Wed, Jul 10, 2024 at 3:55 PM Ramsay, Trey <Trey.Ramsay@dell.com> wrote:
>
> Hi Luis,
> It is a Prepare Write Request but prep_write_complete_cb is never getting called. In gatt_db_attribute_write, the prep_write_complete_cb function is not getting called since "attribe->write_func" is not null and the function will return "True".  The prep_write_complete_cb is supposed to get called after "goto done;" but it's not getting called.  The prep_write_complete_cb is assigned to "func".    The patch checks to see if len is 0 and will goto done which will call prep_write_complete_cb.

Well if it returns true then it should not return unlikely:

    status = gatt_db_attribute_write(attr, offset, NULL, 0,
                        BT_ATT_OP_PREP_WRITE_REQ,
                        server->att,
                        prep_write_complete_cb, pwcd);

    if (status)
        return;

    ecode = BT_ATT_ERROR_UNLIKELY;

error:
    bt_att_chan_send_error_rsp(chan, opcode, handle, ecode);

>
> > ACL data: handle 0 flags 0x01 dlen 3
>     ATT: Prepare Write req (0x16)
>       attr handle 0x0069, value offset 0x0000
>       part attr value  0x80 0x02 0x00 0x01 0xaa 0xd3 0x81 0x51 0x54 0x5b 0xea 0xaf 0x68 0x0d 0xeb 0xe6 0x11 0x2d 0x63 0xb1 0x8e 0xbd 0xc4 0x63 0x8f 0xf6 0xb6 0x10 0x63 0xb5 0x54 0x3f 0x36 0x19 0x41 0x5b 0x25 0xcd 0xa7 0xe5 0x9d 0xc7 0x71 0x26 0x33 0x7c 0xe8 0x0e 0x67 0xd8 0x9a 0x0a 0xb5 0xe5 0x24 0x87 0x2d 0xcc 0x00 0xa9 0xc8 0xb8 0x95 0x76 0x75 0x9f 0x79 0x1f 0x94 0xe4 0xd9 0xbe 0xab 0x22 0xa3 0x33 0x18 0x28 0x57 0x26 0xae 0x6d 0x0a 0x9b 0x63 0xeb 0x10 0xf3 0xb5 0xea 0x64 0x4a 0x81 0x55 0xe0 0xa9 0x43 0x8c 0x87 0xb4 0x32 0x1c 0x79 0xd6 0x34 0x97 0xff 0xae 0x71 0x1e 0x50 0x7c 0xb6 0x72 0x7b 0x49 0x44 0xef 0xfe 0xe2 0x40 0xc7 0x3e 0x5e 0x42 0x9b 0xca 0xa4 0x61 0x66 0x72 0x0a 0x1d 0x5c 0xb0 0xdb 0xa1 0xbb 0xf7 0xb6 0x27 0xa0 0x67 0xde 0x69 0xd9 0x67 0xa7 0x09 0x58 0x71 0x37 0x99 0x95 0x5c 0x5d 0x10 0x4d 0xed 0x2f 0xe2 0x85 0x6c 0x03 0x60 0x80 0x67 0x25 0x1b 0x33 0x02 0x53 0xbe 0x67 0xdb 0xd4 0x2a 0x9e 0x8d 0x82 0xe2 0x9d 0xc4 0x86 0x08 0x84 0x2c 0xbf 0xa5 0xc5 0xd3 0x99 0xf1 0x02 0x09 0x80 0x0c 0xc5 0xf9 0x99 0x06 0x20 0x01 0x75 0xdb 0x0c 0x11 0x81 0x87 0x04 0x4d 0xf0 0xcc 0xf7 0x27 0x85 0xcd 0x22 0x84 0x85 0x04 0xb3 0xa2 0xa9 0xcc 0xe9 0x27 0x8b 0x67 0x02 0x1b 0xe0 0x8c 0xd7 0x8f 0x51 0x3a 0xa6 0x0c 0x23 0xa0 0x09 0x2b 0x4c 0xb0 0x80 0x34 0xf9 0x61 0xaa 0x72 0x90 0x3a 0x5e 0xb7 0x11 0xaf 0xc3 0xcd 0x78 0x4f 0xb6 0x1b 0xbb 0xb4 0xb2 0x42 0x9f 0x87 0xad 0xf6 0xa1 0xae 0xdd 0xde 0x38 0x09 0x7a 0xc5 0x7c 0xbd 0x98 0x89 0xae 0x49 0x98 0xe7 0xae 0x92 0x28 0x45 0x5a 0xbc 0x30 0x53 0xe5 0xc1 0x56 0xb3 0x9f 0x56 0x7b 0xa1 0x02 0xcd 0xc2 0x25 0x2a 0xb2 0xc5 0xc9 0x35 0xec 0xa7 0x26 0x79 0x97 0x2e 0x96 0x97 0x3e 0x5b 0x8f 0xc7 0x2f 0xa8 0x39 0x70 0xb1 0x22 0x5b 0x2c 0x15 0x41 0xec 0x6b 0xc4 0x1e 0x2d 0xc0 0x47 0x75 0x42 0x01 0x40 0xc5 0x17 0x69 0xf4 0x0a 0xcd 0x7e 0x62 0x25 0xec 0x1f 0x7c 0xae 0x7b 0xf9 0x1e 0x9f 0x98 0xbd 0xc7 0xc3 0x44 0x4c 0xe2 0x0a 0x8c 0xbe 0xeb 0x1e 0xae 0x7b 0xbc 0x49 0xfa 0x7d 0xa3 0xdf 0xb2 0xc0 0x69 0xf7 0x57 0x6b 0x6f 0xe7 0x2e 0x3c 0x90 0x0a 0x16 0xe8 0x03 0x0d 0xf1 0x9c 0x4c 0xa3 0x4b 0xcf 0x6d 0xc3 0x4a 0x69 0x25 0xc5 0xf6 0x9c 0x4b 0xb3 0x77 0x67 0x7b 0x00 0xbb 0x1f 0xcd 0x59 0xb0 0xe9 0xf6 0xbe 0xa3 0x41 0xd1 0x2c 0x1f 0x09 0x6b 0x4e 0x52 0x01 0x0c 0xe1 0x20 0x6c 0x76 0xfd 0xc9 0xb9 0xb4 0xd8 0xdf 0xcb 0xac 0x77 0x65 0xcd 0x98 0xe9 0x66 0x6c 0xc8 0x8f 0xfc 0xef 0x7e 0x48 0x9f 0xc8 0xd6 0x9c 0x72 0xac 0x44 0xa3 0x67 0xa3 0x6a 0xe3 0xde 0x3a 0xd5 0x21 0x94 0x29 0x94 0x3d 0x7b 0x88 0x29 0xc3 0xc2 0x7e 0x82 0x9d 0xe7 0x00 0x7c 0x96 0x28 0x1d 0x20 0xf8 0x81 0x02 0x7c 0xc2 0xb2 0xfa 0x43 0x90 0x6e

That doesn't seem like a zero length, what BlueZ version is this btw?

> < ACL data: handle 0 flags 0x00 dlen 9
>     ATT: Error (0x01)
>       Error: Unlikely error (14)
>       Prepare Write req (0x16) on handle 0x0069

Check what time does this error is generated, since this well be:

static bool write_timeout(void *user_data)
{
    struct pending_write *p = user_data;

    p->timeout_id = 0;

    queue_remove(p->attrib->pending_writes, p);

    pending_write_result(p, -ETIMEDOUT);

    return false;
}

The -ETIMEOUT would be converted to:

static uint8_t att_ecode_from_error(int err)
{
    /*
     * If the error fits in a single byte, treat it as an ATT protocol
     * error as is. Since "0" is not a valid ATT protocol error code, we map
     * that to UNLIKELY below.
     */
    if (err > 0 && err < UINT8_MAX)
        return err;

    /*
     * Since we allow UNIX errnos, map them to appropriate ATT protocol
     * and "Common Profile and Service" error codes.
     */
    switch (err) {
    case -ENOENT:
        return BT_ATT_ERROR_INVALID_HANDLE;
    case -ENOMEM:
        return BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
    case -EALREADY:
        return BT_ERROR_ALREADY_IN_PROGRESS;
    case -EOVERFLOW:
        return BT_ERROR_OUT_OF_RANGE;
    }

    return BT_ATT_ERROR_UNLIKELY;
}

So on write_timeout it would also generate the unlikely error.

Note that normally prepare write don't need authorization, but perhaps
you have an application setting 'authorize':

https://github.com/bluez/bluez/blob/master/doc/org.bluez.GattCharacteristic.rst#arraystring-flags-read-only,
which means the following code would execute:

    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;
    }

You can also try adding passing -t -p debug to btmon so it logs the
debug messages from bluetoothd and include timing information.

> > HCI Event: Number of Completed Packets (0x13) plen 5
>     handle 0 packets 1
> > ACL data: handle 0 flags 0x02 dlen 6
>     ATT: Exec Write req (0x18)
>       cancel all prepared writes (0x00)
> < ACL data: handle 0 flags 0x00 dlen 5
>     ATT: Exec Write resp (0x19)
> > HCI Event: Number of Completed Packets (0x13) plen 5
>     handle 0 packets 1
>
> -----Original Message-----
> From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
> Sent: Tuesday, July 9, 2024 3:34 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 Tue, Jul 9, 2024 at 1:34 PM Ramsay, Trey <Trey.Ramsay@dell.com> wrote:
> >
> > 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
>
> This doesn't sound quite right, 0 length still needs to be passed to the attribute to confirm since we don't know if it could be a procedure or not. Can you explain what attribute is being written and if it could be due to the application not responding and the procedure timing out (e.g. write_timeout is called?), perhaps if you can paste a btmon trace as well that could help checking what attribute it is trying to use prepare write.
>
> > 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)) {
> >
> >
> >
> > -----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/c
> > ommit/246bc960629dff34e744c728f048e9f50f1a005d__;!!LpKI!jkJYamzU8bOdd1
> > qt-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
> >
>
>
> --
> Luiz Augusto von Dentz
>
Ramsay, Trey July 11, 2024, 5:17 p.m. UTC | #5
Hi Luiz,
Correct, the request is timing out.  The problem is "prep_write_complete_cb" is never getting called after the "prep_write_cb" is called.  The prep_write_complete_cb is responsible for sending the response BT_ATT_OP_PREP_WRITE_RSP back.  The patch I provided fixes the code so that prep_write_complete_cb  will get called and the response is sent back.   Sorry, I had debugged this issue a quite a while ago using bluez 5.55 and 5.66 and noticed the same issue in the master branch.  We have been using the patch and it has resolved the issue.

Thanks,
Trey

-----Original Message-----
From: Luiz Augusto von Dentz <luiz.dentz@gmail.com> 
Sent: Wednesday, July 10, 2024 4:14 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 Wed, Jul 10, 2024 at 3:55 PM Ramsay, Trey <Trey.Ramsay@dell.com> wrote:
>
> Hi Luis,
> It is a Prepare Write Request but prep_write_complete_cb is never getting called. In gatt_db_attribute_write, the prep_write_complete_cb function is not getting called since "attribe->write_func" is not null and the function will return "True".  The prep_write_complete_cb is supposed to get called after "goto done;" but it's not getting called.  The prep_write_complete_cb is assigned to "func".    The patch checks to see if len is 0 and will goto done which will call prep_write_complete_cb.

Well if it returns true then it should not return unlikely:

    status = gatt_db_attribute_write(attr, offset, NULL, 0,
                        BT_ATT_OP_PREP_WRITE_REQ,
                        server->att,
                        prep_write_complete_cb, pwcd);

    if (status)
        return;

    ecode = BT_ATT_ERROR_UNLIKELY;

error:
    bt_att_chan_send_error_rsp(chan, opcode, handle, ecode);

>
> > ACL data: handle 0 flags 0x01 dlen 3
>     ATT: Prepare Write req (0x16)
>       attr handle 0x0069, value offset 0x0000
>       part attr value  0x80 0x02 0x00 0x01 0xaa 0xd3 0x81 0x51 0x54 
> 0x5b 0xea 0xaf 0x68 0x0d 0xeb 0xe6 0x11 0x2d 0x63 0xb1 0x8e 0xbd 0xc4 
> 0x63 0x8f 0xf6 0xb6 0x10 0x63 0xb5 0x54 0x3f 0x36 0x19 0x41 0x5b 0x25 
> 0xcd 0xa7 0xe5 0x9d 0xc7 0x71 0x26 0x33 0x7c 0xe8 0x0e 0x67 0xd8 0x9a 
> 0x0a 0xb5 0xe5 0x24 0x87 0x2d 0xcc 0x00 0xa9 0xc8 0xb8 0x95 0x76 0x75 
> 0x9f 0x79 0x1f 0x94 0xe4 0xd9 0xbe 0xab 0x22 0xa3 0x33 0x18 0x28 0x57 
> 0x26 0xae 0x6d 0x0a 0x9b 0x63 0xeb 0x10 0xf3 0xb5 0xea 0x64 0x4a 0x81 
> 0x55 0xe0 0xa9 0x43 0x8c 0x87 0xb4 0x32 0x1c 0x79 0xd6 0x34 0x97 0xff 
> 0xae 0x71 0x1e 0x50 0x7c 0xb6 0x72 0x7b 0x49 0x44 0xef 0xfe 0xe2 0x40 
> 0xc7 0x3e 0x5e 0x42 0x9b 0xca 0xa4 0x61 0x66 0x72 0x0a 0x1d 0x5c 0xb0 
> 0xdb 0xa1 0xbb 0xf7 0xb6 0x27 0xa0 0x67 0xde 0x69 0xd9 0x67 0xa7 0x09 
> 0x58 0x71 0x37 0x99 0x95 0x5c 0x5d 0x10 0x4d 0xed 0x2f 0xe2 0x85 0x6c 
> 0x03 0x60 0x80 0x67 0x25 0x1b 0x33 0x02 0x53 0xbe 0x67 0xdb 0xd4 0x2a 
> 0x9e 0x8d 0x82 0xe2 0x9d 0xc4 0x86 0x08 0x84 0x2c 0xbf 0xa5 0xc5 0xd3 
> 0x99 0xf1 0x02 0x09 0x80 0x0c 0xc5 0xf9 0x99 0x06 0x20 0x01 0x75 0xdb 
> 0x0c 0x11 0x81 0x87 0x04 0x4d 0xf0 0xcc 0xf7 0x27 0x85 0xcd 0x22 0x84 
> 0x85 0x04 0xb3 0xa2 0xa9 0xcc 0xe9 0x27 0x8b 0x67 0x02 0x1b 0xe0 0x8c 
> 0xd7 0x8f 0x51 0x3a 0xa6 0x0c 0x23 0xa0 0x09 0x2b 0x4c 0xb0 0x80 0x34 
> 0xf9 0x61 0xaa 0x72 0x90 0x3a 0x5e 0xb7 0x11 0xaf 0xc3 0xcd 0x78 0x4f 
> 0xb6 0x1b 0xbb 0xb4 0xb2 0x42 0x9f 0x87 0xad 0xf6 0xa1 0xae 0xdd 0xde 
> 0x38 0x09 0x7a 0xc5 0x7c 0xbd 0x98 0x89 0xae 0x49 0x98 0xe7 0xae 0x92 
> 0x28 0x45 0x5a 0xbc 0x30 0x53 0xe5 0xc1 0x56 0xb3 0x9f 0x56 0x7b 0xa1 
> 0x02 0xcd 0xc2 0x25 0x2a 0xb2 0xc5 0xc9 0x35 0xec 0xa7 0x26 0x79 0x97 
> 0x2e 0x96 0x97 0x3e 0x5b 0x8f 0xc7 0x2f 0xa8 0x39 0x70 0xb1 0x22 0x5b 
> 0x2c 0x15 0x41 0xec 0x6b 0xc4 0x1e 0x2d 0xc0 0x47 0x75 0x42 0x01 0x40 
> 0xc5 0x17 0x69 0xf4 0x0a 0xcd 0x7e 0x62 0x25 0xec 0x1f 0x7c 0xae 0x7b 
> 0xf9 0x1e 0x9f 0x98 0xbd 0xc7 0xc3 0x44 0x4c 0xe2 0x0a 0x8c 0xbe 0xeb 
> 0x1e 0xae 0x7b 0xbc 0x49 0xfa 0x7d 0xa3 0xdf 0xb2 0xc0 0x69 0xf7 0x57 
> 0x6b 0x6f 0xe7 0x2e 0x3c 0x90 0x0a 0x16 0xe8 0x03 0x0d 0xf1 0x9c 0x4c 
> 0xa3 0x4b 0xcf 0x6d 0xc3 0x4a 0x69 0x25 0xc5 0xf6 0x9c 0x4b 0xb3 0x77 
> 0x67 0x7b 0x00 0xbb 0x1f 0xcd 0x59 0xb0 0xe9 0xf6 0xbe 0xa3 0x41 0xd1 
> 0x2c 0x1f 0x09 0x6b 0x4e 0x52 0x01 0x0c 0xe1 0x20 0x6c 0x76 0xfd 0xc9 
> 0xb9 0xb4 0xd8 0xdf 0xcb 0xac 0x77 0x65 0xcd 0x98 0xe9 0x66 0x6c 0xc8 
> 0x8f 0xfc 0xef 0x7e 0x48 0x9f 0xc8 0xd6 0x9c 0x72 0xac 0x44 0xa3 0x67 
> 0xa3 0x6a 0xe3 0xde 0x3a 0xd5 0x21 0x94 0x29 0x94 0x3d 0x7b 0x88 0x29 
> 0xc3 0xc2 0x7e 0x82 0x9d 0xe7 0x00 0x7c 0x96 0x28 0x1d 0x20 0xf8 0x81 
> 0x02 0x7c 0xc2 0xb2 0xfa 0x43 0x90 0x6e

That doesn't seem like a zero length, what BlueZ version is this btw?

> < ACL data: handle 0 flags 0x00 dlen 9
>     ATT: Error (0x01)
>       Error: Unlikely error (14)
>       Prepare Write req (0x16) on handle 0x0069

Check what time does this error is generated, since this well be:

static bool write_timeout(void *user_data) {
    struct pending_write *p = user_data;

    p->timeout_id = 0;

    queue_remove(p->attrib->pending_writes, p);

    pending_write_result(p, -ETIMEDOUT);

    return false;
}

The -ETIMEOUT would be converted to:

static uint8_t att_ecode_from_error(int err) {
    /*
     * If the error fits in a single byte, treat it as an ATT protocol
     * error as is. Since "0" is not a valid ATT protocol error code, we map
     * that to UNLIKELY below.
     */
    if (err > 0 && err < UINT8_MAX)
        return err;

    /*
     * Since we allow UNIX errnos, map them to appropriate ATT protocol
     * and "Common Profile and Service" error codes.
     */
    switch (err) {
    case -ENOENT:
        return BT_ATT_ERROR_INVALID_HANDLE;
    case -ENOMEM:
        return BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
    case -EALREADY:
        return BT_ERROR_ALREADY_IN_PROGRESS;
    case -EOVERFLOW:
        return BT_ERROR_OUT_OF_RANGE;
    }

    return BT_ATT_ERROR_UNLIKELY;
}

So on write_timeout it would also generate the unlikely error.

Note that normally prepare write don't need authorization, but perhaps you have an application setting 'authorize':

https://urldefense.com/v3/__https://github.com/bluez/bluez/blob/master/doc/org.bluez.GattCharacteristic.rst*arraystring-flags-read-only__;Iw!!LpKI!mOAXmul0EbN_7I2R6edizAu4TW4H0BMt5s6EDMhpj23Ap8xFtV5BRjMJtpqVFcVIZQnbtBdGNs0UyAwX178$ [github[.]com], which means the following code would execute:

    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;
    }

You can also try adding passing -t -p debug to btmon so it logs the debug messages from bluetoothd and include timing information.

> > HCI Event: Number of Completed Packets (0x13) plen 5
>     handle 0 packets 1
> > ACL data: handle 0 flags 0x02 dlen 6
>     ATT: Exec Write req (0x18)
>       cancel all prepared writes (0x00) < ACL data: handle 0 flags 
> 0x00 dlen 5
>     ATT: Exec Write resp (0x19)
> > HCI Event: Number of Completed Packets (0x13) plen 5
>     handle 0 packets 1
>
> -----Original Message-----
> From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
> Sent: Tuesday, July 9, 2024 3:34 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 Tue, Jul 9, 2024 at 1:34 PM Ramsay, Trey <Trey.Ramsay@dell.com> wrote:
> >
> > 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
>
> This doesn't sound quite right, 0 length still needs to be passed to the attribute to confirm since we don't know if it could be a procedure or not. Can you explain what attribute is being written and if it could be due to the application not responding and the procedure timing out (e.g. write_timeout is called?), perhaps if you can paste a btmon trace as well that could help checking what attribute it is trying to use prepare write.
>
> > 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)) {
> >
> >
> >
> > -----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
> > /c
> > ommit/246bc960629dff34e744c728f048e9f50f1a005d__;!!LpKI!jkJYamzU8bOd
> > d1 
> > qt-sWpj6gy1YwS30UyamHLUJj9Uy0UecrB6QxvCdSWFAUH7Dvq2wVJqu1C5jjoX5amyw
> > JH
> > $ [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
> >
>
>
> --
> Luiz Augusto von Dentz
>


--
Luiz Augusto von Dentz
Luiz Augusto von Dentz July 11, 2024, 6:09 p.m. UTC | #6
Hi Trey,

On Thu, Jul 11, 2024 at 1:17 PM Ramsay, Trey <Trey.Ramsay@dell.com> wrote:
>
> Hi Luiz,
> Correct, the request is timing out.  The problem is "prep_write_complete_cb" is never getting called after the "prep_write_cb" is called.  The prep_write_complete_cb is responsible for sending the response BT_ATT_OP_PREP_WRITE_RSP back.  The patch I provided fixes the code so that prep_write_complete_cb  will get called and the response is sent back.   Sorry, I had debugged this issue a quite a while ago using bluez 5.55 and 5.66 and noticed the same issue in the master branch.  We have been using the patch and it has resolved the issue.

Well your patch is more of a workaround and in case the issue is
really the application setting 'authorize' flag the prepare write will
need to be authorized even if they are of 0 length, so it is a nack
from my side. If you think the application is responding properly then
the problem is somewhere else and in that case we probably need to
debug the code path it is taking.

> Thanks,
> Trey
>
> -----Original Message-----
> From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
> Sent: Wednesday, July 10, 2024 4:14 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 Wed, Jul 10, 2024 at 3:55 PM Ramsay, Trey <Trey.Ramsay@dell.com> wrote:
> >
> > Hi Luis,
> > It is a Prepare Write Request but prep_write_complete_cb is never getting called. In gatt_db_attribute_write, the prep_write_complete_cb function is not getting called since "attribe->write_func" is not null and the function will return "True".  The prep_write_complete_cb is supposed to get called after "goto done;" but it's not getting called.  The prep_write_complete_cb is assigned to "func".    The patch checks to see if len is 0 and will goto done which will call prep_write_complete_cb.
>
> Well if it returns true then it should not return unlikely:
>
>     status = gatt_db_attribute_write(attr, offset, NULL, 0,
>                         BT_ATT_OP_PREP_WRITE_REQ,
>                         server->att,
>                         prep_write_complete_cb, pwcd);
>
>     if (status)
>         return;
>
>     ecode = BT_ATT_ERROR_UNLIKELY;
>
> error:
>     bt_att_chan_send_error_rsp(chan, opcode, handle, ecode);
>
> >
> > > ACL data: handle 0 flags 0x01 dlen 3
> >     ATT: Prepare Write req (0x16)
> >       attr handle 0x0069, value offset 0x0000
> >       part attr value  0x80 0x02 0x00 0x01 0xaa 0xd3 0x81 0x51 0x54
> > 0x5b 0xea 0xaf 0x68 0x0d 0xeb 0xe6 0x11 0x2d 0x63 0xb1 0x8e 0xbd 0xc4
> > 0x63 0x8f 0xf6 0xb6 0x10 0x63 0xb5 0x54 0x3f 0x36 0x19 0x41 0x5b 0x25
> > 0xcd 0xa7 0xe5 0x9d 0xc7 0x71 0x26 0x33 0x7c 0xe8 0x0e 0x67 0xd8 0x9a
> > 0x0a 0xb5 0xe5 0x24 0x87 0x2d 0xcc 0x00 0xa9 0xc8 0xb8 0x95 0x76 0x75
> > 0x9f 0x79 0x1f 0x94 0xe4 0xd9 0xbe 0xab 0x22 0xa3 0x33 0x18 0x28 0x57
> > 0x26 0xae 0x6d 0x0a 0x9b 0x63 0xeb 0x10 0xf3 0xb5 0xea 0x64 0x4a 0x81
> > 0x55 0xe0 0xa9 0x43 0x8c 0x87 0xb4 0x32 0x1c 0x79 0xd6 0x34 0x97 0xff
> > 0xae 0x71 0x1e 0x50 0x7c 0xb6 0x72 0x7b 0x49 0x44 0xef 0xfe 0xe2 0x40
> > 0xc7 0x3e 0x5e 0x42 0x9b 0xca 0xa4 0x61 0x66 0x72 0x0a 0x1d 0x5c 0xb0
> > 0xdb 0xa1 0xbb 0xf7 0xb6 0x27 0xa0 0x67 0xde 0x69 0xd9 0x67 0xa7 0x09
> > 0x58 0x71 0x37 0x99 0x95 0x5c 0x5d 0x10 0x4d 0xed 0x2f 0xe2 0x85 0x6c
> > 0x03 0x60 0x80 0x67 0x25 0x1b 0x33 0x02 0x53 0xbe 0x67 0xdb 0xd4 0x2a
> > 0x9e 0x8d 0x82 0xe2 0x9d 0xc4 0x86 0x08 0x84 0x2c 0xbf 0xa5 0xc5 0xd3
> > 0x99 0xf1 0x02 0x09 0x80 0x0c 0xc5 0xf9 0x99 0x06 0x20 0x01 0x75 0xdb
> > 0x0c 0x11 0x81 0x87 0x04 0x4d 0xf0 0xcc 0xf7 0x27 0x85 0xcd 0x22 0x84
> > 0x85 0x04 0xb3 0xa2 0xa9 0xcc 0xe9 0x27 0x8b 0x67 0x02 0x1b 0xe0 0x8c
> > 0xd7 0x8f 0x51 0x3a 0xa6 0x0c 0x23 0xa0 0x09 0x2b 0x4c 0xb0 0x80 0x34
> > 0xf9 0x61 0xaa 0x72 0x90 0x3a 0x5e 0xb7 0x11 0xaf 0xc3 0xcd 0x78 0x4f
> > 0xb6 0x1b 0xbb 0xb4 0xb2 0x42 0x9f 0x87 0xad 0xf6 0xa1 0xae 0xdd 0xde
> > 0x38 0x09 0x7a 0xc5 0x7c 0xbd 0x98 0x89 0xae 0x49 0x98 0xe7 0xae 0x92
> > 0x28 0x45 0x5a 0xbc 0x30 0x53 0xe5 0xc1 0x56 0xb3 0x9f 0x56 0x7b 0xa1
> > 0x02 0xcd 0xc2 0x25 0x2a 0xb2 0xc5 0xc9 0x35 0xec 0xa7 0x26 0x79 0x97
> > 0x2e 0x96 0x97 0x3e 0x5b 0x8f 0xc7 0x2f 0xa8 0x39 0x70 0xb1 0x22 0x5b
> > 0x2c 0x15 0x41 0xec 0x6b 0xc4 0x1e 0x2d 0xc0 0x47 0x75 0x42 0x01 0x40
> > 0xc5 0x17 0x69 0xf4 0x0a 0xcd 0x7e 0x62 0x25 0xec 0x1f 0x7c 0xae 0x7b
> > 0xf9 0x1e 0x9f 0x98 0xbd 0xc7 0xc3 0x44 0x4c 0xe2 0x0a 0x8c 0xbe 0xeb
> > 0x1e 0xae 0x7b 0xbc 0x49 0xfa 0x7d 0xa3 0xdf 0xb2 0xc0 0x69 0xf7 0x57
> > 0x6b 0x6f 0xe7 0x2e 0x3c 0x90 0x0a 0x16 0xe8 0x03 0x0d 0xf1 0x9c 0x4c
> > 0xa3 0x4b 0xcf 0x6d 0xc3 0x4a 0x69 0x25 0xc5 0xf6 0x9c 0x4b 0xb3 0x77
> > 0x67 0x7b 0x00 0xbb 0x1f 0xcd 0x59 0xb0 0xe9 0xf6 0xbe 0xa3 0x41 0xd1
> > 0x2c 0x1f 0x09 0x6b 0x4e 0x52 0x01 0x0c 0xe1 0x20 0x6c 0x76 0xfd 0xc9
> > 0xb9 0xb4 0xd8 0xdf 0xcb 0xac 0x77 0x65 0xcd 0x98 0xe9 0x66 0x6c 0xc8
> > 0x8f 0xfc 0xef 0x7e 0x48 0x9f 0xc8 0xd6 0x9c 0x72 0xac 0x44 0xa3 0x67
> > 0xa3 0x6a 0xe3 0xde 0x3a 0xd5 0x21 0x94 0x29 0x94 0x3d 0x7b 0x88 0x29
> > 0xc3 0xc2 0x7e 0x82 0x9d 0xe7 0x00 0x7c 0x96 0x28 0x1d 0x20 0xf8 0x81
> > 0x02 0x7c 0xc2 0xb2 0xfa 0x43 0x90 0x6e
>
> That doesn't seem like a zero length, what BlueZ version is this btw?
>
> > < ACL data: handle 0 flags 0x00 dlen 9
> >     ATT: Error (0x01)
> >       Error: Unlikely error (14)
> >       Prepare Write req (0x16) on handle 0x0069
>
> Check what time does this error is generated, since this well be:
>
> static bool write_timeout(void *user_data) {
>     struct pending_write *p = user_data;
>
>     p->timeout_id = 0;
>
>     queue_remove(p->attrib->pending_writes, p);
>
>     pending_write_result(p, -ETIMEDOUT);
>
>     return false;
> }
>
> The -ETIMEOUT would be converted to:
>
> static uint8_t att_ecode_from_error(int err) {
>     /*
>      * If the error fits in a single byte, treat it as an ATT protocol
>      * error as is. Since "0" is not a valid ATT protocol error code, we map
>      * that to UNLIKELY below.
>      */
>     if (err > 0 && err < UINT8_MAX)
>         return err;
>
>     /*
>      * Since we allow UNIX errnos, map them to appropriate ATT protocol
>      * and "Common Profile and Service" error codes.
>      */
>     switch (err) {
>     case -ENOENT:
>         return BT_ATT_ERROR_INVALID_HANDLE;
>     case -ENOMEM:
>         return BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
>     case -EALREADY:
>         return BT_ERROR_ALREADY_IN_PROGRESS;
>     case -EOVERFLOW:
>         return BT_ERROR_OUT_OF_RANGE;
>     }
>
>     return BT_ATT_ERROR_UNLIKELY;
> }
>
> So on write_timeout it would also generate the unlikely error.
>
> Note that normally prepare write don't need authorization, but perhaps you have an application setting 'authorize':
>
> https://urldefense.com/v3/__https://github.com/bluez/bluez/blob/master/doc/org.bluez.GattCharacteristic.rst*arraystring-flags-read-only__;Iw!!LpKI!mOAXmul0EbN_7I2R6edizAu4TW4H0BMt5s6EDMhpj23Ap8xFtV5BRjMJtpqVFcVIZQnbtBdGNs0UyAwX178$ [github[.]com], which means the following code would execute:
>
>     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;
>     }
>
> You can also try adding passing -t -p debug to btmon so it logs the debug messages from bluetoothd and include timing information.
>
> > > HCI Event: Number of Completed Packets (0x13) plen 5
> >     handle 0 packets 1
> > > ACL data: handle 0 flags 0x02 dlen 6
> >     ATT: Exec Write req (0x18)
> >       cancel all prepared writes (0x00) < ACL data: handle 0 flags
> > 0x00 dlen 5
> >     ATT: Exec Write resp (0x19)
> > > HCI Event: Number of Completed Packets (0x13) plen 5
> >     handle 0 packets 1
> >
> > -----Original Message-----
> > From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
> > Sent: Tuesday, July 9, 2024 3:34 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 Tue, Jul 9, 2024 at 1:34 PM Ramsay, Trey <Trey.Ramsay@dell.com> wrote:
> > >
> > > 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
> >
> > This doesn't sound quite right, 0 length still needs to be passed to the attribute to confirm since we don't know if it could be a procedure or not. Can you explain what attribute is being written and if it could be due to the application not responding and the procedure timing out (e.g. write_timeout is called?), perhaps if you can paste a btmon trace as well that could help checking what attribute it is trying to use prepare write.
> >
> > > 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)) {
> > >
> > >
> > >
> > > -----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
> > > /c
> > > ommit/246bc960629dff34e744c728f048e9f50f1a005d__;!!LpKI!jkJYamzU8bOd
> > > d1
> > > qt-sWpj6gy1YwS30UyamHLUJj9Uy0UecrB6QxvCdSWFAUH7Dvq2wVJqu1C5jjoX5amyw
> > > JH
> > > $ [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
> > >
> >
> >
> > --
> > Luiz Augusto von Dentz
> >
>
>
> --
> Luiz Augusto von Dentz
Ramsay, Trey July 11, 2024, 8:14 p.m. UTC | #7
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);
}




Internal Use - Confidential
-----Original Message-----
From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Sent: Thursday, July 11, 2024 1:10 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 1:17 PM Ramsay, Trey <Trey.Ramsay@dell.com> wrote:
>
> Hi Luiz,
> Correct, the request is timing out.  The problem is "prep_write_complete_cb" is never getting called after the "prep_write_cb" is called.  The prep_write_complete_cb is responsible for sending the response BT_ATT_OP_PREP_WRITE_RSP back.  The patch I provided fixes the code so that prep_write_complete_cb  will get called and the response is sent back.   Sorry, I had debugged this issue a quite a while ago using bluez 5.55 and 5.66 and noticed the same issue in the master branch.  We have been using the patch and it has resolved the issue.

Well your patch is more of a workaround and in case the issue is really the application setting 'authorize' flag the prepare write will need to be authorized even if they are of 0 length, so it is a nack from my side. If you think the application is responding properly then the problem is somewhere else and in that case we probably need to debug the code path it is taking.

> Thanks,
> Trey
>
> -----Original Message-----
> From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
> Sent: Wednesday, July 10, 2024 4:14 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 Wed, Jul 10, 2024 at 3:55 PM Ramsay, Trey <Trey.Ramsay@dell.com> wrote:
> >
> > Hi Luis,
> > It is a Prepare Write Request but prep_write_complete_cb is never getting called. In gatt_db_attribute_write, the prep_write_complete_cb function is not getting called since "attribe->write_func" is not null and the function will return "True".  The prep_write_complete_cb is supposed to get called after "goto done;" but it's not getting called.  The prep_write_complete_cb is assigned to "func".    The patch checks to see if len is 0 and will goto done which will call prep_write_complete_cb.
>
> Well if it returns true then it should not return unlikely:
>
>     status = gatt_db_attribute_write(attr, offset, NULL, 0,
>                         BT_ATT_OP_PREP_WRITE_REQ,
>                         server->att,
>                         prep_write_complete_cb, pwcd);
>
>     if (status)
>         return;
>
>     ecode = BT_ATT_ERROR_UNLIKELY;
>
> error:
>     bt_att_chan_send_error_rsp(chan, opcode, handle, ecode);
>
> >
> > > ACL data: handle 0 flags 0x01 dlen 3
> >     ATT: Prepare Write req (0x16)
> >       attr handle 0x0069, value offset 0x0000
> >       part attr value  0x80 0x02 0x00 0x01 0xaa 0xd3 0x81 0x51 0x54
> > 0x5b 0xea 0xaf 0x68 0x0d 0xeb 0xe6 0x11 0x2d 0x63 0xb1 0x8e 0xbd
> > 0xc4
> > 0x63 0x8f 0xf6 0xb6 0x10 0x63 0xb5 0x54 0x3f 0x36 0x19 0x41 0x5b
> > 0x25 0xcd 0xa7 0xe5 0x9d 0xc7 0x71 0x26 0x33 0x7c 0xe8 0x0e 0x67
> > 0xd8 0x9a 0x0a 0xb5 0xe5 0x24 0x87 0x2d 0xcc 0x00 0xa9 0xc8 0xb8
> > 0x95 0x76 0x75 0x9f 0x79 0x1f 0x94 0xe4 0xd9 0xbe 0xab 0x22 0xa3
> > 0x33 0x18 0x28 0x57
> > 0x26 0xae 0x6d 0x0a 0x9b 0x63 0xeb 0x10 0xf3 0xb5 0xea 0x64 0x4a
> > 0x81
> > 0x55 0xe0 0xa9 0x43 0x8c 0x87 0xb4 0x32 0x1c 0x79 0xd6 0x34 0x97
> > 0xff 0xae 0x71 0x1e 0x50 0x7c 0xb6 0x72 0x7b 0x49 0x44 0xef 0xfe
> > 0xe2 0x40
> > 0xc7 0x3e 0x5e 0x42 0x9b 0xca 0xa4 0x61 0x66 0x72 0x0a 0x1d 0x5c
> > 0xb0 0xdb 0xa1 0xbb 0xf7 0xb6 0x27 0xa0 0x67 0xde 0x69 0xd9 0x67
> > 0xa7 0x09
> > 0x58 0x71 0x37 0x99 0x95 0x5c 0x5d 0x10 0x4d 0xed 0x2f 0xe2 0x85
> > 0x6c
> > 0x03 0x60 0x80 0x67 0x25 0x1b 0x33 0x02 0x53 0xbe 0x67 0xdb 0xd4
> > 0x2a 0x9e 0x8d 0x82 0xe2 0x9d 0xc4 0x86 0x08 0x84 0x2c 0xbf 0xa5
> > 0xc5 0xd3
> > 0x99 0xf1 0x02 0x09 0x80 0x0c 0xc5 0xf9 0x99 0x06 0x20 0x01 0x75
> > 0xdb 0x0c 0x11 0x81 0x87 0x04 0x4d 0xf0 0xcc 0xf7 0x27 0x85 0xcd
> > 0x22 0x84
> > 0x85 0x04 0xb3 0xa2 0xa9 0xcc 0xe9 0x27 0x8b 0x67 0x02 0x1b 0xe0
> > 0x8c
> > 0xd7 0x8f 0x51 0x3a 0xa6 0x0c 0x23 0xa0 0x09 0x2b 0x4c 0xb0 0x80
> > 0x34
> > 0xf9 0x61 0xaa 0x72 0x90 0x3a 0x5e 0xb7 0x11 0xaf 0xc3 0xcd 0x78
> > 0x4f
> > 0xb6 0x1b 0xbb 0xb4 0xb2 0x42 0x9f 0x87 0xad 0xf6 0xa1 0xae 0xdd
> > 0xde
> > 0x38 0x09 0x7a 0xc5 0x7c 0xbd 0x98 0x89 0xae 0x49 0x98 0xe7 0xae
> > 0x92
> > 0x28 0x45 0x5a 0xbc 0x30 0x53 0xe5 0xc1 0x56 0xb3 0x9f 0x56 0x7b
> > 0xa1
> > 0x02 0xcd 0xc2 0x25 0x2a 0xb2 0xc5 0xc9 0x35 0xec 0xa7 0x26 0x79
> > 0x97 0x2e 0x96 0x97 0x3e 0x5b 0x8f 0xc7 0x2f 0xa8 0x39 0x70 0xb1
> > 0x22 0x5b 0x2c 0x15 0x41 0xec 0x6b 0xc4 0x1e 0x2d 0xc0 0x47 0x75
> > 0x42 0x01 0x40
> > 0xc5 0x17 0x69 0xf4 0x0a 0xcd 0x7e 0x62 0x25 0xec 0x1f 0x7c 0xae
> > 0x7b
> > 0xf9 0x1e 0x9f 0x98 0xbd 0xc7 0xc3 0x44 0x4c 0xe2 0x0a 0x8c 0xbe
> > 0xeb 0x1e 0xae 0x7b 0xbc 0x49 0xfa 0x7d 0xa3 0xdf 0xb2 0xc0 0x69
> > 0xf7 0x57 0x6b 0x6f 0xe7 0x2e 0x3c 0x90 0x0a 0x16 0xe8 0x03 0x0d
> > 0xf1 0x9c 0x4c
> > 0xa3 0x4b 0xcf 0x6d 0xc3 0x4a 0x69 0x25 0xc5 0xf6 0x9c 0x4b 0xb3
> > 0x77
> > 0x67 0x7b 0x00 0xbb 0x1f 0xcd 0x59 0xb0 0xe9 0xf6 0xbe 0xa3 0x41
> > 0xd1 0x2c 0x1f 0x09 0x6b 0x4e 0x52 0x01 0x0c 0xe1 0x20 0x6c 0x76
> > 0xfd 0xc9
> > 0xb9 0xb4 0xd8 0xdf 0xcb 0xac 0x77 0x65 0xcd 0x98 0xe9 0x66 0x6c
> > 0xc8 0x8f 0xfc 0xef 0x7e 0x48 0x9f 0xc8 0xd6 0x9c 0x72 0xac 0x44
> > 0xa3 0x67
> > 0xa3 0x6a 0xe3 0xde 0x3a 0xd5 0x21 0x94 0x29 0x94 0x3d 0x7b 0x88
> > 0x29
> > 0xc3 0xc2 0x7e 0x82 0x9d 0xe7 0x00 0x7c 0x96 0x28 0x1d 0x20 0xf8
> > 0x81
> > 0x02 0x7c 0xc2 0xb2 0xfa 0x43 0x90 0x6e
>
> That doesn't seem like a zero length, what BlueZ version is this btw?
>
> > < ACL data: handle 0 flags 0x00 dlen 9
> >     ATT: Error (0x01)
> >       Error: Unlikely error (14)
> >       Prepare Write req (0x16) on handle 0x0069
>
> Check what time does this error is generated, since this well be:
>
> static bool write_timeout(void *user_data) {
>     struct pending_write *p = user_data;
>
>     p->timeout_id = 0;
>
>     queue_remove(p->attrib->pending_writes, p);
>
>     pending_write_result(p, -ETIMEDOUT);
>
>     return false;
> }
>
> The -ETIMEOUT would be converted to:
>
> static uint8_t att_ecode_from_error(int err) {
>     /*
>      * If the error fits in a single byte, treat it as an ATT protocol
>      * error as is. Since "0" is not a valid ATT protocol error code, we map
>      * that to UNLIKELY below.
>      */
>     if (err > 0 && err < UINT8_MAX)
>         return err;
>
>     /*
>      * Since we allow UNIX errnos, map them to appropriate ATT protocol
>      * and "Common Profile and Service" error codes.
>      */
>     switch (err) {
>     case -ENOENT:
>         return BT_ATT_ERROR_INVALID_HANDLE;
>     case -ENOMEM:
>         return BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
>     case -EALREADY:
>         return BT_ERROR_ALREADY_IN_PROGRESS;
>     case -EOVERFLOW:
>         return BT_ERROR_OUT_OF_RANGE;
>     }
>
>     return BT_ATT_ERROR_UNLIKELY;
> }
>
> So on write_timeout it would also generate the unlikely error.
>
> Note that normally prepare write don't need authorization, but perhaps you have an application setting 'authorize':
>
> https://urldefense.com/v3/__https://github.com/bluez/bluez/blob/master/doc/org.bluez.GattCharacteristic.rst*arraystring-flags-read-only__;Iw!!LpKI!mOAXmul0EbN_7I2R6edizAu4TW4H0BMt5s6EDMhpj23Ap8xFtV5BRjMJtpqVFcVIZQnbtBdGNs0UyAwX178$ [github[.]com], which means the following code would execute:
>
>     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;
>     }
>
> You can also try adding passing -t -p debug to btmon so it logs the debug messages from bluetoothd and include timing information.
>
> > > HCI Event: Number of Completed Packets (0x13) plen 5
> >     handle 0 packets 1
> > > ACL data: handle 0 flags 0x02 dlen 6
> >     ATT: Exec Write req (0x18)
> >       cancel all prepared writes (0x00) < ACL data: handle 0 flags
> > 0x00 dlen 5
> >     ATT: Exec Write resp (0x19)
> > > HCI Event: Number of Completed Packets (0x13) plen 5
> >     handle 0 packets 1
> >
> > -----Original Message-----
> > From: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
> > Sent: Tuesday, July 9, 2024 3:34 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 Tue, Jul 9, 2024 at 1:34 PM Ramsay, Trey <Trey.Ramsay@dell.com> wrote:
> > >
> > > 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
> >
> > This doesn't sound quite right, 0 length still needs to be passed to the attribute to confirm since we don't know if it could be a procedure or not. Can you explain what attribute is being written and if it could be due to the application not responding and the procedure timing out (e.g. write_timeout is called?), perhaps if you can paste a btmon trace as well that could help checking what attribute it is trying to use prepare write.
> >
> > > 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)) {
> > >
> > >
> > >
> > > -----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-trams
> > > ay
> > > /c
> > > ommit/246bc960629dff34e744c728f048e9f50f1a005d__;!!LpKI!jkJYamzU8b
> > > Od
> > > d1
> > > qt-sWpj6gy1YwS30UyamHLUJj9Uy0UecrB6QxvCdSWFAUH7Dvq2wVJqu1C5jjoX5am
> > > yw
> > > JH
> > > $ [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
> > >
> >
> >
> > --
> > Luiz Augusto von Dentz
> >
>
>
> --
> Luiz Augusto von Dentz



--
Luiz Augusto von Dentz
Luiz Augusto von Dentz July 11, 2024, 8:52 p.m. UTC | #8
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.
Ramsay, Trey July 12, 2024, 4:42 p.m. UTC | #9
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

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

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.
Luiz Augusto von Dentz July 12, 2024, 5:41 p.m. UTC | #10
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)) {