]> Pileus Git - ~andy/linux/blobdiff - net/nfc/hci/core.c
Merge branch 'x86-acpi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[~andy/linux] / net / nfc / hci / core.c
index 8a9a811b558abb29a19b5efb425516ecc8137d34..7bea574d59344f754ad74a1a390a8d742843549b 100644 (file)
 /* Largest headroom needed for outgoing HCI commands */
 #define HCI_CMDS_HEADROOM 1
 
-static int nfc_hci_result_to_errno(u8 result)
+int nfc_hci_result_to_errno(u8 result)
 {
        switch (result) {
        case NFC_HCI_ANY_OK:
                return 0;
+       case NFC_HCI_ANY_E_REG_PAR_UNKNOWN:
+               return -EOPNOTSUPP;
        case NFC_HCI_ANY_E_TIMEOUT:
                return -ETIME;
        default:
                return -1;
        }
 }
+EXPORT_SYMBOL(nfc_hci_result_to_errno);
 
 static void nfc_hci_msg_tx_work(struct work_struct *work)
 {
@@ -65,8 +68,9 @@ static void nfc_hci_msg_tx_work(struct work_struct *work)
                                                          -ETIME);
                        kfree(hdev->cmd_pending_msg);
                        hdev->cmd_pending_msg = NULL;
-               } else
+               } else {
                        goto exit;
+               }
        }
 
 next_msg:
@@ -166,7 +170,7 @@ void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
        kfree_skb(skb);
 }
 
-static u32 nfc_hci_sak_to_protocol(u8 sak)
+u32 nfc_hci_sak_to_protocol(u8 sak)
 {
        switch (NFC_HCI_TYPE_A_SEL_PROT(sak)) {
        case NFC_HCI_TYPE_A_SEL_PROT_MIFARE:
@@ -181,6 +185,7 @@ static u32 nfc_hci_sak_to_protocol(u8 sak)
                return 0xffffffff;
        }
 }
+EXPORT_SYMBOL(nfc_hci_sak_to_protocol);
 
 int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate)
 {
@@ -263,7 +268,9 @@ int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate)
                break;
        }
 
-       targets->hci_reader_gate = gate;
+       /* if driver set the new gate, we will skip the old one */
+       if (targets->hci_reader_gate == 0x00)
+               targets->hci_reader_gate = gate;
 
        r = nfc_targets_found(hdev->ndev, targets, 1);
 
@@ -281,6 +288,12 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event,
                            struct sk_buff *skb)
 {
        int r = 0;
+       u8 gate = nfc_hci_pipe2gate(hdev, pipe);
+
+       if (gate == 0xff) {
+               pr_err("Discarded event %x to unopened pipe %x\n", event, pipe);
+               goto exit;
+       }
 
        switch (event) {
        case NFC_HCI_EVT_TARGET_DISCOVERED:
@@ -304,14 +317,11 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event,
                        goto exit;
                }
 
-               r = nfc_hci_target_discovered(hdev,
-                                             nfc_hci_pipe2gate(hdev, pipe));
+               r = nfc_hci_target_discovered(hdev, gate);
                break;
        default:
                if (hdev->ops->event_received) {
-                       hdev->ops->event_received(hdev,
-                                               nfc_hci_pipe2gate(hdev, pipe),
-                                               event, skb);
+                       hdev->ops->event_received(hdev, gate, event, skb);
                        return;
                }
 
@@ -416,6 +426,10 @@ static int hci_dev_version(struct nfc_hci_dev *hdev)
 
        r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE,
                              NFC_HCI_ID_MGMT_VERSION_SW, &skb);
+       if (r == -EOPNOTSUPP) {
+               pr_info("Software/Hardware info not available\n");
+               return 0;
+       }
        if (r < 0)
                return r;
 
@@ -533,7 +547,8 @@ static int hci_start_poll(struct nfc_dev *nfc_dev,
                return hdev->ops->start_poll(hdev, im_protocols, tm_protocols);
        else
                return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE,
-                                      NFC_HCI_EVT_READER_REQUESTED, NULL, 0);
+                                         NFC_HCI_EVT_READER_REQUESTED,
+                                         NULL, 0);
 }
 
 static void hci_stop_poll(struct nfc_dev *nfc_dev)
@@ -544,6 +559,28 @@ static void hci_stop_poll(struct nfc_dev *nfc_dev)
                           NFC_HCI_EVT_END_OPERATION, NULL, 0);
 }
 
+static int hci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
+                               __u8 comm_mode, __u8 *gb, size_t gb_len)
+{
+       struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev);
+
+       if (hdev->ops->dep_link_up)
+               return hdev->ops->dep_link_up(hdev, target, comm_mode,
+                                               gb, gb_len);
+
+       return 0;
+}
+
+static int hci_dep_link_down(struct nfc_dev *nfc_dev)
+{
+       struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev);
+
+       if (hdev->ops->dep_link_down)
+               return hdev->ops->dep_link_down(hdev);
+
+       return 0;
+}
+
 static int hci_activate_target(struct nfc_dev *nfc_dev,
                               struct nfc_target *target, u32 protocol)
 {
@@ -592,8 +629,8 @@ static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target,
        switch (target->hci_reader_gate) {
        case NFC_HCI_RF_READER_A_GATE:
        case NFC_HCI_RF_READER_B_GATE:
-               if (hdev->ops->data_exchange) {
-                       r = hdev->ops->data_exchange(hdev, target, skb, cb,
+               if (hdev->ops->im_transceive) {
+                       r = hdev->ops->im_transceive(hdev, target, skb, cb,
                                                     cb_context);
                        if (r <= 0)     /* handled */
                                break;
@@ -610,14 +647,14 @@ static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target,
                                           skb->len, hci_transceive_cb, hdev);
                break;
        default:
-               if (hdev->ops->data_exchange) {
-                       r = hdev->ops->data_exchange(hdev, target, skb, cb,
+               if (hdev->ops->im_transceive) {
+                       r = hdev->ops->im_transceive(hdev, target, skb, cb,
                                                     cb_context);
                        if (r == 1)
                                r = -ENOTSUPP;
-               }
-               else
+               } else {
                        r = -ENOTSUPP;
+               }
                break;
        }
 
@@ -626,6 +663,16 @@ static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target,
        return r;
 }
 
+static int hci_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb)
+{
+       struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev);
+
+       if (hdev->ops->tm_send)
+               return hdev->ops->tm_send(hdev, skb);
+       else
+               return -ENOTSUPP;
+}
+
 static int hci_check_presence(struct nfc_dev *nfc_dev,
                              struct nfc_target *target)
 {
@@ -729,9 +776,12 @@ static struct nfc_ops hci_nfc_ops = {
        .dev_down = hci_dev_down,
        .start_poll = hci_start_poll,
        .stop_poll = hci_stop_poll,
+       .dep_link_up = hci_dep_link_up,
+       .dep_link_down = hci_dep_link_down,
        .activate_target = hci_activate_target,
        .deactivate_target = hci_deactivate_target,
        .im_transceive = hci_transceive,
+       .tm_send = hci_tm_send,
        .check_presence = hci_check_presence,
 };
 
@@ -854,7 +904,7 @@ void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err)
 }
 EXPORT_SYMBOL(nfc_hci_driver_failure);
 
-void inline nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb)
+void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb)
 {
        nfc_llc_rcv_from_drv(hdev->llc, skb);
 }