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-2024 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 2.4.0
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
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 handle periodic
123  * 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  NetRxAncillary ancillary;
204 
205  //Additional options can be passed to the stack along with the packet
206  ancillary = NET_DEFAULT_RX_ANCILLARY;
207 
208  //Pass the packet to the upper layer
209  nicProcessPacket(interface, temp, length, &ancillary);
210  }
211 
212  //No more data in the receive buffer?
213  } while(error != ERROR_BUFFER_EMPTY);
214 }
215 
216 
217 /**
218  * @brief Send a packet
219  * @param[in] interface Underlying network interface
220  * @param[in] buffer Multi-part buffer containing the data to send
221  * @param[in] offset Offset to the first data byte
222  * @param[in] ancillary Additional options passed to the stack along with
223  * the packet
224  * @return Error code
225  **/
226 
228  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
229 {
230  size_t length;
232 
233  //Retrieve the length of the packet
234  length = netBufferGetLength(buffer) - offset;
235 
236  //Check the frame length
237  if((length + sizeof(RndisPacketMsg)) > RNDIS_TX_BUFFER_SIZE)
238  {
239  //The transmitter can accept another packet
240  osSetEvent(&interface->nicTxEvent);
241  //Report an error
242  return ERROR_INVALID_LENGTH;
243  }
244 
245  //Make sure the current buffer is available for writing
247  return ERROR_FAILURE;
248 
249  //Point to the buffer where to format the RNDIS Packet message
251 
252  //Format the RNDIS Packet message
253  message->messageType = RNDIS_PACKET_MSG;
254  message->messageLength = sizeof(RndisPacketMsg) + length;
255  message->dataOffset = sizeof(RndisPacketMsg) - 8;
256  message->dataLength = length;
257  message->oobDataOffset = 0;
258  message->oobDataLength = 0;
259  message->numOobDataElements = 0;
260  message->perPacketInfoOffset = 0;
261  message->perPacketInfoLength = 0;
262  message->vcHandle = 0;
263  message->reserved = 0;
264 
265  //Copy user data to the transmit buffer
266  netBufferRead(message->payload, buffer, offset, length);
267 
268  //Debug message
269  TRACE_DEBUG("Sending RNDIS Packet message (%" PRIuSIZE " bytes)...\r\n",
270  message->messageLength);
271  //Dump RNDIS Packet message contents
272  rndisDumpMsg((RndisMsg *) message, message->messageLength);
273 
274  //Check whether the RNDIS Packet message ends with a USB packet whose
275  //length is exactly the wMaxPacketSize for the DATA IN endpoint
276  if((message->messageLength % RNDIS_DATA_IN_EP_MPS_FS) == 0)
277  {
278  //The device may send an additional one-byte zero packet
279  message->payload[length] = 0;
280  message->messageLength++;
281  }
282 
283  //Set the number of bytes to send
284  rndisTxBuffer[rndisTxWriteIndex].length = message->messageLength;
285 
286  //Give the ownership of the buffer to the USB engine
288 
289  //Debug message
290  TRACE_DEBUG("########## Sending DATA IN\r\n");
291 
292  //Transmission is currently suspended?
293  if(!rndisContext.txState)
294  {
295  //Start transmitting data
296  USBD_LL_Transmit(&USBD_Device, RNDIS_DATA_IN_EP,
299 
300  //Transmission is active
302  }
303 
304  //Increment index and wrap around if necessary
306  rndisTxWriteIndex = 0;
307 
308  //Check whether the next buffer is available for writing
309  if(!rndisTxBuffer[rndisTxWriteIndex].ready)
310  {
311  //The transmitter can accept another packet
312  osSetEvent(&interface->nicTxEvent);
313  }
314 
315  //Data successfully written
316  return NO_ERROR;
317 }
318 
319 
320 /**
321  * @brief Receive a packet
322  * @param[in] interface Underlying network interface
323  * @param[out] buffer Buffer where to store the incoming data
324  * @param[in] size Maximum number of bytes that can be received
325  * @param[out] length Number of bytes that have been received
326  * @return Error code
327  **/
328 
330  uint8_t *buffer, size_t size, size_t *length)
331 {
332  error_t error;
333  size_t n;
335 
336  //Check whether the current buffer is available for reading
338  {
339  //Retrieve the length of the RNDIS Packet message
341 
342  //Check the length of message
343  if(n >= sizeof(RndisPacketMsg))
344  {
345  //Point to the RNDIS Packet message
347 
348  //Make sure the message is valid
349  if((message->dataOffset + message->dataLength) <= n)
350  {
351  //Limit the number of data to read
352  n = MIN(message->dataLength, size);
353  //Copy data from the receive buffer
354  osMemcpy(buffer, (uint8_t *) message + message->dataOffset + 8, n);
355 
356  //Total number of bytes that have been received
357  *length = n;
358  //Packet successfully received
359  error = NO_ERROR;
360  }
361  else
362  {
363  //Invalid message
364  error = ERROR_INVALID_MESSAGE;
365  }
366  }
367  else
368  {
369  //Invalid message
370  error = ERROR_INVALID_MESSAGE;
371  }
372 
373  //Reset the length field
375  //Give the ownership of the buffer to the USB engine
377 
378  //Increment index and wrap around if necessary
380  rndisRxReadIndex = 0;
381 
382  //Reception is currently suspended?
383  if(!rndisContext.rxState)
384  {
385  //Debug message
386  TRACE_DEBUG("### usbdRndisReceivePacket 111 ###\r\n");
387 
388  //Prepare DATA OUT endpoint for reception
389  USBD_LL_PrepareReceive(&USBD_Device, RNDIS_DATA_OUT_EP,
391 
392  //Reception is active
394  }
395  }
396  else
397  {
398  //No more data in the receive buffer
399  error = ERROR_BUFFER_EMPTY;
400  }
401 
402  //Return status code
403  return error;
404 }
405 
406 
407 /**
408  * @brief Configure multicast MAC address filtering
409  * @param[in] interface Underlying network interface
410  * @return Error code
411  **/
412 
414 {
415  //Successful processing
416  return NO_ERROR;
417 }
uint8_t message[]
Definition: chap.h:154
unsigned int uint_t
Definition: compiler_port.h:50
#define PRIuSIZE
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_MESSAGE
Definition: error.h:105
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define ETH_MTU
Definition: ethernet.h:116
uint8_t data[]
Definition: ethernet.h:222
#define ETH_MAX_FRAME_SIZE
Definition: ethernet.h:110
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
#define netEvent
Definition: net_legacy.h:196
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
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:674
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:101
#define NetRxAncillary
Definition: net_misc.h:40
#define NetTxAncillary
Definition: net_misc.h:36
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:391
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:548
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
#define osMemset(p, value, length)
Definition: os_port.h:135
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define MIN(a, b)
Definition: os_port.h:63
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
RndisContext rndisContext
Definition: rndis.c:54
RNDIS (Remote Network Driver Interface Specification)
#define RNDIS_PACKET_MSG
Definition: rndis.h:56
error_t rndisDumpMsg(const RndisMsg *message, size_t length)
Dump RNDIS message for debugging purpose.
Definition: rndis_debug.c:124
RNDIS (Remote Network Driver Interface Specification)
NetInterface * rndisDriverInterface
Definition: rndis_driver.c:44
void rndisDriverDisableIrq(NetInterface *interface)
Disable interrupts.
Definition: rndis_driver.c:151
error_t rndisDriverSetMulticastFilter(NetInterface *interface)
Configure multicast MAC address filtering.
Definition: rndis_driver.c:413
uint_t rndisRxReadIndex
Definition: rndis_driver.c:54
error_t rndisDriverInit(NetInterface *interface)
RNDIS driver initialization.
Definition: rndis_driver.c:88
void rndisDriverEnableIrq(NetInterface *interface)
Enable interrupts.
Definition: rndis_driver.c:139
uint_t rndisTxReadIndex
Definition: rndis_driver.c:52
RndisRxBufferDesc rndisRxBuffer[RNDIS_RX_BUFFER_COUNT]
Definition: rndis_driver.c:48
error_t rndisDriverSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
Definition: rndis_driver.c:227
void rndisDriverTick(NetInterface *interface)
RNDIS driver timer handler.
Definition: rndis_driver.c:128
void rndisDriverEventHandler(NetInterface *interface)
RNDIS driver event handler.
Definition: rndis_driver.c:163
uint_t rndisTxWriteIndex
Definition: rndis_driver.c:51
error_t rndisDriverReceivePacket(NetInterface *interface, uint8_t *buffer, size_t size, size_t *length)
Receive a packet.
Definition: rndis_driver.c:329
uint_t rndisRxWriteIndex
Definition: rndis_driver.c:53
const NicDriver rndisDriver
RNDIS driver.
Definition: rndis_driver.c:61
RndisTxBufferDesc rndisTxBuffer[RNDIS_TX_BUFFER_COUNT]
Definition: rndis_driver.c:47
RNDIS driver.
#define RNDIS_TX_BUFFER_SIZE
Definition: rndis_driver.h:46
#define RNDIS_RX_BUFFER_COUNT
Definition: rndis_driver.h:53
#define RNDIS_TX_BUFFER_COUNT
Definition: rndis_driver.h:39
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
NIC driver.
Definition: nic.h:283
bool_t txState
Definition: rndis.h:470
bool_t rxState
Definition: rndis.h:471
bool_t linkState
Definition: rndis.h:469
bool_t linkEvent
Definition: rndis.h:468
uint8_t rxBuffer[RNDIS_MAX_TRANSFER_SIZE]
Definition: rndis.h:473
Generic RNDIS message.
Definition: rndis.h:209
RNDIS Packet message.
Definition: rndis.h:408
RX buffer descriptor.
Definition: rndis_driver.h:83
TX buffer descriptor.
Definition: rndis_driver.h:71
uint8_t length
Definition: tcp.h:368
USB RNDIS class.
USBD_HandleTypeDef USBD_Device
#define RNDIS_DATA_IN_EP_MPS_FS
Definition: usbd_rndis.h:44
#define RNDIS_DATA_IN_EP
Definition: usbd_rndis.h:39
#define RNDIS_DATA_OUT_EP_MPS_FS
Definition: usbd_rndis.h:45
#define RNDIS_DATA_OUT_EP
Definition: usbd_rndis.h:40