Changeset 45bf63c in mainline for uspace/drv/bus


Ignore:
Timestamp:
2011-10-30T15:35:36Z (14 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
20a3465, 3ce78580
Parents:
1737bfb (diff), e978ada (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge from USB branch.

Cleanup libusbhost interfaces.
Fix few possible memory corruption/crashes and memory leaks.
Add device_remove hooks for usbflbk, usbhid.

Location:
uspace/drv/bus/usb
Files:
23 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/ohci/endpoint_list.c

    r1737bfb r45bf63c  
    7373 * Does not check whether this replaces an existing list.
    7474 */
    75 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next)
     75void endpoint_list_set_next(
     76    const endpoint_list_t *instance, const endpoint_list_t *next)
    7677{
    7778        assert(instance);
  • uspace/drv/bus/usb/ohci/endpoint_list.h

    r1737bfb r45bf63c  
    6868
    6969int endpoint_list_init(endpoint_list_t *instance, const char *name);
    70 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next);
     70void endpoint_list_set_next(
     71    const endpoint_list_t *instance, const endpoint_list_t *next);
    7172void endpoint_list_add_ep(endpoint_list_t *instance, ohci_endpoint_t *ep);
    7273void endpoint_list_remove_ep(endpoint_list_t *instance, ohci_endpoint_t *ep);
  • uspace/drv/bus/usb/ohci/hc.c

    r1737bfb r45bf63c  
    142142if (ret != EOK) { \
    143143        usb_log_error(message); \
    144         usb_endpoint_manager_unregister_ep( \
    145             &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH);\
     144        usb_endpoint_manager_remove_ep( \
     145            &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH, \
     146            NULL, NULL);\
    146147        usb_device_manager_release( \
    147148            &instance->generic.dev_manager, hub_address); \
     
    150151        int ret = usb_endpoint_manager_add_ep(
    151152            &instance->generic.ep_manager, hub_address, 0, USB_DIRECTION_BOTH,
    152             USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 0);
     153            USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 0, NULL, NULL);
    153154        CHECK_RET_UNREG_RETURN(ret,
    154155            "Failed to register root hub control endpoint: %s.\n",
     
    192193        list_initialize(&instance->pending_batches);
    193194
    194         ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
     195        hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
    195196            bandwidth_count_usb11);
    196         CHECK_RET_RETURN(ret, "Failed to initialize generic driver: %s.\n",
    197             str_error(ret));
    198197        instance->generic.private_data = instance;
    199198        instance->generic.schedule = hc_schedule;
    200199        instance->generic.ep_add_hook = ohci_endpoint_init;
     200        instance->generic.ep_remove_hook = ohci_endpoint_fini;
    201201
    202202        ret = hc_init_memory(instance);
     
    221221}
    222222/*----------------------------------------------------------------------------*/
    223 void hc_enqueue_endpoint(hc_t *instance, endpoint_t *ep)
    224 {
     223void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep)
     224{
     225        assert(instance);
     226        assert(ep);
     227
    225228        endpoint_list_t *list = &instance->lists[ep->transfer_type];
    226229        ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep);
     230        assert(list);
     231        assert(ohci_ep);
     232
    227233        /* Enqueue ep */
    228234        switch (ep->transfer_type) {
     
    247253}
    248254/*----------------------------------------------------------------------------*/
    249 void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep)
    250 {
     255void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep)
     256{
     257        assert(instance);
     258        assert(ep);
     259
    251260        /* Dequeue ep */
    252261        endpoint_list_t *list = &instance->lists[ep->transfer_type];
    253262        ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ep);
     263
     264        assert(list);
     265        assert(ohci_ep);
    254266        switch (ep->transfer_type) {
    255267        case USB_TRANSFER_CONTROL:
  • uspace/drv/bus/usb/ohci/hc.h

    r1737bfb r45bf63c  
    8686static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ };
    8787
    88 void hc_enqueue_endpoint(hc_t *instance, endpoint_t *ep);
    89 void hc_dequeue_endpoint(hc_t *instance, endpoint_t *ep);
     88void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep);
     89void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep);
    9090
    9191void hc_interrupt(hc_t *instance, uint32_t status);
  • uspace/drv/bus/usb/ohci/ohci.c

    r1737bfb r45bf63c  
    8989            &dev_to_ohci(fun->dev)->hc.generic.dev_manager;
    9090
    91         const usb_address_t addr = usb_device_manager_find(manager, handle);
     91        const usb_address_t addr =
     92            usb_device_manager_find_address(manager, handle);
    9293        if (addr < 0) {
    9394                return addr;
  • uspace/drv/bus/usb/ohci/ohci_batch.c

    r1737bfb r45bf63c  
    5959                free(ohci_batch->tds);
    6060        }
    61         usb_transfer_batch_dispose(ohci_batch->usb_batch);
     61        usb_transfer_batch_destroy(ohci_batch->usb_batch);
    6262        free32(ohci_batch->device_buffer);
    6363        free(ohci_batch);
  • uspace/drv/bus/usb/ohci/ohci_endpoint.c

    r1737bfb r45bf63c  
    6262}
    6363/*----------------------------------------------------------------------------*/
    64 /** Disposes hcd endpoint structure
    65  *
    66  * @param[in] hcd_ep endpoint structure
    67  */
    68 static void ohci_endpoint_fini(endpoint_t *ep)
    69 {
    70         ohci_endpoint_t *instance = ep->hc_data.data;
    71         hc_dequeue_endpoint(instance->hcd->private_data, ep);
    72         if (instance) {
    73                 free32(instance->ed);
    74                 free32(instance->td);
    75                 free(instance);
    76         }
    77 }
    78 /*----------------------------------------------------------------------------*/
    7964/** Creates new hcd endpoint representation.
    8065 *
    8166 * @param[in] ep USBD endpoint structure
    82  * @return pointer to a new hcd endpoint structure, NULL on failure.
     67 * @return Error code.
    8368 */
    8469int ohci_endpoint_init(hcd_t *hcd, endpoint_t *ep)
     
    10489        ed_init(ohci_ep->ed, ep, ohci_ep->td);
    10590        endpoint_set_hc_data(
    106             ep, ohci_ep, ohci_endpoint_fini, ohci_ep_toggle_get, ohci_ep_toggle_set);
    107         ohci_ep->hcd = hcd;
     91            ep, ohci_ep, ohci_ep_toggle_get, ohci_ep_toggle_set);
    10892        hc_enqueue_endpoint(hcd->private_data, ep);
    10993        return EOK;
     94}
     95/*----------------------------------------------------------------------------*/
     96/** Disposes hcd endpoint structure
     97 *
     98 * @param[in] hcd driver using this instance.
     99 * @param[in] ep endpoint structure.
     100 */
     101void ohci_endpoint_fini(hcd_t *hcd, endpoint_t *ep)
     102{
     103        assert(hcd);
     104        assert(ep);
     105        ohci_endpoint_t *instance = ohci_endpoint_get(ep);
     106        hc_dequeue_endpoint(hcd->private_data, ep);
     107        if (instance) {
     108                free32(instance->ed);
     109                free32(instance->td);
     110                free(instance);
     111        }
     112        endpoint_clear_hc_data(ep);
    110113}
    111114/**
  • uspace/drv/bus/usb/ohci/ohci_endpoint.h

    r1737bfb r45bf63c  
    5151        /** Linked list used by driver software */
    5252        link_t link;
    53         /** Device using this ep */
    54         hcd_t *hcd;
    5553} ohci_endpoint_t;
    5654
    5755int ohci_endpoint_init(hcd_t *hcd, endpoint_t *ep);
     56void ohci_endpoint_fini(hcd_t *hcd, endpoint_t *ep);
    5857
    5958/** Get and convert assigned ohci_endpoint_t structure
     
    6160 * @return Pointer to assigned hcd endpoint structure
    6261 */
    63 static inline ohci_endpoint_t * ohci_endpoint_get(endpoint_t *ep)
     62static inline ohci_endpoint_t * ohci_endpoint_get(const endpoint_t *ep)
    6463{
    6564        assert(ep);
  • uspace/drv/bus/usb/ohci/ohci_regs.h

    r1737bfb r45bf63c  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbohcihc
     28/** @addtogroup drvusbohci
    2929 * @{
    3030 */
  • uspace/drv/bus/usb/ohci/root_hub.c

    r1737bfb r45bf63c  
    235235                usb_transfer_batch_finish_error(request, NULL, 0, EINVAL);
    236236        }
    237         usb_transfer_batch_dispose(request);
     237        usb_transfer_batch_destroy(request);
    238238}
    239239/*----------------------------------------------------------------------------*/
     
    254254                interrupt_request(instance->unfinished_interrupt_transfer,
    255255                    mask, instance->interrupt_mask_size);
    256                 usb_transfer_batch_dispose(
     256                usb_transfer_batch_destroy(
    257257                    instance->unfinished_interrupt_transfer);
    258258                instance->unfinished_interrupt_transfer = NULL;
  • uspace/drv/bus/usb/uhci/hc.c

    r1737bfb r45bf63c  
    192192            "Device registers at %p (%zuB) accessible.\n", io, reg_size);
    193193
    194         ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
     194        ret = hc_init_mem_structures(instance);
     195        CHECK_RET_RETURN(ret,
     196            "Failed to initialize UHCI memory structures: %s.\n",
     197            str_error(ret));
     198
     199#undef CHECK_RET_RETURN
     200
     201        hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11,
    195202            bandwidth_count_usb11);
    196         CHECK_RET_RETURN(ret, "Failed to initialize HCD generic driver: %s.\n",
    197             str_error(ret));
    198203
    199204        instance->generic.private_data = instance;
    200205        instance->generic.schedule = hc_schedule;
    201206        instance->generic.ep_add_hook = NULL;
    202 
    203 #undef CHECK_RET_DEST_FUN_RETURN
    204 
    205         ret = hc_init_mem_structures(instance);
    206         if (ret != EOK) {
    207                 usb_log_error(
    208                     "Failed to initialize UHCI memory structures: %s.\n",
    209                     str_error(ret));
    210                 hcd_destroy(&instance->generic);
    211                 return ret;
    212         }
    213207
    214208        hc_init_hw(instance);
  • uspace/drv/bus/usb/uhci/uhci.c

    r1737bfb r45bf63c  
    101101        usb_device_manager_t *manager =
    102102            &dev_to_uhci(fun->dev)->hc.generic.dev_manager;
    103         const usb_address_t addr = usb_device_manager_find(manager, handle);
     103        const usb_address_t addr =
     104            usb_device_manager_find_address(manager, handle);
    104105
    105106        if (addr < 0) {
  • uspace/drv/bus/usb/uhci/uhci_batch.c

    r1737bfb r45bf63c  
    4848{
    4949        if (uhci_batch) {
    50                 usb_transfer_batch_dispose(uhci_batch->usb_batch);
     50                usb_transfer_batch_destroy(uhci_batch->usb_batch);
    5151                free32(uhci_batch->device_buffer);
    5252                free(uhci_batch);
  • uspace/drv/bus/usb/usbflbk/main.c

    r1737bfb r45bf63c  
    7474}
    7575
     76/** Callback when new device is about to be removed.
     77 *
     78 * @param dev Representation of a generic DDF device.
     79 * @return Error code.
     80 */
     81static int usbfallback_device_remove(usb_device_t *dev)
     82{
     83        return EOK;
     84}
     85
    7686/** Callback when new device is removed and recognized as gone by DDF.
    7787 *
     
    93103        return EOK;
    94104}
     105
    95106/** USB fallback driver ops. */
    96 static usb_driver_ops_t usbfallback_driver_ops = {
     107static const usb_driver_ops_t usbfallback_driver_ops = {
    97108        .device_add = usbfallback_device_add,
     109        .device_rem = usbfallback_device_remove,
    98110        .device_gone = usbfallback_device_gone,
    99111};
    100112
    101113/** USB fallback driver. */
    102 static usb_driver_t usbfallback_driver = {
     114static const usb_driver_t usbfallback_driver = {
    103115        .name = NAME,
    104116        .ops = &usbfallback_driver_ops,
  • uspace/drv/bus/usb/usbhid/main.c

    r1737bfb r45bf63c  
    4646#include "usbhid.h"
    4747
    48 /*----------------------------------------------------------------------------*/
    49 
    5048#define NAME "usbhid"
    5149
     
    6765 *
    6866 * @param dev Device to add.
    69  *
    70  * @retval EOK if successful.
    71  * @retval ENOMEM if there
    72  * @return Other error code inherited from one of functions usb_kbd_init(),
    73  *         ddf_fun_bind() and ddf_fun_add_to_class().
     67 * @return Error code.
    7468 */
    7569static int usb_hid_try_add_device(usb_device_t *dev)
     
    138132        return EOK;
    139133}
    140 
    141134/*----------------------------------------------------------------------------*/
    142135/**
     
    146139 *
    147140 * @param dev Structure representing the new device.
    148  *
    149  * @retval EOK if successful.
    150  * @retval EREFUSED if the device is not supported.
     141 * @return Error code.
    151142 */
    152143static int usb_hid_device_add(usb_device_t *dev)
     
    179170        return EOK;
    180171}
    181 
    182 /*----------------------------------------------------------------------------*/
    183 
     172/*----------------------------------------------------------------------------*/
     173/**
     174 * Callback for a device about to be removed from the driver.
     175 *
     176 * @param dev Structure representing the device.
     177 * @return Error code.
     178 */
     179static int usb_hid_device_rem(usb_device_t *dev)
     180{
     181        return EOK;
     182}
     183/*----------------------------------------------------------------------------*/
    184184/**
    185185 * Callback for removing a device from the driver.
    186186 *
    187187 * @param dev Structure representing the device.
    188  *
    189  * @retval EOK if successful.
    190  * @retval EREFUSED if the device is not supported.
     188 * @return Error code.
    191189 */
    192190static int usb_hid_device_gone(usb_device_t *dev)
     
    198196                if (!tries--) {
    199197                        usb_log_error("Can't remove hub, still running.\n");
    200                         return EINPROGRESS;
     198                        return EBUSY;
    201199                }
    202200        }
     
    207205        return EOK;
    208206}
    209 
     207/*----------------------------------------------------------------------------*/
    210208/** USB generic driver callbacks */
    211 static usb_driver_ops_t usb_hid_driver_ops = {
     209static const usb_driver_ops_t usb_hid_driver_ops = {
    212210        .device_add = usb_hid_device_add,
     211        .device_rem = usb_hid_device_rem,
    213212        .device_gone = usb_hid_device_gone,
    214213};
    215 
    216 
     214/*----------------------------------------------------------------------------*/
    217215/** The driver itself. */
    218 static usb_driver_t usb_hid_driver = {
     216static const usb_driver_t usb_hid_driver = {
    219217        .name = NAME,
    220218        .ops = &usb_hid_driver_ops,
    221219        .endpoints = usb_hid_endpoints
    222220};
    223 
    224 /*----------------------------------------------------------------------------*/
    225 
     221/*----------------------------------------------------------------------------*/
    226222int main(int argc, char *argv[])
    227223{
     
    232228        return usb_driver_main(&usb_hid_driver);
    233229}
    234 
    235230/**
    236231 * @}
  • uspace/drv/bus/usb/usbhub/main.c

    r1737bfb r45bf63c  
    4747 * For more information see section 11.15.1 of USB 1.1 specification.
    4848 */
    49 static usb_endpoint_description_t hub_status_change_endpoint_description = {
     49static const usb_endpoint_description_t hub_status_change_endpoint_description =
     50{
    5051        .transfer_type = USB_TRANSFER_INTERRUPT,
    5152        .direction = USB_DIRECTION_IN,
     
    5657};
    5758
    58 /**
    59  * USB hub driver operations
    60  *
    61  * The most important one is device_add, which is set to usb_hub_device_add.
    62  */
    63 static usb_driver_ops_t usb_hub_driver_ops = {
     59/** USB hub driver operations. */
     60static const usb_driver_ops_t usb_hub_driver_ops = {
    6461        .device_add = usb_hub_device_add,
     62//      .device_rem = usb_hub_device_remove,
    6563        .device_gone = usb_hub_device_gone,
    6664};
     
    7270};
    7371/** Static usb hub driver information. */
    74 static usb_driver_t usb_hub_driver = {
     72static const usb_driver_t usb_hub_driver = {
    7573        .name = NAME,
    7674        .ops = &usb_hub_driver_ops,
    7775        .endpoints = usb_hub_endpoints
    7876};
    79 
    8077
    8178int main(int argc, char *argv[])
  • uspace/drv/bus/usb/usbhub/port.h

    r1737bfb r45bf63c  
    4444/** Information about single port on a hub. */
    4545typedef struct {
     46        /* Port number as reporteed in descriptors. */
    4647        size_t port_number;
     48        /** Device communication pipe. */
    4749        usb_pipe_t *control_pipe;
    4850        /** Mutex needed not only by CV for checking port reset. */
  • uspace/drv/bus/usb/usbhub/usbhub.c

    r1737bfb r45bf63c  
    6868
    6969static int usb_set_first_configuration(usb_device_t *usb_device);
    70 static usb_hub_dev_t * usb_hub_dev_create(usb_device_t *usb_dev);
    7170static int usb_hub_process_hub_specific_info(usb_hub_dev_t *hub_dev);
    7271static void usb_hub_over_current(const usb_hub_dev_t *hub_dev,
     
    7574static void usb_hub_polling_terminated_callback(usb_device_t *device,
    7675    bool was_error, void *data);
    77 /**
    78  * Initialize hub device driver fibril
     76
     77/**
     78 * Initialize hub device driver structure.
    7979 *
    8080 * Creates hub representation and fibril that periodically checks hub's status.
    8181 * Hub representation is passed to the fibril.
     82 * @param usb_dev generic usb device information
     83 * @return error code
     84 */
     85int usb_hub_device_add(usb_device_t *usb_dev)
     86{
     87        assert(usb_dev);
     88        /* Create driver soft-state structure */
     89        usb_hub_dev_t *hub_dev =
     90            usb_device_data_alloc(usb_dev, sizeof(usb_hub_dev_t));
     91        if (hub_dev == NULL) {
     92                usb_log_error("Failed to create hub driver structure.\n");
     93                return ENOMEM;
     94        }
     95        hub_dev->usb_device = usb_dev;
     96        hub_dev->pending_ops_count = 0;
     97        hub_dev->running = false;
     98        fibril_mutex_initialize(&hub_dev->pending_ops_mutex);
     99        fibril_condvar_initialize(&hub_dev->pending_ops_cv);
     100
     101        /* Create hc connection */
     102        usb_log_debug("Initializing USB wire abstraction.\n");
     103        int opResult = usb_hc_connection_initialize_from_device(
     104            &hub_dev->connection, hub_dev->usb_device->ddf_dev);
     105        if (opResult != EOK) {
     106                usb_log_error("Could not initialize connection to device: %s\n",
     107                    str_error(opResult));
     108                return opResult;
     109        }
     110
     111        /* Set hub's first configuration. (There should be only one) */
     112        opResult = usb_set_first_configuration(usb_dev);
     113        if (opResult != EOK) {
     114                usb_log_error("Could not set hub configuration: %s\n",
     115                    str_error(opResult));
     116                return opResult;
     117        }
     118
     119        /* Get port count and create attached_devices. */
     120        opResult = usb_hub_process_hub_specific_info(hub_dev);
     121        if (opResult != EOK) {
     122                usb_log_error("Could process hub specific info, %s\n",
     123                    str_error(opResult));
     124                return opResult;
     125        }
     126
     127        /* Create hub control function. */
     128        usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n");
     129        hub_dev->hub_fun = ddf_fun_create(hub_dev->usb_device->ddf_dev,
     130            fun_exposed, HUB_FNC_NAME);
     131        if (hub_dev->hub_fun == NULL) {
     132                usb_log_error("Failed to create hub function.\n");
     133                return ENOMEM;
     134        }
     135
     136        /* Bind hub control function. */
     137        opResult = ddf_fun_bind(hub_dev->hub_fun);
     138        if (opResult != EOK) {
     139                usb_log_error("Failed to bind hub function: %s.\n",
     140                   str_error(opResult));
     141                ddf_fun_destroy(hub_dev->hub_fun);
     142                return opResult;
     143        }
     144
     145        /* Start hub operation. */
     146        opResult = usb_device_auto_poll(hub_dev->usb_device, 0,
     147            hub_port_changes_callback, ((hub_dev->port_count + 1 + 8) / 8),
     148            usb_hub_polling_terminated_callback, hub_dev);
     149        if (opResult != EOK) {
     150                /* Function is already bound */
     151                ddf_fun_unbind(hub_dev->hub_fun);
     152                ddf_fun_destroy(hub_dev->hub_fun);
     153                usb_log_error("Failed to create polling fibril: %s.\n",
     154                    str_error(opResult));
     155                return opResult;
     156        }
     157        hub_dev->running = true;
     158        usb_log_info("Controlling hub '%s' (%zu ports).\n",
     159            hub_dev->usb_device->ddf_dev->name, hub_dev->port_count);
     160
     161        return EOK;
     162}
     163/*----------------------------------------------------------------------------*/
     164/**
     165 * Turn off power to all ports.
     166 *
     167 * @param usb_dev generic usb device information
     168 * @return error code
     169 */
     170int usb_hub_device_remove(usb_device_t *usb_dev)
     171{
     172        assert(usb_dev);
     173        usb_hub_dev_t *hub_dev = usb_dev->driver_data;
     174        assert(hub_dev);
     175        //TODO: Cascade the call here.
     176        //TODO: Enable after cascading is implemented.
     177        return ENOTSUP;
     178        if (!hub_dev->power_switched) {
     179                /* That is all we can do. */
     180                return EOK;
     181        }
     182        int ret = EOK;
     183        usb_log_info("Hub is about to be removed, powering down all ports.\n");
     184        for (size_t port = 0; port < hub_dev->port_count; ++port) {
     185                usb_log_debug("Powering down port %zu.\n", port);
     186                int pret = usb_hub_port_clear_feature(
     187                    &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
     188                if (pret != EOK) {
     189                        usb_log_error("Cannot power down port %zu: %s.\n",
     190                            hub_dev->ports[port].port_number, str_error(pret));
     191                        ret = pret;
     192                } else {
     193                        if (!hub_dev->per_port_power) {
     194                                usb_log_debug("Ganged power switching mode, "
     195                                   "one port is enough.\n");
     196                                break;
     197                        }
     198                }
     199        }
     200        return ret;
     201}
     202/*----------------------------------------------------------------------------*/
     203/**
     204 * Remove all attached devices
    82205 * @param usb_dev generic usb device information
    83206 * @return error code
     
    121244}
    122245/*----------------------------------------------------------------------------*/
    123 /**
    124  * Initialize hub device driver fibril
    125  *
    126  * Creates hub representation and fibril that periodically checks hub's status.
    127  * Hub representation is passed to the fibril.
    128  * @param usb_dev generic usb device information
    129  * @return error code
    130  */
    131 int usb_hub_device_add(usb_device_t *usb_dev)
    132 {
    133         assert(usb_dev);
    134         /* Create driver soft-state structure */
    135         usb_hub_dev_t *hub_dev = usb_hub_dev_create(usb_dev);
    136         if (hub_dev == NULL) {
    137                 usb_log_error("Failed to create hun driver structure.\n");
    138                 return ENOMEM;
    139         }
    140 
    141         /* Create hc connection */
    142         usb_log_debug("Initializing USB wire abstraction.\n");
    143         int opResult = usb_hc_connection_initialize_from_device(
    144             &hub_dev->connection, hub_dev->usb_device->ddf_dev);
    145         if (opResult != EOK) {
    146                 usb_log_error("Could not initialize connection to device: %s\n",
    147                     str_error(opResult));
    148                 free(hub_dev);
    149                 return opResult;
    150         }
    151 
    152         /* Set hub's first configuration. (There should be only one) */
    153         opResult = usb_set_first_configuration(usb_dev);
    154         if (opResult != EOK) {
    155                 usb_log_error("Could not set hub configuration: %s\n",
    156                     str_error(opResult));
    157                 free(hub_dev);
    158                 return opResult;
    159         }
    160 
    161         /* Get port count and create attached_devices. */
    162         opResult = usb_hub_process_hub_specific_info(hub_dev);
    163         if (opResult != EOK) {
    164                 usb_log_error("Could process hub specific info, %s\n",
    165                     str_error(opResult));
    166                 free(hub_dev);
    167                 return opResult;
    168         }
    169 
    170         usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n");
    171         hub_dev->hub_fun = ddf_fun_create(hub_dev->usb_device->ddf_dev,
    172             fun_exposed, HUB_FNC_NAME);
    173         if (hub_dev->hub_fun == NULL) {
    174                 usb_log_error("Failed to create hub function.\n");
    175                 free(hub_dev);
    176                 return ENOMEM;
    177         }
    178 
    179         opResult = ddf_fun_bind(hub_dev->hub_fun);
    180         if (opResult != EOK) {
    181                 usb_log_error("Failed to bind hub function: %s.\n",
    182                    str_error(opResult));
    183                 free(hub_dev);
    184                 ddf_fun_destroy(hub_dev->hub_fun);
    185                 return opResult;
    186         }
    187 
    188         opResult = usb_device_auto_poll(hub_dev->usb_device, 0,
    189             hub_port_changes_callback, ((hub_dev->port_count + 1 + 8) / 8),
    190             usb_hub_polling_terminated_callback, hub_dev);
    191         if (opResult != EOK) {
    192                 /* Function is already bound */
    193                 ddf_fun_unbind(hub_dev->hub_fun);
    194                 ddf_fun_destroy(hub_dev->hub_fun);
    195                 free(hub_dev);
    196                 usb_log_error("Failed to create polling fibril: %s.\n",
    197                     str_error(opResult));
    198                 return opResult;
    199         }
    200         hub_dev->running = true;
    201         usb_log_info("Controlling hub '%s' (%zu ports).\n",
    202             hub_dev->usb_device->ddf_dev->name, hub_dev->port_count);
    203 
    204         return EOK;
    205 }
    206 /*----------------------------------------------------------------------------*/
    207246/** Callback for polling hub for changes.
    208247 *
     
    243282/*----------------------------------------------------------------------------*/
    244283/**
    245  * create usb_hub_dev_t structure
    246  *
    247  * Does only basic copying of known information into new structure.
    248  * @param usb_dev usb device structure
    249  * @return basic usb_hub_dev_t structure
    250  */
    251 static usb_hub_dev_t * usb_hub_dev_create(usb_device_t *usb_dev)
    252 {
    253         assert(usb_dev);
    254         usb_hub_dev_t *hub_dev =
    255             usb_device_data_alloc(usb_dev, sizeof(usb_hub_dev_t));
    256         if (!hub_dev)
    257             return NULL;
    258 
    259         hub_dev->usb_device = usb_dev;
    260         hub_dev->ports = NULL;
    261         hub_dev->port_count = 0;
    262         hub_dev->pending_ops_count = 0;
    263         hub_dev->running = false;
    264         fibril_mutex_initialize(&hub_dev->pending_ops_mutex);
    265         fibril_condvar_initialize(&hub_dev->pending_ops_cv);
    266 
    267         return hub_dev;
    268 }
    269 /*----------------------------------------------------------------------------*/
    270 /**
    271284 * Load hub-specific information into hub_dev structure and process if needed
    272285 *
     
    311324        }
    312325
    313         const bool is_power_switched =
     326        hub_dev->power_switched =
    314327            !(descriptor.characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG);
    315         if (is_power_switched) {
    316                 usb_log_debug("Hub power switched\n");
    317                 const bool per_port_power = descriptor.characteristics
    318                     & HUB_CHAR_POWER_PER_PORT_FLAG;
    319 
    320                 for (size_t port = 0; port < hub_dev->port_count; ++port) {
    321                         usb_log_debug("Powering port %zu.\n", port);
    322                         opResult = usb_hub_port_set_feature(
    323                             &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
    324                         if (opResult != EOK) {
    325                                 usb_log_error("Cannot power on port %zu: %s.\n",
    326                                     port, str_error(opResult));
    327                         } else {
    328                                 if (!per_port_power) {
    329                                         usb_log_debug(
    330                                             "Ganged power switching mode, "
    331                                             "one port is enough.\n");
    332                                         break;
    333                                 }
     328        hub_dev->per_port_power =
     329            descriptor.characteristics & HUB_CHAR_POWER_PER_PORT_FLAG;
     330
     331        if (!hub_dev->power_switched) {
     332                usb_log_info(
     333                   "Power switching not supported, ports always powered.\n");
     334                return EOK;
     335        }
     336
     337        usb_log_info("Hub port power switching enabled.\n");
     338
     339        for (size_t port = 0; port < hub_dev->port_count; ++port) {
     340                usb_log_debug("Powering port %zu.\n", port);
     341                const int ret = usb_hub_port_set_feature(
     342                    &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
     343
     344                if (ret != EOK) {
     345                        usb_log_error("Cannot power on port %zu: %s.\n",
     346                            hub_dev->ports[port].port_number, str_error(ret));
     347                } else {
     348                        if (!hub_dev->per_port_power) {
     349                                usb_log_debug("Ganged power switching, "
     350                                    "one port is enough.\n");
     351                                break;
    334352                        }
    335353                }
    336         } else {
    337                 usb_log_debug("Power not switched, ports always powered\n");
    338354        }
    339355        return EOK;
     
    402418                usb_log_warning("Detected hub over-current condition, "
    403419                    "all ports should be powered off.");
    404         } else {
    405                 /* Over-current condition is gone, it is safe to turn the
    406                  * ports on. */
    407                 for (size_t port = 0; port < hub_dev->port_count; ++port) {
    408                         const int opResult = usb_hub_port_set_feature(
    409                             &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
    410                         // TODO: consider power policy here
    411                         if (opResult != EOK) {
    412                                 usb_log_warning(
    413                                     "HUB OVER-CURRENT GONE: Cannot power on "
    414                                     "port %zu;  %s\n",
    415                                     port, str_error(opResult));
    416                         }
    417                 }
    418         }
    419         const int opResult = usb_request_clear_feature(
    420             &hub_dev->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS,
    421             USB_REQUEST_RECIPIENT_DEVICE,
    422             USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0);
    423         if (opResult != EOK) {
    424                 usb_log_error(
    425                     "Failed to clear hub over-current change flag: %s.\n",
    426                     str_error(opResult));
    427         }
     420                return;
     421        }
     422
     423        /* Ports are always powered. */
     424        if (!hub_dev->power_switched)
     425                return;
     426
     427        /* Over-current condition is gone, it is safe to turn the ports on. */
     428        for (size_t port = 0; port < hub_dev->port_count; ++port) {
     429                const int ret = usb_hub_port_set_feature(
     430                    &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
     431                if (ret != EOK) {
     432                        usb_log_warning("HUB OVER-CURRENT GONE: Cannot power on"
     433                            " port %zu: %s\n", hub_dev->ports[port].port_number,
     434                            str_error(ret));
     435                } else {
     436                        if (!hub_dev->per_port_power)
     437                                return;
     438                }
     439        }
     440
    428441}
    429442/*----------------------------------------------------------------------------*/
     
    461474        if (status & USB_HUB_STATUS_C_OVER_CURRENT) {
    462475                usb_hub_over_current(hub_dev, status);
     476                /* Ack change in hub OC flag */
     477                const int ret = usb_request_clear_feature(
     478                    &hub_dev->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS,
     479                    USB_REQUEST_RECIPIENT_DEVICE,
     480                    USB_HUB_FEATURE_C_HUB_OVER_CURRENT, 0);
     481                if (ret != EOK) {
     482                        usb_log_error("Failed to clear hub over-current "
     483                            "change flag: %s.\n", str_error(opResult));
     484                }
    463485        }
    464486
     
    477499                 * Just ACK the change.
    478500                 */
    479                 const int opResult = usb_request_clear_feature(
     501                const int ret = usb_request_clear_feature(
    480502                    control_pipe, USB_REQUEST_TYPE_CLASS,
    481503                    USB_REQUEST_RECIPIENT_DEVICE,
    482504                    USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0);
    483505                if (opResult != EOK) {
    484                         usb_log_error(
    485                             "Failed to clear hub power change flag: %s.\n",
    486                             str_error(opResult));
     506                        usb_log_error("Failed to clear hub power change "
     507                            "flag: %s.\n", str_error(ret));
    487508                }
    488509        }
  • uspace/drv/bus/usb/usbhub/usbhub.h

    r1737bfb r45bf63c  
    7777        /** Status indicator */
    7878        bool running;
     79        /** Hub supports port power switching. */
     80        bool power_switched;
     81        /** Each port is switched individually. */
     82        bool per_port_power;
    7983};
    8084
    8185int usb_hub_device_add(usb_device_t *usb_dev);
     86int usb_hub_device_remove(usb_device_t *usb_dev);
    8287int usb_hub_device_gone(usb_device_t *usb_dev);
    8388
  • uspace/drv/bus/usb/usbmast/main.c

    r1737bfb r45bf63c  
    5555#define GET_BULK_OUT(dev) ((dev)->pipes[BULK_OUT_EP].pipe)
    5656
    57 static usb_endpoint_description_t bulk_in_ep = {
     57static const usb_endpoint_description_t bulk_in_ep = {
    5858        .transfer_type = USB_TRANSFER_BULK,
    5959        .direction = USB_DIRECTION_IN,
     
    6363        .flags = 0
    6464};
    65 static usb_endpoint_description_t bulk_out_ep = {
     65static const usb_endpoint_description_t bulk_out_ep = {
    6666        .transfer_type = USB_TRANSFER_BULK,
    6767        .direction = USB_DIRECTION_OUT,
     
    106106}
    107107
     108/** Callback when a device is about to be removed.
     109 *
     110 * @param dev Representation of USB device.
     111 * @return Error code.
     112 */
     113static int usbmast_device_remove(usb_device_t *dev)
     114{
     115        //TODO: flush buffers, or whatever.
     116        return ENOTSUP;
     117}
     118
    108119/** Callback when new device is attached and recognized as a mass storage.
    109120 *
    110  * @param dev Representation of a the USB device.
     121 * @param dev Representation of USB device.
    111122 * @return Error code.
    112123 */
     
    336347
    337348/** USB mass storage driver ops. */
    338 static usb_driver_ops_t usbmast_driver_ops = {
     349static const usb_driver_ops_t usbmast_driver_ops = {
    339350        .device_add = usbmast_device_add,
     351        .device_rem = usbmast_device_remove,
    340352        .device_gone = usbmast_device_gone,
    341353};
    342354
    343355/** USB mass storage driver. */
    344 static usb_driver_t usbmast_driver = {
     356static const usb_driver_t usbmast_driver = {
    345357        .name = NAME,
    346358        .ops = &usbmast_driver_ops,
  • uspace/drv/bus/usb/usbmid/main.c

    r1737bfb r45bf63c  
    6565        return EOK;
    6666}
     67/*----------------------------------------------------------------------------*/
     68/** Callback when a MID device is about to be removed from the host.
     69 *
     70 * @param gen_dev Generic DDF device representing the removed device.
     71 * @return Error code.
     72 */
     73static int usbmid_device_remove(usb_device_t *dev)
     74{
     75        assert(dev);
     76        int ret = ENOTSUP;
     77        usb_mid_t *usb_mid = dev->driver_data;
     78        assert(usb_mid);
    6779
     80        /* Signal all interface functions */
     81        list_foreach(usb_mid->interface_list, item) {
     82                usbmid_interface_t *iface = usbmid_interface_from_link(item);
     83
     84                usb_log_info("Signaling remove to child for interface "
     85                    "%d (%s).\n", iface->interface_no,
     86                    usb_str_class(iface->interface->interface_class));
     87                // TODO cascade the call.
     88        }
     89        return ret;
     90}
     91/*----------------------------------------------------------------------------*/
     92/** Callback when a MID device was removed from the host.
     93 *
     94 * @param gen_dev Generic DDF device representing the removed device.
     95 * @return Error code.
     96 */
    6897static int usbmid_device_gone(usb_device_t *dev)
    6998{
     
    86115                list_remove(item);
    87116
    88                 usbmid_interface_t *iface = list_get_instance(item,
    89                     usbmid_interface_t, link);
     117                usbmid_interface_t *iface = usbmid_interface_from_link(item);
    90118
    91119                usb_log_info("Removing child for interface %d (%s).\n",
     
    107135
    108136/** USB MID driver ops. */
    109 static usb_driver_ops_t mid_driver_ops = {
     137static const usb_driver_ops_t mid_driver_ops = {
    110138        .device_add = usbmid_device_add,
     139        .device_rem = usbmid_device_remove,
    111140        .device_gone = usbmid_device_gone,
    112141};
    113142
    114143/** USB MID driver. */
    115 static usb_driver_t mid_driver = {
     144static const usb_driver_t mid_driver = {
    116145        .name = NAME,
    117146        .ops = &mid_driver_ops,
  • uspace/drv/bus/usb/usbmid/usbmid.h

    r1737bfb r45bf63c  
    7171int usbmid_interface_destroy(usbmid_interface_t *mid_iface);
    7272
     73static inline usbmid_interface_t * usbmid_interface_from_link(link_t *item)
     74{
     75        return list_get_instance(item, usbmid_interface_t, link);
     76}
     77
    7378#endif
    7479/**
  • uspace/drv/bus/usb/vhc/connhost.c

    r1737bfb r45bf63c  
    104104{
    105105        VHC_DATA(vhc, fun);
    106         bool found =
    107             usb_device_manager_find_by_address(&vhc->dev_manager, address, handle);
    108         return found ? EOK : ENOENT;
     106        return usb_device_manager_get_info_by_address(
     107            &vhc->dev_manager, address, handle, NULL);
    109108}
    110109
     
    141140    size_t max_packet_size, unsigned int interval)
    142141{
    143         /* TODO: Use usb_endpoint_manager_add_ep */
    144         VHC_DATA(vhc, fun);
    145 
    146         endpoint_t *ep = endpoint_get(
    147             address, endpoint, direction, transfer_type, USB_SPEED_FULL, 1);
    148         if (ep == NULL) {
    149                 return ENOMEM;
    150         }
    151 
    152         int rc = usb_endpoint_manager_register_ep(&vhc->ep_manager, ep, 1);
    153         if (rc != EOK) {
    154                 endpoint_destroy(ep);
    155                 return rc;
    156         }
    157 
    158         return EOK;
     142        VHC_DATA(vhc, fun);
     143
     144        return usb_endpoint_manager_add_ep(&vhc->ep_manager,
     145            address, endpoint, direction, transfer_type, USB_SPEED_FULL, 1, 0,
     146            NULL, NULL);
     147
    159148}
    160149
     
    172161        VHC_DATA(vhc, fun);
    173162
    174         int rc = usb_endpoint_manager_unregister_ep(&vhc->ep_manager,
    175             address, endpoint, direction);
     163        int rc = usb_endpoint_manager_remove_ep(&vhc->ep_manager,
     164            address, endpoint, direction, NULL, NULL);
    176165
    177166        return rc;
     
    414403        VHC_DATA(vhc, fun);
    415404
    416         endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,
    417             target.address, target.endpoint, USB_DIRECTION_IN, NULL);
     405        endpoint_t *ep = usb_endpoint_manager_find_ep(&vhc->ep_manager,
     406            target.address, target.endpoint, USB_DIRECTION_IN);
    418407        if (ep == NULL) {
    419408                return ENOENT;
     
    456445        VHC_DATA(vhc, fun);
    457446
    458         endpoint_t *ep = usb_endpoint_manager_get_ep(&vhc->ep_manager,
    459             target.address, target.endpoint, USB_DIRECTION_OUT, NULL);
     447        endpoint_t *ep = usb_endpoint_manager_find_ep(&vhc->ep_manager,
     448            target.address, target.endpoint, USB_DIRECTION_OUT);
    460449        if (ep == NULL) {
    461450                return ENOENT;
     
    518507
    519508        usb_log_debug("tell_address_rh(handle=%" PRIun ")\n", handle);
    520         usb_address_t addr = usb_device_manager_find(&vhc->dev_manager, handle);
     509        const usb_address_t addr =
     510            usb_device_manager_find_address(&vhc->dev_manager, handle);
    521511        if (addr < 0) {
    522512                return addr;
Note: See TracChangeset for help on using the changeset viewer.