3 -S`O@sdZdZddgZdZdZddlZddlZddlZddlm Z ddl Z ej d Z e d gZe d gZe d gZe d gZe dgZe dgZe dgZe dgZGdddeZe eddZddZedkrejedS)a =============================== XMODEM file transfer protocol =============================== .. $Id$ This is a literal implementation of XMODEM.TXT_, XMODEM1K.TXT_ and XMODMCRC.TXT_, support for YMODEM and ZMODEM is pending. YMODEM should be fairly easy to implement as it is a hack on top of the XMODEM protocol using sequence bytes ``0x00`` for sending file names (and some meta data). .. _XMODEM.TXT: doc/XMODEM.TXT .. _XMODEM1K.TXT: doc/XMODEM1K.TXT .. _XMODMCRC.TXT: doc/XMODMCRC.TXT Data flow example including error recovery ========================================== Here is a sample of the data flow, sending a 3-block message. It includes the two most common line hits - a garbaged block, and an ``ACK`` reply getting garbaged. ``CRC`` or ``CSUM`` represents the checksum bytes. XMODEM 128 byte blocks ---------------------- :: SENDER RECEIVER <-- NAK SOH 01 FE Data[128] CSUM --> <-- ACK SOH 02 FD Data[128] CSUM --> <-- ACK SOH 03 FC Data[128] CSUM --> <-- ACK SOH 04 FB Data[128] CSUM --> <-- ACK SOH 05 FA Data[100] CPMEOF[28] CSUM --> <-- ACK EOT --> <-- ACK XMODEM-1k blocks, CRC mode -------------------------- :: SENDER RECEIVER <-- C STX 01 FE Data[1024] CRC CRC --> <-- ACK STX 02 FD Data[1024] CRC CRC --> <-- ACK STX 03 FC Data[1000] CPMEOF[24] CRC CRC --> <-- ACK EOT --> <-- ACK Mixed 1024 and 128 byte Blocks ------------------------------ :: SENDER RECEIVER <-- C STX 01 FE Data[1024] CRC CRC --> <-- ACK STX 02 FD Data[1024] CRC CRC --> <-- ACK SOH 03 FC Data[128] CRC CRC --> <-- ACK SOH 04 FB Data[100] CPMEOF[28] CRC CRC --> <-- ACK EOT --> <-- ACK YMODEM Batch Transmission Session (1 file) ------------------------------------------ :: SENDER RECEIVER <-- C (command:rb) SOH 00 FF foo.c NUL[123] CRC CRC --> <-- ACK <-- C SOH 01 FE Data[128] CRC CRC --> <-- ACK SOH 02 FC Data[128] CRC CRC --> <-- ACK SOH 03 FB Data[100] CPMEOF[28] CRC CRC --> <-- ACK EOT --> <-- NAK EOT --> <-- ACK <-- C SOH 00 FF NUL[128] CRC CRC --> <-- ACK z#Wijnand Modderman z$Copyright (c) 2010 Wijnand Moddermanz!Copyright (c) 1981 Chuck ForsbergZMITz0.3.2N)partialxmodemCc@s|eZdZdZdddddddd d d d d ddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7d8d9d:d;dd?d@dAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddedfdgdhdidjdkdldmdndodpdqdrdsdtdudvdwdxdydzd{d|d}d~dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddgZdddZddd Zdd dZdddZdddZ dddZ d S(XMODEMa^ XMODEM Protocol handler, expects an object to read from and an object to write to. >>> def getc(size, timeout=1): ... return data or None ... >>> def putc(data, timeout=1): ... return size or None ... >>> modem = XMODEM(getc, putc) :param getc: Function to retreive bytes from a stream :type getc: callable :param putc: Function to transmit bytes to a stream :type putc: callable :param mode: XMODEM protocol mode :type mode: string :param pad: Padding character to make the packets match the packet size :type pad: char ri!iB ic0i@iPi`ipii)iJikiiiii1iis2iR"iRiBiribi9ii{iZiiiiib$iC4i iiditiDiTijiKi(i iiiiiS6ir&ii0ivifiViFi[izii8iiiiiHiXihixi@iai(i#8iiiiiHiii i+iZiJizijiqiP i3:i*iiiiiyiXi;iili|iLi\i",i<i` iAiiiii*i ihiIi~ini^iNi>i2.iQipiiiiii:iYixiiiʱii i-iNioii0i iPi%@iFpig`iiiiڳi=iii^iii"i2i5BiRiwbiVrii˥iiiniOi,i i4i$iiiftiGdi$TiDiۧiiii_i~ii<i&i6iiiWfivviFi4ViLimii/ișiiiiDXieHixi'hiii8i(i}i\i?iii؛iiiuJiTZi7jizi ii*i:i.iiliMiiiiɍi&|ilid\iELi<i,ii ii>i]i|iiiُiini6~iUNit^i.i>iircCs||_||_||_||_dS)N)getcputcmodepad)selfrrrrrT/home/CORPUSERS/88882248/cp-gnss-test/tinyusb-fork/hw/mcu/sony/cxd56/tools/xmodem.py__init__szXMODEM.__init__r<cCs$xtd|D]}|jt|q WdS)z9 Send an abort sequence using CAN bytes. rN)rangerCAN)rcounttimeoutZcounterrrrabortsz XMODEM.abort hNc Cs.ytddd|j}Wntk r2tdYnXd}d}d} x|jd} | r| tkr`d}PnL| tkrpd}Pn<| tkr|stdt j d| rd Sd} nt j d t | f|d7}||krB|j|d d SqBWd}d} d} d} x|j|}|st jd P| d7} |j||j}|r(|j|}n |j|}x|dkrL|jtn |jt|jt| g|jtd | g|j||r|jt|d?g|jt|d @gn|jt|g|jd|} | tkr| d7} t|tjr|| | |P| tkrT|d7}t|tjr*|| | |||kr6|j|d t jdd Sq6nTt j d|d7}t|tjr|| | |||kr6|j|d t jdd Sq6|j|d t j dd S| dd} qWxV|jt|jd|} | tkrPn,|d7}||kr|j|d t jdd SqWdS)a Send a stream via the XMODEM protocol. >>> stream = file('/etc/issue', 'rb') >>> print modem.send(stream) True Returns ``True`` upon succesful transmission or ``False`` in case of failure. :param stream: The stream object to send data from. :type stream: stream (file, etc.) :param retry: The maximum number of times to try to resend a failed packet before failing. :type retry: int :param timeout: The number of seconds to wait for a response before timing out. :type timeout: int :param quiet: If 0, it prints info to stderr. If 1, it does not print any info. :type quiet: int :param callback: Reference to a callback function that has the following signature. This is useful for getting status updates while a xmodem transfer is underway. Expected callback signature: def callback(total_packets, success_count, error_count) :type callback: callable i)rxmodem1kzAn invalid mode was suppliedrrz received CAN)fileFz#send ERROR expected NAK/CRC, got %s)rz sending EOTz excessive NAKs, transfer abortedzNot ACK, Not NAKz+excessive protocol errors, transfer abortedzprotocol errorz"EOT was not ACKd, transfer abortedT)dictrAttributeError ValueErrorrNAKCRCrprintsysstderrlogerrorordrreadinfoljustrcalc_crc calc_checksumrSOHSTXbytesACK isinstance collectionsCallableZwarningEOT)rstreamretryrquietcallback packet_size error_countcrc_modecancelcharZ success_countZ total_packetssequencedatacrcrrrsends                                 z XMODEM.sendrrcCsd}d}d} x||kr&|j|ddS|rT||dkrT|jtsttj||d7}n d}|jtsttj||d7}|jd|}|s|d7}qq|tkrPq|tkrPq|t kr| rdSd} q|d7}qWd}d} d} d} d} xx|tkrd} Pq|tkrd} Pq|t kr|jt | S|t kr8| r2dSd} q|sRt dt |tjd |d7}||kr|jdSqWd}d} t |jd} d t |jd}| | kr|| kr|j| d||}|rt |dd >t |d}|dd}tjd ||j|f||j|k}nB|d}|dd}tjd t ||j|ft ||j|k}|r| t|7} |j||jt | dd} |jd|}qn&|j| d||jd| | |f|jtqWdS)a  Receive a stream via the XMODEM protocol. >>> stream = file('/etc/issue', 'wb') >>> print modem.recv(stream) 2342 Returns the number of bytes received on success or ``None`` in case of failure. r)rNrrriz recv ERROR expected SOH/EOT, got)r!r"r#zCRC (%04x <> %04x)z checksum (checksum(%02x <> %02x)r$z expecting sequence %d, got %d/%drJrKrK)rrr)timesleepr(rr5r6rr<r8r*r/r+r,r-debugr3r4lenwrite)rr=rCr>rdelayr?rBrErDZ income_sizerArFZseq1Zseq2rGZcsumZvalidrrrrecvqs                    z XMODEM.recvcCsttt||dS)a Calculate the checksum for a given block of data, can also be used to update a checksum. >>> csum = modem.calc_checksum('hello') >>> csum = modem.calc_checksum('world', csum) >>> hex(csum) '0x3c' r$)summapr/)rrGZchecksumrrrr4s zXMODEM.calc_checksumcCs8x.|D]&}|d>|j|d?t|Ad@A}qW|d@S)a  Calculate the Cyclic Redundancy Check for a given block of data, can also be used to update a CRC. >>> crc = modem.calc_crc('hello') >>> crc = modem.calc_crc('world', crc) >>> hex(crc) '0xd5e3' r#r"i)crctableint)rrGrHrErrrr3s &zXMODEM.calc_crc)rr)rr)rrrN)rrrrr)r)r) __name__ __module__ __qualname____doc__rUrrrIrRr4r3rrrrr sP x r r )rc sBddl}ddl|jdd}|jddddd|j\}}t|d krT|jd d S|ddkrn|jdd Sdd}fdd}|dd krddl}||dd|d\}}t|d d} t |||j d} | j | dd} | j nZ|dd kr>||dd|d\}}t|d d} t |||j d} | j | dd} | j dS)Nrz/%prog [] filename filename)usagez-mz--moderzXMODEM mode (xmodem, xmodem1k))defaulthelpzinvalid argumentsrrIrRz invalid modecsLddlddl}tdtdd fdd }d fdd }||fS) Nrsisor^cs@jggg|\}}}|r(j|}nd}tdt|d|S)Nzgetc())selectr0r*repr)sizerwtfrG)rbr`rrr!s  z run.._func..getccsVjggg|\}}}|r8j|jt|}nd}tdt|t|d|S)Nzputc(ra)rbrPflushrOr*rc)rGrrerfrgrd)rbr_rrr+s  z run.._func..putc)r^)r^)rb subprocessr*)r`r_rirrr)rbr_r`r_funcs    zrun.._funccs j|jjd}|j|jfS)N)stdoutstdin)PopenPIPErkrl)commandpipe)rirr_pipe9szrun.._pipeZszz--xmodemrwb)rr#)r>Zrzrb)rIrR)optparseriZ OptionParserZ add_option parse_argsrOr.ioopenr rrRcloserI) rtparseroptionsargsrjrqrvrrr=rstatusr)rirrun s6          r}__main__)rZ __author__Z __copyright__Z __license__ __version__ZloggingrLr+ functoolsrr:Z getLoggerr-r7r5r6r<r8ZDLEr(rr)objectr ZXMODEM1kr}rWexitrrrrls6           D