diff options
Diffstat (limited to 'rust/kernel/firmware.rs')
-rw-r--r-- | rust/kernel/firmware.rs | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/rust/kernel/firmware.rs b/rust/kernel/firmware.rs new file mode 100644 index 000000000000..8c54096a6737 --- /dev/null +++ b/rust/kernel/firmware.rs @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Firmware load +//! +//! C header: [`include/linux/firmware.h`](../../../../include/linux/firmware.h") + +use crate::{ + bindings, + error::Error, + error::Result, + device::{RawDevice}, + str::CStr, + types::Opaque, +}; + +/// Pointer to a C firmware struct +pub struct Firmware { + pub fw: Opaque<*const bindings::firmware>, + fw_size: usize, +} + +impl Firmware { + /// Create a new firmware instance. + pub const fn new() -> Self { + Self { + fw: Opaque::uninit(), + fw_size: 0, + } + } + + pub fn request(&mut self, name: &CStr, dev: &dyn RawDevice) -> Result { + let ret = unsafe { bindings::request_firmware(self.fw.get(), + name.as_char_ptr(), dev.raw_device()) }; + if ret != 0 { + return Err(Error::from_errno(ret)); + } + self.fw_size = unsafe { (*(*self.fw.get())).size }; + Ok(()) + } + + pub fn request_nowarn(&mut self, name: &CStr, dev: &dyn RawDevice) -> Result { + let ret = unsafe { bindings::firmware_request_nowarn(self.fw.get(), + name.as_char_ptr(), dev.raw_device()) }; + if ret != 0 { + return Err(Error::from_errno(ret)); + } + self.fw_size = unsafe { (*(*self.fw.get())).size }; + Ok(()) + } + + pub fn size(&self) -> usize { + self.fw_size + } +} + +impl Drop for Firmware { + fn drop(&mut self) { + unsafe {bindings::release_firmware(*self.fw.get())}; + } +} |