Contiki 2.5
cdc_eem.c
1 #include "cdc_eem.h"
2 #include "contiki.h"
3 #include "usb_drv.h"
4 #include "usb_descriptors.h"
5 #include "usb_specific_request.h"
6 #include "rndis/rndis_task.h"
7 #include "rndis/rndis_protocol.h"
8 #include "uip.h"
9 #include "sicslow_ethernet.h"
10 #include <stdio.h>
11 
12 #include <avr/pgmspace.h>
13 #include <util/delay.h>
14 
15 #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
16 #define PRINTF printf
17 #define PRINTF_P printf_P
18 
19 extern uint8_t usb_eth_data_buffer[64];
20 
21 
22 //_____ M A C R O S ________________________________________________________
23 
24 
25 #define EEMCMD_ECHO 0x00 ///bmEEMCmd Echo
26 #define EEMCMD_ECHO_RESPONSE 0x01 ///bmEEMCmd Echo Response
27 #define EEMCMD_SUSPEND_HINT 0x02 ///bmEEMCmd Suspend Hint
28 #define EEMCMD_RESPONSE_HINT 0x03 ///bmEEMCmd Response Hint
29 #define EEMCMD_RESPONSE_COMPLETE_HINT 0x04 ///bmEEMCmd Response Complete Hint
30 #define EEMCMD_TICKLE 0x05 ///bmEEMCmd Tickle
31 
32 
33 void cdc_eem_configure_endpoints() {
34  usb_configure_endpoint(TX_EP, \
35  TYPE_BULK, \
36  DIRECTION_IN, \
37  SIZE_64, \
38  TWO_BANKS, \
39  NYET_ENABLED);
40 
41  usb_configure_endpoint(RX_EP, \
42  TYPE_BULK, \
43  DIRECTION_OUT, \
44  SIZE_64, \
45  TWO_BANKS, \
46  NYET_ENABLED);
47  Usb_reset_endpoint(TX_EP);
48  Usb_reset_endpoint(RX_EP);
49 }
50 
51 void cdc_eem_process(void) {
52  uint16_t datalength;
53  uint8_t bytecounter, headercounter;
54  uint16_t i;
55 
56 #ifdef USB_ETH_HOOK_INIT
57  static uint8_t doInit = 1;
58  if (doInit) {
59  USB_ETH_HOOK_INIT();
60  doInit = 0;
61  }
62 #endif
63 
64  //Connected!
65  Led0_on();
66 
67  Usb_select_endpoint(RX_EP);
68 
69  //If we have data and a free buffer
70  if(Is_usb_receive_out() && (uip_len == 0)) {
71 
72  //Read how much (endpoint only stores up to 64 bytes anyway)
73  bytecounter = Usb_byte_counter_8();
74 
75  //EEM uses 2 bytes as a header
76  headercounter = 2;
77 
78  uint8_t fail = 0;
79 
80  //Hmm.. what's going on here?
81  if (bytecounter < headercounter) {
83  //TODO CO done = 1;
84  }
85 
86  //Read EEM Header
87  i = 0;
88  while (headercounter) {
90  bytecounter--;
91  headercounter--;
92  i++;
93  }
94 
95  //Order is LSB/MSB, so MSN is in usb_eth_data_buffer[1]
96  //Bit 15 indicates command packet when set
97  if (usb_eth_data_buffer[1] & 0x80) {
98  //not a data payload
99  datalength = 0;
100  } else {
101  //'0' indicates data packet
102  //Length is lower 14 bits
103  datalength = usb_eth_data_buffer[0] | ((usb_eth_data_buffer[1] & 0x3F) << 8);
104  }
105 
106  /* EEM Command Packet */
107  if ((datalength == 0) && (fail == 0))
108  {
109  uint8_t command;
110  uint16_t echoLength;
111 
112  //Strip command off
113  command = usb_eth_data_buffer[1] & 0x38;
114  command = command >> 3;
115 
116  //Decode command type
117  switch (command)
118  {
119  /* Echo Request */
120  case EEMCMD_ECHO:
121 
122  //Get echo length
123  echoLength = (usb_eth_data_buffer[1] & 0x07) << 8; //MSB
124  echoLength |= usb_eth_data_buffer[0]; //LSB
125 
126  //TODO: everything. oops.
127 
128  break;
129 
130  /* Everything else: Whatever. */
131  case EEMCMD_ECHO_RESPONSE:
132  case EEMCMD_SUSPEND_HINT:
133  case EEMCMD_RESPONSE_HINT:
134  case EEMCMD_RESPONSE_COMPLETE_HINT:
135  case EEMCMD_TICKLE:
136  break;
137 
138  default: break;
139  }
140  }
141  /* EEM Data Packet */
142  else if (datalength && (fail == 0))
143  {
144  //Looks like we've got a live one
145 #ifdef USB_ETH_HOOK_RX_START
146  USB_ETH_HOOK_RX_START();
147 #endif
148 
149  uint16_t bytes_received = 0;
150  uint16_t dataleft = datalength;
151  U8 * buffer = uip_buf;
152 
153  while(dataleft)
154  {
155  *buffer++ = Usb_read_byte();
156 
157  dataleft--;
158  bytecounter--;
159  bytes_received++;
160 
161  //Check if endpoint is done but we are expecting more data
162  if ((bytecounter == 0) && (dataleft))
163  {
164  //ACK previous data
166 
167  //Wait for new data
168  while (!Is_usb_receive_out());
169 
170  //Get new data
171  bytecounter = Usb_byte_counter_8();
172 
173  //ZLP?
174  if (bytecounter == 0)
175  {
176  //Incomplete!!
177  break;
178  }
179  }
180  }
181 
182  //Ack final data packet
184 
185 #ifdef USB_ETH_HOOK_RX_END
186  USB_ETH_HOOK_RX_END();
187 #endif
188 
189  //Packet has CRC, nobody wants that garbage
190  datalength -= 4;
191 
192  //Send data over RF or to local stack
193  if(datalength <= USB_ETH_MTU) {
194  USB_ETH_HOOK_HANDLE_INBOUND_PACKET(uip_buf,datalength);
195  } else {
196  USB_ETH_HOOK_RX_ERROR("Oversized packet");
197  }
198  } //if (datalength)
199  } //if(Is_usb_receive_out() && (uip_len == 0))
200 }
201 
202 
203 /**
204  \brief Send a single ethernet frame using EEM
205  */
206 uint8_t eem_send(uint8_t * senddata, uint16_t sendlen, uint8_t led)
207 {
208  //Make a header
209  uint8_t header[2];
210 
211  //Fake CRC! Add 4 to length for CRC
212  sendlen += 4;
213  header[0] = (sendlen >> 8) & 0x3f;
214  header[1] = sendlen & 0xff;
215 
216  //We send CRC seperatly..
217  sendlen -= 4;
218 
219  //Send Data
220  Usb_select_endpoint(TX_EP);
221  //Usb_send_in();
222 
223  //Wait for ready
224  if(usb_endpoint_wait_for_write_enabled()!=0) {
225  USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
226  return 0;
227  }
228 
229 #ifdef USB_ETH_HOOK_TX_START
230  USB_ETH_HOOK_TX_START();
231 #endif
232 
233  //Send header (LSB then MSB)
234  Usb_write_byte(header[1]);
235  Usb_write_byte(header[0]);
236 
237  //Send packet
238  while(sendlen) {
239  Usb_write_byte(*senddata);
240  senddata++;
241  sendlen--;
242 
243  //If endpoint is full, send data in
244  //And then wait for data to transfer
245  if (!Is_usb_write_enabled()) {
246  Usb_send_in();
247 
248  if(usb_endpoint_wait_for_write_enabled()!=0) {
249  USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
250  return 0;
251  }
252  }
253 
254  }
255 
256  //CRC = 0xdeadbeef
257  //Linux kernel 2.6.31 needs 0xdeadbeef in wrong order,
258  //like this: uint8_t crc[4] = {0xef, 0xbe, 0xad, 0xde};
259  //This is fixed in 2.6.32 to the correct order (0xde, 0xad, 0xbe, 0xef)
260  uint8_t crc[4] = {0xde, 0xad, 0xbe, 0xef};
261 
262  sendlen = 4;
263  uint8_t i = 0;
264 
265  //Send fake CRC
266  while(sendlen) {
267  Usb_write_byte(crc[i]);
268  i++;
269  sendlen--;
270 
271  //If endpoint is full, send data in
272  //And then wait for data to transfer
273  if (!Is_usb_write_enabled()) {
274  Usb_send_in();
275  if(usb_endpoint_wait_for_write_enabled()!=0) {
276  USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
277  return 0;
278  }
279  }
280  }
281 
282  //Send last data in - also handles sending a ZLP if needed
283  Usb_send_in();
284 
285 #ifdef USB_ETH_HOOK_TX_END
286  USB_ETH_HOOK_TX_END();
287 #endif
288 
289  //Wait for ready
290  if(usb_endpoint_wait_for_IN_ready()!=0) {
291  USB_ETH_HOOK_TX_ERROR("Timeout: IN ready");
292  return 0;
293  }
294 
295  return 1;
296 }