Tasmota/lib/libesp32_div/ESP32-HomeKit/src/esp_hap_serv.c
2021-11-15 12:35:48 +01:00

330 lines
7.7 KiB
C

/*
* ESPRESSIF MIT License
*
* Copyright (c) 2020 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
*
* Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case,
* it is free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <string.h>
#include <hap_platform_memory.h>
#include <esp_hap_serv.h>
#include <esp_mfi_debug.h>
void hap_serv_mark_primary(hap_serv_t *hs)
{
if (hs) {
((__hap_serv_t *)hs)->primary = true;
}
}
void hap_serv_mark_hidden(hap_serv_t *hs)
{
if (hs) {
((__hap_serv_t *)hs)->hidden = true;
}
}
/**
* @brief get service hidden attribute
*/
bool hap_serv_get_hidden(hap_serv_t *hs)
{
if (hs) {
return ((__hap_serv_t *)hs)->hidden;
}
return false;
}
void hap_serv_set_iid(hap_serv_t *hs, int32_t iid)
{
if (hs) {
((__hap_serv_t *)hs)->iid = iid;
}
}
/**
* @brief get service "primary" attribute
*/
bool hap_serv_get_primary(hap_serv_t *hs)
{
if (hs) {
return ((__hap_serv_t *)hs)->primary;
}
return false;
}
hap_char_t *hap_serv_get_first_char(hap_serv_t *hs)
{
return ((__hap_serv_t *)hs)->chars;
}
/**
* @brief get target characteristics by it's IID
*/
hap_char_t *hap_serv_get_char_by_iid(hap_serv_t *hs, int32_t iid)
{
if (!hs)
return NULL;
hap_char_t *hc;
for (hc = hap_serv_get_first_char(hs); hc; hc = hap_char_get_next(hc)) {
if (((__hap_char_t *)hc)->iid == iid)
return hc;
}
return NULL;
}
/**
* @brief get target characteristics by it's UUID
*/
hap_char_t *hap_serv_get_char_by_uuid(hap_serv_t *hs, const char *uuid)
{
if (!hs | !uuid)
return NULL;
hap_char_t *hc;
for (hc = hap_serv_get_first_char(hs); hc; hc = hap_char_get_next(hc)) {
if (!strcmp(((__hap_char_t *)hc)->type_uuid, uuid))
return hc;
}
return NULL;
}
/**
* @brief get characteristics UUID prefix number
*/
const char *hap_serv_get_uuid(hap_serv_t *hs)
{
return ((__hap_serv_t *)hs)->type_uuid;
}
/**
* Default service bulk read callback, which will be registered while creating a service.
* It will internally call the actual read routines
*/
static int hap_serv_def_bulk_read_cb(hap_read_data_t read_data[], int count,
void *serv_priv, void *read_priv)
{
int i;
if (!count) {
return HAP_FAIL;
}
__hap_serv_t *hs = (__hap_serv_t *)hap_char_get_parent(read_data[0].hc);
/* If no read routine is registered, just return success so that the cached values
* will be used
*/
if (!hs->read_cb) {
return HAP_SUCCESS;
}
int ret = HAP_SUCCESS;
for (i = 0; i < count; i++) {
if (hs->read_cb(read_data[i].hc, read_data[i].status, serv_priv, read_priv) != HAP_SUCCESS) {
ret = HAP_FAIL;
}
}
return ret;
}
/**
* @brief HAP create a service
*/
hap_serv_t *hap_serv_create(const char *type_uuid)
{
ESP_MFI_ASSERT(type_uuid);
__hap_serv_t *_hs = hap_platform_memory_calloc(1, sizeof(__hap_serv_t));
if (!_hs) {
return NULL;
}
_hs->type_uuid = type_uuid;
_hs->bulk_read = hap_serv_def_bulk_read_cb;
return (hap_serv_t *)_hs;
}
int hap_serv_link_serv(hap_serv_t *hs, hap_serv_t *linked_serv)
{
if (!hs || !linked_serv)
return HAP_FAIL;
hap_linked_serv_t *cur = hap_platform_memory_calloc(1, sizeof(hap_linked_serv_t));
if (!cur)
return HAP_FAIL;
cur->hs = linked_serv;
__hap_serv_t *_hs = (__hap_serv_t *)hs;
hap_linked_serv_t *linked = _hs->linked_servs;
if (!linked) {
_hs->linked_servs = cur;
return HAP_SUCCESS;
} else {
while(linked->next) {
linked = linked->next;
}
linked->next = cur;
return HAP_SUCCESS;
}
return HAP_FAIL;
}
/**
* @brief HAP get target service IID
*/
uint32_t hap_serv_get_iid(hap_serv_t *hs)
{
if (!hs)
return 0;
__hap_serv_t *tmp = (__hap_serv_t *)hs;
return tmp->iid;
}
const char *hap_serv_get_type_uuid(hap_serv_t *hs)
{
if (!hs)
return 0;
__hap_serv_t *tmp = (__hap_serv_t *)hs;
return tmp->type_uuid;
}
/**
* @brief HAP delete target service
*/
void hap_serv_delete(hap_serv_t *hs)
{
/* Returning success even if pointer is NULL, because it means
* that the service is absent and as good as deleted
*/
if (!hs)
return;
__hap_serv_t *_hs = (__hap_serv_t *)hs;
__hap_char_t *_hc = (__hap_char_t *)_hs->chars;
while (_hc) {
_hs->chars = _hc->next_char;
hap_char_delete((hap_char_t *)_hc);
_hc = (__hap_char_t *)_hs->chars;
}
if (_hs->linked_servs) {
hap_linked_serv_t *cur = _hs->linked_servs;
hap_linked_serv_t *next = cur->next;
while (next) {
hap_platform_memory_free(cur);
cur = next;
next = cur->next;
}
hap_platform_memory_free(cur);
}
hap_platform_memory_free(hs);
}
/**
* @brief add a characteristics to a service
*/
int hap_serv_add_char(hap_serv_t *hs, hap_char_t *hc)
{
if (!hs || !hc)
return -1;
__hap_serv_t *_hs = (__hap_serv_t *)hs;
__hap_char_t *_hc = (__hap_char_t *)hc;
if (_hc->parent) {
ESP_MFI_DEBUG(ESP_MFI_DEBUG_ERR, "Characteristic already added");
return HAP_FAIL;
}
/* If the service has no characteristics, add this as the first */
if (!_hs->chars) {
_hs->chars = hc;
} else {
/* Else loop through the characteristics to get to the last one,
* and add this at the end
*/
__hap_char_t *temp = (__hap_char_t *)_hs->chars;
while (temp->next_char)
temp = (__hap_char_t *)temp->next_char;
temp->next_char = hc;
}
if (_hs->parent) {
_hc->iid = ((__hap_acc_t *)(_hs->parent))->next_iid++;
}
_hc->parent = hs;
return 0;
}
void hap_serv_set_write_cb(hap_serv_t *hs, hap_serv_write_t write)
{
if (hs) {
((__hap_serv_t *)hs)->write_cb = write;
}
}
void hap_serv_set_read_cb(hap_serv_t *hs, hap_serv_read_t read)
{
if (hs) {
((__hap_serv_t *)hs)->read_cb = read;
}
}
void hap_serv_set_bulk_read_cb(hap_serv_t *hs, hap_serv_bulk_read_t read)
{
if (hs) {
((__hap_serv_t *)hs)->bulk_read = read;
}
}
hap_serv_t *hap_serv_get_next(hap_serv_t *hs)
{
if (hs) {
return ((__hap_serv_t *)hs)->next_serv;
} else {
return NULL;
}
}
hap_acc_t *hap_serv_get_parent(hap_serv_t *hs)
{
if (hs) {
return ((__hap_serv_t *)hs)->parent;
} else {
return NULL;
}
}
void hap_serv_set_priv(hap_serv_t *hs, void *priv)
{
if (hs) {
((__hap_serv_t *)hs)->priv = priv;
}
}
void *hap_serv_get_priv(hap_serv_t *hs)
{
if (hs) {
return ((__hap_serv_t *)hs)->priv;
} else {
return NULL;
}
}