diff options
Diffstat (limited to 'input/input-service.c')
| -rw-r--r-- | input/input-service.c | 82 | 
1 files changed, 53 insertions, 29 deletions
| diff --git a/input/input-service.c b/input/input-service.c index c1df0a37..dbbdb877 100644 --- a/input/input-service.c +++ b/input/input-service.c @@ -60,6 +60,7 @@  #define L2CAP_PSM_HIDP_INTR		0x13  static DBusConnection *connection = NULL; +  const char *pnp_uuid = "00001200-0000-1000-8000-00805f9b34fb";  const char *hid_uuid = "00001124-0000-1000-8000-00805f9b34fb"; @@ -68,6 +69,11 @@ struct input_device {  	struct hidp_connadd_req hidp;  }; +struct input_manager { +	bdaddr_t sba;		/* Local adapter BT address */ +	GSList *paths;		/* Input registered paths */ +}; +  struct pending_req {  	char *adapter_path;	/* Local adapter D-Bus path */  	bdaddr_t sba;		/* Local adapter BT address */ @@ -110,8 +116,8 @@ static void input_device_free(struct input_device *idev)  }  static struct pending_req *pending_req_new(DBusConnection *conn, -		DBusMessage *msg, const char *adapter_path, -		bdaddr_t *sba, bdaddr_t *dba) +				DBusMessage *msg, const char *adapter_path, +						bdaddr_t *sba, bdaddr_t *dba)  {  	struct pending_req *pr;  	pr = malloc(sizeof(struct pending_req)); @@ -357,7 +363,7 @@ static const char *create_input_path(uint8_t minor)  }  static int l2cap_connect(struct pending_connect *pc, -		unsigned short psm, GIOFunc cb) +					unsigned short psm, GIOFunc cb)  {  	GIOChannel *io;  	struct sockaddr_l2 addr; @@ -413,7 +419,7 @@ failed:  }  static gboolean interrupt_connect_cb(GIOChannel *chan, GIOCondition cond, -			struct pending_connect *pc) +						struct pending_connect *pc)  {  	struct input_device *idev;  	int ctl, isk, ret, err; @@ -431,7 +437,7 @@ static gboolean interrupt_connect_cb(GIOChannel *chan, GIOCondition cond,  	isk = g_io_channel_unix_get_fd(chan);  	idev->hidp.intr_sock = isk; -	idev->hidp.idle_to = 1800; /* 30 sec */ +	idev->hidp.idle_to = 30 * 60;	/* 30 minutes */  	len = sizeof(ret);  	if (getsockopt(isk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) { @@ -452,11 +458,21 @@ static gboolean interrupt_connect_cb(GIOChannel *chan, GIOCondition cond,  		error("Can't open HIDP control socket");  		goto failed;  	} + +	if (idev->hidp.subclass & 0x40) { +		err = encrypt_link(&pc->sba, &pc->dba); +		if (err < 0) { +			close(ctl); +			goto failed; +		} +	} +  	if (ioctl(ctl, HIDPCONNADD, &idev->hidp) < 0) {  		err = errno;  		close(ctl);  		goto failed;  	} +  	close(ctl);  	send_message_and_unref(pc->conn, @@ -466,6 +482,7 @@ static gboolean interrupt_connect_cb(GIOChannel *chan, GIOCondition cond,  	g_io_channel_unref(chan);  	return FALSE; +  failed:  	if (isk > 0)  		close(isk); @@ -479,7 +496,7 @@ failed:  }  static gboolean control_connect_cb(GIOChannel *chan, GIOCondition cond, -			struct pending_connect *pc) +						struct pending_connect *pc)  {  	struct input_device *idev;  	int ret, csk, err; @@ -511,6 +528,7 @@ static gboolean control_connect_cb(GIOChannel *chan, GIOCondition cond,  		error("connect(): %s (%d)", strerror(ret), ret);  		goto failed;  	} +  	/* Connect to the HID interrupt channel */  	if (l2cap_connect(pc, L2CAP_PSM_HIDP_INTR,  			(GIOFunc) interrupt_connect_cb) < 0) { @@ -550,7 +568,7 @@ static int disconnect(struct input_device *idev,  uint32_t flags)  	memset(&ci, 0, sizeof(struct hidp_conninfo));  	bacpy(&ci.bdaddr, &idev->dba);  	if ((ioctl(ctl, HIDPGETCONNINFO, &ci) < 0) || -			(ci.state != BT_CONNECTED)) { +				(ci.state != BT_CONNECTED)) {  		errno = ENOTCONN;  		goto fail;  	} @@ -606,15 +624,17 @@ static int is_connected(bdaddr_t *dba)   * Input Device methods   */  static DBusHandlerResult device_connect(DBusConnection *conn, -				DBusMessage *msg, void *data) +						DBusMessage *msg, void *data)  {  	struct input_device *idev = data; +	struct input_manager *mgr;  	struct pending_connect *pc;  	if (is_connected(&idev->dba))  		return err_connection_failed(conn, msg, "Already connected"); -	pc = pending_connect_new(BDADDR_ANY, &idev->dba, conn, msg); +	dbus_connection_get_object_path_data(conn, INPUT_PATH, (void *) &mgr); +	pc = pending_connect_new(&mgr->sba, &idev->dba, conn, msg);  	if (!pc)  		return DBUS_HANDLER_RESULT_NEED_MEMORY; @@ -629,7 +649,7 @@ static DBusHandlerResult device_connect(DBusConnection *conn,  }  static DBusHandlerResult device_disconnect(DBusConnection *conn, -				DBusMessage *msg, void *data) +						DBusMessage *msg, void *data)  {  	struct input_device *idev = data; @@ -641,7 +661,7 @@ static DBusHandlerResult device_disconnect(DBusConnection *conn,  }  static DBusHandlerResult device_is_connected(DBusConnection *conn, -				DBusMessage *msg, void *data) +						DBusMessage *msg, void *data)  {  	struct input_device *idev = data;  	DBusMessage *reply; @@ -660,13 +680,13 @@ static DBusHandlerResult device_is_connected(DBusConnection *conn,  }  static DBusHandlerResult device_get_address(DBusConnection *conn, -				DBusMessage *msg, void *data) +						DBusMessage *msg, void *data)  {  	struct input_device *idev = data;  	DBusMessage *reply;  	char addr[18];  	const char *paddr = addr; -	 +  	ba2str(&idev->dba, addr);  	reply = dbus_message_new_method_return(msg); @@ -681,7 +701,7 @@ static DBusHandlerResult device_get_address(DBusConnection *conn,  }  static DBusHandlerResult device_get_name(DBusConnection *conn, -				DBusMessage *msg, void *data) +						DBusMessage *msg, void *data)  {  	struct input_device *idev = data;  	DBusMessage *reply; @@ -699,7 +719,7 @@ static DBusHandlerResult device_get_name(DBusConnection *conn,  }  static DBusHandlerResult device_get_product_id(DBusConnection *conn, -				DBusMessage *msg, void *data) +						DBusMessage *msg, void *data)  {  	struct input_device *idev = data;  	DBusMessage *reply; @@ -716,7 +736,7 @@ static DBusHandlerResult device_get_product_id(DBusConnection *conn,  }  static DBusHandlerResult device_get_vendor_id(DBusConnection *conn, -				DBusMessage *msg, void *data) +						DBusMessage *msg, void *data)  {  	struct input_device *idev = data;  	DBusMessage *reply; @@ -733,13 +753,13 @@ static DBusHandlerResult device_get_vendor_id(DBusConnection *conn,  }  static DBusHandlerResult device_set_timeout(DBusConnection *conn, -				DBusMessage *msg, void *data) +						DBusMessage *msg, void *data)  {  	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;  }  static DBusHandlerResult device_message(DBusConnection *conn, -		DBusMessage *msg, void *data) +						DBusMessage *msg, void *data)  {  	const char *iface, *member; @@ -791,19 +811,16 @@ static const DBusObjectPathVTable device_table = {  /*   * Input Manager methods   */ -struct input_manager { -	bdaddr_t sba;		/* Local adapter BT address */ -	GSList *paths;		/* Input registered paths */ -}; -  static void input_manager_free(struct input_manager *mgr)  {  	if (!mgr)  		return; +  	if (mgr->paths) {  		g_slist_foreach(mgr->paths, (GFunc) free, NULL);  		g_slist_free(mgr->paths);  	} +  	free(mgr);  } @@ -876,7 +893,7 @@ static int path_bdaddr_cmp(const char *path, const bdaddr_t *bdaddr)  }  static int get_record(struct pending_req *pr, uint32_t handle, -			DBusPendingCallNotifyFunction cb) +					DBusPendingCallNotifyFunction cb)  {  	DBusMessage *msg;  	DBusPendingCall *pending; @@ -906,7 +923,7 @@ static int get_record(struct pending_req *pr, uint32_t handle,  }  static int get_handles(struct pending_req *pr, const char *uuid, -			DBusPendingCallNotifyFunction cb) +					DBusPendingCallNotifyFunction cb)  {  	DBusMessage *msg;  	DBusPendingCall *pending; @@ -1068,9 +1085,12 @@ static void pnp_record_reply(DBusPendingCall *call, void *data)  		else  			goto done;  	} +  	err_failed(pr->conn, pr->msg, "SDP error"); +  fail:  	pending_req_free(pr); +  done:  	dbus_message_unref(reply);  	dbus_pending_call_unref(call); @@ -1115,15 +1135,17 @@ static void pnp_handle_reply(DBusPendingCall *call, void *data)  	}  	goto done; +  fail:  	pending_req_free(pr); +  done:  	dbus_message_unref(reply);  	dbus_pending_call_unref(call);  }  static DBusHandlerResult manager_create_device(DBusConnection *conn, -				DBusMessage *msg, void *data) +						DBusMessage *msg, void *data)  {  	struct input_manager *mgr = data;  	struct input_device *idev; @@ -1186,6 +1208,7 @@ static DBusHandlerResult manager_create_device(DBusConnection *conn,  		input_device_free(idev);  		return DBUS_HANDLER_RESULT_NEED_MEMORY;  	} +  	dbus_message_append_args(reply,  			DBUS_TYPE_STRING, &path,  			DBUS_TYPE_INVALID); @@ -1194,7 +1217,7 @@ static DBusHandlerResult manager_create_device(DBusConnection *conn,  }  static DBusHandlerResult manager_remove_device(DBusConnection *conn, -				DBusMessage *msg, void *data) +						DBusMessage *msg, void *data)  {  	struct input_manager *mgr = data;  	struct input_device *idev; @@ -1238,7 +1261,7 @@ static DBusHandlerResult manager_remove_device(DBusConnection *conn,  }  static DBusHandlerResult manager_list_devices(DBusConnection *conn, -				DBusMessage *msg, void *data) +						DBusMessage *msg, void *data)  {  	struct input_manager *mgr = data;  	DBusMessageIter iter, iter_array; @@ -1265,7 +1288,7 @@ static DBusHandlerResult manager_list_devices(DBusConnection *conn,  }  static DBusHandlerResult manager_message(DBusConnection *conn, -				DBusMessage *msg, void *data) +						DBusMessage *msg, void *data)  {  	const char *path, *iface, *member; @@ -1380,6 +1403,7 @@ int input_dbus_init(void)  	register_stored_inputs(connection, &sba);  	return 0; +  fail:  	input_manager_free(mgr); | 
