Changeset 1e1b1a9 in mainline


Ignore:
Timestamp:
2011-04-09T15:06:34Z (13 years ago)
Author:
Matus Dekanek <smekideki@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f35b294
Parents:
8961c22
Message:

usbhub refactoring

Location:
uspace/drv/usbhub
Files:
2 deleted
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbhub/Makefile

    r8961c22 r1e1b1a9  
    3636        utils.c \
    3737        usbhub.c \
    38         usblist.c
     38        ports.c
    3939
    4040include $(USPACE_PREFIX)/Makefile.common
  • uspace/drv/usbhub/usbhub.c

    r8961c22 r1e1b1a9  
    5555
    5656
    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 
    6557static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev);
    6658
     
    6961static int usb_hub_set_configuration(usb_hub_info_t * hub_info);
    7062
    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);
     63//static int usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param);
    9764
    9865static int usb_process_hub_over_current(usb_hub_info_t * hub_info,
     
    10471static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info);
    10572
    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  */
     73
    13774/// \TODO malloc checking
    13875
     
    250187
    251188
    252 /** Callback for polling hub for port changes.
     189/** Callback for polling hub for changes.
    253190 *
    254191 * @param dev Device where the change occured.
     
    266203        if (change_bitmap_size == 0) {
    267204                goto leave;
     205        }
     206
     207        bool change;
     208        change = ((uint8_t*)change_bitmap)[0] & 1;
     209        if(change){
     210                usb_hub_process_global_interrupt(hub);
    268211        }
    269212
     
    277220
    278221
     222
     223
     224
    279225leave:
    280226        /* FIXME: proper interval. */
     
    286232
    287233/**
    288  * check changes on hub
    289  *
    290  * Handles changes on each port with a status change.
    291  * @param hub_info hub representation
    292  * @return error code
    293  */
    294 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info) {
    295         int opResult;
    296         opResult = usb_pipe_start_session(
    297                 hub_info->status_change_pipe);
    298         //this might not be necessary - if all non-removables are ok, it is
    299         //not needed here
    300         opResult = usb_pipe_start_session(hub_info->control_pipe);
    301         if (opResult != EOK) {
    302                 usb_log_error("could not initialize communication for hub; %d\n",
    303                         opResult);
    304                 return opResult;
    305         }
    306 
    307         size_t port_count = hub_info->port_count;
    308         //first check non-removable devices
    309         /*
    310         {
    311                 unsigned int port;
    312                 for (port = 0; port < port_count; ++port) {
    313                         bool is_non_removable =
    314                                 hub_info->not_initialized_non_removables[port/8]
    315                                 & (1 << (port-1 % 8));
    316                         if (is_non_removable) {
    317                                 opResult = initialize_non_removable(hub_info,
    318                                         port+1);
    319                         }
    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);
     234 * release default address used by given hub
     235 *
     236 * Also unsets hub->is_default_address_used. Convenience wrapper function.
     237 * @note hub->connection MUST be open for communication
     238 * @param hub hub representation
     239 * @return error code
     240 */
     241int usb_hub_release_default_address(usb_hub_info_t * hub) {
     242        int opResult = usb_hc_release_default_address(&hub->connection);
     243        if (opResult != EOK) {
     244                usb_log_error("could not release default address, errno %d\n",
     245                        opResult);
     246                return opResult;
     247        }
     248        hub->is_default_address_used = false;
    380249        return EOK;
    381250}
     251
    382252
    383253//*********************************************
     
    422292        int opResult;
    423293
    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 
    437294        size_t received_size;
    438295        opResult = usb_request_get_descriptor(hub_info->control_pipe,
     
    457314        usb_log_debug("setting port count to %d\n", descriptor->ports_count);
    458315        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 //              );
     316        /// \TODO this is not semantically correct
    464317        hub_info->ports = malloc(sizeof(usb_hub_port_t) * (hub_info->port_count+1));
    465318        size_t port;
     
    467320                usb_hub_port_init(&hub_info->ports[port]);
    468321        }
    469         //handle non-removable devices
    470         //usb_hub_trigger_connecting_non_removable_devices(hub_info, descriptor);
    471322        usb_log_debug2("freeing data\n");
    472323        free(serialized_descriptor);
     
    515366}
    516367
    517 /**
    518  * release default address used by given hub
    519  *
    520  * Also unsets hub->is_default_address_used. Convenience wrapper function.
    521  * @note hub->connection MUST be open for communication
    522  * @param hub hub representation
    523  * @return error code
    524  */
    525 static int usb_hub_release_default_address(usb_hub_info_t * hub) {
    526         int opResult = usb_hc_release_default_address(&hub->connection);
    527         if (opResult != EOK) {
    528                 usb_log_error("could not release default address, errno %d\n",
    529                         opResult);
    530                 return opResult;
    531         }
    532         hub->is_default_address_used = false;
     368#if 0
     369/**
     370 * check changes on hub
     371 *
     372 * Handles changes on each port with a status change.
     373 * @param hub_info hub representation
     374 * @return error code
     375 */
     376static int usb_hub_check_hub_changes(usb_hub_info_t * hub_info) {
     377        int opResult;
     378        opResult = usb_pipe_start_session(
     379                hub_info->status_change_pipe);
     380        //this might not be necessary - if all non-removables are ok, it is
     381        //not needed here
     382        opResult = usb_pipe_start_session(hub_info->control_pipe);
     383        if (opResult != EOK) {
     384                usb_log_error("could not initialize communication for hub; %d\n",
     385                        opResult);
     386                return opResult;
     387        }
     388
     389        size_t port_count = hub_info->port_count;
     390        size_t byte_length = ((port_count + 1) / 8) + 1;
     391        void *change_bitmap = malloc(byte_length);
     392        size_t actual_size;
     393
     394        /*
     395         * Send the request.
     396         */
     397        opResult = usb_pipe_read(
     398                hub_info->status_change_pipe,
     399                change_bitmap, byte_length, &actual_size
     400                );
     401
     402        if (opResult != EOK) {
     403                free(change_bitmap);
     404                usb_log_warning("something went wrong while getting the"
     405                        "status of hub\n");
     406                usb_pipe_end_session(hub_info->status_change_pipe);
     407                return opResult;
     408        }
     409        unsigned int port;
     410
     411        if (opResult != EOK) {
     412                usb_log_error("could not start control pipe session %d\n",
     413                        opResult);
     414                usb_pipe_end_session(hub_info->status_change_pipe);
     415                return opResult;
     416        }
     417        opResult = usb_hc_connection_open(&hub_info->connection);
     418        if (opResult != EOK) {
     419                usb_log_error("could not start host controller session %d\n",
     420                        opResult);
     421                usb_pipe_end_session(hub_info->control_pipe);
     422                usb_pipe_end_session(hub_info->status_change_pipe);
     423                return opResult;
     424        }
     425
     426        ///todo, opresult check, pre obe konekce
     427        bool interrupt;
     428        interrupt = ((uint8_t*)change_bitmap)[0] & 1;
     429        if(interrupt){
     430                usb_hub_process_global_interrupt(hub_info);
     431        }
     432        for (port = 1; port < port_count + 1; ++port) {
     433                interrupt =
     434                        ((uint8_t*) change_bitmap)[port / 8] & (1<<(port % 8));
     435                if (interrupt) {
     436                        usb_hub_process_interrupt(
     437                                hub_info, port);
     438                }
     439        }
     440        /// \todo check hub status
     441        usb_hc_connection_close(&hub_info->connection);
     442        usb_pipe_end_session(hub_info->control_pipe);
     443        usb_pipe_end_session(hub_info->status_change_pipe);
     444        free(change_bitmap);
    533445        return EOK;
    534446}
    535447
    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 }
    584448#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
    681 
    682 /**
    683  * routine called when a device on port has been removed
    684  *
    685  * If the device on port had default address, it releases default address.
    686  * Otherwise does not do anything, because DDF does not allow to remove device
    687  * from it`s device tree.
    688  * @param hub hub representation
    689  * @param port port number, starting from 1
    690  */
    691 static void usb_hub_removed_device(
    692         usb_hub_info_t * hub, uint16_t port) {
    693 
    694         int opResult = usb_hub_clear_port_feature(hub->control_pipe,
    695                 port, USB_HUB_FEATURE_C_PORT_CONNECTION);
    696         if (opResult != EOK) {
    697                 usb_log_warning("could not clear port-change-connection flag\n");
    698         }
    699         /** \TODO remove device from device manager - not yet implemented in
    700          * devide manager
    701          */
    702 
    703         //close address
    704         //if (hub->attached_devs[port].address != 0) {
    705         if(hub->ports[port].attached_device.address >= 0){
    706                 /*uncomment this code to use it when DDF allows device removal
    707                 opResult = usb_hc_unregister_device(
    708                         &hub->connection,
    709                         hub->attached_devs[port].address);
    710                 if(opResult != EOK) {
    711                         dprintf(USB_LOG_LEVEL_WARNING, "could not release "
    712                                 "address of "
    713                             "removed device: %d", opResult);
    714                 }
    715                 hub->attached_devs[port].address = 0;
    716                 hub->attached_devs[port].handle = 0;
    717                  */
    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
    723                 usb_hub_release_default_address(hub);
    724         }
    725 }
    726 
    727 /**
    728  * Process over current condition on port.
    729  *
    730  * Turn off the power on the port.
    731  *
    732  * @param hub hub representation
    733  * @param port port number, starting from 1
    734  */
    735 static void usb_hub_port_over_current(usb_hub_info_t * hub,
    736         uint16_t port, uint32_t status) {
    737         int opResult;
    738         if(usb_port_over_current(&status)){
    739                 opResult = usb_hub_clear_port_feature(hub->control_pipe,
    740                         port, USB_HUB_FEATURE_PORT_POWER);
    741                 if (opResult != EOK) {
    742                         usb_log_error("cannot power off port %d;  %d\n",
    743                                 port, opResult);
    744                 }
    745         }else{
    746                 opResult = usb_hub_set_port_feature(hub->control_pipe,
    747                         port, USB_HUB_FEATURE_PORT_POWER);
    748                 if (opResult != EOK) {
    749                         usb_log_error("cannot power on port %d;  %d\n",
    750                                 port, opResult);
    751                 }
    752         }
    753 }
    754 
    755 /** Retrieve port status.
    756  *
    757  * @param[in] ctrl_pipe Control pipe to use.
    758  * @param[in] port Port number (starting at 1).
    759  * @param[out] status Where to store the port status.
    760  * @return Error code.
    761  */
    762 static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,
    763     usb_port_status_t *status)
    764 {
    765         size_t recv_size;
    766         usb_device_request_setup_packet_t request;
    767         usb_port_status_t status_tmp;
    768 
    769         usb_hub_set_port_status_request(&request, port);
    770         int rc = usb_pipe_control_read(ctrl_pipe,
    771             &request, sizeof(usb_device_request_setup_packet_t),
    772             &status_tmp, sizeof(status_tmp), &recv_size);
    773         if (rc != EOK) {
    774                 return rc;
    775         }
    776 
    777         if (recv_size != sizeof (status_tmp)) {
    778                 return ELIMIT;
    779         }
    780 
    781         if (status != NULL) {
    782                 *status = status_tmp;
    783         }
    784 
    785         return EOK;
    786 }
    787 
    788 /** Callback for enabling a specific port.
    789  *
    790  * We wait on a CV until port is reseted.
    791  * That is announced via change on interrupt pipe.
    792  *
    793  * @param port_no Port number (starting at 1).
    794  * @param arg Custom argument, points to @c usb_hub_info_t.
    795  * @return Error code.
    796  */
    797 static int enable_port_callback(int port_no, void *arg)
    798 {
    799         usb_hub_info_t *hub = (usb_hub_info_t *) arg;
    800         int rc;
    801         usb_device_request_setup_packet_t request;
    802         usb_hub_port_t *my_port = hub->ports + port_no;
    803 
    804         usb_hub_set_reset_port_request(&request, port_no);
    805         rc = usb_pipe_control_write(hub->control_pipe,
    806             &request, sizeof(request), NULL, 0);
    807         if (rc != EOK) {
    808                 usb_log_warning("Port reset failed: %s.\n", str_error(rc));
    809                 return rc;
    810         }
    811 
    812         /*
    813          * Wait until reset completes.
    814          */
    815         fibril_mutex_lock(&my_port->reset_mutex);
    816         while (!my_port->reset_completed) {
    817                 fibril_condvar_wait(&my_port->reset_cv, &my_port->reset_mutex);
    818         }
    819         fibril_mutex_unlock(&my_port->reset_mutex);
    820 
    821         /* Clear the port reset change. */
    822         rc = usb_hub_clear_port_feature(hub->control_pipe,
    823             port_no, USB_HUB_FEATURE_C_PORT_RESET);
    824         if (rc != EOK) {
    825                 usb_log_error("Failed to clear port %d reset feature: %s.\n",
    826                     port_no, str_error(rc));
    827                 return rc;
    828         }
    829 
    830         return EOK;
    831 }
    832 
    833 /** Fibril for adding a new device.
    834  *
    835  * Separate fibril is needed because the port reset completion is announced
    836  * via interrupt pipe and thus we cannot block here.
    837  *
    838  * @param arg Pointer to struct add_device_phase1.
    839  * @return 0 Always.
    840  */
    841 static int add_device_phase1_worker_fibril(void *arg)
    842 {
    843         struct add_device_phase1 *data
    844             = (struct add_device_phase1 *) arg;
    845 
    846         usb_address_t new_address;
    847         devman_handle_t child_handle;
    848 
    849         int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev,
    850             &data->hub->connection, data->speed,
    851             enable_port_callback, (int) data->port, data->hub,
    852             &new_address, &child_handle,
    853             NULL, NULL, NULL);
    854 
    855         if (rc != EOK) {
    856                 usb_log_error("Failed registering device on port %zu: %s.\n",
    857                     data->port, str_error(rc));
    858                 goto leave;
    859         }
    860 
    861         data->hub->ports[data->port].attached_device.handle = child_handle;
    862         data->hub->ports[data->port].attached_device.address = new_address;
    863 
    864         usb_log_info("Detected new device on `%s' (port %zu), "
    865             "address %d (handle %" PRIun ").\n",
    866             data->hub->usb_device->ddf_dev->name, data->port,
    867             new_address, child_handle);
    868 
    869 leave:
    870         free(arg);
    871 
    872         return EOK;
    873 }
    874 
    875 
    876 /** Start device adding when connection change is detected.
    877  *
    878  * This fires a new fibril to complete the device addition.
    879  *
    880  * @param hub Hub where the change occured.
    881  * @param port Port index (starting at 1).
    882  * @param speed Speed of the device.
    883  * @return Error code.
    884  */
    885 static int add_device_phase1_new_fibril(usb_hub_info_t *hub, size_t port,
    886     usb_speed_t speed)
    887 {
    888         struct add_device_phase1 *data
    889             = malloc(sizeof(struct add_device_phase1));
    890         if (data == NULL) {
    891                 return ENOMEM;
    892         }
    893         data->hub = hub;
    894         data->port = port;
    895         data->speed = speed;
    896 
    897         usb_hub_port_t *the_port = hub->ports + port;
    898 
    899         fibril_mutex_lock(&the_port->reset_mutex);
    900         the_port->reset_completed = false;
    901         fibril_mutex_unlock(&the_port->reset_mutex);
    902 
    903         int rc = usb_hub_clear_port_feature(hub->control_pipe, port,
    904             USB_HUB_FEATURE_C_PORT_CONNECTION);
    905         if (rc != EOK) {
    906                 free(data);
    907                 usb_log_warning("Failed to clear port change flag: %s.\n",
    908                     str_error(rc));
    909                 return rc;
    910         }
    911 
    912         fid_t fibril = fibril_create(add_device_phase1_worker_fibril, data);
    913         if (fibril == 0) {
    914                 free(data);
    915                 return ENOMEM;
    916         }
    917         fibril_add_ready(fibril);
    918 
    919         return EOK;
    920 }
    921 
    922 
    923 /**
    924  * Process interrupts on given hub port
    925  *
    926  * Accepts connection, over current and port reset change.
    927  * @param hub hub representation
    928  * @param port port number, starting from 1
    929  */
    930 static void usb_hub_process_interrupt(usb_hub_info_t * hub,
    931         uint16_t port) {
    932         usb_log_debug("interrupt at port %d\n", port);
    933         //determine type of change
    934         //usb_pipe_t *pipe = hub->control_pipe;
    935 
    936         int opResult;
    937 
    938         usb_port_status_t status;
    939         opResult = get_port_status(&hub->usb_device->ctrl_pipe, port, &status);
    940         if (opResult != EOK) {
    941                 usb_log_error("Failed to get port %zu status: %s.\n",
    942                     port, str_error(opResult));
    943                 return;
    944         }
    945 
    946         //something connected/disconnected
    947         /*
    948         if (usb_port_connect_change(&status)) {
    949                 usb_log_debug("connection change on port\n");
    950                 if (usb_port_dev_connected(&status)) {
    951                         usb_hub_init_add_device(hub, port,
    952                                 usb_port_speed(&status));
    953                 } else {
    954                         usb_hub_removed_device(hub, port);
    955                 }
    956         }*/
    957         if (usb_port_connect_change(&status)) {
    958                 bool device_connected = usb_port_dev_connected(&status);
    959                 usb_log_debug("Connection change on port %zu: %s.\n", port,
    960                     device_connected ? "device attached" : "device removed");
    961 
    962                 if (device_connected) {
    963                         opResult = add_device_phase1_new_fibril(hub, port,
    964                             usb_port_speed(&status));
    965                         if (opResult != EOK) {
    966                                 usb_log_error(
    967                                     "Cannot handle change on port %zu: %s.\n",
    968                                     str_error(opResult));
    969                         }
    970                 } else {
    971                         usb_hub_removed_device(hub, port);
    972                 }
    973         }
    974         //over current
    975         if (usb_port_overcurrent_change(&status)) {
    976                 //check if it was not auto-resolved
    977                 usb_log_debug("overcurrent change on port\n");
    978                 usb_hub_port_over_current(hub, port, status);
    979         }
    980         //port reset
    981         if (usb_port_reset_completed(&status)) {
    982                 /*
    983                 usb_log_debug("port reset complete\n");
    984                 if (usb_port_enabled(&status)) {
    985                         usb_hub_finalize_add_device(hub, port,
    986                                 usb_port_speed(&status));
    987                 } else {
    988                         usb_log_warning("port reset, but port still not "
    989                                 "enabled\n");
    990                 }
    991                  * */
    992                 usb_log_debug("Port %zu reset complete.\n", port);
    993                 if (usb_port_enabled(&status)) {
    994                         /* Finalize device adding. */
    995                         usb_hub_port_t *the_port = hub->ports + port;
    996                         fibril_mutex_lock(&the_port->reset_mutex);
    997                         the_port->reset_completed = true;
    998                         fibril_condvar_broadcast(&the_port->reset_cv);
    999                         fibril_mutex_unlock(&the_port->reset_mutex);
    1000                 } else {
    1001                         usb_log_warning(
    1002                             "Port %zu reset complete but port not enabled.\n",
    1003                             port);
    1004                 }
    1005         }
    1006         usb_log_debug("status x%x : %d\n ", status, status);
    1007 
    1008         usb_port_set_connect_change(&status, false);
    1009         usb_port_set_reset(&status, false);
    1010         usb_port_set_reset_completed(&status, false);
    1011         usb_port_set_dev_connected(&status, false);
    1012         usb_port_set_overcurrent_change(&status,false);
    1013         /// \TODO what about port power change?
    1014         if (status >> 16) {
    1015                 usb_log_info("there was unsupported change on port %d: %X\n",
    1016                         port, status);
    1017 
    1018         }
    1019 }
    1020449
    1021450/**
  • uspace/drv/usbhub/usbhub.h

    r8961c22 r1e1b1a9  
    3737
    3838#include <ipc/devman.h>
    39 #include <usb/usb.h>
    4039#include <ddf/driver.h>
    41 
    42 #define NAME "usbhub"
    4340
    4441#include <usb/hub.h>
     
    5047#include <fibril_synch.h>
    5148
     49#define NAME "usbhub"
    5250
    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;
     51#include "ports.h"
    6352
    64         /** Information about attached device. */
    65         usb_hc_attached_device_t attached_device;
    66 } usb_hub_port_t;
    6753
    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 }
    7854
    7955/** Information about attached hub. */
    80 typedef struct {
     56typedef struct usb_hub_info_t{
    8157        /** Number of ports. */
    8258        size_t port_count;
     
    11995int usb_hub_add_device(usb_device_t * usb_dev);
    12096
    121 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param);
    122 
    12397bool hub_port_changes_callback(usb_device_t *dev,
    12498    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg);
     99
     100int usb_hub_release_default_address(usb_hub_info_t * hub);
     101
    125102#endif
    126103/**
  • uspace/drv/usbhub/usbhub_private.h

    r8961c22 r1e1b1a9  
    3838
    3939#include "usbhub.h"
    40 #include "usblist.h"
    4140
    4241#include <adt/list.h>
Note: See TracChangeset for help on using the changeset viewer.