Commit 6c9f886ceae5b998dc2b9af2bf77666941689bce

Authored by balrog
1 parent e6bf7d70

Add CDC-Ethernet usb NIC (original patch from Thomas Sailer).


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4884 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile
... ... @@ -60,7 +60,8 @@ OBJS+=ssd0303.o ssd0323.o ads7846.o stellaris_input.o twl92230.o
60 60 OBJS+=tmp105.o lm832x.o
61 61 OBJS+=scsi-disk.o cdrom.o
62 62 OBJS+=scsi-generic.o
63   -OBJS+=usb.o usb-hub.o usb-linux.o usb-hid.o usb-msd.o usb-wacom.o usb-serial.o
  63 +OBJS+=usb.o usb-hub.o usb-linux.o usb-hid.o usb-msd.o usb-wacom.o
  64 +OBJS+=usb-serial.o usb-net.o
64 65 OBJS+=sd.o ssi-sd.o
65 66  
66 67 ifdef CONFIG_BRLAPI
... ...
hw/usb-net.c 0 → 100644
  1 +/*
  2 + * QEMU USB Net devices
  3 + *
  4 + * Copyright (c) 2006 Thomas Sailer
  5 + * Copyright (c) 2008 Andrzej Zaborowski
  6 + *
  7 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  8 + * of this software and associated documentation files (the "Software"), to deal
  9 + * in the Software without restriction, including without limitation the rights
  10 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 + * copies of the Software, and to permit persons to whom the Software is
  12 + * furnished to do so, subject to the following conditions:
  13 + *
  14 + * The above copyright notice and this permission notice shall be included in
  15 + * all copies or substantial portions of the Software.
  16 + *
  17 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23 + * THE SOFTWARE.
  24 + */
  25 +
  26 +#include "qemu-common.h"
  27 +#include "usb.h"
  28 +#include "net.h"
  29 +#include "audio/sys-queue.h"
  30 +
  31 +/*#define TRAFFIC_DEBUG*/
  32 +/* Thanks to NetChip Technologies for donating this product ID.
  33 + * It's for devices with only CDC Ethernet configurations.
  34 + */
  35 +#define CDC_VENDOR_NUM 0x0525 /* NetChip */
  36 +#define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */
  37 +/* For hardware that can talk RNDIS and either of the above protocols,
  38 + * use this ID ... the windows INF files will know it.
  39 + */
  40 +#define RNDIS_VENDOR_NUM 0x0525 /* NetChip */
  41 +#define RNDIS_PRODUCT_NUM 0xa4a2 /* Ethernet/RNDIS Gadget */
  42 +
  43 +enum usbstring_idx {
  44 + STRING_MANUFACTURER = 1,
  45 + STRING_PRODUCT,
  46 + STRING_ETHADDR,
  47 + STRING_DATA,
  48 + STRING_CONTROL,
  49 + STRING_RNDIS_CONTROL,
  50 + STRING_CDC,
  51 + STRING_SUBSET,
  52 + STRING_RNDIS,
  53 + STRING_SERIALNUMBER,
  54 +};
  55 +
  56 +#define DEV_CONFIG_VALUE 1 /* CDC or a subset */
  57 +#define DEV_RNDIS_CONFIG_VALUE 2 /* RNDIS; optional */
  58 +
  59 +#define USB_CDC_SUBCLASS_ACM 0x02
  60 +#define USB_CDC_SUBCLASS_ETHERNET 0x06
  61 +
  62 +#define USB_CDC_PROTO_NONE 0
  63 +#define USB_CDC_ACM_PROTO_VENDOR 0xff
  64 +
  65 +#define USB_CDC_HEADER_TYPE 0x00 /* header_desc */
  66 +#define USB_CDC_CALL_MANAGEMENT_TYPE 0x01 /* call_mgmt_descriptor */
  67 +#define USB_CDC_ACM_TYPE 0x02 /* acm_descriptor */
  68 +#define USB_CDC_UNION_TYPE 0x06 /* union_desc */
  69 +#define USB_CDC_ETHERNET_TYPE 0x0f /* ether_desc */
  70 +
  71 +#define USB_DT_CS_INTERFACE 0x24
  72 +#define USB_DT_CS_ENDPOINT 0x25
  73 +
  74 +#define ClassInterfaceRequest \
  75 + ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
  76 +#define ClassInterfaceOutRequest \
  77 + ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
  78 +
  79 +#define USB_CDC_SEND_ENCAPSULATED_COMMAND 0x00
  80 +#define USB_CDC_GET_ENCAPSULATED_RESPONSE 0x01
  81 +#define USB_CDC_REQ_SET_LINE_CODING 0x20
  82 +#define USB_CDC_REQ_GET_LINE_CODING 0x21
  83 +#define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22
  84 +#define USB_CDC_REQ_SEND_BREAK 0x23
  85 +#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40
  86 +#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER 0x41
  87 +#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER 0x42
  88 +#define USB_CDC_SET_ETHERNET_PACKET_FILTER 0x43
  89 +#define USB_CDC_GET_ETHERNET_STATISTIC 0x44
  90 +
  91 +#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
  92 +#define STATUS_BYTECOUNT 16 /* 8 byte header + data */
  93 +
  94 +#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */
  95 +
  96 +/*
  97 + * mostly the same descriptor as the linux gadget rndis driver
  98 + */
  99 +static const uint8_t qemu_net_dev_descriptor[] = {
  100 + 0x12, /* u8 bLength; */
  101 + USB_DT_DEVICE, /* u8 bDescriptorType; Device */
  102 + 0x00, 0x02, /* u16 bcdUSB; v2.0 */
  103 + USB_CLASS_COMM, /* u8 bDeviceClass; */
  104 + 0x00, /* u8 bDeviceSubClass; */
  105 + 0x00, /* u8 bDeviceProtocol; [ low/full only ] */
  106 + 0x40, /* u8 bMaxPacketSize0 */
  107 + RNDIS_VENDOR_NUM & 0xff, RNDIS_VENDOR_NUM >> 8, /* u16 idVendor; */
  108 + RNDIS_PRODUCT_NUM & 0xff, RNDIS_PRODUCT_NUM >> 8, /* u16 idProduct; */
  109 + 0x00, 0x00, /* u16 bcdDevice */
  110 + STRING_MANUFACTURER, /* u8 iManufacturer; */
  111 + STRING_PRODUCT, /* u8 iProduct; */
  112 + STRING_SERIALNUMBER, /* u8 iSerialNumber; */
  113 + 0x02, /* u8 bNumConfigurations; */
  114 +};
  115 +
  116 +static const uint8_t qemu_net_rndis_config_descriptor[] = {
  117 + /* Configuration Descriptor */
  118 + 0x09, /* u8 bLength */
  119 + USB_DT_CONFIG, /* u8 bDescriptorType */
  120 + 0x43, 0x00, /* le16 wTotalLength */
  121 + 0x02, /* u8 bNumInterfaces */
  122 + DEV_RNDIS_CONFIG_VALUE, /* u8 bConfigurationValue */
  123 + STRING_RNDIS, /* u8 iConfiguration */
  124 + 0xc0, /* u8 bmAttributes */
  125 + 0x32, /* u8 bMaxPower */
  126 + /* RNDIS Control Interface */
  127 + 0x09, /* u8 bLength */
  128 + USB_DT_INTERFACE, /* u8 bDescriptorType */
  129 + 0x00, /* u8 bInterfaceNumber */
  130 + 0x00, /* u8 bAlternateSetting */
  131 + 0x01, /* u8 bNumEndpoints */
  132 + USB_CLASS_COMM, /* u8 bInterfaceClass */
  133 + USB_CDC_SUBCLASS_ACM, /* u8 bInterfaceSubClass */
  134 + USB_CDC_ACM_PROTO_VENDOR, /* u8 bInterfaceProtocol */
  135 + STRING_RNDIS_CONTROL, /* u8 iInterface */
  136 + /* Header Descriptor */
  137 + 0x05, /* u8 bLength */
  138 + USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
  139 + USB_CDC_HEADER_TYPE, /* u8 bDescriptorSubType */
  140 + 0x10, 0x01, /* le16 bcdCDC */
  141 + /* Call Management Descriptor */
  142 + 0x05, /* u8 bLength */
  143 + USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
  144 + USB_CDC_CALL_MANAGEMENT_TYPE, /* u8 bDescriptorSubType */
  145 + 0x00, /* u8 bmCapabilities */
  146 + 0x01, /* u8 bDataInterface */
  147 + /* ACM Descriptor */
  148 + 0x04, /* u8 bLength */
  149 + USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
  150 + USB_CDC_ACM_TYPE, /* u8 bDescriptorSubType */
  151 + 0x00, /* u8 bmCapabilities */
  152 + /* Union Descriptor */
  153 + 0x05, /* u8 bLength */
  154 + USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
  155 + USB_CDC_UNION_TYPE, /* u8 bDescriptorSubType */
  156 + 0x00, /* u8 bMasterInterface0 */
  157 + 0x01, /* u8 bSlaveInterface0 */
  158 + /* Status Descriptor */
  159 + 0x07, /* u8 bLength */
  160 + USB_DT_ENDPOINT, /* u8 bDescriptorType */
  161 + USB_DIR_IN | 1, /* u8 bEndpointAddress */
  162 + USB_ENDPOINT_XFER_INT, /* u8 bmAttributes */
  163 + STATUS_BYTECOUNT & 0xff, STATUS_BYTECOUNT >> 8, /* le16 wMaxPacketSize */
  164 + 1 << LOG2_STATUS_INTERVAL_MSEC, /* u8 bInterval */
  165 + /* RNDIS Data Interface */
  166 + 0x09, /* u8 bLength */
  167 + USB_DT_INTERFACE, /* u8 bDescriptorType */
  168 + 0x01, /* u8 bInterfaceNumber */
  169 + 0x00, /* u8 bAlternateSetting */
  170 + 0x02, /* u8 bNumEndpoints */
  171 + USB_CLASS_CDC_DATA, /* u8 bInterfaceClass */
  172 + 0x00, /* u8 bInterfaceSubClass */
  173 + 0x00, /* u8 bInterfaceProtocol */
  174 + STRING_DATA, /* u8 iInterface */
  175 + /* Source Endpoint */
  176 + 0x07, /* u8 bLength */
  177 + USB_DT_ENDPOINT, /* u8 bDescriptorType */
  178 + USB_DIR_IN | 2, /* u8 bEndpointAddress */
  179 + USB_ENDPOINT_XFER_BULK, /* u8 bmAttributes */
  180 + 0x40, 0x00, /* le16 wMaxPacketSize */
  181 + 0x00, /* u8 bInterval */
  182 + /* Sink Endpoint */
  183 + 0x07, /* u8 bLength */
  184 + USB_DT_ENDPOINT, /* u8 bDescriptorType */
  185 + USB_DIR_OUT | 2, /* u8 bEndpointAddress */
  186 + USB_ENDPOINT_XFER_BULK, /* u8 bmAttributes */
  187 + 0x40, 0x00, /* le16 wMaxPacketSize */
  188 + 0x00 /* u8 bInterval */
  189 +};
  190 +
  191 +static const uint8_t qemu_net_cdc_config_descriptor[] = {
  192 + /* Configuration Descriptor */
  193 + 0x09, /* u8 bLength */
  194 + USB_DT_CONFIG, /* u8 bDescriptorType */
  195 + 0x50, 0x00, /* le16 wTotalLength */
  196 + 0x02, /* u8 bNumInterfaces */
  197 + DEV_CONFIG_VALUE, /* u8 bConfigurationValue */
  198 + STRING_CDC, /* u8 iConfiguration */
  199 + 0xc0, /* u8 bmAttributes */
  200 + 0x32, /* u8 bMaxPower */
  201 + /* CDC Control Interface */
  202 + 0x09, /* u8 bLength */
  203 + USB_DT_INTERFACE, /* u8 bDescriptorType */
  204 + 0x00, /* u8 bInterfaceNumber */
  205 + 0x00, /* u8 bAlternateSetting */
  206 + 0x01, /* u8 bNumEndpoints */
  207 + USB_CLASS_COMM, /* u8 bInterfaceClass */
  208 + USB_CDC_SUBCLASS_ETHERNET, /* u8 bInterfaceSubClass */
  209 + USB_CDC_PROTO_NONE, /* u8 bInterfaceProtocol */
  210 + STRING_CONTROL, /* u8 iInterface */
  211 + /* Header Descriptor */
  212 + 0x05, /* u8 bLength */
  213 + USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
  214 + USB_CDC_HEADER_TYPE, /* u8 bDescriptorSubType */
  215 + 0x10, 0x01, /* le16 bcdCDC */
  216 + /* Union Descriptor */
  217 + 0x05, /* u8 bLength */
  218 + USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
  219 + USB_CDC_UNION_TYPE, /* u8 bDescriptorSubType */
  220 + 0x00, /* u8 bMasterInterface0 */
  221 + 0x01, /* u8 bSlaveInterface0 */
  222 + /* Ethernet Descriptor */
  223 + 0x0d, /* u8 bLength */
  224 + USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
  225 + USB_CDC_ETHERNET_TYPE, /* u8 bDescriptorSubType */
  226 + STRING_ETHADDR, /* u8 iMACAddress */
  227 + 0x00, 0x00, 0x00, 0x00, /* le32 bmEthernetStatistics */
  228 + ETH_FRAME_LEN & 0xff, ETH_FRAME_LEN >> 8, /* le16 wMaxSegmentSize */
  229 + 0x00, 0x00, /* le16 wNumberMCFilters */
  230 + 0x00, /* u8 bNumberPowerFilters */
  231 + /* Status Descriptor */
  232 + 0x07, /* u8 bLength */
  233 + USB_DT_ENDPOINT, /* u8 bDescriptorType */
  234 + USB_DIR_IN | 1, /* u8 bEndpointAddress */
  235 + USB_ENDPOINT_XFER_INT, /* u8 bmAttributes */
  236 + STATUS_BYTECOUNT & 0xff, STATUS_BYTECOUNT >> 8, /* le16 wMaxPacketSize */
  237 + 1 << LOG2_STATUS_INTERVAL_MSEC, /* u8 bInterval */
  238 + /* CDC Data (nop) Interface */
  239 + 0x09, /* u8 bLength */
  240 + USB_DT_INTERFACE, /* u8 bDescriptorType */
  241 + 0x01, /* u8 bInterfaceNumber */
  242 + 0x00, /* u8 bAlternateSetting */
  243 + 0x00, /* u8 bNumEndpoints */
  244 + USB_CLASS_CDC_DATA, /* u8 bInterfaceClass */
  245 + 0x00, /* u8 bInterfaceSubClass */
  246 + 0x00, /* u8 bInterfaceProtocol */
  247 + 0x00, /* u8 iInterface */
  248 + /* CDC Data Interface */
  249 + 0x09, /* u8 bLength */
  250 + USB_DT_INTERFACE, /* u8 bDescriptorType */
  251 + 0x01, /* u8 bInterfaceNumber */
  252 + 0x01, /* u8 bAlternateSetting */
  253 + 0x02, /* u8 bNumEndpoints */
  254 + USB_CLASS_CDC_DATA, /* u8 bInterfaceClass */
  255 + 0x00, /* u8 bInterfaceSubClass */
  256 + 0x00, /* u8 bInterfaceProtocol */
  257 + STRING_DATA, /* u8 iInterface */
  258 + /* Source Endpoint */
  259 + 0x07, /* u8 bLength */
  260 + USB_DT_ENDPOINT, /* u8 bDescriptorType */
  261 + USB_DIR_IN | 2, /* u8 bEndpointAddress */
  262 + USB_ENDPOINT_XFER_BULK, /* u8 bmAttributes */
  263 + 0x40, 0x00, /* le16 wMaxPacketSize */
  264 + 0x00, /* u8 bInterval */
  265 + /* Sink Endpoint */
  266 + 0x07, /* u8 bLength */
  267 + USB_DT_ENDPOINT, /* u8 bDescriptorType */
  268 + USB_DIR_OUT | 2, /* u8 bEndpointAddress */
  269 + USB_ENDPOINT_XFER_BULK, /* u8 bmAttributes */
  270 + 0x40, 0x00, /* le16 wMaxPacketSize */
  271 + 0x00 /* u8 bInterval */
  272 +};
  273 +
  274 +/*
  275 + * RNDIS Definitions - in theory not specific to USB.
  276 + */
  277 +#define RNDIS_MAXIMUM_FRAME_SIZE 1518
  278 +#define RNDIS_MAX_TOTAL_SIZE 1558
  279 +
  280 +/* Remote NDIS Versions */
  281 +#define RNDIS_MAJOR_VERSION 1
  282 +#define RNDIS_MINOR_VERSION 0
  283 +
  284 +/* Status Values */
  285 +#define RNDIS_STATUS_SUCCESS 0x00000000U /* Success */
  286 +#define RNDIS_STATUS_FAILURE 0xc0000001U /* Unspecified error */
  287 +#define RNDIS_STATUS_INVALID_DATA 0xc0010015U /* Invalid data */
  288 +#define RNDIS_STATUS_NOT_SUPPORTED 0xc00000bbU /* Unsupported request */
  289 +#define RNDIS_STATUS_MEDIA_CONNECT 0x4001000bU /* Device connected */
  290 +#define RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000cU /* Device disconnected */
  291 +
  292 +/* Message Set for Connectionless (802.3) Devices */
  293 +enum {
  294 + RNDIS_PACKET_MSG = 1,
  295 + RNDIS_INITIALIZE_MSG = 2, /* Initialize device */
  296 + RNDIS_HALT_MSG = 3,
  297 + RNDIS_QUERY_MSG = 4,
  298 + RNDIS_SET_MSG = 5,
  299 + RNDIS_RESET_MSG = 6,
  300 + RNDIS_INDICATE_STATUS_MSG = 7,
  301 + RNDIS_KEEPALIVE_MSG = 8,
  302 +};
  303 +
  304 +/* Message completion */
  305 +enum {
  306 + RNDIS_INITIALIZE_CMPLT = 0x80000002U,
  307 + RNDIS_QUERY_CMPLT = 0x80000004U,
  308 + RNDIS_SET_CMPLT = 0x80000005U,
  309 + RNDIS_RESET_CMPLT = 0x80000006U,
  310 + RNDIS_KEEPALIVE_CMPLT = 0x80000008U,
  311 +};
  312 +
  313 +/* Device Flags */
  314 +enum {
  315 + RNDIS_DF_CONNECTIONLESS = 1,
  316 + RNDIS_DF_CONNECTIONORIENTED = 2,
  317 +};
  318 +
  319 +#define RNDIS_MEDIUM_802_3 0x00000000U
  320 +
  321 +/* from drivers/net/sk98lin/h/skgepnmi.h */
  322 +#define OID_PNP_CAPABILITIES 0xfd010100
  323 +#define OID_PNP_SET_POWER 0xfd010101
  324 +#define OID_PNP_QUERY_POWER 0xfd010102
  325 +#define OID_PNP_ADD_WAKE_UP_PATTERN 0xfd010103
  326 +#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xfd010104
  327 +#define OID_PNP_ENABLE_WAKE_UP 0xfd010106
  328 +
  329 +typedef uint32_t le32;
  330 +
  331 +typedef struct rndis_init_msg_type {
  332 + le32 MessageType;
  333 + le32 MessageLength;
  334 + le32 RequestID;
  335 + le32 MajorVersion;
  336 + le32 MinorVersion;
  337 + le32 MaxTransferSize;
  338 +} rndis_init_msg_type;
  339 +
  340 +typedef struct rndis_init_cmplt_type {
  341 + le32 MessageType;
  342 + le32 MessageLength;
  343 + le32 RequestID;
  344 + le32 Status;
  345 + le32 MajorVersion;
  346 + le32 MinorVersion;
  347 + le32 DeviceFlags;
  348 + le32 Medium;
  349 + le32 MaxPacketsPerTransfer;
  350 + le32 MaxTransferSize;
  351 + le32 PacketAlignmentFactor;
  352 + le32 AFListOffset;
  353 + le32 AFListSize;
  354 +} rndis_init_cmplt_type;
  355 +
  356 +typedef struct rndis_halt_msg_type {
  357 + le32 MessageType;
  358 + le32 MessageLength;
  359 + le32 RequestID;
  360 +} rndis_halt_msg_type;
  361 +
  362 +typedef struct rndis_query_msg_type {
  363 + le32 MessageType;
  364 + le32 MessageLength;
  365 + le32 RequestID;
  366 + le32 OID;
  367 + le32 InformationBufferLength;
  368 + le32 InformationBufferOffset;
  369 + le32 DeviceVcHandle;
  370 +} rndis_query_msg_type;
  371 +
  372 +typedef struct rndis_query_cmplt_type {
  373 + le32 MessageType;
  374 + le32 MessageLength;
  375 + le32 RequestID;
  376 + le32 Status;
  377 + le32 InformationBufferLength;
  378 + le32 InformationBufferOffset;
  379 +} rndis_query_cmplt_type;
  380 +
  381 +typedef struct rndis_set_msg_type {
  382 + le32 MessageType;
  383 + le32 MessageLength;
  384 + le32 RequestID;
  385 + le32 OID;
  386 + le32 InformationBufferLength;
  387 + le32 InformationBufferOffset;
  388 + le32 DeviceVcHandle;
  389 +} rndis_set_msg_type;
  390 +
  391 +typedef struct rndis_set_cmplt_type {
  392 + le32 MessageType;
  393 + le32 MessageLength;
  394 + le32 RequestID;
  395 + le32 Status;
  396 +} rndis_set_cmplt_type;
  397 +
  398 +typedef struct rndis_reset_msg_type {
  399 + le32 MessageType;
  400 + le32 MessageLength;
  401 + le32 Reserved;
  402 +} rndis_reset_msg_type;
  403 +
  404 +typedef struct rndis_reset_cmplt_type {
  405 + le32 MessageType;
  406 + le32 MessageLength;
  407 + le32 Status;
  408 + le32 AddressingReset;
  409 +} rndis_reset_cmplt_type;
  410 +
  411 +typedef struct rndis_indicate_status_msg_type {
  412 + le32 MessageType;
  413 + le32 MessageLength;
  414 + le32 Status;
  415 + le32 StatusBufferLength;
  416 + le32 StatusBufferOffset;
  417 +} rndis_indicate_status_msg_type;
  418 +
  419 +typedef struct rndis_keepalive_msg_type {
  420 + le32 MessageType;
  421 + le32 MessageLength;
  422 + le32 RequestID;
  423 +} rndis_keepalive_msg_type;
  424 +
  425 +typedef struct rndis_keepalive_cmplt_type {
  426 + le32 MessageType;
  427 + le32 MessageLength;
  428 + le32 RequestID;
  429 + le32 Status;
  430 +} rndis_keepalive_cmplt_type;
  431 +
  432 +struct rndis_packet_msg_type {
  433 + le32 MessageType;
  434 + le32 MessageLength;
  435 + le32 DataOffset;
  436 + le32 DataLength;
  437 + le32 OOBDataOffset;
  438 + le32 OOBDataLength;
  439 + le32 NumOOBDataElements;
  440 + le32 PerPacketInfoOffset;
  441 + le32 PerPacketInfoLength;
  442 + le32 VcHandle;
  443 + le32 Reserved;
  444 +};
  445 +
  446 +struct rndis_config_parameter {
  447 + le32 ParameterNameOffset;
  448 + le32 ParameterNameLength;
  449 + le32 ParameterType;
  450 + le32 ParameterValueOffset;
  451 + le32 ParameterValueLength;
  452 +};
  453 +
  454 +/* implementation specific */
  455 +enum rndis_state
  456 +{
  457 + RNDIS_UNINITIALIZED,
  458 + RNDIS_INITIALIZED,
  459 + RNDIS_DATA_INITIALIZED,
  460 +};
  461 +
  462 +/* from ndis.h */
  463 +enum ndis_oid {
  464 + /* Required Object IDs (OIDs) */
  465 + OID_GEN_SUPPORTED_LIST = 0x00010101,
  466 + OID_GEN_HARDWARE_STATUS = 0x00010102,
  467 + OID_GEN_MEDIA_SUPPORTED = 0x00010103,
  468 + OID_GEN_MEDIA_IN_USE = 0x00010104,
  469 + OID_GEN_MAXIMUM_LOOKAHEAD = 0x00010105,
  470 + OID_GEN_MAXIMUM_FRAME_SIZE = 0x00010106,
  471 + OID_GEN_LINK_SPEED = 0x00010107,
  472 + OID_GEN_TRANSMIT_BUFFER_SPACE = 0x00010108,
  473 + OID_GEN_RECEIVE_BUFFER_SPACE = 0x00010109,
  474 + OID_GEN_TRANSMIT_BLOCK_SIZE = 0x0001010a,
  475 + OID_GEN_RECEIVE_BLOCK_SIZE = 0x0001010b,
  476 + OID_GEN_VENDOR_ID = 0x0001010c,
  477 + OID_GEN_VENDOR_DESCRIPTION = 0x0001010d,
  478 + OID_GEN_CURRENT_PACKET_FILTER = 0x0001010e,
  479 + OID_GEN_CURRENT_LOOKAHEAD = 0x0001010f,
  480 + OID_GEN_DRIVER_VERSION = 0x00010110,
  481 + OID_GEN_MAXIMUM_TOTAL_SIZE = 0x00010111,
  482 + OID_GEN_PROTOCOL_OPTIONS = 0x00010112,
  483 + OID_GEN_MAC_OPTIONS = 0x00010113,
  484 + OID_GEN_MEDIA_CONNECT_STATUS = 0x00010114,
  485 + OID_GEN_MAXIMUM_SEND_PACKETS = 0x00010115,
  486 + OID_GEN_VENDOR_DRIVER_VERSION = 0x00010116,
  487 + OID_GEN_SUPPORTED_GUIDS = 0x00010117,
  488 + OID_GEN_NETWORK_LAYER_ADDRESSES = 0x00010118,
  489 + OID_GEN_TRANSPORT_HEADER_OFFSET = 0x00010119,
  490 + OID_GEN_MACHINE_NAME = 0x0001021a,
  491 + OID_GEN_RNDIS_CONFIG_PARAMETER = 0x0001021b,
  492 + OID_GEN_VLAN_ID = 0x0001021c,
  493 +
  494 + /* Optional OIDs */
  495 + OID_GEN_MEDIA_CAPABILITIES = 0x00010201,
  496 + OID_GEN_PHYSICAL_MEDIUM = 0x00010202,
  497 +
  498 + /* Required statistics OIDs */
  499 + OID_GEN_XMIT_OK = 0x00020101,
  500 + OID_GEN_RCV_OK = 0x00020102,
  501 + OID_GEN_XMIT_ERROR = 0x00020103,
  502 + OID_GEN_RCV_ERROR = 0x00020104,
  503 + OID_GEN_RCV_NO_BUFFER = 0x00020105,
  504 +
  505 + /* Optional statistics OIDs */
  506 + OID_GEN_DIRECTED_BYTES_XMIT = 0x00020201,
  507 + OID_GEN_DIRECTED_FRAMES_XMIT = 0x00020202,
  508 + OID_GEN_MULTICAST_BYTES_XMIT = 0x00020203,
  509 + OID_GEN_MULTICAST_FRAMES_XMIT = 0x00020204,
  510 + OID_GEN_BROADCAST_BYTES_XMIT = 0x00020205,
  511 + OID_GEN_BROADCAST_FRAMES_XMIT = 0x00020206,
  512 + OID_GEN_DIRECTED_BYTES_RCV = 0x00020207,
  513 + OID_GEN_DIRECTED_FRAMES_RCV = 0x00020208,
  514 + OID_GEN_MULTICAST_BYTES_RCV = 0x00020209,
  515 + OID_GEN_MULTICAST_FRAMES_RCV = 0x0002020a,
  516 + OID_GEN_BROADCAST_BYTES_RCV = 0x0002020b,
  517 + OID_GEN_BROADCAST_FRAMES_RCV = 0x0002020c,
  518 + OID_GEN_RCV_CRC_ERROR = 0x0002020d,
  519 + OID_GEN_TRANSMIT_QUEUE_LENGTH = 0x0002020e,
  520 + OID_GEN_GET_TIME_CAPS = 0x0002020f,
  521 + OID_GEN_GET_NETCARD_TIME = 0x00020210,
  522 + OID_GEN_NETCARD_LOAD = 0x00020211,
  523 + OID_GEN_DEVICE_PROFILE = 0x00020212,
  524 + OID_GEN_INIT_TIME_MS = 0x00020213,
  525 + OID_GEN_RESET_COUNTS = 0x00020214,
  526 + OID_GEN_MEDIA_SENSE_COUNTS = 0x00020215,
  527 + OID_GEN_FRIENDLY_NAME = 0x00020216,
  528 + OID_GEN_MINIPORT_INFO = 0x00020217,
  529 + OID_GEN_RESET_VERIFY_PARAMETERS = 0x00020218,
  530 +
  531 + /* IEEE 802.3 (Ethernet) OIDs */
  532 + OID_802_3_PERMANENT_ADDRESS = 0x01010101,
  533 + OID_802_3_CURRENT_ADDRESS = 0x01010102,
  534 + OID_802_3_MULTICAST_LIST = 0x01010103,
  535 + OID_802_3_MAXIMUM_LIST_SIZE = 0x01010104,
  536 + OID_802_3_MAC_OPTIONS = 0x01010105,
  537 + OID_802_3_RCV_ERROR_ALIGNMENT = 0x01020101,
  538 + OID_802_3_XMIT_ONE_COLLISION = 0x01020102,
  539 + OID_802_3_XMIT_MORE_COLLISIONS = 0x01020103,
  540 + OID_802_3_XMIT_DEFERRED = 0x01020201,
  541 + OID_802_3_XMIT_MAX_COLLISIONS = 0x01020202,
  542 + OID_802_3_RCV_OVERRUN = 0x01020203,
  543 + OID_802_3_XMIT_UNDERRUN = 0x01020204,
  544 + OID_802_3_XMIT_HEARTBEAT_FAILURE = 0x01020205,
  545 + OID_802_3_XMIT_TIMES_CRS_LOST = 0x01020206,
  546 + OID_802_3_XMIT_LATE_COLLISIONS = 0x01020207,
  547 +};
  548 +
  549 +static const uint32_t oid_supported_list[] =
  550 +{
  551 + /* the general stuff */
  552 + OID_GEN_SUPPORTED_LIST,
  553 + OID_GEN_HARDWARE_STATUS,
  554 + OID_GEN_MEDIA_SUPPORTED,
  555 + OID_GEN_MEDIA_IN_USE,
  556 + OID_GEN_MAXIMUM_FRAME_SIZE,
  557 + OID_GEN_LINK_SPEED,
  558 + OID_GEN_TRANSMIT_BLOCK_SIZE,
  559 + OID_GEN_RECEIVE_BLOCK_SIZE,
  560 + OID_GEN_VENDOR_ID,
  561 + OID_GEN_VENDOR_DESCRIPTION,
  562 + OID_GEN_VENDOR_DRIVER_VERSION,
  563 + OID_GEN_CURRENT_PACKET_FILTER,
  564 + OID_GEN_MAXIMUM_TOTAL_SIZE,
  565 + OID_GEN_MEDIA_CONNECT_STATUS,
  566 + OID_GEN_PHYSICAL_MEDIUM,
  567 +
  568 + /* the statistical stuff */
  569 + OID_GEN_XMIT_OK,
  570 + OID_GEN_RCV_OK,
  571 + OID_GEN_XMIT_ERROR,
  572 + OID_GEN_RCV_ERROR,
  573 + OID_GEN_RCV_NO_BUFFER,
  574 +
  575 + /* IEEE 802.3 */
  576 + /* the general stuff */
  577 + OID_802_3_PERMANENT_ADDRESS,
  578 + OID_802_3_CURRENT_ADDRESS,
  579 + OID_802_3_MULTICAST_LIST,
  580 + OID_802_3_MAC_OPTIONS,
  581 + OID_802_3_MAXIMUM_LIST_SIZE,
  582 +
  583 + /* the statistical stuff */
  584 + OID_802_3_RCV_ERROR_ALIGNMENT,
  585 + OID_802_3_XMIT_ONE_COLLISION,
  586 + OID_802_3_XMIT_MORE_COLLISIONS,
  587 +};
  588 +
  589 +#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA (1 << 0)
  590 +#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED (1 << 1)
  591 +#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND (1 << 2)
  592 +#define NDIS_MAC_OPTION_NO_LOOPBACK (1 << 3)
  593 +#define NDIS_MAC_OPTION_FULL_DUPLEX (1 << 4)
  594 +#define NDIS_MAC_OPTION_EOTX_INDICATION (1 << 5)
  595 +#define NDIS_MAC_OPTION_8021P_PRIORITY (1 << 6)
  596 +
  597 +struct rndis_response {
  598 + TAILQ_ENTRY(rndis_response) entries;
  599 + uint32_t length;
  600 + uint8_t buf[0];
  601 +};
  602 +
  603 +typedef struct USBNetState {
  604 + USBDevice dev;
  605 +
  606 + unsigned int rndis;
  607 + enum rndis_state rndis_state;
  608 + uint32_t medium;
  609 + uint32_t speed;
  610 + uint32_t media_state;
  611 + uint16_t filter;
  612 + uint32_t vendorid;
  613 + uint8_t mac[6];
  614 +
  615 + unsigned int out_ptr;
  616 + uint8_t out_buf[2048];
  617 +
  618 + USBPacket *inpkt;
  619 + unsigned int in_ptr, in_len;
  620 + uint8_t in_buf[2048];
  621 +
  622 + char usbstring_mac[13];
  623 + VLANClientState *vc;
  624 + TAILQ_HEAD(rndis_resp_head, rndis_response) rndis_resp;
  625 +} USBNetState;
  626 +
  627 +static int ndis_query(USBNetState *s, uint32_t oid,
  628 + uint8_t *inbuf, unsigned int inlen, uint8_t *outbuf)
  629 +{
  630 + unsigned int i, count;
  631 +
  632 + switch (oid) {
  633 + /* general oids (table 4-1) */
  634 + /* mandatory */
  635 + case OID_GEN_SUPPORTED_LIST:
  636 + count = sizeof(oid_supported_list) / sizeof(uint32_t);
  637 + for (i = 0; i < count; i++)
  638 + ((le32 *) outbuf)[i] = cpu_to_le32(oid_supported_list[i]);
  639 + return sizeof(oid_supported_list);
  640 +
  641 + /* mandatory */
  642 + case OID_GEN_HARDWARE_STATUS:
  643 + *((le32 *) outbuf) = cpu_to_le32(0);
  644 + return sizeof(le32);
  645 +
  646 + /* mandatory */
  647 + case OID_GEN_MEDIA_SUPPORTED:
  648 + *((le32 *) outbuf) = cpu_to_le32(s->medium);
  649 + return sizeof(le32);
  650 +
  651 + /* mandatory */
  652 + case OID_GEN_MEDIA_IN_USE:
  653 + *((le32 *) outbuf) = cpu_to_le32(s->medium);
  654 + return sizeof(le32);
  655 +
  656 + /* mandatory */
  657 + case OID_GEN_MAXIMUM_FRAME_SIZE:
  658 + *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN);
  659 + return sizeof(le32);
  660 +
  661 + /* mandatory */
  662 + case OID_GEN_LINK_SPEED:
  663 + *((le32 *) outbuf) = cpu_to_le32(s->speed);
  664 + return sizeof(le32);
  665 +
  666 + /* mandatory */
  667 + case OID_GEN_TRANSMIT_BLOCK_SIZE:
  668 + *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN);
  669 + return sizeof(le32);
  670 +
  671 + /* mandatory */
  672 + case OID_GEN_RECEIVE_BLOCK_SIZE:
  673 + *((le32 *) outbuf) = cpu_to_le32(ETH_FRAME_LEN);
  674 + return sizeof(le32);
  675 +
  676 + /* mandatory */
  677 + case OID_GEN_VENDOR_ID:
  678 + *((le32 *) outbuf) = cpu_to_le32(s->vendorid);
  679 + return sizeof(le32);
  680 +
  681 + /* mandatory */
  682 + case OID_GEN_VENDOR_DESCRIPTION:
  683 + strcpy(outbuf, "QEMU USB RNDIS Net");
  684 + return strlen(outbuf) + 1;
  685 +
  686 + case OID_GEN_VENDOR_DRIVER_VERSION:
  687 + *((le32 *) outbuf) = cpu_to_le32(1);
  688 + return sizeof(le32);
  689 +
  690 + /* mandatory */
  691 + case OID_GEN_CURRENT_PACKET_FILTER:
  692 + *((le32 *) outbuf) = cpu_to_le32(s->filter);
  693 + return sizeof(le32);
  694 +
  695 + /* mandatory */
  696 + case OID_GEN_MAXIMUM_TOTAL_SIZE:
  697 + *((le32 *) outbuf) = cpu_to_le32(RNDIS_MAX_TOTAL_SIZE);
  698 + return sizeof(le32);
  699 +
  700 + /* mandatory */
  701 + case OID_GEN_MEDIA_CONNECT_STATUS:
  702 + *((le32 *) outbuf) = cpu_to_le32(s->media_state);
  703 + return sizeof(le32);
  704 +
  705 + case OID_GEN_PHYSICAL_MEDIUM:
  706 + *((le32 *) outbuf) = cpu_to_le32(0);
  707 + return sizeof(le32);
  708 +
  709 + case OID_GEN_MAC_OPTIONS:
  710 + *((le32 *) outbuf) = cpu_to_le32(
  711 + NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
  712 + NDIS_MAC_OPTION_FULL_DUPLEX);
  713 + return sizeof(le32);
  714 +
  715 + /* statistics OIDs (table 4-2) */
  716 + /* mandatory */
  717 + case OID_GEN_XMIT_OK:
  718 + *((le32 *) outbuf) = cpu_to_le32(0);
  719 + return sizeof(le32);
  720 +
  721 + /* mandatory */
  722 + case OID_GEN_RCV_OK:
  723 + *((le32 *) outbuf) = cpu_to_le32(0);
  724 + return sizeof(le32);
  725 +
  726 + /* mandatory */
  727 + case OID_GEN_XMIT_ERROR:
  728 + *((le32 *) outbuf) = cpu_to_le32(0);
  729 + return sizeof(le32);
  730 +
  731 + /* mandatory */
  732 + case OID_GEN_RCV_ERROR:
  733 + *((le32 *) outbuf) = cpu_to_le32(0);
  734 + return sizeof(le32);
  735 +
  736 + /* mandatory */
  737 + case OID_GEN_RCV_NO_BUFFER:
  738 + *((le32 *) outbuf) = cpu_to_le32(0);
  739 + return sizeof(le32);
  740 +
  741 + /* ieee802.3 OIDs (table 4-3) */
  742 + /* mandatory */
  743 + case OID_802_3_PERMANENT_ADDRESS:
  744 + memcpy(outbuf, s->mac, 6);
  745 + return 6;
  746 +
  747 + /* mandatory */
  748 + case OID_802_3_CURRENT_ADDRESS:
  749 + memcpy(outbuf, s->mac, 6);
  750 + return 6;
  751 +
  752 + /* mandatory */
  753 + case OID_802_3_MULTICAST_LIST:
  754 + *((le32 *) outbuf) = cpu_to_le32(0xe0000000);
  755 + return sizeof(le32);
  756 +
  757 + /* mandatory */
  758 + case OID_802_3_MAXIMUM_LIST_SIZE:
  759 + *((le32 *) outbuf) = cpu_to_le32(1);
  760 + return sizeof(le32);
  761 +
  762 + case OID_802_3_MAC_OPTIONS:
  763 + return 0;
  764 +
  765 + /* ieee802.3 statistics OIDs (table 4-4) */
  766 + /* mandatory */
  767 + case OID_802_3_RCV_ERROR_ALIGNMENT:
  768 + *((le32 *) outbuf) = cpu_to_le32(0);
  769 + return sizeof(le32);
  770 +
  771 + /* mandatory */
  772 + case OID_802_3_XMIT_ONE_COLLISION:
  773 + *((le32 *) outbuf) = cpu_to_le32(0);
  774 + return sizeof(le32);
  775 +
  776 + /* mandatory */
  777 + case OID_802_3_XMIT_MORE_COLLISIONS:
  778 + *((le32 *) outbuf) = cpu_to_le32(0);
  779 + return sizeof(le32);
  780 +
  781 + default:
  782 + fprintf(stderr, "usbnet: unknown OID 0x%08x\n", oid);
  783 + return 0;
  784 + }
  785 + return -1;
  786 +}
  787 +
  788 +static int ndis_set(USBNetState *s, uint32_t oid,
  789 + uint8_t *inbuf, unsigned int inlen)
  790 +{
  791 + switch (oid) {
  792 + case OID_GEN_CURRENT_PACKET_FILTER:
  793 + s->filter = le32_to_cpup((le32 *) inbuf);
  794 + if (s->filter) {
  795 + s->rndis_state = RNDIS_DATA_INITIALIZED;
  796 + } else {
  797 + s->rndis_state = RNDIS_INITIALIZED;
  798 + }
  799 + return 0;
  800 +
  801 + case OID_802_3_MULTICAST_LIST:
  802 + return 0;
  803 + }
  804 + return -1;
  805 +}
  806 +
  807 +static int rndis_get_response(USBNetState *s, uint8_t *buf)
  808 +{
  809 + int ret = 0;
  810 + struct rndis_response *r = s->rndis_resp.tqh_first;
  811 +
  812 + if (!r)
  813 + return ret;
  814 +
  815 + TAILQ_REMOVE(&s->rndis_resp, r, entries);
  816 + ret = r->length;
  817 + memcpy(buf, r->buf, r->length);
  818 + qemu_free(r);
  819 +
  820 + return ret;
  821 +}
  822 +
  823 +static void *rndis_queue_response(USBNetState *s, unsigned int length)
  824 +{
  825 + struct rndis_response *r =
  826 + qemu_mallocz(sizeof(struct rndis_response) + length);
  827 +
  828 + TAILQ_INSERT_TAIL(&s->rndis_resp, r, entries);
  829 + r->length = length;
  830 +
  831 + return &r->buf[0];
  832 +}
  833 +
  834 +static void rndis_clear_responsequeue(USBNetState *s)
  835 +{
  836 + struct rndis_response *r;
  837 +
  838 + while ((r = s->rndis_resp.tqh_first)) {
  839 + TAILQ_REMOVE(&s->rndis_resp, r, entries);
  840 + qemu_free(r);
  841 + }
  842 +}
  843 +
  844 +static int rndis_init_response(USBNetState *s, rndis_init_msg_type *buf)
  845 +{
  846 + rndis_init_cmplt_type *resp =
  847 + rndis_queue_response(s, sizeof(rndis_init_cmplt_type));
  848 +
  849 + if (!resp)
  850 + return USB_RET_STALL;
  851 +
  852 + resp->MessageType = cpu_to_le32(RNDIS_INITIALIZE_CMPLT);
  853 + resp->MessageLength = cpu_to_le32(sizeof(rndis_init_cmplt_type));
  854 + resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
  855 + resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
  856 + resp->MajorVersion = cpu_to_le32(RNDIS_MAJOR_VERSION);
  857 + resp->MinorVersion = cpu_to_le32(RNDIS_MINOR_VERSION);
  858 + resp->DeviceFlags = cpu_to_le32(RNDIS_DF_CONNECTIONLESS);
  859 + resp->Medium = cpu_to_le32(RNDIS_MEDIUM_802_3);
  860 + resp->MaxPacketsPerTransfer = cpu_to_le32(1);
  861 + resp->MaxTransferSize = cpu_to_le32(ETH_FRAME_LEN +
  862 + sizeof(struct rndis_packet_msg_type) + 22);
  863 + resp->PacketAlignmentFactor = cpu_to_le32(0);
  864 + resp->AFListOffset = cpu_to_le32(0);
  865 + resp->AFListSize = cpu_to_le32(0);
  866 + return 0;
  867 +}
  868 +
  869 +static int rndis_query_response(USBNetState *s,
  870 + rndis_query_msg_type *buf, unsigned int length)
  871 +{
  872 + rndis_query_cmplt_type *resp;
  873 + /* oid_supported_list is the largest data reply */
  874 + uint8_t infobuf[sizeof(oid_supported_list)];
  875 + uint32_t bufoffs, buflen;
  876 + int infobuflen;
  877 + unsigned int resplen;
  878 +
  879 + bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8;
  880 + buflen = le32_to_cpu(buf->InformationBufferLength);
  881 + if (bufoffs + buflen > length)
  882 + return USB_RET_STALL;
  883 +
  884 + infobuflen = ndis_query(s, le32_to_cpu(buf->OID),
  885 + bufoffs + (uint8_t *) buf, buflen, infobuf);
  886 + resplen = sizeof(rndis_query_cmplt_type) +
  887 + ((infobuflen < 0) ? 0 : infobuflen);
  888 + resp = rndis_queue_response(s, resplen);
  889 + if (!resp)
  890 + return USB_RET_STALL;
  891 +
  892 + resp->MessageType = cpu_to_le32(RNDIS_QUERY_CMPLT);
  893 + resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
  894 + resp->MessageLength = cpu_to_le32(resplen);
  895 +
  896 + if (infobuflen < 0) {
  897 + /* OID not supported */
  898 + resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
  899 + resp->InformationBufferLength = cpu_to_le32(0);
  900 + resp->InformationBufferOffset = cpu_to_le32(0);
  901 + return 0;
  902 + }
  903 +
  904 + resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
  905 + resp->InformationBufferOffset =
  906 + cpu_to_le32(infobuflen ? sizeof(rndis_query_cmplt_type) - 8 : 0);
  907 + resp->InformationBufferLength = cpu_to_le32(infobuflen);
  908 + memcpy(resp + 1, infobuf, infobuflen);
  909 +
  910 + return 0;
  911 +}
  912 +
  913 +static int rndis_set_response(USBNetState *s,
  914 + rndis_set_msg_type *buf, unsigned int length)
  915 +{
  916 + rndis_set_cmplt_type *resp =
  917 + rndis_queue_response(s, sizeof(rndis_set_cmplt_type));
  918 + uint32_t bufoffs, buflen;
  919 + int ret;
  920 +
  921 + if (!resp)
  922 + return USB_RET_STALL;
  923 +
  924 + bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8;
  925 + buflen = le32_to_cpu(buf->InformationBufferLength);
  926 + if (bufoffs + buflen > length)
  927 + return USB_RET_STALL;
  928 +
  929 + ret = ndis_set(s, le32_to_cpu(buf->OID),
  930 + bufoffs + (uint8_t *) buf, buflen);
  931 + resp->MessageType = cpu_to_le32(RNDIS_SET_CMPLT);
  932 + resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
  933 + resp->MessageLength = cpu_to_le32(sizeof(rndis_set_cmplt_type));
  934 + if (ret < 0) {
  935 + /* OID not supported */
  936 + resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
  937 + return 0;
  938 + }
  939 + resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
  940 +
  941 + return 0;
  942 +}
  943 +
  944 +static int rndis_reset_response(USBNetState *s, rndis_reset_msg_type *buf)
  945 +{
  946 + rndis_reset_cmplt_type *resp =
  947 + rndis_queue_response(s, sizeof(rndis_reset_cmplt_type));
  948 +
  949 + if (!resp)
  950 + return USB_RET_STALL;
  951 +
  952 + resp->MessageType = cpu_to_le32(RNDIS_RESET_CMPLT);
  953 + resp->MessageLength = cpu_to_le32(sizeof(rndis_reset_cmplt_type));
  954 + resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
  955 + resp->AddressingReset = cpu_to_le32(1); /* reset information */
  956 +
  957 + return 0;
  958 +}
  959 +
  960 +static int rndis_keepalive_response(USBNetState *s,
  961 + rndis_keepalive_msg_type *buf)
  962 +{
  963 + rndis_keepalive_cmplt_type *resp =
  964 + rndis_queue_response(s, sizeof(rndis_keepalive_cmplt_type));
  965 +
  966 + if (!resp)
  967 + return USB_RET_STALL;
  968 +
  969 + resp->MessageType = cpu_to_le32(RNDIS_KEEPALIVE_CMPLT);
  970 + resp->MessageLength = cpu_to_le32(sizeof(rndis_keepalive_cmplt_type));
  971 + resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
  972 + resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
  973 +
  974 + return 0;
  975 +}
  976 +
  977 +static int rndis_parse(USBNetState *s, uint8_t *data, int length)
  978 +{
  979 + uint32_t msg_type, msg_length;
  980 + le32 *tmp = (le32 *) data;
  981 +
  982 + msg_type = le32_to_cpup(tmp++);
  983 + msg_length = le32_to_cpup(tmp++);
  984 +
  985 + switch (msg_type) {
  986 + case RNDIS_INITIALIZE_MSG:
  987 + s->rndis_state = RNDIS_INITIALIZED;
  988 + return rndis_init_response(s, (rndis_init_msg_type *) data);
  989 +
  990 + case RNDIS_HALT_MSG:
  991 + s->rndis_state = RNDIS_UNINITIALIZED;
  992 + return 0;
  993 +
  994 + case RNDIS_QUERY_MSG:
  995 + return rndis_query_response(s, (rndis_query_msg_type *) data, length);
  996 +
  997 + case RNDIS_SET_MSG:
  998 + return rndis_set_response(s, (rndis_set_msg_type *) data, length);
  999 +
  1000 + case RNDIS_RESET_MSG:
  1001 + rndis_clear_responsequeue(s);
  1002 + s->out_ptr = s->in_ptr = s->in_len = 0;
  1003 + return rndis_reset_response(s, (rndis_reset_msg_type *) data);
  1004 +
  1005 + case RNDIS_KEEPALIVE_MSG:
  1006 + /* For USB: host does this every 5 seconds */
  1007 + return rndis_keepalive_response(s, (rndis_keepalive_msg_type *) data);
  1008 + }
  1009 +
  1010 + return USB_RET_STALL;
  1011 +}
  1012 +
  1013 +static void usb_net_handle_reset(USBDevice *dev)
  1014 +{
  1015 +}
  1016 +
  1017 +static char *usb_net_stringtable[] = {
  1018 + [STRING_MANUFACTURER] = "QEMU",
  1019 + [STRING_PRODUCT] = "RNDIS/QEMU USB Network Device",
  1020 + [STRING_ETHADDR] = "400102030405",
  1021 + [STRING_DATA] = "QEMU USB Net Data Interface",
  1022 + [STRING_CONTROL] = "QEMU USB Net Control Interface",
  1023 + [STRING_RNDIS_CONTROL] = "QEMU USB Net RNDIS Control Interface",
  1024 + [STRING_CDC] = "QEMU USB Net CDC",
  1025 + [STRING_SUBSET] = "QEMU USB Net Subset",
  1026 + [STRING_RNDIS] = "QEMU USB Net RNDIS",
  1027 + [STRING_SERIALNUMBER] = "1",
  1028 +};
  1029 +
  1030 +static int usb_net_handle_control(USBDevice *dev, int request, int value,
  1031 + int index, int length, uint8_t *data)
  1032 +{
  1033 + USBNetState *s = (USBNetState *) dev;
  1034 + int ret = 0;
  1035 +
  1036 + switch(request) {
  1037 + case DeviceRequest | USB_REQ_GET_STATUS:
  1038 + data[0] = (1 << USB_DEVICE_SELF_POWERED) |
  1039 + (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
  1040 + data[1] = 0x00;
  1041 + ret = 2;
  1042 + break;
  1043 +
  1044 + case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
  1045 + if (value == USB_DEVICE_REMOTE_WAKEUP) {
  1046 + dev->remote_wakeup = 0;
  1047 + } else {
  1048 + goto fail;
  1049 + }
  1050 + ret = 0;
  1051 + break;
  1052 +
  1053 + case DeviceOutRequest | USB_REQ_SET_FEATURE:
  1054 + if (value == USB_DEVICE_REMOTE_WAKEUP) {
  1055 + dev->remote_wakeup = 1;
  1056 + } else {
  1057 + goto fail;
  1058 + }
  1059 + ret = 0;
  1060 + break;
  1061 +
  1062 + case DeviceOutRequest | USB_REQ_SET_ADDRESS:
  1063 + dev->addr = value;
  1064 + ret = 0;
  1065 + break;
  1066 +
  1067 + case ClassInterfaceOutRequest | USB_CDC_SEND_ENCAPSULATED_COMMAND:
  1068 + if (!s->rndis || value || index != 0)
  1069 + goto fail;
  1070 +#if TRAFFIC_DEBUG
  1071 + {
  1072 + unsigned int i;
  1073 + fprintf(stderr, "SEND_ENCAPSULATED_COMMAND:");
  1074 + for (i = 0; i < length; i++) {
  1075 + if (!(i & 15))
  1076 + fprintf(stderr, "\n%04x:", i);
  1077 + fprintf(stderr, " %02x", data[i]);
  1078 + }
  1079 + fprintf(stderr, "\n\n");
  1080 + }
  1081 +#endif
  1082 + ret = rndis_parse(s, data, length);
  1083 + break;
  1084 +
  1085 + case ClassInterfaceRequest | USB_CDC_GET_ENCAPSULATED_RESPONSE:
  1086 + if (!s->rndis || value || index != 0)
  1087 + goto fail;
  1088 + ret = rndis_get_response(s, data);
  1089 + if (!ret) {
  1090 + data[0] = 0;
  1091 + ret = 1;
  1092 + }
  1093 +#if TRAFFIC_DEBUG
  1094 + {
  1095 + unsigned int i;
  1096 + fprintf(stderr, "GET_ENCAPSULATED_RESPONSE:");
  1097 + for (i = 0; i < ret; i++) {
  1098 + if (!(i & 15))
  1099 + fprintf(stderr, "\n%04x:", i);
  1100 + fprintf(stderr, " %02x", data[i]);
  1101 + }
  1102 + fprintf(stderr, "\n\n");
  1103 + }
  1104 +#endif
  1105 + break;
  1106 +
  1107 + case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
  1108 + switch(value >> 8) {
  1109 + case USB_DT_DEVICE:
  1110 + ret = sizeof(qemu_net_dev_descriptor);
  1111 + memcpy(data, qemu_net_dev_descriptor, ret);
  1112 + break;
  1113 +
  1114 + case USB_DT_CONFIG:
  1115 + switch (value & 0xff) {
  1116 + case 0:
  1117 + ret = sizeof(qemu_net_rndis_config_descriptor);
  1118 + memcpy(data, qemu_net_rndis_config_descriptor, ret);
  1119 + break;
  1120 +
  1121 + case 1:
  1122 + ret = sizeof(qemu_net_cdc_config_descriptor);
  1123 + memcpy(data, qemu_net_cdc_config_descriptor, ret);
  1124 + break;
  1125 +
  1126 + default:
  1127 + goto fail;
  1128 + }
  1129 +
  1130 + data[2] = ret & 0xff;
  1131 + data[3] = ret >> 8;
  1132 + break;
  1133 +
  1134 + case USB_DT_STRING:
  1135 + switch (value & 0xff) {
  1136 + case 0:
  1137 + /* language ids */
  1138 + data[0] = 4;
  1139 + data[1] = 3;
  1140 + data[2] = 0x09;
  1141 + data[3] = 0x04;
  1142 + ret = 4;
  1143 + break;
  1144 +
  1145 + case STRING_ETHADDR:
  1146 + ret = set_usb_string(data, s->usbstring_mac);
  1147 + break;
  1148 +
  1149 + default:
  1150 + if (usb_net_stringtable[value & 0xff]) {
  1151 + ret = set_usb_string(data,
  1152 + usb_net_stringtable[value & 0xff]);
  1153 + break;
  1154 + }
  1155 +
  1156 + goto fail;
  1157 + }
  1158 + break;
  1159 +
  1160 + default:
  1161 + goto fail;
  1162 + }
  1163 + break;
  1164 +
  1165 + case DeviceRequest | USB_REQ_GET_CONFIGURATION:
  1166 + data[0] = s->rndis ? DEV_RNDIS_CONFIG_VALUE : DEV_CONFIG_VALUE;
  1167 + ret = 1;
  1168 + break;
  1169 +
  1170 + case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
  1171 + switch (value & 0xff) {
  1172 + case DEV_CONFIG_VALUE:
  1173 + s->rndis = 0;
  1174 + break;
  1175 +
  1176 + case DEV_RNDIS_CONFIG_VALUE:
  1177 + s->rndis = 1;
  1178 + break;
  1179 +
  1180 + default:
  1181 + goto fail;
  1182 + }
  1183 + ret = 0;
  1184 + break;
  1185 +
  1186 + case DeviceRequest | USB_REQ_GET_INTERFACE:
  1187 + case InterfaceRequest | USB_REQ_GET_INTERFACE:
  1188 + data[0] = 0;
  1189 + ret = 1;
  1190 + break;
  1191 +
  1192 + case DeviceOutRequest | USB_REQ_SET_INTERFACE:
  1193 + case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
  1194 + ret = 0;
  1195 + break;
  1196 +
  1197 + default:
  1198 + fail:
  1199 + fprintf(stderr, "usbnet: failed control transaction: "
  1200 + "request 0x%x value 0x%x index 0x%x length 0x%x\n",
  1201 + request, value, index, length);
  1202 + ret = USB_RET_STALL;
  1203 + break;
  1204 + }
  1205 + return ret;
  1206 +}
  1207 +
  1208 +static int usb_net_handle_statusin(USBNetState *s, USBPacket *p)
  1209 +{
  1210 + int ret = 8;
  1211 +
  1212 + if (p->len < 8)
  1213 + return USB_RET_STALL;
  1214 +
  1215 + ((le32 *) p->data)[0] = cpu_to_le32(1);
  1216 + ((le32 *) p->data)[1] = cpu_to_le32(0);
  1217 + if (!s->rndis_resp.tqh_first)
  1218 + ret = USB_RET_NAK;
  1219 +
  1220 +#if DEBUG
  1221 + fprintf(stderr, "usbnet: interrupt poll len %u return %d", p->len, ret);
  1222 + {
  1223 + int i;
  1224 + fprintf(stderr, ":");
  1225 + for (i = 0; i < ret; i++) {
  1226 + if (!(i & 15))
  1227 + fprintf(stderr, "\n%04x:", i);
  1228 + fprintf(stderr, " %02x", p->data[i]);
  1229 + }
  1230 + fprintf(stderr, "\n\n");
  1231 + }
  1232 +#endif
  1233 +
  1234 + return ret;
  1235 +}
  1236 +
  1237 +static int usb_net_handle_datain(USBNetState *s, USBPacket *p)
  1238 +{
  1239 + int ret = USB_RET_NAK;
  1240 +
  1241 + if (s->in_ptr > s->in_len) {
  1242 + s->in_ptr = s->in_len = 0;
  1243 + ret = USB_RET_NAK;
  1244 + return ret;
  1245 + }
  1246 + if (!s->in_len) {
  1247 + ret = USB_RET_NAK;
  1248 + return ret;
  1249 + }
  1250 + ret = s->in_len - s->in_ptr;
  1251 + if (ret > p->len)
  1252 + ret = p->len;
  1253 + memcpy(p->data, &s->in_buf[s->in_ptr], ret);
  1254 + s->in_ptr += ret;
  1255 + if (s->in_ptr >= s->in_len &&
  1256 + (s->rndis || (s->in_len & (64 - 1)) || !ret)) {
  1257 + /* no short packet necessary */
  1258 + s->in_ptr = s->in_len = 0;
  1259 + }
  1260 +
  1261 +#if TRAFFIC_DEBUG
  1262 + fprintf(stderr, "usbnet: data in len %u return %d", p->len, ret);
  1263 + {
  1264 + int i;
  1265 + fprintf(stderr, ":");
  1266 + for (i = 0; i < ret; i++) {
  1267 + if (!(i & 15))
  1268 + fprintf(stderr, "\n%04x:", i);
  1269 + fprintf(stderr, " %02x", p->data[i]);
  1270 + }
  1271 + fprintf(stderr, "\n\n");
  1272 + }
  1273 +#endif
  1274 +
  1275 + return ret;
  1276 +}
  1277 +
  1278 +static int usb_net_handle_dataout(USBNetState *s, USBPacket *p)
  1279 +{
  1280 + int ret = p->len;
  1281 + int sz = sizeof(s->out_buf) - s->out_ptr;
  1282 + struct rndis_packet_msg_type *msg =
  1283 + (struct rndis_packet_msg_type *) s->out_buf;
  1284 + uint32_t len;
  1285 +
  1286 +#if TRAFFIC_DEBUG
  1287 + fprintf(stderr, "usbnet: data out len %u\n", p->len);
  1288 + {
  1289 + int i;
  1290 + fprintf(stderr, ":");
  1291 + for (i = 0; i < p->len; i++) {
  1292 + if (!(i & 15))
  1293 + fprintf(stderr, "\n%04x:", i);
  1294 + fprintf(stderr, " %02x", p->data[i]);
  1295 + }
  1296 + fprintf(stderr, "\n\n");
  1297 + }
  1298 +#endif
  1299 +
  1300 + if (sz > ret)
  1301 + sz = ret;
  1302 + memcpy(&s->out_buf[s->out_ptr], p->data, sz);
  1303 + s->out_ptr += sz;
  1304 +
  1305 + if (!s->rndis) {
  1306 + if (ret < 64) {
  1307 + qemu_send_packet(s->vc, s->out_buf, s->out_ptr);
  1308 + s->out_ptr = 0;
  1309 + }
  1310 + return ret;
  1311 + }
  1312 + len = le32_to_cpu(msg->MessageLength);
  1313 + if (s->out_ptr < 8 || s->out_ptr < len)
  1314 + return ret;
  1315 + if (le32_to_cpu(msg->MessageType) == RNDIS_PACKET_MSG) {
  1316 + uint32_t offs = 8 + le32_to_cpu(msg->DataOffset);
  1317 + uint32_t size = le32_to_cpu(msg->DataLength);
  1318 + if (offs + size <= len)
  1319 + qemu_send_packet(s->vc, s->out_buf + offs, size);
  1320 + }
  1321 + s->out_ptr -= len;
  1322 + memmove(s->out_buf, &s->out_buf[len], s->out_ptr);
  1323 +
  1324 + return ret;
  1325 +}
  1326 +
  1327 +static int usb_net_handle_data(USBDevice *dev, USBPacket *p)
  1328 +{
  1329 + USBNetState *s = (USBNetState *) dev;
  1330 + int ret = 0;
  1331 +
  1332 + switch(p->pid) {
  1333 + case USB_TOKEN_IN:
  1334 + switch (p->devep) {
  1335 + case 1:
  1336 + ret = usb_net_handle_statusin(s, p);
  1337 + break;
  1338 +
  1339 + case 2:
  1340 + ret = usb_net_handle_datain(s, p);
  1341 + break;
  1342 +
  1343 + default:
  1344 + goto fail;
  1345 + }
  1346 + break;
  1347 +
  1348 + case USB_TOKEN_OUT:
  1349 + switch (p->devep) {
  1350 + case 2:
  1351 + ret = usb_net_handle_dataout(s, p);
  1352 + break;
  1353 +
  1354 + default:
  1355 + goto fail;
  1356 + }
  1357 + break;
  1358 +
  1359 + default:
  1360 + fail:
  1361 + ret = USB_RET_STALL;
  1362 + break;
  1363 + }
  1364 + if (ret == USB_RET_STALL)
  1365 + fprintf(stderr, "usbnet: failed data transaction: "
  1366 + "pid 0x%x ep 0x%x len 0x%x\n",
  1367 + p->pid, p->devep, p->len);
  1368 + return ret;
  1369 +}
  1370 +
  1371 +static void usbnet_receive(void *opaque, const uint8_t *buf, int size)
  1372 +{
  1373 + USBNetState *s = opaque;
  1374 + struct rndis_packet_msg_type *msg;
  1375 +
  1376 + if (s->rndis) {
  1377 + msg = (struct rndis_packet_msg_type *) s->in_buf;
  1378 + if (!s->rndis_state == RNDIS_DATA_INITIALIZED)
  1379 + return;
  1380 + if (size + sizeof(struct rndis_packet_msg_type) > sizeof(s->in_buf))
  1381 + return;
  1382 +
  1383 + memset(msg, 0, sizeof(struct rndis_packet_msg_type));
  1384 + msg->MessageType = cpu_to_le32(RNDIS_PACKET_MSG);
  1385 + msg->MessageLength = cpu_to_le32(size + sizeof(struct rndis_packet_msg_type));
  1386 + msg->DataOffset = cpu_to_le32(sizeof(struct rndis_packet_msg_type) - 8);
  1387 + msg->DataLength = cpu_to_le32(size);
  1388 + /* msg->OOBDataOffset;
  1389 + * msg->OOBDataLength;
  1390 + * msg->NumOOBDataElements;
  1391 + * msg->PerPacketInfoOffset;
  1392 + * msg->PerPacketInfoLength;
  1393 + * msg->VcHandle;
  1394 + * msg->Reserved;
  1395 + */
  1396 + memcpy(msg + 1, buf, size);
  1397 + s->in_len = size + sizeof(struct rndis_packet_msg_type);
  1398 + } else {
  1399 + if (size > sizeof(s->in_buf))
  1400 + return;
  1401 + memcpy(s->in_buf, buf, size);
  1402 + s->in_len = size;
  1403 + }
  1404 + s->in_ptr = 0;
  1405 +}
  1406 +
  1407 +static int usbnet_can_receive(void *opaque)
  1408 +{
  1409 + USBNetState *s = opaque;
  1410 +
  1411 + if (s->rndis && !s->rndis_state == RNDIS_DATA_INITIALIZED)
  1412 + return 1;
  1413 +
  1414 + return !s->in_len;
  1415 +}
  1416 +
  1417 +static void usb_net_handle_destroy(USBDevice *dev)
  1418 +{
  1419 + USBNetState *s = (USBNetState *) dev;
  1420 +
  1421 + /* FIXME: delete the VLAN client and the nic */
  1422 + rndis_clear_responsequeue(s);
  1423 + qemu_free(s);
  1424 +}
  1425 +
  1426 +USBDevice *usb_net_init(NICInfo *nd)
  1427 +{
  1428 + USBNetState *s;
  1429 +
  1430 + s = qemu_mallocz(sizeof(USBNetState));
  1431 + if (!s)
  1432 + return NULL;
  1433 + s->dev.speed = USB_SPEED_FULL;
  1434 + s->dev.handle_packet = usb_generic_handle_packet;
  1435 +
  1436 + s->dev.handle_reset = usb_net_handle_reset;
  1437 + s->dev.handle_control = usb_net_handle_control;
  1438 + s->dev.handle_data = usb_net_handle_data;
  1439 + s->dev.handle_destroy = usb_net_handle_destroy;
  1440 +
  1441 + s->rndis = 1;
  1442 + s->rndis_state = RNDIS_UNINITIALIZED;
  1443 + s->medium = 0; /* NDIS_MEDIUM_802_3 */
  1444 + s->speed = 1000000; /* 100MBps, in 100Bps units */
  1445 + s->media_state = 0; /* NDIS_MEDIA_STATE_CONNECTED */;
  1446 + s->filter = 0;
  1447 + s->vendorid = 0x1234;
  1448 +
  1449 + memcpy(s->mac, nd->macaddr, 6);
  1450 + TAILQ_INIT(&s->rndis_resp);
  1451 +
  1452 + pstrcpy(s->dev.devname, sizeof(s->dev.devname),
  1453 + "QEMU USB Network Interface");
  1454 + s->vc = qemu_new_vlan_client(nd->vlan,
  1455 + usbnet_receive, usbnet_can_receive, s);
  1456 +
  1457 + snprintf(s->usbstring_mac, sizeof(s->usbstring_mac),
  1458 + "%02x%02x%02x%02x%02x%02x",
  1459 + 0x40, s->mac[1], s->mac[2],
  1460 + s->mac[3], s->mac[4], s->mac[5]);
  1461 + snprintf(s->vc->info_str, sizeof(s->vc->info_str),
  1462 + "usbnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
  1463 + s->mac[0], s->mac[1], s->mac[2],
  1464 + s->mac[3], s->mac[4], s->mac[5]);
  1465 + fprintf(stderr, "usbnet: initialized mac %02x:%02x:%02x:%02x:%02x:%02x\n",
  1466 + s->mac[0], s->mac[1], s->mac[2],
  1467 + s->mac[3], s->mac[4], s->mac[5]);
  1468 +
  1469 + return (USBDevice *) s;
  1470 +}
... ...
hw/usb.h
... ... @@ -219,6 +219,9 @@ USBDevice *usb_keyboard_init(void);
219 219 /* usb-msd.c */
220 220 USBDevice *usb_msd_init(const char *filename);
221 221  
  222 +/* usb-net.c */
  223 +USBDevice *usb_net_init(NICInfo *nd);
  224 +
222 225 /* usb-wacom.c */
223 226 USBDevice *usb_wacom_init(void);
224 227  
... ...
qemu-doc.texi
... ... @@ -567,6 +567,9 @@ available devices.
567 567 Braille device. This will use BrlAPI to display the braille output on a real
568 568 or fake device.
569 569  
  570 +@item net:nic_num
  571 +Network adapter that supports CDC ethernet and RNDIS protocols.
  572 +
570 573 @end table
571 574  
572 575 @end table
... ... @@ -584,7 +587,7 @@ Qemu can emulate several different models of network card.
584 587 Valid values for @var{type} are
585 588 @code{i82551}, @code{i82557b}, @code{i82559er},
586 589 @code{ne2k_pci}, @code{ne2k_isa}, @code{pcnet}, @code{rtl8139},
587   -@code{e1000}, @code{smc91c111}, @code{lance} and @code{mcf_fec}.
  590 +@code{e1000}, @code{smc91c111}, @code{lance}, @code{mcf_fec} and @code{usb}.
588 591 Not all devices are supported on all targets. Use -net nic,model=?
589 592 for a list of available devices for your target.
590 593  
... ... @@ -1707,6 +1710,16 @@ serial converter, faking a Matrix Orbital LCD Display (USB ID 0403:FA00).
1707 1710 @item braille
1708 1711 Braille device. This will use BrlAPI to display the braille output on a real
1709 1712 or fake device.
  1713 +@item net:@var{nic_num}
  1714 +Network adapter that supports CDC ethernet and RNDIS protocols. This must be
  1715 +used together with the @code{-net nic,model=usb,...} option (see description),
  1716 +where @var{nic_num} specifies the index of the @code{-net nic,...} option
  1717 +describing the interface (zero-based).
  1718 +For instance, user-mode networking can be used by specifying
  1719 +@example
  1720 +qemu -net user,vlan=1 -net nic,model=usb,vlan=1 -usbdevice net:0 [...OPTIONS...]
  1721 +@end example
  1722 +Currently this cannot be used in machines that support PCI NICs.
1710 1723 @end table
1711 1724  
1712 1725 @node host_usb_devices
... ...
... ... @@ -5475,6 +5475,12 @@ static int usb_device_add(const char *devname)
5475 5475 } else if (!strcmp(devname, "braille")) {
5476 5476 dev = usb_baum_init();
5477 5477 #endif
  5478 + } else if (strstart(devname, "net:", &p)) {
  5479 + int nicidx = strtoul(p, NULL, 0);
  5480 +
  5481 + if (nicidx >= nb_nics || strcmp(nd_table[nicidx].model, "usb"))
  5482 + return -1;
  5483 + dev = usb_net_init(&nd_table[nicidx]);
5478 5484 } else {
5479 5485 return -1;
5480 5486 }
... ...