MCUXpresso_MIMXRT1052xxxxB/middleware/lwip/port/usb_ethernetif_bm.c
Yilin Sun 6baf4427ce
Updated to v2.15.000
Signed-off-by: Yilin Sun <imi415@imi.moe>
2024-03-18 23:15:10 +08:00

822 lines
32 KiB
C

/*
* Copyright 2018,2020,2022 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"
#include "lwip/ethip6.h"
#include "netif/etharp.h"
#include "netif/ppp/pppoe.h"
#include "lwip/igmp.h"
#include "lwip/mld6.h"
#if USE_RTOS && defined(SDK_OS_FREE_RTOS)
#include "FreeRTOS.h"
#include "event_groups.h"
#endif
#include "usb_host_config.h"
#include "usb_host.h"
#include "usb_host_cdc_rndis.h"
#include "usb_host_cdc.h"
#include "board.h"
#include "usb_ethernetif.h"
#include "board.h"
#if ((!USB_HOST_CONFIG_KHCI) && (!USB_HOST_CONFIG_EHCI) && (!USB_HOST_CONFIG_OHCI) && (!USB_HOST_CONFIG_IP3516HS))
#error Please enable USB_HOST_CONFIG_KHCI, USB_HOST_CONFIG_EHCI, USB_HOST_CONFIG_OHCI, or USB_HOST_CONFIG_IP3516HS in file usb_host_config.
#endif
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
extern void USB_HostClockInit(void);
extern void USB_HostIsrEnable(void);
extern void USB_HostTaskFn(void *param);
/*******************************************************************************
* Variables
******************************************************************************/
#define IFNAME0 'N'
#define IFNAME1 'X'
/*each g_RndisInstance should have its own's buffer*/
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) uint8_t g_SendMessage[RNDIS_CONTROL_MESSAGE];
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) uint8_t g_GetMessage[RNDIS_CONTROL_MESSAGE];
/*used for send/recv data from/to device rndis, the message length should be the sum of max frame packet size and usb rndis header*/
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) uint8_t g_OutPutBuffer[RNDIS_DATA_MESSAGE];
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) uint8_t g_InPutBuffer[RNDIS_DATA_MESSAGE];
usb_host_rndis_instance_struct_t g_RndisInstance = {0};
usb_host_handle g_HostHandle;
/*******************************************************************************
* Code
******************************************************************************/
/*!
* @brief host cdc data transfer callback.
*
* This function is used as callback function for bulk in transfer .
*
* @param param the host cdc instance pointer.
* @param data data buffer pointer.
* @param dataLength data length.
* @status transfer result status.
*/
void USB_HostCdcRndisDataInCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status)
{
usb_host_rndis_instance_struct_t * rndisInstance = (usb_host_rndis_instance_struct_t *)param;
struct netif *netif = (struct netif *)rndisInstance->netif;
if (status != kStatus_USB_Success)
{
if (status == kStatus_USB_TransferCancel)
{
/*usb_echo("cdc transfer cancel\r\n");*/
}
else
{
/**usb_echo("cdc in transfer retry\r\n");*/
}
rndisInstance->runState = kUSB_HostCdcRndisRunDataReceive;
}
else
{
struct pbuf *pbuf;
if((dataLength > 0) && (NULL != data))
{
rndis_packet_msg_struct_t *temp = (rndis_packet_msg_struct_t *)data;
pbuf= pbuf_alloc(PBUF_RAW, temp->dataLength, PBUF_POOL);
if (pbuf)
{
temp->dataBuffer[temp->dataLength] = 0;
pbuf->tot_len = temp->dataLength;
pbuf->len = temp->dataLength;
uint8_t *p = (uint8_t*)(&temp->dataOffset);
memcpy(pbuf->payload, (p + temp->dataOffset), temp->dataLength);
/*in special case, when polling out packet, in packet maybe finihsed, the in packet will be not be handled*/
if (!rndisInstance->pollingInSending)
{
netif->input(pbuf, netif);
}
}
}
rndisInstance->runState = kUSB_HostCdcRndisRunDataReceive;
}
return;
}
/*!
* @brief host cdc data transfer callback.
*
* This function is used as callback function for bulk out transfer .
*
* @param param the host cdc instance pointer.
* @param data data buffer pointer.
* @param dataLength data length.
* @status transfer result status.
*/
void USB_HostCdcRndisDataOutCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status)
{
usb_host_rndis_instance_struct_t *rndisInstance = (usb_host_rndis_instance_struct_t *)param;
if (status != kStatus_USB_Success)
{
if (status == kStatus_USB_TransferCancel)
{
usb_echo("cdc transfer cancel\r\n");
}
else
{
/*usb_echo("cdc out transfer error\r\n");*/
}
}
rndisInstance->dataSend = 0U;
return;
}
err_t USB_EthernetIfOutPut(struct netif *netif, struct pbuf *p)
{
err_t status;
usb_host_rndis_instance_struct_t * rndisInstance = (usb_host_rndis_instance_struct_t *)netif->state;
status = ERR_OK;
if (rndisInstance->attach)
{
if(p->tot_len == p->len)
{
uint32_t total;
total = p->tot_len;
uint32_t transferDone = 0;
while (total)
{
rndisInstance->pollingInSending = 1;
if(rndisInstance->dataSend)
{
/*discard current data if send flag is not cleared*/
return ERR_BUF;
}
rndisInstance->pollingInSending = 0;
rndisInstance->dataSend = 1;
if(total <= RNDIS_FRAME_MAX_FRAMELEN)
{
USB_HostRndisSendDataMsg(rndisInstance->classHandle, rndisInstance->outPutBuffer, RNDIS_FRAME_MAX_FRAMELEN, 0, 0, 0, 0, 0, ((uint8_t*)p->payload + transferDone),total,
USB_HostCdcRndisDataOutCallback, rndisInstance);
transferDone += total;
total = 0U;
}
else
{
USB_HostRndisSendDataMsg(rndisInstance->classHandle, rndisInstance->outPutBuffer, RNDIS_FRAME_MAX_FRAMELEN, 0, 0, 0, 0, 0, ((uint8_t*)p->payload + transferDone),RNDIS_FRAME_MAX_FRAMELEN,
USB_HostCdcRndisDataOutCallback, rndisInstance);
transferDone += RNDIS_FRAME_MAX_FRAMELEN;
total -= RNDIS_FRAME_MAX_FRAMELEN;
}
}
}
else
{
if (p->tot_len < RNDIS_FRAME_MAX_FRAMELEN)
{
u16_t uCopied = pbuf_copy_partial(p, rndisInstance->outPutBuffer, p->tot_len, 0);
LWIP_ASSERT("uCopied != p->tot_len", uCopied == p->tot_len);
rndisInstance->pollingInSending = 1;
while(rndisInstance->dataSend)
{
USB_HostTaskFn(g_HostHandle);
}
rndisInstance->pollingInSending = 0;
USB_HostRndisSendDataMsg(rndisInstance->classHandle, rndisInstance->outPutBuffer, RNDIS_FRAME_MAX_FRAMELEN, 0, 0, 0, 0, 0, ((uint8_t*)&g_OutPutBuffer[0]),p->tot_len,
USB_HostCdcRndisDataOutCallback, rndisInstance);
}
else
{
/*TO DO*/
return ERR_BUF;
}
}
}
else
{
status = ERR_CONN;
usb_echo("USB Rndis device is not attached\r\n");
}
return status;
}
/*!
* @brief host callback function.
*
* device attach/detach callback function.
*
* @param deviceHandle device handle.
* @param configurationHandle attached device's configuration descriptor information.
* @param event_code callback event code, please reference to enumeration host_event_t.
*
* @retval kStatus_USB_Success The host is initialized successfully.
* @retval kStatus_USB_NotSupported The application don't support the configuration.
*/
usb_status_t USB_HostEvent(usb_device_handle deviceHandle,
usb_host_configuration_handle configurationHandle,
uint32_t event_code)
{
usb_status_t status;
status = kStatus_USB_Success;
switch (event_code)
{
case kUSB_HostEventAttach:
status = USB_HostCdcRndisEvent(deviceHandle, configurationHandle, event_code);
break;
case kUSB_HostEventNotSupported:
status = USB_HostCdcRndisEvent(deviceHandle, configurationHandle, event_code);
usb_echo("device not supported.\r\n");
break;
case kUSB_HostEventEnumerationDone:
status = USB_HostCdcRndisEvent(deviceHandle, configurationHandle, event_code);
break;
case kUSB_HostEventDetach:
status = USB_HostCdcRndisEvent(deviceHandle, configurationHandle, event_code);
break;
default:
break;
}
return status;
}
static void USB_HostApplicationInit(uint8_t controllerId, struct netif *netif)
{
usb_status_t status = kStatus_USB_Success;
USB_HostClockInit();
status = USB_HostInit(controllerId, &g_HostHandle, USB_HostEvent);
if (status != kStatus_USB_Success)
{
usb_echo("host init error\r\n");
return;
}
USB_HostIsrEnable();
usb_echo(" host init.\r\n");
netif->state = (void *)&g_RndisInstance;
g_RndisInstance.netif = (void*)netif;
g_RndisInstance.hostHandle = g_HostHandle;
g_RndisInstance.sendMessage = &g_SendMessage[0];
g_RndisInstance.getMessage = &g_GetMessage[0];
g_RndisInstance.outPutBuffer = &g_OutPutBuffer[0];
g_RndisInstance.inPutBuffer = &g_InPutBuffer[0];
while (!g_RndisInstance.attach)
{
USB_HostTaskFn(g_RndisInstance.hostHandle);
USB_HosCdcRndisTask(&g_RndisInstance);
}
}
err_t USB_EthernetIfInIt(struct netif *netif)
{
err_t status;
status = ERR_IF;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
#if LWIP_IPV4
netif->output = etharp_output;
#endif
netif->linkoutput = USB_EthernetIfOutPut;
/* set MAC hardware address length */
netif->hwaddr_len = ETH_HWADDR_LEN;
ethernetifConfig_t *config;
if(netif->state)
{
config = (ethernetifConfig_t *)netif->state;
USB_HostApplicationInit(config->controllerId, netif);
/*USB enet card is ready*/
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
status = ERR_OK;
}
return status;
}
/*!
* @brief host cdc interrupt transfer callback.
*
* This function is used as callback function for interrupt transfer . Interrupt transfer is used to implement
* asynchronous notification of UART status as pstn sepc. This callback suppose the device will return SerialState
* notification. If there is need to suppose other notification ,please refer pstn spec 6.5 and cdc spec6.3.
* @param param the host cdc instance pointer.
* @param data data buffer pointer.
* @param dataLength data length.
* @status transfer result status.
*/
void USB_HostCdcRndisInterruptCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status)
{
/*usb_host_cdc_acm_state_struct_t *state = (usb_host_cdc_acm_state_struct_t *)data;*/
usb_host_rndis_instance_struct_t *rndisInstance = (usb_host_rndis_instance_struct_t *)param;
if (status != kStatus_USB_Success)
{
if (status == kStatus_USB_TransferCancel)
{
usb_echo("cdc transfer cancel\r\n");
}
else
{
usb_echo("cdc control transfer error\r\n");
}
}
else
{ /*more information about SerialState ,please pstn spec 6.5.4 */
/* usb_echo("get serial state value = %d\r\n", state->bmstate);*/
rndisInstance->responseAvailable = 1;
rndisInstance->interruptRunState = kUSB_HostCdcRndisRunInterruptRecvDone;
}
}
/*!
* @brief host cdc rndis control transfer callback.
*
* This function is used as callback function for control transfer .
*
* @param param the host cdc rndis instance pointer.
* @param data data buffer pointer.
* @param dataLength data length.
* @status transfer result status.
*/
void USB_HostCdcRndisControlCallback(void *param, uint8_t *data, uint32_t dataLength, usb_status_t status)
{
usb_host_rndis_instance_struct_t *rndisInstance = (usb_host_rndis_instance_struct_t *)param;
struct netif *netif = (struct netif *)rndisInstance->netif;
if (status != kStatus_USB_Success)
{
usb_echo("data transfer error = %d\r\n",status);
return;
}
if (rndisInstance->runWaitState == kUSB_HostCdcRndisRunWaitSetControlInterface)
{
rndisInstance->runState = kUSB_HostCdcRndisRunSetControlInterfaceDone;
}
else if (rndisInstance->runWaitState == kUSB_HostCdcRndisRunWaitSetDataInterface)
{
rndisInstance->runState = kUSB_HostCdcRndisRunSetDataInterfaceDone;
}
else if (rndisInstance->runWaitState == kUSB_HostCdcRndisRunWaitInitMsg)
{
rndisInstance->runState = kUSB_HostCdcRndisRunWaitInitMsgDone;
}
else if (rndisInstance->runWaitState == kUSB_HostCdcRndisRunWaitMaxmumFrame)
{
rndisInstance->runState = kUSB_HostCdcRndisRunWaitMaxmumFrameDone;
}
else if (rndisInstance->runWaitState == kUSB_HostCdcRndisRunWaitGetMACAddress)
{
rndisInstance->runState = kUSB_HostCdcRndisRunWaitGetMACAddressDone;
}
else if (rndisInstance->runWaitState == kUSB_HostCdcRndisRunWaitSetMsg)
{
rndisInstance->runState = kUSB_HostCdcRndisRunWaitSetMsgDone;
}
else if (rndisInstance->runWaitState == kUSB_HostCdcRndisRunWaitGetEncapsulatedCommand)
{
rndisInstance->runState = kUSB_HostCdcRndisRunGetEncapsulatedResponseDone;
if (rndisInstance->previousRunState == kUSB_HostCdcRndisRunWaitInitMsgDone)
{
rndisInstance->runState = kUSB_HostCdcRndisRunWaitMaxmumFrame;
}
else if (rndisInstance->previousRunState == kUSB_HostCdcRndisRunWaitMaxmumFrameDone)
{
rndisInstance->runState = kUSB_HostCdcRndisRunWaitGetMACAddress;
rndis_query_cmplt_struct_t * msg = (rndis_query_cmplt_struct_t *)data;
if(REMOTE_NDIS_QUERY_CMPLT == msg->messageType)
{
netif->mtu = USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(((uint8_t*)&msg->requestID + msg->informationBufferOffset));
}
else
{
/*set default value if device doesn't send query complete message*/
netif->mtu = 1500U;
}
}
else if (rndisInstance->previousRunState == kUSB_HostCdcRndisRunWaitGetMACAddressDone)
{
rndisInstance->runState = kUSB_HostCdcRndisRunWaitSetMsg;
rndis_query_cmplt_struct_t * msg = (rndis_query_cmplt_struct_t *)data;
netif->hwaddr_len = NETIF_MAX_HWADDR_LEN;
memcpy(netif->hwaddr,(((uint8_t*)&msg->requestID + msg->informationBufferOffset)), NETIF_MAX_HWADDR_LEN);
}
else if (rndisInstance->previousRunState == kUSB_HostCdcRndisRunWaitSetMsgDone)
{
rndisInstance->runState = kUSB_HostCdcRndisRunGetState;
}
rndisInstance->previousRunState = kUSB_HostCdcRndisRunIdle;
}
else
{
}
}
/*!
* @brief host rndis task function.
*
* This function implements the host cdc action, it is used to create task.
*
* @param param the host rndis instance pointer.
*/
void USB_HosCdcRndisTask(void *param)
{
usb_status_t status = kStatus_USB_Success;
usb_host_rndis_instance_struct_t *rndisInstance = (usb_host_rndis_instance_struct_t *)param;
uint32_t filtertype;
struct netif *netif ;
/* device state changes */
if (rndisInstance->deviceState != rndisInstance->previousState)
{
rndisInstance->previousState = rndisInstance->deviceState;
switch (rndisInstance->deviceState)
{
case kStatus_DEV_Idle:
break;
case kStatus_DEV_Attached:
rndisInstance->runState = kUSB_HostCdcRndisRunSetControlInterface;
status = USB_HostCdcInit(rndisInstance->deviceHandle, &rndisInstance->classHandle);
usb_echo("rndis device attached\r\n");
break;
case kStatus_DEV_Detached:
rndisInstance->deviceState = kStatus_DEV_Idle;
rndisInstance->runState = kUSB_HostCdcRndisRunIdle;
USB_HostCdcDeinit(rndisInstance->deviceHandle, rndisInstance->classHandle);
rndisInstance->dataInterfaceHandle = NULL;
rndisInstance->classHandle = NULL;
rndisInstance->controlInterfaceHandle = NULL;
rndisInstance->deviceHandle = NULL;
rndisInstance->interruptRunState = kUSB_HostCdcRndisRunIdle;
usb_echo("rndis device detached\r\n");
break;
default:
break;
}
}
/* run state */
switch (rndisInstance->runState)
{
case kUSB_HostCdcRndisRunIdle:
break;
case kUSB_HostCdcRndisRunSetControlInterface:
rndisInstance->runWaitState = kUSB_HostCdcRndisRunWaitSetControlInterface;
rndisInstance->runState = kUSB_HostCdcRndisRunIdle;
if (USB_HostCdcSetControlInterface(rndisInstance->classHandle, rndisInstance->controlInterfaceHandle, 0,
USB_HostCdcRndisControlCallback, rndisInstance) != kStatus_USB_Success)
{
usb_echo("set control interface error\r\n");
}
break;
case kUSB_HostCdcRndisRunSetControlInterfaceDone:
rndisInstance->runWaitState = kUSB_HostCdcRndisRunWaitSetDataInterface;
rndisInstance->runState = kUSB_HostCdcRndisRunIdle;
if (USB_HostCdcSetDataInterface(rndisInstance->classHandle, rndisInstance->dataInterfaceHandle, 0,
USB_HostCdcRndisControlCallback,rndisInstance) != kStatus_USB_Success)
{
usb_echo("set data interface error\r\n");
}
break;
case kUSB_HostCdcRndisRunSetDataInterfaceDone:
rndisInstance->runWaitState = kUSB_HostCdcRndisRunWaitInitMsg;
rndisInstance->runState = kUSB_HostCdcRndisRunIdle;
if(USB_HostRndisInitMsg(rndisInstance->classHandle,rndisInstance->sendMessage, RNDIS_CONTROL_MESSAGE,
USB_HostCdcRndisControlCallback, rndisInstance))
{
usb_echo("Error in Init message\r\n");
}
break;
case kUSB_HostCdcRndisRunWaitInitMsgDone:
if (rndisInstance->interruptRunState == kUSB_HostCdcRndisRunIdle)
{
rndisInstance->interruptRunState = kUSB_HostCdcRndisRunInterruptRecvPrime;
if (USB_HostCdcInterruptRecv(rndisInstance->classHandle, (uint8_t *)&rndisInstance->state,
RNDIS_RESPONSE_AVAILABLE, USB_HostCdcRndisInterruptCallback,
rndisInstance) != kStatus_USB_Success)
{
usb_echo("Error in USB_HostCdcInterruptRecv: %x\r\n", status);
}
}
else if (rndisInstance->interruptRunState == kUSB_HostCdcRndisRunInterruptRecvDone)
{
rndisInstance->interruptRunState = kUSB_HostCdcRndisRunIdle;
/*remember the previous set encapsulated command*/
rndisInstance->previousRunState = kUSB_HostCdcRndisRunWaitInitMsgDone;
rndisInstance->runWaitState = kUSB_HostCdcRndisRunWaitGetEncapsulatedCommand;
rndisInstance->runState = kUSB_HostCdcRndisRunIdle;
if(USB_HostCdcGetEncapsulatedResponse(rndisInstance->classHandle, rndisInstance->getMessage,
RNDIS_CONTROL_MESSAGE, USB_HostCdcRndisControlCallback, rndisInstance))
{
usb_echo("Error in Init message\r\n");
}
}
break;
case kUSB_HostCdcRndisRunWaitMaxmumFrame:
rndisInstance->previousRunState = kUSB_HostCdcRndisRunWaitMaxmumFrame;
rndisInstance->runWaitState = kUSB_HostCdcRndisRunWaitMaxmumFrame;
rndisInstance->runState = kUSB_HostCdcRndisRunIdle;
if(USB_HostRndisQueryMsg(rndisInstance->classHandle, OID_GEN_MAXIMUM_FRAME_SIZE, rndisInstance->sendMessage,
RNDIS_CONTROL_MESSAGE, 0, 0, NULL, USB_HostCdcRndisControlCallback, rndisInstance))
{
usb_echo("Error in Init message\r\n");
}
break;
case kUSB_HostCdcRndisRunWaitMaxmumFrameDone:
if (rndisInstance->interruptRunState == kUSB_HostCdcRndisRunIdle)
{
rndisInstance->interruptRunState = kUSB_HostCdcRndisRunInterruptRecvPrime;
if (USB_HostCdcInterruptRecv(rndisInstance->classHandle, (uint8_t *)&rndisInstance->state,
RNDIS_RESPONSE_AVAILABLE, USB_HostCdcRndisInterruptCallback,
rndisInstance) != kStatus_USB_Success)
{
usb_echo("Error in USB_HostCdcInterruptRecv: %x\r\n", status);
}
}
else if (rndisInstance->interruptRunState == kUSB_HostCdcRndisRunInterruptRecvDone)
{
rndisInstance->interruptRunState = kUSB_HostCdcRndisRunIdle;
rndisInstance->previousRunState = kUSB_HostCdcRndisRunWaitMaxmumFrameDone;
rndisInstance->runWaitState = kUSB_HostCdcRndisRunWaitGetEncapsulatedCommand;
rndisInstance->runState = kUSB_HostCdcRndisRunIdle;
if(USB_HostCdcGetEncapsulatedResponse(rndisInstance->classHandle, rndisInstance->getMessage,
RNDIS_CONTROL_MESSAGE, USB_HostCdcRndisControlCallback, rndisInstance))
{
usb_echo("Error in Init message\r\n");
}
}
break;
case kUSB_HostCdcRndisRunWaitGetMACAddress:
rndisInstance->previousRunState = kUSB_HostCdcRndisRunWaitGetMACAddress;
rndisInstance->runWaitState = kUSB_HostCdcRndisRunWaitGetMACAddress;
rndisInstance->runState = kUSB_HostCdcRndisRunIdle;
if(USB_HostRndisQueryMsg(rndisInstance->classHandle, OID_802_3_CURRENT_ADDRESS,rndisInstance->sendMessage,
RNDIS_CONTROL_MESSAGE, 0, 0, NULL, USB_HostCdcRndisControlCallback, rndisInstance))
{
usb_echo("Error in Init message\r\n");
}
break;
case kUSB_HostCdcRndisRunWaitGetMACAddressDone:
if (rndisInstance->interruptRunState == kUSB_HostCdcRndisRunIdle)
{
rndisInstance->interruptRunState = kUSB_HostCdcRndisRunInterruptRecvPrime;
rndisInstance->interruptRunState = kUSB_HostCdcRndisRunInterruptRecvPrime;
if (USB_HostCdcInterruptRecv(rndisInstance->classHandle, (uint8_t *)&rndisInstance->state,
RNDIS_RESPONSE_AVAILABLE, USB_HostCdcRndisInterruptCallback,
rndisInstance) != kStatus_USB_Success)
{
usb_echo("Error in USB_HostCdcInterruptRecv: %x\r\n", status);
}
}
else if (rndisInstance->interruptRunState == kUSB_HostCdcRndisRunInterruptRecvDone)
{
rndisInstance->interruptRunState = kUSB_HostCdcRndisRunIdle;
rndisInstance->responseAvailable = 0;
rndisInstance->previousRunState = kUSB_HostCdcRndisRunWaitGetMACAddressDone;
rndisInstance->runWaitState = kUSB_HostCdcRndisRunWaitGetEncapsulatedCommand;
rndisInstance->runState = kUSB_HostCdcRndisRunIdle;
if(USB_HostCdcGetEncapsulatedResponse(rndisInstance->classHandle, rndisInstance->getMessage,
RNDIS_CONTROL_MESSAGE, USB_HostCdcRndisControlCallback, rndisInstance))
{
usb_echo("Error in Init message\r\n");
}
}
break;
case kUSB_HostCdcRndisRunWaitSetMsg:
rndisInstance->previousRunState = kUSB_HostCdcRndisRunWaitSetMsg;
rndisInstance->runWaitState = kUSB_HostCdcRndisRunWaitSetMsg;
rndisInstance->runState = kUSB_HostCdcRndisRunIdle;
filtertype = NDIS_PACKET_TYPE_DIRECTED;
if(USB_HostRndisSetMsg(rndisInstance->classHandle, OID_GEN_CURRENT_PACKET_FILTER, rndisInstance->sendMessage, RNDIS_CONTROL_MESSAGE, 20U, (sizeof(filtertype)),&filtertype,
USB_HostCdcRndisControlCallback, rndisInstance))
{
usb_echo("Error in set message\r\n");
}
break;
case kUSB_HostCdcRndisRunWaitSetMsgDone:
if (rndisInstance->interruptRunState == kUSB_HostCdcRndisRunIdle)
{
rndisInstance->interruptRunState = kUSB_HostCdcRndisRunInterruptRecvPrime;
rndisInstance->interruptRunState = kUSB_HostCdcRndisRunInterruptRecvPrime;
if (USB_HostCdcInterruptRecv(rndisInstance->classHandle, (uint8_t *)&rndisInstance->state,
RNDIS_RESPONSE_AVAILABLE, USB_HostCdcRndisInterruptCallback,
rndisInstance) != kStatus_USB_Success)
{
usb_echo("Error in USB_HostCdcInterruptRecv: %x\r\n", status);
}
}
else if (rndisInstance->interruptRunState == kUSB_HostCdcRndisRunInterruptRecvDone)
{
rndisInstance->responseAvailable = 0;
rndisInstance->previousRunState = kUSB_HostCdcRndisRunWaitSetMsgDone;
rndisInstance->runWaitState = kUSB_HostCdcRndisRunWaitGetEncapsulatedCommand;
rndisInstance->runState = kUSB_HostCdcRndisRunIdle;
if(USB_HostCdcGetEncapsulatedResponse(rndisInstance->classHandle, rndisInstance->getMessage,
RNDIS_CONTROL_MESSAGE, USB_HostCdcRndisControlCallback, rndisInstance))
{
usb_echo("Error in Init message\r\n");
}
}
break;
case kUSB_HostCdcRndisRunGetState:
rndisInstance->attach = 1;
rndisInstance->dataSend = 0;
netif = (struct netif *)rndisInstance->netif;
netif_set_link_up(netif);
case kUSB_HostCdcRndisRunDataReceive:
rndisInstance->runState = kUSB_HostCdcRndisRunIdle;
USB_HostRndisRecvDataMsg(rndisInstance->classHandle, rndisInstance->inPutBuffer, RNDIS_DATA_MESSAGE,
USB_HostCdcRndisDataInCallback, rndisInstance);
break;
default:
break;
}
}
usb_status_t USB_HostCdcRndisEvent(usb_device_handle deviceHandle,
usb_host_configuration_handle configurationHandle,
uint32_t event_code)
{
usb_status_t status;
uint8_t id;
usb_host_configuration_t *configuration;
uint8_t interface_index;
usb_host_interface_t *hostInterface;
uint32_t info_value = 0U;
struct netif *netif;
status = kStatus_USB_Success;
switch (event_code)
{
case kUSB_HostEventAttach:
/* judge whether is configurationHandle supported */
configuration = (usb_host_configuration_t *)configurationHandle;
for (interface_index = 0; interface_index < configuration->interfaceCount; ++interface_index)
{
hostInterface = &configuration->interfaceList[interface_index];
id = hostInterface->interfaceDesc->bInterfaceClass;
if (id != USB_HOST_CDC_RNDIS_CLASS_CODE)
{
continue;
}
id = hostInterface->interfaceDesc->bInterfaceSubClass;
if (id != USB_HOST_CDC_RNDIS_SUBCLASS_CODE)
{
continue;
}
id = hostInterface->interfaceDesc->bInterfaceProtocol;
if (id != USB_HOST_CDC_RNDIS_PROTOCOL_CODE)
{
continue;
}
else
{
/* the interface is supported by the application */
g_RndisInstance.controlInterfaceHandle = hostInterface;
}
}
for (interface_index = 0; interface_index < configuration->interfaceCount; ++interface_index)
{
hostInterface = &configuration->interfaceList[interface_index];
id = hostInterface->interfaceDesc->bInterfaceClass;
if (id != USB_HOST_CDC_DATA_CLASS_CODE)
{
continue;
}
id = hostInterface->interfaceDesc->bInterfaceSubClass;
if (id != USB_HOST_CDC_DATA_SUBCLASS_CODE)
{
continue;
}
id = hostInterface->interfaceDesc->bInterfaceProtocol;
if (id != USB_HOST_CDC_DATA_PROTOCOL_CODE)
{
continue;
}
else
{
g_RndisInstance.dataInterfaceHandle = hostInterface;
}
}
g_RndisInstance.deviceHandle = deviceHandle;
if ((NULL != g_RndisInstance.dataInterfaceHandle) && (NULL != g_RndisInstance.controlInterfaceHandle))
{
status = kStatus_USB_Success;
}
else
{
status = kStatus_USB_NotSupported;
}
break;
case kUSB_HostEventNotSupported:
usb_echo(" the usb tethering featue is not enabled, please turn on usb tethering in mobile phone\r\n ");
break;
case kUSB_HostEventEnumerationDone:
if (g_RndisInstance.deviceState == kStatus_DEV_Idle)
{
if ((g_RndisInstance.deviceHandle != NULL) && (g_RndisInstance.dataInterfaceHandle != NULL) && (g_RndisInstance.controlInterfaceHandle != NULL))
{
g_RndisInstance.deviceState = kStatus_DEV_Attached;
USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDevicePID, &info_value);
usb_echo("device cdc attached:\r\npid=0x%x", info_value);
USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceVID, &info_value);
usb_echo("vid=0x%x ", info_value);
USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceAddress, &info_value);
usb_echo("address=%d\r\n", info_value);
}
}
else
{
usb_echo("not idle rndis instance\r\n");
}
break;
case kUSB_HostEventDetach:
if (g_RndisInstance.deviceState != kStatus_DEV_Idle)
{
g_RndisInstance.attach = 0;
g_RndisInstance.dataSend = 0;
netif = (struct netif *)g_RndisInstance.netif;
netif_set_link_down(netif);
g_RndisInstance.deviceState = kStatus_DEV_Detached;
}
break;
default:
break;
}
return status;
}
void usb_ethernetif_input(struct netif *netif)
{
usb_host_rndis_instance_struct_t * rndisInstance = (usb_host_rndis_instance_struct_t *)netif->state;
USB_HostTaskFn(rndisInstance->hostHandle);
USB_HosCdcRndisTask(rndisInstance);
}