Changes in uspace/lib/usb/src/recognise.c [7f56fb7:345ea18] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/recognise.c
r7f56fb7 r345ea18 34 34 */ 35 35 #include <sys/types.h> 36 #include <usb_iface.h> 36 37 #include <usb/usbdrv.h> 37 38 #include <usb/pipes.h> 38 39 #include <usb/recognise.h> 39 #include <usb/ddfiface.h>40 40 #include <usb/request.h> 41 41 #include <usb/classes/classes.h> … … 46 46 static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex); 47 47 48 /** Callback for getting host controller handle. 49 * 50 * @param dev Device in question. 51 * @param[out] handle Devman handle of the host controller. 52 * @return Error code. 53 */ 54 static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle) 55 { 56 assert(dev); 57 assert(dev->parent != NULL); 58 59 device_t *parent = dev->parent; 60 61 if (parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) { 62 usb_iface_t *usb_iface 63 = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE]; 64 assert(usb_iface != NULL); 65 if (usb_iface->get_hc_handle) { 66 int rc = usb_iface->get_hc_handle(parent, handle); 67 return rc; 68 } 69 } 70 71 return ENOTSUP; 72 } 73 74 static usb_iface_t usb_iface = { 75 .get_hc_handle = usb_iface_get_hc_handle 76 }; 77 48 78 device_ops_t child_ops = { 49 .interfaces[USB_DEV_IFACE] = &usb_iface _hub_child_impl79 .interfaces[USB_DEV_IFACE] = &usb_iface 50 80 }; 51 81 … … 112 142 } 113 143 114 #define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \115 do { \116 int __rc = usb_add_match_id((match_ids), (score), \117 format, ##__VA_ARGS__); \118 if (__rc != EOK) { \119 return __rc; \120 } \121 } while (0)122 123 /** Create device match ids based on its interface.124 *125 * @param[in] descriptor Interface descriptor.126 * @param[out] matches Initialized list of match ids.127 * @return Error code (the two mentioned are not the only ones).128 * @retval EINVAL Invalid input parameters (expects non NULL pointers).129 * @retval ENOENT Interface does not specify class.130 */131 int usb_device_create_match_ids_from_interface(132 const usb_standard_device_descriptor_t *desc_device,133 const usb_standard_interface_descriptor_t *desc_interface,134 match_id_list_t *matches)135 {136 if (desc_interface == NULL) {137 return EINVAL;138 }139 if (matches == NULL) {140 return EINVAL;141 }142 143 if (desc_interface->interface_class == USB_CLASS_USE_INTERFACE) {144 return ENOENT;145 }146 147 const char *classname = usb_str_class(desc_interface->interface_class);148 assert(classname != NULL);149 150 #define IFACE_PROTOCOL_FMT "interface&class=%s&subclass=0x%02x&protocol=0x%02x"151 #define IFACE_PROTOCOL_ARGS classname, desc_interface->interface_subclass, \152 desc_interface->interface_protocol153 154 #define IFACE_SUBCLASS_FMT "interface&class=%s&subclass=0x%02x"155 #define IFACE_SUBCLASS_ARGS classname, desc_interface->interface_subclass156 157 #define IFACE_CLASS_FMT "interface&class=%s"158 #define IFACE_CLASS_ARGS classname159 160 #define VENDOR_RELEASE_FMT "vendor=0x%04x&product=0x%04x&release=" BCD_FMT161 #define VENDOR_RELEASE_ARGS desc_device->vendor_id, desc_device->product_id, \162 BCD_ARGS(desc_device->device_version)163 164 #define VENDOR_PRODUCT_FMT "vendor=0x%04x&product=0x%04x"165 #define VENDOR_PRODUCT_ARGS desc_device->vendor_id, desc_device->product_id166 167 #define VENDOR_ONLY_FMT "vendor=0x%04x"168 #define VENDOR_ONLY_ARGS desc_device->vendor_id169 170 /*171 * If the vendor is specified, create match ids with vendor with172 * higher score.173 * Then the same ones without the vendor part.174 */175 if ((desc_device != NULL) && (desc_device->vendor_id != 0)) {176 /* First, interface matches with device release number. */177 ADD_MATCHID_OR_RETURN(matches, 250,178 "usb&" VENDOR_RELEASE_FMT "&" IFACE_PROTOCOL_FMT,179 VENDOR_RELEASE_ARGS, IFACE_PROTOCOL_ARGS);180 ADD_MATCHID_OR_RETURN(matches, 240,181 "usb&" VENDOR_RELEASE_FMT "&" IFACE_SUBCLASS_FMT,182 VENDOR_RELEASE_ARGS, IFACE_SUBCLASS_ARGS);183 ADD_MATCHID_OR_RETURN(matches, 230,184 "usb&" VENDOR_RELEASE_FMT "&" IFACE_CLASS_FMT,185 VENDOR_RELEASE_ARGS, IFACE_CLASS_ARGS);186 187 /* Next, interface matches without release number. */188 ADD_MATCHID_OR_RETURN(matches, 220,189 "usb&" VENDOR_PRODUCT_FMT "&" IFACE_PROTOCOL_FMT,190 VENDOR_PRODUCT_ARGS, IFACE_PROTOCOL_ARGS);191 ADD_MATCHID_OR_RETURN(matches, 210,192 "usb&" VENDOR_PRODUCT_FMT "&" IFACE_SUBCLASS_FMT,193 VENDOR_PRODUCT_ARGS, IFACE_SUBCLASS_ARGS);194 ADD_MATCHID_OR_RETURN(matches, 200,195 "usb&" VENDOR_PRODUCT_FMT "&" IFACE_CLASS_FMT,196 VENDOR_PRODUCT_ARGS, IFACE_CLASS_ARGS);197 198 /* Finally, interface matches with only vendor. */199 ADD_MATCHID_OR_RETURN(matches, 190,200 "usb&" VENDOR_ONLY_FMT "&" IFACE_PROTOCOL_FMT,201 VENDOR_ONLY_ARGS, IFACE_PROTOCOL_ARGS);202 ADD_MATCHID_OR_RETURN(matches, 180,203 "usb&" VENDOR_ONLY_FMT "&" IFACE_SUBCLASS_FMT,204 VENDOR_ONLY_ARGS, IFACE_SUBCLASS_ARGS);205 ADD_MATCHID_OR_RETURN(matches, 170,206 "usb&" VENDOR_ONLY_FMT "&" IFACE_CLASS_FMT,207 VENDOR_ONLY_ARGS, IFACE_CLASS_ARGS);208 }209 210 /* Now, the same but without any vendor specification. */211 ADD_MATCHID_OR_RETURN(matches, 160,212 "usb&" IFACE_PROTOCOL_FMT,213 IFACE_PROTOCOL_ARGS);214 ADD_MATCHID_OR_RETURN(matches, 150,215 "usb&" IFACE_SUBCLASS_FMT,216 IFACE_SUBCLASS_ARGS);217 ADD_MATCHID_OR_RETURN(matches, 140,218 "usb&" IFACE_CLASS_FMT,219 IFACE_CLASS_ARGS);220 221 #undef IFACE_PROTOCOL_FMT222 #undef IFACE_PROTOCOL_ARGS223 #undef IFACE_SUBCLASS_FMT224 #undef IFACE_SUBCLASS_ARGS225 #undef IFACE_CLASS_FMT226 #undef IFACE_CLASS_ARGS227 #undef VENDOR_RELEASE_FMT228 #undef VENDOR_RELEASE_ARGS229 #undef VENDOR_PRODUCT_FMT230 #undef VENDOR_PRODUCT_ARGS231 #undef VENDOR_ONLY_FMT232 #undef VENDOR_ONLY_ARGS233 234 return EOK;235 }236 237 144 /** Create DDF match ids from USB device descriptor. 238 145 * … … 245 152 const usb_standard_device_descriptor_t *device_descriptor) 246 153 { 154 int rc; 155 247 156 /* 248 157 * Unless the vendor id is 0, the pair idVendor-idProduct … … 251 160 if (device_descriptor->vendor_id != 0) { 252 161 /* First, with release number. */ 253 ADD_MATCHID_OR_RETURN(matches, 100,162 rc = usb_add_match_id(matches, 100, 254 163 "usb&vendor=0x%04x&product=0x%04x&release=" BCD_FMT, 255 164 (int) device_descriptor->vendor_id, 256 165 (int) device_descriptor->product_id, 257 166 BCD_ARGS(device_descriptor->device_version)); 167 if (rc != EOK) { 168 return rc; 169 } 258 170 259 171 /* Next, without release number. */ 260 ADD_MATCHID_OR_RETURN(matches, 90,172 rc = usb_add_match_id(matches, 90, 261 173 "usb&vendor=0x%04x&product=0x%04x", 262 174 (int) device_descriptor->vendor_id, 263 175 (int) device_descriptor->product_id); 176 if (rc != EOK) { 177 return rc; 178 } 264 179 } 265 180 266 181 /* 267 182 * If the device class points to interface we skip adding 268 * class directly but we add a multi interface device.183 * class directly. 269 184 */ 270 185 if (device_descriptor->device_class != USB_CLASS_USE_INTERFACE) { 271 ADD_MATCHID_OR_RETURN(matches, 50, "usb&class=%s",186 rc = usb_add_match_id(matches, 50, "usb&class=%s", 272 187 usb_str_class(device_descriptor->device_class)); 273 } else { 274 ADD_MATCHID_OR_RETURN(matches, 50, "usb&mid"); 188 if (rc != EOK) { 189 return rc; 190 } 275 191 } 276 192 … … 278 194 } 279 195 196 /** Create DDF match ids from USB configuration descriptor. 197 * The configuration descriptor is expected to be in the complete form, 198 * i.e. including interface, endpoint etc. descriptors. 199 * 200 * @param matches List of match ids to extend. 201 * @param config_descriptor Configuration descriptor returned by given device. 202 * @param total_size Size of the @p config_descriptor. 203 * @return Error code. 204 */ 205 int usb_drv_create_match_ids_from_configuration_descriptor( 206 match_id_list_t *matches, 207 const void *config_descriptor, size_t total_size) 208 { 209 /* 210 * Iterate through config descriptor to find the interface 211 * descriptors. 212 */ 213 size_t position = sizeof(usb_standard_configuration_descriptor_t); 214 while (position + 1 < total_size) { 215 uint8_t *current_descriptor 216 = ((uint8_t *) config_descriptor) + position; 217 uint8_t cur_descr_len = current_descriptor[0]; 218 uint8_t cur_descr_type = current_descriptor[1]; 219 220 if (cur_descr_len == 0) { 221 return ENOENT; 222 } 223 224 position += cur_descr_len; 225 226 if (cur_descr_type != USB_DESCTYPE_INTERFACE) { 227 continue; 228 } 229 230 /* 231 * Finally, we found an interface descriptor. 232 */ 233 usb_standard_interface_descriptor_t *interface 234 = (usb_standard_interface_descriptor_t *) 235 current_descriptor; 236 237 int rc = usb_add_match_id(matches, 50, 238 "usb&interface&class=%s", 239 usb_str_class(interface->interface_class)); 240 if (rc != EOK) { 241 return rc; 242 } 243 } 244 245 return EOK; 246 } 247 248 /** Add match ids based on configuration descriptor. 249 * 250 * @param pipe Control pipe to the device. 251 * @param matches Match ids list to add matches to. 252 * @param config_count Number of configurations the device has. 253 * @return Error code. 254 */ 255 static int usb_add_config_descriptor_match_ids(usb_endpoint_pipe_t *pipe, 256 match_id_list_t *matches, int config_count) 257 { 258 int final_rc = EOK; 259 260 int config_index; 261 for (config_index = 0; config_index < config_count; config_index++) { 262 int rc; 263 usb_standard_configuration_descriptor_t config_descriptor; 264 rc = usb_request_get_bare_configuration_descriptor(pipe, 265 config_index, &config_descriptor); 266 if (rc != EOK) { 267 final_rc = rc; 268 continue; 269 } 270 271 size_t full_config_descriptor_size; 272 void *full_config_descriptor 273 = malloc(config_descriptor.total_length); 274 rc = usb_request_get_full_configuration_descriptor(pipe, 275 config_index, 276 full_config_descriptor, config_descriptor.total_length, 277 &full_config_descriptor_size); 278 if (rc != EOK) { 279 final_rc = rc; 280 continue; 281 } 282 if (full_config_descriptor_size 283 != config_descriptor.total_length) { 284 final_rc = ERANGE; 285 continue; 286 } 287 288 rc = usb_drv_create_match_ids_from_configuration_descriptor( 289 matches, 290 full_config_descriptor, full_config_descriptor_size); 291 if (rc != EOK) { 292 final_rc = rc; 293 continue; 294 } 295 296 } 297 298 return final_rc; 299 } 280 300 281 301 /** Create match ids describing attached device. … … 310 330 311 331 /* 332 * Go through all configurations and add matches 333 * based on interface class. 334 */ 335 rc = usb_add_config_descriptor_match_ids(ctrl_pipe, matches, 336 device_descriptor.configuration_count); 337 if (rc != EOK) { 338 return rc; 339 } 340 341 /* 312 342 * As a fallback, provide the simplest match id possible. 313 343 */ 314 ADD_MATCHID_OR_RETURN(matches, 1, "usb&fallback"); 344 rc = usb_add_match_id(matches, 1, "usb&fallback"); 345 if (rc != EOK) { 346 return rc; 347 } 315 348 316 349 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.