From cd15b15ceaef9f06aedf947ebd5a3173f511b3ef Mon Sep 17 00:00:00 2001 From: Tom Early Date: Sat, 8 Jan 2022 09:50:31 -0700 Subject: [PATCH] switched to ftd2xx --- Controller.cpp | 67 ++- Controller.h | 3 + DV3003.cpp | 471 +++++++++------- DV3003.h | 17 +- Makefile | 4 +- WinTypes.h | 158 ++++++ ftd2xx.h | 1459 ++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 1967 insertions(+), 212 deletions(-) create mode 100644 WinTypes.h create mode 100644 ftd2xx.h diff --git a/Controller.cpp b/Controller.cpp index 8b929ca..aa336ca 100644 --- a/Controller.cpp +++ b/Controller.cpp @@ -78,6 +78,50 @@ bool CController::CheckTCModules() const return trouble; } + +bool CController::DiscoverFtdiDevices(std::list> &found) +{ + int iNbDevices = 0; + auto status = FT_CreateDeviceInfoList((LPDWORD)&iNbDevices); + if (FT_OK != status) + { + std::cerr << "Could not create FTDI device list" << std::endl; + return true; + } + + std::cout << "Detected " << iNbDevices << " USB-FTDI-based DVSI devices" << std::endl; + if ( iNbDevices > 0 ) + { + // allocate the list + FT_DEVICE_LIST_INFO_NODE *list = new FT_DEVICE_LIST_INFO_NODE[iNbDevices]; + if (nullptr == list) + { + std::cerr << "Could not create new device list" << std::endl; + return true; + } + + // fill + status = FT_GetDeviceInfoList(list, (LPDWORD)&iNbDevices); + if (FT_OK != status) + { + std::cerr << "Could not get FTDI device list" << std::endl; + return true; + } + + for ( int i = 0; i < iNbDevices; i++ ) + { + std::cout << "Found '" << list[i].Description << "', SerialNo='" << list[i].SerialNumber << std::endl; + found.emplace_back(std::pair(list[i].SerialNumber, list[i].Description)); + } + + // and delete + delete[] list; + } + + // done + return false; +} + bool CController::InitDevices() { if (CheckTCModules()) @@ -92,18 +136,10 @@ bool CController::InitDevices() } // the 3003 devices - std::vector deviceset; - std::string device; - - for (int i=0; i<32; i++) { - device.assign("/dev/ttyUSB"); - device += std::to_string(i); + std::list> deviceset; - if (access(device.c_str(), R_OK | W_OK)) - break; - else - deviceset.push_back(device); - } + if (DiscoverFtdiDevices(deviceset)) + return true; if (deviceset.empty()) { std::cerr << "could not find a device!" << std::endl; @@ -117,13 +153,18 @@ bool CController::InitDevices() } //initialize each device - if (dstar_device.OpenDevice(deviceset[0], 921600) || dmr_device.OpenDevice(deviceset[1], 921600)) - return true; + for (const auto &it : deviceset) + { + if (dstar_device.OpenDevice(it.first, it.second, 921600)) + return true; + } // and start them up! dstar_device.Start(); dmr_device.Start(); + deviceset.clear(); + return false; } diff --git a/Controller.h b/Controller.h index 0f0f6be..e860a04 100644 --- a/Controller.h +++ b/Controller.h @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include "codec2.h" #include "DV3003.h" @@ -55,6 +57,7 @@ protected: CPacketQueue codec2_queue; std::mutex send_mux; + bool DiscoverFtdiDevices(std::list> &found); bool InitDevices(); // processing threads void ReadReflectorThread(); diff --git a/DV3003.cpp b/DV3003.cpp index a6131a1..c457be3 100644 --- a/DV3003.cpp +++ b/DV3003.cpp @@ -38,7 +38,7 @@ extern CController Controller; -CDV3003::CDV3003(Encoding t) : type(t), fd(-1), ch_depth(0), sp_depth(0) +CDV3003::CDV3003(Encoding t) : type(t), ftHandle(nullptr), buffer_depth(0) { } @@ -50,16 +50,88 @@ CDV3003::~CDV3003() void CDV3003::CloseDevice() { keep_running = false; - if (fd >= 0) { - close(fd); - fd = -1; + if (ftHandle) + { + auto status = FT_Close(ftHandle); + if (FT_OK != status) + FTDI_Error("FT_Close", status); } + if (feedFuture.valid()) feedFuture.get(); if (readFuture.valid()) readFuture.get(); } +void CDV3003::FTDI_Error(const char *where, FT_STATUS status) const +{ + std::cerr << "FTDI ERROR: " << where << ": "; + switch (status) + { + case FT_INVALID_HANDLE: + std::cerr << "handle is invalid"; + break; + case FT_DEVICE_NOT_FOUND: + std::cerr << "device not found"; + break; + case FT_DEVICE_NOT_OPENED: + std::cerr << "device not opne"; + break; + case FT_IO_ERROR: + std::cerr << "io error"; + break; + case FT_INSUFFICIENT_RESOURCES: + std::cerr << "insufficient resources"; + break; + case FT_INVALID_PARAMETER: + std::cerr << "invalid parameter"; + break; + case FT_INVALID_BAUD_RATE: + std::cerr << "invalid baud rate"; + break; + case FT_DEVICE_NOT_OPENED_FOR_ERASE: + std::cerr << "device not opened for erase"; + break; + case FT_DEVICE_NOT_OPENED_FOR_WRITE: + std::cerr << "device not opened for write"; + break; + case FT_FAILED_TO_WRITE_DEVICE: + std::cerr << "failed to write device"; + break; + case FT_EEPROM_READ_FAILED: + std::cerr << "eeprom read failed"; + break; + case FT_EEPROM_WRITE_FAILED: + std::cerr << "eeprom write failed"; + break; + case FT_EEPROM_ERASE_FAILED: + std::cerr << "eeprom erase failed"; + break; + case FT_EEPROM_NOT_PRESENT: + std::cerr << "eeprom not present"; + break; + case FT_EEPROM_NOT_PROGRAMMED: + std::cerr << "eeprom not programmed"; + break; + case FT_INVALID_ARGS: + std::cerr << "invalid arguments"; + break; + case FT_NOT_SUPPORTED: + std::cerr << "not supported"; + break; + case FT_OTHER_ERROR: + std::cerr << "unknown other error"; + break; + case FT_DEVICE_LIST_NOT_READY: + std::cerr << "device list not ready"; + break; + default: + std::cerr << "unknown status: " << status; + break; + } + std::cerr << std::endl; +} + bool CDV3003::checkResponse(SDV3003_Packet &p, uint8_t response) const { if(p.start_byte != PKT_HEADER || p.header.packet_type != PKT_CONTROL || p.field_id != response) @@ -68,83 +140,86 @@ bool CDV3003::checkResponse(SDV3003_Packet &p, uint8_t response) const return false; } -std::string CDV3003::GetDevicePath() const +std::string CDV3003::GetDescription() const { - return devicepath; + return description; } -std::string CDV3003::GetVersion() const +bool CDV3003::OpenDevice(const std::string &serialno, const std::string &desc, int baudrate) { - return version; -} + auto status = FT_OpenEx((PVOID)serialno.c_str(), FT_OPEN_BY_SERIAL_NUMBER, &ftHandle); + if (FT_OK != status) + { + FTDI_Error("FT_OpenEx", status); + return true; + } -std::string CDV3003::GetProductID() const -{ - return productid; -} + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + FT_Purge(ftHandle, FT_PURGE_RX | FT_PURGE_TX ); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); -bool CDV3003::SetBaudRate(int baudrate) -{ - struct termios tty; + status = FT_SetDataCharacteristics(ftHandle, FT_BITS_8, FT_STOP_BITS_1, FT_PARITY_NONE); + if (status != FT_OK) + { + FTDI_Error("FT_SetDataCharacteristics", status); + return true; + } - if (tcgetattr(fd, &tty) != 0) { - std::cerr << devicepath << " tcgetattr: " << strerror(errno) << std::endl; - close(fd); + status = FT_SetFlowControl(ftHandle, FT_FLOW_RTS_CTS, 0x11, 0x13); + if (status != FT_OK) + { + FTDI_Error("FT_SetFlowControl", status); return true; } - // Input speed = output speed - cfsetispeed(&tty, B0); + status = FT_SetRts(ftHandle); + if (status != FT_OK) + { + FTDI_Error((char *)"FT_SetRts", status); + return true; + } - switch(baudrate) { - case 230400: - cfsetospeed(&tty, B230400); - break; - case 460800: - cfsetospeed(&tty, B460800); - break; - case 921600: - cfsetospeed(&tty, B921600); - break; - default: - std::cerr << devicepath << " unsupported baud rate " << baudrate << std::endl; - close(fd); - return true; + //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 + status = FT_ClrDtr(ftHandle); + if (status != FT_OK) + { + FTDI_Error((char *)"FT_ClrDtr", status); + return true; } - tty.c_lflag &= ~(ECHO | ECHOE | ICANON | IEXTEN | ISIG); - tty.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON | IXOFF | IXANY); - tty.c_cflag &= ~(CSIZE | CSTOPB | PARENB); - tty.c_cflag |= CS8 | CRTSCTS; - tty.c_oflag &= ~(OPOST); - tty.c_cc[VMIN] = 0; - tty.c_cc[VTIME] = 1; + status = FT_SetBaudRate(ftHandle, baudrate ); + if (status != FT_OK) + { + FTDI_Error((char *)"FT_SetBaudRate", status); + return false; + } - if (tcsetattr(fd, TCSANOW, &tty) != 0) { - std::cerr << devicepath << " tcsetattr: " << strerror(errno) << std::endl; - close(fd); + status = FT_SetLatencyTimer(ftHandle, 4); + if (status != FT_OK) + { + FTDI_Error((char *)"FT_SetLatencyTimer", status); return true; } - return false; -} -bool CDV3003::OpenDevice(const std::string &ttyname, int baudrate) -{ - fd = open(ttyname.c_str(), O_RDWR | O_NOCTTY | O_SYNC); - if (fd < 0) { - std::cerr << "error when opening " << ttyname << ": " << strerror(errno) << std::endl; + status = FT_SetUSBParameters(ftHandle, USB3XXX_MAXPACKETSIZE, 0); + if (status != FT_OK){ + FTDI_Error((char *)"FT_SetUSBParameters", status); return true; } - if (SetBaudRate(baudrate)) - return true; - std::cout << ttyname << " baudrate it set to " << baudrate << std::endl; + status = FT_SetTimeouts(ftHandle, 200, 200 ); + if (status != FT_OK) + { + FTDI_Error((char *)"FT_SetTimeouts", status); + return false; + } - devicepath.assign(ttyname); - std::cout << "Opened " << devicepath << " using fd " << fd << std::endl; + description.assign(desc); + description.append(": "); + description.append(serialno); - if (Purge()) - return true; + std::cout << "Opened " << description << std::endl; if (InitDV3003()) return true; @@ -157,26 +232,6 @@ bool CDV3003::OpenDevice(const std::string &ttyname, int baudrate) return false; } -bool CDV3003::Purge() -{ - const char zeros[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - // if there is a partial command in the input, this will clear it - for (unsigned int i=0; i<35; i++) - { - auto written = write(fd, zeros, sizeof(zeros)); - if (0 > written) - { - std::cerr << "Cleanse failed to write zeros to " << devicepath << std::endl; - return true; - } - if (written < 10) - { - std::cerr << "On Cleanse pass " << i << ", only " << written << " bytes were written to " << devicepath << std::endl; - } - } - return false; -} - bool CDV3003::InitDV3003() { SDV3003_Packet responsePacket, ctrlPacket; @@ -188,84 +243,127 @@ bool CDV3003::InitDV3003() ctrlPacket.field_id = PKT_RESET; ctrlPacket.payload.ctrl.data.paritymode[0] = PKT_PARITYBYTE; ctrlPacket.payload.ctrl.data.paritymode[1] = 0x3U ^ PKT_RESET ^ PKT_PARITYBYTE; - if (write(fd, &ctrlPacket, packet_size(ctrlPacket)) == -1) { - std::cerr << "InitDV3003: error writing reset packet: " << strerror(errno) << std::endl; + DWORD written = 0; + auto status = FT_Write(ftHandle, &ctrlPacket, 7, &written); + if (FT_OK != status) + { + FTDI_Error("Error writing soft reset packet", status); + return true; + } + else if (7 != written) + { + std::cerr << "Incomplete soft reset packet write" << std::endl; return true; } - if (GetResponse(responsePacket)) { - std::cerr << "InitDV3003: error receiving response to reset" << std::endl; + if (GetResponse(responsePacket)) + { + std::cerr << "Error receiving response to reset" << std::endl; return true; } - if (checkResponse(responsePacket, PKT_READY)) { - std::cerr << "InitDV3003: invalid response to reset" << std::endl; + if (checkResponse(responsePacket, PKT_READY)) + { + std::cerr << "Invalid response to soft reset" << std::endl; + dump("Soft Reset Response Packet:", &responsePacket, packet_size(responsePacket)); return true; } - std::cout << "Successfully reset " << devicepath << std::endl; + std::cout << "Successfully did a soft reset on " << description << std::endl; // ********** turn off parity ********* + ctrlPacket.start_byte = PKT_HEADER; ctrlPacket.header.payload_length = htons(4); + ctrlPacket.header.packet_type = PKT_CONTROL; ctrlPacket.field_id = PKT_PARITYMODE; ctrlPacket.payload.ctrl.data.paritymode[0] = 0; ctrlPacket.payload.ctrl.data.paritymode[1] = PKT_PARITYBYTE; ctrlPacket.payload.ctrl.data.paritymode[2] = 0x4U ^ PKT_PARITYMODE ^ PKT_PARITYBYTE; - if (write(fd, &ctrlPacket, packet_size(ctrlPacket)) == -1) { - std::cerr << "InitDV3003: error writing parity control packet: " << strerror(errno) << std::endl; + status = FT_Write(ftHandle, &ctrlPacket, 8, &written); + if (FT_OK != status) + { + FTDI_Error("Error writing parity control packet: ", status); + return true; + } + else if (8 != written) + { + std::cerr << "Incomplete disable parity packet write" << std::endl; return true; } - memset(&responsePacket, 0, sizeof(responsePacket)); - if (GetResponse(responsePacket)) { - std::cerr << "InitDV3003: error receiving response to parity set" << std::endl; - dump("Parity Ctrl Response Packet", &responsePacket, 4+ntohs(responsePacket.header.payload_length)); + if (GetResponse(responsePacket)) + { + std::cerr << "Error receiving response to parity set" << std::endl; return true; } - if (checkResponse(responsePacket, PKT_PARITYMODE)) { - std::cerr << "InitDV3003: invalid response to parity control" << std::endl; - dump("Parity Ctrl Response Packet", &responsePacket, packet_size(responsePacket)); + if (checkResponse(responsePacket, PKT_PARITYMODE)) + { + std::cerr << "Invalid response to parity control" << std::endl; + dump("Parity Ctrl Response Packet:", &responsePacket, packet_size(responsePacket)); return true; } - std::cout << "Successfully disabled parity on " << devicepath << std::endl; + std::cout << "Successfully disabled parity on " << description << std::endl; // ********* Product ID and Version ************* + ctrlPacket.start_byte = PKT_HEADER; ctrlPacket.header.payload_length = htons(1); + ctrlPacket.header.packet_type = PKT_CONTROL; ctrlPacket.field_id = PKT_PRODID; - if (write(fd, &ctrlPacket, packet_size(ctrlPacket)) == -1) { - std::cerr << "InitDV3003: error writing product id packet: " << strerror(errno) << std::endl; + + status = FT_Write(ftHandle, &ctrlPacket, 5, &written); + if (FT_OK != status) + { + FTDI_Error("Error writing Product ID packet", status); + return true; + } + else if (5 != written) + { + std::cerr << "Incomplete Product ID Packet write" << std::endl; return true; } - if (GetResponse(responsePacket)) { - std::cerr << "InitDV3003: error receiving response to product id request" << std::endl; + if (GetResponse(responsePacket)) + { + std::cerr << "Error receiving response to Product ID request" << std::endl; return true; } - if (checkResponse(responsePacket, PKT_PRODID)) { - std::cerr << "InitDV3003: invalid response to product id query" << std::endl; + if (checkResponse(responsePacket, PKT_PRODID)) + { + std::cerr << "Invalid response to Product ID query" << std::endl; + dump("Product ID Response Packet", &responsePacket, packet_size(responsePacket)); return true; } - productid.assign(responsePacket.payload.ctrl.data.prodid); + const std::string productid(responsePacket.payload.ctrl.data.prodid); ctrlPacket.field_id = PKT_VERSTRING; - if (write(fd, &ctrlPacket, packet_size(ctrlPacket)) == -1) { - std::cerr << "InitDV3003: error writing version packet: " << strerror(errno) << std::endl; + status = FT_Write(ftHandle, &ctrlPacket, 5, &written); + if (FT_OK != status) + { + FTDI_Error("Error writing Version packet", status); + return true; + } + else if (5 != written) + { + std::cerr << "Incomplete Version packet write" << std::endl; return true; } - if (GetResponse(responsePacket)) { - std::cerr << "InitDV3003: error receiving response to version request" << std::endl; + if (GetResponse(responsePacket)) + { + std::cerr << "Error receiving response to Version request" << std::endl; return true; } - if (checkResponse(responsePacket, PKT_VERSTRING)) { - std::cerr << "InitDV3003: invalid response to version query" << std::endl; + if (checkResponse(responsePacket, PKT_VERSTRING)) + { + std::cerr << "Invalid response to Version query" << std::endl; + dump("Product Version Response Packet:", &responsePacket, packet_size(responsePacket)); return true; } - version.assign(responsePacket.payload.ctrl.data.version); - std::cout << "Found " << productid << " version " << version << " at " << devicepath << std::endl; + const std::string version(responsePacket.payload.ctrl.data.version); + std::cout << description << ": ID=" << productid << " Version=" << version << std::endl; return false; } @@ -311,80 +409,87 @@ bool CDV3003::ConfigureVocoder(uint8_t pkt_ch, Encoding type) memcpy(controlPacket.payload.codec.init, init, 2); // write packet - if (0 > write(fd, &controlPacket, packet_size(controlPacket)) ) + DWORD written; + const DWORD size = packet_size(controlPacket); + auto status = FT_Write(ftHandle, &controlPacket, size, &written); + if (FT_OK != status) { - std::cerr << "error writing codec config packet" << strerror(errno) << std::endl; + FTDI_Error("error writing codec config packet", status); + return true; + } + else if (size != written) + { + std::cerr << "Incomplete Configuration packet write" << std::endl; return true; } - memset(&responsePacket, 0, sizeof(SDV3003_Packet)); - if (GetResponse(responsePacket)) { - std::cerr << "error reading vocoder config response packet" << std::endl; + if (GetResponse(responsePacket)) + { + std::cerr << "Error reading Configuration response packet" << std::endl; return true; } if ((ntohs(responsePacket.header.payload_length) != 16) || (responsePacket.field_id != pkt_ch) || (0 != memcmp(responsePacket.payload.ctrl.data.resp, resp, sizeof(resp)))) { - std::cerr << "vocoder config response packet failed" << std::endl; - dump("Configuration response was:", &responsePacket, sizeof(responsePacket)); + std::cerr << "Config response packet failed" << std::endl; + dump("Configuration Response Packet:", &responsePacket, sizeof(responsePacket)); return true; }; -#ifdef DEBUG - std::cout << devicepath << " channel " << (unsigned int)(pkt_ch - PKT_CHANNEL0) << " is now configured for " << ((Encoding::dstar == type) ? "D-Star" : "DMR") << std::endl; -#endif + + std::cout << description << " channel " << (unsigned int)(pkt_ch - PKT_CHANNEL0) << " is now configured for " << ((Encoding::dstar == type) ? "D-Star" : "DMR") << std::endl; + return false; } bool CDV3003::GetResponse(SDV3003_Packet &packet) { - ssize_t bytesRead; + FT_STATUS status; + DWORD bytes_read; // get the start byte - packet.start_byte = 0U; - const unsigned limit = sizeof(SDV3003_Packet) + 2; - unsigned got = 0; - for (unsigned i = 0U; i < limit; ++i) { - bytesRead = read(fd, &packet.start_byte, 1); - if (bytesRead == -1) { - std::cerr << "CDV3003: Error reading from serial port: " << strerror(errno) << std::endl; + for (unsigned i = 0U; i < USB3XXX_MAXPACKETSIZE+2; ++i) { + status = FT_Read(ftHandle, &packet.start_byte, 1, &bytes_read); + if (FT_OK != status) + { + FTDI_Error("Reading packet start byte", status); return true; } - if (bytesRead) - got++; if (packet.start_byte == PKT_HEADER) break; } + if (packet.start_byte != PKT_HEADER) { - std::cerr << "CDV3003: Couldn't find start byte in serial data: tried " << limit << " times, got " << got << " bytes" << std::endl; + std::cerr << "Couldn't find start byte!" << std::endl; return true; } // get the packet size and type (three bytes) - ssize_t bytesLeft = sizeof(packet.header); - ssize_t total = bytesLeft; + DWORD bytesLeft = sizeof(packet.header); while (bytesLeft > 0) { - bytesRead = read(fd, ((uint8_t *) &packet.header) + total - bytesLeft, bytesLeft); - if(bytesRead == -1) { - std::cout << "AMBEserver: Couldn't read serial data header" << std::endl; + status = FT_Read(ftHandle, &packet.header, sizeof(packet.header), &bytes_read); + if (FT_OK != status) + { + FTDI_Error("Error reading response packet header", status); return true; } - bytesLeft -= bytesRead; + bytesLeft -= bytes_read; } - total = bytesLeft = ntohs(packet.header.payload_length); + bytesLeft = ntohs(packet.header.payload_length); if (bytesLeft > 1 + int(sizeof(packet.payload))) { std::cout << "AMBEserver: Serial payload exceeds buffer size: " << int(bytesLeft) << std::endl; return true; } while (bytesLeft > 0) { - bytesRead = read(fd, ((uint8_t *) &packet.field_id) + total - bytesLeft, bytesLeft); - if (bytesRead == -1) { - std::cerr << "AMBEserver: Couldn't read payload: " << strerror(errno) << std::endl; - return true; - } + status = FT_Read(ftHandle, &packet.payload, bytesLeft, &bytes_read); + if (FT_OK != status) + { + FTDI_Error("Error reading packet payload", status); + return true; + } - bytesLeft -= bytesRead; + bytesLeft -= bytes_read; } return false; @@ -398,22 +503,12 @@ void CDV3003::FeedDevice() { auto packet = input_queue.pop(); // blocks until there is something to pop - const bool needs_audio = (Encoding::dstar==type) ? packet->DStarIsSet() : packet->DMRIsSet(); while (keep_running) // wait until there is room { - if (needs_audio) - { - // we need to decode ambe to audio - if (ch_depth < 2) - break; - } - else - { - // we need to encode audio to ambe - if (sp_depth < 2) - break; - } + if (buffer_depth < 2) + break; + std::this_thread::sleep_for(std::chrono::milliseconds(5)); } @@ -423,22 +518,23 @@ void CDV3003::FeedDevice() // save the packet in the vocoder's queue while the vocoder does its magic if (std::string::npos == index) { - std::cerr << "Module '" << packet->GetModule() << "' is not configured on " << devicepath << std::endl; + std::cerr << "Module '" << packet->GetModule() << "' is not configured on " << description << std::endl; } else { waiting_packet[index].push(packet); + const bool needs_audio = (Encoding::dstar==type) ? packet->DStarIsSet() : packet->DMRIsSet(); + if (needs_audio) { SendData(index, (Encoding::dstar==type) ? packet->GetDStarData() : packet->GetDMRData()); - ch_depth++; } else { SendAudio(index, packet->GetAudioSamples()); - sp_depth++; } + buffer_depth++; } } } @@ -448,24 +544,6 @@ void CDV3003::ReadDevice() { while (keep_running) { - fd_set FdSet; - FD_ZERO(&FdSet); - FD_SET(fd, &FdSet); - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 400000; // wait for 0.4 sec for something to read - auto rval = select(fd+1, &FdSet, 0, 0, &tv); - - if (rval < 0) - { - std::cerr << "ERROR: select() on " << devicepath << ": " << strerror(errno) << std::endl; - keep_running = false; - exit(1); - } - - if (0 == rval) - continue; // nothing to read, try again - dv3003_packet p; if (! GetResponse(p)) { @@ -475,7 +553,7 @@ void CDV3003::ReadDevice() { if (12!=ntohs(p.header.payload_length) || PKT_CHAND!=p.payload.ambe.chand || 72!=p.payload.ambe.num_bits) dump("Improper ambe packet:", &p, packet_size(p)); - sp_depth--; + buffer_depth--; if (Encoding::dstar == type) packet->SetDStarData(p.payload.ambe.data); else @@ -486,7 +564,7 @@ void CDV3003::ReadDevice() { if (323!=ntohs(p.header.payload_length) || PKT_SPEECHD!=p.payload.audio.speechd || 160!=p.payload.audio.num_samples) dump("Improper audio packet:", &p, packet_size(p)); - ch_depth--; + buffer_depth--; packet->SetAudioSamples(p.payload.audio.samples, true); } else @@ -530,11 +608,20 @@ bool CDV3003::SendAudio(const uint8_t channel, const int16_t *audio) const p.payload.audio.samples[i] = htons(audio[i]); // send audio packet to DV3000 - int size = packet_size(p); - if (write(fd, &p, size) != size) { - std::cerr << "Error sending audio packet" << std::endl; + const DWORD size = packet_size(p); + DWORD written; + auto status = FT_Write(ftHandle, &p, size, &written); + if (FT_OK != status) + { + FTDI_Error("Error writing audio packet", status); + return true; + } + else if (size != written) + { + std::cerr << "Incomplete Speech Packet write on " << description << std::endl; return true; } + return false; } @@ -551,12 +638,20 @@ bool CDV3003::SendData(const uint8_t channel, const uint8_t *data) const memcpy(p.payload.ambe.data, data, 9); // send data packet to DV3000 - int size = packet_size(p); - if (write(fd, &p, size) != size) { - std::cerr << "SendData: error sending data packet" << std::endl; - dump("Received Data", &p, size); + const DWORD size = packet_size(p); + DWORD written; + auto status = FT_Write(ftHandle, &p, size, &written); + if (FT_OK != status) + { + FTDI_Error("Error writing AMBE Packet", status); + return true; + } + else if (size != written) + { + std::cerr << "Incomplete AMBE Packet write on " << description << std::endl; return true; } + return false; } diff --git a/DV3003.h b/DV3003.h index d6debaf..ce2b9ea 100644 --- a/DV3003.h +++ b/DV3003.h @@ -23,6 +23,7 @@ #include #include "PacketQueue.h" +#include "ftd2xx.h" #define USB3XXX_MAXPACKETSIZE 1024 // must be multiple of 64 @@ -103,29 +104,27 @@ class CDV3003 { public: CDV3003(Encoding t); ~CDV3003(); - bool OpenDevice(const std::string &device, int baudrate); + bool OpenDevice(const std::string &serialno, const std::string &desc, int baudrate); void Start(); void CloseDevice(); - std::string GetDevicePath() const; - std::string GetProductID() const; - std::string GetVersion() const; + std::string GetDescription() const; void AddPacket(const std::shared_ptr packet); private: const Encoding type; - int fd; - std::atomic ch_depth, sp_depth; + FT_HANDLE ftHandle; + std::atomic buffer_depth; std::atomic keep_running; CPacketQueue waiting_packet[3]; // the packet currently being processed in each vocoder CPacketQueue input_queue; std::future feedFuture, readFuture; - std::string devicepath, productid, version; + std::string description; + bool DiscoverFtdiDevices(); + void FTDI_Error(const char *where, FT_STATUS status) const; void FeedDevice(); void ReadDevice(); - bool SetBaudRate(int baudrate); bool InitDV3003(); - bool Purge(); bool ConfigureVocoder(uint8_t pkt_ch, Encoding type); bool checkResponse(SDV3003_Packet &responsePacket, uint8_t response) const; bool SendAudio(const uint8_t channel, const int16_t *audio) const; diff --git a/Makefile b/Makefile index 06ec29d..5e4782e 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ else CFLAGS = -W -Werror -Icodec2 -MMD -MD -std=c++11 endif -LDFLAGS = -pthread +LDFLAGS = -lftd2xx -pthread SRCS = $(wildcard *.cpp) $(wildcard codec2/*.cpp) OBJS = $(SRCS:.cpp=.o) @@ -22,7 +22,7 @@ DEPS = $(SRCS:.cpp=.d) EXE = tcd $(EXE) : $(OBJS) - $(GCC) $(LDFLAGS) $(OBJS) -o $@ + $(GCC) -o $@ $(OBJS) $(LDFLAGS) %.o : %.cpp $(GCC) $(CFLAGS) -c $< -o $@ diff --git a/WinTypes.h b/WinTypes.h new file mode 100644 index 0000000..df4c16f --- /dev/null +++ b/WinTypes.h @@ -0,0 +1,158 @@ +#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/ftd2xx.h b/ftd2xx.h new file mode 100644 index 0000000..4d874dc --- /dev/null +++ b/ftd2xx.h @@ -0,0 +1,1459 @@ +/*++ + +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 */ +