Changeset 20a3465 in mainline for uspace/drv


Ignore:
Timestamp:
2011-10-30T19:50:54Z (14 years ago)
Author:
Maurizio Lombardi <m.lombardi85@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
3ce78580, 48902fa
Parents:
4c3ad56 (diff), 45bf63c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes

Location:
uspace/drv/bus/usb
Files:
6 deleted
49 edited

Legend:

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

    r4c3ad56 r20a3465  
    6060            name, instance->list_head, instance->list_head_pa);
    6161
    62         ed_init(instance->list_head, NULL);
     62        ed_init(instance->list_head, NULL, NULL);
    6363        list_initialize(&instance->endpoint_list);
    6464        fibril_mutex_initialize(&instance->guard);
     
    7373 * Does not check whether this replaces an existing list.
    7474 */
    75 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next)
     75void endpoint_list_set_next(
     76    const endpoint_list_t *instance, const endpoint_list_t *next)
    7677{
    7778        assert(instance);
  • uspace/drv/bus/usb/ohci/endpoint_list.h

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

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

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

    r4c3ad56 r20a3465  
    3434#include "endpoint_descriptor.h"
    3535
    36 static unsigned direc[3] =
    37     { ED_STATUS_D_IN, ED_STATUS_D_OUT, ED_STATUS_D_TRANSFER };
     36/** USB direction to OHCI values translation table. */
     37static const uint32_t dir[] = {
     38        [USB_DIRECTION_IN] = ED_STATUS_D_IN,
     39        [USB_DIRECTION_OUT] = ED_STATUS_D_OUT,
     40        [USB_DIRECTION_BOTH] = ED_STATUS_D_TD,
     41};
    3842
    39 void ed_init(ed_t *instance, endpoint_t *ep)
     43/**
     44 * Initialize ED.
     45 *
     46 * @param instance ED structure to initialize.
     47 * @param ep Driver endpoint to use.
     48 * @param td TD to put in the list.
     49 *
     50 * If @param ep is NULL, dummy ED is initalized with only skip flag set.
     51 */
     52void ed_init(ed_t *instance, const endpoint_t *ep, const td_t *td)
    4053{
    4154        assert(instance);
    4255        bzero(instance, sizeof(ed_t));
     56
    4357        if (ep == NULL) {
     58                /* Mark as dead, used for dummy EDs at the beginning of
     59                 * endpoint lists. */
    4460                instance->status = ED_STATUS_K_FLAG;
    4561                return;
    4662        }
    47         assert(ep);
     63        /* Non-dummy ED must have TD assigned */
     64        assert(td);
     65
     66        /* Status: address, endpoint nr, direction mask and max packet size. */
    4867        instance->status = 0
    4968            | ((ep->address & ED_STATUS_FA_MASK) << ED_STATUS_FA_SHIFT)
    5069            | ((ep->endpoint & ED_STATUS_EN_MASK) << ED_STATUS_EN_SHIFT)
    51             | ((direc[ep->direction] & ED_STATUS_D_MASK) << ED_STATUS_D_SHIFT)
     70            | ((dir[ep->direction] & ED_STATUS_D_MASK) << ED_STATUS_D_SHIFT)
    5271            | ((ep->max_packet_size & ED_STATUS_MPS_MASK)
    5372                << ED_STATUS_MPS_SHIFT);
    5473
    55 
     74        /* Low speed flag */
    5675        if (ep->speed == USB_SPEED_LOW)
    5776                instance->status |= ED_STATUS_S_FLAG;
     77
     78        /* Isochronous format flag */
    5879        if (ep->transfer_type == USB_TRANSFER_ISOCHRONOUS)
    5980                instance->status |= ED_STATUS_F_FLAG;
    6081
     82        /* Set TD to the list */
     83        const uintptr_t pa = addr_to_phys(td);
     84        instance->td_head = pa & ED_TDHEAD_PTR_MASK;
     85        instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
     86
     87        /* Set toggle bit */
    6188        if (ep->toggle)
    6289                instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
     90
    6391}
    6492/**
  • uspace/drv/bus/usb/ohci/hw_struct/endpoint_descriptor.h

    r4c3ad56 r20a3465  
    4545#include "completion_codes.h"
    4646
     47/**
     48 * OHCI Endpoint Descriptor representation.
     49 *
     50 * See OHCI spec. Chapter 4.2, page 16 (pdf page 30) for details */
    4751typedef struct ed {
     52        /**
     53         * Status field.
     54         *
     55         * See table 4-1, p. 17 OHCI spec (pdf page 31).
     56         */
    4857        volatile uint32_t status;
    4958#define ED_STATUS_FA_MASK (0x7f)   /* USB device address   */
     
    5160#define ED_STATUS_EN_MASK (0xf)    /* USB endpoint address */
    5261#define ED_STATUS_EN_SHIFT (7)
    53 #define ED_STATUS_D_MASK (0x3)     /* direction */
     62#define ED_STATUS_D_MASK (0x3)     /* Direction */
    5463#define ED_STATUS_D_SHIFT (11)
    5564#define ED_STATUS_D_OUT (0x1)
    5665#define ED_STATUS_D_IN (0x2)
    57 #define ED_STATUS_D_TRANSFER (0x3)
     66#define ED_STATUS_D_TD (0x3) /* Direction is specified by TD */
    5867
    59 #define ED_STATUS_S_FLAG (1 << 13) /* speed flag: 1 = low */
    60 #define ED_STATUS_K_FLAG (1 << 14) /* skip flag (no not execute this ED) */
    61 #define ED_STATUS_F_FLAG (1 << 15) /* format: 1 = isochronous*/
    62 #define ED_STATUS_MPS_MASK (0x3ff) /* max_packet_size*/
     68#define ED_STATUS_S_FLAG (1 << 13) /* Speed flag: 1 = low */
     69#define ED_STATUS_K_FLAG (1 << 14) /* Skip flag (no not execute this ED) */
     70#define ED_STATUS_F_FLAG (1 << 15) /* Format: 1 = isochronous */
     71#define ED_STATUS_MPS_MASK (0x3ff) /* Maximum packet size */
    6372#define ED_STATUS_MPS_SHIFT (16)
    6473
     74        /**
     75         * Pointer to the last TD.
     76         *
     77         * OHCI hw never changes this field and uses it only for a reference.
     78         */
    6579        volatile uint32_t td_tail;
    6680#define ED_TDTAIL_PTR_MASK (0xfffffff0)
    6781#define ED_TDTAIL_PTR_SHIFT (0)
    6882
     83        /**
     84         * Pointer to the first TD.
     85         *
     86         * Driver should not change this field if the ED is active.
     87         * This field is updated by OHCI hw and points to the next TD
     88         * to be executed.
     89         */
    6990        volatile uint32_t td_head;
    7091#define ED_TDHEAD_PTR_MASK (0xfffffff0)
     
    7596#define ED_TDHEAD_HALTED_FLAG (0x1)
    7697
     98        /**
     99         * Pointer to the next ED.
     100         *
     101         * Driver should not change this field on active EDs.
     102         */
    77103        volatile uint32_t next;
    78104#define ED_NEXT_PTR_MASK (0xfffffff0)
     
    80106} __attribute__((packed)) ed_t;
    81107
    82 void ed_init(ed_t *instance, endpoint_t *ep);
     108void ed_init(ed_t *instance, const endpoint_t *ep, const td_t *td);
    83109
    84 static inline void ed_set_td(ed_t *instance, td_t *td)
     110/**
     111 * Check for SKIP or HALTED flag being set.
     112 * @param instance ED
     113 * @return true if either SKIP or HALTED flag is set, false otherwise.
     114 */
     115static inline bool ed_inactive(const ed_t *instance)
    85116{
    86117        assert(instance);
    87         uintptr_t pa = addr_to_phys(td);
    88         instance->td_head =
    89             ((pa & ED_TDHEAD_PTR_MASK)
    90             | (instance->td_head & ~ED_TDHEAD_PTR_MASK));
     118        return (instance->td_head & ED_TDHEAD_HALTED_FLAG)
     119            || (instance->status & ED_STATUS_K_FLAG);
     120}
     121
     122/**
     123 * Check whether this ED contains TD to be executed.
     124 * @param instance ED
     125 * @return true if there are pending TDs, false otherwise.
     126 */
     127static inline bool ed_transfer_pending(const ed_t *instance)
     128{
     129        assert(instance);
     130        return (instance->td_head & ED_TDHEAD_PTR_MASK)
     131            != (instance->td_tail & ED_TDTAIL_PTR_MASK);
     132}
     133
     134/**
     135 * Set the last element of TD list
     136 * @param instance ED
     137 * @param instance TD to set as the last item.
     138 */
     139static inline void ed_set_tail_td(ed_t *instance, const td_t *td)
     140{
     141        assert(instance);
     142        const uintptr_t pa = addr_to_phys(td);
    91143        instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
    92144}
    93145
    94 static inline void ed_set_end_td(ed_t *instance, td_t *td)
    95 {
    96         assert(instance);
    97         uintptr_t pa = addr_to_phys(td);
    98         instance->td_tail = pa & ED_TDTAIL_PTR_MASK;
    99 }
    100 
    101 static inline void ed_append_ed(ed_t *instance, ed_t *next)
     146/**
     147 * Set next ED in ED chain.
     148 * @param instance ED to modify
     149 * @param next ED to append
     150 */
     151static inline void ed_append_ed(ed_t *instance, const ed_t *next)
    102152{
    103153        assert(instance);
    104154        assert(next);
    105         uint32_t pa = addr_to_phys(next);
     155        const uint32_t pa = addr_to_phys(next);
    106156        assert((pa & ED_NEXT_PTR_MASK) << ED_NEXT_PTR_SHIFT == pa);
    107157        instance->next = pa;
    108158}
    109159
    110 static inline int ed_toggle_get(ed_t *instance)
     160/**
     161 * Get toggle bit value stored in this ED
     162 * @param instance ED
     163 * @return Toggle bit value
     164 */
     165static inline int ed_toggle_get(const ed_t *instance)
    111166{
    112167        assert(instance);
     
    114169}
    115170
    116 static inline void ed_toggle_set(ed_t *instance, int toggle)
     171/**
     172 * Set toggle bit value stored in this ED
     173 * @param instance ED
     174 * @param toggle Toggle bit value
     175 */
     176static inline void ed_toggle_set(ed_t *instance, bool toggle)
    117177{
    118178        assert(instance);
    119         assert(toggle == 0 || toggle == 1);
    120         if (toggle == 1) {
     179        if (toggle) {
    121180                instance->td_head |= ED_TDHEAD_TOGGLE_CARRY;
    122181        } else {
    123                 /* clear halted flag when reseting toggle */
     182                /* Clear halted flag when reseting toggle TODO: Why? */
    124183                instance->td_head &= ~ED_TDHEAD_TOGGLE_CARRY;
    125184                instance->td_head &= ~ED_TDHEAD_HALTED_FLAG;
  • uspace/drv/bus/usb/ohci/hw_struct/hcca.h

    r4c3ad56 r20a3465  
    3636
    3737#include <stdint.h>
     38#include <malloc.h>
    3839
    3940/** Host controller communication area.
     
    4849} __attribute__((packed, aligned)) hcca_t;
    4950
     51static inline void * hcca_get(void)
     52{
     53        assert(sizeof(hcca_t) == 256);
     54        return memalign(256, sizeof(hcca_t));
     55}
    5056#endif
    5157/**
  • uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.c

    r4c3ad56 r20a3465  
    3535#include "transfer_descriptor.h"
    3636
    37 static unsigned dp[3] =
    38     { TD_STATUS_DP_IN, TD_STATUS_DP_OUT, TD_STATUS_DP_SETUP };
    39 static unsigned togg[2] = { TD_STATUS_T_0, TD_STATUS_T_1 };
     37/** USB direction to OHCI TD values translation table */
     38static const uint32_t dir[] = {
     39        [USB_DIRECTION_IN] = TD_STATUS_DP_IN,
     40        [USB_DIRECTION_OUT] = TD_STATUS_DP_OUT,
     41        [USB_DIRECTION_BOTH] = TD_STATUS_DP_SETUP,
     42};
    4043
    41 void td_init(td_t *instance,
    42     usb_direction_t dir, const void *buffer, size_t size, int toggle)
     44/**
     45 * Initialize OHCI TD.
     46 * @param instance TD structure to initialize.
     47 * @param next Next TD in ED list.
     48 * @param direction Used to determine PID, BOTH means setup PID.
     49 * @param buffer Pointer to the first byte of transferred data.
     50 * @param size Size of the buffer.
     51 * @param toggle Toggle bit value, use 0/1 to set explicitly,
     52 *        any other value means that ED toggle will be used.
     53 */
     54void td_init(td_t *instance, const td_t *next,
     55    usb_direction_t direction, const void *buffer, size_t size, int toggle)
    4356{
    4457        assert(instance);
    4558        bzero(instance, sizeof(td_t));
     59        /* Set PID and Error code */
    4660        instance->status = 0
    47             | ((dp[dir] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT)
     61            | ((dir[direction] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT)
    4862            | ((CC_NOACCESS2 & TD_STATUS_CC_MASK) << TD_STATUS_CC_SHIFT);
     63
    4964        if (toggle == 0 || toggle == 1) {
    50                 instance->status |= togg[toggle] << TD_STATUS_T_SHIFT;
     65                /* Set explicit toggle bit */
     66                instance->status |= TD_STATUS_T_USE_TD_FLAG;
     67                instance->status |= toggle ? TD_STATUS_T_FLAG : 0;
    5168        }
     69
     70        /* Alow less data on input. */
    5271        if (dir == USB_DIRECTION_IN) {
    5372                instance->status |= TD_STATUS_ROUND_FLAG;
    5473        }
     74
    5575        if (buffer != NULL) {
    5676                assert(size != 0);
     
    5878                instance->be = addr_to_phys(buffer + size - 1);
    5979        }
     80
     81        instance->next = addr_to_phys(next) & TD_NEXT_PTR_MASK;
     82
    6083}
    6184/**
  • uspace/drv/bus/usb/ohci/hw_struct/transfer_descriptor.h

    r4c3ad56 r20a3465  
    3737#include <bool.h>
    3838#include <stdint.h>
     39
    3940#include "../utils/malloc32.h"
    40 
    4141#include "completion_codes.h"
    4242
     
    4646#define OHCI_TD_MAX_TRANSFER (4 * 1024)
    4747
     48/**
     49 * Transfer Descriptor representation.
     50 *
     51 * See OHCI spec chapter 4.3.1 General Transfer Descriptor on page 19
     52 * (pdf page 33) for details.
     53 */
    4854typedef struct td {
     55        /** Status field. Do not touch on active TDs. */
    4956        volatile uint32_t status;
    5057#define TD_STATUS_ROUND_FLAG (1 << 18)
    51 #define TD_STATUS_DP_MASK (0x3) /* direction/PID */
     58#define TD_STATUS_DP_MASK (0x3) /* Direction/PID */
    5259#define TD_STATUS_DP_SHIFT (19)
    5360#define TD_STATUS_DP_SETUP (0x0)
    5461#define TD_STATUS_DP_OUT (0x1)
    5562#define TD_STATUS_DP_IN (0x2)
    56 #define TD_STATUS_DI_MASK (0x7) /* delay interrupt, wait DI frames before int */
     63#define TD_STATUS_DI_MASK (0x7) /* Delay interrupt, wait n frames before irq */
    5764#define TD_STATUS_DI_SHIFT (21)
    5865#define TD_STATUS_DI_NO_INTERRUPT (0x7)
    59 #define TD_STATUS_T_MASK (0x3)  /* data toggle 1x = use ED toggle carry */
    60 #define TD_STATUS_T_SHIFT (24)
    61 #define TD_STATUS_T_0 (0x2)
    62 #define TD_STATUS_T_1 (0x3)
    63 #define TD_STATUS_T_ED (0)
    64 #define TD_STATUS_EC_MASK (0x3) /* error count */
     66#define TD_STATUS_T_FLAG (1 << 24) /* Explicit toggle bit value for this TD */
     67#define TD_STATUS_T_USE_TD_FLAG (1 << 25) /* 1 = use bit 24 as toggle bit */
     68#define TD_STATUS_EC_MASK (0x3) /* Error count */
    6569#define TD_STATUS_EC_SHIFT (26)
    66 #define TD_STATUS_CC_MASK (0xf) /* condition code */
     70#define TD_STATUS_CC_MASK (0xf) /* Condition code */
    6771#define TD_STATUS_CC_SHIFT (28)
    6872
    69         volatile uint32_t cbp; /* current buffer ptr, data to be transfered */
     73        /**
     74         * Current buffer pointer.
     75         * Phys address of the first byte to be transferred. */
     76        volatile uint32_t cbp;
     77
     78        /** Pointer to the next TD in chain. 16-byte aligned. */
    7079        volatile uint32_t next;
    7180#define TD_NEXT_PTR_MASK (0xfffffff0)
    7281#define TD_NEXT_PTR_SHIFT (0)
    7382
    74         volatile uint32_t be; /* buffer end, address of the last byte */
     83        /**
     84         * Buffer end.
     85         * Phys address of the last byte of the transfer.
     86         * @note this does not have to be on the same page as cbp.
     87         */
     88        volatile uint32_t be;
    7589} __attribute__((packed)) td_t;
    7690
    77 void td_init(td_t *instance,
     91void td_init(td_t *instance, const td_t *next,
    7892    usb_direction_t dir, const void *buffer, size_t size, int toggle);
    7993
    80 inline static void td_set_next(td_t *instance, td_t *next)
     94/**
     95 * Check TD for completion.
     96 * @param instance TD structure.
     97 * @return true if the TD was accessed and processed by hw, false otherwise.
     98 */
     99inline static bool td_is_finished(const td_t *instance)
    81100{
    82101        assert(instance);
    83         instance->next = addr_to_phys(next) & TD_NEXT_PTR_MASK;
    84 }
    85 
    86 inline static bool td_is_finished(td_t *instance)
    87 {
    88         assert(instance);
    89         int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
    90         /* something went wrong, error code is set */
     102        const int cc =
     103            (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
     104        /* This value is changed on transfer completion,
     105         * either to CC_NOERROR or and error code.
     106         * See OHCI spec 4.3.1.3.5 p. 23 (pdf 37) */
    91107        if (cc != CC_NOACCESS1 && cc != CC_NOACCESS2) {
    92                 return true;
    93         }
    94         /* everything done */
    95         if (cc == CC_NOERROR && instance->cbp == 0) {
    96108                return true;
    97109        }
     
    99111}
    100112
    101 static inline int td_error(td_t *instance)
     113/**
     114 * Get error code that indicates transfer status.
     115 * @param instance TD structure.
     116 * @return Error code.
     117 */
     118static inline int td_error(const td_t *instance)
    102119{
    103120        assert(instance);
    104         int cc = (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
     121        const int cc =
     122            (instance->status >> TD_STATUS_CC_SHIFT) & TD_STATUS_CC_MASK;
    105123        return cc_to_rc(cc);
    106124}
    107125
     126/**
     127 * Get remaining portion of buffer to be read/written
     128 * @param instance TD structure
     129 * @return size of remaining buffer.
     130 */
    108131static inline size_t td_remain_size(td_t *instance)
    109132{
    110133        assert(instance);
     134        /* Current buffer pointer is cleared on successful transfer */
    111135        if (instance->cbp == 0)
    112136                return 0;
     137        /* Buffer end points to the last byte of transfer buffer, so add 1 */
    113138        return instance->be - instance->cbp + 1;
    114139}
  • uspace/drv/bus/usb/ohci/ohci.c

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

    r4c3ad56 r20a3465  
    5959                free(ohci_batch->tds);
    6060        }
    61         usb_transfer_batch_dispose(ohci_batch->usb_batch);
     61        usb_transfer_batch_destroy(ohci_batch->usb_batch);
    6262        free32(ohci_batch->device_buffer);
    6363        free(ohci_batch);
     
    163163            ohci_batch->ed->td_tail, ohci_batch->ed->next);
    164164
    165         size_t i = 0;
    166         for (; i < ohci_batch->td_count; ++i) {
     165        if (!ed_inactive(ohci_batch->ed) && ed_transfer_pending(ohci_batch->ed))
     166                return false;
     167
     168        /* Now we may be sure that either the ED is inactive because of errors
     169         * or all transfer descriptors completed successfully */
     170
     171        /* Assume all data got through */
     172        ohci_batch->usb_batch->transfered_size =
     173            ohci_batch->usb_batch->buffer_size;
     174
     175        /* Assume we will leave the last(unused) TD behind */
     176        ohci_batch->leave_td = ohci_batch->td_count;
     177
     178        /* Check all TDs */
     179        for (size_t i = 0; i < ohci_batch->td_count; ++i) {
    167180                assert(ohci_batch->tds[i] != NULL);
    168181                usb_log_debug("TD %zu: %08x:%08x:%08x:%08x.\n", i,
    169182                    ohci_batch->tds[i]->status, ohci_batch->tds[i]->cbp,
    170183                    ohci_batch->tds[i]->next, ohci_batch->tds[i]->be);
    171                 if (!td_is_finished(ohci_batch->tds[i])) {
    172                         return false;
    173                 }
     184
     185                /* If the TD got all its data through, it will report 0 bytes
     186                 * remain, the sole exception is INPUT with data rounding flag
     187                 * (short), i.e. every INPUT. Nice thing is that short packets
     188                 * will correctly report remaining data, thus making
     189                 * this computation correct (short packets need to be produced
     190                 * by the last TD)
     191                 * NOTE: This also works for CONTROL transfer as
     192                 * the first TD will return 0 remain.
     193                 * NOTE: Short packets don't break the assumption that
     194                 * we leave the very last(unused) TD behind.
     195                 */
     196                ohci_batch->usb_batch->transfered_size
     197                    -= td_remain_size(ohci_batch->tds[i]);
     198
    174199                ohci_batch->usb_batch->error = td_error(ohci_batch->tds[i]);
    175200                if (ohci_batch->usb_batch->error != EOK) {
     
    177202                            ohci_batch->usb_batch, i,
    178203                            ohci_batch->tds[i]->status);
    179                         /* Make sure TD queue is empty (one TD),
    180                          * ED should be marked as halted */
    181                         ohci_batch->ed->td_tail =
    182                             (ohci_batch->ed->td_head & ED_TDTAIL_PTR_MASK);
    183                         ++i;
     204
     205                        /* ED should be stopped because of errors */
     206                        assert((ohci_batch->ed->td_head & ED_TDHEAD_HALTED_FLAG) != 0);
     207
     208                        /* Now we have a problem: we don't know what TD
     209                         * the head pointer points to, the retiring rules
     210                         * described in specs say it should be the one after
     211                         * the failed one so set the tail pointer accordingly.
     212                         * It will be the one TD we leave behind.
     213                         */
     214                        ohci_batch->leave_td = i + 1;
     215
     216                        /* Check TD assumption */
     217                        const uint32_t pa = addr_to_phys(
     218                            ohci_batch->tds[ohci_batch->leave_td]);
     219                        assert((ohci_batch->ed->td_head & ED_TDTAIL_PTR_MASK)
     220                            == pa);
     221
     222                        ed_set_tail_td(ohci_batch->ed,
     223                            ohci_batch->tds[ohci_batch->leave_td]);
     224
     225                        /* Clear possible ED HALT */
     226                        ohci_batch->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
    184227                        break;
    185228                }
    186229        }
    187 
    188         assert(i <= ohci_batch->td_count);
    189         ohci_batch->leave_td = i;
    190 
     230        assert(ohci_batch->usb_batch->transfered_size <=
     231            ohci_batch->usb_batch->buffer_size);
     232
     233        /* Store the remaining TD */
    191234        ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->usb_batch->ep);
    192235        assert(ohci_ep);
    193236        ohci_ep->td = ohci_batch->tds[ohci_batch->leave_td];
    194         assert(i > 0);
    195         ohci_batch->usb_batch->transfered_size =
    196             ohci_batch->usb_batch->buffer_size;
    197         for (--i;i < ohci_batch->td_count; ++i) {
    198                 ohci_batch->usb_batch->transfered_size
    199                     -= td_remain_size(ohci_batch->tds[i]);
    200         }
    201 
    202         /* Clear possible ED HALT */
    203         ohci_batch->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
    204         /* just make sure that we are leaving the right TD behind */
     237
     238        /* Make sure that we are leaving the right TD behind */
    205239        const uint32_t pa = addr_to_phys(ohci_ep->td);
    206240        assert(pa == (ohci_batch->ed->td_head & ED_TDHEAD_PTR_MASK));
     
    217251{
    218252        assert(ohci_batch);
    219         ed_set_end_td(ohci_batch->ed, ohci_batch->tds[ohci_batch->td_count]);
     253        ed_set_tail_td(ohci_batch->ed, ohci_batch->tds[ohci_batch->td_count]);
    220254}
    221255/*----------------------------------------------------------------------------*/
     
    247281        const usb_direction_t status_dir = reverse_dir[dir];
    248282
    249         /* setup stage */
    250         td_init(ohci_batch->tds[0], USB_DIRECTION_BOTH, buffer,
    251                 ohci_batch->usb_batch->setup_size, toggle);
    252         td_set_next(ohci_batch->tds[0], ohci_batch->tds[1]);
     283        /* Setup stage */
     284        td_init(
     285            ohci_batch->tds[0], ohci_batch->tds[1], USB_DIRECTION_BOTH,
     286            buffer, ohci_batch->usb_batch->setup_size, toggle);
    253287        usb_log_debug("Created CONTROL SETUP TD: %08x:%08x:%08x:%08x.\n",
    254288            ohci_batch->tds[0]->status, ohci_batch->tds[0]->cbp,
     
    256290        buffer += ohci_batch->usb_batch->setup_size;
    257291
    258         /* data stage */
     292        /* Data stage */
    259293        size_t td_current = 1;
    260294        size_t remain_size = ohci_batch->usb_batch->buffer_size;
     
    265299                toggle = 1 - toggle;
    266300
    267                 td_init(ohci_batch->tds[td_current], data_dir, buffer,
    268                     transfer_size, toggle);
    269                 td_set_next(ohci_batch->tds[td_current],
    270                     ohci_batch->tds[td_current + 1]);
     301                td_init(ohci_batch->tds[td_current],
     302                    ohci_batch->tds[td_current + 1],
     303                    data_dir, buffer, transfer_size, toggle);
    271304                usb_log_debug("Created CONTROL DATA TD: %08x:%08x:%08x:%08x.\n",
    272305                    ohci_batch->tds[td_current]->status,
     
    281314        }
    282315
    283         /* status stage */
     316        /* Status stage */
    284317        assert(td_current == ohci_batch->td_count - 1);
    285         td_init(ohci_batch->tds[td_current], status_dir, NULL, 0, 1);
    286         td_set_next(ohci_batch->tds[td_current],
    287             ohci_batch->tds[td_current + 1]);
     318        td_init(ohci_batch->tds[td_current], ohci_batch->tds[td_current + 1],
     319            status_dir, NULL, 0, 1);
    288320        usb_log_debug("Created CONTROL STATUS TD: %08x:%08x:%08x:%08x.\n",
    289321            ohci_batch->tds[td_current]->status,
     
    323355                    ? OHCI_TD_MAX_TRANSFER : remain_size;
    324356
    325                 td_init(ohci_batch->tds[td_current], dir, buffer,
    326                     transfer_size, -1);
    327                 td_set_next(ohci_batch->tds[td_current],
    328                     ohci_batch->tds[td_current + 1]);
     357                td_init(
     358                    ohci_batch->tds[td_current], ohci_batch->tds[td_current + 1],
     359                    dir, buffer, transfer_size, -1);
    329360
    330361                usb_log_debug("Created DATA TD: %08x:%08x:%08x:%08x.\n",
  • uspace/drv/bus/usb/ohci/ohci_endpoint.c

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

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

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

    r4c3ad56 r20a3465  
    3535#include <errno.h>
    3636#include <str_error.h>
     37#include <fibril_synch.h>
    3738
    3839#include <usb/debug.h>
     40#include <usb/dev/request.h>
     41#include <usb/classes/hub.h>
    3942
    4043#include "root_hub.h"
     
    4346#include <usb/dev/driver.h>
    4447#include "ohci_regs.h"
    45 
    46 #include <usb/dev/request.h>
    47 #include <usb/classes/hub.h>
    4848
    4949/**
     
    108108static void create_serialized_hub_descriptor(rh_t *instance);
    109109static void rh_init_descriptors(rh_t *instance);
    110 static uint16_t create_interrupt_mask(rh_t *instance);
    111 static int get_status(rh_t *instance, usb_transfer_batch_t *request);
    112 static int get_descriptor(rh_t *instance, usb_transfer_batch_t *request);
    113 static int set_feature(rh_t *instance, usb_transfer_batch_t *request);
    114 static int clear_feature(rh_t *instance, usb_transfer_batch_t *request);
    115 static int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port);
    116 static int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port);
     110static uint16_t create_interrupt_mask(const rh_t *instance);
     111static int get_status(const rh_t *instance, usb_transfer_batch_t *request);
     112static int get_descriptor(const rh_t *instance, usb_transfer_batch_t *request);
     113static int set_feature(const rh_t *instance, usb_transfer_batch_t *request);
     114static int clear_feature(const rh_t *instance, usb_transfer_batch_t *request);
     115static int set_feature_port(
     116    const rh_t *instance, uint16_t feature, uint16_t port);
     117static int clear_feature_port(
     118    const rh_t *instance, uint16_t feature, uint16_t port);
    117119static int control_request(rh_t *instance, usb_transfer_batch_t *request);
    118120static inline void interrupt_request(
     
    153155        instance->unfinished_interrupt_transfer = NULL;
    154156
    155 #ifdef OHCI_POWER_SWITCH_no
     157#if defined OHCI_POWER_SWITCH_no
    156158        /* Set port power mode to no power-switching. (always on) */
    157159        instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
     160
    158161        /* Set to no over-current reporting */
    159162        instance->registers->rh_desc_a |= RHDA_NOCP_FLAG;
     163
    160164#elif defined OHCI_POWER_SWITCH_ganged
    161165        /* Set port power mode to no ganged power-switching. */
     
    163167        instance->registers->rh_desc_a &= ~RHDA_PSM_FLAG;
    164168        instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
     169
    165170        /* Set to global over-current */
    166171        instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
     
    174179        instance->registers->rh_desc_b &= (RHDB_PCC_MASK << RHDB_PCC_SHIFT);
    175180        instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;
     181
    176182        /* Return control to per port state */
    177183        instance->registers->rh_desc_b |=
    178184                ((1 << (instance->port_count + 1)) - 1) << RHDB_PCC_SHIFT;
     185
    179186        /* Set per port over-current */
    180187        instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;
     
    182189#endif
    183190
     191        fibril_mutex_initialize(&instance->guard);
    184192        rh_init_descriptors(instance);
    185193
     
    209217        case USB_TRANSFER_INTERRUPT:
    210218                usb_log_debug("Root hub got INTERRUPT packet\n");
     219                fibril_mutex_lock(&instance->guard);
     220                assert(instance->unfinished_interrupt_transfer == NULL);
    211221                const uint16_t mask = create_interrupt_mask(instance);
    212222                if (mask == 0) {
    213223                        usb_log_debug("No changes..\n");
    214                         assert(instance->unfinished_interrupt_transfer == NULL);
    215224                        instance->unfinished_interrupt_transfer = request;
     225                        fibril_mutex_unlock(&instance->guard);
    216226                        return;
    217227                }
    218228                usb_log_debug("Processing changes...\n");
    219229                interrupt_request(request, mask, instance->interrupt_mask_size);
     230                fibril_mutex_unlock(&instance->guard);
    220231                break;
    221232
     
    224235                usb_transfer_batch_finish_error(request, NULL, 0, EINVAL);
    225236        }
    226         usb_transfer_batch_dispose(request);
     237        usb_transfer_batch_destroy(request);
    227238}
    228239/*----------------------------------------------------------------------------*/
     
    237248        assert(instance);
    238249
    239         if (!instance->unfinished_interrupt_transfer)
    240                 return;
    241 
    242         usb_log_debug("Finalizing interrupt transfer\n");
    243         const uint16_t mask = create_interrupt_mask(instance);
    244         interrupt_request(instance->unfinished_interrupt_transfer,
    245             mask, instance->interrupt_mask_size);
    246         usb_transfer_batch_dispose(instance->unfinished_interrupt_transfer);
    247 
    248         instance->unfinished_interrupt_transfer = NULL;
     250        fibril_mutex_lock(&instance->guard);
     251        if (instance->unfinished_interrupt_transfer) {
     252                usb_log_debug("Finalizing interrupt transfer\n");
     253                const uint16_t mask = create_interrupt_mask(instance);
     254                interrupt_request(instance->unfinished_interrupt_transfer,
     255                    mask, instance->interrupt_mask_size);
     256                usb_transfer_batch_destroy(
     257                    instance->unfinished_interrupt_transfer);
     258                instance->unfinished_interrupt_transfer = NULL;
     259        }
     260        fibril_mutex_unlock(&instance->guard);
    249261}
    250262/*----------------------------------------------------------------------------*/
     
    342354 * @return Mask of changes.
    343355 */
    344 uint16_t create_interrupt_mask(rh_t *instance)
     356uint16_t create_interrupt_mask(const rh_t *instance)
    345357{
    346358        assert(instance);
     
    372384 * @return error code
    373385 */
    374 int get_status(rh_t *instance, usb_transfer_batch_t *request)
     386int get_status(const rh_t *instance, usb_transfer_batch_t *request)
    375387{
    376388        assert(instance);
     
    418430 * @return Error code
    419431 */
    420 int get_descriptor(rh_t *instance, usb_transfer_batch_t *request)
     432int get_descriptor(const rh_t *instance, usb_transfer_batch_t *request)
    421433{
    422434        assert(instance);
     
    496508 * @return error code
    497509 */
    498 int set_feature_port(rh_t *instance, uint16_t feature, uint16_t port)
     510int set_feature_port(const rh_t *instance, uint16_t feature, uint16_t port)
    499511{
    500512        assert(instance);
     
    535547 * @return error code
    536548 */
    537 int clear_feature_port(rh_t *instance, uint16_t feature, uint16_t port)
     549int clear_feature_port(const rh_t *instance, uint16_t feature, uint16_t port)
    538550{
    539551        assert(instance);
     
    592604 * @return error code
    593605 */
    594 int set_feature(rh_t *instance, usb_transfer_batch_t *request)
     606int set_feature(const rh_t *instance, usb_transfer_batch_t *request)
    595607{
    596608        assert(instance);
     
    628640 * @return error code
    629641 */
    630 int clear_feature(rh_t *instance, usb_transfer_batch_t *request)
     642int clear_feature(const rh_t *instance, usb_transfer_batch_t *request)
    631643{
    632644        assert(instance);
     
    635647        const usb_device_request_setup_packet_t *setup_request =
    636648            (usb_device_request_setup_packet_t *) request->setup_buffer;
     649
    637650        request->transfered_size = 0;
     651
    638652        switch (setup_request->request_type)
    639653        {
     
    647661                /*
    648662                 * Chapter 11.16.2 specifies that only C_HUB_LOCAL_POWER and
    649                  * C_HUB_OVER_CURRENT are supported. C_HUB_OVER_CURRENT is represented
    650                  * by OHCI RHS_OCIC_FLAG. C_HUB_LOCAL_POWER is not supported
     663                 * C_HUB_OVER_CURRENT are supported.
     664                 * C_HUB_OVER_CURRENT is represented by OHCI RHS_OCIC_FLAG.
     665                 * C_HUB_LOCAL_POWER is not supported
    651666                 * as root hubs do not support local power status feature.
    652667                 * (OHCI pg. 127) */
     
    720735                    "additional data\n");
    721736                return clear_feature(instance, request);
     737
    722738        case USB_DEVREQ_SET_FEATURE:
    723739                usb_log_debug2("Processing request without "
  • uspace/drv/bus/usb/ohci/root_hub.h

    r4c3ad56 r20a3465  
    4747 */
    4848typedef struct rh {
     49        fibril_mutex_t guard;
    4950        /** pointer to ohci driver registers */
    5051        ohci_regs_t *registers;
  • uspace/drv/bus/usb/ohci/utils/malloc32.h

    r4c3ad56 r20a3465  
    4141#include <as.h>
    4242
     43/* Generic TDs and EDs require 16byte alignment,
     44 * Isochronous TD require 32byte alignment,
     45 * buffers do not have to be aligned.
     46 */
     47#define OHCI_ALIGN 32
     48
    4349/** Get physical address translation
    4450 *
     
    6268 */
    6369static inline void * malloc32(size_t size)
    64         { return memalign(size, size); }
     70        { return memalign(OHCI_ALIGN, size); }
    6571/*----------------------------------------------------------------------------*/
    6672/** Physical mallocator simulator
  • uspace/drv/bus/usb/uhci/hc.c

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

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

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

    r4c3ad56 r20a3465  
    6464        }
    6565
     66        dev->driver_data = ctl_fun;
     67
    6668        usb_log_info("Pretending to control %s `%s'" \
    6769            " (node `%s', handle %" PRIun ").\n",
     
    7274}
    7375
     76/** Callback when new device is about to be removed.
     77 *
     78 * @param dev Representation of a generic DDF device.
     79 * @return Error code.
     80 */
     81static int usbfallback_device_remove(usb_device_t *dev)
     82{
     83        return EOK;
     84}
     85
     86/** Callback when new device is removed and recognized as gone by DDF.
     87 *
     88 * @param dev Representation of a generic DDF device.
     89 * @return Error code.
     90 */
     91static int usbfallback_device_gone(usb_device_t *dev)
     92{
     93        assert(dev);
     94        ddf_fun_t *ctl_fun = dev->driver_data;
     95        const int ret = ddf_fun_unbind(ctl_fun);
     96        if (ret != EOK) {
     97                usb_log_error("Failed to unbind %s.\n", ctl_fun->name);
     98                return ret;
     99        }
     100        ddf_fun_destroy(ctl_fun);
     101        dev->driver_data = NULL;
     102
     103        return EOK;
     104}
     105
    74106/** USB fallback driver ops. */
    75 static usb_driver_ops_t usbfallback_driver_ops = {
     107static const usb_driver_ops_t usbfallback_driver_ops = {
    76108        .device_add = usbfallback_device_add,
     109        .device_rem = usbfallback_device_remove,
     110        .device_gone = usbfallback_device_gone,
    77111};
    78112
    79113/** USB fallback driver. */
    80 static usb_driver_t usbfallback_driver = {
     114static const usb_driver_t usbfallback_driver = {
    81115        .name = NAME,
    82116        .ops = &usbfallback_driver_ops,
  • uspace/drv/bus/usb/usbhid/generic/hiddev.c

    r4c3ad56 r20a3465  
    4848/*----------------------------------------------------------------------------*/
    4949
    50 usb_endpoint_description_t usb_hid_generic_poll_endpoint_description = {
     50const usb_endpoint_description_t usb_hid_generic_poll_endpoint_description = {
    5151        .transfer_type = USB_TRANSFER_INTERRUPT,
    5252        .direction = USB_DIRECTION_IN,
    5353        .interface_class = USB_CLASS_HID,
     54        .interface_subclass = -1,
     55        .interface_protocol = -1,
    5456        .flags = 0
    5557};
     
    9294        usb_log_debug2("Generic HID: Get event length (fun: %p, "
    9395            "fun->driver_data: %p.\n", fun, fun->driver_data);
    94        
     96
    9597        if (fun == NULL || fun->driver_data == NULL) {
    9698                return 0;
     
    98100
    99101        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
    100        
     102
    101103        usb_log_debug2("hid_dev: %p, Max input report size (%zu).\n",
    102104            hid_dev, hid_dev->max_input_report_size);
    103        
     105
    104106        return hid_dev->max_input_report_size;
    105107}
     
    111113{
    112114        usb_log_debug2("Generic HID: Get event.\n");
    113        
     115
    114116        if (fun == NULL || fun->driver_data == NULL || buffer == NULL
    115117            || act_size == NULL || event_nr == NULL) {
     
    119121
    120122        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
    121        
     123
    122124        if (hid_dev->input_report_size > size) {
    123125                usb_log_debug("input_report_size > size (%zu, %zu)\n",
     
    125127                return EINVAL;  // TODO: other error code
    126128        }
    127        
     129
    128130        /*! @todo This should probably be somehow atomic. */
    129131        memcpy(buffer, hid_dev->input_report,
     
    131133        *act_size = hid_dev->input_report_size;
    132134        *event_nr = usb_hid_report_number(hid_dev);
    133        
     135
    134136        usb_log_debug2("OK\n");
    135        
     137
    136138        return EOK;
    137139}
     
    142144{
    143145        usb_log_debug("Generic HID: Get report descriptor length.\n");
    144        
     146
    145147        if (fun == NULL || fun->driver_data == NULL) {
    146148                usb_log_debug("No function");
    147149                return EINVAL;
    148150        }
    149        
    150         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
    151        
     151
     152        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
     153
    152154        usb_log_debug2("hid_dev->report_desc_size = %zu\n",
    153155            hid_dev->report_desc_size);
    154        
     156
    155157        return hid_dev->report_desc_size;
    156158}
     
    162164{
    163165        usb_log_debug2("Generic HID: Get report descriptor.\n");
    164        
     166
    165167        if (fun == NULL || fun->driver_data == NULL) {
    166168                usb_log_debug("No function");
    167169                return EINVAL;
    168170        }
    169        
    170         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
    171        
     171
     172        usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)fun->driver_data;
     173
    172174        if (hid_dev->report_desc_size > size) {
    173175                return EINVAL;
    174176        }
    175        
     177
    176178        memcpy(desc, hid_dev->report_desc, hid_dev->report_desc_size);
    177179        *actual_size = hid_dev->report_desc_size;
    178        
     180
    179181        return EOK;
    180182}
     
    190192/*----------------------------------------------------------------------------*/
    191193
    192 static int usb_generic_hid_create_function(usb_hid_dev_t *hid_dev)
    193 {       
     194void usb_generic_hid_deinit(usb_hid_dev_t *hid_dev, void *data)
     195{
     196        ddf_fun_t *fun = data;
     197        const int ret = ddf_fun_unbind(fun);
     198        if (ret != EOK) {
     199                usb_log_error("Failed to unbind generic hid fun.\n");
     200                return;
     201        }
     202        usb_log_debug2("%s unbound.\n", fun->name);
     203        /* We did not allocate this, so leave this alone
     204         * the device would take care of it */
     205        fun->driver_data = NULL;
     206        ddf_fun_destroy(fun);
     207}
     208
     209/*----------------------------------------------------------------------------*/
     210
     211int usb_generic_hid_init(usb_hid_dev_t *hid_dev, void **data)
     212{
     213        if (hid_dev == NULL) {
     214                return EINVAL;
     215        }
     216
    194217        /* Create the exposed function. */
    195218        /** @todo Generate numbers for the devices? */
     
    201224                return ENOMEM;
    202225        }
    203        
     226
    204227        fun->ops = &usb_generic_hid_ops;
    205         fun->driver_data = hid_dev;
    206228
    207229        int rc = ddf_fun_bind(fun);
     
    212234                return rc;
    213235        }
    214        
     236        /* This is nasty both device and this function have the same
     237         * driver data, thus destruction would lead to double free */
     238        fun->driver_data = hid_dev;
     239
    215240        usb_log_debug("HID function created. Handle: %" PRIun "\n", fun->handle);
    216        
    217         return EOK;
    218 }
    219 
    220 /*----------------------------------------------------------------------------*/
    221 
    222 int usb_generic_hid_init(usb_hid_dev_t *hid_dev, void **data)
    223 {
    224         if (hid_dev == NULL) {
    225                 return EINVAL;
    226         }
    227        
    228         return usb_generic_hid_create_function(hid_dev);
     241        *data = fun;
     242
     243        return EOK;
    229244}
    230245
  • uspace/drv/bus/usb/usbhid/generic/hiddev.h

    r4c3ad56 r20a3465  
    4141struct usb_hid_dev;
    4242
    43 usb_endpoint_description_t usb_hid_generic_poll_endpoint_description;
     43extern const usb_endpoint_description_t
     44    usb_hid_generic_poll_endpoint_description;
    4445
    4546const char *HID_GENERIC_FUN_NAME;
     
    5051int usb_generic_hid_init(struct usb_hid_dev *hid_dev, void **data);
    5152
     53void usb_generic_hid_deinit(struct usb_hid_dev *hid_dev, void *data);
     54
    5255bool usb_generic_hid_polling_callback(struct usb_hid_dev *hid_dev, void *data);
    5356
  • uspace/drv/bus/usb/usbhid/kbd/conv.c

    r4c3ad56 r20a3465  
    8787        [0x26] = KC_9,
    8888        [0x27] = KC_0,
    89        
     89
    9090        [0x28] = KC_ENTER,
    9191        [0x29] = KC_ESCAPE,
     
    109109
    110110        [0x39] = KC_CAPS_LOCK,
    111        
     111
    112112        [0x3a] = KC_F1,
    113113        [0x3b] = KC_F2,
     
    122122        [0x44] = KC_F11,
    123123        [0x45] = KC_F12,
    124        
     124
    125125        [0x46] = KC_PRTSCR,
    126126        [0x47] = KC_SCROLL_LOCK,
     
    136136        [0x51] = KC_DOWN,
    137137        [0x52] = KC_UP,
    138        
     138
    139139        //[0x64] = // some funny key
    140        
     140
    141141        [0xe0] = KC_LCTRL,
    142142        [0xe1] = KC_LSHIFT,
     
    147147        [0xe6] = KC_RALT,
    148148        //[0xe7] = KC_R // TODO: right GUI
    149        
     149
    150150        [0x53] = KC_NUM_LOCK,
    151151        [0x54] = KC_NSLASH,
     
    165165        [0x62] = KC_N0,
    166166        [0x63] = KC_NPERIOD
    167        
     167
    168168};
    169169
     
    186186
    187187        key = map[scancode];
    188        
     188
    189189        return key;
    190190}
  • uspace/drv/bus/usb/usbhid/kbd/kbddev.c

    r4c3ad56 r20a3465  
    8888
    8989/** Keyboard polling endpoint description for boot protocol class. */
    90 usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description = {
     90const usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description = {
    9191        .transfer_type = USB_TRANSFER_INTERRUPT,
    9292        .direction = USB_DIRECTION_IN,
     
    174174{
    175175        sysarg_t method = IPC_GET_IMETHOD(*icall);
    176        
     176
    177177        usb_kbd_t *kbd_dev = (usb_kbd_t *) fun->driver_data;
    178178        if (kbd_dev == NULL) {
     
    182182                return;
    183183        }
    184        
     184
    185185        async_sess_t *sess =
    186186            async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
     
    237237
    238238        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    239             hid_dev->report, NULL, kbd_dev->led_path,
     239            &hid_dev->report, NULL, kbd_dev->led_path,
    240240            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    241241            USB_HID_REPORT_TYPE_OUTPUT);
    242        
     242
    243243        while (field != NULL) {
    244                
    245                 if ((field->usage == USB_HID_LED_NUM_LOCK) 
     244
     245                if ((field->usage == USB_HID_LED_NUM_LOCK)
    246246                    && (kbd_dev->mods & KM_NUM_LOCK)){
    247247                        field->value = 1;
    248248                }
    249249
    250                 if ((field->usage == USB_HID_LED_CAPS_LOCK) 
     250                if ((field->usage == USB_HID_LED_CAPS_LOCK)
    251251                    && (kbd_dev->mods & KM_CAPS_LOCK)){
    252252                        field->value = 1;
    253253                }
    254254
    255                 if ((field->usage == USB_HID_LED_SCROLL_LOCK) 
     255                if ((field->usage == USB_HID_LED_SCROLL_LOCK)
    256256                    && (kbd_dev->mods & KM_SCROLL_LOCK)){
    257257                        field->value = 1;
    258258                }
    259                
    260                 field = usb_hid_report_get_sibling(hid_dev->report, field,
    261                     kbd_dev->led_path, 
    262                 USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    263                         USB_HID_REPORT_TYPE_OUTPUT);
    264         }
    265        
     259
     260                field = usb_hid_report_get_sibling(
     261                    &hid_dev->report, field, kbd_dev->led_path,
     262                USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     263                    USB_HID_REPORT_TYPE_OUTPUT);
     264        }
     265
    266266        // TODO: what about the Report ID?
    267         int rc = usb_hid_report_output_translate(hid_dev->report, 0,
     267        int rc = usb_hid_report_output_translate(&hid_dev->report, 0,
    268268            kbd_dev->output_buffer, kbd_dev->output_size);
    269        
     269
    270270        if (rc != EOK) {
    271271                usb_log_warning("Error translating LED output to output report"
     
    273273                return;
    274274        }
    275        
     275
    276276        usb_log_debug("Output report buffer: %s\n",
    277277            usb_debug_str_buffer(kbd_dev->output_buffer, kbd_dev->output_size,
    278278                0));
    279        
     279
    280280        usbhid_req_set_report(&hid_dev->usb_dev->ctrl_pipe,
    281281            hid_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT,
     
    300300                return;
    301301        }
    302        
     302
    303303        async_exch_t *exch = async_exchange_begin(kbd_dev->console_sess);
    304304        async_msg_2(exch, KBDEV_EVENT, type, key);
     
    347347        unsigned int key;
    348348        size_t i;
    349        
     349
    350350        /*
    351351         * First of all, check if the kbd have reported phantom state.
     
    362362                return;
    363363        }
    364        
     364
    365365        /*
    366366         * Key releases
     
    382382                }
    383383        }
    384        
     384
    385385        /*
    386386         * Key presses
     
    402402                }
    403403        }
    404        
     404
    405405        memcpy(kbd_dev->keys_old, kbd_dev->keys, kbd_dev->key_count * 4);
    406        
     406
    407407        char key_buffer[512];
    408408        ddf_dump_buffer(key_buffer, 512,
     
    432432static void usb_kbd_process_data(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
    433433{
    434         assert(hid_dev->report != NULL);
    435434        assert(hid_dev != NULL);
    436435        assert(kbd_dev != NULL);
    437        
     436
    438437        usb_hid_report_path_t *path = usb_hid_report_path();
    439438        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    440439
    441440        usb_hid_report_path_set_report_id (path, hid_dev->report_id);
    442        
     441
    443442        // fill in the currently pressed keys
    444        
     443
    445444        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    446             hid_dev->report, NULL, path,
    447             USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
     445            &hid_dev->report, NULL, path,
     446            USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    448447            USB_HID_REPORT_TYPE_INPUT);
    449448        unsigned i = 0;
    450        
     449
    451450        while (field != NULL) {
    452451                usb_log_debug2("FIELD (%p) - VALUE(%d) USAGE(%u)\n",
     
    454453               
    455454                assert(i < kbd_dev->key_count);
    456                
     455
    457456                // save the key usage
    458457                if (field->value != 0) {
     
    463462                }
    464463                usb_log_debug2("Saved %u. key usage %d\n", i, kbd_dev->keys[i]);
    465                
     464
    466465                ++i;
    467                 field = usb_hid_report_get_sibling(hid_dev->report, field, path,
    468                     USB_HID_PATH_COMPARE_END
    469                     | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
     466                field = usb_hid_report_get_sibling(
     467                    &hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
     468                        | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    470469                    USB_HID_REPORT_TYPE_INPUT);
    471470        }
    472        
     471
    473472        usb_hid_report_path_free(path);
    474        
     473
    475474        usb_kbd_check_key_changes(hid_dev, kbd_dev);
    476475}
     
    502501
    503502        if (kbd_dev == NULL) {
    504                 usb_log_fatal("No memory!\n");
     503                usb_log_error("No memory!\n");
    505504                return NULL;
    506505        }
    507        
     506
    508507        kbd_dev->console_sess = NULL;
    509508        kbd_dev->initialized = USB_KBD_STATUS_UNINITIALIZED;
    510        
     509
    511510        return kbd_dev;
    512511}
     
    514513/*----------------------------------------------------------------------------*/
    515514
    516 static int usb_kbd_create_function(usb_hid_dev_t *hid_dev, usb_kbd_t *kbd_dev)
    517 {
    518         assert(hid_dev != NULL);
    519         assert(hid_dev->usb_dev != NULL);
     515static int usb_kbd_create_function(usb_kbd_t *kbd_dev)
     516{
    520517        assert(kbd_dev != NULL);
    521        
     518        assert(kbd_dev->hid_dev != NULL);
     519        assert(kbd_dev->hid_dev->usb_dev != NULL);
     520
    522521        /* Create the exposed function. */
    523522        usb_log_debug("Creating DDF function %s...\n", HID_KBD_FUN_NAME);
    524         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    525             HID_KBD_FUN_NAME);
     523        ddf_fun_t *fun = ddf_fun_create(kbd_dev->hid_dev->usb_dev->ddf_dev,
     524            fun_exposed, HID_KBD_FUN_NAME);
    526525        if (fun == NULL) {
    527526                usb_log_error("Could not create DDF function node.\n");
    528527                return ENOMEM;
    529528        }
    530        
     529
    531530        /*
    532531         * Store the initialized HID device and HID ops
     
    540539                usb_log_error("Could not bind DDF function: %s.\n",
    541540                    str_error(rc));
     541                fun->driver_data = NULL; /* We need this later */
    542542                ddf_fun_destroy(fun);
    543543                return rc;
    544544        }
    545        
     545
    546546        usb_log_debug("%s function created. Handle: %" PRIun "\n",
    547547            HID_KBD_FUN_NAME, fun->handle);
    548        
     548
    549549        usb_log_debug("Adding DDF function to category %s...\n",
    550550            HID_KBD_CLASS_NAME);
     
    554554                    "Could not add DDF function to category %s: %s.\n",
    555555                    HID_KBD_CLASS_NAME, str_error(rc));
     556                fun->driver_data = NULL; /* We need this later */
    556557                ddf_fun_destroy(fun);
    557558                return rc;
    558559        }
    559        
     560        kbd_dev->fun = fun;
     561
    560562        return EOK;
    561563}
     
    587589{
    588590        usb_log_debug("Initializing HID/KBD structure...\n");
    589        
     591
    590592        if (hid_dev == NULL) {
    591593                usb_log_error("Failed to init keyboard structure: no structure"
     
    593595                return EINVAL;
    594596        }
    595        
     597
    596598        usb_kbd_t *kbd_dev = usb_kbd_new();
    597599        if (kbd_dev == NULL) {
     
    603605        /* Store link to HID device */
    604606        kbd_dev->hid_dev = hid_dev;
    605        
     607
    606608        /*
    607609         * TODO: make more general
     
    609611        usb_hid_report_path_t *path = usb_hid_report_path();
    610612        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
    611        
     613
    612614        usb_hid_report_path_set_report_id(path, 0);
    613        
     615
    614616        kbd_dev->key_count = usb_hid_report_size(
    615             hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
     617            &hid_dev->report, 0, USB_HID_REPORT_TYPE_INPUT);
    616618        usb_hid_report_path_free(path);
    617        
     619
    618620        usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
    619        
    620         kbd_dev->keys = (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
    621        
     621
     622        kbd_dev->keys = calloc(kbd_dev->key_count, sizeof(int32_t));
     623
    622624        if (kbd_dev->keys == NULL) {
    623                 usb_log_fatal("No memory!\n");
     625                usb_log_error("No memory!\n");
    624626                free(kbd_dev);
    625627                return ENOMEM;
    626628        }
    627        
     629
    628630        kbd_dev->keys_old =
    629631                (int32_t *)calloc(kbd_dev->key_count, sizeof(int32_t));
    630        
     632
    631633        if (kbd_dev->keys_old == NULL) {
    632                 usb_log_fatal("No memory!\n");
     634                usb_log_error("No memory!\n");
    633635                free(kbd_dev->keys);
    634636                free(kbd_dev);
    635637                return ENOMEM;
    636638        }
    637        
     639
    638640        /*
    639641         * Output report
    640642         */
    641643        kbd_dev->output_size = 0;
    642         kbd_dev->output_buffer = usb_hid_report_output(hid_dev->report,
     644        kbd_dev->output_buffer = usb_hid_report_output(&hid_dev->report,
    643645            &kbd_dev->output_size, 0);
    644646        if (kbd_dev->output_buffer == NULL) {
     
    647649                return ENOMEM;
    648650        }
    649        
     651
    650652        usb_log_debug("Output buffer size: %zu\n", kbd_dev->output_size);
    651        
     653
    652654        kbd_dev->led_path = usb_hid_report_path();
    653655        usb_hid_report_path_append_item(
    654656            kbd_dev->led_path, USB_HIDUT_PAGE_LED, 0);
    655        
    656         kbd_dev->led_output_size = usb_hid_report_size(hid_dev->report,
    657             0, USB_HID_REPORT_TYPE_OUTPUT);
    658        
     657
     658        kbd_dev->led_output_size = usb_hid_report_size(
     659            &hid_dev->report, 0, USB_HID_REPORT_TYPE_OUTPUT);
     660
    659661        usb_log_debug("Output report size (in items): %zu\n",
    660662            kbd_dev->led_output_size);
    661        
     663
    662664        kbd_dev->led_data = (int32_t *)calloc(
    663665            kbd_dev->led_output_size, sizeof(int32_t));
    664        
     666
    665667        if (kbd_dev->led_data == NULL) {
    666668                usb_log_warning("Error creating buffer for LED output report."
     
    671673                return ENOMEM;
    672674        }
    673        
     675
    674676        /*
    675677         * Modifiers and locks
     
    678680        kbd_dev->mods = DEFAULT_ACTIVE_MODS;
    679681        kbd_dev->lock_keys = 0;
    680        
     682
    681683        /*
    682684         * Autorepeat
     
    686688        kbd_dev->repeat.delay_before = DEFAULT_DELAY_BEFORE_FIRST_REPEAT;
    687689        kbd_dev->repeat.delay_between = DEFAULT_REPEAT_DELAY;
    688        
    689         kbd_dev->repeat_mtx = (fibril_mutex_t *)(
    690             malloc(sizeof(fibril_mutex_t)));
    691         if (kbd_dev->repeat_mtx == NULL) {
    692                 usb_log_fatal("No memory!\n");
    693                 free(kbd_dev->keys);
    694                 usb_hid_report_output_free(kbd_dev->output_buffer);
    695                 free(kbd_dev);
    696                 return ENOMEM;
    697         }
    698        
    699         fibril_mutex_initialize(kbd_dev->repeat_mtx);
    700        
     690
     691        fibril_mutex_initialize(&kbd_dev->repeat_mtx);
     692
    701693        // save the KBD device structure into the HID device structure
    702694        *data = kbd_dev;
    703        
     695
    704696        // set handler for incoming calls
    705697        kbd_dev->ops.default_handler = default_connection_handler;
    706        
     698
    707699        /*
    708700         * Set LEDs according to initial setup.
     
    710702         */
    711703        usb_kbd_set_led(hid_dev, kbd_dev);
    712        
     704
    713705        usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    714706            hid_dev->usb_dev->interface_no, IDLE_RATE);
    715        
     707
    716708        /*
    717709         * Create new fibril for auto-repeat
     
    723715        }
    724716        fibril_add_ready(fid);
    725        
     717
    726718        kbd_dev->initialized = USB_KBD_STATUS_INITIALIZED;
    727719        usb_log_debug("HID/KBD device structure initialized.\n");
    728        
     720
    729721        usb_log_debug("Creating KBD function...\n");
    730         int rc = usb_kbd_create_function(hid_dev, kbd_dev);
     722        int rc = usb_kbd_create_function(kbd_dev);
    731723        if (rc != EOK) {
    732724                usb_kbd_destroy(kbd_dev);
    733725                return rc;
    734726        }
    735        
     727
    736728        return EOK;
    737729}
     
    745737                return false;
    746738        }
    747        
     739
    748740        usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
    749741        assert(kbd_dev != NULL);
    750        
     742
    751743        // TODO: add return value from this function
    752744        usb_kbd_process_data(hid_dev, kbd_dev);
    753        
     745
    754746        return true;
    755747}
     
    780772                return;
    781773        }
    782        
     774
    783775        // hangup session to the console
    784776        async_hangup(kbd_dev->console_sess);
    785        
    786         if (kbd_dev->repeat_mtx != NULL) {
    787                 //assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
    788                 // FIXME - the fibril_mutex_is_locked may not cause
    789                 // fibril scheduling
    790                 while (fibril_mutex_is_locked(kbd_dev->repeat_mtx)) {}
    791                 free(kbd_dev->repeat_mtx);
    792         }
    793        
     777
     778        //assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
     779        // FIXME - the fibril_mutex_is_locked may not cause
     780        // fibril scheduling
     781        while (fibril_mutex_is_locked(&kbd_dev->repeat_mtx)) {}
     782
    794783        // free all buffers
    795         if (kbd_dev->keys != NULL) {
    796                 free(kbd_dev->keys);
    797         }
    798         if (kbd_dev->keys_old != NULL) {
    799                 free(kbd_dev->keys_old);
    800         }
    801         if (kbd_dev->led_data != NULL) {
    802                 free(kbd_dev->led_data);
    803         }
     784        free(kbd_dev->keys);
     785        free(kbd_dev->keys_old);
     786        free(kbd_dev->led_data);
     787
    804788        if (kbd_dev->led_path != NULL) {
    805789                usb_hid_report_path_free(kbd_dev->led_path);
     
    808792                usb_hid_report_output_free(kbd_dev->output_buffer);
    809793        }
     794
     795        if (ddf_fun_unbind(kbd_dev->fun) != EOK) {
     796                usb_log_warning("Failed to unbind kbd function.\n");
     797        } else {
     798                usb_log_debug2("%s unbound.\n", kbd_dev->fun->name);
     799                kbd_dev->fun->driver_data = NULL;
     800                ddf_fun_destroy(kbd_dev->fun);
     801        }
    810802}
    811803
     
    817809                return;
    818810        }
    819        
     811
    820812        if (data != NULL) {
    821                 usb_kbd_t *kbd_dev = (usb_kbd_t *)data;
     813                usb_kbd_t *kbd_dev = data;
    822814                if (usb_kbd_is_initialized(kbd_dev)) {
    823815                        usb_kbd_mark_unusable(kbd_dev);
    824                 } else {
     816                        /* wait for autorepeat */
     817                        async_usleep(CHECK_DELAY);
    825818                        usb_kbd_destroy(kbd_dev);
    826819                }
     
    832825int usb_kbd_set_boot_protocol(usb_hid_dev_t *hid_dev)
    833826{
    834         int rc = usb_hid_parse_report_descriptor(hid_dev->report,
    835             USB_KBD_BOOT_REPORT_DESCRIPTOR,
     827        int rc = usb_hid_parse_report_descriptor(
     828            &hid_dev->report, USB_KBD_BOOT_REPORT_DESCRIPTOR,
    836829            USB_KBD_BOOT_REPORT_DESCRIPTOR_SIZE);
    837        
     830
    838831        if (rc != EOK) {
    839832                usb_log_error("Failed to parse boot report descriptor: %s\n",
     
    841834                return rc;
    842835        }
    843        
    844         rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe, 
     836
     837        rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe,
    845838            hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT);
    846        
     839
    847840        if (rc != EOK) {
    848841                usb_log_warning("Failed to set boot protocol to the device: "
     
    850843                return rc;
    851844        }
    852        
     845
    853846        return EOK;
    854847}
  • uspace/drv/bus/usb/usbhid/kbd/kbddev.h

    r4c3ad56 r20a3465  
    7575        /** Currently pressed modifiers (bitmap). */
    7676        uint8_t modifiers;
    77        
     77
    7878        /** Currently active modifiers including locks. Sent to the console. */
    7979        unsigned mods;
    80        
     80
    8181        /** Currently active lock keys. */
    8282        unsigned lock_keys;
    83        
     83
    8484        /** IPC session to the console device (for sending key events). */
    8585        async_sess_t *console_sess;
    86        
     86
    8787        /** @todo What is this actually? */
    8888        ddf_dev_ops_t ops;
    89        
     89
    9090        /** Information for auto-repeat of keys. */
    9191        usb_kbd_repeat_t repeat;
    92        
     92
    9393        /** Mutex for accessing the information about auto-repeat. */
    94         fibril_mutex_t *repeat_mtx;
    95        
     94        fibril_mutex_t repeat_mtx;
     95
    9696        uint8_t *output_buffer;
    97        
     97
    9898        size_t output_size;
    99        
     99
    100100        size_t led_output_size;
    101        
     101
    102102        usb_hid_report_path_t *led_path;
    103        
     103
    104104        int32_t *led_data;
    105        
     105
    106106        /** State of the structure (for checking before use).
    107107         *
     
    111111         */
    112112        int initialized;
     113
     114        /** DDF function */
     115        ddf_fun_t *fun;
    113116} usb_kbd_t;
    114117
    115118/*----------------------------------------------------------------------------*/
    116119
    117 usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description;
     120extern const usb_endpoint_description_t usb_hid_kbd_poll_endpoint_description;
    118121
    119122const char *HID_KBD_FUN_NAME;
  • uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.c

    r4c3ad56 r20a3465  
    4646
    4747
    48 /** Delay between auto-repeat state checks when no key is being repeated. */
    49 static unsigned int CHECK_DELAY = 10000;
    5048
    5149/*----------------------------------------------------------------------------*/
     
    7371{
    7472        unsigned int delay = 0;
    75        
     73
    7674        usb_log_debug("Starting autorepeat loop.\n");
    7775
     
    7977                // check if the kbd structure is usable
    8078                if (!usb_kbd_is_initialized(kbd)) {
    81                         if (usb_kbd_is_ready_to_destroy(kbd)) {
    82                                 usb_kbd_destroy(kbd);
    83                         }
     79                        usb_log_warning("kbd not ready, exiting autorepeat.\n");
    8480                        return;
    8581                }
    8682               
    87                 fibril_mutex_lock(kbd->repeat_mtx);
     83                fibril_mutex_lock(&kbd->repeat_mtx);
    8884
    8985                if (kbd->repeat.key_new > 0) {
     
    109105                        delay = CHECK_DELAY;
    110106                }
    111                 fibril_mutex_unlock(kbd->repeat_mtx);
     107                fibril_mutex_unlock(&kbd->repeat_mtx);
    112108               
    113109                async_usleep(delay);
     
    130126{
    131127        usb_log_debug("Autorepeat fibril spawned.\n");
    132        
     128
    133129        if (arg == NULL) {
    134130                usb_log_error("No device!\n");
    135131                return EINVAL;
    136132        }
    137        
     133
    138134        usb_kbd_t *kbd = (usb_kbd_t *)arg;
    139        
     135
    140136        usb_kbd_repeat_loop(kbd);
    141        
     137
    142138        return EOK;
    143139}
     
    156152void usb_kbd_repeat_start(usb_kbd_t *kbd, unsigned int key)
    157153{
    158         fibril_mutex_lock(kbd->repeat_mtx);
     154        fibril_mutex_lock(&kbd->repeat_mtx);
    159155        kbd->repeat.key_new = key;
    160         fibril_mutex_unlock(kbd->repeat_mtx);
     156        fibril_mutex_unlock(&kbd->repeat_mtx);
    161157}
    162158
     
    174170void usb_kbd_repeat_stop(usb_kbd_t *kbd, unsigned int key)
    175171{
    176         fibril_mutex_lock(kbd->repeat_mtx);
     172        fibril_mutex_lock(&kbd->repeat_mtx);
    177173        if (key == kbd->repeat.key_new) {
    178174                kbd->repeat.key_new = 0;
    179175        }
    180         fibril_mutex_unlock(kbd->repeat_mtx);
     176        fibril_mutex_unlock(&kbd->repeat_mtx);
    181177}
    182178
  • uspace/drv/bus/usb/usbhid/kbd/kbdrepeat.h

    r4c3ad56 r20a3465  
    3737#define USB_HID_KBDREPEAT_H_
    3838
     39/** Delay between auto-repeat state checks when no key is being repeated. */
     40#define CHECK_DELAY 10000
     41
    3942struct usb_kbd_t;
    4043
  • uspace/drv/bus/usb/usbhid/main.c

    r4c3ad56 r20a3465  
    4646#include "usbhid.h"
    4747
    48 /*----------------------------------------------------------------------------*/
    49 
    5048#define NAME "usbhid"
    5149
     
    6765 *
    6866 * @param dev Device to add.
    69  *
    70  * @retval EOK if successful.
    71  * @retval ENOMEM if there
    72  * @return Other error code inherited from one of functions usb_kbd_init(),
    73  *         ddf_fun_bind() and ddf_fun_add_to_class().
     67 * @return Error code.
    7468 */
    7569static int usb_hid_try_add_device(usb_device_t *dev)
    7670{
    7771        assert(dev != NULL);
    78        
    79         /*
    80          * Initialize device (get and process descriptors, get address, etc.)
    81          */
     72
     73        /* Initialize device (get and process descriptors, get address, etc.) */
    8274        usb_log_debug("Initializing USB/HID device...\n");
    83        
    84         usb_hid_dev_t *hid_dev = usb_hid_new();
     75
     76        usb_hid_dev_t *hid_dev =
     77            usb_device_data_alloc(dev, sizeof(usb_hid_dev_t));
    8578        if (hid_dev == NULL) {
    8679                usb_log_error("Error while creating USB/HID device "
     
    8881                return ENOMEM;
    8982        }
    90        
     83
    9184        int rc = usb_hid_init(hid_dev, dev);
    92        
     85
    9386        if (rc != EOK) {
    9487                usb_log_error("Failed to initialize USB/HID device.\n");
    95                 usb_hid_destroy(hid_dev);
     88                usb_hid_deinit(hid_dev);
    9689                return rc;
    97         }       
    98        
     90        }
     91
    9992        usb_log_debug("USB/HID device structure initialized.\n");
    100        
     93
    10194        /*
    10295         * 1) subdriver vytvori vlastnu ddf_fun, vlastne ddf_dev_ops, ktore da
     
    109102         *    pouzit usb/classes/hid/iface.h - prvy int je telefon
    110103         */
    111        
     104
    112105        /* Start automated polling function.
    113106         * This will create a separate fibril that will query the device
     
    125118           /* Custom argument. */
    126119           hid_dev);
    127        
    128        
     120
    129121        if (rc != EOK) {
    130122                usb_log_error("Failed to start polling fibril for `%s'.\n",
    131123                    dev->ddf_dev->name);
     124                usb_hid_deinit(hid_dev);
    132125                return rc;
    133126        }
     127        hid_dev->running = true;
    134128
    135129        /*
     
    138132        return EOK;
    139133}
    140 
    141134/*----------------------------------------------------------------------------*/
    142135/**
     
    146139 *
    147140 * @param dev Structure representing the new device.
    148  *
    149  * @retval EOK if successful.
    150  * @retval EREFUSED if the device is not supported.
     141 * @return Error code.
    151142 */
    152143static int usb_hid_device_add(usb_device_t *dev)
    153144{
    154145        usb_log_debug("usb_hid_device_add()\n");
    155        
     146
    156147        if (dev == NULL) {
    157148                usb_log_warning("Wrong parameter given for add_device().\n");
    158149                return EINVAL;
    159150        }
    160        
     151
    161152        if (dev->interface_no < 0) {
    162153                usb_log_warning("Device is not a supported HID device.\n");
     
    165156                return ENOTSUP;
    166157        }
    167        
     158
    168159        int rc = usb_hid_try_add_device(dev);
    169        
     160
    170161        if (rc != EOK) {
    171162                usb_log_warning("Device is not a supported HID device.\n");
     
    174165                return rc;
    175166        }
    176        
     167
    177168        usb_log_info("HID device `%s' ready to use.\n", dev->ddf_dev->name);
    178169
    179170        return EOK;
    180171}
    181 
    182 /*----------------------------------------------------------------------------*/
    183 
    184 /* Currently, the framework supports only device adding. Once the framework
    185  * supports unplug, more callbacks will be added. */
    186 static usb_driver_ops_t usb_hid_driver_ops = {
    187         .device_add = usb_hid_device_add,
     172/*----------------------------------------------------------------------------*/
     173/**
     174 * Callback for a device about to be removed from the driver.
     175 *
     176 * @param dev Structure representing the device.
     177 * @return Error code.
     178 */
     179static int usb_hid_device_rem(usb_device_t *dev)
     180{
     181        return EOK;
     182}
     183/*----------------------------------------------------------------------------*/
     184/**
     185 * Callback for removing a device from the driver.
     186 *
     187 * @param dev Structure representing the device.
     188 * @return Error code.
     189 */
     190static int usb_hid_device_gone(usb_device_t *dev)
     191{
     192        usb_hid_dev_t *hid_dev = dev->driver_data;
     193        unsigned tries = 10;
     194        while (hid_dev->running) {
     195                async_usleep(100000);
     196                if (!tries--) {
     197                        usb_log_error("Can't remove hub, still running.\n");
     198                        return EBUSY;
     199                }
     200        }
     201
     202        assert(!hid_dev->running);
     203        usb_hid_deinit(hid_dev);
     204        usb_log_debug2("%s destruction complete.\n", dev->ddf_dev->name);
     205        return EOK;
     206}
     207/*----------------------------------------------------------------------------*/
     208/** USB generic driver callbacks */
     209static const usb_driver_ops_t usb_hid_driver_ops = {
     210        .device_add = usb_hid_device_add,
     211        .device_rem = usb_hid_device_rem,
     212        .device_gone = usb_hid_device_gone,
    188213};
    189 
    190 
    191 /* The driver itself. */
    192 static usb_driver_t usb_hid_driver = {
     214/*----------------------------------------------------------------------------*/
     215/** The driver itself. */
     216static const usb_driver_t usb_hid_driver = {
    193217        .name = NAME,
    194218        .ops = &usb_hid_driver_ops,
    195219        .endpoints = usb_hid_endpoints
    196220};
    197 
    198 /*----------------------------------------------------------------------------*/
    199 
     221/*----------------------------------------------------------------------------*/
    200222int main(int argc, char *argv[])
    201223{
     
    206228        return usb_driver_main(&usb_hid_driver);
    207229}
    208 
    209230/**
    210231 * @}
  • uspace/drv/bus/usb/usbhid/mouse/mousedev.c

    r4c3ad56 r20a3465  
    5959/*----------------------------------------------------------------------------*/
    6060
    61 usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description = {
     61const usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description = {
    6262        .transfer_type = USB_TRANSFER_INTERRUPT,
    6363        .direction = USB_DIRECTION_IN,
     
    124124{
    125125        usb_mouse_t *mouse_dev = (usb_mouse_t *) fun->driver_data;
    126        
     126
    127127        if (mouse_dev == NULL) {
    128128                usb_log_debug("default_connection_handler: Missing "
     
    131131                return;
    132132        }
    133        
     133
    134134        usb_log_debug("default_connection_handler: fun->name: %s\n",
    135135                      fun->name);
    136136        usb_log_debug("default_connection_handler: mouse_sess: %p, "
    137137            "wheel_sess: %p\n", mouse_dev->mouse_sess, mouse_dev->wheel_sess);
    138        
     138
    139139        async_sess_t **sess_ptr =
    140140            (str_cmp(fun->name, HID_MOUSE_FUN_NAME) == 0) ?
    141141            &mouse_dev->mouse_sess : &mouse_dev->wheel_sess;
    142        
     142
    143143        async_sess_t *sess =
    144144            async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
     
    170170        mouse->mouse_sess = NULL;
    171171        mouse->wheel_sess = NULL;
    172        
     172
    173173        return mouse;
    174174}
     
    179179{
    180180        assert(mouse_dev != NULL);
    181        
     181
    182182        // hangup session to the console
    183183        if (mouse_dev->mouse_sess != NULL)
    184184                async_hangup(mouse_dev->mouse_sess);
    185        
     185
    186186        if (mouse_dev->wheel_sess != NULL)
    187187                async_hangup(mouse_dev->wheel_sess);
     188        int ret = ddf_fun_unbind(mouse_dev->mouse_fun);
     189        if (ret != EOK) {
     190                usb_log_error("Failed to unbind mouse function.\n");
     191        } else {
     192                ddf_fun_destroy(mouse_dev->mouse_fun);
     193                /* Prevent double free */
     194                mouse_dev->wheel_fun->driver_data = NULL;
     195        }
     196
     197        ret = ddf_fun_unbind(mouse_dev->wheel_fun);
     198        if (ret != EOK) {
     199                usb_log_error("Failed to unbind wheel function.\n");
     200        } else {
     201                ddf_fun_destroy(mouse_dev->wheel_fun);
     202        }
    188203}
    189204
     
    199214                return;
    200215        }
    201        
     216
    202217        int count = ((wheel < 0) ? -wheel : wheel) * ARROWS_PER_SINGLE_WHEEL;
    203218        int i;
    204        
     219
    205220        for (i = 0; i < count; i++) {
    206221                /* Send arrow press and release. */
     
    246261{
    247262        assert(mouse_dev != NULL);
    248        
     263
    249264        if (mouse_dev->mouse_sess == NULL) {
    250265                usb_log_warning(NAME " No console session.\n");
     
    253268
    254269        int shift_x = get_mouse_axis_move_value(hid_dev->report_id,
    255             hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_X);
     270            &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_X);
    256271        int shift_y = get_mouse_axis_move_value(hid_dev->report_id,
    257             hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_Y);
     272            &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_Y);
    258273        int wheel = get_mouse_axis_move_value(hid_dev->report_id,
    259             hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
     274            &hid_dev->report, USB_HIDUT_USAGE_GENERIC_DESKTOP_WHEEL);
    260275
    261276        if ((shift_x != 0) || (shift_y != 0)) {
    262                 async_exch_t *exch = async_exchange_begin(mouse_dev->mouse_sess);
     277                async_exch_t *exch =
     278                    async_exchange_begin(mouse_dev->mouse_sess);
    263279                async_req_2_0(exch, MOUSEEV_MOVE_EVENT, shift_x, shift_y);
    264280                async_exchange_end(exch);
    265281        }
    266        
     282
    267283        if (wheel != 0)
    268284                usb_mouse_send_wheel(mouse_dev, wheel);
    269        
     285
    270286        /*
    271287         * Buttons
     
    274290        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_BUTTON, 0);
    275291        usb_hid_report_path_set_report_id(path, hid_dev->report_id);
    276        
     292
    277293        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    278             hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
    279             | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    280             USB_HID_REPORT_TYPE_INPUT);
     294            &hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
     295            | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, USB_HID_REPORT_TYPE_INPUT);
    281296
    282297        while (field != NULL) {
     
    299314                        async_req_2_0(exch, MOUSEEV_BUTTON_EVENT, field->usage, 0);
    300315                        async_exchange_end(exch);
    301                        
     316
    302317                        mouse_dev->buttons[field->usage - field->usage_minimum] =
    303318                           field->value;
    304319                }
    305                
     320
    306321                field = usb_hid_report_get_sibling(
    307                     hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
    308                     | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
     322                    &hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
     323                    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    309324                    USB_HID_REPORT_TYPE_INPUT);
    310325        }
    311        
     326
    312327        usb_hid_report_path_free(path);
    313328
     
    321336        assert(hid_dev != NULL);
    322337        assert(mouse != NULL);
    323        
     338
    324339        /* Create the exposed function. */
    325340        usb_log_debug("Creating DDF function %s...\n", HID_MOUSE_FUN_NAME);
     
    330345                return ENOMEM;
    331346        }
    332        
     347
    333348        fun->ops = &mouse->ops;
    334349        fun->driver_data = mouse;
     
    338353                usb_log_error("Could not bind DDF function: %s.\n",
    339354                    str_error(rc));
    340                 ddf_fun_destroy(fun);
    341                 return rc;
    342         }
    343        
     355                return rc;
     356        }
     357
    344358        usb_log_debug("Adding DDF function to category %s...\n",
    345359            HID_MOUSE_CATEGORY);
     
    349363                    "Could not add DDF function to category %s: %s.\n",
    350364                    HID_MOUSE_CATEGORY, str_error(rc));
    351                 ddf_fun_destroy(fun);
    352                 return rc;
    353         }
    354        
     365                return rc;
     366        }
     367        mouse->mouse_fun = fun;
     368
    355369        /*
    356370         * Special function for acting as keyboard (wheel)
     
    364378                return ENOMEM;
    365379        }
    366        
     380
    367381        /*
    368382         * Store the initialized HID device and HID ops
     
    376390                usb_log_error("Could not bind DDF function: %s.\n",
    377391                    str_error(rc));
    378                 ddf_fun_destroy(fun);
    379                 return rc;
    380         }
    381        
     392                return rc;
     393        }
     394
    382395        usb_log_debug("Adding DDF function to category %s...\n",
    383396            HID_MOUSE_WHEEL_CATEGORY);
     
    387400                    "Could not add DDF function to category %s: %s.\n",
    388401                    HID_MOUSE_WHEEL_CATEGORY, str_error(rc));
    389                 ddf_fun_destroy(fun);
    390                 return rc;
    391         }
    392        
     402                return rc;
     403        }
     404        mouse->wheel_fun = fun;
     405
    393406        return EOK;
    394407}
     
    441454{
    442455        usb_log_debug("Initializing HID/Mouse structure...\n");
    443        
     456
    444457        if (hid_dev == NULL) {
    445458                usb_log_error("Failed to init keyboard structure: no structure"
     
    447460                return EINVAL;
    448461        }
    449        
     462
    450463        usb_mouse_t *mouse_dev = usb_mouse_new();
    451464        if (mouse_dev == NULL) {
     
    454467                return ENOMEM;
    455468        }
    456        
     469
    457470        // FIXME: This may not be optimal since stupid hardware vendor may
    458471        // use buttons 1, 2, 3 and 6000 and we would allocate array of
     
    461474        // that the current solution is good enough.
    462475        /* Adding 1 because we will be accessing buttons[highest]. */
    463         mouse_dev->buttons_count = usb_mouse_get_highest_button(hid_dev->report,
    464             hid_dev->report_id) + 1;
     476        mouse_dev->buttons_count = 1 + usb_mouse_get_highest_button(
     477            &hid_dev->report, hid_dev->report_id);
    465478        mouse_dev->buttons = calloc(mouse_dev->buttons_count, sizeof(int32_t));
    466        
     479
    467480        if (mouse_dev->buttons == NULL) {
    468481                usb_log_error(NAME ": out of memory, giving up on device!\n");
     
    474487        // save the Mouse device structure into the HID device structure
    475488        *data = mouse_dev;
    476        
     489
    477490        // set handler for incoming calls
    478491        mouse_dev->ops.default_handler = default_connection_handler;
    479        
     492
    480493        // TODO: how to know if the device supports the request???
    481494        usbhid_req_set_idle(&hid_dev->usb_dev->ctrl_pipe,
    482495            hid_dev->usb_dev->interface_no, IDLE_RATE);
    483        
     496
    484497        int rc = usb_mouse_create_function(hid_dev, mouse_dev);
    485498        if (rc != EOK) {
     
    487500                return rc;
    488501        }
    489        
     502
    490503        return EOK;
    491504}
     
    500513                return false;
    501514        }
    502        
     515
    503516        usb_mouse_t *mouse_dev = (usb_mouse_t *)data;
    504517               
     
    511524{
    512525        if (data != NULL) {
    513                 usb_mouse_destroy((usb_mouse_t *)data);
     526                usb_mouse_destroy(data);
    514527        }
    515528}
     
    519532int usb_mouse_set_boot_protocol(usb_hid_dev_t *hid_dev)
    520533{
    521         int rc = usb_hid_parse_report_descriptor(hid_dev->report,
    522             USB_MOUSE_BOOT_REPORT_DESCRIPTOR,
     534        int rc = usb_hid_parse_report_descriptor(
     535            &hid_dev->report, USB_MOUSE_BOOT_REPORT_DESCRIPTOR,
    523536            USB_MOUSE_BOOT_REPORT_DESCRIPTOR_SIZE);
    524        
     537
    525538        if (rc != EOK) {
    526539                usb_log_error("Failed to parse boot report descriptor: %s\n",
     
    528541                return rc;
    529542        }
    530        
    531         rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe, 
     543
     544        rc = usbhid_req_set_protocol(&hid_dev->usb_dev->ctrl_pipe,
    532545            hid_dev->usb_dev->interface_no, USB_HID_PROTOCOL_BOOT);
    533        
     546
    534547        if (rc != EOK) {
    535548                usb_log_warning("Failed to set boot protocol to the device: "
     
    537550                return rc;
    538551        }
    539        
     552
    540553        return EOK;
    541554}
  • uspace/drv/bus/usb/usbhid/mouse/mousedev.h

    r4c3ad56 r20a3465  
    4949        async_sess_t *mouse_sess;
    5050        async_sess_t *wheel_sess;
    51        
     51
    5252        /* Mouse buttons statuses. */
    5353        int32_t *buttons;
    5454        size_t buttons_count;
    55        
     55
    5656        ddf_dev_ops_t ops;
     57        /* DDF mouse function */
     58        ddf_fun_t *mouse_fun;
     59        /* DDF mouse function */
     60        ddf_fun_t *wheel_fun;
    5761} usb_mouse_t;
    5862
    5963/*----------------------------------------------------------------------------*/
    6064
    61 usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description;
     65extern const usb_endpoint_description_t usb_hid_mouse_poll_endpoint_description;
    6266
    6367const char *HID_MOUSE_FUN_NAME;
  • uspace/drv/bus/usb/usbhid/multimedia/multimedia.c

    r4c3ad56 r20a3465  
    6464        //int32_t *keys;
    6565        /** Count of stored keys (i.e. number of keys in the report). */
    66         //size_t key_count;     
     66        //size_t key_count;
    6767        /** IPC session to the console device (for sending key events). */
    6868        async_sess_t *console_sess;
     69        /** DDF function */
     70        ddf_fun_t *fun;
    6971} usb_multimedia_t;
    7072
     
    8688{
    8789        usb_log_debug(NAME " default_connection_handler()\n");
    88        
     90
    8991        usb_multimedia_t *multim_dev = (usb_multimedia_t *)fun->driver_data;
    90        
     92
    9193        if (multim_dev == NULL) {
    9294                async_answer_0(icallid, EINVAL);
    9395                return;
    9496        }
    95        
     97
    9698        async_sess_t *sess =
    9799            async_callback_receive_start(EXCHANGE_SERIALIZE, icall);
     
    137139        assert(hid_dev != NULL);
    138140        assert(multim_dev != NULL);
    139        
     141
    140142        kbd_event_t ev;
    141        
     143
    142144        ev.type = type;
    143145        ev.key = key;
     
    151153                return;
    152154        }
    153        
     155
    154156        async_exch_t *exch = async_exchange_begin(multim_dev->console_sess);
    155157        async_msg_4(exch, KBDEV_EVENT, ev.type, ev.key, ev.mods, ev.c);
     
    159161/*----------------------------------------------------------------------------*/
    160162
    161 static int usb_multimedia_create_function(usb_hid_dev_t *hid_dev,
    162     usb_multimedia_t *multim_dev)
    163 {
     163int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data)
     164{
     165        if (hid_dev == NULL || hid_dev->usb_dev == NULL) {
     166                return EINVAL; /*! @todo Other return code? */
     167        }
     168
     169        usb_log_debug(NAME " Initializing HID/multimedia structure...\n");
     170
    164171        /* Create the exposed function. */
    165         ddf_fun_t *fun = ddf_fun_create(hid_dev->usb_dev->ddf_dev, fun_exposed,
    166             NAME);
     172        ddf_fun_t *fun = ddf_fun_create(
     173            hid_dev->usb_dev->ddf_dev, fun_exposed, NAME);
    167174        if (fun == NULL) {
    168175                usb_log_error("Could not create DDF function node.\n");
    169176                return ENOMEM;
    170177        }
    171        
     178
    172179        fun->ops = &multimedia_ops;
    173         fun->driver_data = multim_dev;   // TODO: maybe change to hid_dev->data
    174        
     180
     181        usb_multimedia_t *multim_dev =
     182            ddf_fun_data_alloc(fun, sizeof(usb_multimedia_t));
     183        if (multim_dev == NULL) {
     184                ddf_fun_destroy(fun);
     185                return ENOMEM;
     186        }
     187
     188        multim_dev->console_sess = NULL;
     189        multim_dev->fun = fun;
     190
     191        //todo Autorepeat?
     192
    175193        int rc = ddf_fun_bind(fun);
    176194        if (rc != EOK) {
    177195                usb_log_error("Could not bind DDF function: %s.\n",
    178196                    str_error(rc));
    179                 // TODO: Can / should I destroy the DDF function?
    180197                ddf_fun_destroy(fun);
    181198                return rc;
    182199        }
    183        
     200
    184201        usb_log_debug("%s function created (handle: %" PRIun ").\n",
    185202            NAME, fun->handle);
    186        
     203
    187204        rc = ddf_fun_add_to_category(fun, "keyboard");
    188205        if (rc != EOK) {
     
    190207                    "Could not add DDF function to category 'keyboard': %s.\n",
    191208                    str_error(rc));
    192                 // TODO: Can / should I destroy the DDF function?
    193209                ddf_fun_destroy(fun);
    194210                return rc;
    195211        }
    196        
    197         return EOK;
    198 }
    199 
    200 /*----------------------------------------------------------------------------*/
    201 
    202 int usb_multimedia_init(struct usb_hid_dev *hid_dev, void **data)
    203 {
    204         if (hid_dev == NULL || hid_dev->usb_dev == NULL) {
    205                 return EINVAL; /*! @todo Other return code? */
    206         }
    207        
    208         usb_log_debug(NAME " Initializing HID/multimedia structure...\n");
    209        
    210         usb_multimedia_t *multim_dev = (usb_multimedia_t *)malloc(
    211             sizeof(usb_multimedia_t));
    212         if (multim_dev == NULL) {
    213                 return ENOMEM;
    214         }
    215        
    216         multim_dev->console_sess = NULL;
    217        
    218         /*! @todo Autorepeat */
    219        
    220         // save the KBD device structure into the HID device structure
     212
     213        /* Save the KBD device structure into the HID device structure. */
    221214        *data = multim_dev;
    222        
    223         usb_log_debug(NAME " HID/multimedia device structure initialized.\n");
    224        
    225         int rc = usb_multimedia_create_function(hid_dev, multim_dev);
    226         if (rc != EOK)
    227                 return rc;
    228        
     215
    229216        usb_log_debug(NAME " HID/multimedia structure initialized.\n");
    230        
    231217        return EOK;
    232218}
     
    239225                return;
    240226        }
    241        
     227
    242228        if (data != NULL) {
    243229                usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
    244230                // hangup session to the console
    245231                async_hangup(multim_dev->console_sess);
     232                const int ret = ddf_fun_unbind(multim_dev->fun);
     233                if (ret != EOK) {
     234                        usb_log_error("Failed to unbind multim function.\n");
     235                } else {
     236                        usb_log_debug2("%s unbound.\n", multim_dev->fun->name);
     237                        ddf_fun_destroy(multim_dev->fun);
     238                }
    246239        }
    247240}
     
    257250
    258251        usb_multimedia_t *multim_dev = (usb_multimedia_t *)data;
    259        
     252
    260253        usb_hid_report_path_t *path = usb_hid_report_path();
    261254        usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_CONSUMER, 0);
     
    264257
    265258        usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    266             hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
    267             | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
     259            &hid_dev->report, NULL, path, USB_HID_PATH_COMPARE_END
     260            | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    268261            USB_HID_REPORT_TYPE_INPUT);
    269262
     
    283276                                               key);
    284277                }
    285                
     278
    286279                field = usb_hid_report_get_sibling(
    287                     hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
     280                    &hid_dev->report, field, path, USB_HID_PATH_COMPARE_END
    288281                    | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
    289282                    USB_HID_REPORT_TYPE_INPUT);
    290         }       
     283        }
    291284
    292285        usb_hid_report_path_free(path);
    293        
     286
    294287        return true;
    295288}
  • uspace/drv/bus/usb/usbhid/subdrivers.c

    r4c3ad56 r20a3465  
    4242#include "generic/hiddev.h"
    4343
    44 static usb_hid_subdriver_usage_t path_kbd[] = {
    45         {USB_HIDUT_PAGE_GENERIC_DESKTOP, 
    46          USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYBOARD}, 
     44static const usb_hid_subdriver_usage_t path_kbd[] = {
     45        {USB_HIDUT_PAGE_GENERIC_DESKTOP,
     46         USB_HIDUT_USAGE_GENERIC_DESKTOP_KEYBOARD},
    4747        {0, 0}
    4848};
    4949
    50 static usb_hid_subdriver_usage_t path_mouse[] = {
     50static const usb_hid_subdriver_usage_t path_mouse[] = {
    5151        {USB_HIDUT_PAGE_GENERIC_DESKTOP, USB_HIDUT_USAGE_GENERIC_DESKTOP_MOUSE},
    5252        {0, 0}
    5353};
    5454
    55 static usb_hid_subdriver_usage_t multim_key_path[] = {
     55static const usb_hid_subdriver_usage_t multim_key_path[] = {
    5656        {USB_HIDUT_PAGE_CONSUMER, USB_HIDUT_USAGE_CONSUMER_CONSUMER_CONTROL},
    5757        {0, 0}
     
    7171                        .poll_end = NULL
    7272                },
    73                
    7473        },
    7574        {
     
    102101};
    103102
     103const int USB_HID_MAX_SUBDRIVERS =
     104    sizeof(usb_hid_subdrivers) / sizeof(usb_hid_subdrivers[0]);
     105
    104106/**
    105107 * @}
  • uspace/drv/bus/usb/usbhid/subdrivers.h

    r4c3ad56 r20a3465  
    6464         */
    6565        const usb_hid_subdriver_usage_t *usage_path;
    66        
     66
    6767        /** Report ID for which the path should apply. */
    6868        int report_id;
    69        
     69
    7070        /** Compare type for the Usage path. */
    7171        int compare;
    72        
     72
    7373        /** Vendor ID (set to -1 if not specified). */
    7474        int vendor_id;
    75        
     75
    7676        /** Product ID (set to -1 if not specified). */
    7777        int product_id;
    78        
     78
    7979        /** Subdriver for controlling this device. */
    80         usb_hid_subdriver_t subdriver;
     80        const usb_hid_subdriver_t subdriver;
    8181} usb_hid_subdriver_mapping_t;
    8282
     
    8484
    8585extern const usb_hid_subdriver_mapping_t usb_hid_subdrivers[];
     86extern const int USB_HID_MAX_SUBDRIVERS;
    8687
    8788/*----------------------------------------------------------------------------*/
  • uspace/drv/bus/usb/usbhid/usbhid.c

    r4c3ad56 r20a3465  
    5454
    5555/* Array of endpoints expected on the device, NULL terminated. */
    56 usb_endpoint_description_t *usb_hid_endpoints[USB_HID_POLL_EP_COUNT + 1] = {
     56const usb_endpoint_description_t *usb_hid_endpoints[] = {
    5757        &usb_hid_kbd_poll_endpoint_description,
    5858        &usb_hid_mouse_poll_endpoint_description,
     
    6161};
    6262
    63 static const int USB_HID_MAX_SUBDRIVERS = 10;
    64 
    6563/*----------------------------------------------------------------------------*/
    6664
    6765static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
    6866{
    69         assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
    70        
    71         hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
    72             sizeof(usb_hid_subdriver_t));
     67        assert(hid_dev != NULL);
     68        assert(hid_dev->subdriver_count == 0);
     69
     70        hid_dev->subdrivers = malloc(sizeof(usb_hid_subdriver_t));
    7371        if (hid_dev->subdrivers == NULL) {
    7472                return ENOMEM;
    7573        }
    76        
    77         assert(hid_dev->subdriver_count >= 0);
    78        
    79         // set the init callback
    80         hid_dev->subdrivers[hid_dev->subdriver_count].init = usb_kbd_init;
    81        
    82         // set the polling callback
    83         hid_dev->subdrivers[hid_dev->subdriver_count].poll =
    84             usb_kbd_polling_callback;
    85        
    86         // set the polling ended callback
    87         hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
    88        
    89         // set the deinit callback
    90         hid_dev->subdrivers[hid_dev->subdriver_count].deinit = usb_kbd_deinit;
    91        
    92         // set subdriver count
    93         ++hid_dev->subdriver_count;
    94        
     74        hid_dev->subdriver_count = 1;
     75        // TODO 0 should be keyboard, but find a better way
     76        hid_dev->subdrivers[0] = usb_hid_subdrivers[0].subdriver;
     77
    9578        return EOK;
    9679}
     
    10083static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
    10184{
    102         assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
    103        
    104         hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
    105             sizeof(usb_hid_subdriver_t));
     85        assert(hid_dev != NULL);
     86        assert(hid_dev->subdriver_count == 0);
     87
     88        hid_dev->subdrivers = malloc(sizeof(usb_hid_subdriver_t));
    10689        if (hid_dev->subdrivers == NULL) {
    10790                return ENOMEM;
    10891        }
    109        
    110         assert(hid_dev->subdriver_count >= 0);
    111        
    112         // set the init callback
    113         hid_dev->subdrivers[hid_dev->subdriver_count].init = usb_mouse_init;
    114        
    115         // set the polling callback
    116         hid_dev->subdrivers[hid_dev->subdriver_count].poll =
    117             usb_mouse_polling_callback;
    118        
    119         // set the polling ended callback
    120         hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
    121        
    122         // set the deinit callback
    123         hid_dev->subdrivers[hid_dev->subdriver_count].deinit = usb_mouse_deinit;
    124        
    125         // set subdriver count
    126         ++hid_dev->subdriver_count;
    127        
     92        hid_dev->subdriver_count = 1;
     93        // TODO 2 should be mouse, but find a better way
     94        hid_dev->subdrivers[2] = usb_hid_subdrivers[0].subdriver;
     95
    12896        return EOK;
    12997}
     
    134102{
    135103        assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
    136        
    137         hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
    138             sizeof(usb_hid_subdriver_t));
     104
     105        hid_dev->subdrivers = malloc(sizeof(usb_hid_subdriver_t));
    139106        if (hid_dev->subdrivers == NULL) {
    140107                return ENOMEM;
    141108        }
    142        
    143         assert(hid_dev->subdriver_count >= 0);
    144        
    145         // set the init callback
    146         hid_dev->subdrivers[hid_dev->subdriver_count].init =
    147             usb_generic_hid_init;
    148        
    149         // set the polling callback
    150         hid_dev->subdrivers[hid_dev->subdriver_count].poll =
    151             usb_generic_hid_polling_callback;
    152        
    153         // set the polling ended callback
    154         hid_dev->subdrivers[hid_dev->subdriver_count].poll_end = NULL;
    155        
    156         // set the deinit callback
    157         hid_dev->subdrivers[hid_dev->subdriver_count].deinit = NULL;
    158        
    159         // set subdriver count
    160         ++hid_dev->subdriver_count;
    161        
     109        hid_dev->subdriver_count = 1;
     110
     111        /* Set generic hid subdriver routines */
     112        hid_dev->subdrivers[0].init = usb_generic_hid_init;
     113        hid_dev->subdrivers[0].poll = usb_generic_hid_polling_callback;
     114        hid_dev->subdrivers[0].poll_end = NULL;
     115        hid_dev->subdrivers[0].deinit = usb_generic_hid_deinit;
     116
    162117        return EOK;
    163118}
     
    165120/*----------------------------------------------------------------------------*/
    166121
    167 static bool usb_hid_ids_match(usb_hid_dev_t *hid_dev,
     122static bool usb_hid_ids_match(const usb_hid_dev_t *hid_dev,
    168123    const usb_hid_subdriver_mapping_t *mapping)
    169124{
    170125        assert(hid_dev != NULL);
    171126        assert(hid_dev->usb_dev != NULL);
    172        
    173         return (hid_dev->usb_dev->descriptors.device.vendor_id 
     127
     128        return (hid_dev->usb_dev->descriptors.device.vendor_id
    174129            == mapping->vendor_id
    175130            && hid_dev->usb_dev->descriptors.device.product_id
     
    179134/*----------------------------------------------------------------------------*/
    180135
    181 static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev, 
     136static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev,
    182137    const usb_hid_subdriver_mapping_t *mapping)
    183138{
    184139        assert(hid_dev != NULL);
    185140        assert(mapping != NULL);
    186        
     141
    187142        usb_hid_report_path_t *usage_path = usb_hid_report_path();
    188143        if (usage_path == NULL) {
     
    191146        }
    192147        int i = 0;
    193         while (mapping->usage_path[i].usage != 0 
     148        while (mapping->usage_path[i].usage != 0
    194149            || mapping->usage_path[i].usage_page != 0) {
    195                 if (usb_hid_report_path_append_item(usage_path, 
    196                     mapping->usage_path[i].usage_page, 
     150                if (usb_hid_report_path_append_item(usage_path,
     151                    mapping->usage_path[i].usage_page,
    197152                    mapping->usage_path[i].usage) != EOK) {
    198153                        usb_log_debug("Failed to append to usage path.\n");
     
    202157                ++i;
    203158        }
    204        
    205         assert(hid_dev->report != NULL);
    206        
     159
    207160        usb_log_debug("Compare flags: %d\n", mapping->compare);
    208        
     161
    209162        bool matches = false;
    210163        uint8_t report_id = mapping->report_id;
     
    212165        do {
    213166                usb_log_debug("Trying report id %u\n", report_id);
    214                
     167
    215168                if (report_id != 0) {
    216169                        usb_hid_report_path_set_report_id(usage_path,
     
    219172
    220173                usb_hid_report_field_t *field = usb_hid_report_get_sibling(
    221                     hid_dev->report,
    222                     NULL, usage_path, mapping->compare,
     174                    &hid_dev->report, NULL, usage_path, mapping->compare,
    223175                    USB_HID_REPORT_TYPE_INPUT);
    224                
     176
    225177                usb_log_debug("Field: %p\n", field);
    226178
     
    229181                        break;
    230182                }
    231                
     183
    232184                report_id = usb_hid_get_next_report_id(
    233                     hid_dev->report, report_id,
    234                     USB_HID_REPORT_TYPE_INPUT);
     185                    &hid_dev->report, report_id, USB_HID_REPORT_TYPE_INPUT);
    235186        } while (!matches && report_id != 0);
    236        
     187
    237188        usb_hid_report_path_free(usage_path);
    238        
     189
    239190        return matches;
    240191}
     
    242193/*----------------------------------------------------------------------------*/
    243194
    244 static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev, 
     195static int usb_hid_save_subdrivers(usb_hid_dev_t *hid_dev,
    245196    const usb_hid_subdriver_t **subdrivers, int count)
    246197{
    247198        int i;
    248        
     199
    249200        if (count <= 0) {
    250201                hid_dev->subdriver_count = 0;
     
    252203                return EOK;
    253204        }
    254        
    255         // add one generic HID subdriver per device
    256        
    257         hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc((count + 1) *
    258             sizeof(usb_hid_subdriver_t));
     205
     206        /* +1 for generic hid subdriver */
     207        hid_dev->subdrivers = calloc((count + 1), sizeof(usb_hid_subdriver_t));
    259208        if (hid_dev->subdrivers == NULL) {
    260209                return ENOMEM;
    261210        }
    262        
     211
    263212        for (i = 0; i < count; ++i) {
    264213                hid_dev->subdrivers[i].init = subdrivers[i]->init;
     
    267216                hid_dev->subdrivers[i].poll_end = subdrivers[i]->poll_end;
    268217        }
    269        
     218
     219        /* Add one generic HID subdriver per device */
    270220        hid_dev->subdrivers[count].init = usb_generic_hid_init;
    271221        hid_dev->subdrivers[count].poll = usb_generic_hid_polling_callback;
    272         hid_dev->subdrivers[count].deinit = NULL;
     222        hid_dev->subdrivers[count].deinit = usb_generic_hid_deinit;
    273223        hid_dev->subdrivers[count].poll_end = NULL;
    274        
     224
    275225        hid_dev->subdriver_count = count + 1;
    276        
     226
    277227        return EOK;
    278228}
     
    283233{
    284234        assert(hid_dev != NULL);
    285        
     235
    286236        const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
    287        
     237
    288238        int i = 0, count = 0;
    289239        const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i];
     
    291241        bool ids_matched;
    292242        bool matched;
    293        
     243
    294244        while (count < USB_HID_MAX_SUBDRIVERS &&
    295245            (mapping->usage_path != NULL
     
    306256                        return EINVAL;
    307257                }
    308                
     258
    309259                ids_matched = false;
    310260                matched = false;
    311                
     261
    312262                if (mapping->vendor_id >= 0) {
    313263                        assert(mapping->product_id >= 0);
     
    320270                        }
    321271                }
    322                
     272
    323273                if (mapping->usage_path != NULL) {
    324274                        usb_log_debug("Comparing device against usage path.\n");
     
    331281                        matched = ids_matched;
    332282                }
    333                
     283
    334284                if (matched) {
    335285                        usb_log_debug("Subdriver matched.\n");
    336286                        subdrivers[count++] = &mapping->subdriver;
    337287                }
    338                
     288
    339289                mapping = &usb_hid_subdrivers[++i];
    340290        }
    341        
    342         // we have all subdrivers determined, save them into the hid device
     291
     292        /* We have all subdrivers determined, save them into the hid device */
     293        // TODO Dowe really need this complicated stuff if there is
     294        // max_subdrivers limitation?
    343295        return usb_hid_save_subdrivers(hid_dev, subdrivers, count);
    344296}
     
    346298/*----------------------------------------------------------------------------*/
    347299
    348 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
    349 {
    350         assert(hid_dev != NULL && dev != NULL);
    351        
    352         int rc = EOK;
    353        
     300static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, const usb_device_t *dev)
     301{
     302        assert(hid_dev);
     303        assert(dev);
     304
    354305        if (dev->pipes[USB_HID_KBD_POLL_EP_NO].present) {
    355306                usb_log_debug("Found keyboard endpoint.\n");
     
    367318                usb_log_error("None of supported endpoints found - probably"
    368319                    " not a supported device.\n");
    369                 rc = ENOTSUP;
    370         }
    371        
    372         return rc;
     320                return ENOTSUP;
     321        }
     322
     323        return EOK;
    373324}
    374325
     
    377328static int usb_hid_init_report(usb_hid_dev_t *hid_dev)
    378329{
    379         assert(hid_dev != NULL && hid_dev->report != NULL);
    380        
     330        assert(hid_dev != NULL);
     331
    381332        uint8_t report_id = 0;
    382         size_t size;
    383        
    384333        size_t max_size = 0;
    385        
     334
    386335        do {
    387336                usb_log_debug("Getting size of the report.\n");
    388                 size = usb_hid_report_byte_size(hid_dev->report, report_id,
    389                     USB_HID_REPORT_TYPE_INPUT);
     337                const size_t size =
     338                    usb_hid_report_byte_size(&hid_dev->report, report_id,
     339                        USB_HID_REPORT_TYPE_INPUT);
    390340                usb_log_debug("Report ID: %u, size: %zu\n", report_id, size);
    391341                max_size = (size > max_size) ? size : max_size;
    392342                usb_log_debug("Getting next report ID\n");
    393                 report_id = usb_hid_get_next_report_id(hid_dev->report,
     343                report_id = usb_hid_get_next_report_id(&hid_dev->report,
    394344                    report_id, USB_HID_REPORT_TYPE_INPUT);
    395345        } while (report_id != 0);
    396        
     346
    397347        usb_log_debug("Max size of input report: %zu\n", max_size);
    398        
    399         hid_dev->max_input_report_size = max_size;
     348
    400349        assert(hid_dev->input_report == NULL);
    401        
    402         hid_dev->input_report = malloc(max_size);
     350
     351        hid_dev->input_report = calloc(1, max_size);
    403352        if (hid_dev->input_report == NULL) {
    404353                return ENOMEM;
    405354        }
    406         memset(hid_dev->input_report, 0, max_size);
    407        
     355        hid_dev->max_input_report_size = max_size;
     356
    408357        return EOK;
    409358}
     
    411360/*----------------------------------------------------------------------------*/
    412361
    413 usb_hid_dev_t *usb_hid_new(void)
    414 {
    415         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)calloc(1,
    416             sizeof(usb_hid_dev_t));
    417        
    418         if (hid_dev == NULL) {
    419                 usb_log_fatal("No memory!\n");
    420                 return NULL;
    421         }
    422        
    423         hid_dev->report = (usb_hid_report_t *)(malloc(sizeof(
    424             usb_hid_report_t)));
    425         if (hid_dev->report == NULL) {
    426                 usb_log_fatal("No memory!\n");
    427                 free(hid_dev);
    428                 return NULL;
    429         }
    430        
    431         hid_dev->poll_pipe_index = -1;
    432        
    433         return hid_dev;
    434 }
    435 
    436 /*----------------------------------------------------------------------------*/
    437 
    438362int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev)
    439363{
    440364        int rc, i;
    441        
     365
    442366        usb_log_debug("Initializing HID structure...\n");
    443        
     367
    444368        if (hid_dev == NULL) {
    445369                usb_log_error("Failed to init HID structure: no structure given"
     
    447371                return EINVAL;
    448372        }
    449        
     373
    450374        if (dev == NULL) {
    451375                usb_log_error("Failed to init HID structure: no USB device"
     
    453377                return EINVAL;
    454378        }
    455        
     379
     380        usb_hid_report_init(&hid_dev->report);
     381
    456382        /* The USB device should already be initialized, save it in structure */
    457383        hid_dev->usb_dev = dev;
    458        
     384        hid_dev->poll_pipe_index = -1;
     385
    459386        rc = usb_hid_check_pipes(hid_dev, dev);
    460387        if (rc != EOK) {
    461388                return rc;
    462389        }
    463                
     390
    464391        /* Get the report descriptor and parse it. */
    465         rc = usb_hid_process_report_descriptor(hid_dev->usb_dev, 
    466             hid_dev->report, &hid_dev->report_desc, &hid_dev->report_desc_size);
    467        
     392        rc = usb_hid_process_report_descriptor(hid_dev->usb_dev,
     393            &hid_dev->report, &hid_dev->report_desc, &hid_dev->report_desc_size);
     394
    468395        bool fallback = false;
    469        
     396
    470397        if (rc == EOK) {
    471398                // try to find subdrivers that may want to handle this device
     
    484411                fallback = true;
    485412        }
    486        
     413
    487414        if (fallback) {
    488415                // fall back to boot protocol
     
    503430                        break;
    504431                default:
    505                         assert(hid_dev->poll_pipe_index 
     432                        assert(hid_dev->poll_pipe_index
    506433                            == USB_HID_GENERIC_POLL_EP_NO);
    507                        
     434
    508435                        usb_log_info("Falling back to generic HID driver.\n");
    509436                        rc = usb_hid_set_generic_hid_subdriver(hid_dev);
    510437                }
    511438        }
    512        
     439
    513440        if (rc != EOK) {
    514441                usb_log_error("No subdriver for handling this device could be"
    515442                    " initialized: %s.\n", str_error(rc));
    516                 usb_log_debug("Subdriver count: %d\n", 
     443                usb_log_debug("Subdriver count: %d\n",
    517444                    hid_dev->subdriver_count);
    518                
    519445        } else {
    520446                bool ok = false;
    521                
    522                 usb_log_debug("Subdriver count: %d\n", 
     447
     448                usb_log_debug("Subdriver count: %d\n",
    523449                    hid_dev->subdriver_count);
    524                
     450
    525451                for (i = 0; i < hid_dev->subdriver_count; ++i) {
    526452                        if (hid_dev->subdrivers[i].init != NULL) {
     
    539465                        }
    540466                }
    541                
     467
    542468                rc = (ok) ? EOK : -1;   // what error to report
    543469        }
    544        
    545        
     470
     471
    546472        if (rc == EOK) {
    547473                // save max input report size and allocate space for the report
     
    552478                }
    553479        }
    554        
    555        
     480
    556481        return rc;
    557482}
     
    559484/*----------------------------------------------------------------------------*/
    560485
    561 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer, 
     486bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
    562487    size_t buffer_size, void *arg)
    563488{
    564         int i;
    565        
    566489        if (dev == NULL || arg == NULL || buffer == NULL) {
    567490                usb_log_error("Missing arguments to polling callback.\n");
    568491                return false;
    569492        }
    570        
    571         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
    572        
     493        usb_hid_dev_t *hid_dev = arg;
     494
    573495        assert(hid_dev->input_report != NULL);
     496
    574497        usb_log_debug("New data [%zu/%zu]: %s\n", buffer_size,
    575498            hid_dev->max_input_report_size,
     
    582505                usb_hid_new_report(hid_dev);
    583506        }
    584        
    585         // parse the input report
    586        
    587         int rc = usb_hid_parse_report(hid_dev->report, buffer, buffer_size,
    588             &hid_dev->report_id);
    589        
     507
     508        /* Parse the input report */
     509        const int rc = usb_hid_parse_report(
     510            &hid_dev->report, buffer, buffer_size, &hid_dev->report_id);
    590511        if (rc != EOK) {
    591512                usb_log_warning("Error in usb_hid_parse_report():"
    592513                    "%s\n", str_error(rc));
    593         }       
    594        
     514        }
     515
    595516        bool cont = false;
    596        
    597         // continue if at least one of the subdrivers want to continue
    598         for (i = 0; i < hid_dev->subdriver_count; ++i) {
    599                 if (hid_dev->subdrivers[i].poll != NULL
    600                     && hid_dev->subdrivers[i].poll(hid_dev,
    601                         hid_dev->subdrivers[i].data)) {
    602                         cont = true;
    603                 }
    604         }
    605        
     517        /* Continue if at least one of the subdrivers want to continue */
     518        for (int i = 0; i < hid_dev->subdriver_count; ++i) {
     519                if (hid_dev->subdrivers[i].poll != NULL) {
     520                        cont = cont || hid_dev->subdrivers[i].poll(
     521                            hid_dev, hid_dev->subdrivers[i].data);
     522                }
     523        }
     524
    606525        return cont;
    607526}
     
    609528/*----------------------------------------------------------------------------*/
    610529
    611 void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason,
    612      void *arg)
    613 {
    614         int i;
    615        
    616         if (dev == NULL || arg == NULL) {
    617                 return;
    618         }
    619        
    620         usb_hid_dev_t *hid_dev = (usb_hid_dev_t *)arg;
    621        
    622         for (i = 0; i < hid_dev->subdriver_count; ++i) {
     530void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, void *arg)
     531{
     532        assert(dev);
     533        assert(arg);
     534
     535        usb_hid_dev_t *hid_dev = arg;
     536
     537        for (int i = 0; i < hid_dev->subdriver_count; ++i) {
    623538                if (hid_dev->subdrivers[i].poll_end != NULL) {
    624                         hid_dev->subdrivers[i].poll_end(hid_dev,
    625                             hid_dev->subdrivers[i].data, reason);
    626                 }
    627         }
    628        
    629         usb_hid_destroy(hid_dev);
     539                        hid_dev->subdrivers[i].poll_end(
     540                            hid_dev, hid_dev->subdrivers[i].data, reason);
     541                }
     542        }
     543
     544        hid_dev->running = false;
    630545}
    631546
     
    639554/*----------------------------------------------------------------------------*/
    640555
    641 int usb_hid_report_number(usb_hid_dev_t *hid_dev)
     556int usb_hid_report_number(const usb_hid_dev_t *hid_dev)
    642557{
    643558        return hid_dev->report_nr;
     
    646561/*----------------------------------------------------------------------------*/
    647562
    648 void usb_hid_destroy(usb_hid_dev_t *hid_dev)
    649 {
    650         int i;
    651        
    652         if (hid_dev == NULL) {
    653                 return;
    654         }
    655        
     563void usb_hid_deinit(usb_hid_dev_t *hid_dev)
     564{
     565        assert(hid_dev);
     566        assert(hid_dev->subdrivers != NULL || hid_dev->subdriver_count == 0);
     567
     568
    656569        usb_log_debug("Subdrivers: %p, subdriver count: %d\n",
    657570            hid_dev->subdrivers, hid_dev->subdriver_count);
    658        
    659         assert(hid_dev->subdrivers != NULL
    660             || hid_dev->subdriver_count == 0);
    661        
    662         for (i = 0; i < hid_dev->subdriver_count; ++i) {
     571
     572        for (int i = 0; i < hid_dev->subdriver_count; ++i) {
    663573                if (hid_dev->subdrivers[i].deinit != NULL) {
    664574                        hid_dev->subdrivers[i].deinit(hid_dev,
     
    666576                }
    667577        }
    668        
    669         // free the subdrivers info
    670         if (hid_dev->subdrivers != NULL) {
    671                 free(hid_dev->subdrivers);
    672         }
    673 
    674         // destroy the parser
    675         if (hid_dev->report != NULL) {
    676                 usb_hid_free_report(hid_dev->report);
    677         }
    678 
    679         if (hid_dev->report_desc != NULL) {
    680                 free(hid_dev->report_desc);
    681         }
     578
     579        /* Free allocated structures */
     580        free(hid_dev->subdrivers);
     581        free(hid_dev->report_desc);
     582
     583        /* Destroy the parser */
     584        usb_hid_report_deinit(&hid_dev->report);
     585
    682586}
    683587
  • uspace/drv/bus/usb/usbhid/usbhid.h

    r4c3ad56 r20a3465  
    102102        /** Structure holding generic USB device information. */
    103103        usb_device_t *usb_dev;
    104        
     104
    105105        /** Index of the polling pipe in usb_hid_endpoints array. */
    106106        int poll_pipe_index;
    107        
     107
    108108        /** Subdrivers. */
    109109        usb_hid_subdriver_t *subdrivers;
    110        
     110
    111111        /** Number of subdrivers. */
    112112        int subdriver_count;
    113        
     113
    114114        /** Report descriptor. */
    115115        uint8_t *report_desc;
     
    117117        /** Report descriptor size. */
    118118        size_t report_desc_size;
    119        
     119
    120120        /** HID Report parser. */
    121         usb_hid_report_t *report;
    122        
     121        usb_hid_report_t report;
     122
    123123        uint8_t report_id;
    124        
     124
    125125        uint8_t *input_report;
    126        
     126
    127127        size_t input_report_size;
    128128        size_t max_input_report_size;
    129        
     129
    130130        int report_nr;
     131        volatile bool running;
    131132};
    132133
     
    140141};
    141142
    142 usb_endpoint_description_t *usb_hid_endpoints[USB_HID_POLL_EP_COUNT + 1];
     143extern const usb_endpoint_description_t *usb_hid_endpoints[];
    143144
    144145/*----------------------------------------------------------------------------*/
    145146
    146 usb_hid_dev_t *usb_hid_new(void);
    147 
    148147int usb_hid_init(usb_hid_dev_t *hid_dev, usb_device_t *dev);
    149148
    150 bool usb_hid_polling_callback(usb_device_t *dev, uint8_t *buffer,
    151     size_t buffer_size, void *arg);
     149void usb_hid_deinit(usb_hid_dev_t *hid_dev);
    152150
    153 void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason,
    154      void *arg);
     151bool usb_hid_polling_callback(usb_device_t *dev,
     152    uint8_t *buffer, size_t buffer_size, void *arg);
     153
     154void usb_hid_polling_ended_callback(usb_device_t *dev, bool reason, void *arg);
    155155
    156156void usb_hid_new_report(usb_hid_dev_t *hid_dev);
    157157
    158 int usb_hid_report_number(usb_hid_dev_t *hid_dev);
    159 
    160 void usb_hid_destroy(usb_hid_dev_t *hid_dev);
     158int usb_hid_report_number(const usb_hid_dev_t *hid_dev);
    161159
    162160#endif /* USB_HID_USBHID_H_ */
  • uspace/drv/bus/usb/usbhub/main.c

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

    r4c3ad56 r20a3465  
    288288        port->attached_device.fun = NULL;
    289289
    290         ret = usb_hc_unregister_device(&hub->connection,
    291             port->attached_device.address);
    292         if (ret != EOK) {
    293                 usb_log_warning("Failed to unregister address of the removed "
    294                     "device: %s.\n", str_error(ret));
    295         }
     290        ret = usb_hc_connection_open(&hub->connection);
     291        if (ret == EOK) {
     292                ret = usb_hc_unregister_device(&hub->connection,
     293                    port->attached_device.address);
     294                if (ret != EOK) {
     295                        usb_log_warning("Failed to unregister address of the "
     296                            "removed device: %s.\n", str_error(ret));
     297                }
     298                ret = usb_hc_connection_close(&hub->connection);
     299                if (ret != EOK) {
     300                        usb_log_warning("Failed to close hc connection %s.\n",
     301                            str_error(ret));
     302                }
     303
     304        } else {
     305                usb_log_warning("Failed to open hc connection %s.\n",
     306                    str_error(ret));
     307        }
     308
    296309        port->attached_device.address = -1;
    297310        fibril_mutex_unlock(&port->mutex);
  • uspace/drv/bus/usb/usbhub/port.h

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

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

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

    r4c3ad56 r20a3465  
    5555#define GET_BULK_OUT(dev) ((dev)->pipes[BULK_OUT_EP].pipe)
    5656
    57 static usb_endpoint_description_t bulk_in_ep = {
     57static const usb_endpoint_description_t bulk_in_ep = {
    5858        .transfer_type = USB_TRANSFER_BULK,
    5959        .direction = USB_DIRECTION_IN,
     
    6363        .flags = 0
    6464};
    65 static usb_endpoint_description_t bulk_out_ep = {
     65static const usb_endpoint_description_t bulk_out_ep = {
    6666        .transfer_type = USB_TRANSFER_BULK,
    6767        .direction = USB_DIRECTION_OUT,
     
    7272};
    7373
    74 usb_endpoint_description_t *mast_endpoints[] = {
     74static const usb_endpoint_description_t *mast_endpoints[] = {
    7575        &bulk_in_ep,
    7676        &bulk_out_ep,
     
    8282    void *arg);
    8383
     84/** Callback when a device is removed from the system.
     85 *
     86 * @param dev Representation of USB device.
     87 * @return Error code.
     88 */
     89static int usbmast_device_gone(usb_device_t *dev)
     90{
     91        usbmast_dev_t *mdev = dev->driver_data;
     92        assert(mdev);
     93
     94        for (size_t i = 0; i < mdev->lun_count; ++i) {
     95                const int rc = ddf_fun_unbind(mdev->luns[i]);
     96                if (rc != EOK) {
     97                        usb_log_error("Failed to unbind LUN function %zu: "
     98                            "%s\n", i, str_error(rc));
     99                        return rc;
     100                }
     101                ddf_fun_destroy(mdev->luns[i]);
     102                mdev->luns[i] = NULL;
     103        }
     104        free(mdev->luns);
     105        return EOK;
     106}
     107
     108/** Callback when a device is about to be removed.
     109 *
     110 * @param dev Representation of USB device.
     111 * @return Error code.
     112 */
     113static int usbmast_device_remove(usb_device_t *dev)
     114{
     115        //TODO: flush buffers, or whatever.
     116        return ENOTSUP;
     117}
     118
    84119/** Callback when new device is attached and recognized as a mass storage.
    85120 *
    86  * @param dev Representation of a the USB device.
     121 * @param dev Representation of USB device.
    87122 * @return Error code.
    88123 */
     
    94129
    95130        /* Allocate softstate */
    96         dev->driver_data = mdev = malloc(sizeof(usbmast_dev_t));
     131        mdev = usb_device_data_alloc(dev, sizeof(usbmast_dev_t));
    97132        if (mdev == NULL) {
    98133                usb_log_error("Failed allocating softstate.\n");
     
    112147
    113148        usb_log_debug("Get LUN count...\n");
    114         mdev->luns = usb_masstor_get_lun_count(mdev);
    115 
    116         for (i = 0; i < mdev->luns; i++) {
     149        mdev->lun_count = usb_masstor_get_lun_count(mdev);
     150        mdev->luns = calloc(mdev->lun_count, sizeof(ddf_fun_t*));
     151        if (mdev->luns == NULL) {
     152                rc = ENOMEM;
     153                usb_log_error("Failed allocating luns table.\n");
     154                goto error;
     155        }
     156
     157        for (i = 0; i < mdev->lun_count; i++) {
    117158                rc = usbmast_fun_create(mdev, i);
    118159                if (rc != EOK)
     
    122163        return EOK;
    123164error:
    124         /* XXX Destroy functions */
     165        /* Destroy functions */
     166        for (size_t i = 0; i < mdev->lun_count; ++i) {
     167                if (mdev->luns[i] == NULL)
     168                        continue;
     169                const int rc = ddf_fun_unbind(mdev->luns[i]);
     170                if (rc != EOK) {
     171                        usb_log_warning("Failed to unbind LUN function %zu: "
     172                            "%s.\n", i, str_error(rc));
     173                }
     174                ddf_fun_destroy(mdev->luns[i]);
     175        }
     176        free(mdev->luns);
    125177        return rc;
    126178}
     
    162214        }
    163215
     216        mfun->ddf_fun = fun;
    164217        mfun->mdev = mdev;
    165218        mfun->lun = lun;
     
    212265
    213266        free(fun_name);
     267        mdev->luns[lun] = fun;
    214268
    215269        return EOK;
     
    293347
    294348/** USB mass storage driver ops. */
    295 static usb_driver_ops_t usbmast_driver_ops = {
     349static const usb_driver_ops_t usbmast_driver_ops = {
    296350        .device_add = usbmast_device_add,
     351        .device_rem = usbmast_device_remove,
     352        .device_gone = usbmast_device_gone,
    297353};
    298354
    299355/** USB mass storage driver. */
    300 static usb_driver_t usbmast_driver = {
     356static const usb_driver_t usbmast_driver = {
    301357        .name = NAME,
    302358        .ops = &usbmast_driver_ops,
  • uspace/drv/bus/usb/usbmast/usbmast.h

    r4c3ad56 r20a3465  
    4141
    4242/** Mass storage device. */
    43 typedef struct {
     43typedef struct usbmast_dev {
    4444        /** DDF device */
    4545        ddf_dev_t *ddf_dev;
     
    4747        usb_device_t *usb_dev;
    4848        /** Number of LUNs */
    49         unsigned luns;
     49        unsigned lun_count;
     50        /** LUN functions */
     51        ddf_fun_t **luns;
    5052} usbmast_dev_t;
     53
    5154
    5255/** Mass storage function.
  • uspace/drv/bus/usb/usbmid/dump.c

    r4c3ad56 r20a3465  
    4747 * @param depth Nesting depth.
    4848 */
    49 static void dump_tree_descriptor(uint8_t *data, size_t depth)
     49static void dump_tree_descriptor(const uint8_t *data, size_t depth)
    5050{
    5151        if (data == NULL) {
    5252                return;
    5353        }
    54         int type = (int) *(data + 1);
     54        const int type = data[1];
    5555        if (type == USB_DESCTYPE_INTERFACE) {
    5656                usb_standard_interface_descriptor_t *descriptor
     
    7171 * @param depth Nesting depth.
    7272 */
    73 static void dump_tree_internal(usb_dp_parser_t *parser, usb_dp_parser_data_t *data,
    74     uint8_t *root, size_t depth)
     73static void dump_tree_internal(
     74    usb_dp_parser_t *parser, usb_dp_parser_data_t *data,
     75    const uint8_t *root, size_t depth)
    7576{
    7677        if (root == NULL) {
     
    7879        }
    7980        dump_tree_descriptor(root, depth);
    80         uint8_t *child = usb_dp_get_nested_descriptor(parser, data, root);
     81        const uint8_t *child = usb_dp_get_nested_descriptor(parser, data, root);
    8182        do {
    8283                dump_tree_internal(parser, data, child, depth + 1);
     
    9293static void dump_tree(usb_dp_parser_t *parser, usb_dp_parser_data_t *data)
    9394{
    94         uint8_t *ptr = data->data;
     95        const uint8_t *ptr = data->data;
    9596        dump_tree_internal(parser, data, ptr, 0);
    9697}
  • uspace/drv/bus/usb/usbmid/explore.c

    r4c3ad56 r20a3465  
    7373 * @param list List where to add the interfaces.
    7474 */
    75 static void create_interfaces(uint8_t *config_descriptor,
     75static void create_interfaces(const uint8_t *config_descriptor,
    7676    size_t config_descriptor_size, list_t *list)
    7777{
    78         usb_dp_parser_data_t data = {
     78        const usb_dp_parser_data_t data = {
    7979                .data = config_descriptor,
    8080                .size = config_descriptor_size,
     
    8686        };
    8787
    88         uint8_t *interface_ptr = usb_dp_get_nested_descriptor(&parser, &data,
    89             data.data);
     88        const uint8_t *interface_ptr =
     89            usb_dp_get_nested_descriptor(&parser, &data, data.data);
    9090        if (interface_ptr == NULL) {
    9191                return;
     
    149149
    150150        /* Short cuts to save on typing ;-). */
    151         uint8_t *config_descriptor_raw = dev->descriptors.configuration;
     151        const void *config_descriptor_raw = dev->descriptors.configuration;
    152152        size_t config_descriptor_size = dev->descriptors.configuration_size;
    153         usb_standard_configuration_descriptor_t *config_descriptor =
    154             (usb_standard_configuration_descriptor_t *) config_descriptor_raw;
     153        const usb_standard_configuration_descriptor_t *config_descriptor =
     154            config_descriptor_raw;
    155155
    156156        /* Select the first configuration */
     
    163163        }
    164164
     165        usb_mid_t *usb_mid = usb_device_data_alloc(dev, sizeof(usb_mid_t));
     166        if (!usb_mid) {
     167                usb_log_error("Failed to create USB MID structure.\n");
     168                return false;
     169        }
     170
    165171        /* Create control function */
    166         ddf_fun_t *ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "ctl");
    167         if (ctl_fun == NULL) {
     172        usb_mid->ctl_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "ctl");
     173        if (usb_mid->ctl_fun == NULL) {
    168174                usb_log_error("Failed to create control function.\n");
    169175                return false;
    170176        }
    171177
    172         ctl_fun->ops = &mid_device_ops;
    173 
    174         rc = ddf_fun_bind(ctl_fun);
     178        usb_mid->ctl_fun->ops = &mid_device_ops;
     179
     180        rc = ddf_fun_bind(usb_mid->ctl_fun);
    175181        if (rc != EOK) {
    176182                usb_log_error("Failed to bind control function: %s.\n",
    177183                    str_error(rc));
    178                 return false;
    179         }
     184                ddf_fun_destroy(usb_mid->ctl_fun);
     185                return false;
     186        }
     187
    180188
    181189        /* Create interface children. */
    182         list_t interface_list;
    183         list_initialize(&interface_list);
     190        list_initialize(&usb_mid->interface_list);
    184191        create_interfaces(config_descriptor_raw, config_descriptor_size,
    185             &interface_list);
    186 
    187         list_foreach(interface_list, link) {
     192            &usb_mid->interface_list);
     193
     194        list_foreach(usb_mid->interface_list, link) {
    188195                usbmid_interface_t *iface = list_get_instance(link,
    189196                    usbmid_interface_t, link);
  • uspace/drv/bus/usb/usbmid/main.c

    r4c3ad56 r20a3465  
    6565        return EOK;
    6666}
     67/*----------------------------------------------------------------------------*/
     68/** Callback when a MID device is about to be removed from the host.
     69 *
     70 * @param gen_dev Generic DDF device representing the removed device.
     71 * @return Error code.
     72 */
     73static int usbmid_device_remove(usb_device_t *dev)
     74{
     75        assert(dev);
     76        int ret = ENOTSUP;
     77        usb_mid_t *usb_mid = dev->driver_data;
     78        assert(usb_mid);
     79
     80        /* Signal all interface functions */
     81        list_foreach(usb_mid->interface_list, item) {
     82                usbmid_interface_t *iface = usbmid_interface_from_link(item);
     83
     84                usb_log_info("Signaling remove to child for interface "
     85                    "%d (%s).\n", iface->interface_no,
     86                    usb_str_class(iface->interface->interface_class));
     87                // TODO cascade the call.
     88        }
     89        return ret;
     90}
     91/*----------------------------------------------------------------------------*/
     92/** Callback when a MID device was removed from the host.
     93 *
     94 * @param gen_dev Generic DDF device representing the removed device.
     95 * @return Error code.
     96 */
     97static int usbmid_device_gone(usb_device_t *dev)
     98{
     99        assert(dev);
     100        usb_log_info("USB MID gone: `%s'.\n", dev->ddf_dev->name);
     101
     102        /* Remove ctl function */
     103        usb_mid_t *usb_mid = dev->driver_data;
     104        int ret = ddf_fun_unbind(usb_mid->ctl_fun);
     105        if (ret != EOK) {
     106                usb_log_error("Failed to unbind USB MID ctl function: %s.\n",
     107                    str_error(ret));
     108                return ret;
     109        }
     110        ddf_fun_destroy(usb_mid->ctl_fun);
     111
     112        /* Now remove all other functions */
     113        while (!list_empty(&usb_mid->interface_list)) {
     114                link_t *item = list_first(&usb_mid->interface_list);
     115                list_remove(item);
     116
     117                usbmid_interface_t *iface = usbmid_interface_from_link(item);
     118
     119                usb_log_info("Removing child for interface %d (%s).\n",
     120                    iface->interface_no,
     121                    usb_str_class(iface->interface->interface_class));
     122
     123                const int pret = usbmid_interface_destroy(iface);
     124                if (pret != EOK) {
     125                        usb_log_error("Failed to remove child for interface "
     126                            "%d (%s): %s\n",
     127                            iface->interface_no,
     128                            usb_str_class(iface->interface->interface_class),
     129                            str_error(pret));
     130                        ret = pret;
     131                }
     132        }
     133        return ret;
     134}
    67135
    68136/** USB MID driver ops. */
    69 static usb_driver_ops_t mid_driver_ops = {
     137static const usb_driver_ops_t mid_driver_ops = {
    70138        .device_add = usbmid_device_add,
     139        .device_rem = usbmid_device_remove,
     140        .device_gone = usbmid_device_gone,
    71141};
    72142
    73143/** USB MID driver. */
    74 static usb_driver_t mid_driver = {
     144static const usb_driver_t mid_driver = {
    75145        .name = NAME,
    76146        .ops = &mid_driver_ops,
  • uspace/drv/bus/usb/usbmid/usbmid.c

    r4c3ad56 r20a3465  
    4545
    4646/** Callback for DDF USB interface. */
    47 static int usb_iface_get_address_impl(ddf_fun_t *fun, devman_handle_t handle,
    48     usb_address_t *address)
    49 {
    50         return usb_iface_get_address_hub_impl(fun, handle, address);
    51 }
    52 
    53 /** Callback for DDF USB interface. */
    5447static int usb_iface_get_interface_impl(ddf_fun_t *fun, devman_handle_t handle,
    5548    int *iface_no)
     
    7063static usb_iface_t child_usb_iface = {
    7164        .get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
    72         .get_address = usb_iface_get_address_impl,
     65        .get_address = usb_iface_get_address_hub_impl,
    7366        .get_interface = usb_iface_get_interface_impl
    7467};
     
    7972};
    8073
     74int usbmid_interface_destroy(usbmid_interface_t *mid_iface)
     75{
     76        assert(mid_iface);
     77        assert_link_not_used(&mid_iface->link);
     78        const int ret = ddf_fun_unbind(mid_iface->fun);
     79        if (ret != EOK) {
     80                return ret;
     81        }
     82        /* NOTE: usbmid->interface points somewhere, but we did not
     83         * allocate that space, so don't touch */
     84        ddf_fun_destroy(mid_iface->fun);
     85        /* NOTE: mid_iface is invalid at this point, it was assigned to
     86         * mid_iface->fun->driver_data and freed in ddf_fun_destroy */
     87        return EOK;
     88}
    8189
    8290/** Spawn new child device from one interface.
     
    106114            (int) interface_descriptor->interface_number);
    107115        if (rc < 0) {
    108                 goto error_leave;
     116                return ENOMEM;
    109117        }
    110118
    111119        /* Create the device. */
    112120        child = ddf_fun_create(parent->ddf_dev, fun_inner, child_name);
     121        free(child_name);
    113122        if (child == NULL) {
    114                 rc = ENOMEM;
    115                 goto error_leave;
     123                return ENOMEM;
    116124        }
    117125
     
    122130
    123131        rc = usb_device_create_match_ids_from_interface(device_descriptor,
    124             interface_descriptor,
    125             &child->match_ids);
     132            interface_descriptor, &child->match_ids);
    126133        if (rc != EOK) {
    127                 goto error_leave;
     134                ddf_fun_destroy(child);
     135                return rc;
    128136        }
    129137
    130138        rc = ddf_fun_bind(child);
    131139        if (rc != EOK) {
    132                 goto error_leave;
     140                /* This takes care of match_id deallocation as well. */
     141                ddf_fun_destroy(child);
     142                return rc;
    133143        }
    134144
    135145        return EOK;
    136 
    137 error_leave:
    138         if (child != NULL) {
    139                 child->name = NULL;
    140                 /* This takes care of match_id deallocation as well. */
    141                 ddf_fun_destroy(child);
    142         }
    143         if (child_name != NULL) {
    144                 free(child_name);
    145         }
    146 
    147         return rc;
    148146}
    149147
  • uspace/drv/bus/usb/usbmid/usbmid.h

    r4c3ad56 r20a3465  
    5858} usbmid_interface_t;
    5959
     60/** Container to hold all the function pointers */
     61typedef struct usb_mid {
     62        ddf_fun_t *ctl_fun;
     63        list_t interface_list;
     64} usb_mid_t;
     65
    6066bool usbmid_explore_device(usb_device_t *);
    6167int usbmid_spawn_interface_child(usb_device_t *, usbmid_interface_t *,
     
    6369    const usb_standard_interface_descriptor_t *);
    6470void usbmid_dump_descriptors(uint8_t *, size_t);
     71int usbmid_interface_destroy(usbmid_interface_t *mid_iface);
     72
     73static inline usbmid_interface_t * usbmid_interface_from_link(link_t *item)
     74{
     75        return list_get_instance(item, usbmid_interface_t, link);
     76}
    6577
    6678#endif
  • uspace/drv/bus/usb/vhc/connhost.c

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