HelenOS sources

root/uspace/lib/usbhost/include/usb/host/bus.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


/*
 * Copyright (c) 2018 Ondrej Hlavaty, Petr Manek
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 * - The name of the author may not be used to endorse or promote products
 *   derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/** @addtogroup libusbhost
 * @{
 */
/** @file
 * Virtual base for usb bus implementations.
 *
 * The purpose of this structure is to keep information about connected devices
 * and endpoints, manage available bandwidth and the toggle bit flipping.
 *
 * The generic implementation is provided for USB 1 and 2 in usb2_bus.c. Some
 * details in [OUE]HCI are solved through overriding some functions. XHCI does
 * not need the bookkeeping functionality, because addresses are managed by HC
 * itself.
 */
#ifndef LIBUSBHOST_HOST_BUS_H
#define LIBUSBHOST_HOST_BUS_H

#include <assert.h>
#include <fibril_synch.h>
#include <stdbool.h>
#include <usb/host/hcd.h>
#include <usb/request.h>
#include <usb/usb.h>
#include <usbhc_iface.h>

typedef struct hcd hcd_t;
typedef struct endpoint endpoint_t;
typedef struct bus bus_t;
typedef struct ddf_fun ddf_fun_t;
typedef struct usb_transfer_batch usb_transfer_batch_t;

typedef struct device {
        /* Device tree keeping */
        link_t link;
        list_t devices;
        fibril_mutex_t guard;

        /* Associated DDF function, if any */
        ddf_fun_t *fun;

        /* Invalid for the roothub device */
        unsigned port;

        /** Hub under which this device is connected */
        struct device *hub;

        /** USB Tier of the device */
        uint8_t tier;

        /* Transaction translator */
        struct {
                device_t *dev;
                unsigned port;
        } tt;

        /* The following are not set by the library */
        usb_speed_t speed;
        usb_address_t address;
        endpoint_t *endpoints [USB_ENDPOINT_COUNT];

        /* Managing bus */
        bus_t *bus;

        /** True if the device can add new endpoints and schedule transfers. */
        volatile bool online;

        /* This structure is meant to be extended by overriding. */
} device_t;

typedef struct bus_ops bus_ops_t;

/**
 * Operations structure serving as an interface of hc driver for the library
 * (and the rest of the system).
 */
struct bus_ops {
        /* Global operations on the bus */
        void (*interrupt)(bus_t *, uint32_t);
        int (*status)(bus_t *, uint32_t *);

        /* Operations on device */
        int (*device_enumerate)(device_t *);
        void (*device_gone)(device_t *);
        int (*device_online)(device_t *);                       /**< Optional */
        void (*device_offline)(device_t *);                     /**< Optional */
        endpoint_t *(*endpoint_create)(device_t *,
            const usb_endpoint_descriptors_t *);

        /* Operations on endpoint */
        int (*endpoint_register)(endpoint_t *);
        void (*endpoint_unregister)(endpoint_t *);
        void (*endpoint_destroy)(endpoint_t *);                 /**< Optional */
        usb_transfer_batch_t *(*batch_create)(endpoint_t *);    /**< Optional */

        /* Operations on batch */
        int (*batch_schedule)(usb_transfer_batch_t *);
        void (*batch_destroy)(usb_transfer_batch_t *);          /**< Optional */
};

/** Endpoint management structure */
typedef struct bus {
        /* Synchronization of ops */
        fibril_mutex_t guard;

        /* Size of the device_t extended structure */
        size_t device_size;

        /* Do not call directly, ops are synchronized. */
        const bus_ops_t *ops;

        /* Reserving default address */
        device_t *default_address_owner;
        fibril_condvar_t default_address_cv;

        /* This structure is meant to be extended by overriding. */
} bus_t;

void bus_init(bus_t *, size_t);
int bus_device_init(device_t *, bus_t *);

int bus_device_set_default_name(device_t *);

int bus_device_enumerate(device_t *);
void bus_device_gone(device_t *);

int bus_device_online(device_t *);
int bus_device_offline(device_t *);

/**
 * A proforma to USB transfer batch. As opposed to transfer batch, which is
 * supposed to be a dynamic structrure, this one is static and descriptive only.
 * Its fields are copied to the final batch.
 */
typedef struct transfer_request {
        usb_target_t target;
        usb_direction_t dir;

        dma_buffer_t buffer;
        size_t offset, size;
        uint64_t setup;

        usbhc_iface_transfer_callback_t on_complete;
        void *arg;

        const char *name;
} transfer_request_t;

int bus_issue_transfer(device_t *, const transfer_request_t *);

errno_t bus_device_send_batch_sync(device_t *, usb_target_t,
    usb_direction_t direction, char *, size_t, uint64_t,
    const char *, size_t *);

int bus_endpoint_add(device_t *, const usb_endpoint_descriptors_t *, endpoint_t **);
endpoint_t *bus_find_endpoint(device_t *, usb_endpoint_t, usb_direction_t);
int bus_endpoint_remove(endpoint_t *);

int bus_reserve_default_address(bus_t *, device_t *);
void bus_release_default_address(bus_t *, device_t *);

#endif
/**
 * @}
 */

/* [<][>][^][v][top][bottom][index][help] */
HelenOS homepage, sources at GitHub