summaryrefslogtreecommitdiffstats
path: root/hcid
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2005-10-09 22:15:21 +0000
committerMarcel Holtmann <marcel@holtmann.org>2005-10-09 22:15:21 +0000
commit34e266aaa88d0ff1e5930946d96783420c232895 (patch)
tree9c5ccf044fd4cc8cf3d60579c25cb8c8bde1dc78 /hcid
parent3e077cde783d52817e9934681699c51994ba2031 (diff)
Add basic rough version of the D-Bus support
Diffstat (limited to 'hcid')
-rw-r--r--hcid/Makefile.am4
-rw-r--r--hcid/dbus.c977
-rw-r--r--hcid/dbus.h180
-rw-r--r--hcid/hcid.h35
-rw-r--r--hcid/main.c14
5 files changed, 1182 insertions, 28 deletions
diff --git a/hcid/Makefile.am b/hcid/Makefile.am
index 875de7cd..7f235c73 100644
--- a/hcid/Makefile.am
+++ b/hcid/Makefile.am
@@ -13,7 +13,7 @@ state_DATA =
sbin_PROGRAMS = hcid
if DBUS
-dbus_hcid_sources = dbus.c
+dbus_hcid_sources = dbus.h dbus.c
dbus_hcid_libs = @DBUS_LIBS@
dbus_hcid_cflags = -DENABLE_DBUS -DDBUS_API_SUBJECT_TO_CHANGE
else
@@ -35,7 +35,7 @@ AM_YFLAGS = -d
CLEANFILES = lexer.c parser.c parser.h
-EXTRA_DIST = $(man_MANS) $(conf_DATA) dbus.c
+EXTRA_DIST = $(man_MANS) $(conf_DATA) dbus.h dbus.c
MAINTAINERCLEANFILES = Makefile.in
diff --git a/hcid/dbus.c b/hcid/dbus.c
index 39daf783..36fd476c 100644
--- a/hcid/dbus.c
+++ b/hcid/dbus.c
@@ -33,6 +33,10 @@
#endif
#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/syslog.h>
@@ -45,23 +49,187 @@
#include "glib-ectomy.h"
#include "hcid.h"
+#include "dbus.h"
static DBusConnection *connection;
+static int num_adapters = 0;
#define TIMEOUT (30 * 1000) /* 30 seconds */
+#define BLUETOOTH_DEVICE_NAME_LEN (18)
+#define BLUETOOTH_DEVICE_ADDR_LEN (18)
+#define MAX_PATH_LENGTH (64)
-#define SERVICE_NAME "org.bluez.PinAgent"
-#define INTERFACE_NAME SERVICE_NAME
-#define REQUEST_NAME "PinRequest"
-#define PATH_NAME "/org/bluez/PinAgent"
-
-#define WRONG_ARGS_ERROR "org.bluez.Error.WrongArgs"
+#define PINAGENT_SERVICE_NAME BASE_INTERFACE ".PinAgent"
+#define PINAGENT_INTERFACE PINAGENT_SERVICE_NAME
+#define PIN_REQUEST "PinRequest"
+#define PINAGENT_PATH BASE_PATH "/PinAgent"
struct pin_request {
int dev;
bdaddr_t bda;
};
+typedef DBusMessage* (service_handler_func_t)(DBusMessage *, void *);
+
+struct service_data {
+ const char *name;
+ service_handler_func_t *handler_func;
+ const char *signature;
+};
+
+typedef int register_function_t(DBusConnection *conn, int dft_reg, uint16_t id);
+typedef int unregister_function_t(DBusConnection *conn, int unreg_dft, uint16_t id);
+
+const struct service_data *get_hci_table(void);
+
+static int hci_dbus_reg_obj_path(DBusConnection *conn, int dft_reg, uint16_t id);
+static int hci_dbus_unreg_obj_path(DBusConnection *conn, int unreg_dft, uint16_t id);
+
+typedef const struct service_data *get_svc_table_func_t(void);
+
+struct profile_obj_path_data {
+ const char *name;
+ int status; /* 1:active 0:disabled */
+ int dft_reg; /* dft path registered */
+ register_function_t *reg_func;
+ unregister_function_t *unreg_func;
+ get_svc_table_func_t *get_svc_table; /* return the service table */
+};
+
+/*
+ * D-Bus error messages functions and declarations.
+ * This section should be moved to a common file
+ * in the future
+ *
+ */
+typedef struct {
+ uint32_t code;
+ const char *str;
+}bluez_error_t;
+
+static const bluez_error_t error_array[] = {
+ { BLUEZ_EDBUS_UNKNOWN_METHOD, "Method not found" },
+ { BLUEZ_EDBUS_WRONG_SIGNATURE, "Wrong method signature" },
+ { BLUEZ_EDBUS_WRONG_PARAM, "Invalid parameters" },
+ { BLUEZ_EDBUS_RECORD_NOT_FOUND, "No record found" },
+ { BLUEZ_EDBUS_NO_MEM, "No memory" },
+ { BLUEZ_EDBUS_CONN_NOT_FOUND, "Connection not found" },
+ { BLUEZ_EDBUS_UNKNOWN_PATH, "Device path is not registered" },
+ { 0, NULL }
+};
+
+static const char *bluez_dbus_error_to_str(const uint32_t ecode)
+{
+ const bluez_error_t *ptr;
+ uint32_t raw_code = 0;
+
+ if (ecode & BLUEZ_ESYSTEM_OFFSET) {
+ /* System error */
+ raw_code = (!BLUEZ_ESYSTEM_OFFSET) & ecode;
+ syslog(LOG_INFO, "%s - msg:%s", __PRETTY_FUNCTION__, strerror(raw_code));
+ return strerror(raw_code);
+ } else if (ecode & BLUEZ_EDBUS_OFFSET) {
+ /* D-Bus error */
+ for (ptr = error_array; ptr->code; ptr++) {
+ if (ptr->code == ecode) {
+ syslog(LOG_INFO, "%s - msg:%s", __PRETTY_FUNCTION__, ptr->str);
+ return ptr->str;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static DBusMessage *bluez_new_failure_msg(DBusMessage *msg, const uint32_t ecode)
+{
+ DBusMessageIter iter;
+ DBusMessage *reply = NULL;
+ const char *error_msg = NULL;
+
+ error_msg = bluez_dbus_error_to_str(ecode);
+
+ if (error_msg) {
+ reply = dbus_message_new_error(msg, ERROR_INTERFACE, error_msg);
+
+ dbus_message_iter_init_append(reply, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32 ,&ecode);
+ }
+
+ return reply;
+}
+
+/*
+ * Object path register/unregister functions
+ *
+ */
+static struct profile_obj_path_data obj_path_table[] = {
+ { BLUEZ_HCI, 1, 0, hci_dbus_reg_obj_path, hci_dbus_unreg_obj_path, get_hci_table },
+ /* add other profiles here */
+ { NULL, 0, 0, NULL, NULL, NULL }
+};
+
+/*
+ * Device Message handler functions object table declaration
+ */
+static DBusHandlerResult msg_func(DBusConnection *conn, DBusMessage *msg, void *data);
+
+static DBusMessage* handle_get_devices_req(DBusMessage *msg, void *data);
+static DBusMessage* handle_not_implemented_req(DBusMessage *msg, void *data);
+
+static const DBusObjectPathVTable obj_vtable = {
+ NULL,
+ &msg_func,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*
+ * Service provided under the path DEVICE_PATH
+ * TODO add the handlers
+ */
+static const struct service_data dev_services[] = {
+ { DEV_UP, handle_not_implemented_req, DEV_UP_SIGNATURE },
+ { DEV_DOWN, handle_not_implemented_req, DEV_DOWN_SIGNATURE },
+ { DEV_RESET, handle_not_implemented_req, DEV_RESET_SIGNATURE },
+ { DEV_SET_PROPERTY, handle_not_implemented_req, DEV_SET_PROPERTY_SIGNATURE },
+ { DEV_GET_PROPERTY, handle_not_implemented_req, DEV_GET_PROPERTY_SIGNATURE },
+ { NULL, NULL, NULL}
+};
+
+/*
+ * Manager Message handler functions object table declaration
+ *
+ */
+static const struct service_data mgr_services[] = {
+ { MGR_GET_DEV, handle_get_devices_req, MGR_GET_DEV_SIGNATURE },
+ { MGR_INIT, handle_not_implemented_req, NULL },
+ { MGR_ENABLE, handle_not_implemented_req, NULL },
+ { MGR_DISABLE, handle_not_implemented_req, NULL },
+ { NULL, handle_not_implemented_req, NULL }
+};
+
+/*
+ * HCI Manager Message handler functions object table declaration
+ *
+ */
+static DBusHandlerResult hci_signal_filter (DBusConnection *conn, DBusMessage *msg, void *data);
+
+static DBusMessage* handle_periodic_inq_req(DBusMessage *msg, void *data);
+static DBusMessage* handle_cancel_periodic_inq_req(DBusMessage *msg, void *data);
+static DBusMessage* handle_inq_req(DBusMessage *msg, void *data);
+static DBusMessage* handle_role_switch_req(DBusMessage *msg, void *data);
+
+static const struct service_data hci_services[] = {
+ { HCI_PERIODIC_INQ, handle_periodic_inq_req, HCI_PERIODIC_INQ_SIGNATURE },
+ { HCI_CANCEL_PERIODIC_INQ, handle_cancel_periodic_inq_req, HCI_CANCEL_PERIODIC_INQ_SIGNATURE },
+ { HCI_ROLE_SWITCH, handle_role_switch_req, HCI_ROLE_SWITCH_SIGNATURE },
+ { HCI_INQ, handle_inq_req, HCI_INQ_SIGNATURE },
+ { NULL, NULL, NULL }
+};
+
static void reply_handler_function(DBusPendingCall *call, void *user_data)
{
struct pin_request *req = (struct pin_request *) user_data;
@@ -73,9 +241,9 @@ static void reply_handler_function(DBusPendingCall *call, void *user_data)
size_t len;
char *pin;
const char *error_msg;
-
+
message = dbus_pending_call_steal_reply(call);
-
+
if (message) {
msg_type = dbus_message_get_type(message);
dbus_message_iter_init(message, &iter);
@@ -105,7 +273,7 @@ static void reply_handler_function(DBusPendingCall *call, void *user_data)
hci_send_cmd(req->dev, OGF_LINK_CTL, OCF_PIN_CODE_REPLY,
PIN_CODE_REPLY_CP_SIZE, &pr);
}
- }
+ }
dbus_message_unref(message);
}
@@ -126,8 +294,8 @@ void hcid_dbus_request_pin(int dev, struct hci_conn_info *ci)
uint8_t *addr = (uint8_t *) &ci->bdaddr;
dbus_bool_t out = ci->out;
- message = dbus_message_new_method_call(SERVICE_NAME, PATH_NAME,
- INTERFACE_NAME, REQUEST_NAME);
+ message = dbus_message_new_method_call(PINAGENT_SERVICE_NAME, PINAGENT_PATH,
+ PINAGENT_INTERFACE, PIN_REQUEST);
if (message == NULL) {
syslog(LOG_ERR, "Couldn't allocate D-BUS message");
goto failed;
@@ -165,13 +333,13 @@ failed:
void hcid_dbus_inquiry_start(bdaddr_t *local)
{
DBusMessage *message;
- char *local_addr;
+ char *local_addr;
bdaddr_t tmp;
baswap(&tmp, local); local_addr = batostr(&tmp);
- message = dbus_message_new_signal("/org/bluez/DevAgent",
- "org.bluez.DevAgent", "InquiryStart");
+ message = dbus_message_new_signal(BLUEZ_HCI_PATH,
+ BLUEZ_HCI_INTERFACE, BLUEZ_HCI_INQ_START);
if (message == NULL) {
syslog(LOG_ERR, "Can't allocate D-BUS inquiry start message");
goto failed;
@@ -204,8 +372,8 @@ void hcid_dbus_inquiry_complete(bdaddr_t *local)
baswap(&tmp, local); local_addr = batostr(&tmp);
- message = dbus_message_new_signal("/org/bluez/DevAgent",
- "org.bluez.DevAgent", "InquiryComplete");
+ message = dbus_message_new_signal(BLUEZ_HCI_PATH,
+ BLUEZ_HCI_INTERFACE, BLUEZ_HCI_INQ_COMPLETE);
if (message == NULL) {
syslog(LOG_ERR, "Can't allocate D-BUS inquiry complete message");
goto failed;
@@ -241,8 +409,8 @@ void hcid_dbus_inquiry_result(bdaddr_t *local, bdaddr_t *peer, uint32_t class, i
baswap(&tmp, local); local_addr = batostr(&tmp);
baswap(&tmp, peer); peer_addr = batostr(&tmp);
- message = dbus_message_new_signal("/org/bluez/DevAgent",
- "org.bluez.DevAgent", "InquiryResult");
+ message = dbus_message_new_signal(BLUEZ_HCI_PATH,
+ BLUEZ_HCI_INTERFACE, BLUEZ_HCI_INQ_RESULT);
if (message == NULL) {
syslog(LOG_ERR, "Can't allocate D-BUS inquiry result message");
goto failed;
@@ -280,8 +448,8 @@ void hcid_dbus_remote_name(bdaddr_t *local, bdaddr_t *peer, char *name)
baswap(&tmp, local); local_addr = batostr(&tmp);
baswap(&tmp, peer); peer_addr = batostr(&tmp);
- message = dbus_message_new_signal("/org/bluez/DevAgent",
- "org.bluez.DevAgent", "RemoteName");
+ message = dbus_message_new_signal(BLUEZ_HCI_PATH,
+ BLUEZ_HCI_INTERFACE, BLUEZ_HCI_REMOTE_NAME);
if (message == NULL) {
syslog(LOG_ERR, "Can't allocate D-BUS remote name message");
goto failed;
@@ -376,8 +544,7 @@ static void remove_watch(DBusWatch *watch, void *data)
static void watch_toggled(DBusWatch *watch, void *data)
{
/* Because we just exit on OOM, enable/disable is
- * no different from add/remove
- */
+ * no different from add/remove */
if (dbus_watch_get_enabled(watch))
add_watch(watch, data);
else
@@ -387,19 +554,777 @@ static void watch_toggled(DBusWatch *watch, void *data)
gboolean hcid_dbus_init(void)
{
DBusError error;
+ uint16_t *dev_path_id = (uint16_t *) malloc(1);
+ uint16_t *mgr_path_id = (uint16_t *) malloc(1);
dbus_error_init(&error);
connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
- if (connection == NULL) {
- fprintf(stderr, "Failed to open connection to system message bus: %s\n",
- error.message);
+
+ if (dbus_error_is_set(&error)) {
+ syslog(LOG_ERR, "Can't open system message bus connection: %s\n",
+ error.message);
dbus_error_free(&error);
return FALSE;
}
+ dbus_bus_request_name(connection, BASE_INTERFACE,
+ DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error);
+
+ if (dbus_error_is_set(&error)) {
+ syslog(LOG_ERR,"Can't get system message bus name: %s\n",
+ error.message);
+ dbus_error_free(&error);
+ return FALSE;
+ }
+
+ if (!dev_path_id)
+ return FALSE;
+
+ *dev_path_id = DEVICE_PATH_ID;
+
+ if (!dbus_connection_register_object_path(connection, DEVICE_PATH,
+ &obj_vtable, dev_path_id)) {
+ syslog(LOG_ERR, "Can't register %s object", DEVICE_PATH);
+ return FALSE;
+ }
+
+ syslog(LOG_INFO,"Registered %s object", DEVICE_PATH);
+
+ if (!mgr_path_id)
+ goto done;
+
+ *mgr_path_id = MANAGER_PATH_ID;
+
+ if (!dbus_connection_register_fallback(connection, MANAGER_PATH,
+ &obj_vtable, mgr_path_id)) {
+ syslog(LOG_ERR, "Can't register %s object", MANAGER_PATH);
+ return FALSE;
+ }
+
+ syslog(LOG_INFO, "Registered %s object", MANAGER_PATH);
+
+done:
+ if (!dbus_connection_add_filter(connection, hci_signal_filter, NULL, NULL)) {
+ syslog(LOG_ERR, "Can't add new HCI filter");
+ return FALSE;
+ }
+
dbus_connection_set_watch_functions(connection,
- add_watch, remove_watch, watch_toggled, NULL, NULL);
+ add_watch, remove_watch, watch_toggled, NULL, NULL);
+
+ return TRUE;
+}
+
+void hcid_dbus_exit(void)
+{
+ char path[MAX_PATH_LENGTH];
+ char fst_parent[] = MANAGER_PATH;
+ char snd_parent[MAX_PATH_LENGTH];
+ char **fst_level = NULL;
+ char **snd_level = NULL;
+ char *ptr1;
+ char *ptr2;
+ uint16_t *data = NULL;
+
+ if (!connection)
+ return;
+
+ if (dbus_connection_get_object_path_data(connection,
+ DEVICE_PATH, (void *) &data)) {
+ if (data) {
+ free(data);
+ data = NULL;
+ }
+ }
+
+ if (!dbus_connection_unregister_object_path(connection, DEVICE_PATH))
+ syslog(LOG_ERR, "Can't unregister %s object", DEVICE_PATH);
+ else
+ syslog(LOG_INFO, "Unregistered %s object", DEVICE_PATH);
+
+ if (dbus_connection_get_object_path_data(connection,
+ MANAGER_PATH, (void*) &data)) {
+ if (data) {
+ free(data);
+ data = NULL;
+ }
+ }
+
+ if (!dbus_connection_unregister_object_path(connection, MANAGER_PATH))
+ syslog(LOG_ERR, "Can't unregister %s object", MANAGER_PATH);
+ else
+ syslog(LOG_INFO, "Unregistered %s object", MANAGER_PATH);
+
+ dbus_connection_list_registered(connection, fst_parent, &fst_level);
+
+ for (; *fst_level; fst_level++) {
+ ptr1 = *fst_level;
+ sprintf(snd_parent, "%s/%s", fst_parent, ptr1);
+
+ dbus_connection_list_registered(connection, snd_parent, &snd_level);
+
+ if (!(*snd_level)) {
+ sprintf(path, "%s/%s", MANAGER_PATH, ptr1);
+
+ syslog(LOG_INFO, "Unregistered %s object", path);
+
+ if (dbus_connection_get_object_path_data(connection,
+ path, (void*) &data)) {
+ if (data) {
+ free(data);
+ data = NULL;
+ }
+ }
+
+ if (!dbus_connection_unregister_object_path(connection, path))
+ syslog(LOG_ERR, "Can't unregister %s object", path);
+
+ continue;
+ }
+
+ for (; *snd_level; snd_level++) {
+ ptr2 = *snd_level;
+ sprintf(path, "%s/%s/%s", MANAGER_PATH, ptr1, ptr2);
+
+ syslog(LOG_INFO, "Unregistered %s object", path);
+
+ if (dbus_connection_get_object_path_data(connection,
+ path, (void*) &data)) {
+ if (data) {
+ free(data);
+ data = NULL;
+ }
+ }
+
+ if (!dbus_connection_unregister_object_path(connection, path))
+ syslog(LOG_ERR, "Can't unregister %s object", path);
+ }
+
+ if (*snd_level)
+ dbus_free_string_array(snd_level);
+ }
+
+ if (*fst_level)
+ dbus_free_string_array(fst_level);
+}
+
+gboolean hcid_dbus_register_device(uint16_t id)
+{
+ struct profile_obj_path_data *ptr = obj_path_table;
+ int ret = -1;
+
+ if (!connection)
+ return FALSE;
+
+ for (; ptr->name; ptr++) {
+ ret = ptr->reg_func(connection, ptr->dft_reg, id);
+ ptr->dft_reg = 1;
+ }
+
+ if (!ret)
+ num_adapters++;
+
+ return TRUE;
+}
+
+gboolean hcid_dbus_unregister_device(uint16_t id)
+{
+ struct profile_obj_path_data *ptr = obj_path_table;
+ int dft_unreg = 0;
+
+ if (!connection)
+ return FALSE;
+
+ for (; ptr->name; ptr++) {
+ dft_unreg = (num_adapters > 1) ? 0 : 1;
+ num_adapters--;
+ ptr->unreg_func(connection, dft_unreg, id);
+
+ if (dft_unreg )
+ ptr->dft_reg = 0;
+ }
return TRUE;
}
+
+/*
+ * @brief HCI object path register function
+ * Detailed description: function responsible for register a new hci
+ * D-Bus path. If necessary the default path must be registered too.
+ * @param conn D-Bus connection
+ * @param dft_reg register the default path(0 or !0)
+ * @param id hci device identification
+ * @return (0-Success/-1 failure)
+ */
+static int hci_dbus_reg_obj_path(DBusConnection *conn, int dft_reg, uint16_t id)
+{
+ char path[MAX_PATH_LENGTH];
+ uint16_t *ptr_id = (uint16_t*)malloc(1);
+ uint16_t *ptr_id_dft;
+
+ /* register the default path*/
+ if (!dft_reg) {
+ ptr_id_dft = (uint16_t*)malloc(1);
+ *ptr_id_dft = DEFAULT_DEVICE_PATH_ID;
+ sprintf(path, "%s/%s/%s", MANAGER_PATH, HCI_DEFAULT_DEVICE_NAME, BLUEZ_HCI);
+
+ syslog(LOG_INFO, "registering dft path:%s - id:%d", path, DEFAULT_DEVICE_PATH_ID);
+
+ if (!dbus_connection_register_object_path(conn, path, &obj_vtable, ptr_id_dft)) {
+ syslog(LOG_ERR,"DBUS failed to register %s object", path);
+ /* ignore, the default path was already registered */
+ }
+ }
+
+ *ptr_id = id;
+
+ /* register the default path*/
+ sprintf(path, "%s/%s%d/%s", MANAGER_PATH, HCI_DEVICE_NAME, id, BLUEZ_HCI);
+
+ syslog(LOG_INFO, "registering - path:%s - id:%d",path, id);
+
+ if (!dbus_connection_register_object_path(conn, path, &obj_vtable, ptr_id)) {
+ syslog(LOG_ERR,"DBUS failed to register %s object", path);
+ /* ignore, the path was already registered */
+ }
+
+ return 0;
+}
+
+/*
+ * @brief HCI object path unregister function
+ * Detailed description: function responsible for unregister HCI D-Bus
+ * path for a detached hci device. If necessary the default path must
+ * be registered too.
+ * @param conn D-Bus connection
+ * @param unreg_dft register the default path(0 or !0)
+ * @param id hci device identification
+ * @return (0-Success/-1 failure)
+ */
+static int hci_dbus_unreg_obj_path(DBusConnection *conn, int unreg_dft, uint16_t id)
+{
+ int ret = 0;
+ char path[MAX_PATH_LENGTH];
+ char dft_path[MAX_PATH_LENGTH];
+ uint16_t *data;
+
+ if (unreg_dft) {
+ sprintf(dft_path, "%s/%s/%s", MANAGER_PATH, HCI_DEFAULT_DEVICE_NAME, BLUEZ_HCI);
+ syslog(LOG_INFO, "%s - unregistering dft:%s", __PRETTY_FUNCTION__, dft_path);
+ if (!dbus_connection_unregister_object_path (connection, dft_path)) {
+ syslog(LOG_ERR,"DBUS failed to unregister %s object", dft_path);
+ ret = -1;
+ } else {
+ if (dbus_connection_get_object_path_data(conn, dft_path, (void *) &data)) {
+ if (data) {
+ free(data);
+ data = NULL;
+ }
+ }
+ }
+ }
+
+ sprintf(path, "%s/%s%d/%s", MANAGER_PATH, HCI_DEVICE_NAME, id, BLUEZ_HCI);
+ syslog(LOG_INFO, "%s - unregistering spec:%s", __PRETTY_FUNCTION__, path);
+ if (!dbus_connection_unregister_object_path (connection, path)) {
+ syslog(LOG_ERR,"DBUS failed to unregister %s object", path);
+ ret = -1;
+ } else {
+ if (dbus_connection_get_object_path_data(conn, path, (void *) &data)) {
+ if (data) {
+ free(data);
+ data = NULL;
+ }
+ }
+ }
+
+ return ret;
+}
+
+const struct service_data *get_hci_table(void)
+{
+ return hci_services;
+}
+
+/*****************************************************************
+ *
+ * Section reserved to HCI Manaher D-Bus message handlers
+ *
+ *****************************************************************/
+
+static DBusHandlerResult hci_signal_filter (DBusConnection *conn, DBusMessage *msg, void *data)
+{
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ const char *iface;
+ const char *method;
+
+ if (!msg || !conn)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (dbus_message_get_type (msg) != DBUS_MESSAGE_TYPE_SIGNAL)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ iface = dbus_message_get_interface(msg);
+ method = dbus_message_get_member(msg);
+
+ if (strcmp(iface, DBUS_INTERFACE_LOCAL) == 0) {
+ if (strcmp(method, "Disconnected") == 0)
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ } else if (strcmp(iface, DBUS_INTERFACE_DBUS) == 0) {
+ if (strcmp(method, "NameOwnerChanged") == 0)
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+
+ if (strcmp(method, "NameAcquired") == 0)
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return ret;
+}
+/*
+ * There is only one message handler function for all object paths
+ *
+ */
+
+static DBusHandlerResult msg_func(DBusConnection *conn, DBusMessage *msg, void *data)
+{
+ const struct service_data *ptr_handlers = NULL;
+ DBusMessage *reply = NULL;
+ int type;
+ const char *iface;
+ const char *method;
+ const char *signature;
+ const char *path;
+ const char *rel_path;
+ const char *tmp_iface = NULL;
+ const uint16_t *udata = (uint16_t *) data;
+ uint32_t result = BLUEZ_EDBUS_UNKNOWN_METHOD;
+ DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ uint8_t found = 0;
+
+ path = dbus_message_get_path(msg);
+ type = dbus_message_get_type(msg);
+ iface = dbus_message_get_interface(msg);
+ method = dbus_message_get_member (msg);
+ signature = dbus_message_get_signature(msg);
+
+ syslog (LOG_INFO, "%s - path:%s, udata:0x%X", __PRETTY_FUNCTION__, path, *udata);
+
+ if (strcmp(path, DEVICE_PATH) == 0) {
+ ptr_handlers = dev_services;
+ tmp_iface = DEVICE_INTERFACE;
+ found = 1;
+ } else {
+ if (strcmp(path, MANAGER_PATH) > 0) {
+ /* it is device specific path */
+ if ( *udata == MANAGER_PATH_ID ) {
+ /* fallback handling. The child path IS NOT registered */
+ reply = bluez_new_failure_msg(msg, BLUEZ_EDBUS_UNKNOWN_PATH);
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ } else {
+ const struct profile_obj_path_data *mgr_child = obj_path_table;
+ rel_path = strrchr(path,'/');
+ rel_path++;
+
+ if (rel_path) {
+ for ( ;mgr_child->name; mgr_child++) {
+ if (strcmp(mgr_child->name, rel_path) == 0) {
+ ptr_handlers = mgr_child->get_svc_table();
+ found = 1;
+ }
+ }
+
+ tmp_iface = MANAGER_INTERFACE;
+ }
+ }
+ } else {
+ /* it's the manager path */
+ ptr_handlers = mgr_services;
+ tmp_iface = MANAGER_INTERFACE;
+ found = 1;
+ }
+ }
+
+ if (found && (type == DBUS_MESSAGE_TYPE_METHOD_CALL) &&
+ (strcmp(iface, tmp_iface) == 0) && (method != NULL)) {
+
+ for (; ptr_handlers->name; ptr_handlers++) {
+ if (strcmp(method, ptr_handlers->name) == 0) {
+ /* resetting unknown method. It's possible handle method overload */
+ result = BLUEZ_EDBUS_WRONG_SIGNATURE;
+ if (strcmp(ptr_handlers->signature, signature) == 0) {
+ if (ptr_handlers->handler_func) {
+ reply = (ptr_handlers->handler_func)(msg, data);
+ result = 0; /* resetting wrong signature*/
+ } else
+ syslog(LOG_INFO, "Service not implemented");
+
+ break;
+ }
+
+ }
+ }
+
+ if (result) {
+ reply = bluez_new_failure_msg(msg, result);
+ }
+
+ /* send an error or the success reply*/
+ if (reply) {
+ if (!dbus_connection_send (conn, reply, NULL)) {
+ syslog(LOG_ERR, "%s line:%d Can't send reply message!",
+ __PRETTY_FUNCTION__, __LINE__) ;
+ }
+ dbus_message_unref (reply);
+ }
+
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ }
+ return ret;
+}
+
+static DBusMessage* handle_periodic_inq_req(DBusMessage *msg, void *data)
+{
+ write_inquiry_mode_cp inq_mode;
+ periodic_inquiry_cp inq_param;
+ DBusMessageIter iter;
+ DBusMessage *reply = NULL;
+ const uint16_t *udata = (uint16_t *) data;
+ uint8_t length;
+ uint8_t max_period;
+ uint8_t min_period;
+ int sock = -1;
+ int dev_id = -1;
+
+ if (*udata == DEFAULT_DEVICE_PATH_ID) {
+ if ((dev_id = hci_get_route(NULL)) < 0) {
+ syslog(LOG_ERR, "Bluetooth device is not available");
+ reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_ENODEV);
+ goto failed;
+
+ }
+ } else
+ dev_id = *udata;
+
+ if ((sock = hci_open_dev(dev_id)) < 0) {
+ syslog(LOG_ERR, "HCI device open failed");
+ reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_ENODEV);
+ goto failed;
+ }
+
+ dbus_message_iter_init(msg, &iter);
+ dbus_message_iter_get_basic(&iter, &length);
+ dbus_message_iter_next(&iter);
+ dbus_message_iter_get_basic(&iter, &min_period);
+ dbus_message_iter_next(&iter);
+ dbus_message_iter_get_basic(&iter, &max_period);
+
+ if ((length >= min_period) || (min_period >= max_period)) {
+ reply = bluez_new_failure_msg(msg, BLUEZ_EDBUS_WRONG_PARAM);
+ goto failed;
+ }
+
+ inq_param.num_rsp = 100;
+ inq_param.length = length;
+
+ inq_param.max_period = max_period;
+ inq_param.min_period = min_period;
+
+ /* General/Unlimited Inquiry Access Code (GIAC) */
+ inq_param.lap[0] = 0x33;
+ inq_param.lap[1] = 0x8b;
+ inq_param.lap[2] = 0x9e;
+
+ inq_mode.mode = 1; //INQUIRY_WITH_RSSI;
+
+ if (hci_send_cmd(sock, OGF_HOST_CTL, OCF_WRITE_INQUIRY_MODE,
+ WRITE_INQUIRY_MODE_CP_SIZE, &inq_mode) < 0) {
+ syslog(LOG_ERR, "Can't set inquiry mode:%s.", strerror(errno));
+ reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET + errno);
+ goto failed;
+ }
+
+ if (hci_send_cmd(sock, OGF_LINK_CTL, OCF_PERIODIC_INQUIRY,
+ PERIODIC_INQUIRY_CP_SIZE, &inq_param) < 0) {
+ syslog(LOG_ERR, "Can't send HCI commands:%s.", strerror(errno));
+ reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET + errno);
+ goto failed;
+ } else {
+ uint8_t result = 0;
+ /* return TRUE to indicate that operation was completed */
+ reply = dbus_message_new_method_return(msg);
+ dbus_message_iter_init_append(reply, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_BYTE ,&result);
+ }
+
+failed:
+ if (sock > 0)
+ close(sock);
+
+ return reply;
+}
+
+static DBusMessage* handle_cancel_periodic_inq_req(DBusMessage *msg, void *data)
+{
+ DBusMessageIter iter;
+ DBusMessage *reply = NULL;
+ const uint16_t *udata = (uint16_t *)data;
+ int sock = -1;
+ int dev_id = -1;
+
+ if (*udata == DEFAULT_DEVICE_PATH_ID) {
+ if ((dev_id = hci_get_route(NULL)) < 0) {
+ syslog(LOG_ERR, "Bluetooth device is not available");
+ reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_ENODEV);
+ goto failed;
+ }
+ } else
+ dev_id = *udata;
+
+ if ((sock = hci_open_dev(dev_id)) < 0) {
+ syslog(LOG_ERR, "HCI device open failed");
+ reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_ENODEV);
+ goto failed;
+ }
+
+ if (hci_send_cmd(sock, OGF_LINK_CTL, OCF_EXIT_PERIODIC_INQUIRY, 0 , NULL) < 0) {
+ syslog(LOG_ERR, "Send hci command failed.");
+ reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET + errno);
+ } else {
+ uint8_t result = 0;
+ /* return TRUE to indicate that operation was completed */
+ reply = dbus_message_new_method_return(msg);
+ dbus_message_iter_init_append(reply, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_BYTE ,&result);
+ }
+
+failed:
+ if (sock > 0)
+ close(sock);
+
+ return reply;
+}
+
+static DBusMessage* handle_inq_req(DBusMessage *msg, void *data)
+{
+ char addr[18];
+ const char array_sig[] = HCI_INQ_REPLY_SIGNATURE;
+ DBusMessageIter iter;
+ DBusMessageIter array_iter;
+ DBusMessageIter struct_iter;
+ DBusMessage *reply = NULL;
+ inquiry_info *info = NULL;
+ const uint16_t *udata = (uint16_t *)data;
+ const char *paddr = addr;
+ int dev_id = -1;
+ int i;
+ uint32_t class = 0;
+ uint16_t clock_offset;
+ uint16_t flags;
+ int8_t length;
+ int8_t num_rsp;
+
+ if (*udata == DEFAULT_DEVICE_PATH_ID) {
+ if ((dev_id = hci_get_route(NULL)) < 0) {
+ syslog(LOG_ERR, "Bluetooth device is not available");
+ reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_ENODEV);
+ goto failed;
+ }
+ } else
+ dev_id = *udata;
+
+ dbus_message_iter_init(msg, &iter);
+ dbus_message_iter_get_basic(&iter, &length);
+ dbus_message_iter_next(&iter);
+ dbus_message_iter_get_basic(&iter, &num_rsp);
+ dbus_message_iter_next(&iter);
+ dbus_message_iter_get_basic(&iter, &flags);
+
+ if ((length <= 0) || (num_rsp <= 0)) {
+ reply = bluez_new_failure_msg(msg, BLUEZ_EDBUS_WRONG_PARAM);
+ goto failed;
+ }
+
+ num_rsp = hci_inquiry(dev_id, length, num_rsp, NULL, &info, flags);
+
+ if (num_rsp < 0) {
+ reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET + errno);
+ } else {
+ reply = dbus_message_new_method_return(msg);
+ dbus_message_iter_init_append(reply, &iter);
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, array_sig, &array_iter);
+
+ for (i = 0; i < num_rsp; i++) {
+ ba2str(&(info+i)->bdaddr, addr);
+
+ clock_offset = btohs((info+i)->clock_offset);
+ /* only 3 bytes are used */
+ memcpy(&class, (info+i)->dev_class, 3);
+
+ dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter);
+ dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING , &paddr);
+ dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT32 , &class);
+ dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT16 , &clock_offset);
+ dbus_message_iter_close_container(&array_iter, &struct_iter);
+ }
+
+ dbus_message_iter_close_container(&iter, &array_iter);
+ }
+
+failed:
+ if(info)
+ bt_free(info);
+
+ return NULL;
+}
+
+static DBusMessage* handle_role_switch_req(DBusMessage *msg, void *data)
+{
+ DBusMessageIter iter;
+ DBusMessage *reply = NULL;
+ char *str_bdaddr = NULL;
+ const uint16_t *udata = (uint16_t *)data;
+ bdaddr_t bdaddr;
+ uint8_t role;
+ int dev_id = -1;
+ int sock = -1;
+
+ dbus_message_iter_init(msg, &iter);
+ dbus_message_iter_get_basic(&iter, &str_bdaddr);
+ dbus_message_iter_next(&iter);
+ dbus_message_iter_get_basic(&iter, &role);
+
+ str2ba(str_bdaddr, &bdaddr);
+
+ dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr);
+
+ if (dev_id < 0) {
+ syslog(LOG_ERR, "Bluetooth device failed\n");
+ reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_ENODEV);
+ goto failed;
+ }
+
+ if (*udata != DEFAULT_DEVICE_PATH_ID && *udata != dev_id) {
+ syslog(LOG_ERR, "Connection not found\n");
+ reply = bluez_new_failure_msg(msg, BLUEZ_EDBUS_CONN_NOT_FOUND);
+ goto failed;
+ }
+
+ sock = hci_open_dev(dev_id);
+
+ if (sock < 0) {
+ syslog(LOG_ERR, "HCI device open failed\n");
+ reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_ENODEV);
+ goto failed;
+ }
+
+ if (hci_switch_role(sock, &bdaddr, role, 10000) < 0) {
+ syslog(LOG_ERR, "Switch role request failed\n");
+ reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET + errno);
+ } else {
+ uint8_t result = 0;
+ /* return TRUE to indicate that operation was completed */
+ reply = dbus_message_new_method_return(msg);
+ dbus_message_iter_init_append(reply, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_BYTE, &result);
+ }
+
+failed:
+ return reply;
+}
+
+/*****************************************************************
+ *
+ * Section reserved to Device D-Bus message handlers
+ *
+ *****************************************************************/
+
+static DBusMessage* handle_get_devices_req(DBusMessage *msg, void *data)
+{
+ DBusMessageIter iter;
+ DBusMessageIter array_iter;
+ DBusMessageIter struct_iter;
+ DBusMessage *reply = NULL;
+
+ struct hci_dev_list_req *dl = NULL;
+ struct hci_dev_req *dr = NULL;
+ struct hci_dev_info di;
+ int i;
+ int sock = -1;
+
+ char aname[BLUETOOTH_DEVICE_NAME_LEN];
+ char aaddr[BLUETOOTH_DEVICE_ADDR_LEN];
+ char *paddr = aaddr;
+ char *pname = aname;
+ const char array_sig[] = HCI_DEVICE_STRUCT_SIGNATURE;
+
+ /* Create and bind HCI socket */
+ if ((sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0) {
+ syslog(LOG_ERR, "Can't open HCI socket: %s (%d)", strerror(errno), errno);
+ reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET + errno);
+ goto failed;
+ }
+
+ dl = malloc(HCI_MAX_DEV * sizeof(*dr) + sizeof(*dl));
+
+ if (!dl) {
+ syslog(LOG_ERR, "Can't allocate memory");
+ reply = bluez_new_failure_msg(msg, BLUEZ_EDBUS_NO_MEM);
+ goto failed;
+ }
+
+ dl->dev_num = HCI_MAX_DEV;
+ dr = dl->dev_req;
+
+ if (ioctl(sock, HCIGETDEVLIST, (void *) dl) < 0) {
+ reply = bluez_new_failure_msg(msg, BLUEZ_ESYSTEM_OFFSET + errno);
+ goto failed;
+ }
+
+ /* active bluetooth adapter found */
+ reply = dbus_message_new_method_return(msg);
+ dbus_message_iter_init_append(reply, &iter);
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, array_sig, &array_iter);
+ dr = dl->dev_req;
+
+ for (i = 0; i < dl->dev_num; i++, dr++) {
+ if (hci_test_bit(HCI_UP, &dr->dev_opt)) {
+ memset(&di, 0 , sizeof(struct hci_dev_info));
+ di.dev_id = dr->dev_id;
+
+ if (!ioctl(sock, HCIGETDEVINFO, (void *) &di)) {
+ strcpy(aname, di.name);
+ ba2str(&di.bdaddr, aaddr);
+ dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL,
+ &struct_iter);
+ dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING ,&pname);
+ dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING ,&paddr);
+
+ dbus_message_iter_close_container(&array_iter, &struct_iter);
+ }
+ }
+ }
+
+ dbus_message_iter_close_container(&iter, &array_iter);
+
+failed:
+ if (dl)
+ free(dl);
+
+ if (sock > 0)
+ close (sock);
+
+ return reply;
+}
+
+static DBusMessage* handle_not_implemented_req(DBusMessage *msg, void *data)
+{
+ const char *path = dbus_message_get_path(msg);
+ const char *iface = dbus_message_get_interface(msg);
+ const char *method = dbus_message_get_member(msg);
+
+ syslog(LOG_INFO, "Not Implemented - path %s iface %s method %s",
+ path, iface, method);
+
+ return NULL;
+}
diff --git a/hcid/dbus.h b/hcid/dbus.h
new file mode 100644
index 00000000..585739ce
--- /dev/null
+++ b/hcid/dbus.h
@@ -0,0 +1,180 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2000-2001 Qualcomm Incorporated
+ * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
+ * Copyright (C) 2002-2005 Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+ * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+ * SOFTWARE IS DISCLAIMED.
+ *
+ *
+ * $Id$
+ */
+
+#define __END_SIG__ DBUS_TYPE_INVALID_AS_STRING
+
+#define BASE_PATH "/org/bluez"
+#define BASE_INTERFACE "org.bluez"
+
+#define DEVICE_PATH BASE_PATH "/Device"
+#define DEVICE_INTERFACE BASE_INTERFACE ".Device"
+
+#define MANAGER_PATH BASE_PATH "/Manager"
+#define MANAGER_INTERFACE BASE_INTERFACE ".Manager"
+
+#define ERROR_INTERFACE BASE_INTERFACE ".Error"
+
+#define ERROR_UNKNOWN_HCI_COMMAND 0x01
+#define ERROR_UNKNOWN_CONNECTION_IDENTIFIER 0x02
+#define ERROR_HARDWARE_FAILURE 0x03
+#define ERROR_PAGE_TIMEOUT 0x04
+#define ERROR_AUTHENTICATION_FAILURE 0x05
+#define ERROR_PIN_OR_KEY_MISSING 0x06
+#define ERROR_MEMORY_CAPACITY_EXCEEDED 0x07
+#define ERROR_CONNECTION_TIMEOUT 0x08
+#define ERROR_CONNECTION_LIMIT_EXCEEDED 0x09
+#define ERROR_SYNCHRONOUS_CONNECTION_LIMIT_EXCEEDED 0x0a
+#define ERROR_ACL_CONNECTION_ALREADY_EXISTS 0x0b
+#define ERROR_COMMAND_DISALLOWED 0x0c
+#define ERROR_CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES 0x0d
+#define ERROR_CONNECTION_REJECTED_DUE_TO_SECURITY_REASONS 0x0e
+#define ERROR_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BDADDR 0x0f
+#define ERROR_CONNECTION_ACCEPT_TIMEOUT_EXCEEDED 0x10
+#define ERROR_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE 0x11
+#define ERROR_INVALID_HCI_COMMAND_PARAMETERS 0x12
+#define ERROR_REMOTE_USER_TERMINATED_CONNECTION 0x13
+#define ERROR_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO 0x14
+
+#define DEFAULT_DEVICE_PATH_ID (0xFFFF)
+#define MANAGER_PATH_ID (0xFFFE)
+#define DEVICE_PATH_ID (0xFFFD)
+
+#define HCI_DEFAULT_DEVICE_NAME "default"
+#define HCI_DEVICE_NAME "hci"
+
+/*========================================================================
+ BlueZ D-Bus Device service definitions "/org/bluez/Device"
+ *========================================================================*/
+#define DEV_UP "Up"
+#define DEV_DOWN "Down"
+#define DEV_RESET "Reset"
+#define DEV_SET_PROPERTY "SetProperty"
+#define DEV_GET_PROPERTY "GetProperty"
+
+#define DEV_UP_SIGNATURE __END_SIG__
+#define DEV_DOWN_SIGNATURE __END_SIG__
+#define DEV_RESET_SIGNATURE __END_SIG__
+#define DEV_SET_PROPERTY_SIGNATURE __END_SIG__
+#define DEV_GET_PROPERTY_SIGNATURE __END_SIG__
+
+/*========================================================================
+ BlueZ D-Bus Manager service definitions "/org/bluez/Manager"
+ *========================================================================*/
+
+ /* ===== Manager definitions, services under DEVICE_PATH ===== */
+#define MGR_GET_DEV "DeviceList"
+#define MGR_INIT "Init"
+
+/* Enable/Disable services controller, pan, serial, ... */
+#define MGR_ENABLE "Enable"
+#define MGR_DISABLE "Disable"
+
+//signatures
+#define MGR_GET_DEV_SIGNATURE __END_SIG__
+
+/* yya(ss)*/
+#define MGR_GET_DEV_REPLY_SIGNATURE DBUS_TYPE_BYTE_AS_STRING\
+ DBUS_TYPE_BYTE_AS_STRING\
+ DBUS_TYPE_ARRAY_AS_STRING\
+ HCI_DEVICE_STRUCT_SIGNATURE\
+ __END_SIG__
+
+/* ===== HCI definitions ===== */
+#define BLUEZ_HCI "Controller"
+#define BLUEZ_HCI_PATH MANAGER_PATH "/" BLUEZ_HCI
+#define BLUEZ_HCI_INTERFACE MANAGER_INTERFACE "." BLUEZ_HCI
+
+//HCI signals
+#define BLUEZ_HCI_INQ_START "InquiryStart"
+#define BLUEZ_HCI_INQ_COMPLETE "InquiryComplete"
+#define BLUEZ_HCI_INQ_RESULT "InquiryResult"
+#define BLUEZ_HCI_REMOTE_NAME "RemoteName"
+
+//HCI Provided services
+#define HCI_PERIODIC_INQ "PeriodicInquiry"
+#define HCI_CANCEL_PERIODIC_INQ "CancelPeriodic"
+#define HCI_INQ "Inquiry"
+#define HCI_ROLE_SWITCH "RoleSwitch"
+
+
+#define HCI_PERIODIC_INQ_SIGNATURE DBUS_TYPE_BYTE_AS_STRING\
+ DBUS_TYPE_BYTE_AS_STRING\
+ DBUS_TYPE_BYTE_AS_STRING\
+ __END_SIG__
+
+#define HCI_CANCEL_PERIODIC_INQ_SIGNATURE __END_SIG__
+
+#define HCI_INQ_SIGNATURE DBUS_TYPE_BYTE_AS_STRING\
+ DBUS_TYPE_BYTE_AS_STRING\
+ DBUS_TYPE_UINT16_AS_STRING\
+ __END_SIG__
+
+#define HCI_ROLE_SWITCH_SIGNATURE DBUS_TYPE_STRING_AS_STRING\
+ DBUS_TYPE_BYTE_AS_STRING\
+ __END_SIG__
+
+#define HCI_DEVICE_STRUCT_SIGNATURE DBUS_STRUCT_BEGIN_CHAR_AS_STRING\
+ DBUS_TYPE_STRING_AS_STRING\
+ DBUS_TYPE_STRING_AS_STRING\
+ DBUS_STRUCT_END_CHAR_AS_STRING
+
+#define HCI_INQ_REPLY_SIGNATURE DBUS_STRUCT_BEGIN_CHAR_AS_STRING\
+ DBUS_TYPE_STRING_AS_STRING\
+ DBUS_TYPE_UINT32_AS_STRING\
+ DBUS_TYPE_UINT16_AS_STRING\
+ DBUS_STRUCT_END_CHAR_AS_STRING\
+ __END_SIG__
+
+/* BLUEZ_DBUS_ERROR
+ * EFailed error messages signature is : su
+ * Where the first argument is a string(error message description),
+ * the last is a uint32 that contains the error class(system, dbus or hci). */
+
+/* Error code offsets */
+#define BLUEZ_EBT_OFFSET (0x00000000) /* see Bluetooth error code */
+#define BLUEZ_EBT_EXT_OFFSET (0x00000100)
+#define BLUEZ_EDBUS_OFFSET (0x00010000)
+#define BLUEZ_ESYSTEM_OFFSET (0x00020000)
+#define BLUEZ_EFUTURE_OFFSET (0x00040000)
+
+/* D-Bus error code, class BLUEZ_EDBUS_OFFSET */
+#define BLUEZ_EDBUS_UNKNOWN_METHOD (0x01 + BLUEZ_EDBUS_OFFSET)
+#define BLUEZ_EDBUS_WRONG_SIGNATURE (0x02 + BLUEZ_EDBUS_OFFSET)
+#define BLUEZ_EDBUS_WRONG_PARAM (0x03 + BLUEZ_EDBUS_OFFSET)
+#define BLUEZ_EDBUS_RECORD_NOT_FOUND (0x04 + BLUEZ_EDBUS_OFFSET)
+#define BLUEZ_EDBUS_NO_MEM (0x05 + BLUEZ_EDBUS_OFFSET)
+#define BLUEZ_EDBUS_CONN_NOT_FOUND (0x06 + BLUEZ_EDBUS_OFFSET)
+#define BLUEZ_EDBUS_UNKNOWN_PATH (0x07 + BLUEZ_EDBUS_OFFSET)
+
+/* D-Bus error code, class BLUEZ_ESYSTEM_OFFSET */
+#define BLUEZ_ESYSTEM_ENODEV (ENODEV + BLUEZ_ESYSTEM_OFFSET)
+
+/* BLUEZ_DBUS_ERR_NO_MEMORY */
+#define BLUEZ_DBUS_ERR_NO_MEMORY_STR "No memory"
diff --git a/hcid/hcid.h b/hcid/hcid.h
index 39b2cd09..d407c4c7 100644
--- a/hcid/hcid.h
+++ b/hcid/hcid.h
@@ -28,7 +28,9 @@
* $Id$
*/
+#include <syslog.h>
#include <sys/types.h>
+#include <sys/ioctl.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
@@ -122,6 +124,9 @@ void toggle_pairing(int enable);
#ifdef ENABLE_DBUS
gboolean hcid_dbus_init(void);
+void hcid_dbus_exit(void);
+gboolean hcid_dbus_register_device(uint16_t id);
+gboolean hcid_dbus_unregister_device(uint16_t id);
void hcid_dbus_request_pin(int dev, struct hci_conn_info *ci);
void hcid_dbus_inquiry_start(bdaddr_t *local);
void hcid_dbus_inquiry_complete(bdaddr_t *local);
@@ -145,3 +150,33 @@ int write_features_info(bdaddr_t *local, bdaddr_t *peer, unsigned char *features
int write_link_key(bdaddr_t *local, bdaddr_t *peer, unsigned char *key, int type);
int read_link_key(bdaddr_t *local, bdaddr_t *peer, unsigned char *key);
int read_pin_code(bdaddr_t *local, bdaddr_t *peer, char *pin);
+
+static inline int find_conn(int dd, int dev_id, long arg)
+{
+ struct hci_conn_list_req *cl;
+ struct hci_conn_info *ci;
+ int i;
+
+ cl = malloc(10 * sizeof(*ci) + sizeof(*cl));
+ if (!cl) {
+ syslog(LOG_ERR, "Can't allocate memory");
+ return 0;
+ }
+
+ cl->dev_id = dev_id;
+ cl->conn_num = 10;
+ ci = cl->conn_info;
+
+ if (ioctl(dd, HCIGETCONNLIST, (void *) cl)) {
+ syslog(LOG_ERR, "Can't get connection list");
+ return 0;
+ }
+
+ for (i = 0; i < cl->conn_num; i++, ci++)
+ if (!bacmp((bdaddr_t *) arg, &ci->bdaddr))
+ return 1;
+
+ free(cl);
+
+ return 0;
+}
diff --git a/hcid/main.c b/hcid/main.c
index ecfc7db6..b6891ee4 100644
--- a/hcid/main.c
+++ b/hcid/main.c
@@ -375,6 +375,10 @@ static void init_all_devices(int ctl)
if (hcid.security && hci_test_bit(HCI_UP, &dr->dev_opt))
start_security_manager(dr->dev_id);
+
+#ifdef ENABLE_DBUS
+ hcid_dbus_register_device(dr->dev_id);
+#endif
}
free(dl);
@@ -438,12 +442,18 @@ static inline void device_event(GIOChannel *chan, evt_stack_internal *si)
configure_device(sd->dev_id);
if (hcid.security)
start_security_manager(sd->dev_id);
+#ifdef ENABLE_DBUS
+ hcid_dbus_register_device(sd->dev_id);
+#endif
break;
case HCI_DEV_DOWN:
syslog(LOG_INFO, "HCI dev %d down", sd->dev_id);
if (hcid.security)
stop_security_manager(sd->dev_id);
+#ifdef ENABLE_DBUS
+ hcid_dbus_unregister_device(sd->dev_id);
+#endif
break;
}
}
@@ -628,6 +638,10 @@ int main(int argc, char *argv[], char *env[])
free_device_opts();
+#ifdef ENABLE_DBUS
+ hcid_dbus_exit();
+#endif
+
syslog(LOG_INFO, "Exit.");
return 0;
}