static int pn533_autopoll_complete()

in pn533/pn533.c [1395:1488]


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;
		} else if (rc < 0) {
			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;
}