OSDN Git Service

dfde1933e86c20e2bc23d5f7ec479b37de243799
[kozos-expbrd/kozos_expbrd.git] / firm / sample / sample1 / bootload / xmodem.c
1 #include "defines.h"
2 #include "serial.h"
3 #include "lib.h"
4 #include "xmodem.h"
5
6 #define XMODEM_SOH 0x01
7 #define XMODEM_STX 0x02
8 #define XMODEM_EOT 0x04
9 #define XMODEM_ACK 0x06
10 #define XMODEM_NAK 0x15
11 #define XMODEM_CAN 0x18
12 #define XMODEM_EOF 0x1a /* Ctrl-Z */
13
14 #define XMODEM_BLOCK_SIZE 128
15
16 /* ¼õ¿®³«»Ï¤µ¤ì¤ë¤Þ¤ÇÁ÷¿®Í×µá¤ò½Ð¤¹ */
17 static int xmodem_wait(void)
18 {
19   long cnt = 0;
20
21   while (!serial_is_recv_enable(SERIAL_DEFAULT_DEVICE)) {
22     if (++cnt >= 2000000) {
23       cnt = 0;
24       serial_send_byte(SERIAL_DEFAULT_DEVICE, XMODEM_NAK);
25     }
26   }
27
28   return 0;
29 }
30
31 /* ¥Ö¥í¥Ã¥¯Ã±°Ì¤Ç¤Î¼õ¿® */
32 static int xmodem_read_block(unsigned char block_number, char *buf)
33 {
34   unsigned char c, block_num, check_sum;
35   int i;
36
37   block_num = serial_recv_byte(SERIAL_DEFAULT_DEVICE);
38   if (block_num != block_number)
39     return -1;
40
41   block_num ^= serial_recv_byte(SERIAL_DEFAULT_DEVICE);
42   if (block_num != 0xff)
43     return -1;
44
45   check_sum = 0;
46   for (i = 0; i < XMODEM_BLOCK_SIZE; i++) {
47     c = serial_recv_byte(SERIAL_DEFAULT_DEVICE);
48     *(buf++) = c;
49     check_sum += c;
50   }
51
52   check_sum ^= serial_recv_byte(SERIAL_DEFAULT_DEVICE);
53   if (check_sum)
54     return -1;
55
56   return i;
57 }
58
59 long xmodem_recv(char *buf)
60 {
61   int r, receiving = 0;
62   long size = 0;
63   unsigned char c, block_number = 1;
64
65   while (1) {
66     if (!receiving)
67       xmodem_wait(); /* ¼õ¿®³«»Ï¤µ¤ì¤ë¤Þ¤ÇÁ÷¿®Í×µá¤ò½Ð¤¹ */
68
69     c = serial_recv_byte(SERIAL_DEFAULT_DEVICE);
70
71     if (c == XMODEM_EOT) { /* ¼õ¿®½ªÎ» */
72       serial_send_byte(SERIAL_DEFAULT_DEVICE, XMODEM_ACK);
73       break;
74     } else if (c == XMODEM_CAN) { /* ¼õ¿®ÃæÃÇ */
75       return -1;
76     } else if (c == XMODEM_SOH) { /* ¼õ¿®³«»Ï */
77       receiving++;
78       r = xmodem_read_block(block_number, buf); /* ¥Ö¥í¥Ã¥¯Ã±°Ì¤Ç¤Î¼õ¿® */
79       if (r < 0) { /* ¼õ¿®¥¨¥é¡¼ */
80         serial_send_byte(SERIAL_DEFAULT_DEVICE, XMODEM_NAK);
81       } else { /* Àµ¾ï¼õ¿® */
82         block_number++;
83         size += r;
84         buf  += r;
85         serial_send_byte(SERIAL_DEFAULT_DEVICE, XMODEM_ACK);
86       }
87     } else {
88       if (receiving)
89         return -1;
90     }
91   }
92
93   return size;
94 }