X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=mware%2Fxmodem.c;h=2b9651dfc5973dff8c10742317719ce500f89d28;hb=56068931f6cfe45f14fd183dfe549692719701bc;hp=5861ac9acc9a07890116d1d462c3c9e1b13ec04b;hpb=b329fe228f081ec0d011874dfb3774e515648053;p=bertos.git diff --git a/mware/xmodem.c b/mware/xmodem.c index 5861ac9a..2b9651df 100755 --- a/mware/xmodem.c +++ b/mware/xmodem.c @@ -1,38 +1,65 @@ +#error This module has not been revised for the API changes in several DevLib modules /*! * \file * * \brief X-Modem serial transmission protocol (implementation) * * Suppots the CRC-16 and 1K-blocks variants of the standard. * \see ymodem.txt for the protocol description. * - * \version $Id$ - * \author Bernardo Innocenti - */ - -/* - * $Log$ - * Revision 1.5 2004/08/12 23:46:21 bernie - * Remove extra indentation level in switch statements. - * - * Revision 1.4 2004/08/12 23:35:50 bernie - * Replace a handmade loop with memset(). + * \todo Decouple this code from the LCD, buzzer and timer drivers + * introducing user hooks or macros like CHECK_ABORT. * - * Revision 1.3 2004/08/12 23:34:36 bernie - * Replace if/else with continue to reduce indentation level. + * \todo Break xmodem_send() and xmodem_recv() in smaller functions. * - * Revision 1.2 2004/08/12 23:24:07 bernie - * Rename UPDCRC() to UPDCRC16(). + * \todo Add CONFIG_* vars to exclude either the receiver or the sender, + * to reduce the footprint for applications that don't need both. * - * Revision 1.1 2004/08/11 19:54:22 bernie - * Import XModem protocol into DevLib. + * \todo Maybe convert drv/ser.c to the KFile interface for symmetry and + * flexibility. * + * \version $Id$ + * \author Bernardo Innocenti */ +/*#* + *#* $Log$ + *#* Revision 1.9 2005/11/04 16:20:02 bernie + *#* Fix reference to README.devlib in header. + *#* + *#* Revision 1.8 2004/08/25 14:12:09 rasky + *#* Aggiornato il comment block dei log RCS + *#* + *#* Revision 1.7 2004/08/15 06:30:06 bernie + *#* Make the buffer a local variable, as documented. + *#* + *#* Revision 1.6 2004/08/15 05:31:46 bernie + *#* Add an #error to spread some FUD about the quality of this module; + *#* Add a few TODOs from Rasky's review; + *#* Update to the new drv/ser.c API; + *#* Move FlushSerial() to drv/ser.c and generalize. + *#* + *#* Revision 1.5 2004/08/12 23:46:21 bernie + *#* Remove extra indentation level in switch statements. + *#* + *#* Revision 1.4 2004/08/12 23:35:50 bernie + *#* Replace a handmade loop with memset(). + *#* + *#* Revision 1.3 2004/08/12 23:34:36 bernie + *#* Replace if/else with continue to reduce indentation level. + *#* + *#* Revision 1.2 2004/08/12 23:24:07 bernie + *#* Rename UPDCRC() to UPDCRC16(). + *#* + *#* Revision 1.1 2004/08/11 19:54:22 bernie + *#* Import XModem protocol into DevLib. + *#* + *#*/ + #include "xmodem.h" #include @@ -79,21 +106,16 @@ #endif /* ARCH_BOOT */ -/*! Buffer to hold a block of data */ -static char block_buffer[XM_BUFSIZE]; - - /*! - * Decode serial driver errors and print - * them on the display. + * Decode serial driver errors and print them on the display. */ -static void SerialError(int retries) +static void print_serial_error(struct Serial *port, int retries) { serstatus_t err, status; /* Get serial error code and reset it */ - status = ser_getstatus(); - ser_setstatus(0); + status = ser_getstatus(port); + ser_setstatus(port, 0); /* Mostra tutti gli errori in sequenza */ for (err = 0; status != 0; status >>= 1, err++) @@ -110,21 +132,16 @@ static void SerialError(int retries) /*! - * Reset previous serial errors and flush the receive buffer - * (set a short timeout to speed up purge) + * \brief Receive a file using the XModem protocol. + * + * \param port Serial port to use for transfer + * \param fd Destination file + * + * \note This function allocates a large amount of stack (>1KB). */ -static void FlushSerial(void) -{ - ser_setstatus(0); - ser_settimeouts(200, SER_DEFTXTIMEOUT); - while (ser_getchar() != EOF) {} - ser_settimeouts(SER_DEFRXTIMEOUT, SER_DEFTXTIMEOUT); - ser_setstatus(0); -} - - -bool xmodem_recv(KFile *fd) +bool xmodem_recv(struct Serial *port, KFile *fd) { + char block_buffer[XM_BUFSIZE]; /* Buffer to hold a block of data */ int c, i, blocksize; int blocknr = 0, last_block_done = 0, retries = 0; char *buf; @@ -137,16 +154,16 @@ bool xmodem_recv(KFile *fd) lcd_printf(0, 2, LCD_FILL, "Starting Transfer..."); lcd_clear(); purge = true; - ser_settimeouts(SER_DEFRXTIMEOUT, SER_DEFTXTIMEOUT); - ser_setstatus(0); + ser_settimeouts(port, SER_DEFRXTIMEOUT, SER_DEFTXTIMEOUT); + ser_setstatus(port, 0); /* Send initial NAK to start transmission */ for(;;) { if (CHECK_ABORT) { - ser_putchar(XM_CAN); - ser_putchar(XM_CAN); + ser_putchar(XM_CAN, port); + ser_putchar(XM_CAN, port); lcd_printf(0, 2, LCD_FILL, "Transfer aborted"); return false; } @@ -162,13 +179,13 @@ bool xmodem_recv(KFile *fd) if (ser_getstatus()) SerialError(retries); - FlushSerial(); + ser_resync(port, 200); retries++; if (retries >= XM_MAXRETRIES) { - ser_putchar(XM_CAN); - ser_putchar(XM_CAN); + ser_putchar(XM_CAN, port); + ser_putchar(XM_CAN, port); lcd_printf(0, 2, LCD_FILL, "Transfer aborted"); return false; } @@ -179,21 +196,21 @@ bool xmodem_recv(KFile *fd) if (retries < XM_MAXCRCRETRIES) { lcd_printf(0, 2, LCD_FILL, "Request Tx (CRC)"); - ser_putchar(XM_C); + ser_putchar(XM_C, port); } else { /* Give up with CRC and fall back to checksum */ usecrc = false; lcd_printf(0, 2, LCD_FILL, "Request Tx (BCC)"); - ser_putchar(XM_NAK); + ser_putchar(XM_NAK, port); } } else - ser_putchar(XM_NAK); + ser_putchar(XM_NAK, port); } - switch (ser_getchar()) + switch (ser_getchar(port)) { case XM_STX: /* Start of header (1024-byte block) */ blocksize = 1024; @@ -204,10 +221,10 @@ bool xmodem_recv(KFile *fd) getblock: /* Get block number */ - c = ser_getchar(); + c = ser_getchar(port); /* Check complemented block number */ - if ((~c & 0xff) != ser_getchar()) + if ((~c & 0xff) != ser_getchar(port)) { lcd_printf(0, 3, LCD_FILL, "Bad blk (%d)", c); purge = true; @@ -234,7 +251,7 @@ bool xmodem_recv(KFile *fd) crc = 0; for (i = 0; i < blocksize; i++) { - if ((c = ser_getchar()) == EOF) + if ((c = ser_getchar(port)) == EOF) { purge = true; break; @@ -254,7 +271,7 @@ bool xmodem_recv(KFile *fd) break; /* Get the checksum byte or the CRC-16 MSB */ - if ((c = ser_getchar()) == EOF) + if ((c = ser_getchar(port)) == EOF) { purge = true; break; @@ -265,7 +282,7 @@ bool xmodem_recv(KFile *fd) crc = UPDCRC16(c, crc); /* Get CRC-16 LSB */ - if ((c = ser_getchar()) == EOF) + if ((c = ser_getchar(port)) == EOF) { purge = true; break; @@ -299,7 +316,7 @@ bool xmodem_recv(KFile *fd) if (fd->write(fd, block_buffer, blocksize)) { /* Acknowledge block and clear error counter */ - ser_putchar(XM_ACK); + ser_putchar(XM_ACK, port); retries = 0; last_block_done = blocknr; } @@ -313,7 +330,7 @@ bool xmodem_recv(KFile *fd) break; case XM_EOT: /* End of transmission */ - ser_putchar(XM_ACK); + ser_putchar(XM_ACK, port); lcd_printf(0, 2, LCD_FILL, "Transfer completed"); return true; @@ -330,8 +347,18 @@ bool xmodem_recv(KFile *fd) } -bool xmodem_send(KFile *fd) +/*! + * \brief Transmit a file using the XModem protocol. + * + * \param port Serial port to use for transfer + * \param fd Source file + * + * \note This function allocates a large amount of stack for + * the XModem transfer buffer (1KB). + */ +bool xmodem_send(struct Serial *port, KFile *fd) { + char block_buffer[XM_BUFSIZE]; /* Buffer to hold a block of data */ size_t size = -1; int blocknr = 1, retries = 0, c, i; bool proceed, usecrc = false; @@ -339,9 +366,9 @@ bool xmodem_send(KFile *fd) uint8_t sum; - ser_settimeouts(SER_DEFRXTIMEOUT, SER_DEFTXTIMEOUT); - ser_setstatus(0); - FlushSerial(); + ser_settimeouts(port, SER_DEFRXTIMEOUT, SER_DEFTXTIMEOUT); + ser_setstatus(port, 0); + ser_purge(port); lcd_printf(0, 2, LCD_FILL, "Wait remote host"); for(;;) @@ -352,7 +379,7 @@ bool xmodem_send(KFile *fd) if (CHECK_ABORT) return false; - switch (c = ser_getchar()) + switch (c = ser_getchar(port)) { case XM_NAK: case XM_C: @@ -407,7 +434,7 @@ bool xmodem_send(KFile *fd) if (!size) { - ser_putchar(XM_EOT); + ser_putchar(XM_EOT, port); continue; } @@ -415,16 +442,16 @@ bool xmodem_send(KFile *fd) memset(block_buffer + size, 0xFF, XM_BUFSIZE - size); /* Send block header (STX, blocknr, ~blocknr) */ - ser_putchar(XM_STX); - ser_putchar(blocknr & 0xFF); - ser_putchar(~blocknr & 0xFF); + ser_putchar(XM_STX, port); + ser_putchar(blocknr & 0xFF, port); + ser_putchar(~blocknr & 0xFF, port); /* Send block and compute its CRC/checksum */ sum = 0; crc = 0; for (i = 0; i < XM_BUFSIZE; i++) { - ser_putchar(block_buffer[i]); + ser_putchar(block_buffer[i], port); crc = UPDCRC16(block_buffer[i], crc); sum += block_buffer[i]; } @@ -434,10 +461,10 @@ bool xmodem_send(KFile *fd) { crc = UPDCRC16(0, crc); crc = UPDCRC16(0, crc); - ser_putchar(crc >> 8); - ser_putchar(crc & 0xFF); + ser_putchar(crc >> 8, port); + ser_putchar(crc & 0xFF, port); } else - ser_putchar(sum); + ser_putchar(sum, port); } }