Index: uspace/lib/c/generic/io/input.c
===================================================================
--- uspace/lib/c/generic/io/input.c	(revision 3a6d44b7107686f79a1655757bb73fedf182438b)
+++ uspace/lib/c/generic/io/input.c	(revision 7bcd15fa8041cc8c21cbf98b41cba30ec9aa11f3)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2022 Jiri Svoboda
  * All rights reserved.
  *
@@ -106,4 +106,5 @@
 static void input_ev_key(input_t *input, ipc_call_t *call)
 {
+	unsigned kbd_id;
 	kbd_event_type_t type;
 	keycode_t key;
@@ -112,10 +113,11 @@
 	errno_t rc;
 
-	type = ipc_get_arg1(call);
-	key = ipc_get_arg2(call);
-	mods = ipc_get_arg3(call);
-	c = ipc_get_arg4(call);
-
-	rc = input->ev_ops->key(input, type, key, mods, c);
+	kbd_id = ipc_get_arg1(call);
+	type = ipc_get_arg2(call);
+	key = ipc_get_arg3(call);
+	mods = ipc_get_arg4(call);
+	c = ipc_get_arg5(call);
+
+	rc = input->ev_ops->key(input, kbd_id, type, key, mods, c);
 	async_answer_0(call, rc);
 }
@@ -123,12 +125,14 @@
 static void input_ev_move(input_t *input, ipc_call_t *call)
 {
+	unsigned pos_id;
 	int dx;
 	int dy;
 	errno_t rc;
 
-	dx = ipc_get_arg1(call);
-	dy = ipc_get_arg2(call);
-
-	rc = input->ev_ops->move(input, dx, dy);
+	pos_id = ipc_get_arg1(call);
+	dx = ipc_get_arg2(call);
+	dy = ipc_get_arg3(call);
+
+	rc = input->ev_ops->move(input, pos_id, dx, dy);
 	async_answer_0(call, rc);
 }
@@ -136,4 +140,5 @@
 static void input_ev_abs_move(input_t *input, ipc_call_t *call)
 {
+	unsigned pos_id;
 	unsigned x;
 	unsigned y;
@@ -142,10 +147,11 @@
 	errno_t rc;
 
-	x = ipc_get_arg1(call);
-	y = ipc_get_arg2(call);
-	max_x = ipc_get_arg3(call);
-	max_y = ipc_get_arg4(call);
-
-	rc = input->ev_ops->abs_move(input, x, y, max_x, max_y);
+	pos_id = ipc_get_arg1(call);
+	x = ipc_get_arg2(call);
+	y = ipc_get_arg3(call);
+	max_x = ipc_get_arg4(call);
+	max_y = ipc_get_arg5(call);
+
+	rc = input->ev_ops->abs_move(input, pos_id, x, y, max_x, max_y);
 	async_answer_0(call, rc);
 }
@@ -153,12 +159,14 @@
 static void input_ev_button(input_t *input, ipc_call_t *call)
 {
+	unsigned pos_id;
 	int bnum;
 	int press;
 	errno_t rc;
 
-	bnum = ipc_get_arg1(call);
-	press = ipc_get_arg2(call);
-
-	rc = input->ev_ops->button(input, bnum, press);
+	pos_id = ipc_get_arg1(call);
+	bnum = ipc_get_arg2(call);
+	press = ipc_get_arg3(call);
+
+	rc = input->ev_ops->button(input, pos_id, bnum, press);
 	async_answer_0(call, rc);
 }
@@ -166,10 +174,12 @@
 static void input_ev_dclick(input_t *input, ipc_call_t *call)
 {
+	unsigned pos_id;
 	int bnum;
 	errno_t rc;
 
-	bnum = ipc_get_arg1(call);
-
-	rc = input->ev_ops->dclick(input, bnum);
+	pos_id = ipc_get_arg1(call);
+	bnum = ipc_get_arg2(call);
+
+	rc = input->ev_ops->dclick(input, pos_id, bnum);
 	async_answer_0(call, rc);
 }
Index: uspace/lib/c/include/io/input.h
===================================================================
--- uspace/lib/c/include/io/input.h	(revision 3a6d44b7107686f79a1655757bb73fedf182438b)
+++ uspace/lib/c/include/io/input.h	(revision 7bcd15fa8041cc8c21cbf98b41cba30ec9aa11f3)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2022 Jiri Svoboda
  * All rights reserved.
  *
@@ -50,9 +50,11 @@
 	errno_t (*active)(input_t *);
 	errno_t (*deactive)(input_t *);
