22
33use crate :: { bios, osprintln, Ctx , API } ;
44
5+ use super :: { parse_u8, parse_usize} ;
6+
57pub static LSBLK_ITEM : menu:: Item < Ctx > = menu:: Item {
68 item_type : menu:: ItemType :: Callback {
79 function : lsblk,
@@ -65,6 +67,32 @@ pub static SHUTDOWN_ITEM: menu::Item<Ctx> = menu::Item {
6567 help : Some ( "Shutdown the system" ) ,
6668} ;
6769
70+ pub static I2C_ITEM : menu:: Item < Ctx > = menu:: Item {
71+ item_type : menu:: ItemType :: Callback {
72+ function : i2c,
73+ parameters : & [
74+ menu:: Parameter :: Mandatory {
75+ parameter_name : "bus_idx" ,
76+ help : Some ( "I2C bus index" ) ,
77+ } ,
78+ menu:: Parameter :: Mandatory {
79+ parameter_name : "dev_addr" ,
80+ help : Some ( "7-bit I2C device address" ) ,
81+ } ,
82+ menu:: Parameter :: Mandatory {
83+ parameter_name : "tx_bytes" ,
84+ help : Some ( "Hex string to transmit" ) ,
85+ } ,
86+ menu:: Parameter :: Mandatory {
87+ parameter_name : "rx_count" ,
88+ help : Some ( "How many bytes to receive" ) ,
89+ } ,
90+ ] ,
91+ } ,
92+ command : "i2c" ,
93+ help : Some ( "Do an I2C transaction on a bus" ) ,
94+ } ;
95+
6896/// Called when the "lsblk" command is executed.
6997fn lsblk ( _menu : & menu:: Menu < Ctx > , _item : & menu:: Item < Ctx > , _args : & [ & str ] , _ctx : & mut Ctx ) {
7098 let api = API . get ( ) ;
@@ -195,7 +223,6 @@ fn lsuart(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, _args: &[&str], _ctx
195223/// Called when the "shutdown" command is executed.
196224fn shutdown ( _menu : & menu:: Menu < Ctx > , item : & menu:: Item < Ctx > , args : & [ & str ] , _ctx : & mut Ctx ) {
197225 let api = API . get ( ) ;
198-
199226 if let Ok ( Some ( _) ) = menu:: argument_finder ( item, args, "reboot" ) {
200227 osprintln ! ( "Rebooting..." ) ;
201228 ( api. power_control ) ( bios:: PowerMode :: Reset ) ;
@@ -208,4 +235,99 @@ fn shutdown(_menu: &menu::Menu<Ctx>, item: &menu::Item<Ctx>, args: &[&str], _ctx
208235 }
209236}
210237
238+ /// Called when the "i2c" command is executed.
239+ fn i2c ( _menu : & menu:: Menu < Ctx > , item : & menu:: Item < Ctx > , args : & [ & str ] , _ctx : & mut Ctx ) {
240+ let bus_idx = menu:: argument_finder ( item, args, "bus_idx" ) . unwrap ( ) ;
241+ let dev_addr = menu:: argument_finder ( item, args, "dev_addr" ) . unwrap ( ) ;
242+ let tx_bytes = menu:: argument_finder ( item, args, "tx_bytes" ) . unwrap ( ) ;
243+ let rx_count = menu:: argument_finder ( item, args, "rx_count" ) . unwrap ( ) ;
244+
245+ let ( Some ( bus_idx) , Some ( dev_addr) , Some ( tx_bytes) , Some ( rx_count) ) =
246+ ( bus_idx, dev_addr, tx_bytes, rx_count)
247+ else {
248+ osprintln ! ( "Missing arguments." ) ;
249+ return ;
250+ } ;
251+
252+ let mut tx_buffer: heapless:: Vec < u8 , 16 > = heapless:: Vec :: new ( ) ;
253+
254+ for hex_pair in tx_bytes. as_bytes ( ) . chunks ( 2 ) {
255+ let Some ( top) = hex_digit ( hex_pair[ 0 ] ) else {
256+ osprintln ! ( "Bad hex." ) ;
257+ return ;
258+ } ;
259+ let Some ( bottom) = hex_digit ( hex_pair[ 1 ] ) else {
260+ osprintln ! ( "Bad hex." ) ;
261+ return ;
262+ } ;
263+ let byte = top << 4 | bottom;
264+ let Ok ( _) = tx_buffer. push ( byte) else {
265+ osprintln ! ( "Too much hex." ) ;
266+ return ;
267+ } ;
268+ }
269+
270+ let Ok ( bus_idx) = parse_u8 ( bus_idx) else {
271+ osprintln ! ( "Bad bus_idx" ) ;
272+ return ;
273+ } ;
274+
275+ let Ok ( dev_addr) = parse_u8 ( dev_addr) else {
276+ osprintln ! ( "Bad dev_addr" ) ;
277+ return ;
278+ } ;
279+
280+ let Ok ( rx_count) = parse_usize ( rx_count) else {
281+ osprintln ! ( "Bad rx count." ) ;
282+ return ;
283+ } ;
284+
285+ let mut rx_buf = [ 0u8 ; 16 ] ;
286+
287+ let Some ( rx_buf) = rx_buf. get_mut ( 0 ..rx_count) else {
288+ osprintln ! ( "Too much rx." ) ;
289+ return ;
290+ } ;
291+
292+ let api = API . get ( ) ;
293+
294+ match ( api. i2c_write_read ) (
295+ bus_idx,
296+ dev_addr,
297+ tx_buffer. as_slice ( ) . into ( ) ,
298+ bios:: FfiByteSlice :: empty ( ) ,
299+ rx_buf. into ( ) ,
300+ ) {
301+ bios:: FfiResult :: Ok ( _) => {
302+ osprintln ! ( "Ok, got {:x?}" , rx_buf) ;
303+ }
304+ bios:: FfiResult :: Err ( e) => {
305+ osprintln ! ( "Failed: {:?}" , e) ;
306+ }
307+ }
308+ }
309+
310+ /// Convert an ASCII hex digit into a number
311+ fn hex_digit ( input : u8 ) -> Option < u8 > {
312+ match input {
313+ b'0' => Some ( 0 ) ,
314+ b'1' => Some ( 1 ) ,
315+ b'2' => Some ( 2 ) ,
316+ b'3' => Some ( 3 ) ,
317+ b'4' => Some ( 4 ) ,
318+ b'5' => Some ( 5 ) ,
319+ b'6' => Some ( 6 ) ,
320+ b'7' => Some ( 7 ) ,
321+ b'8' => Some ( 8 ) ,
322+ b'9' => Some ( 9 ) ,
323+ b'a' | b'A' => Some ( 10 ) ,
324+ b'b' | b'B' => Some ( 11 ) ,
325+ b'c' | b'C' => Some ( 12 ) ,
326+ b'd' | b'D' => Some ( 13 ) ,
327+ b'e' | b'E' => Some ( 14 ) ,
328+ b'f' | b'F' => Some ( 15 ) ,
329+ _ => None ,
330+ }
331+ }
332+
211333// End of file
0 commit comments