Changes in / [8961c22:61727bf] in mainline
- Location:
- uspace/drv/usbhub
- Files:
-
- 2 added
- 2 deleted
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbhub/Makefile
r8961c22 r61727bf 34 34 SOURCES = \ 35 35 main.c \ 36 ports.c \ 36 37 utils.c \ 37 usbhub.c \ 38 usblist.c 38 usbhub.c 39 39 40 40 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/usbhub/port_status.h
r8961c22 r61727bf 49 49 50 50 /** 51 * structure holding hub status and changes flags.52 * should not be accessed directly, use supplied getter/setter methods.53 *54 * For more information refer to table 11.16.2.5 in55 * "Universal Serial Bus Specification Revision 1.1"56 *57 */58 typedef uint32_t usb_hub_status_t;59 60 /**61 51 * set values in request to be it a port status request 62 52 * @param request … … 64 54 */ 65 55 static inline void usb_hub_set_port_status_request( 66 67 ){56 usb_device_request_setup_packet_t * request, uint16_t port 57 ){ 68 58 request->index = port; 69 59 request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS; … … 73 63 } 74 64 75 /**76 * set values in request to be it a port status request77 * @param request78 * @param port79 */80 static inline void usb_hub_set_hub_status_request(81 usb_device_request_setup_packet_t * request82 ) {83 request->index = 0;84 request->request_type = USB_HUB_REQ_TYPE_GET_HUB_STATUS;85 request->request = USB_HUB_REQUEST_GET_STATUS;86 request->value = 0;87 request->length = 4;88 }89 65 90 66 /** … … 94 70 */ 95 71 static inline usb_device_request_setup_packet_t * 96 usb_hub_create_port_status_request(uint16_t port) 72 usb_hub_create_port_status_request(uint16_t port){ 97 73 usb_device_request_setup_packet_t * result = 98 74 usb_new(usb_device_request_setup_packet_t); 99 usb_hub_set_port_status_request(result, 75 usb_hub_set_port_status_request(result,port); 100 76 return result; 101 77 } 102 78 79 103 80 /** 104 81 * set the device request to be a port feature enable request … … 108 85 */ 109 86 static inline void usb_hub_set_enable_port_feature_request( 110 111 uint16_t feature_selector112 ){87 usb_device_request_setup_packet_t * request, uint16_t port, 88 uint16_t feature_selector 89 ){ 113 90 request->index = port; 114 91 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 125 102 */ 126 103 static inline void usb_hub_set_disable_port_feature_request( 127 128 uint16_t feature_selector129 ){104 usb_device_request_setup_packet_t * request, uint16_t port, 105 uint16_t feature_selector 106 ){ 130 107 request->index = port; 131 108 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 141 118 */ 142 119 static inline void usb_hub_set_enable_port_request( 143 144 ){120 usb_device_request_setup_packet_t * request, uint16_t port 121 ){ 145 122 request->index = port; 146 123 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 156 133 */ 157 134 static inline usb_device_request_setup_packet_t * 158 usb_hub_create_enable_port_request(uint16_t port) 135 usb_hub_create_enable_port_request(uint16_t port){ 159 136 usb_device_request_setup_packet_t * result = 160 137 usb_new(usb_device_request_setup_packet_t); 161 usb_hub_set_enable_port_request(result, 138 usb_hub_set_enable_port_request(result,port); 162 139 return result; 163 140 } … … 169 146 */ 170 147 static inline void usb_hub_set_disable_port_request( 171 172 ){148 usb_device_request_setup_packet_t * request, uint16_t port 149 ){ 173 150 request->index = port; 174 151 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 184 161 */ 185 162 static inline usb_device_request_setup_packet_t * 186 usb_hub_create_disable_port_request(uint16_t port) 163 usb_hub_create_disable_port_request(uint16_t port){ 187 164 usb_device_request_setup_packet_t * result = 188 165 usb_new(usb_device_request_setup_packet_t); 189 usb_hub_set_disable_port_request(result, 166 usb_hub_set_disable_port_request(result,port); 190 167 return result; 191 168 } … … 197 174 */ 198 175 static inline void usb_hub_set_reset_port_request( 199 200 ){176 usb_device_request_setup_packet_t * request, uint16_t port 177 ){ 201 178 request->index = port; 202 179 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 212 189 */ 213 190 static inline usb_device_request_setup_packet_t * 214 usb_hub_create_reset_port_request(uint16_t port) 191 usb_hub_create_reset_port_request(uint16_t port){ 215 192 usb_device_request_setup_packet_t * result = 216 193 usb_new(usb_device_request_setup_packet_t); 217 usb_hub_set_reset_port_request(result, 194 usb_hub_set_reset_port_request(result,port); 218 195 return result; 219 196 } … … 225 202 */ 226 203 static inline void usb_hub_set_power_port_request( 227 228 ){204 usb_device_request_setup_packet_t * request, uint16_t port 205 ){ 229 206 request->index = port; 230 207 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 240 217 */ 241 218 static inline void usb_hub_unset_power_port_request( 242 243 ){219 usb_device_request_setup_packet_t * request, uint16_t port 220 ){ 244 221 request->index = port; 245 222 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 249 226 } 250 227 251 /** 252 * get i`th bit of port status 253 * 254 * @param status 255 * @param idx 256 * @return 257 */ 258 static inline bool usb_port_get_bit(usb_port_status_t * status, int idx) { 259 return ((*status)&(1 << idx))!=0; 260 } 261 262 /** 263 * set i`th bit of port status 264 * 265 * @param status 266 * @param idx 267 * @param value 268 */ 228 229 /** get i`th bit of port status */ 230 static inline bool usb_port_get_bit(usb_port_status_t * status, int idx) 231 { 232 return (((*status)>>(idx))%2); 233 } 234 235 /** set i`th bit of port status */ 269 236 static inline void usb_port_set_bit( 270 usb_port_status_t * status, int idx, bool value) { 271 (*status) = value ? 272 ((*status) | (1 << (idx))) : 273 ((*status)&(~(1 << (idx)))); 274 } 275 276 /** 277 * get i`th bit of hub status 278 * 279 * @param status 280 * @param idx 281 * @return 282 */ 283 static inline bool usb_hub_get_bit(usb_hub_status_t * status, int idx) { 284 return ((*status)&(1 << idx))!=0; 285 } 286 287 /** 288 * set i`th bit of hub status 289 * 290 * @param status 291 * @param idx 292 * @param value 293 */ 294 static inline void usb_hub_set_bit( 295 usb_hub_status_t * status, int idx, bool value) { 296 (*status) = value ? 297 ((*status) | (1 << (idx))) : 298 ((*status)&(~(1 << (idx)))); 299 } 300 301 /** 302 * connection status geter for port status 303 * 304 * @param status 305 * @return true if there is something connected 306 */ 307 static inline bool usb_port_dev_connected(usb_port_status_t * status) { 308 return usb_port_get_bit(status, 0); 309 } 310 311 /** 312 * set device connected bit in port status 313 * 314 * @param status 315 * @param connected value of the bit 316 */ 317 static inline void usb_port_set_dev_connected(usb_port_status_t * status, bool connected) { 318 usb_port_set_bit(status, 0, connected); 237 usb_port_status_t * status, int idx, bool value) 238 { 239 (*status) = value? 240 ((*status)|(1<<(idx))): 241 ((*status)&(~(1<<(idx)))); 242 } 243 244 //device connnected on port 245 static inline bool usb_port_dev_connected(usb_port_status_t * status){ 246 return usb_port_get_bit(status,0); 247 } 248 249 static inline void usb_port_set_dev_connected(usb_port_status_t * status,bool connected){ 250 usb_port_set_bit(status,0,connected); 319 251 } 320 252 321 253 //port enabled 322 323 /** 324 * port enabled getter for port status 325 * 326 * @param status 327 * @return true if the port is enabled 328 */ 329 static inline bool usb_port_enabled(usb_port_status_t * status) { 330 return usb_port_get_bit(status, 1); 331 } 332 333 /** 334 * set port enabled bit in port status 335 * 336 * @param status 337 * @param enabled value of the bit 338 */ 339 static inline void usb_port_set_enabled(usb_port_status_t * status, bool enabled) { 340 usb_port_set_bit(status, 1, enabled); 254 static inline bool usb_port_enabled(usb_port_status_t * status){ 255 return usb_port_get_bit(status,1); 256 } 257 258 static inline void usb_port_set_enabled(usb_port_status_t * status,bool enabled){ 259 usb_port_set_bit(status,1,enabled); 341 260 } 342 261 343 262 //port suspended 344 /** 345 * port suspended getter for port status 346 * 347 * @param status 348 * @return true if port is suspended 349 */ 350 static inline bool usb_port_suspended(usb_port_status_t * status) { 351 return usb_port_get_bit(status, 2); 352 } 353 354 /** 355 * set port suspended bit in port status 356 * 357 * @param status 358 * @param suspended value of the bit 359 */ 360 static inline void usb_port_set_suspended(usb_port_status_t * status, bool suspended) { 361 usb_port_set_bit(status, 2, suspended); 263 static inline bool usb_port_suspended(usb_port_status_t * status){ 264 return usb_port_get_bit(status,2); 265 } 266 267 static inline void usb_port_set_suspended(usb_port_status_t * status,bool suspended){ 268 usb_port_set_bit(status,2,suspended); 362 269 } 363 270 364 271 //over currect 365 /** 366 * over current condition indicator getter for port status 367 * 368 * @param status 369 * @return true if there is opver-current condition on the hub 370 */ 371 static inline bool usb_port_over_current(usb_port_status_t * status) { 372 return usb_port_get_bit(status, 3); 373 } 374 375 /** 376 * set over current indicator bit in port status 377 * 378 * @param status 379 * @param value value of the bit 380 */ 381 static inline void usb_port_set_over_current(usb_port_status_t * status, bool value) { 382 usb_port_set_bit(status, 3, value); 272 static inline bool usb_port_over_current(usb_port_status_t * status){ 273 return usb_port_get_bit(status,3); 274 } 275 276 static inline void usb_port_set_over_current(usb_port_status_t * status,bool value){ 277 usb_port_set_bit(status,3,value); 383 278 } 384 279 385 280 //port reset 386 /** 387 * port reset indicator getter for port status 388 * 389 * @param status 390 * @return true if port is reset 391 */ 392 static inline bool usb_port_reset(usb_port_status_t * status) { 393 return usb_port_get_bit(status, 4); 394 } 395 396 /** 397 * set port reset bit in port status 398 * 399 * @param status 400 * @param value value of the bit 401 */ 402 static inline void usb_port_set_reset(usb_port_status_t * status, bool value) { 403 usb_port_set_bit(status, 4, value); 281 static inline bool usb_port_reset(usb_port_status_t * status){ 282 return usb_port_get_bit(status,4); 283 } 284 285 static inline void usb_port_set_reset(usb_port_status_t * status,bool value){ 286 usb_port_set_bit(status,4,value); 404 287 } 405 288 406 289 //powered 407 /** 408 * power state getter for port status 409 * 410 * @param status 411 * @return true if port is powered 412 */ 413 static inline bool usb_port_powered(usb_port_status_t * status) { 414 return usb_port_get_bit(status, 8); 415 } 416 417 /** 418 * set port powered bit in port status 419 * 420 * @param status 421 * @param powered value of the bit 422 */ 423 static inline void usb_port_set_powered(usb_port_status_t * status, bool powered) { 424 usb_port_set_bit(status, 8, powered); 290 static inline bool usb_port_powered(usb_port_status_t * status){ 291 return usb_port_get_bit(status,8); 292 } 293 294 static inline void usb_port_set_powered(usb_port_status_t * status,bool powered){ 295 usb_port_set_bit(status,8,powered); 425 296 } 426 297 427 298 //low speed device attached 428 /** 429 * low speed device on the port indicator 430 * 431 * @param status 432 * @return true if low speed device is attached 433 */ 434 static inline bool usb_port_low_speed(usb_port_status_t * status) { 435 return usb_port_get_bit(status, 9); 436 } 437 438 /** 439 * set device connected bit in port status 440 * 441 * @param status 442 * @param low_speed value of the bit 443 */ 444 static inline void usb_port_set_low_speed(usb_port_status_t * status, bool low_speed) { 445 usb_port_set_bit(status, 9, low_speed); 446 } 447 448 //high speed device attached 449 /** 450 * high speed device on the port indicator 451 * 452 * @param status 453 * @return true if high speed device is on port 454 */ 455 static inline bool usb_port_high_speed(usb_port_status_t * status) { 456 return usb_port_get_bit(status, 10); 457 } 458 459 /** 460 * set high speed device bit in port status 461 * 462 * @param status 463 * @param high_speed value of the bit 464 */ 465 static inline void usb_port_set_high_speed(usb_port_status_t * status, bool high_speed) { 466 usb_port_set_bit(status, 10, high_speed); 467 } 468 469 /** 470 * speed getter for port status 471 * 472 * @param status 473 * @return speed of usb device (for more see usb specification) 474 */ 475 static inline usb_speed_t usb_port_speed(usb_port_status_t * status) { 476 if (usb_port_low_speed(status)) 299 static inline bool usb_port_low_speed(usb_port_status_t * status){ 300 return usb_port_get_bit(status,9); 301 } 302 303 static inline void usb_port_set_low_speed(usb_port_status_t * status,bool low_speed){ 304 usb_port_set_bit(status,9,low_speed); 305 } 306 307 //low speed device attached 308 static inline bool usb_port_high_speed(usb_port_status_t * status){ 309 return usb_port_get_bit(status,10); 310 } 311 312 static inline void usb_port_set_high_speed(usb_port_status_t * status,bool high_speed){ 313 usb_port_set_bit(status,10,high_speed); 314 } 315 316 static inline usb_speed_t usb_port_speed(usb_port_status_t * status){ 317 if(usb_port_low_speed(status)) 477 318 return USB_SPEED_LOW; 478 if 319 if(usb_port_high_speed(status)) 479 320 return USB_SPEED_HIGH; 480 321 return USB_SPEED_FULL; … … 483 324 484 325 //connect change 485 /** 486 * port connect change indicator 487 * 488 * @param status 489 * @return true if connection has changed 490 */ 491 static inline bool usb_port_connect_change(usb_port_status_t * status) { 492 return usb_port_get_bit(status, 16); 493 } 494 495 /** 496 * set connection change bit in port status 497 * @param status 498 * @param change value of the bit 499 */ 500 static inline void usb_port_set_connect_change(usb_port_status_t * status, bool change) { 501 usb_port_set_bit(status, 16, change); 326 static inline bool usb_port_connect_change(usb_port_status_t * status){ 327 return usb_port_get_bit(status,16); 328 } 329 330 static inline void usb_port_set_connect_change(usb_port_status_t * status,bool change){ 331 usb_port_set_bit(status,16,change); 502 332 } 503 333 504 334 //port enable change 505 /** 506 * port enable change for port status 507 * 508 * @param status 509 * @return true if the port has been enabled/disabled 510 */ 511 static inline bool usb_port_enabled_change(usb_port_status_t * status) { 512 return usb_port_get_bit(status, 17); 513 } 514 515 /** 516 * set port enable change bit in port status 517 * 518 * @param status 519 * @param change value of the bit 520 */ 521 static inline void usb_port_set_enabled_change(usb_port_status_t * status, bool change) { 522 usb_port_set_bit(status, 17, change); 335 static inline bool usb_port_enabled_change(usb_port_status_t * status){ 336 return usb_port_get_bit(status,17); 337 } 338 339 static inline void usb_port_set_enabled_change(usb_port_status_t * status,bool change){ 340 usb_port_set_bit(status,17,change); 523 341 } 524 342 525 343 //suspend change 526 /** 527 * port suspend change for port status 528 * 529 * @param status 530 * @return ture if suspend status has changed 531 */ 532 static inline bool usb_port_suspend_change(usb_port_status_t * status) { 533 return usb_port_get_bit(status, 18); 534 } 535 536 /** 537 * set port suspend change bit in port status 538 * 539 * @param status 540 * @param change value of the bit 541 */ 542 static inline void usb_port_set_suspend_change(usb_port_status_t * status, bool change) { 543 usb_port_set_bit(status, 18, change); 344 static inline bool usb_port_suspend_change(usb_port_status_t * status){ 345 return usb_port_get_bit(status,18); 346 } 347 348 static inline void usb_port_set_suspend_change(usb_port_status_t * status,bool change){ 349 usb_port_set_bit(status,18,change); 544 350 } 545 351 546 352 //over current change 547 /** 548 * over current change indicator 549 * 550 * @param status 551 * @return true if over-current condition on port has changed 552 */ 553 static inline bool usb_port_overcurrent_change(usb_port_status_t * status) { 554 return usb_port_get_bit(status, 19); 555 } 556 557 /** 558 * set port over current change bit in port status 559 * 560 * @param status 561 * @param change value of the bit 562 */ 563 static inline void usb_port_set_overcurrent_change(usb_port_status_t * status, bool change) { 564 usb_port_set_bit(status, 19, change); 353 static inline bool usb_port_overcurrent_change(usb_port_status_t * status){ 354 return usb_port_get_bit(status,19); 355 } 356 357 static inline void usb_port_set_overcurrent_change(usb_port_status_t * status,bool change){ 358 usb_port_set_bit(status,19,change); 565 359 } 566 360 567 361 //reset change 568 /** 569 * port reset change indicator 570 * @param status 571 * @return true if port has been reset 572 */ 573 static inline bool usb_port_reset_completed(usb_port_status_t * status) { 574 return usb_port_get_bit(status, 20); 575 } 576 577 /** 578 * set port reset completed bit in port status 579 * 580 * @param status 581 * @param change value of the bit 582 */ 583 static inline void usb_port_set_reset_completed(usb_port_status_t * status, bool completed) { 584 usb_port_set_bit(status, 20, completed); 585 } 586 587 //local power status 588 /** 589 * local power lost indicator for hub status 590 * 591 * @param status 592 * @return true if hub is not powered 593 */ 594 static inline bool usb_hub_local_power_lost(usb_hub_status_t * status) { 595 return usb_hub_get_bit(status, 0); 596 } 597 598 /** 599 * set hub power lost bit in hub status 600 * 601 * @param status 602 * @param change value of the bit 603 */ 604 static inline void usb_hub_set_local_power_lost(usb_port_status_t * status, 605 bool power_lost) { 606 usb_hub_set_bit(status, 0, power_lost); 607 } 608 609 //over current ocndition 610 /** 611 * hub over-current indicator 612 * 613 * @param status 614 * @return true if over-current condition occurred on hub 615 */ 616 static inline bool usb_hub_over_current(usb_hub_status_t * status) { 617 return usb_hub_get_bit(status, 1); 618 } 619 620 /** 621 * set hub over current bit in hub status 622 * 623 * @param status 624 * @param change value of the bit 625 */ 626 static inline void usb_hub_set_over_current(usb_port_status_t * status, 627 bool over_current) { 628 usb_hub_set_bit(status, 1, over_current); 629 } 630 631 //local power change 632 /** 633 * hub power change indicator 634 * 635 * @param status 636 * @return true if local power status has been changed - power has been 637 * dropped or re-established 638 */ 639 static inline bool usb_hub_local_power_change(usb_hub_status_t * status) { 640 return usb_hub_get_bit(status, 16); 641 } 642 643 /** 644 * set hub power change bit in hub status 645 * 646 * @param status 647 * @param change value of the bit 648 */ 649 static inline void usb_hub_set_local_power_change(usb_port_status_t * status, 650 bool change) { 651 usb_hub_set_bit(status, 16, change); 652 } 653 654 //local power status 655 /** 656 * hub over-current condition change indicator 657 * 658 * @param status 659 * @return true if over-current condition has changed 660 */ 661 static inline bool usb_hub_over_current_change(usb_hub_status_t * status) { 662 return usb_hub_get_bit(status, 17); 663 } 664 665 /** 666 * set hub over current change bit in hub status 667 * 668 * @param status 669 * @param change value of the bit 670 */ 671 static inline void usb_hub_set_over_current_change(usb_port_status_t * status, 672 bool change) { 673 usb_hub_set_bit(status, 17, change); 674 } 362 static inline bool usb_port_reset_completed(usb_port_status_t * status){ 363 return usb_port_get_bit(status,20); 364 } 365 366 static inline void usb_port_set_reset_completed(usb_port_status_t * status,bool completed){ 367 usb_port_set_bit(status,20,completed); 368 } 369 675 370 676 371 -
uspace/drv/usbhub/usbhub.c
r8961c22 r61727bf 37 37 #include <errno.h> 38 38 #include <str_error.h> 39 #include <inttypes.h>40 39 41 40 #include <usb_iface.h> … … 54 53 #include "usb/classes/classes.h" 55 54 56 57 /** Information for fibril for device discovery. */ 58 struct add_device_phase1 { 59 usb_hub_info_t *hub; 60 size_t port; 61 usb_speed_t speed; 62 }; 63 64 65 static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev); 66 67 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info); 68 69 static int usb_hub_set_configuration(usb_hub_info_t * hub_info); 70 71 static int usb_hub_release_default_address(usb_hub_info_t * hub); 72 73 //static int usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port, 74 // usb_speed_t speed); 75 76 //static void usb_hub_finalize_add_device(usb_hub_info_t * hub, 77 // uint16_t port, usb_speed_t speed); 78 79 static void usb_hub_removed_device( 80 usb_hub_info_t * hub, uint16_t port); 81 82 static void usb_hub_port_over_current(usb_hub_info_t * hub, 83 uint16_t port, uint32_t status); 84 85 static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port, 86 usb_port_status_t *status); 87 88 static int enable_port_callback(int port_no, void *arg); 89 90 static int add_device_phase1_worker_fibril(void *arg); 91 92 static int add_device_phase1_new_fibril(usb_hub_info_t *hub, size_t port, 93 usb_speed_t speed); 94 95 static void usb_hub_process_interrupt(usb_hub_info_t * hub, 96 uint16_t port); 97 98 static int usb_process_hub_over_current(usb_hub_info_t * hub_info, 99 usb_hub_status_t status); 100 101 static int usb_process_hub_power_change(usb_hub_info_t * hub_info, 102 usb_hub_status_t status); 103 104 static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info); 105 106 //static int initialize_non_removable(usb_hub_info_t * hub_info, 107 // unsigned int port); 108 109 //static int usb_hub_trigger_connecting_non_removable_devices( 110 // usb_hub_info_t * hub, usb_hub_descriptor_t * descriptor); 111 112 113 /** 114 * control loop running in hub`s fibril 115 * 116 * Hub`s fibril periodically asks for changes on hub and if needded calls 117 * change handling routine. 118 * @warning currently hub driver asks for changes once a second 119 * @param hub_info_param hub representation pointer 120 * @return zero 121 */ 122 /* 123 int usb_hub_control_loop(void * hub_info_param) { 124 usb_hub_info_t * hub_info = (usb_hub_info_t*) hub_info_param; 125 int errorCode = EOK; 126 127 while (errorCode == EOK) { 128 async_usleep(1000 * 1000 * 10); /// \TODO proper number once 129 errorCode = usb_hub_check_hub_changes(hub_info); 130 } 131 usb_log_error("something in ctrl loop went wrong, errno %d\n", 132 errorCode); 133 134 return 0; 135 } 136 */ 137 /// \TODO malloc checking 55 static int usb_hub_trigger_connecting_non_removable_devices( 56 usb_hub_info_t * hub, usb_hub_descriptor_t * descriptor); 57 138 58 139 59 //********************************************* … … 143 63 //********************************************* 144 64 145 65 /** 66 * create usb_hub_info_t structure 67 * 68 * Does only basic copying of known information into new structure. 69 * @param usb_dev usb device structure 70 * @return basic usb_hub_info_t structure 71 */ 72 static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev) { 73 usb_hub_info_t * result = usb_new(usb_hub_info_t); 74 if(!result) return NULL; 75 result->usb_device = usb_dev; 76 result->status_change_pipe = usb_dev->pipes[0].pipe; 77 result->control_pipe = &usb_dev->ctrl_pipe; 78 result->is_default_address_used = false; 79 return result; 80 } 81 82 /** 83 * Load hub-specific information into hub_info structure and process if needed 84 * 85 * Particularly read port count and initialize structure holding port 86 * information. If there are non-removable devices, start initializing them. 87 * This function is hub-specific and should be run only after the hub is 88 * configured using usb_hub_set_configuration function. 89 * @param hub_info hub representation 90 * @return error code 91 */ 92 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info){ 93 // get hub descriptor 94 usb_log_debug("creating serialized descriptor\n"); 95 void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE); 96 usb_hub_descriptor_t * descriptor; 97 98 /* this was one fix of some bug, should not be needed anymore 99 * these lines allow to reset hub once more, it can be used as 100 * brute-force initialization for non-removable devices 101 int opResult = usb_request_set_configuration(&result->endpoints.control, 1); 102 if(opResult!=EOK){ 103 usb_log_error("could not set default configuration, errno %d",opResult); 104 return opResult; 105 } 106 */ 107 size_t received_size; 108 int opResult = usb_request_get_descriptor(&hub_info->usb_device->ctrl_pipe, 109 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE, 110 USB_DESCTYPE_HUB, 111 0, 0, serialized_descriptor, 112 USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size); 113 114 if (opResult != EOK) { 115 usb_log_error("failed when receiving hub descriptor, badcode = %d\n", 116 opResult); 117 free(serialized_descriptor); 118 return opResult; 119 } 120 usb_log_debug2("deserializing descriptor\n"); 121 descriptor = usb_deserialize_hub_desriptor(serialized_descriptor); 122 if(descriptor==NULL){ 123 usb_log_warning("could not deserialize descriptor \n"); 124 return opResult; 125 } 126 usb_log_debug("setting port count to %d\n",descriptor->ports_count); 127 hub_info->port_count = descriptor->ports_count; 128 hub_info->ports = malloc(sizeof(usb_hub_port_t) * (hub_info->port_count+1)); 129 size_t port; 130 for (port = 0; port < hub_info->port_count + 1; port++) { 131 usb_hub_port_init(&hub_info->ports[port]); 132 } 133 //handle non-removable devices 134 usb_hub_trigger_connecting_non_removable_devices(hub_info, descriptor); 135 usb_log_debug2("freeing data\n"); 136 free(serialized_descriptor); 137 free(descriptor->devices_removable); 138 free(descriptor); 139 return EOK; 140 } 141 /** 142 * Set configuration of hub 143 * 144 * Check whether there is at least one configuration and sets the first one. 145 * This function should be run prior to running any hub-specific action. 146 * @param hub_info hub representation 147 * @return error code 148 */ 149 static int usb_hub_set_configuration(usb_hub_info_t * hub_info){ 150 //device descriptor 151 usb_standard_device_descriptor_t *std_descriptor 152 = &hub_info->usb_device->descriptors.device; 153 usb_log_debug("hub has %d configurations\n", 154 std_descriptor->configuration_count); 155 if(std_descriptor->configuration_count<1){ 156 usb_log_error("there are no configurations available\n"); 157 return EINVAL; 158 } 159 160 usb_standard_configuration_descriptor_t *config_descriptor 161 = (usb_standard_configuration_descriptor_t *) 162 hub_info->usb_device->descriptors.configuration; 163 164 /* Set configuration. */ 165 int opResult = usb_request_set_configuration( 166 &hub_info->usb_device->ctrl_pipe, 167 config_descriptor->configuration_number); 168 169 if (opResult != EOK) { 170 usb_log_error("Failed to set hub configuration: %s.\n", 171 str_error(opResult)); 172 return opResult; 173 } 174 usb_log_debug("\tused configuration %d\n", 175 config_descriptor->configuration_number); 176 177 return EOK; 178 } 146 179 147 180 /** … … 153 186 * @return error code 154 187 */ 155 int usb_hub_add_device(usb_device_t * usb_dev) 156 if 188 int usb_hub_add_device(usb_device_t * usb_dev){ 189 if(!usb_dev) return EINVAL; 157 190 usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev); 158 191 //create hc connection 159 192 usb_log_debug("Initializing USB wire abstraction.\n"); 160 193 int opResult = usb_hc_connection_initialize_from_device( 161 &hub_info->connection, 162 hub_info->usb_device->ddf_dev); 163 if (opResult != EOK) { 164 usb_log_error("could not initialize connection to device, " 165 "errno %d\n", 166 opResult); 194 &hub_info->connection, 195 hub_info->usb_device->ddf_dev); 196 if(opResult != EOK){ 197 usb_log_error("could not initialize connection to device, errno %d\n", 198 opResult); 167 199 free(hub_info); 168 200 return opResult; 169 201 } 170 202 171 203 usb_pipe_start_session(hub_info->control_pipe); 172 204 //set hub configuration 173 205 opResult = usb_hub_set_configuration(hub_info); 174 if (opResult != EOK) { 175 usb_log_error("could not set hub configuration, errno %d\n", 176 opResult); 206 if(opResult!=EOK){ 207 usb_log_error("could not set hub configuration, errno %d\n",opResult); 177 208 free(hub_info); 178 209 return opResult; … … 180 211 //get port count and create attached_devs 181 212 opResult = usb_hub_process_hub_specific_info(hub_info); 182 if (opResult != EOK) { 183 usb_log_error("could not set hub configuration, errno %d\n", 184 opResult); 213 if(opResult!=EOK){ 214 usb_log_error("could not set hub configuration, errno %d\n",opResult); 185 215 free(hub_info); 186 216 return opResult; … … 192 222 usb_log_debug("Creating `hub' function.\n"); 193 223 ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev, 194 fun_exposed, "hub");224 fun_exposed, "hub"); 195 225 assert(hub_fun != NULL); 196 226 hub_fun->ops = NULL; … … 234 264 235 265 usb_log_info("Controlling hub `%s' (%d ports).\n", 236 266 hub_info->usb_device->ddf_dev->name, hub_info->port_count); 237 267 return EOK; 268 238 269 leave: 239 270 free(hub_info); … … 249 280 //********************************************* 250 281 251 252 /** Callback for polling hub for port changes. 253 * 254 * @param dev Device where the change occured.255 * @param change_bitmap Bitmap of changed ports.256 * @param change_bitmap_size Size of the bitmap in bytes.257 * @param arg Custom argument, points to @c usb_hub_info_t.258 * @return Whether to continue polling.259 */ 260 bool hub_port_changes_callback(usb_device_t *dev,261 uint8_t *change_bitmap, size_t change_bitmap_size, void *arg)282 /** 283 * triggers actions to connect non0removable devices 284 * 285 * This will trigger operations leading to activated non-removable device. 286 * Control pipe of the hub must be open fo communication. 287 * @param hub hub representation 288 * @param descriptor usb hub descriptor 289 * @return error code 290 */ 291 static int usb_hub_trigger_connecting_non_removable_devices(usb_hub_info_t * hub, 292 usb_hub_descriptor_t * descriptor) 262 293 { 263 usb_hub_info_t *hub = (usb_hub_info_t *) arg; 264 265 /* FIXME: check that we received enough bytes. */ 266 if (change_bitmap_size == 0) { 267 goto leave; 268 } 269 270 size_t port; 271 for (port = 1; port < hub->port_count + 1; port++) { 272 bool change = (change_bitmap[port / 8] >> (port % 8)) % 2; 273 if (change) { 274 usb_hub_process_interrupt(hub, port); 275 } 276 } 277 278 279 leave: 280 /* FIXME: proper interval. */ 281 async_usleep(1000 * 1000 * 10 ); 282 283 return true; 284 } 285 286 287 /** 288 * check changes on hub 289 * 290 * Handles changes on each port with a status change. 291 * @param hub_info hub representation 292 * @return error code 293 */ 294 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info) { 294 usb_log_info("attaching non-removable devices(if any)\n"); 295 usb_device_request_setup_packet_t request; 295 296 int opResult; 296 opResult = usb_pipe_start_session( 297 hub_info->status_change_pipe); 298 //this might not be necessary - if all non-removables are ok, it is 299 //not needed here 300 opResult = usb_pipe_start_session(hub_info->control_pipe); 301 if (opResult != EOK) { 302 usb_log_error("could not initialize communication for hub; %d\n", 303 opResult); 304 return opResult; 305 } 306 307 size_t port_count = hub_info->port_count; 308 //first check non-removable devices 309 /* 310 { 311 unsigned int port; 312 for (port = 0; port < port_count; ++port) { 313 bool is_non_removable = 314 hub_info->not_initialized_non_removables[port/8] 315 & (1 << (port-1 % 8)); 316 if (is_non_removable) { 317 opResult = initialize_non_removable(hub_info, 318 port+1); 297 size_t rcvd_size; 298 usb_port_status_t status; 299 uint8_t * non_removable_dev_bitmap = descriptor->devices_removable; 300 int port; 301 for(port=1;port<=descriptor->ports_count;++port){ 302 bool is_non_removable = 303 ((non_removable_dev_bitmap[port/8]) >> (port%8)) %2; 304 if(is_non_removable){ 305 usb_log_debug("non-removable device on port %d\n",port); 306 usb_hub_set_port_status_request(&request, port); 307 opResult = usb_pipe_control_read( 308 hub->control_pipe, 309 &request, sizeof(usb_device_request_setup_packet_t), 310 &status, 4, &rcvd_size 311 ); 312 if (opResult != EOK) { 313 usb_log_error("could not get port status of port %d errno:%d\n", 314 port, opResult); 315 return opResult; 316 } 317 //set the status change bit, so it will be noticed in driver loop 318 if(usb_port_dev_connected(&status)){ 319 usb_hub_set_disable_port_feature_request(&request, port, 320 USB_HUB_FEATURE_PORT_CONNECTION); 321 opResult = usb_pipe_control_read( 322 hub->control_pipe, 323 &request, sizeof(usb_device_request_setup_packet_t), 324 &status, 4, &rcvd_size 325 ); 326 if (opResult != EOK) { 327 usb_log_warning( 328 "could not clear port connection on port %d errno:%d\n", 329 port, opResult); 330 } 331 usb_log_debug("cleared port connection\n"); 332 usb_hub_set_enable_port_feature_request(&request, port, 333 USB_HUB_FEATURE_PORT_ENABLE); 334 opResult = usb_pipe_control_read( 335 hub->control_pipe, 336 &request, sizeof(usb_device_request_setup_packet_t), 337 &status, 4, &rcvd_size 338 ); 339 if (opResult != EOK) { 340 usb_log_warning( 341 "could not set port enabled on port %d errno:%d\n", 342 port, opResult); 343 } 344 usb_log_debug("port set to enabled - should lead to connection change\n"); 319 345 } 320 346 } 321 347 } 322 */ 323 324 /// FIXME: count properly 325 size_t byte_length = ((port_count + 1) / 8) + 1; 326 void *change_bitmap = malloc(byte_length); 327 size_t actual_size; 328 329 /* 330 * Send the request. 331 */ 332 opResult = usb_pipe_read( 333 hub_info->status_change_pipe, 334 change_bitmap, byte_length, &actual_size 335 ); 336 337 if (opResult != EOK) { 338 free(change_bitmap); 339 usb_log_warning("something went wrong while getting the" 340 "status of hub\n"); 341 usb_pipe_end_session(hub_info->status_change_pipe); 342 return opResult; 343 } 344 unsigned int port; 345 346 if (opResult != EOK) { 347 usb_log_error("could not start control pipe session %d\n", 348 opResult); 349 usb_pipe_end_session(hub_info->status_change_pipe); 350 return opResult; 351 } 352 opResult = usb_hc_connection_open(&hub_info->connection); 353 if (opResult != EOK) { 354 usb_log_error("could not start host controller session %d\n", 355 opResult); 356 usb_pipe_end_session(hub_info->control_pipe); 357 usb_pipe_end_session(hub_info->status_change_pipe); 358 return opResult; 359 } 360 361 ///todo, opresult check, pre obe konekce 362 bool interrupt; 363 interrupt = ((uint8_t*)change_bitmap)[0] & 1; 364 if(interrupt){ 365 usb_hub_process_global_interrupt(hub_info); 366 } 367 for (port = 1; port < port_count + 1; ++port) { 368 interrupt = 369 ((uint8_t*) change_bitmap)[port / 8] & (1<<(port % 8)); 370 if (interrupt) { 371 usb_hub_process_interrupt( 372 hub_info, port); 348 /// \TODO this is just a debug code 349 for(port=1;port<=descriptor->ports_count;++port){ 350 bool is_non_removable = 351 ((non_removable_dev_bitmap[port/8]) >> (port%8)) %2; 352 if(is_non_removable){ 353 usb_log_debug("port %d is non-removable\n",port); 354 usb_port_status_t status; 355 size_t rcvd_size; 356 usb_device_request_setup_packet_t request; 357 //int opResult; 358 usb_hub_set_port_status_request(&request, port); 359 //endpoint 0 360 opResult = usb_pipe_control_read( 361 hub->control_pipe, 362 &request, sizeof(usb_device_request_setup_packet_t), 363 &status, 4, &rcvd_size 364 ); 365 if (opResult != EOK) { 366 usb_log_error("could not get port status %d\n",opResult); 367 } 368 if (rcvd_size != sizeof (usb_port_status_t)) { 369 usb_log_error("received status has incorrect size\n"); 370 } 371 //something connected/disconnected 372 if (usb_port_connect_change(&status)) { 373 usb_log_debug("some connection changed\n"); 374 } 375 usb_log_debug("status: %s\n",usb_debug_str_buffer( 376 (uint8_t *)&status,4,4)); 373 377 } 374 378 } 375 /// \todo check hub status376 usb_hc_connection_close(&hub_info->connection);377 usb_pipe_end_session(hub_info->control_pipe);378 usb_pipe_end_session(hub_info->status_change_pipe);379 free(change_bitmap);380 379 return EOK; 381 380 } 382 381 383 //*********************************************384 //385 // support functions386 //387 //*********************************************388 389 /**390 * create usb_hub_info_t structure391 *392 * Does only basic copying of known information into new structure.393 * @param usb_dev usb device structure394 * @return basic usb_hub_info_t structure395 */396 static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev) {397 usb_hub_info_t * result = usb_new(usb_hub_info_t);398 if (!result) return NULL;399 result->usb_device = usb_dev;400 result->status_change_pipe = usb_dev->pipes[0].pipe;401 result->control_pipe = &usb_dev->ctrl_pipe;402 result->is_default_address_used = false;403 return result;404 }405 406 407 /**408 * Load hub-specific information into hub_info structure and process if needed409 *410 * Particularly read port count and initialize structure holding port411 * information. If there are non-removable devices, start initializing them.412 * This function is hub-specific and should be run only after the hub is413 * configured using usb_hub_set_configuration function.414 * @param hub_info hub representation415 * @return error code416 */417 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info) {418 // get hub descriptor419 usb_log_debug("creating serialized descriptor\n");420 void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE);421 usb_hub_descriptor_t * descriptor;422 int opResult;423 424 /* this was one fix of some bug, should not be needed anymore425 * these lines allow to reset hub once more, it can be used as426 * brute-force initialization for non-removable devices427 *428 opResult = usb_request_set_configuration(hub_info->control_pipe,429 1);430 if (opResult != EOK) {431 usb_log_error("could not set default configuration, errno %d",432 opResult);433 return opResult;434 }*/435 436 437 size_t received_size;438 opResult = usb_request_get_descriptor(hub_info->control_pipe,439 USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,440 USB_DESCTYPE_HUB,441 0, 0, serialized_descriptor,442 USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);443 444 if (opResult != EOK) {445 usb_log_error("failed when receiving hub descriptor, "446 "badcode = %d\n",447 opResult);448 free(serialized_descriptor);449 return opResult;450 }451 usb_log_debug2("deserializing descriptor\n");452 descriptor = usb_deserialize_hub_desriptor(serialized_descriptor);453 if (descriptor == NULL) {454 usb_log_warning("could not deserialize descriptor \n");455 return opResult;456 }457 usb_log_debug("setting port count to %d\n", descriptor->ports_count);458 hub_info->port_count = descriptor->ports_count;459 /// \TODO check attached_devices array: this is not semantically correct460 //hub_info->attached_devs = (usb_hc_attached_device_t*)461 // malloc((hub_info->port_count + 1) *462 // sizeof (usb_hc_attached_device_t)463 // );464 hub_info->ports = malloc(sizeof(usb_hub_port_t) * (hub_info->port_count+1));465 size_t port;466 for (port = 0; port < hub_info->port_count + 1; port++) {467 usb_hub_port_init(&hub_info->ports[port]);468 }469 //handle non-removable devices470 //usb_hub_trigger_connecting_non_removable_devices(hub_info, descriptor);471 usb_log_debug2("freeing data\n");472 free(serialized_descriptor);473 free(descriptor->devices_removable);474 free(descriptor);475 return EOK;476 }477 478 /**479 * Set configuration of hub480 *481 * Check whether there is at least one configuration and sets the first one.482 * This function should be run prior to running any hub-specific action.483 * @param hub_info hub representation484 * @return error code485 */486 static int usb_hub_set_configuration(usb_hub_info_t * hub_info) {487 //device descriptor488 usb_standard_device_descriptor_t *std_descriptor489 = &hub_info->usb_device->descriptors.device;490 usb_log_debug("hub has %d configurations\n",491 std_descriptor->configuration_count);492 if (std_descriptor->configuration_count < 1) {493 usb_log_error("there are no configurations available\n");494 return EINVAL;495 }496 497 usb_standard_configuration_descriptor_t *config_descriptor498 = (usb_standard_configuration_descriptor_t *)499 hub_info->usb_device->descriptors.configuration;500 501 /* Set configuration. */502 int opResult = usb_request_set_configuration(503 &hub_info->usb_device->ctrl_pipe,504 config_descriptor->configuration_number);505 506 if (opResult != EOK) {507 usb_log_error("Failed to set hub configuration: %s.\n",508 str_error(opResult));509 return opResult;510 }511 usb_log_debug("\tused configuration %d\n",512 config_descriptor->configuration_number);513 514 return EOK;515 }516 382 517 383 /** … … 523 389 * @return error code 524 390 */ 525 static int usb_hub_release_default_address(usb_hub_info_t * hub) 391 static int usb_hub_release_default_address(usb_hub_info_t * hub){ 526 392 int opResult = usb_hc_release_default_address(&hub->connection); 527 if (opResult != EOK) { 528 usb_log_error("could not release default address, errno %d\n", 529 opResult); 393 if(opResult!=EOK){ 394 usb_log_error("could not release default address, errno %d\n",opResult); 530 395 return opResult; 531 396 } … … 533 398 return EOK; 534 399 } 535 536 #if 0537 /**538 * Reset the port with new device and reserve the default address.539 * @param hub hub representation540 * @param port port number, starting from 1541 * @param speed transfer speed of attached device, one of low, full or high542 * @return error code543 */544 static int usb_hub_init_add_device(usb_hub_info_t * hub, uint16_t port,545 usb_speed_t speed) {546 //if this hub already uses default address, it cannot request it once more547 if (hub->is_default_address_used) {548 usb_log_info("default address used, another time\n");549 return EREFUSED;550 }551 usb_log_debug("some connection changed\n");552 assert(hub->control_pipe->hc_phone);553 int opResult = usb_hub_clear_port_feature(hub->control_pipe,554 port, USB_HUB_FEATURE_C_PORT_CONNECTION);555 if (opResult != EOK) {556 usb_log_warning("could not clear port-change-connection flag\n");557 }558 usb_device_request_setup_packet_t request;559 560 //get default address561 opResult = usb_hc_reserve_default_address(&hub->connection, speed);562 563 if (opResult != EOK) {564 usb_log_warning("cannot assign default address, it is probably "565 "used %d\n",566 opResult);567 return opResult;568 }569 hub->is_default_address_used = true;570 //reset port571 usb_hub_set_reset_port_request(&request, port);572 opResult = usb_pipe_control_write(573 hub->control_pipe,574 &request, sizeof (usb_device_request_setup_packet_t),575 NULL, 0576 );577 if (opResult != EOK) {578 usb_log_error("something went wrong when reseting a port %d\n",579 opResult);580 usb_hub_release_default_address(hub);581 }582 return opResult;583 }584 #endif585 586 #if 0587 /**588 * Finalize adding new device after port reset589 *590 * Set device`s address and start it`s driver.591 * @param hub hub representation592 * @param port port number, starting from 1593 * @param speed transfer speed of attached device, one of low, full or high594 */595 static void usb_hub_finalize_add_device(usb_hub_info_t * hub,596 uint16_t port, usb_speed_t speed) {597 598 int opResult;599 usb_log_debug("finalizing add device\n");600 opResult = usb_hub_clear_port_feature(hub->control_pipe,601 port, USB_HUB_FEATURE_C_PORT_RESET);602 603 if (opResult != EOK) {604 usb_log_error("failed to clear port reset feature\n");605 usb_hub_release_default_address(hub);606 return;607 }608 //create connection to device609 usb_pipe_t new_device_pipe;610 usb_device_connection_t new_device_connection;611 usb_device_connection_initialize_on_default_address(612 &new_device_connection,613 &hub->connection614 );615 usb_pipe_initialize_default_control(616 &new_device_pipe,617 &new_device_connection);618 usb_pipe_probe_default_control(&new_device_pipe);619 620 /* Request address from host controller. */621 usb_address_t new_device_address = usb_hc_request_address(622 &hub->connection,623 speed624 );625 if (new_device_address < 0) {626 usb_log_error("failed to get free USB address\n");627 opResult = new_device_address;628 usb_hub_release_default_address(hub);629 return;630 }631 usb_log_debug("setting new address %d\n", new_device_address);632 //opResult = usb_drv_req_set_address(hc, USB_ADDRESS_DEFAULT,633 // new_device_address);634 usb_pipe_start_session(&new_device_pipe);635 opResult = usb_request_set_address(&new_device_pipe,636 new_device_address);637 usb_pipe_end_session(&new_device_pipe);638 if (opResult != EOK) {639 usb_log_error("could not set address for new device %d\n",640 opResult);641 usb_hub_release_default_address(hub);642 return;643 }644 645 //opResult = usb_hub_release_default_address(hc);646 opResult = usb_hub_release_default_address(hub);647 if (opResult != EOK) {648 return;649 }650 651 devman_handle_t child_handle;652 //??653 opResult = usb_device_register_child_in_devman(new_device_address,654 hub->connection.hc_handle, hub->usb_device->ddf_dev,655 &child_handle,656 NULL, NULL, NULL);657 658 if (opResult != EOK) {659 usb_log_error("could not start driver for new device %d\n",660 opResult);661 return;662 }663 hub->attached_devs[port].handle = child_handle;664 hub->attached_devs[port].address = new_device_address;665 666 //opResult = usb_drv_bind_address(hc, new_device_address, child_handle);667 opResult = usb_hc_register_device(668 &hub->connection,669 &hub->attached_devs[port]);670 if (opResult != EOK) {671 usb_log_error("could not assign address of device in hcd %d\n",672 opResult);673 return;674 }675 usb_log_info("Detected new device on `%s' (port %d), " \676 "address %d (handle %llu).\n",677 hub->usb_device->ddf_dev->name, (int) port,678 new_device_address, child_handle);679 }680 #endif681 400 682 401 /** … … 689 408 * @param port port number, starting from 1 690 409 */ 691 staticvoid usb_hub_removed_device(692 usb_hub_info_t * hub,uint16_t port) {410 void usb_hub_removed_device( 411 usb_hub_info_t * hub,uint16_t port) { 693 412 694 413 int opResult = usb_hub_clear_port_feature(hub->control_pipe, 695 port, USB_HUB_FEATURE_C_PORT_CONNECTION);696 if (opResult != EOK){414 port, USB_HUB_FEATURE_C_PORT_CONNECTION); 415 if(opResult != EOK){ 697 416 usb_log_warning("could not clear port-change-connection flag\n"); 698 417 } … … 700 419 * devide manager 701 420 */ 702 421 703 422 //close address 704 //if (hub->attached_devs[port].address != 0) {705 423 if(hub->ports[port].attached_device.address >= 0){ 706 424 /*uncomment this code to use it when DDF allows device removal 707 425 opResult = usb_hc_unregister_device( 708 &hub->connection, 709 hub->attached_devs[port].address); 426 &hub->connection, hub->attached_devs[port].address); 710 427 if(opResult != EOK) { 711 dprintf(USB_LOG_LEVEL_WARNING, "could not release " 712 "address of " 428 dprintf(USB_LOG_LEVEL_WARNING, "could not release address of " \ 713 429 "removed device: %d", opResult); 714 430 } … … 716 432 hub->attached_devs[port].handle = 0; 717 433 */ 718 } else { 719 usb_log_warning("this is strange, disconnected device had " 720 "no address\n"); 721 //device was disconnected before it`s port was reset - 722 //return default address 434 }else{ 435 usb_log_warning("this is strange, disconnected device had no address\n"); 436 //device was disconnected before it`s port was reset - return default address 723 437 usb_hub_release_default_address(hub); 724 438 } 725 439 } 726 440 441 727 442 /** 728 443 * Process over current condition on port. 729 * 444 * 730 445 * Turn off the power on the port. 731 446 * … … 733 448 * @param port port number, starting from 1 734 449 */ 735 static void usb_hub_port_over_current(usb_hub_info_t * hub,736 uint16_t port, uint32_t status){450 void usb_hub_over_current( usb_hub_info_t * hub, 451 uint16_t port){ 737 452 int opResult; 738 if(usb_port_over_current(&status)){ 739 opResult = usb_hub_clear_port_feature(hub->control_pipe, 740 port, USB_HUB_FEATURE_PORT_POWER); 741 if (opResult != EOK) { 742 usb_log_error("cannot power off port %d; %d\n", 453 opResult = usb_hub_clear_port_feature(hub->control_pipe, 454 port, USB_HUB_FEATURE_PORT_POWER); 455 if(opResult!=EOK){ 456 usb_log_error("cannot power off port %d; %d\n", 743 457 port, opResult); 744 } 745 }else{ 746 opResult = usb_hub_set_port_feature(hub->control_pipe, 747 port, USB_HUB_FEATURE_PORT_POWER); 748 if (opResult != EOK) { 749 usb_log_error("cannot power on port %d; %d\n", 750 port, opResult); 751 } 752 } 753 } 754 755 /** Retrieve port status. 756 * 757 * @param[in] ctrl_pipe Control pipe to use. 758 * @param[in] port Port number (starting at 1). 759 * @param[out] status Where to store the port status. 760 * @return Error code. 761 */ 762 static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port, 763 usb_port_status_t *status) 764 { 765 size_t recv_size; 766 usb_device_request_setup_packet_t request; 767 usb_port_status_t status_tmp; 768 769 usb_hub_set_port_status_request(&request, port); 770 int rc = usb_pipe_control_read(ctrl_pipe, 771 &request, sizeof(usb_device_request_setup_packet_t), 772 &status_tmp, sizeof(status_tmp), &recv_size); 773 if (rc != EOK) { 774 return rc; 775 } 776 777 if (recv_size != sizeof (status_tmp)) { 778 return ELIMIT; 779 } 780 781 if (status != NULL) { 782 *status = status_tmp; 783 } 784 785 return EOK; 786 } 787 788 /** Callback for enabling a specific port. 789 * 790 * We wait on a CV until port is reseted. 791 * That is announced via change on interrupt pipe. 792 * 793 * @param port_no Port number (starting at 1). 794 * @param arg Custom argument, points to @c usb_hub_info_t. 795 * @return Error code. 796 */ 797 static int enable_port_callback(int port_no, void *arg) 798 { 799 usb_hub_info_t *hub = (usb_hub_info_t *) arg; 800 int rc; 801 usb_device_request_setup_packet_t request; 802 usb_hub_port_t *my_port = hub->ports + port_no; 803 804 usb_hub_set_reset_port_request(&request, port_no); 805 rc = usb_pipe_control_write(hub->control_pipe, 806 &request, sizeof(request), NULL, 0); 807 if (rc != EOK) { 808 usb_log_warning("Port reset failed: %s.\n", str_error(rc)); 809 return rc; 810 } 811 812 /* 813 * Wait until reset completes. 814 */ 815 fibril_mutex_lock(&my_port->reset_mutex); 816 while (!my_port->reset_completed) { 817 fibril_condvar_wait(&my_port->reset_cv, &my_port->reset_mutex); 818 } 819 fibril_mutex_unlock(&my_port->reset_mutex); 820 821 /* Clear the port reset change. */ 822 rc = usb_hub_clear_port_feature(hub->control_pipe, 823 port_no, USB_HUB_FEATURE_C_PORT_RESET); 824 if (rc != EOK) { 825 usb_log_error("Failed to clear port %d reset feature: %s.\n", 826 port_no, str_error(rc)); 827 return rc; 828 } 829 830 return EOK; 831 } 832 833 /** Fibril for adding a new device. 834 * 835 * Separate fibril is needed because the port reset completion is announced 836 * via interrupt pipe and thus we cannot block here. 837 * 838 * @param arg Pointer to struct add_device_phase1. 839 * @return 0 Always. 840 */ 841 static int add_device_phase1_worker_fibril(void *arg) 842 { 843 struct add_device_phase1 *data 844 = (struct add_device_phase1 *) arg; 845 846 usb_address_t new_address; 847 devman_handle_t child_handle; 848 849 int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev, 850 &data->hub->connection, data->speed, 851 enable_port_callback, (int) data->port, data->hub, 852 &new_address, &child_handle, 853 NULL, NULL, NULL); 854 855 if (rc != EOK) { 856 usb_log_error("Failed registering device on port %zu: %s.\n", 857 data->port, str_error(rc)); 858 goto leave; 859 } 860 861 data->hub->ports[data->port].attached_device.handle = child_handle; 862 data->hub->ports[data->port].attached_device.address = new_address; 863 864 usb_log_info("Detected new device on `%s' (port %zu), " 865 "address %d (handle %" PRIun ").\n", 866 data->hub->usb_device->ddf_dev->name, data->port, 867 new_address, child_handle); 868 869 leave: 870 free(arg); 871 872 return EOK; 873 } 874 875 876 /** Start device adding when connection change is detected. 877 * 878 * This fires a new fibril to complete the device addition. 879 * 880 * @param hub Hub where the change occured. 881 * @param port Port index (starting at 1). 882 * @param speed Speed of the device. 883 * @return Error code. 884 */ 885 static int add_device_phase1_new_fibril(usb_hub_info_t *hub, size_t port, 886 usb_speed_t speed) 887 { 888 struct add_device_phase1 *data 889 = malloc(sizeof(struct add_device_phase1)); 890 if (data == NULL) { 891 return ENOMEM; 892 } 893 data->hub = hub; 894 data->port = port; 895 data->speed = speed; 896 897 usb_hub_port_t *the_port = hub->ports + port; 898 899 fibril_mutex_lock(&the_port->reset_mutex); 900 the_port->reset_completed = false; 901 fibril_mutex_unlock(&the_port->reset_mutex); 902 903 int rc = usb_hub_clear_port_feature(hub->control_pipe, port, 904 USB_HUB_FEATURE_C_PORT_CONNECTION); 905 if (rc != EOK) { 906 free(data); 907 usb_log_warning("Failed to clear port change flag: %s.\n", 908 str_error(rc)); 909 return rc; 910 } 911 912 fid_t fibril = fibril_create(add_device_phase1_worker_fibril, data); 913 if (fibril == 0) { 914 free(data); 915 return ENOMEM; 916 } 917 fibril_add_ready(fibril); 918 919 return EOK; 920 } 921 922 923 /** 924 * Process interrupts on given hub port 925 * 926 * Accepts connection, over current and port reset change. 927 * @param hub hub representation 928 * @param port port number, starting from 1 929 */ 930 static void usb_hub_process_interrupt(usb_hub_info_t * hub, 931 uint16_t port) { 932 usb_log_debug("interrupt at port %d\n", port); 933 //determine type of change 934 //usb_pipe_t *pipe = hub->control_pipe; 935 936 int opResult; 937 938 usb_port_status_t status; 939 opResult = get_port_status(&hub->usb_device->ctrl_pipe, port, &status); 940 if (opResult != EOK) { 941 usb_log_error("Failed to get port %zu status: %s.\n", 942 port, str_error(opResult)); 943 return; 944 } 945 946 //something connected/disconnected 947 /* 948 if (usb_port_connect_change(&status)) { 949 usb_log_debug("connection change on port\n"); 950 if (usb_port_dev_connected(&status)) { 951 usb_hub_init_add_device(hub, port, 952 usb_port_speed(&status)); 953 } else { 954 usb_hub_removed_device(hub, port); 955 } 956 }*/ 957 if (usb_port_connect_change(&status)) { 958 bool device_connected = usb_port_dev_connected(&status); 959 usb_log_debug("Connection change on port %zu: %s.\n", port, 960 device_connected ? "device attached" : "device removed"); 961 962 if (device_connected) { 963 opResult = add_device_phase1_new_fibril(hub, port, 964 usb_port_speed(&status)); 965 if (opResult != EOK) { 966 usb_log_error( 967 "Cannot handle change on port %zu: %s.\n", 968 str_error(opResult)); 969 } 970 } else { 971 usb_hub_removed_device(hub, port); 972 } 973 } 974 //over current 975 if (usb_port_overcurrent_change(&status)) { 976 //check if it was not auto-resolved 977 usb_log_debug("overcurrent change on port\n"); 978 usb_hub_port_over_current(hub, port, status); 979 } 980 //port reset 981 if (usb_port_reset_completed(&status)) { 982 /* 983 usb_log_debug("port reset complete\n"); 984 if (usb_port_enabled(&status)) { 985 usb_hub_finalize_add_device(hub, port, 986 usb_port_speed(&status)); 987 } else { 988 usb_log_warning("port reset, but port still not " 989 "enabled\n"); 990 } 991 * */ 992 usb_log_debug("Port %zu reset complete.\n", port); 993 if (usb_port_enabled(&status)) { 994 /* Finalize device adding. */ 995 usb_hub_port_t *the_port = hub->ports + port; 996 fibril_mutex_lock(&the_port->reset_mutex); 997 the_port->reset_completed = true; 998 fibril_condvar_broadcast(&the_port->reset_cv); 999 fibril_mutex_unlock(&the_port->reset_mutex); 1000 } else { 1001 usb_log_warning( 1002 "Port %zu reset complete but port not enabled.\n", 1003 port); 1004 } 1005 } 1006 usb_log_debug("status x%x : %d\n ", status, status); 1007 1008 usb_port_set_connect_change(&status, false); 1009 usb_port_set_reset(&status, false); 1010 usb_port_set_reset_completed(&status, false); 1011 usb_port_set_dev_connected(&status, false); 1012 usb_port_set_overcurrent_change(&status,false); 1013 /// \TODO what about port power change? 1014 if (status >> 16) { 1015 usb_log_info("there was unsupported change on port %d: %X\n", 1016 port, status); 1017 1018 } 1019 } 1020 1021 /** 1022 * process hub over current change 1023 * 1024 * This means either to power off the hub or power it on. 1025 * @param hub_info hub instance 1026 * @param status hub status bitmask 1027 * @return error code 1028 */ 1029 static int usb_process_hub_over_current(usb_hub_info_t * hub_info, 1030 usb_hub_status_t status) 1031 { 1032 int opResult; 1033 if(usb_hub_over_current(&status)){ 1034 opResult = usb_hub_clear_feature(hub_info->control_pipe, 1035 USB_HUB_FEATURE_PORT_POWER); 1036 if (opResult != EOK) { 1037 usb_log_error("cannot power off hub: %d\n", 1038 opResult); 1039 } 1040 }else{ 1041 opResult = usb_hub_set_feature(hub_info->control_pipe, 1042 USB_HUB_FEATURE_PORT_POWER); 1043 if (opResult != EOK) { 1044 usb_log_error("cannot power on hub: %d\n", 1045 opResult); 1046 } 1047 } 1048 return opResult; 1049 } 1050 1051 /** 1052 * process hub power change 1053 * 1054 * If the power has been lost, reestablish it. 1055 * If it was reestablished, re-power all ports. 1056 * @param hub_info hub instance 1057 * @param status hub status bitmask 1058 * @return error code 1059 */ 1060 static int usb_process_hub_power_change(usb_hub_info_t * hub_info, 1061 usb_hub_status_t status) 1062 { 1063 int opResult; 1064 if(usb_hub_local_power_lost(&status)){ 1065 //restart power on hub 1066 opResult = usb_hub_set_feature(hub_info->control_pipe, 1067 USB_HUB_FEATURE_PORT_POWER); 1068 if (opResult != EOK) { 1069 usb_log_error("cannot power on hub: %d\n", 1070 opResult); 1071 } 1072 }else{//power reestablished on hub- restart ports 1073 size_t port; 1074 for(port=0;port<hub_info->port_count;++port){ 1075 opResult = usb_hub_set_port_feature( 1076 hub_info->control_pipe, 1077 port, USB_HUB_FEATURE_PORT_POWER); 1078 if (opResult != EOK) { 1079 usb_log_error("cannot power on port %d; %d\n", 1080 port, opResult); 1081 } 1082 } 1083 } 1084 return opResult; 1085 } 1086 1087 /** 1088 * process hub interrupts 1089 * 1090 * The change can be either in the over-current condition or 1091 * local-power lost condition. 1092 * @param hub_info hub instance 1093 */ 1094 static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info){ 1095 usb_log_debug("global interrupt on a hub\n"); 1096 usb_pipe_t *pipe = hub_info->control_pipe; 1097 int opResult; 1098 1099 usb_port_status_t status; 1100 size_t rcvd_size; 1101 usb_device_request_setup_packet_t request; 1102 //int opResult; 1103 usb_hub_set_hub_status_request(&request); 1104 //endpoint 0 1105 1106 opResult = usb_pipe_control_read( 1107 pipe, 1108 &request, sizeof (usb_device_request_setup_packet_t), 1109 &status, 4, &rcvd_size 1110 ); 1111 if (opResult != EOK) { 1112 usb_log_error("could not get hub status\n"); 1113 return; 1114 } 1115 if (rcvd_size != sizeof (usb_port_status_t)) { 1116 usb_log_error("received status has incorrect size\n"); 1117 return; 1118 } 1119 //port reset 1120 if (usb_hub_over_current_change(&status)) { 1121 usb_process_hub_over_current(hub_info,status); 1122 } 1123 if (usb_hub_local_power_change(&status)) { 1124 usb_process_hub_power_change(hub_info,status); 1125 } 1126 } 1127 458 } 459 } 1128 460 1129 461 -
uspace/drv/usbhub/usbhub.h
r8961c22 r61727bf 43 43 44 44 #include <usb/hub.h> 45 #include <usb/classes/hub.h>46 45 47 46 #include <usb/pipes.h> 48 47 #include <usb/devdrv.h> 49 48 50 #include <fibril_synch.h>49 #include "ports.h" 51 50 52 51 53 /** Information about single port on a hub. */54 typedef struct {55 /** Mutex needed by CV for checking port reset. */56 fibril_mutex_t reset_mutex;57 /** CV for waiting to port reset completion. */58 fibril_condvar_t reset_cv;59 /** Whether port reset is completed.60 * Guarded by @c reset_mutex.61 */62 bool reset_completed;63 64 /** Information about attached device. */65 usb_hc_attached_device_t attached_device;66 } usb_hub_port_t;67 68 /** Initialize hub port information.69 *70 * @param port Port to be initialized.71 */72 static inline void usb_hub_port_init(usb_hub_port_t *port) {73 port->attached_device.address = -1;74 port->attached_device.handle = 0;75 fibril_mutex_initialize(&port->reset_mutex);76 fibril_condvar_initialize(&port->reset_cv);77 }78 52 79 53 /** Information about attached hub. */ … … 82 56 size_t port_count; 83 57 84 /** attached device handles, for each port one*/58 /** Ports. */ 85 59 usb_hub_port_t *ports; 86 60 87 61 /** connection to hcd */ 88 62 usb_hc_connection_t connection; … … 115 89 } usb_hub_info_t; 116 90 117 //int usb_hub_control_loop(void * hub_info_param); 91 /** 92 * function running the hub-controlling loop. 93 * @param hub_info_param hub info pointer 94 */ 95 int usb_hub_control_loop(void * hub_info_param); 96 97 /** 98 * Check changes on specified hub 99 * @param hub_info_param pointer to usb_hub_info_t structure 100 * @return error code if there is problem when initializing communication with 101 * hub, EOK otherwise 102 */ 103 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param); 104 105 void usb_hub_removed_device(usb_hub_info_t *, uint16_t); 106 void usb_hub_over_current(usb_hub_info_t *, uint16_t); 118 107 119 108 int usb_hub_add_device(usb_device_t * usb_dev); 120 109 121 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param);122 123 bool hub_port_changes_callback(usb_device_t *dev,124 uint8_t *change_bitmap, size_t change_bitmap_size, void *arg);125 110 #endif 126 111 /** -
uspace/drv/usbhub/usbhub_private.h
r8961c22 r61727bf 38 38 39 39 #include "usbhub.h" 40 #include "usblist.h"41 40 42 41 #include <adt/list.h> … … 111 110 112 111 /** 113 * Clear feature on hub port.114 *115 * @param hc Host controller telephone116 * @param address Hub address117 * @param port_index Port118 * @param feature Feature selector119 * @return Operation result120 */121 static inline int usb_hub_set_port_feature(usb_pipe_t *pipe,122 int port_index,123 usb_hub_class_feature_t feature) {124 125 usb_device_request_setup_packet_t clear_request = {126 .request_type = USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE,127 .request = USB_DEVREQ_SET_FEATURE,128 .length = 0,129 .index = port_index130 };131 clear_request.value = feature;132 return usb_pipe_control_write(pipe, &clear_request,133 sizeof(clear_request), NULL, 0);134 }135 136 137 /**138 * Clear feature on hub port.139 *140 * @param pipe pipe to hub control endpoint141 * @param feature Feature selector142 * @return Operation result143 */144 static inline int usb_hub_clear_feature(usb_pipe_t *pipe,145 usb_hub_class_feature_t feature) {146 147 usb_device_request_setup_packet_t clear_request = {148 .request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,149 .request = USB_DEVREQ_CLEAR_FEATURE,150 .length = 0,151 .index = 0152 };153 clear_request.value = feature;154 return usb_pipe_control_write(pipe, &clear_request,155 sizeof(clear_request), NULL, 0);156 }157 158 /**159 * Clear feature on hub port.160 *161 * @param pipe pipe to hub control endpoint162 * @param feature Feature selector163 * @return Operation result164 */165 static inline int usb_hub_set_feature(usb_pipe_t *pipe,166 usb_hub_class_feature_t feature) {167 168 usb_device_request_setup_packet_t clear_request = {169 .request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,170 .request = USB_DEVREQ_SET_FEATURE,171 .length = 0,172 .index = 0173 };174 clear_request.value = feature;175 return usb_pipe_control_write(pipe, &clear_request,176 sizeof(clear_request), NULL, 0);177 }178 179 /**180 112 * create uint8_t array with serialized descriptor 181 113 *
Note:
See TracChangeset
for help on using the changeset viewer.