tizen 2.3.1 release
[framework/connectivity/bluez.git] / android / map-client.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2014  Intel Corporation. All rights reserved.
6  *
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Lesser General Public
10  *  License as published by the Free Software Foundation; either
11  *  version 2.1 of the License, or (at your option) any later version.
12  *
13  *  This library is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  Lesser General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Lesser General Public
19  *  License along with this library; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdbool.h>
29 #include <stdlib.h>
30 #include <stdint.h>
31 #include <glib.h>
32
33 #include "lib/sdp.h"
34 #include "lib/sdp_lib.h"
35 #include "src/sdp-client.h"
36
37 #include "ipc.h"
38 #include "lib/bluetooth.h"
39 #include "map-client.h"
40 #include "src/log.h"
41 #include "hal-msg.h"
42 #include "ipc-common.h"
43 #include "utils.h"
44 #include "src/shared/util.h"
45
46 static struct ipc *hal_ipc = NULL;
47 static bdaddr_t adapter_addr;
48
49 static int fill_mce_inst(void *buf, int32_t id, int32_t scn, int32_t msg_type,
50                                         const void *name, uint8_t name_len)
51 {
52         struct hal_map_client_mas_instance *inst = buf;
53
54         inst->id = id;
55         inst->scn = scn;
56         inst->msg_types = msg_type;
57         inst->name_len = name_len;
58
59         if (name_len)
60                 memcpy(inst->name, name, name_len);
61
62         return sizeof(*inst) + name_len;
63 }
64
65 static void map_client_sdp_search_cb(sdp_list_t *recs, int err, gpointer data)
66 {
67         uint8_t buf[IPC_MTU];
68         struct hal_ev_map_client_remote_mas_instances *ev = (void *) buf;
69         bdaddr_t *dst = data;
70         sdp_list_t *list, *protos;
71         uint8_t status;
72         int32_t id, scn, msg_type, name_len, num_instances = 0;
73         char *name;
74         size_t size;
75
76         size = sizeof(*ev);
77         bdaddr2android(dst, &ev->bdaddr);
78
79         if (err < 0) {
80                 error("mce: Unable to get SDP record: %s", strerror(-err));
81                 status = HAL_STATUS_FAILED;
82                 goto fail;
83         }
84
85         for (list = recs; list != NULL; list = list->next) {
86                 sdp_record_t *rec = list->data;
87                 sdp_data_t *data;
88
89                 data = sdp_data_get(rec, SDP_ATTR_MAS_INSTANCE_ID);
90                 if (!data) {
91                         error("mce: cannot get mas instance id");
92                         continue;
93                 }
94
95                 id = data->val.uint8;
96
97                 data = sdp_data_get(rec, SDP_ATTR_SVCNAME_PRIMARY);
98                 if (!data) {
99                         error("mce: cannot get mas instance name");
100                         continue;
101                 }
102
103                 name = data->val.str;
104                 name_len = data->unitSize;
105
106                 data = sdp_data_get(rec, SDP_ATTR_SUPPORTED_MESSAGE_TYPES);
107                 if (!data) {
108                         error("mce: cannot get mas instance msg type");
109                         continue;
110                 }
111
112                 msg_type = data->val.uint8;
113
114                 if (sdp_get_access_protos(rec, &protos) < 0) {
115                         error("mce: cannot get mas instance sdp protocol list");
116                         continue;
117                 }
118
119                 scn = sdp_get_proto_port(protos, RFCOMM_UUID);
120
121                 sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
122                 sdp_list_free(protos, NULL);
123
124                 if (!scn) {
125                         error("mce: cannot get mas instance rfcomm channel");
126                         continue;
127                 }
128
129                 size += fill_mce_inst(buf + size, id, scn, msg_type, name,
130                                                                 name_len);
131                 num_instances++;
132         }
133
134         status = HAL_STATUS_SUCCESS;
135
136 fail:
137         ev->num_instances = num_instances;
138         ev->status = status;
139
140         ipc_send_notif(hal_ipc, HAL_SERVICE_ID_MAP_CLIENT,
141                         HAL_EV_MAP_CLIENT_REMOTE_MAS_INSTANCES, size, buf);
142 }
143
144 static void handle_get_instances(const void *buf, uint16_t len)
145 {
146         const struct hal_cmd_map_client_get_instances *cmd = buf;
147         uint8_t status;
148         bdaddr_t *dst;
149         uuid_t uuid;
150
151         DBG("");
152
153         dst = new0(bdaddr_t, 1);
154         if (!dst) {
155                 error("mce: Fail to allocate cb data");
156                 status = HAL_STATUS_FAILED;
157                 goto failed;
158         }
159
160         android2bdaddr(&cmd->bdaddr, dst);
161         sdp_uuid16_create(&uuid, MAP_MSE_SVCLASS_ID);
162
163         if (bt_search_service(&adapter_addr, dst, &uuid,
164                                 map_client_sdp_search_cb, dst, free, 0)) {
165                 error("mce: Failed to search SDP details");
166                 status = HAL_STATUS_FAILED;
167                 goto failed;
168         }
169
170         status = HAL_STATUS_SUCCESS;
171
172 failed:
173         ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_MAP_CLIENT,
174                                 HAL_OP_MAP_CLIENT_GET_INSTANCES, status);
175 }
176
177 static const struct ipc_handler cmd_handlers[] = {
178         /* HAL_OP_MAP_CLIENT_GET_INSTANCES */
179         { handle_get_instances, false,
180                         sizeof(struct hal_cmd_map_client_get_instances) },
181 };
182
183 bool bt_map_client_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode)
184 {
185         DBG("");
186
187         bacpy(&adapter_addr, addr);
188
189         hal_ipc = ipc;
190
191         ipc_register(hal_ipc, HAL_SERVICE_ID_MAP_CLIENT, cmd_handlers,
192                                                 G_N_ELEMENTS(cmd_handlers));
193
194         return true;
195 }
196
197 void bt_map_client_unregister(void)
198 {
199         DBG("");
200
201         ipc_unregister(hal_ipc, HAL_SERVICE_ID_MAP_CLIENT);
202         hal_ipc = NULL;
203 }