diff --git a/CMakeLists.txt b/CMakeLists.txt index 624b04a0..aaf8a12e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,8 @@ add_subdirectory("recorder") add_subdirectory("soapy") add_subdirectory("file_source") add_subdirectory("rtl_tcp_source") +# add_subdirectory("audio_sink") +add_subdirectory("rx888_source") add_subdirectory("demo") if (MSVC) diff --git a/audio_sink/CMakeLists.txt b/audio_sink/CMakeLists.txt new file mode 100644 index 00000000..ce0091fb --- /dev/null +++ b/audio_sink/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.13) +project(audio_sink) + +if (MSVC) + set(CMAKE_CXX_FLAGS "-O2 /std:c++17") +else() + set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive") +endif (MSVC) + +file(GLOB SRC "src/*.cpp") + +include_directories("src/") + +add_library(audio_sink SHARED ${SRC}) +target_link_libraries(audio_sink PRIVATE sdrpp_core) +set_target_properties(audio_sink PROPERTIES PREFIX "") \ No newline at end of file diff --git a/audio_sink/src/main.cpp b/audio_sink/src/main.cpp new file mode 100644 index 00000000..d2b4b3d3 --- /dev/null +++ b/audio_sink/src/main.cpp @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include + +#define CONCAT(a, b) ((std::string(a) + b).c_str()) + +class AudioSink : SinkManager::Sink { +public: + AudioSink(SinkManager::Stream* stream) { + _stream = stream; + } + + ~AudioSink() { + + } + + void menuHandler() { + + } + +private: + SinkManager::Stream* _stream; + +}; + +class AudioSinkModule { +public: + AudioSinkModule(std::string name) { + this->name = name; + provider.create = create_sink; + provider.ctx = this; + sigpath::sinkManager.registerSinkProvider("Audio", provider); + } + + ~AudioSinkModule() { + + } + +private: + static SinkManager::Sink* create_sink(SinkManager::Stream* stream, void* ctx) { + return (SinkManager::Sink*)(new AudioSink(stream)); + } + + std::string name; + SinkManager::SinkProvider provider; + +}; + +MOD_EXPORT void _INIT_() { + // Nothing here +} + +MOD_EXPORT void* _CREATE_INSTANCE_(std::string name) { + AudioSinkModule* instance = new AudioSinkModule(name); + return instance; +} + +MOD_EXPORT void _DELETE_INSTANCE_() { + +} + +MOD_EXPORT void _STOP_() { + +} \ No newline at end of file diff --git a/core/src/dsp/demodulator.h b/core/src/dsp/demodulator.h index b08cd820..a7f87b13 100644 --- a/core/src/dsp/demodulator.h +++ b/core/src/dsp/demodulator.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include @@ -138,6 +139,14 @@ namespace dsp { volk_32fc_magnitude_32f(out.data, (lv_32fc_t*)_in->data, count); _in->flush(); + + volk_32f_accumulator_s32f(&avg, out.data, count); + avg /= (float)count; + + for (int i = 0; i < count; i++) { + out.data[i] -= avg; + } + out.write(count); return count; } @@ -145,6 +154,7 @@ namespace dsp { stream out; private: + float avg; int count; stream* _in; diff --git a/core/src/dsp/filter.h b/core/src/dsp/filter.h index e59c34a9..36279766 100644 --- a/core/src/dsp/filter.h +++ b/core/src/dsp/filter.h @@ -1,8 +1,7 @@ #pragma once #include #include - -#include +#include namespace dsp { diff --git a/core/src/dsp/processing.h b/core/src/dsp/processing.h index 2574ddbf..fa3d5fc7 100644 --- a/core/src/dsp/processing.h +++ b/core/src/dsp/processing.h @@ -1,7 +1,7 @@ #pragma once #include - -#include +#include +#include namespace dsp { class FrequencyXlator : public generic_block { @@ -75,4 +75,56 @@ namespace dsp { stream* _in; }; + + class AGC : public generic_block { + public: + AGC() {} + + AGC(stream* in, float ratio) { init(in, ratio); } + + ~AGC() { generic_block::stop(); } + + void init(stream* in, float ratio) { + _in = in; + _ratio = ratio; + generic_block::registerInput(_in); + generic_block::registerOutput(&out); + } + + void setInputSize(stream* in) { + std::lock_guard lck(generic_block::ctrlMtx); + generic_block::tempStop(); + generic_block::unregisterInput(_in); + _in = in; + generic_block::registerInput(_in); + generic_block::tempStart(); + } + + int run() { + count = _in->read(); + if (count < 0) { return -1; } + + if (out.aquire() < 0) { return -1; } + + for (int i = 0; i < count; i++) { + level = (fabsf(_in->data[i]) * _ratio) + (level * (1.0f - _ratio)); + out.data[i] = _in->data[i] / level; + } + + + + _in->flush(); + out.write(count); + return count; + } + + stream out; + + private: + int count; + float level = 1.0f; + float _ratio; + stream* _in; + + }; } \ No newline at end of file diff --git a/core/src/dsp/resampling.h b/core/src/dsp/resampling.h index 0abbf6fa..257ab962 100644 --- a/core/src/dsp/resampling.h +++ b/core/src/dsp/resampling.h @@ -2,6 +2,7 @@ #include #include #include +#include namespace dsp { template diff --git a/core/src/dsp/routing.h b/core/src/dsp/routing.h index 1683a6e6..71f9d94c 100644 --- a/core/src/dsp/routing.h +++ b/core/src/dsp/routing.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include #include #include diff --git a/core/src/dsp/window.h b/core/src/dsp/window.h index aca55df3..ad96d0ff 100644 --- a/core/src/dsp/window.h +++ b/core/src/dsp/window.h @@ -27,7 +27,7 @@ namespace dsp { void setCutoff(float cutoff) { _cutoff = cutoff; } - + void setTransWidth(float transWidth) { _transWidth = transWidth; } diff --git a/core/src/event.h b/core/src/event.h new file mode 100644 index 00000000..5adea8f4 --- /dev/null +++ b/core/src/event.h @@ -0,0 +1,42 @@ +#pragma once +#include +#include + +template +class Event { +public: + Event() {} + ~Event() {} + + struct EventHandler { + EventHandler(void (*handler)(T, void*), void* ctx) { + this->handler = handler; + this->ctx = ctx; + } + + void (*handler)(T, void*); + void* ctx; + }; + + void emit(T value) { + for (auto const& handler : handlers) { + handler.handler(value, handler.ctx); + } + } + + void bindHandler(const EventHandler& handler) { + handlers.push_back(handler); + } + + void unbindHandler(const EventHandler& handler) { + if (handlers.find(handler) == handlers.end()) { + spdlog::error("Tried to remove a non-existant event handler"); + return; + } + handlers.erase(std::remove(handlers.begin(), handlers.end(), handler), handlers.end()); + } + +private: + std::vector handlers; + +}; \ No newline at end of file diff --git a/core/src/gui/main_window.cpp b/core/src/gui/main_window.cpp index 73e8af55..4fcdfe7d 100644 --- a/core/src/gui/main_window.cpp +++ b/core/src/gui/main_window.cpp @@ -7,13 +7,8 @@ #include #include #include -#include -#include -#include #include #include -#include -#include #include #include #include diff --git a/core/src/signal_path/dsp.h b/core/src/signal_path/dsp.h index e41860aa..900e3cf2 100644 --- a/core/src/signal_path/dsp.h +++ b/core/src/signal_path/dsp.h @@ -1,13 +1,8 @@ #pragma once -#include -#include -#include -#include -#include #include -#include #include #include +#include #include class SignalPath { diff --git a/core/src/signal_path/signal_path.cpp b/core/src/signal_path/signal_path.cpp index 2ae0939d..89c10d1c 100644 --- a/core/src/signal_path/signal_path.cpp +++ b/core/src/signal_path/signal_path.cpp @@ -4,4 +4,5 @@ namespace sigpath { SignalPath signalPath; VFOManager vfoManager; SourceManager sourceManager; + SinkManager sinkManager; }; \ No newline at end of file diff --git a/core/src/signal_path/signal_path.h b/core/src/signal_path/signal_path.h index d179306d..49693270 100644 --- a/core/src/signal_path/signal_path.h +++ b/core/src/signal_path/signal_path.h @@ -2,10 +2,12 @@ #include #include #include +#include #include namespace sigpath { SDRPP_EXPORT SignalPath signalPath; SDRPP_EXPORT VFOManager vfoManager; SDRPP_EXPORT SourceManager sourceManager; + SDRPP_EXPORT SinkManager sinkManager; }; \ No newline at end of file diff --git a/core/src/signal_path/sink.cpp b/core/src/signal_path/sink.cpp new file mode 100644 index 00000000..22c862c7 --- /dev/null +++ b/core/src/signal_path/sink.cpp @@ -0,0 +1,98 @@ +#include +#include +#include + +SinkManager::SinkManager() { + +} + +SinkManager::Stream::Stream(dsp::stream* in, const Event::EventHandler& srChangeHandler, float sampleRate) { + _in = in; + srChange.bindHandler(srChangeHandler); + _sampleRate = sampleRate; + splitter.init(_in); +} + +void SinkManager::Stream::setInput(dsp::stream* in) { + std::lock_guard lck(ctrlMtx); + _in = in; + splitter.setInput(_in); +} + +dsp::stream* SinkManager::Stream::bindStream() { + dsp::stream* stream = new dsp::stream; + splitter.bindStream(stream); + return stream; +} + +void SinkManager::Stream::unbindStream(dsp::stream* stream) { + splitter.unbindStream(stream); + delete stream; +} + +void SinkManager::Stream::setSampleRate(float sampleRate) { + std::lock_guard lck(ctrlMtx); + _sampleRate = sampleRate; + srChange.emit(sampleRate); +} + +void SinkManager::registerSinkProvider(std::string name, SinkProvider provider) { + if (providers.find(name) != providers.end()) { + spdlog::error("Cannot create sink provider '{0}', this name is already taken", name); + return; + } + providers[name] = provider; +} + +void SinkManager::registerStream(std::string name, SinkManager::Stream* stream) { + if (streams.find(name) != streams.end()) { + spdlog::error("Cannot register stream '{0}', this name is already taken", name); + return; + } + + core::configManager.aquire(); + std::string providerName = core::configManager.conf["defaultSink"]; + core::configManager.release(); + + SinkManager::SinkProvider provider; + if (providers.find(providerName) == providers.end()) { + // TODO: get default + } + else { + provider = providers[providerName]; + } + + stream->sink = provider.create(stream, provider.ctx); +} + +void SinkManager::unregisterStream(std::string name) { + if (streams.find(name) == streams.end()) { + spdlog::error("Cannot unregister stream '{0}', this stream doesn't exist", name); + return; + } + SinkManager::Stream* stream = streams[name]; + delete stream->sink; + delete stream; +} + +dsp::stream* SinkManager::bindStream(std::string name) { + if (streams.find(name) == streams.end()) { + spdlog::error("Cannot bind to stream '{0}'. Stream doesn't exist", name); + return NULL; + } + return streams[name]->bindStream(); +} + +void SinkManager::unbindStream(std::string name, dsp::stream* stream) { + if (streams.find(name) == streams.end()) { + spdlog::error("Cannot unbind from stream '{0}'. Stream doesn't exist", name); + return; + } + streams[name]->unbindStream(stream); +} + +void SinkManager::showMenu() { + for (auto const& [name, stream] : streams) { + + } +} \ No newline at end of file diff --git a/core/src/signal_path/sink.h b/core/src/signal_path/sink.h new file mode 100644 index 00000000..0b89a28a --- /dev/null +++ b/core/src/signal_path/sink.h @@ -0,0 +1,65 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include + +class SinkManager { +public: + SinkManager(); + + class Sink { + public: + virtual void menuHandler() = 0; + }; + + class Stream { + public: + Stream(dsp::stream* in, const Event::EventHandler& srChangeHandler, float sampleRate); + + void setInput(dsp::stream* in); + + dsp::stream* bindStream(); + void unbindStream(dsp::stream* stream); + + friend SinkManager; + friend SinkManager::Sink; + + Event srChange; + + private: + void setSampleRate(float sampleRate); + + dsp::stream* _in; + dsp::Splitter splitter; + SinkManager::Sink* sink; + std::mutex ctrlMtx; + float _sampleRate; + + }; + + struct SinkProvider { + SinkManager::Sink* (*create)(SinkManager::Stream* stream, void* ctx); + void* ctx; + }; + + void registerSinkProvider(std::string name, SinkProvider provider); + + void registerStream(std::string name, Stream* stream); + void unregisterStream(std::string name); + + dsp::stream* bindStream(std::string name); + void unbindStream(std::string name, dsp::stream* stream); + + void showMenu(); + +private: + // TODO: Replace with std::unordered_map + std::map providers; + std::map streams; + + +}; \ No newline at end of file diff --git a/radio/src/path.cpp b/radio/src/path.cpp index 2bcd298b..1dbea4a4 100644 --- a/radio/src/path.cpp +++ b/radio/src/path.cpp @@ -45,6 +45,8 @@ void SigPath::init(std::string vfoName, uint64_t sampleRate, int blockSize) { amDemod.init(vfo->output); ssbDemod.init(vfo->output, 6000, 3000, dsp::SSBDemod::MODE_USB); + agc.init(&amDemod.out, 1.0f / 125.0f); + audioWin.init(24000, 24000, 200000); audioResamp.init(&demod.out, &audioWin, 200000, 48000); audioWin.setSampleRate(audioResamp.getInterpolation() * 200000); @@ -82,6 +84,7 @@ void SigPath::setDemodulator(int demId, float bandWidth) { demod.stop(); } else if (_demod == DEMOD_AM) { + agc.stop(); amDemod.stop(); } else if (_demod == DEMOD_USB) { @@ -139,7 +142,7 @@ void SigPath::setDemodulator(int demId, float bandWidth) { else if (demId == DEMOD_AM) { demodOutputSamplerate = 125000; vfo->setSampleRate(12500, bandwidth); - audioResamp.setInput(&amDemod.out); + audioResamp.setInput(&agc.out); audioBw = std::min(bandwidth, outputSampleRate / 2.0f); audioResamp.setInSampleRate(12500); @@ -150,6 +153,7 @@ void SigPath::setDemodulator(int demId, float bandWidth) { deemp.bypass = true; vfo->setReference(ImGui::WaterfallVFO::REF_CENTER); + agc.start(); amDemod.start(); } else if (demId == DEMOD_USB) { diff --git a/radio/src/path.h b/radio/src/path.h index 5b21c098..f6c8e8f4 100644 --- a/radio/src/path.h +++ b/radio/src/path.h @@ -1,18 +1,13 @@ #pragma once -#include #include -#include -#include #include -#include -#include -#include -#include +#include #include #include #include #include #include +#include class SigPath { public: @@ -58,13 +53,14 @@ private: dsp::AMDemod amDemod; dsp::SSBDemod ssbDemod; + // Gain control + dsp::AGC agc; + // Audio output dsp::MonoToStereo m2s; dsp::filter_window::BlackmanWindow audioWin; dsp::PolyphaseResampler audioResamp; - dsp::NullSink ns; - std::string vfoName; float sampleRate; diff --git a/recorder/src/main.cpp b/recorder/src/main.cpp index 76675b5f..c12676c0 100644 --- a/recorder/src/main.cpp +++ b/recorder/src/main.cpp @@ -179,32 +179,30 @@ private: while (true) { int count = _this->audioStream->read(); if (count < 0) { break; } - for (int i = 0; i < 240; i++) { + for (int i = 0; i < count; i++) { sampleBuf[(i * 2) + 0] = _this->audioStream->data[i].l * 0x7FFF; sampleBuf[(i * 2) + 1] = _this->audioStream->data[i].r * 0x7FFF; } _this->audioStream->flush(); - _this->samplesWritten += 240; - _this->writer->writeSamples(sampleBuf, 480 * sizeof(int16_t)); + _this->samplesWritten += count; + _this->writer->writeSamples(sampleBuf, count * sizeof(int16_t) * 2); } delete[] sampleBuf; } static void _iqWriteWorker(RecorderModule* _this) { - dsp::complex_t* iqBuf = new dsp::complex_t[1024]; - int16_t* sampleBuf = new int16_t[2048]; + int16_t* sampleBuf = new int16_t[STREAM_BUFFER_SIZE]; while (true) { int count = _this->iqStream->read(); if (count < 0) { break; } - for (int i = 0; i < 1024; i++) { + for (int i = 0; i < count; i++) { sampleBuf[(i * 2) + 0] = _this->iqStream->data[i].q * 0x7FFF; sampleBuf[(i * 2) + 1] = _this->iqStream->data[i].i * 0x7FFF; } _this->iqStream->flush(); - _this->samplesWritten += 1024; - _this->writer->writeSamples(sampleBuf, 2048 * sizeof(int16_t)); + _this->samplesWritten += count; + _this->writer->writeSamples(sampleBuf, count * sizeof(int16_t) * 2); } - delete[] iqBuf; delete[] sampleBuf; } diff --git a/root_dev/config.json b/root_dev/config.json index ceecee59..7a7f906b 100644 --- a/root_dev/config.json +++ b/root_dev/config.json @@ -1,43 +1,44 @@ -{ - "audio": { - "Radio": { - "device": "Speakers (Realtek High Definiti", - "sampleRate": 48000.0, - "volume": 0.7265625 - }, - "Radio 1": { - "device": "Speakers (Realtek High Definition Audio)", - "sampleRate": 48000.0, - "volume": 0.609375 - }, - "Radio 2": { - "device": "CABLE Input (VB-Audio Virtual Cable)", - "sampleRate": 48000.0, - "volume": 1.0 - } - }, - "bandPlan": "General", - "bandPlanEnabled": true, - "fftHeight": 296, - "frequency": 99000000, - "max": 0.0, - "maximized": false, - "menuOrder": [ - "Source", - "Radio", - "Recorder", - "Audio", - "Scripting", - "Band Plan", - "Display" - ], - "menuWidth": 300, - "min": -52.20588302612305, - "showWaterfall": true, - "source": "", - "sourceSettings": {}, - "windowSize": { - "h": 1053, - "w": 959 - } +{ + "audio": { + "Radio": { + "device": "Speakers (Realtek High Definiti", + "sampleRate": 48000.0, + "volume": 0.4888888895511627 + }, + "Radio 1": { + "device": "Speakers (Realtek High Definition Audio)", + "sampleRate": 48000.0, + "volume": 0.609375 + }, + "Radio 2": { + "device": "CABLE Input (VB-Audio Virtual Cable)", + "sampleRate": 48000.0, + "volume": 1.0 + } + }, + "bandPlan": "General", + "bandPlanEnabled": true, + "defaultSink": "Audio", + "fftHeight": 296, + "frequency": 144751270, + "max": -5.14705753326416, + "maximized": true, + "menuOrder": [ + "Source", + "Radio", + "Recorder", + "Audio", + "Scripting", + "Band Plan", + "Display" + ], + "menuWidth": 300, + "min": -63.97058868408203, + "showWaterfall": true, + "source": "", + "sourceSettings": {}, + "windowSize": { + "h": 720, + "w": 1280 + } } \ No newline at end of file diff --git a/root_dev/module_list.json b/root_dev/module_list.json index 5a29e31f..e068ba01 100644 --- a/root_dev/module_list.json +++ b/root_dev/module_list.json @@ -1,6 +1,7 @@ { - "Radio": "./radio/radio.so", - "Recorder": "./recorder/recorder.so", - "Soapy": "./soapy/soapy.so", - "RTLTCPSource": "./rtl_tcp_source/rtl_tcp_source.so" + "Radio": "./radio/Release/radio.dll", + "Recorder": "./recorder/Release/recorder.dll", + "Soapy": "./soapy/Release/soapy.dll", + "RTLTCPSource": "./rtl_tcp_source/Release/rtl_tcp_source.dll", + "RX888Source": "./rx888_source/Release/rx888_source.dll" } diff --git a/root_dev/soapy_source_config.json b/root_dev/soapy_source_config.json index 18a48d4a..af377c41 100644 --- a/root_dev/soapy_source_config.json +++ b/root_dev/soapy_source_config.json @@ -1,5 +1,5 @@ { - "device": "HackRF One #0 901868dc282c8f8b", + "device": "Generic RTL2832U OEM :: 00000001", "devices": { "AirSpy HF+ [c852435de0224af7]": { "gains": { @@ -13,9 +13,9 @@ }, "Generic RTL2832U OEM :: 00000001": { "gains": { - "TUNER": 49.599998474121094 + "TUNER": 7.244999885559082 }, - "sampleRate": 2560000.0 + "sampleRate": 250000.0 }, "HackRF One #0 901868dc282c8f8b": { "gains": { diff --git a/rx888_source/CMakeLists.txt b/rx888_source/CMakeLists.txt new file mode 100644 index 00000000..4922e29f --- /dev/null +++ b/rx888_source/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.13) +project(rx888_source) + +if (MSVC) + set(CMAKE_CXX_FLAGS "-O2 /std:c++17") +else() + set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive") +endif (MSVC) + +include_directories("src/CyAPI") + +file(GLOB SRC "src/*.cpp") +file(GLOB CYAPI "src/CyAPI/*.cpp") + +add_library(rx888_source SHARED ${SRC} ${CYAPI}) +target_link_libraries(rx888_source PRIVATE sdrpp_core) +set_target_properties(rx888_source PROPERTIES PREFIX "") \ No newline at end of file diff --git a/rx888_source/src/CyAPI/CyAPI.cpp b/rx888_source/src/CyAPI/CyAPI.cpp new file mode 100644 index 00000000..ac9a5ced --- /dev/null +++ b/rx888_source/src/CyAPI/CyAPI.cpp @@ -0,0 +1,3360 @@ +/* + ## Cypress CyAPI C++ library source file (CyAPI.cpp) + ## ======================================================= + ## + ## Copyright Cypress Semiconductor Corporation, 2009-2012, + ## All Rights Reserved + ## UNPUBLISHED, LICENSED SOFTWARE. + ## + ## CONFIDENTIAL AND PROPRIETARY INFORMATION + ## WHICH IS THE PROPERTY OF CYPRESS. + ## + ## Use of this file is governed + ## by the license agreement included in the file + ## + ## /license/license.rtf + ## + ## where is the Cypress software + ## install root directory path. + ## + ## ======================================================= +*/ +#ifndef WINVER +#define WINVER 0x0500 +#endif + +#include +#include +#include +#include "cyioctl.h" +#include "CyAPI.h" +#include "UsbdStatus.h" +#include "dbt.h" + +const char API_VERSION[8] = "1.3.2.0"; + +UINT SPI_FLASH_PAGE_SIZE_IN_BYTE = 256; +UINT SPI_FLASH_SECTOR_SIZE_IN_BYTE = (64 * 1024); +UINT CYWB_BL_MAX_BUFFER_SIZE_WHEN_USING_EP0_TRANSPORT = BUFSIZE_UPORT; //(8 * 512); // 4KB + +//////////////////////////////////////////////////////////////////////////////// +// +// The USB Device Class +// +//////////////////////////////////////////////////////////////////////////////// + +// Constructor +CCyUSBDevice::CCyUSBDevice(HANDLE hnd, GUID guid, BOOL bOpen) +{ + hDevice = INVALID_HANDLE_VALUE; + hDevNotification = 0; + hHndNotification = 0; + + DevNum = 0; + CfgNum = 0; + IntfcNum = 0; // The current selected interface's bInterfaceNumber + IntfcIndex = 0; // The entry in the Config's interfaces table matching to IntfcNum and AltSetting + + Devices = 0; + Interfaces = 0; + AltInterfaces = 0; + Configs = 0; + + DrvGuid = guid; + hWnd = hnd; + LastError = 0; + + EndPoints = NULL; + ControlEndPt = NULL; + IsocInEndPt = NULL; + IsocOutEndPt = NULL; + BulkInEndPt = NULL; + BulkOutEndPt = NULL; + InterruptInEndPt = NULL; + InterruptOutEndPt = NULL; + + USBCfgs[0] = NULL; + USBCfgs[1] = NULL; + USBConfigDescriptors[0] = NULL; + USBConfigDescriptors[1] = NULL; + pUsbBosDescriptor = NULL; + UsbBos = NULL; + + ZeroMemory(Manufacturer, USB_STRING_MAXLEN); + ZeroMemory(Product, USB_STRING_MAXLEN); + ZeroMemory(SerialNumber, USB_STRING_MAXLEN); + ZeroMemory(DeviceName, USB_STRING_MAXLEN); + ZeroMemory(FriendlyName, USB_STRING_MAXLEN); + + + if (hnd) RegisterForPnpEvents(hnd); + + if (bOpen) Open(DevNum); +} + +//______________________________________________________________________________ + +CCyUSBDevice::~CCyUSBDevice(void) +{ + + Close(); + + if (hDevNotification) { + if (! UnregisterDeviceNotification(hDevNotification)) + throw "Failed to close the device notification handle."; + + hDevNotification = 0; + } + +} + + +//______________________________________________________________________________ +// +// It is expected that the device will only expose a single Config via the +// Windows USB HCD stack. The driver doesn't even expose an IOCTL for setting +// the configuration. +// +// This method just initializes a bunch of important variables, most important +// of which is the call to SetAltIntfcParams( ). + +void CCyUSBDevice::SetConfig(UCHAR cfg){ + + if (!USBCfgs[0]) return; + + CfgNum = 0; + if ((USBCfgs[0]) && (USBCfgs[0]->iConfiguration == cfg)) CfgNum = cfg; + if ((USBCfgs[1]) && (USBCfgs[1]->iConfiguration == cfg)) CfgNum = cfg; + + ConfigValue = USBCfgs[CfgNum]->bConfigurationValue; + ConfigAttrib = USBCfgs[CfgNum]->bmAttributes; + MaxPower = USBCfgs[CfgNum]->MaxPower; + Interfaces = USBCfgs[CfgNum]->bNumInterfaces; + AltInterfaces = USBCfgs[CfgNum]->AltInterfaces; + IntfcNum = USBCfgs[CfgNum]->Interfaces[0]->bInterfaceNumber; + + UCHAR a = AltIntfc(); // Get the current alt setting from the device + SetAltIntfcParams(a); // Initializes endpts, IntfcIndex, etc. without actually setting the AltInterface + + if (USBCfgs[CfgNum]->Interfaces[IntfcIndex]) { + IntfcClass = USBCfgs[CfgNum]->Interfaces[IntfcIndex]->bInterfaceClass; + IntfcSubClass = USBCfgs[CfgNum]->Interfaces[IntfcIndex]->bInterfaceSubClass; + IntfcProtocol = USBCfgs[CfgNum]->Interfaces[IntfcIndex]->bInterfaceProtocol; + } + + +} + +//______________________________________________________________________________ + + +UCHAR CCyUSBDevice::ConfigCount(void){ + + if (hDevice == INVALID_HANDLE_VALUE) return (UCHAR) NULL; + + return Configs; + +} + +//______________________________________________________________________________ + +UCHAR CCyUSBDevice::IntfcCount(void){ + + if (hDevice == INVALID_HANDLE_VALUE) return (UCHAR) NULL; + + return Interfaces; + +} + +//______________________________________________________________________________ +// This method is not currently exposed because the driver does not support +// selection of the interface. This is because the Windows USB hub driver +// creates a new device node for each interface. +/* +void CCyUSBDevice::SetInterface(UCHAR i){ +if (i < NumInterfaces) IntfcNum = i; + +if (Configs[CfgNum]) { +for (int j=0; j < Configs[CfgNum]->bAltInterfaces; j++) +if ( (Configs[CfgNum]->Interfaces[j]->bInterfaceNumber == IntfcNum) && +(Configs[CfgNum]->Interfaces[j]->bAlternateSetting == AltSetting) ) { + + +// TODO: Select the specified interface via the driver + + + +IntfcIndex = j; +return; +} +} + +} + +*/ +//______________________________________________________________________________ + +UCHAR CCyUSBDevice::AltIntfc(void){ + + UCHAR alt; + if (IoControl(IOCTL_ADAPT_GET_ALT_INTERFACE_SETTING, &alt, 1)) + return alt; + else + return 0xFF; +} + + +//______________________________________________________________________________ + +void CCyUSBDevice::SetAltIntfcParams(UCHAR alt){ + + // Find match of IntfcNum and alt in table of interfaces + if (USBCfgs[CfgNum]) { + for (int j=0; j < USBCfgs[CfgNum]->AltInterfaces; j++) + if ( //(USBCfgs[CfgNum]->Interfaces[j]->bInterfaceNumber == IntfcNum) && + (USBCfgs[CfgNum]->Interfaces[j]->bAlternateSetting == alt) ) { + + IntfcIndex = j; + IntfcClass = USBCfgs[CfgNum]->Interfaces[j]->bInterfaceClass; + IntfcSubClass = USBCfgs[CfgNum]->Interfaces[j]->bInterfaceSubClass;; + IntfcProtocol = USBCfgs[CfgNum]->Interfaces[j]->bInterfaceProtocol;; + + SetEndPointPtrs(); + return; + } + } + +} + +//______________________________________________________________________________ + +bool CCyUSBDevice::SetAltIntfc(UCHAR alt){ + + bool bSuccess = false; + + if (alt == AltIntfc()) return true; + + // Find match of IntfcNum and alt in table of interfaces + if (USBCfgs[CfgNum]) { + for (int j=0; j < USBCfgs[CfgNum]->AltInterfaces; j++) + if ( //(USBCfgs[CfgNum]->Interfaces[j]->bInterfaceNumber == IntfcNum) && + (USBCfgs[CfgNum]->Interfaces[j]->bAlternateSetting == alt) ) { + + IntfcIndex = j; + + // Actually change to the alt interface, calling the driver + bSuccess = IoControl(IOCTL_ADAPT_SELECT_INTERFACE, &alt, 1L); + + IntfcClass = USBCfgs[CfgNum]->Interfaces[j]->bInterfaceClass; + IntfcSubClass = USBCfgs[CfgNum]->Interfaces[j]->bInterfaceSubClass;; + IntfcProtocol = USBCfgs[CfgNum]->Interfaces[j]->bInterfaceProtocol;; + + SetEndPointPtrs(); + return bSuccess; + } + } + + return bSuccess; + +} + +//______________________________________________________________________________ +// Returns the total number of alternate interfaces for the current interface + +UCHAR CCyUSBDevice::AltIntfcCount(void) { + + if (USBCfgs[CfgNum]) + return USBCfgs[CfgNum]->Interfaces[IntfcIndex]->bAltSettings - 1; + + return 0; // The primary interface is not considered an Alt interface + // even though it does have an AltSetting value (0) + +} + + +//______________________________________________________________________________ + +UCHAR CCyUSBDevice::EndPointCount(void) { + + if (hDevice == INVALID_HANDLE_VALUE) return (UCHAR) NULL; + + if (USBCfgs[CfgNum]) + return USBCfgs[CfgNum]->Interfaces[IntfcIndex]->bNumEndpoints+1; // Include EndPt0 + + return (UCHAR) NULL; +} + + +//______________________________________________________________________________ + +void CCyUSBDevice::GetDeviceName(void) { + + ZeroMemory(DeviceName, USB_STRING_MAXLEN); + + if (hDevice == INVALID_HANDLE_VALUE) return; + + IoControl(IOCTL_ADAPT_GET_DEVICE_NAME, (PUCHAR)DeviceName, USB_STRING_MAXLEN); +} + +//______________________________________________________________________________ + +void CCyUSBDevice::GetFriendlyName(void) { + + ZeroMemory(FriendlyName, USB_STRING_MAXLEN); + + if (hDevice == INVALID_HANDLE_VALUE) return; + + IoControl(IOCTL_ADAPT_GET_FRIENDLY_NAME, (PUCHAR)FriendlyName, USB_STRING_MAXLEN); +} + +//______________________________________________________________________________ + +void CCyUSBDevice::GetUSBAddress(void) { + + if (hDevice == INVALID_HANDLE_VALUE) { + USBAddress = 0; + return; + } + + bool bRetVal = IoControl(IOCTL_ADAPT_GET_ADDRESS, &USBAddress, 1L); + if (!bRetVal || BytesXfered == 0) USBAddress = 0; +} + +//______________________________________________________________________________ + +void CCyUSBDevice::GetDriverVer(void) { + + if (hDevice == INVALID_HANDLE_VALUE) { + DriverVersion = (ULONG) NULL; + return; + } + + bool bRetVal = IoControl(IOCTL_ADAPT_GET_DRIVER_VERSION, (PUCHAR) &DriverVersion, sizeof(ULONG)); + if (!bRetVal || BytesXfered == 0) DriverVersion = 0; +} + +//______________________________________________________________________________ + +void CCyUSBDevice::GetUSBDIVer(void) { + + if (hDevice == INVALID_HANDLE_VALUE) { + USBDIVersion = (ULONG) NULL; + return; + } + + bool bRetVal = IoControl(IOCTL_ADAPT_GET_USBDI_VERSION, (PUCHAR) &USBDIVersion, sizeof(ULONG)); + if (!bRetVal || BytesXfered == 0) USBDIVersion = 0; +} + +//______________________________________________________________________________ + +UCHAR CCyUSBDevice::DeviceCount(void){ + + //SP_DEVINFO_DATA devInfoData; + SP_DEVICE_INTERFACE_DATA devInterfaceData; + + //Open a handle to the plug and play dev node. + //SetupDiGetClassDevs() returns a device information set that contains info on all + // installed devices of a specified class which are present. + HDEVINFO hwDeviceInfo = SetupDiGetClassDevs ( (LPGUID) &DrvGuid, + NULL, + NULL, + DIGCF_PRESENT|DIGCF_INTERFACEDEVICE); + + Devices = 0; + + if (hwDeviceInfo != INVALID_HANDLE_VALUE) { + + //SetupDiEnumDeviceInterfaces() returns information about device interfaces + // exposed by one or more devices. Each call returns information about one interface. + //The routine can be called repeatedly to get information about several interfaces + // exposed by one or more devices. + + devInterfaceData.cbSize = sizeof(devInterfaceData); + + // Count the number of devices + int i=0; + Devices = 0; + bool bDone = false; + + while (!bDone) { + BOOL bRetVal = SetupDiEnumDeviceInterfaces (hwDeviceInfo, 0, (LPGUID) &DrvGuid, + i, &devInterfaceData); + + if (bRetVal) + Devices++; + else { + DWORD dwLastError = GetLastError(); + if (dwLastError == ERROR_NO_MORE_ITEMS) bDone = TRUE; + } + + i++; + } + + SetupDiDestroyDeviceInfoList(hwDeviceInfo); + } + + return Devices; +} + +//______________________________________________________________________________ + +bool CCyUSBDevice::CreateHandle(UCHAR dev){ + + Devices = DeviceCount(); + + if (!Devices) return false; + + if (dev > (Devices - 1)) return false; //dev = Devices-1; + + SP_DEVINFO_DATA devInfoData; + SP_DEVICE_INTERFACE_DATA devInterfaceData; + PSP_INTERFACE_DEVICE_DETAIL_DATA functionClassDeviceData; + SP_INTERFACE_DEVICE_DETAIL_DATA tmpInterfaceDeviceDetailData; + + ULONG requiredLength = 0; + int deviceNumber = dev; + + HANDLE hFile; + + //Open a handle to the plug and play dev node. + //SetupDiGetClassDevs() returns a device information set that contains info on all + // installed devices of a specified class which are present. + HDEVINFO hwDeviceInfo = SetupDiGetClassDevs ( (LPGUID) &DrvGuid, + NULL, + NULL, + DIGCF_PRESENT|DIGCF_INTERFACEDEVICE); + + if (hwDeviceInfo != INVALID_HANDLE_VALUE) { + + //SetupDiEnumDeviceInterfaces() returns information about device interfaces + // exposed by one or more devices. Each call returns information about one interface. + //The routine can be called repeatedly to get information about several interfaces + // exposed by one or more devices. + + devInterfaceData.cbSize = sizeof(devInterfaceData); + + if (SetupDiEnumDeviceInterfaces ( hwDeviceInfo, 0, (LPGUID) &DrvGuid, + deviceNumber, &devInterfaceData)) { + //Allocate a function class device data structure to receive the goods about this + // particular device. + SetupDiGetInterfaceDeviceDetail ( hwDeviceInfo, &devInterfaceData, NULL, 0, + &requiredLength, NULL); + + ULONG predictedLength = requiredLength; + + functionClassDeviceData = (PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc (predictedLength); + functionClassDeviceData->cbSize = sizeof (SP_INTERFACE_DEVICE_DETAIL_DATA); + devInfoData.cbSize = sizeof(devInfoData); + //Retrieve the information from Plug and Play */ + if (SetupDiGetInterfaceDeviceDetail (hwDeviceInfo, + &devInterfaceData, + functionClassDeviceData, + predictedLength, + &requiredLength, + &devInfoData)) { + + /* NOTE : x64 packing issue ,requiredLength return 5byte size of the (SP_INTERFACE_DEVICE_DETAIL_DATA) and functionClassDeviceData needed sizeof functionClassDeviceData 8byte */ + int pathLen = requiredLength - (sizeof (tmpInterfaceDeviceDetailData.cbSize)+sizeof (tmpInterfaceDeviceDetailData.DevicePath)); + //int pathLen = requiredLength - functionClassDeviceData->cbSize; + + memcpy (DevPath, functionClassDeviceData->DevicePath, pathLen); + DevPath[pathLen] = 0; + + hFile = CreateFile (DevPath, + GENERIC_WRITE | GENERIC_READ, + FILE_SHARE_WRITE | FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + NULL); + + DWORD errCode = GetLastError(); + free(functionClassDeviceData); + SetupDiDestroyDeviceInfoList(hwDeviceInfo); + + if (hFile == INVALID_HANDLE_VALUE) + { + LastError = GetLastError(); + return false; + } + // hDevice, DevNum, USBDeviceDescriptor, and Configs are data members + hDevice = hFile; + + return true; + } + + } + + SetupDiDestroyDeviceInfoList(hwDeviceInfo); + + } + + // Got here by failing at some point + + hDevice = INVALID_HANDLE_VALUE; + DevNum = 0; + return false; + +} + + +//______________________________________________________________________________ + +bool CCyUSBDevice::Open(UCHAR dev){ + + // If this CCyUSBDevice object already has the driver open, close it. + if (hDevice != INVALID_HANDLE_VALUE) + Close(); + + + + if (CreateHandle(dev)) { + DevNum = dev; + + // Important call: Gets the device descriptor data from the device + GetDevDescriptor(); + + // Gets the language IDs and selects English, if avail + SetStringDescrLanguage(); + + GetString(Manufacturer,USBDeviceDescriptor.iManufacturer); + GetString(Product,USBDeviceDescriptor.iProduct); + GetString(SerialNumber,USBDeviceDescriptor.iSerialNumber); + + // Get BOS descriptor + if ((BcdUSB & BCDUSBJJMASK) == USB30MAJORVER) + { + if(GetInternalBosDescriptor()) // USB3.0 specific descriptor + { + try + { + UsbBos = new CCyUSBBOS(hDevice,pUsbBosDescriptor); + } + catch(char *Str) + { + char *Str1 = Str;// just to ignore warning + MessageBox(NULL,"Please correct firmware BOS descriptor table","Wrong BOS Descriptor",(UINT) NULL); + Close(); // Close the device handle. + return false; + } + } + } + GetUSBAddress(); + GetDeviceName(); + GetFriendlyName(); + GetDriverVer(); + GetUSBDIVer(); + GetSpeed(); + + // Gets the config (including interface and endpoint) descriptors from the device + for (int i=0; iDscLen = 7; + ControlEndPt->DscType = 5; + ControlEndPt->Address = 0; + ControlEndPt->Attributes = 0; + ControlEndPt->MaxPktSize = MaxPacketSize; + ControlEndPt->Interval = 0; + + // We succeeded in openning a handle to the device. But, the device + // is not returning descriptors properly. We don't call Close( ) because + // we want to leave the hDevice intact, giving the user the opportunity + // to call the Reset( ) method + if (!USBCfgs[0] || !USBCfgs[0]->Interfaces[0]) + return false; + + // This call sets values for ConfigVal, ConfigAttrib, MaxPower, etc. + SetConfig(0); + + // If we registered for device notification, also register the handle + // This is necessary in order to receive notification of removal (allowing us to close) + // before the device re-connects (for such things as our ReConnect method). + if (hDevNotification) { + DEV_BROADCAST_HANDLE hFilter; + hFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE); + hFilter.dbch_devicetype = DBT_DEVTYP_HANDLE; + hFilter.dbch_handle = hDevice; + + hHndNotification = RegisterDeviceNotification(hWnd, (PVOID) &hFilter, DEVICE_NOTIFY_WINDOW_HANDLE); + } + + return true; + } + + + // Got here by failing at some point + + hDevice = INVALID_HANDLE_VALUE; + DevNum = 0; + return false; +} + + +//______________________________________________________________________________ + +void CCyUSBDevice::DestroyHandle(void){ + + if ( hDevice != INVALID_HANDLE_VALUE ) { + + if (hHndNotification) + if (! UnregisterDeviceNotification(hHndNotification)) + { + LastError = GetLastError(); + throw "Failed to close the handle notification handle."; + } + + if (! CloseHandle(hDevice)) + { + LastError = GetLastError(); + throw "Failed to close handle to driver."; + } + + hDevice = INVALID_HANDLE_VALUE; + hHndNotification = 0; + } + +} +//______________________________________________________________________________ + +void CCyUSBDevice::Close(void){ + + DestroyHandle(); + ZeroMemory(&USBDeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR)); + + if(pUsbBosDescriptor) + { + free(pUsbBosDescriptor); + pUsbBosDescriptor =NULL; + } + if(UsbBos) + { + delete UsbBos ; + UsbBos = NULL; + } + // Clean-up dynamically allocated objects + for (int i=0; iSetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST; + pSingleTransfer->SetupPacket.bmReqType.Type = 0; + pSingleTransfer->SetupPacket.bmReqType.Recipient = 0; + pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; + pSingleTransfer->SetupPacket.wVal.hiByte = USB_BOS_DESCRIPTOR_TYPE; + pSingleTransfer->SetupPacket.wVal.lowByte = 0; + pSingleTransfer->SetupPacket.wLength = sizeof(USB_BOS_DESCRIPTOR); + pSingleTransfer->SetupPacket.ulTimeOut = 5; + pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength; + pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER); + + bool bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf, length); + UsbdStatus = pSingleTransfer->UsbdStatus; + NtStatus = pSingleTransfer->NtStatus; + + if (bRetVal) { + PUSB_BOS_DESCRIPTOR BosDesc = (PUSB_BOS_DESCRIPTOR)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset); + USHORT BosDescLength= BosDesc->wTotalLength; + + length = sizeof(SINGLE_TRANSFER) + BosDescLength; + PUCHAR buf2 = new UCHAR[length]; + ZeroMemory (buf2, length); + + pSingleTransfer = (PSINGLE_TRANSFER) buf2; + pSingleTransfer->SetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST; + pSingleTransfer->SetupPacket.bmReqType.Type = 0; + pSingleTransfer->SetupPacket.bmReqType.Recipient = 0; + pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; + pSingleTransfer->SetupPacket.wVal.hiByte = USB_BOS_DESCRIPTOR_TYPE; + pSingleTransfer->SetupPacket.wVal.lowByte = 0; + pSingleTransfer->SetupPacket.wLength = BosDescLength; + pSingleTransfer->SetupPacket.ulTimeOut = 5; + pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength; + pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER); + + bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf2, length); + UsbdStatus = pSingleTransfer->UsbdStatus; + NtStatus = pSingleTransfer->NtStatus; + + if (bRetVal) + { + pUsbBosDescriptor = (PUSB_BOS_DESCRIPTOR)malloc(BosDescLength); + memcpy(pUsbBosDescriptor, (PVOID)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset), BosDescLength); + } + + delete[] buf2; + + } + + delete[] buf; + return bRetVal; +} +void CCyUSBDevice::GetDevDescriptor(void) +{ + + ULONG length = sizeof(SINGLE_TRANSFER) + sizeof(USB_DEVICE_DESCRIPTOR); + PUCHAR buf = new UCHAR[length]; + ZeroMemory (buf, length); + + //USB_DEVICE_DESCRIPTOR devDescriptor; + ZeroMemory (&USBDeviceDescriptor, sizeof(USB_DEVICE_DESCRIPTOR)); + + PSINGLE_TRANSFER pSingleTransfer = (PSINGLE_TRANSFER) buf; + pSingleTransfer->SetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST; + pSingleTransfer->SetupPacket.bmReqType.Type = 0; + pSingleTransfer->SetupPacket.bmReqType.Recipient = 0; + pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; + pSingleTransfer->SetupPacket.wVal.hiByte = USB_DEVICE_DESCRIPTOR_TYPE; + pSingleTransfer->SetupPacket.wLength = sizeof(USB_DEVICE_DESCRIPTOR); + pSingleTransfer->SetupPacket.ulTimeOut = 5; + pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength; + pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER); + + bool bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf, length); + UsbdStatus = pSingleTransfer->UsbdStatus; + NtStatus = pSingleTransfer->NtStatus; + + if (bRetVal) { + memcpy(&USBDeviceDescriptor, (PVOID)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset), sizeof(USB_DEVICE_DESCRIPTOR)); + + BcdUSB = USBDeviceDescriptor.bcdUSB; + VendorID = USBDeviceDescriptor.idVendor; + ProductID = USBDeviceDescriptor.idProduct; + DevClass = USBDeviceDescriptor.bDeviceClass; + DevSubClass = USBDeviceDescriptor.bDeviceSubClass; + DevProtocol = USBDeviceDescriptor.bDeviceProtocol; + if((BcdUSB & BCDUSBJJMASK) == USB20MAJORVER) + MaxPacketSize = USBDeviceDescriptor.bMaxPacketSize0; + else + MaxPacketSize = (1<SetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST; + pSingleTransfer->SetupPacket.bmReqType.Type = 0; + pSingleTransfer->SetupPacket.bmReqType.Recipient = 0; + pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; + pSingleTransfer->SetupPacket.wVal.hiByte = USB_STRING_DESCRIPTOR_TYPE; + pSingleTransfer->SetupPacket.wVal.lowByte = 0; + pSingleTransfer->SetupPacket.wLength = sizeof(USB_COMMON_DESCRIPTOR); + pSingleTransfer->SetupPacket.ulTimeOut = 5; + pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength; + pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER); + + bool bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf, length); + UsbdStatus = pSingleTransfer->UsbdStatus; + + if (bRetVal) { + memcpy(&cmnDescriptor, (PVOID)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset), sizeof(USB_COMMON_DESCRIPTOR)); + + int LangIDs = (cmnDescriptor.bLength - 2 ) / 2; + + // Get the entire descriptor, all LangIDs + length = sizeof(SINGLE_TRANSFER) + cmnDescriptor.bLength; + PUCHAR buf2 = new UCHAR[length]; + ZeroMemory (buf2, length); + + pSingleTransfer = (PSINGLE_TRANSFER) buf2; + pSingleTransfer->SetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST; + pSingleTransfer->SetupPacket.bmReqType.Type = 0; + pSingleTransfer->SetupPacket.bmReqType.Recipient = 0; + pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; + pSingleTransfer->SetupPacket.wVal.hiByte = USB_STRING_DESCRIPTOR_TYPE; + pSingleTransfer->SetupPacket.wVal.lowByte = 0; + pSingleTransfer->SetupPacket.wLength = cmnDescriptor.bLength; + pSingleTransfer->SetupPacket.ulTimeOut = 5; + pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength; + pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER); + + bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf2, length); + + UsbdStatus = pSingleTransfer->UsbdStatus; + + if (bRetVal) { + PUSB_STRING_DESCRIPTOR IDs = (PUSB_STRING_DESCRIPTOR) (buf2 + sizeof(SINGLE_TRANSFER)); + + StrLangID =(LangIDs) ? IDs[0].bString[0] : 0; + + for (int i=0; iSetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST; + pSingleTransfer->SetupPacket.bmReqType.Type = 0; + pSingleTransfer->SetupPacket.bmReqType.Recipient = 0; + pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; + pSingleTransfer->SetupPacket.wVal.hiByte = USB_STRING_DESCRIPTOR_TYPE; + pSingleTransfer->SetupPacket.wVal.lowByte = sIndex; + pSingleTransfer->SetupPacket.wIndex = StrLangID; + pSingleTransfer->SetupPacket.wLength = sizeof(USB_COMMON_DESCRIPTOR); + pSingleTransfer->SetupPacket.ulTimeOut = 5; + pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength; + pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER); + + bool bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf, length); + UsbdStatus = pSingleTransfer->UsbdStatus; + NtStatus = pSingleTransfer->NtStatus; + + if (bRetVal) { + memcpy(&cmnDescriptor, (PVOID)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset), sizeof(USB_COMMON_DESCRIPTOR)); + + // Get the entire descriptor + length = sizeof(SINGLE_TRANSFER) + cmnDescriptor.bLength; + PUCHAR buf2 = new UCHAR[length]; + ZeroMemory (buf2, length); + + pSingleTransfer = (PSINGLE_TRANSFER) buf2; + pSingleTransfer->SetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST; + pSingleTransfer->SetupPacket.bmReqType.Type = 0; + pSingleTransfer->SetupPacket.bmReqType.Recipient = 0; + pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; + pSingleTransfer->SetupPacket.wVal.hiByte = USB_STRING_DESCRIPTOR_TYPE; + pSingleTransfer->SetupPacket.wVal.lowByte = sIndex; + pSingleTransfer->SetupPacket.wIndex = StrLangID; + pSingleTransfer->SetupPacket.wLength = cmnDescriptor.bLength; + pSingleTransfer->SetupPacket.ulTimeOut = 5; + pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength; + pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER); + + bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf2, length); + UsbdStatus = pSingleTransfer->UsbdStatus; + NtStatus = pSingleTransfer->NtStatus; + + UCHAR bytes = (buf2[sizeof(SINGLE_TRANSFER)]); + UCHAR signature = (buf2[sizeof(SINGLE_TRANSFER)+1]); + + if (bRetVal && (bytes>2) && (signature == 0x03)) { + ZeroMemory (str, USB_STRING_MAXLEN); + memcpy(str, (PVOID)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset+2), bytes-2); + } + + delete[] buf2; + + } + + delete[] buf; +} + +//______________________________________________________________________________ + +void CCyUSBDevice::GetCfgDescriptor(int descIndex) +{ + + ULONG length = sizeof(SINGLE_TRANSFER) + sizeof(USB_CONFIGURATION_DESCRIPTOR); + PUCHAR buf = new UCHAR[length]; + ZeroMemory (buf, length); + + PSINGLE_TRANSFER pSingleTransfer = (PSINGLE_TRANSFER) buf; + pSingleTransfer->SetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST; + pSingleTransfer->SetupPacket.bmReqType.Type = 0; + pSingleTransfer->SetupPacket.bmReqType.Recipient = 0; + pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; + pSingleTransfer->SetupPacket.wVal.hiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE; + pSingleTransfer->SetupPacket.wVal.lowByte = descIndex; + pSingleTransfer->SetupPacket.wLength = sizeof(USB_CONFIGURATION_DESCRIPTOR); + pSingleTransfer->SetupPacket.ulTimeOut = 5; + pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength; + pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER); + + bool bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf, length); + UsbdStatus = pSingleTransfer->UsbdStatus; + NtStatus = pSingleTransfer->NtStatus; + + if (bRetVal) { + PUSB_CONFIGURATION_DESCRIPTOR configDesc = (PUSB_CONFIGURATION_DESCRIPTOR)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset); + USHORT configDescLength= configDesc->wTotalLength; + + length = sizeof(SINGLE_TRANSFER) + configDescLength; + PUCHAR buf2 = new UCHAR[length]; + ZeroMemory (buf2, length); + + pSingleTransfer = (PSINGLE_TRANSFER) buf2; + pSingleTransfer->SetupPacket.bmReqType.Direction = DIR_DEVICE_TO_HOST; + pSingleTransfer->SetupPacket.bmReqType.Type = 0; + pSingleTransfer->SetupPacket.bmReqType.Recipient = 0; + pSingleTransfer->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR; + pSingleTransfer->SetupPacket.wVal.hiByte = USB_CONFIGURATION_DESCRIPTOR_TYPE; + pSingleTransfer->SetupPacket.wVal.lowByte = descIndex; + pSingleTransfer->SetupPacket.wLength = configDescLength; + pSingleTransfer->SetupPacket.ulTimeOut = 5; + pSingleTransfer->BufferLength = pSingleTransfer->SetupPacket.wLength; + pSingleTransfer->BufferOffset = sizeof(SINGLE_TRANSFER); + + bRetVal = IoControl(IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, buf2, length); + UsbdStatus = pSingleTransfer->UsbdStatus; + NtStatus = pSingleTransfer->NtStatus; + + if (bRetVal){ + USBConfigDescriptors[descIndex] = (PUSB_CONFIGURATION_DESCRIPTOR)malloc(configDescLength); + memcpy(USBConfigDescriptors[descIndex], (PVOID)((PCHAR)pSingleTransfer + pSingleTransfer->BufferOffset), configDescLength); + } + + delete[] buf2; + + } + + delete[] buf; +} + +//______________________________________________________________________________ + +bool CCyUSBDevice::Reset() +{ + return IoControl(IOCTL_ADAPT_RESET_PARENT_PORT, NULL, 0); +} + +//______________________________________________________________________________ + +bool CCyUSBDevice::ReConnect() +{ + return IoControl(IOCTL_ADAPT_CYCLE_PORT, NULL, 0); +} + + +//______________________________________________________________________________ + +bool CCyUSBDevice::Suspend() +{ + if (PowerState() == 4) return true; + + ULONG state = 4; + bool ret = IoControl(IOCTL_ADAPT_SET_DEVICE_POWER_STATE, (PUCHAR) &state, sizeof(state)); + + if ( 0 == state) return ret; + + return true; + +} + + +//______________________________________________________________________________ + +bool CCyUSBDevice::Resume() +{ + if (PowerState() == 1) return true; + + ULONG state = 1; + bool ret = IoControl(IOCTL_ADAPT_SET_DEVICE_POWER_STATE, (PUCHAR) &state, sizeof(state)); + + if ( 0 == state) return ret; + + return true; +} + + +//______________________________________________________________________________ + +void CCyUSBDevice::GetSpeed() +{ + ULONG speed = 0; + bHighSpeed = false; + bSuperSpeed = false; + + IoControl(IOCTL_ADAPT_GET_DEVICE_SPEED, (PUCHAR) &speed, sizeof(speed)); + + bHighSpeed = (speed == DEVICE_SPEED_HIGH); + bSuperSpeed = (speed == DEVICE_SPEED_SUPER); +} + + +//______________________________________________________________________________ + +UCHAR CCyUSBDevice::PowerState() +{ + ULONG state; + bool rval = IoControl(IOCTL_ADAPT_GET_DEVICE_POWER_STATE, (PUCHAR) &state, sizeof(state)); + + UCHAR s = (UCHAR) NULL; + + if (rval) s = (UCHAR) state; + + return s; + +} + + +//______________________________________________________________________________ + +CCyUSBEndPoint * CCyUSBDevice::EndPointOf(UCHAR addr) //throw(...) +{ + + if (addr == 0) return ControlEndPt; + + CCyUSBEndPoint *ept; + + int n = EndPointCount(); + + for (int i=0; iInterfaces[IntfcIndex]->EndPoints[i]; + + if (ept) + { + if (addr == ept->Address) return ept; } + else + throw "Failed to find endpoint."; + } + + return NULL; // Error + +} +//______________________________________________________________________________ + +bool CCyUSBDevice::GetBosDescriptor(PUSB_BOS_DESCRIPTOR descr) +{ + if ((BcdUSB & BCDUSBJJMASK) == USB30MAJORVER) + { + if(UsbBos!=NULL) + { + descr->bLength = UsbBos->bLength; + descr->bDescriptorType = UsbBos->bDescriptorType; + descr->bNumDeviceCaps = UsbBos->bNumDeviceCaps; + descr->wTotalLength = UsbBos->wTotalLength; + return true; + } + return false; + } + else + return false; +} +bool CCyUSBDevice::GetBosUSB20DeviceExtensionDescriptor(PUSB_BOS_USB20_DEVICE_EXTENSION descr) +{ + if ((BcdUSB & BCDUSBJJMASK) == USB30MAJORVER) + { + if(UsbBos->pUSB20_DeviceExt != NULL) + { + descr->bLength = UsbBos->pUSB20_DeviceExt->bLength; + descr->bDescriptorType = UsbBos->pUSB20_DeviceExt->bDescriptorType; + descr->bDevCapabilityType = UsbBos->pUSB20_DeviceExt->bDevCapabilityType; + descr->bmAttribute = UsbBos->pUSB20_DeviceExt->bmAttribute; + return true; + } + return false; + } + else + return false; +} +bool CCyUSBDevice::GetBosContainedIDDescriptor(PUSB_BOS_CONTAINER_ID descr) +{ + if ((BcdUSB & BCDUSBJJMASK) == USB30MAJORVER) + { + if(UsbBos->pContainer_ID != NULL) + { + descr->bLength = UsbBos->pContainer_ID->bLength; + descr->bDescriptorType = UsbBos->pContainer_ID->bDescriptorType; + descr->bDevCapabilityType = UsbBos->pContainer_ID->bDevCapabilityType; + descr->bReserved = UsbBos->pContainer_ID->bReserved; + for (int i=0;iContainerID[i] = UsbBos->pContainer_ID->ContainerID[i]; + + return true; + } + return false; + } + else + return false; +} +bool CCyUSBDevice::GetBosSSCapabilityDescriptor(PUSB_BOS_SS_DEVICE_CAPABILITY descr) +{ + if ((BcdUSB & BCDUSBJJMASK) == USB30MAJORVER) + { + if(UsbBos->pSS_DeviceCap != NULL) + { + descr->bLength = UsbBos->pSS_DeviceCap->bLength; + descr->bDescriptorType = UsbBos->pSS_DeviceCap->bDescriptorType; + descr->bDevCapabilityType = UsbBos->pSS_DeviceCap->bDevCapabilityType; + descr->bFunctionalitySupporte = UsbBos->pSS_DeviceCap->bFunctionalitySupporte; + descr->bmAttribute = UsbBos->pSS_DeviceCap->bmAttribute; + descr->bU1DevExitLat = UsbBos->pSS_DeviceCap->bU1DevExitLat; + descr->wSpeedsSuported = UsbBos->pSS_DeviceCap->SpeedsSuported; + descr->bU2DevExitLat = UsbBos->pSS_DeviceCap->bU2DevExitLat; + return true; + } + return false; + } + else + return false; +} +//______________________________________________________________________________ + +void CCyUSBDevice::GetDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR descr) +{ + // Copy the internal private data to the passed parameter + *descr = USBDeviceDescriptor; +} + +//______________________________________________________________________________ + +void CCyUSBDevice::GetConfigDescriptor(PUSB_CONFIGURATION_DESCRIPTOR descr) +{ + // Copy the internal private data to the passed parameter + *descr = *USBConfigDescriptors[CfgNum]; +} + +//______________________________________________________________________________ + +void CCyUSBDevice::GetIntfcDescriptor(PUSB_INTERFACE_DESCRIPTOR descr) +{ + CCyUSBInterface *i = USBCfgs[CfgNum]->Interfaces[IntfcIndex]; + + // Copy the internal private data to the passed parameter + descr->bLength = i->bLength; + descr->bDescriptorType = i->bDescriptorType; + descr->bInterfaceNumber = i->bInterfaceNumber; + descr->bAlternateSetting = i->bAlternateSetting; + descr->bNumEndpoints = i->bNumEndpoints; + descr->bInterfaceClass = i->bInterfaceClass; + descr->bInterfaceSubClass = i->bInterfaceSubClass; + descr->bInterfaceProtocol = i->bInterfaceProtocol; + descr->iInterface = i->iInterface; +} + +//______________________________________________________________________________ + +CCyUSBConfig CCyUSBDevice::GetUSBConfig(int index) +{ + // Rarely (i.e. never) have more than 1 Configuration + int i = (index > (Configs-1)) ? 0 : index; + + return *USBCfgs[i]; // Invoke the copy constructor +} + +//______________________________________________________________________________ + +void CCyUSBDevice::UsbdStatusString(ULONG stat, PCHAR str) +{ + //CString tmp; // MFC Version + //String tmp; + + char StateStr[24]; + char StatusStr[64]; + ZeroMemory(StateStr,24); + ZeroMemory(StatusStr,64); + + if (! USBD_STATUS(stat)) { + sprintf(StateStr,"[state=SUCCESS "); + sprintf(StatusStr,"status=USBD_STATUS_SUCCESS]"); + } else { + + switch(USBD_STATE(stat)) { + case USBD_STATUS_SUCCESS: sprintf(StateStr," [state=SUCCESS "); break; + case USBD_STATUS_PENDING: sprintf(StateStr," [state=PENDING "); break; + case USBD_STATUS_HALTED: sprintf(StateStr," [state=STALLED "); break; + case USBD_STATUS_ERROR: sprintf(StateStr," [state=ERROR "); break; + default: break; + } + + switch(stat|0xC0000000L) { // Note: error typedefs have both error and stall bit set + case USBD_STATUS_CRC: sprintf(StatusStr,"status=USBD_STATUS_CRC]"); break; + case USBD_STATUS_BTSTUFF: sprintf(StatusStr,"status=USBD_STATUS_BTSTUFF]"); break; + case USBD_STATUS_DATA_TOGGLE_MISMATCH: sprintf(StatusStr,"status=USBD_STATUS_DATA_TOGGLE_MISMATCH]"); break; + case USBD_STATUS_STALL_PID: sprintf(StatusStr,"status=USBD_STATUS_STALL_PID]"); break; + case USBD_STATUS_DEV_NOT_RESPONDING: sprintf(StatusStr,"status=USBD_STATUS_DEV_NOT_RESPONDING]"); break; + case USBD_STATUS_PID_CHECK_FAILURE: sprintf(StatusStr,"status=USBD_STATUS_PID_CHECK_FAILURE]"); break; + case USBD_STATUS_UNEXPECTED_PID: sprintf(StatusStr,"status=USBD_STATUS_UNEXPECTED_PID]"); break; + case USBD_STATUS_DATA_OVERRUN: sprintf(StatusStr,"status=USBD_STATUS_DATA_OVERRUN]"); break; + case USBD_STATUS_DATA_UNDERRUN: sprintf(StatusStr,"status=USBD_STATUS_DATA_UNDERRUN]"); break; + case USBD_STATUS_RESERVED1: sprintf(StatusStr,"status=USBD_STATUS_RESERVED1]"); break; + case USBD_STATUS_RESERVED2: sprintf(StatusStr,"status=USBD_STATUS_RESERVED2]"); break; + case USBD_STATUS_BUFFER_OVERRUN: sprintf(StatusStr,"status=USBD_STATUS_BUFFER_OVERRUN]"); break; + case USBD_STATUS_BUFFER_UNDERRUN: sprintf(StatusStr,"status=USBD_STATUS_BUFFER_UNDERRUN]"); break; + case USBD_STATUS_NOT_ACCESSED: sprintf(StatusStr,"status=USBD_STATUS_NOT_ACCESSED]"); break; + case USBD_STATUS_FIFO: sprintf(StatusStr,"status=USBD_STATUS_FIFO]"); break; + + case USBD_STATUS_ENDPOINT_HALTED: sprintf(StatusStr,"status=USBD_STATUS_ENDPOINT_HALTED]"); break; + case USBD_STATUS_NO_MEMORY: sprintf(StatusStr,"status=USBD_STATUS_NO_MEMORY]"); break; + case USBD_STATUS_INVALID_URB_FUNCTION: sprintf(StatusStr,"status=USBD_STATUS_INVALID_URB_FUNCTION]"); break; + case USBD_STATUS_INVALID_PARAMETER: sprintf(StatusStr,"status=USBD_STATUS_INVALID_PARAMETER]"); break; + case USBD_STATUS_ERROR_BUSY: sprintf(StatusStr,"status=USBD_STATUS_ERROR_BUSY]"); break; + case USBD_STATUS_REQUEST_FAILED: sprintf(StatusStr,"status=USBD_STATUS_REQUEST_FAILED]"); break; + case USBD_STATUS_INVALID_PIPE_HANDLE: sprintf(StatusStr,"status=USBD_STATUS_INVALID_PIPE_HANDLE]"); break; + case USBD_STATUS_NO_BANDWIDTH: sprintf(StatusStr,"status=USBD_STATUS_NO_BANDWIDTH]"); break; + case USBD_STATUS_INTERNAL_HC_ERROR: sprintf(StatusStr,"status=USBD_STATUS_INTERNAL_HC_ERROR]"); break; + case USBD_STATUS_ERROR_SHORT_TRANSFER: sprintf(StatusStr,"status=USBD_STATUS_ERROR_SHORT_TRANSFER]"); break; + case USBD_STATUS_BAD_START_FRAME: sprintf(StatusStr,"status=USBD_STATUS_BAD_START_FRAME]"); break; + case USBD_STATUS_ISOCH_REQUEST_FAILED: sprintf(StatusStr,"status=USBD_STATUS_ISOCH_REQUEST_FAILED]"); break; + case USBD_STATUS_FRAME_CONTROL_OWNED: sprintf(StatusStr,"status=USBD_STATUS_FRAME_CONTROL_OWNED]"); break; + case USBD_STATUS_FRAME_CONTROL_NOT_OWNED:sprintf(StatusStr,"status=USBD_STATUS_FRAME_CONTROL_NOT_OWNED]"); break; + case USBD_STATUS_CANCELED: sprintf(StatusStr,"status=USBD_STATUS_CANCELED]"); break; + case USBD_STATUS_CANCELING: sprintf(StatusStr,"status=USBD_STATUS_CANCELING]"); break; + + default: sprintf(StatusStr,"status=UNKNOWN]"); break; + } + } + + sprintf(str, "%s%s", StateStr, StatusStr); + +} + +//______________________________________________________________________________ + +// This method is called from Open, just after ControlEndPt has been instantiated +// It also gets called whenever a different Alt Interface setting is made +void CCyUSBDevice::SetEndPointPtrs(void) +{ + if (Configs == 0) return; + if (Interfaces == 0) return; + + EndPoints = USBCfgs[CfgNum]->Interfaces[IntfcIndex]->EndPoints; + EndPoints[0] = ControlEndPt; + int eptCount = EndPointCount() - 1; + + IsocInEndPt = NULL; + IsocOutEndPt = NULL; + BulkInEndPt = NULL; + BulkOutEndPt = NULL; + InterruptInEndPt = NULL; + InterruptOutEndPt = NULL; + + for (int i=0; iAddress & 0x80; + UCHAR attrib = EndPoints[i+1]->Attributes; + + + EndPoints[i+1]->XferMode = XMODE_DIRECT; + + if ((IsocInEndPt == NULL) && (attrib == 1) && bIn) IsocInEndPt = (CCyIsocEndPoint *)EndPoints[i+1]; + if ((BulkInEndPt == NULL) && (attrib == 2) && bIn) BulkInEndPt = (CCyBulkEndPoint *)EndPoints[i+1]; + if ((InterruptInEndPt == NULL) && (attrib == 3) && bIn) InterruptInEndPt = (CCyInterruptEndPoint *)EndPoints[i+1]; + + if ((IsocOutEndPt == NULL) && (attrib == 1) && !bIn) IsocOutEndPt = (CCyIsocEndPoint *)EndPoints[i+1]; + if ((BulkOutEndPt == NULL) && (attrib == 2) && !bIn) BulkOutEndPt = (CCyBulkEndPoint *)EndPoints[i+1]; + if ((InterruptOutEndPt == NULL) && (attrib == 3) && !bIn) InterruptOutEndPt = (CCyInterruptEndPoint *)EndPoints[i+1]; + } + +} + +//______________________________________________________________________________ + +bool CCyUSBDevice::RegisterForPnpEvents(HANDLE Handle) +{ + DEV_BROADCAST_DEVICEINTERFACE dFilter = {0}; + dFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); + dFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + dFilter.dbcc_classguid = DrvGuid; + + hDevNotification = RegisterDeviceNotification(Handle, (PVOID) &dFilter, DEVICE_NOTIFY_WINDOW_HANDLE); + if (!hDevNotification) + { + LastError = GetLastError(); + return false; + } + + return true; +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// The USB Interface Class +// +//////////////////////////////////////////////////////////////////////////////// + + +// The Copy Constructor +CCyUSBInterface::CCyUSBInterface(CCyUSBInterface &ifc) +{ + bLength = ifc.bLength; + bDescriptorType = ifc.bDescriptorType; + bInterfaceNumber = ifc.bInterfaceNumber; + bAlternateSetting = ifc.bAlternateSetting; + bNumEndpoints = ifc.bNumEndpoints; + bInterfaceClass = ifc.bInterfaceClass; + bInterfaceSubClass = ifc.bInterfaceSubClass; + bInterfaceProtocol = ifc.bInterfaceProtocol; + iInterface = ifc.iInterface; + + wTotalLength = ifc.wTotalLength; + + int i; + + for (i=0; iAttributes == 0) { + CCyControlEndPoint *e = (CCyControlEndPoint*)ifc.EndPoints[i]; + EndPoints[i] = new CCyControlEndPoint(*e); + } + + if (ifc.EndPoints[i]->Attributes == 1) { + CCyIsocEndPoint *e = (CCyIsocEndPoint*)ifc.EndPoints[i]; + EndPoints[i] = new CCyIsocEndPoint(*e); + } + + if (ifc.EndPoints[i]->Attributes == 2) { + CCyBulkEndPoint *e = (CCyBulkEndPoint*)ifc.EndPoints[i]; + EndPoints[i] = new CCyBulkEndPoint(*e); + } + + if (ifc.EndPoints[i]->Attributes == 3) { + CCyInterruptEndPoint *e = (CCyInterruptEndPoint*)ifc.EndPoints[i]; + EndPoints[i] = new CCyInterruptEndPoint(*e); + } + + } + +} + + +CCyUSBInterface::CCyUSBInterface(HANDLE handle, PUSB_INTERFACE_DESCRIPTOR pIntfcDescriptor) +{ + + PUSB_ENDPOINT_DESCRIPTOR endPtDesc; + + bLength = pIntfcDescriptor->bLength; + bDescriptorType = pIntfcDescriptor->bDescriptorType; + bInterfaceNumber = pIntfcDescriptor->bInterfaceNumber; + bAlternateSetting = pIntfcDescriptor->bAlternateSetting; + bNumEndpoints = pIntfcDescriptor->bNumEndpoints; + bInterfaceClass = pIntfcDescriptor->bInterfaceClass; + bInterfaceSubClass = pIntfcDescriptor->bInterfaceSubClass; + bInterfaceProtocol = pIntfcDescriptor->bInterfaceProtocol; + iInterface = pIntfcDescriptor->iInterface; + + bAltSettings = 0; + wTotalLength = bLength; + + PUCHAR desc = (PUCHAR)pIntfcDescriptor + pIntfcDescriptor->bLength; + + int i; + int unexpected = 0; + + for (i=0; ibLength; + + // We leave slot [0] empty to hold THE obligatory EndPoint Zero control endpoint + if (endPtDesc->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE) { + switch (endPtDesc->bmAttributes ) { + case 0: + EndPoints[i+1] = new CCyControlEndPoint(handle, endPtDesc); + break; + case 1: + EndPoints[i+1] = new CCyIsocEndPoint(handle, endPtDesc); + break; + case 2: + EndPoints[i+1] = new CCyBulkEndPoint(handle, endPtDesc); + break; + case 3: + EndPoints[i+1] = new CCyInterruptEndPoint(handle, endPtDesc); + break; + } + + desc += endPtDesc->bLength; + } else { + + unexpected++; + if (unexpected < 12) { // Sanity check - prevent infinite loop + + // This may have been a class-specific descriptor (like HID). Skip it. + desc += endPtDesc->bLength; + + // Stay in the loop, grabbing the next descriptor + i--; + } + + } + + } + + +} + +CCyUSBInterface::CCyUSBInterface(HANDLE handle, PUSB_INTERFACE_DESCRIPTOR pIntfcDescriptor,UCHAR usb30Dummy) +{ + + PUSB_ENDPOINT_DESCRIPTOR endPtDesc; + + bLength = pIntfcDescriptor->bLength; + bDescriptorType = pIntfcDescriptor->bDescriptorType; + bInterfaceNumber = pIntfcDescriptor->bInterfaceNumber; + bAlternateSetting = pIntfcDescriptor->bAlternateSetting; + bNumEndpoints = pIntfcDescriptor->bNumEndpoints; + bInterfaceClass = pIntfcDescriptor->bInterfaceClass; + bInterfaceSubClass = pIntfcDescriptor->bInterfaceSubClass; + bInterfaceProtocol = pIntfcDescriptor->bInterfaceProtocol; + iInterface = pIntfcDescriptor->iInterface; + + bAltSettings = 0; + wTotalLength = bLength; + + PUCHAR desc = (PUCHAR)pIntfcDescriptor + pIntfcDescriptor->bLength; + + int i; + int unexpected = 0; + + for (i=0; ibLength; + + PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR ssendPtDesc = (PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR)desc; + wTotalLength += endPtDesc->bLength; + + // We leave slot [0] empty to hold THE obligatory EndPoint Zero control endpoint + if (ssendPtDesc != NULL) + bSSDec = (ssendPtDesc->bDescriptorType == USB_SUPERSPEED_ENDPOINT_COMPANION); + + if ((endPtDesc->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE) && bSSDec) + { + switch (endPtDesc->bmAttributes ) + { + case 0: + EndPoints[i+1] = new CCyControlEndPoint(handle, endPtDesc); + break; + case 1: + EndPoints[i+1] = new CCyIsocEndPoint(handle, endPtDesc,ssendPtDesc); + break; + case 2: + EndPoints[i+1] = new CCyBulkEndPoint(handle, endPtDesc,ssendPtDesc); + break; + case 3: + EndPoints[i+1] = new CCyInterruptEndPoint(handle, endPtDesc,ssendPtDesc); + break; + } + + desc += ssendPtDesc->bLength; + wTotalLength += ssendPtDesc->bLength; + + } + else if (endPtDesc->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE) + { + switch (endPtDesc->bmAttributes ) + { + case 0: + EndPoints[i+1] = new CCyControlEndPoint(handle, endPtDesc); + break; + case 1: + EndPoints[i+1] = new CCyIsocEndPoint(handle, endPtDesc); + break; + case 2: + EndPoints[i+1] = new CCyBulkEndPoint(handle, endPtDesc); + break; + case 3: + EndPoints[i+1] = new CCyInterruptEndPoint(handle, endPtDesc); + break; + } + + //desc += endPtDesc->bLength; // THis a bug for the composite device + + } + else + { + + unexpected++; + if (unexpected < 12) { // Sanity check - prevent infinite loop + + // This may have been a class-specific descriptor (like HID). Skip it. + desc += endPtDesc->bLength; + + // Stay in the loop, grabbing the next descriptor + i--; + } + + } + + } + + +} + +//______________________________________________________________________________ + +CCyUSBInterface::~CCyUSBInterface(void) { + + for (int i=0; ibLength; + bDescriptorType = pConfigDescr->bDescriptorType; + wTotalLength = pConfigDescr->wTotalLength; + bNumInterfaces = pConfigDescr->bNumInterfaces; + AltInterfaces = 0; + bConfigurationValue = pConfigDescr->bConfigurationValue; + iConfiguration = pConfigDescr->iConfiguration; + bmAttributes = pConfigDescr->bmAttributes; + MaxPower = pConfigDescr->MaxPower; + + int tLen = pConfigDescr->wTotalLength; + + PUCHAR desc = (PUCHAR)pConfigDescr + pConfigDescr->bLength; + int bytesConsumed = pConfigDescr->bLength; + + for (i=0; ibDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) { + Interfaces[i] = new CCyUSBInterface(handle, interfaceDesc); + i++; + AltInterfaces++; // Actually the total number of interfaces for the config + bytesConsumed += Interfaces[i-1]->wTotalLength; + } else { + // Unexpected descriptor type + // Just skip it and go on - could have thrown an exception instead + // since this indicates that the descriptor structure is invalid. + bytesConsumed += interfaceDesc->bLength; + } + + + desc = (PUCHAR) pConfigDescr + bytesConsumed; + + } while ((bytesConsumed < tLen) && (ibAltSettings = 0; + + for (int j=0; jbInterfaceNumber == Interfaces[j]->bInterfaceNumber) + Interfaces[i]->bAltSettings++; + + } + +} + + +CCyUSBConfig::CCyUSBConfig(HANDLE handle, PUSB_CONFIGURATION_DESCRIPTOR pConfigDescr,UCHAR usb30Dummy) +{ + + PUSB_INTERFACE_DESCRIPTOR interfaceDesc; + int i; + + bLength = pConfigDescr->bLength; + bDescriptorType = pConfigDescr->bDescriptorType; + wTotalLength = pConfigDescr->wTotalLength; + bNumInterfaces = pConfigDescr->bNumInterfaces; + AltInterfaces = 0; + bConfigurationValue = pConfigDescr->bConfigurationValue; + iConfiguration = pConfigDescr->iConfiguration; + bmAttributes = pConfigDescr->bmAttributes; + MaxPower = pConfigDescr->MaxPower; + + int tLen = pConfigDescr->wTotalLength; + + PUCHAR desc = (PUCHAR)pConfigDescr + pConfigDescr->bLength; + int bytesConsumed = pConfigDescr->bLength; + + for (i=0; ibDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) { + Interfaces[i] = new CCyUSBInterface(handle, interfaceDesc,usb30Dummy); + i++; + AltInterfaces++; // Actually the total number of interfaces for the config + bytesConsumed += Interfaces[i-1]->wTotalLength; + } else { + // Unexpected descriptor type + // Just skip it and go on - could have thrown an exception instead + // since this indicates that the descriptor structure is invalid. + bytesConsumed += interfaceDesc->bLength; + } + + + desc = (PUCHAR) pConfigDescr + bytesConsumed; + + } while ((bytesConsumed < tLen) && (ibAltSettings = 0; + + for (int j=0; jbInterfaceNumber == Interfaces[j]->bInterfaceNumber) + Interfaces[i]->bAltSettings++; + + } + +} + + +//______________________________________________________________________________ + +CCyUSBConfig::~CCyUSBConfig(void){ + + for (int i=0; iEndPoints[0] != 0) + { + delete Interfaces[i]->EndPoints[0]; + + for (int j=0; jEndPoints[0] = NULL; + } + + delete Interfaces[i]; + Interfaces[i] = NULL; + } + +} + +//////////////////////////////////////////////////////////////////////////////// +// +// The CCyEndPoint ABSTRACT Class +// +//////////////////////////////////////////////////////////////////////////////// + +CCyUSBEndPoint::CCyUSBEndPoint(void) +{ + hDevice = INVALID_HANDLE_VALUE; + + DscLen = 0; + DscType = 0; + Address = 0; + Attributes = 0; + MaxPktSize = 0; + Interval = 0; + TimeOut = 10000; // 10 Sec timeout is default + bIn = false; + XferMode = XMODE_DIRECT; + LastError = 0; + // Initialize the SS companion descriptor with zero, as this constructore will be called for usb2.0 device + ssdscLen =0; + ssdscType =0; + ssmaxburst=0; /* Maximum number of packets endpoint can send in one burst*/ + ssbmAttribute=0; // store endpoint attribute like for bulk it will be number of streams + ssbytesperinterval=0; +} + +// Copy constructor +CCyUSBEndPoint::CCyUSBEndPoint(CCyUSBEndPoint& ept) +{ + hDevice = ept.hDevice; + + DscLen = ept.DscLen; + DscType = ept.DscType; + Address = ept.Address; + Attributes = ept.Attributes; + MaxPktSize = ept.MaxPktSize; + Interval = ept.Interval; + TimeOut = ept.TimeOut; + bIn = ept.bIn; + XferMode = ept.XferMode; + ssdscLen =ept.ssdscLen; + ssdscType =ept.ssdscType; + ssmaxburst=ept.ssmaxburst; /* Maximum number of packets endpoint can send in one burst*/ + ssbmAttribute=ept.ssbmAttribute; // store endpoint attribute like for bulk it will be number of streams + ssbytesperinterval=ept.ssbytesperinterval; + LastError = 0; +} + +CCyUSBEndPoint::CCyUSBEndPoint(HANDLE hDev, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor) +{ + + hDevice = hDev; + + if (pEndPtDescriptor) { + PktsPerFrame = (pEndPtDescriptor->wMaxPacketSize & 0x1800) >> 11; + PktsPerFrame++; + + DscLen = pEndPtDescriptor->bLength; + DscType = pEndPtDescriptor->bDescriptorType; + Address = pEndPtDescriptor->bEndpointAddress; + Attributes = pEndPtDescriptor->bmAttributes; + MaxPktSize = (pEndPtDescriptor->wMaxPacketSize & 0x7ff) * PktsPerFrame; + Interval = pEndPtDescriptor->bInterval; + bIn = ((Address & 0x80) == 0x80); + } + + TimeOut = 10000; // 10 Sec timeout is default + + XferMode = XMODE_DIRECT; // Normally, use Direct xfers + + // Initialize the SS companion descriptor with zero, as this constructore will be called for usb2.0 device + ssdscLen =0; + ssdscType =0; + ssmaxburst=0; /* Maximum number of packets endpoint can send in one burst*/ + ssbmAttribute=0; // store endpoint attribute like for bulk it will be number of streams + ssbytesperinterval=0; + +} + + +CCyUSBEndPoint::CCyUSBEndPoint(HANDLE hDev, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor,USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR* SSEndPtDescriptor) +{ + + hDevice = hDev; + + if (pEndPtDescriptor) { + PktsPerFrame = (pEndPtDescriptor->wMaxPacketSize & 0x1800) >> 11; + PktsPerFrame++; + + DscLen = pEndPtDescriptor->bLength; + DscType = pEndPtDescriptor->bDescriptorType; + Address = pEndPtDescriptor->bEndpointAddress; + Attributes = pEndPtDescriptor->bmAttributes; + MaxPktSize = (pEndPtDescriptor->wMaxPacketSize & 0x7ff) * PktsPerFrame; + Interval = pEndPtDescriptor->bInterval; + bIn = ((Address & 0x80) == 0x80); + } + + TimeOut = 10000; // 10 Sec timeout is default + + XferMode = XMODE_DIRECT; // Normally, use Direct xfers + + if(SSEndPtDescriptor != NULL) + { + ssdscLen =SSEndPtDescriptor->bLength; + ssdscType =SSEndPtDescriptor->bDescriptorType; + ssmaxburst=SSEndPtDescriptor->bMaxBurst; /* Maximum number of packets endpoint can send in one burst*/ + MaxPktSize *=(ssmaxburst+1); + ssbmAttribute=SSEndPtDescriptor->bmAttributes; // store endpoint attribute like for bulk it will be number of streams + if((Attributes & 0x03) ==1) // MULT is valid for Isochronous transfer only + MaxPktSize*=((SSEndPtDescriptor->bmAttributes & 0x03)+1); // Adding the MULT fields. + + ssbytesperinterval=SSEndPtDescriptor->bBytesPerInterval; + + } + else + { + // Initialize the SS companion descriptor with zero + ssdscLen =0; + ssdscType =0; + ssmaxburst=0; /* Maximum number of packets endpoint can send in one burst*/ + ssbmAttribute=0; // store endpoint attribute like for bulk it will be number of streams + ssbytesperinterval=0; + } + +} + + +//______________________________________________________________________________ + +bool CCyUSBEndPoint::Reset(void) +{ + DWORD dwBytes = 0; + bool RetVal = false; + + RetVal = (DeviceIoControl(hDevice, + IOCTL_ADAPT_RESET_PIPE, + &Address, + sizeof(UCHAR), + NULL, + 0, + &dwBytes, + 0) !=0); + + if(!RetVal) LastError = GetLastError(); + return RetVal; +} + +//______________________________________________________________________________ + +bool CCyUSBEndPoint::Abort(void) +{ + DWORD dwBytes = 0; + bool RetVal = false; + OVERLAPPED ov; + + memset(&ov,0,sizeof(ov)); + ov.hEvent = CreateEvent(NULL,false,false,NULL); + + RetVal = (DeviceIoControl(hDevice, + IOCTL_ADAPT_ABORT_PIPE, + &Address, + sizeof(UCHAR), + NULL, + 0, + &dwBytes, + &ov)!=0); + if(!RetVal) + { + DWORD LastError = GetLastError(); + if(LastError == ERROR_IO_PENDING) + WaitForSingleObject(ov.hEvent,1000); + } + CloseHandle(ov.hEvent); + return true; + +} +//______________________________________________________________________________ + +bool CCyUSBEndPoint::XferData(PUCHAR buf, LONG &bufLen, CCyIsoPktInfo* pktInfos) +{ + + OVERLAPPED ovLapStatus; + memset(&ovLapStatus,0,sizeof(OVERLAPPED)); + + ovLapStatus.hEvent = CreateEvent(NULL, false, false, NULL); + + PUCHAR context = BeginDataXfer(buf, bufLen, &ovLapStatus); + bool wResult = WaitForIO(&ovLapStatus); + bool fResult = FinishDataXfer(buf, bufLen, &ovLapStatus, context, pktInfos); + + CloseHandle(ovLapStatus.hEvent); + + return wResult && fResult; +} + +//______________________________________________________________________________ + +bool CCyUSBEndPoint::XferData(PUCHAR buf, LONG &bufLen, CCyIsoPktInfo* pktInfos, bool pktMode) +{ + if ((bIn == false) || (pktMode == false)) + { + return XferData(buf, bufLen); + } + else + { + int size = 0; + LONG xferLen = (LONG)MaxPktSize; + bool status = true; + PUCHAR ptr = buf; + + while (status && (size < bufLen)) + { + if ((bufLen - size) < MaxPktSize) + xferLen = bufLen - size; + + status = XferData(ptr, xferLen); + if (status) + { + ptr += xferLen; + size += xferLen; + + if (xferLen < MaxPktSize) + break; + } + } + + bufLen = size; + if (bufLen > 0) + return true; + return status; + } +} + +//______________________________________________________________________________ + +bool CCyUSBEndPoint::FinishDataXfer(PUCHAR buf, LONG &bufLen, OVERLAPPED *ov, PUCHAR pXmitBuf, CCyIsoPktInfo* pktInfos) +{ + DWORD bytes = 0; + bool rResult = (GetOverlappedResult(hDevice, ov, &bytes, FALSE)!=0); + + PSINGLE_TRANSFER pTransfer = (PSINGLE_TRANSFER) pXmitBuf; + bufLen = (bytes) ? bytes - pTransfer->BufferOffset : 0; + bytesWritten = bufLen; + + UsbdStatus = pTransfer->UsbdStatus; + NtStatus = pTransfer->NtStatus; + + if (bIn && (XferMode == XMODE_BUFFERED) && (bufLen > 0)) { + UCHAR *ptr = (PUCHAR)pTransfer + pTransfer->BufferOffset; + memcpy (buf, ptr, bufLen); + } + + // If a buffer was provided, pass-back the Isoc packet info records + if (pktInfos && (bufLen > 0)) { + ZeroMemory(pktInfos, pTransfer->IsoPacketLength); + PUCHAR pktPtr = pXmitBuf + pTransfer->IsoPacketOffset; + memcpy(pktInfos, pktPtr, pTransfer->IsoPacketLength); + } + + delete[] pXmitBuf; // [] Changed in 1.5.1.3 + + return rResult && (UsbdStatus == 0) && (NtStatus == 0); +} + +//______________________________________________________________________________ + +PUCHAR CCyUSBEndPoint::BeginBufferedXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov) +{ + if ( hDevice == INVALID_HANDLE_VALUE ) return NULL; + + int iXmitBufSize = sizeof (SINGLE_TRANSFER) + bufLen; + PUCHAR pXmitBuf = new UCHAR[iXmitBufSize]; + ZeroMemory (pXmitBuf, iXmitBufSize); + + PSINGLE_TRANSFER pTransfer = (PSINGLE_TRANSFER) pXmitBuf; + pTransfer->ucEndpointAddress = Address; + pTransfer->IsoPacketLength = 0; + pTransfer->BufferOffset = sizeof (SINGLE_TRANSFER); + pTransfer->BufferLength = bufLen; + + // Copy buf into pXmitBuf + UCHAR *ptr = (PUCHAR) pTransfer + pTransfer->BufferOffset; + memcpy (ptr, buf, bufLen); + + DWORD dwReturnBytes; + + DeviceIoControl (hDevice, + IOCTL_ADAPT_SEND_NON_EP0_TRANSFER, + pXmitBuf, + iXmitBufSize, + pXmitBuf, + iXmitBufSize, + &dwReturnBytes, + ov); + + UsbdStatus = pTransfer->UsbdStatus; + NtStatus = pTransfer->NtStatus; + + LastError = GetLastError(); + return pXmitBuf; +} + + + +//______________________________________________________________________________ +PUCHAR CCyUSBEndPoint::BeginDirectXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov) +{ + if ( hDevice == INVALID_HANDLE_VALUE ) return NULL; + + int iXmitBufSize = sizeof (SINGLE_TRANSFER); + PUCHAR pXmitBuf = new UCHAR[iXmitBufSize]; + ZeroMemory (pXmitBuf, iXmitBufSize); + + PSINGLE_TRANSFER pTransfer = (PSINGLE_TRANSFER) pXmitBuf; + pTransfer->ucEndpointAddress = Address; + pTransfer->IsoPacketLength = 0; + pTransfer->BufferOffset = 0; + pTransfer->BufferLength = 0; + + DWORD dwReturnBytes; + DeviceIoControl (hDevice, + IOCTL_ADAPT_SEND_NON_EP0_DIRECT, + pXmitBuf, + iXmitBufSize, + buf, + bufLen, + &dwReturnBytes, + ov); + + UsbdStatus = pTransfer->UsbdStatus; + NtStatus = pTransfer->NtStatus; + + LastError = GetLastError(); + return pXmitBuf; +} + + + +//______________________________________________________________________________ +// Unlike WaitForIO, this method does not record the bytes written or reset the +// endpoint if errors occurred. This method is called from the application level +// in conjunction with BeginDataXfer and FinishDataXfer + +bool CCyUSBEndPoint::WaitForXfer(OVERLAPPED *ov, ULONG tOut) +{ + + //if (LastError == ERROR_SUCCESS) return true; // The command completed + + //if (LastError == ERROR_IO_PENDING) + { + DWORD waitResult = WaitForSingleObject(ov->hEvent,tOut); + + if (waitResult == WAIT_TIMEOUT) return false; + + if (waitResult == WAIT_OBJECT_0) return true; + } + + return false; +} + +//______________________________________________________________________________ + +bool CCyUSBEndPoint::WaitForIO(OVERLAPPED *ovLapStatus) +{ + LastError = GetLastError(); + DWORD retcode =1; + + if (LastError == ERROR_SUCCESS) return true; // The command completed + + if (LastError == ERROR_IO_PENDING) { + DWORD waitResult = WaitForSingleObject(ovLapStatus->hEvent,TimeOut); + + if (waitResult == WAIT_OBJECT_0) return true; + + if (waitResult == WAIT_TIMEOUT) + { + Abort(); + //// Wait for the stalled command to complete - should be done already + //retcode = WaitForSingleObject(ovLapStatus->hEvent,50); // Wait for 50 milisecond + Sleep(50); + + //if(retcode == WAIT_TIMEOUT || retcode==WAIT_FAILED) + //{// Worst case condition , in multithreaded environment if user set time out to ZERO and cancel the IO the requiest, rarely first Abort() fail to cancel the IO, so reissueing second Abort(0. + //Abort(); + //retcode = WaitForSingleObject(ovLapStatus->hEvent,INFINITE); + + //} + } + } + + return (retcode==0) ? true:false; +} + +//______________________________________________________________________________ + +ULONG CCyUSBEndPoint::GetXferSize(void){ + + ULONG ulTransferSize; + DWORD BytesXfered; + + if (hDevice == INVALID_HANDLE_VALUE) return (ULONG) NULL; + + SET_TRANSFER_SIZE_INFO SetTransferInfo; + + ulTransferSize = 0; + SetTransferInfo.EndpointAddress = Address; + SetTransferInfo.TransferSize = ulTransferSize; + + BOOL bRetVal = DeviceIoControl(hDevice, + IOCTL_ADAPT_GET_TRANSFER_SIZE, + &SetTransferInfo, sizeof(SET_TRANSFER_SIZE_INFO), + &SetTransferInfo, sizeof(SET_TRANSFER_SIZE_INFO), + &BytesXfered, + NULL); + + if (bRetVal && BytesXfered >= sizeof(SET_TRANSFER_SIZE_INFO)) + ulTransferSize = SetTransferInfo.TransferSize; + else + LastError = GetLastError(); + + return ulTransferSize; +} + +//______________________________________________________________________________ + +void CCyUSBEndPoint::SetXferSize(ULONG xfer){ + + if (hDevice == INVALID_HANDLE_VALUE) return; + + DWORD BytesXfered; + SET_TRANSFER_SIZE_INFO SetTransferInfo; + + if(MaxPktSize==0) + return; + // Force a multiple of MaxPktSize + ULONG pkts = (xfer % MaxPktSize) ? 1+(xfer / MaxPktSize) : (xfer / MaxPktSize); + ULONG xferSize = pkts * MaxPktSize; + + SetTransferInfo.EndpointAddress = Address; + SetTransferInfo.TransferSize = xferSize; + + if(DeviceIoControl(hDevice, + IOCTL_ADAPT_SET_TRANSFER_SIZE, + &SetTransferInfo, sizeof(SET_TRANSFER_SIZE_INFO), + &SetTransferInfo, sizeof(SET_TRANSFER_SIZE_INFO), + &BytesXfered, + NULL)==false) + { + LastError = GetLastError(); + } + +} + + + +//////////////////////////////////////////////////////////////////////////////// +// +// The CCyControlEndPoint Class +// +//////////////////////////////////////////////////////////////////////////////// + +CCyControlEndPoint::CCyControlEndPoint(void):CCyUSBEndPoint() +{ + + Target = TGT_DEVICE; + ReqType = REQ_VENDOR; + Direction = DIR_TO_DEVICE; + + ReqCode = 0; + Value = 0; + Index = 0; + + XferMode = XMODE_BUFFERED; + +} + +// Copy Constructor +CCyControlEndPoint::CCyControlEndPoint(CCyControlEndPoint& ept):CCyUSBEndPoint(ept) +{ + + Target = ept.Target; + ReqType = ept.ReqType; + Direction = ept.Direction; + + ReqCode = ept.ReqCode; + Value = ept.Value; + Index = ept.Index; + + XferMode = ept.XferMode; +} + + +CCyControlEndPoint::CCyControlEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor) : +CCyUSBEndPoint(h, pEndPtDescriptor) +{ + Target = TGT_DEVICE; + ReqType = REQ_VENDOR; + Direction = DIR_TO_DEVICE; + + ReqCode = 0; + Value = 0; + Index = 0; + + XferMode = XMODE_BUFFERED; + +} + +//______________________________________________________________________________ + +bool CCyControlEndPoint::Read(PUCHAR buf, LONG &bufLen) +{ + Direction = DIR_FROM_DEVICE; + return XferData(buf, bufLen); +} + + +//______________________________________________________________________________ + +bool CCyControlEndPoint::Write(PUCHAR buf, LONG &bufLen) +{ + Direction = DIR_TO_DEVICE; + return XferData(buf, bufLen); +} + + +//______________________________________________________________________________ + +PUCHAR CCyControlEndPoint::BeginDataXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov) +{ + union { + struct { + UCHAR Recipient:5; + UCHAR Type:2; + UCHAR Direction:1; + } bmRequest; + + UCHAR bmReq; + }; + + if ( hDevice == INVALID_HANDLE_VALUE ) return NULL; + + bmRequest.Recipient = Target; + bmRequest.Type = ReqType; + bmRequest.Direction = Direction; + + bIn = (Direction == DIR_FROM_DEVICE); + + int iXmitBufSize = sizeof (SINGLE_TRANSFER) + bufLen; + UCHAR *pXmitBuf = new UCHAR[iXmitBufSize]; + ZeroMemory (pXmitBuf, iXmitBufSize); + + // The Control Endpoint has a 1 sec resolution on its timeout + // But, TimeOut is in milliseconds. + ULONG tmo = ((TimeOut > 0) && (TimeOut < 1000)) ? 1 : TimeOut / 1000; + + PSINGLE_TRANSFER pTransfer = (PSINGLE_TRANSFER) pXmitBuf; + pTransfer->SetupPacket.bmRequest = bmReq; + pTransfer->SetupPacket.bRequest = ReqCode; + pTransfer->SetupPacket.wValue = Value; + pTransfer->SetupPacket.wIndex = Index; + pTransfer->SetupPacket.wLength = (USHORT)bufLen; + pTransfer->SetupPacket.ulTimeOut = tmo; // Seconds, not milliseconds + pTransfer->ucEndpointAddress = 0x00; // control pipe + pTransfer->IsoPacketLength = 0; + pTransfer->BufferOffset = sizeof (SINGLE_TRANSFER); + pTransfer->BufferLength = bufLen; + + // Copy buf into pXmitBuf + UCHAR *ptr = pXmitBuf + sizeof (SINGLE_TRANSFER); + memcpy (ptr, buf, bufLen); + + DWORD dwReturnBytes; + DeviceIoControl (hDevice, + IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, + pXmitBuf, + iXmitBufSize, + pXmitBuf, + iXmitBufSize, + &dwReturnBytes, + ov); + + // Note that this method leaves pXmitBuf allocated. It will get deleted in + // FinishDataXfer. + + LastError = GetLastError(); + return pXmitBuf; + +} + +//////////////////////////////////////////////////////////////////////////////// +// +// The CCyIsocEndPoint Class +// +//////////////////////////////////////////////////////////////////////////////// + +CCyIsocEndPoint::CCyIsocEndPoint(void) : CCyUSBEndPoint() +{ +} + +CCyIsocEndPoint::CCyIsocEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor) : +CCyUSBEndPoint(h, pEndPtDescriptor) +{ +} +CCyIsocEndPoint::CCyIsocEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor,USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR* SSEndPtDescriptor) : +CCyUSBEndPoint(h, pEndPtDescriptor,SSEndPtDescriptor) +{ +} + +//______________________________________________________________________________ + +PUCHAR CCyIsocEndPoint::BeginDataXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov) +{ + if ( hDevice == INVALID_HANDLE_VALUE ) return NULL; + + if (XferMode == XMODE_DIRECT) + return BeginDirectXfer(buf, bufLen, ov); + else + return BeginBufferedXfer(buf, bufLen, ov); + +} + +//______________________________________________________________________________ + +PUCHAR CCyIsocEndPoint::BeginBufferedXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov) +{ + if ( hDevice == INVALID_HANDLE_VALUE ) return NULL; + + int pkts; + if(MaxPktSize) + pkts = bufLen / MaxPktSize; // Number of packets implied by bufLen & pktSize + else + { + pkts = 0; + return NULL; + } + + if (bufLen % MaxPktSize) pkts++; + + if (pkts == 0) return NULL; + + int iXmitBufSize = sizeof (SINGLE_TRANSFER) + (pkts * sizeof(ISO_PACKET_INFO)) + bufLen; + UCHAR *pXmitBuf = new UCHAR[iXmitBufSize]; + ZeroMemory (pXmitBuf, iXmitBufSize); + + PSINGLE_TRANSFER pTransfer = (PSINGLE_TRANSFER) pXmitBuf; + pTransfer->ucEndpointAddress = Address; + pTransfer->IsoPacketOffset = sizeof (SINGLE_TRANSFER); + pTransfer->IsoPacketLength = pkts * sizeof(ISO_PACKET_INFO); + pTransfer->BufferOffset = sizeof (SINGLE_TRANSFER) + pTransfer->IsoPacketLength; + pTransfer->BufferLength = bufLen; + + // Copy buf into pXmitBuf + UCHAR *ptr = pXmitBuf + pTransfer->BufferOffset; + memcpy (ptr, buf, bufLen); + + DWORD dwReturnBytes = 0; + + DeviceIoControl (hDevice, + IOCTL_ADAPT_SEND_NON_EP0_TRANSFER, + pXmitBuf, + iXmitBufSize, + pXmitBuf, + iXmitBufSize, + &dwReturnBytes, + ov); + + // Note that this method leaves pXmitBuf allocated. It will get deleted in + // FinishDataXfer. + + UsbdStatus = pTransfer->UsbdStatus; + NtStatus = pTransfer->NtStatus; + + LastError = GetLastError(); + return pXmitBuf; +} + +//______________________________________________________________________________ + +PUCHAR CCyIsocEndPoint::BeginDirectXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov) +{ + if ( hDevice == INVALID_HANDLE_VALUE ) return NULL; + + int pkts; + if(MaxPktSize) + pkts = bufLen / MaxPktSize; // Number of packets implied by bufLen & pktSize + else + { + pkts = 0; + return NULL; + } + + if (bufLen % MaxPktSize) pkts++; + + if (pkts == 0) return NULL; + + int iXmitBufSize = sizeof (SINGLE_TRANSFER) + (pkts * sizeof(ISO_PACKET_INFO)); + UCHAR *pXmitBuf = new UCHAR[iXmitBufSize]; + ZeroMemory (pXmitBuf, iXmitBufSize); + + PSINGLE_TRANSFER pTransfer = (PSINGLE_TRANSFER) pXmitBuf; + pTransfer->ucEndpointAddress = Address; + pTransfer->IsoPacketOffset = sizeof (SINGLE_TRANSFER); + pTransfer->IsoPacketLength = pkts * sizeof(ISO_PACKET_INFO); + pTransfer->BufferOffset = 0; + pTransfer->BufferLength = 0; + + DWORD dwReturnBytes = 0; + DeviceIoControl (hDevice, + IOCTL_ADAPT_SEND_NON_EP0_DIRECT, + pXmitBuf, + iXmitBufSize, + buf, + bufLen, + &dwReturnBytes, + ov); + + // Note that this method leaves pXmitBuf allocated. It will get deleted in + // FinishDataXfer. + + UsbdStatus = pTransfer->UsbdStatus; + NtStatus = pTransfer->NtStatus; + + LastError = GetLastError(); + return pXmitBuf; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// The CCyFX3Device Class +// +//////////////////////////////////////////////////////////////////////////////// +CCyFX3Device::CCyFX3Device() +{ +} +CCyFX3Device::~CCyFX3Device() +{ +} +bool CCyFX3Device::Ep0VendorCommand(vendorCmdData cmdData) +{ + ControlEndPt->Target = TGT_DEVICE ; + ControlEndPt->ReqType = REQ_VENDOR ; + ControlEndPt->ReqCode = cmdData.opCode ; + ControlEndPt->Direction = (cmdData.isRead) ? DIR_FROM_DEVICE : DIR_TO_DEVICE ; + + ControlEndPt->Value = (cmdData.addr & 0xFFFF); + ControlEndPt->Index = ((cmdData.addr >> 16) & 0xFFFF); + + int maxpkt = ControlEndPt->MaxPktSize; + + long len = cmdData.size; + + /* Handle the case where transfer length is 0 (used to send the Program Entry) */ + if (cmdData.size == 0) + return ControlEndPt->XferData(cmdData.buf, len, NULL); + else + { + bool bRetCode = false; + long Stagelen = 0; + int BufIndex = 0; + while (len > 0) + { + if (len >= 65535) + Stagelen = 65535; + else + Stagelen = (len) % 65535; + + /* Allocate the buffer */ + PUCHAR StageBuf = new UCHAR[Stagelen]; + + if (!cmdData.isRead) + { + /*write operation */ + for (int i = 0; i < Stagelen; i++) + StageBuf[i] = cmdData.buf[BufIndex + i]; + } + + bRetCode = ControlEndPt->XferData(StageBuf, Stagelen, NULL); + if (!bRetCode) + { + if(StageBuf) + delete[] StageBuf; + + return false; + } + + if (cmdData.isRead) + { + /*read operation */ + for (int i = 0; i < Stagelen; i++) + cmdData.buf[BufIndex + i] = StageBuf[i]; + } + + if(StageBuf) + delete[] StageBuf; + + len -= Stagelen; + BufIndex += Stagelen; + } + + } + + return true; +} + +//______________________________________________________________________________ + +/* Function to transmit data on the control endpoint. */ +bool CCyFX3Device::DownloadBufferToDevice(UINT start_addr, USHORT count, UCHAR *data_buf, UCHAR opCode) +{ + vendorCmdData cmdData; + cmdData.addr = start_addr; + + cmdData.isRead = 0; + cmdData.buf = data_buf; + cmdData.opCode = opCode; + cmdData.size = count; + + return Ep0VendorCommand(cmdData); +} + +//______________________________________________________________________________ + +/* Function to read data using control endpoint. */ +bool CCyFX3Device::UploadBufferFromDevice(UINT start_addr, USHORT count, UCHAR *data_buf, UCHAR opCode) +{ + vendorCmdData cmdData; + cmdData.addr = start_addr; + + cmdData.isRead = 1; + cmdData.buf = data_buf; + cmdData.opCode = opCode; + cmdData.size = count; + + return Ep0VendorCommand(cmdData); +} + +//______________________________________________________________________________ + +/* This function sends out the 0xA0 vendor request for transferring the control to +program entry point. +*/ +bool CCyFX3Device::SetProgramEntry (UCHAR opCode,UINT start_addr) +{ + vendorCmdData cmdData; + cmdData.addr = ((start_addr >> 16) | (start_addr << 16)); /* swap LSB and MSB */ + + cmdData.isRead = 0; + cmdData.buf = NULL; + cmdData.opCode = opCode; + cmdData.size = 0; + + return Ep0VendorCommand(cmdData); +} + +//______________________________________________________________________________ + +bool CCyFX3Device::IsBootLoaderRunning() +{ + /*Dire : in, Target : Device, ReqCode:0xA0,wValue:0x0000,wIndex:0x0000 */ + /* This function checks for bootloader,it will return false if it is not running. */ + UCHAR buf[1]; + long len = 1; + bool ret; + UCHAR opCode = 0xA0; // Vendore command + + vendorCmdData cmdData; + + cmdData.addr = 0x0000; + + cmdData.isRead = true; + cmdData.buf = buf; + cmdData.opCode = opCode; + cmdData.size = len; + + /* Value = isErase, index = sector number */ + ret = Ep0VendorCommand(cmdData); + return ret; +} + +//______________________________________________________________________________ + +FX3_FWDWNLOAD_ERROR_CODE CCyFX3Device::EraseSectorOfSPIFlash(UINT SectorNumber, UCHAR opCode) +{ + vendorCmdData cmdData; + bool ret; + UCHAR buf[1]; + UINT buflen = 0; + buf[0] = 1; + + cmdData.addr = (1 + (SectorNumber << 16)); + + cmdData.isRead = false; + cmdData.buf = buf; + cmdData.opCode = opCode; + cmdData.size = buflen; + + /* Value = isErase, index = sector number */ + ret = Ep0VendorCommand(cmdData); + if (ret) + { + /* Check the status of erase. Value should be 0 */ + buflen = 1; + cmdData.size = buflen; + while (buf[0] != 0) + { + cmdData.isRead = true; + cmdData.addr = (0 + (SectorNumber << 16)); + if (!Ep0VendorCommand(cmdData)) + return FAILED; + } + } + else + return FAILED; + + return SUCCESS; +} + +//______________________________________________________________________________ + +bool CCyFX3Device::WriteToSPIFlash(PUCHAR Buf, UINT buflen, UINT ByteAddress, UCHAR opCode) +{ + vendorCmdData cmdData; + cmdData.addr = ((ByteAddress / SPI_FLASH_PAGE_SIZE_IN_BYTE) << 16); // swap LSB and MSB + + cmdData.isRead = 0; + cmdData.buf = Buf; + cmdData.opCode = opCode; + cmdData.size = buflen; + + return Ep0VendorCommand(cmdData); +} + +//______________________________________________________________________________ + +FX3_FWDWNLOAD_ERROR_CODE CCyFX3Device::DownloadUserIMGtoSPIFLASH(PUCHAR buffer_p, UINT fw_size, UCHAR opCode) +{ + /* The size of the image needs to be rounded to a multiple of the SPI page size. */ + UINT ImageSizeInPage = (fw_size + SPI_FLASH_PAGE_SIZE_IN_BYTE - 1) / SPI_FLASH_PAGE_SIZE_IN_BYTE; + UINT TotalNumOfByteToWrote = ImageSizeInPage * SPI_FLASH_PAGE_SIZE_IN_BYTE; + /* Sectors needs to be erased in case of SPI. Sector size = 64k. Page Size = 256 bytes. 1 Sector = 256 pages. */ + /* Calculate the number of sectors needed to write firmware image and erase them. */ + UINT NumOfSector = fw_size / SPI_FLASH_SECTOR_SIZE_IN_BYTE; + if ((fw_size % SPI_FLASH_SECTOR_SIZE_IN_BYTE) != 0) + NumOfSector++; + + /* Erase the sectors */ + for (UINT i = 0; i < NumOfSector; i++) + { + if (EraseSectorOfSPIFlash(i, opCode) != SUCCESS) + return SPILASH_ERASE_FAILED; + } + + /*Write the firmware to the SPI flash */ + UINT numberOfBytesLeftToWrite = TotalNumOfByteToWrote; /* Current number of bytes left to write */ + + UINT FwFilePointer = 0; + UINT massStorageByteAddress = 0; /* Current Mass Storage Byte Address */ + + PUCHAR WriteBuf = new UCHAR[CYWB_BL_MAX_BUFFER_SIZE_WHEN_USING_EP0_TRANSPORT]; + + while (numberOfBytesLeftToWrite > 0) + { + UINT numberOfBytesToWrite = CYWB_BL_MAX_BUFFER_SIZE_WHEN_USING_EP0_TRANSPORT; + + if (numberOfBytesLeftToWrite < CYWB_BL_MAX_BUFFER_SIZE_WHEN_USING_EP0_TRANSPORT) + { + numberOfBytesToWrite = numberOfBytesLeftToWrite; + } + + /* Trigger a mass storage write... */ + for (UINT i = 0; i < numberOfBytesToWrite; i++) + { + if ((FwFilePointer + i) < fw_size) + WriteBuf[i] = buffer_p[i + FwFilePointer]; + } + opCode = 0xC2; // Operation code to Write to SPI + if (WriteToSPIFlash(WriteBuf, numberOfBytesToWrite, massStorageByteAddress, opCode) == false) + { + if(WriteBuf) + delete[] WriteBuf; + + return FAILED; + } + + /* Adjust pointers */ + numberOfBytesLeftToWrite -= numberOfBytesToWrite; + FwFilePointer += numberOfBytesToWrite; + massStorageByteAddress += numberOfBytesToWrite; + } + + if(WriteBuf) + delete[] WriteBuf; + + return SUCCESS; +} + +//______________________________________________________________________________ + +FX3_FWDWNLOAD_ERROR_CODE CCyFX3Device::DownloadUserIMGtoI2CE2PROM(PUCHAR buffer_p, UINT fw_size, UCHAR opCode) +{ + int STAGE_SIZE = BUFSIZE_UPORT; + PUCHAR downloadbuf = new UCHAR[STAGE_SIZE]; + + int NoOfStage = ((int)fw_size / STAGE_SIZE); + long LastStage = ((int)fw_size % STAGE_SIZE); + UINT DownloadAddress = 0; + long FwImagePtr = 0; + long StageSize = STAGE_SIZE; + + //Get the I2C addressing size + UCHAR ImgI2CSizeByte = buffer_p[2]; // the 2nd byte of the IMG file will tell us the I2EPROM internal addressing. + UINT AddresingStageSize = 0; + ImgI2CSizeByte = ((ImgI2CSizeByte >> 1) & 0x07); // Bit3:1 represent the addressing + bool IsMicroShipE2Prom = false; + + switch (ImgI2CSizeByte) + { + case 0: + case 1: + return I2CE2PROM_UNKNOWN_I2C_SIZE; + case 2: + AddresingStageSize = (4 * 1024); // 4KByte + break; + case 3: + AddresingStageSize = (8 * 1024); // 8KByte + break; + case 4: + AddresingStageSize = (16 * 1024); // 16KByte + break; + case 5: + AddresingStageSize = (32 * 1024); // 32KByte + break; + case 6: + AddresingStageSize = (64 * 1024); // 64KByte + break; + case 7: + IsMicroShipE2Prom = true; // 128KByte Addressing for Microchip. + AddresingStageSize = (64 * 1024); // 64KByte // case 7 represent 128Kbyte but it follow 64Kbyte addressing + break; + default: + { + if(downloadbuf) + delete[] downloadbuf; + + return I2CE2PROM_UNKNOWN_I2C_SIZE; + } + } + + + ControlEndPt->Target = TGT_DEVICE ; + ControlEndPt->ReqType = REQ_VENDOR ; + ControlEndPt->ReqCode = opCode ; + ControlEndPt->Direction = DIR_TO_DEVICE ; + + ControlEndPt->Value = (DownloadAddress & 0xFFFF); + ControlEndPt->Index = ((DownloadAddress >> 16) & 0xFFFF); + int maxpkt = ControlEndPt->MaxPktSize; + + for (int i = 0; i < NoOfStage; i++) + { + /* Copy data from main buffer to tmp buffer */ + for (long j = 0; j < STAGE_SIZE; j++) + downloadbuf[j] = buffer_p[FwImagePtr + j]; + + if (!ControlEndPt->XferData(downloadbuf, StageSize, NULL)) + { + if(downloadbuf) + delete[] downloadbuf; + + return FAILED; + } + + FwImagePtr += STAGE_SIZE; + ControlEndPt->Index += (WORD)StageSize; + + ///// + // Address calculation done in the below box + if (IsMicroShipE2Prom) + {//Microchip Addressing(0-(1-64),4(64 to 128),1(128 to 192 ),5(192 to 256)) + if (FwImagePtr >= (128 * 1024)) + { + if ((FwImagePtr % AddresingStageSize) == 0) + { + if (ControlEndPt->Value == 0x04) + ControlEndPt->Value = 0x01; + else + ControlEndPt->Value = 0x05; + + ControlEndPt->Index = 0; + } + } + else if ((FwImagePtr % AddresingStageSize) == 0) + { + ControlEndPt->Value = 0x04; + ControlEndPt->Index = 0; + } + } + else + {//ATMEL addressing sequential + if ((FwImagePtr % AddresingStageSize)==0) + {// Increament the Value field to represent the address and reset the Index value to zero. + ControlEndPt->Value += 0x01; + if(ControlEndPt->Value>=8) + ControlEndPt->Value = 0x0; //reset the Address to ZERO + + ControlEndPt->Index = 0; + } + } + ///// + + + } + + if (LastStage != 0) + { + /*check for last stage */ + + for (long j = 0; j < LastStage; j++) + downloadbuf[j] = buffer_p[FwImagePtr + j]; + + if ((LastStage % maxpkt) != 0) + { + /* make it multiple of max packet size */ + int diff = (maxpkt - (LastStage % maxpkt)); + for (int j = LastStage; j < (LastStage + diff); j++) + downloadbuf[j] = 0; + + LastStage += diff; + } + + if (!ControlEndPt->XferData(downloadbuf, LastStage, NULL)) + { + if(downloadbuf) + delete[] downloadbuf; + + return FAILED; + } + + /*Failure Case: + The device does not return failure message when file size is more than 128KByte and only one 128Byte E2PROM on the DVK. + Solution: + Read back the last stage data to confirm that all data transferred successfully.*/ + ControlEndPt->ReqCode = 0xBB; + ControlEndPt->Direction = DIR_FROM_DEVICE; + if (!ControlEndPt->XferData(downloadbuf, LastStage, NULL)) + { + if(downloadbuf) + delete[] downloadbuf; + + return FAILED; + } + } + + if(downloadbuf) + delete[] downloadbuf; + + return SUCCESS; +} + +//______________________________________________________________________________ + +FX3_FWDWNLOAD_ERROR_CODE CCyFX3Device::DownloadFwToRam(PUCHAR buffer_p, UINT fw_size, UCHAR opCode) +{ + UCHAR downloadBuffer[BUFSIZE_UPORT]; + UCHAR uploadbuffer[BUFSIZE_UPORT]; + bool isTrue = true; + UINT ComputeCheckSum = 0; + UINT ExpectedCheckSum = 0; + INT fwImagePtr = 0; + UINT SectionLength = 0; + UINT SectionAddress; + UINT DownloadAddress; + UINT ProgramEntry; + + /* Initialize computed checksum */ + ComputeCheckSum = 0; + + /* Check "CY" signature (0x43,0x59) and download the firmware image */ + if ((buffer_p[fwImagePtr] != 0x43) || (buffer_p[fwImagePtr + 1] != 0x59)) + { /*signature doesn't match */ + return INVALID_FWSIGNATURE; + } + + /* Skip the two bytes signature and the following two bytes */ + fwImagePtr += 4; + + /* Download one section at a time to the device, compute checksum, and upload-verify it */ + while (isTrue) + { + /* Get section length (4 bytes) and convert it from 32-bit word count to byte count */ + CYWB_BL_4_BYTES_COPY(&SectionLength, &buffer_p[fwImagePtr]); + fwImagePtr += 4; + + SectionLength = SectionLength << 2; + + /* If length = 0, the transfer is complete */ + if (SectionLength == 0) break; + + /* Get section address (4 bytes) */ + CYWB_BL_4_BYTES_COPY(&SectionAddress, &buffer_p[fwImagePtr]); + fwImagePtr += 4; + + /* Download BUFSIZE_UPORT maximum bytes at a time */ + INT bytesLeftToDownload = SectionLength; + DownloadAddress = SectionAddress; + + while (bytesLeftToDownload > 0) + { + INT bytesToTransfer = BUFSIZE_UPORT; + if (bytesLeftToDownload < BUFSIZE_UPORT) + bytesToTransfer = bytesLeftToDownload; + + /* sanity check for incomplete fw with valid signatures. + Note: bytesToTransfer should never be greater then fw length i.e buflen */ + if (bytesToTransfer > (INT)fw_size) + return CORRUPT_FIRMWARE_IMAGE_FILE; + + memcpy(downloadBuffer, (void *)(buffer_p + fwImagePtr), bytesToTransfer); + + /* Compute checksum: Here transferLength is assumed to be a multiple of 4. If it is not, the checksum will fail anyway */ + for (INT index = 0; index < bytesToTransfer; index += 4) + { + UINT buf32bits = 0; + CYWB_BL_4_BYTES_COPY(&buf32bits, &downloadBuffer[index]); + ComputeCheckSum += buf32bits; + } + + /*The FPGA does not seem to always be reliable: if an error is encountered, try again twice */ + INT maxTryCount = 3; + for (INT tryCount = 1; tryCount <= maxTryCount; tryCount++) + { + /* Download one buffer worth of data to the device */ + if (!DownloadBufferToDevice(DownloadAddress, bytesToTransfer, downloadBuffer, opCode)) + { + /* Check if we exceeded the max try count */ + if (tryCount == maxTryCount) + { + /* Failure while downloading firmware to the device. Abort */ + return FAILED; + } + else + { + /* F/W buffer download failure. Trying writing/verifying current buffer again... */ + continue; + } + } + + memset (uploadbuffer, 0, bytesToTransfer); + + if (!UploadBufferFromDevice(DownloadAddress, bytesToTransfer, uploadbuffer, opCode)) + { + /* Check if we exceeded the max try count */ + if (tryCount == maxTryCount) + { + /* Failure while uploading firmware from the device for verification. Abort */ + return FAILED; + } + else + { + /* F/W buffer upload failure. Trying writing/verifying current buffer again... */ + continue; + } + } + + for (int count = 0; count < bytesToTransfer; count++) + { + if (downloadBuffer[count] != uploadbuffer[count]) + { + /* Check if we exceeded the max try count */ + if (tryCount == maxTryCount) + { + /* Uploaded firmware data does not match downloaded data. Abort */ + return FAILED; + } + else + { + /* Uploaded data does not match downloaded data. Trying writing/verifying current buffer again...*/ + continue; + } + } + } + } + + DownloadAddress += bytesToTransfer; + fwImagePtr += bytesToTransfer; + bytesLeftToDownload -= bytesToTransfer; + + /* Sanity check */ + if (fwImagePtr > (INT)fw_size) + return INCORRECT_IMAGE_LENGTH; + } + } + + /* Get Program Entry Address(4 bytes) */ + CYWB_BL_4_BYTES_COPY(&ProgramEntry, &buffer_p[fwImagePtr]); + fwImagePtr += 4; + + /* Get expected checksum (4 bytes) */ + CYWB_BL_4_BYTES_COPY(&ExpectedCheckSum, &buffer_p[fwImagePtr]); + fwImagePtr += 4; + + /* Compare computed checksum against expected value */ + if (ComputeCheckSum != ExpectedCheckSum) + { + /* CheckSum mismatch. Expected=0x" << std::hex << expectedCheckSum << " Computed=0x" << std::hex << computedCheckSum; */ + } + + /* Transfer execution to Program Entry */ + UCHAR dummyBuffer[1]; + // Few of the xHCI driver stack have issue with Control IN transfer,due to that below request fails , + // Control IN transfer is ZERO lenght packet , and it does not have any impact on execution of firmware. + //if (!DownloadBufferToDevice(ProgramEntry, 0, dummyBuffer, opCode)) + //{ + // /* Downloading Program Entry failed */ + // return FAILED; + //} + DownloadBufferToDevice(ProgramEntry, 0, dummyBuffer, opCode); + + return SUCCESS; +} + +//______________________________________________________________________________ + +FX3_FWDWNLOAD_ERROR_CODE CCyFX3Device::DownloadFw(char *fileName, FX3_FWDWNLOAD_MEDIA_TYPE enMediaType) +{ + UINT fwSize = 0; + PUCHAR FwImage; + FILE *FwImagePtr; + int error; + +// error = fopen_s(&FwImagePtr, fileName, "rb"); + FwImagePtr = fopen( fileName, "rb"); + if (FwImagePtr == NULL) + return INVALID_FILE; + + /* Find the length of the image */ + fseek (FwImagePtr, 0, SEEK_END); + fwSize = ftell(FwImagePtr); + fseek (FwImagePtr, 0, SEEK_SET); + + /* Allocate memory for the image */ + FwImage = new unsigned char[fwSize]; + + if (FwImage == NULL) + return INVALID_FILE; + + if (fwSize <= 0) + { + fclose (FwImagePtr); + return INVALID_FILE; + } + + /* Read into buffer */ + fread (FwImage, fwSize, 1, FwImagePtr); + fclose (FwImagePtr); + + FX3_FWDWNLOAD_ERROR_CODE ErroCode = SUCCESS; + // call api to download the image + if (enMediaType == RAM) + ErroCode = DownloadFwToRam(FwImage, fwSize, 0xA0); + else if (enMediaType == I2CE2PROM) + ErroCode = DownloadUserIMGtoI2CE2PROM(FwImage, fwSize, 0xBA); + else if (enMediaType == SPIFLASH) + ErroCode = DownloadUserIMGtoSPIFLASH(FwImage, fwSize, 0xC4); + else + ErroCode = INVALID_MEDIA_TYPE; + + if(FwImage) + delete[] FwImage; + + return ErroCode; +} + +//______________________________________________________________________________ + +CCyIsoPktInfo* CCyIsocEndPoint::CreatePktInfos(LONG bufLen, int &packets) +{ + if(MaxPktSize==0) + return NULL; + + packets = bufLen / MaxPktSize; // Number of packets implied by bufLen & pktSize + if (bufLen % MaxPktSize) packets++; + + if (packets) { + CCyIsoPktInfo *isoPktInfos = new CCyIsoPktInfo[packets]; + return isoPktInfos; + } else + return NULL; + +} + +//////////////////////////////////////////////////////////////////////////////// +// +// The CCyBulkEndPoint Class +// +//////////////////////////////////////////////////////////////////////////////// + +CCyBulkEndPoint::CCyBulkEndPoint(void) : CCyUSBEndPoint() +{ +} + +CCyBulkEndPoint::CCyBulkEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor) : +CCyUSBEndPoint(h, pEndPtDescriptor) +{ + +} +CCyBulkEndPoint::CCyBulkEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor,USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR* SSEndPtDescriptor): +CCyUSBEndPoint(h, pEndPtDescriptor,SSEndPtDescriptor) +{ + +} +//______________________________________________________________________________ + +PUCHAR CCyBulkEndPoint::BeginDataXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov) +{ + if ( hDevice == INVALID_HANDLE_VALUE ) return NULL; + + if (XferMode == XMODE_DIRECT) + return BeginDirectXfer(buf, bufLen, ov); + else + return BeginBufferedXfer(buf, bufLen, ov); +} + + + +//////////////////////////////////////////////////////////////////////////////// +// +// The CCyInterruptEndPoint Class +// +//////////////////////////////////////////////////////////////////////////////// + +CCyInterruptEndPoint::CCyInterruptEndPoint(void) : CCyUSBEndPoint() +{ +} + +CCyInterruptEndPoint::CCyInterruptEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor) : +CCyUSBEndPoint(h, pEndPtDescriptor) +{ + +} +CCyInterruptEndPoint::CCyInterruptEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor,USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR* SSEndPtDescriptor): +CCyUSBEndPoint(h, pEndPtDescriptor,SSEndPtDescriptor) +{ +} + +//______________________________________________________________________________ + +PUCHAR CCyInterruptEndPoint::BeginDataXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov) +{ + if ( hDevice == INVALID_HANDLE_VALUE ) return NULL; + + if (XferMode == XMODE_DIRECT) + return BeginDirectXfer(buf, bufLen, ov); + else + return BeginBufferedXfer(buf, bufLen, ov); + +} +CCyUSBBOS::CCyUSBBOS(void) +{ + // initialize to null + pUSB20_DeviceExt = NULL; + pSS_DeviceCap = NULL; + pContainer_ID = NULL; +} +CCyUSBBOS::~CCyUSBBOS() +{ + if(pContainer_ID) + { + delete pContainer_ID; + pContainer_ID = NULL; + } + if(pUSB20_DeviceExt) + { + delete pUSB20_DeviceExt; + pUSB20_DeviceExt = NULL; + } + if(pSS_DeviceCap) + { + delete pSS_DeviceCap; + pSS_DeviceCap = NULL; + } +} + +CCyUSBBOS::CCyUSBBOS(HANDLE h,PUSB_BOS_DESCRIPTOR pBosDescrData) +{ + // initialize to null + pUSB20_DeviceExt = NULL; + pSS_DeviceCap = NULL; + pContainer_ID = NULL; + + bLength = pBosDescrData->bLength; + bDescriptorType = pBosDescrData->bDescriptorType; + bNumDeviceCaps = pBosDescrData->bNumDeviceCaps; + wTotalLength = pBosDescrData->wTotalLength; + + int totallen = wTotalLength; + totallen -=pBosDescrData->bLength; + + if (totallen < 0) + return; + + UCHAR* DevCap = (byte*)((byte*)pBosDescrData + pBosDescrData->bLength); // get nex descriptor + + for (int i = 0; i < bNumDeviceCaps; i++) + { + //check capability type + switch (DevCap[USB_BOS_DEVICE_CAPABILITY_TYPE_INDEX]) + { + case USB_BOS_CAPABILITY_TYPE_USB20_EXT: + { + PUSB_BOS_USB20_DEVICE_EXTENSION pUSB20_ext = (PUSB_BOS_USB20_DEVICE_EXTENSION)DevCap; + totallen -= pUSB20_ext->bLength; + DevCap = (byte *)DevCap +pUSB20_ext->bLength; + pUSB20_DeviceExt = new CCyBosUSB20Extesnion(h, pUSB20_ext); + break; + } + case USB_BOS_CAPABILITY_TYPE_SUPERSPEED_USB: + { + PUSB_BOS_SS_DEVICE_CAPABILITY pSS_Capability = (PUSB_BOS_SS_DEVICE_CAPABILITY)DevCap; + totallen -= pSS_Capability->bLength; + DevCap = (byte*)DevCap + pSS_Capability->bLength; + pSS_DeviceCap = new CCyBosSuperSpeedCapability(h, pSS_Capability); + break; + } + case USB_BOS_CAPABILITY_TYPE_CONTAINER_ID: + { + PUSB_BOS_CONTAINER_ID pUSB_ContainerID = (PUSB_BOS_CONTAINER_ID)DevCap; + totallen -= pUSB_ContainerID->bLength; + DevCap = (byte*)DevCap + pUSB_ContainerID->bLength; + pContainer_ID = new CCyBosContainerID(h, pUSB_ContainerID); + break; + } + default: + { + break; + } + } + if(totallen<0) + break; + } +} +CCyBosUSB20Extesnion::CCyBosUSB20Extesnion(void) +{} +CCyBosUSB20Extesnion::CCyBosUSB20Extesnion(HANDLE h,PUSB_BOS_USB20_DEVICE_EXTENSION pBosUsb20ExtDesc) +{ + bLength = pBosUsb20ExtDesc->bLength; + bDescriptorType = pBosUsb20ExtDesc->bDescriptorType; + bDevCapabilityType = pBosUsb20ExtDesc->bDevCapabilityType; + bmAttribute = pBosUsb20ExtDesc->bmAttribute; +} +CCyBosSuperSpeedCapability::CCyBosSuperSpeedCapability(void) +{} +CCyBosSuperSpeedCapability::CCyBosSuperSpeedCapability(HANDLE h,PUSB_BOS_SS_DEVICE_CAPABILITY pUSB_SuperSpeedUsb) +{ + bLength = pUSB_SuperSpeedUsb->bLength; + bDescriptorType = pUSB_SuperSpeedUsb->bDescriptorType; + bDevCapabilityType = pUSB_SuperSpeedUsb->bDevCapabilityType; + bFunctionalitySupporte = pUSB_SuperSpeedUsb->bFunctionalitySupporte; + SpeedsSuported = pUSB_SuperSpeedUsb->wSpeedsSuported; + bmAttribute = pUSB_SuperSpeedUsb->bmAttribute; + bU1DevExitLat = pUSB_SuperSpeedUsb->bU1DevExitLat; + bU2DevExitLat = pUSB_SuperSpeedUsb->bU2DevExitLat; +} +CCyBosContainerID::CCyBosContainerID(void) +{} +CCyBosContainerID::CCyBosContainerID(HANDLE handle, PUSB_BOS_CONTAINER_ID pUSB_ContainerID) +{ + bLength = pUSB_ContainerID->bLength; + bDescriptorType = pUSB_ContainerID->bDescriptorType; + bDevCapabilityType = pUSB_ContainerID->bDevCapabilityType; + for (int i = 0; i < USB_BOS_CAPABILITY_TYPE_CONTAINER_ID_SIZE; i++) + ContainerID[i] = pUSB_ContainerID->ContainerID[i]; +} diff --git a/rx888_source/src/CyAPI/CyAPI.h b/rx888_source/src/CyAPI/CyAPI.h new file mode 100644 index 00000000..35492ef1 --- /dev/null +++ b/rx888_source/src/CyAPI/CyAPI.h @@ -0,0 +1,602 @@ +/* + ## Cypress CyAPI C++ library header file (CyAPI.h) + ## ======================================================= + ## + ## Copyright Cypress Semiconductor Corporation, 2009-2012, + ## All Rights Reserved + ## UNPUBLISHED, LICENSED SOFTWARE. + ## + ## CONFIDENTIAL AND PROPRIETARY INFORMATION + ## WHICH IS THE PROPERTY OF CYPRESS. + ## + ## Use of this file is governed + ## by the license agreement included in the file + ## + ## /license/license.rtf + ## + ## where is the Cypress software + ## install root directory path. + ## + ## ======================================================= +*/ + +#ifndef CyUSBH +#define CyUSBH + +#include "cyusb30_def.h" + +/* Data straucture for the Vendor request and data */ +typedef struct vendorCmdData +{ + UCHAR *buf; /* Pointer to the data */ + UCHAR opCode; /* Vendor request code */ + UINT addr; /* Read/Write address */ + long size; /* Size of the read/write */ + bool isRead; /* Read or write */ +} vendorCmdData ; + +#ifndef __USB200_H__ +#define __USB200_H__ +#pragma pack(push,1) +typedef struct _USB_DEVICE_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + USHORT bcdUSB; + UCHAR bDeviceClass; + UCHAR bDeviceSubClass; + UCHAR bDeviceProtocol; + UCHAR bMaxPacketSize0; + USHORT idVendor; + USHORT idProduct; + USHORT bcdDevice; + UCHAR iManufacturer; + UCHAR iProduct; + UCHAR iSerialNumber; + UCHAR bNumConfigurations; +} USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR; + +typedef struct _USB_ENDPOINT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bEndpointAddress; + UCHAR bmAttributes; + USHORT wMaxPacketSize; + UCHAR bInterval; +} USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR; + +typedef struct _USB_CONFIGURATION_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + USHORT wTotalLength; + UCHAR bNumInterfaces; + UCHAR bConfigurationValue; + UCHAR iConfiguration; + UCHAR bmAttributes; + UCHAR MaxPower; +} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR; + +typedef struct _USB_INTERFACE_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bInterfaceNumber; + UCHAR bAlternateSetting; + UCHAR bNumEndpoints; + UCHAR bInterfaceClass; + UCHAR bInterfaceSubClass; + UCHAR bInterfaceProtocol; + UCHAR iInterface; +} USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR; + +typedef struct _USB_STRING_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + WCHAR bString[1]; +} USB_STRING_DESCRIPTOR, *PUSB_STRING_DESCRIPTOR; + +typedef struct _USB_COMMON_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; +} USB_COMMON_DESCRIPTOR, *PUSB_COMMON_DESCRIPTOR; +#pragma pack(pop) +#endif + +/*******************************************************************************/ +class CCyIsoPktInfo { +public: + LONG Status; + LONG Length; +}; + +/*******************************************************************************/ + + +/* {AE18AA60-7F6A-11d4-97DD-00010229B959} */ + +static GUID CYUSBDRV_GUID = {0xae18aa60, 0x7f6a, 0x11d4, {0x97, 0xdd, 0x0, 0x1, 0x2, 0x29, 0xb9, 0x59}}; + + +typedef enum {TGT_DEVICE, TGT_INTFC, TGT_ENDPT, TGT_OTHER } CTL_XFER_TGT_TYPE; +typedef enum {REQ_STD, REQ_CLASS, REQ_VENDOR } CTL_XFER_REQ_TYPE; +typedef enum {DIR_TO_DEVICE, DIR_FROM_DEVICE } CTL_XFER_DIR_TYPE; +typedef enum {XMODE_BUFFERED, XMODE_DIRECT } XFER_MODE_TYPE; + +const int MAX_ENDPTS = 32; +const int MAX_INTERFACES = 255; +const int USB_STRING_MAXLEN = 256; + +#define BUFSIZE_UPORT 2048 //4096 - CDT 130492 +typedef enum { RAM = 1, I2CE2PROM, SPIFLASH } FX3_FWDWNLOAD_MEDIA_TYPE ; +typedef enum { SUCCESS = 0, FAILED, INVALID_MEDIA_TYPE, INVALID_FWSIGNATURE, DEVICE_CREATE_FAILED, INCORRECT_IMAGE_LENGTH, INVALID_FILE, SPILASH_ERASE_FAILED, CORRUPT_FIRMWARE_IMAGE_FILE,I2CE2PROM_UNKNOWN_I2C_SIZE } FX3_FWDWNLOAD_ERROR_CODE; + +#define CYWB_BL_4_BYTES_COPY(destination,source) {memcpy((void *)(destination), (void *)(source), 4);} + +/******************************************************************************** +* +* The CCyEndPoint ABSTRACT Class +* +********************************************************************************/ +class CCyUSBEndPoint +{ +protected: + bool WaitForIO(OVERLAPPED *ovLapStatus); + + virtual PUCHAR BeginDirectXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov); + virtual PUCHAR BeginBufferedXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov); + +public: + + CCyUSBEndPoint(void); + CCyUSBEndPoint(CCyUSBEndPoint& ept); + CCyUSBEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor); + CCyUSBEndPoint(HANDLE hDev, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor,USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR* SSEndPtDescriptor); + + HANDLE hDevice; + + /* The fields of an EndPoint Descriptor */ + UCHAR DscLen; + UCHAR DscType; + UCHAR Address; + UCHAR Attributes; + USHORT MaxPktSize; + USHORT PktsPerFrame; + UCHAR Interval; + /* This are the fields for Super speed endpoint */ + UCHAR ssdscLen; + UCHAR ssdscType; + UCHAR ssmaxburst; /* Maximum number of packets endpoint can send in one burst */ + UCHAR ssbmAttribute; /* store endpoint attribute like for bulk it will be number of streams */ + USHORT ssbytesperinterval; + + /* Other fields */ + ULONG TimeOut; + ULONG UsbdStatus; + ULONG NtStatus; + + DWORD bytesWritten; + DWORD LastError; + bool bIn; + + XFER_MODE_TYPE XferMode; + + bool XferData(PUCHAR buf, LONG &len, CCyIsoPktInfo* pktInfos = NULL); + bool XferData(PUCHAR buf, LONG &bufLen, CCyIsoPktInfo* pktInfos, bool pktMode); + virtual PUCHAR BeginDataXfer(PUCHAR buf, LONG len, OVERLAPPED *ov) = 0; + virtual bool FinishDataXfer(PUCHAR buf, LONG &len, OVERLAPPED *ov, PUCHAR pXmitBuf, CCyIsoPktInfo* pktInfos = NULL); + bool WaitForXfer(OVERLAPPED *ov, ULONG tOut); + ULONG GetXferSize(void); + void SetXferSize(ULONG xfer); + + bool Reset(void); + bool Abort(void); +}; + + +/******************************************************************************** +* +* The Control Endpoint Class +* +********************************************************************************/ +class CCyControlEndPoint : public CCyUSBEndPoint +{ +public: + CCyControlEndPoint(void); + CCyControlEndPoint(CCyControlEndPoint& ept); + CCyControlEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor); + + CTL_XFER_TGT_TYPE Target; + CTL_XFER_REQ_TYPE ReqType; + CTL_XFER_DIR_TYPE Direction; + + UCHAR ReqCode; + WORD Value; + WORD Index; + + bool Read(PUCHAR buf, LONG &len); + bool Write(PUCHAR buf, LONG &len); + PUCHAR BeginDataXfer(PUCHAR buf, LONG len, OVERLAPPED *ov); +}; + + +/******************************************************************************** +* +* The Isoc Endpoint Class +* +********************************************************************************/ +class CCyIsocEndPoint : public CCyUSBEndPoint +{ + +protected: + virtual PUCHAR BeginDirectXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov); + virtual PUCHAR BeginBufferedXfer(PUCHAR buf, LONG bufLen, OVERLAPPED *ov); + +public: + CCyIsocEndPoint(void); + CCyIsocEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor); + CCyIsocEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor,USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR* SSEndPtDescriptor); + + PUCHAR BeginDataXfer(PUCHAR buf, LONG len, OVERLAPPED *ov); + CCyIsoPktInfo* CreatePktInfos(LONG bufLen, int &packets); +}; + + +/******************************************************************************** +* +* The Bulk Endpoint Class +* +********************************************************************************/ +class CCyBulkEndPoint : public CCyUSBEndPoint +{ +public: + CCyBulkEndPoint(void); + CCyBulkEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor); + CCyBulkEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor,USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR* SSEndPtDescriptor); + + PUCHAR BeginDataXfer(PUCHAR buf, LONG len, OVERLAPPED *ov); +}; + + +/******************************************************************************** +* +* The Interrupt Endpoint Class +* +********************************************************************************/ +class CCyInterruptEndPoint : public CCyUSBEndPoint +{ +public: + CCyInterruptEndPoint(void); + CCyInterruptEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor); + CCyInterruptEndPoint(HANDLE h, PUSB_ENDPOINT_DESCRIPTOR pEndPtDescriptor,USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR* SSEndPtDescriptor); + + PUCHAR BeginDataXfer(PUCHAR buf, LONG len, OVERLAPPED *ov); +}; + + +/******************************************************************************** +* +* The Interface Class +* +********************************************************************************/ +class CCyUSBInterface +{ +public: + CCyUSBEndPoint *EndPoints[MAX_ENDPTS]; /* Holds pointers to all the interface's endpoints, + plus a pointer to the Control endpoint zero */ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bInterfaceNumber; + UCHAR bAlternateSetting; + UCHAR bNumEndpoints; /* Not counting the control endpoint */ + UCHAR bInterfaceClass; + UCHAR bInterfaceSubClass; + UCHAR bInterfaceProtocol; + UCHAR iInterface; + + UCHAR bAltSettings; + USHORT wTotalLength; /* Needed in case Intfc has additional (non-endpt) descriptors */ + + CCyUSBInterface(HANDLE handle, PUSB_INTERFACE_DESCRIPTOR pIntfcDescriptor,UCHAR usb30Dummy); + CCyUSBInterface(HANDLE h, PUSB_INTERFACE_DESCRIPTOR pIntfcDescriptor); + CCyUSBInterface(CCyUSBInterface& ifc); /* Copy Constructor */ + ~CCyUSBInterface(void); + +}; + + +/******************************************************************************** +* +* The Config Class +* +********************************************************************************/ +class CCyUSBConfig +{ +public: + CCyUSBInterface *Interfaces[MAX_INTERFACES]; + + UCHAR bLength; + UCHAR bDescriptorType; + USHORT wTotalLength; + UCHAR bNumInterfaces; + UCHAR bConfigurationValue; + UCHAR iConfiguration; + UCHAR bmAttributes; + UCHAR MaxPower; + + UCHAR AltInterfaces; + + CCyUSBConfig(void); + CCyUSBConfig(CCyUSBConfig& cfg); /* Copy Constructor */ + CCyUSBConfig(HANDLE h, PUSB_CONFIGURATION_DESCRIPTOR pConfigDescr); + CCyUSBConfig(HANDLE h, PUSB_CONFIGURATION_DESCRIPTOR pConfigDescr,UCHAR usb30Dummy); + ~CCyUSBConfig(void); +}; + + +/******************************************************************************** +* +* The Bos USB20 Extesnion Class +* +********************************************************************************/ +class CCyBosUSB20Extesnion +{ +public: + UCHAR bLength; /* Descriptor length */ + UCHAR bDescriptorType; /* Descriptor Type */ + UCHAR bDevCapabilityType; /* Device capability type */ + UINT bmAttribute; /* Bitmap encoding for supprted feature and Link power managment supprted if set */ + + CCyBosUSB20Extesnion(void); + CCyBosUSB20Extesnion(HANDLE h,PUSB_BOS_USB20_DEVICE_EXTENSION BosUsb20ExtDesc); +}; + + +/******************************************************************************** +* +* The Bos SuperSpeed Capability Class +* +********************************************************************************/ +class CCyBosSuperSpeedCapability +{ +public: + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDevCapabilityType; + UCHAR bmAttribute; + USHORT SpeedsSuported; + UCHAR bFunctionalitySupporte; + UCHAR bU1DevExitLat; + USHORT bU2DevExitLat; + + CCyBosSuperSpeedCapability(void); + CCyBosSuperSpeedCapability(HANDLE h,PUSB_BOS_SS_DEVICE_CAPABILITY pUSB_SuperSpeedUsb); + +}; + + +/******************************************************************************** +* +* The Bos Container ID Class +* +********************************************************************************/ +class CCyBosContainerID +{ +public: + UCHAR bLength; /* Descriptor length */ + UCHAR bDescriptorType; /* Descriptor Type */ + UCHAR bDevCapabilityType; /* Device capability type */ + UCHAR bReserved; /* no use */ + UCHAR ContainerID[USB_BOS_CAPABILITY_TYPE_CONTAINER_ID_SIZE]; /* UUID */ + + CCyBosContainerID(void); + CCyBosContainerID(HANDLE h,PUSB_BOS_CONTAINER_ID pContainerID); +}; + + +/******************************************************************************** +* +* The USB BOS Class +* +********************************************************************************/ +class CCyUSBBOS +{ +public: + + CCyBosContainerID *pContainer_ID; + CCyBosUSB20Extesnion *pUSB20_DeviceExt; + CCyBosSuperSpeedCapability *pSS_DeviceCap; + + UCHAR bLength; /* Descriptor length */ + UCHAR bDescriptorType; /* Descriptor Type */ + USHORT wTotalLength; /* Total length of descriptor ( icluding device capabilty */ + UCHAR bNumDeviceCaps; /* Number of device capability descriptors in BOS */ + + CCyUSBBOS(void); + CCyUSBBOS(HANDLE h,PUSB_BOS_DESCRIPTOR pBosDescrData); + ~CCyUSBBOS(); +}; + +/********************************************************************************* +* +* The USB Device Class - This is the main class that contains members of all the +* other classes. +* +* To use the library, create an instance of this Class and call it's Open method. +* +*********************************************************************************/ +class CCyUSBDevice +{ + /* The public members are accessible (i.e. corruptible) by the user of the library + * Algorithms of the class don't rely on any public members. Instead, they use the + * private members of the class for their calculations. */ + +public: + + CCyUSBDevice(HANDLE hnd = NULL, GUID guid = CYUSBDRV_GUID, BOOL bOpen = true); + ~CCyUSBDevice(void); + + CCyUSBEndPoint **EndPoints; /* Shortcut to USBCfgs[CfgNum]->Interfaces[IntfcIndex]->Endpoints */ + CCyUSBEndPoint *EndPointOf(UCHAR addr); + + CCyUSBBOS *UsbBos; + CCyIsocEndPoint *IsocInEndPt; + CCyIsocEndPoint *IsocOutEndPt; + CCyBulkEndPoint *BulkInEndPt; + CCyBulkEndPoint *BulkOutEndPt; + CCyControlEndPoint *ControlEndPt; + CCyInterruptEndPoint *InterruptInEndPt; + CCyInterruptEndPoint *InterruptOutEndPt; + + + USHORT StrLangID; + ULONG LastError; + ULONG UsbdStatus; + ULONG NtStatus; + ULONG DriverVersion; + ULONG USBDIVersion; + char DeviceName[USB_STRING_MAXLEN]; + char FriendlyName[USB_STRING_MAXLEN]; + wchar_t Manufacturer[USB_STRING_MAXLEN]; + wchar_t Product[USB_STRING_MAXLEN]; + wchar_t SerialNumber[USB_STRING_MAXLEN]; + + CHAR DevPath[USB_STRING_MAXLEN]; + + USHORT BcdUSB; + USHORT VendorID; + USHORT ProductID; + UCHAR USBAddress; + UCHAR DevClass; + UCHAR DevSubClass; + UCHAR DevProtocol; + INT MaxPacketSize; + USHORT BcdDevice; + + UCHAR ConfigValue; + UCHAR ConfigAttrib; + UCHAR MaxPower; + + UCHAR IntfcClass; + UCHAR IntfcSubClass; + UCHAR IntfcProtocol; + bool bHighSpeed; + bool bSuperSpeed; + + DWORD BytesXfered; + + UCHAR DeviceCount(void); + UCHAR ConfigCount(void); + UCHAR IntfcCount(void); + UCHAR AltIntfcCount(void); + UCHAR EndPointCount(void); + + void SetConfig(UCHAR cfg); + UCHAR Config(void) { return CfgNum; } /* Normally 0 */ + UCHAR Interface(void) { return IntfcNum; } /* Usually 0 */ + + /* No SetInterface method since only 1 intfc per device (per Windows) */ + UCHAR AltIntfc(void); + bool SetAltIntfc(UCHAR alt); + + GUID DriverGUID(void) { return DrvGuid; } + HANDLE DeviceHandle(void) { return hDevice; } + void UsbdStatusString(ULONG stat, PCHAR s); + bool CreateHandle(UCHAR dev); + void DestroyHandle(); + + bool Open(UCHAR dev); + void Close(void); + bool Reset(void); + bool ReConnect(void); + bool Suspend(void); + bool Resume(void); + bool IsOpen(void) { return (hDevice != INVALID_HANDLE_VALUE); } + + UCHAR PowerState(void); + + bool GetBosDescriptor(PUSB_BOS_DESCRIPTOR descr); + bool GetBosUSB20DeviceExtensionDescriptor(PUSB_BOS_USB20_DEVICE_EXTENSION descr); + bool GetBosContainedIDDescriptor(PUSB_BOS_CONTAINER_ID descr); + bool GetBosSSCapabilityDescriptor(PUSB_BOS_SS_DEVICE_CAPABILITY descr); + + void GetDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR descr); + void GetConfigDescriptor(PUSB_CONFIGURATION_DESCRIPTOR descr); + void GetIntfcDescriptor(PUSB_INTERFACE_DESCRIPTOR descr); + CCyUSBConfig GetUSBConfig(int index); + +private: + + USB_DEVICE_DESCRIPTOR USBDeviceDescriptor; + PUSB_CONFIGURATION_DESCRIPTOR USBConfigDescriptors[2]; + PUSB_BOS_DESCRIPTOR pUsbBosDescriptor; + + CCyUSBConfig *USBCfgs[2]; + + HANDLE hWnd; + HANDLE hDevice; + HANDLE hDevNotification; + HANDLE hHndNotification; + + GUID DrvGuid; + + UCHAR Devices; + UCHAR Interfaces; + UCHAR AltInterfaces; + UCHAR Configs; + + UCHAR DevNum; + UCHAR CfgNum; + UCHAR IntfcNum; /* The current selected interface's bInterfaceNumber */ + UCHAR IntfcIndex; /* The entry in the Config's interfaces table matching to IntfcNum and AltSetting */ + + bool GetInternalBosDescriptor(); + void GetDevDescriptor(void); + void GetCfgDescriptor(int descIndex); + void GetString(wchar_t *s, UCHAR sIndex); + void SetStringDescrLanguage(void); + void SetAltIntfcParams(UCHAR alt); + bool IoControl(ULONG cmd, PUCHAR buf, ULONG len); + + void SetEndPointPtrs(void); + void GetDeviceName(void); + void GetFriendlyName(void); + void GetDriverVer(void); + void GetUSBDIVer(void); + void GetSpeed(void); + void GetUSBAddress(void); + //void CloseEndPtHandles(void); + + bool RegisterForPnpEvents(HANDLE h); +}; + + +/******************************************************************************** +* +* The FX3 Device Class +* +********************************************************************************/ +class CCyFX3Device: public CCyUSBDevice +{ +public: + CCyFX3Device(void); + ~CCyFX3Device(void); + bool IsBootLoaderRunning(); + FX3_FWDWNLOAD_ERROR_CODE DownloadFw(char *fileName, FX3_FWDWNLOAD_MEDIA_TYPE enMediaType); + +private: + + bool Ep0VendorCommand(vendorCmdData cmdData); + bool SetProgramEntry(UCHAR opCode,UINT start_addr); + + bool DownloadBufferToDevice(UINT start_addr, USHORT count, UCHAR *data_buf, UCHAR opCode); + bool UploadBufferFromDevice(UINT start_addr, USHORT count, UCHAR *data_buf, UCHAR opCode); + + FX3_FWDWNLOAD_ERROR_CODE DownloadFwToRam(PUCHAR buffer_p, UINT fw_size, UCHAR opCode); + FX3_FWDWNLOAD_ERROR_CODE DownloadUserIMGtoI2CE2PROM(PUCHAR buffer_p, UINT fw_size, UCHAR opCode); + FX3_FWDWNLOAD_ERROR_CODE DownloadUserIMGtoSPIFLASH(PUCHAR buffer_p, UINT fw_size, UCHAR opCode); + + FX3_FWDWNLOAD_ERROR_CODE EraseSectorOfSPIFlash(UINT SectorNumber, UCHAR opCode); + bool WriteToSPIFlash(PUCHAR Buf, UINT buflen, UINT ByteAddress, UCHAR opCode); +}; + +/********************************************************************************/ + +#endif diff --git a/rx888_source/src/CyAPI/CyUSB30_def.h b/rx888_source/src/CyAPI/CyUSB30_def.h new file mode 100644 index 00000000..878349b8 --- /dev/null +++ b/rx888_source/src/CyAPI/CyUSB30_def.h @@ -0,0 +1,90 @@ +/* + ## Cypress CyAPI C++ library USB3.0 defination header file (CyUSB30_def.h) + ## ======================================================= + ## + ## Copyright Cypress Semiconductor Corporation, 2009-2012, + ## All Rights Reserved + ## UNPUBLISHED, LICENSED SOFTWARE. + ## + ## CONFIDENTIAL AND PROPRIETARY INFORMATION + ## WHICH IS THE PROPERTY OF CYPRESS. + ## + ## Use of this file is governed + ## by the license agreement included in the file + ## + ## /license/license.rtf + ## + ## where is the Cypress software + ## install root directory path. + ## + ## ======================================================= +*/ +#ifndef _CYUSB30_H +#define _CYUSB30_H + +//#pragma pack(1) +#pragma pack(push, 1) +// USB3.0 specific constant defination +#define BCDUSBJJMASK 0xFF00 //(0xJJMN JJ - Major version,M Minor version, N sub-minor vesion) +#define USB30MAJORVER 0x0300 +#define USB20MAJORVER 0x0200 + +#define USB_BOS_DESCRIPTOR_TYPE 0x0F +#define USB_DEVICE_CAPABILITY 0x10 +#define USB_SUPERSPEED_ENDPOINT_COMPANION 0x30 +#define USB_BOS_CAPABILITY_TYPE_Wireless_USB 0x01 +#define USB_BOS_CAPABILITY_TYPE_USB20_EXT 0x02 +#define USB_BOS_CAPABILITY_TYPE_SUPERSPEED_USB 0x03 +#define USB_BOS_CAPABILITY_TYPE_CONTAINER_ID 0x04 +#define USB_BOS_CAPABILITY_TYPE_CONTAINER_ID_SIZE 0x10 + +#define USB_BOS_DEVICE_CAPABILITY_TYPE_INDEX 0x2 +//constant defination +typedef struct _USB_BOS_DESCRIPTOR +{ + UCHAR bLength;/* Descriptor length*/ + UCHAR bDescriptorType;/* Descriptor Type */ + USHORT wTotalLength;/* Total length of descriptor ( icluding device capability*/ + UCHAR bNumDeviceCaps;/* Number of device capability descriptors in BOS */ +}USB_BOS_DESCRIPTOR,*PUSB_BOS_DESCRIPTOR; + +typedef struct _USB_BOS_USB20_DEVICE_EXTENSION +{ + UCHAR bLength;/* Descriptor length*/ + UCHAR bDescriptorType;/* Descriptor Type */ + UCHAR bDevCapabilityType;/* Device capability type*/ + UINT bmAttribute;// Bitmap encoding for supprted feature and Link power managment supprted if set +}USB_BOS_USB20_DEVICE_EXTENSION,*PUSB_BOS_USB20_DEVICE_EXTENSION; + +typedef struct _USB_BOS_SS_DEVICE_CAPABILITY +{ + UCHAR bLength;/* Descriptor length*/ + UCHAR bDescriptorType;/* Descriptor Type */ + UCHAR bDevCapabilityType;/* Device capability type*/ + UCHAR bmAttribute;// Bitmap encoding for supprted feature and Link power managment supprted if set + USHORT wSpeedsSuported;//low speed supported if set,full speed supported if set,high speed supported if set,super speed supported if set,15:4 nt used + UCHAR bFunctionalitySupporte; + UCHAR bU1DevExitLat;//U1 device exit latency + USHORT bU2DevExitLat;//U2 device exit latency +}USB_BOS_SS_DEVICE_CAPABILITY,*PUSB_BOS_SS_DEVICE_CAPABILITY; + +typedef struct _USB_BOS_CONTAINER_ID +{ + UCHAR bLength;/* Descriptor length*/ + UCHAR bDescriptorType;/* Descriptor Type */ + UCHAR bDevCapabilityType;/* Device capability type*/ + UCHAR bReserved; // no use + UCHAR ContainerID[USB_BOS_CAPABILITY_TYPE_CONTAINER_ID_SIZE];/* UUID */ +}USB_BOS_CONTAINER_ID,*PUSB_BOS_CONTAINER_ID; + +typedef struct _USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bMaxBurst; + UCHAR bmAttributes; + USHORT bBytesPerInterval; +}USB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR,*PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR; +#pragma pack(pop) +#endif /*_CYUSB30_H*/ + diff --git a/rx888_source/src/CyAPI/Si5351.cpp b/rx888_source/src/CyAPI/Si5351.cpp new file mode 100644 index 00000000..b85a274a --- /dev/null +++ b/rx888_source/src/CyAPI/Si5351.cpp @@ -0,0 +1,256 @@ +#include "Si5351.h" +#include "openFX3.h" +#include + +#define DbgPrintf spdlog::info + +#define SI_CLK0_CONTROL 16 // Registers +#define SI_CLK1_CONTROL 17 +#define SI_CLK2_CONTROL 18 +#define SI_SYNTH_PLL_A 26 +#define SI_SYNTH_PLL_B 34 +#define SI_SYNTH_MS_0 42 +#define SI_SYNTH_MS_1 50 +#define SI_SYNTH_MS_2 58 +#define SI_PLL_RESET (0x177) + +#define SI_R_DIV_1 (0) // 0b00000000 / +#define SI_R_DIV_2 (0x10) // 0b00010000 +#define SI_R_DIV_4 (0x20) // 0b00100000 +#define SI_R_DIV_8 (0x30) // 0b00110000 +#define SI_R_DIV_16 (0x40) // 0b01000000 +#define SI_R_DIV_32 (0x50) // 0b01010000 +#define SI_R_DIV_64 (0x60) // 0b01100000 +#define SI_R_DIV_128 (0x70) // 0b01110000 + +#define SI_CLK_SRC_PLL_A 0b00000000 +#define SI_CLK_SRC_PLL_B 0b00100000 + +#define SI5351_FREQ 27000000 // Crystal frequency +#define SI5351_PLL_FIXED 80000000000ULL + +#define SI5351_ADDR (0x60 << 1 ) + +#define SI5351_CRYSTAL_LOAD 183 +#define SI5351_CRYSTAL_LOAD_MASK (3<<6) +#define SI5351_CRYSTAL_LOAD_0PF (0<<6) +#define SI5351_CRYSTAL_LOAD_6PF (1<<6) +#define SI5351_CRYSTAL_LOAD_8PF (2<<6) +#define SI5351_CRYSTAL_LOAD_10PF (3<<6) + +#define SI5351_PLL_INPUT_SOURCE 15 +#define SI5351_CLKIN_DIV_MASK (3<<6) +#define SI5351_CLKIN_DIV_1 (0<<6) +#define SI5351_CLKIN_DIV_2 (1<<6) +#define SI5351_CLKIN_DIV_4 (2<<6) +#define SI5351_CLKIN_DIV_8 (3<<6) +#define SI5351_PLLB_SOURCE (1<<3) +#define SI5351_PLLA_SOURCE (1<<2) + +void Si5351init() +{ + // Set crystal load capacitance + fx3SendI2cbyte(SI5351_ADDR, SI5351_CRYSTAL_LOAD, SI5351_CRYSTAL_LOAD_6PF | 0b00010010); + fx3SendI2cbyte(SI5351_ADDR, SI_CLK0_CONTROL, 0x80); // clocks off + fx3SendI2cbyte(SI5351_ADDR, SI_CLK1_CONTROL, 0x80); + fx3SendI2cbyte(SI5351_ADDR, SI_CLK2_CONTROL, 0x80); + // si5351aSetFrequency(ADC_FREQ, R820T_ZERO); + DbgPrintf("Si5351_init()\n"); +} + + +#define _PLLDEBUG_ +// +// Set up specified PLL with mult, num and denom +// mult is 15..90 +// num is 0..1,048,575 (0xFFFFF) +// denom is 0..1,048,575 (0xFFFFF) +// +static void setupPLL(UINT8 pll, UINT8 mult, UINT32 num, UINT32 denom) +{ + UINT32 P1; // PLL config register P1 + UINT32 P2; // PLL config register P2 + UINT32 P3; // PLL config register P3 + UINT8 data[8]; + + // the actual multiplier is mult + num / denom +#ifdef _PLLDEBUG_ + double fa; + double x = 27000000.0; + fa = x * ((double)mult + (double)num / (double)denom); + DbgPrintf((char *) "pll = %d , mult = %d , num = %d , denom = %d\n", pll, mult, num, denom); + DbgPrintf((char *) "pll target %e \n", fa); +#endif + + P1 = (UINT32)(128 * ((float)num / (float)denom)); + P1 = (UINT32)(128 * (UINT32)(mult)+P1 - 512); + P2 = (UINT32)(128 * ((float)num / (float)denom)); + P2 = (UINT32)(128 * num - denom * P2); + P3 = denom; + + data[0] = (P3 & 0x0000FF00) >> 8; + data[1] = (P3 & 0x000000FF); + data[2] = (P1 & 0x00030000) >> 16; + data[3] = (P1 & 0x0000FF00) >> 8; + data[4] = (P1 & 0x000000FF); + data[5] = ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16); + data[6] = (P2 & 0x0000FF00) >> 8; + data[7] = (P2 & 0x000000FF); + + fx3SendI2cbytes(SI5351_ADDR, pll, data, sizeof(data)); +} +// +// Set up MultiSynth with integer divider and R divider +// R divider is the bit value which is OR'ed onto the appropriate register, it is a #define in si5351a.h +// +static void setupMultisynth(UINT8 synth, UINT32 divider, UINT8 rDiv) +{ + UINT32 P1; // Synth config register P1 + UINT32 P2; // Synth config register P2 + UINT32 P3; // Synth config register P3 + UINT8 data[8]; + +#ifdef _PLLDEBUG_ + DbgPrintf("setupMultisynth synth = %d divider = %d rDiv= %d \n", synth, divider, rDiv); + //DbgPrintf("output expected f = %e\n", fa / divider); +#endif + + P1 = 128 * divider - 512; + P2 = 0; // P2 = 0, P3 = 1 forces an integer value for the divider + P3 = 1; + + data[0] = (P3 & 0x0000FF00) >> 8; + data[1] = (P3 & 0x000000FF); + data[2] = ((P1 & 0x00030000) >> 16) | rDiv; + data[3] = (P1 & 0x0000FF00) >> 8; + data[4] = (P1 & 0x000000FF); + data[5] = ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16); + data[6] = (P2 & 0x0000FF00) >> 8; + data[7] = (P2 & 0x000000FF); + + fx3SendI2cbytes(SI5351_ADDR, synth, data, sizeof(data)); +} +// +// Switches off Si5351a output +// Example: si5351aOutputOff(SI_CLK0_CONTROL); +// will switch off output CLK0 +// +void si5351aOutputOff(UINT8 clk) +{ + fx3SendI2cbyte(SI5351_ADDR, clk, 0x80); // Refer to SiLabs AN619 to see bit values - 0x80 turns off the output stage +} + +void si5351aSetFrequency(UINT32 freq, UINT32 freq2) +{ + UINT32 frequency; + UINT32 pllFreq; + UINT32 xtalFreq = SI5351_FREQ; + UINT32 l; + double f; + UINT8 mult; + UINT32 num; + UINT32 denom; + UINT32 divider; + UINT32 rdiv; + + double corr = 0.9999314; + //double corr = 1.0; + + DbgPrintf("BBRF103 si5351 SetFreq ADC sampling:%d R820T reference:%d\n", freq, freq2); + + rdiv = (UINT32)SI_R_DIV_1; + + frequency = (UINT32)((double)freq * corr); + + while (frequency < 1000000) + { + frequency = frequency * 2; + rdiv += SI_R_DIV_2; + } +#ifdef _PLLDEBUG_ + DbgPrintf((char *) "\nCLK0 frequency %d \n", frequency); +#endif + divider = 900000000UL / frequency;// Calculate the division ratio. 900,000,000 is the maximum internal + // PLL frequency: 900MHz + if (divider % 2) divider--; // Ensure an even integer division ratio + + pllFreq = divider * frequency; // Calculate the pllFrequency: the divider * desired output frequency +#ifdef _PLLDEBUG_ + DbgPrintf((char *) "pllA Freq %d \n", pllFreq); +#endif + mult = pllFreq / xtalFreq; // Determine the multiplier to get to the required pllFrequency + l = pllFreq % xtalFreq; // It has three parts: + f = (double)l; // mult is an integer that must be in the range 15..90 + f *= 1048575; // num and denom are the fractional parts, the numerator and denominator + f /= xtalFreq; // each is 20 bits (range 0..1048575) + num = (UINT32)f; // the actual multiplier is mult + num / denom + denom = 1048575; // For simplicity we set the denominator to the maximum 1048575 + // Set up PLL A with the calculated multiplication ratio + setupPLL(SI_SYNTH_PLL_A, mult, num, denom); + // Set up MultiSynth divider 0, with the calculated divider. + // The final R division stage can divide by a power of two, from 1..128. + // represented by constants SI_R_DIV1 to SI_R_DIV128 (see si5351a.h header file) + // If you want to output frequencies below 1MHz, you have to use the + // final R division stage + setupMultisynth(SI_SYNTH_MS_0, divider, rdiv); + // Reset the PLL. This causes a glitch in the output. For small changes to + // the parameters, you don't need to reset the PLL, and there is no glitch + fx3SendI2cbyte((UINT8)SI5351_ADDR, (UINT8)SI_PLL_RESET, (UINT8)0x20); //pllA + // Finally switch on the CLK0 output (0x4F) + // and set the MultiSynth0 input to be PLL A + fx3SendI2cbyte(SI5351_ADDR, SI_CLK0_CONTROL, 0x4F | SI_CLK_SRC_PLL_A); + + if (freq2 > 0) + { + // calculate clk2 + frequency = (UINT32)((double)freq2 * corr); + rdiv = SI_R_DIV_1; + xtalFreq = SI5351_FREQ; + while (frequency <= 1000000) + { + frequency = frequency * 2; + rdiv += SI_R_DIV_2; + } +#ifdef _PLLDEBUG_ + DbgPrintf((char *) "\nCLK2 frequency %d \n", frequency); +#endif + divider = 900000000UL / frequency;// Calculate the division ratio. 900,000,000 is the maximum internal + // PLL frequency: 900MHz + if (divider % 2) divider--; // Ensure an even integer division ratio + + pllFreq = divider * frequency; // Calculate the pllFrequency: the divider * desired output frequency +#ifdef _PLLDEBUG_ + DbgPrintf((char *) "pllB Freq %d \n", pllFreq); +#endif + mult = pllFreq / xtalFreq; // Determine the multiplier to get to the required pllFrequency + l = pllFreq % xtalFreq; // It has three parts: + f = (double)l; // mult is an integer that must be in the range 15..90 + f *= 1048575; // num and denom are the fractional parts, the numerator and denominator + f /= xtalFreq; // each is 20 bits (range 0..1048575) + num = (UINT32)f; // the actual multiplier is mult + num / denom + denom = 1048575; // For simplicity we set the denominator to the maximum 1048575 + + // Set up PLL B with the calculated multiplication ratio + setupPLL(SI_SYNTH_PLL_B, mult, num, denom); + // Set up MultiSynth divider 0, with the calculated divider. + // The final R division stage can divide by a power of two, from 1..128. + // represented by constants SI_R_DIV1 to SI_R_DIV128 (see si5351a.h header file) + // If you want to output frequencies below 1MHz, you have to use the + // final R division stage + + setupMultisynth(SI_SYNTH_MS_2, divider, rdiv); + // Reset the PLL. This causes a glitch in the output. For small changes to + // the parameters, you don't need to reset the PLL, and there is no glitch + fx3SendI2cbyte((UINT8)SI5351_ADDR, (UINT8)SI_PLL_RESET, (UINT8)0x80); //pllB + // Finally switch on the CLK2 output (0x4C) + // and set the MultiSynth0 input to be PLL A + fx3SendI2cbyte(SI5351_ADDR, SI_CLK2_CONTROL, 0x4C | SI_CLK_SRC_PLL_B); // select PLLB + // calculate clk2 + } + else + { + fx3SendI2cbyte(SI5351_ADDR, SI_CLK2_CONTROL, 0x80); + } + +} + diff --git a/rx888_source/src/CyAPI/Si5351.h b/rx888_source/src/CyAPI/Si5351.h new file mode 100644 index 00000000..b94c183b --- /dev/null +++ b/rx888_source/src/CyAPI/Si5351.h @@ -0,0 +1,13 @@ +// MIT License Copyright (c) 2017 ik1xpv@gmail.com, http://www.steila.com/blog + +#ifndef SI5351_H +#define SI5351_H + +#include + +void Si5351init(); +void si5351aSetFrequency(UINT32 freq, UINT32 freq2); +void si5351aOutputOff(UINT8 clk); + + +#endif diff --git a/rx888_source/src/CyAPI/UsbdStatus.h b/rx888_source/src/CyAPI/UsbdStatus.h new file mode 100644 index 00000000..e2bbaa05 --- /dev/null +++ b/rx888_source/src/CyAPI/UsbdStatus.h @@ -0,0 +1,46 @@ + +// Note: see usbdi.h in the DDK for the USBD_STATUS source definitions +typedef LONG USBD_STATUS; +#define USBD_STATUS(Status) ((ULONG)(Status) & 0x0FFFFFFFL) +#define USBD_STATE(Status) ((ULONG)(Status) & 0xF0000000L) + +// HC status codes (Note: both error and stall bit are set) +#define USBD_STATUS_SUCCESS ((USBD_STATUS)0x00000000L) +#define USBD_STATUS_PENDING ((USBD_STATUS)0x40000000L) +#define USBD_STATUS_HALTED ((USBD_STATUS)0xC0000000L) +#define USBD_STATUS_ERROR ((USBD_STATUS)0x80000000L) + +#define USBD_STATUS_CRC ((USBD_STATUS)0xC0000001L) +#define USBD_STATUS_BTSTUFF ((USBD_STATUS)0xC0000002L) +#define USBD_STATUS_DATA_TOGGLE_MISMATCH ((USBD_STATUS)0xC0000003L) +#define USBD_STATUS_STALL_PID ((USBD_STATUS)0xC0000004L) +#define USBD_STATUS_DEV_NOT_RESPONDING ((USBD_STATUS)0xC0000005L) +#define USBD_STATUS_PID_CHECK_FAILURE ((USBD_STATUS)0xC0000006L) +#define USBD_STATUS_UNEXPECTED_PID ((USBD_STATUS)0xC0000007L) +#define USBD_STATUS_DATA_OVERRUN ((USBD_STATUS)0xC0000008L) +#define USBD_STATUS_DATA_UNDERRUN ((USBD_STATUS)0xC0000009L) +#define USBD_STATUS_RESERVED1 ((USBD_STATUS)0xC000000AL) +#define USBD_STATUS_RESERVED2 ((USBD_STATUS)0xC000000BL) +#define USBD_STATUS_BUFFER_OVERRUN ((USBD_STATUS)0xC000000CL) +#define USBD_STATUS_BUFFER_UNDERRUN ((USBD_STATUS)0xC000000DL) +#define USBD_STATUS_NOT_ACCESSED ((USBD_STATUS)0xC000000FL) +#define USBD_STATUS_FIFO ((USBD_STATUS)0xC0000010L) + +#define USBD_STATUS_ENDPOINT_HALTED ((USBD_STATUS)0xC0000030L) +#define USBD_STATUS_NO_MEMORY ((USBD_STATUS)0x80000100L) +#define USBD_STATUS_INVALID_URB_FUNCTION ((USBD_STATUS)0x80000200L) +#define USBD_STATUS_INVALID_PARAMETER ((USBD_STATUS)0x80000300L) +#define USBD_STATUS_ERROR_BUSY ((USBD_STATUS)0x80000400L) +#define USBD_STATUS_REQUEST_FAILED ((USBD_STATUS)0x80000500L) +#define USBD_STATUS_INVALID_PIPE_HANDLE ((USBD_STATUS)0x80000600L) +#define USBD_STATUS_NO_BANDWIDTH ((USBD_STATUS)0x80000700L) +#define USBD_STATUS_INTERNAL_HC_ERROR ((USBD_STATUS)0x80000800L) +#define USBD_STATUS_ERROR_SHORT_TRANSFER ((USBD_STATUS)0x80000900L) +#define USBD_STATUS_BAD_START_FRAME ((USBD_STATUS)0xC0000A00L) +#define USBD_STATUS_ISOCH_REQUEST_FAILED ((USBD_STATUS)0xC0000B00L) +#define USBD_STATUS_FRAME_CONTROL_OWNED ((USBD_STATUS)0xC0000C00L) +#define USBD_STATUS_FRAME_CONTROL_NOT_OWNED ((USBD_STATUS)0xC0000D00L) +#define USBD_STATUS_CANCELED ((USBD_STATUS)0x00010000L) +#define USBD_STATUS_CANCELING ((USBD_STATUS)0x00020000L) + + diff --git a/rx888_source/src/CyAPI/VersionNo.h b/rx888_source/src/CyAPI/VersionNo.h new file mode 100644 index 00000000..50a937c0 --- /dev/null +++ b/rx888_source/src/CyAPI/VersionNo.h @@ -0,0 +1,26 @@ +/* + ## Cypress CyAPI C++ library version number header file (VersionNo.h) + ## ======================================================= + ## + ## Copyright Cypress Semiconductor Corporation, 2009-2012, + ## All Rights Reserved + ## UNPUBLISHED, LICENSED SOFTWARE. + ## + ## CONFIDENTIAL AND PROPRIETARY INFORMATION + ## WHICH IS THE PROPERTY OF CYPRESS. + ## + ## Use of this file is governed + ## by the license agreement included in the file + ## + ## /license/license.rtf + ## + ## where is the Cypress software + ## install root directory path. + ## + ## ======================================================= +*/ +#define FILEVER 1,2,1,0 +#define PRODUCTVER 1,2,1,0 +#define STRFILEVER "1, 2, 1, 0" +#define STRPRODUCTVER "1, 2, 1, 0" +#define STRFILEVER_ASSENBLY "1.2.1.0" diff --git a/rx888_source/src/CyAPI/cyioctl.h b/rx888_source/src/CyAPI/cyioctl.h new file mode 100644 index 00000000..1a905b53 --- /dev/null +++ b/rx888_source/src/CyAPI/cyioctl.h @@ -0,0 +1,213 @@ +/* + ## Cypress CyAPI C++ library IOCTL defination header file (cyioctl.h) + ## ======================================================= + ## + ## Copyright Cypress Semiconductor Corporation, 2009-2012, + ## All Rights Reserved + ## UNPUBLISHED, LICENSED SOFTWARE. + ## + ## CONFIDENTIAL AND PROPRIETARY INFORMATION + ## WHICH IS THE PROPERTY OF CYPRESS. + ## + ## Use of this file is governed + ## by the license agreement included in the file + ## + ## /license/license.rtf + ## + ## where is the Cypress software + ## install root directory path. + ## + ## ======================================================= +*/ +#ifndef __IOCTL_H__ +#define __IOCTL_H__ + + +#ifndef DRIVER + +#ifndef CTL_CODE +#include "devioctl.h" +#endif + +#ifndef BM_REQUEST_TYPE +#include "usb200.h" +#endif + +#include + +#define DIR_HOST_TO_DEVICE 0 +#define DIR_DEVICE_TO_HOST 1 + +#define DEVICE_SPEED_UNKNOWN 0x00000000 +#define DEVICE_SPEED_LOW_FULL 0x00000001 +#define DEVICE_SPEED_HIGH 0x00000002 +#define DEVICE_SPEED_SUPER 0x00000004 + +typedef struct _WORD_SPLIT { + UCHAR lowByte; + UCHAR hiByte; +} WORD_SPLIT, *PWORD_SPLIT; + +typedef struct _BM_REQ_TYPE { + UCHAR Recipient:2; + UCHAR Reserved:3; + UCHAR Type:2; + UCHAR Direction:1; +} BM_REQ_TYPE, *PBM_REQ_TYPE; + +typedef struct _SETUP_PACKET { + + union { + BM_REQ_TYPE bmReqType; + UCHAR bmRequest; + }; + + UCHAR bRequest; + + union { + WORD_SPLIT wVal; + USHORT wValue; + }; + + union { + WORD_SPLIT wIndx; + USHORT wIndex; + }; + + union { + WORD_SPLIT wLen; + USHORT wLength; + }; + + ULONG ulTimeOut; + +} SETUP_PACKET, *PSETUP_PACKET; + +#define USB_ISO_ID 0x4945 +#define USB_ISO_CMD_ASAP 0x8000 +#define USB_ISO_CMD_CURRENT_FRAME 0x8001 +#define USB_ISO_CMD_SET_FRAME 0x8002 + +typedef struct _ISO_ADV_PARAMS { + + USHORT isoId; + USHORT isoCmd; + + ULONG ulParam1; + ULONG ulParam2; + +} ISO_ADV_PARAMS, *PISO_ADV_PARAMS; + +typedef struct _ISO_PACKET_INFO { + ULONG Status; + ULONG Length; +} ISO_PACKET_INFO, *PISO_PACKET_INFO; + + +typedef struct _SINGLE_TRANSFER { + union { + SETUP_PACKET SetupPacket; + ISO_ADV_PARAMS IsoParams; + }; + + UCHAR reserved; + + UCHAR ucEndpointAddress; + ULONG NtStatus; + ULONG UsbdStatus; + ULONG IsoPacketOffset; + ULONG IsoPacketLength; + ULONG BufferOffset; + ULONG BufferLength; +} SINGLE_TRANSFER, *PSINGLE_TRANSFER; + +#endif // #ifndef DRIVER + +typedef struct _SET_TRANSFER_SIZE_INFO { + UCHAR EndpointAddress; + ULONG TransferSize; +} SET_TRANSFER_SIZE_INFO, *PSET_TRANSFER_SIZE_INFO; + + +// +// Macro to extract function out of the device io control code +// +#ifdef WIN_98_DDK +#define DEVICE_TYPE_FROM_CTL_CODE(ctrlCode) (((ULONG)(ctrlCode & 0xffff0000)) >> 16) +#endif +#define FUNCTION_FROM_CTL_CODE(ctrlCode) (((ULONG)(ctrlCode & 0x00003FFC)) >> 2) +#define ACCESS_FROM_CTL_CODE(ctrlCode) (((ULONG)(ctrlCode & 0x000C0000)) >> 14) +//#define METHOD_FROM_CTL_CODE(ctrlCode) (((ULONG)(ctrlCode & 0x00000003))) + + +#define IOCTL_ADAPT_INDEX 0x0000 + +// Get the driver version +#define IOCTL_ADAPT_GET_DRIVER_VERSION CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Get the current USBDI version +#define IOCTL_ADAPT_GET_USBDI_VERSION CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+1, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Get the current device alt interface settings from driver +#define IOCTL_ADAPT_GET_ALT_INTERFACE_SETTING CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+2, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Set the device interface and alt interface setting +#define IOCTL_ADAPT_SELECT_INTERFACE CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+3, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Get device address from driver +#define IOCTL_ADAPT_GET_ADDRESS CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+4, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Get number of endpoints for current interface and alt interface setting from driver +#define IOCTL_ADAPT_GET_NUMBER_ENDPOINTS CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+5, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Get the current device power state +#define IOCTL_ADAPT_GET_DEVICE_POWER_STATE CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+6, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Set the device power state +#define IOCTL_ADAPT_SET_DEVICE_POWER_STATE CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+7, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Send a raw packet to endpoint 0 +#define IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+8, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Send/receive data to/from nonep0 +#define IOCTL_ADAPT_SEND_NON_EP0_TRANSFER CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+9, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Simulate a disconnect/reconnect +#define IOCTL_ADAPT_CYCLE_PORT CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+10, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Reset the pipe +#define IOCTL_ADAPT_RESET_PIPE CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+11, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Reset the device +#define IOCTL_ADAPT_RESET_PARENT_PORT CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+12, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Get the current transfer size of an endpoint (in number of bytes) +#define IOCTL_ADAPT_GET_TRANSFER_SIZE CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+13, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Set the transfer size of an endpoint (in number of bytes) +#define IOCTL_ADAPT_SET_TRANSFER_SIZE CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+14, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Return the name of the device +#define IOCTL_ADAPT_GET_DEVICE_NAME CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+15, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Return the "Friendly Name" of the device +#define IOCTL_ADAPT_GET_FRIENDLY_NAME CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+16, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Abort all outstanding transfers on the pipe +#define IOCTL_ADAPT_ABORT_PIPE CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+17, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Send/receive data to/from nonep0 w/ direct buffer acccess (no buffering) +#define IOCTL_ADAPT_SEND_NON_EP0_DIRECT CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+18, METHOD_NEITHER, FILE_ANY_ACCESS) + +// Return device speed +#define IOCTL_ADAPT_GET_DEVICE_SPEED CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+19, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// Get the current USB frame number +#define IOCTL_ADAPT_GET_CURRENT_FRAME CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_ADAPT_INDEX+20, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#define NUMBER_OF_ADAPT_IOCTLS 21 // Last IOCTL_ADAPT_INDEX + 1 + + +#include + +#endif // __IOCTL_H__ diff --git a/rx888_source/src/CyAPI/devioctl.h b/rx888_source/src/CyAPI/devioctl.h new file mode 100644 index 00000000..f10aa950 --- /dev/null +++ b/rx888_source/src/CyAPI/devioctl.h @@ -0,0 +1,184 @@ +/***************************************************************************** +* * +* OpenNI 1.x Alpha * +* Copyright (C) 2012 PrimeSense Ltd. * +* * +* This file is part of OpenNI. * +* * +* Licensed under the Apache License, Version 2.0 (the "License"); * +* you may not use this file except in compliance with the License. * +* You may obtain a copy of the License at * +* * +* http://www.apache.org/licenses/LICENSE-2.0 * +* * +* Unless required by applicable law or agreed to in writing, software * +* distributed under the License is distributed on an "AS IS" BASIS, * +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * +* See the License for the specific language governing permissions and * +* limitations under the License. * +* * +*****************************************************************************/ +/*++ BUILD Version: 0004 // Increment this if a change has global effects + +Copyright (c) 1992-1999 Microsoft Corporation + +Module Name: + + devioctl.h + +Abstract: + + This module contains + + +Revision History: + + +--*/ + +// begin_winioctl + +#ifndef _DEVIOCTL_ +#define _DEVIOCTL_ + +// begin_ntddk begin_wdm begin_nthal begin_ntifs +// +// Define the various device type values. Note that values used by Microsoft +// Corporation are in the range 0-32767, and 32768-65535 are reserved for use +// by customers. +// + +#define DEVICE_TYPE ULONG + +#define FILE_DEVICE_BEEP 0x00000001 +#define FILE_DEVICE_CD_ROM 0x00000002 +#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003 +#define FILE_DEVICE_CONTROLLER 0x00000004 +#define FILE_DEVICE_DATALINK 0x00000005 +#define FILE_DEVICE_DFS 0x00000006 +#define FILE_DEVICE_DISK 0x00000007 +#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008 +#define FILE_DEVICE_FILE_SYSTEM 0x00000009 +#define FILE_DEVICE_INPORT_PORT 0x0000000a +#define FILE_DEVICE_KEYBOARD 0x0000000b +#define FILE_DEVICE_MAILSLOT 0x0000000c +#define FILE_DEVICE_MIDI_IN 0x0000000d +#define FILE_DEVICE_MIDI_OUT 0x0000000e +#define FILE_DEVICE_MOUSE 0x0000000f +#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010 +#define FILE_DEVICE_NAMED_PIPE 0x00000011 +#define FILE_DEVICE_NETWORK 0x00000012 +#define FILE_DEVICE_NETWORK_BROWSER 0x00000013 +#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 +#define FILE_DEVICE_NULL 0x00000015 +#define FILE_DEVICE_PARALLEL_PORT 0x00000016 +#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017 +#define FILE_DEVICE_PRINTER 0x00000018 +#define FILE_DEVICE_SCANNER 0x00000019 +#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a +#define FILE_DEVICE_SERIAL_PORT 0x0000001b +#define FILE_DEVICE_SCREEN 0x0000001c +#define FILE_DEVICE_SOUND 0x0000001d +#define FILE_DEVICE_STREAMS 0x0000001e +#define FILE_DEVICE_TAPE 0x0000001f +#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020 +#define FILE_DEVICE_TRANSPORT 0x00000021 +#define FILE_DEVICE_UNKNOWN 0x00000022 +#define FILE_DEVICE_VIDEO 0x00000023 +#define FILE_DEVICE_VIRTUAL_DISK 0x00000024 +#define FILE_DEVICE_WAVE_IN 0x00000025 +#define FILE_DEVICE_WAVE_OUT 0x00000026 +#define FILE_DEVICE_8042_PORT 0x00000027 +#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028 +#define FILE_DEVICE_BATTERY 0x00000029 +#define FILE_DEVICE_BUS_EXTENDER 0x0000002a +#define FILE_DEVICE_MODEM 0x0000002b +#define FILE_DEVICE_VDM 0x0000002c +#define FILE_DEVICE_MASS_STORAGE 0x0000002d +#define FILE_DEVICE_SMB 0x0000002e +#define FILE_DEVICE_KS 0x0000002f +#define FILE_DEVICE_CHANGER 0x00000030 +#define FILE_DEVICE_SMARTCARD 0x00000031 +#define FILE_DEVICE_ACPI 0x00000032 +#define FILE_DEVICE_DVD 0x00000033 +#define FILE_DEVICE_FULLSCREEN_VIDEO 0x00000034 +#define FILE_DEVICE_DFS_FILE_SYSTEM 0x00000035 +#define FILE_DEVICE_DFS_VOLUME 0x00000036 +#define FILE_DEVICE_SERENUM 0x00000037 +#define FILE_DEVICE_TERMSRV 0x00000038 +#define FILE_DEVICE_KSEC 0x00000039 +#define FILE_DEVICE_FIPS 0x0000003A +#define FILE_DEVICE_INFINIBAND 0x0000003B +#define FILE_DEVICE_VMBUS 0x0000003E +#define FILE_DEVICE_CRYPT_PROVIDER 0x0000003F +#define FILE_DEVICE_WPD 0x00000040 +#define FILE_DEVICE_BLUETOOTH 0x00000041 +#define FILE_DEVICE_MT_COMPOSITE 0x00000042 +#define FILE_DEVICE_MT_TRANSPORT 0x00000043 +#define FILE_DEVICE_BIOMETRIC 0x00000044 +#define FILE_DEVICE_PMI 0x00000045 + +// +// Macro definition for defining IOCTL and FSCTL function control codes. Note +// that function codes 0-2047 are reserved for Microsoft Corporation, and +// 2048-4095 are reserved for customers. +// + +#define CTL_CODE( DeviceType, Function, Method, Access ) ( \ + ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ +) + +// +// Macro to extract device type out of the device io control code +// +#define DEVICE_TYPE_FROM_CTL_CODE(ctrlCode) (((ULONG)(ctrlCode & 0xffff0000)) >> 16) + +// +// Macro to extract buffering method out of the device io control code +// +#define METHOD_FROM_CTL_CODE(ctrlCode) ((ULONG)(ctrlCode & 3)) + +// +// Define the method codes for how buffers are passed for I/O and FS controls +// + +#define METHOD_BUFFERED 0 +#define METHOD_IN_DIRECT 1 +#define METHOD_OUT_DIRECT 2 +#define METHOD_NEITHER 3 + +// +// Define some easier to comprehend aliases: +// METHOD_DIRECT_TO_HARDWARE (writes, aka METHOD_IN_DIRECT) +// METHOD_DIRECT_FROM_HARDWARE (reads, aka METHOD_OUT_DIRECT) +// + +#define METHOD_DIRECT_TO_HARDWARE METHOD_IN_DIRECT +#define METHOD_DIRECT_FROM_HARDWARE METHOD_OUT_DIRECT + +// +// Define the access check value for any access +// +// +// The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in +// ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these +// constants *MUST* always be in sync. +// +// +// FILE_SPECIAL_ACCESS is checked by the NT I/O system the same as FILE_ANY_ACCESS. +// The file systems, however, may add additional access checks for I/O and FS controls +// that use this value. +// + + +#define FILE_ANY_ACCESS 0 +#define FILE_SPECIAL_ACCESS (FILE_ANY_ACCESS) +#define FILE_READ_ACCESS ( 0x0001 ) // file & pipe +#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe + +// end_ntddk end_wdm end_nthal end_ntifs + +#endif // _DEVIOCTL_ + +// end_winioctl + diff --git a/rx888_source/src/CyAPI/openFX3.cpp b/rx888_source/src/CyAPI/openFX3.cpp new file mode 100644 index 00000000..25e0f549 --- /dev/null +++ b/rx888_source/src/CyAPI/openFX3.cpp @@ -0,0 +1,208 @@ +// MIT License Copyright (c) 2016 Booya Corp. +// booyasdr@gmail.com, http://booyasdr.sf.net +// modified 2017 11 30 ik1xpv@gmail.com, http://www.steila.com/blog +#include + +#include +#include +#include +#include "openfx3.h" + +#include + +#define DbgPrintf spdlog::info + +using namespace std; + +void fx3Control(FX3Command command) { // firmware control + long lgt = 1; + UINT8 z = 0; // dummy data = 0 + fx3dev->ControlEndPt->ReqCode = command; + fx3dev->ControlEndPt->Write(&z, lgt); +} + +bool fx3Control(FX3Command command, PUINT8 data) { // firmware control BBRF + long lgt = 1; // default + bool r = false; + switch (command) + { + case GPIOFX3: + fx3dev->ControlEndPt->ReqCode = command; + fx3dev->ControlEndPt->Value = (USHORT)0; + fx3dev->ControlEndPt->Index = (USHORT)0; + lgt = 2; + DbgPrintf("GPIO %x %x\n", data[0], data[1]); + r = fx3dev->ControlEndPt->Write(data, lgt); + break; + case TESTFX3: + fx3dev->ControlEndPt->ReqCode = command; + fx3dev->ControlEndPt->Value = (USHORT)0; + fx3dev->ControlEndPt->Index = (USHORT)0; + lgt = 4; // TESTFX3 len + r = fx3dev->ControlEndPt->Read(data, lgt); + break; + default: + break; + } + if (r == false) + { + DbgPrintf("WARNING FX3FWControl failed %x .%x %x\n", r, command, *data); + closeFX3(); + } + return r; +} + + +bool fx3SendI2cbytes(UINT8 i2caddr, UINT8 regaddr, PUINT8 pdata, UINT8 len) +{ + bool r = false; + LONG lgt = len; + fx3dev->ControlEndPt->ReqCode = I2CWFX3; + fx3dev->ControlEndPt->Value = (USHORT)i2caddr; + fx3dev->ControlEndPt->Index = (USHORT)regaddr; + Sleep(10); + r = fx3dev->ControlEndPt->Write(pdata, lgt); + if (r == false) + DbgPrintf("\nWARNING fx3FWSendI2cbytes i2caddr 0x%02x regaddr 0x%02x 1data 0x%02x len 0x%02x \n", + i2caddr, regaddr, *pdata, len); + return r; +} + +bool fx3SendI2cbyte(UINT8 i2caddr, UINT8 regaddr, UINT8 data) +{ + return fx3SendI2cbytes(i2caddr, regaddr, &data, 1); +} + +bool fx3ReadI2cbytes(UINT8 i2caddr, UINT8 regaddr, PUINT8 pdata, UINT8 len) +{ + bool r = false; + LONG lgt = len; + WORD saveValue, saveIndex; + saveValue = fx3dev->ControlEndPt->Value; + saveIndex = fx3dev->ControlEndPt->Index; + + fx3dev->ControlEndPt->ReqCode = I2CRFX3; + fx3dev->ControlEndPt->Value = (USHORT)i2caddr; + fx3dev->ControlEndPt->Index = (USHORT)regaddr; + r = fx3dev->ControlEndPt->Read(pdata, lgt); + if (r == false) + printf("WARNING fx3FWReadI2cbytes failed %x : %02x %02x %02x %02x : %02x\n", r, I2CRFX3, i2caddr, regaddr, len, *pdata); + fx3dev->ControlEndPt->Value = saveValue; + fx3dev->ControlEndPt->Index = saveIndex; + return r; +} + +bool fx3ReadI2cbyte(UINT8 i2caddr, UINT8 regaddr, UINT8 data) +{ + return fx3ReadI2cbytes(i2caddr, regaddr, &data, 1); +} + +bool GetFx3Device(void); // open the device, called in initFX3() + +CCyFX3Device *fx3dev = NULL; +const int VENDOR_ID = 0x04B4; +const int STREAMER_ID = 0x00F1; +const int BOOTLOADER_ID = 0x00F3; +CCyUSBEndPoint *EndPt; +bool bHighSpeedDevice; +bool bSuperSpeedDevice; + +bool openFX3() { + bool r = false; + fx3dev = new CCyFX3Device; // instantiate the device + if (fx3dev == NULL) return 0; // return if failed + int n = fx3dev->DeviceCount(); // return if no devices connected + if (n == 0) { + DbgPrintf("Device Count = 0, Exit\n"); + return r; + } + if (!GetFx3Device()) { DbgPrintf("No streamer or boot device found, Exit\n"); return r; } + + char fwname[] = "rx888.img"; // firmware file + + if (!fx3dev->IsBootLoaderRunning()) { // if not bootloader device + fx3Control(RESETFX3); // reset the fx3 firmware via CyU3PDeviceReset(false) + DbgPrintf("Reset Device\n"); + Sleep(300); + fx3dev->Close(); // close class + delete fx3dev; // destroy class + Sleep(300); + fx3dev = new CCyFX3Device; // create class + GetFx3Device(); // open class + } + FX3_FWDWNLOAD_ERROR_CODE dlf = FAILED; + if (fx3dev->IsBootLoaderRunning()) { + dlf = fx3dev->DownloadFw(fwname, RAM); + Sleep(500); // wait for download to finish + } + if (dlf == 0) { + struct stat stbuf; + stat(fwname, &stbuf); + char *timestr; + timestr = ctime(&stbuf.st_mtime); + DbgPrintf("Loaded NEW FIRMWARE {0} {1}", fwname, timestr); + } + else if (dlf != 0) + { + DbgPrintf("OLD FIRMWARE\n"); + } + + GetFx3Device(); // open class with new firmware + if (!fx3dev->IsOpen()) { + DbgPrintf("Failed to open device\n"); + return r; + } + EndPt = fx3dev->BulkInEndPt; + if (!EndPt) { + DbgPrintf("No Bulk In end point\n"); + return r; // init failed + } + r = true; + return r; // init success + +} + +bool closeFX3() { + bool r = false; + fx3dev->Close(); // close class + delete fx3dev; // destroy class + Sleep(300); + return r; +} + +bool GetFx3Device() { // open class + + bool r = false; + if (fx3dev == NULL) return r; + int n = fx3dev->DeviceCount(); + // Walk through all devices looking for VENDOR_ID/STREAMER_ID + if (n == 0) { DbgPrintf("Device Count = 0, Exit\n"); return r; } + + fx3dev->Open(0); + // go down the list of devices to find our device + for (int i = 1; i <= n; i++) { + cout << hex << fx3dev->VendorID << " " + << hex << fx3dev->ProductID << " " << fx3dev->FriendlyName << '\n'; + if ((fx3dev->VendorID == VENDOR_ID) && (fx3dev->ProductID == STREAMER_ID)) + { + r = true; + break; + } + + if ((fx3dev->VendorID == VENDOR_ID) && (fx3dev->ProductID == BOOTLOADER_ID)) + { + r = true; + break; + } + + fx3dev->Open(i); + } + if (r == false) + fx3dev->Close(); + return r; +} + +bool fx3Check() +{ + return (fx3dev != NULL); +} diff --git a/rx888_source/src/CyAPI/openFX3.h b/rx888_source/src/CyAPI/openFX3.h new file mode 100644 index 00000000..b906798b --- /dev/null +++ b/rx888_source/src/CyAPI/openFX3.h @@ -0,0 +1,36 @@ +// MIT License Copyright (c) 2016 Booya Corp. +// booyasdr@gmail.com, http://booyasdr.sf.net +// modified 2017 11 30 ik1xpv@gmail.com, http://www.steila.com/blog + +#ifndef FX3DEV_H +#define FX3DEV_H + +#include +#include "CyAPI.h" + +#define PUINT8 UINT8* + +bool openFX3(void); +extern CCyFX3Device *fx3dev; +extern CCyUSBEndPoint *EndPt; +bool closeFX3(void); + +enum FX3Command { + STARTFX3 = 0xaa, + STOPFX3 = 0xab, + TESTFX3 = 0xac, + RESETFX3 = 0xcc, + PAUSEFX3 = 0xdd, + GPIOFX3 = 0xbc, + I2CWFX3 = 0xba, + I2CRFX3 = 0xbe +}; +void fx3Control(FX3Command command); +bool fx3Control(FX3Command command, PUINT8 data); +bool fx3SendI2cbytes(UINT8 i2caddr, UINT8 regaddr, PUINT8 pdata, UINT8 len); +bool fx3SendI2cbyte(UINT8 i2caddr, UINT8 regaddr, UINT8 pdata); +bool fx3ReadI2cbytes(UINT8 i2caddr, UINT8 regaddr, PUINT8 pdata, UINT8 len); +bool fx3ReadI2cbyte(UINT8 i2caddr, UINT8 regaddr, UINT8 pdata); +bool fx3Check(); + +#endif diff --git a/rx888_source/src/CyAPI/usb100.h b/rx888_source/src/CyAPI/usb100.h new file mode 100644 index 00000000..63c87b58 --- /dev/null +++ b/rx888_source/src/CyAPI/usb100.h @@ -0,0 +1,270 @@ +#ifndef __USB100_H__ +#define __USB100_H__ + + +#include + + +//bmRequest.Dir +#define BMREQUEST_HOST_TO_DEVICE 0 +#define BMREQUEST_DEVICE_TO_HOST 1 + +//bmRequest.Type +#define BMREQUEST_STANDARD 0 +#define BMREQUEST_CLASS 1 +#define BMREQUEST_VENDOR 2 + +//bmRequest.Recipient +#define BMREQUEST_TO_DEVICE 0 +#define BMREQUEST_TO_INTERFACE 1 +#define BMREQUEST_TO_ENDPOINT 2 +#define BMREQUEST_TO_OTHER 3 + + +#define MAXIMUM_USB_STRING_LENGTH 255 + +// values for the bits returned by the USB GET_STATUS command +#define USB_GETSTATUS_SELF_POWERED 0x01 +#define USB_GETSTATUS_REMOTE_WAKEUP_ENABLED 0x02 + + +#define USB_DEVICE_DESCRIPTOR_TYPE 0x01 +#define USB_CONFIGURATION_DESCRIPTOR_TYPE 0x02 +#define USB_STRING_DESCRIPTOR_TYPE 0x03 +#define USB_INTERFACE_DESCRIPTOR_TYPE 0x04 +#define USB_ENDPOINT_DESCRIPTOR_TYPE 0x05 + +// descriptor types defined by DWG documents +#define USB_RESERVED_DESCRIPTOR_TYPE 0x06 +#define USB_CONFIG_POWER_DESCRIPTOR_TYPE 0x07 +#define USB_INTERFACE_POWER_DESCRIPTOR_TYPE 0x08 + +#define USB_DESCRIPTOR_MAKE_TYPE_AND_INDEX(d, i) ((USHORT)((USHORT)d<<8 | i)) + +// +// Values for bmAttributes field of an +// endpoint descriptor +// + +#define USB_ENDPOINT_TYPE_MASK 0x03 + +#define USB_ENDPOINT_TYPE_CONTROL 0x00 +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01 +#define USB_ENDPOINT_TYPE_BULK 0x02 +#define USB_ENDPOINT_TYPE_INTERRUPT 0x03 + + +// +// definitions for bits in the bmAttributes field of a +// configuration descriptor. +// +#define USB_CONFIG_POWERED_MASK 0xc0 + +#define USB_CONFIG_BUS_POWERED 0x80 +#define USB_CONFIG_SELF_POWERED 0x40 +#define USB_CONFIG_REMOTE_WAKEUP 0x20 + +// +// Endpoint direction bit, stored in address +// + +#define USB_ENDPOINT_DIRECTION_MASK 0x80 + +// test direction bit in the bEndpointAddress field of +// an endpoint descriptor. +#define USB_ENDPOINT_DIRECTION_OUT(addr) (!((addr) & USB_ENDPOINT_DIRECTION_MASK)) +#define USB_ENDPOINT_DIRECTION_IN(addr) ((addr) & USB_ENDPOINT_DIRECTION_MASK) + +// +// USB defined request codes +// see chapter 9 of the USB 1.0 specifcation for +// more information. +// + +// These are the correct values based on the USB 1.0 +// specification + +#define USB_REQUEST_GET_STATUS 0x00 +#define USB_REQUEST_CLEAR_FEATURE 0x01 + +#define USB_REQUEST_SET_FEATURE 0x03 + +#define USB_REQUEST_SET_ADDRESS 0x05 +#define USB_REQUEST_GET_DESCRIPTOR 0x06 +#define USB_REQUEST_SET_DESCRIPTOR 0x07 +#define USB_REQUEST_GET_CONFIGURATION 0x08 +#define USB_REQUEST_SET_CONFIGURATION 0x09 +#define USB_REQUEST_GET_INTERFACE 0x0A +#define USB_REQUEST_SET_INTERFACE 0x0B +#define USB_REQUEST_SYNC_FRAME 0x0C + + +// +// defined USB device classes +// + + +#define USB_DEVICE_CLASS_RESERVED 0x00 +#define USB_DEVICE_CLASS_AUDIO 0x01 +#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02 +#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03 +#define USB_DEVICE_CLASS_MONITOR 0x04 +#define USB_DEVICE_CLASS_PHYSICAL_INTERFACE 0x05 +#define USB_DEVICE_CLASS_POWER 0x06 +#define USB_DEVICE_CLASS_PRINTER 0x07 +#define USB_DEVICE_CLASS_STORAGE 0x08 +#define USB_DEVICE_CLASS_HUB 0x09 +#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF + +// +// USB Core defined Feature selectors +// + +#define USB_FEATURE_ENDPOINT_STALL 0x0000 +#define USB_FEATURE_REMOTE_WAKEUP 0x0001 + +// +// USB DWG defined Feature selectors +// + +#define USB_FEATURE_INTERFACE_POWER_D0 0x0002 +#define USB_FEATURE_INTERFACE_POWER_D1 0x0003 +#define USB_FEATURE_INTERFACE_POWER_D2 0x0004 +#define USB_FEATURE_INTERFACE_POWER_D3 0x0005 + +typedef struct _USB_DEVICE_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + USHORT bcdUSB; + UCHAR bDeviceClass; + UCHAR bDeviceSubClass; + UCHAR bDeviceProtocol; + UCHAR bMaxPacketSize0; + USHORT idVendor; + USHORT idProduct; + USHORT bcdDevice; + UCHAR iManufacturer; + UCHAR iProduct; + UCHAR iSerialNumber; + UCHAR bNumConfigurations; +} USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR; + +typedef struct _USB_ENDPOINT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bEndpointAddress; + UCHAR bmAttributes; + USHORT wMaxPacketSize; + UCHAR bInterval; +} USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR; + +typedef struct _USB_CONFIGURATION_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + USHORT wTotalLength; + UCHAR bNumInterfaces; + UCHAR bConfigurationValue; + UCHAR iConfiguration; + UCHAR bmAttributes; + UCHAR MaxPower; +} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR; + +typedef struct _USB_INTERFACE_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bInterfaceNumber; + UCHAR bAlternateSetting; + UCHAR bNumEndpoints; + UCHAR bInterfaceClass; + UCHAR bInterfaceSubClass; + UCHAR bInterfaceProtocol; + UCHAR iInterface; +} USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR; + +typedef struct _USB_STRING_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + WCHAR bString[1]; +} USB_STRING_DESCRIPTOR, *PUSB_STRING_DESCRIPTOR; + +typedef struct _USB_COMMON_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; +} USB_COMMON_DESCRIPTOR, *PUSB_COMMON_DESCRIPTOR; + + +// +// Standard USB HUB definitions +// +// See Chapter 11 USB core specification +// + +typedef struct _USB_HUB_DESCRIPTOR { + UCHAR bDescriptorLength; // Length of this descriptor + UCHAR bDescriptorType; // Hub configuration type + UCHAR bNumberOfPorts; // number of ports on this hub + USHORT wHubCharacteristics; // Hub Charateristics + UCHAR bPowerOnToPowerGood; // port power on till power good in 2ms + UCHAR bHubControlCurrent; // max current in mA + // + // room for 255 ports power control and removable bitmask + UCHAR bRemoveAndPowerMask[64]; +} USB_HUB_DESCRIPTOR, *PUSB_HUB_DESCRIPTOR; + + +// +// Structures defined by various DWG feature documents +// + + +// +// See DWG USB Feature Specification: Interface Power Management +// + +#define USB_SUPPORT_D0_COMMAND 0x01 +#define USB_SUPPORT_D1_COMMAND 0x02 +#define USB_SUPPORT_D2_COMMAND 0x04 +#define USB_SUPPORT_D3_COMMAND 0x08 + +#define USB_SUPPORT_D1_WAKEUP 0x10 +#define USB_SUPPORT_D2_WAKEUP 0x20 + + +typedef struct _USB_CONFIGURATION_POWER_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR SelfPowerConsumedD0[3]; + UCHAR bPowerSummaryId; + UCHAR bBusPowerSavingD1; + UCHAR bSelfPowerSavingD1; + UCHAR bBusPowerSavingD2; + UCHAR bSelfPowerSavingD2; + UCHAR bBusPowerSavingD3; + UCHAR bSelfPowerSavingD3; + USHORT TransitionTimeFromD1; + USHORT TransitionTimeFromD2; + USHORT TransitionTimeFromD3; +} USB_CONFIGURATION_POWER_DESCRIPTOR, *PUSB_CONFIGURATION_POWER_DESCRIPTOR; + + +typedef struct _USB_INTERFACE_POWER_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bmCapabilitiesFlags; + UCHAR bBusPowerSavingD1; + UCHAR bSelfPowerSavingD1; + UCHAR bBusPowerSavingD2; + UCHAR bSelfPowerSavingD2; + UCHAR bBusPowerSavingD3; + UCHAR bSelfPowerSavingD3; + USHORT TransitionTimeFromD1; + USHORT TransitionTimeFromD2; + USHORT TransitionTimeFromD3; +} USB_INTERFACE_POWER_DESCRIPTOR, *PUSB_INTERFACE_POWER_DESCRIPTOR; + + +#include + + +#endif /* __USB100_H__ */ + diff --git a/rx888_source/src/CyAPI/usb200.h b/rx888_source/src/CyAPI/usb200.h new file mode 100644 index 00000000..c032c45c --- /dev/null +++ b/rx888_source/src/CyAPI/usb200.h @@ -0,0 +1,111 @@ +#ifndef __USB200_H__ +#define __USB200_H__ + +#include "usb100.h" + + +#include + +typedef enum _USB_DEVICE_SPEED { + UsbLowSpeed = 0, + UsbFullSpeed, + UsbHighSpeed +} USB_DEVICE_SPEED; + +typedef enum _USB_DEVICE_TYPE { + Usb11Device = 0, + Usb20Device +} USB_DEVICE_TYPE; + +// standard definiions for the port status +// word of the HUB port register + +#define USB_PORT_STATUS_CONNECT 0x0001 +#define USB_PORT_STATUS_ENABLE 0x0002 +#define USB_PORT_STATUS_SUSPEND 0x0004 +#define USB_PORT_STATUS_OVER_CURRENT 0x0008 +#define USB_PORT_STATUS_RESET 0x0010 +#define USB_PORT_STATUS_POWER 0x0100 +#define USB_PORT_STATUS_LOW_SPEED 0x0200 +#define USB_PORT_STATUS_HIGH_SPEED 0x0400 + +typedef union _BM_REQUEST_TYPE { + struct _BM { + UCHAR Recipient:2; + UCHAR Reserved:3; + UCHAR Type:2; + UCHAR Dir:1; + }; + UCHAR B; +} BM_REQUEST_TYPE, *PBM_REQUEST_TYPE; + +typedef struct _USB_DEFAULT_PIPE_SETUP_PACKET { + BM_REQUEST_TYPE bmRequestType; + UCHAR bRequest; + + union _wValue { + struct { + UCHAR LowByte; + UCHAR HiByte; + }; + USHORT W; + } wValue; + + union _wIndex { + struct { + UCHAR LowByte; + UCHAR HiByte; + }; + USHORT W; + } wIndex; + USHORT wLength; +} USB_DEFAULT_PIPE_SETUP_PACKET, *PUSB_DEFAULT_PIPE_SETUP_PACKET; + +// setup packet is eight bytes -- defined by spec +C_ASSERT(sizeof(USB_DEFAULT_PIPE_SETUP_PACKET) == 8); + + +#define USB_DEVICE_QUALIFIER_DESCRIPTOR_TYPE 0x06 + +typedef struct _USB_DEVICE_QUALIFIER_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + USHORT bcdUSB; + UCHAR bDeviceClass; + UCHAR bDeviceSubClass; + UCHAR bDeviceProtocol; + UCHAR bMaxPacketSize0; + UCHAR bNumConfigurations; + UCHAR bReserved; +} USB_DEVICE_QUALIFIER_DESCRIPTOR, *PUSB_DEVICE_QUALIFIER_DESCRIPTOR; + + +typedef union _USB_HIGH_SPEED_MAXPACKET { + struct _MP { + USHORT MaxPacket:11; /* 0..10 */ + USHORT HSmux:2; /* 11..12 */ + USHORT Reserved:3; /* 13..15 */ + }; + USHORT us; +} USB_HIGH_SPEED_MAXPACKET, *PUSB_HIGH_SPEED_MAXPACKET; + +#define USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE 0x0B + +typedef struct _USB_INTERFACE_ASSOCIATION_DESCRIPTOR { + + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bFirstInterface; + UCHAR bInterfaceCount; + UCHAR bFunctionClass; + UCHAR bFunctionSubClass; + UCHAR bFunctionProtocol; + UCHAR iFunction; + +} USB_INTERFACE_ASSOCIATION_DESCRIPTOR, *PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR; + + +#include + +#endif // __USB200_H__ + diff --git a/rx888_source/src/main.cpp b/rx888_source/src/main.cpp new file mode 100644 index 00000000..ac4d4ceb --- /dev/null +++ b/rx888_source/src/main.cpp @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define CONCAT(a, b) ((std::string(a) + b).c_str()) + +#define SEL0 (8) // SEL0 GPIO26 +#define SEL1 (16) // SEL1 GPIO27 + +MOD_INFO { + /* Name: */ "rx888_source", + /* Description: */ "RX888 input module for SDR++", + /* Author: */ "Ryzerth", + /* Version: */ "0.1.0" +}; + +class RX888SourceModule { +public: + RX888SourceModule(std::string name) { + this->name = name; + + if (!openFX3()) { + spdlog::error("No RX888 found!"); + return; + } + + Si5351init(); + + sampleRate = 8000000; + + handler.ctx = this; + handler.selectHandler = menuSelected; + handler.deselectHandler = menuDeselected; + handler.menuHandler = menuHandler; + handler.startHandler = start; + handler.stopHandler = stop; + handler.tuneHandler = tune; + handler.stream = &stream; + sigpath::sourceManager.registerSource("RX888", &handler); + + spdlog::info("RX888SourceModule '{0}': Instance created!", name); + } + + ~RX888SourceModule() { + spdlog::info("RX888SourceModule '{0}': Instance deleted!", name); + } + +private: + + static void menuSelected(void* ctx) { + RX888SourceModule* _this = (RX888SourceModule*)ctx; + spdlog::info("RX888SourceModule '{0}': Menu Select!", _this->name); + + core::setInputSampleRate(_this->sampleRate); + } + + static void menuDeselected(void* ctx) { + RX888SourceModule* _this = (RX888SourceModule*)ctx; + spdlog::info("RX888SourceModule '{0}': Menu Deselect!", _this->name); + } + + static void start(void* ctx) { + RX888SourceModule* _this = (RX888SourceModule*)ctx; + + _this->doStart(); + + spdlog::info("RX888SourceModule '{0}': Start!", _this->name); + } + + void doStart() { + uint8_t Bgpio[2]; + Bgpio[0] = 0x17 | SEL0 & (~SEL1); + Bgpio[1] = 0x00; + + si5351aSetFrequency(sampleRate * 2, 0); + fx3Control(GPIOFX3, Bgpio); + + running = true; + workerThread = std::thread(_worker, this); + } + + static void stop(void* ctx) { + RX888SourceModule* _this = (RX888SourceModule*)ctx; + _this->running = false; + _this->workerThread.join(); + spdlog::info("RX888SourceModule '{0}': Stop!", _this->name); + } + + static void tune(double freq, void* ctx) { + RX888SourceModule* _this = (RX888SourceModule*)ctx; + _this->freq = freq; + + spdlog::info("RX888SourceModule '{0}': Tune: {1}!", _this->name, freq); + } + + + static void menuHandler(void* ctx) { + RX888SourceModule* _this = (RX888SourceModule*)ctx; + + ImGui::Text("RX888 source"); + } + + static void _worker(RX888SourceModule* _this) { + int blockSize = _this->sampleRate / 200.0f; + if ((blockSize % 2) != 0) { blockSize++; } + int flags = 0; + long long timeMs = 0; + + int16_t* buffer = new int16_t[blockSize * 2]; + + long pktSize = EndPt->MaxPktSize; + EndPt->SetXferSize(blockSize * 2); + long ppx = blockSize * 2 / pktSize; + + OVERLAPPED inOvLap; + inOvLap.hEvent = CreateEvent(NULL, false, false, NULL); + auto context = EndPt->BeginDataXfer((PUCHAR)buffer, blockSize, &inOvLap); + + fx3Control(STARTFX3); + + while (_this->running) { + //if (_this->stream.aquire() < 0) { break; } + + + LONG rLen = blockSize * 2; + if (!EndPt->WaitForXfer(&inOvLap, 5000)) { + spdlog::error("Transfer aborted"); + EndPt->Abort(); + if (EndPt->LastError == ERROR_IO_PENDING) { + WaitForSingleObject(inOvLap.hEvent, 5000); + } + break; + } + + if (EndPt->Attributes == 2) { + if (EndPt->FinishDataXfer((PUCHAR)buffer, rLen, &inOvLap, context)) { + spdlog::warn("{0}", rLen); + } + } + + context = EndPt->BeginDataXfer((PUCHAR)buffer, blockSize, &inOvLap); + } + + delete[] buffer; + } + + std::string name; + dsp::stream stream; + SourceManager::SourceHandler handler; + std::thread workerThread; + double freq; + double sampleRate; + bool running = false; +}; + +MOD_EXPORT void _INIT_() { + +} + +MOD_EXPORT void* _CREATE_INSTANCE_(std::string name) { + return new RX888SourceModule(name); +} + +MOD_EXPORT void _DELETE_INSTANCE_(void* instance) { + delete (RX888SourceModule*)instance; +} + +MOD_EXPORT void _STOP_() { + +} \ No newline at end of file