Changeset 747ef72 in mainline for uspace/lib


Ignore:
Timestamp:
2011-11-10T11:29:10Z (14 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
54464f6a, c2245a3, c6f189f7
Parents:
2e1b9dc (diff), 2d1ba51 (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 USB changes.

Interface changes:

  • GET_ADDRESS has been renamed to GET_MY_ADDRESS and the handle parameter was dropped. Tis call no longer cascades up to the root hub, but it is answered in the first place the information is available (nearest hub)
  • Reintroduced address reservation for USB_DEFAULT_ADDRESS. The interface now enables device drivers to request specific address on initialization and either insists on that address or accept any other if the address is not available. Note that it is not possible to get the default address if the driver does not insist.
  • Any endpoint registered is removed when address is released and a warning is produced if there were any such endpoints.
  • It is no longer necessary or possible to pass device speed information when registering endpoints.

Driver fixes: memory leaks and crashes (not only) in error paths.
Fixes or removes flaky device_remove implementation in device drivers.

Location:
uspace/lib
Files:
38 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/drv/generic/remote_usb.c

    r2e1b9dc r747ef72  
    4040
    4141
    42 static void remote_usb_get_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     42static void remote_usb_get_my_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    4343static void remote_usb_get_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
    4444static void remote_usb_get_hc_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
     
    4747/** Remote USB interface operations. */
    4848static remote_iface_func_ptr_t remote_usb_iface_ops [] = {
    49         remote_usb_get_address,
    50         remote_usb_get_interface,
    51         remote_usb_get_hc_handle
     49        [IPC_M_USB_GET_MY_ADDRESS] = remote_usb_get_my_address,
     50        [IPC_M_USB_GET_INTERFACE] = remote_usb_get_interface,
     51        [IPC_M_USB_GET_HOST_CONTROLLER_HANDLE] = remote_usb_get_hc_handle,
    5252};
    5353
     
    6161
    6262
    63 void remote_usb_get_address(ddf_fun_t *fun, void *iface,
     63void remote_usb_get_my_address(ddf_fun_t *fun, void *iface,
    6464    ipc_callid_t callid, ipc_call_t *call)
    6565{
    6666        usb_iface_t *usb_iface = (usb_iface_t *) iface;
    6767
    68         if (usb_iface->get_address == NULL) {
     68        if (usb_iface->get_my_address == NULL) {
    6969                async_answer_0(callid, ENOTSUP);
    7070                return;
    7171        }
    7272
    73         devman_handle_t handle = DEV_IPC_GET_ARG1(*call);
    74 
    7573        usb_address_t address;
    76         int rc = usb_iface->get_address(fun, handle, &address);
     74        int rc = usb_iface->get_my_address(fun, &address);
    7775        if (rc != EOK) {
    7876                async_answer_0(callid, rc);
  • uspace/lib/drv/generic/remote_usbhc.c

    r2e1b9dc r747ef72  
    5555static remote_iface_func_ptr_t remote_usbhc_iface_ops[] = {
    5656        [IPC_M_USBHC_REQUEST_ADDRESS] = remote_usbhc_request_address,
     57        [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address,
    5758        [IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address,
    5859        [IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_find_by_address,
    59         [IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address,
    6060
    6161        [IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint,
     
    118118        }
    119119
    120         usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
    121 
    122         usb_address_t address;
    123         int rc = usb_iface->request_address(fun, speed, &address);
     120        usb_address_t address = DEV_IPC_GET_ARG1(*call);
     121        const bool strict = DEV_IPC_GET_ARG2(*call);
     122        const usb_speed_t speed = DEV_IPC_GET_ARG3(*call);
     123
     124        const int rc = usb_iface->request_address(fun, &address, strict, speed);
    124125        if (rc != EOK) {
    125126                async_answer_0(callid, rc);
     
    233234
    234235#define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \
    235         type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16)
     236        type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) >> 16)
    236237#define _INIT_FROM_LOW_DATA2(type, var, arg_no) \
    237         type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 16)
    238 #define _INIT_FROM_HIGH_DATA3(type, var, arg_no) \
    239         type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / (1 << 16)
    240 #define _INIT_FROM_MIDDLE_DATA3(type, var, arg_no) \
    241         type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) / (1 << 8)) % (1 << 8)
    242 #define _INIT_FROM_LOW_DATA3(type, var, arg_no) \
    243         type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % (1 << 8)
     238        type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) & 0xffff)
    244239
    245240        const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
    246241
    247         _INIT_FROM_HIGH_DATA3(usb_speed_t, speed, 2);
    248         _INIT_FROM_MIDDLE_DATA3(usb_transfer_type_t, transfer_type, 2);
    249         _INIT_FROM_LOW_DATA3(usb_direction_t, direction, 2);
     242        _INIT_FROM_HIGH_DATA2(usb_transfer_type_t, transfer_type, 2);
     243        _INIT_FROM_LOW_DATA2(usb_direction_t, direction, 2);
    250244
    251245        _INIT_FROM_HIGH_DATA2(size_t, max_packet_size, 3);
     
    254248#undef _INIT_FROM_HIGH_DATA2
    255249#undef _INIT_FROM_LOW_DATA2
    256 #undef _INIT_FROM_HIGH_DATA3
    257 #undef _INIT_FROM_MIDDLE_DATA3
    258 #undef _INIT_FROM_LOW_DATA3
    259 
    260         int rc = usb_iface->register_endpoint(fun, target.address, speed,
     250
     251        int rc = usb_iface->register_endpoint(fun, target.address,
    261252            target.endpoint, transfer_type, direction, max_packet_size, interval);
    262253
  • uspace/lib/drv/include/usb_iface.h

    r2e1b9dc r747ef72  
    6565         * handle must be resolved by its parent.
    6666         */
    67         IPC_M_USB_GET_ADDRESS,
     67        IPC_M_USB_GET_MY_ADDRESS,
    6868
    6969        /** Tell interface number given device can use.
     
    9090/** USB device communication interface. */
    9191typedef struct {
    92         int (*get_address)(ddf_fun_t *, devman_handle_t, usb_address_t *);
     92        int (*get_my_address)(ddf_fun_t *, usb_address_t *);
    9393        int (*get_interface)(ddf_fun_t *, devman_handle_t, int *);
    9494        int (*get_hc_handle)(ddf_fun_t *, devman_handle_t *);
  • uspace/lib/drv/include/usbhc_iface.h

    r2e1b9dc r747ef72  
    170170/** USB host controller communication interface. */
    171171typedef struct {
    172         int (*request_address)(ddf_fun_t *, usb_speed_t, usb_address_t *);
     172        int (*request_address)(ddf_fun_t *, usb_address_t *, bool, usb_speed_t);
    173173        int (*bind_address)(ddf_fun_t *, usb_address_t, devman_handle_t);
    174174        int (*find_by_address)(ddf_fun_t *, usb_address_t, devman_handle_t *);
     
    176176
    177177        int (*register_endpoint)(ddf_fun_t *,
    178             usb_address_t, usb_speed_t, usb_endpoint_t,
     178            usb_address_t, usb_endpoint_t,
    179179            usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
    180180        int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
  • uspace/lib/usb/Makefile

    r2e1b9dc r747ef72  
    3131EXTRA_CFLAGS += \
    3232        -I$(LIBDRV_PREFIX)/include \
     33        -I$(LIBUSBDEV_PREFIX)/include \
    3334        -Iinclude
    3435
  • uspace/lib/usb/include/usb/ddfiface.h

    r2e1b9dc r747ef72  
    3939#include <usb_iface.h>
    4040
    41 int usb_iface_get_hc_handle_hub_impl(ddf_fun_t *, devman_handle_t *);
    42 int usb_iface_get_address_hub_impl(ddf_fun_t *, devman_handle_t,
    43     usb_address_t *);
     41int usb_iface_get_hc_handle_device_impl(ddf_fun_t *, devman_handle_t *);
     42int usb_iface_get_my_address_forward_impl(ddf_fun_t *, usb_address_t *);
    4443extern usb_iface_t usb_iface_hub_impl;
    4544
    46 int usb_iface_get_hc_handle_hub_child_impl(ddf_fun_t *, devman_handle_t *);
    47 int usb_iface_get_address_hub_child_impl(ddf_fun_t *, devman_handle_t,
    48     usb_address_t *);
     45int usb_iface_get_my_address_from_device_data(ddf_fun_t *, usb_address_t *);
    4946extern usb_iface_t usb_iface_hub_child_impl;
    5047
    5148int usb_iface_get_hc_handle_hc_impl(ddf_fun_t *, devman_handle_t *);
    52 
    5349
    5450#endif
  • uspace/lib/usb/include/usb/hc.h

    r2e1b9dc r747ef72  
    6262    devman_handle_t *);
    6363
    64 usb_address_t usb_hc_get_address_by_handle(devman_handle_t);
     64usb_address_t usb_get_address_by_handle(devman_handle_t);
    6565
    6666int usb_hc_find(devman_handle_t, devman_handle_t *);
  • uspace/lib/usb/src/class.c

    r2e1b9dc r747ef72  
    8181                        return "application";
    8282                case USB_CLASS_VENDOR_SPECIFIC:
    83                         return "vendor";
     83                        return "vendor-specific";
    8484                default:
    8585                        return "unknown";
  • uspace/lib/usb/src/ddfiface.c

    r2e1b9dc r747ef72  
    3939#include <usb/hc.h>
    4040#include <usb/debug.h>
     41#include <usb/dev/hub.h>
    4142#include <errno.h>
    4243#include <assert.h>
    4344
    4445/** DDF interface for USB device, implementation for typical hub. */
    45 usb_iface_t  usb_iface_hub_impl = {
    46         .get_hc_handle = usb_iface_get_hc_handle_hub_impl,
    47         .get_address = usb_iface_get_address_hub_impl
     46usb_iface_t usb_iface_hub_impl = {
     47        .get_hc_handle = usb_iface_get_hc_handle_device_impl,
     48        .get_my_address = usb_iface_get_my_address_forward_impl,
    4849};
    4950
    5051/** DDF interface for USB device, implementation for child of a typical hub. */
    51 usb_iface_t  usb_iface_hub_child_impl = {
    52         .get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
    53         .get_address = usb_iface_get_address_hub_child_impl
     52usb_iface_t usb_iface_hub_child_impl = {
     53        .get_hc_handle = usb_iface_get_hc_handle_device_impl,
     54        .get_my_address = usb_iface_get_my_address_from_device_data,
    5455};
    5556
     
    6162 * @return Error code.
    6263 */
    63 int usb_iface_get_hc_handle_hub_impl(ddf_fun_t *fun, devman_handle_t *handle)
     64int usb_iface_get_hc_handle_device_impl(ddf_fun_t *fun, devman_handle_t *handle)
    6465{
    6566        assert(fun);
    6667        return usb_hc_find(fun->handle, handle);
    67 }
    68 
    69 /** Get host controller handle, interface implementation for child of
    70  * a hub driver.
    71  *
    72  * @param[in] fun Device function the operation is running on.
    73  * @param[out] handle Storage for the host controller handle.
    74  * @return Error code.
    75  */
    76 int usb_iface_get_hc_handle_hub_child_impl(ddf_fun_t *fun,
    77     devman_handle_t *handle)
    78 {
    79         assert(fun != NULL);
    80        
    81         async_sess_t *parent_sess =
    82             devman_parent_device_connect(EXCHANGE_SERIALIZE, fun->handle,
    83             IPC_FLAG_BLOCKING);
    84         if (!parent_sess)
    85                 return ENOMEM;
    86        
    87         async_exch_t *exch = async_exchange_begin(parent_sess);
    88        
    89         sysarg_t hc_handle;
    90         int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    91             IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &hc_handle);
    92        
    93         async_exchange_end(exch);
    94         async_hangup(parent_sess);
    95        
    96         if (rc != EOK)
    97                 return rc;
    98        
    99         *handle = hc_handle;
    100         return EOK;
    10168}
    10269
     
    12592 * @return Error code.
    12693 */
    127 int usb_iface_get_address_hub_impl(ddf_fun_t *fun, devman_handle_t handle,
     94int usb_iface_get_my_address_forward_impl(ddf_fun_t *fun,
    12895    usb_address_t *address)
    12996{
    13097        assert(fun);
    131        
     98
    13299        async_sess_t *parent_sess =
    133100            devman_parent_device_connect(EXCHANGE_SERIALIZE, fun->handle,
     
    135102        if (!parent_sess)
    136103                return ENOMEM;
    137        
     104
    138105        async_exch_t *exch = async_exchange_begin(parent_sess);
    139        
     106
    140107        sysarg_t addr;
    141         int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    142             IPC_M_USB_GET_ADDRESS, handle, &addr);
    143        
     108        int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
     109            IPC_M_USB_GET_MY_ADDRESS, &addr);
     110
    144111        async_exchange_end(exch);
    145112        async_hangup(parent_sess);
    146        
     113
    147114        if (rc != EOK)
    148115                return rc;
    149        
     116
    150117        if (address != NULL)
    151118                *address = (usb_address_t) addr;
    152        
     119
    153120        return EOK;
    154121}
     
    157124 * a hub driver.
    158125 *
     126 * This implementation eccepts 0 as valid handle and replaces it with fun's
     127 * handle.
     128 *
    159129 * @param[in] fun Device function the operation is running on.
    160130 * @param[in] handle Devman handle of USB device we want address of.
     
    162132 * @return Error code.
    163133 */
    164 int usb_iface_get_address_hub_child_impl(ddf_fun_t *fun,
    165     devman_handle_t handle, usb_address_t *address)
     134int usb_iface_get_my_address_from_device_data(ddf_fun_t *fun,
     135    usb_address_t *address)
    166136{
    167         if (handle == 0) {
    168                 handle = fun->handle;
    169         }
    170         return usb_iface_get_address_hub_impl(fun, handle, address);
     137        assert(fun);
     138        assert(fun->driver_data);
     139        usb_hub_attached_device_t *device = fun->driver_data;
     140        assert(device->fun == fun);
     141        if (address)
     142                *address = device->address;
     143        return EOK;
    171144}
    172145
  • uspace/lib/usb/src/hc.c

    r2e1b9dc r747ef72  
    174174 * @return USB address or negative error code.
    175175 */
    176 usb_address_t usb_hc_get_address_by_handle(devman_handle_t dev_handle)
     176usb_address_t usb_get_address_by_handle(devman_handle_t dev_handle)
    177177{
    178178        async_sess_t *parent_sess =
     
    185185       
    186186        sysarg_t address;
    187         int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    188             IPC_M_USB_GET_ADDRESS,
    189             dev_handle, &address);
     187        int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
     188            IPC_M_USB_GET_MY_ADDRESS, &address);
    190189       
    191190        async_exchange_end(exch);
  • uspace/lib/usb/src/resolve.c

    r2e1b9dc r747ef72  
    200200                /* Try to get its address. */
    201201                if (!found_addr) {
    202                         dev_addr = usb_hc_get_address_by_handle(tmp_handle);
     202                        dev_addr = usb_get_address_by_handle(tmp_handle);
    203203                        if (dev_addr >= 0) {
    204204                                found_addr = true;
  • uspace/lib/usbdev/include/usb/dev/dp.h

    r2e1b9dc r747ef72  
    5454} usb_dp_descriptor_nesting_t;
    5555
    56 extern usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[];
     56extern const usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[];
    5757
    5858/** Descriptor parser structure. */
  • uspace/lib/usbdev/include/usb/dev/driver.h

    r2e1b9dc r747ef72  
    7272/** USB device structure. */
    7373typedef struct {
     74        /** Connection backing the pipes.
     75         * Typically, you will not need to use this attribute at all.
     76         */
     77        usb_device_connection_t wire;
    7478        /** The default control pipe. */
    7579        usb_pipe_t ctrl_pipe;
     
    8791        int interface_no;
    8892
    89         /** Alternative interfaces.
    90          * Set to NULL when the driver controls whole device
    91          * (i.e. more (or any) interfaces).
    92          */
    93         usb_alternate_interfaces_t *alternate_interfaces;
     93        /** Alternative interfaces. */
     94        usb_alternate_interfaces_t alternate_interfaces;
    9495
    9596        /** Some useful descriptors. */
    9697        usb_device_descriptors_t descriptors;
    9798
    98         /** Generic DDF device backing this one. RO: DO NOT TOUCH!*/
     99        /** Generic DDF device backing this one. DO NOT TOUCH! */
    99100        ddf_dev_t *ddf_dev;
    100101        /** Custom driver data.
     
    103104         */
    104105        void *driver_data;
    105 
    106         /** Connection backing the pipes.
    107          * Typically, you will not need to use this attribute at all.
    108          */
    109         usb_device_connection_t wire;
    110106} usb_device_t;
    111107
     
    163159int usb_driver_main(const usb_driver_t *);
    164160
     161int usb_device_init(usb_device_t *, ddf_dev_t *,
     162    const usb_endpoint_description_t **, const char **);
     163void usb_device_deinit(usb_device_t *);
     164
    165165int usb_device_select_interface(usb_device_t *, uint8_t,
    166166    const usb_endpoint_description_t **);
    167167
    168168int usb_device_retrieve_descriptors(usb_pipe_t *, usb_device_descriptors_t *);
     169void usb_device_release_descriptors(usb_device_descriptors_t *);
     170
    169171int usb_device_create_pipes(const ddf_dev_t *, usb_device_connection_t *,
    170172    const usb_endpoint_description_t **, const uint8_t *, size_t, int, int,
    171173    usb_endpoint_mapping_t **, size_t *);
    172174int usb_device_destroy_pipes(const ddf_dev_t *, usb_endpoint_mapping_t *, size_t);
    173 int usb_device_init(usb_device_t *, ddf_dev_t *,
    174     const usb_endpoint_description_t **, const char **);
    175 void usb_device_deinit(usb_device_t *);
    176175
    177176void * usb_device_data_alloc(usb_device_t *, size_t);
    178177
    179178size_t usb_interface_count_alternates(const uint8_t *, size_t, uint8_t);
    180 int usb_alternate_interfaces_create(const uint8_t *, size_t, int,
    181     usb_alternate_interfaces_t **);
    182 void usb_alternate_interfaces_destroy(usb_alternate_interfaces_t *);
     179int usb_alternate_interfaces_init(usb_alternate_interfaces_t *,
     180    const uint8_t *, size_t, int);
     181void usb_alternate_interfaces_deinit(usb_alternate_interfaces_t *);
    183182#endif
    184183/**
  • uspace/lib/usbdev/include/usb/dev/hub.h

    r2e1b9dc r747ef72  
    5959} usb_hub_attached_device_t;
    6060
    61 usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_speed_t);
     61usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_address_t,
     62    bool, usb_speed_t);
    6263int usb_hc_register_device(usb_hc_connection_t *,
    6364    const usb_hub_attached_device_t *);
  • uspace/lib/usbdev/include/usb/dev/pipes.h

    r2e1b9dc r747ef72  
    141141typedef struct {
    142142        /** Endpoint pipe. */
    143         usb_pipe_t *pipe;
     143        usb_pipe_t pipe;
    144144        /** Endpoint description. */
    145145        const usb_endpoint_description_t *description;
     
    149149        int interface_setting;
    150150        /** Found descriptor fitting the description. */
    151         usb_standard_endpoint_descriptor_t *descriptor;
     151        const usb_standard_endpoint_descriptor_t *descriptor;
    152152        /** Interface descriptor the endpoint belongs to. */
    153         usb_standard_interface_descriptor_t *interface;
     153        const usb_standard_interface_descriptor_t *interface;
    154154        /** Whether the endpoint was actually found. */
    155155        bool present;
     
    172172int usb_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
    173173    size_t, const uint8_t *, size_t, usb_device_connection_t *);
    174 int usb_pipe_register_with_speed(usb_pipe_t *, usb_speed_t,
    175     unsigned int, usb_hc_connection_t *);
    176174int usb_pipe_register(usb_pipe_t *, unsigned int, usb_hc_connection_t *);
    177175int usb_pipe_unregister(usb_pipe_t *, usb_hc_connection_t *);
  • uspace/lib/usbdev/include/usb/dev/poll.h

    r2e1b9dc r747ef72  
    8484} usb_device_auto_polling_t;
    8585
    86 int usb_device_auto_polling(usb_device_t *, size_t, usb_device_auto_polling_t *,
    87     size_t, void *);
     86int usb_device_auto_polling(usb_device_t *, size_t,
     87    const usb_device_auto_polling_t *, size_t, void *);
    8888
    8989typedef bool (*usb_polling_callback_t)(usb_device_t *,
  • uspace/lib/usbdev/include/usb/dev/recognise.h

    r2e1b9dc r747ef72  
    5050int usb_device_create_match_ids(usb_pipe_t *, match_id_list_t *);
    5151
    52 int usb_device_register_child_in_devman(usb_address_t, devman_handle_t,
     52int usb_device_register_child_in_devman(usb_pipe_t *ctrl_pipe,
    5353    ddf_dev_t *, ddf_dev_ops_t *, void *, ddf_fun_t **);
    5454
  • uspace/lib/usbdev/include/usb/dev/request.h

    r2e1b9dc r747ef72  
    115115int usb_request_set_feature(usb_pipe_t *, usb_request_type_t,
    116116    usb_request_recipient_t, uint16_t, uint16_t);
    117 int usb_request_set_address(usb_pipe_t *, usb_address_t);
    118117int usb_request_get_descriptor(usb_pipe_t *, usb_request_type_t,
    119     usb_request_recipient_t, uint8_t, uint8_t, uint16_t, void *, size_t, 
     118    usb_request_recipient_t, uint8_t, uint8_t, uint16_t, void *, size_t,
    120119    size_t *);
    121120int usb_request_get_descriptor_alloc(usb_pipe_t *, usb_request_type_t,
     
    131130int usb_request_set_descriptor(usb_pipe_t *, usb_request_type_t,
    132131    usb_request_recipient_t, uint8_t, uint8_t, uint16_t, void *, size_t);
     132
    133133int usb_request_get_configuration(usb_pipe_t *, uint8_t *);
    134134int usb_request_set_configuration(usb_pipe_t *, uint8_t);
  • uspace/lib/usbdev/src/altiface.c

    r2e1b9dc r747ef72  
    9090 * @return Error code.
    9191 */
    92 int usb_alternate_interfaces_create(const uint8_t *config_descr,
    93     size_t config_descr_size, int interface_number,
    94     usb_alternate_interfaces_t **alternates_ptr)
     92int usb_alternate_interfaces_init(usb_alternate_interfaces_t *alternates,
     93    const uint8_t *config_descr, size_t config_descr_size, int interface_number)
    9594{
    96         assert(alternates_ptr != NULL);
     95        assert(alternates != NULL);
    9796        assert(config_descr != NULL);
    9897        assert(config_descr_size > 0);
    9998
    100         *alternates_ptr = NULL;
     99        alternates->alternatives = NULL;
     100        alternates->alternative_count = 0;
     101        alternates->current = 0;
     102
    101103        if (interface_number < 0) {
    102104                return EOK;
    103         }
    104 
    105         usb_alternate_interfaces_t *alternates
    106             = malloc(sizeof(usb_alternate_interfaces_t));
    107         if (alternates == NULL) {
    108                 return ENOMEM;
    109105        }
    110106
     
    114110
    115111        if (alternates->alternative_count == 0) {
    116                 free(alternates);
    117112                return ENOENT;
    118113        }
     
    121116            sizeof(usb_alternate_interface_descriptors_t));
    122117        if (alternates->alternatives == NULL) {
    123                 free(alternates);
    124118                return ENOMEM;
    125119        }
    126120
    127         alternates->current = 0;
    128 
    129         usb_dp_parser_t dp_parser = {
     121        const usb_dp_parser_t dp_parser = {
    130122                .nesting = usb_dp_standard_descriptor_nesting
    131123        };
    132         usb_dp_parser_data_t dp_data = {
     124        const usb_dp_parser_data_t dp_data = {
    133125                .data = config_descr,
    134126                .size = config_descr_size,
     
    147139                    || (iface->interface_number != interface_number)) {
    148140                        iface_ptr = usb_dp_get_sibling_descriptor(&dp_parser,
    149                             &dp_data,
    150                             dp_data.data, iface_ptr);
     141                            &dp_data, dp_data.data, iface_ptr);
    151142                        continue;
    152143                }
     
    170161        }
    171162
    172         *alternates_ptr = alternates;
    173 
    174163        return EOK;
    175164}
    176165
    177 void usb_alternate_interfaces_destroy(usb_alternate_interfaces_t *alternate)
     166void usb_alternate_interfaces_deinit(usb_alternate_interfaces_t *alternate)
    178167{
    179168        if (!alternate)
    180169                return;
    181170        free(alternate->alternatives);
    182         free(alternate);
    183171}
    184172/**
  • uspace/lib/usbdev/src/devdrv.c

    r2e1b9dc r747ef72  
    8181 * @return Number of pipes (excluding default control pipe).
    8282 */
    83 static size_t count_other_pipes(const usb_endpoint_description_t **endpoints)
    84 {
    85         size_t count = 0;
    86         if (endpoints == NULL) {
    87                 return 0;
    88         }
    89 
    90         while (endpoints[count] != NULL) {
    91                 count++;
    92         }
    93 
     83static inline size_t count_other_pipes(
     84    const usb_endpoint_description_t **endpoints)
     85{
     86        size_t count;
     87        for (count = 0; endpoints && endpoints[count] != NULL; ++count);
    9488        return count;
    9589}
     
    10498    usb_device_t *dev, int alternate_setting)
    10599{
     100        assert(dev);
     101
    106102        if (endpoints == NULL) {
    107103                dev->pipes = NULL;
     
    300296
    301297        return rc;
     298}
     299
     300/** Cleanup structure initialized via usb_device_retrieve_descriptors.
     301 *
     302 * @param[in] descriptors Where to store the descriptors.
     303 */
     304void usb_device_release_descriptors(usb_device_descriptors_t *descriptors)
     305{
     306        assert(descriptors);
     307        free(descriptors->configuration);
     308        descriptors->configuration = NULL;
    302309}
    303310
     
    319326 *      (not NULL terminated).
    320327 * @param[out] pipes_count_ptr Where to store number of pipes
    321  *      (set to if you wish to ignore the count).
     328 *      (set to NULL if you wish to ignore the count).
    322329 * @return Error code.
    323330 */
     
    340347        const size_t pipe_count = count_other_pipes(endpoints);
    341348        if (pipe_count == 0) {
    342                 *pipes_count_ptr = pipe_count;
     349                if (pipes_count_ptr)
     350                        *pipes_count_ptr = pipe_count;
    343351                *pipes_ptr = NULL;
    344352                return EOK;
     
    346354
    347355        usb_endpoint_mapping_t *pipes
    348             = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
     356            = calloc(pipe_count, sizeof(usb_endpoint_mapping_t));
    349357        if (pipes == NULL) {
    350358                return ENOMEM;
    351359        }
    352360
    353         /* Initialize to NULL to allow smooth rollback. */
    354         for (i = 0; i < pipe_count; i++) {
    355                 pipes[i].pipe = NULL;
    356         }
    357 
    358361        /* Now allocate and fully initialize. */
    359362        for (i = 0; i < pipe_count; i++) {
    360                 pipes[i].pipe = malloc(sizeof(usb_pipe_t));
    361                 if (pipes[i].pipe == NULL) {
    362                         rc = ENOMEM;
    363                         goto rollback_free_only;
    364                 }
    365363                pipes[i].description = endpoints[i];
    366364                pipes[i].interface_no = interface_no;
     
    389387        for (i = 0; i < pipe_count; i++) {
    390388                if (pipes[i].present) {
    391                         rc = usb_pipe_register(pipes[i].pipe,
     389                        rc = usb_pipe_register(&pipes[i].pipe,
    392390                            pipes[i].descriptor->poll_interval, &hc_conn);
    393391                        if (rc != EOK) {
     
    398396
    399397        if (usb_hc_connection_close(&hc_conn) != EOK)
    400                 usb_log_warning("usb_device_create_pipes(): "
    401                     "Failed to close connection.\n");
     398                usb_log_warning("%s: Failed to close connection.\n",
     399                    __FUNCTION__);
    402400
    403401        *pipes_ptr = pipes;
     
    417415        for (i = 0; i < pipe_count; i++) {
    418416                if (pipes[i].present) {
    419                         usb_pipe_unregister(pipes[i].pipe, &hc_conn);
     417                        usb_pipe_unregister(&pipes[i].pipe, &hc_conn);
    420418                }
    421419        }
     
    431429         */
    432430rollback_free_only:
    433         for (i = 0; i < pipe_count; i++) {
    434                 if (pipes[i].pipe != NULL) {
    435                         free(pipes[i].pipe);
    436                 }
    437         }
    438431        free(pipes);
    439432
     
    477470                    i, pipes[i].present ? "" : "not ");
    478471                if (pipes[i].present)
    479                         usb_pipe_unregister(pipes[i].pipe, &hc_conn);
    480                 free(pipes[i].pipe);
     472                        usb_pipe_unregister(&pipes[i].pipe, &hc_conn);
    481473        }
    482474
     
    489481        return EOK;
    490482}
    491 
    492 /** Initialize control pipe in a device.
    493  *
    494  * @param dev USB device in question.
    495  * @param errmsg Where to store error context.
    496  * @return
    497  */
    498 static int init_wire_and_ctrl_pipe(usb_device_t *dev, const char **errmsg)
    499 {
    500         int rc;
    501 
    502         rc = usb_device_connection_initialize_from_device(&dev->wire,
    503             dev->ddf_dev);
    504         if (rc != EOK) {
    505                 *errmsg = "device connection initialization";
    506                 return rc;
    507         }
    508 
    509         rc = usb_pipe_initialize_default_control(&dev->ctrl_pipe,
    510             &dev->wire);
    511         if (rc != EOK) {
    512                 *errmsg = "default control pipe initialization";
    513                 return rc;
    514         }
    515 
    516         return EOK;
    517 }
    518 
    519483
    520484/** Initialize new instance of USB device.
     
    533497        assert(ddf_dev != NULL);
    534498
     499        *errstr_ptr = NULL;
     500
    535501        usb_dev->ddf_dev = ddf_dev;
    536502        usb_dev->driver_data = NULL;
    537503        usb_dev->descriptors.configuration = NULL;
    538         usb_dev->alternate_interfaces = NULL;
    539504        usb_dev->pipes_count = 0;
    540505        usb_dev->pipes = NULL;
    541506
    542507        /* Initialize backing wire and control pipe. */
    543         int rc = init_wire_and_ctrl_pipe(usb_dev, errstr_ptr);
    544         if (rc != EOK) {
     508        int rc = usb_device_connection_initialize_from_device(
     509            &usb_dev->wire, ddf_dev);
     510        if (rc != EOK) {
     511                *errstr_ptr = "device connection initialization";
     512                return rc;
     513        }
     514
     515        /* This pipe was registered by the hub driver,
     516         * during device initialization. */
     517        rc = usb_pipe_initialize_default_control(&usb_dev->ctrl_pipe,
     518            &usb_dev->wire);
     519        if (rc != EOK) {
     520                *errstr_ptr = "default control pipe initialization";
    545521                return rc;
    546522        }
     
    553529            &usb_dev->descriptors);
    554530        if (rc != EOK) {
    555                 /* Nothing allocated, nothing to free. */
    556531                *errstr_ptr = "descriptor retrieval";
    557532                return rc;
    558533        }
    559534
    560         /* Create alternate interfaces. We will silently ignore failure. */
    561         //TODO Why ignore?
    562         usb_alternate_interfaces_create(usb_dev->descriptors.configuration,
    563             usb_dev->descriptors.configuration_size, usb_dev->interface_no,
    564             &usb_dev->alternate_interfaces);
    565 
    566         rc = initialize_other_pipes(endpoints, usb_dev, 0);
     535        /* Create alternate interfaces. We will silently ignore failure.
     536         * We might either control one interface or an entire device,
     537         * it makes no sense to speak about alternate interfaces when
     538         * controlling a device. */
     539        rc = usb_alternate_interfaces_init(&usb_dev->alternate_interfaces,
     540            usb_dev->descriptors.configuration,
     541            usb_dev->descriptors.configuration_size, usb_dev->interface_no);
     542        const int alternate_iface =
     543            (rc == EOK) ? usb_dev->alternate_interfaces.current : 0;
     544
     545        /* TODO Add comment here. */
     546        rc = initialize_other_pipes(endpoints, usb_dev, alternate_iface);
    567547        if (rc != EOK) {
    568548                /* Full configuration descriptor is allocated. */
    569                 free(usb_dev->descriptors.configuration);
     549                usb_device_release_descriptors(&usb_dev->descriptors);
    570550                /* Alternate interfaces may be allocated */
    571                 usb_alternate_interfaces_destroy(usb_dev->alternate_interfaces);
     551                usb_alternate_interfaces_deinit(&usb_dev->alternate_interfaces);
    572552                *errstr_ptr = "pipes initialization";
    573553                return rc;
    574554        }
    575 
    576         *errstr_ptr = NULL;
    577555
    578556        return EOK;
     
    591569                destroy_current_pipes(dev);
    592570
    593                 usb_alternate_interfaces_destroy(dev->alternate_interfaces);
    594                 free(dev->descriptors.configuration);
     571                usb_alternate_interfaces_deinit(&dev->alternate_interfaces);
     572                usb_device_release_descriptors(&dev->descriptors);
    595573                free(dev->driver_data);
    596574        }
  • uspace/lib/usbdev/src/devpoll.c

    r2e1b9dc r747ef72  
    7373
    7474        usb_pipe_t *pipe
    75             = polling_data->dev->pipes[polling_data->pipe_index].pipe;
     75            = &polling_data->dev->pipes[polling_data->pipe_index].pipe;
    7676       
    7777        if (polling_data->debug > 0) {
     
    208208                return EINVAL;
    209209        }
    210         if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
    211             || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
     210        if ((dev->pipes[pipe_index].pipe.transfer_type != USB_TRANSFER_INTERRUPT)
     211            || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) {
    212212                return EINVAL;
    213213        }
    214214
    215         usb_device_auto_polling_t *auto_polling
    216             = malloc(sizeof(usb_device_auto_polling_t));
    217         if (auto_polling == NULL) {
    218                 return ENOMEM;
    219         }
    220 
    221         auto_polling->debug = 1;
    222         auto_polling->auto_clear_halt = true;
    223         auto_polling->delay = 0;
    224         auto_polling->max_failures = MAX_FAILED_ATTEMPTS;
    225         auto_polling->on_data = callback;
    226         auto_polling->on_polling_end = terminated_callback;
    227         auto_polling->on_error = NULL;
    228 
    229         int rc = usb_device_auto_polling(dev, pipe_index, auto_polling,
     215        const usb_device_auto_polling_t auto_polling = {
     216                .debug = 1,
     217                .auto_clear_halt = true,
     218                .delay = 0,
     219                .max_failures = MAX_FAILED_ATTEMPTS,
     220                .on_data = callback,
     221                .on_polling_end = terminated_callback,
     222                .on_error = NULL,
     223        };
     224
     225        return usb_device_auto_polling(dev, pipe_index, &auto_polling,
    230226           request_size, arg);
    231 
    232         free(auto_polling);
    233 
    234         return rc;
    235227}
    236228
     
    253245 */
    254246int usb_device_auto_polling(usb_device_t *dev, size_t pipe_index,
    255     usb_device_auto_polling_t *polling,
     247    const usb_device_auto_polling_t *polling,
    256248    size_t request_size, void *arg)
    257249{
     
    262254                return EINVAL;
    263255        }
    264         if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
    265             || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
     256        if ((dev->pipes[pipe_index].pipe.transfer_type != USB_TRANSFER_INTERRUPT)
     257            || (dev->pipes[pipe_index].pipe.direction != USB_DIRECTION_IN)) {
    266258                return EINVAL;
    267259        }
  • uspace/lib/usbdev/src/dp.c

    r2e1b9dc r747ef72  
    5757
    5858/** Nesting of standard USB descriptors. */
    59 usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[] = {
     59const usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[] = {
    6060        NESTING(CONFIGURATION, INTERFACE),
    6161        NESTING(INTERFACE, ENDPOINT),
  • uspace/lib/usbdev/src/hub.c

    r2e1b9dc r747ef72  
    6666 *
    6767 * @param connection Opened connection to host controller.
     68 * @param preferred Preferred SUB address.
     69 * @param strict Fail if the preferred address is not avialable.
    6870 * @param speed Speed of the new device (device that will be assigned
    6971 *    the returned address).
     
    7173 */
    7274usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
    73     usb_speed_t speed)
     75    usb_address_t preferred, bool strict, usb_speed_t speed)
    7476{
    7577        CHECK_CONNECTION(connection);
     
    7880       
    7981        sysarg_t address;
    80         int rc = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    81             IPC_M_USBHC_REQUEST_ADDRESS, speed,
    82             &address);
     82        int rc = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     83            IPC_M_USBHC_REQUEST_ADDRESS, preferred, strict, speed, &address);
    8384       
    8485        async_exchange_end(exch);
     
    132133}
    133134
    134 
    135 static void unregister_control_endpoint_on_default_address(
    136     usb_hc_connection_t *connection)
     135/** Change address of connected device.
     136 * This function automatically updates the backing connection to point to
     137 * the new address. It also unregisterrs the old endpoint and registers
     138 * a new one.
     139 * This creates whole bunch of problems:
     140 *  1. All pipes using this wire are broken because they are not
     141 *     registered for new address
     142 *  2. All other pipes for this device are using wrong address,
     143 *     possibly targeting completely different device
     144 *
     145 * @param pipe Control endpoint pipe (session must be already started).
     146 * @param new_address New USB address to be set (in native endianness).
     147 * @return Error code.
     148 */
     149static int usb_request_set_address(usb_pipe_t *pipe, usb_address_t new_address,
     150    usb_hc_connection_t *hc_conn)
    137151{
    138         usb_device_connection_t dev_conn;
    139         int rc = usb_device_connection_initialize_on_default_address(&dev_conn,
    140             connection);
    141         if (rc != EOK) {
    142                 return;
    143         }
    144 
    145         usb_pipe_t ctrl_pipe;
    146         rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn);
    147         if (rc != EOK) {
    148                 return;
    149         }
    150 
    151         usb_pipe_unregister(&ctrl_pipe, connection);
     152        if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) {
     153                return EINVAL;
     154        }
     155        assert(pipe);
     156        assert(hc_conn);
     157        assert(pipe->wire != NULL);
     158
     159        const uint16_t addr = uint16_host2usb((uint16_t)new_address);
     160
     161        int rc = usb_control_request_set(pipe,
     162            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
     163            USB_DEVREQ_SET_ADDRESS, addr, 0, NULL, 0);
     164
     165        if (rc != EOK) {
     166                return rc;
     167        }
     168
     169        /* TODO: prevent others from accessing the wire now. */
     170        if (usb_pipe_unregister(pipe, hc_conn) != EOK) {
     171                usb_log_warning(
     172                    "Failed to unregister the old pipe on address change.\n");
     173        }
     174        /* The address is already changed so set it in the wire */
     175        pipe->wire->address = new_address;
     176        rc = usb_pipe_register(pipe, 0, hc_conn);
     177        if (rc != EOK)
     178                return EADDRNOTAVAIL;
     179
     180        return EOK;
    152181}
    153182
     
    171200 *
    172201 * @param[in] parent Parent device (i.e. the hub device).
    173  * @param[in] connection Connection to host controller.
     202 * @param[in] connection Connection to host controller. Must be non-null.
    174203 * @param[in] dev_speed New device speed.
    175204 * @param[in] enable_port Function for enabling signaling through the port the
     
    177206 * @param[in] arg Any data argument to @p enable_port.
    178207 * @param[out] assigned_address USB address of the device.
    179  * @param[in] dev_ops Child device ops.
     208 * @param[in] dev_ops Child device ops. Will use default if not provided.
    180209 * @param[in] new_dev_data Arbitrary pointer to be stored in the child
    181  *      as @c driver_data.
     210 *      as @c driver_data. Will allocate and assign usb_hub_attached_device_t
     211 *      structure if NULL.
    182212 * @param[out] new_fun Storage where pointer to allocated child function
    183  *      will be written.
     213 *      will be written. Must be non-null.
    184214 * @return Error code.
     215 * @retval EINVAL Either connection or new_fun is a NULL pointer.
    185216 * @retval ENOENT Connection to HC not opened.
    186217 * @retval EADDRNOTAVAIL Failed retrieving free address from host controller.
     
    195226    ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun)
    196227{
    197         assert(connection != NULL);
     228        if (new_fun == NULL || connection == NULL)
     229                return EINVAL;
     230
    198231        // FIXME: this is awful, we are accessing directly the structure.
     232        // TODO: Why not use provided connection?
    199233        usb_hc_connection_t hc_conn = {
    200234                .hc_handle = connection->hc_handle,
     
    215249        }
    216250
    217 
    218251        /*
    219252         * Request new address.
    220253         */
    221         usb_address_t dev_addr = usb_hc_request_address(&hc_conn, dev_speed);
     254        usb_address_t dev_addr =
     255            usb_hc_request_address(&hc_conn, 0, false, dev_speed);
    222256        if (dev_addr < 0) {
    223257                rc = EADDRNOTAVAIL;
     
    240274
    241275        usb_pipe_t ctrl_pipe;
    242         rc = usb_pipe_initialize_default_control(&ctrl_pipe,
    243             &dev_conn);
     276        rc = usb_pipe_initialize_default_control(&ctrl_pipe, &dev_conn);
    244277        if (rc != EOK) {
    245278                rc = ENOTCONN;
     
    248281
    249282        do {
    250                 rc = usb_pipe_register_with_speed(&ctrl_pipe, dev_speed, 0,
    251                     &hc_conn);
    252                 if (rc != EOK) {
     283                rc = usb_hc_request_address(&hc_conn, USB_ADDRESS_DEFAULT,
     284                    true, dev_speed);
     285                if (rc == ENOENT) {
    253286                        /* Do not overheat the CPU ;-). */
    254287                        async_usleep(ENDPOINT_0_0_REGISTER_ATTEMPT_DELAY_USEC);
    255288                }
    256         } while (rc != EOK);
     289        } while (rc == ENOENT);
     290        if (rc < 0) {
     291                goto leave_release_free_address;
     292        }
     293
     294        /* Register control pipe on default address. */
     295        rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
     296        if (rc != EOK) {
     297                rc = ENOTCONN;
     298                goto leave_release_default_address;
     299        }
     300
    257301        struct timeval end_time;
    258302
     
    267311         * above might use much of this time so we should only wait to fill
    268312         * up the 100ms quota*/
    269         suseconds_t elapsed = tv_sub(&end_time, &start_time);
     313        const suseconds_t elapsed = tv_sub(&end_time, &start_time);
    270314        if (elapsed < 100000) {
    271315                async_usleep(100000 - elapsed);
    272316        }
    273317
    274         /*
    275          * Endpoint is registered. We can enable the port and change
    276          * device address.
    277          */
     318        /* Endpoint is registered. We can enable the port and change address. */
    278319        rc = enable_port(arg);
    279320        if (rc != EOK) {
     
    287328        async_usleep(10000);
    288329
     330        /* Get max_packet_size value. */
    289331        rc = usb_pipe_probe_default_control(&ctrl_pipe);
    290332        if (rc != EOK) {
     
    293335        }
    294336
    295         rc = usb_request_set_address(&ctrl_pipe, dev_addr);
     337        rc = usb_request_set_address(&ctrl_pipe, dev_addr, &hc_conn);
    296338        if (rc != EOK) {
    297339                rc = ESTALL;
     
    299341        }
    300342
    301         /*
    302          * Address changed. We can release the original endpoint, thus
    303          * allowing other to access the default address.
    304          */
    305         unregister_control_endpoint_on_default_address(&hc_conn);
    306 
    307         /*
    308          * Time to register the new endpoint.
    309          */
    310         rc = usb_pipe_register(&ctrl_pipe, 0, &hc_conn);
    311         if (rc != EOK) {
    312                 goto leave_release_free_address;
    313         }
    314 
    315         /*
    316          * It is time to register the device with devman.
    317          */
     343        /* Address changed. We can release the default, thus
     344         * allowing other to access the default address. */
     345        usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT);
     346
     347        /* Register the device with devman. */
    318348        /* FIXME: create device_register that will get opened ctrl pipe. */
    319349        ddf_fun_t *child_fun;
    320         rc = usb_device_register_child_in_devman(dev_addr, dev_conn.hc_handle,
     350        rc = usb_device_register_child_in_devman(&ctrl_pipe,
    321351            parent, dev_ops, new_dev_data, &child_fun);
    322352        if (rc != EOK) {
    323                 rc = ESTALL;
    324353                goto leave_release_free_address;
    325354        }
    326355
    327         /*
    328          * And now inform the host controller about the handle.
    329          */
    330         usb_hub_attached_device_t new_device = {
     356        const usb_hub_attached_device_t new_device = {
    331357                .address = dev_addr,
    332358                .fun = child_fun,
    333359        };
     360
     361
     362        /* Inform the host controller about the handle. */
    334363        rc = usb_hc_register_device(&hc_conn, &new_device);
    335364        if (rc != EOK) {
     365                /* We know nothing about that data. */
     366                if (new_dev_data)
     367                        child_fun->driver_data = NULL;
     368                /* The child function is already created. */
     369                ddf_fun_destroy(child_fun);
    336370                rc = EDESTADDRREQ;
    337371                goto leave_release_free_address;
    338372        }
    339373
    340 
    341         /*
    342          * And we are done.
    343          */
    344374        if (assigned_address != NULL) {
    345375                *assigned_address = dev_addr;
    346376        }
    347         if (new_fun != NULL) {
    348                 *new_fun = child_fun;
    349         }
     377
     378        *new_fun = child_fun;
    350379
    351380        rc = EOK;
     
    357386         */
    358387leave_release_default_address:
    359         usb_pipe_unregister(&ctrl_pipe, &hc_conn);
     388        usb_hc_unregister_device(&hc_conn, USB_ADDRESS_DEFAULT);
    360389
    361390leave_release_free_address:
    362         usb_hc_unregister_device(&hc_conn, dev_addr);
     391        /* This might be either 0:0 or dev_addr:0 */
     392        if (usb_pipe_unregister(&ctrl_pipe, &hc_conn) != EOK)
     393                usb_log_warning("%s: Failed to unregister default pipe.\n",
     394                    __FUNCTION__);
     395
     396        if (usb_hc_unregister_device(&hc_conn, dev_addr) != EOK)
     397                usb_log_warning("%s: Failed to unregister device.\n",
     398                    __FUNCTION__);
    363399
    364400close_connection:
    365401        if (usb_hc_connection_close(&hc_conn) != EOK)
    366                 usb_log_warning("usb_hc_new_device_wrapper(): Failed to close "
    367                     "connection.\n");
     402                usb_log_warning("%s: Failed to close hc connection.\n",
     403                    __FUNCTION__);
    368404
    369405        return rc;
  • uspace/lib/usbdev/src/pipes.c

    r2e1b9dc r747ef72  
    5656        async_exch_t *exch = async_exchange_begin(sess);
    5757       
    58         /*
    59          * We are sending special value as a handle - zero - to get
    60          * handle of the parent function (that handle was used
    61          * when registering our device @p dev.
    62          */
    6358        sysarg_t address;
    64         int rc = async_req_2_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
    65             IPC_M_USB_GET_ADDRESS, 0, &address);
     59        int rc = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
     60            IPC_M_USB_GET_MY_ADDRESS, &address);
    6661       
    6762        async_exchange_end(exch);
     
    8075int usb_device_get_assigned_interface(const ddf_dev_t *device)
    8176{
     77        assert(device);
    8278        async_sess_t *parent_sess =
    8379            devman_parent_device_connect(EXCHANGE_ATOMIC, device->handle,
  • uspace/lib/usbdev/src/pipesinit.c

    r2e1b9dc r747ef72  
    192192        }
    193193
    194         if (ep_mapping->pipe == NULL) {
    195                 return EBADMEM;
    196         }
    197194        if (ep_mapping->present) {
    198195                return EEXISTS;
    199196        }
    200197
    201         int rc = usb_pipe_initialize(ep_mapping->pipe, wire,
     198        int rc = usb_pipe_initialize(&ep_mapping->pipe, wire,
    202199            ep_no, description.transfer_type, endpoint->max_packet_size,
    203200            description.direction);
     
    254251 *
    255252 * The mapping array is expected to conform to following rules:
    256  * - @c pipe must point to already allocated structure with uninitialized pipe
     253 * - @c pipe must be uninitialized pipe
    257254 * - @c description must point to prepared endpoint description
    258255 * - @c descriptor does not need to be initialized (will be overwritten)
     
    297294        }
    298295
    299         /*
    300          * Go through the mapping and set all endpoints to not present.
    301          */
    302         size_t i;
    303         for (i = 0; i < mapping_count; i++) {
     296        /* Go through the mapping and set all endpoints to not present. */
     297        for (size_t i = 0; i < mapping_count; i++) {
    304298                mapping[i].present = false;
    305299                mapping[i].descriptor = NULL;
     
    307301        }
    308302
    309         /*
    310          * Prepare the descriptor parser.
    311          */
     303        /* Prepare the descriptor parser. */
    312304        const usb_dp_parser_t dp_parser = {
    313305                .nesting = descriptor_nesting
     
    454446 * @return Error code.
    455447 */
    456 int usb_pipe_register(usb_pipe_t *pipe,
    457     unsigned int interval,
    458     usb_hc_connection_t *hc_connection)
    459 {
    460         return usb_pipe_register_with_speed(pipe, USB_SPEED_MAX + 1,
    461             interval, hc_connection);
    462 }
    463 
    464 /** Register endpoint with a speed at the host controller.
    465  *
    466  * You will rarely need to use this function because it is needed only
    467  * if the registered endpoint is of address 0 and there is no other way
    468  * to tell speed of the device at address 0.
    469  *
    470  * @param pipe Pipe to be registered.
    471  * @param speed Speed of the device
    472  *      (invalid speed means use previously specified one).
    473  * @param interval Polling interval.
    474  * @param hc_connection Connection to the host controller (must be opened).
    475  * @return Error code.
    476  */
    477 int usb_pipe_register_with_speed(usb_pipe_t *pipe, usb_speed_t speed,
    478     unsigned int interval,
     448int usb_pipe_register(usb_pipe_t *pipe, unsigned interval,
    479449    usb_hc_connection_t *hc_connection)
    480450{
    481451        assert(pipe);
    482452        assert(hc_connection);
    483        
     453
    484454        if (!usb_hc_connection_is_opened(hc_connection))
    485455                return EBADF;
    486        
     456
    487457        const usb_target_t target =
    488458            {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
    489 #define _PACK2(high, low) (((high) << 16) + (low))
    490 #define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low))
    491        
     459#define _PACK2(high, low) (((high & 0xffff) << 16) | (low & 0xffff))
     460
    492461        async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
    493462        int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
    494463            IPC_M_USBHC_REGISTER_ENDPOINT, target.packed,
    495             _PACK3(speed, pipe->transfer_type, pipe->direction),
     464            _PACK2(pipe->transfer_type, pipe->direction),
    496465            _PACK2(pipe->max_packet_size, interval));
    497466        async_exchange_end(exch);
    498        
     467
    499468#undef _PACK2
    500 #undef _PACK3
    501        
    502469        return rc;
    503470}
  • uspace/lib/usbdev/src/recognise.c

    r2e1b9dc r747ef72  
    3535#include <sys/types.h>
    3636#include <fibril_synch.h>
     37#include <usb/debug.h>
     38#include <usb/dev/hub.h>
    3739#include <usb/dev/pipes.h>
    3840#include <usb/dev/recognise.h>
     
    5052
    5153/** DDF operations of child devices. */
    52 ddf_dev_ops_t child_ops = {
     54static ddf_dev_ops_t child_ops = {
    5355        .interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
    5456};
     
    6466#define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a))
    6567
    66 /* FIXME: make this dynamic */
    67 #define MATCH_STRING_MAX 256
    68 
    6968/** Add formatted match id.
    7069 *
     
    7574 */
    7675static int usb_add_match_id(match_id_list_t *matches, int score,
    77     const char *format, ...)
     76    const char *match_str)
    7877{
    79         char *match_str = NULL;
    80         match_id_t *match_id = NULL;
    81         int rc;
    82        
    83         match_str = malloc(MATCH_STRING_MAX + 1);
    84         if (match_str == NULL) {
    85                 rc = ENOMEM;
    86                 goto failure;
    87         }
    88 
    89         /*
    90          * FIXME: replace with dynamic allocation of exact size
    91          */
    92         va_list args;
    93         va_start(args, format   );
    94         vsnprintf(match_str, MATCH_STRING_MAX, format, args);
    95         match_str[MATCH_STRING_MAX] = 0;
    96         va_end(args);
    97 
    98         match_id = create_match_id();
     78        assert(matches);
     79
     80        match_id_t *match_id = create_match_id();
    9981        if (match_id == NULL) {
    100                 rc = ENOMEM;
    101                 goto failure;
     82                return ENOMEM;
    10283        }
    10384
     
    10788
    10889        return EOK;
    109        
    110 failure:
    111         if (match_str != NULL) {
    112                 free(match_str);
    113         }
    114         if (match_id != NULL) {
    115                 match_id->id = NULL;
    116                 delete_match_id(match_id);
    117         }
    118        
    119         return rc;
    12090}
    12191
     
    12999#define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \
    130100        do { \
    131                 int __rc = usb_add_match_id((match_ids), (score), \
    132                     format, ##__VA_ARGS__); \
     101                char *str = NULL; \
     102                int __rc = asprintf(&str, format, ##__VA_ARGS__); \
     103                if (__rc > 0) { \
     104                        __rc = usb_add_match_id((match_ids), (score), str); \
     105                } \
    133106                if (__rc != EOK) { \
     107                        free(str); \
    134108                        return __rc; \
    135109                } \
     
    150124    match_id_list_t *matches)
    151125{
    152         if (desc_interface == NULL) {
    153                 return EINVAL;
    154         }
    155         if (matches == NULL) {
     126        if (desc_interface == NULL || matches == NULL) {
    156127                return EINVAL;
    157128        }
     
    314285    match_id_list_t *matches)
    315286{
     287        assert(ctrl_pipe);
    316288        int rc;
    317289        /*
     
    336308/** Probe for device kind and register it in devman.
    337309 *
    338  * @param[in] address Address of the (unknown) attached device.
    339  * @param[in] hc_handle Handle of the host controller.
     310 * @param[in] ctrl_pipe Control pipe to the device.
    340311 * @param[in] parent Parent device.
    341  * @param[in] dev_ops Child device ops.
     312 * @param[in] dev_ops Child device ops. Default child_ops will be used if NULL.
    342313 * @param[in] dev_data Arbitrary pointer to be stored in the child
    343314 *      as @c driver_data.
     
    346317 * @return Error code.
    347318 */
    348 int usb_device_register_child_in_devman(usb_address_t address,
    349     devman_handle_t hc_handle, ddf_dev_t *parent,
    350     ddf_dev_ops_t *dev_ops, void *dev_data, ddf_fun_t **child_fun)
     319int usb_device_register_child_in_devman(usb_pipe_t *ctrl_pipe,
     320    ddf_dev_t *parent, ddf_dev_ops_t *dev_ops, void *dev_data,
     321    ddf_fun_t **child_fun)
    351322{
    352         size_t this_device_name_index;
     323        if (child_fun == NULL || ctrl_pipe == NULL)
     324                return EINVAL;
     325
     326        if (!dev_ops && dev_data) {
     327                usb_log_warning("Using standard fun ops with arbitrary "
     328                    "driver data. This does not have to work.\n");
     329        }
    353330
    354331        fibril_mutex_lock(&device_name_index_mutex);
    355         this_device_name_index = device_name_index;
    356         device_name_index++;
     332        const size_t this_device_name_index = device_name_index++;
    357333        fibril_mutex_unlock(&device_name_index_mutex);
    358334
    359335        ddf_fun_t *child = NULL;
    360         char *child_name = NULL;
    361336        int rc;
    362         usb_device_connection_t dev_connection;
    363         usb_pipe_t ctrl_pipe;
    364 
    365         rc = usb_device_connection_initialize(&dev_connection, hc_handle, address);
    366         if (rc != EOK) {
    367                 goto failure;
    368         }
    369 
    370         rc = usb_pipe_initialize_default_control(&ctrl_pipe,
    371             &dev_connection);
    372         if (rc != EOK) {
    373                 goto failure;
    374         }
    375         rc = usb_pipe_probe_default_control(&ctrl_pipe);
    376         if (rc != EOK) {
    377                 goto failure;
    378         }
    379337
    380338        /*
     
    382340         * naming etc., something more descriptive could be created.
    383341         */
    384         rc = asprintf(&child_name, "usb%02zu_a%d",
    385             this_device_name_index, address);
     342        char child_name[12]; /* The format is: "usbAB_aXYZ", length 11 */
     343        rc = snprintf(child_name, sizeof(child_name),
     344            "usb%02zu_a%d", this_device_name_index, ctrl_pipe->wire->address);
    386345        if (rc < 0) {
    387346                goto failure;
     
    401360
    402361        child->driver_data = dev_data;
    403 
    404         rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids);
     362        /* Store the attached device in fun driver data if there is no
     363         * other data */
     364        if (!dev_data) {
     365                usb_hub_attached_device_t *new_device = ddf_fun_data_alloc(
     366                    child, sizeof(usb_hub_attached_device_t));
     367                if (!new_device) {
     368                        rc = ENOMEM;
     369                        goto failure;
     370                }
     371                new_device->address = ctrl_pipe->wire->address;
     372                new_device->fun = child;
     373        }
     374
     375
     376        rc = usb_device_create_match_ids(ctrl_pipe, &child->match_ids);
    405377        if (rc != EOK) {
    406378                goto failure;
     
    412384        }
    413385
    414         if (child_fun != NULL) {
    415                 *child_fun = child;
    416         }
    417 
     386        *child_fun = child;
    418387        return EOK;
    419388
    420389failure:
    421390        if (child != NULL) {
    422                 child->name = NULL;
     391                /* We know nothing about the data if it came from outside. */
     392                if (dev_data) {
     393                        child->driver_data = NULL;
     394                }
    423395                /* This takes care of match_id deallocation as well. */
    424396                ddf_fun_destroy(child);
    425397        }
    426         if (child_name != NULL) {
    427                 free(child_name);
    428         }
    429398
    430399        return rc;
  • uspace/lib/usbdev/src/request.c

    r2e1b9dc r747ef72  
    250250}
    251251
    252 /** Change address of connected device.
    253  * This function automatically updates the backing connection to point to
    254  * the new address.
    255  *
    256  * @param pipe Control endpoint pipe (session must be already started).
    257  * @param new_address New USB address to be set (in native endianness).
    258  * @return Error code.
    259  */
    260 int usb_request_set_address(usb_pipe_t *pipe,
    261     usb_address_t new_address)
    262 {
    263         if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) {
    264                 return EINVAL;
    265         }
    266 
    267         uint16_t addr = uint16_host2usb((uint16_t)new_address);
    268 
    269         int rc = usb_control_request_set(pipe,
    270             USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
    271             USB_DEVREQ_SET_ADDRESS,
    272             addr, 0,
    273             NULL, 0);
    274 
    275         if (rc != EOK) {
    276                 return rc;
    277         }
    278 
    279         assert(pipe->wire != NULL);
    280         /* TODO: prevent other from accessing wire now. */
    281         pipe->wire->address = new_address;
    282 
    283         return EOK;
    284 }
    285 
    286252/** Retrieve USB descriptor of a USB device.
    287253 *
  • uspace/lib/usbhid/include/usb/hid/usages/consumer.h

    r2e1b9dc r747ef72  
    3737#define LIBUSBHID_CONSUMER_H_
    3838
    39 const char *usbhid_multimedia_usage_to_str(int usage);
     39const char *usbhid_multimedia_usage_to_str(unsigned usage);
    4040
    4141#endif /* LIBUSBHID_CONSUMER_H_ */
  • uspace/lib/usbhid/src/consumer.c

    r2e1b9dc r747ef72  
    3838#include <usb/hid/usages/consumer.h>
    3939
    40 static const char *usbhid_consumer_usage_str[0x29d] = {
     40static const char *usbhid_consumer_usage_str[] = {
    4141        [0x01] = "Consumer Control",
    4242        [0x02] = "Numeric Key Pad",
     
    358358        [0x13e] = "Reserved",
    359359        [0x13f] = "Reserved",
    360         [0x140] = "Reserved", 
     360        [0x140] = "Reserved",
    361361        [0x141] = "Reserved",
    362362        [0x142] = "Reserved",
     
    717717 * @retval HelenOS key code corresponding to the given USB Consumer Page Usage.
    718718 */
    719 const char *usbhid_multimedia_usage_to_str(int usage)
     719const char *usbhid_multimedia_usage_to_str(unsigned usage)
    720720{
    721         size_t map_length = sizeof(usbhid_consumer_usage_str) / sizeof(char *);
     721        static const size_t map_length =
     722            sizeof(usbhid_consumer_usage_str) / sizeof(char *);
    722723
    723         if ((usage < 0) || ((size_t)usage >= map_length))
     724        if (usage >= map_length)
    724725                return "Unknown usage";
    725726
    726         /*! @todo What if the usage is not in the table? */
    727727        return usbhid_consumer_usage_str[usage];
    728728}
  • uspace/lib/usbhid/src/hiddescriptor.c

    r2e1b9dc r747ef72  
    135135int usb_hid_report_init(usb_hid_report_t *report)
    136136{
    137         if(report == NULL) {
     137        if (report == NULL) {
    138138                return EINVAL;
    139139        }
     
    144144
    145145        report->use_report_ids = 0;
    146     return EOK;   
     146    return EOK;
    147147}
    148148
  • uspace/lib/usbhid/src/hidpath.c

    r2e1b9dc r747ef72  
    385385void usb_hid_report_path_free(usb_hid_report_path_t *path)
    386386{
     387        if (path == NULL)
     388                return;
    387389        while(!list_empty(&path->items)){
    388390                usb_hid_report_remove_last_item(path);
  • uspace/lib/usbhid/src/hidreq.c

    r2e1b9dc r747ef72  
    8484        usb_log_debug("Sending Set Report request to the device.\n");
    8585       
    86         rc = usb_control_request_set(ctrl_pipe, 
    87             USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
     86        rc = usb_control_request_set(ctrl_pipe,
     87            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
    8888            USB_HIDREQ_SET_REPORT, value, iface_no, buffer, buf_size);
    8989
    9090        if (rc != EOK) {
    91                 usb_log_warning("Error sending Set Report request to the "
     91                usb_log_error("Error sending Set Report request to the "
    9292                    "device: %s.\n", str_error(rc));
    9393                return rc;
  • uspace/lib/usbhost/include/usb/host/hcd.h

    r2e1b9dc r747ef72  
    6868 * @param bw_count Bandwidth compute function, passed to endpoint manager.
    6969 */
    70 static inline void hcd_init(hcd_t *hcd, size_t bandwidth,
     70static inline void hcd_init(hcd_t *hcd, usb_speed_t max_speed, size_t bandwidth,
    7171    size_t (*bw_count)(usb_speed_t, usb_transfer_type_t, size_t, size_t))
    7272{
    7373        assert(hcd);
    74         usb_device_manager_init(&hcd->dev_manager);
     74        usb_device_manager_init(&hcd->dev_manager, max_speed);
    7575        usb_endpoint_manager_init(&hcd->ep_manager, bandwidth, bw_count);
    7676        hcd->private_data = NULL;
  • uspace/lib/usbhost/include/usb/host/usb_device_manager.h

    r2e1b9dc r747ef72  
    5959                devman_handle_t handle; /**< Devman handle of the device. */
    6060        } devices[USB_ADDRESS_COUNT];
     61        usb_speed_t max_speed;
    6162        fibril_mutex_t guard;
    6263        /** The last reserved address */
     
    6465} usb_device_manager_t;
    6566
    66 void usb_device_manager_init(usb_device_manager_t *instance);
     67void usb_device_manager_init(
     68    usb_device_manager_t *instance, usb_speed_t max_speed);
    6769
    68 usb_address_t usb_device_manager_get_free_address(
    69     usb_device_manager_t *instance, usb_speed_t speed);
     70int usb_device_manager_request_address(usb_device_manager_t *instance,
     71    usb_address_t *address, bool strict, usb_speed_t speed);
    7072
    71 int usb_device_manager_bind(usb_device_manager_t *instance,
     73int usb_device_manager_bind_address(usb_device_manager_t *instance,
    7274    usb_address_t address, devman_handle_t handle);
    7375
    74 int usb_device_manager_release(usb_device_manager_t *instance,
     76int usb_device_manager_release_address(usb_device_manager_t *instance,
    7577    usb_address_t address);
    7678
  • uspace/lib/usbhost/include/usb/host/usb_endpoint_manager.h

    r2e1b9dc r747ef72  
    9090    usb_address_t address, usb_endpoint_t endpoint, usb_direction_t direction,
    9191    void (*callback)(endpoint_t *, void *), void *arg);
     92
     93void usb_endpoint_manager_remove_address(usb_endpoint_manager_t *instance,
     94    usb_address_t address, void (*callback)(endpoint_t *, void *), void *arg);
    9295#endif
    9396/**
  • uspace/lib/usbhost/src/iface.c

    r2e1b9dc r747ef72  
    8989}
    9090/*----------------------------------------------------------------------------*/
    91 /** Request address interface function
    92  *
    93  * @param[in] fun DDF function that was called.
    94  * @param[in] speed Speed to associate with the new default address.
    95  * @param[out] address Place to write a new address.
    96  * @return Error code.
    97  */
    98 static int request_address(
    99     ddf_fun_t *fun, usb_speed_t speed, usb_address_t *address)
    100 {
    101         assert(fun);
    102         hcd_t *hcd = fun_to_hcd(fun);
    103         assert(hcd);
    104         assert(address);
    105 
    106         usb_log_debug("Address request speed: %s.\n", usb_str_speed(speed));
    107         *address =
    108             usb_device_manager_get_free_address(&hcd->dev_manager, speed);
    109         usb_log_debug("Address request with result: %d.\n", *address);
    110         if (*address <= 0)
    111                 return *address;
    112         return EOK;
    113 }
    114 /*----------------------------------------------------------------------------*/
    115 /** Bind address interface function
    116  *
    117  * @param[in] fun DDF function that was called.
    118  * @param[in] address Address of the device
    119  * @param[in] handle Devman handle of the device driver.
    120  * @return Error code.
    121  */
    122 static int bind_address(
    123   ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
    124 {
    125         assert(fun);
    126         hcd_t *hcd = fun_to_hcd(fun);
    127         assert(hcd);
    128 
    129         usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle);
    130         return usb_device_manager_bind(&hcd->dev_manager, address, handle);
    131 }
    132 /*----------------------------------------------------------------------------*/
    133 /** Find device handle by address interface function.
    134  *
    135  * @param[in] fun DDF function that was called.
    136  * @param[in] address Address in question.
    137  * @param[out] handle Where to store device handle if found.
    138  * @return Error code.
    139  */
    140 static int find_by_address(ddf_fun_t *fun, usb_address_t address,
    141     devman_handle_t *handle)
    142 {
    143         assert(fun);
    144         hcd_t *hcd = fun_to_hcd(fun);
    145         assert(hcd);
    146         return usb_device_manager_get_info_by_address(
    147             &hcd->dev_manager, address, handle, NULL);
    148 }
    149 /*----------------------------------------------------------------------------*/
    150 /** Release address interface function
    151  *
    152  * @param[in] fun DDF function that was called.
    153  * @param[in] address USB address to be released.
    154  * @return Error code.
    155  */
    156 static int release_address(ddf_fun_t *fun, usb_address_t address)
    157 {
    158         assert(fun);
    159         hcd_t *hcd = fun_to_hcd(fun);
    160         assert(hcd);
    161         usb_log_debug("Address release %d.\n", address);
    162         usb_device_manager_release(&hcd->dev_manager, address);
    163         return EOK;
    164 }
    165 /*----------------------------------------------------------------------------*/
    16691static int register_helper(endpoint_t *ep, void *arg)
    16792{
     
    183108}
    184109/*----------------------------------------------------------------------------*/
     110static void unregister_helper_warn(endpoint_t *ep, void *arg)
     111{
     112        hcd_t *hcd = arg;
     113        assert(ep);
     114        assert(hcd);
     115        usb_log_warning("Endpoint %d:%d %s was left behind, removing.\n",
     116            ep->address, ep->endpoint, usb_str_direction(ep->direction));
     117        if (hcd->ep_remove_hook)
     118                hcd->ep_remove_hook(hcd, ep);
     119}
     120/*----------------------------------------------------------------------------*/
     121/** Request address interface function
     122 *
     123 * @param[in] fun DDF function that was called.
     124 * @param[in] speed Speed to associate with the new default address.
     125 * @param[out] address Place to write a new address.
     126 * @return Error code.
     127 */
     128static int request_address(
     129    ddf_fun_t *fun, usb_address_t *address, bool strict, usb_speed_t speed)
     130{
     131        assert(fun);
     132        hcd_t *hcd = fun_to_hcd(fun);
     133        assert(hcd);
     134        assert(address);
     135
     136        usb_log_debug("Address request: speed: %s, address: %d, strict: %s.\n",
     137            usb_str_speed(speed), *address, strict ? "YES" : "NO");
     138        return usb_device_manager_request_address(
     139            &hcd->dev_manager, address, strict, speed);
     140}
     141/*----------------------------------------------------------------------------*/
     142/** Bind address interface function
     143 *
     144 * @param[in] fun DDF function that was called.
     145 * @param[in] address Address of the device
     146 * @param[in] handle Devman handle of the device driver.
     147 * @return Error code.
     148 */
     149static int bind_address(
     150  ddf_fun_t *fun, usb_address_t address, devman_handle_t handle)
     151{
     152        assert(fun);
     153        hcd_t *hcd = fun_to_hcd(fun);
     154        assert(hcd);
     155
     156        usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle);
     157        return usb_device_manager_bind_address(
     158            &hcd->dev_manager, address, handle);
     159}
     160/*----------------------------------------------------------------------------*/
     161/** Find device handle by address interface function.
     162 *
     163 * @param[in] fun DDF function that was called.
     164 * @param[in] address Address in question.
     165 * @param[out] handle Where to store device handle if found.
     166 * @return Error code.
     167 */
     168static int find_by_address(ddf_fun_t *fun, usb_address_t address,
     169    devman_handle_t *handle)
     170{
     171        assert(fun);
     172        hcd_t *hcd = fun_to_hcd(fun);
     173        assert(hcd);
     174        return usb_device_manager_get_info_by_address(
     175            &hcd->dev_manager, address, handle, NULL);
     176}
     177/*----------------------------------------------------------------------------*/
     178/** Release address interface function
     179 *
     180 * @param[in] fun DDF function that was called.
     181 * @param[in] address USB address to be released.
     182 * @return Error code.
     183 */
     184static int release_address(ddf_fun_t *fun, usb_address_t address)
     185{
     186        assert(fun);
     187        hcd_t *hcd = fun_to_hcd(fun);
     188        assert(hcd);
     189        usb_log_debug("Address release %d.\n", address);
     190        usb_device_manager_release_address(&hcd->dev_manager, address);
     191        usb_endpoint_manager_remove_address(&hcd->ep_manager, address,
     192            unregister_helper_warn, hcd);
     193        return EOK;
     194}
     195/*----------------------------------------------------------------------------*/
    185196static int register_endpoint(
    186     ddf_fun_t *fun, usb_address_t address, usb_speed_t ep_speed,
    187     usb_endpoint_t endpoint,
     197    ddf_fun_t *fun, usb_address_t address, usb_endpoint_t endpoint,
    188198    usb_transfer_type_t transfer_type, usb_direction_t direction,
    189199    size_t max_packet_size, unsigned int interval)
     
    193203        assert(hcd);
    194204        const size_t size = max_packet_size;
    195         /* Default address is not bound or registered,
    196          * thus it does not provide speed info. */
    197         usb_speed_t speed = ep_speed;
    198         /* NOTE The function will return EINVAL and won't
    199          * touch speed variable for default address */
    200         usb_device_manager_get_info_by_address(
     205        usb_speed_t speed = USB_SPEED_MAX;
     206        const int ret = usb_device_manager_get_info_by_address(
    201207            &hcd->dev_manager, address, NULL, &speed);
     208        if (ret != EOK) {
     209                return ret;
     210        }
    202211
    203212        usb_log_debug("Register endpoint %d:%d %s-%s %s %zuB %ums.\n",
  • uspace/lib/usbhost/src/usb_device_manager.c

    r2e1b9dc r747ef72  
    3838#include <usb/host/usb_device_manager.h>
    3939
     40/** Get a free USB address
     41 *
     42 * @param[in] instance Device manager structure to use.
     43 * @param[in] speed Speed of the device requiring address.
     44 * @return Free address, or error code.
     45 */
     46static usb_address_t usb_device_manager_get_free_address(
     47    usb_device_manager_t *instance)
     48{
     49
     50        usb_address_t new_address = instance->last_address;
     51        do {
     52                new_address = (new_address + 1) % USB_ADDRESS_COUNT;
     53                if (new_address == USB_ADDRESS_DEFAULT)
     54                        new_address = 1;
     55                if (new_address == instance->last_address) {
     56                        return ENOSPC;
     57                }
     58        } while (instance->devices[new_address].occupied);
     59
     60        assert(new_address != USB_ADDRESS_DEFAULT);
     61        instance->last_address = new_address;
     62
     63        return new_address;
     64}
     65/*----------------------------------------------------------------------------*/
    4066/** Initialize device manager structure.
    4167 *
    4268 * @param[in] instance Memory place to initialize.
     69 * @param[in] max_speed Maximum allowed USB speed of devices (inclusive).
    4370 *
    4471 * Set all values to false/0.
    4572 */
    46 void usb_device_manager_init(usb_device_manager_t *instance)
     73void usb_device_manager_init(
     74    usb_device_manager_t *instance, usb_speed_t max_speed)
    4775{
    4876        assert(instance);
     
    5280                instance->devices[i].speed = USB_SPEED_MAX;
    5381        }
    54         // TODO: is this hack enough?
    55         // (it is needed to allow smooth registration at default address)
    56         instance->devices[0].occupied = true;
    57         instance->last_address = 0;
     82        instance->last_address = 1;
     83        instance->max_speed = max_speed;
    5884        fibril_mutex_initialize(&instance->guard);
    5985}
    6086/*----------------------------------------------------------------------------*/
    61 /** Get a free USB address
    62  *
    63  * @param[in] instance Device manager structure to use.
    64  * @param[in] speed Speed of the device requiring address.
    65  * @return Free address, or error code.
    66  */
    67 usb_address_t usb_device_manager_get_free_address(
    68     usb_device_manager_t *instance, usb_speed_t speed)
    69 {
    70         assert(instance);
    71         fibril_mutex_lock(&instance->guard);
    72 
    73         usb_address_t new_address = instance->last_address;
    74         do {
    75                 ++new_address;
    76                 if (new_address > USB11_ADDRESS_MAX)
    77                         new_address = 1; // NOTE it should be safe to put 0 here
    78                                          // TODO Use mod
    79                 if (new_address == instance->last_address) {
     87/** Request USB address.
     88 * @param instance usb_device_manager
     89 * @param address Pointer to requested address value, place to store new address
     90 * @parma strict Fail if the requested address is not available.
     91 * @return Error code.
     92 * @note Default address is only available in strict mode.
     93 */
     94int usb_device_manager_request_address(usb_device_manager_t *instance,
     95    usb_address_t *address, bool strict, usb_speed_t speed)
     96{
     97        assert(instance);
     98        assert(address);
     99        if (speed > instance->max_speed)
     100                return ENOTSUP;
     101
     102        if ((*address) < 0 || (*address) >= USB_ADDRESS_COUNT)
     103                return EINVAL;
     104
     105        fibril_mutex_lock(&instance->guard);
     106        /* Only grant default address to strict requests */
     107        if (( (*address) == USB_ADDRESS_DEFAULT) && !strict) {
     108                *address = instance->last_address;
     109        }
     110
     111        if (instance->devices[*address].occupied) {
     112                if (strict) {
    80113                        fibril_mutex_unlock(&instance->guard);
    81                         return ENOSPC;
     114                        return ENOENT;
    82115                }
    83         } while (instance->devices[new_address].occupied);
    84 
    85         assert(new_address != USB_ADDRESS_DEFAULT);
    86         assert(instance->devices[new_address].occupied == false);
    87         assert(instance->devices[new_address].handle == 0);
    88 
    89         instance->devices[new_address].occupied = true;
    90         instance->devices[new_address].speed = speed;
    91         instance->last_address = new_address;
    92 
    93         fibril_mutex_unlock(&instance->guard);
    94         return new_address;
     116                *address = usb_device_manager_get_free_address(instance);
     117        }
     118        assert(instance->devices[*address].occupied == false);
     119        assert(instance->devices[*address].handle == 0);
     120        assert(*address != USB_ADDRESS_DEFAULT || strict);
     121
     122        instance->devices[*address].occupied = true;
     123        instance->devices[*address].speed = speed;
     124
     125        fibril_mutex_unlock(&instance->guard);
     126        return EOK;
    95127}
    96128/*----------------------------------------------------------------------------*/
     
    102134 * @return Error code.
    103135 */
    104 int usb_device_manager_bind(usb_device_manager_t *instance,
     136int usb_device_manager_bind_address(usb_device_manager_t *instance,
    105137    usb_address_t address, devman_handle_t handle)
    106138{
     
    132164 * @return Error code.
    133165 */
    134 int usb_device_manager_release(
     166int usb_device_manager_release_address(
    135167    usb_device_manager_t *instance, usb_address_t address)
    136168{
    137         if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) {
     169        if ((address < 0) || (address >= USB_ADDRESS_COUNT)) {
    138170                return EINVAL;
    139171        }
     
    188220{
    189221        assert(instance);
    190         if ((address <= 0) || (address >= USB_ADDRESS_COUNT)) {
     222        if ((address < 0) || (address >= USB_ADDRESS_COUNT)) {
    191223                return EINVAL;
    192224        }
  • uspace/lib/usbhost/src/usb_endpoint_manager.c

    r2e1b9dc r747ef72  
    384384        return EOK;
    385385}
     386/*----------------------------------------------------------------------------*/
     387void usb_endpoint_manager_remove_address(usb_endpoint_manager_t *instance,
     388    usb_address_t address, void (*callback)(endpoint_t *, void *), void *arg)
     389{
     390        assert(address >= 0);
     391        assert(instance);
     392        fibril_mutex_lock(&instance->guard);
     393        list_foreach(*get_list(instance, address), iterator) {
     394                endpoint_t *ep = endpoint_get_instance(iterator);
     395                if (ep->address == address) {
     396                        iterator = iterator->next;
     397                        list_remove(&ep->link);
     398                        if (callback)
     399                                callback(ep, arg);
     400                        endpoint_destroy(ep);
     401                }
     402        }
     403        fibril_mutex_unlock(&instance->guard);
     404}
Note: See TracChangeset for help on using the changeset viewer.