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>
28 /**< ZigBee Service object */
29 struct zblib_service_type {
30 GMainLoop *main_loop; /**< Service main-loop */
32 GSList *interface_objs; /**< ZigBee Service interface objects */
33 GSList *plugins; /**< ZigBee plug-ins */
35 GHashTable *request_table; /**< Request Hash table */
36 guint request_id; /**< Request ID */
39 static void *__zblib_service_load_plugin(gchar *filename,
40 ZblibPluginDescriptor_t **descriptor_out)
42 ZblibPluginDescriptor_t *descriptor = NULL;
47 zblib_check_null_ret_error("descriptor_out", descriptor_out, NULL);
50 handle = dlopen(filename, RTLD_LAZY);
51 if (G_UNLIKELY(NULL == handle)) {
52 Z_LOGE("dlopen() failed:[%s]", filename);
56 /* Get symbol - "zigbee_plugin_descriptor" */
57 descriptor = dlsym(handle, "zigbee_plugin_descriptor");
58 if (G_UNLIKELY(NULL == descriptor)) {
59 Z_LOGE("dlsym() failed:[%s]", "plugin_define_desc");
64 Z_LOGD("%s plugin", descriptor->name);
65 Z_LOGD(" - path = %s", filename);
66 Z_LOGD(" - version = %d", descriptor->version);
68 memset(&stat_buf, 0x00, sizeof(stat_buf));
69 memset(&file_date, '\0', sizeof(file_date));
71 if (0 == stat(filename, &stat_buf)) {
72 if (NULL != ctime_r(&stat_buf.st_mtime, file_date)) {
73 if (1 < strlen(file_date))
74 file_date[strlen(file_date)-1] = '\0';
75 Z_LOGD(" - date = %s", file_date);
80 if (G_LIKELY(descriptor->load)) {
81 if (G_UNLIKELY(FALSE == descriptor->load())) {
82 Z_LOGW("load() failed... Skip this plugin!");
86 Z_LOGI("Plug-in (%s) loaded!", descriptor->name);
90 *descriptor_out = descriptor;
95 static gboolean __zblib_service_init_plugin(ZigBeePlugin *plugin)
97 const ZblibPluginDescriptor_t *descriptor = zblib_plugin_get_descriptor(plugin);
99 zblib_check_null_ret_error("descriptor", descriptor, FALSE);
100 zblib_check_null_ret_error("descriptor->init", descriptor->init, FALSE);
102 if (G_UNLIKELY(FALSE == descriptor->init(plugin))) {
103 char *plugin_name = zblib_plugin_get_plugin_name(plugin);
104 if (G_UNLIKELY(NULL != plugin_name)) {
105 Z_LOGE("plugin(%s) init failed!", plugin_name);
114 static gboolean __zblib_service_unload_plugin(ZigBeePlugin *plugin)
116 const ZblibPluginDescriptor_t *descriptor = zblib_plugin_get_descriptor(plugin);
117 char *plugin_name = NULL;
119 zblib_check_null_ret_error("descriptor", descriptor, FALSE);
120 zblib_check_null_ret_error("descriptor->unload", descriptor->unload, FALSE);
122 plugin_name = zblib_plugin_get_plugin_name(plugin);
124 descriptor->unload(plugin);
125 Z_LOGI("plugin(%s) unloaded!", plugin_name);
132 static void __zblib_service_remove_request_table_iter(gpointer key,
133 gpointer value, gpointer user_data)
135 ZigBeeServiceInterface *service_interface = (ZigBeeServiceInterface *)user_data;
136 gint request_id = (gint)key;
140 zblib_check_null_ret("service_interface", service_interface);
142 Z_LOGD("Removing request id [%d]", request_id);
143 zblib_request_free(service_interface, request_id);
146 ZigBeeService *zblib_service_new()
148 ZigBeeService *service;
150 service = g_malloc0(sizeof(struct zblib_service_type));
152 /* Create g-main loop */
153 service->main_loop = g_main_loop_new(NULL, FALSE);
154 if (G_UNLIKELY(NULL == service->main_loop)) {
155 Z_LOGE("g-main loop creation failed!!!");
160 /* Create request hash table */
161 service->request_table = g_hash_table_new_full(g_direct_hash,
162 g_direct_equal, NULL, NULL);
167 void zblib_service_free(ZigBeeService *service)
169 zblib_check_null_ret("service", service);
171 if (service->request_table) {
172 GSList *interface_objs = NULL;
173 ZigBeeServiceInterface *service_interface = NULL;
175 interface_objs = service->interface_objs;
176 if (NULL == interface_objs) {
177 Z_LOGE("interface_objs is NULL");
179 while (interface_objs) {
180 service_interface = (ZigBeeServiceInterface *)interface_objs->data;
182 /* Remove left request */
183 g_hash_table_foreach(service->request_table,
184 __zblib_service_remove_request_table_iter,
187 /* Move to next service interface */
188 interface_objs = g_slist_next(interface_objs);
190 g_hash_table_remove_all(service->request_table);
191 g_hash_table_destroy(service->request_table);
192 service->request_table = NULL;
197 if (service->plugins) {
198 g_slist_free(service->plugins);
199 service->plugins = NULL;
202 /* Unref 'g-main loop' */
203 if (service->main_loop)
204 g_main_loop_unref(service->main_loop);
209 gboolean zblib_service_run(ZigBeeService *service)
211 zblib_check_null_ret_error("service", service, FALSE);
212 zblib_check_null_ret_error("service->main_loop", service->main_loop, FALSE);
214 g_main_loop_run(service->main_loop);
219 gboolean zblib_service_exit(ZigBeeService *service)
221 zblib_check_null_ret_error("service", service, FALSE);
222 zblib_check_null_ret_error("service->main_loop", service->main_loop, FALSE);
224 g_main_loop_quit(service->main_loop);
229 gboolean zblib_service_add_plugin(ZigBeeService *service, ZigBeePlugin *plugin)
233 zblib_check_null_ret_error("service", service, FALSE);
234 zblib_check_null_ret_error("plugin", plugin, FALSE);
236 plugin_name = zblib_plugin_get_plugin_name(plugin);
238 /* All plug-ins would be appended */
239 service->plugins = g_slist_append(service->plugins, plugin);
240 Z_LOGD("%s added", plugin_name);
246 gboolean zblib_service_remove_plugin(ZigBeeService *service, ZigBeePlugin *plugin)
248 zblib_check_null_ret_error("service", service, FALSE);
249 zblib_check_null_ret_error("plugin", plugin, FALSE);
251 /* Specific vendor plug-in would be removed */
252 service->plugins = g_slist_remove(service->plugins, plugin);
254 /* Deinitialize plugin */
255 zblib_plugin_free(plugin);
260 gboolean zblib_service_load_plugins(ZigBeeService *service, const char *plugin_path)
262 const gchar *file = NULL;
263 gchar *filename = NULL;
266 ZblibPluginDescriptor_t *descriptor = NULL;
267 ZigBeePlugin *plugin = NULL;
270 zblib_check_null_ret_error("service", service, FALSE);
271 zblib_check_null_ret_error("plugin_path", plugin_path, FALSE);
273 /* Open plug-in directory */
274 dir = g_dir_open(plugin_path, 0, NULL);
275 if (G_UNLIKELY(dir == NULL)) {
276 Z_LOGE("Directory open failed!");
280 /* Scan through all libraries in plug-in directory */
281 while ((file = g_dir_read_name(dir)) != NULL) {
282 if ((g_str_has_prefix(file, "lib") == TRUE)
283 || (g_str_has_suffix(file, ".so") == FALSE))
286 filename = g_build_filename(plugin_path, file, NULL);
289 handle = __zblib_service_load_plugin(filename, &descriptor);
290 if (G_UNLIKELY(NULL == handle)) {
295 /* Create new plug-in */
296 plugin = zblib_plugin_new(service, filename, descriptor, handle);
297 if (G_UNLIKELY(NULL == plugin)) {
302 /* Add new plug-in */
303 ret = zblib_service_add_plugin(service, plugin);
304 if (G_UNLIKELY(FALSE == ret)) {
305 zblib_plugin_free(plugin);
315 gboolean zblib_service_initialize_plugins(ZigBeeService *service)
319 zblib_check_null_ret_error("service", service, FALSE);
321 /* Refer plug-in list */
322 list = zblib_service_ref_plugins(service);
323 while (list != NULL) {
324 /* Initialize each plug-in */
325 if (G_UNLIKELY(FALSE == __zblib_service_init_plugin((ZigBeePlugin *)(list->data)))) {
326 list = g_slist_next(list);
329 list = g_slist_next(list);
335 gboolean zblib_service_unload_plugins(ZigBeeService *service)
339 zblib_check_null_ret_error("service", service, FALSE);
341 list = zblib_service_ref_plugins(service);
342 while (list != NULL) {
343 ZigBeePlugin *plugin = list->data;
345 /* Unload each plug-in */
346 if (G_UNLIKELY(FALSE == __zblib_service_unload_plugin(plugin))) {
347 list = g_slist_next(list);
351 list = g_slist_next(list);
352 zblib_service_remove_plugin(service, plugin);
358 GSList *zblib_service_ref_plugins(ZigBeeService *service)
360 zblib_check_null_ret_error("service", service, NULL);
362 return service->plugins;
365 gboolean zblib_service_add_service_interface(ZigBeeService *service,
366 ZigBeeServiceInterface *service_interface)
370 zblib_check_null_ret_error("service", service, FALSE);
371 zblib_check_null_ret_error("service_interface_name", service_interface, FALSE);
373 object_name = zblib_service_interface_get_name(service_interface);
376 * All service interface objects would be appended
378 service->interface_objs = g_slist_append(service->interface_objs, service_interface);
379 Z_LOGD("%s added", object_name);
385 gboolean zblib_service_remove_service_interface(ZigBeeService *service,
386 ZigBeeServiceInterface *service_interface)
388 zblib_check_null_ret_error("service", service, FALSE);
389 zblib_check_null_ret_error("service_interface_name", service_interface, FALSE);
392 * service interface object would be removed
394 service->interface_objs = g_slist_remove(service->interface_objs, service_interface);
399 ZigBeeServiceInterface *zblib_service_ref_service_interface(ZigBeeService *service,
400 const gchar *service_interface_name)
402 ZigBeeServiceInterface *service_interface = NULL;
403 ZigBeeServiceInterface *tmp_service_interface = NULL;
408 zblib_check_null_ret_error("service", service, NULL);
409 zblib_check_null_ret_error("service_interface_name", service_interface_name, NULL);
411 list = service->interface_objs;
413 tmp_service_interface = (ZigBeeServiceInterface *)list->data;
415 /* Get object name of service_interface */
416 object_name = zblib_service_interface_get_name(tmp_service_interface);
417 if (g_strcmp0(service_interface_name, object_name) == 0) {
420 service_interface = tmp_service_interface;
425 list = g_slist_next(list);
428 if (NULL == service_interface) {
429 Z_LOGE("Service interface object of name '%s' not found!",
430 service_interface_name);
434 Z_LOGD("'%s' found", service_interface_name);
436 return service_interface;
439 GHashTable *zblib_service_ref_request_hash_table(ZigBeeService *service)
441 zblib_check_null_ret_error("service", service, NULL);
443 return service->request_table;
446 gint zblib_service_generate_request_id(ZigBeeService *service)
448 zblib_check_null_ret_error("service", service, -1);
450 /* Increment request ID */
451 service->request_id++;
453 return (gint)service->request_id;
456 gboolean zblib_service_dispatch_request(ZigBeeService *service,
459 ZigBeePlugin *plugin = NULL;
460 GSList *plugin_list = NULL;
461 gboolean ret = FALSE;
463 zblib_check_null_ret_error("service", service, FALSE);
465 /* Fetch plugin_list */
466 plugin_list = service->plugins;
467 zblib_check_null_ret_error("plugin_list", plugin_list, FALSE);
469 while (plugin_list) {
470 plugin = (ZigBeePlugin *)plugin_list->data;
472 /* Dispatch request to plugin */
473 ret = zblib_plugin_dispatch_request(plugin, request_id);
475 /* Move to next plugin */
476 plugin_list = g_slist_next(plugin_list);
482 void zblib_service_send_response(ZigBeeService *service,
483 guint request_id, gpointer resp_data, guint resp_data_len)
485 ZigBeeServiceInterface *service_interface = NULL;
487 zblib_check_null_ret("service", service);
489 service_interface = zblib_request_ref_service_interface(service, request_id);
490 zblib_check_null_ret("service_interface", service_interface);
492 /* Send response to service interface */
493 zblib_service_interface_send_response(service_interface,
494 request_id, resp_data, resp_data_len);
497 void zblib_service_send_notification(ZigBeeService *service,
498 guint noti_id, gpointer noti_data, guint noti_data_len)
500 GSList *interface_objs = NULL;
501 ZigBeeServiceInterface *service_interface = NULL;
503 zblib_check_null_ret("service", service);
505 interface_objs = service->interface_objs;
506 zblib_check_null_ret("interface_objs", interface_objs);
508 while (interface_objs) {
509 service_interface = (ZigBeeServiceInterface *)interface_objs->data;
511 /* Send notification to service interface */
512 zblib_service_interface_send_notification(service_interface,
513 noti_id, noti_data, noti_data_len);
515 /* Move to next service interface */
516 interface_objs = g_slist_next(interface_objs);