📄 hci_event.c
字号:
hci_cc_read_local_version(hdev, skb); break; case HCI_OP_READ_LOCAL_COMMANDS: hci_cc_read_local_commands(hdev, skb); break; case HCI_OP_READ_LOCAL_FEATURES: hci_cc_read_local_features(hdev, skb); break; case HCI_OP_READ_BUFFER_SIZE: hci_cc_read_buffer_size(hdev, skb); break; case HCI_OP_READ_BD_ADDR: hci_cc_read_bd_addr(hdev, skb); break; default: BT_DBG("%s opcode 0x%x", hdev->name, opcode); break; } if (ev->ncmd) { atomic_set(&hdev->cmd_cnt, 1); if (!skb_queue_empty(&hdev->cmd_q)) hci_sched_cmd(hdev); }}static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb){ struct hci_ev_cmd_status *ev = (void *) skb->data; __u16 opcode; skb_pull(skb, sizeof(*ev)); opcode = __le16_to_cpu(ev->opcode); switch (opcode) { case HCI_OP_INQUIRY: hci_cs_inquiry(hdev, ev->status); break; case HCI_OP_CREATE_CONN: hci_cs_create_conn(hdev, ev->status); break; case HCI_OP_ADD_SCO: hci_cs_add_sco(hdev, ev->status); break; case HCI_OP_REMOTE_NAME_REQ: hci_cs_remote_name_req(hdev, ev->status); break; case HCI_OP_SETUP_SYNC_CONN: hci_cs_setup_sync_conn(hdev, ev->status); break; case HCI_OP_SNIFF_MODE: hci_cs_sniff_mode(hdev, ev->status); break; case HCI_OP_EXIT_SNIFF_MODE: hci_cs_exit_sniff_mode(hdev, ev->status); break; default: BT_DBG("%s opcode 0x%x", hdev->name, opcode); break; } if (ev->ncmd) { atomic_set(&hdev->cmd_cnt, 1); if (!skb_queue_empty(&hdev->cmd_q)) hci_sched_cmd(hdev); }}static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb){ struct hci_ev_role_change *ev = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s status %d", hdev->name, ev->status); hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); if (conn) { if (!ev->status) { if (ev->role) conn->link_mode &= ~HCI_LM_MASTER; else conn->link_mode |= HCI_LM_MASTER; } clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); hci_role_switch_cfm(conn, ev->status, ev->role); } hci_dev_unlock(hdev);}static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb){ struct hci_ev_num_comp_pkts *ev = (void *) skb->data; __le16 *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 = (__le16 *) 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 == ACL_LINK) { if ((hdev->acl_cnt += count) > hdev->acl_pkts) hdev->acl_cnt = hdev->acl_pkts; } else { if ((hdev->sco_cnt += count) > hdev->sco_pkts) hdev->sco_cnt = hdev->sco_pkts; } } } hci_sched_tx(hdev); tasklet_enable(&hdev->tx_task);}static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb){ struct hci_ev_mode_change *ev = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s status %d", hdev->name, ev->status); hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); if (conn) { conn->mode = ev->mode; conn->interval = __le16_to_cpu(ev->interval); if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { if (conn->mode == HCI_CM_ACTIVE) conn->power_save = 1; else conn->power_save = 0; } } hci_dev_unlock(hdev);}static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb){ BT_DBG("%s", hdev->name);}static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb){ BT_DBG("%s", hdev->name);}static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb){ BT_DBG("%s", hdev->name);}static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb){ struct hci_ev_clock_offset *ev = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s status %d", hdev->name, ev->status); hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); if (conn && !ev->status) { struct inquiry_entry *ie; if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) { ie->data.clock_offset = ev->clock_offset; ie->timestamp = jiffies; } } hci_dev_unlock(hdev);}static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb){ struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; struct inquiry_entry *ie; BT_DBG("%s", hdev->name); hci_dev_lock(hdev); if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) { ie->data.pscan_rep_mode = ev->pscan_rep_mode; ie->timestamp = jiffies; } hci_dev_unlock(hdev);}static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb){ struct inquiry_data data; int num_rsp = *((__u8 *) skb->data); BT_DBG("%s num_rsp %d", hdev->name, num_rsp); if (!num_rsp) return; hci_dev_lock(hdev); if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { struct inquiry_info_with_rssi_and_pscan_mode *info = (void *) (skb->data + 1); for (; num_rsp; num_rsp--) { bacpy(&data.bdaddr, &info->bdaddr); data.pscan_rep_mode = info->pscan_rep_mode; data.pscan_period_mode = info->pscan_period_mode; data.pscan_mode = info->pscan_mode; memcpy(data.dev_class, info->dev_class, 3); data.clock_offset = info->clock_offset; data.rssi = info->rssi; info++; hci_inquiry_cache_update(hdev, &data); } } else { struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); for (; num_rsp; num_rsp--) { bacpy(&data.bdaddr, &info->bdaddr); data.pscan_rep_mode = info->pscan_rep_mode; data.pscan_period_mode = info->pscan_period_mode; data.pscan_mode = 0x00; memcpy(data.dev_class, info->dev_class, 3); data.clock_offset = info->clock_offset; data.rssi = info->rssi; info++; hci_inquiry_cache_update(hdev, &data); } } hci_dev_unlock(hdev);}static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb){ BT_DBG("%s", hdev->name);}static inline void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb){ struct hci_ev_sync_conn_complete *ev = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s status %d", hdev->name, ev->status); hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); if (!conn) goto unlock; if (!ev->status) { conn->handle = __le16_to_cpu(ev->handle); conn->state = BT_CONNECTED; } else conn->state = BT_CLOSED; hci_proto_connect_cfm(conn, ev->status); if (ev->status) hci_conn_del(conn);unlock: hci_dev_unlock(hdev);}static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb){ BT_DBG("%s", hdev->name);}static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb){ struct hci_ev_sniff_subrate *ev = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s status %d", hdev->name, ev->status); hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); if (conn) { } hci_dev_unlock(hdev);}static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb){ struct inquiry_data data; struct extended_inquiry_info *info = (void *) (skb->data + 1); int num_rsp = *((__u8 *) skb->data); BT_DBG("%s num_rsp %d", hdev->name, num_rsp); if (!num_rsp) return; hci_dev_lock(hdev); for (; num_rsp; num_rsp--) { bacpy(&data.bdaddr, &info->bdaddr); data.pscan_rep_mode = info->pscan_rep_mode; data.pscan_period_mode = info->pscan_period_mode; data.pscan_mode = 0x00; memcpy(data.dev_class, info->dev_class, 3); data.clock_offset = info->clock_offset; data.rssi = info->rssi; info++; hci_inquiry_cache_update(hdev, &data); } hci_dev_unlock(hdev);}void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb){ struct hci_event_hdr *hdr = (void *) skb->data; __u8 event = hdr->evt; skb_pull(skb, HCI_EVENT_HDR_SIZE); switch (event) { 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_CONN_COMPLETE: hci_conn_complete_evt(hdev, skb); break; case HCI_EV_CONN_REQUEST: hci_conn_request_evt(hdev, skb); break; case HCI_EV_DISCONN_COMPLETE: hci_disconn_complete_evt(hdev, skb); break; case HCI_EV_AUTH_COMPLETE: hci_auth_complete_evt(hdev, skb); break; case HCI_EV_REMOTE_NAME: hci_remote_name_evt(hdev, skb); break; case HCI_EV_ENCRYPT_CHANGE: hci_encrypt_change_evt(hdev, skb); break; case HCI_EV_CHANGE_LINK_KEY_COMPLETE: hci_change_link_key_complete_evt(hdev, skb); break; case HCI_EV_REMOTE_FEATURES: hci_remote_features_evt(hdev, skb); break; case HCI_EV_REMOTE_VERSION: hci_remote_version_evt(hdev, skb); break; case HCI_EV_QOS_SETUP_COMPLETE: hci_qos_setup_complete_evt(hdev, skb); break; case HCI_EV_CMD_COMPLETE: hci_cmd_complete_evt(hdev, skb); break; case HCI_EV_CMD_STATUS: hci_cmd_status_evt(hdev, skb); break; case HCI_EV_ROLE_CHANGE: hci_role_change_evt(hdev, skb); break; case HCI_EV_NUM_COMP_PKTS: hci_num_comp_pkts_evt(hdev, skb); break; case HCI_EV_MODE_CHANGE: hci_mode_change_evt(hdev, skb); break; case HCI_EV_PIN_CODE_REQ: hci_pin_code_request_evt(hdev, skb); break; case HCI_EV_LINK_KEY_REQ: hci_link_key_request_evt(hdev, skb); break; case HCI_EV_LINK_KEY_NOTIFY: hci_link_key_notify_evt(hdev, skb); break; case HCI_EV_CLOCK_OFFSET: hci_clock_offset_evt(hdev, skb); break; case HCI_EV_PSCAN_REP_MODE: hci_pscan_rep_mode_evt(hdev, skb); break; case HCI_EV_INQUIRY_RESULT_WITH_RSSI: hci_inquiry_result_with_rssi_evt(hdev, skb); break; case HCI_EV_REMOTE_EXT_FEATURES: hci_remote_ext_features_evt(hdev, skb); break; case HCI_EV_SYNC_CONN_COMPLETE: hci_sync_conn_complete_evt(hdev, skb); break; case HCI_EV_SYNC_CONN_CHANGED: hci_sync_conn_changed_evt(hdev, skb); break; case HCI_EV_SNIFF_SUBRATE: hci_sniff_subrate_evt(hdev, skb); break; case HCI_EV_EXTENDED_INQUIRY_RESULT: hci_extended_inquiry_result_evt(hdev, skb); break; default: BT_DBG("%s event 0x%x", hdev->name, event); 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); bt_cb(skb)->incoming = 1; __net_timestamp(skb); bt_cb(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 + -