blob: a7b18783223d16d0fdb42ea9d06d5b3c96f513ed [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.
*/
/* btp_core.c - Bluetooth BTP Core service */
/*
* Copyright (C) 2023 Codecoup
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "btp/btp.h"
static uint8_t registered_services[((BTP_SERVICE_ID_MAX - 1) / 8) + 1];
static uint8_t
supported_commands(const void *cmd, uint16_t cmd_len,
void *rsp, uint16_t *rsp_len)
{
struct btp_core_read_supported_commands_rp *rp = rsp;
tester_set_bit(rp->data, BTP_CORE_READ_SUPPORTED_COMMANDS);
tester_set_bit(rp->data, BTP_CORE_READ_SUPPORTED_SERVICES);
tester_set_bit(rp->data, BTP_CORE_REGISTER_SERVICE);
tester_set_bit(rp->data, BTP_CORE_UNREGISTER_SERVICE);
*rsp_len = sizeof(*rp) + 1;
return BTP_STATUS_SUCCESS;
}
static uint8_t
supported_services(const void *cmd, uint16_t cmd_len,
void *rsp, uint16_t *rsp_len)
{
struct btp_core_read_supported_services_rp *rp = rsp;
/* octet 0 */
tester_set_bit(rp->data, BTP_SERVICE_ID_CORE);
tester_set_bit(rp->data, BTP_SERVICE_ID_GAP);
tester_set_bit(rp->data, BTP_SERVICE_ID_GATT);
#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
tester_set_bit(rp->data, BTP_SERVICE_ID_L2CAP);
#endif /* MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) */
#if MYNEWT_VAL(BLE_MESH)
tester_set_bit(rp->data, BTP_SERVICE_ID_MESH);
#endif /* MYNEWT_VAL(BLE_MESH) */
tester_set_bit(rp->data, BTP_SERVICE_ID_GATTC);
*rsp_len = sizeof(*rp) + 2;
return BTP_STATUS_SUCCESS;
}
static uint8_t
register_service(const void *cmd, uint16_t cmd_len,
void *rsp, uint16_t *rsp_len)
{
const struct btp_core_register_service_cmd *cp = cmd;
uint8_t status;
/* invalid service */
if ((cp->id == BTP_SERVICE_ID_CORE) || (cp->id > BTP_SERVICE_ID_MAX)) {
return BTP_STATUS_FAILED;
}
/* already registered */
if (tester_test_bit(registered_services, cp->id)) {
return BTP_STATUS_FAILED;
}
switch (cp->id) {
case BTP_SERVICE_ID_GAP:
status = tester_init_gap();
break;
case BTP_SERVICE_ID_GATT:
status = tester_init_gatt();
break;
#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
case BTP_SERVICE_ID_L2CAP:
status = tester_init_l2cap();
break;
#endif /* MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) */
#if MYNEWT_VAL(BLE_MESH)
case BTP_SERVICE_ID_MESH:
status = tester_init_mesh();
break;
#endif /* MYNEWT_VAL(BLE_MESH) */
#if MYNEWT_VAL(BLE_ISO_BROADCAST_SOURCE)
case BTP_SERVICE_ID_BAP:
status = tester_init_bap();
break;
#endif /* MYNEWT_VAL(BLE_ISO_BROADCAST_SOURCE) */
case BTP_SERVICE_ID_GATTC:
status = tester_init_gatt_cl();
break;
default:
status = BTP_STATUS_FAILED;
break;
}
if (status == BTP_STATUS_SUCCESS) {
tester_set_bit(registered_services, cp->id);
}
return status;
}
static uint8_t
unregister_service(const void *cmd, uint16_t cmd_len,
void *rsp, uint16_t *rsp_len)
{
const struct btp_core_unregister_service_cmd *cp = cmd;
uint8_t status;
/* invalid service ID */
if ((cp->id == BTP_SERVICE_ID_CORE) || (cp->id > BTP_SERVICE_ID_MAX)) {
return BTP_STATUS_FAILED;
}
/* not registered */
if (!tester_test_bit(registered_services, cp->id)) {
return BTP_STATUS_FAILED;
}
switch (cp->id) {
case BTP_SERVICE_ID_GAP:
status = tester_unregister_gap();
break;
case BTP_SERVICE_ID_GATT:
status = tester_unregister_gatt();
break;
#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
case BTP_SERVICE_ID_L2CAP:
status = tester_unregister_l2cap();
break;
#endif /* MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) */
#if MYNEWT_VAL(BLE_MESH)
case BTP_SERVICE_ID_MESH:
status = tester_unregister_mesh();
break;
#endif /* MYNEWT_VAL(BLE_MESH) */
case BTP_SERVICE_ID_GATTC:
status = tester_unregister_gatt_cl();
break;
#if MYNEWT_VAL(BLE_ISO_BROADCAST_SOURCE)
case BTP_SERVICE_ID_BAP:
status = tester_unregister_bap();
break;
#endif /* MYNEWT_VAL(BLE_ISO_BROADCAST_SOURCE) */
default:
status = BTP_STATUS_FAILED;
break;
}
if (status == BTP_STATUS_SUCCESS) {
tester_clear_bit(registered_services, cp->id);
}
return status;
}
static const struct btp_handler handlers[] = {
{
.opcode = BTP_CORE_READ_SUPPORTED_COMMANDS,
.index = BTP_INDEX_NONE,
.expect_len = 0,
.func = supported_commands,
},
{
.opcode = BTP_CORE_READ_SUPPORTED_SERVICES,
.index = BTP_INDEX_NONE,
.expect_len = 0,
.func = supported_services,
},
{
.opcode = BTP_CORE_REGISTER_SERVICE,
.index = BTP_INDEX_NONE,
.expect_len = sizeof(struct btp_core_register_service_cmd),
.func = register_service,
},
{
.opcode = BTP_CORE_UNREGISTER_SERVICE,
.index = BTP_INDEX_NONE,
.expect_len = sizeof(struct btp_core_unregister_service_cmd),
.func = unregister_service,
},
};
void
tester_init_core(void)
{
tester_register_command_handlers(BTP_SERVICE_ID_CORE, handlers,
ARRAY_SIZE(handlers));
tester_set_bit(registered_services, BTP_SERVICE_ID_CORE);
}