diff options
-rw-r--r-- | include/net/nfc/nci.h | 4 | ||||
-rw-r--r-- | include/net/nfc/nci_core.h | 41 | ||||
-rw-r--r-- | net/nfc/nci/spi.c | 180 |
3 files changed, 70 insertions, 155 deletions
diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h index 88785e5c6b2c..e5aa5acafea0 100644 --- a/include/net/nfc/nci.h +++ b/include/net/nfc/nci.h @@ -166,6 +166,10 @@ #define NCI_GID_NFCEE_MGMT 0x2 #define NCI_GID_PROPRIETARY 0xf +/* ----- NCI over SPI head/crc(tail) room needed for outgoing frames ----- */ +#define NCI_SPI_HDR_LEN 4 +#define NCI_SPI_CRC_LEN 2 + /* ---- NCI Packet structures ---- */ #define NCI_CTRL_HDR_SIZE 3 #define NCI_DATA_HDR_SIZE 3 diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h index c08399621c8b..37ba06f2dfa9 100644 --- a/include/net/nfc/nci_core.h +++ b/include/net/nfc/nci_core.h @@ -207,16 +207,14 @@ int nci_to_errno(__u8 code); #define NCI_SPI_CRC_ENABLED 0x01 /* ----- NCI SPI structures ----- */ -struct nci_spi_dev; +struct nci_spi; struct nci_spi_ops { - int (*open)(struct nci_spi_dev *nsdev); - int (*close)(struct nci_spi_dev *nsdev); - void (*assert_int)(struct nci_spi_dev *nsdev); - void (*deassert_int)(struct nci_spi_dev *nsdev); + void (*assert_int)(struct nci_spi *nspi); + void (*deassert_int)(struct nci_spi *nspi); }; -struct nci_spi_dev { +struct nci_spi { struct nci_dev *ndev; struct spi_device *spi; struct nci_spi_ops *ops; @@ -227,31 +225,14 @@ struct nci_spi_dev { struct completion req_completion; u8 req_result; - - void *driver_data; }; -/* ----- NCI SPI Devices ----- */ -struct nci_spi_dev *nci_spi_allocate_device(struct spi_device *spi, - struct nci_spi_ops *ops, - u32 supported_protocols, - u32 supported_se, - u8 acknowledge_mode, - unsigned int delay); -void nci_spi_free_device(struct nci_spi_dev *nsdev); -int nci_spi_register_device(struct nci_spi_dev *nsdev); -void nci_spi_unregister_device(struct nci_spi_dev *nsdev); -int nci_spi_recv_frame(struct nci_spi_dev *nsdev); - -static inline void nci_spi_set_drvdata(struct nci_spi_dev *nsdev, - void *data) -{ - nsdev->driver_data = data; -} - -static inline void *nci_spi_get_drvdata(struct nci_spi_dev *nsdev) -{ - return nsdev->driver_data; -} +/* ----- NCI SPI ----- */ +struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi, + struct nci_spi_ops *ops, + u8 acknowledge_mode, unsigned int delay, + struct nci_dev *ndev); +int nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb); +int nci_spi_recv_frame(struct nci_spi *nspi); #endif /* __NCI_CORE_H */ diff --git a/net/nfc/nci/spi.c b/net/nfc/nci/spi.c index e66fda4d9ede..910dfd8015f4 100644 --- a/net/nfc/nci/spi.c +++ b/net/nfc/nci/spi.c @@ -24,8 +24,6 @@ #include <linux/nfc.h> #include <net/nfc/nci_core.h> -#define NCI_SPI_HDR_LEN 4 -#define NCI_SPI_CRC_LEN 2 #define NCI_SPI_ACK_SHIFT 6 #define NCI_SPI_MSB_PAYLOAD_MASK 0x3F @@ -41,21 +39,7 @@ #define CRC_INIT 0xFFFF -static int nci_spi_open(struct nci_dev *ndev) -{ - struct nci_spi_dev *nsdev = nci_get_drvdata(ndev); - - return nsdev->ops->open(nsdev); -} - -static int nci_spi_close(struct nci_dev *ndev) -{ - struct nci_spi_dev *nsdev = nci_get_drvdata(ndev); - - return nsdev->ops->close(nsdev); -} - -static int __nci_spi_send(struct nci_spi_dev *nsdev, struct sk_buff *skb) +static int __nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb) { struct spi_message m; struct spi_transfer t; @@ -63,32 +47,31 @@ static int __nci_spi_send(struct nci_spi_dev *nsdev, struct sk_buff *skb) t.tx_buf = skb->data; t.len = skb->len; t.cs_change = 0; - t.delay_usecs = nsdev->xfer_udelay; + t.delay_usecs = nspi->xfer_udelay; spi_message_init(&m); spi_message_add_tail(&t, &m); - return spi_sync(nsdev->spi, &m); + return spi_sync(nspi->spi, &m); } -static int nci_spi_send(struct nci_dev *ndev, struct sk_buff *skb) +int nci_spi_send(struct nci_spi *nspi, struct sk_buff *skb) { - struct nci_spi_dev *nsdev = nci_get_drvdata(ndev); unsigned int payload_len = skb->len; unsigned char *hdr; int ret; long completion_rc; - nsdev->ops->deassert_int(nsdev); + nspi->ops->deassert_int(nspi); /* add the NCI SPI header to the start of the buffer */ hdr = skb_push(skb, NCI_SPI_HDR_LEN); hdr[0] = NCI_SPI_DIRECT_WRITE; - hdr[1] = nsdev->acknowledge_mode; + hdr[1] = nspi->acknowledge_mode; hdr[2] = payload_len >> 8; hdr[3] = payload_len & 0xFF; - if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { + if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) { u16 crc; crc = crc_ccitt(CRC_INIT, skb->data, skb->len); @@ -96,123 +79,70 @@ static int nci_spi_send(struct nci_dev *ndev, struct sk_buff *skb) *skb_put(skb, 1) = crc & 0xFF; } - ret = __nci_spi_send(nsdev, skb); + ret = __nci_spi_send(nspi, skb); kfree_skb(skb); - nsdev->ops->assert_int(nsdev); + nspi->ops->assert_int(nspi); - if (ret != 0 || nsdev->acknowledge_mode == NCI_SPI_CRC_DISABLED) + if (ret != 0 || nspi->acknowledge_mode == NCI_SPI_CRC_DISABLED) goto done; - init_completion(&nsdev->req_completion); + init_completion(&nspi->req_completion); completion_rc = wait_for_completion_interruptible_timeout( - &nsdev->req_completion, + &nspi->req_completion, NCI_SPI_SEND_TIMEOUT); - if (completion_rc <= 0 || nsdev->req_result == ACKNOWLEDGE_NACK) + if (completion_rc <= 0 || nspi->req_result == ACKNOWLEDGE_NACK) ret = -EIO; done: return ret; } - -static struct nci_ops nci_spi_ops = { - .open = nci_spi_open, - .close = nci_spi_close, - .send = nci_spi_send, -}; +EXPORT_SYMBOL_GPL(nci_spi_send); /* ---- Interface to NCI SPI drivers ---- */ /** - * nci_spi_allocate_device - allocate a new nci spi device + * nci_spi_allocate_spi - allocate a new nci spi * * @spi: SPI device * @ops: device operations - * @supported_protocols: NFC protocols supported by the device - * @supported_se: NFC Secure Elements supported by the device - * @acknowledge_mode: Acknowledge mode used by the device + * @acknowledge_mode: Acknowledge mode used by the NFC device * @delay: delay between transactions in us + * @ndev: nci dev to send incoming nci frames to */ -struct nci_spi_dev *nci_spi_allocate_device(struct spi_device *spi, - struct nci_spi_ops *ops, - u32 supported_protocols, - u32 supported_se, - u8 acknowledge_mode, - unsigned int delay) +struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi, + struct nci_spi_ops *ops, + u8 acknowledge_mode, unsigned int delay, + struct nci_dev *ndev) { - struct nci_spi_dev *nsdev; - int tailroom = 0; - - if (!ops->open || !ops->close || !ops->assert_int || !ops->deassert_int) - return NULL; - - if (!supported_protocols) - return NULL; + struct nci_spi *nspi; - nsdev = devm_kzalloc(&spi->dev, sizeof(struct nci_spi_dev), GFP_KERNEL); - if (!nsdev) + if (!ops->assert_int || !ops->deassert_int) return NULL; - nsdev->ops = ops; - nsdev->acknowledge_mode = acknowledge_mode; - nsdev->xfer_udelay = delay; - - if (acknowledge_mode == NCI_SPI_CRC_ENABLED) - tailroom += NCI_SPI_CRC_LEN; - - nsdev->ndev = nci_allocate_device(&nci_spi_ops, supported_protocols, - NCI_SPI_HDR_LEN, tailroom); - if (!nsdev->ndev) + nspi = devm_kzalloc(&spi->dev, sizeof(struct nci_spi), GFP_KERNEL); + if (!nspi) return NULL; - nci_set_drvdata(nsdev->ndev, nsdev); - - return nsdev; -} -EXPORT_SYMBOL_GPL(nci_spi_allocate_device); - -/** - * nci_spi_free_device - deallocate nci spi device - * - * @nsdev: The nci spi device to deallocate - */ -void nci_spi_free_device(struct nci_spi_dev *nsdev) -{ - nci_free_device(nsdev->ndev); -} -EXPORT_SYMBOL_GPL(nci_spi_free_device); + nspi->ops = ops; + nspi->acknowledge_mode = acknowledge_mode; + nspi->xfer_udelay = delay; -/** - * nci_spi_register_device - register a nci spi device in the nfc subsystem - * - * @pdev: The nci spi device to register - */ -int nci_spi_register_device(struct nci_spi_dev *nsdev) -{ - return nci_register_device(nsdev->ndev); -} -EXPORT_SYMBOL_GPL(nci_spi_register_device); + nspi->ndev = ndev; -/** - * nci_spi_unregister_device - unregister a nci spi device in the nfc subsystem - * - * @dev: The nci spi device to unregister - */ -void nci_spi_unregister_device(struct nci_spi_dev *nsdev) -{ - nci_unregister_device(nsdev->ndev); + return nspi; } -EXPORT_SYMBOL_GPL(nci_spi_unregister_device); +EXPORT_SYMBOL_GPL(nci_spi_allocate_spi); -static int send_acknowledge(struct nci_spi_dev *nsdev, u8 acknowledge) +static int send_acknowledge(struct nci_spi *nspi, u8 acknowledge) { struct sk_buff *skb; unsigned char *hdr; u16 crc; int ret; - skb = nci_skb_alloc(nsdev->ndev, 0, GFP_KERNEL); + skb = nci_skb_alloc(nspi->ndev, 0, GFP_KERNEL); /* add the NCI SPI header to the start of the buffer */ hdr = skb_push(skb, NCI_SPI_HDR_LEN); @@ -225,14 +155,14 @@ static int send_acknowledge(struct nci_spi_dev *nsdev, u8 acknowledge) *skb_put(skb, 1) = crc >> 8; *skb_put(skb, 1) = crc & 0xFF; - ret = __nci_spi_send(nsdev, skb); + ret = __nci_spi_send(nspi, skb); kfree_skb(skb); return ret; } -static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *nsdev) +static struct sk_buff *__nci_spi_recv_frame(struct nci_spi *nspi) { struct sk_buff *skb; struct spi_message m; @@ -243,7 +173,7 @@ static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *nsdev) spi_message_init(&m); req[0] = NCI_SPI_DIRECT_READ; - req[1] = nsdev->acknowledge_mode; + req[1] = nspi->acknowledge_mode; tx.tx_buf = req; tx.len = 2; tx.cs_change = 0; @@ -252,18 +182,18 @@ static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *nsdev) rx.len = 2; rx.cs_change = 1; spi_message_add_tail(&rx, &m); - ret = spi_sync(nsdev->spi, &m); + ret = spi_sync(nspi->spi, &m); if (ret) return NULL; - if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) + if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) rx_len = ((resp_hdr[0] & NCI_SPI_MSB_PAYLOAD_MASK) << 8) + resp_hdr[1] + NCI_SPI_CRC_LEN; else rx_len = (resp_hdr[0] << 8) | resp_hdr[1]; - skb = nci_skb_alloc(nsdev->ndev, rx_len, GFP_KERNEL); + skb = nci_skb_alloc(nspi->ndev, rx_len, GFP_KERNEL); if (!skb) return NULL; @@ -271,14 +201,14 @@ static struct sk_buff *__nci_spi_recv_frame(struct nci_spi_dev *nsdev) rx.rx_buf = skb_put(skb, rx_len); rx.len = rx_len; rx.cs_change = 0; - rx.delay_usecs = nsdev->xfer_udelay; + rx.delay_usecs = nspi->xfer_udelay; spi_message_add_tail(&rx, &m); - ret = spi_sync(nsdev->spi, &m); + ret = spi_sync(nspi->spi, &m); if (ret) goto receive_error; - if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { + if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) { *skb_push(skb, 1) = resp_hdr[1]; *skb_push(skb, 1) = resp_hdr[0]; } @@ -320,7 +250,7 @@ static u8 nci_spi_get_ack(struct sk_buff *skb) /** * nci_spi_recv_frame - receive frame from NCI SPI drivers * - * @nsdev: The nci spi device + * @nspi: The nci spi * Context: can sleep * * This call may only be used from a context that may sleep. The sleep @@ -328,32 +258,32 @@ static u8 nci_spi_get_ack(struct sk_buff *skb) * * It returns zero on success, else a negative error code. */ -int nci_spi_recv_frame(struct nci_spi_dev *nsdev) +int nci_spi_recv_frame(struct nci_spi *nspi) { struct sk_buff *skb; int ret = 0; - nsdev->ops->deassert_int(nsdev); + nspi->ops->deassert_int(nspi); /* Retrieve frame from SPI */ - skb = __nci_spi_recv_frame(nsdev); + skb = __nci_spi_recv_frame(nspi); if (!skb) { ret = -EIO; goto done; } - if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) { + if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) { if (!nci_spi_check_crc(skb)) { - send_acknowledge(nsdev, ACKNOWLEDGE_NACK); + send_acknowledge(nspi, ACKNOWLEDGE_NACK); goto done; } /* In case of acknowledged mode: if ACK or NACK received, * unblock completion of latest frame sent. */ - nsdev->req_result = nci_spi_get_ack(skb); - if (nsdev->req_result) - complete(&nsdev->req_completion); + nspi->req_result = nci_spi_get_ack(skb); + if (nspi->req_result) + complete(&nspi->req_completion); } /* If there is no payload (ACK/NACK only frame), @@ -364,14 +294,14 @@ int nci_spi_recv_frame(struct nci_spi_dev *nsdev) goto done; } - if (nsdev->acknowledge_mode == NCI_SPI_CRC_ENABLED) - send_acknowledge(nsdev, ACKNOWLEDGE_ACK); + if (nspi->acknowledge_mode == NCI_SPI_CRC_ENABLED) + send_acknowledge(nspi, ACKNOWLEDGE_ACK); /* Forward skb to NCI core layer */ - ret = nci_recv_frame(nsdev->ndev, skb); + ret = nci_recv_frame(nspi->ndev, skb); done: - nsdev->ops->assert_int(nsdev); + nspi->ops->assert_int(nspi); return ret; } |