@@ -9,15 +9,17 @@ use core::str::FromStr;
99
1010use at_commands:: builder:: CommandBuilder ;
1111use at_commands:: parser:: CommandParser ;
12+ use embassy_sync:: { blocking_mutex:: raw:: CriticalSectionRawMutex , mutex:: Mutex } ;
1213use embassy_time:: { Duration , Timer } ;
1314use heapless:: Vec ;
1415
15- use crate :: embassy_net_modem:: CAP_SIZE ;
16+ use crate :: { embassy_net_modem:: CAP_SIZE , Error , LteLink } ;
1617
1718/// Provides a higher level API for controlling a given context.
1819pub struct Control < ' a > {
1920 control : super :: Control < ' a > ,
2021 cid : u8 ,
22+ lte_link : Mutex < CriticalSectionRawMutex , Option < LteLink > > ,
2123}
2224
2325/// Authentication parameters for the Packet Data Network (PDN).
@@ -78,24 +80,6 @@ pub enum AuthProt {
7880 Chap = 2 ,
7981}
8082
81- /// Error returned by control.
82- #[ derive( Clone , Copy , PartialEq , Debug ) ]
83- #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
84- pub enum Error {
85- /// Not enough space for command.
86- BufferTooSmall ,
87- /// Error parsing response from modem.
88- AtParseError ,
89- /// Error parsing IP addresses.
90- AddrParseError ,
91- }
92-
93- impl From < at_commands:: parser:: ParseError > for Error {
94- fn from ( _: at_commands:: parser:: ParseError ) -> Self {
95- Self :: AtParseError
96- }
97- }
98-
9983/// Status of a given context.
10084#[ derive( PartialEq , Debug ) ]
10185pub struct Status {
@@ -131,7 +115,11 @@ impl<'a> Control<'a> {
131115 ///
132116 /// `cid` indicates which PDP context to use, range 0-10.
133117 pub async fn new ( control : super :: Control < ' a > , cid : u8 ) -> Self {
134- Self { control, cid }
118+ Self {
119+ control,
120+ cid,
121+ lte_link : Mutex :: new ( None ) ,
122+ }
135123 }
136124
137125 /// Perform a raw AT command
@@ -148,15 +136,9 @@ impl<'a> Control<'a> {
148136 pub async fn configure ( & self , config : & PdConfig < ' _ > , pin : Option < & [ u8 ] > ) -> Result < ( ) , Error > {
149137 let mut cmd: [ u8 ; 256 ] = [ 0 ; 256 ] ;
150138
151- let op = CommandBuilder :: create_set ( & mut cmd, true )
152- . named ( "+CFUN" )
153- . with_int_parameter ( 0 )
154- . finish ( )
155- . map_err ( |_| Error :: BufferTooSmall ) ?;
156- let n = self . control . at_command ( op) . await ;
157- CommandParser :: parse ( n. as_bytes ( ) )
158- . expect_identifier ( b"OK" )
159- . finish ( ) ?;
139+ if let Some ( link) = self . lte_link . lock ( ) . await . take ( ) {
140+ link. deactivate ( ) . await ?;
141+ }
160142
161143 let mut op = CommandBuilder :: create_set ( & mut cmd, true )
162144 . named ( "+CGDCONT" )
@@ -165,7 +147,7 @@ impl<'a> Control<'a> {
165147 if let Some ( apn) = config. apn {
166148 op = op. with_string_parameter ( apn) ;
167149 }
168- let op = op. finish ( ) . map_err ( |_ | Error :: BufferTooSmall ) ?;
150+ let op = op. finish ( ) . map_err ( |s | Error :: BufferTooSmall ( Some ( s ) ) ) ?;
169151
170152 let n = self . control . at_command ( op) . await ;
171153 // info!("RES1: {}", unsafe { core::str::from_utf8_unchecked(&buf[..n]) });
@@ -183,7 +165,7 @@ impl<'a> Control<'a> {
183165 . with_string_parameter ( username)
184166 . with_string_parameter ( password) ;
185167 }
186- let op = op. finish ( ) . map_err ( |_ | Error :: BufferTooSmall ) ?;
168+ let op = op. finish ( ) . map_err ( |s | Error :: BufferTooSmall ( Some ( s ) ) ) ?;
187169
188170 let n = self . control . at_command ( op) . await ;
189171 // info!("RES2: {}", unsafe { core::str::from_utf8_unchecked(&buf[..n]) });
@@ -197,7 +179,7 @@ impl<'a> Control<'a> {
197179 . named ( "+CPIN" )
198180 . with_string_parameter ( pin)
199181 . finish ( )
200- . map_err ( |_ | Error :: BufferTooSmall ) ?;
182+ . map_err ( |s | Error :: BufferTooSmall ( Some ( s ) ) ) ?;
201183 let _ = self . control . at_command ( op) . await ;
202184 // Ignore ERROR which means no pin required
203185 }
@@ -212,7 +194,7 @@ impl<'a> Control<'a> {
212194 . named ( "+CGATT" )
213195 . with_int_parameter ( 1 )
214196 . finish ( )
215- . map_err ( |_ | Error :: BufferTooSmall ) ?;
197+ . map_err ( |s | Error :: BufferTooSmall ( Some ( s ) ) ) ?;
216198 let n = self . control . at_command ( op) . await ;
217199 CommandParser :: parse ( n. as_bytes ( ) )
218200 . expect_identifier ( b"OK" )
@@ -227,7 +209,7 @@ impl<'a> Control<'a> {
227209 . named ( "+CGATT" )
228210 . with_int_parameter ( 0 )
229211 . finish ( )
230- . map_err ( |_ | Error :: BufferTooSmall ) ?;
212+ . map_err ( |s | Error :: BufferTooSmall ( Some ( s ) ) ) ?;
231213 let n = self . control . at_command ( op) . await ;
232214 CommandParser :: parse ( n. as_bytes ( ) )
233215 . expect_identifier ( b"OK" )
@@ -241,7 +223,7 @@ impl<'a> Control<'a> {
241223 let op = CommandBuilder :: create_query ( & mut cmd, true )
242224 . named ( "+CGATT" )
243225 . finish ( )
244- . map_err ( |_ | Error :: BufferTooSmall ) ?;
226+ . map_err ( |s | Error :: BufferTooSmall ( Some ( s ) ) ) ?;
245227 let n = self . control . at_command ( op) . await ;
246228 let ( res, ) = CommandParser :: parse ( n. as_bytes ( ) )
247229 . expect_identifier ( b"+CGATT: " )
@@ -258,7 +240,7 @@ impl<'a> Control<'a> {
258240 let op = CommandBuilder :: create_query ( & mut cmd, true )
259241 . named ( "+CGATT" )
260242 . finish ( )
261- . map_err ( |_ | Error :: BufferTooSmall ) ?;
243+ . map_err ( |s | Error :: BufferTooSmall ( Some ( s ) ) ) ?;
262244 let n = self . control . at_command ( op) . await ;
263245 let ( res, ) = CommandParser :: parse ( n. as_bytes ( ) )
264246 . expect_identifier ( b"+CGATT: " )
@@ -280,7 +262,7 @@ impl<'a> Control<'a> {
280262 . named ( "+CGPADDR" )
281263 . with_int_parameter ( self . cid )
282264 . finish ( )
283- . map_err ( |_ | Error :: BufferTooSmall ) ?;
265+ . map_err ( |s | Error :: BufferTooSmall ( Some ( s ) ) ) ?;
284266 let n = self . control . at_command ( op) . await ;
285267 let ( _, ip1, ip2) = CommandParser :: parse ( n. as_bytes ( ) )
286268 . expect_identifier ( b"+CGPADDR: " )
@@ -308,7 +290,7 @@ impl<'a> Control<'a> {
308290 . named ( "+CGCONTRDP" )
309291 . with_int_parameter ( self . cid )
310292 . finish ( )
311- . map_err ( |_ | Error :: BufferTooSmall ) ?;
293+ . map_err ( |s | Error :: BufferTooSmall ( Some ( s ) ) ) ?;
312294 let n = self . control . at_command ( op) . await ;
313295 let ( _cid, _bid, _apn, _mask, gateway, dns1, dns2, _, _, _, _, _mtu) =
314296 CommandParser :: parse ( n. as_bytes ( ) )
@@ -368,41 +350,24 @@ impl<'a> Control<'a> {
368350
369351 /// Disable modem
370352 pub async fn disable ( & self ) -> Result < ( ) , Error > {
371- let mut cmd: [ u8 ; 256 ] = [ 0 ; 256 ] ;
372-
373- let op = CommandBuilder :: create_set ( & mut cmd, true )
374- . named ( "+CFUN" )
375- . with_int_parameter ( 0 )
376- . finish ( )
377- . map_err ( |_| Error :: BufferTooSmall ) ?;
378- let n = self . control . at_command ( op) . await ;
379- CommandParser :: parse ( n. as_bytes ( ) )
380- . expect_identifier ( b"OK" )
381- . finish ( ) ?;
382-
353+ if let Some ( link) = self . lte_link . lock ( ) . await . take ( ) {
354+ link. deactivate ( ) . await ?;
355+ } ;
383356 Ok ( ( ) )
384357 }
385358
386359 /// Enable modem
387360 pub async fn enable ( & self ) -> Result < ( ) , Error > {
388361 let mut cmd: [ u8 ; 256 ] = [ 0 ; 256 ] ;
389362
390- let op = CommandBuilder :: create_set ( & mut cmd, true )
391- . named ( "+CFUN" )
392- . with_int_parameter ( 1 )
393- . finish ( )
394- . map_err ( |_| Error :: BufferTooSmall ) ?;
395- let n = self . control . at_command ( op) . await ;
396- CommandParser :: parse ( n. as_bytes ( ) )
397- . expect_identifier ( b"OK" )
398- . finish ( ) ?;
363+ self . lte_link . lock ( ) . await . replace ( LteLink :: new ( ) . await ?) ;
399364
400365 // Make modem survive PDN detaches
401366 let op = CommandBuilder :: create_set ( & mut cmd, true )
402367 . named ( "%XPDNCFG" )
403368 . with_int_parameter ( 1 )
404369 . finish ( )
405- . map_err ( |_ | Error :: BufferTooSmall ) ?;
370+ . map_err ( |s | Error :: BufferTooSmall ( Some ( s ) ) ) ?;
406371 let n = self . control . at_command ( op) . await ;
407372 CommandParser :: parse ( n. as_bytes ( ) )
408373 . expect_identifier ( b"OK" )
0 commit comments