<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>CUSTOM BLE SERVICE : READ WRITE RESPONSE</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/61986/custom-ble-service-read-write-response</link><description>Hi, I am creating custom ble service.there i need to perform 
 1. character - READ , NOTIF 
 2. character - WRITE READ 
 3 . character - READ,WRITE, NOTIF 
 
 I achieved - WRITE. but i am unable to read the response 
 Here i upload the example code that</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Wed, 10 Jun 2020 10:02:32 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/61986/custom-ble-service-read-write-response" /><item><title>RE: CUSTOM BLE SERVICE : READ WRITE RESPONSE</title><link>https://devzone.nordicsemi.com/thread/254206?ContentTypeID=1</link><pubDate>Wed, 10 Jun 2020 10:02:32 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c33a5742-b390-4524-b08e-ef89646aebfb</guid><dc:creator>Hung Bui</dc:creator><description>&lt;p&gt;&lt;a href="http://www.theunixschool.com/2010/05/how-to-use-extern-variable-in-c.html"&gt;http://www.theunixschool.com/2010/05/how-to-use-extern-variable-in-c.html&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: CUSTOM BLE SERVICE : READ WRITE RESPONSE</title><link>https://devzone.nordicsemi.com/thread/254142?ContentTypeID=1</link><pubDate>Wed, 10 Jun 2020 05:52:31 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e7191642-6049-457e-a6c9-0d91a260dc64</guid><dc:creator>Sunil vignesh</dc:creator><description>&lt;p&gt;yes, that is the case. can yu give me an example&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: CUSTOM BLE SERVICE : READ WRITE RESPONSE</title><link>https://devzone.nordicsemi.com/thread/254067?ContentTypeID=1</link><pubDate>Tue, 09 Jun 2020 14:00:45 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:2112e936-a843-4cfc-a477-342d2277aae7</guid><dc:creator>Hung Bui</dc:creator><description>&lt;p&gt;Are you sharing the same variable between different C files ?&amp;nbsp;&lt;br /&gt;If it&amp;#39;s the case you need to use extern when you refer to a variable initialized in other file.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: CUSTOM BLE SERVICE : READ WRITE RESPONSE</title><link>https://devzone.nordicsemi.com/thread/253119?ContentTypeID=1</link><pubDate>Wed, 03 Jun 2020 18:29:37 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:881ef26c-3a5d-4a1f-895a-da3fd4a48def</guid><dc:creator>Sunil vignesh</dc:creator><description>&lt;p&gt;Ok, If in that case. I have main.c and drv_motion.c file and ble_motion.h&lt;/p&gt;
&lt;p&gt;in drv_motion.c file&lt;/p&gt;
&lt;p&gt;public variable&lt;/p&gt;
&lt;p&gt;static ble_motion_init_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; motion_init;&lt;/p&gt;
&lt;p&gt;and i process the data. anywhere in the .c file i am able to print or read the perfect variable.&lt;/p&gt;
&lt;p&gt;but same public variable declare in main.c file&lt;/p&gt;
&lt;p&gt;it repeats zero.&lt;/p&gt;
&lt;p&gt;eg:&lt;/p&gt;
&lt;p&gt;in drv_motion.c&lt;/p&gt;
&lt;p&gt;motion_init.init_train.training value = 5;&lt;/p&gt;
&lt;p&gt;anf it prints&amp;nbsp; value 5;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;but in same method at same time of drv_motion.c prints from main.c file also doing print&lt;/p&gt;
&lt;p&gt;static ble_motion_init_t&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; b_motion_i;&lt;/p&gt;
&lt;p&gt;when prints it shows 0.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: CUSTOM BLE SERVICE : READ WRITE RESPONSE</title><link>https://devzone.nordicsemi.com/thread/252930?ContentTypeID=1</link><pubDate>Wed, 03 Jun 2020 09:06:23 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:0c204af9-4862-4d5c-9387-5a76d4518fbd</guid><dc:creator>Hung Bui</dc:creator><description>&lt;p&gt;Maybe you need to use static variable ? or public variable ? The way you defined&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp;ble_motion_init_t&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;motion_init;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;it&amp;#39;s a local variable and will be discarded after&amp;nbsp;service_init() finishes.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: CUSTOM BLE SERVICE : READ WRITE RESPONSE</title><link>https://devzone.nordicsemi.com/thread/252883?ContentTypeID=1</link><pubDate>Wed, 03 Jun 2020 04:18:30 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:ad3a81c8-0bf6-4d23-bb75-a66c43411ba7</guid><dc:creator>Sunil vignesh</dc:creator><description>&lt;p&gt;Hi Hung,&lt;/p&gt;
&lt;p&gt;Ok , I will tried this&lt;/p&gt;
&lt;p&gt;&amp;quot;BLE_GAP_CONN_SEC_MODE_SET_OPEN(&amp;amp;attr_md.read_perm);&lt;br /&gt; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&amp;amp;attr_md.write_perm);&amp;nbsp;&amp;quot;&amp;nbsp;&amp;nbsp; its working but&lt;/p&gt;
&lt;p&gt;i received &lt;strong&gt;&amp;quot;ldr r3, [pc, #4] &amp;quot; &lt;/strong&gt;while i force to write the data.&lt;/p&gt;
&lt;p&gt;I received this error while&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;if ( valid_data )
            {
               p_motion-&amp;gt;calib_write_handler(p_motion,(ble_calibrate_t *)p_evt_rw_authorize_request-&amp;gt;request.write.data);
            }&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;But when i use these line it doesn&amp;#39;t entered into the &lt;strong&gt;calib_write_handler &lt;/strong&gt; it means that calib_write_handler is NULL. how to make this as not equal to NULL.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;if ( valid_data &amp;amp;&amp;amp; (p_motion-&amp;gt;calib_write_handler != NULL))
            {
               p_motion-&amp;gt;calib_write_handler(p_motion,(ble_calibrate_t *)p_evt_rw_authorize_request-&amp;gt;request.write.data);
            }&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;the respective code sequence is below&lt;/p&gt;
&lt;p&gt;ble_motion.c&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;...
....


static void on_authorize_req(ble_motion_t * p_motion, ble_evt_t const * p_ble_evt)
{
    ble_gatts_evt_rw_authorize_request_t const * p_evt_rw_authorize_request = &amp;amp;p_ble_evt-&amp;gt;evt.gatts_evt.params.authorize_request;
    uint32_t err_code;

    if (p_evt_rw_authorize_request-&amp;gt;type  == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
    {
         if (p_evt_rw_authorize_request-&amp;gt;request.write.handle == p_motion-&amp;gt;calibrate_char_handles.value_handle)
        {
            ble_gatts_rw_authorize_reply_params_t rw_authorize_reply;
            bool                                  valid_data = true;
            uint16_t                              data_length = p_evt_rw_authorize_request-&amp;gt;request.write.len;

            // Check for valid data
            if (data_length != sizeof(ble_calibrate_t))
            {
                valid_data = false;
            }
            else
            {
                ble_calibrate_t * p_calib = (ble_calibrate_t *)p_evt_rw_authorize_request-&amp;gt;request.write.data;

                if ( ((p_calib-&amp;gt;calibrate &amp;gt; 0) &amp;amp;&amp;amp; (p_calib-&amp;gt;calibrate &amp;lt; 255)))
                   
                     
                {
                    valid_data = false;
                }
            }

            rw_authorize_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;

            if (valid_data)
            {
                rw_authorize_reply.params.write.update      = 1;
                rw_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
                rw_authorize_reply.params.write.p_data      = p_evt_rw_authorize_request-&amp;gt;request.write.data;
                rw_authorize_reply.params.write.len         = p_evt_rw_authorize_request-&amp;gt;request.write.len;
                rw_authorize_reply.params.write.offset      = p_evt_rw_authorize_request-&amp;gt;request.write.offset;
            }
            else
            {
                rw_authorize_reply.params.write.update      = 0;
                rw_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_WRITE_NOT_PERMITTED;
            }

            err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt-&amp;gt;evt.gatts_evt.conn_handle,
                                                       &amp;amp;rw_authorize_reply);
            APP_ERROR_CHECK(err_code);

            if ( valid_data &amp;amp;&amp;amp; (p_motion-&amp;gt;calib_write_handler != NULL))
            {
               p_motion-&amp;gt;calib_write_handler(p_motion,(ble_calibrate_t *)p_evt_rw_authorize_request-&amp;gt;request.write.data);
            }
        }
        
    }
}

...
...


static uint32_t calibrate_char_add(ble_motion_t * p_motion, const ble_motion_init_t * p_motion_init)
{
    ble_gatts_char_md_t char_md;
    ble_gatts_attr_t    attr_char_value;
    ble_uuid_t          ble_uuid;
    ble_gatts_attr_md_t attr_md;

    memset(&amp;amp;char_md, 0, sizeof(char_md));

    char_md.char_props.read          = 1;
    char_md.char_props.write         = 1;
    char_md.char_props.write_wo_resp = 0;
    char_md.p_char_user_desc         = NULL;
    char_md.p_char_pf                = NULL;
    char_md.p_user_desc_md           = NULL;
    char_md.p_cccd_md                = NULL;
    char_md.p_sccd_md                = NULL;

    ble_uuid.type = p_motion-&amp;gt;uuid_type;
    ble_uuid.uuid = BLE_CALIBRATE_CHAR;

    memset(&amp;amp;attr_md, 0, sizeof(attr_md));

    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&amp;amp;attr_md.read_perm);
    BLE_GAP_CONN_SEC_MODE_SET_OPEN(&amp;amp;attr_md.write_perm);

    attr_md.vloc       = BLE_GATTS_VLOC_STACK;
    attr_md.rd_auth    = 0;
    attr_md.wr_auth    = 1;
    attr_md.vlen       = 0;

    memset(&amp;amp;attr_char_value, 0, sizeof(attr_char_value));

    attr_char_value.p_uuid       = &amp;amp;ble_uuid;
    attr_char_value.p_attr_md    = &amp;amp;attr_md;
    attr_char_value.init_len     = sizeof(ble_calibrate_t);
    attr_char_value.init_offs    = 0;
    attr_char_value.max_len      = sizeof(ble_calibrate_t);;
    attr_char_value.p_value      = ((uint8_t *)(&amp;amp;p_motion_init-&amp;gt;init_calibrate));

    return sd_ble_gatts_characteristic_add(p_motion-&amp;gt;service_handle,
                                           &amp;amp;char_md,
                                           &amp;amp;attr_char_value,
                                           &amp;amp;p_motion-&amp;gt;calibrate_char_handles);
}


