Commit 33e98512 authored by Andrei Emeltchenko's avatar Andrei Emeltchenko Committed by Anas Nashif
Browse files

usb: rndis: Add Remote NDIS protocol handling



Add implementation of Microsoft Remote NDIS USB Ethernet protocol.

Signed-off-by: default avatarAndrei Emeltchenko <andrei.emeltchenko@intel.com>
parent 337601b4
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -19,3 +19,8 @@ zephyr_library_sources_ifdef(
  CONFIG_USB_DEVICE_NETWORK_ECM
  function_ecm.c
  )

zephyr_library_sources_ifdef(
  CONFIG_USB_DEVICE_NETWORK_RNDIS
  function_rndis.c
  )
+37 −0
Original line number Diff line number Diff line
@@ -78,4 +78,41 @@ config USB_DEVICE_NETWORK_ECM_MAC

endif # USB_DEVICE_NETWORK_ECM

if USB_DEVICE_NETWORK_RNDIS

config RNDIS_INT_EP_ADDR
	hex "RNDIS Interrupt Endpoint address"
	default 0x83
	range 0x81 0x8F
	help
	RNDIS interrupt endpoint address

config RNDIS_IN_EP_ADDR
	hex "RNDIS BULK IN Endpoint address"
	default 0x82
	range 0x81 0x8F
	help
	RNDIS bulk IN endpoint address

config RNDIS_OUT_EP_ADDR
	hex "RNDIS BULK OUT Endpoint address"
	default 0x01
	range 0x01 0x0F
	help
	RNDIS bulk OUT endpoint address

config RNDIS_INTERRUPT_EP_MPS
	int
	default 16
	help
	RNDIS interrupt endpoint size

config RNDIS_BULK_EP_MPS
	int
	default 64
	help
	RNDIS bulk endpoint size

endif # USB_DEVICE_NETWORK_RNDIS

endmenu # USB Device Networking support
+1054 −0

File added.

Preview size limit exceeded, changes collapsed.

+185 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2017 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

void rndis_clean(void);

/*
 * RNDIS definitons
 */

#define RNDIS_GEN_MAX_TOTAL_SIZE	1558

#define RNDIS_MAJOR_VERSION		1
#define RNDIS_MINOR_VERSION		0

#define COMPLETE			BIT(31)

#define RNDIS_DATA_PACKET		0x01
#define RNDIS_CMD_INITIALIZE		0x02
#define RNDIS_CMD_INITIALIZE_COMPLETE	(RNDIS_CMD_INITIALIZE | COMPLETE)
#define RNDIS_CMD_HALT			0x03
#define RNDIS_CMD_QUERY			0x04
#define RNDIS_CMD_QUERY_COMPLETE	(RNDIS_CMD_QUERY | COMPLETE)
#define RNDIS_CMD_SET			0x05
#define RNDIS_CMD_SET_COMPLETE		(RNDIS_CMD_SET | COMPLETE)
#define RNDIS_CMD_RESET			0x06
#define RNDIS_CMD_RESET_COMPLETE	(RNDIS_CMD_RESET | COMPLETE)
#define RNDIS_CMD_INDICATE		0x07
#define RNDIS_CMD_KEEPALIVE		0x08
#define RNDIS_CMD_KEEPALIVE_COMPLETE	(RNDIS_CMD_KEEPALIVE | COMPLETE)

#define RNDIS_CMD_STATUS_SUCCESS	0
#define RNDIS_CMD_STATUS_NOT_SUPP	0xC00000BB

#define RNDIS_FLAG_CONNECTIONLESS	BIT(0)

#define RNDIS_MEDIUM_WIRED_ETHERNET	0

struct rndis_init_cmd {
	u32_t type;
	u32_t len;
	u32_t req_id;
	u32_t major_ver;
	u32_t minor_version;
	u32_t max_transfer_size;
} __packed;

struct rndis_init_cmd_complete {
	u32_t type;
	u32_t len;
	u32_t req_id;
	u32_t status;
	u32_t major_ver;
	u32_t minor_ver;
	u32_t flags;
	u32_t medium;
	u32_t max_packets;
	u32_t max_transfer_size;
	u32_t pkt_align_factor;
	u32_t __reserved[2];
} __packed;

struct rndis_query_cmd {
	u32_t type;
	u32_t len;
	u32_t req_id;
	u32_t object_id;
	u32_t buf_len;
	u32_t buf_offset;
	u32_t vc_handle;	/* Reserved for connection-oriented devices */
} __packed;

/* Specifies RNDS objects for Query and Set */
#define RNDIS_OBJECT_ID_GEN_SUPP_LIST		0x00010101
#define RNDIS_OBJECT_ID_GEN_HW_STATUS		0x00010102
#define RNDIS_OBJECT_ID_GEN_SUPP_MEDIA		0x00010103
#define RNDIS_OBJECT_ID_GEN_IN_USE_MEDIA	0x00010104

#define RNDIS_OBJECT_ID_GEN_MAX_FRAME_SIZE	0x00010106
#define RNDIS_OBJECT_ID_GEN_LINK_SPEED		0x00010107
#define RNDIS_OBJECT_ID_GEN_BLOCK_TX_SIZE	0x0001010A
#define RNDIS_OBJECT_ID_GEN_BLOCK_RX_SIZE	0x0001010B

#define RNDIS_OBJECT_ID_GEN_VENDOR_ID		0x0001010C
#define RNDIS_OBJECT_ID_GEN_VENDOR_DESC		0x0001010D
#define RNDIS_OBJECT_ID_GEN_VENDOR_DRV_VER	0x00010116

