usb-linux: catch ENODEV in more places.
Factor out disconnect code (called when a device disappears) to a separate function. Add a check for ENODEV errno to a few more places to make sure we notice disconnects. Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
		
							parent
							
								
									0b862cedf3
								
							
						
					
					
						commit
						41c01ee715
					
				
							
								
								
									
										27
									
								
								usb-linux.c
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								usb-linux.c
									
									
									
									
									
								
							| @ -267,6 +267,14 @@ static void async_free(AsyncURB *aurb) | ||||
|     qemu_free(aurb); | ||||
| } | ||||
| 
 | ||||
| static void do_disconnect(USBHostDevice *s) | ||||
| { | ||||
|     printf("husb: device %d.%d disconnected\n", | ||||
|            s->bus_num, s->addr); | ||||
|     usb_host_close(s); | ||||
|     usb_host_auto_check(NULL); | ||||
| } | ||||
| 
 | ||||
| static void async_complete(void *opaque) | ||||
| { | ||||
|     USBHostDevice *s = opaque; | ||||
| @ -281,10 +289,7 @@ static void async_complete(void *opaque) | ||||
|                 return; | ||||
|             } | ||||
|             if (errno == ENODEV && !s->closing) { | ||||
|                 printf("husb: device %d.%d disconnected\n", | ||||
|                        s->bus_num, s->addr); | ||||
|                 usb_host_close(s); | ||||
|                 usb_host_auto_check(NULL); | ||||
|                 do_disconnect(s); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
| @ -358,6 +363,7 @@ static void usb_host_async_cancel(USBDevice *dev, USBPacket *p) | ||||
| 
 | ||||
| static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration) | ||||
| { | ||||
|     const char *op = NULL; | ||||
|     int dev_descr_len, config_descr_len; | ||||
|     int interface, nb_interfaces; | ||||
|     int ret, i; | ||||
| @ -410,9 +416,9 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration) | ||||
|             ctrl.ioctl_code = USBDEVFS_DISCONNECT; | ||||
|             ctrl.ifno = interface; | ||||
|             ctrl.data = 0; | ||||
|             op = "USBDEVFS_DISCONNECT"; | ||||
|             ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl); | ||||
|             if (ret < 0 && errno != ENODATA) { | ||||
|                 perror("USBDEVFS_DISCONNECT"); | ||||
|                 goto fail; | ||||
|             } | ||||
|         } | ||||
| @ -421,6 +427,7 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration) | ||||
| 
 | ||||
|     /* XXX: only grab if all interfaces are free */ | ||||
|     for (interface = 0; interface < nb_interfaces; interface++) { | ||||
|         op = "USBDEVFS_CLAIMINTERFACE"; | ||||
|         ret = ioctl(dev->fd, USBDEVFS_CLAIMINTERFACE, &interface); | ||||
|         if (ret < 0) { | ||||
|             if (errno == EBUSY) { | ||||
| @ -428,8 +435,7 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration) | ||||
|             } else { | ||||
|                 perror("husb: failed to claim interface"); | ||||
|             } | ||||
|         fail: | ||||
|             return 0; | ||||
|             goto fail; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -439,6 +445,13 @@ static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration) | ||||
|     dev->ninterfaces   = nb_interfaces; | ||||
|     dev->configuration = configuration; | ||||
|     return 1; | ||||
| 
 | ||||
| fail: | ||||
|     if (errno == ENODEV) { | ||||
|         do_disconnect(dev); | ||||
|     } | ||||
|     perror(op); | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static int usb_host_release_interfaces(USBHostDevice *s) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Gerd Hoffmann
						Gerd Hoffmann