2 * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
4 * Contact: Suresh Kumar N (suresh.n@samsung.com)
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <zblib_service.h>
24 #include <zblib_plugin.h>
25 #include <zblib_service_interface.h>
26 #include <zblib_request.h>
27 #include <zblib_driver.h>
28 #include <zblib_driver_manager.h>
30 struct _zblib_async_init_info {
31 gboolean is_initialized; /**< Does initialization succeeded? */
32 gboolean is_finished; /**< Does initialization finished? */
34 ZigBeePlugin *plugin; /**< ZigBee plugin */
35 void *user_data; /**< User data */
38 /**< ZigBee Service object */
39 struct zblib_service_type {
40 GMainLoop *main_loop; /**< Service main-loop */
42 GSList *interface_objs; /**< ZigBee Service interface objects */
43 GSList *plugins; /**< ZigBee plug-ins */
45 GHashTable *request_table; /**< Request Hash table */
46 guint request_id; /**< Request ID */
48 GSList *async_initializer; /**< Hash table for asynchronous initializer */
49 zblib_plugin_init_finished_cb callback; /**< Callback */
52 static GSList *__zblib_service_ref_async_initializer(ZigBeeService* service)
54 zblib_check_null_ret_error("service", service, NULL);
56 return service->async_initializer;
59 static void __zblib_service_set_async_initializer(ZigBeeService* service, GSList* list)
61 zblib_check_null_ret("service", service);
63 service->async_initializer = list;
66 static void __on_zblib_init_async_finished(gboolean result, void *user_data)
68 GSList *list_async = NULL;
69 ZigBeeService *service = NULL;
70 ZigBeePlugin *plugin = NULL;
71 struct _zblib_async_init_info *info = (struct _zblib_async_init_info*)user_data;
72 char *plugin_name = NULL;
75 int _finished_count = 0;
76 int _succeeded_count = 0;
78 zblib_check_null_ret("info", info);
80 plugin = info->plugin;
81 service = zblib_plugin_ref_service(plugin);
82 zblib_check_null_ret("service", service);
84 plugin_name = zblib_plugin_get_plugin_name(plugin);
86 info->is_finished = TRUE;
88 Z_LOGD("Plugin [%s] succeeded async init", plugin_name);
89 info->is_initialized = TRUE;
91 Z_LOGE("Plugin [%s] failed to init !", plugin_name);
95 /* Check all async initializer list */
96 list_async = __zblib_service_ref_async_initializer(service);
97 while (list_async != NULL) {
98 /* Initialize each plug-in */
99 struct _zblib_async_init_info *in =
100 (struct _zblib_async_init_info *)(list_async->data);
102 if (G_UNLIKELY(NULL == in)) {
103 Z_LOGE("Invalid parameter !");
104 list_async = g_slist_next(list_async);
110 if (in->is_initialized)
113 list_async = g_slist_next(list_async);
116 if (i == _finished_count) {
118 guint driver_noti_id = (ZBLIB_DRIVER_TYPE_MANAGER << 24)
119 | ZBLIB_MANAGER_NOTI_ZIGBEE_ENABLED;
121 if (_finished_count == _succeeded_count) {
122 /* All initializer finished successfully */
123 Z_LOGD("All async init finished !");
126 /* Some initializers are failed */
127 Z_LOGE("There are some failed plugin initializer !");
130 /* Notify whether zigbee service is enabled or not */
131 zblib_plugin_send_notification(plugin,
132 driver_noti_id, &ret, sizeof(ret));
136 static void *__zblib_service_load_plugin(gchar *filename,
137 ZblibPluginDescriptor_t **descriptor_out)
139 ZblibPluginDescriptor_t *descriptor = NULL;
141 struct stat stat_buf;
144 zblib_check_null_ret_error("descriptor_out", descriptor_out, NULL);
147 handle = dlopen(filename, RTLD_LAZY);
148 if (G_UNLIKELY(NULL == handle)) {
149 Z_LOGE("dlopen() failed:[%s]", filename);
153 /* Get symbol - "zigbee_plugin_descriptor" */
154 descriptor = dlsym(handle, "zigbee_plugin_descriptor");
155 if (G_UNLIKELY(NULL == descriptor)) {
156 Z_LOGE("dlsym() failed:[%s]", "plugin_define_desc");
161 Z_LOGD("%s plugin", descriptor->name);
162 Z_LOGD(" - path = %s", filename);
163 Z_LOGD(" - version = %d", descriptor->version);
165 memset(&stat_buf, 0x00, sizeof(stat_buf));
166 memset(&file_date, '\0', sizeof(file_date));
168 if (0 == stat(filename, &stat_buf)) {
169 if (NULL != ctime_r(&stat_buf.st_mtime, file_date)) {
170 if (1 < strlen(file_date))
171 file_date[strlen(file_date)-1] = '\0';
172 Z_LOGD(" - date = %s", file_date);
177 if (G_LIKELY(descriptor->load)) {
178 if (G_UNLIKELY(FALSE == descriptor->load())) {
179 Z_LOGW("load() failed... Skip this plugin!");
183 Z_LOGI("Plug-in (%s) loaded!", descriptor->name);
187 *descriptor_out = descriptor;
192 static gboolean __zblib_service_init_plugin(ZigBeePlugin *plugin)
194 const ZblibPluginDescriptor_t *descriptor = zblib_plugin_get_descriptor(plugin);
196 zblib_check_null_ret_error("descriptor", descriptor, FALSE);
197 if (NULL == descriptor->init) {
198 Z_LOGD("descriptor->init is NULL, trying async init");
202 if (G_UNLIKELY(FALSE == descriptor->init(plugin))) {
203 char *plugin_name = zblib_plugin_get_plugin_name(plugin);
204 if (G_UNLIKELY(NULL != plugin_name)) {
205 Z_LOGE("plugin(%s) init failed!", plugin_name);
214 static gboolean __zblib_service_init_async_plugin(ZigBeePlugin *plugin,
215 zblib_plugin_init_finished_cb callback, void *user_data)
217 const ZblibPluginDescriptor_t *descriptor = zblib_plugin_get_descriptor(plugin);
218 char *plugin_name = NULL;
220 zblib_check_null_ret_error("descriptor", descriptor, FALSE);
221 zblib_check_null_ret_error("descriptor->init_async", descriptor->init_async, FALSE);
223 plugin_name = zblib_plugin_get_plugin_name(plugin);
224 if (G_UNLIKELY(NULL != plugin_name))
225 plugin_name = g_strdup("NONAME");
227 if (G_UNLIKELY(FALSE == descriptor->init_async(plugin, callback, user_data))) {
228 Z_LOGE("plugin(%s) init failed!", plugin_name);
237 static gboolean __zblib_service_unload_plugin(ZigBeePlugin *plugin)
239 const ZblibPluginDescriptor_t *descriptor = zblib_plugin_get_descriptor(plugin);
240 char *plugin_name = NULL;
242 zblib_check_null_ret_error("descriptor", descriptor, FALSE);
243 zblib_check_null_ret_error("descriptor->unload", descriptor->unload, FALSE);
245 plugin_name = zblib_plugin_get_plugin_name(plugin);
247 descriptor->unload(plugin);
248 Z_LOGI("plugin(%s) unloaded!", plugin_name);
255 static void __zblib_service_remove_request_table_iter(gpointer key,
256 gpointer value, gpointer user_data)
258 ZigBeeServiceInterface *service_interface = (ZigBeeServiceInterface *)user_data;
259 gint request_id = GPOINTER_TO_INT(key);
263 zblib_check_null_ret("service_interface", service_interface);
265 Z_LOGD("Removing request id [%d]", request_id);
266 zblib_request_free(service_interface, request_id);
269 static void __zblib_service_remove_async_list(GSList *list_async)
272 if (0 < g_slist_length(list_async)) {
273 iter = g_slist_nth(list_async, 0);
276 struct _zblib_async_init_info *async_plugin =
277 (struct _zblib_async_init_info *)(list_async->data);
278 list_async = g_slist_remove(list_async, async_plugin);
280 iter = g_slist_nth(list_async, 0);
285 ZigBeeService *zblib_service_new()
287 ZigBeeService *service;
289 service = g_malloc0(sizeof(struct zblib_service_type));
291 /* Create g-main loop */
292 service->main_loop = g_main_loop_new(NULL, FALSE);
293 if (G_UNLIKELY(NULL == service->main_loop)) {
294 Z_LOGE("g-main loop creation failed!!!");
299 /* Create request hash table */
300 service->request_table = g_hash_table_new_full(g_direct_hash,
301 g_direct_equal, NULL, NULL);
306 void zblib_service_free(ZigBeeService *service)
308 zblib_check_null_ret("service", service);
310 if (service->request_table) {
311 GSList *interface_objs = NULL;
312 ZigBeeServiceInterface *service_interface = NULL;
314 interface_objs = service->interface_objs;
315 if (NULL == interface_objs) {
316 Z_LOGE("interface_objs is NULL");
318 while (interface_objs) {
319 service_interface = (ZigBeeServiceInterface *)interface_objs->data;
321 /* Remove left request */
322 g_hash_table_foreach(service->request_table,
323 __zblib_service_remove_request_table_iter,
326 /* Move to next service interface */
327 interface_objs = g_slist_next(interface_objs);
329 g_hash_table_remove_all(service->request_table);
330 g_hash_table_destroy(service->request_table);
331 service->request_table = NULL;
335 /* Free async initializer */
336 if (service->async_initializer) {
337 g_slist_free(service->async_initializer);
338 service->async_initializer = NULL;
342 if (service->plugins) {
343 g_slist_free(service->plugins);
344 service->plugins = NULL;
347 /* Unref 'g-main loop' */
348 if (service->main_loop)
349 g_main_loop_unref(service->main_loop);
354 gboolean zblib_service_run(ZigBeeService *service)
356 zblib_check_null_ret_error("service", service, FALSE);
357 zblib_check_null_ret_error("service->main_loop", service->main_loop, FALSE);
359 g_main_loop_run(service->main_loop);
364 gboolean zblib_service_exit(ZigBeeService *service)
366 zblib_check_null_ret_error("service", service, FALSE);
367 zblib_check_null_ret_error("service->main_loop", service->main_loop, FALSE);
369 g_main_loop_quit(service->main_loop);
374 gboolean zblib_service_add_plugin(ZigBeeService *service, ZigBeePlugin *plugin)
378 zblib_check_null_ret_error("service", service, FALSE);
379 zblib_check_null_ret_error("plugin", plugin, FALSE);
381 plugin_name = zblib_plugin_get_plugin_name(plugin);
383 /* All plug-ins would be appended */
384 service->plugins = g_slist_append(service->plugins, plugin);
385 Z_LOGD("%s added", plugin_name);
391 gboolean zblib_service_remove_plugin(ZigBeeService *service, ZigBeePlugin *plugin)
393 zblib_check_null_ret_error("service", service, FALSE);
394 zblib_check_null_ret_error("plugin", plugin, FALSE);
396 /* Specific vendor plug-in would be removed */
397 service->plugins = g_slist_remove(service->plugins, plugin);
399 /* Deinitialize plugin */
400 zblib_plugin_free(plugin);
405 gboolean zblib_service_load_plugins(ZigBeeService *service, const char *plugin_path)
407 const gchar *file = NULL;
408 gchar *filename = NULL;
411 ZblibPluginDescriptor_t *descriptor = NULL;
412 ZigBeePlugin *plugin = NULL;
415 zblib_check_null_ret_error("service", service, FALSE);
416 zblib_check_null_ret_error("plugin_path", plugin_path, FALSE);
418 /* Open plug-in directory */
419 dir = g_dir_open(plugin_path, 0, NULL);
420 if (G_UNLIKELY(dir == NULL)) {
421 Z_LOGE("Directory open failed!");
425 /* Scan through all libraries in plug-in directory */
426 while ((file = g_dir_read_name(dir)) != NULL) {
427 if ((g_str_has_prefix(file, "lib") == TRUE)
428 || (g_str_has_suffix(file, ".so") == FALSE))
431 filename = g_build_filename(plugin_path, file, NULL);
434 handle = __zblib_service_load_plugin(filename, &descriptor);
435 if (G_UNLIKELY(NULL == handle)) {
440 /* Create new plug-in */
441 plugin = zblib_plugin_new(service, filename, descriptor, handle);
442 if (G_UNLIKELY(NULL == plugin)) {
448 /* Add new plug-in */
449 ret = zblib_service_add_plugin(service, plugin);
450 if (G_UNLIKELY(FALSE == ret))
451 zblib_plugin_free(plugin);
460 gboolean zblib_service_initialize_plugins(ZigBeeService *service)
465 zblib_check_null_ret_error("service", service, FALSE);
467 /* Refer plug-in list */
468 list = zblib_service_ref_plugins(service);
469 list_async = __zblib_service_ref_async_initializer(service);
470 while (list != NULL) {
471 /* Initialize each plug-in */
472 ZigBeePlugin *plugin = (ZigBeePlugin *)(list->data);
473 if (FALSE == __zblib_service_init_plugin(plugin)) {
474 /* If there is no initializer, it should have asynchronous one */
475 const ZblibPluginDescriptor_t *descriptor =
476 zblib_plugin_get_descriptor(plugin);
477 if (NULL != descriptor && NULL != descriptor->init_async) {
478 /* Register async initializer */
479 struct _zblib_async_init_info *info =
480 g_try_new0(struct _zblib_async_init_info, 1);
482 Z_LOGE("Fatal : Failed to allocate memory");
485 info->is_finished = FALSE;
486 info->is_initialized = FALSE;
487 info->plugin = plugin;
488 info->user_data = NULL;
490 list_async = g_slist_append(list_async, info);
492 __zblib_service_remove_async_list(list_async);
493 Z_LOGE("Fatal : Failed to initialize plugin");
497 list = g_slist_next(list);
500 __zblib_service_set_async_initializer(service, list_async);
505 gboolean zblib_service_initialize_async_plugins(ZigBeeService *service)
509 zblib_check_null_ret_error("service", service, FALSE);
511 /* Refer async initializer list */
512 list_async = __zblib_service_ref_async_initializer(service);
513 while (list_async != NULL) {
514 /* Initialize each plug-in */
515 struct _zblib_async_init_info *info =
516 (struct _zblib_async_init_info *)(list_async->data);
518 if (G_UNLIKELY(NULL == info)) {
519 Z_LOGE("Invalid parameter !");
520 list_async = g_slist_next(list_async);
524 if (G_UNLIKELY(FALSE == __zblib_service_init_async_plugin(
525 info->plugin, __on_zblib_init_async_finished, info))) {
526 Z_LOGE("Fatal : Failed to initialize mandatory plugin");
529 list_async = g_slist_next(list_async);
535 gboolean zblib_service_unload_plugins(ZigBeeService *service)
538 GSList *list_async = NULL;
540 zblib_check_null_ret_error("service", service, FALSE);
542 /* Unload everyy async_plugin */
543 list_async = __zblib_service_ref_async_initializer(service);
544 __zblib_service_remove_async_list(list_async);
546 list = zblib_service_ref_plugins(service);
547 while (list != NULL) {
548 ZigBeePlugin *plugin = list->data;
550 /* Unload each plug-in */
551 if (G_UNLIKELY(FALSE == __zblib_service_unload_plugin(plugin))) {
552 list = g_slist_next(list);
556 list = g_slist_next(list);
557 zblib_service_remove_plugin(service, plugin);
563 GSList *zblib_service_ref_plugins(ZigBeeService *service)
565 zblib_check_null_ret_error("service", service, NULL);
567 return service->plugins;
570 gboolean zblib_service_add_service_interface(ZigBeeService *service,
571 ZigBeeServiceInterface *service_interface)
575 zblib_check_null_ret_error("service", service, FALSE);
576 zblib_check_null_ret_error("service_interface_name", service_interface, FALSE);
578 object_name = zblib_service_interface_get_name(service_interface);
581 * All service interface objects would be appended
583 service->interface_objs = g_slist_append(service->interface_objs, service_interface);
584 Z_LOGD("%s added", object_name);
590 gboolean zblib_service_remove_service_interface(ZigBeeService *service,
591 ZigBeeServiceInterface *service_interface)
593 zblib_check_null_ret_error("service", service, FALSE);
594 zblib_check_null_ret_error("service_interface_name", service_interface, FALSE);
597 * service interface object would be removed
599 service->interface_objs = g_slist_remove(service->interface_objs, service_interface);
604 ZigBeeServiceInterface *zblib_service_ref_service_interface(ZigBeeService *service,
605 const gchar *service_interface_name)
607 ZigBeeServiceInterface *service_interface = NULL;
608 ZigBeeServiceInterface *tmp_service_interface = NULL;
613 zblib_check_null_ret_error("service", service, NULL);
614 zblib_check_null_ret_error("service_interface_name", service_interface_name, NULL);
616 list = service->interface_objs;
618 tmp_service_interface = (ZigBeeServiceInterface *)list->data;
620 /* Get object name of service_interface */
621 object_name = zblib_service_interface_get_name(tmp_service_interface);
622 if (g_strcmp0(service_interface_name, object_name) == 0) {
625 service_interface = tmp_service_interface;
630 list = g_slist_next(list);
633 if (NULL == service_interface) {
634 Z_LOGE("Service interface object of name '%s' not found!",
635 service_interface_name);
639 Z_LOGD("'%s' found", service_interface_name);
641 return service_interface;
644 GHashTable *zblib_service_ref_request_hash_table(ZigBeeService *service)
646 zblib_check_null_ret_error("service", service, NULL);
648 return service->request_table;
651 gint zblib_service_generate_request_id(ZigBeeService *service)
653 zblib_check_null_ret_error("service", service, -1);
655 /* Increment request ID */
656 service->request_id++;
658 return (gint)service->request_id;
661 gboolean zblib_service_dispatch_request(ZigBeeService *service,
664 ZigBeePlugin *plugin = NULL;
665 GSList *plugin_list = NULL;
666 gboolean ret = FALSE;
668 zblib_check_null_ret_error("service", service, FALSE);
670 /* Fetch plugin_list */
671 plugin_list = service->plugins;
672 zblib_check_null_ret_error("plugin_list", plugin_list, FALSE);
674 while (plugin_list) {
675 plugin = (ZigBeePlugin *)plugin_list->data;
677 /* Dispatch request to plugin */
678 ret = zblib_plugin_dispatch_request(plugin, request_id);
680 /* Move to next plugin */
681 plugin_list = g_slist_next(plugin_list);
687 void zblib_service_send_response(ZigBeeService *service,
688 guint request_id, gpointer resp_data, guint resp_data_len)
690 ZigBeeServiceInterface *service_interface = NULL;
692 zblib_check_null_ret("service", service);
694 service_interface = zblib_request_ref_service_interface(service, request_id);
695 zblib_check_null_ret("service_interface", service_interface);
697 /* Send response to service interface */
698 zblib_service_interface_send_response(service_interface,
699 request_id, resp_data, resp_data_len);
702 void zblib_service_send_notification(ZigBeeService *service,
703 guint noti_id, gpointer noti_data, guint noti_data_len)
705 GSList *interface_objs = NULL;
706 ZigBeeServiceInterface *service_interface = NULL;
708 zblib_check_null_ret("service", service);
710 interface_objs = service->interface_objs;
711 zblib_check_null_ret("interface_objs", interface_objs);
713 while (interface_objs) {
714 service_interface = (ZigBeeServiceInterface *)interface_objs->data;
716 /* Send notification to service interface */
717 zblib_service_interface_send_notification(service_interface,
718 noti_id, noti_data, noti_data_len);
720 /* Move to next service interface */
721 interface_objs = g_slist_next(interface_objs);