mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Add USBPhy, USB HAL and Utility class
Add the USBPhy and USBPhyEvents abstract classes, the HAL header using this class and the EndpointResolver utility class.pull/9768/head
							parent
							
								
									e03b3b68c1
								
							
						
					
					
						commit
						8ae123f2d4
					
				| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2018-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include "usb_phy_api.h"
 | 
			
		||||
#include "mbed_error.h"
 | 
			
		||||
 | 
			
		||||
#if !defined(DEVICE_USBDEVICE) || !DEVICE_USBDEVICE
 | 
			
		||||
 | 
			
		||||
USBPhy *get_usb_phy()
 | 
			
		||||
{
 | 
			
		||||
    error("This board does not have a hardware USB driver");
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
 | 
			
		||||
/** \addtogroup hal */
 | 
			
		||||
/** @{*/
 | 
			
		||||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2018-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * 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 MBED_USB_PHY_API_H
 | 
			
		||||
#define MBED_USB_PHY_API_H
 | 
			
		||||
 | 
			
		||||
#include "USBPhy.h"
 | 
			
		||||
 | 
			
		||||
/** Return a the USBPhy instance for this hardware
 | 
			
		||||
 *
 | 
			
		||||
 * For details on adding support for a USBPhy see the specification in USBPhy.h.
 | 
			
		||||
 *
 | 
			
		||||
 * @return A pointer to a USBPhy instance
 | 
			
		||||
 * @note Calling this function on platforms without a USBPhy will result in an
 | 
			
		||||
 * error
 | 
			
		||||
 */
 | 
			
		||||
USBPhy *get_usb_phy();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** @}*/
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,302 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2018-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * 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 USBPHY_H
 | 
			
		||||
#define USBPHY_H
 | 
			
		||||
 | 
			
		||||
#include "USBPhyTypes.h"
 | 
			
		||||
#include "USBPhyEvents.h"
 | 
			
		||||
 | 
			
		||||
/** Abstract interface to physical USB hardware
 | 
			
		||||
 *
 | 
			
		||||
 * # Defined behavior
 | 
			
		||||
 * * Any endpoint configurations which fit in the parameters of the table returned
 | 
			
		||||
 *      by USBPhy::endpoint_table can be used.
 | 
			
		||||
 * * All endpoints in any valid endpoint configuration can be used concurrently
 | 
			
		||||
 * * Device supports use of at least one control, bulk, interrupt and
 | 
			
		||||
 *      isochronous in each direction at the same time - at least 8 endpoints.
 | 
			
		||||
 * * Device supports all standard endpoint sizes (wMaxPacketSize)
 | 
			
		||||
 * * Device can handle an interrupt latency of at least 100ms if reset is not being performed and address is not being set
 | 
			
		||||
 * * USBPhyEvents events are only sent when USBPhy is in the initialized state
 | 
			
		||||
 * * When unpowered only the USBPhyEvents::power event can be sent
 | 
			
		||||
 * * On USB reset all endpoints are removed except for endpoint 0
 | 
			
		||||
 * * USBPhyEvents::out and USBPhyEvents::in events only occur for endpoints which have been added
 | 
			
		||||
 * * A call to USBPhy::ep0_write results in USBPhyEvents::in getting called if not
 | 
			
		||||
 *      interrupted by a power loss or reset
 | 
			
		||||
 * * A call to endpoint_read followed by endpoint_read_result results in USBPhyEvents::out getting called if not
 | 
			
		||||
 *      interrupted by a power loss or reset
 | 
			
		||||
 * * Endpoint 0 naks all transactions aside from setup packets until one
 | 
			
		||||
 *      of ep0_read, ep0_write or ep0_stall has been called
 | 
			
		||||
 * * Endpoint 0 stall is automatically cleared on reception of a setup packet
 | 
			
		||||
 *
 | 
			
		||||
 * # Undefined behavior
 | 
			
		||||
 * * Calling USBPhy::endpoint_add or USBPhy::endpoint_remove outside of the control requests SetInterface or SetConfiguration
 | 
			
		||||
 * * Devices behavior is undefined if latency is greater than 2ms when address is being set - see USB spec 9.2.6.3
 | 
			
		||||
 * * Devices behavior is undefined if latency is greater than 10ms when a reset occurs - see USB spec 7.1.7.5
 | 
			
		||||
 * * Calling any of the USBPhy::endpoint_* functions on endpoint 0
 | 
			
		||||
 *
 | 
			
		||||
 * # Notes
 | 
			
		||||
 * * Make sure USB packets are processed in the correct order when multiple packets are present.
 | 
			
		||||
 *      Typically IN endpoints should be handled before OUT endpoints if both are pending.
 | 
			
		||||
 * * Setup packets may be resent if there is noise on the USB line. The USBPhy should be able
 | 
			
		||||
 *      to gracefully handle this scenario and respond to the setup packet with an ACK.
 | 
			
		||||
 * * Bi-directional protocols making use of alternating IN and OUT phases should not rely
 | 
			
		||||
 *      on the last ACK an IN transfer to indicate that the OUT phase should start. Instead,
 | 
			
		||||
 *      the OUT phase should be started at the same time the last IN transfer is started. This
 | 
			
		||||
 *      is because the ACK to the last in transfer may be dropped if there is noise on the USB
 | 
			
		||||
 *      line. If dropped it will only get re-sent on the next IN phase. More info on this can be
 | 
			
		||||
 *      found in section 8.5.3.3 of the USB spec.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup usb_device_core
 | 
			
		||||
 */
 | 
			
		||||
