Changes in / [61727bf:8961c22] in mainline


Ignore:
Location:
uspace/drv/usbhub
Files:
2 added
2 deleted
5 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbhub/Makefile

    r61727bf r8961c22  
    3434SOURCES = \
    3535        main.c \
    36         ports.c \
    3736        utils.c \
    38         usbhub.c
     37        usbhub.c \
     38        usblist.c
    3939
    4040include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/usbhub/port_status.h

    r61727bf r8961c22  
    4949
    5050/**
     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 */
     58typedef uint32_t usb_hub_status_t;
     59
     60/**
    5161 * set values in request to be it a port status request
    5262 * @param request
     
    5464 */
    5565static inline void usb_hub_set_port_status_request(
    56 usb_device_request_setup_packet_t * request, uint16_t port
    57 ){
     66        usb_device_request_setup_packet_t * request, uint16_t port
     67        ) {
    5868        request->index = port;
    5969        request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS;
     
    6373}
    6474
     75/**
     76 * set values in request to be it a port status request
     77 * @param request
     78 * @param port
     79 */
     80static 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}
    6589
    6690/**
     
    7094 */
    7195static inline usb_device_request_setup_packet_t *
    72 usb_hub_create_port_status_request(uint16_t port){
     96usb_hub_create_port_status_request(uint16_t port) {
    7397        usb_device_request_setup_packet_t * result =
    7498                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);
    76100        return result;
    77101}
    78102
    79 
    80103/**
    81104 * set the device request to be a port feature enable request
     
    85108 */
    86109static inline void usb_hub_set_enable_port_feature_request(
    87 usb_device_request_setup_packet_t * request, uint16_t port,
    88                 uint16_t feature_selector
    89 ){
     110        usb_device_request_setup_packet_t * request, uint16_t port,
     111        uint16_t feature_selector
     112        ) {
    90113        request->index = port;
    91114        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    102125 */
    103126static inline void usb_hub_set_disable_port_feature_request(
    104 usb_device_request_setup_packet_t * request, uint16_t port,
    105                 uint16_t feature_selector
    106 ){
     127        usb_device_request_setup_packet_t * request, uint16_t port,
     128        uint16_t feature_selector
     129        ) {
    107130        request->index = port;
    108131        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    118141 */
    119142static inline void usb_hub_set_enable_port_request(
    120 usb_device_request_setup_packet_t * request, uint16_t port
    121 ){
     143        usb_device_request_setup_packet_t * request, uint16_t port
     144        ) {
    122145        request->index = port;
    123146        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    133156 */
    134157static inline usb_device_request_setup_packet_t *
    135 usb_hub_create_enable_port_request(uint16_t port){
     158usb_hub_create_enable_port_request(uint16_t port) {
    136159        usb_device_request_setup_packet_t * result =
    137160                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);
    139162        return result;
    140163}
     
    146169 */
    147170static inline void usb_hub_set_disable_port_request(
    148 usb_device_request_setup_packet_t * request, uint16_t port
    149 ){
     171        usb_device_request_setup_packet_t * request, uint16_t port
     172        ) {
    150173        request->index = port;
    151174        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    161184 */
    162185static inline usb_device_request_setup_packet_t *
    163 usb_hub_create_disable_port_request(uint16_t port){
     186usb_hub_create_disable_port_request(uint16_t port) {
    164187        usb_device_request_setup_packet_t * result =
    165188                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);
    167190        return result;
    168191}
     
    174197 */
    175198static inline void usb_hub_set_reset_port_request(
    176 usb_device_request_setup_packet_t * request, uint16_t port
    177 ){
     199        usb_device_request_setup_packet_t * request, uint16_t port
     200        ) {
    178201        request->index = port;
    179202        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    189212 */
    190213static inline usb_device_request_setup_packet_t *
    191 usb_hub_create_reset_port_request(uint16_t port){
     214usb_hub_create_reset_port_request(uint16_t port) {
    192215        usb_device_request_setup_packet_t * result =
    193216                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);
    195218        return result;
    196219}
     
    202225 */
    203226static inline void usb_hub_set_power_port_request(
    204 usb_device_request_setup_packet_t * request, uint16_t port
    205 ){
     227        usb_device_request_setup_packet_t * request, uint16_t port
     228        ) {
    206229        request->index = port;
    207230        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    217240 */
    218241static inline void usb_hub_unset_power_port_request(
    219 usb_device_request_setup_packet_t * request, uint16_t port
    220 ){
     242        usb_device_request_setup_packet_t * request, uint16_t port
     243        ) {
    221244        request->index = port;
    222245        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    226249}
    227250
    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 */
     258static 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 */
    236269static 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 */
     283static 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 */
     294static 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 */
     307static 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 */
     317static inline void usb_port_set_dev_connected(usb_port_status_t * status, bool connected) {
     318        usb_port_set_bit(status, 0, connected);
    251319}
    252320
    253321//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 */
     329static 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 */
     339static inline void usb_port_set_enabled(usb_port_status_t * status, bool enabled) {
     340        usb_port_set_bit(status, 1, enabled);
    260341}
    261342
    262343//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 */
     350static 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 */
     360static inline void usb_port_set_suspended(usb_port_status_t * status, bool suspended) {
     361        usb_port_set_bit(status, 2, suspended);
    269362}
    270363
    271364//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 */
     371static 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 */
     381static inline void usb_port_set_over_current(usb_port_status_t * status, bool value) {
     382        usb_port_set_bit(status, 3, value);
    278383}
    279384
    280385//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 */
     392static 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 */
     402static inline void usb_port_set_reset(usb_port_status_t * status, bool value) {
     403        usb_port_set_bit(status, 4, value);
    287404}
    288405
    289406//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 */
     413static 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 */
     423static inline void usb_port_set_powered(usb_port_status_t * status, bool powered) {
     424        usb_port_set_bit(status, 8, powered);
    296425}
    297426
    298427//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 */
     434static 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 */
     444static 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 */
     455static 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 */
     465static 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 */
     475static inline usb_speed_t usb_port_speed(usb_port_status_t * status) {
     476        if (usb_port_low_speed(status))
    318477                return USB_SPEED_LOW;
    319         if(usb_port_high_speed(status))
     478        if (usb_port_high_speed(status))
    320479                return USB_SPEED_HIGH;
    321480        return USB_SPEED_FULL;
     
    324483
    325484//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 */
     491static 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 */
     500static inline void usb_port_set_connect_change(usb_port_status_t * status, bool change) {
     501        usb_port_set_bit(status, 16, change);
    332502}
    333503
    334504//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 */
     511static 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 */
     521static inline void usb_port_set_enabled_change(usb_port_status_t * status, bool change) {
     522        usb_port_set_bit(status, 17, change);
    341523}
    342524
    343525//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 */
     532static 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 */
     542static inline void usb_port_set_suspend_change(usb_port_status_t * status, bool change) {
     543        usb_port_set_bit(status, 18, change);
    350544}
    351545
    352546//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 */
     553static 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 */
     563static inline void usb_port_set_overcurrent_change(usb_port_status_t * status, bool change) {
     564        usb_port_set_bit(status, 19, change);
    359565}
    360566
    361567//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 */
     573static 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 */
     583static 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 */
     594static 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 */
     604static 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 */
     616static 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 */
     626static 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 */
     639static 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 */
     649static 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 */
     661static 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 */
     671static 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}
    370675
    371676
  • uspace/drv/usbhub/usbhub.c

    r61727bf r8961c22  
    3737#include <errno.h>
    3838#include <str_error.h>
     39#include <inttypes.h>
    3940
    4041#include <usb_iface.h>
     
    5354#include "usb/classes/classes.h"
    5455
    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. */
     58struct add_device_phase1 {
     59        usb_hub_info_t *hub;
     60        size_t port;
     61        usb_speed_t speed;
     62};
     63
     64
     65static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev);
     66
     67static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info);
     68
     69static int usb_hub_set_configuration(usb_hub_info_t * hub_info);
     70
     71static 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
     79static void usb_hub_removed_device(
     80        usb_hub_info_t * hub, uint16_t port);
     81
     82static void usb_hub_port_over_current(usb_hub_info_t * hub,
     83        uint16_t port, uint32_t status);
     84
     85static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,
     86    usb_port_status_t *status);
     87
     88static int enable_port_callback(int port_no, void *arg);
     89
     90static int add_device_phase1_worker_fibril(void *arg);
     91
     92static int add_device_phase1_new_fibril(usb_hub_info_t *hub, size_t port,
     93    usb_speed_t speed);
     94
     95static void usb_hub_process_interrupt(usb_hub_info_t * hub,
     96        uint16_t port);
     97
     98static int usb_process_hub_over_current(usb_hub_info_t * hub_info,
     99        usb_hub_status_t status);
     100
     101static int usb_process_hub_power_change(usb_hub_info_t * hub_info,
     102        usb_hub_status_t status);
     103
     104static 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/*
     123int 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
    58138
    59139//*********************************************
     
    63143//*********************************************
    64144
    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
    179146
    180147/**
     
    186153 * @return error code
    187154 */
    188 int usb_hub_add_device(usb_device_t * usb_dev){
    189         if(!usb_dev) return EINVAL;
     155int usb_hub_add_device(usb_device_t * usb_dev) {
     156        if (!usb_dev) return EINVAL;
    190157        usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev);
    191158        //create hc connection
    192159        usb_log_debug("Initializing USB wire abstraction.\n");
    193160        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);
    199167                free(hub_info);
    200168                return opResult;
    201169        }
    202        
     170
    203171        usb_pipe_start_session(hub_info->control_pipe);
    204172        //set hub configuration
    205173        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);
    208177                free(hub_info);
    209178                return opResult;
     
    211180        //get port count and create attached_devs
    212181        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);
    215185                free(hub_info);
    216186                return opResult;
     
    222192        usb_log_debug("Creating `hub' function.\n");
    223193        ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,
    224                         fun_exposed, "hub");
     194                fun_exposed, "hub");
    225195        assert(hub_fun != NULL);
    226196        hub_fun->ops = NULL;
     
    264234
    265235        usb_log_info("Controlling hub `%s' (%d ports).\n",
    266             hub_info->usb_device->ddf_dev->name, hub_info->port_count);
     236                hub_info->usb_device->ddf_dev->name, hub_info->port_count);
    267237        return EOK;
    268 
    269238leave:
    270239        free(hub_info);
     
    280249//*********************************************
    281250
    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 */
     260bool 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
     279leave:
     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
    289292 * @return error code
    290293 */
    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;
     294int usb_hub_check_hub_changes(usb_hub_info_t * hub_info) {
    296295        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);
    316319                        }
    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);
    379380        return EOK;
    380381}
    381382
     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 */
     396static 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 */
     417static 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 */
     486static 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}
    382516
    383517/**
     
    389523 * @return error code
    390524 */
    391 static int usb_hub_release_default_address(usb_hub_info_t * hub){
     525static int usb_hub_release_default_address(usb_hub_info_t * hub) {
    392526        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);
    395530                return opResult;
    396531        }
     
    398533        return EOK;
    399534}
     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 */
     544static 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 */
     595static 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
    400681
    401682/**
     
    408689 * @param port port number, starting from 1
    409690 */
    410 void usb_hub_removed_device(
    411     usb_hub_info_t * hub,uint16_t port) {
     691static void usb_hub_removed_device(
     692        usb_hub_info_t * hub, uint16_t port) {
    412693
    413694        int opResult = usb_hub_clear_port_feature(hub->control_pipe,
    414                                 port, USB_HUB_FEATURE_C_PORT_CONNECTION);
    415         if(opResult != EOK){
     695                port, USB_HUB_FEATURE_C_PORT_CONNECTION);
     696        if (opResult != EOK) {
    416697                usb_log_warning("could not clear port-change-connection flag\n");
    417698        }
     
    419700         * devide manager
    420701         */
    421        
     702
    422703        //close address
     704        //if (hub->attached_devs[port].address != 0) {
    423705        if(hub->ports[port].attached_device.address >= 0){
    424706                /*uncomment this code to use it when DDF allows device removal
    425707                opResult = usb_hc_unregister_device(
    426                                 &hub->connection, hub->attached_devs[port].address);
     708                        &hub->connection,
     709                        hub->attached_devs[port].address);
    427710                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 "
    429713                            "removed device: %d", opResult);
    430714                }
     
    432716                hub->attached_devs[port].handle = 0;
    433717                 */
    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
    437723                usb_hub_release_default_address(hub);
    438724        }
    439725}
    440726
    441 
    442727/**
    443728 * Process over current condition on port.
    444  * 
     729 *
    445730 * Turn off the power on the port.
    446731 *
     
    448733 * @param port port number, starting from 1
    449734 */
    450 void usb_hub_over_current( usb_hub_info_t * hub,
    451                 uint16_t port){
     735static void usb_hub_port_over_current(usb_hub_info_t * hub,
     736        uint16_t port, uint32_t status) {
    452737        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",
    457743                                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 */
     762static 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 */
     797static 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 */
     841static 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
     869leave:
     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 */
     885static 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 */
     930static 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 */
     1029static 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 */
     1060static 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 */
     1094static 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
    4601128
    4611129
  • uspace/drv/usbhub/usbhub.h

    r61727bf r8961c22  
    4343
    4444#include <usb/hub.h>
     45#include <usb/classes/hub.h>
    4546
    4647#include <usb/pipes.h>
    4748#include <usb/devdrv.h>
    4849
    49 #include "ports.h"
     50#include <fibril_synch.h>
    5051
    5152
     53/** Information about single port on a hub. */
     54typedef 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 */
     72static 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}
    5278
    5379/** Information about attached hub. */
     
    5682        size_t port_count;
    5783
    58         /** Ports. */
     84        /** attached device handles, for each port one */
    5985        usb_hub_port_t *ports;
    60        
     86
    6187        /** connection to hcd */
    6288        usb_hc_connection_t connection;
     
    89115} usb_hub_info_t;
    90116
    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);
    107118
    108119int usb_hub_add_device(usb_device_t * usb_dev);
    109120
     121int usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param);
     122
     123bool hub_port_changes_callback(usb_device_t *dev,
     124    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg);
    110125#endif
    111126/**
  • uspace/drv/usbhub/usbhub_private.h

    r61727bf r8961c22  
    3838
    3939#include "usbhub.h"
     40#include "usblist.h"
    4041
    4142#include <adt/list.h>
     
    110111
    111112/**
     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 */
     121static 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 */
     144static 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 */
     165static 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/**
    112180 * create uint8_t array with serialized descriptor
    113181 *
Note: See TracChangeset for help on using the changeset viewer.