Changes in / [153cc76a:2f0dd2a] in mainline
- Location:
- uspace
- Files:
-
- 4 added
- 3 deleted
- 52 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/mkbd/main.c
r153cc76a r2f0dd2a 48 48 #include <usb/dev/pipes.h> 49 49 #include <async.h> 50 #include <usb/dev.h>51 50 #include <usb/hid/usages/core.h> 52 51 #include <usb/hid/hidparser.h> -
uspace/app/usbinfo/dev.c
r153cc76a r2f0dd2a 34 34 * Representation of queried device. 35 35 */ 36 #include <usb/dev.h> 37 #include <usb/hc.h> 36 #include <usb/dev/pipes.h> 38 37 #include <errno.h> 39 38 #include <str_error.h> … … 53 52 bool transfer_started = false; 54 53 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); 54 rc = usb_device_connection_initialize(&dev->wire, hc_handle, dev_addr); 59 55 if (rc != EOK) { 60 56 fprintf(stderr, -
uspace/app/usbinfo/info.c
r153cc76a r2f0dd2a 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 304 289 /* Get supported languages. */ 305 290 l18_win_locales_t *langs; … … 320 305 } 321 306 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); 322 318 323 319 /* Get all strings and dump them. */ -
uspace/app/usbinfo/main.c
r153cc76a r2f0dd2a 44 44 #include <loc.h> 45 45 #include <usb/hc.h> 46 #include <usb/dev.h>47 46 #include <usb/dev/pipes.h> 48 47 #include "usbinfo.h" -
uspace/app/usbinfo/usbinfo.h
r153cc76a r2f0dd2a 44 44 45 45 typedef struct { 46 usb_ hc_connection_t hc_conn;46 usb_pipe_t ctrl_pipe; 47 47 usb_device_connection_t wire; 48 usb_pipe_t ctrl_pipe;49 48 usb_standard_device_descriptor_t device_descriptor; 50 49 uint8_t *full_configuration_descriptor; -
uspace/drv/bus/usb/ohci/hc.c
r153cc76a r2f0dd2a 137 137 return ret; 138 138 } 139 usb_device_manager_bind_address(&instance->generic.dev_manager, 140 instance->rh.address, hub_fun->handle); 139 141 140 142 #define CHECK_RET_UNREG_RETURN(ret, message...) \ … … 148 150 return ret; \ 149 151 } else (void)0 150 151 152 ret = usb_endpoint_manager_add_ep( 152 153 &instance->generic.ep_manager, instance->rh.address, 0, … … 164 165 CHECK_RET_UNREG_RETURN(ret, 165 166 "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));172 167 173 168 return EOK; -
uspace/drv/bus/usb/ohci/ohci.c
r153cc76a r2f0dd2a 140 140 int device_setup_ohci(ddf_dev_t *device) 141 141 { 142 if (device == NULL) 143 return EBADMEM; 144 145 ohci_t *instance = ddf_dev_data_alloc(device,sizeof(ohci_t)); 142 assert(device); 143 144 ohci_t *instance = malloc(sizeof(ohci_t)); 146 145 if (instance == NULL) { 147 146 usb_log_error("Failed to allocate OHCI driver.\n"); 148 147 return ENOMEM; 149 148 } 149 instance->rh_fun = NULL; 150 instance->hc_fun = NULL; 150 151 151 152 #define CHECK_RET_DEST_FREE_RETURN(ret, message...) \ 152 153 if (ret != EOK) { \ 153 154 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; \159 158 ddf_fun_destroy(instance->rh_fun); \ 160 159 } \ 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 221 223 #define CHECK_RET_FINI_RETURN(ret, message...) \ 222 224 if (ret != EOK) { \ -
uspace/drv/bus/usb/ohci/ohci_batch.c
r153cc76a r2f0dd2a 34 34 #include <errno.h> 35 35 #include <str_error.h> 36 #include <macros.h>37 36 38 37 #include <usb/usb.h> … … 54 53 return; 55 54 if (ohci_batch->tds) { 56 const ohci_endpoint_t *ohci_ep =57 ohci_endpoint_get(ohci_batch->usb_batch->ep);58 assert(ohci_ep);59 55 for (unsigned i = 0; i < ohci_batch->td_count; ++i) { 60 if ( ohci_batch->tds[i] != ohci_ep->td)56 if (i != ohci_batch->leave_td) 61 57 free32(ohci_batch->tds[i]); 62 58 } … … 68 64 } 69 65 /*----------------------------------------------------------------------------*/ 70 /** Finishes usb_transfer_batch and destroys the structure.71 *72 * @param[in] uhci_batch Instance to finish and destroy.73 */74 66 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *ohci_batch) 75 67 { … … 77 69 assert(ohci_batch->usb_batch); 78 70 usb_transfer_batch_finish(ohci_batch->usb_batch, 79 ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size); 71 ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size, 72 ohci_batch->usb_batch->buffer_size); 80 73 ohci_transfer_batch_dispose(ohci_batch); 81 74 } 82 75 /*----------------------------------------------------------------------------*/ 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 */93 76 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *usb_batch) 94 77 { … … 122 105 ohci_batch->ed = ohci_endpoint_get(usb_batch->ep)->ed; 123 106 ohci_batch->tds[0] = ohci_endpoint_get(usb_batch->ep)->td; 107 ohci_batch->leave_td = 0; 124 108 125 109 for (unsigned i = 1; i <= ohci_batch->td_count; ++i) { … … 168 152 * completes with the last TD. 169 153 */ 170 bool ohci_transfer_batch_is_complete( constohci_transfer_batch_t *ohci_batch)154 bool ohci_transfer_batch_is_complete(ohci_transfer_batch_t *ohci_batch) 171 155 { 172 156 assert(ohci_batch); … … 190 174 191 175 /* Assume we will leave the last(unused) TD behind */ 192 unsignedleave_td = ohci_batch->td_count;176 ohci_batch->leave_td = ohci_batch->td_count; 193 177 194 178 /* Check all TDs */ … … 228 212 * It will be the one TD we leave behind. 229 213 */ 230 leave_td = i + 1;214 ohci_batch->leave_td = i + 1; 231 215 232 216 /* Check TD assumption */ 233 const uint32_t pa = 234 addr_to_phys(ohci_batch->tds[leave_td]);235 assert((ohci_batch->ed->td_head & ED_TD HEAD_PTR_MASK)217 const uint32_t pa = addr_to_phys( 218 ohci_batch->tds[ohci_batch->leave_td]); 219 assert((ohci_batch->ed->td_head & ED_TDTAIL_PTR_MASK) 236 220 == pa); 237 221 238 222 ed_set_tail_td(ohci_batch->ed, 239 ohci_batch->tds[ leave_td]);223 ohci_batch->tds[ohci_batch->leave_td]); 240 224 241 225 /* Clear possible ED HALT */ … … 250 234 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->usb_batch->ep); 251 235 assert(ohci_ep); 252 ohci_ep->td = ohci_batch->tds[ leave_td];236 ohci_ep->td = ohci_batch->tds[ohci_batch->leave_td]; 253 237 254 238 /* Make sure that we are leaving the right TD behind */ … … 264 248 * @param[in] ohci_batch Batch structure to use 265 249 */ 266 void ohci_transfer_batch_commit( constohci_transfer_batch_t *ohci_batch)250 void ohci_transfer_batch_commit(ohci_transfer_batch_t *ohci_batch) 267 251 { 268 252 assert(ohci_batch); … … 311 295 while (remain_size > 0) { 312 296 const size_t transfer_size = 313 min(remain_size, OHCI_TD_MAX_TRANSFER); 297 remain_size > OHCI_TD_MAX_TRANSFER ? 298 OHCI_TD_MAX_TRANSFER : remain_size; 314 299 toggle = 1 - toggle; 315 300 … … 393 378 } 394 379 /*----------------------------------------------------------------------------*/ 395 /** Transfer setup table. */396 380 static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t) = 397 381 { -
uspace/drv/bus/usb/ohci/ohci_batch.h
r153cc76a r2f0dd2a 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; 55 57 /** Data buffer, must be accessible by the OHCI hw. */ 56 58 char *device_buffer; … … 60 62 61 63 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *batch); 62 bool ohci_transfer_batch_is_complete( constohci_transfer_batch_t *batch);63 void ohci_transfer_batch_commit( constohci_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); 64 66 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *batch); 65 67 /*----------------------------------------------------------------------------*/ -
uspace/drv/bus/usb/ohci/pci.c
r153cc76a r2f0dd2a 42 42 #include <ddi.h> 43 43 #include <libarch/ddi.h> 44 #include <device/hw_res _parsed.h>44 #include <device/hw_res.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); 63 66 64 67 async_sess_t *parent_sess = … … 68 71 return ENOMEM; 69 72 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); 73 hw_resource_list_t hw_resources; 74 int rc = hw_res_get_resource_list(parent_sess, &hw_resources); 73 75 async_hangup(parent_sess); 74 if (r et!= EOK) {75 return r et;76 if (rc != EOK) { 77 return rc; 76 78 } 77 79 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; 80 uintptr_t mem_address = 0; 81 size_t mem_size = 0; 82 bool mem_found = false; 83 84 int irq = 0; 85 bool irq_found = false; 86 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 } 82 107 } 108 free(hw_resources.resources); 83 109 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]; 90 91 hw_res_list_parsed_clean(&hw_res); 92 return EOK; 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; 93 117 } 94 118 -
uspace/drv/bus/usb/ohci/root_hub.c
r153cc76a r2f0dd2a 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 voidget_status(const rh_t *instance, usb_transfer_batch_t *request);112 static voidget_descriptor(const rh_t *instance, usb_transfer_batch_t *request);113 static voidset_feature(const rh_t *instance, usb_transfer_batch_t *request);114 static voidclear_feature(const rh_t *instance, usb_transfer_batch_t *request);111 static int get_status(const rh_t *instance, usb_transfer_batch_t *request); 112 static int get_descriptor(const rh_t *instance, usb_transfer_batch_t *request); 113 static int set_feature(const rh_t *instance, usb_transfer_batch_t *request); 114 static int 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 voidcontrol_request(rh_t *instance, usb_transfer_batch_t *request);119 static int 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; 124 126 usb_transfer_batch_finish_error(request, &mask, size, EOK); 125 usb_transfer_batch_destroy(request); 126 } 127 128 #define TRANSFER_END_DATA(request, data, bytes) \ 127 } 128 129 #define TRANSFER_OK(bytes) \ 129 130 do { \ 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; \ 131 request->transfered_size = bytes; \ 132 return EOK; \ 140 133 } while (0) 141 134 … … 219 212 case USB_TRANSFER_CONTROL: 220 213 usb_log_debug("Root hub got CONTROL packet\n"); 221 control_request(instance, request); 214 const int ret = control_request(instance, request); 215 usb_transfer_batch_finish_error(request, NULL, 0, ret); 222 216 break; 223 224 217 case USB_TRANSFER_INTERRUPT: 225 218 usb_log_debug("Root hub got INTERRUPT packet\n"); … … 228 221 const uint16_t mask = create_interrupt_mask(instance); 229 222 if (mask == 0) { 230 usb_log_debug("No changes.. .\n");223 usb_log_debug("No changes..\n"); 231 224 instance->unfinished_interrupt_transfer = request; 232 } else { 233 usb_log_debug("Processing changes...\n"); 234 interrupt_request( 235 request, mask, instance->interrupt_mask_size); 225 fibril_mutex_unlock(&instance->guard); 226 return; 236 227 } 228 usb_log_debug("Processing changes...\n"); 229 interrupt_request(request, mask, instance->interrupt_mask_size); 237 230 fibril_mutex_unlock(&instance->guard); 238 231 break; … … 240 233 default: 241 234 usb_log_error("Root hub got unsupported request.\n"); 242 TRANSFER_END(request, ENOTSUP); 243 } 235 usb_transfer_batch_finish_error(request, NULL, 0, EINVAL); 236 } 237 usb_transfer_batch_destroy(request); 244 238 } 245 239 /*----------------------------------------------------------------------------*/ … … 260 254 interrupt_request(instance->unfinished_interrupt_transfer, 261 255 mask, instance->interrupt_mask_size); 256 usb_transfer_batch_destroy( 257 instance->unfinished_interrupt_transfer); 262 258 instance->unfinished_interrupt_transfer = NULL; 263 259 } … … 388 384 * @return error code 389 385 */ 390 voidget_status(const rh_t *instance, usb_transfer_batch_t *request)386 int get_status(const rh_t *instance, usb_transfer_batch_t *request) 391 387 { 392 388 assert(instance); 393 389 assert(request); 394 395 390 396 391 const usb_device_request_setup_packet_t *request_packet = 397 392 (usb_device_request_setup_packet_t*)request->setup_buffer; 398 393 399 switch (request_packet->request_type) 400 { 401 case USB_HUB_REQ_TYPE_GET_HUB_STATUS: 394 if (request->buffer_size < 4) { 395 usb_log_error("Buffer too small for get status request.\n"); 396 return EOVERFLOW; 397 } 398 402 399 /* Hub status: just filter relevant info from rh_status reg */ 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 } 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 } 413 406 414 407 /* Copy appropriate rh_port_status register, OHCI designers were 415 408 * kind enough to make those bit values match USB specification */ 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 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; 466 421 } 467 422 /*----------------------------------------------------------------------------*/ … … 475 430 * @return Error code 476 431 */ 477 voidget_descriptor(const rh_t *instance, usb_transfer_batch_t *request)432 int get_descriptor(const rh_t *instance, usb_transfer_batch_t *request) 478 433 { 479 434 assert(instance); … … 482 437 const usb_device_request_setup_packet_t *setup_request = 483 438 (usb_device_request_setup_packet_t *) request->setup_buffer; 439 size_t size; 440 const void *descriptor = NULL; 484 441 const uint16_t setup_request_value = setup_request->value_high; 442 //(setup_request->value_low << 8); 485 443 switch (setup_request_value) 486 444 { 487 445 case USB_DESCTYPE_HUB: 488 446 usb_log_debug2("USB_DESCTYPE_HUB\n"); 489 /* Hub descriptor was generated locally .490 * Class specific request. */491 TRANSFER_END_DATA(request, instance->descriptors.hub,492 instance->hub_descriptor_size);447 /* Hub descriptor was generated locally */ 448 descriptor = instance->descriptors.hub; 449 size = instance->hub_descriptor_size; 450 break; 493 451 494 452 case USB_DESCTYPE_DEVICE: 495 453 usb_log_debug2("USB_DESCTYPE_DEVICE\n"); 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)); 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; 501 458 502 459 case USB_DESCTYPE_CONFIGURATION: 503 460 usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n"); 504 461 /* Start with configuration and add others depending on 505 * request size. Standard USB request. */ 506 TRANSFER_END_DATA(request, &instance->descriptors, 507 instance->descriptors.configuration.total_length); 462 * request size */ 463 descriptor = &instance->descriptors; 464 size = instance->descriptors.configuration.total_length; 465 break; 508 466 509 467 case USB_DESCTYPE_INTERFACE: 510 468 usb_log_debug2("USB_DESCTYPE_INTERFACE\n"); 511 469 /* Use local interface descriptor. There is one and it 512 * might be modified . Hub driver should not ask or this513 * descriptor as it is not part of standard requests set. */514 TRANSFER_END_DATA(request, &instance->descriptors.interface,515 sizeof(instance->descriptors.interface));470 * might be modified */ 471 descriptor = &instance->descriptors.interface; 472 size = sizeof(instance->descriptors.interface); 473 break; 516 474 517 475 case USB_DESCTYPE_ENDPOINT: 518 476 /* Use local endpoint descriptor. There is one 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. */ 477 * it might have max_packet_size field modified*/ 522 478 usb_log_debug2("USB_DESCTYPE_ENDPOINT\n"); 523 TRANSFER_END_DATA(request, &instance->descriptors.endpoint, 524 sizeof(instance->descriptors.endpoint)); 479 descriptor = &instance->descriptors.endpoint; 480 size = sizeof(instance->descriptors.endpoint); 481 break; 525 482 526 483 default: … … 532 489 setup_request_value, setup_request->index, 533 490 setup_request->length); 534 TRANSFER_END(request, EINVAL); 535 } 536 537 TRANSFER_END(request, ENOTSUP); 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); 538 499 } 539 500 /*----------------------------------------------------------------------------*/ … … 643 604 * @return error code 644 605 */ 645 voidset_feature(const rh_t *instance, usb_transfer_batch_t *request)606 int set_feature(const rh_t *instance, usb_transfer_batch_t *request) 646 607 { 647 608 assert(instance); … … 654 615 case USB_HUB_REQ_TYPE_SET_PORT_FEATURE: 655 616 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 656 const int ret =set_feature_port(instance,617 return set_feature_port(instance, 657 618 setup_request->value, setup_request->index); 658 TRANSFER_END(request, ret);659 619 660 620 case USB_HUB_REQ_TYPE_SET_HUB_FEATURE: … … 663 623 * features. It makes no sense to SET either. */ 664 624 usb_log_error("Invalid HUB set feature request.\n"); 665 TRANSFER_END(request, ENOTSUP); 666 //TODO: Consider standard USB requests: REMOTE WAKEUP, ENDPOINT STALL 625 return ENOTSUP; 667 626 default: 668 627 usb_log_error("Invalid set feature request type: %d\n", 669 628 setup_request->request_type); 670 TRANSFER_END(request, ENOTSUP);629 return EINVAL; 671 630 } 672 631 } … … 681 640 * @return error code 682 641 */ 683 voidclear_feature(const rh_t *instance, usb_transfer_batch_t *request)642 int clear_feature(const rh_t *instance, usb_transfer_batch_t *request) 684 643 { 685 644 assert(instance); … … 688 647 const usb_device_request_setup_packet_t *setup_request = 689 648 (usb_device_request_setup_packet_t *) request->setup_buffer; 649 650 request->transfered_size = 0; 690 651 691 652 switch (setup_request->request_type) … … 693 654 case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE: 694 655 usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n"); 695 const int ret =clear_feature_port(instance,656 return clear_feature_port(instance, 696 657 setup_request->value, setup_request->index); 697 TRANSFER_END(request, ret);698 658 699 659 case USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE: … … 708 668 if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) { 709 669 instance->registers->rh_status = RHS_OCIC_FLAG; 710 TRANSFER_ END(request, EOK);670 TRANSFER_OK(0); 711 671 } 712 //TODO: Consider standard USB requests: REMOTE WAKEUP, ENDPOINT STALL713 672 default: 714 673 usb_log_error("Invalid clear feature request type: %d\n", 715 674 setup_request->request_type); 716 TRANSFER_END(request, ENOTSUP);675 return EINVAL; 717 676 } 718 677 } … … 736 695 * @return error code 737 696 */ 738 voidcontrol_request(rh_t *instance, usb_transfer_batch_t *request)697 int control_request(rh_t *instance, usb_transfer_batch_t *request) 739 698 { 740 699 assert(instance); … … 743 702 if (!request->setup_buffer) { 744 703 usb_log_error("Root hub received empty transaction!"); 745 TRANSFER_END(request, EBADMEM);704 return EINVAL; 746 705 } 747 706 748 707 if (sizeof(usb_device_request_setup_packet_t) > request->setup_size) { 749 708 usb_log_error("Setup packet too small\n"); 750 TRANSFER_END(request, EOVERFLOW);709 return EOVERFLOW; 751 710 } 752 711 … … 759 718 case USB_DEVREQ_GET_STATUS: 760 719 usb_log_debug("USB_DEVREQ_GET_STATUS\n"); 761 get_status(instance, request); 762 break; 720 return get_status(instance, request); 763 721 764 722 case USB_DEVREQ_GET_DESCRIPTOR: 765 723 usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n"); 766 get_descriptor(instance, request); 767 break; 724 return get_descriptor(instance, request); 768 725 769 726 case USB_DEVREQ_GET_CONFIGURATION: 770 727 usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n"); 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));728 if (request->buffer_size != 1) 729 return EINVAL; 730 request->buffer[0] = 1; 731 TRANSFER_OK(1); 775 732 776 733 case USB_DEVREQ_CLEAR_FEATURE: 777 usb_log_debug2(" USB_DEVREQ_CLEAR_FEATURE\n");778 clear_feature(instance, request);779 break;734 usb_log_debug2("Processing request without " 735 "additional data\n"); 736 return clear_feature(instance, request); 780 737 781 738 case USB_DEVREQ_SET_FEATURE: 782 usb_log_debug2(" USB_DEVREQ_SET_FEATURE\n");783 set_feature(instance, request);784 break;739 usb_log_debug2("Processing request without " 740 "additional data\n"); 741 return set_feature(instance, request); 785 742 786 743 case USB_DEVREQ_SET_ADDRESS: 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 744 usb_log_debug("USB_DEVREQ_SET_ADDRESS\n"); 792 745 instance->address = setup_request->value; 793 TRANSFER_ END(request, EOK);746 TRANSFER_OK(0); 794 747 795 748 case USB_DEVREQ_SET_CONFIGURATION: 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: 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 */ 808 754 default: 809 /* Hub class GET_STATE(2) falls in here too. */810 755 usb_log_error("Received unsupported request: %d.\n", 811 756 setup_request->request); 812 TRANSFER_END(request, ENOTSUP); 813 } 814 } 757 return ENOTSUP; 758 } 759 } 760 815 761 /** 816 762 * @} -
uspace/drv/bus/usb/uhci/hc.c
r153cc76a r2f0dd2a 130 130 uhci_transfer_batch_t *batch = 131 131 uhci_transfer_batch_from_link(item); 132 uhci_transfer_batch_ finish_dispose(batch);132 uhci_transfer_batch_call_dispose(batch); 133 133 } 134 134 } -
uspace/drv/bus/usb/uhci/pci.c
r153cc76a r2f0dd2a 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 28 29 /** 29 30 * @addtogroup drvusbuhcihc … … 38 39 #include <assert.h> 39 40 #include <devman.h> 40 #include <device/hw_res _parsed.h>41 #include <device/hw_res.h> 41 42 42 43 #include <usb/debug.h> … … 67 68 return ENOMEM; 68 69 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); 70 hw_resource_list_t hw_resources; 71 const int rc = hw_res_get_resource_list(parent_sess, &hw_resources); 72 72 async_hangup(parent_sess); 73 if (r et!= EOK) {74 return r et;73 if (rc != EOK) { 74 return rc; 75 75 } 76 76 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; 77 uintptr_t io_address = 0; 78 size_t io_size = 0; 79 bool io_found = false; 80 81 int irq = 0; 82 bool irq_found = false; 83 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 } 81 102 } 103 free(hw_resources.resources); 82 104 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]; 105 if (!io_found || !irq_found) 106 return ENOENT; 89 107 90 hw_res_list_parsed_clean(&hw_res); 108 *io_reg_address = io_address; 109 *io_reg_size = io_size; 110 *irq_no = irq; 111 91 112 return EOK; 92 113 } -
uspace/drv/bus/usb/uhci/transfer_list.c
r153cc76a r2f0dd2a 184 184 uhci_transfer_batch_from_link(current); 185 185 transfer_list_remove_batch(instance, batch); 186 uhci_transfer_batch_abort(batch); 186 batch->usb_batch->error = EINTR; 187 uhci_transfer_batch_call_dispose(batch); 187 188 } 188 189 fibril_mutex_unlock(&instance->guard); -
uspace/drv/bus/usb/uhci/uhci.c
r153cc76a r2f0dd2a 148 148 int device_setup_uhci(ddf_dev_t *device) 149 149 { 150 if (!device) 151 return EBADMEM; 152 153 uhci_t *instance = ddf_dev_data_alloc(device, sizeof(uhci_t)); 150 assert(device); 151 uhci_t *instance = malloc(sizeof(uhci_t)); 154 152 if (instance == NULL) { 155 153 usb_log_error("Failed to allocate OHCI driver.\n"); … … 160 158 if (ret != EOK) { \ 161 159 if (instance->hc_fun) \ 160 instance->hc_fun->ops = NULL; \ 162 161 instance->hc_fun->driver_data = NULL; \ 163 162 ddf_fun_destroy(instance->hc_fun); \ 164 163 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; \ 168 169 usb_log_error(message); \ 169 170 return ret; \ … … 226 227 "Failed to init uhci_hcd: %s.\n", str_error(ret)); 227 228 229 device->driver_data = instance; 230 228 231 #define CHECK_RET_FINI_RETURN(ret, message...) \ 229 232 if (ret != EOK) { \ -
uspace/drv/bus/usb/uhci/uhci_batch.c
r153cc76a r2f0dd2a 34 34 #include <errno.h> 35 35 #include <str_error.h> 36 #include <macros.h>37 36 38 37 #include <usb/usb.h> … … 46 45 #define DEFAULT_ERROR_COUNT 3 47 46 48 /** Safely destructs uhci_transfer_batch_t structure.49 *50 * @param[in] uhci_batch Instance to destroy.51 */52 47 static void uhci_transfer_batch_dispose(uhci_transfer_batch_t *uhci_batch) 53 48 { … … 59 54 } 60 55 /*----------------------------------------------------------------------------*/ 61 /** Finishes usb_transfer_batch and destroys the structure.62 * 63 * @param[in] uhci_batch Instance to finish anddestroy.64 */ 65 void uhci_transfer_batch_ finish_dispose(uhci_transfer_batch_t *uhci_batch)56 /** Safely destructs uhci_transfer_batch_t structure 57 * 58 * @param[in] uhci_batch Instance to destroy. 59 */ 60 void uhci_transfer_batch_call_dispose(uhci_transfer_batch_t *uhci_batch) 66 61 { 67 62 assert(uhci_batch); 68 63 assert(uhci_batch->usb_batch); 69 64 usb_transfer_batch_finish(uhci_batch->usb_batch, 70 uhci_transfer_batch_data_buffer(uhci_batch)); 65 uhci_transfer_batch_data_buffer(uhci_batch), 66 uhci_batch->usb_batch->buffer_size); 71 67 uhci_transfer_batch_dispose(uhci_batch); 72 68 } 73 69 /*----------------------------------------------------------------------------*/ 74 /** Transfer batch setup table. */75 70 static void (*const batch_setup[])(uhci_transfer_batch_t*, usb_direction_t); 76 71 /*----------------------------------------------------------------------------*/ 77 72 /** Allocate memory and initialize internal data structure. 78 73 * 79 * @param[in] usb_batch Pointer to generic USB batch structure. 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 80 83 * @return Valid pointer if all structures were successfully created, 81 84 * NULL otherwise. … … 153 156 * is reached. 154 157 */ 155 bool uhci_transfer_batch_is_complete( constuhci_transfer_batch_t *uhci_batch)158 bool uhci_transfer_batch_is_complete(uhci_transfer_batch_t *uhci_batch) 156 159 { 157 160 assert(uhci_batch); … … 197 200 } 198 201 /*----------------------------------------------------------------------------*/ 199 /** Direction to pid conversion table */200 202 static const usb_packet_id direction_pids[] = { 201 203 [USB_DIRECTION_IN] = USB_PID_IN, … … 235 237 236 238 while (remain_size > 0) { 237 const size_t packet_size = min(remain_size, mps); 239 const size_t packet_size = 240 (remain_size < mps) ? remain_size : mps; 238 241 239 242 const td_t *next_td = (td + 1 < uhci_batch->td_count) … … 306 309 307 310 while (remain_size > 0) { 308 const size_t packet_size = min(remain_size, mps); 311 const size_t packet_size = 312 (remain_size < mps) ? remain_size : mps; 309 313 310 314 td_init( -
uspace/drv/bus/usb/uhci/uhci_batch.h
r153cc76a r2f0dd2a 61 61 62 62 uhci_transfer_batch_t * uhci_transfer_batch_get(usb_transfer_batch_t *batch); 63 void uhci_transfer_batch_ finish_dispose(uhci_transfer_batch_t *uhci_batch);64 bool uhci_transfer_batch_is_complete( constuhci_transfer_batch_t *uhci_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); 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 */70 66 static inline void * uhci_transfer_batch_setup_buffer( 71 67 const uhci_transfer_batch_t *uhci_batch) … … 77 73 } 78 74 /*----------------------------------------------------------------------------*/ 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 */83 75 static inline void * uhci_transfer_batch_data_buffer( 84 76 const uhci_transfer_batch_t *uhci_batch) … … 90 82 } 91 83 /*----------------------------------------------------------------------------*/ 92 /** Aborts the batch.93 * Sets error to EINTR and size off transferd data to 0, before finishing the94 * 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 */110 84 static inline uhci_transfer_batch_t *uhci_transfer_batch_from_link(link_t *l) 111 85 { -
uspace/drv/bus/usb/uhcirh/main.c
r153cc76a r2f0dd2a 36 36 #include <ddf/driver.h> 37 37 #include <devman.h> 38 #include <device/hw_res _parsed.h>38 #include <device/hw_res.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_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); 144 145 hw_resource_list_t hw_resources; 146 const int ret = hw_res_get_resource_list(parent_sess, &hw_resources); 149 147 if (ret != EOK) { 148 async_hangup(parent_sess); 150 149 return ret; 151 150 } 152 153 if (hw_res.io_ranges.count != 1) { 154 hw_res_list_parsed_clean(&hw_res); 155 return EINVAL; 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 156 165 } 157 166 async_hangup(parent_sess); 167 168 if (!io_found) 169 return ENOENT; 170 158 171 if (io_reg_address != NULL) 159 *io_reg_address = hw_res.io_ranges.ranges[0].address;160 172 *io_reg_address = io_address; 173 161 174 if (io_reg_size != NULL) 162 *io_reg_size = hw_res.io_ranges.ranges[0].size; 163 164 hw_res_list_parsed_clean(&hw_res); 175 *io_reg_size = io_size; 176 165 177 return EOK; 166 178 } -
uspace/drv/bus/usb/uhcirh/port.c
r153cc76a r2f0dd2a 260 260 { 261 261 assert(port); 262 assert(usb_hc_connection_is_opened(&port->hc_connection)); 262 263 263 264 usb_log_debug("%s: Detected new device.\n", port->id_string); … … 313 314 314 315 /* Driver stopped, free used address */ 315 ret = usb_h ub_unregister_device(&port->hc_connection,316 &port->attached_device);316 ret = usb_hc_unregister_device(&port->hc_connection, 317 port->attached_device.address); 317 318 if (ret != EOK) { 318 319 usb_log_error("%s: Failed to unregister address of removed " -
uspace/drv/bus/usb/usbhub/port.c
r153cc76a r2f0dd2a 288 288 port->attached_device.fun = NULL; 289 289 290 ret = usb_hub_unregister_device(&hub->usb_device->hc_conn, 291 &port->attached_device); 292 if (ret != EOK) { 293 usb_log_warning("Failed to unregister address of the " 294 "removed device: %s.\n", str_error(ret)); 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)); 295 307 } 296 308 … … 426 438 427 439 const int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev, 428 &data->hub-> usb_device->hc_conn, data->speed, enable_port_callback,440 &data->hub->connection, data->speed, enable_port_callback, 429 441 data->port, &new_address, NULL, NULL, &child_fun); 430 442 -
uspace/drv/bus/usb/usbhub/usbhub.c
r153cc76a r2f0dd2a 99 99 fibril_condvar_initialize(&hub_dev->pending_ops_cv); 100 100 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", 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", 105 107 str_error(opResult)); 106 108 return opResult; … … 110 112 opResult = usb_set_first_configuration(usb_dev); 111 113 if (opResult != EOK) { 112 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);113 114 usb_log_error("Could not set hub configuration: %s\n", 114 115 str_error(opResult)); … … 119 120 opResult = usb_hub_process_hub_specific_info(hub_dev); 120 121 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);133 132 usb_log_error("Failed to create hub function.\n"); 134 133 return ENOMEM; … … 138 137 opResult = ddf_fun_bind(hub_dev->hub_fun); 139 138 if (opResult != EOK) { 140 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);141 139 usb_log_error("Failed to bind hub function: %s.\n", 142 140 str_error(opResult)); … … 150 148 usb_hub_polling_terminated_callback, hub_dev); 151 149 if (opResult != EOK) { 152 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);153 150 /* Function is already bound */ 154 151 ddf_fun_unbind(hub_dev->hub_fun); … … 162 159 hub_dev->usb_device->ddf_dev->name, hub_dev->port_count); 163 160 164 usb_pipe_end_long_transfer(&usb_dev->ctrl_pipe);165 161 return EOK; 166 162 } -
uspace/drv/bus/usb/usbhub/usbhub.h
r153cc76a r2f0dd2a 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; 59 61 /** Generic usb device data*/ 60 62 usb_device_t *usb_device; -
uspace/drv/bus/usb/usbmid/main.c
r153cc76a r2f0dd2a 53 53 usb_log_info("Taking care of new MID `%s'.\n", dev->ddf_dev->name); 54 54 55 const bool accept = usbmid_explore_device(dev); 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); 56 60 57 61 if (!accept) { -
uspace/drv/bus/usb/vhc/hub.c
r153cc76a r2f0dd2a 107 107 108 108 usb_hc_connection_t hc_conn; 109 usb_hc_connection_initialize(&hc_conn, hc_dev->handle); 109 rc = usb_hc_connection_initialize(&hc_conn, hc_dev->handle); 110 assert(rc == EOK); 110 111 111 112 rc = usb_hc_connection_open(&hc_conn); -
uspace/lib/drv/include/usbhc_iface.h
r153cc76a r2f0dd2a 1 1 /* 2 2 * Copyright (c) 2010 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely4 3 * All rights reserved. 5 4 * … … 27 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 27 */ 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, usb_endpoint_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
r153cc76a r2f0dd2a 37 37 src/class.c \ 38 38 src/ddfiface.c \ 39 src/dev.c \40 39 src/debug.c \ 41 40 src/dump.c \ 42 41 src/hc.c \ 42 src/resolve.c \ 43 43 src/usb.c 44 44 -
uspace/lib/usb/include/usb/classes/hub.h
r153cc76a r2f0dd2a 84 84 85 85 /** 86 * @brief usb hub descriptor 87 * 88 * For more information see Universal Serial Bus Specification Revision 1.1 89 * chapter 11.16.2 86 * @brief usb hub descriptor 87 * 88 * For more information see Universal Serial Bus Specification Revision 1.1 chapter 11.16.2 90 89 */ 91 90 typedef struct usb_hub_descriptor_type { -
uspace/lib/usb/include/usb/hc.h
r153cc76a r2f0dd2a 1 1 /* 2 2 * Copyright (c) 2011 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely4 3 * All rights reserved. 5 4 * … … 27 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 27 */ 28 29 29 /** @addtogroup libusb 30 30 * @{ 31 31 */ 32 32 /** @file 33 * General communication with host controller .33 * General communication with host controller driver. 34 34 */ 35 35 #ifndef LIBUSB_HC_H_ 36 36 #define LIBUSB_HC_H_ 37 37 38 #include <async.h> 39 #include <devman.h> 38 #include <sys/types.h> 39 #include <ipc/devman.h> 40 #include <ipc/loc.h> 40 41 #include <ddf/driver.h> 41 42 #include <bool.h> 42 #include < fibril_synch.h>43 #include <async.h> 43 44 #include <usb/usb.h> 44 45 45 /** Connection to the host controller driver. 46 * 47 * This is a high level IPC communication wrapper. After the structure has been 48 * initialized using devman handle of an USB host controller, it 49 * will manage all communication to that host controller, including session 50 * creation/destruction and proper IPC protocol. 51 */ 46 /** Connection to the host controller driver. */ 52 47 typedef struct { 53 48 /** Devman handle of the host controller. */ … … 55 50 /** Session to the host controller. */ 56 51 async_sess_t *hc_sess; 57 /** Session guard. */58 fibril_mutex_t guard;59 /** Use counter. */60 unsigned ref_count;61 52 } usb_hc_connection_t; 62 63 /** Initialize connection to USB host controller.64 *65 * @param connection Connection to be initialized.66 * @param hc_handle Devman handle of the host controller.67 * @return Error code.68 */69 static inline void usb_hc_connection_initialize(usb_hc_connection_t *connection,70 devman_handle_t hc_handle)71 {72 assert(connection);73 connection->hc_handle = hc_handle;74 connection->hc_sess = NULL;75 connection->ref_count = 0;76 fibril_mutex_initialize(&connection->guard);77 }78 53 79 54 int usb_hc_connection_initialize_from_device(usb_hc_connection_t *, 80 55 const ddf_dev_t *); 81 82 void usb_hc_connection_deinitialize(usb_hc_connection_t *); 56 int usb_hc_connection_initialize(usb_hc_connection_t *, devman_handle_t); 83 57 84 58 int usb_hc_connection_open(usb_hc_connection_t *); 59 bool usb_hc_connection_is_opened(const usb_hc_connection_t *); 85 60 int usb_hc_connection_close(usb_hc_connection_t *); 86 87 usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_address_t, bool,88 usb_speed_t);89 int usb_hc_bind_address(usb_hc_connection_t *, usb_address_t, devman_handle_t);90 61 int usb_hc_get_handle_by_address(usb_hc_connection_t *, usb_address_t, 91 62 devman_handle_t *); 92 int usb_hc_release_address(usb_hc_connection_t *, usb_address_t);93 63 94 int usb_hc_register_endpoint(usb_hc_connection_t *, usb_address_t, 95 usb_endpoint_t, usb_transfer_type_t, usb_direction_t, size_t, unsigned int); 96 int usb_hc_unregister_endpoint(usb_hc_connection_t *, usb_address_t, 97 usb_endpoint_t, usb_direction_t); 64 usb_address_t usb_get_address_by_handle(devman_handle_t); 98 65 99 int usb_hc_read(usb_hc_connection_t *, usb_address_t, usb_endpoint_t, 100 uint64_t, void *, size_t, size_t *); 101 int usb_hc_write(usb_hc_connection_t *, usb_address_t, usb_endpoint_t, 102 uint64_t, const void *, size_t); 66 int usb_hc_find(devman_handle_t, devman_handle_t *); 103 67 104 /** Get host controller handle by its class index. 105 * 106 * @param sid Service ID of the HC function. 107 * @param hc_handle Where to store the HC handle 108 * (can be NULL for existence test only). 109 * @return Error code. 110 */ 111 static inline int usb_ddf_get_hc_handle_by_sid( 112 service_id_t sid, devman_handle_t *handle) 113 { 114 devman_handle_t h; 115 return devman_fun_sid_to_handle(sid, handle ? handle : &h); 116 } 68 int usb_resolve_device_handle(const char *, devman_handle_t *, usb_address_t *, 69 devman_handle_t *); 70 71 int usb_ddf_get_hc_handle_by_sid(service_id_t, devman_handle_t *); 72 117 73 118 74 #endif -
uspace/lib/usb/include/usb/usb.h
r153cc76a r2f0dd2a 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 28 29 /** @addtogroup libusb 29 30 * @{ -
uspace/lib/usb/src/ddfiface.c
r153cc76a r2f0dd2a 44 44 #include <assert.h> 45 45 46 #include <usb/dev.h>47 48 46 /** DDF interface for USB device, implementation for typical hub. */ 49 47 usb_iface_t usb_iface_hub_impl = { … … 68 66 { 69 67 assert(fun); 70 return usb_ get_hc_by_handle(fun->handle, handle);68 return usb_hc_find(fun->handle, handle); 71 69 } 72 70 … … 99 97 { 100 98 assert(fun); 101 return usb_get_address_by_handle(fun->handle, address); 99 100 async_sess_t *parent_sess = 101 devman_parent_device_connect(EXCHANGE_SERIALIZE, fun->handle, 102 IPC_FLAG_BLOCKING); 103 if (!parent_sess) 104 return ENOMEM; 105 106 async_exch_t *exch = async_exchange_begin(parent_sess); 107 if (!exch) { 108 async_hangup(parent_sess); 109 return ENOMEM; 110 } 111 112 const int ret = usb_get_my_address(exch, address); 113 114 async_exchange_end(exch); 115 async_hangup(parent_sess); 116 117 return ret; 102 118 } 103 119 … … 118 134 assert(fun); 119 135 assert(fun->driver_data); 120 constusb_hub_attached_device_t *device = fun->driver_data;136 usb_hub_attached_device_t *device = fun->driver_data; 121 137 assert(device->fun == fun); 122 138 if (address) -
uspace/lib/usb/src/hc.c
r153cc76a r2f0dd2a 1 1 /* 2 2 * Copyright (c) 2011 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely4 3 * All rights reserved. 5 4 * … … 27 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 27 */ 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> 39 #include <usbhc_iface.h> 40 #include <usb/hc.h> 35 41 #include <usb/debug.h> 36 42 #include <errno.h> 37 43 #include <assert.h> 38 #include <errno.h>39 #include <usbhc_iface.h>40 #include <usb/dev.h>41 #include <usb/hc.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 if (connection->ref_count == 0) {67 /* Closing already closed connection... */68 assert(connection->hc_sess = NULL);69 fibril_mutex_unlock(&connection->guard);70 return EOK;71 }72 --connection->ref_count;73 int ret = EOK;74 if (connection->ref_count == 0) {75 assert(connection->hc_sess);76 ret = async_hangup(connection->hc_sess);77 connection->hc_sess = NULL;78 }79 fibril_mutex_unlock(&connection->guard);80 return ret;81 }82 83 #define EXCH_INIT(connection, exch) \84 do { \85 exch = NULL; \86 if (!connection) \87 return EBADMEM; \88 const int ret = usb_hc_connection_add_ref(connection); \89 if (ret != EOK) \90 return ret; \91 exch = async_exchange_begin(connection->hc_sess); \92 if (exch == NULL) { \93 usb_hc_connection_del_ref(connection); \94 return ENOMEM; \95 } \96 } while (0)97 98 #define EXCH_FINI(connection, exch) \99 if (exch) { \100 async_exchange_end(exch); \101 usb_hc_connection_del_ref(connection); \102 } else (void)0103 44 104 45 /** Initialize connection to USB host controller. … … 118 59 119 60 devman_handle_t hc_handle; 120 const int rc = usb_get_hc_by_handle(device->handle, &hc_handle); 121 if (rc == EOK) { 122 usb_hc_connection_initialize(connection, hc_handle); 123 } 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); 124 67 125 68 return rc; 126 69 } 127 /*----------------------------------------------------------------------------*/ 128 void usb_hc_connection_deinitialize(usb_hc_connection_t *connection) 129 { 130 assert(connection); 131 fibril_mutex_lock(&connection->guard); 132 if (connection->ref_count != 0) { 133 usb_log_warning("%u stale reference(s) to HC connection.\n", 134 connection->ref_count); 135 assert(connection->hc_sess); 136 async_hangup(connection->hc_sess); 137 connection->hc_sess = NULL; 138 connection->ref_count = 0; 139 } 140 fibril_mutex_unlock(&connection->guard); 141 } 142 /*----------------------------------------------------------------------------*/ 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 143 88 /** Open connection to host controller. 144 89 * … … 148 93 int usb_hc_connection_open(usb_hc_connection_t *connection) 149 94 { 150 return usb_hc_connection_add_ref(connection); 151 } 152 /*----------------------------------------------------------------------------*/ 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. 110 * 111 * @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 153 120 /** Close connection to the host controller. 154 121 * … … 158 125 int usb_hc_connection_close(usb_hc_connection_t *connection) 159 126 { 160 return usb_hc_connection_del_ref(connection); 161 } 162 /*----------------------------------------------------------------------------*/ 163 /** Ask host controller for free address assignment. 164 * 165 * @param connection Opened connection to host controller. 166 * @param preferred Preferred SUB address. 167 * @param strict Fail if the preferred address is not avialable. 168 * @param speed Speed of the new device (device that will be assigned 169 * the returned address). 170 * @return Assigned USB address or negative error code. 171 */ 172 usb_address_t usb_hc_request_address(usb_hc_connection_t *connection, 173 usb_address_t preferred, bool strict, usb_speed_t speed) 174 { 175 async_exch_t *exch; 176 EXCH_INIT(connection, exch); 177 178 usb_address_t address = preferred; 179 const int ret = usbhc_request_address(exch, &address, strict, speed); 180 181 EXCH_FINI(connection, exch); 182 return ret == EOK ? address : ret; 183 } 184 /*----------------------------------------------------------------------------*/ 185 int usb_hc_bind_address(usb_hc_connection_t * connection, 186 usb_address_t address, devman_handle_t handle) 187 { 188 async_exch_t *exch; 189 EXCH_INIT(connection, exch); 190 191 const int ret = usbhc_bind_address(exch, address, handle); 192 193 EXCH_FINI(connection, exch); 194 return ret; 195 } 196 /*----------------------------------------------------------------------------*/ 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 197 143 /** Get handle of USB device with given address. 198 144 * … … 205 151 usb_address_t address, devman_handle_t *handle) 206 152 { 207 async_exch_t *exch; 208 EXCH_INIT(connection, exch); 209 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; 210 159 const int ret = usbhc_get_handle(exch, address, handle); 211 212 EXCH_FINI(connection, exch); 160 async_exchange_end(exch); 213 161 return ret; 214 162 } 215 /*----------------------------------------------------------------------------*/ 216 int usb_hc_release_address(usb_hc_connection_t *connection, 217 usb_address_t address) 218 { 219 async_exch_t *exch; 220 EXCH_INIT(connection, exch); 221 222 const int ret = usbhc_release_address(exch, address); 223 224 EXCH_FINI(connection, exch); 225 return ret; 226 } 227 /*----------------------------------------------------------------------------*/ 228 int usb_hc_register_endpoint(usb_hc_connection_t *connection, 229 usb_address_t address, usb_endpoint_t endpoint, usb_transfer_type_t type, 230 usb_direction_t direction, size_t packet_size, unsigned interval) 231 { 232 async_exch_t *exch; 233 EXCH_INIT(connection, exch); 234 235 const int ret = usbhc_register_endpoint(exch, address, endpoint, 236 type, direction, packet_size, interval); 237 238 EXCH_FINI(connection, exch); 239 return ret; 240 } 241 /*----------------------------------------------------------------------------*/ 242 int usb_hc_unregister_endpoint(usb_hc_connection_t *connection, 243 usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction) 244 { 245 async_exch_t *exch; 246 EXCH_INIT(connection, exch); 247 248 const int ret = 249 usbhc_unregister_endpoint(exch, address, endpoint, direction); 250 251 EXCH_FINI(connection, exch); 252 return ret; 253 } 254 /*----------------------------------------------------------------------------*/ 255 int usb_hc_read(usb_hc_connection_t *connection, usb_address_t address, 256 usb_endpoint_t endpoint, uint64_t setup, void *data, size_t size, 257 size_t *real_size) 258 { 259 async_exch_t *exch; 260 EXCH_INIT(connection, exch); 261 262 const int ret = 263 usbhc_read(exch, address, endpoint, setup, data, size, real_size); 264 265 EXCH_FINI(connection, exch); 266 return ret; 267 } 268 /*----------------------------------------------------------------------------*/ 269 int usb_hc_write(usb_hc_connection_t *connection, usb_address_t address, 270 usb_endpoint_t endpoint, uint64_t setup, const void *data, size_t size) 271 { 272 async_exch_t *exch; 273 EXCH_INIT(connection, exch); 274 275 const int ret = usbhc_write(exch, address, endpoint, setup, data, size); 276 277 EXCH_FINI(connection, exch); 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 195 /** Get host controller handle by its class index. 196 * 197 * @param sid Service ID of the HC function. 198 * @param hc_handle Where to store the HC handle 199 * (can be NULL for existence test only). 200 * @return Error code. 201 */ 202 int usb_ddf_get_hc_handle_by_sid(service_id_t sid, devman_handle_t *hc_handle) 203 { 204 devman_handle_t handle; 205 int rc; 206 207 rc = devman_fun_sid_to_handle(sid, &handle); 208 if (hc_handle != NULL) 209 *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 controller 218 * 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 278 239 return ret; 279 240 } -
uspace/lib/usb/src/usb.c
r153cc76a r2f0dd2a 39 39 40 40 static const char *str_speed[] = { 41 [USB_SPEED_LOW] ="low",42 [USB_SPEED_FULL] ="full",43 [USB_SPEED_HIGH] = "high",41 "low", 42 "full", 43 "high" 44 44 }; 45 45 46 46 static const char *str_transfer_type[] = { 47 [USB_TRANSFER_CONTROL] ="control",48 [USB_TRANSFER_ISOCHRONOUS] ="isochronous",49 [USB_TRANSFER_BULK] ="bulk",50 [USB_TRANSFER_INTERRUPT] = "interrupt",47 "control", 48 "isochronous", 49 "bulk", 50 "interrupt" 51 51 }; 52 52 53 53 static const char *str_transfer_type_short[] = { 54 [USB_TRANSFER_CONTROL] ="ctrl",55 [USB_TRANSFER_ISOCHRONOUS] ="iso",56 [USB_TRANSFER_BULK] ="bulk",57 [USB_TRANSFER_INTERRUPT] = "intr",54 "ctrl", 55 "iso", 56 "bulk", 57 "intr" 58 58 }; 59 59 60 60 static const char *str_direction[] = { 61 [USB_DIRECTION_IN] ="in",62 [USB_DIRECTION_OUT] ="out",63 [USB_DIRECTION_BOTH] = "both",61 "in", 62 "out", 63 "both" 64 64 }; 65 65 -
uspace/lib/usbdev/Makefile
r153cc76a r2f0dd2a 40 40 src/dp.c \ 41 41 src/hub.c \ 42 src/pipepriv.c \ 43 src/pipepriv.h \ 42 44 src/pipes.c \ 43 45 src/pipesinit.c \ 46 src/pipesio.c \ 44 47 src/recognise.c \ 45 48 src/request.c -
uspace/lib/usbdev/include/usb/dev/driver.h
r153cc76a r2f0dd2a 36 36 #define LIBUSBDEV_DRIVER_H_ 37 37 38 #include <usb/hc.h>39 #include <usb/dev/usb_device_connection.h>40 38 #include <usb/dev/pipes.h> 41 39 … … 74 72 /** USB device structure. */ 75 73 typedef struct { 76 /** Connection to USB hc, used by wire and arbitrary requests. */77 usb_hc_connection_t hc_conn;78 74 /** Connection backing the pipes. 79 75 * Typically, you will not need to use this attribute at all. … … 173 169 void usb_device_release_descriptors(usb_device_descriptors_t *); 174 170 175 int usb_device_create_pipes( usb_device_connection_t *,171 int usb_device_create_pipes(const ddf_dev_t *, usb_device_connection_t *, 176 172 const usb_endpoint_description_t **, const uint8_t *, size_t, int, int, 177 173 usb_endpoint_mapping_t **, size_t *); 178 void usb_device_destroy_pipes(usb_endpoint_mapping_t *, size_t);174 int usb_device_destroy_pipes(const ddf_dev_t *, usb_endpoint_mapping_t *, size_t); 179 175 180 176 void * usb_device_data_alloc(usb_device_t *, size_t); -
uspace/lib/usbdev/include/usb/dev/hub.h
r153cc76a r2f0dd2a 40 40 #include <ddf/driver.h> 41 41 #include <sys/types.h> 42 #include <errno.h>43 42 #include <usb/hc.h> 44 43 … … 60 59 } usb_hub_attached_device_t; 61 60 62 int usb_hub_register_device(usb_hc_connection_t *, 61 usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_address_t, 62 bool, usb_speed_t); 63 int usb_hc_register_device(usb_hc_connection_t *, 63 64 const usb_hub_attached_device_t *); 64 65 static inline int usb_hub_unregister_device(usb_hc_connection_t *conn, 66 const usb_hub_attached_device_t *attached_device) 67 { 68 assert(conn); 69 if (attached_device == NULL) 70 return EBADMEM; 71 return usb_hc_release_address(conn, attached_device->address); 72 } 65 int usb_hc_unregister_device(usb_hc_connection_t *, usb_address_t); 73 66 74 67 #endif -
uspace/lib/usbdev/include/usb/dev/pipes.h
r153cc76a r2f0dd2a 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 28 29 /** @addtogroup libusbdev 29 30 * @{ … … 36 37 37 38 #include <sys/types.h> 39 #include <usb/usb.h> 40 #include <usb/hc.h> 41 #include <usb/descriptor.h> 38 42 #include <ipc/devman.h> 39 43 #include <ddf/driver.h> 40 44 #include <fibril_synch.h> 41 #include <usb/usb.h> 42 #include <usb/descriptor.h> 43 #include <usb/dev/usb_device_connection.h> 45 #include <async.h> 44 46 45 #define CTRL_PIPE_MIN_PACKET_SIZE 8 47 /** Abstraction of a physical connection to the device. 48 * This type is an abstraction of the USB wire that connects the host and 49 * 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 46 58 /** Abstraction of a logical connection to USB device endpoint. 47 * It encapsulates endpoint attributes (transfer type etc.). 59 * It encapsulates endpoint attributes (transfer type etc.) as well 60 * as information about currently running sessions. 48 61 * This endpoint must be bound with existing usb_device_connection_t 49 62 * (i.e. the wire to send data over). 63 * 64 * Locking order: if you want to lock both mutexes 65 * (@c guard and @c hc_sess_mutex), lock @c guard first. 66 * It is not necessary to lock @c guard if you want to lock @c hc_sess_mutex 67 * only. 50 68 */ 51 69 typedef struct { 70 /** Guard of the whole pipe. */ 71 fibril_mutex_t guard; 72 52 73 /** The connection used for sending the data. */ 53 74 usb_device_connection_t *wire; … … 65 86 size_t max_packet_size; 66 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_mutex 91 * being locked. 92 * If call over the phone is to be made, it must be preceeded by 93 * 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 operation 104 * 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 to 107 * add reference as well. 108 * If that fails, it is reported to the user. If it is okay, the 109 * real reference counter is incremented. 110 * The problem might arise when ending the long transfer (since 111 * the number of references would be only 1, but logically it shall be 112 * two). 113 * Decrementing the soft counter first shall solve this. 114 */ 115 int refcount_soft; 116 67 117 /** Whether to automatically reset halt on the endpoint. 68 118 * Valid only for control endpoint zero. … … 70 120 bool auto_reset_halt; 71 121 } usb_pipe_t; 122 72 123 73 124 /** Description of endpoint characteristics. */ … … 105 156 } usb_endpoint_mapping_t; 106 157 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 165 int usb_device_get_assigned_interface(const ddf_dev_t *); 166 107 167 int usb_pipe_initialize(usb_pipe_t *, usb_device_connection_t *, 108 168 usb_endpoint_t, usb_transfer_type_t, size_t, usb_direction_t); 109 169 int usb_pipe_initialize_default_control(usb_pipe_t *, 110 170 usb_device_connection_t *); 111 112 171 int usb_pipe_probe_default_control(usb_pipe_t *); 113 172 int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *, 114 173 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 *); 115 176 116 int usb_pipe_register(usb_pipe_t *, unsigned); 117 int usb_pipe_unregister(usb_pipe_t *); 118 119 int usb_pipe_start_long_transfer(usb_pipe_t *); 120 int usb_pipe_end_long_transfer(usb_pipe_t *); 177 void usb_pipe_start_long_transfer(usb_pipe_t *); 178 void usb_pipe_end_long_transfer(usb_pipe_t *); 121 179 122 180 int usb_pipe_read(usb_pipe_t *, void *, size_t, size_t *); -
uspace/lib/usbdev/include/usb/dev/poll.h
r153cc76a r2f0dd2a 39 39 #include <time.h> 40 40 41 /** Parameters and callbacks for automated polling. */42 41 typedef struct { 43 42 /** Level of debugging messages from auto polling. … … 83 82 */ 84 83 bool (*on_error)(usb_device_t *dev, int err_code, void *arg); 85 /** Argument to pass to callbacks. */86 void *arg;87 84 } usb_device_auto_polling_t; 88 85 89 86 int usb_device_auto_polling(usb_device_t *, size_t, 90 const usb_device_auto_polling_t *, size_t );87 const usb_device_auto_polling_t *, size_t, void *); 91 88 92 89 typedef bool (*usb_polling_callback_t)(usb_device_t *, -
uspace/lib/usbdev/include/usb/dev/request.h
r153cc76a r2f0dd2a 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))91 85 92 86 /** Request identification. */ -
uspace/lib/usbdev/src/altiface.c
r153cc76a r2f0dd2a 167 167 } 168 168 169 /** Clean initialized structure. 170 * @param instance structure do deinitialize. 171 */ 172 void usb_alternate_interfaces_deinit(usb_alternate_interfaces_t *instance) 169 void usb_alternate_interfaces_deinit(usb_alternate_interfaces_t *alternate) 173 170 { 174 if (! instance)171 if (!alternate) 175 172 return; 176 free(instance->alternatives); 177 instance->alternatives = NULL; 173 free(alternate->alternatives); 178 174 } 179 175 /** -
uspace/lib/usbdev/src/devdrv.c
r153cc76a r2f0dd2a 1 1 /* 2 2 * Copyright (c) 2011 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely4 3 * All rights reserved. 5 4 * … … 27 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 27 */ 28 29 29 /** @addtogroup libusbdev 30 30 * @{ … … 36 36 #include <usb/dev/request.h> 37 37 #include <usb/debug.h> 38 #include <usb/dev .h>38 #include <usb/dev/dp.h> 39 39 #include <errno.h> 40 40 #include <str_error.h> … … 56 56 static const usb_driver_t *driver = NULL; 57 57 58 58 59 /** Main routine of USB device driver. 59 60 * … … 74 75 return ddf_driver_main(&generic_driver); 75 76 } 76 /*----------------------------------------------------------------------------*/ 77 77 78 /** Count number of pipes the driver expects. 78 79 * … … 84 85 { 85 86 size_t count; 86 for (count = 0; endpoints != NULL&& endpoints[count] != NULL; ++count);87 for (count = 0; endpoints && endpoints[count] != NULL; ++count); 87 88 return count; 89 } 90 91 /** Initialize endpoint pipes, excluding default control one. 92 * 93 * @param drv The device driver. 94 * @param dev Device to be initialized. 95 * @return Error code. 96 */ 97 static int initialize_other_pipes(const usb_endpoint_description_t **endpoints, 98 usb_device_t *dev, int alternate_setting) 99 { 100 assert(dev); 101 102 if (endpoints == NULL) { 103 dev->pipes = NULL; 104 dev->pipes_count = 0; 105 return EOK; 106 } 107 108 usb_endpoint_mapping_t *pipes; 109 size_t pipes_count; 110 111 int rc = usb_device_create_pipes(dev->ddf_dev, &dev->wire, endpoints, 112 dev->descriptors.configuration, dev->descriptors.configuration_size, 113 dev->interface_no, alternate_setting, &pipes, &pipes_count); 114 115 if (rc != EOK) { 116 return rc; 117 } 118 119 dev->pipes = pipes; 120 dev->pipes_count = pipes_count; 121 122 return EOK; 88 123 } 89 124 /*----------------------------------------------------------------------------*/ … … 101 136 assert(driver->ops->device_add); 102 137 103 /* Get place for driver data. */104 138 usb_device_t *dev = ddf_dev_data_alloc(gen_dev, sizeof(usb_device_t)); 105 139 if (dev == NULL) { … … 108 142 return ENOMEM; 109 143 } 110 111 /* Initialize generic USB driver data. */112 144 const char *err_msg = NULL; 113 145 int rc = usb_device_init(dev, gen_dev, driver->endpoints, &err_msg); … … 118 150 } 119 151 120 /* Start USB driver specific initialization. */121 152 rc = driver->ops->device_add(dev); 122 153 if (rc != EOK) … … 138 169 if (driver->ops->device_rem == NULL) 139 170 return ENOTSUP; 140 /* Just tell the driver to stop whatever it is doing */ 141 usb_device_t *usb_dev = gen_dev->driver_data; 142 const int ret = driver->ops->device_rem(usb_dev); 143 if (ret != EOK) 144 return ret; 145 usb_device_deinit(usb_dev); 146 return EOK; 171 /* Just tell the driver to stop whatever it is doing, keep structures */ 172 return driver->ops->device_rem(gen_dev->driver_data); 147 173 } 148 174 /*----------------------------------------------------------------------------*/ … … 171 197 * 172 198 * @param dev Device where to destroy the pipes. 173 */ 174 static void destroy_current_pipes(usb_device_t *dev) 175 { 176 usb_device_destroy_pipes(dev->pipes, dev->pipes_count); 199 * @return Error code. 200 */ 201 static int destroy_current_pipes(usb_device_t *dev) 202 { 203 int rc = usb_device_destroy_pipes(dev->ddf_dev, 204 dev->pipes, dev->pipes_count); 205 if (rc != EOK) { 206 return rc; 207 } 208 177 209 dev->pipes = NULL; 178 210 dev->pipes_count = 0; 179 } 180 /*----------------------------------------------------------------------------*/ 211 212 return EOK; 213 } 214 181 215 /** Change interface setting of a device. 182 216 * This function selects new alternate setting of an interface by issuing … … 208 242 } 209 243 244 int rc; 245 210 246 /* Destroy existing pipes. */ 211 destroy_current_pipes(dev); 247 rc = destroy_current_pipes(dev); 248 if (rc != EOK) { 249 return rc; 250 } 212 251 213 252 /* Change the interface itself. */ 214 intrc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no,253 rc = usb_request_set_interface(&dev->ctrl_pipe, dev->interface_no, 215 254 alternate_setting); 216 255 if (rc != EOK) { … … 219 258 220 259 /* Create new pipes. */ 221 rc = usb_device_create_pipes(&dev->wire, endpoints, 222 dev->descriptors.configuration, dev->descriptors.configuration_size, 223 dev->interface_no, (int)alternate_setting, 224 &dev->pipes, &dev->pipes_count); 260 rc = initialize_other_pipes(endpoints, dev, (int) alternate_setting); 225 261 226 262 return rc; … … 280 316 * - registers endpoints with the host controller 281 317 * 318 * @param[in] dev Generic DDF device backing the USB one. 282 319 * @param[in] wire Initialized backing connection to the host controller. 283 320 * @param[in] endpoints Endpoints description, NULL terminated. … … 292 329 * @return Error code. 293 330 */ 294 int usb_device_create_pipes( usb_device_connection_t *wire,331 int usb_device_create_pipes(const ddf_dev_t *dev, usb_device_connection_t *wire, 295 332 const usb_endpoint_description_t **endpoints, 296 333 const uint8_t *config_descr, size_t config_descr_size, … … 298 335 usb_endpoint_mapping_t **pipes_ptr, size_t *pipes_count_ptr) 299 336 { 337 assert(dev != NULL); 300 338 assert(wire != NULL); 339 assert(endpoints != NULL); 301 340 assert(config_descr != NULL); 302 341 assert(config_descr_size > 0); … … 320 359 } 321 360 322 /* Now initialize. */361 /* Now allocate and fully initialize. */ 323 362 for (i = 0; i < pipe_count; i++) { 324 363 pipes[i].description = endpoints[i]; … … 331 370 config_descr, config_descr_size, wire); 332 371 if (rc != EOK) { 333 free(pipes); 334 return rc; 335 } 336 337 /* Register created pipes. */ 372 goto rollback_free_only; 373 } 374 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 338 387 for (i = 0; i < pipe_count; i++) { 339 388 if (pipes[i].present) { 340 389 rc = usb_pipe_register(&pipes[i].pipe, 341 pipes[i].descriptor->poll_interval );390 pipes[i].descriptor->poll_interval, &hc_conn); 342 391 if (rc != EOK) { 343 392 goto rollback_unregister_endpoints; … … 345 394 } 346 395 } 396 397 if (usb_hc_connection_close(&hc_conn) != EOK) 398 usb_log_warning("%s: Failed to close connection.\n", 399 __FUNCTION__); 347 400 348 401 *pipes_ptr = pipes; … … 362 415 for (i = 0; i < pipe_count; i++) { 363 416 if (pipes[i].present) { 364 usb_pipe_unregister(&pipes[i].pipe );417 usb_pipe_unregister(&pipes[i].pipe, &hc_conn); 365 418 } 366 419 } 367 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 425 /* 426 * Jump here if something went wrong before some actual communication 427 * with HC. Then the only thing that needs to be done is to free 428 * allocated memory. 429 */ 430 rollback_free_only: 368 431 free(pipes); 432 369 433 return rc; 370 434 } … … 372 436 /** Destroy pipes previously created by usb_device_create_pipes. 373 437 * 438 * @param[in] dev Generic DDF device backing the USB one. 374 439 * @param[in] pipes Endpoint mapping to be destroyed. 375 440 * @param[in] pipes_count Number of endpoints. 376 441 */ 377 void usb_device_destroy_pipes(usb_endpoint_mapping_t *pipes, size_t pipes_count) 378 { 442 int usb_device_destroy_pipes(const ddf_dev_t *dev, 443 usb_endpoint_mapping_t *pipes, size_t pipes_count) 444 { 445 assert(dev != NULL); 446 447 if (pipes_count == 0) { 448 assert(pipes == NULL); 449 return EOK; 450 } 451 assert(pipes != NULL); 452 453 int rc; 454 455 /* Prepare connection to HC to allow endpoint unregistering. */ 456 usb_hc_connection_t hc_conn; 457 rc = usb_hc_connection_initialize_from_device(&hc_conn, dev); 458 if (rc != EOK) { 459 return rc; 460 } 461 rc = usb_hc_connection_open(&hc_conn); 462 if (rc != EOK) { 463 return rc; 464 } 465 379 466 /* Destroy the pipes. */ 380 for (size_t i = 0; i < pipes_count; ++i) {381 assert(pipes);382 usb_log_debug2("Unregistering pipe %zu : %spresent.\n",467 size_t i; 468 for (i = 0; i < pipes_count; i++) { 469 usb_log_debug2("Unregistering pipe %zu (%spresent).\n", 383 470 i, pipes[i].present ? "" : "not "); 384 471 if (pipes[i].present) 385 usb_pipe_unregister(&pipes[i].pipe); 386 } 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"); 478 387 479 free(pipes); 480 481 return EOK; 388 482 } 389 483 … … 411 505 usb_dev->pipes = NULL; 412 506 413 /* Get assigned params */414 devman_handle_t hc_handle;415 usb_address_t address;416 417 int rc = usb_get_info_by_handle(ddf_dev->handle,418 &hc_handle, &address, &usb_dev->interface_no);419 if (rc != EOK) {420 *errstr_ptr = "device parameters retrieval";421 return rc;422 }423 424 /* Initialize hc connection. */425 usb_hc_connection_initialize(&usb_dev->hc_conn, hc_handle);426 427 507 /* Initialize backing wire and control pipe. */ 428 rc = usb_device_connection_initialize(429 &usb_dev->wire, &usb_dev->hc_conn, address);508 int rc = usb_device_connection_initialize_from_device( 509 &usb_dev->wire, ddf_dev); 430 510 if (rc != EOK) { 431 511 *errstr_ptr = "device connection initialization"; … … 435 515 /* This pipe was registered by the hub driver, 436 516 * during device initialization. */ 437 rc = usb_pipe_initialize_default_control( 438 &usb_dev-> ctrl_pipe, &usb_dev->wire);517 rc = usb_pipe_initialize_default_control(&usb_dev->ctrl_pipe, 518 &usb_dev->wire); 439 519 if (rc != EOK) { 440 520 *errstr_ptr = "default control pipe initialization"; … … 442 522 } 443 523 444 /* Open hc connection for pipe registration. */ 445 rc = usb_hc_connection_open(&usb_dev->hc_conn); 446 if (rc != EOK) { 447 *errstr_ptr = "hc connection open"; 448 return rc; 449 } 524 /* Get our interface. */ 525 usb_dev->interface_no = usb_device_get_assigned_interface(ddf_dev); 450 526 451 527 /* Retrieve standard descriptors. */ 452 rc = usb_device_retrieve_descriptors( 453 &usb_dev-> ctrl_pipe, &usb_dev->descriptors);528 rc = usb_device_retrieve_descriptors(&usb_dev->ctrl_pipe, 529 &usb_dev->descriptors); 454 530 if (rc != EOK) { 455 531 *errstr_ptr = "descriptor retrieval"; 456 usb_hc_connection_close(&usb_dev->hc_conn);457 532 return rc; 458 533 } … … 468 543 (rc == EOK) ? usb_dev->alternate_interfaces.current : 0; 469 544 470 /* Create and register other pipes than default control (EP 0) */ 471 rc = usb_device_create_pipes(&usb_dev->wire, endpoints, 472 usb_dev->descriptors.configuration, 473 usb_dev->descriptors.configuration_size, 474 usb_dev->interface_no, (int)alternate_iface, 475 &usb_dev->pipes, &usb_dev->pipes_count); 476 if (rc != EOK) { 477 usb_hc_connection_close(&usb_dev->hc_conn); 545 /* TODO Add comment here. */ 546 rc = initialize_other_pipes(endpoints, usb_dev, alternate_iface); 547 if (rc != EOK) { 478 548 /* Full configuration descriptor is allocated. */ 479 549 usb_device_release_descriptors(&usb_dev->descriptors); … … 484 554 } 485 555 486 usb_hc_connection_close(&usb_dev->hc_conn);487 556 return EOK; 488 557 } … … 497 566 { 498 567 if (dev) { 499 /* Destroy existing pipes. */568 /* Ignore errors and hope for the best. */ 500 569 destroy_current_pipes(dev); 501 /* Ignore errors and hope for the best. */ 502 usb_hc_connection_deinitialize(&dev->hc_conn); 570 503 571 usb_alternate_interfaces_deinit(&dev->alternate_interfaces); 504 572 usb_device_release_descriptors(&dev->descriptors); 505 573 free(dev->driver_data); 506 dev->driver_data = NULL; 507 } 508 } 509 510 /** Allocate driver specific data. 511 * @param usb_dev usb_device structure. 512 * @param size requested data size. 513 * @return Pointer to the newly allocated space, NULL on failure. 514 */ 574 } 575 } 576 515 577 void * usb_device_data_alloc(usb_device_t *usb_dev, size_t size) 516 578 { -
uspace/lib/usbdev/src/devpoll.c
r153cc76a r2f0dd2a 46 46 /** Data needed for polling. */ 47 47 typedef struct { 48 /** Parameters for automated polling. */49 48 usb_device_auto_polling_t auto_polling; 50 49 51 /** USB device to poll. */52 50 usb_device_t *dev; 53 /** Device pipe to use for polling. */54 51 size_t pipe_index; 55 /** Size of the recieved data. */56 52 size_t request_size; 57 /** Data buffer. */58 53 uint8_t *buffer; 54 void *custom_arg; 59 55 } polling_data_t; 60 56 … … 123 119 ++failed_attempts; 124 120 const bool cont = (params->on_error == NULL) ? true : 125 params->on_error(data->dev, rc, params->arg);121 params->on_error(data->dev, rc, data->custom_arg); 126 122 if (!cont) { 127 123 failed_attempts = params->max_failures; … … 133 129 assert(params->on_data); 134 130 const bool carry_on = params->on_data( 135 data->dev, data->buffer, actual_size, params->arg);131 data->dev, data->buffer, actual_size, data->custom_arg); 136 132 137 133 if (!carry_on) { … … 153 149 154 150 if (params->on_polling_end != NULL) { 155 params->on_polling_end(data->dev, failed, params->arg);151 params->on_polling_end(data->dev, failed, data->custom_arg); 156 152 } 157 153 … … 203 199 .on_polling_end = terminated_callback, 204 200 .on_error = NULL, 205 .arg = arg,206 201 }; 207 202 208 203 return usb_device_auto_polling(dev, pipe_index, &auto_polling, 209 request_size );204 request_size, arg); 210 205 } 211 206 … … 229 224 int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index, 230 225 const usb_device_auto_polling_t *polling, 231 size_t request_size )226 size_t request_size, void *arg) 232 227 { 233 228 if ((dev == NULL) || (polling == NULL) || (polling->on_data == NULL)) { … … 257 252 polling_data->dev = dev; 258 253 polling_data->pipe_index = pipe_index; 254 polling_data->custom_arg = arg; 259 255 260 256 /* Copy provided settings. */ -
uspace/lib/usbdev/src/hub.c
r153cc76a r2f0dd2a 38 38 #include <usb/dev/recognise.h> 39 39 #include <usb/debug.h> 40 #include <usbhc_iface.h> 40 41 #include <errno.h> 41 42 #include <assert.h> … … 44 45 #include <async.h> 45 46 46 /** How much time to wait between attempts to get the default address.47 /** How much time to wait between attempts to register endpoint 0:0. 47 48 * The value is based on typical value for port reset + some overhead. 48 49 */ 49 #define DEFAULT_ADDRESS_ATTEMPT_DELAY_USEC (1000 * (10 + 2)) 50 #define ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC (1000 * (10 + 2)) 51 52 /** Check that HC connection is alright. 53 * 54 * @param conn Connection to be checked. 55 */ 56 #define CHECK_CONNECTION(conn) \ 57 do { \ 58 assert((conn)); \ 59 if (!usb_hc_connection_is_opened((conn))) { \ 60 usb_log_error("Connection not open.\n"); \ 61 return ENOTCONN; \ 62 } \ 63 } while (false) 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 assigned 71 * 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 } 50 89 51 90 /** Inform host controller about new device. … … 55 94 * @return Error code. 56 95 */ 57 int usb_h ub_register_device(usb_hc_connection_t *connection,96 int usb_hc_register_device(usb_hc_connection_t *connection, 58 97 const usb_hub_attached_device_t *attached_device) 59 98 { 60 assert(connection);99 CHECK_CONNECTION(connection); 61 100 if (attached_device == NULL || attached_device->fun == NULL) 62 return EBADMEM; 63 return usb_hc_bind_address(connection, 101 return EINVAL; 102 103 async_exch_t *exch = async_exchange_begin(connection->hc_sess); 104 if (!exch) 105 return ENOMEM; 106 const int ret = usbhc_bind_address(exch, 64 107 attached_device->address, attached_device->fun->handle); 108 async_exchange_end(exch); 109 110 return ret; 111 } 112 113 /** Inform host controller about device removal. 114 * 115 * @param connection Opened connection to host controller. 116 * @param address Address of the device that is being removed. 117 * @return Error code. 118 */ 119 int usb_hc_unregister_device(usb_hc_connection_t *connection, 120 usb_address_t address) 121 { 122 CHECK_CONNECTION(connection); 123 124 async_exch_t *exch = async_exchange_begin(connection->hc_sess); 125 if (!exch) 126 return ENOMEM; 127 const int ret = usbhc_release_address(exch, address); 128 async_exchange_end(exch); 129 130 return ret; 65 131 } 66 132 … … 79 145 * @return Error code. 80 146 */ 81 static int usb_request_set_address(usb_pipe_t *pipe, usb_address_t new_address) 147 static int usb_request_set_address(usb_pipe_t *pipe, usb_address_t new_address, 148 usb_hc_connection_t *hc_conn) 82 149 { 83 150 if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) { … … 85 152 } 86 153 assert(pipe); 154 assert(hc_conn); 87 155 assert(pipe->wire != NULL); 88 156 … … 98 166 99 167 /* TODO: prevent others from accessing the wire now. */ 100 if (usb_pipe_unregister(pipe ) != EOK) {168 if (usb_pipe_unregister(pipe, hc_conn) != EOK) { 101 169 usb_log_warning( 102 170 "Failed to unregister the old pipe on address change.\n"); 103 171 } 104 /* Address changed. We can release the old one, thus105 * allowing other to us it. */106 usb_hc_release_address(pipe->wire->hc_connection, pipe->wire->address);107 108 172 /* The address is already changed so set it in the wire */ 109 173 pipe->wire->address = new_address; 110 rc = usb_pipe_register(pipe, 0 );174 rc = usb_pipe_register(pipe, 0, hc_conn); 111 175 if (rc != EOK) 112 176 return EADDRNOTAVAIL; … … 156 220 */ 157 221 int usb_hc_new_device_wrapper(ddf_dev_t *parent, 158 usb_hc_connection_t * hc_conn, usb_speed_t dev_speed,222 usb_hc_connection_t *connection, usb_speed_t dev_speed, 159 223 int (*enable_port)(void *arg), void *arg, usb_address_t *assigned_address, 160 224 ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun) 161 225 { 162 if (new_fun == NULL || hc_conn == NULL)226 if (new_fun == NULL || connection == NULL) 163 227 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); 164 232 165 233 int rc; … … 171 239 } 172 240 173 /* We are gona do a lot of communication better open it in advance. */ 174 rc = usb_hc_connection_open(hc_conn); 241 rc = usb_hc_connection_open(&hc_conn); 175 242 if (rc != EOK) { 176 243 return rc; 177 244 } 178 245 179 /* Request a new address. */ 246 /* 247 * Request new address. 248 */ 180 249 usb_address_t dev_addr = 181 usb_hc_request_address( hc_conn, 0, false, dev_speed);250 usb_hc_request_address(&hc_conn, 0, false, dev_speed); 182 251 if (dev_addr < 0) { 183 252 rc = EADDRNOTAVAIL; … … 185 254 } 186 255 187 /* Initialize connection to device. */ 256 /* 257 * We will not register control pipe on default address. 258 * The registration might fail. That means that someone else already 259 * registered that endpoint. We will simply wait and try again. 260 * (Someone else already wants to add a new device.) 261 */ 188 262 usb_device_connection_t dev_conn; 189 rc = usb_device_connection_initialize (190 & dev_conn, hc_conn, USB_ADDRESS_DEFAULT);263 rc = usb_device_connection_initialize_on_default_address(&dev_conn, 264 &hc_conn); 191 265 if (rc != EOK) { 192 266 rc = ENOTCONN; … … 194 268 } 195 269 196 /* Initialize control pipe on default address. Don't register yet. */197 270 usb_pipe_t ctrl_pipe; 198 271 rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn); … … 202 275 } 203 276 204 /*205 * The default address request might fail.206 * That means that someone else is already using that address.207 * We will simply wait and try again.208 * (Someone else already wants to add a new device.)209 */210 277 do { 211 rc = usb_hc_request_address( hc_conn, USB_ADDRESS_DEFAULT,278 rc = usb_hc_request_address(&hc_conn, USB_ADDRESS_DEFAULT, 212 279 true, dev_speed); 213 280 if (rc == ENOENT) { 214 281 /* Do not overheat the CPU ;-). */ 215 async_usleep( DEFAULT_ADDRESS_ATTEMPT_DELAY_USEC);282 async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC); 216 283 } 217 284 } while (rc == ENOENT); … … 220 287 } 221 288 222 /* Register control pipe on default address. 0 means no interval.*/223 rc = usb_pipe_register(&ctrl_pipe, 0 );289 /* Register control pipe on default address. */ 290 rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn); 224 291 if (rc != EOK) { 225 292 rc = ENOTCONN; … … 228 295 229 296 struct timeval end_time; 297 230 298 rc = gettimeofday(&end_time, NULL); 231 299 if (rc != EOK) { … … 262 330 } 263 331 264 rc = usb_request_set_address(&ctrl_pipe, dev_addr );332 rc = usb_request_set_address(&ctrl_pipe, dev_addr, &hc_conn); 265 333 if (rc != EOK) { 266 334 rc = ESTALL; … … 268 336 } 269 337 338 /* Address changed. We can release the default, thus 339 * allowing other to access the default address. */ 340 usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT); 270 341 271 342 /* Register the device with devman. */ … … 285 356 286 357 /* Inform the host controller about the handle. */ 287 rc = usb_h ub_register_device(hc_conn, &new_device);358 rc = usb_hc_register_device(&hc_conn, &new_device); 288 359 if (rc != EOK) { 289 360 /* We know nothing about that data. */ … … 310 381 */ 311 382 leave_release_default_address: 312 if (usb_hc_release_address(hc_conn, USB_ADDRESS_DEFAULT) != EOK) 313 usb_log_warning("%s: Failed to release defaut address.\n", 314 __FUNCTION__); 383 usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT); 315 384 316 385 leave_release_free_address: 317 386 /* This might be either 0:0 or dev_addr:0 */ 318 if (usb_pipe_unregister(&ctrl_pipe ) != EOK)387 if (usb_pipe_unregister(&ctrl_pipe, &hc_conn) != EOK) 319 388 usb_log_warning("%s: Failed to unregister default pipe.\n", 320 389 __FUNCTION__); 321 390 322 if (usb_hc_ release_address(hc_conn, dev_addr) != EOK)323 usb_log_warning("%s: Failed to release address: %d.\n",324 __FUNCTION__ , dev_addr);391 if (usb_hc_unregister_device(&hc_conn, dev_addr) != EOK) 392 usb_log_warning("%s: Failed to unregister device.\n", 393 __FUNCTION__); 325 394 326 395 close_connection: 327 if (usb_hc_connection_close( hc_conn) != EOK)396 if (usb_hc_connection_close(&hc_conn) != EOK) 328 397 usb_log_warning("%s: Failed to close hc connection.\n", 329 398 __FUNCTION__); -
uspace/lib/usbdev/src/pipes.c
r153cc76a r2f0dd2a 1 1 /* 2 2 * Copyright (c) 2011 Vojtech Horky 3 * Copyright (c) 2011 Jan Vesely4 3 * All rights reserved. 5 4 * … … 27 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 27 */ 28 29 29 /** @addtogroup libusbdev 30 30 * @{ 31 31 */ 32 32 /** @file 33 * USB endpoint pipes functions. 34 */ 33 * USB endpoint pipes miscellaneous functions. 34 */ 35 #include <usb/usb.h> 35 36 #include <usb/dev/pipes.h> 36 #include <usb/dev/request.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 42 #include <errno.h> 38 43 #include <assert.h> 39 40 /** Prepare pipe for a long transfer. 41 * 42 * Long transfer is transfer consisting of several requests to the HC. 43 * Calling this function is optional and it has positive effect of 44 * improved performance because IPC session is initiated only once. 45 * 46 * @param pipe Pipe over which the transfer will happen. 47 * @return Error code. 48 */ 49 int usb_pipe_start_long_transfer(usb_pipe_t *pipe) 50 { 51 assert(pipe); 52 assert(pipe->wire); 53 assert(pipe->wire->hc_connection); 54 return usb_hc_connection_open(pipe->wire->hc_connection); 55 } 56 /*----------------------------------------------------------------------------*/ 57 /** Terminate a long transfer on a pipe. 58 * @param pipe Pipe where to end the long transfer. 59 * @return Error code. 60 * @see usb_pipe_start_long_transfer 61 */ 62 int usb_pipe_end_long_transfer(usb_pipe_t *pipe) 63 { 64 assert(pipe); 65 assert(pipe->wire); 66 assert(pipe->wire->hc_connection); 67 return usb_hc_connection_close(pipe->wire->hc_connection); 68 } 69 /*----------------------------------------------------------------------------*/ 70 /** Try to clear endpoint halt of default control pipe. 71 * 72 * @param pipe Pipe for control endpoint zero. 73 */ 74 static void clear_self_endpoint_halt(usb_pipe_t *pipe) 75 { 76 assert(pipe != NULL); 77 78 if (!pipe->auto_reset_halt || (pipe->endpoint_no != 0)) { 79 return; 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 69 /** Tell USB interface assigned to given device. 70 * 71 * @param device Device in question. 72 * @return Error code (ENOTSUP means any). 73 */ 74 int usb_device_get_assigned_interface(const ddf_dev_t *device) 75 { 76 assert(device); 77 async_sess_t *parent_sess = 78 devman_parent_device_connect(EXCHANGE_ATOMIC, device->handle, 79 IPC_FLAG_BLOCKING); 80 if (!parent_sess) 81 return ENOMEM; 82 83 async_exch_t *exch = async_exchange_begin(parent_sess); 84 if (!exch) { 85 async_hangup(parent_sess); 86 return ENOMEM; 80 87 } 81 88 82 /* Prevent infinite recursion. */ 83 pipe->auto_reset_halt = false; 84 usb_request_clear_endpoint_halt(pipe, 0); 85 pipe->auto_reset_halt = true; 86 } 87 /*----------------------------------------------------------------------------*/ 88 /** Request a control read transfer on an endpoint pipe. 89 * 90 * This function encapsulates all three stages of a control transfer. 91 * 92 * @param[in] pipe Pipe used for the transfer. 93 * @param[in] setup_buffer Buffer with the setup packet. 94 * @param[in] setup_buffer_size Size of the setup packet (in bytes). 95 * @param[out] data_buffer Buffer for incoming data. 96 * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes). 97 * @param[out] data_transfered_size Number of bytes that were actually 98 * transfered during the DATA stage. 99 * @return Error code. 100 */ 101 int usb_pipe_control_read(usb_pipe_t *pipe, 102 const void *setup_buffer, size_t setup_buffer_size, 103 void *buffer, size_t buffer_size, size_t *transfered_size) 104 { 105 assert(pipe); 106 107 if ((setup_buffer == NULL) || (setup_buffer_size != 8)) { 89 int iface_no; 90 const int ret = usb_get_my_interface(exch, &iface_no); 91 92 return ret == EOK ? iface_no : ret; 93 } 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)) { 108 169 return EINVAL; 109 170 } 110 171 111 if ((buffer == NULL) || (buffer_size == 0)) { 112 return EINVAL; 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; 113 192 } 114 193 115 if ((pipe->direction != USB_DIRECTION_BOTH) 116 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { 117 return EBADF; 118 } 119 120 uint64_t setup_packet; 121 memcpy(&setup_packet, setup_buffer, 8); 122 123 size_t act_size = 0; 124 const int rc = usb_device_control_read(pipe->wire, 125 pipe->endpoint_no, setup_packet, buffer, buffer_size, &act_size); 126 127 if (rc == ESTALL) { 128 clear_self_endpoint_halt(pipe); 129 } 130 131 if (rc == EOK && transfered_size != NULL) { 132 *transfered_size = act_size; 133 } 134 135 return rc; 136 } 137 /*----------------------------------------------------------------------------*/ 138 /** Request a control write transfer on an endpoint pipe. 139 * 140 * This function encapsulates all three stages of a control transfer. 141 * 142 * @param[in] pipe Pipe used for the transfer. 143 * @param[in] setup_buffer Buffer with the setup packet. 144 * @param[in] setup_buffer_size Size of the setup packet (in bytes). 145 * @param[in] data_buffer Buffer with data to be sent. 146 * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes). 147 * @return Error code. 148 */ 149 int usb_pipe_control_write(usb_pipe_t *pipe, 150 const void *setup_buffer, size_t setup_buffer_size, 151 const void *buffer, size_t buffer_size) 152 { 153 assert(pipe); 154 155 if ((setup_buffer == NULL) || (setup_buffer_size != 8)) { 156 return EINVAL; 157 } 158 159 if ((buffer == NULL) && (buffer_size > 0)) { 160 return EINVAL; 161 } 162 163 if ((buffer != NULL) && (buffer_size == 0)) { 164 return EINVAL; 165 } 166 167 if ((pipe->direction != USB_DIRECTION_BOTH) 168 || (pipe->transfer_type != USB_TRANSFER_CONTROL)) { 169 return EBADF; 170 } 171 172 uint64_t setup_packet; 173 memcpy(&setup_packet, setup_buffer, 8); 174 175 const int rc = usb_device_control_write(pipe->wire, 176 pipe->endpoint_no, setup_packet, buffer, buffer_size); 177 178 if (rc == ESTALL) { 179 clear_self_endpoint_halt(pipe); 180 } 181 182 return rc; 183 } 184 /*----------------------------------------------------------------------------*/ 185 /** Request a read (in) transfer on an endpoint pipe. 186 * 187 * @param[in] pipe Pipe used for the transfer. 188 * @param[out] buffer Buffer where to store the data. 189 * @param[in] size Size of the buffer (in bytes). 190 * @param[out] size_transfered Number of bytes that were actually transfered. 191 * @return Error code. 192 */ 193 int usb_pipe_read(usb_pipe_t *pipe, 194 void *buffer, size_t size, size_t *size_transfered) 195 { 196 assert(pipe); 197 198 if (buffer == NULL) { 199 return EINVAL; 200 } 201 202 if (size == 0) { 203 return EINVAL; 204 } 205 206 if (pipe->direction != USB_DIRECTION_IN) { 207 return EBADF; 208 } 209 210 if (pipe->transfer_type == USB_TRANSFER_CONTROL) { 211 return EBADF; 212 } 213 214 /* Isochronous transfer are not supported (yet) */ 215 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 216 pipe->transfer_type != USB_TRANSFER_BULK) 217 return ENOTSUP; 218 219 size_t act_size = 0; 220 const int rc = usb_device_read(pipe->wire, 221 pipe->endpoint_no, buffer, size, &act_size); 222 223 if (rc == EOK && size_transfered != NULL) { 224 *size_transfered = act_size; 225 } 226 227 return rc; 228 } 229 /*----------------------------------------------------------------------------*/ 230 /** Request a write (out) transfer on an endpoint pipe. 231 * 232 * @param[in] pipe Pipe used for the transfer. 233 * @param[in] buffer Buffer with data to transfer. 234 * @param[in] size Size of the buffer (in bytes). 235 * @return Error code. 236 */ 237 int usb_pipe_write(usb_pipe_t *pipe, const void *buffer, size_t size) 238 { 239 assert(pipe); 240 241 if (buffer == NULL || size == 0) { 242 return EINVAL; 243 } 244 245 if (pipe->direction != USB_DIRECTION_OUT) { 246 return EBADF; 247 } 248 249 if (pipe->transfer_type == USB_TRANSFER_CONTROL) { 250 return EBADF; 251 } 252 253 /* Isochronous transfer are not supported (yet) */ 254 if (pipe->transfer_type != USB_TRANSFER_INTERRUPT && 255 pipe->transfer_type != USB_TRANSFER_BULK) 256 return ENOTSUP; 257 258 return usb_device_write(pipe->wire, 259 pipe->endpoint_no, buffer, size); 260 } 261 /*----------------------------------------------------------------------------*/ 262 /** Initialize USB endpoint pipe. 263 * 264 * @param pipe Endpoint pipe to be initialized. 265 * @param connection Connection to the USB device backing this pipe (the wire). 266 * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15). 267 * @param transfer_type Transfer type (e.g. interrupt or bulk). 268 * @param max_packet_size Maximum packet size in bytes. 269 * @param direction Endpoint direction (in/out). 270 * @return Error code. 271 */ 272 int usb_pipe_initialize(usb_pipe_t *pipe, 273 usb_device_connection_t *connection, usb_endpoint_t endpoint_no, 274 usb_transfer_type_t transfer_type, size_t max_packet_size, 275 usb_direction_t direction) 276 { 277 assert(pipe); 278 assert(connection); 279 280 pipe->wire = connection; 281 pipe->endpoint_no = endpoint_no; 282 pipe->transfer_type = transfer_type; 283 pipe->max_packet_size = max_packet_size; 284 pipe->direction = direction; 285 pipe->auto_reset_halt = false; 286 287 return EOK; 288 } 289 /*----------------------------------------------------------------------------*/ 290 /** Initialize USB endpoint pipe as the default zero control pipe. 291 * 292 * @param pipe Endpoint pipe to be initialized. 293 * @param connection Connection to the USB device backing this pipe (the wire). 294 * @return Error code. 295 */ 296 int usb_pipe_initialize_default_control(usb_pipe_t *pipe, 297 usb_device_connection_t *connection) 298 { 299 assert(pipe); 300 assert(connection); 301 302 int rc = usb_pipe_initialize(pipe, connection, 0, USB_TRANSFER_CONTROL, 303 CTRL_PIPE_MIN_PACKET_SIZE, USB_DIRECTION_BOTH); 304 305 pipe->auto_reset_halt = true; 306 307 return rc; 308 } 309 /*----------------------------------------------------------------------------*/ 310 /** Register endpoint with the host controller. 311 * 312 * @param pipe Pipe to be registered. 313 * @param interval Polling interval. 314 * @return Error code. 315 */ 316 int usb_pipe_register(usb_pipe_t *pipe, unsigned interval) 317 { 318 assert(pipe); 319 assert(pipe->wire); 320 321 return usb_device_register_endpoint(pipe->wire, 322 pipe->endpoint_no, pipe->transfer_type, 323 pipe->direction, pipe->max_packet_size, interval); 324 } 325 /*----------------------------------------------------------------------------*/ 326 /** Revert endpoint registration with the host controller. 327 * 328 * @param pipe Pipe to be unregistered. 329 * @return Error code. 330 */ 331 int usb_pipe_unregister(usb_pipe_t *pipe) 332 { 333 assert(pipe); 334 assert(pipe->wire); 335 336 return usb_device_unregister_endpoint(pipe->wire, 337 pipe->endpoint_no, pipe->direction); 194 return usb_device_connection_initialize(dev_connection, 195 hc_connection->hc_handle, (usb_address_t) 0); 196 } 197 198 /** Prepare pipe for a long transfer. 199 * 200 * By a long transfer is mean transfer consisting of several 201 * requests to the HC. 202 * Calling such function is optional and it has positive effect of 203 * improved performance because IPC session is initiated only once. 204 * 205 * @param pipe Pipe over which the transfer will happen. 206 * @return Error code. 207 */ 208 void usb_pipe_start_long_transfer(usb_pipe_t *pipe) 209 { 210 (void) pipe_add_ref(pipe, true); 211 } 212 213 /** Terminate a long transfer on a pipe. 214 * 215 * @see usb_pipe_start_long_transfer 216 * 217 * @param pipe Pipe where to end the long transfer. 218 */ 219 void usb_pipe_end_long_transfer(usb_pipe_t *pipe) 220 { 221 pipe_drop_ref(pipe); 338 222 } 339 223 -
uspace/lib/usbdev/src/pipesinit.c
r153cc76a r2f0dd2a 31 31 */ 32 32 /** @file 33 * Non trivial initialization of endpoint pipes.33 * Initialization of endpoint pipes. 34 34 * 35 35 */ … … 38 38 #include <usb/dev/dp.h> 39 39 #include <usb/dev/request.h> 40 #include <usbhc_iface.h> 40 41 #include <errno.h> 41 42 #include <assert.h> 42 43 44 #define CTRL_PIPE_MIN_PACKET_SIZE 8 43 45 #define DEV_DESCR_MAX_PACKET_SIZE_OFFSET 7 46 44 47 45 48 #define NESTING(parentname, childname) \ … … 324 327 325 328 return EOK; 329 } 330 331 /** Initialize USB endpoint pipe. 332 * 333 * @param pipe Endpoint pipe to be initialized. 334 * @param connection Connection to the USB device backing this pipe (the wire). 335 * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15). 336 * @param transfer_type Transfer type (e.g. interrupt or bulk). 337 * @param max_packet_size Maximum packet size in bytes. 338 * @param direction Endpoint direction (in/out). 339 * @return Error code. 340 */ 341 int usb_pipe_initialize(usb_pipe_t *pipe, 342 usb_device_connection_t *connection, usb_endpoint_t endpoint_no, 343 usb_transfer_type_t transfer_type, size_t max_packet_size, 344 usb_direction_t direction) 345 { 346 assert(pipe); 347 assert(connection); 348 349 fibril_mutex_initialize(&pipe->guard); 350 pipe->wire = connection; 351 pipe->hc_sess = NULL; 352 fibril_mutex_initialize(&pipe->hc_sess_mutex); 353 pipe->endpoint_no = endpoint_no; 354 pipe->transfer_type = transfer_type; 355 pipe->max_packet_size = max_packet_size; 356 pipe->direction = direction; 357 pipe->refcount = 0; 358 pipe->refcount_soft = 0; 359 pipe->auto_reset_halt = false; 360 361 return EOK; 362 } 363 364 365 /** Initialize USB endpoint pipe as the default zero control pipe. 366 * 367 * @param pipe Endpoint pipe to be initialized. 368 * @param connection Connection to the USB device backing this pipe (the wire). 369 * @return Error code. 370 */ 371 int usb_pipe_initialize_default_control(usb_pipe_t *pipe, 372 usb_device_connection_t *connection) 373 { 374 assert(pipe); 375 assert(connection); 376 377 int rc = usb_pipe_initialize(pipe, connection, 378 0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE, 379 USB_DIRECTION_BOTH); 380 381 pipe->auto_reset_halt = true; 382 383 return rc; 326 384 } 327 385 … … 377 435 } 378 436 437 /** Register endpoint with the host controller. 438 * 439 * @param pipe Pipe to be registered. 440 * @param interval Polling interval. 441 * @param hc_connection Connection to the host controller (must be opened). 442 * @return Error code. 443 */ 444 int usb_pipe_register(usb_pipe_t *pipe, unsigned interval, 445 usb_hc_connection_t *hc_connection) 446 { 447 assert(pipe); 448 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; 462 } 463 464 /** Revert endpoint registration with the host controller. 465 * 466 * @param pipe Pipe to be unregistered. 467 * @param hc_connection Connection to the host controller (must be opened). 468 * @return Error code. 469 */ 470 int usb_pipe_unregister(usb_pipe_t *pipe, 471 usb_hc_connection_t *hc_connection) 472 { 473 assert(pipe); 474 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, 484 pipe->wire->address, pipe->endpoint_no, pipe->direction); 485 async_exchange_end(exch); 486 487 return ret; 488 } 489 379 490 /** 380 491 * @} -
uspace/lib/usbdev/src/recognise.c
r153cc76a r2f0dd2a 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); 47 52 48 53 /** DDF operations of child devices. */ … … 324 329 } 325 330 326 /** Index to append after device name for uniqueness. */ 327 static atomic_t device_name_index = {0}; 328 const size_t this_device_name_index = 329 (size_t) atomic_preinc(&device_name_index); 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); 330 334 331 335 ddf_fun_t *child = NULL; -
uspace/lib/usbhost/include/usb/host/endpoint.h
r153cc76a r2f0dd2a 95 95 /** list_get_instance wrapper. 96 96 * @param item Pointer to link member. 97 * @return Pointer to en dpoint_t structure.97 * @return Pointer to enpoint_t structure. 98 98 */ 99 99 static inline endpoint_t * endpoint_get_instance(link_t *item) 100 100 { 101 return item ? list_get_instance(item, endpoint_t, link) : NULL;101 return list_get_instance(item, endpoint_t, link); 102 102 } 103 103 #endif -
uspace/lib/usbhost/include/usb/host/usb_device_manager.h
r153cc76a r2f0dd2a 59 59 devman_handle_t handle; /**< Devman handle of the device. */ 60 60 } devices[USB_ADDRESS_COUNT]; 61 /** Maximum speed allowed. */62 61 usb_speed_t max_speed; 63 /** Protect access to members. */64 62 fibril_mutex_t guard; 65 63 /** The last reserved address */ -
uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h
r153cc76a r2f0dd2a 65 65 */ 66 66 size_t setup_size; 67 /** Actually used portion of the buffer */ 68 size_t transfered_size; 69 /** Indicates success/failure of the communication */ 70 int error; 67 71 /** Host controller function, passed to callback function */ 68 72 ddf_fun_t *fun; 69 70 /** Actually used portion of the buffer71 * This member is never accessed by functions provided in this header,72 * with the exception of usb_transfer_batch_finish. For external use.73 */74 size_t transfered_size;75 /** Indicates success/failure of the communication76 * This member is never accessed by functions provided in this header,77 * with the exception of usb_transfer_batch_finish. For external use.78 */79 int error;80 73 81 74 /** Driver specific data */ … … 113 106 void usb_transfer_batch_destroy(const usb_transfer_batch_t *instance); 114 107 115 void usb_transfer_batch_finish _error(const usb_transfer_batch_t *instance,116 const void* data, size_t size , int error);108 void usb_transfer_batch_finish(const usb_transfer_batch_t *instance, 109 const void* data, size_t size); 117 110 /*----------------------------------------------------------------------------*/ 118 /** Finish batch using stored error value and transferred size.111 /** Override error value and finishes transfer. 119 112 * 120 113 * @param[in] instance Batch structure to use. 121 114 * @param[in] data Data to copy to the output buffer. 115 * @param[in] size Size of @p data. 116 * @param[in] error Set batch status to this error value. 122 117 */ 123 static inline void usb_transfer_batch_finish (124 const usb_transfer_batch_t *instance, const void* data)118 static inline void usb_transfer_batch_finish_error( 119 usb_transfer_batch_t *instance, const void* data, size_t size, int error) 125 120 { 126 121 assert(instance); 127 usb_transfer_batch_finish_error(128 instance, data, instance->transfered_size, instance->error);122 instance->error = error; 123 usb_transfer_batch_finish(instance, data, size); 129 124 } 130 125 /*----------------------------------------------------------------------------*/ -
uspace/lib/usbhost/src/iface.c
r153cc76a r2f0dd2a 39 39 #include <usb/host/hcd.h> 40 40 41 /** Prepare generic usb_transfer_batch and schedule it.42 * @param fun DDF fun43 * @param target address and endpoint number.44 * @param setup_data Data to use in setup stage (Control communication type)45 * @param in Callback for device to host communication.46 * @param out Callback for host to device communication.47 * @param arg Callback parameter.48 * @param name Communication identifier (for nicer output).49 * @return Error code.50 */51 41 static inline int send_batch( 52 42 ddf_fun_t *fun, usb_target_t target, usb_direction_t direction, … … 99 89 } 100 90 /*----------------------------------------------------------------------------*/ 101 /** Calls ep_add_hook upon endpoint registration.102 * @param ep Endpoint to be registered.103 * @param arg hcd_t in disguise.104 * @return Error code.105 */106 91 static int register_helper(endpoint_t *ep, void *arg) 107 92 { … … 114 99 } 115 100 /*----------------------------------------------------------------------------*/ 116 /** Calls ep_remove_hook upon endpoint removal.117 * @param ep Endpoint to be unregistered.118 * @param arg hcd_t in disguise.119 */120 101 static void unregister_helper(endpoint_t *ep, void *arg) 121 102 { … … 127 108 } 128 109 /*----------------------------------------------------------------------------*/ 129 /** Calls ep_remove_hook upon endpoint removal. Prints warning.130 * @param ep Endpoint to be unregistered.131 * @param arg hcd_t in disguise.132 */133 110 static void unregister_helper_warn(endpoint_t *ep, void *arg) 134 111 { … … 142 119 } 143 120 /*----------------------------------------------------------------------------*/ 144 /** Request address interface function .145 * 146 * @param[in] fun DDF function that was called. 147 * @param[in] address Pointer to preferred USBaddress.121 /** Request address interface function 122 * 123 * @param[in] fun DDF function that was called. 124 * @param[in] speed Speed to associate with the new default address. 148 125 * @param[out] address Place to write a new address. 149 * @param[in] strict Fail if the preferred address is not available.150 * @param[in] speed Speed to associate with the new default address.151 126 * @return Error code. 152 127 */ … … 165 140 } 166 141 /*----------------------------------------------------------------------------*/ 167 /** Bind address interface function .142 /** Bind address interface function 168 143 * 169 144 * @param[in] fun DDF function that was called. … … 173 148 */ 174 149 static int bind_address( 175 150 ddf_fun_t *fun, usb_address_t address, devman_handle_t handle) 176 151 { 177 152 assert(fun); … … 201 176 } 202 177 /*----------------------------------------------------------------------------*/ 203 /** Release address interface function .178 /** Release address interface function 204 179 * 205 180 * @param[in] fun DDF function that was called. … … 219 194 } 220 195 /*----------------------------------------------------------------------------*/ 221 /** Register endpoint interface function.222 * @param fun DDF function.223 * @param address USB address of the device.224 * @param endpoint USB endpoint number to be registered.225 * @param transfer_type Endpoint's transfer type.226 * @param direction USB communication direction the endpoint is capable of.227 * @param max_packet_size Maximu size of packets the endpoint accepts.228 * @param interval Preferred timeout between communication.229 * @return Error code.230 */231 196 static int register_endpoint( 232 197 ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint, 233 198 usb_transfer_type_t transfer_type, usb_direction_t direction, 234 size_t max_packet_size, unsigned int erval)199 size_t max_packet_size, unsigned int interval) 235 200 { 236 201 assert(fun); … … 255 220 } 256 221 /*----------------------------------------------------------------------------*/ 257 /** Unregister endpoint interface function.258 * @param fun DDF function.259 * @param address USB address of the endpoint.260 * @param endpoint USB endpoint number.261 * @param direction Communication direction of the enpdoint to unregister.262 * @return Error code.263 */264 222 static int unregister_endpoint( 265 223 ddf_fun_t *fun, usb_address_t address, … … 275 233 } 276 234 /*----------------------------------------------------------------------------*/ 277 /** Inbound communication interface function.278 * @param fun DDF function.279 * @param target Communication target.280 * @param setup_data Data to use in setup stage (control transfers).281 * @param data Pointer to data buffer.282 * @param size Size of the data buffer.283 * @param callback Function to call on communication end.284 * @param arg Argument passed to the callback function.285 * @return Error code.286 */287 235 static int usb_read(ddf_fun_t *fun, usb_target_t target, uint64_t setup_data, 288 236 uint8_t *data, size_t size, usbhc_iface_transfer_in_callback_t callback, … … 293 241 } 294 242 /*----------------------------------------------------------------------------*/ 295 /** Outbound communication interface function.296 * @param fun DDF function.297 * @param target Communication target.298 * @param setup_data Data to use in setup stage (control transfers).299 * @param data Pointer to data buffer.300 * @param size Size of the data buffer.301 * @param callback Function to call on communication end.302 * @param arg Argument passed to the callback function.303 * @return Error code.304 */305 243 static int usb_write(ddf_fun_t *fun, usb_target_t target, uint64_t setup_data, 306 244 const uint8_t *data, size_t size, … … 311 249 } 312 250 /*----------------------------------------------------------------------------*/ 313 /** usbhc Interface implementation using hcd_t from libusbhost library. */314 251 usbhc_iface_t hcd_iface = { 315 252 .request_address = request_address, -
uspace/lib/usbhost/src/usb_device_manager.c
r153cc76a r2f0dd2a 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 28 29 /** @addtogroup libusbhost 29 30 * @{ … … 40 41 * 41 42 * @param[in] instance Device manager structure to use. 43 * @param[in] speed Speed of the device requiring address. 42 44 * @return Free address, or error code. 43 45 */ … … 131 133 * @param[in] handle Devman handle of the device. 132 134 * @return Error code. 133 * @note Won't accept binding for default address.134 135 */ 135 136 int usb_device_manager_bind_address(usb_device_manager_t *instance, … … 183 184 } 184 185 /*----------------------------------------------------------------------------*/ 185 /** Find USB address associated with the device .186 /** Find USB address associated with the device 186 187 * 187 188 * @param[in] instance Device manager structure to use. … … 207 208 /*----------------------------------------------------------------------------*/ 208 209 /** Find devman handle and speed assigned to USB address. 210 * Intentionally refuse to work on default address. 209 211 * 210 212 * @param[in] instance Device manager structure to use. -
uspace/lib/usbhost/src/usb_endpoint_manager.c
r153cc76a r2f0dd2a 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 /** @addtogroup libusbhost29 * @{30 */31 /** @file32 * HC Endpoint management.33 */34 28 35 29 #include <bool.h> … … 62 56 } 63 57 /*----------------------------------------------------------------------------*/ 64 /** Get list that holds endp oints for given address.58 /** Get list that holds endpints for given address. 65 59 * @param instance usb_endpoint_manager structure, non-null. 66 60 * @param addr USB address, must be >= 0. … … 81 75 * @return Pointer to endpoint_t structure representing given communication 82 76 * target, NULL if there is no such endpoint registered. 83 * @note Assumes that the internal mutex is locked.84 77 */ 85 78 static endpoint_t * find_locked(usb_endpoint_manager_t *instance, … … 176 169 * 177 170 * Really ugly one. Resets toggle bit on all endpoints that need it. 178 * @TODO Use tools from libusbdev requests.h179 171 */ 180 172 void usb_endpoint_manager_reset_eps_if_need(usb_endpoint_manager_t *instance, … … 192 184 case 0x01: /* Clear Feature -- resets only cleared ep */ 193 185 /* Recipient is endpoint, value is zero (ENDPOINT_STALL) */ 194 // TODO Use macros in libusbdev requests.h195 186 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 196 187 fibril_mutex_lock(&instance->guard); … … 211 202 /* Recipient must be device, this resets all endpoints, 212 203 * In fact there should be no endpoints but EP 0 registered 213 * as different interfaces use different endpoints, 214 * unless you're changing configuration or alternative 215 * interface of an already setup device. */ 204 * as different interfaces use different endpoints. */ 216 205 if ((data[0] & 0xf) == 0) { 217 206 fibril_mutex_lock(&instance->guard); … … 396 385 } 397 386 /*----------------------------------------------------------------------------*/ 398 /** Unregister and destroy all endpoints using given address.399 * @param instance usb_endpoint_manager structure, non-null.400 * @param address USB address.401 * @param endpoint USB endpoint number.402 * @param direction Communication direction.403 * @param callback Function to call after unregister, before destruction.404 * @arg Argument to pass to the callback function.405 * @return Error code.406 */407 387 void usb_endpoint_manager_remove_address(usb_endpoint_manager_t *instance, 408 388 usb_address_t address, void (*callback)(endpoint_t *, void *), void *arg) … … 423 403 fibril_mutex_unlock(&instance->guard); 424 404 } 425 /**426 * @}427 */ -
uspace/lib/usbhost/src/usb_transfer_batch.c
r153cc76a r2f0dd2a 33 33 */ 34 34 #include <errno.h> 35 #include < macros.h>35 #include <str_error.h> 36 36 37 37 #include <usb/usb.h> … … 48 48 * @param func_in callback on IN transfer completion. 49 49 * @param func_out callback on OUT transfer completion. 50 * @param fun DDF function (passed to callback function).51 50 * @param arg Argument to pass to the callback function. 52 51 * @param private_data driver specific per batch data. … … 122 121 * @param[in] data Data to copy to the output buffer. 123 122 * @param[in] size Size of @p data. 124 * @param[in] error Error value to use.125 123 */ 126 void usb_transfer_batch_finish _error(const usb_transfer_batch_t *instance,127 const void *data, size_t size, int error)124 void usb_transfer_batch_finish( 125 const usb_transfer_batch_t *instance, const void *data, size_t size) 128 126 { 129 127 assert(instance); … … 135 133 /* Check for commands that reset toggle bit */ 136 134 if (instance->ep->transfer_type == USB_TRANSFER_CONTROL 137 && error == EOK) {135 && instance->error == EOK) { 138 136 const usb_target_t target = 139 137 {{ instance->ep->address, instance->ep->endpoint }}; … … 141 139 instance->setup_buffer); 142 140 } 143 instance->callback_out(instance->fun, error, instance->arg); 141 instance->callback_out(instance->fun, 142 instance->error, instance->arg); 144 143 } 145 144 146 145 if (instance->callback_in) { 147 146 /* We care about the data and there are some to copy */ 148 const size_t safe_size = min(size, instance->buffer_size);149 147 if (data) { 150 memcpy(instance->buffer, data, safe_size); 148 const size_t min_size = size < instance->buffer_size 149 ? size : instance->buffer_size; 150 memcpy(instance->buffer, data, min_size); 151 151 } 152 instance->callback_in(instance->fun, error,153 safe_size, instance->arg);152 instance->callback_in(instance->fun, instance->error, 153 instance->transfered_size, instance->arg); 154 154 } 155 155 }
Note:
See TracChangeset
for help on using the changeset viewer.