diff options
Diffstat (limited to 'drivers/nfc/pn533/pn533.c')
| -rw-r--r-- | drivers/nfc/pn533/pn533.c | 415 |
1 files changed, 285 insertions, 130 deletions
diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c index c05cb637ba92..2b043a9f9533 100644 --- a/drivers/nfc/pn533/pn533.c +++ b/drivers/nfc/pn533/pn533.c @@ -1,21 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Driver for NXP PN533 NFC Chip - core functions * * Copyright (C) 2011 Instituto Nokia de Tecnologia * Copyright (C) 2012-2013 Tieto Poland - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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/device.h> @@ -197,6 +185,32 @@ struct pn533_cmd_jump_dep_response { u8 gt[]; } __packed; +struct pn532_autopoll_resp { + u8 type; + u8 ln; + u8 tg; + u8 tgdata[]; +}; + +/* PN532_CMD_IN_AUTOPOLL */ +#define PN532_AUTOPOLL_POLLNR_INFINITE 0xff +#define PN532_AUTOPOLL_PERIOD 0x03 /* in units of 150 ms */ + +#define PN532_AUTOPOLL_TYPE_GENERIC_106 0x00 +#define PN532_AUTOPOLL_TYPE_GENERIC_212 0x01 +#define PN532_AUTOPOLL_TYPE_GENERIC_424 0x02 +#define PN532_AUTOPOLL_TYPE_JEWEL 0x04 +#define PN532_AUTOPOLL_TYPE_MIFARE 0x10 +#define PN532_AUTOPOLL_TYPE_FELICA212 0x11 +#define PN532_AUTOPOLL_TYPE_FELICA424 0x12 +#define PN532_AUTOPOLL_TYPE_ISOA 0x20 +#define PN532_AUTOPOLL_TYPE_ISOB 0x23 +#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_106 0x40 +#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_212 0x41 +#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_424 0x42 +#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_106 0x80 +#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_212 0x81 +#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_424 0x82 /* PN533_TG_INIT_AS_TARGET */ #define PN533_INIT_TARGET_PASSIVE 0x1 @@ -475,12 +489,8 @@ static int pn533_send_data_async(struct pn533 *dev, u8 cmd_code, pn533_send_async_complete_t complete_cb, void *complete_cb_context) { - int rc; - - rc = __pn533_send_async(dev, cmd_code, req, complete_cb, + return __pn533_send_async(dev, cmd_code, req, complete_cb, complete_cb_context); - - return rc; } static int pn533_send_cmd_async(struct pn533 *dev, u8 cmd_code, @@ -488,18 +498,14 @@ static int pn533_send_cmd_async(struct pn533 *dev, u8 cmd_code, pn533_send_async_complete_t complete_cb, void *complete_cb_context) { - int rc; - - rc = __pn533_send_async(dev, cmd_code, req, complete_cb, + return __pn533_send_async(dev, cmd_code, req, complete_cb, complete_cb_context); - - return rc; } /* * pn533_send_cmd_direct_async * - * The function sends a piority cmd directly to the chip omitting the cmd + * The function sends a priority cmd directly to the chip omitting the cmd * queue. It's intended to be used by chaining mechanism of received responses * where the host has to request every single chunk of data before scheduling * next cmd from the queue. @@ -601,7 +607,7 @@ static int pn533_send_sync_complete(struct pn533 *dev, void *_arg, * as it's been already freed at the beginning of RX path by * async_complete_cb. * - * 3. valid pointer in case of succesfult RX path + * 3. valid pointer in case of successful RX path * * A caller has to check a return value with IS_ERR macro. If the test pass, * the returned pointer is valid. @@ -692,6 +698,9 @@ static bool pn533_target_type_a_is_valid(struct pn533_target_type_a *type_a, if (PN533_TYPE_A_SEL_CASCADE(type_a->sel_res) != 0) return false; + if (type_a->nfcid_len > NFC_NFCID1_MAXSIZE) + return false; + return true; } @@ -1066,8 +1075,6 @@ static int pn533_tm_get_data_complete(struct pn533 *dev, void *arg, u8 status, ret, mi; int rc; - dev_dbg(dev->dev, "%s\n", __func__); - if (IS_ERR(resp)) { skb_queue_purge(&dev->resp_q); return PTR_ERR(resp); @@ -1115,8 +1122,6 @@ static void pn533_wq_tm_mi_recv(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(dev->dev, "%s\n", __func__); - skb = pn533_alloc_skb(dev, 0); if (!skb) return; @@ -1139,8 +1144,6 @@ static void pn533_wq_tm_mi_send(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(dev->dev, "%s\n", __func__); - /* Grab the first skb in the queue */ skb = skb_dequeue(&dev->fragment_skb); if (skb == NULL) { /* No more data */ @@ -1177,8 +1180,6 @@ static void pn533_wq_tg_get_data(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(dev->dev, "%s\n", __func__); - skb = pn533_alloc_skb(dev, 0); if (!skb) return; @@ -1197,8 +1198,6 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) size_t gb_len; int rc; - dev_dbg(dev->dev, "%s\n", __func__); - if (resp->len < ATR_REQ_GB_OFFSET + 1) return -EINVAL; @@ -1232,11 +1231,9 @@ static int pn533_init_target_complete(struct pn533 *dev, struct sk_buff *resp) return 0; } -static void pn533_listen_mode_timer(unsigned long data) +static void pn533_listen_mode_timer(struct timer_list *t) { - struct pn533 *dev = (struct pn533 *)data; - - dev_dbg(dev->dev, "Listen mode timeout\n"); + struct pn533 *dev = timer_container_of(dev, t, listen_timer); dev->cancel_listen = 1; @@ -1251,8 +1248,6 @@ static int pn533_rf_complete(struct pn533 *dev, void *arg, { int rc = 0; - dev_dbg(dev->dev, "%s\n", __func__); - if (IS_ERR(resp)) { rc = PTR_ERR(resp); @@ -1274,8 +1269,6 @@ static void pn533_wq_rf(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(dev->dev, "%s\n", __func__); - skb = pn533_alloc_skb(dev, 2); if (!skb) return; @@ -1302,6 +1295,8 @@ static int pn533_poll_dep_complete(struct pn533 *dev, void *arg, if (IS_ERR(resp)) return PTR_ERR(resp); + memset(&nfc_target, 0, sizeof(struct nfc_target)); + rsp = (struct pn533_cmd_jump_dep_response *)resp->data; rc = rsp->status & PN533_CMD_RET_MASK; @@ -1351,8 +1346,6 @@ static int pn533_poll_dep(struct nfc_dev *nfc_dev) u8 *next, nfcid3[NFC_NFCID3_MAXSIZE]; u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; - dev_dbg(dev->dev, "%s", __func__); - if (!dev->gb) { dev->gb = nfc_get_local_general_bytes(nfc_dev, &dev->gb_len); @@ -1401,14 +1394,105 @@ static int pn533_poll_dep(struct nfc_dev *nfc_dev) return rc; } +static int pn533_autopoll_complete(struct pn533 *dev, void *arg, + struct sk_buff *resp) +{ + struct pn532_autopoll_resp *apr; + struct nfc_target nfc_tgt; + u8 nbtg; + int rc; + + if (IS_ERR(resp)) { + rc = PTR_ERR(resp); + + nfc_err(dev->dev, "%s autopoll complete error %d\n", + __func__, rc); + + if (rc == -ENOENT) { + if (dev->poll_mod_count != 0) + return rc; + goto stop_poll; + } + nfc_err(dev->dev, "Error %d when running autopoll\n", rc); + goto stop_poll; + } + + nbtg = resp->data[0]; + if ((nbtg > 2) || (nbtg <= 0)) + return -EAGAIN; + + apr = (struct pn532_autopoll_resp *)&resp->data[1]; + while (nbtg--) { + memset(&nfc_tgt, 0, sizeof(struct nfc_target)); + switch (apr->type) { + case PN532_AUTOPOLL_TYPE_ISOA: + dev_dbg(dev->dev, "ISOA\n"); + rc = pn533_target_found_type_a(&nfc_tgt, apr->tgdata, + apr->ln - 1); + break; + case PN532_AUTOPOLL_TYPE_FELICA212: + case PN532_AUTOPOLL_TYPE_FELICA424: + dev_dbg(dev->dev, "FELICA\n"); + rc = pn533_target_found_felica(&nfc_tgt, apr->tgdata, + apr->ln - 1); + break; + case PN532_AUTOPOLL_TYPE_JEWEL: + dev_dbg(dev->dev, "JEWEL\n"); + rc = pn533_target_found_jewel(&nfc_tgt, apr->tgdata, + apr->ln - 1); + break; + case PN532_AUTOPOLL_TYPE_ISOB: + dev_dbg(dev->dev, "ISOB\n"); + rc = pn533_target_found_type_b(&nfc_tgt, apr->tgdata, + apr->ln - 1); + break; + case PN532_AUTOPOLL_TYPE_MIFARE: + dev_dbg(dev->dev, "Mifare\n"); + rc = pn533_target_found_type_a(&nfc_tgt, apr->tgdata, + apr->ln - 1); + break; + default: + nfc_err(dev->dev, + "Unknown current poll modulation\n"); + rc = -EPROTO; + } + + if (rc) + goto done; + + if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) { + nfc_err(dev->dev, + "The Tg found doesn't have the desired protocol\n"); + rc = -EAGAIN; + goto done; + } + + dev->tgt_available_prots = nfc_tgt.supported_protocols; + apr = (struct pn532_autopoll_resp *) + (apr->tgdata + (apr->ln - 1)); + } + + pn533_poll_reset_mod_list(dev); + nfc_targets_found(dev->nfc_dev, &nfc_tgt, 1); + +done: + dev_kfree_skb(resp); + return rc; + +stop_poll: + nfc_err(dev->dev, "autopoll operation has been stopped\n"); + + pn533_poll_reset_mod_list(dev); + dev->poll_protocols = 0; + return rc; +} + static int pn533_poll_complete(struct pn533 *dev, void *arg, struct sk_buff *resp) { struct pn533_poll_modulations *cur_mod; int rc; - dev_dbg(dev->dev, "%s\n", __func__); - if (IS_ERR(resp)) { rc = PTR_ERR(resp); @@ -1419,17 +1503,15 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, if (dev->poll_mod_count != 0) return rc; goto stop_poll; - } else if (rc < 0) { - nfc_err(dev->dev, - "Error %d when running poll\n", rc); - goto stop_poll; } + nfc_err(dev->dev, "Error %d when running poll\n", rc); + goto stop_poll; } cur_mod = dev->poll_mod_active[dev->poll_mod_curr]; if (cur_mod->len == 0) { /* Target mode */ - del_timer(&dev->listen_timer); + timer_delete(&dev->listen_timer); rc = pn533_init_target_complete(dev, resp); goto done; } @@ -1544,6 +1626,7 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev, { struct pn533 *dev = nfc_get_drvdata(nfc_dev); struct pn533_poll_modulations *cur_mod; + struct sk_buff *skb; u8 rand_mod; int rc; @@ -1569,9 +1652,78 @@ static int pn533_start_poll(struct nfc_dev *nfc_dev, tm_protocols = 0; } - pn533_poll_create_mod_list(dev, im_protocols, tm_protocols); dev->poll_protocols = im_protocols; dev->listen_protocols = tm_protocols; + if (dev->device_type == PN533_DEVICE_PN532_AUTOPOLL) { + skb = pn533_alloc_skb(dev, 4 + 6); + if (!skb) + return -ENOMEM; + + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_POLLNR_INFINITE; + *((u8 *)skb_put(skb, sizeof(u8))) = PN532_AUTOPOLL_PERIOD; + + if ((im_protocols & NFC_PROTO_MIFARE_MASK) && + (im_protocols & NFC_PROTO_ISO14443_MASK) && + (im_protocols & NFC_PROTO_NFC_DEP_MASK)) + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_GENERIC_106; + else { + if (im_protocols & NFC_PROTO_MIFARE_MASK) + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_MIFARE; + + if (im_protocols & NFC_PROTO_ISO14443_MASK) + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_ISOA; + + if (im_protocols & NFC_PROTO_NFC_DEP_MASK) { + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_DEP_PASSIVE_106; + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_DEP_PASSIVE_212; + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_DEP_PASSIVE_424; + } + } + + if (im_protocols & NFC_PROTO_FELICA_MASK || + im_protocols & NFC_PROTO_NFC_DEP_MASK) { + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_FELICA212; + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_FELICA424; + } + + if (im_protocols & NFC_PROTO_JEWEL_MASK) + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_JEWEL; + + if (im_protocols & NFC_PROTO_ISO14443_B_MASK) + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_ISOB; + + if (tm_protocols) + *((u8 *)skb_put(skb, sizeof(u8))) = + PN532_AUTOPOLL_TYPE_DEP_ACTIVE_106; + + rc = pn533_send_cmd_async(dev, PN533_CMD_IN_AUTOPOLL, skb, + pn533_autopoll_complete, NULL); + + if (rc < 0) + dev_kfree_skb(skb); + else + dev->poll_mod_count++; + + return rc; + } + + pn533_poll_create_mod_list(dev, im_protocols, tm_protocols); + if (!dev->poll_mod_count) { + nfc_err(dev->dev, + "Poll mod list is empty\n"); + return -EINVAL; + } /* Do not always start polling from the same modulation */ get_random_bytes(&rand_mod, sizeof(rand_mod)); @@ -1593,7 +1745,7 @@ static void pn533_stop_poll(struct nfc_dev *nfc_dev) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); - del_timer(&dev->listen_timer); + timer_delete(&dev->listen_timer); if (!dev->poll_mod_count) { dev_dbg(dev->dev, @@ -1614,8 +1766,6 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) struct sk_buff *skb; struct sk_buff *resp; - dev_dbg(dev->dev, "%s\n", __func__); - skb = pn533_alloc_skb(dev, sizeof(u8) * 2); /*TG + Next*/ if (!skb) return -ENOMEM; @@ -1697,8 +1847,6 @@ static int pn533_deactivate_target_complete(struct pn533 *dev, void *arg, { int rc = 0; - dev_dbg(dev->dev, "%s\n", __func__); - if (IS_ERR(resp)) { rc = PTR_ERR(resp); @@ -1723,8 +1871,6 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, struct sk_buff *skb; int rc; - dev_dbg(dev->dev, "%s\n", __func__); - if (!dev->tgt_active_prot) { nfc_err(dev->dev, "There is no active target\n"); return; @@ -1783,6 +1929,8 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, dev_dbg(dev->dev, "Creating new target\n"); + memset(&nfc_target, 0, sizeof(struct nfc_target)); + nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK; nfc_target.nfcid1_len = 10; memcpy(nfc_target.nfcid1, rsp->nfcid3t, nfc_target.nfcid1_len); @@ -1819,8 +1967,6 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, u8 *next, *arg, nfcid3[NFC_NFCID3_MAXSIZE]; u8 passive_data[PASSIVE_DATA_LEN] = {0x00, 0xff, 0xff, 0x00, 0x3}; - dev_dbg(dev->dev, "%s\n", __func__); - if (dev->poll_mod_count) { nfc_err(dev->dev, "Cannot bring the DEP link up while polling\n"); @@ -1898,8 +2044,6 @@ static int pn533_dep_link_down(struct nfc_dev *nfc_dev) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); - dev_dbg(dev->dev, "%s\n", __func__); - pn533_poll_reset_mod_list(dev); if (dev->tgt_mode || dev->tgt_active_prot) @@ -1923,8 +2067,6 @@ static struct sk_buff *pn533_build_response(struct pn533 *dev) struct sk_buff *skb, *tmp, *t; unsigned int skb_len = 0, tmp_len = 0; - dev_dbg(dev->dev, "%s\n", __func__); - if (skb_queue_empty(&dev->resp_q)) return NULL; @@ -1964,8 +2106,6 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg, int rc = 0; u8 status, ret, mi; - dev_dbg(dev->dev, "%s\n", __func__); - if (IS_ERR(resp)) { rc = PTR_ERR(resp); goto _error; @@ -2036,7 +2176,7 @@ void pn533_recv_frame(struct pn533 *dev, struct sk_buff *skb, int status) } if (skb == NULL) { - pr_err("NULL Frame -> link is dead\n"); + dev_err(dev->dev, "NULL Frame -> link is dead\n"); goto sched_wq; } @@ -2081,7 +2221,7 @@ static int pn533_fill_fragment_skbs(struct pn533 *dev, struct sk_buff *skb) frag = pn533_alloc_skb(dev, frag_size); if (!frag) { skb_queue_purge(&dev->fragment_skb); - break; + return -ENOMEM; } if (!dev->tgt_mode) { @@ -2119,8 +2259,6 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, struct pn533_data_exchange_arg *arg = NULL; int rc; - dev_dbg(dev->dev, "%s\n", __func__); - if (!dev->tgt_active_prot) { nfc_err(dev->dev, "Can't exchange data if there is no active target\n"); @@ -2147,11 +2285,12 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, break; } + fallthrough; default: /* jumbo frame ? */ if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { rc = pn533_fill_fragment_skbs(dev, skb); - if (rc <= 0) + if (rc < 0) goto error; skb = skb_dequeue(&dev->fragment_skb); @@ -2186,8 +2325,6 @@ static int pn533_tm_send_complete(struct pn533 *dev, void *arg, { u8 status; - dev_dbg(dev->dev, "%s\n", __func__); - if (IS_ERR(resp)) return PTR_ERR(resp); @@ -2218,12 +2355,10 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) struct pn533 *dev = nfc_get_drvdata(nfc_dev); int rc; - dev_dbg(dev->dev, "%s\n", __func__); - /* let's split in multiple chunks if size's too big */ if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { rc = pn533_fill_fragment_skbs(dev, skb); - if (rc <= 0) + if (rc < 0) goto error; /* get the first skb */ @@ -2256,8 +2391,6 @@ static void pn533_wq_mi_recv(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(dev->dev, "%s\n", __func__); - skb = pn533_alloc_skb(dev, PN533_CMD_DATAEXCH_HEAD_LEN); if (!skb) goto error; @@ -2273,6 +2406,7 @@ static void pn533_wq_mi_recv(struct work_struct *work) break; } + fallthrough; default: skb_put_u8(skb, 1); /*TG*/ @@ -2305,8 +2439,6 @@ static void pn533_wq_mi_send(struct work_struct *work) struct sk_buff *skb; int rc; - dev_dbg(dev->dev, "%s\n", __func__); - /* Grab the first skb in the queue */ skb = skb_dequeue(&dev->fragment_skb); @@ -2362,8 +2494,6 @@ static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, struct sk_buff *resp; int skb_len; - dev_dbg(dev->dev, "%s\n", __func__); - skb_len = sizeof(cfgitem) + cfgdata_len; /* cfgitem + cfgdata */ skb = pn533_alloc_skb(dev, skb_len); @@ -2409,8 +2539,6 @@ static int pn533_pasori_fw_reset(struct pn533 *dev) struct sk_buff *skb; struct sk_buff *resp; - dev_dbg(dev->dev, "%s\n", __func__); - skb = pn533_alloc_skb(dev, sizeof(u8)); if (!skb) return -ENOMEM; @@ -2441,7 +2569,7 @@ static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf) return rc; } - return rc; + return 0; } static int pn532_sam_configuration(struct nfc_dev *nfc_dev) @@ -2467,9 +2595,17 @@ static int pn532_sam_configuration(struct nfc_dev *nfc_dev) static int pn533_dev_up(struct nfc_dev *nfc_dev) { struct pn533 *dev = nfc_get_drvdata(nfc_dev); + int rc; - if (dev->device_type == PN533_DEVICE_PN532) { - int rc = pn532_sam_configuration(nfc_dev); + if (dev->phy_ops->dev_up) { + rc = dev->phy_ops->dev_up(dev); + if (rc) + return rc; + } + + if ((dev->device_type == PN533_DEVICE_PN532) || + (dev->device_type == PN533_DEVICE_PN532_AUTOPOLL)) { + rc = pn532_sam_configuration(nfc_dev); if (rc) return rc; @@ -2480,10 +2616,17 @@ static int pn533_dev_up(struct nfc_dev *nfc_dev) static int pn533_dev_down(struct nfc_dev *nfc_dev) { - return pn533_rf_field(nfc_dev, 0); + struct pn533 *dev = nfc_get_drvdata(nfc_dev); + int ret; + + ret = pn533_rf_field(nfc_dev, 0); + if (dev->phy_ops->dev_down && !ret) + ret = dev->phy_ops->dev_down(dev); + + return ret; } -static struct nfc_ops pn533_nfc_ops = { +static const struct nfc_ops pn533_nfc_ops = { .dev_up = pn533_dev_up, .dev_down = pn533_dev_down, .dep_link_up = pn533_dep_link_up, @@ -2508,6 +2651,7 @@ static int pn533_setup(struct pn533 *dev) case PN533_DEVICE_PASORI: case PN533_DEVICE_ACR122U: case PN533_DEVICE_PN532: + case PN533_DEVICE_PN532_AUTOPOLL: max_retries.mx_rty_atr = 0x2; max_retries.mx_rty_psl = 0x1; max_retries.mx_rty_passive_act = @@ -2544,6 +2688,7 @@ static int pn533_setup(struct pn533 *dev) switch (dev->device_type) { case PN533_DEVICE_STD: case PN533_DEVICE_PN532: + case PN533_DEVICE_PN532_AUTOPOLL: break; case PN533_DEVICE_PASORI: @@ -2590,17 +2735,14 @@ int pn533_finalize_setup(struct pn533 *dev) } EXPORT_SYMBOL_GPL(pn533_finalize_setup); -struct pn533 *pn533_register_device(u32 device_type, - u32 protocols, +struct pn533 *pn53x_common_init(u32 device_type, enum pn533_protocol_type protocol_type, void *phy, - struct pn533_phy_ops *phy_ops, + const struct pn533_phy_ops *phy_ops, struct pn533_frame_ops *fops, - struct device *dev, - struct device *parent) + struct device *dev) { struct pn533 *priv; - int rc = -ENOMEM; priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) @@ -2632,58 +2774,32 @@ struct pn533 *pn533_register_device(u32 device_type, if (priv->wq == NULL) goto error; - init_timer(&priv->listen_timer); - priv->listen_timer.data = (unsigned long) priv; - priv->listen_timer.function = pn533_listen_mode_timer; + timer_setup(&priv->listen_timer, pn533_listen_mode_timer, 0); skb_queue_head_init(&priv->resp_q); skb_queue_head_init(&priv->fragment_skb); INIT_LIST_HEAD(&priv->cmd_queue); - - priv->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, - priv->ops->tx_header_len + - PN533_CMD_DATAEXCH_HEAD_LEN, - priv->ops->tx_tail_len); - if (!priv->nfc_dev) { - rc = -ENOMEM; - goto destroy_wq; - } - - nfc_set_parent_dev(priv->nfc_dev, parent); - nfc_set_drvdata(priv->nfc_dev, priv); - - rc = nfc_register_device(priv->nfc_dev); - if (rc) - goto free_nfc_dev; - return priv; -free_nfc_dev: - nfc_free_device(priv->nfc_dev); - -destroy_wq: - destroy_workqueue(priv->wq); error: kfree(priv); - return ERR_PTR(rc); + return ERR_PTR(-ENOMEM); } -EXPORT_SYMBOL_GPL(pn533_register_device); +EXPORT_SYMBOL_GPL(pn53x_common_init); -void pn533_unregister_device(struct pn533 *priv) +void pn53x_common_clean(struct pn533 *priv) { struct pn533_cmd *cmd, *n; - nfc_unregister_device(priv->nfc_dev); - nfc_free_device(priv->nfc_dev); + /* delete the timer before cleanup the worker */ + timer_shutdown_sync(&priv->listen_timer); flush_delayed_work(&priv->poll_work); destroy_workqueue(priv->wq); skb_queue_purge(&priv->resp_q); - del_timer(&priv->listen_timer); - list_for_each_entry_safe(cmd, n, &priv->cmd_queue, queue) { list_del(&cmd->queue); kfree(cmd); @@ -2691,8 +2807,47 @@ void pn533_unregister_device(struct pn533 *priv) kfree(priv); } -EXPORT_SYMBOL_GPL(pn533_unregister_device); +EXPORT_SYMBOL_GPL(pn53x_common_clean); + +int pn532_i2c_nfc_alloc(struct pn533 *priv, u32 protocols, + struct device *parent) +{ + priv->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, + priv->ops->tx_header_len + + PN533_CMD_DATAEXCH_HEAD_LEN, + priv->ops->tx_tail_len); + if (!priv->nfc_dev) + return -ENOMEM; + nfc_set_parent_dev(priv->nfc_dev, parent); + nfc_set_drvdata(priv->nfc_dev, priv); + return 0; +} +EXPORT_SYMBOL_GPL(pn532_i2c_nfc_alloc); + +int pn53x_register_nfc(struct pn533 *priv, u32 protocols, + struct device *parent) +{ + int rc; + + rc = pn532_i2c_nfc_alloc(priv, protocols, parent); + if (rc) + return rc; + + rc = nfc_register_device(priv->nfc_dev); + if (rc) + nfc_free_device(priv->nfc_dev); + + return rc; +} +EXPORT_SYMBOL_GPL(pn53x_register_nfc); + +void pn53x_unregister_nfc(struct pn533 *priv) +{ + nfc_unregister_device(priv->nfc_dev); + nfc_free_device(priv->nfc_dev); +} +EXPORT_SYMBOL_GPL(pn53x_unregister_nfc); MODULE_AUTHOR("Lauro Ramos Venancio <lauro.venancio@openbossa.org>"); MODULE_AUTHOR("Aloisio Almeida Jr <aloisio.almeida@openbossa.org>"); |
