common: Implement the "get" shell command.
authorTilman Sauerbeck <tilman@code-monkey.de>
Thu, 9 Jan 2020 14:18:25 +0000 (15:18 +0100)
committerTilman Sauerbeck <tilman@code-monkey.de>
Thu, 9 Jan 2020 20:16:04 +0000 (21:16 +0100)
Retrieves a recording in yenc format.

src/common/shell.rs

index bb59b62e322f62edd5e81685d9cf4664361f3837..59472f6c9eb029d5e4aa6c70649586fa2a7f379c 100644 (file)
@@ -79,6 +79,44 @@ impl<'a> Iterator for ArgumentIter<'a> {
     }
 }
 
+fn atoi32(s: &[u8]) -> Option<u32> {
+    let mut u = 0u32;
+
+    for o in 0..s.len() {
+        let c = s[o];
+        let zero = b'0' as u8;
+        let nine = b'9' as u8;
+
+        if c < zero || c > nine {
+            return None;
+        }
+
+        let d = (c - zero) as u32;
+
+        if let Some(u2) = u.checked_mul(10) {
+            if let Some(u3) = u2.checked_add(d) {
+                u = u3;
+            } else {
+                return None;
+            }
+        } else {
+            return None;
+        }
+    }
+
+    Some(u)
+}
+
+fn atoi16(s: &[u8]) -> Option<u16> {
+    atoi32(s).and_then(|u| {
+        if u <= u16::max_value() as u32 {
+            Some(u as u16)
+        } else {
+            None
+        }
+    })
+}
+
 fn read_char() -> Option<u8> {
     unsafe {
         let mut c = b'\0';
@@ -159,6 +197,7 @@ impl<'a> Shell<'a> {
                 let usage = b"\
 Supported commands:
     help           Show this help message.
+    get REC_ID     Retrieve recording.
     clear_storage  Fully erase the flash's contents.
     dump_storage   Dump the flash's contents.
 ";
@@ -166,6 +205,7 @@ Supported commands:
                 self.tx_buf.write(usage);
             },
 
+            Some(b"get") => self.run_get(logger, &mut args_iter),
             Some(b"clear_storage") => self.run_clear_storage(logger),
             Some(b"dump_storage") => self.run_dump_storage(logger),
 
@@ -180,6 +220,44 @@ Supported commands:
         }
     }
 
+    fn run_get(&mut self, logger: &mut Logger, args_iter: &mut ArgumentIter) {
+        if let Some(recording_id_s) = args_iter.next() {
+            if let Some(recording_id) = atoi16(recording_id_s) {
+                if logger.has_recording(recording_id) {
+                    self.tx_buf.write(b"waiting for receiver to start...\n");
+                    self.tx_buf.flush();
+
+                    let have_receiver = read_char_delay_ms(5000).map(|c| {
+                        c == b'R'
+                    }).map_or_else(|| {
+                        false
+                    }, |_| {
+                        let result = logger.get_recording(recording_id,
+                                                          self.tx_buf);
+
+                        if result.is_err() {
+                            self.tx_buf.write(b"get: failed to retrieve recording\n");
+                        }
+
+                        true
+                    });
+
+                    if !have_receiver {
+                        self.tx_buf.write(b"no signal from receiver\n");
+                    }
+                } else {
+                    self.tx_buf.write(b"get: no such recording\n");
+                }
+            } else {
+                self.tx_buf.write(b"get: invalid argument\n");
+            }
+        } else {
+            self.tx_buf.write(b"get: missing argument\n");
+        }
+
+        self.tx_buf.flush();
+    }
+
     fn run_clear_storage(&self, logger: &mut Logger) {
         logger.storage.clear();
     }