A bug on 920736_LE board

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

Hello,

I have created a simple BLE application called demo, by way of the WICED IDE wizard, with one characteristics, 15 bytes, with notify/read/write properties.

This is the code that the wizard has generated, the following:

<pre>

CHARACTERISTIC_UUID128_WRITABLE (HDLC_DEMO_CHREGISTERHS,

            HDLC_DEMO_CHREGISTERHS_VALUE,

            __UUID_DEMO_CHREGISTERHS,

            LEGATTDB_CHAR_PROP_READ | LEGATTDB_CHAR_PROP_WRITE,

            LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_REQ,

            15),

            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

            /* Characteristic User Description Descriptor */

            //<UserDescription>

            //<Value>Host To Sensor</Value>

            CHAR_DESCRIPTOR_UUID16 (HDLD_DEMO_CHREGISTERHS_USER_DESCRIPTION,

                UUID_DESCRIPTOR_CHARACTERISTIC_USER_DESCRIPTION,

                LEGATTDB_PERM_READABLE, 14),

                //UTF-8 <User Description> Host To Sensor

                'H','o','s','t',' ','T','o',' ','S','e','n','s','o','r',

</pre>

The generated code with additions in there commented out for this purpose:

<pre>

BOOL store_in_db_demo_chregisterhs(UINT8* p_value, UINT8 value_len)

{

    BLEPROFILE_DB_PDU db_pdu;

//    memset(&db_pdu.pdu[0], 0x0, 15); // Ensure we wipe the data first!!!!!

//    db_pdu.len = 15;

//    bleprofile_WriteHandle(HDLC_DEMO_CHREGISTERHS_VALUE, &db_pdu);

    // Write value to the GATT DB

    ble_trace2("write len:%d handle:%02x", value_len, HDLC_DEMO_CHREGISTERHS_VALUE);

    memcpy(&db_pdu.pdu[0], p_value, value_len);

    db_pdu.len = value_len;

    bleprofile_WriteHandle(HDLC_DEMO_CHREGISTERHS_VALUE, &db_pdu);

    return TRUE;

}

</pre>

It was during testing using LightBlue on iOS, I can see, that writing this, 'A','B','C','D','E','F','G','H','I','J', 'K' gets stored good and verified, all 11 bytes.

On the next update of characteristic, I write this, 'Z','Y','X','W','V','U','T','S','R', all 10 bytes.

What surprised me was that the actual value stored was this:

'Z','Y','X','W','V','U','T','S','R','K'

By uncommenting the portion of the code that is in place, one would suspect that the value would be cleanly resetted with zero bytes.

I get the same results.

Can anyone shed light on this?

1 Solution
Anonymous
Not applicable

Hello again.

I looked at the code and ran the application myself.

I found out that what you are trying to do is not supported by our stack, and we confirmed it with the developers.

Let me explain.

When LightBlue writes something to the characteristic value, it writes to the GATT database. Then your application gets a callback handled by the write_handle function. The thing is the writing to the GATT database is done by the stack and you don't have any control of it. It supports variable length writes, which means when you write 10 bytes, only the first 10 bytes get changed and the rest stay the same. If you want to change the whole characteristic value, resetting the previous value, you must write the whole max length of the characteristic. That means if you want to overwrite 'A','B','C','D','E','F','G','H','I','J', 'K', you must write 'Z','Y','X','W','V','U','T','S','R',' '.

I also want to comment on the source code.

The two functions generated by the wizard:

store_in_db_demo_chregisterhs and store_in_db_demo_charegisterhs

never get called in the application unless you make the call yourself.

So if you want to use these functions, you must make a function call, probably in the write_handle function.

In the source code that you posted, you've never called these functions, so they were not being used in the app.

However, even if the functions were used, they wouldn't have solved your problem because of the reason I mentioned above.

I hope this helped.

Please let us know if you have any other questions.

Thank you.

James

View solution in original post

0 Likes
8 Replies
JacobT_81
Employee
Employee
250 replies posted 100 replies posted 50 replies posted

When you send a notification or read a characteristic, you read the whole thing no matter what. The 'K' appears at the end of the second read because it was never overwritten after being stored in the characteristic the first time. In order to not see this 'K," you must overwrite with a blank space.

Jacob

0 Likes
Anonymous
Not applicable

jakewtorres

From the portion of the code that was commented out, get the same results which is the point I am conveying, it did not matter despite calling memset to scratch the buffer  prior to writing it out.

BOOL store_in_db_demo_chregisterhs(UINT8* p_value, UINT8 value_len)

