The ftdispi library doesn't do much, it just calls into ftdi You should
be able to run this little test program.
Mike
On 9/29/2011 9:45 AM, Uwe Bonnes wrote:
"Michael" == Michael Wilt<[email protected]> writes:
Michael> Thank you, now I see how it is supposed to work. When I
Michael> specify INTERFACE_B I can see that ftdi_set_interface sets the
Michael> end points correctly for the second interface. However, the
Michael> next call to usb_bulk_write returns -22.
Michael> Mike
Tell us what programs from what source you use and I can try to reproduce if
I can compiles these programs on my Linux machine.
Bye
--
libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to [email protected]
#include <stdio.h>
#include "ftdispi.h"
int main(int argc, char **argv)
{
struct ftdi_context fc;
struct ftdispi_context fsc;
int i;
unsigned char rbuf[5];
if (ftdi_init(&fc) < 0)
{
fprintf(stderr, "ftdi_init failed\n");
return 1;
}
// i = ftdi_usb_open(&fc, 0x0403, 0x6010);
i = ftdi_usb_open_desc_index(&fc, 0x0403, 0x6010, NULL, NULL, 0);
if (i < 0 && i != -5)
{
fprintf(stderr,
"OPEN: %s\n",
ftdi_get_error_string(&fc));
exit(-1);
}
ftdispi_open(&fsc, &fc, INTERFACE_B);
ftdispi_setmode(&fsc, 1, 0, 0, 0, 0, 0);
ftdispi_setclock(&fsc, 50000);
ftdispi_setloopback(&fsc, 1);
ftdispi_write_read(&fsc, "Test", 4, rbuf, 0, 0);
printf ("read 0x%02x 0x%02x 0x%02x 0x%02x\n", rbuf[0], rbuf[1], rbuf[2],
rbuf[3]);
// ftdispi_write(&fsc, "Test", 4, 0);
ftdispi_close(&fsc, 1);
return 0;
}
/**
* @file ftdispi.c
*
* @author Stany MARCEL <[email protected]>
*
* @brief libftdispi permits to use FTDI component in SPI master mode. Require
* libftdi
*
* BSD License
*
* Copyright ©2010, Stany MARCEL <[email protected]> All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the owner nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include "ftdispi.h"
#define BBMODE_NORMAL 1
#define BBMODE_SPI 2
/* Clock X5 Command for H class component */
#define TCK_X5 0x8a
#define BIT_P_CS 0x08
#define BIT_P_DI 0x04
#define BIT_P_DO 0x02
#define BIT_P_SK 0x01
#define BIT_P_G0 FTDISPI_GPO0
#define BIT_P_G1 FTDISPI_GPO1
#define BIT_P_G2 FTDISPI_GPO2
#define BIT_P_G3 FTDISPI_GPO3
#define BIT_P_GX (FTDISPI_GPO0|FTDISPI_GPO1|FTDISPI_GPO2|FTDISPI_GPO3)
#define BIT_DIR (BIT_P_SK|BIT_P_DO|BIT_P_CS|BIT_P_G0|BIT_P_G1|BIT_P_G2|BIT_P_G3)
#define SPI_MAX_MSG_SIZE (64*1024)
#define DEFAULT_MEM_SIZE ((SPI_MAX_MSG_SIZE) + 9)
#define RETRY_MAX 10
#define RETRY_TIME 1000
#define FTDI_CHECK(FUN, MSG, CTX) do { \
if ((FUN) < 0) \
{ \
fprintf(stderr, \
"%s: %s\n", \
MSG, \
ftdi_get_error_string(&CTX)); \
return FTDISPI_ERROR_LIB; \
} \
} while (0)
#define ASSERT_CHECK(TEST, MSG, RVAL) do { \
if ((TEST)) \
{ \
fprintf(stderr, \
"ASSERT: %s\n", MSG); \
return RVAL; \
} } while (0)
static int ftdispi_realloc(struct ftdispi_context * fsc, size_t size);
static int ftdispi_wait(struct ftdispi_context * fsc, uint8_t mask, uint8_t
value, int maxtry);
__dll int ftdispi_open(struct ftdispi_context * fsc,
struct ftdi_context * fc,
int intface)
{
ASSERT_CHECK(!fc || !fsc, "CTX NOT INITIALIZED", FTDISPI_ERROR_CTX);
memset(fsc, 0, sizeof(*fsc));
memcpy(&fsc->fc, fc, sizeof(*fc));
if (0 != (fsc->mem = malloc(DEFAULT_MEM_SIZE)))
{
fsc->memsize = DEFAULT_MEM_SIZE;
}
FTDI_CHECK(ftdi_write_data_set_chunksize(&fsc->fc, 512), "SET CHUNK 512",
fsc->fc);
FTDI_CHECK(ftdi_set_interface(&fsc->fc, intface), "SET INT", fsc->fc);
FTDI_CHECK(ftdi_usb_reset(&fsc->fc), "RESET", fsc->fc);
FTDI_CHECK(ftdi_set_latency_timer(&fsc->fc, 2), "SET LAT 2ms", fsc->fc);
FTDI_CHECK(ftdi_setflowctrl(&fsc->fc, SIO_RTS_CTS_HS), "RTS/CTS", fsc->fc);
/*FTDI_CHECK(ftdi_set_bitmode(&fsc->fc, 0, 0), "RESET MPSSE", fsc->fc);*/
FTDI_CHECK(ftdi_set_bitmode(&fsc->fc, 0, BBMODE_SPI), "SET SPI MODE",
fsc->fc);
fsc->wr_cmd = MPSSE_DO_WRITE | MPSSE_DO_READ; // do write/read
simultaneously on write
fsc->rd_cmd = MPSSE_DO_READ | MPSSE_READ_NEG;
fsc->bitini = BIT_P_CS;
FTDI_CHECK(ftdi_usb_purge_buffers(&fsc->fc), "PURGE", fsc->fc);
return FTDISPI_ERROR_NONE;
}
__dll int ftdispi_setclock(struct ftdispi_context * fsc,
uint32_t speed)
{
uint8_t buf[3] = { 0, 0, 0 };
uint32_t div;
uint32_t base;
ASSERT_CHECK(!fsc, "CTX NOT INITIALIZED", FTDISPI_ERROR_CTX);
if (speed > CLOCK_MAX_SPEEDX5 || speed < CLOCK_MIN_SPEED)
{
return FTDISPI_ERROR_CLK;
}
if (speed > CLOCK_MAX_SPEED)
{
/* TODO check if the device can support this */
base = CLOCK_MAX_SPEEDX5;
}
else
{
base = CLOCK_MAX_SPEED;
}
div = (base / speed) - 1;
if (div > 0xFFFF)
{
return FTDISPI_ERROR_CLK;
}
if (base == CLOCK_MAX_SPEEDX5)
{
buf[0] = TCK_X5;
FTDI_CHECK(ftdi_write_data(&fsc->fc, buf, 1), "SET CLK X5", fsc->fc);
}
buf[0] = TCK_DIVISOR;
buf[1] = (div >> 0) & 0xFF;
buf[2] = (div >> 8) & 0xFF;
FTDI_CHECK(ftdi_write_data(&fsc->fc, buf, 3), "SET CLK DIV", fsc->fc);
return FTDISPI_ERROR_NONE;
}
__dll int ftdispi_setloopback(struct ftdispi_context * fsc,
int active)
{
uint8_t buf[1] = { 0 };
ASSERT_CHECK(!fsc, "CTX NOT INITIALIZED", FTDISPI_ERROR_CTX);
if (active)
{
buf[0] = LOOPBACK_START;
FTDI_CHECK(ftdi_write_data(&fsc->fc, buf, 1), "SET LOOP", fsc->fc);
}
else
{
buf[0] = LOOPBACK_END;
FTDI_CHECK(ftdi_write_data(&fsc->fc, buf, 1), "SET NO LOOP", fsc->fc);
}
return FTDISPI_ERROR_NONE;
}
__dll int ftdispi_setmode(struct ftdispi_context * fsc,
int csh,
int cpol,
int cpha,
int lsbfirst,
int bitmode,
int gpoini)
{
uint8_t buf[3] = { 0, 0, 0 };
ASSERT_CHECK(!fsc, "CTX NOT INITIALIZED", FTDISPI_ERROR_CTX);
fsc->wr_cmd = MPSSE_DO_WRITE | MPSSE_DO_READ | (bitmode ? MPSSE_BITMODE :
0); // OR in read too on write
fsc->rd_cmd = MPSSE_DO_READ | (bitmode ? MPSSE_BITMODE : 0);
fsc->bitini = (csh ? BIT_P_CS : 0) | (BIT_P_GX & gpoini);
if (!cpol)
{
/* CLK IDLE = 0 */
if (!cpha)
{
/* W=FE R=RE => NO TX */
fsc->wr_cmd |= MPSSE_WRITE_NEG;
}
else
{
/* W=RE R=FE > RX OPT */
fsc->rd_cmd |= MPSSE_READ_NEG;
}
}
else
{
/* CLK IDLE == 1 */
fsc->bitini |= BIT_P_SK;
if (!cpha)
{
/* W=RE R=FE => NO TX */
fsc->rd_cmd |= MPSSE_READ_NEG;
}
else
{
/* W=FE R=RE => RX OPT */
fsc->wr_cmd |= MPSSE_WRITE_NEG;
}
}
if (lsbfirst)
{
fsc->wr_cmd |= MPSSE_LSB;
fsc->rd_cmd |= MPSSE_LSB;
}
else
{
fsc->wr_cmd &= ~MPSSE_LSB;
fsc->rd_cmd &= ~MPSSE_LSB;
}
buf[0] = SET_BITS_LOW;
buf[1] = fsc->bitini;
buf[2] = BIT_DIR;
FTDI_CHECK(ftdi_write_data(&fsc->fc, buf, 3), "WR INI", fsc->fc);
if (ftdispi_wait(fsc, BIT_P_CS | BIT_P_GX, fsc->bitini, RETRY_MAX))
{
/* I still don't know why sometime the command must be resent */
FTDI_CHECK(ftdi_write_data(&fsc->fc, buf, 3), "WR INI", fsc->fc);
}
return ftdispi_wait(fsc, BIT_P_CS | BIT_P_GX, fsc->bitini, RETRY_MAX);
}
__dll int ftdispi_write_read(struct ftdispi_context * fsc,
const void *wbuf,
uint16_t wcount,
void *rbuf,
uint16_t rcount,
uint8_t gpo)
{
int i, n, r;
ASSERT_CHECK(!fsc, "CTX NOT INITIALIZED", FTDISPI_ERROR_CTX);
ASSERT_CHECK(!((wbuf && wcount) || (rbuf && rcount)),
"NO CMD", FTDISPI_ERROR_CMD);
n = wcount + (rcount ? 9 : 6);
ASSERT_CHECK(ftdispi_realloc(fsc, n), "REALLOC", FTDISPI_ERROR_MEM);
i = 0;
fsc->mem[i++] = SET_BITS_LOW;
fsc->mem[i++] = ((0x0F & (fsc->bitini ^ BIT_P_CS)) |
(BIT_P_GX & gpo));
fsc->mem[i++] = BIT_DIR;
if (wcount && wbuf)
{
fsc->mem[i++] = fsc->wr_cmd;
fsc->mem[i++] = (wcount - 1) & 0xFF;
fsc->mem[i++] = ((wcount - 1) >> 8) & 0xFF;
memcpy(fsc->mem + i, wbuf, wcount);
i += wcount;
}
if (rcount && rbuf)
{
fsc->mem[i++] = fsc->rd_cmd;
fsc->mem[i++] = (rcount - 1) & 0xFF;
fsc->mem[i++] = ((rcount - 1) >> 8) & 0xFF;
FTDI_CHECK(ftdi_write_data(&fsc->fc, fsc->mem, i), "[WR]RD", fsc->fc);
for (n = 0; n < rcount; )
{
FTDI_CHECK(r = ftdi_read_data(&fsc->fc, ((char *) rbuf) + n, rcount
- n), "RD", fsc->fc);
n += r;
}
i = 0;
}
fsc->mem[i++] = SET_BITS_LOW;
fsc->mem[i++] = fsc->bitini;
fsc->mem[i++] = BIT_DIR;
FTDI_CHECK(ftdi_write_data(&fsc->fc, fsc->mem, i), "WR", fsc->fc);
Sleep (10);
// mjw try to read the exchange data from the write transaction
FTDI_CHECK(r = ftdi_read_data(&fsc->fc, ((char *) rbuf), wcount), "RD",
fsc->fc);
printf ("r %d\n", r);
return ftdispi_wait(fsc, BIT_P_CS, fsc->bitini, RETRY_MAX);
}
__dll int ftdispi_write(struct ftdispi_context * fsc,
const void *buf,
uint16_t count,
uint8_t gpo)
{
return ftdispi_write_read(fsc, buf, count, 0, 0, gpo);
}
__dll int ftdispi_read(struct ftdispi_context * fsc,
void *buf,
uint16_t count,
uint8_t gpo)
{
return ftdispi_write_read(fsc, 0, 0, buf, count, gpo);
}
__dll int ftdispi_setgpo(struct ftdispi_context * fsc,
uint8_t gpo)
{
uint8_t buf[3];
ASSERT_CHECK(!fsc, "CTX NOT INITIALIZED", FTDISPI_ERROR_CTX);
if ((fsc->bitini & BIT_P_GX) != (gpo & BIT_P_GX))
{
fsc->bitini = ((fsc->bitini & BIT_P_GX) | (gpo & BIT_P_GX));
}
buf[0] = SET_BITS_LOW;
buf[1] = fsc->bitini;
buf[2] = BIT_DIR;
FTDI_CHECK(ftdi_write_data(&fsc->fc, buf, 3), "SETGPO", fsc->fc);
return ftdispi_wait(fsc, BIT_P_GX, fsc->bitini, RETRY_MAX);
}
__dll int ftdispi_close(struct ftdispi_context * fsc,
int close_ftdi)
{
ASSERT_CHECK(!fsc, "CTX NOT INITIALIZED", FTDISPI_ERROR_CTX);
if (fsc->mem)
{
free(fsc->mem);
fsc->mem = 0;
fsc->memsize = 0;
}
if (close_ftdi)
{
ftdi_usb_close(&fsc->fc);
ftdi_deinit(&fsc->fc);
}
return FTDISPI_ERROR_NONE;
}
static int ftdispi_realloc(struct ftdispi_context * fsc, size_t size)
{
uint8_t * p;
if (fsc->memsize < size)
{
if (!(p = realloc(fsc->mem, size)))
{
return FTDISPI_ERROR_MEM;
}
fsc->mem = p;
fsc->memsize = size;
}
return FTDISPI_ERROR_NONE;
}
static int ftdispi_wait(struct ftdispi_context * fsc, uint8_t mask, uint8_t
value, int maxtry)
{
uint8_t cmd = GET_BITS_LOW;
uint8_t ret = 0;
FTDI_CHECK(ftdi_write_data(&fsc->fc, &cmd, 1), "GBLW", fsc->fc);
FTDI_CHECK(ftdi_read_data(&fsc->fc, &ret, 1), "GBLR", fsc->fc);
while (maxtry-- && (ret & mask) != (value & mask))
{
// usleep(RETRY_TIME);
FTDI_CHECK(ftdi_write_data(&fsc->fc, &cmd, 1), "GBLW", fsc->fc);
FTDI_CHECK(ftdi_read_data(&fsc->fc, &ret, 1), "GBLR", fsc->fc);
}
if ((ret & mask) == (value & mask))
{
return FTDISPI_ERROR_NONE;
}
else
{
return FTDISPI_ERROR_TO;
}
}
/**
* @file ftdispi.h
*
* @author Stany MARCEL <[email protected]>
*
* @brief libftdispi permits to use FTDI component in SPI master mode. Require
* libftdi
*
* BSD License
*
* Copyright ©2010, Stany MARCEL <[email protected]> All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the owner nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FTDISPI_H__
# define __FTDISPI_H__
# include "ftdi.h"
//# include <unistd.h>
# include <string.h>
# include "stdint.h"
//# ifdef WIN32
//# ifdef EXPORT_DLL
//# define __dll __declspec(dllexport)
//# else
//# define __dll __declspec(dllimport)
//# endif
//# else
# define __dll
//# endif
# ifdef __cplusplus
extern "C" {
# endif
/** @brief returned when no error */
# define FTDISPI_ERROR_NONE 0
/** @brief returned when a function is called with a non/bad init context */
# define FTDISPI_ERROR_CTX -1
/** @brief returned when a command is imposible */
# define FTDISPI_ERROR_CMD -2
/** @brief returned on allocation problems */
# define FTDISPI_ERROR_MEM -3
/** @brief returned on libftdi error */
# define FTDISPI_ERROR_LIB -4
/** @brief returned on clock error */
# define FTDISPI_ERROR_CLK -5
/** @brief returned on timeout error */
# define FTDISPI_ERROR_TO -6
# define CLOCK_MAX_SPEEDX5 30000000 /**< @brief Clock max speed in Hz for H
class device */
# define CLOCK_MAX_SPEED 6000000 /**< @brief Clock max speed in Hz */
# define CLOCK_MIN_SPEED 100 /**< @brief Clock min speed in Hz */
# define FTDISPI_GPO0 0x10 /**< @brief General Purpose Output bits 0 (D4) */
# define FTDISPI_GPO1 0x20 /**< @brief General Purpose Output bits 1 (D5) */
# define FTDISPI_GPO2 0x40 /**< @brief General Purpose Output bits 2 (D6) */
# define FTDISPI_GPO3 0x80 /**< @brief General Purpose Output bits 3 (D7) */
/**
* @brief FDTI SPI context
*/
struct ftdispi_context {
struct ftdi_context fc; /**< @brief ftdi context */
uint8_t wr_cmd; /**< @brief write command */
uint8_t rd_cmd; /**< @brief read command */
uint8_t bitini; /**< @brief initial states of all bits */
uint8_t *mem; /**< @brief memory region for write and read
* functions */
size_t memsize; /**< @brief size of the memory region for write
* and read functions */
};
/**
* @brief Open the a FTDI interface in SPI mode.
*
* @param[in,out] fsc the spi context to open
* @param[in] fc a previously opened usb ftdi device
* @param[in] interface the interface to use
*
* @retval #FTDISPI_ERROR_NONE on success
* @retval #FTDISPI_ERROR_CTX on context error
* @retval #FTDISPI_ERROR_LIB on libftdi error
*
* @sa ftdi_init
* @sa ftdi_usb_open
*/
__dll int
ftdispi_open(struct ftdispi_context * fsc,
struct ftdi_context * fc,
int interface);
/**
* @brief Set the mode for future SPI operations. Returns only when GPO and CS
* are in wanted state.
*
* ftdispi_open set a default mode to CSH=1, CPOL=0, CPHA=1, MSB first.
*
* @param[in,out] fsc previously opened spi contex
* @param[in] csh idle state of chip select
* @param[in] cpol idle state of clock
* @param[in] cpha read and write edge settings
* @param[in] lsbfirst if set data are serialized LSB first
* @param[in] bitmode set to 1 for mpsse bit mode active
* @param[in] gpoini initial state of General Purpose Output
* (#FTDISPI_GPO0 | #FTDISPI_GPO1 |#FTDISPI_GPO2 |#FTDISPI_GPO3)
*
* - CPOL=0 CPHA=0 => Mode 0, W=FE R=RE
* - CPOL=0 CPHA=1 => Mode 1, W=RE R=FE (CLK inverted at each byte for un
unknown reason)
* - CPOL=1 CPHA=0 => Mode 2, W=RE R=FE (CLK inverted at each byte for un
unknown reason)
* - CPOL=1 CPHA=1 => Mode 3, W=FE R=RE
*
* W: Write,
* R: Read,
* RE: Rising Edge,
* FE: Falling Edge,
*
* WFE means data clocked out on Falling Edge
* RRE means data read on Rising Edge
*
* @retval #FTDISPI_ERROR_NONE on success
* @retval #FTDISPI_ERROR_CTX on context error
* @retval #FTDISPI_ERROR_TO on timeout error
*
* @sa ftdispi_open
*/
__dll int
ftdispi_setmode(struct ftdispi_context * fsc,
int csh,
int cpol,
int cpha,
int lsbfirst,
int bitmode,
int gpoini);
/**
* @brief Set the clock divisor from the given speed.
*
* @param[in,out] fsc previously opened spi contex
* @param[in] speed the wanted in Hz from #CLOCK_MIN_SPEED to #CLOCK_MAX_SPEEDX5
*
* For the moment no check are done to verify that your device support the max
* speed x 5
*
* @retval #FTDISPI_ERROR_NONE on success
* @retval #FTDISPI_ERROR_CTX on context error
* @retval #FTDISPI_ERROR_LIB on libftdi error
*/
__dll int
ftdispi_setclock(struct ftdispi_context * fsc,
uint32_t speed);
/**
* @brief set the loopback for TDI/DO TDO/DI
*
* @param[in,out] fsc previously opened spi contex
* @param[in] active set to 0 to diable loopback
*
* @retval #FTDISPI_ERROR_NONE on success
* @retval #FTDISPI_ERROR_CTX on context error
* @retval #FTDISPI_ERROR_LIB on libftdi error
*/
__dll int
ftdispi_setloopback(struct ftdispi_context * fsc,
int active);
/**
* @brief Set general purpose output and then write from wbuf to spi and read
* from spi to rbuf. Returns only when CS get back to idle state.
*
* @param[in,out] fsc previously opened spi contex
* @param[in] wbuf buffer to write
* @param[in] wcount number of bytes to write
* @param[out] rbuf buffer to read to
* @param[in] rcount number of bytes to read
* @param[in] gpo general purpose output states for the duration of the
operation
*
* @retval #FTDISPI_ERROR_NONE on success
* @retval #FTDISPI_ERROR_CTX on context error
* @retval #FTDISPI_ERROR_LIB on libftdi error
* @retval #FTDISPI_ERROR_MEM on allocation error
* @retval #FTDISPI_ERROR_CMD on invalid parameters
* @retval #FTDISPI_ERROR_TO on timeout error
*/
__dll int
ftdispi_write_read(struct ftdispi_context * fsc,
const void *wbuf,
uint16_t wcount,
void *rbuf,
uint16_t rcount,
uint8_t gpo);
/**
* @brief Set general purpose output and then write from buf to spi. Returns
only
* when CS get back to idle state.
*
* @param[in,out] fsc previously opened spi contex
* @param[in] buf buffer to write
* @param[in] count number of bytes to write
* @param[in] gpo general purpose output states for the duration of the
operation
*
* @retval #FTDISPI_ERROR_NONE on success
* @retval #FTDISPI_ERROR_CTX on context error
* @retval #FTDISPI_ERROR_LIB on libftdi error
* @retval #FTDISPI_ERROR_MEM on allocation error
* @retval #FTDISPI_ERROR_CMD on invalid parameters
* @retval #FTDISPI_ERROR_TO on timeout error
*/
__dll int
ftdispi_write(struct ftdispi_context * fsc,
const void *buf,
uint16_t count,
uint8_t gpo);
/**
* @brief Set general purpose output and then read from spi to buf. Returns only
* when CS get back to idle state.
*
* @param[in,out] fsc previously opened spi contex
* @param[out] buf buffer to read to
* @param[in] count number of bytes to read
* @param[in] gpo general purpose output states for the duration of the
operation
*
* @retval #FTDISPI_ERROR_NONE on success
* @retval #FTDISPI_ERROR_CTX on context error
* @retval #FTDISPI_ERROR_LIB on libftdi error
* @retval #FTDISPI_ERROR_MEM on allocation error
* @retval #FTDISPI_ERROR_CMD on invalid parameters
* @retval #FTDISPI_ERROR_TO on timeout error
*/
__dll int
ftdispi_read(struct ftdispi_context * fsc,
void *buf,
uint16_t count,
uint8_t gpo);
/**
* @brief Set the new general purpose default state, and change the device
* output accordingly. Returns only when GPO status have changed.
*
* @param[in,out] fsc previously opened spi contex
* @param[in] gpo general purpose output new states
*
* @retval #FTDISPI_ERROR_NONE on success
* @retval #FTDISPI_ERROR_CTX on context error
* @retval #FTDISPI_ERROR_LIB on libftdi error
* @retval #FTDISPI_ERROR_TO on timeout error
*/
__dll int
ftdispi_setgpo(struct ftdispi_context * fsc,
uint8_t gpo);
/**
* @brief Close the ftdispi context.
*
* @param[in,out] fsc previously opened spi contex
* @param[in] close_ftdi if set the ftdi_context is also closed and deinit
*
* @retval #FTDISPI_ERROR_NONE on success
* @retval #FTDISPI_ERROR_CTX on context error
*/
__dll int
ftdispi_close(struct ftdispi_context * fsc,
int close_ftdi);
# ifdef __cplusplus
}
# endif
#endif