cdc_ecm.c
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
00076 return;
00077 }
00078
00079 if(usb_endpoint_wait_for_IN_ready()!=0) {
00080
00081 return;
00082 }
00083
00084 Usb_send_control_in();
00085
00086 Usb_write_byte(0x51);
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);
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
00204 Usb_select_endpoint(RX_EP);
00205 }
00206
00207 if(!usb_eth_is_active) {
00208
00209 if(Is_usb_read_enabled()) {
00210 Usb_ack_receive_out();
00211 }
00212 return 0;
00213 }
00214
00215
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
00225
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
00241 Usb_ack_receive_out();
00242
00243
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
00257 Usb_ack_receive_out();
00258
00259
00260
00261 #ifdef USB_ETH_HOOK_RX_END
00262 USB_ETH_HOOK_RX_END();
00263 #endif
00264
00265
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
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
00294 while(sendlen) {
00295 Usb_write_byte(*senddata);
00296 senddata++;
00297 sendlen--;
00298 byte_in_packet++;
00299
00300
00301
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
00315 Usb_ack_in_ready();
00316
00317 #ifdef USB_ETH_HOOK_TX_END
00318 USB_ETH_HOOK_TX_END();
00319 #endif
00320
00321
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