Changeset deece2f in mainline for uspace/lib/usb/src/recognise.c
- Timestamp:
- 2011-02-21T22:25:58Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 233e68d
- Parents:
- fb78ae72 (diff), dbe25f1 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/recognise.c
rfb78ae72 rdeece2f 34 34 */ 35 35 #include <sys/types.h> 36 #include <usb_iface.h>37 #include <usb/usbdrv.h>38 36 #include <usb/pipes.h> 39 37 #include <usb/recognise.h> 38 #include <usb/ddfiface.h> 40 39 #include <usb/request.h> 41 40 #include <usb/classes/classes.h> … … 46 45 static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex); 47 46 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_iface63 = (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_handle76 };77 78 47 device_ops_t child_ops = { 79 .interfaces[USB_DEV_IFACE] = &usb_iface 48 .interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl 80 49 }; 81 50 … … 142 111 } 143 112 113 #define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \ 114 do { \ 115 int __rc = usb_add_match_id((match_ids), (score), \ 116 format, ##__VA_ARGS__); \ 117 if (__rc != EOK) { \ 118 return __rc; \ 119 } \ 120 } while (0) 121 122 /** Create device match ids based on its interface. 123 * 124 * @param[in] descriptor Interface descriptor. 125 * @param[out] matches Initialized list of match ids. 126 * @return Error code (the two mentioned are not the only ones). 127 * @retval EINVAL Invalid input parameters (expects non NULL pointers). 128 * @retval ENOENT Interface does not specify class. 129 */ 130 int usb_device_create_match_ids_from_interface( 131 const usb_standard_device_descriptor_t *desc_device, 132 const usb_standard_interface_descriptor_t *desc_interface, 133 match_id_list_t *matches) 134 { 135 if (desc_interface == NULL) { 136 return EINVAL; 137 } 138 if (matches == NULL) { 139 return EINVAL; 140 } 141 142 if (desc_interface->interface_class == USB_CLASS_USE_INTERFACE) { 143 return ENOENT; 144 } 145 146 const char *classname = usb_str_class(desc_interface->interface_class); 147 assert(classname != NULL); 148 149 #define IFACE_PROTOCOL_FMT "interface&class=%s&subclass=0x%02x&protocol=0x%02x" 150 #define IFACE_PROTOCOL_ARGS classname, desc_interface->interface_subclass, \ 151 desc_interface->interface_protocol 152 153 #define IFACE_SUBCLASS_FMT "interface&class=%s&subclass=0x%02x" 154 #define IFACE_SUBCLASS_ARGS classname, desc_interface->interface_subclass 155 156 #define IFACE_CLASS_FMT "interface&class=%s" 157 #define IFACE_CLASS_ARGS classname 158 159 #define VENDOR_RELEASE_FMT "vendor=0x%04x&product=0x%04x&release=" BCD_FMT 160 #define VENDOR_RELEASE_ARGS desc_device->vendor_id, desc_device->product_id, \ 161 BCD_ARGS(desc_device->device_version) 162 163 #define VENDOR_PRODUCT_FMT "vendor=0x%04x&product=0x%04x" 164 #define VENDOR_PRODUCT_ARGS desc_device->vendor_id, desc_device->product_id 165 166 #define VENDOR_ONLY_FMT "vendor=0x%04x" 167 #define VENDOR_ONLY_ARGS desc_device->vendor_id 168 169 /* 170 * If the vendor is specified, create match ids with vendor with 171 * higher score. 172 * Then the same ones without the vendor part. 173 */ 174 if ((desc_device != NULL) && (desc_device->vendor_id != 0)) { 175 /* First, interface matches with device release number. */ 176 ADD_MATCHID_OR_RETURN(matches, 250, 177 "usb&" VENDOR_RELEASE_FMT "&" IFACE_PROTOCOL_FMT, 178 VENDOR_RELEASE_ARGS, IFACE_PROTOCOL_ARGS); 179 ADD_MATCHID_OR_RETURN(matches, 240, 180 "usb&" VENDOR_RELEASE_FMT "&" IFACE_SUBCLASS_FMT, 181 VENDOR_RELEASE_ARGS, IFACE_SUBCLASS_ARGS); 182 ADD_MATCHID_OR_RETURN(matches, 230, 183 "usb&" VENDOR_RELEASE_FMT "&" IFACE_CLASS_FMT, 184 VENDOR_RELEASE_ARGS, IFACE_CLASS_ARGS); 185 186 /* Next, interface matches without release number. */ 187 ADD_MATCHID_OR_RETURN(matches, 220, 188 "usb&" VENDOR_PRODUCT_FMT "&" IFACE_PROTOCOL_FMT, 189 VENDOR_PRODUCT_ARGS, IFACE_PROTOCOL_ARGS); 190 ADD_MATCHID_OR_RETURN(matches, 210, 191 "usb&" VENDOR_PRODUCT_FMT "&" IFACE_SUBCLASS_FMT, 192 VENDOR_PRODUCT_ARGS, IFACE_SUBCLASS_ARGS); 193 ADD_MATCHID_OR_RETURN(matches, 200, 194 "usb&" VENDOR_PRODUCT_FMT "&" IFACE_CLASS_FMT, 195 VENDOR_PRODUCT_ARGS, IFACE_CLASS_ARGS); 196 197 /* Finally, interface matches with only vendor. */ 198 ADD_MATCHID_OR_RETURN(matches, 190, 199 "usb&" VENDOR_ONLY_FMT "&" IFACE_PROTOCOL_FMT, 200 VENDOR_ONLY_ARGS, IFACE_PROTOCOL_ARGS); 201 ADD_MATCHID_OR_RETURN(matches, 180, 202 "usb&" VENDOR_ONLY_FMT "&" IFACE_SUBCLASS_FMT, 203 VENDOR_ONLY_ARGS, IFACE_SUBCLASS_ARGS); 204 ADD_MATCHID_OR_RETURN(matches, 170, 205 "usb&" VENDOR_ONLY_FMT "&" IFACE_CLASS_FMT, 206 VENDOR_ONLY_ARGS, IFACE_CLASS_ARGS); 207 } 208 209 /* Now, the same but without any vendor specification. */ 210 ADD_MATCHID_OR_RETURN(matches, 160, 211 "usb&" IFACE_PROTOCOL_FMT, 212 IFACE_PROTOCOL_ARGS); 213 ADD_MATCHID_OR_RETURN(matches, 150, 214 "usb&" IFACE_SUBCLASS_FMT, 215 IFACE_SUBCLASS_ARGS); 216 ADD_MATCHID_OR_RETURN(matches, 140, 217 "usb&" IFACE_CLASS_FMT, 218 IFACE_CLASS_ARGS); 219 220 #undef IFACE_PROTOCOL_FMT 221 #undef IFACE_PROTOCOL_ARGS 222 #undef IFACE_SUBCLASS_FMT 223 #undef IFACE_SUBCLASS_ARGS 224 #undef IFACE_CLASS_FMT 225 #undef IFACE_CLASS_ARGS 226 #undef VENDOR_RELEASE_FMT 227 #undef VENDOR_RELEASE_ARGS 228 #undef VENDOR_PRODUCT_FMT 229 #undef VENDOR_PRODUCT_ARGS 230 #undef VENDOR_ONLY_FMT 231 #undef VENDOR_ONLY_ARGS 232 233 return EOK; 234 } 235 144 236 /** Create DDF match ids from USB device descriptor. 145 237 * … … 148 240 * @return Error code. 149 241 */ 150 int usb_d rv_create_match_ids_from_device_descriptor(151 match_id_list_t *matches,152 const usb_standard_device_descriptor_t *device_descriptor)242 int usb_device_create_match_ids_from_device_descriptor( 243 const usb_standard_device_descriptor_t *device_descriptor, 244 match_id_list_t *matches) 153 245 { 154 int rc;155 156 246 /* 157 247 * Unless the vendor id is 0, the pair idVendor-idProduct … … 160 250 if (device_descriptor->vendor_id != 0) { 161 251 /* First, with release number. */ 162 rc = usb_add_match_id(matches, 100,252 ADD_MATCHID_OR_RETURN(matches, 100, 163 253 "usb&vendor=0x%04x&product=0x%04x&release=" BCD_FMT, 164 254 (int) device_descriptor->vendor_id, 165 255 (int) device_descriptor->product_id, 166 256 BCD_ARGS(device_descriptor->device_version)); 167 if (rc != EOK) {168 return rc;169 }170 257 171 258 /* Next, without release number. */ 172 rc = usb_add_match_id(matches, 90,259 ADD_MATCHID_OR_RETURN(matches, 90, 173 260 "usb&vendor=0x%04x&product=0x%04x", 174 261 (int) device_descriptor->vendor_id, 175 262 (int) device_descriptor->product_id); 176 if (rc != EOK) {177 return rc;178 }179 263 } 180 264 181 265 /* 182 266 * If the device class points to interface we skip adding 183 * class directly .267 * class directly but we add a multi interface device. 184 268 */ 185 269 if (device_descriptor->device_class != USB_CLASS_USE_INTERFACE) { 186 rc = usb_add_match_id(matches, 50, "usb&class=%s",270 ADD_MATCHID_OR_RETURN(matches, 50, "usb&class=%s", 187 271 usb_str_class(device_descriptor->device_class)); 188 if (rc != EOK) { 189 return rc; 190 } 272 } else { 273 ADD_MATCHID_OR_RETURN(matches, 50, "usb&mid"); 191 274 } 192 275 … … 194 277 } 195 278 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 interface211 * descriptors.212 */213 size_t position = sizeof(usb_standard_configuration_descriptor_t);214 while (position + 1 < total_size) {215 uint8_t *current_descriptor216 = ((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 *interface234 = (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_descriptor273 = 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_size283 != 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 }300 279 301 280 /** Create match ids describing attached device. … … 323 302 } 324 303 325 rc = usb_d rv_create_match_ids_from_device_descriptor(matches,326 &device_descriptor );304 rc = usb_device_create_match_ids_from_device_descriptor( 305 &device_descriptor, matches); 327 306 if (rc != EOK) { 328 307 return rc; … … 330 309 331 310 /* 332 * Go through all configurations and add matches333 * 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 /*342 311 * As a fallback, provide the simplest match id possible. 343 312 */ 344 rc = usb_add_match_id(matches, 1, "usb&fallback"); 345 if (rc != EOK) { 346 return rc; 347 } 313 ADD_MATCHID_OR_RETURN(matches, 1, "usb&fallback"); 348 314 349 315 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.