diff options
author | Christophe Ricard <christophe.ricard@gmail.com> | 2015-02-03 13:48:05 -0500 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2015-02-04 03:10:50 -0500 |
commit | b16ae7160a836c4a1e443ea6efca31421e86bae1 (patch) | |
tree | 8d4185e4b41b0d71f5abe293c3183068a129a86c | |
parent | 12bdf27d46c9d5e490fa164551642e065105db78 (diff) |
NFC: nci: Support all destinations type when creating a connection
The current implementation limits nci_core_conn_create_req()
to only manage NCI_DESTINATION_NFCEE.
Add new parameters to nci_core_conn_create() to support all
destination types described in the NCI specification.
Because there are some parameters with variable size dynamic
buffer allocation is needed.
Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r-- | drivers/nfc/st21nfcb/st21nfcb_se.c | 38 | ||||
-rw-r--r-- | include/net/nfc/nci.h | 18 | ||||
-rw-r--r-- | include/net/nfc/nci_core.h | 4 | ||||
-rw-r--r-- | net/nfc/nci/core.c | 48 |
4 files changed, 74 insertions, 34 deletions
diff --git a/drivers/nfc/st21nfcb/st21nfcb_se.c b/drivers/nfc/st21nfcb/st21nfcb_se.c index 9f4d8b744f32..3b465e4c85e3 100644 --- a/drivers/nfc/st21nfcb/st21nfcb_se.c +++ b/drivers/nfc/st21nfcb/st21nfcb_se.c | |||
@@ -494,7 +494,8 @@ EXPORT_SYMBOL_GPL(st21nfcb_nci_enable_se); | |||
494 | 494 | ||
495 | static int st21nfcb_hci_network_init(struct nci_dev *ndev) | 495 | static int st21nfcb_hci_network_init(struct nci_dev *ndev) |
496 | { | 496 | { |
497 | struct core_conn_create_dest_spec_params dest_params; | 497 | struct core_conn_create_dest_spec_params *dest_params; |
498 | struct dest_spec_params spec_params; | ||
498 | struct nci_conn_info *conn_info; | 499 | struct nci_conn_info *conn_info; |
499 | int r, dev_num; | 500 | int r, dev_num; |
500 | 501 | ||
@@ -502,17 +503,29 @@ static int st21nfcb_hci_network_init(struct nci_dev *ndev) | |||
502 | if (r != NCI_STATUS_OK) | 503 | if (r != NCI_STATUS_OK) |
503 | goto exit; | 504 | goto exit; |
504 | 505 | ||
505 | dest_params.type = NCI_DESTINATION_SPECIFIC_PARAM_NFCEE_TYPE; | 506 | dest_params = |
506 | dest_params.length = sizeof(struct dest_spec_params); | 507 | kzalloc(sizeof(struct core_conn_create_dest_spec_params) + |
507 | dest_params.value.id = ndev->hci_dev->conn_info->id; | 508 | sizeof(struct dest_spec_params), GFP_KERNEL); |
508 | dest_params.value.protocol = NCI_NFCEE_INTERFACE_HCI_ACCESS; | 509 | if (dest_params == NULL) { |
509 | r = nci_core_conn_create(ndev, &dest_params); | 510 | r = -ENOMEM; |
510 | if (r != NCI_STATUS_OK) | ||
511 | goto exit; | 511 | goto exit; |
512 | } | ||
513 | |||
514 | dest_params->type = NCI_DESTINATION_SPECIFIC_PARAM_NFCEE_TYPE; | ||
515 | dest_params->length = sizeof(struct dest_spec_params); | ||
516 | spec_params.id = ndev->hci_dev->conn_info->id; | ||
517 | spec_params.protocol = NCI_NFCEE_INTERFACE_HCI_ACCESS; | ||
518 | memcpy(dest_params->value, &spec_params, sizeof(struct dest_spec_params)); | ||
519 | r = nci_core_conn_create(ndev, NCI_DESTINATION_NFCEE, 1, | ||
520 | sizeof(struct core_conn_create_dest_spec_params) + | ||
521 | sizeof(struct dest_spec_params), | ||
522 | dest_params); | ||
523 | if (r != NCI_STATUS_OK) | ||
524 | goto free_dest_params; | ||
512 | 525 | ||
513 | conn_info = ndev->hci_dev->conn_info; | 526 | conn_info = ndev->hci_dev->conn_info; |
514 | if (!conn_info) | 527 | if (!conn_info) |
515 | goto exit; | 528 | goto free_dest_params; |
516 | 529 | ||
517 | memcpy(ndev->hci_dev->init_data.gates, st21nfcb_gates, | 530 | memcpy(ndev->hci_dev->init_data.gates, st21nfcb_gates, |
518 | sizeof(st21nfcb_gates)); | 531 | sizeof(st21nfcb_gates)); |
@@ -522,8 +535,10 @@ static int st21nfcb_hci_network_init(struct nci_dev *ndev) | |||
522 | * persistent info to discriminate 2 identical chips | 535 | * persistent info to discriminate 2 identical chips |
523 | */ | 536 | */ |
524 | dev_num = find_first_zero_bit(dev_mask, ST21NFCB_NUM_DEVICES); | 537 | dev_num = find_first_zero_bit(dev_mask, ST21NFCB_NUM_DEVICES); |
525 | if (dev_num >= ST21NFCB_NUM_DEVICES) | 538 | if (dev_num >= ST21NFCB_NUM_DEVICES) { |
526 | return -ENODEV; | 539 | r = -ENODEV; |
540 | goto free_dest_params; | ||
541 | } | ||
527 | 542 | ||
528 | scnprintf(ndev->hci_dev->init_data.session_id, | 543 | scnprintf(ndev->hci_dev->init_data.session_id, |
529 | sizeof(ndev->hci_dev->init_data.session_id), | 544 | sizeof(ndev->hci_dev->init_data.session_id), |
@@ -540,6 +555,9 @@ static int st21nfcb_hci_network_init(struct nci_dev *ndev) | |||
540 | 555 | ||
541 | return 0; | 556 | return 0; |
542 | 557 | ||
558 | free_dest_params: | ||
559 | kfree(dest_params); | ||
560 | |||
543 | exit: | 561 | exit: |
544 | return r; | 562 | return r; |
545 | } | 563 | } |
diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h index 6c1beb2704b1..695d33cb75e8 100644 --- a/include/net/nfc/nci.h +++ b/include/net/nfc/nci.h | |||
@@ -244,21 +244,23 @@ struct nci_core_set_config_cmd { | |||
244 | } __packed; | 244 | } __packed; |
245 | 245 | ||
246 | #define NCI_OP_CORE_CONN_CREATE_CMD nci_opcode_pack(NCI_GID_CORE, 0x04) | 246 | #define NCI_OP_CORE_CONN_CREATE_CMD nci_opcode_pack(NCI_GID_CORE, 0x04) |
247 | #define DEST_SPEC_PARAMS_ID_INDEX 0 | ||
248 | #define DEST_SPEC_PARAMS_PROTOCOL_INDEX 1 | ||
247 | struct dest_spec_params { | 249 | struct dest_spec_params { |
248 | __u8 id; | 250 | __u8 id; |
249 | __u8 protocol; | 251 | __u8 protocol; |
250 | } __packed; | 252 | } __packed; |
251 | 253 | ||
252 | struct core_conn_create_dest_spec_params { | 254 | struct core_conn_create_dest_spec_params { |
253 | __u8 type; | 255 | __u8 type; |
254 | __u8 length; | 256 | __u8 length; |
255 | struct dest_spec_params value; | 257 | __u8 value[0]; |
256 | } __packed; | 258 | } __packed; |
257 | 259 | ||
258 | struct nci_core_conn_create_cmd { | 260 | struct nci_core_conn_create_cmd { |
259 | __u8 destination_type; | 261 | __u8 destination_type; |
260 | __u8 number_destination_params; | 262 | __u8 number_destination_params; |
261 | struct core_conn_create_dest_spec_params params; | 263 | struct core_conn_create_dest_spec_params params[0]; |
262 | } __packed; | 264 | } __packed; |
263 | 265 | ||
264 | #define NCI_OP_CORE_CONN_CLOSE_CMD nci_opcode_pack(NCI_GID_CORE, 0x05) | 266 | #define NCI_OP_CORE_CONN_CLOSE_CMD nci_opcode_pack(NCI_GID_CORE, 0x05) |
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index 731fa5be9989..d34c1b2295d7 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h | |||
@@ -263,7 +263,9 @@ int nci_set_config(struct nci_dev *ndev, __u8 id, size_t len, __u8 *val); | |||
263 | 263 | ||
264 | int nci_nfcee_discover(struct nci_dev *ndev, u8 action); | 264 | int nci_nfcee_discover(struct nci_dev *ndev, u8 action); |
265 | int nci_nfcee_mode_set(struct nci_dev *ndev, u8 nfcee_id, u8 nfcee_mode); | 265 | int nci_nfcee_mode_set(struct nci_dev *ndev, u8 nfcee_id, u8 nfcee_mode); |
266 | int nci_core_conn_create(struct nci_dev *ndev, | 266 | int nci_core_conn_create(struct nci_dev *ndev, u8 destination_type, |
267 | u8 number_destination_params, | ||
268 | size_t params_len, | ||
267 | struct core_conn_create_dest_spec_params *params); | 269 | struct core_conn_create_dest_spec_params *params); |
268 | int nci_core_conn_close(struct nci_dev *ndev, u8 conn_id); | 270 | int nci_core_conn_close(struct nci_dev *ndev, u8 conn_id); |
269 | 271 | ||
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 17ff5f83393c..ddfe91e43c88 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -41,6 +41,11 @@ | |||
41 | #include <net/nfc/nci_core.h> | 41 | #include <net/nfc/nci_core.h> |
42 | #include <linux/nfc.h> | 42 | #include <linux/nfc.h> |
43 | 43 | ||
44 | struct core_conn_create_data { | ||
45 | int length; | ||
46 | struct nci_core_conn_create_cmd *cmd; | ||
47 | }; | ||
48 | |||
44 | static void nci_cmd_work(struct work_struct *work); | 49 | static void nci_cmd_work(struct work_struct *work); |
45 | static void nci_rx_work(struct work_struct *work); | 50 | static void nci_rx_work(struct work_struct *work); |
46 | static void nci_tx_work(struct work_struct *work); | 51 | static void nci_tx_work(struct work_struct *work); |
@@ -509,25 +514,38 @@ EXPORT_SYMBOL(nci_nfcee_mode_set); | |||
509 | 514 | ||
510 | static void nci_core_conn_create_req(struct nci_dev *ndev, unsigned long opt) | 515 | static void nci_core_conn_create_req(struct nci_dev *ndev, unsigned long opt) |
511 | { | 516 | { |
512 | struct nci_core_conn_create_cmd cmd; | 517 | struct core_conn_create_data *data = |
513 | struct core_conn_create_dest_spec_params *params = | 518 | (struct core_conn_create_data *)opt; |
514 | (struct core_conn_create_dest_spec_params *)opt; | 519 | |
515 | 520 | nci_send_cmd(ndev, NCI_OP_CORE_CONN_CREATE_CMD, data->length, data->cmd); | |
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 | } | 521 | } |
523 | 522 | ||
524 | int nci_core_conn_create(struct nci_dev *ndev, | 523 | int nci_core_conn_create(struct nci_dev *ndev, u8 destination_type, |
524 | u8 number_destination_params, | ||
525 | size_t params_len, | ||
525 | struct core_conn_create_dest_spec_params *params) | 526 | struct core_conn_create_dest_spec_params *params) |
526 | { | 527 | { |
527 | ndev->cur_id = params->value.id; | 528 | int r; |
528 | return nci_request(ndev, nci_core_conn_create_req, | 529 | struct nci_core_conn_create_cmd *cmd; |
529 | (unsigned long)params, | 530 | struct core_conn_create_data data; |
530 | msecs_to_jiffies(NCI_CMD_TIMEOUT)); | 531 | |
532 | data.length = params_len + sizeof(struct nci_core_conn_create_cmd); | ||
533 | cmd = kzalloc(data.length, GFP_KERNEL); | ||
534 | if (!cmd) | ||
535 | return -ENOMEM; | ||
536 | |||
537 | cmd->destination_type = destination_type; | ||
538 | cmd->number_destination_params = number_destination_params; | ||
539 | memcpy(cmd->params, params, params_len); | ||
540 | |||
541 | data.cmd = cmd; | ||
542 | ndev->cur_id = params->value[DEST_SPEC_PARAMS_ID_INDEX]; | ||
543 | |||
544 | r = __nci_request(ndev, nci_core_conn_create_req, | ||
545 | (unsigned long)&data, | ||
546 | msecs_to_jiffies(NCI_CMD_TIMEOUT)); | ||
547 | kfree(cmd); | ||
548 | return r; | ||
531 | } | 549 | } |
532 | EXPORT_SYMBOL(nci_core_conn_create); | 550 | EXPORT_SYMBOL(nci_core_conn_create); |
533 | 551 | ||