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