Changeset a8ac368 in mainline for uspace/drv/ohci/root_hub.c
- Timestamp:
- 2011-03-29T20:08:53Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- fc883bb
- Parents:
- 0d92638 (diff), 51e5608 (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/ohci/root_hub.c
r0d92638 ra8ac368 39 39 40 40 #include "root_hub.h" 41 #include "usb/classes/classes.h" 42 #include <usb/request.h> 43 #include <usb/classes/hub.h> 44 45 /** 46 * standart device descriptor for ohci root hub 47 */ 48 static const usb_standard_device_descriptor_t ohci_rh_device_descriptor = 49 { 50 .configuration_count = 1, 51 .descriptor_type = USB_DESCTYPE_DEVICE, 52 .device_class = USB_CLASS_HUB, 53 .device_protocol = 0, 54 .device_subclass = 0, 55 .device_version = 0, 56 .length = sizeof(usb_standard_device_descriptor_t), 57 /// \TODO this value is guessed 58 .max_packet_size = 8, 59 .vendor_id = 0x16db, 60 .product_id = 0x0001, 61 /// \TODO these values migt be different 62 .str_serial_number = 0, 63 .usb_spec_version = 0, 64 }; 65 66 /** 67 * standart configuration descriptor with filled common values 68 * for ohci root hubs 69 */ 70 static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor = 71 { 72 /// \TODO some values are default or guessed 73 .attributes = 1<<7, 74 .configuration_number = 1, 75 .descriptor_type = USB_DESCTYPE_CONFIGURATION, 76 .interface_count = 1, 77 .length = sizeof(usb_standard_configuration_descriptor_t), 78 .max_power = 100, 79 .str_configuration = 0, 80 }; 81 82 /** 83 * standart ohci root hub interface descriptor 84 */ 85 static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor = 86 { 87 .alternate_setting = 0, 88 .descriptor_type = USB_DESCTYPE_INTERFACE, 89 .endpoint_count = 1, 90 .interface_class = USB_CLASS_HUB, 91 /// \TODO is this correct? 92 .interface_number = 1, 93 .interface_protocol = 0, 94 .interface_subclass = 0, 95 .length = sizeof(usb_standard_interface_descriptor_t), 96 .str_interface = 0, 97 }; 98 99 /** 100 * standart ohci root hub endpoint descriptor 101 */ 102 static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor = 103 { 104 .attributes = USB_TRANSFER_INTERRUPT, 105 .descriptor_type = USB_DESCTYPE_ENDPOINT, 106 .endpoint_address = 1 + (1<<7), 107 .length = sizeof(usb_standard_endpoint_descriptor_t), 108 .max_packet_size = 8, 109 .poll_interval = 255, 110 }; 41 111 42 112 /** Root hub initialization … … 50 120 instance->device = dev; 51 121 122 52 123 usb_log_info("OHCI root hub with %d ports.\n", regs->rh_desc_a & 0xff); 53 124 125 //start generic usb hub driver 126 54 127 /* TODO: implement */ 55 128 return EOK; 56 129 } 57 130 /*----------------------------------------------------------------------------*/ 131 132 /** 133 * create answer to port status_request 134 * 135 * Copy content of corresponding port status register to answer buffer. 136 * 137 * @param instance root hub instance 138 * @param port port number, counted from 1 139 * @param request structure containing both request and response information 140 * @return error code 141 */ 142 static int process_get_port_status_request(rh_t *instance, uint16_t port, 143 usb_transfer_batch_t * request){ 144 if(port<1 || port>instance->port_count) 145 return EINVAL; 146 uint32_t * uint32_buffer = (uint32_t*)request->buffer; 147 request->transfered_size = 4; 148 uint32_buffer[0] = instance->registers->rh_port_status[port -1]; 149 return EOK; 150 } 151 152 /** 153 * create answer to port status_request 154 * 155 * Copy content of hub status register to answer buffer. 156 * 157 * @param instance root hub instance 158 * @param request structure containing both request and response information 159 * @return error code 160 */ 161 static int process_get_hub_status_request(rh_t *instance, 162 usb_transfer_batch_t * request){ 163 uint32_t * uint32_buffer = (uint32_t*)request->buffer; 164 //bits, 0,1,16,17 165 request->transfered_size = 4; 166 uint32_t mask = 1 & (1<<1) & (1<<16) & (1<<17); 167 uint32_buffer[0] = mask & instance->registers->rh_status; 168 return EOK; 169 170 } 171 172 /** 173 * Create hub descriptor used in hub-driver <-> hub communication 174 * 175 * This means creating byt array from data in root hub registers. For more 176 * info see usb hub specification. 177 * 178 * @param instance root hub instance 179 * @param@out out_result pointer to resultant serialized descriptor 180 * @param@out out_size size of serialized descriptor 181 */ 182 static void usb_create_serialized_hub_descriptor(rh_t *instance, 183 uint8_t ** out_result, 184 size_t * out_size) { 185 //base size 186 size_t size = 7; 187 //variable size according to port count 188 size_t var_size = instance->port_count / 8 + 189 ((instance->port_count % 8 > 0) ? 1 : 0); 190 size += 2 * var_size; 191 uint8_t * result = (uint8_t*) malloc(size); 192 bzero(result,size); 193 //size 194 result[0] = size; 195 //descriptor type 196 result[1] = USB_DESCTYPE_HUB; 197 result[2] = instance->port_count; 198 uint32_t hub_desc_reg = instance->registers->rh_desc_a; 199 result[3] = 200 ((hub_desc_reg >> 8) %2) + 201 (((hub_desc_reg >> 9) %2) << 1) + 202 (((hub_desc_reg >> 10) %2) << 2) + 203 (((hub_desc_reg >> 11) %2) << 3) + 204 (((hub_desc_reg >> 12) %2) << 4); 205 result[4] = 0; 206 result[5] = /*descriptor->pwr_on_2_good_time*/ 50; 207 result[6] = 50; 208 209 int port; 210 for (port = 1; port <= instance->port_count; ++port) { 211 result[7 + port/8] += 212 ((instance->registers->rh_desc_b >> port)%2) << (port%8); 213 } 214 size_t i; 215 for (i = 0; i < var_size; ++i) { 216 result[7 + var_size + i] = 255; 217 } 218 (*out_result) = result; 219 (*out_size) = size; 220 } 221 222 223 /** 224 * create answer to status request 225 * 226 * This might be either hub status or port status request. If neither, 227 * ENOTSUP is returned. 228 * @param instance root hub instance 229 * @param request structure containing both request and response information 230 * @return error code 231 */ 232 static int process_get_status_request(rh_t *instance, 233 usb_transfer_batch_t * request) 234 { 235 size_t buffer_size = request->buffer_size; 236 usb_device_request_setup_packet_t * request_packet = 237 (usb_device_request_setup_packet_t*) 238 request->setup_buffer; 239 240 usb_hub_bm_request_type_t request_type = request_packet->request_type; 241 if(buffer_size<4/*request_packet->length*/){///\TODO 242 usb_log_warning("requested more data than buffer size\n"); 243 return EINVAL; 244 } 245 246 if(request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS) 247 return process_get_hub_status_request(instance, request); 248 if(request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS) 249 return process_get_port_status_request(instance, request_packet->index, 250 request); 251 return ENOTSUP; 252 } 253 254 /** 255 * create answer to status interrupt consisting of change bitmap 256 * 257 * Result contains bitmap where bit 0 indicates change on hub and 258 * bit i indicates change on i`th port (i>0). For more info see 259 * Hub and Port status bitmap specification in USB specification. 260 * @param instance root hub instance 261 * @param@out buffer pointer to created interrupt mas 262 * @param@out buffer_size size of created interrupt mask 263 */ 264 static void create_interrupt_mask(rh_t *instance, void ** buffer, 265 size_t * buffer_size){ 266 int bit_count = instance->port_count + 1; 267 (*buffer_size) = (bit_count / 8) + (bit_count%8==0)?0:1; 268 (*buffer) = malloc(*buffer_size); 269 uint8_t * bitmap = (uint8_t*)(*buffer); 270 uint32_t mask = (1<<16) + (1<<17); 271 bzero(bitmap,(*buffer_size)); 272 if(instance->registers->rh_status & mask){ 273 bitmap[0] = 1; 274 } 275 int port; 276 mask = 0; 277 int i; 278 for(i=16;i<=20;++i) 279 mask += 1<<i; 280 for(port = 1; port<=instance->port_count;++port){ 281 if(mask & instance->registers->rh_port_status[port-1]){ 282 bitmap[(port+1)/8] += 1<<(port%8); 283 } 284 } 285 } 286 287 /** 288 * create standart configuration descriptor for the root hub instance 289 * @param instance root hub instance 290 * @return newly allocated descriptor 291 */ 292 static usb_standard_configuration_descriptor_t * 293 usb_ohci_rh_create_standart_configuration_descriptor(rh_t *instance){ 294 usb_standard_configuration_descriptor_t * descriptor = 295 malloc(sizeof(usb_standard_configuration_descriptor_t)); 296 memcpy(descriptor, &ohci_rh_conf_descriptor, 297 sizeof(usb_standard_configuration_descriptor_t)); 298 /// \TODO should this include device descriptor? 299 const size_t hub_descriptor_size = 7 + 300 2* (instance->port_count / 8 + 301 ((instance->port_count % 8 > 0) ? 1 : 0)); 302 descriptor->total_length = 303 sizeof(usb_standard_configuration_descriptor_t)+ 304 sizeof(usb_standard_endpoint_descriptor_t)+ 305 sizeof(usb_standard_interface_descriptor_t)+ 306 hub_descriptor_size; 307 return descriptor; 308 } 309 310 /** 311 * create answer to a descriptor request 312 * 313 * This might be a request for standard (configuration, device, endpoint or 314 * interface) or device specific (hub) descriptor. 315 * @param instance root hub instance 316 * @param request structure containing both request and response information 317 * @return error code 318 */ 319 static int process_get_descriptor_request(rh_t *instance, 320 usb_transfer_batch_t *request){ 321 usb_device_request_setup_packet_t * setup_request = 322 (usb_device_request_setup_packet_t*)request->setup_buffer; 323 size_t size; 324 const void * result_descriptor = NULL; 325 const uint16_t setup_request_value = setup_request->value_high; 326 //(setup_request->value_low << 8); 327 bool del = false; 328 switch (setup_request_value) 329 { 330 case USB_DESCTYPE_HUB: { 331 uint8_t * descriptor; 332 usb_create_serialized_hub_descriptor( 333 instance, &descriptor, &size); 334 result_descriptor = descriptor; 335 if(result_descriptor) del = true; 336 break; 337 } 338 case USB_DESCTYPE_DEVICE: { 339 usb_log_debug("USB_DESCTYPE_DEVICE\n"); 340 result_descriptor = &ohci_rh_device_descriptor; 341 size = sizeof(ohci_rh_device_descriptor); 342 break; 343 } 344 case USB_DESCTYPE_CONFIGURATION: { 345 usb_log_debug("USB_DESCTYPE_CONFIGURATION\n"); 346 usb_standard_configuration_descriptor_t * descriptor = 347 usb_ohci_rh_create_standart_configuration_descriptor( 348 instance); 349 result_descriptor = descriptor; 350 size = sizeof(usb_standard_configuration_descriptor_t); 351 del = true; 352 break; 353 } 354 case USB_DESCTYPE_INTERFACE: { 355 usb_log_debug("USB_DESCTYPE_INTERFACE\n"); 356 result_descriptor = &ohci_rh_iface_descriptor; 357 size = sizeof(ohci_rh_iface_descriptor); 358 break; 359 } 360 case USB_DESCTYPE_ENDPOINT: { 361 usb_log_debug("USB_DESCTYPE_ENDPOINT\n"); 362 result_descriptor = &ohci_rh_ep_descriptor; 363 size = sizeof(ohci_rh_ep_descriptor); 364 break; 365 } 366 default: { 367 usb_log_debug("USB_DESCTYPE_EINVAL %d \n",setup_request->value); 368 usb_log_debug("\ttype %d\n\trequest %d\n\tvalue %d\n\tindex %d\n\tlen %d\n ", 369 setup_request->request_type, 370 setup_request->request, 371 setup_request_value, 372 setup_request->index, 373 setup_request->length 374 ); 375 return EINVAL; 376 } 377 } 378 if(request->buffer_size < size){ 379 size = request->buffer_size; 380 } 381 request->transfered_size = size; 382 memcpy(request->buffer,result_descriptor,size); 383 if (del) 384 free(result_descriptor); 385 return EOK; 386 } 387 388 /** 389 * answer to get configuration request 390 * 391 * Root hub works independently on the configuration. 392 * @param instance root hub instance 393 * @param request structure containing both request and response information 394 * @return error code 395 */ 396 static int process_get_configuration_request(rh_t *instance, 397 usb_transfer_batch_t *request){ 398 //set and get configuration requests do not have any meaning, only dummy 399 //values are returned 400 if(request->buffer_size != 1) 401 return EINVAL; 402 request->buffer[0] = 1; 403 request->transfered_size = 1; 404 return EOK; 405 } 406 407 /** 408 * process feature-enabling/disabling request on hub 409 * 410 * @param instance root hub instance 411 * @param feature feature selector 412 * @param enable enable or disable specified feature 413 * @return error code 414 */ 415 static int process_hub_feature_set_request(rh_t *instance, 416 uint16_t feature, bool enable){ 417 if(feature > USB_HUB_FEATURE_C_HUB_OVER_CURRENT) 418 return EINVAL; 419 instance->registers->rh_status = 420 enable ? 421 (instance->registers->rh_status | (1<<feature)) 422 : 423 (instance->registers->rh_status & (~(1<<feature))); 424 /// \TODO any error? 425 return EOK; 426 } 427 428 /** 429 * process feature-enabling/disabling request on hub 430 * 431 * @param instance root hub instance 432 * @param feature feature selector 433 * @param port port number, counted from 1 434 * @param enable enable or disable the specified feature 435 * @return error code 436 */ 437 static int process_port_feature_set_request(rh_t *instance, 438 uint16_t feature, uint16_t port, bool enable){ 439 if(feature > USB_HUB_FEATURE_C_PORT_RESET) 440 return EINVAL; 441 if(port<1 || port>instance->port_count) 442 return EINVAL; 443 instance->registers->rh_port_status[port - 1] = 444 enable ? 445 (instance->registers->rh_port_status[port - 1] | (1<<feature)) 446 : 447 (instance->registers->rh_port_status[port - 1] & (~(1<<feature))); 448 /// \TODO any error? 449 return EOK; 450 } 451 452 /** 453 * register address to this device 454 * 455 * @param instance root hub instance 456 * @param address new address 457 * @return error code 458 */ 459 static int process_address_set_request(rh_t *instance, 460 uint16_t address){ 461 instance->address = address; 462 return EOK; 463 } 464 465 /** 466 * process one of requests that requere output data 467 * 468 * Request can be one of USB_DEVREQ_GET_STATUS, USB_DEVREQ_GET_DESCRIPTOR or 469 * USB_DEVREQ_GET_CONFIGURATION. 470 * @param instance root hub instance 471 * @param request structure containing both request and response information 472 * @return error code 473 */ 474 static int process_request_with_output(rh_t *instance, 475 usb_transfer_batch_t *request){ 476 usb_device_request_setup_packet_t * setup_request = 477 (usb_device_request_setup_packet_t*)request->setup_buffer; 478 if(setup_request->request == USB_DEVREQ_GET_STATUS){ 479 usb_log_debug("USB_DEVREQ_GET_STATUS\n"); 480 return process_get_status_request(instance, request); 481 } 482 if(setup_request->request == USB_DEVREQ_GET_DESCRIPTOR){ 483 usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n"); 484 return process_get_descriptor_request(instance, request); 485 } 486 if(setup_request->request == USB_DEVREQ_GET_CONFIGURATION){ 487 usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n"); 488 return process_get_configuration_request(instance, request); 489 } 490 return ENOTSUP; 491 } 492 493 /** 494 * process one of requests that carry input data 495 * 496 * Request can be one of USB_DEVREQ_SET_DESCRIPTOR or 497 * USB_DEVREQ_SET_CONFIGURATION. 498 * @param instance root hub instance 499 * @param request structure containing both request and response information 500 * @return error code 501 */ 502 static int process_request_with_input(rh_t *instance, 503 usb_transfer_batch_t *request){ 504 usb_device_request_setup_packet_t * setup_request = 505 (usb_device_request_setup_packet_t*)request->setup_buffer; 506 request->transfered_size = 0; 507 if(setup_request->request == USB_DEVREQ_SET_DESCRIPTOR){ 508 return ENOTSUP; 509 } 510 if(setup_request->request == USB_DEVREQ_SET_CONFIGURATION){ 511 //set and get configuration requests do not have any meaning, 512 //only dummy values are returned 513 return EOK; 514 } 515 return ENOTSUP; 516 } 517 518 /** 519 * process one of requests that do not request nor carry additional data 520 * 521 * Request can be one of USB_DEVREQ_CLEAR_FEATURE, USB_DEVREQ_SET_FEATURE or 522 * USB_DEVREQ_SET_ADDRESS. 523 * @param instance root hub instance 524 * @param request structure containing both request and response information 525 * @return error code 526 */ 527 static int process_request_without_data(rh_t *instance, 528 usb_transfer_batch_t *request){ 529 usb_device_request_setup_packet_t * setup_request = 530 (usb_device_request_setup_packet_t*)request->setup_buffer; 531 request->transfered_size = 0; 532 if(setup_request->request == USB_DEVREQ_CLEAR_FEATURE 533 || setup_request->request == USB_DEVREQ_SET_FEATURE){ 534 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){ 535 usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n"); 536 return process_hub_feature_set_request(instance, setup_request->value, 537 setup_request->request == USB_DEVREQ_SET_FEATURE); 538 } 539 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){ 540 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 541 return process_port_feature_set_request(instance, setup_request->value, 542 setup_request->index, 543 setup_request->request == USB_DEVREQ_SET_FEATURE); 544 } 545 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",setup_request->request_type); 546 return EINVAL; 547 } 548 if(setup_request->request == USB_DEVREQ_SET_ADDRESS){ 549 usb_log_debug("USB_DEVREQ_SET_ADDRESS\n"); 550 return process_address_set_request(instance, setup_request->value); 551 } 552 usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n",setup_request->request_type); 553 return ENOTSUP; 554 } 555 556 /** 557 * process hub control request 558 * 559 * If needed, writes answer into the request structure. 560 * Request can be one of 561 * USB_DEVREQ_GET_STATUS, 562 * USB_DEVREQ_GET_DESCRIPTOR, 563 * USB_DEVREQ_GET_CONFIGURATION, 564 * USB_DEVREQ_CLEAR_FEATURE, 565 * USB_DEVREQ_SET_FEATURE, 566 * USB_DEVREQ_SET_ADDRESS, 567 * USB_DEVREQ_SET_DESCRIPTOR or 568 * USB_DEVREQ_SET_CONFIGURATION. 569 * 570 * @param instance root hub instance 571 * @param request structure containing both request and response information 572 * @return error code 573 */ 574 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request){ 575 int opResult; 576 if (request->setup_buffer) { 577 if(sizeof(usb_device_request_setup_packet_t)>request->setup_size){ 578 usb_log_error("setup packet too small\n"); 579 return EINVAL; 580 } 581 usb_log_info("CTRL packet: %s.\n", 582 usb_debug_str_buffer((const uint8_t *)request->setup_buffer, 8, 8)); 583 usb_device_request_setup_packet_t * setup_request = 584 (usb_device_request_setup_packet_t*)request->setup_buffer; 585 if( 586 setup_request->request == USB_DEVREQ_GET_STATUS 587 || setup_request->request == USB_DEVREQ_GET_DESCRIPTOR 588 || setup_request->request == USB_DEVREQ_GET_CONFIGURATION 589 ){ 590 usb_log_debug("processing request with output\n"); 591 opResult = process_request_with_output(instance,request); 592 }else if( 593 setup_request->request == USB_DEVREQ_CLEAR_FEATURE 594 || setup_request->request == USB_DEVREQ_SET_FEATURE 595 || setup_request->request == USB_DEVREQ_SET_ADDRESS 596 ){ 597 usb_log_debug("processing request without additional data\n"); 598 opResult = process_request_without_data(instance,request); 599 }else if(setup_request->request == USB_DEVREQ_SET_DESCRIPTOR 600 || setup_request->request == USB_DEVREQ_SET_CONFIGURATION 601 ){ 602 usb_log_debug("processing request with input\n"); 603 opResult = process_request_with_input(instance,request); 604 }else{ 605 usb_log_warning("received unsuported request: %d\n", 606 setup_request->request 607 ); 608 opResult = ENOTSUP; 609 } 610 }else{ 611 usb_log_error("root hub received empty transaction?"); 612 opResult = EINVAL; 613 } 614 return opResult; 615 } 616 617 /** 618 * process root hub request 619 * 620 * @param instance root hub instance 621 * @param request structure containing both request and response information 622 * @return error code 623 */ 58 624 int rh_request(rh_t *instance, usb_transfer_batch_t *request) 59 625 { 60 626 assert(instance); 61 627 assert(request); 62 /* TODO: implement */ 63 if (request->setup_buffer) { 64 usb_log_info("Root hub got SETUP packet: %s.\n", 65 usb_debug_str_buffer((const uint8_t *)request->setup_buffer, 8, 8)); 66 } 67 usb_log_error("Root hub request processing not implemented.\n"); 68 usb_transfer_batch_finish(request, ENOTSUP); 628 int opResult; 629 if(request->transfer_type == USB_TRANSFER_CONTROL){ 630 usb_log_info("Root hub got CONTROL packet\n"); 631 opResult = process_ctrl_request(instance,request); 632 }else if(request->transfer_type == USB_TRANSFER_INTERRUPT){ 633 usb_log_info("Root hub got INTERRUPT packet\n"); 634 void * buffer; 635 create_interrupt_mask(instance, &buffer, 636 &(request->transfered_size)); 637 memcpy(request->transport_buffer,buffer, request->transfered_size); 638 opResult = EOK; 639 }else{ 640 opResult = EINVAL; 641 } 642 usb_transfer_batch_finish(request, opResult); 69 643 return EOK; 70 644 } 71 645 /*----------------------------------------------------------------------------*/ 646 647 72 648 void rh_interrupt(rh_t *instance) 73 649 { 74 usb_log_ error("Root hub interrupt not implemented.\n");75 /* TODO: implement */650 usb_log_info("Whoa whoa wait, I`m not supposed to receive any interrupts, am I?\n"); 651 /* TODO: implement? */ 76 652 } 77 653 /**
Note:
See TracChangeset
for help on using the changeset viewer.