cancel
Showing results for 
Search instead for 
Did you mean: 

RNDIS USB device help

greg239955_stm1
Associate II
Posted on November 08, 2015 at 11:04

I'm trying to get port the code athttps://github.com/fetisov/lrndis/tree/master/lrndis/rndis-stm32 over to the Cube firmware libs, but running into troubles.

Using STM32F429 Eval board, Keil uVision, Cube F4 V1.9.0 (also tried earlier version.) Its works fine right up until I try to send Ethernet data back to the PC on the bulk endpoint. As soon as I send, the foreground execution stops and it gets stuck repeatedly firing the USB interrupt. USB logging on the PC shows that data on that endpoint never arrives. Here's some of the code:

#define RNDIS_NOTIFICATION_IN_EP 0x81
#define RNDIS_DATA_IN_EP 0x82
#define RNDIS_DATA_OUT_EP 0x03
#define RNDIS_NOTIFICATION_IN_SZ 0x08
#define RNDIS_DATA_IN_SZ 0x40
#define RNDIS_DATA_OUT_SZ 0x40
/* USB RNDIS device Configuration Descriptor */
static uint8_t USBD_RNDIS_CfgDesc[USB_RNDIS_CONFIG_DESC_SIZ] =
{
// RNDIS requires only one configuration as follows..
9, // bLength = 9 bytes.
USB_DESC_TYPE_CONFIGURATION, // bDescriptorType = CONFIGURATION
USB_RNDIS_CONFIG_DESC_SIZ, 0x00, // wTotalLength = From offset 18 to end <---
0x02, // bNumInterfaces = 2 (RNDIS spec).
0x01, // bConfValue = 1
0x00, // iConfiguration = unused.
0x40, // bmAttributes = Self-Powered.
0x01, // MaxPower = x2mA
// Communication Class INTERFACE descriptor
9, // bLength = 9 bytes.
USB_DESC_TYPE_INTERFACE, // bDescriptorType = INTERFACE
0x00, // bInterfaceNo = 0
0x00, // bAlternateSet = 0
0x01, // bNumEndPoints = 1 (RNDIS spec)
0x02, // bInterfaceClass = Comm if class (RNDIS spec)
0x02, // bIfSubClass = Comm if sub
0xff, // bIfProtocol = Vendor specific
0x00, // iInterface = unused
// Functional Descriptors for Communication Class Interface per RNDIS spec.
// Header Functional Descriptor
0x05, // bFunctionLength
0x24, // bDescriptorType = CS Interface
0x00, // bDescriptorSubtype
0x10, // bcdCDC = 1.10
0x01, // bcdCDC = 1.10
// Call Management Functional Descriptor
0x05, // bFunctionLength
0x24, // bDescriptorType = CS Interface
0x01, // bDescriptorSubtype = Call Management
0x00, // bmCapabilities
0x01, // bDataInterface
// Abstract Control Management Functional Descriptor
0x04, // bFunctionLength
0x24, // bDescriptorType = CS Interface
0x02, // bDescriptorSubtype = Abstract Control Management
0x00, // bmCapabilities = Requests/notifications not supported
// Union Functional Descriptor
0x05, // bFunctionLength
0x24, // bDescriptorType = CS Interface
0x06, // bDescriptorSubtype = Union
0x00, // bControlInterface = ''RNDIS Communications Control''
0x01, // bSubordinateInterface0 = ''RNDIS Ethernet Data''
// Endpoint descriptors for Communication Class Interface
7, // bLength = 7 bytes
USB_DESC_TYPE_ENDPOINT, // bDescriptorType = ENDPOINT
RNDIS_NOTIFICATION_IN_EP, // bEndpointAddr = IN - EP3
0x03, // bmAttributes = Interrupt endpoint
8, 0, // wMaxPacketSize
80, // bInterval = 1 ms polling from host
// Data Class INTERFACE descriptor
9, // bLength = 9 bytes
USB_DESC_TYPE_INTERFACE, // bDescriptorType = INTERFACE
0x01, // bInterfaceNo = 1
0x00, // bAlternateSet = 0
0x02, // bNumEndPoints = 2 (RNDIS spec)
0x0A, // bInterfaceClass = Data if class (RNDIS spec)
0x00, // bIfSubClass = unused
0x00, // bIfProtocol = unused
0x00, // iInterface = unused
// Endpoint descriptors for Data Class Interface 
7, // bLength = 7 bytes.
USB_DESC_TYPE_ENDPOINT, // bDescriptorType = ENDPOINT [IN]
RNDIS_DATA_IN_EP, // bEndpointAddr = IN EP
0x02, // bmAttributes = BULK
RNDIS_DATA_IN_SZ, 0, // wMaxPacketSize
0, // bInterval = ignored for BULK.
7, // bLength = 7 bytes.
USB_DESC_TYPE_ENDPOINT, // bDescriptorType = ENDPOINT [OUT]
RNDIS_DATA_OUT_EP, // bEndpointAddr = OUT EP
0x02, // bmAttributes = BULK
RNDIS_DATA_OUT_SZ, 0, // wMaxPacketSize
0 // bInterval = ignored for BULK
};
/**
* @brief USBD_RNDIS_Init
* Initialize the RNDIS interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_RNDIS_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
RNDIS_DEBUG_OUT(''RNDIS Init\n'');
// open data end points
USBD_LL_OpenEP(pdev, RNDIS_DATA_IN_EP, USBD_EP_TYPE_BULK, RNDIS_DATA_IN_SZ);
USBD_LL_OpenEP(pdev, RNDIS_DATA_OUT_EP, USBD_EP_TYPE_BULK, RNDIS_DATA_OUT_SZ);
// open control end point
USBD_LL_OpenEP(pdev, RNDIS_NOTIFICATION_IN_EP, USBD_EP_TYPE_INTR, RNDIS_NOTIFICATION_IN_SZ);
USBD_LL_PrepareReceive(pdev, RNDIS_DATA_OUT_EP, (uint8_t*)usb_rx_buffer, RNDIS_DATA_OUT_SZ);
return USBD_OK;
}
__ALIGN_BEGIN static uint8_t RNDIS_SendBuff[ETH_MTU + sizeof(rndis_data_packet_t)] __ALIGN_END;
static inline uint8_t usbd_cdc_transfer(void *pdev, uint8_t *data, uint16_t size)
{ 
rndis_data_packet_t *hdr;
RNDIS_DEBUG_OUT(''RNDIS cdc transfer start\n'');
rndis_sending = 1;
// build header
hdr = (rndis_data_packet_t *)RNDIS_SendBuff;
memset(hdr, 0, sizeof(rndis_data_packet_t));
hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
hdr->MessageLength = sizeof(rndis_data_packet_t) + size;
hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset);
hdr->DataLength = size;
// add payload
memcpy(RNDIS_SendBuff + sizeof(rndis_data_packet_t), data, size);
USBD_LL_Transmit(pdev, RNDIS_DATA_IN_EP, RNDIS_SendBuff, sizeof(rndis_data_packet_t) + size);
RNDIS_DEBUG_OUT(''RNDIS cdc transfer end\n'');
return USBD_OK;
}

usbd_cdc_transfer() I initially was calling from the foreground, but then switched to calling it from a timer interrupt (like the CDC example.) Both had the same problem. Can anyone help out with what is wrong with the RNDIS_DATA_IN_EP endpoint? Thanks. #rndis #usb-device
5 REPLIES 5
greg239955_stm1
Associate II
Posted on November 09, 2015 at 02:08

Finally found the cause.

I'd based it off the CDC sample, which sets the TX Fifo sizes like this:

  HAL_PCDEx_SetTxFiFo(&hpcd, 0, 0x80);

  HAL_PCDEx_SetTxFiFo(&hpcd, 1, 0x174); 

This sets the fifo size for end points 0 and 1, but it leaves endpoint 2 with a Fifo size of 0.

Endpoint 2 for the CDC sample is the control channel, which doesn't normally send anything back.

In my case, endpoint 1 is the RNDIS control channel (used) and endpoint 2 is the data channel (also used.)

The code was getting stuck waiting for enough TX Fifo size to be available (which was stuck at 0.)

Simple fix:

  HAL_PCD_SetTxFiFo(&hpcd_USB_OTG_HS, 0, 0x40);

  HAL_PCD_SetTxFiFo(&hpcd_USB_OTG_HS, 1, 0x80);

  HAL_PCD_SetTxFiFo(&hpcd_USB_OTG_HS, 2, 0x80);

thorsten
Associate II
Posted on December 16, 2015 at 03:01

Hi,

have you had success with the port ? Could you be so kind and share it ?

Best, Thorsten

YILDIRIM.Alper
Associate
Posted on December 31, 2015 at 13:35

Hello Greg,

I checked the original project by Sergey Fetisov. Since he used relatively old STD Peripheral Libs with old USB API's, some porting effort is needed to support HAL Drivers and new USB Device API's. Looks like you accomplished that job.

It will be really helpful if you can share your project with us.

Regards

Alper

cipher
Associate II
Posted on January 23, 2016 at 19:15

Can you please share the HAL port of the RNDIS driver? Would really appreciate it

Shail Shah
Associate II
Posted on April 12, 2017 at 09:18

  • Hi all,

    we are facing problem in RNDIS USB Class implementation for STM32 Nucleo 144pin. We have reference code but still not able to use USB OTG Library for RNIDS Class. Kindly explain function flow and necessary files required for USB.

    Thanks and Regards,

    Shail Shah