1#![doc(html_root_url = "https://docs.rs/i2c-linux-sys/0.2.1/")]
3
4#[macro_use]
5extern crate bitflags;
6extern crate byteorder;
7extern crate libc;
8
9use std::{fmt, io, ptr, mem, cmp};
10use std::os::unix::io::RawFd;
11use byteorder::{NativeEndian, ByteOrder};
12use libc::c_int;
13
14bitflags! {
15 pub struct Flags: u16 {
16 const RD = I2C_M_RD;
18 const TEN = I2C_M_TEN;
20 const RECV_LEN = I2C_M_RECV_LEN;
22 const NO_RD_ACK = I2C_M_NO_RD_ACK;
24 const IGNORE_NACK = I2C_M_IGNORE_NAK;
26 const REV_DIR_ADDR = I2C_M_REV_DIR_ADDR;
28 const NO_START = I2C_M_NOSTART;
30 const STOP = I2C_M_STOP;
32 }
33}
34
35pub const I2C_M_RD: u16 = 0x0001;
37pub const I2C_M_TEN: u16 = 0x0010;
39pub const I2C_M_RECV_LEN: u16 = 0x0400;
41pub const I2C_M_NO_RD_ACK: u16 = 0x0800;
43pub const I2C_M_IGNORE_NAK: u16 = 0x1000;
45pub const I2C_M_REV_DIR_ADDR: u16 = 0x2000;
47pub const I2C_M_NOSTART: u16 = 0x4000;
49pub const I2C_M_STOP: u16 = 0x8000;
51
52bitflags! {
53 pub struct Functionality: u32 {
55 const I2C = I2C_FUNC_I2C;
59 const TENBIT_ADDR = I2C_FUNC_10BIT_ADDR;
61 const PROTOCOL_MANGLING = I2C_FUNC_PROTOCOL_MANGLING;
63 const SMBUS_PEC = I2C_FUNC_SMBUS_PEC;
64 const NO_START = I2C_FUNC_NOSTART;
66 const SLAVE = I2C_FUNC_SLAVE;
67 const SMBUS_BLOCK_PROC_CALL = I2C_FUNC_SMBUS_BLOCK_PROC_CALL;
69 const SMBUS_QUICK = I2C_FUNC_SMBUS_QUICK;
70 const SMBUS_READ_BYTE = I2C_FUNC_SMBUS_READ_BYTE;
71 const SMBUS_WRITE_BYTE = I2C_FUNC_SMBUS_WRITE_BYTE;
72 const SMBUS_READ_BYTE_DATA = I2C_FUNC_SMBUS_READ_BYTE_DATA;
73 const SMBUS_WRITE_BYTE_DATA = I2C_FUNC_SMBUS_WRITE_BYTE_DATA;
74 const SMBUS_READ_WORD_DATA = I2C_FUNC_SMBUS_READ_WORD_DATA;
75 const SMBUS_WRITE_WORD_DATA = I2C_FUNC_SMBUS_WRITE_WORD_DATA;
76 const SMBUS_PROC_CALL = I2C_FUNC_SMBUS_PROC_CALL;
77 const SMBUS_READ_BLOCK_DATA = I2C_FUNC_SMBUS_READ_BLOCK_DATA;
78 const SMBUS_WRITE_BLOCK_DATA = I2C_FUNC_SMBUS_WRITE_BLOCK_DATA;
79 const SMBUS_READ_I2C_BLOCK = I2C_FUNC_SMBUS_READ_I2C_BLOCK;
81 const SMBUS_WRITE_I2C_BLOCK = I2C_FUNC_SMBUS_WRITE_I2C_BLOCK;
83 const SMBUS_HOST_NOTIFY = I2C_FUNC_SMBUS_HOST_NOTIFY;
84
85 const SMBUS_BYTE = I2C_FUNC_SMBUS_BYTE;
86 const SMBUS_BYTE_DATA = I2C_FUNC_SMBUS_BYTE_DATA;
87 const SMBUS_WORD_DATA = I2C_FUNC_SMBUS_WORD_DATA;
88 const SMBUS_BLOCK_DATA = I2C_FUNC_SMBUS_BLOCK_DATA;
89 const SMBUS_I2C_BLOCK = I2C_FUNC_SMBUS_I2C_BLOCK;
90
91 const SMBUS_EMUL = I2C_FUNC_SMBUS_EMUL;
92 }
93}
94
95pub const I2C_FUNC_I2C: u32 = 0x00000001;
96pub const I2C_FUNC_10BIT_ADDR: u32 = 0x00000002;
97pub const I2C_FUNC_PROTOCOL_MANGLING: u32 = 0x00000004;
99pub const I2C_FUNC_SMBUS_PEC: u32 = 0x00000008;
100pub const I2C_FUNC_NOSTART: u32 = 0x00000010;
102pub const I2C_FUNC_SLAVE: u32 = 0x00000020;
103
104pub const I2C_FUNC_SMBUS_BLOCK_PROC_CALL: u32 = 0x00008000;
106pub const I2C_FUNC_SMBUS_QUICK: u32 = 0x00010000;
107pub const I2C_FUNC_SMBUS_READ_BYTE: u32 = 0x00020000;
108pub const I2C_FUNC_SMBUS_WRITE_BYTE: u32 = 0x00040000;
109pub const I2C_FUNC_SMBUS_READ_BYTE_DATA: u32 = 0x00080000;
110pub const I2C_FUNC_SMBUS_WRITE_BYTE_DATA: u32 = 0x00100000;
111pub const I2C_FUNC_SMBUS_READ_WORD_DATA: u32 = 0x00200000;
112pub const I2C_FUNC_SMBUS_WRITE_WORD_DATA: u32 = 0x00400000;
113pub const I2C_FUNC_SMBUS_PROC_CALL: u32 = 0x00800000;
114pub const I2C_FUNC_SMBUS_READ_BLOCK_DATA: u32 = 0x01000000;
115pub const I2C_FUNC_SMBUS_WRITE_BLOCK_DATA: u32 = 0x02000000;
116pub const I2C_FUNC_SMBUS_READ_I2C_BLOCK: u32 = 0x04000000;
118pub const I2C_FUNC_SMBUS_WRITE_I2C_BLOCK: u32 = 0x08000000;
120pub const I2C_FUNC_SMBUS_HOST_NOTIFY: u32 = 0x10000000;
121
122pub const I2C_FUNC_SMBUS_BYTE: u32 = I2C_FUNC_SMBUS_READ_BYTE | I2C_FUNC_SMBUS_WRITE_BYTE;
123pub const I2C_FUNC_SMBUS_BYTE_DATA: u32 = I2C_FUNC_SMBUS_READ_BYTE_DATA | I2C_FUNC_SMBUS_WRITE_BYTE_DATA;
124pub const I2C_FUNC_SMBUS_WORD_DATA: u32 = I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA;
125pub const I2C_FUNC_SMBUS_BLOCK_DATA: u32 = I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_BLOCK_DATA;
126pub const I2C_FUNC_SMBUS_I2C_BLOCK: u32 = I2C_FUNC_SMBUS_READ_I2C_BLOCK | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK;
127
128pub const I2C_FUNC_SMBUS_EMUL: u32 = I2C_FUNC_SMBUS_QUICK |
129 I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
130 I2C_FUNC_SMBUS_PROC_CALL |
131 I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | I2C_FUNC_SMBUS_I2C_BLOCK |
132 I2C_FUNC_SMBUS_PEC;
133
134#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
136#[repr(u8)]
137pub enum SmbusReadWrite {
138 Read = 1,
139 Write = 0,
140}
141
142pub const I2C_SMBUS_READ: SmbusReadWrite = SmbusReadWrite::Read;
143pub const I2C_SMBUS_WRITE: SmbusReadWrite = SmbusReadWrite::Write;
144
145#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
149#[repr(u32)]
150pub enum SmbusTransaction {
151 Quick = I2C_SMBUS_QUICK,
152 Byte = I2C_SMBUS_BYTE,
153 ByteData = I2C_SMBUS_BYTE_DATA,
154 WordData = I2C_SMBUS_WORD_DATA,
155 ProcCall = I2C_SMBUS_PROC_CALL,
156 BlockData = I2C_SMBUS_BLOCK_DATA,
157 I2cBlockBroken = I2C_SMBUS_I2C_BLOCK_BROKEN,
158 BlockProcCall = I2C_SMBUS_BLOCK_PROC_CALL,
160 I2cBlockData = I2C_SMBUS_I2C_BLOCK_DATA,
161}
162
163pub const I2C_SMBUS_QUICK: u32 = 0;
164pub const I2C_SMBUS_BYTE: u32 = 1;
165pub const I2C_SMBUS_BYTE_DATA: u32 = 2;
166pub const I2C_SMBUS_WORD_DATA: u32 = 3;
167pub const I2C_SMBUS_PROC_CALL: u32 = 4;
168pub const I2C_SMBUS_BLOCK_DATA: u32 = 5;
169pub const I2C_SMBUS_I2C_BLOCK_BROKEN: u32 = 6;
170pub const I2C_SMBUS_BLOCK_PROC_CALL: u32 = 7;
172pub const I2C_SMBUS_I2C_BLOCK_DATA: u32 = 8;
173
174pub const I2C_SMBUS_BLOCK_MAX: usize = 32;
176
177#[repr(C)]
178#[derive(Copy, Clone, Debug)]
179pub struct i2c_msg {
201 pub addr: u16,
207 pub flags: Flags,
213 pub len: u16,
222 pub buf: *mut u8,
224}
225
226#[repr(C)]
227#[derive(Copy, Clone, Debug)]
228pub struct i2c_rdwr_ioctl_data {
230 pub msgs: *mut i2c_msg,
232 pub nmsgs: c_int,
234}
235
236#[repr(C)]
237#[derive(Copy, Clone)]
238pub struct i2c_smbus_data {
240 _alignment: [u16; 0],
241 pub block: [u8; I2C_SMBUS_BLOCK_MAX + 2],
243}
244
245impl i2c_smbus_data {
246 pub fn from_byte(v: u8) -> Self {
247 let mut data = Self::default();
248 data.set_byte(v);
249 data
250 }
251
252 pub fn from_word(v: u16) -> Self {
253 let mut data = Self::default();
254 data.set_word(v);
255 data
256 }
257
258 pub fn from_block(v: &[u8]) -> Self {
259 let mut data = Self::default();
260 data.set_block(v);
261 data
262 }
263
264 pub fn byte(&self) -> u8 {
265 self.block[0]
266 }
267
268 pub fn set_byte(&mut self, v: u8) {
269 self.block[0] = v;
270 }
271
272 pub fn word(&self) -> u16 {
273 NativeEndian::read_u16(&self.block[..2])
274 }
275
276 pub fn set_word(&mut self, v: u16) {
277 NativeEndian::write_u16(&mut self.block[..2], v)
278 }
279
280 pub fn block(&self) -> Option<&[u8]> {
281 let len = self.block[0] as usize;
282 if len <= I2C_SMBUS_BLOCK_MAX {
283 Some(&self.block[1..1 + len])
284 } else {
285 None
286 }
287 }
288
289 pub fn block_mut(&mut self) -> Option<&mut [u8]> {
290 let len = self.block[0] as usize;
291 if len <= I2C_SMBUS_BLOCK_MAX {
292 Some(&mut self.block[1..1 + len])
293 } else {
294 None
295 }
296 }
297
298 pub fn set_block(&mut self, v: &[u8]) {
299 assert!(v.len() <= I2C_SMBUS_BLOCK_MAX);
300
301 self.block[0] = v.len() as u8;
302 self.block[1..1 + v.len()].copy_from_slice(v);
303 }
304}
305
306impl fmt::Debug for i2c_smbus_data {
307 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
308 f.debug_struct("i2c_smbus_data")
309 .field("byte", &self.byte())
310 .field("word", &self.word())
311 .field("block", &self.block())
312 .finish()
313 }
314}
315
316impl Default for i2c_smbus_data {
317 fn default() -> Self {
318 unsafe { mem::zeroed() }
319 }
320}
321
322#[repr(C)]
323#[derive(Copy, Clone, Debug)]
324pub struct i2c_smbus_ioctl_data {
326 pub read_write: SmbusReadWrite,
327 pub command: u8,
328 pub size: SmbusTransaction,
329 pub data: *mut i2c_smbus_data,
330}
331
332pub const I2C_RETRIES: u16 = 0x0701;
334pub const I2C_TIMEOUT: u16 = 0x0702;
336
337pub const I2C_SLAVE: u16 = 0x0703;
342pub const I2C_SLAVE_FORCE: u16 = 0x0706;
344pub const I2C_TENBIT: u16 = 0x0704;
346
347pub const I2C_FUNCS: u16 = 0x0705;
349
350pub const I2C_RDWR: u16 = 0x0707;
352
353pub const I2C_PEC: u16 = 0x0708;
355pub const I2C_SMBUS: u16 = 0x0720;
357
358pub const I2C_RDWR_IOCTL_MAX_MSGS: usize = 42;
359
360pub mod ioctls {
361 use libc::{ioctl, c_int, c_ulong};
362 use std::os::unix::io::RawFd;
363 use std::io;
364
365 #[inline]
366 fn ioctl_result(res: c_int) -> io::Result<c_int> {
367 if res == -1 {
368 Err(io::Error::last_os_error())
369 } else {
370 Ok(res)
371 }
372 }
373
374 pub unsafe fn i2c_retries(fd: RawFd, value: c_int) -> io::Result<c_int> {
375 ioctl_result(ioctl(fd, super::I2C_RETRIES as _, value))
376 }
377
378 pub unsafe fn i2c_timeout(fd: RawFd, value: c_int) -> io::Result<c_int> {
379 ioctl_result(ioctl(fd, super::I2C_TIMEOUT as _, value))
380 }
381
382 pub unsafe fn i2c_slave(fd: RawFd, value: c_int) -> io::Result<c_int> {
383 ioctl_result(ioctl(fd, super::I2C_SLAVE as _, value))
384 }
385
386 pub unsafe fn i2c_slave_force(fd: RawFd, value: c_int) -> io::Result<c_int> {
387 ioctl_result(ioctl(fd, super::I2C_SLAVE_FORCE as _, value))
388 }
389
390 pub unsafe fn i2c_tenbit(fd: RawFd, value: c_int) -> io::Result<c_int> {
391 ioctl_result(ioctl(fd, super::I2C_TENBIT as _, value))
392 }
393
394 pub unsafe fn i2c_funcs(fd: RawFd, value: *mut c_ulong) -> io::Result<c_int> {
395 ioctl_result(ioctl(fd, super::I2C_FUNCS as _, value))
396 }
397
398 pub unsafe fn i2c_rdwr(fd: RawFd, value: *mut super::i2c_rdwr_ioctl_data) -> io::Result<c_int> {
399 ioctl_result(ioctl(fd, super::I2C_RDWR as _, value))
400 }
401
402 pub unsafe fn i2c_pec(fd: RawFd, value: c_int) -> io::Result<c_int> {
403 ioctl_result(ioctl(fd, super::I2C_PEC as _, value))
404 }
405
406 pub unsafe fn i2c_smbus(fd: RawFd, value: *mut super::i2c_smbus_ioctl_data) -> io::Result<c_int> {
407 ioctl_result(ioctl(fd, super::I2C_SMBUS as _, value))
408 }
409}
410
411#[inline]
413pub fn i2c_set_retries(fd: RawFd, value: usize) -> io::Result<()> {
414 unsafe {
415 ioctls::i2c_retries(fd, value as _).map(drop)
416 }
417}
418
419#[inline]
421pub fn i2c_set_timeout_ms(fd: RawFd, value: usize) -> io::Result<()> {
422 unsafe {
423 ioctls::i2c_timeout(fd, (value / 10) as _).map(drop)
424 }
425}
426
427#[inline]
429pub fn i2c_set_slave_address(fd: RawFd, address: u16, force: bool) -> io::Result<()> {
430 unsafe {
431 if force {
432 ioctls::i2c_slave(fd, address as _)
433 } else {
434 ioctls::i2c_slave_force(fd, address as _)
435 }.map(drop)
436 }
437}
438
439#[inline]
441pub fn i2c_set_slave_address_10bit(fd: RawFd, tenbit: bool) -> io::Result<()> {
442 unsafe {
443 ioctls::i2c_tenbit(fd, if tenbit { 1 } else { 0 }).map(drop)
444 }
445}
446
447#[inline]
449pub fn i2c_get_functionality(fd: RawFd) -> io::Result<Functionality> {
450 unsafe {
451 let mut res = 0;
452 ioctls::i2c_funcs(fd, &mut res)
453 .map(|_| Functionality::from_bits_truncate(res as _))
454 }
455}
456
457#[inline]
459pub fn i2c_pec(fd: RawFd, pec: bool) -> io::Result<()> {
460 unsafe {
461 ioctls::i2c_pec(fd, if pec { 1 } else { 0 }).map(drop)
462 }
463}
464
465#[inline]
467pub unsafe fn i2c_rdwr(fd: RawFd, msgs: &mut [i2c_msg]) -> io::Result<()> {
468 let mut data = i2c_rdwr_ioctl_data {
469 msgs: msgs.as_mut_ptr(),
470 nmsgs: msgs.len() as _,
471 };
472 ioctls::i2c_rdwr(fd, &mut data).map(drop)
473}
474
475#[inline]
477pub unsafe fn i2c_smbus(fd: RawFd, data: &mut i2c_smbus_ioctl_data) -> io::Result<()> {
478 ioctls::i2c_smbus(fd, data).map(drop)
479}
480
481pub fn i2c_smbus_write_quick(fd: RawFd, value: SmbusReadWrite) -> io::Result<()> {
482 unsafe {
483 i2c_smbus(fd, &mut i2c_smbus_ioctl_data {
484 read_write: value,
485 command: 0,
486 size: SmbusTransaction::Quick,
487 data: ptr::null_mut(),
488 })
489 }
490}
491
492pub fn i2c_smbus_read_byte(fd: RawFd) -> io::Result<u8> {
493 unsafe {
494 let mut data = i2c_smbus_data::default();
495 let mut ioctl = i2c_smbus_ioctl_data {
496 read_write: SmbusReadWrite::Read,
497 command: 0,
498 size: SmbusTransaction::Byte,
499 data: &mut data,
500 };
501 i2c_smbus(fd, &mut ioctl)
502 .map(|_| data.byte())
503 }
504}
505
506pub fn i2c_smbus_write_byte(fd: RawFd, value: u8) -> io::Result<()> {
507 unsafe {
508 let mut ioctl = i2c_smbus_ioctl_data {
509 read_write: SmbusReadWrite::Write,
510 command: value,
511 size: SmbusTransaction::Byte,
512 data: ptr::null_mut(),
513 };
514 i2c_smbus(fd, &mut ioctl)
515 }
516}
517
518pub fn i2c_smbus_read_byte_data(fd: RawFd, command: u8) -> io::Result<u8> {
519 unsafe {
520 let mut data = i2c_smbus_data::default();
521 let mut ioctl = i2c_smbus_ioctl_data {
522 read_write: SmbusReadWrite::Read,
523 command: command,
524 size: SmbusTransaction::ByteData,
525 data: &mut data,
526 };
527 i2c_smbus(fd, &mut ioctl)
528 .map(|_| data.byte())
529 }
530}
531
532pub fn i2c_smbus_write_byte_data(fd: RawFd, command: u8, value: u8) -> io::Result<()> {
533 unsafe {
534 let mut data = i2c_smbus_data::from_byte(value);
535 let mut ioctl = i2c_smbus_ioctl_data {
536 read_write: SmbusReadWrite::Write,
537 command: command,
538 size: SmbusTransaction::ByteData,
539 data: &mut data,
540 };
541 i2c_smbus(fd, &mut ioctl)
542 }
543}
544
545pub fn i2c_smbus_read_word_data(fd: RawFd, command: u8) -> io::Result<u16> {
546 unsafe {
547 let mut data = i2c_smbus_data::default();
548 let mut ioctl = i2c_smbus_ioctl_data {
549 read_write: SmbusReadWrite::Read,
550 command: command,
551 size: SmbusTransaction::WordData,
552 data: &mut data,
553 };
554 i2c_smbus(fd, &mut ioctl)
555 .map(|_| data.word())
556 }
557}
558
559pub fn i2c_smbus_write_word_data(fd: RawFd, command: u8, value: u16) -> io::Result<()> {
560 unsafe {
561 let mut data = i2c_smbus_data::from_word(value);
562 let mut ioctl = i2c_smbus_ioctl_data {
563 read_write: SmbusReadWrite::Write,
564 command: command,
565 size: SmbusTransaction::WordData,
566 data: &mut data,
567 };
568 i2c_smbus(fd, &mut ioctl)
569 }
570}
571
572pub fn i2c_smbus_process_call(fd: RawFd, command: u8, value: u16) -> io::Result<u16> {
573 unsafe {
574 let mut data = i2c_smbus_data::from_word(value);
575 let mut ioctl = i2c_smbus_ioctl_data {
576 read_write: SmbusReadWrite::Write,
577 command: command,
578 size: SmbusTransaction::ProcCall,
579 data: &mut data,
580 };
581 i2c_smbus(fd, &mut ioctl)
582 .map(|_| data.word())
583 }
584}
585
586pub fn i2c_smbus_read_block_data(fd: RawFd, command: u8, value: &mut [u8]) -> io::Result<usize> {
587 unsafe {
588 let mut data = i2c_smbus_data::default();
589 let mut ioctl = i2c_smbus_ioctl_data {
590 read_write: SmbusReadWrite::Read,
591 command: command,
592 size: SmbusTransaction::BlockData,
593 data: &mut data,
594 };
595 i2c_smbus(fd, &mut ioctl)
596 .map(|_| {
597 let block = data.block().expect("kernel provided an invalid block length");
598 let len = cmp::min(block.len(), value.len());
599 value[..len].copy_from_slice(&block[..len]);
600 block.len()
601 })
602 }
603}
604
605pub fn i2c_smbus_write_block_data(fd: RawFd, command: u8, value: &[u8]) -> io::Result<()> {
606 unsafe {
607 let mut data = i2c_smbus_data::from_block(value);
608 let mut ioctl = i2c_smbus_ioctl_data {
609 read_write: SmbusReadWrite::Write,
610 command: command,
611 size: SmbusTransaction::BlockData,
612 data: &mut data,
613 };
614 i2c_smbus(fd, &mut ioctl)
615 }
616}
617
618pub fn i2c_smbus_read_i2c_block_data(fd: RawFd, command: u8, value: &mut [u8]) -> io::Result<usize> {
619 assert!(value.len() <= I2C_SMBUS_BLOCK_MAX);
620
621 unsafe {
622 let mut data = i2c_smbus_data::from_byte(value.len() as u8);
623 let mut ioctl = i2c_smbus_ioctl_data {
624 read_write: SmbusReadWrite::Read,
625 command: command,
626 size: if value.len() == I2C_SMBUS_BLOCK_MAX { SmbusTransaction::I2cBlockBroken } else { SmbusTransaction::I2cBlockData },
627 data: &mut data,
628 };
629 i2c_smbus(fd, &mut ioctl)
630 .map(|_| {
631 let block = data.block().expect("kernel provided an invalid block length");
632 let len = cmp::min(block.len(), value.len());
633 value[..len].copy_from_slice(&block[..len]);
634 block.len()
635 })
636 }
637}
638
639pub fn i2c_smbus_write_i2c_block_data(fd: RawFd, command: u8, value: &[u8]) -> io::Result<()> {
640 unsafe {
641 let mut data = i2c_smbus_data::from_block(value);
642 let mut ioctl = i2c_smbus_ioctl_data {
643 read_write: SmbusReadWrite::Write,
644 command: command,
645 size: SmbusTransaction::I2cBlockBroken,
646 data: &mut data,
647 };
648 i2c_smbus(fd, &mut ioctl)
649 }
650}
651
652pub fn i2c_smbus_block_process_call(fd: RawFd, command: u8, write: &[u8], read: &mut [u8]) -> io::Result<usize> {
653 assert!(read.len() <= I2C_SMBUS_BLOCK_MAX - 1);
654
655 unsafe {
656 let mut data = i2c_smbus_data::from_block(write);
657 let mut ioctl = i2c_smbus_ioctl_data {
658 read_write: SmbusReadWrite::Write,
659 command: command,
660 size: SmbusTransaction::BlockProcCall,
661 data: &mut data,
662 };
663 i2c_smbus(fd, &mut ioctl)
664 .map(|_| {
665 let block = data.block().expect("kernel provided an invalid block length");
666 let len = cmp::min(block.len(), read.len());
667 read[..len].copy_from_slice(&block[..len]);
668 block.len()
669 })
670 }
671}