1#![allow(dead_code)]
10#![allow(non_camel_case_types)]
11
12use nix;
13use std::mem;
14use std::ptr;
15use std::io::Cursor;
16use std::os::unix::prelude::*;
17use std::marker::PhantomData;
18use byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt};
19use core::{I2CMsg};
20use libc::c_int;
21
22pub type I2CError = nix::Error;
23
24#[repr(C)]
25#[derive(Debug)]
26struct i2c_msg<'a> {
29 addr: u16,
31 flags: u16,
33 len: u16,
35 buf: *mut u8,
37 _phantom: PhantomData<&'a mut u8>,
38}
39
40impl<'a, 'b> From<&'b mut I2CMsg<'a>> for i2c_msg<'a> {
41 fn from(msg: &mut I2CMsg) -> Self {
42 i2c_msg {
43 addr: msg.addr,
44 flags: msg.flags,
45 len: msg.data.len() as u16,
46 buf: msg.data.as_mut_ptr(),
47 _phantom: PhantomData
48 }
49 }
50}
51
52bitflags! {
53 struct I2CFunctions: u32 {
54 const I2C_FUNC_I2C = 0x00000001;
55 const I2C_FUNC_10BIT_ADDR = 0x00000002;
56 const I2C_FUNC_PROTOCOL_MANGLING = 0x00000004; const I2C_FUNC_SMBUS_PEC = 0x00000008;
58 const I2C_FUNC_NOSTART = 0x00000010; const I2C_FUNC_SMBUS_BLOCK_PROC_CALL = 0x00008000; const I2C_FUNC_SMBUS_QUICK = 0x00010000;
61 const I2C_FUNC_SMBUS_READ_BYTE = 0x00020000;
62 const I2C_FUNC_SMBUS_WRITE_BYTE = 0x00040000;
63 const I2C_FUNC_SMBUS_READ_BYTE_DATA = 0x00080000;
64 const I2C_FUNC_SMBUS_WRITE_BYTE_DATA = 0x00100000;
65 const I2C_FUNC_SMBUS_READ_WORD_DATA = 0x00200000;
66 const I2C_FUNC_SMBUS_WRITE_WORD_DATA = 0x00400000;
67 const I2C_FUNC_SMBUS_PROC_CALL = 0x00800000;
68 const I2C_FUNC_SMBUS_READ_BLOCK_DATA = 0x01000000;
69 const I2C_FUNC_SMBUS_WRITE_BLOCK_DATA = 0x02000000;
70 const I2C_FUNC_SMBUS_READ_I2C_BLOCK = 0x04000000; const I2C_FUNC_SMBUS_WRITE_I2C_BLOCK = 0x08000000; const I2C_FUNC_SMBUS_BYTE = (I2CFunctions::I2C_FUNC_SMBUS_READ_BYTE.bits |
74 I2CFunctions::I2C_FUNC_SMBUS_WRITE_BYTE.bits);
75 const I2C_FUNC_SMBUS_BYTE_DATA = (I2CFunctions::I2C_FUNC_SMBUS_READ_BYTE_DATA.bits |
76 I2CFunctions::I2C_FUNC_SMBUS_WRITE_BYTE_DATA.bits);
77 const I2C_FUNC_SMBUS_WORD_DATA = (I2CFunctions::I2C_FUNC_SMBUS_READ_WORD_DATA.bits |
78 I2CFunctions::I2C_FUNC_SMBUS_WRITE_WORD_DATA.bits);
79 const I2C_FUNC_SMBUS_BLOCK_DATA = (I2CFunctions::I2C_FUNC_SMBUS_READ_BLOCK_DATA.bits |
80 I2CFunctions::I2C_FUNC_SMBUS_WRITE_BLOCK_DATA.bits);
81 const I2C_FUNC_SMBUS_I2C_BLOCK = (I2CFunctions::I2C_FUNC_SMBUS_READ_I2C_BLOCK.bits |
82 I2CFunctions::I2C_FUNC_SMBUS_WRITE_I2C_BLOCK.bits);
83 const I2C_FUNC_SMBUS_EMUL = (I2CFunctions::I2C_FUNC_SMBUS_QUICK.bits |
84 I2CFunctions::I2C_FUNC_SMBUS_BYTE.bits |
85 I2CFunctions::I2C_FUNC_SMBUS_BYTE_DATA.bits |
86 I2CFunctions::I2C_FUNC_SMBUS_WORD_DATA.bits |
87 I2CFunctions::I2C_FUNC_SMBUS_PROC_CALL.bits |
88 I2CFunctions::I2C_FUNC_SMBUS_WRITE_BLOCK_DATA.bits |
89 I2CFunctions::I2C_FUNC_SMBUS_I2C_BLOCK.bits |
90 I2CFunctions::I2C_FUNC_SMBUS_PEC.bits);
91 }
92}
93
94
95const I2C_SMBUS_BLOCK_MAX: u8 = 32;
97
98#[repr(C)]
109struct i2c_smbus_data {
110 block: [u8; (I2C_SMBUS_BLOCK_MAX + 2) as usize],
111}
112
113impl i2c_smbus_data {
114 fn empty() -> i2c_smbus_data {
115 unsafe { mem::zeroed() }
116 }
117}
118
119#[repr(u8)]
120enum I2CSMBusReadWrite {
121 I2C_SMBUS_READ = 1,
122 I2C_SMBUS_WRITE = 0,
123}
124
125#[repr(u32)]
126enum I2CSMBusSize {
127 I2C_SMBUS_QUICK = 0,
128 I2C_SMBUS_BYTE = 1,
129 I2C_SMBUS_BYTE_DATA = 2,
130 I2C_SMBUS_WORD_DATA = 3,
131 I2C_SMBUS_PROC_CALL = 4,
132 I2C_SMBUS_BLOCK_DATA = 5,
133 I2C_SMBUS_I2C_BLOCK_BROKEN = 6,
134 I2C_SMBUS_BLOCK_PROC_CALL = 7, I2C_SMBUS_I2C_BLOCK_DATA = 8,
136}
137
138const I2C_RETRIES: u16 = 0x0701;
140const I2C_TIMEOUT: u16 = 0x0702;
141const I2C_SLAVE: u16 = 0x0703;
142const I2C_SLAVE_FORCE: u16 = 0x0706;
143const I2C_TENBIT: u16 = 0x0704;
144const I2C_FUNCS: u16 = 0x0705;
145const I2C_RDWR: u16 = 0x0707;
146const I2C_PEC: u16 = 0x0708;
147const I2C_SMBUS: u16 = 0x0720;
148const I2C_RDRW_IOCTL_MAX_MSGS: u8 = 42;
149
150#[repr(C)]
152pub struct i2c_smbus_ioctl_data {
153 read_write: u8,
155 command: u8,
157 size: u32,
159 data: *mut i2c_smbus_data,
161}
162
163#[repr(C)]
166pub struct i2c_rdwr_ioctl_data<'a> {
167 msgs: *mut i2c_msg<'a>,
169 nmsgs: u32,
171}
172
173mod ioctl {
174 use super::{I2C_SLAVE, I2C_SMBUS, I2C_RDWR};
175 pub use super::i2c_smbus_ioctl_data;
176 pub use super::i2c_rdwr_ioctl_data;
177
178 ioctl_write_int_bad!(set_i2c_slave_address, I2C_SLAVE);
179 ioctl_write_ptr_bad!(i2c_smbus, I2C_SMBUS, i2c_smbus_ioctl_data);
180 ioctl_write_ptr_bad!(i2c_rdwr, I2C_RDWR, i2c_rdwr_ioctl_data);
181}
182
183pub fn i2c_set_slave_address(fd: RawFd, slave_address: u16) -> Result<(), nix::Error> {
184 unsafe {
185 ioctl::set_i2c_slave_address(fd, slave_address as i32)?;
186 }
187 Ok(())
188}
189
190unsafe fn i2c_smbus_access(fd: RawFd,
191 read_write: I2CSMBusReadWrite,
192 command: u8, size: I2CSMBusSize,
194 data: *mut i2c_smbus_data)
195 -> Result<(), I2CError> {
196 let mut args = i2c_smbus_ioctl_data {
197 read_write: read_write as u8,
198 command: command,
199 size: size as u32,
200 data: data,
201 };
202
203 ioctl::i2c_smbus(fd, &mut args).map(drop)
205}
206
207#[inline]
208pub fn i2c_smbus_write_quick(fd: RawFd, bit: bool) -> Result<(), I2CError> {
209 let read_write = match bit {
210 true => I2CSMBusReadWrite::I2C_SMBUS_READ,
211 false => I2CSMBusReadWrite::I2C_SMBUS_WRITE,
212 };
213 unsafe {
214 i2c_smbus_access(fd,
215 read_write,
216 0,
217 I2CSMBusSize::I2C_SMBUS_QUICK,
218 ptr::null_mut())
219 }
220}
221
222#[inline]
223pub fn i2c_smbus_read_byte(fd: RawFd) -> Result<u8, I2CError> {
224 let mut data = i2c_smbus_data::empty();
225 unsafe {
226 i2c_smbus_access(fd,
227 I2CSMBusReadWrite::I2C_SMBUS_READ,
228 0,
229 I2CSMBusSize::I2C_SMBUS_BYTE,
230 &mut data)?
231 }
232 Ok(data.block[0])
233}
234
235#[inline]
236pub fn i2c_smbus_write_byte(fd: RawFd, value: u8) -> Result<(), I2CError> {
237 unsafe {
238 i2c_smbus_access(fd,
239 I2CSMBusReadWrite::I2C_SMBUS_WRITE,
240 value,
241 I2CSMBusSize::I2C_SMBUS_BYTE,
242 ptr::null_mut())
243 }
244}
245
246#[inline]
247pub fn i2c_smbus_read_byte_data(fd: RawFd, register: u8) -> Result<u8, I2CError> {
248 let mut data = i2c_smbus_data::empty();
249 unsafe {
250 i2c_smbus_access(fd,
251 I2CSMBusReadWrite::I2C_SMBUS_READ,
252 register,
253 I2CSMBusSize::I2C_SMBUS_BYTE_DATA,
254 &mut data)?;
255 }
256 Ok(data.block[0])
257}
258
259#[inline]
260pub fn i2c_smbus_write_byte_data(fd: RawFd, register: u8, value: u8) -> Result<(), I2CError> {
261 let mut data = i2c_smbus_data::empty();
262 data.block[0] = value;
263 unsafe {
264 i2c_smbus_access(fd,
265 I2CSMBusReadWrite::I2C_SMBUS_WRITE,
266 register,
267 I2CSMBusSize::I2C_SMBUS_BYTE_DATA,
268 &mut data)?;
269 }
270 Ok(())
271}
272
273#[inline]
274pub fn i2c_smbus_read_word_data(fd: RawFd, register: u8) -> Result<u16, I2CError> {
275 let mut data = i2c_smbus_data::empty();
276 unsafe {
277 i2c_smbus_access(fd,
278 I2CSMBusReadWrite::I2C_SMBUS_READ,
279 register,
280 I2CSMBusSize::I2C_SMBUS_WORD_DATA,
281 &mut data)?;
282 };
283
284 Ok(Cursor::new(&data.block[..])
285 .read_u16::<NativeEndian>()
286 .unwrap())
287}
288
289
290#[inline]
291pub fn i2c_smbus_write_word_data(fd: RawFd, register: u8, value: u16) -> Result<(), I2CError> {
292 let mut data = i2c_smbus_data::empty();
293 Cursor::new(&mut data.block[..])
294 .write_u16::<NativeEndian>(value)
295 .unwrap();
296
297 unsafe {
298 i2c_smbus_access(fd,
299 I2CSMBusReadWrite::I2C_SMBUS_WRITE,
300 register,
301 I2CSMBusSize::I2C_SMBUS_WORD_DATA,
302 &mut data)?;
303 };
304 Ok(())
305}
306
307#[inline]
308pub fn i2c_smbus_process_call(fd: RawFd, register: u8, value: u16) -> Result<u16, I2CError> {
309 let mut data = i2c_smbus_data::empty();
310 Cursor::new(&mut data.block[..])
311 .write_u16::<NativeEndian>(value)
312 .unwrap();
313
314 unsafe {
315 i2c_smbus_access(fd,
316 I2CSMBusReadWrite::I2C_SMBUS_WRITE,
317 register,
318 I2CSMBusSize::I2C_SMBUS_PROC_CALL,
319 &mut data)?;
320 }
321 Ok(Cursor::new(&data.block[..])
322 .read_u16::<NativeEndian>()
323 .unwrap())
324}
325
326#[inline]
327pub fn i2c_smbus_read_block_data(fd: RawFd, register: u8) -> Result<Vec<u8>, I2CError> {
328 let mut data = i2c_smbus_data::empty();
329 unsafe {
330 i2c_smbus_access(fd,
331 I2CSMBusReadWrite::I2C_SMBUS_READ,
332 register,
333 I2CSMBusSize::I2C_SMBUS_BLOCK_DATA,
334 &mut data)?;
335 }
336
337 let count = data.block[0];
340 Ok((&data.block[1..(count + 1) as usize]).to_vec())
341}
342
343pub fn i2c_smbus_read_i2c_block_data(fd: RawFd, register: u8, len: u8) -> Result<Vec<u8>, I2CError> {
344 let mut data = i2c_smbus_data::empty();
345 data.block[0] = len;
346 unsafe {
347 i2c_smbus_access(fd,
348 I2CSMBusReadWrite::I2C_SMBUS_READ,
349 register,
350 I2CSMBusSize::I2C_SMBUS_I2C_BLOCK_DATA,
351 &mut data)?;
352 }
353
354 let count = data.block[0];
357 Ok((&data.block[1..(count + 1) as usize]).to_vec())
358}
359
360#[inline]
361pub fn i2c_smbus_write_block_data(fd: RawFd, register: u8, values: &[u8]) -> Result<(), I2CError> {
362 let mut data = i2c_smbus_data::empty();
363 let len: usize = if values.len() > 32 {
364 32
365 } else {
366 values.len()
367 };
368 data.block[0] = len as u8;
369 for i in 1..(len + 1) {
370 data.block[i] = values[i - 1];
371 }
372 unsafe {
373 i2c_smbus_access(fd,
374 I2CSMBusReadWrite::I2C_SMBUS_WRITE,
375 register,
376 I2CSMBusSize::I2C_SMBUS_BLOCK_DATA,
377 &mut data)?;
378 }
379 Ok(())
380}
381
382#[inline]
383pub fn i2c_smbus_write_i2c_block_data(fd: RawFd,
384 register: u8,
385 values: &[u8])
386 -> Result<(), I2CError> {
387 let mut data = i2c_smbus_data::empty();
388 let len: usize = if values.len() > 32 {
389 32
390 } else {
391 values.len()
392 };
393 data.block[0] = len as u8;
394 for i in 1..(len + 1) {
395 data.block[i] = values[i - 1];
396 }
397 unsafe {
398 i2c_smbus_access(fd,
399 I2CSMBusReadWrite::I2C_SMBUS_WRITE,
400 register,
401 I2CSMBusSize::I2C_SMBUS_I2C_BLOCK_DATA,
402 &mut data)?;
403 }
404 Ok(())
405}
406
407#[inline]
408pub fn i2c_smbus_process_call_block(fd: RawFd, register: u8, values: &[u8]) -> Result<Vec<u8>, I2CError> {
409 let mut data = i2c_smbus_data::empty();
410 let len: usize = if values.len() > 31 {
411 31
412 } else {
413 values.len()
414 };
415 data.block[0] = len as u8;
416 for i in 1..(len + 1) {
417 data.block[i] = values[i - 1];
418 }
419 unsafe {
420 i2c_smbus_access(fd,
421 I2CSMBusReadWrite::I2C_SMBUS_WRITE,
422 register,
423 I2CSMBusSize::I2C_SMBUS_BLOCK_PROC_CALL,
424 &mut data)?;
425 };
426
427 let count = data.block[0];
430 Ok((&data.block[1..(count + 1) as usize]).to_vec())
431}
432
433unsafe fn i2c_rdwr_access(fd: RawFd,
435 msgs: *mut i2c_msg,
436 nmsgs: usize)
437 -> Result<(c_int), I2CError> {
438 let args = i2c_rdwr_ioctl_data {
439 msgs,
440 nmsgs: nmsgs as u32,
441 };
442
443 ioctl::i2c_rdwr(fd, &args)
444}
445
446pub fn i2c_rdwr_read_write(fd: RawFd,
447 msgs: &mut Vec<I2CMsg>) -> Result<(i32), I2CError> {
448 let mut cmsgs = msgs.iter_mut().map(<i2c_msg>::from).collect::<Vec<_>>();
451
452 unsafe {
454 i2c_rdwr_access(fd,
455 cmsgs.as_mut_ptr(),
456 cmsgs.len())
457 }
458}
459