Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / android / client / if-hl.c
1 /*
2  * Copyright (C) 2014 Intel Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <stdio.h>
19 #include <ctype.h>
20 #include <unistd.h>
21 #include <string.h>
22
23 #include <hardware/bluetooth.h>
24 #include <hardware/bt_hl.h>
25
26 #include "if-main.h"
27 #include "pollhandler.h"
28 #include "../hal-utils.h"
29
30 SINTMAP(bthl_mdep_role_t, -1, "(unknown)")
31         DELEMENT(BTHL_MDEP_ROLE_SOURCE),
32         DELEMENT(BTHL_MDEP_ROLE_SINK),
33 ENDMAP
34
35 SINTMAP(bthl_channel_type_t, -1, "(unknown)")
36         DELEMENT(BTHL_CHANNEL_TYPE_RELIABLE),
37         DELEMENT(BTHL_CHANNEL_TYPE_STREAMING),
38         DELEMENT(BTHL_CHANNEL_TYPE_ANY),
39 ENDMAP
40
41 SINTMAP(bthl_app_reg_state_t, -1, "(unknown)")
42         DELEMENT(BTHL_APP_REG_STATE_REG_SUCCESS),
43         DELEMENT(BTHL_APP_REG_STATE_REG_FAILED),
44         DELEMENT(BTHL_APP_REG_STATE_DEREG_SUCCESS),
45         DELEMENT(BTHL_APP_REG_STATE_DEREG_FAILED),
46 ENDMAP
47
48 SINTMAP(bthl_channel_state_t, -1, "(unknown)")
49         DELEMENT(BTHL_CONN_STATE_CONNECTING),
50         DELEMENT(BTHL_CONN_STATE_CONNECTED),
51         DELEMENT(BTHL_CONN_STATE_DISCONNECTING),
52         DELEMENT(BTHL_CONN_STATE_DISCONNECTED),
53         DELEMENT(BTHL_CONN_STATE_DESTROYED),
54 ENDMAP
55
56 #define APP_ID_SIZE 20
57 #define MDEP_CFG_SIZE 10
58 #define CHANNEL_ID_SIZE 50
59
60 struct channel_info {
61         int fd;
62 };
63
64 struct mdep_cfg {
65         uint8_t role;
66         struct channel_info channel[CHANNEL_ID_SIZE];
67 };
68
69 struct {
70         struct mdep_cfg mdep[MDEP_CFG_SIZE];
71 } app[APP_ID_SIZE];
72
73 const bthl_interface_t *if_hl = NULL;
74
75 static void app_reg_state_cb(int app_id, bthl_app_reg_state_t state)
76 {
77         haltest_info("%s: app_id=%d app_reg_state=%s\n", __func__,
78                                 app_id, bthl_app_reg_state_t2str(state));
79 }
80
81 static void channel_state_cb(int app_id, bt_bdaddr_t *bd_addr,
82                                         int index, int channel_id,
83                                         bthl_channel_state_t state, int fd)
84 {
85         char addr[MAX_ADDR_STR_LEN];
86
87         haltest_info("%s: app_id=%d bd_addr=%s mdep_cfg_index=%d\n"
88                         "channel_id=%d channel_state=%s fd=%d\n", __func__,
89                         app_id, bt_bdaddr_t2str(bd_addr, addr), index,
90                         channel_id, bthl_channel_state_t2str(state), fd);
91
92         if (app_id >= APP_ID_SIZE || index >= MDEP_CFG_SIZE
93                         || channel_id >= CHANNEL_ID_SIZE) {
94                 haltest_error("exceeds maximum limit");
95                 return;
96         }
97
98         if (state == BTHL_CONN_STATE_CONNECTED) {
99                 app[app_id].mdep[index].channel[channel_id].fd = fd;
100
101                 /*
102                  * PTS expects dummy data on fd when it
103                  * connects in source role.
104                  */
105                 if (app[app_id].mdep[index].role == BTHL_MDEP_ROLE_SOURCE)
106                         if (write(fd, "0", sizeof("0")) < 0)
107                                 haltest_error("writing data on fd failed\n");
108
109                 return;
110         }
111
112         if (state == BTHL_CONN_STATE_DISCONNECTED ||
113                         state == BTHL_CONN_STATE_DESTROYED) {
114                 if (app[app_id].mdep[index].channel[channel_id].fd >= 0) {
115                         close(app[app_id].mdep[index].channel[channel_id].fd);
116                         app[app_id].mdep[index].channel[channel_id].fd = -1;
117                 }
118         }
119 }
120
121 static bthl_callbacks_t hl_cbacks = {
122         .size = sizeof(hl_cbacks),
123         .app_reg_state_cb = app_reg_state_cb,
124         .channel_state_cb = channel_state_cb,
125 };
126
127 /* init */
128
129 static void init_p(int argc, const char **argv)
130 {
131         int i, j, k;
132
133         for (i = 0; i < APP_ID_SIZE; i++) {
134                 for (j = 0; j < MDEP_CFG_SIZE; j++) {
135                         app[i].mdep[j].role = 0;
136                         for (k = 0; k < CHANNEL_ID_SIZE; k++)
137                                 app[i].mdep[j].channel[k].fd = -1;
138                 }
139         }
140
141
142         RETURN_IF_NULL(if_hl);
143
144         EXEC(if_hl->init, &hl_cbacks);
145 }
146
147 /* register_application */
148
149 static void register_application_p(int argc, const char **argv)
150 {
151         bthl_reg_param_t reg;
152         uint16_t mdep_argc_init, mdep_argc_off;
153         int app_id = -1;
154         int i;
155
156         RETURN_IF_NULL(if_hl);
157
158         if (argc <= 2) {
159                 haltest_error("No app name is specified\n");
160                 return;
161         }
162
163         if (argc <= 3) {
164                 haltest_error("No provider is specified\n");
165                 return;
166         }
167
168         if (argc <= 4) {
169                 haltest_error("No service name is specified\n");
170                 return;
171         }
172
173         if (argc <= 5) {
174                 haltest_error("No service description is specified\n");
175                 return;
176         }
177
178         if (argc <= 6) {
179                 haltest_error("No num of mdeps is specified\n");
180                 return;
181         }
182
183         memset(&reg, 0, sizeof(reg));
184
185         if (argc != ((atoi(argv[6]) * 4) + 7)) {
186                 haltest_error("mdep cfg argumetns are not proper\n");
187                 return;
188         }
189
190         reg.application_name = argv[2];
191
192         if (strcmp("-", argv[3]))
193                 reg.provider_name = argv[3];
194
195         if (strcmp("-", argv[4]))
196                 reg.srv_name = argv[4];
197
198         if (strcmp("-", argv[5]))
199                 reg.srv_desp = argv[5];
200
201         reg.number_of_mdeps = atoi(argv[6]);
202
203         reg.mdep_cfg = malloc(reg.number_of_mdeps * sizeof(bthl_mdep_cfg_t));
204         if (!reg.mdep_cfg) {
205                 haltest_error("malloc failed\n");
206                 return;
207         }
208         mdep_argc_init = 7;
209
210         for (i = 0; i < reg.number_of_mdeps; i++) {
211                 mdep_argc_off = mdep_argc_init + (4 * i);
212                 reg.mdep_cfg[i].mdep_role =
213                                 str2bthl_mdep_role_t(argv[mdep_argc_off]);
214                 reg.mdep_cfg[i].data_type = atoi(argv[mdep_argc_off + 1]);
215                 reg.mdep_cfg[i].channel_type =
216                         str2bthl_channel_type_t(argv[mdep_argc_off + 2]);
217
218                 if (!strcmp("-", argv[mdep_argc_off + 3])) {
219                         reg.mdep_cfg[i].mdep_description = NULL;
220                         continue;
221                 }
222
223                 reg.mdep_cfg[i].mdep_description = argv[mdep_argc_off + 3];
224         }
225
226         EXEC(if_hl->register_application, &reg, &app_id);
227
228         for (i = 0; i < reg.number_of_mdeps; i++)
229                 app[app_id].mdep[i].role = reg.mdep_cfg[i].mdep_role;
230
231         free(reg.mdep_cfg);
232 }
233
234 /* unregister_application */
235
236 static void unregister_application_p(int argc, const char **argv)
237 {
238         uint32_t app_id;
239
240         RETURN_IF_NULL(if_hl);
241
242         if (argc <= 2) {
243                 haltest_error("No app id is specified");
244                 return;
245         }
246
247         app_id = (uint32_t) atoi(argv[2]);
248
249         EXEC(if_hl->unregister_application, app_id);
250 }
251
252 /* connect_channel */
253
254 static void connect_channel_p(int argc, const char **argv)
255 {
256         uint32_t app_id, mdep_cfg_index;
257         int channel_id = -1;
258         bt_bdaddr_t bd_addr;
259
260         RETURN_IF_NULL(if_hl);
261
262         if (argc <= 2) {
263                 haltest_error("No app id is specified");
264                 return;
265         }
266
267         VERIFY_ADDR_ARG(3, &bd_addr);
268
269         if (argc <= 4) {
270                 haltest_error("No mdep cfg index is specified");
271                 return;
272         }
273
274         app_id = (uint32_t) atoi(argv[2]);
275         mdep_cfg_index = (uint32_t) atoi(argv[4]);
276
277         EXEC(if_hl->connect_channel, app_id, &bd_addr, mdep_cfg_index,
278                                                                 &channel_id);
279 }
280
281 /* destroy_channel */
282
283 static void destroy_channel_p(int argc, const char **argv)
284 {
285         uint32_t channel_id;
286
287         RETURN_IF_NULL(if_hl);
288
289         if (argc <= 2) {
290                 haltest_error("No channel id is specified");
291                 return;
292         }
293
294         channel_id = (uint32_t) atoi(argv[2]);
295
296         EXEC(if_hl->destroy_channel, channel_id);
297 }
298
299 /* close_channel */
300
301 static void close_channel_p(int argc, const char **argv)
302 {
303         uint32_t app_id;
304         uint8_t index;
305         int channel_id;
306
307         RETURN_IF_NULL(if_hl);
308
309         if (argc <= 2) {
310                 haltest_error("No app id is specified");
311                 return;
312         }
313
314         if (argc <= 3) {
315                 haltest_error("No mdep_cfg_index is specified");
316                 return;
317         }
318
319         if (argc <= 4) {
320                 haltest_error("No channel_id is specified");
321                 return;
322         }
323
324         app_id = (uint32_t) atoi(argv[2]);
325         if (app_id >= APP_ID_SIZE) {
326                 haltest_error("Wrong app_id specified: %u\n", app_id);
327                 return;
328         }
329
330         index = (uint8_t) atoi(argv[3]);
331         if (index >= MDEP_CFG_SIZE) {
332                 haltest_error("Wrong mdep cfg index: %u\n", index);
333                 return;
334         }
335
336         channel_id = atoi(argv[4]);
337         if (channel_id >= CHANNEL_ID_SIZE) {
338                 haltest_error("Wrong channel id: %u\n", channel_id);
339                 return;
340         }
341
342         if (app[app_id].mdep[index].channel[channel_id].fd >= 0) {
343                 shutdown(app[app_id].mdep[index].channel[channel_id].fd,
344                                                                 SHUT_RDWR);
345                 app[app_id].mdep[index].channel[channel_id].fd = -1;
346         }
347 }
348
349 /* cleanup */
350
351 static void cleanup_p(int argc, const char **argv)
352 {
353         RETURN_IF_NULL(if_hl);
354
355         EXECV(if_hl->cleanup);
356         if_hl = NULL;
357 }
358
359 static struct method methods[] = {
360         STD_METHOD(init),
361         STD_METHODH(register_application,
362                 "<app_name> <provider_name> <srv_name> <srv_descr>\n"
363                 "<num_of_mdeps>\n"
364                 "[[<mdep_role>] [<data_type>] [<channel_type>] [<mdep_descr>]]"
365                 "..."),
366         STD_METHODH(unregister_application, "<app_id>"),
367         STD_METHODH(connect_channel, "<app_id> <bd_addr> <mdep_cfg_index>"),
368         STD_METHODH(destroy_channel, "<channel_id>"),
369         STD_METHODH(close_channel, "<app_id> <mdep_cfg_index> <channel_id>"),
370         STD_METHOD(cleanup),
371         END_METHOD
372 };
373
374 const struct interface hl_if = {
375         .name = "hl",
376         .methods = methods
377 };