diff --git a/hal/port/unix/lt_port_unix_usb_dongle.c b/hal/port/unix/lt_port_unix_usb_dongle.c new file mode 100644 index 0000000..f48d29b --- /dev/null +++ b/hal/port/unix/lt_port_unix_usb_dongle.c @@ -0,0 +1,219 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "libtropic_common.h" +#include "libtropic_port.h" + + +#define READ_WRITE_DELAY 10 + +int fd; +const char device[] = "/dev/ttyACM0"; +uint32_t baud_rate = 115200; + +// Writes bytes to the serial port, returning 0 on success and -1 on failure. +int write_port(int fd, uint8_t * buffer, size_t size) +{ + ssize_t result = write(fd, buffer, size); + if (result != (ssize_t)size) + { + perror("failed to write to port"); + return -1; + } + return 0; +} + +// Reads bytes from the serial port. +// Returns after all the desired bytes have been read, or if there is a +// timeout or other error. +// Returns the number of bytes successfully read into the buffer, or -1 if +// there was an error reading. +ssize_t read_port(int fd, uint8_t * buffer, size_t size) +{ + size_t received = 0; + while (received < size) + { + ssize_t r = read(fd, buffer + received, size - received); + if (r < 0) + { + perror("failed to read from port"); + return -1; + } + if (r == 0) + { + // Timeout + break; + } + received += r; + } + return received; +} + +lt_ret_t lt_port_init(lt_handle_t *h) +{ + UNUSED(h); + memset(h, 0, sizeof(lt_handle_t)); + + // serialport init + fd = open(device, O_RDWR | O_NOCTTY); + if (fd == -1) + { + perror(device); + return LT_FAIL; + } + + // Flush away any bytes previously read or written. + int result = tcflush(fd, TCIOFLUSH); + if (result) + { + perror("tcflush failed"); // just a warning, not a fatal error + } + + // Get the current configuration of the serial port. + struct termios options; + result = tcgetattr(fd, &options); + if (result) + { + perror("tcgetattr failed"); + close(fd); + return LT_FAIL; + } + + // Turn off any options that might interfere with our ability to send and + // receive raw binary bytes. + options.c_iflag &= ~(INLCR | IGNCR | ICRNL | IXON | IXOFF); + options.c_oflag &= ~(ONLCR | OCRNL); + options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + + // Set up timeouts: Calls to read() will return as soon as there is + // at least one byte available or when 100 ms has passed. + options.c_cc[VTIME] = 1; + options.c_cc[VMIN] = 0; + + // This code only supports certain standard baud rates. Supporting + // non-standard baud rates should be possible but takes more work. + switch (baud_rate) + { + case 4800: cfsetospeed(&options, B4800); break; + case 9600: cfsetospeed(&options, B9600); break; + case 19200: cfsetospeed(&options, B19200); break; + case 38400: cfsetospeed(&options, B38400); break; + case 115200: cfsetospeed(&options, B115200); break; + default: + fprintf(stderr, "warning: baud rate %u is not supported, using 9600.\n", + baud_rate); + cfsetospeed(&options, B9600); + break; + } + cfsetispeed(&options, cfgetospeed(&options)); + + result = tcsetattr(fd, TCSANOW, &options); + if (result) + { + perror("tcsetattr failed"); + close(fd); + return LT_FAIL; + } + + return LT_OK; +} + +lt_ret_t lt_port_deinit(lt_handle_t *h) +{ + UNUSED(h); + close(fd); + + return LT_OK; +} + +lt_ret_t lt_port_delay (lt_handle_t *h, uint32_t wait_time_msecs) +{ + UNUSED(h); + usleep(wait_time_msecs*1000); + return LT_OK; +} + +lt_ret_t lt_port_random_bytes(uint32_t *buff, uint16_t len) { + + for(int i=0; i LT_L1_LEN_MAX) { + return LT_L1_DATA_LEN_ERROR; + } + + // Bytes from handle which are about to be sent are encoded as chars and stored here: + char buffered_chars[512] = {0}; + for(int i=0; i<(tx_data_length); i++) { + sprintf(buffered_chars + i*2, "%02X", h->l2_buff[i+offset]); // TODO make this better? + } + // Controll characters to keep CS LOW, they are expected by USB dongle + buffered_chars[tx_data_length*2] = 'x'; + buffered_chars[tx_data_length*2+1] = '\n'; + + + int ret = write_port(fd, buffered_chars, (tx_data_length*2)+2); + if(ret != 0) { + return LT_L1_SPI_ERROR; + } + + lt_port_delay(h, READ_WRITE_DELAY); + + int readed = read_port(fd, buffered_chars, (2*tx_data_length)+2); + if(readed!= ((2*tx_data_length)+2)) { + return LT_L1_SPI_ERROR; + } + + for (size_t count = 0; count < 2*tx_data_length; count++) { + sscanf(&buffered_chars[count*2], "%2hhx", &h->l2_buff[count+offset]); // TODO make this better? + } + + return LT_OK; +} diff --git a/tests/platforms/libtropic-unix-usb-dongle/CMakeLists.txt b/tests/platforms/libtropic-unix-usb-dongle/CMakeLists.txt new file mode 100644 index 0000000..6c2eb9a --- /dev/null +++ b/tests/platforms/libtropic-unix-usb-dongle/CMakeLists.txt @@ -0,0 +1,93 @@ +cmake_minimum_required(VERSION 3.21.0) + + +########################################################################### +# # +# Paths and setup # +# # +########################################################################### + +#set(CMAKE_BUILD_TYPE Debug) + +set(PATH_TREZOR_CRYPTO "../../vendor/trezor_crypto/") +set(PATH_LIBTROPIC "../../../") + + +########################################################################### +# # +# Define project's name # +# # +########################################################################### + +project(libtropic_unix_example + VERSION 0.1.0 + DESCRIPTION "Example of libtropic's usage in Unix environment" + LANGUAGES C) + + +########################################################################### +# # +# Sources defined by this project # +# # +########################################################################### + +add_executable(run main.c + ${CMAKE_CURRENT_SOURCE_DIR}/${PATH_LIBTROPIC}hal/port/unix/lt_port_unix_usb_dongle.c +) + + +########################################################################### +# # +# Define what examples will be compiled into main(). # +# If any of examples is enabled, libtropic is compiled with # +# examples exposed. # +# # +########################################################################### + +# -DLT_EX_HW_WALLET=1 +if(LT_EX_HW_WALLET) + set(LT_ADD_EXAMPLES ON) + target_compile_definitions(run PRIVATE LT_EX_HW_WALLET) +endif() +# -DLT_EX_HELLO_WORLD=1 +if(LT_EX_HELLO_WORLD) + set(LT_ADD_EXAMPLES ON) + target_compile_definitions(run PRIVATE LT_EX_HELLO_WORLD) +endif() +# -DLT_EX_TEST_REVERSIBLE=1 +if(LT_EX_TEST_REVERSIBLE) + set(LT_ADD_EXAMPLES ON) + target_compile_definitions(run PRIVATE LT_EX_TEST_REVERSIBLE) +endif() +# --DLT_EX_TEST_IREVERSIBLE=1 +if(LT_EX_TEST_IREVERSIBLE) + set(LT_ADD_EXAMPLES ON) + target_compile_definitions(run PRIVATE LT_EX_TEST_IREVERSIBLE) +endif() + +########################################################################### +# # +# Add libtropic and set it up # +# # +########################################################################### + +# Use trezor crypto as a source of backend cryptography code +set(LT_USE_TREZOR_CRYPTO ON) + +# Add path to libtropic's repository root folder +add_subdirectory(${PATH_LIBTROPIC} "libtropic") + +# Customize libtropic's compilation +target_compile_options(tropic PRIVATE -Wall) +target_compile_options(tropic PRIVATE -ffunction-sections -fdata-sections) +target_compile_options(tropic PRIVATE -Wno-implicit-function-declaration) + + +########################################################################### +# # +# Link executable # +# # +########################################################################### + +target_link_options(run PRIVATE -Wl,--gc-sections) +target_link_libraries(run PRIVATE tropic) diff --git a/tests/platforms/libtropic-unix-usb-dongle/main.c b/tests/platforms/libtropic-unix-usb-dongle/main.c new file mode 100644 index 0000000..026c75d --- /dev/null +++ b/tests/platforms/libtropic-unix-usb-dongle/main.c @@ -0,0 +1,33 @@ +/** + * @file main.c + * @author Tropic Square s.r.o. + * + * @license For the license see file LICENSE.txt file in the root directory of this source tree. + */ + +#include +#include "string.h" +#include "libtropic_examples.h" + +int main(void) +{ + // Test routines +#ifdef LT_EX_TEST_REVERSIBLE + lt_ex_test_reversible(); +#endif +#ifdef LT_EX_TEST_IREVERSIBLE + lt_ex_test_ireversible(); +#endif + + // Full examples +#ifdef LT_FEATURES_FWUPDATE + lt_ex_fwupdate(); +#endif +#ifdef LT_EX_HELLO_WORLD + /*int*/ lt_ex_hello_world(); +#endif +#ifdef LT_EX_HW_WALLET + /*int*/ lt_ex_hardware_wallet(); +#endif + +}