summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--input/input-api.txt93
-rw-r--r--input/input-service.c267
2 files changed, 253 insertions, 107 deletions
diff --git a/input/input-api.txt b/input/input-api.txt
new file mode 100644
index 00000000..f321ac2b
--- /dev/null
+++ b/input/input-api.txt
@@ -0,0 +1,93 @@
+Bluetooth input service API description
+******************************************
+
+Copyright (C) 2006-2007 Marcel Holtmann <marcel@holtmann.org>
+
+Error hierarchy
+===============
+
+Interface org.bluez.Error
+
+Errors Failed
+
+ An unknown error occured. The error messages is
+ taken from the strerror(errno) function.
+
+ UnknownDevice
+
+ Error returned when the input device path is invalid
+
+ UnknownMethod
+
+ Error returned when the input device path doesn't
+ implement the requested method.
+
+
+Input Manager hierarchy
+=================
+
+Service org.bluez.input
+Interface org.bluez.input.Manager
+Object path /org/bluez/input
+
+Methods
+ array{string} ListDevices()
+
+ Returns an array of available input devices path.
+
+ void CreateDevice(string address)
+
+ Create an input device object: HID service record is
+ retrieved and bonding(if applied) is created.
+
+ void RemoveDevice(string path)
+
+ Remove the input device object for a given path.
+
+
+Input hierarchy
+=================
+
+Service org.bluez.input
+Interface org.bluez.input
+Object path /org/bluez/input_*
+
+Methods string GetAddress()
+
+ Returns the device address.
+
+ Example: "00:11:22:33:44:55"
+
+ string GetName()
+
+ Returns the service name.
+
+ string GetProductId()
+
+ Returns the product id.
+
+ string GetVendorId()
+
+ Returns the vendor id.
+
+ boolean IsConnected()
+
+ Returns the connection status.
+
+ void Connect()
+
+ Connect to the input device.
+
+ void Disconnect()
+
+ Disconnect from the input device.
+
+ void Unplug()
+
+ Unplug the virtual cable device.
+
+ void SetTimeout(uint32 timeout)
+
+ Set the idle timeout.
+
+
diff --git a/input/input-service.c b/input/input-service.c
index accb17c9..54e745a4 100644
--- a/input/input-service.c
+++ b/input/input-service.c
@@ -25,173 +25,226 @@
#include <config.h>
#endif
-#include <string.h>
-#include <signal.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
#include "dbus.h"
#include "logging.h"
+#include "input-service.h"
+#include "glib-ectomy.h"
#include <dbus/dbus.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+
+#define INPUT_SERVICE "org.bluez.input"
#define INPUT_PATH "/org/bluez/input"
+#define INPUT_MANAGER_INTERFACE "org.bluez.input.Manager"
+#define INPUT_DEVICE_INTERFACE "org.bluez.input.Device"
+#define INPUT_ERROR_INTERFACE "org.bluez.Error"
-static int started = 0;
static DBusConnection *connection = NULL;
-static DBusHandlerResult start_message(DBusConnection *conn,
- DBusMessage *msg, void *data)
-{
- DBusMessage *reply;
+static DBusHandlerResult manager_message(DBusConnection *conn,
+ DBusMessage *msg, void *data);
+static DBusHandlerResult device_message(DBusConnection *conn,
+ DBusMessage *msg, void *data);
- info("Starting input service");
+static const DBusObjectPathVTable manager_table = {
+ .message_function = manager_message,
+};
- reply = dbus_message_new_method_return(msg);
- if (!reply) {
- error("Can't create reply message");
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
- }
+static const DBusObjectPathVTable device_table = {
+ .message_function = device_message,
+};
- dbus_connection_send(conn, reply, NULL);
+/*
+ * Common D-Bus BlueZ input error functions
+ */
+static DBusHandlerResult err_unknown_device(DBusConnection *conn, DBusMessage *msg)
+{
+ return send_message_and_unref(conn,
+ dbus_message_new_error(msg,
+ INPUT_ERROR_INTERFACE ".UnknownDevice",
+ "Invalid device"));
+}
- dbus_message_unref(reply);
+static DBusHandlerResult err_unknown_method(DBusConnection *conn, DBusMessage *msg)
+{
+ return send_message_and_unref(conn,
+ dbus_message_new_error(msg,
+ INPUT_ERROR_INTERFACE ".UnknownMethod",
+ "Unknown input method"));
+}
- started = 1;
+/*
+ * Input Manager methods
+ */
+static DBusHandlerResult manager_create_device(DBusConnection *conn,
+ DBusMessage *msg, void *udata)
+{
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
- return DBUS_HANDLER_RESULT_HANDLED;
+static DBusHandlerResult manager_remove_device(DBusConnection *conn,
+ DBusMessage *msg, void *udata)
+{
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
-static DBusHandlerResult stop_message(DBusConnection *conn,
- DBusMessage *msg, void *data)
+static DBusHandlerResult manager_list_devices(DBusConnection *conn,
+ DBusMessage *msg, void *udata)
{
- DBusMessage *reply;
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
- info("Stopping input service");
+static DBusHandlerResult manager_message(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ const char *path, *iface, *member;
- reply = dbus_message_new_method_return(msg);
- if (!reply) {
- error("Can't create reply message");
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
- }
+ path = dbus_message_get_path(msg);
+ iface = dbus_message_get_interface(msg);
+ member = dbus_message_get_member(msg);
+
+ /* Catching fallback paths */
+ if (strcmp(INPUT_PATH, path) != 0)
+ return err_unknown_device(conn, msg);
+
+ /* Accept messages from the input manager interface only */
+ if (strcmp(INPUT_MANAGER_INTERFACE, iface))
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- dbus_connection_send(conn, reply, NULL);
+ if (strcmp(member, "ListDevices") == 0)
+ return manager_list_devices(conn, msg, data);
- dbus_message_unref(reply);
+ if (strcmp(member, "CreateDevice") == 0)
+ return manager_create_device(conn, msg, data);
- started = 0;
+ if (strcmp(member, "RemoveDevice") == 0)
+ return manager_remove_device(conn, msg, data);
- return DBUS_HANDLER_RESULT_HANDLED;
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
-static DBusHandlerResult release_message(DBusConnection *conn,
- DBusMessage *msg, void *data)
+/*
+ * Input Device methods
+ */
+static DBusHandlerResult device_connect(DBusConnection *conn,
+ DBusMessage *msg, void *udata)
{
- DBusMessage *reply;
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
- reply = dbus_message_new_method_return(msg);
- if (!reply) {
- error("Can't create reply message");
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
- }
+static DBusHandlerResult device_disconnect(DBusConnection *conn,
+ DBusMessage *msg, void *udata)
+{
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
- dbus_connection_send(conn, reply, NULL);
+static DBusHandlerResult device_unplug(DBusConnection *conn,
+ DBusMessage *msg, void *udata)
+{
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
- dbus_message_unref(reply);
+static DBusHandlerResult device_is_connected(DBusConnection *conn,
+ DBusMessage *msg, void *udata)
+{
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
- info("Got Release method. Exiting.");
+static DBusHandlerResult device_get_address(DBusConnection *conn,
+ DBusMessage *msg, void *udata)
+{
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
- raise(SIGTERM);
+static DBusHandlerResult device_get_name(DBusConnection *conn,
+ DBusMessage *msg, void *udata)
+{
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
- return DBUS_HANDLER_RESULT_HANDLED;
+static DBusHandlerResult device_get_product_id(DBusConnection *conn,
+ DBusMessage *msg, void *udata)
+{
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
-static DBusHandlerResult input_message(DBusConnection *conn,
- DBusMessage *msg, void *data)
+static DBusHandlerResult device_get_vendor_id(DBusConnection *conn,
+ DBusMessage *msg, void *udata)
+{
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusHandlerResult device_set_timeout(DBusConnection *conn,
+ DBusMessage *msg, void *udata)
+{
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
+static DBusHandlerResult device_message(DBusConnection *conn,
+ DBusMessage *msg, void *data)
{
- const char *interface;
- const char *member;
+ const char *iface, *member;
- interface = dbus_message_get_interface(msg);
+ iface = dbus_message_get_interface(msg);
member = dbus_message_get_member(msg);
- if (strcmp(interface, "org.bluez.ServiceAgent") == 0) {
- if (strcmp(member, "Start") == 0)
- return start_message(conn, msg, data);
- if (strcmp(member, "Stop") == 0)
- return stop_message(conn, msg, data);
- if (strcmp(member, "Release") == 0)
- return release_message(conn, msg, data);
+ /* Accept messages from the input interface only */
+ if (strcmp(INPUT_DEVICE_INTERFACE, iface))
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- }
- if (strcmp(interface, "org.bluez.Input") != 0)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ if (strcmp(member, "Connect") == 0)
+ return device_connect(conn, msg, data);
- /* Handle Input interface methods here */
+ if (strcmp(member, "Disconnect") == 0)
+ return device_disconnect(conn, msg, data);
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
+ if (strcmp(member, "Unplug") == 0)
+ return device_unplug(conn, msg, data);
-static const DBusObjectPathVTable input_table = {
- .message_function = input_message,
-};
+ if (strcmp(member, "IsConnected") == 0)
+ return device_is_connected(conn, msg, data);
-static void register_reply(DBusPendingCall *call, void *data)
-{
- DBusMessage *reply = dbus_pending_call_steal_reply(call);
- DBusError err;
+ if (strcmp(member, "GetAddress") == 0)
+ return device_get_address(conn, msg, data);
- dbus_error_init(&err);
- if (dbus_set_error_from_message(&err, reply)) {
- error("Registering failed: %s", err.message);
- dbus_error_free(&err);
- raise(SIGTERM);
- }
- else
- debug("Successfully registered");
+ if (strcmp(member, "GetName") == 0)
+ return device_get_name(conn, msg, data);
+
+ if (strcmp(member, "GetProductId") == 0)
+ return device_get_product_id(conn, msg, data);
+
+ if (strcmp(member, "GetVendorId") == 0)
+ return device_get_vendor_id(conn, msg, data);
+
+ if (strcmp(member, "SetTimeout") == 0)
+ return device_set_timeout(conn, msg, data);
- dbus_message_unref(reply);
+ return err_unknown_method(conn, msg);
}
int input_dbus_init(void)
{
- DBusMessage *msg;
- DBusPendingCall *pending;
- const char *name = "Input service";
- const char *description = "A service for input devices";
- const char *input_path = INPUT_PATH;
-
- connection = init_dbus("org.bluez.input", NULL, NULL);
+ connection = init_dbus(INPUT_SERVICE, NULL, NULL);
if (!connection)
return -1;
- if (!dbus_connection_register_object_path(connection, input_path,
- &input_table, NULL)) {
+ /* Fallback to catch invalid device path */
+ if (!dbus_connection_register_fallback(connection, INPUT_PATH,
+ &manager_table, NULL)) {
error("D-Bus failed to register %s path", INPUT_PATH);
return -1;
}
- msg = dbus_message_new_method_call("org.bluez", "/org/bluez",
- "org.bluez.Manager", "RegisterService");
- if (!msg) {
- error("Can't allocate new method call");
- return -1;
- }
-
- dbus_message_append_args(msg, DBUS_TYPE_STRING, &input_path,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_STRING, &description,
- DBUS_TYPE_INVALID);
-
- if (!dbus_connection_send_with_reply(connection, msg, &pending, -1)) {
- error("Sending Register method call failed");
- dbus_message_unref(msg);
- return -1;
- }
-
- dbus_pending_call_set_notify(pending, register_reply, NULL, NULL);
- dbus_message_unref(msg);
+ info("Registered input manager path:%s", INPUT_PATH);
return 0;
}
-