void ble_motion_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
{
    ble_motion_t * p_motion = (ble_motion_t *) p_context;

    if ((p_motion == NULL) || (p_ble_evt == NULL))
    {
        return;
    }

    switch (p_ble_evt-&amp;gt;header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            on_connect(p_motion, p_ble_evt);
            NRF_LOG_INFO(&amp;quot;BLE UI connected\r\n&amp;quot;);
            break;

        case BLE_GAP_EVT_DISCONNECTED:
            on_disconnect(p_motion, p_ble_evt);
            break;

        case BLE_GATTS_EVT_WRITE:
            on_write(p_motion, p_ble_evt);
            break;

        case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
            on_authorize_req(p_motion, p_ble_evt);
            break;

        default:
            // No implementation needed.
            break;
    }
}




uint32_t ble_motion_init(ble_motion_t * p_motion, const ble_motion_init_t * p_motion_init)
{
    uint32_t   err_code;
    ble_uuid_t ble_uuid;

    // Initialize service structure.
    p_motion-&amp;gt;conn_handle             = BLE_CONN_HANDLE_INVALID;
//    p_motion-&amp;gt;evt_handler             =  p_motion_init-&amp;gt;evt_handler;
   

    ble_uuid128_t base_uuid = LSPOT_BASE_UUID;
    err_code = sd_ble_uuid_vs_add(&amp;amp;base_uuid, &amp;amp;p_motion-&amp;gt;uuid_type);
    VERIFY_SUCCESS(err_code);

    ble_uuid.type = p_motion-&amp;gt;uuid_type;
    ble_uuid.uuid = BLE_MOTION_SERVICE;

    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &amp;amp;ble_uuid, &amp;amp;p_motion-&amp;gt;service_handle);
    VERIFY_SUCCESS(err_code);

    // Add characteristics.
    err_code = raw_data_char_add(p_motion, p_motion_init);
    VERIFY_SUCCESS(err_code);

     err_code = current_char_add(p_motion, p_motion_init);
    VERIFY_SUCCESS(err_code);


    err_code = calibrate_char_add(p_motion, p_motion_init);
    VERIFY_SUCCESS(err_code);


    return NRF_SUCCESS;
}


&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;ble_motion.h&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;.
...
...

typedef PACKED( struct
{
    uint8_t calibrate;  /**&amp;lt; Transisior 1 */
   
}) ble_calibrate_t;

typedef struct ble_motion_s          ble_motion_t;

typedef void (*ble_calibrate_write_handler_t) (ble_motion_t * p_motion, ble_calibrate_t * calib);

typedef struct
{
    ble_current_t                   init_current;
    ble_calibrate_t                 init_calibrate;
    ble_calibrate_write_handler_t   calib_write_handler;
    
} ble_motion_init_t;


struct ble_motion_s
{
    uint16_t                    service_handle;  
    uint8_t                     uuid_type;                 
    uint16_t                    conn_handle; 
    ble_gatts_char_handles_t    raw_data_char_handles;          
    ble_gatts_char_handles_t    threshold_char_handles;          
    ble_gatts_char_handles_t    side_current_char_handles;       
    ble_gatts_char_handles_t    front_current_char_handles;       
    ble_gatts_char_handles_t    calibrate_char_handles;       
    ble_gatts_char_handles_t    tracking_char_handles;       
    ble_gatts_char_handles_t    device_pos_char_handles;       
    ble_gatts_char_handles_t    angle_pos_char_handles;       
    ble_gatts_char_handles_t    pos_config_char_handles;       
    ble_gatts_char_handles_t    vib_config_char_handles;                      
    bool                        is_raw_data_notif_enabled;
    bool                        is_threshold_notif_enabled;
    bool                        is_side_current_notif_enabled;
    bool                        is_front_current_notif_enabled;
    ble_calibrate_write_handler_t   calib_write_handler;
    
};

void ble_motion_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context);

uint32_t ble_motion_init(ble_motion_t * p_motion, const ble_motion_init_t * p_motion_init);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;and declared at motion.c&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;...
...



...

static void ble_calibrate_handler(ble_motion_t * p_motion, ble_calibrate_t * calib)
{
    ret_code_t         err_code;
      NRF_LOG_INFO(&amp;quot;RECEIVED VALUE :%d&amp;quot;,calib-&amp;gt;calibrate);

}



static ret_code_t service_init(bool major_minor_fw_ver_changed)
{
    uint32_t                                    err_code;
    ble_motion_init_t                           motion_init;
    motion_init.init_calibrate.calibrate  =     5;
    motion_init.calib_write_handler       =     ble_calibrate_handler;
    //uis_init.device_write_handler = ble_uis_device_handler;

   return ble_motion_init(&amp;amp;b_motion, &amp;amp;motion_init);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: CUSTOM BLE SERVICE : READ WRITE RESPONSE</title><link>https://devzone.nordicsemi.com/thread/252784?ContentTypeID=1</link><pubDate>Tue, 02 Jun 2020 14:20:07 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:373e3b71-59de-4589-b82a-238f3701cb10</guid><dc:creator>Hung Bui</dc:creator><description>&lt;p&gt;Hi Sunil,&amp;nbsp;&lt;br /&gt;You set&amp;nbsp;&lt;/p&gt;
&lt;p&gt;BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&amp;amp;attr_md.read_perm);&lt;br /&gt; BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&amp;amp;attr_md.write_perm);&lt;/p&gt;
&lt;p&gt;So both read and write permission are not allowed. This explain why you can&amp;#39;t read. Note that permission is different from properties. Properties is the information the peer can get from the server, but the permission is the actual configuration of the read/write attribute.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;You need to set&amp;nbsp;&lt;/p&gt;
&lt;p&gt;BLE_GAP_CONN_SEC_MODE_SET_OPEN(&amp;amp;attr_md.read_perm);&lt;br /&gt; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&amp;amp;attr_md.write_perm);&amp;nbsp;&lt;/p&gt;
&lt;p&gt;instead.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>