|
@@ -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 );
|