class USBPhy {
 | 
			
		||||
public:
 | 
			
		||||
    USBPhy() {};
 | 
			
		||||
    virtual ~USBPhy() {};
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initialize this USBPhy instance
 | 
			
		||||
     *
 | 
			
		||||
     * This function must be called before calling
 | 
			
		||||
     * any other functions of this class, unless specifically
 | 
			
		||||
     * noted.
 | 
			
		||||
     *
 | 
			
		||||
     * @param events Callback class to handle USB events
 | 
			
		||||
     */
 | 
			
		||||
    virtual void init(USBPhyEvents *events) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Power down this USBPhy instance
 | 
			
		||||
     *
 | 
			
		||||
     * Disable interrupts and stop sending events.
 | 
			
		||||
     */
 | 
			
		||||
    virtual void deinit() = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if USB power is present
 | 
			
		||||
     *
 | 
			
		||||
     * Devices which don't support checking the USB power state
 | 
			
		||||
     * must always return true.
 | 
			
		||||
     *
 | 
			
		||||
     * @return true if USB power is present, false otherwise
 | 
			
		||||
     */
 | 
			
		||||
    virtual bool powered() = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Make the USB phy visible to the USB host
 | 
			
		||||
     *
 | 
			
		||||
     * Enable either the D+ or D-  pullup so the host can detect
 | 
			
		||||
     * the presence of this device.
 | 
			
		||||
     */
 | 
			
		||||
    virtual void connect() = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Detach the USB phy
 | 
			
		||||
     *
 | 
			
		||||
     * Disable the D+ and D- pullup and stop responding to
 | 
			
		||||
     * USB traffic.
 | 
			
		||||
     */
 | 
			
		||||
    virtual void disconnect() = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set this device to the configured state
 | 
			
		||||
     *
 | 
			
		||||
     * Enable added endpoints if they are not enabled
 | 
			
		||||
     * already.
 | 
			
		||||
     */
 | 
			
		||||
    virtual void configure() = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Leave the configured state
 | 
			
		||||
     *
 | 
			
		||||
     * This is a notification to the USBPhy indicating that the device
 | 
			
		||||
     * is leaving the configured state. The USBPhy can disable all
 | 
			
		||||
     * endpoints other than endpoint 0.
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    virtual void unconfigure() = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Enable the start of frame interrupt
 | 
			
		||||
     *
 | 
			
		||||
     * Call USBPhyEvents::sof on every frame.
 | 
			
		||||
     */
 | 
			
