diff options
| author | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2007-05-07 19:06:44 +0000 | 
|---|---|---|
| committer | Claudio Takahasi <claudio.takahasi@openbossa.org> | 2007-05-07 19:06:44 +0000 | 
| commit | 4a653936cf357c3266777e176da15508e08d7271 (patch) | |
| tree | c791738e366bdc32fd8b3a59c82e388a10c18911 /serial/manager.c | |
| parent | 7026c4f01e50040d2539a6ca7f80cb533210e8dd (diff) | |
serial: added get_handles and pending_connection struct
Diffstat (limited to 'serial/manager.c')
| -rw-r--r-- | serial/manager.c | 142 | 
1 files changed, 135 insertions, 7 deletions
| diff --git a/serial/manager.c b/serial/manager.c index 36711c1a..6e46bc51 100644 --- a/serial/manager.c +++ b/serial/manager.c @@ -48,14 +48,34 @@  #define PATH_LENGTH		32  #define BASE_UUID			"00000000-0000-1000-8000-00805F9B34FB" +struct pending_connection { +	DBusConnection	*conn; +	DBusMessage	*msg; +	bdaddr_t	src;		/* Source address */ +	char		*addr;		/* Destination address */ +	char		*adapter_path;	/* Adapter D-Bus path */ +}; +  static DBusConnection *connection = NULL; -static DBusHandlerResult err_invalid_args(DBusConnection *conn, +static void pending_connection_free(struct pending_connection *pc) +{ +	if (pc->conn) +		dbus_connection_unref(pc->conn); +	if (pc->msg) +		dbus_message_unref(pc->msg); +	if (pc->addr) +		g_free(pc->addr); +	if (pc->adapter_path) +		g_free(pc->adapter_path); +} + +static DBusHandlerResult err_connection_failed(DBusConnection *conn,  					DBusMessage *msg, const char *str)  {  	return send_message_and_unref(conn,  			dbus_message_new_error(msg, -				SERIAL_ERROR_INTERFACE ".InvalidArguments", str)); +			SERIAL_ERROR_INTERFACE".ConnectionAttemptFailed", str));  }  static DBusHandlerResult err_failed(DBusConnection *conn, @@ -66,11 +86,100 @@ static DBusHandlerResult err_failed(DBusConnection *conn,  				SERIAL_ERROR_INTERFACE ".Failed", str));  } +static DBusHandlerResult err_invalid_args(DBusConnection *conn, +					DBusMessage *msg, const char *str) +{ +	return send_message_and_unref(conn, +			dbus_message_new_error(msg, +				SERIAL_ERROR_INTERFACE ".InvalidArguments", str)); +} + +static DBusHandlerResult err_not_supported(DBusConnection *conn, +							DBusMessage *msg) +{ +	return send_message_and_unref(conn, +			dbus_message_new_error(msg, +			SERIAL_ERROR_INTERFACE ".NotSupported", +			"The service is not supported by the remote device")); +} + +static void handles_reply(DBusPendingCall *call, void *data) +{ +	struct pending_connection *pc = data; +	DBusMessage *reply = dbus_pending_call_steal_reply(call); +	DBusError derr; +	uint32_t *phandle; +	int len; + +	dbus_error_init(&derr); +	if (dbus_set_error_from_message(&derr, reply)) { +		if (dbus_error_has_name(&derr, +				"org.bluez.Error.ConnectionAttemptFailed")) +			err_connection_failed(pc->conn, pc->msg, derr.message); +		else +			err_not_supported(pc->conn, pc->msg); + +		error("GetRemoteServiceHandles: %s(%s)", +					derr.name, derr.message); +		goto fail; +	} +	 +	if (!dbus_message_get_args(reply, &derr, +				DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &phandle, +				&len, DBUS_TYPE_INVALID)) { +		err_not_supported(pc->conn, pc->msg); +		error("%s: %s", derr.name, derr.message); +		goto fail; +	} + +	if (len == 0) { +		err_not_supported(pc->conn, pc->msg); +		goto fail; +	} + +	/* FIXME: Get the record */ +	dbus_message_unref(reply); +	return; +fail: +	dbus_message_unref(reply); +	dbus_error_free(&derr); +	pending_connection_free(pc); +} + +static int get_handles(struct pending_connection *pc, const char *uuid, +					DBusPendingCallNotifyFunction cb) +{ +	DBusMessage *msg; +	DBusPendingCall *pending; + +	msg = dbus_message_new_method_call("org.bluez", pc->adapter_path, +				"org.bluez.Adapter", "GetRemoteServiceHandles"); +	if (!msg) +		return -1; + +	dbus_message_append_args(msg, +			DBUS_TYPE_STRING, &pc->addr, +			DBUS_TYPE_STRING, &uuid, +			DBUS_TYPE_INVALID); + +	if (dbus_connection_send_with_reply(pc->conn, msg, &pending, -1) == FALSE) { +		error("Can't send D-Bus message."); +		return -1; +	} + +	dbus_pending_call_set_notify(pending, cb, pc, NULL); +	dbus_message_unref(msg); +	dbus_pending_call_unref(pending); + +	return 0; +} +  static DBusHandlerResult connect_service(DBusConnection *conn,  					DBusMessage *msg, void *data)  {  	DBusError derr;  	bdaddr_t src; +	struct pending_connection *pc;  	const char *addr, *pattern;  	char *endptr;  	long val; @@ -92,6 +201,14 @@ static DBusHandlerResult connect_service(DBusConnection *conn,  	if ((dev_id < 0) ||  (hci_devba(dev_id, &src) < 0))  		return err_failed(conn, msg, "Adapter not available"); +	pc = g_new0(struct pending_connection, 1); +	pc->conn = dbus_connection_ref(conn); +	pc->msg = dbus_message_ref(msg); +	bacpy(&pc->src, &src); +	pc->addr = g_strdup(addr); +	pc->adapter_path = g_malloc0(16); +	snprintf(pc->adapter_path, 16, "/org/bluez/hci%d", dev_id); +  	/* UUID 128*/  	if (strlen(pattern) == 36) {  		char tmp[37]; @@ -102,10 +219,15 @@ static DBusHandlerResult connect_service(DBusConnection *conn,  		tmp[6] = '0';  		tmp[7] = '0'; -		if (strcasecmp(BASE_UUID, tmp) != 0) +		if (strcasecmp(BASE_UUID, tmp) != 0) { +			pending_connection_free(pc);  			return err_invalid_args(conn, msg, "invalid UUID"); +		} -		/* FIXME: Retrieve the handle/record */ +		if (get_handles(pc, pattern, handles_reply) < 0) { +			pending_connection_free(pc); +			return err_not_supported(conn, msg); +		}  		return DBUS_HANDLER_RESULT_HANDLED;  	} @@ -113,22 +235,28 @@ static DBusHandlerResult connect_service(DBusConnection *conn,  	errno = 0;  	val = strtol(pattern, &endptr, 0);  	if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || -			(errno != 0 && val == 0) || (pattern == endptr)) +			(errno != 0 && val == 0) || (pattern == endptr)) { +		pending_connection_free(pc);  		return err_invalid_args(conn, msg, "Invalid pattern"); +	}  	/* Record handle: starts at 0x10000 */  	if (strncasecmp("0x", pattern, 2) == 0) { -		if (val < 0x10000) +		if (val < 0x10000) { +			pending_connection_free(pc);  			return err_invalid_args(conn, msg,  					"invalid record handle"); +		}  		/* FIXME: retrieve the record */  		return DBUS_HANDLER_RESULT_HANDLED;  	}  	/* RFCOMM Channel range: 1 - 30 */ -	if (val < 1 || val > 30) +	if (val < 1 || val > 30) { +		pending_connection_free(pc);  		return err_invalid_args(conn, msg,  				"invalid RFCOMM channel"); +	}  	/* FIXME: Connect */  	info("Connecting to channel: %d", val); | 
