Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net/nfc/nci: Support NCI 2.x initial sequence

implement the NCI 2.x initial sequence to support NCI 2.x NFCC.
Since NCI 2.0, CORE_RESET and CORE_INIT sequence have been changed.
If NFCEE supports NCI 2.x, then NCI 2.x initial sequence will work.

In NCI 1.0, Initial sequence and payloads are as below:
(DH) (NFCC)
| -- CORE_RESET_CMD --> |
| <-- CORE_RESET_RSP -- |
| -- CORE_INIT_CMD --> |
| <-- CORE_INIT_RSP -- |
CORE_RESET_RSP payloads are Status, NCI version, Configuration Status.
CORE_INIT_CMD payloads are empty.
CORE_INIT_RSP payloads are Status, NFCC Features,
Number of Supported RF Interfaces, Supported RF Interface,
Max Logical Connections, Max Routing table Size,
Max Control Packet Payload Size, Max Size for Large Parameters,
Manufacturer ID, Manufacturer Specific Information.

In NCI 2.0, Initial Sequence and Parameters are as below:
(DH) (NFCC)
| -- CORE_RESET_CMD --> |
| <-- CORE_RESET_RSP -- |
| <-- CORE_RESET_NTF -- |
| -- CORE_INIT_CMD --> |
| <-- CORE_INIT_RSP -- |
CORE_RESET_RSP payloads are Status.
CORE_RESET_NTF payloads are Reset Trigger,
Configuration Status, NCI Version, Manufacturer ID,
Manufacturer Specific Information Length,
Manufacturer Specific Information.
CORE_INIT_CMD payloads are Feature1, Feature2.
CORE_INIT_RSP payloads are Status, NFCC Features,
Max Logical Connections, Max Routing Table Size,
Max Control Packet Payload Size,
Max Data Packet Payload Size of the Static HCI Connection,
Number of Credits of the Static HCI Connection,
Max NFC-V RF Frame Size, Number of Supported RF Interfaces,
Supported RF Interfaces.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
Link: https://lore.kernel.org/r/20201202223147.3472-1-bongsu.jeon@samsung.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Bongsu Jeon and committed by
Jakub Kicinski
bcd684aa 41fdfffd

+138 -16
+34
include/net/nfc/nci.h
··· 25 25 #define NCI_MAX_PARAM_LEN 251 26 26 #define NCI_MAX_PAYLOAD_SIZE 255 27 27 #define NCI_MAX_PACKET_SIZE 258 28 + #define NCI_MAX_LARGE_PARAMS_NCI_v2 15 29 + #define NCI_VER_2_MASK 0x20 28 30 29 31 /* NCI Status Codes */ 30 32 #define NCI_STATUS_OK 0x00 ··· 133 131 #define NCI_LF_CON_BITR_F_212 0x02 134 132 #define NCI_LF_CON_BITR_F_424 0x04 135 133 134 + /* NCI 2.x Feature Enable Bit */ 135 + #define NCI_FEATURE_DISABLE 0x00 136 + 136 137 /* NCI Reset types */ 137 138 #define NCI_RESET_TYPE_KEEP_CONFIG 0x00 138 139 #define NCI_RESET_TYPE_RESET_CONFIG 0x01 ··· 225 220 } __packed; 226 221 227 222 #define NCI_OP_CORE_INIT_CMD nci_opcode_pack(NCI_GID_CORE, 0x01) 223 + /* To support NCI 2.x */ 224 + struct nci_core_init_v2_cmd { 225 + u8 feature1; 226 + u8 feature2; 227 + }; 228 228 229 229 #define NCI_OP_CORE_SET_CONFIG_CMD nci_opcode_pack(NCI_GID_CORE, 0x02) 230 230 struct set_config_param { ··· 344 334 __le32 manufact_specific_info; 345 335 } __packed; 346 336 337 + /* To support NCI ver 2.x */ 338 + struct nci_core_init_rsp_nci_ver2 { 339 + u8 status; 340 + __le32 nfcc_features; 341 + u8 max_logical_connections; 342 + __le16 max_routing_table_size; 343 + u8 max_ctrl_pkt_payload_len; 344 + u8 max_data_pkt_hci_payload_len; 345 + u8 number_of_hci_credit; 346 + __le16 max_nfc_v_frame_size; 347 + u8 num_supported_rf_interfaces; 348 + u8 supported_rf_interfaces[]; 349 + } __packed; 350 + 347 351 #define NCI_OP_CORE_SET_CONFIG_RSP nci_opcode_pack(NCI_GID_CORE, 0x02) 348 352 struct nci_core_set_config_rsp { 349 353 __u8 status; ··· 396 372 /* --------------------------- */ 397 373 /* ---- NCI Notifications ---- */ 398 374 /* --------------------------- */ 375 + #define NCI_OP_CORE_RESET_NTF nci_opcode_pack(NCI_GID_CORE, 0x00) 376 + struct nci_core_reset_ntf { 377 + u8 reset_trigger; 378 + u8 config_status; 379 + u8 nci_ver; 380 + u8 manufact_id; 381 + u8 manufacturer_specific_len; 382 + __le32 manufact_specific_info; 383 + } __packed; 384 + 399 385 #define NCI_OP_CORE_CONN_CREDITS_NTF nci_opcode_pack(NCI_GID_CORE, 0x06) 400 386 struct conn_credit_entry { 401 387 __u8 conn_id;
+16 -2
net/nfc/nci/core.c
··· 165 165 166 166 static void nci_init_req(struct nci_dev *ndev, unsigned long opt) 167 167 { 168 - nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, 0, NULL); 168 + u8 plen = 0; 169 + 170 + if (opt) 171 + plen = sizeof(struct nci_core_init_v2_cmd); 172 + 173 + nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, plen, (void *)opt); 169 174 } 170 175 171 176 static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt) ··· 502 497 } 503 498 504 499 if (!rc) { 505 - rc = __nci_request(ndev, nci_init_req, 0, 500 + struct nci_core_init_v2_cmd nci_init_v2_cmd = { 501 + .feature1 = NCI_FEATURE_DISABLE, 502 + .feature2 = NCI_FEATURE_DISABLE 503 + }; 504 + unsigned long opt = 0; 505 + 506 + if (!(ndev->nci_ver & NCI_VER_2_MASK)) 507 + opt = (unsigned long)&nci_init_v2_cmd; 508 + 509 + rc = __nci_request(ndev, nci_init_req, opt, 506 510 msecs_to_jiffies(NCI_INIT_TIMEOUT)); 507 511 } 508 512
+21
net/nfc/nci/ntf.c
··· 27 27 28 28 /* Handle NCI Notification packets */ 29 29 30 + static void nci_core_reset_ntf_packet(struct nci_dev *ndev, 31 + struct sk_buff *skb) 32 + { 33 + /* Handle NCI 2.x core reset notification */ 34 + struct nci_core_reset_ntf *ntf = (void *)skb->data; 35 + 36 + ndev->nci_ver = ntf->nci_ver; 37 + pr_debug("nci_ver 0x%x, config_status 0x%x\n", 38 + ntf->nci_ver, ntf->config_status); 39 + 40 + ndev->manufact_id = ntf->manufact_id; 41 + ndev->manufact_specific_info = 42 + __le32_to_cpu(ntf->manufact_specific_info); 43 + 44 + nci_req_complete(ndev, NCI_STATUS_OK); 45 + } 46 + 30 47 static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev, 31 48 struct sk_buff *skb) 32 49 { ··· 773 756 } 774 757 775 758 switch (ntf_opcode) { 759 + case NCI_OP_CORE_RESET_NTF: 760 + nci_core_reset_ntf_packet(ndev, skb); 761 + break; 762 + 776 763 case NCI_OP_CORE_CONN_CREDITS_NTF: 777 764 nci_core_conn_credits_ntf_packet(ndev, skb); 778 765 break;
+67 -14
net/nfc/nci/rsp.c
··· 31 31 32 32 pr_debug("status 0x%x\n", rsp->status); 33 33 34 - if (rsp->status == NCI_STATUS_OK) { 35 - ndev->nci_ver = rsp->nci_ver; 36 - pr_debug("nci_ver 0x%x, config_status 0x%x\n", 37 - rsp->nci_ver, rsp->config_status); 38 - } 34 + /* Handle NCI 1.x ver */ 35 + if (skb->len != 1) { 36 + if (rsp->status == NCI_STATUS_OK) { 37 + ndev->nci_ver = rsp->nci_ver; 38 + pr_debug("nci_ver 0x%x, config_status 0x%x\n", 39 + rsp->nci_ver, rsp->config_status); 40 + } 39 41 40 - nci_req_complete(ndev, rsp->status); 42 + nci_req_complete(ndev, rsp->status); 43 + } 41 44 } 42 45 43 - static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) 46 + static u8 nci_core_init_rsp_packet_v1(struct nci_dev *ndev, struct sk_buff *skb) 44 47 { 45 48 struct nci_core_init_rsp_1 *rsp_1 = (void *) skb->data; 46 49 struct nci_core_init_rsp_2 *rsp_2; ··· 51 48 pr_debug("status 0x%x\n", rsp_1->status); 52 49 53 50 if (rsp_1->status != NCI_STATUS_OK) 54 - goto exit; 51 + return rsp_1->status; 55 52 56 53 ndev->nfcc_features = __le32_to_cpu(rsp_1->nfcc_features); 57 54 ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces; 58 55 59 - if (ndev->num_supported_rf_interfaces > 60 - NCI_MAX_SUPPORTED_RF_INTERFACES) { 61 - ndev->num_supported_rf_interfaces = 62 - NCI_MAX_SUPPORTED_RF_INTERFACES; 63 - } 56 + ndev->num_supported_rf_interfaces = 57 + min((int)ndev->num_supported_rf_interfaces, 58 + NCI_MAX_SUPPORTED_RF_INTERFACES); 64 59 65 60 memcpy(ndev->supported_rf_interfaces, 66 61 rsp_1->supported_rf_interfaces, ··· 77 76 rsp_2->manufact_id; 78 77 ndev->manufact_specific_info = 79 78 __le32_to_cpu(rsp_2->manufact_specific_info); 79 + 80 + return NCI_STATUS_OK; 81 + } 82 + 83 + static u8 nci_core_init_rsp_packet_v2(struct nci_dev *ndev, struct sk_buff *skb) 84 + { 85 + struct nci_core_init_rsp_nci_ver2 *rsp = (void *)skb->data; 86 + u8 *supported_rf_interface = rsp->supported_rf_interfaces; 87 + u8 rf_interface_idx = 0; 88 + u8 rf_extension_cnt = 0; 89 + 90 + pr_debug("status %x\n", rsp->status); 91 + 92 + if (rsp->status != NCI_STATUS_OK) 93 + return rsp->status; 94 + 95 + ndev->nfcc_features = __le32_to_cpu(rsp->nfcc_features); 96 + ndev->num_supported_rf_interfaces = rsp->num_supported_rf_interfaces; 97 + 98 + ndev->num_supported_rf_interfaces = 99 + min((int)ndev->num_supported_rf_interfaces, 100 + NCI_MAX_SUPPORTED_RF_INTERFACES); 101 + 102 + while (rf_interface_idx < ndev->num_supported_rf_interfaces) { 103 + ndev->supported_rf_interfaces[rf_interface_idx++] = *supported_rf_interface++; 104 + 105 + /* skip rf extension parameters */ 106 + rf_extension_cnt = *supported_rf_interface++; 107 + supported_rf_interface += rf_extension_cnt; 108 + } 109 + 110 + ndev->max_logical_connections = rsp->max_logical_connections; 111 + ndev->max_routing_table_size = 112 + __le16_to_cpu(rsp->max_routing_table_size); 113 + ndev->max_ctrl_pkt_payload_len = 114 + rsp->max_ctrl_pkt_payload_len; 115 + ndev->max_size_for_large_params = NCI_MAX_LARGE_PARAMS_NCI_v2; 116 + 117 + return NCI_STATUS_OK; 118 + } 119 + 120 + static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) 121 + { 122 + u8 status = 0; 123 + 124 + if (!(ndev->nci_ver & NCI_VER_2_MASK)) 125 + status = nci_core_init_rsp_packet_v1(ndev, skb); 126 + else 127 + status = nci_core_init_rsp_packet_v2(ndev, skb); 128 + 129 + if (status != NCI_STATUS_OK) 130 + goto exit; 80 131 81 132 pr_debug("nfcc_features 0x%x\n", 82 133 ndev->nfcc_features); ··· 156 103 ndev->manufact_specific_info); 157 104 158 105 exit: 159 - nci_req_complete(ndev, rsp_1->status); 106 + nci_req_complete(ndev, status); 160 107 } 161 108 162 109 static void nci_core_set_config_rsp_packet(struct nci_dev *ndev,