blob: f824e9000ab1256b5719abb567489091e96e93d5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <stddef.h>
#include <string.h>
#include "host/ble_gatt.h"
#include "host/ble_uuid.h"
#include "console/console.h"
#include "nimble/ble.h"
#include "ble_hs_priv.h"
#if NIMBLE_BLE_CONNECT
static const ble_uuid_t *uuid_ccc =
BLE_UUID16_DECLARE(BLE_GATT_DSC_CLT_CFG_UUID16);
static const char * const ble_gatt_chr_f_names[] = {
"BROADCAST",
"READ",
"WRITE_NO_RSP",
"WRITE",
"NOTIFY",
"INDICATE",
"AUTH_SIGN_WRITE",
"RELIABLE_WRITE",
"AUX_WRITE",
"READ_ENC",
"READ_AUTHEN",
"READ_AUTHOR",
"WRITE_ENC",
"WRITE_AUTHEN",
"WRITE_AUTHOR",
NULL
};
static const char * const ble_gatt_dsc_f_names[] = {
"READ",
"WRITE",
"READ_ENC",
"READ_AUTHEN",
"READ_AUTHOR",
"WRITE_ENC",
"WRITE_AUTHEN",
"WRITE_AUTHOR",
NULL
};
#define BLE_CHR_FLAGS_STR_LEN 180
static char *
ble_gatts_flags_to_str(uint16_t flags, char *buf,
const char * const *names)
{
int bit;
bool non_empty = false;
size_t length = 0;
buf[0] = '\0';
strcpy(buf, "[");
length += 1;
for (bit = 0; names[bit]; ++bit) {
if (flags & (1 << bit)) {
length += strlen(names[bit]);
if (length + 1 >= BLE_CHR_FLAGS_STR_LEN) {
return buf;
}
if (non_empty) {
strcat(buf, "|");
length += 1;
}
strcat(buf, names[bit]);
non_empty = true;
}
}
strcat(buf, "]");
return buf;
}
#define STRINGIFY(X) #X
#define FIELD_NAME_LEN STRINGIFY(12)
#define FIELD_INDENT STRINGIFY(2)
static void
ble_gatt_show_local_chr(const struct ble_gatt_svc_def *svc,
uint16_t handle, char *uuid_buf, char *flags_buf)
{
const struct ble_gatt_chr_def *chr;
const struct ble_gatt_dsc_def *dsc;
for (chr = svc->characteristics; chr && chr->uuid; ++chr) {
console_printf("characteristic\n");
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%s\n", " ", "uuid",
ble_uuid_to_str(chr->uuid, uuid_buf));
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%d\n", " ", "def_handle", handle);
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%d\n", " ", "val_handle", handle+1);
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%d\n", " ", "min_key_size", chr->min_key_size);
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%s\n", " ", "flags",
ble_gatts_flags_to_str(chr->flags,
flags_buf, ble_gatt_chr_f_names));
handle += 2;
if ((chr->flags & BLE_GATT_CHR_F_NOTIFY) ||
(chr->flags & BLE_GATT_CHR_F_INDICATE)) {
console_printf("ccc descriptor\n");
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%s\n", " ", "uuid",
ble_uuid_to_str(uuid_ccc, uuid_buf));
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%d\n", " ", "handle", handle);
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%d\n", " ", "min_key_size", 0);
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%s\n", " ", "flags",
ble_gatts_flags_to_str(BLE_ATT_F_READ | BLE_ATT_F_WRITE,
flags_buf, ble_gatt_dsc_f_names));
handle++;
}
for (dsc = chr->descriptors; dsc && dsc->uuid; ++dsc) {
console_printf("descriptor\n");
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%s\n", " ", "uuid",
ble_uuid_to_str(dsc->uuid, uuid_buf));
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%d\n", " ", "handle", handle);
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%d\n", " ", "min_key_size", dsc->min_key_size);
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%s\n", " ", "flags",
ble_gatts_flags_to_str(dsc->att_flags,
flags_buf, ble_gatt_dsc_f_names));
handle++;
}
}
}
static int
ble_gatt_show_local_inc_svc(const struct ble_gatt_svc_def *svc,
uint16_t handle, char *uuid_buf)
{
const struct ble_gatt_svc_def **includes;
int num = 0;
for (includes = &svc->includes[0]; *includes != NULL; ++includes) {
console_printf("included service\n");
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%s\n", " ", "uuid",
ble_uuid_to_str((*includes)->uuid, uuid_buf));
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%d\n", " ", "attr handle", handle);
++num;
}
return num;
}
static void
ble_gatt_show_local_svc(const struct ble_gatt_svc_def *svc,
uint16_t handle, uint16_t end_group_handle,
void *arg)
{
char uuid_buf[BLE_UUID_STR_LEN];
char flags_buf[BLE_CHR_FLAGS_STR_LEN];
console_printf("%s service\n",
svc->type == BLE_GATT_SVC_TYPE_PRIMARY ?
"primary" : "secondary");
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%s\n", " ", "uuid",
ble_uuid_to_str(svc->uuid, uuid_buf));
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%d\n", " ", "handle",
handle);
console_printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
"%d\n", " ", "end_handle",
end_group_handle);
handle++;
if (svc->includes) {
handle += ble_gatt_show_local_inc_svc(svc, handle, uuid_buf);
}
ble_gatt_show_local_chr(svc, handle,
uuid_buf, flags_buf);
}
void
ble_gatts_show_local(void)
{
ble_gatts_lcl_svc_foreach(ble_gatt_show_local_svc, NULL);
}
#endif