mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Revision:
1:9db0e321a9f4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/drivers/internal/USBDevice.h	Tue Dec 31 06:02:27 2019 +0000
@@ -0,0 +1,623 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited and affiliates.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef USBDEVICE_H
+#define USBDEVICE_H
+
+#include <stddef.h>
+#include "USBDevice_Types.h"
+#include "USBPhy.h"
+#include "mbed_critical.h"
+#include "Callback.h"
+
+/**
+ * \defgroup drivers_USBDevice USBDevice class
+ * \ingroup drivers-internal-api-usb
+ * @{
+ */
+
+/**
+ * Core USB Device driver
+ *
+ * USB driver which wraps and provides synchronization for a USBPhy object.
+ */
+class USBDevice: public  USBPhyEvents {
+public:
+    typedef void (USBDevice::*ep_cb_t)();
+
+    enum RequestResult {
+        Receive = 0,
+        Send = 1,
+        Success = 2,
+        Failure = 3,
+        PassThrough = 4,
+    };
+
+    enum DeviceState {
+        Attached,
+        Powered,
+        Default,
+        Address,
+        Configured
+    };
+
+    struct setup_packet_t {
+        struct {
+            uint8_t dataTransferDirection;
+            uint8_t Type;
+            uint8_t Recipient;
+        } bmRequestType;
+        uint8_t  bRequest;
+        uint16_t wValue;
+        uint16_t wIndex;
+        uint16_t wLength;
+    };
+
+    /**
+     * Instantiate a new USBDevice with the given parameters
+     *
+     * @param phy The USBPhy providing physical USB access
+     * @param vendor_id The USB vendor ID
+     * @param product_id The USB product ID
+     * @param product_release The device release number
+     */
+    USBDevice(USBPhy *phy, uint16_t vendor_id, uint16_t product_id, uint16_t product_release);
+
+    /**
+     * Cleanup this USBDevice
+     *
+     * This USBDevice must be uninitialized when the destructor is
+     * called or the behavior is undefined.
+     */
+    virtual ~USBDevice();
+
+    /**
+     * Initialize this instance
+     *
+     * This function must be called before calling
+     * any other functions of this class, unless specifically
+     */
+    void init();
+
+    /**
+     * Power down this instance
+     *
+     * Disable interrupts and stop sending events.
+     * This method can be used for temporary power-saving; This call can allow
+     * USB to be temporarily disabled to permit power saving.
+     * However, it is up to the user to make sure all the
+     * transfers have concluded (for example when USB power is lost).
+     * USBDevice::connect can be used to resume USB operation.
+     */
+    void deinit();
+
+    /**
+    * Check if the device is configured
+    *
+    * @returns true if configured, false otherwise
+    */
+    bool configured();
+
+    /**
+    * Connect a device
+    * This method can also be used to resume USB operation when USB power is
+    * detected after it was suspended via USBDevice::deinit.
+    */
+    void connect();
+
+    /**
+    * Disconnect a device
+    */
+    void disconnect();
+
+    /**
+     * Enable the start of frame interrupt
+     *
+     * Call USBDevice::callback_sof on every frame.
+     */
+    void sof_enable();
+
+    /**
+     * Disable the start of frame interrupt
+     *
+     * Stop calling USBDevice::callback_sof.
+     */
+    void sof_disable();
+
+    /**
+    * Add an endpoint
+    *
+    * @param endpoint Endpoint to enable
+    * @param max_packet Maximum size of a packet which can be sent or received on this endpoint
+    * @param type Endpoint type - USB_EP_TYPE_BULK, USB_EP_TYPE_INT or USB_EP_TYPE_ISO
+    * @param callback Method pointer to be called when a packet is transferred
+    * @returns true if successful, false otherwise
+    */
+    bool endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type, mbed::Callback<void()> callback = NULL);
+
+    /**
+    * Add an endpoint
+    *
+    * @param endpoint Endpoint to enable
+    * @param max_packet Maximum size of a packet which can be sent or received on this endpoint
+    * @param type Endpoint type - USB_EP_TYPE_BULK, USB_EP_TYPE_INT or USB_EP_TYPE_ISO
+    * @param callback Method pointer to be called when a packet is transferred
+    * @returns true if successful, false otherwise
+    */
+    template<typename T>
+    bool endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type, void (T::*callback)())
+    {
+        return endpoint_add(endpoint, max_packet, type, mbed::callback(this, static_cast<ep_cb_t>(callback)));
+    }
+
+    /**
+    * Remove an endpoint
+    *
+    * @param endpoint Endpoint to disable
+    * @note This endpoint must already have been setup with endpoint_add
+    */
+    void endpoint_remove(usb_ep_t endpoint);
+
+    /**
+    * Remove all non-zero endpoints
+    */
+    void endpoint_remove_all();
+
+    /**
+    * Stall an endpoint
+    *
+    * If there is an ongoing transfer on this endpoint then it will
+    * be aborted.
+    *
+    * @param endpoint Endpoint to stall
+    * @note You cannot stall endpoint 0 with this function
+    * @note This endpoint must already have been setup with endpoint_add
+    */
+    void endpoint_stall(usb_ep_t endpoint);
+
+    /**
+    * Un-stall an endpoint
+    *
+    * Un-stalling an endpoint resets data toggle back to DATA0.
+    * Additionally, if there is an ongoing transfer on this endpoint
+    * it will be aborted.
+    *
+    * @param endpoint Endpoint to un-stall
+    * @note This endpoint must already have been setup with endpoint_add
+    */
+    void endpoint_unstall(usb_ep_t endpoint);
+
+    /**
+     * Get the current maximum size for this endpoint
+     *
+     * Return the currently configured maximum packet size, wMaxPacketSize,
+     * for this endpoint.
+     * @note This endpoint must already have been setup with endpoint_add
+     */
+    uint32_t endpoint_max_packet_size(usb_ep_t endpoint);
+
+    /**
+     * Abort the current transfer on this endpoint
+     *
+     * @param endpoint endpoint with transfer to abort
+     * @note This endpoint must already have been setup with endpoint_add
+     */
+    void endpoint_abort(usb_ep_t endpoint);
+
+    /**
+     * start a read on the given endpoint
+     *
+     * Start a read on the given endpoint. The data buffer must remain
+     * unchanged until the transfer either completes or is aborted.
+     *
+     * @param endpoint endpoint to read data from
+     * @param buffer buffer to fill with read data
+     * @param size The size of data to read. This must be greater than or equal
+     *        to the max packet size for this endpoint
+     * @return true if the read was completed, otherwise false
+     * @note This endpoint must already have been setup with endpoint_add
+     */
+    bool read_start(usb_ep_t endpoint, uint8_t *buffer, uint32_t size);
+
+    /**
+     * Get the status of a read
+     *
+     * @param endpoint endpoint to get the status of
+     * @return number of bytes read by this endpoint
+     */
+    uint32_t read_finish(usb_ep_t endpoint);
+
+    /**
+     * Write a data to the given endpoint
+     *
+     * Write data to an endpoint. The data sent must remain unchanged until
+     * the transfer either completes or is aborted.
+     *
+     * @param endpoint endpoint to write data to
+     * @param buffer data to write
+     * @param size the size of data to send. This must be less than or equal to the
+     * max packet size of this endpoint
+     * @note This endpoint must already have been setup with endpoint_add
+     */
+    bool write_start(usb_ep_t endpoint, uint8_t *buffer, uint32_t size);
+
+    /**
+     * Get the status of a write
+     *
+     * @param endpoint endpoint to get the status of
+     * @return number of bytes sent by this endpoint
+     */
+    uint32_t write_finish(usb_ep_t endpoint);
+
+    /*
+    * Get device descriptor.
+    *
+    * @returns pointer to the device descriptor
+    */
+    virtual const uint8_t *device_desc();
+
+    /*
+    * Get configuration descriptor
+    *
+    * @param index descriptor index
+    * @returns pointer to the configuration descriptor
+    */
+    virtual const uint8_t *configuration_desc(uint8_t index) = 0;
+
+    /*
+    * Get string lang id descriptor
+    *
+    * @return pointer to the string lang id descriptor
+    */
+    virtual const uint8_t *string_langid_desc();
+
+    /*
+    * Get string manufacturer descriptor
+    *
+    * @returns pointer to the string manufacturer descriptor
+    */
+    virtual const uint8_t *string_imanufacturer_desc();
+
+    /*
+    * Get string product descriptor
+    *
+    * @returns pointer to the string product descriptor
+    */
+    virtual const uint8_t *string_iproduct_desc();
+
+    /*
+    * Get string serial descriptor
+    *
+    * @returns pointer to the string serial descriptor
+    */
+    virtual const uint8_t *string_iserial_desc();
+
+    /*
+    * Get string configuration descriptor
+    *
+    * @returns pointer to the string configuration descriptor
+    */
+    virtual const uint8_t *string_iconfiguration_desc();
+
+    /*
+    * Get string interface descriptor
+    *
+    * @returns pointer to the string interface descriptor
+    */
+    virtual const uint8_t *string_iinterface_desc();
+
+    /*
+    * Get the length of the report descriptor
+    *
+    * @returns length of the report descriptor
+    */
+    virtual uint16_t report_desc_dength()
+    {
+        return 0;
+    };
+
+protected:
+
+    /**
+    * Called by USBDevice layer on power state change.
+    *
+    * @param powered true if device is powered, false otherwise
+    *
+    * Warning: Called in ISR context
+    */
+    virtual void callback_power(bool powered)
+    {
+
+    }
+
+    /**
+    * Called by USBDevice layer on each new USB frame.
+    *
+    * Callbacks are enabled and disabled by calling sof_enable
+    * and sof_disable.
+    *
+    * @param frame_number The current frame number
+    *
+    * Warning: Called in ISR context
+    */
+    virtual void callback_sof(int frame_number)
+    {
+
+    }
+
+    /**
+    * Called by USBDevice layer on bus reset.
+    *
+    * complete_reset must be called after
+    * the device is fully reset.
+    *
+    * Warning: Called in ISR context
+    */
+    virtual void callback_reset()
+    {
+
+    }
+
+    /**
+    * Called when USB changes state
+    *
+    * @param new_state The new state of the USBDevice
+    *
+    * Warning: Called in ISR context
+    */
+    virtual void callback_state_change(DeviceState new_state) = 0;
+
+    /**
+    * Called by USBDevice on Endpoint0 request.
+    *
+    * This is used to handle extensions to standard requests
+    * and class specific requests. The function complete_request
+    * must be always be called in response to this callback.
+    *
+    * Warning: Called in ISR context
+    */
+    virtual void callback_request(const setup_packet_t *setup) = 0;
+
+    /**
+     * Called to complete the setup stage of a callback request
+     *
+     * Possible options that can be passed as a result are:
+     * - Receive - Start the data OUT phase of this control transfer
+     * - Send - Start the data IN phase of this control transfer
+     * - Success - Operation was a success so start the status phase
+     * - Failure - Operation failed or is unsupported so send a stall
+     * - PassThrough - Pass on the request for standard processing
+     *
+     * @param result The result of the setup phase.
+     * @param data Buffer to send or receive if the result is Send or Receive
+     * @param size Size to transfer if the result is Send or Receive
+     */
+    void complete_request(RequestResult result, uint8_t *data = NULL, uint32_t size = 0);
+
+    /**
+    * Called by USBDevice on data stage completion
+    *
+    * The function complete_request_xfer_done must be always be called
+    * in response to this callback.
+    *
+    * @param setup Setup packet of the current request
+    * @param aborted false if the operation was aborted, true otherwise
+    *
+    * Warning: Called in ISR context
+    */
+    virtual void callback_request_xfer_done(const setup_packet_t *setup, bool aborted) = 0;
+
+    /**
+     * Called to complete the data stage of a callback request
+     *
+     * @param success true if the operation was successful, false otherwise
+     */
+    void complete_request_xfer_done(bool success);
+
+    /*
+    * Called by USBDevice layer in response to set_configuration.
+    *
+    * Upon reception of this command endpoints of the previous configuration
+    * if any must be removed with endpoint_remove and new endpoint added with
+    * endpoint_add.
+    *
+    * @param configuration Number of the configuration
+    *
+    * Warning: Called in ISR context
+    */
+    virtual void callback_set_configuration(uint8_t configuration) = 0;
+
+    /**
+     * Called to complete a set configuration command
+     *
+     * @param success true if the configuration was set, false otherwise
+     */
+    void complete_set_configuration(bool success);
+
+    /*
+    * Called by USBDevice layer in response to set_interface.
+    *
+    * Upon reception of this command endpoints of any previous interface
+    * if any must be removed with endpoint_remove and new endpoint added with
+    * endpoint_add.
+    *
+    * @param configuration Number of the configuration
+    *
+    * Warning: Called in ISR context
+    */
+    virtual void callback_set_interface(uint16_t interface, uint8_t alternate) = 0;
+
+    /**
+     * Called to complete a set interface command
+     *
+     * @param success true if the interface was set, false otherwise
+     */
+    void complete_set_interface(bool success);
+
+    /**
+     * Find a descriptor type inside the configuration descriptor
+     *
+     * @param descriptor_type Type of descriptor to find
+     * @param index Configuration descriptor index ( 0 if only one configuration present )
+     * @return A descriptor of the given type or NULL if none were found
+     */
+    uint8_t *find_descriptor(uint8_t descriptor_type, uint8_t index = 0);
+
+    /**
+     * Get the endpoint table of this device
+     *
+     * @return Endpoint table of the USBPhy attached to this USBDevice
+     */
+    const usb_ep_table_t *endpoint_table();
+
+    /**
+     * Callback called to indicate the USB processing needs to be done
+     */
+    virtual void start_process();
+
+    /**
+     * Acquire exclusive access to this instance USBDevice
+     */
+    virtual void lock();
+
+    /**
+     * Release exclusive access to this instance USBDevice
+     */
+    virtual void unlock();
+
+    /**
+     * Assert that the current thread of execution holds the lock
+     *
+     */
+    virtual void assert_locked();
+
+    uint16_t vendor_id;
+    uint16_t product_id;
+    uint16_t product_release;
+    uint8_t device_descriptor[18];
+
+private:
+    // USBPhyEvents
+    virtual void power(bool powered);
+    virtual void suspend(bool suspended);
+    virtual void sof(int frame_number);
+    virtual void reset();
+    virtual void ep0_setup();
+    virtual void ep0_out();
+    virtual void ep0_in();
+    virtual void out(usb_ep_t endpoint);
+    virtual void in(usb_ep_t endpoint);
+
+    bool _request_get_descriptor();
+    bool _control_out();
+    bool _control_in();
+    bool _request_set_address();
+    bool _request_set_configuration();
+    bool _request_set_feature();
+    bool _request_clear_feature();
+    bool _request_get_status();
+    bool _request_setup();
+    void _control_setup();
+    void _control_abort();
+    void _control_abort_start();
+    void _control_setup_continue();
+    void _decode_setup_packet(uint8_t *data, setup_packet_t *packet);
+    bool _request_get_configuration();
+    bool _request_get_interface();
+    bool _request_set_interface();
+    void _change_state(DeviceState state);
+    void _run_later(void (USBDevice::*function)());
+
+    void _complete_request();
+    void _complete_request_xfer_done();
+    void _complete_set_configuration();
+    void _complete_set_interface();
+
+    struct endpoint_info_t {
+        mbed::Callback<void()> callback;
+        uint16_t max_packet_size;
+        uint16_t transfer_size;
+        uint8_t flags;
+        uint8_t pending;
+    };
+
+    struct usb_device_t {
+        volatile DeviceState state;
+        uint8_t configuration;
+        bool suspended;
+    };
+
+    enum ControlState {
+        Setup,
+        DataOut,
+        DataIn,
+        Status
+    };
+
+    enum UserCallback {
+        None,
+        Request,
+        RequestXferDone,
+        SetConfiguration,
+        SetInterface
+    };
+
+    struct complete_request_t {
+        RequestResult result;
+        uint8_t *data;
+        uint32_t size;
+    };
+
+    union complete_args_t {
+        complete_request_t request;
+        bool status;
+    };
+
+    struct control_transfer_t {
+        setup_packet_t setup;
+        uint8_t *ptr;
+        uint32_t remaining;
+        uint8_t direction;
+        bool zlp;
+        bool notify;
+        ControlState stage;
+        UserCallback user_callback;
+        complete_args_t args;
+    };
+
+    endpoint_info_t _endpoint_info[32 - 2];
+
+    USBPhy *_phy;
+    bool _initialized;
+    bool _connected;
+    bool _endpoint_add_remove_allowed;
+    control_transfer_t _transfer;
+    usb_device_t _device;
+    uint32_t _max_packet_size_ep0;
+    void (USBDevice::*_post_process)();
+
+    bool _setup_ready;
+    bool _abort_control;
+
+    uint16_t _current_interface;
+    uint8_t _current_alternate;
+    uint32_t _locked;
+};
+
+/** @}*/
+
+#endif