Changes in uspace/drv/ohci/root_hub.c [361fcec:f35b294] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/ohci/root_hub.c
r361fcec rf35b294 149 149 150 150 151 static int create_serialized_hub_descriptor(rh_t *instance); 152 153 static int rh_init_descriptors(rh_t *instance); 151 static void usb_create_serialized_hub_descriptor(rh_t *instance, 152 uint8_t ** out_result, 153 size_t * out_size); 154 155 static void rh_init_descriptors(rh_t *instance); 154 156 155 157 static int process_get_port_status_request(rh_t *instance, uint16_t port, … … 162 164 usb_transfer_batch_t * request); 163 165 164 static void create_interrupt_mask_in_instance(rh_t *instance); 166 static void create_interrupt_mask(rh_t *instance, void ** buffer, 167 size_t * buffer_size); 165 168 166 169 static int process_get_descriptor_request(rh_t *instance, … … 195 198 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request); 196 199 197 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request); 198 199 static bool is_zeros(void * buffer, size_t size); 200 200 201 201 202 … … 204 205 * @return Error code. 205 206 */ 206 int rh_init(rh_t *instance, ohci_regs_t *regs) {207 int rh_init(rh_t *instance, ddf_dev_t *dev, ohci_regs_t *regs) { 207 208 assert(instance); 209 //instance->address = -1; 208 210 instance->registers = regs; 209 instance->port_count = 210 (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK; 211 int opResult = rh_init_descriptors(instance); 212 if(opResult != EOK){ 213 return opResult; 214 } 211 instance->device = dev; 212 instance->port_count = instance->registers->rh_desc_a & 0xff; 213 rh_init_descriptors(instance); 215 214 // set port power mode to no-power-switching 216 instance->registers->rh_desc_a |= RHDA_NPS_FLAG; 217 instance->unfinished_interrupt_transfer = NULL; 218 instance->interrupt_mask_size = (instance->port_count + 8)/8; 219 instance->interrupt_buffer = malloc(instance->interrupt_mask_size); 220 if(!instance->interrupt_buffer) 221 return ENOMEM; 222 215 instance->registers->rh_desc_a = 216 instance->registers->rh_desc_a | (1<<9); 223 217 224 218 usb_log_info("OHCI root hub with %d ports.\n", instance->port_count); 219 220 //start generic usb hub driver 221 222 /* TODO: implement */ 225 223 return EOK; 226 224 } … … 238 236 assert(request); 239 237 int opResult; 240 if (request-> ep->transfer_type == USB_TRANSFER_CONTROL) {238 if (request->transfer_type == USB_TRANSFER_CONTROL) { 241 239 usb_log_info("Root hub got CONTROL packet\n"); 242 240 opResult = process_ctrl_request(instance, request); 243 usb_transfer_batch_finish_error(request, opResult); 244 } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) { 241 } else if (request->transfer_type == USB_TRANSFER_INTERRUPT) { 245 242 usb_log_info("Root hub got INTERRUPT packet\n"); 246 create_interrupt_mask_in_instance(instance); 247 if(is_zeros(instance->interrupt_buffer, 248 instance->interrupt_mask_size)){ 249 usb_log_debug("no changes..\n"); 250 instance->unfinished_interrupt_transfer = request; 251 //will be finished later 252 }else{ 253 usb_log_debug("processing changes..\n"); 254 process_interrupt_mask_in_instance(instance, request); 255 } 243 void * buffer; 244 create_interrupt_mask(instance, &buffer, 245 &(request->transfered_size)); 246 memcpy(request->transport_buffer, buffer, 247 request->transfered_size); 256 248 opResult = EOK; 257 249 } else { 258 250 opResult = EINVAL; 259 usb_transfer_batch_finish_error(request, opResult); 260 } 261 return EOK; 262 } 263 264 /*----------------------------------------------------------------------------*/ 265 266 /** 267 * process interrupt on a hub 268 * 269 * If there is no pending interrupt transfer, nothing happens. 270 * @param instance 271 */ 251 } 252 usb_transfer_batch_finish_error(request, opResult); 253 return EOK; 254 } 255 256 /*----------------------------------------------------------------------------*/ 257 258 272 259 void rh_interrupt(rh_t *instance) { 273 if(!instance->unfinished_interrupt_transfer){ 274 return; 275 } 276 usb_log_debug("finalizing interrupt transfer\n"); 277 create_interrupt_mask_in_instance(instance); 278 process_interrupt_mask_in_instance(instance, 279 instance->unfinished_interrupt_transfer); 260 usb_log_info("Whoa whoa wait, I`m not supposed to receive any " 261 "interrupts, am I?\n"); 262 /* TODO: implement? */ 280 263 } 281 264 /*----------------------------------------------------------------------------*/ … … 288 271 * 289 272 * @param instance root hub instance 290 * @return error code 291 */ 292 static int create_serialized_hub_descriptor(rh_t *instance) { 293 size_t size = 7 + 294 ((instance->port_count +7 )/ 8) * 2; 295 size_t var_size = (instance->port_count +7 )/ 8; 273 * @param@out out_result pointer to resultant serialized descriptor 274 * @param@out out_size size of serialized descriptor 275 */ 276 static void usb_create_serialized_hub_descriptor(rh_t *instance, 277 uint8_t ** out_result, 278 size_t * out_size) { 279 //base size 280 size_t size = 7; 281 //variable size according to port count 282 size_t var_size = instance->port_count / 8 + 283 ((instance->port_count % 8 > 0) ? 1 : 0); 284 size += 2 * var_size; 296 285 uint8_t * result = (uint8_t*) malloc(size); 297 if(!result) return ENOMEM;298 299 286 bzero(result, size); 300 287 //size … … 325 312 result[7 + var_size + i] = 255; 326 313 } 327 instance->hub_descriptor = result; 328 instance->descriptor_size = size; 329 return EOK; 314 (*out_result) = result; 315 (*out_size) = size; 330 316 } 331 317 /*----------------------------------------------------------------------------*/ … … 336 322 * be initialized only once per hub. 337 323 * @instance root hub instance 338 * @return error code 339 */ 340 static int rh_init_descriptors(rh_t *instance) { 324 */ 325 static void rh_init_descriptors(rh_t *instance) { 341 326 memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor, 342 327 sizeof (ohci_rh_device_descriptor) … … 345 330 memcpy(&descriptor, &ohci_rh_conf_descriptor, 346 331 sizeof (ohci_rh_conf_descriptor)); 347 348 int opResult = create_serialized_hub_descriptor(instance);349 if(opResult != EOK){350 return opResult;351 } 332 uint8_t * hub_descriptor; 333 size_t hub_desc_size; 334 usb_create_serialized_hub_descriptor(instance, &hub_descriptor, 335 &hub_desc_size); 336 352 337 descriptor.total_length = 353 338 sizeof (usb_standard_configuration_descriptor_t) + 354 339 sizeof (usb_standard_endpoint_descriptor_t) + 355 340 sizeof (usb_standard_interface_descriptor_t) + 356 instance->descriptor_size;341 hub_desc_size; 357 342 358 343 uint8_t * full_config_descriptor = 359 344 (uint8_t*) malloc(descriptor.total_length); 360 if(!full_config_descriptor){361 return ENOMEM;362 }363 345 memcpy(full_config_descriptor, &descriptor, sizeof (descriptor)); 364 346 memcpy(full_config_descriptor + sizeof (descriptor), … … 370 352 sizeof (ohci_rh_iface_descriptor) + 371 353 sizeof (ohci_rh_ep_descriptor), 372 instance->hub_descriptor, instance->descriptor_size);373 354 hub_descriptor, hub_desc_size); 355 374 356 instance->descriptors.configuration = full_config_descriptor; 375 357 instance->descriptors.configuration_size = descriptor.total_length; 376 return EOK;377 358 } 378 359 /*----------------------------------------------------------------------------*/ … … 392 373 if (port < 1 || port > instance->port_count) 393 374 return EINVAL; 394 uint32_t * uint32_buffer = (uint32_t*) request-> data_buffer;375 uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer; 395 376 request->transfered_size = 4; 396 377 uint32_buffer[0] = instance->registers->rh_port_status[port - 1]; … … 418 399 static int process_get_hub_status_request(rh_t *instance, 419 400 usb_transfer_batch_t * request) { 420 uint32_t * uint32_buffer = (uint32_t*) request-> data_buffer;401 uint32_t * uint32_buffer = (uint32_t*) request->transport_buffer; 421 402 request->transfered_size = 4; 422 403 //bits, 0,1,16,17 … … 465 446 * bit i indicates change on i`th port (i>0). For more info see 466 447 * Hub and Port status bitmap specification in USB specification 467 * (chapter 11.13.4). 468 * Uses instance`s interrupt buffer to store the interrupt information. 469 * @param instance root hub instance 470 */ 471 static void create_interrupt_mask_in_instance(rh_t * instance) { 472 uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer); 448 * (chapter 11.13.4) 449 * @param instance root hub instance 450 * @param@out buffer pointer to created interrupt mas 451 * @param@out buffer_size size of created interrupt mask 452 */ 453 static void create_interrupt_mask(rh_t *instance, void ** buffer, 454 size_t * buffer_size) { 455 int bit_count = instance->port_count + 1; 456 (*buffer_size) = (bit_count / 8) + ((bit_count % 8 == 0) ? 0 : 1); 457 458 (*buffer) = malloc(*buffer_size); 459 uint8_t * bitmap = (uint8_t*) (*buffer); 473 460 uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16)) 474 461 | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16)); 475 bzero(bitmap, instance->interrupt_mask_size);462 bzero(bitmap, (*buffer_size)); 476 463 if (instance->registers->rh_status & mask) { 477 464 bitmap[0] = 1; … … 504 491 const uint16_t setup_request_value = setup_request->value_high; 505 492 //(setup_request->value_low << 8); 493 bool del = false; 506 494 switch (setup_request_value) { 507 495 case USB_DESCTYPE_HUB: 508 496 { 509 usb_log_debug("USB_DESCTYPE_HUB\n"); 510 result_descriptor = instance->hub_descriptor; 511 size = instance->descriptor_size; 497 uint8_t * descriptor; 498 usb_create_serialized_hub_descriptor( 499 instance, &descriptor, &size); 500 result_descriptor = descriptor; 501 if (result_descriptor) del = true; 512 502 break; 513 503 } … … 559 549 } 560 550 request->transfered_size = size; 561 memcpy(request->data_buffer, result_descriptor, size); 551 memcpy(request->transport_buffer, result_descriptor, size); 552 if (del) 553 free(result_descriptor); 562 554 return EOK; 563 555 } … … 578 570 if (request->buffer_size != 1) 579 571 return EINVAL; 580 request-> data_buffer[0] = 1;572 request->transport_buffer[0] = 1; 581 573 request->transfered_size = 1; 582 574 return EOK; … … 873 865 return opResult; 874 866 } 875 /*----------------------------------------------------------------------------*/876 877 /**878 * process hanging interrupt request879 *880 * If an interrupt transfer has been received and there was no change,881 * the driver stores the transfer information and waits for change to occcur.882 * This routine is called when that happens and it finalizes the interrupt883 * transfer.884 *885 * @param instance hub instance886 * @param request batch request to be processed887 *888 * @return889 */890 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request){891 memcpy(request->data_buffer, instance->interrupt_buffer,892 instance->interrupt_mask_size);893 request->transfered_size = instance->interrupt_mask_size;894 instance->unfinished_interrupt_transfer = NULL;895 usb_transfer_batch_finish_error(request, EOK);896 return EOK;897 }898 899 /*----------------------------------------------------------------------------*/900 901 /**902 * return whether the buffer is full of zeros903 *904 * Convenience function.905 * @param buffer906 * @param size907 * @return908 */909 static bool is_zeros(void * buffer, size_t size){910 if(!buffer) return true;911 if(!size) return true;912 size_t i;913 for(i=0;i<size;++i){914 if(((char*)buffer)[i])915 return false;916 }917 return true;918 }919 867 920 868 /**
Note:
See TracChangeset
for help on using the changeset viewer.