2 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License")
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include <ua-plugin.h>
22 #include <ua-plugin-manager.h>
23 #include <tzplatform_config.h>
25 #include "ua-pm-util.h"
27 static unsigned int available_sensors = 0;
29 extern const uas_callbacks_t ble_cbs;
30 extern const uas_callbacks_t wifi_cbs;
31 extern const uas_callbacks_t light_cbs;
32 extern const uas_callbacks_t motion_cbs;
34 static int ble_detection_type = 0;
35 static int wifi_detection_type = 0;
41 uas_capability_e capability;
42 } uam_sensor_plugin_info_t;
44 uam_sensor_plugin_info_t* plugins[UAS_PLUGIN_ID_MAX];
46 static gboolean __add_plugin(void *handle, uas_module_t *module)
49 uas_api_t *api = NULL;
50 uam_sensor_plugin_info_t *plugin;
52 UAM_DBG("Plugin [id: %d, name: %s, version: %s]",
53 module->id, module->name, module->version);
55 if (UAS_PLUGIN_ID_MAX <= module->id ||
56 UAS_PLUGIN_ID_BLE > module->id) {
57 UAM_ERR("Unknown Id %d for %s", module->id, module->name);
61 if (NULL != plugins[module->id]) {
62 UAM_ERR("Plugin %s already added",
63 plugins[module->id]->module->name);
67 if (g_str_equal(module->version, UAM_VERSION) == FALSE) {
68 UAM_ERR("Version (%s) mismatch for %s",
69 module->version, module->name);
73 plugin = g_try_new0(uam_sensor_plugin_info_t, 1);
75 UAM_ERR("Memory allocation failed");
78 if (NULL == module->init) {
79 UAM_ERR("module->init is NULL");
86 UAM_ERR("API returned is NULL");
91 plugin->handle = handle;
92 plugin->module = module;
95 plugins[module->id] = plugin;
101 static int __load_plugin(const char *path, const char *name, const char *symbol)
106 uas_module_t *module;
108 retv_if(NULL == path, UAM_ERROR_INVALID_PARAMETER);
109 retv_if(NULL == name, UAM_ERROR_INVALID_PARAMETER);
110 retv_if(NULL == symbol, UAM_ERROR_INVALID_PARAMETER);
112 filename = g_build_filename(path, name, NULL);
113 UAM_DBG("Loading [%s]", filename);
115 handle = dlopen(filename, RTLD_NOW);
117 if (handle == NULL) {
118 UAM_ERR("Can't load plugin %s", dlerror());
119 return UAM_ERROR_INTERNAL;
122 module = (uas_module_t *)dlsym(handle, symbol);
123 if (module == NULL) {
124 UAM_ERR("Can't load plugin module: %s", dlerror());
126 return UAM_ERROR_INTERNAL;
129 retv_if(FALSE == __add_plugin(handle, module), UAM_ERROR_INTERNAL);
132 return UAM_ERROR_NONE;
135 static int __load_sensor_plugins(void)
140 const char *filename;
141 int ret = UAM_ERROR_INTERNAL;
143 retv_if(0 == strlen(SENSOR_PLUGIN_DIR), UAM_ERROR_INVALID_PARAMETER);
145 UAM_DBG("Loading plugins from %s", SENSOR_PLUGIN_DIR);
147 dir = g_dir_open(SENSOR_PLUGIN_DIR, 0, NULL);
149 UAM_ERR("Unable to open directory");
150 return UAM_ERROR_INTERNAL;
153 while ((filename = g_dir_read_name(dir)) != NULL) {
155 if (g_str_has_suffix(filename, ".so") == FALSE)
158 /* If atleast one plugin is loaded, return value is UAM_ERROR_NONE */
159 if (UAM_ERROR_NONE == __load_plugin(
160 SENSOR_PLUGIN_DIR, filename, "uas_module"))
161 ret = UAM_ERROR_NONE;
171 static int __init_sensor_plugins(void)
174 int ret = UAM_ERROR_INTERNAL;
177 retv_if(UAM_ERROR_NONE != __load_sensor_plugins(), UAM_ERROR_INTERNAL);
179 /* Initialize loaded sensor plugins */
180 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
181 uam_sensor_plugin_info_t *plugin = plugins[id];
184 if (!plugin || !plugin->api) {
185 UAM_WARN("Plugin with ID: %s is NULL", _uam_get_sensor_str(id));
190 case UAS_PLUGIN_ID_BLE:
191 status = plugin->api->init(&ble_cbs);
192 if (UAS_STATUS_SUCCESS != status) {
197 plugin->capability = UAS_NOT_SUPPORT_USER;
198 if (UAS_STATUS_SUCCESS != plugin->api->get_capability(
199 &plugin->capability))
200 plugin->capability = UAS_NOT_SUPPORT_USER;
202 available_sensors |= UAM_SENSOR_BITMASK_BLE;
204 case UAS_PLUGIN_ID_WIFI:
205 status = plugin->api->init(&wifi_cbs);
206 if (UAS_STATUS_SUCCESS != status) {
211 plugin->capability = UAS_NOT_SUPPORT_USER;
212 if (UAS_STATUS_SUCCESS != plugin->api->get_capability(
213 &plugin->capability))
214 plugin->capability = UAS_NOT_SUPPORT_USER;
216 available_sensors |= UAM_SENSOR_BITMASK_WIFI;
219 case UAS_PLUGIN_ID_LIGHT:
220 status = plugin->api->init(&light_cbs);
221 if (UAS_STATUS_SUCCESS != status) {
226 available_sensors |= UAM_SENSOR_BITMASK_LIGHT;
228 case UAS_PLUGIN_ID_MOTION:
229 status = plugin->api->init(&motion_cbs);
230 if (UAS_STATUS_SUCCESS != status) {
235 available_sensors |= UAM_SENSOR_BITMASK_MOTION;
239 /* If atleast one sensor init is success, return success */
240 ret = UAM_ERROR_NONE;
247 static void __deinit_sensor_plugins(void)
252 /* Deinitialize and unload sensor plugins */
253 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
254 uam_sensor_plugin_info_t *plugin = plugins[id];
259 if (plugin->api && plugin->api->deinit)
260 plugin->api->deinit();
262 if (plugin->module && plugin->module->deinit)
263 plugin->module->deinit();
266 dlclose(plugin->handle);
272 available_sensors = 0;
276 static void __uas_device_list_free(int count, uas_device_info_t *devices)
282 for (i = 0; i < count; i++) {
283 uas_device_info_t *device = &(devices[i]);
285 g_free(device->device_id);
287 for (j = 0; j < device->num_addr; j++)
288 g_free(device->addr_list[j].address);
290 g_free(device->addr_list);
298 static uas_device_info_t *__get_uas_device_list(int id, GSList *devices, int *num_devices)
301 uas_device_info_t *dev_list;
305 unsigned int tech_type;
307 retv_if(NULL == devices, NULL);
309 tech_type = _pm_util_uas_plugin_id_to_tech_type(id);
310 retv_if(UAM_TECH_TYPE_NONE == tech_type, NULL);
312 len = g_slist_length(devices);
313 dev_list = g_new0(uas_device_info_t, len);
315 for (l = devices; NULL != l; l = g_slist_next(l)) {
316 uam_db_device_info_t *dev = l->data;
317 uas_device_info_t *device = &(dev_list[count]);
322 if (dev->supported_techs & tech_type) {
323 _pm_util_uam_db_dev_to_uas_dev(tech_type, dev, &device);
324 device->supported_techs = dev->supported_techs;
329 *num_devices = count;
335 int _uam_pm_init(void)
340 ret = __init_sensor_plugins();
341 if (UAM_ERROR_NONE != ret)
345 return UAM_ERROR_NONE;
348 void _uam_pm_deinit(void)
352 __deinit_sensor_plugins();
357 unsigned int _uam_pm_get_avaliable_sensors(void)
361 UAM_DBG("Available sensors: 0x%8.8X", available_sensors);
364 return available_sensors;
367 gboolean _uam_pm_is_sensor_ready(unsigned int sensor_bitmask)
372 uam_sensor_plugin_info_t *plugin;
374 id = _pm_util_sensor_bitmask_to_plugin_id(sensor_bitmask);
375 retv_if(UAS_PLUGIN_ID_MAX <= id, FALSE);
377 plugin = plugins[id];
378 retv_if(!plugin || !plugin->api, FALSE);
380 if (UAS_STATUS_SUCCESS != plugin->api->get_state(&state))
381 state = UAS_STATE_NOT_READY;
383 UAM_DBG("Sensor: 0x%8.8X, State: %d", sensor_bitmask, state);
386 return (UAS_STATE_READY == state ? TRUE : FALSE);
389 int _uam_pm_register_device(int user_id, const uam_device_info_s *dev)
393 uam_sensor_plugin_info_t *plugin;
394 uas_device_info_t *device = NULL;
396 retv_if(NULL == dev, UAM_ERROR_INVALID_PARAMETER);
398 id = _pm_util_uam_tech_type_to_plugin_id(dev->type);
399 retv_if(UAS_PLUGIN_ID_MAX <= id, UAM_ERROR_INVALID_PARAMETER);
401 plugin = plugins[id];
402 retv_if(!plugin || !plugin->api, UAM_ERROR_NOT_SUPPORTED);
403 retv_if(UAS_SUPPORT_USER != plugin->capability, UAM_ERROR_NOT_SUPPORTED);
405 device = _pm_util_uam_dev_info_to_uas_dev_info(dev);
406 retv_if(NULL == device, UAM_ERROR_INTERNAL);
408 device->user_id = user_id;
409 if (UAS_STATUS_SUCCESS != plugin->api->add_device(device)) {
410 UAM_ERR("plugin->add_device() failed");
411 return UAM_ERROR_INTERNAL;
413 _pm_util_uas_device_info_free(device);
416 return UAM_ERROR_NONE;
419 int _uam_pm_unregister_device(int user_id, const uam_device_info_s *dev)
423 uam_sensor_plugin_info_t *plugin;
424 uas_device_info_t *device = NULL;
427 retv_if(NULL == dev, UAM_ERROR_INVALID_PARAMETER);
429 id = _pm_util_uam_tech_type_to_plugin_id(dev->type);
430 retv_if(UAS_PLUGIN_ID_MAX <= id, UAM_ERROR_INVALID_PARAMETER);
432 plugin = plugins[id];
433 retv_if(!plugin || !plugin->api, UAM_ERROR_NOT_SUPPORTED);
434 retv_if(UAS_SUPPORT_USER != plugin->capability, UAM_ERROR_NOT_SUPPORTED);
436 device = _pm_util_uam_dev_info_to_uas_dev_info(dev);
437 retv_if(NULL == device, UAM_ERROR_INTERNAL);
438 device->user_id = user_id;
440 ret = plugin->api->remove_device(device);
441 if (UAS_STATUS_SUCCESS != ret && UAS_STATUS_ALREADY_DONE != ret) {
442 UAM_ERR("plugin->remove_device() failed");
445 _pm_util_uas_device_info_free(device);
448 return UAM_ERROR_NONE;
451 int _uam_pm_set_registered_devices(GSList *devices)
455 uas_device_info_t *dev_list = NULL;
458 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
459 uam_sensor_plugin_info_t *plugin = plugins[id];
461 if (!plugin || !plugin->api)
464 if (UAS_SUPPORT_USER != plugin->capability)
467 dev_list = __get_uas_device_list(id, devices, &num_devices);
469 UAM_INFO("No devices for Plugin %d", id);
471 if (UAS_STATUS_SUCCESS != plugin->api->set_registered_devices(
472 num_devices, dev_list))
473 UAM_ERR("plugin->set_registered_devices() failed for %d", id);
475 __uas_device_list_free(num_devices, dev_list);
479 return UAM_ERROR_NONE;
482 int _uam_pm_start_detection(unsigned int detection_mode, unsigned int bitmask)
487 int ret = UAM_ERROR_INTERNAL;
488 uas_detection_type_e type;
490 switch (detection_mode) {
491 case UAM_DETECT_PRESENCE:
494 case UAM_DETECT_ABSENCE:
498 type = UAS_PRESENCE | UAS_ABSENCE;
501 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
502 uam_sensor_plugin_info_t *plugin = plugins[id];
503 unsigned int sensor = _pm_util_uas_plugin_id_to_sensor_bitmask(id);
505 if (!(sensor & bitmask))
508 if (!plugin || !plugin->api)
512 * For User/device detection capable plugins, need to start both, PRESENCE
513 * as well as ABSENCE detection, to keep UA database updated.
515 if (UAS_PLUGIN_ID_BLE == id || UAS_PLUGIN_ID_WIFI == id)
516 status = plugin->api->start_detection(UAS_PRESENCE | UAS_ABSENCE);
518 status = plugin->api->start_detection(type);
520 if (UAS_STATUS_SUCCESS != status && UAS_STATUS_ALREADY_DONE != status) {
521 UAM_ERR("plugin->start_detection(%d) failed for %d", type, id);
525 if (UAS_PLUGIN_ID_BLE == id)
526 ble_detection_type |= type;
527 if (UAS_PLUGIN_ID_WIFI == id)
528 wifi_detection_type |= type;
530 /* Result success if detection started for atleast 1 of the sensor */
531 ret = UAM_ERROR_NONE;
538 int _uam_pm_stop_detection(unsigned int detection_mode, unsigned int bitmask)
543 int ret = UAM_ERROR_INTERNAL;
544 uas_detection_type_e type;
546 switch (detection_mode) {
547 case UAM_DETECT_PRESENCE:
550 case UAM_DETECT_ABSENCE:
554 type = UAS_PRESENCE | UAS_ABSENCE;
557 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
558 uam_sensor_plugin_info_t *plugin = plugins[id];
559 unsigned int sensor = _pm_util_uas_plugin_id_to_sensor_bitmask(id);
561 if (!(sensor & bitmask))
564 if (!plugin || !plugin->api)
567 if (UAS_PLUGIN_ID_BLE == id) {
568 ble_detection_type &= ~type;
569 ret = UAM_ERROR_NONE;
570 if (0 != ble_detection_type)
574 if (UAS_PLUGIN_ID_WIFI == id) {
575 wifi_detection_type &= ~type;
576 ret = UAM_ERROR_NONE;
577 if (0 != wifi_detection_type)
581 if (UAS_PLUGIN_ID_BLE == id || UAS_PLUGIN_ID_WIFI == id)
582 status = plugin->api->stop_detection(UAS_PRESENCE | UAS_ABSENCE);
584 status = plugin->api->stop_detection(type);
586 if (UAS_STATUS_SUCCESS != status && UAS_STATUS_ALREADY_DONE != status) {
587 UAM_ERR("plugin->stop_detection(%d) failed for %d", type, id);
591 /* Result success if detection stopped for atleast 1 of the sensor */
592 ret = UAM_ERROR_NONE;
599 int _uam_pm_set_low_power_mode(unsigned int bitmask, gboolean mode)
604 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
605 uam_sensor_plugin_info_t *plugin = plugins[id];
606 unsigned int sensor = _pm_util_uas_plugin_id_to_sensor_bitmask(id);
608 if (!(sensor & bitmask))
611 if (!plugin || !plugin->api || !plugin->api->set_low_power_mode)
614 if (UAS_STATUS_SUCCESS !=
615 plugin->api->set_low_power_mode(mode ? 1 : 0))
616 UAM_ERR("plugin->set_low_power_mode() failed for %d", id);
620 return UAM_ERROR_NONE;
623 int _uam_pm_set_detection_window(unsigned int detection_window)
627 int ret = UAM_ERROR_INTERNAL;
629 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
630 uam_sensor_plugin_info_t *plugin = plugins[id];
632 if (!plugin || !plugin->api || !plugin->api->set_detection_window)
635 if (UAS_STATUS_SUCCESS != plugin->api->set_detection_window(detection_window)) {
636 UAM_ERR("plugin->set_detection_window() failed");
640 /* Result success if detection params set for atleast 1 of the sensors */
641 ret = UAM_ERROR_NONE;
648 int _uam_pm_set_detection_threshold(unsigned int sensor,
649 int presence_threshold, int absence_threshold)
653 uam_sensor_plugin_info_t *plugin;
655 id = _pm_util_sensor_bitmask_to_plugin_id(sensor);
656 retv_if(UAS_PLUGIN_ID_MAX <= id, UAM_ERROR_INVALID_PARAMETER);
658 plugin = plugins[id];
659 retv_if(!plugin || !plugin->api, UAM_ERROR_NOT_SUPPORTED);
661 if (UAS_STATUS_SUCCESS != plugin->api->set_detection_threshold(
662 presence_threshold, absence_threshold)) {
663 UAM_ERR("plugin->set_detection_threshold() failed");
664 return UAM_ERROR_INTERNAL;
668 return UAM_ERROR_NONE;
671 int _uam_pm_start_active_device_scan(unsigned int* bitmask, int detection_period)
676 int ret = UAM_ERROR_INTERNAL;
678 unsigned int scanning_sensor = 0;
680 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
681 uam_sensor_plugin_info_t *plugin = plugins[id];
682 unsigned int sensor = _pm_util_uas_plugin_id_to_sensor_bitmask(id);
684 if (!(sensor & (*bitmask)))
687 if (!plugin || !plugin->api || !plugin->api->scan_active_devices)
690 status = plugin->api->scan_active_devices(detection_period);
692 if (UAS_STATUS_SUCCESS != status && UAS_STATUS_ALREADY_DONE != status) {
693 UAM_ERR("plugin->search_active_devices(%d) failed for %d", detection_period, id);
697 scanning_sensor |= sensor;
698 /* Result success if scanning started for atleast 1 of the sensor */
699 ret = UAM_ERROR_NONE;
702 (*bitmask) &= scanning_sensor;
708 int _uam_pm_stop_active_device_scan(unsigned int bitmask)
713 int ret = UAM_ERROR_INTERNAL;
715 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
716 uam_sensor_plugin_info_t *plugin = plugins[id];
717 unsigned int sensor = _pm_util_uas_plugin_id_to_sensor_bitmask(id);
719 if (!(sensor & bitmask))
722 if (!plugin || !plugin->api || !plugin->api->cancel_active_device_scan)
725 status = plugin->api->cancel_active_device_scan();
727 if (UAS_STATUS_SUCCESS != status && UAS_STATUS_ALREADY_DONE != status) {
728 UAM_ERR("plugin->stop_search_active_devices() failed for %d", id);
732 ret = UAM_ERROR_NONE;
739 int _uam_pm_add_ibeacon_adv(unsigned int adv_len, const char *iadv)
744 int ret = UAM_ERROR_INTERNAL;
746 id = UAS_PLUGIN_ID_BLE;
747 uam_sensor_plugin_info_t *plugin = plugins[id];
749 if (!plugin || !plugin->api || !plugin->api->add_ibeacon_adv) {
750 ret = UAM_ERROR_NOT_SUPPORTED;
754 status = plugin->api->add_ibeacon_adv(adv_len, iadv);
755 if (UAS_STATUS_SUCCESS != status && UAS_STATUS_ALREADY_DONE != status) {
756 UAM_ERR("plugin->add_ibeacon_adv failed for %d", id);
759 ret = UAM_ERROR_NONE;