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 ) ]
3536pub 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 ) ]
4351pub 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 ) ]
5262pub 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 ) ]
7996pub 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 ) ]
91109pub 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