25#define YM_FILE_SIZE_LENGTH (16)
28#define YM_PACKET_SEQNO_INDEX (1)
29#define YM_PACKET_SEQNO_COMP_INDEX (2)
30#define YM_PACKET_HEADER (3)
31#define YM_PACKET_TRAILER (2)
32#define YM_PACKET_OVERHEAD (YM_PACKET_HEADER + YM_PACKET_TRAILER)
33#define YM_PACKET_SIZE (128)
34#define YM_PACKET_1K_SIZE (1024)
35#define YM_PACKET_RX_TIMEOUT_MS (2000)
36#define YM_PACKET_ERROR_MAX_NBR (5)
52#define YM_ERR(fmt, ...) do { printf(fmt, __VA_ARGS__); } while(0)
56char __ym_getchar(
int timeout_ms)
60 ReadFile((HANDLE)global_fd, &c, (DWORD)1, NULL, NULL);
62 read(global_fd, &c, 1);
67void __ym_putchar(
char c)
70 WriteFile((HANDLE)global_fd, &c, (DWORD)1, NULL, NULL);
72 write(global_fd, &c, 1);
76void __ym_sleep_ms(
int delay_ms)
81 usleep(delay_ms * 1000);
88 tcflush(global_fd,TCIOFLUSH);
96static uint16_t ym_crc16(
const uint8_t *buf, uint16_t len)
101 x = (crc >> 8) ^ *buf++;
103 crc = (crc << 8) ^ (x << 12) ^ (x << 5) ^ x;
110static uint32_t ym_writeU32(uint32_t val, uint8_t *buf)
120 int32_t i =
sizeof(s) - 1;
123 while ((val > 0) && (i > 0)) {
125 s[--i] = (val % 10) +
'0';
142static void ym_readU32(
const uint8_t* buf, uint32_t *val)
144 const uint8_t *s = buf;
151 while ((c >=
'0') && (c <=
'9')) {
172static int32_t ym_rx_packet(uint8_t *rxdata,
174 uint32_t packets_rxed,
179 int32_t c = __ym_getchar(timeout_ms);
185 uint32_t rx_packet_size;
189 rx_packet_size = YM_PACKET_SIZE;
192 rx_packet_size = YM_PACKET_1K_SIZE;
198 c = __ym_getchar(timeout_ms);
206 if (packets_rxed == 0) {
226 *rxdata = (uint8_t)c;
229 for (i = 1; i < (rx_packet_size + YM_PACKET_OVERHEAD); i++) {
230 c = __ym_getchar(timeout_ms);
236 rxdata[i] = (uint8_t)c;
241 uint8_t seq_nbr = (rxdata[YM_PACKET_SEQNO_INDEX] & 0xff);
242 uint8_t seq_cmp = ((rxdata[YM_PACKET_SEQNO_COMP_INDEX] ^ 0xff) & 0xff);
243 if (seq_nbr != seq_cmp) {
249 uint16_t crc16_val = ym_crc16((
const unsigned char *)(rxdata + YM_PACKET_HEADER),
250 rx_packet_size + YM_PACKET_TRAILER);
255 *rxlen = rx_packet_size;
267int32_t fymodem_receive(uint8_t *rxdata,
269 char filename[FYMODEM_FILE_NAME_MAX_LENGTH])
272 uint8_t rx_packet_data[YM_PACKET_1K_SIZE + YM_PACKET_OVERHEAD];
273 int32_t rx_packet_len;
275 uint8_t filesize_asc[YM_FILE_SIZE_LENGTH];
276 uint32_t filesize = 0;
278 bool first_try =
true;
279 bool session_done =
false;
281 uint32_t nbr_errors = 0;
290 __ym_putchar(YM_CRC);
295 bool file_done =
false;
296 uint32_t packets_rxed = 0;
299 uint8_t *rxptr = rxdata;
302 int32_t res = ym_rx_packet(rx_packet_data,
305 YM_PACKET_RX_TIMEOUT_MS);
310 switch (rx_packet_len) {
313 __ym_putchar(YM_ACK);
318 __ym_putchar(YM_ACK);
323 __ym_putchar(YM_CRC);
328 uint8_t seq_nbr = rx_packet_data[YM_PACKET_SEQNO_INDEX];
329 if (seq_nbr != (packets_rxed & 0xff)) {
331 __ym_putchar(YM_NAK);
333 if (packets_rxed == 0) {
339 for (i = YM_PACKET_HEADER; i < YM_PACKET_HEADER + 4; i++) {
340 if (rx_packet_data[i] != 0) {
345 if (i < YM_PACKET_HEADER + 4) {
347 uint8_t *file_ptr = (uint8_t*)(rx_packet_data + YM_PACKET_HEADER);
349 while ((*file_ptr !=
'\0') &&
350 (i < FYMODEM_FILE_NAME_MAX_LENGTH)) {
351 filename[i++] = *file_ptr++;
353 filename[i++] =
'\0';
358 while ((*file_ptr !=
'\0') &&
359 (*file_ptr !=
' ') &&
360 (i < YM_FILE_SIZE_LENGTH)) {
361 filesize_asc[i++] = *file_ptr++;
363 filesize_asc[i++] =
'\0';
365 ym_readU32(filesize_asc, &filesize);
367 if (filesize > rxlen) {
368 YM_ERR(
"YM: RX buffer too small (0x%08x vs 0x%08x)\n", (
unsigned int)rxlen, (
unsigned int)filesize);
371 __ym_putchar(YM_ACK);
372 __ym_putchar(crc_nak ? YM_CRC : YM_NAK);
377 __ym_putchar(YM_ACK);
386 if (((rxptr + rx_packet_len) - rxdata) > (int32_t)rxlen) {
387 YM_ERR(
"YM: RX buffer overflow (exceeded 0x%08x)\n", (
unsigned int)rxlen);
391 for (i = 0; i < rx_packet_len; i++) {
392 rxptr[i] = rx_packet_data[YM_PACKET_HEADER + i];
394 rxptr += rx_packet_len;
395 __ym_putchar(YM_ACK);
405 if (packets_rxed > 0) {
407 if (nbr_errors >= YM_PACKET_ERROR_MAX_NBR) {
408 YM_ERR(
"YM: RX errors too many: %d - ABORT.\n", (
unsigned int)nbr_errors);
412 __ym_putchar(YM_CRC);
418 }
while (! file_done);
421 }
while (! session_done);
427 __ym_putchar(YM_CAN);
428 __ym_putchar(YM_CAN);
434static void ym_send_packet(uint8_t *txdata,
437 int32_t tx_packet_size;
440 if (block_nbr == 0) {
441 tx_packet_size = YM_PACKET_SIZE;
444 tx_packet_size = YM_PACKET_1K_SIZE;
447 uint16_t crc16_val = ym_crc16(txdata, tx_packet_size);
450 __ym_putchar( (block_nbr == 0) ? YM_SOH : YM_STX );
452 __ym_putchar(block_nbr & 0xFF);
453 __ym_putchar(~block_nbr & 0xFF);
457 for (i = 0; i < tx_packet_size; i++) {
458 __ym_putchar(txdata[i]);
462 __ym_putchar((crc16_val >> 8) & 0xFF);
463 __ym_putchar(crc16_val & 0xFF);
468static void ym_send_packet0(
const char* filename,
473 uint8_t block[YM_PACKET_SIZE];
476 while (*filename && (pos < YM_PACKET_SIZE - YM_FILE_SIZE_LENGTH - 2)) {
477 block[pos++] = *filename++;
483 pos += ym_writeU32(filesize, &block[pos]);
487 while (pos < YM_PACKET_SIZE) {
492 ym_send_packet(block, 0);
496static void ym_send_data_packets(uint8_t* txdata,
500 int32_t block_nbr = 1;
505 if (txlen > YM_PACKET_1K_SIZE) {
506 send_size = YM_PACKET_1K_SIZE;
511 ym_send_packet(txdata, block_nbr);
512 int32_t c = __ym_getchar(timeout_ms);
531 __ym_putchar(YM_EOT);
532 ch = __ym_getchar(timeout_ms);
533 }
while ((ch != YM_ACK) && (ch != -1));
537 ch = __ym_getchar(timeout_ms);
540 ym_send_packet0(0, 0);
541 ch = __ym_getchar(timeout_ms);
542 }
while ((ch != YM_ACK) && (ch != -1));
548int32_t fymodem_send(
int fd, uint8_t* txdata,
size_t txsize,
const char* filename)
555 (void)__ym_getchar(1000);
561 bool file_done =
false;
563 ym_send_packet0(filename, txsize);
568 ch = __ym_getchar(YM_PACKET_RX_TIMEOUT_MS);
570 ch = __ym_getchar(YM_PACKET_RX_TIMEOUT_MS);
572 ym_send_data_packets(txdata, txsize, YM_PACKET_RX_TIMEOUT_MS);
577 else if ((ch == YM_CRC) && (crc_nak)) {
581 else if ((ch != YM_NAK) || (crc_nak)) {
584 }
while (! file_done);
589 printf(
"TX Error!\n");
590 __ym_putchar(YM_CAN);
591 __ym_putchar(YM_CAN);