// SPDX-License-Identifier: LGPL-2.1-or-later /* * * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2014 Intel Corporation. All rights reserved. * * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "lib/sdp.h" #include "lib/sdp_lib.h" #include "src/sdp-client.h" #include "ipc.h" #include "lib/bluetooth.h" #include "map-client.h" #include "src/log.h" #include "hal-msg.h" #include "ipc-common.h" #include "utils.h" #include "src/shared/util.h" static struct ipc *hal_ipc = NULL; static bdaddr_t adapter_addr; static int fill_mce_inst(void *buf, int32_t id, int32_t scn, int32_t msg_type, const void *name, uint8_t name_len) { struct hal_map_client_mas_instance *inst = buf; inst->id = id; inst->scn = scn; inst->msg_types = msg_type; inst->name_len = name_len; if (name_len) memcpy(inst->name, name, name_len); return sizeof(*inst) + name_len; } static void map_client_sdp_search_cb(sdp_list_t *recs, int err, gpointer data) { uint8_t buf[IPC_MTU]; struct hal_ev_map_client_remote_mas_instances *ev = (void *) buf; bdaddr_t *dst = data; sdp_list_t *list, *protos; uint8_t status; int32_t id, scn, msg_type, name_len, num_instances = 0; char *name; size_t size; size = sizeof(*ev); bdaddr2android(dst, &ev->bdaddr); if (err < 0) { error("mce: Unable to get SDP record: %s", strerror(-err)); status = HAL_STATUS_FAILED; goto fail; } for (list = recs; list != NULL; list = list->next) { sdp_record_t *rec = list->data; sdp_data_t *data; data = sdp_data_get(rec, SDP_ATTR_MAS_INSTANCE_ID); if (!data) { error("mce: cannot get mas instance id"); continue; } id = data->val.uint8; data = sdp_data_get(rec, SDP_ATTR_SVCNAME_PRIMARY); if (!data) { error("mce: cannot get mas instance name"); continue; } name = data->val.str; name_len = data->unitSize; data = sdp_data_get(rec, SDP_ATTR_SUPPORTED_MESSAGE_TYPES); if (!data) { error("mce: cannot get mas instance msg type"); continue; } msg_type = data->val.uint8; if (sdp_get_access_protos(rec, &protos) < 0) { error("mce: cannot get mas instance sdp protocol list"); continue; } scn = sdp_get_proto_port(protos, RFCOMM_UUID); sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL); sdp_list_free(protos, NULL); if (!scn) { error("mce: cannot get mas instance rfcomm channel"); continue; } size += fill_mce_inst(buf + size, id, scn, msg_type, name, name_len); num_instances++; } status = HAL_STATUS_SUCCESS; fail: ev->num_instances = num_instances; ev->status = status; ipc_send_notif(hal_ipc, HAL_SERVICE_ID_MAP_CLIENT, HAL_EV_MAP_CLIENT_REMOTE_MAS_INSTANCES, size, buf); } static void handle_get_instances(const void *buf, uint16_t len) { const struct hal_cmd_map_client_get_instances *cmd = buf; uint8_t status; bdaddr_t *dst; uuid_t uuid; DBG(""); dst = new0(bdaddr_t, 1); if (!dst) { error("mce: Fail to allocate cb data"); status = HAL_STATUS_FAILED; goto failed; } android2bdaddr(&cmd->bdaddr, dst); sdp_uuid16_create(&uuid, MAP_MSE_SVCLASS_ID); if (bt_search_service(&adapter_addr, dst, &uuid, map_client_sdp_search_cb, dst, free, 0)) { error("mce: Failed to search SDP details"); status = HAL_STATUS_FAILED; goto failed; } status = HAL_STATUS_SUCCESS; failed: ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_MAP_CLIENT, HAL_OP_MAP_CLIENT_GET_INSTANCES, status); } static const struct ipc_handler cmd_handlers[] = { /* HAL_OP_MAP_CLIENT_GET_INSTANCES */ { handle_get_instances, false, sizeof(struct hal_cmd_map_client_get_instances) }, }; bool bt_map_client_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode) { DBG(""); bacpy(&adapter_addr, addr); hal_ipc = ipc; ipc_register(hal_ipc, HAL_SERVICE_ID_MAP_CLIENT, cmd_handlers, G_N_ELEMENTS(cmd_handlers)); return true; } void bt_map_client_unregister(void) { DBG(""); ipc_unregister(hal_ipc, HAL_SERVICE_ID_MAP_CLIENT); hal_ipc = NULL; }