ref: f9995781ebfd63edfa89088134d806434736ac30
parent: 8e0bad662f99eebde515dbc63c5670b0eb0e87e9
author: Jonne Kokkonen <jonne.kokkonen@gmail.com>
date: Tue Apr 27 06:19:11 EDT 2021
use libserialport for serial operations
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@
DEPS = serial.h slip.h command.h write.h render.h input.h stealth57_ttf.h
#Any special libraries you are using in your project (e.g. -lbcm2835 -lrt `pkg-config --libs gtk+-3.0` ), or leave blank
-INCLUDES = -lSDL2_ttf
+INCLUDES = -lSDL2_ttf -lserialport
#Set any compiler flags you want to use (e.g. -I/usr/include/somefolder `pkg-config --cflags gtk+-3.0` ), or leave blank
CFLAGS = `sdl2-config --libs --cflags` -march=native -Wall -O2 -pipe -I.
--- a/main.c
+++ b/main.c
@@ -1,6 +1,7 @@
#include <SDL2/SDL.h>
#include <SDL2/SDL_timer.h>
#include <errno.h>
+#include <libserialport.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
@@ -14,6 +15,9 @@
#include "slip.h"
#include "write.h"
+// maximum amount of bytes to read from the serial in one read()
+#define serial_read_size 1024
+
uint8_t run = 1;
// Handles CTRL+C / SIGINT
@@ -21,13 +25,10 @@
int main(int argc, char *argv[]) {- // maximum amount of bytes to read from the serial in one read()
- const int serial_read_size = 1024;
-
// allocate memory for serial buffer
- uint8_t serial_buf[serial_read_size];
+ uint8_t *serial_buf = malloc(serial_read_size);
- static uint8_t slip_buffer[1024]; // SLIP command buffer
+ static uint8_t slip_buffer[serial_read_size]; // SLIP command buffer
// settings for the slip packet handler
static const slip_descriptor_s slip_descriptor = {@@ -40,18 +41,14 @@
static slip_handler_s slip;
signal(SIGINT, intHandler);
+ signal(SIGTERM, intHandler);
slip_init(&slip, &slip_descriptor);
- // open device
- char *portname;
- if (argc > 1) {- portname = argv[1];
- } else {- portname = "/dev/ttyACM0";
- }
- int port = init_serial(portname);
- if (port == -1)
+ struct sp_port *port;
+
+ port = init_serial();
+ if (port == NULL)
return -1;
if (enable_and_reset_display(port) == -1)
@@ -68,10 +65,10 @@
// main loop
while (run) {- // read data from serial port
- size_t bytes_read = read(port, &serial_buf, sizeof(serial_buf));
- if (bytes_read == -1) {- fprintf(stderr, "Error %d reading serial: %s\n", errno, strerror(errno));
+ size_t bytes_read =
+ sp_nonblocking_read(port, serial_buf, serial_read_size);
+ if (bytes_read < 0) {+ fprintf(stderr, "Error %zu reading serial. \n", bytes_read);
run = 0;
}
if (bytes_read > 0) {@@ -98,7 +95,7 @@
if (input.value != prev_input) {prev_input = input.value;
if (input.value != 0) {- send_msg_keyjazz(port, input.value, 64);
+ send_msg_keyjazz(port, input.value, 0xFF);
} else {send_msg_keyjazz(port, 0, 0);
}
@@ -123,7 +120,9 @@
close_input();
close_renderer();
disconnect(port);
- close(port);
+ sp_close(port);
+ sp_free_port(port);
+ free(serial_buf);
return 0;
}
\ No newline at end of file
--- a/serial.c
+++ b/serial.c
@@ -1,83 +1,98 @@
-#include <errno.h>
-#include <fcntl.h>
+#include <libserialport.h>
#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
+#include <stdlib.h>
#include "serial.h"
-/* This code is originally by wallyk,
-https://stackoverflow.com/questions/6947413/how-to-open-read-and-write-from-serial-port-in-c
-with small tweaks to the blocking settings. Big thanks to the
-original author. */
-static int set_interface_attribs(int fd, int speed, int parity) {- struct termios tty;
- if (tcgetattr(fd, &tty) != 0) {- fprintf(stderr, "error %d from tcgetattr", errno);
- return -1;
- }
+// Helper function for error handling
+static int check(enum sp_return result);
- cfsetospeed(&tty, speed);
- cfsetispeed(&tty, speed);
+static int detect_m8_serial_device(struct sp_port *port) {+ // Check the connection method - we want USB serial devices
+ enum sp_transport transport = sp_get_port_transport(port);
- tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
- // disable IGNBRK for mismatched speed tests; otherwise receive break
- // as \000 chars
- tty.c_iflag &= ~IGNBRK; // disable break processing
- tty.c_lflag = 0; // no signaling chars, no echo,
- // no canonical processing
- tty.c_oflag = 0; // no remapping, no delays
- tty.c_cc[VMIN] = 0; // read doesn't block
- tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
+ if (transport == SP_TRANSPORT_USB) {+ // Get the USB vendor and product IDs.
+ int usb_vid, usb_pid;
+ sp_get_port_usb_vid_pid(port, &usb_vid, &usb_pid);
- tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
-
- tty.c_cflag |= (CLOCAL | CREAD); // ignore modem controls,
- // enable reading
- tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
- tty.c_cflag |= parity;
- tty.c_cflag &= ~CSTOPB;
- tty.c_cflag &= ~CRTSCTS;
-
- if (tcsetattr(fd, TCSANOW, &tty) != 0) {- fprintf(stderr, "Error %d from tcsetattr\n", errno);
- return -1;
+ if (usb_vid == 0x16C0 && usb_pid == 0x048A)
+ return 1;
}
+
return 0;
}
-static void set_blocking(int fd, int should_block) {+struct sp_port *init_serial() {+ /* A pointer to a null-terminated array of pointers to
+ * struct sp_port, which will contain the ports found.*/
+ struct sp_port *m8_port = NULL;
+ struct sp_port **port_list;
- struct termios tty;
- memset(&tty, 0, sizeof tty);
- if (tcgetattr(fd, &tty) != 0) {- fprintf(stderr, "Error %d from tggetattr\n", errno);
- return;
+ fprintf(stderr, "Looking for USB serial devices.\n");
+
+ /* Call sp_list_ports() to get the ports. The port_list
+ * pointer will be updated to refer to the array created. */
+ enum sp_return result = sp_list_ports(&port_list);
+
+ if (result != SP_OK) {+ fprintf(stderr, "sp_list_ports() failed!\n");
+ abort();
}
- // non-blocking VMIN and VTIME should both be 0
- tty.c_cc[VMIN] = should_block ? 1 : 0;
- tty.c_cc[VTIME] = should_block ? 5 : 0;
+ /* Iterate through the ports. When port_list[i] is NULL
+ * this indicates the end of the list. */
+ for (int i = 0; port_list[i] != NULL; i++) {+ struct sp_port *port = port_list[i];
- if (tcsetattr(fd, TCSANOW, &tty) != 0)
- fprintf(stderr, "Error %d setting term attributes\n", errno);
-}
+ if (detect_m8_serial_device(port)) {+ fprintf(stderr, "Found M8 in %s.\n", sp_get_port_name(port));
+ sp_copy_port(port, &m8_port);
+ }
+ }
-int init_serial(char *portname) {+ sp_free_port_list(port_list);
- int fd = open(portname, O_RDWR);
+ if (m8_port != NULL) {+ // Open the serial port and configure it
+ fprintf(stderr, "Opening port.\n");
+ check(sp_open(m8_port, SP_MODE_READ_WRITE));
- if (fd < 0) {- fprintf(stderr, "Error %d opening %s: %s\n", errno, portname,
- strerror(errno));
- return -1;
+ check(sp_set_baudrate(m8_port, 115200));
+ check(sp_set_bits(m8_port, 8));
+ check(sp_set_parity(m8_port, SP_PARITY_NONE));
+ check(sp_set_stopbits(m8_port, 1));
+ check(sp_set_flowcontrol(m8_port, SP_FLOWCONTROL_NONE));
+ } else {+ fprintf(stderr, "Cannot find a M8.\n");
}
- set_interface_attribs(fd, __MAX_BAUD,
- 0); // set speed to max bps, 8n1 (no parity)
- set_blocking(fd, 0); // set no blocking
+ return (m8_port);
+}
- return fd;
+// Helper function for error handling.
+static int check(enum sp_return result) {+
+ char *error_message;
+
+ switch (result) {+ case SP_ERR_ARG:
+ fprintf(stderr,"Error: Invalid argument.\n");
+ abort();
+ case SP_ERR_FAIL:
+ error_message = sp_last_error_message();
+ fprintf(stderr,"Error: Failed: %s\n", error_message);
+ sp_free_error_message(error_message);
+ abort();
+ case SP_ERR_SUPP:
+ fprintf(stderr,"Error: Not supported.\n");
+ abort();
+ case SP_ERR_MEM:
+ fprintf(stderr,"Error: Couldn't allocate memory.\n");
+ abort();
+ case SP_OK:
+ default:
+ return result;
+ }
}
\ No newline at end of file
--- a/serial.h
+++ b/serial.h
@@ -1,6 +1,8 @@
#ifndef _SERIAL_H_
#define _SERIAL_H_
-int init_serial(char *portname);
+#include <libserialport.h>
+
+struct sp_port *init_serial();
#endif
\ No newline at end of file
--- a/write.c
+++ b/write.c
@@ -1,28 +1,26 @@
-#include <errno.h>
+#include <libserialport.h>
#include <stdint.h>
#include <stdio.h>
-#include <string.h>
#include <unistd.h>
-int enable_and_reset_display(int port) {+int enable_and_reset_display(struct sp_port *port) {uint8_t buf[2];
- ssize_t bytes_written;
+ int result;
fprintf(stderr, "Enabling and resetting M8 display\n");
buf[0] = 0x44;
- bytes_written = write(port, buf, 1);
- if (bytes_written == -1) {- fprintf(stderr, "Error code %d: %s\n", errno, strerror(errno));
- return -1;
+ result = sp_blocking_write(port, buf, 1, 5);
+ if (result != 1) {+ fprintf(stderr, "Error enabling M8 display, code %d", result);
}
+
usleep(500);
buf[0] = 0x45;
buf[1] = 0x52;
- bytes_written = write(port, buf, 2);
- if (bytes_written == -1) {- fprintf(stderr, "Error code %d: %s\n", errno, strerror(errno));
- return -1;
+ result = sp_blocking_write(port, buf, 2, 5);
+ if (result != 2) {+ fprintf(stderr, "Error resetting M8 display, code %d", result);
}
sleep(1);
@@ -29,40 +27,27 @@
return 1;
}
-int disconnect(int port) {+int disconnect(struct sp_port *port) { char buf[1] = {'D'};- size_t nbytes = 1;
- ssize_t bytes_written;
+ int result;
fprintf(stderr, "Disconnecting M8\n");
- bytes_written = write(port, buf, nbytes);
- if (bytes_written != nbytes) {- fprintf(stderr,
- "Error disconnecting, expected to write %zu bytes, %zd written\n",
- nbytes, bytes_written);
-
- if (bytes_written == -1) {- fprintf(stderr, "Error code %d: %s\n", errno, strerror(errno));
- }
+ result = sp_blocking_write(port, buf, 1, 5);
+ if (result != 1) {+ fprintf(stderr, "Error sending disconnect, code %d", result);
return -1;
}
return 1;
}
-int send_msg_controller(int port, uint8_t input) {+int send_msg_controller(struct sp_port *port, uint8_t input) { char buf[2] = {'C',input};size_t nbytes = 2;
- ssize_t bytes_written;
- bytes_written = write(port, buf, nbytes);
- if (bytes_written != nbytes) {- fprintf(stderr,
- "Error sending controller message, expected to write %zu bytes, %zd written\n",
- nbytes, bytes_written);
-
- if (bytes_written == -1) {- fprintf(stderr, "Error code %d: %s\n", errno, strerror(errno));
- }
+ int result;
+ result = sp_blocking_write(port, buf, nbytes, 5);
+ if (result != nbytes) {+ fprintf(stderr, "Error sending input, code %d", result);
return -1;
}
return 1;
@@ -69,23 +54,17 @@
}
-int send_msg_keyjazz(int port, uint8_t note, uint8_t velocity) {+int send_msg_keyjazz(struct sp_port *port, uint8_t note, uint8_t velocity) {if (velocity > 64)
velocity = 64;
char buf[3] = {'K',note,velocity};size_t nbytes = 3;
- ssize_t bytes_written;
- bytes_written = write(port, buf, nbytes);
- if (bytes_written != nbytes) {- fprintf(stderr,
- "Error sending keyjazz message, expected to write %zu bytes, %zd written\n",
- nbytes, bytes_written);
-
- if (bytes_written == -1) {- fprintf(stderr, "Error code %d: %s\n", errno, strerror(errno));
- }
+ int result;
+ result = sp_blocking_write(port, buf, nbytes,5);
+ if (result != nbytes) {+ fprintf(stderr, "Error sending keyjazz, code %d", result);
return -1;
}
- return 1;
+ return 1;
}
\ No newline at end of file
--- a/write.h
+++ b/write.h
@@ -2,10 +2,11 @@
#define WRITE_H_
#include <stdint.h>
-int enable_and_reset_display(int port);
-int disconnect(int port);
-int send_msg_controller(int port, uint8_t input);
-int send_msg_keyjazz(int port, uint8_t note, uint8_t velocity);
+#include <libserialport.h>
+int enable_and_reset_display(struct sp_port *port);
+int disconnect(struct sp_port *port);
+int send_msg_controller(struct sp_port *port, uint8_t input);
+int send_msg_keyjazz(struct sp_port *port, uint8_t note, uint8_t velocity);
#endif
\ No newline at end of file
--
⑨