Add notification handling framework
[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         ZigbeeCustomData_t *custom_data = user_data;
263
264         Z_LOGW("'%s' - [Name Lost]", name);
265
266         NOT_USED(connection);
267
268         /* Bus name is 'lost' */
269         custom_data->name_acquired = FALSE;
270 }
271
272 static void zigbee_on_name_acquired(GDBusConnection *connection,
273         const gchar *name, gpointer user_data)
274 {
275         ZigbeeCustomData_t *custom_data = user_data;
276
277         Z_LOGI("'%s' - [Name Acquired]", name);
278
279         NOT_USED(connection);
280
281         /* Bus name is 'acquired' */
282         custom_data->name_acquired = TRUE;
283
284         if (TRUE == custom_data->sevice_interface_init_complete) {
285                 /* TODO - Emit zigbee_state signal */
286         }
287 }
288
289 static void zigbee_on_bus_acquired(GDBusConnection *connection,
290         const gchar *name, gpointer user_data)
291 {
292         ZigbeeObjectSkeleton *zigbee_object;
293         ZigBeeServiceInterface *service_interface = (ZigBeeServiceInterface *)user_data;
294         ZigBeeService *service = NULL;
295         ZigbeeCustomData_t *custom_data = NULL;
296         char *path = NULL;
297
298         Z_LOGI("'%s' - [BUS Acquired]", name);
299
300         if (NULL == service_interface) {
301                 Z_LOGE("service_interface is NULL!");
302                 return;
303         }
304
305         service = zblib_service_interface_ref_service(service_interface);
306         if (NULL == service) {
307                 Z_LOGE("service is NULL!");
308                 return;
309         }
310
311         custom_data = (ZigbeeCustomData_t *)zblib_service_interface_ref_user_data(service_interface);
312         if (NULL == custom_data) {
313                 Z_LOGE("D-BUS service interface custom_data is NULL!");
314                 return;
315         }
316
317         /*
318          * Create ZigBee 'manager' D-BUS object
319          */
320         custom_data->zigbee_mgr = zigbee_manager_skeleton_new();
321
322         /*
323          * Set ZigBee 'manager' D-BUS object method(s)
324          */
325         g_signal_connect(custom_data->zigbee_mgr,
326                         "handle-get-zigbee-state",
327                         G_CALLBACK(zigbee_on_manager_get_zigbee_state),
328                         custom_data);
329
330         /*
331          * Export 'manager' interface on ZigBee D-BUS
332          */
333         g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(custom_data->zigbee_mgr),
334                 connection, ZIGBEE_DBUS_PATH, NULL);
335
336         /*
337          * Exports all objects managed by 'manager' on Connection (connection)
338          */
339         g_dbus_object_manager_server_set_connection(custom_data->manager, connection);
340
341         path = g_strdup_printf("%s/service", ZIGBEE_DBUS_PATH);
342         Z_LOGI("dbus object path: [%s]", path);
343
344         /*
345          * Create 'object' for specific path only once.
346          */
347         zigbee_object = g_hash_table_lookup(custom_data->objects, path);
348         if (zigbee_object) {
349                 Z_LOGW("ZigBee D-BUS interface object already created (object: %p)", zigbee_object);
350                 goto OUT;
351         }
352
353         /*
354          * Create ZigBee D-BUS object
355          */
356         zigbee_object = zigbee_object_skeleton_new(path);
357         Z_LOGI("ZigBee D-BUS object created (zigbee_object: [%p])", zigbee_object);
358
359         /*
360          * Insert ZigBee object to HASH table
361          */
362         g_hash_table_insert(custom_data->objects, g_strdup(path), zigbee_object);
363
364         /*
365          * Initialize interfaces
366          */
367         zigbee_service_dbus_interface_initialize_interfaces(service_interface, zigbee_object);
368         Z_LOGI("ZigBee service interfaces initialized!!!");
369
370         /* Export the Object to Manager */
371         g_dbus_object_manager_server_export(custom_data->manager,
372                 G_DBUS_OBJECT_SKELETON(zigbee_object));
373
374         /* Servcie interface initialization completed */
375         custom_data->sevice_interface_init_complete = TRUE;
376
377         if (TRUE == custom_data->name_acquired) {
378                 /* TODO - Emit zigbee_state signal */
379         }
380
381 OUT:
382         g_free(path);
383 }
384
385 /**< Zigbee service dbus interface initialization */
386 gboolean zigbee_service_dbus_interface_init(ZigBeeService *service)
387 {
388         ZigBeeServiceInterface *service_interface = NULL;
389         ZigbeeCustomData_t *interface_data = NULL;
390         gboolean ret;
391
392         if (NULL == service) {
393                 Z_LOGE("service is NULL");
394                 return FALSE;
395         }
396
397         /*
398          * Create ZigBee service interface object
399          */
400         service_interface = zblib_service_interface_new(service,
401                 ZIGBEE_DBUS_SERVICE_INTERFACE_NAME);
402         if (NULL == service_interface) {
403                 Z_LOGE("Create D-BUS service interface failed!");
404
405                 return FALSE;
406         }
407
408         /*
409          * Set Service interface notification callback
410          */
411         ret = zblib_service_interface_set_noti_cb(service_interface,
412                 zigbee_service_dbus_interface_noti_cb, NULL);
413         if (FALSE == ret) {
414                 Z_LOGE("Set service interface notification callback failed!");
415
416                 goto EXIT;
417         }
418
419         /*
420          * Add Service interface object to 'service'
421          */
422         ret = zblib_service_add_service_interface(service,
423                         service_interface);
424         if (FALSE == ret) {
425                 Z_LOGE("Add D-BUS service interface failed!");
426
427                 goto EXIT;
428         }
429
430         /*
431          * ZigBee D-BUS interface custom data
432          */
433         interface_data = g_malloc0(sizeof(ZigbeeCustomData_t));
434
435         /*
436          * Link interface data to service
437          */
438         ret = zblib_service_interface_link_user_data(service_interface,
439                         interface_data);
440         if (FALSE == ret) {
441                 Z_LOGE("Link D-BUS service interface data failed!");
442
443                 goto EXIT;
444         }
445
446         /* HASH table for maintaining 'objects' list */
447         interface_data->objects = g_hash_table_new(g_str_hash, g_str_equal);
448
449         /*
450          * Acquire "org.tizen.zigbee" named bus on D-BUS SYSTEM bus.
451          */
452         interface_data->bus_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
453                         ZIGBEE_DBUS_SERVICE,
454                         G_BUS_NAME_OWNER_FLAGS_REPLACE,
455                         zigbee_on_bus_acquired,
456                         zigbee_on_name_acquired,
457                         zigbee_on_name_lost,
458                         service_interface,
459                         NULL);
460         Z_LOGI("ZigBee D-BUS ID: [%d]", interface_data->bus_id);
461
462         interface_data->manager = g_dbus_object_manager_server_new(ZIGBEE_DBUS_PATH);
463
464         return TRUE;
465
466 EXIT:
467         g_free(interface_data);
468
469         /*
470          * Remove Service interface object from 'service'
471          */
472         ret = zblib_service_remove_service_interface(service,
473                         service_interface);
474         if (FALSE == ret) {
475                 Z_LOGE("Remove service interface failed!");
476         }
477
478         /*
479          * Free Service interface object
480          */
481         zblib_service_interface_free(service,
482                         service_interface);
483
484         return FALSE;
485 }
486
487 /**< Zigbee service dbus interface de-initialization */
488 void zigbee_service_dbus_interface_deinit(ZigBeeService *service)
489 {
490         ZigBeeServiceInterface *service_interface = NULL;
491         ZigbeeCustomData_t *interface_data = NULL;
492         gboolean ret;
493
494         if (NULL == service) {
495                 Z_LOGE("service is NULL");
496                 return;
497         }
498
499         service_interface = zblib_service_ref_service_interface(service,
500                 ZIGBEE_DBUS_SERVICE_INTERFACE_NAME);
501         if (NULL == service_interface) {
502                 Z_LOGE("D-BUS service interface not found!");
503
504                 return;
505         }
506
507         interface_data = (ZigbeeCustomData_t *)zblib_service_interface_ref_user_data(service_interface);
508         if (NULL == service_interface) {
509                 Z_LOGE("D-BUS service interface not found!");
510
511                 goto EXIT;
512         }
513
514         /*
515          * Unown "org.tizen.zigbee" named bus on D-BUS SYSTEM bus
516          */
517         if (interface_data->bus_id > 0) {
518                 Z_LOGI("Unowning ZigBee Service interface D-BUS ID: [%d]", interface_data->bus_id);
519                 g_bus_unown_name(interface_data->bus_id);
520         }
521
522         /* Free resources */
523         g_hash_table_destroy(interface_data->objects);
524         g_free(interface_data);
525
526 EXIT:
527         /*
528          * Remove Service interface object from 'service'
529          */
530         ret = zblib_service_remove_service_interface(service,
531                         service_interface);
532         if (FALSE == ret) {
533                 Z_LOGE("Remove service interface failed!");
534         }
535
536         /*
537          * Free Service interface object
538          */
539         zblib_service_interface_free(service,
540                         service_interface);
541 }