Contiki 2.6

cdc_eem.c

00001 #include "cdc_eem.h"
00002 #include "contiki.h"
00003 #include "usb_drv.h"
00004 #include "usb_descriptors.h"
00005 #include "usb_specific_request.h"
00006 #include "rndis/rndis_task.h"
00007 #include "rndis/rndis_protocol.h"
00008 #include "uip.h"
00009 #include "sicslow_ethernet.h"
00010 #include <stdio.h>
00011 
00012 #include <avr/pgmspace.h>
00013 #include <util/delay.h>
00014 
00015 #define BUF ((struct uip_eth_hdr *)&uip_buf[0])
00016 #define PRINTF printf
00017 #define PRINTF_P printf_P
00018 
00019 extern uint8_t usb_eth_data_buffer[64];
00020 
00021 
00022 //_____ M A C R O S ________________________________________________________
00023 
00024 
00025 #define EEMCMD_ECHO                    0x00 ///bmEEMCmd Echo
00026 #define EEMCMD_ECHO_RESPONSE           0x01 ///bmEEMCmd Echo Response
00027 #define EEMCMD_SUSPEND_HINT            0x02 ///bmEEMCmd Suspend Hint
00028 #define EEMCMD_RESPONSE_HINT           0x03 ///bmEEMCmd Response Hint
00029 #define EEMCMD_RESPONSE_COMPLETE_HINT  0x04 ///bmEEMCmd Response Complete Hint
00030 #define EEMCMD_TICKLE                  0x05 ///bmEEMCmd Tickle
00031 
00032 
00033 void cdc_eem_configure_endpoints() {
00034         usb_configure_endpoint(TX_EP,         \
00035                                           TYPE_BULK,     \
00036                                           DIRECTION_IN,  \
00037                                           SIZE_64,       \
00038                                           TWO_BANKS,     \
00039                                           NYET_ENABLED);
00040 
00041         usb_configure_endpoint(RX_EP,          \
00042                                                   TYPE_BULK,     \
00043                                           DIRECTION_OUT, \
00044                                           SIZE_64,       \
00045                                           TWO_BANKS,     \
00046                                           NYET_ENABLED);
00047         Usb_reset_endpoint(TX_EP);
00048         Usb_reset_endpoint(RX_EP);
00049 }
00050 
00051 void cdc_eem_process(void) {
00052         uint16_t datalength;
00053         uint8_t bytecounter, headercounter;
00054         uint16_t i;
00055 
00056 #ifdef USB_ETH_HOOK_INIT
00057         static uint8_t doInit = 1;
00058         if (doInit) {
00059                 USB_ETH_HOOK_INIT();
00060                 doInit = 0;
00061         }
00062 #endif
00063 
00064         //Connected!
00065         Led0_on();
00066 
00067         Usb_select_endpoint(RX_EP);
00068 
00069         //If we have data and a free buffer
00070         if(Is_usb_receive_out() && (uip_len == 0)) {
00071 
00072                 //Read how much (endpoint only stores up to 64 bytes anyway)
00073                 bytecounter = Usb_byte_counter_8();
00074 
00075                 //EEM uses 2 bytes as a header
00076                 headercounter = 2;
00077 
00078                 uint8_t fail = 0;
00079 
00080                 //Hmm.. what's going on here?
00081                  if (bytecounter < headercounter) {
00082                          Usb_ack_receive_out();
00083                                         //TODO CO done = 1;
00084                  }
00085 
00086                  //Read EEM Header
00087                  i = 0;
00088                  while (headercounter) {
00089                         usb_eth_data_buffer[i] = Usb_read_byte();
00090                         bytecounter--;
00091                         headercounter--;
00092                         i++;
00093                  }
00094 
00095                 //Order is LSB/MSB, so MSN is in usb_eth_data_buffer[1]
00096                 //Bit 15 indicates command packet when set
00097                 if (usb_eth_data_buffer[1] & 0x80) {
00098                         //not a data payload
00099                         datalength = 0;
00100                 } else {
00101                         //'0' indicates data packet
00102                         //Length is lower 14 bits
00103                         datalength = usb_eth_data_buffer[0] | ((usb_eth_data_buffer[1] & 0x3F) << 8);
00104                 }
00105 
00106                 /* EEM Command Packet */
00107                 if ((datalength == 0) && (fail == 0))
00108                 {
00109                         uint8_t command;
00110                         uint16_t echoLength;
00111 
00112                         //Strip command off
00113                         command = usb_eth_data_buffer[1] & 0x38;
00114                         command = command >> 3;
00115 
00116                         //Decode command type
00117                         switch (command)
00118                         {
00119                                 /* Echo Request */
00120                                 case EEMCMD_ECHO:
00121 
00122                                         //Get echo length
00123                                         echoLength  = (usb_eth_data_buffer[1] & 0x07) << 8; //MSB
00124                                         echoLength |= usb_eth_data_buffer[0];               //LSB
00125 
00126                                         //TODO: everything. oops.
00127 
00128                                         break;
00129 
00130                                 /* Everything else: Whatever. */
00131                                 case EEMCMD_ECHO_RESPONSE:
00132                                 case EEMCMD_SUSPEND_HINT:
00133                                 case EEMCMD_RESPONSE_HINT:
00134                                 case EEMCMD_RESPONSE_COMPLETE_HINT:
00135                                 case EEMCMD_TICKLE:
00136                                         break;
00137 
00138                                 default: break;
00139                         }
00140                 }
00141                 /* EEM Data Packet */
00142                 else if (datalength && (fail == 0))
00143                 {
00144                         //Looks like we've got a live one
00145 #ifdef USB_ETH_HOOK_RX_START
00146                         USB_ETH_HOOK_RX_START();
00147 #endif
00148 
00149                         uint16_t bytes_received = 0;
00150                         uint16_t dataleft = datalength;
00151                         U8 * buffer = uip_buf;
00152 
00153                         while(dataleft)
00154                         {
00155                                 *buffer++ = Usb_read_byte();
00156 
00157                                 dataleft--;
00158                                 bytecounter--;
00159                                 bytes_received++;
00160 
00161                                 //Check if endpoint is done but we are expecting more data
00162                                 if ((bytecounter == 0) && (dataleft))
00163                                 {
00164                                         //ACK previous data
00165                                         Usb_ack_receive_out();
00166 
00167                                         //Wait for new data
00168                                         while (!Is_usb_receive_out());
00169 
00170                                         //Get new data
00171                                         bytecounter = Usb_byte_counter_8();
00172 
00173                                         //ZLP?
00174                                         if (bytecounter == 0)
00175                                         {
00176                                                 //Incomplete!!
00177                                                 break;
00178                                         }
00179                                 }
00180                         }
00181 
00182                         //Ack final data packet
00183                         Usb_ack_receive_out();
00184 
00185 #ifdef USB_ETH_HOOK_RX_END
00186                         USB_ETH_HOOK_RX_END();
00187 #endif
00188 
00189                         //Packet has CRC, nobody wants that garbage
00190                         datalength -= 4;
00191 
00192                         //Send data over RF or to local stack
00193                         if(datalength <= USB_ETH_MTU) {
00194                                 USB_ETH_HOOK_HANDLE_INBOUND_PACKET(uip_buf,datalength);
00195                         } else {
00196                                 USB_ETH_HOOK_RX_ERROR("Oversized packet");
00197                         }
00198                 } //if (datalength)
00199         }  //if(Is_usb_receive_out() && (uip_len == 0))
00200 }
00201 
00202 
00203 /**
00204  \brief Send a single ethernet frame using EEM
00205  */
00206 uint8_t eem_send(uint8_t * senddata, uint16_t sendlen, uint8_t led)
00207 {
00208         //Make a header
00209         uint8_t header[2];
00210 
00211         //Fake CRC! Add 4 to length for CRC
00212         sendlen += 4;
00213         header[0] = (sendlen >> 8) & 0x3f;
00214         header[1] = sendlen & 0xff;
00215 
00216         //We send CRC seperatly..
00217         sendlen -= 4;
00218 
00219         //Send Data
00220         Usb_select_endpoint(TX_EP);
00221         //Usb_send_in();
00222 
00223         //Wait for ready
00224         if(usb_endpoint_wait_for_write_enabled()!=0) {
00225                 USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
00226                 return 0;
00227         }
00228 
00229 #ifdef USB_ETH_HOOK_TX_START
00230         USB_ETH_HOOK_TX_START();
00231 #endif
00232 
00233         //Send header (LSB then MSB)
00234         Usb_write_byte(header[1]);
00235         Usb_write_byte(header[0]);
00236 
00237         //Send packet
00238         while(sendlen) {
00239                 Usb_write_byte(*senddata);
00240                 senddata++;
00241                 sendlen--;
00242 
00243                 //If endpoint is full, send data in
00244                 //And then wait for data to transfer
00245                 if (!Is_usb_write_enabled()) {
00246                         Usb_send_in();
00247 
00248                         if(usb_endpoint_wait_for_write_enabled()!=0) {
00249                                 USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
00250                                 return 0;
00251                         }
00252                 }
00253 
00254         }
00255 
00256         //CRC = 0xdeadbeef
00257         //Linux kernel 2.6.31 needs 0xdeadbeef in wrong order,
00258         //like this: uint8_t crc[4] = {0xef, 0xbe, 0xad, 0xde};
00259         //This is fixed in 2.6.32 to the correct order (0xde, 0xad, 0xbe, 0xef)
00260         uint8_t crc[4] = {0xde, 0xad, 0xbe, 0xef};
00261 
00262         sendlen = 4;
00263         uint8_t i = 0;
00264 
00265         //Send fake CRC
00266         while(sendlen) {
00267                 Usb_write_byte(crc[i]);
00268                 i++;
00269                 sendlen--;
00270 
00271                 //If endpoint is full, send data in
00272                 //And then wait for data to transfer
00273                 if (!Is_usb_write_enabled()) {
00274                         Usb_send_in();
00275                         if(usb_endpoint_wait_for_write_enabled()!=0) {
00276                                 USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
00277                                 return 0;
00278                         }
00279                 }
00280         }
00281 
00282         //Send last data in - also handles sending a ZLP if needed
00283         Usb_send_in();
00284 
00285 #ifdef USB_ETH_HOOK_TX_END
00286         USB_ETH_HOOK_TX_END();
00287 #endif
00288 
00289     //Wait for ready
00290         if(usb_endpoint_wait_for_IN_ready()!=0) {
00291                 USB_ETH_HOOK_TX_ERROR("Timeout: IN ready");
00292                 return 0;
00293         }
00294 
00295         return 1;
00296 }