Ejemplo n.º 1
0
static int xmodem_send_pkt(struct xmodem_send * sx, int data_len)
{
	unsigned char * pkt = sx->pkt.hdr; 
	unsigned char * cp;
	int retry = 0;
	int pkt_len;
	int ret;
	int c;


	if (sx->state == XMODEM_SEND_IDLE) {

		for (;;) {

			// Wait for NAK or 'C'
			if ((ret = serial_recv(sx->dev, pkt, 
								   1, XMODEM_SEND_TMOUT_MS)) <= 0) {
				if (ret == 0) {
					DBG(DBG_TRACE, "serial_recv() timed out!");
					if (++retry < 20) 
						continue;
				}
				DBG(DBG_WARNING, "serial_recv() failed 1!");
				return ret;
			}
			c = *pkt;

			if (c == CAN) {
				DBG(DBG_WARNING, "<-- CAN");
				return -1;
			}

			if (c == 'C') {
				DBG(DBG_TRACE, "<-- 'C' (CRC mode)");
				sx->state = XMODEM_SEND_CRC;
				break;
			}

			if (c == NAK) {
				DBG(DBG_TRACE, "<-- NAK (Checksum mode)");
				sx->state = XMODEM_SEND_CKS;
				break;
			}

		}
	}


	if (data_len) {
		unsigned char * fcs;

		if (data_len == 1024)
			pkt[0] = STX;
		else if (data_len == 128)
			pkt[0] = SOH;
		else
			return -1;

		pkt[1] = sx->seq;
		pkt[2] = ~sx->seq;
		cp = &pkt[3];
		fcs = &pkt[3 + data_len];

		if (sx->state == XMODEM_SEND_CRC) {
			unsigned short crc = 0;
			int i;

			for (i = 0; i < data_len; ++i)
				crc = CRC16CCITT(crc, cp[i]);

			fcs[0] = crc >> 8;
			fcs[1] = crc & 0xff;
			pkt_len = 3 + data_len + 2;
		} else {
Ejemplo n.º 2
0
int dmon_ymodem_rcv_pkt(struct dmon_comm * comm, struct ymodem_rcv * rx)
{
	unsigned char * pkt = rx->pkt.hdr;
	unsigned char * cp;
	int ret = 0;
	int cnt = 0;
	int nseq;
	int seq;
	int rem;

	for (;;) {

		dbgmon_alarm(XMODEM_RCV_TMOUT_MS);
		DCC_LOG1(LOG_INFO, "SYN=%02x", rx->sync);
		dmon_comm_send(comm, &rx->sync, 1);

		for (;;) {
			int c;

			ret = dmon_comm_recv(comm, pkt, 1);
			if (ret < 0)
				goto timeout;

			c = pkt[0];

			if (c == STX) {
				cnt = 1024;
				break;
			}

			if (c == SOH) {
				cnt = 128;
				break;
			}

			if (c == CAN) {
				return -1;
			}

			if (c == EOT) {
				DCC_LOG(LOG_INFO, "EOT!!");
				/* end of transmission */
				rx->sync = rx->crc_mode ? 'C' : NAK;
				rx->pktno = 0;
				pkt[0] = ACK;
				dmon_comm_send(comm, pkt, 1);
				return 0;
			}
		}

		rem = cnt + ((rx->crc_mode) ? 4 : 3);
		cp = pkt + 1;

		/* receive the packet */
		while (rem) {
			dbgmon_alarm(500);
			ret = dmon_comm_recv(comm, cp, rem);
			if (ret < 0)
				goto timeout;

			rem -= ret;
			cp += ret;
		}

		/* sequence */
		seq = pkt[1];
		/* inverse sequence */
		nseq = pkt[2];

		if (seq != ((~nseq) & 0xff)) {
			goto error;
		}

		cp = &pkt[3];

		if (rx->crc_mode) {
			unsigned short crc = 0;
			unsigned short cmp;
			int i;

			for (i = 0; i < cnt; ++i)
				crc = CRC16CCITT(crc, cp[i]);

			cmp = (unsigned short)cp[i] << 8 | cp[i + 1];

			if (cmp != crc) {
				DCC_LOG(LOG_WARNING, "CRC error");
				goto error;
			}

		} else {
			unsigned char cks = 0;
			int i;

			for (i = 0; i < cnt; ++i)
				cks += cp[i];

			if (cp[i] != cks) {
				DCC_LOG(LOG_WARNING, "wrong sum");
				goto error;
			}
		}

		if (seq == ((rx->pktno - 1) & 0xff)) {
			/* retransmission */
			DCC_LOG(LOG_INFO, "rxmit ...");
			continue;
		}

		if (seq != (rx->pktno & 0xff)) {
			if ((rx->pktno == 0) && (seq == 1)) {
				rx->pktno++;
				/* Fallback to XMODEM */
				rx->xmodem = 1;
				DCC_LOG(LOG_INFO, "XMODEM...");
			} else {
				DCC_LOG(LOG_WARNING, "wrong sequence");
				goto error;
			}
		}

		/* YModem first packet ... */
		if (rx->pktno == 0) {
			DCC_LOG(LOG_INFO, "ACK");
			pkt[0] = ACK;
			dmon_comm_send(comm, pkt, 1);
		} else {
			rx->retry = 10;
			rx->sync = ACK;
			if ((rx->count + cnt) > rx->fsize)
				cnt = rx->fsize - rx->count;
			rx->count += cnt;
		}

		DCC_LOG2(LOG_INFO, "pktno=%d count=%d", rx->pktno, rx->count);

		rx->pktno++;

		dbgmon_alarm_stop();

		return cnt;

error:
		/* flush */
		while (dmon_comm_recv(comm, pkt, 1024) > 0);
		ret = -1;
		break;

timeout:
		DCC_LOG(LOG_WARNING, "timeout!!");
		if ((--rx->retry) == 0) {
			/* too many errors */
			ret = -1;
			break;
		}
	}


	pkt[0] = CAN;
	pkt[1] = CAN;

	dmon_comm_send(comm, pkt, 2);

	dbgmon_alarm_stop();
	return ret;
}
Ejemplo n.º 3
0
static int usb_ymodem_rcv_pkt(struct ymodem_rcv * rx)
{
	unsigned char * pkt = rx->pkt.hdr;
	unsigned char * cp;
	int ret = 0;
	int cnt = 0;
#if XMODEM_SEQUENCE_CHECK
	int nseq;
	int seq;
#endif
	int rem;
	int pos;
	int i;

	for (;;) {
		if ((ret = usb_send(CDC_TX_EP, &rx->sync, 1)) < 0) {
			return ret;
		}

		rem = 0;
		pos = 0;
		for (;;) {
			int c;

			if (rem == 0) {
				ret = usb_recv(CDC_RX_EP, pkt, 128, 2000);
				DCC_LOG1(LOG_TRACE, "usb_recv() ret=%d)", ret);

				if (ret <= 0)
					goto timeout;

				pos = 0;
				rem = ret;
			}

			c = pkt[pos];
			pos++;
			rem--;

			if (c == STX) {
				cnt = 1024;
				break;
			}

			if (c == SOH) {
				cnt = 128;
				break;
			}

			if (c == CAN) {
				return -1;
			}

			if (c == EOT) {
				/* end of transmission */
#if XMODEM_CHECKSUM
				rx->sync = rx->crc_mode ? 'C' : NAK;
#else
				rx->sync = 'C';
#endif
				rx->pktno = 0;
				pkt[0] = ACK;
				usb_send(CDC_TX_EP, pkt, 1);
				return 0;
			}
		}

		cp = pkt + 1;
		for (i = 0; i < rem; ++i)
			cp[i] = pkt[pos + i];
		cp += rem;

		rem = cnt + 4 - rem;

		/* receive the packet */
		while (rem) {
			ret = usb_recv(CDC_RX_EP, cp, rem, 500);
			DCC_LOG1(LOG_TRACE, "usb_recv() ret=%d)", ret);
			if (ret < 0)
				goto timeout;

			rem -= ret;
			cp += ret;
		}

#if XMODEM_SEQUENCE_CHECK
		/* sequence */
		seq = pkt[1];
		/* inverse sequence */
		nseq = pkt[2];

		if (seq != ((~nseq) & 0xff)) {
			goto error;
		}
#endif
		cp = &pkt[3];

#if XMODEM_CHECKSUM
		if (rx->crc_mode) 
#endif
#if XMODEM_CRC_CHECK
		{
			unsigned short crc = 0;
			unsigned short cmp;
			int i;

			for (i = 0; i < cnt; ++i)
				crc = CRC16CCITT(crc, cp[i]);

			cmp = (unsigned short)cp[i] << 8 | cp[i + 1];

			if (cmp != crc) {
				goto error;
			}

		} 
#endif
#if XMODEM_CHECKSUM
		else {
			unsigned char cks = 0;
			int i;

			for (i = 0; i < cnt; ++i)
				cks += cp[i];

			if (cp[i] != cks) {
				goto error;
			}
		}
#endif
#if XMODEM_SEQUENCE_CHECK
		if (seq == ((rx->pktno - 1) & 0xff)) {
			/* retransmission */
			continue;
		}

		if (seq != (rx->pktno & 0xff)) {
#if XMODEM_FALLBACK
			if ((rx->pktno == 0) && (seq == 1)) {
				rx->pktno++;
				/* Fallback to XMODEM */
				rx->xmodem = true;
			} else 
#endif
			{
				goto error;
			}
		}
#endif
		/* YModem first packet ... */
		if (rx->pktno == 0) {
			pkt[0] = ACK;
			usb_send(CDC_TX_EP, pkt, 1);
		} else {
			rx->retry = 10;
			rx->sync = ACK;
			if ((rx->count + cnt) > rx->fsize)
				cnt = rx->fsize - rx->count;
			rx->count += cnt;
		}

		rx->pktno++;

		return cnt;

#if XMODEM_SEQUENCE_CHECK || XMODEM_CRC_CHECK
error:
		/* flush */
		while (usb_recv(CDC_RX_EP, pkt, 1024, 100) > 0);
		ret = -1;
		break;
#endif

timeout:
		if ((--rx->retry) == 0) {
			/* too many errors */
			DCC_LOG(LOG_WARNING, "too many errors!");
			ret = -1;
			break;
		}
	}


	return usb_ymodem_rcv_cancel(rx);
}