-	errno_t (*key)(input_t *, kbd_event_type_t, keycode_t, keymod_t, char32_t);
-	errno_t (*move)(input_t *, int, int);
-	errno_t (*abs_move)(input_t *, unsigned, unsigned, unsigned, unsigned);
-	errno_t (*button)(input_t *, int, int);
-	errno_t (*dclick)(input_t *, int);
+	errno_t (*key)(input_t *, unsigned, kbd_event_type_t, keycode_t,
+	    keymod_t, char32_t);
+	errno_t (*move)(input_t *, unsigned, int, int);
+	errno_t (*abs_move)(input_t *, unsigned, unsigned, unsigned, unsigned,
+	    unsigned);
+	errno_t (*button)(input_t *, unsigned, int, int);
+	errno_t (*dclick)(input_t *, unsigned, int);
 } input_ev_ops_t;
 
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision 3a6d44b7107686f79a1655757bb73fedf182438b)
+++ uspace/srv/hid/console/console.c	(revision 7bcd15fa8041cc8c21cbf98b41cba30ec9aa11f3)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2022 Jiri Svoboda
  * Copyright (c) 2011 Martin Decky
  * All rights reserved.
@@ -120,9 +120,11 @@
 static errno_t input_ev_active(input_t *);
 static errno_t input_ev_deactive(input_t *);
-static errno_t input_ev_key(input_t *, kbd_event_type_t, keycode_t, keymod_t, char32_t);
-static errno_t input_ev_move(input_t *, int, int);
-static errno_t input_ev_abs_move(input_t *, unsigned, unsigned, unsigned, unsigned);
-static errno_t input_ev_button(input_t *, int, int);
-static errno_t input_ev_dclick(input_t *, int);
+static errno_t input_ev_key(input_t *, unsigned, kbd_event_type_t, keycode_t,
+    keymod_t, char32_t);
+static errno_t input_ev_move(input_t *, unsigned, int, int);
+static errno_t input_ev_abs_move(input_t *, unsigned, unsigned, unsigned,
+    unsigned, unsigned);
+static errno_t input_ev_button(input_t *, unsigned, int, int);
+static errno_t input_ev_dclick(input_t *, unsigned, int);
 
 static input_ev_ops_t input_ev_ops = {
@@ -357,6 +359,6 @@
 }
 
-static errno_t input_ev_key(input_t *input, kbd_event_type_t type, keycode_t key,
-    keymod_t mods, char32_t c)
+static errno_t input_ev_key(input_t *input, unsigned kbd_id,
+    kbd_event_type_t type, keycode_t key, keymod_t mods, char32_t c)
 {
 	cons_event_t event;
@@ -369,4 +371,5 @@
 		event.type = CEV_KEY;
 
+		(void)kbd_id;
 		event.ev.key.type = type;
 		event.ev.key.key = key;
@@ -417,20 +420,25 @@
 }
 
