summaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2007-10-20 13:33:56 +0200
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-22 02:59:40 -0700
commita9de9248064bfc8eb0a183a6a951a4e7b5ca10a4 (patch)
tree4934b99543a9ae0f0282a7f366a8b765c6fb1a08 /net/bluetooth
parent55b70a0300b873c0ec7ea6e33752af56f41250ce (diff)
[Bluetooth] Switch from OGF+OCF to using only opcodes
The Bluetooth HCI commands are divided into logical OGF groups for easier identification of their purposes. While this still makes sense for the written specification, its makes the code only more complex and harder to read. So instead of using separate OGF and OCF values to identify the commands, use a common 16-bit opcode that combines both values. As a side effect this also reduces the complexity of OGF and OCF calculations during command header parsing. Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/hci_conn.c43
-rw-r--r--net/bluetooth/hci_core.c48
-rw-r--r--net/bluetooth/hci_event.c1598
-rw-r--r--net/bluetooth/hci_sock.c2
-rw-r--r--net/bluetooth/hci_sysfs.c37
5 files changed, 954 insertions, 774 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 5fdfc9a67d39..797a30bec6fd 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -82,7 +82,7 @@ void hci_acl_connect(struct hci_conn *conn)
else
cp.role_switch = 0x00;
- hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp);
}
static void hci_acl_connect_cancel(struct hci_conn *conn)
@@ -95,8 +95,7 @@ static void hci_acl_connect_cancel(struct hci_conn *conn)
return;
bacpy(&cp.bdaddr, &conn->dst);
- hci_send_cmd(conn->hdev, OGF_LINK_CTL,
- OCF_CREATE_CONN_CANCEL, sizeof(cp), &cp);
+ hci_send_cmd(conn->hdev, HCI_OP_CREATE_CONN_CANCEL, sizeof(cp), &cp);
}
void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
@@ -109,8 +108,7 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason)
cp.handle = cpu_to_le16(conn->handle);
cp.reason = reason;
- hci_send_cmd(conn->hdev, OGF_LINK_CTL,
- OCF_DISCONNECT, sizeof(cp), &cp);
+ hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp);
}
void hci_add_sco(struct hci_conn *conn, __u16 handle)
@@ -126,7 +124,7 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle)
cp.handle = cpu_to_le16(handle);
cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK);
- hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_ADD_SCO, sizeof(cp), &cp);
}
static void hci_conn_timeout(unsigned long arg)
@@ -348,7 +346,7 @@ int hci_conn_auth(struct hci_conn *conn)
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
struct hci_cp_auth_requested cp;
cp.handle = cpu_to_le16(conn->handle);
- hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_AUTH_REQUESTED, sizeof(cp), &cp);
+ hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
}
return 0;
}
@@ -369,7 +367,7 @@ int hci_conn_encrypt(struct hci_conn *conn)
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);
+ hci_send_cmd(conn->hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp), &cp);
}
return 0;
}
@@ -383,7 +381,7 @@ int hci_conn_change_link_key(struct hci_conn *conn)
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) {
struct hci_cp_change_conn_link_key cp;
cp.handle = cpu_to_le16(conn->handle);
- hci_send_cmd(conn->hdev, OGF_LINK_CTL, OCF_CHANGE_CONN_LINK_KEY, sizeof(cp), &cp);
+ hci_send_cmd(conn->hdev, HCI_OP_CHANGE_CONN_LINK_KEY, sizeof(cp), &cp);
}
return 0;
}
@@ -401,7 +399,7 @@ int hci_conn_switch_role(struct hci_conn *conn, uint8_t role)
struct hci_cp_switch_role cp;
bacpy(&cp.bdaddr, &conn->dst);
cp.role = role;
- hci_send_cmd(conn->hdev, OGF_LINK_POLICY, OCF_SWITCH_ROLE, sizeof(cp), &cp);
+ hci_send_cmd(conn->hdev, HCI_OP_SWITCH_ROLE, sizeof(cp), &cp);
}
return 0;
}
@@ -423,8 +421,7 @@ void hci_conn_enter_active_mode(struct hci_conn *conn)
if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
struct hci_cp_exit_sniff_mode cp;
cp.handle = cpu_to_le16(conn->handle);
- hci_send_cmd(hdev, OGF_LINK_POLICY,
- OCF_EXIT_SNIFF_MODE, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_EXIT_SNIFF_MODE, sizeof(cp), &cp);
}
timer:
@@ -455,8 +452,7 @@ void hci_conn_enter_sniff_mode(struct hci_conn *conn)
cp.max_latency = cpu_to_le16(0);
cp.min_remote_timeout = cpu_to_le16(0);
cp.min_local_timeout = cpu_to_le16(0);
- hci_send_cmd(hdev, OGF_LINK_POLICY,
- OCF_SNIFF_SUBRATE, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp);
}
if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
@@ -466,8 +462,7 @@ void hci_conn_enter_sniff_mode(struct hci_conn *conn)
cp.min_interval = cpu_to_le16(hdev->sniff_min_interval);
cp.attempt = cpu_to_le16(4);
cp.timeout = cpu_to_le16(1);
- hci_send_cmd(hdev, OGF_LINK_POLICY,
- OCF_SNIFF_MODE, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp);
}
}
@@ -493,6 +488,22 @@ void hci_conn_hash_flush(struct hci_dev *hdev)
}
}
+/* Check pending connect attempts */
+void hci_conn_check_pending(struct hci_dev *hdev)
+{
+ struct hci_conn *conn;
+
+ BT_DBG("hdev %s", hdev->name);
+
+ hci_dev_lock(hdev);
+
+ conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
+ if (conn)
+ hci_acl_connect(conn);
+
+ hci_dev_unlock(hdev);
+}
+
int hci_get_conn_list(void __user *arg)
{
struct hci_conn_list_req req, *cl;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 18e3afc964df..2894382dd26d 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -176,7 +176,7 @@ static void hci_reset_req(struct hci_dev *hdev, unsigned long opt)
BT_DBG("%s %ld", hdev->name, opt);
/* Reset device */
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_RESET, 0, NULL);
+ hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
}
static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
@@ -202,16 +202,16 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
/* Reset */
if (test_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks))
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_RESET, 0, NULL);
+ hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
/* Read Local Supported Features */
- hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_FEATURES, 0, NULL);
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
/* Read Local Version */
- hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_LOCAL_VERSION, 0, NULL);
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
/* Read Buffer Size (ACL mtu, max pkt, etc.) */
- hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_BUFFER_SIZE, 0, NULL);
+ hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
#if 0
/* Host buffer size */
@@ -221,29 +221,35 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
cp.sco_mtu = HCI_MAX_SCO_SIZE;
cp.acl_max_pkt = cpu_to_le16(0xffff);
cp.sco_max_pkt = cpu_to_le16(0xffff);
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_HOST_BUFFER_SIZE, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_HOST_BUFFER_SIZE, sizeof(cp), &cp);
}
#endif
/* Read BD Address */
- hci_send_cmd(hdev, OGF_INFO_PARAM, OCF_READ_BD_ADDR, 0, NULL);
+ hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
+
+ /* Read Class of Device */
+ hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
+
+ /* Read Local Name */
+ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
/* Read Voice Setting */
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_READ_VOICE_SETTING, 0, NULL);
+ hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
/* Optional initialization */
/* Clear Event Filters */
flt_type = HCI_FLT_CLEAR_ALL;
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_SET_EVENT_FLT, 1, &flt_type);
+ hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
/* Page timeout ~20 secs */
param = cpu_to_le16(0x8000);
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_PG_TIMEOUT, 2, &param);
+ hci_send_cmd(hdev, HCI_OP_WRITE_PG_TIMEOUT, 2, &param);
/* Connection accept timeout ~20 secs */
param = cpu_to_le16(0x7d00);
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_CA_TIMEOUT, 2, &param);
+ hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
}
static void hci_scan_req(struct hci_dev *hdev, unsigned long opt)
@@ -253,7 +259,7 @@ static void hci_scan_req(struct hci_dev *hdev, unsigned long opt)
BT_DBG("%s %x", hdev->name, scan);
/* Inquiry and Page scans */
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE, 1, &scan);
+ hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
}
static void hci_auth_req(struct hci_dev *hdev, unsigned long opt)
@@ -263,7 +269,7 @@ static void hci_auth_req(struct hci_dev *hdev, unsigned long opt)
BT_DBG("%s %x", hdev->name, auth);
/* Authentication */
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_AUTH_ENABLE, 1, &auth);
+ hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, 1, &auth);
}
static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt)
@@ -273,7 +279,7 @@ static void hci_encrypt_req(struct hci_dev *hdev, unsigned long opt)
BT_DBG("%s %x", hdev->name, encrypt);
/* Authentication */
- hci_send_cmd(hdev, OGF_HOST_CTL, OCF_WRITE_ENCRYPT_MODE, 1, &encrypt);
+ hci_send_cmd(hdev, HCI_OP_WRITE_ENCRYPT_MODE, 1, &encrypt);
}
/* Get HCI device by index.
@@ -384,7 +390,7 @@ static void hci_inq_req(struct hci_dev *hdev, unsigned long opt)
memcpy(&cp.lap, &ir->lap, 3);
cp.length = ir->length;
cp.num_rsp = ir->num_rsp;
- hci_send_cmd(hdev, OGF_LINK_CTL, OCF_INQUIRY, sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_INQUIRY, sizeof(cp), &cp);
}
int hci_inquiry(void __user *arg)
@@ -1111,13 +1117,13 @@ static int hci_send_frame(struct sk_buff *skb)
}
/* Send HCI command */
-int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *param)
+int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
{
int len = HCI_COMMAND_HDR_SIZE + plen;
struct hci_command_hdr *hdr;
struct sk_buff *skb;
- BT_DBG("%s ogf 0x%x ocf 0x%x plen %d", hdev->name, ogf, ocf, plen);
+ BT_DBG("%s opcode 0x%x plen %d", hdev->name, opcode, plen);
skb = bt_skb_alloc(len, GFP_ATOMIC);
if (!skb) {
@@ -1126,7 +1132,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *p
}
hdr = (struct hci_command_hdr *) skb_put(skb, HCI_COMMAND_HDR_SIZE);
- hdr->opcode = cpu_to_le16(hci_opcode_pack(ogf, ocf));
+ hdr->opcode = cpu_to_le16(opcode);
hdr->plen = plen;
if (plen)
@@ -1143,7 +1149,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *p
}
/* Get data from the previously sent command */
-void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 ogf, __u16 ocf)
+void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
{
struct hci_command_hdr *hdr;
@@ -1152,10 +1158,10 @@ void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 ogf, __u16 ocf)
hdr = (void *) hdev->sent_cmd->data;
- if (hdr->opcode != cpu_to_le16(hci_opcode_pack(ogf, ocf)))
+ if (hdr->opcode != cpu_to_le16(opcode))
return NULL;
- BT_DBG("%s ogf 0x%x ocf 0x%x", hdev->name, ogf, ocf);
+ BT_DBG("%s opcode 0x%x", hdev->name, opcode);
return hdev->sent_cmd->data + HCI_COMMAND_HDR_SIZE;
}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 4baea1e38652..e2cfeea5ee72 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -52,234 +52,273 @@
/* 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);
+}
+
+static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ BT_DBG("%s", hdev->name);
+}
+
+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);
}
-/* 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_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;
- 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 status 0x%x", hdev->name, rp->status);
- switch (ocf) {
- case OCF_ROLE_DISCOVERY:
- rd = (void *) skb->data;
+ if (rp->status)
+ return;
- if (rd->status)
- break;
+ sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
+ if (!sent)
+ return;
- hci_dev_lock(hdev);
+ hci_dev_lock(hdev);
- 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;
- }
+ conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
+ if (conn) {
+ __le16 policy = get_unaligned((__le16 *) (sent + 2));
+ conn->link_policy = __le16_to_cpu(policy);
+ }
- hci_dev_unlock(hdev);
- break;
+ hci_dev_unlock(hdev);
+}
+
+static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *) skb->data);
+
+ BT_DBG("%s status 0x%x", hdev->name, status);
- case OCF_WRITE_LINK_POLICY:
- sent = hci_sent_cmd_data(hdev, OGF_LINK_POLICY, OCF_WRITE_LINK_POLICY);
- if (!sent)
- break;
+ hci_req_complete(hdev, status);
+}
- lp = (struct hci_rp_write_link_policy *) skb->data;
+static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *) skb->data);
+ void *sent;
- if (lp->status)
- break;
+ BT_DBG("%s status 0x%x", hdev->name, status);
- hci_dev_lock(hdev);
+ sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
+ if (!sent)
+ 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);
- }
+ if (!status)
+ memcpy(hdev->dev_name, sent, 248);
+}
- hci_dev_unlock(hdev);
- break;
+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;
- default:
- BT_DBG("%s: Command complete: ogf LINK_POLICY ocf %x",
- hdev->name, ocf);
- break;
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (rp->status)
+ return;
+
+ memcpy(hdev->dev_name, rp->name, 248);
+}
+
+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 status 0x%x", hdev->name, status);
+
+ sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
+ if (!sent)
+ return;
+
+ if (!status) {
+ __u8 param = *((__u8 *) sent);
+
+ 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 HOST_CTL */
-static void hci_cc_host_ctl(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)
{
- __u8 status, param;
- __u16 setting;
- struct hci_rp_read_voice_setting *vs;
+ __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_RESET:
- status = *((__u8 *) skb->data);
- hci_req_complete(hdev, status);
- break;
+ sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
+ if (!sent)
+ 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;
+ if (!status) {
+ __u8 param = *((__u8 *) sent);
- case OCF_WRITE_AUTH_ENABLE:
- sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_AUTH_ENABLE);
- if (!sent)
- break;
+ if (param)
+ set_bit(HCI_ENCRYPT, &hdev->flags);
+ else
+ clear_bit(HCI_ENCRYPT, &hdev->flags);
+ }
- status = *((__u8 *) skb->data);
- param = *((__u8 *) sent);
+ hci_req_complete(hdev, status);
+}
- 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_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *) skb->data);
+ void *sent;
- 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, status);
- status = *((__u8 *) skb->data);
- param = *((__u8 *) sent);
+ sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
+ if (!sent)
+ return;
- if (!status) {
- if (param)
- set_bit(HCI_ENCRYPT, &hdev->flags);
- else
- clear_bit(HCI_ENCRYPT, &hdev->flags);
- }
- hci_req_complete(hdev, status);
- break;
+ if (!status) {
+ __u8 param = *((__u8 *) sent);
- 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;
+ clear_bit(HCI_PSCAN, &hdev->flags);
+ clear_bit(HCI_ISCAN, &hdev->flags);
- 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;
+ if (param & SCAN_INQUIRY)
+ set_bit(HCI_ISCAN, &hdev->flags);
- case OCF_WRITE_SCAN_ENABLE:
- sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE);
- if (!sent)
- break;
+ if (param & SCAN_PAGE)
+ set_bit(HCI_PSCAN, &hdev->flags);
+ }
- status = *((__u8 *) skb->data);
- param = *((__u8 *) sent);
+ hci_req_complete(hdev, status);
+}
- BT_DBG("param 0x%x", param);
+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 (!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, rp->status);
- if (param & SCAN_PAGE)
- set_bit(HCI_PSCAN, &hdev->flags);
- }
- hci_req_complete(hdev, status);
- break;
+ if (rp->status)
+ return;
- case OCF_READ_VOICE_SETTING:
- vs = (struct hci_rp_read_voice_setting *) skb->data;
+ memcpy(hdev->dev_class, rp->dev_class, 3);
- if (vs->status) {
- BT_DBG("%s READ_VOICE_SETTING failed %d", hdev->name, vs->status);
- break;
- }
+ BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name,
+ hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]);
+}
- setting = __le16_to_cpu(vs->voice_setting);
+static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *) skb->data);
+ void *sent;
- if (hdev->voice_setting != setting ) {
- hdev->voice_setting = setting;
+ BT_DBG("%s status 0x%x", hdev->name, status);
- BT_DBG("%s: voice setting 0x%04x", hdev->name, setting);
+ sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
+ if (!sent)
+ return;
- if (hdev->notify) {
- tasklet_disable(&hdev->tx_task);
- hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
- tasklet_enable(&hdev->tx_task);
- }
- }
- break;
+ if (!status)
+ memcpy(hdev->dev_class, sent, 3);
+}
+
+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;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (rp->status)
+ return;
- case OCF_WRITE_VOICE_SETTING:
- sent = hci_sent_cmd_data(hdev, OGF_HOST_CTL, OCF_WRITE_VOICE_SETTING);
- if (!sent)
- break;
+ setting = __le16_to_cpu(rp->voice_setting);
- status = *((__u8 *) skb->data);
- setting = __le16_to_cpu(get_unaligned((__le16 *) sent));
+ if (hdev->voice_setting == setting )
+ return;
+
+ hdev->voice_setting = setting;
- if (!status && 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);
+ }
+}
+
+static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *) skb->data);
+ void *sent;
+
+ BT_DBG("%s status 0x%x", hdev->name, status);
+
+ sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
+ if (!sent)
+ return;
+
+ if (!status) {
+ __u16 setting = __le16_to_cpu(get_unaligned((__le16 *) sent));
+
+ if (hdev->voice_setting != setting) {
hdev->voice_setting = setting;
- BT_DBG("%s: voice setting 0x%04x", hdev->name, setting);
+ BT_DBG("%s voice setting 0x%04x", hdev->name, setting);
if (hdev->notify) {
tasklet_disable(&hdev->tx_task);
@@ -287,143 +326,153 @@ static void hci_cc_host_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb
tasklet_enable(&hdev->tx_task);
}
}
- hci_req_complete(hdev, status);
- break;
-
- 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;
-
- default:
- BT_DBG("%s Command complete: ogf HOST_CTL ocf %x", hdev->name, ocf);
- break;
}
}
-/* 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_host_buffer_size(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);
- 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;
+ hci_req_complete(hdev, status);
+}
- if (lv->status) {
- BT_DBG("%s READ_LOCAL_VERSION failed %d", hdev->name, lf->status);
- 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;
- hdev->hci_ver = lv->hci_ver;
- hdev->hci_rev = btohs(lv->hci_rev);
- hdev->manufacturer = btohs(lv->manufacturer);
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
- BT_DBG("%s: manufacturer %d hci_ver %d hci_rev %d", hdev->name,
- hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
+ if (rp->status)
+ return;
- break;
+ hdev->hci_ver = rp->hci_ver;
+ hdev->hci_rev = btohs(rp->hci_rev);
+ hdev->manufacturer = btohs(rp->manufacturer);
- case OCF_READ_LOCAL_FEATURES:
- lf = (struct hci_rp_read_local_features *) skb->data;
+ BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
+ hdev->manufacturer,
+ hdev->hci_ver, hdev->hci_rev);
+}
- if (lf->status) {
- BT_DBG("%s READ_LOCAL_FEATURES failed %d", hdev->name, lf->status);
- break;
- }
+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;
- memcpy(hdev->features, lf->features, sizeof(hdev->features));
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
- /* Adjust default settings according to features
- * supported by device. */
- if (hdev->features[0] & LMP_3SLOT)
- hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
+ if (rp->status)
+ return;
- if (hdev->features[0] & LMP_5SLOT)
- hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
+ memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
+}
- if (hdev->features[1] & LMP_HV2) {
- hdev->pkt_type |= (HCI_HV2);
- hdev->esco_type |= (ESCO_HV2);
- }
+static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_read_local_features *rp = (void *) skb->data;
- if (hdev->features[1] & LMP_HV3) {
- hdev->pkt_type |= (HCI_HV3);
- hdev->esco_type |= (ESCO_HV3);
- }
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
- if (hdev->features[3] & LMP_ESCO)
- hdev->esco_type |= (ESCO_EV3);
+ if (rp->status)
+ return;
- if (hdev->features[4] & LMP_EV4)
- hdev->esco_type |= (ESCO_EV4);
+ memcpy(hdev->features, rp->features, 8);
- if (hdev->features[4] & LMP_EV5)
- hdev->esco_type |= (ESCO_EV5);
+ /* Adjust default settings according to features
+ * supported by device. */
- BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name,
- lf->features[0], lf->features[1], lf->features[2]);
+ if (hdev->features[0] & LMP_3SLOT)
+ hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
- break;
+ if (hdev->features[0] & LMP_5SLOT)
+ hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
- case OCF_READ_BUFFER_SIZE:
- bs = (struct hci_rp_read_buffer_size *) skb->data;
+ if (hdev->features[1] & LMP_HV2) {
+ hdev->pkt_type |= (HCI_HV2);
+ hdev->esco_type |= (ESCO_HV2);
+ }
- if (bs->status) {
- BT_DBG("%s READ_BUFFER_SIZE failed %d", hdev->name, bs->status);
- hci_req_complete(hdev, bs->status);
- break;
- }
+ if (hdev->features[1] & LMP_HV3) {
+ hdev->pkt_type |= (HCI_HV3);
+ hdev->esco_type |= (ESCO_HV3);
+ }
- 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 (hdev->features[3] & LMP_ESCO)
+ hdev->esco_type |= (ESCO_EV3);
- if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
- hdev->sco_mtu = 64;
- hdev->sco_pkts = 8;
- }
+ if (hdev->features[4] & LMP_EV4)
+ hdev->esco_type |= (ESCO_EV4);
- hdev->acl_cnt = hdev->acl_pkts;
- hdev->sco_cnt = hdev->sco_pkts;
+ if (hdev->features[4] & LMP_EV5)
+ hdev->esco_type |= (ESCO_EV5);
- 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;
+ 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]);
+}
- case OCF_READ_BD_ADDR:
- ba = (struct hci_rp_read_bd_addr *) skb->data;
+static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_read_buffer_size *rp = (void *) skb->data;
- if (!ba->status) {
- bacpy(&hdev->bdaddr, &ba->bdaddr);
- } else {
- BT_DBG("%s: READ_BD_ADDR failed %d", hdev->name, ba->status);
- }
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
- hci_req_complete(hdev, ba->status);
- break;
+ if (rp->status)
+ return;
- default:
- BT_DBG("%s Command complete: 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);
+}
+
+static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb)
+{
+ struct hci_rp_read_bd_addr *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (!rp->status)
+ bacpy(&hdev->bdaddr, &rp->bdaddr);
+
+ hci_req_complete(hdev, rp->status);
+}
+
+static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
+{
+ BT_DBG("%s status 0x%x", hdev->name, status);
+
+ if (status) {
+ hci_req_complete(hdev, status);
+
+ hci_conn_check_pending(hdev);
+ } else
+ set_bit(HCI_INQUIRY, &hdev->flags);
}
-/* Command Status OGF LINK_CTL */
static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
{
+ struct hci_cp_create_conn *cp;
struct hci_conn *conn;
- struct hci_cp_create_conn *cp = hci_sent_cmd_data(hdev, OGF_LINK_CTL, OCF_CREATE_CONN);
+ BT_DBG("%s status 0x%x", hdev->name, status);
+
+ cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
if (!cp)
return;
@@ -431,8 +480,7 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
- BT_DBG("%s status 0x%x bdaddr %s conn %p", hdev->name,
- status, batostr(&cp->bdaddr), conn);
+ BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->bdaddr), conn);
if (status) {
if (conn && conn->state == BT_CONNECT) {
@@ -457,234 +505,111 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
hci_dev_unlock(hdev);
}
-static void hci_cs_link_ctl(struct hci_dev *hdev, __u16 ocf, __u8 status)
+static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
{
- BT_DBG("%s ocf 0x%x", hdev->name, ocf);
-
- switch (ocf) {
- case OCF_CREATE_CONN:
- hci_cs_create_conn(hdev, status);
- break;
-
- 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;
-
- if (!cp)
- break;
+ struct hci_cp_add_sco *cp;
+ struct hci_conn *acl, *sco;
+ __u16 handle;
- handle = __le16_to_cpu(cp->handle);
+ if (!status)
+ return;
- BT_DBG("%s Add SCO error: handle %d status 0x%x", hdev->name, handle, status);
+ BT_DBG("%s status 0x%x", hdev->name, status);
- hci_dev_lock(hdev);
+ cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
+ if (!cp)
+ return;
- acl = hci_conn_hash_lookup_handle(hdev, handle);
- if (acl && (sco = acl->link)) {
- sco->state = BT_CLOSED;
+ handle = __le16_to_cpu(cp->handle);
- hci_proto_connect_cfm(sco, status);
- hci_conn_del(sco);
- }
+ BT_DBG("%s handle %d", hdev->name, handle);
- hci_dev_unlock(hdev);
- }
- break;
+ hci_dev_lock(hdev);
- 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;
+ acl = hci_conn_hash_lookup_handle(hdev, handle);
+ if (acl && (sco = acl->link)) {
+ sco->state = BT_CLOSED;
- default:
- BT_DBG("%s Command status: ogf LINK_CTL ocf %x status %d",
- hdev->name, ocf, status);
- break;
+ hci_proto_connect_cfm(sco, status);
+ hci_conn_del(sco);
}
-}
-
-/* Command Status OGF LINK_POLICY */
-static void hci_cs_link_policy(struct hci_dev *hdev, __u16 ocf, __u8 status)
-{<