summaryrefslogtreecommitdiff
path: root/rust/kernel/firmware.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/kernel/firmware.rs')
-rw-r--r--rust/kernel/firmware.rs60
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())};
+ }
+}