[OTP] Add support for OACP Read
[platform/core/connectivity/bluetooth-frwk.git] / bt-api / bt-otp.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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 #include <gio/gunixfdlist.h>
18
19 #include "bluetooth-api.h"
20 #include "bt-internal-types.h"
21
22 #include "bt-common.h"
23 #include "bt-request-sender.h"
24 #include "bt-event-handler.h"
25
26 static int _bluetooth_handle_get_len(const char *str)
27 {
28         int i;
29         for (i = 0; str && str[i] != '\0'; i++);
30         return i;
31 }
32
33 BT_EXPORT_API int bluetooth_otp_server_init(const char *directory)
34 {
35         int result = BLUETOOTH_ERROR_INTERNAL;
36         bt_user_info_t *user_info;
37         char dir_name[BLUETOOTH_MAX_OTP_SERVER_DIR_NAME];
38         BT_DBG("+");
39
40         BT_CHECK_ENABLED(return);
41
42         user_info = _bt_get_user_data(BT_COMMON);
43         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
44
45         BT_INIT_PARAMS();
46         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
47
48         if (directory)
49                 g_strlcpy(dir_name, directory, sizeof(dir_name));
50         else
51                 dir_name[0] = '\0';
52
53         g_array_append_vals(in_param1, dir_name,
54                         BLUETOOTH_MAX_OTP_SERVER_DIR_NAME);
55
56         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_OTP_SERVER_INIT,
57                 in_param1, in_param2, in_param3, in_param4,
58                 user_info->cb, user_info->user_data);
59
60         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
61
62         BT_DBG("-");
63         return result;
64 }
65
66 BT_EXPORT_API int bluetooth_otp_server_deinit()
67 {
68         int result = BLUETOOTH_ERROR_INTERNAL;
69         bt_user_info_t *user_info;
70         BT_DBG("+");
71
72         BT_CHECK_ENABLED(return);
73
74         user_info = _bt_get_user_data(BT_COMMON);
75         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
76
77         BT_INIT_PARAMS();
78         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
79         BT_DBG("");
80
81         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_OTP_SERVER_DEINIT,
82                 in_param1, in_param2, in_param3, in_param4,
83                 user_info->cb, user_info->user_data);
84
85         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
86
87         BT_DBG("-");
88         return result;
89 }
90
91 BT_EXPORT_API int bluetooth_otp_read_characteristic_value(const char *handle)
92 {
93         char *path;
94         int path_len = 0;
95         bt_user_info_t *user_info;
96         int result = BLUETOOTH_ERROR_INTERNAL;
97         BT_DBG("+");
98
99         BT_CHECK_PARAMETER(handle, return);
100         BT_CHECK_ENABLED_LE(return);
101
102         user_info = _bt_get_user_data(BT_COMMON);
103         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
104
105         BT_INIT_PARAMS();
106         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
107
108         path = g_strdup(handle);
109         path_len = _bluetooth_handle_get_len(path);
110         g_array_append_vals(in_param1, path, path_len);
111         g_free(path);
112
113         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_OTP_READ_VALUE,
114                         in_param1, in_param2, in_param3, in_param4,
115                         user_info->cb, user_info->user_data);
116
117         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
118
119         BT_DBG("-");
120         return result;
121 }
122
123 BT_EXPORT_API int bluetooth_otp_enable_notification(const char *handle)
124 {
125         char *path;
126         int path_len = 0;
127         bt_user_info_t *user_info;
128         int result = BLUETOOTH_ERROR_INTERNAL;
129         BT_DBG("+");
130
131         BT_CHECK_PARAMETER(handle, return);
132         BT_CHECK_ENABLED_LE(return);
133
134         user_info = _bt_get_user_data(BT_COMMON);
135         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
136
137         BT_INIT_PARAMS();
138         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
139
140         path = g_strdup(handle);
141         path_len = _bluetooth_handle_get_len(path);
142         g_array_append_vals(in_param1, path, path_len);
143         g_free(path);
144
145         result = _bt_send_request_async(
146                                         BT_BLUEZ_SERVICE,
147                                         BT_OTP_ENABLE_NOTIFICATION,
148                                         in_param1, in_param2,
149                                         in_param3, in_param4,
150                                         user_info->cb, user_info->user_data);
151
152         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
153
154         BT_DBG("-");
155         return result;
156 }
157
158 BT_EXPORT_API int bluetooth_otp_write_characteristics_value(const char *handle,
159                                                 unsigned char *buf, int length)
160 {
161         char *path;
162         int path_len = 0;
163         bt_user_info_t *user_info;
164         int result = BLUETOOTH_ERROR_INTERNAL;
165         bluetooth_otp_charc_data_t data;
166         BT_DBG("+");
167
168         BT_CHECK_PARAMETER(handle, return);
169         BT_CHECK_PARAMETER(buf, return);
170         BT_CHECK_ENABLED_LE(return);
171
172         user_info = _bt_get_user_data(BT_COMMON);
173         retv_if(user_info->cb == NULL, BLUETOOTH_ERROR_INTERNAL);
174
175         BT_INIT_PARAMS();
176         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
177
178         memset(&data, 0x00, sizeof(bluetooth_otp_charc_data_t));
179
180         data.length = length;
181         if (length > 0)
182                 memcpy(data.data, buf, length);
183
184         path = g_strdup(handle);
185         path_len = _bluetooth_handle_get_len(path);
186
187         /*Fill parameters*/
188         g_array_append_vals(in_param1, path, path_len);
189
190         g_array_append_vals(in_param2, &data,
191                         sizeof(bluetooth_otp_charc_data_t));
192
193         int i;
194         for (i = 0; i < length; i++)
195                 BT_INFO("Value[%d] = %u", i, buf[i]);
196         result = _bt_send_request_async(BT_BLUEZ_SERVICE, BT_OTP_WRITE_VALUE,
197                         in_param1, in_param2, in_param3, in_param4,
198                         user_info->cb, user_info->user_data);
199
200         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
201
202         g_free(path);
203         BT_DBG("-");
204         return result;
205 }
206
207 #define BT_OTP_CLIENT_SERVICE_NAME      "org.otp.client"
208 #define BT_OTP_CLIENT_OBJECT_PATH       "/org/otp/client"
209
210 static const gchar otc_connection_xml[] =
211 "<node name='/'>"
212 " <interface name='org.otp.otc_channel'>"
213 "     <method name='NewConnection'>"
214 "          <arg type='o' name='object' direction='in'/>"
215 "          <arg type='h' name='fd' direction='in'/>"
216 "     </method>"
217 "  </interface>"
218 "</node>";
219
220 GDBusNodeInfo *otp_node_info = NULL;
221 static GDBusConnection *g_conn;
222 static guint g_owner_id = 0;
223
224 static void __new_connection_method(GDBusConnection *connection,
225                                             const gchar *sender,
226                                             const gchar *object_path,
227                                             const gchar *interface_name,
228                                             const gchar *method_name,
229                                             GVariant *parameters,
230                                             GDBusMethodInvocation *invocation,
231                                             gpointer user_data)
232 {
233         BT_DBG("method %s", method_name);
234         if (g_strcmp0(method_name, "NewConnection") == 0) {
235                 int index;
236                 GDBusMessage *msg;
237                 GUnixFDList *fd_list;
238                 char *dev_path;
239                 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
240                 int fd;
241                 bluetooth_otc_info_t *otc_info = NULL;
242                 bt_event_info_t *event_info;
243                 int result = BLUETOOTH_ERROR_NONE;
244
245                 g_variant_get(parameters, "(oh)", &dev_path, &index);
246
247                 msg = g_dbus_method_invocation_get_message(invocation);
248                 fd_list = g_dbus_message_get_unix_fd_list(msg);
249                 if (fd_list == NULL) {
250                         BT_ERR("fd_list is NULL");
251                         return;
252                 }
253
254                 fd = g_unix_fd_list_get(fd_list, index, NULL);
255                 if (fd == -1) {
256                         BT_ERR("Invalid fd return");
257                         return;
258                 }
259
260                 _bt_convert_device_path_to_address(dev_path, address);
261
262                 BT_INFO("OTC Connected fd: %d, address %s", fd, address);
263
264                 otc_info = g_malloc0(sizeof(bluetooth_otc_info_t));
265                 otc_info->fd = fd;
266                 otc_info->connected = TRUE;
267                 otc_info->address = g_strdup(address);
268
269                 event_info = _bt_event_get_cb_data(BT_OTP_EVENT);
270
271                 if (event_info) {
272                         _bt_common_event_cb(BLUETOOTH_EVENT_OTC_STATE_CHANGED,
273                                         result, otc_info, event_info->cb,
274                                         event_info->user_data);
275                 }
276
277                 g_dbus_method_invocation_return_value(invocation, NULL);
278         }
279 }
280
281 static const GDBusInterfaceVTable method_table = {
282         __new_connection_method,
283         NULL,
284         NULL,
285 };
286
287 static void _bt_otp_on_bus_acquired(GDBusConnection *connection,
288                                 const gchar *name, gpointer user_data)
289 {
290         guint object_id;
291         GError *error = NULL;
292
293         BT_DBG("+");
294
295         g_conn = connection;
296
297         object_id = g_dbus_connection_register_object(connection,
298                                                 BT_OTP_CLIENT_OBJECT_PATH,
299                                                 otp_node_info->interfaces[0],
300                                                 &method_table,
301                                                 NULL, NULL, &error);
302         if (object_id == 0) {
303                 BT_ERR("Failed to register method table: %s", error->message);
304                 g_error_free(error);
305                 g_dbus_node_info_unref(otp_node_info);
306         }
307
308         BT_DBG("-");
309 }
310
311 static void _bt_otp_on_name_acquired(GDBusConnection *connection,
312                                         const gchar     *name,
313                                         gpointer user_data)
314 {
315         BT_DBG("");
316 }
317
318 static void _bt_otp_on_name_lost(GDBusConnection *connection,
319                                 const gchar     *name,
320                                 gpointer user_data)
321 {
322         BT_DBG("+");
323
324         if (g_conn) {
325                 g_object_unref(g_conn);
326                 g_conn = NULL;
327         }
328
329         g_dbus_node_info_unref(otp_node_info);
330         BT_DBG("-");
331 }
332
333 int _bt_otp_register_interface(void)
334 {
335         BT_DBG("+");
336         GError *error = NULL;
337         guint owner_id;
338
339         otp_node_info = g_dbus_node_info_new_for_xml(otc_connection_xml,
340                                                                 &error);
341         if (!otp_node_info) {
342                 BT_ERR("Failed to install: %s", error->message);
343                 return BLUETOOTH_ERROR_INTERNAL;
344         }
345
346         owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
347                                 BT_OTP_CLIENT_SERVICE_NAME,
348                                 G_BUS_NAME_OWNER_FLAGS_NONE,
349                                 _bt_otp_on_bus_acquired,
350                                 _bt_otp_on_name_acquired,
351                                 _bt_otp_on_name_lost,
352                                 NULL, NULL);
353         g_owner_id = owner_id;
354         BT_DBG("owner_id is [%d]\n", owner_id);
355
356         BT_DBG("-");
357         return BLUETOOTH_ERROR_NONE;
358 }
359
360 void _bt_otp_unregister_interface(void)
361 {
362         BT_DBG("+");
363
364         g_bus_unown_name(g_owner_id);
365
366         BT_DBG("-");
367 }
368
369 BT_EXPORT_API int bluetooth_otp_connect_otc(const bluetooth_device_address_t *device_address)
370 {
371         int ret = BLUETOOTH_ERROR_INTERNAL;
372
373         BT_CHECK_PARAMETER(device_address, return);
374         BT_CHECK_ENABLED_LE(return);
375
376         BT_INIT_PARAMS();
377         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
378
379         g_array_append_vals(in_param1, device_address,
380                                 sizeof(bluetooth_device_address_t));
381
382         _bt_otp_register_interface();
383
384         ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_LE_OTC_CONNECT,
385                 in_param1, in_param2, in_param3, in_param4, &out_param);
386
387         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
388
389         return ret;
390 }
391
392 BT_EXPORT_API int bluetooth_otp_disconnect_otc(const bluetooth_device_address_t *device_address)
393 {
394         int ret = BLUETOOTH_ERROR_INTERNAL;
395
396         BT_CHECK_PARAMETER(device_address, return);
397         BT_CHECK_ENABLED_LE(return);
398
399         BT_INIT_PARAMS();
400         BT_ALLOC_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
401         /* TODO: Send fd as in_param2 */
402         g_array_append_vals(in_param1, device_address,
403                                 sizeof(bluetooth_device_address_t));
404
405         ret = _bt_send_request(BT_BLUEZ_SERVICE, BT_LE_OTC_DISCONNECT,
406                 in_param1, in_param2, in_param3, in_param4, &out_param);
407
408         _bt_otp_unregister_interface();
409
410         BT_FREE_PARAMS(in_param1, in_param2, in_param3, in_param4, out_param);
411
412         return ret;
413 }