afab090ef5bd110a7437a3f1d3c50e36cdf037a6
[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 #include <zblib_driver_manager.h>
30
31 #include "zigbee_service_interface.h"
32 #include "zigbee_service_interface_common.h"
33 #include "zigbee_service_dbus_interface.h"
34
35 /**< ZigBee D-BUS service interface name */
36 #define ZIGBEE_DBUS_SERVICE_INTERFACE_NAME "zigbee-dbus"
37
38 static void _notify_zigbee_state(ZigBeeServiceInterface *service_interface,
39                 gboolean result)
40 {
41         ZigbeeCustomData_t *custom_data = zblib_service_interface_ref_user_data(service_interface);
42         ZigBeeService *service = zblib_service_interface_ref_service(service_interface);
43
44         if (NULL == custom_data) {
45                 Z_LOGE("Unexpected invalid parameter !");
46                 return;
47         }
48
49         if (result) {
50                 /* Notify zigbee service manually here (Enabled) */
51                 zigbee_manager_emit_zigbee_state(custom_data->zigbee_mgr, result);
52         } else {
53                 /* ZigBee state will be emitted on bus termination */
54                 zblib_service_exit(service);
55         }
56 }
57
58 static gboolean on_manager_enable(ZigbeeManager *zigbee_mgr,
59         GDBusMethodInvocation *invocation,
60         gpointer user_data)
61 {
62         ZigBeeServiceInterface *service_interface = (ZigBeeServiceInterface *)user_data;
63         ZigbeeCustomData_t *custom_data = zblib_service_interface_ref_user_data(service_interface);
64
65         if (NULL == custom_data) {
66                 ZIGBEE_DBUS_FAIL_RESPONSE(invocation, ZIGBEE_DBUS_DEFAULT_REQ_FAILED_MSG);
67
68                 return TRUE;
69         }
70
71         zigbee_manager_complete_enable(zigbee_mgr, invocation);
72
73         return TRUE;
74 }
75
76 static gboolean on_manager_disable(ZigbeeManager *zigbee_mgr,
77         GDBusMethodInvocation *invocation,
78         gpointer user_data)
79 {
80         ZigBeeServiceInterface *service_interface = (ZigBeeServiceInterface *)user_data;
81         ZigBeeService *service = zblib_service_interface_ref_service(service_interface);
82
83         NOT_USED(user_data);
84
85         zigbee_manager_complete_disable(zigbee_mgr, invocation, 0);
86
87         if (service)
88                 zblib_service_exit(service);
89
90         return TRUE;
91 }
92
93 static gboolean on_manager_get_zigbee_state(ZigbeeManager *zigbee_mgr,
94         GDBusMethodInvocation *invocation, gpointer user_data)
95 {
96         ZigBeeServiceInterface *service_interface = (ZigBeeServiceInterface *)user_data;
97         ZigbeeCustomData_t *custom_data = zblib_service_interface_ref_user_data(service_interface);
98
99         Z_LOGI("Entered");
100
101         if (NULL == custom_data) {
102                 ZIGBEE_DBUS_FAIL_RESPONSE(invocation, ZIGBEE_DBUS_DEFAULT_REQ_FAILED_MSG);
103
104                 return TRUE;
105         }
106
107         zigbee_manager_complete_get_zigbee_state(zigbee_mgr, invocation,
108                         0, custom_data->sevice_interface_init_complete);
109
110         return TRUE;
111 }
112
113 static void zigbee_service_dbus_interface_initialize_interfaces(ZigBeeServiceInterface *service_interface,
114         ZigbeeObjectSkeleton *zigbee_object)
115 {
116         gboolean ret;
117
118         ret = zigbee_service_dbus_interface_zcl_alarm_init(service_interface, zigbee_object);
119         Z_LOGD("ret: %d", ret);
120
121         ret = zigbee_service_dbus_interface_custom_init(service_interface, zigbee_object);
122         Z_LOGD("ret: %d", ret);
123
124         ret = zigbee_service_dbus_interface_zcl_door_lock_init(service_interface, zigbee_object);
125         Z_LOGD("ret: %d", ret);
126
127         ret = zigbee_service_dbus_interface_zcl_fan_control_init(service_interface, zigbee_object);
128         Z_LOGD("ret: %d", ret);
129
130         ret = zigbee_service_dbus_interface_zcl_level_control_init(service_interface, zigbee_object);
131         Z_LOGD("ret: %d", ret);
132
133         ret = zigbee_service_dbus_interface_mfglib_control_init(service_interface, zigbee_object);
134         Z_LOGD("ret: %d", ret);
135
136         ret = zigbee_service_dbus_interface_zcl_on_off_init(service_interface, zigbee_object);
137         Z_LOGD("ret: %d", ret);
138
139         ret = zigbee_service_dbus_interface_service_init(service_interface, zigbee_object);
140         Z_LOGD("ret: %d", ret);
141
142         ret = zigbee_service_dbus_interface_zcl_thermostat_init(service_interface, zigbee_object);
143         Z_LOGD("ret: %d", ret);
144
145         ret = zigbee_service_dbus_interface_zcl_basic_init(service_interface, zigbee_object);
146         Z_LOGD("ret: %d", ret);
147
148         ret = zigbee_service_dbus_interface_zcl_color_control_init(service_interface, zigbee_object);
149         Z_LOGD("ret: %d", ret);
150
151         ret = zigbee_service_dbus_interface_zcl_global_control_init(service_interface, zigbee_object);
152         Z_LOGD("ret: %d", ret);
153
154         ret = zigbee_service_dbus_interface_zcl_group_init(service_interface, zigbee_object);
155         Z_LOGD("ret: %d", ret);
156
157         ret = zigbee_service_dbus_interface_zcl_ias_zone_init(service_interface, zigbee_object);
158         Z_LOGD("ret: %d", ret);
159
160         ret = zigbee_service_dbus_interface_zcl_identify_init(service_interface, zigbee_object);
161         Z_LOGD("ret: %d", ret);
162
163         ret = zigbee_service_dbus_interface_zcl_poll_control_init(service_interface, zigbee_object);
164         Z_LOGD("ret: %d", ret);
165
166         ret = zigbee_service_dbus_interface_zcl_scene_init(service_interface, zigbee_object);
167         Z_LOGD("ret: %d", ret);
168
169         ret = zigbee_service_dbus_interface_zdo_bind_init(service_interface, zigbee_object);
170         Z_LOGD("ret: %d", ret);
171
172         ret = zigbee_service_dbus_interface_zdo_dev_control_init(service_interface, zigbee_object);
173         Z_LOGD("ret: %d", ret);
174 }
175
176 static void zigbee_service_dbus_interface_noti_cb(ZigBeeServiceInterface *service_interface,
177         guint noti_id, gpointer noti_data, guint noti_data_len, gpointer noti_cb_data)
178 {
179         ZblibDriverType_e driver_type;
180         guint notification_id;
181
182         if (NULL == service_interface) {
183                 Z_LOGE("service_interface is NULL");
184                 return;
185         }
186
187         /* Extract driver_type */
188         driver_type = ((noti_id & 0xFF000000) >> 24);
189
190         /* Extract notification_id */
191         notification_id = (noti_id & 0x000000FF);
192
193         Z_LOGI("Driver type: [%d] Notification ID: [%d]", driver_type, notification_id);
194
195         switch (driver_type) {
196         case ZBLIB_DRIVER_TYPE_ZCL_ALARM: {
197                 zigbee_service_dbus_interface_zcl_alarm_notification(service_interface,
198                         notification_id, noti_data, noti_data_len, noti_cb_data);
199         }
200         break;
201
202         case ZBLIB_DRIVER_TYPE_CUSTOM: {
203                 zigbee_service_dbus_interface_custom_notification(service_interface,
204                         notification_id, noti_data, noti_data_len, noti_cb_data);
205         }
206         break;
207
208         case ZBLIB_DRIVER_TYPE_ZCL_DOOR_LOCK: {
209                 zigbee_service_dbus_interface_zcl_door_lock_notification(service_interface,
210                         notification_id, noti_data, noti_data_len, noti_cb_data);
211         }
212         break;
213
214         case ZBLIB_DRIVER_TYPE_ZCL_FAN_CONTROL: {
215                 zigbee_service_dbus_interface_zcl_fan_control_notification(service_interface,
216                         notification_id, noti_data, noti_data_len, noti_cb_data);
217         }
218         break;
219
220         case ZBLIB_DRIVER_TYPE_ZCL_LEVEL_CONTROL: {
221                 zigbee_service_dbus_interface_zcl_level_control_notification(service_interface,
222                         notification_id, noti_data, noti_data_len, noti_cb_data);
223         }
224         break;
225
226         case ZBLIB_DRIVER_TYPE_MFGLIB_CONTROL: {
227                 zigbee_service_dbus_interface_mfglib_control_notification(service_interface,
228                         notification_id, noti_data, noti_data_len, noti_cb_data);
229         }
230         break;
231
232         case ZBLIB_DRIVER_TYPE_ZCL_ON_OFF: {
233                 zigbee_service_dbus_interface_zcl_on_off_notification(service_interface,
234                         notification_id, noti_data, noti_data_len, noti_cb_data);
235         }
236         break;
237
238         case ZBLIB_DRIVER_TYPE_SERVICE: {
239                 zigbee_service_dbus_interface_service_notification(service_interface,
240                         notification_id, noti_data, noti_data_len, noti_cb_data);
241         }
242         break;
243
244         case ZBLIB_DRIVER_TYPE_ZCL_THERMOSTAT: {
245                 zigbee_service_dbus_interface_zcl_thermostat_notification(service_interface,
246                         notification_id, noti_data, noti_data_len, noti_cb_data);
247         }
248         break;
249
250         case ZBLIB_DRIVER_TYPE_ZCL_BASIC: {
251                 zigbee_service_dbus_interface_zcl_basic_notification(service_interface,
252                         notification_id, noti_data, noti_data_len, noti_cb_data);
253         }
254         break;
255
256         case ZBLIB_DRIVER_TYPE_ZCL_GLOBAL_CONTROL: {
257                 zigbee_service_dbus_interface_zcl_global_control_notification(service_interface,
258                         notification_id, noti_data, noti_data_len, noti_cb_data);
259         }
260         break;
261
262         case ZBLIB_DRIVER_TYPE_ZCL_IAS_ZONE: {
263                 zigbee_service_dbus_interface_zcl_ias_zone_notification(service_interface,
264                         notification_id, noti_data, noti_data_len, noti_cb_data);
265         }
266         break;
267
268         case ZBLIB_DRIVER_TYPE_ZCL_IDENTIFY: {
269                 zigbee_service_dbus_interface_zcl_identify_notification(service_interface,
270                         notification_id, noti_data, noti_data_len, noti_cb_data);
271         }
272         break;
273
274         case ZBLIB_DRIVER_TYPE_ZCL_COLOR_CONTROL: {
275                 zigbee_service_dbus_interface_zcl_color_control_notification(service_interface,
276                         notification_id, noti_data, noti_data_len, noti_cb_data);
277         }
278         break;
279
280         case ZBLIB_DRIVER_TYPE_ZCL_GROUP: {
281                 zigbee_service_dbus_interface_zcl_group_notification(service_interface,
282                         notification_id, noti_data, noti_data_len, noti_cb_data);
283         }
284         break;
285
286         case ZBLIB_DRIVER_TYPE_ZCL_POLL_CONTROL: {
287                 zigbee_service_dbus_interface_zcl_poll_control_notification(service_interface,
288                         notification_id, noti_data, noti_data_len, noti_cb_data);
289         }
290         break;
291
292         case ZBLIB_DRIVER_TYPE_ZCL_SCENE: {
293                 zigbee_service_dbus_interface_zcl_scene_notification(service_interface,
294                         notification_id, noti_data, noti_data_len, noti_cb_data);
295         }
296         break;
297
298         case ZBLIB_DRIVER_TYPE_ZDO_DEV_CONTROL: {
299                 zigbee_service_dbus_interface_zdo_dev_control_notification(service_interface,
300                         notification_id, noti_data, noti_data_len, noti_cb_data);
301         }
302         break;
303
304         case ZBLIB_DRIVER_TYPE_ZDO_BIND: {
305                 zigbee_service_dbus_interface_zdo_bind_notification(service_interface,
306                         notification_id, noti_data, noti_data_len, noti_cb_data);
307         }
308         break;
309
310         case ZBLIB_DRIVER_TYPE_MANAGER: {
311                 /* Handle 'enabled' notification here */
312                 if (notification_id == ZBLIB_MANAGER_NOTI_ZIGBEE_ENABLED) {
313                         gboolean *rsp = (gboolean*)noti_data;
314
315                         Z_LOGD("Firmware update result : [%s]", ((*rsp) ? "Succeed" : "Failed"));
316                         _notify_zigbee_state(service_interface, *rsp);
317                 } else
318                         Z_LOGE("Unhandled notification id: [%d]", notification_id);
319         }
320         break;
321
322         case ZBLIB_DRIVER_TYPE_NONE: /* Fall through */
323         default: {
324                 Z_LOGE("Unhandled driver type: [%d]", driver_type);
325         }
326         break;
327         }
328 }
329
330 static void zigbee_on_name_lost(GDBusConnection *connection,
331         const gchar *name, gpointer user_data)
332 {
333         ZigBeeServiceInterface *service_interface = (ZigBeeServiceInterface *)user_data;
334         ZigbeeCustomData_t *custom_data = zblib_service_interface_ref_user_data(service_interface);
335
336         Z_LOGW("'%s' - [Name Lost]", name);
337
338         zblib_check_null_ret("custom_data", custom_data);
339
340         NOT_USED(connection);
341
342         /* Bus name is 'lost' */
343         custom_data->name_acquired = FALSE;
344 }
345
346 static void zigbee_on_name_acquired(GDBusConnection *connection,
347         const gchar *name, gpointer user_data)
348 {
349         ZigBeeServiceInterface *service_interface = (ZigBeeServiceInterface *)user_data;
350         ZigbeeCustomData_t *custom_data = zblib_service_interface_ref_user_data(service_interface);
351
352         Z_LOGI("'%s' - [Name Acquired]", name);
353
354         NOT_USED(connection);
355
356         zblib_check_null_ret("custom_data", custom_data);
357
358         /* Bus name is 'acquired' */
359         custom_data->name_acquired = TRUE;
360 }
361
362 static void zigbee_on_bus_acquired(GDBusConnection *connection,
363         const gchar *name, gpointer user_data)
364 {
365         ZigbeeObjectSkeleton *zigbee_object;
366         ZigBeeServiceInterface *service_interface = (ZigBeeServiceInterface *)user_data;
367         ZigBeeService *service = NULL;
368         ZigbeeCustomData_t *custom_data = NULL;
369         char *path = NULL;
370
371         Z_LOGI("'%s' - [BUS Acquired]", name);
372
373         if (NULL == service_interface) {
374                 Z_LOGE("service_interface is NULL!");
375                 return;
376         }
377
378         service = zblib_service_interface_ref_service(service_interface);
379         if (NULL == service) {
380                 Z_LOGE("service is NULL!");
381                 return;
382         }
383
384         custom_data = (ZigbeeCustomData_t *)zblib_service_interface_ref_user_data(service_interface);
385         if (NULL == custom_data) {
386                 Z_LOGE("D-BUS service interface custom_data is NULL!");
387                 return;
388         }
389
390         /*
391          * Create ZigBee 'manager' D-BUS object
392          */
393         custom_data->zigbee_mgr = zigbee_manager_skeleton_new();
394
395         /*
396          * Set ZigBee 'manager' D-BUS object method(s)
397          */
398         g_signal_connect(custom_data->zigbee_mgr,
399                         "handle-get-zigbee-state",
400                         G_CALLBACK(on_manager_get_zigbee_state),
401                         service_interface);
402
403         g_signal_connect(custom_data->zigbee_mgr,
404                         "handle-enable",
405                         G_CALLBACK(on_manager_enable),
406                         service_interface);
407
408         g_signal_connect(custom_data->zigbee_mgr,
409                         "handle-disable",
410                         G_CALLBACK(on_manager_disable),
411                         service_interface);
412
413         /*
414          * Export 'manager' interface on ZigBee D-BUS
415          */
416         g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(custom_data->zigbee_mgr),
417                 connection, ZIGBEE_DBUS_PATH, NULL);
418
419         /*
420          * Exports all objects managed by 'manager' on Connection (connection)
421          */
422         g_dbus_object_manager_server_set_connection(custom_data->manager, connection);
423
424         path = g_strdup_printf("%s", ZIGBEE_SERVICE_PATH);
425         Z_LOGI("dbus object path: [%s]", path);
426
427         /*
428          * Create 'object' for specific path only once.
429          */
430         zigbee_object = g_hash_table_lookup(custom_data->objects, path);
431         if (zigbee_object) {
432                 Z_LOGW("ZigBee D-BUS interface object already created (object: %p)", zigbee_object);
433                 goto OUT;
434         }
435
436         /*
437          * Create ZigBee D-BUS object
438          */
439         zigbee_object = zigbee_object_skeleton_new(path);
440         Z_LOGI("ZigBee D-BUS object created (zigbee_object: [%p])", zigbee_object);
441
442         /*
443          * Insert ZigBee object to HASH table
444          */
445         g_hash_table_insert(custom_data->objects, g_strdup(path), zigbee_object);
446
447         /*
448          * Initialize interfaces
449          */
450         zigbee_service_dbus_interface_initialize_interfaces(service_interface, zigbee_object);
451         Z_LOGI("ZigBee service interfaces initialized!!!");
452
453         /* Export the Object to Manager */
454         g_dbus_object_manager_server_export(custom_data->manager,
455                 G_DBUS_OBJECT_SKELETON(zigbee_object));
456
457         /* Service interface initialization completed */
458         custom_data->sevice_interface_init_complete = TRUE;
459
460 OUT:
461         g_free(path);
462 }
463
464 static void zigbee_get_activation_sbus(ZigbeeCustomData_t *interface_data)
465 {
466         /* Get D-Bus owner to activate zigbee-daemon */
467         interface_data->activation_dbus_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
468                         ZIGBEE_DBUS_SERVICE".manager",
469                         G_BUS_NAME_OWNER_FLAGS_REPLACE,
470                         NULL,
471                         NULL,
472                         NULL,
473                         NULL,
474                         NULL);
475         Z_LOGI("ZigBee D-BUS activation ID: [%d]", interface_data->activation_dbus_id);
476 }
477
478 /**< Zigbee service dbus interface initialization */
479 gboolean zigbee_service_dbus_interface_init(ZigBeeService *service)
480 {
481         ZigBeeServiceInterface *service_interface = NULL;
482         ZigbeeCustomData_t *interface_data = NULL;
483         gboolean ret;
484
485         if (NULL == service) {
486                 Z_LOGE("service is NULL");
487                 return FALSE;
488         }
489
490         /*
491          * Create ZigBee service interface object
492          */
493         service_interface = zblib_service_interface_new(service,
494                 ZIGBEE_DBUS_SERVICE_INTERFACE_NAME);
495         if (NULL == service_interface) {
496                 Z_LOGE("Create D-BUS service interface failed!");
497
498                 return FALSE;
499         }
500
501         /*
502          * Set Service interface notification callback
503          */
504         ret = zblib_service_interface_set_noti_cb(service_interface,
505                 zigbee_service_dbus_interface_noti_cb, NULL);
506         if (FALSE == ret) {
507                 Z_LOGE("Set service interface notification callback failed!");
508
509                 goto EXIT;
510         }
511
512         /*
513          * Add Service interface object to 'service'
514          */
515         ret = zblib_service_add_service_interface(service,
516                         service_interface);
517         if (FALSE == ret) {
518                 Z_LOGE("Add D-BUS service interface failed!");
519
520                 goto EXIT;
521         }
522
523         /*
524          * ZigBee D-BUS interface custom data
525          */
526         interface_data = g_malloc0(sizeof(ZigbeeCustomData_t));
527
528         /*
529          * Link interface data to service
530          */
531         ret = zblib_service_interface_link_user_data(service_interface,
532                         interface_data);
533         if (FALSE == ret) {
534                 Z_LOGE("Link D-BUS service interface data failed!");
535
536                 goto EXIT;
537         }
538
539         /* HASH table for maintaining 'objects' list */
540         interface_data->objects = g_hash_table_new_full(g_str_hash, g_str_equal,
541                         g_free, NULL);
542
543         /*
544          * Acquire "org.tizen.zigbee.manager" named bus on D-BUS SYSTEM bus.
545          */
546         zigbee_get_activation_sbus(interface_data);
547
548         /*
549          * Acquire "org.tizen.zigbee" named bus on D-BUS SYSTEM bus.
550          */
551         interface_data->bus_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
552                         ZIGBEE_DBUS_SERVICE,
553                         G_BUS_NAME_OWNER_FLAGS_REPLACE,
554                         zigbee_on_bus_acquired,
555                         zigbee_on_name_acquired,
556                         zigbee_on_name_lost,
557                         service_interface,
558                         NULL);
559         Z_LOGI("ZigBee D-BUS ID: [%d]", interface_data->bus_id);
560
561         interface_data->manager = g_dbus_object_manager_server_new(ZIGBEE_DBUS_PATH);
562
563         return TRUE;
564
565 EXIT:
566         g_free(interface_data);
567
568         /*
569          * Remove Service interface object from 'service'
570          */
571         ret = zblib_service_remove_service_interface(service,
572                         service_interface);
573         if (FALSE == ret)
574                 Z_LOGE("Remove service interface failed!");
575
576         /*
577          * Free Service interface object
578          */
579         zblib_service_interface_free(service,
580                         service_interface);
581
582         return FALSE;
583 }
584
585 /**< Zigbee service dbus interface de-initialization */
586 void zigbee_service_dbus_interface_deinit(ZigBeeService *service)
587 {
588         ZigBeeServiceInterface *service_interface = NULL;
589         ZigbeeCustomData_t *interface_data = NULL;
590         gboolean ret;
591
592         if (NULL == service) {
593                 Z_LOGE("service is NULL");
594                 return;
595         }
596
597         service_interface = zblib_service_ref_service_interface(service,
598                 ZIGBEE_DBUS_SERVICE_INTERFACE_NAME);
599         if (NULL == service_interface) {
600                 Z_LOGE("D-BUS service interface not found!");
601
602                 return;
603         }
604
605         interface_data = (ZigbeeCustomData_t *)zblib_service_interface_ref_user_data(service_interface);
606         if (NULL == interface_data) {
607                 Z_LOGE("D-BUS interface data not found!");
608
609                 goto EXIT;
610         }
611
612         /* Emit zigbee_state - disabled */
613         Z_LOGD("Update zigbee_state ----");
614         zigbee_manager_emit_zigbee_state(interface_data->zigbee_mgr, FALSE);
615
616         /*
617          * Unown "org.tizen.zigbee.manager" named bus on D-BUS SYSTEM bus
618          */
619         if (interface_data->activation_dbus_id > 0) {
620                 Z_LOGI("Unowning ZigBee Service interface activation D-BUS ID: [%d]",
621                         interface_data->activation_dbus_id);
622                 g_bus_unown_name(interface_data->activation_dbus_id);
623         }
624
625         /*
626          * Unown "org.tizen.zigbee" named bus on D-BUS SYSTEM bus
627          */
628         if (interface_data->bus_id > 0) {
629                 Z_LOGI("Unowning ZigBee Service interface D-BUS ID: [%d]", interface_data->bus_id);
630                 g_bus_unown_name(interface_data->bus_id);
631         }
632
633         /* Free resources */
634         g_hash_table_destroy(interface_data->objects);
635         g_free(interface_data);
636
637 EXIT:
638         /*
639          * Remove Service interface object from 'service'
640          */
641         ret = zblib_service_remove_service_interface(service,
642                         service_interface);
643         if (FALSE == ret)
644                 Z_LOGE("Remove service interface failed!");
645
646         /*
647          * Free Service interface object
648          */
649         zblib_service_interface_free(service,
650                         service_interface);
651 }