Changes in uspace/drv/ohci/root_hub.c [b3f655f:1387692] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/ohci/root_hub.c
rb3f655f 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 static const usb_standard_device_descriptor_t ohci_rh_device_descriptor =46 {47 .configuration_count = 1,48 .descriptor_type = USB_DESCTYPE_DEVICE,49 .device_class = USB_CLASS_HUB,50 .device_protocol = 0,51 .device_subclass = 0,52 .device_version = 0,53 .length = sizeof(usb_standard_device_descriptor_t),54 /// \TODO this value is guessed55 .max_packet_size = 8,56 .vendor_id = 0x16db,57 .product_id = 0x0001,58 /// \TODO these values migt be different59 .str_serial_number = 0,60 .usb_spec_version = 0,61 };62 63 static const usb_standard_configuration_descriptor_t ohci_rh_conf_descriptor =64 {65 /// \TODO some values are default or guessed66 .attributes = 1<<7,67 .configuration_number = 1,68 .descriptor_type = USB_DESCTYPE_CONFIGURATION,69 .interface_count = 1,70 .length = sizeof(usb_standard_configuration_descriptor_t),71 .max_power = 100,72 .str_configuration = 0,73 };74 75 static const usb_standard_interface_descriptor_t ohci_rh_iface_descriptor =76 {77 .alternate_setting = 0,78 .descriptor_type = USB_DESCTYPE_INTERFACE,79 .endpoint_count = 1,80 .interface_class = USB_CLASS_HUB,81 /// \TODO is this correct?82 .interface_number = 1,83 .interface_protocol = 0,84 .interface_subclass = 0,85 .length = sizeof(usb_standard_interface_descriptor_t),86 .str_interface = 0,87 };88 89 static const usb_standard_endpoint_descriptor_t ohci_rh_ep_descriptor =90 {91 .attributes = USB_TRANSFER_INTERRUPT,92 .descriptor_type = USB_DESCTYPE_ENDPOINT,93 .endpoint_address = 1 + (1<<7),94 .length = sizeof(usb_standard_endpoint_descriptor_t),95 .max_packet_size = 8,96 .poll_interval = 255,97 };98 41 99 42 /** Root hub initialization … … 107 50 instance->device = dev; 108 51 109 110 52 usb_log_info("OHCI root hub with %d ports.\n", regs->rh_desc_a & 0xff); 111 53 112 //start generic usb hub driver113 114 54 /* TODO: implement */ 115 55 return EOK; 116 56 } 117 57 /*----------------------------------------------------------------------------*/ 118 119 120 static int process_get_port_status_request(rh_t *instance, uint16_t port,121 usb_transfer_batch_t * request){122 if(port<1 || port>instance->port_count)123 return EINVAL;124 uint32_t * uint32_buffer = (uint32_t*)request->buffer;125 request->transfered_size = 4;126 uint32_buffer[0] = instance->registers->rh_port_status[port -1];127 return EOK;128 }129 130 static int process_get_hub_status_request(rh_t *instance,131 usb_transfer_batch_t * request){132 uint32_t * uint32_buffer = (uint32_t*)request->buffer;133 //bits, 0,1,16,17134 request->transfered_size = 4;135 uint32_t mask = 1 & (1<<1) & (1<<16) & (1<<17);136 uint32_buffer[0] = mask & instance->registers->rh_status;137 return EOK;138 139 }140 141 static void usb_create_serialized_hub_descriptor(rh_t *instance, uint8_t ** out_result,142 size_t * out_size) {143 //base size144 size_t size = 7;145 //variable size according to port count146 size_t var_size = instance->port_count / 8 +147 ((instance->port_count % 8 > 0) ? 1 : 0);148 size += 2 * var_size;149 uint8_t * result = (uint8_t*) malloc(size);150 bzero(result,size);151 //size152 result[0] = size;153 //descriptor type154 result[1] = USB_DESCTYPE_HUB;155 result[2] = instance->port_count;156 uint32_t hub_desc_reg = instance->registers->rh_desc_a;157 result[3] =158 ((hub_desc_reg >> 8) %2) +159 (((hub_desc_reg >> 9) %2) << 1) +160 (((hub_desc_reg >> 10) %2) << 2) +161 (((hub_desc_reg >> 11) %2) << 3) +162 (((hub_desc_reg >> 12) %2) << 4);163 result[4] = 0;164 result[5] = /*descriptor->pwr_on_2_good_time*/ 50;165 result[6] = 50;166 167 int port;168 for (port = 1; port <= instance->port_count; ++port) {169 result[7 + port/8] +=170 ((instance->registers->rh_desc_b >> port)%2) << (port%8);171 }172 size_t i;173 for (i = 0; i < var_size; ++i) {174 result[7 + var_size + i] = 255;175 }176 (*out_result) = result;177 (*out_size) = size;178 }179 180 181 static int process_get_status_request(rh_t *instance,182 usb_transfer_batch_t * request)183 {184 size_t buffer_size = request->buffer_size;185 usb_device_request_setup_packet_t * request_packet =186 (usb_device_request_setup_packet_t*)187 request->setup_buffer;188 189 usb_hub_bm_request_type_t request_type = request_packet->request_type;190 if(buffer_size<4/*request_packet->length*/){///\TODO191 usb_log_warning("requested more data than buffer size\n");192 return EINVAL;193 }194 195 if(request_type == USB_HUB_REQ_TYPE_GET_HUB_STATUS)196 return process_get_hub_status_request(instance, request);197 if(request_type == USB_HUB_REQ_TYPE_GET_PORT_STATUS)198 return process_get_port_status_request(instance, request_packet->index,199 request);200 return ENOTSUP;201 }202 203 static void create_interrupt_mask(rh_t *instance, void ** buffer,204 size_t * buffer_size){205 int bit_count = instance->port_count + 1;206 (*buffer_size) = (bit_count / 8) + (bit_count%8==0)?0:1;207 (*buffer) = malloc(*buffer_size);208 uint8_t * bitmap = (uint8_t*)(*buffer);209 uint32_t mask = (1<<16) + (1<<17);210 bzero(bitmap,(*buffer_size));211 if(instance->registers->rh_status & mask){212 bitmap[0] = 1;213 }214 int port;215 mask = 0;216 int i;217 for(i=16;i<=20;++i)218 mask += 1<<i;219 for(port = 1; port<=instance->port_count;++port){220 if(mask & instance->registers->rh_port_status[port-1]){221 bitmap[(port+1)/8] += 1<<(port%8);222 }223 }224 }225 226 227 static int process_get_descriptor_request(rh_t *instance,228 usb_transfer_batch_t *request){229 /// \TODO230 usb_device_request_setup_packet_t * setup_request =231 (usb_device_request_setup_packet_t*)request->setup_buffer;232 size_t size;233 const void * result_descriptor;234 const uint16_t setup_request_value = setup_request->value_high;235 //(setup_request->value_low << 8);236 bool del = false;237 238 switch (setup_request_value)239 {240 case USB_DESCTYPE_HUB: {241 uint8_t * descriptor;242 usb_create_serialized_hub_descriptor(243 instance, &descriptor, &size);244 result_descriptor = descriptor;245 break;246 }247 case USB_DESCTYPE_DEVICE: {248 usb_log_debug("USB_DESCTYPE_DEVICE\n");249 result_descriptor = &ohci_rh_device_descriptor;250 size = sizeof(ohci_rh_device_descriptor);251 break;252 }253 case USB_DESCTYPE_CONFIGURATION: {254 usb_log_debug("USB_DESCTYPE_CONFIGURATION\n");255 usb_standard_configuration_descriptor_t * descriptor =256 malloc(sizeof(usb_standard_configuration_descriptor_t));257 memcpy(descriptor, &ohci_rh_conf_descriptor,258 sizeof(usb_standard_configuration_descriptor_t));259 /// \TODO should this include device descriptor?260 const size_t hub_descriptor_size = 7 +261 2* (instance->port_count / 8 +262 ((instance->port_count % 8 > 0) ? 1 : 0));263 descriptor->total_length =264 sizeof(usb_standard_configuration_descriptor_t)+265 sizeof(usb_standard_endpoint_descriptor_t)+266 sizeof(usb_standard_interface_descriptor_t)+267 hub_descriptor_size;268 result_descriptor = descriptor;269 size = sizeof(usb_standard_configuration_descriptor_t);270 del = true;271 break;272 }273 case USB_DESCTYPE_INTERFACE: {274 usb_log_debug("USB_DESCTYPE_INTERFACE\n");275 result_descriptor = &ohci_rh_iface_descriptor;276 size = sizeof(ohci_rh_iface_descriptor);277 break;278 }279 case USB_DESCTYPE_ENDPOINT: {280 usb_log_debug("USB_DESCTYPE_ENDPOINT\n");281 result_descriptor = &ohci_rh_ep_descriptor;282 size = sizeof(ohci_rh_ep_descriptor);283 break;284 }285 default: {286 usb_log_debug("USB_DESCTYPE_EINVAL %d \n",setup_request->value);287 usb_log_debug("\ttype %d\n\trequest %d\n\tvalue %d\n\tindex %d\n\tlen %d\n ",288 setup_request->request_type,289 setup_request->request,290 setup_request_value,291 setup_request->index,292 setup_request->length293 );294 return EINVAL;295 }296 }297 #if 0298 if(setup_request_value == USB_DESCTYPE_HUB){299 usb_log_debug("USB_DESCTYPE_HUB\n");300 //create hub descriptor301 uint8_t * descriptor;302 usb_create_serialized_hub_descriptor(instance,303 &descriptor, &size);304 result_descriptor = descriptor;305 }else if(setup_request_value == USB_DESCTYPE_DEVICE){306 //create std device descriptor307 usb_log_debug("USB_DESCTYPE_DEVICE\n");308 usb_standard_device_descriptor_t * descriptor =309 (usb_standard_device_descriptor_t*)310 malloc(sizeof(usb_standard_device_descriptor_t));311 descriptor->configuration_count = 1;312 descriptor->descriptor_type = USB_DESCTYPE_DEVICE;313 descriptor->device_class = USB_CLASS_HUB;314 descriptor->device_protocol = 0;315 descriptor->device_subclass = 0;316 descriptor->device_version = 0;317 descriptor->length = sizeof(usb_standard_device_descriptor_t);318 /// \TODO this value is guessed319 descriptor->max_packet_size = 8;320 descriptor->product_id = 0x0001;321 /// \TODO these values migt be different322 descriptor->str_serial_number = 0;323 descriptor->str_serial_number = 0;324 descriptor->usb_spec_version = 0;325 descriptor->vendor_id = 0x16db;326 result_descriptor = descriptor;327 size = sizeof(usb_standard_device_descriptor_t);328 }else if(setup_request_value == USB_DESCTYPE_CONFIGURATION){329 usb_log_debug("USB_DESCTYPE_CONFIGURATION\n");330 usb_standard_configuration_descriptor_t * descriptor =331 (usb_standard_configuration_descriptor_t*)332 malloc(sizeof(usb_standard_configuration_descriptor_t));333 /// \TODO some values are default or guessed334 descriptor->attributes = 1<<7;335 descriptor->configuration_number = 1;336 descriptor->descriptor_type = USB_DESCTYPE_CONFIGURATION;337 descriptor->interface_count = 1;338 descriptor->length = sizeof(usb_standard_configuration_descriptor_t);339 descriptor->max_power = 100;340 descriptor->str_configuration = 0;341 /// \TODO should this include device descriptor?342 size_t hub_descriptor_size = 7 +343 2* (instance->port_count / 8 +344 ((instance->port_count % 8 > 0) ? 1 : 0));345 descriptor->total_length =346 sizeof(usb_standard_configuration_descriptor_t)+347 sizeof(usb_standard_endpoint_descriptor_t)+348 sizeof(usb_standard_interface_descriptor_t)+349 hub_descriptor_size;350 result_descriptor = descriptor;351 size = sizeof(usb_standard_configuration_descriptor_t);352 353 }else if(setup_request_value == USB_DESCTYPE_INTERFACE){354 usb_log_debug("USB_DESCTYPE_INTERFACE\n");355 usb_standard_interface_descriptor_t * descriptor =356 (usb_standard_interface_descriptor_t*)357 malloc(sizeof(usb_standard_interface_descriptor_t));358 descriptor->alternate_setting = 0;359 descriptor->descriptor_type = USB_DESCTYPE_INTERFACE;360 descriptor->endpoint_count = 1;361 descriptor->interface_class = USB_CLASS_HUB;362 /// \TODO is this correct?363 descriptor->interface_number = 1;364 descriptor->interface_protocol = 0;365 descriptor->interface_subclass = 0;366 descriptor->length = sizeof(usb_standard_interface_descriptor_t);367 descriptor->str_interface = 0;368 result_descriptor = descriptor;369 size = sizeof(usb_standard_interface_descriptor_t);370 }else if(setup_request_value == USB_DESCTYPE_ENDPOINT){371 usb_log_debug("USB_DESCTYPE_ENDPOINT\n");372 usb_standard_endpoint_descriptor_t * descriptor =373 (usb_standard_endpoint_descriptor_t*)374 malloc(sizeof(usb_standard_endpoint_descriptor_t));375 descriptor->attributes = USB_TRANSFER_INTERRUPT;376 descriptor->descriptor_type = USB_DESCTYPE_ENDPOINT;377 descriptor->endpoint_address = 1 + (1<<7);378 descriptor->length = sizeof(usb_standard_endpoint_descriptor_t);379 descriptor->max_packet_size = 8;380 descriptor->poll_interval = 255;381 result_descriptor = descriptor;382 size = sizeof(usb_standard_endpoint_descriptor_t);383 }else{384 usb_log_debug("USB_DESCTYPE_EINVAL %d \n",setup_request->value);385 usb_log_debug("\ttype %d\n\trequest %d\n\tvalue %d\n\tindex %d\n\tlen %d\n ",386 setup_request->request_type,387 setup_request->request,388 setup_request_value,389 setup_request->index,390 setup_request->length391 );392 return EINVAL;393 }394 #endif395 if(request->buffer_size < size){396 size = request->buffer_size;397 }398 request->transfered_size = size;399 memcpy(request->buffer,result_descriptor,size);400 if (del)401 free(result_descriptor);402 return EOK;403 }404 405 static int process_get_configuration_request(rh_t *instance,406 usb_transfer_batch_t *request){407 //set and get configuration requests do not have any meaning, only dummy408 //values are returned409 if(request->buffer_size != 1)410 return EINVAL;411 request->buffer[0] = 1;412 request->transfered_size = 1;413 return EOK;414 }415 416 static int process_hub_feature_set_request(rh_t *instance,417 uint16_t feature, bool enable){418 if(feature > USB_HUB_FEATURE_C_HUB_OVER_CURRENT)419 return EINVAL;420 instance->registers->rh_status =421 enable ?422 (instance->registers->rh_status | (1<<feature))423 :424 (instance->registers->rh_status & (~(1<<feature)));425 /// \TODO any error?426 return EOK;427 }428 429 static int process_port_feature_set_request(rh_t *instance,430 uint16_t feature, uint16_t port, bool enable){431 if(feature > USB_HUB_FEATURE_C_PORT_RESET)432 return EINVAL;433 if(port<1 || port>instance->port_count)434 return EINVAL;435 instance->registers->rh_port_status[port - 1] =436 enable ?437 (instance->registers->rh_port_status[port - 1] | (1<<feature))438 :439 (instance->registers->rh_port_status[port - 1] & (~(1<<feature)));440 /// \TODO any error?441 return EOK;442 }443 444 static int process_address_set_request(rh_t *instance,445 uint16_t address){446 instance->address = address;447 return EOK;448 }449 450 static int process_request_with_output(rh_t *instance,451 usb_transfer_batch_t *request){452 usb_device_request_setup_packet_t * setup_request =453 (usb_device_request_setup_packet_t*)request->setup_buffer;454 if(setup_request->request == USB_DEVREQ_GET_STATUS){455 usb_log_debug("USB_DEVREQ_GET_STATUS\n");456 return process_get_status_request(instance, request);457 }458 if(setup_request->request == USB_DEVREQ_GET_DESCRIPTOR){459 usb_log_debug("USB_DEVREQ_GET_DESCRIPTOR\n");460 return process_get_descriptor_request(instance, request);461 }462 if(setup_request->request == USB_DEVREQ_GET_CONFIGURATION){463 usb_log_debug("USB_DEVREQ_GET_CONFIGURATION\n");464 return process_get_configuration_request(instance, request);465 }466 return ENOTSUP;467 }468 469 static int process_request_with_input(rh_t *instance,470 usb_transfer_batch_t *request){471 usb_device_request_setup_packet_t * setup_request =472 (usb_device_request_setup_packet_t*)request->setup_buffer;473 request->transfered_size = 0;474 if(setup_request->request == USB_DEVREQ_SET_DESCRIPTOR){475 return ENOTSUP;476 }477 if(setup_request->request == USB_DEVREQ_SET_CONFIGURATION){478 //set and get configuration requests do not have any meaning,479 //only dummy values are returned480 return EOK;481 }482 return ENOTSUP;483 }484 485 486 static int process_request_without_data(rh_t *instance,487 usb_transfer_batch_t *request){488 usb_device_request_setup_packet_t * setup_request =489 (usb_device_request_setup_packet_t*)request->setup_buffer;490 request->transfered_size = 0;491 if(setup_request->request == USB_DEVREQ_CLEAR_FEATURE492 || setup_request->request == USB_DEVREQ_SET_FEATURE){493 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_HUB_FEATURE){494 usb_log_debug("USB_HUB_REQ_TYPE_SET_HUB_FEATURE\n");495 return process_hub_feature_set_request(instance, setup_request->value,496 setup_request->request == USB_DEVREQ_SET_FEATURE);497 }498 if(setup_request->request_type == USB_HUB_REQ_TYPE_SET_PORT_FEATURE){499 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n");500 return process_port_feature_set_request(instance, setup_request->value,501 setup_request->index,502 setup_request->request == USB_DEVREQ_SET_FEATURE);503 }504 usb_log_debug("USB_HUB_REQ_TYPE_INVALID %d\n",setup_request->request_type);505 return EINVAL;506 }507 if(setup_request->request == USB_DEVREQ_SET_ADDRESS){508 usb_log_debug("USB_DEVREQ_SET_ADDRESS\n");509 return process_address_set_request(instance, setup_request->value);510 }511 usb_log_debug("USB_DEVREQ_SET_ENOTSUP %d\n",setup_request->request_type);512 return ENOTSUP;513 }514 515 516 /**517 *518 * @param instance519 * @param request520 * @return521 */522 58 int rh_request(rh_t *instance, usb_transfer_batch_t *request) 523 59 { 524 60 assert(instance); 525 61 assert(request); 526 int opResult; 527 if(request->transfer_type == USB_TRANSFER_CONTROL){ 528 if (request->setup_buffer) { 529 usb_log_info("Root hub got CTRL packet: %s.\n", 530 usb_debug_str_buffer((const uint8_t *)request->setup_buffer, 8, 8)); 531 if(sizeof(usb_device_request_setup_packet_t)>request->setup_size){ 532 usb_log_error("setup packet too small\n"); 533 return EINVAL; 534 } 535 usb_device_request_setup_packet_t * setup_request = 536 (usb_device_request_setup_packet_t*)request->setup_buffer; 537 if( 538 setup_request->request == USB_DEVREQ_GET_STATUS 539 || setup_request->request == USB_DEVREQ_GET_DESCRIPTOR 540 || setup_request->request == USB_DEVREQ_GET_CONFIGURATION 541 ){ 542 usb_log_debug("processing request with output\n"); 543 opResult = process_request_with_output(instance,request); 544 }else if( 545 setup_request->request == USB_DEVREQ_CLEAR_FEATURE 546 || setup_request->request == USB_DEVREQ_SET_FEATURE 547 || setup_request->request == USB_DEVREQ_SET_ADDRESS 548 ){ 549 usb_log_debug("processing request without additional data\n"); 550 opResult = process_request_without_data(instance,request); 551 }else if(setup_request->request == USB_DEVREQ_SET_DESCRIPTOR 552 || setup_request->request == USB_DEVREQ_SET_CONFIGURATION 553 ){ 554 usb_log_debug("processing request with input\n"); 555 opResult = process_request_with_input(instance,request); 556 }else{ 557 usb_log_warning("received unsuported request: %d\n", 558 setup_request->request 559 ); 560 opResult = ENOTSUP; 561 } 562 }else{ 563 usb_log_error("root hub received empty transaction?"); 564 opResult = EINVAL; 565 } 566 }else if(request->transfer_type == USB_TRANSFER_INTERRUPT){ 567 usb_log_info("Root hub got INTERRUPT packet\n"); 568 void * buffer; 569 create_interrupt_mask(instance, &buffer, 570 &(request->transfered_size)); 571 memcpy(request->transport_buffer,buffer, request->transfered_size); 572 opResult = EOK; 573 }else{ 574 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)); 575 66 } 576 usb_transfer_batch_finish(request, opResult); 67 usb_log_error("Root hub request processing not implemented.\n"); 68 usb_transfer_batch_finish(request, ENOTSUP); 577 69 return EOK; 578 70 } 579 71 /*----------------------------------------------------------------------------*/ 580 581 582 72 void rh_interrupt(rh_t *instance) 583 73 {
Note:
See TracChangeset
for help on using the changeset viewer.