Contiki 2.6
|
00001 #include <stdbool.h> 00002 #include "cdc_ecm.h" 00003 #include "contiki.h" 00004 #include "usb_drv.h" 00005 #include "usb_descriptors.h" 00006 #include "usb_specific_request.h" 00007 #include "rndis/rndis_task.h" 00008 #include "rndis/rndis_protocol.h" 00009 #include "uip.h" 00010 #include "sicslow_ethernet.h" 00011 #include <stdio.h> 00012 #if RF230BB 00013 #include "rf230bb.h" 00014 #endif 00015 00016 #include <avr/pgmspace.h> 00017 #include <util/delay.h> 00018 00019 #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) 00020 #define PRINTF printf 00021 #define PRINTF_P printf_P 00022 00023 extern uint8_t usb_eth_data_buffer[64]; 00024 static U16 usb_ecm_packet_filter = 0; 00025 00026 #define PACKET_TYPE_PROMISCUOUS (1<<0) 00027 #define PACKET_TYPE_ALL_MULTICAST (1<<1) 00028 #define PACKET_TYPE_DIRECTED (1<<2) 00029 #define PACKET_TYPE_BROADCAST (1<<3) 00030 #define PACKET_TYPE_MULTICAST (1<<4) 00031 00032 #define Usb_write_word(x) Usb_write_byte((x)&0xFF),Usb_write_byte((x>>8)&0xFF) 00033 #define Usb_write_long(x) Usb_write_word((x)&0xFFFF),Usb_write_word((x>>16)&0xFFFF) 00034 00035 #define Usb_read_word() ((U16)Usb_read_byte()+((U16)Usb_read_byte()<<8)) 00036 00037 void 00038 cdc_ecm_set_ethernet_packet_filter(void) { 00039 usb_ecm_packet_filter = Usb_read_word(); 00040 00041 Usb_ack_receive_setup(); 00042 Usb_send_control_in(); 00043 usb_endpoint_wait_for_read_control_enabled(); 00044 00045 PRINTF_P(PSTR("cdc_ecm: Received SET_ETHERNET_PACKET_FILTER: (0x%04X) "),usb_ecm_packet_filter); 00046 if(usb_ecm_packet_filter & PACKET_TYPE_PROMISCUOUS) { 00047 PRINTF_P(PSTR("PROMISCUOUS ")); 00048 USB_ETH_HOOK_SET_PROMISCIOUS_MODE(true); 00049 } else { 00050 USB_ETH_HOOK_SET_PROMISCIOUS_MODE(false); 00051 } 00052 00053 if(usb_ecm_packet_filter & PACKET_TYPE_ALL_MULTICAST) 00054 PRINTF_P(PSTR("ALL_MULTICAST ")); 00055 if(usb_ecm_packet_filter & PACKET_TYPE_DIRECTED) 00056 PRINTF_P(PSTR("DIRECTED ")); 00057 if(usb_ecm_packet_filter & PACKET_TYPE_BROADCAST) 00058 PRINTF_P(PSTR("BROADCAST ")); 00059 if(usb_ecm_packet_filter & PACKET_TYPE_MULTICAST) 00060 PRINTF_P(PSTR("MULTICAST ")); 00061 00062 PRINTF_P(PSTR("\n")); 00063 } 00064 00065 00066 #define CDC_NOTIFY_NETWORK_CONNECTION (0x00) 00067 #define CDC_NOTIFY_CONNECTION_SPEED_CHANGE (0x2A) 00068 00069 void 00070 cdc_ecm_notify_network_connection(uint8_t value) { 00071 #if CDC_ECM_USES_INTERRUPT_ENDPOINT 00072 Usb_select_endpoint(INT_EP); 00073 00074 if(!Is_usb_endpoint_enabled()) { 00075 //PRINTF_P(PSTR("cdc_ecm: cdc_ecm_notify_network_connection: endpoint not enabled\n")); 00076 return; 00077 } 00078 00079 if(usb_endpoint_wait_for_IN_ready()!=0) { 00080 //PRINTF_P(PSTR("cdc_ecm: cdc_ecm_notify_network_connection: Timeout waiting for interrupt endpoint to be available\n")); 00081 return; 00082 } 00083 00084 Usb_send_control_in(); 00085 00086 Usb_write_byte(0x51); // 10100001b 00087 Usb_write_byte(CDC_NOTIFY_NETWORK_CONNECTION); 00088 Usb_write_byte(value); 00089 Usb_write_byte(0x00); 00090 Usb_write_word(ECM_INTERFACE0_NB); 00091 Usb_write_word(0x0000); 00092 00093 Usb_send_in(); 00094 PRINTF_P(PSTR("cdc_ecm: CDC_NOTIFY_NETWORK_CONNECTION %d\n"),value); 00095 #endif 00096 } 00097 00098 #define CDC_ECM_DATA_ENDPOINT_SIZE 64 00099 00100 void cdc_ecm_configure_endpoints() { 00101 #if CDC_ECM_USES_INTERRUPT_ENDPOINT 00102 usb_configure_endpoint(INT_EP, \ 00103 TYPE_INTERRUPT, \ 00104 DIRECTION_IN, \ 00105 SIZE_8, \ 00106 TWO_BANKS, \ 00107 NYET_ENABLED); 00108 #endif 00109 00110 usb_configure_endpoint(TX_EP, \ 00111 TYPE_BULK, \ 00112 DIRECTION_IN, \ 00113 SIZE_64, \ 00114 TWO_BANKS, \ 00115 NYET_ENABLED); 00116 00117 usb_configure_endpoint(RX_EP, \ 00118 TYPE_BULK, \ 00119 DIRECTION_OUT, \ 00120 SIZE_64, \ 00121 TWO_BANKS, \ 00122 NYET_ENABLED); 00123 #if CDC_ECM_USES_INTERRUPT_ENDPOINT 00124 Usb_reset_endpoint(INT_EP); 00125 #endif 00126 Usb_reset_endpoint(TX_EP); 00127 Usb_reset_endpoint(RX_EP); 00128 usb_eth_is_active = 1; 00129 } 00130 00131 00132 void 00133 cdc_ecm_notify_connection_speed_change(uint32_t upstream,uint32_t downstream) { 00134 #if CDC_ECM_USES_INTERRUPT_ENDPOINT 00135 Usb_select_endpoint(INT_EP); 00136 00137 if(!Is_usb_endpoint_enabled()) 00138 return; 00139 00140 if(usb_endpoint_wait_for_IN_ready()!=0) 00141 return; 00142 00143 Usb_send_control_in(); 00144 00145 Usb_write_byte(0x51); // 10100001b 00146 Usb_write_byte(CDC_NOTIFY_CONNECTION_SPEED_CHANGE); 00147 Usb_write_word(0x0000); 00148 Usb_write_word(ECM_INTERFACE0_NB); 00149 Usb_write_word(0x0008); 00150 00151 Usb_send_in(); 00152 00153 if(usb_endpoint_wait_for_write_enabled()!=0) 00154 return; 00155 00156 Usb_write_long(upstream); 00157 Usb_write_long(downstream); 00158 Usb_send_in(); 00159 00160 PRINTF_P(PSTR("cdc_ecm: CDC_NOTIFY_CONNECTION_SPEED_CHANGE UP:%d DOWN:%d\n"),upstream,downstream); 00161 #endif 00162 } 00163 00164 void cdc_ecm_set_active(uint8_t value) { 00165 if(value!=usb_eth_is_active) { 00166 Led3_on(); 00167 00168 usb_eth_is_active = value; 00169 cdc_ecm_notify_network_connection(value); 00170 if(value) { 00171 cdc_ecm_notify_connection_speed_change(250000,250000); 00172 } else { 00173 cdc_ecm_notify_connection_speed_change(0,0); 00174 } 00175 } 00176 } 00177 00178 uint8_t 00179 cdc_ecm_process(void) { 00180 static uint8_t doInit = 1; 00181 00182 Usb_select_endpoint(RX_EP); 00183 00184 if(!Is_usb_endpoint_enabled()) { 00185 return 0; 00186 } 00187 00188 if (doInit) { 00189 #ifdef USB_ETH_HOOK_INIT 00190 USB_ETH_HOOK_INIT(); 00191 #endif 00192 cdc_ecm_notify_network_connection(1); 00193 cdc_ecm_notify_connection_speed_change(250000,250000); 00194 doInit = 0; 00195 if(usb_ecm_packet_filter & PACKET_TYPE_PROMISCUOUS) { 00196 #if RF230BB 00197 rf230_set_promiscuous_mode(true); 00198 #else 00199 radio_set_trx_state(RX_ON); 00200 #endif 00201 } 00202 00203 // Select again, just to make sure. 00204 Usb_select_endpoint(RX_EP); 00205 } 00206 00207 if(!usb_eth_is_active) { 00208 // If we aren't active, just eat the packets. 00209 if(Is_usb_read_enabled()) { 00210 Usb_ack_receive_out(); 00211 } 00212 return 0; 00213 } 00214 00215 //Connected! 00216 Led0_on(); 00217 00218 if(Is_usb_read_enabled()) { 00219 uint16_t bytecounter; 00220 uint16_t bytes_received = 0; 00221 U8 * buffer = uip_buf; 00222 00223 if(!usb_eth_ready_for_next_packet()) { 00224 // Since we aren't ready for a packet yet, 00225 // just return. 00226 goto bail; 00227 } 00228 00229 #ifdef USB_ETH_HOOK_RX_START 00230 USB_ETH_HOOK_RX_START(); 00231 #endif 00232 00233 while((bytecounter=Usb_byte_counter_8())==CDC_ECM_DATA_ENDPOINT_SIZE) { 00234 while((bytes_received<USB_ETH_MTU) && (bytecounter--)) { 00235 *buffer++ = Usb_read_byte(); 00236 bytes_received++; 00237 } 00238 bytes_received+=bytecounter+1; 00239 00240 //ACK previous data 00241 Usb_ack_receive_out(); 00242 00243 //Wait for new data 00244 if(usb_endpoint_wait_for_read_enabled()!=0) { 00245 USB_ETH_HOOK_RX_ERROR("Timeout: read enabled"); 00246 goto bail; 00247 } 00248 } 00249 bytecounter = Usb_byte_counter_8(); 00250 while((bytes_received<USB_ETH_MTU) && (bytecounter--)) { 00251 *buffer++ = Usb_read_byte(); 00252 bytes_received++; 00253 } 00254 bytes_received+=bytecounter+1; 00255 00256 //Ack final data packet 00257 Usb_ack_receive_out(); 00258 00259 //PRINTF_P(PSTR("cdc_ecm: Got packet %d bytes long\n"),bytes_received); 00260 00261 #ifdef USB_ETH_HOOK_RX_END 00262 USB_ETH_HOOK_RX_END(); 00263 #endif 00264 00265 //Send data over RF or to local stack 00266 if(bytes_received<=USB_ETH_MTU) { 00267 00268 USB_ETH_HOOK_HANDLE_INBOUND_PACKET(uip_buf,bytes_received); 00269 } else { 00270 USB_ETH_HOOK_RX_ERROR("Oversized packet"); 00271 } 00272 } 00273 bail: 00274 return 1; 00275 } 00276 00277 uint8_t 00278 ecm_send(uint8_t * senddata, uint16_t sendlen, uint8_t led) { 00279 U8 byte_in_packet = 0; 00280 00281 //Send Data 00282 Usb_select_endpoint(TX_EP); 00283 00284 if(usb_endpoint_wait_for_write_enabled()!=0) { 00285 USB_ETH_HOOK_TX_ERROR("Timeout: write enabled"); 00286 return 0; 00287 } 00288 00289 #ifdef USB_ETH_HOOK_TX_START 00290 USB_ETH_HOOK_TX_START(); 00291 #endif 00292 00293 //Send packet 00294 while(sendlen) { 00295 Usb_write_byte(*senddata); 00296 senddata++; 00297 sendlen--; 00298 byte_in_packet++; 00299 00300 //If endpoint is full, send data in 00301 //And then wait for data to transfer 00302 if (!Is_usb_write_enabled()) { 00303 Usb_ack_in_ready(); 00304 00305 if(usb_endpoint_wait_for_write_enabled()!=0) { 00306 USB_ETH_HOOK_TX_ERROR("Timeout: write enabled"); 00307 return 0; 00308 } 00309 byte_in_packet=0; 00310 } 00311 00312 } 00313 00314 //Send last data in - also handles sending a ZLP if needed 00315 Usb_ack_in_ready(); 00316 00317 #ifdef USB_ETH_HOOK_TX_END 00318 USB_ETH_HOOK_TX_END(); 00319 #endif 00320 00321 //Wait for ready 00322 if(usb_endpoint_wait_for_IN_ready()!=0) { 00323 USB_ETH_HOOK_TX_ERROR("Timeout: IN ready"); 00324 return 0; 00325 } 00326 00327 return 1; 00328 } 00329 00330