From 8a7d17430468d08c3d0660e2159cc046eebc5dfc Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Thu, 18 Jan 2007 13:42:11 +0000 Subject: Added methods skeleton --- input/input-api.txt | 93 ++++++++++++++++++ input/input-service.c | 267 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 253 insertions(+), 107 deletions(-) create mode 100644 input/input-api.txt 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 + +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 #endif -#include -#include +#include +#include +#include #include "dbus.h" #include "logging.h" +#include "input-service.h" +#include "glib-ectomy.h" #include +#include +#include +#include + +#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; } - -- cgit