blob: ba7e6db9785c6d007ce46b030b4e3a67d2d72715 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::types::*;
const fn new_ioctl(dir: u32, _type: u8, number: u32, size: u32) -> u32 {
(dir << _IOC_DIRSHIFT)
| ((_type as u32) << _IOC_TYPESHIFT)
| (number << _IOC_NRSHIFT)
| (size << _IOC_SIZESHIFT)
}
#[cfg(test)]
pub const fn encode_ioctl(_type: u8, number: u32) -> u32 {
new_ioctl(_IOC_NONE, _type, number, 0)
}
#[cfg(test)]
pub const fn encode_ioctl_read<T>(_type: u8, number: u32) -> u32 {
new_ioctl(_IOC_READ, _type, number, std::mem::size_of::<T>() as u32)
}
pub const fn encode_ioctl_write<T>(_type: u8, number: u32) -> u32 {
new_ioctl(_IOC_WRITE, _type, number, std::mem::size_of::<T>() as u32)
}
pub const fn encode_ioctl_write_read<T>(_type: u8, number: u32) -> u32 {
new_ioctl(_IOC_READ | _IOC_WRITE, _type, number, std::mem::size_of::<T>() as u32)
}
#[cfg(test)]
mod tests {
use super::*;
pub struct IoctlRequest {
pub dir: u32,
pub _type: u32,
pub number: u32,
pub size: u32,
}
impl IoctlRequest {
pub fn new(request: u32) -> IoctlRequest {
IoctlRequest {
dir: decode_ioctl_dir(request),
_type: decode_ioctl_type(request),
number: decode_ioctl_number(request),
size: decode_ioctl_size(request),
}
}
}
pub fn decode_ioctl_dir(number: u32) -> u32 {
(number >> _IOC_DIRSHIFT) & _IOC_DIRMASK
}
pub fn decode_ioctl_type(number: u32) -> u32 {
(number >> _IOC_TYPESHIFT) & _IOC_TYPEMASK
}
pub fn decode_ioctl_number(number: u32) -> u32 {
(number >> _IOC_NRSHIFT) & _IOC_NRMASK
}
pub fn decode_ioctl_size(number: u32) -> u32 {
(number >> _IOC_SIZESHIFT) & _IOC_SIZEMASK
}
#[::fuchsia::test]
fn test_encode() {
let encoded = encode_ioctl(7, 9);
assert_eq!(decode_ioctl_dir(encoded), _IOC_NONE);
assert_eq!(decode_ioctl_type(encoded), 7);
assert_eq!(decode_ioctl_number(encoded), 9);
assert_eq!(decode_ioctl_size(encoded), 0);
}
#[::fuchsia::test]
fn test_encode_read() {
let encoded = encode_ioctl_read::<u32>(1, 7);
assert_eq!(decode_ioctl_dir(encoded), _IOC_READ);
assert_eq!(decode_ioctl_type(encoded), 1);
assert_eq!(decode_ioctl_number(encoded), 7);
assert_eq!(decode_ioctl_size(encoded), std::mem::size_of::<u32>() as u32);
}
#[::fuchsia::test]
fn test_encode_write() {
let encoded = encode_ioctl_write::<u64>(2, 8);
assert_eq!(decode_ioctl_dir(encoded), _IOC_WRITE);
assert_eq!(decode_ioctl_type(encoded), 2);
assert_eq!(decode_ioctl_number(encoded), 8);
assert_eq!(decode_ioctl_size(encoded), std::mem::size_of::<u64>() as u32);
}
#[::fuchsia::test]
fn test_encode_write_read() {
let encoded = encode_ioctl_write_read::<u32>(2, 8);
assert_eq!(decode_ioctl_dir(encoded), _IOC_WRITE | _IOC_READ);
assert_eq!(decode_ioctl_type(encoded), 2);
assert_eq!(decode_ioctl_number(encoded), 8);
assert_eq!(decode_ioctl_size(encoded), std::mem::size_of::<u32>() as u32);
}
#[::fuchsia::test]
fn test_encode_ioctl_request() {
let encoded = encode_ioctl_write_read::<u32>(2, 8);
let request = IoctlRequest::new(encoded);
assert_eq!(decode_ioctl_dir(encoded), request.dir);
assert_eq!(decode_ioctl_type(encoded), request._type);
assert_eq!(decode_ioctl_number(encoded), request.number);
assert_eq!(decode_ioctl_size(encoded), request.size);
}
}