static void load_devices(struct btd_adapter *adapter)
{
	char dirname[PATH_MAX];
	GSList *keys = NULL;
	GSList *ltks = NULL;
	GSList *irks = NULL;
	GSList *params = NULL;
	GSList *added_devices = NULL;
	DIR *dir;
	struct dirent *entry;

	snprintf(dirname, PATH_MAX, STORAGEDIR "/%s",
					btd_adapter_get_storage_dir(adapter));

	dir = opendir(dirname);
	if (!dir) {
		btd_error(adapter->dev_id,
				"Unable to open adapter storage directory: %s",
								dirname);
		return;
	}

	while ((entry = readdir(dir)) != NULL) {
		struct btd_device *device;
		char filename[PATH_MAX];
		GKeyFile *key_file;
		struct link_key_info *key_info;
		struct smp_ltk_info *ltk_info;
		struct smp_ltk_info *slave_ltk_info;
		GSList *list;
		struct irk_info *irk_info;
		struct conn_param *param;
		uint8_t bdaddr_type;

		if (entry->d_type == DT_UNKNOWN)
			entry->d_type = util_get_dt(dirname, entry->d_name);

		if (entry->d_type != DT_DIR || bachk(entry->d_name) < 0)
			continue;

		snprintf(filename, PATH_MAX, STORAGEDIR "/%s/%s/info",
					btd_adapter_get_storage_dir(adapter),
					entry->d_name);

		key_file = g_key_file_new();
		g_key_file_load_from_file(key_file, filename, 0, NULL);

		key_info = get_key_info(key_file, entry->d_name);

		bdaddr_type = get_le_addr_type(key_file);

		ltk_info = get_ltk_info(key_file, entry->d_name, bdaddr_type);

		slave_ltk_info = get_slave_ltk_info(key_file, entry->d_name,
								bdaddr_type);

		irk_info = get_irk_info(key_file, entry->d_name, bdaddr_type);

		// If any key for the device is blocked, we discard all.
		if ((key_info && key_info->is_blocked) ||
				(ltk_info && ltk_info->is_blocked) ||
				(slave_ltk_info &&
					slave_ltk_info->is_blocked) ||
				(irk_info && irk_info->is_blocked)) {

			if (key_info) {
				g_free(key_info);
				key_info = NULL;
			}

			if (ltk_info) {
				g_free(ltk_info);
				ltk_info = NULL;
			}

			if (slave_ltk_info) {
				g_free(slave_ltk_info);
				slave_ltk_info = NULL;
			}

			if (irk_info) {
				g_free(irk_info);
				irk_info = NULL;
			}

			goto free;
		}

		if (key_info)
			keys = g_slist_append(keys, key_info);

		if (ltk_info)
			ltks = g_slist_append(ltks, ltk_info);

		if (slave_ltk_info)
			ltks = g_slist_append(ltks, slave_ltk_info);

		if (irk_info)
			irks = g_slist_append(irks, irk_info);

		param = get_conn_param(key_file, entry->d_name, bdaddr_type);
		if (param)
			params = g_slist_append(params, param);

		list = g_slist_find_custom(adapter->devices, entry->d_name,
							device_address_cmp);
		if (list) {
			device = list->data;
			goto device_exist;
		}

		device = device_create_from_storage(adapter, entry->d_name,
							key_file);
		if (!device)
			goto free;

		btd_device_set_temporary(device, false);
		adapter->devices = g_slist_append(adapter->devices, device);

		/* TODO: register services from pre-loaded list of primaries */

		added_devices = g_slist_append(added_devices, device);

device_exist:
		if (key_info) {
			device_set_paired(device, BDADDR_BREDR);
			device_set_bonded(device, BDADDR_BREDR);
		}

		if (ltk_info || slave_ltk_info) {
			device_set_paired(device, bdaddr_type);
			device_set_bonded(device, bdaddr_type);

			if (ltk_info)
				device_set_ltk_enc_size(device,
							ltk_info->enc_size);
			else if (slave_ltk_info)
				device_set_ltk_enc_size(device,
						slave_ltk_info->enc_size);
		}

free:
		g_key_file_free(key_file);
	}

	closedir(dir);

	load_link_keys(adapter, keys, btd_opts.debug_keys);
	g_slist_free_full(keys, g_free);

	load_ltks(adapter, ltks);
	g_slist_free_full(ltks, g_free);
	load_irks(adapter, irks);
	g_slist_free_full(irks, g_free);
	load_conn_params(adapter, params);
	g_slist_free_full(params, g_free);

	g_slist_free_full(added_devices, probe_devices);
}