Changeset d083126 in mainline


Ignore:
Timestamp:
2011-10-13T13:20:26Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
3a5506a
Parents:
cff3fb6 (diff), 22a2b763 (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 initial USB unplug support.

Support device_remove and device_gone in libusbdev.
usbhub and uhcirh try to unbind and destroy functions of attached devices.
add unplug support for usbhub driver (only works on empty hubs as there is no support in other drivers).

Drivers to go:

usbmid
usbflbk
usbhid
usbmast
usbmouse

Tested on:

qemu UHCI and emulated hub,
ICH8 hw and Alcor Micro Corp. USB Hub

Location:
uspace
Files:
33 edited

Legend:

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

    rcff3fb6 rd083126  
    571571        usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
    572572
    573         unsigned i = 0;
    574         for (; i < 32; ++i) {
     573        for (unsigned i = 0; i < 32; ++i) {
    575574                instance->hcca->int_ep[i] =
    576575                    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
  • uspace/drv/bus/usb/ohci/ohci_batch.c

    rcff3fb6 rd083126  
    5252        if (!ohci_batch)
    5353                return;
    54         unsigned i = 0;
    5554        if (ohci_batch->tds) {
    56                 for (; i< ohci_batch->td_count; ++i) {
     55                for (unsigned i = 0; i < ohci_batch->td_count; ++i) {
    5756                        if (i != ohci_batch->leave_td)
    5857                                free32(ohci_batch->tds[i]);
     
    107106        ohci_batch->tds[0] = ohci_endpoint_get(usb_batch->ep)->td;
    108107        ohci_batch->leave_td = 0;
    109         unsigned i = 1;
    110         for (; i <= ohci_batch->td_count; ++i) {
     108
     109        for (unsigned i = 1; i <= ohci_batch->td_count; ++i) {
    111110                ohci_batch->tds[i] = malloc32(sizeof(td_t));
    112111                CHECK_NULL_DISPOSE_RET(ohci_batch->tds[i],
     
    160159        usb_log_debug("Batch %p checking %zu td(s) for completion.\n",
    161160            ohci_batch->usb_batch, ohci_batch->td_count);
    162         usb_log_debug2("ED: %x:%x:%x:%x.\n",
     161        usb_log_debug2("ED: %08x:%08x:%08x:%08x.\n",
    163162            ohci_batch->ed->status, ohci_batch->ed->td_head,
    164163            ohci_batch->ed->td_tail, ohci_batch->ed->next);
     
    167166        for (; i < ohci_batch->td_count; ++i) {
    168167                assert(ohci_batch->tds[i] != NULL);
    169                 usb_log_debug("TD %zu: %x:%x:%x:%x.\n", i,
     168                usb_log_debug("TD %zu: %08x:%08x:%08x:%08x.\n", i,
    170169                    ohci_batch->tds[i]->status, ohci_batch->tds[i]->cbp,
    171170                    ohci_batch->tds[i]->next, ohci_batch->tds[i]->be);
     
    175174                ohci_batch->usb_batch->error = td_error(ohci_batch->tds[i]);
    176175                if (ohci_batch->usb_batch->error != EOK) {
    177                         usb_log_debug("Batch %p found error TD(%zu):%x.\n",
     176                        usb_log_debug("Batch %p found error TD(%zu):%08x.\n",
    178177                            ohci_batch->usb_batch, i,
    179178                            ohci_batch->tds[i]->status);
     
    196195        ohci_batch->usb_batch->transfered_size =
    197196            ohci_batch->usb_batch->buffer_size;
    198         for (--i;i < ohci_batch->td_count; ++i)
     197        for (--i;i < ohci_batch->td_count; ++i) {
    199198                ohci_batch->usb_batch->transfered_size
    200199                    -= td_remain_size(ohci_batch->tds[i]);
     200        }
    201201
    202202        /* Clear possible ED HALT */
     
    234234        assert(ohci_batch->usb_batch);
    235235        assert(dir == USB_DIRECTION_IN || dir == USB_DIRECTION_OUT);
    236         usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", ohci_batch->ed,
     236        usb_log_debug("Using ED(%p): %08x:%08x:%08x:%08x.\n", ohci_batch->ed,
    237237            ohci_batch->ed->status, ohci_batch->ed->td_tail,
    238238            ohci_batch->ed->td_head, ohci_batch->ed->next);
     
    251251                ohci_batch->usb_batch->setup_size, toggle);
    252252        td_set_next(ohci_batch->tds[0], ohci_batch->tds[1]);
    253         usb_log_debug("Created CONTROL SETUP TD: %x:%x:%x:%x.\n",
     253        usb_log_debug("Created CONTROL SETUP TD: %08x:%08x:%08x:%08x.\n",
    254254            ohci_batch->tds[0]->status, ohci_batch->tds[0]->cbp,
    255255            ohci_batch->tds[0]->next, ohci_batch->tds[0]->be);
     
    269269                td_set_next(ohci_batch->tds[td_current],
    270270                    ohci_batch->tds[td_current + 1]);
    271                 usb_log_debug("Created CONTROL DATA TD: %x:%x:%x:%x.\n",
     271                usb_log_debug("Created CONTROL DATA TD: %08x:%08x:%08x:%08x.\n",
    272272                    ohci_batch->tds[td_current]->status,
    273273                    ohci_batch->tds[td_current]->cbp,
     
    286286        td_set_next(ohci_batch->tds[td_current],
    287287            ohci_batch->tds[td_current + 1]);
    288         usb_log_debug("Created CONTROL STATUS TD: %x:%x:%x:%x.\n",
     288        usb_log_debug("Created CONTROL STATUS TD: %08x:%08x:%08x:%08x.\n",
    289289            ohci_batch->tds[td_current]->status,
    290290            ohci_batch->tds[td_current]->cbp,
     
    312312        assert(ohci_batch->usb_batch);
    313313        assert(dir == USB_DIRECTION_IN || dir == USB_DIRECTION_OUT);
    314         usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", ohci_batch->ed,
     314        usb_log_debug("Using ED(%p): %08x:%08x:%08x:%08x.\n", ohci_batch->ed,
    315315            ohci_batch->ed->status, ohci_batch->ed->td_tail,
    316316            ohci_batch->ed->td_head, ohci_batch->ed->next);
     
    328328                    ohci_batch->tds[td_current + 1]);
    329329
    330                 usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
     330                usb_log_debug("Created DATA TD: %08x:%08x:%08x:%08x.\n",
    331331                    ohci_batch->tds[td_current]->status,
    332332                    ohci_batch->tds[td_current]->cbp,
  • uspace/drv/bus/usb/ohci/pci.c

    rcff3fb6 rd083126  
    8585        bool irq_found = false;
    8686
    87         size_t i;
    88         for (i = 0; i < hw_resources.count; i++) {
     87        for (size_t i = 0; i < hw_resources.count; i++) {
    8988                hw_resource_t *res = &hw_resources.resources[i];
    9089                switch (res->type) {
  • uspace/drv/bus/usb/ohci/root_hub.c

    rcff3fb6 rd083126  
    351351                mask |= 1;
    352352        }
    353         size_t port = 1;
    354         for (; port <= instance->port_count; ++port) {
     353        for (size_t port = 1; port <= instance->port_count; ++port) {
    355354                /* Write-clean bits are those that indicate change */
    356355                if (RHPS_CHANGE_WC_MASK
  • uspace/drv/bus/usb/ohci/utils/malloc32.h

    rcff3fb6 rd083126  
    6969 */
    7070static inline void free32(void *addr)
    71         { if (addr) free(addr); }
     71        { free(addr); }
    7272#endif
    7373/**
  • uspace/drv/bus/usb/uhci/hc.c

    rcff3fb6 rd083126  
    299299        const uint32_t queue = LINK_POINTER_QH(
    300300                addr_to_phys(instance->transfers_interrupt.queue_head));
    301         unsigned i = 0;
    302         for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
     301
     302        for (unsigned i = 0; i < UHCI_FRAME_LIST_COUNT; ++i) {
    303303                instance->frame_list[i] = queue;
    304304        }
  • uspace/drv/bus/usb/uhci/pci.c

    rcff3fb6 rd083126  
    8282        bool irq_found = false;
    8383
    84         size_t i;
    85         for (i = 0; i < hw_resources.count; i++) {
     84        for (size_t i = 0; i < hw_resources.count; i++) {
    8685                const hw_resource_t *res = &hw_resources.resources[i];
    8786                switch (res->type) {
  • uspace/drv/bus/usb/uhci/uhci_batch.c

    rcff3fb6 rd083126  
    167167            uhci_batch->td_count);
    168168        uhci_batch->usb_batch->transfered_size = 0;
    169         size_t i = 0;
    170         for (;i < uhci_batch->td_count; ++i) {
     169
     170        for (size_t i = 0;i < uhci_batch->td_count; ++i) {
    171171                if (td_is_active(&uhci_batch->tds[i])) {
    172172                        return false;
  • uspace/drv/bus/usb/uhci/utils/malloc32.h

    rcff3fb6 rd083126  
    6262}
    6363/*----------------------------------------------------------------------------*/
    64 /** Physical mallocator simulator
     64/** DMA malloc simulator
    6565 *
    6666 * @param[in] size Size of the required memory space
    67  * @return Address of the alligned and big enough memory place, NULL on failure.
     67 * @return Address of the aligned and big enough memory place, NULL on failure.
    6868 */
    69 static inline void * malloc32(size_t size) {
     69static inline void * malloc32(size_t size)
     70{
    7071        /* This works only when the host has less than 4GB of memory as
    7172         * physical address needs to fit into 32 bits */
     
    8384}
    8485/*----------------------------------------------------------------------------*/
    85 /** Physical mallocator simulator
     86/** DMA malloc simulator
    8687 *
    8788 * @param[in] addr Address of the place allocated by malloc32
    8889 */
    89 static inline void free32(void *addr) {
    90         if (!addr)
    91                 return;
    92         free(addr);
    93 }
     90static inline void free32(void *addr)
     91        { free(addr); }
    9492/*----------------------------------------------------------------------------*/
    9593/** Create 4KB page mapping
  • uspace/drv/bus/usb/uhcirh/port.c

    rcff3fb6 rd083126  
    3737#include <str_error.h>
    3838#include <async.h>
     39#include <devman.h>
    3940
    4041#include <usb/usb.h>    /* usb_address_t */
    41 #include <usb/dev/hub.h>    /* usb_hc_new_device_wrapper */
    4242#include <usb/debug.h>
    4343
    4444#include "port.h"
    4545
     46#define MAX_ERROR_COUNT 5
     47
    4648static int uhci_port_check(void *port);
    47 static int uhci_port_reset_enable(int portno, void *arg);
     49static int uhci_port_reset_enable(void *arg);
    4850static int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed);
    4951static int uhci_port_remove_device(uhci_port_t *port);
     
    100102        port->number = number;
    101103        port->wait_period_usec = usec;
    102         port->attached_device = 0;
     104        port->attached_device.fun = NULL;
     105        port->attached_device.address = -1;
    103106        port->rh = rh;
    104107
     
    150153        assert(instance);
    151154
     155        unsigned allowed_failures = MAX_ERROR_COUNT;
     156#define CHECK_RET_FAIL(ret, msg...) \
     157        if (ret != EOK) { \
     158                usb_log_error(msg); \
     159                if (!(allowed_failures-- > 0)) { \
     160                        usb_log_fatal( \
     161                           "Maximum number of failures reached, " \
     162                           "bailing out.\n"); \
     163                        return ret; \
     164                } \
     165                continue; \
     166        } else (void)0
     167
    152168        while (1) {
    153169                async_usleep(instance->wait_period_usec);
     
    167183                    instance->id_string, port_status);
    168184
     185                int ret = usb_hc_connection_open(&instance->hc_connection);
     186                CHECK_RET_FAIL(ret, "%s: Failed to connect to HC %s.\n",
     187                    instance->id_string, str_error(ret));
     188
    169189                /* Remove any old device */
    170                 if (instance->attached_device) {
    171                         usb_log_debug2("%s: Removing device.\n",
    172                             instance->id_string);
     190                if (instance->attached_device.fun) {
    173191                        uhci_port_remove_device(instance);
    174192                }
    175193
    176                 int ret =
    177                     usb_hc_connection_open(&instance->hc_connection);
    178                 if (ret != EOK) {
    179                         usb_log_error("%s: Failed to connect to HC.",
    180                             instance->id_string);
    181                         continue;
    182                 }
    183 
    184194                if ((port_status & STATUS_CONNECTED) != 0) {
    185                         /* New device */
     195                        /* New device, this will take care of WC bits */
    186196                        const usb_speed_t speed =
    187197                            ((port_status & STATUS_LOW_SPEED) != 0) ?
     
    196206
    197207                ret = usb_hc_connection_close(&instance->hc_connection);
    198                 if (ret != EOK) {
    199                         usb_log_error("%s: Failed to disconnect.",
    200                             instance->id_string);
    201                 }
     208                CHECK_RET_FAIL(ret, "%s: Failed to disconnect from hc: %s.\n",
     209                    instance->id_string, str_error(ret));
    202210        }
    203211        return EOK;
     
    212220 * Resets and enables the ub port.
    213221 */
    214 int uhci_port_reset_enable(int portno, void *arg)
     222int uhci_port_reset_enable(void *arg)
    215223{
    216224        uhci_port_t *port = arg;
     
    256264        usb_log_debug("%s: Detected new device.\n", port->id_string);
    257265
    258         int ret, count = 0;
    259         usb_address_t dev_addr;
     266        int ret, count = MAX_ERROR_COUNT;
    260267        do {
    261268                ret = usb_hc_new_device_wrapper(port->rh, &port->hc_connection,
    262                     speed, uhci_port_reset_enable, port->number, port,
    263                     &dev_addr, &port->attached_device, NULL, NULL, NULL);
    264         } while (ret != EOK && ++count < 4);
     269                    speed, uhci_port_reset_enable, port,
     270                    &port->attached_device.address, NULL, NULL,
     271                    &port->attached_device.fun);
     272        } while (ret != EOK && count-- > 0);
    265273
    266274        if (ret != EOK) {
     
    271279        }
    272280
    273         usb_log_info("New device at port %u, address %d (handle %" PRIun ").\n",
    274             port->number, dev_addr, port->attached_device);
     281        usb_log_info("%s: New device, address %d (handle %" PRIun ").\n",
     282            port->id_string, port->attached_device.address,
     283            port->attached_device.fun->handle);
    275284        return EOK;
    276285}
     
    278287/** Remove device.
    279288 *
    280  * @param[in] port Memory structure to use.
    281  * @return Error code.
    282  *
    283  * Does not work, DDF does not support device removal.
    284  * Does not even free used USB address (it would be dangerous if tis driver
    285  * is still running).
     289 * @param[in] port Port instance to use.
     290 * @return Error code.
    286291 */
    287292int uhci_port_remove_device(uhci_port_t *port)
    288293{
    289         usb_log_error("%s: Don't know how to remove device %" PRIun ".\n",
    290             port->id_string, port->attached_device);
    291         port->attached_device = 0;
    292         return ENOTSUP;
     294        assert(port);
     295        /* There is nothing to remove. */
     296        if (port->attached_device.fun == NULL) {
     297                usb_log_warning("%s: Removed a ghost device.\n",
     298                    port->id_string);
     299                assert(port->attached_device.address == -1);
     300                return EOK;
     301        }
     302
     303        usb_log_debug("%s: Removing device.\n", port->id_string);
     304
     305        /* Stop driver first */
     306        int ret = ddf_fun_unbind(port->attached_device.fun);
     307        if (ret != EOK) {
     308                usb_log_error("%s: Failed to remove child function: %s.\n",
     309                   port->id_string, str_error(ret));
     310                return ret;
     311        }
     312        ddf_fun_destroy(port->attached_device.fun);
     313        port->attached_device.fun = NULL;
     314
     315        /* Driver stopped, free used address */
     316        ret = usb_hc_unregister_device(&port->hc_connection,
     317            port->attached_device.address);
     318        if (ret != EOK) {
     319                usb_log_error("%s: Failed to unregister address of removed "
     320                    "device: %s.\n", port->id_string, str_error(ret));
     321                return ret;
     322        }
     323        port->attached_device.address = -1;
     324
     325        usb_log_info("%s: Removed attached device.\n", port->id_string);
     326        return EOK;
    293327}
    294328/*----------------------------------------------------------------------------*/
  • uspace/drv/bus/usb/uhcirh/port.h

    rcff3fb6 rd083126  
    3939#include <ddf/driver.h>
    4040#include <usb/hc.h> /* usb_hc_connection_t */
     41#include <usb/dev/hub.h>
    4142
    4243typedef uint16_t port_status_t;
     
    6263        usb_hc_connection_t hc_connection;
    6364        ddf_dev_t *rh;
    64         devman_handle_t attached_device;
     65        usb_hub_attached_device_t attached_device;
    6566        fid_t checker;
    6667} uhci_port_t;
  • uspace/drv/bus/usb/usbflbk/main.c

    rcff3fb6 rd083126  
    4646 * @return Error code.
    4747 */
    48 static int usbfallback_add_device(usb_device_t *dev)
     48static int usbfallback_device_add(usb_device_t *dev)
    4949{
    5050        int rc;
     
    7474/** USB fallback driver ops. */
    7575static usb_driver_ops_t usbfallback_driver_ops = {
    76         .add_device = usbfallback_add_device,
     76        .device_add = usbfallback_device_add,
    7777};
    7878
  • uspace/drv/bus/usb/usbhid/main.c

    rcff3fb6 rd083126  
    150150 * @retval EREFUSED if the device is not supported.
    151151 */
    152 static int usb_hid_add_device(usb_device_t *dev)
     152static int usb_hid_device_add(usb_device_t *dev)
    153153{
    154         usb_log_debug("usb_hid_add_device()\n");
     154        usb_log_debug("usb_hid_device_add()\n");
    155155       
    156156        if (dev == NULL) {
     
    185185 * supports unplug, more callbacks will be added. */
    186186static usb_driver_ops_t usb_hid_driver_ops = {
    187         .add_device = usb_hid_add_device,
     187        .device_add = usb_hid_device_add,
    188188};
    189189
  • uspace/drv/bus/usb/usbhub/main.c

    rcff3fb6 rd083126  
    5959 * USB hub driver operations
    6060 *
    61  * The most important one is add_device, which is set to usb_hub_add_device.
     61 * The most important one is device_add, which is set to usb_hub_device_add.
    6262 */
    6363static usb_driver_ops_t usb_hub_driver_ops = {
    64         .add_device = usb_hub_add_device
     64        .device_add = usb_hub_device_add,
     65        .device_gone = usb_hub_device_gone,
    6566};
    6667
  • uspace/drv/bus/usb/usbhub/port.c

    rcff3fb6 rd083126  
    5050/** Information for fibril for device discovery. */
    5151struct add_device_phase1 {
    52         usb_hub_info_t *hub;
     52        usb_hub_dev_t *hub;
    5353        usb_hub_port_t *port;
    5454        usb_speed_t speed;
    5555};
    5656
    57 static void usb_hub_port_removed_device(usb_hub_port_t *port,
    58     usb_hub_info_t *hub);
     57static int usb_hub_port_device_gone(usb_hub_port_t *port, usb_hub_dev_t *hub);
    5958static void usb_hub_port_reset_completed(usb_hub_port_t *port,
    6059    usb_port_status_t status);
    6160static int get_port_status(usb_hub_port_t *port, usb_port_status_t *status);
    62 static int enable_port_callback(int port_no, void *arg);
     61static int enable_port_callback(void *arg);
    6362static int add_device_phase1_worker_fibril(void *arg);
    64 static int create_add_device_fibril(usb_hub_port_t *port, usb_hub_info_t *hub,
     63static int create_add_device_fibril(usb_hub_port_t *port, usb_hub_dev_t *hub,
    6564    usb_speed_t speed);
    6665
     66int usb_hub_port_fini(usb_hub_port_t *port, usb_hub_dev_t *hub)
     67{
     68        assert(port);
     69        if (port->attached_device.fun)
     70                return usb_hub_port_device_gone(port, hub);
     71        return EOK;
     72}
     73/*----------------------------------------------------------------------------*/
    6774/**
    6875 * Clear feature on hub port.
    6976 *
    70  * @param hc Host controller telephone
    71  * @param address Hub address
    72  * @param port_index Port
    73  * @param feature Feature selector
     77 * @param port Port structure.
     78 * @param feature Feature selector.
    7479 * @return Operation result
    7580 */
     
    7883{
    7984        assert(port);
    80         usb_device_request_setup_packet_t clear_request = {
     85        const usb_device_request_setup_packet_t clear_request = {
    8186                .request_type = USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE,
    8287                .request = USB_DEVREQ_CLEAR_FEATURE,
     
    9095/*----------------------------------------------------------------------------*/
    9196/**
    92  * Clear feature on hub port.
    93  *
    94  * @param hc Host controller telephone
    95  * @param address Hub address
    96  * @param port_index Port
    97  * @param feature Feature selector
     97 * Set feature on hub port.
     98 *
     99 * @param port Port structure.
     100 * @param feature Feature selector.
    98101 * @return Operation result
    99102 */
     
    102105{
    103106        assert(port);
    104         usb_device_request_setup_packet_t clear_request = {
     107        const usb_device_request_setup_packet_t clear_request = {
    105108                .request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE,
    106109                .request = USB_DEVREQ_SET_FEATURE,
     
    113116}
    114117/*----------------------------------------------------------------------------*/
     118/**
     119 * Mark reset process as failed due to external reasons
     120 *
     121 * @param port Port structure
     122 */
    115123void usb_hub_port_reset_fail(usb_hub_port_t *port)
    116124{
     
    124132/*----------------------------------------------------------------------------*/
    125133/**
    126  * Process interrupts on given hub port
     134 * Process interrupts on given port
    127135 *
    128136 * Accepts connection, over current and port reset change.
     137 * @param port port structure
    129138 * @param hub hub representation
    130  * @param port port number, starting from 1
    131  */
    132 void usb_hub_port_process_interrupt(usb_hub_port_t *port, usb_hub_info_t *hub)
     139 */
     140void usb_hub_port_process_interrupt(usb_hub_port_t *port, usb_hub_dev_t *hub)
    133141{
    134142        assert(port);
     
    171179                         * to that handler, it shall ACK the change too. */
    172180                        if (!(status & USB_HUB_PORT_C_STATUS_ENABLED)) {
    173                                 usb_hub_port_removed_device(port, hub);
     181                                usb_hub_port_device_gone(port, hub);
    174182                        }
    175183                }
     
    180188                usb_log_info("Port %zu, disabled because of errors.\n",
    181189                   port->port_number);
    182                 usb_hub_port_removed_device(port, hub);
     190                usb_hub_port_device_gone(port, hub);
    183191                const int rc = usb_hub_port_clear_feature(port,
    184192                        USB_HUB_FEATURE_C_PORT_ENABLE);
     
    238246            port->port_number, status);
    239247}
    240 
     248/*----------------------------------------------------------------------------*/
    241249/**
    242250 * routine called when a device on port has been removed
     
    245253 * Otherwise does not do anything, because DDF does not allow to remove device
    246254 * from it`s device tree.
     255 * @param port port structure
    247256 * @param hub hub representation
    248  * @param port port number, starting from 1
    249  */
    250 static void usb_hub_port_removed_device(usb_hub_port_t *port,
    251     usb_hub_info_t *hub)
     257 */
     258int usb_hub_port_device_gone(usb_hub_port_t *port, usb_hub_dev_t *hub)
    252259{
    253260        assert(port);
    254261        assert(hub);
    255         if (port->attached_device.address >= 0) {
    256                 fibril_mutex_lock(&port->mutex);
    257                 port->attached_device.address = -1;
    258                 port->attached_device.handle = 0;
    259                 fibril_mutex_unlock(&port->mutex);
    260                 usb_log_info("Removed device on port %zu.\n",
    261                     port->port_number);
    262         } else {
     262        if (port->attached_device.address < 0) {
    263263                usb_log_warning(
    264264                    "Device on port %zu removed before being registered.\n",
     
    271271                 */
    272272                usb_hub_port_reset_fail(port);
    273         }
    274 }
    275 
     273                return EOK;
     274        }
     275
     276        fibril_mutex_lock(&port->mutex);
     277        assert(port->attached_device.fun);
     278        usb_log_debug("Removing device on port %zu.\n", port->port_number);
     279        int ret = ddf_fun_unbind(port->attached_device.fun);
     280        if (ret != EOK) {
     281                usb_log_error("Failed to unbind child function on port"
     282                    " %zu: %s.\n", port->port_number, str_error(ret));
     283                fibril_mutex_unlock(&port->mutex);
     284                return ret;
     285        }
     286
     287        ddf_fun_destroy(port->attached_device.fun);
     288        port->attached_device.fun = NULL;
     289
     290        ret = usb_hc_unregister_device(&hub->connection,
     291            port->attached_device.address);
     292        if (ret != EOK) {
     293                usb_log_warning("Failed to unregister address of the removed "
     294                    "device: %s.\n", str_error(ret));
     295        }
     296        port->attached_device.address = -1;
     297        fibril_mutex_unlock(&port->mutex);
     298        usb_log_info("Removed device on port %zu.\n", port->port_number);
     299        return EOK;
     300}
     301/*----------------------------------------------------------------------------*/
    276302/**
    277303 * Process port reset change
     
    279305 * After this change port should be enabled, unless some problem occurred.
    280306 * This functions triggers second phase of enabling new device.
    281  * @param hub
    282  * @param port
    283  * @param status
    284  */
    285 static void usb_hub_port_reset_completed(usb_hub_port_t *port,
     307 * @param port Port structure
     308 * @param status Port status mask
     309 */
     310void usb_hub_port_reset_completed(usb_hub_port_t *port,
    286311    usb_port_status_t status)
    287312{
     
    313338/** Retrieve port status.
    314339 *
    315  * @param[in] ctrl_pipe Control pipe to use.
    316  * @param[in] port Port number (starting at 1).
     340 * @param[in] port Port structure
    317341 * @param[out] status Where to store the port status.
    318342 * @return Error code.
     
    358382 *
    359383 * @param port_no Port number (starting at 1).
    360  * @param arg Custom argument, points to @c usb_hub_info_t.
     384 * @param arg Custom argument, points to @c usb_hub_dev_t.
    361385 * @return Error code.
    362386 */
    363 static int enable_port_callback(int port_no, void *arg)
     387static int enable_port_callback(void *arg)
    364388{
    365389        usb_hub_port_t *port = arg;
     
    380404        fibril_mutex_unlock(&port->mutex);
    381405
    382         if (port->reset_okay) {
    383                 return EOK;
    384         } else {
    385                 return ESTALL;
    386         }
    387 }
    388 
     406        return port->reset_okay ? EOK : ESTALL;
     407}
     408/*----------------------------------------------------------------------------*/
    389409/** Fibril for adding a new device.
    390410 *
     
    395415 * @return 0 Always.
    396416 */
    397 static int add_device_phase1_worker_fibril(void *arg)
     417int add_device_phase1_worker_fibril(void *arg)
    398418{
    399419        struct add_device_phase1 *data = arg;
     
    401421
    402422        usb_address_t new_address;
    403         devman_handle_t child_handle;
     423        ddf_fun_t *child_fun;
    404424
    405425        const int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev,
    406             &data->hub->connection, data->speed,
    407             enable_port_callback, (int) data->port->port_number,
    408             data->port, &new_address, &child_handle,
    409             NULL, NULL, NULL);
     426            &data->hub->connection, data->speed, enable_port_callback,
     427            data->port, &new_address, NULL, NULL, &child_fun);
    410428
    411429        if (rc != EOK) {
     
    416434
    417435        fibril_mutex_lock(&data->port->mutex);
    418         data->port->attached_device.handle = child_handle;
     436        data->port->attached_device.fun = child_fun;
    419437        data->port->attached_device.address = new_address;
    420438        fibril_mutex_unlock(&data->port->mutex);
     
    423441            "address %d (handle %" PRIun ").\n",
    424442            data->hub->usb_device->ddf_dev->name, data->port->port_number,
    425             new_address, child_handle);
     443            new_address, child_fun->handle);
    426444
    427445leave:
     
    434452        free(arg);
    435453
    436         return EOK;
    437 }
    438 
     454        return rc;
     455}
     456/*----------------------------------------------------------------------------*/
    439457/** Start device adding when connection change is detected.
    440458 *
     
    446464 * @return Error code.
    447465 */
    448 static int create_add_device_fibril(usb_hub_port_t *port, usb_hub_info_t *hub,
     466static int create_add_device_fibril(usb_hub_port_t *port, usb_hub_dev_t *hub,
    449467    usb_speed_t speed)
    450468{
     
    452470        assert(port);
    453471        struct add_device_phase1 *data
    454             = malloc(sizeof (struct add_device_phase1));
     472            = malloc(sizeof(struct add_device_phase1));
    455473        if (data == NULL) {
    456474                return ENOMEM;
  • uspace/drv/bus/usb/usbhub/port.h

    rcff3fb6 rd083126  
    4040#include <usb/classes/hub.h>
    4141
    42 typedef struct usb_hub_info_t usb_hub_info_t;
     42typedef struct usb_hub_dev usb_hub_dev_t;
    4343
    4444/** Information about single port on a hub. */
     
    5858
    5959        /** Information about attached device. */
    60         usb_hc_attached_device_t attached_device;
     60        usb_hub_attached_device_t attached_device;
    6161} usb_hub_port_t;
    6262
     
    7070        assert(port);
    7171        port->attached_device.address = -1;
    72         port->attached_device.handle = 0;
     72        port->attached_device.fun = NULL;
    7373        port->port_number = port_number;
    7474        port->control_pipe = control_pipe;
     
    7676        fibril_condvar_initialize(&port->reset_cv);
    7777}
    78 
    79 void usb_hub_port_reset_fail(usb_hub_port_t *port);
    80 void usb_hub_port_process_interrupt(usb_hub_port_t *port, usb_hub_info_t *hub);
     78int usb_hub_port_fini(usb_hub_port_t *port, usb_hub_dev_t *hub);
    8179int usb_hub_port_clear_feature(
    8280    usb_hub_port_t *port, usb_hub_class_feature_t feature);
    8381int usb_hub_port_set_feature(
    8482    usb_hub_port_t *port, usb_hub_class_feature_t feature);
     83void usb_hub_port_reset_fail(usb_hub_port_t *port);
     84void usb_hub_port_process_interrupt(usb_hub_port_t *port, usb_hub_dev_t *hub);
    8585
    8686#endif
  • uspace/drv/bus/usb/usbhub/usbhub.c

    rcff3fb6 rd083126  
    6868
    6969static int usb_set_first_configuration(usb_device_t *usb_device);
    70 static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev);
    71 static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info);
    72 static void usb_hub_over_current(const usb_hub_info_t *hub_info,
     70static usb_hub_dev_t * usb_hub_dev_create(usb_device_t *usb_dev);
     71static int usb_hub_process_hub_specific_info(usb_hub_dev_t *hub_dev);
     72static void usb_hub_over_current(const usb_hub_dev_t *hub_dev,
    7373    usb_hub_status_t status);
    74 static void usb_hub_global_interrupt(const usb_hub_info_t *hub_info);
     74static void usb_hub_global_interrupt(const usb_hub_dev_t *hub_dev);
    7575static void usb_hub_polling_terminated_callback(usb_device_t *device,
    7676    bool was_error, void *data);
    77 
    7877/**
    7978 * Initialize hub device driver fibril
     
    8483 * @return error code
    8584 */
    86 int usb_hub_add_device(usb_device_t *usb_dev)
     85int usb_hub_device_gone(usb_device_t *usb_dev)
     86{
     87        assert(usb_dev);
     88        usb_hub_dev_t *hub = usb_dev->driver_data;
     89        assert(hub);
     90        unsigned tries = 10;
     91        while (hub->running) {
     92                async_usleep(100000);
     93                if (!tries--) {
     94                        usb_log_error("Can't remove hub, still running.\n");
     95                        return EINPROGRESS;
     96                }
     97        }
     98
     99        assert(!hub->running);
     100
     101        for (size_t port = 0; port < hub->port_count; ++port) {
     102                if (hub->ports[port].attached_device.fun) {
     103                        const int ret =
     104                            usb_hub_port_fini(&hub->ports[port], hub);
     105                        if (ret != EOK)
     106                                return ret;
     107                }
     108        }
     109        free(hub->ports);
     110
     111        const int ret = ddf_fun_unbind(hub->hub_fun);
     112        if (ret != EOK) {
     113                usb_log_error("Failed to unbind '%s' function: %s.\n",
     114                   HUB_FNC_NAME, str_error(ret));
     115                return ret;
     116        }
     117        ddf_fun_destroy(hub->hub_fun);
     118
     119        free(hub);
     120        usb_dev->driver_data = NULL;
     121        usb_log_info("USB hub driver, stopped and cleaned.\n");
     122        return EOK;
     123}
     124/*----------------------------------------------------------------------------*/
     125/**
     126 * Initialize hub device driver fibril
     127 *
     128 * Creates hub representation and fibril that periodically checks hub's status.
     129 * Hub representation is passed to the fibril.
     130 * @param usb_dev generic usb device information
     131 * @return error code
     132 */
     133int usb_hub_device_add(usb_device_t *usb_dev)
    87134{
    88135        assert(usb_dev);
    89136        /* Create driver soft-state structure */
    90         usb_hub_info_t *hub_info = usb_hub_info_create(usb_dev);
    91         if (hub_info == NULL) {
     137        usb_hub_dev_t *hub_dev = usb_hub_dev_create(usb_dev);
     138        if (hub_dev == NULL) {
    92139                usb_log_error("Failed to create hun driver structure.\n");
    93140                return ENOMEM;
     
    97144        usb_log_debug("Initializing USB wire abstraction.\n");
    98145        int opResult = usb_hc_connection_initialize_from_device(
    99             &hub_info->connection, hub_info->usb_device->ddf_dev);
     146            &hub_dev->connection, hub_dev->usb_device->ddf_dev);
    100147        if (opResult != EOK) {
    101148                usb_log_error("Could not initialize connection to device: %s\n",
    102149                    str_error(opResult));
    103                 free(hub_info);
     150                free(hub_dev);
    104151                return opResult;
    105152        }
     
    110157                usb_log_error("Could not set hub configuration: %s\n",
    111158                    str_error(opResult));
    112                 free(hub_info);
     159                free(hub_dev);
    113160                return opResult;
    114161        }
    115162
    116         //get port count and create attached_devs
    117         opResult = usb_hub_process_hub_specific_info(hub_info);
     163        /* Get port count and create attached_devices. */
     164        opResult = usb_hub_process_hub_specific_info(hub_dev);
    118165        if (opResult != EOK) {
    119166                usb_log_error("Could process hub specific info, %s\n",
    120167                    str_error(opResult));
    121                 free(hub_info);
     168                free(hub_dev);
    122169                return opResult;
    123170        }
    124171
    125172        usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n");
    126         ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,
     173        hub_dev->hub_fun = ddf_fun_create(hub_dev->usb_device->ddf_dev,
    127174            fun_exposed, HUB_FNC_NAME);
    128         if (hub_fun == NULL) {
     175        if (hub_dev->hub_fun == NULL) {
    129176                usb_log_error("Failed to create hub function.\n");
    130                 free(hub_info);
     177                free(hub_dev);
    131178                return ENOMEM;
    132179        }
    133180
    134         opResult = ddf_fun_bind(hub_fun);
     181        opResult = ddf_fun_bind(hub_dev->hub_fun);
    135182        if (opResult != EOK) {
    136183                usb_log_error("Failed to bind hub function: %s.\n",
    137184                   str_error(opResult));
    138                 free(hub_info);
    139                 ddf_fun_destroy(hub_fun);
     185                free(hub_dev);
     186                ddf_fun_destroy(hub_dev->hub_fun);
    140187                return opResult;
    141188        }
    142189
    143         opResult = usb_device_auto_poll(hub_info->usb_device, 0,
    144             hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1,
    145             usb_hub_polling_terminated_callback, hub_info);
    146         if (opResult != EOK) {
    147                 ddf_fun_destroy(hub_fun);
    148                 free(hub_info);
     190        opResult = usb_device_auto_poll(hub_dev->usb_device, 0,
     191            hub_port_changes_callback, ((hub_dev->port_count + 1 + 8) / 8),
     192            usb_hub_polling_terminated_callback, hub_dev);
     193        if (opResult != EOK) {
     194                /* Function is already bound */
     195                ddf_fun_unbind(hub_dev->hub_fun);
     196                ddf_fun_destroy(hub_dev->hub_fun);
     197                free(hub_dev);
    149198                usb_log_error("Failed to create polling fibril: %s.\n",
    150199                    str_error(opResult));
    151200                return opResult;
    152201        }
     202        hub_dev->running = true;
    153203        usb_log_info("Controlling hub '%s' (%zu ports).\n",
    154             hub_info->usb_device->ddf_dev->name, hub_info->port_count);
     204            hub_dev->usb_device->ddf_dev->name, hub_dev->port_count);
    155205
    156206        return EOK;
     
    162212 * @param change_bitmap Bitmap of changed ports.
    163213 * @param change_bitmap_size Size of the bitmap in bytes.
    164  * @param arg Custom argument, points to @c usb_hub_info_t.
     214 * @param arg Custom argument, points to @c usb_hub_dev_t.
    165215 * @return Whether to continue polling.
    166216 */
     
    169219{
    170220        usb_log_debug("hub_port_changes_callback\n");
    171         usb_hub_info_t *hub = arg;
     221        usb_hub_dev_t *hub = arg;
    172222        assert(hub);
    173223
     
    184234
    185235        /* N + 1 bit indicates change on port N */
    186         size_t port = 1;
    187         for (; port < hub->port_count + 1; port++) {
    188                 const bool change = (change_bitmap[port / 8] >> (port % 8)) & 1;
     236        for (size_t port = 0; port < hub->port_count + 1; port++) {
     237                const size_t bit = port + 1;
     238                const bool change = (change_bitmap[bit / 8] >> (bit % 8)) & 1;
    189239                if (change) {
    190240                        usb_hub_port_process_interrupt(&hub->ports[port], hub);
     
    195245/*----------------------------------------------------------------------------*/
    196246/**
    197  * create usb_hub_info_t structure
     247 * create usb_hub_dev_t structure
    198248 *
    199249 * Does only basic copying of known information into new structure.
    200250 * @param usb_dev usb device structure
    201  * @return basic usb_hub_info_t structure
    202  */
    203 static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev)
     251 * @return basic usb_hub_dev_t structure
     252 */
     253static usb_hub_dev_t * usb_hub_dev_create(usb_device_t *usb_dev)
    204254{
    205255        assert(usb_dev);
    206         usb_hub_info_t *info = malloc(sizeof(usb_hub_info_t));
    207         if (!info)
     256        usb_hub_dev_t *hub_dev = malloc(sizeof(usb_hub_dev_t));
     257        if (!hub_dev)
    208258            return NULL;
    209259
    210         info->usb_device = usb_dev;
    211 
    212         info->ports = NULL;
    213         info->port_count = -1;
    214         fibril_mutex_initialize(&info->pending_ops_mutex);
    215         fibril_condvar_initialize(&info->pending_ops_cv);
    216         info->pending_ops_count = 0;
    217 
    218         return info;
    219 }
    220 /*----------------------------------------------------------------------------*/
    221 /**
    222  * Load hub-specific information into hub_info structure and process if needed
     260        hub_dev->usb_device = usb_dev;
     261
     262        hub_dev->ports = NULL;
     263        hub_dev->port_count = 0;
     264        hub_dev->pending_ops_count = 0;
     265        hub_dev->running = false;
     266        fibril_mutex_initialize(&hub_dev->pending_ops_mutex);
     267        fibril_condvar_initialize(&hub_dev->pending_ops_cv);
     268        usb_dev->driver_data = hub_dev;
     269
     270        return hub_dev;
     271}
     272/*----------------------------------------------------------------------------*/
     273/**
     274 * Load hub-specific information into hub_dev structure and process if needed
    223275 *
    224276 * Read port count and initialize structures holding per port information.
     
    226278 * This function is hub-specific and should be run only after the hub is
    227279 * configured using usb_set_first_configuration function.
    228  * @param hub_info hub representation
     280 * @param hub_dev hub representation
    229281 * @return error code
    230282 */
    231 static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info)
    232 {
    233         assert(hub_info);
     283static int usb_hub_process_hub_specific_info(usb_hub_dev_t *hub_dev)
     284{
     285        assert(hub_dev);
    234286
    235287        /* Get hub descriptor. */
    236288        usb_log_debug("Retrieving descriptor\n");
    237         usb_pipe_t *control_pipe = &hub_info->usb_device->ctrl_pipe;
     289        usb_pipe_t *control_pipe = &hub_dev->usb_device->ctrl_pipe;
    238290
    239291        usb_hub_descriptor_header_t descriptor;
     
    250302
    251303        usb_log_debug("Setting port count to %d.\n", descriptor.port_count);
    252         hub_info->port_count = descriptor.port_count;
    253 
    254         // TODO: +1 hack is no longer necessary
    255         hub_info->ports =
    256             malloc(sizeof(usb_hub_port_t) * (hub_info->port_count + 1));
    257         if (!hub_info->ports) {
     304        hub_dev->port_count = descriptor.port_count;
     305
     306        hub_dev->ports = calloc(hub_dev->port_count, sizeof(usb_hub_port_t));
     307        if (!hub_dev->ports) {
    258308                return ENOMEM;
    259309        }
    260310
    261         size_t port;
    262         for (port = 0; port < hub_info->port_count + 1; ++port) {
    263                 usb_hub_port_init(&hub_info->ports[port], port, control_pipe);
     311        for (size_t port = 0; port < hub_dev->port_count; ++port) {
     312                usb_hub_port_init(
     313                    &hub_dev->ports[port], port + 1, control_pipe);
    264314        }
    265315
     
    271321                    & HUB_CHAR_POWER_PER_PORT_FLAG;
    272322
    273                 for (port = 1; port <= hub_info->port_count; ++port) {
     323                for (size_t port = 0; port < hub_dev->port_count; ++port) {
    274324                        usb_log_debug("Powering port %zu.\n", port);
    275325                        opResult = usb_hub_port_set_feature(
    276                             &hub_info->ports[port], USB_HUB_FEATURE_PORT_POWER);
     326                            &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
    277327                        if (opResult != EOK) {
    278328                                usb_log_error("Cannot power on port %zu: %s.\n",
     
    314364        }
    315365
    316         // TODO: Make sure that there is enough data and the cast is correct
     366        if (usb_device->descriptors.configuration_size
     367            < sizeof(usb_standard_configuration_descriptor_t)) {
     368            usb_log_error("Configuration descriptor is not big enough"
     369                " to fit standard configuration descriptor.\n");
     370            return EOVERFLOW;
     371        }
     372
     373        // TODO: Make sure that the cast is correct
    317374        usb_standard_configuration_descriptor_t *config_descriptor
    318375            = (usb_standard_configuration_descriptor_t *)
     
    337394 *
    338395 * This means either to power off the hub or power it on.
    339  * @param hub_info hub instance
     396 * @param hub_dev hub instance
    340397 * @param status hub status bitmask
    341398 * @return error code
    342399 */
    343 static void usb_hub_over_current(const usb_hub_info_t *hub_info,
     400static void usb_hub_over_current(const usb_hub_dev_t *hub_dev,
    344401    usb_hub_status_t status)
    345402{
     
    351408                /* Over-current condition is gone, it is safe to turn the
    352409                 * ports on. */
    353                 size_t port;
    354                 for (port = 1; port <= hub_info->port_count; ++port) {
     410                for (size_t port = 0; port < hub_dev->port_count; ++port) {
    355411                        const int opResult = usb_hub_port_set_feature(
    356                             &hub_info->ports[port], USB_HUB_FEATURE_PORT_POWER);
     412                            &hub_dev->ports[port], USB_HUB_FEATURE_PORT_POWER);
     413                        // TODO: consider power policy here
    357414                        if (opResult != EOK) {
    358415                                usb_log_warning(
     
    364421        }
    365422        const int opResult = usb_request_clear_feature(
    366             &hub_info->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS,
     423            &hub_dev->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS,
    367424            USB_REQUEST_RECIPIENT_DEVICE,
    368425            USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0);
     
    378435 *
    379436 * The change can be either in the over-current condition or local-power change.
    380  * @param hub_info hub instance
    381  */
    382 static void usb_hub_global_interrupt(const usb_hub_info_t *hub_info)
    383 {
    384         assert(hub_info);
    385         assert(hub_info->usb_device);
     437 * @param hub_dev hub instance
     438 */
     439static void usb_hub_global_interrupt(const usb_hub_dev_t *hub_dev)
     440{
     441        assert(hub_dev);
     442        assert(hub_dev->usb_device);
    386443        usb_log_debug("Global interrupt on a hub\n");
    387         usb_pipe_t *control_pipe = &hub_info->usb_device->ctrl_pipe;
     444        usb_pipe_t *control_pipe = &hub_dev->usb_device->ctrl_pipe;
    388445
    389446        usb_hub_status_t status;
     
    406463        /* Handle status changes */
    407464        if (status & USB_HUB_STATUS_C_OVER_CURRENT) {
    408                 usb_hub_over_current(hub_info, status);
     465                usb_hub_over_current(hub_dev, status);
    409466        }
    410467
     
    438495 * callback called from hub polling fibril when the fibril terminates
    439496 *
    440  * Should perform a cleanup - deletes hub_info.
     497 * Does not perform cleanup, just marks the hub as not running.
    441498 * @param device usb device afected
    442499 * @param was_error indicates that the fibril is stoped due to an error
    443  * @param data pointer to usb_hub_info_t structure
     500 * @param data pointer to usb_hub_dev_t structure
    444501 */
    445502static void usb_hub_polling_terminated_callback(usb_device_t *device,
    446503    bool was_error, void *data)
    447504{
    448         usb_hub_info_t *hub = data;
     505        usb_hub_dev_t *hub = data;
    449506        assert(hub);
    450507
     
    460517         */
    461518        if (hub->pending_ops_count > 0) {
    462                 size_t port;
    463                 for (port = 0; port < hub->port_count; port++) {
     519                for (size_t port = 0; port < hub->port_count; ++port) {
    464520                        usb_hub_port_reset_fail(&hub->ports[port]);
    465521                }
     
    471527        }
    472528        fibril_mutex_unlock(&hub->pending_ops_mutex);
    473 
    474         usb_device_destroy(hub->usb_device);
    475 
    476         free(hub->ports);
    477         free(hub);
     529        hub->running = false;
    478530}
    479531/**
  • uspace/drv/bus/usb/usbhub/usbhub.h

    rcff3fb6 rd083126  
    5252
    5353/** Information about attached hub. */
    54 struct usb_hub_info_t {
     54struct usb_hub_dev {
    5555        /** Number of ports. */
    5656        size_t port_count;
    57 
    58         /** Attached device handles, for each port one */
     57        /** Port structures, one for each port */
    5958        usb_hub_port_t *ports;
    60 
    6159        /** Connection to hcd */
    6260        usb_hc_connection_t connection;
    63 
    6461        /** Generic usb device data*/
    6562        usb_device_t *usb_device;
     
    7673        /** Condition variable for pending_ops_count. */
    7774        fibril_condvar_t pending_ops_cv;
     75        /** Pointer to devman usbhub function. */
     76        ddf_fun_t *hub_fun;
     77        /** Status indicator */
     78        bool running;
    7879};
    7980
    80 int usb_hub_add_device(usb_device_t *usb_dev);
     81int usb_hub_device_add(usb_device_t *usb_dev);
     82int usb_hub_device_gone(usb_device_t *usb_dev);
    8183
    8284bool hub_port_changes_callback(usb_device_t *dev,
  • uspace/drv/bus/usb/usbmast/main.c

    rcff3fb6 rd083126  
    8787 * @return Error code.
    8888 */
    89 static int usbmast_add_device(usb_device_t *dev)
     89static int usbmast_device_add(usb_device_t *dev)
    9090{
    9191        int rc;
     
    9494
    9595        /* Allocate softstate */
    96         mdev = ddf_dev_data_alloc(dev->ddf_dev, sizeof(usbmast_dev_t));
     96        dev->driver_data = mdev = malloc(sizeof(usbmast_dev_t));
    9797        if (mdev == NULL) {
    9898                usb_log_error("Failed allocating softstate.\n");
     
    103103        mdev->usb_dev = dev;
    104104
    105         usb_log_info("Initializing mass storage `%s'.\n",
    106             dev->ddf_dev->name);
     105        usb_log_info("Initializing mass storage `%s'.\n", dev->ddf_dev->name);
    107106        usb_log_debug(" Bulk in endpoint: %d [%zuB].\n",
    108107            dev->pipes[BULK_IN_EP].pipe->endpoint_no,
     
    295294/** USB mass storage driver ops. */
    296295static usb_driver_ops_t usbmast_driver_ops = {
    297         .add_device = usbmast_add_device,
     296        .device_add = usbmast_device_add,
    298297};
    299298
  • uspace/drv/bus/usb/usbmid/main.c

    rcff3fb6 rd083126  
    4949 * @return Error code.
    5050 */
    51 static int usbmid_add_device(usb_device_t *dev)
     51static int usbmid_device_add(usb_device_t *dev)
    5252{
    5353        usb_log_info("Taking care of new MID `%s'.\n", dev->ddf_dev->name);
     
    6868/** USB MID driver ops. */
    6969static usb_driver_ops_t mid_driver_ops = {
    70         .add_device = usbmid_add_device,
     70        .device_add = usbmid_device_add,
    7171};
    7272
  • uspace/drv/bus/usb/usbmouse/main.c

    rcff3fb6 rd083126  
    5050 *
    5151 */
    52 static int usbmouse_add_device(usb_device_t *dev)
     52static int usbmouse_device_add(usb_device_t *dev)
    5353{
    5454        int rc = usb_mouse_create(dev);
     
    8080/** USB mouse driver ops. */
    8181static usb_driver_ops_t mouse_driver_ops = {
    82         .add_device = usbmouse_add_device,
     82        .device_add = usbmouse_device_add,
    8383};
    8484
  • uspace/drv/bus/usb/vhc/hub.c

    rcff3fb6 rd083126  
    8181}
    8282
    83 static int pretend_port_rest(int unused, void *unused2)
     83static int pretend_port_rest(void *unused2)
    8484{
    8585        return EOK;
     
    114114
    115115        ddf_fun_t *hub_dev;
    116         rc = usb_hc_new_device_wrapper(hc_dev->dev, &hc_conn,
    117             USB_SPEED_FULL,
    118             pretend_port_rest, 0, NULL,
    119             NULL, NULL, &rh_ops, hc_dev, &hub_dev);
     116        rc = usb_hc_new_device_wrapper(hc_dev->dev, &hc_conn, USB_SPEED_FULL,
     117            pretend_port_rest, NULL, NULL, &rh_ops, hc_dev, &hub_dev);
    120118        if (rc != EOK) {
    121119                usb_log_fatal("Failed to create root hub: %s.\n",
  • uspace/lib/usb/include/usb/hc.h

    rcff3fb6 rd083126  
    5353
    5454int usb_hc_connection_initialize_from_device(usb_hc_connection_t *,
    55     ddf_dev_t *);
     55    const ddf_dev_t *);
    5656int usb_hc_connection_initialize(usb_hc_connection_t *, devman_handle_t);
    5757
  • uspace/lib/usb/src/hc.c

    rcff3fb6 rd083126  
    5050 */
    5151int usb_hc_connection_initialize_from_device(usb_hc_connection_t *connection,
    52     ddf_dev_t *device)
     52    const ddf_dev_t *device)
    5353{
    5454        assert(connection);
  • uspace/lib/usbdev/include/usb/dev/driver.h

    rcff3fb6 rd083126  
    9696        usb_device_descriptors_t descriptors;
    9797
    98         /** Generic DDF device backing this one. */
     98        /** Generic DDF device backing this one. RO: DO NOT TOUCH!*/
    9999        ddf_dev_t *ddf_dev;
    100100        /** Custom driver data.
     
    112112/** USB driver ops. */
    113113typedef struct {
    114         /** Callback when new device is about to be controlled by the driver. */
    115         int (*add_device)(usb_device_t *);
     114        /** Callback when a new device was added to the system. */
     115        int (*device_add)(usb_device_t *);
     116        /** Callback when a device is about to be removed from the system. */
     117        int (*device_rem)(usb_device_t *);
     118        /** Callback when a device was removed from the system. */
     119        int (*device_gone)(usb_device_t *);
    116120} usb_driver_ops_t;
    117121
     
    163167
    164168int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *);
    165 int usb_device_create_pipes(ddf_dev_t *, usb_device_connection_t *,
     169int usb_device_create_pipes(const ddf_dev_t *, usb_device_connection_t *,
    166170    usb_endpoint_description_t **, uint8_t *, size_t, int, int,
    167171    usb_endpoint_mapping_t **, size_t *);
    168 int usb_device_destroy_pipes(ddf_dev_t *, usb_endpoint_mapping_t *, size_t);
     172int usb_device_destroy_pipes(const ddf_dev_t *, usb_endpoint_mapping_t *, size_t);
    169173int usb_device_create(ddf_dev_t *, usb_endpoint_description_t **, usb_device_t **, const char **);
    170174void usb_device_destroy(usb_device_t *);
  • uspace/lib/usbdev/include/usb/dev/hub.h

    rcff3fb6 rd083126  
    3838#define LIBUSBDEV_HUB_H_
    3939
     40#include <ddf/driver.h>
    4041#include <sys/types.h>
    4142#include <usb/hc.h>
    4243
    4344int usb_hc_new_device_wrapper(ddf_dev_t *, usb_hc_connection_t *, usb_speed_t,
    44     int (*)(int, void *), int, void *,
    45     usb_address_t *, devman_handle_t *,
    46     ddf_dev_ops_t *, void *, ddf_fun_t **);
     45    int (*)(void *), void *, usb_address_t *, ddf_dev_ops_t *, void *,
     46    ddf_fun_t **);
    4747
    4848/** Info about device attached to host controller.
     
    5555        /** Device address. */
    5656        usb_address_t address;
    57         /** Devman handle of the device. */
    58         devman_handle_t handle;
    59 } usb_hc_attached_device_t;
     57        /** DDF function (external) of the device. */
     58        ddf_fun_t *fun;
     59} usb_hub_attached_device_t;
    6060
    6161usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_speed_t);
    6262int usb_hc_register_device(usb_hc_connection_t *,
    63     const usb_hc_attached_device_t *);
     63    const usb_hub_attached_device_t *);
    6464int usb_hc_unregister_device(usb_hc_connection_t *, usb_address_t);
    6565
  • uspace/lib/usbdev/include/usb/dev/pipes.h

    rcff3fb6 rd083126  
    159159    usb_device_connection_t *, usb_hc_connection_t *);
    160160int usb_device_connection_initialize_from_device(usb_device_connection_t *,
    161     ddf_dev_t *);
     161    const ddf_dev_t *);
    162162int usb_device_connection_initialize(usb_device_connection_t *,
    163163    devman_handle_t, usb_address_t);
    164164
    165 int usb_device_get_assigned_interface(ddf_dev_t *);
     165int usb_device_get_assigned_interface(const ddf_dev_t *);
    166166
    167167int usb_pipe_initialize(usb_pipe_t *, usb_device_connection_t *,
     
    185185int usb_pipe_control_read(usb_pipe_t *, const void *, size_t,
    186186    void *, size_t, size_t *);
    187 int usb_pipe_control_write(usb_pipe_t *, void *, size_t,
    188     void *, size_t);
     187int usb_pipe_control_write(usb_pipe_t *, const void *, size_t,
     188    const void *, size_t);
    189189
    190190#endif
  • uspace/lib/usbdev/include/usb/dev/recognise.h

    rcff3fb6 rd083126  
    5151
    5252int usb_device_register_child_in_devman(usb_address_t, devman_handle_t,
    53     ddf_dev_t *, devman_handle_t *, ddf_dev_ops_t *, void *, ddf_fun_t **);
     53    ddf_dev_t *, ddf_dev_ops_t *, void *, ddf_fun_t **);
    5454
    5555#endif
  • uspace/lib/usbdev/src/devdrv.c

    rcff3fb6 rd083126  
    4141#include <assert.h>
    4242
    43 static int generic_add_device(ddf_dev_t *);
     43static int generic_device_add(ddf_dev_t *);
     44static int generic_device_remove(ddf_dev_t *);
     45static int generic_device_gone(ddf_dev_t *);
    4446
    4547static driver_ops_t generic_driver_ops = {
    46         .add_device = generic_add_device
     48        .add_device = generic_device_add,
     49        .dev_remove = generic_device_remove,
     50        .dev_gone = generic_device_gone,
    4751};
    4852static driver_t generic_driver = {
     
    123127        return EOK;
    124128}
    125 
    126 /** Callback when new device is supposed to be controlled by this driver.
    127  *
    128  * This callback is a wrapper for USB specific version of @c add_device.
     129/*----------------------------------------------------------------------------*/
     130/** Callback when a new device is supposed to be controlled by this driver.
     131 *
     132 * This callback is a wrapper for USB specific version of @c device_add.
    129133 *
    130134 * @param gen_dev Device structure as prepared by DDF.
    131135 * @return Error code.
    132136 */
    133 int generic_add_device(ddf_dev_t *gen_dev)
     137int generic_device_add(ddf_dev_t *gen_dev)
    134138{
    135139        assert(driver);
    136140        assert(driver->ops);
    137         assert(driver->ops->add_device);
     141        assert(driver->ops->device_add);
    138142
    139143        int rc;
     
    147151                return rc;
    148152        }
    149 
    150         return driver->ops->add_device(dev);
    151 }
    152 
     153        gen_dev->driver_data = dev;
     154
     155        return driver->ops->device_add(dev);
     156}
     157/*----------------------------------------------------------------------------*/
     158/** Callback when a device is supposed to be removed from the system.
     159 *
     160 * This callback is a wrapper for USB specific version of @c device_remove.
     161 *
     162 * @param gen_dev Device structure as prepared by DDF.
     163 * @return Error code.
     164 */
     165int generic_device_remove(ddf_dev_t *gen_dev)
     166{
     167        assert(driver);
     168        assert(driver->ops);
     169        if (driver->ops->device_rem == NULL)
     170                return ENOTSUP;
     171        /* Just tell the driver to stop whatever it is doing, keep structures */
     172        return driver->ops->device_rem(gen_dev->driver_data);
     173}
     174/*----------------------------------------------------------------------------*/
     175/** Callback when a device was removed from the system.
     176 *
     177 * This callback is a wrapper for USB specific version of @c device_gone.
     178 *
     179 * @param gen_dev Device structure as prepared by DDF.
     180 * @return Error code.
     181 */
     182int generic_device_gone(ddf_dev_t *gen_dev)
     183{
     184        assert(driver);
     185        assert(driver->ops);
     186        if (driver->ops->device_gone == NULL)
     187                return ENOTSUP;
     188        const int ret = driver->ops->device_gone(gen_dev->driver_data);
     189        if (ret == EOK)
     190                usb_device_destroy(gen_dev->driver_data);
     191
     192        return ret;
     193}
     194/*----------------------------------------------------------------------------*/
    153195/** Destroy existing pipes of a USB device.
    154196 *
     
    275317 * @return Error code.
    276318 */
    277 int usb_device_create_pipes(ddf_dev_t *dev, usb_device_connection_t *wire,
     319int usb_device_create_pipes(const ddf_dev_t *dev, usb_device_connection_t *wire,
    278320    usb_endpoint_description_t **endpoints,
    279321    uint8_t *config_descr, size_t config_descr_size,
     
    349391        }
    350392
    351         usb_hc_connection_close(&hc_conn);
     393        if (usb_hc_connection_close(&hc_conn) != EOK)
     394                usb_log_warning("usb_device_create_pipes(): "
     395                    "Failed to close connection.\n");
    352396
    353397        *pipes_ptr = pipes;
     
    371415        }
    372416
    373         usb_hc_connection_close(&hc_conn);
     417        if (usb_hc_connection_close(&hc_conn) != EOK)
     418                usb_log_warning("usb_device_create_pipes(): "
     419                    "Failed to close connection.\n");
    374420
    375421        /*
     
    395441 * @param[in] pipes_count Number of endpoints.
    396442 */
    397 int usb_device_destroy_pipes(ddf_dev_t *dev,
     443int usb_device_destroy_pipes(const ddf_dev_t *dev,
    398444    usb_endpoint_mapping_t *pipes, size_t pipes_count)
    399445{
     
    426472        }
    427473
    428         usb_hc_connection_close(&hc_conn);
     474        if (usb_hc_connection_close(&hc_conn) != EOK)
     475                usb_log_warning("usb_device_destroy_pipes(): "
     476                    "Failed to close connection.\n");
    429477
    430478        free(pipes);
     
    545593        /* Ignore errors and hope for the best. */
    546594        usb_device_destroy_pipes(dev->ddf_dev, dev->pipes, dev->pipes_count);
    547         if (dev->descriptors.configuration != NULL) {
    548                 free(dev->descriptors.configuration);
    549         }
     595        free(dev->descriptors.configuration);
    550596
    551597        if (dev->alternate_interfaces != NULL) {
    552                 if (dev->alternate_interfaces->alternatives != NULL) {
    553                         free(dev->alternate_interfaces->alternatives);
    554                 }
    555                 free(dev->alternate_interfaces);
    556         }
     598                free(dev->alternate_interfaces->alternatives);
     599        }
     600        free(dev->alternate_interfaces);
    557601
    558602        free(dev);
  • uspace/lib/usbdev/src/hub.c

    rcff3fb6 rd083126  
    3737#include <usb/dev/request.h>
    3838#include <usb/dev/recognise.h>
     39#include <usb/debug.h>
    3940#include <usbhc_iface.h>
    4041#include <errno.h>
     
    5758                assert((conn)); \
    5859                if (!usb_hc_connection_is_opened((conn))) { \
    59                         return ENOENT; \
     60                        usb_log_error("Connection not open.\n"); \
     61                        return ENOTCONN; \
    6062                } \
    6163        } while (false)
     
    9597 */
    9698int usb_hc_register_device(usb_hc_connection_t * connection,
    97     const usb_hc_attached_device_t *attached_device)
     99    const usb_hub_attached_device_t *attached_device)
    98100{
    99101        CHECK_CONNECTION(connection);
     
    105107        int rc = async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    106108            IPC_M_USBHC_BIND_ADDRESS,
    107             attached_device->address, attached_device->handle);
     109            attached_device->address, attached_device->fun->handle);
    108110        async_exchange_end(exch);
    109111       
     
    155157 * The @p enable_port function is expected to enable signaling on given
    156158 * port.
    157  * The two arguments to it can have arbitrary meaning
    158  * (the @p port_no is only a suggestion)
    159  * and are not touched at all by this function
    160  * (they are passed as is to the @p enable_port function).
     159 * The argument can have arbitrary meaning and it is not touched at all
     160 * by this function (it is passed as is to the @p enable_port function).
    161161 *
    162162 * If the @p enable_port fails (i.e. does not return EOK), the device
     
    175175 * @param[in] enable_port Function for enabling signaling through the port the
    176176 *      device is attached to.
    177  * @param[in] port_no Port number (passed through to @p enable_port).
    178177 * @param[in] arg Any data argument to @p enable_port.
    179178 * @param[out] assigned_address USB address of the device.
    180  * @param[out] assigned_handle Devman handle of the new device.
    181179 * @param[in] dev_ops Child device ops.
    182180 * @param[in] new_dev_data Arbitrary pointer to be stored in the child
     
    194192int usb_hc_new_device_wrapper(ddf_dev_t *parent, usb_hc_connection_t *connection,
    195193    usb_speed_t dev_speed,
    196     int (*enable_port)(int port_no, void *arg), int port_no, void *arg,
    197     usb_address_t *assigned_address, devman_handle_t *assigned_handle,
     194    int (*enable_port)(void *arg), void *arg, usb_address_t *assigned_address,
    198195    ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun)
    199196{
     
    224221        usb_address_t dev_addr = usb_hc_request_address(&hc_conn, dev_speed);
    225222        if (dev_addr < 0) {
    226                 usb_hc_connection_close(&hc_conn);
    227                 return EADDRNOTAVAIL;
     223                rc = EADDRNOTAVAIL;
     224                goto close_connection;
    228225        }
    229226
     
    279276         * device address.
    280277         */
    281         rc = enable_port(port_no, arg);
     278        rc = enable_port(arg);
    282279        if (rc != EOK) {
    283280                goto leave_release_default_address;
     
    320317         */
    321318        /* FIXME: create device_register that will get opened ctrl pipe. */
    322         devman_handle_t child_handle;
     319        ddf_fun_t *child_fun;
    323320        rc = usb_device_register_child_in_devman(dev_addr, dev_conn.hc_handle,
    324             parent, &child_handle,
    325             dev_ops, new_dev_data, new_fun);
     321            parent, dev_ops, new_dev_data, &child_fun);
    326322        if (rc != EOK) {
    327323                rc = ESTALL;
     
    332328         * And now inform the host controller about the handle.
    333329         */
    334         usb_hc_attached_device_t new_device = {
     330        usb_hub_attached_device_t new_device = {
    335331                .address = dev_addr,
    336                 .handle = child_handle
     332                .fun = child_fun,
    337333        };
    338334        rc = usb_hc_register_device(&hc_conn, &new_device);
     
    341337                goto leave_release_free_address;
    342338        }
    343        
    344         usb_hc_connection_close(&hc_conn);
     339
    345340
    346341        /*
     
    350345                *assigned_address = dev_addr;
    351346        }
    352         if (assigned_handle != NULL) {
    353                 *assigned_handle = child_handle;
    354         }
    355 
    356         return EOK;
    357 
    358 
     347        if (new_fun != NULL) {
     348                *new_fun = child_fun;
     349        }
     350
     351        rc = EOK;
     352        goto close_connection;
    359353
    360354        /*
     
    368362        usb_hc_unregister_device(&hc_conn, dev_addr);
    369363
    370         usb_hc_connection_close(&hc_conn);
     364close_connection:
     365        if (usb_hc_connection_close(&hc_conn) != EOK)
     366                usb_log_warning("usb_hc_new_device_wrapper(): Failed to close "
     367                    "connection.\n");
    371368
    372369        return rc;
  • uspace/lib/usbdev/src/pipes.c

    rcff3fb6 rd083126  
    5252 * @return USB address or error code.
    5353 */
    54 static usb_address_t get_my_address(async_sess_t *sess, ddf_dev_t *dev)
     54static usb_address_t get_my_address(async_sess_t *sess, const ddf_dev_t *dev)
    5555{
    5656        async_exch_t *exch = async_exchange_begin(sess);
     
    7878 * @return Interface number (negative code means any).
    7979 */
    80 int usb_device_get_assigned_interface(ddf_dev_t *device)
     80int usb_device_get_assigned_interface(const ddf_dev_t *device)
    8181{
    8282        async_sess_t *parent_sess =
     
    108108 */
    109109int usb_device_connection_initialize_from_device(
    110     usb_device_connection_t *connection, ddf_dev_t *dev)
     110    usb_device_connection_t *connection, const ddf_dev_t *dev)
    111111{
    112112        assert(connection);
  • uspace/lib/usbdev/src/pipesio.c

    rcff3fb6 rd083126  
    469469 */
    470470static int usb_pipe_control_write_no_check(usb_pipe_t *pipe,
    471     void *setup_buffer, size_t setup_buffer_size,
    472     void *data_buffer, size_t data_buffer_size)
     471    const void *setup_buffer, size_t setup_buffer_size,
     472    const void *data_buffer, size_t data_buffer_size)
    473473{
    474474        /* Ensure serialization over the phone. */
     
    536536 */
    537537int usb_pipe_control_write(usb_pipe_t *pipe,
    538     void *setup_buffer, size_t setup_buffer_size,
    539     void *data_buffer, size_t data_buffer_size)
     538    const void *setup_buffer, size_t setup_buffer_size,
     539    const void *data_buffer, size_t data_buffer_size)
    540540{
    541541        assert(pipe);
  • uspace/lib/usbdev/src/recognise.c

    rcff3fb6 rd083126  
    339339 * @param[in] hc_handle Handle of the host controller.
    340340 * @param[in] parent Parent device.
    341  * @param[out] child_handle Handle of the child device.
    342341 * @param[in] dev_ops Child device ops.
    343342 * @param[in] dev_data Arbitrary pointer to be stored in the child
     
    348347 */
    349348int usb_device_register_child_in_devman(usb_address_t address,
    350     devman_handle_t hc_handle,
    351     ddf_dev_t *parent, devman_handle_t *child_handle,
     349    devman_handle_t hc_handle, ddf_dev_t *parent,
    352350    ddf_dev_ops_t *dev_ops, void *dev_data, ddf_fun_t **child_fun)
    353351{
     
    414412        }
    415413
    416         if (child_handle != NULL) {
    417                 *child_handle = child->handle;
    418         }
    419 
    420414        if (child_fun != NULL) {
    421415                *child_fun = child;
Note: See TracChangeset for help on using the changeset viewer.