1use std::io;
2use std::io::prelude::*;
3use unix_socket::UnixStream;
4
5use self::Command::*;
6
7mod raw_cmd {
8 pub const NOP: u8 = 0x00;
9 pub const FLUSH: u8 = 0x01;
10 pub const ECHO: u8 = 0x02;
11 pub const GPIO_IN: u8 = 0x03;
12 pub const GPIO_HIGH: u8 = 0x04;
13 pub const GPIO_LOW: u8 = 0x05;
14 pub const GPIO_CFG: u8 = 0x06;
15 pub const GPIO_WAIT: u8 = 0x07;
16 pub const GPIO_INT: u8 = 0x08;
17 pub const ENABLE_SPI: u8 = 0x0A;
18 pub const DISABLE_SPI: u8 = 0x0B;
19 pub const ENABLE_I2C: u8 = 0x0C;
20 pub const DISABLE_I2C: u8 = 0x0D;
21 pub const ENABLE_UART: u8 = 0x0E;
22 pub const DISABLE_UART: u8 = 0x0F;
23 pub const TX: u8 = 0x10;
24 pub const RX: u8 = 0x11;
25 pub const TXRX: u8 = 0x12;
26 pub const START: u8 = 0x13;
27 pub const STOP: u8 = 0x14;
28 pub const GPIO_TOGGLE: u8 = 0x15;
29 pub const GPIO_INPUT: u8 = 0x16;
30 pub const GPIO_RAW_READ: u8 = 0x17;
31 pub const ANALOG_READ: u8 = 0x18;
32 pub const ANALOG_WRITE: u8 = 0x19;
33 pub const GPIO_PULL: u8 = 0x1A;
34 pub const PWM_DUTY_CYCLE: u8 = 0x1B;
35 pub const PWM_PERIOD: u8 = 0x1C;
36}
37
38#[derive(Debug, Copy, Clone, PartialEq, Eq)]
39pub enum Command<'a> {
40 Nop,
41 Flush,
42
43 GpioIn(u8),
44 GpioHigh(u8),
45 GpioLow(u8),
46 GpioToggle(u8),
47 GpioWait(u8),
48 GpioInt(u8),
49 GpioCfg(u8),
50 GpioInput(u8),
51 GpioRawRead(u8),
52 GpioPull(u8),
53 AnalogRead(u8),
54
55 AnalogWrite{ pin: u8, value: u8 },
56
57 EnableSpi{ mode: u8, freq: u8, div: u8 },
58 DisableSpi,
59 EnableI2c{ baud: u8 },
60 DisableI2c,
61 EnableUart{ baud: u8, mode: u8 },
62 DisableUart,
63
64 Start(u8),
65 Stop,
66
67 PwmDutyCycle{ pin: u8, duty_cycle: u16 },
68 PwmPeriod{ prescalar: u8, tcc_id: u8, period: u16 },
69
70 Rx(u8),
71 Echo(&'a [u8]),
72 Tx(&'a [u8]),
73 TxRx(&'a [u8]),
74}
75
76pub mod reply {
79 pub struct Reply(pub u8);
80
81 pub const ACK: Reply = Reply(0x80);
82 pub const NACK: Reply = Reply(0x81);
83 pub const HIGH: Reply = Reply(0x82);
84 pub const LOW: Reply = Reply(0x83);
85 pub const DATA: Reply = Reply(0x84);
86
87 pub const MIN_ASYNC: Reply = Reply(0xA0);
88 pub const ASYNC_PIN_CHANGE_N: Reply = Reply(0xC0);
90 pub const ASYNC_UART_RX: Reply = Reply(0xD0);
91}
92
93pub struct PortSocket {
95 _socket_path: String,
96 socket: UnixStream,
97}
98
99impl PortSocket {
100 pub fn new(path: &str) -> PortSocket {
101 let socket = UnixStream::connect(path).unwrap();
103
104 PortSocket {
105 _socket_path: path.to_string(),
106 socket: socket
107 }
108 }
109
110 pub fn raw_write(&mut self, buffer: &[u8]) -> io::Result<()> {
111 self.socket.write_all(buffer)
112 }
113
114 pub fn write_command(&mut self, cmd: Command) -> io::Result<()> {
115 let socket = &mut self.socket;
116 match cmd {
117 Nop => socket.write_all(&[raw_cmd::NOP]),
118 Flush => socket.write_all(&[raw_cmd::FLUSH]),
119 Rx(len) => socket.write_all(&[raw_cmd::RX, len]),
120 Echo(data) => {
121 assert!(data.len() <= u8::max_value() as usize);
122 try!(socket.write_all(&[raw_cmd::ECHO, data.len() as u8]));
123 socket.write_all(data)
124 },
125 Tx(data) => {
126 for slice in data.chunks(u8::max_value() as usize) {
127 try!(socket.write_all(&[raw_cmd::TX, slice.len() as u8]));
128 try!(socket.write_all(slice));
129 }
130 Ok(())
131 }
132 TxRx(data) => {
133 assert!(data.len() <= u8::max_value() as usize);
134 try!(socket.write_all(&[raw_cmd::TXRX, data.len() as u8]));
135 socket.write_all(data)
136 }
137 GpioIn(pin) => socket.write_all(&[raw_cmd::GPIO_IN, pin]),
138 GpioHigh(pin) => socket.write_all(&[raw_cmd::GPIO_HIGH, pin]),
139 GpioLow(pin) => socket.write_all(&[raw_cmd::GPIO_LOW, pin]),
140 GpioToggle(pin) => socket.write_all(&[raw_cmd::GPIO_TOGGLE, pin]),
141 GpioWait(pin) => socket.write_all(&[raw_cmd::GPIO_WAIT, pin]),
142 GpioInt(pin) => socket.write_all(&[raw_cmd::GPIO_INT, pin]),
143 GpioCfg(pin) => socket.write_all(&[raw_cmd::GPIO_CFG, pin]),
144 GpioInput(pin) => socket.write_all(&[raw_cmd::GPIO_INPUT, pin]),
145 GpioRawRead(pin) => socket.write_all(&[raw_cmd::GPIO_RAW_READ, pin]),
146 GpioPull(pin) => socket.write_all(&[raw_cmd::GPIO_PULL, pin]),
147 AnalogRead(pin) => socket.write_all(&[raw_cmd::ANALOG_READ, pin]),
148
149 AnalogWrite{ pin, value } => socket.write_all(&[raw_cmd::ANALOG_WRITE, pin, value]),
150
151 EnableSpi{ mode, freq, div } => socket.write_all(&[raw_cmd::ENABLE_SPI, mode, freq, div]),
152 DisableSpi => socket.write_all(&[raw_cmd::DISABLE_SPI]),
153 EnableI2c{ baud } => socket.write_all(&[raw_cmd::ENABLE_I2C, baud]),
154 DisableI2c => socket.write_all(&[raw_cmd::DISABLE_I2C]),
155 EnableUart{ baud, mode } => socket.write_all(&[raw_cmd::ENABLE_UART, baud, mode]),
156 DisableUart => socket.write_all(&[raw_cmd::DISABLE_UART]),
157
158 Start(addr) => socket.write_all(&[raw_cmd::START, addr]),
159 Stop => socket.write_all(&[raw_cmd::STOP]),
160
161 PwmDutyCycle{ pin, duty_cycle } => socket.write_all(&[raw_cmd::PWM_DUTY_CYCLE, pin, (duty_cycle >> 8) as u8, (duty_cycle & 0xFF) as u8]),
162 PwmPeriod{ prescalar, tcc_id, period } => socket.write_all(&[raw_cmd::PWM_PERIOD, prescalar << 4 | tcc_id & 0x7, (period >> 8) as u8, (period & 0xf) as u8]),
163 }
164 }
165
166 pub fn read_exact(&mut self, buffer: &mut [u8]) -> io::Result<()> {
167 self.socket.read_exact(buffer)
168 }
169}