From 03ada50f4e3993fc9e3d4c17e952f12bb67d7d98 Mon Sep 17 00:00:00 2001 From: guowenxue <guowenxue@gmail.com> Date: Tue, 27 Aug 2019 00:50:13 +0800 Subject: [PATCH] add AT91 GPIO AND spi library --- program/lylib/at91_sysGpio.c | 210 +++++++++++++++ program/lylib/at91_sysGpioDef.h | 221 +++++++++++++++ program/lylib/spidev.c | 255 ++++++++++++++++++ program/lylib/at91_sysGpio.h | 62 ++++ program/lylib/spidev.h | 75 +++++ 5 files changed, 823 insertions(+), 0 deletions(-) diff --git a/program/lylib/at91_sysGpio.c b/program/lylib/at91_sysGpio.c new file mode 100644 index 0000000..add9038 --- /dev/null +++ b/program/lylib/at91_sysGpio.c @@ -0,0 +1,210 @@ +/********************************************************************************* + * Copyright: (C) 2019 LingYun IoT System Studio + * All rights reserved. + * + * Filename: at91_sysGpio.c + * Description: This file si GPIO API operatore on /sys/class/gpio/xxx + * + * Version: 1.0.0(2019年08月26日) + * Author: Guo Wenxue <guowenxue@gmail.com> + * ChangeLog: 1, Release initial version on "2019年08月26日 22时28分19秒" + * + ********************************************************************************/ + +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> + +#include "at91_sysGpio.h" + + +/* export $port in /sys/class/gpio/export */ +int gpio_export(const char *port) +{ + char fpath[SYSFILE_LEN]; + FILE *fp; + int pin; + + if(!port) + { + gpio_print("invalid input arguments\n"); + return -1; + } + + snprintf(fpath, SYSFILE_LEN, "%s/%s", SYSGPIO_PATH, port); + + /* GPIO port already export */ + if( !access(fpath, F_OK) ) + { + gpio_print("%s already export\n", port); + return 0; + } + + if( !(fp=fopen(SYSGPIO_EXPORT_PATH, "w")) ) + { + gpio_print("open '%s' failure: %s\n", SYSGPIO_EXPORT_PATH, strerror(errno)); + return -2; + } + + pin = at91_port2pin(port); + fprintf(fp, "%d", pin); + + fclose(fp); + + return 0; +} + + +/* unexport $port in /sys/class/gpio/unexport */ +int gpio_unexport(const char *port) +{ + char fpath[SYSFILE_LEN]; + FILE *fp; + int pin; + + if(!port) + { + gpio_print("invalid input arguments\n"); + return -1; + } + + snprintf(fpath, SYSFILE_LEN, "%s/%s", SYSGPIO_PATH, port); + + /* GPIO port not export */ + if( access(fpath, F_OK) ) + { + gpio_print("%s not export\n", port); + return 0; + } + + if( !(fp=fopen(SYSGPIO_UNEXPORT_PATH, "w")) ) + { + gpio_print("open '%s' failure: %s\n", SYSGPIO_EXPORT_PATH, strerror(errno)); + return -2; + } + + pin = at91_port2pin(port); + fprintf(fp, "%d", pin); + + fclose(fp); + + return 0; +} + + +/* configure $port direction as $mode */ +int gpio_config(const char *port, const char *mode) +{ + char fpath[SYSFILE_LEN]; + FILE *fp; + int size; + + if(!port) + { + gpio_print("invalid input arguments\n"); + return 0; + } + + snprintf(fpath, SYSFILE_LEN, "%s/%s", SYSGPIO_PATH, port); + + if( access(fpath, F_OK) ) /* GPIO port not export */ + { + if( gpio_export(port) < 0 ) + return -1; + } + + size = SYSFILE_LEN-strlen(fpath); + strncat(fpath, "/direction", size); + if( !(fp=fopen(fpath, "w")) ) + { + gpio_print("open '%s' failure: %s\n", fpath, strerror(errno)); + return -1; + } + + fputs(mode, fp); + + fclose(fp); + + return 0; +} + + + +/* write $value into GPIO $port */ +int gpio_write(const char *port, const char *value) +{ + char fpath[SYSFILE_LEN]; + FILE *fp; + int size; + + if(!port) + { + gpio_print("invalid input arguments\n"); + return 0; + } + + snprintf(fpath, SYSFILE_LEN, "%s/%s", SYSGPIO_PATH, port); + + if( access(fpath, F_OK) ) /* GPIO port not export */ + { + if( gpio_export(port) < 0 ) + return -1; + } + + size = SYSFILE_LEN-strlen(fpath); + strncat(fpath, "/value", size); + if( !(fp=fopen(fpath, "w")) ) + { + gpio_print("open '%s' failure: %s\n", fpath, strerror(errno)); + return -1; + } + + fputs(value, fp); + + fclose(fp); + + return 0; +} + + +/* read gpio value from $port */ +int gpio_read(const char *port) +{ + char fpath[SYSFILE_LEN]; + FILE *fp; + int size; + char v_str[32]; + + if(!port) + { + gpio_print("invalid input arguments\n"); + return 0; + } + + snprintf(fpath, SYSFILE_LEN, "%s/%s", SYSGPIO_PATH, port); + + if( access(fpath, F_OK) ) /* GPIO port not export */ + { + return -1; + } + + size = SYSFILE_LEN-strlen(fpath); + strncat(fpath, "/value", size); + if( !(fp=fopen(fpath, "r")) ) + { + gpio_print("open '%s' failure: %s\n", fpath, strerror(errno)); + return -1; + } + + memset(v_str, 0, sizeof(v_str)); + fgets(v_str, sizeof(v_str), fp); + + fclose(fp); + + return atoi(v_str); +} + diff --git a/program/lylib/at91_sysGpio.h b/program/lylib/at91_sysGpio.h new file mode 100644 index 0000000..556750f --- /dev/null +++ b/program/lylib/at91_sysGpio.h @@ -0,0 +1,62 @@ +/********************************************************************************* + * Copyright: (C) 2019 LingYun IoT System Studio + * All rights reserved. + * + * Filename: at91_sysGpio.h + * Description: This file si GPIO API operatore on /sys/class/gpio/xxx + * + * Version: 1.0.0(2019年08月26日) + * Author: Guo Wenxue <guowenxue@gmail.com> + * ChangeLog: 1, Release initial version on "2019年08月26日 22时28分19秒" + * + ********************************************************************************/ + +#ifndef _AT91_SYSGPIO_H_ +#define _AT91_SYSGPIO_H_ + +#include "at91_sysGpioDef.h" + +#define SYSFILE_LEN 64 + +#define SYSGPIO_PATH "/sys/class/gpio/" + +#define SYSGPIO_EXPORT_PATH SYSGPIO_PATH"export" +#define SYSGPIO_UNEXPORT_PATH SYSGPIO_PATH"unexport" + +//#define GPIO_DEBUG_PRINT + +#ifdef GPIO_DEBUG_PRINT +#define gpio_print(format,args...) printf(format, ##args) +#else +#define gpio_print(format,args...) do{} while(0); +#endif + + +/* export $port in /sys/class/gpio/export */ +extern int gpio_export(const char *port); + + +/* unexport $port in /sys/class/gpio/unexport */ +extern int gpio_unexport(const char *port); + + +#define M_IN "in" /* set GPIO as input mode */ +#define M_OUT "out" /* set GPIO as output mode */ +#define M_HIGH "high" /* set GPIO as output mode and value be high<1> */ +#define M_LOW "low" /* set GPIO as output mode and value be low<0> */ +/* configure $port direction as $mode */ +extern int gpio_config(const char *port, const char *mode); + + +#define V_HIGH "1" +#define V_LOW "0" +/* write $value into GPIO $port */ +extern int gpio_write(const char *port, const char *value); + + +/* read gpio value from $port */ +extern int gpio_read(const char *port); + +#endif /* ----- #ifndef _AT91_SYSGPIO_H_ ----- */ + + diff --git a/program/lylib/at91_sysGpioDef.h b/program/lylib/at91_sysGpioDef.h new file mode 100644 index 0000000..a4f827d --- /dev/null +++ b/program/lylib/at91_sysGpioDef.h @@ -0,0 +1,221 @@ +/******************************************************************************** + * Copyright: (C) 2019 LingYun IoT System Studio + * All rights reserved. + * + * Filename: at91_sysGpioDef.h + * Description: This head file + * + * Version: 1.0.0(2019年08月26日) + * Author: Guo Wenxue <guowenxue@gmail.com> + * ChangeLog: 1, Release initial version on "2019年08月26日 21时46分02秒" + * + ********************************************************************************/ + +#ifndef _AT91_SYSGPIODEF_H_ +#define _AT91_SYSGPIODEF_H_ + +#include <ctype.h> +#include <stdlib.h> + +#define PA(x) "pioA"#x +#define PB(x) "pioB"#x +#define PC(x) "pioC"#x +#define PD(x) "pioD"#x +#define PE(x) "pioE"#x + +/* SAMA5D44 devided all GPIOs into 5 groups(PA,PB,PC,PD,PE), and each group control 32 Pins + * + * This macro used convert PAx,PBx...,PEx to Pin number: 0~158 + * s should be: PA0-PA31, PB0-PB31, PC0-PC31, PD0-PD31, PE0-PE30(158) + */ +#define at91_port2pin(p) ((tolower(p[3])-'a')*32 + atoi(p+4) ) + + +/*+-----------------------------------------------------+ + *| GPIO PortA: PA0~PA31 defined as "pioA0"-"pioA31" | + *+-----------------------------------------------------+*/ + +#define PA0 PA(0) +#define PA1 PA(1) +#define PA2 PA(2) +#define PA3 PA(3) +#define PA4 PA(4) +#define PA5 PA(5) +#define PA6 PA(6) +#define PA7 PA(7) +#define PA8 PA(8) +#define PA9 PA(9) +#define PA10 PA(10) +#define PA11 PA(11) +#define PA12 PA(12) +#define PA13 PA(13) +#define PA14 PA(14) +#define PA15 PA(15) +#define PA16 PA(16) +#define PA17 PA(17) +#define PA18 PA(18) +#define PA19 PA(19) +#define PA20 PA(20) +#define PA21 PA(21) +#define PA22 PA(22) +#define PA23 PA(23) +#define PA24 PA(24) +#define PA25 PA(25) +#define PA26 PA(26) +#define PA27 PA(27) +#define PA28 PA(28) +#define PA29 PA(29) +#define PA30 PA(30) +#define PA31 PA(31) + + +/*+-----------------------------------------------------+ + *| GPIO PortB: PB0~PB31 defined as "pioB0"-"pioB31" | + *+-----------------------------------------------------+*/ + +#define PB0 PB(0) +#define PB1 PB(1) +#define PB2 PB(2) +#define PB3 PB(3) +#define PB4 PB(4) +#define PB5 PB(5) +#define PB6 PB(6) +#define PB7 PB(7) +#define PB8 PB(8) +#define PB9 PB(9) +#define PB10 PB(10) +#define PB11 PB(11) +#define PB12 PB(12) +#define PB13 PB(13) +#define PB14 PB(14) +#define PB15 PB(15) +#define PB16 PB(16) +#define PB17 PB(17) +#define PB18 PB(18) +#define PB19 PB(19) +#define PB20 PB(20) +#define PB21 PB(21) +#define PB22 PB(22) +#define PB23 PB(23) +#define PB24 PB(24) +#define PB25 PB(25) +#define PB26 PB(26) +#define PB27 PB(27) +#define PB28 PB(28) +#define PB29 PB(29) +#define PB30 PB(30) +#define PB31 PB(31) + +/*+-----------------------------------------------------+ + *| GPIO PortC: PC0~PC31 defined as "pioC0"-"pioC31" | + *+-----------------------------------------------------+*/ + +#define PC0 PC(0) +#define PC1 PC(1) +#define PC2 PC(2) +#define PC3 PC(3) +#define PC4 PC(4) +#define PC5 PC(5) +#define PC6 PC(6) +#define PC7 PC(7) +#define PC8 PC(8) +#define PC9 PC(9) +#define PC10 PC(10) +#define PC11 PC(11) +#define PC12 PC(12) +#define PC13 PC(13) +#define PC14 PC(14) +#define PC15 PC(15) +#define PC16 PC(16) +#define PC17 PC(17) +#define PC18 PC(18) +#define PC19 PC(19) +#define PC20 PC(20) +#define PC21 PC(21) +#define PC22 PC(22) +#define PC23 PC(23) +#define PC24 PC(24) +#define PC25 PC(25) +#define PC26 PC(26) +#define PC27 PC(27) +#define PC28 PC(28) +#define PC29 PC(29) +#define PC30 PC(30) +#define PC31 PC(31) + +/*+-----------------------------------------------------+ + *| GPIO PortD: PD0~PD31 defined as "pioD0"-"pioD31" | + *+-----------------------------------------------------+*/ + +#define PD0 PD(0) +#define PD1 PD(1) +#define PD2 PD(2) +#define PD3 PD(3) +#define PD4 PD(4) +#define PD5 PD(5) +#define PD6 PD(6) +#define PD7 PD(7) +#define PD8 PD(8) +#define PD9 PD(9) +#define PD10 PD(10) +#define PD11 PD(11) +#define PD12 PD(12) +#define PD13 PD(13) +#define PD14 PD(14) +#define PD15 PD(15) +#define PD16 PD(16) +#define PD17 PD(17) +#define PD18 PD(18) +#define PD19 PD(19) +#define PD20 PD(20) +#define PD21 PD(21) +#define PD22 PD(22) +#define PD23 PD(23) +#define PD24 PD(24) +#define PD25 PD(25) +#define PD26 PD(26) +#define PD27 PD(27) +#define PD28 PD(28) +#define PD29 PD(29) +#define PD30 PD(30) +#define PD31 PD(31) + +/*+-----------------------------------------------------+ + *| GPIO PortE: PE0~PE30 defined as "pioE0"-"pioE30" | + *+-----------------------------------------------------+*/ + +#define PE0 PE(0) +#define PE1 PE(1) +#define PE2 PE(2) +#define PE3 PE(3) +#define PE4 PE(4) +#define PE5 PE(5) +#define PE6 PE(6) +#define PE7 PE(7) +#define PE8 PE(8) +#define PE9 PE(9) +#define PE10 PE(10) +#define PE11 PE(11) +#define PE12 PE(12) +#define PE13 PE(13) +#define PE14 PE(14) +#define PE15 PE(15) +#define PE16 PE(16) +#define PE17 PE(17) +#define PE18 PE(18) +#define PE19 PE(19) +#define PE20 PE(20) +#define PE21 PE(21) +#define PE22 PE(22) +#define PE23 PE(23) +#define PE24 PE(24) +#define PE25 PE(25) +#define PE26 PE(26) +#define PE27 PE(27) +#define PE28 PE(28) +#define PE29 PE(29) +#define PE30 PE(30) + + +#endif /* ----- #ifndef _AT91_SYSGPIODEF_H_ ----- */ + diff --git a/program/lylib/spidev.c b/program/lylib/spidev.c new file mode 100644 index 0000000..8a5d29a --- /dev/null +++ b/program/lylib/spidev.c @@ -0,0 +1,255 @@ +/********************************************************************************* + * Copyright: (C) 2019 LingYun IoT System Studio + * All rights reserved. + * + * Filename: spidev.c + * Description: This file is spidev user space API. + * + * Version: 1.0.0(2019年08月19日) + * Author: Guo Wenxue <guowenxue@gmail.com> + * ChangeLog: 1, Release initial version on "2019年08月19日 23时18分54秒" + * + ********************************************************************************/ +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include "spidev.h" + +int spi_init(spidev_t *spi, char *spidev, uint8_t bpw, uint32_t speed, uint32_t delay, uint32_t mode) +{ + int rv = 0; + + if( !spi || !spidev ) + { + spi_dbg("Invalid input arguments\n"); + return -1; + } + + memset(spi, 0, sizeof(*spi)); + + strncpy(spi->devname, spidev, DEVNAME_LEN); + spi->bits = bpw; + spi->speed = speed*1000; /* speed unit is KHz */ + spi->delay = delay; + spi->mode = mode; + + spi->fd = open(spidev, O_RDWR); + if( spi->fd < 0) + { + spi_dbg("Open SPI device '%s' failure: %s\n", spidev, strerror(errno)); + rv = -2; + goto cleanup; + } + + /* set bits per word */ + if( ioctl(spi->fd, SPI_IOC_WR_BITS_PER_WORD, &bpw) < 0 ) + { + spi_dbg("Set SPI '%s' bit per words to [%d] failure: %s\n", spidev, bpw, strerror(errno)); + rv = -3; + goto cleanup; + } + + /* set bits per word */ + if( ioctl(spi->fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi->speed) < 0 ) + { + spi_dbg("Set SPI '%s' speed to %dKHz failure: %s\n", spidev, speed, strerror(errno)); + rv = -4; + goto cleanup; + } + + /* set spi mode */ + if( ioctl(spi->fd, SPI_IOC_WR_MODE32, &mode) < 0 ) + { + spi_dbg("Set SPI '%s' mode to [0x%0x] failure: %s\n", spidev, mode, strerror(errno)); + rv = -5; + goto cleanup; + } + +cleanup: + if( rv < 0 ) + { + close(spi->fd); + } + + return rv; +} + +int spi_read(spidev_t *spi, char *buf, int size) +{ + int rv = 0; + void *dummy_buf; + + struct spi_ioc_transfer tr = + { + .rx_buf = (unsigned long)buf, + .len = size, + .delay_usecs = spi->delay, + .speed_hz = spi->speed, + .bits_per_word = spi->bits, + }; + + if( !spi || !buf || size<=0 ) + { + spi_dbg("Invalid input arguments\n"); + return -1; + } + + if( ! (dummy_buf=malloc(tr.len)) ) + { + spi_dbg("spi_read malloc failure: %s\n", strerror(errno)); + return -2; + } + tr.tx_buf = (unsigned long)dummy_buf; + + if ( spi->mode & (SPI_TX_QUAD|SPI_RX_QUAD) ) + tr.tx_nbits = 4; + + if ( spi->mode & (SPI_TX_DUAL|SPI_RX_DUAL) ) + tr.tx_nbits = 2; + + if (!(spi->mode & SPI_LOOP)) + { + if (spi->mode & (SPI_TX_QUAD|SPI_TX_DUAL)) + tr.rx_buf = 0; + else if (spi->mode & (SPI_RX_QUAD|SPI_RX_DUAL)) + tr.tx_buf = 0; + } + + if( ioctl(spi->fd, SPI_IOC_MESSAGE(1), &tr) < 0) + { + spi_dbg("spi_read SPI_IOC_MESSAGE failure: %s\n", strerror(errno)); + rv = -3; + goto cleanup; + } + +cleanup: + if( dummy_buf ) + { + free( dummy_buf ); + } + + return rv; +} + + +int spi_write(spidev_t *spi, char *data, int nbytes) +{ + int rv = 0; + void *dummy_buf; + + struct spi_ioc_transfer tr = + { + .tx_buf = (unsigned long)data, + .len = nbytes, + .delay_usecs = spi->delay, + .speed_hz = spi->speed, + .bits_per_word = spi->bits, + }; + + + if( !spi || !data || nbytes<= 0) + { + spi_dbg("Invalid input arguments\n"); + return -1; + } + + if( ! (dummy_buf=malloc(tr.len)) ) + { + spi_dbg("spi_read malloc failure: %s\n", strerror(errno)); + return -1; + } + tr.rx_buf = (unsigned long)dummy_buf; + + if ( spi->mode & (SPI_TX_QUAD|SPI_RX_QUAD) ) + tr.tx_nbits = 4; + + if ( spi->mode & (SPI_TX_DUAL|SPI_RX_DUAL) ) + tr.tx_nbits = 2; + + if (!(spi->mode & SPI_LOOP)) + { + if (spi->mode & (SPI_TX_QUAD|SPI_TX_DUAL)) + tr.rx_buf = 0; + else if (spi->mode & (SPI_RX_QUAD|SPI_RX_DUAL)) + tr.tx_buf = 0; + } + + if( ioctl(spi->fd, SPI_IOC_MESSAGE(1), &tr) < 0) + { + spi_dbg("spi_read SPI_IOC_MESSAGE failure: %s\n", strerror(errno)); + rv = -2; + goto cleanup; + } + +cleanup: + if( dummy_buf ) + { + free( dummy_buf ); + } + + return rv; +} + +int spi_rdwr(spidev_t *spi, char *data, char *rbuf, int nbytes) +{ + int rv = 0; + + struct spi_ioc_transfer tr = + { + .tx_buf = (unsigned long)data, + .rx_buf = (unsigned long)rbuf, + .len = nbytes, + .delay_usecs = spi->delay, + .speed_hz = spi->speed, + .bits_per_word = spi->bits, + }; + + if( !spi || !data || nbytes<=0 ) + { + spi_dbg("Invalid input arguments\n"); + return -1; + } + + + if ( spi->mode & (SPI_TX_QUAD|SPI_RX_QUAD) ) + tr.tx_nbits = 4; + + if ( spi->mode & (SPI_TX_DUAL|SPI_RX_DUAL) ) + tr.tx_nbits = 2; + + if (!(spi->mode & SPI_LOOP)) + { + if (spi->mode & (SPI_TX_QUAD|SPI_TX_DUAL)) + tr.rx_buf = 0; + else if (spi->mode & (SPI_RX_QUAD|SPI_RX_DUAL)) + tr.tx_buf = 0; + } + + + if( ioctl(spi->fd, SPI_IOC_MESSAGE(1), &tr) < 0) + { + spi_dbg("spi_read SPI_IOC_MESSAGE failure: %s\n", strerror(errno)); + rv = -3; + } + + return rv; +} + +int spi_term(spidev_t *spi) +{ + if( !spi ) + { + spi_dbg("Invalid input arguments\n"); + return -1; + } + + if(spi->fd) + { + spi_dbg("close spi device '%s'\n", spi->devname); + close(spi->fd); + } + + memset(spi, 0, sizeof(*spi)); + spi->fd = -1; +} + diff --git a/program/lylib/spidev.h b/program/lylib/spidev.h new file mode 100644 index 0000000..84be549 --- /dev/null +++ b/program/lylib/spidev.h @@ -0,0 +1,75 @@ +/********************************************************************************* + * Copyright: (C) 2019 LingYun IoT System Studio + * All rights reserved. + * + * Filename: spidev.h + * Description: This file is spidev user space API. + * + * Version: 1.0.0(2019年08月19日) + * Author: Guo Wenxue <guowenxue@gmail.com> + * ChangeLog: 1, Release initial version on "2019年08月19日 23时18分54秒" + * + ********************************************************************************/ +#ifndef _SPIDEV_H_ +#define _SPIDEV_H_ + +#include <stdint.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <linux/ioctl.h> +#include <sys/stat.h> +#include <linux/types.h> +#include <linux/spi/spidev.h> + +#define DEVNAME_LEN 64 + +#define DEF_SPI_BPW 8 /* bits per word */ +#define DEF_SPI_SPEED 500 /* unit kHZ */ +#define DEF_SPI_MODE SPI_CPHA + +//#define SPI_DEBUG +#ifdef SPI_DEBUG +#define spi_dbg(format,args...) printf(format, ##args) +#else +#define spi_dbg(format,args...) do{} while(0); +#endif + +typedef struct spidev_s +{ + char devname[DEVNAME_LEN]; + int fd; + uint8_t bits; /* bits per word */ + uint32_t speed; /* max speed in HZ */ + uint32_t delay; /* delay usecs */ + + /* mode: SPI_CPHA,SPI_CPOL => <SPI_MODE_0,SPI_MODE_1,SPI_MODE_2,SPI_MODE_3> + * SPI_CS_HIGH | SPI_LSB_FIRST | SPI_3WIRE | SPI_LOOP | SPI_NO_CS + * | SPI_READY | SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD */ + uint32_t mode; +} spidev_t; + + +/* initialise and open spidev context + * NOTE: $speed unit is KHz + */ +extern int spi_init(spidev_t *spi, char *spidev, uint8_t bpw, uint32_t speed, uint32_t delay, uint32_t mode); + + +/* read size bytes from SPI slave */ +extern int spi_read(spidev_t *spi, char *buf, int size); + + +/* write nbytes to SPI slave */ +extern int spi_write(spidev_t *spi, char *data, int nbytes); + + +/* write nbytes and read nbytes to/from SPI slave */ +extern int spi_rdwr(spidev_t *spi, char *data, char *rbuf, int nbytes); + + +/* terminate and close spidev context */ +extern int spi_term(spidev_t *spi); + + +#endif /* ----- #ifndef _SPIDEV_H_ ----- */ + -- Gitblit v1.9.1