X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=net%2Fbluetooth%2Fhci_event.c;h=7c9ac01cd8f94029f97fd0a75696ef2f3f5c93ed;hp=4baea1e3865222cff1bb8c2238eafd11712ba39a;hb=0493684ed2397e111574f343534d8e4ec440dfa5;hpb=5b7f990927fe87ad3bec762a33c0e72bcbf6841e diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 4baea1e38652..7c9ac01cd8f9 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -52,639 +52,644 @@ /* Handle HCI Event packets */ -/* Command Complete OGF LINK_CTL */ -static void hci_cc_link_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb) +static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status; - struct hci_conn *pend; + __u8 status = *((__u8 *) skb->data); - BT_DBG("%s ocf 0x%x", hdev->name, ocf); + BT_DBG("%s status 0x%x", hdev->name, status); - switch (ocf) { - case OCF_INQUIRY_CANCEL: - case OCF_EXIT_PERIODIC_INQ: - status = *((__u8 *) skb->data); + if (status) + return; - if (status) { - BT_DBG("%s Inquiry cancel error: status 0x%x", hdev->name, status); - } else { - clear_bit(HCI_INQUIRY, &hdev->flags); - hci_req_complete(hdev, status); - } + clear_bit(HCI_INQUIRY, &hdev->flags); - hci_dev_lock(hdev); + hci_req_complete(hdev, status); - pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); - if (pend) - hci_acl_connect(pend); + hci_conn_check_pending(hdev); +} - hci_dev_unlock(hdev); +static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) +{ + __u8 status = *((__u8 *) skb->data); - break; + BT_DBG("%s status 0x%x", hdev->name, status); - default: - BT_DBG("%s Command complete: ogf LINK_CTL ocf %x", hdev->name, ocf); - break; - } + if (status) + return; + + clear_bit(HCI_INQUIRY, &hdev->flags); + + hci_conn_check_pending(hdev); } -/* Command Complete OGF LINK_POLICY */ -static void hci_cc_link_policy(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb) +static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_conn *conn; - struct hci_rp_role_discovery *rd; - struct hci_rp_write_link_policy *lp; - void *sent; - - BT_DBG("%s ocf 0x%x", hdev->name, ocf); + BT_DBG("%s", hdev->name); +} - switch (ocf) { - case OCF_ROLE_DISCOVERY: - rd = (void *) skb->data; +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; - if (rd->status) - break; + BT_DBG("%s status 0x%x", hdev->name, rp->status); - hci_dev_lock(hdev); + if (rp->status) + return; - conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rd->handle)); - if (conn) { - if (rd->role) - conn->link_mode &= ~HCI_LM_MASTER; - else - conn->link_mode |= HCI_LM_MASTER; - } + hci_dev_lock(hdev); - hci_dev_unlock(hdev); - break; + 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; + } - case OCF_WRITE_LINK_POLICY: - sent = hci_sent_cmd_data(hdev, OGF_LINK_POLICY, OCF_WRITE_LINK_POLICY); - if (!sent) - break; + hci_dev_unlock(hdev); +} - lp = (struct hci_rp_write_link_policy *) skb->data; +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; - if (lp->status) - break; + BT_DBG("%s status 0x%x", hdev->name, rp->status); - hci_dev_lock(hdev); + if (rp->status) + return; - conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(lp->handle)); - if (conn) { - __le16 policy = get_unaligned((__le16 *) (sent + 2)); - conn->link_policy = __le16_to_cpu(policy); - } + hci_dev_lock(hdev); - hci_dev_unlock(hdev); - break; + conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); + if (conn) + conn->link_policy = __le16_to_cpu(rp->policy); - default: - BT_DBG("%s: Command complete: ogf LINK_POLICY ocf %x", - hdev->name, ocf); - break; - } + hci_dev_unlock(hdev); } -/* Command Complete OGF HOST_CTL */ -static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb) +static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status, param; - __u16 setting; - struct hci_rp_read_voice_setting *vs; + struct hci_rp_write_link_policy *rp = (void *) skb->data; + struct hci_conn *conn; void *sent; - BT_DBG("%s ocf 0x%x", hdev->name, ocf); + BT_DBG("%s status 0x%x", hdev->name, rp->status); - switch (ocf) { - case OCF_RESET: - status = *((__u8 *) skb->data); - hci_req_complete(hdev, status); - break; + if (rp->status) + return; - case OCF_SET_EVENT_FLT: - status = *((__u8 *) skb->data); - if (status) { - BT_DBG("%s SET_EVENT_FLT failed %d", hdev->name, status); - } else { - BT_DBG("%s SET_EVENT_FLT succeseful", hdev->name); - } - break; + sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); + if (!sent) + return; + + hci_dev_lock(hdev); - case OCF_WRITE_AUTH_ENABLE: - sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_AUTH_ENABLE); - if (!sent) - break; + conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); + if (conn) + conn->link_policy = get_unaligned_le16(sent + 2); - status = *((__u8 *) skb->data); - param = *((__u8 *) sent); + hci_dev_unlock(hdev); +} - if (!status) { - if (param == AUTH_ENABLED) - set_bit(HCI_AUTH, &hdev->flags); - else - clear_bit(HCI_AUTH, &hdev->flags); - } - hci_req_complete(hdev, status); - break; +static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_rp_read_def_link_policy *rp = (void *) skb->data; - case OCF_WRITE_ENCRYPT_MODE: - sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_ENCRYPT_MODE); - if (!sent) - break; + BT_DBG("%s status 0x%x", hdev->name, rp->status); - status = *((__u8 *) skb->data); - param = *((__u8 *) sent); + if (rp->status) + return; - if (!status) { - if (param) - set_bit(HCI_ENCRYPT, &hdev->flags); - else - clear_bit(HCI_ENCRYPT, &hdev->flags); - } - hci_req_complete(hdev, status); - break; + hdev->link_policy = __le16_to_cpu(rp->policy); +} - case OCF_WRITE_CA_TIMEOUT: - status = *((__u8 *) skb->data); - if (status) { - BT_DBG("%s OCF_WRITE_CA_TIMEOUT failed %d", hdev->name, status); - } else { - BT_DBG("%s OCF_WRITE_CA_TIMEOUT succeseful", hdev->name); - } - break; +static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) +{ + __u8 status = *((__u8 *) skb->data); + void *sent; - case OCF_WRITE_PG_TIMEOUT: - status = *((__u8 *) skb->data); - if (status) { - BT_DBG("%s OCF_WRITE_PG_TIMEOUT failed %d", hdev->name, status); - } else { - BT_DBG("%s: OCF_WRITE_PG_TIMEOUT succeseful", hdev->name); - } - break; + BT_DBG("%s status 0x%x", hdev->name, status); + + sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); + if (!sent) + return; - case OCF_WRITE_SCAN_ENABLE: - sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE); - if (!sent) - break; + if (!status) + hdev->link_policy = get_unaligned_le16(sent); - status = *((__u8 *) skb->data); - param = *((__u8 *) sent); + hci_req_complete(hdev, status); +} - BT_DBG("param 0x%x", param); +static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) +{ + __u8 status = *((__u8 *) skb->data); - if (!status) { - clear_bit(HCI_PSCAN, &hdev->flags); - clear_bit(HCI_ISCAN, &hdev->flags); - if (param & SCAN_INQUIRY) - set_bit(HCI_ISCAN, &hdev->flags); + BT_DBG("%s status 0x%x", hdev->name, status); - if (param & SCAN_PAGE) - set_bit(HCI_PSCAN, &hdev->flags); - } - hci_req_complete(hdev, status); - break; + hci_req_complete(hdev, status); +} + +static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) +{ + __u8 status = *((__u8 *) skb->data); + void *sent; - case OCF_READ_VOICE_SETTING: - vs = (struct hci_rp_read_voice_setting *) skb->data; + BT_DBG("%s status 0x%x", hdev->name, status); - if (vs->status) { - BT_DBG("%s READ_VOICE_SETTING failed %d", hdev->name, vs->status); - break; - } + if (status) + return; - setting = __le16_to_cpu(vs->voice_setting); + sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); + if (!sent) + return; - if (hdev->voice_setting != setting ) { - hdev->voice_setting = setting; + memcpy(hdev->dev_name, sent, 248); +} - BT_DBG("%s: voice setting 0x%04x", hdev->name, setting); +static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_rp_read_local_name *rp = (void *) skb->data; - if (hdev->notify) { - tasklet_disable(&hdev->tx_task); - hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); - tasklet_enable(&hdev->tx_task); - } - } - break; + BT_DBG("%s status 0x%x", hdev->name, rp->status); - case OCF_WRITE_VOICE_SETTING: - sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_VOICE_SETTING); - if (!sent) - break; + if (rp->status) + return; - status = *((__u8 *) skb->data); - setting = __le16_to_cpu(get_unaligned((__le16 *) sent)); + memcpy(hdev->dev_name, rp->name, 248); +} - if (!status && hdev->voice_setting != setting) { - hdev->voice_setting = setting; +static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) +{ + __u8 status = *((__u8 *) skb->data); + void *sent; - BT_DBG("%s: voice setting 0x%04x", hdev->name, setting); + BT_DBG("%s status 0x%x", hdev->name, status); - if (hdev->notify) { - tasklet_disable(&hdev->tx_task); - hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); - tasklet_enable(&hdev->tx_task); - } - } - hci_req_complete(hdev, status); - break; + sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); + if (!sent) + return; - case OCF_HOST_BUFFER_SIZE: - status = *((__u8 *) skb->data); - if (status) { - BT_DBG("%s OCF_BUFFER_SIZE failed %d", hdev->name, status); - hci_req_complete(hdev, status); - } - break; + if (!status) { + __u8 param = *((__u8 *) sent); - default: - BT_DBG("%s Command complete: ogf HOST_CTL ocf %x", hdev->name, ocf); - break; + if (param == AUTH_ENABLED) + set_bit(HCI_AUTH, &hdev->flags); + else + clear_bit(HCI_AUTH, &hdev->flags); } + + hci_req_complete(hdev, status); } -/* Command Complete OGF INFO_PARAM */ -static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb) +static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_loc_version *lv; - struct hci_rp_read_local_features *lf; - struct hci_rp_read_buffer_size *bs; - struct hci_rp_read_bd_addr *ba; + __u8 status = *((__u8 *) skb->data); + void *sent; - BT_DBG("%s ocf 0x%x", hdev->name, ocf); + BT_DBG("%s status 0x%x", hdev->name, status); - switch (ocf) { - case OCF_READ_LOCAL_VERSION: - lv = (struct hci_rp_read_loc_version *) skb->data; + sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); + if (!sent) + return; - if (lv->status) { - BT_DBG("%s READ_LOCAL_VERSION failed %d", hdev->name, lf->status); - break; - } + if (!status) { + __u8 param = *((__u8 *) sent); - hdev->hci_ver = lv->hci_ver; - hdev->hci_rev = btohs(lv->hci_rev); - hdev->manufacturer = btohs(lv->manufacturer); + if (param) + set_bit(HCI_ENCRYPT, &hdev->flags); + else + clear_bit(HCI_ENCRYPT, &hdev->flags); + } - BT_DBG("%s: manufacturer %d hci_ver %d hci_rev %d", hdev->name, - hdev->manufacturer, hdev->hci_ver, hdev->hci_rev); + hci_req_complete(hdev, status); +} - break; +static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) +{ + __u8 status = *((__u8 *) skb->data); + void *sent; - case OCF_READ_LOCAL_FEATURES: - lf = (struct hci_rp_read_local_features *) skb->data; + BT_DBG("%s status 0x%x", hdev->name, status); - if (lf->status) { - BT_DBG("%s READ_LOCAL_FEATURES failed %d", hdev->name, lf->status); - break; - } + sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); + if (!sent) + return; - memcpy(hdev->features, lf->features, sizeof(hdev->features)); + if (!status) { + __u8 param = *((__u8 *) sent); - /* Adjust default settings according to features - * supported by device. */ - if (hdev->features[0] & LMP_3SLOT) - hdev->pkt_type |= (HCI_DM3 | HCI_DH3); + clear_bit(HCI_PSCAN, &hdev->flags); + clear_bit(HCI_ISCAN, &hdev->flags); - if (hdev->features[0] & LMP_5SLOT) - hdev->pkt_type |= (HCI_DM5 | HCI_DH5); + if (param & SCAN_INQUIRY) + set_bit(HCI_ISCAN, &hdev->flags); - if (hdev->features[1] & LMP_HV2) { - hdev->pkt_type |= (HCI_HV2); - hdev->esco_type |= (ESCO_HV2); - } + if (param & SCAN_PAGE) + set_bit(HCI_PSCAN, &hdev->flags); + } - if (hdev->features[1] & LMP_HV3) { - hdev->pkt_type |= (HCI_HV3); - hdev->esco_type |= (ESCO_HV3); - } + hci_req_complete(hdev, status); +} - if (hdev->features[3] & LMP_ESCO) - hdev->esco_type |= (ESCO_EV3); +static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_rp_read_class_of_dev *rp = (void *) skb->data; - if (hdev->features[4] & LMP_EV4) - hdev->esco_type |= (ESCO_EV4); + BT_DBG("%s status 0x%x", hdev->name, rp->status); - if (hdev->features[4] & LMP_EV5) - hdev->esco_type |= (ESCO_EV5); + if (rp->status) + return; - BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name, - lf->features[0], lf->features[1], lf->features[2]); + memcpy(hdev->dev_class, rp->dev_class, 3); - break; + BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, + hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); +} - case OCF_READ_BUFFER_SIZE: - bs = (struct hci_rp_read_buffer_size *) skb->data; +static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) +{ + __u8 status = *((__u8 *) skb->data); + void *sent; - if (bs->status) { - BT_DBG("%s READ_BUFFER_SIZE failed %d", hdev->name, bs->status); - hci_req_complete(hdev, bs->status); - break; - } + BT_DBG("%s status 0x%x", hdev->name, status); - hdev->acl_mtu = __le16_to_cpu(bs->acl_mtu); - hdev->sco_mtu = bs->sco_mtu; - hdev->acl_pkts = __le16_to_cpu(bs->acl_max_pkt); - hdev->sco_pkts = __le16_to_cpu(bs->sco_max_pkt); + if (status) + return; - if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { - hdev->sco_mtu = 64; - hdev->sco_pkts = 8; - } + sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); + if (!sent) + return; - hdev->acl_cnt = hdev->acl_pkts; - hdev->sco_cnt = hdev->sco_pkts; + memcpy(hdev->dev_class, sent, 3); +} - BT_DBG("%s mtu: acl %d, sco %d max_pkt: acl %d, sco %d", hdev->name, - hdev->acl_mtu, hdev->sco_mtu, hdev->acl_pkts, hdev->sco_pkts); - break; +static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_rp_read_voice_setting *rp = (void *) skb->data; + __u16 setting; - case OCF_READ_BD_ADDR: - ba = (struct hci_rp_read_bd_addr *) skb->data; + BT_DBG("%s status 0x%x", hdev->name, rp->status); - if (!ba->status) { - bacpy(&hdev->bdaddr, &ba->bdaddr); - } else { - BT_DBG("%s: READ_BD_ADDR failed %d", hdev->name, ba->status); - } + if (rp->status) + return; - hci_req_complete(hdev, ba->status); - break; + setting = __le16_to_cpu(rp->voice_setting); - default: - BT_DBG("%s Command complete: ogf INFO_PARAM ocf %x", hdev->name, ocf); - break; + if (hdev->voice_setting == setting) + return; + + hdev->voice_setting = setting; + + BT_DBG("%s voice setting 0x%04x", hdev->name, setting); + + if (hdev->notify) { + tasklet_disable(&hdev->tx_task); + hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); + tasklet_enable(&hdev->tx_task); } } -/* Command Status OGF LINK_CTL */ -static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) +static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_conn *conn; - struct hci_cp_create_conn *cp = hci_sent_cmd_data(hdev, OGF_LINK_CTL, OCF_CREATE_CONN); + __u8 status = *((__u8 *) skb->data); + __u16 setting; + void *sent; - if (!cp) + BT_DBG("%s status 0x%x", hdev->name, status); + + if (status) return; - hci_dev_lock(hdev); + sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); + if (!sent) + return; - conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); + setting = get_unaligned_le16(sent); - BT_DBG("%s status 0x%x bdaddr %s conn %p", hdev->name, - status, batostr(&cp->bdaddr), conn); + if (hdev->voice_setting == setting) + return; - 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, &cp->bdaddr); - if (conn) { - conn->out = 1; - conn->link_mode |= HCI_LM_MASTER; - } else - BT_ERR("No memmory for new connection"); - } - } + hdev->voice_setting = setting; - hci_dev_unlock(hdev); + BT_DBG("%s voice setting 0x%04x", hdev->name, setting); + + if (hdev->notify) { + tasklet_disable(&hdev->tx_task); + hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); + tasklet_enable(&hdev->tx_task); + } } -static void hci_cs_link_ctl(struct hci_dev *hdev, __u16 ocf, __u8 status) +static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) { - BT_DBG("%s ocf 0x%x", hdev->name, ocf); + __u8 status = *((__u8 *) skb->data); - switch (ocf) { - case OCF_CREATE_CONN: - hci_cs_create_conn(hdev, status); - break; + BT_DBG("%s status 0x%x", hdev->name, status); - case OCF_ADD_SCO: - if (status) { - struct hci_conn *acl, *sco; - struct hci_cp_add_sco *cp = hci_sent_cmd_data(hdev, OGF_LINK_CTL, OCF_ADD_SCO); - __u16 handle; + hci_req_complete(hdev, status); +} - if (!cp) - break; +static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_rp_read_local_version *rp = (void *) skb->data; - handle = __le16_to_cpu(cp->handle); + BT_DBG("%s status 0x%x", hdev->name, rp->status); - BT_DBG("%s Add SCO error: handle %d status 0x%x", hdev->name, handle, status); + if (rp->status) + return; - hci_dev_lock(hdev); + hdev->hci_ver = rp->hci_ver; + hdev->hci_rev = __le16_to_cpu(rp->hci_rev); + hdev->manufacturer = __le16_to_cpu(rp->manufacturer); - acl = hci_conn_hash_lookup_handle(hdev, handle); - if (acl && (sco = acl->link)) { - sco->state = BT_CLOSED; + BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name, + hdev->manufacturer, + hdev->hci_ver, hdev->hci_rev); +} - hci_proto_connect_cfm(sco, status); - hci_conn_del(sco); - } +static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_rp_read_local_commands *rp = (void *) skb->data; - hci_dev_unlock(hdev); - } - break; + BT_DBG("%s status 0x%x", hdev->name, rp->status); - case OCF_INQUIRY: - if (status) { - BT_DBG("%s Inquiry error: status 0x%x", hdev->name, status); - hci_req_complete(hdev, status); - } else { - set_bit(HCI_INQUIRY, &hdev->flags); - } - break; + if (rp->status) + return; - default: - BT_DBG("%s Command status: ogf LINK_CTL ocf %x status %d", - hdev->name, ocf, status); - break; - } + memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); } -/* Command Status OGF LINK_POLICY */ -static void hci_cs_link_policy(struct hci_dev *hdev, __u16 ocf, __u8 status) +static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) { - BT_DBG("%s ocf 0x%x", hdev->name, ocf); + struct hci_rp_read_local_features *rp = (void *) skb->data; + + BT_DBG("%s status 0x%x", hdev->name, rp->status); - switch (ocf) { - case OCF_SNIFF_MODE: - if (status) { - struct hci_conn *conn; - struct hci_cp_sniff_mode *cp = hci_sent_cmd_data(hdev, OGF_LINK_POLICY, OCF_SNIFF_MODE); + if (rp->status) + return; - if (!cp) - break; + memcpy(hdev->features, rp->features, 8); - hci_dev_lock(hdev); + /* Adjust default settings according to features + * supported by device. */ - conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); - if (conn) { - clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); - } + if (hdev->features[0] & LMP_3SLOT) + hdev->pkt_type |= (HCI_DM3 | HCI_DH3); - hci_dev_unlock(hdev); - } - break; + if (hdev->features[0] & LMP_5SLOT) + hdev->pkt_type |= (HCI_DM5 | HCI_DH5); - case OCF_EXIT_SNIFF_MODE: - if (status) { - struct hci_conn *conn; - struct hci_cp_exit_sniff_mode *cp = hci_sent_cmd_data(hdev, OGF_LINK_POLICY, OCF_EXIT_SNIFF_MODE); + if (hdev->features[1] & LMP_HV2) { + hdev->pkt_type |= (HCI_HV2); + hdev->esco_type |= (ESCO_HV2); + } - if (!cp) - break; + if (hdev->features[1] & LMP_HV3) { + hdev->pkt_type |= (HCI_HV3); + hdev->esco_type |= (ESCO_HV3); + } - hci_dev_lock(hdev); + if (hdev->features[3] & LMP_ESCO) + hdev->esco_type |= (ESCO_EV3); - conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); - if (conn) { - clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend); - } + if (hdev->features[4] & LMP_EV4) + hdev->esco_type |= (ESCO_EV4); - hci_dev_unlock(hdev); - } - break; + if (hdev->features[4] & LMP_EV5) + hdev->esco_type |= (ESCO_EV5); - default: - BT_DBG("%s Command status: ogf LINK_POLICY ocf %x", hdev->name, ocf); - break; - } + BT_DBG("%s features 0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", hdev->name, + hdev->features[0], hdev->features[1], + hdev->features[2], hdev->features[3], + hdev->features[4], hdev->features[5], + hdev->features[6], hdev->features[7]); } -/* Command Status OGF HOST_CTL */ -static void hci_cs_host_ctl(struct hci_dev *hdev, __u16 ocf, __u8 status) +static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) { - BT_DBG("%s ocf 0x%x", hdev->name, ocf); + struct hci_rp_read_buffer_size *rp = (void *) skb->data; - switch (ocf) { - default: - BT_DBG("%s Command status: ogf HOST_CTL ocf %x", hdev->name, ocf); - break; - } -} + BT_DBG("%s status 0x%x", hdev->name, rp->status); -/* Command Status OGF INFO_PARAM */ -static void hci_cs_info_param(struct hci_dev *hdev, __u16 ocf, __u8 status) -{ - BT_DBG("%s: hci_cs_info_param: ocf 0x%x", hdev->name, ocf); + if (rp->status) + return; - switch (ocf) { - default: - BT_DBG("%s Command status: ogf INFO_PARAM ocf %x", hdev->name, ocf); - break; + hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); + hdev->sco_mtu = rp->sco_mtu; + hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt); + hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt); + + if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) { + hdev->sco_mtu = 64; + hdev->sco_pkts = 8; } + + hdev->acl_cnt = hdev->acl_pkts; + hdev->sco_cnt = hdev->sco_pkts; + + BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, + hdev->acl_mtu, hdev->acl_pkts, + hdev->sco_mtu, hdev->sco_pkts); } -/* Inquiry Complete */ -static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); - struct hci_conn *pend; + struct hci_rp_read_bd_addr *rp = (void *) skb->data; - BT_DBG("%s status %d", hdev->name, status); + BT_DBG("%s status 0x%x", hdev->name, rp->status); - clear_bit(HCI_INQUIRY, &hdev->flags); - hci_req_complete(hdev, status); + if (!rp->status) + bacpy(&hdev->bdaddr, &rp->bdaddr); - hci_dev_lock(hdev); + hci_req_complete(hdev, rp->status); +} - pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); - if (pend) - hci_acl_connect(pend); +static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) +{ + BT_DBG("%s status 0x%x", hdev->name, status); - hci_dev_unlock(hdev); + if (status) { + hci_req_complete(hdev, status); + + hci_conn_check_pending(hdev); + } else + set_bit(HCI_INQUIRY, &hdev->flags); } -/* Inquiry Result */ -static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) +static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) { - struct inquiry_data data; - struct inquiry_info *info = (struct inquiry_info *) (skb->data + 1); - int num_rsp = *((__u8 *) skb->data); + struct hci_cp_create_conn *cp; + struct hci_conn *conn; - BT_DBG("%s num_rsp %d", hdev->name, num_rsp); + BT_DBG("%s status 0x%x", hdev->name, status); - if (!num_rsp) + cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); + if (!cp) 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 = 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); + 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, &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); } -/* Inquiry Result With RSSI */ -static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) { - struct inquiry_data data; - int num_rsp = *((__u8 *) skb->data); + struct hci_cp_add_sco *cp; + struct hci_conn *acl, *sco; + __u16 handle; - BT_DBG("%s num_rsp %d", hdev->name, num_rsp); + BT_DBG("%s status 0x%x", hdev->name, status); - if (!num_rsp) + if (!status) + return; + + cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO); + if (!cp) return; + handle = __le16_to_cpu(cp->handle); + + BT_DBG("%s handle %d", hdev->name, handle); + 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 = - (struct inquiry_info_with_rssi_and_pscan_mode *) (skb->data + 1); + acl = hci_conn_hash_lookup_handle(hdev, handle); + if (acl && (sco = acl->link)) { + sco->state = BT_CLOSED; - 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 = - (struct inquiry_info_with_rssi *) (skb->data + 1); + hci_proto_connect_cfm(sco, status); + hci_conn_del(sco); + } - 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 void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) +{ + BT_DBG("%s status 0x%x", hdev->name, status); +} + +static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) +{ + struct hci_cp_setup_sync_conn *cp; + struct hci_conn *acl, *sco; + __u16 handle; + + BT_DBG("%s status 0x%x", hdev->name, status); + + if (!status) + return; + + cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN); + if (!cp) + return; + + handle = __le16_to_cpu(cp->handle); + + BT_DBG("%s handle %d", hdev->name, handle); + + hci_dev_lock(hdev); + + acl = hci_conn_hash_lookup_handle(hdev, handle); + if (acl && (sco = acl->link)) { + sco->state = BT_CLOSED; + + hci_proto_connect_cfm(sco, status); + hci_conn_del(sco); } hci_dev_unlock(hdev); } -/* Extended Inquiry Result */ -static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) +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); +} + +static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) +{ + struct hci_cp_exit_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_EXIT_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); +} + +static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + __u8 status = *((__u8 *) skb->data); + + BT_DBG("%s status %d", hdev->name, status); + + clear_bit(HCI_INQUIRY, &hdev->flags); + + hci_req_complete(hdev, status); + + hci_conn_check_pending(hdev); +} + +static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct inquiry_data data; - struct extended_inquiry_info *info = (struct extended_inquiry_info *) (skb->data + 1); + struct inquiry_info *info = (void *) (skb->data + 1); int num_rsp = *((__u8 *) skb->data); BT_DBG("%s num_rsp %d", hdev->name, num_rsp); @@ -696,12 +701,12 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct 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; + 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.clock_offset = info->clock_offset; + data.rssi = 0x00; info++; hci_inquiry_cache_update(hdev, &data); } @@ -709,23 +714,96 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct hci_dev_unlock(hdev); } -/* Connect Request */ +static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_ev_conn_complete *ev = (void *) skb->data; + struct hci_conn *conn; + + BT_DBG("%s", hdev->name); + + 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; + + 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; + + /* Get remote features */ + if (conn->type == ACL_LINK) { + struct hci_cp_read_remote_features cp; + cp.handle = ev->handle; + hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, sizeof(cp), &cp); + } + + /* Set packet type for incoming connection */ + if (!conn->out && hdev->hci_ver < 3) { + struct hci_cp_change_conn_ptype cp; + cp.handle = ev->handle; + cp.pkt_type = cpu_to_le16(conn->pkt_type); + hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, + sizeof(cp), &cp); + } else { + /* Update disconnect timer */ + hci_conn_hold(conn); + hci_conn_put(conn); + } + } else + conn->state = BT_CLOSED; + + if (conn->type == ACL_LINK) { + struct hci_conn *sco = conn->link; + if (sco) { + if (!ev->status) { + if (lmp_esco_capable(hdev)) + hci_setup_sync(sco, conn->handle); + else + 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); + +unlock: + hci_dev_unlock(hdev); + + hci_conn_check_pending(hdev); +} + 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; + struct hci_ev_conn_request *ev = (void *) skb->data; int mask = hdev->link_mode; - BT_DBG("%s Connection request: %s type 0x%x", hdev->name, - batostr(&ev->bdaddr), ev->link_type); + BT_DBG("%s bdaddr %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 inquiry_entry *ie; struct hci_conn *conn; - struct hci_cp_accept_conn_req cp; hci_dev_lock(hdev); + + if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) + memcpy(ie->data.dev_class, ev->dev_class, 3); + 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))) { @@ -734,118 +812,166 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk return; } } + memcpy(conn->dev_class, ev->dev_class, 3); conn->state = BT_CONNECT; + hci_dev_unlock(hdev); - bacpy(&cp.bdaddr, &ev->bdaddr); + if (ev->link_type == ACL_LINK || !lmp_esco_capable(hdev)) { + struct hci_cp_accept_conn_req cp; - if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) - cp.role = 0x00; /* Become master */ - else - cp.role = 0x01; /* Remain slave */ + 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, HCI_OP_ACCEPT_CONN_REQ, + sizeof(cp), &cp); + } else { + struct hci_cp_accept_sync_conn_req cp; + + bacpy(&cp.bdaddr, &ev->bdaddr); + cp.pkt_type = cpu_to_le16(conn->pkt_type); - hci_send_cmd(hdev, OGF_LINK_CTL, - OCF_ACCEPT_CONN_REQ, sizeof(cp), &cp); + cp.tx_bandwidth = cpu_to_le32(0x00001f40); + cp.rx_bandwidth = cpu_to_le32(0x00001f40); + cp.max_latency = cpu_to_le16(0xffff); + cp.content_format = cpu_to_le16(hdev->voice_setting); + cp.retrans_effort = 0xff; + + hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_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); + hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); } } -/* Connect Complete */ -static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +static inline void hci_disconn_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, *pend; + struct hci_ev_disconn_complete *ev = (void *) skb->data; + struct hci_conn *conn; - BT_DBG("%s", hdev->name); + BT_DBG("%s status %d", hdev->name, ev->status); + + if (ev->status) + return; hci_dev_lock(hdev); - conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); - if (!conn) { - hci_dev_unlock(hdev); - return; + 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); } - if (!ev->status) { - conn->handle = __le16_to_cpu(ev->handle); - conn->state = BT_CONNECTED; + hci_dev_unlock(hdev); +} - if (test_bit(HCI_AUTH, &hdev->flags)) +static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_ev_auth_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_AUTH; - if (test_bit(HCI_ENCRYPT, &hdev->flags)) - conn->link_mode |= HCI_LM_ENCRYPT; + clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); - /* Get remote features */ - if (conn->type == ACL_LINK) { - struct hci_cp_read_remote_features cp; - cp.handle = ev->handle; - hci_send_cmd(hdev, OGF_LINK_CTL, - OCF_READ_REMOTE_FEATURES, sizeof(cp), &cp); - } + hci_auth_cfm(conn, ev->status); - /* 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); + 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, + HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), &cp); + } else { + clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); + hci_encrypt_cfm(conn, ev->status, 0x00); + } } + } - /* 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_dev_unlock(hdev); +} - hci_send_cmd(hdev, OGF_LINK_CTL, - OCF_CHANGE_CONN_PTYPE, sizeof(cp), &cp); - } else { - /* Update disconnect timer */ - hci_conn_hold(conn); - hci_conn_put(conn); - } - } else - conn->state = BT_CLOSED; +static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + BT_DBG("%s", hdev->name); - 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_conn_check_pending(hdev); +} + +static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_ev_encrypt_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) { + if (!ev->status) { + if (ev->encrypt) { + /* Encryption implies authentication */ + conn->link_mode |= HCI_LM_AUTH; + conn->link_mode |= HCI_LM_ENCRYPT; + } else + conn->link_mode &= ~HCI_LM_ENCRYPT; } + + clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); + + hci_encrypt_cfm(conn, ev->status, ev->encrypt); } - hci_proto_connect_cfm(conn, ev->status); - if (ev->status) - hci_conn_del(conn); + hci_dev_unlock(hdev); +} - pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); - if (pend) - hci_acl_connect(pend); +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) +static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_disconn_complete *ev = (struct hci_ev_disconn_complete *) skb->data; + struct hci_ev_remote_features *ev = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s status %d", hdev->name, ev->status); @@ -856,19 +982,219 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); + if (conn) + memcpy(conn->features, ev->features, 8); + + hci_dev_unlock(hdev); +} + +static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + BT_DBG("%s", hdev->name); +} + +static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + BT_DBG("%s", hdev->name); +} + +static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_ev_cmd_complete *ev = (void *) skb->data; + __u16 opcode; + + skb_pull(skb, sizeof(*ev)); + + opcode = __le16_to_cpu(ev->opcode); + + switch (opcode) { + case HCI_OP_INQUIRY_CANCEL: + hci_cc_inquiry_cancel(hdev, skb); + break; + + case HCI_OP_EXIT_PERIODIC_INQ: + hci_cc_exit_periodic_inq(hdev, skb); + break; + + case HCI_OP_REMOTE_NAME_REQ_CANCEL: + hci_cc_remote_name_req_cancel(hdev, skb); + break; + + case HCI_OP_ROLE_DISCOVERY: + hci_cc_role_discovery(hdev, skb); + break; + + case HCI_OP_READ_LINK_POLICY: + hci_cc_read_link_policy(hdev, skb); + break; + + case HCI_OP_WRITE_LINK_POLICY: + hci_cc_write_link_policy(hdev, skb); + break; + + case HCI_OP_READ_DEF_LINK_POLICY: + hci_cc_read_def_link_policy(hdev, skb); + break; + + case HCI_OP_WRITE_DEF_LINK_POLICY: + hci_cc_write_def_link_policy(hdev, skb); + break; + + case HCI_OP_RESET: + hci_cc_reset(hdev, skb); + break; + + case HCI_OP_WRITE_LOCAL_NAME: + hci_cc_write_local_name(hdev, skb); + break; + + case HCI_OP_READ_LOCAL_NAME: + hci_cc_read_local_name(hdev, skb); + break; + + case HCI_OP_WRITE_AUTH_ENABLE: + hci_cc_write_auth_enable(hdev, skb); + break; + + case HCI_OP_WRITE_ENCRYPT_MODE: + hci_cc_write_encrypt_mode(hdev, skb); + break; + + case HCI_OP_WRITE_SCAN_ENABLE: + hci_cc_write_scan_enable(hdev, skb); + break; + + case HCI_OP_READ_CLASS_OF_DEV: + hci_cc_read_class_of_dev(hdev, skb); + break; + + case HCI_OP_WRITE_CLASS_OF_DEV: + hci_cc_write_class_of_dev(hdev, skb); + break; + + case HCI_OP_READ_VOICE_SETTING: + hci_cc_read_voice_setting(hdev, skb); + break; + + case HCI_OP_WRITE_VOICE_SETTING: + hci_cc_write_voice_setting(hdev, skb); + break; + + case HCI_OP_HOST_BUFFER_SIZE: + hci_cc_host_buffer_size(hdev, skb); + break; + + case HCI_OP_READ_LOCAL_VERSION: + 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) { - conn->state = BT_CLOSED; - hci_proto_disconn_ind(conn, ev->reason); - hci_conn_del(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); } -/* 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; + struct hci_ev_num_comp_pkts *ev = (void *) skb->data; __le16 *ptr; int i; @@ -887,8 +1213,8 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s struct hci_conn *conn; __u16 handle, count; - handle = __le16_to_cpu(get_unaligned(ptr++)); - count = __le16_to_cpu(get_unaligned(ptr++)); + handle = get_unaligned_le16(ptr++); + count = get_unaligned_le16(ptr++); conn = hci_conn_hash_lookup_handle(hdev, handle); if (conn) { @@ -903,42 +1229,55 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s } } } + 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) +static inline void hci_mode_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_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_ba(hdev, ACL_LINK, &ev->bdaddr); + conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); if (conn) { - if (!ev->status) { - if (ev->role) - conn->link_mode &= ~HCI_LM_MASTER; + 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->link_mode |= HCI_LM_MASTER; + conn->power_save = 0; } + } - clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend); + hci_dev_unlock(hdev); +} - hci_role_switch_cfm(conn, ev->status, ev->role); - } +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); +} - hci_dev_unlock(hdev); +static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + BT_DBG("%s", hdev->name); } -/* Mode Change */ -static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) +static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_mode_change *ev = (struct hci_ev_mode_change *) skb->data; + struct hci_ev_clock_offset *ev = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s status %d", hdev->name, ev->status); @@ -946,25 +1285,21 @@ static inline void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb 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 (conn && !ev->status) { + struct inquiry_entry *ie; - 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; + if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) { + ie->data.clock_offset = ev->clock_offset; + ie->timestamp = jiffies; } } hci_dev_unlock(hdev); } -/* Authentication Complete */ -static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +static inline void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_auth_complete *ev = (struct hci_ev_auth_complete *) skb->data; + struct hci_ev_pkt_type_change *ev = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s status %d", hdev->name, ev->status); @@ -972,100 +1307,122 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s 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_AUTH; + if (conn && !ev->status) + conn->pkt_type = __le16_to_cpu(ev->pkt_type); - clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); + hci_dev_unlock(hdev); +} - hci_auth_cfm(conn, ev->status); +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; - 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); - } - } + 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); } -/* Encryption Change */ -static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) +static inline void hci_inquiry_result_with_rssi_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; + struct inquiry_data data; + int num_rsp = *((__u8 *) skb->data); - BT_DBG("%s status %d", hdev->name, ev->status); + BT_DBG("%s num_rsp %d", hdev->name, num_rsp); + + if (!num_rsp) + return; hci_dev_lock(hdev); - conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); - if (conn) { - if (!ev->status) { - if (ev->encrypt) - conn->link_mode |= HCI_LM_ENCRYPT; - else - conn->link_mode &= ~HCI_LM_ENCRYPT; - } + 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); - clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); + 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); - hci_encrypt_cfm(conn, ev->status, ev->encrypt); + 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); } -/* Change Connection Link Key Complete */ -static inline void hci_change_conn_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +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_change_conn_link_key_complete *ev = (struct hci_ev_change_conn_link_key_complete *) skb->data; + 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_handle(hdev, __le16_to_cpu(ev->handle)); - if (conn) { - if (!ev->status) - conn->link_mode |= HCI_LM_SECURE; + conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); + if (!conn) { + if (ev->link_type == ESCO_LINK) + goto unlock; - clear_bit(HCI_CONN_AUTH_PEND, &conn->pend); + conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr); + if (!conn) + goto unlock; - hci_key_change_cfm(conn, ev->status); + conn->type = SCO_LINK; } - hci_dev_unlock(hdev); -} + if (!ev->status) { + conn->handle = __le16_to_cpu(ev->handle); + conn->state = BT_CONNECTED; + } else + conn->state = BT_CLOSED; -/* Pin Code Request*/ -static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) -{ -} + hci_proto_connect_cfm(conn, ev->status); + if (ev->status) + hci_conn_del(conn); -/* Link Key Request */ -static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) -{ +unlock: + hci_dev_unlock(hdev); } -/* Link Key Notification */ -static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) +static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buff *skb) { + BT_DBG("%s", hdev->name); } -/* Remote Features */ -static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) +static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_remote_features *ev = (struct hci_ev_remote_features *) skb->data; + struct hci_ev_sniff_subrate *ev = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s status %d", hdev->name, ev->status); @@ -1073,87 +1430,80 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); - if (conn && !ev->status) { - memcpy(conn->features, ev->features, sizeof(conn->features)); + if (conn) { } hci_dev_unlock(hdev); } -/* Clock Offset */ -static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) +static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_clock_offset *ev = (struct hci_ev_clock_offset *) skb->data; - struct hci_conn *conn; + struct inquiry_data data; + struct extended_inquiry_info *info = (void *) (skb->data + 1); + int num_rsp = *((__u8 *) skb->data); - BT_DBG("%s status %d", hdev->name, ev->status); + BT_DBG("%s num_rsp %d", hdev->name, num_rsp); - hci_dev_lock(hdev); + if (!num_rsp) + return; - conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); - if (conn && !ev->status) { - struct inquiry_entry *ie; + hci_dev_lock(hdev); - if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) { - ie->data.clock_offset = ev->clock_offset; - ie->timestamp = jiffies; - } + 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); } -/* Page Scan Repetition Mode */ -static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) +static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_pscan_rep_mode *ev = (struct hci_ev_pscan_rep_mode *) skb->data; - struct inquiry_entry *ie; + struct hci_ev_io_capa_request *ev = (void *) skb->data; + struct hci_conn *conn; 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; - } + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); + if (conn) + hci_conn_hold(conn); hci_dev_unlock(hdev); } -/* Sniff Subrate */ -static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb) +static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_sniff_subrate *ev = (struct hci_ev_sniff_subrate *) skb->data; + struct hci_ev_simple_pair_complete *ev = (void *) skb->data; struct hci_conn *conn; - BT_DBG("%s status %d", hdev->name, ev->status); + BT_DBG("%s", hdev->name); hci_dev_lock(hdev); - conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); - if (conn) { - } + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); + if (conn) + hci_conn_put(conn); 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; + struct hci_event_hdr *hdr = (void *) skb->data; + __u8 event = hdr->evt; 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; - + switch (event) { case HCI_EV_INQUIRY_COMPLETE: hci_inquiry_complete_evt(hdev, skb); break; @@ -1162,146 +1512,124 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) 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_EXTENDED_INQUIRY_RESULT: - hci_extended_inquiry_result_evt(hdev, skb); + 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_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_MODE_CHANGE: - hci_mode_change_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_CONN_LINK_KEY_COMPLETE: - hci_change_conn_link_key_complete_evt(hdev, skb); + case HCI_EV_CHANGE_LINK_KEY_COMPLETE: + hci_change_link_key_complete_evt(hdev, skb); break; - case HCI_EV_PIN_CODE_REQ: - hci_pin_code_request_evt(hdev, skb); + case HCI_EV_REMOTE_FEATURES: + hci_remote_features_evt(hdev, skb); break; - case HCI_EV_LINK_KEY_REQ: - hci_link_key_request_evt(hdev, skb); + case HCI_EV_REMOTE_VERSION: + hci_remote_version_evt(hdev, skb); break; - case HCI_EV_LINK_KEY_NOTIFY: - hci_link_key_notify_evt(hdev, skb); + case HCI_EV_QOS_SETUP_COMPLETE: + hci_qos_setup_complete_evt(hdev, skb); break; - case HCI_EV_REMOTE_FEATURES: - hci_remote_features_evt(hdev, skb); + case HCI_EV_CMD_COMPLETE: + hci_cmd_complete_evt(hdev, skb); break; - case HCI_EV_CLOCK_OFFSET: - hci_clock_offset_evt(hdev, skb); + case HCI_EV_CMD_STATUS: + hci_cmd_status_evt(hdev, skb); break; - case HCI_EV_PSCAN_REP_MODE: - hci_pscan_rep_mode_evt(hdev, skb); + case HCI_EV_ROLE_CHANGE: + hci_role_change_evt(hdev, skb); break; - case HCI_EV_SNIFF_SUBRATE: - hci_sniff_subrate_evt(hdev, skb); + case HCI_EV_NUM_COMP_PKTS: + hci_num_comp_pkts_evt(hdev, skb); break; - case HCI_EV_CMD_STATUS: - cs = (struct hci_ev_cmd_status *) skb->data; - skb_pull(skb, sizeof(cs)); + case HCI_EV_MODE_CHANGE: + hci_mode_change_evt(hdev, skb); + break; - opcode = __le16_to_cpu(cs->opcode); - ogf = hci_opcode_ogf(opcode); - ocf = hci_opcode_ocf(opcode); + case HCI_EV_PIN_CODE_REQ: + hci_pin_code_request_evt(hdev, skb); + break; - switch (ogf) { - case OGF_INFO_PARAM: - hci_cs_info_param(hdev, ocf, cs->status); - break; + case HCI_EV_LINK_KEY_REQ: + hci_link_key_request_evt(hdev, skb); + break; - case OGF_HOST_CTL: - hci_cs_host_ctl(hdev, ocf, cs->status); - break; + case HCI_EV_LINK_KEY_NOTIFY: + hci_link_key_notify_evt(hdev, skb); + break; - case OGF_LINK_CTL: - hci_cs_link_ctl(hdev, ocf, cs->status); - break; + case HCI_EV_CLOCK_OFFSET: + hci_clock_offset_evt(hdev, skb); + break; - case OGF_LINK_POLICY: - hci_cs_link_policy(hdev, ocf, cs->status); - break; + case HCI_EV_PKT_TYPE_CHANGE: + hci_pkt_type_change_evt(hdev, skb); + break; - default: - BT_DBG("%s Command Status OGF %x", hdev->name, ogf); - break; - } + case HCI_EV_PSCAN_REP_MODE: + hci_pscan_rep_mode_evt(hdev, skb); + break; - if (cs->ncmd) { - atomic_set(&hdev->cmd_cnt, 1); - if (!skb_queue_empty(&hdev->cmd_q)) - hci_sched_cmd(hdev); - } + case HCI_EV_INQUIRY_RESULT_WITH_RSSI: + hci_inquiry_result_with_rssi_evt(hdev, skb); break; - case HCI_EV_CMD_COMPLETE: - ec = (struct hci_ev_cmd_complete *) skb->data; - skb_pull(skb, sizeof(*ec)); + case HCI_EV_REMOTE_EXT_FEATURES: + hci_remote_ext_features_evt(hdev, skb); + break; - opcode = __le16_to_cpu(ec->opcode); - ogf = hci_opcode_ogf(opcode); - ocf = hci_opcode_ocf(opcode); + case HCI_EV_SYNC_CONN_COMPLETE: + hci_sync_conn_complete_evt(hdev, skb); + break; - switch (ogf) { - case OGF_INFO_PARAM: - hci_cc_info_param(hdev, ocf, skb); - break; + case HCI_EV_SYNC_CONN_CHANGED: + hci_sync_conn_changed_evt(hdev, skb); + break; - case OGF_HOST_CTL: - hci_cc_host_ctl(hdev, ocf, skb); - break; + case HCI_EV_SNIFF_SUBRATE: + hci_sniff_subrate_evt(hdev, skb); + break; - case OGF_LINK_CTL: - hci_cc_link_ctl(hdev, ocf, skb); - break; + case HCI_EV_EXTENDED_INQUIRY_RESULT: + hci_extended_inquiry_result_evt(hdev, skb); + break; - case OGF_LINK_POLICY: - hci_cc_link_policy(hdev, ocf, skb); - break; + case HCI_EV_IO_CAPA_REQUEST: + hci_io_capa_request_evt(hdev, skb); + break; - default: - BT_DBG("%s Command Completed OGF %x", hdev->name, ogf); - break; - } + case HCI_EV_SIMPLE_PAIR_COMPLETE: + hci_simple_pair_complete_evt(hdev, skb); + break; - if (ec->ncmd) { - atomic_set(&hdev->cmd_cnt, 1); - if (!skb_queue_empty(&hdev->cmd_q)) - hci_sched_cmd(hdev); - } + default: + BT_DBG("%s event 0x%x", hdev->name, event); break; }