0001
0002
0003
0004
0005
0006
0007
0008 #include <net/genetlink.h>
0009 #include <linux/module.h>
0010 #include <linux/nfc.h>
0011 #include <net/nfc/hci.h>
0012 #include <net/nfc/llc.h>
0013
0014 #include "st21nfca.h"
0015
0016 #define ST21NFCA_HCI_DM_GETDATA 0x10
0017 #define ST21NFCA_HCI_DM_PUTDATA 0x11
0018 #define ST21NFCA_HCI_DM_LOAD 0x12
0019 #define ST21NFCA_HCI_DM_GETINFO 0x13
0020 #define ST21NFCA_HCI_DM_UPDATE_AID 0x20
0021 #define ST21NFCA_HCI_DM_RESET 0x3e
0022
0023 #define ST21NFCA_HCI_DM_FIELD_GENERATOR 0x32
0024
0025 #define ST21NFCA_FACTORY_MODE_ON 1
0026 #define ST21NFCA_FACTORY_MODE_OFF 0
0027
0028 #define ST21NFCA_EVT_POST_DATA 0x02
0029
0030 struct get_param_data {
0031 u8 gate;
0032 u8 data;
0033 } __packed;
0034
0035 static int st21nfca_factory_mode(struct nfc_dev *dev, void *data,
0036 size_t data_len)
0037 {
0038 struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
0039
0040 if (data_len != 1)
0041 return -EINVAL;
0042
0043 pr_debug("factory mode: %x\n", ((u8 *)data)[0]);
0044
0045 switch (((u8 *)data)[0]) {
0046 case ST21NFCA_FACTORY_MODE_ON:
0047 test_and_set_bit(ST21NFCA_FACTORY_MODE, &hdev->quirks);
0048 break;
0049 case ST21NFCA_FACTORY_MODE_OFF:
0050 clear_bit(ST21NFCA_FACTORY_MODE, &hdev->quirks);
0051 break;
0052 default:
0053 return -EINVAL;
0054 }
0055
0056 return 0;
0057 }
0058
0059 static int st21nfca_hci_clear_all_pipes(struct nfc_dev *dev, void *data,
0060 size_t data_len)
0061 {
0062 struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
0063
0064 return nfc_hci_disconnect_all_gates(hdev);
0065 }
0066
0067 static int st21nfca_hci_dm_put_data(struct nfc_dev *dev, void *data,
0068 size_t data_len)
0069 {
0070 struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
0071
0072 return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
0073 ST21NFCA_HCI_DM_PUTDATA, data,
0074 data_len, NULL);
0075 }
0076
0077 static int st21nfca_hci_dm_update_aid(struct nfc_dev *dev, void *data,
0078 size_t data_len)
0079 {
0080 struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
0081
0082 return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
0083 ST21NFCA_HCI_DM_UPDATE_AID, data, data_len, NULL);
0084 }
0085
0086 static int st21nfca_hci_dm_get_info(struct nfc_dev *dev, void *data,
0087 size_t data_len)
0088 {
0089 int r;
0090 struct sk_buff *msg, *skb;
0091 struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
0092
0093 r = nfc_hci_send_cmd(hdev,
0094 ST21NFCA_DEVICE_MGNT_GATE,
0095 ST21NFCA_HCI_DM_GETINFO,
0096 data, data_len, &skb);
0097 if (r)
0098 goto exit;
0099
0100 msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST21NFCA_VENDOR_OUI,
0101 HCI_DM_GET_INFO, skb->len);
0102 if (!msg) {
0103 r = -ENOMEM;
0104 goto free_skb;
0105 }
0106
0107 if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
0108 kfree_skb(msg);
0109 r = -ENOBUFS;
0110 goto free_skb;
0111 }
0112
0113 r = nfc_vendor_cmd_reply(msg);
0114
0115 free_skb:
0116 kfree_skb(skb);
0117 exit:
0118 return r;
0119 }
0120
0121 static int st21nfca_hci_dm_get_data(struct nfc_dev *dev, void *data,
0122 size_t data_len)
0123 {
0124 int r;
0125 struct sk_buff *msg, *skb;
0126 struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
0127
0128 r = nfc_hci_send_cmd(hdev,
0129 ST21NFCA_DEVICE_MGNT_GATE,
0130 ST21NFCA_HCI_DM_GETDATA,
0131 data, data_len, &skb);
0132 if (r)
0133 goto exit;
0134
0135 msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST21NFCA_VENDOR_OUI,
0136 HCI_DM_GET_DATA, skb->len);
0137 if (!msg) {
0138 r = -ENOMEM;
0139 goto free_skb;
0140 }
0141
0142 if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
0143 kfree_skb(msg);
0144 r = -ENOBUFS;
0145 goto free_skb;
0146 }
0147
0148 r = nfc_vendor_cmd_reply(msg);
0149
0150 free_skb:
0151 kfree_skb(skb);
0152 exit:
0153 return r;
0154 }
0155
0156 static int st21nfca_hci_dm_load(struct nfc_dev *dev, void *data,
0157 size_t data_len)
0158 {
0159 struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
0160
0161 return nfc_hci_send_cmd(hdev, ST21NFCA_DEVICE_MGNT_GATE,
0162 ST21NFCA_HCI_DM_LOAD, data, data_len, NULL);
0163 }
0164
0165 static int st21nfca_hci_dm_reset(struct nfc_dev *dev, void *data,
0166 size_t data_len)
0167 {
0168 int r;
0169 struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
0170
0171 r = nfc_hci_send_cmd_async(hdev, ST21NFCA_DEVICE_MGNT_GATE,
0172 ST21NFCA_HCI_DM_RESET, data, data_len, NULL, NULL);
0173 if (r < 0)
0174 return r;
0175
0176 r = nfc_llc_stop(hdev->llc);
0177 if (r < 0)
0178 return r;
0179
0180 return nfc_llc_start(hdev->llc);
0181 }
0182
0183 static int st21nfca_hci_get_param(struct nfc_dev *dev, void *data,
0184 size_t data_len)
0185 {
0186 int r;
0187 struct sk_buff *msg, *skb;
0188 struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
0189 struct get_param_data *param = (struct get_param_data *)data;
0190
0191 if (data_len < sizeof(struct get_param_data))
0192 return -EPROTO;
0193
0194 r = nfc_hci_get_param(hdev, param->gate, param->data, &skb);
0195 if (r)
0196 goto exit;
0197
0198 msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST21NFCA_VENDOR_OUI,
0199 HCI_GET_PARAM, skb->len);
0200 if (!msg) {
0201 r = -ENOMEM;
0202 goto free_skb;
0203 }
0204
0205 if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
0206 kfree_skb(msg);
0207 r = -ENOBUFS;
0208 goto free_skb;
0209 }
0210
0211 r = nfc_vendor_cmd_reply(msg);
0212
0213 free_skb:
0214 kfree_skb(skb);
0215 exit:
0216 return r;
0217 }
0218
0219 static int st21nfca_hci_dm_field_generator(struct nfc_dev *dev, void *data,
0220 size_t data_len)
0221 {
0222 struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
0223
0224 return nfc_hci_send_cmd(hdev,
0225 ST21NFCA_DEVICE_MGNT_GATE,
0226 ST21NFCA_HCI_DM_FIELD_GENERATOR,
0227 data, data_len, NULL);
0228 }
0229
0230 int st21nfca_hci_loopback_event_received(struct nfc_hci_dev *hdev, u8 event,
0231 struct sk_buff *skb)
0232 {
0233 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
0234
0235 switch (event) {
0236 case ST21NFCA_EVT_POST_DATA:
0237 info->vendor_info.rx_skb = skb;
0238 break;
0239 default:
0240 nfc_err(&hdev->ndev->dev, "Unexpected event on loopback gate\n");
0241 }
0242 complete(&info->vendor_info.req_completion);
0243 return 0;
0244 }
0245 EXPORT_SYMBOL(st21nfca_hci_loopback_event_received);
0246
0247 static int st21nfca_hci_loopback(struct nfc_dev *dev, void *data,
0248 size_t data_len)
0249 {
0250 int r;
0251 struct sk_buff *msg;
0252 struct nfc_hci_dev *hdev = nfc_get_drvdata(dev);
0253 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
0254
0255 if (data_len <= 0)
0256 return -EPROTO;
0257
0258 reinit_completion(&info->vendor_info.req_completion);
0259 info->vendor_info.rx_skb = NULL;
0260
0261 r = nfc_hci_send_event(hdev, NFC_HCI_LOOPBACK_GATE,
0262 ST21NFCA_EVT_POST_DATA, data, data_len);
0263 if (r < 0) {
0264 r = -EPROTO;
0265 goto exit;
0266 }
0267
0268 wait_for_completion_interruptible(&info->vendor_info.req_completion);
0269 if (!info->vendor_info.rx_skb ||
0270 info->vendor_info.rx_skb->len != data_len) {
0271 r = -EPROTO;
0272 goto exit;
0273 }
0274
0275 msg = nfc_vendor_cmd_alloc_reply_skb(hdev->ndev,
0276 ST21NFCA_VENDOR_OUI,
0277 HCI_LOOPBACK,
0278 info->vendor_info.rx_skb->len);
0279 if (!msg) {
0280 r = -ENOMEM;
0281 goto free_skb;
0282 }
0283
0284 if (nla_put(msg, NFC_ATTR_VENDOR_DATA, info->vendor_info.rx_skb->len,
0285 info->vendor_info.rx_skb->data)) {
0286 kfree_skb(msg);
0287 r = -ENOBUFS;
0288 goto free_skb;
0289 }
0290
0291 r = nfc_vendor_cmd_reply(msg);
0292 free_skb:
0293 kfree_skb(info->vendor_info.rx_skb);
0294 exit:
0295 return r;
0296 }
0297
0298 static const struct nfc_vendor_cmd st21nfca_vendor_cmds[] = {
0299 {
0300 .vendor_id = ST21NFCA_VENDOR_OUI,
0301 .subcmd = FACTORY_MODE,
0302 .doit = st21nfca_factory_mode,
0303 },
0304 {
0305 .vendor_id = ST21NFCA_VENDOR_OUI,
0306 .subcmd = HCI_CLEAR_ALL_PIPES,
0307 .doit = st21nfca_hci_clear_all_pipes,
0308 },
0309 {
0310 .vendor_id = ST21NFCA_VENDOR_OUI,
0311 .subcmd = HCI_DM_PUT_DATA,
0312 .doit = st21nfca_hci_dm_put_data,
0313 },
0314 {
0315 .vendor_id = ST21NFCA_VENDOR_OUI,
0316 .subcmd = HCI_DM_UPDATE_AID,
0317 .doit = st21nfca_hci_dm_update_aid,
0318 },
0319 {
0320 .vendor_id = ST21NFCA_VENDOR_OUI,
0321 .subcmd = HCI_DM_GET_INFO,
0322 .doit = st21nfca_hci_dm_get_info,
0323 },
0324 {
0325 .vendor_id = ST21NFCA_VENDOR_OUI,
0326 .subcmd = HCI_DM_GET_DATA,
0327 .doit = st21nfca_hci_dm_get_data,
0328 },
0329 {
0330 .vendor_id = ST21NFCA_VENDOR_OUI,
0331 .subcmd = HCI_DM_LOAD,
0332 .doit = st21nfca_hci_dm_load,
0333 },
0334 {
0335 .vendor_id = ST21NFCA_VENDOR_OUI,
0336 .subcmd = HCI_DM_RESET,
0337 .doit = st21nfca_hci_dm_reset,
0338 },
0339 {
0340 .vendor_id = ST21NFCA_VENDOR_OUI,
0341 .subcmd = HCI_GET_PARAM,
0342 .doit = st21nfca_hci_get_param,
0343 },
0344 {
0345 .vendor_id = ST21NFCA_VENDOR_OUI,
0346 .subcmd = HCI_DM_FIELD_GENERATOR,
0347 .doit = st21nfca_hci_dm_field_generator,
0348 },
0349 {
0350 .vendor_id = ST21NFCA_VENDOR_OUI,
0351 .subcmd = HCI_LOOPBACK,
0352 .doit = st21nfca_hci_loopback,
0353 },
0354 };
0355
0356 int st21nfca_vendor_cmds_init(struct nfc_hci_dev *hdev)
0357 {
0358 struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
0359
0360 init_completion(&info->vendor_info.req_completion);
0361 return nfc_hci_set_vendor_cmds(hdev, st21nfca_vendor_cmds,
0362 sizeof(st21nfca_vendor_cmds));
0363 }
0364 EXPORT_SYMBOL(st21nfca_vendor_cmds_init);