in trf7970a.c [1459:1561]
static int trf7970a_send_cmd(struct nfc_digital_dev *ddev,
struct sk_buff *skb, u16 timeout,
nfc_digital_cmd_complete_t cb, void *arg)
{
struct trf7970a *trf = nfc_digital_get_drvdata(ddev);
u8 prefix[5];
unsigned int len;
int ret;
u8 status;
dev_dbg(trf->dev, "New request - state: %d, timeout: %d ms, len: %d\n",
trf->state, timeout, skb->len);
if (skb->len > TRF7970A_TX_MAX)
return -EINVAL;
mutex_lock(&trf->lock);
if ((trf->state != TRF7970A_ST_IDLE) &&
(trf->state != TRF7970A_ST_IDLE_RX_BLOCKED)) {
dev_err(trf->dev, "%s - Bogus state: %d\n", __func__,
trf->state);
ret = -EIO;
goto out_err;
}
if (trf->aborting) {
dev_dbg(trf->dev, "Abort process complete\n");
trf->aborting = false;
ret = -ECANCELED;
goto out_err;
}
if (timeout) {
trf->rx_skb = nfc_alloc_recv_skb(TRF7970A_RX_SKB_ALLOC_SIZE,
GFP_KERNEL);
if (!trf->rx_skb) {
dev_dbg(trf->dev, "Can't alloc rx_skb\n");
ret = -ENOMEM;
goto out_err;
}
}
if (trf->state == TRF7970A_ST_IDLE_RX_BLOCKED) {
ret = trf7970a_cmd(trf, TRF7970A_CMD_ENABLE_RX);
if (ret)
goto out_err;
trf->state = TRF7970A_ST_IDLE;
}
if (trf->is_initiator) {
ret = trf7970a_per_cmd_config(trf, skb);
if (ret)
goto out_err;
}
trf->ddev = ddev;
trf->tx_skb = skb;
trf->cb = cb;
trf->cb_arg = arg;
trf->timeout = timeout;
trf->ignore_timeout = false;
len = skb->len;
/* TX data must be prefixed with a FIFO reset cmd, a cmd that depends
* on what the current framing is, the address of the TX length byte 1
* register (0x1d), and the 2 byte length of the data to be transmitted.
* That totals 5 bytes.
*/
prefix[0] = TRF7970A_CMD_BIT_CTRL |
TRF7970A_CMD_BIT_OPCODE(TRF7970A_CMD_FIFO_RESET);
prefix[1] = TRF7970A_CMD_BIT_CTRL |
TRF7970A_CMD_BIT_OPCODE(trf->tx_cmd);
prefix[2] = TRF7970A_CMD_BIT_CONTINUOUS | TRF7970A_TX_LENGTH_BYTE1;
if (trf->framing == NFC_DIGITAL_FRAMING_NFCA_SHORT) {
prefix[3] = 0x00;
prefix[4] = 0x0f; /* 7 bits */
} else {
prefix[3] = (len & 0xf00) >> 4;
prefix[3] |= ((len & 0xf0) >> 4);
prefix[4] = ((len & 0x0f) << 4);
}
len = min_t(int, skb->len, TRF7970A_FIFO_SIZE);
/* Clear possible spurious interrupt */
ret = trf7970a_read_irqstatus(trf, &status);
if (ret)
goto out_err;
ret = trf7970a_transmit(trf, skb, len, prefix, sizeof(prefix));
if (ret) {
kfree_skb(trf->rx_skb);
trf->rx_skb = NULL;
}
out_err:
mutex_unlock(&trf->lock);
return ret;
}