-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
26cb320
commit 373de8f
Showing
13 changed files
with
403 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Used by "mix format" | ||
[ | ||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# The directory Mix will write compiled artifacts to. | ||
/_build/ | ||
|
||
# If you run "mix test --cover", coverage assets end up here. | ||
/cover/ | ||
|
||
# The directory Mix downloads your dependencies sources to. | ||
/deps/ | ||
|
||
# Where third-party dependencies like ExDoc output generated docs. | ||
/doc/ | ||
|
||
# Ignore .fetch files in case you like to edit your project deps locally. | ||
/.fetch | ||
|
||
# If the VM crashes, it generates a dump, let's ignore it too. | ||
erl_crash.dump | ||
|
||
# Also ignore archive artifacts (built via "mix archive.build"). | ||
*.ez | ||
|
||
# Ignore package tarball (built via "mix hex.build"). | ||
ash_serial-*.tar | ||
|
||
# Temporary files, for example, from tests. | ||
/tmp/ | ||
|
||
priv | ||
Makefile.*.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
|
||
MIX_ENV ?= dev | ||
MIX_TARGET ?= host | ||
UNAME := $(shell uname -s | tr '[:upper:]' '[:lower:]') | ||
|
||
SRCDIR = src | ||
PRIVDIR = priv | ||
OUTDIR = $(PRIVDIR)/$(MIX_TARGET) | ||
LOCBIN = ~/.local/bin | ||
|
||
#-pedantic -Wall allow unused during debugging | ||
#-Werror remove to run on macos with lots of warnings | ||
PORT_TARGET = $(OUTDIR)/ash_serial | ||
PORT_SOURCES = $(SRCDIR)/*.c | ||
PORT_HEADERS = $(SRCDIR)/*.h | ||
PORT_CFLAGS = -g0 -O3 -pedantic -Wall -Wextra -D_XOPEN_SOURCE=700 | ||
PORT_LDFLAGS = -fPIC -Wl,-rpath,'$$ORIGIN' -L$(OUTDIR) -lpthread | ||
|
||
.PHONY: all pre clean reset post | ||
|
||
all: pre $(PORT_TARGET) post | ||
|
||
pre: | ||
env | sort > Makefile.$(UNAME).$(MIX_TARGET).env | ||
[ -d $(OUTDIR) ] || mkdir -p $(OUTDIR) | ||
echo $(MIX_TARGET) > $(PRIVDIR)/target | ||
|
||
post: | ||
rm -fR $(OUTDIR)/*.dSYM | ||
|
||
clean: | ||
rm -fr $(PRIVDIR)/target | ||
rm -fr $(OUTDIR) | ||
|
||
reset: clean | ||
rm -fr _build deps | ||
rm Makefile.*.env | ||
|
||
$(PORT_TARGET): $(PORT_SOURCES) $(PORT_HEADERS) Makefile $(FONTS) $(IMAGES) $(TARGET_CAIRO) | ||
$(CC) $(PORT_CFLAGS) $(PORT_SOURCES) $(PORT_LDFLAGS) -o $@ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
# ash_serial | ||
# Ash.Serial | ||
|
||
- https://github.com/samuelventura/sport | ||
- https://github.com/samuelventura/sniff |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
defmodule AshSerial do | ||
@moduledoc """ | ||
Documentation for `AshSerial`. | ||
""" | ||
|
||
@doc """ | ||
Hello world. | ||
## Examples | ||
iex> AshSerial.hello() | ||
:world | ||
""" | ||
def hello do | ||
:world | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
defmodule AshSerial.MixProject do | ||
use Mix.Project | ||
|
||
def project do | ||
[ | ||
app: :ash_serial, | ||
version: "0.1.0", | ||
elixir: "~> 1.13", | ||
make_clean: ["clean"], | ||
# make_args: ["-dn"], | ||
compilers: [:elixir_make | Mix.compilers()], | ||
start_permanent: Mix.env() == :prod, | ||
deps: deps() | ||
] | ||
end | ||
|
||
def application do | ||
[ | ||
extra_applications: [:logger] | ||
] | ||
end | ||
|
||
defp deps do | ||
[ | ||
{:elixir_make, "~> 0.6", runtime: false} | ||
] | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
%{ | ||
"castore": {:hex, :castore, "0.1.20", "62a0126cbb7cb3e259257827b9190f88316eb7aa3fdac01fd6f2dfd64e7f46e9", [:mix], [], "hexpm", "a020b7650529c986c454a4035b6b13a328e288466986307bea3aadb4c95ac98a"}, | ||
"elixir_make": {:hex, :elixir_make, "0.7.3", "c37fdae1b52d2cc51069713a58c2314877c1ad40800a57efb213f77b078a460d", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "24ada3e3996adbed1fa024ca14995ef2ba3d0d17b678b0f3f2b1f66e6ce2b274"}, | ||
"nerves": {:hex, :nerves, "1.9.1", "09cfd3589af81c4b1ac35179aee5f6d94bde36548a905c2d4d4efa9ff311222e", [:make, :mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "011409116923e1dbab250a6dc241ab529790163233c44e374ff352af72d09a56"}, | ||
"nerves_system_br": {:hex, :nerves_system_br, "1.20.6", "6622ee4230e968a95716105518bbd7ef569ac82b44e9114cf6a78a1ddca65455", [:mix], [], "hexpm", "ca187a129288156a1e5fb4f34d393aeddb7580091f41aefb82dbed6a4e378748"}, | ||
"nerves_system_rpi3": {:hex, :nerves_system_rpi3, "1.20.2", "3a43b8333b733e7a9f19b2eaa984bd0f33aa1fca6b8595f4a439eb32482c5ed0", [:mix], [{:nerves, "~> 1.5.4 or ~> 1.6.0 or ~> 1.7.15 or ~> 1.8", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_system_br, "1.20.6", [hex: :nerves_system_br, repo: "hexpm", optional: false]}, {:nerves_toolchain_armv7_nerves_linux_gnueabihf, "~> 1.6.0", [hex: :nerves_toolchain_armv7_nerves_linux_gnueabihf, repo: "hexpm", optional: false]}], "hexpm", "0c3b1526e99e84ed05ddaadab629aeed172f40ed06ef59960a3f199a1f9deb8f"}, | ||
"nerves_system_rpi4": {:hex, :nerves_system_rpi4, "1.20.2", "db83189a20bbdb439311308c0a344587ddc9b8f295041b458a558bda0922a694", [:mix], [{:nerves, "~> 1.5.4 or ~> 1.6.0 or ~> 1.7.15 or ~> 1.8", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_system_br, "1.20.6", [hex: :nerves_system_br, repo: "hexpm", optional: false]}, {:nerves_toolchain_aarch64_nerves_linux_gnu, "~> 1.6.0", [hex: :nerves_toolchain_aarch64_nerves_linux_gnu, repo: "hexpm", optional: false]}], "hexpm", "942333f7754d9b9a34372cf0f1c92a195cb6fae120770569da64dc65f52ebf68"}, | ||
"nerves_system_x86_64": {:hex, :nerves_system_x86_64, "1.20.3", "c011857f01d8659f9aef2f3ef344651f115347fd07a260ff9f5e280a52017155", [:mix], [{:nerves, "~> 1.5.4 or ~> 1.6.0 or ~> 1.7.15 or ~> 1.8", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_system_br, "1.20.6", [hex: :nerves_system_br, repo: "hexpm", optional: false]}, {:nerves_toolchain_x86_64_nerves_linux_musl, "~> 1.6.0", [hex: :nerves_toolchain_x86_64_nerves_linux_musl, repo: "hexpm", optional: false]}], "hexpm", "2fc00a72c0f1c61b858c20e006caa32cbc1e26a769f20aabb1444817819251c2"}, | ||
"nerves_toolchain_aarch64_nerves_linux_gnu": {:hex, :nerves_toolchain_aarch64_nerves_linux_gnu, "1.6.1", "2ddc1aecb55b55e1cf18b7252b8074418c1b7dd5497e1e6a167b5a9fb40955a9", [:mix], [{:nerves, "~> 1.4", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_toolchain_ctng, "~> 1.9.0", [hex: :nerves_toolchain_ctng, repo: "hexpm", optional: false]}], "hexpm", "57ed1c2df89c7425aadfb18c8e7da6b9d1be9ffeafa1d54061cc8abe6e5e0e4c"}, | ||
"nerves_toolchain_armv7_nerves_linux_gnueabihf": {:hex, :nerves_toolchain_armv7_nerves_linux_gnueabihf, "1.6.1", "4014bc32142ef980e39af90e1377747095f3f3f8517e41815a23638ef1711702", [:mix], [{:nerves, "~> 1.0", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_toolchain_ctng, "~> 1.9.0", [hex: :nerves_toolchain_ctng, repo: "hexpm", optional: false]}], "hexpm", "20a529ce1ab54677f121ac97333cc6b7c32f75ebb4b83cee7e0934867d61bbb5"}, | ||
"nerves_toolchain_ctng": {:hex, :nerves_toolchain_ctng, "1.9.3", "60e87fde05988c4264babc8d68a9221c7b8fe5dc195b7d1526f29b8e626c735c", [:mix], [{:nerves, "~> 1.0", [hex: :nerves, repo: "hexpm", optional: false]}], "hexpm", "2b6edb0687b7f78d3fa49958d759f647e351b23c1f59f637c617a6dc179994ae"}, | ||
"nerves_toolchain_x86_64_nerves_linux_musl": {:hex, :nerves_toolchain_x86_64_nerves_linux_musl, "1.6.1", "3e10d1c8e848afe4c7ea506d89f0a3ea12d63c4e91c6ea6bbc1e458c0ef6f940", [:mix], [{:nerves, "~> 1.0", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_toolchain_ctng, "~> 1.9.0", [hex: :nerves_toolchain_ctng, repo: "hexpm", optional: false]}], "hexpm", "8453041055bc2271279674fe284b9e093a1e8bddf931a8502a88afce43c578b2"}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#include "main.h" | ||
|
||
#define DATA_LEN 256 | ||
|
||
//ash_serial /dev/ttyUSB0 8N1 9600 | ||
int main(int argc, char *argv[]) | ||
{ | ||
UNUSED(argc); | ||
Serial serial = {0}; | ||
serial.path = argv[1]; | ||
serial.config = argv[2]; | ||
serial.speed = atoi(argv[3]); | ||
serial_open(&serial); | ||
if (serial.error != NULL) | ||
{ | ||
ash_crash(serial.error); | ||
} | ||
char* data[DATA_LEN]; | ||
struct pollfd fds[2]; | ||
fds[0].fd = 0; | ||
fds[0].events = POLLIN; | ||
fds[1].fd = serial.fd; | ||
fds[1].events = POLLIN; | ||
while(1) { | ||
int r = poll(fds, 2, -1); | ||
if (r < 0) ash_crash("events poll"); | ||
if (fds[0].revents & POLLIN) { | ||
int rn = read(0, data, DATA_LEN); | ||
if (rn <= 0) break; | ||
int wn = write(serial.fd, data, rn); | ||
if (wn != rn) ash_crash("fds[0] wn %d != rn %d", wn, rn); | ||
} | ||
if (fds[1].revents & POLLIN) { | ||
int rn = read(serial.fd, data, DATA_LEN); | ||
if (rn <= 0) break; | ||
int wn = write(1, data, rn); | ||
if (wn != rn) ash_crash("fds[1] wn %d != rn %d", wn, rn); | ||
} | ||
} | ||
exit(1); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#ifndef __MAIN_H__ | ||
#define __MAIN_H__ | ||
|
||
#include <stdarg.h> | ||
#include <stdio.h> | ||
#include <errno.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <unistd.h> | ||
#include <time.h> | ||
#include <math.h> | ||
#include <pthread.h> | ||
#include <sys/time.h> | ||
#include <sys/types.h> | ||
#include <sys/ioctl.h> | ||
#include <termios.h> | ||
#include <fcntl.h> | ||
#include <poll.h> | ||
|
||
#include <stdbool.h> | ||
#include <stdint.h> | ||
|
||
#define UNUSED(x) (void)(x) | ||
#define UNUSED2(x,y) UNUSED(x);UNUSED(y); | ||
#define UNUSED3(x,y,z) UNUSED(x);UNUSED(y);UNUSED(z); | ||
// #define MAX(x, y) ((x)>(y)?(x):(y)) | ||
|
||
void ash_debug(const char* fmt, ...); | ||
void ash_crash(const char* fmt, ...); | ||
|
||
// #define __TRACE_ENABLED__ | ||
|
||
#ifdef __TRACE_ENABLED__ | ||
|
||
#define ash_trace(...) ash_debug(__VA_ARGS__) | ||
#define ash_trace_every() ash_trace("%s:%s tid:%ul", __FILE__, __func__, pthread_self()); | ||
#define ash_trace_once() static bool _##__func__ = false; \ | ||
if (!_##__func__) ash_trace_every(); \ | ||
_##__func__ = true; | ||
|
||
#else | ||
|
||
#define ash_trace(...) | ||
#define ash_trace_every() | ||
#define ash_trace_once() | ||
|
||
#endif | ||
|
||
typedef struct { | ||
int fd; | ||
int speed; | ||
struct termios fdt; | ||
const char* error; | ||
const char *path; | ||
const char *config; // 8N1 | 7E1 | 7O1 | ||
} Serial; | ||
|
||
void ash_debug(const char* fmt, ...); | ||
void ash_crash(const char* fmt, ...); | ||
|
||
int serial_baud(int speed); | ||
void serial_open(Serial *serial); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
#include "main.h" | ||
|
||
int serial_baud(int speed) | ||
{ | ||
switch (speed) { | ||
case 50: return B50; | ||
case 75: return B75; | ||
case 110: return B110; | ||
case 134: return B134; | ||
case 150: return B150; | ||
case 200: return B200; | ||
case 300: return B300; | ||
case 600: return B600; | ||
case 1200: return B1200; | ||
case 1800: return B1800; | ||
case 2400: return B2400; | ||
case 4800: return B4800; | ||
case 9600: return B9600; | ||
case 19200: return B19200; | ||
case 38400: return B38400; | ||
case 57600: return B57600; | ||
case 115200: return B115200; | ||
case 230400: return B230400; | ||
case 460800: return B460800; | ||
case 500000: return B500000; | ||
case 576000: return B576000; | ||
case 921600: return B921600; | ||
case 1000000: return B1000000; | ||
case 1152000: return B1152000; | ||
case 1500000: return B1500000; | ||
case 2000000: return B2000000; | ||
case 2500000: return B2500000; | ||
case 3000000: return B3000000; | ||
case 3500000: return B3500000; | ||
case 4000000: return B4000000; | ||
default: return -1; | ||
} | ||
} | ||
|
||
void serial_open(Serial *serial) | ||
{ | ||
struct termios *fdt = &serial->fdt; | ||
memset(fdt, 0, sizeof(struct termios)); | ||
serial->fd = open(serial->path, O_RDWR | O_NOCTTY); | ||
if (serial->fd < 0) { | ||
serial->error = "open failed"; | ||
return; | ||
} | ||
if (isatty(serial->fd) < 0) { | ||
serial->error = "isatty failed"; | ||
return; | ||
} | ||
if (tcgetattr(serial->fd, fdt) < 0) { | ||
serial->error = "tcgetattr failed"; | ||
return; | ||
} | ||
|
||
fdt->c_cflag |= CLOCAL | CREAD; | ||
fdt->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); | ||
fdt->c_iflag &= ~(INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY); | ||
fdt->c_oflag &= ~(ONLCR | OCRNL | OPOST); | ||
|
||
int baud = serial_baud(serial->speed); | ||
if (baud > 0) { | ||
cfsetispeed(fdt, baud); | ||
cfsetospeed(fdt, baud); | ||
} else { | ||
serial->error = "Invalid speed"; | ||
return; | ||
} | ||
|
||
// config {8,7}{N,E,O}{1,2} | ||
switch (serial->config[0]) { | ||
case '8': | ||
fdt->c_cflag &= ~CSIZE; | ||
fdt->c_cflag |= CS8; | ||
break; | ||
case '7': | ||
fdt->c_cflag &= ~CSIZE; | ||
fdt->c_cflag |= CS7; | ||
break; | ||
default: | ||
serial->error = "Invalid databits"; | ||
return; | ||
} | ||
switch (serial->config[1]) { | ||
case 'N': | ||
fdt->c_cflag &= ~PARENB; | ||
break; | ||
case 'E': | ||
fdt->c_cflag |= PARENB; | ||
fdt->c_cflag &= ~PARODD; | ||
fdt->c_iflag |= INPCK; | ||
fdt->c_iflag |= ISTRIP; | ||
break; | ||
case 'O': | ||
fdt->c_cflag |= PARENB; | ||
fdt->c_cflag |= PARODD; | ||
fdt->c_iflag |= INPCK; | ||
fdt->c_iflag |= ISTRIP; | ||
break; | ||
default: | ||
serial->error = "Invalid parity"; | ||
return; | ||
} | ||
switch (serial->config[2]) { | ||
case '1': | ||
fdt->c_cflag &= ~CSTOPB; | ||
break; | ||
case '2': | ||
fdt->c_cflag |= CSTOPB; | ||
break; | ||
default: | ||
serial->error = "Invalid stopbits"; | ||
return; | ||
} | ||
|
||
// http://unixwiz.net/techtips/termios-vmin-vtime.html | ||
// blocks until 1 char arrives. | ||
fdt->c_cc[VMIN] = 1; | ||
fdt->c_cc[VTIME] = 0; | ||
|
||
if (tcsetattr(serial->fd, TCSANOW, fdt) < 0) { | ||
serial->error = "tcsetattr failed"; | ||
return; | ||
} | ||
} |
Oops, something went wrong.