From 0b5f1fbdd4720477f9d39bbcdec3aeb35ff2e6e7 Mon Sep 17 00:00:00 2001 From: LX3JL Date: Wed, 9 Aug 2017 13:26:01 +0200 Subject: [PATCH] ambed version 1.0.0 added amber version 1.0.0 --- ambed/WinTypes.h | 154 ++++ ambed/cambepacket.cpp | 71 ++ ambed/cambepacket.h | 67 ++ ambed/cambeserver.cpp | 125 +++ ambed/cambeserver.h | 76 ++ ambed/cbuffer.cpp | 200 +++++ ambed/cbuffer.h | 68 ++ ambed/ccallsign.cpp | 198 +++++ ambed/ccallsign.h | 83 ++ ambed/ccontroller.cpp | 373 +++++++++ ambed/ccontroller.h | 98 +++ ambed/cftdidevicedescr.cpp | 58 ++ ambed/cftdidevicedescr.h | 77 ++ ambed/cip.cpp | 91 +++ ambed/cip.h | 59 ++ ambed/cpacket.cpp | 49 ++ ambed/cpacket.h | 58 ++ ambed/cpacketqueue.cpp | 60 ++ ambed/cpacketqueue.h | 55 ++ ambed/cstream.cpp | 241 ++++++ ambed/cstream.h | 97 +++ ambed/ctimepoint.cpp | 53 ++ ambed/ctimepoint.h | 55 ++ ambed/cudpsocket.cpp | 172 +++++ ambed/cudpsocket.h | 78 ++ ambed/cusb3003interface.cpp | 185 +++++ ambed/cusb3003interface.h | 70 ++ ambed/cusb3xxxinterface.cpp | 667 ++++++++++++++++ ambed/cusb3xxxinterface.h | 134 ++++ ambed/cvocodecchannel.cpp | 109 +++ ambed/cvocodecchannel.h | 98 +++ ambed/cvocodecinterface.cpp | 95 +++ ambed/cvocodecinterface.h | 75 ++ ambed/cvocodecs.cpp | 399 ++++++++++ ambed/cvocodecs.h | 78 ++ ambed/cvoicepacket.cpp | 86 +++ ambed/cvoicepacket.h | 68 ++ ambed/ftd2xx.h | 1443 +++++++++++++++++++++++++++++++++++ ambed/main.cpp | 127 +++ ambed/main.h | 110 +++ ambed/makefile | 22 + ambed/readme | 103 +++ ambed/run | 6 + ambed/syslog.h | 96 +++ 44 files changed, 6687 insertions(+) create mode 100755 ambed/WinTypes.h create mode 100644 ambed/cambepacket.cpp create mode 100644 ambed/cambepacket.h create mode 100644 ambed/cambeserver.cpp create mode 100644 ambed/cambeserver.h create mode 100644 ambed/cbuffer.cpp create mode 100644 ambed/cbuffer.h create mode 100644 ambed/ccallsign.cpp create mode 100644 ambed/ccallsign.h create mode 100644 ambed/ccontroller.cpp create mode 100644 ambed/ccontroller.h create mode 100644 ambed/cftdidevicedescr.cpp create mode 100644 ambed/cftdidevicedescr.h create mode 100644 ambed/cip.cpp create mode 100644 ambed/cip.h create mode 100644 ambed/cpacket.cpp create mode 100644 ambed/cpacket.h create mode 100644 ambed/cpacketqueue.cpp create mode 100644 ambed/cpacketqueue.h create mode 100644 ambed/cstream.cpp create mode 100644 ambed/cstream.h create mode 100644 ambed/ctimepoint.cpp create mode 100644 ambed/ctimepoint.h create mode 100644 ambed/cudpsocket.cpp create mode 100644 ambed/cudpsocket.h create mode 100644 ambed/cusb3003interface.cpp create mode 100644 ambed/cusb3003interface.h create mode 100644 ambed/cusb3xxxinterface.cpp create mode 100644 ambed/cusb3xxxinterface.h create mode 100644 ambed/cvocodecchannel.cpp create mode 100644 ambed/cvocodecchannel.h create mode 100644 ambed/cvocodecinterface.cpp create mode 100644 ambed/cvocodecinterface.h create mode 100644 ambed/cvocodecs.cpp create mode 100644 ambed/cvocodecs.h create mode 100644 ambed/cvoicepacket.cpp create mode 100644 ambed/cvoicepacket.h create mode 100755 ambed/ftd2xx.h create mode 100644 ambed/main.cpp create mode 100644 ambed/main.h create mode 100644 ambed/makefile create mode 100644 ambed/readme create mode 100644 ambed/run create mode 100644 ambed/syslog.h diff --git a/ambed/WinTypes.h b/ambed/WinTypes.h new file mode 100755 index 0000000..88e500e --- /dev/null +++ b/ambed/WinTypes.h @@ -0,0 +1,154 @@ +#ifndef __WINDOWS_TYPES__ +#define __WINDOWS_TYPES__ + +#define WINAPI + +typedef unsigned int DWORD; +typedef unsigned int ULONG; +typedef unsigned short USHORT; +typedef unsigned short SHORT; +typedef unsigned char UCHAR; +typedef unsigned short WORD; +typedef unsigned short WCHAR; +typedef unsigned char BYTE; +typedef BYTE *LPBYTE; +typedef unsigned int BOOL; +typedef unsigned char BOOLEAN; +typedef unsigned char CHAR; +typedef BOOL *LPBOOL; +typedef UCHAR *PUCHAR; +typedef const char *LPCSTR; +typedef char *PCHAR; +typedef void *PVOID; +typedef void *HANDLE; +typedef unsigned int LONG; +typedef int INT; +typedef unsigned int UINT; +typedef char *LPSTR; +typedef char *LPTSTR; +typedef const char *LPCTSTR; +typedef DWORD *LPDWORD; +typedef WORD *LPWORD; +typedef ULONG *PULONG; +typedef LONG *LPLONG; +typedef PVOID LPVOID; +typedef void VOID; +typedef USHORT *PUSHORT; +typedef unsigned long long int ULONGLONG; + +typedef struct _OVERLAPPED { + DWORD Internal; + DWORD InternalHigh; + union { + struct{ + DWORD Offset; + DWORD OffsetHigh; + }; + PVOID Pointer; + }; + HANDLE hEvent; +} OVERLAPPED, *LPOVERLAPPED; + +typedef struct _SECURITY_ATTRIBUTES { + DWORD nLength; + LPVOID lpSecurityDescriptor; + BOOL bInheritHandle; +} SECURITY_ATTRIBUTES , *LPSECURITY_ATTRIBUTES; + +#include +// Substitute for HANDLE returned by Windows CreateEvent API. +// FT_SetEventNotification expects parameter 3 to be the address +// of one of these structures. +typedef struct _EVENT_HANDLE +{ + pthread_cond_t eCondVar; + pthread_mutex_t eMutex; + int iVar; +} EVENT_HANDLE; + +typedef struct timeval SYSTEMTIME; +typedef struct timeval FILETIME; + +// WaitForSingleObject return values. +#define WAIT_ABANDONED 0x00000080L +#define WAIT_OBJECT_0 0x00000000L +#define WAIT_TIMEOUT 0x00000102L +#define WAIT_FAILED 0xFFFFFFFF +// Special value for WaitForSingleObject dwMilliseconds parameter +#define INFINITE 0xFFFFFFFF // Infinite timeout + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef CONST +#define CONST const +#endif +// +// Modem Status Flags +// +#define MS_CTS_ON ((DWORD)0x0010) +#define MS_DSR_ON ((DWORD)0x0020) +#define MS_RING_ON ((DWORD)0x0040) +#define MS_RLSD_ON ((DWORD)0x0080) + +// +// Error Flags +// +#define CE_RXOVER 0x0001 // Receive Queue overflow +#define CE_OVERRUN 0x0002 // Receive Overrun Error +#define CE_RXPARITY 0x0004 // Receive Parity Error +#define CE_FRAME 0x0008 // Receive Framing error +#define CE_BREAK 0x0010 // Break Detected +#define CE_TXFULL 0x0100 // TX Queue is full +#define CE_PTO 0x0200 // LPTx Timeout +#define CE_IOE 0x0400 // LPTx I/O Error +#define CE_DNS 0x0800 // LPTx Device not selected +#define CE_OOP 0x1000 // LPTx Out-Of-Paper +#define CE_MODE 0x8000 // Requested mode unsupported + +// +// Events +// +#define EV_RXCHAR 0x0001 // Any Character received +#define EV_RXFLAG 0x0002 // Received certain character +#define EV_TXEMPTY 0x0004 // Transmit Queue Empty +#define EV_CTS 0x0008 // CTS changed state +#define EV_DSR 0x0010 // DSR changed state +#define EV_RLSD 0x0020 // RLSD changed state +#define EV_BREAK 0x0040 // BREAK received +#define EV_ERR 0x0080 // Line status error occurred +#define EV_RING 0x0100 // Ring signal detected +#define EV_PERR 0x0200 // Printer error occured +#define EV_RX80FULL 0x0400 // Receive buffer is 80 percent full +#define EV_EVENT1 0x0800 // Provider specific event 1 +#define EV_EVENT2 0x1000 // Provider specific event 2 + +// +// Escape Functions +// +#define SETXOFF 1 // Simulate XOFF received +#define SETXON 2 // Simulate XON received +#define SETRTS 3 // Set RTS high +#define CLRRTS 4 // Set RTS low +#define SETDTR 5 // Set DTR high +#define CLRDTR 6 // Set DTR low +#define RESETDEV 7 // Reset device if possible +#define SETBREAK 8 // Set the device break line. +#define CLRBREAK 9 // Clear the device break line. + +// +// PURGE function flags. +// +#define PURGE_TXABORT 0x0001 // Kill the pending/current writes to the comm port. +#define PURGE_RXABORT 0x0002 // Kill the pending/current reads to the comm port. +#define PURGE_TXCLEAR 0x0004 // Kill the transmit queue if there. +#define PURGE_RXCLEAR 0x0008 // Kill the typeahead buffer if there. + +#ifndef INVALID_HANDLE_VALUE +#define INVALID_HANDLE_VALUE 0xFFFFFFFF +#endif + +#endif /* __WINDOWS_TYPES__ */ diff --git a/ambed/cambepacket.cpp b/ambed/cambepacket.cpp new file mode 100644 index 0000000..e5fe175 --- /dev/null +++ b/ambed/cambepacket.cpp @@ -0,0 +1,71 @@ +// +// cambepacket.cpp +// ambed +// +// cpacketqueue.cpp +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include +#include "cambepacket.h" + + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CAmbePacket::CAmbePacket() +{ + m_uiCodec = CODEC_NONE; + ::memset(m_uiAmbe, 0, AMBE_SIZE); +} + +CAmbePacket::CAmbePacket(uint8 uiPid, uint8 uiCodec, const uint8 *Ambe) + : CPacket(uiPid) +{ + m_uiCodec = uiCodec; + ::memcpy(m_uiAmbe, Ambe, AMBE_SIZE); +} + +CAmbePacket::CAmbePacket(const CAmbePacket &packet) + : CPacket(packet) +{ + m_uiCodec = packet.m_uiCodec; + ::memcpy(m_uiAmbe, packet.m_uiAmbe, sizeof(m_uiAmbe)); +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// destructor + +CAmbePacket::~CAmbePacket() +{ +} + +//////////////////////////////////////////////////////////////////////////////////////// +// Set + +void CAmbePacket::SetAmbe(const uint8 *p) +{ + ::memcpy(m_uiAmbe, p, AMBE_SIZE); +} + diff --git a/ambed/cambepacket.h b/ambed/cambepacket.h new file mode 100644 index 0000000..13cd124 --- /dev/null +++ b/ambed/cambepacket.h @@ -0,0 +1,67 @@ +// +// cambepacket.h +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cambepacket_h +#define cambepacket_h + +#include "cpacket.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// define + + +// frame sizes +#define AMBE_SIZE 9 + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CAmbePacket : public CPacket +{ +public: + // constructors + CAmbePacket(); + CAmbePacket(uint8, uint8, const uint8 *); + CAmbePacket(const CAmbePacket &); + + // destructor + virtual ~CAmbePacket(); + + // get + uint8 GetCodec(void) const { return m_uiCodec; } + uint8 *GetAmbe(void) { return m_uiAmbe; } + int GetAmbeSize(void) const { return AMBE_SIZE; } + + // set + void SetCodec(uint8 c) { m_uiCodec = c; } + void SetAmbe(const uint8 *); + +protected: + // data + uint8 m_uiCodec; + uint8 m_uiAmbe[AMBE_SIZE]; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cambepacket_h */ diff --git a/ambed/cambeserver.cpp b/ambed/cambeserver.cpp new file mode 100644 index 0000000..9ce1da2 --- /dev/null +++ b/ambed/cambeserver.cpp @@ -0,0 +1,125 @@ +// +// cambeserver.cpp +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include "ctimepoint.h" +#include "ccontroller.h" +#include "cvocodecs.h" +#include "cambeserver.h" + +//////////////////////////////////////////////////////////////////////////////////////// + +CAmbeServer g_AmbeServer; + + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CAmbeServer::CAmbeServer() +{ + m_bStopThreads = false; + m_pThread = NULL; +#ifdef DEBUG_DUMPFILE + m_DebugFile.open("/Users/jeanluc/Desktop/ambed.txt"); +#endif +} + +//////////////////////////////////////////////////////////////////////////////////////// +// destructor + +CAmbeServer::~CAmbeServer() +{ + m_bStopThreads = true; + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + } +#ifdef DEBUG_DUMPFILE + m_DebugFile.close(); +#endif +} + +//////////////////////////////////////////////////////////////////////////////////////// +// operation + +bool CAmbeServer::Start(void) +{ + bool ok = true; + + // init interfaces & controller + std::cout << "Initializing vocodecs:" << std::endl; + ok &= g_Vocodecs.Init(); + std::cout << std::endl; + std::cout << "Initializing controller" << std::endl; + ok &= m_Controller.Init(); + std::cout << std::endl; + + // if ok, start threads + if ( ok ) + { + // + m_pThread = new std::thread(CAmbeServer::Thread, this); + } + + // done + return ok; +} + +void CAmbeServer::Stop(void) +{ + // stop controller + m_Controller.Close(); + + // stop & delete all threads + m_bStopThreads = true; + + // stop & delete report threads + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + m_pThread = NULL; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// thread + +void CAmbeServer::Thread(CAmbeServer *This) +{ + while ( !This->m_bStopThreads ) + { + This->Task(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// task + +void CAmbeServer::Task(void) +{ + // and wait a bit + CTimePoint::TaskSleepFor(10000); +} diff --git a/ambed/cambeserver.h b/ambed/cambeserver.h new file mode 100644 index 0000000..7ba77c2 --- /dev/null +++ b/ambed/cambeserver.h @@ -0,0 +1,76 @@ +// +// cambeserver.h +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cambeserver_h +#define cambeserver_h + +#include "ccontroller.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CAmbeServer +{ +public: + // constructors + CAmbeServer(); + + // destructor + virtual ~CAmbeServer(); + + // operation + bool Start(void); + void Stop(void); + + // task + static void Thread(CAmbeServer *); + void Task(void); + + // get + const CIp &GetListenIp(void) const { return m_Controller.GetListenIp(); } + + // set + void SetListenIp(const CIp &ip) { m_Controller.SetListenIp(ip); } + + + // operator + //bool operator ==(const CIp &) const; + //operator const char *() const; + +protected: + // objects + CController m_Controller; + + // threads + bool m_bStopThreads; + std::thread *m_pThread; + +public: +#ifdef DEBUG_DUMPFILE + std::ofstream m_DebugFile; +#endif +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cambeserver_h */ diff --git a/ambed/cbuffer.cpp b/ambed/cbuffer.cpp new file mode 100644 index 0000000..550c3df --- /dev/null +++ b/ambed/cbuffer.cpp @@ -0,0 +1,200 @@ +// +// cbuffer.cpp +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 02/11/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include +#include "cbuffer.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CBuffer::CBuffer(uint8 *buffer, int len) +{ + resize(len); + ::memcpy(data(), buffer, len); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// set + +void CBuffer::Set(uint8 *buffer, int len) +{ + resize(len); + ::memcpy(data(), buffer, len); +} + +void CBuffer::Set(const char *sz) +{ + resize(::strlen(sz)+1); + ::strcpy((char *)data(), sz); +} + +void CBuffer::Append(uint8 *buffer, int len) +{ + int n = (int)size(); + resize(n+len); + ::memcpy(&(data()[n]), buffer, len); +} + +void CBuffer::Append(uint8 ui, int len) +{ + int n = (int)size(); + resize(n+len); + ::memset(&(data()[n]), ui, len); +} + +void CBuffer::Append(uint8 ui) +{ + int n = (int)size(); + resize(n+sizeof(uint8)); + ::memcpy(&(data()[n]), &ui, sizeof(uint8)); +} + +void CBuffer::Append(uint16 ui) +{ + int n = (int)size(); + resize(n+sizeof(uint16)); + ::memcpy(&(data()[n]), &ui, sizeof(uint16)); +} + +void CBuffer::Append(uint32 ui) +{ + int n = (int)size(); + resize(n+sizeof(uint32)); + ::memcpy(&(data()[n]), &ui, sizeof(uint32)); +} + +void CBuffer::Append(const char *sz) +{ + Append((uint8 *)sz, (int)strlen(sz)); + Append((uint8)0x00); +} + +void CBuffer::ReplaceAt(int i, uint8 ui) +{ + if ( size() < (i+sizeof(uint8)) ) + { + resize(i+sizeof(uint8)); + } + *(uint8 *)(&(data()[i])) = ui; +} + +void CBuffer::ReplaceAt(int i, uint16 ui) +{ + if ( size() < (i+sizeof(uint16)) ) + { + resize(i+sizeof(uint16)); + } + *(uint16 *)(&(data()[i])) = ui; +} + +void CBuffer::ReplaceAt(int i, uint32 ui) +{ + if ( size() < (i+sizeof(uint32)) ) + { + resize(i+sizeof(uint32)); + } + *(uint32 *)(&(data()[i])) = ui; +} + +void CBuffer::ReplaceAt(int i, const uint8 *ptr, int len) +{ + if ( size() < (i+len) ) + { + resize(i+len); + } + ::memcpy(&(data()[i]), ptr, len); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// operation + +int CBuffer::Compare(uint8 *buffer, int len) const +{ + int result = -1; + if ( size() >= len ) + { + result = ::memcmp(data(), buffer, len); + } + return result; +} + +int CBuffer::Compare(uint8 *buffer, int off, int len) const +{ + int result = -1; + if ( size() >= (off+len) ) + { + result = ::memcmp(&(data()[off]), buffer, len); + } + return result; +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// operator + +bool CBuffer::operator ==(const CBuffer &Buffer) const +{ + if ( size() == Buffer.size() ) + { + return (::memcmp((const char *)data(), (const char *)Buffer.data(), size()) == 0); + } + return false; +} + +bool CBuffer::operator ==(const char *sz) const +{ + if ( size() == ::strlen(sz) ) + { + return (::memcmp((const char *)data(), sz, size()) == 0); + } + return false; +} + +CBuffer::operator const char *() const +{ + return (const char *)data(); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// debug + +void CBuffer::DebugDump(std::ofstream &debugout) +{ + for ( int i = 0; i < size(); i++ ) + { + char sz[16]; + sprintf(sz, "%02X", data()[i]); + debugout << sz; + if ( i == size()-1 ) + { + debugout << std::endl; + } + else + { + debugout << ','; + } + } +} + diff --git a/ambed/cbuffer.h b/ambed/cbuffer.h new file mode 100644 index 0000000..5762a85 --- /dev/null +++ b/ambed/cbuffer.h @@ -0,0 +1,68 @@ +// +// cbuffer.h +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 02/11/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cbuffer_h +#define cbuffer_h + +//////////////////////////////////////////////////////////////////////////////////////// + +class CBuffer : public std::vector +{ +public: + // constructor + CBuffer() {}; + CBuffer(uint8 *, int); + + // destructor + virtual ~CBuffer() {}; + + // set + void Set(uint8 *, int); + void Set(const char *); + void Append(uint8 *, int); + void Append(uint8, int); + void Append(uint8); + void Append(uint16); + void Append(uint32); + void Append(const char *); + void ReplaceAt(int, uint8); + void ReplaceAt(int, uint16); + void ReplaceAt(int, uint32); + void ReplaceAt(int, const uint8 *, int); + + // operation + int Compare(uint8 *, int) const; + int Compare(uint8 *, int, int) const; + + // operator + bool operator ==(const CBuffer &) const; + bool operator ==(const char *) const; + operator const char *() const; + + // debug + void DebugDump(std::ofstream &); +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cbuffer_h */ diff --git a/ambed/ccallsign.cpp b/ambed/ccallsign.cpp new file mode 100644 index 0000000..aa81c9d --- /dev/null +++ b/ambed/ccallsign.cpp @@ -0,0 +1,198 @@ +// +// ccallsign.cpp +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include +#include +#include "ccallsign.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// constructors + +CCallsign::CCallsign() +{ + // blank all + ::memset(m_Callsign, ' ', sizeof(m_Callsign)); +} + +CCallsign::CCallsign(const char *sz) +{ + ::memset(m_Callsign, ' ', sizeof(m_Callsign)); + ::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign))); +} + +CCallsign::CCallsign(const CCallsign &callsign) +{ + ::memcpy(m_Callsign, callsign.m_Callsign, sizeof(m_Callsign)); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// status + +bool CCallsign::IsValid(void) const +{ + bool valid = true; + int i; + + // callsign + // first 3 chars are letter or number but cannot be all number + int iNum = 0; + for ( i = 0; i < 3; i++ ) + { + valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]); + if ( IsNumber(m_Callsign[i]) ) + { + iNum++; + } + } + valid &= (iNum < 3); + // all remaining char are letter, number or space + for ( ; i < CALLSIGN_LEN; i++) + { + valid &= IsLetter(m_Callsign[i]) || IsNumber(m_Callsign[i]) || IsSpace(m_Callsign[i]); + } + + // done + return valid; +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// set + +void CCallsign::SetCallsign(const char *sz) +{ + // set callsign + ::memset(m_Callsign, ' ', sizeof(m_Callsign)); + ::memcpy(m_Callsign, sz, MIN(strlen(sz), sizeof(m_Callsign))); +} + +void CCallsign::SetCallsign(const uint8 *buffer, int len) +{ + // set callsign + ::memset(m_Callsign, ' ', sizeof(m_Callsign)); + ::memcpy(m_Callsign, buffer, MIN(len, sizeof(m_Callsign))); + for ( int i = 0; i < sizeof(m_Callsign); i++ ) + { + if ( m_Callsign[i] == 0 ) + { + m_Callsign[i] = ' '; + } + } +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// modify + +void CCallsign::PatchCallsign(int off, const uint8 *patch, int len) +{ + if ( off < sizeof(m_Callsign) ) + { + ::memcpy(m_Callsign, patch, MIN(len, sizeof(m_Callsign) - off)); + } +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// get + +void CCallsign::GetCallsign(uint8 *buffer) const +{ + ::memcpy(buffer, m_Callsign, sizeof(m_Callsign)); +} + +void CCallsign::GetCallsignString(char *sz) const +{ + int i; + for ( i = 0; (i < sizeof(m_Callsign)) && (m_Callsign[i] != ' '); i++ ) + { + sz[i] = m_Callsign[i]; + } + sz[i] = 0; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// compare + +bool CCallsign::HasSameCallsign(const CCallsign &Callsign) const +{ + return (::memcmp(m_Callsign, Callsign.m_Callsign, sizeof(m_Callsign)) == 0); +} + +bool CCallsign::HasSameCallsignWithWildcard(const CCallsign &callsign) const +{ + bool same = true; + bool done = false; + + for ( int i = 0; (i < sizeof(m_Callsign)) && same && !done; i++ ) + { + if ( !(done = ((m_Callsign[i] == '*') || (callsign[i] == '*'))) ) + { + same &= (m_Callsign[i] == callsign[i]); + } + } + return same; +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// operators + +bool CCallsign::operator ==(const CCallsign &callsign) const +{ + return (::memcmp(callsign.m_Callsign, m_Callsign, sizeof(m_Callsign)) == 0); +} + +CCallsign::operator const char *() const +{ + char *sz = (char *)(const char *)m_sz; + + // empty + ::memset(sz, 0, sizeof(m_sz)); + // callsign + sz[CALLSIGN_LEN] = 0; + ::memcpy(sz, m_Callsign, sizeof(m_Callsign)); + + // done + return m_sz; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// helper + +bool CCallsign::IsNumber(char c) const +{ + return ((c >= '0') && (c <= '9')); +} + +bool CCallsign::IsLetter(char c) const +{ + return ((c >= 'A') && (c <= 'Z')); +} + +bool CCallsign::IsSpace(char c) const +{ + return (c == ' '); +} diff --git a/ambed/ccallsign.h b/ambed/ccallsign.h new file mode 100644 index 0000000..5ca6c35 --- /dev/null +++ b/ambed/ccallsign.h @@ -0,0 +1,83 @@ +// +// ccallsign.h +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef ccallsign_h +#define ccallsign_h + +//////////////////////////////////////////////////////////////////////////////////////// +// define + +#define CALLSIGN_LEN 8 + + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CCallsign +{ +public: + // contructors + CCallsign(); + CCallsign(const char *); + CCallsign(const CCallsign &); + + // destructor + virtual ~CCallsign() {}; + + // status + bool IsValid(void) const; + + // set + void SetCallsign(const char *); + void SetCallsign(const uint8 *, int); + + // modify + void PatchCallsign(int, const uint8 *, int); + + // get + void GetCallsign(uint8 *) const; + void GetCallsignString(char *) const; + + // compare + bool HasSameCallsign(const CCallsign &) const; + bool HasSameCallsignWithWildcard(const CCallsign &) const; + + // operators + bool operator ==(const CCallsign &) const; + operator const char *() const; + +protected: + // helper + bool IsNumber(char) const; + bool IsLetter(char) const; + bool IsSpace(char) const; + +protected: + // data + char m_Callsign[CALLSIGN_LEN]; + char m_sz[CALLSIGN_LEN+1]; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* ccallsign_h */ diff --git a/ambed/ccontroller.cpp b/ambed/ccontroller.cpp new file mode 100644 index 0000000..d6039e8 --- /dev/null +++ b/ambed/ccontroller.cpp @@ -0,0 +1,373 @@ +// +// ccontroller.cpp +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include "ctimepoint.h" +#include "cvocodecs.h" +#include "ccontroller.h" + + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CController::CController() +{ + m_bStopThread = false; + m_pThread = NULL; + m_Ip = CIp("127.0.0.1"); + m_uiLastStreamId = 0; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// destructor + +CController::~CController() +{ + // close socket + m_Socket.Close(); + + // close all streams + m_Mutex.lock(); + { + for ( int i = 0; i < m_Streams.size(); i++ ) + { + delete m_Streams[i]; + } + m_Streams.clear(); + + } + + m_Mutex.unlock(); + m_bStopThread = true; + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// initialization + +bool CController::Init(void) +{ + bool ok; + + // reset stop flag + m_bStopThread = false; + + // create our socket + ok = m_Socket.Open(m_Ip, TRANSCODER_PORT); + if ( ok ) + { + // start thread; + m_pThread = new std::thread(CController::Thread, this); + } + else + { + std::cout << "Error opening socket on port UDP" << TRANSCODER_PORT << " on ip " << m_Ip << std::endl; + } + + // done + return true; +} + +void CController::Close(void) +{ + m_bStopThread = true; + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + m_pThread = NULL; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// thread + +void CController::Thread(CController *This) +{ + while ( !This->m_bStopThread ) + { + This->Task(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// task + +void CController::Task(void) +{ + CBuffer Buffer; + CIp Ip; + CCallsign Callsign; + uint8 CodecIn; + uint8 CodecOut; + uint16 StreamId; + CStream *Stream; + + // anything coming in from codec client ? + if ( m_Socket.Receive(&Buffer, &Ip, 20) != -1 ) + { + // crack packet + if ( IsValidOpenstreamPacket(Buffer, &Callsign, &CodecIn, &CodecOut) ) + { + std::cout << "Stream Open from " << Callsign << std::endl; + + // try create the stream + Stream = OpenStream(Callsign, Ip, CodecIn, CodecOut); + + // send back details + if ( Stream != NULL ) + { + EncodeStreamDescrPacket(&Buffer, *Stream); + } + else + { + EncodeNoStreamAvailablePacket(&Buffer); + } + m_Socket.Send(Buffer, Ip); + } + else if ( IsValidClosestreamPacket(Buffer, &StreamId) ) + { + // close the stream + CloseStream(StreamId); + + std::cout << "Stream " << (int)StreamId << " closed" << std::endl; + } + else if ( IsValidKeepAlivePacket(Buffer, &Callsign) ) + { + //std::cout << "ping - " << Callsign << std::endl; + // pong back + EncodeKeepAlivePacket(&Buffer); + m_Socket.Send(Buffer, Ip); + } + } + + + // HandleTimout/keepalive + bool timeout; + do + { + // init loop stuffs + timeout = false; + CStream *stream = NULL; + + // any inactive streams? + Lock(); + { + for ( int i = 0; (i < m_Streams.size()) && !timeout; i++ ) + { + if ( !(m_Streams[i]->IsActive()) ) + { + timeout = true; + stream = m_Streams[i]; + std::cout << "Stream " << (int)m_Streams[i]->GetId() << " activity timeout " << std::endl; + } + } + } + Unlock(); + + // if any streams timeout, close it + // this cannot be done in above loop as it suppress it from array + if ( timeout ) + { + CloseStream(stream); + } + } while (timeout); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// streams management + +CStream *CController::OpenStream(const CCallsign &Callsign, const CIp &Ip, uint8 CodecIn, uint8 CodecOut) +{ + CStream *stream = NULL; + + // create a new stream + m_uiLastStreamId = (m_uiLastStreamId + 1); + m_uiLastStreamId = (m_uiLastStreamId == NB_MAX_STREAMS+1) ? 1 : m_uiLastStreamId; + stream = new CStream(m_uiLastStreamId, Callsign, Ip, CodecIn, CodecOut); + if ( stream->Init(TRANSCODER_PORT+m_uiLastStreamId) ) + { + std::cout << "Opened stream " << m_uiLastStreamId << std::endl; + // and store it + Lock(); + m_Streams.push_back(stream); + Unlock(); + } + else + { + delete stream; + stream = NULL; + } + + // done + return stream; +} + +void CController::CloseStream(CStream *stream) +{ + Lock(); + { + // look for the stream + bool found = false; + for ( int i = 0; (i < m_Streams.size()) && !found; i++ ) + { + // compare object pointers + if ( (m_Streams[i]) == stream ) + { + // close it + m_Streams[i]->Close(); + // remove it + //std::cout << "Stream " << m_Streams[i]->GetId() << " removed" << std::endl; + delete m_Streams[i]; + m_Streams.erase(m_Streams.begin()+i); + found = true; + } + } + } + Unlock(); +} + +void CController::CloseStream(uint16 StreamId) +{ + Lock(); + { + // look for the stream + bool found = false; + for ( int i = 0; (i < m_Streams.size()) && !found; i++ ) + { + // compare object pointers + if ( (m_Streams[i]->GetId()) == StreamId ) + { + // close it + m_Streams[i]->Close(); + // remove it + //std::cout << "Stream " << m_Streams[i]->GetId() << " removed" << std::endl; + delete m_Streams[i]; + m_Streams.erase(m_Streams.begin()+i); + found = true; + } + } + } + Unlock(); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// packet decoding helpers + +bool CController::IsValidKeepAlivePacket(const CBuffer &Buffer, CCallsign *Callsign) +{ + uint8 tag[] = { 'A','M','B','E','D','P','I','N','G' }; + + bool valid = false; + if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + // get callsign here + Callsign->SetCallsign(&(Buffer.data()[9]), 8); + valid = Callsign->IsValid(); + } + return valid; +} + +bool CController::IsValidOpenstreamPacket(const CBuffer &Buffer, CCallsign *Callsign, uint8 *CodecIn, uint8 *CodecOut) +{ + uint8 tag[] = { 'A','M','B','E','D','O','S' }; + + bool valid = false; + if ( (Buffer.size() == 17) && (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + // get callsign here + Callsign->SetCallsign(&(Buffer.data()[7]), 8); + *CodecIn = Buffer.data()[15]; + *CodecOut = Buffer.data()[16]; + + // valid ? + valid = Callsign->IsValid() && IsValidCodecIn(*CodecIn) && IsValidCodecOut(*CodecOut); + } + return valid; +} + +bool CController::IsValidClosestreamPacket(const CBuffer &Buffer, uint16 *StreamId) +{ + uint8 tag[] = { 'A','M','B','E','D','C','S' }; + + bool valid = false; + if ( /*(Buffer.size() == 16) &&*/ (Buffer.Compare(tag, sizeof(tag)) == 0) ) + { + // get stream id + *StreamId = *(uint16 *)(&Buffer.data()[7]); + valid = true; + } + return valid; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// packet encoding helpers + +void CController::EncodeKeepAlivePacket(CBuffer *Buffer) +{ + uint8 tag[] = { 'A','M','B','E','D','P','O','N','G' }; + + Buffer->Set(tag, sizeof(tag)); +} + +void CController::EncodeStreamDescrPacket(CBuffer *Buffer, const CStream &Stream) +{ + uint8 tag[] = { 'A','M','B','E','D','S','T','D' }; + + Buffer->Set(tag, sizeof(tag)); + // id + Buffer->Append((uint16)Stream.GetId()); + // port + Buffer->Append((uint16)Stream.GetPort()); + // codecin + Buffer->Append((uint8)Stream.GetCodecIn()); + // codecout + Buffer->Append((uint8)Stream.GetCodecOut()); +} + +void CController::EncodeNoStreamAvailablePacket(CBuffer *Buffer) +{ + uint8 tag[] = { 'A','M','B','E','D','B','U','S','Y' }; + + Buffer->Set(tag, sizeof(tag)); +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// codec helpers + +bool CController::IsValidCodecIn(uint8 codec) +{ + return ((codec == CODEC_AMBEPLUS) || (codec == CODEC_AMBE2PLUS) ); +} + +bool CController::IsValidCodecOut(uint8 codec) +{ + return ((codec == CODEC_AMBEPLUS) || (codec == CODEC_AMBE2PLUS) ); +} + diff --git a/ambed/ccontroller.h b/ambed/ccontroller.h new file mode 100644 index 0000000..c39fb60 --- /dev/null +++ b/ambed/ccontroller.h @@ -0,0 +1,98 @@ +// +// ccontroller.h +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef ccontroller_h +#define ccontroller_h + +#include "ccallsign.h" +#include "cstream.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CController +{ +public: + // constructors + CController(); + + // destructor + virtual ~CController(); + + // initialization + bool Init(void); + void Close(void); + + // locks + void Lock(void) { m_Mutex.lock(); } + void Unlock(void) { m_Mutex.unlock(); } + + // get + const CIp &GetListenIp(void) const { return (const CIp &)m_Ip; } + + // set + void SetListenIp(const CIp &ip) { m_Ip = ip; } + + // streams management + CStream *OpenStream(const CCallsign &, const CIp &, uint8, uint8); + void CloseStream(CStream *); + void CloseStream(uint16); + + // task + static void Thread(CController *); + void Task(void); + +protected: + // packet decoding helpers + bool IsValidKeepAlivePacket(const CBuffer &, CCallsign *); + bool IsValidOpenstreamPacket(const CBuffer &, CCallsign *, uint8 *, uint8 *); + bool IsValidClosestreamPacket(const CBuffer &, uint16 *); + + // packet encoding helpers + void EncodeKeepAlivePacket(CBuffer *); + void EncodeStreamDescrPacket(CBuffer *, const CStream &); + void EncodeNoStreamAvailablePacket(CBuffer *); + + // codec helpers + bool IsValidCodecIn(uint8); + bool IsValidCodecOut(uint8); + +protected: + // control socket + CIp m_Ip; + CUdpSocket m_Socket; + + // streams + uint16 m_uiLastStreamId; + std::mutex m_Mutex; + std::vector m_Streams; + + // thread + bool m_bStopThread; + std::thread *m_pThread; + +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* ccontroller_h */ diff --git a/ambed/cftdidevicedescr.cpp b/ambed/cftdidevicedescr.cpp new file mode 100644 index 0000000..71cbfbf --- /dev/null +++ b/ambed/cftdidevicedescr.cpp @@ -0,0 +1,58 @@ +// +// cftdidevicedescr.cpp +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 02/06/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include +#include "cftdidevicedescr.h" + + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CFtdiDeviceDescr::CFtdiDeviceDescr(void) +{ + m_bUsed = false; + m_uiVid = 0; + m_uiPid = 0; + ::memset(m_szDescription, 0, sizeof(m_szDescription)); + ::memset(m_szSerial, 0, sizeof(m_szSerial)); +} + +CFtdiDeviceDescr::CFtdiDeviceDescr(uint32 uiVid, uint32 uiPid, const char *szDescription, const char *szSerial) +{ + m_bUsed = false; + m_uiVid = uiVid; + m_uiPid = uiPid; + ::strcpy(m_szDescription, szDescription); + ::strcpy(m_szSerial, szSerial); +} + +CFtdiDeviceDescr::CFtdiDeviceDescr(const CFtdiDeviceDescr &descr) +{ + m_bUsed = descr.m_bUsed; + m_uiVid = descr.m_uiVid; + m_uiPid = descr.m_uiPid; + ::memcpy(m_szDescription, descr.m_szDescription, sizeof(m_szDescription)); + ::memcpy(m_szSerial, descr.m_szSerial, sizeof(m_szSerial)); +} diff --git a/ambed/cftdidevicedescr.h b/ambed/cftdidevicedescr.h new file mode 100644 index 0000000..acbc1bd --- /dev/null +++ b/ambed/cftdidevicedescr.h @@ -0,0 +1,77 @@ +// +// cftdidevicedescr.h +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 02/06/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cftdidevicedescr_h +#define cftdidevicedescr_h + +#include +#include "ftd2xx.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// define + +#define FTDI_MAX_STRINGLENGTH 256 + + + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CFtdiDeviceDescr +{ +public: + // constructors + CFtdiDeviceDescr(void); + CFtdiDeviceDescr(uint32, uint32, const char *, const char *); + CFtdiDeviceDescr(const CFtdiDeviceDescr &); + + // destructor + virtual ~CFtdiDeviceDescr() {} + + // get + bool IsUsed(void) const {return m_bUsed; } + bool IsUsb3000(void) const { return (::strcmp(m_szDescription, "USB-3000") == 0); } + bool IsUsb3003(void) const { return (::strcmp(m_szDescription, "USB-3003") == 0); } + bool IsUsb3012(void) const { return (::strcmp(m_szDescription, "USB-3012 A") == 0); } + uint32 GetVid(void) const { return m_uiVid; } + uint32 GetPid(void) const { return m_uiPid; } + const char *GetDescription(void) const { return m_szDescription; } + const char *GetSerialNumber(void) const { return m_szSerial; } + + // set + void SetUsed(bool used) { m_bUsed = used; } + +protected: + // status + bool m_bUsed; + + // data + uint32 m_uiVid; + uint32 m_uiPid; + char m_szDescription[FTDI_MAX_STRINGLENGTH]; + char m_szSerial[FTDI_MAX_STRINGLENGTH]; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cftdidevicedescr_h */ diff --git a/ambed/cip.cpp b/ambed/cip.cpp new file mode 100644 index 0000000..5cec9b5 --- /dev/null +++ b/ambed/cip.cpp @@ -0,0 +1,91 @@ +// +// cip.cpp +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include +#include "cip.h" + +#include + +//////////////////////////////////////////////////////////////////////////////////////// +// constructors + +CIp::CIp() +{ + ::memset(&m_Addr, 0, sizeof(m_Addr)); + m_Addr.sin_family = AF_INET; +} + +CIp::CIp(const char *sz) +{ + ::memset(&m_Addr, 0, sizeof(m_Addr)); + m_Addr.sin_family = AF_INET; + // try xxx.xxx.xxx.xxxx first + m_Addr.sin_addr.s_addr = inet_addr(sz); + if ( m_Addr.sin_addr.s_addr == INADDR_NONE ) + { + // otherwise try to resolve via dns + hostent *record = gethostbyname(sz); + if( record != NULL ) + { + m_Addr.sin_addr.s_addr = ((in_addr * )record->h_addr)->s_addr; + } + } +} + +CIp::CIp(const struct sockaddr_in *sa) +{ + ::memcpy(&m_Addr, sa, sizeof(m_Addr)); +} + + +CIp::CIp(const CIp &ip) +{ + ::memcpy(&m_Addr, &ip.m_Addr, sizeof(m_Addr)); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// set + +void CIp::SetSockAddr(struct sockaddr_in *sa) +{ + ::memcpy(&m_Addr, sa, sizeof(m_Addr)); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// operator + +bool CIp::operator ==(const CIp &ip) const +{ + return ( (ip.m_Addr.sin_family == m_Addr.sin_family) && + (ip.m_Addr.sin_addr.s_addr == m_Addr.sin_addr.s_addr) && + (ip.m_Addr.sin_port == m_Addr.sin_port)) ; +} + +CIp::operator const char *() const +{ + return ::inet_ntoa(m_Addr.sin_addr); +} + + diff --git a/ambed/cip.h b/ambed/cip.h new file mode 100644 index 0000000..3a65fd6 --- /dev/null +++ b/ambed/cip.h @@ -0,0 +1,59 @@ +// +// cip.h +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cip_h +#define cip_h + + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CIp +{ +public: + // constructors + CIp(); + //CIp(uint8, uint8, uint8, uint8); + CIp(const struct sockaddr_in *); + CIp(const char *); + CIp(const CIp &); + + // destructor + virtual ~CIp() {}; + + // sockaddr + void SetSockAddr(struct sockaddr_in *); + struct sockaddr_in *GetSockAddr(void) { return &m_Addr; } + + // operator + bool operator ==(const CIp &) const; + operator const char *() const; + +protected: + // data + struct sockaddr_in m_Addr; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cip_h */ diff --git a/ambed/cpacket.cpp b/ambed/cpacket.cpp new file mode 100644 index 0000000..a661984 --- /dev/null +++ b/ambed/cpacket.cpp @@ -0,0 +1,49 @@ +// +// cpacket.cpp +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include "cpacket.h" + + +//////////////////////////////////////////////////////////////////////////////////////// +// constructors + +CPacket::CPacket() +{ + m_iCh = 0; + m_uiPid = 0; +}; + +CPacket::CPacket(uint8 uiPid) +{ + m_iCh = 0; + m_uiPid = uiPid; +} + +CPacket::CPacket(const CPacket &packet) +{ + m_iCh = packet.m_iCh; + m_uiPid = packet.m_uiPid; +}; + diff --git a/ambed/cpacket.h b/ambed/cpacket.h new file mode 100644 index 0000000..cd30d6a --- /dev/null +++ b/ambed/cpacket.h @@ -0,0 +1,58 @@ +// +// cpacket.h +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 24/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cpacket_h +#define cpacket_h + + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CPacket +{ +public: + // constructors + CPacket(); + CPacket(uint8); + CPacket(const CPacket &); + + // destructor + virtual ~CPacket() {}; + + // get + int GetChannel(void) const { return m_iCh; } + uint8 GetPid(void) const { return m_uiPid; } + + // set + void SetChannel(int i) { m_iCh = i; } + void SetPid(uint8 ui) { m_uiPid = ui; } + +protected: + // data + int m_iCh; + uint8 m_uiPid; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cpacket_h */ diff --git a/ambed/cpacketqueue.cpp b/ambed/cpacketqueue.cpp new file mode 100644 index 0000000..ff14dcb --- /dev/null +++ b/ambed/cpacketqueue.cpp @@ -0,0 +1,60 @@ +// +// cpacketqueue.cpp +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include "cpacketqueue.h" + + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CPacketQueue::CPacketQueue() +{ +} + +//////////////////////////////////////////////////////////////////////////////////////// +// destructor + +CPacketQueue::~CPacketQueue() +{ + // empty codec queue + while ( !empty() ) + { + delete front(); + pop(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// purge + +void CPacketQueue::Purge(void) +{ + // this assume queue is already locked + while ( !empty() ) + { + delete front(); + pop(); + } +} diff --git a/ambed/cpacketqueue.h b/ambed/cpacketqueue.h new file mode 100644 index 0000000..cb7144d --- /dev/null +++ b/ambed/cpacketqueue.h @@ -0,0 +1,55 @@ +// +// cpacketqueue.h +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 24/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cpacketqueue_h +#define cpacketqueue_h + +#include "cpacket.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CPacketQueue : public std::queue +{ +public: + // constructor + CPacketQueue(); + + // destructor + ~CPacketQueue(); + + // lock + void Lock() { m_Mutex.lock(); } + void Unlock() { m_Mutex.unlock(); } + + // purge + void Purge(void); + +protected: + // status + std::mutex m_Mutex; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cpacketqueue_h */ diff --git a/ambed/cstream.cpp b/ambed/cstream.cpp new file mode 100644 index 0000000..feb3cac --- /dev/null +++ b/ambed/cstream.cpp @@ -0,0 +1,241 @@ +// +// cstream.cpp +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include +#include "ctimepoint.h" +#include "cambeserver.h" +#include "cvocodecs.h" +#include "cambepacket.h" +#include "cstream.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// define + +#define AMBE_FRAME_SIZE 9 + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CStream::CStream() +{ + m_uiId = 0; + m_uiPort = 0; + m_bStopThread = false; + m_pThread = NULL; + m_VocodecChannel = NULL; + m_LastActivity.Now(); + m_iTotalPackets = 0; + m_iLostPackets = 0; +} + +CStream::CStream(uint16 uiId, const CCallsign &Callsign, const CIp &Ip, uint8 uiCodecIn, uint8 uiCodecOut) +{ + m_uiId = uiId; + m_Callsign = Callsign; + m_Ip = Ip; + m_uiPort = 0; + m_uiCodecIn = uiCodecIn; + m_uiCodecOut = uiCodecOut; + m_bStopThread = false; + m_pThread = NULL; + m_VocodecChannel = NULL; + m_LastActivity.Now(); + m_iTotalPackets = 0; + m_iLostPackets = 0; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// destructor + +CStream::~CStream() +{ + m_Socket.Close(); + if ( m_VocodecChannel != NULL ) + { + g_Vocodecs.CloseChannel(m_VocodecChannel); + m_VocodecChannel = NULL; + } + + m_bStopThread = true; + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// initialization + +bool CStream::Init(uint16 uiPort) +{ + bool ok; + + // reset stop flag + m_bStopThread = false; + + // create our socket + ok = m_Socket.Open(g_AmbeServer.GetListenIp(), uiPort); + if ( ok ) + { + // open the vocodecchannel + ok &= ((m_VocodecChannel = g_Vocodecs.OpenChannel(m_uiCodecIn, m_uiCodecOut)) != NULL); + + if ( ok ) + { + // store port + m_uiPort = uiPort; + + // start thread; + m_pThread = new std::thread(CStream::Thread, this); + + // init timeout system + m_LastActivity.Now(); + m_iTotalPackets = 0; + m_iLostPackets = 0; + + } + else + { + std::cout << "Error opening stream : no suitable channel available" << std::endl; + } + } + else + { + std::cout << "Error opening socket on port UDP" << uiPort << " on ip " << m_Ip << std::endl; + } + + // done + return ok; + +} + +void CStream::Close(void) +{ + // close everything + m_Socket.Close(); + if ( m_VocodecChannel != NULL ) + { + m_VocodecChannel->Close(); + } + + m_bStopThread = true; + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + m_pThread = NULL; + } + + // report + std::cout << m_iLostPackets << " of " << m_iTotalPackets << " packets lost" << std::endl; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// thread + +void CStream::Thread(CStream *This) +{ + while ( !This->m_bStopThread ) + { + This->Task(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// task + +void CStream::Task(void) +{ + CBuffer Buffer; + static CIp Ip; + uint8 uiPid; + uint8 Ambe[AMBE_FRAME_SIZE]; + CAmbePacket *packet; + CPacketQueue *queue; + + // anything coming in from codec client ? + if ( m_Socket.Receive(&Buffer, &Ip, 1) != -1 ) + { + // crack packet + if ( IsValidDvFramePacket(Buffer, &uiPid, Ambe) ) + { + // transcode AMBE here + m_LastActivity.Now(); + m_iTotalPackets++; + + // post packet to VocoderChannel + packet = new CAmbePacket(uiPid, m_uiCodecIn, Ambe); + queue = m_VocodecChannel->GetPacketQueueIn(); + queue->push(packet); + m_VocodecChannel->ReleasePacketQueueIn(); + } + } + + // anything in our queue ? + queue = m_VocodecChannel->GetPacketQueueOut(); + while ( !queue->empty() ) + { + // get the packet + packet = (CAmbePacket *)queue->front(); + queue->pop(); + // send it to client + EncodeDvFramePacket(&Buffer, packet->GetPid(), packet->GetAmbe()); + m_Socket.Send(Buffer, Ip, m_uiPort); + // and done + delete packet; + } + m_VocodecChannel->ReleasePacketQueueOut(); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// packet decoding helpers + +bool CStream::IsValidDvFramePacket(const CBuffer &Buffer, uint8 *pid, uint8 *ambe) +{ + bool valid = false; + + if ( Buffer.size() == 11 ) + { + uint8 codec = Buffer.data()[0]; + *pid = Buffer.data()[1]; + ::memcpy(ambe, &(Buffer.data()[2]), 9); + valid = (codec == GetCodecIn()); + } + + return valid; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// packet encodeing helpers + +void CStream::EncodeDvFramePacket(CBuffer *Buffer, uint8 Pid, uint8 *Ambe) +{ + Buffer->clear(); + Buffer->Append((uint8)GetCodecOut()); + Buffer->Append((uint8)Pid); + Buffer->Append(Ambe, 9); +} + diff --git a/ambed/cstream.h b/ambed/cstream.h new file mode 100644 index 0000000..2abc0f9 --- /dev/null +++ b/ambed/cstream.h @@ -0,0 +1,97 @@ +// +// cstream.h +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 15/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cstream_h +#define cstream_h + +#include "cudpsocket.h" +#include "ccallsign.h" +#include "cvocodecchannel.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CStream +{ +public: + // constructors + CStream(); + CStream(uint16, const CCallsign &, const CIp &, uint8, uint8); + + // destructor + virtual ~CStream(); + + // initialization + bool Init(uint16); + void Close(void); + + // get + uint16 GetId(void) const { return m_uiId; } + uint16 GetPort(void) const { return m_uiPort; } + uint8 GetCodecIn(void) const { return m_uiCodecIn; } + uint8 GetCodecOut(void) const { return m_uiCodecOut; } + + // activity timer + bool IsActive(void) const { return m_LastActivity.DurationSinceNow() <= STREAM_ACTIVITY_TIMEOUT; } + + // task + static void Thread(CStream *); + void Task(void); + +protected: + // packet decoding helpers + bool IsValidDvFramePacket(const CBuffer &, uint8 *, uint8 *); + + // packet encodeing helpers + void EncodeDvFramePacket(CBuffer *, uint8, uint8 *); + + +protected: + // data + uint16 m_uiId; + CUdpSocket m_Socket; + uint16 m_uiPort; + uint8 m_uiCodecIn; + uint8 m_uiCodecOut; + CVocodecChannel *m_VocodecChannel; + + // client details + CCallsign m_Callsign; + CIp m_Ip; + + // counters + int m_iTotalPackets; + int m_iLostPackets; + + // activity timer + CTimePoint m_LastActivity; + + // thread + bool m_bStopThread; + std::thread *m_pThread; + +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cstream_h */ diff --git a/ambed/ctimepoint.cpp b/ambed/ctimepoint.cpp new file mode 100644 index 0000000..41b59f0 --- /dev/null +++ b/ambed/ctimepoint.cpp @@ -0,0 +1,53 @@ +// +// ctimepoint.cpp +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 05/11/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include "ctimepoint.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CTimePoint::CTimePoint() +{ + m_TimePoint = std::chrono::steady_clock::now(); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// operation + +double CTimePoint::DurationSinceNow(void) const +{ + std::chrono::steady_clock::time_point Now = std::chrono::steady_clock::now(); + std::chrono::steady_clock::duration time_span = (Now - m_TimePoint); + return double(time_span.count()) * std::chrono::steady_clock::period::num / std::chrono::steady_clock::period::den; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// task + +void CTimePoint::TaskSleepFor(uint ms) +{ + std::chrono::milliseconds timespan(ms); + std::this_thread::sleep_for(timespan); +} diff --git a/ambed/ctimepoint.h b/ambed/ctimepoint.h new file mode 100644 index 0000000..9a9e5a2 --- /dev/null +++ b/ambed/ctimepoint.h @@ -0,0 +1,55 @@ +// +// ctimepoint.h +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 05/11/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef ctimepoint_h +#define ctimepoint_h + + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CTimePoint : public std::chrono::steady_clock::time_point +{ +public: + // constructor + CTimePoint(); + + // destructor + virtual ~CTimePoint() {} + + // operation + void Now(void) { m_TimePoint = std::chrono::steady_clock::now(); } + double DurationSinceNow(void) const; + + // task + static void TaskSleepFor(uint); + +protected: + // data + std::chrono::steady_clock::time_point m_TimePoint; +}; + + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* ctimepoint_h */ diff --git a/ambed/cudpsocket.cpp b/ambed/cudpsocket.cpp new file mode 100644 index 0000000..7e9f336 --- /dev/null +++ b/ambed/cudpsocket.cpp @@ -0,0 +1,172 @@ +// +// cudpsocket.cpp +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include +#include "cudpsocket.h" + + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CUdpSocket::CUdpSocket() +{ + m_Socket = -1; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// destructor + +CUdpSocket::~CUdpSocket() +{ + if ( m_Socket != -1 ) + { + Close(); + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// open & close + +bool CUdpSocket::Open(const CIp &ListenIp, uint16 uiPort) +{ + bool open = false; + + // create socket + m_Socket = socket(PF_INET,SOCK_DGRAM,0); + if ( m_Socket != -1 ) + { + // initialize sockaddr struct + ::memset(&m_SocketAddr, 0, sizeof(struct sockaddr_in)); + m_SocketAddr.sin_family = AF_INET; + m_SocketAddr.sin_port = htons(uiPort); + m_SocketAddr.sin_addr.s_addr = inet_addr(ListenIp); + + if ( bind(m_Socket, (struct sockaddr *)&m_SocketAddr, sizeof(struct sockaddr_in)) == 0 ) + { + fcntl(m_Socket, F_SETFL, O_NONBLOCK); + open = true; + } + else + { + close(m_Socket); + m_Socket = -1; + } + } + + // done + return open; +} + +void CUdpSocket::Close(void) +{ + if ( m_Socket != -1 ) + { + close(m_Socket); + m_Socket = -1; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// read + +int CUdpSocket::Receive(CBuffer *Buffer, CIp *Ip, int timeout) +{ + struct sockaddr_in Sin; + fd_set FdSet; + unsigned int uiFromLen = sizeof(struct sockaddr_in); + int iRecvLen = -1; + struct timeval tv; + + // socket valid ? + if ( m_Socket != -1 ) + { + // control socket + FD_ZERO(&FdSet); + FD_SET(m_Socket, &FdSet); + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + select(m_Socket + 1, &FdSet, 0, 0, &tv); + + // allocate buffer + Buffer->resize(UDP_BUFFER_LENMAX); + + // read + iRecvLen = (int)recvfrom(m_Socket, + (void *)Buffer->data(), UDP_BUFFER_LENMAX, + 0, (struct sockaddr *)&Sin, &uiFromLen); + + // handle + if ( iRecvLen != -1 ) + { + // adjust buffer size + Buffer->resize(iRecvLen); + + // get IP + Ip->SetSockAddr(&Sin); + } + } + + // done + return iRecvLen; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// write + +int CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip) +{ + CIp temp(Ip); + return (int)::sendto(m_Socket, + (void *)Buffer.data(), Buffer.size(), + 0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in)); +} + +int CUdpSocket::Send(const char *Buffer, const CIp &Ip) +{ + CIp temp(Ip); + return (int)::sendto(m_Socket, + (void *)Buffer, ::strlen(Buffer), + 0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in)); +} + +int CUdpSocket::Send(const CBuffer &Buffer, const CIp &Ip, uint16 destport) +{ + CIp temp(Ip); + temp.GetSockAddr()->sin_port = htons(destport); + return (int)::sendto(m_Socket, + (void *)Buffer.data(), Buffer.size(), + 0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in)); +} + +int CUdpSocket::Send(const char *Buffer, const CIp &Ip, uint16 destport) +{ + CIp temp(Ip); + temp.GetSockAddr()->sin_port = htons(destport); + return (int)::sendto(m_Socket, + (void *)Buffer, ::strlen(Buffer), + 0, (struct sockaddr *)temp.GetSockAddr(), sizeof(struct sockaddr_in)); +} + + diff --git a/ambed/cudpsocket.h b/ambed/cudpsocket.h new file mode 100644 index 0000000..3cb1b08 --- /dev/null +++ b/ambed/cudpsocket.h @@ -0,0 +1,78 @@ +// +// cudpsocket.h +// xlxd +// +// Created by Jean-Luc Deltombe (LX3JL) on 31/10/2015. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of xlxd. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cudpsocket_h +#define cudpsocket_h + +#include +//#include +#include +#include +#include +#include +#include + +#include "cip.h" +#include "cbuffer.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// define + +#define UDP_BUFFER_LENMAX 1024 + + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CUdpSocket +{ +public: + // constructor + CUdpSocket(); + + // destructor + ~CUdpSocket(); + + // open & close + bool Open(const CIp &, uint16); + void Close(void); + int GetSocket(void) { return m_Socket; } + + // read + int Receive(CBuffer *, CIp *, int); + + // write + int Send(const CBuffer &, const CIp &); + int Send(const CBuffer &, const CIp &, uint16); + int Send(const char *, const CIp &); + int Send(const char *, const CIp &, uint16); + +protected: + // data + int m_Socket; + struct sockaddr_in m_SocketAddr; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cudpsocket_h */ diff --git a/ambed/cusb3003interface.cpp b/ambed/cusb3003interface.cpp new file mode 100644 index 0000000..e2a77d9 --- /dev/null +++ b/ambed/cusb3003interface.cpp @@ -0,0 +1,185 @@ +// +// cusb3003interface.cpp +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include "ctimepoint.h" +#include "cambepacket.h" +#include "cusb3003interface.h" +#include "cvocodecs.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// configuration: +// +// PKT_CHANNEL0 = DSTAR (AMBEPLUS) +// PKT_CHANNEL1 = DMR/C4FM (AMBE2PLUS) +// PKT_CHANNEL2 = UNUSED or HYBRID + + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CUsb3003Interface::CUsb3003Interface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial) +: CUsb3xxxInterface(uiVid, uiPid, szDeviceName, szDeviceSerial) +{ + m_uiChCodecs[0]= CODEC_AMBEPLUS; + m_uiChCodecs[1]= CODEC_AMBE2PLUS; + m_uiChCodecs[2]= CODEC_NONE; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// initialization + +bool CUsb3003Interface::Init(uint8 uiOddCodec) +{ + bool ok = true; + + // init the odd channel + m_uiChCodecs[2] = uiOddCodec; + + // base class + ok &= CUsb3xxxInterface::Init(); + + // do not create our channels now + // this is delegated to caller (CVocodecs) as our channel + // may be hybrids between 2 interfaces in case of odd n' of channel device) + + // done + return ok; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// manage Channels + +uint8 CUsb3003Interface::GetChannelCodec(int iCh) const +{ + uint8 uiCodec = CODEC_NONE; + if ( (iCh >= 0) && (iCh <= USB3003_NB_CH) ) + { + uiCodec = m_uiChCodecs[iCh]; + } + return uiCodec; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// manage vocodec channels + +CVocodecChannel *CUsb3003Interface::GetChannelWithChannelIn(int iCh) +{ + CVocodecChannel *Channel = NULL; + bool done = false; + for ( int i = 0; (i < m_Channels.size()) && !done; i++ ) + { + if ( iCh == 2 ) + { + if ( (m_Channels[i]->GetChannelIn() == iCh) && !(m_Channels[i]->IsInterfaceOut(this)) ) + { + Channel = m_Channels[i]; + done = true; + } + } + else + { + if ( (m_Channels[i]->GetChannelIn() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) ) + { + Channel = m_Channels[i]; + done = true; + } + } + } + return Channel; +} + +CVocodecChannel *CUsb3003Interface::GetChannelWithChannelOut(int iCh) +{ + CVocodecChannel *Channel = NULL; + bool done = false; + for ( int i = 0; (i < m_Channels.size()) && !done; i++ ) + { + if ( (m_Channels[i]->GetChannelOut() == iCh) && (m_Channels[i]->IsInterfaceOut(this)) ) + { + Channel = m_Channels[i]; + done = true; + } + } + return Channel; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// low level + +bool CUsb3003Interface::SoftResetDevice(void) +{ + bool ok = false; + FT_STATUS ftStatus; + int len; + char rxpacket[100]; + + //if the device is a USB-3003, it supports reset via UART break signal + //printf("reset via uart break...\n"); + ftStatus = FT_SetBreakOn( m_FtdiHandle ); + CTimePoint::TaskSleepFor(10); + ftStatus = FT_SetBreakOff( m_FtdiHandle ); + //CTimePoint::TaskSleepFor(10); + + len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ); + ok = ((len == 7) && (rxpacket[4] == PKT_READY)); + if ( !ok ) + { + std::cout << "USB-3xxx soft reset failed" << std::endl; + } + + // done + return ok; +} + +bool CUsb3003Interface::ConfigureDevice(void) +{ + bool ok = true; + uint8 pkt_ratep_ambeplus[] = { 0x01,0x30,0x07,0x63,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x48 }; + uint8 pkt_ratep_ambe2plus[] = { 0x04,0x31,0x07,0x54,0x24,0x00,0x00,0x00,0x00,0x00,0x6F,0x48 }; + + // configure each channels for desired codec + for ( int i = 0; i < USB3003_NB_CH; i++ ) + { + switch ( m_uiChCodecs[i] ) + { + case CODEC_AMBEPLUS: + ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambeplus, 0, 0); + break; + case CODEC_AMBE2PLUS: + //ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambe2plus, -12, 0); // DSTAR->DMR ok + //ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambe2plus, 0, +10); // DMR->DSTAR ok + //ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambe2plus, -12, +10); // not ok! + ok &= ConfigureChannel(PKT_CHANNEL0+i, pkt_ratep_ambe2plus, 0, 0); + break; + case CODEC_NONE: + default: + break; + } + } + + // done + return ok; +} + diff --git a/ambed/cusb3003interface.h b/ambed/cusb3003interface.h new file mode 100644 index 0000000..27872ea --- /dev/null +++ b/ambed/cusb3003interface.h @@ -0,0 +1,70 @@ +// +// cusb3003interface.h +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cusb3003interface_h +#define cusb3003interface_h + +#include "ftd2xx.h" +#include "cbuffer.h" +#include "cusb3xxxinterface.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// define + +#define USB3003_NB_CH 3 + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CUsb3003Interface : public CUsb3xxxInterface +{ +public: + // constructors + CUsb3003Interface(uint32, uint32, const char *, const char *); + + // destructor + virtual ~CUsb3003Interface() {} + + // initialization + bool Init(uint8); + + // manage channels + int GetNbChannels(void) const { return USB3003_NB_CH; } + uint8 GetChannelCodec(int) const; + + // manage vocodec channels + CVocodecChannel *GetChannelWithChannelIn(int); + CVocodecChannel *GetChannelWithChannelOut(int); + +protected: + // low level + bool SoftResetDevice(void); + bool ConfigureDevice(void); + + // data + uint8 m_uiChCodecs[USB3003_NB_CH]; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cusb3003interface_h */ diff --git a/ambed/cusb3xxxinterface.cpp b/ambed/cusb3xxxinterface.cpp new file mode 100644 index 0000000..05bbc15 --- /dev/null +++ b/ambed/cusb3xxxinterface.cpp @@ -0,0 +1,667 @@ +// +// cusb3xxxinterface.cpp +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 26/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include +#include "ctimepoint.h" +#include "cusb3xxxinterface.h" +#include "cvocodecchannel.h" +#include "cambeserver.h" + +// queues ID +#define QUEUE_CHANNEL 0 +#define QUEUE_SPEECH 1 + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CUsb3xxxInterface::CUsb3xxxInterface(uint32 uiVid, uint32 uiPid, const char *szDeviceName, const char *szDeviceSerial) +{ + m_FtdiHandle = NULL; + m_iDeviceFifoLevel = 0; + m_iActiveQueue = QUEUE_CHANNEL; + m_uiVid = uiVid; + m_uiPid = uiPid; + ::strcpy(m_szDeviceName, szDeviceName); + ::strcpy(m_szDeviceSerial, szDeviceSerial); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// destructor + +CUsb3xxxInterface::~CUsb3xxxInterface() +{ +} + +//////////////////////////////////////////////////////////////////////////////////////// +// initialization + +bool CUsb3xxxInterface::Init(void) +{ + bool ok = true; + + // open USB device + std::cout << "Opening " << m_szDeviceName << ":" << m_szDeviceSerial << " device" << std::endl; + if ( ok &= OpenDevice() ) + { + // reset + //std::cout << "Reseting " << m_szDeviceName << "device" << std::endl; + if ( ok &= SoftResetDevice() ) + { + // read version + //std::cout << "Reading " << m_szDeviceName << " device version" << std::endl; + if ( ok &= ReadDeviceVersion() ) + { + // send configuration packet(s) + //std::cout << "Configuring " << m_szDeviceName << " device" << std::endl; + ok &= DisableParity(); + ok &= ConfigureDevice(); + } + } + } + std::cout << std::endl; + + // base class + if ( ok ) + { + ok &= CVocodecInterface::Init(); + } + + // done + return ok; +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// task + +void CUsb3xxxInterface::Task(void) +{ + CBuffer Buffer; + int iCh; + CPacketQueue *Queue; + CVocodecChannel *Channel; + CAmbePacket AmbePacket; + CVoicePacket VoicePacket; + bool done; + + // TODO : + // preserve packets PIDs, so the transcoded CAmbePacket returned + // to CStream client is garantied to have the same PID + // than the corresponding incoming packet + + // process the device incoming packet + // get all packets from device and push them + // to the relevant clients queues + if ( ReadBuffer(&Buffer) ) + { + if ( IsValidSpeechPacket(Buffer, &iCh, &VoicePacket) ) + { +#ifdef DEBUG_DUMPFILE + g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "->Sp" << iCh << std::endl; std::cout.flush(); +#endif + // update fifo status + m_iDeviceFifoLevel = MAX(m_iDeviceFifoLevel-1, 0); + + // push back to relevant channel voice queue + // our incoming channel packet has now been through the decoder + // find the coupled channel encoder and push to it's queue + // this is were the DVSI enc-dec channel crossover take place + Channel = GetChannelWithChannelIn(iCh); + if ( Channel != NULL ) + { + Queue = Channel->GetVoiceQueue(); + CVoicePacket *clone = new CVoicePacket(VoicePacket); + clone->ApplyGain(Channel->GetSpeechGain()); + Queue->push(clone); + Channel->ReleaseVoiceQueue(); + } + } + else if ( IsValidChannelPacket(Buffer, &iCh, &AmbePacket) ) + { +#ifdef DEBUG_DUMPFILE + g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "->Ch" << iCh << std::endl; std::cout.flush(); +#endif + // update fifo status + m_iDeviceFifoLevel = MAX(m_iDeviceFifoLevel-1, 0); + + // push back to relevant channel outcoming queue + Channel = GetChannelWithChannelOut(iCh); + if ( Channel != NULL ) + { + Queue = Channel->GetPacketQueueOut(); + CAmbePacket *clone = new CAmbePacket(AmbePacket); + Queue->push(clone); + Channel->ReleasePacketQueueOut(); + } + } + } + + // process the streams (channels) incoming queue + // make sure that packets from different channels + // are interlaced so to keep the device fifo busy + do + { + done = true; + for ( int i = 0; i < m_Channels.size(); i++) + { + // get channel + Channel = m_Channels[i]; + + // any packet in voice queue ? + if ( Channel->IsInterfaceOut(this) ) + { + Queue = Channel->GetVoiceQueue(); + if ( !Queue->empty() ) + { + // get packet + CVoicePacket *Packet = (CVoicePacket *)Queue->front(); + Queue->pop(); + // post it to relevant channel encoder + Packet->SetChannel(Channel->GetChannelOut()); + m_SpeechQueue.push(Packet); + // done + done = false; + } + Channel->ReleaseVoiceQueue(); + } + + // any packet in ambe queue for us ? + if ( Channel->IsInterfaceIn(this) ) + { + Queue = Channel->GetPacketQueueIn(); + if ( !Queue->empty() ) + { + // get packet + CAmbePacket *Packet = (CAmbePacket *)Queue->front(); + Queue->pop(); + // post it to relevant channel decoder + Packet->SetChannel(Channel->GetChannelIn()); + m_ChannelQueue.push(Packet); + // done + done = false; + } + Channel->ReleasePacketQueueIn(); + } + } + } while (!done); + + // process device incoming queues + // interlace speech and channels packets + // and make sure that the fifo is always + // fed. + unsigned long iQueueLevel = m_SpeechQueue.size() + m_ChannelQueue.size(); + if ( ((m_iDeviceFifoLevel == 0) && (iQueueLevel >= 2)) || (m_iDeviceFifoLevel == 1) ) + { + if ( m_iActiveQueue == QUEUE_CHANNEL ) + { + // post next channel packet + if ( !m_ChannelQueue.empty() ) + { + // get packet + CAmbePacket *Packet = (CAmbePacket *)m_ChannelQueue.front(); + m_ChannelQueue.pop(); + //Post it + EncodeChannelPacket(&Buffer, Packet->GetChannel(), Packet); + WriteBuffer(Buffer); + m_iDeviceFifoLevel++; + // and delete it +#ifdef DEBUG_DUMPFILE + g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Ch" << Packet->GetChannel() << "->" << std::endl; std::cout.flush(); +#endif + delete Packet; + } + // and interlace + m_iActiveQueue = QUEUE_SPEECH; + } + else + { + // post next speech packet + if ( !m_SpeechQueue.empty() ) + { + // get packet + CVoicePacket *Packet = (CVoicePacket *)m_SpeechQueue.front(); + m_SpeechQueue.pop(); + //Post it + EncodeSpeechPacket(&Buffer, Packet->GetChannel(), Packet); + WriteBuffer(Buffer); + m_iDeviceFifoLevel++; + // and delete it +#ifdef DEBUG_DUMPFILE + g_AmbeServer.m_DebugFile << m_szDeviceName << "\t" << "Sp" << Packet->GetChannel() << "->" << std::endl; std::cout.flush(); +#endif + delete Packet; + } + // and interlace + m_iActiveQueue = QUEUE_CHANNEL; + } + } + + + // and wait a bit + CTimePoint::TaskSleepFor(2); +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// decoder helper + +bool CUsb3xxxInterface::IsValidChannelPacket(const CBuffer &buffer, int *ch, CAmbePacket *packet) +{ + bool valid = false; + uint8 tag[] = { PKT_HEADER,0x00,0x0C,PKT_CHANNEL }; + + if ( (buffer.size() == 16) && (buffer.Compare(tag, sizeof(tag)) == 0)) + { + *ch = buffer.data()[4] - PKT_CHANNEL0; + if ( *ch == 0 ) + packet->SetCodec(CODEC_AMBEPLUS); + else if ( *ch == 1 ) + packet->SetCodec(CODEC_AMBE2PLUS); + else + packet->SetCodec(CODEC_NONE); + packet->SetAmbe(&(buffer.data()[7])); + valid = (*ch < GetNbChannels()); + //std::cout << "CHAN " << *ch << " " << buffer.size() << " " << (int)buffer[6] << std::endl; + } + return valid; +} + +bool CUsb3xxxInterface::IsValidSpeechPacket(const CBuffer &buffer, int *ch, CVoicePacket *packet) +{ + bool valid = false; + + if ( (buffer.size() > 6) && + (buffer.data()[0] == PKT_HEADER) && (buffer.data()[3] == PKT_SPEECH) && + (buffer.data()[5] == PKT_SPEECHD) ) + { + *ch = buffer.data()[4] - PKT_CHANNEL0; + packet->SetVoice(&(buffer.data()[7]), buffer.data()[6] * 2); + valid = (*ch < GetNbChannels()); + //std::cout << "SPCH " << *ch << " " << buffer.size() << std::endl; + } + return valid; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// encoder helpers + +void CUsb3xxxInterface::EncodeChannelPacket(CBuffer *buffer, int ch, CAmbePacket *packet) +{ + uint size = (uint16)packet->GetAmbeSize() + 3; + buffer->clear(); + buffer->Append((uint8)PKT_HEADER); + buffer->Append((uint8)HIBYTE(size)); + buffer->Append((uint8)LOBYTE(size)); + buffer->Append((uint8)PKT_CHANNEL); + buffer->Append((uint8)(PKT_CHANNEL0+ch)); + buffer->Append((uint8)(PKT_CHAND)); + buffer->Append((uint8)(packet->GetAmbeSize()*8)); + buffer->Append(packet->GetAmbe(), packet->GetAmbeSize()); +} + +void CUsb3xxxInterface::EncodeSpeechPacket(CBuffer *buffer, int ch, CVoicePacket *packet) +{ + uint16 size = (uint16)packet->GetVoiceSize() + 3; + buffer->clear(); + buffer->Append((uint8)PKT_HEADER); + buffer->Append((uint8)HIBYTE(size)); + buffer->Append((uint8)LOBYTE(size)); + buffer->Append((uint8)PKT_SPEECH); + buffer->Append((uint8)(PKT_CHANNEL0+ch)); + buffer->Append((uint8)PKT_SPEECHD); + buffer->Append((uint8)(packet->GetVoiceSize()/2)); + buffer->Append(packet->GetVoice(), packet->GetVoiceSize()); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// low level + + +bool CUsb3xxxInterface::OpenDevice(void) +{ + { + FT_STATUS ftStatus; + int baudrate = 921600; + + //sets serial VID/PID for a Standard Device NOTE: This is for legacy purposes only. This can be ommitted. + ftStatus = FT_SetVIDPID(m_uiVid, m_uiPid); + if (ftStatus != FT_OK) {FTDI_Error((char *)"FT_SetVIDPID", ftStatus ); return false; } + + //ftStatus = FT_OpenEx((PVOID)m_szDeviceSerial, FT_OPEN_BY_SERIAL_NUMBER, &m_FtdiHandle); + ftStatus = FT_OpenEx((PVOID)m_szDeviceName, FT_OPEN_BY_DESCRIPTION, &m_FtdiHandle); + baudrate = 921600; + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_OpenEx", ftStatus ); return false; } + + CTimePoint::TaskSleepFor(50); + FT_Purge(m_FtdiHandle, FT_PURGE_RX | FT_PURGE_TX ); + CTimePoint::TaskSleepFor(50); + + ftStatus = FT_SetDataCharacteristics(m_FtdiHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE); + if ( ftStatus != FT_OK ) { FTDI_Error((char *)"FT_SetDataCharacteristics", ftStatus ); return false; } + + ftStatus = FT_SetFlowControl(m_FtdiHandle, FT_FLOW_RTS_CTS, 0x11, 0x13); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetFlowControl", ftStatus ); return false; } + + ftStatus = FT_SetRts (m_FtdiHandle); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetRts", ftStatus ); return false; } + + //for usb-3012 pull DTR high to take AMBE3003 out of reset. + //for other devices noting is connected to DTR so it is a dont care + ftStatus = FT_ClrDtr(m_FtdiHandle); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_ClrDtr", ftStatus); return false; } + + ftStatus = FT_SetBaudRate(m_FtdiHandle, baudrate ); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetBaudRate", ftStatus ); return false; } + + ftStatus = FT_SetLatencyTimer(m_FtdiHandle, 4); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetLatencyTimer", ftStatus ); return false; } + + ftStatus = FT_SetUSBParameters(m_FtdiHandle, USB3XXX_MAXPACKETSIZE, 0); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetUSBParameters", ftStatus ); return false; } + + ftStatus = FT_SetTimeouts(m_FtdiHandle, 200, 200 ); + if (ftStatus != FT_OK) { FTDI_Error((char *)"FT_SetTimeouts", ftStatus ); return false; } + + // done + return true; + } +} + +bool CUsb3xxxInterface::ReadDeviceVersion(void) +{ + bool ok = false; + int i, len; + char rxpacket[128]; + char txpacket[8] = + { + PKT_HEADER, + 0, + 4, + PKT_CONTROL, + PKT_PRODID, + PKT_VERSTRING, + PKT_PARITYBYTE, + 4 ^ PKT_CONTROL ^ PKT_PRODID ^ PKT_VERSTRING ^ PKT_PARITYBYTE + }; + + // write packet + if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) + { + // read reply + len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4; + ok = (len != 0); + //we succeed in reading a packet, print it out + std::cout << "ReadDeviceVersion : "; + for ( i = 4; i < len+4 ; i++ ) + { + std::cout << (char)(rxpacket[i] & 0x00ff); + } + std::cout << std::endl; + } + return ok; +} + +bool CUsb3xxxInterface::DisableParity(void) +{ + bool ok = false; + int len; + char rxpacket[16]; + char txpacket[8] = + { + PKT_HEADER, + 0, + 4, + PKT_CONTROL, + PKT_PARITYMODE,0x00, + PKT_PARITYBYTE, + 4 ^ PKT_CONTROL ^ PKT_PARITYMODE ^ 0x00 ^ PKT_PARITYBYTE + }; + + // write packet + if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) + { + // read reply + len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4; + ok = ((len == 2) && (rxpacket[4] == PKT_PARITYMODE) &&(rxpacket[5] == 0x00) ); + } + return ok; +} + +bool CUsb3xxxInterface::ConfigureChannel(uint8 pkt_ch, const uint8 *pkt_ratep, int in_gain, int out_gain) +{ + bool ok = false; + int len; + char rxpacket[64]; + char txpacket[] = + { + PKT_HEADER, + 0, + 33, + PKT_CONTROL, + 0x00, + PKT_ECMODE, 0x00,0x00, + PKT_DCMODE, 0x00,0x00, + PKT_COMPAND,0x00, + PKT_RATEP, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + PKT_CHANFMT,0x00,0x00, + PKT_SPCHFMT,0x00,0x00, + PKT_GAIN, 0x00,0x00, + PKT_INIT, 0x03 + }; + + // update packet content + txpacket[4] = pkt_ch; + :: memcpy(&(txpacket[14]), pkt_ratep, 12); + txpacket[33] = (uint8)(signed char)in_gain; + txpacket[34] = (uint8)(signed char)out_gain; + + // write packet + if ( FTDI_write_packet(m_FtdiHandle, txpacket, sizeof(txpacket)) ) + { + // read reply + len = FTDI_read_packet( m_FtdiHandle, rxpacket, sizeof(rxpacket) ) - 4; + ok = ((len == 18) && (rxpacket[20] == PKT_INIT) &&(rxpacket[21] == 0x00) ); + } + return ok; + +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// io level + +bool CUsb3xxxInterface::ReadBuffer(CBuffer *buffer) +{ + bool ok = false; + int n; + + // any byte in tx queue ? + if ( FT_GetQueueStatus(m_FtdiHandle, (LPDWORD)&n) == FT_OK ) + { + //if ( (FT_GetQueueStatus(m_FtdiHandle, (LPDWORD)&n) == FT_OK) && (n != 0) ) + if ( n != 0 ) + { + buffer->clear(); + buffer->resize(USB3XXX_MAXPACKETSIZE); + n = FTDI_read_packet(m_FtdiHandle, (char *)buffer->data(), USB3XXX_MAXPACKETSIZE); + buffer->resize(n); + ok = (n != 0); + } + } + return ok; +} + +bool CUsb3xxxInterface::WriteBuffer(const CBuffer &buffer) +{ + return FTDI_write_packet(m_FtdiHandle, (const char *)buffer.data(), (int)buffer.size()); +} + +int CUsb3xxxInterface::FTDI_read_packet(FT_HANDLE ftHandle, char *pkt, int maxlen) +{ + int plen; + + // first read 4 bytes header + if ( FTDI_read_bytes(ftHandle, pkt, 4) ) + { + // get payload length + plen = (pkt[1] & 0x00ff); + plen <<= 8; + plen += (pkt[2] & 0x00ff); + // check buffer length + if (plen+4 > maxlen) + { + std::cout << "FTDI_read_packet supplied buffer is not large enough for packet" << std::endl; + FT_Purge(ftHandle, FT_PURGE_RX); + return 0; + } + // and get payload + if ( FTDI_read_bytes(ftHandle, &pkt[4], plen) ) + { + return plen+4; + } + } + return 0; +} + +bool CUsb3xxxInterface::FTDI_read_bytes(FT_HANDLE ftHandle, char *buffer, int len) +{ + // this relies on FT_SetTimouts() mechanism + int n; + bool ok = false; + + ok = (FT_Read(ftHandle, (LPVOID)buffer, len, (LPDWORD)&n) == FT_OK) && (n == len); + if ( !ok ) + { + //FT_Purge(ftHandle, FT_PURGE_RX); + std::cout << "FTDI_read_bytes(" << len << ") failed : " << n << std::endl; + } + + return ok; +} + +/* +int CUsb3xxxInterface::FTDI_read_packet(FT_HANDLE ftHandle, char *pkt, int maxlen) +{ + FT_STATUS ftStatus; + int nr; + int plen; + int offset = 0; + int nrt; + int len; + + // first read 4 bytes header + len = 4; + nrt = 0; + offset = 0; + do + { + ftStatus = FT_Read( ftHandle, (LPVOID)&pkt[offset], len, (LPDWORD)&nr ); + if (ftStatus != FT_OK) + { + FTDI_Error((char *)"FT_Read C0", ftStatus ); + return 0; + } + len -= nr; + nrt += nr; + offset += nr; + } while (len > 0); + + if (nrt != 4) + { + std::cout << "FTDI_read_packet nrt = " << nrt << std::endl; + return 0; + } + + // get packet payload length + plen = (pkt[1] & 0x00ff); + plen <<= 8; + plen += (pkt[2] & 0x00ff); + if (plen+4 > maxlen) + { + std::cout << "FTDI_read_packet supplied buffer is not large enough for packet" << std::endl; + plen = maxlen-4; + } + + // and read payload + len = plen; + nrt = 0; + offset = 4; + do + { + ftStatus = FT_Read( ftHandle, (LPVOID)&pkt[offset], len, (LPDWORD)&nr ); + if (ftStatus != FT_OK) + { + FTDI_Error((char *)"FT_Read C1", ftStatus ); + return 0; + } + len -= nr; + nrt += nr; + offset += nr; + } while (len > 0); + + if (nrt != plen) + { + std::cout << "FTDI_read_packet nrt = " << nrt << " plen = " << plen << std::endl; + //printf("reading packet nrt=%d plen=%d\n", nrt, plen ); + //printf("pkt[0]=0x%02x\n", pkt[0] & 0x00ff ); + //printf("pkt[1]=0x%02x\n", pkt[1] & 0x00ff ); + //printf("pkt[2]=0x%02x\n", pkt[2] & 0x00ff ); + //printf("pkt[3]=0x%02x\n", pkt[3] & 0x00ff ); + //printf("pkt[4]=0x%02x\n", pkt[4] & 0x00ff ); + //printf("pkt[5]=0x%02x\n", pkt[5] & 0x00ff ); + return 0; + } + + //NOTE: we could extract the channel data from the packet, but for this + //simple example, the whole packet is echoed back for decoding so + //we don't bother extracting the channel data + return plen+4; +} +*/ +bool CUsb3xxxInterface::FTDI_write_packet(FT_HANDLE ft_handle, const char *pkt, int len) +{ + FT_STATUS ftStatus; + bool ok = true; + int nwritten; + + if ( len > 0 ) + { + ftStatus = FT_Write(m_FtdiHandle, (LPVOID *)pkt, (DWORD)len, (LPDWORD)&nwritten); + ok = (ftStatus == FT_OK) && (len == nwritten); + if ( !ok ) + { + FTDI_Error((char *)"FT_Write", ftStatus); + } + } + return ok; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// error reporting + +void CUsb3xxxInterface::FTDI_Error(char *func_string, FT_STATUS ftStatus) +{ + std::cout << "FTDI function " << func_string << " error " << (int)ftStatus << std::endl; +} diff --git a/ambed/cusb3xxxinterface.h b/ambed/cusb3xxxinterface.h new file mode 100644 index 0000000..445002a --- /dev/null +++ b/ambed/cusb3xxxinterface.h @@ -0,0 +1,134 @@ +// +// cusb3xxxinterface.h +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 26/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cusb3xxxinterface_h +#define cusb3xxxinterface_h + + +#include "ftd2xx.h" +#include "cftdidevicedescr.h" +#include "cbuffer.h" +#include "cambepacket.h" +#include "cvoicepacket.h" +#include "cvocodecinterface.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// define + +#define USB3XXX_MAXPACKETSIZE 1024 // must be multiple of 64 + +#define PKT_HEADER 0x61 + +#define PKT_CONTROL 0x00 +#define PKT_CHANNEL 0x01 +#define PKT_SPEECH 0x02 + +#define PKT_SPEECHD 0x00 +#define PKT_CHAND 0x01 +#define PKT_RATET 0x09 +#define PKT_INIT 0x0b +#define PKT_PRODID 0x30 +#define PKT_VERSTRING 0x31 +#define PKT_PARITYBYTE 0x2F +#define PKT_RESET 0x33 +#define PKT_READY 0x39 +#define PKT_CHANNEL0 0x40 +#define PKT_CHANNEL1 0x41 +#define PKT_CHANNEL2 0x42 +#define PKT_PARITYMODE 0x3F +#define PKT_ECMODE 0x05 +#define PKT_DCMODE 0x06 +#define PKT_COMPAND 0x32 +#define PKT_RATEP 0x0A +#define PKT_CHANFMT 0x15 +#define PKT_SPCHFMT 0x16 +#define PKT_GAIN 0x4B + + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CUsb3xxxInterface : public CVocodecInterface +{ +public: + // constructors + CUsb3xxxInterface(uint32, uint32, const char *, const char *); + + // destructor + virtual ~CUsb3xxxInterface(); + + // initialization + bool Init(void); + + // get + const char *GetName(void) const { return m_szDeviceName; } + const char *GetSerial(void) const { return m_szDeviceSerial; } + + // task + void Task(void); + +protected: + // decoder helper + bool IsValidChannelPacket(const CBuffer &, int *, CAmbePacket *); + bool IsValidSpeechPacket(const CBuffer &, int *, CVoicePacket *); + + // encoder helpers + void EncodeChannelPacket(CBuffer *, int, CAmbePacket *); + void EncodeSpeechPacket(CBuffer *, int, CVoicePacket *); + + // low level + bool OpenDevice(void); + virtual bool SoftResetDevice(void) { return false; } + bool ReadDeviceVersion(void); + bool DisableParity(void); + virtual bool ConfigureDevice(void) { return false; } + bool ConfigureChannel(uint8, const uint8 *, int, int); + + // io level + bool ReadBuffer(CBuffer *); + bool WriteBuffer(const CBuffer &); + int FTDI_read_packet(FT_HANDLE, char *, int); + bool FTDI_read_bytes(FT_HANDLE, char *, int); + bool FTDI_write_packet(FT_HANDLE, const char *, int); + + // error reporting + void FTDI_Error(char *, FT_STATUS); + +protected: + // data + uint32 m_uiVid; + uint32 m_uiPid; + char m_szDeviceName[FTDI_MAX_STRINGLENGTH]; + char m_szDeviceSerial[FTDI_MAX_STRINGLENGTH]; + FT_HANDLE m_FtdiHandle; + + // queue + CPacketQueue m_SpeechQueue; + CPacketQueue m_ChannelQueue; + int m_iDeviceFifoLevel; + int m_iActiveQueue; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cusb3xxxinterface_h */ diff --git a/ambed/cvocodecchannel.cpp b/ambed/cvocodecchannel.cpp new file mode 100644 index 0000000..52476fb --- /dev/null +++ b/ambed/cvocodecchannel.cpp @@ -0,0 +1,109 @@ +// +// cvocodecchannel.cpp +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include "ctimepoint.h" +#include "cvocodecchannel.h" +#include "cvocodecinterface.h" + + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CVocodecChannel::CVocodecChannel(CVocodecInterface *InterfaceIn, int iChIn, CVocodecInterface *InterfaceOut, int iChOut, int iSpeechGain) +{ + m_bOpen = false; + m_InterfaceIn = InterfaceIn; + m_iChannelIn = iChIn; + m_InterfaceOut = InterfaceOut; + m_iChannelOut = iChOut; + m_iSpeechGain = iSpeechGain; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// destructor + +CVocodecChannel::~CVocodecChannel() +{ + PurgeAllQueues(); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// open & close + +bool CVocodecChannel::Open(void) +{ + bool ok = false; + if ( !m_bOpen ) + { + m_bOpen = true; + ok = true; + PurgeAllQueues(); + std::cout << "Vocodec channel " << + m_InterfaceIn->GetName() << ":" << (int)m_iChannelIn << " -> " << + m_InterfaceOut->GetName() << ":" << (int)m_iChannelOut << " open" << std::endl; + } + return ok; +} + +void CVocodecChannel::Close(void) +{ + if ( m_bOpen ) + { + m_bOpen = false; + PurgeAllQueues(); + std::cout << "Vocodec channel " << + m_InterfaceIn->GetName() << ":" << (int)m_iChannelIn << " -> " << + m_InterfaceIn->GetName() << ":" << (int)m_iChannelOut << " closed" << std::endl; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// get + +uint8 CVocodecChannel::GetCodecIn(void) const +{ + return m_InterfaceIn->GetChannelCodec(m_iChannelIn); +} + +uint8 CVocodecChannel::GetCodecOut(void) const +{ + return m_InterfaceOut->GetChannelCodec(m_iChannelOut); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// queues helpers + +void CVocodecChannel::PurgeAllQueues(void) +{ + GetPacketQueueIn()->Purge(); + ReleasePacketQueueIn(); + GetPacketQueueOut()->Purge(); + ReleasePacketQueueOut(); + GetVoiceQueue()->Purge(); + ReleaseVoiceQueue(); +} + + + diff --git a/ambed/cvocodecchannel.h b/ambed/cvocodecchannel.h new file mode 100644 index 0000000..4848c87 --- /dev/null +++ b/ambed/cvocodecchannel.h @@ -0,0 +1,98 @@ +// +// cvocodecchannel.h +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + + +#ifndef cvocodecchannel_h +#define cvocodecchannel_h + +#include "cpacketqueue.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CVocodecInterface; + +class CVocodecChannel +{ +public: + // constructors + CVocodecChannel(CVocodecInterface *, int, CVocodecInterface *, int, int); + + // destructor + virtual ~CVocodecChannel(); + + // open & close + bool Open(void); + bool IsOpen(void) const { return m_bOpen; } + void Close(void); + + // get + uint8 GetCodecIn(void) const; + uint8 GetCodecOut(void) const; + int GetChannelIn(void) const { return m_iChannelIn; } + int GetChannelOut(void) const { return m_iChannelOut; } + int GetSpeechGain(void) const { return m_iSpeechGain; } + + // interfaces + bool IsInterfaceIn(const CVocodecInterface *interface) { return (interface == m_InterfaceIn); } + bool IsInterfaceOut(const CVocodecInterface *interface) { return (interface == m_InterfaceOut); } + + // queues + CPacketQueue *GetPacketQueueIn(void) { m_QueuePacketIn.Lock(); return &m_QueuePacketIn; } + void ReleasePacketQueueIn(void) { m_QueuePacketIn.Unlock(); } + CPacketQueue *GetPacketQueueOut(void) { m_QueuePacketOut.Lock(); return &m_QueuePacketOut; } + void ReleasePacketQueueOut(void) { m_QueuePacketOut.Unlock(); } + CPacketQueue *GetVoiceQueue(void) { m_QueueVoice.Lock(); return &m_QueueVoice; } + void ReleaseVoiceQueue(void) { m_QueueVoice.Unlock(); } + + // operators + //virtual bool operator ==(const CVocodecChannel &) const { return false; } + +protected: + // queues helpers + void PurgeAllQueues(void); + +protected: + // status + bool m_bOpen; + + // connected interfaces + CVocodecInterface *m_InterfaceIn; + int m_iChannelIn; + CVocodecInterface *m_InterfaceOut; + int m_iChannelOut; + + // ambe queues + CPacketQueue m_QueuePacketIn; + CPacketQueue m_QueuePacketOut; + // voice queue + CPacketQueue m_QueueVoice; + + // settings + int m_iSpeechGain; + +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cvocodecchannel_h */ diff --git a/ambed/cvocodecinterface.cpp b/ambed/cvocodecinterface.cpp new file mode 100644 index 0000000..e730e09 --- /dev/null +++ b/ambed/cvocodecinterface.cpp @@ -0,0 +1,95 @@ +// +// cvocodecinterface.cpp +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include "ctimepoint.h" +#include "cpacketqueue.h" +#include "cvocodecinterface.h" + + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CVocodecInterface::CVocodecInterface() +{ + m_Channels.reserve(5); + m_bStopThread = false; + m_pThread = NULL; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// destructor + +CVocodecInterface::~CVocodecInterface() +{ + // empty channel array + // chennels are deleted by their owner (CVocodecs) + m_Channels.clear(); + + // stop thread + m_bStopThread = true; + if ( m_pThread != NULL ) + { + m_pThread->join(); + delete m_pThread; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// initialization + +bool CVocodecInterface::Init(void) +{ + // reset stop flag + m_bStopThread = false; + + // start thread; + m_pThread = new std::thread(CVocodecInterface::Thread, this); + + // done + return true; +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// thread + +void CVocodecInterface::Thread(CVocodecInterface *This) +{ + while ( !This->m_bStopThread ) + { + This->Task(); + } +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// manage Channels + +void CVocodecInterface::AddChannel(CVocodecChannel *Channel) +{ + m_Channels.push_back(Channel); +} + + diff --git a/ambed/cvocodecinterface.h b/ambed/cvocodecinterface.h new file mode 100644 index 0000000..66f8fbb --- /dev/null +++ b/ambed/cvocodecinterface.h @@ -0,0 +1,75 @@ +// +// cvocodecinterface.h +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cvocodecinterface_h +#define cvocodecinterface_h + +#include "cvocodecchannel.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CVocodecs; + +class CVocodecInterface +{ +public: + // constructors + CVocodecInterface(); + + // destructor + virtual ~CVocodecInterface(); + + // initialization + virtual bool Init(void); + + // get + virtual const char *GetName(void) const { return ""; } + + // manage channels + virtual int GetNbChannels(void) const { return 0; } + virtual uint8 GetChannelCodec(int) const { return CODEC_NONE; } + void AddChannel(CVocodecChannel *); + virtual CVocodecChannel *GetChannelWithChannelIn(int) { return NULL; } + virtual CVocodecChannel *GetChannelWithChannelOut(int) { return NULL; } + + // task + static void Thread(CVocodecInterface *); + virtual void Task(void) {}; + + // operators + virtual bool operator ==(const CVocodecInterface &) const { return false; } + +protected: + // array of channels + std::vector m_Channels; + + // thread + bool m_bStopThread; + std::thread *m_pThread; + +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cvocodecinterface_h */ diff --git a/ambed/cvocodecs.cpp b/ambed/cvocodecs.cpp new file mode 100644 index 0000000..04393bd --- /dev/null +++ b/ambed/cvocodecs.cpp @@ -0,0 +1,399 @@ +// +// cvocodecs.cpp +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include +#include "cusb3003interface.h" +#include "cvocodecs.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// global object + +CVocodecs g_Vocodecs; + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CVocodecs::CVocodecs() +{ + m_Interfaces.reserve(5); + m_Channels.reserve(20); + m_FtdiDeviceDescrs.reserve(10); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// destructor + +CVocodecs::~CVocodecs() +{ + // delete channels + m_MutexChannels.lock(); + { + for ( int i = 0; i < m_Channels.size(); i++ ) + { + delete m_Channels[i]; + } + m_Channels.clear(); + } + m_MutexChannels.unlock(); + + // delete interfaces + m_MutexInterfaces.lock(); + { + for ( int i = 0; i < m_Interfaces.size(); i++ ) + { + delete m_Interfaces[i]; + } + m_Interfaces.clear(); + } + m_MutexInterfaces.unlock(); + + // delete ftdi device descriptors + for ( int i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) + { + delete m_FtdiDeviceDescrs[i]; + } +} + +//////////////////////////////////////////////////////////////////////////////////////// +// initialization + +bool CVocodecs::Init(void) +{ + bool ok = true; + int iNbCh = 0; + + // discover and add vocodecs interfaces + DiscoverFtdiDevices(); + + // and create interfaces for the discovered devices + for ( int i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) + { + // create relevant interface + if ( m_FtdiDeviceDescrs[i]->IsUsb3012() ) + { + iNbCh += InitUsb3012(*m_FtdiDeviceDescrs[i]); + m_FtdiDeviceDescrs[i]->SetUsed(true); + } + else if ( m_FtdiDeviceDescrs[i]->IsUsb3003() && !m_FtdiDeviceDescrs[i]->IsUsed() ) + { + // another unsed USB-3003 avaliable for a pair ? + bool found = false; + int j = i+1; + while ( !found && (j < m_FtdiDeviceDescrs.size()) && + !(m_FtdiDeviceDescrs[j]->IsUsb3003() && !m_FtdiDeviceDescrs[i]->IsUsed()) ) + { + j++; + } + + // pair ? + if ( found ) + { + // yes! + iNbCh += InitUsb3003Pair(*m_FtdiDeviceDescrs[i], *m_FtdiDeviceDescrs[j]); + m_FtdiDeviceDescrs[i]->SetUsed(true); + m_FtdiDeviceDescrs[j]->SetUsed(true); + } + else + { + // just single + iNbCh += InitUsb3003(*m_FtdiDeviceDescrs[i]); + m_FtdiDeviceDescrs[i]->SetUsed(true); + } + } + } + + if ( ok ) + { + std::cout << "Codec interfaces initialized successfully : " << iNbCh << " channels availables" << std::endl; + } + else + { + std::cout << "At least one codec interfaces failed to initialize : " << iNbCh << " channels availables" << std::endl; + } + // done + return ok; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// initialisation helpers + +bool CVocodecs::DiscoverFtdiDevices(void) +{ + bool ok = false; + int iNbDevices = 0; + FT_DEVICE_LIST_INFO_NODE *list; + + // clear vector + for ( int i = 0; i < m_FtdiDeviceDescrs.size(); i++ ) + { + delete m_FtdiDeviceDescrs[i]; + } + + // and discover + if ( FT_CreateDeviceInfoList((LPDWORD)&iNbDevices) == FT_OK ) + { + std::cout << "Detected " << iNbDevices << " USB-FTDI devices" << std::endl << std::endl; + ok = true; + if ( iNbDevices > 0 ) + { + // allocate the list + list = new FT_DEVICE_LIST_INFO_NODE[iNbDevices]; + + // fill + if ( FT_GetDeviceInfoList(list, (LPDWORD)&iNbDevices) == FT_OK ) + { + // process + for ( int i = 0; i < iNbDevices; i++ ) + { + std::cout << "Description : " << list[i].Description << "\t Serial : " << list[i].SerialNumber << std::endl; + CFtdiDeviceDescr *descr = new CFtdiDeviceDescr( + LOWORD(list[i].ID), HIWORD(list[i].ID), + list[i].Description, list[i].SerialNumber); + m_FtdiDeviceDescrs.push_back(descr); + } + } + else + { + ok = false; + } + + // and delete + delete list; + } + } + + // done + return ok; +} + +int CVocodecs::InitUsb3012(const CFtdiDeviceDescr &descr) +{ + int nStreams = 0; + + // create the interfaces for the four 3003 chips + CUsb3003Interface *Usb3003A = new CUsb3003Interface(descr.GetVid(), descr.GetPid(), "USB-3012_A", descr.GetSerialNumber()); + CUsb3003Interface *Usb3003B = new CUsb3003Interface(descr.GetVid(), descr.GetPid(), "USB-3012_B", descr.GetSerialNumber()); + CUsb3003Interface *Usb3003C = new CUsb3003Interface(descr.GetVid(), descr.GetPid(), "USB-3012_C", descr.GetSerialNumber()); + CUsb3003Interface *Usb3003D = new CUsb3003Interface(descr.GetVid(), descr.GetPid(), "USB-3012_D", descr.GetSerialNumber()); + + // init the interfaces + if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) && + Usb3003C->Init(CODEC_AMBEPLUS) && Usb3003D->Init(CODEC_AMBE2PLUS) ) + { + CVocodecChannel *Channel; + // create all channels + { + // ch1 + Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS); + m_Channels.push_back(Channel); + Usb3003A->AddChannel(Channel); + // ch2 + Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS); + m_Channels.push_back(Channel); + Usb3003A->AddChannel(Channel); + // ch3 + Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS); + m_Channels.push_back(Channel); + Usb3003B->AddChannel(Channel); + // ch4 + Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS); + m_Channels.push_back(Channel); + Usb3003B->AddChannel(Channel); + // ch5 + Channel = new CVocodecChannel(Usb3003C, 0, Usb3003C, 1, CODECGAIN_AMBEPLUS); + m_Channels.push_back(Channel); + Usb3003C->AddChannel(Channel); + // ch6 + Channel = new CVocodecChannel(Usb3003C, 1, Usb3003C, 0, CODECGAIN_AMBE2PLUS); + m_Channels.push_back(Channel); + Usb3003C->AddChannel(Channel); + // ch7 + Channel = new CVocodecChannel(Usb3003D, 0, Usb3003D, 1, CODECGAIN_AMBEPLUS); + m_Channels.push_back(Channel); + Usb3003D->AddChannel(Channel); + // ch8 + Channel = new CVocodecChannel(Usb3003D, 1, Usb3003D, 0, CODECGAIN_AMBE2PLUS); + m_Channels.push_back(Channel); + Usb3003D->AddChannel(Channel); + // ch9 + Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS); + m_Channels.push_back(Channel); + Usb3003A->AddChannel(Channel); + Usb3003B->AddChannel(Channel); + // ch10 + Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS); + m_Channels.push_back(Channel); + Usb3003A->AddChannel(Channel); + Usb3003B->AddChannel(Channel); + // ch11 + Channel = new CVocodecChannel(Usb3003C, 2, Usb3003D, 2, CODECGAIN_AMBEPLUS); + m_Channels.push_back(Channel); + Usb3003C->AddChannel(Channel); + Usb3003D->AddChannel(Channel); + // ch12 + Channel = new CVocodecChannel(Usb3003D, 2, Usb3003C, 2, CODECGAIN_AMBE2PLUS); + m_Channels.push_back(Channel); + Usb3003C->AddChannel(Channel); + Usb3003D->AddChannel(Channel); + //done + nStreams = 12; + } + } + else + { + // cleanup + delete Usb3003A; + delete Usb3003B; + delete Usb3003C; + delete Usb3003D; + } + + // done + return nStreams; +} + +int CVocodecs::InitUsb3003(const CFtdiDeviceDescr &descr) +{ + int nStreams = 0; + + // create the interfaces for the 3003 chip + CUsb3003Interface *Usb3003 = new CUsb3003Interface(descr.GetVid(), descr.GetPid(), "USB-3003", descr.GetSerialNumber()); + + // init the interface + if ( Usb3003->Init(CODEC_NONE) ) + { + CVocodecChannel *Channel; + // create all channels + { + // ch1 + Channel = new CVocodecChannel(Usb3003, 0, Usb3003, 1, CODECGAIN_AMBEPLUS); + m_Channels.push_back(Channel); + Usb3003->AddChannel(Channel); + // ch2 + Channel = new CVocodecChannel(Usb3003, 1, Usb3003, 0, CODECGAIN_AMBE2PLUS); + m_Channels.push_back(Channel); + Usb3003->AddChannel(Channel); + // done + nStreams = 2; + } + } + else + { + // cleanup + delete Usb3003; + } + + // done + return nStreams; +} + +int CVocodecs::InitUsb3003Pair(const CFtdiDeviceDescr &descr1, const CFtdiDeviceDescr &descr2) +{ + int nStreams = 0; + + // create the interfaces for the two 3003 chips + CUsb3003Interface *Usb3003A = new CUsb3003Interface(descr1.GetVid(), descr1.GetPid(), "USB-3003", descr1.GetSerialNumber()); + CUsb3003Interface *Usb3003B = new CUsb3003Interface(descr2.GetVid(), descr2.GetPid(), "USB-3003", descr2.GetSerialNumber()); + + // init the interfaces + if ( Usb3003A->Init(CODEC_AMBEPLUS) && Usb3003B->Init(CODEC_AMBE2PLUS) ) + { + CVocodecChannel *Channel; + // create all channels + { + // ch1 + Channel = new CVocodecChannel(Usb3003A, 0, Usb3003A, 1, CODECGAIN_AMBEPLUS); + m_Channels.push_back(Channel); + Usb3003A->AddChannel(Channel); + // ch2 + Channel = new CVocodecChannel(Usb3003A, 1, Usb3003A, 0, CODECGAIN_AMBE2PLUS); + m_Channels.push_back(Channel); + Usb3003A->AddChannel(Channel); + // ch3 + Channel = new CVocodecChannel(Usb3003B, 0, Usb3003B, 1, CODECGAIN_AMBEPLUS); + m_Channels.push_back(Channel); + Usb3003B->AddChannel(Channel); + // ch4 + Channel = new CVocodecChannel(Usb3003B, 1, Usb3003B, 0, CODECGAIN_AMBE2PLUS); + m_Channels.push_back(Channel); + Usb3003B->AddChannel(Channel); + // ch5 + Channel = new CVocodecChannel(Usb3003A, 2, Usb3003B, 2, CODECGAIN_AMBEPLUS); + m_Channels.push_back(Channel); + Usb3003A->AddChannel(Channel); + Usb3003B->AddChannel(Channel); + // ch6 + Channel = new CVocodecChannel(Usb3003B, 2, Usb3003A, 2, CODECGAIN_AMBE2PLUS); + m_Channels.push_back(Channel); + Usb3003A->AddChannel(Channel); + Usb3003B->AddChannel(Channel); + // done + nStreams = 6; + } + } + else + { + // cleanup + delete Usb3003A; + delete Usb3003B; + } + + // done + return nStreams; +} + +//////////////////////////////////////////////////////////////////////////////////////// +// manage channels + +CVocodecChannel *CVocodecs::OpenChannel(uint8 uiCodecIn, uint8 uiCodecOut) +{ + CVocodecChannel *Channel = NULL; + bool done = false; + + // loop on all interface until suitable & available channel found + m_MutexChannels.lock(); + for ( int i = 0; (i < m_Channels.size()) && !done; i++ ) + { + if ( !m_Channels[i]->IsOpen() && + (m_Channels[i]->GetCodecIn() == uiCodecIn) && + (m_Channels[i]->GetCodecOut() == uiCodecOut) ) + { + if ( m_Channels[i]->Open() ) + { + Channel = m_Channels[i]; + done = true; + } + } + } + m_MutexChannels.unlock(); + + // done + return Channel; +} + +void CVocodecs::CloseChannel(CVocodecChannel *Channel) +{ + Channel->Close(); +} diff --git a/ambed/cvocodecs.h b/ambed/cvocodecs.h new file mode 100644 index 0000000..6688ebb --- /dev/null +++ b/ambed/cvocodecs.h @@ -0,0 +1,78 @@ +// +// cvocodecs.h +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 23/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cvocodecs_h +#define cvocodecs_h + +#include "cftdidevicedescr.h" +#include "cvocodecinterface.h" +#include "cvocodecchannel.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CVocodecs +{ +public: + // constructors + CVocodecs(); + + // destructor + virtual ~CVocodecs(); + + // initialization + bool Init(void); + + // manage interfaces + int GetNbInterfaces(void) const { return (int)m_Interfaces.size(); } + CVocodecInterface *GetInterface(int); + + // manage channels + CVocodecChannel *OpenChannel(uint8, uint8); + void AddChannel(CVocodecChannel *ch) { m_Channels.push_back(ch); } + void CloseChannel(CVocodecChannel *); + +protected: + // initialisation helpers + bool DiscoverFtdiDevices(void); + int InitUsb3012(const CFtdiDeviceDescr &); + int InitUsb3003(const CFtdiDeviceDescr &); + int InitUsb3003Pair(const CFtdiDeviceDescr &, const CFtdiDeviceDescr &); + int InitUsb3000Pair(const CFtdiDeviceDescr &, const CFtdiDeviceDescr &); + +protected: + // array of interfaces + std::mutex m_MutexInterfaces; + std::vector m_Interfaces; + + // array of channels + std::mutex m_MutexChannels; + std::vector m_Channels; + + // array of FTDI desciptors + std::vector m_FtdiDeviceDescrs; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cvocodecs_h */ diff --git a/ambed/cvoicepacket.cpp b/ambed/cvoicepacket.cpp new file mode 100644 index 0000000..0fc05f7 --- /dev/null +++ b/ambed/cvoicepacket.cpp @@ -0,0 +1,86 @@ +// +// cvoicepacket.cpp +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include +#include +#include "cvoicepacket.h" + + +//////////////////////////////////////////////////////////////////////////////////////// +// constructor + +CVoicePacket::CVoicePacket() +{ + m_iSize = 0; + ::memset(m_uiVoice, 0, sizeof(m_uiVoice)); +} + +CVoicePacket::CVoicePacket(const uint8 *voice, int size) +{ + m_iSize = MIN(size, sizeof(m_uiVoice)); + ::memset(m_uiVoice, 0, sizeof(m_uiVoice)); + ::memcpy(m_uiVoice, voice, m_iSize); +} + +CVoicePacket::CVoicePacket(const CVoicePacket &packet) + : CPacket(packet) +{ + m_iSize = packet.m_iSize; + ::memcpy(m_uiVoice, packet.m_uiVoice, sizeof(m_uiVoice)); +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// destructor + +CVoicePacket::~CVoicePacket() +{ +} + +//////////////////////////////////////////////////////////////////////////////////////// +// Set + +void CVoicePacket::SetVoice(const uint8 *voice, int size) +{ + m_iSize = MIN(size, sizeof(m_uiVoice)); + ::memset(m_uiVoice, 0, sizeof(m_uiVoice)); + ::memcpy(m_uiVoice, voice, m_iSize); +} + + +//////////////////////////////////////////////////////////////////////////////////////// +// gain + +void CVoicePacket::ApplyGain(int dB) +{ + float mult = pow(10, dB/20.0); + for ( int i = 0; i < m_iSize; i += 2 ) + { + float smp = (float)(short)MAKEWORD(m_uiVoice[i+1], m_uiVoice[i]); + smp *= mult; + m_uiVoice[i] = HIBYTE((short)smp); + m_uiVoice[i+1] = LOBYTE((short)smp); + } +} diff --git a/ambed/cvoicepacket.h b/ambed/cvoicepacket.h new file mode 100644 index 0000000..7189d01 --- /dev/null +++ b/ambed/cvoicepacket.h @@ -0,0 +1,68 @@ +// +// cvoicepacket.h +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 28/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef cvoicepacket_h +#define cvoicepacket_h + + +#include "cpacket.h" + +//////////////////////////////////////////////////////////////////////////////////////// +// define + +// frame sizes +#define VOICE_SIZEMAX 512 + +//////////////////////////////////////////////////////////////////////////////////////// +// class + +class CVoicePacket : public CPacket +{ +public: + // constructors + CVoicePacket(); + CVoicePacket(const uint8 *, int); + CVoicePacket(const CVoicePacket &); + + // destructor + virtual ~CVoicePacket(); + + // get + uint8 *GetVoice(void) { return m_uiVoice; } + int GetVoiceSize(void) const { return m_iSize; } + + // set + void SetVoice(const uint8 *, int); + + // gain + void ApplyGain(int); + +protected: + // data + int m_iSize; + uint8 m_uiVoice[VOICE_SIZEMAX]; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* cvoicepacket_h */ diff --git a/ambed/ftd2xx.h b/ambed/ftd2xx.h new file mode 100755 index 0000000..e5bbb46 --- /dev/null +++ b/ambed/ftd2xx.h @@ -0,0 +1,1443 @@ +/*++ + +Copyright © 2001-2011 Future Technology Devices International Limited + +THIS SOFTWARE IS PROVIDED BY FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED "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 +FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED 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. + +FTDI DRIVERS MAY BE USED ONLY IN CONJUNCTION WITH PRODUCTS BASED ON FTDI PARTS. + +FTDI DRIVERS MAY BE DISTRIBUTED IN ANY FORM AS LONG AS LICENSE INFORMATION IS NOT MODIFIED. + +IF A CUSTOM VENDOR ID AND/OR PRODUCT ID OR DESCRIPTION STRING ARE USED, IT IS THE +RESPONSIBILITY OF THE PRODUCT MANUFACTURER TO MAINTAIN ANY CHANGES AND SUBSEQUENT WHQL +RE-CERTIFICATION AS A RESULT OF MAKING THESE CHANGES. + + +Module Name: + +ftd2xx.h + +Abstract: + +Native USB device driver for FTDI FT232x, FT245x, FT2232x and FT4232x devices +FTD2XX library definitions + +Environment: + +kernel & user mode + + +--*/ + + +#ifndef FTD2XX_H +#define FTD2XX_H + +#ifdef _WIN32 +// Compiling on Windows +#include + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// FTD2XX_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef FTD2XX_EXPORTS +#define FTD2XX_API __declspec(dllexport) +#elif defined(FTD2XX_STATIC) +// Avoid decorations when linking statically to D2XX. +#define FTD2XX_API +// Static D2XX depends on these Windows libs: +#pragma comment(lib, "setupapi.lib") +#pragma comment(lib, "advapi32.lib") +#pragma comment(lib, "user32.lib") +#else +#define FTD2XX_API __declspec(dllimport) +#endif + +#else // _WIN32 +// Compiling on non-Windows platform. +#include "WinTypes.h" +// No decorations needed. +#define FTD2XX_API + +#endif // _WIN32 + +typedef PVOID FT_HANDLE; +typedef ULONG FT_STATUS; + +// +// Device status +// +enum { + FT_OK, + FT_INVALID_HANDLE, + FT_DEVICE_NOT_FOUND, + FT_DEVICE_NOT_OPENED, + FT_IO_ERROR, + FT_INSUFFICIENT_RESOURCES, + FT_INVALID_PARAMETER, + FT_INVALID_BAUD_RATE, + + FT_DEVICE_NOT_OPENED_FOR_ERASE, + FT_DEVICE_NOT_OPENED_FOR_WRITE, + FT_FAILED_TO_WRITE_DEVICE, + FT_EEPROM_READ_FAILED, + FT_EEPROM_WRITE_FAILED, + FT_EEPROM_ERASE_FAILED, + FT_EEPROM_NOT_PRESENT, + FT_EEPROM_NOT_PROGRAMMED, + FT_INVALID_ARGS, + FT_NOT_SUPPORTED, + FT_OTHER_ERROR, + FT_DEVICE_LIST_NOT_READY, +}; + + +#define FT_SUCCESS(status) ((status) == FT_OK) + +// +// FT_OpenEx Flags +// + +#define FT_OPEN_BY_SERIAL_NUMBER 1 +#define FT_OPEN_BY_DESCRIPTION 2 +#define FT_OPEN_BY_LOCATION 4 + +#define FT_OPEN_MASK (FT_OPEN_BY_SERIAL_NUMBER | \ + FT_OPEN_BY_DESCRIPTION | \ + FT_OPEN_BY_LOCATION) + +// +// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags +// + +#define FT_LIST_NUMBER_ONLY 0x80000000 +#define FT_LIST_BY_INDEX 0x40000000 +#define FT_LIST_ALL 0x20000000 + +#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) + +// +// Baud Rates +// + +#define FT_BAUD_300 300 +#define FT_BAUD_600 600 +#define FT_BAUD_1200 1200 +#define FT_BAUD_2400 2400 +#define FT_BAUD_4800 4800 +#define FT_BAUD_9600 9600 +#define FT_BAUD_14400 14400 +#define FT_BAUD_19200 19200 +#define FT_BAUD_38400 38400 +#define FT_BAUD_57600 57600 +#define FT_BAUD_115200 115200 +#define FT_BAUD_230400 230400 +#define FT_BAUD_460800 460800 +#define FT_BAUD_921600 921600 + +// +// Word Lengths +// + +#define FT_BITS_8 (UCHAR) 8 +#define FT_BITS_7 (UCHAR) 7 + +// +// Stop Bits +// + +#define FT_STOP_BITS_1 (UCHAR) 0 +#define FT_STOP_BITS_2 (UCHAR) 2 + +// +// Parity +// + +#define FT_PARITY_NONE (UCHAR) 0 +#define FT_PARITY_ODD (UCHAR) 1 +#define FT_PARITY_EVEN (UCHAR) 2 +#define FT_PARITY_MARK (UCHAR) 3 +#define FT_PARITY_SPACE (UCHAR) 4 + +// +// Flow Control +// + +#define FT_FLOW_NONE 0x0000 +#define FT_FLOW_RTS_CTS 0x0100 +#define FT_FLOW_DTR_DSR 0x0200 +#define FT_FLOW_XON_XOFF 0x0400 + +// +// Purge rx and tx buffers +// +#define FT_PURGE_RX 1 +#define FT_PURGE_TX 2 + +// +// Events +// + +typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); + +#define FT_EVENT_RXCHAR 1 +#define FT_EVENT_MODEM_STATUS 2 +#define FT_EVENT_LINE_STATUS 4 + +// +// Timeouts +// + +#define FT_DEFAULT_RX_TIMEOUT 300 +#define FT_DEFAULT_TX_TIMEOUT 300 + +// +// Device types +// + +typedef ULONG FT_DEVICE; + +enum { + FT_DEVICE_BM, + FT_DEVICE_AM, + FT_DEVICE_100AX, + FT_DEVICE_UNKNOWN, + FT_DEVICE_2232C, + FT_DEVICE_232R, + FT_DEVICE_2232H, + FT_DEVICE_4232H, + FT_DEVICE_232H, + FT_DEVICE_X_SERIES, + FT_DEVICE_4222H_0, + FT_DEVICE_4222H_1_2, + FT_DEVICE_4222H_3, + FT_DEVICE_4222_PROG, +}; + +// +// Bit Modes +// + +#define FT_BITMODE_RESET 0x00 +#define FT_BITMODE_ASYNC_BITBANG 0x01 +#define FT_BITMODE_MPSSE 0x02 +#define FT_BITMODE_SYNC_BITBANG 0x04 +#define FT_BITMODE_MCU_HOST 0x08 +#define FT_BITMODE_FAST_SERIAL 0x10 +#define FT_BITMODE_CBUS_BITBANG 0x20 +#define FT_BITMODE_SYNC_FIFO 0x40 + +// +// FT232R CBUS Options EEPROM values +// + +#define FT_232R_CBUS_TXDEN 0x00 // Tx Data Enable +#define FT_232R_CBUS_PWRON 0x01 // Power On +#define FT_232R_CBUS_RXLED 0x02 // Rx LED +#define FT_232R_CBUS_TXLED 0x03 // Tx LED +#define FT_232R_CBUS_TXRXLED 0x04 // Tx and Rx LED +#define FT_232R_CBUS_SLEEP 0x05 // Sleep +#define FT_232R_CBUS_CLK48 0x06 // 48MHz clock +#define FT_232R_CBUS_CLK24 0x07 // 24MHz clock +#define FT_232R_CBUS_CLK12 0x08 // 12MHz clock +#define FT_232R_CBUS_CLK6 0x09 // 6MHz clock +#define FT_232R_CBUS_IOMODE 0x0A // IO Mode for CBUS bit-bang +#define FT_232R_CBUS_BITBANG_WR 0x0B // Bit-bang write strobe +#define FT_232R_CBUS_BITBANG_RD 0x0C // Bit-bang read strobe + +// +// FT232H CBUS Options EEPROM values +// + +#define FT_232H_CBUS_TRISTATE 0x00 // Tristate +#define FT_232H_CBUS_TXLED 0x01 // Tx LED +#define FT_232H_CBUS_RXLED 0x02 // Rx LED +#define FT_232H_CBUS_TXRXLED 0x03 // Tx and Rx LED +#define FT_232H_CBUS_PWREN 0x04 // Power Enable +#define FT_232H_CBUS_SLEEP 0x05 // Sleep +#define FT_232H_CBUS_DRIVE_0 0x06 // Drive pin to logic 0 +#define FT_232H_CBUS_DRIVE_1 0x07 // Drive pin to logic 1 +#define FT_232H_CBUS_IOMODE 0x08 // IO Mode for CBUS bit-bang +#define FT_232H_CBUS_TXDEN 0x09 // Tx Data Enable +#define FT_232H_CBUS_CLK30 0x0A // 30MHz clock +#define FT_232H_CBUS_CLK15 0x0B // 15MHz clock +#define FT_232H_CBUS_CLK7_5 0x0C // 7.5MHz clock + +// +// FT X Series CBUS Options EEPROM values +// + +#define FT_X_SERIES_CBUS_TRISTATE 0x00 // Tristate +#define FT_X_SERIES_CBUS_TXLED 0x01 // Tx LED +#define FT_X_SERIES_CBUS_RXLED 0x02 // Rx LED +#define FT_X_SERIES_CBUS_TXRXLED 0x03 // Tx and Rx LED +#define FT_X_SERIES_CBUS_PWREN 0x04 // Power Enable +#define FT_X_SERIES_CBUS_SLEEP 0x05 // Sleep +#define FT_X_SERIES_CBUS_DRIVE_0 0x06 // Drive pin to logic 0 +#define FT_X_SERIES_CBUS_DRIVE_1 0x07 // Drive pin to logic 1 +#define FT_X_SERIES_CBUS_IOMODE 0x08 // IO Mode for CBUS bit-bang +#define FT_X_SERIES_CBUS_TXDEN 0x09 // Tx Data Enable +#define FT_X_SERIES_CBUS_CLK24 0x0A // 24MHz clock +#define FT_X_SERIES_CBUS_CLK12 0x0B // 12MHz clock +#define FT_X_SERIES_CBUS_CLK6 0x0C // 6MHz clock +#define FT_X_SERIES_CBUS_BCD_CHARGER 0x0D // Battery charger detected +#define FT_X_SERIES_CBUS_BCD_CHARGER_N 0x0E // Battery charger detected inverted +#define FT_X_SERIES_CBUS_I2C_TXE 0x0F // I2C Tx empty +#define FT_X_SERIES_CBUS_I2C_RXF 0x10 // I2C Rx full +#define FT_X_SERIES_CBUS_VBUS_SENSE 0x11 // Detect VBUS +#define FT_X_SERIES_CBUS_BITBANG_WR 0x12 // Bit-bang write strobe +#define FT_X_SERIES_CBUS_BITBANG_RD 0x13 // Bit-bang read strobe +#define FT_X_SERIES_CBUS_TIMESTAMP 0x14 // Toggle output when a USB SOF token is received +#define FT_X_SERIES_CBUS_KEEP_AWAKE 0x15 // + + +// Driver types +#define FT_DRIVER_TYPE_D2XX 0 +#define FT_DRIVER_TYPE_VCP 1 + + + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef FTD2XX_STATIC + FTD2XX_API + FT_STATUS WINAPI FT_Initialise( + void + ); + + FTD2XX_API + void WINAPI FT_Finalise( + void + ); +#endif // FTD2XX_STATIC + + FTD2XX_API + FT_STATUS WINAPI FT_Open( + int deviceNumber, + FT_HANDLE *pHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_OpenEx( + PVOID pArg1, + DWORD Flags, + FT_HANDLE *pHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_ListDevices( + PVOID pArg1, + PVOID pArg2, + DWORD Flags + ); + + FTD2XX_API + FT_STATUS WINAPI FT_Close( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_Read( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD dwBytesToRead, + LPDWORD lpBytesReturned + ); + + FTD2XX_API + FT_STATUS WINAPI FT_Write( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD dwBytesToWrite, + LPDWORD lpBytesWritten + ); + + FTD2XX_API + FT_STATUS WINAPI FT_IoCtl( + FT_HANDLE ftHandle, + DWORD dwIoControlCode, + LPVOID lpInBuf, + DWORD nInBufSize, + LPVOID lpOutBuf, + DWORD nOutBufSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetBaudRate( + FT_HANDLE ftHandle, + ULONG BaudRate + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetDivisor( + FT_HANDLE ftHandle, + USHORT Divisor + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetDataCharacteristics( + FT_HANDLE ftHandle, + UCHAR WordLength, + UCHAR StopBits, + UCHAR Parity + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetFlowControl( + FT_HANDLE ftHandle, + USHORT FlowControl, + UCHAR XonChar, + UCHAR XoffChar + ); + + FTD2XX_API + FT_STATUS WINAPI FT_ResetDevice( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetDtr( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_ClrDtr( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetRts( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_ClrRts( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetModemStatus( + FT_HANDLE ftHandle, + ULONG *pModemStatus + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetChars( + FT_HANDLE ftHandle, + UCHAR EventChar, + UCHAR EventCharEnabled, + UCHAR ErrorChar, + UCHAR ErrorCharEnabled + ); + + FTD2XX_API + FT_STATUS WINAPI FT_Purge( + FT_HANDLE ftHandle, + ULONG Mask + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetTimeouts( + FT_HANDLE ftHandle, + ULONG ReadTimeout, + ULONG WriteTimeout + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetQueueStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetEventNotification( + FT_HANDLE ftHandle, + DWORD Mask, + PVOID Param + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes, + DWORD *dwTxBytes, + DWORD *dwEventDWord + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetBreakOn( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetBreakOff( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetWaitMask( + FT_HANDLE ftHandle, + DWORD Mask + ); + + FTD2XX_API + FT_STATUS WINAPI FT_WaitOnMask( + FT_HANDLE ftHandle, + DWORD *Mask + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetEventStatus( + FT_HANDLE ftHandle, + DWORD *dwEventDWord + ); + + FTD2XX_API + FT_STATUS WINAPI FT_ReadEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + LPWORD lpwValue + ); + + FTD2XX_API + FT_STATUS WINAPI FT_WriteEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + WORD wValue + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EraseEE( + FT_HANDLE ftHandle + ); + + // + // structure to hold program data for FT_EE_Program, FT_EE_ProgramEx, FT_EE_Read + // and FT_EE_ReadEx functions + // + typedef struct ft_program_data { + + DWORD Signature1; // Header - must be 0x00000000 + DWORD Signature2; // Header - must be 0xffffffff + DWORD Version; // Header - FT_PROGRAM_DATA version + // 0 = original + // 1 = FT2232 extensions + // 2 = FT232R extensions + // 3 = FT2232H extensions + // 4 = FT4232H extensions + // 5 = FT232H extensions + + WORD VendorId; // 0x0403 + WORD ProductId; // 0x6001 + char *Manufacturer; // "FTDI" + char *ManufacturerId; // "FT" + char *Description; // "USB HS Serial Converter" + char *SerialNumber; // "FT000001" if fixed, or NULL + WORD MaxPower; // 0 < MaxPower <= 500 + WORD PnP; // 0 = disabled, 1 = enabled + WORD SelfPowered; // 0 = bus powered, 1 = self powered + WORD RemoteWakeup; // 0 = not capable, 1 = capable + // + // Rev4 (FT232B) extensions + // + UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise + UCHAR IsoIn; // non-zero if in endpoint is isochronous + UCHAR IsoOut; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable; // non-zero if pull down enabled + UCHAR SerNumEnable; // non-zero if serial number to be used + UCHAR USBVersionEnable; // non-zero if chip uses USBVersion + WORD USBVersion; // BCD (0x0200 => USB2) + // + // Rev 5 (FT2232) extensions + // + UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise + UCHAR IsoInA; // non-zero if in endpoint is isochronous + UCHAR IsoInB; // non-zero if in endpoint is isochronous + UCHAR IsoOutA; // non-zero if out endpoint is isochronous + UCHAR IsoOutB; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable5; // non-zero if pull down enabled + UCHAR SerNumEnable5; // non-zero if serial number to be used + UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion + WORD USBVersion5; // BCD (0x0200 => USB2) + UCHAR AIsHighCurrent; // non-zero if interface is high current + UCHAR BIsHighCurrent; // non-zero if interface is high current + UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer; // non-zero if interface is Fast serial + UCHAR AIsVCP; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsVCP; // non-zero if interface is to use VCP drivers + // + // Rev 6 (FT232R) extensions + // + UCHAR UseExtOsc; // Use External Oscillator + UCHAR HighDriveIOs; // High Drive I/Os + UCHAR EndpointSize; // Endpoint size + UCHAR PullDownEnableR; // non-zero if pull down enabled + UCHAR SerNumEnableR; // non-zero if serial number to be used + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + UCHAR RIsD2XX; // non-zero if using D2XX driver + // + // Rev 7 (FT2232H) Extensions + // + UCHAR PullDownEnable7; // non-zero if pull down enabled + UCHAR SerNumEnable7; // non-zero if serial number to be used + UCHAR ALSlowSlew; // non-zero if AL pins have slow slew + UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input + UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR AHSlowSlew; // non-zero if AH pins have slow slew + UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input + UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BLSlowSlew; // non-zero if BL pins have slow slew + UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input + UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BHSlowSlew; // non-zero if BH pins have slow slew + UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input + UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR IFAIsFifo7; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar7; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer7; // non-zero if interface is Fast serial + UCHAR AIsVCP7; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo7; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar7; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer7; // non-zero if interface is Fast serial + UCHAR BIsVCP7; // non-zero if interface is to use VCP drivers + UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs + // + // Rev 8 (FT4232H) Extensions + // + UCHAR PullDownEnable8; // non-zero if pull down enabled + UCHAR SerNumEnable8; // non-zero if serial number to be used + UCHAR ASlowSlew; // non-zero if A pins have slow slew + UCHAR ASchmittInput; // non-zero if A pins are Schmitt input + UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BSlowSlew; // non-zero if B pins have slow slew + UCHAR BSchmittInput; // non-zero if B pins are Schmitt input + UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR CSlowSlew; // non-zero if C pins have slow slew + UCHAR CSchmittInput; // non-zero if C pins are Schmitt input + UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR DSlowSlew; // non-zero if D pins have slow slew + UCHAR DSchmittInput; // non-zero if D pins are Schmitt input + UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN + UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN + UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN + UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN + UCHAR AIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR BIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR CIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR DIsVCP8; // non-zero if interface is to use VCP drivers + // + // Rev 9 (FT232H) Extensions + // + UCHAR PullDownEnableH; // non-zero if pull down enabled + UCHAR SerNumEnableH; // non-zero if serial number to be used + UCHAR ACSlowSlewH; // non-zero if AC pins have slow slew + UCHAR ACSchmittInputH; // non-zero if AC pins are Schmitt input + UCHAR ACDriveCurrentH; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR ADSlowSlewH; // non-zero if AD pins have slow slew + UCHAR ADSchmittInputH; // non-zero if AD pins are Schmitt input + UCHAR ADDriveCurrentH; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR Cbus0H; // Cbus Mux control + UCHAR Cbus1H; // Cbus Mux control + UCHAR Cbus2H; // Cbus Mux control + UCHAR Cbus3H; // Cbus Mux control + UCHAR Cbus4H; // Cbus Mux control + UCHAR Cbus5H; // Cbus Mux control + UCHAR Cbus6H; // Cbus Mux control + UCHAR Cbus7H; // Cbus Mux control + UCHAR Cbus8H; // Cbus Mux control + UCHAR Cbus9H; // Cbus Mux control + UCHAR IsFifoH; // non-zero if interface is 245 FIFO + UCHAR IsFifoTarH; // non-zero if interface is 245 FIFO CPU target + UCHAR IsFastSerH; // non-zero if interface is Fast serial + UCHAR IsFT1248H; // non-zero if interface is FT1248 + UCHAR FT1248CpolH; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) + UCHAR FT1248LsbH; // FT1248 data is LSB (1) or MSB (0) + UCHAR FT1248FlowControlH; // FT1248 flow control enable + UCHAR IsVCPH; // non-zero if interface is to use VCP drivers + UCHAR PowerSaveEnableH; // non-zero if using ACBUS7 to save power for self-powered designs + + } FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; + + FTD2XX_API + FT_STATUS WINAPI FT_EE_Program( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EE_ProgramEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EE_Read( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EE_ReadEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EE_UASize( + FT_HANDLE ftHandle, + LPDWORD lpdwSize + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EE_UAWrite( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EE_UARead( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen, + LPDWORD lpdwBytesRead + ); + + + typedef struct ft_eeprom_header { + FT_DEVICE deviceType; // FTxxxx device type to be programmed + // Device descriptor options + WORD VendorId; // 0x0403 + WORD ProductId; // 0x6001 + UCHAR SerNumEnable; // non-zero if serial number to be used + // Config descriptor options + WORD MaxPower; // 0 < MaxPower <= 500 + UCHAR SelfPowered; // 0 = bus powered, 1 = self powered + UCHAR RemoteWakeup; // 0 = not capable, 1 = capable + // Hardware options + UCHAR PullDownEnable; // non-zero if pull down in suspend enabled + } FT_EEPROM_HEADER, *PFT_EEPROM_HEADER; + + + // FT232B EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program + typedef struct ft_eeprom_232b { + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + } FT_EEPROM_232B, *PFT_EEPROM_232B; + + + // FT2232 EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program + typedef struct ft_eeprom_2232 { + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR AIsHighCurrent; // non-zero if interface is high current + UCHAR BIsHighCurrent; // non-zero if interface is high current + // Hardware options + UCHAR AIsFifo; // non-zero if interface is 245 FIFO + UCHAR AIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR AIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsFifo; // non-zero if interface is 245 FIFO + UCHAR BIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR BIsFastSer; // non-zero if interface is Fast serial + // Driver option + UCHAR ADriverType; // + UCHAR BDriverType; // + } FT_EEPROM_2232, *PFT_EEPROM_2232; + + + // FT232R EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program + typedef struct ft_eeprom_232r { + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR IsHighCurrent; // non-zero if interface is high current + // Hardware options + UCHAR UseExtOsc; // Use External Oscillator + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + // Driver option + UCHAR DriverType; // + } FT_EEPROM_232R, *PFT_EEPROM_232R; + + + // FT2232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program + typedef struct ft_eeprom_2232h { + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR ALSlowSlew; // non-zero if AL pins have slow slew + UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input + UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR AHSlowSlew; // non-zero if AH pins have slow slew + UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input + UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BLSlowSlew; // non-zero if BL pins have slow slew + UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input + UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BHSlowSlew; // non-zero if BH pins have slow slew + UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input + UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + // Hardware options + UCHAR AIsFifo; // non-zero if interface is 245 FIFO + UCHAR AIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR AIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsFifo; // non-zero if interface is 245 FIFO + UCHAR BIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR BIsFastSer; // non-zero if interface is Fast serial + UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs + // Driver option + UCHAR ADriverType; // + UCHAR BDriverType; // + } FT_EEPROM_2232H, *PFT_EEPROM_2232H; + + + // FT4232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program + typedef struct ft_eeprom_4232h { + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR ASlowSlew; // non-zero if A pins have slow slew + UCHAR ASchmittInput; // non-zero if A pins are Schmitt input + UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BSlowSlew; // non-zero if B pins have slow slew + UCHAR BSchmittInput; // non-zero if B pins are Schmitt input + UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR CSlowSlew; // non-zero if C pins have slow slew + UCHAR CSchmittInput; // non-zero if C pins are Schmitt input + UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR DSlowSlew; // non-zero if D pins have slow slew + UCHAR DSchmittInput; // non-zero if D pins are Schmitt input + UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + // Hardware options + UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN + UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN + UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN + UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN + // Driver option + UCHAR ADriverType; // + UCHAR BDriverType; // + UCHAR CDriverType; // + UCHAR DDriverType; // + } FT_EEPROM_4232H, *PFT_EEPROM_4232H; + + + // FT232H EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program + typedef struct ft_eeprom_232h { + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR ACSlowSlew; // non-zero if AC bus pins have slow slew + UCHAR ACSchmittInput; // non-zero if AC bus pins are Schmitt input + UCHAR ACDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR ADSlowSlew; // non-zero if AD bus pins have slow slew + UCHAR ADSchmittInput; // non-zero if AD bus pins are Schmitt input + UCHAR ADDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + // CBUS options + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + UCHAR Cbus5; // Cbus Mux control + UCHAR Cbus6; // Cbus Mux control + UCHAR Cbus7; // Cbus Mux control + UCHAR Cbus8; // Cbus Mux control + UCHAR Cbus9; // Cbus Mux control + // FT1248 options + UCHAR FT1248Cpol; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) + UCHAR FT1248Lsb; // FT1248 data is LSB (1) or MSB (0) + UCHAR FT1248FlowControl; // FT1248 flow control enable + // Hardware options + UCHAR IsFifo; // non-zero if interface is 245 FIFO + UCHAR IsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IsFastSer; // non-zero if interface is Fast serial + UCHAR IsFT1248 ; // non-zero if interface is FT1248 + UCHAR PowerSaveEnable; // + // Driver option + UCHAR DriverType; // + } FT_EEPROM_232H, *PFT_EEPROM_232H; + + + // FT X Series EEPROM structure for use with FT_EEPROM_Read and FT_EEPROM_Program + typedef struct ft_eeprom_x_series { + // Common header + FT_EEPROM_HEADER common; // common elements for all device EEPROMs + // Drive options + UCHAR ACSlowSlew; // non-zero if AC bus pins have slow slew + UCHAR ACSchmittInput; // non-zero if AC bus pins are Schmitt input + UCHAR ACDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR ADSlowSlew; // non-zero if AD bus pins have slow slew + UCHAR ADSchmittInput; // non-zero if AD bus pins are Schmitt input + UCHAR ADDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + // CBUS options + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + UCHAR Cbus5; // Cbus Mux control + UCHAR Cbus6; // Cbus Mux control + // UART signal options + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + // Battery Charge Detect options + UCHAR BCDEnable; // Enable Battery Charger Detection + UCHAR BCDForceCbusPWREN; // asserts the power enable signal on CBUS when charging port detected + UCHAR BCDDisableSleep; // forces the device never to go into sleep mode + // I2C options + WORD I2CSlaveAddress; // I2C slave device address + DWORD I2CDeviceId; // I2C device ID + UCHAR I2CDisableSchmitt; // Disable I2C Schmitt trigger + // FT1248 options + UCHAR FT1248Cpol; // FT1248 clock polarity - clock idle high (1) or clock idle low (0) + UCHAR FT1248Lsb; // FT1248 data is LSB (1) or MSB (0) + UCHAR FT1248FlowControl; // FT1248 flow control enable + // Hardware options + UCHAR RS485EchoSuppress; // + UCHAR PowerSaveEnable; // + // Driver option + UCHAR DriverType; // + } FT_EEPROM_X_SERIES, *PFT_EEPROM_X_SERIES; + + + FTD2XX_API + FT_STATUS WINAPI FT_EEPROM_Read( + FT_HANDLE ftHandle, + void *eepromData, + DWORD eepromDataSize, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + + + FTD2XX_API + FT_STATUS WINAPI FT_EEPROM_Program( + FT_HANDLE ftHandle, + void *eepromData, + DWORD eepromDataSize, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + + + FTD2XX_API + FT_STATUS WINAPI FT_SetLatencyTimer( + FT_HANDLE ftHandle, + UCHAR ucLatency + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetLatencyTimer( + FT_HANDLE ftHandle, + PUCHAR pucLatency + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetBitMode( + FT_HANDLE ftHandle, + UCHAR ucMask, + UCHAR ucEnable + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetBitMode( + FT_HANDLE ftHandle, + PUCHAR pucMode + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetUSBParameters( + FT_HANDLE ftHandle, + ULONG ulInTransferSize, + ULONG ulOutTransferSize + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetDeadmanTimeout( + FT_HANDLE ftHandle, + ULONG ulDeadmanTimeout + ); + +#ifndef _WIN32 + // Extra functions for non-Windows platforms to compensate + // for lack of .INF file to specify Vendor and Product IDs. + + FTD2XX_API + FT_STATUS FT_SetVIDPID( + DWORD dwVID, + DWORD dwPID + ); + + FTD2XX_API + FT_STATUS FT_GetVIDPID( + DWORD * pdwVID, + DWORD * pdwPID + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetDeviceLocId( + FT_HANDLE ftHandle, + LPDWORD lpdwLocId + ); +#endif // _WIN32 + + FTD2XX_API + FT_STATUS WINAPI FT_GetDeviceInfo( + FT_HANDLE ftHandle, + FT_DEVICE *lpftDevice, + LPDWORD lpdwID, + PCHAR SerialNumber, + PCHAR Description, + LPVOID Dummy + ); + + FTD2XX_API + FT_STATUS WINAPI FT_StopInTask( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_RestartInTask( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_SetResetPipeRetryCount( + FT_HANDLE ftHandle, + DWORD dwCount + ); + + FTD2XX_API + FT_STATUS WINAPI FT_ResetPort( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_CyclePort( + FT_HANDLE ftHandle + ); + + + // + // Win32-type functions + // + + FTD2XX_API + FT_HANDLE WINAPI FT_W32_CreateFile( + LPCTSTR lpszName, + DWORD dwAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreate, + DWORD dwAttrsAndFlags, + HANDLE hTemplate + ); + + FTD2XX_API + BOOL WINAPI FT_W32_CloseHandle( + FT_HANDLE ftHandle + ); + + FTD2XX_API + BOOL WINAPI FT_W32_ReadFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + + FTD2XX_API + BOOL WINAPI FT_W32_WriteFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten, + LPOVERLAPPED lpOverlapped + ); + + FTD2XX_API + DWORD WINAPI FT_W32_GetLastError( + FT_HANDLE ftHandle + ); + + FTD2XX_API + BOOL WINAPI FT_W32_GetOverlappedResult( + FT_HANDLE ftHandle, + LPOVERLAPPED lpOverlapped, + LPDWORD lpdwBytesTransferred, + BOOL bWait + ); + + FTD2XX_API + BOOL WINAPI FT_W32_CancelIo( + FT_HANDLE ftHandle + ); + + + // + // Win32 COMM API type functions + // + typedef struct _FTCOMSTAT { + DWORD fCtsHold : 1; + DWORD fDsrHold : 1; + DWORD fRlsdHold : 1; + DWORD fXoffHold : 1; + DWORD fXoffSent : 1; + DWORD fEof : 1; + DWORD fTxim : 1; + DWORD fReserved : 25; + DWORD cbInQue; + DWORD cbOutQue; + } FTCOMSTAT, *LPFTCOMSTAT; + + typedef struct _FTDCB { + DWORD DCBlength; /* sizeof(FTDCB) */ + DWORD BaudRate; /* Baudrate at which running */ + DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ + DWORD fParity: 1; /* Enable parity checking */ + DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ + DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ + DWORD fDtrControl:2; /* DTR Flow control */ + DWORD fDsrSensitivity:1; /* DSR Sensitivity */ + DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ + DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ + DWORD fInX: 1; /* Enable input X-ON/X-OFF */ + DWORD fErrorChar: 1; /* Enable Err Replacement */ + DWORD fNull: 1; /* Enable Null stripping */ + DWORD fRtsControl:2; /* Rts Flow control */ + DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ + DWORD fDummy2:17; /* Reserved */ + WORD wReserved; /* Not currently used */ + WORD XonLim; /* Transmit X-ON threshold */ + WORD XoffLim; /* Transmit X-OFF threshold */ + BYTE ByteSize; /* Number of bits/byte, 4-8 */ + BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ + BYTE StopBits; /* FT_STOP_BITS_1 or FT_STOP_BITS_2 */ + char XonChar; /* Tx and Rx X-ON character */ + char XoffChar; /* Tx and Rx X-OFF character */ + char ErrorChar; /* Error replacement char */ + char EofChar; /* End of Input character */ + char EvtChar; /* Received Event character */ + WORD wReserved1; /* Fill for now. */ + } FTDCB, *LPFTDCB; + + typedef struct _FTTIMEOUTS { + DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ + DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ + DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ + } FTTIMEOUTS,*LPFTTIMEOUTS; + + + FTD2XX_API + BOOL WINAPI FT_W32_ClearCommBreak( + FT_HANDLE ftHandle + ); + + FTD2XX_API + BOOL WINAPI FT_W32_ClearCommError( + FT_HANDLE ftHandle, + LPDWORD lpdwErrors, + LPFTCOMSTAT lpftComstat + ); + + FTD2XX_API + BOOL WINAPI FT_W32_EscapeCommFunction( + FT_HANDLE ftHandle, + DWORD dwFunc + ); + + FTD2XX_API + BOOL WINAPI FT_W32_GetCommModemStatus( + FT_HANDLE ftHandle, + LPDWORD lpdwModemStatus + ); + + FTD2XX_API + BOOL WINAPI FT_W32_GetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + + FTD2XX_API + BOOL WINAPI FT_W32_GetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + + FTD2XX_API + BOOL WINAPI FT_W32_PurgeComm( + FT_HANDLE ftHandle, + DWORD dwMask + ); + + FTD2XX_API + BOOL WINAPI FT_W32_SetCommBreak( + FT_HANDLE ftHandle + ); + + FTD2XX_API + BOOL WINAPI FT_W32_SetCommMask( + FT_HANDLE ftHandle, + ULONG ulEventMask + ); + + FTD2XX_API + BOOL WINAPI FT_W32_GetCommMask( + FT_HANDLE ftHandle, + LPDWORD lpdwEventMask + ); + + FTD2XX_API + BOOL WINAPI FT_W32_SetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + + FTD2XX_API + BOOL WINAPI FT_W32_SetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + + FTD2XX_API + BOOL WINAPI FT_W32_SetupComm( + FT_HANDLE ftHandle, + DWORD dwReadBufferSize, + DWORD dwWriteBufferSize + ); + + FTD2XX_API + BOOL WINAPI FT_W32_WaitCommEvent( + FT_HANDLE ftHandle, + PULONG pulEvent, + LPOVERLAPPED lpOverlapped + ); + + + // + // Device information + // + + typedef struct _ft_device_list_info_node { + ULONG Flags; + ULONG Type; + ULONG ID; + DWORD LocId; + char SerialNumber[16]; + char Description[64]; + FT_HANDLE ftHandle; + } FT_DEVICE_LIST_INFO_NODE; + + // Device information flags + enum { + FT_FLAGS_OPENED = 1, + FT_FLAGS_HISPEED = 2 + }; + + + FTD2XX_API + FT_STATUS WINAPI FT_CreateDeviceInfoList( + LPDWORD lpdwNumDevs + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetDeviceInfoList( + FT_DEVICE_LIST_INFO_NODE *pDest, + LPDWORD lpdwNumDevs + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetDeviceInfoDetail( + DWORD dwIndex, + LPDWORD lpdwFlags, + LPDWORD lpdwType, + LPDWORD lpdwID, + LPDWORD lpdwLocId, + LPVOID lpSerialNumber, + LPVOID lpDescription, + FT_HANDLE *pftHandle + ); + + + // + // Version information + // + + FTD2XX_API + FT_STATUS WINAPI FT_GetDriverVersion( + FT_HANDLE ftHandle, + LPDWORD lpdwVersion + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetLibraryVersion( + LPDWORD lpdwVersion + ); + + + FTD2XX_API + FT_STATUS WINAPI FT_Rescan( + void + ); + + FTD2XX_API + FT_STATUS WINAPI FT_Reload( + WORD wVid, + WORD wPid + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetComPortNumber( + FT_HANDLE ftHandle, + LPLONG lpdwComPortNumber + ); + + + // + // FT232H additional EEPROM functions + // + + FTD2XX_API + FT_STATUS WINAPI FT_EE_ReadConfig( + FT_HANDLE ftHandle, + UCHAR ucAddress, + PUCHAR pucValue + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EE_WriteConfig( + FT_HANDLE ftHandle, + UCHAR ucAddress, + UCHAR ucValue + ); + + FTD2XX_API + FT_STATUS WINAPI FT_EE_ReadECC( + FT_HANDLE ftHandle, + UCHAR ucOption, + LPWORD lpwValue + ); + + FTD2XX_API + FT_STATUS WINAPI FT_GetQueueStatusEx( + FT_HANDLE ftHandle, + DWORD *dwRxBytes + ); + + FTD2XX_API + FT_STATUS WINAPI FT_ComPortIdle( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_ComPortCancelIdle( + FT_HANDLE ftHandle + ); + + FTD2XX_API + FT_STATUS WINAPI FT_VendorCmdGet( + FT_HANDLE ftHandle, + UCHAR Request, + UCHAR *Buf, + USHORT Len + ); + + FTD2XX_API + FT_STATUS WINAPI FT_VendorCmdSet( + FT_HANDLE ftHandle, + UCHAR Request, + UCHAR *Buf, + USHORT Len + ); + + FTD2XX_API + FT_STATUS WINAPI FT_VendorCmdGetEx( + FT_HANDLE ftHandle, + USHORT wValue, + UCHAR *Buf, + USHORT Len + ); + + FTD2XX_API + FT_STATUS WINAPI FT_VendorCmdSetEx( + FT_HANDLE ftHandle, + USHORT wValue, + UCHAR *Buf, + USHORT Len + ); + +#ifdef __cplusplus +} +#endif + + +#endif /* FTD2XX_H */ + diff --git a/ambed/main.cpp b/ambed/main.cpp new file mode 100644 index 0000000..6892471 --- /dev/null +++ b/ambed/main.cpp @@ -0,0 +1,127 @@ +// +// main.cpp +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#include "main.h" +#include "ctimepoint.h" +#include "cambeserver.h" + +#include "syslog.h" +#include + +//////////////////////////////////////////////////////////////////////////////////////// +// global objects + + +//////////////////////////////////////////////////////////////////////////////////////// +// function declaration + + +int main(int argc, const char * argv[]) +{ +#ifdef RUN_AS_DAEMON + + // redirect cout, cerr and clog to syslog + syslog::redirect cout_redir(std::cout); + syslog::redirect cerr_redir(std::cerr); + syslog::redirect clog_redir(std::clog); + + //Fork the Parent Process + pid_t pid, sid; + pid = ::fork(); + //pid = ::vfork(); + if ( pid < 0 ) + { + exit(EXIT_FAILURE); + } + + // We got a good pid, Close the Parent Process + if (pid > 0) + { + exit(EXIT_SUCCESS); + } + + // Change File Mask + ::umask(0); + + //Create a new Signature Id for our child + sid = ::setsid(); + if (sid < 0) + { + exit(EXIT_FAILURE); + } + + // Change Directory + // If we cant find the directory we exit with failure. + if ( (::chdir("/")) < 0) + { + exit(EXIT_FAILURE); + } + + // Close Standard File Descriptors + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + +#endif + + // check arguments + if ( argc != 2 ) + { + std::cout << "Usage: ambed ip" << std::endl; + std::cout << "example: ambed 192.168.178.212" << std::endl; + return 1; + } + + // initialize ambeserver + g_AmbeServer.SetListenIp(CIp(argv[1])); + + // and let it run + std::cout << "Starting AMBEd" << std::endl << std::endl; + if ( !g_AmbeServer.Start() ) + { + std::cout << "Error starting AMBEd" << std::endl; + exit(EXIT_FAILURE); + } + std::cout << "AMBEd started and listening on " << g_AmbeServer.GetListenIp() << std::endl; + +#ifdef RUN_AS_DAEMON + // run forever + while ( true ) + { + // sleep 60 seconds + CTimePoint::TaskSleepFor(60000); + } +#else + // wait any key + for (;;); + //std::cin.get(); +#endif + + // and wait for end + g_AmbeServer.Stop(); + std::cout << "AMBEd stopped" << std::endl; + + // done + exit(EXIT_SUCCESS); +} diff --git a/ambed/main.h b/ambed/main.h new file mode 100644 index 0000000..8ed4c22 --- /dev/null +++ b/ambed/main.h @@ -0,0 +1,110 @@ +// +// main.h +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 13/04/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + +#ifndef main_h +#define main_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////// +// defines + +// version ----------------------------------------------------- + +#define VERSION_MAJOR 1 +#define VERSION_MINOR 0 +#define VERSION_REVISION 0 + +// global ------------------------------------------------------ + +//#define RUN_AS_DAEMON +#define NB_MAX_STREAMS 99 +//#define DEBUG_DUMPFILE + +// Transcoder server -------------------------------------------- +#define TRANSCODER_PORT 10100 // UDP port +#define TRANSCODER_KEEPALIVE_PERIOD 5 // in seconds +#define TRANSCODER_KEEPALIVE_TIMEOUT 30 // in seconds + +// Codecs ------------------------------------------------------- +#define CODEC_NONE 0 +#define CODEC_AMBEPLUS 1 +#define CODEC_AMBE2PLUS 2 + +// Transcoding speech gains +#define CODECGAIN_AMBEPLUS -10 // in dB +#define CODECGAIN_AMBE2PLUS +10 // in dB + +// Timeouts ----------------------------------------------------- +#define STREAM_ACTIVITY_TIMEOUT 3 // in seconds + + +//////////////////////////////////////////////////////////////////////////////////////// +// typedefs + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; +typedef unsigned int uint; + + +//////////////////////////////////////////////////////////////////////////////////////// +// macros + +#define MIN(a,b) ((a) < (b))?(a):(b) +#define MAX(a,b) ((a) > (b))?(a):(b) +#define MAKEWORD(low, high) ((uint16)(((uint8)(low)) | (((uint16)((uint8)(high))) << 8))) +#define MAKEDWORD(low, high) ((uint32)(((uint16)(low)) | (((uint32)((uint16)(high))) << 16))) +#define LOBYTE(w) ((uint8)(uint16)(w & 0x00FF)) +#define HIBYTE(w) ((uint8)((((uint16)(w)) >> 8) & 0xFF)) +#define LOWORD(dw) ((uint16)(uint32)(dw & 0x0000FFFF)) +#define HIWORD(dw) ((uint16)((((uint32)(dw)) >> 16) & 0xFFFF)) + +//////////////////////////////////////////////////////////////////////////////////////// +// global objects + +class CAmbeServer; +extern CAmbeServer g_AmbeServer; + +class CVocodecs; +extern CVocodecs g_Vocodecs; + + +//////////////////////////////////////////////////////////////////////////////////////// +#endif /* main_h */ diff --git a/ambed/makefile b/ambed/makefile new file mode 100644 index 0000000..0aa514e --- /dev/null +++ b/ambed/makefile @@ -0,0 +1,22 @@ +CC=g++ +CFLAGS=-c -std=c++11 -pthread +LDFLAGS=-std=c++11 -pthread +SOURCES=$(wildcard *.cpp) +OBJECTS=$(SOURCES:.cpp=.o) +EXECUTABLE=ambed + +all: $(SOURCES) $(EXECUTABLE) + +$(EXECUTABLE): $(OBJECTS) + $(CC) $(LDFLAGS) $(OBJECTS) -lftd2xx -Wl,-rpath,/usr/local/lib -o $@ + +.cpp.o: + $(CC) $(CFLAGS) $< -o $@ + +clean: + $(RM) *.o + +install: + mkdir -p /ambed + cp ./ambed /ambed/ + cp ./run /ambed/ diff --git a/ambed/readme b/ambed/readme new file mode 100644 index 0000000..36f6240 --- /dev/null +++ b/ambed/readme @@ -0,0 +1,103 @@ +// +// readme +// ambed +// +// Created by Jean-Luc Deltombe (LX3JL) on 09/07/2017. +// Copyright © 2015 Jean-Luc Deltombe (LX3JL). All rights reserved. +// +// ---------------------------------------------------------------------------- +// This file is part of ambed. +// +// xlxd 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 3 of the License, or +// (at your option) any later version. +// +// xlxd 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 Foobar. If not, see . +// ---------------------------------------------------------------------------- + + +Hardware compatibility. +====================== +This version of ambed is compatible with FTDI's USB-3003 and USB-3012 device + +Available transcoding channels: + +device DMR->DSTAR DSTAR->DMR Nb Of concurrent channels +---------------------------------------------------------------------- +USB-3003 1 1 1 +USB-3012 4 4 4 + +multiple USB-3xxx can be used at the same time. + +Instructions: +============= + +1) Installation of FTDI drivers + +Download from FTDI web site the latest D2XX driver package (tested on 1.4.6). +Follow FTDI provided documentation for installation and testing of the drivers. + + +2) installation of g++ compiler + +# apt-get install build-essential +# apt-get install g++-4.7 + +2) download and compile ambed + +# git clone https://github.com/LX3JL/xlxd.git +# cd xlxd/ambed/ +# make +# make clean +# make install + +3) configuring ambed startup script + +# nano /ambed/run + +edit following line to match your IP: + +sudo /ambed/ambed 127.0.0.1 & + +if ambed is running on same machine than xlxd, use default 127.0.0.1 +otherwise use the machine own IP + + +4) running ambed + +note: +Due to specific FTDI driver implementation, ambed must be running +with roor privilege, and cannot be run as a daemon. +So ambed will display the information and error messages in the +terminal it has been started from + +plug at least one USB-3xxx USB device + +# cd /ambed +# ./run + + +during initialisation phase, ambed will scan all USB port to discover +and configure ans report status of all available USB-3xxx devices + + +5) stoping ambed + +find PID of ambed process, using for example ps + +# ps ax | grep ambed + +and kill the process + +# kill xxxx + +where xxxx is PID found previously. + + diff --git a/ambed/run b/ambed/run new file mode 100644 index 0000000..4c56312 --- /dev/null +++ b/ambed/run @@ -0,0 +1,6 @@ +#!/bin/bash +# start ambed server + +sudo rmmod ftdi_sio +sudo rmmod usbserial +sudo ./ambed 127.0.0.1 & \ No newline at end of file diff --git a/ambed/syslog.h b/ambed/syslog.h new file mode 100644 index 0000000..aba8f83 --- /dev/null +++ b/ambed/syslog.h @@ -0,0 +1,96 @@ +/************************************************************************* + ** Copyright (C) 2014 Jan Pedersen + ** + ** 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 3 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, see . + *************************************************************************/ + +#ifndef __syslog +#define __syslog + +#include +#include +#include +namespace csyslog { +#include +} + +namespace syslog +{ + struct level { + enum pri { + emerg = LOG_EMERG, // A panic condition + alert = LOG_ALERT, // A condition that should be corrected + critical= LOG_CRIT, // Critical condition, e.g, hard device error + error = LOG_ERR, // Errors + warning = LOG_WARNING, // Warning messages + notice = LOG_NOTICE, // Possibly be handled specially + info = LOG_INFO, // Informational + debug = LOG_DEBUG // For debugging program + }; + }; + + class streambuf : public std::streambuf + { + std::string _buf; + int _level; + + public: + + streambuf() : _level(level::debug) { } + void level(int level) { _level = level; } + + protected: + + int sync() + { + if (_buf.size()) { + csyslog::syslog(_level, "%s", _buf.c_str()); + _buf.erase(); + } + return 0; + } + + int_type overflow(int_type c) + { + if(c == traits_type::eof()) sync(); + else _buf += static_cast(c); + return c; + } + + }; + + class ostream : public std::ostream + { + streambuf _logbuf; + public: + ostream() : std::ostream(&_logbuf) {} + ostream& operator<<(const level::pri lev) { _logbuf.level(lev); return *this; } + }; + + class redirect + { + ostream dst; + std::ostream &src; + std::streambuf * const sbuf; + + public: + redirect(std::ostream & src) : src(src), sbuf(src.rdbuf(dst.rdbuf())) { dst << (&src == &std::cout ? level::info : level::error); } + ~redirect() { src.rdbuf(sbuf); } + }; +} + +#endif + + +