|  | @@ -831,7 +831,7 @@ usb_probe_all ( struct usb_device *usb,
 | 
		
	
		
			
			| 831 | 831 |  		func->dev.desc.vendor = le16_to_cpu ( usb->device.vendor );
 | 
		
	
		
			
			| 832 | 832 |  		func->dev.desc.device = le16_to_cpu ( usb->device.product );
 | 
		
	
		
			
			| 833 | 833 |  		snprintf ( func->dev.name, sizeof ( func->dev.name ),
 | 
		
	
		
			
			| 834 |  | -			   "%s-%d", usb->name, first );
 | 
		
	
		
			
			|  | 834 | +			   "%s-%d.%d", usb->name, config->config, first );
 | 
		
	
		
			
			| 835 | 835 |  		INIT_LIST_HEAD ( &func->dev.children );
 | 
		
	
		
			
			| 836 | 836 |  		func->dev.parent = bus->dev;
 | 
		
	
		
			
			| 837 | 837 |  
 | 
		
	
	
		
			
			|  | @@ -905,6 +905,133 @@ static void usb_remove_all ( struct usb_device *usb ) {
 | 
		
	
		
			
			| 905 | 905 |  	}
 | 
		
	
		
			
			| 906 | 906 |  }
 | 
		
	
		
			
			| 907 | 907 |  
 | 
		
	
		
			
			|  | 908 | +/**
 | 
		
	
		
			
			|  | 909 | + * Select USB device configuration
 | 
		
	
		
			
			|  | 910 | + *
 | 
		
	
		
			
			|  | 911 | + * @v usb		USB device
 | 
		
	
		
			
			|  | 912 | + * @v index		Configuration index
 | 
		
	
		
			
			|  | 913 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 914 | + */
 | 
		
	
		
			
			|  | 915 | +static int usb_configure ( struct usb_device *usb, unsigned int index ) {
 | 
		
	
		
			
			|  | 916 | +	struct usb_configuration_descriptor partial;
 | 
		
	
		
			
			|  | 917 | +	struct usb_configuration_descriptor *config;
 | 
		
	
		
			
			|  | 918 | +	size_t len;
 | 
		
	
		
			
			|  | 919 | +	int rc;
 | 
		
	
		
			
			|  | 920 | +
 | 
		
	
		
			
			|  | 921 | +	/* Read first part of configuration descriptor to get size */
 | 
		
	
		
			
			|  | 922 | +	if ( ( rc = usb_get_config_descriptor ( usb, index, &partial,
 | 
		
	
		
			
			|  | 923 | +						sizeof ( partial ) ) ) != 0 ) {
 | 
		
	
		
			
			|  | 924 | +		DBGC ( usb, "USB %s could not get configuration descriptor %d: "
 | 
		
	
		
			
			|  | 925 | +		       "%s\n", usb->name, index, strerror ( rc ) );
 | 
		
	
		
			
			|  | 926 | +		goto err_get_partial;
 | 
		
	
		
			
			|  | 927 | +	}
 | 
		
	
		
			
			|  | 928 | +	len = le16_to_cpu ( partial.len );
 | 
		
	
		
			
			|  | 929 | +	if ( len < sizeof ( partial ) ) {
 | 
		
	
		
			
			|  | 930 | +		DBGC ( usb, "USB %s underlength configuraton descriptor %d\n",
 | 
		
	
		
			
			|  | 931 | +		       usb->name, index );
 | 
		
	
		
			
			|  | 932 | +		rc = -EINVAL;
 | 
		
	
		
			
			|  | 933 | +		goto err_partial_len;
 | 
		
	
		
			
			|  | 934 | +	}
 | 
		
	
		
			
			|  | 935 | +
 | 
		
	
		
			
			|  | 936 | +	/* Allocate buffer for whole configuration descriptor */
 | 
		
	
		
			
			|  | 937 | +	config = malloc ( len );
 | 
		
	
		
			
			|  | 938 | +	if ( ! config ) {
 | 
		
	
		
			
			|  | 939 | +		rc = -ENOMEM;
 | 
		
	
		
			
			|  | 940 | +		goto err_alloc_config;
 | 
		
	
		
			
			|  | 941 | +	}
 | 
		
	
		
			
			|  | 942 | +
 | 
		
	
		
			
			|  | 943 | +	/* Read whole configuration descriptor */
 | 
		
	
		
			
			|  | 944 | +	if ( ( rc = usb_get_config_descriptor ( usb, index, config,
 | 
		
	
		
			
			|  | 945 | +						len ) ) != 0 ) {
 | 
		
	
		
			
			|  | 946 | +		DBGC ( usb, "USB %s could not get configuration descriptor %d: "
 | 
		
	
		
			
			|  | 947 | +		       "%s\n", usb->name, index, strerror ( rc ) );
 | 
		
	
		
			
			|  | 948 | +		goto err_get_config_descriptor;
 | 
		
	
		
			
			|  | 949 | +	}
 | 
		
	
		
			
			|  | 950 | +	if ( config->len != partial.len ) {
 | 
		
	
		
			
			|  | 951 | +		DBGC ( usb, "USB %s bad configuration descriptor %d length\n",
 | 
		
	
		
			
			|  | 952 | +		       usb->name, index );
 | 
		
	
		
			
			|  | 953 | +		rc = -EINVAL;
 | 
		
	
		
			
			|  | 954 | +		goto err_config_len;
 | 
		
	
		
			
			|  | 955 | +	}
 | 
		
	
		
			
			|  | 956 | +
 | 
		
	
		
			
			|  | 957 | +	/* Set configuration */
 | 
		
	
		
			
			|  | 958 | +	if ( ( rc = usb_set_configuration ( usb, config->config ) ) != 0){
 | 
		
	
		
			
			|  | 959 | +		DBGC ( usb, "USB %s could not set configuration %d: %s\n",
 | 
		
	
		
			
			|  | 960 | +		       usb->name, config->config, strerror ( rc ) );
 | 
		
	
		
			
			|  | 961 | +		goto err_set_configuration;
 | 
		
	
		
			
			|  | 962 | +	}
 | 
		
	
		
			
			|  | 963 | +
 | 
		
	
		
			
			|  | 964 | +	/* Probe USB device drivers */
 | 
		
	
		
			
			|  | 965 | +	usb_probe_all ( usb, config );
 | 
		
	
		
			
			|  | 966 | +
 | 
		
	
		
			
			|  | 967 | +	/* Free configuration descriptor */
 | 
		
	
		
			
			|  | 968 | +	free ( config );
 | 
		
	
		
			
			|  | 969 | +
 | 
		
	
		
			
			|  | 970 | +	return 0;
 | 
		
	
		
			
			|  | 971 | +
 | 
		
	
		
			
			|  | 972 | +	usb_remove_all ( usb );
 | 
		
	
		
			
			|  | 973 | +	usb_set_configuration ( usb, 0 );
 | 
		
	
		
			
			|  | 974 | + err_set_configuration:
 | 
		
	
		
			
			|  | 975 | + err_config_len:
 | 
		
	
		
			
			|  | 976 | + err_get_config_descriptor:
 | 
		
	
		
			
			|  | 977 | +	free ( config );
 | 
		
	
		
			
			|  | 978 | + err_alloc_config:
 | 
		
	
		
			
			|  | 979 | + err_partial_len:
 | 
		
	
		
			
			|  | 980 | + err_get_partial:
 | 
		
	
		
			
			|  | 981 | +	return rc;
 | 
		
	
		
			
			|  | 982 | +}
 | 
		
	
		
			
			|  | 983 | +
 | 
		
	
		
			
			|  | 984 | +/**
 | 
		
	
		
			
			|  | 985 | + * Clear USB device configuration
 | 
		
	
		
			
			|  | 986 | + *
 | 
		
	
		
			
			|  | 987 | + * @v usb		USB device
 | 
		
	
		
			
			|  | 988 | + */
 | 
		
	
		
			
			|  | 989 | +static void usb_deconfigure ( struct usb_device *usb ) {
 | 
		
	
		
			
			|  | 990 | +	unsigned int i;
 | 
		
	
		
			
			|  | 991 | +
 | 
		
	
		
			
			|  | 992 | +	/* Remove device drivers */
 | 
		
	
		
			
			|  | 993 | +	usb_remove_all ( usb );
 | 
		
	
		
			
			|  | 994 | +
 | 
		
	
		
			
			|  | 995 | +	/* Sanity checks */
 | 
		
	
		
			
			|  | 996 | +	for ( i = 0 ; i < ( sizeof ( usb->ep ) / sizeof ( usb->ep[0] ) ) ; i++){
 | 
		
	
		
			
			|  | 997 | +		if ( i != USB_ENDPOINT_IDX ( USB_EP0_ADDRESS ) )
 | 
		
	
		
			
			|  | 998 | +			assert ( usb->ep[i] == NULL );
 | 
		
	
		
			
			|  | 999 | +	}
 | 
		
	
		
			
			|  | 1000 | +
 | 
		
	
		
			
			|  | 1001 | +	/* Clear device configuration */
 | 
		
	
		
			
			|  | 1002 | +	usb_set_configuration ( usb, 0 );
 | 
		
	
		
			
			|  | 1003 | +}
 | 
		
	
		
			
			|  | 1004 | +
 | 
		
	
		
			
			|  | 1005 | +/**
 | 
		
	
		
			
			|  | 1006 | + * Find and select a supported USB device configuration
 | 
		
	
		
			
			|  | 1007 | + *
 | 
		
	
		
			
			|  | 1008 | + * @v usb		USB device
 | 
		
	
		
			
			|  | 1009 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 1010 | + */
 | 
		
	
		
			
			|  | 1011 | +static int usb_configure_any ( struct usb_device *usb ) {
 | 
		
	
		
			
			|  | 1012 | +	unsigned int index;
 | 
		
	
		
			
			|  | 1013 | +	int rc = -ENOENT;
 | 
		
	
		
			
			|  | 1014 | +
 | 
		
	
		
			
			|  | 1015 | +	/* Attempt all configuration indexes */
 | 
		
	
		
			
			|  | 1016 | +	for ( index = 0 ; index < usb->device.configurations ; index++ ) {
 | 
		
	
		
			
			|  | 1017 | +
 | 
		
	
		
			
			|  | 1018 | +		/* Attempt this configuration index */
 | 
		
	
		
			
			|  | 1019 | +		if ( ( rc = usb_configure ( usb, index ) ) != 0 )
 | 
		
	
		
			
			|  | 1020 | +			continue;
 | 
		
	
		
			
			|  | 1021 | +
 | 
		
	
		
			
			|  | 1022 | +		/* If we have no drivers, then try the next configuration */
 | 
		
	
		
			
			|  | 1023 | +		if ( list_empty ( &usb->functions ) ) {
 | 
		
	
		
			
			|  | 1024 | +			rc = -ENOTSUP;
 | 
		
	
		
			
			|  | 1025 | +			usb_deconfigure ( usb );
 | 
		
	
		
			
			|  | 1026 | +			continue;
 | 
		
	
		
			
			|  | 1027 | +		}
 | 
		
	
		
			
			|  | 1028 | +
 | 
		
	
		
			
			|  | 1029 | +		return 0;
 | 
		
	
		
			
			|  | 1030 | +	}
 | 
		
	
		
			
			|  | 1031 | +
 | 
		
	
		
			
			|  | 1032 | +	return rc;
 | 
		
	
		
			
			|  | 1033 | +}
 | 
		
	
		
			
			|  | 1034 | +
 | 
		
	
		
			
			| 908 | 1035 |  /******************************************************************************
 | 
		
	
		
			
			| 909 | 1036 |   *
 | 
		
	
		
			
			| 910 | 1037 |   * USB device
 | 
		
	
	
		
			
			|  | @@ -948,11 +1075,8 @@ static int register_usb ( struct usb_device *usb ) {
 | 
		
	
		
			
			| 948 | 1075 |  	struct usb_port *port = usb->port;
 | 
		
	
		
			
			| 949 | 1076 |  	struct usb_hub *hub = port->hub;
 | 
		
	
		
			
			| 950 | 1077 |  	struct usb_bus *bus = hub->bus;
 | 
		
	
		
			
			| 951 |  | -	struct usb_configuration_descriptor partial;
 | 
		
	
		
			
			| 952 |  | -	struct usb_configuration_descriptor *config;
 | 
		
	
		
			
			| 953 | 1078 |  	unsigned int protocol;
 | 
		
	
		
			
			| 954 | 1079 |  	size_t mtu;
 | 
		
	
		
			
			| 955 |  | -	size_t len;
 | 
		
	
		
			
			| 956 | 1080 |  	int rc;
 | 
		
	
		
			
			| 957 | 1081 |  
 | 
		
	
		
			
			| 958 | 1082 |  	/* Add to port */
 | 
		
	
	
		
			
			|  | @@ -1040,65 +1164,14 @@ static int register_usb ( struct usb_device *usb ) {
 | 
		
	
		
			
			| 1040 | 1164 |  	       usb_bcd ( le16_to_cpu ( usb->device.protocol ) ),
 | 
		
	
		
			
			| 1041 | 1165 |  	       usb_speed_name ( port->speed ), usb->control.mtu );
 | 
		
	
		
			
			| 1042 | 1166 |  
 | 
		
	
		
			
			| 1043 |  | -	/* Read first part of configuration descriptor to get size */
 | 
		
	
		
			
			| 1044 |  | -	if ( ( rc = usb_get_config_descriptor ( usb, 0, &partial,
 | 
		
	
		
			
			| 1045 |  | -						sizeof ( partial ) ) ) != 0 ) {
 | 
		
	
		
			
			| 1046 |  | -		DBGC ( usb, "USB %s could not get configuration descriptor: "
 | 
		
	
		
			
			| 1047 |  | -		       "%s\n", usb->name, strerror ( rc ) );
 | 
		
	
		
			
			| 1048 |  | -		goto err_get_partial;
 | 
		
	
		
			
			| 1049 |  | -	}
 | 
		
	
		
			
			| 1050 |  | -	len = le16_to_cpu ( partial.len );
 | 
		
	
		
			
			| 1051 |  | -	if ( len < sizeof ( partial ) ) {
 | 
		
	
		
			
			| 1052 |  | -		DBGC ( usb, "USB %s underlength configuraton descriptor\n",
 | 
		
	
		
			
			| 1053 |  | -		       usb->name );
 | 
		
	
		
			
			| 1054 |  | -		rc = -EINVAL;
 | 
		
	
		
			
			| 1055 |  | -		goto err_partial_len;
 | 
		
	
		
			
			| 1056 |  | -	}
 | 
		
	
		
			
			| 1057 |  | -
 | 
		
	
		
			
			| 1058 |  | -	/* Allocate buffer for whole configuration descriptor */
 | 
		
	
		
			
			| 1059 |  | -	config = malloc ( len );
 | 
		
	
		
			
			| 1060 |  | -	if ( ! config ) {
 | 
		
	
		
			
			| 1061 |  | -		rc = -ENOMEM;
 | 
		
	
		
			
			| 1062 |  | -		goto err_alloc_config;
 | 
		
	
		
			
			| 1063 |  | -	}
 | 
		
	
		
			
			| 1064 |  | -
 | 
		
	
		
			
			| 1065 |  | -	/* Read whole configuration descriptor */
 | 
		
	
		
			
			| 1066 |  | -	if ( ( rc = usb_get_config_descriptor ( usb, 0, config, len ) ) != 0 ) {
 | 
		
	
		
			
			| 1067 |  | -		DBGC ( usb, "USB %s could not get configuration descriptor: "
 | 
		
	
		
			
			| 1068 |  | -		       "%s\n", usb->name, strerror ( rc ) );
 | 
		
	
		
			
			| 1069 |  | -		goto err_get_config_descriptor;
 | 
		
	
		
			
			| 1070 |  | -	}
 | 
		
	
		
			
			| 1071 |  | -	if ( config->len != partial.len ) {
 | 
		
	
		
			
			| 1072 |  | -		DBGC ( usb, "USB %s bad configuration descriptor length\n",
 | 
		
	
		
			
			| 1073 |  | -		       usb->name );
 | 
		
	
		
			
			| 1074 |  | -		rc = -EINVAL;
 | 
		
	
		
			
			| 1075 |  | -		goto err_config_len;
 | 
		
	
		
			
			| 1076 |  | -	}
 | 
		
	
		
			
			| 1077 |  | -
 | 
		
	
		
			
			| 1078 |  | -	/* Set configuration */
 | 
		
	
		
			
			| 1079 |  | -	if ( ( rc = usb_set_configuration ( usb, config->config ) ) != 0){
 | 
		
	
		
			
			| 1080 |  | -		DBGC ( usb, "USB %s could not set configuration %#02x: %s\n",
 | 
		
	
		
			
			| 1081 |  | -		       usb->name, config->config, strerror ( rc ) );
 | 
		
	
		
			
			| 1082 |  | -		goto err_set_configuration;
 | 
		
	
		
			
			| 1083 |  | -	}
 | 
		
	
		
			
			| 1084 |  | -
 | 
		
	
		
			
			| 1085 |  | -	/* Probe USB device drivers */
 | 
		
	
		
			
			| 1086 |  | -	usb_probe_all ( usb, config );
 | 
		
	
		
			
			| 1087 |  | -
 | 
		
	
		
			
			| 1088 |  | -	/* Free configuration descriptor */
 | 
		
	
		
			
			| 1089 |  | -	free ( config );
 | 
		
	
		
			
			|  | 1167 | +	/* Configure device */
 | 
		
	
		
			
			|  | 1168 | +	if ( ( rc = usb_configure_any ( usb ) ) != 0 )
 | 
		
	
		
			
			|  | 1169 | +		goto err_configure_any;
 | 
		
	
		
			
			| 1090 | 1170 |  
 | 
		
	
		
			
			| 1091 | 1171 |  	return 0;
 | 
		
	
		
			
			| 1092 | 1172 |  
 | 
		
	
		
			
			| 1093 |  | -	usb_remove_all ( usb );
 | 
		
	
		
			
			| 1094 |  | -	usb_set_configuration ( usb, 0 );
 | 
		
	
		
			
			| 1095 |  | - err_set_configuration:
 | 
		
	
		
			
			| 1096 |  | - err_config_len:
 | 
		
	
		
			
			| 1097 |  | - err_get_config_descriptor:
 | 
		
	
		
			
			| 1098 |  | -	free ( config );
 | 
		
	
		
			
			| 1099 |  | - err_alloc_config:
 | 
		
	
		
			
			| 1100 |  | - err_partial_len:
 | 
		
	
		
			
			| 1101 |  | - err_get_partial:
 | 
		
	
		
			
			|  | 1173 | +	usb_deconfigure ( usb );
 | 
		
	
		
			
			|  | 1174 | + err_configure_any:
 | 
		
	
		
			
			| 1102 | 1175 |   err_get_device_descriptor:
 | 
		
	
		
			
			| 1103 | 1176 |   err_mtu:
 | 
		
	
		
			
			| 1104 | 1177 |   err_get_mtu:
 | 
		
	
	
		
			
			|  | @@ -1126,20 +1199,12 @@ static void unregister_usb ( struct usb_device *usb ) {
 | 
		
	
		
			
			| 1126 | 1199 |  	struct usb_hub *hub = port->hub;
 | 
		
	
		
			
			| 1127 | 1200 |  	struct io_buffer *iobuf;
 | 
		
	
		
			
			| 1128 | 1201 |  	struct io_buffer *tmp;
 | 
		
	
		
			
			| 1129 |  | -	unsigned int i;
 | 
		
	
		
			
			| 1130 |  | -
 | 
		
	
		
			
			| 1131 |  | -	/* Remove device drivers */
 | 
		
	
		
			
			| 1132 |  | -	usb_remove_all ( usb );
 | 
		
	
		
			
			| 1133 | 1202 |  
 | 
		
	
		
			
			| 1134 | 1203 |  	/* Sanity checks */
 | 
		
	
		
			
			| 1135 |  | -	for ( i = 0 ; i < ( sizeof ( usb->ep ) / sizeof ( usb->ep[0] ) ) ; i++){
 | 
		
	
		
			
			| 1136 |  | -		if ( i != USB_ENDPOINT_IDX ( USB_EP0_ADDRESS ) )
 | 
		
	
		
			
			| 1137 |  | -			assert ( usb->ep[i] == NULL );
 | 
		
	
		
			
			| 1138 |  | -	}
 | 
		
	
		
			
			| 1139 | 1204 |  	assert ( port->usb == usb );
 | 
		
	
		
			
			| 1140 | 1205 |  
 | 
		
	
		
			
			| 1141 | 1206 |  	/* Clear device configuration */
 | 
		
	
		
			
			| 1142 |  | -	usb_set_configuration ( usb, 0 );
 | 
		
	
		
			
			|  | 1207 | +	usb_deconfigure ( usb );
 | 
		
	
		
			
			| 1143 | 1208 |  
 | 
		
	
		
			
			| 1144 | 1209 |  	/* Close control endpoint */
 | 
		
	
		
			
			| 1145 | 1210 |  	usb_endpoint_close ( &usb->control );
 |