diff options
author | Christophe Ricard <christophe.ricard@gmail.com> | 2015-02-01 16:26:10 -0500 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2015-02-02 15:50:38 -0500 |
commit | af9c8aa67d07adcd3b41fb2934af7af056eabecf (patch) | |
tree | 69419bec627cc506669a6227bf9df9daba1ce17b | |
parent | 8277f6937ae97c51ced5b54faa4934613c76999c (diff) |
NFC: nci: Add NFCEE discover support
NFCEEs (NFC Execution Environment) have to be explicitly
discovered by sending the NCI_OP_NFCEE_DISCOVER_CMD
command. The NFCC will respond to this command by telling
us how many NFCEEs are connected to it. Then the NFCC sends
a notification command for each and every NFCEE connected.
Here we implement support for sending
NCI_OP_NFCEE_DISCOVER_CMD command, receiving the response
and the potential notifications.
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r-- | include/net/nfc/nci_core.h | 4 | ||||
-rw-r--r-- | net/nfc/nci/core.c | 17 | ||||
-rw-r--r-- | net/nfc/nci/ntf.c | 30 | ||||
-rw-r--r-- | net/nfc/nci/rsp.c | 21 |
4 files changed, 72 insertions, 0 deletions
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index 5e508741f208..31ad795aa4b5 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h | |||
@@ -100,6 +100,8 @@ struct nci_conn_info { | |||
100 | struct sk_buff *rx_skb; | 100 | struct sk_buff *rx_skb; |
101 | }; | 101 | }; |
102 | 102 | ||
103 | #define NCI_INVALID_CONN_ID 0x80 | ||
104 | |||
103 | /* NCI Core structures */ | 105 | /* NCI Core structures */ |
104 | struct nci_dev { | 106 | struct nci_dev { |
105 | struct nfc_dev *nfc_dev; | 107 | struct nfc_dev *nfc_dev; |
@@ -182,6 +184,8 @@ void nci_unregister_device(struct nci_dev *ndev); | |||
182 | int nci_recv_frame(struct nci_dev *ndev, struct sk_buff *skb); | 184 | int nci_recv_frame(struct nci_dev *ndev, struct sk_buff *skb); |
183 | int nci_set_config(struct nci_dev *ndev, __u8 id, size_t len, __u8 *val); | 185 | int nci_set_config(struct nci_dev *ndev, __u8 id, size_t len, __u8 *val); |
184 | 186 | ||
187 | int nci_nfcee_discover(struct nci_dev *ndev, u8 action); | ||
188 | |||
185 | static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev, | 189 | static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev, |
186 | unsigned int len, | 190 | unsigned int len, |
187 | gfp_t how) | 191 | gfp_t how) |
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index eb607970bd56..a25857548524 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -469,6 +469,23 @@ int nci_set_config(struct nci_dev *ndev, __u8 id, size_t len, __u8 *val) | |||
469 | } | 469 | } |
470 | EXPORT_SYMBOL(nci_set_config); | 470 | EXPORT_SYMBOL(nci_set_config); |
471 | 471 | ||
472 | static void nci_nfcee_discover_req(struct nci_dev *ndev, unsigned long opt) | ||
473 | { | ||
474 | struct nci_nfcee_discover_cmd cmd; | ||
475 | __u8 action = opt; | ||
476 | |||
477 | cmd.discovery_action = action; | ||
478 | |||
479 | nci_send_cmd(ndev, NCI_OP_NFCEE_DISCOVER_CMD, 1, &cmd); | ||
480 | } | ||
481 | |||
482 | int nci_nfcee_discover(struct nci_dev *ndev, u8 action) | ||
483 | { | ||
484 | return nci_request(ndev, nci_nfcee_discover_req, action, | ||
485 | msecs_to_jiffies(NCI_CMD_TIMEOUT)); | ||
486 | } | ||
487 | EXPORT_SYMBOL(nci_nfcee_discover); | ||
488 | |||
472 | static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev) | 489 | static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev) |
473 | { | 490 | { |
474 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 491 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c index 28fdbe234bd4..4c0be7e82d29 100644 --- a/net/nfc/nci/ntf.c +++ b/net/nfc/nci/ntf.c | |||
@@ -713,6 +713,33 @@ static void nci_rf_deactivate_ntf_packet(struct nci_dev *ndev, | |||
713 | nci_req_complete(ndev, NCI_STATUS_OK); | 713 | nci_req_complete(ndev, NCI_STATUS_OK); |
714 | } | 714 | } |
715 | 715 | ||
716 | static void nci_nfcee_discover_ntf_packet(struct nci_dev *ndev, | ||
717 | struct sk_buff *skb) | ||
718 | { | ||
719 | u8 status = NCI_STATUS_OK; | ||
720 | struct nci_conn_info *conn_info; | ||
721 | struct nci_nfcee_discover_ntf *nfcee_ntf = | ||
722 | (struct nci_nfcee_discover_ntf *)skb->data; | ||
723 | |||
724 | pr_debug("\n"); | ||
725 | |||
726 | conn_info = devm_kzalloc(&ndev->nfc_dev->dev, | ||
727 | sizeof(struct nci_conn_info), GFP_KERNEL); | ||
728 | if (!conn_info) { | ||
729 | status = NCI_STATUS_REJECTED; | ||
730 | goto exit; | ||
731 | } | ||
732 | |||
733 | conn_info->id = nfcee_ntf->nfcee_id; | ||
734 | conn_info->conn_id = NCI_INVALID_CONN_ID; | ||
735 | |||
736 | INIT_LIST_HEAD(&conn_info->list); | ||
737 | list_add(&conn_info->list, &ndev->conn_info_list); | ||
738 | |||
739 | exit: | ||
740 | nci_req_complete(ndev, status); | ||
741 | } | ||
742 | |||
716 | void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) | 743 | void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) |
717 | { | 744 | { |
718 | __u16 ntf_opcode = nci_opcode(skb->data); | 745 | __u16 ntf_opcode = nci_opcode(skb->data); |
@@ -751,6 +778,9 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) | |||
751 | nci_rf_deactivate_ntf_packet(ndev, skb); | 778 | nci_rf_deactivate_ntf_packet(ndev, skb); |
752 | break; | 779 | break; |
753 | 780 | ||
781 | case NCI_OP_NFCEE_DISCOVER_NTF: | ||
782 | nci_nfcee_discover_ntf_packet(ndev, skb); | ||
783 | break; | ||
754 | default: | 784 | default: |
755 | pr_err("unknown ntf opcode 0x%x\n", ntf_opcode); | 785 | pr_err("unknown ntf opcode 0x%x\n", ntf_opcode); |
756 | break; | 786 | break; |
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c index 93b914937263..ee094dfab2ed 100644 --- a/net/nfc/nci/rsp.c +++ b/net/nfc/nci/rsp.c | |||
@@ -196,6 +196,23 @@ static void nci_rf_deactivate_rsp_packet(struct nci_dev *ndev, | |||
196 | } | 196 | } |
197 | } | 197 | } |
198 | 198 | ||
199 | static void nci_nfcee_discover_rsp_packet(struct nci_dev *ndev, | ||
200 | struct sk_buff *skb) | ||
201 | { | ||
202 | struct nci_nfcee_discover_rsp *discover_rsp; | ||
203 | |||
204 | if (skb->len != 2) { | ||
205 | nci_req_complete(ndev, NCI_STATUS_NFCEE_PROTOCOL_ERROR); | ||
206 | return; | ||
207 | } | ||
208 | |||
209 | discover_rsp = (struct nci_nfcee_discover_rsp *)skb->data; | ||
210 | |||
211 | if (discover_rsp->status != NCI_STATUS_OK || | ||
212 | discover_rsp->num_nfcee == 0) | ||
213 | nci_req_complete(ndev, discover_rsp->status); | ||
214 | } | ||
215 | |||
199 | void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) | 216 | void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) |
200 | { | 217 | { |
201 | __u16 rsp_opcode = nci_opcode(skb->data); | 218 | __u16 rsp_opcode = nci_opcode(skb->data); |
@@ -241,6 +258,10 @@ void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) | |||
241 | nci_rf_deactivate_rsp_packet(ndev, skb); | 258 | nci_rf_deactivate_rsp_packet(ndev, skb); |
242 | break; | 259 | break; |
243 | 260 | ||
261 | case NCI_OP_NFCEE_DISCOVER_RSP: | ||
262 | nci_nfcee_discover_rsp_packet(ndev, skb); | ||
263 | break; | ||
264 | |||
244 | default: | 265 | default: |
245 | pr_err("unknown rsp opcode 0x%x\n", rsp_opcode); | 266 | pr_err("unknown rsp opcode 0x%x\n", rsp_opcode); |
246 | break; | 267 | break; |