usb: add device qualifier support
Add support for device_qualifier and other_speed_config descriptors. These are used to query the "other speed" configuration of usb 2.0 devices, i.e. in high-speed mode they return the full-speed configuration and visa versa. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
		
							parent
							
								
									32d4191978
								
							
						
					
					
						commit
						25620cba94
					
				| @ -48,6 +48,30 @@ int usb_desc_device(const USBDescID *id, const USBDescDevice *dev, | ||||
|     return bLength; | ||||
| } | ||||
| 
 | ||||
| int usb_desc_device_qualifier(const USBDescDevice *dev, | ||||
|                               uint8_t *dest, size_t len) | ||||
| { | ||||
|     uint8_t bLength = 0x0a; | ||||
| 
 | ||||
|     if (len < bLength) { | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     dest[0x00] = bLength; | ||||
|     dest[0x01] = USB_DT_DEVICE_QUALIFIER; | ||||
| 
 | ||||
|     dest[0x02] = usb_lo(dev->bcdUSB); | ||||
|     dest[0x03] = usb_hi(dev->bcdUSB); | ||||
|     dest[0x04] = dev->bDeviceClass; | ||||
|     dest[0x05] = dev->bDeviceSubClass; | ||||
|     dest[0x06] = dev->bDeviceProtocol; | ||||
|     dest[0x07] = dev->bMaxPacketSize0; | ||||
|     dest[0x08] = dev->bNumConfigurations; | ||||
|     dest[0x09] = 0; /* reserved */ | ||||
| 
 | ||||
|     return bLength; | ||||
| } | ||||
| 
 | ||||
| int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len) | ||||
| { | ||||
|     uint8_t  bLength = 0x09; | ||||
| @ -263,11 +287,18 @@ int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len) | ||||
| int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len) | ||||
| { | ||||
|     const USBDesc *desc = dev->info->usb_desc; | ||||
|     const USBDescDevice *other_dev; | ||||
|     uint8_t buf[256]; | ||||
|     uint8_t type = value >> 8; | ||||
|     uint8_t index = value & 0xff; | ||||
|     int ret = -1; | ||||
| 
 | ||||
|     if (dev->speed == USB_SPEED_HIGH) { | ||||
|         other_dev = dev->info->usb_desc->full; | ||||
|     } else { | ||||
|         other_dev = dev->info->usb_desc->high; | ||||
|     } | ||||
| 
 | ||||
|     switch(type) { | ||||
|     case USB_DT_DEVICE: | ||||
|         ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf)); | ||||
| @ -283,6 +314,21 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len | ||||
|         ret = usb_desc_string(dev, index, buf, sizeof(buf)); | ||||
|         trace_usb_desc_string(dev->addr, index, len, ret); | ||||
|         break; | ||||
| 
 | ||||
|     case USB_DT_DEVICE_QUALIFIER: | ||||
|         if (other_dev != NULL) { | ||||
|             ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf)); | ||||
|         } | ||||
|         trace_usb_desc_device_qualifier(dev->addr, len, ret); | ||||
|         break; | ||||
|     case USB_DT_OTHER_SPEED_CONFIG: | ||||
|         if (other_dev != NULL && index < other_dev->bNumConfigurations) { | ||||
|             ret = usb_desc_config(other_dev->confs + index, buf, sizeof(buf)); | ||||
|             buf[0x01] = USB_DT_OTHER_SPEED_CONFIG; | ||||
|         } | ||||
|         trace_usb_desc_other_speed_config(dev->addr, index, len, ret); | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|         fprintf(stderr, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__, | ||||
|                 dev->addr, type, len); | ||||
|  | ||||
| @ -72,6 +72,8 @@ struct USBDesc { | ||||
| /* generate usb packages from structs */ | ||||
| int usb_desc_device(const USBDescID *id, const USBDescDevice *dev, | ||||
|                     uint8_t *dest, size_t len); | ||||
| int usb_desc_device_qualifier(const USBDescDevice *dev, | ||||
|                               uint8_t *dest, size_t len); | ||||
| int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len); | ||||
| int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len); | ||||
| int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len); | ||||
|  | ||||
							
								
								
									
										2
									
								
								hw/usb.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								hw/usb.h
									
									
									
									
									
								
							| @ -122,6 +122,8 @@ | ||||
| #define USB_DT_STRING			0x03 | ||||
| #define USB_DT_INTERFACE		0x04 | ||||
| #define USB_DT_ENDPOINT			0x05 | ||||
| #define USB_DT_DEVICE_QUALIFIER         0x06 | ||||
| #define USB_DT_OTHER_SPEED_CONFIG       0x07 | ||||
| 
 | ||||
| #define USB_ENDPOINT_XFER_CONTROL	0 | ||||
| #define USB_ENDPOINT_XFER_ISOC		1 | ||||
|  | ||||
| @ -192,7 +192,9 @@ disable sun4m_iommu_bad_addr(uint64_t addr) "bad addr %"PRIx64"" | ||||
| 
 | ||||
| # hw/usb-desc.c | ||||
| disable usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d" | ||||
| disable usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device qualifier, len %d, ret %d" | ||||
| disable usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d" | ||||
| disable usb_desc_other_speed_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d" | ||||
| disable usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d" | ||||
| disable usb_set_addr(int addr) "dev %d" | ||||
| disable usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %d" | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Gerd Hoffmann
						Gerd Hoffmann