Changeset 3f3afb9 in mainline


Ignore:
Timestamp:
2011-04-11T20:38:37Z (14 years ago)
Author:
Matus Dekanek <smekideki@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1324ff3, a39cfb8
Parents:
58226b4 (diff), d91645ab (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

forgotten hub port powering

Location:
uspace
Files:
5 added
48 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/ohci/batch.c

    r58226b4 r3f3afb9  
    5151static void batch_control(usb_transfer_batch_t *instance,
    5252    usb_direction_t data_dir, usb_direction_t status_dir);
     53static void batch_data(usb_transfer_batch_t *instance);
    5354static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);
    5455static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);
     
    134135        assert(data);
    135136        size_t tds = data->td_count - 1;
    136         usb_log_debug2("Batch(%p) checking %d td(s) for completion.\n",
     137        usb_log_debug("Batch(%p) checking %d td(s) for completion.\n",
    137138            instance, tds);
     139        usb_log_debug("ED: %x:%x:%x:%x.\n",
     140            data->ed->status, data->ed->td_head, data->ed->td_tail,
     141            data->ed->next);
    138142        size_t i = 0;
    139143        for (; i < tds; ++i) {
    140                 if (!td_is_finished(&data->tds[i]))
     144                usb_log_debug("TD %d: %x:%x:%x:%x.\n", i,
     145                    data->tds[i].status, data->tds[i].cbp, data->tds[i].next,
     146                    data->tds[i].be);
     147                if (!td_is_finished(&data->tds[i])) {
    141148                        return false;
     149                }
    142150                instance->error = td_error(&data->tds[i]);
    143151                /* FIXME: calculate real transfered size */
     
    177185        assert(instance->direction == USB_DIRECTION_IN);
    178186        instance->next_step = batch_call_in_and_dispose;
    179         /* TODO: implement */
     187        batch_data(instance);
    180188        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    181189}
     
    189197            instance->buffer_size);
    190198        instance->next_step = batch_call_out_and_dispose;
    191         /* TODO: implement */
     199        batch_data(instance);
    192200        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    193201}
     
    198206        instance->direction = USB_DIRECTION_IN;
    199207        instance->next_step = batch_call_in_and_dispose;
    200         /* TODO: implement */
     208        batch_data(instance);
    201209        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    202210}
     
    207215        instance->direction = USB_DIRECTION_IN;
    208216        instance->next_step = batch_call_in_and_dispose;
    209         /* TODO: implement */
     217        batch_data(instance);
    210218        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    211219}
     
    227235        ed_init(data->ed, instance->ep);
    228236        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);
     237        usb_log_debug("Created ED(%p): %x:%x:%x:%x.\n", data->ed,
     238            data->ed->status, data->ed->td_tail, data->ed->td_head,
     239            data->ed->next);
    231240        int toggle = 0;
    232241        /* setup stage */
     
    267276}
    268277/*----------------------------------------------------------------------------*/
     278void batch_data(usb_transfer_batch_t *instance)
     279{
     280        assert(instance);
     281        ohci_batch_t *data = instance->private_data;
     282        assert(data);
     283        ed_init(data->ed, instance->ep);
     284        ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]);
     285        usb_log_debug("Created ED(%p): %x:%x:%x:%x.\n", data->ed,
     286            data->ed->status, data->ed->td_tail, data->ed->td_head,
     287            data->ed->next);
     288
     289        /* data stage */
     290        size_t td_current = 0;
     291        size_t remain_size = instance->buffer_size;
     292        char *transfer_buffer = instance->transport_buffer;
     293        while (remain_size > 0) {
     294                size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ?
     295                    OHCI_TD_MAX_TRANSFER : remain_size;
     296
     297                td_init(&data->tds[td_current], instance->ep->direction,
     298                    transfer_buffer, transfer_size, -1);
     299                td_set_next(&data->tds[td_current], &data->tds[td_current + 1]);
     300                usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n",
     301                    data->tds[td_current].status, data->tds[td_current].cbp,
     302                    data->tds[td_current].next, data->tds[td_current].be);
     303
     304                transfer_buffer += transfer_size;
     305                remain_size -= transfer_size;
     306                assert(td_current < data->td_count);
     307                ++td_current;
     308        }
     309}
     310/*----------------------------------------------------------------------------*/
    269311/** Helper function calls callback and correctly disposes of batch structure.
    270312 *
  • uspace/drv/ohci/hc.c

    r58226b4 r3f3afb9  
    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        fibril_mutex_initialize(&instance->guard);
     116
     117        rh_init(&instance->rh, dev, instance->registers);
     118
    110119        if (!interrupts) {
    111120                instance->interrupt_emulator =
     
    114123        }
    115124
    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 */
    124125        return EOK;
    125126}
     
    135136        }
    136137
    137         transfer_list_add_batch(
    138             instance->transfers[batch->transfer_type], batch);
    139 
     138        fibril_mutex_lock(&instance->guard);
    140139        switch (batch->transfer_type) {
    141140        case USB_TRANSFER_CONTROL:
     141                instance->registers->control &= ~C_CLE;
     142                transfer_list_add_batch(
     143                    instance->transfers[batch->transfer_type], batch);
    142144                instance->registers->command_status |= CS_CLF;
     145                usb_log_debug2("Set CS control transfer filled: %x.\n",
     146                        instance->registers->command_status);
     147                instance->registers->control_current = 0;
     148                instance->registers->control |= C_CLE;
    143149                break;
    144150        case USB_TRANSFER_BULK:
     151                instance->registers->control &= ~C_BLE;
     152                transfer_list_add_batch(
     153                    instance->transfers[batch->transfer_type], batch);
    145154                instance->registers->command_status |= CS_BLF;
     155                usb_log_debug2("Set bulk transfer filled: %x.\n",
     156                        instance->registers->command_status);
     157                instance->registers->control |= C_BLE;
     158                break;
     159        case USB_TRANSFER_INTERRUPT:
     160        case USB_TRANSFER_ISOCHRONOUS:
     161                instance->registers->control &= (~C_PLE & ~C_IE);
     162                transfer_list_add_batch(
     163                    instance->transfers[batch->transfer_type], batch);
     164                instance->registers->control |= C_PLE | C_IE;
     165                usb_log_debug2("Added periodic transfer: %x.\n",
     166                    instance->registers->periodic_current);
    146167                break;
    147168        default:
    148169                break;
    149170        }
     171        fibril_mutex_unlock(&instance->guard);
    150172        return EOK;
    151173}
     
    154176{
    155177        assert(instance);
    156         if (status == 0)
     178        if ((status & ~IS_SF) == 0) /* ignore sof status */
    157179                return;
    158180        if (status & IS_RHSC)
    159181                rh_interrupt(&instance->rh);
    160182
    161         usb_log_info("OHCI interrupt: %x.\n", status);
    162 
    163         LIST_INITIALIZE(done);
    164         transfer_list_remove_finished(&instance->transfers_interrupt, &done);
    165         transfer_list_remove_finished(&instance->transfers_isochronous, &done);
    166         transfer_list_remove_finished(&instance->transfers_control, &done);
    167         transfer_list_remove_finished(&instance->transfers_bulk, &done);
    168 
    169         while (!list_empty(&done)) {
    170                 link_t *item = done.next;
    171                 list_remove(item);
    172                 usb_transfer_batch_t *batch =
    173                     list_get_instance(item, usb_transfer_batch_t, link);
    174                 usb_transfer_batch_finish(batch);
     183        usb_log_debug("OHCI interrupt: %x.\n", status);
     184
     185        if (status & IS_WDH) {
     186                fibril_mutex_lock(&instance->guard);
     187                usb_log_debug2("HCCA: %p-%p(%p).\n", instance->hcca,
     188                    instance->registers->hcca, addr_to_phys(instance->hcca));
     189                usb_log_debug2("Periodic current: %p.\n",
     190                    instance->registers->periodic_current);
     191                LIST_INITIALIZE(done);
     192                transfer_list_remove_finished(
     193                    &instance->transfers_interrupt, &done);
     194                transfer_list_remove_finished(
     195                    &instance->transfers_isochronous, &done);
     196                transfer_list_remove_finished(
     197                    &instance->transfers_control, &done);
     198                transfer_list_remove_finished(
     199                    &instance->transfers_bulk, &done);
     200
     201                while (!list_empty(&done)) {
     202                        link_t *item = done.next;
     203                        list_remove(item);
     204                        usb_transfer_batch_t *batch =
     205                            list_get_instance(item, usb_transfer_batch_t, link);
     206                        usb_transfer_batch_finish(batch);
     207                }
     208                fibril_mutex_unlock(&instance->guard);
    175209        }
    176210}
     
    184218                instance->registers->interrupt_status = status;
    185219                hc_interrupt(instance, status);
    186                 async_usleep(1000);
     220                async_usleep(50000);
    187221        }
    188222        return EOK;
     
    192226{
    193227        assert(instance);
     228        /* Turn off legacy emulation */
     229        volatile uint32_t *ohci_emulation_reg =
     230            (uint32_t*)((char*)instance->registers + 0x100);
     231        usb_log_debug("OHCI legacy register %p: %x.\n",
     232                ohci_emulation_reg, *ohci_emulation_reg);
     233        *ohci_emulation_reg = 0;
     234
    194235        /* Interrupt routing enabled => smm driver is active */
    195236        if (instance->registers->control & C_IR) {
    196                 usb_log_info("Found SMM driver requesting ownership change.\n");
     237                usb_log_debug("SMM driver: request ownership change.\n");
    197238                instance->registers->command_status |= CS_OCR;
    198239                while (instance->registers->control & C_IR) {
    199240                        async_usleep(1000);
    200241                }
    201                 usb_log_info("Ownership taken from SMM driver.\n");
     242                usb_log_info("SMM driver: Ownership taken.\n");
    202243                return;
    203244        }
     
    207248        /* Interrupt routing disabled && status != USB_RESET => BIOS active */
    208249        if (hc_status != C_HCFS_RESET) {
    209                 usb_log_info("Found BIOS driver.\n");
     250                usb_log_debug("BIOS driver found.\n");
    210251                if (hc_status == C_HCFS_OPERATIONAL) {
    211                         usb_log_info("HC operational(BIOS).\n");
     252                        usb_log_info("BIOS driver: HC operational.\n");
    212253                        return;
    213254                }
     
    215256                instance->registers->control &= (C_HCFS_RESUME << C_HCFS_SHIFT);
    216257                async_usleep(20000);
     258                usb_log_info("BIOS driver: HC resumed.\n");
    217259                return;
    218260        }
     
    220262        /* HC is in reset (hw startup) => no other driver
    221263         * maintain reset for at least the time specified in USB spec (50 ms)*/
     264        usb_log_info("HC found in reset.\n");
    222265        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 
    231266}
    232267/*----------------------------------------------------------------------------*/
    233268void hc_init_hw(hc_t *instance)
    234269{
    235         assert(instance);
     270        /* OHCI guide page 42 */
     271        assert(instance);
     272        usb_log_debug2("Started hc initialization routine.\n");
     273
     274        /* Save contents of fm_interval register */
    236275        const uint32_t fm_interval = instance->registers->fm_interval;
    237 
    238         /* reset hc */
     276        usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
     277
     278        /* Reset hc */
     279        usb_log_debug2("HC reset.\n");
     280        size_t time = 0;
    239281        instance->registers->command_status = CS_HCR;
    240         async_usleep(10);
    241 
    242         /* restore fm_interval */
     282        while (instance->registers->command_status & CS_HCR) {
     283                async_usleep(10);
     284                time += 10;
     285        }
     286        usb_log_debug2("HC reset complete in %zu us.\n", time);
     287
     288        /* Restore fm_interval */
    243289        instance->registers->fm_interval = fm_interval;
    244290        assert((instance->registers->command_status & CS_HCR) == 0);
    245291
    246292        /* hc is now in suspend state */
    247 
    248         /* enable queues */
     293        usb_log_debug2("HC should be in suspend state(%x).\n",
     294            instance->registers->control);
     295
     296        /* Use HCCA */
     297        instance->registers->hcca = addr_to_phys(instance->hcca);
     298
     299        /* Use queues */
     300        instance->registers->bulk_head = instance->transfers_bulk.list_head_pa;
     301        usb_log_debug2("Bulk HEAD set to: %p(%p).\n",
     302            instance->transfers_bulk.list_head,
     303            instance->transfers_bulk.list_head_pa);
     304
     305        instance->registers->control_head =
     306            instance->transfers_control.list_head_pa;
     307        usb_log_debug2("Control HEAD set to: %p(%p).\n",
     308            instance->transfers_control.list_head,
     309            instance->transfers_control.list_head_pa);
     310
     311        /* Enable queues */
    249312        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;
     313        usb_log_debug2("All queues enabled(%x).\n",
     314            instance->registers->control);
     315
     316        /* Disable interrupts */
     317        instance->registers->interrupt_disable = I_SF | I_OC;
     318        usb_log_debug2("Disabling interrupts: %x.\n",
     319            instance->registers->interrupt_disable);
     320        instance->registers->interrupt_disable = I_MI;
     321        usb_log_debug2("Enabled interrupts: %x.\n",
     322            instance->registers->interrupt_enable);
     323
     324        /* Set periodic start to 90% */
     325        uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK);
     326        instance->registers->periodic_start = (frame_length / 10) * 9;
     327        usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n",
     328            instance->registers->periodic_start,
     329            instance->registers->periodic_start, frame_length);
    253330
    254331        instance->registers->control &= (C_HCFS_OPERATIONAL << C_HCFS_SHIFT);
    255         usb_log_info("OHCI HC up and running.\n");
     332        usb_log_info("OHCI HC up and running(%x).\n",
     333            instance->registers->control);
    256334}
    257335/*----------------------------------------------------------------------------*/
     
    277355        SETUP_TRANSFER_LIST(transfers_control, "CONTROL");
    278356        SETUP_TRANSFER_LIST(transfers_bulk, "BULK");
    279 
     357#undef SETUP_TRANSFER_LIST
    280358        transfer_list_set_next(&instance->transfers_interrupt,
    281359            &instance->transfers_isochronous);
     
    292370
    293371        return EOK;
    294 #undef CHECK_RET_CLEAR_RETURN
    295372}
    296373/*----------------------------------------------------------------------------*/
     
    298375{
    299376        assert(instance);
    300         /* init queues */
     377        /* Init queues */
    301378        hc_init_transfer_lists(instance);
    302379
    303         /* init HCCA */
     380        /*Init HCCA */
    304381        instance->hcca = malloc32(sizeof(hcca_t));
    305382        if (instance->hcca == NULL)
    306383                return ENOMEM;
    307384        bzero(instance->hcca, sizeof(hcca_t));
    308         instance->registers->hcca = addr_to_phys(instance->hcca);
    309 
    310         /* use queues */
    311         instance->registers->bulk_head = instance->transfers_bulk.list_head_pa;
    312         instance->registers->control_head =
    313             instance->transfers_control.list_head_pa;
     385        usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
    314386
    315387        unsigned i = 0;
     
    318390                    instance->transfers_interrupt.list_head_pa;
    319391        }
     392        usb_log_debug2("Interrupt HEADs set to: %p(%p).\n",
     393            instance->transfers_interrupt.list_head,
     394            instance->transfers_interrupt.list_head_pa);
    320395
    321396        return EOK;
  • uspace/drv/ohci/hc.h

    r58226b4 r3f3afb9  
    6969        usb_endpoint_manager_t ep_manager;
    7070        fid_t interrupt_emulator;
     71        fibril_mutex_t guard;
    7172} hc_t;
    7273
  • uspace/drv/ohci/hw_struct/endpoint_descriptor.c

    r58226b4 r3f3afb9  
    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        }
     
    5353                << ED_STATUS_MPS_SHIFT);
    5454
     55
    5556        if (ep->speed == USB_SPEED_LOW)
    5657                instance->status |= ED_STATUS_S_FLAG;
     
    5859                instance->status |= ED_STATUS_F_FLAG;
    5960
     61        if (ep->toggle)
     62                instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
    6063}
    61 
    6264/**
    6365 * @}
  • uspace/drv/ohci/hw_struct/endpoint_descriptor.h

    r58226b4 r3f3afb9  
    5353#define ED_STATUS_D_MASK (0x3)     /* direction */
    5454#define ED_STATUS_D_SHIFT (11)
    55 #define ED_STATUS_D_IN (0x1)
    56 #define ED_STATUS_D_OUT (0x2)
     55#define ED_STATUS_D_OUT (0x1)
     56#define ED_STATUS_D_IN (0x2)
    5757#define ED_STATUS_D_TRANSFER (0x3)
    5858
     
    8484{
    8585        assert(instance);
    86         instance->td_head = addr_to_phys(head) & ED_TDHEAD_PTR_MASK;
     86        instance->td_head =
     87            ((addr_to_phys(head) & ED_TDHEAD_PTR_MASK)
     88            | (instance->td_head & ~ED_TDHEAD_PTR_MASK));
    8789        instance->td_tail = addr_to_phys(tail) & ED_TDTAIL_PTR_MASK;
    8890}
     
    9698        instance->next = pa;
    9799}
    98 
    99100#endif
    100101/**
  • uspace/drv/ohci/hw_struct/hcca.h

    r58226b4 r3f3afb9  
    4343        uint32_t done_head;
    4444        uint32_t reserved[29];
    45 } __attribute__((packed)) hcca_t;
     45} __attribute__((packed, aligned)) hcca_t;
    4646
    4747#endif
  • uspace/drv/ohci/hw_struct/transfer_descriptor.c

    r58226b4 r3f3afb9  
    5353        }
    5454        if (buffer != NULL) {
     55                assert(size != 0);
    5556                instance->cbp = addr_to_phys(buffer);
    5657                instance->be = addr_to_phys(buffer + size - 1);
  • uspace/drv/ohci/hw_struct/transfer_descriptor.h

    r58226b4 r3f3afb9  
    5050#define TD_STATUS_DP_SHIFT (19)
    5151#define TD_STATUS_DP_SETUP (0x0)
    52 #define TD_STATUS_DP_IN (0x1)
    53 #define TD_STATUS_DP_OUT (0x2)
     52#define TD_STATUS_DP_OUT (0x1)
     53#define TD_STATUS_DP_IN (0x2)
    5454#define TD_STATUS_DI_MASK (0x7) /* delay interrupt, wait DI frames before int */
    5555#define TD_STATUS_DI_SHIFT (21)
     
    8686        int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
    8787        /* something went wrong, error code is set */
    88         if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2 && cc != CC_NOERROR) {
     88        if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2) {
    8989                return true;
    9090        }
  • uspace/drv/ohci/iface.c

    r58226b4 r3f3afb9  
    6363        }
    6464
     65        usb_log_debug("%s %d:%d %zu(%zu).\n",
     66            name, target.address, target.endpoint, size, ep->max_packet_size);
     67
    6568        const size_t bw = bandwidth_count_usb11(
    6669            ep->speed, ep->transfer_type, size, ep->max_packet_size);
     
    6871                usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
    6972                    "but only %zu is reserved.\n",
    70                     name, target.address, target.endpoint, bw, res_bw);
     73                    target.address, target.endpoint, name, bw, res_bw);
    7174                return ENOSPC;
    7275        }
    73         usb_log_debug("%s %d:%d %zu(%zu).\n",
    74             name, target.address, target.endpoint, size, ep->max_packet_size);
    75 
    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
     77        *batch = batch_get(
     78            fun, ep, data, size, setup_data, setup_size, in, out, arg);
     79        if (!*batch)
    8580                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);
    13981        return EOK;
    14082}
     
    216158        hc_t *hc = fun_to_hc(fun);
    217159        assert(hc);
    218         if (address == hc->rh.address)
    219                 return EOK;
     160
    220161        usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
    221162        if (speed >= USB_SPEED_MAX) {
    222163                speed = ep_speed;
    223164        }
    224         const size_t size =
    225             (transfer_type == USB_TRANSFER_INTERRUPT
    226             || transfer_type == USB_TRANSFER_ISOCHRONOUS) ?
    227             max_packet_size : 0;
     165        const size_t size = max_packet_size;
    228166        int ret;
     167
     168        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
     169            address, endpoint, usb_str_transfer_type(transfer_type),
     170            usb_str_speed(speed), direction, size, max_packet_size, interval);
    229171
    230172        endpoint_t *ep = malloc(sizeof(endpoint_t));
     
    238180        }
    239181
    240         usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
    241             address, endpoint, usb_str_transfer_type(transfer_type),
    242             usb_str_speed(speed), direction, size, max_packet_size, interval);
    243 
    244182        ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size);
    245183        if (ret != EOK) {
    246184                endpoint_destroy(ep);
    247         } else {
    248                 usb_device_keeper_add_ep(&hc->manager, address, ep);
    249185        }
    250186        return ret;
     
    259195        usb_log_debug("Unregister endpoint %d:%d %d.\n",
    260196            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         }
    266197        return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
    267198            endpoint, direction);
     
    435366        if (ret != EOK)
    436367                return ret;
    437         usb_device_keeper_reset_if_need(&hc->manager, target, setup_data);
     368        usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);
    438369        batch_control_write(batch);
    439370        ret = hc_schedule(hc, batch);
     
    484415/*----------------------------------------------------------------------------*/
    485416usbhc_iface_t hc_iface = {
    486         .reserve_default_address = reserve_default_address,
    487         .release_default_address = release_default_address,
    488417        .request_address = request_address,
    489418        .bind_address = bind_address,
  • uspace/drv/ohci/ohci.ma

    r58226b4 r3f3afb9  
    1110 pci/ven=106b&dev=003f
     210 pci/ven=10de&dev=0aa5
     310 pci/ven=10de&dev=0aa5
  • uspace/drv/ohci/ohci_regs.h

    r58226b4 r3f3afb9  
    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 */
     
    100100#define HCCA_PTR_MASK 0xffffff00 /* HCCA is 256B aligned */
    101101
    102         /** Currently executed period endpoint */
    103         const volatile uint32_t period_current;
     102        /** Currently executed periodic endpoint */
     103        const volatile uint32_t periodic_current;
    104104
    105105        /** The first control endpoint */
     
    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

    r58226b4 r3f3afb9  
    210210        instance->registers = regs;
    211211        instance->device = dev;
    212         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;
    213214        rh_init_descriptors(instance);
    214215        // set port power mode to no-power-switching
  • uspace/drv/ohci/transfer_list.c

    r58226b4 r3f3afb9  
    7979        assert(instance);
    8080        assert(next);
    81         /* Set both queue_head.next to point to the follower */
    8281        ed_append_ed(instance->list_head, next->list_head);
    8382}
     
    122121        usb_transfer_batch_t *first = list_get_instance(
    123122            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);
     123        usb_log_debug("Batch(%p) added to list %s, first is %p(%p).\n",
     124                batch, instance->name, first, batch_ed(first));
     125        if (last_ed == instance->list_head) {
     126                usb_log_debug2("%s head ED(%p-%p): %x:%x:%x:%x.\n",
     127                    instance->name, last_ed, instance->list_head_pa,
     128                    last_ed->status, last_ed->td_tail, last_ed->td_head,
     129                    last_ed->next);
     130        }
    126131        fibril_mutex_unlock(&instance->guard);
    127132}
     
    138143
    139144        fibril_mutex_lock(&instance->guard);
     145        usb_log_debug2("Checking list %s for completed batches(%d).\n",
     146            instance->name, list_count(&instance->batch_list));
    140147        link_t *current = instance->batch_list.next;
    141148        while (current != &instance->batch_list) {
  • uspace/drv/ohci/utils/malloc32.h

    r58226b4 r3f3afb9  
    4141#include <as.h>
    4242
    43 #define UHCI_STRCUTURES_ALIGNMENT 16
    4443#define UHCI_REQUIRED_PAGE_SIZE 4096
    4544
     
    6564 */
    6665static inline void * malloc32(size_t size)
    67         { return memalign(UHCI_STRCUTURES_ALIGNMENT, size); }
     66        { return memalign(size, size); }
    6867/*----------------------------------------------------------------------------*/
    6968/** Physical mallocator simulator
  • uspace/drv/uhci-hcd/iface.c

    r58226b4 r3f3afb9  
    6363        }
    6464
     65        usb_log_debug("%s %d:%d %zu(%zu).\n",
     66            name, target.address, target.endpoint, size, ep->max_packet_size);
     67
    6568        const size_t bw = bandwidth_count_usb11(
    6669            ep->speed, ep->transfer_type, size, ep->max_packet_size);
     
    6871                usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
    6972                    "but only %zu is reserved.\n",
    70                     name, target.address, target.endpoint, bw, res_bw);
     73                    target.address, target.endpoint, name, bw, res_bw);
    7174                return ENOSPC;
    7275        }
    73         usb_log_debug("%s %d:%d %zu(%zu).\n",
    74             name, target.address, target.endpoint, size, ep->max_packet_size);
    75 
    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
     77        *batch = batch_get(
     78                fun, ep, data, size, setup_data, setup_size, in, out, arg);
     79        if (!*batch)
    8580                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);
    13981        return EOK;
    14082}
     
    205147        hc_t *hc = fun_to_hc(fun);
    206148        assert(hc);
     149        const size_t size = max_packet_size;
     150        int ret;
    207151        usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
    208152        if (speed >= USB_SPEED_MAX) {
    209153                speed = ep_speed;
    210154        }
    211         const size_t size =
    212             (transfer_type == USB_TRANSFER_INTERRUPT
    213             || transfer_type == USB_TRANSFER_ISOCHRONOUS) ?
    214             max_packet_size : 0;
    215         int ret;
     155        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
     156            address, endpoint, usb_str_transfer_type(transfer_type),
     157            usb_str_speed(speed), direction, size, max_packet_size, interval);
     158
    216159
    217160        endpoint_t *ep = malloc(sizeof(endpoint_t));
     
    225168        }
    226169
    227         usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
    228             address, endpoint, usb_str_transfer_type(transfer_type),
    229             usb_str_speed(speed), direction, size, max_packet_size, interval);
    230 
    231170        ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size);
    232171        if (ret != EOK) {
    233172                endpoint_destroy(ep);
    234         } else {
    235                 usb_device_keeper_add_ep(&hc->manager, address, ep);
    236173        }
    237174        return ret;
     
    246183        usb_log_debug("Unregister endpoint %d:%d %d.\n",
    247184            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         }
    253185        return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address,
    254186            endpoint, direction);
     
    391323        if (ret != EOK)
    392324                return ret;
    393         usb_device_keeper_reset_if_need(&hc->manager, target, setup_data);
     325        usb_endpoint_manager_reset_if_need(&hc->ep_manager, target, setup_data);
    394326        batch_control_write(batch);
    395327        ret = hc_schedule(hc, batch);
     
    433365/*----------------------------------------------------------------------------*/
    434366usbhc_iface_t hc_iface = {
    435         .reserve_default_address = reserve_default_address,
    436         .release_default_address = release_default_address,
    437367        .request_address = request_address,
    438368        .bind_address = bind_address,
  • uspace/drv/usbhid/Makefile

    r58226b4 r3f3afb9  
    4040        main.c \
    4141        usbhid.c \
     42        subdrivers.c \
    4243        kbd/conv.c \
    4344        kbd/kbddev.c \
    4445        kbd/kbdrepeat.c \
    4546        generic/hiddev.c \
     47        mouse/mousedev.c \
    4648        $(STOLEN_LAYOUT_SOURCES)
    4749
  • uspace/drv/usbhid/generic/hiddev.c

    r58226b4 r3f3afb9  
    3939
    4040#include "hiddev.h"
     41#include "usbhid.h"
    4142
    4243/*----------------------------------------------------------------------------*/
     
    5455/*----------------------------------------------------------------------------*/
    5556
    56 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
    57      size_t buffer_size, void *arg)
     57bool usb_generic_hid_polling_callback(usb_hid_dev_t *hid_dev,
     58    uint8_t *buffer, size_t buffer_size)
    5859{
    59         usb_log_debug("usb_hid_polling_callback()\n");
     60        usb_log_debug("usb_hid_polling_callback(%p, %p, %zu)\n",
     61            hid_dev, buffer, buffer_size);
    6062        usb_debug_str_buffer(buffer, buffer_size, 0);
    6163        return true;
  • uspace/drv/usbhid/generic/hiddev.h

    r58226b4 r3f3afb9  
    3434 */
    3535
    36 #ifndef USB_HIDD_H_
    37 #define USB_HIDD_H_
     36#ifndef USB_HID_HIDDDEV_H_
     37#define USB_HID_HIDDDEV_H_
    3838
    3939#include <usb/devdrv.h>
     40
     41struct usb_hid_dev;
    4042
    4143usb_endpoint_description_t usb_hid_generic_poll_endpoint_description;
     
    4446const char *HID_GENERIC_CLASS_NAME;
    4547
    46 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
    47      size_t buffer_size, void *arg);
     48bool usb_generic_hid_polling_callback(struct usb_hid_dev *hid_dev,
     49    uint8_t *buffer, size_t buffer_size);
    4850
    49 #endif // USB_HIDD_H_
     51#endif // USB_HID_HIDDDEV_H_
    5052
    5153/**
  • uspace/drv/usbhid/kbd/conv.h

    r58226b4 r3f3afb9  
    3434 */
    3535
    36 #ifndef USB_KBD_CONV_H_
    37 #define USB_KBD_CONV_H_
     36#ifndef USB_HID_CONV_H_
     37#define USB_HID_CONV_H_
    3838
    3939unsigned int usbhid_parse_scancode(int scancode);
    4040
    41 #endif /* USB_KBD_CONV_H_ */
     41#endif /* USB_HID_CONV_H_ */
    4242
    4343/**
  • uspace/drv/usbhid/kbd/kbddev.c

    r58226b4 r3f3afb9  
    238238 * @param icall Call data.
    239239 */
    240 void default_connection_handler(ddf_fun_t *fun,
     240static void default_connection_handler(ddf_fun_t *fun,
    241241    ipc_callid_t icallid, ipc_call_t *icall)
    242242{
     
    856856/*----------------------------------------------------------------------------*/
    857857
    858 bool usb_kbd_polling_callback(usb_device_t *dev, uint8_t *buffer,
    859      size_t buffer_size, void *arg)
    860 {
    861         if (dev == NULL || buffer == NULL || arg == NULL) {
     858bool usb_kbd_polling_callback(usb_hid_dev_t *hid_dev, uint8_t *buffer,
     859     size_t buffer_size)
     860{
     861        if (hid_dev == NULL || buffer == NULL) {
    862862                // do not continue polling (???)
    863863                return false;
    864864        }
    865        
    866         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
    867865       
    868866        // TODO: add return value from this function
     
    916914/*----------------------------------------------------------------------------*/
    917915
    918 void usb_kbd_deinit(struct usb_hid_dev_t *hid_dev)
     916void usb_kbd_deinit(usb_hid_dev_t *hid_dev)
    919917{
    920918        if (hid_dev == NULL) {
  • uspace/drv/usbhid/kbd/kbddev.h

    r58226b4 r3f3afb9  
    3434 */
    3535
    36 #ifndef USB_KBDDEV_H_
    37 #define USB_KBDDEV_H_
     36#ifndef USB_HID_KBDDEV_H_
     37#define USB_HID_KBDDEV_H_
    3838
    3939#include <stdint.h>
     
    4949#include "kbdrepeat.h"
    5050
    51 struct usb_hid_dev_t;
     51struct usb_hid_dev;
    5252
    5353/*----------------------------------------------------------------------------*/
     
    6565 */
    6666typedef struct usb_kbd_t {
    67         /** Structure holding generic USB device information. */
    68         //usbhid_dev_t *hid_dev;
    69         //usb_device_t *usb_dev;
    70        
    7167        /** Currently pressed keys (not translated to key codes). */
    7268        uint8_t *keys;
     
    9187        fibril_mutex_t *repeat_mtx;
    9288       
    93         /** Report descriptor. */
    94         //uint8_t *report_desc;
    95 
    96         /** Report descriptor size. */
    97         //size_t report_desc_size;
    98        
    9989        uint8_t *output_buffer;
    10090       
     
    10696       
    10797        int32_t *led_data;
    108 
    109         /** HID Report parser. */
    110         //usb_hid_report_parser_t *parser;
    11198       
    11299        /** State of the structure (for checking before use).
     
    121108/*----------------------------------------------------------------------------*/
    122109
    123 //enum {
    124 //      USB_KBD_POLL_EP_NO = 0,
    125 //      USB_HID_POLL_EP_NO = 1,
    126 //      USB_KBD_POLL_EP_COUNT = 2
    127 //};
    128 
    129 //usb_endpoint_description_t *usb_kbd_endpoints[USB_KBD_POLL_EP_COUNT + 1];
    130 
    131 //ddf_dev_ops_t keyboard_ops;
    132 
    133110usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description;
    134111
     
    138115/*----------------------------------------------------------------------------*/
    139116
    140 //usb_kbd_t *usb_kbd_new(void);
     117int usb_kbd_init(struct usb_hid_dev *hid_dev);
    141118
    142 int usb_kbd_init(struct usb_hid_dev_t *hid_dev);
    143 
    144 bool usb_kbd_polling_callback(usb_device_t *dev, uint8_t *buffer,
    145      size_t buffer_size, void *arg);
    146 
    147 //void usb_kbd_polling_ended_callback(usb_device_t *dev, bool reason,
    148 //     void *arg);
     119bool usb_kbd_polling_callback(struct usb_hid_dev *hid_dev, uint8_t *buffer,
     120    size_t buffer_size);
    149121
    150122int usb_kbd_is_initialized(const usb_kbd_t *kbd_dev);
     
    154126void usb_kbd_free(usb_kbd_t **kbd_dev);
    155127
    156 void usb_kbd_push_ev(struct usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev,
     128void usb_kbd_push_ev(struct usb_hid_dev *hid_dev, usb_kbd_t *kbd_dev,
    157129    int type, unsigned int key);
    158130
     131void usb_kbd_deinit(struct usb_hid_dev *hid_dev);
    159132
    160 void usb_kbd_deinit(struct usb_hid_dev_t *hid_dev);
     133int usb_kbd_set_boot_protocol(struct usb_hid_dev *hid_dev);
    161134
    162 int usb_kbd_set_boot_protocol(struct usb_hid_dev_t *hid_dev);
    163 
    164 #endif /* USB_KBDDEV_H_ */
     135#endif /* USB_HID_KBDDEV_H_ */
    165136
    166137/**
  • uspace/drv/usbhid/kbd/kbdrepeat.h

    r58226b4 r3f3afb9  
    3434 */
    3535
    36 #ifndef USB_KBDREPEAT_H_
    37 #define USB_KBDREPEAT_H_
     36#ifndef USB_HID_KBDREPEAT_H_
     37#define USB_HID_KBDREPEAT_H_
    3838
    3939struct usb_kbd_t;
     
    6262void usb_kbd_repeat_stop(struct usb_kbd_t *kbd, unsigned int key);
    6363
    64 #endif /* USB_KBDREPEAT_H_ */
     64#endif /* USB_HID_KBDREPEAT_H_ */
    6565
    6666/**
  • uspace/drv/usbhid/layout.h

    r58226b4 r3f3afb9  
    3636 */
    3737
    38 #ifndef USB_KBD_LAYOUT_H_
    39 #define USB_KBD_LAYOUT_H_
     38#ifndef USB_HID_LAYOUT_H_
     39#define USB_HID_LAYOUT_H_
    4040
    4141#include <sys/types.h>
  • uspace/drv/usbhid/main.c

    r58226b4 r3f3afb9  
    9898        /* Create the function exposed under /dev/devices. */
    9999        ddf_fun_t *hid_fun = ddf_fun_create(dev->ddf_dev, fun_exposed,
    100             usb_hid_get_function_name(hid_dev->device_type));
     100            usb_hid_get_function_name(hid_dev));
    101101        if (hid_fun == NULL) {
    102102                usb_log_error("Could not create DDF function node.\n");
     
    122122        }
    123123       
    124         rc = ddf_fun_add_to_class(hid_fun,
    125             usb_hid_get_class_name(hid_dev->device_type));
     124        rc = ddf_fun_add_to_class(hid_fun, usb_hid_get_class_name(hid_dev));
    126125        if (rc != EOK) {
    127126                usb_log_error(
     
    142141           hid_dev->poll_pipe_index,
    143142           /* Callback when data arrives. */
    144            hid_dev->poll_callback,
     143           usb_hid_polling_callback,
    145144           /* How much data to request. */
    146145           dev->pipes[hid_dev->poll_pipe_index].pipe->max_packet_size,
  • uspace/drv/usbhid/usbhid.c

    r58226b4 r3f3afb9  
    4242#include <usb/classes/hidreq.h>
    4343#include <errno.h>
     44#include <str_error.h>
    4445
    4546#include "usbhid.h"
     
    4748#include "kbd/kbddev.h"
    4849#include "generic/hiddev.h"
    49 
    50 /*----------------------------------------------------------------------------*/
    51 
    52 /** Mouse polling endpoint description for boot protocol class. */
    53 static usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description = {
    54         .transfer_type = USB_TRANSFER_INTERRUPT,
    55         .direction = USB_DIRECTION_IN,
    56         .interface_class = USB_CLASS_HID,
    57         .interface_subclass = USB_HID_SUBCLASS_BOOT,
    58         .interface_protocol = USB_HID_PROTOCOL_MOUSE,
    59         .flags = 0
    60 };
     50#include "mouse/mousedev.h"
     51#include "subdrivers.h"
     52
     53/*----------------------------------------------------------------------------*/
    6154
    6255/* Array of endpoints expected on the device, NULL terminated. */
     
    6861};
    6962
    70 static const char *HID_MOUSE_FUN_NAME = "mouse";
    71 static const char *HID_MOUSE_CLASS_NAME = "mouse";
     63static const int USB_HID_MAX_SUBDRIVERS = 10;
     64
     65/*----------------------------------------------------------------------------*/
     66
     67static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
     68{
     69        assert(hid_dev->subdriver_count == 0);
     70       
     71        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
     72            sizeof(usb_hid_subdriver_t));
     73        if (hid_dev->subdrivers == NULL) {
     74                return ENOMEM;
     75        }
     76       
     77        // set the init callback
     78        hid_dev->subdrivers[0].init = usb_kbd_init;
     79       
     80        // set the polling callback
     81        hid_dev->subdrivers[0].poll = usb_kbd_polling_callback;
     82       
     83        // set the polling ended callback
     84        hid_dev->subdrivers[0].poll_end = NULL;
     85       
     86        // set the deinit callback
     87        hid_dev->subdrivers[0].deinit = usb_kbd_deinit;
     88       
     89        // set subdriver count
     90        hid_dev->subdriver_count = 1;
     91       
     92        return EOK;
     93}
     94
     95/*----------------------------------------------------------------------------*/
     96
     97static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
     98{
     99        assert(hid_dev->subdriver_count == 0);
     100       
     101        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
     102            sizeof(usb_hid_subdriver_t));
     103        if (hid_dev->subdrivers == NULL) {
     104                return ENOMEM;
     105        }
     106       
     107        // set the init callback
     108        hid_dev->subdrivers[0].init = usb_mouse_init;
     109       
     110        // set the polling callback
     111        hid_dev->subdrivers[0].poll = usb_mouse_polling_callback;
     112       
     113        // set the polling ended callback
     114        hid_dev->subdrivers[0].poll_end = NULL;
     115       
     116        // set the deinit callback
     117        hid_dev->subdrivers[0].deinit = usb_mouse_deinit;
     118       
     119        // set subdriver count
     120        hid_dev->subdriver_count = 1;
     121       
     122        return EOK;
     123}
     124
     125/*----------------------------------------------------------------------------*/
     126
     127static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
     128{
     129        assert(hid_dev->subdriver_count == 0);
     130       
     131        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
     132            sizeof(usb_hid_subdriver_t));
     133        if (hid_dev->subdrivers == NULL) {
     134                return ENOMEM;
     135        }
     136       
     137        // set the init callback
     138        hid_dev->subdrivers[0].init = NULL;
     139       
     140        // set the polling callback
     141        hid_dev->subdrivers[0].poll = usb_generic_hid_polling_callback;
     142       
     143        // set the polling ended callback
     144        hid_dev->subdrivers[0].poll_end = NULL;
     145       
     146        // set the deinit callback
     147        hid_dev->subdrivers[0].deinit = NULL;
     148       
     149        // set subdriver count
     150        hid_dev->subdriver_count = 1;
     151       
     152        return EOK;
     153}
     154
     155/*----------------------------------------------------------------------------*/
     156
     157static bool usb_hid_ids_match(usb_hid_dev_t *hid_dev,
     158    const usb_hid_subdriver_mapping_t *mapping)
     159{
     160        return false;
     161}
     162
     163/*----------------------------------------------------------------------------*/
     164
     165static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev,
     166    const usb_hid_subdriver_usage_t *path, int path_size, int compare)
     167{
     168        assert(hid_dev != NULL);
     169        assert(path != NULL);
     170       
     171        usb_hid_report_path_t *usage_path = usb_hid_report_path();
     172        if (usage_path == NULL) {
     173                usb_log_debug("Failed to create usage path.\n");
     174                return false;
     175        }
     176        int i;
     177        for (i = 0; i < path_size; ++i) {
     178                if (usb_hid_report_path_append_item(usage_path,
     179                    path[i].usage_page, path[i].usage) != EOK) {
     180                        usb_log_debug("Failed to append to usage path.\n");
     181                        usb_hid_report_path_free(usage_path);
     182                        return false;
     183                }
     184        }
     185       
     186        assert(hid_dev->parser != NULL);
     187       
     188        usb_log_debug("Compare flags: %d\n", compare);
     189        size_t size = usb_hid_report_input_length(hid_dev->parser, usage_path,
     190            compare);
     191        usb_log_debug("Size of the input report: %d\n", size);
     192       
     193        usb_hid_report_path_free(usage_path);
     194       
     195        return (size > 0);
     196}
     197
     198/*----------------------------------------------------------------------------*/
     199
     200static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev,
     201    const usb_hid_subdriver_t **subdrivers, int count)
     202{
     203        int i;
     204       
     205        if (count <= 0) {
     206                hid_dev->subdriver_count = 0;
     207                hid_dev->subdrivers = NULL;
     208                return EOK;
     209        }
     210       
     211        hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(count *
     212            sizeof(usb_hid_subdriver_t));
     213        if (hid_dev->subdrivers == NULL) {
     214                return ENOMEM;
     215        }
     216       
     217        for (i = 0; i < count; ++i) {
     218                hid_dev->subdrivers[i].init = subdrivers[i]->init;
     219                hid_dev->subdrivers[i].deinit = subdrivers[i]->deinit;
     220                hid_dev->subdrivers[i].poll = subdrivers[i]->poll;
     221                hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end;
     222        }
     223       
     224        hid_dev->subdriver_count = count;
     225       
     226        return EOK;
     227}
     228
     229/*----------------------------------------------------------------------------*/
     230
     231static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
     232{
     233        const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
     234       
     235        int i = 0, count = 0;
     236        const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i];
     237       
     238        while (count < USB_HID_MAX_SUBDRIVERS &&
     239            (mapping->usage_path != NULL
     240            || mapping->vendor_id != NULL
     241            || mapping->product_id != NULL)) {
     242                // check the vendor & product ID
     243                if (mapping->vendor_id != NULL && mapping->product_id == NULL) {
     244                        usb_log_warning("Missing Product ID for Vendor ID %s\n",
     245                            mapping->vendor_id);
     246                        return EINVAL;
     247                }
     248                if (mapping->product_id != NULL && mapping->vendor_id == NULL) {
     249                        usb_log_warning("Missing Vendor ID for Product ID %s\n",
     250                            mapping->product_id);
     251                        return EINVAL;
     252                }
     253               
     254                if (mapping->vendor_id != NULL) {
     255                        assert(mapping->product_id != NULL);
     256                        usb_log_debug("Comparing device against vendor ID %s"
     257                            " and product ID %s.\n", mapping->vendor_id,
     258                            mapping->product_id);
     259                        if (usb_hid_ids_match(hid_dev, mapping)) {
     260                                usb_log_debug("Matched.\n");
     261                                subdrivers[count++] = &mapping->subdriver;
     262                                // skip the checking of usage path
     263                                goto next;
     264                        }
     265                }
     266               
     267                if (mapping->usage_path != NULL) {
     268                        usb_log_debug("Comparing device against usage path.\n");
     269                        if (usb_hid_path_matches(hid_dev,
     270                            mapping->usage_path, mapping->path_size,
     271                            mapping->compare)) {
     272                                subdrivers[count++] = &mapping->subdriver;
     273                        } else {
     274                                usb_log_debug("Not matched.\n");
     275                        }
     276                }
     277        next:
     278                mapping = &usb_hid_subdrivers[++i];
     279        }
     280       
     281        // we have all subdrivers determined, save them into the hid device
     282        return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
     283}
     284
     285/*----------------------------------------------------------------------------*/
     286
     287static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
     288{
     289        int rc = EOK;
     290       
     291        if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
     292                usb_log_debug("Found keyboard endpoint.\n");
     293                // save the pipe index
     294                hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
     295        } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
     296                usb_log_debug("Found mouse endpoint.\n");
     297                // save the pipe index
     298                hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
     299        } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
     300                usb_log_debug("Found generic HID endpoint.\n");
     301                // save the pipe index
     302                hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
     303        } else {
     304                usb_log_error("None of supported endpoints found - probably"
     305                    " not a supported device.\n");
     306                rc = ENOTSUP;
     307        }
     308       
     309        return rc;
     310}
    72311
    73312/*----------------------------------------------------------------------------*/
     
    91330        }
    92331       
     332        hid_dev->poll_pipe_index = -1;
     333       
    93334        return hid_dev;
    94335}
     
    96337/*----------------------------------------------------------------------------*/
    97338
    98 static bool usb_dummy_polling_callback(usb_device_t *dev, uint8_t *buffer,
    99      size_t buffer_size, void *arg)
    100 {
    101         usb_log_debug("Dummy polling callback.\n");
    102         return false;
    103 }
    104 
    105 /*----------------------------------------------------------------------------*/
    106 
    107 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
    108 {
    109         if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
    110                 usb_log_debug("Found keyboard endpoint.\n");
    111                
    112                 // save the pipe index and device type
    113                 hid_dev->poll_pipe_index = USB_HID_KBD_POLL_EP_NO;
    114                 hid_dev->device_type = USB_HID_PROTOCOL_KEYBOARD;
    115                
    116                 // set the polling callback
    117                 hid_dev->poll_callback = usb_kbd_polling_callback;
    118 
    119         } else if (dev->pipes[USB_HID_MOUSE_POLL_EP_NO].present) {
    120                 usb_log_debug("Found mouse endpoint.\n");
    121                
    122                 // save the pipe index and device type
    123                 hid_dev->poll_pipe_index = USB_HID_MOUSE_POLL_EP_NO;
    124                 hid_dev->device_type = USB_HID_PROTOCOL_MOUSE;
    125                
    126                 // set the polling callback
    127                 hid_dev->poll_callback = usb_dummy_polling_callback;
    128                
    129         } else if (dev->pipes[USB_HID_GENERIC_POLL_EP_NO].present) {
    130                 usb_log_debug("Found generic HID endpoint.\n");
    131                
    132                 // save the pipe index and device type
    133                 hid_dev->poll_pipe_index = USB_HID_GENERIC_POLL_EP_NO;
    134                 hid_dev->device_type = USB_HID_PROTOCOL_NONE;
    135                
    136                 // set the polling callback
    137                 hid_dev->poll_callback = usb_hid_polling_callback;
    138                
    139         } else {
    140                 usb_log_warning("None of supported endpoints found - probably"
    141                     " not a supported device.\n");
    142                 return ENOTSUP;
    143         }
    144        
    145         return EOK;
    146 }
    147 
    148 /*----------------------------------------------------------------------------*/
    149 
    150 static int usb_hid_init_parser(usb_hid_dev_t *hid_dev)
    151 {
    152         /* Initialize the report parser. */
    153         int rc = usb_hid_parser_init(hid_dev->parser);
    154         if (rc != EOK) {
    155                 usb_log_error("Failed to initialize report parser.\n");
    156                 return rc;
    157         }
    158        
    159         /* Get the report descriptor and parse it. */
    160         rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
    161             hid_dev->parser);
    162        
    163         if (rc != EOK) {
    164                 usb_log_warning("Could not process report descriptor.\n");
    165                
    166                 if (hid_dev->device_type == USB_HID_PROTOCOL_KEYBOARD) {
    167                         usb_log_warning("Falling back to boot protocol.\n");
    168                        
    169                         rc = usb_kbd_set_boot_protocol(hid_dev);
    170                        
    171                 } else if (hid_dev->device_type == USB_HID_PROTOCOL_MOUSE) {
    172                         usb_log_warning("No boot protocol for mouse yet.\n");
    173                         rc = ENOTSUP;
    174                 }
    175         }
    176        
    177         return rc;
    178 }
    179 
    180 /*----------------------------------------------------------------------------*/
    181 
    182339int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
    183340{
    184         int rc;
     341        int rc, i;
    185342       
    186343        usb_log_debug("Initializing HID structure...\n");
     
    203360        rc = usb_hid_check_pipes(hid_dev, dev);
    204361        if (rc != EOK) {
     362                usb_hid_free(&hid_dev);
    205363                return rc;
    206364        }
    207365       
    208         rc = usb_hid_init_parser(hid_dev);
     366        /* Initialize the report parser. */
     367        rc = usb_hid_parser_init(hid_dev->parser);
    209368        if (rc != EOK) {
    210                 usb_log_error("Failed to initialize HID parser.\n");
     369                usb_log_error("Failed to initialize report parser.\n");
     370                usb_hid_free(&hid_dev);
    211371                return rc;
    212372        }
    213373       
    214         switch (hid_dev->device_type) {
    215         case USB_HID_PROTOCOL_KEYBOARD:
    216                 // initialize the keyboard structure
    217                 rc = usb_kbd_init(hid_dev);
    218                 if (rc != EOK) {
    219                         usb_log_warning("Failed to initialize KBD structure."
    220                             "\n");
    221                 }
    222                 break;
    223         case USB_HID_PROTOCOL_MOUSE:
    224                 break;
    225         default:
    226 //              usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    227 //                  hid_dev->usb_dev->interface_no, 0);
    228                 break;
     374        /* Get the report descriptor and parse it. */
     375        rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
     376            hid_dev->parser);
     377       
     378        bool fallback = false;
     379       
     380        if (rc == EOK) {
     381                // try to find subdrivers that may want to handle this device
     382                rc = usb_hid_find_subdrivers(hid_dev);
     383                if (rc != EOK || hid_dev->subdriver_count == 0) {
     384                        // try to fall back to the boot protocol if available
     385                        usb_log_info("No subdrivers found to handle this"
     386                            " device.\n");
     387                        fallback = true;
     388                }
     389        } else {
     390                usb_log_error("Failed to parse Report descriptor.\n");
     391                // try to fall back to the boot protocol if available
     392                fallback = true;
     393        }
     394       
     395        // TODO: remove the mouse hack
     396        if (hid_dev->poll_pipe_index == USB_HID_MOUSE_POLL_EP_NO ||
     397            fallback) {
     398                // fall back to boot protocol
     399                switch (hid_dev->poll_pipe_index) {
     400                case USB_HID_KBD_POLL_EP_NO:
     401                        usb_log_info("Falling back to kbd boot protocol.\n");
     402                        rc = usb_kbd_set_boot_protocol(hid_dev);
     403                        if (rc == EOK) {
     404                                rc = usb_hid_set_boot_kbd_subdriver(hid_dev);
     405                        }
     406                        break;
     407                case USB_HID_MOUSE_POLL_EP_NO:
     408                        usb_log_info("Falling back to mouse boot protocol.\n");
     409                        rc = usb_mouse_set_boot_protocol(hid_dev);
     410                        if (rc == EOK) {
     411                                rc = usb_hid_set_boot_mouse_subdriver(hid_dev);
     412                        }
     413                        break;
     414                default:
     415                        assert(hid_dev->poll_pipe_index
     416                            == USB_HID_GENERIC_POLL_EP_NO);
     417                       
     418                        /* TODO: this has no meaning if the report descriptor
     419                                 is not parsed */
     420                        usb_log_info("Falling back to generic HID driver.\n");
     421                        rc = usb_hid_set_generic_hid_subdriver(hid_dev);
     422                }
     423        }
     424       
     425        if (rc != EOK) {
     426                usb_log_error("No subdriver for handling this device could be"
     427                    " initialized: %s.\n", str_error(rc));
     428                usb_hid_free(&hid_dev);
     429        } else {
     430                bool ok = false;
     431               
     432                usb_log_debug("Subdriver count: %d\n",
     433                    hid_dev->subdriver_count);
     434               
     435                for (i = 0; i < hid_dev->subdriver_count; ++i) {
     436                        if (hid_dev->subdrivers[i].init != NULL) {
     437                                usb_log_debug("Initializing subdriver %d.\n",i);
     438                                rc = hid_dev->subdrivers[i].init(hid_dev);
     439                                if (rc != EOK) {
     440                                        usb_log_warning("Failed to initialize"
     441                                            " HID subdriver structure.\n");
     442                                } else {
     443                                        // at least one subdriver initialized
     444                                        ok = true;
     445                                }
     446                        } else {
     447                                ok = true;
     448                        }
     449                }
     450               
     451                rc = (ok) ? EOK : -1;   // what error to report
    229452        }
    230453       
    231454        return rc;
     455}
     456
     457/*----------------------------------------------------------------------------*/
     458
     459bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
     460    size_t buffer_size, void *arg)
     461{
     462        int i;
     463       
     464        if (dev == NULL || arg == NULL || buffer == NULL) {
     465                usb_log_error("Missing arguments to polling callback.\n");
     466                return false;
     467        }
     468       
     469        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
     470       
     471        bool cont = false;
     472       
     473        // continue if at least one of the subdrivers want to continue
     474        for (i = 0; i < hid_dev->subdriver_count; ++i) {
     475                if (hid_dev->subdrivers[i].poll != NULL
     476                    && hid_dev->subdrivers[i].poll(hid_dev, buffer,
     477                    buffer_size)) {
     478                        cont = true;
     479                }
     480        }
     481       
     482        return cont;
    232483}
    233484
     
    237488     void *arg)
    238489{
     490        int i;
     491       
    239492        if (dev == NULL || arg == NULL) {
    240493                return;
     
    243496        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
    244497       
     498        for (i = 0; i < hid_dev->subdriver_count; ++i) {
     499                if (hid_dev->subdrivers[i].poll_end != NULL) {
     500                        hid_dev->subdrivers[i].poll_end(hid_dev, reason);
     501                }
     502        }
     503       
    245504        usb_hid_free(&hid_dev);
    246505}
     
    248507/*----------------------------------------------------------------------------*/
    249508
    250 const char *usb_hid_get_function_name(usb_hid_iface_protocol_t device_type)
    251 {
    252         switch (device_type) {
    253         case USB_HID_PROTOCOL_KEYBOARD:
     509const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev)
     510{
     511        switch (hid_dev->poll_pipe_index) {
     512        case USB_HID_KBD_POLL_EP_NO:
    254513                return HID_KBD_FUN_NAME;
    255514                break;
    256         case USB_HID_PROTOCOL_MOUSE:
     515        case USB_HID_MOUSE_POLL_EP_NO:
    257516                return HID_MOUSE_FUN_NAME;
    258517                break;
     
    264523/*----------------------------------------------------------------------------*/
    265524
    266 const char *usb_hid_get_class_name(usb_hid_iface_protocol_t device_type)
    267 {
    268         switch (device_type) {
    269         case USB_HID_PROTOCOL_KEYBOARD:
     525const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev)
     526{
     527        // this means that only boot protocol keyboards will be connected
     528        // to the console; there is probably no better way to do this
     529       
     530        switch (hid_dev->poll_pipe_index) {
     531        case USB_HID_KBD_POLL_EP_NO:
    270532                return HID_KBD_CLASS_NAME;
    271533                break;
    272         case USB_HID_PROTOCOL_MOUSE:
     534        case USB_HID_MOUSE_POLL_EP_NO:
    273535                return HID_MOUSE_CLASS_NAME;
    274536                break;
     
    282544void usb_hid_free(usb_hid_dev_t **hid_dev)
    283545{
     546        int i;
     547       
    284548        if (hid_dev == NULL || *hid_dev == NULL) {
    285549                return;
    286550        }
    287551       
    288         switch ((*hid_dev)->device_type) {
    289         case USB_HID_PROTOCOL_KEYBOARD:
    290                 usb_kbd_deinit(*hid_dev);
    291                 break;
    292         case USB_HID_PROTOCOL_MOUSE:
    293                 break;
    294         default:
    295                 break;
     552        assert((*hid_dev)->subdrivers != NULL
     553            || (*hid_dev)->subdriver_count == 0);
     554       
     555        for (i = 0; i < (*hid_dev)->subdriver_count; ++i) {
     556                if ((*hid_dev)->subdrivers[i].deinit != NULL) {
     557                        (*hid_dev)->subdrivers[i].deinit(*hid_dev);
     558                }
     559        }
     560       
     561        // free the subdrivers info
     562        if ((*hid_dev)->subdrivers != NULL) {
     563                free((*hid_dev)->subdrivers);
    296564        }
    297565
  • uspace/drv/usbhid/usbhid.h

    r58226b4 r3f3afb9  
    3434 */
    3535
    36 #ifndef USB_USBHID_H_
    37 #define USB_USBHID_H_
     36#ifndef USB_HID_USBHID_H_
     37#define USB_HID_USBHID_H_
    3838
    3939#include <stdint.h>
     
    4545#include <usb/classes/hid.h>
    4646
     47struct usb_hid_dev;
     48
     49typedef int (*usb_hid_driver_init_t)(struct usb_hid_dev *);
     50typedef void (*usb_hid_driver_deinit_t)(struct usb_hid_dev *);
     51typedef bool (*usb_hid_driver_poll)(struct usb_hid_dev *, uint8_t *, size_t);
     52typedef int (*usb_hid_driver_poll_ended)(struct usb_hid_dev *, bool reason);
     53
     54// TODO: add function and class name??
     55typedef struct usb_hid_subdriver {     
     56        /** Function to be called when initializing HID device. */
     57        usb_hid_driver_init_t init;
     58        /** Function to be called when destroying the HID device structure. */
     59        usb_hid_driver_deinit_t deinit;
     60        /** Function to be called when data arrives from the device. */
     61        usb_hid_driver_poll poll;
     62        /** Function to be called when polling ends. */
     63        usb_hid_driver_poll_ended poll_end;
     64} usb_hid_subdriver_t;
     65
    4766/*----------------------------------------------------------------------------*/
    4867/**
    4968 * Structure for holding general HID device data.
    5069 */
    51 typedef struct usb_hid_dev_t {
     70typedef struct usb_hid_dev {
    5271        /** Structure holding generic USB device information. */
    5372        usb_device_t *usb_dev;
     
    5978        int poll_pipe_index;
    6079       
    61         /** Function to be called when data arrives from the device. */
    62         usb_polling_callback_t poll_callback;
     80        /** Subdrivers. */
     81        usb_hid_subdriver_t *subdrivers;
     82       
     83        /** Number of subdrivers. */
     84        int subdriver_count;
    6385       
    6486        /** Report descriptor. */
     
    7395        /** Arbitrary data (e.g. a special structure for handling keyboard). */
    7496        void *data;
    75        
    76         /** Type of the device (keyboard, mouse, generic HID device). */
    77         usb_hid_iface_protocol_t device_type;
    7897} usb_hid_dev_t;
    7998
     
    95114int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev);
    96115
     116bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
     117    size_t buffer_size, void *arg);
     118
    97119void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason,
    98120     void *arg);
    99121
    100 const char *usb_hid_get_function_name(usb_hid_iface_protocol_t device_type);
     122const char *usb_hid_get_function_name(const usb_hid_dev_t *hid_dev);
    101123
    102 const char *usb_hid_get_class_name(usb_hid_iface_protocol_t device_type);
     124const char *usb_hid_get_class_name(const usb_hid_dev_t *hid_dev);
    103125
    104126void usb_hid_free(usb_hid_dev_t **hid_dev);
    105127
    106 #endif /* USB_USBHID_H_ */
     128#endif /* USB_HID_USBHID_H_ */
    107129
    108130/**
  • uspace/drv/usbhid/usbhid.ma

    r58226b4 r3f3afb9  
    11100 usb&interface&class=HID&subclass=0x01&protocol=0x01
    2 100 usb&interface&class=HID&subclass=0x01&protocol=0x02
     21000 usb&interface&class=HID&subclass=0x01&protocol=0x02
    33100 usb&interface&class=HID
  • uspace/drv/usbhub/ports.c

    r58226b4 r3f3afb9  
    181181                 */
    182182        } 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);
     183                // TODO: is this really reason to print a warning?
     184                usb_log_warning("Device removed before being registered.\n");
     185
     186                /*
     187                 * Device was removed before port reset completed.
     188                 * We will announce a failed port reset to unblock the
     189                 * port reset callback from new device wrapper.
     190                 */
     191                usb_hub_port_t *the_port = hub->ports + port;
     192                fibril_mutex_lock(&the_port->reset_mutex);
     193                the_port->reset_completed = true;
     194                the_port->reset_okay = false;
     195                fibril_condvar_broadcast(&the_port->reset_cv);
     196                fibril_mutex_unlock(&the_port->reset_mutex);
    188197        }
    189198}
     
    207216                fibril_mutex_lock(&the_port->reset_mutex);
    208217                the_port->reset_completed = true;
     218                the_port->reset_okay = true;
    209219                fibril_condvar_broadcast(&the_port->reset_cv);
    210220                fibril_mutex_unlock(&the_port->reset_mutex);
     
    319329        }
    320330
    321         return EOK;
     331        if (my_port->reset_okay) {
     332                return EOK;
     333        } else {
     334                return ESTALL;
     335        }
    322336}
    323337
  • uspace/drv/usbhub/ports.h

    r58226b4 r3f3afb9  
    5151         */
    5252        bool reset_completed;
     53        /** Whether to announce the port reset as successful. */
     54        bool reset_okay;
    5355
    5456        /** Information about attached device. */
  • uspace/drv/usbhub/usbhub.c

    r58226b4 r3f3afb9  
    179179}
    180180
    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  */
    189 int 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 
    200181
    201182//*********************************************
     
    266247        for (port = 0; port < hub_info->port_count + 1; port++) {
    267248                usb_hub_port_init(&hub_info->ports[port]);
     249        }
     250        for (port = 0; port < hub_info->port_count; port++) {
    268251                opResult = usb_hub_set_port_feature(hub_info->control_pipe,
    269                     port, USB_HUB_FEATURE_PORT_POWER);
     252                    port+1, USB_HUB_FEATURE_PORT_POWER);
    270253                if (opResult != EOK) {
    271254                        usb_log_error("cannot power on port %d;  %d\n",
    272                             port, opResult);
     255                            port+1, opResult);
    273256                }
    274257        }
  • uspace/drv/usbhub/usbhub.h

    r58226b4 r3f3afb9  
    9898    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg);
    9999
    100 int usb_hub_release_default_address(usb_hub_info_t * hub);
    101 
    102100#endif
    103101/**
  • uspace/drv/vhc/connhost.c

    r58226b4 r3f3afb9  
    324324}
    325325
    326 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t ignored)
    327 {
    328         usb_address_keeping_reserve_default(&addresses);
    329         return EOK;
    330 }
    331 
    332 static int release_default_address(ddf_fun_t *fun)
    333 {
    334         usb_address_keeping_release_default(&addresses);
    335         return EOK;
    336 }
    337 
    338326static int request_address(ddf_fun_t *fun, usb_speed_t ignored,
    339327    usb_address_t *address)
     
    388376
    389377usbhc_iface_t vhc_iface = {
    390         .reserve_default_address = reserve_default_address,
    391         .release_default_address = release_default_address,
    392378        .request_address = request_address,
    393379        .bind_address = bind_address,
  • uspace/lib/drv/generic/remote_usbhc.c

    r58226b4 r3f3afb9  
    5050static void remote_usbhc_control_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5151static void remote_usbhc_control_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    52 static void remote_usbhc_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    53 static void remote_usbhc_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5452static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    5553static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     
    6159/** Remote USB host controller interface operations. */
    6260static remote_iface_func_ptr_t remote_usbhc_iface_ops [] = {
    63         remote_usbhc_reserve_default_address,
    64         remote_usbhc_release_default_address,
    65 
    6661        remote_usbhc_request_address,
    6762        remote_usbhc_bind_address,
     
    127122
    128123        return trans;
    129 }
    130 
    131 void remote_usbhc_reserve_default_address(ddf_fun_t *fun, void *iface,
    132     ipc_callid_t callid, ipc_call_t *call)
    133 {
    134         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    135 
    136         if (!usb_iface->reserve_default_address) {
    137                 async_answer_0(callid, ENOTSUP);
    138                 return;
    139         }
    140        
    141         usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
    142        
    143         int rc = usb_iface->reserve_default_address(fun, speed);
    144 
    145         async_answer_0(callid, rc);
    146 }
    147 
    148 void remote_usbhc_release_default_address(ddf_fun_t *fun, void *iface,
    149     ipc_callid_t callid, ipc_call_t *call)
    150 {
    151         usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
    152 
    153         if (!usb_iface->release_default_address) {
    154                 async_answer_0(callid, ENOTSUP);
    155                 return;
    156         }
    157 
    158         int rc = usb_iface->release_default_address(fun);
    159 
    160         async_answer_0(callid, rc);
    161124}
    162125
  • uspace/lib/drv/include/usbhc_iface.h

    r58226b4 r3f3afb9  
    8484 */
    8585typedef enum {
    86         /** Reserve usage of default address.
    87          * This call informs the host controller that the caller will be
    88          * using default USB address. It is duty of the HC driver to ensure
    89          * that only single entity will have it reserved.
    90          * The address is returned via IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS.
    91          * The caller can start using the address after receiving EOK
    92          * answer.
    93          */
    94         IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS,
    95 
    96         /** Release usage of default address.
    97          * @see IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS
    98          */
    99         IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS,
    100 
    10186        /** Asks for address assignment by host controller.
    10287         * Answer:
  • uspace/lib/usb/Makefile

    r58226b4 r3f3afb9  
    3434SOURCES = \
    3535        src/addrkeep.c \
     36        src/altiface.c \
    3637        src/class.c \
    3738        src/ddfiface.c \
  • uspace/lib/usb/include/usb/devdrv.h

    r58226b4 r3f3afb9  
    174174    usb_endpoint_mapping_t **, size_t *);
    175175int usb_device_destroy_pipes(ddf_dev_t *, usb_endpoint_mapping_t *, size_t);
     176int usb_device_create(ddf_dev_t *, usb_endpoint_description_t **, usb_device_t **, const char **);
    176177
    177178size_t usb_interface_count_alternates(uint8_t *, size_t, uint8_t);
     179int usb_alternate_interfaces_create(uint8_t *, size_t, int,
     180    usb_alternate_interfaces_t **);
    178181
    179182#endif
  • uspace/lib/usb/include/usb/host/device_keeper.h

    r58226b4 r3f3afb9  
    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

    r58226b4 r3f3afb9  
    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

    r58226b4 r3f3afb9  
    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/include/usb/hub.h

    r58226b4 r3f3afb9  
    5959} usb_hc_attached_device_t;
    6060
    61 int usb_hc_reserve_default_address(usb_hc_connection_t *, usb_speed_t);
    62 int usb_hc_release_default_address(usb_hc_connection_t *);
    63 
    6461usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_speed_t);
    6562int usb_hc_register_device(usb_hc_connection_t *,
  • uspace/lib/usb/include/usb/request.h

    r58226b4 r3f3afb9  
    5050/** USB endpoint status - endpoint is halted (stalled). */
    5151#define USB_ENDPOINT_STATUS_HALTED ((uint16_t)(1 << 0))
     52
     53/** USB feature selector - endpoint halt (stall). */
     54#define USB_FEATURE_SELECTOR_ENDPOINT_HALT (0)
     55
     56/** USB feature selector - device remote wake-up. */
     57#define USB_FEATURE_SELECTOR_REMOTE_WAKEUP (1)
    5258
    5359/** Standard device request. */
     
    135141    char **);
    136142
     143int usb_request_clear_endpoint_halt(usb_pipe_t *, uint16_t);
     144
    137145#endif
    138146/**
  • uspace/lib/usb/src/devdrv.c

    r58226b4 r3f3afb9  
    100100    usb_device_t *dev, int alternate_setting)
    101101{
     102        if (endpoints == NULL) {
     103                dev->pipes = NULL;
     104                dev->pipes_count = 0;
     105                return EOK;
     106        }
     107
    102108        usb_endpoint_mapping_t *pipes;
    103109        size_t pipes_count;
     
    109115
    110116        if (rc != EOK) {
    111                 usb_log_error(
    112                     "Failed to create endpoint pipes for `%s': %s.\n",
    113                     dev->ddf_dev->name, str_error(rc));
    114117                return rc;
    115118        }
     
    117120        dev->pipes = pipes;
    118121        dev->pipes_count = pipes_count;
    119 
    120         return EOK;
    121 }
    122 
    123 /** Initialize all endpoint pipes.
    124  *
    125  * @param drv The driver.
    126  * @param dev The device to be initialized.
    127  * @return Error code.
    128  */
    129 static int initialize_pipes(usb_device_t *dev)
    130 {
    131         int rc;
    132 
    133         rc = usb_device_connection_initialize_from_device(&dev->wire,
    134             dev->ddf_dev);
    135         if (rc != EOK) {
    136                 usb_log_error(
    137                     "Failed initializing connection on device `%s'. %s.\n",
    138                     dev->ddf_dev->name, str_error(rc));
    139                 return rc;
    140         }
    141 
    142         rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,
    143             &dev->wire);
    144         if (rc != EOK) {
    145                 usb_log_error("Failed to initialize default control pipe " \
    146                     "on device `%s': %s.\n",
    147                     dev->ddf_dev->name, str_error(rc));
    148                 return rc;
    149         }
    150 
    151         rc = usb_pipe_probe_default_control(&dev->ctrl_pipe);
    152         if (rc != EOK) {
    153                 usb_log_error(
    154                     "Probing default control pipe on device `%s' failed: %s.\n",
    155                     dev->ddf_dev->name, str_error(rc));
    156                 return rc;
    157         }
    158 
    159         /* Get our interface. */
    160         dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
    161 
    162         /*
    163          * We will do some querying of the device, it is worth to prepare
    164          * the long transfer.
    165          */
    166         rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe);
    167         if (rc != EOK) {
    168                 usb_log_error("Failed to start transfer: %s.\n",
    169                     str_error(rc));
    170                 return rc;
    171         }
    172 
    173         /* Retrieve the descriptors. */
    174         rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe,
    175             &dev->descriptors);
    176         if (rc != EOK) {
    177                 usb_log_error("Failed to retrieve standard device " \
    178                     "descriptors of %s: %s.\n",
    179                     dev->ddf_dev->name, str_error(rc));
    180                 return rc;
    181         }
    182 
    183 
    184         if (driver->endpoints != NULL) {
    185                 rc = initialize_other_pipes(driver->endpoints, dev, 0);
    186         }
    187 
    188         usb_pipe_end_long_transfer(&dev->ctrl_pipe);
    189 
    190         /* Rollback actions. */
    191         if (rc != EOK) {
    192                 if (dev->descriptors.configuration != NULL) {
    193                         free(dev->descriptors.configuration);
    194                 }
    195         }
    196 
    197         return rc;
    198 }
    199 
    200 /** Count number of alternate settings of a interface.
    201  *
    202  * @param config_descr Full configuration descriptor.
    203  * @param config_descr_size Size of @p config_descr in bytes.
    204  * @param interface_no Interface number.
    205  * @return Number of alternate interfaces for @p interface_no interface.
    206  */
    207 size_t usb_interface_count_alternates(uint8_t *config_descr,
    208     size_t config_descr_size, uint8_t interface_no)
    209 {
    210         assert(config_descr != NULL);
    211         assert(config_descr_size > 0);
    212 
    213         usb_dp_parser_t dp_parser = {
    214                 .nesting = usb_dp_standard_descriptor_nesting
    215         };
    216         usb_dp_parser_data_t dp_data = {
    217                 .data = config_descr,
    218                 .size = config_descr_size,
    219                 .arg = NULL
    220         };
    221 
    222         size_t alternate_count = 0;
    223 
    224         uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
    225             &dp_data, config_descr);
    226         while (iface_ptr != NULL) {
    227                 usb_standard_interface_descriptor_t *iface
    228                     = (usb_standard_interface_descriptor_t *) iface_ptr;
    229                 if (iface->descriptor_type == USB_DESCTYPE_INTERFACE) {
    230                         if (iface->interface_number == interface_no) {
    231                                 alternate_count++;
    232                         }
    233                 }
    234                 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
    235                     config_descr, iface_ptr);
    236         }
    237 
    238         return alternate_count;
    239 }
    240 
    241 /** Initialize structures related to alternate interfaces.
    242  *
    243  * @param dev Device where alternate settings shall be initialized.
    244  * @return Error code.
    245  */
    246 static int initialize_alternate_interfaces(usb_device_t *dev)
    247 {
    248         if (dev->interface_no < 0) {
    249                 dev->alternate_interfaces = NULL;
    250                 return EOK;
    251         }
    252 
    253         usb_alternate_interfaces_t *alternates
    254             = malloc(sizeof(usb_alternate_interfaces_t));
    255 
    256         if (alternates == NULL) {
    257                 return ENOMEM;
    258         }
    259 
    260         alternates->alternative_count
    261             = usb_interface_count_alternates(dev->descriptors.configuration,
    262             dev->descriptors.configuration_size, dev->interface_no);
    263 
    264         if (alternates->alternative_count == 0) {
    265                 free(alternates);
    266                 return ENOENT;
    267         }
    268 
    269         alternates->alternatives = malloc(alternates->alternative_count
    270             * sizeof(usb_alternate_interface_descriptors_t));
    271         if (alternates->alternatives == NULL) {
    272                 free(alternates);
    273                 return ENOMEM;
    274         }
    275 
    276         alternates->current = 0;
    277 
    278         usb_dp_parser_t dp_parser = {
    279                 .nesting = usb_dp_standard_descriptor_nesting
    280         };
    281         usb_dp_parser_data_t dp_data = {
    282                 .data = dev->descriptors.configuration,
    283                 .size = dev->descriptors.configuration_size,
    284                 .arg = NULL
    285         };
    286 
    287         usb_alternate_interface_descriptors_t *cur_alt_iface
    288             = &alternates->alternatives[0];
    289 
    290         uint8_t *iface_ptr = usb_dp_get_nested_descriptor(&dp_parser,
    291             &dp_data, dp_data.data);
    292         while (iface_ptr != NULL) {
    293                 usb_standard_interface_descriptor_t *iface
    294                     = (usb_standard_interface_descriptor_t *) iface_ptr;
    295                 if ((iface->descriptor_type != USB_DESCTYPE_INTERFACE)
    296                     || (iface->interface_number != dev->interface_no)) {
    297                         iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser,
    298                             &dp_data,
    299                             dp_data.data, iface_ptr);
    300                         continue;
    301                 }
    302 
    303                 cur_alt_iface->interface = iface;
    304                 cur_alt_iface->nested_descriptors = iface_ptr + sizeof(*iface);
    305 
    306                 /* Find next interface to count size of nested descriptors. */
    307                 iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
    308                     dp_data.data, iface_ptr);
    309                 if (iface_ptr == NULL) {
    310                         uint8_t *next = dp_data.data + dp_data.size;
    311                         cur_alt_iface->nested_descriptors_size
    312                             = next - cur_alt_iface->nested_descriptors;
    313                 } else {
    314                         cur_alt_iface->nested_descriptors_size
    315                             = iface_ptr - cur_alt_iface->nested_descriptors;
    316                 }
    317 
    318                 cur_alt_iface++;
    319         }
    320 
    321         dev->alternate_interfaces = alternates;
    322122
    323123        return EOK;
     
    339139        int rc;
    340140
    341         usb_device_t *dev = malloc(sizeof(usb_device_t));
    342         if (dev == NULL) {
    343                 usb_log_error("Out of memory when adding device `%s'.\n",
    344                     gen_dev->name);
    345                 return ENOMEM;
    346         }
    347 
    348 
    349         dev->ddf_dev = gen_dev;
    350         dev->ddf_dev->driver_data = dev;
    351         dev->driver_data = NULL;
    352         dev->descriptors.configuration = NULL;
    353 
    354         dev->pipes_count = 0;
    355         dev->pipes = NULL;
    356 
    357         rc = initialize_pipes(dev);
    358         if (rc != EOK) {
    359                 free(dev);
    360                 return rc;
    361         }
    362 
    363         (void) initialize_alternate_interfaces(dev);
     141        usb_device_t *dev = NULL;
     142        const char *err_msg = NULL;
     143        rc = usb_device_create(gen_dev, driver->endpoints, &dev, &err_msg);
     144        if (rc != EOK) {
     145                usb_log_error("USB device `%s' creation failed (%s): %s.\n",
     146                    gen_dev->name, err_msg, str_error(rc));
     147                return rc;
     148        }
    364149
    365150        return driver->ops->add_device(dev);
     
    395180 * with usb_pipe_initialize_from_configuration().
    396181 *
     182 * @warning This is a wrapper function that does several operations that
     183 * can fail and that cannot be rollbacked easily. That means that a failure
     184 * during the SET_INTERFACE request would result in having a device with
     185 * no pipes at all (except the default control one). That is because the old
     186 * pipes needs to be unregistered at HC first and the new ones could not
     187 * be created.
     188 *
    397189 * @param dev USB device.
    398190 * @param alternate_setting Alternate setting to choose.
     
    409201        int rc;
    410202
    411         /* TODO: more transactional behavior. */
    412 
    413203        /* Destroy existing pipes. */
    414204        rc = destroy_current_pipes(dev);
     
    432222/** Retrieve basic descriptors from the device.
    433223 *
    434  * @param[in] ctrl_pipe Control pipe with opened session.
     224 * @param[in] ctrl_pipe Control endpoint pipe.
    435225 * @param[out] descriptors Where to store the descriptors.
    436226 * @return Error code.
     
    440230{
    441231        assert(descriptors != NULL);
    442         assert(usb_pipe_is_session_started(ctrl_pipe));
    443232
    444233        descriptors->configuration = NULL;
    445234
    446235        int rc;
     236
     237        /* It is worth to start a long transfer. */
     238        rc = usb_pipe_start_long_transfer(ctrl_pipe);
     239        if (rc != EOK) {
     240                return rc;
     241        }
    447242
    448243        /* Get the device descriptor. */
    449244        rc = usb_request_get_device_descriptor(ctrl_pipe, &descriptors->device);
    450245        if (rc != EOK) {
    451                 return rc;
     246                goto leave;
    452247        }
    453248
     
    456251            ctrl_pipe, 0, (void **) &descriptors->configuration,
    457252            &descriptors->configuration_size);
    458         if (rc != EOK) {
    459                 return rc;
    460         }
    461 
    462         return EOK;
     253
     254leave:
     255        usb_pipe_end_long_transfer(ctrl_pipe);
     256
     257        return rc;
    463258}
    464259
     
    641436}
    642437
     438/** Initialize control pipe in a device.
     439 *
     440 * @param dev USB device in question.
     441 * @param errmsg Where to store error context.
     442 * @return
     443 */
     444static int init_wire_and_ctrl_pipe(usb_device_t *dev, const char **errmsg)
     445{
     446        int rc;
     447
     448        rc = usb_device_connection_initialize_from_device(&dev->wire,
     449            dev->ddf_dev);
     450        if (rc != EOK) {
     451                *errmsg = "device connection initialization";
     452                return rc;
     453        }
     454
     455        rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,
     456            &dev->wire);
     457        if (rc != EOK) {
     458                *errmsg = "default control pipe initialization";
     459                return rc;
     460        }
     461
     462        return EOK;
     463}
     464
     465
     466/** Create new instance of USB device.
     467 *
     468 * @param[in] ddf_dev Generic DDF device backing the USB one.
     469 * @param[in] endpoints NULL terminated array of endpoints (NULL for none).
     470 * @param[out] dev_ptr Where to store pointer to the new device.
     471 * @param[out] errstr_ptr Where to store description of context
     472 *      (in case error occurs).
     473 * @return Error code.
     474 */
     475int usb_device_create(ddf_dev_t *ddf_dev,
     476    usb_endpoint_description_t **endpoints,
     477    usb_device_t **dev_ptr, const char **errstr_ptr)
     478{
     479        assert(dev_ptr != NULL);
     480        assert(ddf_dev != NULL);
     481
     482        int rc;
     483
     484        usb_device_t *dev = malloc(sizeof(usb_device_t));
     485        if (dev == NULL) {
     486                *errstr_ptr = "structure allocation";
     487                return ENOMEM;
     488        }
     489
     490        // FIXME: proper deallocation in case of errors
     491
     492        dev->ddf_dev = ddf_dev;
     493        dev->driver_data = NULL;
     494        dev->descriptors.configuration = NULL;
     495        dev->alternate_interfaces = NULL;
     496
     497        dev->pipes_count = 0;
     498        dev->pipes = NULL;
     499
     500        /* Initialize backing wire and control pipe. */
     501        rc = init_wire_and_ctrl_pipe(dev, errstr_ptr);
     502        if (rc != EOK) {
     503                return rc;
     504        }
     505
     506        /* Get our interface. */
     507        dev->interface_no = usb_device_get_assigned_interface(dev->ddf_dev);
     508
     509        /* Retrieve standard descriptors. */
     510        rc = usb_device_retrieve_descriptors(&dev->ctrl_pipe,
     511            &dev->descriptors);
     512        if (rc != EOK) {
     513                *errstr_ptr = "descriptor retrieval";
     514                return rc;
     515        }
     516
     517        /* Create alternate interfaces. */
     518        rc = usb_alternate_interfaces_create(dev->descriptors.configuration,
     519            dev->descriptors.configuration_size, dev->interface_no,
     520            &dev->alternate_interfaces);
     521        if (rc != EOK) {
     522                /* We will try to silently ignore this. */
     523                dev->alternate_interfaces = NULL;
     524        }
     525
     526        rc = initialize_other_pipes(endpoints, dev, 0);
     527        if (rc != EOK) {
     528                *errstr_ptr = "pipes initialization";
     529                return rc;
     530        }
     531
     532        *errstr_ptr = NULL;
     533        *dev_ptr = dev;
     534
     535        return EOK;
     536}
     537
    643538/**
    644539 * @}
  • uspace/lib/usb/src/hidparser.c

    r58226b4 r3f3afb9  
    900900        item->usage_page = usage_page;
    901901       
     902        usb_log_debug("Appending usage %d, usage page %d\n", usage, usage_page);
     903       
    902904        list_append (&usage_path->link, &item->link);
    903905        usage_path->depth++;
  • uspace/lib/usb/src/host/device_keeper.c

    r58226b4 r3f3afb9  
    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

    r58226b4 r3f3afb9  
    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 || target.endpoint == 0))
    113102                instance->toggle = 0;
    114103}
  • uspace/lib/usb/src/host/usb_endpoint_manager.c

    r58226b4 r3f3afb9  
    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}
  • uspace/lib/usb/src/hub.c

    r58226b4 r3f3afb9  
    4242#include <usb/debug.h>
    4343
     44/** How much time to wait between attempts to register endpoint 0:0.
     45 * The value is based on typical value for port reset + some overhead.
     46 */
     47#define ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC (1000 * (10 + 2))
     48
    4449/** Check that HC connection is alright.
    4550 *
     
    5358                } \
    5459        } while (false)
    55 
    56 
    57 /** Tell host controller to reserve default address.
    58  * @deprecated
    59  *
    60  * @param connection Opened connection to host controller.
    61  * @param speed Speed of the device that will respond on the default address.
    62  * @return Error code.
    63  */
    64 int usb_hc_reserve_default_address(usb_hc_connection_t *connection,
    65     usb_speed_t speed)
    66 {
    67         CHECK_CONNECTION(connection);
    68 
    69         usb_log_warning("usb_hc_reserve_default_address() considered obsolete");
    70 
    71         return async_req_2_0(connection->hc_phone,
    72             DEV_IFACE_ID(USBHC_DEV_IFACE),
    73             IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, speed);
    74 }
    75 
    76 /** Tell host controller to release default address.
    77  * @deprecated
    78  *
    79  * @param connection Opened connection to host controller.
    80  * @return Error code.
    81  */
    82 int usb_hc_release_default_address(usb_hc_connection_t *connection)
    83 {
    84         CHECK_CONNECTION(connection);
    85 
    86         usb_log_warning("usb_hc_release_default_address() considered obsolete");
    87 
    88         return async_req_1_0(connection->hc_phone,
    89             DEV_IFACE_ID(USBHC_DEV_IFACE),
    90             IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);
    91 }
    9260
    9361/** Ask host controller for free address assignment.
     
    269237                if (rc != EOK) {
    270238                        /* Do not overheat the CPU ;-). */
    271                         async_usleep(10);
     239                        async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC);
    272240                }
    273241        } while (rc != EOK);
  • uspace/lib/usb/src/request.c

    r58226b4 r3f3afb9  
    871871}
    872872
     873/** Clear halt bit of an endpoint pipe (after pipe stall).
     874 *
     875 * @param pipe Control pipe.
     876 * @param ep_index Endpoint index (in native endianness).
     877 * @return Error code.
     878 */
     879int usb_request_clear_endpoint_halt(usb_pipe_t *pipe, uint16_t ep_index)
     880{
     881        return usb_request_clear_feature(pipe,
     882            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT,
     883            uint16_host2usb(USB_FEATURE_SELECTOR_ENDPOINT_HALT),
     884            uint16_host2usb(ep_index));
     885}
     886
    873887/**
    874888 * @}
Note: See TracChangeset for help on using the changeset viewer.