diff --git a/src/ble/ctrlm_ble_network.cpp b/src/ble/ctrlm_ble_network.cpp index f196876..25abbe1 100644 --- a/src/ble/ctrlm_ble_network.cpp +++ b/src/ble/ctrlm_ble_network.cpp @@ -56,6 +56,9 @@ using namespace std; #define CTRLM_BLE_UPGRADE_CONTINUE_TIMEOUT (MINUTE_IN_MILLISECONDS * 5) // 5 minutes #define CTRLM_BLE_UPGRADE_PAUSE_TIMEOUT (MINUTE_IN_MILLISECONDS * 2) // 2 minutes +#define CTRLM_VENDOR_BLE_REMOTE_WHITELIST_FILE "/etc/vendor/input/ble_remote_whitelist.json" +#define CTRLM_VENDOR_BLE_NETWORK_TIMEOUTS_FILE "/etc/vendor/input/ble_network_timeouts.json" + typedef struct { guint upgrade_controllers_timer_tag; guint upgrade_pause_timer_tag; @@ -130,6 +133,78 @@ static int ctrlm_ble_network_factory(vendor_network_opts_t *opts, json_t *json_c } } + // If the vendor supplied model list is provided, use it. Otherwise use the default model list. + const char *vendor_model_file = CTRLM_VENDOR_BLE_REMOTE_WHITELIST_FILE; + + if(ctrlm_file_exists(vendor_model_file)) { + XLOGD_INFO("Using vendor model file: %s", vendor_model_file); + + json_t *json_obj_vendor_models = json_load_file(vendor_model_file, JSON_REJECT_DUPLICATES, NULL); + + if(json_obj_vendor_models == NULL || !json_is_array(json_obj_vendor_models)) { + XLOGD_ERROR("invalid vendor model file format"); + } else { + // Make sure the json_obj_net_ble object is valid + if(json_obj_net_ble == NULL) { // Create a json object + json_obj_net_ble = json_object(); + } + if(json_obj_net_ble == NULL) { + XLOGD_ERROR("invalid BLE network json object"); + } else { // Overwrite the "models" section in the json_obj_net_ble object + int rc = json_object_set_new(json_obj_net_ble, JSON_ARRAY_NAME_NETWORK_BLE_MODELS, json_obj_vendor_models); + if(rc != 0) { + XLOGD_ERROR("failed to set vendor models in BLE network json object"); + } else { + XLOGD_INFO("successfully set vendor models in BLE network json object"); + json_obj_vendor_models = NULL; + } + } + } + if(json_obj_vendor_models != NULL) { + json_decref(json_obj_vendor_models); + json_obj_vendor_models = NULL; + } + } + + // If the vendor supplied timeouts are provided, use them. Otherwise use the default timeouts. + const char *vendor_timeouts_file = CTRLM_VENDOR_BLE_NETWORK_TIMEOUTS_FILE; + + if(ctrlm_file_exists(vendor_timeouts_file)) { + XLOGD_INFO("Using vendor timeouts file: %s", vendor_timeouts_file); + + json_t *json_obj_vendor_timeouts = json_load_file(vendor_timeouts_file, JSON_REJECT_DUPLICATES, NULL); + + if(json_obj_vendor_timeouts == NULL || !json_is_object(json_obj_vendor_timeouts)) { + XLOGD_ERROR("invalid vendor timeouts file format"); + } else { + // Make sure the json_obj_net_ble object is valid + if(json_obj_net_ble == NULL) { // Create a json object + json_obj_net_ble = json_object(); + } + if(json_obj_net_ble == NULL) { + XLOGD_ERROR("invalid BLE network json object"); + } else { // Update the "timeouts" section in the json_obj_net_ble object + int rc = 0; + json_t *obj_timeouts = json_object_get(json_obj_net_ble, JSON_OBJ_NAME_NETWORK_BLE_TIMEOUTS); + if(obj_timeouts == NULL || !json_is_object(obj_timeouts)) { + rc = json_object_set_new(json_obj_net_ble, JSON_OBJ_NAME_NETWORK_BLE_TIMEOUTS, json_obj_vendor_timeouts); + } else { + rc = json_object_update(obj_timeouts, json_obj_vendor_timeouts); + } + if(rc != 0) { + XLOGD_ERROR("failed to update vendor timeouts in BLE network json object"); + } else { + XLOGD_INFO("successfully updated vendor timeouts in BLE network json object"); + json_obj_vendor_timeouts = NULL; + } + } + } + if(json_obj_vendor_timeouts != NULL) { + json_decref(json_obj_vendor_timeouts); + json_obj_vendor_timeouts = NULL; + } + } + // add network if enabled if ( !(opts->ignore_mask & (1 << CTRLM_NETWORK_TYPE_BLUETOOTH_LE)) ) { ctrlm_network_id_t network_id = network_id_get_next(CTRLM_NETWORK_TYPE_BLUETOOTH_LE); diff --git a/src/ble/hal/configsettings/configsettings.cpp b/src/ble/hal/configsettings/configsettings.cpp index 7b69f5f..053e93a 100644 --- a/src/ble/hal/configsettings/configsettings.cpp +++ b/src/ble/hal/configsettings/configsettings.cpp @@ -61,18 +61,31 @@ using namespace std; */ ConfigSettings::TimeOuts ConfigSettings::parseTimeouts(json_t *json) { - TimeOuts timeouts = { 15000, 15000, 60000, 20000, 20000, 65000 }; + TimeOuts timeouts = { + JSON_INT_VALUE_NETWORK_BLE_TIMEOUTS_DISCOVERY, + JSON_INT_VALUE_NETWORK_BLE_TIMEOUTS_PAIR, + JSON_INT_VALUE_NETWORK_BLE_TIMEOUTS_SETUP, + JSON_INT_VALUE_NETWORK_BLE_TIMEOUTS_UNPAIR, + JSON_INT_VALUE_NETWORK_BLE_TIMEOUTS_HIDRAWPOLL, + JSON_INT_VALUE_NETWORK_BLE_TIMEOUTS_HIDRAWLIMIT + }; + + if(json == NULL) { // return default values + return timeouts; + } struct { const char *name; int *storage; + int minValue; + int maxValue; } fields[6] = { - { "discovery", &timeouts.discoveryMSecs }, - { "pair", &timeouts.pairingMSecs }, - { "setup", &timeouts.setupMSecs }, - { "unpair", &timeouts.upairingMSecs }, - { "hidrawPoll", &timeouts.hidrawWaitPollMSecs }, - { "hidrawLimit", &timeouts.hidrawWaitLimitMSecs }, + { "discovery", &timeouts.discoveryMSecs, 0, 600000 }, + { "pair", &timeouts.pairingMSecs, 0, 600000 }, + { "setup", &timeouts.setupMSecs, 0, 600000 }, + { "unpair", &timeouts.upairingMSecs, 0, 600000 }, + { "hidrawPoll", &timeouts.hidrawWaitPollMSecs, 0, 600000 }, + { "hidrawLimit", &timeouts.hidrawWaitLimitMSecs, 0, 600000 }, }; // process the fields @@ -83,7 +96,12 @@ ConfigSettings::TimeOuts ConfigSettings::parseTimeouts(json_t *json) XLOGD_WARN("invalid '%s' field, reverting to default", fields[i].name); } } else { - *(fields[i].storage) = (int)json_integer_value(timeout); + json_int_t value = json_integer_value(timeout); + if(value < fields[i].minValue || value > fields[i].maxValue) { + XLOGD_WARN("'%s' field value %d out of range (%d - %d), using default", fields[i].name, (int)value, fields[i].minValue, fields[i].maxValue); + } else { + *(fields[i].storage) = (int)value; + } XLOGD_DEBUG("'%s' field = %d", fields[i].name, *(fields[i].storage)); } } @@ -123,25 +141,43 @@ std::shared_ptr ConfigSettings::fromJsonObj(json_t *jsonConfig) */ std::shared_ptr ConfigSettings::parseJson(json_t *jsonConfig) { + TimeOuts timeouts; // find the timeout params json_t *timeoutsObj = json_object_get(jsonConfig, "timeouts"); if (!timeoutsObj || !json_is_object(timeoutsObj)) { - XLOGD_ERROR( "missing or invalid 'timeouts' field in config"); - return std::shared_ptr(); + XLOGD_WARN( "missing or invalid 'timeouts' field in config (using defaults)"); + timeouts = parseTimeouts(NULL); + } else { + timeouts = parseTimeouts(timeoutsObj); } - TimeOuts timeouts = parseTimeouts(timeoutsObj); + json_t *obj_network_ble = NULL; - // find the vendor details array json_t *modelArray = json_object_get(jsonConfig, "models"); if (!modelArray || !json_is_array(modelArray)) { - XLOGD_ERROR( "missing or invalid 'models' field in config"); - return std::shared_ptr(); + XLOGD_WARN( "missing or invalid 'models' field in config (using defaults)"); + + obj_network_ble = json_loads(DEFAULT_CONFIG::json(), JSON_DECODE_ANY, NULL); + if (!obj_network_ble || !json_is_object(obj_network_ble)) { + if(!obj_network_ble) { + XLOGD_ERROR("invalid default config buffer"); + } else { + XLOGD_ERROR("default config buffer is not a json object"); + json_decref(obj_network_ble); + } + return std::shared_ptr(); + } + + modelArray = json_object_get(obj_network_ble, "models"); + if((!modelArray || !json_is_array(modelArray))) { + XLOGD_ERROR("missing or invalid 'models' field in default config"); + json_decref(obj_network_ble); + return std::shared_ptr(); + } } size_t array_size = json_array_size(modelArray); - vector models; for (unsigned int i = 0; i < array_size; i++) { @@ -156,6 +192,10 @@ std::shared_ptr ConfigSettings::parseJson(json_t *jsonConfig) } } + if(obj_network_ble != NULL) { + json_decref(obj_network_ble); + } + // finally return the config return std::make_shared(timeouts, std::move(models)); } diff --git a/src/ctrlm_config_default.json b/src/ctrlm_config_default.json index edb2725..8d536a0 100755 --- a/src/ctrlm_config_default.json +++ b/src/ctrlm_config_default.json @@ -223,7 +223,9 @@ "discovery": 15000, "pair": 20000, "setup": 60000, - "unpair": 20000 + "unpair": 20000, + "hidrawPoll": 20000, + "hidrawLimit": 65000 }, "models": [ ]