Contiki 2.6

rndis.c

Go to the documentation of this file.
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 /** @} */