summaryrefslogtreecommitdiffstats
path: root/net/nfc/hci/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/nfc/hci/core.c')
-rw-r--r--net/nfc/hci/core.c104
1 files changed, 63 insertions, 41 deletions
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index a8b0b71e8f86..36717cebfbb6 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -32,6 +32,18 @@
/* Largest headroom needed for outgoing HCI commands */
#define HCI_CMDS_HEADROOM 1
+static int nfc_hci_result_to_errno(u8 result)
+{
+ switch (result) {
+ case NFC_HCI_ANY_OK:
+ return 0;
+ case NFC_HCI_ANY_E_TIMEOUT:
+ return -ETIME;
+ default:
+ return -1;
+ }
+}
+
static void nfc_hci_msg_tx_work(struct work_struct *work)
{
struct nfc_hci_dev *hdev = container_of(work, struct nfc_hci_dev,
@@ -46,7 +58,7 @@ static void nfc_hci_msg_tx_work(struct work_struct *work)
if (timer_pending(&hdev->cmd_timer) == 0) {
if (hdev->cmd_pending_msg->cb)
hdev->cmd_pending_msg->cb(hdev,
- NFC_HCI_ANY_E_TIMEOUT,
+ -ETIME,
NULL,
hdev->
cmd_pending_msg->
@@ -71,8 +83,7 @@ next_msg:
kfree_skb(skb);
skb_queue_purge(&msg->msg_frags);
if (msg->cb)
- msg->cb(hdev, NFC_HCI_ANY_E_NOK, NULL,
- msg->cb_context);
+ msg->cb(hdev, r, NULL, msg->cb_context);
kfree(msg);
break;
}
@@ -116,20 +127,13 @@ static void nfc_hci_msg_rx_work(struct work_struct *work)
}
}
-void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result,
- struct sk_buff *skb)
+static void __nfc_hci_cmd_completion(struct nfc_hci_dev *hdev, int err,
+ struct sk_buff *skb)
{
- mutex_lock(&hdev->msg_tx_mutex);
-
- if (hdev->cmd_pending_msg == NULL) {
- kfree_skb(skb);
- goto exit;
- }
-
del_timer_sync(&hdev->cmd_timer);
if (hdev->cmd_pending_msg->cb)
- hdev->cmd_pending_msg->cb(hdev, result, skb,
+ hdev->cmd_pending_msg->cb(hdev, err, skb,
hdev->cmd_pending_msg->cb_context);
else
kfree_skb(skb);
@@ -138,6 +142,19 @@ void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result,
hdev->cmd_pending_msg = NULL;
queue_work(hdev->msg_tx_wq, &hdev->msg_tx_work);
+}
+
+void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result,
+ struct sk_buff *skb)
+{
+ mutex_lock(&hdev->msg_tx_mutex);
+
+ if (hdev->cmd_pending_msg == NULL) {
+ kfree_skb(skb);
+ goto exit;
+ }
+
+ __nfc_hci_cmd_completion(hdev, nfc_hci_result_to_errno(result), skb);
exit:
mutex_unlock(&hdev->msg_tx_mutex);
@@ -213,7 +230,7 @@ static int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate)
}
break;
case NFC_HCI_RF_READER_B_GATE:
- targets->supported_protocols = NFC_PROTO_ISO14443_MASK;
+ targets->supported_protocols = NFC_PROTO_ISO14443_B_MASK;
break;
default:
if (hdev->ops->target_from_gate)
@@ -298,15 +315,15 @@ static void nfc_hci_cmd_timeout(unsigned long data)
}
static int hci_dev_connect_gates(struct nfc_hci_dev *hdev, u8 gate_count,
- u8 gates[])
+ struct nfc_hci_gate *gates)
{
int r;
- u8 *p = gates;
while (gate_count--) {
- r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID, *p);
+ r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID,
+ gates->gate, gates->pipe);
if (r < 0)
return r;
- p++;
+ gates++;
}
return 0;
@@ -316,14 +333,13 @@ static int hci_dev_session_init(struct nfc_hci_dev *hdev)
{
struct sk_buff *skb = NULL;
int r;
- u8 hci_gates[] = { /* NFC_HCI_ADMIN_GATE MUST be first */
- NFC_HCI_ADMIN_GATE, NFC_HCI_LOOPBACK_GATE,
- NFC_HCI_ID_MGMT_GATE, NFC_HCI_LINK_MGMT_GATE,
- NFC_HCI_RF_READER_B_GATE, NFC_HCI_RF_READER_A_GATE
- };
+
+ if (hdev->init_data.gates[0].gate != NFC_HCI_ADMIN_GATE)
+ return -EPROTO;
r = nfc_hci_connect_gate(hdev, NFC_HCI_HOST_CONTROLLER_ID,
- NFC_HCI_ADMIN_GATE);
+ hdev->init_data.gates[0].gate,
+ hdev->init_data.gates[0].pipe);
if (r < 0)
goto exit;
@@ -351,10 +367,6 @@ static int hci_dev_session_init(struct nfc_hci_dev *hdev)
if (r < 0)
goto exit;
- r = hci_dev_connect_gates(hdev, sizeof(hci_gates), hci_gates);
- if (r < 0)
- goto disconnect_all;
-
r = hci_dev_connect_gates(hdev, hdev->init_data.gate_count,
hdev->init_data.gates);
if (r < 0)
@@ -717,6 +729,27 @@ void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev)
}
EXPORT_SYMBOL(nfc_hci_get_clientdata);
+static void nfc_hci_failure(struct nfc_hci_dev *hdev, int err)
+{
+ mutex_lock(&hdev->msg_tx_mutex);
+
+ if (hdev->cmd_pending_msg == NULL) {
+ nfc_driver_failure(hdev->ndev, err);
+ goto exit;
+ }
+
+ __nfc_hci_cmd_completion(hdev, err, NULL);
+
+exit:
+ mutex_unlock(&hdev->msg_tx_mutex);
+}
+
+void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err)
+{
+ nfc_hci_failure(hdev, err);
+}
+EXPORT_SYMBOL(nfc_hci_driver_failure);
+
void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb)
{
struct hcp_packet *packet;
@@ -727,16 +760,6 @@ void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb)
struct sk_buff *frag_skb;
int msg_len;
- if (skb == NULL) {
- /* TODO ELa: lower layer had permanent failure, need to
- * propagate that up
- */
-
- skb_queue_purge(&hdev->rx_hcp_frags);
-
- return;
- }
-
packet = (struct hcp_packet *)skb->data;
if ((packet->header & ~NFC_HCI_FRAGMENT) == 0) {
skb_queue_tail(&hdev->rx_hcp_frags, skb);
@@ -757,9 +780,8 @@ void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb)
hcp_skb = nfc_alloc_recv_skb(NFC_HCI_HCP_PACKET_HEADER_LEN +
msg_len, GFP_KERNEL);
if (hcp_skb == NULL) {
- /* TODO ELa: cannot deliver HCP message. How to
- * propagate error up?
- */
+ nfc_hci_failure(hdev, -ENOMEM);
+ return;
}
*skb_put(hcp_skb, NFC_HCI_HCP_PACKET_HEADER_LEN) = pipe;