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

📄 dbus-hci.c

📁 Linux的蓝牙操作工具。配合bluez-lib使用
💻 C
📖 第 1 页 / 共 4 页
字号:
	snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id);	if (hci_devinfo(id, &di) < 0) {		error("Getting device info failed: hci%d", id);		return -1;	}	if (hci_test_bit(HCI_RAW, &di.flags))		return -1;	if (!dbus_connection_get_object_user_data(connection, path,							(void *) &adapter)) {		error("Getting %s path data failed!", path);		return -1;	}	if (hci_test_bit(HCI_INQUIRY, &di.flags))		adapter->discov_active = 1;	else		adapter->discov_active = 0;	adapter->up = 1;	adapter->discov_timeout = get_discoverable_timeout(id);	adapter->discov_type = DISCOVER_TYPE_NONE;	dd = hci_open_dev(id);	if (dd < 0)		goto failed;	adapter->scan_enable = get_startup_scan(id);	hci_send_cmd(dd, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE,					1, &adapter->scan_enable);	/*	 * Get the adapter Bluetooth address	 */	err = get_device_address(adapter->dev_id, adapter->address,					sizeof(adapter->address));	if (err < 0)		goto failed;	err = get_device_class(adapter->dev_id, adapter->class);	if (err < 0)		goto failed;	adapter->mode = get_startup_mode(id);	if (adapter->mode == MODE_LIMITED)		set_limited_discoverable(dd, adapter->class, TRUE);	/*	 * retrieve the active connections: address the scenario where	 * the are active connections before the daemon've started	 */	cl = g_malloc0(10 * sizeof(*ci) + sizeof(*cl));	cl->dev_id = id;	cl->conn_num = 10;	ci = cl->conn_info;	if (ioctl(dd, HCIGETCONNLIST, cl) < 0)		goto failed;	for (i = 0; i < cl->conn_num; i++, ci++)		active_conn_append(&adapter->active_conn,					&ci->bdaddr, ci->handle);	ret = 0;	mode = mode2str(adapter->mode);	dbus_connection_emit_signal(connection, path, ADAPTER_INTERFACE,					"ModeChanged",					DBUS_TYPE_STRING, &mode,					DBUS_TYPE_INVALID);failed:	if (ret == 0 && get_default_adapter() < 0)		set_default_adapter(id);	if (dd >= 0)		hci_close_dev(dd);	g_free(cl);	return ret;}static void send_dc_signal(struct active_conn_info *dev, const char *path){	char addr[18];	const char *paddr = addr;	ba2str(&dev->bdaddr, addr);	dbus_connection_emit_signal(connection, path, ADAPTER_INTERFACE,					"RemoteDeviceDisconnected",					DBUS_TYPE_STRING, &paddr,					DBUS_TYPE_INVALID);}int hcid_dbus_stop_device(uint16_t id){	char path[MAX_PATH_LENGTH];	struct adapter *adapter;	const char *mode = "off";	snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id);	if (!dbus_connection_get_object_user_data(connection, path,							(void *) &adapter)) {		error("Getting %s path data failed!", path);		return -1;	}	/* cancel pending timeout */	if (adapter->timeout_id) {		g_source_remove(adapter->timeout_id);		adapter->timeout_id = 0;	}	/* check pending requests */	reply_pending_requests(path, adapter);	cancel_passkey_agent_requests(adapter->passkey_agents, path, NULL);	release_passkey_agents(adapter, NULL);	if (adapter->discov_requestor) {		name_listener_remove(connection, adapter->discov_requestor,					(name_cb_t) discover_devices_req_exit,					adapter);		g_free(adapter->discov_requestor);		adapter->discov_requestor = NULL;	}	if (adapter->pdiscov_requestor) {		name_listener_remove(connection, adapter->pdiscov_requestor,					(name_cb_t) periodic_discover_req_exit,					adapter);		g_free(adapter->pdiscov_requestor);		adapter->pdiscov_requestor = NULL;	}	if (adapter->found_devices) {		g_slist_foreach(adapter->found_devices, (GFunc) g_free, NULL);		g_slist_free(adapter->found_devices);		adapter->found_devices = NULL;	}	if (adapter->oor_devices) {		g_slist_foreach(adapter->oor_devices, (GFunc) free, NULL);		g_slist_free(adapter->oor_devices);		adapter->oor_devices = NULL;	}	if (adapter->pin_reqs) {		g_slist_foreach(adapter->pin_reqs, (GFunc) g_free, NULL);		g_slist_free(adapter->pin_reqs);		adapter->pin_reqs = NULL;	}	if (adapter->active_conn) {		g_slist_foreach(adapter->active_conn, (GFunc) send_dc_signal, path);		g_slist_foreach(adapter->active_conn, (GFunc) g_free, NULL);		g_slist_free(adapter->active_conn);		adapter->active_conn = NULL;	}	send_adapter_signal(connection, adapter->dev_id, "ModeChanged",				DBUS_TYPE_STRING, &mode,				DBUS_TYPE_INVALID);	adapter->up = 0;	adapter->scan_enable = SCAN_DISABLED;	adapter->mode = MODE_OFF;	adapter->discov_active = 0;	adapter->pdiscov_active = 0;	adapter->pinq_idle = 0;	adapter->discov_type = DISCOVER_TYPE_NONE;	return 0;}int pin_req_cmp(const void *p1, const void *p2){	const struct pending_pin_info *pb1 = p1;	const struct pending_pin_info *pb2 = p2;	return p2 ? bacmp(&pb1->bdaddr, &pb2->bdaddr) : -1;}void hcid_dbus_pending_pin_req_add(bdaddr_t *sba, bdaddr_t *dba){	char path[MAX_PATH_LENGTH], addr[18];	struct adapter *adapter;	struct pending_pin_info *info;	int id;	ba2str(sba, addr);	id = hci_devid(addr);	if (id < 0) {		error("No matching device id for %s", addr);		return;	}	snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id);	if (!dbus_connection_get_object_user_data(connection, path,							(void *) &adapter)) {		error("Getting %s path data failed!", path);		return;	}	info = g_new0(struct pending_pin_info, 1);	bacpy(&info->bdaddr, dba);	adapter->pin_reqs = g_slist_append(adapter->pin_reqs, info);	if (adapter->bonding && !bacmp(dba, &adapter->bonding->bdaddr))		adapter->bonding->auth_active = 1;}int hcid_dbus_request_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci){	char path[MAX_PATH_LENGTH], addr[18];	int id;	ba2str(sba, addr);	id = hci_devid(addr);	if (id < 0) {		error("No matching device id for %s", addr);		return -1;	}	snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id);	return handle_passkey_request(connection, dev, path, sba, &ci->bdaddr);}int hcid_dbus_confirm_pin(int dev, bdaddr_t *sba, struct hci_conn_info *ci, char *pin){	char path[MAX_PATH_LENGTH], addr[18];	int id;	ba2str(sba, addr);	id = hci_devid(addr);	if (id < 0) {		error("No matching device id for %s", addr);		return -1;	}	snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id);	return handle_confirm_request(connection, dev, path, sba, &ci->bdaddr, pin);}void hcid_dbus_bonding_process_complete(bdaddr_t *local, bdaddr_t *peer,					uint8_t status){	struct adapter *adapter;	char path[MAX_PATH_LENGTH], local_addr[18], peer_addr[18];	const char *paddr = peer_addr;	GSList *l;	int id;	ba2str(local, local_addr);	ba2str(peer, peer_addr);	id = hci_devid(local_addr);	if (id < 0) {		error("No matching device id for %s", local_addr);		return;	}	snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id);	/* create the authentication reply */	if (!dbus_connection_get_object_user_data(connection, path,							(void *) &adapter)) {		error("Getting %s path data failed!", path);		return;	}	if (status)		cancel_passkey_agent_requests(adapter->passkey_agents, path,						peer);	l = g_slist_find_custom(adapter->pin_reqs, peer, pin_req_cmp);	if (l) {		void *d = l->data;		adapter->pin_reqs = g_slist_remove(adapter->pin_reqs, l->data);		g_free(d);		if (!status)			send_adapter_signal(connection, adapter->dev_id,						"BondingCreated",						DBUS_TYPE_STRING, &paddr,						DBUS_TYPE_INVALID);	}	release_passkey_agents(adapter, peer);	if (!adapter->bonding || bacmp(&adapter->bonding->bdaddr, peer))		return; /* skip: no bonding req pending */	if (adapter->bonding->cancel) {		/* reply authentication canceled */		error_authentication_canceled(connection, adapter->bonding->rq);	} else {		DBusMessage *reply;		/* reply authentication success or an error */		reply = new_authentication_return(adapter->bonding->rq,							status);		send_message_and_unref(connection, reply);	}	name_listener_remove(connection,				dbus_message_get_sender(adapter->bonding->rq),				(name_cb_t) create_bond_req_exit, adapter);	if (adapter->bonding->io_id)		g_source_remove(adapter->bonding->io_id);	g_io_channel_close(adapter->bonding->io);	bonding_request_free(adapter->bonding);	adapter->bonding = NULL;}void hcid_dbus_inquiry_start(bdaddr_t *local){	struct adapter *adapter;	char path[MAX_PATH_LENGTH], local_addr[18];	int id;	ba2str(local, local_addr);	id = hci_devid(local_addr);	if (id < 0) {		error("No matching device id for %s", local_addr);		return;	}	snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id);	if (dbus_connection_get_object_user_data(connection, path,							(void *) &adapter)) {		adapter->discov_active = 1;		/* 		 * Cancel pending remote name request and clean the device list		 * when inquiry is supported in periodic inquiry idle state.		 */		if (adapter->pdiscov_active)			pending_remote_name_cancel(adapter);		/* Disable name resolution for non D-Bus clients */		if (!adapter->discov_requestor)			adapter->discov_type &= ~RESOLVE_NAME;	}	send_adapter_signal(connection, adapter->dev_id, "DiscoveryStarted",				DBUS_TYPE_INVALID);}int found_device_req_name(struct adapter *adapter){	struct hci_request rq;	evt_cmd_status rp;	remote_name_req_cp cp;	struct remote_dev_info match;	GSList *l;	int dd, req_sent = 0;	/* get the next remote address */	if (!adapter->found_devices)		return -ENODATA;	memset(&match, 0, sizeof(struct remote_dev_info));	bacpy(&match.bdaddr, BDADDR_ANY);	match.name_status = NAME_REQUIRED;	l = g_slist_find_custom(adapter->found_devices, &match,					(GCompareFunc) found_device_cmp);	if (!l)		return -ENODATA;	dd = hci_open_dev(adapter->dev_id);	if (dd < 0)		return -errno;	memset(&rq, 0, sizeof(rq));	rq.ogf    = OGF_LINK_CTL;	rq.ocf    = OCF_REMOTE_NAME_REQ;	rq.cparam = &cp;	rq.clen   = REMOTE_NAME_REQ_CP_SIZE;	rq.rparam = &rp;	rq.rlen   = EVT_CMD_STATUS_SIZE;	rq.event  = EVT_CMD_STATUS;	/* send at least one request or return failed if the list is empty */	do {		struct remote_dev_info *dev = l->data;		char peer_addr[18];		const char *signal = NULL, *paddr = peer_addr;		 /* flag to indicate the current remote name requested */ 		dev->name_status = NAME_REQUESTED;		memset(&rp, 0, sizeof(rp));		memset(&cp, 0, sizeof(cp));		bacpy(&cp.bdaddr, &dev->bdaddr);		cp.pscan_rep_mode = 0x02;		ba2str(&dev->bdaddr, peer_addr);		if (hci_send_req(dd, &rq, 500) < 0) {			error("Unable to send the HCI remote name request: %s (%d)",						strerror(errno), errno);			signal = "RemoteNameFailed";		}		if (rp.status) {			error("Remote name request failed with status 0x%02x",					rp.status);			signal = "RemoteNameFailed";		}		if (!signal) {			req_sent = 1;			/* if we are in discovery, inform application of getting name */			if (adapter->discov_type & (STD_INQUIRY | PERIODIC_INQUIRY))				signal = "RemoteNameRequested";		}		if (signal)			send_adapter_signal(connection, adapter->dev_id, signal,						DBUS_TYPE_STRING, &paddr,						DBUS_TYPE_INVALID);		if (req_sent)			break;		/* if failed, request the next element */		/* remove the element from the list */		adapter->found_devices = g_slist_remove(adapter->found_devices, dev);		g_free(dev);		/* get the next element */		l = g_slist_find_custom(adapter->found_devices, &match,					(GCompareFunc) found_device_cmp);	} while (l);	hci_close_dev(dd);	if (!req_sent)		return -ENODATA;	return 0;}static void send_out_of_range(const char *path, GSList *l){	while (l) {		const char *peer_addr = l->data;		dbus_connection_emit_signal(connection, path,						ADAPTER_INTERFACE,						"RemoteDeviceDisappeared",						DBUS_TYPE_STRING, &peer_addr,						DBUS_TYPE_INVALID);		l = l->next;	}}void hcid_dbus_inquiry_complete(bdaddr_t *local){	struct adapter *adapter;	GSList *l;	char path[MAX_PATH_LENGTH], local_addr[18];	struct remote_dev_info *dev;	bdaddr_t tmp;	int id;	ba2str(local, local_addr);	id = hci_devid(local_addr);	if (id < 0) {		error("No matching device id for %s", local_addr);		return;	}	snprintf(path, sizeof(path), "%s/hci%d", BASE_PATH, id);	if (!dbus_connection_get_object_user_data(connection, path,							(void *) &adapter)) {		error("Getting %s path data failed!", path);		goto done;	}	/* Out of range verification */	if (adapter->pdiscov_active && !adapter->discov_active) {		send_out_of_range(path, adapter->oor_devices);		g_slist_foreach(adapter->oor_devices, (GFunc) free, NULL);		g_slist_free(adapter->oor_devices);		adapter->oor_devices = NULL;		l = adapter->found_devices;		while (l) {			dev = l->data;			baswap(&tmp, &dev->bdaddr);			adapter->oor_devices = g_slist_append(adapter->oor_devices,								batostr(&tmp));			l = l->next;		}	}	adapter->pinq_idle = 1;	/*	 * Enable resolution again: standard inquiry can be	 * received in the periodic inquiry idle state.	 */	if (adapter->pdiscov_requestor && adapter->pdiscov_resolve_names)		adapter->discov_type |= RESOLVE_NAME;	/*	 * The following scenarios can happen:	 * 1. standard inquiry: always send discovery completed signal	 * 2. standard inquiry + name resolving: send discovery completed	 *    after name resolving	 * 3. periodic inquiry: skip discovery completed signal	 * 4. periodic inquiry + standard inquiry: always send discovery	 *    completed signal	 *	 * Keep in mind that non D-Bus requests can arrive.	 */	if (!found_device_req_name(adapter))		goto done; /* skip - there is name to resolve */	if (adapter->discov_active) {		dbus_connection_emit_signal(connection, path,						ADAPTER_INTERFACE,						"DiscoveryCompleted",						DBUS_TYPE_INVALID);		adapter->discov_active = 0;	}	/* free discovered devices list */	g_slist_foreach(adapter->found_devices, (GFunc) g_free, NULL);	g_slist_free(adapter->found_devices);	adapter->found_devices = NULL;	if (adapter->discov_requestor) {		name_listener_remove(connection, adapter->discov_requestor,				(name_cb_t) discover_devices_req_exit, adapter);		g_free(adapter->discov_requestor);		adapter->discov_requestor = NULL;

⌨️ 快捷键说明

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