diff options
Diffstat (limited to 'drivers/nfc/st-nci/se.c')
| -rw-r--r-- | drivers/nfc/st-nci/se.c | 107 |
1 files changed, 55 insertions, 52 deletions
diff --git a/drivers/nfc/st-nci/se.c b/drivers/nfc/st-nci/se.c index f55d082ace71..607ec768eb7b 100644 --- a/drivers/nfc/st-nci/se.c +++ b/drivers/nfc/st-nci/se.c @@ -1,19 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Secure Element driver for STMicroelectronics NFC NCI chip * * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. */ #include <linux/module.h> @@ -268,7 +257,7 @@ static void st_nci_hci_admin_event_received(struct nci_dev *ndev, case ST_NCI_EVT_HOT_PLUG: if (info->se_info.se_active) { if (!ST_NCI_EVT_HOT_PLUG_IS_INHIBITED(skb)) { - del_timer_sync(&info->se_info.se_active_timer); + timer_delete_sync(&info->se_info.se_active_timer); info->se_info.se_active = false; complete(&info->se_info.req_completion); } else { @@ -287,14 +276,13 @@ static int st_nci_hci_apdu_reader_event_received(struct nci_dev *ndev, u8 event, struct sk_buff *skb) { - int r = 0; struct st_nci_info *info = nci_get_drvdata(ndev); pr_debug("apdu reader gate event: %x\n", event); switch (event) { case ST_NCI_EVT_TRANSMIT_DATA: - del_timer_sync(&info->se_info.bwi_timer); + timer_delete_sync(&info->se_info.bwi_timer); info->se_info.bwi_active = false; info->se_info.cb(info->se_info.cb_context, skb->data, skb->len, 0); @@ -309,7 +297,7 @@ static int st_nci_hci_apdu_reader_event_received(struct nci_dev *ndev, } kfree_skb(skb); - return r; + return 0; } /* @@ -324,6 +312,8 @@ static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev, int r = 0; struct device *dev = &ndev->nfc_dev->dev; struct nfc_evt_transaction *transaction; + u32 aid_len; + u8 params_len; pr_debug("connectivity gate event: %x\n", event); @@ -337,25 +327,47 @@ static int st_nci_hci_connectivity_event_received(struct nci_dev *ndev, * Description Tag Length * AID 81 5 to 16 * PARAMETERS 82 0 to 255 + * + * The key differences are aid storage length is variably sized + * in the packet, but fixed in nfc_evt_transaction, and that + * the aid_len is u8 in the packet, but u32 in the structure, + * and the tags in the packet are not included in + * nfc_evt_transaction. + * + * size(b): 1 1 5-16 1 1 0-255 + * offset: 0 1 2 aid_len + 2 aid_len + 3 aid_len + 4 + * mem name: aid_tag(M) aid_len aid params_tag(M) params_len params + * example: 0x81 5-16 X 0x82 0-255 X */ - if (skb->len < NFC_MIN_AID_LENGTH + 2 && - skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG) + if (skb->len < 2 || skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG) return -EPROTO; - transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev, - skb->len - 2, GFP_KERNEL); + aid_len = skb->data[1]; + + if (skb->len < aid_len + 4 || + aid_len > sizeof(transaction->aid)) + return -EPROTO; - transaction->aid_len = skb->data[1]; - memcpy(transaction->aid, &skb->data[2], transaction->aid_len); + params_len = skb->data[aid_len + 3]; - /* Check next byte is PARAMETERS tag (82) */ - if (skb->data[transaction->aid_len + 2] != - NFC_EVT_TRANSACTION_PARAMS_TAG) + /* Verify PARAMETERS tag is (82), and final check that there is + * enough space in the packet to read everything. + */ + if (skb->data[aid_len + 2] != NFC_EVT_TRANSACTION_PARAMS_TAG || + skb->len < aid_len + 4 + params_len) return -EPROTO; - transaction->params_len = skb->data[transaction->aid_len + 3]; - memcpy(transaction->params, skb->data + - transaction->aid_len + 4, transaction->params_len); + transaction = devm_kzalloc(dev, sizeof(*transaction) + + params_len, GFP_KERNEL); + if (!transaction) + return -ENOMEM; + + transaction->aid_len = aid_len; + transaction->params_len = params_len; + + memcpy(transaction->aid, &skb->data[2], aid_len); + memcpy(transaction->params, &skb->data[aid_len + 4], + params_len); r = nfc_se_transaction(ndev->nfc_dev, host, transaction); break; @@ -403,7 +415,7 @@ void st_nci_hci_cmd_received(struct nci_dev *ndev, u8 pipe, u8 cmd, if (ndev->hci_dev->count_pipes == ndev->hci_dev->expected_pipes) { - del_timer_sync(&info->se_info.se_active_timer); + timer_delete_sync(&info->se_info.se_active_timer); info->se_info.se_active = false; ndev->hci_dev->count_pipes = 0; complete(&info->se_info.req_completion); @@ -481,8 +493,6 @@ int st_nci_disable_se(struct nci_dev *ndev, u32 se_idx) { int r; - pr_debug("st_nci_disable_se\n"); - /* * According to upper layer, se_idx == NFC_SE_UICC when * info->se_info.se_status->is_uicc_enable is true should never happen @@ -507,8 +517,6 @@ int st_nci_enable_se(struct nci_dev *ndev, u32 se_idx) { int r; - pr_debug("st_nci_enable_se\n"); - /* * According to upper layer, se_idx == NFC_SE_UICC when * info->se_info.se_status->is_uicc_enable is true should never happen. @@ -545,10 +553,8 @@ static int st_nci_hci_network_init(struct nci_dev *ndev) dest_params = kzalloc(sizeof(struct core_conn_create_dest_spec_params) + sizeof(struct dest_spec_params), GFP_KERNEL); - if (dest_params == NULL) { - r = -ENOMEM; - goto exit; - } + if (dest_params == NULL) + return -ENOMEM; dest_params->type = NCI_DESTINATION_SPECIFIC_PARAM_NFCEE_TYPE; dest_params->length = sizeof(struct dest_spec_params); @@ -605,8 +611,6 @@ static int st_nci_hci_network_init(struct nci_dev *ndev) free_dest_params: kfree(dest_params); - -exit: return r; } @@ -617,8 +621,6 @@ int st_nci_discover_se(struct nci_dev *ndev) int se_count = 0; struct st_nci_info *info = nci_get_drvdata(ndev); - pr_debug("st_nci_discover_se\n"); - r = st_nci_hci_network_init(ndev); if (r != 0) return r; @@ -659,8 +661,6 @@ int st_nci_se_io(struct nci_dev *ndev, u32 se_idx, { struct st_nci_info *info = nci_get_drvdata(ndev); - pr_debug("\n"); - switch (se_idx) { case ST_NCI_ESE_HOST_ID: info->se_info.cb = cb; @@ -672,6 +672,12 @@ int st_nci_se_io(struct nci_dev *ndev, u32 se_idx, ST_NCI_EVT_TRANSMIT_DATA, apdu, apdu_length); default: + /* Need to free cb_context here as at the moment we can't + * clearly indicate to the caller if the callback function + * would be called (and free it) or not. In both cases a + * negative value may be returned to the caller. + */ + kfree(cb_context); return -ENODEV; } } @@ -690,9 +696,8 @@ static void st_nci_se_wt_timeout(struct timer_list *t) */ /* hardware reset managed through VCC_UICC_OUT power supply */ u8 param = 0x01; - struct st_nci_info *info = from_timer(info, t, se_info.bwi_timer); - - pr_debug("\n"); + struct st_nci_info *info = timer_container_of(info, t, + se_info.bwi_timer); info->se_info.bwi_active = false; @@ -710,10 +715,8 @@ static void st_nci_se_wt_timeout(struct timer_list *t) static void st_nci_se_activation_timeout(struct timer_list *t) { - struct st_nci_info *info = from_timer(info, t, - se_info.se_active_timer); - - pr_debug("\n"); + struct st_nci_info *info = timer_container_of(info, t, + se_info.se_active_timer); info->se_info.se_active = false; @@ -749,9 +752,9 @@ void st_nci_se_deinit(struct nci_dev *ndev) struct st_nci_info *info = nci_get_drvdata(ndev); if (info->se_info.bwi_active) - del_timer_sync(&info->se_info.bwi_timer); + timer_delete_sync(&info->se_info.bwi_timer); if (info->se_info.se_active) - del_timer_sync(&info->se_info.se_active_timer); + timer_delete_sync(&info->se_info.se_active_timer); info->se_info.se_active = false; info->se_info.bwi_active = false; |
