Skip to content

Commit

Permalink
Implement Serial I/O for macOS, too
Browse files Browse the repository at this point in the history
This reuses most of the Linux version. I guess we should reintegrate that at some point, but let's make sure it works on both operating systems before we take that step.
  • Loading branch information
yoe committed Jun 28, 2019
1 parent eda5a6f commit 3cc85ac
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 0 deletions.
4 changes: 4 additions & 0 deletions beidmw.xcodeproj/project.pbxproj
Expand Up @@ -115,6 +115,7 @@
6CAFE1D921DF86E40078C7E2 /* pkcs11t.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CAFE1D621DF86E40078C7E2 /* pkcs11t.h */; };
6CAFE1DA21DF86E40078C7E2 /* pkcs11f.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CAFE1D721DF86E40078C7E2 /* pkcs11f.h */; };
6CAFE1DC21DF889B0078C7E2 /* unix.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CAFE1DB21DF889B0078C7E2 /* unix.h */; };
6CBD45C922C609760078C7E2 /* serial_macos.c in Sources */ = {isa = PBXBuildFile; fileRef = 6CBD45C822C609760078C7E2 /* serial_macos.c */; };
6CD1B8C421A5A6470005F6E9 /* state_error.png in Resources */ = {isa = PBXBuildFile; fileRef = 6CD1B8C221A5A6470005F6E9 /* state_error.png */; };
6CD1B8C521A5A6470005F6E9 /* state_noreaders.png in Resources */ = {isa = PBXBuildFile; fileRef = 6CD1B8C321A5A6470005F6E9 /* state_noreaders.png */; };
6CD1B8C621A5A6510005F6E9 /* certificate_bad.png in Resources */ = {isa = PBXBuildFile; fileRef = 6CD1B8BD21A5A61A0005F6E9 /* certificate_bad.png */; };
Expand Down Expand Up @@ -451,6 +452,7 @@
6CAFE1D621DF86E40078C7E2 /* pkcs11t.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pkcs11t.h; sourceTree = "<group>"; };
6CAFE1D721DF86E40078C7E2 /* pkcs11f.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pkcs11f.h; sourceTree = "<group>"; };
6CAFE1DB21DF889B0078C7E2 /* unix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unix.h; sourceTree = "<group>"; };
6CBD45C822C609760078C7E2 /* serial_macos.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = serial_macos.c; path = tests/unit/serial_macos.c; sourceTree = "<group>"; };
6CD1B8BD21A5A61A0005F6E9 /* certificate_bad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = certificate_bad.png; path = "plugins_tools/eid-viewer/resources/certificate_bad.png"; sourceTree = SOURCE_ROOT; };
6CD1B8BF21A5A61A0005F6E9 /* certificate_large.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = certificate_large.png; path = "plugins_tools/eid-viewer/resources/certificate_large.png"; sourceTree = SOURCE_ROOT; };
6CD1B8C021A5A61A0005F6E9 /* certificate_checked.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = certificate_checked.png; path = "plugins_tools/eid-viewer/resources/certificate_checked.png"; sourceTree = SOURCE_ROOT; };
Expand Down Expand Up @@ -815,6 +817,7 @@
65EABAEE1C621F3D00034337 /* labels.h */,
65EABAEF1C621F3D00034337 /* utftranslate.h */,
6CDC503C220858980078C7E2 /* readdata_limited.c */,
6CBD45C822C609760078C7E2 /* serial_macos.c */,
65F3F0211BE236680073F2A3 /* readdata_sequence.c */,
8B8B71581B74CCA300D8910E /* sign_state.c */,
8B07D1011B21CEB80033CD62 /* wrong_init.c */,
Expand Down Expand Up @@ -1498,6 +1501,7 @@
6536232E19A7E92B00D46ECB /* mechlist.c in Sources */,
6536233A19A7E92B00D46ECB /* threads.c in Sources */,
6536232519A7E92B00D46ECB /* decode_photo.c in Sources */,
6CBD45C922C609760078C7E2 /* serial_macos.c in Sources */,
8B8B71591B74CCA300D8910E /* sign_state.c in Sources */,
6536233D19A7E93A00D46ECB /* main.c in Sources */,
6536233519A7E92B00D46ECB /* sign.c in Sources */,
Expand Down
128 changes: 128 additions & 0 deletions tests/unit/serial_macos.c
@@ -0,0 +1,128 @@
#include "serial_io.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <fcntl.h>
#include <termios.h>
#include <unistd.h>

#include <sys/ioctl.h>
#include <sys/select.h>

char *default_card_port = "/dev/tty.usbmodem14141";
char *default_usb_port = "/dev/tty.usbmodem14131";

struct tstserial {
int fd;
char buf[200];
int data_start;
int data_len;
};

Serial* serial_open(char *portname) {
Serial *rv = calloc(sizeof(struct tstserial), 1);
if(!rv) {
perror("malloc");
return NULL;
}

rv->fd = open(portname, O_RDWR | O_NONBLOCK | O_NOCTTY);

if(rv->fd < 0) {
perror("open robot");
free(rv);
return NULL;
}
if(ioctl(rv->fd, TIOCEXCL) == -1) {
perror("ioctl TIOCEXCL");
return NULL;
}
struct termios ios;
tcgetattr(rv->fd, &ios);
cfsetispeed(&ios, B9600);
cfsetospeed(&ios, B9600);
ios.c_cflag &= ~PARENB & ~CSTOPB & ~CSIZE;
ios.c_cflag |= CLOCAL | CREAD | CS8 | CRTSCTS;
ios.c_lflag |= ICANON;
tcsetattr(rv->fd, TCSANOW, &ios);
tcflow(rv->fd, TCOON);

return rv;
}

void serial_close(Serial *port) {
close(port->fd);
free(port);
}

bool wait_for_data(Serial *port, int time) {
struct timeval tv;

fd_set rb;
FD_ZERO(&rb);
FD_SET(port->fd, &rb);
tv.tv_sec = time;
tv.tv_usec = 0;
select(port->fd+1, &rb, NULL, NULL, &tv);
return FD_ISSET(port->fd, &rb) ? true : false;
}

bool serial_has_data(Serial *port) {
return wait_for_data(port, 0);
}

char *serial_read_line(Serial *port) {
if(!port->data_len) {
port->data_start = 0;
} else {
size_t len = strcspn(port->buf + port->data_start, "\r\n");
if(len == 0) {
port->data_len--;
port->data_start++;
return serial_read_line(port);
}
if(len < port->data_len) {
char *ptr = port->buf + port->data_start;
port->data_len -= len + 1;
port->data_start += len + 1;
return strndup(ptr, len);
}
}
if(!serial_has_data(port)) {
wait_for_data(port, 2);
return serial_read_line(port);
}
ssize_t len = read(port->fd, port->buf + port->data_start + port->data_len, sizeof(port->buf) - port->data_start - port->data_len - 1);
if(len < 0) {
perror("read");
return NULL;
}
port->buf[port->data_start + port->data_len + len] = '\0';
port->data_len += len;
return serial_read_line(port);
}

void serial_free_line(char *line) {
free(line);
}

void serial_clear(Serial *port) {
while(serial_has_data(port)) {
char buf[80];
if(read(port->fd, buf, 79) < 0) {
perror("read");
exit(EXIT_FAILURE);
}
}
port->data_len = port->data_start = 0;
}

bool serial_writec(Serial *port, char c) {
return (write(port->fd, &c, 1) == 1) ? true : false;
}

void sr_wait(unsigned int millis) {
usleep(millis * 1000);
}

0 comments on commit 3cc85ac

Please sign in to comment.