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