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); }
/* 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; } } memcpy(conn->dev_class, ev->dev_class, 3); 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 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); } }
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; data.ssp_mode = 0x00; 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; data.ssp_mode = 0x00; info++; hci_inquiry_cache_update(hdev, &data); } } hci_dev_unlock(hdev); }
static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_remote_features *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) goto unlock; if (!ev->status) memcpy(conn->features, ev->features, 8); if (conn->state != BT_CONFIG) goto unlock; if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { struct hci_cp_read_remote_ext_features cp; cp.handle = ev->handle; cp.page = 0x01; hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, sizeof(cp), &cp); goto unlock; } if (!ev->status) { struct hci_cp_remote_name_req cp; memset(&cp, 0, sizeof(cp)); bacpy(&cp.bdaddr, &conn->dst); cp.pscan_rep_mode = 0x02; hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); } if (!hci_outgoing_auth_needed(hdev, conn)) { conn->state = BT_CONNECTED; hci_proto_connect_cfm(conn, ev->status); hci_conn_put(conn); } unlock: hci_dev_unlock(hdev); }
/* Inquiry Complete */ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { __u8 status = *((__u8 *) skb->data); struct hci_conn *pend; BT_DBG("%s status %d", hdev->name, status); clear_bit(HCI_INQUIRY, &hdev->flags); hci_req_complete(hdev, status); hci_dev_lock(hdev); pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); if (pend) hci_acl_connect(pend); hci_dev_unlock(hdev); }
static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_rp_read_link_policy *rp = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s status 0x%x", hdev->name, rp->status); if (rp->status) return; hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); if (conn) conn->link_policy = __le16_to_cpu(rp->policy); hci_dev_unlock(hdev); }
static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_pin_code_req *ev = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s", hdev->name); hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); if (conn && conn->state == BT_CONNECTED) { hci_conn_hold(conn); conn->disc_timeout = HCI_PAIRING_TIMEOUT; hci_conn_put(conn); } hci_dev_unlock(hdev); }
static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_link_key_notify *ev = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s", hdev->name); hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); if (conn) { hci_conn_hold(conn); conn->disc_timeout = HCI_DISCONN_TIMEOUT; hci_conn_put(conn); } hci_dev_unlock(hdev); }
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) { if (ev->link_type == ESCO_LINK) goto unlock; conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); if (!conn) goto unlock; conn->type = SCO_LINK; } if (conn->out && (ev->status == 0x1a || ev->status == 0x1c || ev->status == 0x1f) && conn->attempt < 2) { conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | (hdev->esco_type & EDR_ESCO_MASK); hci_setup_sync(conn, conn->link->handle); goto unlock; } if (!ev->status) { conn->handle = __le16_to_cpu(ev->handle); conn->state = BT_CONNECTED; hci_conn_add_sysfs(conn); } 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_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_remote_ext_features *ev = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s", hdev->name); hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); if (!conn) goto unlock; if (!ev->status && ev->page == 0x01) { struct inquiry_entry *ie; ie = hci_inquiry_cache_lookup(hdev, &conn->dst); if (ie) ie->data.ssp_mode = (ev->features[0] & 0x01); conn->ssp_mode = (ev->features[0] & 0x01); } if (conn->state != BT_CONFIG) goto unlock; if (!ev->status) { struct hci_cp_remote_name_req cp; memset(&cp, 0, sizeof(cp)); bacpy(&cp.bdaddr, &conn->dst); cp.pscan_rep_mode = 0x02; hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); } if (!hci_outgoing_auth_needed(hdev, conn)) { conn->state = BT_CONNECTED; hci_proto_connect_cfm(conn, ev->status); hci_conn_put(conn); } unlock: hci_dev_unlock(hdev); }
static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_remote_name *ev = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s", hdev->name); hci_conn_check_pending(hdev); hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); if (conn && hci_outgoing_auth_needed(hdev, conn)) { struct hci_cp_auth_requested cp; cp.handle = __cpu_to_le16(conn->handle); hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); } hci_dev_unlock(hdev); }
static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) { struct smp_cmd_master_ident *rp = (void *) skb->data; struct smp_chan *smp = conn->smp_chan; struct hci_dev *hdev = conn->hcon->hdev; struct hci_conn *hcon = conn->hcon; u8 authenticated; skb_pull(skb, sizeof(*rp)); hci_dev_lock(hdev); authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH); hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type, HCI_SMP_LTK, 1, authenticated, smp->tk, smp->enc_key_size, rp->ediv, rp->rand); smp_distribute_keys(conn, 1); hci_dev_unlock(hdev); return 0; }
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; if (!(conn->features[3]&(0x02|0x04))) /* not support 2M/3M EDR. 0x02=2M 0x04=3M */ { struct hci_cp_write_link_policy cp; cp.handle = 0; /* init */ cp.policy = 0; /* disable role_switch when changed to master */ cp.handle = cpu_to_le16(conn->handle); conn->link_policy |= HCI_LP_SNIFF; conn->link_policy |= HCI_LP_HOLD; conn->link_policy &= ~HCI_LP_RSWITCH; cp.policy = cpu_to_le16(conn->link_policy); hci_send_cmd(conn->hdev, HCI_OP_WRITE_LINK_POLICY, sizeof(cp), &cp); } } } clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); hci_role_switch_cfm(conn, ev->status, ev->role); } 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) { inquiry_info_with_rssi *info = (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--) { 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++; inquiry_cache_update(hdev, &tmp); } hci_dev_unlock(hdev); }
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_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_change_link_key_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_handle(hdev, __le16_to_cpu(ev->handle)); if (conn) { if (!ev->status) conn->link_mode |= HCI_LM_SECURE; clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); hci_key_change_cfm(conn, ev->status); } 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; BT_DBG("%s status %d", hdev->name, ev->status); if (ev->status) return; hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); if (conn) { conn->state = BT_CLOSED; hci_proto_disconn_ind(conn, ev->reason); 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); }
static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) { struct hci_cp_create_conn *cp; struct hci_conn *conn; BT_DBG("%s status 0x%x", hdev->name, status); cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); if (!cp) return; hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn); if (status) { if (conn && conn->state == BT_CONNECT) { if (status != 0x0c || conn->attempt > 2) { conn->state = BT_CLOSED; hci_proto_connect_cfm(conn, status); hci_conn_del(conn); } else conn->state = BT_CONNECT2; } } else { if (!conn) { conn = hci_conn_add(hdev, ACL_LINK, 0, &cp->bdaddr); if (conn) { conn->out = 1; conn->link_mode |= HCI_LM_MASTER; } else BT_ERR("No memmory for new connection"); } } hci_dev_unlock(hdev); }
static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) { struct hci_cp_sniff_mode *cp; struct hci_conn *conn; BT_DBG("%s status 0x%x", hdev->name, status); if (!status) return; cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE); if (!cp) return; hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); if (conn) clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); hci_dev_unlock(hdev); }
/* 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--) { struct inquiry_data data; 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 = 0x00; info++; hci_inquiry_cache_update(hdev, &data); } hci_dev_unlock(hdev); }
static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_rp_role_discovery *rp = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s status 0x%x", hdev->name, rp->status); if (rp->status) return; hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); if (conn) { if (rp->role) conn->link_mode &= ~HCI_LM_MASTER; else conn->link_mode |= HCI_LM_MASTER; } hci_dev_unlock(hdev); }
/* 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); }
static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_remote_ext_features *ev = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s", hdev->name); hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); if (conn) { if (!ev->status && ev->page == 0x01) { struct inquiry_entry *ie; if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) ie->data.ssp_mode = (ev->features[0] & 0x01); conn->ssp_mode = (ev->features[0] & 0x01); } if (conn->state == BT_CONFIG) { if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0 && conn->out && conn->sec_level != BT_SECURITY_SDP) { struct hci_cp_auth_requested cp; cp.handle = ev->handle; hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); } else { conn->state = BT_CONNECTED; hci_proto_connect_cfm(conn, ev->status); hci_conn_put(conn); } } } hci_dev_unlock(hdev); }
//BT_TIK 2011.09.23 SH Start : QoS patch from IL static inline void hci_flowspec_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_flowspec_complete *ev = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s status %d", hdev->name, ev->status); if (!ev->status) { hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); if (conn) { /* conn->qos_info.delay_variation = le32_to_cpu(ev->qos.delay_variation); conn->qos_info.latency = le32_to_cpu(ev->qos.latency); conn->qos_info.peak_bandwidth = le32_to_cpu(ev->qos.peak_bandwidth); conn->qos_info.service_type = ev->qos.service_type; conn->qos_info.token_rate = le32_to_cpu(ev->qos.token_rate); */ conn->flowspec.bucket_size = le32_to_cpu(ev->flowspec.bucket_size); conn->flowspec.flowdir = ev->flowspec.flowdir; conn->flowspec.latency = le32_to_cpu(ev->flowspec.latency); conn->flowspec.peak_bandwidth = le32_to_cpu(ev->flowspec.peak_bandwidth); conn->flowspec.service_type = ev->flowspec.service_type; conn->flowspec.token_rate = le32_to_cpu(ev->flowspec.token_rate); } hci_dev_unlock(hdev); } //BT_TIK 2011.09.23 SH : Removed HCI_OP_SET_FLOW_SPEC because kernel version of // GT-P1010 is different from one of patch from IL //hci_req_complete(hdev, HCI_OP_SET_FLOW_SPEC, ev->status); hci_req_complete(hdev, ev->status); }
static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_rp_write_link_policy *rp = (void *) skb->data; struct hci_conn *conn; void *sent; BT_DBG("%s status 0x%x", hdev->name, rp->status); if (rp->status) return; sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); if (!sent) return; hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); if (conn) conn->link_policy = get_unaligned_le16(sent + 2); hci_dev_unlock(hdev); }
static void confirm_work(struct work_struct *work) { struct smp_chan *smp = container_of(work, struct smp_chan, confirm); struct l2cap_conn *conn = smp->conn; struct hci_dev *hdev = conn->hcon->hdev; struct crypto_blkcipher *tfm = hdev->tfm_aes; struct smp_cmd_pairing_confirm cp; int ret; u8 reason; BT_DBG("conn %p", conn); /* Prevent mutual access to hdev->tfm_aes */ hci_dev_lock(hdev); ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, conn->hcon->init_addr_type, &conn->hcon->init_addr, conn->hcon->resp_addr_type, &conn->hcon->resp_addr, cp.confirm_val); hci_dev_unlock(hdev); if (ret) { reason = SMP_UNSPECIFIED; goto error; } clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); return; error: smp_failure(conn, reason); }
/* Mode Change */ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_mode_change *ev = (struct hci_ev_mode_change *) 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); }
/* 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_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_encrypt_cfm(conn, ev->status, 0x00); } } } hci_dev_unlock(hdev); }