たれぱんのびぼーろく

わたしの備忘録、生物学とプログラミングが多いかも

bluetoothとESP32

#

Bluetooth Low Energy (BLE)を利用したESP32の開発.

ESP32のBLE対応状況

2017-04-04: API群とexampleが存在する. しかし、documentが無い. そして色々不備が指摘されてる.
www.esp32.com
esp-idf2.0で大改修なのかな?

掘り出しもんを見つけた

esp-idf内にHID Over GATT Profile関係…?
命名からして、hid_le_prf = HID Low Energy Profileぽいよね.
esp-idf/hid_le_prf.c at release/v2.0 · espressif/esp-idf · GitHub

Bluetooth のプロファイルについて調べたことのまとめ - Over&Out その後

GATT SERVER API

application callbacksの登録.
esp_ble_gatts_register_callback()

This function is called to register application callbacks with BTA GATTS module.

esp_ble_gap_register_callback()

This function is called to occur gap event, such as scan result.

serviceへのcharacteristic追加.
esp_ble_gatts_add_char()
GATT SERVER API
実体: https://github.com/espressif/esp-idf/blob/47b8f78cb0e15fa43647788a808dac353167a485/components/bt/bluedroid/api/esp_gatts_api.c

This function is called to add a characteristic into a service.

struct esp_attr_value_t
  {
    uint16_t attr_max_len,  
    uint16_t attr_len,  
    uint8_t *attr_value
  }
esp_err_t esp_ble_gatts_add_char(uint16_t service_handle,  esp_bt_uuid_t  *char_uuid,
                                 esp_gatt_perm_t perm, esp_gatt_char_prop_t property, esp_attr_value_t *char_val,
                                 esp_attr_control_t *control){
...
    // set memory block. <string.h> (?)
    memset(&arg, 0, sizeof(btc_ble_gatts_args_t));

    // add to btc_msg struct.
    msg.sig = BTC_SIG_API_CALL;
    msg.pid = BTC_PID_GATTS;
    msg.act = BTC_GATTS_ACT_ADD_CHAR;

    // add functionArguments to "arg" variable.
    arg.add_char.service_handle = service_handle; // argument 0
    arg.add_char.perm = perm; // argument 2
    arg.add_char.property = property; // argument 3
    if (char_val != NULL) { // argument 4
        arg.add_char.char_val.attr_max_len = char_val->attr_max_len;
        arg.add_char.char_val.attr_len = char_val->attr_len;
        arg.add_char.char_val.attr_value = char_val->attr_value;
    }

    if (control != NULL) { .. argument 5
        arg.add_char.attr_control.auto_rsp = control->auto_rsp; 
    }

    // arg.add_char_uuid <- char_uuid
    memcpy(&arg.add_char.char_uuid, char_uuid, sizeof(esp_bt_uuid_t));

    // execute "btc_transfer_context" and return success/failure.
    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}

[https://github.com/espressif/esp-idf/blob/fbe89a083322c7903fd7baae966441546052354e/components/bt/bluedroid/api/esp_gatts_api.c#L134:title]
typedef struct btc_msg {
    uint8_t sig;    //event signal
    uint8_t aid;    //application id
    uint8_t pid;    //profile id
    uint8_t act;    //profile action, defined in seprerate header files
    void   *arg;    //param for btc function or function param
} btc_msg_t;

[https://github.com/espressif/esp-idf/blob/65f57e5da7287576d98f657ea45163411bc3a564/components/bt/bluedroid/btc/include/btc_task.h:title]  
bt_status_t btc_transfer_context(btc_msg_t *msg, void *arg, int arg_len, btc_arg_deep_copy_t copy_func)
{
    btc_msg_t lmsg;
    //lmsg {
    //    uint8_t sig;    //event signal
    //    uint8_t aid;    //application id
    //    uint8_t pid;    //profile id
    //    uint8_t act;    //profile action, defined in seprerate header files
    //    void   *arg;    //param for btc function or function param
    //}

    if (msg == NULL) {
        return BT_STATUS_PARM_INVALID;
    }

    LOG_DEBUG("%s msg %u %u %u %p\n", __func__, msg->sig, msg->pid, msg->act, arg);

    // copy "msg -> lmsg"
    memcpy(&lmsg, msg, sizeof(btc_msg_t));
    //lmsg {
    //    uint8_t sig: BTC_SIG_API_CALL,    //event signal
    //    uint8_t aid,    //application id
    //    uint8_t pid: BTC_PID_GATTS,    //profile id
    //    uint8_t act: BTC_GATTS_ACT_ADD_CHAR,    //profile action, defined in seprerate header files
    //    void   *arg: many information about "Characteristic"    //param for btc function or function param
    //}

    if (arg) {
        lmsg.arg = (void *)GKI_getbuf(arg_len);
        
        // lmsg.arg : 0x00, 0x00, 0x00, ... (No. arg_len) 0x00.
        memset(lmsg.arg, 0x00, arg_len);    //important, avoid arg which have no length
        if (lmsg.arg == NULL) {
            return BT_STATUS_NOMEM;
        }
        // copy arg -> lmsg.arg(0x00, 0x00, ...)
        memcpy(lmsg.arg, arg, arg_len);

        // copy_finc == btc_gatts_arg_deep_copy
        if (copy_func) {
            copy_func(&lmsg, lmsg.arg, arg);
        }
    } else {
        lmsg.arg = NULL;
    }

    return btc_task_post(&lmsg);
}

[https://github.com/espressif/esp-idf/blob/65f57e5da7287576d98f657ea45163411bc3a564/components/bt/bluedroid/btc/core/btc_task.c:title]  
void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
{
    btc_ble_gatts_args_t *dst = (btc_ble_gatts_args_t *) p_dest;
    btc_ble_gatts_args_t *src = (btc_ble_gatts_args_t *)p_src;

    switch (msg->act) {
...  
        case BTC_GATTS_ACT_ADD_CHAR:{
            if (src->add_char.char_val.attr_value != NULL){
                dst->add_char.char_val.attr_value = (uint8_t *)GKI_getbuf(src->add_char.char_val.attr_len);
                if(dst->add_char.char_val.attr_value != NULL){
                    memcpy(dst->add_char.char_val.attr_value, src->add_char.char_val.attr_value, 
                        src->add_char.char_val.attr_len);
                }else{
                    LOG_ERROR("%s %d no mem\n", __func__, msg->act);
                }
            }
            break;
        }
    ...
    }
...
}

[https://github.com/espressif/esp-idf/blob/c06cc31d85cc700e1dbddbe527d4282c4bc5845a/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c#L69:title]