diff options
| -rw-r--r-- | hcid/Makefile.am | 4 | ||||
| -rw-r--r-- | hcid/dbus.c | 977 | ||||
| -rw-r--r-- | hcid/dbus.h | 180 | ||||
| -rw-r--r-- | hcid/hcid.h | 35 | ||||
| -rw-r--r-- | hcid/main.c | 14 | 
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;  }  | 
