diff --git a/include/firmata/firmata.h b/include/firmata/firmata.h index 41f7c32..030f57a 100644 --- a/include/firmata/firmata.h +++ b/include/firmata/firmata.h @@ -24,7 +24,7 @@ #pragma once -#include "serial.h" +#include "uart.h" #define MODE_INPUT 0x00 #define MODE_OUTPUT 0x01 @@ -89,7 +89,7 @@ typedef struct s_pin { } t_pin; typedef struct s_firmata { - t_serial* serial; + mraa_uart_context uart; t_pin pins[128]; int i2cmsg[256][256]; int parse_command_len; diff --git a/include/firmata/serial.h b/include/firmata/serial.h deleted file mode 100644 index e35e273..0000000 --- a/include/firmata/serial.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation - * Copyright (c) 2015 Jules Dourlens (jdourlens@gmail.com) - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#pragma once - -#include -#include - -typedef struct s_serial { - int port_is_open; - const char* port_name; - int baud_rate; - char* error_msg; - - int port_fd; - struct termios settings_orig; - struct termios settings; - int tx; - int rx; -} t_serial; - -t_serial* serial_new(); -int serial_open(t_serial* serial, const char* name); -int serial_setBaud(t_serial* serial, int baud); -int serial_read(t_serial* serial, void* ptr, int count); -int serial_write(t_serial* serial, void* ptr, int len); -int serial_waitInput(t_serial* serial, int msec); -int serial_discardInput(t_serial* serial); -void serial_flushOutput(t_serial* serial); -int serial_setControl(t_serial* serial, int dtr, int rts); diff --git a/src/firmata/CMakeLists.txt b/src/firmata/CMakeLists.txt index 540a1af..91c4b69 100644 --- a/src/firmata/CMakeLists.txt +++ b/src/firmata/CMakeLists.txt @@ -3,7 +3,6 @@ if (FIRMATA) set (mraa_LIB_PLAT_SRCS_NOAUTO ${mraa_LIB_PLAT_SRCS_NOAUTO} ${PROJECT_SOURCE_DIR}/src/firmata/firmata.c ${PROJECT_SOURCE_DIR}/src/firmata/servo.c - ${PROJECT_SOURCE_DIR}/src/firmata/serial.c ${PROJECT_SOURCE_DIR}/src/firmata/firmata_mraa.c PARENT_SCOPE ) diff --git a/src/firmata/firmata.c b/src/firmata/firmata.c index 16b887c..e9e47f9 100644 --- a/src/firmata/firmata.c +++ b/src/firmata/firmata.c @@ -22,7 +22,6 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "firmata/serial.h" #include "firmata/firmata.h" #include @@ -33,6 +32,7 @@ t_firmata* firmata_new(const char* name) { t_firmata* res; + mraa_result_t uart_res = MRAA_ERROR_UNSPECIFIED; printf("Opening device at: %s\n", name); res = malloc(sizeof(t_firmata)); @@ -41,14 +41,20 @@ firmata_new(const char* name) return (NULL); } memset(res, 0, sizeof(*res)); - res->serial = serial_new(); - if (!res->serial) { - perror("firmata_new::Failed malloc"); - return (NULL); + + res->uart = mraa_uart_init_raw(name); + if (res->uart == NULL) { + fprintf(stderr, "UART failed to setup\n"); + return EXIT_FAILURE; } - serial_open(res->serial, name); + firmata_initPins(res); - serial_setBaud(res->serial, 57600); + + uart_res = mraa_uart_set_baudrate(res->uart, 57600); + if (uart_res != MRAA_SUCCESS) { + mraa_result_print(uart_res); + } + firmata_askFirmware(res); printf("Device opened at: %s\n", name); return (res); @@ -60,9 +66,9 @@ firmata_pull(t_firmata* firmata) uint8_t buff[FIRMATA_MSG_LEN]; int r; - r = serial_waitInput(firmata->serial, 40); + r = mraa_uart_data_available(firmata->uart, 40); if (r > 0) { - r = serial_read(firmata->serial, buff, sizeof(buff)); + r = mraa_uart_read(firmata->uart, buff, sizeof(buff)); if (r < 0) { return (0); } @@ -178,7 +184,7 @@ firmata_endParse(t_firmata* firmata) buf[len++] = 1; } firmata->isReady = 1; - serial_write(firmata->serial, buf, len); + mraa_uart_write(firmata->uart, buf, len); } else if (firmata->parse_buff[1] == FIRMATA_CAPABILITY_RESPONSE) { int pin, i, n; for (pin = 0; pin < 128; pin++) { @@ -206,7 +212,7 @@ firmata_endParse(t_firmata* firmata) buf[len++] = pin; buf[len++] = FIRMATA_END_SYSEX; } - serial_write(firmata->serial, buf, len); + mraa_uart_write(firmata->uart, buf, len); } } else if (firmata->parse_buff[1] == FIRMATA_ANALOG_MAPPING_RESPONSE) { int pin = 0; @@ -228,12 +234,12 @@ firmata_endParse(t_firmata* firmata) printf("got an i2c reply with count %d!!\n", firmata->parse_count); int addr = (firmata->parse_buff[2] & 0x7f) | ((firmata->parse_buff[3] & 0x7f) << 7); int reg = (firmata->parse_buff[4] & 0x7f) | ((firmata->parse_buff[5] & 0x7f) << 7); - int i = 6; - int ii = 0; - for (ii; ii < (firmata->parse_count - 7) / 2; ii++) { - firmata->i2cmsg[addr][reg+ii] = (firmata->parse_buff[i] & 0x7f) | ((firmata->parse_buff[i+1] & 0x7f) << 7);; - i = i+2; - } + int i = 6; + int ii = 0; + for (ii; ii < (firmata->parse_count - 7) / 2; ii++) { + firmata->i2cmsg[addr][reg+ii] = (firmata->parse_buff[i] & 0x7f) | ((firmata->parse_buff[i+1] & 0x7f) << 7);; + i = i+2; + } printf("i2c reply is %d\n", firmata->i2cmsg[addr][reg]); } return; @@ -265,7 +271,7 @@ firmata_askFirmware(t_firmata* firmata) buf[0] = FIRMATA_START_SYSEX; buf[1] = FIRMATA_REPORT_FIRMWARE; // read firmata name & version buf[2] = FIRMATA_END_SYSEX; - res = serial_write(firmata->serial, buf, 3); + res = mraa_uart_write(firmata->uart, buf, 3); return (res); } @@ -280,7 +286,7 @@ firmata_pinMode(t_firmata* firmata, int pin, int mode) buff[1] = pin; buff[2] = mode; printf("Setting pinMode at: %i with value: %i\n", pin, mode); - res = serial_write(firmata->serial, buff, 3); + res = mraa_uart_write(firmata->uart, buff, 3); return (res); } @@ -294,7 +300,7 @@ firmata_analogWrite(t_firmata* firmata, int pin, int value) buff[0] = 0xE0 | pin; buff[1] = value & 0x7F; buff[2] = (value >> 7) & 0x7F; - res = serial_write(firmata->serial, buff, 3); + res = mraa_uart_write(firmata->uart, buff, 3); return (res); } @@ -308,7 +314,7 @@ firmata_analogRead(t_firmata *firmata, int pin) buff[0] = FIRMATA_REPORT_ANALOG | pin; buff[1] = value; printf("192 == %d, pinval == %d, pin %d", buff[0], buff[1], pin); - res = serial_write(firmata->serial, buff, 2); + res = mraa_uart_write(firmata->uart, buff, 2); return res; } @@ -336,6 +342,6 @@ firmata_digitalWrite(t_firmata* firmata, int pin, int value) buff[0] = FIRMATA_DIGITAL_MESSAGE | port_num; buff[1] = port_val & 0x7F; buff[2] = (port_val >> 7) & 0x7F; - res = serial_write(firmata->serial, buff, 3); + res = mraa_uart_write(firmata->uart, buff, 3); return (res); } diff --git a/src/firmata/firmata_mraa.c b/src/firmata/firmata_mraa.c index e6f9ed6..e7355af 100644 --- a/src/firmata/firmata_mraa.c +++ b/src/firmata/firmata_mraa.c @@ -28,7 +28,6 @@ #include "mraa_internal.h" #include "firmata/firmata_mraa.h" #include "firmata/firmata.h" -#include "firmata/serial.h" static t_firmata* firmata_dev; static pthread_t thread_id; @@ -43,7 +42,7 @@ mraa_firmata_i2c_init_bus_replace(mraa_i2c_context dev) buff[1] = FIRMATA_I2C_CONFIG; buff[2] = delay & 0xFF, (delay >> 8) & 0xFF; buff[3] = FIRMATA_END_SYSEX; - serial_write(firmata_dev->serial, buff, 4); + mraa_uart_write(firmata_dev->uart, buff, 4); return MRAA_SUCCESS; } @@ -80,9 +79,11 @@ mraa_firmata_send_i2c_read_req(mraa_i2c_context dev, int length) buffer[5] = (length >> 7) & 0x7f; buffer[6] = FIRMATA_END_SYSEX; - if (serial_write(firmata_dev->serial, buffer, 7) != 7) { + mraa_result_t res = mraa_uart_write(firmata_dev->uart, buffer, 7); + if (res != MRAA_SUCCESS) { free(buffer); - return MRAA_ERROR_INVALID_RESOURCE; + mraa_result_print(res); + return res; } // this needs a lock :) @@ -112,9 +113,11 @@ mraa_firmata_send_i2c_read_cont_req(mraa_i2c_context dev, uint8_t command, int l buffer[7] = (length >> 7) & 0x7f; buffer[8] = FIRMATA_END_SYSEX; - if (serial_write(firmata_dev->serial, buffer, 9) != 9) { + mraa_result_t res = mraa_uart_write(firmata_dev->uart, buffer, 9); + if (res != MRAA_SUCCESS) { free(buffer); - return MRAA_ERROR_INVALID_RESOURCE; + mraa_result_print(res); + return res; } // this needs a lock :) @@ -218,7 +221,7 @@ mraa_firmata_i2c_write(mraa_i2c_context dev, const uint8_t* data, int bytesToWri ii = ii+2; } buffer[buffer_size-1] = FIRMATA_END_SYSEX; - serial_write(firmata_dev->serial, buffer, buffer_size); + mraa_uart_write(firmata_dev->uart, buffer, buffer_size); return MRAA_SUCCESS; } @@ -233,7 +236,7 @@ mraa_firmata_i2c_write_byte(mraa_i2c_context dev, uint8_t data) buffer[4] = data & 0x7F; buffer[5] = (data >> 7) & 0x7F; buffer[6] = FIRMATA_END_SYSEX; - serial_write(firmata_dev->serial, buffer, 7); + mraa_uart_write(firmata_dev->uart, buffer, 7); return MRAA_SUCCESS; } @@ -250,7 +253,7 @@ mraa_firmata_i2c_write_byte_data(mraa_i2c_context dev, const uint8_t data, const buffer[6] = data & 0x7F; buffer[7] = (data >> 7) & 0x7F; buffer[8] = FIRMATA_END_SYSEX; - serial_write(firmata_dev->serial, buffer, 9); + mraa_uart_write(firmata_dev->uart, buffer, 9); return MRAA_SUCCESS; } diff --git a/src/firmata/serial.c b/src/firmata/serial.c deleted file mode 100644 index ee61ce6..0000000 --- a/src/firmata/serial.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (c) 2016 Intel Corporation - * Copyright (c) 2015 Jules Dourlens (jdourlens@gmail.com) - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "firmata/serial.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -t_serial* -serial_new() -{ - t_serial* res; - - res = malloc(sizeof(t_serial)); - if (!res) { - return (NULL); - } - res->port_is_open = 0; - res->baud_rate = 57600; - res->tx = 0; - res->rx = 0; - return (res); -} - -int -serial_open(t_serial* serial, const char* name) -{ - struct serial_struct kernel_serial_settings; - int bits; - - serial->port_fd = open(name, O_RDWR | O_NOCTTY | O_NONBLOCK); - if (serial->port_fd < 0) { - if (errno == EACCES) { - perror("Unable to access, insufficient permission"); - } else if (errno == EISDIR) { - perror("Unable to open, Object is a directory, not a serial port"); - } else if (errno == ENODEV || errno == ENXIO) { - perror("Unable to open, Serial port hardware not installed"); - } else if (errno == ENOENT) { - perror("Unable to open, Device name does not exist"); - } else { - perror("Unable to open: Unknown error."); - } - return (-1); - } - memset(&(serial->settings), 0, sizeof(struct termios)); -#if 0 - if (ioctl(serial->port_fd, TIOCMGET, &bits) < 0) { - close(serial->port_fd); - perror("Unable to query serial port signals"); - return (-1); - } - bits &= ~(TIOCM_DTR | TIOCM_RTS); - if (ioctl(serial->port_fd, TIOCMSET, &bits) < 0) { - close(serial->port_fd); - perror("Unable to control serial port signals"); - return (-1); - } - if (tcgetattr(serial->port_fd, &(serial->settings_orig)) != 0) { - close(serial->port_fd); - perror("Unable to query serial port settings (perhaps not a serial port)"); - return (-1); - } - memset(&(serial->settings), 0, sizeof(struct termios)); - serial->settings.c_iflag = IGNBRK | IGNPAR; - serial->settings.c_cflag = CS8 | CREAD | HUPCL | CLOCAL; - serial_setBaud(serial, serial->baud_rate); - if (ioctl(serial->port_fd, TIOCGSERIAL, &kernel_serial_settings) == 0) { - kernel_serial_settings.flags |= ASYNC_LOW_LATENCY; - ioctl(serial->port_fd, TIOCSSERIAL, &kernel_serial_settings); - } - tcflush(serial->port_fd, TCIFLUSH); -#endif - serial->port_name = name; - serial->port_is_open = 1; - return 0; -} - -int -serial_setBaud(t_serial* serial, int baud) -{ - speed_t spd; - switch (baud) { - case 230400: - spd = B230400; - break; - case 115200: - spd = B115200; - break; - case 57600: - spd = B57600; - break; - case 38400: - spd = B38400; - break; - case 19200: - spd = B19200; - break; - case 9600: - spd = B9600; - break; - case 4800: - spd = B4800; - break; - case 2400: - spd = B2400; - break; - case 1800: - spd = B1800; - break; - case 1200: - spd = B1200; - break; - case 600: - spd = B600; - break; - case 300: - spd = B300; - break; - case 200: - spd = B200; - break; - case 150: - spd = B150; - break; - case 134: - spd = B134; - break; - case 110: - spd = B110; - break; - case 75: - spd = B75; - break; - case 50: - spd = B50; - break; -#ifdef B460800 - case 460800: - spd = B460800; - break; -#endif -#ifdef B500000 - case 500000: - spd = B500000; - break; -#endif -#ifdef B576000 - case 576000: - spd = B576000; - break; -#endif -#ifdef B921600 - case 921600: - spd = B921600; - break; -#endif -#ifdef B1000000 - case 1000000: - spd = B1000000; - break; -#endif -#ifdef B1152000 - case 1152000: - spd = B1152000; - break; -#endif -#ifdef B1500000 - case 1500000: - spd = B1500000; - break; -#endif -#ifdef B2000000 - case 2000000: - spd = B2000000; - break; -#endif -#ifdef B2500000 - case 2500000: - spd = B2500000; - break; -#endif -#ifdef B3000000 - case 3000000: - spd = B3000000; - break; -#endif -#ifdef B3500000 - case 3500000: - spd = B3500000; - break; -#endif -#ifdef B4000000 - case 4000000: - spd = B4000000; - break; -#endif -#ifdef B7200 - case 7200: - spd = B7200; - break; -#endif -#ifdef B14400 - case 14400: - spd = B14400; - break; -#endif -#ifdef B28800 - case 28800: - spd = B28800; - break; -#endif -#ifdef B76800 - case 76800: - spd = B76800; - break; -#endif - default: { - return -1; - } - } - cfsetospeed(&(serial->settings), spd); - cfsetispeed(&(serial->settings), spd); - if (tcsetattr(serial->port_fd, TCSANOW, &(serial->settings)) < 0) - return (-1); - return (0); -} - -int -serial_read(t_serial* serial, void* ptr, int count) -{ - int n, bits; - - if (!serial->port_is_open) - return (-1); - if (count <= 0) - return (0); - n = read(serial->port_fd, ptr, count); - if (n < 0 && (errno == EAGAIN || errno == EINTR)) - return (0); - if (n == 0 && ioctl(serial->port_fd, TIOCMGET, &bits) < 0) - return (-99); - serial->rx += n; - return (n); -} - -int -serial_write(t_serial* serial, void* ptr, int len) -{ - //printf("Write %d\n", len); - write(serial->port_fd, (const char *)ptr, len); - return (len); -} - -int -serial_waitInput(t_serial* serial, int msec) -{ - if (!serial->port_is_open) - return -1; - fd_set rfds; - struct timeval tv; - tv.tv_sec = msec / 1000; - tv.tv_usec = (msec % 1000) * 1000; - FD_ZERO(&rfds); - FD_SET(serial->port_fd, &rfds); - return (select(serial->port_fd + 1, &rfds, NULL, NULL, &tv)); -} - -int -serial_discardInput(t_serial* serial) -{ - if (!serial->port_is_open) - return; - // does this really work properly (and is it thread safe) on Linux?? - tcflush(serial->port_fd, TCIFLUSH); -} - -void -serial_flushOutput(t_serial* serial) -{ - if (!serial->port_is_open) - return; - tcdrain(serial->port_fd); -} - -int -serial_setControl(t_serial* serial, int dtr, int rts) -{ - if (!serial->port_is_open) - return -1; - int bits; - if (ioctl(serial->port_fd, TIOCMGET, &bits) < 0) - return -1; - if (dtr == 1) { - bits |= TIOCM_DTR; - } else if (dtr == 0) { - bits &= ~TIOCM_DTR; - } - if (rts == 1) { - bits |= TIOCM_RTS; - } else if (rts == 0) { - bits &= ~TIOCM_RTS; - } - if (ioctl(serial->port_fd, TIOCMSET, &bits) < 0) - return -1; - ; - return (0); -}