[RFC generichid 4/5]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Adds the rest of the keyboard functions.

 input/generichid.c |  175 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 175 insertions(+), 0 deletions(-)

diff --git a/input/generichid.c b/input/generichid.c
index 3a5f073..42d6a29 100644
--- a/input/generichid.c
+++ b/input/generichid.c
@@ -363,10 +363,185 @@ static void initiate_keyboard(struct
keyboard_state *keyboard)
 	keyboard->last_value = 3;
 }

+static char is_control(unsigned char code)
+{
+	unsigned char hidcode = keycode2hidp[code];
+
+	if (hidcode >= 224 && hidcode <= 231)
+		return 1;
+
+	return 0;
+}
+
+static unsigned char mask(unsigned char code)
+{
+	unsigned char hidcode = keycode2hidp[code];
+
+	return 1 << (hidcode - 224);
+}
+
+static int key_up(struct keyboard_state *keyboard, unsigned char code)
+{
+    unsigned char i;
+
+    for (i = 4; i <= keyboard->last_value &&
+            keyboard->value[i] != keycode2hidp[code]; i++)
+        ;
+
+    if (i > keyboard->last_value)
+        return -EINVAL;
+
+    keyboard->value[i] = keyboard->value[keyboard->last_value];
+    keyboard->value[keyboard->last_value] = 0;
+    keyboard->last_value--;
+
+    return 0;
+}
+
+static int key_down(struct keyboard_state *keyboard, unsigned char code)
+{
+	int i;
+	unsigned char keycode;
+
+	keycode = keycode2hidp[code];
+	for (i = 4; i <= keyboard->last_value; i++)
+		if (keyboard->value[i] == keycode)
+			return 0;
+
+	if (keyboard->last_value == HIDP_KEYB_SIZE - 1)
+		return -EPERM;
+
+	keyboard->last_value++;
+	keyboard->value[keyboard->last_value] = keycode;
+
+	return 0;
+}
+
+static DBusMessage *phantom_state(GIOChannel *chan,
+		struct keyboard_state *keyboard, DBusMessage *msg)
+{
+	int fd, err;
+	unsigned char value[10];
+
+	value[0] = 0xa1;
+	value[1] = 0x01;
+	value[2] = value[3] = 0;
+
+	/* phantom state */
+	memset(&value[4], 1, 6);
+
+	if (chan == NULL)
+		return btd_error_not_connected(msg);
+
+	fd = g_io_channel_unix_get_fd(chan);
+
+	err = write(fd, value, HIDP_KEYB_SIZE);
+	if (err < 0)
+		return btd_error_not_connected(msg);
+
+	return NULL;
+}
+
+static DBusMessage *send_report(GIOChannel *chan,
+		struct keyboard_state *keyboard, DBusMessage *msg)
+{
+	int fd, err;
+
+	if (chan == NULL)
+		return btd_error_not_connected(msg);;
+
+	fd = g_io_channel_unix_get_fd(chan);
+
+	err = write(fd, keyboard->value, HIDP_KEYB_SIZE);
+	if (err < 0)
+		return btd_error_not_connected(msg);
+
+	return NULL;
+}
+
+
+
+static DBusMessage *keyboard_event(GIOChannel *chan, DBusMessage *msg,
+					struct keyboard_state *keyboard,
+					unsigned char code,
+					char value)
+{
+	DBusMessage *ret_msg;
+	int err = 0;
+
+	if (is_control(code)) {
+
+		if (value)
+			keyboard->value[2] |= mask(code);
+		else
+			keyboard->value[2] &= ~mask(code);
+
+	} else {
+
+		if (value)
+			err = key_down(keyboard, code);
+		else
+			err = key_up(keyboard, code);
+	}
+
+	if (err < 0) {
+
+		ret_msg = phantom_state(chan, keyboard, msg);
+
+		if (ret_msg)
+			return ret_msg;
+
+		return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+	}
+
+	ret_msg = send_report(chan, keyboard, msg);
+
+	if (ret_msg)
+		return ret_msg;
+
+	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+

 static DBusMessage *send_event(DBusConnection *conn,
 		DBusMessage *msg, void *data)
 {
+	DBusMessageIter iter;
+	char mode, value;
+	unsigned int code;
+	struct adapter_data *adapt = data;
+	struct device_data *dev = adapt->dev;
+
+	if (!dbus_message_iter_init(msg, &iter))
+			return btd_error_invalid_args(msg);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BYTE)
+		return btd_error_invalid_args(msg);
+
+	dbus_message_iter_get_basic(&iter, &mode);
+	dbus_message_iter_next(&iter);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT16)
+		return btd_error_invalid_args(msg);
+
+	dbus_message_iter_get_basic(&iter, &code);
+	dbus_message_iter_next(&iter);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BYTE)
+		return btd_error_invalid_args(msg);
+
+	dbus_message_iter_get_basic(&iter, &value);
+
+	if (dev->intr == NULL)
+		return btd_error_not_connected(msg);
+
+	if (mode == EV_KEY) /* keboard */
+		return keyboard_event(dev->intr, msg,
+					&(dev->keyboard),
+					(unsigned char) code, value);
+
+
 	return btd_error_failed(msg, "Invalid profile mode");
 }
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux