Changes in / [77223f8:0748854] in mainline


Ignore:
Location:
uspace
Files:
24 edited

Legend:

Unmodified
Added
Removed
  • uspace/doc/doxygroups.h

    r77223f8 r0748854  
    269269
    270270        /**
     271         * @defgroup drvusbohci OHCI driver
     272         * @ingroup usb
     273         * @brief Driver for OHCI host controller.
     274         */
     275
     276        /**
    271277         * @defgroup drvusbehci EHCI driver
    272278         * @ingroup usb
     
    275281
    276282        /**
    277          * @defgroup drvusbfallback USB fallback driver.
     283         * @defgroup drvusbfallback USB fallback driver
    278284         * @ingroup usb
    279285         * @brief Fallback driver for any USB device.
  • uspace/drv/ohci/batch.c

    r77223f8 r0748854  
    227227        ed_init(data->ed, instance->ep);
    228228        ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]);
    229         usb_log_debug("Created ED: %x:%x:%x:%x.\n", data->ed->status,
    230             data->ed->td_tail, data->ed->td_head, data->ed->next);
     229        usb_log_debug("Created ED(%p): %x:%x:%x:%x.\n", data->ed,
     230            data->ed->status, data->ed->td_tail, data->ed->td_head,
     231            data->ed->next);
    231232        int toggle = 0;
    232233        /* setup stage */
  • uspace/drv/ohci/hc.c

    r77223f8 r0748854  
    108108            ret, str_error(ret));
    109109
     110        hc_gain_control(instance);
     111        ret = hc_init_memory(instance);
     112        CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures:%s.\n",
     113            ret, str_error(ret));
     114        hc_init_hw(instance);
     115
     116        rh_init(&instance->rh, dev, instance->registers);
     117
    110118        if (!interrupts) {
    111119                instance->interrupt_emulator =
     
    114122        }
    115123
    116         hc_gain_control(instance);
    117 
    118         rh_init(&instance->rh, dev, instance->registers);
    119 
    120         hc_init_memory(instance);
    121         hc_init_hw(instance);
    122 
    123         /* TODO: implement */
    124124        return EOK;
    125125}
     
    140140        switch (batch->transfer_type) {
    141141        case USB_TRANSFER_CONTROL:
     142                instance->registers->control &= ~C_CLE;
    142143                instance->registers->command_status |= CS_CLF;
     144                usb_log_debug2("Set control transfer filled: %x.\n",
     145                        instance->registers->command_status);
     146                instance->registers->control |= C_CLE;
    143147                break;
    144148        case USB_TRANSFER_BULK:
    145149                instance->registers->command_status |= CS_BLF;
     150                usb_log_debug2("Set bulk transfer filled: %x.\n",
     151                        instance->registers->command_status);
    146152                break;
    147153        default:
     
    154160{
    155161        assert(instance);
    156         if (status == 0)
     162        if ((status & ~IS_SF) == 0) /* ignore sof status */
    157163                return;
    158164        if (status & IS_RHSC)
     
    160166
    161167        usb_log_info("OHCI interrupt: %x.\n", status);
     168
    162169
    163170        LIST_INITIALIZE(done);
     
    192199{
    193200        assert(instance);
     201        /* Turn off legacy emulation */
     202        volatile uint32_t *ohci_emulation_reg =
     203            (uint32_t*)((char*)instance->registers + 0x100);
     204        usb_log_debug("OHCI legacy register %p: %x.\n",
     205                ohci_emulation_reg, *ohci_emulation_reg);
     206        *ohci_emulation_reg = 0;
     207
    194208        /* Interrupt routing enabled => smm driver is active */
    195209        if (instance->registers->control & C_IR) {
    196                 usb_log_info("Found SMM driver requesting ownership change.\n");
     210                usb_log_debug("SMM driver: request ownership change.\n");
    197211                instance->registers->command_status |= CS_OCR;
    198212                while (instance->registers->control & C_IR) {
    199213                        async_usleep(1000);
    200214                }
    201                 usb_log_info("Ownership taken from SMM driver.\n");
     215                usb_log_info("SMM driver: Ownership taken.\n");
    202216                return;
    203217        }
     
    207221        /* Interrupt routing disabled && status != USB_RESET => BIOS active */
    208222        if (hc_status != C_HCFS_RESET) {
    209                 usb_log_info("Found BIOS driver.\n");
     223                usb_log_debug("BIOS driver found.\n");
    210224                if (hc_status == C_HCFS_OPERATIONAL) {
    211                         usb_log_info("HC operational(BIOS).\n");
     225                        usb_log_info("BIOS driver: HC operational.\n");
    212226                        return;
    213227                }
     
    215229                instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);
    216230                async_usleep(20000);
     231                usb_log_info("BIOS driver: HC resumed.\n");
    217232                return;
    218233        }
     
    220235        /* HC is in reset (hw startup) => no other driver
    221236         * maintain reset for at least the time specified in USB spec (50 ms)*/
     237        usb_log_info("HC found in reset.\n");
    222238        async_usleep(50000);
    223 
    224         /* turn off legacy emulation */
    225         volatile uint32_t *ohci_emulation_reg =
    226             (uint32_t*)((char*)instance->registers + 0x100);
    227         usb_log_info("OHCI legacy register status %p: %x.\n",
    228                 ohci_emulation_reg, *ohci_emulation_reg);
    229         *ohci_emulation_reg = 0;
    230 
    231239}
    232240/*----------------------------------------------------------------------------*/
    233241void hc_init_hw(hc_t *instance)
    234242{
    235         assert(instance);
     243        /* OHCI guide page 42 */
     244        assert(instance);
     245        usb_log_debug2("Started hc initialization routine.\n");
     246
     247        /* Save contents of fm_interval register */
    236248        const uint32_t fm_interval = instance->registers->fm_interval;
    237 
    238         /* reset hc */
     249        usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
     250
     251        /* Reset hc */
     252        usb_log_debug2("HC reset.\n");
     253        size_t time = 0;
    239254        instance->registers->command_status = CS_HCR;
    240         async_usleep(10);
    241 
    242         /* restore fm_interval */
     255        while (instance->registers->command_status & CS_HCR) {
     256                async_usleep(10);
     257                time += 10;
     258        }
     259        usb_log_debug2("HC reset complete in %zu us.\n", time);
     260
     261        /* Restore fm_interval */
    243262        instance->registers->fm_interval = fm_interval;
    244263        assert((instance->registers->command_status & CS_HCR) == 0);
    245264
    246265        /* hc is now in suspend state */
    247 
    248         /* enable queues */
     266        usb_log_debug2("HC should be in suspend state(%x).\n",
     267            instance->registers->control);
     268
     269        /* Enable queues */
    249270        instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);
    250         /* TODO: enable interrupts */
    251         /* set periodic start to 90% */
    252         instance->registers->periodic_start = (fm_interval / 10) * 9;
     271        usb_log_debug2("All queues enabled(%x).\n",
     272            instance->registers->control);
     273
     274        /* Disable interrupts */
     275        instance->registers->interrupt_disable = I_SF | I_OC;
     276        usb_log_debug2("Disabling interrupts: %x.\n",
     277            instance->registers->interrupt_disable);
     278        instance->registers->interrupt_disable = I_MI;
     279        usb_log_debug2("Enabled interrupts: %x.\n",
     280            instance->registers->interrupt_enable);
     281
     282        /* Set periodic start to 90% */
     283        uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK);
     284        instance->registers->periodic_start = (frame_length / 10) * 9;
     285        usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n",
     286            instance->registers->periodic_start,
     287            instance->registers->periodic_start, frame_length);
    253288
    254289        instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);
    255         usb_log_info("OHCI HC up and running.\n");
     290        usb_log_info("OHCI HC up and running(%x).\n",
     291            instance->registers->control);
    256292}
    257293/*----------------------------------------------------------------------------*/
     
    298334{
    299335        assert(instance);
    300         /* init queues */
     336        /* Init queues */
    301337        hc_init_transfer_lists(instance);
    302338
    303         /* init HCCA */
     339        /*Init HCCA */
    304340        instance->hcca = malloc32(sizeof(hcca_t));
    305341        if (instance->hcca == NULL)
     
    307343        bzero(instance->hcca, sizeof(hcca_t));
    308344        instance->registers->hcca = addr_to_phys(instance->hcca);
    309 
    310         /* use queues */
     345        usb_log_debug2("OHCI HCCA initialized at %p(%p).\n",
     346            instance->hcca, instance->registers->hcca);
     347
     348        /* Use queues */
    311349        instance->registers->bulk_head = instance->transfers_bulk.list_head_pa;
     350        usb_log_debug2("Bulk HEAD set to: %p(%p).\n",
     351            instance->transfers_bulk.list_head,
     352            instance->transfers_bulk.list_head_pa);
     353
    312354        instance->registers->control_head =
    313355            instance->transfers_control.list_head_pa;
     356        usb_log_debug2("Control HEAD set to: %p(%p).\n",
     357            instance->transfers_control.list_head,
     358            instance->transfers_control.list_head_pa);
    314359
    315360        unsigned i = 0;
     
    318363                    instance->transfers_interrupt.list_head_pa;
    319364        }
     365        usb_log_debug2("Interrupt HEADs set to: %p(%p).\n",
     366            instance->transfers_interrupt.list_head,
     367            instance->transfers_interrupt.list_head_pa);
    320368
    321369        return EOK;
  • uspace/drv/ohci/hw_struct/endpoint_descriptor.c

    r77223f8 r0748854  
    4242        bzero(instance, sizeof(ed_t));
    4343        if (ep == NULL) {
    44                 instance->status |= ED_STATUS_K_FLAG;
     44                instance->status = ED_STATUS_K_FLAG;
    4545                return;
    4646        }
     
    5757        if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS)
    5858                instance->status |= ED_STATUS_F_FLAG;
    59 
    6059}
    61 
    6260/**
    6361 * @}
  • uspace/drv/ohci/iface.c

    r77223f8 r0748854  
    7474            name, target.address, target.endpoint, size, ep->max_packet_size);
    7575
    76         assert(ep->speed ==
    77             usb_device_keeper_get_speed(&(*hc)->manager, target.address));
    78 //      assert(ep->max_packet_size == max_packet_size);
    79 //      assert(ep->transfer_type == USB_TRANSFER_CONTROL);
    80 
    81         *batch =
    82             batch_get(fun, ep, data, size, setup_data, setup_size,
    83                 in, out, arg);
    84         if (!batch)
     76        *batch = batch_get(
     77            fun, ep, data, size, setup_data, setup_size, in, out, arg);
     78        if (!*batch)
    8579                return ENOMEM;
    86         return EOK;
    87 }
    88 
    89 
    90 /** Reserve default address interface function
    91  *
    92  * @param[in] fun DDF function that was called.
    93  * @param[in] speed Speed to associate with the new default address.
    94  * @return Error code.
    95  */
    96 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
    97 {
    98         assert(fun);
    99         hc_t *hc = fun_to_hc(fun);
    100         assert(hc);
    101         usb_log_debug("Default address request with speed %d.\n", speed);
    102         usb_device_keeper_reserve_default_address(&hc->manager, speed);
    103         return EOK;
    104 #if 0
    105         endpoint_t *ep = malloc(sizeof(endpoint_t));
    106         if (ep == NULL)
    107                 return ENOMEM;
    108         const size_t max_packet_size = speed == USB_SPEED_LOW ? 8 : 64;
    109         endpoint_init(ep, USB_TRANSFER_CONTROL, speed, max_packet_size);
    110         int ret;
    111 try_retgister:
    112         ret = usb_endpoint_manager_register_ep(&hc->ep_manager,
    113             USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH, ep, endpoint_destroy, 0);
    114         if (ret == EEXISTS) {
    115                 async_usleep(1000);
    116                 goto try_retgister;
    117         }
    118         if (ret != EOK) {
    119                 endpoint_destroy(ep);
    120         }
    121         return ret;
    122 #endif
    123 }
    124 /*----------------------------------------------------------------------------*/
    125 /** Release default address interface function
    126  *
    127  * @param[in] fun DDF function that was called.
    128  * @return Error code.
    129  */
    130 static int release_default_address(ddf_fun_t *fun)
    131 {
    132         assert(fun);
    133         hc_t *hc = fun_to_hc(fun);
    134         assert(hc);
    135         usb_log_debug("Default address release.\n");
    136 //      return usb_endpoint_manager_unregister_ep(&hc->ep_manager,
    137 //          USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH);
    138         usb_device_keeper_release_default_address(&hc->manager);
    13980        return EOK;
    14081}
     
    245186        if (ret != EOK) {
    246187                endpoint_destroy(ep);
    247         } else {
    248                 usb_device_keeper_add_ep(&hc->manager, address, ep);
    249188        }
    250189        return ret;
     
    259198        usb_log_debug("Unregister endpoint %d:%d %d.\n",
    260199            address, endpoint, direction);
    261         endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
    262             address, endpoint, direction, NULL);
    263         if (ep != NULL) {
    264                 usb_device_keeper_del_ep(&hc->manager, address, ep);
    265         }
    266200        return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
    267201            endpoint, direction);
     
    435369        if (ret != EOK)
    436370                return ret;
    437         usb_device_keeper_reset_if_need(&hc->manager, target, setup_data);
     371        usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);
    438372        batch_control_write(batch);
    439373        ret = hc_schedule(hc, batch);
     
    484418/*----------------------------------------------------------------------------*/
    485419usbhc_iface_t hc_iface = {
    486         .reserve_default_address = reserve_default_address,
    487         .release_default_address = release_default_address,
    488420        .request_address = request_address,
    489421        .bind_address = bind_address,
  • uspace/drv/ohci/ohci_regs.h

    r77223f8 r0748854  
    8484        /** Interupt enable/disable, reads give the same value, writing causes
    8585         * enable/disable */
    86         volatile uint32_t interupt_enable;
     86        volatile uint32_t interrupt_enable;
    8787        volatile uint32_t interrupt_disable;
    8888#define I_SO   (1 << 0)   /* Scheduling overrun */
     
    120120        /** Frame time and max packet size for all transfers */
    121121        volatile uint32_t fm_interval;
    122 #define FMI_FI_MASK (0x1fff) /* Frame interval in bit times (should be 11999)*/
     122#define FMI_FI_MASK (0x3fff) /* Frame interval in bit times (should be 11999)*/
    123123#define FMI_FI_SHIFT (0)
    124124#define FMI_FSMPS_MASK (0x7fff) /* Full speed max packet size */
     
    138138        /** Remaining bit time in frame to start periodic transfers */
    139139        volatile uint32_t periodic_start;
    140 #define PS_PS_MASK (0x1fff) /* bit time when periodic get priority (0x3e67) */
     140#define PS_PS_MASK (0x3fff) /* bit time when periodic get priority (0x3e67) */
    141141
    142142        /** Threshold for starting LS transaction */
  • uspace/drv/ohci/root_hub.c

    r77223f8 r0748854  
    115115
    116116static const uint32_t hub_set_feature_valid_mask =
    117         (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
     117        (1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT) |
     118(1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
    118119
    119120
     
    209210        instance->registers = regs;
    210211        instance->device = dev;
    211         instance->port_count = instance->registers->rh_desc_a & 0xff;
     212        instance->port_count =
     213            (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;
    212214        rh_init_descriptors(instance);
    213215        // set port power mode to no-power-switching
     
    586588        if (!((1 << feature) & hub_set_feature_valid_mask))
    587589                return EINVAL;
     590        if(feature == USB_HUB_FEATURE_C_HUB_LOCAL_POWER)
     591                feature = USB_HUB_FEATURE_C_HUB_LOCAL_POWER << 16;
    588592        instance->registers->rh_status =
    589593                (instance->registers->rh_status | (1 << feature))
  • uspace/drv/ohci/transfer_list.c

    r77223f8 r0748854  
    122122        usb_transfer_batch_t *first = list_get_instance(
    123123            instance->batch_list.next, usb_transfer_batch_t, link);
    124         usb_log_debug("Batch(%p) added to queue %s, first is %p.\n",
    125                 batch, instance->name, first);
     124        usb_log_debug("Batch(%p) added to list %s, first is %p(%p).\n",
     125                batch, instance->name, first, batch_ed(first));
     126        if (last_ed == instance->list_head) {
     127                usb_log_debug2("%s head ED: %x:%x:%x:%x.\n", instance->name,
     128                        last_ed->status, last_ed->td_tail, last_ed->td_head,
     129                        last_ed->next);
     130        }
    126131        fibril_mutex_unlock(&instance->guard);
    127132}
  • uspace/drv/uhci-hcd/iface.c

    r77223f8 r0748854  
    7474            name, target.address, target.endpoint, size, ep->max_packet_size);
    7575
    76 //      assert(ep->speed ==
    77 //          usb_device_keeper_get_speed(&(*hc)->manager, target.address));
    78 //      assert(ep->max_packet_size == max_packet_size);
    79 //      assert(ep->transfer_type == USB_TRANSFER_CONTROL);
    80 
    81         *batch =
    82             batch_get(fun, ep, data, size, setup_data, setup_size,
    83                 in, out, arg);
    84         if (!batch)
     76        *batch = batch_get(
     77                fun, ep, data, size, setup_data, setup_size, in, out, arg);
     78        if (!*batch)
    8579                return ENOMEM;
    86         return EOK;
    87 }
    88 
    89 
    90 /** Reserve default address interface function
    91  *
    92  * @param[in] fun DDF function that was called.
    93  * @param[in] speed Speed to associate with the new default address.
    94  * @return Error code.
    95  */
    96 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed)
    97 {
    98         assert(fun);
    99         hc_t *hc = fun_to_hc(fun);
    100         assert(hc);
    101         usb_log_debug("Default address request with speed %d.\n", speed);
    102         usb_device_keeper_reserve_default_address(&hc->manager, speed);
    103         return EOK;
    104 #if 0
    105         endpoint_t *ep = malloc(sizeof(endpoint_t));
    106         if (ep == NULL)
    107                 return ENOMEM;
    108         const size_t max_packet_size = speed == USB_SPEED_LOW ? 8 : 64;
    109         endpoint_init(ep, USB_TRANSFER_CONTROL, speed, max_packet_size);
    110         int ret;
    111 try_retgister:
    112         ret = usb_endpoint_manager_register_ep(&hc->ep_manager,
    113             USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH, ep, endpoint_destroy, 0);
    114         if (ret == EEXISTS) {
    115                 async_usleep(1000);
    116                 goto try_retgister;
    117         }
    118         if (ret != EOK) {
    119                 endpoint_destroy(ep);
    120         }
    121         return ret;
    122 #endif
    123 }
    124 /*----------------------------------------------------------------------------*/
    125 /** Release default address interface function
    126  *
    127  * @param[in] fun DDF function that was called.
    128  * @return Error code.
    129  */
    130 static int release_default_address(ddf_fun_t *fun)
    131 {
    132         assert(fun);
    133         hc_t *hc = fun_to_hc(fun);
    134         assert(hc);
    135         usb_log_debug("Default address release.\n");
    136 //      return usb_endpoint_manager_unregister_ep(&hc->ep_manager,
    137 //          USB_ADDRESS_DEFAULT, 0, USB_DIRECTION_BOTH);
    138         usb_device_keeper_release_default_address(&hc->manager);
    13980        return EOK;
    14081}
     
    232173        if (ret != EOK) {
    233174                endpoint_destroy(ep);
    234         } else {
    235                 usb_device_keeper_add_ep(&hc->manager, address, ep);
    236175        }
    237176        return ret;
     
    246185        usb_log_debug("Unregister endpoint %d:%d %d.\n",
    247186            address, endpoint, direction);
    248         endpoint_t *ep = usb_endpoint_manager_get_ep(&hc->ep_manager,
    249             address, endpoint, direction, NULL);
    250         if (ep != NULL) {
    251                 usb_device_keeper_del_ep(&hc->manager, address, ep);
    252         }
    253187        return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
    254188            endpoint, direction);
     
    391325        if (ret != EOK)
    392326                return ret;
    393         usb_device_keeper_reset_if_need(&hc->manager, target, setup_data);
     327        usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);
    394328        batch_control_write(batch);
    395329        ret = hc_schedule(hc, batch);
     
    433367/*----------------------------------------------------------------------------*/
    434368usbhc_iface_t hc_iface = {
    435         .reserve_default_address = reserve_default_address,
    436         .release_default_address = release_default_address,
    437369        .request_address = request_address,
    438370        .bind_address = bind_address,
  • uspace/drv/usbhub/Makefile

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

    r77223f8 r0748854  
    4949
    5050/**
     51 * structure holding hub status and changes flags.
     52 * should not be accessed directly, use supplied getter/setter methods.
     53 *
     54 * For more information refer to table 11.16.2.5 in
     55 * "Universal Serial Bus Specification Revision 1.1"
     56 *
     57 */
     58typedef uint32_t usb_hub_status_t;
     59
     60/**
    5161 * set values in request to be it a port status request
    5262 * @param request
     
    5464 */
    5565static inline void usb_hub_set_port_status_request(
    56 usb_device_request_setup_packet_t * request, uint16_t port
    57 ){
     66        usb_device_request_setup_packet_t * request, uint16_t port
     67        ) {
    5868        request->index = port;
    5969        request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS;
     
    6373}
    6474
     75/**
     76 * set values in request to be it a port status request
     77 * @param request
     78 * @param port
     79 */
     80static inline void usb_hub_set_hub_status_request(
     81        usb_device_request_setup_packet_t * request
     82        ) {
     83        request->index = 0;
     84        request->request_type = USB_HUB_REQ_TYPE_GET_HUB_STATUS;
     85        request->request = USB_HUB_REQUEST_GET_STATUS;
     86        request->value = 0;
     87        request->length = 4;
     88}
    6589
    6690/**
     
    7094 */
    7195static inline usb_device_request_setup_packet_t *
    72 usb_hub_create_port_status_request(uint16_t port){
     96usb_hub_create_port_status_request(uint16_t port) {
    7397        usb_device_request_setup_packet_t * result =
    74                 usb_new(usb_device_request_setup_packet_t);
    75         usb_hub_set_port_status_request(result,port);
     98                malloc(sizeof(usb_device_request_setup_packet_t));
     99        usb_hub_set_port_status_request(result, port);
    76100        return result;
    77101}
    78102
    79 
    80103/**
    81104 * set the device request to be a port feature enable request
     
    85108 */
    86109static inline void usb_hub_set_enable_port_feature_request(
    87 usb_device_request_setup_packet_t * request, uint16_t port,
    88                 uint16_t feature_selector
    89 ){
     110        usb_device_request_setup_packet_t * request, uint16_t port,
     111        uint16_t feature_selector
     112        ) {
    90113        request->index = port;
    91114        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    102125 */
    103126static inline void usb_hub_set_disable_port_feature_request(
    104 usb_device_request_setup_packet_t * request, uint16_t port,
    105                 uint16_t feature_selector
    106 ){
     127        usb_device_request_setup_packet_t * request, uint16_t port,
     128        uint16_t feature_selector
     129        ) {
    107130        request->index = port;
    108131        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    118141 */
    119142static inline void usb_hub_set_enable_port_request(
    120 usb_device_request_setup_packet_t * request, uint16_t port
    121 ){
     143        usb_device_request_setup_packet_t * request, uint16_t port
     144        ) {
    122145        request->index = port;
    123146        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    133156 */
    134157static inline usb_device_request_setup_packet_t *
    135 usb_hub_create_enable_port_request(uint16_t port){
     158usb_hub_create_enable_port_request(uint16_t port) {
    136159        usb_device_request_setup_packet_t * result =
    137                 usb_new(usb_device_request_setup_packet_t);
    138         usb_hub_set_enable_port_request(result,port);
     160                malloc(sizeof(usb_device_request_setup_packet_t));
     161        usb_hub_set_enable_port_request(result, port);
    139162        return result;
    140163}
     
    146169 */
    147170static inline void usb_hub_set_disable_port_request(
    148 usb_device_request_setup_packet_t * request, uint16_t port
    149 ){
     171        usb_device_request_setup_packet_t * request, uint16_t port
     172        ) {
    150173        request->index = port;
    151174        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    161184 */
    162185static inline usb_device_request_setup_packet_t *
    163 usb_hub_create_disable_port_request(uint16_t port){
     186usb_hub_create_disable_port_request(uint16_t port) {
    164187        usb_device_request_setup_packet_t * result =
    165                 usb_new(usb_device_request_setup_packet_t);
    166         usb_hub_set_disable_port_request(result,port);
     188                malloc(sizeof(usb_device_request_setup_packet_t));
     189        usb_hub_set_disable_port_request(result, port);
    167190        return result;
    168191}
     
    174197 */
    175198static inline void usb_hub_set_reset_port_request(
    176 usb_device_request_setup_packet_t * request, uint16_t port
    177 ){
     199        usb_device_request_setup_packet_t * request, uint16_t port
     200        ) {
    178201        request->index = port;
    179202        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    189212 */
    190213static inline usb_device_request_setup_packet_t *
    191 usb_hub_create_reset_port_request(uint16_t port){
     214usb_hub_create_reset_port_request(uint16_t port) {
    192215        usb_device_request_setup_packet_t * result =
    193                 usb_new(usb_device_request_setup_packet_t);
    194         usb_hub_set_reset_port_request(result,port);
     216                malloc(sizeof(usb_device_request_setup_packet_t));
     217        usb_hub_set_reset_port_request(result, port);
    195218        return result;
    196219}
     
    202225 */
    203226static inline void usb_hub_set_power_port_request(
    204 usb_device_request_setup_packet_t * request, uint16_t port
    205 ){
     227        usb_device_request_setup_packet_t * request, uint16_t port
     228        ) {
    206229        request->index = port;
    207230        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    217240 */
    218241static inline void usb_hub_unset_power_port_request(
    219 usb_device_request_setup_packet_t * request, uint16_t port
    220 ){
     242        usb_device_request_setup_packet_t * request, uint16_t port
     243        ) {
    221244        request->index = port;
    222245        request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
     
    226249}
    227250
    228 
    229 /** get i`th bit of port status */
    230 static inline bool usb_port_get_bit(usb_port_status_t * status, int idx)
    231 {
    232         return (((*status)>>(idx))%2);
    233 }
    234 
    235 /** set i`th bit of port status */
    236 static inline void usb_port_set_bit(
    237         usb_port_status_t * status, int idx, bool value)
    238 {
    239         (*status) = value?
    240                                ((*status)|(1<<(idx))):
    241                                ((*status)&(~(1<<(idx))));
    242 }
    243 
    244 //device connnected on port
    245 static inline bool usb_port_dev_connected(usb_port_status_t * status){
    246         return usb_port_get_bit(status,0);
    247 }
    248 
    249 static inline void usb_port_set_dev_connected(usb_port_status_t * status,bool connected){
    250         usb_port_set_bit(status,0,connected);
     251/**
     252 * get i`th bit of port status
     253 *
     254 * @param status
     255 * @param idx
     256 * @return
     257 */
     258static inline bool usb_port_is_status(usb_port_status_t status, int idx) {
     259        return (status&(1 << idx))!=0;
     260}
     261
     262/**
     263 * set i`th bit of port status
     264 *
     265 * @param status
     266 * @param idx
     267 * @param value
     268 */
     269static inline void usb_port_status_set_bit(
     270        usb_port_status_t * status, int idx, bool value) {
     271        (*status) = value ?
     272                ((*status) | (1 << (idx))) :
     273                ((*status)&(~(1 << (idx))));
     274}
     275
     276/**
     277 * get i`th bit of hub status
     278 *
     279 * @param status
     280 * @param idx
     281 * @return
     282 */
     283static inline bool usb_hub_is_status(usb_hub_status_t status, int idx) {
     284        return (status&(1 << idx))!=0;
     285}
     286
     287/**
     288 * set i`th bit of hub status
     289 *
     290 * @param status
     291 * @param idx
     292 * @param value
     293 */
     294static inline void usb_hub_status_set_bit(
     295        usb_hub_status_t * status, int idx, bool value) {
     296        (*status) = value ?
     297                ((*status) | (1 << (idx))) :
     298                ((*status)&(~(1 << (idx))));
     299}
     300
     301
     302#if 0
     303/**
     304 * connection status geter for port status
     305 *
     306 * @param status
     307 * @return true if there is something connected
     308 */
     309static inline bool usb_port_dev_connected(usb_port_status_t * status) {
     310        return usb_port_get_bit(status, 0);
     311}
     312
     313/**
     314 * set device connected bit in port status
     315 *
     316 * @param status
     317 * @param connected value of the bit
     318 */
     319static inline void usb_port_set_dev_connected(usb_port_status_t * status, bool connected) {
     320        usb_port_set_bit(status, 0, connected);
    251321}
    252322
    253323//port enabled
    254 static inline bool usb_port_enabled(usb_port_status_t * status){
    255         return usb_port_get_bit(status,1);
    256 }
    257 
    258 static inline void usb_port_set_enabled(usb_port_status_t * status,bool enabled){
    259         usb_port_set_bit(status,1,enabled);
     324
     325/**
     326 * port enabled getter for port status
     327 *
     328 * @param status
     329 * @return true if the port is enabled
     330 */
     331static inline bool usb_port_enabled(usb_port_status_t * status) {
     332        return usb_port_get_bit(status, 1);
     333}
     334
     335/**
     336 * set port enabled bit in port status
     337 *
     338 * @param status
     339 * @param enabled value of the bit
     340 */
     341static inline void usb_port_set_enabled(usb_port_status_t * status, bool enabled) {
     342        usb_port_set_bit(status, 1, enabled);
    260343}
    261344
    262345//port suspended
    263 static inline bool usb_port_suspended(usb_port_status_t * status){
    264         return usb_port_get_bit(status,2);
    265 }
    266 
    267 static inline void usb_port_set_suspended(usb_port_status_t * status,bool suspended){
    268         usb_port_set_bit(status,2,suspended);
     346/**
     347 * port suspended getter for port status
     348 *
     349 * @param status
     350 * @return true if port is suspended
     351 */
     352static inline bool usb_port_suspended(usb_port_status_t * status) {
     353        return usb_port_get_bit(status, 2);
     354}
     355
     356/**
     357 * set port suspended bit in port status
     358 *
     359 * @param status
     360 * @param suspended value of the bit
     361 */
     362static inline void usb_port_set_suspended(usb_port_status_t * status, bool suspended) {
     363        usb_port_set_bit(status, 2, suspended);
    269364}
    270365
    271366//over currect
    272 static inline bool usb_port_over_current(usb_port_status_t * status){
    273         return usb_port_get_bit(status,3);
    274 }
    275 
    276 static inline void usb_port_set_over_current(usb_port_status_t * status,bool value){
    277         usb_port_set_bit(status,3,value);
     367/**
     368 * over current condition indicator getter for port status
     369 *
     370 * @param status
     371 * @return true if there is opver-current condition on the hub
     372 */
     373static inline bool usb_port_over_current(usb_port_status_t * status) {
     374        return usb_port_get_bit(status, 3);
     375}
     376
     377/**
     378 * set over current indicator bit in port status
     379 *
     380 * @param status
     381 * @param value value of the bit
     382 */
     383static inline void usb_port_set_over_current(usb_port_status_t * status, bool value) {
     384        usb_port_set_bit(status, 3, value);
    278385}
    279386
    280387//port reset
    281 static inline bool usb_port_reset(usb_port_status_t * status){
    282         return usb_port_get_bit(status,4);
    283 }
    284 
    285 static inline void usb_port_set_reset(usb_port_status_t * status,bool value){
    286         usb_port_set_bit(status,4,value);
     388/**
     389 * port reset indicator getter for port status
     390 *
     391 * @param status
     392 * @return true if port is reset
     393 */
     394static inline bool usb_port_reset(usb_port_status_t * status) {
     395        return usb_port_get_bit(status, 4);
     396}
     397
     398/**
     399 * set port reset bit in port status
     400 *
     401 * @param status
     402 * @param value value of the bit
     403 */
     404static inline void usb_port_set_reset(usb_port_status_t * status, bool value) {
     405        usb_port_set_bit(status, 4, value);
    287406}
    288407
    289408//powered
    290 static inline bool usb_port_powered(usb_port_status_t * status){
    291         return usb_port_get_bit(status,8);
    292 }
    293 
    294 static inline void usb_port_set_powered(usb_port_status_t * status,bool powered){
    295         usb_port_set_bit(status,8,powered);
    296 }
     409/**
     410 * power state getter for port status
     411 *
     412 * @param status
     413 * @return true if port is powered
     414 */
     415static inline bool usb_port_powered(usb_port_status_t * status) {
     416        return usb_port_get_bit(status, 8);
     417}
     418
     419/**
     420 * set port powered bit in port status
     421 *
     422 * @param status
     423 * @param powered value of the bit
     424 */
     425static inline void usb_port_set_powered(usb_port_status_t * status, bool powered) {
     426        usb_port_set_bit(status, 8, powered);
     427}
     428
     429#endif
    297430
    298431//low speed device attached
    299 static inline bool usb_port_low_speed(usb_port_status_t * status){
    300         return usb_port_get_bit(status,9);
    301 }
    302 
    303 static inline void usb_port_set_low_speed(usb_port_status_t * status,bool low_speed){
    304         usb_port_set_bit(status,9,low_speed);
    305 }
    306 
    307 //low speed device attached
    308 static inline bool usb_port_high_speed(usb_port_status_t * status){
    309         return usb_port_get_bit(status,10);
    310 }
    311 
    312 static inline void usb_port_set_high_speed(usb_port_status_t * status,bool high_speed){
    313         usb_port_set_bit(status,10,high_speed);
    314 }
    315 
    316 static inline usb_speed_t usb_port_speed(usb_port_status_t * status){
    317         if(usb_port_low_speed(status))
     432/**
     433 * low speed device on the port indicator
     434 *
     435 * @param status
     436 * @return true if low speed device is attached
     437 */
     438static inline bool usb_port_low_speed(usb_port_status_t status) {
     439        return usb_port_is_status(status, 9);
     440}
     441
     442/**
     443 * set low speed device connected bit in port status
     444 *
     445 * @param status
     446 * @param low_speed value of the bit
     447 */
     448static inline void usb_port_set_low_speed(usb_port_status_t * status, bool low_speed) {
     449        usb_port_status_set_bit(status, 9, low_speed);
     450}
     451
     452//high speed device attached
     453/**
     454 * high speed device on the port indicator
     455 *
     456 * @param status
     457 * @return true if high speed device is on port
     458 */
     459static inline bool usb_port_high_speed(usb_port_status_t status) {
     460        return usb_port_is_status(status, 10);
     461}
     462
     463/**
     464 * set high speed device bit in port status
     465 *
     466 * @param status
     467 * @param high_speed value of the bit
     468 */
     469static inline void usb_port_set_high_speed(usb_port_status_t * status, bool high_speed) {
     470        usb_port_status_set_bit(status, 10, high_speed);
     471}
     472
     473/**
     474 * speed getter for port status
     475 *
     476 * @param status
     477 * @return speed of usb device (for more see usb specification)
     478 */
     479static inline usb_speed_t usb_port_speed(usb_port_status_t status) {
     480        if (usb_port_low_speed(status))
    318481                return USB_SPEED_LOW;
    319         if(usb_port_high_speed(status))
     482        if (usb_port_high_speed(status))
    320483                return USB_SPEED_HIGH;
    321484        return USB_SPEED_FULL;
    322485}
    323486
    324 
     487#if 0
    325488//connect change
    326 static inline bool usb_port_connect_change(usb_port_status_t * status){
    327         return usb_port_get_bit(status,16);
    328 }
    329 
    330 static inline void usb_port_set_connect_change(usb_port_status_t * status,bool change){
    331         usb_port_set_bit(status,16,change);
     489/**
     490 * port connect change indicator
     491 *
     492 * @param status
     493 * @return true if connection has changed
     494 */
     495static inline bool usb_port_connect_change(usb_port_status_t * status) {
     496        return usb_port_get_bit(status, 16);
     497}
     498
     499/**
     500 * set connection change bit in port status
     501 * @param status
     502 * @param change value of the bit
     503 */
     504static inline void usb_port_set_connect_change(usb_port_status_t * status, bool change) {
     505        usb_port_set_bit(status, 16, change);
    332506}
    333507
    334508//port enable change
    335 static inline bool usb_port_enabled_change(usb_port_status_t * status){
    336         return usb_port_get_bit(status,17);
    337 }
    338 
    339 static inline void usb_port_set_enabled_change(usb_port_status_t * status,bool change){
    340         usb_port_set_bit(status,17,change);
     509/**
     510 * port enable change for port status
     511 *
     512 * @param status
     513 * @return true if the port has been enabled/disabled
     514 */
     515static inline bool usb_port_enabled_change(usb_port_status_t * status) {
     516        return usb_port_get_bit(status, 17);
     517}
     518
     519/**
     520 * set port enable change bit in port status
     521 *
     522 * @param status
     523 * @param change value of the bit
     524 */
     525static inline void usb_port_set_enabled_change(usb_port_status_t * status, bool change) {
     526        usb_port_set_bit(status, 17, change);
    341527}
    342528
    343529//suspend change
    344 static inline bool usb_port_suspend_change(usb_port_status_t * status){
    345         return usb_port_get_bit(status,18);
    346 }
    347 
    348 static inline void usb_port_set_suspend_change(usb_port_status_t * status,bool change){
    349         usb_port_set_bit(status,18,change);
     530/**
     531 * port suspend change for port status
     532 *
     533 * @param status
     534 * @return ture if suspend status has changed
     535 */
     536static inline bool usb_port_suspend_change(usb_port_status_t * status) {
     537        return usb_port_get_bit(status, 18);
     538}
     539
     540/**
     541 * set port suspend change bit in port status
     542 *
     543 * @param status
     544 * @param change value of the bit
     545 */
     546static inline void usb_port_set_suspend_change(usb_port_status_t * status, bool change) {
     547        usb_port_set_bit(status, 18, change);
    350548}
    351549
    352550//over current change
    353 static inline bool usb_port_overcurrent_change(usb_port_status_t * status){
    354         return usb_port_get_bit(status,19);
    355 }
    356 
    357 static inline void usb_port_set_overcurrent_change(usb_port_status_t * status,bool change){
    358         usb_port_set_bit(status,19,change);
     551/**
     552 * over current change indicator
     553 *
     554 * @param status
     555 * @return true if over-current condition on port has changed
     556 */
     557static inline bool usb_port_overcurrent_change(usb_port_status_t * status) {
     558        return usb_port_get_bit(status, 19);
     559}
     560
     561/**
     562 * set port over current change bit in port status
     563 *
     564 * @param status
     565 * @param change value of the bit
     566 */
     567static inline void usb_port_set_overcurrent_change(usb_port_status_t * status, bool change) {
     568        usb_port_set_bit(status, 19, change);
    359569}
    360570
    361571//reset change
    362 static inline bool usb_port_reset_completed(usb_port_status_t * status){
    363         return usb_port_get_bit(status,20);
    364 }
    365 
    366 static inline void usb_port_set_reset_completed(usb_port_status_t * status,bool completed){
    367         usb_port_set_bit(status,20,completed);
    368 }
    369 
     572/**
     573 * port reset change indicator
     574 * @param status
     575 * @return true if port has been reset
     576 */
     577static inline bool usb_port_reset_completed(usb_port_status_t * status) {
     578        return usb_port_get_bit(status, 20);
     579}
     580
     581/**
     582 * set port reset completed bit in port status
     583 *
     584 * @param status
     585 * @param change value of the bit
     586 */
     587static inline void usb_port_set_reset_completed(usb_port_status_t * status, bool completed) {
     588        usb_port_set_bit(status, 20, completed);
     589}
     590
     591//local power status
     592/**
     593 * local power lost indicator for hub status
     594 *
     595 * @param status
     596 * @return true if hub is not powered
     597 */
     598static inline bool usb_hub_local_power_lost(usb_hub_status_t * status) {
     599        return usb_hub_get_bit(status, 0);
     600}
     601
     602/**
     603 * set hub power lost bit in hub status
     604 *
     605 * @param status
     606 * @param change value of the bit
     607 */
     608static inline void usb_hub_set_local_power_lost(usb_port_status_t * status,
     609        bool power_lost) {
     610        usb_hub_set_bit(status, 0, power_lost);
     611}
     612
     613//over current ocndition
     614/**
     615 * hub over-current indicator
     616 *
     617 * @param status
     618 * @return true if over-current condition occurred on hub
     619 */
     620static inline bool usb_hub_over_current(usb_hub_status_t * status) {
     621        return usb_hub_get_bit(status, 1);
     622}
     623
     624/**
     625 * set hub over current bit in hub status
     626 *
     627 * @param status
     628 * @param change value of the bit
     629 */
     630static inline void usb_hub_set_over_current(usb_port_status_t * status,
     631        bool over_current) {
     632        usb_hub_set_bit(status, 1, over_current);
     633}
     634
     635//local power change
     636/**
     637 * hub power change indicator
     638 *
     639 * @param status
     640 * @return true if local power status has been changed - power has been
     641 * dropped or re-established
     642 */
     643static inline bool usb_hub_local_power_change(usb_hub_status_t * status) {
     644        return usb_hub_get_bit(status, 16);
     645}
     646
     647/**
     648 * set hub power change bit in hub status
     649 *
     650 * @param status
     651 * @param change value of the bit
     652 */
     653static inline void usb_hub_set_local_power_change(usb_port_status_t * status,
     654        bool change) {
     655        usb_hub_set_bit(status, 16, change);
     656}
     657
     658//local power status
     659/**
     660 * hub over-current condition change indicator
     661 *
     662 * @param status
     663 * @return true if over-current condition has changed
     664 */
     665static inline bool usb_hub_over_current_change(usb_hub_status_t * status) {
     666        return usb_hub_get_bit(status, 17);
     667}
     668
     669/**
     670 * set hub over current change bit in hub status
     671 *
     672 * @param status
     673 * @param change value of the bit
     674 */
     675static inline void usb_hub_set_over_current_change(usb_port_status_t * status,
     676        bool change) {
     677        usb_hub_set_bit(status, 17, change);
     678}
     679#endif
    370680
    371681
  • uspace/drv/usbhub/ports.c

    r77223f8 r0748854  
    3333 * Hub ports functions.
    3434 */
    35 #include "port_status.h"
    36 #include <inttypes.h>
     35
     36#include <bool.h>
    3737#include <errno.h>
    3838#include <str_error.h>
    39 #include <usb/request.h>
     39#include <inttypes.h>
     40#include <fibril_synch.h>
     41
    4042#include <usb/debug.h>
     43
     44#include "ports.h"
     45#include "usbhub.h"
     46#include "usbhub_private.h"
     47#include "port_status.h"
     48
     49
     50/** Information for fibril for device discovery. */
     51struct add_device_phase1 {
     52        usb_hub_info_t *hub;
     53        size_t port;
     54        usb_speed_t speed;
     55};
     56
     57static void usb_hub_removed_device(
     58        usb_hub_info_t * hub, uint16_t port);
     59
     60static void usb_hub_port_reset_completed(usb_hub_info_t * hub,
     61        uint16_t port, uint32_t status);
     62
     63static void usb_hub_port_over_current(usb_hub_info_t * hub,
     64        uint16_t port, uint32_t status);
     65
     66static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,
     67    usb_port_status_t *status);
     68
     69static int enable_port_callback(int port_no, void *arg);
     70
     71static int add_device_phase1_worker_fibril(void *arg);
     72
     73static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,
     74    usb_speed_t speed);
     75
     76/**
     77 * Process interrupts on given hub port
     78 *
     79 * Accepts connection, over current and port reset change.
     80 * @param hub hub representation
     81 * @param port port number, starting from 1
     82 */
     83void usb_hub_process_interrupt(usb_hub_info_t * hub,
     84        uint16_t port) {
     85        usb_log_debug("interrupt at port %d\n", port);
     86        //determine type of change
     87        //usb_pipe_t *pipe = hub->control_pipe;
     88
     89        int opResult;
     90
     91        usb_port_status_t status;
     92        opResult = get_port_status(&hub->usb_device->ctrl_pipe, port, &status);
     93        if (opResult != EOK) {
     94                usb_log_error("Failed to get port %zu status: %s.\n",
     95                    port, str_error(opResult));
     96                return;
     97        }
     98        //connection change
     99        if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_CONNECTION)) {
     100                bool device_connected = usb_port_is_status(status,
     101                    USB_HUB_FEATURE_PORT_CONNECTION);
     102                usb_log_debug("Connection change on port %zu: %s.\n", port,
     103                    device_connected ? "device attached" : "device removed");
     104
     105                if (device_connected) {
     106                        opResult = create_add_device_fibril(hub, port,
     107                            usb_port_speed(status));
     108                        if (opResult != EOK) {
     109                                usb_log_error(
     110                                    "Cannot handle change on port %zu: %s.\n",
     111                                    str_error(opResult));
     112                        }
     113                } else {
     114                        usb_hub_removed_device(hub, port);
     115                }
     116        }
     117        //over current
     118        if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT)) {
     119                //check if it was not auto-resolved
     120                usb_log_debug("overcurrent change on port\n");
     121                usb_hub_port_over_current(hub, port, status);
     122        }
     123        //port reset
     124        if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_RESET)) {
     125                usb_hub_port_reset_completed(hub, port, status);
     126        }
     127        usb_log_debug("status x%x : %d\n ", status, status);
     128
     129        usb_port_status_set_bit(
     130            &status, USB_HUB_FEATURE_C_PORT_CONNECTION,false);
     131        usb_port_status_set_bit(
     132            &status, USB_HUB_FEATURE_PORT_RESET,false);
     133        usb_port_status_set_bit(
     134            &status, USB_HUB_FEATURE_C_PORT_RESET,false);
     135        usb_port_status_set_bit(
     136            &status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT,false);
     137        /// \TODO what about port power change?
     138        if (status >> 16) {
     139                usb_log_info("there was unsupported change on port %d: %X\n",
     140                        port, status);
     141
     142        }
     143}
     144
     145
     146/**
     147 * routine called when a device on port has been removed
     148 *
     149 * If the device on port had default address, it releases default address.
     150 * Otherwise does not do anything, because DDF does not allow to remove device
     151 * from it`s device tree.
     152 * @param hub hub representation
     153 * @param port port number, starting from 1
     154 */
     155static void usb_hub_removed_device(
     156        usb_hub_info_t * hub, uint16_t port) {
     157
     158        int opResult = usb_hub_clear_port_feature(hub->control_pipe,
     159                port, USB_HUB_FEATURE_C_PORT_CONNECTION);
     160        if (opResult != EOK) {
     161                usb_log_warning("could not clear port-change-connection flag\n");
     162        }
     163        /** \TODO remove device from device manager - not yet implemented in
     164         * devide manager
     165         */
     166
     167        //close address
     168        //if (hub->attached_devs[port].address != 0) {
     169        if(hub->ports[port].attached_device.address >= 0){
     170                /*uncomment this code to use it when DDF allows device removal
     171                opResult = usb_hc_unregister_device(
     172                        &hub->connection,
     173                        hub->attached_devs[port].address);
     174                if(opResult != EOK) {
     175                        dprintf(USB_LOG_LEVEL_WARNING, "could not release "
     176                                "address of "
     177                            "removed device: %d", opResult);
     178                }
     179                hub->attached_devs[port].address = 0;
     180                hub->attached_devs[port].handle = 0;
     181                 */
     182        } else {
     183                usb_log_warning("this is strange, disconnected device had "
     184                        "no address\n");
     185                //device was disconnected before it`s port was reset -
     186                //return default address
     187                usb_hub_release_default_address(hub);
     188        }
     189}
     190
     191
     192/**
     193 * Process port reset change
     194 *
     195 * After this change port should be enabled, unless some problem occured.
     196 * This functions triggers second phase of enabling new device.
     197 * @param hub
     198 * @param port
     199 * @param status
     200 */
     201static void usb_hub_port_reset_completed(usb_hub_info_t * hub,
     202        uint16_t port, uint32_t status){
     203        usb_log_debug("Port %zu reset complete.\n", port);
     204        if (usb_port_is_status(status, USB_HUB_FEATURE_PORT_ENABLE)) {
     205                /* Finalize device adding. */
     206                usb_hub_port_t *the_port = hub->ports + port;
     207                fibril_mutex_lock(&the_port->reset_mutex);
     208                the_port->reset_completed = true;
     209                fibril_condvar_broadcast(&the_port->reset_cv);
     210                fibril_mutex_unlock(&the_port->reset_mutex);
     211        } else {
     212                usb_log_warning(
     213                    "Port %zu reset complete but port not enabled.\n",
     214                    port);
     215        }
     216}
     217
     218/**
     219 * Process over current condition on port.
     220 *
     221 * Turn off the power on the port.
     222 *
     223 * @param hub hub representation
     224 * @param port port number, starting from 1
     225 */
     226static void usb_hub_port_over_current(usb_hub_info_t * hub,
     227        uint16_t port, uint32_t status) {
     228        int opResult;
     229        if(usb_port_is_status(status, USB_HUB_FEATURE_PORT_OVER_CURRENT)){
     230                opResult = usb_hub_clear_port_feature(hub->control_pipe,
     231                        port, USB_HUB_FEATURE_PORT_POWER);
     232                if (opResult != EOK) {
     233                        usb_log_error("cannot power off port %d;  %d\n",
     234                                port, opResult);
     235                }
     236        }else{
     237                opResult = usb_hub_set_port_feature(hub->control_pipe,
     238                        port, USB_HUB_FEATURE_PORT_POWER);
     239                if (opResult != EOK) {
     240                        usb_log_error("cannot power on port %d;  %d\n",
     241                                port, opResult);
     242                }
     243        }
     244}
    41245
    42246/** Retrieve port status.
     
    73277}
    74278
    75 /** Information for fibril for device discovery. */
    76 struct add_device_phase1 {
    77         usb_hub_info_t *hub;
    78         size_t port;
    79         usb_speed_t speed;
    80 };
    81 
    82279/** Callback for enabling a specific port.
    83280 *
     
    91288static int enable_port_callback(int port_no, void *arg)
    92289{
    93         usb_hub_info_t *hub = (usb_hub_info_t *) arg;
     290        usb_hub_info_t *hub = arg;
    94291        int rc;
    95292        usb_device_request_setup_packet_t request;
     
    156353        data->hub->ports[data->port].attached_device.address = new_address;
    157354
    158         usb_log_info("Detected new device on `%s' (port %zu), " \
     355        usb_log_info("Detected new device on `%s' (port %zu), "
    159356            "address %d (handle %" PRIun ").\n",
    160357            data->hub->usb_device->ddf_dev->name, data->port,
     
    166363        return EOK;
    167364}
     365
    168366
    169367/** Start device adding when connection change is detected.
     
    176374 * @return Error code.
    177375 */
    178 static int add_device_phase1_new_fibril(usb_hub_info_t *hub, size_t port,
     376static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,
    179377    usb_speed_t speed)
    180378{
     
    213411}
    214412
    215 /** Process change on a single port.
    216  *
    217  * @param hub Hub to which the port belongs.
    218  * @param port Port index (starting at 1).
    219  */
    220 static void process_port_change(usb_hub_info_t *hub, size_t port)
    221 {
    222         int rc;
    223 
    224         usb_port_status_t port_status;
    225 
    226         rc = get_port_status(&hub->usb_device->ctrl_pipe, port, &port_status);
    227         if (rc != EOK) {
    228                 usb_log_error("Failed to get port %zu status: %s.\n",
    229                     port, str_error(rc));
    230                 return;
    231         }
    232 
    233         /*
    234          * Check exact nature of the change.
    235          */
    236         usb_log_debug("Port %zu change status: %x.\n", port,
    237             (unsigned int) port_status);
    238 
    239         if (usb_port_connect_change(&port_status)) {
    240                 bool device_connected = usb_port_dev_connected(&port_status);
    241                 usb_log_debug("Connection change on port %zu: %s.\n", port,
    242                     device_connected ? "device attached" : "device removed");
    243 
    244                 if (device_connected) {
    245                         rc = add_device_phase1_new_fibril(hub, port,
    246                             usb_port_speed(&port_status));
    247                         if (rc != EOK) {
    248                                 usb_log_error(
    249                                     "Cannot handle change on port %zu: %s.\n",
    250                                     str_error(rc));
    251                         }
    252                 } else {
    253                         usb_hub_removed_device(hub, port);
    254                 }
    255         }
    256 
    257         if (usb_port_overcurrent_change(&port_status)) {
    258                 if (usb_port_over_current(&port_status)) {
    259                         usb_log_warning("Overcurrent on port %zu.\n", port);
    260                         usb_hub_over_current(hub, port);
    261                 } else {
    262                         usb_log_debug("Overcurrent on port %zu autoresolved.\n",
    263                             port);
    264                 }
    265         }
    266 
    267         if (usb_port_reset_completed(&port_status)) {
    268                 usb_log_debug("Port %zu reset complete.\n", port);
    269                 if (usb_port_enabled(&port_status)) {
    270                         /* Finalize device adding. */
    271                         usb_hub_port_t *the_port = hub->ports + port;
    272                         fibril_mutex_lock(&the_port->reset_mutex);
    273                         the_port->reset_completed = true;
    274                         fibril_condvar_broadcast(&the_port->reset_cv);
    275                         fibril_mutex_unlock(&the_port->reset_mutex);
    276                 } else {
    277                         usb_log_warning(
    278                             "Port %zu reset complete but port not enabled.\n",
    279                             port);
    280                 }
    281         }
    282 
    283         usb_port_set_connect_change(&port_status, false);
    284         usb_port_set_reset(&port_status, false);
    285         usb_port_set_reset_completed(&port_status, false);
    286         usb_port_set_dev_connected(&port_status, false);
    287         if (port_status >> 16) {
    288                 usb_log_warning("Unsupported change on port %zu: %x.\n",
    289                     port, (unsigned int) port_status);
    290         }
    291 }
    292 
    293 
    294 /** Callback for polling hub for port changes.
    295  *
    296  * @param dev Device where the change occured.
    297  * @param change_bitmap Bitmap of changed ports.
    298  * @param change_bitmap_size Size of the bitmap in bytes.
    299  * @param arg Custom argument, points to @c usb_hub_info_t.
    300  * @return Whether to continue polling.
    301  */
    302 bool hub_port_changes_callback(usb_device_t *dev,
    303     uint8_t *change_bitmap, size_t change_bitmap_size, void *arg)
    304 {
    305         usb_hub_info_t *hub = (usb_hub_info_t *) arg;
    306 
    307         /* FIXME: check that we received enough bytes. */
    308         if (change_bitmap_size == 0) {
    309                 goto leave;
    310         }
    311 
    312         size_t port;
    313         for (port = 1; port < hub->port_count + 1; port++) {
    314                 bool change = (change_bitmap[port / 8] >> (port % 8)) % 2;
    315                 if (change) {
    316                         process_port_change(hub, port);
    317                 }
    318         }
    319 
    320 
    321 leave:
    322         /* FIXME: proper interval. */
    323         async_usleep(1000 * 1000 * 10 );
    324 
    325         return true;
    326 }
    327 
    328 
    329413/**
    330414 * @}
  • uspace/drv/usbhub/ports.h

    r77223f8 r0748854  
    3636#define DRV_USBHUB_PORTS_H
    3737
    38 #include <ipc/devman.h>
    39 #include <usb/usb.h>
    40 #include <ddf/driver.h>
    41 #include <fibril_synch.h>
    42 
     38#include <usb/devdrv.h>
    4339#include <usb/hub.h>
    4440
    45 #include <usb/pipes.h>
    46 #include <usb/devdrv.h>
     41typedef struct usb_hub_info_t usb_hub_info_t;
    4742
    4843/** Information about single port on a hub. */
     
    7267}
    7368
    74 bool hub_port_changes_callback(usb_device_t *, uint8_t *, size_t, void *);
     69
     70void usb_hub_process_interrupt(usb_hub_info_t * hub,
     71        uint16_t port);
     72
    7573
    7674
  • uspace/drv/usbhub/usbhub.c

    r77223f8 r0748854  
    3737#include <errno.h>
    3838#include <str_error.h>
     39#include <inttypes.h>
    3940
    4041#include <usb_iface.h>
     
    5354#include "usb/classes/classes.h"
    5455
    55 static int usb_hub_trigger_connecting_non_removable_devices(
    56                 usb_hub_info_t * hub, usb_hub_descriptor_t * descriptor);
    57 
     56
     57static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev);
     58
     59static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info);
     60
     61static int usb_hub_set_configuration(usb_hub_info_t * hub_info);
     62
     63static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info);
     64
     65static int usb_process_hub_over_current(usb_hub_info_t * hub_info,
     66    usb_hub_status_t status);
     67
     68static int usb_process_hub_power_change(usb_hub_info_t * hub_info,
     69    usb_hub_status_t status);
     70
     71static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info);
     72
     73
     74/// \TODO malloc checking
    5875
    5976//*********************************************
    6077//
    6178//  hub driver code, initialization
     79//
     80//*********************************************
     81
     82/**
     83 * Initialize hub device driver fibril
     84 *
     85 * Creates hub representation and fibril that periodically checks hub`s status.
     86 * Hub representation is passed to the fibril.
     87 * @param usb_dev generic usb device information
     88 * @return error code
     89 */
     90int usb_hub_add_device(usb_device_t * usb_dev) {
     91        if (!usb_dev) return EINVAL;
     92        usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev);
     93        //create hc connection
     94        usb_log_debug("Initializing USB wire abstraction.\n");
     95        int opResult = usb_hc_connection_initialize_from_device(
     96            &hub_info->connection,
     97            hub_info->usb_device->ddf_dev);
     98        if (opResult != EOK) {
     99                usb_log_error("could not initialize connection to device, "
     100                    "errno %d\n",
     101                    opResult);
     102                free(hub_info);
     103                return opResult;
     104        }
     105
     106        usb_pipe_start_session(hub_info->control_pipe);
     107        //set hub configuration
     108        opResult = usb_hub_set_configuration(hub_info);
     109        if (opResult != EOK) {
     110                usb_log_error("could not set hub configuration, errno %d\n",
     111                    opResult);
     112                free(hub_info);
     113                return opResult;
     114        }
     115        //get port count and create attached_devs
     116        opResult = usb_hub_process_hub_specific_info(hub_info);
     117        if (opResult != EOK) {
     118                usb_log_error("could process hub specific info, errno %d\n",
     119                    opResult);
     120                free(hub_info);
     121                return opResult;
     122        }
     123        usb_pipe_end_session(hub_info->control_pipe);
     124
     125        /// \TODO what is this?
     126        usb_log_debug("Creating `hub' function.\n");
     127        ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,
     128            fun_exposed, "hub");
     129        assert(hub_fun != NULL);
     130        hub_fun->ops = NULL;
     131
     132        opResult = ddf_fun_bind(hub_fun);
     133        assert(opResult == EOK);
     134        opResult = ddf_fun_add_to_class(hub_fun, "hub");
     135        assert(opResult == EOK);
     136
     137        opResult = usb_hub_start_hub_fibril(hub_info);
     138        if(opResult!=EOK)
     139                free(hub_info);
     140        return opResult;
     141}
     142
     143
     144/** Callback for polling hub for changes.
     145 *
     146 * @param dev Device where the change occured.
     147 * @param change_bitmap Bitmap of changed ports.
     148 * @param change_bitmap_size Size of the bitmap in bytes.
     149 * @param arg Custom argument, points to @c usb_hub_info_t.
     150 * @return Whether to continue polling.
     151 */
     152bool hub_port_changes_callback(usb_device_t *dev,
     153    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg) {
     154        usb_hub_info_t *hub = (usb_hub_info_t *) arg;
     155
     156        /* FIXME: check that we received enough bytes. */
     157        if (change_bitmap_size == 0) {
     158                goto leave;
     159        }
     160
     161        bool change;
     162        change = ((uint8_t*) change_bitmap)[0] & 1;
     163        if (change) {
     164                usb_hub_process_global_interrupt(hub);
     165        }
     166
     167        size_t port;
     168        for (port = 1; port < hub->port_count + 1; port++) {
     169                bool change = (change_bitmap[port / 8] >> (port % 8)) % 2;
     170                if (change) {
     171                        usb_hub_process_interrupt(hub, port);
     172                }
     173        }
     174leave:
     175        /* FIXME: proper interval. */
     176        async_usleep(1000 * 1000 * 10);
     177
     178        return true;
     179}
     180
     181/**
     182 * release default address used by given hub
     183 *
     184 * Also unsets hub->is_default_address_used. Convenience wrapper function.
     185 * @note hub->connection MUST be open for communication
     186 * @param hub hub representation
     187 * @return error code
     188 */
     189int usb_hub_release_default_address(usb_hub_info_t * hub) {
     190        int opResult = usb_hc_release_default_address(&hub->connection);
     191        if (opResult != EOK) {
     192                usb_log_error("could not release default address, errno %d\n",
     193                    opResult);
     194                return opResult;
     195        }
     196        hub->is_default_address_used = false;
     197        return EOK;
     198}
     199
     200
     201//*********************************************
     202//
     203//  support functions
    62204//
    63205//*********************************************
     
    71213 */
    72214static usb_hub_info_t * usb_hub_info_create(usb_device_t * usb_dev) {
    73         usb_hub_info_t * result = usb_new(usb_hub_info_t);
    74         if(!result) return NULL;
     215        usb_hub_info_t * result = malloc(sizeof(usb_hub_info_t));
     216        if (!result) return NULL;
    75217        result->usb_device = usb_dev;
    76218        result->status_change_pipe = usb_dev->pipes[0].pipe;
     
    90232 * @return error code
    91233 */
    92 static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info){
     234static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info) {
    93235        // get hub descriptor
    94236        usb_log_debug("creating serialized descriptor\n");
    95237        void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE);
    96238        usb_hub_descriptor_t * descriptor;
    97 
    98         /* this was one fix of some bug, should not be needed anymore
    99          * these lines allow to reset hub once more, it can be used as
    100          * brute-force initialization for non-removable devices
    101         int opResult = usb_request_set_configuration(&result->endpoints.control, 1);
    102         if(opResult!=EOK){
    103                 usb_log_error("could not set default configuration, errno %d",opResult);
    104                 return opResult;
    105         }
    106          */
     239        int opResult;
     240
    107241        size_t received_size;
    108         int opResult = usb_request_get_descriptor(&hub_info->usb_device->ctrl_pipe,
    109                         USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
    110                         USB_DESCTYPE_HUB,
    111                         0, 0, serialized_descriptor,
    112                         USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
    113 
    114         if (opResult != EOK) {
    115                 usb_log_error("failed when receiving hub descriptor, badcode = %d\n",
    116                                 opResult);
     242        opResult = usb_request_get_descriptor(hub_info->control_pipe,
     243            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
     244            USB_DESCTYPE_HUB, 0, 0, serialized_descriptor,
     245            USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
     246
     247        if (opResult != EOK) {
     248                usb_log_error("failed when receiving hub descriptor, "
     249                    "badcode = %d\n",
     250                    opResult);
    117251                free(serialized_descriptor);
    118252                return opResult;
     
    120254        usb_log_debug2("deserializing descriptor\n");
    121255        descriptor = usb_deserialize_hub_desriptor(serialized_descriptor);
    122         if(descriptor==NULL){
     256        if (descriptor == NULL) {
    123257                usb_log_warning("could not deserialize descriptor \n");
    124258                return opResult;
    125259        }
    126         usb_log_debug("setting port count to %d\n",descriptor->ports_count);
     260        usb_log_debug("setting port count to %d\n", descriptor->ports_count);
    127261        hub_info->port_count = descriptor->ports_count;
    128         hub_info->ports = malloc(sizeof(usb_hub_port_t) * (hub_info->port_count+1));
     262        /// \TODO this is not semantically correct
     263        hub_info->ports = malloc(
     264            sizeof (usb_hub_port_t) * (hub_info->port_count + 1));
    129265        size_t port;
    130266        for (port = 0; port < hub_info->port_count + 1; port++) {
    131267                usb_hub_port_init(&hub_info->ports[port]);
    132268        }
    133         //handle non-removable devices
    134         usb_hub_trigger_connecting_non_removable_devices(hub_info, descriptor);
    135269        usb_log_debug2("freeing data\n");
    136270        free(serialized_descriptor);
     
    139273        return EOK;
    140274}
     275
    141276/**
    142277 * Set configuration of hub
     
    147282 * @return error code
    148283 */
    149 static int usb_hub_set_configuration(usb_hub_info_t * hub_info){
     284static int usb_hub_set_configuration(usb_hub_info_t * hub_info) {
    150285        //device descriptor
    151286        usb_standard_device_descriptor_t *std_descriptor
     
    153288        usb_log_debug("hub has %d configurations\n",
    154289            std_descriptor->configuration_count);
    155         if(std_descriptor->configuration_count<1){
     290        if (std_descriptor->configuration_count < 1) {
    156291                usb_log_error("there are no configurations available\n");
    157292                return EINVAL;
     
    173308        }
    174309        usb_log_debug("\tused configuration %d\n",
    175                         config_descriptor->configuration_number);
     310            config_descriptor->configuration_number);
    176311
    177312        return EOK;
     
    179314
    180315/**
    181  * Initialize hub device driver fibril
    182  *
    183  * Creates hub representation and fibril that periodically checks hub`s status.
    184  * Hub representation is passed to the fibril.
    185  * @param usb_dev generic usb device information
    186  * @return error code
    187  */
    188 int usb_hub_add_device(usb_device_t * usb_dev){
    189         if(!usb_dev) return EINVAL;
    190         usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev);
    191         //create hc connection
    192         usb_log_debug("Initializing USB wire abstraction.\n");
    193         int opResult = usb_hc_connection_initialize_from_device(
    194                         &hub_info->connection,
    195                         hub_info->usb_device->ddf_dev);
    196         if(opResult != EOK){
    197                 usb_log_error("could not initialize connection to device, errno %d\n",
    198                                 opResult);
    199                 free(hub_info);
    200                 return opResult;
    201         }
    202        
    203         usb_pipe_start_session(hub_info->control_pipe);
    204         //set hub configuration
    205         opResult = usb_hub_set_configuration(hub_info);
    206         if(opResult!=EOK){
    207                 usb_log_error("could not set hub configuration, errno %d\n",opResult);
    208                 free(hub_info);
    209                 return opResult;
    210         }
    211         //get port count and create attached_devs
    212         opResult = usb_hub_process_hub_specific_info(hub_info);
    213         if(opResult!=EOK){
    214                 usb_log_error("could not set hub configuration, errno %d\n",opResult);
    215                 free(hub_info);
    216                 return opResult;
    217         }
    218         usb_pipe_end_session(hub_info->control_pipe);
    219 
    220 
    221         /// \TODO what is this?
    222         usb_log_debug("Creating `hub' function.\n");
    223         ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,
    224                         fun_exposed, "hub");
    225         assert(hub_fun != NULL);
    226         hub_fun->ops = NULL;
    227 
    228         int rc = ddf_fun_bind(hub_fun);
    229         assert(rc == EOK);
    230         rc = ddf_fun_add_to_class(hub_fun, "hub");
    231         assert(rc == EOK);
    232 
     316 * create and start fibril with hub control loop
     317 *
     318 * Before the fibril is started, the control pipe and host controller
     319 * connection of the hub is open.
     320 *
     321 * @param hub_info hub representing structure
     322 * @return error code
     323 */
     324static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info){
    233325        /*
    234326         * The processing will require opened control pipe and connection
     
    239331         * auto destruction, this could work better.
    240332         */
    241         rc = usb_pipe_start_session(&usb_dev->ctrl_pipe);
     333        int rc = usb_pipe_start_session(hub_info->control_pipe);
    242334        if (rc != EOK) {
    243335                usb_log_error("Failed to start session on control pipe: %s.\n",
    244336                    str_error(rc));
    245                 goto leave;
     337                return rc;
    246338        }
    247339        rc = usb_hc_connection_open(&hub_info->connection);
    248340        if (rc != EOK) {
    249                 usb_pipe_end_session(&usb_dev->ctrl_pipe);
     341                usb_pipe_end_session(hub_info->control_pipe);
    250342                usb_log_error("Failed to open connection to HC: %s.\n",
    251343                    str_error(rc));
    252                 goto leave;
     344                return rc;
    253345        }
    254346
    255347        rc = usb_device_auto_poll(hub_info->usb_device, 0,
    256             hub_port_changes_callback, ((hub_info->port_count+1) / 8) + 1,
     348            hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1,
    257349            NULL, hub_info);
    258350        if (rc != EOK) {
     
    266358            hub_info->usb_device->ddf_dev->name, hub_info->port_count);
    267359        return EOK;
    268 
    269 leave:
    270         free(hub_info);
    271 
    272         return rc;
    273 }
    274 
    275 
    276 //*********************************************
    277 //
    278 //  hub driver code, main loop and port handling
    279 //
    280 //*********************************************
    281 
    282 /**
    283  * triggers actions to connect non0removable devices
    284  *
    285  * This will trigger operations leading to activated non-removable device.
    286  * Control pipe of the hub must be open fo communication.
    287  * @param hub hub representation
    288  * @param descriptor usb hub descriptor
    289  * @return error code
    290  */
    291 static int usb_hub_trigger_connecting_non_removable_devices(usb_hub_info_t * hub,
    292                 usb_hub_descriptor_t * descriptor)
    293 {
    294         usb_log_info("attaching non-removable devices(if any)\n");
    295         usb_device_request_setup_packet_t request;
     360}
     361
     362//*********************************************
     363//
     364//  change handling functions
     365//
     366//*********************************************
     367
     368
     369/**
     370 * process hub over current change
     371 *
     372 * This means either to power off the hub or power it on.
     373 * @param hub_info hub instance
     374 * @param status hub status bitmask
     375 * @return error code
     376 */
     377static int usb_process_hub_over_current(usb_hub_info_t * hub_info,
     378    usb_hub_status_t status) {
    296379        int opResult;
    297         size_t rcvd_size;
    298         usb_port_status_t status;
    299         uint8_t * non_removable_dev_bitmap = descriptor->devices_removable;
    300         int port;
    301         for(port=1;port<=descriptor->ports_count;++port){
    302                 bool is_non_removable =
    303                                 ((non_removable_dev_bitmap[port/8]) >> (port%8)) %2;
    304                 if(is_non_removable){
    305                         usb_log_debug("non-removable device on port %d\n",port);
    306                         usb_hub_set_port_status_request(&request, port);
    307                         opResult = usb_pipe_control_read(
    308                                         hub->control_pipe,
    309                                         &request, sizeof(usb_device_request_setup_packet_t),
    310                                         &status, 4, &rcvd_size
    311                                         );
     380        if (usb_hub_is_status(status,USB_HUB_FEATURE_HUB_OVER_CURRENT)){
     381                opResult = usb_hub_clear_feature(hub_info->control_pipe,
     382                    USB_HUB_FEATURE_HUB_LOCAL_POWER);
     383                if (opResult != EOK) {
     384                        usb_log_error("cannot power off hub: %d\n",
     385                            opResult);
     386                }
     387        } else {
     388                opResult = usb_hub_set_feature(hub_info->control_pipe,
     389                    USB_HUB_FEATURE_HUB_LOCAL_POWER);
     390                if (opResult != EOK) {
     391                        usb_log_error("cannot power on hub: %d\n",
     392                            opResult);
     393                }
     394        }
     395        return opResult;
     396}
     397
     398/**
     399 * process hub power change
     400 *
     401 * If the power has been lost, reestablish it.
     402 * If it was reestablished, re-power all ports.
     403 * @param hub_info hub instance
     404 * @param status hub status bitmask
     405 * @return error code
     406 */
     407static int usb_process_hub_power_change(usb_hub_info_t * hub_info,
     408    usb_hub_status_t status) {
     409        int opResult;
     410        if (usb_hub_is_status(status,USB_HUB_FEATURE_HUB_LOCAL_POWER)) {
     411                //restart power on hub
     412                opResult = usb_hub_set_feature(hub_info->control_pipe,
     413                    USB_HUB_FEATURE_HUB_LOCAL_POWER);
     414                if (opResult != EOK) {
     415                        usb_log_error("cannot power on hub: %d\n",
     416                            opResult);
     417                }
     418        } else {//power reestablished on hub- restart ports
     419                size_t port;
     420                for (port = 0; port < hub_info->port_count; ++port) {
     421                        opResult = usb_hub_set_port_feature(
     422                            hub_info->control_pipe,
     423                            port, USB_HUB_FEATURE_PORT_POWER);
    312424                        if (opResult != EOK) {
    313                                 usb_log_error("could not get port status of port %d errno:%d\n",
    314                                                 port, opResult);
    315                                 return opResult;
    316                         }
    317                         //set the status change bit, so it will be noticed in driver loop
    318                         if(usb_port_dev_connected(&status)){
    319                                 usb_hub_set_disable_port_feature_request(&request, port,
    320                                                 USB_HUB_FEATURE_PORT_CONNECTION);
    321                                 opResult = usb_pipe_control_read(
    322                                                 hub->control_pipe,
    323                                                 &request, sizeof(usb_device_request_setup_packet_t),
    324                                                 &status, 4, &rcvd_size
    325                                                 );
    326                                 if (opResult != EOK) {
    327                                         usb_log_warning(
    328                                                         "could not clear port connection on port %d errno:%d\n",
    329                                                         port, opResult);
    330                                 }
    331                                 usb_log_debug("cleared port connection\n");
    332                                 usb_hub_set_enable_port_feature_request(&request, port,
    333                                                 USB_HUB_FEATURE_PORT_ENABLE);
    334                                 opResult = usb_pipe_control_read(
    335                                                 hub->control_pipe,
    336                                                 &request, sizeof(usb_device_request_setup_packet_t),
    337                                                 &status, 4, &rcvd_size
    338                                                 );
    339                                 if (opResult != EOK) {
    340                                         usb_log_warning(
    341                                                         "could not set port enabled on port %d errno:%d\n",
    342                                                         port, opResult);
    343                                 }
    344                                 usb_log_debug("port set to enabled - should lead to connection change\n");
     425                                usb_log_error("cannot power on port %d;  %d\n",
     426                                    port, opResult);
    345427                        }
    346428                }
    347429        }
    348         /// \TODO this is just a debug code
    349         for(port=1;port<=descriptor->ports_count;++port){
    350                 bool is_non_removable =
    351                                 ((non_removable_dev_bitmap[port/8]) >> (port%8)) %2;
    352                 if(is_non_removable){
    353                         usb_log_debug("port %d is non-removable\n",port);
    354                         usb_port_status_t status;
    355                         size_t rcvd_size;
    356                         usb_device_request_setup_packet_t request;
    357                         //int opResult;
    358                         usb_hub_set_port_status_request(&request, port);
    359                         //endpoint 0
    360                         opResult = usb_pipe_control_read(
    361                                         hub->control_pipe,
    362                                         &request, sizeof(usb_device_request_setup_packet_t),
    363                                         &status, 4, &rcvd_size
    364                                         );
    365                         if (opResult != EOK) {
    366                                 usb_log_error("could not get port status %d\n",opResult);
    367                         }
    368                         if (rcvd_size != sizeof (usb_port_status_t)) {
    369                                 usb_log_error("received status has incorrect size\n");
    370                         }
    371                         //something connected/disconnected
    372                         if (usb_port_connect_change(&status)) {
    373                                 usb_log_debug("some connection changed\n");
    374                         }
    375                         usb_log_debug("status: %s\n",usb_debug_str_buffer(
    376                                         (uint8_t *)&status,4,4));
    377                 }
    378         }
    379         return EOK;
    380 }
    381 
    382 
    383 /**
    384  * release default address used by given hub
    385  *
    386  * Also unsets hub->is_default_address_used. Convenience wrapper function.
    387  * @note hub->connection MUST be open for communication
    388  * @param hub hub representation
    389  * @return error code
    390  */
    391 static int usb_hub_release_default_address(usb_hub_info_t * hub){
    392         int opResult = usb_hc_release_default_address(&hub->connection);
    393         if(opResult!=EOK){
    394                 usb_log_error("could not release default address, errno %d\n",opResult);
    395                 return opResult;
    396         }
    397         hub->is_default_address_used = false;
    398         return EOK;
    399 }
    400 
    401 /**
    402  * routine called when a device on port has been removed
    403  *
    404  * If the device on port had default address, it releases default address.
    405  * Otherwise does not do anything, because DDF does not allow to remove device
    406  * from it`s device tree.
    407  * @param hub hub representation
    408  * @param port port number, starting from 1
    409  */
    410 void usb_hub_removed_device(
    411     usb_hub_info_t * hub,uint16_t port) {
    412 
    413         int opResult = usb_hub_clear_port_feature(hub->control_pipe,
    414                                 port, USB_HUB_FEATURE_C_PORT_CONNECTION);
    415         if(opResult != EOK){
    416                 usb_log_warning("could not clear port-change-connection flag\n");
    417         }
    418         /** \TODO remove device from device manager - not yet implemented in
    419          * devide manager
    420          */
    421        
    422         //close address
    423         if(hub->ports[port].attached_device.address >= 0){
    424                 /*uncomment this code to use it when DDF allows device removal
    425                 opResult = usb_hc_unregister_device(
    426                                 &hub->connection, hub->attached_devs[port].address);
    427                 if(opResult != EOK) {
    428                         dprintf(USB_LOG_LEVEL_WARNING, "could not release address of " \
    429                             "removed device: %d", opResult);
    430                 }
    431                 hub->attached_devs[port].address = 0;
    432                 hub->attached_devs[port].handle = 0;
    433                  */
    434         }else{
    435                 usb_log_warning("this is strange, disconnected device had no address\n");
    436                 //device was disconnected before it`s port was reset - return default address
    437                 usb_hub_release_default_address(hub);
    438         }
    439 }
    440 
    441 
    442 /**
    443  * Process over current condition on port.
    444  *
    445  * Turn off the power on the port.
    446  *
    447  * @param hub hub representation
    448  * @param port port number, starting from 1
    449  */
    450 void usb_hub_over_current( usb_hub_info_t * hub,
    451                 uint16_t port){
     430        return opResult;
     431}
     432
     433/**
     434 * process hub interrupts
     435 *
     436 * The change can be either in the over-current condition or
     437 * local-power lost condition.
     438 * @param hub_info hub instance
     439 */
     440static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info) {
     441        usb_log_debug("global interrupt on a hub\n");
     442        usb_pipe_t *pipe = hub_info->control_pipe;
    452443        int opResult;
    453         opResult = usb_hub_clear_port_feature(hub->control_pipe,
    454             port, USB_HUB_FEATURE_PORT_POWER);
    455         if(opResult!=EOK){
    456                 usb_log_error("cannot power off port %d;  %d\n",
    457                                 port, opResult);
    458         }
    459 }
    460 
     444
     445        usb_port_status_t status;
     446        size_t rcvd_size;
     447        usb_device_request_setup_packet_t request;
     448        //int opResult;
     449        usb_hub_set_hub_status_request(&request);
     450        //endpoint 0
     451
     452        opResult = usb_pipe_control_read(
     453            pipe,
     454            &request, sizeof (usb_device_request_setup_packet_t),
     455            &status, 4, &rcvd_size
     456            );
     457        if (opResult != EOK) {
     458                usb_log_error("could not get hub status\n");
     459                return;
     460        }
     461        if (rcvd_size != sizeof (usb_port_status_t)) {
     462                usb_log_error("received status has incorrect size\n");
     463                return;
     464        }
     465        //port reset
     466        if (
     467            usb_hub_is_status(status,16+USB_HUB_FEATURE_C_HUB_OVER_CURRENT)) {
     468                usb_process_hub_over_current(hub_info, status);
     469        }
     470        if (
     471            usb_hub_is_status(status,16+USB_HUB_FEATURE_C_HUB_LOCAL_POWER)) {
     472                usb_process_hub_power_change(hub_info, status);
     473        }
     474}
    461475
    462476/**
  • uspace/drv/usbhub/usbhub.h

    r77223f8 r0748854  
    3737
    3838#include <ipc/devman.h>
    39 #include <usb/usb.h>
    4039#include <ddf/driver.h>
    4140
    42 #define NAME "usbhub"
    43 
    4441#include <usb/hub.h>
     42#include <usb/classes/hub.h>
    4543
    4644#include <usb/pipes.h>
    4745#include <usb/devdrv.h>
     46
     47#include <fibril_synch.h>
     48
     49#define NAME "usbhub"
    4850
    4951#include "ports.h"
     
    5254
    5355/** Information about attached hub. */
    54 typedef struct {
     56struct usb_hub_info_t{
    5557        /** Number of ports. */
    5658        size_t port_count;
    5759
    58         /** Ports. */
     60        /** attached device handles, for each port one */
    5961        usb_hub_port_t *ports;
    60        
     62
    6163        /** connection to hcd */
    6264        usb_hc_connection_t connection;
     
    8789        /** generic usb device data*/
    8890        usb_device_t * usb_device;
    89 } usb_hub_info_t;
     91};
    9092
    91 /**
    92  * function running the hub-controlling loop.
    93  * @param hub_info_param hub info pointer
    94  */
    95 int usb_hub_control_loop(void * hub_info_param);
    96 
    97 /**
    98  * Check changes on specified hub
    99  * @param hub_info_param pointer to usb_hub_info_t structure
    100  * @return error code if there is problem when initializing communication with
    101  * hub, EOK otherwise
    102  */
    103 int usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param);
    104 
    105 void usb_hub_removed_device(usb_hub_info_t *, uint16_t);
    106 void usb_hub_over_current(usb_hub_info_t *, uint16_t);
     93//int usb_hub_control_loop(void * hub_info_param);
    10794
    10895int usb_hub_add_device(usb_device_t * usb_dev);
     96
     97bool hub_port_changes_callback(usb_device_t *dev,
     98    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg);
     99
     100int usb_hub_release_default_address(usb_hub_info_t * hub);
    109101
    110102#endif
  • uspace/drv/usbhub/usbhub_private.h

    r77223f8 r0748854  
    5454//
    5555//************
    56 #define usb_new(type) (type*)malloc(sizeof(type))
    5756
    5857
    59 /**
    60  * Create hub structure instance
    61  *
    62  * Set the address and port count information most importantly.
    63  *
    64  * @param device
    65  * @param hc host controller phone
    66  * @return
    67  */
    6858usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device);
    6959
     
    110100
    111101/**
     102 * Clear feature on hub port.
     103 *
     104 * @param hc Host controller telephone
     105 * @param address Hub address
     106 * @param port_index Port
     107 * @param feature Feature selector
     108 * @return Operation result
     109 */
     110static inline int usb_hub_set_port_feature(usb_pipe_t *pipe,
     111    int port_index,
     112    usb_hub_class_feature_t feature) {
     113
     114        usb_device_request_setup_packet_t clear_request = {
     115                .request_type = USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE,
     116                .request = USB_DEVREQ_SET_FEATURE,
     117                .length = 0,
     118                .index = port_index
     119        };
     120        clear_request.value = feature;
     121        return usb_pipe_control_write(pipe, &clear_request,
     122            sizeof(clear_request), NULL, 0);
     123}
     124
     125
     126/**
     127 * Clear feature on hub port.
     128 *
     129 * @param pipe pipe to hub control endpoint
     130 * @param feature Feature selector
     131 * @return Operation result
     132 */
     133static inline int usb_hub_clear_feature(usb_pipe_t *pipe,
     134    usb_hub_class_feature_t feature) {
     135
     136        usb_device_request_setup_packet_t clear_request = {
     137                .request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,
     138                .request = USB_DEVREQ_CLEAR_FEATURE,
     139                .length = 0,
     140                .index = 0
     141        };
     142        clear_request.value = feature;
     143        return usb_pipe_control_write(pipe, &clear_request,
     144            sizeof(clear_request), NULL, 0);
     145}
     146
     147/**
     148 * Clear feature on hub port.
     149 *
     150 * @param pipe pipe to hub control endpoint
     151 * @param feature Feature selector
     152 * @return Operation result
     153 */
     154static inline int usb_hub_set_feature(usb_pipe_t *pipe,
     155    usb_hub_class_feature_t feature) {
     156
     157        usb_device_request_setup_packet_t clear_request = {
     158                .request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,
     159                .request = USB_DEVREQ_SET_FEATURE,
     160                .length = 0,
     161                .index = 0
     162        };
     163        clear_request.value = feature;
     164        return usb_pipe_control_write(pipe, &clear_request,
     165            sizeof(clear_request), NULL, 0);
     166}
     167
     168/**
    112169 * create uint8_t array with serialized descriptor
    113170 *
  • uspace/drv/usbhub/utils.c

    r77223f8 r0748854  
    6060        size_t size = 7;
    6161        //variable size according to port count
    62         size_t var_size = descriptor->ports_count / 8 + ((descriptor->ports_count % 8 > 0) ? 1 : 0);
     62        size_t var_size = (descriptor->ports_count+7)/8;
    6363        size += 2 * var_size;
    64         uint8_t * result = (uint8_t*) malloc(size);
     64        uint8_t * result = malloc(size);
    6565        //size
    6666        result[0] = size;
     
    8484}
    8585
    86 usb_hub_descriptor_t * usb_deserialize_hub_desriptor(void * serialized_descriptor) {
    87         uint8_t * sdescriptor = (uint8_t*) serialized_descriptor;
     86usb_hub_descriptor_t * usb_deserialize_hub_desriptor(
     87void * serialized_descriptor) {
     88        uint8_t * sdescriptor = serialized_descriptor;
    8889
    8990        if (sdescriptor[1] != USB_DESCTYPE_HUB) {
    90                 usb_log_warning("trying to deserialize wrong descriptor %x\n",sdescriptor[1]);
     91                usb_log_warning("trying to deserialize wrong descriptor %x\n",
     92                    sdescriptor[1]);
    9193                return NULL;
    9294        }
    9395
    94         usb_hub_descriptor_t * result = usb_new(usb_hub_descriptor_t);
     96        usb_hub_descriptor_t * result = malloc(sizeof(usb_hub_descriptor_t));
    9597       
    9698
     
    100102        result->pwr_on_2_good_time = sdescriptor[5];
    101103        result->current_requirement = sdescriptor[6];
    102         size_t var_size = result->ports_count / 8 + ((result->ports_count % 8 > 0)
    103                         ? 1 : 0);
     104        size_t var_size = (result->ports_count+7) / 8;
    104105        result->devices_removable = (uint8_t*) malloc(var_size);
    105106
  • uspace/lib/usb/include/usb/classes/hub.h

    r77223f8 r0748854  
    4343 */
    4444typedef enum {
     45        USB_HUB_FEATURE_HUB_LOCAL_POWER = 0,
     46        USB_HUB_FEATURE_HUB_OVER_CURRENT = 1,
    4547        USB_HUB_FEATURE_C_HUB_LOCAL_POWER = 0,
    4648        USB_HUB_FEATURE_C_HUB_OVER_CURRENT = 1,
     
    5961        /* USB_HUB_FEATURE_ = , */
    6062} usb_hub_class_feature_t;
     63
    6164
    6265/** Header of standard hub descriptor without the "variadic" part. */
  • uspace/lib/usb/include/usb/host/device_keeper.h

    r77223f8 r0748854  
    7171void usb_device_keeper_init(usb_device_keeper_t *instance);
    7272
    73 void usb_device_keeper_add_ep(
    74     usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep);
    75 void usb_device_keeper_del_ep(
    76     usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep);
    77 
    7873void usb_device_keeper_reserve_default_address(
    7974    usb_device_keeper_t *instance, usb_speed_t speed);
  • uspace/lib/usb/include/usb/host/endpoint.h

    r77223f8 r0748854  
    5454        fibril_condvar_t avail;
    5555        volatile bool active;
    56         link_t same_device_eps;
    5756} endpoint_t;
    5857
     
    7170void endpoint_toggle_set(endpoint_t *instance, int toggle);
    7271
    73 void endpoint_toggle_reset(link_t *ep);
    74 
    75 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn);
    76 
     72void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target);
    7773#endif
    7874/**
  • uspace/lib/usb/include/usb/host/usb_endpoint_manager.h

    r77223f8 r0748854  
    7878    size_t *bw);
    7979
     80void usb_endpoint_manager_reset_if_need(
     81    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data);
    8082#endif
    8183/**
  • uspace/lib/usb/src/host/device_keeper.c

    r77223f8 r0748854  
    5454        for (; i < USB_ADDRESS_COUNT; ++i) {
    5555                instance->devices[i].occupied = false;
    56                 instance->devices[i].control_used = 0;
    5756                instance->devices[i].handle = 0;
    5857                instance->devices[i].speed = USB_SPEED_MAX;
    59                 list_initialize(&instance->devices[i].endpoints);
    6058        }
    6159        // TODO: is this hack enough?
    6260        // (it is needed to allow smooth registration at default address)
    6361        instance->devices[0].occupied = true;
    64 }
    65 /*----------------------------------------------------------------------------*/
    66 void usb_device_keeper_add_ep(
    67     usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep)
    68 {
    69         assert(instance);
    70         fibril_mutex_lock(&instance->guard);
    71         assert(instance->devices[address].occupied);
    72         list_append(&ep->same_device_eps, &instance->devices[address].endpoints);
    73         fibril_mutex_unlock(&instance->guard);
    74 }
    75 /*----------------------------------------------------------------------------*/
    76 void usb_device_keeper_del_ep(
    77     usb_device_keeper_t *instance, usb_address_t address, endpoint_t *ep)
    78 {
    79         assert(instance);
    80         fibril_mutex_lock(&instance->guard);
    81         assert(instance->devices[address].occupied);
    82         list_remove(&ep->same_device_eps);
    83         list_initialize(&ep->same_device_eps);
    84         fibril_mutex_unlock(&instance->guard);
    8562}
    8663/*----------------------------------------------------------------------------*/
     
    11794}
    11895/*----------------------------------------------------------------------------*/
    119 /** Check setup packet data for signs of toggle reset.
    120  *
    121  * @param[in] instance Device keeper structure to use.
    122  * @param[in] target Device to receive setup packet.
    123  * @param[in] data Setup packet data.
    124  *
    125  * Really ugly one.
    126  */
    127 void usb_device_keeper_reset_if_need(
    128     usb_device_keeper_t *instance, usb_target_t target, const uint8_t *data)
    129 {
    130         assert(instance);
    131         fibril_mutex_lock(&instance->guard);
    132         if (target.endpoint > 15 || target.endpoint < 0
    133             || target.address >= USB_ADDRESS_COUNT || target.address < 0
    134             || !instance->devices[target.address].occupied) {
    135                 fibril_mutex_unlock(&instance->guard);
    136                 usb_log_error("Invalid data when checking for toggle reset.\n");
    137                 return;
    138         }
    139 
    140         switch (data[1])
    141         {
    142         case 0x01: /*clear feature*/
    143                 /* recipient is endpoint, value is zero (ENDPOINT_STALL) */
    144                 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
    145                         link_t *current =
    146                             instance->devices[target.address].endpoints.next;
    147                         while (current !=
    148                            &instance->devices[target.address].endpoints)
    149                         {
    150                         /* endpoint number is < 16, thus first byte is enough */
    151                                 endpoint_toggle_reset_filtered(
    152                                     current, data[4]);
    153                                 current = current->next;
    154                         }
    155                 }
    156         break;
    157 
    158         case 0x9: /* set configuration */
    159         case 0x11: /* set interface */
    160                 /* target must be device */
    161                 if ((data[0] & 0xf) == 0) {
    162                         link_t *current =
    163                             instance->devices[target.address].endpoints.next;
    164                         while (current !=
    165                            &instance->devices[target.address].endpoints)
    166                         {
    167                                 endpoint_toggle_reset(current);
    168                                 current = current->next;
    169                         }
    170                 }
    171         break;
    172         }
    173         fibril_mutex_unlock(&instance->guard);
    174 }
    17596/*----------------------------------------------------------------------------*/
    17697/** Get a free USB address
  • uspace/lib/usb/src/host/endpoint.c

    r77223f8 r0748854  
    5353        fibril_mutex_initialize(&instance->guard);
    5454        fibril_condvar_initialize(&instance->avail);
    55         link_initialize(&instance->same_device_eps);
    5655        return EOK;
    5756}
     
    6160        assert(instance);
    6261        assert(!instance->active);
    63         list_remove(&instance->same_device_eps);
    6462        free(instance);
    6563}
     
    9795}
    9896/*----------------------------------------------------------------------------*/
    99 void endpoint_toggle_reset(link_t *ep)
     97void endpoint_toggle_reset_filtered(endpoint_t *instance, usb_target_t target)
    10098{
    101         endpoint_t *instance =
    102             list_get_instance(ep, endpoint_t, same_device_eps);
    10399        assert(instance);
    104         instance->toggle = 0;
    105 }
    106 /*----------------------------------------------------------------------------*/
    107 void endpoint_toggle_reset_filtered(link_t *ep, usb_endpoint_t epn)
    108 {
    109         endpoint_t *instance =
    110             list_get_instance(ep, endpoint_t, same_device_eps);
    111         assert(instance);
    112         if (instance->endpoint == epn)
     100        if (instance->address == target.address &&
     101            instance->endpoint == target.endpoint)
    113102                instance->toggle = 0;
    114103}
  • uspace/lib/usb/src/host/usb_endpoint_manager.c

    r77223f8 r0748854  
    3131#include <errno.h>
    3232
     33#include <usb/debug.h>
    3334#include <usb/host/usb_endpoint_manager.h>
    3435
     
    8081        endpoint_destroy(node->ep);
    8182        free(node);
     83}
     84/*----------------------------------------------------------------------------*/
     85static void node_toggle_reset_filtered(link_t *item, void *arg)
     86{
     87        assert(item);
     88        node_t *node = hash_table_get_instance(item, node_t, link);
     89        usb_target_t *target = arg;
     90        endpoint_toggle_reset_filtered(node->ep, *target);
    8291}
    8392/*----------------------------------------------------------------------------*/
     
    230239        return node->ep;
    231240}
     241/*----------------------------------------------------------------------------*/
     242/** Check setup packet data for signs of toggle reset.
     243 *
     244 * @param[in] instance Device keeper structure to use.
     245 * @param[in] target Device to receive setup packet.
     246 * @param[in] data Setup packet data.
     247 *
     248 * Really ugly one.
     249 */
     250void usb_endpoint_manager_reset_if_need(
     251    usb_endpoint_manager_t *instance, usb_target_t target, const uint8_t *data)
     252{
     253        assert(instance);
     254        if (target.endpoint > 15 || target.endpoint < 0
     255            || target.address >= USB11_ADDRESS_MAX || target.address < 0) {
     256                usb_log_error("Invalid data when checking for toggle reset.\n");
     257                return;
     258        }
     259
     260        switch (data[1])
     261        {
     262        case 0x01: /*clear feature*/
     263                /* recipient is endpoint, value is zero (ENDPOINT_STALL) */
     264                if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) {
     265                        /* endpoint number is < 16, thus first byte is enough */
     266                        usb_target_t reset_target =
     267                            { .address = target.address, data[4] };
     268                        fibril_mutex_lock(&instance->guard);
     269                        hash_table_apply(&instance->ep_table,
     270                            node_toggle_reset_filtered, &reset_target);
     271                        fibril_mutex_unlock(&instance->guard);
     272                }
     273        break;
     274
     275        case 0x9: /* set configuration */
     276        case 0x11: /* set interface */
     277                /* target must be device */
     278                if ((data[0] & 0xf) == 0) {
     279                        usb_target_t reset_target =
     280                            { .address = target.address, 0 };
     281                        fibril_mutex_lock(&instance->guard);
     282                        hash_table_apply(&instance->ep_table,
     283                            node_toggle_reset_filtered, &reset_target);
     284                        fibril_mutex_unlock(&instance->guard);
     285                }
     286        break;
     287        }
     288}
Note: See TracChangeset for help on using the changeset viewer.