mirror of
https://github.com/Lorenzooone/cc3dsfs.git
synced 2026-04-19 11:27:24 -05:00
Refactor IS Nitro to IS Devices
This commit is contained in:
parent
8dc0347414
commit
7d7a481745
|
|
@ -8,12 +8,12 @@ include(ExternalProject)
|
|||
|
||||
set(N3DSXL_LOOPY_SUPPORT 1)
|
||||
set(NEW_DS_LOOPY_SUPPORT 1)
|
||||
set(IS_NITRO_SUPPORT 1)
|
||||
set(IS_DEVICES_SUPPORT 1)
|
||||
set(OLD_DS_3DS_LOOPY_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_NITRO_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})
|
||||
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)
|
||||
|
|
@ -291,7 +291,7 @@ set(FETCH_CONTENT_MAKE_AVAILABLE_LIBRARIES_SEPARATE "")
|
|||
set(SOURCE_CPP_EXTRA_FILES "")
|
||||
set(EXTRA_DEPENDENCIES "")
|
||||
set(SOURCE_CPP_DEVICE_FILES_BASE_PATH "source/CaptureDeviceSpecific")
|
||||
set(SOURCE_CPP_IS_NITRO_FILES_BASE_PATH "${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/ISNitro")
|
||||
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")
|
||||
if(N3DSXL_LOOPY_SUPPORT)
|
||||
list(APPEND FETCH_CONTENT_MAKE_AVAILABLE_LIBRARIES FTD3XX)
|
||||
|
|
@ -312,12 +312,12 @@ if(USE_LIBUSB_SUPPORT)
|
|||
list(APPEND EXTRA_CXX_FLAGS "-DUSE_LIBUSB")
|
||||
endif()
|
||||
endif()
|
||||
if(IS_NITRO_SUPPORT)
|
||||
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_communications.cpp ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_acquisition.cpp ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_acquisition_capture.cpp ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_acquisition_emulator.cpp ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_is_driver.cpp ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_libusb.cpp)
|
||||
if(IS_DEVICES_SUPPORT)
|
||||
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_IS_DEVICES_FILES_BASE_PATH}/usb_is_device_communications.cpp ${SOURCE_CPP_IS_DEVICES_FILES_BASE_PATH}/usb_is_device_acquisition.cpp ${SOURCE_CPP_IS_DEVICES_FILES_BASE_PATH}/usb_is_nitro_acquisition_capture.cpp ${SOURCE_CPP_IS_DEVICES_FILES_BASE_PATH}/usb_is_nitro_acquisition_emulator.cpp ${SOURCE_CPP_IS_DEVICES_FILES_BASE_PATH}/usb_is_device_is_driver.cpp ${SOURCE_CPP_IS_DEVICES_FILES_BASE_PATH}/usb_is_device_libusb.cpp)
|
||||
if(MSVC)
|
||||
list(APPEND EXTRA_CXX_FLAGS "/DUSE_IS_NITRO_USB")
|
||||
list(APPEND EXTRA_CXX_FLAGS "/DUSE_IS_DEVICES_USB")
|
||||
else()
|
||||
list(APPEND EXTRA_CXX_FLAGS "-DUSE_IS_NITRO_USB")
|
||||
list(APPEND EXTRA_CXX_FLAGS "-DUSE_IS_DEVICES_USB")
|
||||
endif()
|
||||
endif()
|
||||
if(OLD_DS_3DS_LOOPY_SUPPORT)
|
||||
|
|
@ -498,7 +498,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/ISNitro ${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/DSCapture_FTD2 ${libftdi1_SOURCE_DIR}/src)
|
||||
target_compile_features(${OUTPUT_NAME} PRIVATE cxx_std_20)
|
||||
target_compile_options(${OUTPUT_NAME} PRIVATE ${EXTRA_CXX_FLAGS})
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef __USB_IS_DEVICE_ACQUISITION_HPP
|
||||
#define __USB_IS_DEVICE_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_is_device(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list);
|
||||
bool is_device_connect_usb(bool print_failed, CaptureData* capture_data, CaptureDevice* device);
|
||||
void is_device_acquisition_main_loop(CaptureData* capture_data);
|
||||
void usb_is_device_acquisition_cleanup(CaptureData* capture_data);
|
||||
uint64_t usb_is_device_get_video_in_size(CaptureData* capture_data);
|
||||
uint64_t usb_is_device_get_video_in_size(CaptureStatus* capture_status);
|
||||
bool is_device_is_capture(CaptureDevice* device);
|
||||
bool is_device_is_nitro(CaptureDevice* device);
|
||||
void usb_is_device_init();
|
||||
void usb_is_device_close();
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef __USB_IS_DEVICE_ACQUISITION_GENERAL_HPP
|
||||
#define __USB_IS_DEVICE_ACQUISITION_GENERAL_HPP
|
||||
|
||||
#include "usb_is_device_communications.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "capture_structs.hpp"
|
||||
#include "display_structs.hpp"
|
||||
|
||||
#define NUM_CAPTURE_RECEIVED_DATA_BUFFERS 4
|
||||
|
||||
struct ISDeviceCaptureReceivedData {
|
||||
volatile bool in_use;
|
||||
uint32_t index;
|
||||
CaptureReceived buffer;
|
||||
SharedConsumerMutex* is_buffer_free_shared_mutex;
|
||||
int* status;
|
||||
uint32_t* last_index;
|
||||
CaptureData* capture_data;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start;
|
||||
CaptureScreensType curr_capture_type;
|
||||
isd_async_callback_data cb_data;
|
||||
};
|
||||
|
||||
int set_acquisition_mode(is_device_device_handlers* handlers, CaptureScreensType capture_type, CaptureSpeedsType capture_speed, const is_device_usb_device* usb_device_desc);
|
||||
int EndAcquisition(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data, bool do_drain_frames, int start_frames, CaptureScreensType capture_type);
|
||||
int EndAcquisition(const is_device_usb_device* usb_device_desc, is_device_device_handlers* handlers, bool do_drain_frames, int start_frames, CaptureScreensType capture_type);
|
||||
int is_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);
|
||||
void is_device_read_frame_request(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data, CaptureScreensType curr_capture_type, uint32_t index);
|
||||
uint64_t usb_is_device_get_video_in_size(CaptureScreensType capture_type, is_device_type device_type);
|
||||
|
||||
ISDeviceCaptureReceivedData* is_device_get_free_buffer(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data);
|
||||
bool is_device_are_buffers_all_free(ISDeviceCaptureReceivedData* is_device_capture_recv_data);
|
||||
int is_device_get_num_free_buffers(ISDeviceCaptureReceivedData* is_device_capture_recv_data);
|
||||
void wait_all_is_device_transfers_done(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data);
|
||||
void wait_all_is_device_buffers_free(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data);
|
||||
void wait_one_is_device_buffer_free(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data);
|
||||
int get_is_device_status(ISDeviceCaptureReceivedData* is_device_capture_recv_data);
|
||||
void reset_is_device_status(ISDeviceCaptureReceivedData* is_device_capture_recv_data);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
#ifndef __USB_IS_DEVICE_COMMUNICATIONS_HPP
|
||||
#define __USB_IS_DEVICE_COMMUNICATIONS_HPP
|
||||
|
||||
#include <libusb.h>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
#include "utils.hpp"
|
||||
#include "capture_structs.hpp"
|
||||
|
||||
#define IS_DEVICE_REAL_SERIAL_NUMBER_SIZE 10
|
||||
|
||||
enum is_device_type {
|
||||
IS_NITRO_EMULATOR_DEVICE,
|
||||
IS_NITRO_CAPTURE_DEVICE,
|
||||
};
|
||||
|
||||
enum is_device_forward_config_values_colors {
|
||||
IS_DEVICE_FORWARD_CONFIG_COLOR_RGB24 = 0,
|
||||
};
|
||||
|
||||
enum is_device_forward_config_values_screens {
|
||||
IS_DEVICE_FORWARD_CONFIG_MODE_BOTH = 0,
|
||||
IS_DEVICE_FORWARD_CONFIG_MODE_TOP = 1,
|
||||
IS_DEVICE_FORWARD_CONFIG_MODE_BOTTOM = 2,
|
||||
};
|
||||
|
||||
enum is_device_forward_config_values_rate {
|
||||
IS_DEVICE_FORWARD_CONFIG_RATE_FULL = 0,
|
||||
IS_DEVICE_FORWARD_CONFIG_RATE_HALF = 1,
|
||||
IS_DEVICE_FORWARD_CONFIG_RATE_THIRD = 2,
|
||||
IS_DEVICE_FORWARD_CONFIG_RATE_QUARTER = 3,
|
||||
};
|
||||
|
||||
typedef void (*isd_async_callback_function)(void* user_data, int transfer_length, int transfer_status);
|
||||
|
||||
struct isd_async_callback_data {
|
||||
isd_async_callback_function function;
|
||||
void* actual_user_data;
|
||||
void* transfer_data;
|
||||
void* handle;
|
||||
void* base_transfer_data;
|
||||
std::mutex transfer_data_access;
|
||||
SharedConsumerMutex* is_transfer_done_mutex;
|
||||
SharedConsumerMutex* is_transfer_data_ready_mutex;
|
||||
size_t requested_length;
|
||||
uint8_t* buffer;
|
||||
size_t actual_length;
|
||||
int status_value;
|
||||
bool is_data_ready;
|
||||
int internal_index;
|
||||
};
|
||||
|
||||
struct is_device_usb_device {
|
||||
std::string name;
|
||||
std::string long_name;
|
||||
int vid;
|
||||
int pid;
|
||||
int default_config;
|
||||
int default_interface;
|
||||
int bulk_timeout;
|
||||
int ep2_in;
|
||||
int ep1_out;
|
||||
int product_id;
|
||||
int manufacturer_id;
|
||||
is_device_type device_type;
|
||||
InputVideoDataType video_data_type;
|
||||
};
|
||||
|
||||
struct is_device_device_handlers {
|
||||
libusb_device_handle* usb_handle;
|
||||
void* read_handle;
|
||||
void* write_handle;
|
||||
void* mutex;
|
||||
};
|
||||
|
||||
int GetNumISDeviceDesc(void);
|
||||
const is_device_usb_device* GetISDeviceDesc(int index);
|
||||
int DisableLca2(is_device_device_handlers* handlers, const is_device_usb_device* device_desc);
|
||||
int StartUsbCaptureDma(is_device_device_handlers* handlers, const is_device_usb_device* device_desc);
|
||||
int StopUsbCaptureDma(is_device_device_handlers* handlers, const is_device_usb_device* device_desc);
|
||||
int SetForwardFrameCount(is_device_device_handlers* handlers, uint16_t count, const is_device_usb_device* device_desc);
|
||||
int SetForwardFramePermanent(is_device_device_handlers* handlers, const is_device_usb_device* device_desc);
|
||||
int GetFrameCounter(is_device_device_handlers* handlers, uint16_t* out, const is_device_usb_device* device_desc);
|
||||
int GetDeviceSerial(is_device_device_handlers* handlers, uint8_t* buf, const is_device_usb_device* device_desc);
|
||||
int UpdateFrameForwardConfig(is_device_device_handlers* handlers, is_device_forward_config_values_colors colors, is_device_forward_config_values_screens screens, is_device_forward_config_values_rate rate, const is_device_usb_device* device_desc);
|
||||
int UpdateFrameForwardEnable(is_device_device_handlers* handlers, bool enable, bool restart, const is_device_usb_device* device_desc);
|
||||
int ReadLidState(is_device_device_handlers* handlers, bool* out, const is_device_usb_device* device_desc);
|
||||
int ReadDebugButtonState(is_device_device_handlers* handlers, bool* out, const is_device_usb_device* device_desc);
|
||||
int ReadPowerButtonState(is_device_device_handlers* handlers, bool* out, const is_device_usb_device* device_desc);
|
||||
int ResetCPUStart(is_device_device_handlers* handlers, const is_device_usb_device* device_desc);
|
||||
int ResetCPUEnd(is_device_device_handlers* handlers, const is_device_usb_device* device_desc);
|
||||
int ResetFullHardware(is_device_device_handlers* handlers, const is_device_usb_device* device_desc);
|
||||
int ReadFrame(is_device_device_handlers* handlers, uint8_t* buf, int length, const is_device_usb_device* device_desc);
|
||||
void ReadFrameAsync(is_device_device_handlers* handlers, uint8_t* buf, int length, const is_device_usb_device* device_desc, isd_async_callback_data* cb_data);
|
||||
void CloseAsyncRead(is_device_device_handlers* handlers, isd_async_callback_data* cb_data);
|
||||
int ResetUSBDevice(is_device_device_handlers* handlers);
|
||||
|
||||
void SetupISDeviceAsyncThread(is_device_device_handlers* handlers, void* user_data, std::thread* thread_ptr, bool* keep_going, ConsumerMutex* is_data_ready);
|
||||
void EndISDeviceAsyncThread(is_device_device_handlers* handlers, void* user_data, std::thread* thread_ptr, bool* keep_going, ConsumerMutex* is_data_ready);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef __USB_IS_DEVICE_IS_DRIVER_HPP
|
||||
#define __USB_IS_DEVICE_IS_DRIVER_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "capture_structs.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "usb_is_device_communications.hpp"
|
||||
#include "usb_is_device_acquisition_general.hpp"
|
||||
|
||||
void is_driver_list_devices(std::vector<CaptureDevice>& devices_list, bool* not_supported_elems, int* curr_serial_extra_id_is_device, const size_t num_is_device_desc);
|
||||
is_device_device_handlers* is_driver_serial_reconnection(CaptureDevice* device);
|
||||
void is_driver_end_connection(is_device_device_handlers* handlers);
|
||||
int is_driver_bulk_out(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred);
|
||||
int is_driver_bulk_in(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred);
|
||||
int is_drive_async_in_start(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t* buf, int length, isd_async_callback_data* cb_data);
|
||||
void is_device_is_driver_cancel_callback(isd_async_callback_data* cb_data);
|
||||
int is_device_is_driver_reset_device(is_device_device_handlers* handlers);
|
||||
|
||||
void is_device_is_driver_start_thread(std::thread* thread_ptr, bool* usb_thread_run, ISDeviceCaptureReceivedData* is_device_capture_recv_data, is_device_device_handlers* handlers, ConsumerMutex* AsyncMutexPtr);
|
||||
void is_device_is_driver_close_thread(std::thread* thread_ptr, bool* usb_thread_run, ISDeviceCaptureReceivedData* is_device_capture_recv_data);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef __USB_IS_DEVICE_LIBUSB_HPP
|
||||
#define __USB_IS_DEVICE_LIBUSB_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "capture_structs.hpp"
|
||||
#include "usb_is_device_communications.hpp"
|
||||
|
||||
void is_device_libusb_list_devices(std::vector<CaptureDevice>& devices_list, bool* no_access_elems, bool* not_supported_elems, int* curr_serial_extra_id_is_device, const size_t num_is_device_desc);
|
||||
is_device_device_handlers* is_device_libusb_serial_reconnection(const is_device_usb_device* usb_device_desc, CaptureDevice* device, int& curr_serial_extra_id);
|
||||
void is_device_libusb_end_connection(is_device_device_handlers* handlers, const is_device_usb_device* device_desc, bool interface_claimed);
|
||||
int is_device_libusb_bulk_out(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred);
|
||||
int is_device_libusb_bulk_in(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred);
|
||||
void is_device_libusb_async_in_start(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t* buf, int length, isd_async_callback_data* cb_data);
|
||||
void is_device_libusb_cancell_callback(isd_async_callback_data* cb_data);
|
||||
int is_device_libusb_reset_device(is_device_device_handlers* handlers);
|
||||
|
||||
void is_device_libusb_start_thread(std::thread* thread_ptr, bool* usb_thread_run);
|
||||
void is_device_libusb_close_thread(std::thread* thread_ptr, bool* usb_thread_run);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef __USB_IS_DEVICE_SETUP_GENERAL_HPP
|
||||
#define __USB_IS_DEVICE_SETUP_GENERAL_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "capture_structs.hpp"
|
||||
#include "usb_is_device_communications.hpp"
|
||||
|
||||
std::string get_serial(const is_device_usb_device* usb_device_desc, is_device_device_handlers* handlers, int& curr_serial_extra_id);
|
||||
void is_device_insert_device(std::vector<CaptureDevice>& devices_list, is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, int& curr_serial_extra_id_is_device, std::string path);
|
||||
void is_device_insert_device(std::vector<CaptureDevice>& devices_list, is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, int& curr_serial_extra_id_is_device);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef __USB_IS_NITRO_ACQUISITION_CAPTURE_HPP
|
||||
#define __USB_IS_NITRO_ACQUISITION_CAPTURE_HPP
|
||||
|
||||
#include "usb_is_device_communications.hpp"
|
||||
#include "capture_structs.hpp"
|
||||
|
||||
int initial_cleanup_capture(const is_device_usb_device* usb_device_desc, is_device_device_handlers* handlers);
|
||||
int EndAcquisitionCapture(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_nitro_capture_recv_data);
|
||||
int EndAcquisitionCapture(const is_device_usb_device* usb_device_desc, is_device_device_handlers* handlers);
|
||||
void is_nitro_acquisition_capture_main_loop(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_nitro_capture_recv_data);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef __USB_IS_NITRO_ACQUISITION_EMULATOR_HPP
|
||||
#define __USB_IS_NITRO_ACQUISITION_EMULATOR_HPP
|
||||
|
||||
#include "usb_is_device_communications.hpp"
|
||||
#include "capture_structs.hpp"
|
||||
|
||||
int initial_cleanup_emulator(const is_device_usb_device* usb_device_desc, is_device_device_handlers* handlers);
|
||||
int EndAcquisitionEmulator(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_nitro_capture_recv_data, bool do_drain_frames, int start_frames, CaptureScreensType capture_type);
|
||||
int EndAcquisitionEmulator(const is_device_usb_device* usb_device_desc, is_device_device_handlers* handlers, bool do_drain_frames, int start_frames, CaptureScreensType capture_type);
|
||||
void is_nitro_acquisition_emulator_main_loop(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_nitro_capture_recv_data);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
#ifndef __USB_IS_NITRO_ACQUISITION_HPP
|
||||
#define __USB_IS_NITRO_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_is_nitro(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list);
|
||||
bool is_nitro_connect_usb(bool print_failed, CaptureData* capture_data, CaptureDevice* device);
|
||||
void is_nitro_acquisition_main_loop(CaptureData* capture_data);
|
||||
void usb_is_nitro_acquisition_cleanup(CaptureData* capture_data);
|
||||
uint64_t usb_is_nitro_get_video_in_size(CaptureData* capture_data);
|
||||
uint64_t usb_is_nitro_get_video_in_size(CaptureScreensType capture_type);
|
||||
bool is_nitro_is_capture(CaptureDevice* device);
|
||||
void usb_is_nitro_init();
|
||||
void usb_is_nitro_close();
|
||||
|
||||
#endif
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
#ifndef __USB_IS_NITRO_ACQUISITION_CAPTURE_HPP
|
||||
#define __USB_IS_NITRO_ACQUISITION_CAPTURE_HPP
|
||||
|
||||
#include "usb_is_nitro_communications.hpp"
|
||||
#include "capture_structs.hpp"
|
||||
|
||||
int initial_cleanup_capture(const is_nitro_usb_device* usb_device_desc, is_nitro_device_handlers* handlers);
|
||||
int EndAcquisitionCapture(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data);
|
||||
int EndAcquisitionCapture(const is_nitro_usb_device* usb_device_desc, is_nitro_device_handlers* handlers);
|
||||
void is_nitro_acquisition_capture_main_loop(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
#ifndef __USB_IS_NITRO_ACQUISITION_EMULATOR_HPP
|
||||
#define __USB_IS_NITRO_ACQUISITION_EMULATOR_HPP
|
||||
|
||||
#include "usb_is_nitro_communications.hpp"
|
||||
#include "capture_structs.hpp"
|
||||
|
||||
int initial_cleanup_emulator(const is_nitro_usb_device* usb_device_desc, is_nitro_device_handlers* handlers);
|
||||
int EndAcquisitionEmulator(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data, bool do_drain_frames, int start_frames, CaptureScreensType capture_type);
|
||||
int EndAcquisitionEmulator(const is_nitro_usb_device* usb_device_desc, is_nitro_device_handlers* handlers, bool do_drain_frames, int start_frames, CaptureScreensType capture_type);
|
||||
void is_nitro_acquisition_emulator_main_loop(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
#ifndef __USB_IS_NITRO_ACQUISITION_GENERAL_HPP
|
||||
#define __USB_IS_NITRO_ACQUISITION_GENERAL_HPP
|
||||
|
||||
#include "usb_is_nitro_communications.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "capture_structs.hpp"
|
||||
#include "display_structs.hpp"
|
||||
|
||||
#define NUM_CAPTURE_RECEIVED_DATA_BUFFERS 4
|
||||
|
||||
struct ISNitroCaptureReceivedData {
|
||||
volatile bool in_use;
|
||||
uint32_t index;
|
||||
CaptureReceived buffer;
|
||||
SharedConsumerMutex* is_buffer_free_shared_mutex;
|
||||
int* status;
|
||||
uint32_t* last_index;
|
||||
CaptureData* capture_data;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start;
|
||||
CaptureScreensType curr_capture_type;
|
||||
isn_async_callback_data cb_data;
|
||||
};
|
||||
|
||||
int set_acquisition_mode(is_nitro_device_handlers* handlers, CaptureScreensType capture_type, CaptureSpeedsType capture_speed, const is_nitro_usb_device* usb_device_desc);
|
||||
int EndAcquisition(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data, bool do_drain_frames, int start_frames, CaptureScreensType capture_type);
|
||||
int EndAcquisition(const is_nitro_usb_device* usb_device_desc, is_nitro_device_handlers* handlers, bool do_drain_frames, int start_frames, CaptureScreensType capture_type);
|
||||
int is_nitro_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);
|
||||
void is_nitro_read_frame_request(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data, CaptureScreensType curr_capture_type, uint32_t index);
|
||||
|
||||
ISNitroCaptureReceivedData* is_nitro_get_free_buffer(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data);
|
||||
bool is_nitro_are_buffers_all_free(ISNitroCaptureReceivedData* is_nitro_capture_recv_data);
|
||||
int is_nitro_get_num_free_buffers(ISNitroCaptureReceivedData* is_nitro_capture_recv_data);
|
||||
void wait_all_is_nitro_transfers_done(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data);
|
||||
void wait_all_is_nitro_buffers_free(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data);
|
||||
void wait_one_is_nitro_buffer_free(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data);
|
||||
int get_is_nitro_status(ISNitroCaptureReceivedData* is_nitro_capture_recv_data);
|
||||
void reset_is_nitro_status(ISNitroCaptureReceivedData* is_nitro_capture_recv_data);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
#ifndef __USB_IS_NITRO_COMMUNICATIONS_HPP
|
||||
#define __USB_IS_NITRO_COMMUNICATIONS_HPP
|
||||
|
||||
#include <libusb.h>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
#include "utils.hpp"
|
||||
|
||||
#define IS_NITRO_REAL_SERIAL_NUMBER_SIZE 10
|
||||
|
||||
enum is_nitro_forward_config_values_colors {
|
||||
IS_NITRO_FORWARD_CONFIG_COLOR_RGB24 = 0,
|
||||
};
|
||||
|
||||
enum is_nitro_forward_config_values_screens {
|
||||
IS_NITRO_FORWARD_CONFIG_MODE_BOTH = 0,
|
||||
IS_NITRO_FORWARD_CONFIG_MODE_TOP = 1,
|
||||
IS_NITRO_FORWARD_CONFIG_MODE_BOTTOM = 2,
|
||||
};
|
||||
|
||||
enum is_nitro_forward_config_values_rate {
|
||||
IS_NITRO_FORWARD_CONFIG_RATE_FULL = 0,
|
||||
IS_NITRO_FORWARD_CONFIG_RATE_HALF = 1,
|
||||
IS_NITRO_FORWARD_CONFIG_RATE_THIRD = 2,
|
||||
IS_NITRO_FORWARD_CONFIG_RATE_QUARTER = 3,
|
||||
};
|
||||
|
||||
typedef void (*isn_async_callback_function)(void* user_data, int transfer_length, int transfer_status);
|
||||
|
||||
struct isn_async_callback_data {
|
||||
isn_async_callback_function function;
|
||||
void* actual_user_data;
|
||||
void* transfer_data;
|
||||
void* handle;
|
||||
void* base_transfer_data;
|
||||
std::mutex transfer_data_access;
|
||||
SharedConsumerMutex* is_transfer_done_mutex;
|
||||
SharedConsumerMutex* is_transfer_data_ready_mutex;
|
||||
size_t requested_length;
|
||||
uint8_t* buffer;
|
||||
size_t actual_length;
|
||||
int status_value;
|
||||
bool is_data_ready;
|
||||
int internal_index;
|
||||
};
|
||||
|
||||
struct is_nitro_usb_device {
|
||||
std::string name;
|
||||
std::string long_name;
|
||||
int vid;
|
||||
int pid;
|
||||
int default_config;
|
||||
int default_interface;
|
||||
int bulk_timeout;
|
||||
int ep2_in;
|
||||
int ep1_out;
|
||||
int product_id;
|
||||
int manufacturer_id;
|
||||
bool is_capture;
|
||||
};
|
||||
|
||||
struct is_nitro_device_handlers {
|
||||
libusb_device_handle* usb_handle;
|
||||
void* read_handle;
|
||||
void* write_handle;
|
||||
void* mutex;
|
||||
};
|
||||
|
||||
int GetNumISNitroDesc(void);
|
||||
const is_nitro_usb_device* GetISNitroDesc(int index);
|
||||
int DisableLca2(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc);
|
||||
int StartUsbCaptureDma(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc);
|
||||
int StopUsbCaptureDma(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc);
|
||||
int SetForwardFrameCount(is_nitro_device_handlers* handlers, uint16_t count, const is_nitro_usb_device* device_desc);
|
||||
int SetForwardFramePermanent(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc);
|
||||
int GetFrameCounter(is_nitro_device_handlers* handlers, uint16_t* out, const is_nitro_usb_device* device_desc);
|
||||
int GetDeviceSerial(is_nitro_device_handlers* handlers, uint8_t* buf, const is_nitro_usb_device* device_desc);
|
||||
int UpdateFrameForwardConfig(is_nitro_device_handlers* handlers, is_nitro_forward_config_values_colors colors, is_nitro_forward_config_values_screens screens, is_nitro_forward_config_values_rate rate, const is_nitro_usb_device* device_desc);
|
||||
int UpdateFrameForwardEnable(is_nitro_device_handlers* handlers, bool enable, bool restart, const is_nitro_usb_device* device_desc);
|
||||
int ReadLidState(is_nitro_device_handlers* handlers, bool* out, const is_nitro_usb_device* device_desc);
|
||||
int ReadDebugButtonState(is_nitro_device_handlers* handlers, bool* out, const is_nitro_usb_device* device_desc);
|
||||
int ReadPowerButtonState(is_nitro_device_handlers* handlers, bool* out, const is_nitro_usb_device* device_desc);
|
||||
int ResetCPUStart(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc);
|
||||
int ResetCPUEnd(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc);
|
||||
int ResetFullHardware(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc);
|
||||
int ReadFrame(is_nitro_device_handlers* handlers, uint8_t* buf, int length, const is_nitro_usb_device* device_desc);
|
||||
void ReadFrameAsync(is_nitro_device_handlers* handlers, uint8_t* buf, int length, const is_nitro_usb_device* device_desc, isn_async_callback_data* cb_data);
|
||||
void CloseAsyncRead(is_nitro_device_handlers* handlers, isn_async_callback_data* cb_data);
|
||||
|
||||
void SetupISNitroAsyncThread(is_nitro_device_handlers* handlers, void* user_data, std::thread* thread_ptr, bool* keep_going, ConsumerMutex* is_data_ready);
|
||||
void EndISNitroAsyncThread(is_nitro_device_handlers* handlers, void* user_data, std::thread* thread_ptr, bool* keep_going, ConsumerMutex* is_data_ready);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
#ifndef __USB_IS_NITRO_IS_DRIVER_HPP
|
||||
#define __USB_IS_NITRO_IS_DRIVER_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "capture_structs.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "usb_is_nitro_communications.hpp"
|
||||
#include "usb_is_nitro_acquisition_general.hpp"
|
||||
|
||||
void is_driver_list_devices(std::vector<CaptureDevice>& devices_list, bool* not_supported_elems, int* curr_serial_extra_id_is_nitro, const size_t num_is_nitro_desc);
|
||||
is_nitro_device_handlers* is_driver_serial_reconnection(CaptureDevice* device);
|
||||
void is_driver_end_connection(is_nitro_device_handlers* handlers);
|
||||
int is_driver_bulk_out(is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred);
|
||||
int is_driver_bulk_in(is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred);
|
||||
int is_drive_async_in_start(is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, uint8_t* buf, int length, isn_async_callback_data* cb_data);
|
||||
void is_nitro_is_driver_cancel_callback(isn_async_callback_data* cb_data);
|
||||
|
||||
void is_nitro_is_driver_start_thread(std::thread* thread_ptr, bool* usb_thread_run, ISNitroCaptureReceivedData* is_nitro_capture_recv_data, is_nitro_device_handlers* handlers, ConsumerMutex* AsyncMutexPtr);
|
||||
void is_nitro_is_driver_close_thread(std::thread* thread_ptr, bool* usb_thread_run, ISNitroCaptureReceivedData* is_nitro_capture_recv_data);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
#ifndef __USB_IS_NITRO_LIBUSB_HPP
|
||||
#define __USB_IS_NITRO_LIBUSB_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "capture_structs.hpp"
|
||||
#include "usb_is_nitro_communications.hpp"
|
||||
|
||||
void is_nitro_libusb_list_devices(std::vector<CaptureDevice>& devices_list, bool* no_access_elems, bool* not_supported_elems, int* curr_serial_extra_id_is_nitro, const size_t num_is_nitro_desc);
|
||||
is_nitro_device_handlers* is_nitro_libusb_serial_reconnection(const is_nitro_usb_device* usb_device_desc, CaptureDevice* device, int& curr_serial_extra_id);
|
||||
void is_nitro_libusb_end_connection(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc, bool interface_claimed);
|
||||
int is_nitro_libusb_bulk_out(is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred);
|
||||
int is_nitro_libusb_bulk_in(is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred);
|
||||
void is_nitro_libusb_async_in_start(is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, uint8_t* buf, int length, isn_async_callback_data* cb_data);
|
||||
void is_nitro_libusb_cancell_callback(isn_async_callback_data* cb_data);
|
||||
|
||||
void is_nitro_libusb_start_thread(std::thread* thread_ptr, bool* usb_thread_run);
|
||||
void is_nitro_libusb_close_thread(std::thread* thread_ptr, bool* usb_thread_run);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
#ifndef __USB_IS_NITRO_SETUP_GENERAL_HPP
|
||||
#define __USB_IS_NITRO_SETUP_GENERAL_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "capture_structs.hpp"
|
||||
#include "usb_is_nitro_communications.hpp"
|
||||
|
||||
std::string get_serial(const is_nitro_usb_device* usb_device_desc, is_nitro_device_handlers* handlers, int& curr_serial_extra_id);
|
||||
void is_nitro_insert_device(std::vector<CaptureDevice>& devices_list, is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, int& curr_serial_extra_id_is_nitro, std::string path);
|
||||
void is_nitro_insert_device(std::vector<CaptureDevice>& devices_list, is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, int& curr_serial_extra_id_is_nitro);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __USB_GENERIC_HPP
|
||||
#define __USB_GENERIC_HPP
|
||||
|
||||
#if defined(USE_IS_NITRO_USB) || defined(USE_DS_3DS_USB)
|
||||
#ifdef USE_LIBUSB
|
||||
#include <libusb.h>
|
||||
libusb_context* get_usb_ctx();
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,446 @@
|
|||
#include "devicecapture.hpp"
|
||||
#include "usb_is_device_setup_general.hpp"
|
||||
#include "usb_is_device_libusb.hpp"
|
||||
#include "usb_is_device_is_driver.hpp"
|
||||
#include "usb_is_device_communications.hpp"
|
||||
#include "usb_is_device_acquisition.hpp"
|
||||
#include "usb_is_device_acquisition_general.hpp"
|
||||
#include "usb_is_nitro_acquisition_capture.hpp"
|
||||
#include "usb_is_nitro_acquisition_emulator.hpp"
|
||||
#include "usb_generic.hpp"
|
||||
|
||||
#include <libusb.h>
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
|
||||
// Code based off of Gericom's sample code. Distributed under the MIT License. Copyright (c) 2024 Gericom
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#define SERIAL_NUMBER_SIZE (IS_DEVICE_REAL_SERIAL_NUMBER_SIZE + 1)
|
||||
#define MAX_TIME_WAIT 1.0
|
||||
#define FRAME_BUFFER_SIZE 32
|
||||
|
||||
static void is_device_read_frame_cb(void* user_data, int transfer_length, int transfer_status);
|
||||
|
||||
static bool initial_cleanup(const is_device_usb_device* usb_device_desc, is_device_device_handlers* handlers) {
|
||||
switch(usb_device_desc->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
return initial_cleanup_emulator(usb_device_desc, handlers) != LIBUSB_SUCCESS;
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
return initial_cleanup_capture(usb_device_desc, handlers) != LIBUSB_SUCCESS;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
std::string get_serial(const is_device_usb_device* usb_device_desc, is_device_device_handlers* handlers, int& curr_serial_extra_id) {
|
||||
uint8_t data[SERIAL_NUMBER_SIZE];
|
||||
std::string serial_str = std::to_string(curr_serial_extra_id);
|
||||
bool conn_success = true;
|
||||
if(initial_cleanup(usb_device_desc, handlers))
|
||||
conn_success = false;
|
||||
if (conn_success && (GetDeviceSerial(handlers, data, usb_device_desc) != LIBUSB_SUCCESS))
|
||||
conn_success = false;
|
||||
if (conn_success) {
|
||||
data[IS_DEVICE_REAL_SERIAL_NUMBER_SIZE] = '\0';
|
||||
serial_str = std::string((const char*)data);
|
||||
}
|
||||
else
|
||||
curr_serial_extra_id += 1;
|
||||
return serial_str;
|
||||
}
|
||||
|
||||
void is_device_insert_device(std::vector<CaptureDevice>& devices_list, is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, int& curr_serial_extra_id_is_device, std::string path) {
|
||||
devices_list.emplace_back(get_serial(usb_device_desc, handlers, curr_serial_extra_id_is_device), usb_device_desc->name, usb_device_desc->long_name, path, CAPTURE_CONN_IS_NITRO, (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 is_device_insert_device(std::vector<CaptureDevice>& devices_list, is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, int& curr_serial_extra_id_is_device) {
|
||||
devices_list.emplace_back(get_serial(usb_device_desc, handlers, curr_serial_extra_id_is_device), usb_device_desc->name, usb_device_desc->long_name, CAPTURE_CONN_IS_NITRO, (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);
|
||||
}
|
||||
|
||||
static is_device_device_handlers* usb_find_by_serial_number(const is_device_usb_device* usb_device_desc, CaptureDevice* device) {
|
||||
is_device_device_handlers* final_handlers = NULL;
|
||||
int curr_serial_extra_id = 0;
|
||||
final_handlers = is_device_libusb_serial_reconnection(usb_device_desc, device, curr_serial_extra_id);
|
||||
|
||||
if (final_handlers == NULL)
|
||||
final_handlers = is_driver_serial_reconnection(device);
|
||||
return final_handlers;
|
||||
}
|
||||
|
||||
void list_devices_is_device(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list) {
|
||||
const size_t num_is_device_desc = GetNumISDeviceDesc();
|
||||
int* curr_serial_extra_id_is_device = new int[num_is_device_desc];
|
||||
bool* no_access_elems = new bool[num_is_device_desc];
|
||||
bool* not_supported_elems = new bool[num_is_device_desc];
|
||||
for (int i = 0; i < num_is_device_desc; i++) {
|
||||
no_access_elems[i] = false;
|
||||
not_supported_elems[i] = false;
|
||||
curr_serial_extra_id_is_device[i] = 0;
|
||||
}
|
||||
is_device_libusb_list_devices(devices_list, no_access_elems, not_supported_elems, curr_serial_extra_id_is_device, num_is_device_desc);
|
||||
|
||||
bool any_not_supported = false;
|
||||
for(int i = 0; i < num_is_device_desc; i++)
|
||||
any_not_supported |= not_supported_elems[i];
|
||||
for(int i = 0; i < num_is_device_desc; i++)
|
||||
if(no_access_elems[i]) {
|
||||
const is_device_usb_device* usb_device = GetISDeviceDesc(i);
|
||||
no_access_list.emplace_back(usb_device->vid, usb_device->pid);
|
||||
}
|
||||
if(any_not_supported)
|
||||
is_driver_list_devices(devices_list, not_supported_elems, curr_serial_extra_id_is_device, num_is_device_desc);
|
||||
|
||||
delete[] curr_serial_extra_id_is_device;
|
||||
delete[] no_access_elems;
|
||||
delete[] not_supported_elems;
|
||||
}
|
||||
|
||||
static void is_device_connection_end(is_device_device_handlers* handlers, const is_device_usb_device *device_desc, bool interface_claimed = true) {
|
||||
if (handlers == NULL)
|
||||
return;
|
||||
if (handlers->usb_handle)
|
||||
is_device_libusb_end_connection(handlers, device_desc, interface_claimed);
|
||||
else
|
||||
is_driver_end_connection(handlers);
|
||||
delete handlers;
|
||||
}
|
||||
|
||||
bool is_device_connect_usb(bool print_failed, CaptureData* capture_data, CaptureDevice* device) {
|
||||
const is_device_usb_device* usb_device_info = (const is_device_usb_device*)device->descriptor;
|
||||
is_device_device_handlers* handlers = usb_find_by_serial_number(usb_device_info, device);
|
||||
if(handlers == NULL) {
|
||||
capture_error_print(true, capture_data, "Device not found");
|
||||
return false;
|
||||
}
|
||||
capture_data->handle = (void*)handlers;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t usb_is_device_get_video_in_size(CaptureScreensType capture_type, is_device_type device_type) {
|
||||
if((capture_type == CAPTURE_SCREENS_TOP) || (capture_type == CAPTURE_SCREENS_BOTTOM))
|
||||
return sizeof(ISNitroEmulatorVideoInputData) / 2;
|
||||
return sizeof(ISNitroEmulatorVideoInputData);
|
||||
}
|
||||
|
||||
|
||||
uint64_t usb_is_device_get_video_in_size(CaptureStatus* status) {
|
||||
return usb_is_device_get_video_in_size(status->capture_type, ((const is_device_usb_device*)(status->device.descriptor))->device_type);
|
||||
}
|
||||
|
||||
|
||||
uint64_t usb_is_device_get_video_in_size(CaptureData* capture_data) {
|
||||
return usb_is_device_get_video_in_size(&capture_data->status);
|
||||
}
|
||||
|
||||
int set_acquisition_mode(is_device_device_handlers* handlers, CaptureScreensType capture_type, CaptureSpeedsType capture_speed, const is_device_usb_device* usb_device_desc) {
|
||||
is_device_forward_config_values_screens capture_mode_flag = IS_DEVICE_FORWARD_CONFIG_MODE_BOTH;
|
||||
switch(capture_type) {
|
||||
case CAPTURE_SCREENS_TOP:
|
||||
capture_mode_flag = IS_DEVICE_FORWARD_CONFIG_MODE_TOP;
|
||||
break;
|
||||
case CAPTURE_SCREENS_BOTTOM:
|
||||
capture_mode_flag = IS_DEVICE_FORWARD_CONFIG_MODE_BOTTOM;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
is_device_forward_config_values_rate capture_rate_flag = IS_DEVICE_FORWARD_CONFIG_RATE_FULL;
|
||||
switch(capture_speed) {
|
||||
case CAPTURE_SPEEDS_HALF:
|
||||
capture_rate_flag = IS_DEVICE_FORWARD_CONFIG_RATE_HALF;
|
||||
break;
|
||||
case CAPTURE_SPEEDS_THIRD:
|
||||
capture_rate_flag = IS_DEVICE_FORWARD_CONFIG_RATE_THIRD;
|
||||
break;
|
||||
case CAPTURE_SPEEDS_QUARTER:
|
||||
capture_rate_flag = IS_DEVICE_FORWARD_CONFIG_RATE_QUARTER;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return UpdateFrameForwardConfig(handlers, IS_DEVICE_FORWARD_CONFIG_COLOR_RGB24, capture_mode_flag, capture_rate_flag, usb_device_desc);
|
||||
}
|
||||
|
||||
int EndAcquisition(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data, bool do_drain_frames, int start_frames, CaptureScreensType capture_type) {
|
||||
switch(((const is_device_usb_device*)(capture_data->status.device.descriptor))->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
return EndAcquisitionEmulator(capture_data, is_device_capture_recv_data, do_drain_frames, start_frames, capture_type);
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
return EndAcquisitionCapture(capture_data, is_device_capture_recv_data);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int EndAcquisition(const is_device_usb_device* usb_device_desc, is_device_device_handlers* handlers, bool do_drain_frames, int start_frames, CaptureScreensType capture_type) {
|
||||
switch(usb_device_desc->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
return EndAcquisitionEmulator(usb_device_desc, handlers, do_drain_frames, start_frames, capture_type);
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
return EndAcquisitionCapture(usb_device_desc, handlers);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void output_to_thread(CaptureData* capture_data, CaptureReceived* capture_buf, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start) {
|
||||
// Output to the other threads...
|
||||
const is_device_usb_device* usb_device_info = (const is_device_usb_device*)capture_data->status.device.descriptor;
|
||||
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, usb_is_device_get_video_in_size(curr_capture_type, usb_device_info->device_type), 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 is_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) {
|
||||
const is_device_usb_device* usb_device_info = (const is_device_usb_device*)capture_data->status.device.descriptor;
|
||||
int ret = ReadFrame((is_device_device_handlers*)capture_data->handle, (uint8_t*)capture_buf, usb_is_device_get_video_in_size(curr_capture_type, usb_device_info->device_type), usb_device_info);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
output_to_thread(capture_data, capture_buf, curr_capture_type, &clock_start);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void is_device_read_frame_request(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data, CaptureScreensType curr_capture_type, uint32_t index) {
|
||||
if(is_device_capture_recv_data == NULL)
|
||||
return;
|
||||
const is_device_usb_device* usb_device_info = (const is_device_usb_device*)capture_data->status.device.descriptor;
|
||||
is_device_capture_recv_data->index = index;
|
||||
is_device_capture_recv_data->curr_capture_type = curr_capture_type;
|
||||
is_device_capture_recv_data->cb_data.function = is_device_read_frame_cb;
|
||||
ReadFrameAsync((is_device_device_handlers*)capture_data->handle, (uint8_t*)&is_device_capture_recv_data->buffer, usb_is_device_get_video_in_size(curr_capture_type, usb_device_info->device_type), usb_device_info, &is_device_capture_recv_data->cb_data);
|
||||
}
|
||||
|
||||
static void end_is_device_read_frame_cb(ISDeviceCaptureReceivedData* is_device_capture_recv_data) {
|
||||
is_device_capture_recv_data->in_use = false;
|
||||
is_device_capture_recv_data->is_buffer_free_shared_mutex->specific_unlock(is_device_capture_recv_data->cb_data.internal_index);
|
||||
}
|
||||
|
||||
static void is_device_read_frame_cb(void* user_data, int transfer_length, int transfer_status) {
|
||||
ISDeviceCaptureReceivedData* is_device_capture_recv_data = (ISDeviceCaptureReceivedData*)user_data;
|
||||
if((*is_device_capture_recv_data->status) < 0)
|
||||
return end_is_device_read_frame_cb(is_device_capture_recv_data);
|
||||
if(transfer_status != LIBUSB_TRANSFER_COMPLETED) {
|
||||
*is_device_capture_recv_data->status = LIBUSB_ERROR_OTHER;
|
||||
return end_is_device_read_frame_cb(is_device_capture_recv_data);
|
||||
}
|
||||
|
||||
if(((int32_t)(is_device_capture_recv_data->index - (*is_device_capture_recv_data->last_index))) <= 0) {
|
||||
//*is_device_capture_recv_data->status = LIBUSB_ERROR_INTERRUPTED;
|
||||
return end_is_device_read_frame_cb(is_device_capture_recv_data);
|
||||
}
|
||||
*is_device_capture_recv_data->last_index = is_device_capture_recv_data->index;
|
||||
|
||||
output_to_thread(is_device_capture_recv_data->capture_data, &is_device_capture_recv_data->buffer, is_device_capture_recv_data->curr_capture_type, is_device_capture_recv_data->clock_start);
|
||||
end_is_device_read_frame_cb(is_device_capture_recv_data);
|
||||
}
|
||||
|
||||
int is_device_get_num_free_buffers(ISDeviceCaptureReceivedData* is_device_capture_recv_data) {
|
||||
int num_free = 0;
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
if(!is_device_capture_recv_data[i].in_use)
|
||||
num_free += 1;
|
||||
return num_free;
|
||||
}
|
||||
|
||||
static void close_all_reads_error(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data, bool &errored_out) {
|
||||
if(*is_device_capture_recv_data[0].status < 0) {
|
||||
if(!errored_out) {
|
||||
for (int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
CloseAsyncRead((is_device_device_handlers*)capture_data->handle, &is_device_capture_recv_data[i].cb_data);
|
||||
int ret = ResetUSBDevice((is_device_device_handlers*)capture_data->handle);
|
||||
if((ret == LIBUSB_ERROR_NO_DEVICE) || (ret == LIBUSB_ERROR_NOT_FOUND)) {
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
is_device_capture_recv_data[i].cb_data.transfer_data_access.lock();
|
||||
is_device_capture_recv_data[i].cb_data.transfer_data = NULL;
|
||||
is_device_capture_recv_data[i].cb_data.transfer_data_access.unlock();
|
||||
is_device_capture_recv_data[i].in_use = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
errored_out = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void check_too_much_time_passed(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data, bool &errored_out, 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;
|
||||
if(diff.count() > MAX_TIME_WAIT)
|
||||
*is_device_capture_recv_data[0].status = -1;
|
||||
close_all_reads_error(capture_data, is_device_capture_recv_data, errored_out);
|
||||
}
|
||||
|
||||
void wait_all_is_device_transfers_done(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data) {
|
||||
if (is_device_capture_recv_data == NULL)
|
||||
return;
|
||||
bool errored_out = false;
|
||||
close_all_reads_error(capture_data, is_device_capture_recv_data, errored_out);
|
||||
const auto start_time = std::chrono::high_resolution_clock::now();
|
||||
for (int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
void* transfer_data;
|
||||
do {
|
||||
is_device_capture_recv_data[i].cb_data.transfer_data_access.lock();
|
||||
transfer_data = is_device_capture_recv_data[i].cb_data.transfer_data;
|
||||
is_device_capture_recv_data[i].cb_data.transfer_data_access.unlock();
|
||||
if(transfer_data) {
|
||||
check_too_much_time_passed(capture_data, is_device_capture_recv_data, errored_out, start_time);
|
||||
is_device_capture_recv_data[i].cb_data.is_transfer_done_mutex->specific_timed_lock(i);
|
||||
}
|
||||
} while(transfer_data);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_all_is_device_buffers_free(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data) {
|
||||
if(is_device_capture_recv_data == NULL)
|
||||
return;
|
||||
bool errored_out = false;
|
||||
close_all_reads_error(capture_data, is_device_capture_recv_data, errored_out);
|
||||
const auto start_time = std::chrono::high_resolution_clock::now();
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
while(is_device_capture_recv_data[i].in_use) {
|
||||
check_too_much_time_passed(capture_data, is_device_capture_recv_data, errored_out, start_time);
|
||||
is_device_capture_recv_data[i].is_buffer_free_shared_mutex->specific_timed_lock(i);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_one_is_device_buffer_free(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data) {
|
||||
bool done = false;
|
||||
bool errored_out = 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(!is_device_capture_recv_data[i].in_use)
|
||||
done = true;
|
||||
}
|
||||
if(!done) {
|
||||
check_too_much_time_passed(capture_data, is_device_capture_recv_data, errored_out, start_time);
|
||||
if(*is_device_capture_recv_data[0].status < 0)
|
||||
return;
|
||||
int dummy = 0;
|
||||
is_device_capture_recv_data[0].is_buffer_free_shared_mutex->general_timed_lock(&dummy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_device_are_buffers_all_free(ISDeviceCaptureReceivedData* is_device_capture_recv_data) {
|
||||
return is_device_get_num_free_buffers(is_device_capture_recv_data) == NUM_CAPTURE_RECEIVED_DATA_BUFFERS;
|
||||
}
|
||||
|
||||
ISDeviceCaptureReceivedData* is_device_get_free_buffer(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data) {
|
||||
wait_one_is_device_buffer_free(capture_data, is_device_capture_recv_data);
|
||||
if(*is_device_capture_recv_data[0].status < 0)
|
||||
return NULL;
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
if(!is_device_capture_recv_data[i].in_use) {
|
||||
is_device_capture_recv_data[i].is_buffer_free_shared_mutex->specific_try_lock(i);
|
||||
is_device_capture_recv_data[i].in_use = true;
|
||||
return &is_device_capture_recv_data[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int get_is_device_status(ISDeviceCaptureReceivedData* is_device_capture_recv_data) {
|
||||
return *is_device_capture_recv_data[0].status;
|
||||
}
|
||||
|
||||
void reset_is_device_status(ISDeviceCaptureReceivedData* is_device_capture_recv_data) {
|
||||
*is_device_capture_recv_data[0].status = 0;
|
||||
}
|
||||
|
||||
void is_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;
|
||||
|
||||
uint32_t last_index = -1;
|
||||
int status = 0;
|
||||
isd_async_callback_data* cb_queue[NUM_CAPTURE_RECEIVED_DATA_BUFFERS];
|
||||
int queue_elems = 0;
|
||||
bool one_transfer_active = false;
|
||||
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();
|
||||
ISDeviceCaptureReceivedData* is_device_capture_recv_data = new ISDeviceCaptureReceivedData[NUM_CAPTURE_RECEIVED_DATA_BUFFERS];
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
is_device_capture_recv_data[i].in_use = false;
|
||||
is_device_capture_recv_data[i].index = i;
|
||||
is_device_capture_recv_data[i].capture_data = capture_data;
|
||||
is_device_capture_recv_data[i].last_index = &last_index;
|
||||
is_device_capture_recv_data[i].clock_start = &clock_start;
|
||||
is_device_capture_recv_data[i].is_buffer_free_shared_mutex = &is_buffer_free_shared_mutex;
|
||||
is_device_capture_recv_data[i].status = &status;
|
||||
is_device_capture_recv_data[i].cb_data.actual_user_data = &is_device_capture_recv_data[i];
|
||||
is_device_capture_recv_data[i].cb_data.transfer_data = NULL;
|
||||
is_device_capture_recv_data[i].cb_data.is_transfer_done_mutex = &is_transfer_done_shared_mutex;
|
||||
is_device_capture_recv_data[i].cb_data.internal_index = i;
|
||||
is_device_capture_recv_data[i].cb_data.is_transfer_data_ready_mutex = &is_transfer_data_ready_shared_mutex;
|
||||
is_device_capture_recv_data[i].cb_data.is_data_ready = false;
|
||||
}
|
||||
SetupISDeviceAsyncThread((is_device_device_handlers*)capture_data->handle, is_device_capture_recv_data, &async_processing_thread, &is_done_thread, &has_data_been_processed);
|
||||
capture_data->status.reset_hardware = false;
|
||||
switch(((const is_device_usb_device*)(capture_data->status.device.descriptor))->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
is_nitro_acquisition_emulator_main_loop(capture_data, is_device_capture_recv_data);
|
||||
break;
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
is_nitro_acquisition_capture_main_loop(capture_data, is_device_capture_recv_data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
wait_all_is_device_buffers_free(capture_data, is_device_capture_recv_data);
|
||||
EndISDeviceAsyncThread((is_device_device_handlers*)capture_data->handle, is_device_capture_recv_data, &async_processing_thread, &is_done_thread, &has_data_been_processed);
|
||||
delete []is_device_capture_recv_data;
|
||||
}
|
||||
|
||||
void usb_is_device_acquisition_cleanup(CaptureData* capture_data) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
is_device_connection_end((is_device_device_handlers*)capture_data->handle, (const is_device_usb_device*)capture_data->status.device.descriptor);
|
||||
capture_data->handle = NULL;
|
||||
}
|
||||
|
||||
bool is_device_is_capture(CaptureDevice* device) {
|
||||
const is_device_usb_device* usb_device_info = (const is_device_usb_device*)device->descriptor;
|
||||
return usb_device_info->device_type != IS_NITRO_EMULATOR_DEVICE;
|
||||
}
|
||||
|
||||
bool is_device_is_nitro(CaptureDevice* device) {
|
||||
const is_device_usb_device* usb_device_info = (const is_device_usb_device*)device->descriptor;
|
||||
return (usb_device_info->device_type == IS_NITRO_EMULATOR_DEVICE) || (usb_device_info->device_type == IS_NITRO_CAPTURE_DEVICE);
|
||||
}
|
||||
|
||||
void usb_is_device_init() {
|
||||
return usb_init();
|
||||
}
|
||||
|
||||
void usb_is_device_close() {
|
||||
usb_close();
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,641 @@
|
|||
#include "frontend.hpp"
|
||||
#include "usb_is_device_communications.hpp"
|
||||
#include "usb_is_device_libusb.hpp"
|
||||
#include "usb_is_device_is_driver.hpp"
|
||||
|
||||
#include <libusb.h>
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
// Code based off of Gericom's sample code. Distributed under the MIT License. Copyright (c) 2024 Gericom
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#define USB_PACKET_LIMIT 0x2000
|
||||
|
||||
#define REG_USB_DMA_CONTROL_2 0x0C000028
|
||||
#define REG_USB_BIU_CONTROL_2 0x0C0000A4
|
||||
|
||||
enum is_nitro_packet_emulator_dir {
|
||||
IS_NITRO_PACKET_EMU_DIR_WRITE = 0x10,
|
||||
IS_NITRO_PACKET_EMU_DIR_READ = 0x11
|
||||
};
|
||||
|
||||
enum is_nitro_packet_capture_dir {
|
||||
IS_NITRO_PACKET_CAP_DIR_WRITE = 0x00,
|
||||
IS_NITRO_PACKET_CAP_DIR_READ = 0x01
|
||||
};
|
||||
|
||||
enum is_device_packet_type {
|
||||
IS_NITRO_PACKET_TYPE_COMMAND = 0,
|
||||
IS_NITRO_PACKET_TYPE_EMU_MEMORY = 1,
|
||||
IS_NITRO_EMULATOR_PACKET_TYPE_AGB_SRAM = 2,
|
||||
IS_NITRO_CAPTURE_PACKET_TYPE_DMA_CONTROL = 2,
|
||||
IS_NITRO_PACKET_TYPE_CAPTURE = 3,
|
||||
IS_NITRO_PACKET_TYPE_AGB_CART_ROM = 4,
|
||||
IS_NITRO_PACKET_TYPE_AGB_BUS2 = 5
|
||||
};
|
||||
|
||||
enum is_nitro_emulator_command {
|
||||
IS_NITRO_EMU_CMD_GET_SERIAL = 0x13,
|
||||
IS_NITRO_EMU_CMD_READ_NEC_MEM = 0x17,
|
||||
IS_NITRO_EMU_CMD_WRITE_NEC_MEM = 0x24,
|
||||
IS_NITRO_EMU_CMD_SET_READ_NEC_MEM = 0x25,
|
||||
IS_NITRO_EMU_CMD_FULL_HARDWARE_RESET = 0x81,
|
||||
IS_NITRO_EMU_CMD_CPU_RESET = 0x8A,
|
||||
IS_NITRO_EMU_CMD_AD = 0xAD,
|
||||
};
|
||||
|
||||
enum is_nitro_capture_command {
|
||||
IS_NITRO_CAP_CMD_ENABLE_CAP = 0x00,
|
||||
IS_NITRO_CAP_CMD_GET_SERIAL = 0x03,
|
||||
IS_NITRO_CAP_CMD_SET_FWD_RATE = 0x12,
|
||||
IS_NITRO_CAP_CMD_SET_FWD_MODE = 0x13,
|
||||
IS_NITRO_CAP_CMD_SET_FWD_COLOURS = 0x14,
|
||||
IS_NITRO_CAP_CMD_SET_FWD_FRAMES = 0x15,
|
||||
IS_NITRO_CAP_CMD_GET_DEBUG_STATE = 0x18,
|
||||
IS_NITRO_CAP_CMD_SET_RESTART_FULL = 0x18,
|
||||
IS_NITRO_CAP_CMD_GET_LID_STATE = 0x19,
|
||||
IS_NITRO_CAP_CMD_SET_FWD_RESTART = 0x1C,
|
||||
IS_NITRO_CAP_CMD_SET_RESET_CPU_ON = 0x21,
|
||||
IS_NITRO_CAP_CMD_SET_RESET_CPU_OFF = 0x22,
|
||||
};
|
||||
|
||||
enum is_nitro_emulator_forward_bits {
|
||||
IS_NITRO_EMULATOR_FORWARD_ENABLE_BIT = 0,
|
||||
IS_NITRO_EMULATOR_FORWARD_COUNTER_RESTART_BIT = 1,
|
||||
};
|
||||
|
||||
enum is_nitro_capture_forward_bits {
|
||||
IS_NITRO_CAPTURE_FORWARD_COUNTER_RESTART_BIT = 0,
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct PACKED is_nitro_nec_packet_header {
|
||||
uint8_t command;
|
||||
uint8_t unit_size;
|
||||
uint16_t count;
|
||||
uint32_t address;
|
||||
};
|
||||
|
||||
struct PACKED is_device_packet_header {
|
||||
uint16_t command;
|
||||
uint8_t direction;
|
||||
uint8_t type;
|
||||
uint32_t address;
|
||||
uint32_t length;
|
||||
uint32_t padding;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
static const is_device_usb_device usb_is_nitro_emu_rare_desc = {
|
||||
.name = "ISNEr", .long_name = "IS Nitro Emulator(R)",
|
||||
.vid = 0x0f6e, .pid = 0x0400,
|
||||
.default_config = 1, .default_interface = 0,
|
||||
.bulk_timeout = 500,
|
||||
.ep2_in = 2 | LIBUSB_ENDPOINT_IN, .ep1_out = 1 | LIBUSB_ENDPOINT_OUT,
|
||||
.product_id = 2, .manufacturer_id = 1, .device_type = IS_NITRO_EMULATOR_DEVICE,
|
||||
.video_data_type = VIDEO_DATA_BGR
|
||||
};
|
||||
|
||||
static const is_device_usb_device usb_is_nitro_emu_common_desc = {
|
||||
.name = "ISNE", .long_name = "IS Nitro Emulator",
|
||||
.vid = 0x0f6e, .pid = 0x0404,
|
||||
.default_config = 1, .default_interface = 0,
|
||||
.bulk_timeout = 500,
|
||||
.ep2_in = 2 | LIBUSB_ENDPOINT_IN, .ep1_out = 1 | LIBUSB_ENDPOINT_OUT,
|
||||
.product_id = 2, .manufacturer_id = 1, .device_type = IS_NITRO_EMULATOR_DEVICE,
|
||||
.video_data_type = VIDEO_DATA_BGR
|
||||
};
|
||||
|
||||
static const is_device_usb_device usb_is_nitro_cap_desc = {
|
||||
.name = "ISNC", .long_name = "IS Nitro Capture",
|
||||
.vid = 0x0f6e, .pid = 0x0403,
|
||||
.default_config = 1, .default_interface = 0,
|
||||
.bulk_timeout = 500,
|
||||
.ep2_in = 2 | LIBUSB_ENDPOINT_IN, .ep1_out = 1 | LIBUSB_ENDPOINT_OUT,
|
||||
.product_id = 2, .manufacturer_id = 1, .device_type = IS_NITRO_CAPTURE_DEVICE,
|
||||
.video_data_type = VIDEO_DATA_BGR
|
||||
};
|
||||
|
||||
static const is_device_usb_device* all_usb_is_device_devices_desc[] = {
|
||||
&usb_is_nitro_emu_rare_desc,
|
||||
&usb_is_nitro_emu_common_desc,
|
||||
&usb_is_nitro_cap_desc,
|
||||
};
|
||||
|
||||
int GetNumISDeviceDesc() {
|
||||
return sizeof(all_usb_is_device_devices_desc) / sizeof(all_usb_is_device_devices_desc[0]);
|
||||
}
|
||||
|
||||
const is_device_usb_device* GetISDeviceDesc(int index) {
|
||||
if((index < 0) || (index >= GetNumISDeviceDesc()))
|
||||
index = 0;
|
||||
return all_usb_is_device_devices_desc[index];
|
||||
}
|
||||
|
||||
static void fix_endianness_header(is_device_packet_header* header) {
|
||||
header->command = to_le(header->command);
|
||||
header->address = to_le(header->address);
|
||||
header->length = to_le(header->length);
|
||||
}
|
||||
|
||||
static void fix_endianness_header(is_nitro_nec_packet_header* header) {
|
||||
header->count = to_le(header->count);
|
||||
header->address = to_le(header->address);
|
||||
}
|
||||
|
||||
// Write to bulk endpoint. Returns libusb error code
|
||||
static int bulk_out(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t *buf, int length, int *transferred) {
|
||||
if(handlers->usb_handle)
|
||||
return is_device_libusb_bulk_out(handlers, usb_device_desc, buf, length, transferred);
|
||||
return is_driver_bulk_out(handlers, usb_device_desc, buf, length, transferred);
|
||||
}
|
||||
|
||||
// Read from bulk endpoint. Returns libusb error code
|
||||
static int bulk_in(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t *buf, int length, int *transferred) {
|
||||
if(handlers->usb_handle)
|
||||
return is_device_libusb_bulk_in(handlers, usb_device_desc, buf, length, transferred);
|
||||
return is_driver_bulk_in(handlers, usb_device_desc, buf, length, transferred);
|
||||
}
|
||||
|
||||
// Read from bulk endpoint. Returns libusb error code
|
||||
static void bulk_in_async(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t *buf, int length, isd_async_callback_data* cb_data) {
|
||||
if(handlers->usb_handle)
|
||||
return is_device_libusb_async_in_start(handlers, usb_device_desc, buf, length, cb_data);
|
||||
is_drive_async_in_start(handlers, usb_device_desc, buf, length, cb_data);
|
||||
}
|
||||
|
||||
static int SendWritePacket(is_device_device_handlers* handlers, uint16_t command, is_device_packet_type type, uint32_t address, uint8_t* buf, int length, const is_device_usb_device* device_desc, bool expect_result = true) {
|
||||
is_device_packet_header header;
|
||||
bool append_mode = true;
|
||||
if(device_desc->device_type == IS_NITRO_CAPTURE_DEVICE)
|
||||
append_mode = false;
|
||||
uint8_t single_usb_packet[USB_PACKET_LIMIT];
|
||||
int single_packet_covered_size = USB_PACKET_LIMIT - sizeof(header);
|
||||
if(!append_mode)
|
||||
single_packet_covered_size = USB_PACKET_LIMIT;
|
||||
int num_iters = (length + single_packet_covered_size - 1) / single_packet_covered_size;
|
||||
if(!num_iters)
|
||||
num_iters = 1;
|
||||
for(int i = 0; i < num_iters; i++) {
|
||||
int transfer_size = length - (i * single_packet_covered_size);
|
||||
if(transfer_size > single_packet_covered_size)
|
||||
transfer_size = single_packet_covered_size;
|
||||
|
||||
uint8_t packet_direction = 0;
|
||||
switch(device_desc->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
packet_direction = IS_NITRO_PACKET_EMU_DIR_WRITE;
|
||||
break;
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
packet_direction = IS_NITRO_PACKET_CAP_DIR_WRITE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
header.command = command;
|
||||
header.direction = packet_direction;
|
||||
header.type = type;
|
||||
header.address = address;
|
||||
header.length = transfer_size;
|
||||
header.padding = 0;
|
||||
fix_endianness_header(&header);
|
||||
int ret = 0;
|
||||
int num_bytes = 0;
|
||||
for(int j = 0; j < sizeof(is_device_packet_header); j++)
|
||||
single_usb_packet[j] = ((uint8_t*)&header)[j];
|
||||
if(append_mode && (buf != NULL)) {
|
||||
for(int j = 0; j < transfer_size; j++)
|
||||
single_usb_packet[sizeof(is_device_packet_header) + j] = buf[(i * single_packet_covered_size) + j];
|
||||
ret = bulk_out(handlers, device_desc, single_usb_packet, transfer_size + sizeof(is_device_packet_header), &num_bytes);
|
||||
}
|
||||
else {
|
||||
int header_bytes = 0;
|
||||
ret = bulk_out(handlers, device_desc, single_usb_packet, sizeof(is_device_packet_header), &header_bytes);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
if(header_bytes != sizeof(is_device_packet_header))
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
if((buf != NULL) && (transfer_size > 0))
|
||||
ret = bulk_out(handlers, device_desc, &buf[(i * single_packet_covered_size)], transfer_size, &num_bytes);
|
||||
num_bytes += header_bytes;
|
||||
}
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
if(num_bytes != (transfer_size + sizeof(is_device_packet_header)))
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
}
|
||||
if((device_desc->device_type == IS_NITRO_CAPTURE_DEVICE) && expect_result) {
|
||||
uint8_t status[16];
|
||||
int status_bytes = 0;
|
||||
int ret = bulk_in(handlers, device_desc, status, sizeof(status), &status_bytes);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
if(status_bytes != sizeof(status))
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
if(status[0] != 1)
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
}
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
static int SendReadPacket(is_device_device_handlers* handlers, uint16_t command, is_device_packet_type type, uint32_t address, uint8_t* buf, int length, const is_device_usb_device* device_desc, bool expect_result = true) {
|
||||
is_device_packet_header header;
|
||||
int single_packet_covered_size = USB_PACKET_LIMIT;
|
||||
int num_iters = (length + single_packet_covered_size - 1) / single_packet_covered_size;
|
||||
if(num_iters == 0)
|
||||
num_iters = 1;
|
||||
for(int i = 0; i < num_iters; i++) {
|
||||
int transfer_size = length - (i * single_packet_covered_size);
|
||||
if(transfer_size > single_packet_covered_size)
|
||||
transfer_size = single_packet_covered_size;
|
||||
|
||||
uint8_t packet_direction = 0;
|
||||
switch(device_desc->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
packet_direction = IS_NITRO_PACKET_EMU_DIR_READ;
|
||||
break;
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
packet_direction = IS_NITRO_PACKET_CAP_DIR_READ;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
header.command = command;
|
||||
header.direction = packet_direction;
|
||||
header.type = type;
|
||||
header.address = address;
|
||||
header.length = transfer_size;
|
||||
header.padding = 0;
|
||||
fix_endianness_header(&header);
|
||||
int num_bytes = 0;
|
||||
int ret = bulk_out(handlers, device_desc, (uint8_t*)&header, sizeof(is_device_packet_header), &num_bytes);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
if(num_bytes != sizeof(is_device_packet_header))
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
if(buf != NULL) {
|
||||
ret = bulk_in(handlers, device_desc, buf + (i * single_packet_covered_size), transfer_size, &num_bytes);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
if(num_bytes != transfer_size)
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
}
|
||||
}
|
||||
if((device_desc->device_type == IS_NITRO_CAPTURE_DEVICE) && expect_result) {
|
||||
uint8_t status[16];
|
||||
int status_bytes = 0;
|
||||
int ret = bulk_in(handlers, device_desc, status, sizeof(status), &status_bytes);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
if(status_bytes != sizeof(status))
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
if(status[0] != 1)
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
}
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
int SendReadCommand(is_device_device_handlers* handlers, uint16_t command, uint8_t* buf, int length, const is_device_usb_device* device_desc) {
|
||||
return SendReadPacket(handlers, command, IS_NITRO_PACKET_TYPE_COMMAND, 0, buf, length, device_desc);
|
||||
}
|
||||
|
||||
int SendWriteCommand(is_device_device_handlers* handlers, uint16_t command, uint8_t* buf, int length, const is_device_usb_device* device_desc) {
|
||||
return SendWritePacket(handlers, command, IS_NITRO_PACKET_TYPE_COMMAND, 0, buf, length, device_desc);
|
||||
}
|
||||
|
||||
int SendReadCommandU32(is_device_device_handlers* handlers, uint16_t command, uint32_t* out, const is_device_usb_device* device_desc) {
|
||||
uint32_t buffer;
|
||||
int ret = SendReadCommand(handlers, command, (uint8_t*)&buffer, sizeof(uint32_t), device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = from_le(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SendWriteCommandU32(is_device_device_handlers* handlers, uint16_t command, uint32_t value, const is_device_usb_device* device_desc) {
|
||||
uint32_t buffer = to_le(value);
|
||||
return SendWriteCommand(handlers, command, (uint8_t*)&buffer, sizeof(uint32_t), device_desc);
|
||||
}
|
||||
|
||||
int GetDeviceSerial(is_device_device_handlers* handlers, uint8_t* buf, const is_device_usb_device* device_desc) {
|
||||
switch(device_desc->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
return SendReadCommand(handlers, IS_NITRO_EMU_CMD_GET_SERIAL, buf, IS_DEVICE_REAL_SERIAL_NUMBER_SIZE, device_desc);
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
return SendReadCommand(handlers, IS_NITRO_CAP_CMD_GET_SERIAL, buf, IS_DEVICE_REAL_SERIAL_NUMBER_SIZE, device_desc);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ReadNecMem(is_device_device_handlers* handlers, uint32_t address, uint8_t unit_size, uint8_t* buf, int count, const is_device_usb_device* device_desc) {
|
||||
is_nitro_nec_packet_header header;
|
||||
header.command = IS_NITRO_EMU_CMD_SET_READ_NEC_MEM;
|
||||
header.unit_size = unit_size;
|
||||
header.count = count;
|
||||
header.address = address;
|
||||
fix_endianness_header(&header);
|
||||
int ret = SendWriteCommand(handlers, header.command, (uint8_t*)&header, sizeof(is_nitro_nec_packet_header), device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
return SendReadCommand(handlers, IS_NITRO_EMU_CMD_READ_NEC_MEM, buf, count * unit_size, device_desc);
|
||||
}
|
||||
|
||||
int ReadNecMemU16(is_device_device_handlers* handlers, uint32_t address, uint16_t* out, const is_device_usb_device* device_desc) {
|
||||
uint16_t buffer;
|
||||
int ret = ReadNecMem(handlers, address, 2, (uint8_t*)&buffer, 1, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = from_le(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ReadNecMemU32(is_device_device_handlers* handlers, uint32_t address, uint32_t* out, const is_device_usb_device* device_desc) {
|
||||
uint32_t buffer;
|
||||
int ret = ReadNecMem(handlers, address, 2, (uint8_t*)&buffer, 2, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = from_le(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WriteNecMem(is_device_device_handlers* handlers, uint32_t address, uint8_t unit_size, uint8_t* buf, int count, const is_device_usb_device* device_desc) {
|
||||
uint8_t* buffer = new uint8_t[(count * unit_size) + sizeof(is_nitro_nec_packet_header)];
|
||||
is_nitro_nec_packet_header header;
|
||||
header.command = IS_NITRO_EMU_CMD_WRITE_NEC_MEM;
|
||||
header.unit_size = unit_size;
|
||||
header.count = count;
|
||||
header.address = address;
|
||||
fix_endianness_header(&header);
|
||||
for(int i = 0; i < sizeof(is_nitro_nec_packet_header); i++)
|
||||
buffer[i] = ((uint8_t*)&header)[i];
|
||||
for(int i = 0; i < count * unit_size; i++)
|
||||
buffer[i + sizeof(is_nitro_nec_packet_header)] = buf[i];
|
||||
int ret = SendWriteCommand(handlers, header.command, buffer, (count * unit_size) + sizeof(is_nitro_nec_packet_header), device_desc);
|
||||
delete []buffer;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int WriteNecMemU16(is_device_device_handlers* handlers, uint32_t address, uint16_t value, const is_device_usb_device* device_desc) {
|
||||
uint16_t buffer = to_le(value);
|
||||
return WriteNecMem(handlers, address, 2, (uint8_t*)&buffer, 1, device_desc);
|
||||
}
|
||||
|
||||
int WriteNecMemU32(is_device_device_handlers* handlers, uint32_t address, uint32_t value, const is_device_usb_device* device_desc) {
|
||||
uint32_t buffer = to_le(value);
|
||||
return WriteNecMem(handlers, address, 2, (uint8_t*)&buffer, 2, device_desc);
|
||||
}
|
||||
|
||||
int DisableLca2(is_device_device_handlers* handlers, const is_device_usb_device* device_desc) {
|
||||
if(device_desc->device_type != IS_NITRO_EMULATOR_DEVICE)
|
||||
return LIBUSB_SUCCESS;
|
||||
int ret = WriteNecMemU16(handlers, 0x00805180, 0, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
ret = WriteNecMemU16(handlers, 0x0F84000A, 1, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
//SleepBetweenTransfers(handlers, 2000);
|
||||
return WriteNecMemU16(handlers, 0x0F84000A, 0, device_desc);
|
||||
}
|
||||
|
||||
int StartUsbCaptureDma(is_device_device_handlers* handlers, const is_device_usb_device* device_desc) {
|
||||
int ret = 0;
|
||||
switch(device_desc->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
ret = WriteNecMemU16(handlers, REG_USB_DMA_CONTROL_2, 2, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
return WriteNecMemU16(handlers, REG_USB_BIU_CONTROL_2, 1, device_desc);
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
return SendReadPacket(handlers, IS_NITRO_CAP_CMD_ENABLE_CAP, IS_NITRO_CAPTURE_PACKET_TYPE_DMA_CONTROL, 0, NULL, 1, device_desc, false);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int StopUsbCaptureDma(is_device_device_handlers* handlers, const is_device_usb_device* device_desc) {
|
||||
int ret = 0;
|
||||
switch(device_desc->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
ret = WriteNecMemU16(handlers, REG_USB_DMA_CONTROL_2, 0, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
return WriteNecMemU16(handlers, REG_USB_BIU_CONTROL_2, 0, device_desc);
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
return SendReadPacket(handlers, IS_NITRO_CAP_CMD_ENABLE_CAP, IS_NITRO_CAPTURE_PACKET_TYPE_DMA_CONTROL, 0, NULL, 0, device_desc);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int SetForwardFrameCount(is_device_device_handlers* handlers, uint16_t count, const is_device_usb_device* device_desc) {
|
||||
if(!count)
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
count -= 1;
|
||||
switch(device_desc->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
return WriteNecMemU32(handlers, 0x0800000C, (count >> 8) | ((count & 0xFF) << 16), device_desc);
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
return SendWriteCommandU32(handlers, IS_NITRO_CAP_CMD_SET_FWD_FRAMES, count, device_desc);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int SetForwardFramePermanent(is_device_device_handlers* handlers, const is_device_usb_device* device_desc) {
|
||||
return SetForwardFrameCount(handlers, 0x4001, device_desc);
|
||||
}
|
||||
|
||||
int GetFrameCounter(is_device_device_handlers* handlers, uint16_t* out, const is_device_usb_device* device_desc) {
|
||||
int ret = 0;
|
||||
uint32_t counter = 0;
|
||||
switch(device_desc->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
ReadNecMemU32(handlers, 0x08000028, &counter, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = (counter & 0xFF) | ((counter & 0xFF0000) >> 8);
|
||||
return ret;
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
*out = 0;
|
||||
return LIBUSB_SUCCESS;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int UpdateFrameForwardConfig(is_device_device_handlers* handlers, is_device_forward_config_values_colors colors, is_device_forward_config_values_screens screens, is_device_forward_config_values_rate rate, const is_device_usb_device* device_desc) {
|
||||
int ret = 0;
|
||||
switch(device_desc->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
return WriteNecMemU16(handlers, 0x0800000A, ((colors & 1) << 4) | ((screens & 3) << 2) | ((rate & 3) << 0), device_desc);
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
ret = SendWriteCommandU32(handlers, IS_NITRO_CAP_CMD_SET_FWD_RATE, rate & 3, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
ret = SendWriteCommandU32(handlers, IS_NITRO_CAP_CMD_SET_FWD_MODE, screens & 3, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
return SendWriteCommandU32(handlers, IS_NITRO_CAP_CMD_SET_FWD_COLOURS, colors & 1, device_desc);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int UpdateFrameForwardEnable(is_device_device_handlers* handlers, bool enable, bool restart, const is_device_usb_device* device_desc) {
|
||||
uint32_t value = 0;
|
||||
switch(device_desc->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
if(enable)
|
||||
value |= (1 << IS_NITRO_EMULATOR_FORWARD_ENABLE_BIT);
|
||||
if(restart)
|
||||
value |= (1 << IS_NITRO_EMULATOR_FORWARD_COUNTER_RESTART_BIT);
|
||||
return WriteNecMemU16(handlers, 0x08000008, value, device_desc);
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
if(restart)
|
||||
value |= (1 << IS_NITRO_CAPTURE_FORWARD_COUNTER_RESTART_BIT);
|
||||
return SendWriteCommandU32(handlers, IS_NITRO_CAP_CMD_SET_FWD_RESTART, value, device_desc);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ReadLidState(is_device_device_handlers* handlers, bool* out, const is_device_usb_device* device_desc) {
|
||||
uint32_t flags = 0;
|
||||
int ret = 0;
|
||||
switch(device_desc->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
ret = ReadNecMemU32(handlers, 0x08000000, &flags, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = (flags & 2) ? true : false;
|
||||
return ret;
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
ret = SendReadCommandU32(handlers, IS_NITRO_CAP_CMD_GET_LID_STATE, &flags, device_desc);
|
||||
*out = (flags & 1) ? true : false;
|
||||
return ret;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ReadDebugButtonState(is_device_device_handlers* handlers, bool* out, const is_device_usb_device* device_desc) {
|
||||
uint32_t flags = 0;
|
||||
int ret = 0;
|
||||
switch(device_desc->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
ret = ReadNecMemU32(handlers, 0x08000000, &flags, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = (flags & 1) ? true : false;
|
||||
return ret;
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
ret = SendReadCommandU32(handlers, IS_NITRO_CAP_CMD_GET_DEBUG_STATE, &flags, device_desc);
|
||||
*out = (flags & 1) ? true : false;
|
||||
return ret;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ReadPowerButtonState(is_device_device_handlers* handlers, bool* out, const is_device_usb_device* device_desc) {
|
||||
return ReadDebugButtonState(handlers, out, device_desc);
|
||||
}
|
||||
|
||||
static int ResetCPUEmulatorGeneral(is_device_device_handlers* handlers, bool on, const is_device_usb_device* device_desc) {
|
||||
uint8_t data[] = {IS_NITRO_EMU_CMD_CPU_RESET, 0, (uint8_t)(on ? 1 : 0), 0};
|
||||
return SendWriteCommand(handlers, IS_NITRO_EMU_CMD_CPU_RESET, data, sizeof(data), device_desc);
|
||||
}
|
||||
|
||||
int ResetCPUStart(is_device_device_handlers* handlers, const is_device_usb_device* device_desc) {
|
||||
switch(device_desc->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
return ResetCPUEmulatorGeneral(handlers, true, device_desc);
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
return SendWriteCommand(handlers, IS_NITRO_CAP_CMD_SET_RESET_CPU_ON, NULL, 0, device_desc);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ResetCPUEnd(is_device_device_handlers* handlers, const is_device_usb_device* device_desc) {
|
||||
switch(device_desc->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
return ResetCPUEmulatorGeneral(handlers, false, device_desc);
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
return SendWriteCommand(handlers, IS_NITRO_CAP_CMD_SET_RESET_CPU_OFF, NULL, 0, device_desc);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ResetFullHardware(is_device_device_handlers* handlers, const is_device_usb_device* device_desc) {
|
||||
uint8_t isn_emu_rst_data[] = {IS_NITRO_EMU_CMD_FULL_HARDWARE_RESET, 0xF2};
|
||||
switch(device_desc->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
return SendWriteCommand(handlers, IS_NITRO_EMU_CMD_FULL_HARDWARE_RESET, isn_emu_rst_data, sizeof(isn_emu_rst_data), device_desc);
|
||||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
return SendWriteCommand(handlers, IS_NITRO_CAP_CMD_SET_RESTART_FULL, NULL, 0, device_desc);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ReadFrame(is_device_device_handlers* handlers, uint8_t* buf, int length, const is_device_usb_device* device_desc) {
|
||||
// Maybe making this async would be better for lower end hardware...
|
||||
int num_bytes = 0;
|
||||
int ret = bulk_in(handlers, device_desc, buf, length, &num_bytes);
|
||||
if(num_bytes != length)
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ReadFrameAsync(is_device_device_handlers* handlers, uint8_t* buf, int length, const is_device_usb_device* device_desc, isd_async_callback_data* cb_data) {
|
||||
return bulk_in_async(handlers, device_desc, buf, length, cb_data);
|
||||
}
|
||||
|
||||
void CloseAsyncRead(is_device_device_handlers* handlers, isd_async_callback_data* cb_data) {
|
||||
if(handlers->usb_handle)
|
||||
return is_device_libusb_cancell_callback(cb_data);
|
||||
return is_device_is_driver_cancel_callback(cb_data);
|
||||
}
|
||||
|
||||
int ResetUSBDevice(is_device_device_handlers* handlers) {
|
||||
if(handlers->usb_handle)
|
||||
return is_device_libusb_reset_device(handlers);
|
||||
return is_device_is_driver_reset_device(handlers);
|
||||
}
|
||||
|
||||
void SetupISDeviceAsyncThread(is_device_device_handlers* handlers, void* user_data, std::thread* thread_ptr, bool* keep_going, ConsumerMutex* is_data_ready) {
|
||||
if(handlers->usb_handle)
|
||||
return is_device_libusb_start_thread(thread_ptr, keep_going);
|
||||
return is_device_is_driver_start_thread(thread_ptr, keep_going, (ISDeviceCaptureReceivedData*)user_data, handlers, is_data_ready);
|
||||
}
|
||||
|
||||
void EndISDeviceAsyncThread(is_device_device_handlers* handlers, void* user_data, std::thread* thread_ptr, bool* keep_going, ConsumerMutex* is_data_ready) {
|
||||
if(handlers->usb_handle)
|
||||
return is_device_libusb_close_thread(thread_ptr, keep_going);
|
||||
return is_device_is_driver_close_thread(thread_ptr, keep_going, (ISDeviceCaptureReceivedData*)user_data);
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
#include "usb_is_nitro_communications.hpp"
|
||||
#include "usb_is_nitro_setup_general.hpp"
|
||||
#include "usb_is_nitro_is_driver.hpp"
|
||||
#include "usb_is_nitro_acquisition_general.hpp"
|
||||
#include "usb_is_device_communications.hpp"
|
||||
#include "usb_is_device_setup_general.hpp"
|
||||
#include "usb_is_device_is_driver.hpp"
|
||||
#include "frontend.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
|
|
@ -29,22 +28,22 @@
|
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
const GUID is_nitro_driver_guid = { .Data1 = 0xB78D7ADA, .Data2 = 0xDDF4, .Data3 = 0x418F, .Data4 = {0x8C, 0x7C, 0x4A, 0xC8, 0x80, 0x30, 0xF5, 0x42} };
|
||||
const GUID is_device_driver_guid = { .Data1 = 0xB78D7ADA, .Data2 = 0xDDF4, .Data3 = 0x418F, .Data4 = {0x8C, 0x7C, 0x4A, 0xC8, 0x80, 0x30, 0xF5, 0x42} };
|
||||
|
||||
static void is_nitro_is_driver_function(bool* usb_thread_run, ISNitroCaptureReceivedData* is_nitro_capture_recv_data, is_nitro_device_handlers* handlers) {
|
||||
static void is_device_is_driver_function(bool* usb_thread_run, ISDeviceCaptureReceivedData* is_device_capture_recv_data, is_device_device_handlers* handlers) {
|
||||
while(*usb_thread_run) {
|
||||
for (int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
isn_async_callback_data* cb_data = (isn_async_callback_data*)&is_nitro_capture_recv_data[i].cb_data;
|
||||
isd_async_callback_data* cb_data = (isd_async_callback_data*)&is_device_capture_recv_data[i].cb_data;
|
||||
bool read_data_ready = false;
|
||||
cb_data->transfer_data_access.lock();
|
||||
read_data_ready = cb_data->is_data_ready;
|
||||
cb_data->is_data_ready = false;
|
||||
cb_data->transfer_data_access.unlock();
|
||||
if(is_nitro_capture_recv_data[i].in_use && read_data_ready)
|
||||
cb_data->function(&is_nitro_capture_recv_data[i], cb_data->actual_length, cb_data->status_value);
|
||||
if(is_device_capture_recv_data[i].in_use && read_data_ready)
|
||||
cb_data->function(&is_device_capture_recv_data[i], cb_data->actual_length, cb_data->status_value);
|
||||
}
|
||||
int dummy = 0;
|
||||
is_nitro_capture_recv_data[0].cb_data.is_transfer_data_ready_mutex->general_timed_lock(&dummy);
|
||||
is_device_capture_recv_data[0].cb_data.is_transfer_data_ready_mutex->general_timed_lock(&dummy);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +99,7 @@ static bool is_driver_get_device_pid_vid(std::string path, uint16_t& out_vid, ui
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool is_driver_setup_connection(is_nitro_device_handlers* handlers, std::string path) {
|
||||
static bool is_driver_setup_connection(is_device_device_handlers* handlers, std::string path) {
|
||||
handlers->usb_handle = NULL;
|
||||
handlers->mutex = NULL;
|
||||
handlers->write_handle = INVALID_HANDLE_VALUE;
|
||||
|
|
@ -127,7 +126,7 @@ static bool is_driver_setup_connection(is_nitro_device_handlers* handlers, std::
|
|||
return true;
|
||||
}
|
||||
|
||||
static int wait_result_io_operation(HANDLE handle, OVERLAPPED* overlapped_var, int* transferred, const is_nitro_usb_device* usb_device_desc) {
|
||||
static int wait_result_io_operation(HANDLE handle, OVERLAPPED* overlapped_var, int* transferred, const is_device_usb_device* usb_device_desc) {
|
||||
DWORD num_bytes = 0;
|
||||
int retval = 0;
|
||||
int error = 0;
|
||||
|
|
@ -146,7 +145,7 @@ static int wait_result_io_operation(HANDLE handle, OVERLAPPED* overlapped_var, i
|
|||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
static void STDCALL BasicCompletionOutputRoutine(isn_async_callback_data* cb_data, int num_bytes, int error) {
|
||||
static void STDCALL BasicCompletionOutputRoutine(isd_async_callback_data* cb_data, int num_bytes, int error) {
|
||||
cb_data->transfer_data_access.lock();
|
||||
if ((error == LIBUSB_SUCCESS) && (num_bytes != cb_data->requested_length))
|
||||
error = LIBUSB_ERROR_INTERRUPTED;
|
||||
|
|
@ -165,13 +164,13 @@ static void STDCALL OverlappedCompletionNothingRoutine(DWORD dwErrorCode, DWORD
|
|||
|
||||
#endif
|
||||
|
||||
is_nitro_device_handlers* is_driver_serial_reconnection(CaptureDevice* device) {
|
||||
is_nitro_device_handlers* final_handlers = NULL;
|
||||
is_device_device_handlers* is_driver_serial_reconnection(CaptureDevice* device) {
|
||||
is_device_device_handlers* final_handlers = NULL;
|
||||
#ifdef _WIN32
|
||||
if (device->path != "") {
|
||||
is_nitro_device_handlers handlers;
|
||||
is_device_device_handlers handlers;
|
||||
if (is_driver_setup_connection(&handlers, device->path)) {
|
||||
final_handlers = new is_nitro_device_handlers;
|
||||
final_handlers = new is_device_device_handlers;
|
||||
final_handlers->usb_handle = NULL;
|
||||
final_handlers->mutex = handlers.mutex;
|
||||
final_handlers->read_handle = handlers.read_handle;
|
||||
|
|
@ -184,7 +183,7 @@ is_nitro_device_handlers* is_driver_serial_reconnection(CaptureDevice* device) {
|
|||
return final_handlers;
|
||||
}
|
||||
|
||||
void is_driver_end_connection(is_nitro_device_handlers* handlers) {
|
||||
void is_driver_end_connection(is_device_device_handlers* handlers) {
|
||||
#ifdef _WIN32
|
||||
if (handlers->write_handle != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(handlers->write_handle);
|
||||
|
|
@ -198,10 +197,10 @@ void is_driver_end_connection(is_nitro_device_handlers* handlers) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void is_driver_list_devices(std::vector<CaptureDevice> &devices_list, bool* not_supported_elems, int *curr_serial_extra_id_is_nitro, const size_t num_is_nitro_desc) {
|
||||
void is_driver_list_devices(std::vector<CaptureDevice> &devices_list, bool* not_supported_elems, int *curr_serial_extra_id_is_device, const size_t num_is_device_desc) {
|
||||
#ifdef _WIN32
|
||||
HDEVINFO DeviceInfoSet = SetupDiGetClassDevs(
|
||||
&is_nitro_driver_guid,
|
||||
&is_device_driver_guid,
|
||||
NULL,
|
||||
NULL,
|
||||
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
|
|
@ -210,7 +209,7 @@ void is_driver_list_devices(std::vector<CaptureDevice> &devices_list, bool* not_
|
|||
ZeroMemory(&DeviceInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA));
|
||||
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
uint32_t i = 0;
|
||||
while (SetupDiEnumDeviceInterfaces(DeviceInfoSet, NULL, &is_nitro_driver_guid, i++, &DeviceInterfaceData)) {
|
||||
while (SetupDiEnumDeviceInterfaces(DeviceInfoSet, NULL, &is_device_driver_guid, i++, &DeviceInterfaceData)) {
|
||||
std::string path = is_driver_get_device_path(DeviceInfoSet, &DeviceInterfaceData);
|
||||
if (path == "")
|
||||
continue;
|
||||
|
|
@ -218,12 +217,12 @@ void is_driver_list_devices(std::vector<CaptureDevice> &devices_list, bool* not_
|
|||
uint16_t pid = 0;
|
||||
if(!is_driver_get_device_pid_vid(path, vid, pid))
|
||||
continue;
|
||||
for (int j = 0; j < num_is_nitro_desc; j++) {
|
||||
const is_nitro_usb_device* usb_device_desc = GetISNitroDesc(j);
|
||||
for (int j = 0; j < num_is_device_desc; j++) {
|
||||
const is_device_usb_device* usb_device_desc = GetISDeviceDesc(j);
|
||||
if(not_supported_elems[j] && (usb_device_desc->vid == vid) && (usb_device_desc->pid == pid)) {
|
||||
is_nitro_device_handlers handlers;
|
||||
is_device_device_handlers handlers;
|
||||
if(is_driver_setup_connection(&handlers, path))
|
||||
is_nitro_insert_device(devices_list, &handlers, usb_device_desc, curr_serial_extra_id_is_nitro[j], path);
|
||||
is_device_insert_device(devices_list, &handlers, usb_device_desc, curr_serial_extra_id_is_device[j], path);
|
||||
is_driver_end_connection(&handlers);
|
||||
break;
|
||||
}
|
||||
|
|
@ -237,7 +236,7 @@ void is_driver_list_devices(std::vector<CaptureDevice> &devices_list, bool* not_
|
|||
}
|
||||
|
||||
// Write to bulk
|
||||
int is_driver_bulk_out(is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred) {
|
||||
int is_driver_bulk_out(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred) {
|
||||
#ifdef _WIN32
|
||||
OVERLAPPED overlapped_var;
|
||||
memset(&overlapped_var, 0, sizeof(OVERLAPPED));
|
||||
|
|
@ -251,7 +250,7 @@ int is_driver_bulk_out(is_nitro_device_handlers* handlers, const is_nitro_usb_de
|
|||
}
|
||||
|
||||
// Read from bulk
|
||||
int is_driver_bulk_in(is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred) {
|
||||
int is_driver_bulk_in(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred) {
|
||||
#ifdef _WIN32
|
||||
OVERLAPPED overlapped_var;
|
||||
memset(&overlapped_var, 0, sizeof(OVERLAPPED));
|
||||
|
|
@ -263,7 +262,7 @@ int is_driver_bulk_in(is_nitro_device_handlers* handlers, const is_nitro_usb_dev
|
|||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
int is_drive_async_in_start(is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, uint8_t* buf, int length, isn_async_callback_data* cb_data) {
|
||||
int is_drive_async_in_start(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t* buf, int length, isd_async_callback_data* cb_data) {
|
||||
#ifdef _WIN32
|
||||
cb_data->transfer_data_access.lock();
|
||||
cb_data->is_data_ready = false;
|
||||
|
|
@ -286,26 +285,30 @@ int is_drive_async_in_start(is_nitro_device_handlers* handlers, const is_nitro_u
|
|||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
void is_nitro_is_driver_start_thread(std::thread* thread_ptr, bool* usb_thread_run, ISNitroCaptureReceivedData* is_nitro_capture_recv_data, is_nitro_device_handlers* handlers, ConsumerMutex* AsyncMutexPtr) {
|
||||
void is_device_is_driver_start_thread(std::thread* thread_ptr, bool* usb_thread_run, ISDeviceCaptureReceivedData* is_device_capture_recv_data, is_device_device_handlers* handlers, ConsumerMutex* AsyncMutexPtr) {
|
||||
#ifdef _WIN32
|
||||
*usb_thread_run = true;
|
||||
for (int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
is_nitro_capture_recv_data[i].cb_data.base_transfer_data = new OVERLAPPED;
|
||||
*thread_ptr = std::thread(is_nitro_is_driver_function, usb_thread_run, is_nitro_capture_recv_data, handlers);
|
||||
is_device_capture_recv_data[i].cb_data.base_transfer_data = new OVERLAPPED;
|
||||
*thread_ptr = std::thread(is_device_is_driver_function, usb_thread_run, is_device_capture_recv_data, handlers);
|
||||
#endif
|
||||
}
|
||||
|
||||
void is_nitro_is_driver_close_thread(std::thread* thread_ptr, bool* usb_thread_run, ISNitroCaptureReceivedData* is_nitro_capture_recv_data) {
|
||||
void is_device_is_driver_close_thread(std::thread* thread_ptr, bool* usb_thread_run, ISDeviceCaptureReceivedData* is_device_capture_recv_data) {
|
||||
#ifdef _WIN32
|
||||
*usb_thread_run = false;
|
||||
is_nitro_capture_recv_data[0].cb_data.is_transfer_data_ready_mutex->specific_unlock(0);
|
||||
is_device_capture_recv_data[0].cb_data.is_transfer_data_ready_mutex->specific_unlock(0);
|
||||
thread_ptr->join();
|
||||
for (int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
delete is_nitro_capture_recv_data[i].cb_data.base_transfer_data;
|
||||
delete is_device_capture_recv_data[i].cb_data.base_transfer_data;
|
||||
#endif
|
||||
}
|
||||
|
||||
void is_nitro_is_driver_cancel_callback(isn_async_callback_data* cb_data) {
|
||||
int is_device_is_driver_reset_device(is_device_device_handlers* handlers) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void is_device_is_driver_cancel_callback(isd_async_callback_data* cb_data) {
|
||||
#ifdef _WIN32
|
||||
// Nothing
|
||||
#endif
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "usb_is_nitro_communications.hpp"
|
||||
#include "usb_is_nitro_setup_general.hpp"
|
||||
#include "usb_is_nitro_libusb.hpp"
|
||||
#include "usb_is_device_communications.hpp"
|
||||
#include "usb_is_device_setup_general.hpp"
|
||||
#include "usb_is_device_libusb.hpp"
|
||||
#include "usb_generic.hpp"
|
||||
|
||||
#include <libusb.h>
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
static void is_nitro_usb_thread_function(bool* usb_thread_run) {
|
||||
static void is_device_usb_thread_function(bool* usb_thread_run) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
struct timeval tv;
|
||||
|
|
@ -35,21 +35,21 @@ static void is_nitro_usb_thread_function(bool* usb_thread_run) {
|
|||
libusb_handle_events_timeout_completed(get_usb_ctx(), &tv, NULL);
|
||||
}
|
||||
|
||||
void is_nitro_libusb_start_thread(std::thread* thread_ptr, bool* usb_thread_run) {
|
||||
void is_device_libusb_start_thread(std::thread* thread_ptr, bool* usb_thread_run) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
*usb_thread_run = true;
|
||||
*thread_ptr = std::thread(is_nitro_usb_thread_function, usb_thread_run);
|
||||
*thread_ptr = std::thread(is_device_usb_thread_function, usb_thread_run);
|
||||
}
|
||||
|
||||
void is_nitro_libusb_close_thread(std::thread* thread_ptr, bool* usb_thread_run) {
|
||||
void is_device_libusb_close_thread(std::thread* thread_ptr, bool* usb_thread_run) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
*usb_thread_run = false;
|
||||
thread_ptr->join();
|
||||
}
|
||||
|
||||
static bool is_nitro_libusb_setup_connection(libusb_device_handle* handle, const is_nitro_usb_device* usb_device_desc) {
|
||||
static bool is_device_libusb_setup_connection(libusb_device_handle* handle, const is_device_usb_device* usb_device_desc) {
|
||||
if (libusb_set_configuration(handle, usb_device_desc->default_config) != LIBUSB_SUCCESS)
|
||||
return false;
|
||||
if(libusb_claim_interface(handle, usb_device_desc->default_interface) != LIBUSB_SUCCESS)
|
||||
|
|
@ -61,7 +61,7 @@ static bool is_nitro_libusb_setup_connection(libusb_device_handle* handle, const
|
|||
return true;
|
||||
}
|
||||
|
||||
static int is_nitro_libusb_insert_device(std::vector<CaptureDevice> &devices_list, const is_nitro_usb_device* usb_device_desc, libusb_device *usb_device, libusb_device_descriptor *usb_descriptor, int &curr_serial_extra_id) {
|
||||
static int is_device_libusb_insert_device(std::vector<CaptureDevice> &devices_list, const is_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;
|
||||
|
|
@ -70,26 +70,26 @@ static int is_nitro_libusb_insert_device(std::vector<CaptureDevice> &devices_lis
|
|||
int result = libusb_open(usb_device, &handle);
|
||||
if((result < 0) || (handle == NULL))
|
||||
return result;
|
||||
if(is_nitro_libusb_setup_connection(handle, usb_device_desc)) {
|
||||
is_nitro_device_handlers handlers;
|
||||
if(is_device_libusb_setup_connection(handle, usb_device_desc)) {
|
||||
is_device_device_handlers handlers;
|
||||
handlers.usb_handle = handle;
|
||||
is_nitro_insert_device(devices_list, &handlers, usb_device_desc, curr_serial_extra_id);
|
||||
is_device_insert_device(devices_list, &handlers, usb_device_desc, curr_serial_extra_id);
|
||||
libusb_release_interface(handle, usb_device_desc->default_interface);
|
||||
}
|
||||
libusb_close(handle);
|
||||
return result;
|
||||
}
|
||||
|
||||
is_nitro_device_handlers* is_nitro_libusb_serial_reconnection(const is_nitro_usb_device* usb_device_desc, CaptureDevice* device, int &curr_serial_extra_id) {
|
||||
is_device_device_handlers* is_device_libusb_serial_reconnection(const is_device_usb_device* usb_device_desc, CaptureDevice* device, int &curr_serial_extra_id) {
|
||||
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{};
|
||||
is_nitro_device_handlers* final_handlers = NULL;
|
||||
is_device_device_handlers* final_handlers = NULL;
|
||||
|
||||
for(int i = 0; i < num_devices; i++) {
|
||||
is_nitro_device_handlers handlers;
|
||||
is_device_device_handlers handlers;
|
||||
int result = libusb_get_device_descriptor(usb_devices[i], &usb_descriptor);
|
||||
if(result < 0)
|
||||
continue;
|
||||
|
|
@ -100,10 +100,10 @@ is_nitro_device_handlers* is_nitro_libusb_serial_reconnection(const is_nitro_usb
|
|||
result = libusb_open(usb_devices[i], &handlers.usb_handle);
|
||||
if(result || (handlers.usb_handle == NULL))
|
||||
continue;
|
||||
if (is_nitro_libusb_setup_connection(handlers.usb_handle, usb_device_desc)) {
|
||||
if (is_device_libusb_setup_connection(handlers.usb_handle, usb_device_desc)) {
|
||||
std::string device_serial_number = get_serial(usb_device_desc, &handlers, curr_serial_extra_id);
|
||||
if (device->serial_number == device_serial_number) {
|
||||
final_handlers = new is_nitro_device_handlers;
|
||||
final_handlers = new is_device_device_handlers;
|
||||
final_handlers->usb_handle = handlers.usb_handle;
|
||||
break;
|
||||
}
|
||||
|
|
@ -118,14 +118,14 @@ is_nitro_device_handlers* is_nitro_libusb_serial_reconnection(const is_nitro_usb
|
|||
return final_handlers;
|
||||
}
|
||||
|
||||
void is_nitro_libusb_end_connection(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc, bool interface_claimed) {
|
||||
void is_device_libusb_end_connection(is_device_device_handlers* handlers, const is_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 is_nitro_libusb_list_devices(std::vector<CaptureDevice> &devices_list, bool* no_access_elems, bool* not_supported_elems, int* curr_serial_extra_id_is_nitro, const size_t num_is_nitro_desc) {
|
||||
void is_device_libusb_list_devices(std::vector<CaptureDevice> &devices_list, bool* no_access_elems, bool* not_supported_elems, int* curr_serial_extra_id_is_device, const size_t num_is_device_desc) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
libusb_device **usb_devices;
|
||||
|
|
@ -136,8 +136,8 @@ void is_nitro_libusb_list_devices(std::vector<CaptureDevice> &devices_list, bool
|
|||
int result = libusb_get_device_descriptor(usb_devices[i], &usb_descriptor);
|
||||
if(result < 0)
|
||||
continue;
|
||||
for (int j = 0; j < num_is_nitro_desc; j++) {
|
||||
result = is_nitro_libusb_insert_device(devices_list, GetISNitroDesc(j), usb_devices[i], &usb_descriptor, curr_serial_extra_id_is_nitro[j]);
|
||||
for (int j = 0; j < num_is_device_desc; j++) {
|
||||
result = is_device_libusb_insert_device(devices_list, GetISDeviceDesc(j), usb_devices[i], &usb_descriptor, curr_serial_extra_id_is_device[j]);
|
||||
if (result != LIBUSB_ERROR_NOT_FOUND) {
|
||||
if (result == LIBUSB_ERROR_ACCESS)
|
||||
no_access_elems[j] = true;
|
||||
|
|
@ -153,24 +153,28 @@ void is_nitro_libusb_list_devices(std::vector<CaptureDevice> &devices_list, bool
|
|||
}
|
||||
|
||||
// Write to bulk
|
||||
int is_nitro_libusb_bulk_out(is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred) {
|
||||
int is_device_libusb_bulk_out(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred) {
|
||||
return libusb_bulk_transfer(handlers->usb_handle, usb_device_desc->ep1_out, buf, length, transferred, usb_device_desc->bulk_timeout);
|
||||
}
|
||||
|
||||
// Read from bulk
|
||||
int is_nitro_libusb_bulk_in(is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred) {
|
||||
int is_device_libusb_bulk_in(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred) {
|
||||
return libusb_bulk_transfer(handlers->usb_handle, usb_device_desc->ep2_in, buf, length, transferred, usb_device_desc->bulk_timeout);
|
||||
}
|
||||
|
||||
void is_nitro_libusb_cancell_callback(isn_async_callback_data* cb_data) {
|
||||
void is_device_libusb_cancell_callback(isd_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 is_nitro_libusb_async_callback(libusb_transfer* transfer) {
|
||||
isn_async_callback_data* cb_data = (isn_async_callback_data*)transfer->user_data;
|
||||
int is_device_libusb_reset_device(is_device_device_handlers* handlers) {
|
||||
return libusb_reset_device(handlers->usb_handle);
|
||||
}
|
||||
|
||||
void STDCALL is_device_libusb_async_callback(libusb_transfer* transfer) {
|
||||
isd_async_callback_data* cb_data = (isd_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);
|
||||
|
|
@ -179,14 +183,14 @@ void STDCALL is_nitro_libusb_async_callback(libusb_transfer* transfer) {
|
|||
}
|
||||
|
||||
// Read from bulk
|
||||
void is_nitro_libusb_async_in_start(is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, uint8_t* buf, int length, isn_async_callback_data* cb_data) {
|
||||
void is_device_libusb_async_in_start(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t* buf, int length, isd_async_callback_data* cb_data) {
|
||||
libusb_transfer *transfer_in = libusb_alloc_transfer(0);
|
||||
if(!transfer_in)
|
||||
return;
|
||||
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->ep2_in, buf, length, is_nitro_libusb_async_callback, cb_data, usb_device_desc->bulk_timeout);
|
||||
libusb_fill_bulk_transfer(transfer_in, handlers->usb_handle, usb_device_desc->ep2_in, buf, length, is_device_libusb_async_callback, cb_data, usb_device_desc->bulk_timeout);
|
||||
transfer_in->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
||||
libusb_submit_transfer(transfer_in);
|
||||
cb_data->transfer_data_access.unlock();
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#include "devicecapture.hpp"
|
||||
#include "usb_is_nitro_communications.hpp"
|
||||
#include "usb_is_nitro_acquisition_general.hpp"
|
||||
#include "usb_is_device_communications.hpp"
|
||||
#include "usb_is_device_acquisition_general.hpp"
|
||||
#include "usb_is_nitro_acquisition_capture.hpp"
|
||||
|
||||
// Code created by analyzing the USB packets sent and received by the IS Nitro Capture device.
|
||||
|
|
@ -13,9 +13,9 @@
|
|||
#define SLEEP_CHECKS_TIME_MS 20
|
||||
#define SLEEP_RESET_TIME_MS 2000
|
||||
|
||||
static int StartAcquisitionCapture(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data, CaptureScreensType capture_type, CaptureSpeedsType capture_speed, bool* is_acquisition_off, uint32_t &index) {
|
||||
is_nitro_device_handlers* handlers = (is_nitro_device_handlers*)capture_data->handle;
|
||||
const is_nitro_usb_device* usb_device_desc = (const is_nitro_usb_device*)capture_data->status.device.descriptor;
|
||||
static int StartAcquisitionCapture(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data, CaptureScreensType capture_type, CaptureSpeedsType capture_speed, bool* is_acquisition_off, uint32_t &index) {
|
||||
is_device_device_handlers* handlers = (is_device_device_handlers*)capture_data->handle;
|
||||
const is_device_usb_device* usb_device_desc = (const is_device_usb_device*)capture_data->status.device.descriptor;
|
||||
int ret = 0;
|
||||
ret = ReadLidState(handlers, is_acquisition_off, usb_device_desc);
|
||||
if(ret < 0)
|
||||
|
|
@ -34,16 +34,16 @@ static int StartAcquisitionCapture(CaptureData* capture_data, ISNitroCaptureRece
|
|||
ret = StartUsbCaptureDma(handlers, usb_device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
reset_is_nitro_status(is_nitro_capture_recv_data);
|
||||
reset_is_device_status(is_device_capture_recv_data);
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
is_nitro_read_frame_request(capture_data, is_nitro_get_free_buffer(capture_data, is_nitro_capture_recv_data), capture_type, index++);
|
||||
is_device_read_frame_request(capture_data, is_device_get_free_buffer(capture_data, is_device_capture_recv_data), capture_type, index++);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int LidReopenCaptureCheck(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data, CaptureScreensType &curr_capture_type, CaptureSpeedsType &curr_capture_speed, bool* is_acquisition_off, uint32_t &index) {
|
||||
static int LidReopenCaptureCheck(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data, CaptureScreensType &curr_capture_type, CaptureSpeedsType &curr_capture_speed, bool* is_acquisition_off, uint32_t &index) {
|
||||
curr_capture_type = capture_data->status.capture_type;
|
||||
curr_capture_speed = capture_data->status.capture_speed;
|
||||
int ret = StartAcquisitionCapture(capture_data, is_nitro_capture_recv_data, curr_capture_type, curr_capture_speed, is_acquisition_off, index);
|
||||
int ret = StartAcquisitionCapture(capture_data, is_device_capture_recv_data, curr_capture_type, curr_capture_speed, is_acquisition_off, index);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
if(!(*is_acquisition_off))
|
||||
|
|
@ -51,9 +51,9 @@ static int LidReopenCaptureCheck(CaptureData* capture_data, ISNitroCaptureReceiv
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int CaptureResetHardware(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data, CaptureScreensType &curr_capture_type, CaptureSpeedsType &curr_capture_speed, bool *is_acquisition_off, std::chrono::time_point<std::chrono::high_resolution_clock> &clock_last_reset, uint32_t &index) {
|
||||
is_nitro_device_handlers* handlers = (is_nitro_device_handlers*)capture_data->handle;
|
||||
const is_nitro_usb_device* usb_device_desc = (const is_nitro_usb_device*)capture_data->status.device.descriptor;
|
||||
static int CaptureResetHardware(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data, CaptureScreensType &curr_capture_type, CaptureSpeedsType &curr_capture_speed, bool *is_acquisition_off, std::chrono::time_point<std::chrono::high_resolution_clock> &clock_last_reset, uint32_t &index) {
|
||||
is_device_device_handlers* handlers = (is_device_device_handlers*)capture_data->handle;
|
||||
const is_device_usb_device* usb_device_desc = (const is_device_usb_device*)capture_data->status.device.descriptor;
|
||||
bool reset_hardware = capture_data->status.reset_hardware;
|
||||
capture_data->status.reset_hardware = false;
|
||||
int ret = LIBUSB_SUCCESS;
|
||||
|
|
@ -67,7 +67,7 @@ static int CaptureResetHardware(CaptureData* capture_data, ISNitroCaptureReceive
|
|||
clock_last_reset = curr_time;
|
||||
|
||||
if(!(*is_acquisition_off))
|
||||
ret = EndAcquisitionCapture(capture_data, is_nitro_capture_recv_data);
|
||||
ret = EndAcquisitionCapture(capture_data, is_device_capture_recv_data);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
ret = ResetCPUStart(handlers, usb_device_desc);
|
||||
|
|
@ -80,35 +80,35 @@ static int CaptureResetHardware(CaptureData* capture_data, ISNitroCaptureReceive
|
|||
default_sleep(SLEEP_RESET_TIME_MS);
|
||||
curr_capture_type = capture_data->status.capture_type;
|
||||
curr_capture_speed = capture_data->status.capture_speed;
|
||||
ret = StartAcquisitionCapture(capture_data, is_nitro_capture_recv_data, curr_capture_type, curr_capture_speed, is_acquisition_off, index);
|
||||
ret = StartAcquisitionCapture(capture_data, is_device_capture_recv_data, curr_capture_type, curr_capture_speed, is_acquisition_off, index);
|
||||
}
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int initial_cleanup_capture(const is_nitro_usb_device* usb_device_desc, is_nitro_device_handlers* handlers) {
|
||||
int initial_cleanup_capture(const is_device_usb_device* usb_device_desc, is_device_device_handlers* handlers) {
|
||||
//EndAcquisition(handlers, usb_device_desc, false, 0, CAPTURE_SCREENS_BOTH);
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
int EndAcquisitionCapture(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data) {
|
||||
wait_all_is_nitro_transfers_done(capture_data, is_nitro_capture_recv_data);
|
||||
return EndAcquisitionCapture((const is_nitro_usb_device*)capture_data->status.device.descriptor, (is_nitro_device_handlers*)capture_data->handle);
|
||||
int EndAcquisitionCapture(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data) {
|
||||
wait_all_is_device_transfers_done(capture_data, is_device_capture_recv_data);
|
||||
return EndAcquisitionCapture((const is_device_usb_device*)capture_data->status.device.descriptor, (is_device_device_handlers*)capture_data->handle);
|
||||
}
|
||||
|
||||
int EndAcquisitionCapture(const is_nitro_usb_device* usb_device_desc, is_nitro_device_handlers* handlers) {
|
||||
int EndAcquisitionCapture(const is_device_usb_device* usb_device_desc, is_device_device_handlers* handlers) {
|
||||
return StopUsbCaptureDma(handlers, usb_device_desc);
|
||||
}
|
||||
|
||||
void is_nitro_acquisition_capture_main_loop(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data) {
|
||||
is_nitro_device_handlers* handlers = (is_nitro_device_handlers*)capture_data->handle;
|
||||
const is_nitro_usb_device* usb_device_desc = (const is_nitro_usb_device*)capture_data->status.device.descriptor;
|
||||
void is_nitro_acquisition_capture_main_loop(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data) {
|
||||
is_device_device_handlers* handlers = (is_device_device_handlers*)capture_data->handle;
|
||||
const is_device_usb_device* usb_device_desc = (const is_device_usb_device*)capture_data->status.device.descriptor;
|
||||
bool is_acquisition_off = true;
|
||||
uint32_t index = 0;
|
||||
CaptureScreensType curr_capture_type = capture_data->status.capture_type;
|
||||
CaptureSpeedsType curr_capture_speed = capture_data->status.capture_speed;
|
||||
int ret = StartAcquisitionCapture(capture_data, is_nitro_capture_recv_data, curr_capture_type, curr_capture_speed, &is_acquisition_off, index);
|
||||
int ret = StartAcquisitionCapture(capture_data, is_device_capture_recv_data, curr_capture_type, curr_capture_speed, &is_acquisition_off, index);
|
||||
if(ret < 0) {
|
||||
capture_error_print(true, capture_data, "Capture Start: Failed");
|
||||
return;
|
||||
|
|
@ -116,14 +116,14 @@ void is_nitro_acquisition_capture_main_loop(CaptureData* capture_data, ISNitroCa
|
|||
auto clock_last_reset = std::chrono::high_resolution_clock::now();
|
||||
|
||||
while(capture_data->status.connected && capture_data->status.running) {
|
||||
ret = CaptureResetHardware(capture_data, is_nitro_capture_recv_data, curr_capture_type, curr_capture_speed, &is_acquisition_off, clock_last_reset, index);
|
||||
ret = CaptureResetHardware(capture_data, is_device_capture_recv_data, curr_capture_type, curr_capture_speed, &is_acquisition_off, clock_last_reset, index);
|
||||
if(ret < 0) {
|
||||
capture_error_print(true, capture_data, "Hardware reset: Failed");
|
||||
return;
|
||||
}
|
||||
if(is_acquisition_off) {
|
||||
default_sleep(SLEEP_CHECKS_TIME_MS);
|
||||
ret = LidReopenCaptureCheck(capture_data, is_nitro_capture_recv_data, curr_capture_type, curr_capture_speed, &is_acquisition_off, index);
|
||||
ret = LidReopenCaptureCheck(capture_data, is_device_capture_recv_data, curr_capture_type, curr_capture_speed, &is_acquisition_off, index);
|
||||
if(ret < 0) {
|
||||
capture_error_print(true, capture_data, "Lid Reopen: Failed");
|
||||
return;
|
||||
|
|
@ -131,10 +131,10 @@ void is_nitro_acquisition_capture_main_loop(CaptureData* capture_data, ISNitroCa
|
|||
}
|
||||
if(is_acquisition_off)
|
||||
continue;
|
||||
wait_one_is_nitro_buffer_free(capture_data, is_nitro_capture_recv_data);
|
||||
ret = get_is_nitro_status(is_nitro_capture_recv_data);
|
||||
wait_one_is_device_buffer_free(capture_data, is_device_capture_recv_data);
|
||||
ret = get_is_device_status(is_device_capture_recv_data);
|
||||
if(ret < 0) {
|
||||
ret = EndAcquisition(capture_data, is_nitro_capture_recv_data, true, 0, curr_capture_type);
|
||||
ret = EndAcquisition(capture_data, is_device_capture_recv_data, true, 0, curr_capture_type);
|
||||
if(ret < 0) {
|
||||
capture_error_print(true, capture_data, "Disconnected: Read error");
|
||||
return;
|
||||
|
|
@ -142,17 +142,17 @@ void is_nitro_acquisition_capture_main_loop(CaptureData* capture_data, ISNitroCa
|
|||
is_acquisition_off = true;
|
||||
continue;
|
||||
}
|
||||
is_nitro_read_frame_request(capture_data, is_nitro_get_free_buffer(capture_data, is_nitro_capture_recv_data), curr_capture_type, index++);
|
||||
is_device_read_frame_request(capture_data, is_device_get_free_buffer(capture_data, is_device_capture_recv_data), curr_capture_type, index++);
|
||||
|
||||
if((curr_capture_type != capture_data->status.capture_type) || (curr_capture_speed != capture_data->status.capture_speed)) {
|
||||
ret = EndAcquisition(capture_data, is_nitro_capture_recv_data, true, 0, curr_capture_type);
|
||||
ret = EndAcquisition(capture_data, is_device_capture_recv_data, true, 0, curr_capture_type);
|
||||
if(ret < 0) {
|
||||
capture_error_print(true, capture_data, "Capture End: Failed");
|
||||
return;
|
||||
}
|
||||
curr_capture_type = capture_data->status.capture_type;
|
||||
curr_capture_speed = capture_data->status.capture_speed;
|
||||
ret = StartAcquisitionCapture(capture_data, is_nitro_capture_recv_data, curr_capture_type, curr_capture_speed, &is_acquisition_off, index);
|
||||
ret = StartAcquisitionCapture(capture_data, is_device_capture_recv_data, curr_capture_type, curr_capture_speed, &is_acquisition_off, index);
|
||||
if(ret < 0) {
|
||||
capture_error_print(true, capture_data, "Capture Restart: Failed");
|
||||
return;
|
||||
|
|
@ -160,5 +160,5 @@ void is_nitro_acquisition_capture_main_loop(CaptureData* capture_data, ISNitroCa
|
|||
}
|
||||
}
|
||||
if(!is_acquisition_off)
|
||||
EndAcquisition(capture_data, is_nitro_capture_recv_data, true, 0, curr_capture_type);
|
||||
EndAcquisition(capture_data, is_device_capture_recv_data, true, 0, curr_capture_type);
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
#include "devicecapture.hpp"
|
||||
#include "usb_is_nitro_communications.hpp"
|
||||
#include "usb_is_nitro_acquisition.hpp"
|
||||
#include "usb_is_nitro_acquisition_general.hpp"
|
||||
#include "usb_is_device_communications.hpp"
|
||||
#include "usb_is_device_acquisition_general.hpp"
|
||||
#include "usb_is_nitro_acquisition_emulator.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
|
@ -33,10 +32,10 @@
|
|||
|
||||
#define SLEEP_TIME_DIVISOR 8
|
||||
|
||||
static int drain_frames(is_nitro_device_handlers* handlers, int num_frames, int start_frames, CaptureScreensType capture_type, const is_nitro_usb_device* usb_device_desc) {
|
||||
static int drain_frames(is_device_device_handlers* handlers, int num_frames, int start_frames, CaptureScreensType capture_type, const is_device_usb_device* usb_device_desc) {
|
||||
ISNitroEmulatorVideoInputData* video_in_buffer = new ISNitroEmulatorVideoInputData;
|
||||
for (int i = start_frames; i < num_frames; i++) {
|
||||
int ret = ReadFrame(handlers, (uint8_t*)video_in_buffer, usb_is_nitro_get_video_in_size(capture_type), usb_device_desc);
|
||||
int ret = ReadFrame(handlers, (uint8_t*)video_in_buffer, usb_is_device_get_video_in_size(capture_type, usb_device_desc->device_type), usb_device_desc);
|
||||
if(ret < 0) {
|
||||
delete video_in_buffer;
|
||||
return ret;
|
||||
|
|
@ -46,7 +45,7 @@ static int drain_frames(is_nitro_device_handlers* handlers, int num_frames, int
|
|||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
static int StartAcquisitionEmulator(is_nitro_device_handlers* handlers, uint16_t &out_frame_count, float &single_frame_time, CaptureScreensType capture_type, CaptureSpeedsType capture_speed, const is_nitro_usb_device* usb_device_desc) {
|
||||
static int StartAcquisitionEmulator(is_device_device_handlers* handlers, uint16_t &out_frame_count, float &single_frame_time, CaptureScreensType capture_type, CaptureSpeedsType capture_speed, const is_device_usb_device* usb_device_desc) {
|
||||
int ret = 0;
|
||||
ret = DisableLca2(handlers, usb_device_desc);
|
||||
if(ret < 0)
|
||||
|
|
@ -180,16 +179,16 @@ static void frame_wait(float single_frame_time, std::chrono::time_point<std::chr
|
|||
}
|
||||
}
|
||||
|
||||
static int reset_acquisition_frames(CaptureData* capture_data, uint16_t &curr_frame_counter, uint16_t &last_frame_counter, float &single_frame_time, std::chrono::time_point<std::chrono::high_resolution_clock> &clock_last_reset, CaptureScreensType &curr_capture_type, CaptureScreensType wanted_capture_type, CaptureSpeedsType &curr_capture_speed, CaptureSpeedsType wanted_capture_speed, ISNitroCaptureReceivedData* is_nitro_capture_recv_data) {
|
||||
static int reset_acquisition_frames(CaptureData* capture_data, uint16_t &curr_frame_counter, uint16_t &last_frame_counter, float &single_frame_time, std::chrono::time_point<std::chrono::high_resolution_clock> &clock_last_reset, CaptureScreensType &curr_capture_type, CaptureScreensType wanted_capture_type, CaptureSpeedsType &curr_capture_speed, CaptureSpeedsType wanted_capture_speed, ISDeviceCaptureReceivedData* is_device_capture_recv_data) {
|
||||
curr_frame_counter += 1;
|
||||
|
||||
if(curr_frame_counter < FRAME_BUFFER_SIZE)
|
||||
return LIBUSB_SUCCESS;
|
||||
|
||||
is_nitro_device_handlers* handlers = (is_nitro_device_handlers*)capture_data->handle;
|
||||
const is_nitro_usb_device* usb_device_desc = (const is_nitro_usb_device*)capture_data->status.device.descriptor;
|
||||
wait_all_is_nitro_transfers_done(capture_data, is_nitro_capture_recv_data);
|
||||
int ret = get_is_nitro_status(is_nitro_capture_recv_data);
|
||||
is_device_device_handlers* handlers = (is_device_device_handlers*)capture_data->handle;
|
||||
const is_device_usb_device* usb_device_desc = (const is_device_usb_device*)capture_data->status.device.descriptor;
|
||||
wait_all_is_device_transfers_done(capture_data, is_device_capture_recv_data);
|
||||
int ret = get_is_device_status(is_device_capture_recv_data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
|
@ -300,16 +299,16 @@ static int reset_acquisition_frames(CaptureData* capture_data, uint16_t &curr_fr
|
|||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
int initial_cleanup_emulator(const is_nitro_usb_device* usb_device_desc, is_nitro_device_handlers* handlers) {
|
||||
int initial_cleanup_emulator(const is_device_usb_device* usb_device_desc, is_device_device_handlers* handlers) {
|
||||
return EndAcquisition(usb_device_desc, handlers, false, 0, CAPTURE_SCREENS_BOTH);
|
||||
}
|
||||
|
||||
int EndAcquisitionEmulator(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data, bool do_drain_frames, int start_frames, CaptureScreensType capture_type) {
|
||||
wait_all_is_nitro_transfers_done(capture_data, is_nitro_capture_recv_data);
|
||||
return EndAcquisitionEmulator((const is_nitro_usb_device*)capture_data->status.device.descriptor, (is_nitro_device_handlers*)capture_data->handle, do_drain_frames, start_frames, capture_type);
|
||||
int EndAcquisitionEmulator(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data, bool do_drain_frames, int start_frames, CaptureScreensType capture_type) {
|
||||
wait_all_is_device_transfers_done(capture_data, is_device_capture_recv_data);
|
||||
return EndAcquisitionEmulator((const is_device_usb_device*)capture_data->status.device.descriptor, (is_device_device_handlers*)capture_data->handle, do_drain_frames, start_frames, capture_type);
|
||||
}
|
||||
|
||||
int EndAcquisitionEmulator(const is_nitro_usb_device* usb_device_desc, is_nitro_device_handlers* handlers, bool do_drain_frames, int start_frames, CaptureScreensType capture_type) {
|
||||
int EndAcquisitionEmulator(const is_device_usb_device* usb_device_desc, is_device_device_handlers* handlers, bool do_drain_frames, int start_frames, CaptureScreensType capture_type) {
|
||||
int ret = 0;
|
||||
if (do_drain_frames)
|
||||
ret = drain_frames(handlers, FRAME_BUFFER_SIZE, start_frames, capture_type, usb_device_desc);
|
||||
|
|
@ -321,9 +320,9 @@ int EndAcquisitionEmulator(const is_nitro_usb_device* usb_device_desc, is_nitro_
|
|||
return UpdateFrameForwardEnable(handlers, false, false, usb_device_desc);
|
||||
}
|
||||
|
||||
void is_nitro_acquisition_emulator_main_loop(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data) {
|
||||
is_nitro_device_handlers* handlers = (is_nitro_device_handlers*)capture_data->handle;
|
||||
const is_nitro_usb_device* usb_device_desc = (const is_nitro_usb_device*)capture_data->status.device.descriptor;
|
||||
void is_nitro_acquisition_emulator_main_loop(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data) {
|
||||
is_device_device_handlers* handlers = (is_device_device_handlers*)capture_data->handle;
|
||||
const is_device_usb_device* usb_device_desc = (const is_device_usb_device*)capture_data->status.device.descriptor;
|
||||
uint32_t index = 0;
|
||||
uint16_t last_frame_counter = 0;
|
||||
float single_frame_time = 0;
|
||||
|
|
@ -338,13 +337,13 @@ void is_nitro_acquisition_emulator_main_loop(CaptureData* capture_data, ISNitroC
|
|||
auto clock_last_reset = std::chrono::high_resolution_clock::now();
|
||||
|
||||
while (capture_data->status.connected && capture_data->status.running) {
|
||||
ret = get_is_nitro_status(is_nitro_capture_recv_data);
|
||||
ret = get_is_device_status(is_device_capture_recv_data);
|
||||
if(ret < 0) {
|
||||
capture_error_print(true, capture_data, "Disconnected: Read error");
|
||||
return;
|
||||
}
|
||||
if(single_frame_time > 0) {
|
||||
is_nitro_read_frame_request(capture_data, is_nitro_get_free_buffer(capture_data, is_nitro_capture_recv_data), curr_capture_type, index++);
|
||||
is_device_read_frame_request(capture_data, is_device_get_free_buffer(capture_data, is_device_capture_recv_data), curr_capture_type, index++);
|
||||
frame_wait(single_frame_time, clock_last_reset, curr_capture_type, curr_capture_speed, curr_frame_counter + 1, last_frame_counter);
|
||||
}
|
||||
else {
|
||||
|
|
@ -353,11 +352,11 @@ void is_nitro_acquisition_emulator_main_loop(CaptureData* capture_data, ISNitroC
|
|||
default_sleep(SLEEP_CHECKS_TIME_MS);
|
||||
}
|
||||
capture_data->status.curr_delay = last_frame_counter % FRAME_BUFFER_SIZE;
|
||||
ret = reset_acquisition_frames(capture_data, curr_frame_counter, last_frame_counter, single_frame_time, clock_last_reset, curr_capture_type, capture_data->status.capture_type, curr_capture_speed, capture_data->status.capture_speed, is_nitro_capture_recv_data);
|
||||
ret = reset_acquisition_frames(capture_data, curr_frame_counter, last_frame_counter, single_frame_time, clock_last_reset, curr_capture_type, capture_data->status.capture_type, curr_capture_speed, capture_data->status.capture_speed, is_device_capture_recv_data);
|
||||
if(ret < 0) {
|
||||
capture_error_print(true, capture_data, "Disconnected: Frame counter reset error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
EndAcquisition(capture_data, is_nitro_capture_recv_data, true, curr_frame_counter, curr_capture_type);
|
||||
EndAcquisition(capture_data, is_device_capture_recv_data, true, curr_frame_counter, curr_capture_type);
|
||||
}
|
||||
|
|
@ -1,380 +0,0 @@
|
|||
#include "devicecapture.hpp"
|
||||
#include "usb_is_nitro_communications.hpp"
|
||||
#include "usb_is_nitro_acquisition.hpp"
|
||||
#include "usb_is_nitro_acquisition_general.hpp"
|
||||
#include "usb_is_nitro_acquisition_capture.hpp"
|
||||
#include "usb_is_nitro_acquisition_emulator.hpp"
|
||||
#include "usb_is_nitro_setup_general.hpp"
|
||||
#include "usb_is_nitro_libusb.hpp"
|
||||
#include "usb_is_nitro_is_driver.hpp"
|
||||
#include "usb_generic.hpp"
|
||||
|
||||
#include <libusb.h>
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
|
||||
// Code based off of Gericom's sample code. Distributed under the MIT License. Copyright (c) 2024 Gericom
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#define SERIAL_NUMBER_SIZE (IS_NITRO_REAL_SERIAL_NUMBER_SIZE + 1)
|
||||
|
||||
#define FRAME_BUFFER_SIZE 32
|
||||
|
||||
static void is_nitro_read_frame_cb(void* user_data, int transfer_length, int transfer_status);
|
||||
|
||||
static bool initial_cleanup(const is_nitro_usb_device* usb_device_desc, is_nitro_device_handlers* handlers) {
|
||||
if(!usb_device_desc->is_capture)
|
||||
return initial_cleanup_emulator(usb_device_desc, handlers) != LIBUSB_SUCCESS;
|
||||
return initial_cleanup_capture(usb_device_desc, handlers) != LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
std::string get_serial(const is_nitro_usb_device* usb_device_desc, is_nitro_device_handlers* handlers, int& curr_serial_extra_id) {
|
||||
uint8_t data[SERIAL_NUMBER_SIZE];
|
||||
std::string serial_str = std::to_string(curr_serial_extra_id);
|
||||
bool conn_success = true;
|
||||
if(initial_cleanup(usb_device_desc, handlers))
|
||||
conn_success = false;
|
||||
if (conn_success && (GetDeviceSerial(handlers, data, usb_device_desc) != LIBUSB_SUCCESS))
|
||||
conn_success = false;
|
||||
if (conn_success) {
|
||||
data[IS_NITRO_REAL_SERIAL_NUMBER_SIZE] = '\0';
|
||||
serial_str = std::string((const char*)data);
|
||||
}
|
||||
else
|
||||
curr_serial_extra_id += 1;
|
||||
return serial_str;
|
||||
}
|
||||
|
||||
void is_nitro_insert_device(std::vector<CaptureDevice>& devices_list, is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, int& curr_serial_extra_id_is_nitro, std::string path) {
|
||||
devices_list.emplace_back(get_serial(usb_device_desc, handlers, curr_serial_extra_id_is_nitro), usb_device_desc->name, usb_device_desc->long_name, path, CAPTURE_CONN_IS_NITRO, (void*)usb_device_desc, false, false, false, WIDTH_DS, HEIGHT_DS + HEIGHT_DS, 0, 0, 0, 0, 0, HEIGHT_DS, VIDEO_DATA_BGR);
|
||||
}
|
||||
|
||||
void is_nitro_insert_device(std::vector<CaptureDevice>& devices_list, is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, int& curr_serial_extra_id_is_nitro) {
|
||||
devices_list.emplace_back(get_serial(usb_device_desc, handlers, curr_serial_extra_id_is_nitro), usb_device_desc->name, usb_device_desc->long_name, CAPTURE_CONN_IS_NITRO, (void*)usb_device_desc, false, false, false, WIDTH_DS, HEIGHT_DS + HEIGHT_DS, 0, 0, 0, 0, 0, HEIGHT_DS, VIDEO_DATA_BGR);
|
||||
}
|
||||
|
||||
static is_nitro_device_handlers* usb_find_by_serial_number(const is_nitro_usb_device* usb_device_desc, CaptureDevice* device) {
|
||||
is_nitro_device_handlers* final_handlers = NULL;
|
||||
int curr_serial_extra_id = 0;
|
||||
final_handlers = is_nitro_libusb_serial_reconnection(usb_device_desc, device, curr_serial_extra_id);
|
||||
|
||||
if (final_handlers == NULL)
|
||||
final_handlers = is_driver_serial_reconnection(device);
|
||||
return final_handlers;
|
||||
}
|
||||
|
||||
void list_devices_is_nitro(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list) {
|
||||
const size_t num_is_nitro_desc = GetNumISNitroDesc();
|
||||
int* curr_serial_extra_id_is_nitro = new int[num_is_nitro_desc];
|
||||
bool* no_access_elems = new bool[num_is_nitro_desc];
|
||||
bool* not_supported_elems = new bool[num_is_nitro_desc];
|
||||
for (int i = 0; i < num_is_nitro_desc; i++) {
|
||||
no_access_elems[i] = false;
|
||||
not_supported_elems[i] = false;
|
||||
curr_serial_extra_id_is_nitro[i] = 0;
|
||||
}
|
||||
is_nitro_libusb_list_devices(devices_list, no_access_elems, not_supported_elems, curr_serial_extra_id_is_nitro, num_is_nitro_desc);
|
||||
|
||||
bool any_not_supported = false;
|
||||
for(int i = 0; i < num_is_nitro_desc; i++)
|
||||
any_not_supported |= not_supported_elems[i];
|
||||
for(int i = 0; i < num_is_nitro_desc; i++)
|
||||
if(no_access_elems[i]) {
|
||||
const is_nitro_usb_device* usb_device = GetISNitroDesc(i);
|
||||
no_access_list.emplace_back(usb_device->vid, usb_device->pid);
|
||||
}
|
||||
if(any_not_supported)
|
||||
is_driver_list_devices(devices_list, not_supported_elems, curr_serial_extra_id_is_nitro, num_is_nitro_desc);
|
||||
|
||||
delete[] curr_serial_extra_id_is_nitro;
|
||||
delete[] no_access_elems;
|
||||
delete[] not_supported_elems;
|
||||
}
|
||||
|
||||
static void is_nitro_connection_end(is_nitro_device_handlers* handlers, const is_nitro_usb_device *device_desc, bool interface_claimed = true) {
|
||||
if (handlers == NULL)
|
||||
return;
|
||||
if (handlers->usb_handle)
|
||||
is_nitro_libusb_end_connection(handlers, device_desc, interface_claimed);
|
||||
else
|
||||
is_driver_end_connection(handlers);
|
||||
delete handlers;
|
||||
}
|
||||
|
||||
bool is_nitro_connect_usb(bool print_failed, CaptureData* capture_data, CaptureDevice* device) {
|
||||
const is_nitro_usb_device* usb_device_info = (const is_nitro_usb_device*)device->descriptor;
|
||||
is_nitro_device_handlers* handlers = usb_find_by_serial_number(usb_device_info, device);
|
||||
if(handlers == NULL) {
|
||||
capture_error_print(true, capture_data, "Device not found");
|
||||
return false;
|
||||
}
|
||||
capture_data->handle = (void*)handlers;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t usb_is_nitro_get_video_in_size(CaptureScreensType capture_type) {
|
||||
if((capture_type == CAPTURE_SCREENS_TOP) || (capture_type == CAPTURE_SCREENS_BOTTOM))
|
||||
return sizeof(ISNitroEmulatorVideoInputData) / 2;
|
||||
return sizeof(ISNitroEmulatorVideoInputData);
|
||||
}
|
||||
|
||||
|
||||
uint64_t usb_is_nitro_get_video_in_size(CaptureData* capture_data) {
|
||||
return usb_is_nitro_get_video_in_size(capture_data->status.capture_type);
|
||||
}
|
||||
|
||||
int set_acquisition_mode(is_nitro_device_handlers* handlers, CaptureScreensType capture_type, CaptureSpeedsType capture_speed, const is_nitro_usb_device* usb_device_desc) {
|
||||
is_nitro_forward_config_values_screens capture_mode_flag = IS_NITRO_FORWARD_CONFIG_MODE_BOTH;
|
||||
switch(capture_type) {
|
||||
case CAPTURE_SCREENS_TOP:
|
||||
capture_mode_flag = IS_NITRO_FORWARD_CONFIG_MODE_TOP;
|
||||
break;
|
||||
case CAPTURE_SCREENS_BOTTOM:
|
||||
capture_mode_flag = IS_NITRO_FORWARD_CONFIG_MODE_BOTTOM;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
is_nitro_forward_config_values_rate capture_rate_flag = IS_NITRO_FORWARD_CONFIG_RATE_FULL;
|
||||
switch(capture_speed) {
|
||||
case CAPTURE_SPEEDS_HALF:
|
||||
capture_rate_flag = IS_NITRO_FORWARD_CONFIG_RATE_HALF;
|
||||
break;
|
||||
case CAPTURE_SPEEDS_THIRD:
|
||||
capture_rate_flag = IS_NITRO_FORWARD_CONFIG_RATE_THIRD;
|
||||
break;
|
||||
case CAPTURE_SPEEDS_QUARTER:
|
||||
capture_rate_flag = IS_NITRO_FORWARD_CONFIG_RATE_QUARTER;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return UpdateFrameForwardConfig(handlers, IS_NITRO_FORWARD_CONFIG_COLOR_RGB24, capture_mode_flag, capture_rate_flag, usb_device_desc);
|
||||
}
|
||||
|
||||
int EndAcquisition(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data, bool do_drain_frames, int start_frames, CaptureScreensType capture_type) {
|
||||
if(((const is_nitro_usb_device*)(capture_data->status.device.descriptor))->is_capture)
|
||||
return EndAcquisitionCapture(capture_data, is_nitro_capture_recv_data);
|
||||
return EndAcquisitionEmulator(capture_data, is_nitro_capture_recv_data, do_drain_frames, start_frames, capture_type);
|
||||
}
|
||||
|
||||
int EndAcquisition(const is_nitro_usb_device* usb_device_desc, is_nitro_device_handlers* handlers, bool do_drain_frames, int start_frames, CaptureScreensType capture_type) {
|
||||
if(usb_device_desc->is_capture)
|
||||
return EndAcquisitionCapture(usb_device_desc, handlers);
|
||||
return EndAcquisitionEmulator(usb_device_desc, handlers, do_drain_frames, start_frames, capture_type);
|
||||
}
|
||||
|
||||
static void output_to_thread(CaptureData* capture_data, CaptureReceived* capture_buf, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start) {
|
||||
// Output to the other threads...
|
||||
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, usb_is_nitro_get_video_in_size(curr_capture_type), 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 is_nitro_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 ret = ReadFrame((is_nitro_device_handlers*)capture_data->handle, (uint8_t*)capture_buf, usb_is_nitro_get_video_in_size(curr_capture_type), (const is_nitro_usb_device*)capture_data->status.device.descriptor);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
output_to_thread(capture_data, capture_buf, curr_capture_type, &clock_start);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void is_nitro_read_frame_request(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data, CaptureScreensType curr_capture_type, uint32_t index) {
|
||||
if(is_nitro_capture_recv_data == NULL)
|
||||
return;
|
||||
is_nitro_capture_recv_data->index = index;
|
||||
is_nitro_capture_recv_data->curr_capture_type = curr_capture_type;
|
||||
is_nitro_capture_recv_data->cb_data.function = is_nitro_read_frame_cb;
|
||||
ReadFrameAsync((is_nitro_device_handlers*)capture_data->handle, (uint8_t*)&is_nitro_capture_recv_data->buffer, usb_is_nitro_get_video_in_size(curr_capture_type), (const is_nitro_usb_device*)capture_data->status.device.descriptor, &is_nitro_capture_recv_data->cb_data);
|
||||
}
|
||||
|
||||
static void end_is_nitro_read_frame_cb(ISNitroCaptureReceivedData* is_nitro_capture_recv_data) {
|
||||
is_nitro_capture_recv_data->in_use = false;
|
||||
is_nitro_capture_recv_data->is_buffer_free_shared_mutex->specific_unlock(is_nitro_capture_recv_data->cb_data.internal_index);
|
||||
}
|
||||
|
||||
static void is_nitro_read_frame_cb(void* user_data, int transfer_length, int transfer_status) {
|
||||
ISNitroCaptureReceivedData* is_nitro_capture_recv_data = (ISNitroCaptureReceivedData*)user_data;
|
||||
if((*is_nitro_capture_recv_data->status) < 0)
|
||||
return end_is_nitro_read_frame_cb(is_nitro_capture_recv_data);
|
||||
if(transfer_status != LIBUSB_TRANSFER_COMPLETED) {
|
||||
*is_nitro_capture_recv_data->status = LIBUSB_ERROR_OTHER;
|
||||
return end_is_nitro_read_frame_cb(is_nitro_capture_recv_data);
|
||||
}
|
||||
|
||||
if(((int32_t)(is_nitro_capture_recv_data->index - (*is_nitro_capture_recv_data->last_index))) <= 0) {
|
||||
//*is_nitro_capture_recv_data->status = LIBUSB_ERROR_INTERRUPTED;
|
||||
return end_is_nitro_read_frame_cb(is_nitro_capture_recv_data);
|
||||
}
|
||||
*is_nitro_capture_recv_data->last_index = is_nitro_capture_recv_data->index;
|
||||
|
||||
output_to_thread(is_nitro_capture_recv_data->capture_data, &is_nitro_capture_recv_data->buffer, is_nitro_capture_recv_data->curr_capture_type, is_nitro_capture_recv_data->clock_start);
|
||||
end_is_nitro_read_frame_cb(is_nitro_capture_recv_data);
|
||||
}
|
||||
|
||||
int is_nitro_get_num_free_buffers(ISNitroCaptureReceivedData* is_nitro_capture_recv_data) {
|
||||
int num_free = 0;
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
if(!is_nitro_capture_recv_data[i].in_use)
|
||||
num_free += 1;
|
||||
return num_free;
|
||||
}
|
||||
|
||||
void wait_all_is_nitro_transfers_done(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data) {
|
||||
if (is_nitro_capture_recv_data == NULL)
|
||||
return;
|
||||
if (*is_nitro_capture_recv_data[0].status < 0) {
|
||||
for (int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
CloseAsyncRead((is_nitro_device_handlers*)capture_data->handle, &is_nitro_capture_recv_data[i].cb_data);
|
||||
}
|
||||
for (int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
void* transfer_data;
|
||||
do {
|
||||
is_nitro_capture_recv_data[i].cb_data.transfer_data_access.lock();
|
||||
transfer_data = is_nitro_capture_recv_data[i].cb_data.transfer_data;
|
||||
is_nitro_capture_recv_data[i].cb_data.transfer_data_access.unlock();
|
||||
if(transfer_data)
|
||||
is_nitro_capture_recv_data[i].cb_data.is_transfer_done_mutex->specific_timed_lock(i);
|
||||
} while(transfer_data);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_all_is_nitro_buffers_free(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data) {
|
||||
if(is_nitro_capture_recv_data == NULL)
|
||||
return;
|
||||
if(*is_nitro_capture_recv_data[0].status < 0) {
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
CloseAsyncRead((is_nitro_device_handlers*)capture_data->handle, &is_nitro_capture_recv_data[i].cb_data);
|
||||
}
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
while(is_nitro_capture_recv_data[i].in_use)
|
||||
is_nitro_capture_recv_data[i].is_buffer_free_shared_mutex->specific_timed_lock(i);
|
||||
}
|
||||
|
||||
void wait_one_is_nitro_buffer_free(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data) {
|
||||
bool done = false;
|
||||
while(!done) {
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
if(!is_nitro_capture_recv_data[i].in_use)
|
||||
done = true;
|
||||
}
|
||||
if(!done) {
|
||||
if(*is_nitro_capture_recv_data[0].status < 0)
|
||||
return;
|
||||
int dummy = 0;
|
||||
is_nitro_capture_recv_data[0].is_buffer_free_shared_mutex->general_timed_lock(&dummy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_nitro_are_buffers_all_free(ISNitroCaptureReceivedData* is_nitro_capture_recv_data) {
|
||||
return is_nitro_get_num_free_buffers(is_nitro_capture_recv_data) == NUM_CAPTURE_RECEIVED_DATA_BUFFERS;
|
||||
}
|
||||
|
||||
ISNitroCaptureReceivedData* is_nitro_get_free_buffer(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data) {
|
||||
wait_one_is_nitro_buffer_free(capture_data, is_nitro_capture_recv_data);
|
||||
if(*is_nitro_capture_recv_data[0].status < 0)
|
||||
return NULL;
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
if(!is_nitro_capture_recv_data[i].in_use) {
|
||||
is_nitro_capture_recv_data[i].is_buffer_free_shared_mutex->specific_try_lock(i);
|
||||
is_nitro_capture_recv_data[i].in_use = true;
|
||||
return &is_nitro_capture_recv_data[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int get_is_nitro_status(ISNitroCaptureReceivedData* is_nitro_capture_recv_data) {
|
||||
return *is_nitro_capture_recv_data[0].status;
|
||||
}
|
||||
|
||||
void reset_is_nitro_status(ISNitroCaptureReceivedData* is_nitro_capture_recv_data) {
|
||||
*is_nitro_capture_recv_data[0].status = 0;
|
||||
}
|
||||
|
||||
void is_nitro_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;
|
||||
|
||||
uint32_t last_index = -1;
|
||||
int status = 0;
|
||||
isn_async_callback_data* cb_queue[NUM_CAPTURE_RECEIVED_DATA_BUFFERS];
|
||||
int queue_elems = 0;
|
||||
bool one_transfer_active = false;
|
||||
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();
|
||||
ISNitroCaptureReceivedData* is_nitro_capture_recv_data = new ISNitroCaptureReceivedData[NUM_CAPTURE_RECEIVED_DATA_BUFFERS];
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
is_nitro_capture_recv_data[i].in_use = false;
|
||||
is_nitro_capture_recv_data[i].index = i;
|
||||
is_nitro_capture_recv_data[i].capture_data = capture_data;
|
||||
is_nitro_capture_recv_data[i].last_index = &last_index;
|
||||
is_nitro_capture_recv_data[i].clock_start = &clock_start;
|
||||
is_nitro_capture_recv_data[i].is_buffer_free_shared_mutex = &is_buffer_free_shared_mutex;
|
||||
is_nitro_capture_recv_data[i].status = &status;
|
||||
is_nitro_capture_recv_data[i].cb_data.actual_user_data = &is_nitro_capture_recv_data[i];
|
||||
is_nitro_capture_recv_data[i].cb_data.transfer_data = NULL;
|
||||
is_nitro_capture_recv_data[i].cb_data.is_transfer_done_mutex = &is_transfer_done_shared_mutex;
|
||||
is_nitro_capture_recv_data[i].cb_data.internal_index = i;
|
||||
is_nitro_capture_recv_data[i].cb_data.is_transfer_data_ready_mutex = &is_transfer_data_ready_shared_mutex;
|
||||
is_nitro_capture_recv_data[i].cb_data.is_data_ready = false;
|
||||
}
|
||||
SetupISNitroAsyncThread((is_nitro_device_handlers*)capture_data->handle, is_nitro_capture_recv_data, &async_processing_thread, &is_done_thread, &has_data_been_processed);
|
||||
capture_data->status.reset_hardware = false;
|
||||
if(((const is_nitro_usb_device*)(capture_data->status.device.descriptor))->is_capture)
|
||||
is_nitro_acquisition_capture_main_loop(capture_data, is_nitro_capture_recv_data);
|
||||
else
|
||||
is_nitro_acquisition_emulator_main_loop(capture_data, is_nitro_capture_recv_data);
|
||||
wait_all_is_nitro_buffers_free(capture_data, is_nitro_capture_recv_data);
|
||||
EndISNitroAsyncThread((is_nitro_device_handlers*)capture_data->handle, is_nitro_capture_recv_data, &async_processing_thread, &is_done_thread, &has_data_been_processed);
|
||||
delete []is_nitro_capture_recv_data;
|
||||
}
|
||||
|
||||
void usb_is_nitro_acquisition_cleanup(CaptureData* capture_data) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
is_nitro_connection_end((is_nitro_device_handlers*)capture_data->handle, (const is_nitro_usb_device*)capture_data->status.device.descriptor);
|
||||
capture_data->handle = NULL;
|
||||
}
|
||||
|
||||
bool is_nitro_is_capture(CaptureDevice* device) {
|
||||
const is_nitro_usb_device* usb_device_info = (const is_nitro_usb_device*)device->descriptor;
|
||||
return usb_device_info->is_capture;
|
||||
}
|
||||
|
||||
void usb_is_nitro_init() {
|
||||
return usb_init();
|
||||
}
|
||||
|
||||
void usb_is_nitro_close() {
|
||||
usb_close();
|
||||
}
|
||||
|
||||
|
|
@ -1,556 +0,0 @@
|
|||
#include "frontend.hpp"
|
||||
#include "usb_is_nitro_communications.hpp"
|
||||
#include "usb_is_nitro_libusb.hpp"
|
||||
#include "usb_is_nitro_is_driver.hpp"
|
||||
|
||||
#include <libusb.h>
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
// Code based off of Gericom's sample code. Distributed under the MIT License. Copyright (c) 2024 Gericom
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#define USB_PACKET_LIMIT 0x2000
|
||||
|
||||
#define REG_USB_DMA_CONTROL_2 0x0C000028
|
||||
#define REG_USB_BIU_CONTROL_2 0x0C0000A4
|
||||
|
||||
enum is_nitro_packet_emulator_dir {
|
||||
IS_NITRO_PACKET_EMU_DIR_WRITE = 0x10,
|
||||
IS_NITRO_PACKET_EMU_DIR_READ = 0x11
|
||||
};
|
||||
|
||||
enum is_nitro_packet_capture_dir {
|
||||
IS_NITRO_PACKET_CAP_DIR_WRITE = 0x00,
|
||||
IS_NITRO_PACKET_CAP_DIR_READ = 0x01
|
||||
};
|
||||
|
||||
enum is_nitro_packet_type {
|
||||
IS_NITRO_PACKET_TYPE_COMMAND = 0,
|
||||
IS_NITRO_PACKET_TYPE_EMU_MEMORY = 1,
|
||||
IS_NITRO_EMULATOR_PACKET_TYPE_AGB_SRAM = 2,
|
||||
IS_NITRO_CAPTURE_PACKET_TYPE_DMA_CONTROL = 2,
|
||||
IS_NITRO_PACKET_TYPE_CAPTURE = 3,
|
||||
IS_NITRO_PACKET_TYPE_AGB_CART_ROM = 4,
|
||||
IS_NITRO_PACKET_TYPE_AGB_BUS2 = 5
|
||||
};
|
||||
|
||||
enum is_nitro_emulator_command {
|
||||
IS_NITRO_EMU_CMD_GET_SERIAL = 0x13,
|
||||
IS_NITRO_EMU_CMD_READ_NEC_MEM = 0x17,
|
||||
IS_NITRO_EMU_CMD_WRITE_NEC_MEM = 0x24,
|
||||
IS_NITRO_EMU_CMD_SET_READ_NEC_MEM = 0x25,
|
||||
IS_NITRO_EMU_CMD_FULL_HARDWARE_RESET = 0x81,
|
||||
IS_NITRO_EMU_CMD_CPU_RESET = 0x8A,
|
||||
IS_NITRO_EMU_CMD_AD = 0xAD,
|
||||
};
|
||||
|
||||
enum is_nitro_capture_command {
|
||||
IS_NITRO_CAP_CMD_ENABLE_CAP = 0x00,
|
||||
IS_NITRO_CAP_CMD_GET_SERIAL = 0x03,
|
||||
IS_NITRO_CAP_CMD_SET_FWD_RATE = 0x12,
|
||||
IS_NITRO_CAP_CMD_SET_FWD_MODE = 0x13,
|
||||
IS_NITRO_CAP_CMD_SET_FWD_COLOURS = 0x14,
|
||||
IS_NITRO_CAP_CMD_SET_FWD_FRAMES = 0x15,
|
||||
IS_NITRO_CAP_CMD_GET_DEBUG_STATE = 0x18,
|
||||
IS_NITRO_CAP_CMD_SET_RESTART_FULL = 0x18,
|
||||
IS_NITRO_CAP_CMD_GET_LID_STATE = 0x19,
|
||||
IS_NITRO_CAP_CMD_SET_FWD_RESTART = 0x1C,
|
||||
IS_NITRO_CAP_CMD_SET_RESET_CPU_ON = 0x21,
|
||||
IS_NITRO_CAP_CMD_SET_RESET_CPU_OFF = 0x22,
|
||||
};
|
||||
|
||||
enum is_nitro_emulator_forward_bits {
|
||||
IS_NITRO_EMULATOR_FORWARD_ENABLE_BIT = 0,
|
||||
IS_NITRO_EMULATOR_FORWARD_COUNTER_RESTART_BIT = 1,
|
||||
};
|
||||
|
||||
enum is_nitro_capture_forward_bits {
|
||||
IS_NITRO_CAPTURE_FORWARD_COUNTER_RESTART_BIT = 0,
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct PACKED is_nitro_nec_packet_header {
|
||||
uint8_t command;
|
||||
uint8_t unit_size;
|
||||
uint16_t count;
|
||||
uint32_t address;
|
||||
};
|
||||
|
||||
struct PACKED is_nitro_packet_header {
|
||||
uint16_t command;
|
||||
uint8_t direction;
|
||||
uint8_t type;
|
||||
uint32_t address;
|
||||
uint32_t length;
|
||||
uint32_t padding;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
static const is_nitro_usb_device usb_is_nitro_emu_rare_desc = {
|
||||
.name = "ISNEr", .long_name = "IS Nitro Emulator(R)",
|
||||
.vid = 0x0f6e, .pid = 0x0400,
|
||||
.default_config = 1, .default_interface = 0,
|
||||
.bulk_timeout = 500,
|
||||
.ep2_in = 2 | LIBUSB_ENDPOINT_IN, .ep1_out = 1 | LIBUSB_ENDPOINT_OUT,
|
||||
.product_id = 2, .manufacturer_id = 1, .is_capture = false
|
||||
};
|
||||
|
||||
static const is_nitro_usb_device usb_is_nitro_emu_common_desc = {
|
||||
.name = "ISNE", .long_name = "IS Nitro Emulator",
|
||||
.vid = 0x0f6e, .pid = 0x0404,
|
||||
.default_config = 1, .default_interface = 0,
|
||||
.bulk_timeout = 500,
|
||||
.ep2_in = 2 | LIBUSB_ENDPOINT_IN, .ep1_out = 1 | LIBUSB_ENDPOINT_OUT,
|
||||
.product_id = 2, .manufacturer_id = 1, .is_capture = false
|
||||
};
|
||||
|
||||
static const is_nitro_usb_device usb_is_nitro_cap_desc = {
|
||||
.name = "ISNC", .long_name = "IS Nitro Capture",
|
||||
.vid = 0x0f6e, .pid = 0x0403,
|
||||
.default_config = 1, .default_interface = 0,
|
||||
.bulk_timeout = 500,
|
||||
.ep2_in = 2 | LIBUSB_ENDPOINT_IN, .ep1_out = 1 | LIBUSB_ENDPOINT_OUT,
|
||||
.product_id = 2, .manufacturer_id = 1, .is_capture = true
|
||||
};
|
||||
|
||||
static const is_nitro_usb_device* all_usb_is_nitro_devices_desc[] = {
|
||||
&usb_is_nitro_emu_rare_desc,
|
||||
&usb_is_nitro_emu_common_desc,
|
||||
&usb_is_nitro_cap_desc,
|
||||
};
|
||||
|
||||
int GetNumISNitroDesc() {
|
||||
return sizeof(all_usb_is_nitro_devices_desc) / sizeof(all_usb_is_nitro_devices_desc[0]);
|
||||
}
|
||||
|
||||
const is_nitro_usb_device* GetISNitroDesc(int index) {
|
||||
if((index < 0) || (index >= GetNumISNitroDesc()))
|
||||
index = 0;
|
||||
return all_usb_is_nitro_devices_desc[index];
|
||||
}
|
||||
|
||||
static void fix_endianness_header(is_nitro_packet_header* header) {
|
||||
header->command = to_le(header->command);
|
||||
header->address = to_le(header->address);
|
||||
header->length = to_le(header->length);
|
||||
}
|
||||
|
||||
static void fix_endianness_header(is_nitro_nec_packet_header* header) {
|
||||
header->count = to_le(header->count);
|
||||
header->address = to_le(header->address);
|
||||
}
|
||||
|
||||
// Write to bulk endpoint. Returns libusb error code
|
||||
static int bulk_out(is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, uint8_t *buf, int length, int *transferred) {
|
||||
if(handlers->usb_handle)
|
||||
return is_nitro_libusb_bulk_out(handlers, usb_device_desc, buf, length, transferred);
|
||||
return is_driver_bulk_out(handlers, usb_device_desc, buf, length, transferred);
|
||||
}
|
||||
|
||||
// Read from bulk endpoint. Returns libusb error code
|
||||
static int bulk_in(is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, uint8_t *buf, int length, int *transferred) {
|
||||
if(handlers->usb_handle)
|
||||
return is_nitro_libusb_bulk_in(handlers, usb_device_desc, buf, length, transferred);
|
||||
return is_driver_bulk_in(handlers, usb_device_desc, buf, length, transferred);
|
||||
}
|
||||
|
||||
// Read from bulk endpoint. Returns libusb error code
|
||||
static void bulk_in_async(is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, uint8_t *buf, int length, isn_async_callback_data* cb_data) {
|
||||
if(handlers->usb_handle)
|
||||
return is_nitro_libusb_async_in_start(handlers, usb_device_desc, buf, length, cb_data);
|
||||
is_drive_async_in_start(handlers, usb_device_desc, buf, length, cb_data);
|
||||
}
|
||||
|
||||
static int SendWritePacket(is_nitro_device_handlers* handlers, uint16_t command, is_nitro_packet_type type, uint32_t address, uint8_t* buf, int length, const is_nitro_usb_device* device_desc, bool expect_result = true) {
|
||||
is_nitro_packet_header header;
|
||||
bool append_mode = true;
|
||||
if(device_desc->is_capture)
|
||||
append_mode = false;
|
||||
uint8_t single_usb_packet[USB_PACKET_LIMIT];
|
||||
int single_packet_covered_size = USB_PACKET_LIMIT - sizeof(header);
|
||||
if(!append_mode)
|
||||
single_packet_covered_size = USB_PACKET_LIMIT;
|
||||
int num_iters = (length + single_packet_covered_size - 1) / single_packet_covered_size;
|
||||
if(!num_iters)
|
||||
num_iters = 1;
|
||||
for(int i = 0; i < num_iters; i++) {
|
||||
int transfer_size = length - (i * single_packet_covered_size);
|
||||
if(transfer_size > single_packet_covered_size)
|
||||
transfer_size = single_packet_covered_size;
|
||||
|
||||
uint8_t packet_direction = IS_NITRO_PACKET_EMU_DIR_WRITE;
|
||||
if(device_desc->is_capture)
|
||||
packet_direction = IS_NITRO_PACKET_CAP_DIR_WRITE;
|
||||
|
||||
header.command = command;
|
||||
header.direction = packet_direction;
|
||||
header.type = type;
|
||||
header.address = address;
|
||||
header.length = transfer_size;
|
||||
header.padding = 0;
|
||||
fix_endianness_header(&header);
|
||||
int ret = 0;
|
||||
int num_bytes = 0;
|
||||
for(int j = 0; j < sizeof(is_nitro_packet_header); j++)
|
||||
single_usb_packet[j] = ((uint8_t*)&header)[j];
|
||||
if(append_mode && (buf != NULL)) {
|
||||
for(int j = 0; j < transfer_size; j++)
|
||||
single_usb_packet[sizeof(is_nitro_packet_header) + j] = buf[(i * single_packet_covered_size) + j];
|
||||
ret = bulk_out(handlers, device_desc, single_usb_packet, transfer_size + sizeof(is_nitro_packet_header), &num_bytes);
|
||||
}
|
||||
else {
|
||||
int header_bytes = 0;
|
||||
ret = bulk_out(handlers, device_desc, single_usb_packet, sizeof(is_nitro_packet_header), &header_bytes);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
if(header_bytes != sizeof(is_nitro_packet_header))
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
if((buf != NULL) && (transfer_size > 0))
|
||||
ret = bulk_out(handlers, device_desc, &buf[(i * single_packet_covered_size)], transfer_size, &num_bytes);
|
||||
num_bytes += header_bytes;
|
||||
}
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
if(num_bytes != (transfer_size + sizeof(is_nitro_packet_header)))
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
}
|
||||
if(device_desc->is_capture && expect_result) {
|
||||
uint8_t status[16];
|
||||
int status_bytes = 0;
|
||||
int ret = bulk_in(handlers, device_desc, status, sizeof(status), &status_bytes);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
if(status_bytes != sizeof(status))
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
if(status[0] != 1)
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
}
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
static int SendReadPacket(is_nitro_device_handlers* handlers, uint16_t command, is_nitro_packet_type type, uint32_t address, uint8_t* buf, int length, const is_nitro_usb_device* device_desc, bool expect_result = true) {
|
||||
is_nitro_packet_header header;
|
||||
int single_packet_covered_size = USB_PACKET_LIMIT;
|
||||
int num_iters = (length + single_packet_covered_size - 1) / single_packet_covered_size;
|
||||
if(num_iters == 0)
|
||||
num_iters = 1;
|
||||
for(int i = 0; i < num_iters; i++) {
|
||||
int transfer_size = length - (i * single_packet_covered_size);
|
||||
if(transfer_size > single_packet_covered_size)
|
||||
transfer_size = single_packet_covered_size;
|
||||
|
||||
uint8_t packet_direction = IS_NITRO_PACKET_EMU_DIR_READ;
|
||||
if(device_desc->is_capture)
|
||||
packet_direction = IS_NITRO_PACKET_CAP_DIR_READ;
|
||||
|
||||
header.command = command;
|
||||
header.direction = packet_direction;
|
||||
header.type = type;
|
||||
header.address = address;
|
||||
header.length = transfer_size;
|
||||
header.padding = 0;
|
||||
fix_endianness_header(&header);
|
||||
int num_bytes = 0;
|
||||
int ret = bulk_out(handlers, device_desc, (uint8_t*)&header, sizeof(is_nitro_packet_header), &num_bytes);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
if(num_bytes != sizeof(is_nitro_packet_header))
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
if(buf != NULL) {
|
||||
ret = bulk_in(handlers, device_desc, buf + (i * single_packet_covered_size), transfer_size, &num_bytes);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
if(num_bytes != transfer_size)
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
}
|
||||
}
|
||||
if(device_desc->is_capture && expect_result) {
|
||||
uint8_t status[16];
|
||||
int status_bytes = 0;
|
||||
int ret = bulk_in(handlers, device_desc, status, sizeof(status), &status_bytes);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
if(status_bytes != sizeof(status))
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
if(status[0] != 1)
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
}
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
int SendReadCommand(is_nitro_device_handlers* handlers, uint16_t command, uint8_t* buf, int length, const is_nitro_usb_device* device_desc) {
|
||||
return SendReadPacket(handlers, command, IS_NITRO_PACKET_TYPE_COMMAND, 0, buf, length, device_desc);
|
||||
}
|
||||
|
||||
int SendWriteCommand(is_nitro_device_handlers* handlers, uint16_t command, uint8_t* buf, int length, const is_nitro_usb_device* device_desc) {
|
||||
return SendWritePacket(handlers, command, IS_NITRO_PACKET_TYPE_COMMAND, 0, buf, length, device_desc);
|
||||
}
|
||||
|
||||
int SendReadCommandU32(is_nitro_device_handlers* handlers, uint16_t command, uint32_t* out, const is_nitro_usb_device* device_desc) {
|
||||
uint32_t buffer;
|
||||
int ret = SendReadCommand(handlers, command, (uint8_t*)&buffer, sizeof(uint32_t), device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = from_le(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SendWriteCommandU32(is_nitro_device_handlers* handlers, uint16_t command, uint32_t value, const is_nitro_usb_device* device_desc) {
|
||||
uint32_t buffer = to_le(value);
|
||||
return SendWriteCommand(handlers, command, (uint8_t*)&buffer, sizeof(uint32_t), device_desc);
|
||||
}
|
||||
|
||||
int GetDeviceSerial(is_nitro_device_handlers* handlers, uint8_t* buf, const is_nitro_usb_device* device_desc) {
|
||||
if(device_desc->is_capture)
|
||||
return SendReadCommand(handlers, IS_NITRO_CAP_CMD_GET_SERIAL, buf, IS_NITRO_REAL_SERIAL_NUMBER_SIZE, device_desc);
|
||||
return SendReadCommand(handlers, IS_NITRO_EMU_CMD_GET_SERIAL, buf, IS_NITRO_REAL_SERIAL_NUMBER_SIZE, device_desc);
|
||||
}
|
||||
|
||||
int ReadNecMem(is_nitro_device_handlers* handlers, uint32_t address, uint8_t unit_size, uint8_t* buf, int count, const is_nitro_usb_device* device_desc) {
|
||||
is_nitro_nec_packet_header header;
|
||||
header.command = IS_NITRO_EMU_CMD_SET_READ_NEC_MEM;
|
||||
header.unit_size = unit_size;
|
||||
header.count = count;
|
||||
header.address = address;
|
||||
fix_endianness_header(&header);
|
||||
int ret = SendWriteCommand(handlers, header.command, (uint8_t*)&header, sizeof(is_nitro_nec_packet_header), device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
return SendReadCommand(handlers, IS_NITRO_EMU_CMD_READ_NEC_MEM, buf, count * unit_size, device_desc);
|
||||
}
|
||||
|
||||
int ReadNecMemU16(is_nitro_device_handlers* handlers, uint32_t address, uint16_t* out, const is_nitro_usb_device* device_desc) {
|
||||
uint16_t buffer;
|
||||
int ret = ReadNecMem(handlers, address, 2, (uint8_t*)&buffer, 1, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = from_le(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ReadNecMemU32(is_nitro_device_handlers* handlers, uint32_t address, uint32_t* out, const is_nitro_usb_device* device_desc) {
|
||||
uint32_t buffer;
|
||||
int ret = ReadNecMem(handlers, address, 2, (uint8_t*)&buffer, 2, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = from_le(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WriteNecMem(is_nitro_device_handlers* handlers, uint32_t address, uint8_t unit_size, uint8_t* buf, int count, const is_nitro_usb_device* device_desc) {
|
||||
uint8_t* buffer = new uint8_t[(count * unit_size) + sizeof(is_nitro_nec_packet_header)];
|
||||
is_nitro_nec_packet_header header;
|
||||
header.command = IS_NITRO_EMU_CMD_WRITE_NEC_MEM;
|
||||
header.unit_size = unit_size;
|
||||
header.count = count;
|
||||
header.address = address;
|
||||
fix_endianness_header(&header);
|
||||
for(int i = 0; i < sizeof(is_nitro_nec_packet_header); i++)
|
||||
buffer[i] = ((uint8_t*)&header)[i];
|
||||
for(int i = 0; i < count * unit_size; i++)
|
||||
buffer[i + sizeof(is_nitro_nec_packet_header)] = buf[i];
|
||||
int ret = SendWriteCommand(handlers, header.command, buffer, (count * unit_size) + sizeof(is_nitro_nec_packet_header), device_desc);
|
||||
delete []buffer;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int WriteNecMemU16(is_nitro_device_handlers* handlers, uint32_t address, uint16_t value, const is_nitro_usb_device* device_desc) {
|
||||
uint16_t buffer = to_le(value);
|
||||
return WriteNecMem(handlers, address, 2, (uint8_t*)&buffer, 1, device_desc);
|
||||
}
|
||||
|
||||
int WriteNecMemU32(is_nitro_device_handlers* handlers, uint32_t address, uint32_t value, const is_nitro_usb_device* device_desc) {
|
||||
uint32_t buffer = to_le(value);
|
||||
return WriteNecMem(handlers, address, 2, (uint8_t*)&buffer, 2, device_desc);
|
||||
}
|
||||
|
||||
int DisableLca2(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc) {
|
||||
if(device_desc->is_capture)
|
||||
return LIBUSB_SUCCESS;
|
||||
int ret = WriteNecMemU16(handlers, 0x00805180, 0, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
ret = WriteNecMemU16(handlers, 0x0F84000A, 1, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
//SleepBetweenTransfers(handlers, 2000);
|
||||
return WriteNecMemU16(handlers, 0x0F84000A, 0, device_desc);
|
||||
}
|
||||
|
||||
int StartUsbCaptureDma(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc) {
|
||||
if(!device_desc->is_capture) {
|
||||
int ret = WriteNecMemU16(handlers, REG_USB_DMA_CONTROL_2, 2, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
return WriteNecMemU16(handlers, REG_USB_BIU_CONTROL_2, 1, device_desc);
|
||||
}
|
||||
return SendReadPacket(handlers, IS_NITRO_CAP_CMD_ENABLE_CAP, IS_NITRO_CAPTURE_PACKET_TYPE_DMA_CONTROL, 0, NULL, 1, device_desc, false);
|
||||
}
|
||||
|
||||
int StopUsbCaptureDma(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc) {
|
||||
if(!device_desc->is_capture) {
|
||||
int ret = WriteNecMemU16(handlers, REG_USB_DMA_CONTROL_2, 0, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
return WriteNecMemU16(handlers, REG_USB_BIU_CONTROL_2, 0, device_desc);
|
||||
}
|
||||
return SendReadPacket(handlers, IS_NITRO_CAP_CMD_ENABLE_CAP, IS_NITRO_CAPTURE_PACKET_TYPE_DMA_CONTROL, 0, NULL, 0, device_desc);
|
||||
}
|
||||
|
||||
int SetForwardFrameCount(is_nitro_device_handlers* handlers, uint16_t count, const is_nitro_usb_device* device_desc) {
|
||||
if(!count)
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
count -= 1;
|
||||
if(!device_desc->is_capture)
|
||||
return WriteNecMemU32(handlers, 0x0800000C, (count >> 8) | ((count & 0xFF) << 16), device_desc);
|
||||
return SendWriteCommandU32(handlers, IS_NITRO_CAP_CMD_SET_FWD_FRAMES, count, device_desc);
|
||||
}
|
||||
|
||||
int SetForwardFramePermanent(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc) {
|
||||
return SetForwardFrameCount(handlers, 0x4001, device_desc);
|
||||
}
|
||||
|
||||
int GetFrameCounter(is_nitro_device_handlers* handlers, uint16_t* out, const is_nitro_usb_device* device_desc) {
|
||||
if(device_desc->is_capture) {
|
||||
*out = 0;
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
uint32_t counter = 0;
|
||||
int ret = ReadNecMemU32(handlers, 0x08000028, &counter, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = (counter & 0xFF) | ((counter & 0xFF0000) >> 8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int UpdateFrameForwardConfig(is_nitro_device_handlers* handlers, is_nitro_forward_config_values_colors colors, is_nitro_forward_config_values_screens screens, is_nitro_forward_config_values_rate rate, const is_nitro_usb_device* device_desc) {
|
||||
if(!device_desc->is_capture)
|
||||
return WriteNecMemU16(handlers, 0x0800000A, ((colors & 1) << 4) | ((screens & 3) << 2) | ((rate & 3) << 0), device_desc);
|
||||
int ret = SendWriteCommandU32(handlers, IS_NITRO_CAP_CMD_SET_FWD_RATE, rate & 3, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
ret = SendWriteCommandU32(handlers, IS_NITRO_CAP_CMD_SET_FWD_MODE, screens & 3, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
return SendWriteCommandU32(handlers, IS_NITRO_CAP_CMD_SET_FWD_COLOURS, colors & 1, device_desc);
|
||||
}
|
||||
|
||||
int UpdateFrameForwardEnable(is_nitro_device_handlers* handlers, bool enable, bool restart, const is_nitro_usb_device* device_desc) {
|
||||
uint32_t value = 0;
|
||||
if(!device_desc->is_capture) {
|
||||
if(enable)
|
||||
value |= (1 << IS_NITRO_EMULATOR_FORWARD_ENABLE_BIT);
|
||||
if(restart)
|
||||
value |= (1 << IS_NITRO_EMULATOR_FORWARD_COUNTER_RESTART_BIT);
|
||||
return WriteNecMemU16(handlers, 0x08000008, value, device_desc);
|
||||
}
|
||||
if(restart)
|
||||
value |= (1 << IS_NITRO_CAPTURE_FORWARD_COUNTER_RESTART_BIT);
|
||||
return SendWriteCommandU32(handlers, IS_NITRO_CAP_CMD_SET_FWD_RESTART, value, device_desc);
|
||||
}
|
||||
|
||||
int ReadLidState(is_nitro_device_handlers* handlers, bool* out, const is_nitro_usb_device* device_desc) {
|
||||
uint32_t flags = 0;
|
||||
if(device_desc->is_capture) {
|
||||
int ret = SendReadCommandU32(handlers, IS_NITRO_CAP_CMD_GET_LID_STATE, &flags, device_desc);
|
||||
*out = (flags & 1) ? true : false;
|
||||
return ret;
|
||||
}
|
||||
int ret = ReadNecMemU32(handlers, 0x08000000, &flags, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = (flags & 2) ? true : false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ReadDebugButtonState(is_nitro_device_handlers* handlers, bool* out, const is_nitro_usb_device* device_desc) {
|
||||
uint32_t flags = 0;
|
||||
if(device_desc->is_capture) {
|
||||
int ret = SendReadCommandU32(handlers, IS_NITRO_CAP_CMD_GET_DEBUG_STATE, &flags, device_desc);
|
||||
*out = (flags & 1) ? true : false;
|
||||
return ret;
|
||||
}
|
||||
int ret = ReadNecMemU32(handlers, 0x08000000, &flags, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = (flags & 1) ? true : false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ReadPowerButtonState(is_nitro_device_handlers* handlers, bool* out, const is_nitro_usb_device* device_desc) {
|
||||
return ReadDebugButtonState(handlers, out, device_desc);
|
||||
}
|
||||
|
||||
static int ResetCPUEmulatorGeneral(is_nitro_device_handlers* handlers, bool on, const is_nitro_usb_device* device_desc) {
|
||||
uint8_t data[] = {IS_NITRO_EMU_CMD_CPU_RESET, 0, (uint8_t)(on ? 1 : 0), 0};
|
||||
return SendWriteCommand(handlers, IS_NITRO_EMU_CMD_CPU_RESET, data, sizeof(data), device_desc);
|
||||
}
|
||||
|
||||
int ResetCPUStart(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc) {
|
||||
if(device_desc->is_capture)
|
||||
return SendWriteCommand(handlers, IS_NITRO_CAP_CMD_SET_RESET_CPU_ON, NULL, 0, device_desc);
|
||||
return ResetCPUEmulatorGeneral(handlers, true, device_desc);
|
||||
}
|
||||
|
||||
int ResetCPUEnd(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc) {
|
||||
if(device_desc->is_capture)
|
||||
return SendWriteCommand(handlers, IS_NITRO_CAP_CMD_SET_RESET_CPU_OFF, NULL, 0, device_desc);
|
||||
return ResetCPUEmulatorGeneral(handlers, false, device_desc);
|
||||
}
|
||||
|
||||
int ResetFullHardware(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc) {
|
||||
if(device_desc->is_capture)
|
||||
return SendWriteCommand(handlers, IS_NITRO_CAP_CMD_SET_RESTART_FULL, NULL, 0, device_desc);
|
||||
uint8_t data[] = {IS_NITRO_EMU_CMD_FULL_HARDWARE_RESET, 0xF2};
|
||||
return SendWriteCommand(handlers, IS_NITRO_EMU_CMD_FULL_HARDWARE_RESET, data, sizeof(data), device_desc);
|
||||
}
|
||||
|
||||
int ReadFrame(is_nitro_device_handlers* handlers, uint8_t* buf, int length, const is_nitro_usb_device* device_desc) {
|
||||
// Maybe making this async would be better for lower end hardware...
|
||||
int num_bytes = 0;
|
||||
int ret = bulk_in(handlers, device_desc, buf, length, &num_bytes);
|
||||
if(num_bytes != length)
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ReadFrameAsync(is_nitro_device_handlers* handlers, uint8_t* buf, int length, const is_nitro_usb_device* device_desc, isn_async_callback_data* cb_data) {
|
||||
return bulk_in_async(handlers, device_desc, buf, length, cb_data);
|
||||
}
|
||||
|
||||
void CloseAsyncRead(is_nitro_device_handlers* handlers, isn_async_callback_data* cb_data) {
|
||||
if(handlers->usb_handle)
|
||||
return is_nitro_libusb_cancell_callback(cb_data);
|
||||
return is_nitro_is_driver_cancel_callback(cb_data);
|
||||
}
|
||||
|
||||
void SetupISNitroAsyncThread(is_nitro_device_handlers* handlers, void* user_data, std::thread* thread_ptr, bool* keep_going, ConsumerMutex* is_data_ready) {
|
||||
if(handlers->usb_handle)
|
||||
return is_nitro_libusb_start_thread(thread_ptr, keep_going);
|
||||
return is_nitro_is_driver_start_thread(thread_ptr, keep_going, (ISNitroCaptureReceivedData*)user_data, handlers, is_data_ready);
|
||||
}
|
||||
|
||||
void EndISNitroAsyncThread(is_nitro_device_handlers* handlers, void* user_data, std::thread* thread_ptr, bool* keep_going, ConsumerMutex* is_data_ready) {
|
||||
if(handlers->usb_handle)
|
||||
return is_nitro_libusb_close_thread(thread_ptr, keep_going);
|
||||
return is_nitro_is_driver_close_thread(thread_ptr, keep_going, (ISNitroCaptureReceivedData*)user_data);
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#include "ISNitroMenu.hpp"
|
||||
#include "usb_is_nitro_acquisition.hpp"
|
||||
#include "usb_is_device_acquisition.hpp"
|
||||
|
||||
#define NUM_TOTAL_MENU_OPTIONS (sizeof(pollable_options)/sizeof(pollable_options[0]))
|
||||
|
||||
|
|
@ -75,8 +75,8 @@ void ISNitroMenu::class_setup() {
|
|||
|
||||
void ISNitroMenu::insert_data(CaptureDevice* device) {
|
||||
bool is_capture = false;
|
||||
#ifdef USE_IS_NITRO_USB
|
||||
is_capture = is_nitro_is_capture(device);
|
||||
#ifdef USE_IS_DEVICES_USB
|
||||
is_capture = is_device_is_capture(device);
|
||||
#endif
|
||||
this->num_enabled_options = 0;
|
||||
for(int i = 0; i < NUM_TOTAL_MENU_OPTIONS; i++) {
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ static const LicenseMenuOptionInfo* pollable_options[] = {
|
|||
&libusb_license_3_option,
|
||||
&libusb_license_4_option,
|
||||
#endif
|
||||
#if defined(USE_IS_NITRO_USB)
|
||||
#if defined(USE_IS_DEVICES_USB)
|
||||
&isng_license_0_option,
|
||||
&isng_license_1_option,
|
||||
&isng_license_2_option,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
#include "3dscapture_ftd3.hpp"
|
||||
#include "dscapture_ftd2_shared.hpp"
|
||||
#include "usb_ds_3ds_capture.hpp"
|
||||
#include "usb_is_nitro_acquisition.hpp"
|
||||
#include "usb_is_device_acquisition.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
|
@ -171,8 +171,8 @@ static void usb_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_o
|
|||
usb_oldDSconvertVideoToOutput(&p_in->usb_received_old_ds, p_out, is_big_endian);
|
||||
}
|
||||
|
||||
static void usb_is_nitro_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, CaptureScreensType capture_type) {
|
||||
int num_pixels = usb_is_nitro_get_video_in_size(capture_type) / 3;
|
||||
static void usb_is_device_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, CaptureStatus* status, CaptureScreensType capture_type) {
|
||||
int num_pixels = usb_is_device_get_video_in_size(status) / 3;
|
||||
int out_start_pos = 0;
|
||||
int out_clear_pos = num_pixels;
|
||||
if(capture_type == CAPTURE_SCREENS_BOTTOM) {
|
||||
|
|
@ -206,9 +206,9 @@ bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, Capt
|
|||
converted = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_IS_NITRO_USB
|
||||
#ifdef USE_IS_DEVICES_USB
|
||||
if(chosen_device->cc_type == CAPTURE_CONN_IS_NITRO) {
|
||||
usb_is_nitro_convertVideoToOutput(p_in, p_out, data_buffer->capture_type);
|
||||
usb_is_device_convertVideoToOutput(p_in, p_out, status, data_buffer->capture_type);
|
||||
converted = true;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#include "3dscapture_ftd3.hpp"
|
||||
#include "dscapture_ftd2_shared.hpp"
|
||||
#include "usb_ds_3ds_capture.hpp"
|
||||
#include "usb_is_nitro_acquisition.hpp"
|
||||
#include "usb_is_device_acquisition.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
|
|
@ -85,8 +85,8 @@ bool connect(bool print_failed, CaptureData* capture_data, FrontendData* fronten
|
|||
#ifdef USE_DS_3DS_USB
|
||||
list_devices_usb_ds_3ds(devices_list, no_access_list);
|
||||
#endif
|
||||
#ifdef USE_IS_NITRO_USB
|
||||
list_devices_is_nitro(devices_list, no_access_list);
|
||||
#ifdef USE_IS_DEVICES_USB
|
||||
list_devices_is_device(devices_list, no_access_list);
|
||||
#endif
|
||||
|
||||
if(devices_list.size() <= 0) {
|
||||
|
|
@ -125,8 +125,8 @@ bool connect(bool print_failed, CaptureData* capture_data, FrontendData* fronten
|
|||
if((devices_list[chosen_device].cc_type == CAPTURE_CONN_USB) && (!connect_usb(print_failed, capture_data, &devices_list[chosen_device])))
|
||||
return false;
|
||||
#endif
|
||||
#ifdef USE_IS_NITRO_USB
|
||||
if((devices_list[chosen_device].cc_type == CAPTURE_CONN_IS_NITRO) && (!is_nitro_connect_usb(print_failed, capture_data, &devices_list[chosen_device])))
|
||||
#ifdef USE_IS_DEVICES_USB
|
||||
if((devices_list[chosen_device].cc_type == CAPTURE_CONN_IS_NITRO) && (!is_device_connect_usb(print_failed, capture_data, &devices_list[chosen_device])))
|
||||
return false;
|
||||
#endif
|
||||
update_connected_3ds_ds(frontend_data, capture_data->status.device, devices_list[chosen_device]);
|
||||
|
|
@ -161,9 +161,9 @@ void captureCall(CaptureData* capture_data) {
|
|||
if(capture_data->status.device.cc_type == CAPTURE_CONN_USB)
|
||||
usb_capture_main_loop(capture_data);
|
||||
#endif
|
||||
#ifdef USE_IS_NITRO_USB
|
||||
#ifdef USE_IS_DEVICES_USB
|
||||
if(capture_data->status.device.cc_type == CAPTURE_CONN_IS_NITRO)
|
||||
is_nitro_acquisition_main_loop(capture_data);
|
||||
is_device_acquisition_main_loop(capture_data);
|
||||
#endif
|
||||
|
||||
capture_data->status.close_success = false;
|
||||
|
|
@ -187,9 +187,9 @@ void captureCall(CaptureData* capture_data) {
|
|||
if(capture_data->status.device.cc_type == CAPTURE_CONN_USB)
|
||||
usb_capture_cleanup(capture_data);
|
||||
#endif
|
||||
#ifdef USE_IS_NITRO_USB
|
||||
#ifdef USE_IS_DEVICES_USB
|
||||
if(capture_data->status.device.cc_type == CAPTURE_CONN_IS_NITRO)
|
||||
usb_is_nitro_acquisition_cleanup(capture_data);
|
||||
usb_is_device_acquisition_cleanup(capture_data);
|
||||
#endif
|
||||
|
||||
capture_data->status.close_success = false;
|
||||
|
|
@ -224,9 +224,9 @@ uint64_t get_video_in_size(CaptureData* capture_data) {
|
|||
if(capture_data->status.device.cc_type == CAPTURE_CONN_USB)
|
||||
return usb_get_video_in_size(capture_data);
|
||||
#endif
|
||||
#ifdef USE_IS_NITRO_USB
|
||||
#ifdef USE_IS_DEVICES_USB
|
||||
if(capture_data->status.device.cc_type == CAPTURE_CONN_IS_NITRO)
|
||||
return usb_is_nitro_get_video_in_size(capture_data);
|
||||
return usb_is_device_get_video_in_size(capture_data);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -243,8 +243,8 @@ void capture_init() {
|
|||
#ifdef USE_DS_3DS_USB
|
||||
usb_ds_3ds_init();
|
||||
#endif
|
||||
#ifdef USE_IS_NITRO_USB
|
||||
usb_is_nitro_init();
|
||||
#ifdef USE_IS_DEVICES_USB
|
||||
usb_is_device_init();
|
||||
#endif
|
||||
#ifdef USE_FTD2
|
||||
ftd2_init_shared();
|
||||
|
|
@ -255,8 +255,8 @@ void capture_close() {
|
|||
#ifdef USE_DS_3DS_USB
|
||||
usb_ds_3ds_close();
|
||||
#endif
|
||||
#ifdef USE_IS_NITRO_USB
|
||||
usb_is_nitro_close();
|
||||
#ifdef USE_IS_DEVICES_USB
|
||||
usb_is_device_close();
|
||||
#endif
|
||||
#ifdef USE_FTD2
|
||||
ftd2_end_shared();
|
||||
|
|
|
|||
2
usb_rules/51-isagb.rules
Normal file
2
usb_rules/51-isagb.rules
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0f6e", ATTRS{idProduct}=="0201", MODE="0666"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0f6e", ATTRS{idProduct}=="0202", MODE="0666"
|
||||
1
usb_rules/51-iscgb.rules
Normal file
1
usb_rules/51-iscgb.rules
Normal file
|
|
@ -0,0 +1 @@
|
|||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0f6e", ATTRS{idProduct}=="0100", MODE="0666"
|
||||
2
usb_rules/51-istwl.rules
Normal file
2
usb_rules/51-istwl.rules
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0f6e", ATTRS{idProduct}=="0500", MODE="0666"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0f6e", ATTRS{idProduct}=="0501", MODE="0666"
|
||||
Loading…
Reference in New Issue
Block a user