📄 hci_event.c
字号:
for (; num_rsp; num_rsp--) inquiry_cache_update(hdev, info++); hci_dev_unlock(hdev);}/* Connect Request */static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb){ evt_conn_request *cr = (evt_conn_request *) skb->data; int mask = hdev->link_mode; BT_DBG("%s Connection request: %s type 0x%x", hdev->name, batostr(&cr->bdaddr), cr->link_type); mask |= hci_proto_connect_ind(hdev, &cr->bdaddr, cr->link_type); if (mask & HCI_LM_ACCEPT) { /* Connection accepted */ struct hci_conn *conn; accept_conn_req_cp ac; hci_dev_lock(hdev); conn = conn_hash_lookup_ba(hdev, cr->link_type, &cr->bdaddr); if (!conn) { if (!(conn = hci_conn_add(hdev, cr->link_type, &cr->bdaddr))) { BT_ERR("No memmory for new connection"); hci_dev_unlock(hdev); return; } } conn->state = BT_CONNECT; hci_dev_unlock(hdev); bacpy(&ac.bdaddr, &cr->bdaddr); if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) ac.role = 0x00; /* Become master */ else ac.role = 0x01; /* Remain slave */ hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ACCEPT_CONN_REQ, ACCEPT_CONN_REQ_CP_SIZE, &ac); } else { /* Connection rejected */ reject_conn_req_cp rc; bacpy(&rc.bdaddr, &cr->bdaddr); rc.reason = 0x0f; hci_send_cmd(hdev, OGF_LINK_CTL, OCF_REJECT_CONN_REQ, REJECT_CONN_REQ_CP_SIZE, &rc); }}/* Connect Complete */static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb){ evt_conn_complete *cc = (evt_conn_complete *) skb->data; struct hci_conn *conn = NULL; BT_DBG("%s", hdev->name); hci_dev_lock(hdev); conn = conn_hash_lookup_ba(hdev, cc->link_type, &cc->bdaddr); if (!conn) { hci_dev_unlock(hdev); return; } if (!cc->status) { conn->handle = __le16_to_cpu(cc->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) { write_link_policy_cp lp; lp.handle = cc->handle; lp.policy = __cpu_to_le16(hdev->link_policy); hci_send_cmd(hdev, OGF_LINK_POLICY, OCF_WRITE_LINK_POLICY, WRITE_LINK_POLICY_CP_SIZE, &lp); } /* Set packet type for incomming connection */ if (!conn->out) { change_conn_ptype_cp cp; cp.handle = cc->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, CHANGE_CONN_PTYPE_CP_SIZE, &cp); } } else conn->state = BT_CLOSED; if (conn->type == ACL_LINK) { struct hci_conn *sco = conn->link; if (sco) { if (!cc->status) hci_add_sco(sco, conn->handle); else { hci_proto_connect_cfm(sco, cc->status); hci_conn_del(sco); } } } hci_proto_connect_cfm(conn, cc->status); if (cc->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){ evt_disconn_complete *dc = (evt_disconn_complete *) skb->data; struct hci_conn *conn = NULL; __u16 handle = __le16_to_cpu(dc->handle); BT_DBG("%s status %d", hdev->name, dc->status); if (dc->status) return; hci_dev_lock(hdev); conn = conn_hash_lookup_handle(hdev, handle); if (conn) { conn->state = BT_CLOSED; hci_proto_disconn_ind(conn, dc->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){ evt_num_comp_pkts *nc = (evt_num_comp_pkts *) skb->data; __u16 *ptr; int i; skb_pull(skb, EVT_NUM_COMP_PKTS_SIZE); BT_DBG("%s num_hndl %d", hdev->name, nc->num_hndl); if (skb->len < nc->num_hndl * 4) { BT_DBG("%s bad parameters", hdev->name); return; } tasklet_disable(&hdev->tx_task); for (i = 0, ptr = (__u16 *) skb->data; i < nc->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 = 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){ evt_role_change *rc = (evt_role_change *) skb->data; struct hci_conn *conn = NULL; BT_DBG("%s status %d", hdev->name, rc->status); if (rc->status) return; hci_dev_lock(hdev); conn = conn_hash_lookup_ba(hdev, ACL_LINK, &rc->bdaddr); if (conn) { if (rc->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){ evt_auth_complete *ac = (evt_auth_complete *) skb->data; struct hci_conn *conn = NULL; __u16 handle = __le16_to_cpu(ac->handle); BT_DBG("%s status %d", hdev->name, ac->status); hci_dev_lock(hdev); conn = conn_hash_lookup_handle(hdev, handle); if (conn) { if (!ac->status) conn->link_mode |= HCI_LM_AUTH; clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); hci_proto_auth_cfm(conn, ac->status); if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) { if (!ac->status) { set_conn_encrypt_cp ce; ce.handle = __cpu_to_le16(conn->handle); ce.encrypt = 1; hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_SET_CONN_ENCRYPT, SET_CONN_ENCRYPT_CP_SIZE, &ce); } else { clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); hci_proto_encrypt_cfm(conn, ac->status); } } } hci_dev_unlock(hdev);}/* Encryption Change */static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb){ evt_encrypt_change *ec = (evt_encrypt_change *) skb->data; struct hci_conn *conn = NULL; __u16 handle = __le16_to_cpu(ec->handle); BT_DBG("%s status %d", hdev->name, ec->status); hci_dev_lock(hdev); conn = conn_hash_lookup_handle(hdev, handle); if (conn) { if (!ec->status) { if (ec->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, ec->status); } hci_dev_unlock(hdev);}void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb){ hci_event_hdr *he = (hci_event_hdr *) skb->data; evt_cmd_status *cs; evt_cmd_complete *ec; __u16 opcode, ocf, ogf; skb_pull(skb, HCI_EVENT_HDR_SIZE); BT_DBG("%s evt 0x%x", hdev->name, he->evt); switch (he->evt) { case EVT_NUM_COMP_PKTS: hci_num_comp_pkts_evt(hdev, skb); break; case EVT_INQUIRY_COMPLETE: hci_inquiry_complete_evt(hdev, skb); break; case EVT_INQUIRY_RESULT: hci_inquiry_result_evt(hdev, skb); break; case EVT_CONN_REQUEST: hci_conn_request_evt(hdev, skb); break; case EVT_CONN_COMPLETE: hci_conn_complete_evt(hdev, skb); break; case EVT_DISCONN_COMPLETE: hci_disconn_complete_evt(hdev, skb); break; case EVT_ROLE_CHANGE: hci_role_change_evt(hdev, skb); break; case EVT_AUTH_COMPLETE: hci_auth_complete_evt(hdev, skb); break; case EVT_ENCRYPT_CHANGE: hci_encrypt_change_evt(hdev, skb); break; case EVT_CMD_STATUS: cs = (evt_cmd_status *) skb->data; skb_pull(skb, EVT_CMD_STATUS_SIZE); opcode = __le16_to_cpu(cs->opcode); ogf = cmd_opcode_ogf(opcode); ocf = cmd_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 EVT_CMD_COMPLETE: ec = (evt_cmd_complete *) skb->data; skb_pull(skb, EVT_CMD_COMPLETE_SIZE); opcode = __le16_to_cpu(ec->opcode); ogf = cmd_opcode_ogf(opcode); ocf = cmd_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++;}/* General internal stack event */void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data){ hci_event_hdr *eh; evt_stack_internal *si; struct sk_buff *skb; int size; void *ptr; size = HCI_EVENT_HDR_SIZE + EVT_STACK_INTERNAL_SIZE + dlen; skb = bluez_skb_alloc(size, GFP_ATOMIC); if (!skb) return; ptr = skb_put(skb, size); eh = ptr; eh->evt = EVT_STACK_INTERNAL; eh->plen = EVT_STACK_INTERNAL_SIZE + dlen; ptr += HCI_EVENT_HDR_SIZE; si = ptr; si->type = type; memcpy(si->data, data, dlen); skb->pkt_type = HCI_EVENT_PKT; skb->dev = (void *) hdev; hci_send_to_sock(hdev, skb); kfree_skb(skb);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -