Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / android / hal-pan.c
1 /*
2  * Copyright (C) 2013 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 <stdbool.h>
19 #include <stddef.h>
20 #include <string.h>
21
22 #include "hal-utils.h"
23 #include "hal-log.h"
24 #include "hal.h"
25 #include "hal-msg.h"
26 #include "hal-ipc.h"
27
28 static const btpan_callbacks_t *cbs = NULL;
29
30 static bool interface_ready(void)
31 {
32         return cbs != NULL;
33 }
34
35 static void handle_conn_state(void *buf, uint16_t len, int fd)
36 {
37         struct hal_ev_pan_conn_state *ev = buf;
38
39         if (cbs->connection_state_cb)
40                 cbs->connection_state_cb(ev->state, ev->status,
41                                         (bt_bdaddr_t *) ev->bdaddr,
42                                         ev->local_role, ev->remote_role);
43 }
44
45 static void handle_ctrl_state(void *buf, uint16_t len, int fd)
46 {
47         struct hal_ev_pan_ctrl_state *ev = buf;
48
49 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
50         if (cbs->control_state_cb)
51                 cbs->control_state_cb(ev->state, ev->local_role, ev->status,
52                                                         (char *)ev->name);
53 #else
54         /*
55          * Callback declared in bt_pan.h is 'typedef void
56          * (*btpan_control_state_callback)(btpan_control_state_t state,
57          * bt_status_t error, int local_role, const char* ifname);
58          * But PanService.Java defined it wrong way.
59          * private void onControlStateChanged(int local_role, int state,
60          * int error, String ifname).
61          * First and third parameters are misplaced, so sending data according
62          * to PanService.Java.
63          */
64         if (cbs->control_state_cb)
65                 cbs->control_state_cb(ev->local_role, ev->state, ev->status,
66                                                         (char *)ev->name);
67 #endif
68 }
69
70 /*
71  * handlers will be called from notification thread context,
72  * index in table equals to 'opcode - HAL_MINIMUM_EVENT'
73  */
74 static const struct hal_ipc_handler ev_handlers[] = {
75         /* HAL_EV_PAN_CTRL_STATE */
76         { handle_ctrl_state, false, sizeof(struct hal_ev_pan_ctrl_state) },
77         /* HAL_EV_PAN_CONN_STATE */
78         { handle_conn_state, false, sizeof(struct hal_ev_pan_conn_state) },
79 };
80
81 static bt_status_t pan_enable(int local_role)
82 {
83         struct hal_cmd_pan_enable cmd;
84
85         DBG("");
86
87         if (!interface_ready())
88                 return BT_STATUS_NOT_READY;
89
90         cmd.local_role = local_role;
91
92         return hal_ipc_cmd(HAL_SERVICE_ID_PAN, HAL_OP_PAN_ENABLE,
93                                         sizeof(cmd), &cmd, NULL, NULL, NULL);
94 }
95
96 static int pan_get_local_role(void)
97 {
98         struct hal_rsp_pan_get_role rsp;
99         size_t len = sizeof(rsp);
100         bt_status_t status;
101
102         DBG("");
103
104         if (!interface_ready())
105                 return BTPAN_ROLE_NONE;
106
107         status = hal_ipc_cmd(HAL_SERVICE_ID_PAN, HAL_OP_PAN_GET_ROLE, 0, NULL,
108                                                         &len, &rsp, NULL);
109         if (status != BT_STATUS_SUCCESS)
110                 return BTPAN_ROLE_NONE;
111
112         return rsp.local_role;
113 }
114
115 static bt_status_t pan_connect(const bt_bdaddr_t *bd_addr, int local_role,
116                                         int remote_role)
117 {
118         struct hal_cmd_pan_connect cmd;
119
120         DBG("");
121
122         if (!interface_ready())
123                 return BT_STATUS_NOT_READY;
124
125         memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
126         cmd.local_role = local_role;
127         cmd.remote_role = remote_role;
128
129         return hal_ipc_cmd(HAL_SERVICE_ID_PAN, HAL_OP_PAN_CONNECT,
130                                         sizeof(cmd), &cmd, NULL, NULL, NULL);
131 }
132
133 static bt_status_t pan_disconnect(const bt_bdaddr_t *bd_addr)
134 {
135         struct hal_cmd_pan_disconnect cmd;
136
137         DBG("");
138
139         if (!interface_ready())
140                 return BT_STATUS_NOT_READY;
141
142         memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
143
144         return hal_ipc_cmd(HAL_SERVICE_ID_PAN, HAL_OP_PAN_DISCONNECT,
145                                         sizeof(cmd), &cmd, NULL, NULL, NULL);
146 }
147
148 static bt_status_t pan_init(const btpan_callbacks_t *callbacks)
149 {
150         struct hal_cmd_register_module cmd;
151         int ret;
152
153         DBG("");
154
155         if (interface_ready())
156                 return BT_STATUS_DONE;
157
158         cbs = callbacks;
159
160         hal_ipc_register(HAL_SERVICE_ID_PAN, ev_handlers,
161                                 sizeof(ev_handlers)/sizeof(ev_handlers[0]));
162
163         cmd.service_id = HAL_SERVICE_ID_PAN;
164         cmd.mode = HAL_MODE_DEFAULT;
165         cmd.max_clients = 1;
166
167         ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
168                                         sizeof(cmd), &cmd, NULL, NULL, NULL);
169
170         if (ret != BT_STATUS_SUCCESS) {
171                 cbs = NULL;
172                 hal_ipc_unregister(HAL_SERVICE_ID_PAN);
173         }
174
175         return ret;
176 }
177
178 static void pan_cleanup(void)
179 {
180         struct hal_cmd_unregister_module cmd;
181
182         DBG("");
183
184         if (!interface_ready())
185                 return;
186
187         cmd.service_id = HAL_SERVICE_ID_PAN;
188
189         hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
190                                         sizeof(cmd), &cmd, NULL, NULL, NULL);
191
192         hal_ipc_unregister(HAL_SERVICE_ID_PAN);
193
194         cbs = NULL;
195 }
196
197 static btpan_interface_t pan_if = {
198         .size = sizeof(pan_if),
199         .init = pan_init,
200         .enable = pan_enable,
201         .get_local_role = pan_get_local_role,
202         .connect = pan_connect,
203         .disconnect = pan_disconnect,
204         .cleanup = pan_cleanup
205 };
206
207 btpan_interface_t *bt_get_pan_interface(void)
208 {
209         return &pan_if;
210 }