		||||
    virtual void sof_enable() = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Disable the start of frame interrupt
 | 
			
		||||
     *
 | 
			
		||||
     * Stop calling USBPhyEvents::sof.
 | 
			
		||||
     */
 | 
			
		||||
    virtual void sof_disable() = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set the USBPhy's address
 | 
			
		||||
     *
 | 
			
		||||
     * @param address This device's USB address
 | 
			
		||||
     */
 | 
			
		||||
    virtual void set_address(uint8_t address) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Wake upstream devices
 | 
			
		||||
     */
 | 
			
		||||
    virtual void remote_wakeup() = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the endpoint table
 | 
			
		||||
     *
 | 
			
		||||
     * This function returns a table which describes the endpoints
 | 
			
		||||
     * can be used, the functionality of those endpoints and the
 | 
			
		||||
     * resource cost.
 | 
			
		||||
     */
 | 
			
		||||
    virtual const usb_ep_table_t* endpoint_table() = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set wMaxPacketSize of endpoint 0
 | 
			
		||||
     *
 | 
			
		||||
     * @param max_packet The wMaxPacketSize value for endpoint 0
 | 
			
		||||
     * @return The actual size of endpoint 0
 | 
			
		||||
     */
 | 
			
		||||
    virtual uint32_t ep0_set_max_packet(uint32_t max_packet) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Read the contents of the SETUP packet
 | 
			
		||||
     *
 | 
			
		||||
     * @param buffer Buffer to fill with data
 | 
			
		||||
     * @param size Size of buffer passed in
 | 
			
		||||
     */
 | 
			
		||||
    virtual void ep0_setup_read_result(uint8_t *buffer, uint32_t size) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Start receiving a packet of up to wMaxPacketSize on endpoint 0
 | 
			
		||||
     */
 | 
			
		||||
    virtual void ep0_read() = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Read the contents of a received packet
 | 
			
		||||
     *
 | 
			
		||||
     * @param buffer Buffer to fill with the data read
 | 
			
		||||
     * @param size Size of buffer
 | 
			
		||||
     */
 | 
			
		||||
    virtual uint32_t ep0_read_result(uint8_t *buffer, uint32_t size) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Write a packet on endpoint 0
 | 
			
		||||
     *
 | 
			
		||||
     * @param buffer Buffer fill with data to send
 | 
			
		||||
     * @param size Size of data to send
 | 
			
		||||
     */
 | 
			
		||||
    virtual void ep0_write(uint8_t *buffer, uint32_t size) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Protocol stall on endpoint 0
 | 
			
		||||
     *
 | 
			
		||||
     * Stall all IN and OUT packets on endpoint 0 until a setup packet
 | 
			
		||||
     * is received.
 | 
			
		||||
     * @note The stall is cleared automatically when a setup packet is received
 | 
			
		||||
     */
 | 
			
		||||
    virtual void ep0_stall() = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Configure and enable an endpoint
 | 
			
		||||
     *
 | 
			
		||||
     * @param endpoint Endpoint to configure and enable
 | 
			
		||||
     * @param max_packet The maximum packet size that can be sent or received
 | 
			
		||||
     * @param type The type of endpoint this should be configured as -
 | 
			
		||||
     *  USB_EP_TYPE_BULK, USB_EP_TYPE_INT or USB_EP_TYPE_ISO
 | 
			
		||||
     * @note This function cannot be used to configure endpoint 0. That must be done
 | 
			
		||||
     * with ep0_set_max_packet
 | 
			
		||||
     */
 | 
			
		||||
    virtual bool endpoint_add(usb_ep_t endpoint, uint32_t max_packet, usb_ep_type_t type) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Disable an endpoint
 | 
			
		||||
     *
 | 
			
		||||
     * @param endpoint Endpoint to disable
 | 
			
		||||
     */
 | 
			
		||||
    virtual void endpoint_remove(usb_ep_t endpoint) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Perform a functional stall on the given endpoint
 | 
			
		||||
     *
 | 
			
		||||
     * Set the HALT feature for this endpoint so that all further
 | 
			
