summary refs log tree commit diff
path: root/bin
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2018-07-31 00:00:38 -0400
committerJune McEnroe <june@causal.agency>2018-07-31 00:00:38 -0400
commitc39316749e9224e441ee41a27de613e5fbcb781b (patch)
treeac55bcc05bfb633f096a02b0bcfd11e8e4775a26 /bin
parentUse color numbers in colorscheme (diff)
downloadsrc-c39316749e9224e441ee41a27de613e5fbcb781b.tar.gz
src-c39316749e9224e441ee41a27de613e5fbcb781b.zip
Add msr606
Everything "works" but I'm not able to round-trip data. It seems like
the documentation lies about the format in some way.
Diffstat (limited to 'bin')
-rw-r--r--bin/msr606.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/bin/msr606.c b/bin/msr606.c
new file mode 100644
index 00000000..1f2acbf4
--- /dev/null
+++ b/bin/msr606.c
@@ -0,0 +1,196 @@
+/* Copyright (C) 2018  Curtis McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <termios.h>
+#include <unistd.h>
+
+static int tty = -1;
+
+static void ttyWrite(const uint8_t *ptr, size_t size) {
+	ssize_t ret = write(tty, ptr, size);
+	if (ret < 0) err(EX_IOERR, "write");
+}
+static void ttyRead(uint8_t *ptr, size_t size) {
+	while (size) {
+		ssize_t ret = read(tty, ptr, size);
+		if (ret < 0) err(EX_IOERR, "read");
+		ptr += ret;
+		size -= ret;
+	}
+}
+
+static void reset(void) {
+	uint8_t buf[] = { 0x1B, 'a' };
+	ttyWrite(buf, 2);
+}
+
+static void test(void) {
+	uint8_t buf[3] = { 0x1B, 'e' };
+	ttyWrite(buf, 2);
+	ttyRead(buf, 2);
+	if (buf[1] != 'y') errx(EX_PROTOCOL, "test fail %hhX", buf[1]);
+
+	buf[1] = 0x87;
+	ttyWrite(buf, 2);
+	ttyRead(buf, 2);
+	if (buf[1] != '0') errx(EX_PROTOCOL, "ram fail %hhX", buf[1]);
+
+	buf[1] = 't';
+	ttyWrite(buf, 2);
+	ttyRead(buf, 3);
+	printf("model: %c%c\n", buf[1], buf[2]);
+
+	buf[1] = 'v';
+	ttyWrite(buf, 2);
+	ttyRead(buf, 2);
+	printf("firmware: %hhu\n", buf[1]);
+}
+
+static void sensorTest(void) {
+	uint8_t buf[] = { 0x1B, 0x86 };
+	ttyWrite(buf, 2);
+	ttyRead(buf, 2);
+	if (buf[1] != '0') errx(EX_PROTOCOL, "sensor fail %hhX", buf[1]);
+}
+
+static char led;
+static void setLed(void) {
+	uint8_t buf[2] = { 0x1B };
+	switch (led) {
+		break; case 'a': buf[1] = 0x82;
+		break; case 'g': buf[1] = 0x83;
+		break; case 'y': buf[1] = 0x84;
+		break; case 'r': buf[1] = 0x85;
+		break; default:  buf[1] = 0x81;
+	}
+	ttyWrite(buf, 2);
+}
+
+static void status(void) {
+	uint8_t buf[2];
+	ttyRead(buf, 2);
+	switch (buf[1]) {
+		break; case '0': return;
+		break; case '1': errx(EX_DATAERR, "read/write error");
+		break; case '2': errx(EX_DATAERR, "command format error");
+		break; case '4': errx(EX_DATAERR, "invalid command");
+		break; case '9': errx(EX_DATAERR, "invalid card swipe");
+		break; default:  errx(EX_PROTOCOL, "status fail %hhX", buf[1]);
+	}
+}
+
+static void readCard(void) {
+	uint8_t buf[] = { 0x1B, 'r' };
+	ttyWrite(buf, 2);
+	ttyRead(buf, 2);
+	if (buf[1] != 's') errx(EX_PROTOCOL, "read fail %hhX", buf[1]);
+	for (;;) {
+		ttyRead(buf, 1);
+		if (buf[0] == '?') {
+			ttyRead(buf, 1);
+			if (buf[0] == 0x1C) break;
+			printf("?");
+		} else {
+			printf("%c", buf[0]);
+		}
+	}
+	status();
+}
+
+static void writeCard(void) {
+	uint8_t buf[] = { 0x1B, 'w', 0x1B, 's' };
+	ttyWrite(buf, 4);
+	ssize_t size;
+	while (0 < (size = read(STDIN_FILENO, buf, 1))) {
+		ttyWrite(buf, 1);
+	}
+	if (size < 0) err(EX_IOERR, "(stdin)");
+	buf[0] = '?';
+	buf[1] = 0x1C;
+	ttyWrite(buf, 2);
+	status();
+}
+
+static char erase;
+static void eraseCard(void) {
+	uint8_t buf[] = { 0x1B, 'c', erase - '0' };
+	ttyWrite(buf, 3);
+	ttyRead(buf, 2);
+	if (buf[1] != '0') errx(EX_DATAERR, "erase fail %hhX", buf[1]);
+}
+
+static void setHiCo(void) {
+	uint8_t buf[] = { 0x1B, 'x' };
+	ttyWrite(buf, 2);
+	ttyRead(buf, 2);
+	if (buf[1] != '0') errx(EX_PROTOCOL, "hi-co fail %hhX", buf[1]);
+}
+static void setLoCo(void) {
+	uint8_t buf[] = { 0x1B, 'y' };
+	ttyWrite(buf, 2);
+	ttyRead(buf, 2);
+	if (buf[1] != '0') errx(EX_PROTOCOL, "lo-co fail %hhX", buf[1]);
+}
+static void getCo(void) {
+	uint8_t buf[] = { 0x1B, 'd' };
+	ttyWrite(buf, 2);
+	ttyRead(buf, 2);
+	if (buf[1] == 'h') printf("hi-co\n");
+	else if (buf[1] == 'l') printf("lo-co\n");
+	else errx(EX_PROTOCOL, "get co fail %hhX", buf[1]);
+}
+
+int main(int argc, char *argv[]) {
+	const char *file = "/dev/ttyUSB0";
+	void (*func)(void) = test;
+
+	int opt;
+	while (0 < (opt = getopt(argc, argv, "L:RTce:f:hlrtw"))) {
+		switch (opt) {
+			break; case 'L': led = optarg[0]; func = setLed;
+			break; case 'R': func = reset;
+			break; case 'T': func = sensorTest;
+			break; case 'c': func = getCo;
+			break; case 'e': erase = optarg[0]; func = eraseCard;
+			break; case 'f': file = optarg;
+			break; case 'h': func = setHiCo;
+			break; case 'l': func = setLoCo;
+			break; case 'r': func = readCard;
+			break; case 't': func = test;
+			break; case 'w': func = writeCard;
+			break; default: return EX_USAGE;
+		}
+	}
+
+	tty = open(file, O_RDWR);
+	if (tty < 0) err(EX_NOINPUT, "%s", file);
+
+	struct termios attr;
+	int error = tcgetattr(tty, &attr);
+	if (error) err(EX_IOERR, "tcgetattr");
+
+	cfmakeraw(&attr);
+	error = tcsetattr(tty, TCSANOW, &attr);
+	if (error) err(EX_IOERR, "tcsetattr");
+
+	func();
+}