mirror of
https://github.com/Lorenzooone/cc3dsfs.git
synced 2026-07-18 16:43:28 -05:00
Proper IS TWL Capture initialization
This commit is contained in:
parent
4bd8a189fb
commit
b9cd5ceca0
|
|
@ -313,7 +313,7 @@ if(USE_LIBUSB_SUPPORT)
|
|||
endif()
|
||||
endif()
|
||||
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_twl_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 ${TOOLS_DATA_DIR}/is_twl_0x81_packet.cpp)
|
||||
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_twl_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 ${TOOLS_DATA_DIR}/is_twl_cap_crc32_table.cpp ${TOOLS_DATA_DIR}/is_twl_cap_init_seed_table.cpp)
|
||||
if(MSVC)
|
||||
list(APPEND EXTRA_CXX_FLAGS "/DUSE_IS_DEVICES_USB")
|
||||
else()
|
||||
|
|
@ -517,10 +517,17 @@ add_custom_command(
|
|||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${TOOLS_DATA_DIR}/is_twl_0x81_packet.cpp
|
||||
COMMENT "Convert binary to C - IS TWL Capture 0x81 Packet"
|
||||
COMMAND ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/bin/is_twl_0x81_packet.bin ${TOOLS_DATA_DIR} is_twl_0x81_packet is_twl_0x81_packet
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/bin/is_twl_0x81_packet.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION}
|
||||
OUTPUT ${TOOLS_DATA_DIR}/is_twl_cap_crc32_table.cpp
|
||||
COMMENT "Convert binary to C - IS TWL CRC32 table"
|
||||
COMMAND ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/bin/is_twl_cap_crc32_table.bin ${TOOLS_DATA_DIR} is_twl_cap_crc32_table is_twl_cap_crc32_table
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/bin/is_twl_cap_crc32_table.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION}
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${TOOLS_DATA_DIR}/is_twl_cap_init_seed_table.cpp
|
||||
COMMENT "Convert binary to C - IS TWL CRC32 table"
|
||||
COMMAND ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/bin/is_twl_cap_init_seed_table.bin ${TOOLS_DATA_DIR} is_twl_cap_init_seed_table is_twl_cap_init_seed_table
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/bin/is_twl_cap_init_seed_table.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION}
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@ sudo apt install \
|
|||
libegl1-mesa-dev \
|
||||
libdrm-dev \
|
||||
libgbm-dev \
|
||||
libfreetype-dev
|
||||
libfreetype-dev \
|
||||
xorg-dev
|
||||
```
|
||||
|
||||
Additionally, when compiling for a Raspberry Pi, install gpiod and libgpiod-dev.
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
›"’R¤ŠÅJV1åiTÁE•ªè<C2AA>$‹°bÄÌÍÔ.§÷î‡L7mçªf€Ö«rVÄöå&65™'Eö´¥eYºôð@»´BØ<dý<64>>»x?óþ£¼;}Ûº‚àÒ»:sš$ò1¹x<C2B9>Ga÷Ý´¹…]©ðð\˸c@
œ!?H_Oÿï_Œ?mÞ©~À+>žþåѽHѧ}—ÙÂAeYòÓH<O_Nø÷‚
|
||||
BIN
bin/is_twl_cap_crc32_table.bin
Normal file
BIN
bin/is_twl_cap_crc32_table.bin
Normal file
Binary file not shown.
BIN
bin/is_twl_cap_init_seed_table.bin
Normal file
BIN
bin/is_twl_cap_init_seed_table.bin
Normal file
Binary file not shown.
|
|
@ -78,13 +78,23 @@ struct is_device_device_handlers {
|
|||
libusb_device_handle* usb_handle;
|
||||
void* read_handle;
|
||||
void* write_handle;
|
||||
void* ctrl_in_handle;
|
||||
void* mutex;
|
||||
std::string path;
|
||||
};
|
||||
|
||||
struct is_device_twl_enc_dec_table {
|
||||
uint32_t rotating_value;
|
||||
uint8_t num_values;
|
||||
uint8_t num_iters_full;
|
||||
uint8_t num_iters_before_refresh;
|
||||
uint16_t action_values[8];
|
||||
};
|
||||
|
||||
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 StartUsbCaptureDma(is_device_device_handlers* handlers, const is_device_usb_device* device_desc, bool enable_sound_capture = false, is_device_twl_enc_dec_table* enc_table = NULL, is_device_twl_enc_dec_table* dec_table = NULL);
|
||||
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);
|
||||
|
|
@ -105,6 +115,7 @@ int ReadFrame(is_device_device_handlers* handlers, uint8_t* buf, int length, con
|
|||
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);
|
||||
int PrepareEncDecTable(is_device_device_handlers* handlers, is_device_twl_enc_dec_table* enc_table, is_device_twl_enc_dec_table* dec_table, const is_device_usb_device* device_desc);
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -10,8 +10,11 @@
|
|||
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);
|
||||
bool is_driver_prepare_ctrl_in_handle(is_device_device_handlers* handlers);
|
||||
void is_driver_close_ctrl_in_handle(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_driver_ctrl_in(is_device_device_handlers* handlers, uint8_t* buf, int length, uint8_t request, uint16_t index, 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);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ is_device_device_handlers* is_device_libusb_serial_reconnection(const is_device_
|
|||
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);
|
||||
int is_device_libusb_ctrl_in(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t* buf, int length, uint8_t request, uint16_t index, 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);
|
||||
|
|
|
|||
|
|
@ -122,12 +122,20 @@ struct ALIGNED(16) PACKED ISTWLCaptureVideoReceived {
|
|||
ISTWLCaptureVideoInputData video_in;
|
||||
uint32_t time;
|
||||
uint32_t frame;
|
||||
uint8_t unknown[0x40000 - (sizeof(ISTWLCaptureVideoInputData) + (sizeof(uint32_t) * 2))];
|
||||
};
|
||||
|
||||
struct ALIGNED(16) PACKED ISTWLCaptureAudioReceived {
|
||||
struct ALIGNED(16) PACKED ISTWLCaptureVideoInternalReceived {
|
||||
ISTWLCaptureVideoReceived real_video_in;
|
||||
uint8_t unknown[0x40000 - sizeof(ISTWLCaptureVideoReceived)];
|
||||
};
|
||||
|
||||
struct ALIGNED(4) PACKED ISTWLCaptureSoundData {
|
||||
uint16_t data[TWL_CAPTURE_SAMPLES_IN];
|
||||
};
|
||||
|
||||
struct ALIGNED(4) PACKED ISTWLCaptureAudioReceived {
|
||||
uint32_t time;
|
||||
uint16_t sound_data[TWL_CAPTURE_SAMPLES_IN];
|
||||
ISTWLCaptureSoundData sound_data;
|
||||
};
|
||||
|
||||
struct ALIGNED(16) PACKED ISTWLCaptureReceived {
|
||||
|
|
|
|||
|
|
@ -32,15 +32,31 @@ std::string get_version_string(bool get_letter = true);
|
|||
std::string LayoutNameGenerator(int index);
|
||||
std::string LayoutPathGenerator(int index, bool created_proper_folder);
|
||||
std::string load_layout_name(int index, bool created_proper_folder, bool &success);
|
||||
uint32_t reverse_endianness(uint32_t value);
|
||||
uint16_t reverse_endianness(uint16_t value);
|
||||
bool is_big_endian(void);
|
||||
uint32_t to_le(uint32_t value);
|
||||
uint32_t to_be(uint32_t value);
|
||||
uint16_t to_le(uint16_t value);
|
||||
uint32_t to_be(uint32_t value);
|
||||
uint16_t to_be(uint16_t value);
|
||||
uint32_t from_le(uint32_t value);
|
||||
uint32_t from_be(uint32_t value);
|
||||
uint16_t from_le(uint16_t value);
|
||||
uint32_t from_be(uint32_t value);
|
||||
uint16_t from_be(uint16_t value);
|
||||
uint16_t read_le16(const uint8_t* data, size_t count = 0, size_t multiplier = sizeof(uint16_t));
|
||||
uint16_t read_be16(const uint8_t* data, size_t count = 0, size_t multiplier = sizeof(uint16_t));
|
||||
uint32_t read_le32(const uint8_t* data, size_t count = 0, size_t multiplier = sizeof(uint32_t));
|
||||
uint32_t read_be32(const uint8_t* data, size_t count = 0, size_t multiplier = sizeof(uint32_t));
|
||||
void write_le16(uint8_t* data, uint16_t value, size_t count = 0, size_t multiplier = sizeof(uint16_t));
|
||||
void write_be16(uint8_t* data, uint16_t value, size_t count = 0, size_t multiplier = sizeof(uint16_t));
|
||||
void write_le32(uint8_t* data, uint32_t value, size_t count = 0, size_t multiplier = sizeof(uint32_t));
|
||||
void write_be32(uint8_t* data, uint32_t value, size_t count = 0, size_t multiplier = sizeof(uint32_t));
|
||||
void write_string(uint8_t* data, std::string text);
|
||||
std::string read_string(uint8_t* data, size_t size);
|
||||
uint32_t rotate_bits_left(uint32_t value);
|
||||
uint32_t rotate_bits_right(uint32_t value);
|
||||
void init_start_time();
|
||||
uint32_t ms_since_start();
|
||||
std::string to_hex(uint16_t value);
|
||||
std::string get_float_str_decimals(float value, int decimals);
|
||||
void init_threads(void);
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ bool is_device_connect_usb(bool print_failed, CaptureData* capture_data, Capture
|
|||
|
||||
uint64_t usb_is_device_get_video_in_size(CaptureScreensType capture_type, is_device_type device_type) {
|
||||
if(device_type == IS_TWL_CAPTURE_DEVICE)
|
||||
return sizeof(ISTWLCaptureVideoInputData) + (sizeof(uint32_t) * 2);
|
||||
return sizeof(ISTWLCaptureVideoReceived);
|
||||
if((capture_type == CAPTURE_SCREENS_TOP) || (capture_type == CAPTURE_SCREENS_BOTTOM))
|
||||
return sizeof(ISNitroEmulatorVideoInputData) / 2;
|
||||
return sizeof(ISNitroEmulatorVideoInputData);
|
||||
|
|
@ -216,7 +216,21 @@ void output_to_thread(CaptureData* capture_data, CaptureReceived* capture_buf, C
|
|||
const auto curr_time = std::chrono::high_resolution_clock::now();
|
||||
const std::chrono::duration<double> diff = curr_time - (*clock_start);
|
||||
*clock_start = curr_time;
|
||||
capture_data->data_buffers.WriteToBuffer(capture_buf, read_size, diff.count(), &capture_data->status.device, curr_capture_type);
|
||||
if(usb_device_info->device_type == IS_TWL_CAPTURE_DEVICE) {
|
||||
CaptureDataSingleBuffer* target = capture_data->data_buffers.GetWriterBuffer();
|
||||
// Copy data to buffer, with special memcpy which accounts for ftd2 header data and skips synch bytes
|
||||
size_t video_size = usb_is_device_get_video_in_size(curr_capture_type, usb_device_info->device_type);
|
||||
memcpy(&target->capture_buf.is_twl_capture_received.video_capture_in, &capture_buf->is_twl_capture_received.video_capture_in, video_size);
|
||||
if(read_size > video_size) {
|
||||
size_t audio_size = ((read_size - video_size) / sizeof(ISTWLCaptureSoundData)) * sizeof(ISTWLCaptureAudioReceived);
|
||||
memcpy(&target->capture_buf.is_twl_capture_received.audio_capture_in, &capture_buf->is_twl_capture_received.audio_capture_in, audio_size);
|
||||
}
|
||||
target->read = read_size;
|
||||
target->time_in_buf = diff.count();
|
||||
capture_data->data_buffers.ReleaseWriterBuffer();
|
||||
}
|
||||
else
|
||||
capture_data->data_buffers.WriteToBuffer(capture_buf, read_size, diff.count(), &capture_data->status.device, curr_capture_type);
|
||||
|
||||
if (capture_data->status.cooldown_curr_in)
|
||||
capture_data->status.cooldown_curr_in = capture_data->status.cooldown_curr_in - 1;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
#include "usb_is_device_communications.hpp"
|
||||
#include "usb_is_device_libusb.hpp"
|
||||
#include "usb_is_device_is_driver.hpp"
|
||||
#include "is_twl_0x81_packet.h"
|
||||
#include "is_twl_cap_init_seed_table.h"
|
||||
#include "is_twl_cap_crc32_table.h"
|
||||
|
||||
#include <libusb.h>
|
||||
#include <cstring>
|
||||
|
|
@ -37,8 +38,8 @@
|
|||
#define REG_USB_DMA_CONTROL_2 0x0C000028
|
||||
#define REG_USB_BIU_CONTROL_2 0x0C0000A4
|
||||
|
||||
#define DEFAULT_MAX_LENGTH_IS_TWL_VIDEO 0x00040000
|
||||
#define DEFAULT_MAX_LENGTH_IS_TWL_AUDIO 0x00007800
|
||||
#define DEFAULT_MAX_LENGTH_IS_TWL_VIDEO (5 * sizeof(ISTWLCaptureVideoInternalReceived))
|
||||
#define DEFAULT_MAX_LENGTH_IS_TWL_AUDIO (5 * 5 * sizeof(ISTWLCaptureAudioReceived))
|
||||
|
||||
enum is_nitro_packet_emulator_dir {
|
||||
IS_NITRO_PACKET_EMU_DIR_WRITE = 0x10,
|
||||
|
|
@ -94,16 +95,18 @@ enum is_nitro_capture_command {
|
|||
|
||||
enum is_twl_capture_command {
|
||||
IS_TWL_CAP_CMD_GET_CAP = 0x00,
|
||||
IS_TWL_CAP_CMD_GET_ENC_DEC_SEEDS = 0x04,
|
||||
IS_TWL_CAP_CMD_GET_SERIAL = 0x13,
|
||||
IS_TWL_CAP_CMD_UNLOCK_COMMS = 0x1C,
|
||||
IS_TWL_CAP_CMD_ENABLE_CAP_PRE_3 = 0x80,
|
||||
IS_TWL_CAP_CMD_ENABLE_CAP_PRE_1 = 0x81,
|
||||
IS_TWL_CAP_CMD_MNTR = 0x81,
|
||||
IS_TWL_CAP_CMD_ASK_CAPTURE_INFORMATION = 0x83,
|
||||
IS_TWL_CAP_CMD_ENABLE_CAP = 0x84,
|
||||
IS_TWL_CAP_CMD_ENABLE_CAP_PRE_2 = 0x85,
|
||||
IS_TWL_CAP_CMD_SCTG = 0x84,
|
||||
IS_TWL_CAP_CMD_TCZC = 0x85,
|
||||
IS_TWL_CAP_CMD_STOP_FRAME_READS = 0x88,
|
||||
IS_TWL_CAP_CMD_SET_LAST_FRAME_INFORMATION = 0x8B,
|
||||
IS_TWL_CAP_CMD_ENABLE_CAP_PART_2 = 0x8C,
|
||||
IS_TWL_CAP_CMD_ACTS = 0x8C,
|
||||
IS_TWL_CAP_CMD_EPAC = 0x92,
|
||||
IS_TWL_CAP_CMD_POST_EPAC = 0x93,
|
||||
};
|
||||
|
||||
enum is_nitro_emulator_forward_bits {
|
||||
|
|
@ -207,7 +210,7 @@ static const is_device_usb_device usb_is_twl_cap_desc = {
|
|||
.write_pipe = "Pipe01", .read_pipe = "Pipe03",
|
||||
.product_id = 2, .manufacturer_id = 1, .device_type = IS_TWL_CAPTURE_DEVICE,
|
||||
.video_data_type = VIDEO_DATA_RGB, .max_usb_packet_size = IS_TWL_USB_PACKET_LIMIT,
|
||||
.do_pipe_clear_reset = false, .audio_enabled = true, .max_audio_samples_size = sizeof(ISTWLCaptureAudioReceived) * TWL_CAPTURE_MAX_SAMPLES_CHUNK_NUM
|
||||
.do_pipe_clear_reset = false, .audio_enabled = true, .max_audio_samples_size = sizeof(ISTWLCaptureSoundData) * TWL_CAPTURE_MAX_SAMPLES_CHUNK_NUM
|
||||
};
|
||||
|
||||
static const is_device_usb_device usb_is_twl_cap_desc_2 = {
|
||||
|
|
@ -219,7 +222,7 @@ static const is_device_usb_device usb_is_twl_cap_desc_2 = {
|
|||
.write_pipe = "Pipe01", .read_pipe = "Pipe03",
|
||||
.product_id = 2, .manufacturer_id = 1, .device_type = IS_TWL_CAPTURE_DEVICE,
|
||||
.video_data_type = VIDEO_DATA_RGB, .max_usb_packet_size = IS_TWL_USB_PACKET_LIMIT,
|
||||
.do_pipe_clear_reset = false, .audio_enabled = true, .max_audio_samples_size = sizeof(ISTWLCaptureAudioReceived) * TWL_CAPTURE_MAX_SAMPLES_CHUNK_NUM
|
||||
.do_pipe_clear_reset = false, .audio_enabled = true, .max_audio_samples_size = sizeof(ISTWLCaptureSoundData) * TWL_CAPTURE_MAX_SAMPLES_CHUNK_NUM
|
||||
};
|
||||
|
||||
static const is_device_usb_device* all_usb_is_device_devices_desc[] = {
|
||||
|
|
@ -258,6 +261,113 @@ static void fix_endianness_header(is_nitro_nec_packet_header* header) {
|
|||
header->address = to_le(header->address);
|
||||
}
|
||||
|
||||
static uint32_t get_crc32_data_comm(uint8_t* data, size_t size) {
|
||||
uint32_t value = 0xFFFFFFFF;
|
||||
for(int i = 0; i < size; i++) {
|
||||
uint8_t inner_value = (value >> 24) ^ data[i];
|
||||
value <<= 8;
|
||||
value ^= read_le32(is_twl_cap_crc32_table, inner_value);
|
||||
}
|
||||
return ~value;
|
||||
}
|
||||
|
||||
static void apply_enc_dec_action_value(uint32_t action_value, uint32_t rotating_value, uint8_t* data, size_t size_u16) {
|
||||
int increment = 0;
|
||||
bool is_rot_odd = (rotating_value & 1) == 1;
|
||||
uint16_t first_val = 0;
|
||||
uint16_t last_val = 0;
|
||||
if((action_value & 0xF000) == 0x1000) {
|
||||
if(is_rot_odd)
|
||||
increment = 0xFFFF6494;
|
||||
increment += 0xA597;
|
||||
}
|
||||
else if((action_value & 0xF000) == 0x2000) {
|
||||
if(is_rot_odd)
|
||||
increment = 0x9B6C;
|
||||
increment += 0x5A69;
|
||||
}
|
||||
switch((action_value & 0xFF) - 1) {
|
||||
case 0:
|
||||
for(int j = 0; j < size_u16; j++)
|
||||
write_be16(data, read_le16(data, j), j);
|
||||
break;
|
||||
case 1:
|
||||
for(int j = 0; j < size_u16; j++) {
|
||||
write_le16(data, read_le16(data, j) ^ rotating_value, j);
|
||||
rotating_value += increment;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for(int j = 0; j < size_u16; j++) {
|
||||
write_le16(data, read_le16(data, j) + rotating_value, j);
|
||||
rotating_value += increment;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
for(int j = 0; j < size_u16; j++) {
|
||||
write_le16(data, read_le16(data, j) - rotating_value, j);
|
||||
rotating_value += increment;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for(int j = 0; j < (size_u16 / 2); j++) {
|
||||
first_val = read_le16(data, j);
|
||||
write_le16(data, read_le16(data, size_u16 - 1 - j), j);
|
||||
write_le16(data, first_val, size_u16 - 1 - j);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
first_val = read_le16(data);
|
||||
for(int j = 0; j < (size_u16 - 1); j++)
|
||||
write_le16(data, read_le16(data, j + 1), j);
|
||||
write_le16(data, first_val, size_u16 - 1);
|
||||
break;
|
||||
case 6:
|
||||
last_val = read_le16(data, size_u16 - 1);
|
||||
for(int j = 0; j < (size_u16 - 1); j++)
|
||||
write_le16(data, read_le16(data, size_u16 - 1 - j - 1), size_u16 - 1 - j);
|
||||
write_le16(data, last_val);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void enc_dec_table_add_usage(is_device_twl_enc_dec_table* table) {
|
||||
table->rotating_value = rotate_bits_right(table->rotating_value);
|
||||
table->num_iters_before_refresh -= 1;
|
||||
if(table->num_iters_before_refresh > 0)
|
||||
return;
|
||||
table->num_iters_before_refresh = table->num_iters_full;
|
||||
uint16_t base_table_value = table->action_values[0];
|
||||
for(int i = 0; i < table->num_values - 1; i++)
|
||||
table->action_values[i] = table->action_values[i + 1];
|
||||
table->action_values[table->num_values - 1] = base_table_value;
|
||||
}
|
||||
|
||||
static void table_print(uint8_t* data, size_t size) {
|
||||
/*
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
printf("%02x ", data[i]);
|
||||
if((i % 0x10) == 0xF)
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
*/
|
||||
}
|
||||
|
||||
static void enc_dec_table_apply_to_data(is_device_twl_enc_dec_table* table, uint8_t* data, size_t size, bool is_enc) {
|
||||
table_print(data, size);
|
||||
for(int i = 0; i < table->num_values; i++) {
|
||||
int action_value = table->action_values[i];
|
||||
if(!is_enc)
|
||||
action_value = table->action_values[table->num_values - 1 - i];
|
||||
apply_enc_dec_action_value(action_value, table->rotating_value, data, size / 2);
|
||||
table_print(data, size);
|
||||
}
|
||||
enc_dec_table_add_usage(table);
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
|
@ -272,6 +382,13 @@ static int bulk_in(is_device_device_handlers* handlers, const is_device_usb_devi
|
|||
return is_driver_bulk_in(handlers, usb_device_desc, buf, length, transferred);
|
||||
}
|
||||
|
||||
// Read from ctrl endpoint. Returns libusb error code
|
||||
static int ctrl_in(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t *buf, int length, uint8_t request, uint16_t index, int *transferred) {
|
||||
if(handlers->usb_handle)
|
||||
return is_device_libusb_ctrl_in(handlers, usb_device_desc, buf, length, request, index, transferred);
|
||||
return is_driver_ctrl_in(handlers, buf, length, request, index, 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)
|
||||
|
|
@ -279,6 +396,20 @@ static void bulk_in_async(is_device_device_handlers* handlers, const is_device_u
|
|||
is_drive_async_in_start(handlers, usb_device_desc, buf, length, cb_data);
|
||||
}
|
||||
|
||||
// Prepare ctrl_in pipe, if needed...
|
||||
static bool prepare_ctrl_in(is_device_device_handlers* handlers) {
|
||||
if(handlers->usb_handle)
|
||||
return true;
|
||||
return is_driver_prepare_ctrl_in_handle(handlers);
|
||||
}
|
||||
|
||||
// Close ctrl_in pipe, if needed...
|
||||
static void close_ctrl_in(is_device_device_handlers* handlers) {
|
||||
if(handlers->usb_handle)
|
||||
return;
|
||||
is_driver_close_ctrl_in_handle(handlers);
|
||||
}
|
||||
|
||||
static int return_and_delete(uint8_t* ptr, int value) {
|
||||
delete []ptr;
|
||||
return value;
|
||||
|
|
@ -562,6 +693,39 @@ int SendWriteCommandU32(is_device_device_handlers* handlers, uint16_t command, u
|
|||
return SendWriteCommand(handlers, command, (uint8_t*)&buffer, sizeof(uint32_t), device_desc);
|
||||
}
|
||||
|
||||
static int AuthCtrlIn(is_device_device_handlers* handlers, const is_device_usb_device* device_desc) {
|
||||
int ret = 0;
|
||||
bool b_ret = true;
|
||||
int num_bytes = 0;
|
||||
uint8_t buffer[2];
|
||||
uint16_t auth_val = 0;
|
||||
switch(device_desc->device_type) {
|
||||
case IS_TWL_CAPTURE_DEVICE:
|
||||
b_ret = prepare_ctrl_in(handlers);
|
||||
if(!b_ret)
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
ret = ctrl_in(handlers, device_desc, buffer, 2, 0xDF, 0, &num_bytes);
|
||||
if(ret < 0) {
|
||||
close_ctrl_in(handlers);
|
||||
return ret;
|
||||
}
|
||||
if(num_bytes < 2) {
|
||||
close_ctrl_in(handlers);
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
}
|
||||
auth_val = read_le16(buffer) - 0x644C;
|
||||
ret = ctrl_in(handlers, device_desc, buffer, 1, 0xE3, ((auth_val >> 3) & 0x1C92) ^ auth_val, &num_bytes);
|
||||
close_ctrl_in(handlers);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
if((num_bytes < 1) || (buffer[0] != 0))
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
return LIBUSB_SUCCESS;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int GetDeviceSerial(is_device_device_handlers* handlers, uint8_t* buf, const is_device_usb_device* device_desc) {
|
||||
int ret = 0;
|
||||
uint32_t value = 0;
|
||||
|
|
@ -571,6 +735,9 @@ int GetDeviceSerial(is_device_device_handlers* handlers, uint8_t* buf, const is_
|
|||
case IS_NITRO_CAPTURE_DEVICE:
|
||||
return SendReadCommand(handlers, IS_NITRO_CAP_CMD_GET_SERIAL, buf, IS_DEVICE_REAL_SERIAL_NUMBER_SIZE, device_desc);
|
||||
case IS_TWL_CAPTURE_DEVICE:
|
||||
ret = AuthCtrlIn(handlers, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
ret = SendReadCommandU32(handlers, IS_TWL_CAP_CMD_UNLOCK_COMMS, &value, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
|
|
@ -653,11 +820,48 @@ int DisableLca2(is_device_device_handlers* handlers, const is_device_usb_device*
|
|||
return WriteNecMemU16(handlers, 0x0F84000A, 0, device_desc);
|
||||
}
|
||||
|
||||
int StartUsbCaptureDma(is_device_device_handlers* handlers, const is_device_usb_device* device_desc) {
|
||||
static bool is_string_present_and_same(const std::string text, uint8_t* buffer, size_t text_pos = 0) {
|
||||
if(text == "")
|
||||
return true;
|
||||
// Strings are pain.
|
||||
// For some reason, under MSVC comparing strings doesn't work,
|
||||
// but comparing the .c_str() representation does...
|
||||
// Too bad that same method doesn't work when using GCC... :/
|
||||
// Solution? Write the string to a buffer, and compare the two...
|
||||
uint8_t* str_check = new uint8_t[text.size()];
|
||||
write_string(str_check, text);
|
||||
bool is_different = false;
|
||||
for(size_t i = 0; i < text.size(); i++) {
|
||||
if(str_check[i] != buffer[i + text_pos]) {
|
||||
is_different = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete []str_check;
|
||||
return !is_different;
|
||||
}
|
||||
|
||||
static int data_dec_and_check(is_device_twl_enc_dec_table* dec_table, uint8_t* buffer, size_t total_size, const std::string text = "", size_t text_pos = 0) {
|
||||
enc_dec_table_apply_to_data(dec_table, buffer, total_size, false);
|
||||
uint32_t crc32 = get_crc32_data_comm(buffer, total_size - 4);
|
||||
uint32_t read_crc32 = read_le32(buffer, (total_size - 4) / 4);
|
||||
if((crc32 != read_crc32) || (!is_string_present_and_same(text, buffer, text_pos)))
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
static void data_crc32_and_enc(is_device_twl_enc_dec_table* enc_table, uint8_t* buffer, size_t total_size, const std::string text = "", size_t text_pos = 0) {
|
||||
if(text != "")
|
||||
write_string(buffer + 4 + text_pos, text);
|
||||
uint32_t crc32 = get_crc32_data_comm(buffer + 4, total_size - 4);
|
||||
write_le32(buffer, crc32);
|
||||
enc_dec_table_apply_to_data(enc_table, buffer, total_size, true);
|
||||
}
|
||||
|
||||
int StartUsbCaptureDma(is_device_device_handlers* handlers, const is_device_usb_device* device_desc, bool enable_sound_capture, is_device_twl_enc_dec_table* enc_table, is_device_twl_enc_dec_table* dec_table) {
|
||||
int ret = 0;
|
||||
uint8_t buffer[0x200];
|
||||
uint8_t is_twl_handshake_buffer[0x10] = {0x39, 0xC5, 0x5E, 0xC1, 0xA3, 0x02, 0x1D, 0xA1, 0x1E, 0xE9, 0x2F, 0x35, 0x29, 0x98, 0x63, 0x6C};
|
||||
uint8_t is_twl_handshake_buffer_pre2[0x10] = {0x0C, 0xF7, 0x48, 0x2B, 0xE9, 0x5A, 0xA2, 0x3C, 0xE5, 0x0E, 0x1F, 0xEB, 0x1C, 0x71, 0xB8, 0xAE};
|
||||
uint8_t buffer[0xB4];
|
||||
uint32_t enabled_value = 0;
|
||||
switch(device_desc->device_type) {
|
||||
case IS_NITRO_EMULATOR_DEVICE:
|
||||
ret = WriteNecMemU16(handlers, REG_USB_DMA_CONTROL_2, 2, device_desc);
|
||||
|
|
@ -667,22 +871,63 @@ int StartUsbCaptureDma(is_device_device_handlers* handlers, const is_device_usb_
|
|||
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);
|
||||
case IS_TWL_CAPTURE_DEVICE:
|
||||
ret = SendWriteCommand(handlers, IS_TWL_CAP_CMD_ENABLE_CAP_PART_2, NULL, 0, device_desc);
|
||||
if((enc_table == NULL) || (dec_table == NULL))
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
ret = SendWriteCommand(handlers, IS_TWL_CAP_CMD_ACTS, NULL, 0, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
ret = SendReadWriteCommand(handlers, IS_TWL_CAP_CMD_ENABLE_CAP_PRE_1, is_twl_0x81_packet, is_twl_0x81_packet_len, buffer, is_twl_0x81_packet_len, device_desc);
|
||||
memset(buffer, 0, 0xB4);
|
||||
write_le16(buffer, 0xB0, 2 + 2);
|
||||
write_le16(buffer, 6, 3 + 2);
|
||||
data_crc32_and_enc(enc_table, buffer, 0xB4, "MNTR", 8);
|
||||
ret = SendReadWriteCommand(handlers, IS_TWL_CAP_CMD_MNTR, buffer, 0xB4, buffer, 0xB4, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
ret = SendWriteCommand(handlers, IS_TWL_CAP_CMD_ENABLE_CAP_PRE_2, is_twl_handshake_buffer_pre2, 0x10, device_desc);
|
||||
ret = data_dec_and_check(dec_table, buffer, 0xB4, "MNTR", 8);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
ret = SendReadCommand(handlers, IS_TWL_CAP_CMD_ENABLE_CAP_PRE_3, buffer, 0x200, device_desc);
|
||||
ret = SendReadCommand(handlers, IS_TWL_CAP_CMD_EPAC, buffer, 8, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
ret = SendReadCommand(handlers, IS_TWL_CAP_CMD_ENABLE_CAP, buffer, 0x10, device_desc);
|
||||
ret = data_dec_and_check(dec_table, buffer, 8, "EPAC");
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
ret = SendReadWriteCommand(handlers, IS_TWL_CAP_CMD_ENABLE_CAP_PART_2, is_twl_handshake_buffer, sizeof(is_twl_handshake_buffer), buffer, 8, device_desc);
|
||||
ret = SendReadCommand(handlers, IS_TWL_CAP_CMD_POST_EPAC, buffer, 8, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
ret = data_dec_and_check(dec_table, buffer, 8);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
if(read_le32(buffer) != 0)
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
memset(buffer, 0, 0x10);
|
||||
data_crc32_and_enc(enc_table, buffer, 0x10, "TCZC");
|
||||
ret = SendWriteCommand(handlers, IS_TWL_CAP_CMD_TCZC, buffer, 0x10, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
ret = SendReadCommand(handlers, IS_TWL_CAP_CMD_SCTG, buffer, 0x10, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
ret = data_dec_and_check(dec_table, buffer, 0x10, "SCTG");
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
memset(buffer, 0, 0x10);
|
||||
enabled_value = 1;
|
||||
if(enable_sound_capture)
|
||||
enabled_value |= 0x10;
|
||||
write_le32(buffer, enabled_value, 2);
|
||||
// FPS. Seems to do nothing? Set to 60 / multiplier,
|
||||
// but it has no effect...
|
||||
write_le32(buffer, 60, 3);
|
||||
data_crc32_and_enc(enc_table, buffer, 0x10, "ACTS");
|
||||
ret = SendReadWriteCommand(handlers, IS_TWL_CAP_CMD_ACTS, buffer, 0x10, buffer, 8, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
ret = data_dec_and_check(dec_table, buffer, 8);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
if(read_le32(buffer) != 0)
|
||||
return LIBUSB_ERROR_INTERRUPTED;
|
||||
return ret;
|
||||
default:
|
||||
return 0;
|
||||
|
|
@ -924,6 +1169,61 @@ int ResetUSBDevice(is_device_device_handlers* handlers) {
|
|||
return is_device_is_driver_reset_device(handlers);
|
||||
}
|
||||
|
||||
static void prepare_enc_dec_table_data(is_device_twl_enc_dec_table* table, uint32_t seed_1, uint32_t seed_2, uint8_t num_iters, uint8_t num_values, bool is_enc) {
|
||||
uint32_t rotating_value = seed_1 ^ seed_2 ^ 0x3CF0F03C;
|
||||
table->rotating_value = rotating_value;
|
||||
table->num_values = num_values;
|
||||
table->num_iters_full = num_iters;
|
||||
table->num_iters_before_refresh = num_iters;
|
||||
uint8_t buffer[8];
|
||||
uint8_t values_buffer[8];
|
||||
for(int i = 0; i < 7; i++)
|
||||
buffer[i] = i + 1;
|
||||
buffer[7] = 7;
|
||||
values_buffer[0] = 0;
|
||||
for(int i = 1; i < num_values; i++) {
|
||||
int divisor = (7 - (i - 1));
|
||||
int mod = rotating_value % divisor;
|
||||
values_buffer[i] = buffer[mod];
|
||||
for(int j = mod; j < 7; j++)
|
||||
buffer[j] = buffer[j + 1];
|
||||
rotating_value = rotate_bits_right(rotating_value);
|
||||
}
|
||||
int offset = 0;
|
||||
if(!is_enc)
|
||||
offset = 1;
|
||||
for(int i = 0; i < num_values; i++)
|
||||
table->action_values[i] = read_le16(is_twl_cap_init_seed_table, (values_buffer[i] * 2) + offset);
|
||||
}
|
||||
|
||||
int PrepareEncDecTable(is_device_device_handlers* handlers, is_device_twl_enc_dec_table* enc_table, is_device_twl_enc_dec_table* dec_table, const is_device_usb_device* device_desc) {
|
||||
int ret = 0;
|
||||
uint8_t buffer[0xC];
|
||||
uint32_t system_ms = ms_since_start();
|
||||
uint32_t incoming_seed = 0;
|
||||
switch(device_desc->device_type) {
|
||||
case IS_TWL_CAPTURE_DEVICE:
|
||||
ret = AuthCtrlIn(handlers, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
write_le32(buffer, IS_TWL_CAP_CMD_GET_ENC_DEC_SEEDS);
|
||||
write_le32(buffer, system_ms, 1);
|
||||
write_le32(buffer, system_ms ^ 0x84327472, 2);
|
||||
ret = SendWriteCommand(handlers, IS_TWL_CAP_CMD_GET_ENC_DEC_SEEDS, buffer, sizeof(buffer), device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
ret = SendReadCommand(handlers, IS_TWL_CAP_CMD_GET_ENC_DEC_SEEDS, buffer, 4, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
incoming_seed = read_le32(buffer);
|
||||
prepare_enc_dec_table_data(enc_table, system_ms, system_ms ^ 0x84327472 ^ 0xB0762D27, 0x10, 7, true);
|
||||
prepare_enc_dec_table_data(dec_table, ~system_ms, incoming_seed ^ 0xD13F1EBB, 0x40, 3, false);
|
||||
return ret;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -51,6 +51,16 @@ static bool read_is_driver_device_info(HANDLE handle, uint8_t* buffer, size_t si
|
|||
return DeviceIoControl(handle, 0x22000C, buffer, size, buffer, size, num_read, NULL);
|
||||
}
|
||||
|
||||
static bool is_driver_send_ioctl(HANDLE handle, uint8_t* buffer, size_t size, uint8_t request, uint16_t index, DWORD* num_read) {
|
||||
uint8_t data[0x10];
|
||||
memset(data, 0, 0x10);
|
||||
write_le32(data, 0x17);
|
||||
write_le32(data, 2, 1);
|
||||
write_le32(data, ((uint32_t)request) << 8, 2);
|
||||
write_le32(data, index, 3);
|
||||
return DeviceIoControl(handle, 0x220020, data, 0x10, buffer, size, num_read, NULL);
|
||||
}
|
||||
|
||||
static bool is_driver_device_reset(HANDLE handle) {
|
||||
DWORD num_read;
|
||||
return DeviceIoControl(handle, 0x220004, NULL, 0, NULL, 0, &num_read, NULL);
|
||||
|
|
@ -94,8 +104,8 @@ static bool is_driver_get_device_pid_vid(std::string path, uint16_t& out_vid, ui
|
|||
return false;
|
||||
if (num_read < 11)
|
||||
return false;
|
||||
out_vid = buffer[8] + (buffer[9] << 8);
|
||||
out_pid = buffer[10] + (buffer[11] << 8);
|
||||
out_vid = read_le16(buffer, 4);
|
||||
out_pid = read_le16(buffer, 5);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -104,6 +114,7 @@ static bool is_driver_setup_connection(is_device_device_handlers* handlers, std:
|
|||
handlers->mutex = NULL;
|
||||
handlers->write_handle = INVALID_HANDLE_VALUE;
|
||||
handlers->read_handle = INVALID_HANDLE_VALUE;
|
||||
handlers->path = path;
|
||||
std::string mutex_name = "Global\\ISU_" + path.substr(4);
|
||||
std::replace(mutex_name.begin(), mutex_name.end(), '\\', '@');
|
||||
handlers->mutex = CreateMutex(NULL, true, mutex_name.c_str());
|
||||
|
|
@ -164,8 +175,33 @@ static void STDCALL OverlappedCompletionNothingRoutine(DWORD dwErrorCode, DWORD
|
|||
return;
|
||||
}
|
||||
|
||||
static void is_driver_close_handle(void** handle, void* default_value = INVALID_HANDLE_VALUE) {
|
||||
#ifdef _WIN32
|
||||
if ((*handle) == default_value)
|
||||
return;
|
||||
CloseHandle(*handle);
|
||||
*handle = default_value;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool is_driver_prepare_ctrl_in_handle(is_device_device_handlers* handlers) {
|
||||
#ifdef _WIN32
|
||||
HANDLE handle = CreateFile(handlers->path.c_str(), (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
handlers->ctrl_in_handle = handle;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void is_driver_close_ctrl_in_handle(is_device_device_handlers* handlers) {
|
||||
#ifdef _WIN32
|
||||
is_driver_close_handle(&handlers->ctrl_in_handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
is_device_device_handlers* is_driver_serial_reconnection(CaptureDevice* device) {
|
||||
is_device_device_handlers* final_handlers = NULL;
|
||||
#ifdef _WIN32
|
||||
|
|
@ -178,6 +214,7 @@ is_device_device_handlers* is_driver_serial_reconnection(CaptureDevice* device)
|
|||
final_handlers->mutex = handlers.mutex;
|
||||
final_handlers->read_handle = handlers.read_handle;
|
||||
final_handlers->write_handle = handlers.write_handle;
|
||||
final_handlers->path = device->path;
|
||||
}
|
||||
else
|
||||
is_driver_end_connection(&handlers);
|
||||
|
|
@ -188,15 +225,10 @@ is_device_device_handlers* is_driver_serial_reconnection(CaptureDevice* device)
|
|||
|
||||
void is_driver_end_connection(is_device_device_handlers* handlers) {
|
||||
#ifdef _WIN32
|
||||
if (handlers->write_handle != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(handlers->write_handle);
|
||||
handlers->write_handle = INVALID_HANDLE_VALUE;
|
||||
if (handlers->read_handle != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(handlers->read_handle);
|
||||
handlers->read_handle = INVALID_HANDLE_VALUE;
|
||||
if(handlers->mutex != NULL)
|
||||
CloseHandle(handlers->mutex);
|
||||
handlers->mutex = NULL;
|
||||
is_driver_close_handle(&handlers->write_handle);
|
||||
is_driver_close_handle(&handlers->read_handle);
|
||||
is_driver_close_handle(&handlers->ctrl_in_handle);
|
||||
is_driver_close_handle(&handlers->mutex, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -265,6 +297,18 @@ int is_driver_bulk_in(is_device_device_handlers* handlers, const is_device_usb_d
|
|||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
// Read from ctrl, which also sends commands
|
||||
int is_driver_ctrl_in(is_device_device_handlers* handlers, uint8_t* buf, int length, uint8_t request, uint16_t index, int* transferred) {
|
||||
#ifdef _WIN32
|
||||
DWORD num_read = 0;
|
||||
bool ret = is_driver_send_ioctl(handlers->ctrl_in_handle, buf, length, request, index, &num_read);
|
||||
if(!ret)
|
||||
return LIBUSB_ERROR_BUSY;
|
||||
*transferred = num_read;
|
||||
#endif
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
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();
|
||||
|
|
|
|||
|
|
@ -164,6 +164,14 @@ int is_device_libusb_bulk_in(is_device_device_handlers* handlers, const is_devic
|
|||
return libusb_bulk_transfer(handlers->usb_handle, usb_device_desc->ep_in, buf, length, transferred, usb_device_desc->bulk_timeout);
|
||||
}
|
||||
|
||||
// Read from ctrl_in
|
||||
int is_device_libusb_ctrl_in(is_device_device_handlers* handlers, const is_device_usb_device* usb_device_desc, uint8_t* buf, int length, uint8_t request, uint16_t index, int* transferred) {
|
||||
int ret = libusb_control_transfer(handlers->usb_handle, 0xC0, request, 0, index, buf, length, usb_device_desc->bulk_timeout);
|
||||
if(ret >= 0)
|
||||
*transferred = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void is_device_libusb_cancell_callback(isd_async_callback_data* cb_data) {
|
||||
cb_data->transfer_data_access.lock();
|
||||
if(cb_data->transfer_data)
|
||||
|
|
|
|||
|
|
@ -26,25 +26,26 @@ static int process_frame_and_read(CaptureData* capture_data, CaptureReceived* ca
|
|||
default:
|
||||
break;
|
||||
}
|
||||
int num_available_frames = multiplier;
|
||||
int num_available_frames = video_length / sizeof(ISTWLCaptureVideoInternalReceived);
|
||||
if(num_available_frames < multiplier)
|
||||
return 0;
|
||||
processed = true;
|
||||
int frame_next = num_available_frames - 1;
|
||||
last_read_frame_index += num_available_frames;
|
||||
video_address = video_address + (frame_next * sizeof(ISTWLCaptureVideoReceived));
|
||||
video_address = video_address + (frame_next * sizeof(ISTWLCaptureVideoInternalReceived));
|
||||
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;
|
||||
size_t video_processed_size = usb_is_device_get_video_in_size(curr_capture_type, IS_TWL_CAPTURE_DEVICE);
|
||||
int ret = ReadFrame(handlers, (uint8_t*)&capture_buf->is_twl_capture_received.video_capture_in, 0, video_processed_size, usb_device_desc);
|
||||
int ret = ReadFrame(handlers, (uint8_t*)&capture_buf->is_twl_capture_received.video_capture_in, video_address, video_processed_size, usb_device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
int audio_diff_from_max = usb_device_desc->max_audio_samples_size - audio_length;
|
||||
int max_audio_length = (multiplier * 5) * sizeof(ISTWLCaptureAudioReceived);
|
||||
int audio_diff_from_max = max_audio_length - audio_length;
|
||||
if(audio_diff_from_max >= 0)
|
||||
audio_diff_from_max = 0;
|
||||
else {
|
||||
audio_address -= audio_diff_from_max;
|
||||
audio_length = usb_device_desc->max_audio_samples_size;
|
||||
audio_address += audio_diff_from_max;
|
||||
audio_length = max_audio_length;
|
||||
}
|
||||
ret = ReadFrame(handlers, (uint8_t*)&capture_buf->is_twl_capture_received.audio_capture_in, audio_address, audio_length, usb_device_desc);
|
||||
if(ret < 0)
|
||||
|
|
@ -52,7 +53,7 @@ static int process_frame_and_read(CaptureData* capture_data, CaptureReceived* ca
|
|||
const auto curr_time = std::chrono::high_resolution_clock::now();
|
||||
const std::chrono::duration<double> diff = curr_time - (*clock_start);
|
||||
last_frame_length = diff.count();
|
||||
output_to_thread(capture_data, capture_buf, curr_capture_type, clock_start, video_processed_size + (audio_length / sizeof(ISTWLCaptureAudioReceived)) * (sizeof(ISTWLCaptureAudioReceived) - sizeof(uint32_t)));
|
||||
output_to_thread(capture_data, capture_buf, curr_capture_type, clock_start, video_processed_size + ((audio_length / sizeof(ISTWLCaptureAudioReceived)) * sizeof(ISTWLCaptureSoundData)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -85,12 +86,17 @@ void is_twl_acquisition_capture_main_loop(CaptureData* capture_data, ISDeviceCap
|
|||
uint32_t video_length = 0;
|
||||
uint32_t audio_address = 0;
|
||||
uint32_t audio_length = 0;
|
||||
ret = StartUsbCaptureDma(handlers, usb_device_desc);
|
||||
is_device_twl_enc_dec_table enc_table, dec_table;
|
||||
ret = PrepareEncDecTable(handlers, &enc_table, &dec_table, usb_device_desc);
|
||||
if(ret < 0) {
|
||||
capture_error_print(true, capture_data, "Enc Dec Table init: Failed");
|
||||
return;
|
||||
}
|
||||
ret = StartUsbCaptureDma(handlers, usb_device_desc, audio_enabled, &enc_table, &dec_table);
|
||||
if(ret < 0) {
|
||||
capture_error_print(true, capture_data, "Capture Start: Failed");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
ret = AskFrameLengthPos(handlers, &video_address, &video_length, true, &audio_address, &audio_length, audio_enabled, usb_device_desc);
|
||||
if(ret < 0) {
|
||||
capture_error_print(true, capture_data, "Initial Frame Info Read: Failed");
|
||||
|
|
@ -101,26 +107,23 @@ void is_twl_acquisition_capture_main_loop(CaptureData* capture_data, ISDeviceCap
|
|||
capture_error_print(true, capture_data, "Initial Frame Info Set: Failed");
|
||||
return;
|
||||
}
|
||||
*/
|
||||
default_sleep(DEFAULT_FRAME_TIME_MS / SLEEP_FRAME_DIVIDER);
|
||||
|
||||
while(capture_data->status.connected && capture_data->status.running) {
|
||||
bool processed = false;
|
||||
/*
|
||||
ret = AskFrameLengthPos(handlers, &video_address, &video_length, true, &audio_address, &audio_length, audio_enabled, usb_device_desc);
|
||||
if(ret < 0) {
|
||||
capture_error_print(true, capture_data, "Frame Info Read: Failed");
|
||||
return;
|
||||
}
|
||||
if(video_length > 0) {
|
||||
*/
|
||||
ret = process_frame_and_read(capture_data, &is_device_capture_recv_data[0].buffer, curr_capture_type, curr_capture_speed, &clock_last_frame, last_read_frame_index, video_address, video_length, audio_address, audio_length, processed, last_frame_length);
|
||||
if(ret < 0) {
|
||||
capture_error_print(true, capture_data, "Frame Read: Error " + std::to_string(ret));
|
||||
return;
|
||||
}
|
||||
/*
|
||||
if(processed) {
|
||||
curr_capture_speed = capture_data->status.capture_speed;
|
||||
ret = SetLastFrameInfo(handlers, video_address, video_length, audio_address, audio_length, usb_device_desc);
|
||||
if(ret < 0) {
|
||||
capture_error_print(true, capture_data, "Frame Info Set: Failed");
|
||||
|
|
@ -128,7 +131,6 @@ void is_twl_acquisition_capture_main_loop(CaptureData* capture_data, ISDeviceCap
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
if(last_frame_length > 0)
|
||||
default_sleep((last_frame_length * 1000) / SLEEP_FRAME_DIVIDER);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ struct override_all_data {
|
|||
int loaded_profile = STARTUP_FILE_INDEX;
|
||||
bool mono_app = false;
|
||||
bool recovery_mode = false;
|
||||
bool quit_on_first_connection_failure = false;
|
||||
};
|
||||
|
||||
static void ConsoleOutText(std::string full_text) {
|
||||
|
|
@ -666,6 +667,7 @@ static bool parse_int_arg(int &index, int argc, char **argv, int &target, std::s
|
|||
|
||||
int main(int argc, char **argv) {
|
||||
init_threads();
|
||||
init_start_time();
|
||||
int page_up_id = -1;
|
||||
int page_down_id = -1;
|
||||
int enter_id = -1;
|
||||
|
|
@ -710,6 +712,8 @@ int main(int argc, char **argv) {
|
|||
continue;
|
||||
if(parse_existence_arg(i, argv, override_data.auto_connect_to_first, true, "--auto_connect"))
|
||||
continue;
|
||||
if(parse_existence_arg(i, argv, override_data.quit_on_first_connection_failure, true, "--close_first_on_failure"))
|
||||
continue;
|
||||
if(parse_int_arg(i, argc, argv, override_data.loaded_profile, "--profile"))
|
||||
continue;
|
||||
#ifdef RASPI
|
||||
|
|
|
|||
|
|
@ -315,11 +315,19 @@ bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, const bool i
|
|||
#ifdef USE_IS_DEVICES_USB
|
||||
if(status->device.cc_type == CAPTURE_CONN_IS_NITRO) {
|
||||
base_ptr = (uint8_t*)p_in->is_twl_capture_received.audio_capture_in;
|
||||
uint16_t* base_ptr16 = (uint16_t*)base_ptr;
|
||||
size_t size_real = n_samples * 2;
|
||||
size_t size_packet_converted = sizeof(ISTWLCaptureAudioReceived) - sizeof(uint32_t);
|
||||
size_t size_packet_converted = sizeof(ISTWLCaptureSoundData);
|
||||
size_t num_packets = size_real / size_packet_converted;
|
||||
for(int i = 0; i < num_packets; i++)
|
||||
memcpy(base_ptr + (i * size_packet_converted), ((uint8_t*)&p_in->is_twl_capture_received.audio_capture_in[i]) + sizeof(uint32_t), size_packet_converted);
|
||||
memcpy(base_ptr + (i * size_packet_converted), ((uint8_t*)&p_in->is_twl_capture_received.audio_capture_in[i].sound_data.data), size_packet_converted);
|
||||
// Inverted L and R...
|
||||
for(int i = 0; i < n_samples; i++) {
|
||||
uint16_t r_sample = base_ptr16[(i * 2)];
|
||||
base_ptr16[(i * 2)] = base_ptr16[(i * 2) + 1];
|
||||
base_ptr16[(i * 2) + 1] = r_sample;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
if(base_ptr == NULL)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
static bool checked_be_once = false;
|
||||
static bool _is_be = false;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock> clock_start_program;
|
||||
|
||||
bool is_big_endian(void) {
|
||||
if(checked_be_once)
|
||||
|
|
@ -40,11 +41,11 @@ bool is_big_endian(void) {
|
|||
return _is_be;
|
||||
}
|
||||
|
||||
static uint32_t reverse_endianness(uint32_t value) {
|
||||
uint32_t reverse_endianness(uint32_t value) {
|
||||
return ((value & 0xFF) << 24) | ((value & 0xFF00) << 8) | ((value & 0xFF0000) >> 8) | ((value & 0xFF000000) >> 24);
|
||||
}
|
||||
|
||||
static uint16_t reverse_endianness(uint16_t value) {
|
||||
uint16_t reverse_endianness(uint16_t value) {
|
||||
return ((value & 0xFF) << 8) | ((value & 0xFF00) >> 8);
|
||||
}
|
||||
|
||||
|
|
@ -96,6 +97,85 @@ uint16_t from_be(uint16_t value) {
|
|||
return value;
|
||||
}
|
||||
|
||||
uint16_t read_le16(const uint8_t* data, size_t count, size_t multiplier) {
|
||||
data += count * multiplier;
|
||||
return data[0] | (data[1] << 8);
|
||||
}
|
||||
|
||||
uint16_t read_be16(const uint8_t* data, size_t count, size_t multiplier) {
|
||||
data += count * multiplier;
|
||||
return data[1] | (data[0] << 8);
|
||||
}
|
||||
|
||||
uint32_t read_le32(const uint8_t* data, size_t count, size_t multiplier) {
|
||||
data += count * multiplier;
|
||||
return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
|
||||
}
|
||||
|
||||
uint32_t read_be32(const uint8_t* data, size_t count, size_t multiplier) {
|
||||
data += count * multiplier;
|
||||
return data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24);
|
||||
}
|
||||
|
||||
void write_le16(uint8_t* data, uint16_t value, size_t count, size_t multiplier) {
|
||||
data += count * multiplier;
|
||||
data[0] = value & 0xFF;
|
||||
data[1] = (value >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
void write_be16(uint8_t* data, uint16_t value, size_t count, size_t multiplier) {
|
||||
data += count * multiplier;
|
||||
data[0] = (value >> 8) & 0xFF;
|
||||
data[1] = value & 0xFF;
|
||||
}
|
||||
|
||||
void write_le32(uint8_t* data, uint32_t value, size_t count, size_t multiplier) {
|
||||
data += count * multiplier;
|
||||
data[0] = value & 0xFF;
|
||||
data[1] = (value >> 8) & 0xFF;
|
||||
data[2] = (value >> 16) & 0xFF;
|
||||
data[3] = (value >> 24) & 0xFF;
|
||||
}
|
||||
|
||||
void write_be32(uint8_t* data, uint32_t value, size_t count, size_t multiplier) {
|
||||
data += count * multiplier;
|
||||
data[0] = (value >> 24) & 0xFF;
|
||||
data[1] = (value >> 16) & 0xFF;
|
||||
data[2] = (value >> 8) & 0xFF;
|
||||
data[3] = value & 0xFF;
|
||||
}
|
||||
|
||||
void write_string(uint8_t* data, std::string text) {
|
||||
for(int i = 0; i < text.size(); i++)
|
||||
data[i] = (uint8_t)text[i];
|
||||
}
|
||||
|
||||
std::string read_string(uint8_t* data, size_t size) {
|
||||
std::string out_str = "";
|
||||
out_str.reserve(size);
|
||||
for(int i = 0; i < size; i++)
|
||||
out_str[i] = (char)data[i];
|
||||
return out_str;
|
||||
}
|
||||
|
||||
uint32_t rotate_bits_left(uint32_t value) {
|
||||
return (value << 1) | ((value & 0x80000000) >> 31);
|
||||
}
|
||||
|
||||
uint32_t rotate_bits_right(uint32_t value) {
|
||||
return (value >> 1) | ((value & 1) << 31);
|
||||
}
|
||||
|
||||
void init_start_time() {
|
||||
clock_start_program = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
uint32_t ms_since_start() {
|
||||
const auto curr_time = std::chrono::high_resolution_clock::now();
|
||||
std::chrono::duration<double>diff = curr_time - clock_start_program;
|
||||
return (uint32_t)(diff.count() * 1000);
|
||||
}
|
||||
|
||||
std::string to_hex(uint16_t value) {
|
||||
const int num_digits = sizeof(value) * 2;
|
||||
char digits[num_digits];
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user