		||||
     * communication is aborted.
 | 
			
		||||
     *
 | 
			
		||||
     * @param endpoint Endpoint to stall
 | 
			
		||||
     */
 | 
			
		||||
    virtual void endpoint_stall(usb_ep_t endpoint) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Unstall the endpoint
 | 
			
		||||
     *
 | 
			
		||||
     * Clear the HALT feature on this endpoint so communication can
 | 
			
		||||
     * resume.
 | 
			
		||||
     *
 | 
			
		||||
     * @param endpoint Endpoint to stall
 | 
			
		||||
     */
 | 
			
		||||
    virtual void endpoint_unstall(usb_ep_t endpoint) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Start a read on the given endpoint
 | 
			
		||||
     *
 | 
			
		||||
     * @param endpoint Endpoint to start the read on
 | 
			
		||||
     * @param max_packet A hint as to the wMaxPacketSize of this endpoint.
 | 
			
		||||
     *  This must match the size in endpoint_add.
 | 
			
		||||
     * @return true if the read was successfully started, false otherwise
 | 
			
		||||
     */
 | 
			
		||||
    virtual bool endpoint_read(usb_ep_t endpoint, uint32_t max_packet) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Finish a read on the given endpoint
 | 
			
		||||
     *
 | 
			
		||||
     * @param endpoint Endpoint to read data from
 | 
			
		||||
     * @param data Buffer to fill with data
 | 
			
		||||
     * @param size Size of buffer
 | 
			
		||||
     * @param bytes_read The number of bytes in the current packet. This can be larger than
 | 
			
		||||
     *  the size parameter if the buffer passed in was too small.
 | 
			
		||||
     * @return true if data was read false otherwise
 | 
			
		||||
     */
 | 
			
		||||
    virtual bool endpoint_read_result(usb_ep_t endpoint, uint8_t *data, uint32_t size, uint32_t *bytes_read) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Start a write on the given endpoint
 | 
			
		||||
     *
 | 
			
		||||
     * @param endpoint Endpoint to write to
 | 
			
		||||
     * @param data Buffer to write
 | 
			
		||||
     * @param size Size of data to write
 | 
			
		||||
     * @return true if the data was prepared for transmit, false otherwise
 | 
			
		||||
     */
 | 
			
		||||
    virtual bool endpoint_write(usb_ep_t endpoint, uint8_t *data, uint32_t size) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Abort the current transfer if it has not yet been sent
 | 
			
		||||
     *
 | 
			
		||||
     * @param endpoint Endpoint to abort the transfer on. It is implementation defined
 | 
			
		||||
     * if this function has an effect on receive endpoints.
 | 
			
		||||
     */
 | 
			
		||||
    virtual void endpoint_abort(usb_ep_t endpoint) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Callback used for performing USB processing
 | 
			
		||||
     *
 | 
			
		||||
     * USBPhy processing should be triggered by calling USBPhyEvents::start_process
 | 
			
		||||
     * and done inside process. All USBPhyEvents callbacks aside from
 | 
			
		||||
     * USBPhyEvents::start_process must be called in the context of process
 | 
			
		||||
     */
 | 
			
		||||
    virtual void process() = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,107 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2018-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * 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 USBPHY_EVENTS_H
 | 
			
		||||
#define USBPHY_EVENTS_H
 | 
			
		||||
 | 
			
		||||
#include "USBPhyTypes.h"
 | 
			
		||||
 | 
			
		||||
/** Event handler for USBPhy
 | 
			
		||||
 *
 | 
			
		||||
 * This class is the event handler for the USBPhy class. Any events generated
 | 
			
		||||
 * by USBPhy are passed to this class via the virtual functions.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup usb_device_core
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
class USBPhyEvents {
 | 
			
		||||
public:
 | 
			
		||||
    USBPhyEvents() {};
 | 
			
		||||
    virtual ~USBPhyEvents() {};
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Callback called when a bus reset occurs
 | 
			
		||||
     * @note called in the contex of USBPhy::process
 | 
			
		||||
     */
 | 
			
