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 <ua-vendor-plugin.h>
24 #include <tzplatform_config.h>
26 #include "ua-pm-util.h"
28 static unsigned int available_sensors = 0;
29 static unsigned int user_sensors = 0;
30 static unsigned int env_sensors = 0;
32 extern const uas_callbacks_t plugin_cbs;
38 uas_capability_e capability;
39 } uam_sensor_plugin_info_t;
41 uam_sensor_plugin_info_t* plugins[UAS_PLUGIN_ID_MAX];
43 static gboolean __add_plugin(void *handle, uas_module_t *module)
46 uas_api_t *api = NULL;
47 uam_sensor_plugin_info_t *plugin;
49 UAM_DBG("Plugin [id: %d, name: %s, version: %s]",
50 module->id, module->name, module->version);
52 if (UAS_PLUGIN_ID_MAX <= module->id ||
53 UAS_PLUGIN_ID_BLE > module->id) {
54 UAM_ERR("Unknown Id %d for %s", module->id, module->name);
58 if (NULL != plugins[module->id]) {
59 UAM_ERR("Plugin %s already added",
60 plugins[module->id]->module->name);
64 if (g_str_equal(module->version, UAM_VERSION) == FALSE) {
65 UAM_ERR("Version (%s) mismatch for %s",
66 module->version, module->name);
70 plugin = g_try_new0(uam_sensor_plugin_info_t, 1);
72 UAM_ERR("Memory allocation failed");
75 if (NULL == module->init) {
76 UAM_ERR("module->init is NULL");
83 UAM_ERR("API returned is NULL");
88 plugin->handle = handle;
89 plugin->module = module;
92 plugins[module->id] = plugin;
98 static int __load_plugin(const char *path, const char *name, const char *symbol)
103 uas_module_t *module;
105 retv_if(NULL == path, UAM_ERROR_INVALID_PARAMETER);
106 retv_if(NULL == name, UAM_ERROR_INVALID_PARAMETER);
107 retv_if(NULL == symbol, UAM_ERROR_INVALID_PARAMETER);
109 filename = g_build_filename(path, name, NULL);
110 UAM_DBG("Loading [%s]", filename);
112 handle = dlopen(filename, RTLD_NOW);
114 if (handle == NULL) {
115 UAM_ERR("Can't load plugin %s", dlerror());
116 return UAM_ERROR_INTERNAL;
119 module = (uas_module_t *)dlsym(handle, symbol);
120 if (module == NULL) {
121 UAM_ERR("Can't load plugin module: %s", dlerror());
123 return UAM_ERROR_INTERNAL;
126 if (FALSE == __add_plugin(handle, module)) {
127 UAM_ERR("Can't add plugin module");
129 return UAM_ERROR_INTERNAL;
133 return UAM_ERROR_NONE;
136 static int __load_sensor_plugins(void)
141 const char *filename;
142 int ret = UAM_ERROR_INTERNAL;
144 retv_if(0 == strlen(SENSOR_PLUGIN_DIR), UAM_ERROR_INVALID_PARAMETER);
146 UAM_DBG("Loading plugins from %s", SENSOR_PLUGIN_DIR);
148 dir = g_dir_open(SENSOR_PLUGIN_DIR, 0, NULL);
150 UAM_ERR("Unable to open directory");
151 return UAM_ERROR_INTERNAL;
154 while ((filename = g_dir_read_name(dir)) != NULL) {
156 if (g_str_has_suffix(filename, ".so") == FALSE)
159 /* If atleast one plugin is loaded, return value is UAM_ERROR_NONE */
160 if (UAM_ERROR_NONE == __load_plugin(
161 SENSOR_PLUGIN_DIR, filename, "uas_module"))
162 ret = UAM_ERROR_NONE;
172 static int __init_sensor_plugins(void)
175 int ret = UAM_ERROR_INTERNAL;
178 retv_if(UAM_ERROR_NONE != __load_sensor_plugins(), UAM_ERROR_INTERNAL);
180 /* Initialize loaded sensor plugins */
181 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
182 uam_sensor_plugin_info_t *plugin = plugins[id];
186 if (!plugin || !plugin->api) {
187 UAM_WARN("Plugin with ID: %s is NULL", _uam_get_sensor_str(id));
191 status = plugin->api->init(&plugin_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 sensor = _pm_util_uas_plugin_id_to_sensor_bitmask(id);
203 available_sensors |= sensor;
205 if (plugin->capability == UAS_SUPPORT_USER)
206 user_sensors |= sensor;
208 env_sensors |= sensor;
210 /* If atleast one sensor init is success, return success */
211 ret = UAM_ERROR_NONE;
218 static void __deinit_sensor_plugins(void)
223 /* Deinitialize and unload sensor plugins */
224 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
225 uam_sensor_plugin_info_t *plugin = plugins[id];
230 if (plugin->api && plugin->api->deinit)
231 plugin->api->deinit();
233 if (plugin->module && plugin->module->deinit)
234 plugin->module->deinit();
237 dlclose(plugin->handle);
243 available_sensors = 0;
249 static void __uas_device_list_free(int count, uas_device_info_t *devices)
255 for (i = 0; i < count; i++) {
256 uas_device_info_t *device = &(devices[i]);
258 g_free(device->device_id);
260 for (j = 0; j < device->num_addr; j++)
261 g_free(device->addr_list[j].address);
263 g_free(device->addr_list);
271 static int __get_uas_error_code(int error)
274 case UAS_STATUS_SUCCESS: /* 0x00 */
275 return UAM_ERROR_NONE;
276 case UAS_STATUS_FAIL: /* 0x01 */
277 return UAM_ERROR_INTERNAL;
278 case UAS_STATUS_NOT_READY: /* 0x02 */
279 return UAM_ERROR_NOT_INITIALIZED;
280 case UAS_STATUS_NOMEM: /* 0x03 */
281 return UAM_ERROR_OUT_OF_MEMORY;
282 case UAS_STATUS_BUSY: /* 0x04 */
283 return UAM_ERROR_RESOURCE_BUSY;
284 case UAS_STATUS_ALREADY_DONE: /* 0x05 */
285 return UAM_ERROR_ALREADY_DONE;
286 case UAS_STATUS_UNSUPPORTED: /* 0x06 */
287 return UAM_ERROR_NOT_SUPPORTED;
289 return UAM_ERROR_INTERNAL;
293 /* Only unique devices in list.
294 * Time complexity is n^2. Any other approach? */
295 static uas_device_info_t *__get_uas_device_list(int id, GSList *devices, int *num_devices)
298 uam_db_device_info_t *dev;
299 uam_db_device_info_t *dev1;
300 uas_device_info_t *uas_dev;
301 uas_device_info_t *dev_list;
304 GSList *unique_dev = NULL;
308 unsigned int tech_type = _pm_util_uas_plugin_id_to_tech_type(id);
309 retv_if(UAM_TECH_TYPE_NONE == tech_type, NULL);
310 retv_if(NULL == devices, NULL);
311 retv_if(NULL == num_devices, NULL);
313 for (l = devices; l; l = g_slist_next(l)) {
315 if (!dev || !(dev->supported_techs & tech_type))
318 gboolean unique = TRUE;
319 for (l1 = unique_dev; l1; l1 = g_slist_next(l1)) {
321 if (!dev1 || g_strcmp0(dev->device_id, dev1->device_id))
329 unique_dev = g_slist_prepend(unique_dev, dev);
334 dev_list = g_new0(uas_device_info_t, len);
336 for (l = unique_dev; l; l = g_slist_next(l)) {
338 uas_dev = &(dev_list[count]);
342 _pm_util_uam_db_dev_to_uas_dev(tech_type, dev, &uas_dev);
343 uas_dev->supported_techs = dev->supported_techs;
346 UAM_INFO("%d device present in device list for tech %d", count, tech_type);
348 *num_devices = count;
349 g_slist_free(unique_dev);
354 int _uam_pm_init(void)
359 ret = __init_sensor_plugins();
360 if (UAM_ERROR_NONE != ret)
364 return UAM_ERROR_NONE;
367 void _uam_pm_deinit(void)
371 __deinit_sensor_plugins();
376 unsigned int _uam_pm_get_avaliable_sensors(void)
378 UAM_DBG("Available sensors: 0x%8.8X", available_sensors);
379 return available_sensors;
382 unsigned int _uam_pm_get_user_sensors(void)
384 UAM_DBG("User sensors: 0x%8.8X", user_sensors);
388 unsigned int _uam_pm_get_env_sensors(void)
390 UAM_DBG("Env sensors: 0x%8.8X", env_sensors);
394 gboolean _uam_pm_is_sensor_ready(unsigned int sensor_bitmask)
399 uam_sensor_plugin_info_t *plugin;
401 id = _pm_util_sensor_bitmask_to_plugin_id(sensor_bitmask);
402 retv_if(UAS_PLUGIN_ID_MAX <= id, FALSE);
404 plugin = plugins[id];
405 retv_if(!plugin || !plugin->api, FALSE);
407 if (UAS_STATUS_SUCCESS != plugin->api->get_state(&state))
408 state = UAS_STATE_NOT_READY;
410 UAM_DBG("Sensor: 0x%8.8X, State: %d", sensor_bitmask, state);
413 return (UAS_STATE_READY == state ? TRUE : FALSE);
416 int _uam_pm_register_device(int user_id, const uam_device_info_s *dev)
421 int ret = UAM_ERROR_NONE;
422 uam_sensor_plugin_info_t *plugin;
423 uas_device_info_t *device = NULL;
425 retv_if(NULL == dev, UAM_ERROR_INVALID_PARAMETER);
427 id = _pm_util_uam_tech_type_to_plugin_id(dev->type);
428 retv_if(UAS_PLUGIN_ID_MAX <= id, UAM_ERROR_INVALID_PARAMETER);
430 plugin = plugins[id];
431 retv_if(!plugin || !plugin->api, UAM_ERROR_NOT_SUPPORTED);
432 retv_if(UAS_SUPPORT_USER != plugin->capability, UAM_ERROR_NOT_SUPPORTED);
434 device = _pm_util_uam_dev_info_to_uas_dev_info(dev);
435 retv_if(NULL == device, UAM_ERROR_INTERNAL);
437 device->user_id = user_id;
439 ret = plugin->api->add_device(device);
441 if (UAS_STATUS_SUCCESS != ret)
442 UAM_ERR("plugin->add_device() failed");
444 _pm_util_uas_device_info_free(device);
447 return __get_uas_error_code(ret);
450 int _uam_pm_unregister_device(int user_id, const uam_device_info_s *dev)
454 uam_sensor_plugin_info_t *plugin;
455 uas_device_info_t *device = NULL;
458 retv_if(NULL == dev, UAM_ERROR_INVALID_PARAMETER);
460 id = _pm_util_uam_tech_type_to_plugin_id(dev->type);
461 retv_if(UAS_PLUGIN_ID_MAX <= id, UAM_ERROR_INVALID_PARAMETER);
463 plugin = plugins[id];
464 retv_if(!plugin || !plugin->api, UAM_ERROR_NOT_SUPPORTED);
465 retv_if(UAS_SUPPORT_USER != plugin->capability, UAM_ERROR_NOT_SUPPORTED);
467 device = _pm_util_uam_dev_info_to_uas_dev_info(dev);
468 retv_if(NULL == device, UAM_ERROR_INTERNAL);
469 device->user_id = user_id;
471 ret = plugin->api->remove_device(device);
473 if (UAS_STATUS_SUCCESS != ret && UAS_STATUS_ALREADY_DONE != ret)
474 UAM_ERR("plugin->remove_device() failed");
476 _pm_util_uas_device_info_free(device);
479 return UAM_ERROR_NONE;
482 int _uam_pm_set_registered_devices(GSList *devices, unsigned int bitmask)
487 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
488 uas_device_info_t *dev_list = NULL;
490 uam_sensor_plugin_info_t *plugin = plugins[id];
491 unsigned int sensor = _pm_util_uas_plugin_id_to_sensor_bitmask(id);
493 if (!(sensor & bitmask))
496 if (!plugin || !plugin->api || !plugin->api->set_registered_devices)
499 if (UAS_SUPPORT_USER != plugin->capability)
502 dev_list = __get_uas_device_list(id, devices, &num_devices);
504 UAM_INFO("No devices for Plugin %d", id);
508 UAM_INFO("set registered devices");
509 if (UAS_STATUS_SUCCESS != plugin->api->set_registered_devices(
510 num_devices, dev_list))
511 UAM_ERR("plugin->set_registered_devices() failed for %d", id);
513 __uas_device_list_free(num_devices, dev_list);
517 return UAM_ERROR_NONE;
520 int _uam_pm_start_detection(unsigned int detection_mode, unsigned int bitmask)
525 int scan_mode = UAS_SCAN_MODE_LOW_LATENCY;
526 extern uam_vendor_plugin_info_t* vendor_plugin;
527 int ret = UAM_ERROR_INTERNAL;
528 uas_detection_type_e type;
530 switch (detection_mode) {
531 case UAM_DETECT_PRESENCE:
534 case UAM_DETECT_ABSENCE:
537 case UAM_DETECT_LOCATION:
541 type = UAS_PRESENCE | UAS_ABSENCE;
544 if (vendor_plugin && vendor_plugin->api)
545 vendor_plugin->api->get_scan_level(&scan_mode);
547 UAM_ERR("vendor plugin not INITIALISED");
549 UAM_INFO("The scan_level is [%d]", scan_mode);
551 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
552 uam_sensor_plugin_info_t *plugin = plugins[id];
553 unsigned int sensor = _pm_util_uas_plugin_id_to_sensor_bitmask(id);
555 if (!(sensor & bitmask))
558 if (!plugin || !plugin->api)
561 status = plugin->api->start_detection(type, scan_mode);
563 if (UAS_STATUS_SUCCESS != status && UAS_STATUS_ALREADY_DONE != status) {
564 UAM_ERR("plugin->start_detection(%d) failed for %d", type, id);
568 /* Result success if detection started for atleast 1 of the sensor */
569 ret = UAM_ERROR_NONE;
576 int _uam_pm_stop_detection(unsigned int detection_mode, unsigned int bitmask)
581 int ret = UAM_ERROR_INTERNAL;
582 uas_detection_type_e type;
584 switch (detection_mode) {
585 case UAM_DETECT_PRESENCE:
588 case UAM_DETECT_ABSENCE:
591 case UAM_DETECT_LOCATION:
595 type = UAS_PRESENCE | UAS_ABSENCE;
598 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
599 uam_sensor_plugin_info_t *plugin = plugins[id];
600 unsigned int sensor = _pm_util_uas_plugin_id_to_sensor_bitmask(id);
602 if (!(sensor & bitmask))
605 if (!plugin || !plugin->api)
608 status = plugin->api->stop_detection(type);
610 if (UAS_STATUS_SUCCESS != status && UAS_STATUS_ALREADY_DONE != status) {
611 UAM_ERR("plugin->stop_detection(%d) failed for %d", type, id);
615 /* Result success if detection stopped for atleast 1 of the sensor */
616 ret = UAM_ERROR_NONE;
623 int _uam_pm_set_low_power_mode(unsigned int bitmask, gboolean mode)
628 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
629 uam_sensor_plugin_info_t *plugin = plugins[id];
630 unsigned int sensor = _pm_util_uas_plugin_id_to_sensor_bitmask(id);
632 if (!(sensor & bitmask))
635 if (!plugin || !plugin->api || !plugin->api->set_low_power_mode)
638 if (UAS_STATUS_SUCCESS !=
639 plugin->api->set_low_power_mode(mode ? 1 : 0))
640 UAM_ERR("plugin->set_low_power_mode() failed for %d", id);
644 return UAM_ERROR_NONE;
647 int _uam_pm_set_detection_window(unsigned int detection_window)
651 int ret = UAM_ERROR_INTERNAL;
653 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
654 uam_sensor_plugin_info_t *plugin = plugins[id];
656 if (!plugin || !plugin->api || !plugin->api->set_detection_window)
659 if (UAS_STATUS_SUCCESS != plugin->api->set_detection_window(detection_window)) {
660 UAM_ERR("plugin->set_detection_window() failed");
664 /* Result success if detection params set for atleast 1 of the sensors */
665 ret = UAM_ERROR_NONE;
672 int _uam_pm_set_detection_threshold(unsigned int sensor,
673 int presence_threshold, int absence_threshold)
677 uam_sensor_plugin_info_t *plugin;
679 id = _pm_util_sensor_bitmask_to_plugin_id(sensor);
680 retv_if(UAS_PLUGIN_ID_MAX <= id, UAM_ERROR_INVALID_PARAMETER);
682 plugin = plugins[id];
683 retv_if(!plugin || !plugin->api, UAM_ERROR_NOT_SUPPORTED);
685 if (UAS_STATUS_SUCCESS != plugin->api->set_detection_threshold(
686 presence_threshold, absence_threshold)) {
687 UAM_ERR("plugin->set_detection_threshold() failed");
688 return UAM_ERROR_INTERNAL;
692 return UAM_ERROR_NONE;
695 int _uam_pm_start_active_device_scan(unsigned int* bitmask, int detection_period)
700 int ret = UAM_ERROR_INTERNAL;
702 unsigned int scanning_sensor = 0;
704 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
705 uam_sensor_plugin_info_t *plugin = plugins[id];
706 unsigned int sensor = _pm_util_uas_plugin_id_to_sensor_bitmask(id);
708 if (!(sensor & (*bitmask)))
711 if (!plugin || !plugin->api || !plugin->api->scan_active_devices)
714 status = plugin->api->scan_active_devices(detection_period);
716 if (UAS_STATUS_SUCCESS != status && UAS_STATUS_ALREADY_DONE != status) {
717 UAM_ERR("plugin->search_active_devices(%d) failed for %d", detection_period, id);
721 scanning_sensor |= sensor;
722 /* Result success if scanning started for atleast 1 of the sensor */
723 ret = UAM_ERROR_NONE;
726 (*bitmask) &= scanning_sensor;
732 int _uam_pm_stop_active_device_scan(unsigned int bitmask)
737 int ret = UAM_ERROR_INTERNAL;
739 for (id = UAS_PLUGIN_ID_BLE; id < UAS_PLUGIN_ID_MAX; id++) {
740 uam_sensor_plugin_info_t *plugin = plugins[id];
741 unsigned int sensor = _pm_util_uas_plugin_id_to_sensor_bitmask(id);
743 if (!(sensor & bitmask))
746 if (!plugin || !plugin->api || !plugin->api->cancel_active_device_scan)
749 status = plugin->api->cancel_active_device_scan();
751 if (UAS_STATUS_SUCCESS != status && UAS_STATUS_ALREADY_DONE != status) {
752 UAM_ERR("plugin->stop_search_active_devices() failed for %d", id);
756 ret = UAM_ERROR_NONE;
763 int _uam_pm_add_ibeacon_adv(unsigned int adv_len, const char *iadv)
768 int ret = UAM_ERROR_INTERNAL;
770 id = UAS_PLUGIN_ID_BLE;
771 uam_sensor_plugin_info_t *plugin = plugins[id];
773 if (!plugin || !plugin->api || !plugin->api->add_ibeacon_adv) {
774 ret = UAM_ERROR_NOT_SUPPORTED;
778 status = plugin->api->add_ibeacon_adv(adv_len, iadv);
779 if (UAS_STATUS_SUCCESS != status && UAS_STATUS_ALREADY_DONE != status) {
780 UAM_ERR("plugin->add_ibeacon_adv failed for %d", id);
783 ret = UAM_ERROR_NONE;