Changes in uspace/lib/usb/src/recognise.c [345ea18:7f56fb7] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/src/recognise.c
r345ea18 r7f56fb7 34 34 */ 35 35 #include <sys/types.h> 36 #include <usb_iface.h>37 36 #include <usb/usbdrv.h> 38 37 #include <usb/pipes.h> 39 38 #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_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 48 device_ops_t child_ops = { 79 .interfaces[USB_DEV_IFACE] = &usb_iface 49 .interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl 80 50 }; 81 51 … … 142 112 } 143 113 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_protocol 153 154 #define IFACE_SUBCLASS_FMT "interface&class=%s&subclass=0x%02x" 155 #define IFACE_SUBCLASS_ARGS classname, desc_interface->interface_subclass 156 157 #define IFACE_CLASS_FMT "interface&class=%s" 158 #define IFACE_CLASS_ARGS classname 159 160 #define VENDOR_RELEASE_FMT "vendor=0x%04x&product=0x%04x&release=" BCD_FMT 161 #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_id 166 167 #define VENDOR_ONLY_FMT "vendor=0x%04x" 168 #define VENDOR_ONLY_ARGS desc_device->vendor_id 169 170 /* 171 * If the vendor is specified, create match ids with vendor with 172 * 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_FMT 222 #undef IFACE_PROTOCOL_ARGS 223 #undef IFACE_SUBCLASS_FMT 224 #undef IFACE_SUBCLASS_ARGS 225 #undef IFACE_CLASS_FMT 226 #undef IFACE_CLASS_ARGS 227 #undef VENDOR_RELEASE_FMT 228 #undef VENDOR_RELEASE_ARGS 229 #undef VENDOR_PRODUCT_FMT 230 #undef VENDOR_PRODUCT_ARGS 231 #undef VENDOR_ONLY_FMT 232 #undef VENDOR_ONLY_ARGS 233 234 return EOK; 235 } 236 144 237 /** Create DDF match ids from USB device descriptor. 145 238 * … … 152 245 const usb_standard_device_descriptor_t *device_descriptor) 153 246 { 154 int rc;155 156 247 /* 157 248 * Unless the vendor id is 0, the pair idVendor-idProduct … … 160 251 if (device_descriptor->vendor_id != 0) { 161 252 /* First, with release number. */ 162 rc = usb_add_match_id(matches, 100,253 ADD_MATCHID_OR_RETURN(matches, 100, 163 254 "usb&vendor=0x%04x&product=0x%04x&release=" BCD_FMT, 164 255 (int) device_descriptor->vendor_id, 165 256 (int) device_descriptor->product_id, 166 257 BCD_ARGS(device_descriptor->device_version)); 167 if (rc != EOK) {168 return rc;169 }170 258 171 259 /* Next, without release number. */ 172 rc = usb_add_match_id(matches, 90,260 ADD_MATCHID_OR_RETURN(matches, 90, 173 261 "usb&vendor=0x%04x&product=0x%04x", 174 262 (int) device_descriptor->vendor_id, 175 263 (int) device_descriptor->product_id); 176 if (rc != EOK) {177 return rc;178 }179 264 } 180 265 181 266 /* 182 267 * If the device class points to interface we skip adding 183 * class directly .268 * class directly but we add a multi interface device. 184 269 */ 185 270 if (device_descriptor->device_class != USB_CLASS_USE_INTERFACE) { 186 rc = usb_add_match_id(matches, 50, "usb&class=%s",271 ADD_MATCHID_OR_RETURN(matches, 50, "usb&class=%s", 187 272 usb_str_class(device_descriptor->device_class)); 188 if (rc != EOK) { 189 return rc; 190 } 273 } else { 274 ADD_MATCHID_OR_RETURN(matches, 50, "usb&mid"); 191 275 } 192 276 … … 194 278 } 195 279 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 280 301 281 /** Create match ids describing attached device. … … 330 310 331 311 /* 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 312 * As a fallback, provide the simplest match id possible. 343 313 */ 344 rc = usb_add_match_id(matches, 1, "usb&fallback"); 345 if (rc != EOK) { 346 return rc; 347 } 314 ADD_MATCHID_OR_RETURN(matches, 1, "usb&fallback"); 348 315 349 316 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.