-static errno_t input_ev_move(input_t *input, int dx, int dy)
-{
+static errno_t input_ev_move(input_t *input, unsigned pos_id, int dx, int dy)
+{
+	(void) pos_id;
 	pointer_update(pointer_x + dx, pointer_y + dy);
 	return EOK;
 }
 
-static errno_t input_ev_abs_move(input_t *input, unsigned x, unsigned y,
-    unsigned max_x, unsigned max_y)
-{
+static errno_t input_ev_abs_move(input_t *input, unsigned pos_id, unsigned x,
+    unsigned y, unsigned max_x, unsigned max_y)
+{
+	(void)pos_id;
 	pointer_update(mouse_scale_x * cols * x / max_x, mouse_scale_y * rows * y / max_y);
 	return EOK;
 }
 
-static errno_t input_ev_button(input_t *input, int bnum, int bpress)
+static errno_t input_ev_button(input_t *input, unsigned pos_id, int bnum,
+    int bpress)
 {
 	cons_event_t event;
+
+	(void)pos_id;
 
 	event.type = CEV_POS;
@@ -444,7 +452,9 @@
 }
 
-static errno_t input_ev_dclick(input_t *input, int bnum)
+static errno_t input_ev_dclick(input_t *input, unsigned pos_id, int bnum)
 {
 	cons_event_t event;
+
+	(void)pos_id;
 
 	event.type = CEV_POS;
Index: uspace/srv/hid/display/input.c
===================================================================
--- uspace/srv/hid/display/input.c	(revision 3a6d44b7107686f79a1655757bb73fedf182438b)
+++ uspace/srv/hid/display/input.c	(revision 7bcd15fa8041cc8c21cbf98b41cba30ec9aa11f3)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2022 Jiri Svoboda
  * All rights reserved.
  *
@@ -45,9 +45,11 @@
 static errno_t ds_input_ev_active(input_t *);
 static errno_t ds_input_ev_deactive(input_t *);
-static errno_t ds_input_ev_key(input_t *, kbd_event_type_t, keycode_t, keymod_t, char32_t);
-static errno_t ds_input_ev_move(input_t *, int, int);
-static errno_t ds_input_ev_abs_move(input_t *, unsigned, unsigned, unsigned, unsigned);
-static errno_t ds_input_ev_button(input_t *, int, int);
-static errno_t ds_input_ev_dclick(input_t *, int);
+static errno_t ds_input_ev_key(input_t *, unsigned, kbd_event_type_t, keycode_t,
+    keymod_t, char32_t);
+static errno_t ds_input_ev_move(input_t *, unsigned, int, int);
+static errno_t ds_input_ev_abs_move(input_t *, unsigned, unsigned, unsigned,
+    unsigned, unsigned);
+static errno_t ds_input_ev_button(input_t *, unsigned, int, int);
+static errno_t ds_input_ev_dclick(input_t *, unsigned, int);
 
 static input_ev_ops_t ds_input_ev_ops = {
@@ -71,10 +73,12 @@
 }
 
-static errno_t ds_input_ev_key(input_t *input, kbd_event_type_t type,
-    keycode_t key, keymod_t mods, char32_t c)
+static errno_t ds_input_ev_key(input_t *input, unsigned kbd_id,
+    kbd_event_type_t type, keycode_t key, keymod_t mods, char32_t c)
 {
 	ds_display_t *disp = (ds_display_t *) input->user;
 	kbd_event_t event;
 	errno_t rc;
+
+	(void)kbd_id;
 
 	event.type = type;
@@ -89,10 +93,11 @@
 }
 
-static errno_t ds_input_ev_move(input_t *input, int dx, int dy)
-{
-	ds_display_t *disp = (ds_display_t *) input->user;
-	ptd_event_t event;
-	errno_t rc;
-
+static errno_t ds_input_ev_move(input_t *input, unsigned pos_id, int dx, int dy)
+{
+	ds_display_t *disp = (ds_display_t *) input->user;
+	ptd_event_t event;
+	errno_t rc;
+
+	event.pos_id = pos_id;
 	event.type = PTD_MOVE;
 	event.dmove.x = dx;
@@ -105,11 +110,12 @@
 }
 
-static errno_t ds_input_ev_abs_move(input_t *input, unsigned x, unsigned y,
-    unsigned max_x, unsigned max_y)
-{
-	ds_display_t *disp = (ds_display_t *) input->user;
-	ptd_event_t event;
-	errno_t rc;
-
+static errno_t ds_input_ev_abs_move(input_t *input, unsigned pos_id, unsigned x,
+    unsigned y, unsigned max_x, unsigned max_y)
+{
+	ds_display_t *disp = (ds_display_t *) input->user;
+	ptd_event_t event;
+	errno_t rc;
+
+	event.pos_id = pos_id;
 	event.type = PTD_ABS_MOVE;
 	event.apos.x = x;
@@ -126,10 +132,12 @@
 }
 
-static errno_t ds_input_ev_button(input_t *input, int bnum, int bpress)
-{
-	ds_display_t *disp = (ds_display_t *) input->user;
-	ptd_event_t event;
-	errno_t rc;
-
+static errno_t ds_input_ev_button(input_t *input, unsigned pos_id, int bnum,
+    int bpress)
+{
+	ds_display_t *disp = (ds_display_t *) input->user;
+	ptd_event_t event;
+	errno_t rc;
+
+	event.pos_id = pos_id;
 	event.type = bpress ? PTD_PRESS : PTD_RELEASE;
 	event.btn_num = bnum;
@@ -143,10 +151,11 @@
 }
 
-static errno_t ds_input_ev_dclick(input_t *input, int bnum)
-{
-	ds_display_t *disp = (ds_display_t *) input->user;
-	ptd_event_t event;
-	errno_t rc;
-
+static errno_t ds_input_ev_dclick(input_t *input, unsigned pos_id, int bnum)
+{
+	ds_display_t *disp = (ds_display_t *) input->user;
+	ptd_event_t event;
+	errno_t rc;
+
+	event.pos_id = pos_id;
 	event.type = PTD_DCLICK;
 	event.btn_num = bnum;
Index: uspace/srv/hid/display/seat.c
===================================================================
--- uspace/srv/hid/display/seat.c	(revision 3a6d44b7107686f79a1655757bb73fedf182438b)
+++ uspace/srv/hid/display/seat.c	(revision 7bcd15fa8041cc8c21cbf98b41cba30ec9aa11f3)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2022 Jiri Svoboda
  * All rights reserved.
  *
@@ -364,5 +364,5 @@
 	if (event->type == PTD_PRESS || event->type == PTD_RELEASE ||
 	    event->type == PTD_DCLICK) {
-		pevent.pos_id = 0;
+		pevent.pos_id = event->pos_id;
 		switch (event->type) {
 		case PTD_PRESS:
@@ -395,5 +395,5 @@
 		seat->pntpos = npos;
 
-		pevent.pos_id = 0;
+		pevent.pos_id = event->pos_id;
 		pevent.type = POS_UPDATE;
 		pevent.btn_num = 0;
@@ -423,5 +423,5 @@
 		seat->pntpos = npos;
 
-		pevent.pos_id = 0;
+		pevent.pos_id = event->pos_id;
 		pevent.type = POS_UPDATE;
 		pevent.btn_num = 0;
Index: uspace/srv/hid/display/types/display/ptd_event.h
===================================================================
--- uspace/srv/hid/display/types/display/ptd_event.h	(revision 3a6d44b7107686f79a1655757bb73fedf182438b)
+++ uspace/srv/hid/display/types/display/ptd_event.h	(revision 7bcd15fa8041cc8c21cbf98b41cba30ec9aa11f3)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2022 Jiri Svoboda
  * All rights reserved.
  *
@@ -48,4 +48,7 @@
 /** Pointing device event */
 typedef struct {
+	/** Positioning device ID */
+	unsigned pos_id;
+	/** PTD event type */
 	ptd_event_type_t type;
 	/** Button number for PTD_PRESS or PTD_RELEASE */
Index: uspace/srv/hid/input/input.c
===================================================================
--- uspace/srv/hid/input/input.c	(revision 3a6d44b7107686f79a1655757bb73fedf182438b)
+++ uspace/srv/hid/input/input.c	(revision 7bcd15fa8041cc8c21cbf98b41cba30ec9aa11f3)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2021 Jiri Svoboda
+ * Copyright (c) 2022 Jiri Svoboda
  * Copyright (c) 2006 Josef Cejka
  * All rights reserved.
@@ -253,5 +253,6 @@
 		if (client->active) {
 			async_exch_t *exch = async_exchange_begin(client->sess);
-			async_msg_4(exch, INPUT_EVENT_KEY, ev.type, ev.key, ev.mods, ev.c);
+			async_msg_5(exch, INPUT_EVENT_KEY, kdev->svc_id,
+			    ev.type, ev.key, ev.mods, ev.c);
 			async_exchange_end(exch);
 		}
@@ -267,5 +268,6 @@
 
 			if ((dx) || (dy))
-				async_msg_2(exch, INPUT_EVENT_MOVE, dx, dy);
+				async_msg_3(exch, INPUT_EVENT_MOVE,
+				    mdev->svc_id, dx, dy);
 
 			if (dz) {
@@ -274,7 +276,10 @@
 
 				for (unsigned int i = 0; i < 3; i++)
-					async_msg_4(exch, INPUT_EVENT_KEY, KEY_PRESS, code, 0, 0);
-
-				async_msg_4(exch, INPUT_EVENT_KEY, KEY_RELEASE, code, 0, 0);
+					async_msg_5(exch, INPUT_EVENT_KEY,
+					    0 /* XXX kbd_id */,
+					    KEY_PRESS, code, 0, 0);
+
+				async_msg_5(exch, INPUT_EVENT_KEY, KEY_RELEASE,
+				    0 /* XXX kbd_id */, code, 0, 0);
 			}
 
@@ -292,5 +297,6 @@
 			if ((max_x) && (max_y)) {
 				async_exch_t *exch = async_exchange_begin(client->sess);
-				async_msg_4(exch, INPUT_EVENT_ABS_MOVE, x, y, max_x, max_y);
+				async_msg_5(exch, INPUT_EVENT_ABS_MOVE,
+				    mdev->svc_id, x, y, max_x, max_y);
 				async_exchange_end(exch);
 			}
@@ -305,5 +311,6 @@
 		if (client->active) {
 			async_exch_t *exch = async_exchange_begin(client->sess);
-			async_msg_2(exch, INPUT_EVENT_BUTTON, bnum, press);
+			async_msg_3(exch, INPUT_EVENT_BUTTON, mdev->svc_id,
+			    bnum, press);
 			async_exchange_end(exch);
 		}
@@ -317,5 +324,6 @@
 		if (client->active) {
 			async_exch_t *exch = async_exchange_begin(client->sess);
-			async_msg_1(exch, INPUT_EVENT_DCLICK, bnum);
+			async_msg_2(exch, INPUT_EVENT_DCLICK, mdev->svc_id,
+			    bnum);
 			async_exchange_end(exch);
 		}
