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

📄 hci_event.c

📁 Linux嵌入式平台蓝牙协议栈软件
💻 C
📖 第 1 页 / 共 2 页
字号:
	__u8 status = *((__u8 *) skb->data);	BT_DBG("%s status %d", hdev->name, status);	clear_bit(HCI_INQUIRY, &hdev->flags);	hci_req_complete(hdev, status);}/* Inquiry Result */static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb){	struct inquiry_info *info = (struct inquiry_info *) (skb->data + 1);	int num_rsp = *((__u8 *) skb->data);	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);	hci_dev_lock(hdev);	for (; num_rsp; num_rsp--)		hci_inquiry_cache_update(hdev, info++);	hci_dev_unlock(hdev);}/* Inquiry Result With RSSI */static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb){	struct inquiry_info_with_rssi *info = (struct inquiry_info_with_rssi *) (skb->data + 1);	int num_rsp = *((__u8 *) skb->data);	BT_DBG("%s num_rsp %d", hdev->name, num_rsp);	hci_dev_lock(hdev);	for (; num_rsp; num_rsp--) {		struct inquiry_info tmp;		bacpy(&tmp.bdaddr, &info->bdaddr);		tmp.pscan_rep_mode    = info->pscan_rep_mode;		tmp.pscan_period_mode = info->pscan_period_mode;		tmp.pscan_mode        = 0x00;		memcpy(tmp.dev_class, &info->dev_class, 3);		tmp.clock_offset      = info->clock_offset;		info++;		hci_inquiry_cache_update(hdev, &tmp);	}	hci_dev_unlock(hdev);}/* Connect Request */static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb){	struct hci_ev_conn_request *ev = (struct hci_ev_conn_request *) skb->data;	int mask = hdev->link_mode;	BT_DBG("%s Connection request: %s type 0x%x", hdev->name,			batostr(&ev->bdaddr), ev->link_type);	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);	if (mask & HCI_LM_ACCEPT) {		/* Connection accepted */		struct hci_conn *conn;		struct hci_cp_accept_conn_req cp;		hci_dev_lock(hdev);		conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);		if (!conn) {			if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) {				BT_ERR("No memmory for new connection");				hci_dev_unlock(hdev);				return;			}		}		conn->state = BT_CONNECT;		hci_dev_unlock(hdev);		bacpy(&cp.bdaddr, &ev->bdaddr);			if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))			cp.role = 0x00; /* Become master */		else			cp.role = 0x01; /* Remain slave */		hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ACCEPT_CONN_REQ, sizeof(cp), &cp);	} else {		/* Connection rejected */		struct hci_cp_reject_conn_req cp;		bacpy(&cp.bdaddr, &ev->bdaddr);		cp.reason = 0x0f;		hci_send_cmd(hdev, OGF_LINK_CTL, OCF_REJECT_CONN_REQ, sizeof(cp), &cp);	}}/* Connect Complete */static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb){	struct hci_ev_conn_complete *ev = (struct hci_ev_conn_complete *) skb->data;	struct hci_conn *conn = NULL;	BT_DBG("%s", hdev->name);	hci_dev_lock(hdev);	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);	if (!conn) {		hci_dev_unlock(hdev);		return;	}	if (!ev->status) {		conn->handle = __le16_to_cpu(ev->handle);		conn->state  = BT_CONNECTED;		if (test_bit(HCI_AUTH, &hdev->flags))			conn->link_mode |= HCI_LM_AUTH;		if (test_bit(HCI_ENCRYPT, &hdev->flags))			conn->link_mode |= HCI_LM_ENCRYPT;		/* Set link policy */		if (conn->type == ACL_LINK && hdev->link_policy) {			struct hci_cp_write_link_policy cp;			cp.handle = ev->handle;			cp.policy = __cpu_to_le16(hdev->link_policy);			hci_send_cmd(hdev, OGF_LINK_POLICY, OCF_WRITE_LINK_POLICY, sizeof(cp), &cp);		}		/* Set packet type for incoming connection */		if (!conn->out) {			struct hci_cp_change_conn_ptype cp;			cp.handle = ev->handle;			cp.pkt_type = (conn->type == ACL_LINK) ? 				__cpu_to_le16(hdev->pkt_type & ACL_PTYPE_MASK):				__cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);			hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CHANGE_CONN_PTYPE, sizeof(cp), &cp);		}	} else		conn->state = BT_CLOSED;	if (conn->type == ACL_LINK) {		struct hci_conn *sco = conn->link;		if (sco) {			if (!ev->status)				hci_add_sco(sco, conn->handle);			else {				hci_proto_connect_cfm(sco, ev->status);				hci_conn_del(sco);			}		}	}	hci_proto_connect_cfm(conn, ev->status);	if (ev->status)		hci_conn_del(conn);	hci_dev_unlock(hdev);}/* Disconnect Complete */static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb){	struct hci_ev_disconn_complete *ev = (struct hci_ev_disconn_complete *) skb->data;	struct hci_conn *conn = NULL;	__u16 handle = __le16_to_cpu(ev->handle);	BT_DBG("%s status %d", hdev->name, ev->status);	if (ev->status)		return;	hci_dev_lock(hdev);	conn = hci_conn_hash_lookup_handle(hdev, handle);	if (conn) {		conn->state = BT_CLOSED;		hci_proto_disconn_ind(conn, ev->reason);		hci_conn_del(conn);	}	hci_dev_unlock(hdev);}/* Number of completed packets */static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb){	struct hci_ev_num_comp_pkts *ev = (struct hci_ev_num_comp_pkts *) skb->data;	__u16 *ptr;	int i;	skb_pull(skb, sizeof(*ev));	BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);	if (skb->len < ev->num_hndl * 4) {		BT_DBG("%s bad parameters", hdev->name);		return;	}	tasklet_disable(&hdev->tx_task);	for (i = 0, ptr = (__u16 *) skb->data; i < ev->num_hndl; i++) {		struct hci_conn *conn;		__u16  handle, count;		handle = __le16_to_cpu(get_unaligned(ptr++));		count  = __le16_to_cpu(get_unaligned(ptr++));		conn = hci_conn_hash_lookup_handle(hdev, handle);		if (conn) {			conn->sent -= count;			if (conn->type == SCO_LINK) {				if ((hdev->sco_cnt += count) > hdev->sco_pkts)					hdev->sco_cnt = hdev->sco_pkts;			} else {				if ((hdev->acl_cnt += count) > hdev->acl_pkts)					hdev->acl_cnt = hdev->acl_pkts;			}		}	}	hci_sched_tx(hdev);	tasklet_enable(&hdev->tx_task);}/* Role Change */static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb){	struct hci_ev_role_change *ev = (struct hci_ev_role_change *) skb->data;	struct hci_conn *conn = NULL;	BT_DBG("%s status %d", hdev->name, ev->status);	if (ev->status)		return;	hci_dev_lock(hdev);	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);	if (conn) {		if (ev->role)			conn->link_mode &= ~HCI_LM_MASTER;		else 			conn->link_mode |= HCI_LM_MASTER;	}	hci_dev_unlock(hdev);}/* Authentication Complete */static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb){	struct hci_ev_auth_complete *ev = (struct hci_ev_auth_complete *) skb->data;	struct hci_conn *conn = NULL;	__u16 handle = __le16_to_cpu(ev->handle);	BT_DBG("%s status %d", hdev->name, ev->status);	hci_dev_lock(hdev);	conn = hci_conn_hash_lookup_handle(hdev, handle);	if (conn) {		if (!ev->status)			conn->link_mode |= HCI_LM_AUTH;		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);		hci_proto_auth_cfm(conn, ev->status);		if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {			if (!ev->status) {				struct hci_cp_set_conn_encrypt cp;				cp.handle  = __cpu_to_le16(conn->handle);				cp.encrypt = 1;				hci_send_cmd(conn->hdev, OGF_LINK_CTL,						OCF_SET_CONN_ENCRYPT,						sizeof(cp), &cp);			} else {				clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);				hci_proto_encrypt_cfm(conn, ev->status);			}		}	}	hci_dev_unlock(hdev);}/* Encryption Change */static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb){	struct hci_ev_encrypt_change *ev = (struct hci_ev_encrypt_change *) skb->data;	struct hci_conn *conn = NULL;	__u16 handle = __le16_to_cpu(ev->handle);	BT_DBG("%s status %d", hdev->name, ev->status);	hci_dev_lock(hdev);	conn = hci_conn_hash_lookup_handle(hdev, handle);	if (conn) {		if (!ev->status) {			if (ev->encrypt)				conn->link_mode |= HCI_LM_ENCRYPT;			else				conn->link_mode &= ~HCI_LM_ENCRYPT;		}		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);				hci_proto_encrypt_cfm(conn, ev->status);	}	hci_dev_unlock(hdev);}void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb){	struct hci_event_hdr *hdr = (struct hci_event_hdr *) skb->data;	struct hci_ev_cmd_complete *ec;	struct hci_ev_cmd_status *cs;	u16 opcode, ocf, ogf;	skb_pull(skb, HCI_EVENT_HDR_SIZE);	BT_DBG("%s evt 0x%x", hdev->name, hdr->evt);	switch (hdr->evt) {	case HCI_EV_NUM_COMP_PKTS:		hci_num_comp_pkts_evt(hdev, skb);		break;	case HCI_EV_INQUIRY_COMPLETE:		hci_inquiry_complete_evt(hdev, skb);		break;	case HCI_EV_INQUIRY_RESULT:		hci_inquiry_result_evt(hdev, skb);		break;	case HCI_EV_INQUIRY_RESULT_WITH_RSSI:		hci_inquiry_result_with_rssi_evt(hdev, skb);		break;	case HCI_EV_CONN_REQUEST:		hci_conn_request_evt(hdev, skb);		break;	case HCI_EV_CONN_COMPLETE:		hci_conn_complete_evt(hdev, skb);		break;	case HCI_EV_DISCONN_COMPLETE:		hci_disconn_complete_evt(hdev, skb);		break;	case HCI_EV_ROLE_CHANGE:		hci_role_change_evt(hdev, skb);		break;	case HCI_EV_AUTH_COMPLETE:		hci_auth_complete_evt(hdev, skb);		break;	case HCI_EV_ENCRYPT_CHANGE:		hci_encrypt_change_evt(hdev, skb);		break;	case HCI_EV_CMD_STATUS:		cs = (struct hci_ev_cmd_status *) skb->data;		skb_pull(skb, sizeof(cs));		opcode = __le16_to_cpu(cs->opcode);		ogf = hci_opcode_ogf(opcode);		ocf = hci_opcode_ocf(opcode);		switch (ogf) {		case OGF_INFO_PARAM:			hci_cs_info_param(hdev, ocf, cs->status);			break;		case OGF_HOST_CTL:			hci_cs_host_ctl(hdev, ocf, cs->status);			break;		case OGF_LINK_CTL:			hci_cs_link_ctl(hdev, ocf, cs->status);			break;		case OGF_LINK_POLICY:			hci_cs_link_policy(hdev, ocf, cs->status);			break;		default:			BT_DBG("%s Command Status OGF %x", hdev->name, ogf);			break;		}		if (cs->ncmd) {			atomic_set(&hdev->cmd_cnt, 1);			if (!skb_queue_empty(&hdev->cmd_q))				hci_sched_cmd(hdev);		}		break;	case HCI_EV_CMD_COMPLETE:		ec = (struct hci_ev_cmd_complete *) skb->data;		skb_pull(skb, sizeof(*ec));		opcode = __le16_to_cpu(ec->opcode);		ogf = hci_opcode_ogf(opcode);		ocf = hci_opcode_ocf(opcode);		switch (ogf) {		case OGF_INFO_PARAM:			hci_cc_info_param(hdev, ocf, skb);			break;		case OGF_HOST_CTL:			hci_cc_host_ctl(hdev, ocf, skb);			break;		case OGF_LINK_CTL:			hci_cc_link_ctl(hdev, ocf, skb);			break;		case OGF_LINK_POLICY:			hci_cc_link_policy(hdev, ocf, skb);			break;		default:			BT_DBG("%s Command Completed OGF %x", hdev->name, ogf);			break;		}		if (ec->ncmd) {			atomic_set(&hdev->cmd_cnt, 1);			if (!skb_queue_empty(&hdev->cmd_q))				hci_sched_cmd(hdev);		}		break;	}	kfree_skb(skb);	hdev->stat.evt_rx++;}/* Generate internal stack event */void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data){	struct hci_event_hdr *hdr;	struct hci_ev_stack_internal *ev;	struct sk_buff *skb;	skb = bt_skb_alloc(HCI_EVENT_HDR_SIZE + sizeof(*ev) + dlen, GFP_ATOMIC);	if (!skb)		return;	hdr = (void *) skb_put(skb, HCI_EVENT_HDR_SIZE);	hdr->evt  = HCI_EV_STACK_INTERNAL;	hdr->plen = sizeof(*ev) + dlen;	ev  = (void *) skb_put(skb, sizeof(*ev) + dlen);	ev->type = type;	memcpy(ev->data, data, dlen);	skb->pkt_type = HCI_EVENT_PKT;	skb->dev = (void *) hdev;	hci_send_to_sock(hdev, skb);	kfree_skb(skb);}EXPORT_SYMBOL(hci_si_event);

⌨️ 快捷键说明

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