Christophe Ricard | 6895730 | 2014-03-25 06:51:47 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2014 STMicroelectronics SAS. All rights reserved. |
| 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify it |
| 5 | * under the terms and conditions of the GNU General Public License, |
| 6 | * version 2, as published by the Free Software Foundation. |
| 7 | * |
| 8 | * This program is distributed in the hope that it will be useful, |
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 11 | * GNU General Public License for more details. |
| 12 | * |
| 13 | * You should have received a copy of the GNU General Public License |
| 14 | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
| 15 | */ |
| 16 | |
| 17 | #ifndef __LOCAL_ST21NFCA_H_ |
| 18 | #define __LOCAL_ST21NFCA_H_ |
| 19 | |
| 20 | #include <net/nfc/hci.h> |
Christophe Ricard | 1c54795 | 2015-10-25 22:54:18 +0100 | [diff] [blame] | 21 | #include <linux/skbuff.h> |
| 22 | #include <linux/workqueue.h> |
Christophe Ricard | 1892bf8 | 2014-05-20 22:21:59 +0200 | [diff] [blame] | 23 | |
Christophe Ricard | 6895730 | 2014-03-25 06:51:47 +0100 | [diff] [blame] | 24 | #define HCI_MODE 0 |
| 25 | |
| 26 | /* framing in HCI mode */ |
| 27 | #define ST21NFCA_SOF_EOF_LEN 2 |
| 28 | |
| 29 | /* Almost every time value is 0 */ |
| 30 | #define ST21NFCA_HCI_LLC_LEN 1 |
| 31 | |
| 32 | /* Size in worst case : |
| 33 | * In normal case CRC len = 2 but byte stuffing |
| 34 | * may appear in case one CRC byte = ST21NFCA_SOF_EOF |
| 35 | */ |
| 36 | #define ST21NFCA_HCI_LLC_CRC 4 |
| 37 | |
| 38 | #define ST21NFCA_HCI_LLC_LEN_CRC (ST21NFCA_SOF_EOF_LEN + \ |
| 39 | ST21NFCA_HCI_LLC_LEN + \ |
| 40 | ST21NFCA_HCI_LLC_CRC) |
| 41 | #define ST21NFCA_HCI_LLC_MIN_SIZE (1 + ST21NFCA_HCI_LLC_LEN_CRC) |
| 42 | |
| 43 | /* Worst case when adding byte stuffing between each byte */ |
| 44 | #define ST21NFCA_HCI_LLC_MAX_PAYLOAD 29 |
| 45 | #define ST21NFCA_HCI_LLC_MAX_SIZE (ST21NFCA_HCI_LLC_LEN_CRC + 1 + \ |
| 46 | ST21NFCA_HCI_LLC_MAX_PAYLOAD) |
| 47 | |
Christophe Ricard | 1c54795 | 2015-10-25 22:54:18 +0100 | [diff] [blame] | 48 | /* Reader RF commands */ |
| 49 | #define ST21NFCA_WR_XCHG_DATA 0x10 |
| 50 | |
| 51 | #define ST21NFCA_DEVICE_MGNT_GATE 0x01 |
| 52 | #define ST21NFCA_RF_READER_F_GATE 0x14 |
| 53 | #define ST21NFCA_RF_CARD_F_GATE 0x24 |
| 54 | #define ST21NFCA_APDU_READER_GATE 0xf0 |
| 55 | #define ST21NFCA_CONNECTIVITY_GATE 0x41 |
| 56 | |
| 57 | /* |
| 58 | * ref ISO7816-3 chap 8.1. the initial character TS is followed by a |
| 59 | * sequence of at most 32 characters. |
| 60 | */ |
| 61 | #define ST21NFCA_ESE_MAX_LENGTH 33 |
| 62 | #define ST21NFCA_ESE_HOST_ID 0xc0 |
| 63 | |
Christophe Ricard | 6895730 | 2014-03-25 06:51:47 +0100 | [diff] [blame] | 64 | #define DRIVER_DESC "HCI NFC driver for ST21NFCA" |
| 65 | |
Christophe Ricard | 1c54795 | 2015-10-25 22:54:18 +0100 | [diff] [blame] | 66 | #define ST21NFCA_HCI_MODE 0 |
| 67 | #define ST21NFCA_NUM_DEVICES 256 |
Christophe Ricard | 6895730 | 2014-03-25 06:51:47 +0100 | [diff] [blame] | 68 | |
Christophe Ricard | 15d1717 | 2015-10-26 07:50:11 +0100 | [diff] [blame] | 69 | #define ST21NFCA_VENDOR_OUI 0x0080E1 /* STMicroelectronics */ |
| 70 | #define ST21NFCA_FACTORY_MODE 2 |
| 71 | |
Christophe Ricard | 2130fb9 | 2015-01-27 01:18:19 +0100 | [diff] [blame] | 72 | struct st21nfca_se_status { |
| 73 | bool is_ese_present; |
| 74 | bool is_uicc_present; |
| 75 | }; |
| 76 | |
Christophe Ricard | 6895730 | 2014-03-25 06:51:47 +0100 | [diff] [blame] | 77 | enum st21nfca_state { |
| 78 | ST21NFCA_ST_COLD, |
| 79 | ST21NFCA_ST_READY, |
| 80 | }; |
| 81 | |
Christophe Ricard | 15d1717 | 2015-10-26 07:50:11 +0100 | [diff] [blame] | 82 | /** |
| 83 | * enum nfc_vendor_cmds - supported nfc vendor commands |
| 84 | * |
| 85 | * @FACTORY_MODE: Allow to set the driver into a mode where no secure element |
| 86 | * are activated. It does not consider any NFC_ATTR_VENDOR_DATA. |
| 87 | * @HCI_CLEAR_ALL_PIPES: Allow to execute a HCI clear all pipes command. |
| 88 | * It does not consider any NFC_ATTR_VENDOR_DATA. |
| 89 | * @HCI_DM_PUT_DATA: Allow to configure specific CLF registry as for example |
| 90 | * RF trimmings or low level drivers configurations (I2C, SPI, SWP). |
| 91 | * @HCI_DM_UPDATE_AID: Allow to configure an AID routing into the CLF routing |
| 92 | * table following RF technology, CLF mode or protocol. |
| 93 | * @HCI_DM_GET_INFO: Allow to retrieve CLF information. |
| 94 | * @HCI_DM_GET_DATA: Allow to retrieve CLF configurable data such as low |
| 95 | * level drivers configurations or RF trimmings. |
| 96 | * @HCI_DM_LOAD: Allow to load a firmware into the CLF. A complete |
| 97 | * packet can be more than 8KB. |
| 98 | * @HCI_DM_RESET: Allow to run a CLF reset in order to "commit" CLF |
| 99 | * configuration changes without CLF power off. |
| 100 | * @HCI_GET_PARAM: Allow to retrieve an HCI CLF parameter (for example the |
| 101 | * white list). |
| 102 | * @HCI_DM_FIELD_GENERATOR: Allow to generate different kind of RF |
| 103 | * technology. When using this command to anti-collision is done. |
| 104 | * @HCI_LOOPBACK: Allow to echo a command and test the Dh to CLF |
| 105 | * connectivity. |
| 106 | */ |
| 107 | enum nfc_vendor_cmds { |
| 108 | FACTORY_MODE, |
| 109 | HCI_CLEAR_ALL_PIPES, |
| 110 | HCI_DM_PUT_DATA, |
| 111 | HCI_DM_UPDATE_AID, |
| 112 | HCI_DM_GET_INFO, |
| 113 | HCI_DM_GET_DATA, |
| 114 | HCI_DM_LOAD, |
| 115 | HCI_DM_RESET, |
| 116 | HCI_GET_PARAM, |
| 117 | HCI_DM_FIELD_GENERATOR, |
| 118 | HCI_LOOPBACK, |
| 119 | }; |
| 120 | |
| 121 | struct st21nfca_vendor_info { |
| 122 | struct completion req_completion; |
| 123 | struct sk_buff *rx_skb; |
| 124 | }; |
| 125 | |
Christophe Ricard | 1c54795 | 2015-10-25 22:54:18 +0100 | [diff] [blame] | 126 | struct st21nfca_dep_info { |
| 127 | struct sk_buff *tx_pending; |
| 128 | struct work_struct tx_work; |
| 129 | u8 curr_nfc_dep_pni; |
| 130 | u32 idx; |
| 131 | u8 to; |
| 132 | u8 did; |
| 133 | u8 bsi; |
| 134 | u8 bri; |
| 135 | u8 lri; |
| 136 | } __packed; |
| 137 | |
| 138 | struct st21nfca_se_info { |
| 139 | u8 atr[ST21NFCA_ESE_MAX_LENGTH]; |
| 140 | struct completion req_completion; |
| 141 | |
| 142 | struct timer_list bwi_timer; |
| 143 | int wt_timeout; /* in msecs */ |
| 144 | bool bwi_active; |
| 145 | |
| 146 | struct timer_list se_active_timer; |
| 147 | bool se_active; |
| 148 | int expected_pipes; |
| 149 | int count_pipes; |
| 150 | |
| 151 | bool xch_error; |
| 152 | |
| 153 | se_io_cb_t cb; |
| 154 | void *cb_context; |
| 155 | }; |
| 156 | |
Christophe Ricard | 6895730 | 2014-03-25 06:51:47 +0100 | [diff] [blame] | 157 | struct st21nfca_hci_info { |
| 158 | struct nfc_phy_ops *phy_ops; |
| 159 | void *phy_id; |
| 160 | |
| 161 | struct nfc_hci_dev *hdev; |
Christophe Ricard | 2130fb9 | 2015-01-27 01:18:19 +0100 | [diff] [blame] | 162 | struct st21nfca_se_status *se_status; |
Christophe Ricard | 6895730 | 2014-03-25 06:51:47 +0100 | [diff] [blame] | 163 | |
| 164 | enum st21nfca_state state; |
| 165 | |
| 166 | struct mutex info_lock; |
| 167 | |
| 168 | int async_cb_type; |
| 169 | data_exchange_cb_t async_cb; |
| 170 | void *async_cb_context; |
| 171 | |
Christophe Ricard | 1892bf8 | 2014-05-20 22:21:59 +0200 | [diff] [blame] | 172 | struct st21nfca_dep_info dep_info; |
Christophe Ricard | 2130fb9 | 2015-01-27 01:18:19 +0100 | [diff] [blame] | 173 | struct st21nfca_se_info se_info; |
Christophe Ricard | 15d1717 | 2015-10-26 07:50:11 +0100 | [diff] [blame] | 174 | struct st21nfca_vendor_info vendor_info; |
Christophe Ricard | 1892bf8 | 2014-05-20 22:21:59 +0200 | [diff] [blame] | 175 | }; |
Christophe Ricard | 6895730 | 2014-03-25 06:51:47 +0100 | [diff] [blame] | 176 | |
Christophe Ricard | 1c54795 | 2015-10-25 22:54:18 +0100 | [diff] [blame] | 177 | int st21nfca_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, |
| 178 | char *llc_name, int phy_headroom, int phy_tailroom, |
| 179 | int phy_payload, struct nfc_hci_dev **hdev, |
Christophe Ricard | 15d1717 | 2015-10-26 07:50:11 +0100 | [diff] [blame] | 180 | struct st21nfca_se_status *se_status); |
Christophe Ricard | 1c54795 | 2015-10-25 22:54:18 +0100 | [diff] [blame] | 181 | void st21nfca_hci_remove(struct nfc_hci_dev *hdev); |
Christophe Ricard | 6895730 | 2014-03-25 06:51:47 +0100 | [diff] [blame] | 182 | |
Christophe Ricard | 1c54795 | 2015-10-25 22:54:18 +0100 | [diff] [blame] | 183 | int st21nfca_dep_event_received(struct nfc_hci_dev *hdev, |
| 184 | u8 event, struct sk_buff *skb); |
| 185 | int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb); |
| 186 | |
| 187 | int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len); |
| 188 | int st21nfca_im_send_dep_req(struct nfc_hci_dev *hdev, struct sk_buff *skb); |
| 189 | void st21nfca_dep_init(struct nfc_hci_dev *hdev); |
| 190 | void st21nfca_dep_deinit(struct nfc_hci_dev *hdev); |
| 191 | |
| 192 | int st21nfca_connectivity_event_received(struct nfc_hci_dev *hdev, u8 host, |
| 193 | u8 event, struct sk_buff *skb); |
| 194 | int st21nfca_apdu_reader_event_received(struct nfc_hci_dev *hdev, |
| 195 | u8 event, struct sk_buff *skb); |
| 196 | |
| 197 | int st21nfca_hci_discover_se(struct nfc_hci_dev *hdev); |
| 198 | int st21nfca_hci_enable_se(struct nfc_hci_dev *hdev, u32 se_idx); |
| 199 | int st21nfca_hci_disable_se(struct nfc_hci_dev *hdev, u32 se_idx); |
| 200 | int st21nfca_hci_se_io(struct nfc_hci_dev *hdev, u32 se_idx, |
| 201 | u8 *apdu, size_t apdu_length, |
| 202 | se_io_cb_t cb, void *cb_context); |
| 203 | |
| 204 | void st21nfca_se_init(struct nfc_hci_dev *hdev); |
| 205 | void st21nfca_se_deinit(struct nfc_hci_dev *hdev); |
Christophe Ricard | 1892bf8 | 2014-05-20 22:21:59 +0200 | [diff] [blame] | 206 | |
Christophe Ricard | 15d1717 | 2015-10-26 07:50:11 +0100 | [diff] [blame] | 207 | int st21nfca_hci_loopback_event_received(struct nfc_hci_dev *ndev, u8 event, |
| 208 | struct sk_buff *skb); |
| 209 | int st21nfca_vendor_cmds_init(struct nfc_hci_dev *ndev); |
| 210 | |
Christophe Ricard | 6895730 | 2014-03-25 06:51:47 +0100 | [diff] [blame] | 211 | #endif /* __LOCAL_ST21NFCA_H_ */ |