2 * Copyright (c) 2020 Tilman Sauerbeck (tilman at code-monkey de)
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 pub struct Shell<'a> {
28 tx_buf: &'a mut Buffer,
29 command_offset: usize,
30 command_buffer: [u8; 32],
34 fn usb_serial_read(c: *mut u8) -> bool;
37 struct ArgumentIter<'a> {
42 impl<'a> Iterator for ArgumentIter<'a> {
45 fn next(&mut self) -> Option<&'a [u8]> {
47 let mut start : Option<usize> = None;
49 // Find the start of the substring.
50 for o in self.offset..self.command.len() {
51 if self.command[o] != delimiter {
57 start.and_then(|start2| {
58 let mut end : Option<usize> = None;
60 // Find the end of the substring.
61 for o in start2..self.command.len() {
62 if self.command[o] == delimiter {
74 Some(&self.command[start2..end3])
80 fn read_char() -> Option<u8> {
84 if usb_serial_read(&mut c) {
93 storage: &'a mut dyn Storage,
97 pub fn new(tx_buf: &mut Buffer) -> Shell {
101 command_buffer: [0; 32],
105 pub fn update(&mut self, storage: &mut dyn Storage) {
106 let mut context = Context {
110 while let Some(c) = read_char() {
112 if self.command_offset != self.command_buffer.len() {
113 self.command_buffer[self.command_offset] = c;
114 self.command_offset += 1;
117 let command_length = self.command_offset;
118 self.command_offset = 0;
120 if command_length != self.command_buffer.len() {
121 self.command_buffer[command_length] = b'\0';
123 if command_length != 0 {
124 self.dispatch(command_length, &mut context);
127 self.command_buffer[self.command_offset] = b'\0';
129 self.tx_buf.write(b"maximum command length exceeded.\n");
132 self.tx_buf.write(b"$ ");
138 fn dispatch(&mut self, command_length: usize, mut context: &mut Context) {
139 let command : [u8; 32] = self.command_buffer;
141 let mut args_iter = ArgumentIter {
142 command: &command[0..command_length],
146 match args_iter.next() {
150 help Show this help message.
151 clear_storage Fully erase the flash's contents.
154 self.tx_buf.write(usage);
157 Some(b"clear_storage") => self.run_clear_storage(&mut context),
160 self.tx_buf.write(b"unknown_command: ");
161 self.tx_buf.write(other);
162 self.tx_buf.write(b"\n");
170 fn run_clear_storage(&self, context: &mut Context) {
171 context.storage.clear();