NFC: nci: Allow the driver to set handler for core nci ops
authorRobert Dolca <robert.dolca@intel.com>
Thu, 22 Oct 2015 09:11:38 +0000 (12:11 +0300)
committerSamuel Ortiz <sameo@linux.intel.com>
Sun, 25 Oct 2015 18:12:57 +0000 (19:12 +0100)
The driver may be required to act when some responses or
notifications arrive. For example the NCI core does not have a
handler for NCI_OP_CORE_GET_CONFIG_RSP. The NFCC can send a
config response that has to be read by the driver and the packet
may contain vendor specific data.

The Fields Peak driver needs to take certain actions when a reset
notification arrives (packet also not handled by the nfc core).

The driver handlers do not interfere with the core and they are
called after the core processes the packet.

Signed-off-by: Robert Dolca <robert.dolca@intel.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
include/net/nfc/nci_core.h
net/nfc/nci/core.c
net/nfc/nci/ntf.c
net/nfc/nci/rsp.c

index 4ca1b6d1684b4d32ad55e8043babc2b8f9b4ee8b..d5a1caae9fd980585a00592ed2c5fc7ee24bc195 100644 (file)
@@ -96,6 +96,9 @@ struct nci_ops {
 
        struct nci_prop_ops *prop_ops;
        size_t n_prop_ops;
+
+       struct nci_prop_ops *core_ops;
+       size_t n_core_ops;
 };
 
 #define NCI_MAX_SUPPORTED_RF_INTERFACES                4
@@ -345,9 +348,13 @@ static inline int nci_set_vendor_cmds(struct nci_dev *ndev,
 
 void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb);
 void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb);
-int nci_prop_rsp_packet(struct nci_dev *ndev, __u16 opcode,
+inline int nci_prop_rsp_packet(struct nci_dev *ndev, __u16 opcode,
+                       struct sk_buff *skb);
+inline int nci_prop_ntf_packet(struct nci_dev *ndev, __u16 opcode,
+                       struct sk_buff *skb);
+inline int nci_core_rsp_packet(struct nci_dev *ndev, __u16 opcode,
                        struct sk_buff *skb);
-int nci_prop_ntf_packet(struct nci_dev *ndev, __u16 opcode,
+inline int nci_core_ntf_packet(struct nci_dev *ndev, __u16 opcode,
                        struct sk_buff *skb);
 void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb);
 int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload);
index 5b4f48a827d9ad79588203eddaa7e135bfbb9914..30c270862884e54421d1ce9fd89c2f3b16528f2f 100644 (file)
@@ -1242,46 +1242,77 @@ int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload)
 }
 
 /* Proprietary commands API */
