Skip to content

Commit 10e6ce2

Browse files
committed
Fixing build errors and adding missing documentation.
1 parent 7ce5eb1 commit 10e6ce2

File tree

1 file changed

+113
-30
lines changed

1 file changed

+113
-30
lines changed

src/lib.rs

Lines changed: 113 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
//! along with this program. If not, see <https://www.gnu.org/licenses/>.
2121
2222
#![no_std]
23+
#![deny(missing_docs)]
2324

2425
/// BIOS API semantic version for the API defined in this crate, as <0x00>
2526
/// <major> <minor> <patch>.
@@ -33,15 +34,24 @@ pub type OsStartFn = extern "C" fn(&Api) -> !;
3334
#[derive(Debug)]
3435
#[repr(C)]
3536
pub enum Error {
37+
/// An invalid device number was given to the function.
3638
InvalidDevice,
39+
/// The underlying hardware reported some error. The numeric code is BIOS
40+
/// implementation specific but may give some clues.
41+
DeviceError(u16),
42+
/// The underlying hardware could not accept the given configuration. The
43+
/// numeric code is BIOS implementation specific but may give some clues.
44+
UnsupportedConfiguration(u16),
3745
}
3846

3947
/// All API functions which can fail return this type. We don't use the
4048
/// `Result` type from the standard library because that isn't FFI safe and
4149
/// may change layout between compiler versions.
4250
#[repr(C)]
4351
pub enum Result<T> {
52+
/// The operation succeeded (the same as `core::result::Result::Ok`).
4453
Ok(T),
54+
/// The operation failed (the same as `core::result::Result::Err`).
4555
Err(Error),
4656
}
4757

@@ -50,7 +60,9 @@ pub enum Result<T> {
5060
/// FFI safe and may change layout between compiler versions.
5161
#[repr(C)]
5262
pub enum Option<T> {
63+
/// There is some data (the same as `core::option::Option::Some`)
5364
Some(T),
65+
/// There is no data (the same as `core::option::Option::None`)
5466
None,
5567
}
5668

@@ -62,18 +74,23 @@ pub struct Timeout(u32);
6274
/// valid until the callee returns to the caller. Is not null-terminated.
6375
#[repr(C)]
6476
#[derive(Clone)]
65-
pub struct ApiString(ApiByteSlice);
77+
pub struct ApiString<'a>(ApiByteSlice<'a>);
6678

6779
/// A Rust u8 slice, but compatible with FFI. Assume the lifetime is only valid
6880
/// until the callee returns to the caller.
6981
#[repr(C)]
7082
#[derive(Clone)]
71-
pub struct ApiByteSlice {
83+
pub struct ApiByteSlice<'a> {
84+
/// A pointer to the data
7285
pub data: *const u8,
86+
/// The number of bytes we are pointing at
7387
pub data_len: usize,
88+
/// A phantom object to hold the lifetime
89+
_phantom: core::marker::PhantomData<&'a [u8]>,
7490
}
7591

