comparison network/network.c @ 107:56d09a0969b5 avr-http

Import uIP and the PPP implementation from https://code.google.com/p/avrusbmodem/
author Matt Johnston <matt@ucc.asn.au>
date Fri, 07 Sep 2012 23:53:53 +0800
parents
children
comparison
equal deleted inserted replaced
106:5c8404549cc0 107:56d09a0969b5
1 #define INCLUDE_FROM_NETWORK_C
2 #include "network.h"
3
4 static bool Escape = false;
5 static uint8_t PacketState = PACKET_STATE_NULL;
6 static uint16_t PacketProtocol = 0;
7 static uint16_t PacketLength = 0;
8 static uint16_t CurrentChecksum, OneBackChecksum, TwoBackChecksum;
9
10
11 // Framed packet looks like:
12 // Framing: 0x7e
13 // Address: 0xff
14 // Control: 0x03
15 // Protocol: 0xnn 0xnn
16 // Information: 0xnn 0xnn 0xnn 0xnn ...
17 // Checksum: 0xnn 0xnn
18 // Framing: 0x7e
19 //
20 // If Address-and-Control-Field-Compression is switched on then the remote end is allowed to leave out the 0xff 0x03 in the header
21 // If Protocol-Field-Compression is switched on and the protocol < 0x00ff then the remote end is allowed to leave out the initial 0x00 in the protocol field.
22 // We can check for Protocol-Field-Compression by seeing if the first byte of the protocol is odd (the first byte of a full two-byte protocol value must be even).
23
24 uint16_t network_read(void)
25 {
26 RingBuff_Elements_t c;
27
28 while (Modem_ReceiveBuffer.Elements)
29 {
30 c = Buffer_GetElement(&Modem_ReceiveBuffer);
31
32 switch (PacketState)
33 {
34 case PACKET_STATE_NULL:
35 if (c == 0x7e) // New Packet
36 {
37 PacketState = PACKET_STATE_INHEADER; // We're now in the header
38 PacketLength = 0;
39 CurrentChecksum = 0xffff; // Start new checksum
40 }
41 break;
42
43 case PACKET_STATE_INHEADER:
44 if (c == 0x7d) // Escaped character. Set flag and process next time around
45 {
46 Escape = true;
47 continue;
48 }
49 else if (Escape) // Escaped character. Process now.
50 {
51 Escape = false;
52 c = (c ^ 0x20);
53 }
54
55 if (PacketLength == 1 && c != 0xff) // Should be 0xff. If not then Address-and-Control-Field-Compression is switched on
56 {
57 PacketLength += 2; // Adjust the length as if the 0xff 0x03 was there
58 }
59
60 if (PacketLength == 3)
61 {
62 if (c & 1) // Should be even. If it's odd then Protocol-Field-Compression is switched on
63 {
64 PacketProtocol = 0x00; // Add in the initial 0x00
65 PacketLength++; // Adjust the length as if the 0x00 was there
66 }
67 else
68 PacketProtocol = c * 256; // Store the MSB of the protocol
69 }
70
71 if (PacketLength == 4) // End of header
72 {
73 PacketProtocol |= c; // Store the LSB of the protocol
74 PacketLength = -1; // This will be incremented to 0 at the end of this loop
75 Escape = false;
76 PacketState = PACKET_STATE_INBODY; // We're now in the body
77 }
78
79 CurrentChecksum = CALC_CRC16(CurrentChecksum, c); // Calculate checksum
80 break;
81
82 case PACKET_STATE_INBODY:
83 if (c == 0x7e) // End of packet
84 {
85 uip_len = PacketLength - 2; // Strip off the checksum and framing
86 Escape = false;
87 PacketState = PACKET_STATE_NULL; // Back to waiting for a header
88
89 Debug_Print("\r\nReceive ");
90 DumpPacket();
91
92 if (~TwoBackChecksum == (*(uip_buf + PacketLength - 1) * 256 + *(uip_buf + PacketLength - 2)))
93 return PacketProtocol;
94 else
95 Debug_Print("Bad CRC\r\n");
96 }
97 else
98 {
99 if (c == 0x7d) // Escaped character. Set flag and process next time around
100 {
101 Escape = true;
102 continue;
103 }
104 else if (Escape) // Escaped character. Process now.
105 {
106 Escape = false;
107 c = (c ^ 0x20);
108 }
109
110 *(uip_buf + PacketLength) = c; // Store the character in the buffer
111
112 TwoBackChecksum = OneBackChecksum; // Keep a rolling count of the last 3 checksums
113 OneBackChecksum = CurrentChecksum; // Eventually we need to see if the checksum is valid
114 CurrentChecksum = CALC_CRC16(CurrentChecksum, c); // and we need the one two back (as the current one includes the checksum itself)
115 }
116 break;
117 }
118
119 PacketLength++; // Increment the length of the received packet
120 }
121
122 return 0; // No data or packet not complete yet
123 }
124
125 void network_send(uint16_t protocol)
126 {
127 unsigned int checksum = 0xffff;
128
129 PacketProtocol = protocol;
130 PacketState = PACKET_STATE_NULL;
131
132 Debug_Print("\r\nSend ");
133 DumpPacket();
134
135 // Send out the packet with HDLC-like framing - see http://tools.ietf.org/html/rfc1662
136
137 // Start with the framing flag
138 Buffer_StoreElement(&Modem_SendBuffer, 0x7e);
139
140 // Address
141 Buffer_StoreElement(&Modem_SendBuffer, 0xff);
142 checksum = CALC_CRC16(checksum, 0xff);
143
144 // Control
145 Buffer_StoreElement(&Modem_SendBuffer, 0x03);
146 checksum = CALC_CRC16(checksum, 0x03);
147
148 // Protocol
149 Buffer_StoreElement(&Modem_SendBuffer, protocol / 256);
150 checksum = CALC_CRC16(checksum, protocol / 256);
151
152 Buffer_StoreElement(&Modem_SendBuffer, protocol & 255);
153 checksum = CALC_CRC16(checksum, protocol & 255);
154
155 // Add the information, escaping it as necessary
156 for (uint16_t i = 0; i < uip_len; i++)
157 {
158 if (*(uip_buf + i) < 0x20 || *(uip_buf + i) == 0x7d || *(uip_buf + i) == 0x7e)
159 {
160 Buffer_StoreElement(&Modem_SendBuffer, 0x7d);
161 Buffer_StoreElement(&Modem_SendBuffer, *(uip_buf + i) ^ 0x20);
162 }
163 else
164 {
165 Buffer_StoreElement(&Modem_SendBuffer, *(uip_buf + i));
166 }
167
168 checksum = CALC_CRC16(checksum, *(uip_buf + i));
169
170 if (Modem_SendBuffer.Elements == BUFF_STATICSIZE) // Periodically flush the buffer to the modem
171 USBManagement_SendReceivePipes();
172 }
173
174 // Add the checksum to the end of the packet, escaping it as necessary
175 checksum = ~checksum;
176
177 if ((checksum & 255) < 0x20 || (checksum & 255) == 0x7d || (checksum & 255) == 0x7e)
178 {
179 Buffer_StoreElement(&Modem_SendBuffer, 0x7d);
180 Buffer_StoreElement(&Modem_SendBuffer, (checksum & 255) ^ 0x20);
181 }
182 else
183 {
184 Buffer_StoreElement(&Modem_SendBuffer, checksum & 255); // Insert checksum MSB
185 }
186
187 if ((checksum / 256) < 0x20 || (checksum / 256) == 0x7d || (checksum / 256) == 0x7e)
188 {
189 Buffer_StoreElement(&Modem_SendBuffer, 0x7d);
190 Buffer_StoreElement(&Modem_SendBuffer, (checksum / 256) ^ 0x20);
191 }
192 else
193 {
194 Buffer_StoreElement(&Modem_SendBuffer, checksum / 256); // Insert checksum LSB
195 }
196
197 Buffer_StoreElement(&Modem_SendBuffer, 0x7e); // Framing
198
199 uip_len = 0;
200
201 USBManagement_SendReceivePipes(); // Flush the rest of the buffer
202 }
203
204 void network_init(void)
205 {
206 //Initialise the device
207 PacketState = PACKET_STATE_NULL;
208 Escape = false;
209 uip_len = 0;
210 }
211
212 void DumpPacket(void)
213 {
214 int i, j;
215
216 if (!DebugModeEnabled)
217 return;
218
219 Debug_Print("(Protocol = 0x");
220 Debug_PrintHex(PacketProtocol / 256); Debug_PrintHex(PacketProtocol & 255);
221 Debug_Print("):\r\n");
222
223 for (i = 0; i < uip_len; i += 16)
224 {
225 Debug_PrintHex(i / 256); Debug_PrintHex(i & 255); Debug_Print(": ");
226
227 for (j = 0; j < 16; j++)
228 {
229 if ((i + j) >= uip_len)
230 break;
231
232 Debug_PrintHex(*(uip_buf + i + j));
233 Debug_PrintChar(' ');
234 }
235
236 Debug_Print("\r\n ");
237
238 for (j = 0; j < 16; j++)
239 {
240 if ((i + j) >= uip_len)
241 break;
242
243 if (*(uip_buf + i + j) >= 0x20 && *(uip_buf + i + j) <= 0x7e)
244 {
245 Debug_PrintChar(' ');
246 Debug_PrintChar(*(uip_buf + i + j));
247 Debug_PrintChar(' ');
248 }
249 else
250 Debug_Print(" . ");
251
252 }
253
254 Debug_Print("\r\n");
255 }
256 }