diff options
Diffstat (limited to 'hcid/dbus-device.c')
| -rw-r--r-- | hcid/dbus-device.c | 1313 | 
1 files changed, 0 insertions, 1313 deletions
| diff --git a/hcid/dbus-device.c b/hcid/dbus-device.c index 050aab69..f3bf47c4 100644 --- a/hcid/dbus-device.c +++ b/hcid/dbus-device.c @@ -27,1316 +27,3 @@  #include <stdio.h>  #include <errno.h> -#include <unistd.h> -#include <sys/socket.h> - -#include <bluetooth/bluetooth.h> -#include <bluetooth/hci.h> -#include <bluetooth/hci_lib.h> - -#include <dbus/dbus.h> - -#include "hcid.h" -#include "dbus.h" - -#include "textfile.h" -#include "oui.h" - -static const char *service_cls[] = { -	"positioning", -	"networking", -	"rendering", -	"capturing", -	"object transfer", -	"audio", -	"telephony", -	"information" -}; - -static const char *computer_minor_cls[] = { -	"uncategorized", -	"desktop", -	"server", -	"laptop", -	"handheld", -	"palm", -	"wearable" -}; - -static char *get_peer_name(const bdaddr_t *local, const bdaddr_t *peer) -{ -	char filename[PATH_MAX + 1], addr[18]; - -	ba2str(local, addr); -	snprintf(filename, PATH_MAX, "%s/%s/names", STORAGEDIR, addr); - -	ba2str(peer, addr); -	return textfile_get(filename, addr); -} - -static DBusMessage *handle_dev_get_address_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessage *reply; -	char str[18], *str_ptr = str; -	int err; - -	err = get_device_address(dbus_data->dev_id, str, sizeof(str)); -	if (err < 0) -		return error_generic(msg, -err); - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_ptr, -					DBUS_TYPE_INVALID); - -	return reply; -} - -static DBusMessage *handle_dev_get_version_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessage *reply; -	char str[20], *str_ptr = str; -	int err; - -	err = get_device_version(dbus_data->dev_id, str, sizeof(str)); -	if (err < 0) -		return error_generic(msg, -err); - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_ptr, -					DBUS_TYPE_INVALID); - -	return reply; -} - -static DBusMessage *handle_dev_get_revision_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessage *reply; -	char str[64], *str_ptr = str; -	int err; - -	err = get_device_revision(dbus_data->dev_id, str, sizeof(str)); -	if (err < 0) -		return error_generic(msg, -err); - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_ptr, -					DBUS_TYPE_INVALID); - -	return reply; -} - -static DBusMessage *handle_dev_get_manufacturer_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessage *reply; -	char str[64], *str_ptr = str; -	int err; - -	err = get_device_manufacturer(dbus_data->dev_id, str, sizeof(str)); -	if (err < 0) -		return error_generic(msg, -err); - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_ptr, -					DBUS_TYPE_INVALID); - -	return reply; -} - -static DBusMessage *handle_dev_get_company_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessage *reply; -	char str[64], *str_ptr = str; -	int err; - -	err = get_device_company(dbus_data->dev_id, str, sizeof(str)); -	if (err < 0) -		return error_generic(msg, -err); - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_ptr, -					DBUS_TYPE_INVALID); - -	return reply; -} - -static DBusMessage *handle_dev_get_features_req(DBusMessage *msg, void *data) -{ -	DBusMessage *reply; -	DBusMessageIter iter; -	DBusMessageIter array_iter; - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	dbus_message_iter_init_append(reply, &iter); - -	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, -				DBUS_TYPE_STRING_AS_STRING, &array_iter); - -	dbus_message_iter_close_container(&iter, &array_iter); - -	return reply; -} - -static DBusMessage *handle_dev_get_mode_req(DBusMessage *msg, void *data) -{ -	const struct hci_dbus_data *dbus_data = data; -	DBusMessage *reply = NULL; -	const uint8_t hci_mode = dbus_data->mode; -	const char *scan_mode; - -	switch (hci_mode) { -	case SCAN_DISABLED: -		scan_mode = MODE_OFF; -		break; -	case SCAN_PAGE: -		scan_mode = MODE_CONNECTABLE; -		break; -	case (SCAN_PAGE | SCAN_INQUIRY): -		scan_mode = MODE_DISCOVERABLE; -		break; -	case SCAN_INQUIRY: -	/* inquiry scan mode is not handled, return unknown */ -	default: -		/* reserved */ -		scan_mode = MODE_UNKNOWN; -	} - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &scan_mode, -					DBUS_TYPE_INVALID); - -	return reply; -} - -static DBusMessage *handle_dev_set_mode_req(DBusMessage *msg, void *data) -{ -	const struct hci_dbus_data *dbus_data = data; -	DBusMessage *reply; -	const char* scan_mode; -	uint8_t hci_mode; -	const uint8_t current_mode = dbus_data->mode; -	int dd; - -	dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &scan_mode, -							DBUS_TYPE_INVALID); - -	if (!scan_mode) -		return bluez_new_failure_msg(msg, BLUEZ_EDBUS_WRONG_PARAM); - -	if (strcasecmp(MODE_OFF, scan_mode) == 0) -		hci_mode = SCAN_DISABLED; -	else if (strcasecmp(MODE_CONNECTABLE, scan_mode) == 0) -		hci_mode = SCAN_PAGE; -	else if (strcasecmp(MODE_DISCOVERABLE, scan_mode) == 0) -		hci_mode = (SCAN_PAGE | SCAN_INQUIRY); -	else -		return bluez_new_failure_msg(msg, BLUEZ_EDBUS_WRONG_PARAM); - -	dd = hci_open_dev(dbus_data->dev_id); -	if (dd < 0) -		return error_no_such_device(msg); - -	/* Check if the new requested mode is different from the current */ -	if (current_mode != hci_mode) { -		struct hci_request rq; -		uint8_t status = 0; - -		memset(&rq, 0, sizeof(rq)); -		rq.ogf    = OGF_HOST_CTL; -		rq.ocf    = OCF_WRITE_SCAN_ENABLE; -		rq.cparam = &hci_mode; -		rq.clen   = sizeof(hci_mode); -		rq.rparam = &status; -		rq.rlen   = sizeof(status); - -		if (hci_send_req(dd, &rq, 100) < 0) { -			syslog(LOG_ERR, "Sending write scan enable command failed: %s (%d)", -							strerror(errno), errno); -			hci_close_dev(dd); -			return bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET | errno); -		} - -		if (status) { -			syslog(LOG_ERR, "Setting scan enable failed with status 0x%02x", status); -			hci_close_dev(dd); -			return bluez_new_failure_msg(msg, BLUEZ_EBT_OFFSET | status); -		} -	} - -	hci_close_dev(dd); - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	return reply; -} - -static DBusMessage *handle_dev_get_discoverable_to_req(DBusMessage *msg, void *data) -{ -	const struct hci_dbus_data *dbus_data = data; -	DBusMessage *reply; - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	dbus_message_append_args(reply, DBUS_TYPE_UINT32, &dbus_data->discoverable_timeout, -					DBUS_TYPE_INVALID); - -	return reply; -} - -static DBusMessage *handle_dev_set_discoverable_to_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessage *reply; -	DBusMessageIter iter; -	uint32_t timeout; - -	dbus_message_iter_init(msg, &iter); -	dbus_message_iter_get_basic(&iter, &timeout); - -	dbus_data->discoverable_timeout = timeout; - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	return reply; -} - -static DBusMessage *handle_dev_is_connectable_req(DBusMessage *msg, void *data) -{ -	const struct hci_dbus_data *dbus_data = data; -	DBusMessage *reply; -	const uint8_t hci_mode = dbus_data->mode; -	dbus_bool_t connectable = FALSE; - -	if (hci_mode & SCAN_PAGE) -		connectable = TRUE; - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &connectable, -					DBUS_TYPE_INVALID); - -	return reply; -} - -static DBusMessage *handle_dev_is_discoverable_req(DBusMessage *msg, void *data) -{ -	const struct hci_dbus_data *dbus_data = data; -	DBusMessage *reply; -	const uint8_t hci_mode = dbus_data->mode; -	dbus_bool_t discoverable = FALSE; - -	if (hci_mode & SCAN_INQUIRY) -		discoverable = TRUE; - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &discoverable, -					DBUS_TYPE_INVALID); - -	return reply; -} - -static DBusMessage *handle_dev_get_major_class_req(DBusMessage *msg, void *data) -{ -	DBusMessage *reply; -	const char *str_ptr = "computer"; - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	/*FIXME: Check the real device major class */ -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_ptr, -					DBUS_TYPE_INVALID); - -	return reply; -} - -static DBusMessage *handle_dev_get_minor_class_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessage *reply; -	const char *str_ptr = ""; -	uint8_t cls[3]; -	uint8_t minor_class; -	int dd; - -	dd = hci_open_dev(dbus_data->dev_id); -	if (dd < 0) -		return error_no_such_device(msg); - -	if (hci_read_class_of_dev(dd, cls, 1000) < 0) { -		syslog(LOG_ERR, "Can't read class of device on hci%d: %s(%d)", -				dbus_data->dev_id, strerror(errno), errno); -		hci_close_dev(dd); -		return error_generic(msg, -errno); -	} - -	hci_close_dev(dd); - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	/* FIXME: Currently, only computer major class is supported */ -	if ((cls[1] & 0x1f) != 1) -		goto failed; - -	minor_class = cls[0] >> 2; - -	/* Validate computer minor class */ -	if (minor_class > (sizeof(computer_minor_cls) / sizeof(*computer_minor_cls))) -		goto failed; - -	str_ptr = computer_minor_cls[minor_class]; - -failed: -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_ptr, -					DBUS_TYPE_INVALID); - -	return reply; -} - -static DBusMessage *handle_dev_set_minor_class_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusConnection *connection = get_dbus_connection(); -	DBusMessageIter iter; -	DBusMessage *reply, *signal; -	bdaddr_t bdaddr; -	const char *minor; -	uint8_t cls[3]; -	uint32_t dev_class = 0xFFFFFFFF; -	int i, dd; - -	dbus_message_iter_init(msg, &iter); -	dbus_message_iter_get_basic(&iter, &minor); - -	if (!minor) -		return bluez_new_failure_msg(msg, BLUEZ_EDBUS_WRONG_PARAM); - -	/* FIXME: currently, only computer minor classes are allowed */ -	for (i = 0; i < sizeof(computer_minor_cls) / sizeof(*computer_minor_cls); i++) -		if (!strcasecmp(minor, computer_minor_cls[i])) { -			/* Remove the format type */ -			dev_class = i << 2; -			break; -		} - -	/* Check if it's a valid minor class */ -	if (dev_class == 0xFFFFFFFF) -		return bluez_new_failure_msg(msg, BLUEZ_EDBUS_WRONG_PARAM); - -	dd = hci_open_dev(dbus_data->dev_id); -	if (dd < 0) { -		syslog(LOG_ERR, "HCI device open failed: hci%d", dbus_data->dev_id); -		return bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_ENODEV); -	} - -	if (hci_read_class_of_dev(dd, cls, 1000) < 0) { -		syslog(LOG_ERR, "Can't read class of device on hci%d: %s(%d)", -				dbus_data->dev_id, strerror(errno), errno); -		reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET | errno); -		goto failed; -	} - -	dev_class |= (cls[2] << 16) | (cls[1] << 8); - -	cls[2] = 0x00;	/* no service classes */ -	cls[1] = 0x01;	/* major class computer */ -	cls[0] = (dev_class & 0xff); - -	hci_devba(dbus_data->dev_id, &bdaddr); - -	write_local_class(&bdaddr, cls); - -	if (hci_write_class_of_dev(dd, dev_class, 2000) < 0) { -		syslog(LOG_ERR, "Can't write class of device on hci%d: %s(%d)", -				dbus_data->dev_id, strerror(errno), errno); -		reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET | errno); -		goto failed; -	} - -	signal = dev_signal_factory(dbus_data->dev_id, DEV_SIG_MINOR_CLASS_CHANGED, -						DBUS_TYPE_STRING, &minor, -						DBUS_TYPE_INVALID); -	if (signal) { -		dbus_connection_send(connection, signal, NULL); -		dbus_connection_flush(connection); -		dbus_message_unref(signal); -	} - -	reply = dbus_message_new_method_return(msg); - -failed: -	hci_close_dev(dd); - -	return reply; -} - -static DBusMessage *handle_dev_get_service_classes_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessage *reply; -	DBusMessageIter iter; -	DBusMessageIter array_iter; -	const char *str_ptr; -	uint8_t cls[3]; -	int dd, i; - -	dd = hci_open_dev(dbus_data->dev_id); -	if (dd < 0) { -		syslog(LOG_ERR, "HCI device open failed: hci%d", dbus_data->dev_id); -		return bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_ENODEV); -	} - -	if (hci_read_class_of_dev(dd, cls, 1000) < 0) { -		syslog(LOG_ERR, "Can't read class of device on hci%d: %s(%d)", -				dbus_data->dev_id, strerror(errno), errno); -		hci_close_dev(dd); -		return bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET | errno); -	} - -	reply = dbus_message_new_method_return(msg); - -	dbus_message_iter_init_append(reply, &iter); - -	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, -				DBUS_TYPE_STRING_AS_STRING, &array_iter); - -	for (i = 0; i < (sizeof(service_cls) / sizeof(*service_cls)); i++) { -		if (cls[2] & (1 << i)) { -			str_ptr = service_cls[i]; -			dbus_message_iter_append_basic(&array_iter, -						DBUS_TYPE_STRING, &str_ptr); -		} -	} - -	dbus_message_iter_close_container(&iter, &array_iter); - -	hci_close_dev(dd); - -	return reply; -} - -static DBusMessage *handle_dev_get_name_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessage *reply; -	char str[249], *str_ptr = str; -	int err; - -	err = get_device_name(dbus_data->dev_id, str, sizeof(str)); -	if (err < 0) -		return error_generic(msg, -err); - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_ptr, -					DBUS_TYPE_INVALID); - -	return reply; -} - -static DBusMessage *handle_dev_set_name_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessageIter iter; -	DBusMessage *reply; -	bdaddr_t bdaddr; -	char *str_ptr; -	int err; - -	dbus_message_iter_init(msg, &iter); -	dbus_message_iter_get_basic(&iter, &str_ptr); - -	if (strlen(str_ptr) == 0) { -		syslog(LOG_ERR, "Name change failed: Invalid parameter"); -		return bluez_new_failure_msg(msg, BLUEZ_EDBUS_WRONG_PARAM); -	} - -	hci_devba(dbus_data->dev_id, &bdaddr); - -	write_local_name(&bdaddr, str_ptr); - -	err = set_device_name(dbus_data->dev_id, str_ptr); -	if (err < 0) -		return error_generic(msg, -err); - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	return reply; -} - -static DBusMessage *handle_dev_get_remote_version_req(DBusMessage *msg, void *data) -{ -	/*FIXME: */ -	return bluez_new_failure_msg(msg, BLUEZ_EDBUS_NOT_IMPLEMENTED); -} - -static DBusMessage *handle_dev_get_remote_revision_req(DBusMessage *msg, void *data) -{ -	/*FIXME: */ -	return bluez_new_failure_msg(msg, BLUEZ_EDBUS_NOT_IMPLEMENTED); -} - -static DBusMessage *handle_dev_get_remote_manufacturer_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessageIter iter; -	DBusMessage *reply; -	char filename[PATH_MAX + 1]; -	char addr[18], *addr_ptr, *str; -	int compid; - -	get_device_address(dbus_data->dev_id, addr, sizeof(addr)); - -	snprintf(filename, PATH_MAX, "%s/%s/manufacturers", STORAGEDIR, addr); - -	dbus_message_iter_init(msg, &iter); -	dbus_message_iter_get_basic(&iter, &addr_ptr); - -	str = textfile_get(filename, addr_ptr); -	if (!str) -		return bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET | ENXIO); - -	compid = atoi(str); - -	free(str); - -	str = bt_compidtostr(compid); - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &str, -					DBUS_TYPE_INVALID); - -	return reply; -} - -static DBusMessage *handle_dev_get_remote_company_req(DBusMessage *msg, void *data) -{ -	DBusMessage *reply; -	bdaddr_t bdaddr; -	char oui[9], *str_bdaddr, *tmp; - -	dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &str_bdaddr, -							DBUS_TYPE_INVALID); - - -	str2ba(str_bdaddr, &bdaddr); -	ba2oui(&bdaddr, oui); - -	tmp = ouitocomp(oui); -	if (!tmp) -		return bluez_new_failure_msg(msg, BLUEZ_EDBUS_RECORD_NOT_FOUND); - -	reply = dbus_message_new_method_return(msg); -	if (!reply) { -		reply = error_out_of_memory(msg); -		goto done; -	} - -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &tmp, -					DBUS_TYPE_INVALID); - -done: -	free(tmp); - -	return reply; -} - -static DBusMessage *handle_dev_get_remote_name_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessage *reply = NULL; -	const char *str_bdaddr; -	char *name; -	bdaddr_t bdaddr; -	struct hci_dev_info di; - -	dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &str_bdaddr, -							DBUS_TYPE_INVALID); - -	str2ba(str_bdaddr, &bdaddr); - -	if (hci_devinfo(dbus_data->dev_id, &di) < 0) { -		syslog(LOG_ERR, "Can't get device info"); -		return bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_ENODEV); -	} - -	name = get_peer_name(&di.bdaddr, &bdaddr); -	if (!name) -		return bluez_new_failure_msg(msg, BLUEZ_EDBUS_RECORD_NOT_FOUND); - -	reply = dbus_message_new_method_return(msg); -	if (!reply) { -		reply = error_out_of_memory(msg); -		goto done; -	} - -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &name, -					DBUS_TYPE_INVALID); - -done: -	free(name); - -	return reply; -} - -static DBusMessage *handle_dev_get_remote_alias_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessageIter iter; -	DBusMessage *reply; -	char str[249], *str_ptr = str, *addr_ptr; -	bdaddr_t bdaddr; -	int err; - -	dbus_message_iter_init(msg, &iter); -	dbus_message_iter_get_basic(&iter, &addr_ptr); - -	str2ba(addr_ptr, &bdaddr); - -	err = get_device_alias(dbus_data->dev_id, &bdaddr, str, sizeof(str)); -	if (err < 0) -		return error_generic(msg, -err); - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_ptr, -					DBUS_TYPE_INVALID); - -	return reply; -} - -static DBusMessage *handle_dev_set_remote_alias_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusConnection *connection = get_dbus_connection(); -	DBusMessageIter iter; -	DBusMessage *reply, *signal; -	char *str_ptr, *addr_ptr; -	bdaddr_t bdaddr; -	int err; - -	dbus_message_iter_init(msg, &iter); -	dbus_message_iter_get_basic(&iter, &addr_ptr); -	dbus_message_iter_next(&iter); -	dbus_message_iter_get_basic(&iter, &str_ptr); - -	if (strlen(str_ptr) == 0) { -		syslog(LOG_ERR, "Alias change failed: Invalid parameter"); -		return bluez_new_failure_msg(msg, BLUEZ_EDBUS_WRONG_PARAM); -	} - -	str2ba(addr_ptr, &bdaddr); - -	err = set_device_alias(dbus_data->dev_id, &bdaddr, str_ptr); -	if (err < 0) -		return error_generic(msg, -err); - -	signal = dev_signal_factory(dbus_data->dev_id, DEV_SIG_REMOTE_ALIAS_CHANGED, -						DBUS_TYPE_STRING, &addr_ptr, -						DBUS_TYPE_STRING, &str_ptr, -						DBUS_TYPE_INVALID); -	if (signal) { -		dbus_connection_send(connection, signal, NULL); -		dbus_connection_flush(connection); -		dbus_message_unref(signal); -	} - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return error_out_of_memory(msg); - -	return reply; -} - -static DBusMessage *handle_dev_last_seen_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessageIter iter; -	DBusMessage *reply; -	char filename[PATH_MAX + 1]; -	char addr[18], *addr_ptr, *str; - -	get_device_address(dbus_data->dev_id, addr, sizeof(addr)); - -	snprintf(filename, PATH_MAX, "%s/%s/lastseen", STORAGEDIR, addr); - -	dbus_message_iter_init(msg, &iter); -	dbus_message_iter_get_basic(&iter, &addr_ptr); - -	str = textfile_get(filename, addr_ptr); -	if (!str) -		return bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET | ENXIO); - -	reply = dbus_message_new_method_return(msg); -	if (!reply) { -		reply = error_out_of_memory(msg); -		goto done; -	} - -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &str, -					DBUS_TYPE_INVALID); - -done: -	free(str); - -	return reply; -} - -static DBusMessage *handle_dev_last_used_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessageIter iter; -	DBusMessage *reply; -	char filename[PATH_MAX + 1]; -	char addr[18], *addr_ptr, *str; - -	get_device_address(dbus_data->dev_id, addr, sizeof(addr)); - -	snprintf(filename, PATH_MAX, "%s/%s/lastused", STORAGEDIR, addr); - -	dbus_message_iter_init(msg, &iter); -	dbus_message_iter_get_basic(&iter, &addr_ptr); - -	str = textfile_get(filename, addr_ptr); -	if (!str) -		return bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET | ENXIO); - -	reply = dbus_message_new_method_return(msg); -	if (!reply) { -		reply = error_out_of_memory(msg); -		goto done; -	} - -	dbus_message_append_args(reply, DBUS_TYPE_STRING, &str, -					DBUS_TYPE_INVALID); - -done: -	free(str); - -	return reply; -} - -static DBusMessage *handle_dev_create_bonding_req(DBusMessage *msg, void *data) -{ -	struct hci_request rq; -	auth_requested_cp cp; -	evt_cmd_status rp; -	DBusMessage *reply; -	char *str_bdaddr; -	struct hci_dbus_data *dbus_data = data; -	struct hci_conn_info_req *cr; -	bdaddr_t bdaddr; -	int dd, dev_id; - -	dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &str_bdaddr, -							DBUS_TYPE_INVALID); - -	str2ba(str_bdaddr, &bdaddr); - -	dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); - -	if (dev_id < 0) -		return bluez_new_failure_msg(msg, BLUEZ_EDBUS_CONN_NOT_FOUND); - -	if (dbus_data->dev_id != dev_id) -		return bluez_new_failure_msg(msg, BLUEZ_EDBUS_CONN_NOT_FOUND); - -	dd = hci_open_dev(dev_id); -	if (dd < 0) -		return error_no_such_device(msg); - -	cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); -	if (!cr) { -		reply = bluez_new_failure_msg(msg, BLUEZ_EDBUS_NO_MEM); -		goto failed; -	} - -	bacpy(&cr->bdaddr, &bdaddr); -	cr->type = ACL_LINK; - -	if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { -		reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET + errno); -		goto done; -	} - -	memset(&cp, 0, sizeof(cp)); -	cp.handle = cr->conn_info->handle; - -	memset(&rq, 0, sizeof(rq)); -	rq.ogf    = OGF_LINK_CTL; -	rq.ocf    = OCF_AUTH_REQUESTED; -	rq.cparam = &cp; -	rq.clen   = AUTH_REQUESTED_CP_SIZE; -	rq.rparam = &rp; -	rq.rlen   = EVT_CMD_STATUS_SIZE; -	rq.event  = EVT_CMD_STATUS; - -	if (hci_send_req(dd, &rq, 100) < 0) { -		syslog(LOG_ERR, "Unable to send authentication request: %s (%d)", -							strerror(errno), errno); -		reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET + errno); -		goto done; -	} - -	reply = dbus_message_new_method_return(msg); - -done: -	free(cr); - -failed: -	close(dd); - -	return reply; -} - -static DBusMessage *handle_dev_remove_bonding_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusConnection *connection = get_dbus_connection(); -	DBusMessageIter iter; -	DBusMessage *reply; -	DBusMessage *signal; -	char filename[PATH_MAX + 1]; -	char addr[18], *addr_ptr; -	struct hci_conn_info_req *cr; -	bdaddr_t bdaddr; -	int dd; - -	dd = hci_open_dev(dbus_data->dev_id); -	if (dd < 0) -		return error_no_such_device(msg); - -	get_device_address(dbus_data->dev_id, addr, sizeof(addr)); - -	snprintf(filename, PATH_MAX, "%s/%s/linkkeys", STORAGEDIR, addr); - -	dbus_message_iter_init(msg, &iter); -	dbus_message_iter_get_basic(&iter, &addr_ptr); - -	/* Delete the link key from storage */ -	textfile_del(filename, addr_ptr); - -	str2ba(addr_ptr, &bdaddr); - -	/* Delete the link key from the Bluetooth chip */ -	hci_delete_stored_link_key(dd, &bdaddr, 0, 1000); - -	/* Close active connections for the remote device */ -	cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); -	if (!cr) { -		syslog(LOG_ERR, "Can't allocate memory"); -		hci_close_dev(dd); -		return bluez_new_failure_msg(msg, BLUEZ_EDBUS_NO_MEM); -	} - -	bacpy(&cr->bdaddr, &bdaddr); -	cr->type = ACL_LINK; -	if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { -		/* Ignore when there isn't active connections, return success */ -		reply = dbus_message_new_method_return(msg); -		goto failed; -	} - -	/* Send the HCI disconnect command */ -	if (hci_disconnect(dd, htobs(cr->conn_info->handle), HCI_OE_USER_ENDED_CONNECTION, 1000) < 0) { -		syslog(LOG_ERR, "Disconnect failed"); -		reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET | errno); -		goto failed; -	} - -	/* FIXME: which condition must be verified before send the signal */ -	signal = dev_signal_factory(dbus_data->dev_id, -					DEV_SIG_BONDING_REMOVED, -					DBUS_TYPE_STRING, &addr_ptr, -					DBUS_TYPE_INVALID); -	if (signal) { -		dbus_connection_send(connection, signal, NULL); -		dbus_connection_flush(connection); -		dbus_message_unref(signal); -	} - -	reply = dbus_message_new_method_return(msg); - -failed: -	free(cr); - -	close(dd); - -	return reply; -} - -static DBusMessage *handle_dev_has_bonding_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessageIter iter; -	DBusMessage *reply; -	char filename[PATH_MAX + 1]; -	char addr[18], *addr_ptr, *str; -	dbus_bool_t result; - -	get_device_address(dbus_data->dev_id, addr, sizeof(addr)); - -	snprintf(filename, PATH_MAX, "%s/%s/linkkeys", STORAGEDIR, addr); - -	dbus_message_iter_init(msg, &iter); -	dbus_message_iter_get_basic(&iter, &addr_ptr); - -	str = textfile_get(filename, addr_ptr); -	if (str) { -		result = TRUE; -		free(str); -	} else -		result = FALSE; - -	reply = dbus_message_new_method_return(msg); - -	dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &result, -					DBUS_TYPE_INVALID); - -	return reply; -} - -static DBusMessage *handle_dev_list_bondings_req(DBusMessage *msg, void *data) -{ -	void do_append(char *key, char *value, void *data) -	{ -		DBusMessageIter *iter = data; - -		dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key); -	} - -	struct hci_dbus_data *dbus_data = data; -	DBusMessageIter iter; -	DBusMessageIter array_iter; -	DBusMessage *reply; -	char filename[PATH_MAX + 1]; -	char addr[18]; - -	get_device_address(dbus_data->dev_id, addr, sizeof(addr)); - -	snprintf(filename, PATH_MAX, "%s/%s/linkkeys", STORAGEDIR, addr); - -	reply = dbus_message_new_method_return(msg); - -	dbus_message_iter_init_append(reply, &iter); - -	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, -				DBUS_TYPE_STRING_AS_STRING, &array_iter); - -	textfile_foreach(filename, do_append, &array_iter); - -	dbus_message_iter_close_container(&iter, &array_iter); - -	return reply; -} - -static DBusMessage *handle_dev_pin_code_length_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessageIter iter; -	DBusMessage *reply; -	bdaddr_t local, peer; -	char addr[18], *addr_ptr; -	uint8_t length; -	int len; - -	get_device_address(dbus_data->dev_id, addr, sizeof(addr)); - -	str2ba(addr, &local); - -	dbus_message_iter_init(msg, &iter); -	dbus_message_iter_get_basic(&iter, &addr_ptr); - -	str2ba(addr_ptr, &peer); - -	len = read_pin_length(&local, &peer); -	if (len < 0) -		return bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET | -len); - -	reply = dbus_message_new_method_return(msg); - -	length = len; - -	dbus_message_append_args(reply, DBUS_TYPE_BYTE, &length, -					DBUS_TYPE_INVALID); - -	return reply; -} - -static DBusMessage *handle_dev_encryption_key_size_req(DBusMessage *msg, void *data) -{ -	struct hci_dbus_data *dbus_data = data; -	DBusMessageIter iter; -	DBusMessage *reply; -	bdaddr_t bdaddr; -	char *addr_ptr; -	uint8_t size; -	int val; - -	dbus_message_iter_init(msg, &iter); -	dbus_message_iter_get_basic(&iter, &addr_ptr); - -	str2ba(addr_ptr, &bdaddr); - -	val = get_encryption_key_size(dbus_data->dev_id, &bdaddr); -	if (val < 0) -		return bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET | -val); - -	reply = dbus_message_new_method_return(msg); - -	size = val; - -	dbus_message_append_args(reply, DBUS_TYPE_BYTE, &size, -					DBUS_TYPE_INVALID); - -	return reply; -} - -static DBusMessage *handle_dev_discover_req(DBusMessage *msg, void *data) -{ -	DBusMessage *reply = NULL; -	inquiry_cp cp; -	evt_cmd_status rp; -	struct hci_request rq; -	struct hci_dbus_data *dbus_data = data; -	uint8_t length = 8, num_rsp = 0; -	uint32_t lap = 0x9e8b33; -	int dd; - -	dd = hci_open_dev(dbus_data->dev_id); -	if (dd < 0) -		return error_no_such_device(msg); - -	memset(&cp, 0, sizeof(cp)); -	cp.lap[0]  = lap & 0xff; -	cp.lap[1]  = (lap >> 8) & 0xff; -	cp.lap[2]  = (lap >> 16) & 0xff; -	cp.length  = length; -	cp.num_rsp = num_rsp; - -	memset(&rq, 0, sizeof(rq)); -	rq.ogf    = OGF_LINK_CTL; -	rq.ocf    = OCF_INQUIRY; -	rq.cparam = &cp; -	rq.clen   = INQUIRY_CP_SIZE; -	rq.rparam = &rp; -	rq.rlen   = EVT_CMD_STATUS_SIZE; -	rq.event  = EVT_CMD_STATUS; - -	if (hci_send_req(dd, &rq, 100) < 0) { -		syslog(LOG_ERR, "Unable to start inquiry: %s (%d)", -							strerror(errno), errno); -		reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET + errno); -		goto failed; -	} - -	reply = dbus_message_new_method_return(msg); - -failed: -	hci_close_dev(dd); - -	return reply; -} - -static DBusMessage *handle_dev_discover_cancel_req(DBusMessage *msg, void *data) -{ -	DBusMessage *reply = NULL; -	struct hci_request rq; -	struct hci_dbus_data *dbus_data = data; -	uint8_t status; -	int dd; - -	dd = hci_open_dev(dbus_data->dev_id); -	if (dd < 0) -		return error_no_such_device(msg); - -	memset(&rq, 0, sizeof(rq)); -	rq.ogf    = OGF_LINK_CTL; -	rq.ocf    = OCF_INQUIRY_CANCEL; -	rq.rparam = &status; -	rq.rlen   = sizeof(status); - -	if (hci_send_req(dd, &rq, 100) < 0) { -		syslog(LOG_ERR, "Sending cancel inquiry failed: %s (%d)", -							strerror(errno), errno); -		reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET + errno); -		goto failed; -	} - -	if (status) { -		syslog(LOG_ERR, "Cancel inquiry failed with status 0x%02x", status); -		reply = bluez_new_failure_msg(msg, BLUEZ_EBT_OFFSET + status); -		goto failed; -	} - -	reply = dbus_message_new_method_return(msg); - -failed: -	hci_close_dev(dd); - -	return reply; -} - -static DBusMessage *handle_dev_discover_cache_req(DBusMessage *msg, void *data) -{ -	/*FIXME: */ -	return bluez_new_failure_msg(msg, BLUEZ_EDBUS_NOT_IMPLEMENTED); -} - -static DBusMessage *handle_dev_discover_service_req(DBusMessage *msg, void *data) -{ -	/*FIXME: */ -	return bluez_new_failure_msg(msg, BLUEZ_EDBUS_NOT_IMPLEMENTED); -} - -static const struct service_data dev_services[] = { -	{ DEV_GET_ADDRESS,		handle_dev_get_address_req,		DEV_GET_ADDRESS_SIGNATURE		}, -	{ DEV_GET_VERSION,		handle_dev_get_version_req,		DEV_GET_VERSION_SIGNATURE		}, -	{ DEV_GET_REVISION,		handle_dev_get_revision_req,		DEV_GET_REVISION_SIGNATURE		}, -	{ DEV_GET_MANUFACTURER,		handle_dev_get_manufacturer_req,	DEV_GET_MANUFACTURER_SIGNATURE		}, -	{ DEV_GET_COMPANY,		handle_dev_get_company_req,		DEV_GET_COMPANY_SIGNATURE		}, -	{ DEV_GET_FEATURES,		handle_dev_get_features_req,		DEV_GET_FEATURES_SIGNATURE		}, -	{ DEV_GET_MODE,			handle_dev_get_mode_req,		DEV_GET_MODE_SIGNATURE			}, -	{ DEV_SET_MODE,			handle_dev_set_mode_req,		DEV_SET_MODE_SIGNATURE			}, -	{ DEV_GET_DISCOVERABLE_TO,	handle_dev_get_discoverable_to_req,	DEV_GET_DISCOVERABLE_TO_SIGNATURE	}, -	{ DEV_SET_DISCOVERABLE_TO,	handle_dev_set_discoverable_to_req,	DEV_SET_DISCOVERABLE_TO_SIGNATURE	}, -	{ DEV_IS_CONNECTABLE,		handle_dev_is_connectable_req,		DEV_IS_CONNECTABLE_SIGNATURE		}, -	{ DEV_IS_DISCOVERABLE,		handle_dev_is_discoverable_req,		DEV_IS_DISCOVERABLE_SIGNATURE		}, -	{ DEV_GET_MAJOR_CLASS,		handle_dev_get_major_class_req,		DEV_GET_MAJOR_CLASS_SIGNATURE		}, -	{ DEV_GET_MINOR_CLASS,		handle_dev_get_minor_class_req,		DEV_GET_MINOR_CLASS_SIGNATURE		}, -	{ DEV_SET_MINOR_CLASS,		handle_dev_set_minor_class_req,		DEV_SET_MINOR_CLASS_SIGNATURE		}, -	{ DEV_GET_SERVICE_CLASSES,	handle_dev_get_service_classes_req,	DEV_GET_SERVICE_CLASSES_SIGNATURE	}, -	{ DEV_GET_NAME,			handle_dev_get_name_req,		DEV_GET_NAME_SIGNATURE			}, -	{ DEV_SET_NAME,			handle_dev_set_name_req,		DEV_SET_NAME_SIGNATURE			}, - -	{ DEV_GET_REMOTE_VERSION,	handle_dev_get_remote_version_req,	DEV_GET_REMOTE_VERSION_SIGNATURE	}, -	{ DEV_GET_REMOTE_REVISION,	handle_dev_get_remote_revision_req,	DEV_GET_REMOTE_REVISION_SIGNATURE	}, -	{ DEV_GET_REMOTE_MANUFACTURER,	handle_dev_get_remote_manufacturer_req,	DEV_GET_REMOTE_MANUFACTURER_SIGNATURE	}, -	{ DEV_GET_REMOTE_COMPANY,	handle_dev_get_remote_company_req,	DEV_GET_REMOTE_COMPANY_SIGNATURE	}, -	{ DEV_GET_REMOTE_NAME,		handle_dev_get_remote_name_req,		DEV_GET_REMOTE_NAME_SIGNATURE		}, -	{ DEV_GET_REMOTE_ALIAS,		handle_dev_get_remote_alias_req,	DEV_GET_REMOTE_ALIAS_SIGNATURE		}, -	{ DEV_SET_REMOTE_ALIAS,		handle_dev_set_remote_alias_req,	DEV_SET_REMOTE_ALIAS_SIGNATURE		}, - -	{ DEV_LAST_SEEN,		handle_dev_last_seen_req,		DEV_LAST_SEEN_SIGNATURE			}, -	{ DEV_LAST_USED,		handle_dev_last_used_req,		DEV_LAST_USED_SIGNATURE			}, - -	{ DEV_CREATE_BONDING,		handle_dev_create_bonding_req,		DEV_CREATE_BONDING_SIGNATURE		}, -	{ DEV_REMOVE_BONDING,		handle_dev_remove_bonding_req,		DEV_REMOVE_BONDING_SIGNATURE		}, -	{ DEV_HAS_BONDING_NAME,		handle_dev_has_bonding_req,		DEV_HAS_BONDING_SIGNATURE		}, -	{ DEV_LIST_BONDINGS,		handle_dev_list_bondings_req,		DEV_LIST_BONDINGS_SIGNATURE		}, -	{ DEV_PIN_CODE_LENGTH,		handle_dev_pin_code_length_req,		DEV_PIN_CODE_LENGTH_SIGNATURE		}, -	{ DEV_ENCRYPTION_KEY_SIZE,	handle_dev_encryption_key_size_req,	DEV_ENCRYPTION_KEY_SIZE_SIGNATURE	}, - -	{ DEV_DISCOVER,			handle_dev_discover_req,		DEV_DISCOVER_SIGNATURE			}, -	{ DEV_DISCOVER_CANCEL,		handle_dev_discover_cancel_req,		DEV_DISCOVER_CANCEL_SIGNATURE		}, -	{ DEV_DISCOVER_CACHE,		handle_dev_discover_cache_req,		DEV_DISCOVER_CACHE_SIGNATURE		}, -	{ DEV_DISCOVER_SERVICE,		handle_dev_discover_service_req,	DEV_DISCOVER_SERVICE_SIGNATURE		}, - -	{ NULL, NULL, NULL} -}; - -DBusHandlerResult msg_func_device(DBusConnection *conn, DBusMessage *msg, void *data) -{ -	const struct service_data *handlers = dev_services; -	DBusMessage *reply = NULL; -	struct hci_dbus_data *dbus_data = data; -	const char *method; -	const char *signature; -	const char *iface; -	uint32_t error = BLUEZ_EDBUS_UNKNOWN_METHOD; - -	method = dbus_message_get_member(msg); -	signature = dbus_message_get_signature(msg); -	iface = dbus_message_get_interface(msg); - -	syslog(LOG_INFO, "Adapter path:%s method:%s", -					dbus_message_get_path(msg), method); - -	if (strcmp(ADAPTER_INTERFACE, iface)) -		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - -	if (dbus_data->path_id == ADAPTER_ROOT_ID) { -		/* Adapter is down(path unregistered) or the path is wrong */ -		error = BLUEZ_EDBUS_UNKNOWN_PATH; -		goto failed; -	} - -	/* It's a device path id */ -	for (; handlers->name != NULL; handlers++) { -		if (strcmp(handlers->name, method)) -			continue; - -		if (!strcmp(handlers->signature, signature)) { -			reply = handlers->handler_func(msg, data); -			error = 0; -			break; -		} else { -			/* Set the error, but continue looping incase there is -			 * another method with the same name but a different -			 * signature */ -			error = BLUEZ_EDBUS_WRONG_SIGNATURE; -			continue; -		} -	} - -failed: -	if (error) -		reply = bluez_new_failure_msg(msg, error); - -	if (reply) { -		if (!dbus_connection_send (conn, reply, NULL)) -			syslog(LOG_ERR, "Can't send reply message"); - -		dbus_message_unref(reply); -	} - -	return DBUS_HANDLER_RESULT_HANDLED; -} | 
