1#[macro_use] extern crate log;
11#[macro_use] extern crate failure_derive;
12#[macro_use] extern crate nom;
13#[macro_use] extern crate derive_is_enum_variant;
14#[macro_use] extern crate num_derive;
15
16use std::fs::{File, OpenOptions};
17use tokio_file_unix::File as FileNb;
18use crate::codec::AtCodec;
19use crate::at::{AtResponse, AtCommand};
20use futures::{Future, Poll};
21use futures::sync::{oneshot, mpsc};
22use crate::future::{ModemRequest, ModemResponse, HuaweiModemFuture};
23use tokio_core::reactor::Handle;
24use tokio_codec::Decoder;
25pub use crate::errors::HuaweiResult;
26
27pub type HuaweiFuture<T> = Box<dyn Future<Item = T, Error = errors::HuaweiError>>;
29
30macro_rules! check_offset {
31 ($b:ident, $offset:ident, $reason:expr) => {
32 if $b.get($offset).is_none() {
33 return Err(HuaweiError::InvalidPdu(concat!("Offset check failed for: ", $reason)));
34 }
35 }
36}
37
38pub mod error_codes;
39pub mod errors;
40pub mod gsm_encoding;
41pub mod at;
42pub mod pdu;
43mod parse;
44pub mod codec;
45pub mod cmd;
46mod util;
47mod future;
48
49use std::path::Path;
50use crate::errors::HuaweiError;
51
52pub struct ModemResponseFuture {
54 rx: Result<oneshot::Receiver<ModemResponse>, ()>
55}
56impl Future for ModemResponseFuture {
57 type Item = ModemResponse;
58 type Error = HuaweiError;
59
60 fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
61 match self.rx {
62 Ok(ref mut rx) => Ok(rx.poll()?),
63 Err(_) => Err(HuaweiError::FutureDied)
64 }
65 }
66}
67pub struct HuaweiModem {
69 tx: mpsc::UnboundedSender<ModemRequest>,
70 urc: Option<mpsc::UnboundedReceiver<AtResponse>>
71}
72impl HuaweiModem {
73 pub fn new_from_path<P: AsRef<Path>>(path: P, h: &Handle) -> HuaweiResult<Self> {
75 let file = OpenOptions::new()
76 .read(true)
77 .write(true)
78 .open(path)?;
79 Self::new_from_file(file, h)
80 }
81 pub fn new_from_file(f: File, h: &Handle) -> HuaweiResult<Self> {
85 let ev = FileNb::new_nb(f)?.into_io(h)?;
86 let framed = AtCodec.framed(ev);
87 let (tx, rx) = mpsc::unbounded();
88 let (urctx, urcrx) = mpsc::unbounded();
89 let fut = HuaweiModemFuture::new(framed, rx, urctx);
90 h.spawn(fut.map_err(|e| {
91 error!("HuaweiModemFuture failed: {}", e);
92 error!("Backtrace: {}", e.backtrace());
93 ()
94 }));
95 Ok(Self { tx, urc: Some(urcrx) })
96 }
97 pub fn take_urc_rx(&mut self) -> Option<mpsc::UnboundedReceiver<AtResponse>> {
108 self.urc.take()
109 }
110 pub fn send_raw(&mut self, cmd: AtCommand) -> ModemResponseFuture {
112 let (tx, rx) = oneshot::channel();
113 let expected = cmd.expected();
114 let req = ModemRequest {
115 command: cmd,
116 notif: tx,
117 expected
118 };
119 if let Err(_) = self.tx.unbounded_send(req) {
120 ModemResponseFuture { rx: Err(()) }
121 }
122 else {
123 ModemResponseFuture { rx: Ok(rx) }
124 }
125 }
126}
127