BLE Object Transfer Service OACP advice?
Posted: Tue Jun 19, 2018 1:47 am
I've got a BLE profile working nicely, and I'm trying to add Object Transfer Service support for firmware updates. There's one piece (so far...) that I'm having a really difficult time with, and that's how to specify the OACP characteristic table. The BT specs are really opaque, at least to me. Below is the table I'm using. When I use the Android nrfConnect application, the service is found, and the characteristics are read, but I know the OACP entries aren't correct. They're the two entries at the very end.
Am I supposed to create multiple OTS_IDX_OBJECT_ACTION_CONTROL_POINT_CHARACTERISTIC/VALUE entries for each OACP function supported (create, delete, read, write, checksum, etc)?
Any advice would be greatly appreciated. I've looked at code in the nrf51 SDK, and the TI code base, but they're so different in architecture that I haven't been able to draw a parallel for how the characteristic tables are created.
Am I supposed to create multiple OTS_IDX_OBJECT_ACTION_CONTROL_POINT_CHARACTERISTIC/VALUE entries for each OACP function supported (create, delete, read, write, checksum, etc)?
Any advice would be greatly appreciated. I've looked at code in the nrf51 SDK, and the TI code base, but they're so different in architecture that I haven't been able to draw a parallel for how the characteristic tables are created.
Code: Select all
static otsFeature_t ots_feature_value =
{
.oacp = OTS_OACP_CREATE | OTS_OACP_DELETE | OTS_OACP_CHECKSUM | OTS_OACP_READ | OTS_OACP_WRITE | OTS_OACP_TRUNCATE,
.olcp = 0,
};
static uint8_t ots_name_value [8] = {'F', 'i', 'r', 'm', 'w', 'a', 'r', 'e'};
static uint8_t ots_type_value [ESP_UUID_LEN_128] = {0x14, 0xdc, 0x86, 0x4f, 0xba, 0x52, 0xea, 0x83, 0x12, 0x44, 0xf9, 0x49, 0xce, 0x33, 0xdd, 0xbf};
static otsSize_t ots_size_value = {1024, 1024};
static uint32_t ots_properties_value = OTS_PROPERTIES_DELETE | OTS_PROPERTIES_READ | OTS_PROPERTIES_WRITE | OTS_PROPERTIES_TRUNCATE;
static uint8_t ots_acp_value [] = {OTS_OPCODE_CREATE, OTS_OPCODE_DELETE, OTS_OPCODE_CHECKSUM, OTS_OPCODE_READ, OTS_OPCODE_WRITE, OTS_OPCODE_ABORT, OTS_OPCODE_RESPONSE};
static const uint8_t ots_service_uuid [ESP_UUID_LEN_128] = GATT_UUID_OBJECT_TRANSFER_SERVICE;
static const uint16_t ots_feature_uuid = GATT_UUID_OBJECT_FEATURE; // 0x2abd
static const uint16_t ots_name_uuid = GATT_UUID_OBJECT_NAME; // 0x2abe
static const uint16_t ots_type_uuid = GATT_UUID_OBJECT_TYPE; // 0x2abf
static const uint16_t ots_size_uuid = GATT_UUID_OBJECT_SIZE; // 0x2ac0
static const uint16_t ots_properties_uuid = GATT_UUID_OBJECT_PROPERTIES; // 0x2ac4
static const uint16_t ots_acp_uuid = GATT_UUID_OBJECT_ACTION_CONTROL_POINT; // 0x2ac5
static const esp_gatts_attr_db_t ots_gatt_db [OTS_IDX_NB] =
{
[OTS_IDX_SERVICE] =
{
.attr_control.auto_rsp = ESP_GATT_AUTO_RSP,
.att_desc.uuid_length = sizeof (primary_service_uuid),
.att_desc.uuid_p = (uint8_t *) &primary_service_uuid,
.att_desc.perm = ESP_GATT_PERM_READ,
.att_desc.max_length = sizeof (ots_service_uuid),
.att_desc.length = sizeof (ots_service_uuid),
.att_desc.value = (uint8_t *) &ots_service_uuid,
},
[OTS_IDX_OBJECT_FEATURE_CHARACTERISTIC] =
{
.attr_control.auto_rsp = ESP_GATT_AUTO_RSP,
.att_desc.uuid_length = sizeof (characteristic_declaration_uuid),
.att_desc.uuid_p = (uint8_t *) &characteristic_declaration_uuid,
.att_desc.perm = ESP_GATT_PERM_READ,
.att_desc.max_length = CHARACTERISTIC_DECLARATION_SIZE,
.att_desc.length = CHARACTERISTIC_DECLARATION_SIZE,
.att_desc.value = (uint8_t *) &characteristic_property_read,
},
[OTS_IDX_OBJECT_FEATURE_VALUE] =
{
.attr_control.auto_rsp = ESP_GATT_AUTO_RSP,
.att_desc.uuid_length = sizeof (ots_feature_uuid),
.att_desc.uuid_p = (uint8_t *) &ots_feature_uuid,
.att_desc.perm = ESP_GATT_PERM_READ,
.att_desc.max_length = sizeof (ots_feature_value),
.att_desc.length = sizeof (ots_feature_value),
.att_desc.value = (uint8_t *) &ots_feature_value,
},
[OTS_IDX_OBJECT_NAME_CHARACTERISTIC] =
{
.attr_control.auto_rsp = ESP_GATT_AUTO_RSP,
.att_desc.uuid_length = sizeof (characteristic_declaration_uuid),
.att_desc.uuid_p = (uint8_t *) &characteristic_declaration_uuid,
.att_desc.perm = ESP_GATT_PERM_READ,
.att_desc.max_length = CHARACTERISTIC_DECLARATION_SIZE,
.att_desc.length = CHARACTERISTIC_DECLARATION_SIZE,
.att_desc.value = (uint8_t *) &characteristic_property_read,
},
[OTS_IDX_OBJECT_NAME_VALUE] =
{
.attr_control.auto_rsp = ESP_GATT_AUTO_RSP,
.att_desc.uuid_length = sizeof (ots_name_uuid),
.att_desc.uuid_p = (uint8_t *) &ots_name_uuid,
.att_desc.perm = ESP_GATT_PERM_READ,
.att_desc.max_length = sizeof (ots_name_value),
.att_desc.length = sizeof (ots_name_value),
.att_desc.value = (uint8_t *) &ots_name_value,
},
[OTS_IDX_OBJECT_TYPE_CHARACTERISTIC] =
{
.attr_control.auto_rsp = ESP_GATT_AUTO_RSP,
.att_desc.uuid_length = sizeof (characteristic_declaration_uuid),
.att_desc.uuid_p = (uint8_t *) &characteristic_declaration_uuid,
.att_desc.perm = ESP_GATT_PERM_READ,
.att_desc.max_length = CHARACTERISTIC_DECLARATION_SIZE,
.att_desc.length = CHARACTERISTIC_DECLARATION_SIZE,
.att_desc.value = (uint8_t *) &characteristic_property_read,
},
[OTS_IDX_OBJECT_TYPE_VALUE] =
{
.attr_control.auto_rsp = ESP_GATT_AUTO_RSP,
.att_desc.uuid_length = sizeof (ots_type_uuid),
.att_desc.uuid_p = (uint8_t *) &ots_type_uuid,
.att_desc.perm = ESP_GATT_PERM_READ,
.att_desc.max_length = sizeof (ots_type_value),
.att_desc.length = sizeof (ots_type_value),
.att_desc.value = (uint8_t *) &ots_type_value,
},
[OTS_IDX_OBJECT_SIZE_CHARACTERISTIC] =
{
.attr_control.auto_rsp = ESP_GATT_AUTO_RSP,
.att_desc.uuid_length = sizeof (characteristic_declaration_uuid),
.att_desc.uuid_p = (uint8_t *) &characteristic_declaration_uuid,
.att_desc.perm = ESP_GATT_PERM_READ,
.att_desc.max_length = CHARACTERISTIC_DECLARATION_SIZE,
.att_desc.length = CHARACTERISTIC_DECLARATION_SIZE,
.att_desc.value = (uint8_t *) &characteristic_property_read,
},
[OTS_IDX_OBJECT_SIZE_VALUE] =
{
.attr_control.auto_rsp = ESP_GATT_AUTO_RSP,
.att_desc.uuid_length = sizeof (ots_size_uuid),
.att_desc.uuid_p = (uint8_t *) &ots_size_uuid,
.att_desc.perm = ESP_GATT_PERM_READ,
.att_desc.max_length = sizeof (ots_size_value),
.att_desc.length = sizeof (ots_size_value),
.att_desc.value = (uint8_t *) &ots_size_value,
},
[OTS_IDX_OBJECT_PROPERTIES_CHARACTERISTIC] =
{
.attr_control.auto_rsp = ESP_GATT_AUTO_RSP,
.att_desc.uuid_length = sizeof (characteristic_declaration_uuid),
.att_desc.uuid_p = (uint8_t *) &characteristic_declaration_uuid,
.att_desc.perm = ESP_GATT_PERM_READ,
.att_desc.max_length = CHARACTERISTIC_DECLARATION_SIZE,
.att_desc.length = CHARACTERISTIC_DECLARATION_SIZE,
.att_desc.value = (uint8_t *) &characteristic_property_read,
},
[OTS_IDX_OBJECT_PROPERTIES_VALUE] =
{
.attr_control.auto_rsp = ESP_GATT_AUTO_RSP,
.att_desc.uuid_length = sizeof (ots_properties_uuid),
.att_desc.uuid_p = (uint8_t *) &ots_properties_uuid,
.att_desc.perm = ESP_GATT_PERM_READ,
.att_desc.max_length = sizeof (ots_properties_value),
.att_desc.length = sizeof (ots_properties_value),
.att_desc.value = (uint8_t *) &ots_properties_value,
},
[OTS_IDX_OBJECT_ACTION_CONTROL_POINT_CHARACTERISTIC] =
{
.attr_control.auto_rsp = ESP_GATT_AUTO_RSP,
.att_desc.uuid_length = sizeof (characteristic_declaration_uuid),
.att_desc.uuid_p = (uint8_t *) &characteristic_declaration_uuid,
.att_desc.perm = ESP_GATT_PERM_READ,
.att_desc.max_length = CHARACTERISTIC_DECLARATION_SIZE,
.att_desc.length = CHARACTERISTIC_DECLARATION_SIZE,
.att_desc.value = (uint8_t *) &characteristic_property_read,
},
[OTS_IDX_OBJECT_ACTION_CONTROL_POINT_VALUE] =
{
.attr_control.auto_rsp = ESP_GATT_AUTO_RSP,
.att_desc.uuid_length = sizeof (ots_acp_uuid),
.att_desc.uuid_p = (uint8_t *) &ots_acp_uuid,
.att_desc.perm = ESP_GATT_PERM_READ,
.att_desc.max_length = sizeof (ots_acp_value),
.att_desc.length = sizeof (ots_acp_value),
.att_desc.value = (uint8_t *) &ots_acp_value,
},
};