|
2 | 2 |
|
3 | 3 | //! Abstraction over byte stream devices, also known as serial I/O devices. |
4 | 4 |
|
5 | | -#[cfg(doc)] |
6 | | -use crate::Status; |
7 | 5 | use crate::proto::unsafe_protocol; |
8 | | -use crate::{Result, StatusExt}; |
| 6 | +use crate::{Error, Result, Status, StatusExt}; |
9 | 7 | use core::fmt::Write; |
10 | | -use uefi_raw::protocol::console::serial::SerialIoProtocol; |
| 8 | +use uefi_raw::protocol::console::serial::{ |
| 9 | + SerialIoProtocol, SerialIoProtocol_1_1, SerialIoProtocolRevision, |
| 10 | +}; |
| 11 | +use uguid::Guid; |
11 | 12 |
|
12 | 13 | pub use uefi_raw::protocol::console::serial::{ |
13 | 14 | ControlBits, Parity, SerialIoMode as IoMode, StopBits, |
@@ -52,6 +53,12 @@ pub use uefi_raw::protocol::console::serial::{ |
52 | 53 | pub struct Serial(SerialIoProtocol); |
53 | 54 |
|
54 | 55 | impl Serial { |
| 56 | + /// Returns the revision of the protocol. |
| 57 | + #[must_use] |
| 58 | + pub const fn revision(&self) -> SerialIoProtocolRevision { |
| 59 | + self.0.revision |
| 60 | + } |
| 61 | + |
55 | 62 | /// Reset the device. |
56 | 63 | /// |
57 | 64 | /// # Errors |
@@ -149,6 +156,46 @@ impl Serial { |
149 | 156 | |_| buffer_size, |
150 | 157 | ) |
151 | 158 | } |
| 159 | + |
| 160 | + /// Pointer to a GUID identifying the device connected to the serial port. |
| 161 | + /// |
| 162 | + /// This is either `Ok` if [`Self::revision`] is at least |
| 163 | + /// [`SerialIoProtocolRevision::REVISION_1_1`] or `Err` with |
| 164 | + /// [`Status::UNSUPPORTED`]. |
| 165 | + /// |
| 166 | + /// This GUID is `None` when the protocol is installed by the serial port |
| 167 | + /// driver and may be populated by a platform driver for a serial port with |
| 168 | + /// a known device attached. The GUID will remain `None` if there is no |
| 169 | + /// platform serial device identification information available. |
| 170 | + /// |
| 171 | + /// # Errors |
| 172 | + /// |
| 173 | + /// - [`Status::UNSUPPORTED`]: If the revision is older than |
| 174 | + /// [`SerialIoProtocolRevision::REVISION_1_1`]. |
| 175 | + pub fn device_type_guid(&self) -> Result<Option<&'_ Guid>> { |
| 176 | + let proto = self.as_revision_1_1()?; |
| 177 | + // SAFETY: spec guarantees the layout of the underlying type |
| 178 | + let device_type_guid = unsafe { proto.device_type_guid.as_ref() }; |
| 179 | + Ok(device_type_guid) |
| 180 | + } |
| 181 | + |
| 182 | + /// Casts the underlying [`SerialIoProtocol`] to an |
| 183 | + /// [`SerialIoProtocol_1_1`]. |
| 184 | + fn as_revision_1_1(&self) -> Result<&'_ SerialIoProtocol_1_1> { |
| 185 | + if self.revision() < SerialIoProtocolRevision::REVISION_1_1 { |
| 186 | + return Err(Error::from(Status::UNSUPPORTED)); |
| 187 | + } |
| 188 | + |
| 189 | + let ptr = &raw const self.0; |
| 190 | + // SAFETY: ptr is guaranteed to be not null and by checking the revision |
| 191 | + // we know the underlying allocation has the correct size. |
| 192 | + let protocol = unsafe { |
| 193 | + ptr.cast::<SerialIoProtocol_1_1>() |
| 194 | + .as_ref() |
| 195 | + .unwrap_unchecked() |
| 196 | + }; |
| 197 | + Ok(protocol) |
| 198 | + } |
152 | 199 | } |
153 | 200 |
|
154 | 201 | impl Write for Serial { |
|
0 commit comments