first
This commit is contained in:
270
rt-thread/components/drivers/usb/cherryusb/class/wireless/ndis.h
Normal file
270
rt-thread/components/drivers/usb/cherryusb/class/wireless/ndis.h
Normal file
@@ -0,0 +1,270 @@
|
||||
/* This file has been prepared for Doxygen automatic documentation generation.*/
|
||||
/*! \file ndis.h ***************************************************************
|
||||
*
|
||||
* \brief
|
||||
* This file contains the possible external configuration of the USB.
|
||||
*
|
||||
* \addtogroup usbstick
|
||||
*
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
\ingroup usbstick
|
||||
\defgroup RNDIS RNDIS Support
|
||||
@{
|
||||
*/
|
||||
|
||||
/*
|
||||
* ndis.h
|
||||
*
|
||||
* Modified by Colin O'Flynn <coflynn@newae.com>
|
||||
* ntddndis.h modified by Benedikt Spranger <b.spranger@pengutronix.de>
|
||||
*
|
||||
* Thanks to the cygwin development team,
|
||||
* espacially to Casper S. Hornstrup <chorns@users.sourceforge.net>
|
||||
*
|
||||
* THIS SOFTWARE IS NOT COPYRIGHTED
|
||||
*
|
||||
* This source code is offered for use in the public domain. You may
|
||||
* use, modify or distribute it freely.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful but
|
||||
* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
|
||||
* DISCLAIMED. This includes but is not limited to warranties of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_NDIS_H
|
||||
#define _LINUX_NDIS_H
|
||||
|
||||
#define NDIS_STATUS_MULTICAST_FULL 0xC0010009
|
||||
#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A
|
||||
#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B
|
||||
|
||||
/* from drivers/net/sk98lin/h/skgepnmi.h */
|
||||
#define OID_PNP_CAPABILITIES 0xFD010100
|
||||
#define OID_PNP_SET_POWER 0xFD010101
|
||||
#define OID_PNP_QUERY_POWER 0xFD010102
|
||||
#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103
|
||||
#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104
|
||||
#define OID_PNP_ENABLE_WAKE_UP 0xFD010106
|
||||
|
||||
enum NDIS_DEVICE_POWER_STATE {
|
||||
NdisDeviceStateUnspecified = 0,
|
||||
NdisDeviceStateD0,
|
||||
NdisDeviceStateD1,
|
||||
NdisDeviceStateD2,
|
||||
NdisDeviceStateD3,
|
||||
NdisDeviceStateMaximum
|
||||
};
|
||||
|
||||
struct NDIS_PM_WAKE_UP_CAPABILITIES {
|
||||
enum NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp;
|
||||
enum NDIS_DEVICE_POWER_STATE MinPatternWakeUp;
|
||||
enum NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp;
|
||||
};
|
||||
|
||||
/* NDIS_PNP_CAPABILITIES.Flags constants */
|
||||
#define NDIS_DEVICE_WAKE_UP_ENABLE 0x00000001
|
||||
#define NDIS_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002
|
||||
#define NDIS_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004
|
||||
|
||||
/*
|
||||
struct NDIS_PNP_CAPABILITIES {
|
||||
__le32 Flags;
|
||||
struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities;
|
||||
};
|
||||
|
||||
struct NDIS_PM_PACKET_PATTERN {
|
||||
__le32 Priority;
|
||||
__le32 Reserved;
|
||||
__le32 MaskSize;
|
||||
__le32 PatternOffset;
|
||||
__le32 PatternSize;
|
||||
__le32 PatternFlags;
|
||||
};
|
||||
*/
|
||||
|
||||
/* Required Object IDs (OIDs) */
|
||||
#define OID_GEN_SUPPORTED_LIST 0x00010101
|
||||
#define OID_GEN_HARDWARE_STATUS 0x00010102
|
||||
#define OID_GEN_MEDIA_SUPPORTED 0x00010103
|
||||
#define OID_GEN_MEDIA_IN_USE 0x00010104
|
||||
#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105
|
||||
#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106
|
||||
#define OID_GEN_LINK_SPEED 0x00010107
|
||||
#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108
|
||||
#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109
|
||||
#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A
|
||||
#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B
|
||||
#define OID_GEN_VENDOR_ID 0x0001010C
|
||||
#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D
|
||||
#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
|
||||
#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F
|
||||
#define OID_GEN_DRIVER_VERSION 0x00010110
|
||||
#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111
|
||||
#define OID_GEN_PROTOCOL_OPTIONS 0x00010112
|
||||
#define OID_GEN_MAC_OPTIONS 0x00010113
|
||||
#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114
|
||||
#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115
|
||||
#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116
|
||||
#define OID_GEN_SUPPORTED_GUIDS 0x00010117
|
||||
#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118
|
||||
#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119
|
||||
#define OID_GEN_MACHINE_NAME 0x0001021A
|
||||
#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B
|
||||
#define OID_GEN_VLAN_ID 0x0001021C
|
||||
|
||||
/* Optional OIDs */
|
||||
#define OID_GEN_MEDIA_CAPABILITIES 0x00010201
|
||||
#define OID_GEN_PHYSICAL_MEDIUM 0x00010202
|
||||
|
||||
/* Required statistics OIDs */
|
||||
#define OID_GEN_XMIT_OK 0x00020101
|
||||
#define OID_GEN_RCV_OK 0x00020102
|
||||
#define OID_GEN_XMIT_ERROR 0x00020103
|
||||
#define OID_GEN_RCV_ERROR 0x00020104
|
||||
#define OID_GEN_RCV_NO_BUFFER 0x00020105
|
||||
|
||||
/* Optional statistics OIDs */
|
||||
#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201
|
||||
#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
|
||||
#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203
|
||||
#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
|
||||
#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205
|
||||
#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
|
||||
#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207
|
||||
#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
|
||||
#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209
|
||||
#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
|
||||
#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B
|
||||
#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
|
||||
#define OID_GEN_RCV_CRC_ERROR 0x0002020D
|
||||
#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E
|
||||
#define OID_GEN_GET_TIME_CAPS 0x0002020F
|
||||
#define OID_GEN_GET_NETCARD_TIME 0x00020210
|
||||
#define OID_GEN_NETCARD_LOAD 0x00020211
|
||||
#define OID_GEN_DEVICE_PROFILE 0x00020212
|
||||
#define OID_GEN_INIT_TIME_MS 0x00020213
|
||||
#define OID_GEN_RESET_COUNTS 0x00020214
|
||||
#define OID_GEN_MEDIA_SENSE_COUNTS 0x00020215
|
||||
#define OID_GEN_FRIENDLY_NAME 0x00020216
|
||||
#define OID_GEN_MINIPORT_INFO 0x00020217
|
||||
#define OID_GEN_RESET_VERIFY_PARAMETERS 0x00020218
|
||||
|
||||
/* IEEE 802.3 (Ethernet) OIDs */
|
||||
#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001
|
||||
|
||||
#define OID_802_3_PERMANENT_ADDRESS 0x01010101
|
||||
#define OID_802_3_CURRENT_ADDRESS 0x01010102
|
||||
#define OID_802_3_MULTICAST_LIST 0x01010103
|
||||
#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104
|
||||
#define OID_802_3_MAC_OPTIONS 0x01010105
|
||||
#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101
|
||||
#define OID_802_3_XMIT_ONE_COLLISION 0x01020102
|
||||
#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103
|
||||
#define OID_802_3_XMIT_DEFERRED 0x01020201
|
||||
#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202
|
||||
#define OID_802_3_RCV_OVERRUN 0x01020203
|
||||
#define OID_802_3_XMIT_UNDERRUN 0x01020204
|
||||
#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205
|
||||
#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
|
||||
#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
|
||||
|
||||
/* Wireless LAN OIDs */
|
||||
/* Mandatory */
|
||||
#define OID_802_11_BSSID 0x0D010101 /* Q S */
|
||||
#define OID_802_11_SSID 0x0D010102 /* Q S */
|
||||
#define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204 /* Q S */
|
||||
#define OID_802_11_RSSI 0x0D010206 /* Q I */
|
||||
#define OID_802_11_BSSID_LIST 0x0D010217 /* Q */
|
||||
#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A /* S */
|
||||
#define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108 /* Q S */
|
||||
#define OID_802_11_SUPPORTED_RATES 0x0D01020E /* Q */
|
||||
#define OID_802_11_CONFIGURATION 0x0D010211 /* Q S */
|
||||
#define OID_802_11_ADD_WEP 0x0D010113 /* S */
|
||||
#define OID_802_11_WEP_STATUS 0x0D01011B /* Q S */
|
||||
#define OID_802_11_REMOVE_WEP 0x0D010114 /* S */
|
||||
#define OID_802_11_DISASSOCIATE 0x0D010115 /* S */
|
||||
#define OID_802_11_AUTHENTICATION_MODE 0x0D010118 /* Q S */
|
||||
#define OID_802_11_RELOAD_DEFAULTS 0x0D01011C /* S */
|
||||
|
||||
/* OID_GEN_MINIPORT_INFO constants */
|
||||
#define NDIS_MINIPORT_BUS_MASTER 0x00000001
|
||||
#define NDIS_MINIPORT_WDM_DRIVER 0x00000002
|
||||
#define NDIS_MINIPORT_SG_LIST 0x00000004
|
||||
#define NDIS_MINIPORT_SUPPORTS_MEDIA_QUERY 0x00000008
|
||||
#define NDIS_MINIPORT_INDICATES_PACKETS 0x00000010
|
||||
#define NDIS_MINIPORT_IGNORE_PACKET_QUEUE 0x00000020
|
||||
#define NDIS_MINIPORT_IGNORE_REQUEST_QUEUE 0x00000040
|
||||
#define NDIS_MINIPORT_IGNORE_TOKEN_RING_ERRORS 0x00000080
|
||||
#define NDIS_MINIPORT_INTERMEDIATE_DRIVER 0x00000100
|
||||
#define NDIS_MINIPORT_IS_NDIS_5 0x00000200
|
||||
#define NDIS_MINIPORT_IS_CO 0x00000400
|
||||
#define NDIS_MINIPORT_DESERIALIZE 0x00000800
|
||||
#define NDIS_MINIPORT_REQUIRES_MEDIA_POLLING 0x00001000
|
||||
#define NDIS_MINIPORT_SUPPORTS_MEDIA_SENSE 0x00002000
|
||||
#define NDIS_MINIPORT_NETBOOT_CARD 0x00004000
|
||||
#define NDIS_MINIPORT_PM_SUPPORTED 0x00008000
|
||||
#define NDIS_MINIPORT_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00010000
|
||||
#define NDIS_MINIPORT_USES_SAFE_BUFFER_APIS 0x00020000
|
||||
#define NDIS_MINIPORT_HIDDEN 0x00040000
|
||||
#define NDIS_MINIPORT_SWENUM 0x00080000
|
||||
#define NDIS_MINIPORT_SURPRISE_REMOVE_OK 0x00100000
|
||||
#define NDIS_MINIPORT_NO_HALT_ON_SUSPEND 0x00200000
|
||||
#define NDIS_MINIPORT_HARDWARE_DEVICE 0x00400000
|
||||
#define NDIS_MINIPORT_SUPPORTS_CANCEL_SEND_PACKETS 0x00800000
|
||||
#define NDIS_MINIPORT_64BITS_DMA 0x01000000
|
||||
|
||||
#define NDIS_MEDIUM_802_3 0x00000000
|
||||
#define NDIS_MEDIUM_802_5 0x00000001
|
||||
#define NDIS_MEDIUM_FDDI 0x00000002
|
||||
#define NDIS_MEDIUM_WAN 0x00000003
|
||||
#define NDIS_MEDIUM_LOCAL_TALK 0x00000004
|
||||
#define NDIS_MEDIUM_DIX 0x00000005
|
||||
#define NDIS_MEDIUM_ARCENT_RAW 0x00000006
|
||||
#define NDIS_MEDIUM_ARCENT_878_2 0x00000007
|
||||
#define NDIS_MEDIUM_ATM 0x00000008
|
||||
#define NDIS_MEDIUM_WIRELESS_LAN 0x00000009
|
||||
#define NDIS_MEDIUM_IRDA 0x0000000A
|
||||
#define NDIS_MEDIUM_BPC 0x0000000B
|
||||
#define NDIS_MEDIUM_CO_WAN 0x0000000C
|
||||
#define NDIS_MEDIUM_1394 0x0000000D
|
||||
|
||||
#define NDIS_PACKET_TYPE_DIRECTED 0x00000001
|
||||
#define NDIS_PACKET_TYPE_MULTICAST 0x00000002
|
||||
#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004
|
||||
#define NDIS_PACKET_TYPE_BROADCAST 0x00000008
|
||||
#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010
|
||||
#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020
|
||||
#define NDIS_PACKET_TYPE_SMT 0x00000040
|
||||
#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080
|
||||
#define NDIS_PACKET_TYPE_GROUP 0x00000100
|
||||
#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200
|
||||
#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400
|
||||
#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800
|
||||
|
||||
#define NDIS_MEDIA_STATE_CONNECTED 0x00000000
|
||||
#define NDIS_MEDIA_STATE_DISCONNECTED 0x00000001
|
||||
|
||||
#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001
|
||||
#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002
|
||||
#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004
|
||||
#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008
|
||||
#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010
|
||||
#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020
|
||||
#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040
|
||||
#define NDIS_MAC_OPTION_RESERVED 0x80000000
|
||||
|
||||
/** Hardware status of the underlying NIC */
|
||||
#define NDIS_HW_STS_READY 0x00000000UL
|
||||
#define NDIS_HW_STS_INITIALIZING 0x00000001UL
|
||||
#define NDIS_HW_STS_RESET 0x00000002UL
|
||||
#define NDIS_HW_STS_CLOSING 0x00000003UL
|
||||
#define NDIS_HW_STS_NOT_READY 0x00000004UL
|
||||
|
||||
#endif /* _LINUX_NDIS_H */
|
||||
|
||||
/** @} */
|
@@ -0,0 +1,302 @@
|
||||
/**
|
||||
* \file rndis_protocol.h
|
||||
* RNDIS Defines
|
||||
*
|
||||
* \author
|
||||
* Colin O'Flynn <coflynn@newae.com>
|
||||
*
|
||||
* \addtogroup usbstick
|
||||
*/
|
||||
|
||||
/* Copyright (c) 2008 Colin O'Flynn
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of the copyright holders nor the names of
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _RNDIS_H
|
||||
#define _RNDIS_H
|
||||
|
||||
/**
|
||||
\addtogroup RNDIS
|
||||
@{
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define RNDIS_MAJOR_VERSION 1
|
||||
#define RNDIS_MINOR_VERSION 0
|
||||
|
||||
#define RNDIS_STATUS_SUCCESS 0X00000000
|
||||
#define RNDIS_STATUS_FAILURE 0XC0000001
|
||||
#define RNDIS_STATUS_INVALID_DATA 0XC0010015
|
||||
#define RNDIS_STATUS_NOT_SUPPORTED 0XC00000BB
|
||||
#define RNDIS_STATUS_MEDIA_CONNECT 0X4001000B
|
||||
#define RNDIS_STATUS_MEDIA_DISCONNECT 0X4001000C
|
||||
|
||||
/* Message set for Connectionless (802.3) Devices */
|
||||
#define REMOTE_NDIS_PACKET_MSG 0x00000001
|
||||
#define REMOTE_NDIS_INITIALIZE_MSG 0X00000002
|
||||
#define REMOTE_NDIS_HALT_MSG 0X00000003
|
||||
#define REMOTE_NDIS_QUERY_MSG 0X00000004
|
||||
#define REMOTE_NDIS_SET_MSG 0X00000005
|
||||
#define REMOTE_NDIS_RESET_MSG 0X00000006
|
||||
#define REMOTE_NDIS_INDICATE_STATUS_MSG 0X00000007
|
||||
#define REMOTE_NDIS_KEEPALIVE_MSG 0X00000008
|
||||
#define REMOTE_NDIS_INITIALIZE_CMPLT 0X80000002
|
||||
#define REMOTE_NDIS_QUERY_CMPLT 0X80000004
|
||||
#define REMOTE_NDIS_SET_CMPLT 0X80000005
|
||||
#define REMOTE_NDIS_RESET_CMPLT 0X80000006
|
||||
#define REMOTE_NDIS_KEEPALIVE_CMPLT 0X80000008
|
||||
|
||||
typedef uint32_t rndis_MessageType_t;
|
||||
typedef uint32_t rndis_MessageLength_t;
|
||||
typedef uint32_t rndis_RequestId_t;
|
||||
typedef uint32_t rndis_MajorVersion_t;
|
||||
typedef uint32_t rndis_MinorVersion_t;
|
||||
typedef uint32_t rndis_MaxTransferSize_t;
|
||||
typedef uint32_t rndis_Status_t;
|
||||
|
||||
/* Device Flags */
|
||||
#define RNDIS_DF_CONNECTIONLESS 0x00000001
|
||||
#define RNDIS_DF_CONNECTION_ORIENTED 0x00000002
|
||||
typedef uint32_t rndis_DeviceFlags_t;
|
||||
|
||||
/* Mediums */
|
||||
#define RNDIS_MEDIUM_802_3 0x00000000
|
||||
typedef uint32_t rndis_Medium_t;
|
||||
|
||||
typedef uint32_t rndis_MaxPacketsPerTransfer_t;
|
||||
typedef uint32_t rndis_PacketAlignmentFactor_t;
|
||||
typedef uint32_t rndis_AfListOffset_t;
|
||||
typedef uint32_t rndis_AfListSize_t;
|
||||
|
||||
/*** Remote NDIS Generic Message type ***/
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
} rndis_generic_msg_t;
|
||||
|
||||
/*** Remote NDIS Initialize Message ***/
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
rndis_MajorVersion_t MajorVersion;
|
||||
rndis_MinorVersion_t MinorVersion;
|
||||
rndis_MaxTransferSize_t MaxTransferSize;
|
||||
} rndis_initialize_msg_t;
|
||||
|
||||
/* Response: */
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
rndis_Status_t Status;
|
||||
rndis_MajorVersion_t MajorVersion;
|
||||
rndis_MinorVersion_t MinorVersion;
|
||||
rndis_DeviceFlags_t DeviceFlags;
|
||||
rndis_Medium_t Medium;
|
||||
rndis_MaxPacketsPerTransfer_t MaxPacketsPerTransfer;
|
||||
rndis_MaxTransferSize_t MaxTransferSize;
|
||||
rndis_PacketAlignmentFactor_t PacketAlignmentFactor;
|
||||
rndis_AfListOffset_t AfListOffset;
|
||||
rndis_AfListSize_t AfListSize;
|
||||
} rndis_initialize_cmplt_t;
|
||||
|
||||
/*** Remote NDIS Halt Message ***/
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
} rndis_halt_msg_t;
|
||||
|
||||
typedef uint32_t rndis_Oid_t;
|
||||
typedef uint32_t rndis_InformationBufferLength_t;
|
||||
typedef uint32_t rndis_InformationBufferOffset_t;
|
||||
typedef uint32_t rndis_DeviceVcHandle_t;
|
||||
|
||||
/*** Remote NDIS Query Message ***/
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
rndis_Oid_t Oid;
|
||||
rndis_InformationBufferLength_t InformationBufferLength;
|
||||
rndis_InformationBufferOffset_t InformationBufferOffset;
|
||||
rndis_DeviceVcHandle_t DeviceVcHandle;
|
||||
} rndis_query_msg_t;
|
||||
|
||||
/* Response: */
|
||||
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
rndis_Status_t Status;
|
||||
rndis_InformationBufferLength_t InformationBufferLength;
|
||||
rndis_InformationBufferOffset_t InformationBufferOffset;
|
||||
} rndis_query_cmplt_t;
|
||||
|
||||
/*** Remote NDIS Set Message ***/
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
rndis_Oid_t Oid;
|
||||
rndis_InformationBufferLength_t InformationBufferLength;
|
||||
rndis_InformationBufferOffset_t InformationBufferOffset;
|
||||
rndis_DeviceVcHandle_t DeviceVcHandle;
|
||||
} rndis_set_msg_t;
|
||||
|
||||
/* Response */
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
rndis_Status_t Status;
|
||||
} rndis_set_cmplt_t;
|
||||
|
||||
/* Information buffer layout for OID_GEN_RNDIS_CONFIG_PARAMETER */
|
||||
typedef uint32_t rndis_ParameterNameOffset_t;
|
||||
typedef uint32_t rndis_ParameterNameLength_t;
|
||||
typedef uint32_t rndis_ParameterType_t;
|
||||
typedef uint32_t rndis_ParameterValueOffset_t;
|
||||
typedef uint32_t rndis_ParameterValueLength_t;
|
||||
|
||||
#define PARAMETER_TYPE_STRING 2
|
||||
#define PARAMETER_TYPE_NUMERICAL 0
|
||||
|
||||
typedef struct {
|
||||
rndis_ParameterNameOffset_t ParameterNameOffset;
|
||||
rndis_ParameterNameLength_t ParameterNameLength;
|
||||
rndis_ParameterType_t ParameterType;
|
||||
rndis_ParameterValueOffset_t ParameterValueOffset;
|
||||
rndis_ParameterValueLength_t ParameterValueLength;
|
||||
} rndis_config_parameter_t;
|
||||
|
||||
typedef uint32_t rndis_Reserved_t;
|
||||
|
||||
/*** Remote NDIS Soft Reset Message ***/
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_Reserved_t Reserved;
|
||||
} rndis_reset_msg_t;
|
||||
|
||||
typedef uint32_t rndis_AddressingReset_t;
|
||||
|
||||
/* Response: */
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_Status_t Status;
|
||||
rndis_AddressingReset_t AddressingReset;
|
||||
} rndis_reset_cmplt_t;
|
||||
|
||||
/*** Remote NDIS Indicate Status Message ***/
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_Status_t Status;
|
||||
rndis_Status_t StatusBufferLength;
|
||||
rndis_Status_t StatusBufferOffset;
|
||||
} rndis_indicate_status_t;
|
||||
|
||||
typedef uint32_t rndis_DiagStatus_t;
|
||||
typedef uint32_t rndis_ErrorOffset_t;
|
||||
|
||||
typedef struct {
|
||||
rndis_DiagStatus_t DiagStatus;
|
||||
rndis_ErrorOffset_t ErrorOffset;
|
||||
} rndis_diagnostic_info_t;
|
||||
|
||||
/*** Remote NDIS Keepalive Message */
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
} rndis_keepalive_msg_t;
|
||||
|
||||
/* Response: */
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_RequestId_t RequestId;
|
||||
rndis_Status_t Status;
|
||||
} rndis_keepalive_cmplt_t;
|
||||
|
||||
/*** Remote NDIS Data Packet ***/
|
||||
|
||||
typedef uint32_t rndis_DataOffset_t;
|
||||
typedef uint32_t rndis_DataLength_t;
|
||||
typedef uint32_t rndis_OOBDataOffset_t;
|
||||
typedef uint32_t rndis_OOBDataLength_t;
|
||||
typedef uint32_t rndis_NumOOBDataElements_t;
|
||||
typedef uint32_t rndis_PerPacketInfoOffset_t;
|
||||
typedef uint32_t rndis_PerPacketInfoLength_t;
|
||||
|
||||
typedef struct {
|
||||
rndis_MessageType_t MessageType;
|
||||
rndis_MessageLength_t MessageLength;
|
||||
rndis_DataOffset_t DataOffset;
|
||||
rndis_DataLength_t DataLength;
|
||||
rndis_OOBDataOffset_t OOBDataOffset;
|
||||
rndis_OOBDataLength_t OOBDataLength;
|
||||
rndis_NumOOBDataElements_t NumOOBDataElements;
|
||||
rndis_PerPacketInfoOffset_t PerPacketInfoOffset;
|
||||
rndis_PerPacketInfoLength_t PerPacketInfoLength;
|
||||
rndis_DeviceVcHandle_t DeviceVcHandle;
|
||||
rndis_Reserved_t Reserved;
|
||||
} rndis_data_packet_t;
|
||||
|
||||
typedef uint32_t rndis_ClassInformationOffset_t;
|
||||
typedef uint32_t rndis_Size_t;
|
||||
typedef uint32_t rndis_Type_t;
|
||||
|
||||
typedef struct {
|
||||
rndis_Size_t Size;
|
||||
rndis_Type_t Type;
|
||||
rndis_ClassInformationOffset_t ClassInformationType;
|
||||
} rndis_OOB_packet_t;
|
||||
|
||||
#include "ndis.h"
|
||||
|
||||
typedef enum rnids_state_e {
|
||||
rndis_uninitialized,
|
||||
rndis_initialized,
|
||||
rndis_data_initialized
|
||||
} rndis_state_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t txok;
|
||||
uint32_t rxok;
|
||||
uint32_t txbad;
|
||||
uint32_t rxbad;
|
||||
} usb_eth_stat_t;
|
||||
|
||||
#endif /* _RNDIS_H */
|
||||
|
||||
/** @} */
|
@@ -0,0 +1,566 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_rndis.h"
|
||||
#include "rndis_protocol.h"
|
||||
|
||||
#define RNDIS_OUT_EP_IDX 0
|
||||
#define RNDIS_IN_EP_IDX 1
|
||||
#define RNDIS_INT_EP_IDX 2
|
||||
|
||||
/* Describe EndPoints configuration */
|
||||
static struct usbd_endpoint rndis_ep_data[3];
|
||||
|
||||
#define RNDIS_INQUIRY_PUT(src, len) (memcpy(infomation_buffer, src, len))
|
||||
#define RNDIS_INQUIRY_PUT_LE32(value) (*(uint32_t *)infomation_buffer = (value))
|
||||
|
||||
/* Device data structure */
|
||||
struct usbd_rndis_priv {
|
||||
uint32_t drv_version;
|
||||
uint32_t link_status;
|
||||
uint32_t net_filter;
|
||||
usb_eth_stat_t eth_state;
|
||||
rndis_state_t init_state;
|
||||
uint8_t mac[6];
|
||||
} g_usbd_rndis;
|
||||
|
||||
#if CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE < 140
|
||||
#undef CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE
|
||||
#define CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE 156
|
||||
#endif
|
||||
|
||||
#if CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE < 1580
|
||||
#undef CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE
|
||||
#define CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE 1580
|
||||
#endif
|
||||
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE];
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t rndis_encapsulated_resp_buffer[CONFIG_USBDEV_RNDIS_RESP_BUFFER_SIZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t NOTIFY_RESPONSE_AVAILABLE[8];
|
||||
|
||||
volatile uint8_t *g_rndis_rx_data_buffer;
|
||||
volatile uint32_t g_rndis_rx_data_length;
|
||||
volatile uint32_t g_rndis_tx_data_length;
|
||||
|
||||
/* RNDIS options list */
|
||||
const uint32_t oid_supported_list[] = {
|
||||
/* General OIDs */
|
||||
OID_GEN_SUPPORTED_LIST,
|
||||
OID_GEN_HARDWARE_STATUS,
|
||||
OID_GEN_MEDIA_SUPPORTED,
|
||||
OID_GEN_MEDIA_IN_USE,
|
||||
OID_GEN_MAXIMUM_FRAME_SIZE,
|
||||
OID_GEN_LINK_SPEED,
|
||||
OID_GEN_TRANSMIT_BLOCK_SIZE,
|
||||
OID_GEN_RECEIVE_BLOCK_SIZE,
|
||||
OID_GEN_VENDOR_ID,
|
||||
OID_GEN_VENDOR_DESCRIPTION,
|
||||
OID_GEN_VENDOR_DRIVER_VERSION,
|
||||
OID_GEN_CURRENT_PACKET_FILTER,
|
||||
OID_GEN_MAXIMUM_TOTAL_SIZE,
|
||||
OID_GEN_MEDIA_CONNECT_STATUS,
|
||||
|
||||
OID_GEN_PHYSICAL_MEDIUM,
|
||||
|
||||
/* General Statistic OIDs */
|
||||
OID_GEN_XMIT_OK,
|
||||
OID_GEN_RCV_OK,
|
||||
OID_GEN_XMIT_ERROR,
|
||||
OID_GEN_RCV_ERROR,
|
||||
OID_GEN_RCV_NO_BUFFER,
|
||||
|
||||
/* Please configure us */
|
||||
OID_GEN_RNDIS_CONFIG_PARAMETER,
|
||||
|
||||
/* 802.3 OIDs */
|
||||
OID_802_3_PERMANENT_ADDRESS,
|
||||
OID_802_3_CURRENT_ADDRESS,
|
||||
OID_802_3_MULTICAST_LIST,
|
||||
OID_802_3_MAXIMUM_LIST_SIZE,
|
||||
|
||||
/* 802.3 Statistic OIDs */
|
||||
OID_802_3_RCV_ERROR_ALIGNMENT,
|
||||
OID_802_3_XMIT_ONE_COLLISION,
|
||||
OID_802_3_XMIT_MORE_COLLISIONS,
|
||||
|
||||
OID_802_3_MAC_OPTIONS,
|
||||
};
|
||||
|
||||
static int rndis_encapsulated_cmd_handler(uint8_t *data, uint32_t len);
|
||||
|
||||
static void rndis_notify_rsp(void)
|
||||
{
|
||||
memset(NOTIFY_RESPONSE_AVAILABLE, 0, 8);
|
||||
NOTIFY_RESPONSE_AVAILABLE[0] = 0x01;
|
||||
usbd_ep_start_write(0, rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr, NOTIFY_RESPONSE_AVAILABLE, 8);
|
||||
}
|
||||
|
||||
static int rndis_class_interface_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
switch (setup->bRequest) {
|
||||
case CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
|
||||
rndis_encapsulated_cmd_handler(*data, setup->wLength);
|
||||
break;
|
||||
case CDC_REQUEST_GET_ENCAPSULATED_RESPONSE:
|
||||
*data = rndis_encapsulated_resp_buffer;
|
||||
*len = ((rndis_generic_msg_t *)rndis_encapsulated_resp_buffer)->MessageLength;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rndis_init_cmd_handler(uint8_t *data, uint32_t len);
|
||||
static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len);
|
||||
static int rndis_query_cmd_handler(uint8_t *data, uint32_t len);
|
||||
static int rndis_set_cmd_handler(uint8_t *data, uint32_t len);
|
||||
static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len);
|
||||
static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len);
|
||||
|
||||
static int rndis_encapsulated_cmd_handler(uint8_t *data, uint32_t len)
|
||||
{
|
||||
switch (((rndis_generic_msg_t *)data)->MessageType) {
|
||||
case REMOTE_NDIS_INITIALIZE_MSG:
|
||||
return rndis_init_cmd_handler(data, len);
|
||||
case REMOTE_NDIS_HALT_MSG:
|
||||
return rndis_halt_cmd_handler(data, len);
|
||||
case REMOTE_NDIS_QUERY_MSG:
|
||||
return rndis_query_cmd_handler(data, len);
|
||||
case REMOTE_NDIS_SET_MSG:
|
||||
return rndis_set_cmd_handler(data, len);
|
||||
case REMOTE_NDIS_RESET_MSG:
|
||||
return rndis_reset_cmd_handler(data, len);
|
||||
case REMOTE_NDIS_KEEPALIVE_MSG:
|
||||
return rndis_keepalive_cmd_handler(data, len);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int rndis_init_cmd_handler(uint8_t *data, uint32_t len)
|
||||
{
|
||||
rndis_initialize_msg_t *cmd = (rndis_initialize_msg_t *)data;
|
||||
rndis_initialize_cmplt_t *resp;
|
||||
|
||||
resp = ((rndis_initialize_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->RequestId = cmd->RequestId;
|
||||
resp->MessageType = REMOTE_NDIS_INITIALIZE_CMPLT;
|
||||
resp->MessageLength = sizeof(rndis_initialize_cmplt_t);
|
||||
resp->MajorVersion = RNDIS_MAJOR_VERSION;
|
||||
resp->MinorVersion = RNDIS_MINOR_VERSION;
|
||||
resp->Status = RNDIS_STATUS_SUCCESS;
|
||||
resp->DeviceFlags = RNDIS_DF_CONNECTIONLESS;
|
||||
resp->Medium = RNDIS_MEDIUM_802_3;
|
||||
resp->MaxPacketsPerTransfer = CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE / 1580;
|
||||
resp->MaxTransferSize = CONFIG_USBDEV_RNDIS_ETH_MAX_FRAME_SIZE;
|
||||
resp->PacketAlignmentFactor = 0;
|
||||
resp->AfListOffset = 0;
|
||||
resp->AfListSize = 0;
|
||||
|
||||
g_usbd_rndis.init_state = rndis_initialized;
|
||||
|
||||
rndis_notify_rsp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rndis_halt_cmd_handler(uint8_t *data, uint32_t len)
|
||||
{
|
||||
rndis_halt_msg_t *resp;
|
||||
|
||||
resp = ((rndis_halt_msg_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->MessageLength = 0;
|
||||
|
||||
g_usbd_rndis.init_state = rndis_uninitialized;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rndis_query_cmd_handler(uint8_t *data, uint32_t len)
|
||||
{
|
||||
rndis_query_msg_t *cmd = (rndis_query_msg_t *)data;
|
||||
rndis_query_cmplt_t *resp;
|
||||
uint8_t *infomation_buffer;
|
||||
uint32_t infomation_len = 0;
|
||||
|
||||
resp = ((rndis_query_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->MessageType = REMOTE_NDIS_QUERY_CMPLT;
|
||||
resp->RequestId = cmd->RequestId;
|
||||
resp->InformationBufferOffset = sizeof(rndis_query_cmplt_t) - sizeof(rndis_generic_msg_t);
|
||||
resp->Status = RNDIS_STATUS_SUCCESS;
|
||||
|
||||
infomation_buffer = (uint8_t *)resp + sizeof(rndis_query_cmplt_t);
|
||||
|
||||
switch (cmd->Oid) {
|
||||
case OID_GEN_SUPPORTED_LIST:
|
||||
RNDIS_INQUIRY_PUT(oid_supported_list, sizeof(oid_supported_list));
|
||||
infomation_len = sizeof(oid_supported_list);
|
||||
break;
|
||||
case OID_GEN_HARDWARE_STATUS:
|
||||
RNDIS_INQUIRY_PUT_LE32(NDIS_HW_STS_READY);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_MEDIA_SUPPORTED:
|
||||
case OID_GEN_MEDIA_IN_USE:
|
||||
RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
||||
case OID_GEN_TRANSMIT_BLOCK_SIZE:
|
||||
case OID_GEN_RECEIVE_BLOCK_SIZE:
|
||||
RNDIS_INQUIRY_PUT_LE32(0x05DC); /* mtu 1500 */
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_VENDOR_ID:
|
||||
RNDIS_INQUIRY_PUT_LE32(CONFIG_USBDEV_RNDIS_VENDOR_ID);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_VENDOR_DRIVER_VERSION:
|
||||
RNDIS_INQUIRY_PUT_LE32(0x0001);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_VENDOR_DESCRIPTION:
|
||||
RNDIS_INQUIRY_PUT(CONFIG_USBDEV_RNDIS_VENDOR_DESC, strlen(CONFIG_USBDEV_RNDIS_VENDOR_DESC));
|
||||
infomation_len = (strlen(CONFIG_USBDEV_RNDIS_VENDOR_DESC) + 1);
|
||||
break;
|
||||
case OID_802_3_CURRENT_ADDRESS:
|
||||
case OID_802_3_PERMANENT_ADDRESS:
|
||||
RNDIS_INQUIRY_PUT(g_usbd_rndis.mac, 6);
|
||||
infomation_len = 6;
|
||||
break;
|
||||
case OID_GEN_PHYSICAL_MEDIUM:
|
||||
RNDIS_INQUIRY_PUT_LE32(NDIS_MEDIUM_802_3);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_LINK_SPEED:
|
||||
if (usbd_get_ep_mps(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr) > 64) {
|
||||
RNDIS_INQUIRY_PUT_LE32(480000000 / 100);
|
||||
} else {
|
||||
RNDIS_INQUIRY_PUT_LE32(12000000 / 100);
|
||||
}
|
||||
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_CURRENT_PACKET_FILTER:
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.net_filter);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_MAXIMUM_TOTAL_SIZE:
|
||||
RNDIS_INQUIRY_PUT_LE32(0x0616); /* 1514 + 44 */
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_MEDIA_CONNECT_STATUS:
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.link_status);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_RNDIS_CONFIG_PARAMETER:
|
||||
RNDIS_INQUIRY_PUT_LE32(0);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_802_3_MAXIMUM_LIST_SIZE:
|
||||
RNDIS_INQUIRY_PUT_LE32(1); /* one address */
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_802_3_MULTICAST_LIST:
|
||||
//RNDIS_INQUIRY_PUT_LE32(0xE0000000); /* 224.0.0.0 */
|
||||
resp->Status = RNDIS_STATUS_NOT_SUPPORTED;
|
||||
RNDIS_INQUIRY_PUT_LE32(0);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_802_3_MAC_OPTIONS:
|
||||
// infomation_len = 0;
|
||||
resp->Status = RNDIS_STATUS_NOT_SUPPORTED;
|
||||
RNDIS_INQUIRY_PUT_LE32(0);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_MAC_OPTIONS:
|
||||
RNDIS_INQUIRY_PUT_LE32(0);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_802_3_RCV_ERROR_ALIGNMENT:
|
||||
RNDIS_INQUIRY_PUT_LE32(0);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_802_3_XMIT_ONE_COLLISION:
|
||||
RNDIS_INQUIRY_PUT_LE32(0);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_802_3_XMIT_MORE_COLLISIONS:
|
||||
RNDIS_INQUIRY_PUT_LE32(0);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_XMIT_OK:
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.txok);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_RCV_OK:
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.rxok);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_RCV_ERROR:
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.rxbad);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_XMIT_ERROR:
|
||||
RNDIS_INQUIRY_PUT_LE32(g_usbd_rndis.eth_state.txbad);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
case OID_GEN_RCV_NO_BUFFER:
|
||||
RNDIS_INQUIRY_PUT_LE32(0);
|
||||
infomation_len = 4;
|
||||
break;
|
||||
default:
|
||||
resp->Status = RNDIS_STATUS_FAILURE;
|
||||
infomation_len = 0;
|
||||
USB_LOG_WRN("Unhandled query for Object ID 0x%x\r\n", cmd->Oid);
|
||||
break;
|
||||
}
|
||||
|
||||
resp->MessageLength = sizeof(rndis_query_cmplt_t) + infomation_len;
|
||||
resp->InformationBufferLength = infomation_len;
|
||||
|
||||
rndis_notify_rsp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rndis_set_cmd_handler(uint8_t *data, uint32_t len)
|
||||
{
|
||||
rndis_set_msg_t *cmd = (rndis_set_msg_t *)data;
|
||||
rndis_set_cmplt_t *resp;
|
||||
rndis_config_parameter_t *param;
|
||||
|
||||
resp = ((rndis_set_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->RequestId = cmd->RequestId;
|
||||
resp->MessageType = REMOTE_NDIS_SET_CMPLT;
|
||||
resp->MessageLength = sizeof(rndis_set_cmplt_t);
|
||||
resp->Status = RNDIS_STATUS_SUCCESS;
|
||||
|
||||
switch (cmd->Oid) {
|
||||
case OID_GEN_RNDIS_CONFIG_PARAMETER:
|
||||
param = (rndis_config_parameter_t *)((uint8_t *)&(cmd->RequestId) + cmd->InformationBufferOffset);
|
||||
USB_LOG_WRN("RNDIS cfg param: NameOfs=%d, NameLen=%d, ValueOfs=%d, ValueLen=%d\r\n",
|
||||
param->ParameterNameOffset, param->ParameterNameLength,
|
||||
param->ParameterValueOffset, param->ParameterValueLength);
|
||||
break;
|
||||
case OID_GEN_CURRENT_PACKET_FILTER:
|
||||
if (cmd->InformationBufferLength < sizeof(g_usbd_rndis.net_filter)) {
|
||||
USB_LOG_WRN("PACKET_FILTER!\r\n");
|
||||
resp->Status = RNDIS_STATUS_INVALID_DATA;
|
||||
} else {
|
||||
uint32_t *filter;
|
||||
/* Parameter starts at offset buf_offset of the req_id field */
|
||||
filter = (uint32_t *)((uint8_t *)&(cmd->RequestId) + cmd->InformationBufferOffset);
|
||||
|
||||
//g_usbd_rndis.net_filter = param->ParameterNameOffset;
|
||||
g_usbd_rndis.net_filter = *(uint32_t *)filter;
|
||||
if (g_usbd_rndis.net_filter) {
|
||||
g_usbd_rndis.init_state = rndis_data_initialized;
|
||||
} else {
|
||||
g_usbd_rndis.init_state = rndis_initialized;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OID_GEN_CURRENT_LOOKAHEAD:
|
||||
break;
|
||||
case OID_GEN_PROTOCOL_OPTIONS:
|
||||
break;
|
||||
case OID_802_3_MULTICAST_LIST:
|
||||
break;
|
||||
case OID_PNP_ADD_WAKE_UP_PATTERN:
|
||||
case OID_PNP_REMOVE_WAKE_UP_PATTERN:
|
||||
case OID_PNP_ENABLE_WAKE_UP:
|
||||
default:
|
||||
resp->Status = RNDIS_STATUS_FAILURE;
|
||||
USB_LOG_WRN("Unhandled query for Object ID 0x%x\r\n", cmd->Oid);
|
||||
break;
|
||||
}
|
||||
|
||||
rndis_notify_rsp();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rndis_reset_cmd_handler(uint8_t *data, uint32_t len)
|
||||
{
|
||||
// rndis_reset_msg_t *cmd = (rndis_reset_msg_t *)data;
|
||||
rndis_reset_cmplt_t *resp;
|
||||
|
||||
resp = ((rndis_reset_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->MessageType = REMOTE_NDIS_RESET_CMPLT;
|
||||
resp->MessageLength = sizeof(rndis_reset_cmplt_t);
|
||||
resp->Status = RNDIS_STATUS_SUCCESS;
|
||||
resp->AddressingReset = 1;
|
||||
|
||||
g_usbd_rndis.init_state = rndis_uninitialized;
|
||||
|
||||
rndis_notify_rsp();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rndis_keepalive_cmd_handler(uint8_t *data, uint32_t len)
|
||||
{
|
||||
rndis_keepalive_msg_t *cmd = (rndis_keepalive_msg_t *)data;
|
||||
rndis_keepalive_cmplt_t *resp;
|
||||
|
||||
resp = ((rndis_keepalive_cmplt_t *)rndis_encapsulated_resp_buffer);
|
||||
resp->RequestId = cmd->RequestId;
|
||||
resp->MessageType = REMOTE_NDIS_KEEPALIVE_CMPLT;
|
||||
resp->MessageLength = sizeof(rndis_keepalive_cmplt_t);
|
||||
resp->Status = RNDIS_STATUS_SUCCESS;
|
||||
|
||||
rndis_notify_rsp();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rndis_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||
{
|
||||
switch (event) {
|
||||
case USBD_EVENT_RESET:
|
||||
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
|
||||
break;
|
||||
case USBD_EVENT_CONFIGURED:
|
||||
g_rndis_rx_data_length = 0;
|
||||
g_rndis_tx_data_length = 0;
|
||||
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_CONNECTED;
|
||||
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
rndis_data_packet_t *hdr;
|
||||
|
||||
hdr = (rndis_data_packet_t *)g_rndis_rx_buffer;
|
||||
g_rndis_rx_data_buffer = g_rndis_rx_buffer;
|
||||
if ((hdr->MessageType != REMOTE_NDIS_PACKET_MSG) || (nbytes < hdr->MessageLength)) {
|
||||
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Point to the payload and update the message length */
|
||||
g_rndis_rx_data_buffer += hdr->DataOffset + sizeof(rndis_generic_msg_t);
|
||||
g_rndis_rx_data_length = hdr->DataLength;
|
||||
|
||||
usbd_rndis_data_recv_done();
|
||||
}
|
||||
|
||||
void rndis_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
if ((nbytes % usbd_get_ep_mps(busid, ep)) == 0 && nbytes) {
|
||||
/* send zlp */
|
||||
usbd_ep_start_write(0, ep, NULL, 0);
|
||||
} else {
|
||||
g_rndis_tx_data_length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void rndis_int_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
//USB_LOG_DBG("len:%d\r\n", nbytes);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
|
||||
#include <lwip/pbuf.h>
|
||||
|
||||
struct pbuf *usbd_rndis_eth_rx(void)
|
||||
{
|
||||
struct pbuf *p;
|
||||
|
||||
if (g_rndis_rx_data_length == 0) {
|
||||
return NULL;
|
||||
}
|
||||
p = pbuf_alloc(PBUF_RAW, g_rndis_rx_data_length, PBUF_POOL);
|
||||
if (p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
usb_memcpy(p->payload, (uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
|
||||
p->len = g_rndis_rx_data_length;
|
||||
|
||||
USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_data_length);
|
||||
g_rndis_rx_data_length = 0;
|
||||
usbd_ep_start_read(0, rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr, g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
int usbd_rndis_eth_tx(struct pbuf *p)
|
||||
{
|
||||
struct pbuf *q;
|
||||
uint8_t *buffer;
|
||||
rndis_data_packet_t *hdr;
|
||||
|
||||
if (g_usbd_rndis.link_status == NDIS_MEDIA_STATE_DISCONNECTED) {
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
if (g_rndis_tx_data_length > 0) {
|
||||
return -USB_ERR_BUSY;
|
||||
}
|
||||
|
||||
if (p->tot_len > sizeof(g_rndis_tx_buffer)) {
|
||||
p->tot_len = sizeof(g_rndis_tx_buffer);
|
||||
}
|
||||
|
||||
buffer = (uint8_t *)(g_rndis_tx_buffer + sizeof(rndis_data_packet_t));
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
usb_memcpy(buffer, q->payload, q->len);
|
||||
buffer += q->len;
|
||||
}
|
||||
|
||||
hdr = (rndis_data_packet_t *)g_rndis_tx_buffer;
|
||||
|
||||
memset(hdr, 0, sizeof(rndis_data_packet_t));
|
||||
hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
|
||||
hdr->MessageLength = sizeof(rndis_data_packet_t) + p->tot_len;
|
||||
hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t);
|
||||
hdr->DataLength = p->tot_len;
|
||||
|
||||
g_rndis_tx_data_length = sizeof(rndis_data_packet_t) + p->tot_len;
|
||||
|
||||
USB_LOG_DBG("txlen:%d\r\n", g_rndis_tx_data_length);
|
||||
return usbd_ep_start_write(0, rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr, g_rndis_tx_buffer, g_rndis_tx_data_length);
|
||||
}
|
||||
#endif
|
||||
struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
|
||||
const uint8_t out_ep,
|
||||
const uint8_t in_ep,
|
||||
const uint8_t int_ep, uint8_t mac[6])
|
||||
{
|
||||
memcpy(g_usbd_rndis.mac, mac, 6);
|
||||
|
||||
g_usbd_rndis.drv_version = 0x0001;
|
||||
g_usbd_rndis.link_status = NDIS_MEDIA_STATE_DISCONNECTED;
|
||||
|
||||
rndis_ep_data[RNDIS_OUT_EP_IDX].ep_addr = out_ep;
|
||||
rndis_ep_data[RNDIS_OUT_EP_IDX].ep_cb = rndis_bulk_out;
|
||||
rndis_ep_data[RNDIS_IN_EP_IDX].ep_addr = in_ep;
|
||||
rndis_ep_data[RNDIS_IN_EP_IDX].ep_cb = rndis_bulk_in;
|
||||
rndis_ep_data[RNDIS_INT_EP_IDX].ep_addr = int_ep;
|
||||
rndis_ep_data[RNDIS_INT_EP_IDX].ep_cb = rndis_int_in;
|
||||
|
||||
usbd_add_endpoint(0, &rndis_ep_data[RNDIS_OUT_EP_IDX]);
|
||||
usbd_add_endpoint(0, &rndis_ep_data[RNDIS_IN_EP_IDX]);
|
||||
usbd_add_endpoint(0, &rndis_ep_data[RNDIS_INT_EP_IDX]);
|
||||
|
||||
intf->class_interface_handler = rndis_class_interface_request_handler;
|
||||
intf->class_endpoint_handler = NULL;
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = rndis_notify_handler;
|
||||
|
||||
return intf;
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBD_RNDIS_H
|
||||
#define USBD_RNDIS_H
|
||||
|
||||
#include "usb_cdc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Init rndis interface driver */
|
||||
struct usbd_interface *usbd_rndis_init_intf(struct usbd_interface *intf,
|
||||
const uint8_t out_ep,
|
||||
const uint8_t in_ep,
|
||||
const uint8_t int_ep, uint8_t mac[6]);
|
||||
|
||||
void usbd_rndis_data_recv_done(void);
|
||||
|
||||
#ifdef CONFIG_USBDEV_RNDIS_USING_LWIP
|
||||
struct pbuf *usbd_rndis_eth_rx(void);
|
||||
int usbd_rndis_eth_tx(struct pbuf *p);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBD_RNDIS_H */
|
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_bluetooth.h"
|
||||
|
||||
#undef USB_DBG_TAG
|
||||
#define USB_DBG_TAG "usbh_bluetooth"
|
||||
#include "usb_log.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/bluetooth"
|
||||
|
||||
static struct usbh_bluetooth g_bluetooth_class;
|
||||
|
||||
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_tx_buf[1 + CONFIG_USBHOST_BLUETOOTH_TX_SIZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_rx_buf[1 + CONFIG_USBHOST_BLUETOOTH_RX_SIZE];
|
||||
#else
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_cmd_buf[1 + 256];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_evt_buf[1 + 256];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_tx_buf[1 + CONFIG_USBHOST_BLUETOOTH_TX_SIZE];
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_bluetooth_rx_buf[1 + CONFIG_USBHOST_BLUETOOTH_RX_SIZE];
|
||||
#endif
|
||||
|
||||
static int usbh_bluetooth_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret = 0;
|
||||
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
uint8_t mult;
|
||||
uint16_t mps;
|
||||
#endif
|
||||
|
||||
struct usbh_bluetooth *bluetooth_class = &g_bluetooth_class;
|
||||
|
||||
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
if (intf != 0) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(bluetooth_class, 0, sizeof(struct usbh_bluetooth));
|
||||
|
||||
bluetooth_class->hport = hport;
|
||||
bluetooth_class->intf = intf;
|
||||
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
bluetooth_class->num_of_intf_altsettings = hport->config.intf[intf + 1].altsetting_num;
|
||||
#endif
|
||||
hport->config.intf[intf].priv = bluetooth_class;
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc;
|
||||
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
if (USB_GET_ENDPOINT_TYPE(ep_desc->bmAttributes) == USB_ENDPOINT_TYPE_INTERRUPT) {
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
USBH_EP_INIT(bluetooth_class->intin, ep_desc);
|
||||
} else {
|
||||
return -USB_ERR_NOTSUPP;
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
USBH_EP_INIT(bluetooth_class->bulkin, ep_desc);
|
||||
} else {
|
||||
USBH_EP_INIT(bluetooth_class->bulkout, ep_desc);
|
||||
}
|
||||
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
USB_LOG_INFO("Num of altsettings:%u\r\n", bluetooth_class->num_of_intf_altsettings);
|
||||
|
||||
for (uint8_t i = 0; i < bluetooth_class->num_of_intf_altsettings; i++) {
|
||||
USB_LOG_INFO("Altsetting:%u\r\n", i);
|
||||
for (uint8_t j = 0; j < hport->config.intf[intf + 1].altsetting[i].intf_desc.bNumEndpoints; j++) {
|
||||
ep_desc = &bluetooth_class->hport->config.intf[intf + 1].altsetting[i].ep[j].ep_desc;
|
||||
|
||||
mult = USB_GET_MULT(ep_desc->wMaxPacketSize);
|
||||
mps = USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize);
|
||||
|
||||
USB_LOG_INFO("\tEp=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
|
||||
ep_desc->bEndpointAddress,
|
||||
ep_desc->bmAttributes,
|
||||
mps,
|
||||
ep_desc->bInterval,
|
||||
mult);
|
||||
}
|
||||
}
|
||||
|
||||
ret = usbh_set_interface(hport, intf, 0);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
USB_LOG_INFO("Bluetooth select altsetting 0\r\n");
|
||||
#endif
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
USB_LOG_INFO("Register Bluetooth Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_bluetooth_run(bluetooth_class);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_bluetooth_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_bluetooth *bluetooth_class = (struct usbh_bluetooth *)hport->config.intf[intf].priv;
|
||||
|
||||
if (hport->config.config_desc.bNumInterfaces == (intf + 1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bluetooth_class) {
|
||||
if (bluetooth_class->bulkin) {
|
||||
usbh_kill_urb(&bluetooth_class->bulkin_urb);
|
||||
}
|
||||
|
||||
if (bluetooth_class->bulkout) {
|
||||
usbh_kill_urb(&bluetooth_class->bulkout_urb);
|
||||
}
|
||||
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
if (bluetooth_class->intin) {
|
||||
usbh_kill_urb(&bluetooth_class->intin_urb);
|
||||
}
|
||||
|
||||
// if (bluetooth_class->isoin) {
|
||||
// usbh_kill_urb(&bluetooth_class->isoin_urb);
|
||||
// }
|
||||
|
||||
// if (bluetooth_class->isoin) {
|
||||
// usbh_kill_urb(&bluetooth_class->isoinin_urb);
|
||||
// }
|
||||
#endif
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister Bluetooth Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_bluetooth_stop(bluetooth_class);
|
||||
}
|
||||
|
||||
memset(bluetooth_class, 0, sizeof(struct usbh_bluetooth));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_LOG
|
||||
static void usbh_bluetooth_hci_dump(uint8_t *data, uint32_t len)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (i % 16 == 0) {
|
||||
USB_LOG_RAW("\r\n");
|
||||
}
|
||||
|
||||
USB_LOG_RAW("%02x ", data[i]);
|
||||
}
|
||||
|
||||
USB_LOG_RAW("\r\n");
|
||||
}
|
||||
#else
|
||||
#define usbh_bluetooth_hci_dump(data, len)
|
||||
#endif
|
||||
|
||||
static int usbh_bluetooth_hci_bulk_out(uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
struct usbh_bluetooth *bluetooth_class = &g_bluetooth_class;
|
||||
struct usbh_urb *urb = &bluetooth_class->bulkout_urb;
|
||||
int ret;
|
||||
|
||||
usbh_bulk_urb_fill(urb, bluetooth_class->hport, bluetooth_class->bulkout, buffer, buflen, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(urb);
|
||||
if (ret == 0) {
|
||||
ret = urb->actual_length;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
g_bluetooth_tx_buf[0] = hci_type;
|
||||
memcpy(&g_bluetooth_tx_buf[1], buffer, buflen);
|
||||
usbh_bluetooth_hci_dump(g_bluetooth_tx_buf, buflen + 1);
|
||||
ret = usbh_bluetooth_hci_bulk_out(g_bluetooth_tx_buf, buflen + 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usbh_bluetooth_hci_rx_thread(void *argument)
|
||||
{
|
||||
int ret;
|
||||
uint32_t ep_mps;
|
||||
uint8_t retry = 0;
|
||||
uint16_t actual_len = 0;
|
||||
|
||||
ep_mps = USB_GET_MAXPACKETSIZE(g_bluetooth_class.bulkin->wMaxPacketSize);
|
||||
|
||||
USB_LOG_INFO("Create hc rx thread\r\n");
|
||||
while (1) {
|
||||
usbh_bulk_urb_fill(&g_bluetooth_class.bulkin_urb, g_bluetooth_class.hport, g_bluetooth_class.bulkin, &g_bluetooth_rx_buf[actual_len], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_bluetooth_class.bulkin_urb);
|
||||
if (ret < 0) {
|
||||
if (ret == -USB_ERR_SHUTDOWN) {
|
||||
goto delete;
|
||||
} else {
|
||||
retry++;
|
||||
if (retry == 3) {
|
||||
retry = 0;
|
||||
goto delete;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
actual_len += g_bluetooth_class.bulkin_urb.actual_length;
|
||||
if (g_bluetooth_class.bulkin_urb.actual_length != ep_mps) {
|
||||
usbh_bluetooth_hci_dump(g_bluetooth_rx_buf, actual_len);
|
||||
usbh_bluetooth_hci_read_callback(g_bluetooth_rx_buf, actual_len);
|
||||
actual_len = 0;
|
||||
} else {
|
||||
/* read continue util read short packet */
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
delete :
|
||||
USB_LOG_INFO("Delete hc acl rx thread\r\n");
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
#else
|
||||
static int usbh_bluetooth_hci_cmd(uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
struct usbh_bluetooth *bluetooth_class = &g_bluetooth_class;
|
||||
struct usb_setup_packet *setup;
|
||||
|
||||
if (!bluetooth_class || !bluetooth_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = bluetooth_class->hport->setup;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
|
||||
setup->bRequest = 0x00;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = bluetooth_class->intf;
|
||||
setup->wLength = buflen;
|
||||
|
||||
return usbh_control_transfer(bluetooth_class->hport, setup, buffer);
|
||||
}
|
||||
|
||||
int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (hci_type == USB_BLUETOOTH_HCI_CMD) {
|
||||
g_bluetooth_cmd_buf[0] = USB_BLUETOOTH_HCI_CMD;
|
||||
memcpy(&g_bluetooth_cmd_buf[1], buffer, buflen);
|
||||
usbh_bluetooth_hci_dump(g_bluetooth_cmd_buf, buflen + 1);
|
||||
ret = usbh_bluetooth_hci_cmd(&g_bluetooth_cmd_buf[1], buflen);
|
||||
} else if (hci_type == USB_BLUETOOTH_HCI_ACL) {
|
||||
g_bluetooth_tx_buf[0] = USB_BLUETOOTH_HCI_ACL;
|
||||
memcpy(&g_bluetooth_tx_buf[1], buffer, buflen);
|
||||
usbh_bluetooth_hci_dump(g_bluetooth_tx_buf, buflen + 1);
|
||||
ret = usbh_bluetooth_hci_bulk_out(&g_bluetooth_tx_buf[1], buflen);
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usbh_bluetooth_hci_evt_rx_thread(void *argument)
|
||||
{
|
||||
int ret;
|
||||
uint32_t ep_mps;
|
||||
uint32_t interval;
|
||||
uint8_t retry = 0;
|
||||
uint16_t actual_len = 0;
|
||||
|
||||
ep_mps = USB_GET_MAXPACKETSIZE(g_bluetooth_class.intin->wMaxPacketSize);
|
||||
interval = g_bluetooth_class.intin->bInterval;
|
||||
|
||||
USB_LOG_INFO("Create hc event rx thread\r\n");
|
||||
while (1) {
|
||||
usbh_int_urb_fill(&g_bluetooth_class.intin_urb, g_bluetooth_class.hport, g_bluetooth_class.intin, &g_bluetooth_evt_buf[1 + actual_len], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_bluetooth_class.intin_urb);
|
||||
if (ret < 0) {
|
||||
if (ret == -USB_ERR_SHUTDOWN) {
|
||||
goto delete;
|
||||
} else if (ret == -USB_ERR_NAK) {
|
||||
usb_osal_msleep(interval);
|
||||
continue;
|
||||
} else {
|
||||
retry++;
|
||||
if (retry == 3) {
|
||||
retry = 0;
|
||||
goto delete;
|
||||
}
|
||||
usb_osal_msleep(interval);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
actual_len += g_bluetooth_class.intin_urb.actual_length;
|
||||
if (g_bluetooth_class.intin_urb.actual_length != ep_mps) {
|
||||
g_bluetooth_evt_buf[0] = USB_BLUETOOTH_HCI_EVT;
|
||||
usbh_bluetooth_hci_dump(g_bluetooth_evt_buf, actual_len + 1);
|
||||
usbh_bluetooth_hci_read_callback(g_bluetooth_evt_buf, actual_len + 1);
|
||||
actual_len = 0;
|
||||
} else {
|
||||
/* read continue util read short packet */
|
||||
}
|
||||
usb_osal_msleep(interval);
|
||||
}
|
||||
// clang-format off
|
||||
delete :
|
||||
USB_LOG_INFO("Delete hc event rx thread\r\n");
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void usbh_bluetooth_hci_acl_rx_thread(void *argument)
|
||||
{
|
||||
int ret;
|
||||
uint32_t ep_mps;
|
||||
uint8_t retry = 0;
|
||||
uint16_t actual_len = 0;
|
||||
|
||||
ep_mps = USB_GET_MAXPACKETSIZE(g_bluetooth_class.bulkin->wMaxPacketSize);
|
||||
|
||||
USB_LOG_INFO("Create hc acl rx thread\r\n");
|
||||
while (1) {
|
||||
usbh_bulk_urb_fill(&g_bluetooth_class.bulkin_urb, g_bluetooth_class.hport, g_bluetooth_class.bulkin, &g_bluetooth_rx_buf[1 + actual_len], ep_mps, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_bluetooth_class.bulkin_urb);
|
||||
if (ret < 0) {
|
||||
if (ret == -USB_ERR_SHUTDOWN) {
|
||||
goto delete;
|
||||
} else {
|
||||
retry++;
|
||||
if (retry == 3) {
|
||||
retry = 0;
|
||||
goto delete;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
actual_len += g_bluetooth_class.bulkin_urb.actual_length;
|
||||
if (g_bluetooth_class.bulkin_urb.actual_length != ep_mps) {
|
||||
g_bluetooth_rx_buf[0] = USB_BLUETOOTH_HCI_ACL;
|
||||
usbh_bluetooth_hci_dump(g_bluetooth_rx_buf, actual_len + 1);
|
||||
usbh_bluetooth_hci_read_callback(g_bluetooth_rx_buf, actual_len + 1);
|
||||
actual_len = 0;
|
||||
} else {
|
||||
/* read continue util read short packet */
|
||||
}
|
||||
}
|
||||
// clang-format off
|
||||
delete :
|
||||
USB_LOG_INFO("Delete hc acl rx thread\r\n");
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
#endif
|
||||
|
||||
__WEAK void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_bluetooth_stop(struct usbh_bluetooth *bluetooth_class)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct usbh_class_driver bluetooth_class_driver = {
|
||||
.driver_name = "bluetooth",
|
||||
.connect = usbh_bluetooth_connect,
|
||||
.disconnect = usbh_bluetooth_disconnect
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
static const uint16_t bluetooth_id_table[][2] = {
|
||||
{ 0x2fe3, 0x000c },
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_h4_nrf_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_VID_PID | USB_CLASS_MATCH_INTF_CLASS,
|
||||
.class = 0xff,
|
||||
.subclass = 0x00,
|
||||
.protocol = 0x00,
|
||||
.id_table = bluetooth_id_table,
|
||||
.class_driver = &bluetooth_class_driver
|
||||
};
|
||||
#else
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info bluetooth_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_WIRELESS,
|
||||
.subclass = 0x01,
|
||||
.protocol = 0x01,
|
||||
.id_table = NULL,
|
||||
.class_driver = &bluetooth_class_driver
|
||||
};
|
||||
#endif
|
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2024, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBH_BLUETOOTH_H
|
||||
#define USBH_BLUETOOTH_H
|
||||
|
||||
#define USB_BLUETOOTH_HCI_NONE 0x00
|
||||
#define USB_BLUETOOTH_HCI_CMD 0x01
|
||||
#define USB_BLUETOOTH_HCI_ACL 0x02
|
||||
#define USB_BLUETOOTH_HCI_SCO 0x03
|
||||
#define USB_BLUETOOTH_HCI_EVT 0x04
|
||||
#define USB_BLUETOOTH_HCI_ISO 0x05
|
||||
|
||||
struct usbh_bluetooth {
|
||||
struct usbh_hubport *hport;
|
||||
uint8_t intf;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||
struct usbh_urb bulkin_urb; /* Bulk IN urb */
|
||||
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
|
||||
#ifndef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
struct usb_endpoint_descriptor *intin; /* INTR endpoint */
|
||||
struct usb_endpoint_descriptor *isoin; /* Bulk IN endpoint */
|
||||
struct usb_endpoint_descriptor *isoout; /* Bulk OUT endpoint */
|
||||
struct usbh_urb intin_urb; /* INTR IN urb */
|
||||
struct usbh_urb *isoin_urb; /* Bulk IN urb */
|
||||
struct usbh_urb *isoout_urb; /* Bulk OUT urb */
|
||||
uint8_t num_of_intf_altsettings;
|
||||
#endif
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int usbh_bluetooth_hci_write(uint8_t hci_type, uint8_t *buffer, uint32_t buflen);
|
||||
void usbh_bluetooth_hci_read_callback(uint8_t *data, uint32_t len);
|
||||
#ifdef CONFIG_USBHOST_BLUETOOTH_HCI_H4
|
||||
void usbh_bluetooth_hci_rx_thread(void *argument);
|
||||
#else
|
||||
void usbh_bluetooth_hci_evt_rx_thread(void *argument);
|
||||
void usbh_bluetooth_hci_acl_rx_thread(void *argument);
|
||||
#endif
|
||||
|
||||
void usbh_bluetooth_run(struct usbh_bluetooth *bluetooth_class);
|
||||
void usbh_bluetooth_stop(struct usbh_bluetooth *bluetooth_class);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_BLUETOOTH_H */
|
@@ -0,0 +1,603 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include "usbh_core.h"
|
||||
#include "usbh_rndis.h"
|
||||
#include "rndis_protocol.h"
|
||||
|
||||
#undef USB_DBG_TAG
|
||||
#define USB_DBG_TAG "usbh_rndis"
|
||||
#include "usb_log.h"
|
||||
|
||||
#define DEV_FORMAT "/dev/rndis"
|
||||
|
||||
USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_buf[4096];
|
||||
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE 1514
|
||||
#define CONFIG_USBHOST_RNDIS_ETH_MSG_SIZE (CONFIG_USBHOST_RNDIS_ETH_MAX_FRAME_SIZE + 44)
|
||||
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_rx_buffer[CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE];
|
||||
static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_tx_buffer[CONFIG_USBHOST_RNDIS_ETH_MAX_TX_SIZE];
|
||||
// static USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t g_rndis_inttx_buffer[16];
|
||||
|
||||
static struct usbh_rndis g_rndis_class;
|
||||
|
||||
static int usbh_rndis_get_notification(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
// int ret;
|
||||
// struct usbh_urb *urb = &rndis_class->intin_urb;
|
||||
|
||||
// usbh_int_urb_fill(urb, rndis_class->hport, rndis_class->intin, g_rndis_inttx_buffer, rndis_class->intin->wMaxPacketSize, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
// ret = usbh_submit_urb(urb);
|
||||
// if (ret == 0) {
|
||||
// ret = urb->actual_length;
|
||||
// }
|
||||
// return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_rndis_init_msg_transfer(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret = 0;
|
||||
rndis_initialize_msg_t *cmd;
|
||||
rndis_initialize_cmplt_t *resp;
|
||||
|
||||
if (!rndis_class || !rndis_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = rndis_class->hport->setup;
|
||||
|
||||
cmd = (rndis_initialize_msg_t *)g_rndis_buf;
|
||||
|
||||
cmd->MessageType = REMOTE_NDIS_INITIALIZE_MSG;
|
||||
cmd->MessageLength = sizeof(rndis_initialize_msg_t);
|
||||
cmd->RequestId = rndis_class->request_id++;
|
||||
cmd->MajorVersion = 1;
|
||||
cmd->MinorVersion = 0;
|
||||
cmd->MaxTransferSize = 0x4000;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = sizeof(rndis_initialize_msg_t);
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("rndis_initialize_msg_t send error, ret: %d\r\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
usbh_rndis_get_notification(rndis_class);
|
||||
|
||||
resp = (rndis_initialize_cmplt_t *)g_rndis_buf;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("rndis_initialize_cmplt_t recv error, ret: %d\r\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rndis_class->max_transfer_pkts = resp->MaxPacketsPerTransfer;
|
||||
rndis_class->max_transfer_size = resp->MaxTransferSize;
|
||||
USB_LOG_INFO("MaxPacketsPerTransfer:%d\r\n", resp->MaxPacketsPerTransfer);
|
||||
USB_LOG_INFO("MaxTransferSize:%d\r\n", resp->MaxTransferSize);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_rndis_query_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint32_t query_len, uint8_t *info, uint32_t *info_len)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret = 0;
|
||||
rndis_query_msg_t *cmd;
|
||||
rndis_query_cmplt_t *resp;
|
||||
|
||||
if (!rndis_class || !rndis_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = rndis_class->hport->setup;
|
||||
|
||||
cmd = (rndis_query_msg_t *)g_rndis_buf;
|
||||
|
||||
cmd->MessageType = REMOTE_NDIS_QUERY_MSG;
|
||||
cmd->MessageLength = query_len + sizeof(rndis_query_msg_t);
|
||||
cmd->RequestId = rndis_class->request_id++;
|
||||
cmd->Oid = oid;
|
||||
cmd->InformationBufferLength = query_len;
|
||||
cmd->InformationBufferOffset = 20;
|
||||
cmd->DeviceVcHandle = 0;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = query_len + sizeof(rndis_query_msg_t);
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("oid:%08x send error, ret: %d\r\n", (unsigned int)oid, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
usbh_rndis_get_notification(rndis_class);
|
||||
|
||||
resp = (rndis_query_cmplt_t *)g_rndis_buf;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(info, ((uint8_t *)resp + sizeof(rndis_query_cmplt_t)), resp->InformationBufferLength);
|
||||
*info_len = resp->InformationBufferLength;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_rndis_set_msg_transfer(struct usbh_rndis *rndis_class, uint32_t oid, uint8_t *info, uint32_t info_len)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret = 0;
|
||||
rndis_set_msg_t *cmd;
|
||||
rndis_set_cmplt_t *resp;
|
||||
|
||||
if (!rndis_class || !rndis_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = rndis_class->hport->setup;
|
||||
|
||||
cmd = (rndis_set_msg_t *)g_rndis_buf;
|
||||
|
||||
cmd->MessageType = REMOTE_NDIS_SET_MSG;
|
||||
cmd->MessageLength = info_len + sizeof(rndis_set_msg_t);
|
||||
cmd->RequestId = rndis_class->request_id++;
|
||||
cmd->Oid = oid;
|
||||
cmd->InformationBufferLength = info_len;
|
||||
cmd->InformationBufferOffset = 20;
|
||||
cmd->DeviceVcHandle = 0;
|
||||
|
||||
memcpy(((uint8_t *)cmd + sizeof(rndis_set_msg_t)), info, info_len);
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = info_len + sizeof(rndis_set_msg_t);
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("oid:%08x send error, ret: %d\r\n", (unsigned int)oid, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
usbh_rndis_get_notification(rndis_class);
|
||||
|
||||
resp = (rndis_set_cmplt_t *)g_rndis_buf;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("oid:%08x recv error, ret: %d\r\n", (unsigned int)oid, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
int ret;
|
||||
uint8_t data[32];
|
||||
uint32_t data_len;
|
||||
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, 4, data, &data_len);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
|
||||
rndis_class->connect_status = true;
|
||||
} else {
|
||||
rndis_class->connect_status = false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbh_rndis_keepalive(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
struct usb_setup_packet *setup;
|
||||
int ret = 0;
|
||||
rndis_keepalive_msg_t *cmd;
|
||||
rndis_keepalive_cmplt_t *resp;
|
||||
|
||||
if (!rndis_class || !rndis_class->hport) {
|
||||
return -USB_ERR_INVAL;
|
||||
}
|
||||
setup = rndis_class->hport->setup;
|
||||
|
||||
cmd = (rndis_keepalive_msg_t *)g_rndis_buf;
|
||||
|
||||
cmd->MessageType = REMOTE_NDIS_KEEPALIVE_MSG;
|
||||
cmd->MessageLength = sizeof(rndis_keepalive_msg_t);
|
||||
cmd->RequestId = rndis_class->request_id++;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_SEND_ENCAPSULATED_COMMAND;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = sizeof(rndis_keepalive_msg_t);
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)cmd);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("keepalive send error, ret: %d\r\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
usbh_rndis_get_notification(rndis_class);
|
||||
|
||||
resp = (rndis_keepalive_cmplt_t *)g_rndis_buf;
|
||||
|
||||
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE;
|
||||
setup->bRequest = CDC_REQUEST_GET_ENCAPSULATED_RESPONSE;
|
||||
setup->wValue = 0;
|
||||
setup->wIndex = 0;
|
||||
setup->wLength = 4096;
|
||||
|
||||
ret = usbh_control_transfer(rndis_class->hport, setup, (uint8_t *)resp);
|
||||
if (ret < 0) {
|
||||
USB_LOG_ERR("keepalive recv error, ret: %d\r\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_rndis_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
struct usb_endpoint_descriptor *ep_desc;
|
||||
int ret;
|
||||
uint32_t *oid_support_list;
|
||||
unsigned int oid = 0;
|
||||
unsigned int oid_num = 0;
|
||||
uint32_t data_len;
|
||||
uint8_t tmp_buffer[512];
|
||||
uint8_t data[32];
|
||||
|
||||
struct usbh_rndis *rndis_class = &g_rndis_class;
|
||||
|
||||
memset(rndis_class, 0, sizeof(struct usbh_rndis));
|
||||
|
||||
rndis_class->hport = hport;
|
||||
rndis_class->ctrl_intf = intf;
|
||||
rndis_class->data_intf = intf + 1;
|
||||
|
||||
hport->config.intf[intf].priv = rndis_class;
|
||||
hport->config.intf[intf + 1].priv = NULL;
|
||||
|
||||
// ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
|
||||
// USBH_EP_INIT(rndis_class->intin, ep_desc);
|
||||
|
||||
for (uint8_t i = 0; i < hport->config.intf[intf + 1].altsetting[0].intf_desc.bNumEndpoints; i++) {
|
||||
ep_desc = &hport->config.intf[intf + 1].altsetting[0].ep[i].ep_desc;
|
||||
|
||||
if (ep_desc->bEndpointAddress & 0x80) {
|
||||
USBH_EP_INIT(rndis_class->bulkin, ep_desc);
|
||||
} else {
|
||||
USBH_EP_INIT(rndis_class->bulkout, ep_desc);
|
||||
}
|
||||
}
|
||||
|
||||
ret = usbh_rndis_init_msg_transfer(rndis_class);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
USB_LOG_INFO("rndis init success\r\n");
|
||||
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_SUPPORTED_LIST, 0, tmp_buffer, &data_len);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
oid_num = (data_len / 4);
|
||||
USB_LOG_INFO("rndis query OID_GEN_SUPPORTED_LIST success,oid num :%d\r\n", oid_num);
|
||||
|
||||
oid_support_list = (uint32_t *)tmp_buffer;
|
||||
|
||||
for (uint8_t i = 0; i < oid_num; i++) {
|
||||
oid = oid_support_list[i];
|
||||
switch (oid) {
|
||||
case OID_GEN_PHYSICAL_MEDIUM:
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_PHYSICAL_MEDIUM, 4, data, &data_len);
|
||||
if (ret < 0) {
|
||||
goto query_errorout;
|
||||
}
|
||||
break;
|
||||
case OID_GEN_MAXIMUM_FRAME_SIZE:
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MAXIMUM_FRAME_SIZE, 4, data, &data_len);
|
||||
if (ret < 0) {
|
||||
goto query_errorout;
|
||||
}
|
||||
break;
|
||||
case OID_GEN_LINK_SPEED:
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_LINK_SPEED, 4, data, &data_len);
|
||||
if (ret < 0) {
|
||||
goto query_errorout;
|
||||
}
|
||||
|
||||
memcpy(&rndis_class->link_speed, data, 4);
|
||||
break;
|
||||
case OID_GEN_MEDIA_CONNECT_STATUS:
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_GEN_MEDIA_CONNECT_STATUS, 4, data, &data_len);
|
||||
if (ret < 0) {
|
||||
goto query_errorout;
|
||||
}
|
||||
if (NDIS_MEDIA_STATE_CONNECTED == data[0]) {
|
||||
rndis_class->connect_status = true;
|
||||
} else {
|
||||
rndis_class->connect_status = false;
|
||||
}
|
||||
break;
|
||||
case OID_802_3_MAXIMUM_LIST_SIZE:
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_MAXIMUM_LIST_SIZE, 4, data, &data_len);
|
||||
if (ret < 0) {
|
||||
goto query_errorout;
|
||||
}
|
||||
break;
|
||||
case OID_802_3_CURRENT_ADDRESS:
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_CURRENT_ADDRESS, 6, data, &data_len);
|
||||
if (ret < 0) {
|
||||
goto query_errorout;
|
||||
}
|
||||
|
||||
for (uint8_t j = 0; j < 6; j++) {
|
||||
rndis_class->mac[j] = data[j];
|
||||
}
|
||||
break;
|
||||
case OID_802_3_PERMANENT_ADDRESS:
|
||||
ret = usbh_rndis_query_msg_transfer(rndis_class, OID_802_3_PERMANENT_ADDRESS, 6, data, &data_len);
|
||||
if (ret < 0) {
|
||||
goto query_errorout;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
USB_LOG_WRN("Ignore rndis query iod:%08x\r\n", oid);
|
||||
continue;
|
||||
}
|
||||
USB_LOG_INFO("rndis query iod:%08x success\r\n", oid);
|
||||
}
|
||||
|
||||
uint32_t packet_filter = 0x0f;
|
||||
usbh_rndis_set_msg_transfer(rndis_class, OID_GEN_CURRENT_PACKET_FILTER, (uint8_t *)&packet_filter, 4);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
USB_LOG_INFO("rndis set OID_GEN_CURRENT_PACKET_FILTER success\r\n");
|
||||
|
||||
uint8_t multicast_list[6] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x01 };
|
||||
usbh_rndis_set_msg_transfer(rndis_class, OID_802_3_MULTICAST_LIST, multicast_list, 6);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
USB_LOG_INFO("rndis set OID_802_3_MULTICAST_LIST success\r\n");
|
||||
|
||||
USB_LOG_INFO("rndis MAC address %02x:%02x:%02x:%02x:%02x:%02x\r\n",
|
||||
rndis_class->mac[0],
|
||||
rndis_class->mac[1],
|
||||
rndis_class->mac[2],
|
||||
rndis_class->mac[3],
|
||||
rndis_class->mac[4],
|
||||
rndis_class->mac[5]);
|
||||
|
||||
strncpy(hport->config.intf[intf].devname, DEV_FORMAT, CONFIG_USBHOST_DEV_NAMELEN);
|
||||
|
||||
USB_LOG_INFO("Register RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_rndis_run(rndis_class);
|
||||
return ret;
|
||||
query_errorout:
|
||||
USB_LOG_ERR("rndis query iod:%08x error\r\n", oid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int usbh_rndis_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
struct usbh_rndis *rndis_class = (struct usbh_rndis *)hport->config.intf[intf].priv;
|
||||
|
||||
if (rndis_class) {
|
||||
if (rndis_class->bulkin) {
|
||||
usbh_kill_urb(&rndis_class->bulkin_urb);
|
||||
}
|
||||
|
||||
if (rndis_class->bulkout) {
|
||||
usbh_kill_urb(&rndis_class->bulkout_urb);
|
||||
}
|
||||
|
||||
// if (rndis_class->intin) {
|
||||
// usbh_kill_urb(&rndis_class->intin_urb);
|
||||
// }
|
||||
|
||||
if (hport->config.intf[intf].devname[0] != '\0') {
|
||||
USB_LOG_INFO("Unregister RNDIS Class:%s\r\n", hport->config.intf[intf].devname);
|
||||
usbh_rndis_stop(rndis_class);
|
||||
}
|
||||
|
||||
memset(rndis_class, 0, sizeof(struct usbh_rndis));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void usbh_rndis_rx_thread(void *argument)
|
||||
{
|
||||
uint32_t g_rndis_rx_length;
|
||||
int ret;
|
||||
uint32_t pmg_offset;
|
||||
rndis_data_packet_t *pmsg;
|
||||
rndis_data_packet_t temp;
|
||||
#if CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE <= (16 * 1024)
|
||||
uint32_t transfer_size = CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE;
|
||||
#else
|
||||
uint32_t transfer_size = (16 * 1024);
|
||||
#endif
|
||||
|
||||
USB_LOG_INFO("Create rndis rx thread\r\n");
|
||||
// clang-format off
|
||||
find_class:
|
||||
// clang-format on
|
||||
g_rndis_class.connect_status = false;
|
||||
if (usbh_find_class_instance("/dev/rndis") == NULL) {
|
||||
goto delete;
|
||||
}
|
||||
|
||||
while (g_rndis_class.connect_status == false) {
|
||||
ret = usbh_rndis_get_connect_status(&g_rndis_class);
|
||||
if (ret < 0) {
|
||||
usb_osal_msleep(100);
|
||||
goto find_class;
|
||||
}
|
||||
usb_osal_msleep(128);
|
||||
}
|
||||
|
||||
g_rndis_rx_length = 0;
|
||||
while (1) {
|
||||
usbh_bulk_urb_fill(&g_rndis_class.bulkin_urb, g_rndis_class.hport, g_rndis_class.bulkin, &g_rndis_rx_buffer[g_rndis_rx_length], transfer_size, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
ret = usbh_submit_urb(&g_rndis_class.bulkin_urb);
|
||||
if (ret < 0) {
|
||||
goto find_class;
|
||||
}
|
||||
|
||||
g_rndis_rx_length += g_rndis_class.bulkin_urb.actual_length;
|
||||
|
||||
/* A transfer is complete because last packet is a short packet.
|
||||
* Short packet is not zero, match g_rndis_rx_length % USB_GET_MAXPACKETSIZE(g_rndis_class.bulkin->wMaxPacketSize).
|
||||
* Short packet cannot be zero.
|
||||
*/
|
||||
if (g_rndis_rx_length % USB_GET_MAXPACKETSIZE(g_rndis_class.bulkin->wMaxPacketSize)) {
|
||||
pmg_offset = 0;
|
||||
|
||||
uint32_t total_len = g_rndis_rx_length;
|
||||
|
||||
while (g_rndis_rx_length > 0) {
|
||||
USB_LOG_DBG("rxlen:%d\r\n", g_rndis_rx_length);
|
||||
|
||||
pmsg = (rndis_data_packet_t *)(g_rndis_rx_buffer + pmg_offset);
|
||||
|
||||
/* Not word-aligned case */
|
||||
if (pmg_offset & 0x3) {
|
||||
usb_memcpy(&temp, pmsg, sizeof(rndis_data_packet_t));
|
||||
pmsg = &temp;
|
||||
}
|
||||
|
||||
if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) {
|
||||
uint8_t *buf = (uint8_t *)(g_rndis_rx_buffer + pmg_offset + sizeof(rndis_generic_msg_t) + pmsg->DataOffset);
|
||||
|
||||
usbh_rndis_eth_input(buf, pmsg->DataLength);
|
||||
pmg_offset += pmsg->MessageLength;
|
||||
g_rndis_rx_length -= pmsg->MessageLength;
|
||||
|
||||
/* drop the last dummy byte, it is a short packet to tell us we have received a multiple of wMaxPacketSize */
|
||||
if (g_rndis_rx_length < 4) {
|
||||
g_rndis_rx_length = 0;
|
||||
}
|
||||
} else {
|
||||
USB_LOG_ERR("offset:%d,remain:%d,total:%d\r\n", pmg_offset, g_rndis_rx_length, total_len);
|
||||
g_rndis_rx_length = 0;
|
||||
USB_LOG_ERR("Error rndis packet message\r\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#if CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE <= (16 * 1024)
|
||||
if (g_rndis_rx_length == CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE) {
|
||||
#else
|
||||
if ((g_rndis_rx_length + (16 * 1024)) > CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE) {
|
||||
#endif
|
||||
USB_LOG_ERR("Rx packet is overflow, please ruduce tcp window size or increase CONFIG_USBHOST_RNDIS_ETH_MAX_RX_SIZE\r\n");
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
delete:
|
||||
USB_LOG_INFO("Delete rndis rx thread\r\n");
|
||||
usb_osal_thread_delete(NULL);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
uint8_t *usbh_rndis_get_eth_txbuf(void)
|
||||
{
|
||||
return (g_rndis_tx_buffer + sizeof(rndis_data_packet_t));
|
||||
}
|
||||
|
||||
int usbh_rndis_eth_output(uint32_t buflen)
|
||||
{
|
||||
rndis_data_packet_t *hdr;
|
||||
uint32_t len;
|
||||
|
||||
if (g_rndis_class.connect_status == false) {
|
||||
return -USB_ERR_NOTCONN;
|
||||
}
|
||||
|
||||
hdr = (rndis_data_packet_t *)g_rndis_tx_buffer;
|
||||
memset(hdr, 0, sizeof(rndis_data_packet_t));
|
||||
|
||||
hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
|
||||
hdr->MessageLength = sizeof(rndis_data_packet_t) + buflen;
|
||||
hdr->DataOffset = sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t);
|
||||
hdr->DataLength = buflen;
|
||||
|
||||
len = hdr->MessageLength;
|
||||
/* if message length is the multiple of wMaxPacketSize, we should add a short packet to tell device transfer is over. */
|
||||
if (!(len % g_rndis_class.bulkout->wMaxPacketSize)) {
|
||||
len += 1;
|
||||
}
|
||||
|
||||
USB_LOG_DBG("txlen:%d\r\n", len);
|
||||
|
||||
usbh_bulk_urb_fill(&g_rndis_class.bulkout_urb, g_rndis_class.hport, g_rndis_class.bulkout, g_rndis_tx_buffer, len, USB_OSAL_WAITING_FOREVER, NULL, NULL);
|
||||
return usbh_submit_urb(&g_rndis_class.bulkout_urb);
|
||||
}
|
||||
|
||||
__WEAK void usbh_rndis_run(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
}
|
||||
|
||||
__WEAK void usbh_rndis_stop(struct usbh_rndis *rndis_class)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct usbh_class_driver rndis_class_driver = {
|
||||
.driver_name = "rndis",
|
||||
.connect = usbh_rndis_connect,
|
||||
.disconnect = usbh_rndis_disconnect
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info rndis_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_WIRELESS,
|
||||
.subclass = 0x01,
|
||||
.protocol = 0x03,
|
||||
.id_table = NULL,
|
||||
.class_driver = &rndis_class_driver
|
||||
};
|
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2022, sakumisu
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef USBH_RNDIS_H
|
||||
#define USBH_RNDIS_H
|
||||
|
||||
#include "usb_cdc.h"
|
||||
|
||||
struct usbh_rndis {
|
||||
struct usbh_hubport *hport;
|
||||
struct usb_endpoint_descriptor *bulkin; /* Bulk IN endpoint */
|
||||
struct usb_endpoint_descriptor *bulkout; /* Bulk OUT endpoint */
|
||||
struct usb_endpoint_descriptor *intin; /* INTR endpoint */
|
||||
struct usbh_urb bulkin_urb; /* Bulk IN urb */
|
||||
struct usbh_urb bulkout_urb; /* Bulk OUT urb */
|
||||
struct usbh_urb intin_urb; /* INTR IN urb */
|
||||
|
||||
uint8_t ctrl_intf; /* Control interface number */
|
||||
uint8_t data_intf; /* Data interface number */
|
||||
uint8_t minor;
|
||||
|
||||
uint32_t request_id;
|
||||
uint32_t tx_offset;
|
||||
uint32_t max_transfer_pkts; /* max packets in one transfer */
|
||||
uint32_t max_transfer_size; /* max size in one transfer */
|
||||
|
||||
uint32_t link_speed;
|
||||
bool connect_status;
|
||||
uint8_t mac[6];
|
||||
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int usbh_rndis_get_connect_status(struct usbh_rndis *rndis_class);
|
||||
int usbh_rndis_keepalive(struct usbh_rndis *rndis_class);
|
||||
|
||||
void usbh_rndis_run(struct usbh_rndis *rndis_class);
|
||||
void usbh_rndis_stop(struct usbh_rndis *rndis_class);
|
||||
|
||||
uint8_t *usbh_rndis_get_eth_txbuf(void);
|
||||
int usbh_rndis_eth_output(uint32_t buflen);
|
||||
void usbh_rndis_eth_input(uint8_t *buf, uint32_t buflen);
|
||||
void usbh_rndis_rx_thread(void *argument);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* USBH_RNDIS_H */
|
Reference in New Issue
Block a user