		||||
    virtual void reset() = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Callback called when an endpoint 0 setup packet is received
 | 
			
		||||
     * @note called in the contex of USBPhy::process
 | 
			
		||||
     */
 | 
			
		||||
    virtual void ep0_setup() = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Callback called when an endpoint 0 out packet is received
 | 
			
		||||
     * @note called in the contex of USBPhy::process
 | 
			
		||||
     */
 | 
			
		||||
    virtual void ep0_out() = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Callback called when an endpoint 0 in packet is received
 | 
			
		||||
     * @note called in the contex of USBPhy::process
 | 
			
		||||
     */
 | 
			
		||||
    virtual void ep0_in() = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Callback called USB power is applied or removed
 | 
			
		||||
     *
 | 
			
		||||
     * @param powered true if USB power is present, false otherwise
 | 
			
		||||
     * @note called in the contex of USBPhy::process
 | 
			
		||||
     */
 | 
			
		||||
    virtual void power(bool powered) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Callback called when entering or leaving suspend mode
 | 
			
		||||
     *
 | 
			
		||||
     * @param suspended true if entering suspend mode false otherwise
 | 
			
		||||
     * @note called in the contex of USBPhy::process
 | 
			
		||||
     */
 | 
			
		||||
    virtual void suspend(bool suspended) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Callback called on start of frame
 | 
			
		||||
     *
 | 
			
		||||
     * @param frame_number The current frame number
 | 
			
		||||
     * @note This callback is enabled/disabled by
 | 
			
		||||
     *  calling USBPhy::sof_enable / USBPhy::sof_disable
 | 
			
		||||
     * @note called in the contex of USBPhy::process
 | 
			
		||||
     */
 | 
			
		||||
    virtual void sof(int frame_number) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Callback called on the reception of an OUT packet
 | 
			
		||||
     *
 | 
			
		||||
     * @param endpoint Endpoint which received the OUT packet
 | 
			
		||||
     * @note called in the contex of USBPhy::process
 | 
			
		||||
     */
 | 
			
		||||
    virtual void out(usb_ep_t endpoint) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Callback called on the transmission of an IN packet
 | 
			
		||||
     *
 | 
			
		||||
     * @param endpoint Endpoint which sent the IN packet
 | 
			
		||||
     * @note called in the contex of USBPhy::process
 | 
			
		||||
     */
 | 
			
		||||
    virtual void in(usb_ep_t endpoint) = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Callback called to indicate the USB processing needs to be done
 | 
			
		||||
     */
 | 
			
		||||
    virtual void start_process() = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,58 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2018-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * 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 USBPHY_TYPES_H
 | 
			
		||||
#define USBPHY_TYPES_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
typedef uint8_t usb_ep_t;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    USB_EP_TYPE_CTRL = 0,
 | 
			
		||||
    USB_EP_TYPE_ISO = 1,
 | 
			
		||||
    USB_EP_TYPE_BULK = 2,
 | 
			
		||||
    USB_EP_TYPE_INT = 3
 | 
			
		||||
} usb_ep_type_t;
 | 
			
		||||
 | 
			
		||||
enum  {
 | 
			
		||||
    USB_EP_ATTR_ALLOW_CTRL = 1 << USB_EP_TYPE_CTRL,
 | 
			
		||||
    USB_EP_ATTR_ALLOW_BULK = 1 << USB_EP_TYPE_BULK,
 | 
			
		||||
    USB_EP_ATTR_ALLOW_INT = 1 << USB_EP_TYPE_INT,
 | 
			
		||||
    USB_EP_ATTR_ALLOW_ISO = 1 << USB_EP_TYPE_ISO,
 | 
			
		||||
    USB_EP_ATTR_ALLOW_ALL = USB_EP_ATTR_ALLOW_CTRL | USB_EP_ATTR_ALLOW_BULK |
 | 
			
		||||
                             USB_EP_ATTR_ALLOW_INT | USB_EP_ATTR_ALLOW_ISO,
 | 
			
		||||
 | 
			
		||||
    USB_EP_ATTR_DIR_IN = 0 << 4,
 | 
			
