aboutsummaryrefslogtreecommitdiffstats
path: root/com32/sysdump/be_ymodem.c
diff options
context:
space:
mode:
Diffstat (limited to 'com32/sysdump/be_ymodem.c')
-rw-r--r--com32/sysdump/be_ymodem.c116
1 files changed, 61 insertions, 55 deletions
diff --git a/com32/sysdump/be_ymodem.c b/com32/sysdump/be_ymodem.c
index 632758d9..b36bd039 100644
--- a/com32/sysdump/be_ymodem.c
+++ b/com32/sysdump/be_ymodem.c
@@ -17,6 +17,11 @@ enum {
CAN = 0x18,
};
+struct ymodem_state {
+ struct serial_if serial;
+ uint16_t seq;
+};
+
/*
* Append a CRC16 to a block
*/
@@ -65,101 +70,102 @@ static void add_crc16(uint8_t * blk, int len)
*blk = crc;
}
-static void send_ack(struct backend *be, const uint8_t *blk, size_t bytes);
+static void send_ack(struct ymodem_state *ym, const uint8_t *blk,
+ size_t bytes);
-static void send_ack_blk(struct backend *be, uint8_t *blk)
+static void send_ack_blk(struct ymodem_state *ym, uint8_t *blk)
{
- printf("Sending block %u...\r", be->ymodem.seq);
+ printf("Sending block %u...\r", ym->seq);
blk[0] = STX;
- blk[1] = be->ymodem.seq++;
+ blk[1] = ym->seq++;
blk[2] = ~blk[1];
add_crc16(blk+3, 1024);
- send_ack(be, blk, 1024+5);
+ send_ack(ym, blk, 1024+5);
}
-static void send_ack(struct backend *be, const uint8_t *blk, size_t bytes)
+static void send_ack(struct ymodem_state *ym, const uint8_t *blk, size_t bytes)
{
uint8_t ack_buf;
- serial_write(&be->ymodem.serial, blk, bytes);
+ serial_write(&ym->serial, blk, bytes);
do {
do {
- serial_read(&be->ymodem.serial, &ack_buf, 1);
+ serial_read(&ym->serial, &ack_buf, 1);
} while (ack_buf != ACK && ack_buf != NAK);
} while (ack_buf == NAK);
}
-static int be_ymodem_open(struct backend *be, const char *argv[], size_t len)
+static int be_ymodem_write(struct backend *be)
{
- uint8_t ack_buf, blk_buf[1024 + 5];
+ static const uint8_t eot_buf = EOT;
+ uint8_t ack_buf;
+ uint8_t blk_buf[1024 + 5];
+ struct ymodem_state ym;
+ const char *buf;
+ size_t len, chunk;
- be->ymodem.seq = 0;
+ ym.seq = 0;
/* Initialize serial port */
- if (serial_init(&be->ymodem.serial, argv+1))
+ if (serial_init(&ym.serial, &be->argv[1]))
return -1;
-
+
/* Wait for initial handshake */
printf("Waiting for handshake...\n");
do {
- serial_read(&be->ymodem.serial, &ack_buf, 1);
+ serial_read(&ym.serial, &ack_buf, 1);
} while (ack_buf != 'C');
- snprintf((char *)blk_buf+3, 1024, "%s%c%zu", argv[0], 0, len);
- send_ack_blk(be, blk_buf);
+ /* Send filename block */
+ snprintf((char *)blk_buf+3, 1024, "%s%c%zu", be->argv[0], 0, be->zbytes);
+ send_ack_blk(&ym, blk_buf);
- return 0;
-}
-
-static int be_ymodem_write(struct backend *be, const char *buf, size_t len)
-{
- static const uint8_t eot_buf = EOT;
- uint8_t ack_buf;
- uint8_t blk_buf[1024 + 5];
-
- memcpy(blk_buf+3, buf, len);
- if (len < 1024)
- memset(blk_buf+3+1024-len, 0x1a, 1024-len);
+ buf = be->outbuf;
+ len = be->zbytes;
- send_ack_blk(be, blk_buf);
+ while (len) {
+ chunk = len < 1024 ? len : 1024;
- if (len < 1024) {
- printf("\nSending EOT...\n");
- send_ack(be, &eot_buf, 1);
+ memcpy(blk_buf+3, buf, chunk);
+ if (chunk < 1024)
+ memset(blk_buf+3+1024-chunk, 0x1a, 1024-chunk);
- printf("Waiting for handshake...\n");
- do {
- serial_read(&be->ymodem.serial, &ack_buf, 1);
- } while (ack_buf != 'C');
- be->ymodem.seq = 0;
-
- printf("Sending batch termination block...\n");
- memset(blk_buf+3, 0, 128);
- blk_buf[0] = SOH;
- blk_buf[1] = 0;
- blk_buf[2] = 0xff;
- add_crc16(blk_buf + 3, 128);
- serial_write(&be->ymodem.serial, blk_buf, 128 + 5);
- /*
- * rb doesn't seem to ack the EOT for an end batch transfer,
- * contrary to spec.
- */
- printf("Done.\n");
- serial_cleanup(&be->ymodem.serial);
+ send_ack_blk(&ym, blk_buf);
+ len -= chunk;
}
+ printf("\nSending EOT...\n");
+ send_ack(&ym, &eot_buf, 1);
+
+ printf("Waiting for handshake...\n");
+ do {
+ serial_read(&ym.serial, &ack_buf, 1);
+ } while (ack_buf != 'C');
+ ym.seq = 0;
+
+ printf("Sending batch termination block...\n");
+ memset(blk_buf+3, 0, 128);
+ blk_buf[0] = SOH;
+ blk_buf[1] = 0;
+ blk_buf[2] = 0xff;
+ add_crc16(blk_buf + 3, 128);
+ serial_write(&ym.serial, blk_buf, 128 + 5);
+ /*
+ * rb doesn't seem to ack the EOT for an end batch transfer,
+ * contrary to spec.
+ */
+ printf("Done.\n");
+ serial_cleanup(&ym.serial);
+
return 0;
-}
+}
struct backend be_ymodem = {
.name = "ymodem",
.helpmsg = "filename port [speed]",
.minargs = 2,
- .blocksize = 1024,
- .flags = BE_NEEDLEN,
- .open = be_ymodem_open,
.write = be_ymodem_write,
};