Contiki 2.5
rndis.c
Go to the documentation of this file.
1 /**
2  * \file rndis.c
3  * RNDIS Functions for mounting USB device as network interface
4  *
5  * \author
6  * Colin O'Flynn <coflynn@newae.com>
7  *
8  * \addtogroup usbstick
9  */
10 /* Copyright (c) 2008 Colin O'Flynn
11 
12  The CDC code which this is based on is Copyright (c) Atmel Corporation 2008
13  All rights reserved.
14 
15  Redistribution and use in source and binary forms, with or without
16  modification, are permitted provided that the following conditions are met:
17 
18  * Redistributions of source code must retain the above copyright
19  notice, this list of conditions and the following disclaimer.
20  * Redistributions in binary form must reproduce the above copyright
21  notice, this list of conditions and the following disclaimer in
22  the documentation and/or other materials provided with the
23  distribution.
24  * Neither the name of the copyright holders nor the names of
25  contributors may be used to endorse or promote products derived
26  from this software without specific prior written permission.
27 
28  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
32  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  POSSIBILITY OF SUCH DAMAGE.
39 */
40 
41 /*
42 RNDIS Status Information:
43 
44 802.3 Support:
45  More or less working
46 
47 802.11 Support:
48  Incomplete, would just error out if you tried probably
49 
50 
51 */
52 
53 /**
54  \addtogroup RNDIS
55  @{
56  */
57 
58 
59 //_____ I N C L U D E S ____________________________________________________
60 
61 #include <stdbool.h>
62 #include "radio.h"
63 #include "contiki.h"
64 #include "config.h"
65 #include "usb_drv.h"
66 #include "usb_descriptors.h"
67 #include "usb_specific_request.h"
68 #include "rndis/rndis_protocol.h"
69 #include "rndis/rndis_task.h"
70 #include "uip.h"
71 #include "serial/uart_usb_lib.h"
72 #include "sicslow_ethernet.h"
73 #include <avr/pgmspace.h>
74 #include <string.h>
75 #if RF230BB
76 #include "rf230bb.h"
77 #endif
78 
79 #include <stdio.h>
80 #include <avr/pgmspace.h>
81 #include <util/delay.h>
82 
83 
84 //_____ M A C R O S ________________________________________________________
85 
86 //_____ D E F I N I T I O N ________________________________________________
87 
88 //_____ P R I V A T E D E C L A R A T I O N ______________________________
89 
90 extern PGM_VOID_P pbuffer;
91 extern U8 data_to_transfer;
92 
93 /**
94  * \brief List of supported RNDIS OID's
95  */
96 prog_uint32_t OIDSupportedList[] = {
97  /* Required General */
98  OID_GEN_SUPPORTED_LIST ,
99  OID_GEN_HARDWARE_STATUS ,
100  OID_GEN_MEDIA_SUPPORTED ,
101  OID_GEN_MEDIA_IN_USE ,
102  OID_GEN_MAXIMUM_FRAME_SIZE ,
103  OID_GEN_LINK_SPEED ,
104  OID_GEN_TRANSMIT_BLOCK_SIZE ,
105  OID_GEN_RECEIVE_BLOCK_SIZE ,
106  OID_GEN_VENDOR_ID ,
107  OID_GEN_VENDOR_DESCRIPTION ,
108  OID_GEN_CURRENT_PACKET_FILTER ,
109  OID_GEN_MAXIMUM_TOTAL_SIZE ,
110  OID_GEN_MEDIA_CONNECT_STATUS ,
111  OID_GEN_VENDOR_DRIVER_VERSION ,
112  OID_GEN_PHYSICAL_MEDIUM ,
113 
114  /* Required Statistical */
115  OID_GEN_XMIT_OK ,
116  OID_GEN_RCV_OK ,
117  OID_GEN_XMIT_ERROR ,
118  OID_GEN_RCV_ERROR ,
119  OID_GEN_RCV_NO_BUFFER ,
120 
121  /* Please configure us */
122  OID_GEN_RNDIS_CONFIG_PARAMETER ,
123 
124 
125  /* IEEE 802.3 (Ethernet) OIDs */
126  OID_802_3_PERMANENT_ADDRESS ,
127  OID_802_3_CURRENT_ADDRESS ,
128  OID_802_3_MULTICAST_LIST ,
129  OID_802_3_MAXIMUM_LIST_SIZE ,
130  OID_802_3_MAC_OPTIONS ,
131  OID_802_3_RCV_ERROR_ALIGNMENT ,
132  OID_802_3_XMIT_ONE_COLLISION ,
133  OID_802_3_XMIT_MORE_COLLISIONS ,
134 
135 /*802.11 OID's not fully implemented yet. Hence do not say we
136  support them */
137 #if USB_ETH_EMULATE_WIFI
138  /* 802.11 OIDs */
139  OID_802_11_BSSID ,
140  OID_802_11_SSID ,
141  OID_802_11_NETWORK_TYPE_IN_USE ,
142  OID_802_11_RSSI ,
143  OID_802_11_BSSID_LIST ,
144  OID_802_11_BSSID_LIST_SCAN ,
145  OID_802_11_INFRASTRUCTURE_MODE ,
146  OID_802_11_SUPPORTED_RATES ,
147  OID_802_11_CONFIGURATION ,
148  OID_802_11_ADD_WEP ,
149  OID_802_11_WEP_STATUS ,
150  OID_802_11_REMOVE_WEP ,
151  OID_802_11_DISASSOCIATE ,
152  OID_802_11_AUTHENTICATION_MODE ,
153  OID_802_11_RELOAD_DEFAULTS ,
154 #endif
155 
156  /* Minimum power managment needed for USB */
157 
158  OID_PNP_CAPABILITIES ,
159  OID_PNP_QUERY_POWER ,
160  OID_PNP_SET_POWER ,
161 
162  OID_PNP_ENABLE_WAKE_UP ,
163  OID_PNP_ADD_WAKE_UP_PATTERN ,
164  OID_PNP_REMOVE_WAKE_UP_PATTERN
165 };
166 
167 #define OID_LIST_LENGTH sizeof(OIDSupportedList)/sizeof(*OIDSupportedList)
168 
169 
170 rndis_state_t rndis_state;
171 
172 usb_eth_stat_t usb_eth_stat;
173 
174 uint8_t schedule_interrupt = 0;
175 
176 //_____ D E C L A R A T I O N ______________________________________________
177 
178 
179 void rndis_packetFilter(uint32_t newfilter);
180 
181 /******** RNDIS ********/
182 
183 #define ENC_BUF_SIZE (4*OID_LIST_LENGTH + 32)
184 
185 // Command buffer
186 U8 encapsulated_buffer[ENC_BUF_SIZE];
187 
188 //Do we have data to send back?
189 U8 data_to_send = 0x00;
190 
191 /**
192  * \brief Handles a "SEND ENCAPSULATED COMMAND" message.
193  *
194  * \return True on success, false on failure.
195  */
196 uint8_t rndis_send_encapsulated_command(uint16_t wLength)
197 {
198  U8 i = 0;
199 
200  //Received setup message OK
202 
203 
204  //Crude bounds check
205  if (wLength > ENC_BUF_SIZE)
206  wLength = ENC_BUF_SIZE;
207 
208  //Read in all the bytes...
209 
210  uint8_t nb_counter;
211 
212  //Clear NAK bit
213  Usb_ack_nak_in();
214 
215  while (wLength) {
216  nb_counter = EP_CONTROL_LENGTH;
217 
218  //Wait for data to come in or nak
219  while((!Is_usb_receive_out()) & (!Is_usb_receive_nak_in()));
220 
221  //Received OUT
222  if (Is_usb_receive_out()) {
223  while(nb_counter && wLength) {
224  encapsulated_buffer[i] = Usb_read_byte();
225  i++;
226  wLength--;
227  nb_counter--;
228  }
229 
231 
232  //Received NAK, no more data
233  } else {
234  Usb_ack_nak_in();
235  break;
236  }
237  }
238 
240 
241 
242  switch(((rndis_generic_msg_t *)encapsulated_buffer)->MessageType)
243  {
244  /* Requests remote intilization. Respond with complete,
245  eventually should probably do something */
246  case REMOTE_NDIS_INITIALIZE_MSG:
247  {
248  rndis_initialize_cmplt_t * m;
249  m = ((rndis_initialize_cmplt_t *)encapsulated_buffer);
250 
251  //m->MessageID is same as before
252  m->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
253  m->MessageLength = sizeof(rndis_initialize_cmplt_t);
254  m->MajorVersion = RNDIS_MAJOR_VERSION;
255  m->MinorVersion = RNDIS_MAJOR_VERSION;
256  m->Status = RNDIS_STATUS_SUCCESS;
257  m->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
258 #if USB_ETH_EMULATE_WIFI
259  m->Medium = NDIS_MEDIUM_WIRELESS_LAN;
260 #else
261  m->Medium = RNDIS_MEDIUM_802_3;
262 #endif // USB_ETH_EMULATE_WIFI
263  m->MaxPacketsPerTransfer = 1;
264  m->MaxTransferSize = USB_ETH_MTU + 58; /* Space for 1280 IP buffer, Ethernet Header,
265  RNDIS messages */
266  m->PacketAlignmentFactor = 3;
267  m->AfListOffset = 0;
268  m->AfListSize = 0;
269 
270  rndis_state = rndis_initialized;
271 
272  data_to_send = m->MessageLength;
273  }
274  break;
275  case REMOTE_NDIS_HALT_MSG:
276 
277  Led0_on();
278  Led1_on();
279  Led2_on();
280  Led3_on();
281 
282 
284 
285  while(1);
286 
287 
288  break;
289 
290  case REMOTE_NDIS_QUERY_MSG:
292  break;
293 
294  case REMOTE_NDIS_SET_MSG:
295  {
297  }
298  break;
299 
300  case REMOTE_NDIS_RESET_MSG:
301  {
302  rndis_reset_cmplt_t * m;
303  m = ((rndis_reset_cmplt_t *)encapsulated_buffer);
304 
305  rndis_state = rndis_uninitialized;
306 
307  m->MessageType = REMOTE_NDIS_RESET_CMPLT;
308  m->MessageLength = sizeof(rndis_reset_cmplt_t);
309  m->Status = RNDIS_STATUS_SUCCESS;
310  m->AddressingReset = 1; /* Make it look like we did something */
311  // m->AddressingReset = 0; //Windows halts if set to 1 for some reason
312  data_to_send = m->MessageLength;
313  }
314  break;
315 
316  case REMOTE_NDIS_KEEPALIVE_MSG:
317  {
318  rndis_keepalive_cmplt_t * m;
319  m = (rndis_keepalive_cmplt_t *)encapsulated_buffer;
320  m->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
321  m->MessageLength = sizeof(rndis_keepalive_cmplt_t);
322  m->Status = RNDIS_STATUS_SUCCESS;
323 
324  //We have data to send back
325  data_to_send = m->MessageLength;
326  break;
327  }
328 
329  default:
330  Led2_on();
331  return FALSE;
332  break;
333  }
334 
335  while(!(Is_usb_read_control_enabled()));
336 
338 
340 
341  return TRUE;
342 }
343 
344 /**
345  * \brief Send an interrupt over the interrupt endpoint to the host.
346  */
348  {
349 
350  //Schedule the interrupt to take place next
351  //time USB task is run
352  schedule_interrupt = 1;
353  }
354 
355 #define INFBUF ((uint32_t *)(encapsulated_buffer + sizeof(rndis_query_cmplt_t)))
356 
357 uint32_t oid_packet_filter = 0x0000000;
358 
359 #if USB_ETH_EMULATE_WIFI
360 uint16_t panid = 0xbaad;
361 #endif
362 
363 /**
364  * \brief Function to handle a RNDIS "QUERY" command in the encapsulated_buffer
365  */
367  {
368  rndis_query_msg_t * m;
369  rndis_query_cmplt_t * c;
370  rndis_Status_t status = RNDIS_STATUS_SUCCESS;
371 
372  m = (rndis_query_msg_t *)encapsulated_buffer;
373  c = (rndis_query_cmplt_t *)encapsulated_buffer;
374 
375  /* We set up packet for sending one 4-byte response, which a lot of
376  these will do. If you need more or less just change the defaults in
377  the specific case */
378 
379  c->MessageType = REMOTE_NDIS_QUERY_CMPLT;
380  //c->Status DO NOT SET YET - as m->Oid resides in this space. We still need it...
381  c->InformationBufferLength = 4;
382  c->InformationBufferOffset = 16;
383 
384  switch (m->Oid) {
385 
386  /**** GENERAL ****/
387  case OID_GEN_SUPPORTED_LIST:
388  c->InformationBufferLength = 4 * OID_LIST_LENGTH;
389 
390  //Copy data to SRAM
391  memcpy_P(INFBUF, OIDSupportedList, 4*OID_LIST_LENGTH);
392  break;
393 
394  case OID_GEN_HARDWARE_STATUS:
395  *INFBUF = 0x00000000; /* Ready and Willing */
396  break;
397 
398  case OID_GEN_MEDIA_SUPPORTED:
399  case OID_GEN_MEDIA_IN_USE:
400  case OID_GEN_PHYSICAL_MEDIUM:
401 #if USB_ETH_EMULATE_WIFI
402  *INFBUF = NDIS_MEDIUM_WIRELESS_LAN;
403 #else
404  *INFBUF = NDIS_MEDIUM_802_3;
405 #endif
406  break;
407 
408  case OID_GEN_MAXIMUM_FRAME_SIZE:
409  *INFBUF = (uint32_t) USB_ETH_MTU-14; //1280 //102; /* Assume 25 octet header on 15.4 */
410  break;
411 
412  case OID_GEN_LINK_SPEED:
413  *INFBUF = (uint32_t) 250000/100; /* in 100 bytes/sec units.. this is kinda a lie */
414  break;
415 
416  case OID_GEN_TRANSMIT_BLOCK_SIZE:
417  case OID_GEN_RECEIVE_BLOCK_SIZE:
418  *INFBUF = (uint32_t) 102;
419  break;
420 
421  case OID_GEN_VENDOR_ID:
422  *INFBUF = 0xFFFFFF; /* No vendor ID ! */
423  break;
424 
425  case OID_GEN_VENDOR_DESCRIPTION:
426  c->InformationBufferLength = 8;
427  memcpy_P(INFBUF, PSTR("Atmel\0\0\0\0"), 8);
428  break;
429 
430  case OID_GEN_CURRENT_PACKET_FILTER:
431  *INFBUF = oid_packet_filter;
432  break;
433 
434  case OID_GEN_MAXIMUM_TOTAL_SIZE:
435  *INFBUF = (uint32_t) USB_ETH_MTU; //127;
436  break;
437 
438  case OID_GEN_MEDIA_CONNECT_STATUS:
439  *INFBUF = usb_eth_is_active?NDIS_MEDIA_STATE_CONNECTED:NDIS_MEDIA_STATE_DISCONNECTED;
440  break;
441 
442  case OID_GEN_VENDOR_DRIVER_VERSION:
443  *INFBUF = 0x00001000;
444  break;
445 
446 
447  case OID_GEN_CURRENT_LOOKAHEAD:
448  *INFBUF = (uint32_t) USB_ETH_MTU-14; //102;
449 
450 // case OID_GEN_RNDIS_CONFIG_PARAMETER:
451 // break;
452 
453  /******* 802.3 (Ethernet) *******/
454 
455  /*The address of the NIC encoded in the hardware.*/
456  case OID_802_3_PERMANENT_ADDRESS:
457  case OID_802_3_CURRENT_ADDRESS:
458 
459  //Clear unused bytes
460  *(INFBUF + 1) = 0;
461 
462  //get address
463  usb_eth_get_mac_address((uint8_t*)INFBUF);
464 
465  /*4+2 = 6 Bytes of eth address */
466  c->InformationBufferLength += 2;
467  break;
468 
469  /* The multicast address list on the NIC enabled for packet reception. */
470  case OID_802_3_MULTICAST_LIST:
471  *INFBUF = 0xE000000;
472  break;
473 
474  /* The maximum number of multicast addresses the NIC driver can manage. */
475  case OID_802_3_MAXIMUM_LIST_SIZE:
476  *INFBUF = 1;
477  break;
478 
479  /* Features supported by the underlying driver, which could be emulating Ethernet. */
480  case OID_802_3_MAC_OPTIONS:
481  *INFBUF = 0;
482  break;
483 
484  /* Frames received with alignment error */
485  case OID_802_3_RCV_ERROR_ALIGNMENT:
486  /* Frames transmitted with one collision */
487  case OID_802_3_XMIT_ONE_COLLISION:
488  /* Frames transmitted with more than one collision */
489  case OID_802_3_XMIT_MORE_COLLISIONS:
490  *INFBUF = 0;
491  break;
492 
493 #if USB_ETH_EMULATE_WIFI
494  /*** 802.11 OIDs ***/
495  case OID_802_11_BSSID:
496  *INFBUF = (uint32_t)panid;
497  *(INFBUF + 1) = 0;
498 
499  /*4+2 = 6 Bytes of eth address */
500  c->InformationBufferLength += 2;
501  break;
502 
503  case OID_802_11_SSID:
504  /* Our SSID is *always* "PANID: 0xXXXX", length = 13 */
505  *INFBUF = 13;
506 
507  strncpy_P((char*)(INFBUF + 1), PSTR("PANID: 0xBAAD"), 13);
508  break;
509 
510  case OID_802_11_NETWORK_TYPE_IN_USE:
511  *INFBUF = 0; /* Ndis802_11FH - it's all lies anyway */
512  break;
513 
514  case OID_802_11_RSSI:
515  *((int32_t *) INFBUF) = -20; //-20 dBm
516  break;
517 
518  case OID_802_11_BSSID_LIST:
519  break;
520 
521  /* todo: */
522  case OID_802_11_INFRASTRUCTURE_MODE:
523  case OID_802_11_SUPPORTED_RATES:
524  case OID_802_11_CONFIGURATION:
525  case OID_802_11_WEP_STATUS:
526  case OID_802_11_AUTHENTICATION_MODE:
527  break;
528 #endif //USB_ETH_EMULATE_WIFI
529 
530  /*** Statistical ***/
531 
532  /* Frames transmitted without errors */
533  case OID_GEN_XMIT_OK:
534  *INFBUF = usb_eth_stat.txok;
535  break;
536 
537  /* Frames received without errors */
538  case OID_GEN_RCV_OK:
539  *INFBUF = usb_eth_stat.rxok;
540  break;
541 
542  /* Frames received with errors */
543  case OID_GEN_RCV_ERROR:
544  *INFBUF = usb_eth_stat.rxbad;
545  break;
546 
547  /* Frames transmitted with errors */
548  case OID_GEN_XMIT_ERROR:
549  *INFBUF = usb_eth_stat.txbad;
550  break;
551 
552  /* Frames dropped due to lack of buffer space */
553  case OID_GEN_RCV_NO_BUFFER:
554 
555  *INFBUF = 0; /* Lies! */
556  break;
557 
558  /*** Power Managment ***/
559  case OID_PNP_CAPABILITIES:
560  c->InformationBufferLength = sizeof(struct NDIS_PM_WAKE_UP_CAPABILITIES);
561 
562  //Sorry, I don't play ball. Power managment is for hippies
563  memset((char *)INFBUF, 0, sizeof(struct NDIS_PM_WAKE_UP_CAPABILITIES));
564  break;
565 
566  case OID_PNP_QUERY_POWER:
567  c->InformationBufferLength = 0;
568  break;
569 
570  case OID_PNP_ENABLE_WAKE_UP:
571  *INFBUF = 0; /* Nothing Supported */
572  break;
573 
574  default:
575  status = RNDIS_STATUS_FAILURE;
576  c->InformationBufferLength = 0;
577  break;
578 
579 
580  }
581 
582  //Set Status now that we are done with Oid
583  c->Status = status;
584 
585  //Calculate message size
586  c->MessageLength = sizeof (rndis_query_cmplt_t) + c->InformationBufferLength;
587 
588  //Check if we are sending no information buffer
589  if (c->InformationBufferLength == 0) {
590  c->InformationBufferOffset = 0;
591  }
592 
593  //Set it up
594  data_to_send = c->MessageLength;
595  }
596 
597 
598 #undef INFBUF
599 #define INFBUF ((uint32_t *)((uint8_t *)&(m->RequestId) + m->InformationBufferOffset))
600 #define CFGBUF ((rndis_config_parameter_t *) INFBUF)
601 #define PARMNAME ((uint8_t *)CFGBUF + CFGBUF->ParameterNameOffset)
602 #define PARMVALUE ((uint8_t *)CFGBUF + CFGBUF->ParameterValueOffset)
603 #define PARMVALUELENGTH CFGBUF->ParameterValueLength
604 #define PARM_NAME_LENGTH 25 /* Maximum parameter name length */
605 
606 void
607 rndis_handle_config_parm(const char* parmname,const uint8_t* parmvalue,size_t parmlength) {
608  if (strncmp_P(parmname, PSTR("rawmode"), 7) == 0) {
609  if (parmvalue[0] == '0') {
610  usbstick_mode.raw = 0;
611  } else {
612  usbstick_mode.raw = 1;
613  }
614  }
615 
616 }
617 
618 /**
619  * \brief Function to deal with a RNDIS "SET" command present in the
620  * encapsulated_buffer
621  */
623  {
624  rndis_set_cmplt_t * c;
625  rndis_set_msg_t * m;
626 
627  c = ((rndis_set_cmplt_t *)encapsulated_buffer);
628  m = ((rndis_set_msg_t *)encapsulated_buffer);
629 
630  //Never have longer parameter names than PARM_NAME_LENGTH
631  char parmname[PARM_NAME_LENGTH];
632 
633  uint8_t i;
634  int8_t parmlength;
635 
636  /* The parameter name seems to be transmitted in uint16_t, but
637  we want this in uint8_t. Hence have to throw out some info... */
638  if (CFGBUF->ParameterNameLength > (PARM_NAME_LENGTH*2)) {
639  parmlength = PARM_NAME_LENGTH * 2;
640  } else {
641  parmlength = CFGBUF->ParameterNameLength;
642  }
643 
644  i = 0;
645  while(parmlength > 0) {
646  //Convert from uint16_t to char array.
647  parmname[i] = (char)*(PARMNAME + 2*i);
648  parmlength -= 2;
649  i++;
650  }
651 
652 
653  switch(m->Oid) {
654 
655  /* Parameters set up in 'Advanced' tab */
656  case OID_GEN_RNDIS_CONFIG_PARAMETER:
657  /* Parameter name: rawmode
658  Parameter desc: Enables or disable raw capture of 802.15.4 Packets
659  Parameter type: single octet
660  Parameter values: '0' = disabled, '1' = enabled
661  */
662  rndis_handle_config_parm(parmname,PARMVALUE,PARMVALUELENGTH);
663 
664 
665  break;
666 
667  /* Mandatory general OIDs */
668  case OID_GEN_CURRENT_PACKET_FILTER:
669  oid_packet_filter = *INFBUF;
670 
671  if (oid_packet_filter) {
672 
673  rndis_packetFilter(oid_packet_filter);
674 
675  rndis_state = rndis_data_initialized;
676  } else {
677  rndis_state = rndis_initialized;
678  }
679 
680  break;
681 
682  case OID_GEN_CURRENT_LOOKAHEAD:
683  break;
684 
685  case OID_GEN_PROTOCOL_OPTIONS:
686  break;
687 
688  /* Mandatory 802_3 OIDs */
689  case OID_802_3_MULTICAST_LIST:
690  break;
691 
692 #if USB_ETH_EMULATE_WIFI
693  /* Mandatory 802.11 OIDs */
694  case OID_802_11_BSSID:
695  panid = *INFBUF;
696  break;
697 
698  case OID_802_11_SSID:
699  break;
700  //TODO: rest of 802.11
701 #endif // USB_ETH_EMULATE_WIFI
702 
703  /* Power Managment: fails for now */
704  case OID_PNP_ADD_WAKE_UP_PATTERN:
705  case OID_PNP_REMOVE_WAKE_UP_PATTERN:
706  case OID_PNP_ENABLE_WAKE_UP:
707 
708  default:
709  //c->MessageID is same as before
710  c->MessageType = REMOTE_NDIS_SET_CMPLT;
711  c->MessageLength = sizeof(rndis_set_cmplt_t);
712  c->Status = RNDIS_STATUS_FAILURE;
713  data_to_send = c->MessageLength;
714  return;
715 
716  break;
717  }
718 
719  //c->MessageID is same as before
720  c->MessageType = REMOTE_NDIS_SET_CMPLT;
721  c->MessageLength = sizeof(rndis_set_cmplt_t);
722  c->Status = RNDIS_STATUS_SUCCESS;
723  data_to_send = c->MessageLength;
724  return;
725  }
726 
727 /**
728  * \brief Handle "GET ENCAPSULATED COMMAND"
729  *
730  * \return True on success, false on failure.
731  *
732  * This function assumes the message has already set up in
733  * the "encapsulated_buffer" variable. This will be done by
734  * the "SEND ENCAPSULATED COMMAND" message, which will trigger
735  * and interrupt on the host so it knows data is ready.
736  */
738  {
739  U8 nb_byte, zlp, i;
740 
741  //We assume this is already set up...
742 
743  //Received setup message OK
745 
746  if ((data_to_send % EP_CONTROL_LENGTH) == 0) { zlp = TRUE; }
747  else { zlp = FALSE; } //!< no need of zero length packet
748 
749 
750  i = 0;
751  while((data_to_send != 0) && (!Is_usb_receive_out()))
752  {
753  while(!Is_usb_read_control_enabled());
754 
755  nb_byte=0;
756  while(data_to_send != 0) //!< Send data until necessary
757  {
758  if(nb_byte++==EP_CONTROL_LENGTH) //!< Check endpoint 0 size
759  {
760  break;
761  }
762  Usb_write_byte(encapsulated_buffer[i]);
763  i++;
764  data_to_send--;
765 
766  }
768  }
769 
770  if(Is_usb_receive_out()) { Usb_ack_receive_out(); return TRUE; } //!< abort from Host
771 
772  if(zlp == TRUE)
773  {
774  while(!Is_usb_read_control_enabled());
776  }
777 
778  while(!Is_usb_receive_out());
780 
781  return TRUE;
782  }
783 
784 
785 /**
786  * \brief Send a status packet back to the host
787  *
788  * \return Sucess or Failure
789  * \retval 1 Success
790  * \retval 0 Failure
791  */
792 uint8_t rndis_send_status(rndis_Status_t stat)
793  {
794  uint8_t i;
795 
796  if(Is_usb_read_control_enabled() && !data_to_send) {
797 
798  rndis_indicate_status_t * m;
799  m = (rndis_indicate_status_t *)encapsulated_buffer;
800 
801  m->MessageType = REMOTE_NDIS_INDICATE_STATUS_MSG;
802  m->MessageLength = sizeof(rndis_indicate_status_t);
803  m->Status = stat;
804 
805  for(i = 0; i < sizeof(rndis_indicate_status_t); i++) {
806  Usb_write_byte(encapsulated_buffer[i]);
807  }
808 
810  while(!(Is_usb_read_control_enabled()));
811 
812  while(!Is_usb_receive_out());
814 
815  return 1;
816  }
817 
818 
819  return 0;
820  }
821 
822 void rndis_configure_endpoints() {
823  usb_configure_endpoint(INT_EP, \
824  TYPE_INTERRUPT, \
825  DIRECTION_IN, \
826  SIZE_8, \
827  ONE_BANK, \
828  NYET_ENABLED);
829  usb_configure_endpoint(TX_EP, \
830  TYPE_BULK, \
831  DIRECTION_IN, \
832  SIZE_64, \
833  TWO_BANKS, \
834  NYET_ENABLED);
835 
836  usb_configure_endpoint(RX_EP, \
837  TYPE_BULK, \
838  DIRECTION_OUT, \
839  SIZE_64, \
840  TWO_BANKS, \
841  NYET_ENABLED);
842  Usb_reset_endpoint(INT_EP);
843  Usb_reset_endpoint(TX_EP);
844  Usb_reset_endpoint(RX_EP);
845 }
846 
847 
848 extern char usb_busy;
849 extern uint8_t usb_eth_data_buffer[64];
850 #define PBUF ((rndis_data_packet_t *) usb_eth_data_buffer)
851 
852 
853 uint8_t rndis_process(void)
854 {
855  uint8_t bytecounter, headercounter;
856  uint16_t i, dataoffset;
857 
858  if(rndis_state != rndis_data_initialized) { //Enumeration processs OK ?
859  return 0;
860  }
861 
862 #ifdef USB_ETH_HOOK_INIT
863  static uint8_t doInit = 1;
864  if (doInit) {
865  USB_ETH_HOOK_INIT();
866  doInit = 0;
867  }
868 #endif
869 
870  //Connected!
871  Led0_on();
872 
873  Usb_select_endpoint(RX_EP);
874 
875  //If we have data and a free buffer
876  if(Is_usb_receive_out() && (uip_len == 0)) {
877 
878  //Read how much (endpoint only stores up to 64 bytes anyway)
879  bytecounter = Usb_byte_counter_8();
880 
881  //Try and read the header in
882  headercounter = sizeof(rndis_data_packet_t);
883 
884  uint8_t fail = 0;
885 
886  //Hmm.. what's going on here
887  if (bytecounter < headercounter) {
889  fail = 1;
890  }
891 
892  i = 0;
893  while (headercounter) {
894  usb_eth_data_buffer[i] = Usb_read_byte();
895  bytecounter--;
896  headercounter--;
897  i++;
898  }
899 
900  //This is no good. Probably lost syncronization... just drop it for now
901  if(PBUF->MessageType != REMOTE_NDIS_PACKET_MSG) {
903  fail = 1;
904  }
905 
906  //802.3 does not have OOB data, and we don't care about per-packet data
907  //so that just leave regular packet data...
908  if (PBUF->DataLength && (fail == 0)) {
909 
910  //Looks like we've got a live one
911 #ifdef USB_ETH_HOOK_RX_START
912  USB_ETH_HOOK_RX_START();
913 #endif
914 
915  //Get offset
916  dataoffset = PBUF->DataOffset;
917 
918  //Make it offset from start of message, not DataOffset field
919  dataoffset += (sizeof(rndis_MessageType_t) + sizeof(rndis_MessageLength_t));
920 
921  //Subtract what we already took
922  dataoffset -= sizeof(rndis_data_packet_t);
923 
924  //Clear this flag
925  Usb_ack_nak_out();
926 
927  //Read to the start of data
928  while(dataoffset) {
929  Usb_read_byte();
930  dataoffset--;
931  bytecounter--;
932 
933  //If endpoint is done
934  if (bytecounter == 0) {
935 
937 
938 
939  //Wait for new data
940  while (!Is_usb_receive_out() && (!Is_usb_receive_nak_out()));
941 
942  //Check for NAK
943  // TODO: darco: What in the world is this for?
944  if (Is_usb_receive_nak_out()) {
945  Usb_ack_nak_out();
946  break;
947  }
948 
949  bytecounter = Usb_byte_counter_8();
950 
951  //ZLP?
952  if (bytecounter == 0)
953  break;
954  }
955 
956  }
957 
958  //Read the data itself in
959  uint8_t * uipdata = uip_buf;
960  uint16_t datalen = PBUF->DataLength;
961 
962  while(datalen) {
963  *uipdata++ = Usb_read_byte();
964  datalen--;
965  bytecounter--;
966 
967  //If endpoint is done
968  if (bytecounter == 0) {
969  //Might be everything we need!
970  if (datalen) {
972  //Wait for new data
973  if(usb_endpoint_wait_for_receive_out()!=0) {
974  USB_ETH_HOOK_RX_ERROR("Timeout: receive out");
975  goto bail;
976  }
977  bytecounter = Usb_byte_counter_8();
978  }
979  }
980 
981  }
982 
983  //Ack final data packet
985 
986 #ifdef USB_ETH_HOOK_RX_END
987  USB_ETH_HOOK_RX_END();
988 #endif
989 
990  //Send data over RF or to local stack
991  if(PBUF->DataLength <= USB_ETH_MTU) {
992  USB_ETH_HOOK_HANDLE_INBOUND_PACKET(uip_buf,PBUF->DataLength);
993  } else {
994  USB_ETH_HOOK_RX_ERROR("Oversized packet");
995  }
996  } //if (PBUF->DataLength)
997  }
998 bail:
999  return 1;
1000 }
1001 
1002 /**
1003  \brief Send data over RNDIS interface, data is in uipbuf and length is uiplen
1004  */
1005 uint8_t rndis_send(uint8_t * senddata, uint16_t sendlen, uint8_t led)
1006 {
1007 
1008 
1009  uint16_t i;
1010 
1011  //Setup Header
1012  PBUF->MessageType = REMOTE_NDIS_PACKET_MSG;
1013  PBUF->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_MessageType_t) - sizeof(rndis_MessageLength_t);
1014  PBUF->DataLength = sendlen;
1015  PBUF->OOBDataLength = 0;
1016  PBUF->OOBDataOffset = 0;
1017  PBUF->NumOOBDataElements = 0;
1018  PBUF->PerPacketInfoOffset = 0;
1019  PBUF->PerPacketInfoLength = 0;
1020  PBUF->DeviceVcHandle = 0;
1021  PBUF->Reserved = 0;
1022  PBUF->MessageLength = sizeof(rndis_data_packet_t) + PBUF->DataLength;
1023 
1024  //Send Data
1025  Usb_select_endpoint(TX_EP);
1026  Usb_send_in();
1027 
1028  //Wait for ready
1029  if(usb_endpoint_wait_for_write_enabled()!=0) {
1030  USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
1031  return 0;
1032  }
1033 
1034 #ifdef USB_ETH_HOOK_TX_START
1035  USB_ETH_HOOK_TX_START();
1036 #endif
1037 
1038  //Setup first part of transfer...
1039  for(i = 0; i < sizeof(rndis_data_packet_t); i++) {
1040  Usb_write_byte(usb_eth_data_buffer[i]);
1041  }
1042 
1043  //Send packet
1044  while(sendlen) {
1045  Usb_write_byte(*senddata);
1046  senddata++;
1047  sendlen--;
1048 
1049  //If endpoint is full, send data in
1050  //And then wait for data to transfer
1051  if (!Is_usb_write_enabled()) {
1052  Usb_send_in();
1053 
1054  if(usb_endpoint_wait_for_write_enabled()!=0) {
1055  USB_ETH_HOOK_TX_ERROR("Timeout: write enabled");
1056  return 0;
1057  }
1058  }
1059 
1060  }
1061 
1062  Usb_send_in();
1063 
1064 #ifdef USB_ETH_HOOK_TX_END
1065  USB_ETH_HOOK_TX_END();
1066 #endif
1067 
1068  //Wait for ready
1069  if(usb_endpoint_wait_for_IN_ready()!=0) {
1070  USB_ETH_HOOK_TX_ERROR("Timeout: IN ready");
1071  return 0;
1072  }
1073 
1074  return 1;
1075 }
1076 
1077 
1078 /****************** Radio Interface ****************/
1079 
1080 /**
1081  * \brief Set the packet filter - currently distinguishes
1082  * between promiscuous mode and normal mode
1083  */
1084 void rndis_packetFilter(uint32_t newfilter)
1085 {
1086  if (newfilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
1087  USB_ETH_HOOK_SET_PROMISCIOUS_MODE(true);
1088  } else {
1089  USB_ETH_HOOK_SET_PROMISCIOUS_MODE(false);
1090  }
1091 }
1092 
1093 /** @} */