b40748c377051a1e1516bcca1d90259238ec349e
[platform/core/connectivity/zigbee-manager.git] / zigbee-daemon / zigbee-interface / src / zigbee_service_dbus_interface.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Contact: Suresh Kumar N (suresh.n@samsung.com)
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <glib.h>
24 #include <dlog.h>
25
26 #include <zblib.h>
27 #include <zblib_service.h>
28 #include <zblib_service_interface.h>
29
30 #include "zigbee_service_interface.h"
31 #include "zigbee_service_interface_common.h"
32 #include "zigbee_service_dbus_interface.h"
33
34 /**< ZigBee D-BUS service interface name */
35 #define ZIGBEE_DBUS_SERVICE_INTERFACE_NAME "zigbee-dbus"
36
37 static gboolean zigbee_on_manager_get_zigbee_state(ZigbeeManager *zigbee_mgr,
38         GDBusMethodInvocation *invocation, gpointer user_data)
39 {
40         Z_LOGI("Entered");
41
42         NOT_USED(zigbee_mgr);
43         NOT_USED(invocation);
44         NOT_USED(user_data);
45
46         /*
47          * TODO -
48          * Create and send request for processing
49          */
50
51         return TRUE;
52 }
53
54 static void zigbee_service_dbus_interface_initialize_interfaces(ZigBeeServiceInterface *service_interface,
55         ZigbeeObjectSkeleton *zigbee_object)
56 {
57         gboolean ret;
58
59         ret = zigbee_service_dbus_interface_zcl_alarm_init(service_interface, zigbee_object);
60         Z_LOGD("ret: %d", ret);
61
62         ret = zigbee_service_dbus_interface_custom_init(service_interface, zigbee_object);
63         Z_LOGD("ret: %d", ret);
64
65         ret = zigbee_service_dbus_interface_zcl_door_lock_init(service_interface, zigbee_object);
66         Z_LOGD("ret: %d", ret);
67
68         ret = zigbee_service_dbus_interface_zcl_fan_control_init(service_interface, zigbee_object);
69         Z_LOGD("ret: %d", ret);
70
71         ret = zigbee_service_dbus_interface_zcl_level_control_init(service_interface, zigbee_object);
72         Z_LOGD("ret: %d", ret);
73
74         ret = zigbee_service_dbus_interface_mfglib_control_init(service_interface, zigbee_object);
75         Z_LOGD("ret: %d", ret);
76
77         ret = zigbee_service_dbus_interface_zcl_on_off_init(service_interface, zigbee_object);
78         Z_LOGD("ret: %d", ret);
79
80         ret = zigbee_service_dbus_interface_service_init(service_interface, zigbee_object);
81         Z_LOGD("ret: %d", ret);
82
83         ret = zigbee_service_dbus_interface_zcl_thermostat_init(service_interface, zigbee_object);
84         Z_LOGD("ret: %d", ret);
85
86         ret = zigbee_service_dbus_interface_zcl_basic_init(service_interface, zigbee_object);
87         Z_LOGD("ret: %d", ret);
88
89         ret = zigbee_service_dbus_interface_zcl_color_control_init(service_interface, zigbee_object);
90         Z_LOGD("ret: %d", ret);
91
92         ret = zigbee_service_dbus_interface_zcl_global_control_init(service_interface, zigbee_object);
93         Z_LOGD("ret: %d", ret);
94
95         ret = zigbee_service_dbus_interface_zcl_group_init(service_interface, zigbee_object);
96         Z_LOGD("ret: %d", ret);
97
98         ret = zigbee_service_dbus_interface_zcl_ias_zone_init(service_interface, zigbee_object);
99         Z_LOGD("ret: %d", ret);
100
101         ret = zigbee_service_dbus_interface_zcl_identify_init(service_interface, zigbee_object);
102         Z_LOGD("ret: %d", ret);
103
104         ret = zigbee_service_dbus_interface_zcl_poll_control_init(service_interface, zigbee_object);
105         Z_LOGD("ret: %d", ret);
106
107         ret = zigbee_service_dbus_interface_zcl_scene_init(service_interface, zigbee_object);
108         Z_LOGD("ret: %d", ret);
109
110         ret = zigbee_service_dbus_interface_zdo_bind_init(service_interface, zigbee_object);
111         Z_LOGD("ret: %d", ret);
112
113         ret = zigbee_service_dbus_interface_zdo_dev_control_init(service_interface, zigbee_object);
114         Z_LOGD("ret: %d", ret);
115 }
116
117 static void zigbee_service_dbus_interface_noti_cb(ZigBeeServiceInterface *service_interface,
118         guint noti_id, gpointer noti_data, guint noti_data_len, gpointer noti_cb_data)
119 {
120         ZblibDriverType_e driver_type;
121         guint notification_id;
122
123         if (NULL == service_interface) {
124                 Z_LOGE("service_interface is NULL");
125                 return;
126         }
127
128         /* Extract driver_type */
129         driver_type = ((noti_id & 0xFF000000) >> 24);
130
131         /* Extract notification_id */
132         notification_id = (noti_id & 0x000000FF);
133
134         Z_LOGI("Driver type: [%d] Notification ID: [%d]", driver_type, notification_id);
135
136         switch (driver_type) {
137         case ZBLIB_DRIVER_TYPE_ZCL_ALARM: {
138                 zigbee_service_dbus_interface_zcl_alarm_notification(service_interface,
139                         notification_id, noti_data, noti_data_len, noti_cb_data);
140         }
141         break;
142
143         case ZBLIB_DRIVER_TYPE_CUSTOM: {
144                 zigbee_service_dbus_interface_custom_notification(service_interface,
145                         notification_id, noti_data, noti_data_len, noti_cb_data);
146         }
147         break;
148
149         case ZBLIB_DRIVER_TYPE_ZCL_DOOR_LOCK: {
150                 zigbee_service_dbus_interface_zcl_door_lock_notification(service_interface,
151                         notification_id, noti_data, noti_data_len, noti_cb_data);
152         }
153         break;
154
155         case ZBLIB_DRIVER_TYPE_ZCL_FAN_CONTROL: {
156                 zigbee_service_dbus_interface_zcl_fan_control_notification(service_interface,
157                         notification_id, noti_data, noti_data_len, noti_cb_data);
158         }
159         break;
160
161         case ZBLIB_DRIVER_TYPE_ZCL_LEVEL_CONTROL: {
162                 zigbee_service_dbus_interface_zcl_level_control_notification(service_interface,
163                         notification_id, noti_data, noti_data_len, noti_cb_data);
164         }
165         break;
166
167         case ZBLIB_DRIVER_TYPE_MFGLIB_CONTROL: {
168                 zigbee_service_dbus_interface_mfglib_control_notification(service_interface,
169                         notification_id, noti_data, noti_data_len, noti_cb_data);
170         }
171         break;
172
173         case ZBLIB_DRIVER_TYPE_ZCL_ON_OFF: {
174                 zigbee_service_dbus_interface_zcl_on_off_notification(service_interface,
175                         notification_id, noti_data, noti_data_len, noti_cb_data);
176         }
177         break;
178
179         case ZBLIB_DRIVER_TYPE_SERVICE: {
180                 zigbee_service_dbus_interface_service_notification(service_interface,
181                         notification_id, noti_data, noti_data_len, noti_cb_data);
182         }
183         break;
184
185         case ZBLIB_DRIVER_TYPE_ZCL_THERMOSTAT: {
186                 zigbee_service_dbus_interface_zcl_thermostat_notification(service_interface,
187                         notification_id, noti_data, noti_data_len, noti_cb_data);
188         }
189         break;
190
191         case ZBLIB_DRIVER_TYPE_ZCL_BASIC: {
192                 zigbee_service_dbus_interface_zcl_basic_notification(service_interface,
193                         notification_id, noti_data, noti_data_len, noti_cb_data);
194         }
195         break;
196
197         case ZBLIB_DRIVER_TYPE_ZCL_GLOBAL_CONTROL: {
198                 zigbee_service_dbus_interface_zcl_global_control_notification(service_interface,
199                         notification_id, noti_data, noti_data_len, noti_cb_data);
200         }
201         break;
202
203         case ZBLIB_DRIVER_TYPE_ZCL_IAS_ZONE: {
204                 zigbee_service_dbus_interface_zcl_ias_zone_notification(service_interface,
205                         notification_id, noti_data, noti_data_len, noti_cb_data);
206         }
207         break;
208
209         case ZBLIB_DRIVER_TYPE_ZCL_IDENTIFY: {
210                 zigbee_service_dbus_interface_zcl_identify_notification(service_interface,
211                         notification_id, noti_data, noti_data_len, noti_cb_data);
212         }
213         break;
214
215         case ZBLIB_DRIVER_TYPE_ZCL_COLOR_CONTROL: {
216                 zigbee_service_dbus_interface_zcl_color_control_notification(service_interface,
217                         notification_id, noti_data, noti_data_len, noti_cb_data);
218         }
219         break;
220
221         case ZBLIB_DRIVER_TYPE_ZCL_GROUP: {
222                 zigbee_service_dbus_interface_zcl_group_notification(service_interface,
223                         notification_id, noti_data, noti_data_len, noti_cb_data);
224         }
225         break;
226
227         case ZBLIB_DRIVER_TYPE_ZCL_POLL_CONTROL: {
228                 zigbee_service_dbus_interface_zcl_poll_control_notification(service_interface,
229                         notification_id, noti_data, noti_data_len, noti_cb_data);
230         }
231         break;
232
233         case ZBLIB_DRIVER_TYPE_ZCL_SCENE: {
234                 zigbee_service_dbus_interface_zcl_scene_notification(service_interface,
235                         notification_id, noti_data, noti_data_len, noti_cb_data);
236         }
237         break;
238
239         case ZBLIB_DRIVER_TYPE_ZDO_DEV_CONTROL: {
240                 zigbee_service_dbus_interface_zdo_dev_control_notification(service_interface,
241                         notification_id, noti_data, noti_data_len, noti_cb_data);
242         }
243         break;
244
245         case ZBLIB_DRIVER_TYPE_ZDO_BIND: {
246                 zigbee_service_dbus_interface_zdo_bind_notification(service_interface,
247                         notification_id, noti_data, noti_data_len, noti_cb_data);
248         }
249         break;
250
251         case ZBLIB_DRIVER_TYPE_NONE: /* Fall through */
252         default: {
253                 Z_LOGE("Unhandled driver type: [%d]", driver_type);
254         }
255         break;
256         }
257 }
258
259 static void zigbee_on_name_lost(GDBusConnection *connection,
260         const gchar *name, gpointer user_data)
261 {
262         ZigBeeServiceInterface *service_interface = (ZigBeeServiceInterface *)user_data;
263         ZigbeeCustomData_t *custom_data = zblib_service_interface_ref_user_data(service_interface);
264
265         Z_LOGW("'%s' - [Name Lost]", name);
266
267         NOT_USED(connection);
268
269         /* Bus name is 'lost' */
270         custom_data->name_acquired = FALSE;
271 }
272
273 static void zigbee_on_name_acquired(GDBusConnection *connection,
274         const gchar *name, gpointer user_data)
275 {
276         ZigBeeServiceInterface *service_interface = (ZigBeeServiceInterface *)user_data;
277         ZigbeeCustomData_t *custom_data = zblib_service_interface_ref_user_data(service_interface);
278
279         Z_LOGI("'%s' - [Name Acquired]", name);
280
281         NOT_USED(connection);
282
283         /* Bus name is 'acquired' */
284         custom_data->name_acquired = TRUE;
285
286         if (TRUE == custom_data->sevice_interface_init_complete) {
287                 /* TODO - Emit zigbee_state signal */
288         }
289 }
290
291 static void zigbee_on_bus_acquired(GDBusConnection *connection,
292         const gchar *name, gpointer user_data)
293 {
294         ZigbeeObjectSkeleton *zigbee_object;
295         ZigBeeServiceInterface *service_interface = (ZigBeeServiceInterface *)user_data;
296         ZigBeeService *service = NULL;
297         ZigbeeCustomData_t *custom_data = NULL;
298         char *path = NULL;
299
300         Z_LOGI("'%s' - [BUS Acquired]", name);
301
302         if (NULL == service_interface) {
303                 Z_LOGE("service_interface is NULL!");
304                 return;
305         }
306
307         service = zblib_service_interface_ref_service(service_interface);
308         if (NULL == service) {
309                 Z_LOGE("service is NULL!");
310                 return;
311         }
312
313         custom_data = (ZigbeeCustomData_t *)zblib_service_interface_ref_user_data(service_interface);
314         if (NULL == custom_data) {
315                 Z_LOGE("D-BUS service interface custom_data is NULL!");
316                 return;
317         }
318
319         /*
320          * Create ZigBee 'manager' D-BUS object
321          */
322         custom_data->zigbee_mgr = zigbee_manager_skeleton_new();
323
324         /*
325          * Set ZigBee 'manager' D-BUS object method(s)
326          */
327         g_signal_connect(custom_data->zigbee_mgr,
328                         "handle-get-zigbee-state",
329                         G_CALLBACK(zigbee_on_manager_get_zigbee_state),
330                         custom_data);
331
332         /*
333          * Export 'manager' interface on ZigBee D-BUS
334          */
335         g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(custom_data->zigbee_mgr),
336                 connection, ZIGBEE_DBUS_PATH, NULL);
337
338         /*
339          * Exports all objects managed by 'manager' on Connection (connection)
340          */
341         g_dbus_object_manager_server_set_connection(custom_data->manager, connection);
342
343         path = g_strdup_printf("%s", ZIGBEE_SERVICE_PATH);
344         Z_LOGI("dbus object path: [%s]", path);
345
346         /*
347          * Create 'object' for specific path only once.
348          */
349         zigbee_object = g_hash_table_lookup(custom_data->objects, path);
350         if (zigbee_object) {
351                 Z_LOGW("ZigBee D-BUS interface object already created (object: %p)", zigbee_object);
352                 goto OUT;
353         }
354
355         /*
356          * Create ZigBee D-BUS object
357          */
358         zigbee_object = zigbee_object_skeleton_new(path);
359         Z_LOGI("ZigBee D-BUS object created (zigbee_object: [%p])", zigbee_object);
360
361         /*
362          * Insert ZigBee object to HASH table
363          */
364         g_hash_table_insert(custom_data->objects, g_strdup(path), zigbee_object);
365
366         /*
367          * Initialize interfaces
368          */
369         zigbee_service_dbus_interface_initialize_interfaces(service_interface, zigbee_object);
370         Z_LOGI("ZigBee service interfaces initialized!!!");
371
372         /* Export the Object to Manager */
373         g_dbus_object_manager_server_export(custom_data->manager,
374                 G_DBUS_OBJECT_SKELETON(zigbee_object));
375
376         /* Servcie interface initialization completed */
377         custom_data->sevice_interface_init_complete = TRUE;
378
379         if (TRUE == custom_data->name_acquired) {
380                 /* TODO - Emit zigbee_state signal */
381         }
382
383 OUT:
384         g_free(path);
385 }
386
387 /**< Zigbee service dbus interface initialization */
388 gboolean zigbee_service_dbus_interface_init(ZigBeeService *service)
389 {
390         ZigBeeServiceInterface *service_interface = NULL;
391         ZigbeeCustomData_t *interface_data = NULL;
392         gboolean ret;
393
394         if (NULL == service) {
395                 Z_LOGE("service is NULL");
396                 return FALSE;
397         }
398
399         /*
400          * Create ZigBee service interface object
401          */
402         service_interface = zblib_service_interface_new(service,
403                 ZIGBEE_DBUS_SERVICE_INTERFACE_NAME);
404         if (NULL == service_interface) {
405                 Z_LOGE("Create D-BUS service interface failed!");
406
407                 return FALSE;
408         }
409
410         /*
411          * Set Service interface notification callback
412          */
413         ret = zblib_service_interface_set_noti_cb(service_interface,
414                 zigbee_service_dbus_interface_noti_cb, NULL);
415         if (FALSE == ret) {
416                 Z_LOGE("Set service interface notification callback failed!");
417
418                 goto EXIT;
419         }
420
421         /*
422          * Add Service interface object to 'service'
423          */
424         ret = zblib_service_add_service_interface(service,
425                         service_interface);
426         if (FALSE == ret) {
427                 Z_LOGE("Add D-BUS service interface failed!");
428
429                 goto EXIT;
430         }
431
432         /*
433          * ZigBee D-BUS interface custom data
434          */
435         interface_data = g_malloc0(sizeof(ZigbeeCustomData_t));
436
437         /*
438          * Link interface data to service
439          */
440         ret = zblib_service_interface_link_user_data(service_interface,
441                         interface_data);
442         if (FALSE == ret) {
443                 Z_LOGE("Link D-BUS service interface data failed!");
444
445                 goto EXIT;
446         }
447
448         /* HASH table for maintaining 'objects' list */
449         interface_data->objects = g_hash_table_new(g_str_hash, g_str_equal);
450
451         /*
452          * Acquire "org.tizen.zigbee" named bus on D-BUS SYSTEM bus.
453          */
454         interface_data->bus_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
455                         ZIGBEE_DBUS_SERVICE,
456                         G_BUS_NAME_OWNER_FLAGS_REPLACE,
457                         zigbee_on_bus_acquired,
458                         zigbee_on_name_acquired,
459                         zigbee_on_name_lost,
460                         service_interface,
461                         NULL);
462         Z_LOGI("ZigBee D-BUS ID: [%d]", interface_data->bus_id);
463
464         interface_data->manager = g_dbus_object_manager_server_new(ZIGBEE_DBUS_PATH);
465
466         return TRUE;
467
468 EXIT:
469         g_free(interface_data);
470
471         /*
472          * Remove Service interface object from 'service'
473          */
474         ret = zblib_service_remove_service_interface(service,
475                         service_interface);
476         if (FALSE == ret) {
477                 Z_LOGE("Remove service interface failed!");
478         }
479
480         /*
481          * Free Service interface object
482          */
483         zblib_service_interface_free(service,
484                         service_interface);
485
486         return FALSE;
487 }
488
489 /**< Zigbee service dbus interface de-initialization */
490 void zigbee_service_dbus_interface_deinit(ZigBeeService *service)
491 {
492         ZigBeeServiceInterface *service_interface = NULL;
493         ZigbeeCustomData_t *interface_data = NULL;
494         gboolean ret;
495
496         if (NULL == service) {
497                 Z_LOGE("service is NULL");
498                 return;
499         }
500
501         service_interface = zblib_service_ref_service_interface(service,
502                 ZIGBEE_DBUS_SERVICE_INTERFACE_NAME);
503         if (NULL == service_interface) {
504                 Z_LOGE("D-BUS service interface not found!");
505
506                 return;
507         }
508
509         interface_data = (ZigbeeCustomData_t *)zblib_service_interface_ref_user_data(service_interface);
510         if (NULL == service_interface) {
511                 Z_LOGE("D-BUS service interface not found!");
512
513                 goto EXIT;
514         }
515
516         /*
517          * Unown "org.tizen.zigbee" named bus on D-BUS SYSTEM bus
518          */
519         if (interface_data->bus_id > 0) {
520                 Z_LOGI("Unowning ZigBee Service interface D-BUS ID: [%d]", interface_data->bus_id);
521                 g_bus_unown_name(interface_data->bus_id);
522         }
523
524         /* Free resources */
525         g_hash_table_destroy(interface_data->objects);
526         g_free(interface_data);
527
528 EXIT:
529         /*
530          * Remove Service interface object from 'service'
531          */
532         ret = zblib_service_remove_service_interface(service,
533                         service_interface);
534         if (FALSE == ret) {
535                 Z_LOGE("Remove service interface failed!");
536         }
537
538         /*
539          * Free Service interface object
540          */
541         zblib_service_interface_free(service,
542                         service_interface);
543 }