diff options
| -rw-r--r-- | hcid/dbus-common.c | 5 | ||||
| -rw-r--r-- | hcid/dbus-hci.c | 30 | ||||
| -rwxr-xr-x | hcid/list-devices | 3 | ||||
| -rw-r--r-- | hcid/main.c | 6 | ||||
| -rw-r--r-- | hcid/manager.c | 175 | 
5 files changed, 205 insertions, 14 deletions
| diff --git a/hcid/dbus-common.c b/hcid/dbus-common.c index d3d3a151..a277b401 100644 --- a/hcid/dbus-common.c +++ b/hcid/dbus-common.c @@ -337,6 +337,11 @@ int hcid_dbus_init(void)  	if (!conn)  		return -1; +	if (hcid_dbus_use_experimental()) { +		debug("Registering experimental manager path"); +		dbus_connection_create_object_path(conn, "/", NULL, NULL); +	} +  	if (!dbus_connection_create_object_path(conn, BASE_PATH, NULL, NULL))  		return -1; diff --git a/hcid/dbus-hci.c b/hcid/dbus-hci.c index d8e13447..981d6821 100644 --- a/hcid/dbus-hci.c +++ b/hcid/dbus-hci.c @@ -519,6 +519,14 @@ int hcid_dbus_register_device(uint16_t id)  	/*  	 * Send the adapter added signal  	 */ +	if (hcid_dbus_use_experimental()) { +		dbus_connection_emit_signal(connection, "/", +						MANAGER_INTERFACE, +						"AdapterAdded", +						DBUS_TYPE_OBJECT_PATH, &pptr, +						DBUS_TYPE_INVALID); +	} +  	dbus_connection_emit_signal(connection, BASE_PATH, MANAGER_INTERFACE,  					"AdapterAdded",  					DBUS_TYPE_STRING, &pptr, @@ -543,6 +551,14 @@ int hcid_dbus_unregister_device(uint16_t id)  	snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id); +	if (hcid_dbus_use_experimental()) { +		dbus_connection_emit_signal(connection, "/", +						MANAGER_INTERFACE, +						"AdapterRemoved", +						DBUS_TYPE_OBJECT_PATH, &pptr, +						DBUS_TYPE_INVALID); +	} +  	dbus_connection_emit_signal(connection, BASE_PATH, MANAGER_INTERFACE,  					"AdapterRemoved",  					DBUS_TYPE_STRING, &pptr, @@ -556,6 +572,13 @@ int hcid_dbus_unregister_device(uint16_t id)  		if (new_default >= 0) {  			snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH,  					new_default); +			if (hcid_dbus_use_experimental()) { +				dbus_connection_emit_signal(connection, "/", +						MANAGER_INTERFACE, +						"DefaultAdapterChanged", +						DBUS_TYPE_OBJECT_PATH, &pptr, +						DBUS_TYPE_INVALID); +			}  			dbus_connection_emit_signal(connection, BASE_PATH,  							MANAGER_INTERFACE,  							"DefaultAdapterChanged", @@ -563,6 +586,13 @@ int hcid_dbus_unregister_device(uint16_t id)  							DBUS_TYPE_INVALID);  		} else {  			*path = '\0'; +			if (hcid_dbus_use_experimental()) { +				dbus_connection_emit_signal(connection, "/", +						MANAGER_INTERFACE, +						"DefaultAdapterChanged", +						DBUS_TYPE_OBJECT_PATH, &pptr, +						DBUS_TYPE_INVALID); +			}  			dbus_connection_emit_signal(connection, BASE_PATH,  							MANAGER_INTERFACE,  							"DefaultAdapterChanged", diff --git a/hcid/list-devices b/hcid/list-devices index 2aefbe09..6ee4f5aa 100755 --- a/hcid/list-devices +++ b/hcid/list-devices @@ -19,8 +19,7 @@ def extract_uuids(uuid_list):  	return list -manager = dbus.Interface(bus.get_object('org.bluez', '/org/bluez'), -							'org.bluez.Manager') +manager = dbus.Interface(bus.get_object('org.bluez', '/'), 'org.bluez.Manager')  adapter_list = manager.ListAdapters() diff --git a/hcid/main.c b/hcid/main.c index 8bdc20b0..0fdca81b 100644 --- a/hcid/main.c +++ b/hcid/main.c @@ -890,14 +890,14 @@ int main(int argc, char *argv[])  	init_adapters(); +	if (experimental) +		hcid_dbus_set_experimental(); +  	if (hcid_dbus_init() < 0) {  		error("Unable to get on D-Bus");  		exit(1);  	} -	if (experimental) -		hcid_dbus_set_experimental(); -  	init_security_data();  	/* Create event loop */ diff --git a/hcid/manager.c b/hcid/manager.c index 0c6ebe2d..cb6e80f5 100644 --- a/hcid/manager.c +++ b/hcid/manager.c @@ -80,7 +80,7 @@ static DBusHandlerResult interface_version(DBusConnection *conn,  	return send_message_and_unref(conn, reply);  } -static DBusHandlerResult default_adapter(DBusConnection *conn, +static DBusHandlerResult old_default_adapter(DBusConnection *conn,  						DBusMessage *msg, void *data)  {  	DBusMessage *reply; @@ -148,7 +148,7 @@ out:  	return devid;  } -static DBusHandlerResult find_adapter(DBusConnection *conn, +static DBusHandlerResult old_find_adapter(DBusConnection *conn,  						DBusMessage *msg, void *data)  {  	DBusMessage *reply; @@ -190,7 +190,7 @@ static DBusHandlerResult find_adapter(DBusConnection *conn,  	return send_message_and_unref(conn, reply);  } -static DBusHandlerResult list_adapters(DBusConnection *conn, +static DBusHandlerResult old_list_adapters(DBusConnection *conn,  						DBusMessage *msg, void *data)  {  	DBusMessageIter iter; @@ -349,18 +349,18 @@ static DBusHandlerResult activate_service(DBusConnection *conn,  	return DBUS_HANDLER_RESULT_HANDLED;  } -static DBusMethodVTable manager_methods[] = { +static DBusMethodVTable old_manager_methods[] = {  	{ "InterfaceVersion",	interface_version,	"",	"u"	}, -	{ "DefaultAdapter",	default_adapter,	"",	"s"	}, -	{ "FindAdapter",	find_adapter,		"s",	"s"	}, -	{ "ListAdapters",	list_adapters,		"",	"as"	}, +	{ "DefaultAdapter",	old_default_adapter,	"",	"s"	}, +	{ "FindAdapter",	old_find_adapter,	"s",	"s"	}, +	{ "ListAdapters",	old_list_adapters,	"",	"as"	},  	{ "FindService",	find_service,		"s",	"s"	},  	{ "ListServices",	list_services,		"",	"as"	},  	{ "ActivateService",	activate_service,	"s",	"s"	},  	{ NULL, NULL, NULL, NULL }  }; -static DBusSignalVTable manager_signals[] = { +static DBusSignalVTable old_manager_signals[] = {  	{ "AdapterAdded",		"s"	},  	{ "AdapterRemoved",		"s"	},  	{ "DefaultAdapterChanged",	"s"	}, @@ -369,11 +369,168 @@ static DBusSignalVTable manager_signals[] = {  	{ NULL, NULL }  }; +static DBusHandlerResult default_adapter(DBusConnection *conn, +						DBusMessage *msg, void *data) +{ +	DBusMessage *reply; +	char path[MAX_PATH_LENGTH], *path_ptr = path; + +	if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) +		return error_invalid_arguments(conn, msg, NULL); + +	if (default_adapter_id < 0) +		return error_no_such_adapter(conn, msg); + +	reply = dbus_message_new_method_return(msg); +	if (!reply) +		return DBUS_HANDLER_RESULT_NEED_MEMORY; + +	snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, default_adapter_id); + +	dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path_ptr, +					DBUS_TYPE_INVALID); + +	return send_message_and_unref(conn, reply); +} + +static DBusHandlerResult find_adapter(DBusConnection *conn, +						DBusMessage *msg, void *data) +{ +	DBusMessage *reply; +	char path[MAX_PATH_LENGTH], *path_ptr = path; +	struct hci_dev_info di; +	const char *pattern; +	int dev_id; + +	if (!dbus_message_get_args(msg, NULL, +				DBUS_TYPE_STRING, &pattern, +				DBUS_TYPE_INVALID)) +		return error_invalid_arguments(conn, msg, NULL); + +	/* hci_devid() would make sense to use here, except it +	   is restricted to devices which are up */ +	if (!strncmp(pattern, "hci", 3) && strlen(pattern) >= 4) +		dev_id = atoi(pattern + 3); +	else +		dev_id = find_by_address(pattern); + +	if (dev_id < 0) +		return error_no_such_adapter(conn, msg); + +	if (hci_devinfo(dev_id, &di) < 0) +		return error_no_such_adapter(conn, msg); + +	if (hci_test_bit(HCI_RAW, &di.flags)) +		return error_no_such_adapter(conn, msg); + +	reply = dbus_message_new_method_return(msg); +	if (!reply) +		return DBUS_HANDLER_RESULT_NEED_MEMORY; + +	snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, dev_id); + +	dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path_ptr, +					DBUS_TYPE_INVALID); + +	return send_message_and_unref(conn, reply); +} + +static DBusHandlerResult list_adapters(DBusConnection *conn, +						DBusMessage *msg, void *data) +{ +	DBusMessageIter iter; +	DBusMessageIter array_iter; +	DBusMessage *reply; +	struct hci_dev_list_req *dl; +	struct hci_dev_req *dr; +	int i, sk; + +	if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING)) +		return error_invalid_arguments(conn, msg, NULL); + +	sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); +	if (sk < 0) +		return error_failed_errno(conn, msg, errno); + +	dl = g_malloc0(HCI_MAX_DEV * sizeof(*dr) + sizeof(*dl)); + +	dl->dev_num = HCI_MAX_DEV; +	dr = dl->dev_req; + +	if (ioctl(sk, HCIGETDEVLIST, dl) < 0) { +		int err = errno; +		close(sk); +		g_free(dl); +		return error_failed_errno(conn, msg, err); +	} + +	dr = dl->dev_req; + +	reply = dbus_message_new_method_return(msg); +	if (!reply) { +		close(sk); +		g_free(dl); +		return DBUS_HANDLER_RESULT_NEED_MEMORY; +	} + +	dbus_message_iter_init_append(reply, &iter); + +	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, +				DBUS_TYPE_OBJECT_PATH_AS_STRING, &array_iter); + +	for (i = 0; i < dl->dev_num; i++, dr++) { +		char path[MAX_PATH_LENGTH], *path_ptr = path; +		struct hci_dev_info di; + +		if (hci_devinfo(dr->dev_id, &di) < 0) +			continue; + +		if (hci_test_bit(HCI_RAW, &di.flags)) +			continue; + +		snprintf(path, sizeof(path), "%s/%s", BASE_PATH, di.name); + +		dbus_message_iter_append_basic(&array_iter, +					DBUS_TYPE_OBJECT_PATH, &path_ptr); +	} + +	dbus_message_iter_close_container(&iter, &array_iter); + +	g_free(dl); + +	close(sk); + +	return send_message_and_unref(conn, reply); +} + +static DBusMethodVTable manager_methods[] = { +	{ "DefaultAdapter",	default_adapter,	"",	"o"	}, +	{ "FindAdapter",	find_adapter,		"s",	"o"	}, +	{ "ListAdapters",	list_adapters,		"",	"ao"	}, +	{ NULL, NULL, NULL, NULL } +}; + +static DBusSignalVTable manager_signals[] = { +	{ "AdapterAdded",		"o"	}, +	{ "AdapterRemoved",		"o"	}, +	{ "DefaultAdapterChanged",	"o"	}, +	{ NULL, NULL } +}; +  dbus_bool_t manager_init(DBusConnection *conn, const char *path)  { -	return dbus_connection_register_interface(conn, path, MANAGER_INTERFACE, +	if (hcid_dbus_use_experimental()) { +		debug("Registering experimental manager interface"); +		dbus_connection_register_interface(conn, "/", +							MANAGER_INTERFACE,  							manager_methods,  							manager_signals, NULL); +	} + +	return dbus_connection_register_interface(conn, path, +						MANAGER_INTERFACE, +						old_manager_methods, +						old_manager_signals, NULL);  }  int get_default_adapter(void) | 