76-
/// Represents an instant in time between 2000-01-01T00:00:00Z and 2136-02-07T06:28:16Z.
92+
/// Represents an instant in time between 2000-01-01T00:00:00Z and
93+
/// 2136-02-07T06:28:16Z.
7794
#[repr(C)]
7895
#[derive(Debug, Clone)]
7996
pub struct Time {
@@ -86,7 +103,8 @@ pub struct Time {
86103

87104
/// The BIOS API.
88105
///
89-
/// All Neotron BIOSes should provide this structure to the OS initialisation function.
106+
/// All Neotron BIOSes should provide this structure to the OS initialisation
107+
/// function.
90108
#[repr(C)]
91109
pub struct Api {
92110
/// Gets the version number of the BIOS API. You need this value to
@@ -100,7 +118,7 @@ pub struct Api {
100118
/// (excluding the null) to make it easy to construct a Rust string. It is
101119
/// unspecified as to whether the string is located in Flash ROM or RAM
102120
/// (but it's likely to be Flash ROM).
103-
pub bios_version_get: extern "C" fn() -> ApiString,
121+
pub bios_version_get: extern "C" fn() -> ApiString<'static>,
104122
/// Get information about the Serial ports in the system. Serial ports are
105123
/// ordered octet-oriented pipes. You can push octets into them using a
106124
/// 'write' call, and pull bytes out of them using a 'read' call. They
@@ -174,95 +192,160 @@ pub mod serial {
174192
/// calculated.
175193
#[repr(C)]
176194
pub enum Parity {
195+
/// An extra parity bit is added to each word. There will be an odd
196+
/// number of `1` bits in the new word (old word + parity bit). This
197+
/// parity bit can be used to detect a single bitflip in each word, but
198+
/// it cannot correct that bitflip.
177199
Odd,
200+
/// An extra parity bit is added to each word. There will be an even
201+
/// number of `1` bits in the new word (old word + parity bit). This
202+
/// parity bit can be used to detect a single bitflip in each word, but
203+
/// it cannot correct that bitflip.
178204
Even,
205+
/// No extra parity bit is added.
179206
None,
180207
}
181208

182209
/// Whether to use hardware handshaking lines.
183210
#[repr(C)]
184211
pub enum Handshaking {
212+
/// No hardware handshaking - bytes will be dropped if there is an
213+
/// overflow
185214
None,
215+
/// The Data Terminal Equipment (DTE) asserts Request-To-Send (RTS) when
216+
/// it is ready to receive data, and the Data Communications Equipment
217+
/// (DCE) asserts Clear-To-Send (CTS) when it is ready to receive data.
186218
RtsCts,
219+
/// Each device will send a Transmit-Off (XOFF) byte (0x13) when its
220+
/// receiving serial buffer is full, and a Transmit-On (XON) byte (0x11)
221+
/// when there is buffer space and the transmission can be resumed.
222+
///
223+
/// Note that the driver will not replace or delete any XON or XOFF
224+
/// bytes sent to the stream, so both sides must avoid sending them as
225+
/// part of the normal data flow.
226+
XonXoff,
187227
}
188228

189229
/// The number of stop bits after each word.
190230
#[repr(C)]
191231
pub enum StopBits {
232+
/// One stop bit is added to each word
192233
One,
234+
/// Two stop bits are added to each word
193235
Two,
194236
}
195237

196238
/// The number of data bits in each word sent or received by the UART.
197239
#[repr(C)]
198240
pub enum DataBits {
241+
/// Each word comprises 7 data bits (plus start bit, stop bits and any
242+
/// parity bits)
199243
Seven,
244+
/// Each word comprises 8 data bits (plus start bit, stop bits and any
245+
/// parity bits)
200246
Eight,
201247
}
202248

203249
/// A particular configuration for a serial port.
204250
#[repr(C)]
205251
pub struct Config {
252+
/// The desired transmission speed, in bits per second (also known as
253+
/// the 'baud rate'). Some hardware implementations allow a free choice
254+
/// of data rate, while other limit you to a small subset (e.g. 9600,
255+
/// 57600 and 115200).
206256
pub data_rate_bps: u32,
257+
/// The desired number of data bits
207258
pub data_bits: DataBits,
259+
/// The desired number of stop bits
208260
pub stop_bits: StopBits,
261+
/// The desired parity configuration
209262
pub parity: Parity,
263+
/// The desired handshaking configuration
210264
pub handshaking: Handshaking,
211265
}
212266

213267
/// Information about a particular serial device.
214268
#[repr(C)]
215269
pub struct DeviceInfo {
216-
pub name: crate::ApiString,
270+
/// Some human-readable name for this serial device (e.g. `RS232` or
271+
/// `USB0`)
272+
pub name: crate::ApiString<'static>,
273+
/// The type of this serial device
217274
pub device_type: DeviceType,
218275
}
219276
}
220277

221-
impl core::fmt::Debug for ApiByteSlice {
278+
impl core::fmt::Debug for ApiByteSlice<'_> {
222279
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
280+
let slice = self.as_slice();
223281
write!(f, "[ ")?;
224-
for i in 0..self.data_len {
225-
write!(f, "0x{:02x}, ", unsafe { *self.data.add(i) })?;
282+
if let Some((last, rest)) = slice.split_last() {
283+
for i in rest.iter() {
284+
write!(f, "0x{:02x}, ", i)?;
285+
}
286+
write!(f, "0x{:02x} ", last)?;
226287
}
227288
write!(f, "]")
228289
}
229290
}
230291

231-
impl core::fmt::Debug for ApiString {
232-
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
233-
let buffer = unsafe { core::slice::from_raw_parts(self.0.data, self.0.data_len) };
234-
let s = unsafe { core::str::from_utf8_unchecked(&buffer) };
235-
write!(f, "{:?}", s)
292+
impl<'a> ApiByteSlice<'a> {
293+
/// Create a new byte slice we can send over the FFI. NB: By doing this Rust
294+
/// can't track lifetimes any more.
295+
pub fn new(s: &'a [u8]) -> ApiByteSlice<'a> {
296+
ApiByteSlice {
297+
data: s.as_ptr(),
298+
data_len: s.len(),
299+
_phantom: core::marker::PhantomData,
300+
}
236301
}
237-
}
238302

239-
impl core::fmt::Display for ApiString {
240-
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
241-
let buffer = unsafe { core::slice::from_raw_parts(self.0.data, self.0.data_len) };
242-
let s = unsafe { core::str::from_utf8_unchecked(&buffer) };
243-
write!(f, "{}", s)
303+
/// Turn this byte slice into a Rust byte slice.
304+
pub fn as_slice(&self) -> &[u8] {
305+
unsafe { core::slice::from_raw_parts(self.data, self.data_len) }
244306
}
245307
}
246308

247-
impl ApiByteSlice {
248-
pub const fn new(s: &[u8]) -> ApiByteSlice {
249-
ApiByteSlice {
250-
data: s.as_ptr(),
251-
data_len: s.len(),
252-
}
309+
impl<'a> From<&'a [u8]> for ApiByteSlice<'a> {
310+
/// Convert from a Rust byte slice into an FFI compatible byte slice
311+
fn from(input: &'a [u8]) -> ApiByteSlice<'a> {
312+
ApiByteSlice::new(input)
253313
}
254314
}
255315

256-
impl ApiString {
257-
pub const fn new(s: &str) -> ApiString {
316+
impl<'a> ApiString<'a> {
317+
/// Create a new string slice we can send over the FFI.
318+
pub fn new(s: &'a str) -> ApiString<'a> {
258319
ApiString(ApiByteSlice::new(s.as_bytes()))
259320
}
321+
322+
/// Turn this FFI string into a Rust string slice.
323+
pub fn as_str(&'a self) -> &'a str {
324+
unsafe { core::str::from_utf8_unchecked(self.0.as_slice()) }
325+
}
260326
}
261327

262-
impl From<&str> for ApiString {
263-
fn from(input: &str) -> ApiString {
328+
impl<'a> From<&'a str> for ApiString<'a> {
329+
/// Create a new FFI string from a string slice.
330+
fn from(input: &'a str) -> ApiString<'a> {
264331
ApiString::new(input)
265332
}
266333
}
267334

335+
impl core::fmt::Debug for ApiString<'_> {
336+
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
337+
let buffer = unsafe { core::slice::from_raw_parts(self.0.data, self.0.data_len) };
338+
let s = unsafe { core::str::from_utf8_unchecked(&buffer) };
339+
write!(f, "{:?}", s)
340+
}
341+
}
342+
343+
impl core::fmt::Display for ApiString<'_> {
344+
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
345+
let buffer = unsafe { core::slice::from_raw_parts(self.0.data, self.0.data_len) };
346+
let s = unsafe { core::str::from_utf8_unchecked(&buffer) };
347+
write!(f, "{}", s)
348+
}
349+
}
350+
268351
// End of file

0 commit comments

Comments
 (0)