mirror of
https://github.com/Lorenzooone/cc3dsfs.git
synced 2026-09-13 02:55:19 -05:00
Implement Old DS Nisetro Capture
This commit is contained in:
@@ -10,10 +10,11 @@ set(N3DSXL_LOOPY_SUPPORT 1)
|
||||
set(NEW_DS_LOOPY_SUPPORT 1)
|
||||
set(IS_DEVICES_SUPPORT 1)
|
||||
set(OLD_DS_3DS_LOOPY_SUPPORT 1)
|
||||
set(CYPRESS_NISETRO_SUPPORT 1)
|
||||
|
||||
set(USE_FTD2XX_FOR_NEW_DS_LOOPY ${NEW_DS_LOOPY_SUPPORT})
|
||||
set(USE_LIBFTDI_FOR_NEW_DS_LOOPY ${NEW_DS_LOOPY_SUPPORT})
|
||||
set(USE_LIBUSB_SUPPORT ${IS_DEVICES_SUPPORT} OR ${OLD_DS_3DS_LOOPY_SUPPORT} OR ${USE_LIBFTDI_FOR_NEW_DS_LOOPY})
|
||||
set(USE_LIBUSB_SUPPORT ${IS_DEVICES_SUPPORT} OR ${OLD_DS_3DS_LOOPY_SUPPORT} OR ${USE_LIBFTDI_FOR_NEW_DS_LOOPY} OR ${CYPRESS_NISETRO_SUPPORT})
|
||||
if(NOT (${CMAKE_SYSTEM_NAME} STREQUAL "Windows"))
|
||||
#Performance outside of Windows is very bad for the official drivers...
|
||||
set(USE_FTD2XX_FOR_NEW_DS_LOOPY 0)
|
||||
@@ -293,6 +294,7 @@ set(EXTRA_DEPENDENCIES "")
|
||||
set(SOURCE_CPP_DEVICE_FILES_BASE_PATH "source/CaptureDeviceSpecific")
|
||||
set(SOURCE_CPP_IS_DEVICES_FILES_BASE_PATH "${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/ISDevices")
|
||||
set(SOURCE_CPP_FTD2_FILES_BASE_PATH "${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/DSCapture_FTD2")
|
||||
set(SOURCE_CPP_CYPRESS_NISETRO_DEVICES_FILES_BASE_PATH "${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/Nisetro")
|
||||
if(N3DSXL_LOOPY_SUPPORT)
|
||||
list(APPEND FETCH_CONTENT_MAKE_AVAILABLE_LIBRARIES FTD3XX)
|
||||
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/3dscapture_ftd3.cpp)
|
||||
@@ -328,6 +330,14 @@ if(OLD_DS_3DS_LOOPY_SUPPORT)
|
||||
list(APPEND EXTRA_CXX_FLAGS "-DUSE_DS_3DS_USB")
|
||||
endif()
|
||||
endif()
|
||||
if(CYPRESS_NISETRO_SUPPORT)
|
||||
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_CYPRESS_NISETRO_DEVICES_FILES_BASE_PATH}/cypress_nisetro_driver_comms.cpp ${SOURCE_CPP_CYPRESS_NISETRO_DEVICES_FILES_BASE_PATH}/cypress_nisetro_libusb_comms.cpp ${SOURCE_CPP_CYPRESS_NISETRO_DEVICES_FILES_BASE_PATH}/cypress_nisetro_communications.cpp ${SOURCE_CPP_CYPRESS_NISETRO_DEVICES_FILES_BASE_PATH}/cypress_nisetro_acquisition.cpp ${TOOLS_DATA_DIR}/nisetro_ds_fw.cpp)
|
||||
if(MSVC)
|
||||
list(APPEND EXTRA_CXX_FLAGS "/DUSE_CYNI_USB")
|
||||
else()
|
||||
list(APPEND EXTRA_CXX_FLAGS "-DUSE_CYNI_USB")
|
||||
endif()
|
||||
endif()
|
||||
if(NEW_DS_LOOPY_SUPPORT)
|
||||
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_FTD2_FILES_BASE_PATH}/dscapture_ftd2_shared.cpp ${SOURCE_CPP_FTD2_FILES_BASE_PATH}/dscapture_ftd2_compatibility.cpp ${TOOLS_DATA_DIR}/ftd2_ds2_fw_1.cpp ${TOOLS_DATA_DIR}/ftd2_ds2_fw_2.cpp)
|
||||
if(MSVC)
|
||||
@@ -475,9 +485,9 @@ execute_process(COMMAND ${CMAKE_COMMAND} --build ${TOOLS_DATA_DIR})
|
||||
set(OUTPUT_NAME cc3dsfs)
|
||||
|
||||
if(MSVC)
|
||||
set_source_files_properties(source/conversions.cpp PROPERTIES COMPILE_OPTIONS "/O2")
|
||||
set_source_files_properties(source/conversions.cpp PROPERTIES COMPILE_OPTIONS "$<$<CONFIG:Release>:/O2>")
|
||||
else()
|
||||
set_source_files_properties(source/conversions.cpp PROPERTIES COMPILE_OPTIONS "-O3")
|
||||
set_source_files_properties(source/conversions.cpp PROPERTIES COMPILE_OPTIONS "$<$<CONFIG:Release>:-O3>")
|
||||
endif()
|
||||
add_executable(${OUTPUT_NAME} source/cc3dsfs.cpp source/utils.cpp source/audio_data.cpp source/audio.cpp source/frontend.cpp source/TextRectangle.cpp source/WindowScreen.cpp source/WindowScreen_Menu.cpp source/devicecapture.cpp source/conversions.cpp source/ExtraButtons.cpp source/Menus/ConnectionMenu.cpp source/Menus/OptionSelectionMenu.cpp source/Menus/MainMenu.cpp source/Menus/VideoMenu.cpp source/Menus/CropMenu.cpp source/Menus/PARMenu.cpp source/Menus/RotationMenu.cpp source/Menus/OffsetMenu.cpp source/Menus/AudioMenu.cpp source/Menus/BFIMenu.cpp source/Menus/RelativePositionMenu.cpp source/Menus/ResolutionMenu.cpp source/Menus/FileConfigMenu.cpp source/Menus/ExtraSettingsMenu.cpp source/Menus/StatusMenu.cpp source/Menus/LicenseMenu.cpp source/WindowCommands.cpp source/Menus/ShortcutMenu.cpp source/Menus/ActionSelectionMenu.cpp source/Menus/ScalingRatioMenu.cpp source/Menus/ISNitroMenu.cpp source/Menus/VideoEffectsMenu.cpp source/CaptureDataBuffers.cpp source/Menus/InputMenu.cpp ${TOOLS_DATA_DIR}/font_ttf.cpp ${TOOLS_DATA_DIR}/shaders_list.cpp ${SOURCE_CPP_EXTRA_FILES})
|
||||
|
||||
@@ -498,7 +508,7 @@ endif()
|
||||
if(USE_FTD2XX_FOR_NEW_DS_LOOPY)
|
||||
target_link_libraries(${OUTPUT_NAME} PRIVATE ${ftd2xx_BINARY_DIR}/${FTD2XX_SUBFOLDER}/${FTD2XX_LIB})
|
||||
endif()
|
||||
target_include_directories(${OUTPUT_NAME} PRIVATE ${EXTRA_INCLUDE_DIRECTORIES} ${TOOLS_DATA_DIR} ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include/Menus ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific/ISDevices ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific/DSCapture_FTD2 ${libftdi1_SOURCE_DIR}/src)
|
||||
target_include_directories(${OUTPUT_NAME} PRIVATE ${EXTRA_INCLUDE_DIRECTORIES} ${TOOLS_DATA_DIR} ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include/Menus ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific/ISDevices ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific/Nisetro ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific/DSCapture_FTD2 ${libftdi1_SOURCE_DIR}/src)
|
||||
target_compile_features(${OUTPUT_NAME} PRIVATE cxx_std_20)
|
||||
target_compile_options(${OUTPUT_NAME} PRIVATE ${EXTRA_CXX_FLAGS})
|
||||
|
||||
@@ -537,6 +547,13 @@ add_custom_command(
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/bin/ftd2_ds2_fw_2.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION}
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${TOOLS_DATA_DIR}/nisetro_ds_fw.cpp
|
||||
COMMENT "Convert fw binary to C - Nisetro DS"
|
||||
COMMAND ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/bin/nisetro_ds_fw.bin ${TOOLS_DATA_DIR} nisetro_ds_fw nisetro_ds_fw
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/bin/nisetro_ds_fw.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION}
|
||||
)
|
||||
|
||||
set(SHADERS_LIST "")
|
||||
list(APPEND SHADERS_LIST ${CMAKE_SOURCE_DIR}/shaders/bit_crusher_fragment_shader.2_to_x_1_7.frag ${CMAKE_SOURCE_DIR}/shaders/bit_merger_crusher_fragment_shader.2_to_x_1_6.frag ${CMAKE_SOURCE_DIR}/shaders/bit_merger_crusher_fragment_shader_7.frag ${CMAKE_SOURCE_DIR}/shaders/bit_merger_fragment_shader.2_to_x_0_6.frag ${CMAKE_SOURCE_DIR}/shaders/bit_merger_fragment_shader_7.frag ${CMAKE_SOURCE_DIR}/shaders/frame_blending_bit_crusher_fragment_shader.2_to_x_1_7.frag ${CMAKE_SOURCE_DIR}/shaders/frame_blending_fragment_shader.frag ${CMAKE_SOURCE_DIR}/shaders/no_effect_fragment_shader.frag)
|
||||
|
||||
@@ -606,6 +623,7 @@ else()
|
||||
install(FILES ${USB_RULES_DIR}/51-istwl.rules DESTINATION .)
|
||||
install(FILES ${USB_RULES_DIR}/50-ftd2xx.rules DESTINATION .)
|
||||
install(FILES ${USB_RULES_DIR}/51-ftd2xx.rules DESTINATION .)
|
||||
install(FILES ${USB_RULES_DIR}/51-nisetro.rules DESTINATION .)
|
||||
install(FILES ${SETUP_SCRIPTS_DIR}/install_usb_rules${SCRIPT_EXTENSION} DESTINATION .)
|
||||
endif()
|
||||
|
||||
|
||||
BIN
bin/nisetro_ds_fw.bin
Normal file
BIN
bin/nisetro_ds_fw.bin
Normal file
Binary file not shown.
@@ -0,0 +1,20 @@
|
||||
#ifndef __CYPRESS_NISETRO_ACQUISITION_HPP
|
||||
#define __CYPRESS_NISETRO_ACQUISITION_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "utils.hpp"
|
||||
#include "hw_defs.hpp"
|
||||
#include "capture_structs.hpp"
|
||||
#include "display_structs.hpp"
|
||||
#include "devicecapture.hpp"
|
||||
|
||||
void list_devices_cyni_device(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list);
|
||||
bool cyni_device_connect_usb(bool print_failed, CaptureData* capture_data, CaptureDevice* device);
|
||||
uint64_t cyni_device_get_video_in_size(CaptureStatus* status);
|
||||
uint64_t cyni_device_get_video_in_size(CaptureData* capture_data);
|
||||
void cyni_device_acquisition_main_loop(CaptureData* capture_data);
|
||||
void usb_cyni_device_acquisition_cleanup(CaptureData* capture_data);
|
||||
void usb_cyni_device_init();
|
||||
void usb_cyni_device_close();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef __CYPRESS_NISETRO_ACQUISITION_GENERAL_HPP
|
||||
#define __CYPRESS_NISETRO_ACQUISITION_GENERAL_HPP
|
||||
|
||||
#include "cypress_nisetro_communications.hpp"
|
||||
|
||||
#define NUM_CAPTURE_RECEIVED_DATA_BUFFERS 4
|
||||
|
||||
struct CypressDeviceCaptureReceivedData {
|
||||
volatile bool in_use;
|
||||
uint32_t index;
|
||||
CaptureReceived buffer;
|
||||
SharedConsumerMutex* is_buffer_free_shared_mutex;
|
||||
size_t* scheduled_special_read;
|
||||
uint32_t* active_special_read_index;
|
||||
bool* is_active_special_read;
|
||||
bool* recalibration_request;
|
||||
int* status;
|
||||
uint32_t* last_index;
|
||||
int* errors_since_last_output;
|
||||
int* consecutive_output_to_thread;
|
||||
CaptureData* capture_data;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start;
|
||||
CaptureScreensType curr_capture_type;
|
||||
cyni_async_callback_data cb_data;
|
||||
};
|
||||
|
||||
std::string get_serial(const cyni_device_usb_device* usb_device_desc, std::string serial, uint16_t bcd_device, int& curr_serial_extra_id);
|
||||
CaptureDevice cypress_create_device(const cyni_device_usb_device* usb_device_desc, std::string serial, std::string path);
|
||||
CaptureDevice cypress_create_device(const cyni_device_usb_device* usb_device_desc, std::string serial);
|
||||
void cypress_insert_device(std::vector<CaptureDevice>& devices_list, const cyni_device_usb_device* usb_device_desc, std::string serial, uint16_t bcd_device, int& curr_serial_extra_id, std::string path);
|
||||
void cypress_insert_device(std::vector<CaptureDevice>& devices_list, const cyni_device_usb_device* usb_device_desc, std::string serial, uint16_t bcd_device, int& curr_serial_extra_id);
|
||||
void cypress_output_to_thread(CaptureData* capture_data, CaptureReceived* capture_buf, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start, size_t read_size);
|
||||
int cypress_device_read_frame_and_output(CaptureData* capture_data, CaptureReceived* capture_buf, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock> &clock_start);
|
||||
int cypress_device_read_frame_request(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, CaptureScreensType curr_capture_type, uint32_t index);
|
||||
int cypress_device_get_num_free_buffers(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data);
|
||||
void wait_all_cypress_device_buffers_free(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data);
|
||||
void wait_one_cypress_device_buffer_free(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data);
|
||||
bool cypress_device_are_buffers_all_free(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data);
|
||||
CypressDeviceCaptureReceivedData* cypress_device_get_free_buffer(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data);
|
||||
int get_cypress_device_status(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data);
|
||||
void error_cypress_device_status(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, int error_val);
|
||||
void reset_cypress_device_status(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,84 @@
|
||||
#ifndef __CYPRESS_NISETRO_DEVICE_COMMUNICATIONS_HPP
|
||||
#define __CYPRESS_NISETRO_DEVICE_COMMUNICATIONS_HPP
|
||||
|
||||
#include <libusb.h>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
#include "utils.hpp"
|
||||
#include "capture_structs.hpp"
|
||||
|
||||
enum cypress_nisetro_device_type {
|
||||
CYPRESS_NISETRO_BLANK_DEVICE,
|
||||
CYPRESS_NISETRO_DS_DEVICE,
|
||||
};
|
||||
|
||||
typedef void (*cyni_async_callback_function)(void* user_data, int transfer_length, int transfer_status);
|
||||
|
||||
struct cyni_async_callback_data {
|
||||
cyni_async_callback_function function;
|
||||
void* actual_user_data;
|
||||
void* transfer_data;
|
||||
void* handle;
|
||||
void* extra_transfer_data;
|
||||
void* base_transfer_data;
|
||||
std::mutex transfer_data_access;
|
||||
SharedConsumerMutex* is_transfer_done_mutex;
|
||||
SharedConsumerMutex* is_transfer_data_ready_mutex;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> start_request;
|
||||
float timeout_s;
|
||||
size_t requested_length;
|
||||
uint8_t* buffer;
|
||||
size_t actual_length;
|
||||
int status_value;
|
||||
int internal_index;
|
||||
bool is_data_ready;
|
||||
};
|
||||
|
||||
struct cyni_device_usb_device {
|
||||
std::string name;
|
||||
std::string long_name;
|
||||
int vid;
|
||||
int pid;
|
||||
int default_config;
|
||||
int default_interface;
|
||||
int bulk_timeout;
|
||||
int ep_ctrl_bulk_in;
|
||||
int ep_ctrl_bulk_out;
|
||||
int ep_bulk_in;
|
||||
cypress_nisetro_device_type device_type;
|
||||
InputVideoDataType video_data_type;
|
||||
size_t max_usb_packet_size;
|
||||
bool do_pipe_clear_reset;
|
||||
uint8_t* firmware_to_load;
|
||||
size_t firmware_size;
|
||||
cypress_nisetro_device_type next_device;
|
||||
bool has_bcd_device_serial;
|
||||
int alt_interface;
|
||||
};
|
||||
|
||||
struct cyni_device_device_handlers {
|
||||
libusb_device_handle* usb_handle;
|
||||
void* read_handle;
|
||||
void* write_handle;
|
||||
void* mutex;
|
||||
std::string path;
|
||||
};
|
||||
|
||||
int GetNumCyNiDeviceDesc(void);
|
||||
const cyni_device_usb_device* GetCyNiDeviceDesc(int index);const cyni_device_usb_device* GetNextDeviceDesc(const cyni_device_usb_device* device);
|
||||
const cyni_device_usb_device* GetNextDeviceDesc(const cyni_device_usb_device* device);
|
||||
bool has_to_load_firmware(const cyni_device_usb_device* device);
|
||||
bool load_firmware(cyni_device_device_handlers* handlers, const cyni_device_usb_device* device, uint8_t patch_id);
|
||||
int capture_start(cyni_device_device_handlers* handlers, const cyni_device_usb_device* device);
|
||||
int StartCaptureDma(cyni_device_device_handlers* handlers, const cyni_device_usb_device* device);
|
||||
int capture_end(cyni_device_device_handlers* handlers, const cyni_device_usb_device* device);
|
||||
int ReadFrame(cyni_device_device_handlers* handlers, uint8_t* buf, int length, const cyni_device_usb_device* device_desc);
|
||||
int ReadFrameAsync(cyni_device_device_handlers* handlers, uint8_t* buf, int length, const cyni_device_usb_device* device_desc, cyni_async_callback_data* cb_data);
|
||||
void CloseAsyncRead(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, cyni_async_callback_data* cb_data);
|
||||
void SetupCypressDeviceAsyncThread(cyni_device_device_handlers* handlers, void* user_data, std::thread* thread_ptr, bool* keep_going, ConsumerMutex* is_data_ready);
|
||||
void EndCypressDeviceAsyncThread(cyni_device_device_handlers* handlers, void* user_data, std::thread* thread_ptr, bool* keep_going, ConsumerMutex* is_data_ready);
|
||||
void SetMaxTransferSize(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, size_t new_max_transfer_size);
|
||||
void pipe_reset_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef __CYPRESS_NISETRO_DRIVER_COMMS_HPP
|
||||
#define __CYPRESS_NISETRO_DRIVER_COMMS_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "capture_structs.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "cypress_nisetro_communications.hpp"
|
||||
#include "cypress_nisetro_acquisition_general.hpp"
|
||||
|
||||
void cypress_driver_list_devices(std::vector<CaptureDevice>& devices_list, bool* not_supported_elems, int* curr_serial_extra_id_cypress, const size_t num_cypress_desc);
|
||||
void cypress_driver_find_used_serial(const cyni_device_usb_device* usb_device_desc, bool* found, size_t num_free_fw_ids, int &curr_serial_extra_id);
|
||||
void cypress_nisetro_driver_end_connection(cyni_device_device_handlers* handlers);
|
||||
int cypress_driver_ctrl_transfer_in(cyni_device_device_handlers* handlers, uint8_t* buffer, size_t inner_size, uint16_t value, uint16_t index, uint16_t request_code, int* num_read);
|
||||
int cypress_driver_ctrl_transfer_out(cyni_device_device_handlers* handlers, uint8_t* buffer, size_t inner_size, uint16_t value, uint16_t index, uint16_t request_code, int* num_read);
|
||||
int cypress_driver_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred);
|
||||
int cypress_driver_ctrl_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred);
|
||||
int cypress_driver_ctrl_bulk_out(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred);
|
||||
void cypress_driver_pipe_reset_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc);
|
||||
void cypress_driver_pipe_reset_ctrl_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc);
|
||||
void cypress_driver_pipe_reset_ctrl_bulk_out(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc);
|
||||
cyni_device_device_handlers* cypress_driver_serial_reconnection(CaptureDevice* device);
|
||||
cyni_device_device_handlers* cypress_driver_find_by_serial_number(const cyni_device_usb_device* usb_device_desc, std::string wanted_serial_number, int &curr_serial_extra_id, CaptureDevice* new_device);
|
||||
int cypress_driver_async_in_start(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, cyni_async_callback_data* cb_data);
|
||||
void cypress_driver_start_thread(std::thread* thread_ptr, bool* usb_thread_run, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, cyni_device_device_handlers* handlers, ConsumerMutex* AsyncMutexPtr);
|
||||
void cypress_driver_close_thread(std::thread* thread_ptr, bool* usb_thread_run, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data);
|
||||
void cypress_driver_cancel_callback(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, cyni_async_callback_data* cb_data);
|
||||
void cypress_driver_set_transfer_size_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, size_t new_transfer_size);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef __CYPRESS_NISETRO_DEVICE_LIBUSB_HPP
|
||||
#define __CYPRESS_NISETRO_DEVICE_LIBUSB_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "capture_structs.hpp"
|
||||
#include "cypress_nisetro_communications.hpp"
|
||||
|
||||
void cypress_libusb_start_thread(std::thread* thread_ptr, bool* usb_thread_run);
|
||||
void cypress_libusb_close_thread(std::thread* thread_ptr, bool* usb_thread_run);
|
||||
void cypress_libusb_list_devices(std::vector<CaptureDevice> &devices_list, bool* no_access_elems, bool* not_supported_elems, int *curr_serial_extra_id_cypress, const size_t num_cypress_desc);
|
||||
cyni_device_device_handlers* cypress_libusb_serial_reconnection(const cyni_device_usb_device* usb_device_desc, std::string wanted_serial_number, int &curr_serial_extra_id, CaptureDevice* new_device);
|
||||
void cypress_libusb_find_used_serial(const cyni_device_usb_device* usb_device_desc, bool* found, size_t num_free_fw_ids, int &curr_serial_extra_id);
|
||||
void cypress_libusb_end_connection(cyni_device_device_handlers* handlers, const cyni_device_usb_device* device_desc, bool interface_claimed);
|
||||
int cypress_libusb_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred);
|
||||
int cypress_libusb_ctrl_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred);
|
||||
int cypress_libusb_ctrl_bulk_out(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred);
|
||||
void cypress_libusb_pipe_reset_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc);
|
||||
void cypress_libusb_pipe_reset_ctrl_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc);
|
||||
void cypress_libusb_pipe_reset_ctrl_bulk_out(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc);
|
||||
int cypress_libusb_ctrl_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, uint8_t request, uint16_t value, uint16_t index, int* transferred);
|
||||
int cypress_libusb_ctrl_out(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, uint8_t request, uint16_t value, uint16_t index, int* transferred);
|
||||
int cypress_libusb_async_in_start(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, cyni_async_callback_data* cb_data);
|
||||
void cypress_libusb_cancell_callback(cyni_async_callback_data* cb_data);
|
||||
|
||||
#endif
|
||||
@@ -20,7 +20,7 @@
|
||||
#define FTD2_INTRA_PACKET_HEADER_SIZE 2
|
||||
#define MAX_PACKET_SIZE_FTD2 (MAX_PACKET_SIZE_USB2 - FTD2_INTRA_PACKET_HEADER_SIZE)
|
||||
|
||||
enum CaptureConnectionType { CAPTURE_CONN_FTD3, CAPTURE_CONN_USB, CAPTURE_CONN_FTD2, CAPTURE_CONN_IS_NITRO };
|
||||
enum CaptureConnectionType { CAPTURE_CONN_FTD3, CAPTURE_CONN_USB, CAPTURE_CONN_FTD2, CAPTURE_CONN_IS_NITRO, CAPTURE_CONN_CYPRESS_NISETRO };
|
||||
enum InputVideoDataType { VIDEO_DATA_RGB, VIDEO_DATA_BGR, VIDEO_DATA_RGB16, VIDEO_DATA_BGR16 };
|
||||
enum CaptureScreensType { CAPTURE_SCREENS_BOTH, CAPTURE_SCREENS_TOP, CAPTURE_SCREENS_BOTTOM, CAPTURE_SCREENS_ENUM_END };
|
||||
enum CaptureSpeedsType { CAPTURE_SPEEDS_FULL, CAPTURE_SPEEDS_HALF, CAPTURE_SPEEDS_THIRD, CAPTURE_SPEEDS_QUARTER, CAPTURE_SPEEDS_ENUM_END };
|
||||
@@ -118,6 +118,10 @@ struct ALIGNED(16) PACKED ISNitroCaptureReceived {
|
||||
ISNitroEmulatorVideoInputData video_in;
|
||||
};
|
||||
|
||||
struct ALIGNED(16) PACKED CypressNisetroDSCaptureReceived {
|
||||
ISNitroEmulatorVideoInputData video_in;
|
||||
};
|
||||
|
||||
struct ALIGNED(16) PACKED ISTWLCaptureVideoReceived {
|
||||
ISTWLCaptureVideoInputData video_in;
|
||||
uint32_t time;
|
||||
@@ -155,6 +159,7 @@ union CaptureReceived {
|
||||
FTD2OldDSCaptureReceivedRaw ftd2_received_old_ds_raw;
|
||||
ISNitroCaptureReceived is_nitro_capture_received;
|
||||
ISTWLCaptureReceived is_twl_capture_received;
|
||||
CypressNisetroDSCaptureReceived cypress_nisetro_capture_received;
|
||||
};
|
||||
|
||||
struct CaptureDevice {
|
||||
|
||||
@@ -176,12 +176,10 @@ static void STDCALL OverlappedCompletionNothingRoutine(DWORD dwErrorCode, DWORD
|
||||
}
|
||||
|
||||
static void is_driver_close_handle(void** handle, void* default_value = INVALID_HANDLE_VALUE) {
|
||||
#ifdef _WIN32
|
||||
if ((*handle) == default_value)
|
||||
return;
|
||||
CloseHandle(*handle);
|
||||
*handle = default_value;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,554 @@
|
||||
#include "devicecapture.hpp"
|
||||
#include "cypress_nisetro_driver_comms.hpp"
|
||||
#include "cypress_nisetro_libusb_comms.hpp"
|
||||
#include "cypress_nisetro_communications.hpp"
|
||||
#include "cypress_nisetro_acquisition.hpp"
|
||||
#include "cypress_nisetro_acquisition_general.hpp"
|
||||
#include "usb_generic.hpp"
|
||||
|
||||
#include <libusb.h>
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
|
||||
#define SERIAL_NUMBER_SIZE (0x100 + 1)
|
||||
#define MAX_TIME_WAIT 1.0
|
||||
#define MAX_ERRORS_ALLOWED 100
|
||||
#define NUM_CONSECUTIVE_NEEDED_OUTPUT 6
|
||||
|
||||
static void cypress_device_read_frame_cb(void* user_data, int transfer_length, int transfer_status);
|
||||
|
||||
static cyni_device_device_handlers* usb_find_by_serial_number(const cyni_device_usb_device* usb_device_desc, std::string wanted_serial_number, CaptureDevice* new_device) {
|
||||
cyni_device_device_handlers* final_handlers = NULL;
|
||||
int curr_serial_extra_id = 0;
|
||||
final_handlers = cypress_libusb_serial_reconnection(usb_device_desc, wanted_serial_number, curr_serial_extra_id, new_device);
|
||||
|
||||
if (final_handlers == NULL)
|
||||
final_handlers = cypress_driver_find_by_serial_number(usb_device_desc, wanted_serial_number, curr_serial_extra_id, new_device);
|
||||
return final_handlers;
|
||||
}
|
||||
|
||||
static int usb_find_free_fw_id(const cyni_device_usb_device* usb_device_desc) {
|
||||
int curr_serial_extra_id = 0;
|
||||
const int num_free_fw_ids = 0x100;
|
||||
bool found[num_free_fw_ids];
|
||||
for(int i = 0; i < num_free_fw_ids; i++)
|
||||
found[i] = false;
|
||||
cypress_libusb_find_used_serial(usb_device_desc, found, num_free_fw_ids, curr_serial_extra_id);
|
||||
cypress_driver_find_used_serial(usb_device_desc, found, num_free_fw_ids, curr_serial_extra_id);
|
||||
|
||||
for(int i = 0; i < num_free_fw_ids; i++)
|
||||
if(!found[i])
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static cyni_device_device_handlers* usb_reconnect(const cyni_device_usb_device* usb_device_desc, CaptureDevice* device) {
|
||||
cyni_device_device_handlers* final_handlers = NULL;
|
||||
int curr_serial_extra_id = 0;
|
||||
final_handlers = cypress_libusb_serial_reconnection(usb_device_desc, device->serial_number, curr_serial_extra_id, NULL);
|
||||
|
||||
if (final_handlers == NULL)
|
||||
final_handlers = cypress_driver_serial_reconnection(device);
|
||||
return final_handlers;
|
||||
}
|
||||
|
||||
std::string get_serial(const cyni_device_usb_device* usb_device_desc, std::string serial, uint16_t bcd_device, int& curr_serial_extra_id) {
|
||||
if(serial != "")
|
||||
return serial;
|
||||
if(usb_device_desc->has_bcd_device_serial)
|
||||
return std::to_string(bcd_device & 0xFF);
|
||||
return std::to_string((curr_serial_extra_id++) + 1);
|
||||
}
|
||||
|
||||
static void cypress_nisetro_connection_end(cyni_device_device_handlers* handlers, const cyni_device_usb_device *device_desc, bool interface_claimed = true) {
|
||||
if (handlers == NULL)
|
||||
return;
|
||||
if (handlers->usb_handle)
|
||||
cypress_libusb_end_connection(handlers, device_desc, interface_claimed);
|
||||
else
|
||||
cypress_nisetro_driver_end_connection(handlers);
|
||||
delete handlers;
|
||||
}
|
||||
|
||||
CaptureDevice cypress_create_device(const cyni_device_usb_device* usb_device_desc, std::string serial, std::string path) {
|
||||
return CaptureDevice(serial, usb_device_desc->name, usb_device_desc->long_name, path, CAPTURE_CONN_CYPRESS_NISETRO, (void*)usb_device_desc, false, false, false, WIDTH_DS, HEIGHT_DS + HEIGHT_DS, 0, 0, 0, 0, 0, HEIGHT_DS, usb_device_desc->video_data_type);
|
||||
}
|
||||
|
||||
CaptureDevice cypress_create_device(const cyni_device_usb_device* usb_device_desc, std::string serial) {
|
||||
return CaptureDevice(serial, usb_device_desc->name, usb_device_desc->long_name, CAPTURE_CONN_CYPRESS_NISETRO, (void*)usb_device_desc, false, false, false, WIDTH_DS, HEIGHT_DS + HEIGHT_DS, 0, 0, 0, 0, 0, HEIGHT_DS, usb_device_desc->video_data_type);;
|
||||
}
|
||||
|
||||
void cypress_insert_device(std::vector<CaptureDevice>& devices_list, const cyni_device_usb_device* usb_device_desc, std::string serial, uint16_t bcd_device, int& curr_serial_extra_id, std::string path) {
|
||||
devices_list.push_back(cypress_create_device(usb_device_desc, get_serial(usb_device_desc, serial, bcd_device, curr_serial_extra_id), path));
|
||||
}
|
||||
|
||||
void cypress_insert_device(std::vector<CaptureDevice>& devices_list, const cyni_device_usb_device* usb_device_desc, std::string serial, uint16_t bcd_device, int& curr_serial_extra_id) {
|
||||
devices_list.push_back(cypress_create_device(usb_device_desc, get_serial(usb_device_desc, serial, bcd_device, curr_serial_extra_id)));
|
||||
}
|
||||
|
||||
void list_devices_cyni_device(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list) {
|
||||
const size_t num_cyni_device_desc = GetNumCyNiDeviceDesc();
|
||||
int* curr_serial_extra_id_cyni_device = new int[num_cyni_device_desc];
|
||||
bool* no_access_elems = new bool[num_cyni_device_desc];
|
||||
bool* not_supported_elems = new bool[num_cyni_device_desc];
|
||||
for (int i = 0; i < num_cyni_device_desc; i++) {
|
||||
no_access_elems[i] = false;
|
||||
not_supported_elems[i] = false;
|
||||
curr_serial_extra_id_cyni_device[i] = 0;
|
||||
}
|
||||
cypress_libusb_list_devices(devices_list, no_access_elems, not_supported_elems, curr_serial_extra_id_cyni_device, num_cyni_device_desc);
|
||||
|
||||
bool any_not_supported = false;
|
||||
for(int i = 0; i < num_cyni_device_desc; i++)
|
||||
any_not_supported |= not_supported_elems[i];
|
||||
for(int i = 0; i < num_cyni_device_desc; i++)
|
||||
if(no_access_elems[i]) {
|
||||
const cyni_device_usb_device* usb_device = GetCyNiDeviceDesc(i);
|
||||
no_access_list.emplace_back(usb_device->vid, usb_device->pid);
|
||||
}
|
||||
if(any_not_supported)
|
||||
cypress_driver_list_devices(devices_list, not_supported_elems, curr_serial_extra_id_cyni_device, num_cyni_device_desc);
|
||||
|
||||
delete[] curr_serial_extra_id_cyni_device;
|
||||
delete[] no_access_elems;
|
||||
delete[] not_supported_elems;
|
||||
}
|
||||
|
||||
bool cyni_device_connect_usb(bool print_failed, CaptureData* capture_data, CaptureDevice* device) {
|
||||
const cyni_device_usb_device* usb_device_info = (const cyni_device_usb_device*)device->descriptor;
|
||||
cyni_device_device_handlers* handlers = usb_reconnect(usb_device_info, device);
|
||||
if(handlers == NULL) {
|
||||
capture_error_print(true, capture_data, "Device not found");
|
||||
return false;
|
||||
}
|
||||
if(has_to_load_firmware(usb_device_info)) {
|
||||
const cyni_device_usb_device* next_usb_device_info = GetNextDeviceDesc(usb_device_info);
|
||||
int free_fw_id = usb_find_free_fw_id(next_usb_device_info);
|
||||
int ret = load_firmware(handlers, usb_device_info, free_fw_id);
|
||||
if(!ret) {
|
||||
capture_error_print(true, capture_data, "Firmware load error");
|
||||
return false;
|
||||
}
|
||||
cypress_nisetro_connection_end(handlers, usb_device_info);
|
||||
std::string new_serial_number = std::to_string(free_fw_id);
|
||||
CaptureDevice new_device;
|
||||
for(int i = 0; i < 20; i++) {
|
||||
default_sleep(500);
|
||||
handlers = usb_find_by_serial_number(next_usb_device_info, new_serial_number, &new_device);
|
||||
if(handlers != NULL)
|
||||
break;
|
||||
}
|
||||
if(handlers == NULL) {
|
||||
capture_error_print(true, capture_data, "Device reconnection error");
|
||||
return false;
|
||||
}
|
||||
*device = new_device;
|
||||
}
|
||||
capture_data->handle = (void*)handlers;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t cyni_device_get_video_in_size(cypress_nisetro_device_type device_type) {
|
||||
return sizeof(CypressNisetroDSCaptureReceived);
|
||||
}
|
||||
|
||||
|
||||
uint64_t cyni_device_get_video_in_size(CaptureStatus* status) {
|
||||
return cyni_device_get_video_in_size(((const cyni_device_usb_device*)(status->device.descriptor))->device_type);
|
||||
}
|
||||
|
||||
|
||||
uint64_t cyni_device_get_video_in_size(CaptureData* capture_data) {
|
||||
return cyni_device_get_video_in_size(&capture_data->status);
|
||||
}
|
||||
|
||||
static int find_first_vsync_byte(CaptureReceived* capture_buf, size_t read_size) {
|
||||
uint8_t* data_in = (uint8_t*)capture_buf->cypress_nisetro_capture_received.video_in.screen_data;
|
||||
if((data_in[0] & 0x80) && (!(data_in[read_size - 1] & 0x80)))
|
||||
return 0;
|
||||
int pos = 0;
|
||||
while((pos < read_size) && (data_in[pos] & 0x80))
|
||||
pos++;
|
||||
while((pos < read_size) && (!(data_in[pos] & 0x80)))
|
||||
pos++;
|
||||
return pos;
|
||||
}
|
||||
|
||||
void cypress_output_to_thread(CaptureData* capture_data, CaptureReceived* capture_buf, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start, size_t read_size, size_t* scheduled_special_read, bool* recalibration_request) {
|
||||
// Output to the other threads...
|
||||
int offset = find_first_vsync_byte(capture_buf, read_size);
|
||||
const cyni_device_usb_device* usb_device_info = (const cyni_device_usb_device*)capture_data->status.device.descriptor;
|
||||
if(offset) {
|
||||
if(offset % usb_device_info->max_usb_packet_size)
|
||||
*recalibration_request = true;
|
||||
else
|
||||
*scheduled_special_read = offset;
|
||||
return;
|
||||
}
|
||||
const auto curr_time = std::chrono::high_resolution_clock::now();
|
||||
const std::chrono::duration<double> diff = curr_time - (*clock_start);
|
||||
*clock_start = curr_time;
|
||||
capture_data->data_buffers.WriteToBuffer(capture_buf, read_size, diff.count(), &capture_data->status.device, curr_capture_type);
|
||||
if (capture_data->status.cooldown_curr_in)
|
||||
capture_data->status.cooldown_curr_in = capture_data->status.cooldown_curr_in - 1;
|
||||
capture_data->status.video_wait.unlock();
|
||||
capture_data->status.audio_wait.unlock();
|
||||
}
|
||||
|
||||
int cypress_device_read_frame_and_output(CaptureData* capture_data, CaptureReceived* capture_buf, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock> &clock_start, size_t* scheduled_special_read, bool* recalibration_request) {
|
||||
const cyni_device_usb_device* usb_device_info = (const cyni_device_usb_device*)capture_data->status.device.descriptor;
|
||||
size_t read_size = cyni_device_get_video_in_size(usb_device_info->device_type);
|
||||
if(*scheduled_special_read)
|
||||
read_size = *scheduled_special_read;
|
||||
int ret = ReadFrame((cyni_device_device_handlers*)capture_data->handle, (uint8_t*)capture_buf, read_size, usb_device_info);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if(*scheduled_special_read) {
|
||||
*scheduled_special_read = 0;
|
||||
return ret;
|
||||
}
|
||||
cypress_output_to_thread(capture_data, capture_buf, curr_capture_type, &clock_start, read_size, scheduled_special_read, recalibration_request);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cypress_device_read_frame_request(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, CaptureScreensType curr_capture_type, uint32_t index) {
|
||||
if(cypress_device_capture_recv_data == NULL)
|
||||
return LIBUSB_SUCCESS;
|
||||
if((*cypress_device_capture_recv_data->status) < 0) {
|
||||
cypress_device_capture_recv_data->in_use = false;
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
const cyni_device_usb_device* usb_device_info = (const cyni_device_usb_device*)capture_data->status.device.descriptor;
|
||||
cypress_device_capture_recv_data->index = index;
|
||||
cypress_device_capture_recv_data->curr_capture_type = curr_capture_type;
|
||||
cypress_device_capture_recv_data->cb_data.function = cypress_device_read_frame_cb;
|
||||
size_t read_size = cyni_device_get_video_in_size(usb_device_info->device_type);
|
||||
if(*cypress_device_capture_recv_data->scheduled_special_read) {
|
||||
read_size = *cypress_device_capture_recv_data->scheduled_special_read;
|
||||
*cypress_device_capture_recv_data->active_special_read_index = index;
|
||||
*cypress_device_capture_recv_data->is_active_special_read = true;
|
||||
*cypress_device_capture_recv_data->scheduled_special_read = 0;
|
||||
}
|
||||
return ReadFrameAsync((cyni_device_device_handlers*)capture_data->handle, (uint8_t*)&cypress_device_capture_recv_data->buffer, read_size, usb_device_info, &cypress_device_capture_recv_data->cb_data);
|
||||
}
|
||||
|
||||
static void end_cypress_device_read_frame_cb(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
|
||||
cypress_device_capture_recv_data->in_use = false;
|
||||
cypress_device_capture_recv_data->is_buffer_free_shared_mutex->specific_unlock(cypress_device_capture_recv_data->cb_data.internal_index);
|
||||
}
|
||||
|
||||
static void cypress_device_read_frame_cb(void* user_data, int transfer_length, int transfer_status) {
|
||||
CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data = (CypressDeviceCaptureReceivedData*)user_data;
|
||||
if((*cypress_device_capture_recv_data->status) < 0)
|
||||
return end_cypress_device_read_frame_cb(cypress_device_capture_recv_data);
|
||||
if(transfer_status != LIBUSB_TRANSFER_COMPLETED) {
|
||||
int error = LIBUSB_ERROR_OTHER;
|
||||
if(transfer_status == LIBUSB_TRANSFER_TIMED_OUT)
|
||||
error = LIBUSB_ERROR_TIMEOUT;
|
||||
else {
|
||||
*cypress_device_capture_recv_data->errors_since_last_output += 1;
|
||||
*cypress_device_capture_recv_data->consecutive_output_to_thread = 0;
|
||||
}
|
||||
*cypress_device_capture_recv_data->status = error;
|
||||
return end_cypress_device_read_frame_cb(cypress_device_capture_recv_data);
|
||||
}
|
||||
|
||||
if(((int32_t)(cypress_device_capture_recv_data->index - (*cypress_device_capture_recv_data->last_index))) <= 0) {
|
||||
//*cypress_device_capture_recv_data->status = LIBUSB_ERROR_INTERRUPTED;
|
||||
return end_cypress_device_read_frame_cb(cypress_device_capture_recv_data);
|
||||
}
|
||||
*cypress_device_capture_recv_data->consecutive_output_to_thread += 1;
|
||||
if((*cypress_device_capture_recv_data->consecutive_output_to_thread) > NUM_CONSECUTIVE_NEEDED_OUTPUT)
|
||||
*cypress_device_capture_recv_data->errors_since_last_output = 0;
|
||||
*cypress_device_capture_recv_data->last_index = cypress_device_capture_recv_data->index;
|
||||
if((*cypress_device_capture_recv_data->is_active_special_read) && (((int32_t)(cypress_device_capture_recv_data->index - (*cypress_device_capture_recv_data->active_special_read_index))) >= 0)) {
|
||||
*cypress_device_capture_recv_data->is_active_special_read = false;
|
||||
return end_cypress_device_read_frame_cb(cypress_device_capture_recv_data);
|
||||
}
|
||||
|
||||
if((*cypress_device_capture_recv_data->scheduled_special_read) || (*cypress_device_capture_recv_data->is_active_special_read) || (*cypress_device_capture_recv_data->recalibration_request))
|
||||
return end_cypress_device_read_frame_cb(cypress_device_capture_recv_data);
|
||||
|
||||
cypress_output_to_thread(cypress_device_capture_recv_data->capture_data, &cypress_device_capture_recv_data->buffer, cypress_device_capture_recv_data->curr_capture_type, cypress_device_capture_recv_data->clock_start, transfer_length, cypress_device_capture_recv_data->scheduled_special_read, cypress_device_capture_recv_data->recalibration_request);
|
||||
end_cypress_device_read_frame_cb(cypress_device_capture_recv_data);
|
||||
}
|
||||
|
||||
int cypress_device_get_num_free_buffers(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
|
||||
int num_free = 0;
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
if(!cypress_device_capture_recv_data[i].in_use)
|
||||
num_free += 1;
|
||||
return num_free;
|
||||
}
|
||||
|
||||
static void close_all_reads_error(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, bool &async_read_closed) {
|
||||
cyni_device_device_handlers* handlers = (cyni_device_device_handlers*)capture_data->handle;
|
||||
const cyni_device_usb_device* usb_device_desc = (const cyni_device_usb_device*)capture_data->status.device.descriptor;
|
||||
if(get_cypress_device_status(cypress_device_capture_recv_data) < 0) {
|
||||
if(!async_read_closed) {
|
||||
if(handlers->usb_handle) {
|
||||
for (int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
CloseAsyncRead(handlers, usb_device_desc, &cypress_device_capture_recv_data[i].cb_data);
|
||||
}
|
||||
else
|
||||
CloseAsyncRead(handlers, usb_device_desc, &cypress_device_capture_recv_data[0].cb_data);
|
||||
async_read_closed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool has_too_much_time_passed(const std::chrono::time_point<std::chrono::high_resolution_clock> &start_time) {
|
||||
const auto curr_time = std::chrono::high_resolution_clock::now();
|
||||
const std::chrono::duration<double> diff = curr_time - start_time;
|
||||
return diff.count() > MAX_TIME_WAIT;
|
||||
}
|
||||
|
||||
static void error_too_much_time_passed(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, bool &async_read_closed, const std::chrono::time_point<std::chrono::high_resolution_clock> &start_time) {
|
||||
if(has_too_much_time_passed(start_time)) {
|
||||
error_cypress_device_status(cypress_device_capture_recv_data, -1);
|
||||
close_all_reads_error(capture_data, cypress_device_capture_recv_data, async_read_closed);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_all_cypress_device_buffers_free(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
|
||||
if(cypress_device_capture_recv_data == NULL)
|
||||
return;
|
||||
cyni_device_device_handlers* handlers = (cyni_device_device_handlers*)capture_data->handle;
|
||||
bool async_read_closed = false;
|
||||
close_all_reads_error(capture_data, cypress_device_capture_recv_data, async_read_closed);
|
||||
const auto start_time = std::chrono::high_resolution_clock::now();
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
while(cypress_device_capture_recv_data[i].in_use) {
|
||||
error_too_much_time_passed(capture_data, cypress_device_capture_recv_data, async_read_closed, start_time);
|
||||
cypress_device_capture_recv_data[i].is_buffer_free_shared_mutex->specific_timed_lock(i);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_one_cypress_device_buffer_free(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
|
||||
cyni_device_device_handlers* handlers = (cyni_device_device_handlers*)capture_data->handle;
|
||||
bool done = false;
|
||||
const auto start_time = std::chrono::high_resolution_clock::now();
|
||||
while(!done) {
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
if(!cypress_device_capture_recv_data[i].in_use)
|
||||
done = true;
|
||||
}
|
||||
if(!done) {
|
||||
if(has_too_much_time_passed(start_time))
|
||||
return;
|
||||
if(get_cypress_device_status(cypress_device_capture_recv_data) < 0)
|
||||
return;
|
||||
int dummy = 0;
|
||||
cypress_device_capture_recv_data[0].is_buffer_free_shared_mutex->general_timed_lock(&dummy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wait_specific_cypress_device_buffer_free(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
|
||||
cyni_device_device_handlers* handlers = (cyni_device_device_handlers*)capture_data->handle;
|
||||
bool done = false;
|
||||
const auto start_time = std::chrono::high_resolution_clock::now();
|
||||
while(!done) {
|
||||
if(!cypress_device_capture_recv_data->in_use)
|
||||
done = true;
|
||||
if(!done) {
|
||||
if(has_too_much_time_passed(start_time))
|
||||
return;
|
||||
if(get_cypress_device_status(cypress_device_capture_recv_data) < 0)
|
||||
return;
|
||||
int dummy = 0;
|
||||
cypress_device_capture_recv_data->is_buffer_free_shared_mutex->general_timed_lock(&dummy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool cypress_device_are_buffers_all_free(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
|
||||
return cypress_device_get_num_free_buffers(cypress_device_capture_recv_data) == NUM_CAPTURE_RECEIVED_DATA_BUFFERS;
|
||||
}
|
||||
|
||||
CypressDeviceCaptureReceivedData* cypress_device_get_free_buffer(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
|
||||
wait_one_cypress_device_buffer_free(capture_data, cypress_device_capture_recv_data);
|
||||
if(get_cypress_device_status(cypress_device_capture_recv_data) < 0)
|
||||
return NULL;
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
if(!cypress_device_capture_recv_data[i].in_use) {
|
||||
cypress_device_capture_recv_data[i].is_buffer_free_shared_mutex->specific_try_lock(i);
|
||||
cypress_device_capture_recv_data[i].in_use = true;
|
||||
return &cypress_device_capture_recv_data[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int get_cypress_device_status(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
|
||||
return *cypress_device_capture_recv_data[0].status;
|
||||
}
|
||||
|
||||
void error_cypress_device_status(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, int error_val) {
|
||||
if((error_val == 0) || (get_cypress_device_status(cypress_device_capture_recv_data) == 0))
|
||||
*cypress_device_capture_recv_data[0].status = error_val;
|
||||
}
|
||||
|
||||
void reset_cypress_device_status(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
|
||||
error_cypress_device_status(cypress_device_capture_recv_data, 0);
|
||||
}
|
||||
|
||||
void recalibration_reads(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, CypressDeviceCaptureReceivedData* chosen_buffer, uint32_t &index, CaptureScreensType curr_capture_type) {
|
||||
CaptureData* capture_data = cypress_device_capture_recv_data[0].capture_data;
|
||||
do {
|
||||
if(get_cypress_device_status(cypress_device_capture_recv_data) < 0)
|
||||
return;
|
||||
chosen_buffer->in_use = false;
|
||||
wait_all_cypress_device_buffers_free(capture_data, cypress_device_capture_recv_data);
|
||||
chosen_buffer->in_use = true;
|
||||
if(get_cypress_device_status(cypress_device_capture_recv_data) < 0)
|
||||
return;
|
||||
CypressDeviceCaptureReceivedData* next_buffer = cypress_device_get_free_buffer(capture_data, cypress_device_capture_recv_data);
|
||||
default_sleep();
|
||||
*chosen_buffer->recalibration_request = false;
|
||||
chosen_buffer->in_use = true;
|
||||
int ret = cypress_device_read_frame_request(capture_data, chosen_buffer, curr_capture_type, index++);
|
||||
if(ret < 0) {
|
||||
error_cypress_device_status(cypress_device_capture_recv_data, ret);
|
||||
return;
|
||||
}
|
||||
ret = cypress_device_read_frame_request(capture_data, next_buffer, curr_capture_type, index++);
|
||||
if(ret < 0) {
|
||||
next_buffer->in_use = false;
|
||||
error_cypress_device_status(cypress_device_capture_recv_data, ret);
|
||||
wait_specific_cypress_device_buffer_free(capture_data, chosen_buffer);
|
||||
chosen_buffer->in_use = true;
|
||||
return;
|
||||
}
|
||||
wait_specific_cypress_device_buffer_free(capture_data, chosen_buffer);
|
||||
} while((*chosen_buffer->recalibration_request) && capture_data->status.connected && capture_data->status.running);
|
||||
chosen_buffer->in_use = true;
|
||||
}
|
||||
|
||||
static bool cyni_device_acquisition_loop(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
|
||||
cyni_device_device_handlers* handlers = (cyni_device_device_handlers*)capture_data->handle;
|
||||
const cyni_device_usb_device* usb_device_desc = (const cyni_device_usb_device*)capture_data->status.device.descriptor;
|
||||
uint32_t index = 0;
|
||||
CaptureScreensType curr_capture_type = capture_data->status.capture_type;
|
||||
CaptureSpeedsType curr_capture_speed = capture_data->status.capture_speed;
|
||||
int ret = capture_start(handlers, usb_device_desc);
|
||||
if (ret < 0) {
|
||||
capture_error_print(true, capture_data, "Capture Start: Failed");
|
||||
return false;
|
||||
}
|
||||
SetMaxTransferSize(handlers, usb_device_desc, cyni_device_get_video_in_size(usb_device_desc->device_type));
|
||||
auto clock_last_reset = std::chrono::high_resolution_clock::now();
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
CypressDeviceCaptureReceivedData* chosen_buffer = cypress_device_get_free_buffer(capture_data, cypress_device_capture_recv_data);
|
||||
ret = cypress_device_read_frame_request(capture_data, chosen_buffer, curr_capture_type, index++);
|
||||
if(ret < 0) {
|
||||
chosen_buffer->in_use = false;
|
||||
error_cypress_device_status(cypress_device_capture_recv_data, ret);
|
||||
capture_error_print(true, capture_data, "Initial Reads: Failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
StartCaptureDma(handlers, usb_device_desc);
|
||||
while (capture_data->status.connected && capture_data->status.running) {
|
||||
ret = get_cypress_device_status(cypress_device_capture_recv_data);
|
||||
if(ret < 0) {
|
||||
wait_all_cypress_device_buffers_free(capture_data, cypress_device_capture_recv_data);
|
||||
if((*cypress_device_capture_recv_data[0].errors_since_last_output) > MAX_ERRORS_ALLOWED) {
|
||||
capture_error_print(true, capture_data, "Disconnected: Read error");
|
||||
return false;
|
||||
}
|
||||
*cypress_device_capture_recv_data[0].recalibration_request = false;
|
||||
*cypress_device_capture_recv_data[0].scheduled_special_read = 0;
|
||||
*cypress_device_capture_recv_data[0].is_active_special_read = false;
|
||||
pipe_reset_bulk_in(handlers, usb_device_desc);
|
||||
reset_cypress_device_status(cypress_device_capture_recv_data);
|
||||
default_sleep(100);
|
||||
}
|
||||
CypressDeviceCaptureReceivedData* chosen_buffer = cypress_device_get_free_buffer(capture_data, cypress_device_capture_recv_data);
|
||||
if(chosen_buffer == NULL)
|
||||
error_cypress_device_status(cypress_device_capture_recv_data, LIBUSB_ERROR_TIMEOUT);
|
||||
if(chosen_buffer && (*chosen_buffer->recalibration_request)) {
|
||||
*chosen_buffer->recalibration_request = false;
|
||||
recalibration_reads(handlers, usb_device_desc, cypress_device_capture_recv_data, chosen_buffer, index, curr_capture_type);
|
||||
}
|
||||
ret = cypress_device_read_frame_request(capture_data, chosen_buffer, curr_capture_type, index++);
|
||||
if(ret < 0) {
|
||||
chosen_buffer->in_use = false;
|
||||
error_cypress_device_status(cypress_device_capture_recv_data, ret);
|
||||
capture_error_print(true, capture_data, "Setup Read: Failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void cyni_device_acquisition_main_loop(CaptureData* capture_data) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
bool is_done_thread;
|
||||
ConsumerMutex has_data_been_processed;
|
||||
std::thread async_processing_thread;
|
||||
cyni_device_device_handlers* handlers = (cyni_device_device_handlers*)capture_data->handle;
|
||||
const cyni_device_usb_device* usb_device_desc = (const cyni_device_usb_device*)capture_data->status.device.descriptor;
|
||||
|
||||
uint32_t last_index = -1;
|
||||
int status = 0;
|
||||
cyni_async_callback_data* cb_queue[NUM_CAPTURE_RECEIVED_DATA_BUFFERS];
|
||||
int queue_elems = 0;
|
||||
size_t scheduled_special_read = 0;
|
||||
uint32_t active_special_read_index = 0;
|
||||
bool is_active_special_read = false;
|
||||
bool one_transfer_active = false;
|
||||
bool recalibration_request = false;
|
||||
int errors_since_last_output = 0;
|
||||
int consecutive_output_to_thread = 0;
|
||||
SharedConsumerMutex is_buffer_free_shared_mutex(NUM_CAPTURE_RECEIVED_DATA_BUFFERS);
|
||||
SharedConsumerMutex is_transfer_done_shared_mutex(NUM_CAPTURE_RECEIVED_DATA_BUFFERS);
|
||||
SharedConsumerMutex is_transfer_data_ready_shared_mutex(NUM_CAPTURE_RECEIVED_DATA_BUFFERS);
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> clock_start = std::chrono::high_resolution_clock::now();
|
||||
CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data = new CypressDeviceCaptureReceivedData[NUM_CAPTURE_RECEIVED_DATA_BUFFERS];
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
cypress_device_capture_recv_data[i].in_use = false;
|
||||
cypress_device_capture_recv_data[i].index = i;
|
||||
cypress_device_capture_recv_data[i].capture_data = capture_data;
|
||||
cypress_device_capture_recv_data[i].scheduled_special_read = &scheduled_special_read;
|
||||
cypress_device_capture_recv_data[i].active_special_read_index = &active_special_read_index;
|
||||
cypress_device_capture_recv_data[i].is_active_special_read = &is_active_special_read;
|
||||
cypress_device_capture_recv_data[i].last_index = &last_index;
|
||||
cypress_device_capture_recv_data[i].errors_since_last_output = &errors_since_last_output;
|
||||
cypress_device_capture_recv_data[i].recalibration_request = &recalibration_request;
|
||||
cypress_device_capture_recv_data[i].consecutive_output_to_thread = &consecutive_output_to_thread;
|
||||
cypress_device_capture_recv_data[i].clock_start = &clock_start;
|
||||
cypress_device_capture_recv_data[i].is_buffer_free_shared_mutex = &is_buffer_free_shared_mutex;
|
||||
cypress_device_capture_recv_data[i].status = &status;
|
||||
cypress_device_capture_recv_data[i].cb_data.actual_user_data = &cypress_device_capture_recv_data[i];
|
||||
cypress_device_capture_recv_data[i].cb_data.transfer_data = NULL;
|
||||
cypress_device_capture_recv_data[i].cb_data.is_transfer_done_mutex = &is_transfer_done_shared_mutex;
|
||||
cypress_device_capture_recv_data[i].cb_data.internal_index = i;
|
||||
cypress_device_capture_recv_data[i].cb_data.is_transfer_data_ready_mutex = &is_transfer_data_ready_shared_mutex;
|
||||
}
|
||||
SetupCypressDeviceAsyncThread(handlers, cypress_device_capture_recv_data, &async_processing_thread, &is_done_thread, &has_data_been_processed);
|
||||
bool proper_return = cyni_device_acquisition_loop(capture_data, cypress_device_capture_recv_data);
|
||||
wait_all_cypress_device_buffers_free(capture_data, cypress_device_capture_recv_data);
|
||||
EndCypressDeviceAsyncThread(handlers, cypress_device_capture_recv_data, &async_processing_thread, &is_done_thread, &has_data_been_processed);
|
||||
delete []cypress_device_capture_recv_data;
|
||||
|
||||
if(proper_return)
|
||||
capture_end(handlers, usb_device_desc);
|
||||
}
|
||||
|
||||
void usb_cyni_device_acquisition_cleanup(CaptureData* capture_data) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
cypress_nisetro_connection_end((cyni_device_device_handlers*)capture_data->handle, (const cyni_device_usb_device*)capture_data->status.device.descriptor);
|
||||
capture_data->handle = NULL;
|
||||
}
|
||||
void usb_cyni_device_init() {
|
||||
return usb_init();
|
||||
}
|
||||
|
||||
void usb_cyni_device_close() {
|
||||
usb_close();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
#include "frontend.hpp"
|
||||
#include "cypress_nisetro_communications.hpp"
|
||||
#include "cypress_nisetro_libusb_comms.hpp"
|
||||
#include "cypress_nisetro_driver_comms.hpp"
|
||||
#include "cypress_nisetro_acquisition_general.hpp"
|
||||
#include "nisetro_ds_fw.h"
|
||||
|
||||
#include <libusb.h>
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
#define CYPRESS_BASE_USB_PACKET_LIMIT 64
|
||||
#define CYPRESS_NISETRO_USB_PACKET_LIMIT 512
|
||||
|
||||
#define CMD_EP6IN_START 0x50
|
||||
#define CMD_EP6IN_STOP 0x51
|
||||
#define CMD_EP2OUT_START 0x52
|
||||
#define CMD_EP2OUT_STOP 0x53
|
||||
#define CMD_PORT_CFG 0x54
|
||||
#define CMD_REG_READ 0x55
|
||||
#define CMD_REG_WRITE 0x56
|
||||
#define CMD_PORT_READ 0x57
|
||||
#define CMD_PORT_WRITE 0x58
|
||||
#define CMD_IFCONFIG 0x59
|
||||
#define CMD_MODE_IDLE 0x5a
|
||||
|
||||
#define PIO_DROP 0x20
|
||||
#define PIO_RESET 0x10
|
||||
#define PIO_DIR 0x08
|
||||
|
||||
static const cyni_device_usb_device cypress_fx2_generic_device = {
|
||||
.name = "EZ-USB FX2", .long_name = "EZ-USB FX2",
|
||||
.vid = 0x04B4, .pid = 0x8613,
|
||||
.default_config = 1, .default_interface = 0,
|
||||
.bulk_timeout = 500,
|
||||
.ep_ctrl_bulk_in = 0, .ep_ctrl_bulk_out = 0,
|
||||
.ep_bulk_in = 0,
|
||||
.device_type = CYPRESS_NISETRO_BLANK_DEVICE,
|
||||
.video_data_type = VIDEO_DATA_RGB, .max_usb_packet_size = CYPRESS_BASE_USB_PACKET_LIMIT,
|
||||
.do_pipe_clear_reset = false,
|
||||
.firmware_to_load = nisetro_ds_fw, .firmware_size = nisetro_ds_fw_len,
|
||||
.next_device = CYPRESS_NISETRO_DS_DEVICE,
|
||||
.has_bcd_device_serial = false, .alt_interface = 1
|
||||
};
|
||||
|
||||
static const cyni_device_usb_device cypress_fx2_nisetro_ds_device = {
|
||||
.name = "Nisetro DS", .long_name = "Nisetro DS",
|
||||
.vid = 0x04B4, .pid = 0x1004,
|
||||
.default_config = 1, .default_interface = 0,
|
||||
.bulk_timeout = 500,
|
||||
.ep_ctrl_bulk_in = 1 | LIBUSB_ENDPOINT_IN, .ep_ctrl_bulk_out = 1 | LIBUSB_ENDPOINT_OUT,
|
||||
.ep_bulk_in = 6 | LIBUSB_ENDPOINT_IN,
|
||||
.device_type = CYPRESS_NISETRO_DS_DEVICE,
|
||||
.video_data_type = VIDEO_DATA_RGB, .max_usb_packet_size = CYPRESS_NISETRO_USB_PACKET_LIMIT,
|
||||
.do_pipe_clear_reset = true,
|
||||
.firmware_to_load = NULL, .firmware_size = 0,
|
||||
.next_device = CYPRESS_NISETRO_DS_DEVICE,
|
||||
.has_bcd_device_serial = true, .alt_interface = 0
|
||||
};
|
||||
|
||||
static const cyni_device_usb_device* all_usb_cyni_device_devices_desc[] = {
|
||||
&cypress_fx2_generic_device,
|
||||
&cypress_fx2_nisetro_ds_device,
|
||||
};
|
||||
|
||||
static int ctrl_in_transfer(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, uint8_t request, uint16_t value, uint16_t index, int* transferred) {
|
||||
if(handlers->usb_handle)
|
||||
return cypress_libusb_ctrl_in(handlers, usb_device_desc, buf, length, request, value, index, transferred);
|
||||
return cypress_driver_ctrl_transfer_in(handlers, buf, length, value, index, request, transferred);
|
||||
}
|
||||
|
||||
static int ctrl_out_transfer(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, uint8_t request, uint16_t value, uint16_t index, int* transferred) {
|
||||
if(handlers->usb_handle)
|
||||
return cypress_libusb_ctrl_out(handlers, usb_device_desc, buf, length, request, value, index, transferred);
|
||||
return cypress_driver_ctrl_transfer_out(handlers, buf, length, value, index, request, transferred);
|
||||
}
|
||||
|
||||
static int bulk_in_transfer(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred) {
|
||||
if(handlers->usb_handle)
|
||||
return cypress_libusb_bulk_in(handlers, usb_device_desc, buf, length, transferred);
|
||||
return cypress_driver_bulk_in(handlers, usb_device_desc, buf, length, transferred);
|
||||
}
|
||||
|
||||
static int bulk_in_async(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t *buf, int length, cyni_async_callback_data* cb_data) {
|
||||
if(handlers->usb_handle)
|
||||
return cypress_libusb_async_in_start(handlers, usb_device_desc, buf, length, cb_data);
|
||||
return cypress_driver_async_in_start(handlers, usb_device_desc, buf, length, cb_data);
|
||||
}
|
||||
|
||||
static int ctrl_bulk_in_transfer(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred) {
|
||||
if(handlers->usb_handle)
|
||||
return cypress_libusb_ctrl_bulk_in(handlers, usb_device_desc, buf, length, transferred);
|
||||
return cypress_driver_ctrl_bulk_in(handlers, usb_device_desc, buf, length, transferred);
|
||||
}
|
||||
|
||||
static int ctrl_bulk_out_transfer(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred) {
|
||||
if(handlers->usb_handle)
|
||||
return cypress_libusb_ctrl_bulk_out(handlers, usb_device_desc, buf, length, transferred);
|
||||
return cypress_driver_ctrl_bulk_out(handlers, usb_device_desc, buf, length, transferred);
|
||||
}
|
||||
|
||||
void pipe_reset_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc) {
|
||||
if(handlers->usb_handle)
|
||||
return cypress_libusb_pipe_reset_bulk_in(handlers, usb_device_desc);
|
||||
return cypress_driver_pipe_reset_bulk_in(handlers, usb_device_desc);
|
||||
}
|
||||
|
||||
static void pipe_reset_ctrl_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc) {
|
||||
if(handlers->usb_handle)
|
||||
return cypress_libusb_pipe_reset_ctrl_bulk_in(handlers, usb_device_desc);
|
||||
return cypress_driver_pipe_reset_ctrl_bulk_in(handlers, usb_device_desc);
|
||||
}
|
||||
|
||||
static void pipe_reset_ctrl_bulk_out(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc) {
|
||||
if(handlers->usb_handle)
|
||||
return cypress_libusb_pipe_reset_ctrl_bulk_out(handlers, usb_device_desc);
|
||||
return cypress_driver_pipe_reset_ctrl_bulk_out(handlers, usb_device_desc);
|
||||
}
|
||||
|
||||
int GetNumCyNiDeviceDesc() {
|
||||
return sizeof(all_usb_cyni_device_devices_desc) / sizeof(all_usb_cyni_device_devices_desc[0]);
|
||||
}
|
||||
|
||||
const cyni_device_usb_device* GetCyNiDeviceDesc(int index) {
|
||||
if((index < 0) || (index >= GetNumCyNiDeviceDesc()))
|
||||
index = 0;
|
||||
return all_usb_cyni_device_devices_desc[index];
|
||||
}
|
||||
|
||||
const cyni_device_usb_device* GetNextDeviceDesc(const cyni_device_usb_device* device) {
|
||||
for(int i = 0; i < GetNumCyNiDeviceDesc(); i++) {
|
||||
const cyni_device_usb_device* examined_device = GetCyNiDeviceDesc(i);
|
||||
if(examined_device->device_type == device->next_device)
|
||||
return examined_device;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool has_to_load_firmware(const cyni_device_usb_device* device) {
|
||||
return !((device->firmware_to_load == NULL) || (device->firmware_size == 0));
|
||||
}
|
||||
|
||||
bool load_firmware(cyni_device_device_handlers* handlers, const cyni_device_usb_device* device, uint8_t patch_id) {
|
||||
if(!has_to_load_firmware(device))
|
||||
return true;
|
||||
int transferred = 0;
|
||||
uint8_t* fw_data = new uint8_t[device->firmware_size];
|
||||
memcpy(fw_data, device->firmware_to_load, device->firmware_size);
|
||||
int num_patches = read_le16(fw_data, 1);
|
||||
for(int i = 0; i < num_patches; i++) {
|
||||
int pos_patch = read_le16(fw_data, 2 + i);
|
||||
write_le16(fw_data + pos_patch, patch_id | 0xFF00);
|
||||
}
|
||||
uint8_t buffer[0x8000];
|
||||
buffer[0] = 1;
|
||||
int ret = ctrl_out_transfer(handlers, device, buffer, 1, 0xA0, 0xE600, 0, &transferred);
|
||||
if(ret < 0) {
|
||||
delete []fw_data;
|
||||
return false;
|
||||
}
|
||||
bool done = false;
|
||||
int fw_pos = read_le16(fw_data);
|
||||
while(!done) {
|
||||
int inside_len = read_be16(fw_data + fw_pos);
|
||||
int offset = read_be16(fw_data + fw_pos, 1);
|
||||
done = (inside_len & 0x8000) != 0;
|
||||
inside_len &= 0x7FFF;
|
||||
fw_pos += 4;
|
||||
if((inside_len + fw_pos) > device->firmware_size) {
|
||||
delete []fw_data;
|
||||
return false;
|
||||
}
|
||||
memcpy(buffer, fw_data + fw_pos, inside_len);
|
||||
fw_pos += inside_len;
|
||||
ret = ctrl_out_transfer(handlers, device, buffer, inside_len, 0xA0, offset, 0, &transferred);
|
||||
if(ret < 0) {
|
||||
delete []fw_data;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
delete []fw_data;
|
||||
return true;
|
||||
}
|
||||
|
||||
int capture_start(cyni_device_device_handlers* handlers, const cyni_device_usb_device* device) {
|
||||
uint8_t buffer[] = { CMD_PORT_CFG, 0x07, PIO_RESET | PIO_DIR, CMD_MODE_IDLE, CMD_IFCONFIG, 0xE3, CMD_REG_WRITE, 0, 0x08, CMD_MODE_IDLE};
|
||||
int transferred = 0;
|
||||
pipe_reset_ctrl_bulk_in(handlers, device);
|
||||
pipe_reset_ctrl_bulk_out(handlers, device);
|
||||
int ret = ctrl_bulk_out_transfer(handlers, device, buffer, sizeof(buffer), &transferred);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
pipe_reset_bulk_in(handlers, device);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int StartCaptureDma(cyni_device_device_handlers* handlers, const cyni_device_usb_device* device) {
|
||||
uint8_t buffer[] = { CMD_PORT_WRITE, PIO_RESET, CMD_EP6IN_START, CMD_PORT_WRITE, 0};
|
||||
int transferred = 0;
|
||||
return ctrl_bulk_out_transfer(handlers, device, buffer, sizeof(buffer), &transferred);
|
||||
}
|
||||
|
||||
int capture_end(cyni_device_device_handlers* handlers, const cyni_device_usb_device* device) {
|
||||
int transferred = 0;
|
||||
uint8_t buffer[] = { CMD_PORT_WRITE, 0, CMD_EP6IN_STOP, CMD_MODE_IDLE};
|
||||
int ret = ctrl_bulk_out_transfer(handlers, device, buffer, sizeof(buffer), &transferred);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
|
||||
uint8_t buffer2[] = { CMD_REG_READ, 0, CMD_REG_READ, 1, CMD_REG_READ, 2, CMD_REG_READ, 3, CMD_REG_READ, 4, CMD_REG_READ, 5, CMD_REG_READ, 6, CMD_REG_READ, 7};
|
||||
ret = ctrl_bulk_out_transfer(handlers, device, buffer2, sizeof(buffer2), &transferred);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
|
||||
pipe_reset_ctrl_bulk_in(handlers, device);
|
||||
return ctrl_bulk_in_transfer(handlers, device, buffer2, 8, &transferred);
|
||||
}
|
||||
|
||||
void SetMaxTransferSize(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, size_t new_max_transfer_size) {
|
||||
if(handlers->usb_handle)
|
||||
return;
|
||||
cypress_driver_set_transfer_size_bulk_in(handlers, usb_device_desc, new_max_transfer_size);
|
||||
}
|
||||
|
||||
int ReadFrame(cyni_device_device_handlers* handlers, uint8_t* buf, int length, const cyni_device_usb_device* device_desc) {
|
||||
// Maybe making this async would be better for lower end hardware...
|
||||
int num_bytes = 0;
|
||||
int ret = bulk_in_transfer(handlers, device_desc, buf, length, &num_bytes);
|
||||
if(num_bytes != length)
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ReadFrameAsync(cyni_device_device_handlers* handlers, uint8_t* buf, int length, const cyni_device_usb_device* device_desc, cyni_async_callback_data* cb_data) {
|
||||
return bulk_in_async(handlers, device_desc, buf, length, cb_data);
|
||||
}
|
||||
|
||||
void CloseAsyncRead(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, cyni_async_callback_data* cb_data) {
|
||||
if(handlers->usb_handle)
|
||||
return cypress_libusb_cancell_callback(cb_data);
|
||||
return cypress_driver_cancel_callback(handlers, usb_device_desc, cb_data);
|
||||
}
|
||||
|
||||
void SetupCypressDeviceAsyncThread(cyni_device_device_handlers* handlers, void* user_data, std::thread* thread_ptr, bool* keep_going, ConsumerMutex* is_data_ready) {
|
||||
if(handlers->usb_handle)
|
||||
return cypress_libusb_start_thread(thread_ptr, keep_going);
|
||||
return cypress_driver_start_thread(thread_ptr, keep_going, (CypressDeviceCaptureReceivedData*)user_data, handlers, is_data_ready);
|
||||
}
|
||||
|
||||
void EndCypressDeviceAsyncThread(cyni_device_device_handlers* handlers, void* user_data, std::thread* thread_ptr, bool* keep_going, ConsumerMutex* is_data_ready) {
|
||||
if(handlers->usb_handle)
|
||||
return cypress_libusb_close_thread(thread_ptr, keep_going);
|
||||
return cypress_driver_close_thread(thread_ptr, keep_going, (CypressDeviceCaptureReceivedData*)user_data);
|
||||
}
|
||||
@@ -0,0 +1,716 @@
|
||||
#include "cypress_nisetro_driver_comms.hpp"
|
||||
#include "cypress_nisetro_acquisition_general.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#ifdef _WIN32
|
||||
#include <setupapi.h>
|
||||
#include <devioctl.h>
|
||||
|
||||
#define BASE_IOCTL_INDEX 0
|
||||
|
||||
#define DIR_HOST_TO_DEVICE 0
|
||||
#define DIR_DEVICE_TO_HOST 1
|
||||
|
||||
#define IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER CTL_CODE(FILE_DEVICE_UNKNOWN, BASE_IOCTL_INDEX + 8, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_ADAPT_SEND_NON_EP0_DIRECT CTL_CODE(FILE_DEVICE_UNKNOWN, BASE_IOCTL_INDEX + 18, METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
#define IOCTL_ADAPT_RESET_PIPE CTL_CODE(FILE_DEVICE_UNKNOWN, BASE_IOCTL_INDEX + 11, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_ADAPT_SET_TRANSFER_SIZE CTL_CODE(FILE_DEVICE_UNKNOWN, BASE_IOCTL_INDEX + 14, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_ADAPT_ABORT_PIPE CTL_CODE(FILE_DEVICE_UNKNOWN, BASE_IOCTL_INDEX + 17, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#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
|
||||
|
||||
#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
|
||||
|
||||
#define TARGET_DEVICE 0
|
||||
#define REQUEST_STANDARD 0
|
||||
#define REQUEST_VENDOR 2
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct PACKED USB_COMMON_DESCRIPTOR {
|
||||
UCHAR bLength;
|
||||
UCHAR bDescriptorType;
|
||||
};
|
||||
|
||||
struct PACKED USB_STRING_DESCRIPTOR {
|
||||
UCHAR bLength;
|
||||
UCHAR bDescriptorType;
|
||||
WCHAR bString[1];
|
||||
};
|
||||
|
||||
struct PACKED 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;
|
||||
};
|
||||
|
||||
// Is this fine? Without any check for endianness?
|
||||
// Shouldn't all of this be packed?!
|
||||
struct PACKED CYPRESS_WORD_SPLIT {
|
||||
UCHAR lowByte;
|
||||
UCHAR hiByte;
|
||||
};
|
||||
|
||||
struct PACKED CYPRESS_BM_REQ_TYPE {
|
||||
UCHAR Recipient:2;
|
||||
UCHAR Reserved:3;
|
||||
UCHAR Type:2;
|
||||
UCHAR Direction:1;
|
||||
};
|
||||
|
||||
struct PACKED CYPRESS_SETUP_PACKET {
|
||||
union {
|
||||
CYPRESS_BM_REQ_TYPE bmReqType;
|
||||
UCHAR bmRequest;
|
||||
};
|
||||
UCHAR bRequest;
|
||||
union {
|
||||
CYPRESS_WORD_SPLIT wVal;
|
||||
USHORT wValue;
|
||||
};
|
||||
union {
|
||||
CYPRESS_WORD_SPLIT wIndx;
|
||||
USHORT wIndex;
|
||||
};
|
||||
union {
|
||||
CYPRESS_WORD_SPLIT wLen;
|
||||
USHORT wLength;
|
||||
};
|
||||
ULONG ulTimeOut;
|
||||
};
|
||||
|
||||
struct PACKED CYPRESS_ISO_ADV_PARAMS {
|
||||
USHORT isoId;
|
||||
USHORT isoCmd;
|
||||
ULONG ulParam1;
|
||||
ULONG ulParam2;
|
||||
};
|
||||
|
||||
struct PACKED CYPRESS_SINGLE_TRANSFER {
|
||||
union {
|
||||
CYPRESS_SETUP_PACKET SetupPacket;
|
||||
CYPRESS_ISO_ADV_PARAMS IsoParams;
|
||||
};
|
||||
|
||||
UCHAR reserved;
|
||||
|
||||
UCHAR ucEndpointAddress;
|
||||
ULONG NtStatus;
|
||||
ULONG UsbdStatus;
|
||||
ULONG IsoPacketOffset;
|
||||
ULONG IsoPacketLength;
|
||||
ULONG BufferOffset;
|
||||
ULONG BufferLength;
|
||||
};
|
||||
|
||||
struct PACKED CYPRESS_SET_TRANSFER_SIZE_INFO {
|
||||
UCHAR EndpointAddress;
|
||||
ULONG TransferSize;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
static GUID cypress_driver_guid = {.Data1 = 0xae18aa60, .Data2 = 0x7f6a, .Data3 = 0x11d4, .Data4 = {0x97, 0xdd, 0x0, 0x1, 0x2, 0x29, 0xb9, 0x59}};
|
||||
|
||||
static void cypress_driver_wait_async_transfers(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
|
||||
HANDLE to_wait_array[NUM_CAPTURE_RECEIVED_DATA_BUFFERS];
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
to_wait_array[i] = ((OVERLAPPED*)cypress_device_capture_recv_data[i].cb_data.base_transfer_data)->hEvent;
|
||||
WaitForMultipleObjects(NUM_CAPTURE_RECEIVED_DATA_BUFFERS, to_wait_array, false, 300);
|
||||
}
|
||||
|
||||
static bool cypress_driver_process_async_transfers(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, cyni_device_device_handlers* handlers) {
|
||||
bool found = false;
|
||||
for (int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
cyni_async_callback_data* cb_data = (cyni_async_callback_data*)&cypress_device_capture_recv_data[i].cb_data;
|
||||
bool possible_result = false;
|
||||
bool is_data_ready = false;
|
||||
cb_data->transfer_data_access.lock();
|
||||
possible_result = cb_data->transfer_data != NULL;
|
||||
is_data_ready = cb_data->is_data_ready;
|
||||
cb_data->transfer_data_access.unlock();
|
||||
if(cypress_device_capture_recv_data[i].in_use && is_data_ready)
|
||||
found = true;
|
||||
if(cypress_device_capture_recv_data[i].in_use && possible_result) {
|
||||
DWORD bytes_transferred = 0;
|
||||
int error = 0;
|
||||
if(!GetOverlappedResult(handlers->read_handle, (OVERLAPPED*)cb_data->transfer_data, &bytes_transferred, false))
|
||||
error = GetLastError();
|
||||
if(error == ERROR_IO_INCOMPLETE) {
|
||||
const auto curr_time = std::chrono::high_resolution_clock::now();
|
||||
const std::chrono::duration<double> diff = curr_time - cb_data->start_request;
|
||||
if(diff.count() > cb_data->timeout_s)
|
||||
error_cypress_device_status(cypress_device_capture_recv_data, LIBUSB_ERROR_TIMEOUT);
|
||||
}
|
||||
if(error != ERROR_IO_INCOMPLETE) {
|
||||
CYPRESS_SINGLE_TRANSFER* transfer_info = (CYPRESS_SINGLE_TRANSFER*)cb_data->extra_transfer_data;
|
||||
if(!error) {
|
||||
error = transfer_info->UsbdStatus;
|
||||
if(!error)
|
||||
error = transfer_info->NtStatus;
|
||||
}
|
||||
cb_data->actual_length = bytes_transferred;
|
||||
cb_data->status_value = error;
|
||||
cb_data->transfer_data = NULL;
|
||||
cb_data->is_data_ready = true;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
static void cypress_driver_function(bool* usb_thread_run, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, cyni_device_device_handlers* handlers) {
|
||||
int ret = 0;
|
||||
while(*usb_thread_run) {
|
||||
if(cypress_driver_process_async_transfers(cypress_device_capture_recv_data, handlers)) {
|
||||
for (int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
cyni_async_callback_data* cb_data = (cyni_async_callback_data*)&cypress_device_capture_recv_data[i].cb_data;
|
||||
bool is_data_ready = false;
|
||||
cb_data->transfer_data_access.lock();
|
||||
is_data_ready = cb_data->is_data_ready;
|
||||
cb_data->transfer_data_access.unlock();
|
||||
if(cypress_device_capture_recv_data[i].in_use && is_data_ready) {
|
||||
cb_data->is_data_ready = false;
|
||||
cb_data->function(&cypress_device_capture_recv_data[i], cb_data->actual_length, cb_data->status_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
cypress_driver_wait_async_transfers(cypress_device_capture_recv_data);
|
||||
}
|
||||
}
|
||||
|
||||
static bool cypress_driver_bulk_async_start(HANDLE handle, uint8_t* buffer, size_t size, DWORD* num_read, uint8_t ep_num, OVERLAPPED* overlap, CYPRESS_SINGLE_TRANSFER* single_transfer) {
|
||||
memset(single_transfer, 0, sizeof(CYPRESS_SINGLE_TRANSFER));
|
||||
single_transfer->ucEndpointAddress = ep_num;
|
||||
bool retval = DeviceIoControl(handle, IOCTL_ADAPT_SEND_NON_EP0_DIRECT, single_transfer, sizeof(CYPRESS_SINGLE_TRANSFER), buffer, size, num_read, overlap);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool cypress_driver_bulk_sync_start(HANDLE handle, uint8_t* buffer, size_t size, DWORD* num_read, uint8_t ep_num) {
|
||||
CYPRESS_SINGLE_TRANSFER single_transfer;
|
||||
return cypress_driver_bulk_async_start(handle, buffer, size, num_read, ep_num, NULL, &single_transfer);
|
||||
}
|
||||
|
||||
static bool cypress_driver_generic_ctrl_transfer(HANDLE handle, uint8_t* buffer, size_t inner_size, uint8_t val_hi, uint8_t val_low, uint16_t index, uint16_t timeout_s, uint8_t recipient, uint8_t type, uint8_t direction, uint16_t request_code, DWORD* num_read) {
|
||||
size_t full_size = inner_size + sizeof(CYPRESS_SINGLE_TRANSFER);
|
||||
uint8_t* full_buffer = new uint8_t[full_size];
|
||||
memset(full_buffer, 0, full_size);
|
||||
CYPRESS_SINGLE_TRANSFER* single_transfer = (CYPRESS_SINGLE_TRANSFER*)full_buffer;
|
||||
single_transfer->SetupPacket.bmReqType.Direction = direction;
|
||||
single_transfer->SetupPacket.bmReqType.Type = type;
|
||||
single_transfer->SetupPacket.bmReqType.Recipient = recipient;
|
||||
single_transfer->SetupPacket.bRequest = request_code;
|
||||
single_transfer->SetupPacket.wVal.hiByte = val_hi;
|
||||
single_transfer->SetupPacket.wVal.lowByte = val_low;
|
||||
single_transfer->SetupPacket.wIndex = index;
|
||||
single_transfer->SetupPacket.wLength = inner_size;
|
||||
single_transfer->SetupPacket.ulTimeOut = timeout_s;
|
||||
single_transfer->BufferLength = single_transfer->SetupPacket.wLength;
|
||||
single_transfer->BufferOffset = sizeof(CYPRESS_SINGLE_TRANSFER);
|
||||
if(direction == DIR_HOST_TO_DEVICE)
|
||||
memcpy(full_buffer + single_transfer->BufferOffset, buffer, inner_size);
|
||||
bool retval = DeviceIoControl(handle, IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, full_buffer, full_size, full_buffer, full_size, num_read, NULL);
|
||||
if((*num_read) >= sizeof(CYPRESS_SINGLE_TRANSFER))
|
||||
*num_read -= sizeof(CYPRESS_SINGLE_TRANSFER);
|
||||
else
|
||||
*num_read = 0;
|
||||
if(direction == DIR_DEVICE_TO_HOST)
|
||||
memcpy(buffer, full_buffer + single_transfer->BufferOffset, inner_size);
|
||||
delete []full_buffer;
|
||||
if((*num_read) != inner_size)
|
||||
return false;
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool read_cypress_driver_generic_info(HANDLE handle, uint8_t* buffer, size_t inner_size, uint8_t val_hi, uint8_t val_low, uint16_t index, DWORD* num_read) {
|
||||
return cypress_driver_generic_ctrl_transfer(handle, buffer, inner_size, val_hi, val_low, index, 5, TARGET_DEVICE, REQUEST_STANDARD, DIR_DEVICE_TO_HOST, USB_REQUEST_GET_DESCRIPTOR, num_read);
|
||||
}
|
||||
|
||||
static bool read_cypress_driver_device_info(HANDLE handle, uint8_t* buffer, size_t inner_size, DWORD* num_read) {
|
||||
return read_cypress_driver_generic_info(handle, buffer, inner_size, USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, num_read);
|
||||
}
|
||||
|
||||
static bool cypress_driver_get_string_language_info(HANDLE handle, USHORT &language_id, USHORT preferred_language = 0x0409) {
|
||||
USB_COMMON_DESCRIPTOR cmnDescriptor;
|
||||
DWORD num_read = 0;
|
||||
language_id = 0;
|
||||
bool retval = read_cypress_driver_generic_info(handle, (uint8_t*)&cmnDescriptor, sizeof(cmnDescriptor), USB_STRING_DESCRIPTOR_TYPE, 0, 0, &num_read);
|
||||
if(!retval)
|
||||
return false;
|
||||
if(cmnDescriptor.bLength == 2)
|
||||
return true;
|
||||
uint8_t* buffer = new uint8_t[cmnDescriptor.bLength];
|
||||
retval = read_cypress_driver_generic_info(handle, buffer, cmnDescriptor.bLength, USB_STRING_DESCRIPTOR_TYPE, 0, 0, &num_read);
|
||||
if(retval) {
|
||||
USB_STRING_DESCRIPTOR* IDs = (USB_STRING_DESCRIPTOR*)buffer;
|
||||
int num_langs = (cmnDescriptor.bLength - 2) / 2;
|
||||
language_id = IDs[0].bString[0];
|
||||
for(int i = 0; i < num_langs; i++)
|
||||
if(IDs[i].bString[0] == preferred_language)
|
||||
language_id = preferred_language;
|
||||
}
|
||||
delete []buffer;
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool cypress_driver_get_string_info(HANDLE handle, UCHAR string_index, USHORT language_id, std::string &out_str) {
|
||||
USB_COMMON_DESCRIPTOR cmnDescriptor;
|
||||
DWORD num_read = 0;
|
||||
out_str = "";
|
||||
bool retval = read_cypress_driver_generic_info(handle, (uint8_t*)&cmnDescriptor, sizeof(cmnDescriptor), USB_STRING_DESCRIPTOR_TYPE, string_index, language_id, &num_read);
|
||||
if(!retval)
|
||||
return false;
|
||||
uint8_t* buffer = new uint8_t[cmnDescriptor.bLength];
|
||||
retval = read_cypress_driver_generic_info(handle, buffer, cmnDescriptor.bLength, USB_STRING_DESCRIPTOR_TYPE, string_index, language_id, &num_read);
|
||||
if(retval && num_read >= 2) {
|
||||
uint8_t bytes = buffer[0];
|
||||
if(bytes > num_read)
|
||||
bytes = num_read;
|
||||
uint8_t signature = buffer[1];
|
||||
if((signature == 3) && (bytes > 2))
|
||||
out_str = read_string(buffer, bytes - 2);
|
||||
}
|
||||
delete []buffer;
|
||||
return retval;
|
||||
}
|
||||
|
||||
static std::string cypress_driver_get_device_path(HDEVINFO DeviceInfoSet, SP_DEVICE_INTERFACE_DATA* DeviceInterfaceData) {
|
||||
std::string result = "";
|
||||
// Call this with an empty buffer to the required size of the structure.
|
||||
ULONG requiredSize;
|
||||
SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, DeviceInterfaceData, NULL, 0, &requiredSize, NULL);
|
||||
if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
return result;
|
||||
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA devInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)(new uint8_t[requiredSize]);
|
||||
if(!devInterfaceDetailData)
|
||||
return result;
|
||||
|
||||
devInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
|
||||
if(SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, DeviceInterfaceData, devInterfaceDetailData, requiredSize, &requiredSize, NULL))
|
||||
result = (std::string)(devInterfaceDetailData->DevicePath);
|
||||
|
||||
delete []((uint8_t*)devInterfaceDetailData);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool cypress_driver_get_device_pid_vid_ids(HANDLE handle, uint16_t& out_vid, uint16_t& out_pid, UCHAR &imanufacturer, UCHAR &iserial, USHORT &bcdDevice) {
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
USB_DEVICE_DESCRIPTOR out_descriptor;
|
||||
memset(&out_descriptor, 0, sizeof(out_descriptor));
|
||||
DWORD num_read = 0;
|
||||
bool result = read_cypress_driver_device_info(handle, (uint8_t*)&out_descriptor, sizeof(USB_DEVICE_DESCRIPTOR), &num_read);
|
||||
if(!result)
|
||||
return false;
|
||||
out_vid = out_descriptor.idVendor;
|
||||
out_pid = out_descriptor.idProduct;
|
||||
imanufacturer = out_descriptor.iManufacturer;
|
||||
iserial = out_descriptor.iSerialNumber;
|
||||
bcdDevice = out_descriptor.bcdDevice;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cypress_driver_get_device_pid_vid_manufacturer_serial_number(std::string path, uint16_t& out_vid, uint16_t& out_pid, std::string &manufacturer, std::string &serial, uint16_t& bcd_device) {
|
||||
HANDLE handle = CreateFile(path.c_str(), (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
UCHAR imanufacturer;
|
||||
UCHAR iserial;
|
||||
if(!cypress_driver_get_device_pid_vid_ids(handle, out_vid, out_pid, imanufacturer, iserial, bcd_device)) {
|
||||
CloseHandle(handle);
|
||||
return false;
|
||||
}
|
||||
USHORT language = 0;
|
||||
cypress_driver_get_string_language_info(handle, language);
|
||||
cypress_driver_get_string_info(handle, imanufacturer, language, manufacturer);
|
||||
cypress_driver_get_string_info(handle, iserial, language, serial);
|
||||
CloseHandle(handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cypress_nisetro_driver_setup_connection(cyni_device_device_handlers* handlers, std::string path, bool do_pipe_clear_reset) {
|
||||
handlers->usb_handle = NULL;
|
||||
handlers->mutex = NULL;
|
||||
handlers->write_handle = INVALID_HANDLE_VALUE;
|
||||
handlers->read_handle = INVALID_HANDLE_VALUE;
|
||||
handlers->path = path;
|
||||
std::string mutex_name = "Global\\ISU_" + path.substr(4);
|
||||
std::replace(mutex_name.begin(), mutex_name.end(), '\\', '@');
|
||||
handlers->mutex = CreateMutex(NULL, true, mutex_name.c_str());
|
||||
if((handlers->mutex != NULL) && (GetLastError() == ERROR_ALREADY_EXISTS)) {
|
||||
CloseHandle(handlers->mutex);
|
||||
handlers->mutex = NULL;
|
||||
}
|
||||
if(handlers->mutex == NULL)
|
||||
return false;
|
||||
handlers->write_handle = CreateFile(path.c_str(), (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
||||
handlers->read_handle = handlers->write_handle;
|
||||
if((handlers->write_handle == INVALID_HANDLE_VALUE) || (handlers->read_handle == INVALID_HANDLE_VALUE))
|
||||
return false;
|
||||
if(do_pipe_clear_reset) {
|
||||
/*
|
||||
if(!is_driver_device_reset(handlers->write_handle))
|
||||
return false;
|
||||
if(!is_driver_pipe_reset(handlers->write_handle))
|
||||
return false;
|
||||
if(!is_driver_pipe_reset(handlers->read_handle))
|
||||
return false;
|
||||
*/
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void cypress_nisetro_driver_close_handle(void** handle, void* default_value = INVALID_HANDLE_VALUE) {
|
||||
#ifdef _WIN32
|
||||
if ((*handle) == default_value)
|
||||
return;
|
||||
CloseHandle(*handle);
|
||||
*handle = default_value;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void cypress_driver_pipe_reset(HANDLE handle, uint8_t endpoint) {
|
||||
DWORD dwBytes = 0;
|
||||
DeviceIoControl(handle, IOCTL_ADAPT_RESET_PIPE, &endpoint, sizeof(uint8_t), NULL, 0, &dwBytes, 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
cyni_device_device_handlers* cypress_driver_serial_reconnection(CaptureDevice* device) {
|
||||
cyni_device_device_handlers* final_handlers = NULL;
|
||||
#ifdef _WIN32
|
||||
if(device->path != "") {
|
||||
cyni_device_device_handlers handlers;
|
||||
const cyni_device_usb_device* usb_device_info = (const cyni_device_usb_device*)device->descriptor;
|
||||
if(cypress_nisetro_driver_setup_connection(&handlers, device->path, usb_device_info->do_pipe_clear_reset)) {
|
||||
final_handlers = new cyni_device_device_handlers;
|
||||
final_handlers->usb_handle = NULL;
|
||||
final_handlers->mutex = handlers.mutex;
|
||||
final_handlers->read_handle = handlers.read_handle;
|
||||
final_handlers->write_handle = handlers.write_handle;
|
||||
final_handlers->path = device->path;
|
||||
}
|
||||
else
|
||||
cypress_nisetro_driver_end_connection(&handlers);
|
||||
}
|
||||
#endif
|
||||
return final_handlers;
|
||||
}
|
||||
|
||||
void cypress_driver_list_devices(std::vector<CaptureDevice> &devices_list, bool* not_supported_elems, int *curr_serial_extra_id_cypress, const size_t num_cypress_desc) {
|
||||
#ifdef _WIN32
|
||||
HDEVINFO DeviceInfoSet = SetupDiGetClassDevs(
|
||||
&cypress_driver_guid,
|
||||
NULL,
|
||||
NULL,
|
||||
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
|
||||
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
|
||||
ZeroMemory(&DeviceInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA));
|
||||
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
uint32_t i = 0;
|
||||
while(SetupDiEnumDeviceInterfaces(DeviceInfoSet, NULL, &cypress_driver_guid, i++, &DeviceInterfaceData)) {
|
||||
std::string path = cypress_driver_get_device_path(DeviceInfoSet, &DeviceInterfaceData);
|
||||
if (path == "")
|
||||
continue;
|
||||
uint16_t vid = 0;
|
||||
uint16_t pid = 0;
|
||||
uint16_t bcd_device = 0;
|
||||
std::string manufacturer;
|
||||
std::string serial;
|
||||
if(!cypress_driver_get_device_pid_vid_manufacturer_serial_number(path, vid, pid, manufacturer, serial, bcd_device))
|
||||
continue;
|
||||
for (int j = 0; j < num_cypress_desc; j++) {
|
||||
const cyni_device_usb_device* usb_device_desc = GetCyNiDeviceDesc(j);
|
||||
if(not_supported_elems[j] && (usb_device_desc->vid == vid) && (usb_device_desc->pid == pid)) {
|
||||
cyni_device_device_handlers handlers;
|
||||
bool result_conn_check = cypress_nisetro_driver_setup_connection(&handlers, path, usb_device_desc->do_pipe_clear_reset);
|
||||
cypress_nisetro_driver_end_connection(&handlers);
|
||||
if(result_conn_check)
|
||||
cypress_insert_device(devices_list, usb_device_desc, serial, bcd_device, curr_serial_extra_id_cypress[j], path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(DeviceInfoSet)
|
||||
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
|
||||
#endif
|
||||
}
|
||||
|
||||
cyni_device_device_handlers* cypress_driver_find_by_serial_number(const cyni_device_usb_device* usb_device_desc, std::string wanted_serial_number, int &curr_serial_extra_id, CaptureDevice* new_device) {
|
||||
cyni_device_device_handlers* final_handlers = NULL;
|
||||
#ifdef _WIN32
|
||||
HDEVINFO DeviceInfoSet = SetupDiGetClassDevs(
|
||||
&cypress_driver_guid,
|
||||
NULL,
|
||||
NULL,
|
||||
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
|
||||
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
|
||||
ZeroMemory(&DeviceInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA));
|
||||
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
uint32_t i = 0;
|
||||
while(SetupDiEnumDeviceInterfaces(DeviceInfoSet, NULL, &cypress_driver_guid, i++, &DeviceInterfaceData)) {
|
||||
std::string path = cypress_driver_get_device_path(DeviceInfoSet, &DeviceInterfaceData);
|
||||
if (path == "")
|
||||
continue;
|
||||
uint16_t vid = 0;
|
||||
uint16_t pid = 0;
|
||||
uint16_t bcd_device = 0;
|
||||
std::string manufacturer;
|
||||
std::string serial;
|
||||
if(!cypress_driver_get_device_pid_vid_manufacturer_serial_number(path, vid, pid, manufacturer, serial, bcd_device))
|
||||
continue;
|
||||
std::string read_serial = get_serial(usb_device_desc, serial, bcd_device, curr_serial_extra_id);
|
||||
if((usb_device_desc->vid == vid) && (usb_device_desc->pid == pid) && (wanted_serial_number == read_serial)) {
|
||||
cyni_device_device_handlers handlers;
|
||||
if(cypress_nisetro_driver_setup_connection(&handlers, path, usb_device_desc->do_pipe_clear_reset)) {
|
||||
final_handlers = new cyni_device_device_handlers;
|
||||
final_handlers->usb_handle = NULL;
|
||||
final_handlers->mutex = handlers.mutex;
|
||||
final_handlers->read_handle = handlers.read_handle;
|
||||
final_handlers->write_handle = handlers.write_handle;
|
||||
final_handlers->path = path;
|
||||
if(new_device != NULL)
|
||||
*new_device = cypress_create_device(usb_device_desc, wanted_serial_number, path);
|
||||
}
|
||||
else
|
||||
cypress_nisetro_driver_end_connection(&handlers);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(DeviceInfoSet)
|
||||
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
|
||||
#endif
|
||||
return final_handlers;
|
||||
}
|
||||
|
||||
int cypress_driver_ctrl_transfer_in(cyni_device_device_handlers* handlers, uint8_t* buffer, size_t inner_size, uint16_t value, uint16_t index, uint16_t request_code, int* num_read) {
|
||||
#ifdef _WIN32
|
||||
DWORD dummy = 0;
|
||||
bool retval = cypress_driver_generic_ctrl_transfer(handlers->read_handle, buffer, inner_size, (value >> 8) & 0xFF, value & 0xFF, index, 1, TARGET_DEVICE, REQUEST_VENDOR, DIR_DEVICE_TO_HOST, request_code, &dummy);
|
||||
*num_read = dummy;
|
||||
return retval ? 0 : -1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int cypress_driver_ctrl_transfer_out(cyni_device_device_handlers* handlers, uint8_t* buffer, size_t inner_size, uint16_t value, uint16_t index, uint16_t request_code, int* num_read) {
|
||||
#ifdef _WIN32
|
||||
DWORD dummy = 0;
|
||||
bool retval = cypress_driver_generic_ctrl_transfer(handlers->write_handle, buffer, inner_size, (value >> 8) & 0xFF, value & 0xFF, index, 1, TARGET_DEVICE, REQUEST_VENDOR, DIR_HOST_TO_DEVICE, request_code, &dummy);
|
||||
*num_read = dummy;
|
||||
return retval ? 0 : -1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void cypress_nisetro_driver_end_connection(cyni_device_device_handlers* handlers) {
|
||||
#ifdef _WIN32
|
||||
cypress_nisetro_driver_close_handle(&handlers->write_handle);
|
||||
handlers->read_handle = handlers->write_handle;
|
||||
cypress_nisetro_driver_close_handle(&handlers->mutex, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
int cypress_driver_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred) {
|
||||
int result = LIBUSB_SUCCESS;
|
||||
#ifdef _WIN32
|
||||
DWORD inner_transfered = 0;
|
||||
if(!cypress_driver_bulk_sync_start(handlers->read_handle, buf, length, &inner_transfered, usb_device_desc->ep_bulk_in))
|
||||
result = -1;
|
||||
*transferred = inner_transfered;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
int cypress_driver_ctrl_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred) {
|
||||
int result = LIBUSB_SUCCESS;
|
||||
#ifdef _WIN32
|
||||
DWORD inner_transfered = 0;
|
||||
if(!cypress_driver_bulk_sync_start(handlers->read_handle, buf, length, &inner_transfered, usb_device_desc->ep_ctrl_bulk_in))
|
||||
result = -1;
|
||||
*transferred = inner_transfered;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
int cypress_driver_ctrl_bulk_out(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred) {
|
||||
int result = LIBUSB_SUCCESS;
|
||||
#ifdef _WIN32
|
||||
DWORD inner_transfered = 0;
|
||||
if(!cypress_driver_bulk_sync_start(handlers->write_handle, buf, length, &inner_transfered, usb_device_desc->ep_ctrl_bulk_out))
|
||||
result = -1;
|
||||
*transferred = inner_transfered;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
void cypress_driver_pipe_reset_ctrl_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc) {
|
||||
#ifdef _WIN32
|
||||
cypress_driver_pipe_reset(handlers->read_handle, usb_device_desc->ep_ctrl_bulk_in);
|
||||
#endif
|
||||
}
|
||||
|
||||
void cypress_driver_pipe_reset_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc) {
|
||||
#ifdef _WIN32
|
||||
cypress_driver_pipe_reset(handlers->read_handle, usb_device_desc->ep_bulk_in);
|
||||
#endif
|
||||
}
|
||||
|
||||
void cypress_driver_pipe_reset_ctrl_bulk_out(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc) {
|
||||
#ifdef _WIN32
|
||||
cypress_driver_pipe_reset(handlers->read_handle, usb_device_desc->ep_ctrl_bulk_out);
|
||||
#endif
|
||||
}
|
||||
|
||||
void cypress_driver_find_used_serial(const cyni_device_usb_device* usb_device_desc, bool* found, size_t num_free_fw_ids, int &curr_serial_extra_id) {
|
||||
#ifdef _WIN32
|
||||
HDEVINFO DeviceInfoSet = SetupDiGetClassDevs(
|
||||
&cypress_driver_guid,
|
||||
NULL,
|
||||
NULL,
|
||||
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
|
||||
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
|
||||
ZeroMemory(&DeviceInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA));
|
||||
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
uint32_t i = 0;
|
||||
while(SetupDiEnumDeviceInterfaces(DeviceInfoSet, NULL, &cypress_driver_guid, i++, &DeviceInterfaceData)) {
|
||||
std::string path = cypress_driver_get_device_path(DeviceInfoSet, &DeviceInterfaceData);
|
||||
if (path == "")
|
||||
continue;
|
||||
uint16_t vid = 0;
|
||||
uint16_t pid = 0;
|
||||
uint16_t bcd_device = 0;
|
||||
std::string manufacturer;
|
||||
std::string serial;
|
||||
if(!cypress_driver_get_device_pid_vid_manufacturer_serial_number(path, vid, pid, manufacturer, serial, bcd_device))
|
||||
continue;
|
||||
std::string read_serial = get_serial(usb_device_desc, serial, bcd_device, curr_serial_extra_id);
|
||||
if((usb_device_desc->vid == vid) && (usb_device_desc->pid == pid)) {
|
||||
try {
|
||||
int pos = std::stoi(read_serial);
|
||||
if((pos < 0) || (pos >= num_free_fw_ids))
|
||||
continue;
|
||||
found[pos] = true;
|
||||
}
|
||||
catch(...) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(DeviceInfoSet)
|
||||
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
|
||||
#endif
|
||||
}
|
||||
|
||||
int cypress_driver_async_in_start(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, cyni_async_callback_data* cb_data) {
|
||||
#ifdef _WIN32
|
||||
cb_data->transfer_data_access.lock();
|
||||
cb_data->transfer_data = cb_data->base_transfer_data;
|
||||
cb_data->handle = handlers->read_handle;
|
||||
cb_data->requested_length = length;
|
||||
cb_data->buffer = buf;
|
||||
cb_data->start_request = std::chrono::high_resolution_clock::now();
|
||||
cb_data->timeout_s = usb_device_desc->bulk_timeout / 1000.0;
|
||||
OVERLAPPED* overlap_data = (OVERLAPPED*)cb_data->transfer_data;
|
||||
cb_data->is_transfer_done_mutex->specific_try_lock(cb_data->internal_index);
|
||||
int retval = cypress_driver_bulk_async_start(cb_data->handle, cb_data->buffer, cb_data->requested_length, NULL, usb_device_desc->ep_bulk_in, overlap_data, (CYPRESS_SINGLE_TRANSFER*)cb_data->extra_transfer_data);
|
||||
cb_data->transfer_data_access.unlock();
|
||||
if(!retval) {
|
||||
int error = GetLastError();
|
||||
if(error != ERROR_IO_PENDING)
|
||||
return LIBUSB_ERROR_BUSY;
|
||||
}
|
||||
#endif
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
void cypress_driver_start_thread(std::thread* thread_ptr, bool* usb_thread_run, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, cyni_device_device_handlers* handlers, ConsumerMutex* AsyncMutexPtr) {
|
||||
#ifdef _WIN32
|
||||
*usb_thread_run = true;
|
||||
for (int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
cypress_device_capture_recv_data[i].cb_data.extra_transfer_data = new CYPRESS_SINGLE_TRANSFER;
|
||||
cypress_device_capture_recv_data[i].cb_data.base_transfer_data = new OVERLAPPED;
|
||||
((OVERLAPPED*)cypress_device_capture_recv_data[i].cb_data.base_transfer_data)->hEvent = CreateEvent(NULL, false, false, NULL);
|
||||
}
|
||||
*thread_ptr = std::thread(cypress_driver_function, usb_thread_run, cypress_device_capture_recv_data, handlers);
|
||||
#endif
|
||||
}
|
||||
|
||||
void cypress_driver_close_thread(std::thread* thread_ptr, bool* usb_thread_run, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
|
||||
#ifdef _WIN32
|
||||
*usb_thread_run = false;
|
||||
thread_ptr->join();
|
||||
for (int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
CloseHandle(((OVERLAPPED*)cypress_device_capture_recv_data[i].cb_data.base_transfer_data)->hEvent);
|
||||
delete ((OVERLAPPED*)cypress_device_capture_recv_data[i].cb_data.base_transfer_data);
|
||||
delete ((CYPRESS_SINGLE_TRANSFER*)cypress_device_capture_recv_data[i].cb_data.extra_transfer_data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void cypress_driver_cancel_callback(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, cyni_async_callback_data* cb_data) {
|
||||
#ifdef _WIN32
|
||||
DWORD transferred = 0;
|
||||
OVERLAPPED ov;
|
||||
memset(&ov, 0, sizeof(OVERLAPPED));
|
||||
ov.hEvent = CreateEvent(NULL, false, false, NULL);
|
||||
uint8_t pipe = usb_device_desc->ep_bulk_in;
|
||||
bool ret = DeviceIoControl(handlers->read_handle, IOCTL_ADAPT_ABORT_PIPE, &pipe, sizeof(uint8_t), NULL, 0, &transferred, &ov);
|
||||
if((!ret) && (GetLastError() == ERROR_IO_PENDING))
|
||||
WaitForSingleObject(ov.hEvent, INFINITE);
|
||||
CloseHandle(ov.hEvent);
|
||||
#endif
|
||||
}
|
||||
|
||||
void cypress_driver_set_transfer_size_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, size_t new_transfer_size) {
|
||||
#ifdef _WIN32
|
||||
DWORD transferred;
|
||||
CYPRESS_SET_TRANSFER_SIZE_INFO SetTransferInfo;
|
||||
|
||||
new_transfer_size = ((new_transfer_size + usb_device_desc->max_usb_packet_size - 1) / usb_device_desc->max_usb_packet_size) * usb_device_desc->max_usb_packet_size;
|
||||
|
||||
SetTransferInfo.EndpointAddress = usb_device_desc->ep_bulk_in;
|
||||
SetTransferInfo.TransferSize = new_transfer_size;
|
||||
|
||||
DeviceIoControl(handlers->read_handle, IOCTL_ADAPT_SET_TRANSFER_SIZE, &SetTransferInfo, sizeof(CYPRESS_SET_TRANSFER_SIZE_INFO), &SetTransferInfo, sizeof(CYPRESS_SET_TRANSFER_SIZE_INFO), &transferred, NULL);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
#include "cypress_nisetro_libusb_comms.hpp"
|
||||
#include "cypress_nisetro_acquisition_general.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <libusb.h>
|
||||
#include "usb_generic.hpp"
|
||||
|
||||
static void cypress_device_usb_thread_function(bool* usb_thread_run) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 300000;
|
||||
while(*usb_thread_run)
|
||||
libusb_handle_events_timeout_completed(get_usb_ctx(), &tv, NULL);
|
||||
}
|
||||
|
||||
void cypress_libusb_start_thread(std::thread* thread_ptr, bool* usb_thread_run) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
*usb_thread_run = true;
|
||||
*thread_ptr = std::thread(cypress_device_usb_thread_function, usb_thread_run);
|
||||
}
|
||||
|
||||
void cypress_libusb_close_thread(std::thread* thread_ptr, bool* usb_thread_run) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
*usb_thread_run = false;
|
||||
thread_ptr->join();
|
||||
}
|
||||
|
||||
// Read from ctrl_in
|
||||
int cypress_libusb_ctrl_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, uint8_t request, uint16_t value, uint16_t index, int* transferred) {
|
||||
int ret = libusb_control_transfer(handlers->usb_handle, 0xC0, request, value, index, buf, length, usb_device_desc->bulk_timeout);
|
||||
if(ret >= 0)
|
||||
*transferred = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Write to ctrl_out
|
||||
int cypress_libusb_ctrl_out(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, uint8_t request, uint16_t value, uint16_t index, int* transferred) {
|
||||
int ret = libusb_control_transfer(handlers->usb_handle, 0x40, request, value, index, buf, length, usb_device_desc->bulk_timeout);
|
||||
if(ret >= 0)
|
||||
*transferred = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Read from bulk
|
||||
int cypress_libusb_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred) {
|
||||
return libusb_bulk_transfer(handlers->usb_handle, usb_device_desc->ep_bulk_in, buf, length, transferred, usb_device_desc->bulk_timeout);
|
||||
}
|
||||
|
||||
// Read from ctrl bulk
|
||||
int cypress_libusb_ctrl_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred) {
|
||||
return libusb_bulk_transfer(handlers->usb_handle, usb_device_desc->ep_ctrl_bulk_in, buf, length, transferred, usb_device_desc->bulk_timeout);
|
||||
}
|
||||
|
||||
// Write to ctrl bulk
|
||||
int cypress_libusb_ctrl_bulk_out(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred) {
|
||||
return libusb_bulk_transfer(handlers->usb_handle, usb_device_desc->ep_ctrl_bulk_out, buf, length, transferred, usb_device_desc->bulk_timeout);
|
||||
}
|
||||
|
||||
void cypress_libusb_pipe_reset_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc) {
|
||||
libusb_clear_halt(handlers->usb_handle, usb_device_desc->ep_bulk_in);
|
||||
}
|
||||
|
||||
void cypress_libusb_pipe_reset_ctrl_bulk_in(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc) {
|
||||
libusb_clear_halt(handlers->usb_handle, usb_device_desc->ep_ctrl_bulk_in);
|
||||
}
|
||||
|
||||
void cypress_libusb_pipe_reset_ctrl_bulk_out(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc) {
|
||||
libusb_clear_halt(handlers->usb_handle, usb_device_desc->ep_ctrl_bulk_out);
|
||||
}
|
||||
|
||||
void cypress_libusb_cancell_callback(cyni_async_callback_data* cb_data) {
|
||||
cb_data->transfer_data_access.lock();
|
||||
if(cb_data->transfer_data)
|
||||
libusb_cancel_transfer((libusb_transfer*)cb_data->transfer_data);
|
||||
cb_data->transfer_data_access.unlock();
|
||||
}
|
||||
|
||||
void STDCALL cypress_libusb_async_callback(libusb_transfer* transfer) {
|
||||
cyni_async_callback_data* cb_data = (cyni_async_callback_data*)transfer->user_data;
|
||||
cb_data->transfer_data_access.lock();
|
||||
cb_data->transfer_data = NULL;
|
||||
cb_data->is_transfer_done_mutex->specific_unlock(cb_data->internal_index);
|
||||
cb_data->transfer_data_access.unlock();
|
||||
cb_data->function(cb_data->actual_user_data, transfer->actual_length, transfer->status);
|
||||
}
|
||||
|
||||
// Read from bulk
|
||||
int cypress_libusb_async_in_start(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, uint8_t* buf, int length, cyni_async_callback_data* cb_data) {
|
||||
libusb_transfer *transfer_in = libusb_alloc_transfer(0);
|
||||
if(!transfer_in)
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
cb_data->transfer_data_access.lock();
|
||||
cb_data->transfer_data = transfer_in;
|
||||
cb_data->is_transfer_done_mutex->specific_try_lock(cb_data->internal_index);
|
||||
libusb_fill_bulk_transfer(transfer_in, handlers->usb_handle, usb_device_desc->ep_bulk_in, buf, length, cypress_libusb_async_callback, cb_data, usb_device_desc->bulk_timeout);
|
||||
transfer_in->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
||||
int retval = libusb_submit_transfer(transfer_in);
|
||||
cb_data->transfer_data_access.unlock();
|
||||
return retval;
|
||||
}
|
||||
|
||||
static bool cypress_libusb_setup_connection(libusb_device_handle* handle, const cyni_device_usb_device* usb_device_desc) {
|
||||
int result = libusb_kernel_driver_active(handle, usb_device_desc->default_interface);
|
||||
if(result == 1)
|
||||
libusb_detach_kernel_driver(handle, usb_device_desc->default_interface);
|
||||
result = libusb_set_configuration(handle, usb_device_desc->default_config);
|
||||
if(result != LIBUSB_SUCCESS)
|
||||
return false;
|
||||
result = libusb_kernel_driver_active(handle, usb_device_desc->default_interface);
|
||||
if(result == 1)
|
||||
libusb_detach_kernel_driver(handle, usb_device_desc->default_interface);
|
||||
result = libusb_claim_interface(handle, usb_device_desc->default_interface);
|
||||
if(result != LIBUSB_SUCCESS)
|
||||
return false;
|
||||
if(usb_device_desc->alt_interface != 0) {
|
||||
result = libusb_set_interface_alt_setting(handle, usb_device_desc->default_interface, usb_device_desc->alt_interface);
|
||||
if(result != LIBUSB_SUCCESS)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void read_strings(libusb_device_handle *handle, libusb_device_descriptor *usb_descriptor, char* manufacturer, char* serial) {
|
||||
manufacturer[0] = 0;
|
||||
serial[0] = 0;
|
||||
libusb_get_string_descriptor_ascii(handle, usb_descriptor->iManufacturer, (uint8_t*)manufacturer, 0x100);
|
||||
libusb_get_string_descriptor_ascii(handle, usb_descriptor->iSerialNumber, (uint8_t*)serial, 0x100);
|
||||
manufacturer[0xFF] = 0;
|
||||
serial[0xFF] = 0;
|
||||
}
|
||||
|
||||
static int cypress_libusb_insert_device(std::vector<CaptureDevice> &devices_list, const cyni_device_usb_device* usb_device_desc, libusb_device *usb_device, libusb_device_descriptor *usb_descriptor, int &curr_serial_extra_id) {
|
||||
libusb_device_handle *handle = NULL;
|
||||
if((usb_descriptor->idVendor != usb_device_desc->vid) || (usb_descriptor->idProduct != usb_device_desc->pid))
|
||||
return LIBUSB_ERROR_NOT_FOUND;
|
||||
int result = libusb_open(usb_device, &handle);
|
||||
if((result < 0) || (handle == NULL))
|
||||
return result;
|
||||
char manufacturer[0x100];
|
||||
char serial[0x100];
|
||||
read_strings(handle, usb_descriptor, manufacturer, serial);
|
||||
bool result_setup = cypress_libusb_setup_connection(handle, usb_device_desc);
|
||||
if(result_setup)
|
||||
cypress_insert_device(devices_list, usb_device_desc, (std::string)(serial), usb_descriptor->bcdDevice, curr_serial_extra_id);
|
||||
libusb_release_interface(handle, usb_device_desc->default_interface);
|
||||
libusb_close(handle);
|
||||
return result;
|
||||
}
|
||||
|
||||
cyni_device_device_handlers* cypress_libusb_serial_reconnection(const cyni_device_usb_device* usb_device_desc, std::string wanted_serial_number, int &curr_serial_extra_id, CaptureDevice* new_device) {
|
||||
if(!usb_is_initialized())
|
||||
return NULL;
|
||||
libusb_device **usb_devices;
|
||||
int num_devices = libusb_get_device_list(get_usb_ctx(), &usb_devices);
|
||||
libusb_device_descriptor usb_descriptor{};
|
||||
cyni_device_device_handlers* final_handlers = NULL;
|
||||
|
||||
for(int i = 0; i < num_devices; i++) {
|
||||
cyni_device_device_handlers handlers;
|
||||
int result = libusb_get_device_descriptor(usb_devices[i], &usb_descriptor);
|
||||
if(result < 0)
|
||||
continue;
|
||||
if((usb_descriptor.idVendor != usb_device_desc->vid) || (usb_descriptor.idProduct != usb_device_desc->pid))
|
||||
continue;
|
||||
result = libusb_open(usb_devices[i], &handlers.usb_handle);
|
||||
if(result || (handlers.usb_handle == NULL))
|
||||
continue;
|
||||
char manufacturer[0x100];
|
||||
char serial[0x100];
|
||||
read_strings(handlers.usb_handle, &usb_descriptor, manufacturer, serial);
|
||||
std::string device_serial_number = get_serial(usb_device_desc, (std::string)(serial), usb_descriptor.bcdDevice, curr_serial_extra_id);
|
||||
if((wanted_serial_number == device_serial_number) && (cypress_libusb_setup_connection(handlers.usb_handle, usb_device_desc))) {
|
||||
final_handlers = new cyni_device_device_handlers;
|
||||
final_handlers->usb_handle = handlers.usb_handle;
|
||||
if(new_device != NULL)
|
||||
*new_device = cypress_create_device(usb_device_desc, wanted_serial_number);
|
||||
break;
|
||||
}
|
||||
libusb_close(handlers.usb_handle);
|
||||
}
|
||||
|
||||
if(num_devices >= 0)
|
||||
libusb_free_device_list(usb_devices, 1);
|
||||
|
||||
return final_handlers;
|
||||
}
|
||||
|
||||
void cypress_libusb_end_connection(cyni_device_device_handlers* handlers, const cyni_device_usb_device* device_desc, bool interface_claimed) {
|
||||
if (interface_claimed)
|
||||
libusb_release_interface(handlers->usb_handle, device_desc->default_interface);
|
||||
libusb_close(handlers->usb_handle);
|
||||
handlers->usb_handle = NULL;
|
||||
}
|
||||
|
||||
void cypress_libusb_find_used_serial(const cyni_device_usb_device* usb_device_desc, bool* found, size_t num_free_fw_ids, int &curr_serial_extra_id) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
libusb_device **usb_devices;
|
||||
int num_devices = libusb_get_device_list(get_usb_ctx(), &usb_devices);
|
||||
libusb_device_descriptor usb_descriptor{};
|
||||
cyni_device_device_handlers* final_handlers = NULL;
|
||||
|
||||
for(int i = 0; i < num_devices; i++) {
|
||||
cyni_device_device_handlers handlers;
|
||||
int result = libusb_get_device_descriptor(usb_devices[i], &usb_descriptor);
|
||||
if(result < 0)
|
||||
continue;
|
||||
if((usb_descriptor.idVendor != usb_device_desc->vid) || (usb_descriptor.idProduct != usb_device_desc->pid))
|
||||
continue;
|
||||
result = libusb_open(usb_devices[i], &handlers.usb_handle);
|
||||
if(result || (handlers.usb_handle == NULL))
|
||||
continue;
|
||||
char manufacturer[0x100];
|
||||
char serial[0x100];
|
||||
read_strings(handlers.usb_handle, &usb_descriptor, manufacturer, serial);
|
||||
libusb_close(handlers.usb_handle);
|
||||
std::string device_serial_number = get_serial(usb_device_desc, (std::string)(serial), usb_descriptor.bcdDevice, curr_serial_extra_id);
|
||||
try {
|
||||
int pos = std::stoi(device_serial_number);
|
||||
if((pos < 0) || (pos >= num_free_fw_ids))
|
||||
continue;
|
||||
found[pos] = true;
|
||||
}
|
||||
catch(...) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(num_devices >= 0)
|
||||
libusb_free_device_list(usb_devices, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void cypress_libusb_list_devices(std::vector<CaptureDevice> &devices_list, bool* no_access_elems, bool* not_supported_elems, int *curr_serial_extra_id_cypress, const size_t num_cypress_desc) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
libusb_device **usb_devices;
|
||||
int num_devices = libusb_get_device_list(get_usb_ctx(), &usb_devices);
|
||||
libusb_device_descriptor usb_descriptor{};
|
||||
|
||||
for(int i = 0; i < num_devices; i++) {
|
||||
int result = libusb_get_device_descriptor(usb_devices[i], &usb_descriptor);
|
||||
if(result < 0)
|
||||
continue;
|
||||
for (int j = 0; j < num_cypress_desc; j++) {
|
||||
result = cypress_libusb_insert_device(devices_list, GetCyNiDeviceDesc(j), usb_devices[i], &usb_descriptor, curr_serial_extra_id_cypress[j]);
|
||||
if (result != LIBUSB_ERROR_NOT_FOUND) {
|
||||
if (result == LIBUSB_ERROR_ACCESS)
|
||||
no_access_elems[j] = true;
|
||||
if (result == LIBUSB_ERROR_NOT_SUPPORTED)
|
||||
not_supported_elems[j] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(num_devices >= 0)
|
||||
libusb_free_device_list(usb_devices, 1);
|
||||
}
|
||||
@@ -207,6 +207,20 @@ inline static void to_8_bit_6(uint8_t* out, uint8_t* in) {
|
||||
out[2] = to_8_bit_6(in[2]);
|
||||
}
|
||||
|
||||
static void usb_cypress_nisetro_ds_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out) {
|
||||
int pos_top = 0;
|
||||
int pos_bottom = WIDTH_DS * HEIGHT_DS * 3;
|
||||
uint8_t* data_in = (uint8_t*)p_in->cypress_nisetro_capture_received.video_in.screen_data;
|
||||
uint8_t* data_out = (uint8_t*)p_out->screen_data;
|
||||
for(int i = 0; i < sizeof(CypressNisetroDSCaptureReceived); i++) {
|
||||
uint8_t conv = to_8_bit_6(data_in[i]);
|
||||
if(data_in[i] & 0x40)
|
||||
data_out[pos_bottom++] = conv;
|
||||
else
|
||||
data_out[pos_top++] = conv;
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_is_device_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, CaptureStatus* status, CaptureScreensType capture_type) {
|
||||
bool is_nitro = true;
|
||||
#ifdef USE_IS_DEVICES_USB
|
||||
@@ -284,6 +298,12 @@ bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, Capt
|
||||
converted = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_CYNI_USB
|
||||
if(chosen_device->cc_type == CAPTURE_CONN_CYPRESS_NISETRO) {
|
||||
usb_cypress_nisetro_ds_convertVideoToOutput(p_in, p_out);
|
||||
converted = true;
|
||||
}
|
||||
#endif
|
||||
return converted;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "dscapture_ftd2_shared.hpp"
|
||||
#include "usb_ds_3ds_capture.hpp"
|
||||
#include "usb_is_device_acquisition.hpp"
|
||||
#include "cypress_nisetro_acquisition.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
@@ -78,6 +79,9 @@ bool connect(bool print_failed, CaptureData* capture_data, FrontendData* fronten
|
||||
// Device Listing
|
||||
std::vector<CaptureDevice> devices_list;
|
||||
std::vector<no_access_recap_data> no_access_list;
|
||||
#ifdef USE_CYNI_USB
|
||||
list_devices_cyni_device(devices_list, no_access_list);
|
||||
#endif
|
||||
#ifdef USE_FTD3
|
||||
list_devices_ftd3(devices_list, no_access_list);
|
||||
#endif
|
||||
@@ -115,6 +119,10 @@ bool connect(bool print_failed, CaptureData* capture_data, FrontendData* fronten
|
||||
}
|
||||
|
||||
// Actual connection
|
||||
#ifdef USE_CYNI_USB
|
||||
if((devices_list[chosen_device].cc_type == CAPTURE_CONN_CYPRESS_NISETRO) && (!cyni_device_connect_usb(print_failed, capture_data, &devices_list[chosen_device])))
|
||||
return false;
|
||||
#endif
|
||||
#ifdef USE_FTD3
|
||||
if((devices_list[chosen_device].cc_type == CAPTURE_CONN_FTD3) && (!connect_ftd3(print_failed, capture_data, &devices_list[chosen_device])))
|
||||
return false;
|
||||
@@ -151,6 +159,10 @@ void captureCall(CaptureData* capture_data) {
|
||||
}
|
||||
|
||||
// Main capture loop
|
||||
#ifdef USE_CYNI_USB
|
||||
if(capture_data->status.device.cc_type == CAPTURE_CONN_CYPRESS_NISETRO)
|
||||
cyni_device_acquisition_main_loop(capture_data);
|
||||
#endif
|
||||
#ifdef USE_FTD3
|
||||
if(capture_data->status.device.cc_type == CAPTURE_CONN_FTD3)
|
||||
ftd3_capture_main_loop(capture_data);
|
||||
@@ -177,6 +189,10 @@ void captureCall(CaptureData* capture_data) {
|
||||
capture_data->status.audio_wait.unlock();
|
||||
|
||||
// Capture cleanup
|
||||
#ifdef USE_CYNI_USB
|
||||
if(capture_data->status.device.cc_type == CAPTURE_CONN_CYPRESS_NISETRO)
|
||||
usb_cyni_device_acquisition_cleanup(capture_data);
|
||||
#endif
|
||||
#ifdef USE_FTD3
|
||||
if(capture_data->status.device.cc_type == CAPTURE_CONN_FTD3)
|
||||
ftd3_capture_cleanup(capture_data);
|
||||
@@ -214,6 +230,10 @@ uint64_t get_audio_n_samples(CaptureData* capture_data, uint64_t read) {
|
||||
}
|
||||
|
||||
uint64_t get_video_in_size(CaptureData* capture_data) {
|
||||
#ifdef USE_CYNI_USB
|
||||
if(capture_data->status.device.cc_type == CAPTURE_CONN_CYPRESS_NISETRO)
|
||||
return cyni_device_get_video_in_size(capture_data);
|
||||
#endif
|
||||
#ifdef USE_FTD3
|
||||
if(capture_data->status.device.cc_type == CAPTURE_CONN_FTD3)
|
||||
return ftd3_get_video_in_size(capture_data);
|
||||
@@ -251,6 +271,9 @@ void capture_init() {
|
||||
#ifdef USE_FTD2
|
||||
ftd2_init_shared();
|
||||
#endif
|
||||
#ifdef USE_CYNI_USB
|
||||
usb_cyni_device_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void capture_close() {
|
||||
@@ -263,4 +286,7 @@ void capture_close() {
|
||||
#ifdef USE_FTD2
|
||||
ftd2_end_shared();
|
||||
#endif
|
||||
#ifdef USE_CYNI_USB
|
||||
usb_cyni_device_close();
|
||||
#endif
|
||||
}
|
||||
|
||||
2
usb_rules/51-nisetro.rules
Normal file
2
usb_rules/51-nisetro.rules
Normal file
@@ -0,0 +1,2 @@
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="8613", MODE="0666"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="1004", MODE="0666"
|
||||
Reference in New Issue
Block a user