From 12b756e97ad28ca5d507b92b23e7fb66d241be78 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 27 Mar 2013 17:08:21 +0100 Subject: [PATCH] spi: remove spi_posix.c, exotic platform implementations will have to be done in their respective contrib subdir --- libnfc/buses/spi.c | 285 ++++++++++++++++++++++++++++++++++-- libnfc/buses/spi_posix.c | 305 --------------------------------------- 2 files changed, 276 insertions(+), 314 deletions(-) delete mode 100644 libnfc/buses/spi_posix.c diff --git a/libnfc/buses/spi.c b/libnfc/buses/spi.c index 870f9ae..9d3c38a 100644 --- a/libnfc/buses/spi.c +++ b/libnfc/buses/spi.c @@ -27,7 +27,7 @@ /** * @file spi.c - * @brief SPI driver wrapper + * @brief SPI driver */ #ifdef HAVE_CONFIG_H @@ -36,14 +36,281 @@ #include "spi.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include "nfc-internal.h" -// Test if we are dealing with unix operating systems -#ifndef _WIN32 -// The POSIX SPI port implementation -# include "spi_posix.c" -#else -// The windows SPI port implementation -# error "Not implemented" -#endif /* _WIN32 */ +#define LOG_GROUP NFC_LOG_GROUP_COM +#define LOG_CATEGORY "libnfc.bus.spi" + +# if defined(__APPLE__) +const char *spi_ports_device_radix[] = { "spidev", NULL }; +# elif defined (__FreeBSD__) || defined (__OpenBSD__) +const char *spi_ports_device_radix[] = { "spidev", NULL }; +# elif defined (__linux__) +const char *spi_ports_device_radix[] = { "spidev", NULL }; +# else +# error "Can't determine spi port string for your system" +# endif + + +struct spi_port_unix { + int fd; // Serial port file descriptor + //~ struct termios termios_backup; // Terminal info before using the port + //~ struct termios termios_new; // Terminal info during the transaction +}; + +#define SPI_DATA( X ) ((struct spi_port_unix *) X) + + +spi_port +spi_open(const char *pcPortName) +{ + struct spi_port_unix *sp = malloc(sizeof(struct spi_port_unix)); + + if (sp == 0) + return INVALID_SPI_PORT; + + sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NONBLOCK); + if (sp->fd == -1) { + spi_close(sp); + return INVALID_SPI_PORT; + } + + + return sp; +} + + + +void +spi_set_speed(spi_port sp, const uint32_t uiPortSpeed) +{ + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "SPI port speed requested to be set to %d Hz.", uiPortSpeed); + int ret; + ret = ioctl(SPI_DATA(sp)->fd, SPI_IOC_WR_MAX_SPEED_HZ, &uiPortSpeed); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "ret %d", ret); + + if (ret == -1) log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Error setting SPI speed."); + +} + +void +spi_set_mode(spi_port sp, const uint32_t uiPortMode) +{ + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "SPI port mode requested to be set to %d.", uiPortMode); + int ret; + ret = ioctl(SPI_DATA(sp)->fd, SPI_IOC_WR_MODE, &uiPortMode); + + if (ret == -1) log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Error setting SPI mode."); + +} + +uint32_t +spi_get_speed(spi_port sp) +{ + uint32_t uiPortSpeed = 0; + + int ret; + ret = ioctl(SPI_DATA(sp)->fd, SPI_IOC_RD_MAX_SPEED_HZ, &uiPortSpeed); + + if (ret == -1) log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Error reading SPI speed."); + + return uiPortSpeed; +} + + +void +spi_close(const spi_port sp) +{ + close(SPI_DATA(sp)->fd); + free(sp); +} + + +/** + * @brief Perform bit reversal on one byte \a x + * + * @return reversed byte + */ + +static uint8_t +bit_reversal(const uint8_t x) +{ + uint8_t ret = x; + ret = (((ret & 0xaa) >> 1) | ((ret & 0x55) << 1)); + ret = (((ret & 0xcc) >> 2) | ((ret & 0x33) << 2)); + ret = (((ret & 0xf0) >> 4) | ((ret & 0x0f) << 4)); + return ret; +} + + + + + +/** + * @brief Send \a pbtTx content to SPI then receive data from SPI and copy data to \a pbtRx. CS line stays active between transfers as well as during transfers. + * + * @return 0 on success, otherwise a driver error is returned + */ +int +spi_send_receive(spi_port sp, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, bool lsb_first) +{ + size_t transfers = 0; + struct spi_ioc_transfer tr[2]; + + + uint8_t *pbtTxLSB = 0; + + if (szTx) { + LOG_HEX(LOG_GROUP, "TX", pbtTx, szTx); + if (lsb_first) { + pbtTxLSB = malloc(szTx * sizeof(uint8_t)); + if (!pbtTxLSB) { + return NFC_ESOFT; + } + + size_t i; + for (i = 0; i < szTx; ++i) { + pbtTxLSB[i] = bit_reversal(pbtTx[i]); + } + + pbtTx = pbtTxLSB; + } + + struct spi_ioc_transfer tr_send = { + .tx_buf = (unsigned long) pbtTx, + .rx_buf = 0, + .len = szTx , + .delay_usecs = 0, + .speed_hz = 0, + .bits_per_word = 0, + }; + tr[transfers] = tr_send; + + ++transfers; + } + + if (szRx) { + struct spi_ioc_transfer tr_receive = { + .tx_buf = 0, + .rx_buf = (unsigned long) pbtRx, + .len = szRx, + .delay_usecs = 0, + .speed_hz = 0, + .bits_per_word = 0, + }; + tr[transfers] = tr_receive; + ++transfers; + } + + + + if (transfers) { + int ret = ioctl(SPI_DATA(sp)->fd, SPI_IOC_MESSAGE(transfers), tr); + if (szTx && lsb_first) { + free(pbtTxLSB); + } + + if (ret != (int)(szRx + szTx)) { + return NFC_EIO; + } + + // Reverse received bytes if needed + if (szRx) { + if (lsb_first) { + size_t i; + for (i = 0; i < szRx; ++i) { + pbtRx[i] = bit_reversal(pbtRx[i]); + } + } + + LOG_HEX(LOG_GROUP, "RX", pbtRx, szRx); + } + } + + + return NFC_SUCCESS; +} + + +/** + * @brief Receive data from SPI and copy data to \a pbtRx + * + * @return 0 on success, otherwise driver error code + */ +int +spi_receive(spi_port sp, uint8_t *pbtRx, const size_t szRx, bool lsb_first) +{ + return spi_send_receive(sp, 0, 0, pbtRx, szRx, lsb_first); +} + + +/** + * @brief Send \a pbtTx content to SPI + * + * @return 0 on success, otherwise a driver error is returned + */ +int +spi_send(spi_port sp, const uint8_t *pbtTx, const size_t szTx, bool lsb_first) +{ + return spi_send_receive(sp, pbtTx, szTx, 0, 0, lsb_first); +} + + +char ** +spi_list_ports(void) +{ + char **res = malloc(sizeof(char *)); + size_t szRes = 1; + + res[0] = NULL; + + DIR *pdDir = opendir("/dev"); + struct dirent *pdDirEnt; + struct dirent entry; + struct dirent *result; + while ((readdir_r(pdDir, &entry, &result) == 0) && (result != NULL)) { + pdDirEnt = &entry; +#if !defined(__APPLE__) + if (!isdigit(pdDirEnt->d_name[strlen(pdDirEnt->d_name) - 1])) + continue; +#endif + const char **p = spi_ports_device_radix; + while (*p) { + if (!strncmp(pdDirEnt->d_name, *p, strlen(*p))) { + char **res2 = realloc(res, (szRes + 1) * sizeof(char *)); + if (!res2) + goto oom; + + res = res2; + if (!(res[szRes - 1] = malloc(6 + strlen(pdDirEnt->d_name)))) + goto oom; + + sprintf(res[szRes - 1], "/dev/%s", pdDirEnt->d_name); + + szRes++; + res[szRes - 1] = NULL; + } + p++; + } + } +oom: + closedir(pdDir); + + return res; +} diff --git a/libnfc/buses/spi_posix.c b/libnfc/buses/spi_posix.c deleted file mode 100644 index e862bdf..0000000 --- a/libnfc/buses/spi_posix.c +++ /dev/null @@ -1,305 +0,0 @@ -/*- - * Public platform independent Near Field Communication (NFC) library - * - * Copyright (C) 2013 Evgeny Boger - * Copyright (C) 2009, 2010, 2011 Roel Verdult - * Copyright (C) 2009, 2010, 2011, 2012 Romuald Conty - * Copyright (C) 2011 Romain Tarti?re - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 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 Lesser General Public License - * along with this program. If not, see - * - */ - -/** - * @file spi_posix.c - * @brief POSIX SPI driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nfc-internal.h" - -#define LOG_GROUP NFC_LOG_GROUP_COM -#define LOG_CATEGORY "libnfc.bus.spi" - -# if defined(__APPLE__) -const char *spi_ports_device_radix[] = { "spidev", NULL }; -# elif defined (__FreeBSD__) || defined (__OpenBSD__) -const char *spi_ports_device_radix[] = { "spidev", NULL }; -# elif defined (__linux__) -const char *spi_ports_device_radix[] = { "spidev", NULL }; -# else -# error "Can't determine spi port string for your system" -# endif - - -struct spi_port_unix { - int fd; // Serial port file descriptor - //~ struct termios termios_backup; // Terminal info before using the port - //~ struct termios termios_new; // Terminal info during the transaction -}; - -#define SPI_DATA( X ) ((struct spi_port_unix *) X) - - -spi_port -spi_open(const char *pcPortName) -{ - struct spi_port_unix *sp = malloc(sizeof(struct spi_port_unix)); - - if (sp == 0) - return INVALID_SPI_PORT; - - sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NONBLOCK); - if (sp->fd == -1) { - spi_close(sp); - return INVALID_SPI_PORT; - } - - - return sp; -} - - - -void -spi_set_speed(spi_port sp, const uint32_t uiPortSpeed) -{ - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "SPI port speed requested to be set to %d Hz.", uiPortSpeed); - int ret; - ret = ioctl(SPI_DATA(sp)->fd, SPI_IOC_WR_MAX_SPEED_HZ, &uiPortSpeed); - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "ret %d", ret); - - if (ret == -1) log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Error setting SPI speed."); - -} - -void -spi_set_mode(spi_port sp, const uint32_t uiPortMode) -{ - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "SPI port mode requested to be set to %d.", uiPortMode); - int ret; - ret = ioctl(SPI_DATA(sp)->fd, SPI_IOC_WR_MODE, &uiPortMode); - - if (ret == -1) log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Error setting SPI mode."); - -} - -uint32_t -spi_get_speed(spi_port sp) -{ - uint32_t uiPortSpeed = 0; - - int ret; - ret = ioctl(SPI_DATA(sp)->fd, SPI_IOC_RD_MAX_SPEED_HZ, &uiPortSpeed); - - if (ret == -1) log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Error reading SPI speed."); - - return uiPortSpeed; -} - - -void -spi_close(const spi_port sp) -{ - close(SPI_DATA(sp)->fd); - free(sp); -} - - -/** - * @brief Perform bit reversal on one byte \a x - * - * @return reversed byte - */ - -static uint8_t -bit_reversal(const uint8_t x) -{ - uint8_t ret = x; - ret = (((ret & 0xaa) >> 1) | ((ret & 0x55) << 1)); - ret = (((ret & 0xcc) >> 2) | ((ret & 0x33) << 2)); - ret = (((ret & 0xf0) >> 4) | ((ret & 0x0f) << 4)); - return ret; -} - - - - - -/** - * @brief Send \a pbtTx content to SPI then receive data from SPI and copy data to \a pbtRx. CS line stays active between transfers as well as during transfers. - * - * @return 0 on success, otherwise a driver error is returned - */ -int -spi_send_receive(spi_port sp, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, bool lsb_first) -{ - size_t transfers = 0; - struct spi_ioc_transfer tr[2]; - - - uint8_t *pbtTxLSB = 0; - - if (szTx) { - LOG_HEX(LOG_GROUP, "TX", pbtTx, szTx); - if (lsb_first) { - pbtTxLSB = malloc(szTx * sizeof(uint8_t)); - if (!pbtTxLSB) { - return NFC_ESOFT; - } - - size_t i; - for (i = 0; i < szTx; ++i) { - pbtTxLSB[i] = bit_reversal(pbtTx[i]); - } - - pbtTx = pbtTxLSB; - } - - struct spi_ioc_transfer tr_send = { - .tx_buf = (unsigned long) pbtTx, - .rx_buf = 0, - .len = szTx , - .delay_usecs = 0, - .speed_hz = 0, - .bits_per_word = 0, - }; - tr[transfers] = tr_send; - - ++transfers; - } - - if (szRx) { - struct spi_ioc_transfer tr_receive = { - .tx_buf = 0, - .rx_buf = (unsigned long) pbtRx, - .len = szRx, - .delay_usecs = 0, - .speed_hz = 0, - .bits_per_word = 0, - }; - tr[transfers] = tr_receive; - ++transfers; - } - - - - if (transfers) { - int ret = ioctl(SPI_DATA(sp)->fd, SPI_IOC_MESSAGE(transfers), tr); - if (szTx && lsb_first) { - free(pbtTxLSB); - } - - if (ret != (int)(szRx + szTx)) { - return NFC_EIO; - } - - // Reverse received bytes if needed - if (szRx) { - if (lsb_first) { - size_t i; - for (i = 0; i < szRx; ++i) { - pbtRx[i] = bit_reversal(pbtRx[i]); - } - } - - LOG_HEX(LOG_GROUP, "RX", pbtRx, szRx); - } - } - - - return NFC_SUCCESS; -} - - -/** - * @brief Receive data from SPI and copy data to \a pbtRx - * - * @return 0 on success, otherwise driver error code - */ -int -spi_receive(spi_port sp, uint8_t *pbtRx, const size_t szRx, bool lsb_first) -{ - return spi_send_receive(sp, 0, 0, pbtRx, szRx, lsb_first); -} - - -/** - * @brief Send \a pbtTx content to SPI - * - * @return 0 on success, otherwise a driver error is returned - */ -int -spi_send(spi_port sp, const uint8_t *pbtTx, const size_t szTx, bool lsb_first) -{ - return spi_send_receive(sp, pbtTx, szTx, 0, 0, lsb_first); -} - - -char ** -spi_list_ports(void) -{ - char **res = malloc(sizeof(char *)); - size_t szRes = 1; - - res[0] = NULL; - - DIR *pdDir = opendir("/dev"); - struct dirent *pdDirEnt; - struct dirent entry; - struct dirent *result; - while ((readdir_r(pdDir, &entry, &result) == 0) && (result != NULL)) { - pdDirEnt = &entry; -#if !defined(__APPLE__) - if (!isdigit(pdDirEnt->d_name[strlen(pdDirEnt->d_name) - 1])) - continue; -#endif - const char **p = spi_ports_device_radix; - while (*p) { - if (!strncmp(pdDirEnt->d_name, *p, strlen(*p))) { - char **res2 = realloc(res, (szRes + 1) * sizeof(char *)); - if (!res2) - goto oom; - - res = res2; - if (!(res[szRes - 1] = malloc(6 + strlen(pdDirEnt->d_name)))) - goto oom; - - sprintf(res[szRes - 1], "/dev/%s", pdDirEnt->d_name); - - szRes++; - res[szRes - 1] = NULL; - } - p++; - } - } -oom: - closedir(pdDir); - - return res; -}