summaryrefslogtreecommitdiffstats
path: root/hw/i2c-device.vala
blob: b6d285cabcda7b2da70cfe6210901caf12d9965f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/* Copyright 2012, Sebastian Reichel <sre@ring0.de>
 *
 * 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 errordomain I2CError {
	IO_ERROR,
	ERRNO,
}

public class I2CDevice : Device {
	private int fd;

	public void setup(uint8 dev, uint8 addr) throws I2CError {
		string file = "/dev/i2c-%u".printf(dev);
		fd = Posix.open(file, Posix.O_RDWR);

		if(fd < 0)
			throw new I2CError.IO_ERROR("Could not open device!");

		setup_address(addr);
	}

	~I2CDevice() {
		Posix.close(fd);
	}

	protected void setup_address(uint8 addr) throws I2CError {
		if(Posix.ioctl(fd, Linux.I2C.SLAVE, addr) < 0)
			throw new I2CError.IO_ERROR("Could not seek to I2C device 0x%02x!", addr);
	}

	protected void write_byte(uint8 byte) throws I2CError {
		if(Linux.I2C.SMBUS.write_byte(fd, byte) < 0) {
			throw new I2CError.ERRNO("Could not write to I2C device: %s!", Posix.strerror(Posix.errno));
		}
	}

	protected uint8 read_byte() throws I2CError {
		int rc = Linux.I2C.SMBUS.read_byte(fd);
		if(rc < 0)
			throw new I2CError.ERRNO("Could not read from I2C device: %s!", Posix.strerror(Posix.errno));
		return (uint8) rc;
	}

	protected uint8 get_byte(uint8 addr) throws I2CError {
		int rc = Linux.I2C.SMBUS.read_word_data(fd, addr);
		if(rc < 0)
			throw new I2CError.ERRNO("Could not get byte %d from I2C device: %s!", addr, Posix.strerror(Posix.errno));
		return (uint8) rc;
	}

	protected void set_byte(uint8 addr, uint8 val) throws I2CError {
		int rc = Linux.I2C.SMBUS.write_word_data(fd, addr, val);
		if(rc < 0)
			throw new I2CError.ERRNO("Could not set byte %d to %d from I2C device: %s!", addr, val, Posix.strerror(Posix.errno));
	}

	protected uint16 get_big_word(uint8 addr) throws I2CError {
		int rc = Linux.I2C.SMBUS.read_word_data(fd, addr);
		if(rc < 0)
			throw new I2CError.ERRNO("Could get word %d from I2C device: %s!", addr, Posix.strerror(Posix.errno));
		return uint16.from_big_endian((uint16) rc);
	}

	protected uint16 get_little_word(uint8 addr) throws I2CError {
		int rc = Linux.I2C.SMBUS.read_word_data(fd, addr);
		if(rc < 0)
			throw new I2CError.ERRNO("Could get word %d from I2C device: %s!", addr, Posix.strerror(Posix.errno));
		return uint16.from_little_endian((uint16) rc);
	}

	protected uint8[] get_block(uint8 addr, uint8 size) throws I2CError {
		uint8[] data = new uint8[size];
		int rc = Linux.I2C.SMBUS.read_i2c_block_data(fd, addr, data);
		if(rc < 0)
			throw new I2CError.ERRNO("Could get word %d from I2C device: %s!", addr, Posix.strerror(Posix.errno));
		return data;
	}
}