aboutsummaryrefslogtreecommitdiff
path: root/drivers/ftdi_d2xx/sm_d2xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ftdi_d2xx/sm_d2xx.c')
-rw-r--r--drivers/ftdi_d2xx/sm_d2xx.c264
1 files changed, 264 insertions, 0 deletions
diff --git a/drivers/ftdi_d2xx/sm_d2xx.c b/drivers/ftdi_d2xx/sm_d2xx.c
new file mode 100644
index 0000000..aa5eef7
--- /dev/null
+++ b/drivers/ftdi_d2xx/sm_d2xx.c
@@ -0,0 +1,264 @@
+/*
+ * ftdi_d2xx.c
+ *
+ * Header for FTDI D2XX serial port access library
+ *
+ * Created on: 19.8.2017
+ * Author: Tero Kontkanen
+ */
+
+#include "drivers/ftdi_d2xx/sm_d2xx.h"
+#include "simplemotion_private.h" //needed for timeout variable
+#include "drivers/ftdi_d2xx/third_party/ftd2xx.h"
+#include <string.h>
+#include <simplemotion.h>
+
+smbool handles_initialized=smfalse;
+FT_HANDLE handles[MAX_OPEN_PORTS];//FT_HANDLE type is just a pointer
+
+
+static int stringToNumber( const char *str, smbool *ok )
+{
+ int len=strlen(str);
+ int i, number=0, decade=1;
+
+ if(len<1)
+ {
+ *ok=smfalse;
+ return 0;
+ }
+
+ for(i=len-1;i>=0;i--)
+ {
+ if(str[i]<'0' || str[i]>'9')//non-numeric char->fail
+ {
+ *ok=smfalse;
+ return 0;
+ }
+ number+=decade*(str[i]-'0');
+ decade*=10;
+ }
+ *ok=smtrue;
+ return number;
+}
+
+smint32 d2xxPortOpen(const char *port_device_name, smint32 baudrate_bps)
+{
+ //init array of handles if not done yet
+ if(handles_initialized==smfalse)
+ {
+ int i;
+ for(i=0;i<MAX_OPEN_PORTS;i++)
+ handles[i]=NULL;
+ handles_initialized=smtrue;
+ }
+
+ //parse name string
+ int ftdiIndex;
+ smbool ok;
+
+ if (strncmp(port_device_name,"FTDI",4) != 0)//must start with FTDI. Full name is FTDIn where n=index starting from 0.
+ {
+ smDebug( -1, Low, "FTDI port error: malformed port name '%s'. Must be 'FTDIx' where x is index starting from 0.\n",port_device_name);
+ return -1;
+ }
+ ftdiIndex=stringToNumber(port_device_name+4,&ok);
+ if (ok==smfalse)
+ {
+ smDebug( -1, Low, "FTDI port error: malformed port number '%s'. Must be 'FTDIx' where x is index starting from 0.\n",port_device_name);
+ return -1;
+ }
+
+ //open port
+ FT_HANDLE h;
+ FT_STATUS s=FT_Open(ftdiIndex,&h);
+
+ if(s==FT_OK)
+ {
+ //all good, find free handle
+ int i;
+ for(i=0;i<MAX_OPEN_PORTS;i++)
+ {
+ if(handles[i]==NULL)
+ {
+ if(FT_ResetDevice(h)!=FT_OK)
+ {
+ smDebug( -1, Low, "FTDI port error: failed to reset USB chip\n");
+ goto error;
+ }
+
+ //init port settings
+ s=FT_SetBaudRate(h,baudrate_bps);
+ if(s!=FT_OK)
+ {
+ smDebug( -1, Low, "FTDI port error: failed to set baud rate\n");
+ goto error;
+ }
+
+ if(FT_SetLatencyTimer(h,1)!=FT_OK)//API doc says 2ms is minimum but 1 seem to work too
+ {
+ smDebug( -1, Low, "FTDI port error: failed to set latency\n");
+ goto error;
+ }
+
+ if(FT_SetFlowControl(h,FT_FLOW_NONE,0,0)!=FT_OK)
+ {
+ smDebug( -1, Low, "FTDI port error: failed to set flow control\n");
+ goto error;
+ }
+
+ if(FT_SetDataCharacteristics(h,FT_BITS_8,FT_STOP_BITS_1,FT_PARITY_NONE)!=FT_OK)
+ {
+ smDebug( -1, Low, "FTDI port error: failed to set data characteristics\n");
+ goto error;
+ }
+
+ if(FT_SetTimeouts(h,readTimeoutMs,readTimeoutMs)!=FT_OK)
+ {
+ smDebug( -1, Low, "FTDI port error: failed to set timeout\n");
+ goto error;
+ }
+
+ if(FT_Purge(h,FT_PURGE_RX|FT_PURGE_TX)!=FT_OK)
+ {
+ smDebug( -1, Low, "FTDI port error: failed to set purge\n");
+ goto error;
+ }
+
+ smDebug( -1, Mid, "FTDI port opened\n");
+ handles[i]=h;
+ return i;
+ }
+ }
+ smDebug( -1, Low, "FTDI port error: all handles taken, too many ports open\n");
+ goto error;
+ }
+ else
+ smDebug( -1, Low, "FTDI port error: FT_Open failed\n");
+
+ error:
+ FT_Close(h);
+ return -1;
+}
+
+
+smint32 d2xxPortRead(smint32 serialport_handle, unsigned char *buf, smint32 size)
+{
+ FT_STATUS s;
+ DWORD BytesReceived;
+
+ s=FT_Read(handles[serialport_handle],buf,size,&BytesReceived);
+ if(s!=FT_OK)
+ {
+ //failed
+ smDebug( -1, Low, "FTDI port error: failed to receive data from port\n");
+ }
+
+ return BytesReceived;
+}
+
+
+smint32 d2xxPortWriteByte(smint32 serialport_handle, unsigned char byte)
+{
+ unsigned char buf[1];
+ DWORD BytesWritten;
+ buf[0]=byte;
+ FT_STATUS s=FT_Write(handles[serialport_handle], buf, 1, &BytesWritten);
+
+ if(s!=FT_OK)
+ {
+ //failed
+ smDebug( -1, Low, "FTDI port error: failed to write data to port\n");
+ }
+
+ return BytesWritten;
+}
+
+
+smint32 d2xxPortWriteBuffer(smint32 serialport_handle, unsigned char *buf, smint32 size)
+{
+ DWORD BytesWritten;
+ FT_STATUS s=FT_Write(handles[serialport_handle], buf, size, &BytesWritten);
+
+ if(s!=FT_OK)
+ {
+ //failed
+ smDebug( -1, Low, "FTDI port error: failed to write data to port\n");
+ }
+
+ return BytesWritten;
+}
+
+
+void d2xxPortClose(smint32 serialport_handle)
+{
+ if(FT_Close(handles[serialport_handle])!=FT_OK)
+ {
+ //failed
+ smDebug( -1, Low, "FTDI port error: failed to close port\n");
+ }
+ else
+ handles[serialport_handle]=NULL;
+}
+
+
+
+//BUS DEVICE INFO FETCH FUNCTIONS:
+
+//Return number of bus devices found. details of each device may be consequently fetched by smGetBusDeviceDetails()
+smint d2xxGetNumberOfDetectedBuses()
+{
+ FT_STATUS ftStatus;
+ DWORD numDevs;
+ // Get the number of devices currently connected
+ ftStatus = FT_ListDevices(&numDevs,NULL,FT_LIST_NUMBER_ONLY);
+ if (ftStatus == FT_OK)
+ {
+ return numDevs;
+ }
+ else
+ {
+ return 0;
+ }
+
+ return 0;
+}
+
+smbool d2xxGetBusDeviceDetails( smint index, SM_BUS_DEVICE_INFO *info )
+{
+ DWORD devIndex = index;
+ char description[64]; // more than enough room
+ FT_STATUS ftStatus = FT_ListDevices((PVOID)devIndex, description, FT_LIST_BY_INDEX|FT_OPEN_BY_DESCRIPTION);
+ if (ftStatus == FT_OK)
+ {
+ smbool compatible=smfalse;
+ if(strncmp(description,"TTL232R",7)==0
+ || strncmp(description,"SMV2USB",7)==0
+ || strncmp(description,"USB-SMV2",8)==0
+ || strncmp(description,"FT230X",6)==0
+ || strncmp(description,"IONICUBE",8)==0
+ || strncmp(description,"ATOMI",5)==0)
+ compatible=smtrue;
+
+ info->is_simplemotion_device=compatible;
+
+ if(compatible==smtrue)
+ {
+ sprintf(info->description,"SimpleMotion USB (%s)",description);
+ sprintf(info->device_name,"FTDI%d",index);
+ }
+ else//some unknown device with FTDI chip
+ {
+ sprintf(info->description,"Unknown FTDI device (%s)",description);
+ sprintf(info->device_name,"FTDI%d",index);
+ }
+ return smtrue;
+ }
+ else
+ {
+ return smfalse;
+ }
+
+ return smfalse;
+}
+