⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adapter.c

📁 Linux的蓝牙操作工具。配合bluez-lib使用
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	sk = g_io_channel_unix_get_fd(io);	len = sizeof(ret);	if (getsockopt(sk, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) {		error("Can't get socket error: %s (%d)",				strerror(errno), errno);		error_failed_errno(adapter->bonding->conn, adapter->bonding->rq,				errno);		goto failed;	}	if (ret != 0) {		if (adapter->bonding->auth_active)			reply_authentication_failure(adapter->bonding);		else			error_connection_attempt_failed(adapter->bonding->conn,							adapter->bonding->rq,							ret);		goto failed;	}	len = sizeof(cinfo);	if (getsockopt(sk, SOL_L2CAP, L2CAP_CONNINFO, &cinfo, &len) < 0) {		error("Can't get connection info: %s (%d)",				strerror(errno), errno);		error_failed_errno(adapter->bonding->conn, adapter->bonding->rq,				errno);		goto failed;	}	dd = hci_open_dev(adapter->dev_id);	if (dd < 0) {		error_no_such_adapter(adapter->bonding->conn,					adapter->bonding->rq);		goto failed;	}	memset(&rp, 0, sizeof(rp));	memset(&cp, 0, sizeof(cp));	cp.handle = htobs(cinfo.hci_handle);	memset(&rq, 0, sizeof(rq));	rq.ogf    = OGF_LINK_CTL;	rq.ocf    = OCF_AUTH_REQUESTED;	rq.cparam = &cp;	rq.clen   = AUTH_REQUESTED_CP_SIZE;	rq.rparam = &rp;	rq.rlen   = EVT_CMD_STATUS_SIZE;	rq.event  = EVT_CMD_STATUS;	if (hci_send_req(dd, &rq, 500) < 0) {		error("Unable to send HCI request: %s (%d)",					strerror(errno), errno);		error_failed_errno(adapter->bonding->conn, adapter->bonding->rq,				errno);		hci_close_dev(dd);		goto failed;	}	if (rp.status) {		error("HCI_Authentication_Requested failed with status 0x%02x",				rp.status);		error_failed_errno(adapter->bonding->conn, adapter->bonding->rq,				bt_error(rp.status));		hci_close_dev(dd);		goto failed;	}	hci_close_dev(dd);	adapter->bonding->auth_active = 1;	adapter->bonding->io_id = g_io_add_watch(io,						G_IO_NVAL | G_IO_HUP | G_IO_ERR,						(GIOFunc) create_bonding_conn_complete,						adapter);	return FALSE;failed:	g_io_channel_close(io);cleanup:	name_listener_remove(adapter->bonding->conn,				dbus_message_get_sender(adapter->bonding->rq),				(name_cb_t) create_bond_req_exit, adapter);	bonding_request_free(adapter->bonding);	adapter->bonding = NULL;	return FALSE;}static DBusHandlerResult adapter_create_bonding(DBusConnection *conn,						DBusMessage *msg, void *data){	char filename[PATH_MAX + 1];	char *str, *peer_addr = NULL;	struct adapter *adapter = data;	bdaddr_t peer_bdaddr;	int sk;	if (!adapter->up)		return error_not_ready(conn, msg);	if (!dbus_message_get_args(msg, NULL,				DBUS_TYPE_STRING, &peer_addr,				DBUS_TYPE_INVALID))		return error_invalid_arguments(conn, msg, NULL);	if (check_address(peer_addr) < 0)		return error_invalid_arguments(conn, msg, NULL);	str2ba(peer_addr, &peer_bdaddr);	/* check if there is a pending discover: requested by D-Bus/non clients */	if (adapter->discov_active || (adapter->pdiscov_active && !adapter->pinq_idle))		return error_discover_in_progress(conn, msg);	pending_remote_name_cancel(adapter);	if (adapter->bonding)		return error_bonding_in_progress(conn, msg);	if (g_slist_find_custom(adapter->pin_reqs, &peer_bdaddr, pin_req_cmp))		return error_bonding_in_progress(conn, msg);	/* check if a link key already exists */	create_name(filename, PATH_MAX, STORAGEDIR, adapter->address,			"linkkeys");	str = textfile_caseget(filename, peer_addr);	if (str) {		free(str);		return error_bonding_already_exists(conn, msg);	}	sk = l2raw_connect(adapter->address, &peer_bdaddr);	if (sk < 0)		return error_connection_attempt_failed(conn, msg, 0);	adapter->bonding = bonding_request_new(&peer_bdaddr, conn, msg);	if (!adapter->bonding) {		close(sk);		return DBUS_HANDLER_RESULT_NEED_MEMORY;	}	adapter->bonding->io = g_io_channel_unix_new(sk);	adapter->bonding->io_id = g_io_add_watch(adapter->bonding->io,						G_IO_OUT | G_IO_NVAL | G_IO_HUP | G_IO_ERR,						(GIOFunc) create_bonding_conn_complete,						adapter);	name_listener_add(conn, dbus_message_get_sender(msg),			(name_cb_t) create_bond_req_exit, adapter);	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult adapter_cancel_bonding(DBusConnection *conn,						DBusMessage *msg, void *data){	struct adapter *adapter = data;	DBusMessage *reply;	bdaddr_t peer_bdaddr;	const char *peer_addr;	GSList *l;	if (!adapter->up)		return error_not_ready(conn, msg);	if (!dbus_message_get_args(msg, NULL,				DBUS_TYPE_STRING, &peer_addr,				DBUS_TYPE_INVALID))		return error_invalid_arguments(conn, msg, NULL);	if (check_address(peer_addr) < 0)		return error_invalid_arguments(conn, msg, NULL);	str2ba(peer_addr, &peer_bdaddr);	if (!adapter->bonding || bacmp(&adapter->bonding->bdaddr, &peer_bdaddr))		return error_bonding_not_in_progress(conn, msg);	if (strcmp(dbus_message_get_sender(adapter->bonding->rq),				dbus_message_get_sender(msg)))		return error_not_authorized(conn, msg);	adapter->bonding->cancel = 1;	l = g_slist_find_custom(adapter->pin_reqs, &peer_bdaddr, pin_req_cmp);	if (l) {		struct pending_pin_info *pin_req = l->data;		if (pin_req->replied) {			/*			 * If disconnect can't be applied and the PIN code			 * request was already replied it doesn't make sense			 * cancel the remote passkey: return not authorized.			 */			g_io_channel_close(adapter->bonding->io);			return error_not_authorized(conn, msg);		} else {			int dd = hci_open_dev(adapter->dev_id);			if (dd < 0) {				error("Can't open hci%d: %s (%d)",					adapter->dev_id, strerror(errno), errno);				return DBUS_HANDLER_RESULT_HANDLED;			}			hci_send_cmd(dd, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY,					6, &peer_bdaddr);			hci_close_dev(dd);		}		adapter->pin_reqs = g_slist_remove(adapter->pin_reqs, pin_req);		g_free(pin_req);	}	g_io_channel_close(adapter->bonding->io);	reply = dbus_message_new_method_return(msg);	send_message_and_unref(conn, reply);	return DBUS_HANDLER_RESULT_HANDLED;}static DBusHandlerResult adapter_remove_bonding(DBusConnection *conn,						DBusMessage *msg, void *data){	struct adapter *adapter = data;	GSList *l;	DBusMessage *reply;	char filename[PATH_MAX + 1];	char *addr_ptr, *str;	bdaddr_t bdaddr;	int dd;	if (!adapter->up)		return error_not_ready(conn, msg);	if (!dbus_message_get_args(msg, NULL,				DBUS_TYPE_STRING, &addr_ptr,				DBUS_TYPE_INVALID))		return error_invalid_arguments(conn, msg, NULL);	if (check_address(addr_ptr) < 0)		return error_invalid_arguments(conn, msg, NULL);	dd = hci_open_dev(adapter->dev_id);	if (dd < 0)		return error_no_such_adapter(conn, msg);	create_name(filename, PATH_MAX, STORAGEDIR, adapter->address,			"linkkeys");	/* textfile_del doesn't return an error when the key is not found */	str = textfile_caseget(filename, addr_ptr);	if (!str) {		hci_close_dev(dd);		return error_bonding_does_not_exist(conn, msg);	}	free(str);	/* Delete the link key from storage */	if (textfile_casedel(filename, addr_ptr) < 0) {		int err = errno;		hci_close_dev(dd);		return error_failed_errno(conn, msg, err);	}	str2ba(addr_ptr, &bdaddr);	/* Delete the link key from the Bluetooth chip */	hci_delete_stored_link_key(dd, &bdaddr, 0, 1000);	/* find the connection */	l = g_slist_find_custom(adapter->active_conn, &bdaddr,			active_conn_find_by_bdaddr);	if (l) {		struct active_conn_info *con = l->data;		/* Send the HCI disconnect command */		if (hci_disconnect(dd, htobs(con->handle),					HCI_OE_USER_ENDED_CONNECTION, 500) < 0) {			int err = errno;			error("Disconnect failed");			hci_close_dev(dd);			return error_failed_errno(conn, msg, err);		}	}	dbus_connection_emit_signal(conn, dbus_message_get_path(msg),					ADAPTER_INTERFACE, "BondingRemoved",					DBUS_TYPE_STRING, &addr_ptr,					DBUS_TYPE_INVALID);	reply = dbus_message_new_method_return(msg);	hci_close_dev(dd);	return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_has_bonding(DBusConnection *conn,						DBusMessage *msg, void *data){	struct adapter *adapter = data;	DBusMessage *reply;	char filename[PATH_MAX + 1];	char *addr_ptr, *str;	dbus_bool_t result;	if (!dbus_message_get_args(msg, NULL,				DBUS_TYPE_STRING, &addr_ptr,				DBUS_TYPE_INVALID))		return error_invalid_arguments(conn, msg, NULL);	if (check_address(addr_ptr) < 0)		return error_invalid_arguments(conn, msg, NULL);	create_name(filename, PATH_MAX, STORAGEDIR, adapter->address,			"linkkeys");	str = textfile_caseget(filename, addr_ptr);	if (str) {		result = TRUE;		free(str);	} else		result = FALSE;	reply = dbus_message_new_method_return(msg);	dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &result,					DBUS_TYPE_INVALID);	return send_message_and_unref(conn, reply);}static void list_bondings_do_append(char *key, char *value, void *data){	DBusMessageIter *iter = data;	dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);}static DBusHandlerResult adapter_list_bondings(DBusConnection *conn,						DBusMessage *msg, void *data){	struct adapter *adapter = data;	DBusMessageIter iter;	DBusMessageIter array_iter;	DBusMessage *reply;	char filename[PATH_MAX + 1];	if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING))		return error_invalid_arguments(conn, msg, NULL);	create_name(filename, PATH_MAX, STORAGEDIR, adapter->address,			"linkkeys");	reply = dbus_message_new_method_return(msg);	dbus_message_iter_init_append(reply, &iter);	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,				DBUS_TYPE_STRING_AS_STRING, &array_iter);	textfile_foreach(filename, list_bondings_do_append, &array_iter);	dbus_message_iter_close_container(&iter, &array_iter);	return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_get_pin_code_length(DBusConnection *conn,							DBusMessage *msg,							void *data){	struct adapter *adapter = data;	DBusMessage *reply;	bdaddr_t local, peer;	char *addr_ptr;	uint8_t length;	int len;	if (!dbus_message_get_args(msg, NULL,				DBUS_TYPE_STRING, &addr_ptr,				DBUS_TYPE_INVALID))		return error_invalid_arguments(conn, msg, NULL);	if (check_address(addr_ptr) < 0)		return error_invalid_arguments(conn, msg, NULL);	str2ba(adapter->address, &local);	str2ba(addr_ptr, &peer);	len = read_pin_length(&local, &peer);	if (len < 0)		return error_record_does_not_exist(conn, msg);	reply = dbus_message_new_method_return(msg);	length = len;	dbus_message_append_args(reply, DBUS_TYPE_BYTE, &length,					DBUS_TYPE_INVALID);	return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_get_encryption_key_size(DBusConnection *conn,							DBusMessage *msg,							void *data){	struct adapter *adapter = data;	DBusMessage *reply;	bdaddr_t bdaddr;	char *addr_ptr;	uint8_t size;	int val;	if (!dbus_message_get_args(msg, NULL,				DBUS_TYPE_STRING, &addr_ptr,				DBUS_TYPE_INVALID))		return error_invalid_arguments(conn, msg, NULL);	if (check_address(addr_ptr) < 0)		return error_invalid_arguments(conn, msg, NULL);	str2ba(addr_ptr, &bdaddr);	val = get_encryption_key_size(adapter->dev_id, &bdaddr);	if (val < 0)		return error_failed_errno(conn, msg, -val);	reply = dbus_message_new_method_return(msg);	size = val;	dbus_message_append_args(reply, DBUS_TYPE_BYTE, &size,					DBUS_TYPE_INVALID);	return send_message_and_unref(conn, reply);}static DBusHandlerResult adapter_start_periodic(DBusConnection *conn,						DBusMessage *msg, void *data){	DBusMessage *reply;	periodic_inquiry_cp cp;	struct hci_request rq;	struct adapter *adapter = data;	uint8_t lap[3] = { 0x33, 0x8b, 0x9e };	uint8_t status;	int dd;	if (!adapter->up)		return error_not_ready(conn, msg);	if (!dbus_message_has_signature(msg, DBUS_TYPE_INVALID_AS_STRING))		return error_invalid_arguments(conn, msg, NULL);	if (adapter->discov_active || adapter->pdiscov_active)		return error_discover_in_progress(conn, msg);	pending_remote_name_cancel(adapter);	dd = hci_open_dev(adapter->dev_id);	if (dd < 0)		return error_no_such_adapter(conn, msg);	memset(&cp, 0, sizeof(cp));	memcpy(&cp.lap, lap, 3);	cp.max_period = htobs(24);	cp.min_period = htobs(16);	cp.length  = 0x08;	cp.num_rsp = 0x00;	memset(&rq, 0, sizeof(rq));	rq.ogf    = OGF_LINK_CTL;	rq.ocf    = OCF_PERIODIC_INQUIRY;	rq.cparam = &cp;	rq.clen   = PERIODIC_INQUIRY_CP_SIZE;	rq.rparam = &status;	rq.rlen   = sizeof(status);	rq.event  = EVT_CMD_COMPLETE;	if (hci_send_req(dd, &rq, 1000) < 0) {		int err = errno;		error("Unable to start periodic inquiry: %s (%d)",				strerror(errno), errno);		hci_close_dev(dd);		return error_failed_errno(conn, msg, err);	}	if (status) {		error("HCI_Periodic_Inquiry_Mode failed with status 0x%02x",				status);		hci_close_dev(dd);		return error_failed_errno(conn, msg, bt_error(status));	}	adapter->pdiscov_requestor = g_strdup(dbus_message_get_sender(msg));	if (adapter->pdiscov_resolve_names)		adapter->discov_type = PERIODIC_INQUIRY | RESOLVE_NAME;	else		adapter->discov_type = PERIODIC_INQUIRY;	reply = dbus_message_new_method_return(msg);	hci_close_dev(dd);	/* track the request owner

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -