diff options
| author | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2007-01-19 16:07:37 +0000 | 
|---|---|---|
| committer | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2007-01-19 16:07:37 +0000 | 
| commit | 87113c3bda9245ad758ce75d8cec04ca303faed3 (patch) | |
| tree | de955fe6bbaf3d77e6eb50aa60eb86609b5a57dc | |
| parent | 209c6c831ac8371fa36828ac6f433d5380bc476c (diff) | |
CreateDevice: initial skeleton
| -rw-r--r-- | input/input-service.c | 294 | 
1 files changed, 223 insertions, 71 deletions
diff --git a/input/input-service.c b/input/input-service.c index 35e5306b..4c2105c4 100644 --- a/input/input-service.c +++ b/input/input-service.c @@ -33,6 +33,7 @@  #include "logging.h"  #include "input-service.h"  #include "glib-ectomy.h" +#include "textfile.h"  #include <dbus/dbus.h> @@ -49,6 +50,25 @@  static DBusConnection *connection = NULL; +struct input_device { +	char addr[18]; +}; + +struct input_device *input_device_new(const char *addr) +{ +	struct input_device *idev; + +	idev = malloc(sizeof(struct input_device)); +	if (!idev) +		return NULL; + +	memset(idev, 0, sizeof(struct input_device)); + +	memcpy(idev->addr, addr, 18); + +	return idev; +} +  /*   * Common D-Bus BlueZ input error functions   */ @@ -68,98 +88,60 @@ static DBusHandlerResult err_unknown_method(DBusConnection *conn, DBusMessage *m  				"Unknown input method"));  } -/* - * Input Manager methods - */ -struct input_manager { -	GList *paths; -}; - -static DBusHandlerResult manager_create_device(DBusConnection *conn, -				DBusMessage *msg, void *data) +static DBusHandlerResult err_failed(DBusConnection *conn, DBusMessage *msg, +				const char *str)  { -	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +	return send_message_and_unref(conn, +			dbus_message_new_error(msg, +				INPUT_ERROR_INTERFACE ".Failed", str));  } -static DBusHandlerResult manager_remove_device(DBusConnection *conn, -				DBusMessage *msg, void *data) +static DBusHandlerResult err_already_exists(DBusConnection *conn, +				DBusMessage *msg, const char *str)  { -	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +	return send_message_and_unref(conn, +			dbus_message_new_error(msg, +				INPUT_ERROR_INTERFACE ".AlreadyExists", str));  } -static DBusHandlerResult manager_list_devices(DBusConnection *conn, -				DBusMessage *msg, void *data) +static DBusHandlerResult err_generic(DBusConnection *conn, DBusMessage *msg, +				const char *name, const char *str)  { -	struct input_manager *mgr = data; -	DBusMessageIter iter, iter_array; -	DBusMessage *reply; -	GList *paths; - -	reply = dbus_message_new_method_return(msg); -	if (!reply) -		return DBUS_HANDLER_RESULT_NEED_MEMORY; - -	dbus_message_iter_init_append(reply, &iter); -	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, -			DBUS_TYPE_STRING_AS_STRING, &iter_array); - -	for (paths = mgr->paths; paths != NULL; paths = paths->next) { -		const char *ppath = paths->data; -		dbus_message_iter_append_basic(&iter_array, -				DBUS_TYPE_STRING, &ppath); -	} - -	dbus_message_iter_close_container(&iter, &iter_array); +	return send_message_and_unref(conn, +			dbus_message_new_error(msg, name, str)); -	return send_message_and_unref(conn, reply);  } -static DBusHandlerResult manager_message(DBusConnection *conn, -				DBusMessage *msg, void *data) +static inline int create_filename(char *buf, size_t size, +			bdaddr_t *bdaddr, const char *name)  { -	const char *path, *iface, *member; +	char addr[18]; -	path = dbus_message_get_path(msg); -	iface = dbus_message_get_interface(msg); -	member = dbus_message_get_member(msg); - -	/* Catching fallback paths */ -	if (strcmp(INPUT_PATH, path) != 0) -		return err_unknown_device(conn, msg); - -	/* Accept messages from the input manager interface only */ -	if (strcmp(INPUT_MANAGER_INTERFACE, iface)) -		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - -	if (strcmp(member, "ListDevices") == 0) -		return manager_list_devices(conn, msg, data); +	ba2str(bdaddr, addr); -	if (strcmp(member, "CreateDevice") == 0) -		return manager_create_device(conn, msg, data); - -	if (strcmp(member, "RemoveDevice") == 0) -		return manager_remove_device(conn, msg, data); - -	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +	return create_name(buf, size, STORAGEDIR, addr, name);  } -static void manager_unregister(DBusConnection *conn, void *data) +static int has_hid_record(const char *local, const char *peer)  { -	struct input_manager *mgr = data; +	char filename[PATH_MAX + 1], *str; -	info("Unregistered manager path"); +	create_name(filename, PATH_MAX, STORAGEDIR, local, "hidd"); -	if (mgr->paths) -		g_list_foreach(mgr->paths, (GFunc) free, NULL); +	str = textfile_get(filename, peer); +	if (!str) +		return 0; -	free(mgr); +	free(str); +	return 1;  } -/* Virtual table to handle manager object path hierarchy */ -static const DBusObjectPathVTable manager_table = { -	.message_function = manager_message, -	.unregister_function = manager_unregister, -}; +static int search_request(DBusConnection *conn, +		DBusMessage *msg, const char *peer) +{ +	info("FIXME: service search"); +	return 0; +}  /*   * Input Device methods @@ -260,14 +242,177 @@ static DBusHandlerResult device_message(DBusConnection *conn,  	return err_unknown_method(conn, msg);  } +static DBusHandlerResult device_message(DBusConnection *conn, +				DBusMessage *msg, void *data);  /* Virtual table to handle device object path hierarchy */  static const DBusObjectPathVTable device_table = {  	.message_function = device_message,  }; +/* + * Input Manager methods + */ +struct input_manager { +	char adapter[18]; +	GList *paths; +}; + +static int path_addr_cmp(const char *path, const char *addr) +{ +	struct input_device *idev; + +	if (!dbus_connection_get_object_path_data(connection, path, +				(void *) &idev)) +		return -1; + +	if (!idev) +		return -1; + +	return strcasecmp(idev->addr, addr); +} + +static DBusHandlerResult manager_create_device(DBusConnection *conn, +				DBusMessage *msg, void *data) +{ +	struct input_manager *mgr = data; +	struct input_device *idev; +	DBusMessage *reply; +	DBusError derr; +	const char *addr; +	const char *keyb_path = "/org/bluez/input/keyboard0"; +	GList *path; + +	dbus_error_init(&derr); +	if (!dbus_message_get_args(msg, &derr, +				DBUS_TYPE_STRING, &addr, +				DBUS_TYPE_INVALID)) { +		err_generic(conn, msg, derr.name, derr.message); +		dbus_error_free(&derr); +		return DBUS_HANDLER_RESULT_HANDLED; +	} + +	path = g_list_find_custom(mgr->paths, addr, +			(GCompareFunc) path_addr_cmp); +	if (path) +		return err_already_exists(conn, msg, "Input Already exists"); + +	if (!has_hid_record(mgr->adapter, addr)) { +		if (search_request(conn, msg, addr) < 0) +			return err_failed(conn, msg, "SDP error"); + +		return DBUS_HANDLER_RESULT_HANDLED; +	} + +	idev = input_device_new(addr); +	if (!idev) +		return DBUS_HANDLER_RESULT_NEED_MEMORY; + +	reply = dbus_message_new_method_return(msg); +	if (!reply) { +		free(idev); +		return DBUS_HANDLER_RESULT_NEED_MEMORY; +	} + +	if (!dbus_connection_register_object_path(conn, +				keyb_path, &device_table, idev)) { +		error("Input device path registration failed"); +		free(idev); +		return err_failed(conn, msg, "Path registration failed"); +	} + +	mgr->paths = g_list_append(mgr->paths, strdup(keyb_path)); +	dbus_message_append_args(reply, +			DBUS_TYPE_STRING, &keyb_path, +			DBUS_TYPE_INVALID); + +	return send_message_and_unref(conn, reply); +} + +static DBusHandlerResult manager_remove_device(DBusConnection *conn, +				DBusMessage *msg, void *data) +{ +	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static DBusHandlerResult manager_list_devices(DBusConnection *conn, +				DBusMessage *msg, void *data) +{ +	struct input_manager *mgr = data; +	DBusMessageIter iter, iter_array; +	DBusMessage *reply; +	GList *paths; + +	reply = dbus_message_new_method_return(msg); +	if (!reply) +		return DBUS_HANDLER_RESULT_NEED_MEMORY; + +	dbus_message_iter_init_append(reply, &iter); +	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, +			DBUS_TYPE_STRING_AS_STRING, &iter_array); + +	for (paths = mgr->paths; paths != NULL; paths = paths->next) { +		const char *ppath = paths->data; +		dbus_message_iter_append_basic(&iter_array, +				DBUS_TYPE_STRING, &ppath); +	} + +	dbus_message_iter_close_container(&iter, &iter_array); + +	return send_message_and_unref(conn, reply); +} + +static DBusHandlerResult manager_message(DBusConnection *conn, +				DBusMessage *msg, void *data) +{ +	const char *path, *iface, *member; + +	path = dbus_message_get_path(msg); +	iface = dbus_message_get_interface(msg); +	member = dbus_message_get_member(msg); + +	/* Catching fallback paths */ +	if (strcmp(INPUT_PATH, path) != 0) +		return err_unknown_device(conn, msg); + +	/* Accept messages from the input manager interface only */ +	if (strcmp(INPUT_MANAGER_INTERFACE, iface)) +		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + +	if (strcmp(member, "ListDevices") == 0) +		return manager_list_devices(conn, msg, data); + +	if (strcmp(member, "CreateDevice") == 0) +		return manager_create_device(conn, msg, data); + +	if (strcmp(member, "RemoveDevice") == 0) +		return manager_remove_device(conn, msg, data); + +	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static void manager_unregister(DBusConnection *conn, void *data) +{ +	struct input_manager *mgr = data; + +	info("Unregistered manager path"); + +	if (mgr->paths) +		g_list_foreach(mgr->paths, (GFunc) free, NULL); + +	free(mgr); +} + +/* Virtual table to handle manager object path hierarchy */ +static const DBusObjectPathVTable manager_table = { +	.message_function = manager_message, +	.unregister_function = manager_unregister, +}; +  int input_dbus_init(void)  {  	struct input_manager *mgr; +	bdaddr_t sba; +  	connection = init_dbus(INPUT_SERVICE, NULL, NULL);  	if (!connection)  		return -1; @@ -277,6 +422,13 @@ int input_dbus_init(void)  	mgr = malloc(sizeof(struct input_manager));  	memset(mgr, 0, sizeof(struct input_manager)); +	/* Get the local adapter */ +	if (hci_devba(0, &sba) < 0) { +		error("Can't access local adapter"); +		return -1; +	} +	ba2str(&sba, mgr->adapter); +  	/* Fallback to catch invalid device path */  	if (!dbus_connection_register_fallback(connection, INPUT_PATH,  						&manager_table, mgr)) {  | 
