Annotation of qemu/hw/usb-net.c, revision 1.1

1.1     ! root        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 "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:                       size_t outlen)
        !           630: {
        !           631:     unsigned int i;
        !           632: 
        !           633:     switch (oid) {
        !           634:     /* general oids (table 4-1) */
        !           635:     /* mandatory */
        !           636:     case OID_GEN_SUPPORTED_LIST:
        !           637:         for (i = 0; i < ARRAY_SIZE(oid_supported_list); 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:         pstrcpy((char *)outbuf, outlen, "QEMU USB RNDIS Net");
        !           684:         return strlen((char *)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:                             sizeof(infobuf));
        !           887:     resplen = sizeof(rndis_query_cmplt_type) +
        !           888:             ((infobuflen < 0) ? 0 : infobuflen);
        !           889:     resp = rndis_queue_response(s, resplen);
        !           890:     if (!resp)
        !           891:         return USB_RET_STALL;
        !           892: 
        !           893:     resp->MessageType = cpu_to_le32(RNDIS_QUERY_CMPLT);
        !           894:     resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
        !           895:     resp->MessageLength = cpu_to_le32(resplen);
        !           896: 
        !           897:     if (infobuflen < 0) {
        !           898:         /* OID not supported */
        !           899:         resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
        !           900:         resp->InformationBufferLength = cpu_to_le32(0);
        !           901:         resp->InformationBufferOffset = cpu_to_le32(0);
        !           902:         return 0;
        !           903:     }
        !           904: 
        !           905:     resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
        !           906:     resp->InformationBufferOffset =
        !           907:             cpu_to_le32(infobuflen ? sizeof(rndis_query_cmplt_type) - 8 : 0);
        !           908:     resp->InformationBufferLength = cpu_to_le32(infobuflen);
        !           909:     memcpy(resp + 1, infobuf, infobuflen);
        !           910: 
        !           911:     return 0;
        !           912: }
        !           913: 
        !           914: static int rndis_set_response(USBNetState *s,
        !           915:                 rndis_set_msg_type *buf, unsigned int length)
        !           916: {
        !           917:     rndis_set_cmplt_type *resp =
        !           918:             rndis_queue_response(s, sizeof(rndis_set_cmplt_type));
        !           919:     uint32_t bufoffs, buflen;
        !           920:     int ret;
        !           921: 
        !           922:     if (!resp)
        !           923:         return USB_RET_STALL;
        !           924: 
        !           925:     bufoffs = le32_to_cpu(buf->InformationBufferOffset) + 8;
        !           926:     buflen = le32_to_cpu(buf->InformationBufferLength);
        !           927:     if (bufoffs + buflen > length)
        !           928:         return USB_RET_STALL;
        !           929: 
        !           930:     ret = ndis_set(s, le32_to_cpu(buf->OID),
        !           931:                     bufoffs + (uint8_t *) buf, buflen);
        !           932:     resp->MessageType = cpu_to_le32(RNDIS_SET_CMPLT);
        !           933:     resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
        !           934:     resp->MessageLength = cpu_to_le32(sizeof(rndis_set_cmplt_type));
        !           935:     if (ret < 0) {
        !           936:         /* OID not supported */
        !           937:         resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED);
        !           938:         return 0;
        !           939:     }
        !           940:     resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
        !           941: 
        !           942:     return 0;
        !           943: }
        !           944: 
        !           945: static int rndis_reset_response(USBNetState *s, rndis_reset_msg_type *buf)
        !           946: {
        !           947:     rndis_reset_cmplt_type *resp =
        !           948:             rndis_queue_response(s, sizeof(rndis_reset_cmplt_type));
        !           949: 
        !           950:     if (!resp)
        !           951:         return USB_RET_STALL;
        !           952: 
        !           953:     resp->MessageType = cpu_to_le32(RNDIS_RESET_CMPLT);
        !           954:     resp->MessageLength = cpu_to_le32(sizeof(rndis_reset_cmplt_type));
        !           955:     resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
        !           956:     resp->AddressingReset = cpu_to_le32(1); /* reset information */
        !           957: 
        !           958:     return 0;
        !           959: }
        !           960: 
        !           961: static int rndis_keepalive_response(USBNetState *s,
        !           962:                 rndis_keepalive_msg_type *buf)
        !           963: {
        !           964:     rndis_keepalive_cmplt_type *resp =
        !           965:             rndis_queue_response(s, sizeof(rndis_keepalive_cmplt_type));
        !           966: 
        !           967:     if (!resp)
        !           968:         return USB_RET_STALL;
        !           969: 
        !           970:     resp->MessageType = cpu_to_le32(RNDIS_KEEPALIVE_CMPLT);
        !           971:     resp->MessageLength = cpu_to_le32(sizeof(rndis_keepalive_cmplt_type));
        !           972:     resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
        !           973:     resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS);
        !           974: 
        !           975:     return 0;
        !           976: }
        !           977: 
        !           978: static int rndis_parse(USBNetState *s, uint8_t *data, int length)
        !           979: {
        !           980:     uint32_t msg_type, msg_length;
        !           981:     le32 *tmp = (le32 *) data;
        !           982: 
        !           983:     msg_type = le32_to_cpup(tmp++);
        !           984:     msg_length = le32_to_cpup(tmp++);
        !           985: 
        !           986:     switch (msg_type) {
        !           987:     case RNDIS_INITIALIZE_MSG:
        !           988:         s->rndis_state = RNDIS_INITIALIZED;
        !           989:         return rndis_init_response(s, (rndis_init_msg_type *) data);
        !           990: 
        !           991:     case RNDIS_HALT_MSG:
        !           992:         s->rndis_state = RNDIS_UNINITIALIZED;
        !           993:         return 0;
        !           994: 
        !           995:     case RNDIS_QUERY_MSG:
        !           996:         return rndis_query_response(s, (rndis_query_msg_type *) data, length);
        !           997: 
        !           998:     case RNDIS_SET_MSG:
        !           999:         return rndis_set_response(s, (rndis_set_msg_type *) data, length);
        !          1000: 
        !          1001:     case RNDIS_RESET_MSG:
        !          1002:         rndis_clear_responsequeue(s);
        !          1003:         s->out_ptr = s->in_ptr = s->in_len = 0;
        !          1004:         return rndis_reset_response(s, (rndis_reset_msg_type *) data);
        !          1005: 
        !          1006:     case RNDIS_KEEPALIVE_MSG:
        !          1007:         /* For USB: host does this every 5 seconds */
        !          1008:         return rndis_keepalive_response(s, (rndis_keepalive_msg_type *) data);
        !          1009:     }
        !          1010: 
        !          1011:     return USB_RET_STALL;
        !          1012: }
        !          1013: 
        !          1014: static void usb_net_handle_reset(USBDevice *dev)
        !          1015: {
        !          1016: }
        !          1017: 
        !          1018: static const char * const usb_net_stringtable[] = {
        !          1019:     [STRING_MANUFACTURER]      = "QEMU",
        !          1020:     [STRING_PRODUCT]           = "RNDIS/QEMU USB Network Device",
        !          1021:     [STRING_ETHADDR]           = "400102030405",
        !          1022:     [STRING_DATA]              = "QEMU USB Net Data Interface",
        !          1023:     [STRING_CONTROL]           = "QEMU USB Net Control Interface",
        !          1024:     [STRING_RNDIS_CONTROL]     = "QEMU USB Net RNDIS Control Interface",
        !          1025:     [STRING_CDC]               = "QEMU USB Net CDC",
        !          1026:     [STRING_SUBSET]            = "QEMU USB Net Subset",
        !          1027:     [STRING_RNDIS]             = "QEMU USB Net RNDIS",
        !          1028:     [STRING_SERIALNUMBER]      = "1",
        !          1029: };
        !          1030: 
        !          1031: static int usb_net_handle_control(USBDevice *dev, int request, int value,
        !          1032:                 int index, int length, uint8_t *data)
        !          1033: {
        !          1034:     USBNetState *s = (USBNetState *) dev;
        !          1035:     int ret = 0;
        !          1036: 
        !          1037:     switch(request) {
        !          1038:     case DeviceRequest | USB_REQ_GET_STATUS:
        !          1039:         data[0] = (1 << USB_DEVICE_SELF_POWERED) |
        !          1040:                 (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
        !          1041:         data[1] = 0x00;
        !          1042:         ret = 2;
        !          1043:         break;
        !          1044: 
        !          1045:     case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
        !          1046:         if (value == USB_DEVICE_REMOTE_WAKEUP) {
        !          1047:             dev->remote_wakeup = 0;
        !          1048:         } else {
        !          1049:             goto fail;
        !          1050:         }
        !          1051:         ret = 0;
        !          1052:         break;
        !          1053: 
        !          1054:     case DeviceOutRequest | USB_REQ_SET_FEATURE:
        !          1055:         if (value == USB_DEVICE_REMOTE_WAKEUP) {
        !          1056:             dev->remote_wakeup = 1;
        !          1057:         } else {
        !          1058:             goto fail;
        !          1059:         }
        !          1060:         ret = 0;
        !          1061:         break;
        !          1062: 
        !          1063:     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
        !          1064:         dev->addr = value;
        !          1065:         ret = 0;
        !          1066:         break;
        !          1067: 
        !          1068:     case ClassInterfaceOutRequest | USB_CDC_SEND_ENCAPSULATED_COMMAND:
        !          1069:         if (!s->rndis || value || index != 0)
        !          1070:             goto fail;
        !          1071: #ifdef TRAFFIC_DEBUG
        !          1072:         {
        !          1073:             unsigned int i;
        !          1074:             fprintf(stderr, "SEND_ENCAPSULATED_COMMAND:");
        !          1075:             for (i = 0; i < length; i++) {
        !          1076:                 if (!(i & 15))
        !          1077:                     fprintf(stderr, "\n%04x:", i);
        !          1078:                 fprintf(stderr, " %02x", data[i]);
        !          1079:             }
        !          1080:             fprintf(stderr, "\n\n");
        !          1081:         }
        !          1082: #endif
        !          1083:         ret = rndis_parse(s, data, length);
        !          1084:         break;
        !          1085: 
        !          1086:     case ClassInterfaceRequest | USB_CDC_GET_ENCAPSULATED_RESPONSE:
        !          1087:         if (!s->rndis || value || index != 0)
        !          1088:             goto fail;
        !          1089:         ret = rndis_get_response(s, data);
        !          1090:         if (!ret) {
        !          1091:             data[0] = 0;
        !          1092:             ret = 1;
        !          1093:         }
        !          1094: #ifdef TRAFFIC_DEBUG
        !          1095:         {
        !          1096:             unsigned int i;
        !          1097:             fprintf(stderr, "GET_ENCAPSULATED_RESPONSE:");
        !          1098:             for (i = 0; i < ret; i++) {
        !          1099:                 if (!(i & 15))
        !          1100:                     fprintf(stderr, "\n%04x:", i);
        !          1101:                 fprintf(stderr, " %02x", data[i]);
        !          1102:             }
        !          1103:             fprintf(stderr, "\n\n");
        !          1104:         }
        !          1105: #endif
        !          1106:         break;
        !          1107: 
        !          1108:     case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
        !          1109:         switch(value >> 8) {
        !          1110:         case USB_DT_DEVICE:
        !          1111:             ret = sizeof(qemu_net_dev_descriptor);
        !          1112:             memcpy(data, qemu_net_dev_descriptor, ret);
        !          1113:             break;
        !          1114: 
        !          1115:         case USB_DT_CONFIG:
        !          1116:             switch (value & 0xff) {
        !          1117:             case 0:
        !          1118:                 ret = sizeof(qemu_net_rndis_config_descriptor);
        !          1119:                 memcpy(data, qemu_net_rndis_config_descriptor, ret);
        !          1120:                 break;
        !          1121: 
        !          1122:             case 1:
        !          1123:                 ret = sizeof(qemu_net_cdc_config_descriptor);
        !          1124:                 memcpy(data, qemu_net_cdc_config_descriptor, ret);
        !          1125:                 break;
        !          1126: 
        !          1127:             default:
        !          1128:                 goto fail;
        !          1129:             }
        !          1130: 
        !          1131:             data[2] = ret & 0xff;
        !          1132:             data[3] = ret >> 8;
        !          1133:             break;
        !          1134: 
        !          1135:         case USB_DT_STRING:
        !          1136:             switch (value & 0xff) {
        !          1137:             case 0:
        !          1138:                 /* language ids */
        !          1139:                 data[0] = 4;
        !          1140:                 data[1] = 3;
        !          1141:                 data[2] = 0x09;
        !          1142:                 data[3] = 0x04;
        !          1143:                 ret = 4;
        !          1144:                 break;
        !          1145: 
        !          1146:             case STRING_ETHADDR:
        !          1147:                 ret = set_usb_string(data, s->usbstring_mac);
        !          1148:                 break;
        !          1149: 
        !          1150:             default:
        !          1151:                 if (usb_net_stringtable[value & 0xff]) {
        !          1152:                     ret = set_usb_string(data,
        !          1153:                                     usb_net_stringtable[value & 0xff]);
        !          1154:                     break;
        !          1155:                 }
        !          1156: 
        !          1157:                 goto fail;
        !          1158:             }
        !          1159:             break;
        !          1160: 
        !          1161:         default:
        !          1162:             goto fail;
        !          1163:         }
        !          1164:         break;
        !          1165: 
        !          1166:     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
        !          1167:         data[0] = s->rndis ? DEV_RNDIS_CONFIG_VALUE : DEV_CONFIG_VALUE;
        !          1168:         ret = 1;
        !          1169:         break;
        !          1170: 
        !          1171:     case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
        !          1172:         switch (value & 0xff) {
        !          1173:         case DEV_CONFIG_VALUE:
        !          1174:             s->rndis = 0;
        !          1175:             break;
        !          1176: 
        !          1177:         case DEV_RNDIS_CONFIG_VALUE:
        !          1178:             s->rndis = 1;
        !          1179:             break;
        !          1180: 
        !          1181:         default:
        !          1182:             goto fail;
        !          1183:         }
        !          1184:         ret = 0;
        !          1185:         break;
        !          1186: 
        !          1187:     case DeviceRequest | USB_REQ_GET_INTERFACE:
        !          1188:     case InterfaceRequest | USB_REQ_GET_INTERFACE:
        !          1189:         data[0] = 0;
        !          1190:         ret = 1;
        !          1191:         break;
        !          1192: 
        !          1193:     case DeviceOutRequest | USB_REQ_SET_INTERFACE:
        !          1194:     case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
        !          1195:         ret = 0;
        !          1196:         break;
        !          1197: 
        !          1198:     default:
        !          1199:     fail:
        !          1200:         fprintf(stderr, "usbnet: failed control transaction: "
        !          1201:                         "request 0x%x value 0x%x index 0x%x length 0x%x\n",
        !          1202:                         request, value, index, length);
        !          1203:         ret = USB_RET_STALL;
        !          1204:         break;
        !          1205:     }
        !          1206:     return ret;
        !          1207: }
        !          1208: 
        !          1209: static int usb_net_handle_statusin(USBNetState *s, USBPacket *p)
        !          1210: {
        !          1211:     int ret = 8;
        !          1212: 
        !          1213:     if (p->len < 8)
        !          1214:         return USB_RET_STALL;
        !          1215: 
        !          1216:     ((le32 *) p->data)[0] = cpu_to_le32(1);
        !          1217:     ((le32 *) p->data)[1] = cpu_to_le32(0);
        !          1218:     if (!s->rndis_resp.tqh_first)
        !          1219:         ret = USB_RET_NAK;
        !          1220: 
        !          1221: #ifdef TRAFFIC_DEBUG
        !          1222:     fprintf(stderr, "usbnet: interrupt poll len %u return %d", p->len, ret);
        !          1223:     {
        !          1224:         int i;
        !          1225:         fprintf(stderr, ":");
        !          1226:         for (i = 0; i < ret; i++) {
        !          1227:             if (!(i & 15))
        !          1228:                 fprintf(stderr, "\n%04x:", i);
        !          1229:             fprintf(stderr, " %02x", p->data[i]);
        !          1230:         }
        !          1231:         fprintf(stderr, "\n\n");
        !          1232:     }
        !          1233: #endif
        !          1234: 
        !          1235:     return ret;
        !          1236: }
        !          1237: 
        !          1238: static int usb_net_handle_datain(USBNetState *s, USBPacket *p)
        !          1239: {
        !          1240:     int ret = USB_RET_NAK;
        !          1241: 
        !          1242:     if (s->in_ptr > s->in_len) {
        !          1243:         s->in_ptr = s->in_len = 0;
        !          1244:         ret = USB_RET_NAK;
        !          1245:         return ret;
        !          1246:     }
        !          1247:     if (!s->in_len) {
        !          1248:         ret = USB_RET_NAK;
        !          1249:         return ret;
        !          1250:     }
        !          1251:     ret = s->in_len - s->in_ptr;
        !          1252:     if (ret > p->len)
        !          1253:         ret = p->len;
        !          1254:     memcpy(p->data, &s->in_buf[s->in_ptr], ret);
        !          1255:     s->in_ptr += ret;
        !          1256:     if (s->in_ptr >= s->in_len &&
        !          1257:                     (s->rndis || (s->in_len & (64 - 1)) || !ret)) {
        !          1258:         /* no short packet necessary */
        !          1259:         s->in_ptr = s->in_len = 0;
        !          1260:     }
        !          1261: 
        !          1262: #ifdef TRAFFIC_DEBUG
        !          1263:     fprintf(stderr, "usbnet: data in len %u return %d", p->len, ret);
        !          1264:     {
        !          1265:         int i;
        !          1266:         fprintf(stderr, ":");
        !          1267:         for (i = 0; i < ret; i++) {
        !          1268:             if (!(i & 15))
        !          1269:                 fprintf(stderr, "\n%04x:", i);
        !          1270:             fprintf(stderr, " %02x", p->data[i]);
        !          1271:         }
        !          1272:         fprintf(stderr, "\n\n");
        !          1273:     }
        !          1274: #endif
        !          1275: 
        !          1276:     return ret;
        !          1277: }
        !          1278: 
        !          1279: static int usb_net_handle_dataout(USBNetState *s, USBPacket *p)
        !          1280: {
        !          1281:     int ret = p->len;
        !          1282:     int sz = sizeof(s->out_buf) - s->out_ptr;
        !          1283:     struct rndis_packet_msg_type *msg =
        !          1284:             (struct rndis_packet_msg_type *) s->out_buf;
        !          1285:     uint32_t len;
        !          1286: 
        !          1287: #ifdef TRAFFIC_DEBUG
        !          1288:     fprintf(stderr, "usbnet: data out len %u\n", p->len);
        !          1289:     {
        !          1290:         int i;
        !          1291:         fprintf(stderr, ":");
        !          1292:         for (i = 0; i < p->len; i++) {
        !          1293:             if (!(i & 15))
        !          1294:                 fprintf(stderr, "\n%04x:", i);
        !          1295:             fprintf(stderr, " %02x", p->data[i]);
        !          1296:         }
        !          1297:         fprintf(stderr, "\n\n");
        !          1298:     }
        !          1299: #endif
        !          1300: 
        !          1301:     if (sz > ret)
        !          1302:         sz = ret;
        !          1303:     memcpy(&s->out_buf[s->out_ptr], p->data, sz);
        !          1304:     s->out_ptr += sz;
        !          1305: 
        !          1306:     if (!s->rndis) {
        !          1307:         if (ret < 64) {
        !          1308:             qemu_send_packet(s->vc, s->out_buf, s->out_ptr);
        !          1309:             s->out_ptr = 0;
        !          1310:         }
        !          1311:         return ret;
        !          1312:     }
        !          1313:     len = le32_to_cpu(msg->MessageLength);
        !          1314:     if (s->out_ptr < 8 || s->out_ptr < len)
        !          1315:         return ret;
        !          1316:     if (le32_to_cpu(msg->MessageType) == RNDIS_PACKET_MSG) {
        !          1317:         uint32_t offs = 8 + le32_to_cpu(msg->DataOffset);
        !          1318:         uint32_t size = le32_to_cpu(msg->DataLength);
        !          1319:         if (offs + size <= len)
        !          1320:             qemu_send_packet(s->vc, s->out_buf + offs, size);
        !          1321:     }
        !          1322:     s->out_ptr -= len;
        !          1323:     memmove(s->out_buf, &s->out_buf[len], s->out_ptr);
        !          1324: 
        !          1325:     return ret;
        !          1326: }
        !          1327: 
        !          1328: static int usb_net_handle_data(USBDevice *dev, USBPacket *p)
        !          1329: {
        !          1330:     USBNetState *s = (USBNetState *) dev;
        !          1331:     int ret = 0;
        !          1332: 
        !          1333:     switch(p->pid) {
        !          1334:     case USB_TOKEN_IN:
        !          1335:         switch (p->devep) {
        !          1336:         case 1:
        !          1337:             ret = usb_net_handle_statusin(s, p);
        !          1338:             break;
        !          1339: 
        !          1340:         case 2:
        !          1341:             ret = usb_net_handle_datain(s, p);
        !          1342:             break;
        !          1343: 
        !          1344:         default:
        !          1345:             goto fail;
        !          1346:         }
        !          1347:         break;
        !          1348: 
        !          1349:     case USB_TOKEN_OUT:
        !          1350:         switch (p->devep) {
        !          1351:         case 2:
        !          1352:             ret = usb_net_handle_dataout(s, p);
        !          1353:             break;
        !          1354: 
        !          1355:         default:
        !          1356:             goto fail;
        !          1357:         }
        !          1358:         break;
        !          1359: 
        !          1360:     default:
        !          1361:     fail:
        !          1362:         ret = USB_RET_STALL;
        !          1363:         break;
        !          1364:     }
        !          1365:     if (ret == USB_RET_STALL)
        !          1366:         fprintf(stderr, "usbnet: failed data transaction: "
        !          1367:                         "pid 0x%x ep 0x%x len 0x%x\n",
        !          1368:                         p->pid, p->devep, p->len);
        !          1369:     return ret;
        !          1370: }
        !          1371: 
        !          1372: static void usbnet_receive(void *opaque, const uint8_t *buf, int size)
        !          1373: {
        !          1374:     USBNetState *s = opaque;
        !          1375:     struct rndis_packet_msg_type *msg;
        !          1376: 
        !          1377:     if (s->rndis) {
        !          1378:         msg = (struct rndis_packet_msg_type *) s->in_buf;
        !          1379:         if (!s->rndis_state == RNDIS_DATA_INITIALIZED)
        !          1380:             return;
        !          1381:         if (size + sizeof(struct rndis_packet_msg_type) > sizeof(s->in_buf))
        !          1382:             return;
        !          1383: 
        !          1384:         memset(msg, 0, sizeof(struct rndis_packet_msg_type));
        !          1385:         msg->MessageType = cpu_to_le32(RNDIS_PACKET_MSG);
        !          1386:         msg->MessageLength = cpu_to_le32(size + sizeof(struct rndis_packet_msg_type));
        !          1387:         msg->DataOffset = cpu_to_le32(sizeof(struct rndis_packet_msg_type) - 8);
        !          1388:         msg->DataLength = cpu_to_le32(size);
        !          1389:         /* msg->OOBDataOffset;
        !          1390:          * msg->OOBDataLength;
        !          1391:          * msg->NumOOBDataElements;
        !          1392:          * msg->PerPacketInfoOffset;
        !          1393:          * msg->PerPacketInfoLength;
        !          1394:          * msg->VcHandle;
        !          1395:          * msg->Reserved;
        !          1396:          */
        !          1397:         memcpy(msg + 1, buf, size);
        !          1398:         s->in_len = size + sizeof(struct rndis_packet_msg_type);
        !          1399:     } else {
        !          1400:         if (size > sizeof(s->in_buf))
        !          1401:             return;
        !          1402:         memcpy(s->in_buf, buf, size);
        !          1403:         s->in_len = size;
        !          1404:     }
        !          1405:     s->in_ptr = 0;
        !          1406: }
        !          1407: 
        !          1408: static int usbnet_can_receive(void *opaque)
        !          1409: {
        !          1410:     USBNetState *s = opaque;
        !          1411: 
        !          1412:     if (s->rndis && !s->rndis_state == RNDIS_DATA_INITIALIZED)
        !          1413:         return 1;
        !          1414: 
        !          1415:     return !s->in_len;
        !          1416: }
        !          1417: 
        !          1418: static void usb_net_handle_destroy(USBDevice *dev)
        !          1419: {
        !          1420:     USBNetState *s = (USBNetState *) dev;
        !          1421: 
        !          1422:     /* TODO: remove the nd_table[] entry */
        !          1423:     qemu_del_vlan_client(s->vc);
        !          1424:     rndis_clear_responsequeue(s);
        !          1425:     qemu_free(s);
        !          1426: }
        !          1427: 
        !          1428: USBDevice *usb_net_init(NICInfo *nd)
        !          1429: {
        !          1430:     USBNetState *s;
        !          1431: 
        !          1432:     s = qemu_mallocz(sizeof(USBNetState));
        !          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, nd->model, nd->name,
        !          1455:                     usbnet_receive, usbnet_can_receive, s);
        !          1456: 
        !          1457:     qemu_format_nic_info_str(s->vc, s->mac);
        !          1458: 
        !          1459:     snprintf(s->usbstring_mac, sizeof(s->usbstring_mac),
        !          1460:                     "%02x%02x%02x%02x%02x%02x",
        !          1461:                     0x40, s->mac[1], s->mac[2],
        !          1462:                     s->mac[3], s->mac[4], s->mac[5]);
        !          1463:     fprintf(stderr, "usbnet: initialized mac %02x:%02x:%02x:%02x:%02x:%02x\n",
        !          1464:                     s->mac[0], s->mac[1], s->mac[2],
        !          1465:                     s->mac[3], s->mac[4], s->mac[5]);
        !          1466: 
        !          1467:     return (USBDevice *) s;
        !          1468: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.