#include "frontend.hpp" #include "cypress_partner_ctr_communications.hpp" #include "cypress_shared_communications.hpp" #include "cypress_partner_ctr_acquisition_general.hpp" #include "usb_generic.hpp" #include #include #include #include #include #define CYPRESS_PARTNER_CTR_USB_PACKET_LIMIT 512 #define PARTNER_CTR_OUT_GET_SERIAL 0x5F #define PARTNER_CTR_SERIAL_SIZE 8 static const cypart_device_usb_device cypress_partner_ctr_device = { .name = "P.CTR-Cap", .long_name = "Partner CTR Capture", .video_data_type = VIDEO_DATA_BGR, .index_in_allowed_scan = CC_PARTNER_CTR, .ep_ctrl_serial_io_pipe = 1, .usb_device_info = { .vid = 0x0ED2, .pid = 0x0004, .default_config = 1, .default_interface = 0, .bulk_timeout = 500, .ep_ctrl_bulk_in = 4 | LIBUSB_ENDPOINT_IN, .ep_ctrl_bulk_out = 2 | LIBUSB_ENDPOINT_OUT, .ep_bulk_in = 6 | LIBUSB_ENDPOINT_IN, .max_usb_packet_size = CYPRESS_PARTNER_CTR_USB_PACKET_LIMIT, .do_pipe_clear_reset = true, .alt_interface = 0, .full_data = &cypress_partner_ctr_device, .get_serial_requires_setup = true, .get_serial_fn = cypress_partner_ctr_get_serial, .create_device_fn = cypress_partner_ctr_create_device, .bcd_device_mask = 0x0000, .bcd_device_wanted_value = 0x0000 } }; static const cypart_device_usb_device cypress_partner_ctr2_device = { .name = "P.CTR-Cap2", .long_name = "Partner CTR Capture 2", .video_data_type = VIDEO_DATA_BGR, .index_in_allowed_scan = CC_PARTNER_CTR, .ep_ctrl_serial_io_pipe = 1, .usb_device_info = { .vid = 0x0ED2, .pid = 0x000B, .default_config = 1, .default_interface = 0, .bulk_timeout = 500, .ep_ctrl_bulk_in = 4 | LIBUSB_ENDPOINT_IN, .ep_ctrl_bulk_out = 2 | LIBUSB_ENDPOINT_OUT, .ep_bulk_in = 6 | LIBUSB_ENDPOINT_IN, .max_usb_packet_size = CYPRESS_PARTNER_CTR_USB_PACKET_LIMIT, .do_pipe_clear_reset = true, .alt_interface = 0, .full_data = &cypress_partner_ctr2_device, .get_serial_requires_setup = true, .get_serial_fn = cypress_partner_ctr_get_serial, .create_device_fn = cypress_partner_ctr_create_device, .bcd_device_mask = 0x0000, .bcd_device_wanted_value = 0x0000 } }; static const cypart_device_usb_device* all_usb_cypart_device_devices_desc[] = { &cypress_partner_ctr_device, &cypress_partner_ctr2_device, }; static int write_to_address_partner_ctr(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint32_t address, const uint8_t* data, size_t data_size, uint8_t data_size_byte); static int read_from_address_partner_ctr(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint32_t address, uint8_t* data, size_t data_size, uint8_t data_size_byte); const cy_device_usb_device* get_cy_usb_info(const cypart_device_usb_device* usb_device_desc) { return &usb_device_desc->usb_device_info; } int GetNumCyPartnerCTRDeviceDesc() { return sizeof(all_usb_cypart_device_devices_desc) / sizeof(all_usb_cypart_device_devices_desc[0]); } const cypart_device_usb_device* GetCyPartnerCTRDeviceDesc(int index) { if((index < 0) || (index >= GetNumCyPartnerCTRDeviceDesc())) index = 0; return all_usb_cypart_device_devices_desc[index]; } std::string read_serial_ctr_capture(cy_device_device_handlers* handlers, const cypart_device_usb_device* device) { uint8_t buffer[] = { PARTNER_CTR_OUT_GET_SERIAL, 0}; uint8_t buffer_in[PARTNER_CTR_SERIAL_SIZE]; int transferred = 0; cypress_pipe_reset_ctrl_bulk_out(handlers, get_cy_usb_info(device), device->ep_ctrl_serial_io_pipe | LIBUSB_ENDPOINT_OUT); cypress_pipe_reset_ctrl_bulk_in(handlers, get_cy_usb_info(device), device->ep_ctrl_serial_io_pipe | LIBUSB_ENDPOINT_IN); int ret = cypress_ctrl_bulk_out_transfer(handlers, get_cy_usb_info(device), buffer, sizeof(buffer), &transferred, device->ep_ctrl_serial_io_pipe | LIBUSB_ENDPOINT_OUT); if(ret < 0) return ""; ret = cypress_ctrl_bulk_in_transfer(handlers, get_cy_usb_info(device), buffer_in, sizeof(buffer_in), &transferred, device->ep_ctrl_serial_io_pipe | LIBUSB_ENDPOINT_IN); if(ret < 0) return ""; if(transferred != sizeof(buffer_in)) return ""; uint16_t serial_part_1 = read_be16(buffer_in + 2); return std::to_string(serial_part_1) + "-" + read_string(buffer_in + 5, 3); } static int send_partner_ctr_packet(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, const uint8_t* data, size_t size_data, int &transferred) { cypress_pipe_reset_ctrl_bulk_out(handlers, get_cy_usb_info(device)); return cypress_ctrl_bulk_out_transfer(handlers, get_cy_usb_info(device), data, (int)size_data, &transferred); } static int recv_partner_ctr_packet(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint8_t* data, size_t size_data, int &transferred) { cypress_pipe_reset_ctrl_bulk_in(handlers, get_cy_usb_info(device)); return cypress_ctrl_bulk_in_transfer(handlers, get_cy_usb_info(device), data, (int)size_data, &transferred); } // Name is tentative, based on pattern observed in wireshark packets... static int write_to_address_partner_ctr(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint32_t address, const uint8_t* data, size_t data_size, uint8_t data_size_byte) { int transferred = 0; const size_t out_data_size = 6 + data_size; uint8_t* buffer_out = new uint8_t[out_data_size]; buffer_out[0] = 0x43; buffer_out[1] = data_size_byte; write_le32(buffer_out + 2, address); memcpy(buffer_out + 6, data, data_size); int ret = send_partner_ctr_packet(handlers, device, buffer_out, out_data_size, transferred); delete []buffer_out; if(ret < 0) return ret; if(transferred < ((int)out_data_size)) return -1; return ret; } // Divide data into chunks and read/send them out... static int read_write_generic_data_from_to_address_partner_ctr(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint32_t address, uint8_t* data, size_t data_size, const bool is_write) { size_t max_size = 0x20000; int data_size_byte = 0xF2; size_t curr_pos = 0; int ret = 0; while((max_size >= 1) && (data_size > 0)) { int num_iters = (int)(data_size / max_size); for(int i = 0; i < num_iters; i++) { if(is_write) ret = write_to_address_partner_ctr(handlers, device, (uint32_t)(address + curr_pos), data + curr_pos, max_size, data_size_byte); else ret = read_from_address_partner_ctr(handlers, device, (uint32_t)(address + curr_pos), data + curr_pos, max_size, data_size_byte); if(ret < 0) return ret; data_size -= max_size; curr_pos += max_size; } max_size /= 2; switch(max_size) { case 2: data_size_byte = 0x00; break; // Theoretical...? Not observed in any packet...? case 1: data_size_byte = 0x01; break; case 0: data_size_byte = -1; break; default: data_size_byte -= 0x10; break; } } return ret; } static int write_generic_data_to_address_partner_ctr(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint32_t address, uint8_t* data, size_t data_size) { return read_write_generic_data_from_to_address_partner_ctr(handlers, device, address, data, data_size, true); } // No packet seems to be sent with this pattern?! Would need to be checked // to be sure... static int write_u8_to_address_partner_ctr(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint32_t address, uint8_t value) { return write_generic_data_to_address_partner_ctr(handlers, device, address, &value, sizeof(value)); } static int write_u16_to_address_partner_ctr(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint32_t address, uint16_t value) { uint8_t buffer[sizeof(value)]; write_le16(buffer, value); return write_generic_data_to_address_partner_ctr(handlers, device, address, buffer, sizeof(value)); } static int write_u32_to_address_partner_ctr(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint32_t address, uint32_t value) { uint8_t buffer[sizeof(value)]; write_le32(buffer, value); return write_generic_data_to_address_partner_ctr(handlers, device, address, buffer, sizeof(value)); } // Name is tentative, based on pattern observed in wireshark packets... static int read_from_address_partner_ctr(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint32_t address, uint8_t* data, size_t data_size, uint8_t data_size_byte) { int transferred = 0; const size_t out_data_size = 6; uint8_t buffer_out[out_data_size]; buffer_out[0] = 0x42; buffer_out[1] = data_size_byte; write_le32(buffer_out + 2, address); int ret = send_partner_ctr_packet(handlers, device, buffer_out, out_data_size, transferred); if(ret < 0) return ret; if(transferred < ((int)out_data_size)) return -1; ret = recv_partner_ctr_packet(handlers, device, data, data_size, transferred); if(ret < 0) return ret; if(transferred < ((int)data_size)) return -1; return ret; } // Divide data into chunks and send them out... static int read_generic_data_from_address_partner_ctr(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint32_t address, uint8_t* data, size_t data_size) { return read_write_generic_data_from_to_address_partner_ctr(handlers, device, address, data, data_size, false); } // No packet seems to be read with this pattern?! Would need to be checked // to be sure... static int read_u8_from_address_partner_ctr(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint32_t address, uint8_t &value) { return read_generic_data_from_address_partner_ctr(handlers, device, address, &value, sizeof(value)); } static int read_u16_from_address_partner_ctr(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint32_t address, uint16_t &value) { uint8_t buffer[sizeof(value)]; int ret = read_generic_data_from_address_partner_ctr(handlers, device, address, buffer, sizeof(value)); value = read_le16(buffer); return ret; } static int read_u32_from_address_partner_ctr(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint32_t address, uint32_t &value) { uint8_t buffer[sizeof(value)]; int ret = read_generic_data_from_address_partner_ctr(handlers, device, address, buffer, sizeof(value)); value = read_le32(buffer); return ret; } static int read_partner_ctr_status(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint32_t &status) { return read_u32_from_address_partner_ctr(handlers, device, 0xF0000000, status); } // Name is tentative, especially for this one... static int read_fw_info_partner_ctr(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint8_t info_kind, uint32_t &value) { int transferred = 0; uint8_t buffer_out[4] = {0x20, 0x01, 0x00, 0x00}; uint8_t buffer_in[4]; buffer_out[3] = info_kind; int ret = send_partner_ctr_packet(handlers, device, buffer_out, 4, transferred); if(ret < 0) return ret; if(transferred < 4) return -1; ret = recv_partner_ctr_packet(handlers, device, buffer_in, 4, transferred); if(ret < 0) return ret; if(transferred < 4) return -1; value = read_le32(buffer_in); return ret; } // Seems to be some state, maybe...? Influenced by the writes, which seem to // select stuff...? static int capture_start_unknown_read_0x1002(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint16_t base_value, uint16_t second_value, uint16_t &unk16) { int ret = 0; ret = write_u16_to_address_partner_ctr(handlers, device, 0xF8001002, base_value); if(ret < 0) return ret; ret = read_u16_from_address_partner_ctr(handlers, device, 0xF8001001, unk16); if(ret < 0) return ret; ret = write_u16_to_address_partner_ctr(handlers, device, 0xF8001002, second_value); if(ret < 0) return ret; ret = read_u16_from_address_partner_ctr(handlers, device, 0xF8001001, unk16); if(ret < 0) return ret; ret = read_u16_from_address_partner_ctr(handlers, device, 0xF8001003, unk16); if(ret < 0) return ret; // Resets position...? ret = write_u16_to_address_partner_ctr(handlers, device, 0xF8001000, 0x001D); if(ret < 0) return ret; return ret; } static int capture_start_unknown_write_0x1000(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint16_t out_value_xd) { int ret = 0; uint16_t base_out_val = 0x001D | (out_value_xd & 0xFF00); ret = write_u16_to_address_partner_ctr(handlers, device, 0xF8001000, base_out_val); if(ret < 0) return ret; ret = write_u16_to_address_partner_ctr(handlers, device, 0xF8001000, out_value_xd); if(ret < 0) return ret; return ret; } static int capture_start_unknown_write_and_read_0x1000_0x1002(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint16_t out_value_xd, uint16_t base_value, uint16_t second_value, uint16_t &unk16) { int ret = 0; ret = capture_start_unknown_write_0x1000(handlers, device, out_value_xd); if(ret < 0) return ret; ret = capture_start_unknown_read_0x1002(handlers, device, base_value, second_value, unk16); if(ret < 0) return ret; return ret; } static int capture_start_first_unknown_write_and_read_0x1000_0x1002(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, uint16_t out_value_xd, uint16_t &unk16) { int ret = 0; ret = capture_start_unknown_write_and_read_0x1000_0x1002(handlers, device, out_value_xd, 0x0000, 0x0000, unk16); if(ret < 0) return ret; ret = capture_start_unknown_write_and_read_0x1000_0x1002(handlers, device, out_value_xd, 0x000F, 0x0000, unk16); if(ret < 0) return ret; return ret; } int set_battery_level(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, int battery_level) { uint16_t unk16 = 0; int ret = capture_start_unknown_write_and_read_0x1000_0x1002(handlers, device, 0x005D, 0x0018, 0x0004, unk16); if(ret < 0) return ret; return capture_start_unknown_write_and_read_0x1000_0x1002(handlers, device, 0x005D, 0x001A, battery_level, unk16); } int set_charge_kind(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, bool plugged_in, bool charging) { uint16_t unk16 = 0; // Is this 015D due to uninitialized data, or...? int ret = capture_start_unknown_write_and_read_0x1000_0x1002(handlers, device, 0x015D, 0x0118, 0x000F, unk16); if(ret < 0) return ret; int charge_kind = 0; if(plugged_in) charge_kind |= 1; if(charging) charge_kind |= 2; return capture_start_unknown_write_and_read_0x1000_0x1002(handlers, device, 0x005D, 0x001A, charge_kind, unk16); } int hardware_reset(cy_device_device_handlers* handlers, const cypart_device_usb_device* device) { uint16_t unk16 = 0; // Is this 015D due to uninitialized data, or...? int ret = capture_start_unknown_write_and_read_0x1000_0x1002(handlers, device, 0x003D, 0x0018, 0x0001, unk16); if(ret < 0) return ret; // Is this FF3D due to uninitialized data, or...? return capture_start_unknown_write_and_read_0x1000_0x1002(handlers, device, 0xFF3D, 0xFF18, 0x0000, unk16); } // Various unknown reads and writes from registers... int capture_start(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, std::string &serial) { int ret = 0; uint32_t status = 0; uint32_t unk32 = 0; uint16_t unk16 = 0; // Stop capture, if one already ongoing... ret = write_u32_to_address_partner_ctr(handlers, device, 0xF0000010, 0x80000000); if(ret < 0) return ret; default_sleep(30); serial = read_serial_ctr_capture(handlers, device); ret = read_fw_info_partner_ctr(handlers, device, 0, unk32); if(ret < 0) return ret; // Do processing based on this...? ret = read_fw_info_partner_ctr(handlers, device, 0x0F, unk32); if(ret < 0) return ret; // Do processing based on this...? ret = capture_start_first_unknown_write_and_read_0x1000_0x1002(handlers, device, 0x005D, unk16); if(ret < 0) return ret; ret = capture_start_first_unknown_write_and_read_0x1000_0x1002(handlers, device, 0x003D, unk16); if(ret < 0) return ret; ret = write_u32_to_address_partner_ctr(handlers, device, 0xF000000C, 0xFFFFFFFF); if(ret < 0) return ret; ret = read_fw_info_partner_ctr(handlers, device, 0, unk32); if(ret < 0) return ret; // Do processing based on this...? ret = read_fw_info_partner_ctr(handlers, device, 0x0F, unk32); if(ret < 0) return ret; ret = capture_start_first_unknown_write_and_read_0x1000_0x1002(handlers, device, 0x005D, unk16); if(ret < 0) return ret; ret = capture_start_first_unknown_write_and_read_0x1000_0x1002(handlers, device, 0x003D, unk16); if(ret < 0) return ret; ret = capture_start_unknown_write_and_read_0x1000_0x1002(handlers, device, 0x005D, 0x0018, 0x000F, unk16); if(ret < 0) return ret; ret = capture_start_unknown_write_and_read_0x1000_0x1002(handlers, device, 0x005D, 0x0019, 0x0000, unk16); if(ret < 0) return ret; // Is this FF5D due to uninitialized data, or...? ret = capture_start_unknown_write_and_read_0x1000_0x1002(handlers, device, 0xFF5D, 0xFF18, 0x0004, unk16); if(ret < 0) return ret; ret = capture_start_unknown_write_and_read_0x1000_0x1002(handlers, device, 0x005D, 0x0019, 0x0000, unk16); if(ret < 0) return ret; ret = write_u32_to_address_partner_ctr(handlers, device, 0xF000000C, 0x00001000); if(ret < 0) return ret; ret = capture_start_unknown_write_and_read_0x1000_0x1002(handlers, device, 0x005D, 0x0028, 0x0000, unk16); if(ret < 0) return ret; ret = read_partner_ctr_status(handlers, device, status); if(ret < 0) return ret; // Is this 015D due to uninitialized data, or...? ret = capture_start_unknown_write_and_read_0x1000_0x1002(handlers, device, 0x015D, 0x012A, 0x0000, unk16); if(ret < 0) return ret; ret = read_u32_from_address_partner_ctr(handlers, device, 0xF8002010, unk32); if(ret < 0) return ret; ret = set_battery_level(handlers, device, 100); if(ret < 0) return ret; return 0; } // Various unknown reads and writes from registers... int StartCaptureDma(cy_device_device_handlers* handlers, const cypart_device_usb_device* device, bool is_3d) { int ret = 0; uint32_t status = 0; uint32_t unk32 = 0; uint16_t unk16 = 0; uint8_t buffer_in[16]; // Stop capture, if one already ongoing... ret = write_u32_to_address_partner_ctr(handlers, device, 0xF0000010, 0x80000000); if(ret < 0) return ret; default_sleep(30); ret = write_u32_to_address_partner_ctr(handlers, device, 0xF0000010, 0x00000004); if(ret < 0) return ret; ret = write_u32_to_address_partner_ctr(handlers, device, 0xF0000010, 0x00000008); if(ret < 0) return ret; ret = read_u32_from_address_partner_ctr(handlers, device, 0xF8002010, unk32); if(ret < 0) return ret; ret = read_u32_from_address_partner_ctr(handlers, device, 0xF8002010, unk32); if(ret < 0) return ret; ret = read_u32_from_address_partner_ctr(handlers, device, 0xF800200C, unk32); if(ret < 0) return ret; default_sleep(50); ret = read_u32_from_address_partner_ctr(handlers, device, 0xF800200C, unk32); if(ret < 0) return ret; default_sleep(180); ret = write_u16_to_address_partner_ctr(handlers, device, 0xF8002004, 0x0000); if(ret < 0) return ret; ret = write_u16_to_address_partner_ctr(handlers, device, 0xF8002004, 0x0001); if(ret < 0) return ret; ret = read_u32_from_address_partner_ctr(handlers, device, 0xF800200C, unk32); if(ret < 0) return ret; ret = read_generic_data_from_address_partner_ctr(handlers, device, (unk32 & 0xFF) << 20, buffer_in, 16); if(ret < 0) return ret; ret = write_u16_to_address_partner_ctr(handlers, device, 0xF8002004, 0x0000); if(ret < 0) return ret; ret = read_partner_ctr_status(handlers, device, status); if(ret < 0) return ret; // Act based on status...? ret = write_u32_to_address_partner_ctr(handlers, device, 0xF0000010, 0x00000800); if(ret < 0) return ret; // Framerate... 3D RGB888 is too much for 60 FPS with all screens... // Force it to 30 FPS for now. Could be expanded in the future to have more // options, like "top screens only" or "YUV422/YUV420"... // 0x00 == 60, 0x0110 == 30, 0x0120 == 15 // 0x00 == RGB888, 0x0100 == YUV422, 0x0120 == YUV420 ret = write_u16_to_address_partner_ctr(handlers, device, 0xF8002005, is_3d ? 0x0110 : 0x0000); if(ret < 0) return ret; // 0x00 == 60, 0x10 == 30, 0x20 == 15 // 0x00 == RGB888, 0x01 == YUV422, 0x20 == YUV420 ret = write_u16_to_address_partner_ctr(handlers, device, 0xF8002005, is_3d ? 0x0010 : 0x0000); if(ret < 0) return ret; ret = read_u32_from_address_partner_ctr(handlers, device, 0xF8002010, unk32); if(ret < 0) return ret; ret = read_u32_from_address_partner_ctr(handlers, device, 0xF8002010, unk32); if(ret < 0) return ret; ret = read_u32_from_address_partner_ctr(handlers, device, 0xF800200C, unk32); if(ret < 0) return ret; default_sleep(50); ret = read_u32_from_address_partner_ctr(handlers, device, 0xF800200C, unk32); if(ret < 0) return ret; // With 3D 60 fps, this would be 0x0078 ret = write_u16_to_address_partner_ctr(handlers, device, 0xF8002004, is_3d ? 0x0878 : 0x0068); if(ret < 0) return ret; ret = write_u16_to_address_partner_ctr(handlers, device, 0xF8002004, is_3d ? 0x007A : 0x016A); if(ret < 0) return ret; default_sleep(12); ret = write_u16_to_address_partner_ctr(handlers, device, 0xF8002004, is_3d ? 0x7778 : 0x7668); if(ret < 0) return ret; default_sleep(70); ret = write_u16_to_address_partner_ctr(handlers, device, 0xF8002004, is_3d ? 0x0078 : 0x0068); if(ret < 0) return ret; ret = write_u16_to_address_partner_ctr(handlers, device, 0xF8002004, is_3d ? 0x0079 : 0x0069); if(ret < 0) return ret; ret = read_u32_from_address_partner_ctr(handlers, device, 0xF800200C, unk32); if(ret < 0) return ret; ret = read_generic_data_from_address_partner_ctr(handlers, device, (unk32 & 0xFF) << 20, buffer_in, 16); if(ret < 0) return ret; ret = write_u16_to_address_partner_ctr(handlers, device, 0xF8002004, is_3d ? 0x0078 : 0x0068); if(ret < 0) return ret; ret = read_partner_ctr_status(handlers, device, status); if(ret < 0) return ret; // Act based on status...? ret = write_u32_to_address_partner_ctr(handlers, device, 0xF0000010, 0x00000800); if(ret < 0) return ret; default_sleep(180); // TODO: Wait until delay is 0? return 0; } // Various unknown reads and writes from registers... int capture_end(cy_device_device_handlers* handlers, const cypart_device_usb_device* device) { int ret = 0; ret = write_u32_to_address_partner_ctr(handlers, device, 0xF0000014, 0x00000003); if(ret < 0) return ret; ret = write_u32_to_address_partner_ctr(handlers, device, 0xF0000010, 0x00000001); if(ret < 0) return ret; default_sleep(80); ret = write_u32_to_address_partner_ctr(handlers, device, 0xF000000C, 0x00001000); if(ret < 0) return ret; default_sleep(210); ret = write_u32_to_address_partner_ctr(handlers, device, 0xF0000014, 0x00000004); if(ret < 0) return ret; ret = write_u32_to_address_partner_ctr(handlers, device, 0xF0000014, 0x00000008); if(ret < 0) return ret; return 0; } int ReadFrame(cy_device_device_handlers* handlers, uint8_t* buf, int length, const cypart_device_usb_device* device_desc) { // Maybe making this async would be better for lower end hardware... int num_bytes = 0; cypress_pipe_reset_bulk_in(handlers, get_cy_usb_info(device_desc)); int ret = cypress_bulk_in_transfer(handlers, get_cy_usb_info(device_desc), buf, length, &num_bytes); if(num_bytes != length) return LIBUSB_ERROR_INTERRUPTED; return ret; } int ReadFrameAsync(cy_device_device_handlers* handlers, uint8_t* buf, int length, const cypart_device_usb_device* device_desc, cy_async_callback_data* cb_data) { return cypress_bulk_in_async(handlers, get_cy_usb_info(device_desc), buf, length, cb_data); }