-static struct nci_prop_ops *prop_cmd_lookup(struct nci_dev *ndev,
-                                           __u16 opcode)
+static struct nci_prop_ops *ops_cmd_lookup(struct nci_prop_ops *ops,
+                                          size_t n_ops,
+                                          __u16 opcode)
 {
        size_t i;
-       struct nci_prop_ops *prop_op;
+       struct nci_prop_ops *op;
 
-       if (!ndev->ops->prop_ops || !ndev->ops->n_prop_ops)
+       if (!ops || !n_ops)
                return NULL;
 
-       for (i = 0; i < ndev->ops->n_prop_ops; i++) {
-               prop_op = &ndev->ops->prop_ops[i];
-               if (prop_op->opcode == opcode)
-                       return prop_op;
+       for (i = 0; i < n_ops; i++) {
+               op = &ops[i];
+               if (op->opcode == opcode)
+                       return op;
        }
 
        return NULL;
 }
 
-int nci_prop_rsp_packet(struct nci_dev *ndev, __u16 rsp_opcode,
-                       struct sk_buff *skb)
+static int nci_op_rsp_packet(struct nci_dev *ndev, __u16 rsp_opcode,
+                            struct sk_buff *skb, struct nci_prop_ops *ops,
+                            size_t n_ops)
 {
-       struct nci_prop_ops *prop_op;
+       struct nci_prop_ops *op;
 
-       prop_op = prop_cmd_lookup(ndev, rsp_opcode);
-       if (!prop_op || !prop_op->rsp)
+       op = ops_cmd_lookup(ops, n_ops, rsp_opcode);
+       if (!op || !op->rsp)
                return -ENOTSUPP;
 
-       return prop_op->rsp(ndev, skb);
+       return op->rsp(ndev, skb);
 }
 
-int nci_prop_ntf_packet(struct nci_dev *ndev, __u16 ntf_opcode,
-                       struct sk_buff *skb)
+static int nci_op_ntf_packet(struct nci_dev *ndev, __u16 ntf_opcode,
+                            struct sk_buff *skb, struct nci_prop_ops *ops,
+                            size_t n_ops)
 {
-       struct nci_prop_ops *prop_op;
+       struct nci_prop_ops *op;
 
-       prop_op = prop_cmd_lookup(ndev, ntf_opcode);
-       if (!prop_op || !prop_op->ntf)
+       op = ops_cmd_lookup(ops, n_ops, ntf_opcode);
+       if (!op || !op->ntf)
                return -ENOTSUPP;
 
-       return prop_op->ntf(ndev, skb);
+       return op->ntf(ndev, skb);
+}
+
+inline int nci_prop_rsp_packet(struct nci_dev *ndev, __u16 opcode,
+                              struct sk_buff *skb)
+{
+       return nci_op_rsp_packet(ndev, opcode, skb, ndev->ops->prop_ops,
+                                ndev->ops->n_prop_ops);
+}
+
+inline int nci_prop_ntf_packet(struct nci_dev *ndev, __u16 opcode,
+                              struct sk_buff *skb)
+{
+       return nci_op_ntf_packet(ndev, opcode, skb, ndev->ops->prop_ops,
+                                ndev->ops->n_prop_ops);
+}
+
+inline int nci_core_rsp_packet(struct nci_dev *ndev, __u16 opcode,
+                              struct sk_buff *skb)
+{
+       return nci_op_rsp_packet(ndev, opcode, skb, ndev->ops->core_ops,
+                                 ndev->ops->n_core_ops);
+}
+
+inline int nci_core_ntf_packet(struct nci_dev *ndev, __u16 opcode,
+                              struct sk_buff *skb)
+{
+       return nci_op_ntf_packet(ndev, opcode, skb, ndev->ops->core_ops,
+                                ndev->ops->n_core_ops);
 }
 
 /* ---- NCI TX Data worker thread ---- */
index 5d1c2e391c56a8caf3b457796bcfbc60bf8982a9..2ada2b39e355efa7fd0e4aa154115bec580aadd7 100644 (file)
@@ -759,7 +759,7 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb)
        skb_pull(skb, NCI_CTRL_HDR_SIZE);
 
        if (nci_opcode_gid(ntf_opcode) == NCI_GID_PROPRIETARY) {
-               if (nci_prop_ntf_packet(ndev, ntf_opcode, skb)) {
+               if (nci_prop_ntf_packet(ndev, ntf_opcode, skb) == -ENOTSUPP) {
                        pr_err("unsupported ntf opcode 0x%x\n",
                               ntf_opcode);
                }
@@ -805,6 +805,7 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb)
                break;
        }
 
+       nci_core_ntf_packet(ndev, ntf_opcode, skb);
 end:
        kfree_skb(skb);
 }
index 408bd8f857ab9fd506ad137dd0333db0b2556613..9b6eb913d801b000dc4f50eb3bf0bad7435e7e34 100644 (file)
@@ -355,6 +355,7 @@ void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
                break;
        }
 
+       nci_core_rsp_packet(ndev, rsp_opcode, skb);
 end:
        kfree_skb(skb);