diff options
author | Christophe Ricard <christophe.ricard@gmail.com> | 2015-02-01 16:26:12 -0500 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2015-02-02 15:50:39 -0500 |
commit | 736bb9577407d3556d81c3c3cd57581cd3ae10ea (patch) | |
tree | ab3473fc3494458a13b08e964916d71df3d69dc5 /net/nfc | |
parent | f7f793f31378d5e83276871339c2a8374b0e8657 (diff) |
NFC: nci: Support logical connections management
In order to communicate with an NFCEE, we need to open a logical
connection to it, by sending the NCI_OP_CORE_CONN_CREATE_CMD
command to the NFCC. It's left up to the drivers to decide when
to close an already opened logical connection.
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc')
-rw-r--r-- | net/nfc/nci/core.c | 38 | ||||
-rw-r--r-- | net/nfc/nci/rsp.c | 47 |
2 files changed, 85 insertions, 0 deletions
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index e5fb8c8eed94..2a96ed68c7bb 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -507,6 +507,44 @@ int nci_nfcee_mode_set(struct nci_dev *ndev, u8 nfcee_id, u8 nfcee_mode) | |||
507 | } | 507 | } |
508 | EXPORT_SYMBOL(nci_nfcee_mode_set); | 508 | EXPORT_SYMBOL(nci_nfcee_mode_set); |
509 | 509 | ||
510 | static void nci_core_conn_create_req(struct nci_dev *ndev, unsigned long opt) | ||
511 | { | ||
512 | struct nci_core_conn_create_cmd cmd; | ||
513 | struct core_conn_create_dest_spec_params *params = | ||
514 | (struct core_conn_create_dest_spec_params *)opt; | ||
515 | |||
516 | cmd.destination_type = NCI_DESTINATION_NFCEE; | ||
517 | cmd.number_destination_params = 1; | ||
518 | memcpy(&cmd.params.type, params, | ||
519 | sizeof(struct core_conn_create_dest_spec_params)); | ||
520 | nci_send_cmd(ndev, NCI_OP_CORE_CONN_CREATE_CMD, | ||
521 | sizeof(struct nci_core_conn_create_cmd), &cmd); | ||
522 | } | ||
523 | |||
524 | int nci_core_conn_create(struct nci_dev *ndev, | ||
525 | struct core_conn_create_dest_spec_params *params) | ||
526 | { | ||
527 | ndev->cur_id = params->value.id; | ||
528 | return nci_request(ndev, nci_core_conn_create_req, | ||
529 | (unsigned long)params, | ||
530 | msecs_to_jiffies(NCI_CMD_TIMEOUT)); | ||
531 | } | ||
532 | EXPORT_SYMBOL(nci_core_conn_create); | ||
533 | |||
534 | static void nci_core_conn_close_req(struct nci_dev *ndev, unsigned long opt) | ||
535 | { | ||
536 | __u8 conn_id = opt; | ||
537 | |||
538 | nci_send_cmd(ndev, NCI_OP_CORE_CONN_CLOSE_CMD, 1, &conn_id); | ||
539 | } | ||
540 | |||
541 | int nci_core_conn_close(struct nci_dev *ndev, u8 conn_id) | ||
542 | { | ||
543 | return nci_request(ndev, nci_core_conn_close_req, conn_id, | ||
544 | msecs_to_jiffies(NCI_CMD_TIMEOUT)); | ||
545 | } | ||
546 | EXPORT_SYMBOL(nci_core_conn_close); | ||
547 | |||
510 | static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev) | 548 | static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev) |
511 | { | 549 | { |
512 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 550 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c index 0a3e98240dd6..31ccf7d05e82 100644 --- a/net/nfc/nci/rsp.c +++ b/net/nfc/nci/rsp.c | |||
@@ -222,6 +222,45 @@ static void nci_nfcee_mode_set_rsp_packet(struct nci_dev *ndev, | |||
222 | nci_req_complete(ndev, status); | 222 | nci_req_complete(ndev, status); |
223 | } | 223 | } |
224 | 224 | ||
225 | static void nci_core_conn_create_rsp_packet(struct nci_dev *ndev, | ||
226 | struct sk_buff *skb) | ||
227 | { | ||
228 | __u8 status = skb->data[0]; | ||
229 | struct nci_conn_info *conn_info; | ||
230 | struct nci_core_conn_create_rsp *rsp; | ||
231 | |||
232 | pr_debug("status 0x%x\n", status); | ||
233 | |||
234 | if (status == NCI_STATUS_OK) { | ||
235 | rsp = (struct nci_core_conn_create_rsp *)skb->data; | ||
236 | list_for_each_entry(conn_info, &ndev->conn_info_list, list) { | ||
237 | if (conn_info->id == ndev->cur_id) | ||
238 | break; | ||
239 | } | ||
240 | |||
241 | if (!conn_info || conn_info->id != ndev->cur_id) { | ||
242 | status = NCI_STATUS_REJECTED; | ||
243 | goto exit; | ||
244 | } | ||
245 | |||
246 | conn_info->conn_id = rsp->conn_id; | ||
247 | conn_info->max_pkt_payload_len = rsp->max_ctrl_pkt_payload_len; | ||
248 | atomic_set(&conn_info->credits_cnt, rsp->credits); | ||
249 | } | ||
250 | |||
251 | exit: | ||
252 | nci_req_complete(ndev, status); | ||
253 | } | ||
254 | |||
255 | static void nci_core_conn_close_rsp_packet(struct nci_dev *ndev, | ||
256 | struct sk_buff *skb) | ||
257 | { | ||
258 | __u8 status = skb->data[0]; | ||
259 | |||
260 | pr_debug("status 0x%x\n", status); | ||
261 | nci_req_complete(ndev, status); | ||
262 | } | ||
263 | |||
225 | void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) | 264 | void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) |
226 | { | 265 | { |
227 | __u16 rsp_opcode = nci_opcode(skb->data); | 266 | __u16 rsp_opcode = nci_opcode(skb->data); |
@@ -251,6 +290,14 @@ void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) | |||
251 | nci_core_set_config_rsp_packet(ndev, skb); | 290 | nci_core_set_config_rsp_packet(ndev, skb); |
252 | break; | 291 | break; |
253 | 292 | ||
293 | case NCI_OP_CORE_CONN_CREATE_RSP: | ||
294 | nci_core_conn_create_rsp_packet(ndev, skb); | ||
295 | break; | ||
296 | |||
297 | case NCI_OP_CORE_CONN_CLOSE_RSP: | ||
298 | nci_core_conn_close_rsp_packet(ndev, skb); | ||
299 | break; | ||
300 | |||
254 | case NCI_OP_RF_DISCOVER_MAP_RSP: | 301 | case NCI_OP_RF_DISCOVER_MAP_RSP: |
255 | nci_rf_disc_map_rsp_packet(ndev, skb); | 302 | nci_rf_disc_map_rsp_packet(ndev, skb); |
256 | break; | 303 | break; |