{

    BLEPROFILE_DB_PDU db_pdu;

    memset(&db_pdu.pdu[0], 0x0, 15); // Ensure we wipe the data first!!!!!

    db_pdu.len = 15;

    bleprofile_WriteHandle(HDLC_DEMO_CHREGISTERHS_VALUE, &db_pdu);

    // Write value to the GATT DB

    ble_trace2("write len:%d handle:%02x", value_len, HDLC_DEMO_CHREGISTERHS_VALUE);

    memcpy(&db_pdu.pdu[0], p_value, value_len);

    db_pdu.len = value_len;

    bleprofile_WriteHandle(HDLC_DEMO_CHREGISTERHS_VALUE, &db_pdu);

    return TRUE;

}

Am I missing something? Why space?

0 Likes

I've run into problems with memset() myself. Try running a for loop to zero everything out instead. Let me know how it goes.

Jacob

0 Likes
Anonymous
Not applicable

Hello.

Try to print out what value_len is.

If value_len is 10 bytes then doesn't matter how many bytes you are setting it to 0x0,

because you are only writing the first 10 bytes. In your case, it would be 'Z','Y','X','W','V','U','T','S','R'.

Then the 11th byte and beyond will not be overwritten.

If this is the case, instead of doing

dp_pdu.len = value_len;

try just leaving it alone, because you already changed it to 15 earlier.

* Side notes:

Here is something that you should be familiar in C : Array variable holds pointer to the first element of the array.

So db_pdu.pdu is equal to &db_pdu.pdu[0]. Use the formal instead of the latter.

For example, memcpy(db_pdu.pdu, p_value, value_len);

Revised code:

BOOL store_in_db_demo_chregisterhs(UINT8* p_value, UINT8 value_len)

{

    BLEPROFILE_DB_PDU db_pdu;

  
    // Write value to the GATT DB

    ble_trace2("write len:%d handle:%02x", value_len, HDLC_DEMO_CHREGISTERHS_VALUE);

    

    db_pdu.len = 15;

    memset(db_pdu.pdu, 0x0, 15); // Ensure we wipe the data first!!!!!

  

    // bleprofile_WriteHandle(HDLC_DEMO_CHREGISTERHS_VALUE, &db_pdu); // unnecessary overhead

    memcpy(db_pdu.pdu, p_value, value_len);

    bleprofile_WriteHandle(HDLC_DEMO_CHREGISTERHS_VALUE, &db_pdu);

  

    return TRUE;

}

Please tell us if this helped. Thank you.

James

0 Likes
Anonymous
Not applicable

jamesle1

That did not make a difference, unfortunately.


Even, writing a string value that is longer by a byte or two, the value from the previous write, is retained and becomes part of the new value.

That is the issue, regardless of the bytes being zeroed out. I will gladly attach the project for anyone to try out to confirm this.

I am familiar with the concept of arrays decaying into pointers of type T.


0 Likes
Anonymous
Not applicable

Sure. I'll look into the project if you attach it.

How and where are you calling your function?

Does it happen in the write_handle function?

I'm trying see the big picture.

James

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Hi jamesle1

Many thanks for your assistance, it would be greatly appreciated.

I have attached the demo project.

Kind regards,

Tom.

0 Likes
Anonymous
Not applicable

Hello again.

I looked at the code and ran the application myself.

I found out that what you are trying to do is not supported by our stack, and we confirmed it with the developers.

Let me explain.

When LightBlue writes something to the characteristic value, it writes to the GATT database. Then your application gets a callback handled by the write_handle function. The thing is the writing to the GATT database is done by the stack and you don't have any control of it. It supports variable length writes, which means when you write 10 bytes, only the first 10 bytes get changed and the rest stay the same. If you want to change the whole characteristic value, resetting the previous value, you must write the whole max length of the characteristic. That means if you want to overwrite 'A','B','C','D','E','F','G','H','I','J', 'K', you must write 'Z','Y','X','W','V','U','T','S','R',' '.

I also want to comment on the source code.

The two functions generated by the wizard:

store_in_db_demo_chregisterhs and store_in_db_demo_charegisterhs

never get called in the application unless you make the call yourself.

So if you want to use these functions, you must make a function call, probably in the write_handle function.

In the source code that you posted, you've never called these functions, so they were not being used in the app.

However, even if the functions were used, they wouldn't have solved your problem because of the reason I mentioned above.

I hope this helped.

Please let us know if you have any other questions.

Thank you.

James

0 Likes