#define RNDIS_OBJECT_ID_GEN_PKT_FILTER		0x0001010E
#define RNDIS_OBJECT_ID_GEN_MAX_TOTAL_SIZE	0x00010111
#define RNDIS_OBJECT_ID_GEN_CONN_MEDIA_STATUS	0x00010114

#define RNDIS_OBJECT_ID_GEN_PHYSICAL_MEDIUM	0x00010202

#define RNDIS_OBJECT_ID_GEN_TRANSMIT_OK		0x00020101
#define RNDIS_OBJECT_ID_GEN_RECEIVE_OK		0x00020102
#define RNDIS_OBJECT_ID_GEN_TRANSMIT_ERROR	0x00020103
#define RNDIS_OBJECT_ID_GEN_RECEIVE_ERROR	0x00020104
#define RNDIS_OBJECT_ID_GEN_RECEIVE_NO_BUF	0x00020105

/* The address of the NIC encoded in the hardware */
#define RNDIS_OBJECT_ID_802_3_PERMANENT_ADDRESS	0x01010101
#define RNDIS_OBJECT_ID_802_3_CURR_ADDRESS	0x01010102
#define RNDIS_OBJECT_ID_802_3_MCAST_LIST	0x01010103
#define RNDIS_OBJECT_ID_802_3_MAX_LIST_SIZE	0x01010104
#define RNDIS_OBJECT_ID_802_3_MAC_OPTIONS	0x01010105

/* Media types used */
#define RNDIS_PHYSICAL_MEDIUM_TYPE_UNSPECIFIED	0x00

/* Connection Media states */
#define RNDIS_OBJECT_ID_MEDIA_CONNECTED		0x00
#define RNDIS_OBJECT_ID_MEDIA_DISCONNECTED	0x01

#define RNDIS_STATUS_CONNECT_MEDIA		0x4001000B
#define RNDIS_STATUS_DISCONNECT_MEDIA		0x4001000C

struct rndis_query_cmd_complete {
	u32_t type;
	u32_t len;
	u32_t req_id;
	u32_t status;
	u32_t buf_len;
	u32_t buf_offset;
} __packed;

struct rndis_set_cmd {
	u32_t type;
	u32_t len;
	u32_t req_id;
	u32_t object_id;
	u32_t buf_len;
	u32_t buf_offset;
	u32_t vc_handle;	/* Reserved for connection-oriented devices */
} __packed;

struct rndis_set_cmd_complete {
	u32_t type;
	u32_t len;
	u32_t req_id;
	u32_t status;
} __packed;

struct rndis_payload_packet {
	u32_t type;
	u32_t len;
	u32_t payload_offset;
	u32_t payload_len;
	u32_t oob_payload_offset;
	u32_t oob_payload_len;
	u32_t oob_num;
	u32_t pkt_payload_offset;
	u32_t pkt_payload_len;
	u32_t vc_handle;
	u32_t __reserved;
} __packed;

struct rndis_keepalive_cmd {
	u32_t type;
	u32_t len;
	u32_t req_id;
} __packed;

struct rndis_keepalive_cmd_complete {
	u32_t type;
	u32_t len;
	u32_t req_id;
	u32_t status;
} __packed;

struct rndis_media_status_indicate {
	u32_t type;
	u32_t len;
	u32_t status;
	u32_t buf_len;
	u32_t buf_offset;
} __packed;

struct rndis_reset_cmd_complete {
	u32_t type;
	u32_t len;
	u32_t status;
	u32_t addr_reset;
} __packed;
+19 −6
Original line number Diff line number Diff line
@@ -10,14 +10,19 @@
#define SYS_LOG_DOMAIN "netusb"
#include <logging/sys_log.h>

/* Enable verbose debug printing extra hexdumps */
#define VERBOSE_DEBUG	0

/* This enables basic hexdumps */
#define NET_LOG_ENABLED	0
#include <net_private.h>

#include <init.h>

#include <usb_device.h>
#include <usb_common.h>
#include <class/usb_cdc.h>

#include <net_private.h>

#include "../../usb_descriptor.h"
#include "../../composite.h"
#include "netusb.h"
@@ -52,8 +57,8 @@ void netusb_recv(struct net_pkt *pkt)
{
	SYS_LOG_DBG("Recv pkt, len %u", net_pkt_get_len(pkt));

	if (net_recv_data(netusb.iface, pkt)) {
		SYS_LOG_ERR("Queueing packet %p failed", pkt);
	if (net_recv_data(netusb.iface, pkt) < 0) {
		SYS_LOG_ERR("Packet %p dropped by NET stack", pkt);
		net_pkt_unref(pkt);
	}
}
@@ -204,6 +209,7 @@ int try_write(u8_t ep, u8_t *data, u16_t len)
			break;
		/* TODO: Handle other error codes */
		default:
			SYS_LOG_WRN("Error writing to ep 0x%x ret %d", ep, ret);
			return ret;
		}

@@ -234,8 +240,15 @@ static void netusb_init(struct net_if *iface)

	net_if_down(iface);

/*
 * TODO: Add multi-function configuration
 */
#if defined(CONFIG_USB_DEVICE_NETWORK_ECM)
	netusb.func = &ecm_function;
#elif defined(CONFIG_USB_DEVICE_NETWORK_RNDIS)
	netusb.func = &rndis_function;
#else
#error Unknown USB Device Networking function
#endif
	if (netusb.func->init && netusb.func->init()) {
		SYS_LOG_ERR("Initialization failed");
Loading