Revise file names
[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                 g_source_remove(cb_container->timeout_id);
107                 cb_container->timeout_id = 0;
108         }
109
110         g_variant_get(parameters, "(&s&s&s&s&s)", &uri_path, &info.device_name,
111                         &info.spec_ver, &info.device_id, &info.data_model_ver);
112
113         /* From iotivity, we can get uri_path. But, the value is always "/oic/d". */
114
115         if (cb)
116                 cb(&info, IOTCON_ERROR_NONE, cb_container->user_data);
117 }
118
119 static gboolean _icl_timeout_get_device_info(gpointer p)
120 {
121         FN_CALL;
122         icl_device_info_s *cb_container = p;
123         struct icl_device_info info = {0};
124
125         if (NULL == cb_container) {
126                 ERR("cb_container is NULL");
127                 return G_SOURCE_REMOVE;
128         }
129
130         if (cb_container->cb)
131                 cb_container->cb(&info, IOTCON_ERROR_TIMEOUT, cb_container->user_data);
132
133         icl_dbus_unsubscribe_signal(cb_container->id);
134
135         return G_SOURCE_REMOVE;
136 }
137
138 API int iotcon_get_device_info(const char *host_address,
139                 iotcon_connectivity_type_e connectivity_type,
140                 iotcon_device_info_cb cb,
141                 void *user_data)
142 {
143         GError *error = NULL;
144         unsigned int sub_id;
145         int ret, signal_number;
146         char signal_name[IC_DBUS_SIGNAL_LENGTH] = {0};
147         icl_device_info_s *cb_container;
148
149         RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
150         RETV_IF(NULL == host_address, IOTCON_ERROR_INVALID_PARAMETER);
151         RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
152
153         signal_number = icl_dbus_generate_signal_number();
154
155         ic_dbus_call_get_device_info_sync(icl_dbus_get_object(), host_address,
156                         connectivity_type, signal_number, &ret, NULL, &error);
157         if (error) {
158                 ERR("ic_dbus_call_get_device_info_sync() Fail(%s)", error->message);
159                 ret = icl_dbus_convert_dbus_error(error->code);
160                 g_error_free(error);
161                 return ret;
162         }
163
164         if (IOTCON_ERROR_NONE != ret) {
165                 ERR("iotcon-daemon Fail(%d)", ret);
166                 return icl_dbus_convert_daemon_error(ret);
167         }
168
169         snprintf(signal_name, sizeof(signal_name), "%s_%u", IC_DBUS_SIGNAL_DEVICE,
170                         signal_number);
171
172         cb_container = calloc(1, sizeof(icl_device_info_s));
173         if (NULL == cb_container) {
174                 ERR("calloc() Fail(%d)", errno);
175                 return IOTCON_ERROR_OUT_OF_MEMORY;
176         }
177
178         cb_container->cb = cb;
179         cb_container->user_data = user_data;
180
181         sub_id = icl_dbus_subscribe_signal(signal_name, cb_container, free,
182                         _icl_device_info_cb);
183         if (0 == sub_id) {
184                 ERR("icl_dbus_subscribe_signal() Fail");
185                 free(cb_container);
186                 return IOTCON_ERROR_DBUS;
187         }
188
189         cb_container->id = sub_id;
190
191         cb_container->timeout_id = g_timeout_add_seconds(icl_dbus_get_timeout(),
192                         _icl_timeout_get_device_info, cb_container);
193
194         return ret;
195 }
196
197 API int iotcon_platform_info_get_property(iotcon_platform_info_h platform_info,
198                 iotcon_platform_info_e property, char **value)
199 {
200         RETV_IF(NULL == platform_info, IOTCON_ERROR_INVALID_PARAMETER);
201         RETV_IF(NULL == value, IOTCON_ERROR_INVALID_PARAMETER);
202
203         switch (property) {
204         case IOTCON_PLATFORM_INFO_ID:
205                 *value = platform_info->platform_id;
206                 break;
207         case IOTCON_PLATFORM_INFO_MANUF_NAME:
208                 *value = platform_info->manuf_name;
209                 break;
210         case IOTCON_PLATFORM_INFO_MANUF_URL:
211                 *value = platform_info->manuf_url;
212                 break;
213         case IOTCON_PLATFORM_INFO_MODEL_NUMBER:
214                 *value = platform_info->model_number;
215                 break;
216         case IOTCON_PLATFORM_INFO_DATE_OF_MANUF:
217                 *value = platform_info->date_of_manuf;
218                 break;
219         case IOTCON_PLATFORM_INFO_PLATFORM_VER:
220                 *value = platform_info->platform_ver;
221                 break;
222         case IOTCON_PLATFORM_INFO_OS_VER:
223                 *value = platform_info->os_ver;
224                 break;
225         case IOTCON_PLATFORM_INFO_HARDWARE_VER:
226                 *value = platform_info->hardware_ver;
227                 break;
228         case IOTCON_PLATFORM_INFO_FIRMWARE_VER:
229                 *value = platform_info->firmware_ver;
230                 break;
231         case IOTCON_PLATFORM_INFO_SUPPORT_URL:
232                 *value = platform_info->support_url;
233                 break;
234         case IOTCON_PLATFORM_INFO_SYSTEM_TIME:
235                 *value = platform_info->system_time;
236                 break;
237         default:
238                 ERR("Invalid property(%d)", property);
239                 return IOTCON_ERROR_INVALID_PARAMETER;
240         }
241
242         return IOTCON_ERROR_NONE;
243 }
244
245
246 static void _icl_platform_info_cb(GDBusConnection *connection,
247                 const gchar *sender_name,
248                 const gchar *object_path,
249                 const gchar *interface_name,
250                 const gchar *signal_name,
251                 GVariant *parameters,
252                 gpointer user_data)
253 {
254         char *uri_path;
255         struct icl_platform_info info = {0};
256         icl_platform_info_s *cb_container = user_data;
257         iotcon_platform_info_cb cb = cb_container->cb;
258
259         if (cb_container->timeout_id) {
260                 g_source_remove(cb_container->timeout_id);
261                 cb_container->timeout_id = 0;
262         }
263
264         g_variant_get(parameters, "(&s&s&s&s&s&s&s&s&s&s&s&s)",
265                         &uri_path,
266                         &info.platform_id,
267                         &info.manuf_name,
268                         &info.manuf_url,
269                         &info.model_number,
270                         &info.date_of_manuf,
271                         &info.platform_ver,
272                         &info.os_ver,
273                         &info.hardware_ver,
274                         &info.firmware_ver,
275                         &info.support_url,
276                         &info.system_time);
277
278         /* From iotivity, we can get uri_path. But, the value is always "/oic/p". */
279
280         if (cb)
281                 cb(&info, IOTCON_ERROR_NONE, cb_container->user_data);
282 }
283
284 static gboolean _icl_timeout_get_platform_info(gpointer p)
285 {
286         FN_CALL;
287         icl_platform_info_s *cb_container = p;
288         struct icl_platform_info info = {0};
289
290         if (NULL == cb_container) {
291                 ERR("cb_container is NULL");
292                 return G_SOURCE_REMOVE;
293         }
294
295         if (cb_container->cb)
296                 cb_container->cb(&info, IOTCON_ERROR_TIMEOUT, cb_container->user_data);
297
298         icl_dbus_unsubscribe_signal(cb_container->id);
299
300         return G_SOURCE_REMOVE;
301 }
302
303 API int iotcon_get_platform_info(const char *host_address,
304                 iotcon_connectivity_type_e connectivity_type,
305                 iotcon_platform_info_cb cb,
306                 void *user_data)
307 {
308         GError *error = NULL;
309         unsigned int sub_id;
310         int ret, signal_number;
311         char signal_name[IC_DBUS_SIGNAL_LENGTH] = {0};
312         icl_platform_info_s *cb_container;
313
314         RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
315         RETV_IF(NULL == host_address, IOTCON_ERROR_INVALID_PARAMETER);
316         RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
317
318         signal_number = icl_dbus_generate_signal_number();
319
320         ic_dbus_call_get_platform_info_sync(icl_dbus_get_object(), host_address,
321                         connectivity_type, signal_number, &ret, NULL, &error);
322         if (error) {
323                 ERR("ic_dbus_call_get_platform_info_sync() Fail(%s)", error->message);
324                 ret = icl_dbus_convert_dbus_error(error->code);
325                 g_error_free(error);
326                 return ret;
327         }
328
329         if (IOTCON_ERROR_NONE != ret) {
330                 ERR("iotcon-daemon Fail(%d)", ret);
331                 return icl_dbus_convert_daemon_error(ret);
332         }
333
334         snprintf(signal_name, sizeof(signal_name), "%s_%u", IC_DBUS_SIGNAL_PLATFORM,
335                         signal_number);
336
337         cb_container = calloc(1, sizeof(icl_platform_info_s));
338         if (NULL == cb_container) {
339                 ERR("calloc() Fail(%d)", errno);
340                 return IOTCON_ERROR_OUT_OF_MEMORY;
341         }
342
343         cb_container->cb = cb;
344         cb_container->user_data = user_data;
345
346         sub_id = icl_dbus_subscribe_signal(signal_name, cb_container, free,
347                         _icl_platform_info_cb);
348         if (0 == sub_id) {
349                 ERR("icl_dbus_subscribe_signal() Fail");
350                 free(cb_container);
351                 return IOTCON_ERROR_DBUS;
352         }
353
354         cb_container->id = sub_id;
355         cb_container->timeout_id = g_timeout_add_seconds(icl_dbus_get_timeout(),
356                         _icl_timeout_get_platform_info, cb_container);
357
358         return ret;
359 }
360
361
362 static void _icl_tizen_info_cb(GObject *object, GAsyncResult *g_async_res,
363                 gpointer user_data)
364 {
365         int res;
366         GVariant *result;
367         char *device_name;
368         char *tizen_device_id;
369         GError *error = NULL;
370         struct icl_tizen_info info = {0};
371         icl_tizen_info_s *cb_container = user_data;
372         iotcon_tizen_info_cb cb = cb_container->cb;
373
374         ic_dbus_call_get_tizen_info_finish(IC_DBUS(object), &result, g_async_res, &error);
375         if (error) {
376                 ERR("ic_dbus_call_get_tizen_info_finish() Fail(%s)", error->message);
377                 if (cb) {
378                         int ret = icl_dbus_convert_dbus_error(error->code);
379                         cb(&info, ret, cb_container->user_data);
380                 }
381                 g_error_free(error);
382                 /* TODO contain time out error */
383                 free(cb_container);
384                 return;
385         }
386
387         g_variant_get(result, "(&s&si)", &device_name, &tizen_device_id, &res);
388
389         if (IOTCON_ERROR_NONE == res && NULL != ic_utils_dbus_decode_str(tizen_device_id)) {
390                 info.device_name = ic_utils_dbus_decode_str(device_name);
391                 info.tizen_device_id = tizen_device_id;
392         }
393
394         if (cb)
395                 cb(&info, res, cb_container->user_data);
396
397         free(cb_container);
398 }
399
400
401 API int iotcon_get_tizen_info(const char *host_address,
402                 iotcon_connectivity_type_e connectivity_type,
403                 iotcon_tizen_info_cb cb,
404                 void *user_data)
405 {
406         icl_tizen_info_s *cb_container;
407
408         RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
409         RETV_IF(NULL == host_address, IOTCON_ERROR_INVALID_PARAMETER);
410         RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
411
412         cb_container = calloc(1, sizeof(icl_tizen_info_s));
413         if (NULL == cb_container) {
414                 ERR("calloc() Fail(%d)", errno);
415                 return IOTCON_ERROR_OUT_OF_MEMORY;
416         }
417
418         cb_container->cb = cb;
419         cb_container->user_data = user_data;
420
421         ic_dbus_call_get_tizen_info(icl_dbus_get_object(), host_address, connectivity_type,
422                         NULL, _icl_tizen_info_cb, cb_container);
423
424         return IOTCON_ERROR_NONE;
425 }
426
427
428 API int iotcon_tizen_info_get_property(iotcon_tizen_info_h tizen_info,
429                 iotcon_tizen_info_e property, char **value)
430 {
431         RETV_IF(NULL == tizen_info, IOTCON_ERROR_INVALID_PARAMETER);
432         RETV_IF(NULL == value, IOTCON_ERROR_INVALID_PARAMETER);
433
434         switch (property) {
435         case IOTCON_TIZEN_INFO_DEVICE_NAME:
436                 *value = tizen_info->device_name;
437                 break;
438         case IOTCON_TIZEN_INFO_TIZEN_DEVICE_ID:
439                 *value = tizen_info->tizen_device_id;
440                 break;
441         default:
442                 ERR("Invalid property(%d)", property);
443                 return IOTCON_ERROR_INVALID_PARAMETER;
444         }
445
446         return IOTCON_ERROR_NONE;
447 }