Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usbdev/src/pipesinit.c

    r3538b0e r365e29e2  
    3131 */
    3232/** @file
    33  * Non trivial initialization of endpoint pipes.
     33 * Initialization of endpoint pipes.
    3434 *
    3535 */
     
    3838#include <usb/dev/dp.h>
    3939#include <usb/dev/request.h>
     40#include <usbhc_iface.h>
    4041#include <errno.h>
    4142#include <assert.h>
    4243
     44#define CTRL_PIPE_MIN_PACKET_SIZE 8
    4345#define DEV_DESCR_MAX_PACKET_SIZE_OFFSET 7
     46
    4447
    4548#define NESTING(parentname, childname) \
     
    5154
    5255/** Nesting pairs of standard descriptors. */
    53 static const usb_dp_descriptor_nesting_t descriptor_nesting[] = {
     56static usb_dp_descriptor_nesting_t descriptor_nesting[] = {
    5457        NESTING(CONFIGURATION, INTERFACE),
    5558        NESTING(INTERFACE, ENDPOINT),
     
    6568 * @return Whether the given descriptor is endpoint descriptor.
    6669 */
    67 static inline bool is_endpoint_descriptor(const uint8_t *descriptor)
     70static inline bool is_endpoint_descriptor(uint8_t *descriptor)
    6871{
    6972        return descriptor[1] == USB_DESCTYPE_ENDPOINT;
     
    7780 */
    7881static bool endpoint_fits_description(const usb_endpoint_description_t *wanted,
    79     const usb_endpoint_description_t *found)
     82    usb_endpoint_description_t *found)
    8083{
    8184#define _SAME(fieldname) ((wanted->fieldname) == (found->fieldname))
     
    117120static usb_endpoint_mapping_t *find_endpoint_mapping(
    118121    usb_endpoint_mapping_t *mapping, size_t mapping_count,
    119     const usb_endpoint_description_t *found_endpoint,
     122    usb_endpoint_description_t *found_endpoint,
    120123    int interface_number, int interface_setting)
    121124{
     
    157160    usb_device_connection_t *wire)
    158161{
     162        usb_endpoint_description_t description;
    159163
    160164        /*
     
    163167
    164168        /* Actual endpoint number is in bits 0..3 */
    165         const usb_endpoint_t ep_no = endpoint->endpoint_address & 0x0F;
    166 
    167         const usb_endpoint_description_t description = {
    168                 /* Endpoint direction is set by bit 7 */
    169                 .direction = (endpoint->endpoint_address & 128)
    170                     ? USB_DIRECTION_IN : USB_DIRECTION_OUT,
    171                 /* Transfer type is in bits 0..2 and
    172                  * the enum values corresponds 1:1 */
    173                 .transfer_type = endpoint->attributes & 3,
    174 
    175                 /* Get interface characteristics. */
    176                 .interface_class = interface->interface_class,
    177                 .interface_subclass = interface->interface_subclass,
    178                 .interface_protocol = interface->interface_protocol,
    179         };
     169        usb_endpoint_t ep_no = endpoint->endpoint_address & 0x0F;
     170
     171        /* Endpoint direction is set by bit 7 */
     172        description.direction = (endpoint->endpoint_address & 128)
     173            ? USB_DIRECTION_IN : USB_DIRECTION_OUT;
     174        /* Transfer type is in bits 0..2 and the enum values corresponds 1:1 */
     175        description.transfer_type = endpoint->attributes & 3;
     176
     177        /*
     178         * Get interface characteristics.
     179         */
     180        description.interface_class = interface->interface_class;
     181        description.interface_subclass = interface->interface_subclass;
     182        description.interface_protocol = interface->interface_protocol;
    180183
    181184        /*
     
    189192        }
    190193
     194        if (ep_mapping->pipe == NULL) {
     195                return EBADMEM;
     196        }
    191197        if (ep_mapping->present) {
    192198                return EEXISTS;
    193199        }
    194200
    195         int rc = usb_pipe_initialize(&ep_mapping->pipe, wire,
     201        int rc = usb_pipe_initialize(ep_mapping->pipe, wire,
    196202            ep_no, description.transfer_type, endpoint->max_packet_size,
    197203            description.direction);
     
    218224static int process_interface(
    219225    usb_endpoint_mapping_t *mapping, size_t mapping_count,
    220     const usb_dp_parser_t *parser, const usb_dp_parser_data_t *parser_data,
    221     const uint8_t *interface_descriptor)
    222 {
    223         const uint8_t *descriptor = usb_dp_get_nested_descriptor(parser,
     226    usb_dp_parser_t *parser, usb_dp_parser_data_t *parser_data,
     227    uint8_t *interface_descriptor)
     228{
     229        uint8_t *descriptor = usb_dp_get_nested_descriptor(parser,
    224230            parser_data, interface_descriptor);
    225231
     
    248254 *
    249255 * The mapping array is expected to conform to following rules:
    250  * - @c pipe must be uninitialized pipe
     256 * - @c pipe must point to already allocated structure with uninitialized pipe
    251257 * - @c description must point to prepared endpoint description
    252258 * - @c descriptor does not need to be initialized (will be overwritten)
     
    278284int usb_pipe_initialize_from_configuration(
    279285    usb_endpoint_mapping_t *mapping, size_t mapping_count,
    280     const uint8_t *config_descriptor, size_t config_descriptor_size,
     286    uint8_t *configuration_descriptor, size_t configuration_descriptor_size,
    281287    usb_device_connection_t *connection)
    282288{
    283289        assert(connection);
    284290
    285         if (config_descriptor == NULL) {
     291        if (configuration_descriptor == NULL) {
    286292                return EBADMEM;
    287293        }
    288         if (config_descriptor_size
     294        if (configuration_descriptor_size
    289295            < sizeof(usb_standard_configuration_descriptor_t)) {
    290296                return ERANGE;
    291297        }
    292298
    293         /* Go through the mapping and set all endpoints to not present. */
    294         for (size_t i = 0; i < mapping_count; i++) {
     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++) {
    295304                mapping[i].present = false;
    296305                mapping[i].descriptor = NULL;
     
    298307        }
    299308
    300         /* Prepare the descriptor parser. */
    301         const usb_dp_parser_t dp_parser = {
     309        /*
     310         * Prepare the descriptor parser.
     311         */
     312        usb_dp_parser_t dp_parser = {
    302313                .nesting = descriptor_nesting
    303314        };
    304         const usb_dp_parser_data_t dp_data = {
    305                 .data = config_descriptor,
    306                 .size = config_descriptor_size,
     315        usb_dp_parser_data_t dp_data = {
     316                .data = configuration_descriptor,
     317                .size = configuration_descriptor_size,
    307318                .arg = connection
    308319        };
     
    311322         * Iterate through all interfaces.
    312323         */
    313         const uint8_t *interface = usb_dp_get_nested_descriptor(&dp_parser,
    314             &dp_data, config_descriptor);
     324        uint8_t *interface = usb_dp_get_nested_descriptor(&dp_parser,
     325            &dp_data, configuration_descriptor);
    315326        if (interface == NULL) {
    316327                return ENOENT;
     
    318329        do {
    319330                (void) process_interface(mapping, mapping_count,
    320                     &dp_parser, &dp_data, interface);
     331                    &dp_parser, &dp_data,
     332                    interface);
    321333                interface = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
    322                     config_descriptor, interface);
     334                    configuration_descriptor, interface);
    323335        } while (interface != NULL);
    324336
    325337        return EOK;
     338}
     339
     340/** Initialize USB endpoint pipe.
     341 *
     342 * @param pipe Endpoint pipe to be initialized.
     343 * @param connection Connection to the USB device backing this pipe (the wire).
     344 * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15).
     345 * @param transfer_type Transfer type (e.g. interrupt or bulk).
     346 * @param max_packet_size Maximum packet size in bytes.
     347 * @param direction Endpoint direction (in/out).
     348 * @return Error code.
     349 */
     350int usb_pipe_initialize(usb_pipe_t *pipe,
     351    usb_device_connection_t *connection, usb_endpoint_t endpoint_no,
     352    usb_transfer_type_t transfer_type, size_t max_packet_size,
     353    usb_direction_t direction)
     354{
     355        assert(pipe);
     356        assert(connection);
     357
     358        fibril_mutex_initialize(&pipe->guard);
     359        pipe->wire = connection;
     360        pipe->hc_sess = NULL;
     361        fibril_mutex_initialize(&pipe->hc_sess_mutex);
     362        pipe->endpoint_no = endpoint_no;
     363        pipe->transfer_type = transfer_type;
     364        pipe->max_packet_size = max_packet_size;
     365        pipe->direction = direction;
     366        pipe->refcount = 0;
     367        pipe->refcount_soft = 0;
     368        pipe->auto_reset_halt = false;
     369
     370        return EOK;
     371}
     372
     373
     374/** Initialize USB endpoint pipe as the default zero control pipe.
     375 *
     376 * @param pipe Endpoint pipe to be initialized.
     377 * @param connection Connection to the USB device backing this pipe (the wire).
     378 * @return Error code.
     379 */
     380int usb_pipe_initialize_default_control(usb_pipe_t *pipe,
     381    usb_device_connection_t *connection)
     382{
     383        assert(pipe);
     384        assert(connection);
     385
     386        int rc = usb_pipe_initialize(pipe, connection,
     387            0, USB_TRANSFER_CONTROL, CTRL_PIPE_MIN_PACKET_SIZE,
     388            USB_DIRECTION_BOTH);
     389
     390        pipe->auto_reset_halt = true;
     391
     392        return rc;
    326393}
    327394
     
    347414        }
    348415
     416#define TRY_LOOP(attempt_var) \
     417        for (attempt_var = 0; attempt_var < 3; attempt_var++)
     418
     419        size_t failed_attempts;
     420        int rc;
    349421
    350422        usb_pipe_start_long_transfer(pipe);
     
    352424        uint8_t dev_descr_start[CTRL_PIPE_MIN_PACKET_SIZE];
    353425        size_t transferred_size;
    354         int rc;
    355         for (size_t attempt_var = 0; attempt_var < 3; ++attempt_var) {
     426        TRY_LOOP(failed_attempts) {
    356427                rc = usb_request_get_descriptor(pipe, USB_REQUEST_TYPE_STANDARD,
    357428                    USB_REQUEST_RECIPIENT_DEVICE, USB_DESCTYPE_DEVICE,
     
    377448}
    378449
     450/** Register endpoint with the host controller.
     451 *
     452 * @param pipe Pipe to be registered.
     453 * @param interval Polling interval.
     454 * @param hc_connection Connection to the host controller (must be opened).
     455 * @return Error code.
     456 */
     457int usb_pipe_register(usb_pipe_t *pipe,
     458    unsigned int interval,
     459    usb_hc_connection_t *hc_connection)
     460{
     461        return usb_pipe_register_with_speed(pipe, USB_SPEED_MAX + 1,
     462            interval, hc_connection);
     463}
     464
     465/** Register endpoint with a speed at the host controller.
     466 *
     467 * You will rarely need to use this function because it is needed only
     468 * if the registered endpoint is of address 0 and there is no other way
     469 * to tell speed of the device at address 0.
     470 *
     471 * @param pipe Pipe to be registered.
     472 * @param speed Speed of the device
     473 *      (invalid speed means use previously specified one).
     474 * @param interval Polling interval.
     475 * @param hc_connection Connection to the host controller (must be opened).
     476 * @return Error code.
     477 */
     478int usb_pipe_register_with_speed(usb_pipe_t *pipe, usb_speed_t speed,
     479    unsigned int interval,
     480    usb_hc_connection_t *hc_connection)
     481{
     482        assert(pipe);
     483        assert(hc_connection);
     484       
     485        if (!usb_hc_connection_is_opened(hc_connection))
     486                return EBADF;
     487       
     488        const usb_target_t target =
     489            {{ .address = pipe->wire->address, .endpoint = pipe->endpoint_no }};
     490#define _PACK2(high, low) (((high) << 16) + (low))
     491#define _PACK3(high, middle, low) (((((high) << 8) + (middle)) << 8) + (low))
     492       
     493        async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
     494        int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     495            IPC_M_USBHC_REGISTER_ENDPOINT, target.packed,
     496            _PACK3(speed, pipe->transfer_type, pipe->direction),
     497            _PACK2(pipe->max_packet_size, interval));
     498        async_exchange_end(exch);
     499       
     500#undef _PACK2
     501#undef _PACK3
     502       
     503        return rc;
     504}
     505
     506/** Revert endpoint registration with the host controller.
     507 *
     508 * @param pipe Pipe to be unregistered.
     509 * @param hc_connection Connection to the host controller (must be opened).
     510 * @return Error code.
     511 */
     512int usb_pipe_unregister(usb_pipe_t *pipe,
     513    usb_hc_connection_t *hc_connection)
     514{
     515        assert(pipe);
     516        assert(hc_connection);
     517       
     518        if (!usb_hc_connection_is_opened(hc_connection))
     519                return EBADF;
     520       
     521        async_exch_t *exch = async_exchange_begin(hc_connection->hc_sess);
     522        int rc = async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
     523            IPC_M_USBHC_UNREGISTER_ENDPOINT,
     524            pipe->wire->address, pipe->endpoint_no, pipe->direction);
     525        async_exchange_end(exch);
     526       
     527        return rc;
     528}
     529
    379530/**
    380531 * @}
Note: See TracChangeset for help on using the changeset viewer.