Contiki 2.6
|
00001 /** 00002 * \file rndis.c 00003 * RNDIS Functions for mounting USB device as network interface 00004 * 00005 * \author 00006 * Colin O'Flynn <coflynn@newae.com> 00007 * 00008 * \addtogroup usbstick 00009 */ 00010 /* Copyright (c) 2008 Colin O'Flynn 00011 00012 The CDC code which this is based on is Copyright (c) Atmel Corporation 2008 00013 All rights reserved. 00014 00015 Redistribution and use in source and binary forms, with or without 00016 modification, are permitted provided that the following conditions are met: 00017 00018 * Redistributions of source code must retain the above copyright 00019 notice, this list of conditions and the following disclaimer. 00020 * Redistributions in binary form must reproduce the above copyright 00021 notice, this list of conditions and the following disclaimer in 00022 the documentation and/or other materials provided with the 00023 distribution. 00024 * Neither the name of the copyright holders nor the names of 00025 contributors may be used to endorse or promote products derived 00026 from this software without specific prior written permission. 00027 00028 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00029 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00030 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00031 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00032 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00033 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00034 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00035 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00036 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00037 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00038 POSSIBILITY OF SUCH DAMAGE. 00039 */ 00040 00041 /* 00042 RNDIS Status Information: 00043 00044 802.3 Support: 00045 More or less working 00046 00047 802.11 Support: 00048 Incomplete, would just error out if you tried probably 00049 00050 00051 */ 00052 00053 /** 00054 \addtogroup RNDIS 00055 @{ 00056 */ 00057 00058 00059 //_____ I N C L U D E S ____________________________________________________ 00060 00061 #include <stdbool.h> 00062 #include "radio.h" 00063 #include "contiki.h" 00064 #include "config.h" 00065 #include "usb_drv.h" 00066 #include "usb_descriptors.h" 00067 #include "usb_specific_request.h" 00068 #include "rndis/rndis_protocol.h" 00069 #include "rndis/rndis_task.h" 00070 #include "uip.h" 00071 #include "serial/uart_usb_lib.h" 00072 #include "sicslow_ethernet.h" 00073 #include <avr/pgmspace.h> 00074 #include <string.h> 00075 #if RF230BB 00076 #include "rf230bb.h" 00077 #endif 00078 00079 #include <stdio.h> 00080 #include <avr/pgmspace.h> 00081 #include <util/delay.h> 00082 00083 00084 //_____ M A C R O S ________________________________________________________ 00085 00086 //_____ D E F I N I T I O N ________________________________________________ 00087 00088 //_____ P R I V A T E D E C L A R A T I O N ______________________________ 00089 00090 extern PGM_VOID_P pbuffer; 00091 extern U8 data_to_transfer; 00092 00093 /** 00094 * \brief List of supported RNDIS OID's 00095 */ 00096 const uint32_t OIDSupportedList[] PROGMEM = { 00097 /* Required General */ 00098 OID_GEN_SUPPORTED_LIST , 00099 OID_GEN_HARDWARE_STATUS , 00100 OID_GEN_MEDIA_SUPPORTED , 00101 OID_GEN_MEDIA_IN_USE , 00102 OID_GEN_MAXIMUM_FRAME_SIZE , 00103 OID_GEN_LINK_SPEED , 00104 OID_GEN_TRANSMIT_BLOCK_SIZE , 00105 OID_GEN_RECEIVE_BLOCK_SIZE , 00106 OID_GEN_VENDOR_ID , 00107 OID_GEN_VENDOR_DESCRIPTION , 00108 OID_GEN_CURRENT_PACKET_FILTER , 00109 OID_GEN_MAXIMUM_TOTAL_SIZE , 00110 OID_GEN_MEDIA_CONNECT_STATUS , 00111 OID_GEN_VENDOR_DRIVER_VERSION , 00112 OID_GEN_PHYSICAL_MEDIUM , 00113 00114 /* Required Statistical */ 00115 OID_GEN_XMIT_OK , 00116 OID_GEN_RCV_OK , 00117 OID_GEN_XMIT_ERROR , 00118 OID_GEN_RCV_ERROR , 00119 OID_GEN_RCV_NO_BUFFER , 00120 00121 /* Please configure us */ 00122 OID_GEN_RNDIS_CONFIG_PARAMETER , 00123 00124 00125 /* IEEE 802.3 (Ethernet) OIDs */ 00126 OID_802_3_PERMANENT_ADDRESS , 00127 OID_802_3_CURRENT_ADDRESS , 00128 OID_802_3_MULTICAST_LIST , 00129 OID_802_3_MAXIMUM_LIST_SIZE , 00130 OID_802_3_MAC_OPTIONS , 00131 OID_802_3_RCV_ERROR_ALIGNMENT , 00132 OID_802_3_XMIT_ONE_COLLISION , 00133 OID_802_3_XMIT_MORE_COLLISIONS , 00134 00135 /*802.11 OID's not fully implemented yet. Hence do not say we 00136 support them */ 00137 #if USB_ETH_EMULATE_WIFI 00138 /* 802.11 OIDs */ 00139 OID_802_11_BSSID , 00140 OID_802_11_SSID , 00141 OID_802_11_NETWORK_TYPE_IN_USE , 00142 OID_802_11_RSSI , 00143 OID_802_11_BSSID_LIST , 00144 OID_802_11_BSSID_LIST_SCAN , 00145 OID_802_11_INFRASTRUCTURE_MODE , 00146 OID_802_11_SUPPORTED_RATES , 00147 OID_802_11_CONFIGURATION , 00148 OID_802_11_ADD_WEP , 00149 OID_802_11_WEP_STATUS , 00150 OID_802_11_REMOVE_WEP , 00151 OID_802_11_DISASSOCIATE , 00152 OID_802_11_AUTHENTICATION_MODE , 00153 OID_802_11_RELOAD_DEFAULTS , 00154 #endif 00155 00156 /* Minimum power managment needed for USB */ 00157 00158 OID_PNP_CAPABILITIES , 00159 OID_PNP_QUERY_POWER , 00160 OID_PNP_SET_POWER , 00161 00162 OID_PNP_ENABLE_WAKE_UP , 00163 OID_PNP_ADD_WAKE_UP_PATTERN , 00164 OID_PNP_REMOVE_WAKE_UP_PATTERN 00165 }; 00166 00167 #define OID_LIST_LENGTH sizeof(OIDSupportedList)/sizeof(*OIDSupportedList) 00168 00169 00170 rndis_state_t rndis_state; 00171 00172 usb_eth_stat_t usb_eth_stat; 00173 00174 uint8_t schedule_interrupt = 0; 00175 00176 //_____ D E C L A R A T I O N ______________________________________________ 00177 00178 00179 void rndis_packetFilter(uint32_t newfilter); 00180 00181 /******** RNDIS ********/ 00182 00183 #define ENC_BUF_SIZE (4*OID_LIST_LENGTH + 32) 00184 00185 // Command buffer 00186 U8 encapsulated_buffer[ENC_BUF_SIZE]; 00187 00188 //Do we have data to send back? 00189 U8 data_to_send = 0x00; 00190 00191 /** 00192 * \brief Handles a "SEND ENCAPSULATED COMMAND" message. 00193 * 00194 * \return True on success, false on failure. 00195 */ 00196 uint8_t rndis_send_encapsulated_command(uint16_t wLength) 00197 { 00198 U8 i = 0; 00199 00200 //Received setup message OK 00201 Usb_ack_receive_setup(); 00202 00203 00204 //Crude bounds check 00205 if (wLength > ENC_BUF_SIZE) 00206 wLength = ENC_BUF_SIZE; 00207 00208 //Read in all the bytes... 00209 00210 uint8_t nb_counter; 00211 00212 //Clear NAK bit 00213 Usb_ack_nak_in(); 00214 00215 while (wLength) { 00216 nb_counter = EP_CONTROL_LENGTH; 00217 00218 //Wait for data to come in or nak 00219 while((!Is_usb_receive_out()) & (!Is_usb_receive_nak_in())); 00220 00221 //Received OUT 00222 if (Is_usb_receive_out()) { 00223 while(nb_counter && wLength) { 00224 encapsulated_buffer[i] = Usb_read_byte(); 00225 i++; 00226 wLength--; 00227 nb_counter--; 00228 } 00229 00230 Usb_ack_receive_out(); 00231 00232 //Received NAK, no more data 00233 } else { 00234 Usb_ack_nak_in(); 00235 break; 00236 } 00237 } 00238 00239 Usb_send_control_in(); 00240 00241 00242 switch(((rndis_generic_msg_t *)encapsulated_buffer)->MessageType) 00243 { 00244 /* Requests remote intilization. Respond with complete, 00245 eventually should probably do something */ 00246 case REMOTE_NDIS_INITIALIZE_MSG: 00247 { 00248 rndis_initialize_cmplt_t * m; 00249 m = ((rndis_initialize_cmplt_t *)encapsulated_buffer); 00250 00251 //m->MessageID is same as before 00252 m->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT; 00253 m->MessageLength = sizeof(rndis_initialize_cmplt_t); 00254 m->MajorVersion = RNDIS_MAJOR_VERSION; 00255 m->MinorVersion = RNDIS_MAJOR_VERSION; 00256 m->Status = RNDIS_STATUS_SUCCESS; 00257 m->DeviceFlags = RNDIS_DF_CONNECTIONLESS; 00258 #if USB_ETH_EMULATE_WIFI 00259 m->Medium = NDIS_MEDIUM_WIRELESS_LAN; 00260 #else 00261 m->Medium = RNDIS_MEDIUM_802_3; 00262 #endif // USB_ETH_EMULATE_WIFI 00263 m->MaxPacketsPerTransfer = 1; 00264 m->MaxTransferSize = USB_ETH_MTU + 58; /* Space for 1280 IP buffer, Ethernet Header, 00265 RNDIS messages */ 00266 m->PacketAlignmentFactor = 3; 00267 m->AfListOffset = 0; 00268 m->AfListSize = 0; 00269 00270 rndis_state = rndis_initialized; 00271 00272 data_to_send = m->MessageLength; 00273 } 00274 break; 00275 case REMOTE_NDIS_HALT_MSG: 00276 00277 Led0_on(); 00278 Led1_on(); 00279 Led2_on(); 00280 Led3_on(); 00281 00282 00283 Usb_send_control_in(); 00284 00285 while(1); 00286 00287 00288 break; 00289 00290 case REMOTE_NDIS_QUERY_MSG: 00291 rndis_query_process(); 00292 break; 00293 00294 case REMOTE_NDIS_SET_MSG: 00295 { 00296 rndis_set_process(); 00297 } 00298 break; 00299 00300 case REMOTE_NDIS_RESET_MSG: 00301 { 00302 rndis_reset_cmplt_t * m; 00303 m = ((rndis_reset_cmplt_t *)encapsulated_buffer); 00304 00305 rndis_state = rndis_uninitialized; 00306 00307 m->MessageType = REMOTE_NDIS_RESET_CMPLT; 00308 m->MessageLength = sizeof(rndis_reset_cmplt_t); 00309 m->Status = RNDIS_STATUS_SUCCESS; 00310 m->AddressingReset = 1; /* Make it look like we did something */ 00311 // m->AddressingReset = 0; //Windows halts if set to 1 for some reason 00312 data_to_send = m->MessageLength; 00313 } 00314 break; 00315 00316 case REMOTE_NDIS_KEEPALIVE_MSG: 00317 { 00318 rndis_keepalive_cmplt_t * m; 00319 m = (rndis_keepalive_cmplt_t *)encapsulated_buffer; 00320 m->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT; 00321 m->MessageLength = sizeof(rndis_keepalive_cmplt_t); 00322 m->Status = RNDIS_STATUS_SUCCESS; 00323 00324 //We have data to send back 00325 data_to_send = m->MessageLength; 00326 break; 00327 } 00328 00329 default: 00330 Led2_on(); 00331 return FALSE; 00332 break; 00333 } 00334 00335 while(!(Is_usb_read_control_enabled())); 00336 00337 if (Is_usb_receive_out()) Usb_ack_receive_out(); 00338 00339 rndis_send_interrupt(); 00340 00341 return TRUE; 00342 } 00343 00344 /** 00345 * \brief Send an interrupt over the interrupt endpoint to the host. 00346 */ 00347 void rndis_send_interrupt(void) 00348 { 00349 00350 //Schedule the interrupt to take place next 00351 //time USB task is run 00352 schedule_interrupt = 1; 00353 } 00354 00355 #define INFBUF ((uint32_t *)(encapsulated_buffer + sizeof(rndis_query_cmplt_t))) 00356 00357 uint32_t oid_packet_filter = 0x0000000; 00358 00359 #if USB_ETH_EMULATE_WIFI 00360 uint16_t panid = 0xbaad; 00361 #endif 00362 00363 /** 00364 * \brief Function to handle a RNDIS "QUERY" command in the encapsulated_buffer 00365 */ 00366 void rndis_query_process(void) 00367 { 00368 rndis_query_msg_t * m; 00369 rndis_query_cmplt_t * c; 00370 rndis_Status_t status = RNDIS_STATUS_SUCCESS; 00371 00372 m = (rndis_query_msg_t *)encapsulated_buffer; 00373 c = (rndis_query_cmplt_t *)encapsulated_buffer; 00374 00375 /* We set up packet for sending one 4-byte response, which a lot of 00376 these will do. If you need more or less just change the defaults in 00377 the specific case */ 00378 00379 c->MessageType = REMOTE_NDIS_QUERY_CMPLT; 00380 //c->Status DO NOT SET YET - as m->Oid resides in this space. We still need it... 00381 c->InformationBufferLength = 4; 00382 c->InformationBufferOffset = 16; 00383 00384 switch (m->Oid) { 00385 00386 /**** GENERAL ****/ 00387 case OID_GEN_SUPPORTED_LIST: 00388 c->InformationBufferLength = 4 * OID_LIST_LENGTH; 00389 00390 //Copy data to SRAM 00391 memcpy_P(INFBUF, OIDSupportedList, 4*OID_LIST_LENGTH); 00392 break; 00393 00394 case OID_GEN_HARDWARE_STATUS: 00395 *INFBUF = 0x00000000; /* Ready and Willing */ 00396 break; 00397 00398 case OID_GEN_MEDIA_SUPPORTED: 00399 case OID_GEN_MEDIA_IN_USE: 00400 case OID_GEN_PHYSICAL_MEDIUM: 00401 #if USB_ETH_EMULATE_WIFI 00402 *INFBUF = NDIS_MEDIUM_WIRELESS_LAN; 00403 #else 00404 *INFBUF = NDIS_MEDIUM_802_3; 00405 #endif 00406 break; 00407 00408 case OID_GEN_MAXIMUM_FRAME_SIZE: 00409 *INFBUF = (uint32_t) USB_ETH_MTU-14; //1280 //102; /* Assume 25 octet header on 15.4 */ 00410 break; 00411 00412 case OID_GEN_LINK_SPEED: 00413 *INFBUF = (uint32_t) 250000/100; /* in 100 bytes/sec units.. this is kinda a lie */ 00414 break; 00415 00416 case OID_GEN_TRANSMIT_BLOCK_SIZE: 00417 case OID_GEN_RECEIVE_BLOCK_SIZE: 00418 *INFBUF = (uint32_t) 102; 00419 break; 00420 00421 case OID_GEN_VENDOR_ID: 00422 *INFBUF = 0xFFFFFF; /* No vendor ID ! */ 00423 break; 00424 00425 case OID_GEN_VENDOR_DESCRIPTION: 00426 c->InformationBufferLength = 8; 00427 memcpy_P(INFBUF, PSTR("Atmel\0\0\0\0"), 8); 00428 break; 00429 00430 case OID_GEN_CURRENT_PACKET_FILTER: 00431 *INFBUF = oid_packet_filter; 00432 break; 00433 00434 case OID_GEN_MAXIMUM_TOTAL_SIZE: 00435 *INFBUF = (uint32_t) USB_ETH_MTU; //127; 00436 break; 00437 00438 case OID_GEN_MEDIA_CONNECT_STATUS: 00439 *INFBUF = usb_eth_is_active?NDIS_MEDIA_STATE_CONNECTED:NDIS_MEDIA_STATE_DISCONNECTED; 00440 break; 00441 00442 case OID_GEN_VENDOR_DRIVER_VERSION: 00443 *INFBUF = 0x00001000; 00444 break; 00445 00446 00447 case OID_GEN_CURRENT_LOOKAHEAD: 00448 *INFBUF = (uint32_t) USB_ETH_MTU-14; //102; 00449 00450 // case OID_GEN_RNDIS_CONFIG_PARAMETER: 00451 // break; 00452 00453 /******* 802.3 (Ethernet) *******/ 00454 00455 /*The address of the NIC encoded in the hardware.*/ 00456 case OID_802_3_PERMANENT_ADDRESS: 00457 case OID_802_3_CURRENT_ADDRESS: 00458 00459 //Clear unused bytes 00460 *(INFBUF + 1) = 0; 00461 00462 //get address 00463 usb_eth_get_mac_address((uint8_t*)INFBUF); 00464 00465 /*4+2 = 6 Bytes of eth address */ 00466 c->InformationBufferLength += 2; 00467 break; 00468 00469 /* The multicast address list on the NIC enabled for packet reception. */ 00470 case OID_802_3_MULTICAST_LIST: 00471 *INFBUF = 0xE000000; 00472 break; 00473 00474 /* The maximum number of multicast addresses the NIC driver can manage. */ 00475 case OID_802_3_MAXIMUM_LIST_SIZE: 00476 *INFBUF = 1; 00477 break; 00478 00479 /* Features supported by the underlying driver, which could be emulating Ethernet. */ 00480 case OID_802_3_MAC_OPTIONS: 00481 *INFBUF = 0; 00482 break; 00483 00484 /* Frames received with alignment error */ 00485 case OID_802_3_RCV_ERROR_ALIGNMENT: 00486 /* Frames transmitted with one collision */ 00487 case OID_802_3_XMIT_ONE_COLLISION: 00488 /* Frames transmitted with more than one collision */ 00489 case OID_802_3_XMIT_MORE_COLLISIONS: 00490 *INFBUF = 0; 00491 break; 00492 00493 #if USB_ETH_EMULATE_WIFI 00494 /*** 802.11 OIDs ***/ 00495 case OID_802_11_BSSID: 00496 *INFBUF = (uint32_t)panid; 00497 *(INFBUF + 1) = 0; 00498 00499 /*4+2 = 6 Bytes of eth address */ 00500 c->InformationBufferLength += 2; 00501 break; 00502 00503 case OID_802_11_SSID: 00504 /* Our SSID is *always* "PANID: 0xXXXX", length = 13 */ 00505 *INFBUF = 13; 00506 00507 strncpy_P((char*)(INFBUF + 1), PSTR("PANID: 0xBAAD"), 13); 00508 break; 00509 00510 case OID_802_11_NETWORK_TYPE_IN_USE: 00511 *INFBUF = 0; /* Ndis802_11FH - it's all lies anyway */ 00512 break; 00513 00514 case OID_802_11_RSSI: 00515 *((int32_t *) INFBUF) = -20; //-20 dBm 00516 break; 00517 00518 case OID_802_11_BSSID_LIST: 00519 break; 00520 00521 /* todo: */ 00522 case OID_802_11_INFRASTRUCTURE_MODE: 00523 case OID_802_11_SUPPORTED_RATES: 00524 case OID_802_11_CONFIGURATION: 00525 case OID_802_11_WEP_STATUS: 00526 case OID_802_11_AUTHENTICATION_MODE: 00527 break; 00528 #endif //USB_ETH_EMULATE_WIFI 00529 00530 /*** Statistical ***/ 00531 00532 /* Frames transmitted without errors */ 00533 case OID_GEN_XMIT_OK: 00534 *INFBUF = usb_eth_stat.txok; 00535 break; 00536 00537 /* Frames received without errors */ 00538 case OID_GEN_RCV_OK: 00539 *INFBUF = usb_eth_stat.rxok; 00540 break; 00541 00542 /* Frames received with errors */ 00543 case OID_GEN_RCV_ERROR: 00544 *INFBUF = usb_eth_stat.rxbad; 00545 break; 00546 00547 /* Frames transmitted with errors */ 00548 case OID_GEN_XMIT_ERROR: 00549 *INFBUF = usb_eth_stat.txbad; 00550 break; 00551 00552 /* Frames dropped due to lack of buffer space */ 00553 case OID_GEN_RCV_NO_BUFFER: 00554 00555 *INFBUF = 0; /* Lies! */ 00556 break; 00557 00558 /*** Power Managment ***/ 00559 case OID_PNP_CAPABILITIES: 00560 c->InformationBufferLength = sizeof(struct NDIS_PM_WAKE_UP_CAPABILITIES); 00561 00562 //Sorry, I don't play ball. Power managment is for hippies 00563 memset((char *)INFBUF, 0, sizeof(struct NDIS_PM_WAKE_UP_CAPABILITIES)); 00564 break; 00565 00566 case OID_PNP_QUERY_POWER: 00567 c->InformationBufferLength = 0; 00568 break; 00569 00570 case OID_PNP_ENABLE_WAKE_UP: 00571 *INFBUF = 0; /* Nothing Supported */ 00572 break; 00573 00574 default: 00575 status = RNDIS_STATUS_FAILURE; 00576 c->InformationBufferLength = 0; 00577 break; 00578 00579 00580 } 00581 00582 //Set Status now that we are done with Oid 00583 c->Status = status; 00584 00585 //Calculate message size 00586 c->MessageLength = sizeof (rndis_query_cmplt_t) + c->InformationBufferLength; 00587 00588 //Check if we are sending no information buffer 00589 if (c->InformationBufferLength == 0) { 00590 c->InformationBufferOffset = 0; 00591 } 00592 00593 //Set it up 00594 data_to_send = c->MessageLength; 00595 } 00596 00597 00598 #undef INFBUF 00599 #define INFBUF ((uint32_t *)((uint8_t *)&(m->RequestId) + m->InformationBufferOffset)) 00600 #define CFGBUF ((rndis_config_parameter_t *) INFBUF) 00601 #define PARMNAME ((uint8_t *)CFGBUF + CFGBUF->ParameterNameOffset) 00602 #define PARMVALUE ((uint8_t *)CFGBUF + CFGBUF->ParameterValueOffset) 00603 #define PARMVALUELENGTH CFGBUF->ParameterValueLength 00604 #define PARM_NAME_LENGTH 25 /* Maximum parameter name length */ 00605 00606 void 00607 rndis_handle_config_parm(const char* parmname,const uint8_t* parmvalue,size_t parmlength) { 00608 if (strncmp_P(parmname, PSTR("rawmode"), 7) == 0) { 00609 if (parmvalue[0] == '0') { 00610 usbstick_mode.raw = 0; 00611 } else { 00612 usbstick_mode.raw = 1; 00613 } 00614 } 00615 00616 } 00617 00618 /** 00619 * \brief Function to deal with a RNDIS "SET" command present in the 00620 * encapsulated_buffer 00621 */ 00622 void rndis_set_process(void) 00623 { 00624 rndis_set_cmplt_t * c; 00625 rndis_set_msg_t * m; 00626 00627 c = ((rndis_set_cmplt_t *)encapsulated_buffer); 00628 m = ((rndis_set_msg_t *)encapsulated_buffer); 00629 00630 //Never have longer parameter names than PARM_NAME_LENGTH 00631 char parmname[PARM_NAME_LENGTH]; 00632 00633 uint8_t i; 00634 int8_t parmlength; 00635 00636 /* The parameter name seems to be transmitted in uint16_t, but 00637 we want this in uint8_t. Hence have to throw out some info... */ 00638 if (CFGBUF->ParameterNameLength > (PARM_NAME_LENGTH*2)) { 00639 parmlength = PARM_NAME_LENGTH * 2; 00640 } else { 00641 parmlength = CFGBUF->ParameterNameLength; 00642 } 00643 00644 i = 0; 00645 while(parmlength > 0) { 00646 //Convert from uint16_t to char array. 00647 parmname[i] = (char)*(PARMNAME + 2*i); 00648 parmlength -= 2; 00649 i++; 00650 } 00651 00652 00653 switch(m->Oid) { 00654 00655 /* Parameters set up in 'Advanced' tab */ 00656 case OID_GEN_RNDIS_CONFIG_PARAMETER: 00657 /* Parameter name: rawmode 00658 Parameter desc: Enables or disable raw capture of 802.15.4 Packets 00659 Parameter type: single octet 00660 Parameter values: '0' = disabled, '1' = enabled 00661 */ 00662 rndis_handle_config_parm(parmname,PARMVALUE,PARMVALUELENGTH); 00663 00664 00665 break; 00666 00667 /* Mandatory general OIDs */ 00668 case OID_GEN_CURRENT_PACKET_FILTER: 00669 oid_packet_filter = *INFBUF; 00670 00671 if (oid_packet_filter) { 00672 00673 rndis_packetFilter(oid_packet_filter); 00674 00675 rndis_state = rndis_data_initialized; 00676 } else { 00677 rndis_state = rndis_initialized; 00678 } 00679 00680 break; 00681 00682 case OID_GEN_CURRENT_LOOKAHEAD: 00683 break; 00684 00685 case OID_GEN_PROTOCOL_OPTIONS: 00686 break; 00687 00688 /* Mandatory 802_3 OIDs */ 00689 case OID_802_3_MULTICAST_LIST: 00690 break; 00691 00692 #if USB_ETH_EMULATE_WIFI 00693 /* Mandatory 802.11 OIDs */ 00694 case OID_802_11_BSSID: 00695 panid = *INFBUF; 00696 break; 00697 00698 case OID_802_11_SSID: 00699 break; 00700 //TODO: rest of 802.11 00701 #endif // USB_ETH_EMULATE_WIFI 00702 00703 /* Power Managment: fails for now */ 00704 case OID_PNP_ADD_WAKE_UP_PATTERN: 00705 case OID_PNP_REMOVE_WAKE_UP_PATTERN: 00706 case OID_PNP_ENABLE_WAKE_UP: 00707 00708 default: 00709 //c->MessageID is same as before 00710 c->MessageType = REMOTE_NDIS_SET_CMPLT; 00711 c->MessageLength = sizeof(rndis_set_cmplt_t); 00712 c->Status = RNDIS_STATUS_FAILURE; 00713 data_to_send = c->MessageLength; 00714 return; 00715 00716 break; 00717 } 00718 00719 //c->MessageID is same as before 00720 c->MessageType = REMOTE_NDIS_SET_CMPLT; 00721 c->MessageLength = sizeof(rndis_set_cmplt_t); 00722 c->Status = RNDIS_STATUS_SUCCESS; 00723 data_to_send = c->MessageLength; 00724 return; 00725 } 00726 00727 /** 00728 * \brief Handle "GET ENCAPSULATED COMMAND" 00729 * 00730 * \return True on success, false on failure. 00731 * 00732 * This function assumes the message has already set up in 00733 * the "encapsulated_buffer" variable. This will be done by 00734 * the "SEND ENCAPSULATED COMMAND" message, which will trigger 00735 * and interrupt on the host so it knows data is ready. 00736 */ 00737 uint8_t rndis_get_encapsulated_command(void) 00738 { 00739 U8 nb_byte, zlp, i; 00740 00741 //We assume this is already set up... 00742 00743 //Received setup message OK 00744 Usb_ack_receive_setup(); 00745 00746 if ((data_to_send % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; } 00747 else { zlp = FALSE; } //!< no need of zero length packet 00748 00749 00750 i = 0; 00751 while((data_to_send != 0) && (!Is_usb_receive_out())) 00752 { 00753 while(!Is_usb_read_control_enabled()); 00754 00755 nb_byte=0; 00756 while(data_to_send != 0) //!< Send data until necessary 00757 { 00758 if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size 00759 { 00760 break; 00761 } 00762 Usb_write_byte(encapsulated_buffer[i]); 00763 i++; 00764 data_to_send--; 00765 00766 } 00767 Usb_send_control_in(); 00768 } 00769 00770 if(Is_usb_receive_out()) { Usb_ack_receive_out(); return TRUE; } //!< abort from Host 00771 00772 if(zlp == TRUE) 00773 { 00774 while(!Is_usb_read_control_enabled()); 00775 Usb_send_control_in(); 00776 } 00777 00778 while(!Is_usb_receive_out()); 00779 Usb_ack_receive_out(); 00780 00781 return TRUE; 00782 } 00783 00784 00785 /** 00786 * \brief Send a status packet back to the host 00787 * 00788 * \return Sucess or Failure 00789 * \retval 1 Success 00790 * \retval 0 Failure 00791 */ 00792 uint8_t rndis_send_status(rndis_Status_t stat) 00793 { 00794 uint8_t i; 00795 00796 if(Is_usb_read_control_enabled() && !data_to_send) { 00797 00798 rndis_indicate_status_t * m; 00799 m = (rndis_indicate_status_t *)encapsulated_buffer; 00800 00801 m->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG; 00802 m->MessageLength = sizeof(rndis_indicate_status_t); 00803 m->Status = stat; 00804 00805 for(i = 0; i < sizeof(rndis_indicate_status_t); i++) { 00806 Usb_write_byte(encapsulated_buffer[i]); 00807 } 00808 00809 Usb_send_control_in(); 00810 while(!(Is_usb_read_control_enabled())); 00811 00812 while(!Is_usb_receive_out()); 00813 Usb_ack_receive_out(); 00814 00815 return 1; 00816 } 00817 00818 00819 return 0; 00820 } 00821 00822 void rndis_configure_endpoints() { 00823 usb_configure_endpoint(INT_EP, \ 00824 TYPE_INTERRUPT, \ 00825 DIRECTION_IN, \ 00826 SIZE_8, \ 00827 ONE_BANK, \ 00828 NYET_ENABLED); 00829 usb_configure_endpoint(TX_EP, \ 00830 TYPE_BULK, \ 00831 DIRECTION_IN, \ 00832 SIZE_64, \ 00833 TWO_BANKS, \ 00834 NYET_ENABLED); 00835 00836 usb_configure_endpoint(RX_EP, \ 00837 TYPE_BULK, \ 00838 DIRECTION_OUT, \ 00839 SIZE_64, \ 00840 TWO_BANKS, \ 00841 NYET_ENABLED); 00842 Usb_reset_endpoint(INT_EP); 00843 Usb_reset_endpoint(TX_EP); 00844 Usb_reset_endpoint(RX_EP); 00845 } 00846 00847 00848 extern char usb_busy; 00849 extern uint8_t usb_eth_data_buffer[64]; 00850 #define PBUF ((rndis_data_packet_t *) usb_eth_data_buffer) 00851 00852 00853 uint8_t rndis_process(void) 00854 { 00855 uint8_t bytecounter, headercounter; 00856 uint16_t i, dataoffset; 00857 00858 if(rndis_state != rndis_data_initialized) { //Enumeration processs OK ? 00859 return 0; 00860 } 00861 00862 #ifdef USB_ETH_HOOK_INIT 00863 static uint8_t doInit = 1; 00864 if (doInit) { 00865 USB_ETH_HOOK_INIT(); 00866 doInit = 0; 00867 } 00868 #endif 00869 00870 //Connected! 00871 Led0_on(); 00872 00873 Usb_select_endpoint(RX_EP); 00874 00875 //If we have data and a free buffer 00876 if(Is_usb_receive_out() && (uip_len == 0)) { 00877 00878 //Read how much (endpoint only stores up to 64 bytes anyway) 00879 bytecounter = Usb_byte_counter_8(); 00880 00881 //Try and read the header in 00882 headercounter = sizeof(rndis_data_packet_t); 00883 00884 uint8_t fail = 0; 00885 00886 //Hmm.. what's going on here 00887 if (bytecounter < headercounter) { 00888 Usb_ack_receive_out(); 00889 fail = 1; 00890 } 00891 00892 i = 0; 00893 while (headercounter) { 00894 usb_eth_data_buffer[i] = Usb_read_byte(); 00895 bytecounter--; 00896 headercounter--; 00897 i++; 00898 } 00899 00900 //This is no good. Probably lost syncronization... just drop it for now 00901 if(PBUF->MessageType != REMOTE_NDIS_PACKET_MSG) { 00902 Usb_ack_receive_out(); 00903 fail = 1; 00904 } 00905 00906 //802.3 does not have OOB data, and we don't care about per-packet data 00907 //so that just leave regular packet data... 00908 if (PBUF->DataLength && (fail == 0)) { 00909 00910 //Looks like we've got a live one 00911 #ifdef USB_ETH_HOOK_RX_START 00912 USB_ETH_HOOK_RX_START(); 00913 #endif 00914 00915 //Get offset 00916 dataoffset = PBUF->DataOffset; 00917 00918 //Make it offset from start of message, not DataOffset field 00919 dataoffset += (sizeof(rndis_MessageType_t) + sizeof(rndis_MessageLength_t)); 00920 00921 //Subtract what we already took 00922 dataoffset -= sizeof(rndis_data_packet_t); 00923 00924 //Clear this flag 00925 Usb_ack_nak_out(); 00926 00927 //Read to the start of data 00928 while(dataoffset) { 00929 Usb_read_byte(); 00930 dataoffset--; 00931 bytecounter--; 00932 00933 //If endpoint is done 00934 if (bytecounter == 0) { 00935 00936 Usb_ack_receive_out(); 00937 00938 00939 //Wait for new data 00940 while (!Is_usb_receive_out() && (!Is_usb_receive_nak_out())); 00941 00942 //Check for NAK 00943 // TODO: darco: What in the world is this for? 00944 if (Is_usb_receive_nak_out()) { 00945 Usb_ack_nak_out(); 00946 break; 00947 } 00948 00949 bytecounter = Usb_byte_counter_8(); 00950 00951 //ZLP? 00952 if (bytecounter == 0) 00953 break; 00954 } 00955 00956 } 00957 00958 //Read the data itself in 00959 uint8_t * uipdata = uip_buf; 00960 uint16_t datalen = PBUF->DataLength; 00961 00962 while(datalen) { 00963 *uipdata++ = Usb_read_byte(); 00964 datalen--; 00965 bytecounter--; 00966 00967 //If endpoint is done 00968 if (bytecounter == 0) { 00969 //Might be everything we need! 00970 if (datalen) { 00971 Usb_ack_receive_out(); 00972 //Wait for new data 00973 if(usb_endpoint_wait_for_receive_out()!=0) { 00974 USB_ETH_HOOK_RX_ERROR("Timeout: receive out"); 00975 goto bail; 00976 } 00977 bytecounter = Usb_byte_counter_8(); 00978 } 00979 } 00980 00981 } 00982 00983 //Ack final data packet 00984 Usb_ack_receive_out(); 00985 00986 #ifdef USB_ETH_HOOK_RX_END 00987 USB_ETH_HOOK_RX_END(); 00988 #endif 00989 00990 //Send data over RF or to local stack 00991 if(PBUF->DataLength <= USB_ETH_MTU) { 00992 USB_ETH_HOOK_HANDLE_INBOUND_PACKET(uip_buf,PBUF->DataLength); 00993 } else { 00994 USB_ETH_HOOK_RX_ERROR("Oversized packet"); 00995 } 00996 } //if (PBUF->DataLength) 00997 } 00998 bail: 00999 return 1; 01000 } 01001 01002 /** 01003 \brief Send data over RNDIS interface, data is in uipbuf and length is uiplen 01004 */ 01005 uint8_t rndis_send(uint8_t * senddata, uint16_t sendlen, uint8_t led) 01006 { 01007 01008 01009 uint16_t i; 01010 01011 //Setup Header 01012 PBUF->MessageType = REMOTE_NDIS_PACKET_MSG; 01013 PBUF->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_MessageType_t) - sizeof(rndis_MessageLength_t); 01014 PBUF->DataLength = sendlen; 01015 PBUF->OOBDataLength = 0; 01016 PBUF->OOBDataOffset = 0; 01017 PBUF->NumOOBDataElements = 0; 01018 PBUF->PerPacketInfoOffset = 0; 01019 PBUF->PerPacketInfoLength = 0; 01020 PBUF->DeviceVcHandle = 0; 01021 PBUF->Reserved = 0; 01022 PBUF->MessageLength = sizeof(rndis_data_packet_t) + PBUF->DataLength; 01023 01024 //Send Data 01025 Usb_select_endpoint(TX_EP); 01026 Usb_send_in(); 01027 01028 //Wait for ready 01029 if(usb_endpoint_wait_for_write_enabled()!=0) { 01030 USB_ETH_HOOK_TX_ERROR("Timeout: write enabled"); 01031 return 0; 01032 } 01033 01034 #ifdef USB_ETH_HOOK_TX_START 01035 USB_ETH_HOOK_TX_START(); 01036 #endif 01037 01038 //Setup first part of transfer... 01039 for(i = 0; i < sizeof(rndis_data_packet_t); i++) { 01040 Usb_write_byte(usb_eth_data_buffer[i]); 01041 } 01042 01043 //Send packet 01044 while(sendlen) { 01045 Usb_write_byte(*senddata); 01046 senddata++; 01047 sendlen--; 01048 01049 //If endpoint is full, send data in 01050 //And then wait for data to transfer 01051 if (!Is_usb_write_enabled()) { 01052 Usb_send_in(); 01053 01054 if(usb_endpoint_wait_for_write_enabled()!=0) { 01055 USB_ETH_HOOK_TX_ERROR("Timeout: write enabled"); 01056 return 0; 01057 } 01058 } 01059 01060 } 01061 01062 Usb_send_in(); 01063 01064 #ifdef USB_ETH_HOOK_TX_END 01065 USB_ETH_HOOK_TX_END(); 01066 #endif 01067 01068 //Wait for ready 01069 if(usb_endpoint_wait_for_IN_ready()!=0) { 01070 USB_ETH_HOOK_TX_ERROR("Timeout: IN ready"); 01071 return 0; 01072 } 01073 01074 return 1; 01075 } 01076 01077 01078 /****************** Radio Interface ****************/ 01079 01080 /** 01081 * \brief Set the packet filter - currently distinguishes 01082 * between promiscuous mode and normal mode 01083 */ 01084 void rndis_packetFilter(uint32_t newfilter) 01085 { 01086 if (newfilter & NDIS_PACKET_TYPE_PROMISCUOUS) { 01087 USB_ETH_HOOK_SET_PROMISCIOUS_MODE(true); 01088 } else { 01089 USB_ETH_HOOK_SET_PROMISCIOUS_MODE(false); 01090 } 01091 } 01092 01093 /** @} */