/************************************************************************************ * configs/olimex-stm32-p407/src/stm32_usb.c * * Copyright (C) 2016-2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. 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. * 3. Neither the name NuttX nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "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 * COPYRIGHT OWNER OR CONTRIBUTORS 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. * ************************************************************************************/ /************************************************************************************ * Included Files ************************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include "up_arch.h" #include "stm32.h" #include "stm32_otgfs.h" #include "olimex-stm32-p407.h" #ifdef CONFIG_STM32_OTGFS /************************************************************************************ * Pre-processor Definitions ************************************************************************************/ #if defined(CONFIG_USBDEV) || defined(CONFIG_USBHOST) # define HAVE_USB 1 #else # warning "CONFIG_STM32_OTGFS is enabled but neither CONFIG_USBDEV nor CONFIG_USBHOST" # undef HAVE_USB #endif #ifndef CONFIG_OLIMEXP407_USBHOST_PRIO # define CONFIG_OLIMEXP407_USBHOST_PRIO 100 #endif #ifndef CONFIG_OLIMEXP407_USBHOST_STACKSIZE # define CONFIG_OLIMEXP407_USBHOST_STACKSIZE 1024 #endif /************************************************************************************ * Private Data ************************************************************************************/ #ifdef CONFIG_USBHOST static struct usbhost_connection_s *g_usbconn; #endif /************************************************************************************ * Private Functions ************************************************************************************/ /************************************************************************************ * Name: usbhost_waiter * * Description: * Wait for USB devices to be connected. * ************************************************************************************/ #ifdef CONFIG_USBHOST static int usbhost_waiter(int argc, char *argv[]) { struct usbhost_hubport_s *hport; uinfo("Running\n"); for (;;) { /* Wait for the device to change state */ DEBUGVERIFY(CONN_WAIT(g_usbconn, &hport)); uinfo("%s\n", hport->connected ? "connected" : "disconnected"); /* Did we just become connected? */ if (hport->connected) { /* Yes.. enumerate the newly connected device */ (void)CONN_ENUMERATE(g_usbconn, hport); } } /* Keep the compiler from complaining */ return 0; } #endif /************************************************************************************ * Public Functions ************************************************************************************/ /************************************************************************************ * Name: stm32_usb_configure * * Description: * Called from stm32_boardinitialize very early in inialization to setup USB-related * GPIO pins for the Olimex STM32 P407 board. * ************************************************************************************/ void stm32_usb_configure(void) { #ifdef CONFIG_STM32_OTGFS /* The OTG FS has an internal soft pull-up. No GPIO configuration is required */ /* Configure the OTG FS VBUS sensing GPIO, Power On, and Overcurrent GPIOs */ stm32_configgpio(GPIO_OTGFS_VBUS); stm32_configgpio(GPIO_OTGFS_PWRON); stm32_configgpio(GPIO_OTGFS_OVER); #endif } /*********************************************************************************** * Name: stm32_usbhost_setup * * Description: * Called at application startup time to initialize the USB host functionality. * This function will start a thread that will monitor for device * connection/disconnection events. * ***********************************************************************************/ #ifdef CONFIG_USBHOST int stm32_usbhost_setup(void) { int pid; int ret; /* First, register all of the class drivers needed to support the drivers * that we care about: */ uinfo("Register class drivers\n"); #ifdef CONFIG_USBHOST_HUB /* Initialize USB hub class support */ ret = usbhost_hub_initialize(); if (ret < 0) { uerr("ERROR: usbhost_hub_initialize failed: %d\n", ret); } #endif #ifdef CONFIG_USBHOST_MSC /* Register the USB mass storage class class */ ret = usbhost_msc_initialize(); if (ret != OK) { uerr("ERROR: Failed to register the mass storage class: %d\n", ret); } #endif #ifdef CONFIG_USBHOST_CDCACM /* Register the CDC/ACM serial class */ ret = usbhost_cdcacm_initialize(); if (ret != OK) { uerr("ERROR: Failed to register the CDC/ACM serial class: %d\n", ret); } #endif #ifdef CONFIG_USBHOST_HIDKBD /* Initialize the HID keyboard class */ ret = usbhost_kbdinit(); if (ret != OK) { uerr("ERROR: Failed to register the HID keyboard class\n"); } #endif #ifdef CONFIG_USBHOST_HIDMOUSE /* Initialize the HID mouse class */ ret = usbhost_mouse_init(); if (ret != OK) { uerr("ERROR: Failed to register the HID mouse class\n"); } #endif UNUSED(ret); /* Then get an instance of the USB host interface */ uinfo("Initialize USB host\n"); g_usbconn = stm32_otgfshost_initialize(0); if (g_usbconn) { /* Start a thread to handle device connection. */ uinfo("Start usbhost_waiter\n"); pid = kthread_create("usbhost", CONFIG_OLIMEXP407_USBHOST_PRIO, CONFIG_OLIMEXP407_USBHOST_STACKSIZE, (main_t)usbhost_waiter, (FAR char * const *)NULL); return pid < 0 ? -ENOEXEC : OK; } return -ENODEV; } #endif /*********************************************************************************** * Name: stm32_usbhost_vbusdrive * * Description: * Enable/disable driving of VBUS 5V output. This function must be provided be * each platform that implements the STM32 OTG FS host interface * * "On-chip 5 V VBUS generation is not supported. For this reason, a charge pump * or, if 5 V are available on the application board, a basic power switch, must * be added externally to drive the 5 V VBUS line. The external charge pump can * be driven by any GPIO output. When the application decides to power on VBUS * using the chosen GPIO, it must also set the port power bit in the host port * control and status register (PPWR bit in OTG_FS_HPRT). * * "The application uses this field to control power to this port, and the core * clears this bit on an overcurrent condition." * * Input Parameters: * iface - For future growth to handle multiple USB host interface. Should be zero. * enable - true: enable VBUS power; false: disable VBUS power * * Returned Value: * None * ***********************************************************************************/ #ifdef CONFIG_USBHOST void stm32_usbhost_vbusdrive(int iface, bool enable) { DEBUGASSERT(iface == 0); if (enable) { /* Enable the Power Switch by driving the enable pin low */ stm32_gpiowrite(GPIO_OTGFS_PWRON, false); } else { /* Disable the Power Switch by driving the enable pin high */ stm32_gpiowrite(GPIO_OTGFS_PWRON, true); } } #endif /************************************************************************************ * Name: stm32_setup_overcurrent * * Description: * Setup to receive an interrupt-level callback if an overcurrent condition is * detected. * * Input Parameters: * handler - New overcurrent interrupt handler * arg - The argument provided for the interrupt handler * * Returned Value: * Zero (OK) is returned on success. Otherwise, a negated errno value is returned * to indicate the nature of the failure. * ************************************************************************************/ #ifdef CONFIG_USBHOST int stm32_setup_overcurrent(xcpt_t handler, void *arg) { return stm32_gpiosetevent(GPIO_OTGFS_OVER, true, true, true, handler, arg); } #endif /************************************************************************************ * Name: stm32_usbsuspend * * Description: * Board logic must provide the stm32_usbsuspend logic if the USBDEV driver is * used. This function is called whenever the USB enters or leaves suspend mode. * This is an opportunity for the board logic to shutdown clocks, power, etc. * while the USB is suspended. * ************************************************************************************/ #ifdef CONFIG_USBDEV void stm32_usbsuspend(FAR struct usbdev_s *dev, bool resume) { uinfo("resume: %d\n", resume); } #endif #endif /* CONFIG_STM32_OTGFS */