Modify terms related to signal
[platform/core/iot/iotcon.git] / lib / icl-device.c
1 /*
2  * Copyright (c) 2015 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 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <errno.h>
20 #include <glib.h>
21
22 #include "iotcon.h"
23 #include "ic-utils.h"
24 #include "icl.h"
25 #include "icl-representation.h"
26 #include "icl-dbus.h"
27 #include "icl-dbus-type.h"
28 #include "icl-device.h"
29
30 /**
31  * @brief The maximum length which can be held in a manufacturer name.
32  *
33  * @since_tizen 3.0
34  */
35 #define ICL_MANUFACTURER_NAME_LENGTH_MAX 15
36
37 /**
38  * @brief The maximum length which can be held in a manufacturer url.
39  *
40  * @since_tizen 3.0
41  */
42 #define ICL_MANUFACTURER_URL_LENGTH_MAX 32
43
44
45 typedef struct {
46         iotcon_device_info_cb cb;
47         void *user_data;
48         unsigned int id;
49         int timeout_id;
50 } icl_device_info_s;
51
52 typedef struct {
53         iotcon_platform_info_cb cb;
54         void *user_data;
55         unsigned int id;
56         int timeout_id;
57 } icl_platform_info_s;
58
59 typedef struct {
60         iotcon_tizen_info_cb cb;
61         void *user_data;
62 } icl_tizen_info_s;
63
64
65 API int iotcon_device_info_get_property(iotcon_device_info_h device_info,
66                 iotcon_device_info_e property, char **value)
67 {
68         RETV_IF(NULL == device_info, IOTCON_ERROR_INVALID_PARAMETER);
69         RETV_IF(NULL == value, IOTCON_ERROR_INVALID_PARAMETER);
70
71         switch (property) {
72         case IOTCON_DEVICE_INFO_NAME:
73                 *value = device_info->device_name;
74                 break;
75         case IOTCON_DEVICE_INFO_SPEC_VER:
76                 *value = device_info->spec_ver;
77                 break;
78         case IOTCON_DEVICE_INFO_ID:
79                 *value = device_info->device_id;
80                 break;
81         case IOTCON_DEVICE_INFO_DATA_MODEL_VER:
82                 *value = device_info->data_model_ver;
83                 break;
84         default:
85                 ERR("Invalid property(%d)", property);
86                 return IOTCON_ERROR_INVALID_PARAMETER;
87         }
88
89         return IOTCON_ERROR_NONE;
90 }
91
92 static void _icl_device_info_cb(GDBusConnection *connection,
93                 const gchar *sender_name,
94                 const gchar *object_path,
95                 const gchar *interface_name,
96                 const gchar *signal_name,
97                 GVariant *parameters,
98                 gpointer user_data)
99 {
100         char *uri_path;
101         struct icl_device_info info = {0};
102         icl_device_info_s *cb_container = user_data;
103         iotcon_device_info_cb cb = cb_container->cb;
104
105         if (cb_container->timeout_id)
106                 cb_container->timeout_id = 0;
107
108         g_variant_get(parameters, "(&s&s&s&s&s)", &uri_path, &info.device_name,
109                         &info.spec_ver, &info.device_id, &info.data_model_ver);
110
111         /* From iotivity, we can get uri_path. But, the value is always "/oic/d". */
112
113         if (cb)
114                 cb(&info, IOTCON_ERROR_NONE, cb_container->user_data);
115 }
116
117 static gboolean _icl_timeout_get_device_info(gpointer p)
118 {
119         FN_CALL;
120         icl_device_info_s *cb_container = p;
121         struct icl_device_info info = {0};
122
123         if (NULL == cb_container) {
124                 ERR("cb_container is NULL");
125                 return G_SOURCE_REMOVE;
126         }
127
128         if (cb_container->timeout_id && cb_container->cb)
129                 cb_container->cb(&info, IOTCON_ERROR_TIMEOUT, cb_container->user_data);
130
131         icl_dbus_unsubscribe_signal(cb_container->id);
132
133         return G_SOURCE_REMOVE;
134 }
135
136 API int iotcon_get_device_info(const char *host_address,
137                 iotcon_connectivity_type_e connectivity_type,
138                 iotcon_device_info_cb cb,
139                 void *user_data)
140 {
141         int ret;
142         GError *error = NULL;
143         icl_device_info_s *cb_container;
144         unsigned int sub_id, signal_number;
145         char signal_name[IC_DBUS_SIGNAL_LENGTH] = {0};
146
147         RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
148         RETV_IF(NULL == host_address, IOTCON_ERROR_INVALID_PARAMETER);
149         RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
150
151         signal_number = icl_dbus_generate_signal_number();
152
153         ic_dbus_call_get_device_info_sync(icl_dbus_get_object(), host_address,
154                         connectivity_type, signal_number, &ret, NULL, &error);
155         if (error) {
156                 ERR("ic_dbus_call_get_device_info_sync() Fail(%s)", error->message);
157                 ret = icl_dbus_convert_dbus_error(error->code);
158                 g_error_free(error);
159                 return ret;
160         }
161
162         if (IOTCON_ERROR_NONE != ret) {
163                 ERR("iotcon-daemon Fail(%d)", ret);
164                 return icl_dbus_convert_daemon_error(ret);
165         }
166
167         snprintf(signal_name, sizeof(signal_name), "%s_%u", IC_DBUS_SIGNAL_DEVICE,
168                         signal_number);
169
170         cb_container = calloc(1, sizeof(icl_device_info_s));
171         if (NULL == cb_container) {
172                 ERR("calloc() Fail(%d)", errno);
173                 return IOTCON_ERROR_OUT_OF_MEMORY;
174         }
175
176         cb_container->cb = cb;
177         cb_container->user_data = user_data;
178
179         sub_id = icl_dbus_subscribe_signal(signal_name, cb_container, free,
180                         _icl_device_info_cb);
181         if (0 == sub_id) {
182                 ERR("icl_dbus_subscribe_signal() Fail");
183                 free(cb_container);
184                 return IOTCON_ERROR_DBUS;
185         }
186
187         cb_container->id = sub_id;
188
189         cb_container->timeout_id = g_timeout_add_seconds(icl_dbus_get_timeout(),
190                         _icl_timeout_get_device_info, cb_container);
191
192         return ret;
193 }
194
195 API int iotcon_platform_info_get_property(iotcon_platform_info_h platform_info,
196                 iotcon_platform_info_e property, char **value)
197 {
198         RETV_IF(NULL == platform_info, IOTCON_ERROR_INVALID_PARAMETER);
199         RETV_IF(NULL == value, IOTCON_ERROR_INVALID_PARAMETER);
200
201         switch (property) {
202         case IOTCON_PLATFORM_INFO_ID:
203                 *value = platform_info->platform_id;
204                 break;
205         case IOTCON_PLATFORM_INFO_MANUF_NAME:
206                 *value = platform_info->manuf_name;
207                 break;
208         case IOTCON_PLATFORM_INFO_MANUF_URL:
209                 *value = platform_info->manuf_url;
210                 break;
211         case IOTCON_PLATFORM_INFO_MODEL_NUMBER:
212                 *value = platform_info->model_number;
213                 break;
214         case IOTCON_PLATFORM_INFO_DATE_OF_MANUF:
215                 *value = platform_info->date_of_manuf;
216                 break;
217         case IOTCON_PLATFORM_INFO_PLATFORM_VER:
218                 *value = platform_info->platform_ver;
219                 break;
220         case IOTCON_PLATFORM_INFO_OS_VER:
221                 *value = platform_info->os_ver;
222                 break;
223         case IOTCON_PLATFORM_INFO_HARDWARE_VER:
224                 *value = platform_info->hardware_ver;
225                 break;
226         case IOTCON_PLATFORM_INFO_FIRMWARE_VER:
227                 *value = platform_info->firmware_ver;
228                 break;
229         case IOTCON_PLATFORM_INFO_SUPPORT_URL:
230                 *value = platform_info->support_url;
231                 break;
232         case IOTCON_PLATFORM_INFO_SYSTEM_TIME:
233                 *value = platform_info->system_time;
234                 break;
235         default:
236                 ERR("Invalid property(%d)", property);
237                 return IOTCON_ERROR_INVALID_PARAMETER;
238         }
239
240         return IOTCON_ERROR_NONE;
241 }
242
243
244 static void _icl_platform_info_cb(GDBusConnection *connection,
245                 const gchar *sender_name,
246                 const gchar *object_path,
247                 const gchar *interface_name,
248                 const gchar *signal_name,
249                 GVariant *parameters,
250                 gpointer user_data)
251 {
252         char *uri_path;
253         struct icl_platform_info info = {0};
254         icl_platform_info_s *cb_container = user_data;
255         iotcon_platform_info_cb cb = cb_container->cb;
256
257         if (cb_container->timeout_id)
258                 cb_container->timeout_id = 0;
259
260         g_variant_get(parameters, "(&s&s&s&s&s&s&s&s&s&s&s&s)",
261                         &uri_path,
262                         &info.platform_id,
263                         &info.manuf_name,
264                         &info.manuf_url,
265                         &info.model_number,
266                         &info.date_of_manuf,
267                         &info.platform_ver,
268                         &info.os_ver,
269                         &info.hardware_ver,
270                         &info.firmware_ver,
271                         &info.support_url,
272                         &info.system_time);
273
274         info.manuf_url = ic_utils_dbus_decode_str(info.manuf_url);
275         info.model_number = ic_utils_dbus_decode_str(info.model_number);
276         info.date_of_manuf = ic_utils_dbus_decode_str(info.date_of_manuf);
277         info.platform_ver = ic_utils_dbus_decode_str(info.platform_ver);
278         info.os_ver = ic_utils_dbus_decode_str(info.os_ver);
279         info.hardware_ver = ic_utils_dbus_decode_str(info.hardware_ver);
280         info.firmware_ver = ic_utils_dbus_decode_str(info.firmware_ver);
281         info.support_url = ic_utils_dbus_decode_str(info.support_url);
282         info.system_time = ic_utils_dbus_decode_str(info.system_time);
283
284         /* From iotivity, we can get uri_path. But, the value is always "/oic/p". */
285
286         if (cb)
287                 cb(&info, IOTCON_ERROR_NONE, cb_container->user_data);
288 }
289
290 static gboolean _icl_timeout_get_platform_info(gpointer p)
291 {
292         FN_CALL;
293         icl_platform_info_s *cb_container = p;
294         struct icl_platform_info info = {0};
295
296         if (NULL == cb_container) {
297                 ERR("cb_container is NULL");
298                 return G_SOURCE_REMOVE;
299         }
300
301         if (cb_container->timeout_id && cb_container->cb)
302                 cb_container->cb(&info, IOTCON_ERROR_TIMEOUT, cb_container->user_data);
303
304         icl_dbus_unsubscribe_signal(cb_container->id);
305
306         return G_SOURCE_REMOVE;
307 }
308
309 API int iotcon_get_platform_info(const char *host_address,
310                 iotcon_connectivity_type_e connectivity_type,
311                 iotcon_platform_info_cb cb,
312                 void *user_data)
313 {
314         int ret;
315         GError *error = NULL;
316         icl_platform_info_s *cb_container;
317         unsigned int sub_id, signal_number;
318         char signal_name[IC_DBUS_SIGNAL_LENGTH] = {0};
319
320         RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
321         RETV_IF(NULL == host_address, IOTCON_ERROR_INVALID_PARAMETER);
322         RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
323
324         signal_number = icl_dbus_generate_signal_number();
325
326         ic_dbus_call_get_platform_info_sync(icl_dbus_get_object(), host_address,
327                         connectivity_type, signal_number, &ret, NULL, &error);
328         if (error) {
329                 ERR("ic_dbus_call_get_platform_info_sync() Fail(%s)", error->message);
330                 ret = icl_dbus_convert_dbus_error(error->code);
331                 g_error_free(error);
332                 return ret;
333         }
334
335         if (IOTCON_ERROR_NONE != ret) {
336                 ERR("iotcon-daemon Fail(%d)", ret);
337                 return icl_dbus_convert_daemon_error(ret);
338         }
339
340         snprintf(signal_name, sizeof(signal_name), "%s_%u", IC_DBUS_SIGNAL_PLATFORM,
341                         signal_number);
342
343         cb_container = calloc(1, sizeof(icl_platform_info_s));
344         if (NULL == cb_container) {
345                 ERR("calloc() Fail(%d)", errno);
346                 return IOTCON_ERROR_OUT_OF_MEMORY;
347         }
348
349         cb_container->cb = cb;
350         cb_container->user_data = user_data;
351
352         sub_id = icl_dbus_subscribe_signal(signal_name, cb_container, free,
353                         _icl_platform_info_cb);
354         if (0 == sub_id) {
355                 ERR("icl_dbus_subscribe_signal() Fail");
356                 free(cb_container);
357                 return IOTCON_ERROR_DBUS;
358         }
359
360         cb_container->id = sub_id;
361         cb_container->timeout_id = g_timeout_add_seconds(icl_dbus_get_timeout(),
362                         _icl_timeout_get_platform_info, cb_container);
363
364         return ret;
365 }
366
367
368 static void _icl_tizen_info_cb(GObject *object, GAsyncResult *g_async_res,
369                 gpointer user_data)
370 {
371         int res;
372         GVariant *result;
373         char *device_name;
374         char *tizen_device_id;
375         GError *error = NULL;
376         struct icl_tizen_info info = {0};
377         icl_tizen_info_s *cb_container = user_data;
378         iotcon_tizen_info_cb cb = cb_container->cb;
379
380         ic_dbus_call_get_tizen_info_finish(IC_DBUS(object), &result, g_async_res, &error);
381         if (error) {
382                 ERR("ic_dbus_call_get_tizen_info_finish() Fail(%s)", error->message);
383                 if (cb) {
384                         int ret = icl_dbus_convert_dbus_error(error->code);
385                         cb(&info, ret, cb_container->user_data);
386                 }
387                 g_error_free(error);
388                 /* TODO contain time out error */
389                 free(cb_container);
390                 return;
391         }
392
393         g_variant_get(result, "(&s&si)", &device_name, &tizen_device_id, &res);
394
395         if (IOTCON_ERROR_NONE == res && NULL != ic_utils_dbus_decode_str(tizen_device_id)) {
396                 info.device_name = ic_utils_dbus_decode_str(device_name);
397                 info.tizen_device_id = tizen_device_id;
398         }
399
400         if (cb)
401                 cb(&info, res, cb_container->user_data);
402
403         free(cb_container);
404 }
405
406
407 API int iotcon_get_tizen_info(const char *host_address,
408                 iotcon_connectivity_type_e connectivity_type,
409                 iotcon_tizen_info_cb cb,
410                 void *user_data)
411 {
412         icl_tizen_info_s *cb_container;
413
414         RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
415         RETV_IF(NULL == host_address, IOTCON_ERROR_INVALID_PARAMETER);
416         RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
417
418         cb_container = calloc(1, sizeof(icl_tizen_info_s));
419         if (NULL == cb_container) {
420                 ERR("calloc() Fail(%d)", errno);
421                 return IOTCON_ERROR_OUT_OF_MEMORY;
422         }
423
424         cb_container->cb = cb;
425         cb_container->user_data = user_data;
426
427         ic_dbus_call_get_tizen_info(icl_dbus_get_object(), host_address, connectivity_type,
428                         NULL, _icl_tizen_info_cb, cb_container);
429
430         return IOTCON_ERROR_NONE;
431 }
432
433
434 API int iotcon_tizen_info_get_property(iotcon_tizen_info_h tizen_info,
435                 iotcon_tizen_info_e property, char **value)
436 {
437         RETV_IF(NULL == tizen_info, IOTCON_ERROR_INVALID_PARAMETER);
438         RETV_IF(NULL == value, IOTCON_ERROR_INVALID_PARAMETER);
439
440         switch (property) {
441         case IOTCON_TIZEN_INFO_DEVICE_NAME:
442                 *value = tizen_info->device_name;
443                 break;
444         case IOTCON_TIZEN_INFO_TIZEN_DEVICE_ID:
445                 *value = tizen_info->tizen_device_id;
446                 break;
447         default:
448                 ERR("Invalid property(%d)", property);
449                 return IOTCON_ERROR_INVALID_PARAMETER;
450         }
451
452         return IOTCON_ERROR_NONE;
453 }