hardware 0.0.9

A no_std bare-metal hardware abstraction layer — all port I/O, memory and swap allocations are guarded at runtime. Do not consider this dependency stable before x.1.x
Documentation
pub const AT_PREFIX: &[u8] = b"AT";
pub const AT_CR: u8 = b'\r';

pub const MAX_CMD_LEN: usize = 128;
pub const MAX_RESPONSE_LEN: usize = 256;

#[derive(Clone, Copy, PartialEq)]
pub enum AtResult {
    Ok,
    Error,
    Timeout,
    Incomplete,
}

pub struct AtCommand {
    pub buf: [u8; MAX_CMD_LEN],
    pub len: usize,
}

pub struct AtResponse {
    pub buf: [u8; MAX_RESPONSE_LEN],
    pub len: usize,
    pub result: AtResult,
}

impl AtCommand {
    pub const fn empty() -> Self {
        AtCommand {
            buf: [0u8; MAX_CMD_LEN],
            len: 0,
        }
    }

    pub fn from_bytes(cmd: &[u8]) -> Self {
        let mut at = AtCommand::empty();
        let mut i = 0;
        while i < AT_PREFIX.len() && i < MAX_CMD_LEN {
            at.buf[i] = AT_PREFIX[i];
            i += 1;
        }
        let mut j = 0;
        while j < cmd.len() && i < MAX_CMD_LEN {
            at.buf[i] = cmd[j];
            i += 1;
            j += 1;
        }
        if i < MAX_CMD_LEN {
            at.buf[i] = AT_CR;
            i += 1;
        }
        at.len = i;
        at
    }

    pub fn bytes(&self) -> &[u8] {
        &self.buf[..self.len]
    }
}

impl AtResponse {
    pub const fn empty() -> Self {
        AtResponse {
            buf: [0u8; MAX_RESPONSE_LEN],
            len: 0,
            result: AtResult::Incomplete,
        }
    }

    pub fn push_byte(&mut self, b: u8) -> bool {
        if self.len >= MAX_RESPONSE_LEN {
            return false;
        }
        self.buf[self.len] = b;
        self.len += 1;
        true
    }

    pub fn check_complete(&mut self) {
        if self.len >= 4 {
            let tail = &self.buf[self.len - 4..self.len];
            if tail == b"\r\nOK" || (self.len >= 2 && &self.buf[self.len - 2..self.len] == b"OK") {
                self.result = AtResult::Ok;
                return;
            }
        }
        if self.len >= 7 {
            let tail = &self.buf[self.len - 7..self.len];
            if tail == b"\r\nERROR" || tail == b"ERROR\r\n" {
                self.result = AtResult::Error;
            }
        }
    }

    pub fn bytes(&self) -> &[u8] {
        &self.buf[..self.len]
    }
}

pub fn cmd_signal_quality() -> AtCommand {
    AtCommand::from_bytes(b"+CSQ")
}

pub fn cmd_network_registration() -> AtCommand {
    AtCommand::from_bytes(b"+CREG?")
}

pub fn cmd_operator() -> AtCommand {
    AtCommand::from_bytes(b"+COPS?")
}

pub fn cmd_sim_status() -> AtCommand {
    AtCommand::from_bytes(b"+CPIN?")
}

pub fn cmd_imei() -> AtCommand {
    AtCommand::from_bytes(b"+GSN")
}

pub fn cmd_model() -> AtCommand {
    AtCommand::from_bytes(b"+CGMM")
}