Changeset 7e1b130 in mainline for uspace/drv/bus/usb/ohci
- Timestamp:
- 2011-12-23T18:13:33Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 3819ce5, b39eb79, f0b74b2
- Parents:
- 2f0dd2a (diff), 153cc76a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/drv/bus/usb/ohci
- Files:
-
- 6 edited
-
hc.c (modified) (3 diffs)
-
ohci.c (modified) (2 diffs)
-
ohci_batch.c (modified) (12 diffs)
-
ohci_batch.h (modified) (2 diffs)
-
pci.c (modified) (3 diffs)
-
root_hub.c (modified) (20 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/hc.c
r2f0dd2a r7e1b130 137 137 return ret; 138 138 } 139 usb_device_manager_bind_address(&instance->generic.dev_manager,140 instance->rh.address, hub_fun->handle);141 139 142 140 #define CHECK_RET_UNREG_RETURN(ret, message...) \ … … 150 148 return ret; \ 151 149 } else (void)0 150 152 151 ret = usb_endpoint_manager_add_ep( 153 152 &instance->generic.ep_manager, instance->rh.address, 0, … … 165 164 CHECK_RET_UNREG_RETURN(ret, 166 165 "Failed to bind root hub function: %s.\n", str_error(ret)); 166 167 ret = usb_device_manager_bind_address(&instance->generic.dev_manager, 168 instance->rh.address, hub_fun->handle); 169 if (ret != EOK) 170 usb_log_warning("Failed to bind root hub address: %s.\n", 171 str_error(ret)); 167 172 168 173 return EOK; -
uspace/drv/bus/usb/ohci/ohci.c
r2f0dd2a r7e1b130 140 140 int device_setup_ohci(ddf_dev_t *device) 141 141 { 142 assert(device); 143 144 ohci_t *instance = malloc(sizeof(ohci_t)); 142 if (device == NULL) 143 return EBADMEM; 144 145 ohci_t *instance = ddf_dev_data_alloc(device,sizeof(ohci_t)); 145 146 if (instance == NULL) { 146 147 usb_log_error("Failed to allocate OHCI driver.\n"); 147 148 return ENOMEM; 148 149 } 149 instance->rh_fun = NULL;150 instance->hc_fun = NULL;151 150 152 151 #define CHECK_RET_DEST_FREE_RETURN(ret, message...) \ 153 152 if (ret != EOK) { \ 154 153 if (instance->hc_fun) { \ 154 instance->hc_fun->driver_data = NULL; \ 155 155 ddf_fun_destroy(instance->hc_fun); \ 156 156 } \ 157 157 if (instance->rh_fun) { \ 158 instance->rh_fun->driver_data = NULL; \ 158 159 ddf_fun_destroy(instance->rh_fun); \ 159 160 } \ 160 free(instance); \161 161 usb_log_error(message); \ 162 162 return ret; \ … … 219 219 "Failed to init ohci_hcd: %s.\n", str_error(ret)); 220 220 221 device->driver_data = instance;222 223 221 #define CHECK_RET_FINI_RETURN(ret, message...) \ 224 222 if (ret != EOK) { \ -
uspace/drv/bus/usb/ohci/ohci_batch.c
r2f0dd2a r7e1b130 34 34 #include <errno.h> 35 35 #include <str_error.h> 36 #include <macros.h> 36 37 37 38 #include <usb/usb.h> … … 53 54 return; 54 55 if (ohci_batch->tds) { 56 const ohci_endpoint_t *ohci_ep = 57 ohci_endpoint_get(ohci_batch->usb_batch->ep); 58 assert(ohci_ep); 55 59 for (unsigned i = 0; i < ohci_batch->td_count; ++i) { 56 if ( i != ohci_batch->leave_td)60 if (ohci_batch->tds[i] != ohci_ep->td) 57 61 free32(ohci_batch->tds[i]); 58 62 } … … 64 68 } 65 69 /*----------------------------------------------------------------------------*/ 70 /** Finishes usb_transfer_batch and destroys the structure. 71 * 72 * @param[in] uhci_batch Instance to finish and destroy. 73 */ 66 74 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *ohci_batch) 67 75 { … … 69 77 assert(ohci_batch->usb_batch); 70 78 usb_transfer_batch_finish(ohci_batch->usb_batch, 71 ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size, 72 ohci_batch->usb_batch->buffer_size); 79 ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size); 73 80 ohci_transfer_batch_dispose(ohci_batch); 74 81 } 75 82 /*----------------------------------------------------------------------------*/ 83 /** Allocate memory and initialize internal data structure. 84 * 85 * @param[in] usb_batch Pointer to generic USB batch structure. 86 * @return Valid pointer if all structures were successfully created, 87 * NULL otherwise. 88 * 89 * Determines the number of needed transfer descriptors (TDs). 90 * Prepares a transport buffer (that is accessible by the hardware). 91 * Initializes parameters needed for the transfer and callback. 92 */ 76 93 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *usb_batch) 77 94 { … … 105 122 ohci_batch->ed = ohci_endpoint_get(usb_batch->ep)->ed; 106 123 ohci_batch->tds[0] = ohci_endpoint_get(usb_batch->ep)->td; 107 ohci_batch->leave_td = 0;108 124 109 125 for (unsigned i = 1; i <= ohci_batch->td_count; ++i) { … … 152 168 * completes with the last TD. 153 169 */ 154 bool ohci_transfer_batch_is_complete( ohci_transfer_batch_t *ohci_batch)170 bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *ohci_batch) 155 171 { 156 172 assert(ohci_batch); … … 174 190 175 191 /* Assume we will leave the last(unused) TD behind */ 176 ohci_batch->leave_td = ohci_batch->td_count;192 unsigned leave_td = ohci_batch->td_count; 177 193 178 194 /* Check all TDs */ … … 212 228 * It will be the one TD we leave behind. 213 229 */ 214 ohci_batch->leave_td = i + 1;230 leave_td = i + 1; 215 231 216 232 /* Check TD assumption */ 217 const uint32_t pa = addr_to_phys(218 ohci_batch->tds[ohci_batch->leave_td]);219 assert((ohci_batch->ed->td_head & ED_TD TAIL_PTR_MASK)233 const uint32_t pa = 234 addr_to_phys(ohci_batch->tds[leave_td]); 235 assert((ohci_batch->ed->td_head & ED_TDHEAD_PTR_MASK) 220 236 == pa); 221 237 222 238 ed_set_tail_td(ohci_batch->ed, 223 ohci_batch->tds[ ohci_batch->leave_td]);239 ohci_batch->tds[leave_td]); 224 240 225 241 /* Clear possible ED HALT */ … … 234 250 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->usb_batch->ep); 235 251 assert(ohci_ep); 236 ohci_ep->td = ohci_batch->tds[ ohci_batch->leave_td];252 ohci_ep->td = ohci_batch->tds[leave_td]; 237 253 238 254 /* Make sure that we are leaving the right TD behind */ … … 248 264 * @param[in] ohci_batch Batch structure to use 249 265 */ 250 void ohci_transfer_batch_commit( ohci_transfer_batch_t *ohci_batch)266 void ohci_transfer_batch_commit(const ohci_transfer_batch_t *ohci_batch) 251 267 { 252 268 assert(ohci_batch); … … 295 311 while (remain_size > 0) { 296 312 const size_t transfer_size = 297 remain_size > OHCI_TD_MAX_TRANSFER ? 298 OHCI_TD_MAX_TRANSFER : remain_size; 313 min(remain_size, OHCI_TD_MAX_TRANSFER); 299 314 toggle = 1 - toggle; 300 315 … … 378 393 } 379 394 /*----------------------------------------------------------------------------*/ 395 /** Transfer setup table. */ 380 396 static void (*const batch_setup[])(ohci_transfer_batch_t*, usb_direction_t) = 381 397 { -
uspace/drv/bus/usb/ohci/ohci_batch.h
r2f0dd2a r7e1b130 53 53 /** Number of TDs used by the transfer */ 54 54 size_t td_count; 55 /** Dummy TD to be left at the ED and used by the next transfer */56 size_t leave_td;57 55 /** Data buffer, must be accessible by the OHCI hw. */ 58 56 char *device_buffer; … … 62 60 63 61 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *batch); 64 bool ohci_transfer_batch_is_complete( ohci_transfer_batch_t *batch);65 void ohci_transfer_batch_commit( ohci_transfer_batch_t *batch);62 bool ohci_transfer_batch_is_complete(const ohci_transfer_batch_t *batch); 63 void ohci_transfer_batch_commit(const ohci_transfer_batch_t *batch); 66 64 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *batch); 67 65 /*----------------------------------------------------------------------------*/ -
uspace/drv/bus/usb/ohci/pci.c
r2f0dd2a r7e1b130 42 42 #include <ddi.h> 43 43 #include <libarch/ddi.h> 44 #include <device/hw_res .h>44 #include <device/hw_res_parsed.h> 45 45 46 46 #include <usb/debug.h> … … 61 61 { 62 62 assert(dev); 63 assert(mem_reg_address);64 assert(mem_reg_size);65 assert(irq_no);66 63 67 64 async_sess_t *parent_sess = … … 71 68 return ENOMEM; 72 69 73 hw_resource_list_t hw_resources; 74 int rc = hw_res_get_resource_list(parent_sess, &hw_resources); 70 hw_res_list_parsed_t hw_res; 71 hw_res_list_parsed_init(&hw_res); 72 const int ret = hw_res_get_list_parsed(parent_sess, &hw_res, 0); 75 73 async_hangup(parent_sess); 76 if (r c!= EOK) {77 return r c;74 if (ret != EOK) { 75 return ret; 78 76 } 79 77 80 uintptr_t mem_address = 0; 81 size_t mem_size = 0; 82 bool mem_found = false; 78 /* We want one irq and one mem range. */ 79 if (hw_res.irqs.count != 1 || hw_res.mem_ranges.count != 1) { 80 hw_res_list_parsed_clean(&hw_res); 81 return EINVAL; 82 } 83 83 84 int irq = 0; 85 bool irq_found = false; 84 if (mem_reg_address) 85 *mem_reg_address = hw_res.mem_ranges.ranges[0].address; 86 if (mem_reg_size) 87 *mem_reg_size = hw_res.mem_ranges.ranges[0].size; 88 if (irq_no) 89 *irq_no = hw_res.irqs.irqs[0]; 86 90 87 for (size_t i = 0; i < hw_resources.count; i++) { 88 hw_resource_t *res = &hw_resources.resources[i]; 89 switch (res->type) { 90 case INTERRUPT: 91 irq = res->res.interrupt.irq; 92 irq_found = true; 93 usb_log_debug2("Found interrupt: %d.\n", irq); 94 break; 95 case MEM_RANGE: 96 if (res->res.mem_range.address != 0 97 && res->res.mem_range.size != 0 ) { 98 mem_address = res->res.mem_range.address; 99 mem_size = res->res.mem_range.size; 100 usb_log_debug2("Found mem: %p %zu.\n", 101 (void *) mem_address, mem_size); 102 mem_found = true; 103 } 104 default: 105 break; 106 } 107 } 108 free(hw_resources.resources); 109 110 if (mem_found && irq_found) { 111 *mem_reg_address = mem_address; 112 *mem_reg_size = mem_size; 113 *irq_no = irq; 114 return EOK; 115 } 116 return ENOENT; 91 hw_res_list_parsed_clean(&hw_res); 92 return EOK; 117 93 } 118 94 -
uspace/drv/bus/usb/ohci/root_hub.c
r2f0dd2a r7e1b130 100 100 .attributes = USB_TRANSFER_INTERRUPT, 101 101 .descriptor_type = USB_DESCTYPE_ENDPOINT, 102 .endpoint_address = 1 +(1 << 7),102 .endpoint_address = 1 | (1 << 7), 103 103 .length = sizeof(usb_standard_endpoint_descriptor_t), 104 104 .max_packet_size = 2, … … 109 109 static void rh_init_descriptors(rh_t *instance); 110 110 static uint16_t create_interrupt_mask(const rh_t *instance); 111 static intget_status(const rh_t *instance, usb_transfer_batch_t *request);112 static intget_descriptor(const rh_t *instance, usb_transfer_batch_t *request);113 static intset_feature(const rh_t *instance, usb_transfer_batch_t *request);114 static intclear_feature(const rh_t *instance, usb_transfer_batch_t *request);111 static void get_status(const rh_t *instance, usb_transfer_batch_t *request); 112 static void get_descriptor(const rh_t *instance, usb_transfer_batch_t *request); 113 static void set_feature(const rh_t *instance, usb_transfer_batch_t *request); 114 static void clear_feature(const rh_t *instance, usb_transfer_batch_t *request); 115 115 static int set_feature_port( 116 116 const rh_t *instance, uint16_t feature, uint16_t port); 117 117 static int clear_feature_port( 118 118 const rh_t *instance, uint16_t feature, uint16_t port); 119 static intcontrol_request(rh_t *instance, usb_transfer_batch_t *request);119 static void control_request(rh_t *instance, usb_transfer_batch_t *request); 120 120 static inline void interrupt_request( 121 121 usb_transfer_batch_t *request, uint16_t mask, size_t size) 122 122 { 123 123 assert(request); 124 125 request->transfered_size = size;126 124 usb_transfer_batch_finish_error(request, &mask, size, EOK); 127 } 128 129 #define TRANSFER_OK(bytes) \ 125 usb_transfer_batch_destroy(request); 126 } 127 128 #define TRANSFER_END_DATA(request, data, bytes) \ 130 129 do { \ 131 request->transfered_size = bytes; \ 132 return EOK; \ 130 usb_transfer_batch_finish_error(request, data, bytes, EOK); \ 131 usb_transfer_batch_destroy(request); \ 132 return; \ 133 } while (0) 134 135 #define TRANSFER_END(request, error) \ 136 do { \ 137 usb_transfer_batch_finish_error(request, NULL, 0, error); \ 138 usb_transfer_batch_destroy(request); \ 139 return; \ 133 140 } while (0) 134 141 … … 212 219 case USB_TRANSFER_CONTROL: 213 220 usb_log_debug("Root hub got CONTROL packet\n"); 214 const int ret = control_request(instance, request); 215 usb_transfer_batch_finish_error(request, NULL, 0, ret); 221 control_request(instance, request); 216 222 break; 223 217 224 case USB_TRANSFER_INTERRUPT: 218 225 usb_log_debug("Root hub got INTERRUPT packet\n"); … … 221 228 const uint16_t mask = create_interrupt_mask(instance); 222 229 if (mask == 0) { 223 usb_log_debug("No changes.. \n");230 usb_log_debug("No changes...\n"); 224 231 instance->unfinished_interrupt_transfer = request; 225 fibril_mutex_unlock(&instance->guard); 226 return; 232 } else { 233 usb_log_debug("Processing changes...\n"); 234 interrupt_request( 235 request, mask, instance->interrupt_mask_size); 227 236 } 228 usb_log_debug("Processing changes...\n");229 interrupt_request(request, mask, instance->interrupt_mask_size);230 237 fibril_mutex_unlock(&instance->guard); 231 238 break; … … 233 240 default: 234 241 usb_log_error("Root hub got unsupported request.\n"); 235 usb_transfer_batch_finish_error(request, NULL, 0, EINVAL); 236 } 237 usb_transfer_batch_destroy(request); 242 TRANSFER_END(request, ENOTSUP); 243 } 238 244 } 239 245 /*----------------------------------------------------------------------------*/ … … 254 260 interrupt_request(instance->unfinished_interrupt_transfer, 255 261 mask, instance->interrupt_mask_size); 256 usb_transfer_batch_destroy(257 instance->unfinished_interrupt_transfer);258 262 instance->unfinished_interrupt_transfer = NULL; 259 263 } … … 384 388 * @return error code 385 389 */ 386 intget_status(const rh_t *instance, usb_transfer_batch_t *request)390 void get_status(const rh_t *instance, usb_transfer_batch_t *request) 387 391 { 388 392 assert(instance); 389 393 assert(request); 394 390 395 391 396 const usb_device_request_setup_packet_t *request_packet = 392 397 (usb_device_request_setup_packet_t*)request->setup_buffer; 393 398 394 if (request->buffer_size < 4) { 395 usb_log_error("Buffer too small for get status request.\n"); 396 return EOVERFLOW; 397 } 398 399 switch (request_packet->request_type) 400 { 401 case USB_HUB_REQ_TYPE_GET_HUB_STATUS: 399 402 /* Hub status: just filter relevant info from rh_status reg */ 400 if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) { 401 const uint32_t data = instance->registers->rh_status & 402 (RHS_LPS_FLAG | RHS_LPSC_FLAG | RHS_OCI_FLAG | RHS_OCIC_FLAG); 403 memcpy(request->buffer, &data, sizeof(data)); 404 TRANSFER_OK(sizeof(data)); 405 } 403 if (request->buffer_size < 4) { 404 usb_log_error("Buffer(%zu) too small for hub get " 405 "status request.\n", request->buffer_size); 406 TRANSFER_END(request, EOVERFLOW); 407 } else { 408 const uint32_t data = instance->registers->rh_status & 409 (RHS_LPS_FLAG | RHS_LPSC_FLAG 410 | RHS_OCI_FLAG | RHS_OCIC_FLAG); 411 TRANSFER_END_DATA(request, &data, sizeof(data)); 412 } 406 413 407 414 /* Copy appropriate rh_port_status register, OHCI designers were 408 415 * kind enough to make those bit values match USB specification */ 409 if (request_packet->request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) { 410 const unsigned port = request_packet->index; 411 if (port < 1 || port > instance->port_count) 412 return EINVAL; 413 414 const uint32_t data = 415 instance->registers->rh_port_status[port - 1]; 416 memcpy(request->buffer, &data, sizeof(data)); 417 TRANSFER_OK(sizeof(data)); 418 } 419 420 return ENOTSUP; 416 case USB_HUB_REQ_TYPE_GET_PORT_STATUS: 417 if (request->buffer_size < 4) { 418 usb_log_error("Buffer(%zu) too small for hub get " 419 "status request.\n", request->buffer_size); 420 TRANSFER_END(request, EOVERFLOW); 421 } else { 422 const unsigned port = request_packet->index; 423 if (port < 1 || port > instance->port_count) 424 TRANSFER_END(request, EINVAL); 425 426 const uint32_t data = 427 instance->registers->rh_port_status[port - 1]; 428 TRANSFER_END_DATA(request, &data, sizeof(data)); 429 } 430 case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE): 431 if (request->buffer_size < 2) { 432 usb_log_error("Buffer(%zu) too small for hub generic " 433 "get status request.\n", request->buffer_size); 434 TRANSFER_END(request, EOVERFLOW); 435 } else { 436 static const uint16_t data = 437 uint16_host2usb(USB_DEVICE_STATUS_SELF_POWERED); 438 TRANSFER_END_DATA(request, &data, sizeof(data)); 439 } 440 441 case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE): 442 /* Hubs are allowed to have only one interface */ 443 if (request_packet->index != 0) 444 TRANSFER_END(request, EINVAL); 445 /* Fall through, as the answer will be the same: 0x0000 */ 446 case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT): 447 /* Endpoint 0 (default control) and 1 (interrupt) */ 448 if (request_packet->index >= 2) 449 TRANSFER_END(request, EINVAL); 450 451 if (request->buffer_size < 2) { 452 usb_log_error("Buffer(%zu) too small for hub generic " 453 "get status request.\n", request->buffer_size); 454 TRANSFER_END(request, EOVERFLOW); 455 } else { 456 /* Endpoints are OK. (We don't halt) */ 457 static const uint16_t data = 0; 458 TRANSFER_END_DATA(request, &data, sizeof(data)); 459 } 460 461 default: 462 usb_log_error("Unsupported GET_STATUS request.\n"); 463 TRANSFER_END(request, ENOTSUP); 464 } 465 421 466 } 422 467 /*----------------------------------------------------------------------------*/ … … 430 475 * @return Error code 431 476 */ 432 intget_descriptor(const rh_t *instance, usb_transfer_batch_t *request)477 void get_descriptor(const rh_t *instance, usb_transfer_batch_t *request) 433 478 { 434 479 assert(instance); … … 437 482 const usb_device_request_setup_packet_t *setup_request = 438 483 (usb_device_request_setup_packet_t *) request->setup_buffer; 439 size_t size;440 const void *descriptor = NULL;441 484 const uint16_t setup_request_value = setup_request->value_high; 442 //(setup_request->value_low << 8);443 485 switch (setup_request_value) 444 486 { 445 487 case USB_DESCTYPE_HUB: 446 488 usb_log_debug2("USB_DESCTYPE_HUB\n"); 447 /* Hub descriptor was generated locally */448 descriptor = instance->descriptors.hub;449 size = instance->hub_descriptor_size;450 break;489 /* Hub descriptor was generated locally. 490 * Class specific request. */ 491 TRANSFER_END_DATA(request, instance->descriptors.hub, 492 instance->hub_descriptor_size); 451 493 452 494 case USB_DESCTYPE_DEVICE: 453 495 usb_log_debug2("USB_DESCTYPE_DEVICE\n"); 454 /* Device descriptor is shared (No one should ask for it)*/ 455 descriptor = &ohci_rh_device_descriptor; 456 size = sizeof(ohci_rh_device_descriptor); 457 break; 496 /* Device descriptor is shared 497 * (No one should ask for it, as the device is already setup) 498 * Standard USB device request. */ 499 TRANSFER_END_DATA(request, &ohci_rh_device_descriptor, 500 sizeof(ohci_rh_device_descriptor)); 458 501 459 502 case USB_DESCTYPE_CONFIGURATION: 460 503 usb_log_debug2("USB_DESCTYPE_CONFIGURATION\n"); 461 504 /* Start with configuration and add others depending on 462 * request size */ 463 descriptor = &instance->descriptors; 464 size = instance->descriptors.configuration.total_length; 465 break; 505 * request size. Standard USB request. */ 506 TRANSFER_END_DATA(request, &instance->descriptors, 507 instance->descriptors.configuration.total_length); 466 508 467 509 case USB_DESCTYPE_INTERFACE: 468 510 usb_log_debug2("USB_DESCTYPE_INTERFACE\n"); 469 511 /* Use local interface descriptor. There is one and it 470 * might be modified */471 descriptor = &instance->descriptors.interface;472 size = sizeof(instance->descriptors.interface);473 break;512 * might be modified. Hub driver should not ask or this 513 * descriptor as it is not part of standard requests set. */ 514 TRANSFER_END_DATA(request, &instance->descriptors.interface, 515 sizeof(instance->descriptors.interface)); 474 516 475 517 case USB_DESCTYPE_ENDPOINT: 476 518 /* Use local endpoint descriptor. There is one 477 * it might have max_packet_size field modified*/ 519 * it might have max_packet_size field modified. Hub driver 520 * should not ask for this descriptor as it is not part 521 * of standard requests set. */ 478 522 usb_log_debug2("USB_DESCTYPE_ENDPOINT\n"); 479 descriptor = &instance->descriptors.endpoint; 480 size = sizeof(instance->descriptors.endpoint); 481 break; 523 TRANSFER_END_DATA(request, &instance->descriptors.endpoint, 524 sizeof(instance->descriptors.endpoint)); 482 525 483 526 default: … … 489 532 setup_request_value, setup_request->index, 490 533 setup_request->length); 491 return EINVAL; 492 } 493 if (request->buffer_size < size) { 494 size = request->buffer_size; 495 } 496 497 memcpy(request->buffer, descriptor, size); 498 TRANSFER_OK(size); 534 TRANSFER_END(request, EINVAL); 535 } 536 537 TRANSFER_END(request, ENOTSUP); 499 538 } 500 539 /*----------------------------------------------------------------------------*/ … … 604 643 * @return error code 605 644 */ 606 intset_feature(const rh_t *instance, usb_transfer_batch_t *request)645 void set_feature(const rh_t *instance, usb_transfer_batch_t *request) 607 646 { 608 647 assert(instance); … … 615 654 case USB_HUB_REQ_TYPE_SET_PORT_FEATURE: 616 655 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 617 returnset_feature_port(instance,656 const int ret = set_feature_port(instance, 618 657 setup_request->value, setup_request->index); 658 TRANSFER_END(request, ret); 619 659 620 660 case USB_HUB_REQ_TYPE_SET_HUB_FEATURE: … … 623 663 * features. It makes no sense to SET either. */ 624 664 usb_log_error("Invalid HUB set feature request.\n"); 625 return ENOTSUP; 665 TRANSFER_END(request, ENOTSUP); 666 //TODO: Consider standard USB requests: REMOTE WAKEUP, ENDPOINT STALL 626 667 default: 627 668 usb_log_error("Invalid set feature request type: %d\n", 628 669 setup_request->request_type); 629 return EINVAL;670 TRANSFER_END(request, ENOTSUP); 630 671 } 631 672 } … … 640 681 * @return error code 641 682 */ 642 intclear_feature(const rh_t *instance, usb_transfer_batch_t *request)683 void clear_feature(const rh_t *instance, usb_transfer_batch_t *request) 643 684 { 644 685 assert(instance); … … 647 688 const usb_device_request_setup_packet_t *setup_request = 648 689 (usb_device_request_setup_packet_t *) request->setup_buffer; 649 650 request->transfered_size = 0;651 690 652 691 switch (setup_request->request_type) … … 654 693 case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE: 655 694 usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n"); 656 returnclear_feature_port(instance,695 const int ret = clear_feature_port(instance, 657 696 setup_request->value, setup_request->index); 697 TRANSFER_END(request, ret); 658 698 659 699 case USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE: … … 668 708 if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) { 669 709 instance->registers->rh_status = RHS_OCIC_FLAG; 670 TRANSFER_ OK(0);710 TRANSFER_END(request, EOK); 671 711 } 712 //TODO: Consider standard USB requests: REMOTE WAKEUP, ENDPOINT STALL 672 713 default: 673 714 usb_log_error("Invalid clear feature request type: %d\n", 674 715 setup_request->request_type); 675 return EINVAL;716 TRANSFER_END(request, ENOTSUP); 676 717 } 677 718 } … … 695 736 * @return error code 696 737 */ 697 intcontrol_request(rh_t *instance, usb_transfer_batch_t *request)738 void control_request(rh_t *instance, usb_transfer_batch_t *request) 698 739 { 699 740 assert(instance); … … 702 743 if (!request->setup_buffer) { 703 744 usb_log_error("Root hub received empty transaction!"); 704 return EINVAL;745 TRANSFER_END(request, EBADMEM); 705 746 } 706 747 707 748 if (sizeof(usb_device_request_setup_packet_t) > request->setup_size) { 708 749 usb_log_error("Setup packet too small\n"); 709 return EOVERFLOW;750 TRANSFER_END(request, EOVERFLOW); 710 751 } 711 752 … … 718 759 case USB_DEVREQ_GET_STATUS: 719 760 usb_log_debug("USB_DEVREQ_GET_STATUS\n"); 720 return get_status(instance, request); 761 get_status(instance, request); 762 break; 721 763 722 764 case USB_DEVREQ_GET_DESCRIPTOR: 723 765 usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n"); 724 return get_descriptor(instance, request); 766 get_descriptor(instance, request); 767 break; 725 768 726 769 case USB_DEVREQ_GET_CONFIGURATION: 727 770 usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n"); 728 if (request->buffer_size != 1)729 return EINVAL;730 request->buffer[0]= 1;731 TRANSFER_ OK(1);771 if (request->buffer_size == 0) 772 TRANSFER_END(request, EOVERFLOW); 773 static const uint8_t config = 1; 774 TRANSFER_END_DATA(request, &config, sizeof(config)); 732 775 733 776 case USB_DEVREQ_CLEAR_FEATURE: 734 usb_log_debug2(" Processing request without "735 "additional data\n");736 return clear_feature(instance, request);777 usb_log_debug2("USB_DEVREQ_CLEAR_FEATURE\n"); 778 clear_feature(instance, request); 779 break; 737 780 738 781 case USB_DEVREQ_SET_FEATURE: 739 usb_log_debug2(" Processing request without "740 "additional data\n");741 return set_feature(instance, request);782 usb_log_debug2("USB_DEVREQ_SET_FEATURE\n"); 783 set_feature(instance, request); 784 break; 742 785 743 786 case USB_DEVREQ_SET_ADDRESS: 744 usb_log_debug("USB_DEVREQ_SET_ADDRESS\n"); 787 usb_log_debug("USB_DEVREQ_SET_ADDRESS: %u\n", 788 setup_request->value); 789 if (uint16_usb2host(setup_request->value) > 127) 790 TRANSFER_END(request, EINVAL); 791 745 792 instance->address = setup_request->value; 746 TRANSFER_ OK(0);793 TRANSFER_END(request, EOK); 747 794 748 795 case USB_DEVREQ_SET_CONFIGURATION: 749 usb_log_debug("USB_DEVREQ_SET_CONFIGURATION\n"); 750 /* We don't need to do anything */ 751 TRANSFER_OK(0); 752 753 case USB_DEVREQ_SET_DESCRIPTOR: /* Not supported by OHCI RH */ 796 usb_log_debug("USB_DEVREQ_SET_CONFIGURATION: %u\n", 797 setup_request->value); 798 /* We have only one configuration, it's number is 1 */ 799 if (uint16_usb2host(setup_request->value) != 1) 800 TRANSFER_END(request, EINVAL); 801 TRANSFER_END(request, EOK); 802 803 /* Both class specific and std is optional for hubs */ 804 case USB_DEVREQ_SET_DESCRIPTOR: 805 /* Hubs have only one interface GET/SET is not supported */ 806 case USB_DEVREQ_GET_INTERFACE: 807 case USB_DEVREQ_SET_INTERFACE: 754 808 default: 809 /* Hub class GET_STATE(2) falls in here too. */ 755 810 usb_log_error("Received unsupported request: %d.\n", 756 811 setup_request->request); 757 return ENOTSUP; 758 } 759 } 760 812 TRANSFER_END(request, ENOTSUP); 813 } 814 } 761 815 /** 762 816 * @}
Note:
See TracChangeset
for help on using the changeset viewer.
