12
12
import msvcrt
13
13
import threading
14
14
15
- stop_getkey_thread = False
16
-
17
15
def init_getkey (callback ):
18
- global stop_getkey_thread
19
-
20
16
loop = asyncio .get_event_loop ()
21
17
def getkey_thread ():
22
18
while True :
23
19
c = msvcrt .getch ()
24
- if stop_getkey_thread :
25
- return
20
+ # HACK: This may still attempt to use the loop
21
+ # after it is closed - see comment below.
26
22
loop .call_soon_threadsafe (callback , c )
27
- stop_getkey_thread = False
28
23
threading .Thread (target = getkey_thread , daemon = True ).start ()
29
24
30
25
def deinit_getkey ():
31
26
# Python threads suck.
32
- global stop_getkey_thread
33
- stop_getkey_thread = True
27
+ pass
34
28
else :
35
29
import termios
36
30
@@ -128,15 +122,23 @@ def encode(self):
128
122
129
123
130
124
class Flterm :
131
- def __init__ (self , kernel_image , kernel_address ):
125
+ def __init__ (self , port , speed , kernel_image , kernel_address ):
132
126
self .kernel_image = kernel_image
133
127
self .kernel_address = kernel_address
134
- self .magic_detect_buffer = b"\x00 " * len (sfl_magic_req )
128
+
129
+ self .port = asyncserial .AsyncSerial (port , baudrate = speed )
130
+
131
+ self .keyqueue = asyncio .Queue (100 )
132
+ def getkey_callback (c ):
133
+ self .keyqueue .put_nowait (c )
134
+ init_getkey (getkey_callback )
135
+
136
+ self .main_task = asyncio .ensure_future (self .main_coro ())
135
137
136
138
async def send_frame (self , frame ):
137
139
while retry :
138
- self .writer .write (frame .encode ())
139
- reply = await self .reader .read (1 )
140
+ await self .port .write (frame .encode ())
141
+ reply = await self .port .read (1 )
140
142
if reply == sfl_ack_success :
141
143
return
142
144
elif reply == sfl_ack_crcerror :
@@ -184,7 +186,7 @@ async def boot(self):
184
186
185
187
async def answer_magic (self ):
186
188
print ("[FLTERM] Received firmware download request from the device." )
187
- self .writer .write (sfl_magic_ack )
189
+ await self .port .write (sfl_magic_ack )
188
190
try :
189
191
await self .upload (self .kernel_image , self .kernel_address )
190
192
except FileNotFoundError :
@@ -193,37 +195,44 @@ async def answer_magic(self):
193
195
await self .boot ()
194
196
print ("[FLTERM] Done." );
195
197
196
- async def reader_coro (self ):
198
+ async def main_coro (self ):
199
+ magic_detect_buffer = b"\x00 " * len (sfl_magic_req )
197
200
while True :
198
- c = await self .reader .read (1 )
199
- if c == b"\r " :
200
- sys .stdout .write (b"\n " )
201
- else :
202
- sys .stdout .buffer .write (c )
203
- sys .stdout .flush ()
201
+ fs = [asyncio .ensure_future (self .port .read (1024 )),
202
+ asyncio .ensure_future (self .keyqueue .get ())]
203
+ try :
204
+ done , pending = await asyncio .wait (
205
+ fs , return_when = asyncio .FIRST_COMPLETED )
206
+ except :
207
+ for f in fs :
208
+ f .cancel ()
209
+ raise
210
+ for f in pending :
211
+ f .cancel ()
212
+ await asyncio .wait ([f ])
213
+
214
+ if fs [0 ] in done :
215
+ c = fs [0 ].result ()
216
+ if c == b"\r " :
217
+ sys .stdout .write (b"\n " )
218
+ else :
219
+ sys .stdout .buffer .write (c )
220
+ sys .stdout .flush ()
221
+
222
+ if fs [1 ] in done :
223
+ c = fs [1 ].result ()
224
+ await self .port .write (c )
204
225
205
226
if self .kernel_image is not None :
206
- self .magic_detect_buffer = self .magic_detect_buffer [1 :] + c
207
- if self .magic_detect_buffer == sfl_magic_req :
208
- self .answer_magic ()
209
-
210
- def getkey_callback (self , c ):
211
- self .writer .write (c )
212
-
213
- async def open (self , port , baudrate ):
214
- self .reader , self .writer = await asyncserial .open_serial_connection (
215
- port , baudrate = baudrate )
216
- self .reader_task = asyncio .ensure_future (self .reader_coro ())
217
- init_getkey (self .getkey_callback )
227
+ magic_detect_buffer = magic_detect_buffer [1 :] + c
228
+ if magic_detect_buffer == sfl_magic_req :
229
+ await self .answer_magic ()
218
230
219
231
async def close (self ):
220
232
deinit_getkey ()
221
- self .reader_task .cancel ()
222
- try :
223
- await asyncio .wait_for (self .reader_task , None )
224
- except asyncio .CancelledError :
225
- pass
226
- self .writer .close ()
233
+ self .main_task .cancel ()
234
+ await asyncio .wait ([self .main_task ])
235
+ self .port .close ()
227
236
228
237
229
238
def _get_args ():
@@ -244,14 +253,11 @@ def main():
244
253
loop = asyncio .get_event_loop ()
245
254
try :
246
255
args = _get_args ()
247
- flterm = Flterm (args .kernel , args .kernel_adr )
248
- loop .run_until_complete (
249
- flterm .open (args .port , args .speed ))
256
+ flterm = Flterm (args .port , args .speed , args .kernel , args .kernel_adr )
250
257
try :
251
258
loop .run_forever ()
252
259
finally :
253
- loop .run_until_complete (
254
- flterm .close ())
260
+ loop .run_until_complete (flterm .close ())
255
261
finally :
256
262
loop .close ()
257
263
0 commit comments