From 186049b3ed33f025eeb87eb34c19a28e1d5ba70a Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Tue, 2 Oct 2012 01:05:51 +0200 Subject: restructure code, switch from GTK to Web based UI - move barcode generation scripts into generation/ - move code to src/ - remove database analysis from invoice/graph - put database creation sql files into sql/ - remove glade builder file - add new templates/ directory, which contains files used by the Web-UI --- src/device.vala | 280 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+) create mode 100644 src/device.vala (limited to 'src/device.vala') diff --git a/src/device.vala b/src/device.vala new file mode 100644 index 0000000..5d7fc09 --- /dev/null +++ b/src/device.vala @@ -0,0 +1,280 @@ +/* Copyright 2012, Sebastian Reichel + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +public class Device { + private Posix.termios newtio; + private Posix.termios restoretio; + public int fd=-1; + private IOChannel io_read; + public int byterate; + private File lockfile; + + public signal void received_barcode(string barcode); + + public Device(string device, int rate, int bits, int stopbits) { + Posix.speed_t baudrate = Posix.B9600; + + try { + /* check lock file */ + lockfile = File.new_for_path("/var/lock/LCK.." + device.replace("/dev/", "")); + if(lockfile.query_exists()) { + int pid = -1; + uint8[] data; + if(lockfile.load_contents(null, out data, null)) { + pid = int.parse((string) data); + } else { + error("Can't read lock file!\n"); + } + + if(Posix.kill(pid, 0) == 0) { + error("serial device is locked!\n"); + } + } + + var pid = "%d\n".printf(Posix.getpid()); + lockfile.replace_contents(pid.data, null, false, FileCreateFlags.NONE, null); + + fd = Posix.open(device, Posix.O_RDWR /*| Posix.O_NONBLOCK*/); + + if(fd < 0) { + fd = -1; + lockfile.delete(); + error("Could not open device!\n"); + } + + } catch(Error e) { + error("Could not create lock file: %s!\n", e.message); + } + + + Posix.tcflush(fd, Posix.TCIOFLUSH); + + Posix.tcgetattr(fd, out restoretio); + + /* apply settings */ + switch(rate) { + case 300: + baudrate = Posix.B300; + break; + case 600: + baudrate = Posix.B600; + break; + case 1200: + baudrate = Posix.B1200; + break; + case 2400: + baudrate = Posix.B2400; + break; + case 4800: + baudrate = Posix.B4800; + break; + case 9600: + baudrate = Posix.B9600; + break; + case 19200: + baudrate = Posix.B19200; + break; + case 38400: + baudrate = Posix.B38400; + break; + case 57600: + baudrate = Posix.B57600; + break; + case 115200: + baudrate = Posix.B115200; + break; + case 230400: + baudrate = Posix.B230400; + break; + default: + /* not supported */ + rate = 9600; + break; + } + + Posix.cfsetospeed(ref newtio, baudrate); + Posix.cfsetispeed(ref newtio, baudrate); + + switch(bits) { + case 5: + newtio.c_cflag = (newtio.c_cflag & ~Posix.CSIZE) | Posix.CS5; + break; + case 6: + newtio.c_cflag = (newtio.c_cflag & ~Posix.CSIZE) | Posix.CS6; + break; + case 7: + newtio.c_cflag = (newtio.c_cflag & ~Posix.CSIZE) | Posix.CS7; + break; + case 8: + default: + newtio.c_cflag = (newtio.c_cflag & ~Posix.CSIZE) | Posix.CS8; + break; + } + + newtio.c_cflag |= Posix.CLOCAL | Posix.CREAD; + + newtio.c_cflag &= ~(Posix.PARENB | Posix.PARODD); + + /* TODO: parity */ + + newtio.c_cflag &= ~Linux.Termios.CRTSCTS; + + if(stopbits == 2) + newtio.c_cflag |= Posix.CSTOPB; + else + newtio.c_cflag &= ~Posix.CSTOPB; + + newtio.c_iflag = Posix.IGNBRK; + + newtio.c_lflag = 0; + newtio.c_oflag = 0; + + newtio.c_cc[Posix.VTIME]=1; + newtio.c_cc[Posix.VMIN]=1; + + newtio.c_lflag &= ~(Posix.ECHONL|Posix.NOFLSH); + + int mcs=0; + Posix.ioctl(fd, Linux.Termios.TIOCMGET, out mcs); + mcs |= Linux.Termios.TIOCM_RTS; + Posix.ioctl(fd, Linux.Termios.TIOCMSET, out mcs); + + Posix.tcsetattr(fd, Posix.TCSANOW, newtio); + + this.byterate = rate/bits; + + try { + io_read = new IOChannel.unix_new(fd); + io_read.set_line_term("\r\n", 2); + if(io_read.set_encoding(null) != IOStatus.NORMAL) + error("Failed to set encoding"); + if(!(io_read.add_watch(IOCondition.IN | IOCondition.HUP, device_read) != 0)) { + error("Could not bind IOChannel"); + } + } catch(IOChannelError e) { + error("IOChannel: %s", e.message); + } + } + + ~Device() { + /* restore old tty config */ + Posix.tcsetattr(fd, Posix.TCSANOW, restoretio); + + /* close file */ + Posix.close(fd); + + /* remove lock */ + lockfile.delete(); + } + + private bool device_read(IOChannel gio, IOCondition cond) { + IOStatus ret; + string msg; + size_t len, term_char; + + if((cond & IOCondition.HUP) == IOCondition.HUP) + error("Lost device"); + + try { + ret = gio.read_line(out msg, out len, out term_char); + msg = msg[0:(long)term_char]; + + if(msg.has_prefix("USER ") || msg.has_prefix("STOCK") || msg.has_prefix("AMOUNT ")) { + if(!check_code39_checksum(msg)) + received_barcode("SCANNER RETURNED INCORRECT DATA"); + else {/* remove checksum */ + msg = msg[0:-1]; + received_barcode(msg); + } + } + else + received_barcode(msg); + } + catch(IOChannelError e) { + stderr.printf("IOChannel Error: %s", e.message); + return false; + } + catch(ConvertError e) { + stderr.printf("Convert Error: %s", e.message); + return false; + } + return true; + } + + private ssize_t write(void *buf, size_t count) { + ssize_t size = Posix.write(fd, buf, count); + return size; + } + + private bool check_code39_checksum(string data) { + int result = 0; + + for(int i = 0; i= '0' && data[i] <= '9') + result += data[i] - '0'; + else if(data[i] >= 'A' && data[i] <= 'Z') + result += data[i] - 'A' + 10; + else + switch(data[i]) { + case '-': + result += 36; break; + case '.': + result += 37; break; + case ' ': + result += 38; break; + case '$': + result += 39; break; + case '/': + result += 40; break; + case '+': + result += 41; break; + case '%': + result += 42; break; + default: + /* invalid character */ + return false; + } + + result %= 43; + } + + if(result < 10) + result = result + '0'; + else if(result < 36) + result = result - 10 + 'A'; + else + switch(result) { + case 36: result = '-'; break; + case 37: result = '.'; break; + case 38: result = ' '; break; + case 39: result = '$'; break; + case 40: result = '/'; break; + case 41: result = '+'; break; + case 42: result = '%'; break; + } + + return (data[data.length-1] == result); + } + + /** + * @param duration duration of the blink in 0.1 seconds + */ + public void blink(uint duration) { + uint size = byterate/10 * duration; + var msg = new uint8[size]; + Posix.memset(msg, 0xFF, msg.length); + this.write(msg, msg.length); + } +} -- cgit v1.2.3