rndis_driver.c
Go to the documentation of this file.
1 /**
2  * @file rndis_driver.c
3  * @brief RNDIS driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 1.9.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "usbd_def.h"
36 #include "usbd_rndis.h"
37 #include "core/net.h"
38 #include "rndis.h"
39 #include "rndis_driver.h"
40 #include "rndis_debug.h"
41 #include "debug.h"
42 
43 //Underlying network interface
45 
46 //TX and RX buffers
49 
50 //Buffer indexes
55 
56 
57 /**
58  * @brief RNDIS driver
59  **/
60 
62 {
64  ETH_MTU,
72  NULL,
73  NULL,
74  NULL,
75  TRUE,
76  TRUE,
77  TRUE,
78  TRUE
79 };
80 
81 
82 /**
83  * @brief RNDIS driver initialization
84  * @param[in] interface Underlying network interface
85  * @return Error code
86  **/
87 
89 {
90  //Debug message
91  TRACE_INFO("Initializing RNDIS driver...\r\n");
92 
93  //Save underlying network interface
94  rndisDriverInterface = interface;
95 
96  //Clear TX and RX buffers
97  memset(rndisTxBuffer, 0, sizeof(rndisTxBuffer));
98  memset(rndisRxBuffer, 0, sizeof(rndisRxBuffer));
99 
100  //Initialize variables
101  rndisTxWriteIndex = 0;
102  rndisTxReadIndex = 0;
103  rndisRxWriteIndex = 0;
104  rndisRxReadIndex = 0;
105 
106  //The RNDIS driver is now ready to send
107  osSetEvent(&interface->nicTxEvent);
108 
109  //Force the TCP/IP stack to check the link state
111  interface->nicEvent = TRUE;
113 
114  //Successful initialization
115  return NO_ERROR;
116 }
117 
118 
119 /**
120  * @brief RNDIS driver timer handler
121  *
122  * This routine is periodically called by the TCP/IP stack to
123  * handle periodic operations such as polling the link state
124  *
125  * @param[in] interface Underlying network interface
126  **/
127 
129 {
130  //Not implemented
131 }
132 
133 
134 /**
135  * @brief Enable interrupts
136  * @param[in] interface Underlying network interface
137  **/
138 
140 {
141  //Enable OTG_FS interrupts
142  NVIC_EnableIRQ(OTG_FS_IRQn);
143 }
144 
145 
146 /**
147  * @brief Disable interrupts
148  * @param[in] interface Underlying network interface
149  **/
150 
152 {
153  //Disable OTG_FS interrupts
154  NVIC_DisableIRQ(OTG_FS_IRQn);
155 }
156 
157 
158 /**
159  * @brief RNDIS driver event handler
160  * @param[in] interface Underlying network interface
161  **/
162 
164 {
165  static uint8_t temp[ETH_MAX_FRAME_SIZE];
166  error_t error;
167  size_t length;
168 
169  //Link up/down event is pending?
171  {
172  //Clear event flag
174 
175  //Check link state
177  {
178  //Link is up
179  interface->linkState = TRUE;
180  //Link speed
181  interface->linkSpeed = 12000000;
182  }
183  else
184  {
185  //Link is down
186  interface->linkState = FALSE;
187  }
188 
189  //Process link state change event
190  nicNotifyLinkChange(interface);
191  }
192 
193  //Process all pending packets
194  do
195  {
196  //Read incoming packet
197  error = rndisDriverReceivePacket(interface,
198  temp, ETH_MAX_FRAME_SIZE, &length);
199 
200  //Check whether a valid packet has been received
201  if(!error)
202  {
203  //Pass the packet to the upper layer
204  nicProcessPacket(interface, temp, length);
205  }
206 
207  //No more data in the receive buffer?
208  } while(error != ERROR_BUFFER_EMPTY);
209 }
210 
211 
212 /**
213  * @brief Send a packet
214  * @param[in] interface Underlying network interface
215  * @param[in] buffer Multi-part buffer containing the data to send
216  * @param[in] offset Offset to the first data byte
217  * @return Error code
218  **/
219 
221  const NetBuffer *buffer, size_t offset)
222 {
223  size_t length;
225 
226  //Retrieve the length of the packet
227  length = netBufferGetLength(buffer) - offset;
228 
229  //Check the frame length
230  if((length + sizeof(RndisPacketMsg)) > RNDIS_TX_BUFFER_SIZE)
231  {
232  //The transmitter can accept another packet
233  osSetEvent(&interface->nicTxEvent);
234  //Report an error
235  return ERROR_INVALID_LENGTH;
236  }
237 
238  //Make sure the current buffer is available for writing
240  return ERROR_FAILURE;
241 
242  //Point to the buffer where to format the RNDIS Packet message
244 
245  //Format the RNDIS Packet message
246  message->messageType = RNDIS_PACKET_MSG;
247  message->messageLength = sizeof(RndisPacketMsg) + length;
248  message->dataOffset = sizeof(RndisPacketMsg) - 8;
249  message->dataLength = length;
250  message->oobDataOffset = 0;
251  message->oobDataLength = 0;
252  message->numOobDataElements = 0;
253  message->perPacketInfoOffset = 0;
254  message->perPacketInfoLength = 0;
255  message->vcHandle = 0;
256  message->reserved = 0;
257 
258  //Copy user data to the transmit buffer
259  netBufferRead(message->payload, buffer, offset, length);
260 
261  //Debug message
262  TRACE_DEBUG("Sending RNDIS Packet message (%" PRIuSIZE " bytes)...\r\n",
263  message->messageLength);
264  //Dump RNDIS Packet message contents
265  rndisDumpMsg((RndisMsg *) message, message->messageLength);
266 
267  //Check whether the RNDIS Packet message ends with a USB packet whose
268  //length is exactly the wMaxPacketSize for the DATA IN endpoint
269  if((message->messageLength % RNDIS_DATA_IN_EP_MPS_FS) == 0)
270  {
271  //The device may send an additional one-byte zero packet
272  message->payload[length] = 0;
273  message->messageLength++;
274  }
275 
276  //Set the number of bytes to send
277  rndisTxBuffer[rndisTxWriteIndex].length = message->messageLength;
278 
279  //Give the ownership of the buffer to the USB engine
281 
282  //Debug message
283  TRACE_DEBUG("########## Sending DATA IN\r\n");
284 
285  //Transmission is currently suspended?
286  if(!rndisContext.txState)
287  {
288  //Start transmitting data
289  USBD_LL_Transmit(&USBD_Device, RNDIS_DATA_IN_EP,
292 
293  //Transmission is active
295  }
296 
297  //Increment index and wrap around if necessary
299  rndisTxWriteIndex = 0;
300 
301  //Check whether the next buffer is available for writing
302  if(!rndisTxBuffer[rndisTxWriteIndex].ready)
303  {
304  //The transmitter can accept another packet
305  osSetEvent(&interface->nicTxEvent);
306  }
307 
308  //Data successfully written
309  return NO_ERROR;
310 }
311 
312 
313 /**
314  * @brief Receive a packet
315  * @param[in] interface Underlying network interface
316  * @param[out] buffer Buffer where to store the incoming data
317  * @param[in] size Maximum number of bytes that can be received
318  * @param[out] length Number of bytes that have been received
319  * @return Error code
320  **/
321 
323  uint8_t *buffer, size_t size, size_t *length)
324 {
325  error_t error;
326  size_t n;
328 
329  //Check whether the current buffer is available for reading
331  {
332  //Retrieve the length of the RNDIS Packet message
334 
335  //Check the length of message
336  if(n >= sizeof(RndisPacketMsg))
337  {
338  //Point to the RNDIS Packet message
340 
341  //Make sure the message is valid
342  if((message->dataOffset + message->dataLength) <= n)
343  {
344  //Limit the number of data to read
345  n = MIN(message->dataLength, size);
346  //Copy data from the receive buffer
347  memcpy(buffer, (uint8_t *) message + message->dataOffset + 8, n);
348 
349  //Total number of bytes that have been received
350  *length = n;
351  //Packet successfully received
352  error = NO_ERROR;
353  }
354  else
355  {
356  //Invalid message
357  error = ERROR_INVALID_MESSAGE;
358  }
359  }
360  else
361  {
362  //Invalid message
363  error = ERROR_INVALID_MESSAGE;
364  }
365 
366  //Reset the length field
368  //Give the ownership of the buffer to the USB engine
370 
371  //Increment index and wrap around if necessary
373  rndisRxReadIndex = 0;
374 
375  //Reception is currently suspended?
376  if(!rndisContext.rxState)
377  {
378  //Debug message
379  TRACE_DEBUG("### usbdRndisReceivePacket 111 ###\r\n");
380 
381  //Prepare DATA OUT endpoint for reception
382  USBD_LL_PrepareReceive(&USBD_Device, RNDIS_DATA_OUT_EP,
384 
385  //Reception is active
387  }
388  }
389  else
390  {
391  //No more data in the receive buffer
392  error = ERROR_BUFFER_EMPTY;
393  }
394 
395  //Return status code
396  return error;
397 }
398 
399 
400 /**
401  * @brief Configure multicast MAC address filtering
402  * @param[in] interface Underlying network interface
403  * @return Error code
404  **/
405 
407 {
408  //Successful processing
409  return NO_ERROR;
410 }
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:525
RNDIS Packet message.
Definition: rndis.h:407
#define RNDIS_TX_BUFFER_SIZE
Definition: rndis_driver.h:46
uint_t rndisTxReadIndex
Definition: rndis_driver.c:52
#define RNDIS_DATA_IN_EP_MPS_FS
Definition: usbd_rndis.h:44
uint8_t length
Definition: dtls_misc.h:149
#define RNDIS_PACKET_MSG
Definition: rndis.h:56
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:672
error_t rndisDriverSetMulticastFilter(NetInterface *interface)
Configure multicast MAC address filtering.
Definition: rndis_driver.c:406
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length)
Handle a packet received by the network controller.
Definition: nic.c:383
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:88
#define TRUE
Definition: os_port.h:50
USBD_HandleTypeDef USBD_Device
#define ETH_MAX_FRAME_SIZE
Definition: ethernet.h:89
NetInterface * rndisDriverInterface
Definition: rndis_driver.c:44
@ ERROR_INVALID_MESSAGE
Definition: error.h:103
uint8_t rxBuffer[RNDIS_MAX_TRANSFER_SIZE]
Definition: rndis.h:473
error_t rndisDriverReceivePacket(NetInterface *interface, uint8_t *buffer, size_t size, size_t *length)
Receive a packet.
Definition: rndis_driver.c:322
bool_t linkState
Definition: rndis.h:469
RNDIS (Remote Network Driver Interface Specification)
#define FALSE
Definition: os_port.h:46
USB RNDIS class.
error_t rndisDriverSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
Definition: rndis_driver.c:220
error_t
Error codes.
Definition: error.h:42
RndisRxBufferDesc rndisRxBuffer[RNDIS_RX_BUFFER_COUNT]
Definition: rndis_driver.c:48
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define RNDIS_TX_BUFFER_COUNT
Definition: rndis_driver.h:39
bool_t txState
Definition: rndis.h:470
#define NetInterface
Definition: net.h:36
RX buffer descriptor.
Definition: rndis_driver.h:82
error_t rndisDriverInit(NetInterface *interface)
RNDIS driver initialization.
Definition: rndis_driver.c:88
@ ERROR_INVALID_LENGTH
Definition: error.h:109
@ ERROR_BUFFER_EMPTY
Definition: error.h:139
bool_t linkEvent
Definition: rndis.h:468
uint_t rndisTxWriteIndex
Definition: rndis_driver.c:51
OsEvent netEvent
Definition: net.c:77
#define RNDIS_DATA_OUT_EP
Definition: usbd_rndis.h:40
#define TRACE_INFO(...)
Definition: debug.h:94
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
TX buffer descriptor.
Definition: rndis_driver.h:70
#define MIN(a, b)
Definition: os_port.h:62
Generic RNDIS message.
Definition: rndis.h:208
#define RNDIS_DATA_OUT_EP_MPS_FS
Definition: usbd_rndis.h:45
bool_t rxState
Definition: rndis.h:471
uint_t rndisRxWriteIndex
Definition: rndis_driver.c:53
void rndisDriverDisableIrq(NetInterface *interface)
Disable interrupts.
Definition: rndis_driver.c:151
const NicDriver rndisDriver
RNDIS driver.
Definition: rndis_driver.c:61
#define TRACE_DEBUG(...)
Definition: debug.h:106
RNDIS (Remote Network Driver Interface Specification)
RNDIS driver.
#define ETH_MTU
Definition: ethernet.h:91
uint8_t n
error_t rndisDumpMsg(const RndisMsg *message, size_t length)
Dump RNDIS message for debugging purpose.
Definition: rndis_debug.c:124
#define RNDIS_DATA_IN_EP
Definition: usbd_rndis.h:39
RndisContext rndisContext
Definition: rndis.c:54
uint8_t message[]
Definition: chap.h:152
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define RNDIS_RX_BUFFER_COUNT
Definition: rndis_driver.h:53
void rndisDriverEventHandler(NetInterface *interface)
RNDIS driver event handler.
Definition: rndis_driver.c:163
void rndisDriverTick(NetInterface *interface)
RNDIS driver timer handler.
Definition: rndis_driver.c:128
#define PRIuSIZE
Definition: compiler_port.h:78
unsigned int uint_t
Definition: compiler_port.h:45
TCP/IP stack core.
uint8_t data[]
Definition: dtls_misc.h:176
NIC driver.
Definition: nic.h:179
void rndisDriverEnableIrq(NetInterface *interface)
Enable interrupts.
Definition: rndis_driver.c:139
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
RndisTxBufferDesc rndisTxBuffer[RNDIS_TX_BUFFER_COUNT]
Definition: rndis_driver.c:47
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:79
uint_t rndisRxReadIndex
Definition: rndis_driver.c:54