Changes in / [c7bdfa7:1cbb4b7] in mainline
- Location:
- uspace/lib/usb
- Files:
-
- 1 deleted
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/usb/Makefile
rc7bdfa7 r1cbb4b7 34 34 SOURCES = \ 35 35 src/addrkeep.c \ 36 src/altiface.c \37 36 src/class.c \ 38 37 src/ddfiface.c \ -
uspace/lib/usb/include/usb/devdrv.h
rc7bdfa7 r1cbb4b7 174 174 usb_endpoint_mapping_t **, size_t *); 175 175 int usb_device_destroy_pipes(ddf_dev_t *, usb_endpoint_mapping_t *, size_t); 176 int usb_device_create(ddf_dev_t *, usb_endpoint_description_t **, usb_device_t **, const char **);177 176 178 177 size_t usb_interface_count_alternates(uint8_t *, size_t, uint8_t); 179 int usb_alternate_interfaces_create(uint8_t *, size_t, int,180 usb_alternate_interfaces_t **);181 178 182 179 #endif -
uspace/lib/usb/include/usb/request.h
rc7bdfa7 r1cbb4b7 50 50 /** USB endpoint status - endpoint is halted (stalled). */ 51 51 #define USB_ENDPOINT_STATUS_HALTED ((uint16_t)(1 << 0)) 52 53 /** USB feature selector - endpoint halt (stall). */54 #define USB_FEATURE_SELECTOR_ENDPOINT_HALT (0)55 56 /** USB feature selector - device remote wake-up. */57 #define USB_FEATURE_SELECTOR_REMOTE_WAKEUP (1)58 52 59 53 /** Standard device request. */ … … 141 135 char **); 142 136 143 int usb_request_clear_endpoint_halt(usb_pipe_t *, uint16_t);144 145 137 #endif 146 138 /** -
uspace/lib/usb/src/devdrv.c
rc7bdfa7 r1cbb4b7 100 100 usb_device_t *dev, int alternate_setting) 101 101 { 102 if (endpoints == NULL) {103 dev->pipes = NULL;104 dev->pipes_count = 0;105 return EOK;106 }107 108 102 usb_endpoint_mapping_t *pipes; 109 103 size_t pipes_count; … … 115 109 116 110 if (rc != EOK) { 111 usb_log_error( 112 "Failed to create endpoint pipes for `%s': %s.\n", 113 dev->ddf_dev->name, str_error(rc)); 117 114 return rc; 118 115 } … … 120 117 dev->pipes = pipes; 121 118 dev->pipes_count = pipes_count; 119 120 return EOK; 121 } 122 123 /** Initialize all endpoint pipes. 124 * 125 * @param drv The driver. 126 * @param dev The device to be initialized. 127 * @return Error code. 128 */ 129 static int initialize_pipes(usb_device_t *dev) 130 { 131 int rc; 132 133 rc = usb_device_connection_initialize_from_device(&dev->wire, 134 dev->ddf_dev); 135 if (rc != EOK) { 136 usb_log_error( 137 "Failed initializing connection on device `%s'. %s.\n", 138 dev->ddf_dev->name, str_error(rc)); 139 return rc; 140 } 141 142 rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe, 143 &dev->wire); 144 if (rc != EOK) { 145 usb_log_error("Failed to initialize default control pipe " \ 146 "on device `%s': %s.\n", 147 dev->ddf_dev->name, str_error(rc)); 148 return rc; 149 } 150 151 rc = usb_pipe_probe_default_control(&dev->ctrl_pipe); 152 if (rc != EOK) { 153 usb_log_error( 154 "Probing default control pipe on device `%s' failed: %s.\n", 155 dev->ddf_dev->name, str_error(rc)); 156 return rc; 157 } 158 159 /* Get our interface. */ 160 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev); 161 162 /* 163 * We will do some querying of the device, it is worth to prepare 164 * the long transfer. 165 */ 166 rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe); 167 if (rc != EOK) { 168 usb_log_error("Failed to start transfer: %s.\n", 169 str_error(rc)); 170 return rc; 171 } 172 173 /* Retrieve the descriptors. */ 174 rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe, 175 &dev->descriptors); 176 if (rc != EOK) { 177 usb_log_error("Failed to retrieve standard device " \ 178 "descriptors of %s: %s.\n", 179 dev->ddf_dev->name, str_error(rc)); 180 return rc; 181 } 182 183 184 if (driver->endpoints != NULL) { 185 rc = initialize_other_pipes(driver->endpoints, dev, 0); 186 } 187 188 usb_pipe_end_long_transfer(&dev->ctrl_pipe); 189 190 /* Rollback actions. */ 191 if (rc != EOK) { 192 if (dev->descriptors.configuration != NULL) { 193 free(dev->descriptors.configuration); 194 } 195 } 196 197 return rc; 198 } 199 200 /** Count number of alternate settings of a interface. 201 * 202 * @param config_descr Full configuration descriptor. 203 * @param config_descr_size Size of @p config_descr in bytes. 204 * @param interface_no Interface number. 205 * @return Number of alternate interfaces for @p interface_no interface. 206 */ 207 size_t usb_interface_count_alternates(uint8_t *config_descr, 208 size_t config_descr_size, uint8_t interface_no) 209 { 210 assert(config_descr != NULL); 211 assert(config_descr_size > 0); 212 213 usb_dp_parser_t dp_parser = { 214 .nesting = usb_dp_standard_descriptor_nesting 215 }; 216 usb_dp_parser_data_t dp_data = { 217 .data = config_descr, 218 .size = config_descr_size, 219 .arg = NULL 220 }; 221 222 size_t alternate_count = 0; 223 224 uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser, 225 &dp_data, config_descr); 226 while (iface_ptr != NULL) { 227 usb_standard_interface_descriptor_t *iface 228 = (usb_standard_interface_descriptor_t *) iface_ptr; 229 if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) { 230 if (iface->interface_number == interface_no) { 231 alternate_count++; 232 } 233 } 234 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data, 235 config_descr, iface_ptr); 236 } 237 238 return alternate_count; 239 } 240 241 /** Initialize structures related to alternate interfaces. 242 * 243 * @param dev Device where alternate settings shall be initialized. 244 * @return Error code. 245 */ 246 static int initialize_alternate_interfaces(usb_device_t *dev) 247 { 248 if (dev->interface_no < 0) { 249 dev->alternate_interfaces = NULL; 250 return EOK; 251 } 252 253 usb_alternate_interfaces_t *alternates 254 = malloc(sizeof(usb_alternate_interfaces_t)); 255 256 if (alternates == NULL) { 257 return ENOMEM; 258 } 259 260 alternates->alternative_count 261 = usb_interface_count_alternates(dev->descriptors.configuration, 262 dev->descriptors.configuration_size, dev->interface_no); 263 264 if (alternates->alternative_count == 0) { 265 free(alternates); 266 return ENOENT; 267 } 268 269 alternates->alternatives = malloc(alternates->alternative_count 270 * sizeof(usb_alternate_interface_descriptors_t)); 271 if (alternates->alternatives == NULL) { 272 free(alternates); 273 return ENOMEM; 274 } 275 276 alternates->current = 0; 277 278 usb_dp_parser_t dp_parser = { 279 .nesting = usb_dp_standard_descriptor_nesting 280 }; 281 usb_dp_parser_data_t dp_data = { 282 .data = dev->descriptors.configuration, 283 .size = dev->descriptors.configuration_size, 284 .arg = NULL 285 }; 286 287 usb_alternate_interface_descriptors_t *cur_alt_iface 288 = &alternates->alternatives[0]; 289 290 uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser, 291 &dp_data, dp_data.data); 292 while (iface_ptr != NULL) { 293 usb_standard_interface_descriptor_t *iface 294 = (usb_standard_interface_descriptor_t *) iface_ptr; 295 if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE) 296 || (iface->interface_number != dev->interface_no)) { 297 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, 298 &dp_data, 299 dp_data.data, iface_ptr); 300 continue; 301 } 302 303 cur_alt_iface->interface = iface; 304 cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface); 305 306 /* Find next interface to count size of nested descriptors. */ 307 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data, 308 dp_data.data, iface_ptr); 309 if (iface_ptr == NULL) { 310 uint8_t *next = dp_data.data + dp_data.size; 311 cur_alt_iface->nested_descriptors_size 312 = next - cur_alt_iface->nested_descriptors; 313 } else { 314 cur_alt_iface->nested_descriptors_size 315 = iface_ptr - cur_alt_iface->nested_descriptors; 316 } 317 318 cur_alt_iface++; 319 } 320 321 dev->alternate_interfaces = alternates; 122 322 123 323 return EOK; … … 139 339 int rc; 140 340 141 usb_device_t *dev = NULL; 142 const char *err_msg = NULL; 143 rc = usb_device_create(gen_dev, driver->endpoints, &dev, &err_msg); 144 if (rc != EOK) { 145 usb_log_error("USB device `%s' creation failed (%s): %s.\n", 146 gen_dev->name, err_msg, str_error(rc)); 147 return rc; 148 } 341 usb_device_t *dev = malloc(sizeof(usb_device_t)); 342 if (dev == NULL) { 343 usb_log_error("Out of memory when adding device `%s'.\n", 344 gen_dev->name); 345 return ENOMEM; 346 } 347 348 349 dev->ddf_dev = gen_dev; 350 dev->ddf_dev->driver_data = dev; 351 dev->driver_data = NULL; 352 dev->descriptors.configuration = NULL; 353 354 dev->pipes_count = 0; 355 dev->pipes = NULL; 356 357 rc = initialize_pipes(dev); 358 if (rc != EOK) { 359 free(dev); 360 return rc; 361 } 362 363 (void) initialize_alternate_interfaces(dev); 149 364 150 365 return driver->ops->add_device(dev); … … 180 395 * with usb_pipe_initialize_from_configuration(). 181 396 * 182 * @warning This is a wrapper function that does several operations that183 * can fail and that cannot be rollbacked easily. That means that a failure184 * during the SET_INTERFACE request would result in having a device with185 * no pipes at all (except the default control one). That is because the old186 * pipes needs to be unregistered at HC first and the new ones could not187 * be created.188 *189 397 * @param dev USB device. 190 398 * @param alternate_setting Alternate setting to choose. … … 201 409 int rc; 202 410 411 /* TODO: more transactional behavior. */ 412 203 413 /* Destroy existing pipes. */ 204 414 rc = destroy_current_pipes(dev); … … 222 432 /** Retrieve basic descriptors from the device. 223 433 * 224 * @param[in] ctrl_pipe Control endpoint pipe.434 * @param[in] ctrl_pipe Control pipe with opened session. 225 435 * @param[out] descriptors Where to store the descriptors. 226 436 * @return Error code. … … 230 440 { 231 441 assert(descriptors != NULL); 442 assert(usb_pipe_is_session_started(ctrl_pipe)); 232 443 233 444 descriptors->configuration = NULL; 234 445 235 446 int rc; 236 237 /* It is worth to start a long transfer. */238 rc = usb_pipe_start_long_transfer(ctrl_pipe);239 if (rc != EOK) {240 return rc;241 }242 447 243 448 /* Get the device descriptor. */ 244 449 rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device); 245 450 if (rc != EOK) { 246 goto leave;451 return rc; 247 452 } 248 453 … … 251 456 ctrl_pipe, 0, (void **) &descriptors->configuration, 252 457 &descriptors->configuration_size); 253 254 leave: 255 usb_pipe_end_long_transfer(ctrl_pipe);256 257 return rc;458 if (rc != EOK) { 459 return rc; 460 } 461 462 return EOK; 258 463 } 259 464 … … 436 641 } 437 642 438 /** Initialize control pipe in a device.439 *440 * @param dev USB device in question.441 * @param errmsg Where to store error context.442 * @return443 */444 static int init_wire_and_ctrl_pipe(usb_device_t *dev, const char **errmsg)445 {446 int rc;447 448 rc = usb_device_connection_initialize_from_device(&dev->wire,449 dev->ddf_dev);450 if (rc != EOK) {451 *errmsg = "device connection initialization";452 return rc;453 }454 455 rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,456 &dev->wire);457 if (rc != EOK) {458 *errmsg = "default control pipe initialization";459 return rc;460 }461 462 return EOK;463 }464 465 466 /** Create new instance of USB device.467 *468 * @param[in] ddf_dev Generic DDF device backing the USB one.469 * @param[in] endpoints NULL terminated array of endpoints (NULL for none).470 * @param[out] dev_ptr Where to store pointer to the new device.471 * @param[out] errstr_ptr Where to store description of context472 * (in case error occurs).473 * @return Error code.474 */475 int usb_device_create(ddf_dev_t *ddf_dev,476 usb_endpoint_description_t **endpoints,477 usb_device_t **dev_ptr, const char **errstr_ptr)478 {479 assert(dev_ptr != NULL);480 assert(ddf_dev != NULL);481 482 int rc;483 484 usb_device_t *dev = malloc(sizeof(usb_device_t));485 if (dev == NULL) {486 *errstr_ptr = "structure allocation";487 return ENOMEM;488 }489 490 // FIXME: proper deallocation in case of errors491 492 dev->ddf_dev = ddf_dev;493 dev->driver_data = NULL;494 dev->descriptors.configuration = NULL;495 dev->alternate_interfaces = NULL;496 497 dev->pipes_count = 0;498 dev->pipes = NULL;499 500 /* Initialize backing wire and control pipe. */501 rc = init_wire_and_ctrl_pipe(dev, errstr_ptr);502 if (rc != EOK) {503 return rc;504 }505 506 /* Get our interface. */507 dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);508 509 /* Retrieve standard descriptors. */510 rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe,511 &dev->descriptors);512 if (rc != EOK) {513 *errstr_ptr = "descriptor retrieval";514 return rc;515 }516 517 /* Create alternate interfaces. */518 rc = usb_alternate_interfaces_create(dev->descriptors.configuration,519 dev->descriptors.configuration_size, dev->interface_no,520 &dev->alternate_interfaces);521 if (rc != EOK) {522 /* We will try to silently ignore this. */523 dev->alternate_interfaces = NULL;524 }525 526 rc = initialize_other_pipes(endpoints, dev, 0);527 if (rc != EOK) {528 *errstr_ptr = "pipes initialization";529 return rc;530 }531 532 *errstr_ptr = NULL;533 *dev_ptr = dev;534 535 return EOK;536 }537 538 643 /** 539 644 * @} -
uspace/lib/usb/src/request.c
rc7bdfa7 r1cbb4b7 871 871 } 872 872 873 /** Clear halt bit of an endpoint pipe (after pipe stall).874 *875 * @param pipe Control pipe.876 * @param ep_index Endpoint index (in native endianness).877 * @return Error code.878 */879 int usb_request_clear_endpoint_halt(usb_pipe_t *pipe, uint16_t ep_index)880 {881 return usb_request_clear_feature(pipe,882 USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT,883 uint16_host2usb(USB_FEATURE_SELECTOR_ENDPOINT_HALT),884 uint16_host2usb(ep_index));885 }886 887 873 /** 888 874 * @}
Note:
See TracChangeset
for help on using the changeset viewer.