Mercurial > templog
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 } |