diff --git a/CMakeLists.txt b/CMakeLists.txt index 3937605..de4e44b 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -589,6 +589,7 @@ else() install(FILES ${USB_RULES_DIR}/95-usb3dscapture.rules DESTINATION .) install(FILES ${USB_RULES_DIR}/95-usbdscapture.rules DESTINATION .) install(FILES ${USB_RULES_DIR}/51-isnitro.rules DESTINATION .) + install(FILES ${USB_RULES_DIR}/51-istwl.rules DESTINATION .) install(FILES ${USB_RULES_DIR}/50-ftd2xx.rules DESTINATION .) install(FILES ${USB_RULES_DIR}/51-ftd2xx.rules DESTINATION .) install(FILES ${SETUP_SCRIPTS_DIR}/install_usb_rules${SCRIPT_EXTENSION} DESTINATION .) diff --git a/include/CaptureDeviceSpecific/ISDevices/usb_is_device_communications.hpp b/include/CaptureDeviceSpecific/ISDevices/usb_is_device_communications.hpp index ea17691..73ff553 100644 --- a/include/CaptureDeviceSpecific/ISDevices/usb_is_device_communications.hpp +++ b/include/CaptureDeviceSpecific/ISDevices/usb_is_device_communications.hpp @@ -13,6 +13,7 @@ enum is_device_type { IS_NITRO_EMULATOR_DEVICE, IS_NITRO_CAPTURE_DEVICE, + IS_TWL_CAPTURE_DEVICE, }; enum is_device_forward_config_values_colors { @@ -59,12 +60,16 @@ struct is_device_usb_device { int default_config; int default_interface; int bulk_timeout; - int ep2_in; - int ep1_out; + int ep_in; + int ep_out; + std::string write_pipe; + std::string read_pipe; int product_id; int manufacturer_id; is_device_type device_type; InputVideoDataType video_data_type; + size_t max_usb_packet_size; + bool do_pipe_clear_reset; }; struct is_device_device_handlers { diff --git a/include/capture_structs.hpp b/include/capture_structs.hpp index 2e18be5..e85743c 100755 --- a/include/capture_structs.hpp +++ b/include/capture_structs.hpp @@ -61,6 +61,11 @@ struct PACKED ISNitroEmulatorVideoInputData { uint8_t screen_data[IN_VIDEO_SIZE_DS][3]; }; +struct PACKED ISTWLCaptureVideoInputData { + USBOldDSPixelData screen_data[IN_VIDEO_SIZE_DS]; + uint8_t bit_6_rb_screen_data[(IN_VIDEO_SIZE_DS >> 3) * 2]; +}; + struct ALIGNED(16) PACKED FTD3_3DSCaptureReceived { RGB83DSVideoInputData video_in; uint16_t audio_data[N3DSXL_SAMPLES_IN]; @@ -113,6 +118,23 @@ struct ALIGNED(16) PACKED ISNitroCaptureReceived { ISNitroEmulatorVideoInputData video_in; }; +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 { + uint32_t time; + uint16_t sound_data[TWL_CAPTURE_SAMPLES_IN]; +}; + +struct ALIGNED(16) PACKED ISTWLCaptureReceived { + ISTWLCaptureVideoReceived video_capture_in; + ISTWLCaptureAudioReceived audio_capture_in[TWL_CAPTURE_MAX_SAMPLES_CHUNK_NUM]; +}; + #pragma pack(pop) union CaptureReceived { diff --git a/include/hw_defs.hpp b/include/hw_defs.hpp index 86455ad..172fc39 100755 --- a/include/hw_defs.hpp +++ b/include/hw_defs.hpp @@ -73,5 +73,7 @@ #define N3DSXL_SAMPLES_IN (1096 * 16) #define DS_SAMPLES_IN (1096) #define MAX_SAMPLES_IN O3DS_SAMPLES_IN +#define TWL_CAPTURE_SAMPLES_IN (510) +#define TWL_CAPTURE_MAX_SAMPLES_CHUNK_NUM (MAX_SAMPLES_IN / TWL_CAPTURE_SAMPLES_IN) #endif diff --git a/source/CaptureDeviceSpecific/ISDevices/usb_is_device_acquisition.cpp b/source/CaptureDeviceSpecific/ISDevices/usb_is_device_acquisition.cpp index 3323bcf..189482a 100644 --- a/source/CaptureDeviceSpecific/ISDevices/usb_is_device_acquisition.cpp +++ b/source/CaptureDeviceSpecific/ISDevices/usb_is_device_acquisition.cpp @@ -45,7 +45,7 @@ static bool initial_cleanup(const is_device_usb_device* usb_device_desc, is_devi case IS_NITRO_CAPTURE_DEVICE: return initial_cleanup_capture(usb_device_desc, handlers) != LIBUSB_SUCCESS; default: - return true; + return false; } } diff --git a/source/CaptureDeviceSpecific/ISDevices/usb_is_device_communications.cpp b/source/CaptureDeviceSpecific/ISDevices/usb_is_device_communications.cpp index f2ecb2f..45418a5 100644 --- a/source/CaptureDeviceSpecific/ISDevices/usb_is_device_communications.cpp +++ b/source/CaptureDeviceSpecific/ISDevices/usb_is_device_communications.cpp @@ -28,7 +28,10 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. -#define USB_PACKET_LIMIT 0x2000 +#define IS_TWL_SERIAL_NUMBER_SIZE 8 + +#define IS_NITRO_USB_PACKET_LIMIT 0x2000 +#define IS_TWL_USB_PACKET_LIMIT 0x200000 #define REG_USB_DMA_CONTROL_2 0x0C000028 #define REG_USB_BIU_CONTROL_2 0x0C0000A4 @@ -43,6 +46,12 @@ enum is_nitro_packet_capture_dir { IS_NITRO_PACKET_CAP_DIR_READ = 0x01 }; +enum is_twl_packet_capture_dir { + IS_TWL_PACKET_CAP_DIR_WRITE = 0x00, + IS_TWL_PACKET_CAP_DIR_READ = 0x01, + IS_TWL_PACKET_CAP_DIR_WRITE_READ = 0x02 +}; + enum is_device_packet_type { IS_NITRO_PACKET_TYPE_COMMAND = 0, IS_NITRO_PACKET_TYPE_EMU_MEMORY = 1, @@ -78,6 +87,11 @@ enum is_nitro_capture_command { IS_NITRO_CAP_CMD_SET_RESET_CPU_OFF = 0x22, }; +enum is_twl_capture_command { + IS_TWL_CAP_CMD_GET_SERIAL = 0x13, + IS_TWL_CAP_CMD_UNLOCK_COMMS = 0x1C, +}; + enum is_nitro_emulator_forward_bits { IS_NITRO_EMULATOR_FORWARD_ENABLE_BIT = 0, IS_NITRO_EMULATOR_FORWARD_COUNTER_RESTART_BIT = 1, @@ -103,6 +117,15 @@ struct PACKED is_device_packet_header { uint32_t length; uint32_t padding; }; + +struct PACKED is_device_rw_packet_header { + uint16_t command; + uint8_t direction; + uint8_t type; + uint32_t address; + uint32_t length_w; + uint32_t length_r; +}; #pragma pack(pop) static const is_device_usb_device usb_is_nitro_emu_rare_desc = { @@ -110,9 +133,11 @@ static const is_device_usb_device usb_is_nitro_emu_rare_desc = { .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, +.ep_in = 2 | LIBUSB_ENDPOINT_IN, .ep_out = 1 | LIBUSB_ENDPOINT_OUT, +.write_pipe = "Pipe00", .read_pipe = "Pipe01", .product_id = 2, .manufacturer_id = 1, .device_type = IS_NITRO_EMULATOR_DEVICE, -.video_data_type = VIDEO_DATA_BGR +.video_data_type = VIDEO_DATA_BGR, .max_usb_packet_size = IS_NITRO_USB_PACKET_LIMIT, +.do_pipe_clear_reset = true }; static const is_device_usb_device usb_is_nitro_emu_common_desc = { @@ -120,9 +145,11 @@ static const is_device_usb_device usb_is_nitro_emu_common_desc = { .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, +.ep_in = 2 | LIBUSB_ENDPOINT_IN, .ep_out = 1 | LIBUSB_ENDPOINT_OUT, +.write_pipe = "Pipe00", .read_pipe = "Pipe01", .product_id = 2, .manufacturer_id = 1, .device_type = IS_NITRO_EMULATOR_DEVICE, -.video_data_type = VIDEO_DATA_BGR +.video_data_type = VIDEO_DATA_BGR, .max_usb_packet_size = IS_NITRO_USB_PACKET_LIMIT, +.do_pipe_clear_reset = true }; static const is_device_usb_device usb_is_nitro_cap_desc = { @@ -130,15 +157,43 @@ static const is_device_usb_device usb_is_nitro_cap_desc = { .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, +.ep_in = 2 | LIBUSB_ENDPOINT_IN, .ep_out = 1 | LIBUSB_ENDPOINT_OUT, +.write_pipe = "Pipe00", .read_pipe = "Pipe01", .product_id = 2, .manufacturer_id = 1, .device_type = IS_NITRO_CAPTURE_DEVICE, -.video_data_type = VIDEO_DATA_BGR +.video_data_type = VIDEO_DATA_BGR, .max_usb_packet_size = IS_NITRO_USB_PACKET_LIMIT, +.do_pipe_clear_reset = true +}; + +static const is_device_usb_device usb_is_twl_cap_desc = { +.name = "ISTC", .long_name = "IS TWL Capture", +.vid = 0x0f6e, .pid = 0x0501, +.default_config = 1, .default_interface = 0, +.bulk_timeout = 500, +.ep_in = 6 | LIBUSB_ENDPOINT_IN, .ep_out = 2 | LIBUSB_ENDPOINT_OUT, +.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 +}; + +static const is_device_usb_device usb_is_twl_cap_desc_2 = { +.name = "ISTC", .long_name = "IS TWL Capture", +.vid = 0x0f6e, .pid = 0x0502, +.default_config = 1, .default_interface = 0, +.bulk_timeout = 500, +.ep_in = 6 | LIBUSB_ENDPOINT_IN, .ep_out = 2 | LIBUSB_ENDPOINT_OUT, +.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 }; 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, + &usb_is_twl_cap_desc, + &usb_is_twl_cap_desc_2, }; int GetNumISDeviceDesc() { @@ -157,6 +212,13 @@ static void fix_endianness_header(is_device_packet_header* header) { header->length = to_le(header->length); } +static void fix_endianness_header(is_device_rw_packet_header* header) { + header->command = to_le(header->command); + header->address = to_le(header->address); + header->length_w = to_le(header->length_w); + header->length_r = to_le(header->length_r); +} + static void fix_endianness_header(is_nitro_nec_packet_header* header) { header->count = to_le(header->count); header->address = to_le(header->address); @@ -183,35 +245,93 @@ 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); } +static int return_and_delete(uint8_t* ptr, int value) { + delete []ptr; + return value; +} + +static uint8_t get_packet_direction(is_device_type device_type, size_t transfer_size_r, size_t transfer_size_w) { + if((transfer_size_r != 0) && (transfer_size_w != 0)) { + switch(device_type) { + case IS_TWL_CAPTURE_DEVICE: + return IS_TWL_PACKET_CAP_DIR_WRITE_READ; + default: + return 0; + } + } + else if(transfer_size_r != 0) { + switch(device_type) { + case IS_NITRO_EMULATOR_DEVICE: + return IS_NITRO_PACKET_EMU_DIR_READ; + case IS_NITRO_CAPTURE_DEVICE: + return IS_NITRO_PACKET_CAP_DIR_READ; + case IS_TWL_CAPTURE_DEVICE: + return IS_TWL_PACKET_CAP_DIR_READ; + default: + return 0; + } + } + else { + switch(device_type) { + case IS_NITRO_EMULATOR_DEVICE: + return IS_NITRO_PACKET_EMU_DIR_WRITE; + case IS_NITRO_CAPTURE_DEVICE: + return IS_NITRO_PACKET_CAP_DIR_WRITE; + case IS_TWL_CAPTURE_DEVICE: + return IS_TWL_PACKET_CAP_DIR_WRITE; + default: + return 0; + } + } +} + +static uint8_t is_packet_direction_read(is_device_type device_type, uint8_t packet_direction) { + switch(device_type) { + case IS_NITRO_EMULATOR_DEVICE: + return packet_direction == IS_NITRO_PACKET_EMU_DIR_READ; + case IS_NITRO_CAPTURE_DEVICE: + return packet_direction == IS_NITRO_PACKET_CAP_DIR_READ; + case IS_TWL_CAPTURE_DEVICE: + return (packet_direction == IS_TWL_PACKET_CAP_DIR_WRITE_READ) || (packet_direction == IS_TWL_PACKET_CAP_DIR_READ); + default: + return false; + } +} + +static uint8_t is_packet_direction_write(is_device_type device_type, uint8_t packet_direction) { + switch(device_type) { + case IS_NITRO_EMULATOR_DEVICE: + return packet_direction == IS_NITRO_PACKET_EMU_DIR_WRITE; + case IS_NITRO_CAPTURE_DEVICE: + return packet_direction == IS_NITRO_PACKET_CAP_DIR_WRITE; + case IS_TWL_CAPTURE_DEVICE: + return (packet_direction == IS_TWL_PACKET_CAP_DIR_WRITE_READ) || (packet_direction == IS_TWL_PACKET_CAP_DIR_WRITE); + default: + return false; + } +} + 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); + int single_packet_covered_size = device_desc->max_usb_packet_size - sizeof(header); if(!append_mode) - single_packet_covered_size = USB_PACKET_LIMIT; + single_packet_covered_size = device_desc->max_usb_packet_size; int num_iters = (length + single_packet_covered_size - 1) / single_packet_covered_size; if(!num_iters) num_iters = 1; + size_t max_size_packet = length; + if(length > single_packet_covered_size) + max_size_packet = single_packet_covered_size; + uint8_t* single_usb_packet = new uint8_t[max_size_packet + sizeof(header)]; 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; - } - + uint8_t packet_direction = get_packet_direction(device_desc->device_type, 0, transfer_size); header.command = command; header.direction = packet_direction; header.type = type; @@ -232,35 +352,35 @@ static int SendWritePacket(is_device_device_handlers* handlers, uint16_t command 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; + return return_and_delete(single_usb_packet, ret); if(header_bytes != sizeof(is_device_packet_header)) - return LIBUSB_ERROR_INTERRUPTED; + return return_and_delete(single_usb_packet, 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; + return return_and_delete(single_usb_packet, ret); if(num_bytes != (transfer_size + sizeof(is_device_packet_header))) - return LIBUSB_ERROR_INTERRUPTED; + return return_and_delete(single_usb_packet, 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; + return return_and_delete(single_usb_packet, ret); if(status_bytes != sizeof(status)) - return LIBUSB_ERROR_INTERRUPTED; + return return_and_delete(single_usb_packet, LIBUSB_ERROR_INTERRUPTED); if(status[0] != 1) - return LIBUSB_ERROR_OTHER; + return return_and_delete(single_usb_packet, LIBUSB_ERROR_OTHER); } - return LIBUSB_SUCCESS; + return return_and_delete(single_usb_packet, 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 single_packet_covered_size = device_desc->max_usb_packet_size; int num_iters = (length + single_packet_covered_size - 1) / single_packet_covered_size; if(num_iters == 0) num_iters = 1; @@ -269,18 +389,7 @@ static int SendReadPacket(is_device_device_handlers* handlers, uint16_t command, 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; - } - + uint8_t packet_direction = get_packet_direction(device_desc->device_type, transfer_size, 0); header.command = command; header.direction = packet_direction; header.type = type; @@ -316,6 +425,83 @@ static int SendReadPacket(is_device_device_handlers* handlers, uint16_t command, return LIBUSB_SUCCESS; } +static int SendReadWritePacket(is_device_device_handlers* handlers, uint16_t command, is_device_packet_type type, uint32_t address, uint8_t* buf_w, int length_w, uint8_t* buf_r, int length_r, const is_device_usb_device* device_desc) { + if((device_desc->device_type == IS_NITRO_EMULATOR_DEVICE) || (device_desc->device_type == IS_NITRO_CAPTURE_DEVICE)) + return LIBUSB_SUCCESS; + is_device_rw_packet_header header; + int single_packet_covered_size_w = device_desc->max_usb_packet_size - sizeof(header); + int num_iters_w = (length_w + single_packet_covered_size_w - 1) / single_packet_covered_size_w; + if(!num_iters_w) + num_iters_w = 1; + int single_packet_covered_size_r = device_desc->max_usb_packet_size; + int num_iters_r = (length_r + single_packet_covered_size_r - 1) / single_packet_covered_size_r; + if(!num_iters_r) + num_iters_r = 1; + int num_iters = num_iters_w; + if(num_iters_r > num_iters) + num_iters = num_iters_r; + size_t max_size_packet_w = length_w; + if(length_w > single_packet_covered_size_w) + max_size_packet_w = single_packet_covered_size_w; + uint8_t* single_usb_packet = new uint8_t[max_size_packet_w + sizeof(header)]; + for(int i = 0; i < num_iters; i++) { + int transfer_size_w = length_w - (i * single_packet_covered_size_w); + if(transfer_size_w > single_packet_covered_size_w) + transfer_size_w = single_packet_covered_size_w; + int transfer_size_r = length_r - (i * single_packet_covered_size_r); + if(transfer_size_r > single_packet_covered_size_r) + transfer_size_r = single_packet_covered_size_r; + + uint8_t packet_direction = get_packet_direction(device_desc->device_type, transfer_size_r, transfer_size_w); + header.command = command; + header.direction = packet_direction; + header.type = type; + header.address = address; + header.length_w = transfer_size_w; + header.length_r = transfer_size_r; + fix_endianness_header(&header); + int ret = 0; + int num_bytes = 0; + if(is_packet_direction_write(device_desc->device_type, packet_direction)) { + for(int j = 0; j < sizeof(is_device_rw_packet_header); j++) + single_usb_packet[j] = ((uint8_t*)&header)[j]; + if(buf_w != NULL) { + for(int j = 0; j < transfer_size_w; j++) + single_usb_packet[sizeof(is_device_rw_packet_header) + j] = buf_w[(i * single_packet_covered_size_w) + j]; + ret = bulk_out(handlers, device_desc, single_usb_packet, transfer_size_w + sizeof(is_device_rw_packet_header), &num_bytes); + } + else { + ret = bulk_out(handlers, device_desc, single_usb_packet, sizeof(is_device_rw_packet_header), &num_bytes); + transfer_size_w = 0; + } + if(ret < 0) + return return_and_delete(single_usb_packet, ret); + if(num_bytes != (transfer_size_w + sizeof(is_device_rw_packet_header))) + return return_and_delete(single_usb_packet, LIBUSB_ERROR_INTERRUPTED); + } + else { + header.length_r = 0; + header.length_w = transfer_size_r; + ret = bulk_out(handlers, device_desc, (uint8_t*)&header, sizeof(is_device_rw_packet_header), &num_bytes); + if(ret < 0) + return return_and_delete(single_usb_packet, ret); + if(num_bytes != sizeof(is_device_packet_header)) + return return_and_delete(single_usb_packet, LIBUSB_ERROR_INTERRUPTED); + } + num_bytes = 0; + if(is_packet_direction_read(device_desc->device_type, packet_direction)) { + if(buf_r != NULL) { + ret = bulk_in(handlers, device_desc, buf_r + (i * single_packet_covered_size_r), transfer_size_r, &num_bytes); + if(ret < 0) + return return_and_delete(single_usb_packet, ret); + if(num_bytes != transfer_size_r) + return return_and_delete(single_usb_packet, LIBUSB_ERROR_INTERRUPTED); + } + } + } + return return_and_delete(single_usb_packet, 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); } @@ -339,11 +525,20 @@ int SendWriteCommandU32(is_device_device_handlers* handlers, uint16_t command, u } int GetDeviceSerial(is_device_device_handlers* handlers, uint8_t* buf, const is_device_usb_device* device_desc) { + int ret = 0; + uint32_t value = 0; 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); + case IS_TWL_CAPTURE_DEVICE: + ret = SendReadCommandU32(handlers, IS_TWL_CAP_CMD_UNLOCK_COMMS, &value, device_desc); + if(ret < 0) + return ret; + ret = SendReadCommand(handlers, IS_TWL_CAP_CMD_GET_SERIAL, buf, IS_TWL_SERIAL_NUMBER_SIZE, device_desc); + buf[IS_TWL_SERIAL_NUMBER_SIZE] = '\0'; + return ret; default: return 0; } diff --git a/source/CaptureDeviceSpecific/ISDevices/usb_is_device_is_driver.cpp b/source/CaptureDeviceSpecific/ISDevices/usb_is_device_is_driver.cpp index b6403ec..14891fb 100644 --- a/source/CaptureDeviceSpecific/ISDevices/usb_is_device_is_driver.cpp +++ b/source/CaptureDeviceSpecific/ISDevices/usb_is_device_is_driver.cpp @@ -99,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_device_device_handlers* handlers, std::string path) { +static bool is_driver_setup_connection(is_device_device_handlers* handlers, std::string path, std::string pipe_r, std::string pipe_w, bool do_pipe_clear_reset) { handlers->usb_handle = NULL; handlers->mutex = NULL; handlers->write_handle = INVALID_HANDLE_VALUE; @@ -107,22 +107,24 @@ static bool is_driver_setup_connection(is_device_device_handlers* handlers, std: std::string mutex_name = "Global\\ISU_" + path.substr(4); std::replace(mutex_name.begin(), mutex_name.end(), '\\', '@'); handlers->mutex = CreateMutex(NULL, true, mutex_name.c_str()); - if ((handlers->mutex != NULL) && (GetLastError() == ERROR_ALREADY_EXISTS)) { + if((handlers->mutex != NULL) && (GetLastError() == ERROR_ALREADY_EXISTS)) { CloseHandle(handlers->mutex); handlers->mutex = NULL; } - if (handlers->mutex == NULL) + if(handlers->mutex == NULL) return false; - handlers->write_handle = CreateFile((path + (char)(std::filesystem::path::preferred_separator)+"Pipe00").c_str(), (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - handlers->read_handle = CreateFile((path + (char)(std::filesystem::path::preferred_separator)+"Pipe01").c_str(), (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if ((handlers->write_handle == INVALID_HANDLE_VALUE) || (handlers->read_handle == INVALID_HANDLE_VALUE)) - return false; - if (!is_driver_device_reset(handlers->write_handle)) - return false; - if (!is_driver_pipe_reset(handlers->write_handle)) - return false; - if (!is_driver_pipe_reset(handlers->read_handle)) + handlers->write_handle = CreateFile((path + (char)(std::filesystem::path::preferred_separator)+ pipe_w).c_str(), (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + handlers->read_handle = CreateFile((path + (char)(std::filesystem::path::preferred_separator)+ pipe_r).c_str(), (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + if((handlers->write_handle == INVALID_HANDLE_VALUE) || (handlers->read_handle == INVALID_HANDLE_VALUE)) return false; + if(do_pipe_clear_reset) { + if(!is_driver_device_reset(handlers->write_handle)) + return false; + if(!is_driver_pipe_reset(handlers->write_handle)) + return false; + if(!is_driver_pipe_reset(handlers->read_handle)) + return false; + } return true; } @@ -169,7 +171,8 @@ is_device_device_handlers* is_driver_serial_reconnection(CaptureDevice* device) #ifdef _WIN32 if (device->path != "") { is_device_device_handlers handlers; - if (is_driver_setup_connection(&handlers, device->path)) { + const is_device_usb_device* usb_device_info = (const is_device_usb_device*)device->descriptor; + if (is_driver_setup_connection(&handlers, device->path, usb_device_info->read_pipe, usb_device_info->write_pipe, usb_device_info->do_pipe_clear_reset)) { final_handlers = new is_device_device_handlers; final_handlers->usb_handle = NULL; final_handlers->mutex = handlers.mutex; @@ -221,7 +224,7 @@ void is_driver_list_devices(std::vector &devices_list, bool* not_ 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_device_device_handlers handlers; - if(is_driver_setup_connection(&handlers, path)) + if(is_driver_setup_connection(&handlers, path, usb_device_desc->read_pipe, usb_device_desc->write_pipe, usb_device_desc->do_pipe_clear_reset)) is_device_insert_device(devices_list, &handlers, usb_device_desc, curr_serial_extra_id_is_device[j], path); is_driver_end_connection(&handlers); break; diff --git a/source/CaptureDeviceSpecific/ISDevices/usb_is_device_libusb.cpp b/source/CaptureDeviceSpecific/ISDevices/usb_is_device_libusb.cpp index 5731402..569e258 100644 --- a/source/CaptureDeviceSpecific/ISDevices/usb_is_device_libusb.cpp +++ b/source/CaptureDeviceSpecific/ISDevices/usb_is_device_libusb.cpp @@ -54,10 +54,12 @@ static bool is_device_libusb_setup_connection(libusb_device_handle* handle, cons return false; if(libusb_claim_interface(handle, usb_device_desc->default_interface) != LIBUSB_SUCCESS) return false; - if(libusb_clear_halt(handle, usb_device_desc->ep1_out) != LIBUSB_SUCCESS) - return false; - if(libusb_clear_halt(handle, usb_device_desc->ep2_in) != LIBUSB_SUCCESS) - return false; + if(usb_device_desc->do_pipe_clear_reset) { + if(libusb_clear_halt(handle, usb_device_desc->ep_out) != LIBUSB_SUCCESS) + return false; + if(libusb_clear_halt(handle, usb_device_desc->ep_in) != LIBUSB_SUCCESS) + return false; + } return true; } @@ -154,12 +156,12 @@ void is_device_libusb_list_devices(std::vector &devices_list, boo // Write to bulk 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); + return libusb_bulk_transfer(handlers->usb_handle, usb_device_desc->ep_out, buf, length, transferred, usb_device_desc->bulk_timeout); } // Read from bulk 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); + return libusb_bulk_transfer(handlers->usb_handle, usb_device_desc->ep_in, buf, length, transferred, usb_device_desc->bulk_timeout); } void is_device_libusb_cancell_callback(isd_async_callback_data* cb_data) { @@ -190,7 +192,7 @@ void is_device_libusb_async_in_start(is_device_device_handlers* handlers, const 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_device_libusb_async_callback, cb_data, usb_device_desc->bulk_timeout); + libusb_fill_bulk_transfer(transfer_in, handlers->usb_handle, usb_device_desc->ep_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(); diff --git a/usb_rules/51-isagb.rules b/usb_rules/51-isagb.rules index 15ce081..dfcb953 100644 --- a/usb_rules/51-isagb.rules +++ b/usb_rules/51-isagb.rules @@ -1,2 +1,3 @@ +SUBSYSTEM=="usb", ATTRS{idVendor}=="0f6e", ATTRS{idProduct}=="0200", MODE="0666" SUBSYSTEM=="usb", ATTRS{idVendor}=="0f6e", ATTRS{idProduct}=="0201", MODE="0666" SUBSYSTEM=="usb", ATTRS{idVendor}=="0f6e", ATTRS{idProduct}=="0202", MODE="0666" diff --git a/usb_rules/51-isctr.rules b/usb_rules/51-isctr.rules new file mode 100644 index 0000000..4ac7bd9 --- /dev/null +++ b/usb_rules/51-isctr.rules @@ -0,0 +1 @@ +SUBSYSTEM=="usb", ATTRS{idVendor}=="0f6e", ATTRS{idProduct}=="0600", MODE="0666" diff --git a/usb_rules/51-issnake.rules b/usb_rules/51-issnake.rules new file mode 100644 index 0000000..d428fce --- /dev/null +++ b/usb_rules/51-issnake.rules @@ -0,0 +1,2 @@ +SUBSYSTEM=="usb", ATTRS{idVendor}=="0f6e", ATTRS{idProduct}=="0700", MODE="0666" +SUBSYSTEM=="usb", ATTRS{idVendor}=="0f6e", ATTRS{idProduct}=="0701", MODE="0666" diff --git a/usb_rules/51-isspr.rules b/usb_rules/51-isspr.rules new file mode 100644 index 0000000..baa65b9 --- /dev/null +++ b/usb_rules/51-isspr.rules @@ -0,0 +1,2 @@ +SUBSYSTEM=="usb", ATTRS{idVendor}=="0f6e", ATTRS{idProduct}=="0601", MODE="0666" +SUBSYSTEM=="usb", ATTRS{idVendor}=="0f6e", ATTRS{idProduct}=="0602", MODE="0666" diff --git a/usb_rules/51-istwl.rules b/usb_rules/51-istwl.rules index fba9370..8c01842 100644 --- a/usb_rules/51-istwl.rules +++ b/usb_rules/51-istwl.rules @@ -1,2 +1,3 @@ SUBSYSTEM=="usb", ATTRS{idVendor}=="0f6e", ATTRS{idProduct}=="0500", MODE="0666" SUBSYSTEM=="usb", ATTRS{idVendor}=="0f6e", ATTRS{idProduct}=="0501", MODE="0666" +SUBSYSTEM=="usb", ATTRS{idVendor}=="0f6e", ATTRS{idProduct}=="0502", MODE="0666" diff --git a/usb_rules/51-partnerctr.rules b/usb_rules/51-partnerctr.rules new file mode 100644 index 0000000..393a053 --- /dev/null +++ b/usb_rules/51-partnerctr.rules @@ -0,0 +1,3 @@ +SUBSYSTEM=="usb", ATTRS{idVendor}=="0ed2", ATTRS{idProduct}=="0003", MODE="0666" +SUBSYSTEM=="usb", ATTRS{idVendor}=="0ed2", ATTRS{idProduct}=="0004", MODE="0666" +SUBSYSTEM=="usb", ATTRS{idVendor}=="0ed2", ATTRS{idProduct}=="000b", MODE="0666"