aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Dolca <robert.dolca@intel.com>2015-10-22 05:11:38 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2015-10-25 14:12:57 -0400
commit0a97a3cba298fd989802bf34541c94b6488c3834 (patch)
treec9f980a8390536964381099a45f73e604a59ee74
parent7bc4824ed5cf9feb0173b90a6bec28f694a5f7ce (diff)
NFC: nci: Allow the driver to set handler for core nci ops
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>
-rw-r--r--include/net/nfc/nci_core.h11
-rw-r--r--net/nfc/nci/core.c71
-rw-r--r--net/nfc/nci/ntf.c3
-rw-r--r--net/nfc/nci/rsp.c1
4 files changed, 63 insertions, 23 deletions
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 4ca1b6d1684b..d5a1caae9fd9 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -96,6 +96,9 @@ struct nci_ops {
96 96
97 struct nci_prop_ops *prop_ops; 97 struct nci_prop_ops *prop_ops;
98 size_t n_prop_ops; 98 size_t n_prop_ops;
99
100 struct nci_prop_ops *core_ops;
101 size_t n_core_ops;
99}; 102};
100 103
101#define NCI_MAX_SUPPORTED_RF_INTERFACES 4 104#define NCI_MAX_SUPPORTED_RF_INTERFACES 4
@@ -345,9 +348,13 @@ static inline int nci_set_vendor_cmds(struct nci_dev *ndev,
345 348
346void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb); 349void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb);
347void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb); 350void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb);
348int nci_prop_rsp_packet(struct nci_dev *ndev, __u16 opcode, 351inline int nci_prop_rsp_packet(struct nci_dev *ndev, __u16 opcode,
352 struct sk_buff *skb);
353inline int nci_prop_ntf_packet(struct nci_dev *ndev, __u16 opcode,
354 struct sk_buff *skb);
355inline int nci_core_rsp_packet(struct nci_dev *ndev, __u16 opcode,
349 struct sk_buff *skb); 356 struct sk_buff *skb);
350int nci_prop_ntf_packet(struct nci_dev *ndev, __u16 opcode, 357inline int nci_core_ntf_packet(struct nci_dev *ndev, __u16 opcode,
351 struct sk_buff *skb); 358 struct sk_buff *skb);
352void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb); 359void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb);
353int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload); 360int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload);
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 5b4f48a827d9..30c270862884 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -1242,46 +1242,77 @@ int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload)
1242} 1242}
1243 1243
1244/* Proprietary commands API */ 1244/* Proprietary commands API */
1245static struct nci_prop_ops *prop_cmd_lookup(struct nci_dev *ndev, 1245static struct nci_prop_ops *ops_cmd_lookup(struct nci_prop_ops *ops,
1246 __u16 opcode) 1246 size_t n_ops,
1247 __u16 opcode)
1247{ 1248{
1248 size_t i; 1249 size_t i;
1249 struct nci_prop_ops *prop_op; 1250 struct nci_prop_ops *op;
1250 1251
1251 if (!ndev->ops->prop_ops || !ndev->ops->n_prop_ops) 1252 if (!ops || !n_ops)
1252 return NULL; 1253 return NULL;
1253 1254
1254 for (i = 0; i < ndev->ops->n_prop_ops; i++) { 1255 for (i = 0; i < n_ops; i++) {
1255 prop_op = &ndev->ops->prop_ops[i]; 1256 op = &ops[i];
1256 if (prop_op->opcode == opcode) 1257 if (op->opcode == opcode)
1257 return prop_op; 1258 return op;
1258 } 1259 }
1259 1260
1260 return NULL; 1261 return NULL;
1261} 1262}
1262 1263
1263int nci_prop_rsp_packet(struct nci_dev *ndev, __u16 rsp_opcode, 1264static int nci_op_rsp_packet(struct nci_dev *ndev, __u16 rsp_opcode,
1264 struct sk_buff *skb) 1265 struct sk_buff *skb, struct nci_prop_ops *ops,
1266 size_t n_ops)
1265{ 1267{
1266 struct nci_prop_ops *prop_op; 1268 struct nci_prop_ops *op;
1267 1269
1268 prop_op = prop_cmd_lookup(ndev, rsp_opcode); 1270 op = ops_cmd_lookup(ops, n_ops, rsp_opcode);
1269 if (!prop_op || !prop_op->rsp) 1271 if (!op || !op->rsp)
1270 return -ENOTSUPP; 1272 return -ENOTSUPP;
1271 1273
1272 return prop_op->rsp(ndev, skb); 1274 return op->rsp(ndev, skb);
1273} 1275}
1274 1276
1275int nci_prop_ntf_packet(struct nci_dev *ndev, __u16 ntf_opcode, 1277static int nci_op_ntf_packet(struct nci_dev *ndev, __u16 ntf_opcode,
1276 struct sk_buff *skb) 1278 struct sk_buff *skb, struct nci_prop_ops *ops,
1279 size_t n_ops)
1277{ 1280{
1278 struct nci_prop_ops *prop_op; 1281 struct nci_prop_ops *op;
1279 1282
1280 prop_op = prop_cmd_lookup(ndev, ntf_opcode); 1283 op = ops_cmd_lookup(ops, n_ops, ntf_opcode);
1281 if (!prop_op || !prop_op->ntf) 1284 if (!op || !op->ntf)
1282 return -ENOTSUPP; 1285 return -ENOTSUPP;
1283 1286
1284 return prop_op->ntf(ndev, skb); 1287 return op->ntf(ndev, skb);
1288}
1289
1290inline int nci_prop_rsp_packet(struct nci_dev *ndev, __u16 opcode,
1291 struct sk_buff *skb)
1292{
1293 return nci_op_rsp_packet(ndev, opcode, skb, ndev->ops->prop_ops,
1294 ndev->ops->n_prop_ops);
1295}
1296
1297inline int nci_prop_ntf_packet(struct nci_dev *ndev, __u16 opcode,
1298 struct sk_buff *skb)
1299{
1300 return nci_op_ntf_packet(ndev, opcode, skb, ndev->ops->prop_ops,
1301 ndev->ops->n_prop_ops);
1302}
1303
1304inline int nci_core_rsp_packet(struct nci_dev *ndev, __u16 opcode,
1305 struct sk_buff *skb)
1306{
1307 return nci_op_rsp_packet(ndev, opcode, skb, ndev->ops->core_ops,
1308 ndev->ops->n_core_ops);
1309}
1310
1311inline int nci_core_ntf_packet(struct nci_dev *ndev, __u16 opcode,
1312 struct sk_buff *skb)
1313{
1314 return nci_op_ntf_packet(ndev, opcode, skb, ndev->ops->core_ops,
1315 ndev->ops->n_core_ops);
1285} 1316}
1286 1317
1287/* ---- NCI TX Data worker thread ---- */ 1318/* ---- NCI TX Data worker thread ---- */
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 5d1c2e391c56..2ada2b39e355 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -759,7 +759,7 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb)
759 skb_pull(skb, NCI_CTRL_HDR_SIZE); 759 skb_pull(skb, NCI_CTRL_HDR_SIZE);
760 760
761 if (nci_opcode_gid(ntf_opcode) == NCI_GID_PROPRIETARY) { 761 if (nci_opcode_gid(ntf_opcode) == NCI_GID_PROPRIETARY) {
762 if (nci_prop_ntf_packet(ndev, ntf_opcode, skb)) { 762 if (nci_prop_ntf_packet(ndev, ntf_opcode, skb) == -ENOTSUPP) {
763 pr_err("unsupported ntf opcode 0x%x\n", 763 pr_err("unsupported ntf opcode 0x%x\n",
764 ntf_opcode); 764 ntf_opcode);
765 } 765 }
@@ -805,6 +805,7 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb)
805 break; 805 break;
806 } 806 }
807 807
808 nci_core_ntf_packet(ndev, ntf_opcode, skb);
808end: 809end:
809 kfree_skb(skb); 810 kfree_skb(skb);
810} 811}
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c
index 408bd8f857ab..9b6eb913d801 100644
--- a/net/nfc/nci/rsp.c
+++ b/net/nfc/nci/rsp.c
@@ -355,6 +355,7 @@ void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
355 break; 355 break;
356 } 356 }
357 357
358 nci_core_rsp_packet(ndev, rsp_opcode, skb);
358end: 359end:
359 kfree_skb(skb); 360 kfree_skb(skb);
360 361