Index: uspace/srv/hid/remcons/user.c
===================================================================
--- uspace/srv/hid/remcons/user.c	(revision 89e5c0c74547ac080d125e5482bd7736822f26de)
+++ uspace/srv/hid/remcons/user.c	(revision d05c2377b4a3f7c8e4909dd03fadff4954375186)
@@ -83,5 +83,4 @@
 	user->conn = conn;
 	user->service_id = (service_id_t) -1;
-	prodcons_initialize(&user->in_events);
 	link_initialize(&user->link);
 	user->socket_buffer_len = 0;
@@ -211,7 +210,9 @@
 }
 
-/** Receive next byte from a socket (use buffering.
- * We need to return the value via extra argument because the read byte
- * might be negative.
+/** Receive next byte from a socket (use buffering).
+ *
+ * @param user Telnet user
+ * @param byte Place to store the received byte
+ * @return EOK on success or an error code
  */
 static errno_t telnet_user_recv_next_byte_locked(telnet_user_t *user, char *byte)
@@ -230,57 +231,12 @@
 }
 
-errno_t telnet_user_recv(telnet_user_t *user, void *data, size_t size,
-    size_t *nread)
-{
-	errno_t rc;
-	size_t nb;
-
-	/* No more buffered data? */
-	if (user->socket_buffer_len <= user->socket_buffer_pos) {
-		rc = telnet_user_fill_recv_buf(user);
-		if (rc != EOK)
-			return rc;
-	}
-
-	nb = user->socket_buffer_len - user->socket_buffer_pos;
-	memcpy(data, user->socket_buffer + user->socket_buffer_pos, nb);
-	user->socket_buffer_pos += nb;
-	*nread = nb;
-	return EOK;
-}
-
-/** Creates new keyboard event from given char.
- *
- * @param type Event type (press / release).
- * @param c Pressed character.
- */
-static kbd_event_t *new_kbd_event(kbd_event_type_t type, char32_t c)
-{
-	kbd_event_t *event = malloc(sizeof(kbd_event_t));
-	assert(event);
-
-	link_initialize(&event->link);
-	event->type = type;
-	event->c = c;
-	event->mods = 0;
-
-	switch (c) {
-	case '\n':
-		event->key = KC_ENTER;
-		break;
-	case '\t':
-		event->key = KC_TAB;
-		break;
-	case '\b':
-	case 127: /* This is what Linux telnet sends. */
-		event->key = KC_BACKSPACE;
-		event->c = '\b';
-		break;
-	default:
-		event->key = KC_A;
-		break;
-	}
-
-	return event;
+/** Determine if a received byte is available without waiting.
+ *
+ * @param user Telnet user
+ * @return @c true iff a byte is currently available
+ */
+static bool telnet_user_byte_avail(telnet_user_t *user)
+{
+	return user->socket_buffer_len > user->socket_buffer_pos;
 }
 
@@ -303,14 +259,22 @@
 }
 
-/** Get next keyboard event.
+/** Receive data from telnet connection.
  *
  * @param user Telnet user.
- * @param event Where to store the keyboard event.
- * @return Error code.
- */
-errno_t telnet_user_get_next_keyboard_event(telnet_user_t *user, kbd_event_t *event)
-{
-	fibril_mutex_lock(&user->guard);
-	if (list_empty(&user->in_events.list)) {
+ * @param buf Destination buffer
+ * @param size Buffer size
+ * @param nread Place to store number of bytes read (>0 on success)
+ * @return EOK on success or an error code
+ */
+errno_t telnet_user_recv(telnet_user_t *user, void *buf, size_t size,
+    size_t *nread)
+{
+	uint8_t *bp = (uint8_t *)buf;
+	fibril_mutex_lock(&user->guard);
+
+	assert(size > 0);
+	*nread = 0;
+
+	do {
 		char next_byte = 0;
 		bool inside_telnet_command = false;
@@ -319,13 +283,12 @@
 
 		/* Skip zeros, bail-out on error. */
-		while (next_byte == 0) {
-			fibril_mutex_unlock(&user->guard);
-
-			errno_t rc = telnet_user_recv_next_byte_locked(user, &next_byte);
-			if (rc != EOK)
+		do {
+			errno_t rc = telnet_user_recv_next_byte_locked(user,
+			    &next_byte);
+			if (rc != EOK) {
+				fibril_mutex_unlock(&user->guard);
 				return rc;
-
+			}
 			uint8_t byte = (uint8_t) next_byte;
-			fibril_mutex_lock(&user->guard);
 
 			/* Skip telnet commands. */
@@ -345,5 +308,5 @@
 				next_byte = 0;
 			}
-		}
+		} while (next_byte == 0 && telnet_user_byte_avail(user));
 
 		/* CR-LF conversions. */
@@ -352,21 +315,12 @@
 		}
 
-		kbd_event_t *down = new_kbd_event(KEY_PRESS, next_byte);
-		kbd_event_t *up = new_kbd_event(KEY_RELEASE, next_byte);
-		assert(down);
-		assert(up);
-		prodcons_produce(&user->in_events, &down->link);
-		prodcons_produce(&user->in_events, &up->link);
-	}
-
-	link_t *link = prodcons_consume(&user->in_events);
-	kbd_event_t *tmp = list_get_instance(link, kbd_event_t, link);
-
-	fibril_mutex_unlock(&user->guard);
-
-	*event = *tmp;
-
-	free(tmp);
-
+		if (next_byte != 0) {
+			*bp++ = next_byte;
+			++*nread;
+			--size;
+		}
+	} while (size > 0 && (telnet_user_byte_avail(user) || *nread == 0));
+
+	fibril_mutex_unlock(&user->guard);
 	return EOK;
 }