		||||
    USB_EP_ATTR_DIR_OUT = 1 << 4,
 | 
			
		||||
    USB_EP_ATTR_DIR_IN_OR_OUT = 2 << 4,
 | 
			
		||||
    USB_EP_ATTR_DIR_IN_AND_OUT = 3 << 4,
 | 
			
		||||
    USB_EP_ATTR_DIR_MASK = 3 << 4
 | 
			
		||||
};
 | 
			
		||||
typedef uint8_t usb_ep_attr_t;
 | 
			
		||||
 | 
			
		||||
struct usb_ep_entry_t {
 | 
			
		||||
    usb_ep_attr_t attributes;
 | 
			
		||||
    uint8_t byte_cost;
 | 
			
		||||
    uint16_t base_cost;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct usb_ep_table_t {
 | 
			
		||||
    uint32_t resources;
 | 
			
		||||
    usb_ep_entry_t table[16];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,136 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2018-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "mbed.h"
 | 
			
		||||
#include "EndpointResolver.h"
 | 
			
		||||
 | 
			
		||||
static uint32_t logical_to_index(uint32_t logical, bool in_not_out)
 | 
			
		||||
{
 | 
			
		||||
    return (logical << 1) | (in_not_out ? 1 : 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t index_to_logical(uint32_t index)
 | 
			
		||||
{
 | 
			
		||||
    return index >> 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
EndpointResolver::EndpointResolver(const usb_ep_table_t *table) : _table(table), _cost(0), _used(0), _valid(true)
 | 
			
		||||
{
 | 
			
		||||
    // Do nothing
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EndpointResolver::~EndpointResolver()
 | 
			
		||||
{
 | 
			
		||||
    // Do nothing
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EndpointResolver::endpoint_ctrl(uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
    endpoint_in(USB_EP_TYPE_CTRL, size);
 | 
			
		||||
    endpoint_out(USB_EP_TYPE_CTRL, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
usb_ep_t EndpointResolver::endpoint_in(usb_ep_type_t type, uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
    int index = next_index(type, true);
 | 
			
		||||
    if (index < 0) {
 | 
			
		||||
        _valid = false;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const usb_ep_entry_t &entry = _table->table[index_to_logical(index)];
 | 
			
		||||
    _cost += entry.base_cost + entry.byte_cost * size;
 | 
			
		||||
    _used |= 1 << index;
 | 
			
		||||
 | 
			
		||||
    return index_to_endpoint(index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
usb_ep_t EndpointResolver::endpoint_out(usb_ep_type_t type, uint32_t size)
 | 
			
		||||
{
 | 
			
		||||
    int index = next_index(type, false);
 | 
			
		||||
    if (index < 0) {
 | 
			
		||||
        _valid = false;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const usb_ep_entry_t &entry = _table->table[index_to_logical(index)];
 | 
			
		||||
    _cost += entry.base_cost + entry.byte_cost * size;
 | 
			
		||||
    _used |= 1 << index;
 | 
			
		||||
 | 
			
		||||
    return index_to_endpoint(index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool EndpointResolver::valid()
 | 
			
		||||
{
 | 
			
		||||
    return _valid && (_cost <= _table->resources);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void EndpointResolver::reset() {
 | 
			
		||||
    _cost = 0;
 | 
			
		||||
    _used = 0;
 | 
			
		||||
    _valid = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
usb_ep_t EndpointResolver::index_to_endpoint(int index)
 | 
			
		||||
{
 | 
			
		||||
    return index_to_logical(index) | ((index & 1) ? 0x80 : 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int EndpointResolver::next_index(usb_ep_type_t type, bool in_not_out)
 | 
			
		||||
{
 | 
			
		||||
    for (int logical = 0; logical < (int)(sizeof(_table->table) / sizeof(_table->table[0])); logical++) {
 | 
			
		||||
        uint32_t index = logical_to_index(logical, in_not_out);
 | 
			
		||||
        uint32_t other = logical_to_index(logical, !in_not_out);
 | 
			
		||||
        const usb_ep_entry_t &entry = _table->table[logical];
 | 
			
		||||
 | 
			
		||||
        usb_ep_attr_t dir = entry.attributes & USB_EP_ATTR_DIR_MASK;
 | 
			
		||||
        bool in_allowed = dir != USB_EP_ATTR_DIR_OUT;
 | 
			
		||||
        bool out_allowed = dir != USB_EP_ATTR_DIR_IN;
 | 
			
		||||
        bool shared = dir == USB_EP_ATTR_DIR_IN_OR_OUT;
 | 
			
		||||
 | 
			
		||||
        if (!(entry.attributes & (1 << type))) {
 | 
			
		||||
            // This type is not supported
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (in_not_out && !in_allowed) {
 | 
			
		||||
            // In endpoint not supported
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!in_not_out && !out_allowed) {
 | 
			
		||||
            // Out endpoint not supported
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (_used & (1 << index)) {
 | 
			
		||||
            // This endpoint is in use
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (shared && (1 << other)) {
 | 
			
		||||
            // This endpoint can only be one direction at a time and is in
 | 
			
		||||
            // use by the other direction
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return index;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Not found
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,89 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2018-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * 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 ENDPOINT_RESOLVER_H
 | 
			
		||||
#define ENDPOINT_RESOLVER_H
 | 
			
		||||
 | 
			
		||||
#include "mbed.h"
 | 
			
		||||
 | 
			
		||||
#include "USBPhy.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Utility class for resolving endpoints
 | 
			
		||||
 *
 | 
			
		||||
 * This class is intended to make the process of
 | 
			
		||||
 * selecting the correct endpoint from a device endpoint
 | 
			
		||||
 * table easier. It also provides a verification function
 | 
			
		||||
 * to check if the device has enough resources for the
 | 
			
		||||
 * given configuration.
 | 
			
		||||
 *
 | 
			
		||||
 * @ingroup usb_device_core
 | 
			
		||||
 */
 | 
			
		||||
class EndpointResolver {
 | 
			
		||||
public:
 | 
			
		||||
    EndpointResolver(const usb_ep_table_t *table);
 | 
			
		||||
    ~EndpointResolver();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Add control endpoint size
 | 
			
		||||
     *
 | 
			
		||||
     * @param size Space reserved for control in and control out
 | 
			
		||||
     */
 | 
			
		||||
    void endpoint_ctrl(uint32_t size);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Return a free IN endpoint of the given size
 | 
			
		||||
     *
 | 
			
		||||
     * @param type Desired endpoint type
 | 
			
		||||
     * @param size Space to reserve for this endpoint
 | 
			
		||||
     * @return Endpoint index or 0 if there are not enough resources
 | 
			
		||||
     */
 | 
			
		||||
    usb_ep_t endpoint_in(usb_ep_type_t type, uint32_t size);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Return a free OUT endpoint of the given size
 | 
			
		||||
     *
 | 
			
		||||
     * @param type Desired endpoint type
 | 
			
		||||
     * @param size Space to reserve for this endpoint
 | 
			
		||||
     * @return Endpoint index or 0 if there are not enough resources
 | 
			
		||||
     */
 | 
			
		||||
    usb_ep_t endpoint_out(usb_ep_type_t type, uint32_t size);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if the endpoint configuration created so far is valid
 | 
			
		||||
     *
 | 
			
		||||
     * @return true if all endpoint sizes are available and fit, false otherwise
 | 
			
		||||
     */
 | 
			
		||||
    bool valid();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Reset this class's state to when it was constructed
 | 
			
		||||
     */
 | 
			
		||||
    void reset();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    usb_ep_t index_to_endpoint(int index);
 | 
			
		||||
    int next_index(usb_ep_type_t type, bool in_not_out);
 | 
			
		||||
 | 
			
		||||
    const usb_ep_table_t *_table;
 | 
			
		||||
    uint32_t _cost;
 | 
			
		||||
    uint32_t _used;
 | 
			
		||||
    bool _valid;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
		Loading…
	
		Reference in New Issue