Changes in / [9c3bba0:899f1a9] in mainline
- Location:
- uspace
- Files:
-
- 2 added
- 3 deleted
- 42 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/usbinfo/dev.c
r9c3bba0 r899f1a9 34 34 * Representation of queried device. 35 35 */ 36 #include <usb/dev/pipes.h> 36 #include <usb/dev.h> 37 #include <usb/hc.h> 37 38 #include <errno.h> 38 39 #include <str_error.h> … … 52 53 bool transfer_started = false; 53 54 54 rc = usb_device_connection_initialize(&dev->wire, hc_handle, dev_addr); 55 usb_hc_connection_initialize(&dev->hc_conn, hc_handle); 56 57 rc = usb_device_connection_initialize( 58 &dev->wire, &dev->hc_conn, dev_addr); 55 59 if (rc != EOK) { 56 60 fprintf(stderr, -
uspace/app/usbinfo/info.c
r9c3bba0 r899f1a9 287 287 void dump_strings(usbinfo_device_t *dev) 288 288 { 289 /* Find used indexes. Devices with more than 64 strings are very rare.*/ 290 uint64_t str_mask = 0; 291 find_string_indexes_callback((uint8_t *)&dev->device_descriptor, 0, 292 &str_mask); 293 usb_dp_walk_simple(dev->full_configuration_descriptor, 294 dev->full_configuration_descriptor_size, 295 usb_dp_standard_descriptor_nesting, 296 find_string_indexes_callback, 297 &str_mask); 298 299 if (str_mask == 0) { 300 printf("Device does not support string descriptors.\n"); 301 return; 302 } 303 289 304 /* Get supported languages. */ 290 305 l18_win_locales_t *langs; … … 305 320 } 306 321 printf(".\n"); 307 308 /* Find used indexes. Device with more than 64 strings are very rare.309 */310 uint64_t str_mask = 0;311 find_string_indexes_callback((uint8_t *)&dev->device_descriptor, 0,312 &str_mask);313 usb_dp_walk_simple(dev->full_configuration_descriptor,314 dev->full_configuration_descriptor_size,315 usb_dp_standard_descriptor_nesting,316 find_string_indexes_callback,317 &str_mask);318 322 319 323 /* Get all strings and dump them. */ -
uspace/app/usbinfo/usbinfo.h
r9c3bba0 r899f1a9 44 44 45 45 typedef struct { 46 usb_hc_connection_t hc_conn; 47 usb_device_connection_t wire; 46 48 usb_pipe_t ctrl_pipe; 47 usb_device_connection_t wire;48 49 usb_standard_device_descriptor_t device_descriptor; 49 50 uint8_t *full_configuration_descriptor; -
uspace/drv/bus/usb/ohci/hc.c
r9c3bba0 r899f1a9 137 137 return ret; 138 138 } 139 usb_device_manager_bind_address(&instance->generic.dev_manager,140 instance->rh.address, hub_fun->handle);141 139 142 140 #define CHECK_RET_UNREG_RETURN(ret, message...) \ … … 150 148 return ret; \ 151 149 } else (void)0 150 152 151 ret = usb_endpoint_manager_add_ep( 153 152 &instance->generic.ep_manager, instance->rh.address, 0, … … 165 164 CHECK_RET_UNREG_RETURN(ret, 166 165 "Failed to bind root hub function: %s.\n", str_error(ret)); 166 167 ret = usb_device_manager_bind_address(&instance->generic.dev_manager, 168 instance->rh.address, hub_fun->handle); 169 if (ret != EOK) 170 usb_log_warning("Failed to bind root hub address: %s.\n", 171 str_error(ret)); 167 172 168 173 return EOK; -
uspace/drv/bus/usb/ohci/ohci.c
r9c3bba0 r899f1a9 140 140 int device_setup_ohci(ddf_dev_t *device) 141 141 { 142 assert(device); 143 144 ohci_t *instance = malloc(sizeof(ohci_t)); 142 if (device == NULL) 143 return EBADMEM; 144 145 ohci_t *instance = ddf_dev_data_alloc(device,sizeof(ohci_t)); 145 146 if (instance == NULL) { 146 147 usb_log_error("Failed to allocate OHCI driver.\n"); 147 148 return ENOMEM; 148 149 } 149 instance->rh_fun = NULL;150 instance->hc_fun = NULL;151 150 152 151 #define CHECK_RET_DEST_FREE_RETURN(ret, message...) \ 153 152 if (ret != EOK) { \ 154 153 if (instance->hc_fun) { \ 154 instance->hc_fun->driver_data = NULL; \ 155 155 ddf_fun_destroy(instance->hc_fun); \ 156 156 } \ 157 157 if (instance->rh_fun) { \ 158 instance->rh_fun->driver_data = NULL; \ 158 159 ddf_fun_destroy(instance->rh_fun); \ 159 160 } \ 160 free(instance); \161 161 usb_log_error(message); \ 162 162 return ret; \ … … 219 219 "Failed to init ohci_hcd: %s.\n", str_error(ret)); 220 220 221 device->driver_data = instance;222 223 221 #define CHECK_RET_FINI_RETURN(ret, message...) \ 224 222 if (ret != EOK) { \ -
uspace/drv/bus/usb/ohci/ohci_batch.c
r9c3bba0 r899f1a9 34 34 #include <errno.h> 35 35 #include <str_error.h> 36 #include <macros.h> 36 37 37 38 #include <usb/usb.h> … … 53 54 return; 54 55 if (ohci_batch->tds) { 56 const ohci_endpoint_t *ohci_ep = 57 ohci_endpoint_get(ohci_batch->usb_batch->ep); 58 assert(ohci_ep); 55 59 for (unsigned i = 0; i < ohci_batch->td_count; ++i) { 56 if ( i != ohci_batch->leave_td)60 if (ohci_batch->tds[i] != ohci_ep->td) 57 61 free32(ohci_batch->tds[i]); 58 62 } … … 64 68 } 65 69 /*----------------------------------------------------------------------------*/ 70 /** Finishes usb_transfer_batch and destroys the structure. 71 * 72 * @param[in] uhci_batch Instance to finish and destroy. 73 */ 66 74 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *ohci_batch) 67 75 { … … 69 77 assert(ohci_batch->usb_batch); 70 78 usb_transfer_batch_finish(ohci_batch->usb_batch, 71 ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size, 72 ohci_batch->usb_batch->buffer_size); 79 ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size); 73 80 ohci_transfer_batch_dispose(ohci_batch); 74 81 } 75 82 /*----------------------------------------------------------------------------*/ 83 /** Allocate memory and initialize internal data structure. 84 * 85 * @param[in] usb_batch Pointer to generic USB batch structure. 86 * @return Valid pointer if all structures were successfully created, 87 * NULL otherwise. 88 * 89 * Determines the number of needed transfer descriptors (TDs). 90 * Prepares a transport buffer (that is accessible by the hardware). 91 * Initializes parameters needed for the transfer and callback. 92 */ 76 93 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *usb_batch) 77 94 { … … 105 122 ohci_batch->ed = ohci_endpoint_get(usb_batch->ep)->ed; 106 123 ohci_batch->tds[0] = ohci_endpoint_get(usb_batch->ep)->td; 107 ohci_batch->leave_td = 0;108 124 109 125 for (unsigned i = 1; i <= ohci_batch->td_count; ++i) { … … 152 168 * completes with the last TD. 153 169 */ 154 bool ohci_transfer_batch_is_complete( ohci_transfer_batch_t *ohci_batch)170 bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *ohci_batch) 155 171 { 156 172 assert(ohci_batch); … … 174 190 175 191 /* Assume we will leave the last(unused) TD behind */ 176 ohci_batch->leave_td = ohci_batch->td_count;192 unsigned leave_td = ohci_batch->td_count; 177 193 178 194 /* Check all TDs */ … … 212 228 * It will be the one TD we leave behind. 213 229 */ 214 ohci_batch->leave_td = i + 1;230 leave_td = i + 1; 215 231 216 232 /* Check TD assumption */ 217 const uint32_t pa = addr_to_phys(218 ohci_batch->tds[ohci_batch->leave_td]);219 assert((ohci_batch->ed->td_head & ED_TD TAIL_PTR_MASK)233 const uint32_t pa = 234 addr_to_phys(ohci_batch->tds[leave_td]); 235 assert((ohci_batch->ed->td_head & ED_TDHEAD_PTR_MASK) 220 236 == pa); 221 237 222 238 ed_set_tail_td(ohci_batch->ed, 223 ohci_batch->tds[ ohci_batch->leave_td]);239 ohci_batch->tds[leave_td]); 224 240 225 241 /* Clear possible ED HALT */ … … 234 250 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->usb_batch->ep); 235 251 assert(ohci_ep); 236 ohci_ep->td = ohci_batch->tds[ ohci_batch->leave_td];252 ohci_ep->td = ohci_batch->tds[leave_td]; 237 253 238 254 /* Make sure that we are leaving the right TD behind */ … … 248 264 * @param[in] ohci_batch Batch structure to use 249 265 */ 250 void ohci_transfer_batch_commit( ohci_transfer_batch_t *ohci_batch)266 void ohci_transfer_batch_commit(const ohci_transfer_batch_t *ohci_batch) 251 267 { 252 268 assert(ohci_batch); … … 295 311 while (remain_size > 0) { 296 312 const size_t transfer_size = 297 remain_size > OHCI_TD_MAX_TRANSFER ? 298 OHCI_TD_MAX_TRANSFER : remain_size; 313 min(remain_size, OHCI_TD_MAX_TRANSFER); 299 314 toggle = 1 - toggle; 300 315 … … 378 393 } 379 394 /*----------------------------------------------------------------------------*/ 395 /** Transfer setup table. */ 380 396 static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t) = 381 397 { -
uspace/drv/bus/usb/ohci/ohci_batch.h
r9c3bba0 r899f1a9 53 53 /** Number of TDs used by the transfer */ 54 54 size_t td_count; 55 /** Dummy TD to be left at the ED and used by the next transfer */56 size_t leave_td;57 55 /** Data buffer, must be accessible by the OHCI hw. */ 58 56 char *device_buffer; … … 62 60 63 61 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *batch); 64 bool ohci_transfer_batch_is_complete( ohci_transfer_batch_t *batch);65 void ohci_transfer_batch_commit( ohci_transfer_batch_t *batch);62 bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *batch); 63 void ohci_transfer_batch_commit(const ohci_transfer_batch_t *batch); 66 64 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *batch); 67 65 /*----------------------------------------------------------------------------*/ -
uspace/drv/bus/usb/ohci/pci.c
r9c3bba0 r899f1a9 42 42 #include <ddi.h> 43 43 #include <libarch/ddi.h> 44 #include <device/hw_res .h>44 #include <device/hw_res_parsed.h> 45 45 46 46 #include <usb/debug.h> … … 61 61 { 62 62 assert(dev); 63 assert(mem_reg_address);64 assert(mem_reg_size);65 assert(irq_no);66 63 67 64 async_sess_t *parent_sess = … … 71 68 return ENOMEM; 72 69 73 hw_resource_list_t hw_resources; 74 int rc = hw_res_get_resource_list(parent_sess, &hw_resources); 70 hw_res_list_parsed_t hw_res; 71 hw_res_list_parsed_init(&hw_res); 72 const int ret = hw_res_get_list_parsed(parent_sess, &hw_res, 0); 75 73 async_hangup(parent_sess); 76 if (r c!= EOK) {77 return r c;74 if (ret != EOK) { 75 return ret; 78 76 } 79 77 80 uintptr_t mem_address = 0; 81 size_t mem_size = 0; 82 bool mem_found = false; 78 /* We want one irq and one mem range. */ 79 if (hw_res.irqs.count != 1 || hw_res.mem_ranges.count != 1) { 80 hw_res_list_parsed_clean(&hw_res); 81 return EINVAL; 82 } 83 83 84 int irq = 0; 85 bool irq_found = false; 84 if (mem_reg_address) 85 *mem_reg_address = hw_res.mem_ranges.ranges[0].address; 86 if (mem_reg_size) 87 *mem_reg_size = hw_res.mem_ranges.ranges[0].size; 88 if (irq_no) 89 *irq_no = hw_res.irqs.irqs[0]; 86 90 87 for (size_t i = 0; i < hw_resources.count; i++) { 88 hw_resource_t *res = &hw_resources.resources[i]; 89 switch (res->type) { 90 case INTERRUPT: 91 irq = res->res.interrupt.irq; 92 irq_found = true; 93 usb_log_debug2("Found interrupt: %d.\n", irq); 94 break; 95 case MEM_RANGE: 96 if (res->res.mem_range.address != 0 97 && res->res.mem_range.size != 0 ) { 98 mem_address = res->res.mem_range.address; 99 mem_size = res->res.mem_range.size; 100 usb_log_debug2("Found mem: %p %zu.\n", 101 (void *) mem_address, mem_size); 102 mem_found = true; 103 } 104 default: 105 break; 106 } 107 } 108 free(hw_resources.resources); 109 110 if (mem_found && irq_found) { 111 *mem_reg_address = mem_address; 112 *mem_reg_size = mem_size; 113 *irq_no = irq; 114 return EOK; 115 } 116 return ENOENT; 91 hw_res_list_parsed_clean(&hw_res); 92 return EOK; 117 93 } 118 94 -
uspace/drv/bus/usb/ohci/root_hub.c
r9c3bba0 r899f1a9 100 100 .attributes = USB_TRANSFER_INTERRUPT, 101 101 .descriptor_type = USB_DESCTYPE_ENDPOINT, 102 .endpoint_address = 1 +(1 << 7),102 .endpoint_address = 1 | (1 << 7), 103 103 .length = sizeof(usb_standard_endpoint_descriptor_t), 104 104 .max_packet_size = 2, … … 109 109 static void rh_init_descriptors(rh_t *instance); 110 110 static uint16_t create_interrupt_mask(const rh_t *instance); 111 static intget_status(const rh_t *instance, usb_transfer_batch_t *request);112 static intget_descriptor(const rh_t *instance, usb_transfer_batch_t *request);113 static intset_feature(const rh_t *instance, usb_transfer_batch_t *request);114 static intclear_feature(const rh_t *instance, usb_transfer_batch_t *request);111 static void get_status(const rh_t *instance, usb_transfer_batch_t *request); 112 static void get_descriptor(const rh_t *instance, usb_transfer_batch_t *request); 113 static void set_feature(const rh_t *instance, usb_transfer_batch_t *request); 114 static void clear_feature(const rh_t *instance, usb_transfer_batch_t *request); 115 115 static int set_feature_port( 116 116 const rh_t *instance, uint16_t feature, uint16_t port); 117 117 static int clear_feature_port( 118 118 const rh_t *instance, uint16_t feature, uint16_t port); 119 static intcontrol_request(rh_t *instance, usb_transfer_batch_t *request);119 static void control_request(rh_t *instance, usb_transfer_batch_t *request); 120 120 static inline void interrupt_request( 121 121 usb_transfer_batch_t *request, uint16_t mask, size_t size) 122 122 { 123 123 assert(request); 124 125 request->transfered_size = size;126 124 usb_transfer_batch_finish_error(request, &mask, size, EOK); 127 } 128 129 #define TRANSFER_OK(bytes) \ 125 usb_transfer_batch_destroy(request); 126 } 127 128 #define TRANSFER_END_DATA(request, data, bytes) \ 130 129 do { \ 131 request->transfered_size = bytes; \ 132 return EOK; \ 130 usb_transfer_batch_finish_error(request, data, bytes, EOK); \ 131 usb_transfer_batch_destroy(request); \ 132 return; \ 133 } while (0) 134 135 #define TRANSFER_END(request, error) \ 136 do { \ 137 usb_transfer_batch_finish_error(request, NULL, 0, error); \ 138 usb_transfer_batch_destroy(request); \ 139 return; \ 133 140 } while (0) 134 141 … … 212 219 case USB_TRANSFER_CONTROL: 213 220 usb_log_debug("Root hub got CONTROL packet\n"); 214 const int ret = control_request(instance, request); 215 usb_transfer_batch_finish_error(request, NULL, 0, ret); 221 control_request(instance, request); 216 222 break; 223 217 224 case USB_TRANSFER_INTERRUPT: 218 225 usb_log_debug("Root hub got INTERRUPT packet\n"); … … 221 228 const uint16_t mask = create_interrupt_mask(instance); 222 229 if (mask == 0) { 223 usb_log_debug("No changes.. \n");230 usb_log_debug("No changes...\n"); 224 231 instance->unfinished_interrupt_transfer = request; 225 fibril_mutex_unlock(&instance->guard); 226 return; 232 } else { 233 usb_log_debug("Processing changes...\n"); 234 interrupt_request( 235 request, mask, instance->interrupt_mask_size); 227 236 } 228 usb_log_debug("Processing changes...\n");229 interrupt_request(request, mask, instance->interrupt_mask_size);230 237 fibril_mutex_unlock(&instance->guard); 231 238 break; … … 233 240 default: 234 241 usb_log_error("Root hub got unsupported request.\n"); 235 usb_transfer_batch_finish_error(request, NULL, 0, EINVAL); 236 } 237 usb_transfer_batch_destroy(request); 242 TRANSFER_END(request, ENOTSUP); 243 } 238 244 } 239 245 /*----------------------------------------------------------------------------*/ … … 254 260 interrupt_request(instance->unfinished_interrupt_transfer, 255 261 mask, instance->interrupt_mask_size); 256 usb_transfer_batch_destroy(257 instance->unfinished_interrupt_transfer);258 262 instance->unfinished_interrupt_transfer = NULL; 259 263 } … … 384 388 * @return error code 385 389 */ 386 intget_status(const rh_t *instance, usb_transfer_batch_t *request)390 void get_status(const rh_t *instance, usb_transfer_batch_t *request) 387 391 { 388 392 assert(instance); 389 393 assert(request); 394 390 395 391 396 const usb_device_request_setup_packet_t *request_packet = 392 397 (usb_device_request_setup_packet_t*)request->setup_buffer; 393 398 394 if (request->buffer_size < 4) { 395 usb_log_error("Buffer too small for get status request.\n"); 396 return EOVERFLOW; 397 } 398 399 switch (request_packet->request_type) 400 { 401 case USB_HUB_REQ_TYPE_GET_HUB_STATUS: 399 402 /* Hub status: just filter relevant info from rh_status reg */ 400 if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) { 401 const uint32_t data = instance->registers->rh_status & 402 (RHS_LPS_FLAG | RHS_LPSC_FLAG | RHS_OCI_FLAG | RHS_OCIC_FLAG); 403 memcpy(request->buffer, &data, sizeof(data)); 404 TRANSFER_OK(sizeof(data)); 405 } 403 if (request->buffer_size < 4) { 404 usb_log_error("Buffer(%zu) too small for hub get " 405 "status request.\n", request->buffer_size); 406 TRANSFER_END(request, EOVERFLOW); 407 } else { 408 const uint32_t data = instance->registers->rh_status & 409 (RHS_LPS_FLAG | RHS_LPSC_FLAG 410 | RHS_OCI_FLAG | RHS_OCIC_FLAG); 411 TRANSFER_END_DATA(request, &data, sizeof(data)); 412 } 406 413 407 414 /* Copy appropriate rh_port_status register, OHCI designers were 408 415 * kind enough to make those bit values match USB specification */ 409 if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) { 410 const unsigned port = request_packet->index; 411 if (port < 1 || port > instance->port_count) 412 return EINVAL; 413 414 const uint32_t data = 415 instance->registers->rh_port_status[port - 1]; 416 memcpy(request->buffer, &data, sizeof(data)); 417 TRANSFER_OK(sizeof(data)); 418 } 419 420 return ENOTSUP; 416 case USB_HUB_REQ_TYPE_GET_PORT_STATUS: 417 if (request->buffer_size < 4) { 418 usb_log_error("Buffer(%zu) too small for hub get " 419 "status request.\n", request->buffer_size); 420 TRANSFER_END(request, EOVERFLOW); 421 } else { 422 const unsigned port = request_packet->index; 423 if (port < 1 || port > instance->port_count) 424 TRANSFER_END(request, EINVAL); 425 426 const uint32_t data = 427 instance->registers->rh_port_status[port - 1]; 428 TRANSFER_END_DATA(request, &data, sizeof(data)); 429 } 430 case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE): 431 if (request->buffer_size < 2) { 432 usb_log_error("Buffer(%zu) too small for hub generic " 433 "get status request.\n", request->buffer_size); 434 TRANSFER_END(request, EOVERFLOW); 435 } else { 436 static const uint16_t data = 437 uint16_host2usb(USB_DEVICE_STATUS_SELF_POWERED); 438 TRANSFER_END_DATA(request, &data, sizeof(data)); 439 } 440 441 case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE): 442 /* Hubs are allowed to have only one interface */ 443 if (request_packet->index != 0) 444 TRANSFER_END(request, EINVAL); 445 /* Fall through, as the answer will be the same: 0x0000 */ 446 case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT): 447 /* Endpoint 0 (default control) and 1 (interrupt) */ 448 if (request_packet->index >= 2) 449 TRANSFER_END(request, EINVAL); 450 451 if (request->buffer_size < 2) { 452 usb_log_error("Buffer(%zu) too small for hub generic " 453 "get status request.\n", request->buffer_size); 454 TRANSFER_END(request, EOVERFLOW); 455 } else { 456 /* Endpoints are OK. (We don't halt) */ 457 static const uint16_t data = 0; 458 TRANSFER_END_DATA(request, &data, sizeof(data)); 459 } 460 461 default: 462 usb_log_error("Unsupported GET_STATUS request.\n"); 463 TRANSFER_END(request, ENOTSUP); 464 } 465 421 466 } 422 467 /*----------------------------------------------------------------------------*/ … … 430 475 * @return Error code 431 476 */ 432 intget_descriptor(const rh_t *instance, usb_transfer_batch_t *request)477 void get_descriptor(const rh_t *instance, usb_transfer_batch_t *request) 433 478 { 434 479 assert(instance); … … 437 482 const usb_device_request_setup_packet_t *setup_request = 438 483 (usb_device_request_setup_packet_t *) request->setup_buffer; 439 size_t size;440 const void *descriptor = NULL;441 484 const uint16_t setup_request_value = setup_request->value_high; 442 //(setup_request->value_low << 8);443 485 switch (setup_request_value) 444 486 { 445 487 case USB_DESCTYPE_HUB: 446 488 usb_log_debug2("USB_DESCTYPE_HUB\n"); 447 /* Hub descriptor was generated locally */448 descriptor = instance->descriptors.hub;449 size = instance->hub_descriptor_size;450 break;489 /* Hub descriptor was generated locally. 490 * Class specific request. */ 491 TRANSFER_END_DATA(request, instance->descriptors.hub, 492 instance->hub_descriptor_size); 451 493 452 494 case USB_DESCTYPE_DEVICE: 453 495 usb_log_debug2("USB_DESCTYPE_DEVICE\n"); 454 /* Device descriptor is shared (No one should ask for it)*/ 455 descriptor = &ohci_rh_device_descriptor; 456 size = sizeof(ohci_rh_device_descriptor); 457 break; 496 /* Device descriptor is shared 497 * (No one should ask for it, as the device is already setup) 498 * Standard USB device request. */ 499 TRANSFER_END_DATA(request, &ohci_rh_device_descriptor, 500 sizeof(ohci_rh_device_descriptor)); 458 501 459 502 case USB_DESCTYPE_CONFIGURATION: 460 503 usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n"); 461 504 /* Start with configuration and add others depending on 462 * request size */ 463 descriptor = &instance->descriptors; 464 size = instance->descriptors.configuration.total_length; 465 break; 505 * request size. Standard USB request. */ 506 TRANSFER_END_DATA(request, &instance->descriptors, 507 instance->descriptors.configuration.total_length); 466 508 467 509 case USB_DESCTYPE_INTERFACE: 468 510 usb_log_debug2("USB_DESCTYPE_INTERFACE\n"); 469 511 /* Use local interface descriptor. There is one and it 470 * might be modified */471 descriptor = &instance->descriptors.interface;472 size = sizeof(instance->descriptors.interface);473 break;512 * might be modified. Hub driver should not ask or this 513 * descriptor as it is not part of standard requests set. */ 514 TRANSFER_END_DATA(request, &instance->descriptors.interface, 515 sizeof(instance->descriptors.interface)); 474 516 475 517 case USB_DESCTYPE_ENDPOINT: 476 518 /* Use local endpoint descriptor. There is one 477 * it might have max_packet_size field modified*/ 519 * it might have max_packet_size field modified. Hub driver 520 * should not ask for this descriptor as it is not part 521 * of standard requests set. */ 478 522 usb_log_debug2("USB_DESCTYPE_ENDPOINT\n"); 479 descriptor = &instance->descriptors.endpoint; 480 size = sizeof(instance->descriptors.endpoint); 481 break; 523 TRANSFER_END_DATA(request, &instance->descriptors.endpoint, 524 sizeof(instance->descriptors.endpoint)); 482 525 483 526 default: … … 489 532 setup_request_value, setup_request->index, 490 533 setup_request->length); 491 return EINVAL; 492 } 493 if (request->buffer_size < size) { 494 size = request->buffer_size; 495 } 496 497 memcpy(request->buffer, descriptor, size); 498 TRANSFER_OK(size); 534 TRANSFER_END(request, EINVAL); 535 } 536 537 TRANSFER_END(request, ENOTSUP); 499 538 } 500 539 /*----------------------------------------------------------------------------*/ … … 604 643 * @return error code 605 644 */ 606 intset_feature(const rh_t *instance, usb_transfer_batch_t *request)645 void set_feature(const rh_t *instance, usb_transfer_batch_t *request) 607 646 { 608 647 assert(instance); … … 615 654 case USB_HUB_REQ_TYPE_SET_PORT_FEATURE: 616 655 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 617 returnset_feature_port(instance,656 const int ret = set_feature_port(instance, 618 657 setup_request->value, setup_request->index); 658 TRANSFER_END(request, ret); 619 659 620 660 case USB_HUB_REQ_TYPE_SET_HUB_FEATURE: … … 623 663 * features. It makes no sense to SET either. */ 624 664 usb_log_error("Invalid HUB set feature request.\n"); 625 return ENOTSUP; 665 TRANSFER_END(request, ENOTSUP); 666 //TODO: Consider standard USB requests: REMOTE WAKEUP, ENDPOINT STALL 626 667 default: 627 668 usb_log_error("Invalid set feature request type: %d\n", 628 669 setup_request->request_type); 629 return EINVAL;670 TRANSFER_END(request, ENOTSUP); 630 671 } 631 672 } … … 640 681 * @return error code 641 682 */ 642 intclear_feature(const rh_t *instance, usb_transfer_batch_t *request)683 void clear_feature(const rh_t *instance, usb_transfer_batch_t *request) 643 684 { 644 685 assert(instance); … … 647 688 const usb_device_request_setup_packet_t *setup_request = 648 689 (usb_device_request_setup_packet_t *) request->setup_buffer; 649 650 request->transfered_size = 0;651 690 652 691 switch (setup_request->request_type) … … 654 693 case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE: 655 694 usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n"); 656 returnclear_feature_port(instance,695 const int ret = clear_feature_port(instance, 657 696 setup_request->value, setup_request->index); 697 TRANSFER_END(request, ret); 658 698 659 699 case USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE: … … 668 708 if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) { 669 709 instance->registers->rh_status = RHS_OCIC_FLAG; 670 TRANSFER_ OK(0);710 TRANSFER_END(request, EOK); 671 711 } 712 //TODO: Consider standard USB requests: REMOTE WAKEUP, ENDPOINT STALL 672 713 default: 673 714 usb_log_error("Invalid clear feature request type: %d\n", 674 715 setup_request->request_type); 675 return EINVAL;716 TRANSFER_END(request, ENOTSUP); 676 717 } 677 718 } … … 695 736 * @return error code 696 737 */ 697 intcontrol_request(rh_t *instance, usb_transfer_batch_t *request)738 void control_request(rh_t *instance, usb_transfer_batch_t *request) 698 739 { 699 740 assert(instance); … … 702 743 if (!request->setup_buffer) { 703 744 usb_log_error("Root hub received empty transaction!"); 704 return EINVAL;745 TRANSFER_END(request, EBADMEM); 705 746 } 706 747 707 748 if (sizeof(usb_device_request_setup_packet_t) > request->setup_size) { 708 749 usb_log_error("Setup packet too small\n"); 709 return EOVERFLOW;750 TRANSFER_END(request, EOVERFLOW); 710 751 } 711 752 … … 718 759 case USB_DEVREQ_GET_STATUS: 719 760 usb_log_debug("USB_DEVREQ_GET_STATUS\n"); 720 return get_status(instance, request); 761 get_status(instance, request); 762 break; 721 763 722 764 case USB_DEVREQ_GET_DESCRIPTOR: 723 765 usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n"); 724 return get_descriptor(instance, request); 766 get_descriptor(instance, request); 767 break; 725 768 726 769 case USB_DEVREQ_GET_CONFIGURATION: 727 770 usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n"); 728 if (request->buffer_size != 1)729 return EINVAL;730 request->buffer[0]= 1;731 TRANSFER_ OK(1);771 if (request->buffer_size == 0) 772 TRANSFER_END(request, EOVERFLOW); 773 static const uint8_t config = 1; 774 TRANSFER_END_DATA(request, &config, sizeof(config)); 732 775 733 776 case USB_DEVREQ_CLEAR_FEATURE: 734 usb_log_debug2(" Processing request without "735 "additional data\n");736 return clear_feature(instance, request);777 usb_log_debug2("USB_DEVREQ_CLEAR_FEATURE\n"); 778 clear_feature(instance, request); 779 break; 737 780 738 781 case USB_DEVREQ_SET_FEATURE: 739 usb_log_debug2(" Processing request without "740 "additional data\n");741 return set_feature(instance, request);782 usb_log_debug2("USB_DEVREQ_SET_FEATURE\n"); 783 set_feature(instance, request); 784 break; 742 785 743 786 case USB_DEVREQ_SET_ADDRESS: 744 usb_log_debug("USB_DEVREQ_SET_ADDRESS\n"); 787 usb_log_debug("USB_DEVREQ_SET_ADDRESS: %u\n", 788 setup_request->value); 789 if (uint16_usb2host(setup_request->value) > 127) 790 TRANSFER_END(request, EINVAL); 791 745 792 instance->address = setup_request->value; 746 TRANSFER_ OK(0);793 TRANSFER_END(request, EOK); 747 794 748 795 case USB_DEVREQ_SET_CONFIGURATION: 749 usb_log_debug("USB_DEVREQ_SET_CONFIGURATION\n"); 750 /* We don't need to do anything */ 751 TRANSFER_OK(0); 752 753 case USB_DEVREQ_SET_DESCRIPTOR: /* Not supported by OHCI RH */ 796 usb_log_debug("USB_DEVREQ_SET_CONFIGURATION: %u\n", 797 setup_request->value); 798 /* We have only one configuration, it's number is 1 */ 799 if (uint16_usb2host(setup_request->value) != 1) 800 TRANSFER_END(request, EINVAL); 801 TRANSFER_END(request, EOK); 802 803 /* Both class specific and std is optional for hubs */ 804 case USB_DEVREQ_SET_DESCRIPTOR: 805 /* Hubs have only one interface GET/SET is not supported */ 806 case USB_DEVREQ_GET_INTERFACE: 807 case USB_DEVREQ_SET_INTERFACE: 754 808 default: 809 /* Hub class GET_STATE(2) falls in here too. */ 755 810 usb_log_error("Received unsupported request: %d.\n", 756 811 setup_request->request); 757 return ENOTSUP; 758 } 759 } 760 812 TRANSFER_END(request, ENOTSUP); 813 } 814 } 761 815 /** 762 816 * @} -
uspace/drv/bus/usb/uhci/hc.c
r9c3bba0 r899f1a9 130 130 uhci_transfer_batch_t *batch = 131 131 uhci_transfer_batch_from_link(item); 132 uhci_transfer_batch_ call_dispose(batch);132 uhci_transfer_batch_finish_dispose(batch); 133 133 } 134 134 } -
uspace/drv/bus/usb/uhci/pci.c
r9c3bba0 r899f1a9 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 28 /** 30 29 * @addtogroup drvusbuhcihc … … 39 38 #include <assert.h> 40 39 #include <devman.h> 41 #include <device/hw_res .h>40 #include <device/hw_res_parsed.h> 42 41 43 42 #include <usb/debug.h> … … 68 67 return ENOMEM; 69 68 70 hw_resource_list_t hw_resources; 71 const int rc = hw_res_get_resource_list(parent_sess, &hw_resources); 69 hw_res_list_parsed_t hw_res; 70 hw_res_list_parsed_init(&hw_res); 71 const int ret = hw_res_get_list_parsed(parent_sess, &hw_res, 0); 72 72 async_hangup(parent_sess); 73 if (r c!= EOK) {74 return r c;73 if (ret != EOK) { 74 return ret; 75 75 } 76 76 77 uintptr_t io_address = 0; 78 size_t io_size = 0; 79 bool io_found = false; 77 /* We want one irq and one io range. */ 78 if (hw_res.irqs.count != 1 || hw_res.io_ranges.count != 1) { 79 hw_res_list_parsed_clean(&hw_res); 80 return EINVAL; 81 } 80 82 81 int irq = 0; 82 bool irq_found = false; 83 if (io_reg_address) 84 *io_reg_address = hw_res.io_ranges.ranges[0].address; 85 if (io_reg_size) 86 *io_reg_size = hw_res.io_ranges.ranges[0].size; 87 if (irq_no) 88 *irq_no = hw_res.irqs.irqs[0]; 83 89 84 for (size_t i = 0; i < hw_resources.count; i++) { 85 const hw_resource_t *res = &hw_resources.resources[i]; 86 switch (res->type) { 87 case INTERRUPT: 88 irq = res->res.interrupt.irq; 89 irq_found = true; 90 usb_log_debug2("Found interrupt: %d.\n", irq); 91 break; 92 case IO_RANGE: 93 io_address = res->res.io_range.address; 94 io_size = res->res.io_range.size; 95 usb_log_debug2("Found io: %" PRIx64" %zu.\n", 96 res->res.io_range.address, res->res.io_range.size); 97 io_found = true; 98 break; 99 default: 100 break; 101 } 102 } 103 free(hw_resources.resources); 104 105 if (!io_found || !irq_found) 106 return ENOENT; 107 108 *io_reg_address = io_address; 109 *io_reg_size = io_size; 110 *irq_no = irq; 111 90 hw_res_list_parsed_clean(&hw_res); 112 91 return EOK; 113 92 } -
uspace/drv/bus/usb/uhci/transfer_list.c
r9c3bba0 r899f1a9 184 184 uhci_transfer_batch_from_link(current); 185 185 transfer_list_remove_batch(instance, batch); 186 batch->usb_batch->error = EINTR; 187 uhci_transfer_batch_call_dispose(batch); 186 uhci_transfer_batch_abort(batch); 188 187 } 189 188 fibril_mutex_unlock(&instance->guard); -
uspace/drv/bus/usb/uhci/uhci.c
r9c3bba0 r899f1a9 148 148 int device_setup_uhci(ddf_dev_t *device) 149 149 { 150 assert(device); 151 uhci_t *instance = malloc(sizeof(uhci_t)); 150 if (!device) 151 return EBADMEM; 152 153 uhci_t *instance = ddf_dev_data_alloc(device, sizeof(uhci_t)); 152 154 if (instance == NULL) { 153 155 usb_log_error("Failed to allocate OHCI driver.\n"); … … 158 160 if (ret != EOK) { \ 159 161 if (instance->hc_fun) \ 160 instance->hc_fun->ops = NULL; \161 162 instance->hc_fun->driver_data = NULL; \ 162 163 ddf_fun_destroy(instance->hc_fun); \ 163 164 if (instance->rh_fun) {\ 164 instance->rh_fun->ops = NULL; \165 165 instance->rh_fun->driver_data = NULL; \ 166 166 ddf_fun_destroy(instance->rh_fun); \ 167 167 } \ 168 device->driver_data = NULL; \169 168 usb_log_error(message); \ 170 169 return ret; \ … … 227 226 "Failed to init uhci_hcd: %s.\n", str_error(ret)); 228 227 229 device->driver_data = instance;230 231 228 #define CHECK_RET_FINI_RETURN(ret, message...) \ 232 229 if (ret != EOK) { \ -
uspace/drv/bus/usb/uhci/uhci_batch.c
r9c3bba0 r899f1a9 34 34 #include <errno.h> 35 35 #include <str_error.h> 36 #include <macros.h> 36 37 37 38 #include <usb/usb.h> … … 45 46 #define DEFAULT_ERROR_COUNT 3 46 47 48 /** Safely destructs uhci_transfer_batch_t structure. 49 * 50 * @param[in] uhci_batch Instance to destroy. 51 */ 47 52 static void uhci_transfer_batch_dispose(uhci_transfer_batch_t *uhci_batch) 48 53 { … … 54 59 } 55 60 /*----------------------------------------------------------------------------*/ 56 /** Safely destructs uhci_transfer_batch_t structure57 * 58 * @param[in] uhci_batch Instance to destroy.59 */ 60 void uhci_transfer_batch_ call_dispose(uhci_transfer_batch_t *uhci_batch)61 /** Finishes usb_transfer_batch and destroys the structure. 62 * 63 * @param[in] uhci_batch Instance to finish and destroy. 64 */ 65 void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch) 61 66 { 62 67 assert(uhci_batch); 63 68 assert(uhci_batch->usb_batch); 64 69 usb_transfer_batch_finish(uhci_batch->usb_batch, 65 uhci_transfer_batch_data_buffer(uhci_batch), 66 uhci_batch->usb_batch->buffer_size); 70 uhci_transfer_batch_data_buffer(uhci_batch)); 67 71 uhci_transfer_batch_dispose(uhci_batch); 68 72 } 69 73 /*----------------------------------------------------------------------------*/ 74 /** Transfer batch setup table. */ 70 75 static void (*const batch_setup[])(uhci_transfer_batch_t*, usb_direction_t); 71 76 /*----------------------------------------------------------------------------*/ 72 77 /** Allocate memory and initialize internal data structure. 73 78 * 74 * @param[in] fun DDF function to pass to callback. 75 * @param[in] ep Communication target 76 * @param[in] buffer Data source/destination. 77 * @param[in] buffer_size Size of the buffer. 78 * @param[in] setup_buffer Setup data source (if not NULL) 79 * @param[in] setup_size Size of setup_buffer (should be always 8) 80 * @param[in] func_in function to call on inbound transfer completion 81 * @param[in] func_out function to call on outbound transfer completion 82 * @param[in] arg additional parameter to func_in or func_out 79 * @param[in] usb_batch Pointer to generic USB batch structure. 83 80 * @return Valid pointer if all structures were successfully created, 84 81 * NULL otherwise. … … 156 153 * is reached. 157 154 */ 158 bool uhci_transfer_batch_is_complete( uhci_transfer_batch_t *uhci_batch)155 bool uhci_transfer_batch_is_complete(const uhci_transfer_batch_t *uhci_batch) 159 156 { 160 157 assert(uhci_batch); … … 200 197 } 201 198 /*----------------------------------------------------------------------------*/ 199 /** Direction to pid conversion table */ 202 200 static const usb_packet_id direction_pids[] = { 203 201 [USB_DIRECTION_IN] = USB_PID_IN, … … 237 235 238 236 while (remain_size > 0) { 239 const size_t packet_size = 240 (remain_size < mps) ? remain_size : mps; 237 const size_t packet_size = min(remain_size, mps); 241 238 242 239 const td_t *next_td = (td + 1 < uhci_batch->td_count) … … 309 306 310 307 while (remain_size > 0) { 311 const size_t packet_size = 312 (remain_size < mps) ? remain_size : mps; 308 const size_t packet_size = min(remain_size, mps); 313 309 314 310 td_init( -
uspace/drv/bus/usb/uhci/uhci_batch.h
r9c3bba0 r899f1a9 61 61 62 62 uhci_transfer_batch_t * uhci_transfer_batch_get(usb_transfer_batch_t *batch); 63 void uhci_transfer_batch_ call_dispose(uhci_transfer_batch_t *uhci_batch);64 bool uhci_transfer_batch_is_complete( uhci_transfer_batch_t *uhci_batch);63 void uhci_transfer_batch_finish_dispose(uhci_transfer_batch_t *uhci_batch); 64 bool uhci_transfer_batch_is_complete(const uhci_transfer_batch_t *uhci_batch); 65 65 66 /** Get offset to setup buffer accessible to the HC hw. 67 * @param uhci_batch UHCI batch structure. 68 * @return Pointer to the setup buffer. 69 */ 66 70 static inline void * uhci_transfer_batch_setup_buffer( 67 71 const uhci_transfer_batch_t *uhci_batch) … … 73 77 } 74 78 /*----------------------------------------------------------------------------*/ 79 /** Get offset to data buffer accessible to the HC hw. 80 * @param uhci_batch UHCI batch structure. 81 * @return Pointer to the data buffer. 82 */ 75 83 static inline void * uhci_transfer_batch_data_buffer( 76 84 const uhci_transfer_batch_t *uhci_batch) … … 82 90 } 83 91 /*----------------------------------------------------------------------------*/ 92 /** Aborts the batch. 93 * Sets error to EINTR and size off transferd data to 0, before finishing the 94 * batch. 95 * @param uhci_batch Batch to abort. 96 */ 97 static inline void uhci_transfer_batch_abort(uhci_transfer_batch_t *uhci_batch) 98 { 99 assert(uhci_batch); 100 assert(uhci_batch->usb_batch); 101 uhci_batch->usb_batch->error = EINTR; 102 uhci_batch->usb_batch->transfered_size = 0; 103 uhci_transfer_batch_finish_dispose(uhci_batch); 104 } 105 /*----------------------------------------------------------------------------*/ 106 /** Linked list conversion wrapper. 107 * @param l Linked list link. 108 * @return Pointer to the uhci batch structure. 109 */ 84 110 static inline uhci_transfer_batch_t *uhci_transfer_batch_from_link(link_t *l) 85 111 { -
uspace/drv/bus/usb/uhcirh/main.c
r9c3bba0 r899f1a9 36 36 #include <ddf/driver.h> 37 37 #include <devman.h> 38 #include <device/hw_res .h>38 #include <device/hw_res_parsed.h> 39 39 #include <errno.h> 40 40 #include <str_error.h> … … 136 136 { 137 137 assert(dev); 138 138 139 139 async_sess_t *parent_sess = 140 140 devman_parent_device_connect(EXCHANGE_SERIALIZE, dev->handle, … … 142 142 if (!parent_sess) 143 143 return ENOMEM; 144 145 hw_resource_list_t hw_resources; 146 const int ret = hw_res_get_resource_list(parent_sess, &hw_resources); 144 145 hw_res_list_parsed_t hw_res; 146 hw_res_list_parsed_init(&hw_res); 147 const int ret = hw_res_get_list_parsed(parent_sess, &hw_res, 0); 148 async_hangup(parent_sess); 147 149 if (ret != EOK) { 148 async_hangup(parent_sess);149 150 return ret; 150 151 } 151 152 uintptr_t io_address = 0; 153 size_t io_size = 0; 154 bool io_found = false; 155 156 size_t i = 0; 157 for (; i < hw_resources.count; i++) { 158 hw_resource_t *res = &hw_resources.resources[i]; 159 if (res->type == IO_RANGE) { 160 io_address = res->res.io_range.address; 161 io_size = res->res.io_range.size; 162 io_found = true; 163 } 164 152 153 if (hw_res.io_ranges.count != 1) { 154 hw_res_list_parsed_clean(&hw_res); 155 return EINVAL; 165 156 } 166 async_hangup(parent_sess); 167 168 if (!io_found) 169 return ENOENT; 170 157 171 158 if (io_reg_address != NULL) 172 *io_reg_address = io_address;173 159 *io_reg_address = hw_res.io_ranges.ranges[0].address; 160 174 161 if (io_reg_size != NULL) 175 *io_reg_size = io_size; 176 162 *io_reg_size = hw_res.io_ranges.ranges[0].size; 163 164 hw_res_list_parsed_clean(&hw_res); 177 165 return EOK; 178 166 } -
uspace/drv/bus/usb/uhcirh/port.c
r9c3bba0 r899f1a9 260 260 { 261 261 assert(port); 262 assert(usb_hc_connection_is_opened(&port->hc_connection));263 262 264 263 usb_log_debug("%s: Detected new device.\n", port->id_string); -
uspace/drv/bus/usb/usbhub/port.c
r9c3bba0 r899f1a9 288 288 port->attached_device.fun = NULL; 289 289 290 ret = usb_hc_connection_open(&hub->connection); 291 if (ret == EOK) { 292 ret = usb_hc_unregister_device(&hub->connection, 293 port->attached_device.address); 294 if (ret != EOK) { 295 usb_log_warning("Failed to unregister address of the " 296 "removed device: %s.\n", str_error(ret)); 297 } 298 ret = usb_hc_connection_close(&hub->connection); 299 if (ret != EOK) { 300 usb_log_warning("Failed to close hc connection %s.\n", 301 str_error(ret)); 302 } 303 304 } else { 305 usb_log_warning("Failed to open hc connection %s.\n", 306 str_error(ret)); 290 ret = usb_hc_unregister_device(&hub->usb_device->hc_conn, 291 port->attached_device.address); 292 if (ret != EOK) { 293 usb_log_warning("Failed to unregister address of the " 294 "removed device: %s.\n", str_error(ret)); 307 295 } 308 296 … … 438 426 439 427 const int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev, 440 &data->hub-> connection, data->speed, enable_port_callback,428 &data->hub->usb_device->hc_conn, data->speed, enable_port_callback, 441 429 data->port, &new_address, NULL, NULL, &child_fun); 442 430 -
uspace/drv/bus/usb/usbhub/usbhub.c
r9c3bba0 r899f1a9 99 99 fibril_condvar_initialize(&hub_dev->pending_ops_cv); 100 100 101 /* Create hc connection */ 102 usb_log_debug("Initializing USB wire abstraction.\n"); 103 int opResult = usb_hc_connection_initialize_from_device( 104 &hub_dev->connection, hub_dev->usb_device->ddf_dev); 105 if (opResult != EOK) { 106 usb_log_error("Could not initialize connection to device: %s\n", 101 102 int opResult = usb_pipe_start_long_transfer(&usb_dev->ctrl_pipe); 103 if (opResult != EOK) { 104 usb_log_error("Failed to start long ctrl pipe transfer: %s\n", 107 105 str_error(opResult)); 108 106 return opResult; … … 112 110 opResult = usb_set_first_configuration(usb_dev); 113 111 if (opResult != EOK) { 112 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe); 114 113 usb_log_error("Could not set hub configuration: %s\n", 115 114 str_error(opResult)); … … 120 119 opResult = usb_hub_process_hub_specific_info(hub_dev); 121 120 if (opResult != EOK) { 121 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe); 122 122 usb_log_error("Could process hub specific info, %s\n", 123 123 str_error(opResult)); … … 130 130 fun_exposed, HUB_FNC_NAME); 131 131 if (hub_dev->hub_fun == NULL) { 132 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe); 132 133 usb_log_error("Failed to create hub function.\n"); 133 134 return ENOMEM; … … 137 138 opResult = ddf_fun_bind(hub_dev->hub_fun); 138 139 if (opResult != EOK) { 140 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe); 139 141 usb_log_error("Failed to bind hub function: %s.\n", 140 142 str_error(opResult)); … … 148 150 usb_hub_polling_terminated_callback, hub_dev); 149 151 if (opResult != EOK) { 152 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe); 150 153 /* Function is already bound */ 151 154 ddf_fun_unbind(hub_dev->hub_fun); … … 159 162 hub_dev->usb_device->ddf_dev->name, hub_dev->port_count); 160 163 164 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe); 161 165 return EOK; 162 166 } -
uspace/drv/bus/usb/usbhub/usbhub.h
r9c3bba0 r899f1a9 57 57 /** Port structures, one for each port */ 58 58 usb_hub_port_t *ports; 59 /** Connection to hcd */60 usb_hc_connection_t connection;61 59 /** Generic usb device data*/ 62 60 usb_device_t *usb_device; -
uspace/drv/bus/usb/usbmid/main.c
r9c3bba0 r899f1a9 53 53 usb_log_info("Taking care of new MID `%s'.\n", dev->ddf_dev->name); 54 54 55 usb_pipe_start_long_transfer(&dev->ctrl_pipe); 56 57 bool accept = usbmid_explore_device(dev); 58 59 usb_pipe_end_long_transfer(&dev->ctrl_pipe); 55 const bool accept = usbmid_explore_device(dev); 60 56 61 57 if (!accept) { -
uspace/drv/bus/usb/vhc/hub.c
r9c3bba0 r899f1a9 107 107 108 108 usb_hc_connection_t hc_conn; 109 rc = usb_hc_connection_initialize(&hc_conn, hc_dev->handle); 110 assert(rc == EOK); 109 usb_hc_connection_initialize(&hc_conn, hc_dev->handle); 111 110 112 111 rc = usb_hc_connection_open(&hc_conn); -
uspace/lib/drv/include/usbhc_iface.h
r9c3bba0 r899f1a9 1 1 /* 2 2 * Copyright (c) 2010 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely 3 4 * All rights reserved. 4 5 * … … 26 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 */ 28 29 29 /** @addtogroup libdrv 30 30 * @addtogroup usb … … 46 46 int usbhc_get_handle(async_exch_t *, usb_address_t, devman_handle_t *); 47 47 int usbhc_release_address(async_exch_t *, usb_address_t); 48 int usbhc_register_endpoint(async_exch_t *, usb_address_t, 48 int usbhc_register_endpoint(async_exch_t *, usb_address_t, usb_endpoint_t, 49 49 usb_transfer_type_t, usb_direction_t, size_t, unsigned int); 50 50 int usbhc_unregister_endpoint(async_exch_t *, usb_address_t, usb_endpoint_t, -
uspace/lib/usb/Makefile
r9c3bba0 r899f1a9 37 37 src/class.c \ 38 38 src/ddfiface.c \ 39 src/dev.c \ 39 40 src/debug.c \ 40 41 src/dump.c \ -
uspace/lib/usb/include/usb/classes/hub.h
r9c3bba0 r899f1a9 84 84 85 85 /** 86 * @brief usb hub descriptor 87 * 88 * For more information see Universal Serial Bus Specification Revision 1.1 chapter 11.16.2 86 * @brief usb hub descriptor 87 * 88 * For more information see Universal Serial Bus Specification Revision 1.1 89 * chapter 11.16.2 89 90 */ 90 91 typedef struct usb_hub_descriptor_type { -
uspace/lib/usb/include/usb/hc.h
r9c3bba0 r899f1a9 1 1 /* 2 2 * Copyright (c) 2011 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely 3 4 * All rights reserved. 4 5 * … … 26 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 */ 28 29 29 /** @addtogroup libusb 30 30 * @{ … … 36 36 #define LIBUSB_HC_H_ 37 37 38 #include <sys/types.h> 39 #include <ipc/devman.h> 40 #include <ipc/loc.h> 38 #include <devman.h> 41 39 #include <ddf/driver.h> 42 40 #include <bool.h> 43 #include < async.h>41 #include <fibril_synch.h> 44 42 #include <usb/usb.h> 45 43 … … 50 48 /** Session to the host controller. */ 51 49 async_sess_t *hc_sess; 50 /** Session guard. */ 51 fibril_mutex_t guard; 52 /** Use counter. */ 53 unsigned ref_count; 52 54 } usb_hc_connection_t; 55 56 /** Initialize connection to USB host controller. 57 * 58 * @param connection Connection to be initialized. 59 * @param hc_handle Devman handle of the host controller. 60 * @return Error code. 61 */ 62 static inline void usb_hc_connection_initialize(usb_hc_connection_t *connection, 63 devman_handle_t hc_handle) 64 { 65 assert(connection); 66 connection->hc_handle = hc_handle; 67 connection->hc_sess = NULL; 68 connection->ref_count = 0; 69 fibril_mutex_initialize(&connection->guard); 70 } 53 71 54 72 int usb_hc_connection_initialize_from_device(usb_hc_connection_t *, 55 73 const ddf_dev_t *); 56 int usb_hc_connection_initialize(usb_hc_connection_t *, devman_handle_t);57 74 58 75 int usb_hc_connection_open(usb_hc_connection_t *); 59 bool usb_hc_connection_is_opened(const usb_hc_connection_t *);60 76 int usb_hc_connection_close(usb_hc_connection_t *); 77 78 usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_address_t, bool, 79 usb_speed_t); 80 int usb_hc_bind_address(usb_hc_connection_t *, usb_address_t, devman_handle_t); 61 81 int usb_hc_get_handle_by_address(usb_hc_connection_t *, usb_address_t, 62 82 devman_handle_t *); 83 int usb_hc_release_address(usb_hc_connection_t *, usb_address_t); 63 84 64 usb_address_t usb_get_address_by_handle(devman_handle_t); 85 int usb_hc_register_endpoint(usb_hc_connection_t *, usb_address_t, 86 usb_endpoint_t, usb_transfer_type_t, usb_direction_t, size_t, unsigned int); 87 int usb_hc_unregister_endpoint(usb_hc_connection_t *, usb_address_t, 88 usb_endpoint_t, usb_direction_t); 65 89 66 int usb_hc_find(devman_handle_t, devman_handle_t *); 90 int usb_hc_control_read(usb_hc_connection_t *, usb_address_t, usb_endpoint_t, 91 uint64_t, void *, size_t, size_t *); 92 int usb_hc_control_write(usb_hc_connection_t *, usb_address_t, usb_endpoint_t, 93 uint64_t, const void *, size_t); 67 94 68 int usb_resolve_device_handle(const char *, devman_handle_t *, usb_address_t *, 69 devman_handle_t *); 95 static inline int usb_hc_read(usb_hc_connection_t *connection, 96 usb_address_t address, usb_endpoint_t endpoint, void *data, size_t size, 97 size_t *real_size) 98 { 99 return usb_hc_control_read( 100 connection, address, endpoint, 0, data, size, real_size); 101 } 102 103 static inline int usb_hc_write(usb_hc_connection_t *connection, 104 usb_address_t address, usb_endpoint_t endpoint, const void *data, 105 size_t size) 106 { 107 return usb_hc_control_write( 108 connection, address, endpoint, 0, data, size); 109 } 70 110 71 111 int usb_ddf_get_hc_handle_by_sid(service_id_t, devman_handle_t *); 72 73 112 74 113 #endif -
uspace/lib/usb/include/usb/usb.h
r9c3bba0 r899f1a9 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 28 /** @addtogroup libusb 30 29 * @{ -
uspace/lib/usb/src/ddfiface.c
r9c3bba0 r899f1a9 44 44 #include <assert.h> 45 45 46 #include <usb/dev.h> 47 46 48 /** DDF interface for USB device, implementation for typical hub. */ 47 49 usb_iface_t usb_iface_hub_impl = { … … 66 68 { 67 69 assert(fun); 68 return usb_ hc_find(fun->handle, handle);70 return usb_get_hc_by_handle(fun->handle, handle); 69 71 } 70 72 … … 134 136 assert(fun); 135 137 assert(fun->driver_data); 136 usb_hub_attached_device_t *device = fun->driver_data;138 const usb_hub_attached_device_t *device = fun->driver_data; 137 139 assert(device->fun == fun); 138 140 if (address) -
uspace/lib/usb/src/hc.c
r9c3bba0 r899f1a9 1 1 /* 2 2 * Copyright (c) 2011 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely 3 4 * All rights reserved. 4 5 * … … 26 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 */ 28 29 29 /** @addtogroup libusb 30 30 * @{ … … 33 33 * General communication with host controller driver (implementation). 34 34 */ 35 #include < devman.h>36 #include <async.h> 37 #include < dev_iface.h>38 #include < usb_iface.h>35 #include <usb/debug.h> 36 37 #include <assert.h> 38 #include <errno.h> 39 39 #include <usbhc_iface.h> 40 #include <usb/dev.h> 40 41 #include <usb/hc.h> 41 #include <usb/debug.h> 42 #include <errno.h> 43 #include <assert.h> 42 43 static int usb_hc_connection_add_ref(usb_hc_connection_t *connection) 44 { 45 assert(connection); 46 fibril_mutex_lock(&connection->guard); 47 if (connection->ref_count == 0) { 48 assert(connection->hc_sess == NULL); 49 /* Parallel exchange for us */ 50 connection->hc_sess = devman_device_connect(EXCHANGE_PARALLEL, 51 connection->hc_handle, 0); 52 if (!connection->hc_sess) { 53 fibril_mutex_unlock(&connection->guard); 54 return ENOMEM; 55 } 56 } 57 ++connection->ref_count; 58 fibril_mutex_unlock(&connection->guard); 59 return EOK; 60 } 61 /*----------------------------------------------------------------------------*/ 62 static int usb_hc_connection_del_ref(usb_hc_connection_t *connection) 63 { 64 assert(connection); 65 fibril_mutex_lock(&connection->guard); 66 --connection->ref_count; 67 int ret = EOK; 68 if (connection->ref_count == 0) { 69 assert(connection->hc_sess); 70 ret = async_hangup(connection->hc_sess); 71 connection->hc_sess = NULL; 72 } 73 fibril_mutex_unlock(&connection->guard); 74 return ret; 75 } 76 77 #define EXCH_INIT(connection, exch) \ 78 do { \ 79 exch = NULL; \ 80 if (!connection) \ 81 return EBADMEM; \ 82 const int ret = usb_hc_connection_add_ref(connection); \ 83 if (ret != EOK) \ 84 return ret; \ 85 exch = async_exchange_begin(connection->hc_sess); \ 86 if (exch == NULL) { \ 87 usb_hc_connection_del_ref(connection); \ 88 return ENOMEM; \ 89 } \ 90 } while (0) 91 92 #define EXCH_FINI(connection, exch) \ 93 if (exch) { \ 94 async_exchange_end(exch); \ 95 usb_hc_connection_del_ref(connection); \ 96 } else (void)0 44 97 45 98 /** Initialize connection to USB host controller. … … 59 112 60 113 devman_handle_t hc_handle; 61 int rc = usb_hc_find(device->handle, &hc_handle); 62 if (rc != EOK) { 63 return rc; 64 } 65 66 rc = usb_hc_connection_initialize(connection, hc_handle); 114 const int rc = usb_get_hc_by_handle(device->handle, &hc_handle); 115 if (rc == EOK) { 116 usb_hc_connection_initialize(connection, hc_handle); 117 } 67 118 68 119 return rc; 69 120 } 70 71 /** Manually initialize connection to USB host controller. 72 * 73 * @param connection Connection to be initialized. 74 * @param hc_handle Devman handle of the host controller. 75 * @return Error code. 76 */ 77 int usb_hc_connection_initialize(usb_hc_connection_t *connection, 78 devman_handle_t hc_handle) 79 { 80 assert(connection); 81 82 connection->hc_handle = hc_handle; 83 connection->hc_sess = NULL; 84 85 return EOK; 86 } 87 121 /*----------------------------------------------------------------------------*/ 88 122 /** Open connection to host controller. 89 123 * … … 93 127 int usb_hc_connection_open(usb_hc_connection_t *connection) 94 128 { 95 assert(connection); 96 97 if (usb_hc_connection_is_opened(connection)) 98 return EBUSY; 99 100 async_sess_t *sess = devman_device_connect(EXCHANGE_ATOMIC, 101 connection->hc_handle, 0); 102 if (!sess) 103 return ENOMEM; 104 105 connection->hc_sess = sess; 106 return EOK; 107 } 108 109 /** Tells whether connection to host controller is opened. 129 return usb_hc_connection_add_ref(connection); 130 } 131 /*----------------------------------------------------------------------------*/ 132 /** Close connection to the host controller. 110 133 * 111 134 * @param connection Connection to the host controller. 112 * @return Whether connection is opened.113 */114 bool usb_hc_connection_is_opened(const usb_hc_connection_t *connection)115 {116 assert(connection);117 return (connection->hc_sess != NULL);118 }119 120 /** Close connection to the host controller.121 *122 * @param connection Connection to the host controller.123 135 * @return Error code. 124 136 */ 125 137 int usb_hc_connection_close(usb_hc_connection_t *connection) 126 138 { 127 assert(connection); 128 129 if (!usb_hc_connection_is_opened(connection)) { 130 return ENOENT; 131 } 132 133 int rc = async_hangup(connection->hc_sess); 134 if (rc != EOK) { 135 return rc; 136 } 137 138 connection->hc_sess = NULL; 139 140 return EOK; 141 } 142 139 return usb_hc_connection_del_ref(connection); 140 } 141 /*----------------------------------------------------------------------------*/ 142 /** Ask host controller for free address assignment. 143 * 144 * @param connection Opened connection to host controller. 145 * @param preferred Preferred SUB address. 146 * @param strict Fail if the preferred address is not avialable. 147 * @param speed Speed of the new device (device that will be assigned 148 * the returned address). 149 * @return Assigned USB address or negative error code. 150 */ 151 usb_address_t usb_hc_request_address(usb_hc_connection_t *connection, 152 usb_address_t preferred, bool strict, usb_speed_t speed) 153 { 154 async_exch_t *exch; 155 EXCH_INIT(connection, exch); 156 157 usb_address_t address = preferred; 158 const int ret = usbhc_request_address(exch, &address, strict, speed); 159 160 EXCH_FINI(connection, exch); 161 return ret == EOK ? address : ret; 162 } 163 /*----------------------------------------------------------------------------*/ 164 int usb_hc_bind_address(usb_hc_connection_t * connection, 165 usb_address_t address, devman_handle_t handle) 166 { 167 async_exch_t *exch; 168 EXCH_INIT(connection, exch); 169 170 const int ret = usbhc_bind_address(exch, address, handle); 171 172 EXCH_FINI(connection, exch); 173 return ret; 174 } 175 /*----------------------------------------------------------------------------*/ 143 176 /** Get handle of USB device with given address. 144 177 * … … 151 184 usb_address_t address, devman_handle_t *handle) 152 185 { 153 if (!usb_hc_connection_is_opened(connection)) 154 return ENOENT; 155 156 async_exch_t *exch = async_exchange_begin(connection->hc_sess); 157 if (!exch) 158 return ENOMEM; 186 async_exch_t *exch; 187 EXCH_INIT(connection, exch); 188 159 189 const int ret = usbhc_get_handle(exch, address, handle); 160 async_exchange_end(exch); 161 return ret; 162 } 163 164 /** Tell USB address assigned to device with given handle. 165 * 166 * @param dev_handle Devman handle of the USB device in question. 167 * @return USB address or negative error code. 168 */ 169 usb_address_t usb_get_address_by_handle(devman_handle_t dev_handle) 170 { 171 async_sess_t *parent_sess = 172 devman_parent_device_connect(EXCHANGE_ATOMIC, dev_handle, 173 IPC_FLAG_BLOCKING); 174 if (!parent_sess) 175 return ENOMEM; 176 177 async_exch_t *exch = async_exchange_begin(parent_sess); 178 if (!exch) { 179 async_hangup(parent_sess); 180 return ENOMEM; 181 } 182 usb_address_t address; 183 const int ret = usb_get_my_address(exch, &address); 184 185 async_exchange_end(exch); 186 async_hangup(parent_sess); 187 188 if (ret != EOK) 189 return ret; 190 191 return address; 192 } 193 194 190 191 EXCH_FINI(connection, exch); 192 return ret; 193 } 194 /*----------------------------------------------------------------------------*/ 195 int usb_hc_release_address(usb_hc_connection_t *connection, 196 usb_address_t address) 197 { 198 async_exch_t *exch; 199 EXCH_INIT(connection, exch); 200 201 const int ret = usbhc_release_address(exch, address); 202 203 EXCH_FINI(connection, exch); 204 return ret; 205 } 206 /*----------------------------------------------------------------------------*/ 207 int usb_hc_register_endpoint(usb_hc_connection_t *connection, 208 usb_address_t address, usb_endpoint_t endpoint, usb_transfer_type_t type, 209 usb_direction_t direction, size_t packet_size, unsigned interval) 210 { 211 async_exch_t *exch; 212 EXCH_INIT(connection, exch); 213 214 const int ret = usbhc_register_endpoint(exch, address, endpoint, 215 type, direction, packet_size, interval); 216 217 EXCH_FINI(connection, exch); 218 return ret; 219 } 220 /*----------------------------------------------------------------------------*/ 221 int usb_hc_unregister_endpoint(usb_hc_connection_t *connection, 222 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 223 { 224 async_exch_t *exch; 225 EXCH_INIT(connection, exch); 226 227 const int ret = 228 usbhc_unregister_endpoint(exch, address, endpoint, direction); 229 230 EXCH_FINI(connection, exch); 231 return ret; 232 } 233 /*----------------------------------------------------------------------------*/ 234 int usb_hc_control_read(usb_hc_connection_t *connection, usb_address_t address, 235 usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size, 236 size_t *real_size) 237 { 238 async_exch_t *exch; 239 EXCH_INIT(connection, exch); 240 241 const int ret = 242 usbhc_read(exch, address, endpoint, setup, data, size, real_size); 243 244 EXCH_FINI(connection, exch); 245 return ret; 246 } 247 /*----------------------------------------------------------------------------*/ 248 int usb_hc_control_write(usb_hc_connection_t *connection, usb_address_t address, 249 usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size) 250 { 251 async_exch_t *exch; 252 EXCH_INIT(connection, exch); 253 254 const int ret = usbhc_write(exch, address, endpoint, setup, data, size); 255 256 EXCH_FINI(connection, exch); 257 return ret; 258 } 259 /*----------------------------------------------------------------------------*/ 195 260 /** Get host controller handle by its class index. 196 261 * … … 203 268 { 204 269 devman_handle_t handle; 205 int rc; 206 207 rc = devman_fun_sid_to_handle(sid, &handle); 208 if (hc_handle != NULL) 270 271 const int ret = devman_fun_sid_to_handle(sid, &handle); 272 if (ret == EOK && hc_handle != NULL) 209 273 *hc_handle = handle; 210 211 return rc;212 }213 214 /** Find host controller handle that is ancestor of given device.215 *216 * @param[in] device_handle Device devman handle.217 * @param[out] hc_handle Where to store handle of host controller218 * controlling device with @p device_handle handle.219 * @return Error code.220 */221 int usb_hc_find(devman_handle_t device_handle, devman_handle_t *hc_handle)222 {223 async_sess_t *parent_sess =224 devman_parent_device_connect(EXCHANGE_ATOMIC, device_handle,225 IPC_FLAG_BLOCKING);226 if (!parent_sess)227 return ENOMEM;228 229 async_exch_t *exch = async_exchange_begin(parent_sess);230 if (!exch) {231 async_hangup(parent_sess);232 return ENOMEM;233 }234 const int ret = usb_get_hc_handle(exch, hc_handle);235 236 async_exchange_end(exch);237 async_hangup(parent_sess);238 274 239 275 return ret; -
uspace/lib/usb/src/resolve.c
r9c3bba0 r899f1a9 34 34 */ 35 35 #include <inttypes.h> 36 #include <usb/dev.h> 36 37 #include <usb/hc.h> 37 38 #include <devman.h> … … 77 78 devman_handle_t *dev_handle) 78 79 { 79 int rc;80 80 usb_hc_connection_t conn; 81 82 81 usb_hc_connection_initialize(&conn, hc_handle); 83 rc = usb_hc_connection_open(&conn); 84 if (rc != EOK) { 85 return rc; 86 } 87 88 rc = usb_hc_get_handle_by_address(&conn, addr, dev_handle); 89 90 usb_hc_connection_close(&conn); 82 83 const int rc = usb_hc_get_handle_by_address(&conn, addr, dev_handle); 91 84 92 85 return rc; … … 192 185 /* Try to find its host controller. */ 193 186 if (!found_hc) { 194 rc = usb_ hc_find(tmp_handle, &hc_handle);187 rc = usb_get_hc_by_handle(tmp_handle, &hc_handle); 195 188 if (rc == EOK) { 196 189 found_hc = true; -
uspace/lib/usb/src/usb.c
r9c3bba0 r899f1a9 39 39 40 40 static const char *str_speed[] = { 41 "low",42 "full",43 "high"41 [USB_SPEED_LOW] = "low", 42 [USB_SPEED_FULL] = "full", 43 [USB_SPEED_HIGH] = "high", 44 44 }; 45 45 46 46 static const char *str_transfer_type[] = { 47 "control",48 "isochronous",49 "bulk",50 "interrupt"47 [USB_TRANSFER_CONTROL] = "control", 48 [USB_TRANSFER_ISOCHRONOUS] = "isochronous", 49 [USB_TRANSFER_BULK] = "bulk", 50 [USB_TRANSFER_INTERRUPT] = "interrupt", 51 51 }; 52 52 53 53 static const char *str_transfer_type_short[] = { 54 "ctrl",55 "iso",56 "bulk",57 "intr"54 [USB_TRANSFER_CONTROL] = "ctrl", 55 [USB_TRANSFER_ISOCHRONOUS] = "iso", 56 [USB_TRANSFER_BULK] = "bulk", 57 [USB_TRANSFER_INTERRUPT] = "intr", 58 58 }; 59 59 60 60 static const char *str_direction[] = { 61 "in",62 "out",63 "both"61 [USB_DIRECTION_IN] = "in", 62 [USB_DIRECTION_OUT] = "out", 63 [USB_DIRECTION_BOTH] = "both", 64 64 }; 65 65 -
uspace/lib/usbdev/Makefile
r9c3bba0 r899f1a9 40 40 src/dp.c \ 41 41 src/hub.c \ 42 src/pipepriv.c \43 src/pipepriv.h \44 42 src/pipes.c \ 45 43 src/pipesinit.c \ 46 src/pipesio.c \47 44 src/recognise.c \ 48 45 src/request.c -
uspace/lib/usbdev/include/usb/dev/driver.h
r9c3bba0 r899f1a9 72 72 /** USB device structure. */ 73 73 typedef struct { 74 usb_hc_connection_t hc_conn; 74 75 /** Connection backing the pipes. 75 76 * Typically, you will not need to use this attribute at all. -
uspace/lib/usbdev/include/usb/dev/pipes.h
r9c3bba0 r899f1a9 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 28 /** @addtogroup libusbdev 30 29 * @{ … … 38 37 #include <sys/types.h> 39 38 #include <usb/usb.h> 40 #include <usb/ hc.h>39 #include <usb/dev.h> 41 40 #include <usb/descriptor.h> 42 41 #include <ipc/devman.h> … … 44 43 #include <fibril_synch.h> 45 44 #include <async.h> 46 47 /** Abstraction of a physical connection to the device.48 * This type is an abstraction of the USB wire that connects the host and49 * the function (device).50 */51 typedef struct {52 /** Handle of the host controller device is connected to. */53 devman_handle_t hc_handle;54 /** Address of the device. */55 usb_address_t address;56 } usb_device_connection_t;57 45 58 46 /** Abstraction of a logical connection to USB device endpoint. … … 85 73 /** Maximum packet size for the endpoint. */ 86 74 size_t max_packet_size; 87 88 /** Session to the host controller.89 * NULL when no session is active.90 * It is an error to access this member without @c hc_sess_mutex91 * being locked.92 * If call over the phone is to be made, it must be preceeded by93 * call to pipe_add_ref() [internal libusb function].94 */95 async_sess_t *hc_sess;96 97 /** Guard for serialization of requests over the session. */98 fibril_mutex_t hc_sess_mutex;99 100 /** Number of active transfers over the pipe. */101 int refcount;102 /** Number of failed attempts to open the HC phone.103 * When user requests usb_pipe_start_long_transfer() and the operation104 * fails, there is no way to report this to the user.105 * That the soft reference counter is increased to record the attempt.106 * When the user then request e.g. usb_pipe_read(), it will try to107 * add reference as well.108 * If that fails, it is reported to the user. If it is okay, the109 * real reference counter is incremented.110 * The problem might arise when ending the long transfer (since111 * the number of references would be only 1, but logically it shall be112 * two).113 * Decrementing the soft counter first shall solve this.114 */115 int refcount_soft;116 75 117 76 /** Whether to automatically reset halt on the endpoint. … … 156 115 } usb_endpoint_mapping_t; 157 116 158 int usb_device_connection_initialize_on_default_address(159 usb_device_connection_t *, usb_hc_connection_t *);160 int usb_device_connection_initialize_from_device(usb_device_connection_t *,161 const ddf_dev_t *);162 int usb_device_connection_initialize(usb_device_connection_t *,163 devman_handle_t, usb_address_t);164 117 165 118 int usb_device_get_assigned_interface(const ddf_dev_t *); … … 169 122 int usb_pipe_initialize_default_control(usb_pipe_t *, 170 123 usb_device_connection_t *); 124 171 125 int usb_pipe_probe_default_control(usb_pipe_t *); 172 126 int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *, 173 127 size_t, const uint8_t *, size_t, usb_device_connection_t *); 174 int usb_pipe_register(usb_pipe_t *, unsigned int, usb_hc_connection_t *);175 int usb_pipe_unregister(usb_pipe_t * , usb_hc_connection_t *);128 int usb_pipe_register(usb_pipe_t *, unsigned); 129 int usb_pipe_unregister(usb_pipe_t *); 176 130 177 voidusb_pipe_start_long_transfer(usb_pipe_t *);178 voidusb_pipe_end_long_transfer(usb_pipe_t *);131 int usb_pipe_start_long_transfer(usb_pipe_t *); 132 int usb_pipe_end_long_transfer(usb_pipe_t *); 179 133 180 134 int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *); -
uspace/lib/usbdev/include/usb/dev/request.h
r9c3bba0 r899f1a9 83 83 uint8_t request_type; 84 84 #define SETUP_REQUEST_TYPE_DEVICE_TO_HOST (1 << 7) 85 #define SETUP_REQUEST_TYPE_GET_TYPE(rt) ((rt >> 5) & 0x3) 86 #define SETUP_REQUEST_TYPE_GET_RECIPIENT(rec) (rec & 0x1f) 87 #define SETUP_REQUEST_TO_HOST(type, recipient) \ 88 (uint8_t)((1 << 7) | ((type & 0x3) << 5) | (recipient & 0x1f)) 89 #define SETUP_REQUEST_TO_DEVICE(type, recipient) \ 90 (uint8_t)(((type & 0x3) << 5) | (recipient & 0x1f)) 85 91 86 92 /** Request identification. */ -
uspace/lib/usbdev/src/devdrv.c
r9c3bba0 r899f1a9 170 170 return ENOTSUP; 171 171 /* Just tell the driver to stop whatever it is doing, keep structures */ 172 return driver->ops->device_rem(gen_dev->driver_data); 172 const int ret = driver->ops->device_rem(gen_dev->driver_data); 173 if (ret != EOK) 174 return ret; 175 return ENOTSUP; 173 176 } 174 177 /*----------------------------------------------------------------------------*/ … … 373 376 } 374 377 375 /* Register the endpoints with HC. */376 usb_hc_connection_t hc_conn;377 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev);378 if (rc != EOK) {379 goto rollback_free_only;380 }381 382 rc = usb_hc_connection_open(&hc_conn);383 if (rc != EOK) {384 goto rollback_free_only;385 }386 387 378 for (i = 0; i < pipe_count; i++) { 388 379 if (pipes[i].present) { 389 380 rc = usb_pipe_register(&pipes[i].pipe, 390 pipes[i].descriptor->poll_interval , &hc_conn);381 pipes[i].descriptor->poll_interval); 391 382 if (rc != EOK) { 392 383 goto rollback_unregister_endpoints; … … 394 385 } 395 386 } 396 397 if (usb_hc_connection_close(&hc_conn) != EOK)398 usb_log_warning("%s: Failed to close connection.\n",399 __FUNCTION__);400 387 401 388 *pipes_ptr = pipes; … … 415 402 for (i = 0; i < pipe_count; i++) { 416 403 if (pipes[i].present) { 417 usb_pipe_unregister(&pipes[i].pipe , &hc_conn);404 usb_pipe_unregister(&pipes[i].pipe); 418 405 } 419 406 } 420 421 if (usb_hc_connection_close(&hc_conn) != EOK)422 usb_log_warning("usb_device_create_pipes(): "423 "Failed to close connection.\n");424 407 425 408 /* … … 470 453 i, pipes[i].present ? "" : "not "); 471 454 if (pipes[i].present) 472 usb_pipe_unregister(&pipes[i].pipe, &hc_conn); 473 } 474 475 if (usb_hc_connection_close(&hc_conn) != EOK) 476 usb_log_warning("usb_device_destroy_pipes(): " 477 "Failed to close connection.\n"); 455 usb_pipe_unregister(&pipes[i].pipe); 456 } 478 457 479 458 free(pipes); … … 505 484 usb_dev->pipes = NULL; 506 485 486 /* Initialize hc connection. */ 487 usb_hc_connection_initialize_from_device(&usb_dev->hc_conn, ddf_dev); 488 const usb_address_t address = 489 usb_get_address_by_handle(ddf_dev->handle); 490 507 491 /* Initialize backing wire and control pipe. */ 508 int rc = usb_device_connection_initialize _from_device(509 &usb_dev->wire, ddf_dev);492 int rc = usb_device_connection_initialize( 493 &usb_dev->wire, &usb_dev->hc_conn, address); 510 494 if (rc != EOK) { 511 495 *errstr_ptr = "device connection initialization"; … … 515 499 /* This pipe was registered by the hub driver, 516 500 * during device initialization. */ 517 rc = usb_pipe_initialize_default_control( &usb_dev->ctrl_pipe,518 &usb_dev-> wire);501 rc = usb_pipe_initialize_default_control( 502 &usb_dev->ctrl_pipe, &usb_dev->wire); 519 503 if (rc != EOK) { 520 504 *errstr_ptr = "default control pipe initialization"; 505 return rc; 506 } 507 508 rc = usb_hc_connection_open(&usb_dev->hc_conn); 509 if (rc != EOK) { 510 *errstr_ptr = "hc connection open"; 521 511 return rc; 522 512 } … … 524 514 /* Get our interface. */ 525 515 usb_dev->interface_no = usb_device_get_assigned_interface(ddf_dev); 526 527 516 /* Retrieve standard descriptors. */ 528 rc = usb_device_retrieve_descriptors( &usb_dev->ctrl_pipe,529 &usb_dev-> descriptors);517 rc = usb_device_retrieve_descriptors( 518 &usb_dev->ctrl_pipe, &usb_dev->descriptors); 530 519 if (rc != EOK) { 531 520 *errstr_ptr = "descriptor retrieval"; 521 usb_hc_connection_close(&usb_dev->hc_conn); 532 522 return rc; 533 523 } … … 546 536 rc = initialize_other_pipes(endpoints, usb_dev, alternate_iface); 547 537 if (rc != EOK) { 538 usb_hc_connection_close(&usb_dev->hc_conn); 548 539 /* Full configuration descriptor is allocated. */ 549 540 usb_device_release_descriptors(&usb_dev->descriptors); … … 554 545 } 555 546 547 usb_hc_connection_close(&usb_dev->hc_conn); 556 548 return EOK; 557 549 } -
uspace/lib/usbdev/src/hub.c
r9c3bba0 r899f1a9 63 63 } while (false) 64 64 65 /** Ask host controller for free address assignment.66 *67 * @param connection Opened connection to host controller.68 * @param preferred Preferred SUB address.69 * @param strict Fail if the preferred address is not avialable.70 * @param speed Speed of the new device (device that will be assigned71 * the returned address).72 * @return Assigned USB address or negative error code.73 */74 usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,75 usb_address_t preferred, bool strict, usb_speed_t speed)76 {77 CHECK_CONNECTION(connection);78 79 async_exch_t *exch = async_exchange_begin(connection->hc_sess);80 if (!exch)81 return (usb_address_t)ENOMEM;82 83 usb_address_t address = preferred;84 const int ret = usbhc_request_address(exch, &address, strict, speed);85 86 async_exchange_end(exch);87 return ret == EOK ? address : ret;88 }89 65 90 66 /** Inform host controller about new device. … … 97 73 const usb_hub_attached_device_t *attached_device) 98 74 { 99 CHECK_CONNECTION(connection);75 // CHECK_CONNECTION(connection); 100 76 if (attached_device == NULL || attached_device->fun == NULL) 101 77 return EINVAL; … … 120 96 usb_address_t address) 121 97 { 122 CHECK_CONNECTION(connection);98 // CHECK_CONNECTION(connection); 123 99 124 100 async_exch_t *exch = async_exchange_begin(connection->hc_sess); … … 145 121 * @return Error code. 146 122 */ 147 static int usb_request_set_address(usb_pipe_t *pipe, usb_address_t new_address, 148 usb_hc_connection_t *hc_conn) 123 static int usb_request_set_address(usb_pipe_t *pipe, usb_address_t new_address) 149 124 { 150 125 if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) { … … 152 127 } 153 128 assert(pipe); 154 assert(hc_conn);155 129 assert(pipe->wire != NULL); 156 130 … … 166 140 167 141 /* TODO: prevent others from accessing the wire now. */ 168 if (usb_pipe_unregister(pipe , hc_conn) != EOK) {142 if (usb_pipe_unregister(pipe) != EOK) { 169 143 usb_log_warning( 170 144 "Failed to unregister the old pipe on address change.\n"); 171 145 } 146 /* Address changed. We can release the default, thus 147 * allowing other to access the default address. */ 148 usb_hc_unregister_device(pipe->wire->hc_connection, 149 pipe->wire->address); 150 172 151 /* The address is already changed so set it in the wire */ 173 152 pipe->wire->address = new_address; 174 rc = usb_pipe_register(pipe, 0 , hc_conn);153 rc = usb_pipe_register(pipe, 0); 175 154 if (rc != EOK) 176 155 return EADDRNOTAVAIL; … … 220 199 */ 221 200 int usb_hc_new_device_wrapper(ddf_dev_t *parent, 222 usb_hc_connection_t * connection, usb_speed_t dev_speed,201 usb_hc_connection_t *hc_conn, usb_speed_t dev_speed, 223 202 int (*enable_port)(void *arg), void *arg, usb_address_t *assigned_address, 224 203 ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun) 225 204 { 226 if (new_fun == NULL || connection == NULL)205 if (new_fun == NULL || hc_conn == NULL) 227 206 return EINVAL; 228 229 // TODO: Why not use provided connection?230 usb_hc_connection_t hc_conn;231 usb_hc_connection_initialize(&hc_conn, connection->hc_handle);232 207 233 208 int rc; … … 239 214 } 240 215 241 rc = usb_hc_connection_open(&hc_conn); 216 /* We are gona do a lot of communication better open it in advance. */ 217 rc = usb_hc_connection_open(hc_conn); 242 218 if (rc != EOK) { 243 219 return rc; 244 220 } 245 221 246 /* 247 * Request new address. 248 */ 222 /* Request a new address. */ 249 223 usb_address_t dev_addr = 250 usb_hc_request_address( &hc_conn, 0, false, dev_speed);224 usb_hc_request_address(hc_conn, 0, false, dev_speed); 251 225 if (dev_addr < 0) { 252 226 rc = EADDRNOTAVAIL; 253 227 goto close_connection; 228 } 229 230 /* Initialize connection to device. */ 231 usb_device_connection_t dev_conn; 232 rc = usb_device_connection_initialize_on_default_address( 233 &dev_conn, hc_conn); 234 if (rc != EOK) { 235 rc = ENOTCONN; 236 goto leave_release_free_address; 254 237 } 255 238 … … 260 243 * (Someone else already wants to add a new device.) 261 244 */ 262 usb_device_connection_t dev_conn;263 rc = usb_device_connection_initialize_on_default_address(&dev_conn,264 &hc_conn);265 if (rc != EOK) {266 rc = ENOTCONN;267 goto leave_release_free_address;268 }269 270 245 usb_pipe_t ctrl_pipe; 271 246 rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn); … … 276 251 277 252 do { 278 rc = usb_hc_request_address( &hc_conn, USB_ADDRESS_DEFAULT,253 rc = usb_hc_request_address(hc_conn, USB_ADDRESS_DEFAULT, 279 254 true, dev_speed); 280 255 if (rc == ENOENT) { … … 288 263 289 264 /* Register control pipe on default address. */ 290 rc = usb_pipe_register(&ctrl_pipe, 0 , &hc_conn);265 rc = usb_pipe_register(&ctrl_pipe, 0); 291 266 if (rc != EOK) { 292 267 rc = ENOTCONN; … … 330 305 } 331 306 332 rc = usb_request_set_address(&ctrl_pipe, dev_addr , &hc_conn);307 rc = usb_request_set_address(&ctrl_pipe, dev_addr); 333 308 if (rc != EOK) { 334 309 rc = ESTALL; … … 336 311 } 337 312 338 /* Address changed. We can release the default, thus339 * allowing other to access the default address. */340 usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT);341 313 342 314 /* Register the device with devman. */ … … 356 328 357 329 /* Inform the host controller about the handle. */ 358 rc = usb_hc_register_device( &hc_conn, &new_device);330 rc = usb_hc_register_device(hc_conn, &new_device); 359 331 if (rc != EOK) { 360 332 /* We know nothing about that data. */ … … 381 353 */ 382 354 leave_release_default_address: 383 usb_hc_unregister_device( &hc_conn, USB_ADDRESS_DEFAULT);355 usb_hc_unregister_device(hc_conn, USB_ADDRESS_DEFAULT); 384 356 385 357 leave_release_free_address: 386 358 /* This might be either 0:0 or dev_addr:0 */ 387 if (usb_pipe_unregister(&ctrl_pipe , &hc_conn) != EOK)359 if (usb_pipe_unregister(&ctrl_pipe) != EOK) 388 360 usb_log_warning("%s: Failed to unregister default pipe.\n", 389 361 __FUNCTION__); 390 362 391 if (usb_hc_unregister_device( &hc_conn, dev_addr) != EOK)363 if (usb_hc_unregister_device(hc_conn, dev_addr) != EOK) 392 364 usb_log_warning("%s: Failed to unregister device.\n", 393 365 __FUNCTION__); 394 366 395 367 close_connection: 396 if (usb_hc_connection_close( &hc_conn) != EOK)368 if (usb_hc_connection_close(hc_conn) != EOK) 397 369 usb_log_warning("%s: Failed to close hc connection.\n", 398 370 __FUNCTION__); -
uspace/lib/usbdev/src/pipes.c
r9c3bba0 r899f1a9 1 1 /* 2 2 * Copyright (c) 2011 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely 3 4 * All rights reserved. 4 5 * … … 26 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 */ 28 29 29 /** @addtogroup libusbdev 30 30 * @{ … … 33 33 * USB endpoint pipes miscellaneous functions. 34 34 */ 35 #include <usb /usb.h>35 #include <usb_iface.h> 36 36 #include <usb/dev/pipes.h> 37 #include <usb/debug.h> 38 #include <usb/hc.h> 39 #include <usbhc_iface.h> 40 #include <usb_iface.h> 41 #include <devman.h> 37 #include <usb/dev/request.h> 42 38 #include <errno.h> 43 39 #include <assert.h> 44 #include "pipepriv.h"45 46 #define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */47 48 /** Tell USB address assigned to given device.49 *50 * @param sess Session to parent device.51 * @param dev Device in question.52 * @return USB address or error code.53 */54 static usb_address_t get_my_address(async_sess_t *sess, const ddf_dev_t *dev)55 {56 assert(sess);57 async_exch_t *exch = async_exchange_begin(sess);58 if (!exch)59 return ENOMEM;60 61 usb_address_t address;62 const int ret = usb_get_my_address(exch, &address);63 64 async_exchange_end(exch);65 66 return (ret == EOK) ? address : ret;67 }68 40 69 41 /** Tell USB interface assigned to given device. … … 92 64 return ret == EOK ? iface_no : ret; 93 65 } 94 95 /** Initialize connection to USB device. 96 * 97 * @param connection Connection structure to be initialized. 98 * @param dev Generic device backing the USB device. 99 * @return Error code. 100 */ 101 int usb_device_connection_initialize_from_device( 102 usb_device_connection_t *connection, const ddf_dev_t *dev) 103 { 104 assert(connection); 105 assert(dev); 106 107 int rc; 108 devman_handle_t hc_handle; 109 usb_address_t my_address; 110 111 rc = usb_hc_find(dev->handle, &hc_handle); 112 if (rc != EOK) 113 return rc; 114 115 async_sess_t *parent_sess = 116 devman_parent_device_connect(EXCHANGE_ATOMIC, dev->handle, 117 IPC_FLAG_BLOCKING); 118 if (!parent_sess) 119 return ENOMEM; 120 121 /* 122 * Asking for "my" address may require several attempts. 123 * That is because following scenario may happen: 124 * - parent driver (i.e. driver of parent device) announces new device 125 * and devman launches current driver 126 * - parent driver is preempted and thus does not send address-handle 127 * binding to HC driver 128 * - this driver gets here and wants the binding 129 * - the HC does not know the binding yet and thus it answers ENOENT 130 * So, we need to wait for the HC to learn the binding. 131 */ 132 133 do { 134 my_address = get_my_address(parent_sess, dev); 135 136 if (my_address == ENOENT) { 137 /* Be nice, let other fibrils run and try again. */ 138 async_usleep(IPC_AGAIN_DELAY); 139 } else if (my_address < 0) { 140 /* Some other problem, no sense trying again. */ 141 rc = my_address; 142 goto leave; 143 } 144 145 } while (my_address < 0); 146 147 rc = usb_device_connection_initialize(connection, 148 hc_handle, my_address); 149 150 leave: 151 async_hangup(parent_sess); 152 return rc; 153 } 154 155 /** Initialize connection to USB device. 156 * 157 * @param connection Connection structure to be initialized. 158 * @param host_controller_handle Devman handle of host controller device is 159 * connected to. 160 * @param device_address Device USB address. 161 * @return Error code. 162 */ 163 int usb_device_connection_initialize(usb_device_connection_t *connection, 164 devman_handle_t host_controller_handle, usb_address_t device_address) 165 { 166 assert(connection); 167 168 if ((device_address < 0) || (device_address >= USB11_ADDRESS_MAX)) { 169 return EINVAL; 170 } 171 172 connection->hc_handle = host_controller_handle; 173 connection->address = device_address; 174 175 return EOK; 176 } 177 178 /** Initialize connection to USB device on default address. 179 * 180 * @param dev_connection Device connection structure to be initialized. 181 * @param hc_connection Initialized connection to host controller. 182 * @return Error code. 183 */ 184 int usb_device_connection_initialize_on_default_address( 185 usb_device_connection_t *dev_connection, 186 usb_hc_connection_t *hc_connection) 187 { 188 assert(dev_connection); 189 190 if (hc_connection == NULL) { 191 return EBADMEM; 192 } 193 194 return usb_device_connection_initialize(dev_connection, 195 hc_connection->hc_handle, (usb_address_t) 0); 196 } 197 66 /*----------------------------------------------------------------------------*/ 198 67 /** Prepare pipe for a long transfer. 199 68 * … … 206 75 * @return Error code. 207 76 */ 208 void usb_pipe_start_long_transfer(usb_pipe_t *pipe) 209 { 210 (void) pipe_add_ref(pipe, true); 211 } 212 77 int usb_pipe_start_long_transfer(usb_pipe_t *pipe) 78 { 79 assert(pipe); 80 assert(pipe->wire); 81 assert(pipe->wire->hc_connection); 82 return usb_hc_connection_open(pipe->wire->hc_connection); 83 } 84 /*----------------------------------------------------------------------------*/ 213 85 /** Terminate a long transfer on a pipe. 214 86 * … … 217 89 * @param pipe Pipe where to end the long transfer. 218 90 */ 219 void usb_pipe_end_long_transfer(usb_pipe_t *pipe) 220 { 221 pipe_drop_ref(pipe); 222 } 223 91 int usb_pipe_end_long_transfer(usb_pipe_t *pipe) 92 { 93 assert(pipe); 94 assert(pipe->wire); 95 assert(pipe->wire->hc_connection); 96 return usb_hc_connection_close(pipe->wire->hc_connection); 97 } 98 /*----------------------------------------------------------------------------*/ 99 /** Request an in transfer, no checking of input parameters. 100 * 101 * @param[in] pipe Pipe used for the transfer. 102 * @param[out] buffer Buffer where to store the data. 103 * @param[in] size Size of the buffer (in bytes). 104 * @param[out] size_transfered Number of bytes that were actually transfered. 105 * @return Error code. 106 */ 107 static int usb_pipe_read_no_check(usb_pipe_t *pipe, uint64_t setup, 108 void *buffer, size_t size, size_t *size_transfered) 109 { 110 /* Isochronous transfer are not supported (yet) */ 111 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 112 pipe->transfer_type != USB_TRANSFER_BULK && 113 pipe->transfer_type != USB_TRANSFER_CONTROL) 114 return ENOTSUP; 115 116 return usb_hc_control_read(pipe->wire->hc_connection, 117 pipe->wire->address, pipe->endpoint_no, setup, buffer, size, 118 size_transfered); 119 } 120 /*----------------------------------------------------------------------------*/ 121 /** Request an out transfer, no checking of input parameters. 122 * 123 * @param[in] pipe Pipe used for the transfer. 124 * @param[in] buffer Buffer with data to transfer. 125 * @param[in] size Size of the buffer (in bytes). 126 * @return Error code. 127 */ 128 static int usb_pipe_write_no_check(usb_pipe_t *pipe, uint64_t setup, 129 const void *buffer, size_t size) 130 { 131 /* Only interrupt and bulk transfers are supported */ 132 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 133 pipe->transfer_type != USB_TRANSFER_BULK && 134 pipe->transfer_type != USB_TRANSFER_CONTROL) 135 return ENOTSUP; 136 137 return usb_hc_control_write(pipe->wire->hc_connection, 138 pipe->wire->address, pipe->endpoint_no, setup, buffer, size); 139 } 140 /*----------------------------------------------------------------------------*/ 141 /** Try to clear endpoint halt of default control pipe. 142 * 143 * @param pipe Pipe for control endpoint zero. 144 */ 145 static void clear_self_endpoint_halt(usb_pipe_t *pipe) 146 { 147 assert(pipe != NULL); 148 149 if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) { 150 return; 151 } 152 153 154 /* Prevent infinite recursion. */ 155 pipe->auto_reset_halt = false; 156 usb_request_clear_endpoint_halt(pipe, 0); 157 pipe->auto_reset_halt = true; 158 } 159 /*----------------------------------------------------------------------------*/ 160 /** Request a control read transfer on an endpoint pipe. 161 * 162 * This function encapsulates all three stages of a control transfer. 163 * 164 * @param[in] pipe Pipe used for the transfer. 165 * @param[in] setup_buffer Buffer with the setup packet. 166 * @param[in] setup_buffer_size Size of the setup packet (in bytes). 167 * @param[out] data_buffer Buffer for incoming data. 168 * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes). 169 * @param[out] data_transfered_size Number of bytes that were actually 170 * transfered during the DATA stage. 171 * @return Error code. 172 */ 173 int usb_pipe_control_read(usb_pipe_t *pipe, 174 const void *setup_buffer, size_t setup_buffer_size, 175 void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size) 176 { 177 assert(pipe); 178 179 if ((setup_buffer == NULL) || (setup_buffer_size != 8)) { 180 return EINVAL; 181 } 182 183 if ((data_buffer == NULL) || (data_buffer_size == 0)) { 184 return EINVAL; 185 } 186 187 if ((pipe->direction != USB_DIRECTION_BOTH) 188 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { 189 return EBADF; 190 } 191 192 uint64_t setup_packet; 193 memcpy(&setup_packet, setup_buffer, 8); 194 195 size_t act_size = 0; 196 const int rc = usb_pipe_read_no_check(pipe, setup_packet, 197 data_buffer, data_buffer_size, &act_size); 198 199 if (rc == ESTALL) { 200 clear_self_endpoint_halt(pipe); 201 } 202 203 if (rc == EOK && data_transfered_size != NULL) { 204 *data_transfered_size = act_size; 205 } 206 207 return rc; 208 } 209 /*----------------------------------------------------------------------------*/ 210 /** Request a control write transfer on an endpoint pipe. 211 * 212 * This function encapsulates all three stages of a control transfer. 213 * 214 * @param[in] pipe Pipe used for the transfer. 215 * @param[in] setup_buffer Buffer with the setup packet. 216 * @param[in] setup_buffer_size Size of the setup packet (in bytes). 217 * @param[in] data_buffer Buffer with data to be sent. 218 * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes). 219 * @return Error code. 220 */ 221 int usb_pipe_control_write(usb_pipe_t *pipe, 222 const void *setup_buffer, size_t setup_buffer_size, 223 const void *data_buffer, size_t data_buffer_size) 224 { 225 assert(pipe); 226 227 if ((setup_buffer == NULL) || (setup_buffer_size != 8)) { 228 return EINVAL; 229 } 230 231 if ((data_buffer == NULL) && (data_buffer_size > 0)) { 232 return EINVAL; 233 } 234 235 if ((data_buffer != NULL) && (data_buffer_size == 0)) { 236 return EINVAL; 237 } 238 239 if ((pipe->direction != USB_DIRECTION_BOTH) 240 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { 241 return EBADF; 242 } 243 244 uint64_t setup_packet; 245 memcpy(&setup_packet, setup_buffer, 8); 246 247 const int rc = usb_pipe_write_no_check(pipe, setup_packet, 248 data_buffer, data_buffer_size); 249 250 if (rc == ESTALL) { 251 clear_self_endpoint_halt(pipe); 252 } 253 254 return rc; 255 } 256 /*----------------------------------------------------------------------------*/ 257 /** Request a read (in) transfer on an endpoint pipe. 258 * 259 * @param[in] pipe Pipe used for the transfer. 260 * @param[out] buffer Buffer where to store the data. 261 * @param[in] size Size of the buffer (in bytes). 262 * @param[out] size_transfered Number of bytes that were actually transfered. 263 * @return Error code. 264 */ 265 int usb_pipe_read(usb_pipe_t *pipe, 266 void *buffer, size_t size, size_t *size_transfered) 267 { 268 assert(pipe); 269 270 if (buffer == NULL) { 271 return EINVAL; 272 } 273 274 if (size == 0) { 275 return EINVAL; 276 } 277 278 if (pipe->direction != USB_DIRECTION_IN) { 279 return EBADF; 280 } 281 282 if (pipe->transfer_type == USB_TRANSFER_CONTROL) { 283 return EBADF; 284 } 285 286 size_t act_size = 0; 287 const int rc = usb_pipe_read_no_check(pipe, 0, buffer, size, &act_size); 288 289 290 if (rc == EOK && size_transfered != NULL) { 291 *size_transfered = act_size; 292 } 293 294 return rc; 295 } 296 /*----------------------------------------------------------------------------*/ 297 /** Request a write (out) transfer on an endpoint pipe. 298 * 299 * @param[in] pipe Pipe used for the transfer. 300 * @param[in] buffer Buffer with data to transfer. 301 * @param[in] size Size of the buffer (in bytes). 302 * @return Error code. 303 */ 304 int usb_pipe_write(usb_pipe_t *pipe, const void *buffer, size_t size) 305 { 306 assert(pipe); 307 308 if (buffer == NULL || size == 0) { 309 return EINVAL; 310 } 311 312 if (pipe->direction != USB_DIRECTION_OUT) { 313 return EBADF; 314 } 315 316 if (pipe->transfer_type == USB_TRANSFER_CONTROL) { 317 return EBADF; 318 } 319 320 return usb_pipe_write_no_check(pipe, 0, buffer, size); 321 } 224 322 /** 225 323 * @} -
uspace/lib/usbdev/src/pipesinit.c
r9c3bba0 r899f1a9 349 349 fibril_mutex_initialize(&pipe->guard); 350 350 pipe->wire = connection; 351 pipe->hc_sess = NULL;352 fibril_mutex_initialize(&pipe->hc_sess_mutex);353 351 pipe->endpoint_no = endpoint_no; 354 352 pipe->transfer_type = transfer_type; 355 353 pipe->max_packet_size = max_packet_size; 356 354 pipe->direction = direction; 357 pipe->refcount = 0;358 pipe->refcount_soft = 0;359 355 pipe->auto_reset_halt = false; 360 356 … … 375 371 assert(connection); 376 372 377 int rc = usb_pipe_initialize(pipe, connection, 378 0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE, 379 USB_DIRECTION_BOTH); 373 int rc = usb_pipe_initialize(pipe, connection, 0, USB_TRANSFER_CONTROL, 374 CTRL_PIPE_MIN_PACKET_SIZE, USB_DIRECTION_BOTH); 380 375 381 376 pipe->auto_reset_halt = true; … … 442 437 * @return Error code. 443 438 */ 444 int usb_pipe_register(usb_pipe_t *pipe, unsigned interval, 445 usb_hc_connection_t *hc_connection) 439 int usb_pipe_register(usb_pipe_t *pipe, unsigned interval) 446 440 { 447 441 assert(pipe); 448 442 assert(pipe->wire); 449 assert(hc_connection); 450 451 if (!usb_hc_connection_is_opened(hc_connection)) 452 return EBADF; 453 async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess); 454 if (!exch) 455 return ENOMEM; 456 const int ret = usbhc_register_endpoint(exch, 457 pipe->wire->address, pipe->endpoint_no, pipe->transfer_type, 458 pipe->direction, pipe->max_packet_size, interval); 459 460 async_exchange_end(exch); 461 return ret; 443 assert(pipe->wire->hc_connection); 444 445 return usb_hc_register_endpoint(pipe->wire->hc_connection, 446 pipe->wire->address, pipe->endpoint_no, pipe->transfer_type, 447 pipe->direction, pipe->max_packet_size, interval); 462 448 } 463 449 … … 468 454 * @return Error code. 469 455 */ 470 int usb_pipe_unregister(usb_pipe_t *pipe, 471 usb_hc_connection_t *hc_connection) 456 int usb_pipe_unregister(usb_pipe_t *pipe) 472 457 { 473 458 assert(pipe); 474 459 assert(pipe->wire); 475 assert(hc_connection); 476 477 if (!usb_hc_connection_is_opened(hc_connection)) 478 return EBADF; 479 480 async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess); 481 if (!exch) 482 return ENOMEM; 483 const int ret = usbhc_unregister_endpoint(exch, 460 assert(pipe->wire->hc_connection); 461 462 return usb_hc_unregister_endpoint(pipe->wire->hc_connection, 484 463 pipe->wire->address, pipe->endpoint_no, pipe->direction); 485 async_exchange_end(exch);486 487 return ret;488 464 } 489 465 -
uspace/lib/usbdev/src/recognise.c
r9c3bba0 r899f1a9 45 45 #include <errno.h> 46 46 #include <assert.h> 47 48 /** Index to append after device name for uniqueness. */49 static size_t device_name_index = 0;50 /** Mutex guard for device_name_index. */51 static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex);52 47 53 48 /** DDF operations of child devices. */ … … 329 324 } 330 325 331 fibril_mutex_lock(&device_name_index_mutex); 332 const size_t this_device_name_index = device_name_index++; 333 fibril_mutex_unlock(&device_name_index_mutex); 326 327 /** Index to append after device name for uniqueness. */ 328 static atomic_t device_name_index = {0}; 329 const size_t this_device_name_index = 330 (size_t) atomic_preinc(&device_name_index); 334 331 335 332 ddf_fun_t *child = NULL; -
uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h
r9c3bba0 r899f1a9 106 106 void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance); 107 107 108 void usb_transfer_batch_finish (const usb_transfer_batch_t *instance,109 const void* data, size_t size );108 void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance, 109 const void* data, size_t size, int error); 110 110 /*----------------------------------------------------------------------------*/ 111 /** Override error value and finishes transfer.111 /** Finish batch using stored error value. 112 112 * 113 113 * @param[in] instance Batch structure to use. 114 114 * @param[in] data Data to copy to the output buffer. 115 115 * @param[in] size Size of @p data. 116 * @param[in] error Set batch status to this error value.117 116 */ 118 static inline void usb_transfer_batch_finish _error(119 usb_transfer_batch_t *instance, const void* data, size_t size, int error)117 static inline void usb_transfer_batch_finish( 118 const usb_transfer_batch_t *instance, const void* data) 120 119 { 121 120 assert(instance); 122 instance->error = error;123 usb_transfer_batch_finish(instance, data, size);121 usb_transfer_batch_finish_error( 122 instance, data, instance->transfered_size, instance->error); 124 123 } 125 124 /*----------------------------------------------------------------------------*/ -
uspace/lib/usbhost/src/usb_transfer_batch.c
r9c3bba0 r899f1a9 33 33 */ 34 34 #include <errno.h> 35 #include < str_error.h>35 #include <macros.h> 36 36 37 37 #include <usb/usb.h> … … 121 121 * @param[in] data Data to copy to the output buffer. 122 122 * @param[in] size Size of @p data. 123 * @param[in] error Error value to use. 123 124 */ 124 void usb_transfer_batch_finish (125 const usb_transfer_batch_t *instance, const void *data, size_t size)125 void usb_transfer_batch_finish_error(const usb_transfer_batch_t *instance, 126 const void *data, size_t size, int error) 126 127 { 127 128 assert(instance); … … 133 134 /* Check for commands that reset toggle bit */ 134 135 if (instance->ep->transfer_type == USB_TRANSFER_CONTROL 135 && instance->error == EOK) {136 && error == EOK) { 136 137 const usb_target_t target = 137 138 {{ instance->ep->address, instance->ep->endpoint }}; … … 139 140 instance->setup_buffer); 140 141 } 141 instance->callback_out(instance->fun, 142 instance->error, instance->arg); 142 instance->callback_out(instance->fun, error, instance->arg); 143 143 } 144 144 145 145 if (instance->callback_in) { 146 146 /* We care about the data and there are some to copy */ 147 const size_t safe_size = min(size, instance->buffer_size); 147 148 if (data) { 148 const size_t min_size = size < instance->buffer_size 149 ? size : instance->buffer_size; 150 memcpy(instance->buffer, data, min_size); 149 memcpy(instance->buffer, data, safe_size); 151 150 } 152 instance->callback_in(instance->fun, instance->error,153 instance->transfered_size, instance->arg);151 instance->callback_in(instance->fun, error, 152 safe_size, instance->arg); 154 153 } 155 154 }
Note:
See TracChangeset
for help on using the changeset viewer.