0001
0002
0003
0004
0005
0006
0007
0008 #include <net/genetlink.h>
0009 #include <linux/module.h>
0010 #include <linux/nfc.h>
0011 #include <linux/delay.h>
0012 #include <net/nfc/nci_core.h>
0013
0014 #include "st-nci.h"
0015
0016 #define ST_NCI_HCI_DM_GETDATA 0x10
0017 #define ST_NCI_HCI_DM_PUTDATA 0x11
0018 #define ST_NCI_HCI_DM_LOAD 0x12
0019 #define ST_NCI_HCI_DM_GETINFO 0x13
0020 #define ST_NCI_HCI_DM_FWUPD_START 0x14
0021 #define ST_NCI_HCI_DM_FWUPD_STOP 0x15
0022 #define ST_NCI_HCI_DM_UPDATE_AID 0x20
0023 #define ST_NCI_HCI_DM_RESET 0x3e
0024
0025 #define ST_NCI_HCI_DM_FIELD_GENERATOR 0x32
0026 #define ST_NCI_HCI_DM_VDC_MEASUREMENT_VALUE 0x33
0027 #define ST_NCI_HCI_DM_VDC_VALUE_COMPARISON 0x34
0028
0029 #define ST_NCI_FACTORY_MODE_ON 1
0030 #define ST_NCI_FACTORY_MODE_OFF 0
0031
0032 #define ST_NCI_EVT_POST_DATA 0x02
0033
0034 struct get_param_data {
0035 u8 gate;
0036 u8 data;
0037 } __packed;
0038
0039 static int st_nci_factory_mode(struct nfc_dev *dev, void *data,
0040 size_t data_len)
0041 {
0042 struct nci_dev *ndev = nfc_get_drvdata(dev);
0043 struct st_nci_info *info = nci_get_drvdata(ndev);
0044
0045 if (data_len != 1)
0046 return -EINVAL;
0047
0048 pr_debug("factory mode: %x\n", ((u8 *)data)[0]);
0049
0050 switch (((u8 *)data)[0]) {
0051 case ST_NCI_FACTORY_MODE_ON:
0052 test_and_set_bit(ST_NCI_FACTORY_MODE, &info->flags);
0053 break;
0054 case ST_NCI_FACTORY_MODE_OFF:
0055 clear_bit(ST_NCI_FACTORY_MODE, &info->flags);
0056 break;
0057 default:
0058 return -EINVAL;
0059 }
0060
0061 return 0;
0062 }
0063
0064 static int st_nci_hci_clear_all_pipes(struct nfc_dev *dev, void *data,
0065 size_t data_len)
0066 {
0067 struct nci_dev *ndev = nfc_get_drvdata(dev);
0068
0069 return nci_hci_clear_all_pipes(ndev);
0070 }
0071
0072 static int st_nci_hci_dm_put_data(struct nfc_dev *dev, void *data,
0073 size_t data_len)
0074 {
0075 struct nci_dev *ndev = nfc_get_drvdata(dev);
0076
0077 return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
0078 ST_NCI_HCI_DM_PUTDATA, data,
0079 data_len, NULL);
0080 }
0081
0082 static int st_nci_hci_dm_update_aid(struct nfc_dev *dev, void *data,
0083 size_t data_len)
0084 {
0085 struct nci_dev *ndev = nfc_get_drvdata(dev);
0086
0087 return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
0088 ST_NCI_HCI_DM_UPDATE_AID, data, data_len, NULL);
0089 }
0090
0091 static int st_nci_hci_dm_get_info(struct nfc_dev *dev, void *data,
0092 size_t data_len)
0093 {
0094 int r;
0095 struct sk_buff *msg, *skb;
0096 struct nci_dev *ndev = nfc_get_drvdata(dev);
0097
0098 r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE, ST_NCI_HCI_DM_GETINFO,
0099 data, data_len, &skb);
0100 if (r)
0101 return r;
0102
0103 msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
0104 HCI_DM_GET_INFO, skb->len);
0105 if (!msg) {
0106 r = -ENOMEM;
0107 goto free_skb;
0108 }
0109
0110 if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
0111 kfree_skb(msg);
0112 r = -ENOBUFS;
0113 goto free_skb;
0114 }
0115
0116 r = nfc_vendor_cmd_reply(msg);
0117
0118 free_skb:
0119 kfree_skb(skb);
0120 return r;
0121 }
0122
0123 static int st_nci_hci_dm_get_data(struct nfc_dev *dev, void *data,
0124 size_t data_len)
0125 {
0126 int r;
0127 struct sk_buff *msg, *skb;
0128 struct nci_dev *ndev = nfc_get_drvdata(dev);
0129
0130 r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE, ST_NCI_HCI_DM_GETDATA,
0131 data, data_len, &skb);
0132 if (r)
0133 return r;
0134
0135 msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_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 return r;
0153 }
0154
0155 static int st_nci_hci_dm_fwupd_start(struct nfc_dev *dev, void *data,
0156 size_t data_len)
0157 {
0158 int r;
0159 struct nci_dev *ndev = nfc_get_drvdata(dev);
0160
0161 dev->fw_download_in_progress = true;
0162 r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
0163 ST_NCI_HCI_DM_FWUPD_START, data, data_len, NULL);
0164 if (r)
0165 dev->fw_download_in_progress = false;
0166
0167 return r;
0168 }
0169
0170 static int st_nci_hci_dm_fwupd_end(struct nfc_dev *dev, void *data,
0171 size_t data_len)
0172 {
0173 struct nci_dev *ndev = nfc_get_drvdata(dev);
0174
0175 return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
0176 ST_NCI_HCI_DM_FWUPD_STOP, data, data_len, NULL);
0177 }
0178
0179 static int st_nci_hci_dm_direct_load(struct nfc_dev *dev, void *data,
0180 size_t data_len)
0181 {
0182 struct nci_dev *ndev = nfc_get_drvdata(dev);
0183
0184 if (dev->fw_download_in_progress) {
0185 dev->fw_download_in_progress = false;
0186 return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
0187 ST_NCI_HCI_DM_LOAD, data, data_len, NULL);
0188 }
0189 return -EPROTO;
0190 }
0191
0192 static int st_nci_hci_dm_reset(struct nfc_dev *dev, void *data,
0193 size_t data_len)
0194 {
0195 struct nci_dev *ndev = nfc_get_drvdata(dev);
0196
0197 nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
0198 ST_NCI_HCI_DM_RESET, data, data_len, NULL);
0199 msleep(200);
0200
0201 return 0;
0202 }
0203
0204 static int st_nci_hci_get_param(struct nfc_dev *dev, void *data,
0205 size_t data_len)
0206 {
0207 int r;
0208 struct sk_buff *msg, *skb;
0209 struct nci_dev *ndev = nfc_get_drvdata(dev);
0210 struct get_param_data *param = (struct get_param_data *)data;
0211
0212 if (data_len < sizeof(struct get_param_data))
0213 return -EPROTO;
0214
0215 r = nci_hci_get_param(ndev, param->gate, param->data, &skb);
0216 if (r)
0217 return r;
0218
0219 msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
0220 HCI_GET_PARAM, skb->len);
0221 if (!msg) {
0222 r = -ENOMEM;
0223 goto free_skb;
0224 }
0225
0226 if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
0227 kfree_skb(msg);
0228 r = -ENOBUFS;
0229 goto free_skb;
0230 }
0231
0232 r = nfc_vendor_cmd_reply(msg);
0233
0234 free_skb:
0235 kfree_skb(skb);
0236 return r;
0237 }
0238
0239 static int st_nci_hci_dm_field_generator(struct nfc_dev *dev, void *data,
0240 size_t data_len)
0241 {
0242 struct nci_dev *ndev = nfc_get_drvdata(dev);
0243
0244 return nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
0245 ST_NCI_HCI_DM_FIELD_GENERATOR, data, data_len, NULL);
0246 }
0247
0248 static int st_nci_hci_dm_vdc_measurement_value(struct nfc_dev *dev, void *data,
0249 size_t data_len)
0250 {
0251 int r;
0252 struct sk_buff *msg, *skb;
0253 struct nci_dev *ndev = nfc_get_drvdata(dev);
0254
0255 if (data_len != 4)
0256 return -EPROTO;
0257
0258 r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
0259 ST_NCI_HCI_DM_VDC_MEASUREMENT_VALUE,
0260 data, data_len, &skb);
0261 if (r)
0262 return r;
0263
0264 msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
0265 HCI_DM_VDC_MEASUREMENT_VALUE, skb->len);
0266 if (!msg) {
0267 r = -ENOMEM;
0268 goto free_skb;
0269 }
0270
0271 if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
0272 kfree_skb(msg);
0273 r = -ENOBUFS;
0274 goto free_skb;
0275 }
0276
0277 r = nfc_vendor_cmd_reply(msg);
0278
0279 free_skb:
0280 kfree_skb(skb);
0281 return r;
0282 }
0283
0284 static int st_nci_hci_dm_vdc_value_comparison(struct nfc_dev *dev, void *data,
0285 size_t data_len)
0286 {
0287 int r;
0288 struct sk_buff *msg, *skb;
0289 struct nci_dev *ndev = nfc_get_drvdata(dev);
0290
0291 if (data_len != 2)
0292 return -EPROTO;
0293
0294 r = nci_hci_send_cmd(ndev, ST_NCI_DEVICE_MGNT_GATE,
0295 ST_NCI_HCI_DM_VDC_VALUE_COMPARISON,
0296 data, data_len, &skb);
0297 if (r)
0298 return r;
0299
0300 msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
0301 HCI_DM_VDC_VALUE_COMPARISON, skb->len);
0302 if (!msg) {
0303 r = -ENOMEM;
0304 goto free_skb;
0305 }
0306
0307 if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
0308 kfree_skb(msg);
0309 r = -ENOBUFS;
0310 goto free_skb;
0311 }
0312
0313 r = nfc_vendor_cmd_reply(msg);
0314
0315 free_skb:
0316 kfree_skb(skb);
0317 return r;
0318 }
0319
0320 static int st_nci_loopback(struct nfc_dev *dev, void *data,
0321 size_t data_len)
0322 {
0323 int r;
0324 struct sk_buff *msg, *skb;
0325 struct nci_dev *ndev = nfc_get_drvdata(dev);
0326
0327 if (data_len <= 0)
0328 return -EPROTO;
0329
0330 r = nci_nfcc_loopback(ndev, data, data_len, &skb);
0331 if (r < 0)
0332 return r;
0333
0334 msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
0335 LOOPBACK, skb->len);
0336 if (!msg) {
0337 r = -ENOMEM;
0338 goto free_skb;
0339 }
0340
0341 if (nla_put(msg, NFC_ATTR_VENDOR_DATA, skb->len, skb->data)) {
0342 kfree_skb(msg);
0343 r = -ENOBUFS;
0344 goto free_skb;
0345 }
0346
0347 r = nfc_vendor_cmd_reply(msg);
0348 free_skb:
0349 kfree_skb(skb);
0350 return r;
0351 }
0352
0353 static int st_nci_manufacturer_specific(struct nfc_dev *dev, void *data,
0354 size_t data_len)
0355 {
0356 struct sk_buff *msg;
0357 struct nci_dev *ndev = nfc_get_drvdata(dev);
0358
0359 msg = nfc_vendor_cmd_alloc_reply_skb(dev, ST_NCI_VENDOR_OUI,
0360 MANUFACTURER_SPECIFIC,
0361 sizeof(ndev->manufact_specific_info));
0362 if (!msg)
0363 return -ENOMEM;
0364
0365 if (nla_put(msg, NFC_ATTR_VENDOR_DATA, sizeof(ndev->manufact_specific_info),
0366 &ndev->manufact_specific_info)) {
0367 kfree_skb(msg);
0368 return -ENOBUFS;
0369 }
0370
0371 return nfc_vendor_cmd_reply(msg);
0372 }
0373
0374 static const struct nfc_vendor_cmd st_nci_vendor_cmds[] = {
0375 {
0376 .vendor_id = ST_NCI_VENDOR_OUI,
0377 .subcmd = FACTORY_MODE,
0378 .doit = st_nci_factory_mode,
0379 },
0380 {
0381 .vendor_id = ST_NCI_VENDOR_OUI,
0382 .subcmd = HCI_CLEAR_ALL_PIPES,
0383 .doit = st_nci_hci_clear_all_pipes,
0384 },
0385 {
0386 .vendor_id = ST_NCI_VENDOR_OUI,
0387 .subcmd = HCI_DM_PUT_DATA,
0388 .doit = st_nci_hci_dm_put_data,
0389 },
0390 {
0391 .vendor_id = ST_NCI_VENDOR_OUI,
0392 .subcmd = HCI_DM_UPDATE_AID,
0393 .doit = st_nci_hci_dm_update_aid,
0394 },
0395 {
0396 .vendor_id = ST_NCI_VENDOR_OUI,
0397 .subcmd = HCI_DM_GET_INFO,
0398 .doit = st_nci_hci_dm_get_info,
0399 },
0400 {
0401 .vendor_id = ST_NCI_VENDOR_OUI,
0402 .subcmd = HCI_DM_GET_DATA,
0403 .doit = st_nci_hci_dm_get_data,
0404 },
0405 {
0406 .vendor_id = ST_NCI_VENDOR_OUI,
0407 .subcmd = HCI_DM_DIRECT_LOAD,
0408 .doit = st_nci_hci_dm_direct_load,
0409 },
0410 {
0411 .vendor_id = ST_NCI_VENDOR_OUI,
0412 .subcmd = HCI_DM_RESET,
0413 .doit = st_nci_hci_dm_reset,
0414 },
0415 {
0416 .vendor_id = ST_NCI_VENDOR_OUI,
0417 .subcmd = HCI_GET_PARAM,
0418 .doit = st_nci_hci_get_param,
0419 },
0420 {
0421 .vendor_id = ST_NCI_VENDOR_OUI,
0422 .subcmd = HCI_DM_FIELD_GENERATOR,
0423 .doit = st_nci_hci_dm_field_generator,
0424 },
0425 {
0426 .vendor_id = ST_NCI_VENDOR_OUI,
0427 .subcmd = HCI_DM_FWUPD_START,
0428 .doit = st_nci_hci_dm_fwupd_start,
0429 },
0430 {
0431 .vendor_id = ST_NCI_VENDOR_OUI,
0432 .subcmd = HCI_DM_FWUPD_END,
0433 .doit = st_nci_hci_dm_fwupd_end,
0434 },
0435 {
0436 .vendor_id = ST_NCI_VENDOR_OUI,
0437 .subcmd = LOOPBACK,
0438 .doit = st_nci_loopback,
0439 },
0440 {
0441 .vendor_id = ST_NCI_VENDOR_OUI,
0442 .subcmd = HCI_DM_VDC_MEASUREMENT_VALUE,
0443 .doit = st_nci_hci_dm_vdc_measurement_value,
0444 },
0445 {
0446 .vendor_id = ST_NCI_VENDOR_OUI,
0447 .subcmd = HCI_DM_VDC_VALUE_COMPARISON,
0448 .doit = st_nci_hci_dm_vdc_value_comparison,
0449 },
0450 {
0451 .vendor_id = ST_NCI_VENDOR_OUI,
0452 .subcmd = MANUFACTURER_SPECIFIC,
0453 .doit = st_nci_manufacturer_specific,
0454 },
0455 };
0456
0457 int st_nci_vendor_cmds_init(struct nci_dev *ndev)
0458 {
0459 return nci_set_vendor_cmds(ndev, st_nci_vendor_cmds,
0460 sizeof(st_nci_vendor_cmds));
0461 }
0462 EXPORT_SYMBOL(st_nci_vendor_cmds_init);