Changes in / [61727bf:8961c22] in mainline
- Location:
- uspace/drv/usbhub
- Files:
-
- 2 added
- 2 deleted
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/usbhub/Makefile
r61727bf r8961c22 34 34 SOURCES = \ 35 35 main.c \ 36 ports.c \37 36 utils.c \ 38 usbhub.c 37 usbhub.c \ 38 usblist.c 39 39 40 40 include $(USPACE_PREFIX)/Makefile.common -
uspace/drv/usbhub/port_status.h
r61727bf r8961c22 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 in 55 * "Universal Serial Bus Specification Revision 1.1" 56 * 57 */ 58 typedef uint32_t usb_hub_status_t; 59 60 /** 51 61 * set values in request to be it a port status request 52 62 * @param request … … 54 64 */ 55 65 static inline void usb_hub_set_port_status_request( 56 usb_device_request_setup_packet_t * request, uint16_t port57 ){66 usb_device_request_setup_packet_t * request, uint16_t port 67 ) { 58 68 request->index = port; 59 69 request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS; … … 63 73 } 64 74 75 /** 76 * set values in request to be it a port status request 77 * @param request 78 * @param port 79 */ 80 static inline void usb_hub_set_hub_status_request( 81 usb_device_request_setup_packet_t * request 82 ) { 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 } 65 89 66 90 /** … … 70 94 */ 71 95 static inline usb_device_request_setup_packet_t * 72 usb_hub_create_port_status_request(uint16_t port) {96 usb_hub_create_port_status_request(uint16_t port) { 73 97 usb_device_request_setup_packet_t * result = 74 98 usb_new(usb_device_request_setup_packet_t); 75 usb_hub_set_port_status_request(result, port);99 usb_hub_set_port_status_request(result, port); 76 100 return result; 77 101 } 78 102 79 80 103 /** 81 104 * set the device request to be a port feature enable request … … 85 108 */ 86 109 static inline void usb_hub_set_enable_port_feature_request( 87 usb_device_request_setup_packet_t * request, uint16_t port,88 89 ){110 usb_device_request_setup_packet_t * request, uint16_t port, 111 uint16_t feature_selector 112 ) { 90 113 request->index = port; 91 114 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 102 125 */ 103 126 static inline void usb_hub_set_disable_port_feature_request( 104 usb_device_request_setup_packet_t * request, uint16_t port,105 106 ){127 usb_device_request_setup_packet_t * request, uint16_t port, 128 uint16_t feature_selector 129 ) { 107 130 request->index = port; 108 131 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 118 141 */ 119 142 static inline void usb_hub_set_enable_port_request( 120 usb_device_request_setup_packet_t * request, uint16_t port121 ){143 usb_device_request_setup_packet_t * request, uint16_t port 144 ) { 122 145 request->index = port; 123 146 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 133 156 */ 134 157 static inline usb_device_request_setup_packet_t * 135 usb_hub_create_enable_port_request(uint16_t port) {158 usb_hub_create_enable_port_request(uint16_t port) { 136 159 usb_device_request_setup_packet_t * result = 137 160 usb_new(usb_device_request_setup_packet_t); 138 usb_hub_set_enable_port_request(result, port);161 usb_hub_set_enable_port_request(result, port); 139 162 return result; 140 163 } … … 146 169 */ 147 170 static inline void usb_hub_set_disable_port_request( 148 usb_device_request_setup_packet_t * request, uint16_t port149 ){171 usb_device_request_setup_packet_t * request, uint16_t port 172 ) { 150 173 request->index = port; 151 174 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 161 184 */ 162 185 static inline usb_device_request_setup_packet_t * 163 usb_hub_create_disable_port_request(uint16_t port) {186 usb_hub_create_disable_port_request(uint16_t port) { 164 187 usb_device_request_setup_packet_t * result = 165 188 usb_new(usb_device_request_setup_packet_t); 166 usb_hub_set_disable_port_request(result, port);189 usb_hub_set_disable_port_request(result, port); 167 190 return result; 168 191 } … … 174 197 */ 175 198 static inline void usb_hub_set_reset_port_request( 176 usb_device_request_setup_packet_t * request, uint16_t port177 ){199 usb_device_request_setup_packet_t * request, uint16_t port 200 ) { 178 201 request->index = port; 179 202 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 189 212 */ 190 213 static inline usb_device_request_setup_packet_t * 191 usb_hub_create_reset_port_request(uint16_t port) {214 usb_hub_create_reset_port_request(uint16_t port) { 192 215 usb_device_request_setup_packet_t * result = 193 216 usb_new(usb_device_request_setup_packet_t); 194 usb_hub_set_reset_port_request(result, port);217 usb_hub_set_reset_port_request(result, port); 195 218 return result; 196 219 } … … 202 225 */ 203 226 static inline void usb_hub_set_power_port_request( 204 usb_device_request_setup_packet_t * request, uint16_t port205 ){227 usb_device_request_setup_packet_t * request, uint16_t port 228 ) { 206 229 request->index = port; 207 230 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 217 240 */ 218 241 static inline void usb_hub_unset_power_port_request( 219 usb_device_request_setup_packet_t * request, uint16_t port220 ){242 usb_device_request_setup_packet_t * request, uint16_t port 243 ) { 221 244 request->index = port; 222 245 request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE; … … 226 249 } 227 250 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 */ 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 */ 236 269 static inline void usb_port_set_bit( 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); 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); 251 319 } 252 320 253 321 //port 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); 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); 260 341 } 261 342 262 343 //port 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); 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); 269 362 } 270 363 271 364 //over currect 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); 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); 278 383 } 279 384 280 385 //port reset 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); 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); 287 404 } 288 405 289 406 //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); 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); 296 425 } 297 426 298 427 //low speed device attached 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)) 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)) 318 477 return USB_SPEED_LOW; 319 if (usb_port_high_speed(status))478 if (usb_port_high_speed(status)) 320 479 return USB_SPEED_HIGH; 321 480 return USB_SPEED_FULL; … … 324 483 325 484 //connect 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); 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); 332 502 } 333 503 334 504 //port enable 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); 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); 341 523 } 342 524 343 525 //suspend 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); 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); 350 544 } 351 545 352 546 //over current 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); 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); 359 565 } 360 566 361 567 //reset change 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 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 } 370 675 371 676 -
uspace/drv/usbhub/usbhub.c
r61727bf r8961c22 37 37 #include <errno.h> 38 38 #include <str_error.h> 39 #include <inttypes.h> 39 40 40 41 #include <usb_iface.h> … … 53 54 #include "usb/classes/classes.h" 54 55 55 static int usb_hub_trigger_connecting_non_removable_devices( 56 usb_hub_info_t * hub, usb_hub_descriptor_t * descriptor); 57 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 58 138 59 139 //********************************************* … … 63 143 //********************************************* 64 144 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 } 145 179 146 180 147 /** … … 186 153 * @return error code 187 154 */ 188 int usb_hub_add_device(usb_device_t * usb_dev) {189 if (!usb_dev) return EINVAL;155 int usb_hub_add_device(usb_device_t * usb_dev) { 156 if (!usb_dev) return EINVAL; 190 157 usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev); 191 158 //create hc connection 192 159 usb_log_debug("Initializing USB wire abstraction.\n"); 193 160 int opResult = usb_hc_connection_initialize_from_device( 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); 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); 199 167 free(hub_info); 200 168 return opResult; 201 169 } 202 170 203 171 usb_pipe_start_session(hub_info->control_pipe); 204 172 //set hub configuration 205 173 opResult = usb_hub_set_configuration(hub_info); 206 if(opResult!=EOK){ 207 usb_log_error("could not set hub configuration, errno %d\n",opResult); 174 if (opResult != EOK) { 175 usb_log_error("could not set hub configuration, errno %d\n", 176 opResult); 208 177 free(hub_info); 209 178 return opResult; … … 211 180 //get port count and create attached_devs 212 181 opResult = usb_hub_process_hub_specific_info(hub_info); 213 if(opResult!=EOK){ 214 usb_log_error("could not set hub configuration, errno %d\n",opResult); 182 if (opResult != EOK) { 183 usb_log_error("could not set hub configuration, errno %d\n", 184 opResult); 215 185 free(hub_info); 216 186 return opResult; … … 222 192 usb_log_debug("Creating `hub' function.\n"); 223 193 ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev, 224 194 fun_exposed, "hub"); 225 195 assert(hub_fun != NULL); 226 196 hub_fun->ops = NULL; … … 264 234 265 235 usb_log_info("Controlling hub `%s' (%d ports).\n", 266 236 hub_info->usb_device->ddf_dev->name, hub_info->port_count); 267 237 return EOK; 268 269 238 leave: 270 239 free(hub_info); … … 280 249 //********************************************* 281 250 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 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) 262 { 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 289 292 * @return error code 290 293 */ 291 static int usb_hub_trigger_connecting_non_removable_devices(usb_hub_info_t * hub, 292 usb_hub_descriptor_t * descriptor) 293 { 294 usb_log_info("attaching non-removable devices(if any)\n"); 295 usb_device_request_setup_packet_t request; 294 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info) { 296 295 int opResult; 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; 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); 316 319 } 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"); 345 } 346 } 347 } 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)); 377 } 378 } 320 } 321 } 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); 373 } 374 } 375 /// \todo check hub status 376 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); 379 380 return EOK; 380 381 } 381 382 383 //********************************************* 384 // 385 // support functions 386 // 387 //********************************************* 388 389 /** 390 * create usb_hub_info_t structure 391 * 392 * Does only basic copying of known information into new structure. 393 * @param usb_dev usb device structure 394 * @return basic usb_hub_info_t structure 395 */ 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 needed 409 * 410 * Particularly read port count and initialize structure holding port 411 * information. If there are non-removable devices, start initializing them. 412 * This function is hub-specific and should be run only after the hub is 413 * configured using usb_hub_set_configuration function. 414 * @param hub_info hub representation 415 * @return error code 416 */ 417 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info) { 418 // get hub descriptor 419 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 anymore 425 * these lines allow to reset hub once more, it can be used as 426 * brute-force initialization for non-removable devices 427 * 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 correct 460 //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 devices 470 //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 hub 480 * 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 representation 484 * @return error code 485 */ 486 static int usb_hub_set_configuration(usb_hub_info_t * hub_info) { 487 //device descriptor 488 usb_standard_device_descriptor_t *std_descriptor 489 = &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_descriptor 498 = (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 } 382 516 383 517 /** … … 389 523 * @return error code 390 524 */ 391 static int usb_hub_release_default_address(usb_hub_info_t * hub) {525 static int usb_hub_release_default_address(usb_hub_info_t * hub) { 392 526 int opResult = usb_hc_release_default_address(&hub->connection); 393 if(opResult!=EOK){ 394 usb_log_error("could not release default address, errno %d\n",opResult); 527 if (opResult != EOK) { 528 usb_log_error("could not release default address, errno %d\n", 529 opResult); 395 530 return opResult; 396 531 } … … 398 533 return EOK; 399 534 } 535 536 #if 0 537 /** 538 * Reset the port with new device and reserve the default address. 539 * @param hub hub representation 540 * @param port port number, starting from 1 541 * @param speed transfer speed of attached device, one of low, full or high 542 * @return error code 543 */ 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 more 547 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 address 561 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 port 571 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, 0 576 ); 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 #endif 585 586 #if 0 587 /** 588 * Finalize adding new device after port reset 589 * 590 * Set device`s address and start it`s driver. 591 * @param hub hub representation 592 * @param port port number, starting from 1 593 * @param speed transfer speed of attached device, one of low, full or high 594 */ 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 device 609 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->connection 614 ); 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 speed 624 ); 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 #endif 400 681 401 682 /** … … 408 689 * @param port port number, starting from 1 409 690 */ 410 void usb_hub_removed_device(411 usb_hub_info_t * hub,uint16_t port) {691 static void usb_hub_removed_device( 692 usb_hub_info_t * hub, uint16_t port) { 412 693 413 694 int opResult = usb_hub_clear_port_feature(hub->control_pipe, 414 415 if (opResult != EOK){695 port, USB_HUB_FEATURE_C_PORT_CONNECTION); 696 if (opResult != EOK) { 416 697 usb_log_warning("could not clear port-change-connection flag\n"); 417 698 } … … 419 700 * devide manager 420 701 */ 421 702 422 703 //close address 704 //if (hub->attached_devs[port].address != 0) { 423 705 if(hub->ports[port].attached_device.address >= 0){ 424 706 /*uncomment this code to use it when DDF allows device removal 425 707 opResult = usb_hc_unregister_device( 426 &hub->connection, hub->attached_devs[port].address); 708 &hub->connection, 709 hub->attached_devs[port].address); 427 710 if(opResult != EOK) { 428 dprintf(USB_LOG_LEVEL_WARNING, "could not release address of " \ 711 dprintf(USB_LOG_LEVEL_WARNING, "could not release " 712 "address of " 429 713 "removed device: %d", opResult); 430 714 } … … 432 716 hub->attached_devs[port].handle = 0; 433 717 */ 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 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 437 723 usb_hub_release_default_address(hub); 438 724 } 439 725 } 440 726 441 442 727 /** 443 728 * Process over current condition on port. 444 * 729 * 445 730 * Turn off the power on the port. 446 731 * … … 448 733 * @param port port number, starting from 1 449 734 */ 450 void usb_hub_over_current(usb_hub_info_t * hub,451 uint16_t port){735 static void usb_hub_port_over_current(usb_hub_info_t * hub, 736 uint16_t port, uint32_t status) { 452 737 int opResult; 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", 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", 457 743 port, opResult); 458 } 459 } 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 460 1128 461 1129 -
uspace/drv/usbhub/usbhub.h
r61727bf r8961c22 43 43 44 44 #include <usb/hub.h> 45 #include <usb/classes/hub.h> 45 46 46 47 #include <usb/pipes.h> 47 48 #include <usb/devdrv.h> 48 49 49 #include "ports.h"50 #include <fibril_synch.h> 50 51 51 52 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 } 52 78 53 79 /** Information about attached hub. */ … … 56 82 size_t port_count; 57 83 58 /** Ports.*/84 /** attached device handles, for each port one */ 59 85 usb_hub_port_t *ports; 60 86 61 87 /** connection to hcd */ 62 88 usb_hc_connection_t connection; … … 89 115 } usb_hub_info_t; 90 116 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); 117 //int usb_hub_control_loop(void * hub_info_param); 107 118 108 119 int usb_hub_add_device(usb_device_t * usb_dev); 109 120 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); 110 125 #endif 111 126 /** -
uspace/drv/usbhub/usbhub_private.h
r61727bf r8961c22 38 38 39 39 #include "usbhub.h" 40 #include "usblist.h" 40 41 41 42 #include <adt/list.h> … … 110 111 111 112 /** 113 * Clear feature on hub port. 114 * 115 * @param hc Host controller telephone 116 * @param address Hub address 117 * @param port_index Port 118 * @param feature Feature selector 119 * @return Operation result 120 */ 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_index 130 }; 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 endpoint 141 * @param feature Feature selector 142 * @return Operation result 143 */ 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 = 0 152 }; 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 endpoint 162 * @param feature Feature selector 163 * @return Operation result 164 */ 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 = 0 173 }; 174 clear_request.value = feature; 175 return usb_pipe_control_write(pipe, &clear_request, 176 sizeof(clear_request), NULL, 0); 177 } 178 179 /** 112 180 * create uint8_t array with serialized descriptor 113 181 *
Note:
See TracChangeset
for help on using the changeset viewer.