Changes in uspace/drv/ohci/root_hub.c [0368669c:1387692] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/ohci/root_hub.c
r0368669c r1387692 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 hub47 */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 guessed58 .max_packet_size = 8,59 .vendor_id = 0x16db,60 .product_id = 0x0001,61 /// \TODO these values migt be different62 .str_serial_number = 0,63 .usb_spec_version = 0,64 };65 66 /**67 * standart configuration descriptor with filled common values68 * for ohci root hubs69 */70 static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor =71 {72 /// \TODO some values are default or guessed73 .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 descriptor84 */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 descriptor101 */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 };111 41 112 42 /** Root hub initialization … … 120 50 instance->device = dev; 121 51 122 123 52 usb_log_info("OHCI root hub with %d ports.\n", regs->rh_desc_a & 0xff); 124 53 125 //start generic usb hub driver126 127 54 /* TODO: implement */ 128 55 return EOK; 129 56 } 130 57 /*----------------------------------------------------------------------------*/ 131 132 /**133 * create answer to port status_request134 *135 * Copy content of corresponding port status register to answer buffer.136 *137 * @param instance root hub instance138 * @param port port number, counted from 1139 * @param request structure containing both request and response information140 * @return error code141 */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_request154 *155 * Copy content of hub status register to answer buffer.156 *157 * @param instance root hub instance158 * @param request structure containing both request and response information159 * @return error code160 */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,17165 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 communication174 *175 * This means creating byt array from data in root hub registers. For more176 * info see usb hub specification.177 *178 * @param instance root hub instance179 * @param@out out_result pointer to resultant serialized descriptor180 * @param@out out_size size of serialized descriptor181 */182 static void usb_create_serialized_hub_descriptor(rh_t *instance,183 uint8_t ** out_result,184 size_t * out_size) {185 //base size186 size_t size = 7;187 //variable size according to port count188 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 //size194 result[0] = size;195 //descriptor type196 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 request225 *226 * This might be either hub status or port status request. If neither,227 * ENOTSUP is returned.228 * @param instance root hub instance229 * @param request structure containing both request and response information230 * @return error code231 */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*/){///\TODO242 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 bitmap256 *257 * Result contains bitmap where bit 0 indicates change on hub and258 * bit i indicates change on i`th port (i>0). For more info see259 * Hub and Port status bitmap specification in USB specification.260 * @param instance root hub instance261 * @param@out buffer pointer to created interrupt mas262 * @param@out buffer_size size of created interrupt mask263 */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 instance289 * @param instance root hub instance290 * @return newly allocated descriptor291 */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 request312 *313 * This might be a request for standard (configuration, device, endpoint or314 * interface) or device specific (hub) descriptor.315 * @param instance root hub instance316 * @param request structure containing both request and response information317 * @return error code318 */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->length374 );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 request390 *391 * Root hub works independently on the configuration.392 * @param instance root hub instance393 * @param request structure containing both request and response information394 * @return error code395 */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 dummy399 //values are returned400 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 hub409 *410 * @param instance root hub instance411 * @param feature feature selector412 * @param enable enable or disable specified feature413 * @return error code414 */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 hub430 *431 * @param instance root hub instance432 * @param feature feature selector433 * @param port port number, counted from 1434 * @param enable enable or disable the specified feature435 * @return error code436 */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 device454 *455 * @param instance root hub instance456 * @param address new address457 * @return error code458 */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 data467 *468 * Request can be one of USB_DEVREQ_GET_STATUS, USB_DEVREQ_GET_DESCRIPTOR or469 * USB_DEVREQ_GET_CONFIGURATION.470 * @param instance root hub instance471 * @param request structure containing both request and response information472 * @return error code473 */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 data495 *496 * Request can be one of USB_DEVREQ_SET_DESCRIPTOR or497 * USB_DEVREQ_SET_CONFIGURATION.498 * @param instance root hub instance499 * @param request structure containing both request and response information500 * @return error code501 */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 returned513 return EOK;514 }515 return ENOTSUP;516 }517 518 /**519 * process one of requests that do not request nor carry additional data520 *521 * Request can be one of USB_DEVREQ_CLEAR_FEATURE, USB_DEVREQ_SET_FEATURE or522 * USB_DEVREQ_SET_ADDRESS.523 * @param instance root hub instance524 * @param request structure containing both request and response information525 * @return error code526 */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_FEATURE533 || 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 request558 *559 * If needed, writes answer into the request structure.560 * Request can be one of561 * 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 or568 * USB_DEVREQ_SET_CONFIGURATION.569 *570 * @param instance root hub instance571 * @param request structure containing both request and response information572 * @return error code573 */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_STATUS587 || setup_request->request == USB_DEVREQ_GET_DESCRIPTOR588 || setup_request->request == USB_DEVREQ_GET_CONFIGURATION589 ){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_FEATURE594 || setup_request->request == USB_DEVREQ_SET_FEATURE595 || setup_request->request == USB_DEVREQ_SET_ADDRESS596 ){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_DESCRIPTOR600 || setup_request->request == USB_DEVREQ_SET_CONFIGURATION601 ){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->request607 );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 request619 *620 * @param instance root hub instance621 * @param request structure containing both request and response information622 * @return error code623 */624 58 int rh_request(rh_t *instance, usb_transfer_batch_t *request) 625 59 { 626 60 assert(instance); 627 61 assert(request); 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; 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)); 641 66 } 642 usb_transfer_batch_finish(request, opResult); 67 usb_log_error("Root hub request processing not implemented.\n"); 68 usb_transfer_batch_finish(request, ENOTSUP); 643 69 return EOK; 644 70 } 645 71 /*----------------------------------------------------------------------------*/ 646 647 648 72 void rh_interrupt(rh_t *instance) 649 73 { 650 usb_log_ info("Whoa whoa wait, I`m not supposed to receive any interrupts, am I?\n");651 /* TODO: implement ?*/74 usb_log_error("Root hub interrupt not implemented.\n"); 75 /* TODO: implement */ 652 76 } 653 77 /**
Note:
See TracChangeset
for help on using the changeset viewer.