use libc::{c_int, c_uint, c_uchar, c_ushort, c_void};
use libc::ioctl;
use std::ptr;
#[cfg(not(any(target_env = "musl")))]
use libc::c_ulong;
use std::os::unix::io::AsRawFd;
use std::io;
use Direction;
use scsi::SCSIDevice;
use std::cmp::max;
#[cfg(not(any(target_env = "musl")))]
const SG_IO: c_ulong = 0x2285;
#[cfg(any(target_env = "musl"))]
const SG_IO: c_int = 0x2285;
#[repr(C)]
#[derive(Debug)]
struct sg_io_hdr {
interface_id: c_int, dxfer_direction: c_int, cmd_len: c_uchar, mx_sb_len: c_uchar, iovec_count: c_ushort, dxfer_len: c_uint, dxferp: *mut c_void, cmdp: *const c_uchar, sbp: *mut c_uchar, timeout: c_uint, flags: c_uint, pack_id: c_int, usr_ptr: *mut c_void, status: c_uchar, masked_status: c_uchar, msg_status: c_uchar, sb_len_wr: c_uchar, host_status: c_ushort, driver_status: c_ushort, resid: c_int, duration: c_uint, info: c_uint, }
impl SCSIDevice {
pub(crate) fn do_platform_cmd(&self, cmd: &[u8], dir: Direction, sense_len: usize, data_len: usize) -> Result<(Vec<u8>, Vec<u8>), io::Error> {
let mut sense = vec![0; sense_len];
let mut data = vec![0; data_len];
let hdr = sg_io_hdr {
interface_id: 'S' as c_int,
dxfer_direction: match dir {
Direction::None => -1,
Direction::To => unimplemented!(), Direction::From => -3,
Direction::Both => unimplemented!(), },
dxferp: data.as_mut_ptr() as *mut c_void,
dxfer_len: data.capacity() as c_uint,
resid: 0,
sbp: sense.as_mut_ptr(),
mx_sb_len: sense.capacity() as c_uchar,
sb_len_wr: 0,
cmdp: cmd.as_ptr(),
cmd_len: cmd.len() as c_uchar,
status: 0,
host_status: 0,
driver_status: 0,
timeout: 10000, duration: 0,
iovec_count: 0,
flags: 0,
pack_id: 0,
usr_ptr: ptr::null_mut(),
masked_status: 0,
msg_status: 0,
info: 0,
};
unsafe {
if ioctl(self.device.file.as_raw_fd(), SG_IO, &hdr) == -1 {
return Err(io::Error::last_os_error());
}
}
let data_len = hdr.dxfer_len - max(hdr.resid, 0) as u32;
Ok((
sense[ .. hdr.sb_len_wr as usize].to_vec(),
data[ .. data_len as usize].to_vec(),
))
}
}