prom / xmodem.c

/**
 * \file xmodem protocol
 *
 * Using USB serial
 */

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <string.h>
#include <util/delay.h>
#include "usb_serial.h"
#include "xmodem.h"



/** Send a block.
 * Compute the checksum and complement.
 *
 * \return 0 if all is ok, -1 if a cancel is requested or more
 * than 10 retries occur.
 */
int
xmodem_send(
	xmodem_block_t * const block
)
{
	// Compute the checksum and complement
	uint8_t cksum = 0;
	for (uint8_t i = 0 ; i < sizeof(block->data) ; i++)
		cksum += block->data[i];

	block->cksum = cksum;
	block->block_num++;
	block->block_num_complement = 0xFF - block->block_num;

	// Send the block, and wait for an ACK
	uint8_t retry_count = 0;

	while (retry_count++ < 10)
	{
		usb_serial_write((void*) block, sizeof(*block));

		// Wait for an ACK (done), CAN (abort) or NAK (retry)
		while (1)
		{
			uint8_t c = usb_serial_getchar();
			if (c == XMODEM_ACK)
				return 0;
			if (c == XMODEM_CAN)
				return -1;
			if (c == XMODEM_NAK)
				break;
		}
	}

	// Failure or cancel
	return -1;
}


int
xmodem_init(
	xmodem_block_t * const block
)
{
	block->soh = 0x01;
	block->block_num = 0x00;

	// wait for initial nak
	while (1)
	{
		uint8_t c = usb_serial_getchar();
		if (c == XMODEM_NAK)
			return 0;
		if (c == XMODEM_CAN)
			return -1;
	}
}


int
xmodem_fini(
	xmodem_block_t * const block
)
{
#if 0
/* Don't send EOF?  rx adds it to the file? */
	block->block_num++;
	memset(block->data, XMODEM_EOF, sizeof(block->data));
	if (xmodem_send_block(block) < 0)
		return;
#endif

	// File transmission complete.  send an EOT
	// wait for an ACK or CAN
	while (1)
	{
		usb_serial_putchar(XMODEM_EOT);

		while (1)
		{
			uint16_t c = usb_serial_getchar();
			if (c == -1)
				continue;
			if (c == XMODEM_ACK)
				return 0;
			if (c == XMODEM_CAN)
				return -1;
		}
	}
}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.