📄 libftdi.c
字号:
/* * $Id: libftdi.c 1354 2008-09-06 20:10:31Z arniml $ * * Link driver for accessing FTDI devices via libftdi * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * 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 General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * Written by Arnim Laeuger, 2008 * */#include "sysdep.h"#include <fcntl.h>#if __CYGWIN__ || __MINGW32__#include <windows.h>#endif#include <stdio.h>#include <string.h>#ifdef HAVE_STROPTS_H#include <stropts.h>#endif#include <stdlib.h>#include <stdint.h>#include <unistd.h>#include <ftdi.h>#include "cable.h"#include "usbconn.h"#include "usbconn/libftdx.h"typedef struct { /* USB device information */ unsigned int vid; unsigned int pid; struct ftdi_context *fc; char *serial; /* send and receive buffer handling */ uint32_t send_buf_len; uint32_t send_buffered; uint8_t *send_buf; uint32_t recv_buf_len; uint32_t to_recv; uint32_t recv_write_idx; uint32_t recv_read_idx; uint8_t *recv_buf;} ftdi_param_t;usbconn_driver_t usbconn_ftdi_driver;usbconn_driver_t usbconn_ftdi_mpsse_driver;static int usbconn_ftdi_common_open( usbconn_t *conn, int printerr );static void usbconn_ftdi_free( usbconn_t *conn );/* ---------------------------------------------------------------------- */static intusbconn_ftdi_flush( ftdi_param_t *p ){ int xferred; int recvd = 0; if (!p->fc) return -1; if (p->send_buffered == 0) return 0; if ((xferred = ftdi_write_data( p->fc, p->send_buf, p->send_buffered )) < 0) printf( _("%s(): ftdi_write_data() failed: %s\n"), __FUNCTION__, ftdi_get_error_string( p->fc ) ); if (xferred < p->send_buffered) { printf( _("%s(): Written fewer bytes than requested.\n"), __FUNCTION__ ); return -1; } p->send_buffered = 0; /* now read all scheduled receive bytes */ if (p->to_recv) { if (p->recv_write_idx + p->to_recv > p->recv_buf_len) { /* extend receive buffer */ p->recv_buf_len = p->recv_write_idx + p->to_recv; if (p->recv_buf) p->recv_buf = (uint8_t *)realloc( p->recv_buf, p->recv_buf_len ); } if (!p->recv_buf) { printf( _("%s(): Receive buffer does not exist.\n"), __FUNCTION__ ); return -1; } while (recvd == 0) if ((recvd = ftdi_read_data( p->fc, &(p->recv_buf[p->recv_write_idx]), p->to_recv )) < 0) printf( _("%s(): Error from ftdi_read_data(): %s\n"), __FUNCTION__, ftdi_get_error_string( p->fc ) ); if (recvd < p->to_recv) printf( _("%s(): Received less bytes than requested.\n"), __FUNCTION__ ); p->to_recv -= recvd; p->recv_write_idx += recvd; } return xferred < 0 ? -1 : xferred;}/* ---------------------------------------------------------------------- */static intusbconn_ftdi_read( usbconn_t *conn, uint8_t *buf, int len ){ ftdi_param_t *p = conn->params; int cpy_len; int recvd = 0; if (!p->fc) return -1; /* flush send buffer to get all scheduled receive bytes */ if (usbconn_ftdi_flush( p ) < 0) return -1; if (len == 0) return 0; /* check for number of remaining bytes in receive buffer */ cpy_len = p->recv_write_idx - p->recv_read_idx; if (cpy_len > len) cpy_len = len; len -= cpy_len; if (cpy_len > 0) { /* get data from the receive buffer */ memcpy( buf, &(p->recv_buf[p->recv_read_idx]), cpy_len ); p->recv_read_idx += cpy_len; if (p->recv_read_idx == p->recv_write_idx) p->recv_read_idx = p->recv_write_idx = 0; } if (len > 0) { /* need to get more data directly from the device */ while (recvd == 0) if ((recvd = ftdi_read_data( p->fc, &(buf[cpy_len]), len )) < 0) printf( _("%s(): Error from ftdi_read_data(): %s\n"), __FUNCTION__, ftdi_get_error_string( p->fc ) ); } return recvd < 0 ? -1 : cpy_len + len;}/* ---------------------------------------------------------------------- */static intusbconn_ftdi_write( usbconn_t *conn, uint8_t *buf, int len, int recv ){ ftdi_param_t *p = conn->params; int xferred = 0; if (!p->fc) return -1; /* this write function will try to buffer write data buffering will be ceased and a flush triggered in two cases. */ /* Case A: max number of scheduled receive bytes will be exceeded with this write Case B: max number of scheduled send bytes has been reached */ if ((p->to_recv + recv > FTDI_MAXRECV) || ((p->send_buffered > FTDX_MAXSEND) && (p->to_recv == 0))) xferred = usbconn_ftdi_flush( p ); if (xferred < 0) return -1; /* now buffer this write */ if (p->send_buffered + len > p->send_buf_len) { p->send_buf_len = p->send_buffered + len; if (p->send_buf) p->send_buf = (uint8_t *)realloc( p->send_buf, p->send_buf_len); } if (p->send_buf) { memcpy( &(p->send_buf[p->send_buffered]), buf, len ); p->send_buffered += len; if (recv > 0) p->to_recv += recv; if (recv < 0) { /* immediate write requested, so flush the buffered data */ xferred = usbconn_ftdi_flush( p ); } return xferred < 0 ? -1 : len; } else { printf( _("%s(): Send buffer does not exist.\n"), __FUNCTION__ ); return -1; }}/* ---------------------------------------------------------------------- */usbconn_t *usbconn_ftdi_connect( const char **param, int paramc, usbconn_cable_t *template ){ usbconn_t *c = malloc( sizeof( usbconn_t ) ); ftdi_param_t *p = malloc( sizeof( ftdi_param_t ) ); struct ftdi_context *fc = malloc( sizeof( struct ftdi_context ) ); if (p) { p->send_buf_len = FTDX_MAXSEND; p->send_buffered = 0; p->send_buf = (uint8_t *)malloc( p->send_buf_len ); p->recv_buf_len = FTDI_MAXRECV; p->to_recv = 0; p->recv_write_idx = 0; p->recv_read_idx = 0; p->recv_buf = (uint8_t *)malloc( p->recv_buf_len ); } if (!p || !c || !fc || !p->send_buf || !p->recv_buf) { printf( _("Out of memory\n") ); if (p->send_buf) free( p->send_buf ); if (p->recv_buf) free( p->recv_buf ); if (p) free( p ); if (c) free( c ); if (fc) free( fc ); return NULL; } ftdi_init( fc ); p->fc = fc; p->pid = template->pid; p->vid = template->vid; p->serial = template->desc ? strdup( template->desc ) : NULL; c->params = p; c->driver = &usbconn_ftdi_driver; c->cable = NULL; /* do a test open with the specified cable paramters, alternatively we could use libusb to detect the presence of the specified USB device */ if (usbconn_ftdi_common_open( c, 0 ) != 0) { usbconn_ftdi_free( c ); return NULL; } ftdi_usb_close( fc ); printf( _("Connected to libftdi driver.\n") ); return c;}usbconn_t *usbconn_ftdi_mpsse_connect( const char **param, int paramc, usbconn_cable_t *template ){ usbconn_t *conn = usbconn_ftdi_connect( param, paramc, template );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -