Skip to content
This repository was archived by the owner on Mar 7, 2021. It is now read-only.

Commit d8c6e90

Browse files
alexgeofft
authored andcommitted
Refs #55 -- added API for allocating character device numbers (#59)
1 parent 20005b3 commit d8c6e90

File tree

6 files changed

+111
-0
lines changed

6 files changed

+111
-0
lines changed

build.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ const INCLUDED_FUNCTIONS: &[&str] = &[
1919
"access_ok",
2020
"_copy_to_user",
2121
"_copy_from_user",
22+
"alloc_chrdev_region",
23+
"unregister_chrdev_region",
2224
];
2325
const INCLUDED_VARS: &[&str] = &[
2426
"EINVAL",

src/chrdev.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use core::ops::Range;
2+
3+
use bindings;
4+
use c_types;
5+
use error;
6+
7+
pub struct DeviceNumberRegion {
8+
dev: bindings::dev_t,
9+
count: usize,
10+
}
11+
12+
impl DeviceNumberRegion {
13+
pub fn allocate(
14+
minors: Range<usize>,
15+
name: &'static str,
16+
) -> error::KernelResult<DeviceNumberRegion> {
17+
if !name.ends_with('\x00') {
18+
return Err(error::Error::EINVAL);
19+
}
20+
21+
let count = minors.end - minors.start;
22+
let mut dev: bindings::dev_t = 0;
23+
let res = unsafe {
24+
bindings::alloc_chrdev_region(
25+
&mut dev,
26+
minors.start as bindings::dev_t,
27+
count as bindings::dev_t,
28+
name.as_ptr() as *const c_types::c_char,
29+
)
30+
};
31+
if res != 0 {
32+
return Err(error::Error::from_kernel_errno(res));
33+
}
34+
return Ok(DeviceNumberRegion { dev, count });
35+
}
36+
}
37+
38+
impl Drop for DeviceNumberRegion {
39+
fn drop(&mut self) {
40+
unsafe {
41+
bindings::unregister_chrdev_region(self.dev, self.count as bindings::dev_t);
42+
}
43+
}
44+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use core::panic::PanicInfo;
1111
mod allocator;
1212
pub mod bindings;
1313
mod c_types;
14+
pub mod chrdev;
1415
mod error;
1516
pub mod filesystem;
1617
#[macro_use]

tests/chrdev/Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "chrdev-tests"
3+
version = "0.1.0"
4+
authors = ["Alex Gaynor <alex.gaynor@gmail.com>", "Geoffrey Thomas <geofft@ldpreload.com>"]
5+
6+
[lib]
7+
crate-type = ["staticlib"]
8+
9+
[dependencies]
10+
linux-kernel-module = { path = "../.." }

tests/chrdev/src/lib.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#![no_std]
2+
#![feature(const_str_as_bytes)]
3+
4+
#[macro_use]
5+
extern crate linux_kernel_module;
6+
7+
struct ChrdevTestModule {
8+
_dev: linux_kernel_module::chrdev::DeviceNumberRegion,
9+
}
10+
11+
impl linux_kernel_module::KernelModule for ChrdevTestModule {
12+
fn init() -> linux_kernel_module::KernelResult<Self> {
13+
Ok(ChrdevTestModule {
14+
_dev: linux_kernel_module::chrdev::DeviceNumberRegion::allocate(
15+
0..1,
16+
"chrdev-tests\x00",
17+
)?,
18+
})
19+
}
20+
}
21+
22+
kernel_module!(
23+
ChrdevTestModule,
24+
author: "Alex Gaynor and Geoffrey Thomas",
25+
description: "A module for testing character devices",
26+
license: "GPL"
27+
);

tests/chrdev/tests.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
extern crate kernel_module_tests;
2+
3+
use kernel_module_tests::with_kernel_module;
4+
use std::fs;
5+
6+
#[test]
7+
fn test_proc_devices() {
8+
with_kernel_module(|| {
9+
let devices = fs::read_to_string("/proc/devices").unwrap();
10+
let dev_no_line = devices
11+
.lines()
12+
.find(|l| l.ends_with("chrdev-tests"))
13+
.unwrap();
14+
let elements = dev_no_line.rsplitn(2, " ").collect::<Vec<_>>();
15+
assert_eq!(elements.len(), 2);
16+
assert_eq!(elements[0], "chrdev-tests");
17+
assert!(elements[1].trim().parse::<u32>().is_ok());
18+
});
19+
20+
let devices = fs::read_to_string("/proc/devices").unwrap();
21+
assert!(
22+
devices
23+
.lines()
24+
.find(|l| l.ends_with("chrdev-tests"))
25+
.is_none()
26+
);
27+
}

0 commit comments

Comments
 (0)