21
21
import datetime
22
22
import io
23
23
import os
24
- import signal
25
24
import sys
26
25
import termios
27
26
@@ -54,47 +53,35 @@ def format_time(seconds):
54
53
return time
55
54
56
55
57
- class Timeout (Exception ):
58
- pass
59
-
60
-
61
- def timeout_handle (signum , frame ):
62
- sys .stderr .write ("timeout!\n " )
63
- sys .stderr .flush ()
64
- raise Timeout ("Timeout" )
65
-
66
-
67
56
def ymodem_stdread (size ):
68
57
fd = sys .stdin .fileno ()
69
58
old_settings = termios .tcgetattr (fd )
70
- signal .signal (signal .SIGALRM , timeout_handle )
71
- signal .alarm (3 )
72
- try :
73
- new_settings = termios .tcgetattr (fd )
74
- new_settings [3 ] &= ~ (termios .ICANON | termios .ECHO )
75
- termios .tcsetattr (fd , termios .TCSADRAIN , new_settings )
76
- data = sys .stdin .buffer .read (size )
77
- sys .stdin .flush ()
78
- return data
79
- except Timeout :
80
- return
81
- finally :
82
- signal .alarm (0 )
83
- termios .tcsetattr (fd , termios .TCSADRAIN , old_settings )
59
+ new_settings = termios .tcgetattr (fd )
60
+ new_settings [3 ] &= ~ (termios .ICANON | termios .ECHO )
61
+ termios .tcsetattr (fd , termios .TCSADRAIN , new_settings )
62
+ data = sys .stdin .buffer .read (size )
63
+ termios .tcflush (sys .stdin , termios .TCIFLUSH )
64
+ sys .stdin .flush ()
65
+ termios .tcsetattr (fd , termios .TCSADRAIN , old_settings )
66
+ return data
84
67
85
68
86
69
def ymodem_stdwrite (data ):
87
70
fd = sys .stdout .fileno ()
88
71
old_settings = termios .tcgetattr (fd )
89
- try :
90
- new_settings = termios .tcgetattr (fd )
91
- new_settings [3 ] &= ~ (termios .ICANON | termios .ECHO )
92
- termios .tcsetattr (fd , termios .TCSADRAIN , new_settings )
93
- data = sys .stdout .buffer .write (data )
94
- sys .stdout .flush ()
95
- return data
96
- finally :
97
- termios .tcsetattr (fd , termios .TCSADRAIN , old_settings )
72
+ new_settings = termios .tcgetattr (fd )
73
+ new_settings [3 ] &= ~ (termios .ICANON | termios .ECHO )
74
+ termios .tcsetattr (fd , termios .TCSADRAIN , new_settings )
75
+ data = sys .stdout .buffer .write (data )
76
+ termios .tcflush (sys .stdout , termios .TCIFLUSH )
77
+ sys .stdout .flush ()
78
+ termios .tcsetattr (fd , termios .TCSADRAIN , old_settings )
79
+ return data
80
+
81
+
82
+ def ymodem_stdclear ():
83
+ sys .stdin .flush ()
84
+ sys .stdout .flush ()
98
85
99
86
100
87
def ymodem_stdprogress (data ):
@@ -115,6 +102,13 @@ def ymodem_ser_write(data):
115
102
fd_serial .flush ()
116
103
117
104
105
+ def ymodem_ser_clear ():
106
+ global fd_serial
107
+
108
+ fd_serial .reset_input_buffer ()
109
+ fd_serial .reset_output_buffer ()
110
+
111
+
118
112
def calc_crc16 (data , crc = 0 ):
119
113
crctable = [
120
114
0x0000 ,
@@ -388,15 +382,21 @@ def __init__(
388
382
read = ymodem_stdread ,
389
383
write = ymodem_stdwrite ,
390
384
progress = ymodem_stdprogress ,
385
+ clear = ymodem_stdclear ,
391
386
timeout = 100 ,
387
+ maxretry = RETRIESMAX ,
392
388
debug = "" ,
393
389
customsize = 0 ,
394
390
):
395
391
self .read = read
396
392
self .write = write
393
+ self .clear = clear
397
394
self .timeout = timeout
395
+ self .maxretry = maxretry
398
396
self .progress = progress
399
397
self .customsize = customsize
398
+ self .retries = 0
399
+
400
400
if debug != "" :
401
401
self .debugfd = open (debug , "w+" )
402
402
else :
@@ -460,38 +460,39 @@ def recv_cmd(self, cmd):
460
460
461
461
return 0
462
462
463
+ def send_handshake (self ):
464
+ self .write (CRC )
465
+ while self .retries < self .maxretry :
466
+ chunk = self .read (1 )
467
+ if chunk == CRC :
468
+ return True
469
+ else :
470
+ self .retries += 1
471
+ self .clear ()
472
+
473
+ self .progress ("too many retries\n " )
474
+ return False
475
+
463
476
def send (self , filelist ):
464
- retries = 0
465
477
need_sendfile_num = len (filelist )
466
478
cnt = 0
467
479
now = datetime .datetime .now ()
468
480
base = float (int (now .timestamp () * 1000 )) / 1000
469
481
totolbytes = 0
470
482
471
- while retries < 10 :
472
- self .write (CRC )
473
- chunk = self .read (1 )
474
- if chunk == CRC :
475
- break
476
- else :
477
- retries += 1
478
-
479
- if retries == 10 :
480
- return False
483
+ if not self .send_handshake ():
484
+ return - EINVAL
481
485
482
486
while need_sendfile_num != 0 :
483
487
now = datetime .datetime .now ()
484
488
start = float (int (now .timestamp () * 1000 )) / 1000
485
489
self .init_pkt ()
486
490
self .head = SOH
487
491
filename = os .path .basename (filelist [cnt ])
488
-
489
- self .progress ("name:" + filename )
490
492
self .data = filename .encode ("utf-8" )
491
493
self .data = self .data + bytes ([0x00 ] * 1 )
492
494
filesize = os .path .getsize (filelist [cnt ])
493
495
sendfilesize = 0
494
- self .progress (" filesize:%d\n " % (filesize ))
495
496
self .data = self .data + str (filesize ).encode ("utf-8" )
496
497
self .data = self .data .ljust (self .get_pkt_size (), b"\x00 " )
497
498
self .send_pkt ()
@@ -500,14 +501,21 @@ def send(self, filelist):
500
501
if ret == - EAGAIN :
501
502
continue
502
503
elif ret == - EINVAL :
504
+ if self .send_handshake ():
505
+ continue
503
506
return ret
504
507
505
508
ret = self .recv_cmd (CRC )
506
509
if ret == - EAGAIN :
507
510
continue
508
511
elif ret == - EINVAL :
512
+ if self .send_handshake ():
513
+ continue
509
514
return ret
510
515
516
+ self .progress ("name:" + filename )
517
+ self .progress (" filesize:%d\n " % (filesize ))
518
+
511
519
self .add_seq ()
512
520
readfd = open (filelist [cnt ], "rb" )
513
521
self .progress (" " )
@@ -656,7 +664,6 @@ def recv_packet(self):
656
664
return 0
657
665
658
666
def recv (self ):
659
- retries = 0
660
667
now = datetime .datetime .now ()
661
668
base = float (int (now .timestamp () * 1000 )) / 1000
662
669
totolbytes = 0
@@ -673,12 +680,12 @@ def recv(self):
673
680
continue
674
681
675
682
elif ret < 0 :
676
- if retries > RETRIESMAX :
683
+ if self . retries > self . maxretry :
677
684
return - 1
678
685
679
686
self .progress ("recv ret %d\n " % ret )
680
687
self .debug ("recv frist packet\n " )
681
- retries += 1
688
+ self . retries += 1
682
689
continue
683
690
684
691
filename = bytes .decode (self .data .split (b"\x00 " )[0 ], "utf-8" )
@@ -699,9 +706,9 @@ def recv(self):
699
706
ret = self .recv_packet ()
700
707
if ret < 0 :
701
708
self .debug ("recv a bad data packet\n " )
702
- if retries > RETRIESMAX :
709
+ if self . retries > self . maxretry :
703
710
return - 1
704
- retries += 1
711
+ self . retries += 1
705
712
continue
706
713
707
714
size = 0
@@ -791,6 +798,13 @@ def recv(self):
791
798
""" ,
792
799
)
793
800
801
+ parser .add_argument (
802
+ "--maxretry" ,
803
+ type = int ,
804
+ default = RETRIESMAX ,
805
+ help = "This opthin set max retry for transmission" ,
806
+ )
807
+
794
808
parser .add_argument (
795
809
"--debug" , help = "This opthin is save debug log on host" , default = ""
796
810
)
@@ -821,9 +835,13 @@ def recv(self):
821
835
customsize = args .kblocksize * 1024 ,
822
836
read = ymodem_ser_read ,
823
837
write = ymodem_ser_write ,
838
+ clear = ymodem_ser_clear ,
839
+ maxretry = args .maxretry ,
824
840
)
825
841
else :
826
- sbrb = ymodem (debug = args .debug , customsize = args .kblocksize * 1024 )
842
+ sbrb = ymodem (
843
+ debug = args .debug , customsize = args .kblocksize * 1024 , maxretry = args .maxretry
844
+ )
827
845
828
846
if len (args .filelist ) == 0 :
829
847
sbrb .progress ("receiving\n " )
0 commit comments