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