Do i need to register separate callbacks for each service / characteristic ?

Hello,

I am using PAN1026 and download BT_SDK_v_4_2_0. As the communication between application and SDK happens through callbacks (for notifying, indicating, write, read etc). I saw that each profile has its own callbacks registered.

So if I add some custom services/characteristics, should I register separate callbacks for each service/characteristic? 

Should each profile use separate callback for data communication?

Is it not possible to use the same callback for all profiles? As writing callback for each profile will be a lengthy process.

I will thankful for your guidance.

Regards

4replies Oldest first
  • Oldest first
  • Newest first
  • Active threads
  • Popular
  • If I use the same callback for more than one characteristics then how I will come to know that which characteristic has triggered the callback?

    Like
  • So if I add some custom services/characteristics, should I register separate callbacks for each service/characteristic?

    I would say yes!

    Is it not possible to use the same callback for all profiles? As writing callback for each profile will be a lengthy process.

    It is possible to share callback functions as long as they have the same signature, ie. return value and same number and types of parameters.

    However when you leave callback functions completely empty, some compilers / linkers will notice that and not generate code for these empty functions at all.

    If I use the same callback for more than one characteristics then how I will come to know that which characteristic has triggered the callback?

    It is not possible to distinguish the callback functions any more when you use the same function.

    In any case: all these callback functions actually serve a purpose, so I would suggest to carefully think about the necessary implementation.

    For example: If your characteristic has the read property, the read callback function must return a pointer to the value that should be sent back. If it has the indicate property, it might return the same pointer or a different one, depending on the use case.

    For the write property, the prepare callback can be used if a write is allowed at all and return an error early, before the final write is really done.

    Error handling is especially important and for that you usuallly cannot share the implementation for different characteristics.

    So the recommondation is clearly to implement all necessary callback functions uniquely and then think about the necessary handling, especially when something should not be allowed, is out of range or similar.

    Like
  • Does SDK allow to change the signature of the callback?
    for example in 

    ble_api_server.h

    in
    struct ble_api_srv_characteristic_value


     enum tcu_le_gatt_status (*write)(uint8_t *value, uint16_t length, uint16_t connection_handle);             /*!< characteristic value write */

    to 

     enum tcu_le_gatt_status (*write)(uint16_t shortUUID, uint8_t *value, uint16_t length, uint16_t connection_handle);             /*!< characteristic value write */

    Then based on shortUUID i will be able to distinguish upon which characteristic the value is written.

    Our application will have 4 services and about 8 characteristics. If will start defined the unique callbacks for them, it will increase complexity.
     

    Like
  • Does SDK allow to change the signature of the callback?

    Then based on shortUUID i will be able to distinguish upon which characteristic the value is written.

    Feel free to modify your version of the Bluetooth SDK and make it work as you need it to. The only downside is that you need to carry over the changes if a new version is released.

    Our application will have 4 services and about 8 characteristics. If will start defined the unique callbacks for them, it will increase complexity.

    What is the difference between

    void callback_1(void) {
      /* do work for callback 1 */
    }
    void callback_2(void) {
      /* do work for callback 2 */
    }
    

    and

    void callback(int uuid) {
      if (uuid == UUID_1) {
        /* do work for callback 1 */
      } else if (uuid == UUID_2) {
        /* do work for callback 2 */
      }
    }
    

    In my opinion the upper code is cleaner and less complex because it separates the functionality cleanly into separate functions, whereas the lower code is more complex because it mixes everything together.

    If you like the lower code example better, however, you could even do something like this, then you don't need to modify the SDK...

    static void callback(int uuid) {
      if (uuid == UUID_1) {
        /* do work for callback 1 */
      } else if (uuid == UUID_2) {
        /* do work for callback 2 */
      }
    }
    void callback_1(void) {
      callback(UUID_1);
    }
    void callback_2(void) {
      callback(UUID_2);
    }
    
    Like
Like Follow
  • Status Answered
  • 1 yr agoLast active
  • 4Replies
  • 55Views
  • 3 Following