mirror of
https://github.com/apache/nuttx.git
synced 2025-01-13 09:49:21 +08:00
Merge remote-tracking branch 'origin/master' into beacon802154
This commit is contained in:
commit
2f01b92fe2
33 changed files with 2973 additions and 1581 deletions
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* configs/boardctl.c
|
||||
*
|
||||
* Copyright (C) 2015-2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2015-2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -182,7 +182,10 @@ static inline int boardctl_usbdevctrl(FAR struct boardioc_usbdev_ctrl_s *ctrl)
|
|||
case BOARDIOC_USBDEV_CONNECT: /* Connect the Composite device */
|
||||
{
|
||||
DEBUGASSERT(ctrl->handle != NULL);
|
||||
*ctrl->handle = composite_initialize();
|
||||
|
||||
*ctrl->handle =
|
||||
board_composite_connect(ctrl->instance, ctrl->config);
|
||||
|
||||
if (*ctrl->handle == NULL)
|
||||
{
|
||||
ret = -EIO;
|
||||
|
@ -190,7 +193,8 @@ static inline int boardctl_usbdevctrl(FAR struct boardioc_usbdev_ctrl_s *ctrl)
|
|||
}
|
||||
break;
|
||||
|
||||
case BOARDIOC_USBDEV_DISCONNECT: /* Disconnect the Composite device */
|
||||
case BOARDIOC_USBDEV_DISCONNECT: /* Disconnect the Composite
|
||||
* device */
|
||||
{
|
||||
DEBUGASSERT(ctrl->handle != NULL && *ctrl->handle != NULL);
|
||||
composite_uninitialize(*ctrl->handle);
|
||||
|
|
|
@ -68,8 +68,4 @@ ifeq ($(CONFIG_USBMSC),y)
|
|||
CSRCS += stm32_usbmsc.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USBDEV_COMPOSITE),y)
|
||||
CSRCS += stm32_composite.c
|
||||
endif
|
||||
|
||||
include $(TOPDIR)/configs/Board.mk
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
/****************************************************************************
|
||||
* configs/fire-stm32v2/src/stm32_composite.c
|
||||
*
|
||||
* Copyright (C) 2012, 2016 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Configure and register the STM32 SPI-based MMC/SD block driver.
|
||||
*
|
||||
* 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 <nuttx/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <nuttx/board.h>
|
||||
|
||||
#include "fire-stm32v2.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
/* Device minor number */
|
||||
|
||||
#ifndef CONFIG_SYSTEM_COMPOSITE_DEVMINOR1
|
||||
# define CONFIG_SYSTEM_COMPOSITE_DEVMINOR1 0
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_composite_initialize
|
||||
*
|
||||
* Description:
|
||||
* Perform architecture specific initialization of a composite USB device.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int board_composite_initialize(int port)
|
||||
{
|
||||
/* If system/composite is built as an NSH command, then SD slot should
|
||||
* already have been initialized in board_app_initialize() (see stm32_appinit.c).
|
||||
* In this case, there is nothing further to be done here.
|
||||
*
|
||||
* NOTE: CONFIG_NSH_BUILTIN_APPS is not a fool-proof indication that NSH
|
||||
* was built.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_NSH_BUILTIN_APPS
|
||||
return sd_mount(CONFIG_SYSTEM_COMPOSITE_DEVMINOR1);
|
||||
#else
|
||||
return OK;
|
||||
#endif /* CONFIG_NSH_BUILTIN_APPS */
|
||||
}
|
|
@ -51,11 +51,8 @@ CONFIG_USBDEV=y
|
|||
CONFIG_USBMSC_BULKINREQLEN=256
|
||||
CONFIG_USBMSC_BULKOUTREQLEN=256
|
||||
CONFIG_USBMSC_COMPOSITE=y
|
||||
CONFIG_USBMSC_EPBULKIN=5
|
||||
CONFIG_USBMSC_EPBULKOUT=4
|
||||
CONFIG_USBMSC_NRDREQS=2
|
||||
CONFIG_USBMSC_NWRREQS=2
|
||||
CONFIG_USBMSC_PRODUCTSTR="USBdev Storage"
|
||||
CONFIG_USBMSC_REMOVABLE=y
|
||||
CONFIG_USBMSC_VERSIONNO=0x0399
|
||||
CONFIG_USBMSC=y
|
||||
|
|
|
@ -48,25 +48,290 @@
|
|||
#include <nuttx/board.h>
|
||||
#include <nuttx/mmcsd.h>
|
||||
#include <nuttx/spi/spi.h>
|
||||
#include <nuttx/usb/usbdev.h>
|
||||
#include <nuttx/usb/cdcacm.h>
|
||||
#include <nuttx/usb/usbmsc.h>
|
||||
#include <nuttx/usb/composite.h>
|
||||
|
||||
#include "lpc214x_spi.h"
|
||||
|
||||
#if defined(CONFIG_BOARDCTL_USBDEVCTRL) && defined(CONFIG_USBDEV_COMPOSITE)
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Configuration ************************************************************/
|
||||
|
||||
#ifndef CONFIG_SYSTEM_COMPOSITE_DEVMINOR1
|
||||
# define CONFIG_SYSTEM_COMPOSITE_DEVMINOR1 0
|
||||
#endif
|
||||
|
||||
/* PORT and SLOT number depend on the board configuration */
|
||||
|
||||
#define LPC214X_MMCSDSPIPORTNO 1
|
||||
#define LPC214X_MMCSDSLOTNO 0
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static FAR void *g_mschandle;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_mscclassobject
|
||||
*
|
||||
* Description:
|
||||
* If the mass storage class driver is part of composite device, then
|
||||
* its instantiation and configuration is a multi-step, board-specific,
|
||||
* process (See comments for usbmsc_configure below). In this case,
|
||||
* board-specific logic must provide board_mscclassobject().
|
||||
*
|
||||
* board_mscclassobject() is called from the composite driver. It must
|
||||
* encapsulate the instantiation and configuration of the mass storage
|
||||
* class and the return the mass storage device's class driver instance
|
||||
* to the composite driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* classdev - The location to return the mass storage class' device
|
||||
* instance.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static int board_mscclassobject(int minor,
|
||||
FAR struct usbdev_description_s *devdesc,
|
||||
FAR struct usbdevclass_driver_s **classdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(g_mschandle == NULL);
|
||||
|
||||
/* Configure the mass storage device */
|
||||
|
||||
uinfo("Configuring with NLUNS=1\n");
|
||||
ret = usbmsc_configure(1, &g_mschandle);
|
||||
if (ret < 0)
|
||||
{
|
||||
uerr("ERROR: usbmsc_configure failed: %d\n", -ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uinfo("MSC handle=%p\n", g_mschandle);
|
||||
|
||||
/* Bind the LUN(s) */
|
||||
|
||||
uinfo("Bind LUN=0 to /dev/mmcsd0\n");
|
||||
ret = usbmsc_bindlun(g_mschandle, "/dev/mmcsd0", 0, 0, 0, false);
|
||||
if (ret < 0)
|
||||
{
|
||||
uerr("ERROR: usbmsc_bindlun failed for LUN 1 at /dev/mmcsd0: %d\n",
|
||||
ret);
|
||||
usbmsc_uninitialize(g_mschandle);
|
||||
g_mschandle = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get the mass storage device's class object */
|
||||
|
||||
ret = usbmsc_classobject(g_mschandle, devdesc, classdev);
|
||||
if (ret < 0)
|
||||
{
|
||||
uerr("ERROR: usbmsc_classobject failed: %d\n", -ret);
|
||||
usbmsc_uninitialize(g_mschandle);
|
||||
g_mschandle = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_mscuninitialize
|
||||
*
|
||||
* Description:
|
||||
* Un-initialize the USB storage class driver. This is just an application-
|
||||
* specific wrapper aboutn usbmsc_unitialize() that is called form the
|
||||
* composite device logic.
|
||||
*
|
||||
* Input Parameters:
|
||||
* classdev - The class driver instrance previously give to the composite
|
||||
* driver by board_mscclassobject().
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static void board_mscuninitialize(FAR struct usbdevclass_driver_s *classdev)
|
||||
{
|
||||
DEBUGASSERT(g_mschandle != NULL);
|
||||
usbmsc_uninitialize(g_mschandle);
|
||||
g_mschandle = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_composite0_connect
|
||||
*
|
||||
* Description:
|
||||
* Connect the USB composite device on the specified USB device port for
|
||||
* configuration 0.
|
||||
*
|
||||
* Input Parameters:
|
||||
* port - The USB device port.
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL handle value is returned on success. NULL is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static FAR void *board_composite0_connect(int port)
|
||||
{
|
||||
/* Here we are composing the configuration of the usb composite device.
|
||||
*
|
||||
* The standard is to use one CDC/ACM and one USB mass storage device.
|
||||
*/
|
||||
|
||||
struct composite_devdesc_s dev[2];
|
||||
int ifnobase = 0;
|
||||
int strbase = COMPOSITE_NSTRIDS;
|
||||
|
||||
/* Configure the CDC/ACM device */
|
||||
|
||||
/* Ask the cdcacm driver to fill in the constants we didn't
|
||||
* know here.
|
||||
*/
|
||||
|
||||
cdcacm_get_composite_devdesc(&dev[0]);
|
||||
|
||||
/* Overwrite and correct some values... */
|
||||
/* The callback functions for the CDC/ACM class */
|
||||
|
||||
dev[0].classobject = cdcacm_classobject;
|
||||
dev[0].uninitialize = cdcacm_uninitialize;
|
||||
|
||||
/* Interfaces */
|
||||
|
||||
dev[0].devdesc.ifnobase = ifnobase; /* Offset to Interface-IDs */
|
||||
dev[0].minor = 0; /* The minor interface number */
|
||||
|
||||
/* Strings */
|
||||
|
||||
dev[0].devdesc.strbase = strbase; /* Offset to String Numbers */
|
||||
|
||||
/* Endpoints */
|
||||
|
||||
dev[0].devdesc.epno[CDCACM_EP_INTIN_IDX] = 1;
|
||||
dev[0].devdesc.epno[CDCACM_EP_BULKIN_IDX] = 2;
|
||||
dev[0].devdesc.epno[CDCACM_EP_BULKOUT_IDX] = 3;
|
||||
|
||||
/* Count up the base numbers */
|
||||
|
||||
ifnobase += dev[0].devdesc.ninterfaces;
|
||||
strbase += dev[0].devdesc.nstrings;
|
||||
|
||||
/* Configure the mass storage device device */
|
||||
/* Ask the usbmsc driver to fill in the constants we didn't
|
||||
* know here.
|
||||
*/
|
||||
|
||||
usbmsc_get_composite_devdesc(&dev[1]);
|
||||
|
||||
/* Overwrite and correct some values... */
|
||||
/* The callback functions for the USBMSC class */
|
||||
|
||||
dev[1].classobject = board_mscclassobject;
|
||||
dev[1].uninitialize = board_mscuninitialize;
|
||||
|
||||
/* Interfaces */
|
||||
|
||||
dev[1].devdesc.ifnobase = ifnobase; /* Offset to Interface-IDs */
|
||||
dev[1].minor = 0; /* The minor interface number */
|
||||
|
||||
/* Strings */
|
||||
|
||||
dev[1].devdesc.strbase = strbase; /* Offset to String Numbers */
|
||||
|
||||
/* Endpoints */
|
||||
|
||||
dev[1].devdesc.epno[USBMSC_EP_BULKIN_IDX] = 5;
|
||||
dev[1].devdesc.epno[USBMSC_EP_BULKOUT_IDX] = 4;
|
||||
|
||||
/* Count up the base numbers */
|
||||
|
||||
ifnobase += dev[1].devdesc.ninterfaces;
|
||||
strbase += dev[1].devdesc.nstrings;
|
||||
|
||||
return composite_initialize(2, dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_composite1_connect
|
||||
*
|
||||
* Description:
|
||||
* Connect the USB composite device on the specified USB device port for
|
||||
* configuration 1.
|
||||
*
|
||||
* Input Parameters:
|
||||
* port - The USB device port.
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL handle value is returned on success. NULL is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static FAR void *board_composite1_connect(int port)
|
||||
{
|
||||
struct composite_devdesc_s dev[2];
|
||||
int strbase = COMPOSITE_NSTRIDS;
|
||||
int ifnobase = 0;
|
||||
int epno;
|
||||
int i;
|
||||
|
||||
for (i = 0, epno = 1; i < 2; i++)
|
||||
{
|
||||
/* Ask the cdcacm driver to fill in the constants we didn't know here */
|
||||
|
||||
cdcacm_get_composite_devdesc(&dev[i]);
|
||||
|
||||
/* Overwrite and correct some values... */
|
||||
/* The callback functions for the CDC/ACM class */
|
||||
|
||||
dev[i].classobject = cdcacm_classobject;
|
||||
dev[i].uninitialize = cdcacm_uninitialize;
|
||||
|
||||
dev[i].minor = i; /* The minor interface number */
|
||||
|
||||
/* Interfaces */
|
||||
|
||||
dev[i].devdesc.ifnobase = ifnobase; /* Offset to Interface-IDs */
|
||||
|
||||
/* Strings */
|
||||
|
||||
dev[i].devdesc.strbase = strbase; /* Offset to String Numbers */
|
||||
|
||||
/* Endpoints */
|
||||
|
||||
dev[i].devdesc.epno[CDCACM_EP_INTIN_IDX] = epno++;
|
||||
dev[i].devdesc.epno[CDCACM_EP_BULKIN_IDX] = epno++;
|
||||
dev[i].devdesc.epno[CDCACM_EP_BULKOUT_IDX] = epno++;
|
||||
|
||||
ifnobase += dev[i].devdesc.ninterfaces;
|
||||
strbase += dev[i].devdesc.nstrings;
|
||||
}
|
||||
|
||||
return composite_initialize(2, dev);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -113,8 +378,7 @@ int board_composite_initialize(int port)
|
|||
syslog(LOG_INFO, "Binding SPI port %d to MMC/SD slot %d\n",
|
||||
LPC214X_MMCSDSPIPORTNO, LPC214X_MMCSDSLOTNO);
|
||||
|
||||
ret = mmcsd_spislotinitialize(CONFIG_SYSTEM_COMPOSITE_DEVMINOR1,
|
||||
LPC214X_MMCSDSLOTNO, spi);
|
||||
ret = mmcsd_spislotinitialize(0, LPC214X_MMCSDSLOTNO, spi);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR,
|
||||
|
@ -130,3 +394,43 @@ int board_composite_initialize(int port)
|
|||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_composite_connect
|
||||
*
|
||||
* Description:
|
||||
* Connect the USB composite device on the specified USB device port using
|
||||
* the specified configuration. The interpretation of the configid is
|
||||
* board specific.
|
||||
*
|
||||
* Input Parameters:
|
||||
* port - The USB device port.
|
||||
* configid - The USB composite configuration
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL handle value is returned on success. NULL is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR void *board_composite_connect(int port, int configid)
|
||||
{
|
||||
if (configid == 0)
|
||||
{
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
return board_composite0_connect(port);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
else if (configid == 1)
|
||||
{
|
||||
return board_composite1_connect(port);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BOARDCTL_USBDEVCTRL && CONFIG_USBDEV_COMPOSITE */
|
||||
|
|
|
@ -134,8 +134,6 @@ CONFIG_USART2_RXBUFSIZE=32
|
|||
CONFIG_USART2_TXBUFSIZE=32
|
||||
CONFIG_USBDEV_COMPOSITE=y
|
||||
CONFIG_USBMSC_COMPOSITE=y
|
||||
CONFIG_USBMSC_EPBULKIN=5
|
||||
CONFIG_USBMSC_EPBULKOUT=4
|
||||
CONFIG_USBMSC_NRDREQS=2
|
||||
CONFIG_USBMSC_NWRREQS=2
|
||||
CONFIG_USBMSC_REMOVABLE=y
|
||||
|
|
|
@ -99,11 +99,9 @@ int board_app_initialize(uintptr_t arg)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USBDEV_COMPOSITE
|
||||
#if !defined(CONFIG_NSH_BUILTIN_APPS) && !defined(CONFIG_SYSTEM_COMPOSITE)
|
||||
#if !defined(CONFIG_NSH_BUILTIN_APPS) && defined(CONFIG_USBDEV_COMPOSITE)
|
||||
ret = board_composite_initialize(0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CAN
|
||||
/* Initialize CAN and register the CAN driver. */
|
||||
|
|
|
@ -47,22 +47,26 @@
|
|||
#include <nuttx/board.h>
|
||||
#include <nuttx/mmcsd.h>
|
||||
#include <nuttx/spi/spi.h>
|
||||
#include <nuttx/usb/usbdev.h>
|
||||
#include <nuttx/usb/cdcacm.h>
|
||||
#include <nuttx/usb/usbmsc.h>
|
||||
#include <nuttx/usb/composite.h>
|
||||
|
||||
#include "stm32.h"
|
||||
#include "olimexino-stm32.h"
|
||||
|
||||
/* There is nothing to do here if SPI support is not selected. */
|
||||
|
||||
#ifdef CONFIG_STM32_SPI
|
||||
#if defined(CONFIG_BOARDCTL_USBDEVCTRL) && defined(CONFIG_USBDEV_COMPOSITE)
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Configuration ************************************************************/
|
||||
/* No SPI? Then no USB MSC device in composite */
|
||||
|
||||
#ifndef CONFIG_SYSTEM_COMPOSITE_DEVMINOR1
|
||||
# define CONFIG_SYSTEM_COMPOSITE_DEVMINOR1 0
|
||||
#ifndef CONFIG_STM32_SPI
|
||||
# undef CONFIG_USBMSC_COMPOSITE
|
||||
#endif
|
||||
|
||||
/* SLOT number(s) could depend on the board configuration */
|
||||
|
@ -77,6 +81,282 @@
|
|||
# error "Unrecognized STM32 board"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static FAR void *g_mschandle;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_mscclassobject
|
||||
*
|
||||
* Description:
|
||||
* If the mass storage class driver is part of composite device, then
|
||||
* its instantiation and configuration is a multi-step, board-specific,
|
||||
* process (See comments for usbmsc_configure below). In this case,
|
||||
* board-specific logic must provide board_mscclassobject().
|
||||
*
|
||||
* board_mscclassobject() is called from the composite driver. It must
|
||||
* encapsulate the instantiation and configuration of the mass storage
|
||||
* class and the return the mass storage device's class driver instance
|
||||
* to the composite driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* classdev - The location to return the mass storage class' device
|
||||
* instance.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static int board_mscclassobject(int minor,
|
||||
FAR struct usbdev_description_s *devdesc,
|
||||
FAR struct usbdevclass_driver_s **classdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(g_mschandle == NULL);
|
||||
|
||||
/* Configure the mass storage device */
|
||||
|
||||
uinfo("Configuring with NLUNS=1\n");
|
||||
ret = usbmsc_configure(1, &g_mschandle);
|
||||
if (ret < 0)
|
||||
{
|
||||
uerr("ERROR: usbmsc_configure failed: %d\n", -ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uinfo("MSC handle=%p\n", g_mschandle);
|
||||
|
||||
/* Bind the LUN(s) */
|
||||
|
||||
uinfo("Bind LUN=0 to /dev/mmcsd0\n");
|
||||
ret = usbmsc_bindlun(g_mschandle, "/dev/mmcsd0", 0, 0, 0, false);
|
||||
if (ret < 0)
|
||||
{
|
||||
uerr("ERROR: usbmsc_bindlun failed for LUN 1 at /dev/mmcsd0: %d\n",
|
||||
ret);
|
||||
usbmsc_uninitialize(g_mschandle);
|
||||
g_mschandle = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get the mass storage device's class object */
|
||||
|
||||
ret = usbmsc_classobject(g_mschandle, devdesc, classdev);
|
||||
if (ret < 0)
|
||||
{
|
||||
uerr("ERROR: usbmsc_classobject failed: %d\n", -ret);
|
||||
usbmsc_uninitialize(g_mschandle);
|
||||
g_mschandle = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_mscuninitialize
|
||||
*
|
||||
* Description:
|
||||
* Un-initialize the USB storage class driver. This is just an application-
|
||||
* specific wrapper aboutn usbmsc_unitialize() that is called form the
|
||||
* composite device logic.
|
||||
*
|
||||
* Input Parameters:
|
||||
* classdev - The class driver instrance previously give to the composite
|
||||
* driver by board_mscclassobject().
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static void board_mscuninitialize(FAR struct usbdevclass_driver_s *classdev)
|
||||
{
|
||||
DEBUGASSERT(g_mschandle != NULL);
|
||||
usbmsc_uninitialize(g_mschandle);
|
||||
g_mschandle = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_composite0_connect
|
||||
*
|
||||
* Description:
|
||||
* Connect the USB composite device on the specified USB device port for
|
||||
* configuration 0.
|
||||
*
|
||||
* Input Parameters:
|
||||
* port - The USB device port.
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL handle value is returned on success. NULL is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static FAR void *board_composite0_connect(int port)
|
||||
{
|
||||
/* Here we are composing the configuration of the usb composite device.
|
||||
*
|
||||
* The standard is to use one CDC/ACM and one USB mass storage device.
|
||||
*/
|
||||
|
||||
struct composite_devdesc_s dev[2];
|
||||
int ifnobase = 0;
|
||||
int strbase = COMPOSITE_NSTRIDS;
|
||||
|
||||
/* Configure the CDC/ACM device */
|
||||
|
||||
/* Ask the cdcacm driver to fill in the constants we didn't
|
||||
* know here.
|
||||
*/
|
||||
|
||||
cdcacm_get_composite_devdesc(&dev[0]);
|
||||
|
||||
/* Overwrite and correct some values... */
|
||||
/* The callback functions for the CDC/ACM class */
|
||||
|
||||
dev[0].classobject = cdcacm_classobject;
|
||||
dev[0].uninitialize = cdcacm_uninitialize;
|
||||
|
||||
/* Interfaces */
|
||||
|
||||
dev[0].devdesc.ifnobase = ifnobase; /* Offset to Interface-IDs */
|
||||
dev[0].minor = 0; /* The minor interface number */
|
||||
|
||||
/* Strings */
|
||||
|
||||
dev[0].devdesc.strbase = strbase; /* Offset to String Numbers */
|
||||
|
||||
/* Endpoints */
|
||||
|
||||
dev[0].devdesc.epno[CDCACM_EP_INTIN_IDX] = 1;
|
||||
dev[0].devdesc.epno[CDCACM_EP_BULKIN_IDX] = 2;
|
||||
dev[0].devdesc.epno[CDCACM_EP_BULKOUT_IDX] = 3;
|
||||
|
||||
/* Count up the base numbers */
|
||||
|
||||
ifnobase += dev[0].devdesc.ninterfaces;
|
||||
strbase += dev[0].devdesc.nstrings;
|
||||
|
||||
/* Configure the mass storage device device */
|
||||
/* Ask the usbmsc driver to fill in the constants we didn't
|
||||
* know here.
|
||||
*/
|
||||
|
||||
usbmsc_get_composite_devdesc(&dev[1]);
|
||||
|
||||
/* Overwrite and correct some values... */
|
||||
/* The callback functions for the USBMSC class */
|
||||
|
||||
dev[1].classobject = board_mscclassobject;
|
||||
dev[1].uninitialize = board_mscuninitialize;
|
||||
|
||||
/* Interfaces */
|
||||
|
||||
dev[1].devdesc.ifnobase = ifnobase; /* Offset to Interface-IDs */
|
||||
dev[1].minor = 0; /* The minor interface number */
|
||||
|
||||
/* Strings */
|
||||
|
||||
dev[1].devdesc.strbase = strbase; /* Offset to String Numbers */
|
||||
|
||||
/* Endpoints */
|
||||
|
||||
dev[1].devdesc.epno[USBMSC_EP_BULKIN_IDX] = 5;
|
||||
dev[1].devdesc.epno[USBMSC_EP_BULKOUT_IDX] = 4;
|
||||
|
||||
/* Count up the base numbers */
|
||||
|
||||
ifnobase += dev[1].devdesc.ninterfaces;
|
||||
strbase += dev[1].devdesc.nstrings;
|
||||
|
||||
return composite_initialize(2, dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_composite1_connect
|
||||
*
|
||||
* Description:
|
||||
* Connect the USB composite device on the specified USB device port for
|
||||
* configuration 1.
|
||||
*
|
||||
* Input Parameters:
|
||||
* port - The USB device port.
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL handle value is returned on success. NULL is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static FAR void *board_composite1_connect(int port)
|
||||
{
|
||||
/* REVISIT: This configuration currently fails. stm32_epallocpma() fails
|
||||
* allocate a buffer for the 6th endpoint. Currenlty it supports 7x64 byte
|
||||
* buffers, two required for EP0, leaving only buffers for 5 additional
|
||||
* endpoints.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
struct composite_devdesc_s dev[2];
|
||||
int strbase = COMPOSITE_NSTRIDS;
|
||||
int ifnobase = 0;
|
||||
int epno;
|
||||
int i;
|
||||
|
||||
for (i = 0, epno = 1; i < 2; i++)
|
||||
{
|
||||
/* Ask the cdcacm driver to fill in the constants we didn't know here */
|
||||
|
||||
cdcacm_get_composite_devdesc(&dev[i]);
|
||||
|
||||
/* Overwrite and correct some values... */
|
||||
/* The callback functions for the CDC/ACM class */
|
||||
|
||||
dev[i].classobject = cdcacm_classobject;
|
||||
dev[i].uninitialize = cdcacm_uninitialize;
|
||||
|
||||
dev[i].minor = i; /* The minor interface number */
|
||||
|
||||
/* Interfaces */
|
||||
|
||||
dev[i].devdesc.ifnobase = ifnobase; /* Offset to Interface-IDs */
|
||||
|
||||
/* Strings */
|
||||
|
||||
dev[i].devdesc.strbase = strbase; /* Offset to String Numbers */
|
||||
|
||||
/* Endpoints */
|
||||
|
||||
dev[i].devdesc.epno[CDCACM_EP_INTIN_IDX] = epno++;
|
||||
dev[i].devdesc.epno[CDCACM_EP_BULKIN_IDX] = epno++;
|
||||
dev[i].devdesc.epno[CDCACM_EP_BULKOUT_IDX] = epno++;
|
||||
|
||||
ifnobase += dev[i].devdesc.ninterfaces;
|
||||
strbase += dev[i].devdesc.nstrings;
|
||||
}
|
||||
|
||||
return composite_initialize(2, dev);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -117,17 +397,16 @@ int board_composite_initialize(int port)
|
|||
|
||||
/* Now bind the SPI interface to the MMC/SD driver */
|
||||
|
||||
syslog(LOG_INFO, "Bind SPI to the MMC/SD driver, minor=%d slot=%d\n",
|
||||
CONFIG_SYSTEM_COMPOSITE_DEVMINOR1, OLIMEXINO_STM32_MMCSDSLOTNO);
|
||||
syslog(LOG_INFO, "Bind SPI to the MMC/SD driver, minor=0 slot=%d\n",
|
||||
OLIMEXINO_STM32_MMCSDSLOTNO);
|
||||
|
||||
ret = mmcsd_spislotinitialize(CONFIG_SYSTEM_COMPOSITE_DEVMINOR1,
|
||||
OLIMEXINO_STM32_MMCSDSLOTNO, spi);
|
||||
ret = mmcsd_spislotinitialize(0, OLIMEXINO_STM32_MMCSDSLOTNO, spi);
|
||||
if (ret != OK)
|
||||
{
|
||||
syslog(LOG_ERR,
|
||||
"ERROR: Failed to bind SPI port %d to MMC/SD minor=%d slot=%d %d\n",
|
||||
OLIMEXINO_STM32_MMCSDSPIPORTNO, CONFIG_SYSTEM_COMPOSITE_DEVMINOR1,
|
||||
OLIMEXINO_STM32_MMCSDSLOTNO, ret);
|
||||
"ERROR: Failed to bind SPI port %d to MMC/SD minor=0 slot=%d %d\n",
|
||||
OLIMEXINO_STM32_MMCSDSPIPORTNO, OLIMEXINO_STM32_MMCSDSLOTNO,
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -135,4 +414,43 @@ int board_composite_initialize(int port)
|
|||
|
||||
return OK;
|
||||
}
|
||||
#endif /* CONFIG_STM32_SPI */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_composite_connect
|
||||
*
|
||||
* Description:
|
||||
* Connect the USB composite device on the specified USB device port using
|
||||
* the specified configuration. The interpretation of the configid is
|
||||
* board specific.
|
||||
*
|
||||
* Input Parameters:
|
||||
* port - The USB device port.
|
||||
* configid - The USB composite configuration
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL handle value is returned on success. NULL is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR void *board_composite_connect(int port, int configid)
|
||||
{
|
||||
if (configid == 0)
|
||||
{
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
return board_composite0_connect(port);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
else if (configid == 1)
|
||||
{
|
||||
return board_composite1_connect(port);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BOARDCTL_USBDEVCTRL && CONFIG_USBDEV_COMPOSITE */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* configs/samv71-xult/src/sam_composite.c
|
||||
*
|
||||
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2016, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -40,11 +40,123 @@
|
|||
#include <nuttx/config.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <nuttx/usb/usbdev.h>
|
||||
#include <nuttx/usb/cdcacm.h>
|
||||
#include <nuttx/usb/usbmsc.h>
|
||||
#include <nuttx/usb/composite.h>
|
||||
|
||||
#include "samv71-xult.h"
|
||||
|
||||
#ifdef CONFIG_USBDEV_COMPOSITE
|
||||
#if defined(CONFIG_BOARDCTL_USBDEVCTRL) && defined(CONFIG_USBDEV_COMPOSITE)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static FAR void *g_mschandle;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_mscclassobject
|
||||
*
|
||||
* Description:
|
||||
* If the mass storage class driver is part of composite device, then
|
||||
* its instantiation and configuration is a multi-step, board-specific,
|
||||
* process (See comments for usbmsc_configure below). In this case,
|
||||
* board-specific logic must provide board_mscclassobject().
|
||||
*
|
||||
* board_mscclassobject() is called from the composite driver. It must
|
||||
* encapsulate the instantiation and configuration of the mass storage
|
||||
* class and the return the mass storage device's class driver instance
|
||||
* to the composite driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* classdev - The location to return the mass storage class' device
|
||||
* instance.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static int board_mscclassobject(int minor,
|
||||
FAR struct usbdev_description_s *devdesc,
|
||||
FAR struct usbdevclass_driver_s **classdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(g_mschandle == NULL);
|
||||
|
||||
/* Configure the mass storage device */
|
||||
|
||||
uinfo("Configuring with NLUNS=1\n");
|
||||
ret = usbmsc_configure(1, &g_mschandle);
|
||||
if (ret < 0)
|
||||
{
|
||||
uerr("ERROR: usbmsc_configure failed: %d\n", -ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uinfo("MSC handle=%p\n", g_mschandle);
|
||||
|
||||
/* Bind the LUN(s) */
|
||||
|
||||
uinfo("Bind LUN=0 to /dev/mmcsd0\n");
|
||||
ret = usbmsc_bindlun(g_mschandle, "/dev/mmcsd0", 0, 0, 0, false);
|
||||
if (ret < 0)
|
||||
{
|
||||
uerr("ERROR: usbmsc_bindlun failed for LUN 1 at /dev/mmcsd0: %d\n",
|
||||
ret);
|
||||
usbmsc_uninitialize(g_mschandle);
|
||||
g_mschandle = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get the mass storage device's class object */
|
||||
|
||||
ret = usbmsc_classobject(g_mschandle, devdesc, classdev);
|
||||
if (ret < 0)
|
||||
{
|
||||
uerr("ERROR: usbmsc_classobject failed: %d\n", -ret);
|
||||
usbmsc_uninitialize(g_mschandle);
|
||||
g_mschandle = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_mscuninitialize
|
||||
*
|
||||
* Description:
|
||||
* Un-initialize the USB storage class driver. This is just an application-
|
||||
* specific wrapper aboutn usbmsc_unitialize() that is called form the
|
||||
* composite device logic.
|
||||
*
|
||||
* Input Parameters:
|
||||
* classdev - The class driver instrance previously give to the composite
|
||||
* driver by board_mscclassobject().
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static void board_mscuninitialize(FAR struct usbdevclass_driver_s *classdev)
|
||||
{
|
||||
DEBUGASSERT(g_mschandle != NULL);
|
||||
usbmsc_uninitialize(g_mschandle);
|
||||
g_mschandle = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
|
@ -63,4 +175,176 @@ int board_composite_initialize(int port)
|
|||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_USBDEV_COMPOSITE */
|
||||
/****************************************************************************
|
||||
* Name: board_composite_connect
|
||||
*
|
||||
* Description:
|
||||
* Connect the USB composite device on the specified USB device port using
|
||||
* the specified configuration. The interpretation of the configid is
|
||||
* board specific.
|
||||
*
|
||||
* Input Parameters:
|
||||
* port - The USB device port.
|
||||
* configid - The USB composite configuration
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL handle value is returned on success. NULL is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR void *board_composite_connect(int port, int configid)
|
||||
{
|
||||
/* Here we are composing the configuration of the usb composite device.
|
||||
*
|
||||
* The standard is to use one CDC/ACM and one USB mass storage device.
|
||||
*/
|
||||
|
||||
if (configid == 0)
|
||||
{
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
struct composite_devdesc_s dev[2];
|
||||
int ifnobase = 0;
|
||||
int strbase = COMPOSITE_NSTRIDS;
|
||||
|
||||
/* Configure the CDC/ACM device */
|
||||
|
||||
/* Ask the cdcacm driver to fill in the constants we didn't
|
||||
* know here.
|
||||
*/
|
||||
|
||||
cdcacm_get_composite_devdesc(&dev[0]);
|
||||
|
||||
/* Overwrite and correct some values... */
|
||||
/* The callback functions for the CDC/ACM class */
|
||||
|
||||
dev[0].classobject = cdcacm_classobject;
|
||||
dev[0].uninitialize = cdcacm_uninitialize;
|
||||
|
||||
/* Interfaces */
|
||||
|
||||
dev[0].devdesc.ifnobase = ifnobase; /* Offset to Interface-IDs */
|
||||
dev[0].minor = 0; /* The minor interface number */
|
||||
|
||||
/* Strings */
|
||||
|
||||
dev[0].devdesc.strbase = strbase; /* Offset to String Numbers */
|
||||
|
||||
/* Endpoints */
|
||||
|
||||
dev[0].devdesc.epno[CDCACM_EP_INTIN_IDX] = 3;
|
||||
dev[0].devdesc.epno[CDCACM_EP_BULKIN_IDX] = 4;
|
||||
dev[0].devdesc.epno[CDCACM_EP_BULKOUT_IDX] = 5;
|
||||
|
||||
/* Count up the base numbers */
|
||||
|
||||
ifnobase += dev[0].devdesc.ninterfaces;
|
||||
strbase += dev[0].devdesc.nstrings;
|
||||
|
||||
/* Configure the mass storage device device */
|
||||
/* Ask the usbmsc driver to fill in the constants we didn't
|
||||
* know here.
|
||||
*/
|
||||
|
||||
usbmsc_get_composite_devdesc(&dev[1]);
|
||||
|
||||
/* Overwrite and correct some values... */
|
||||
/* The callback functions for the USBMSC class */
|
||||
|
||||
dev[1].classobject = board_mscclassobject;
|
||||
dev[1].uninitialize = board_mscuninitialize;
|
||||
|
||||
/* Interfaces */
|
||||
|
||||
dev[1].devdesc.ifnobase = ifnobase; /* Offset to Interface-IDs */
|
||||
dev[1].minor = 0; /* The minor interface number */
|
||||
|
||||
/* Strings */
|
||||
|
||||
dev[1].devdesc.strbase = strbase; /* Offset to String Numbers */
|
||||
|
||||
/* Endpoints */
|
||||
|
||||
dev[1].devdesc.epno[USBMSC_EP_BULKIN_IDX] = 1;
|
||||
dev[1].devdesc.epno[USBMSC_EP_BULKOUT_IDX] = 2;
|
||||
|
||||
/* Count up the base numbers */
|
||||
|
||||
ifnobase += dev[1].devdesc.ninterfaces;
|
||||
strbase += dev[1].devdesc.nstrings;
|
||||
|
||||
return composite_initialize(2, dev);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Configuration with three CDC/ACMs
|
||||
*
|
||||
* This configuration can be used e.g. on a samv71-xult. The samv71 has
|
||||
* 10 Endpoints (EPs). The EPs 0 up to 7 are DMA aware. The EPs 8 and 9
|
||||
* are not.
|
||||
*
|
||||
* In a composite device we need the EP0 as an control Endpoint. Each
|
||||
* CDC/ACM needs one Interrupt driven and two bulk Endpoints. This is
|
||||
* why we configure the EPs 7, 8 and 9 to be the IRQ-EPs and the
|
||||
* EP-Pairs 1/2, 3/4, 5/6 to be the bulk EPs for each device.
|
||||
*
|
||||
* This means, that
|
||||
*
|
||||
* - the Composite device uses EP0 as the control-Endpoint,
|
||||
* - the CDC/ACM 0 uses EP7, EP1 and EP2,
|
||||
* - the CDC/ACM 1 uses EP8, EP3 and EP4,
|
||||
* - the CDC/ACM 2 uses EP9, EP5 and EP6
|
||||
*
|
||||
* as its EP-Configuration.
|
||||
*/
|
||||
|
||||
else if (configid == 1)
|
||||
{
|
||||
struct composite_devdesc_s dev[3];
|
||||
int strbase = COMPOSITE_NSTRIDS;
|
||||
int ifnobase = 0;
|
||||
int ia;
|
||||
|
||||
for (ia = 0; ia < 3; ia++)
|
||||
{
|
||||
/* Ask the cdcacm driver to fill in the constants we didn't know here */
|
||||
|
||||
cdcacm_get_composite_devdesc(&dev[ia]);
|
||||
|
||||
/* Overwrite and correct some values... */
|
||||
/* The callback functions for the CDC/ACM class */
|
||||
|
||||
dev[ia].classobject = cdcacm_classobject;
|
||||
dev[ia].uninitialize = cdcacm_uninitialize;
|
||||
|
||||
dev[ia].minor = ia; /* The minor interface number */
|
||||
|
||||
/* Interfaces */
|
||||
|
||||
dev[ia].devdesc.ifnobase = ifnobase; /* Offset to Interface-IDs */
|
||||
|
||||
/* Strings */
|
||||
|
||||
dev[ia].devdesc.strbase = strbase; /* Offset to String Numbers */
|
||||
|
||||
/* Endpoints */
|
||||
|
||||
dev[ia].devdesc.epno[CDCACM_EP_INTIN_IDX] = 7 + ia;
|
||||
dev[ia].devdesc.epno[CDCACM_EP_BULKIN_IDX] = 1 + ia * 2;
|
||||
dev[ia].devdesc.epno[CDCACM_EP_BULKOUT_IDX] = 2 + ia * 2;
|
||||
|
||||
ifnobase += dev[ia].devdesc.ninterfaces;
|
||||
strbase += dev[ia].devdesc.nstrings;
|
||||
}
|
||||
|
||||
return composite_initialize(3, dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BOARDCTL_USBDEVCTRL && CONFIG_USBDEV_COMPOSITE */
|
||||
|
|
|
@ -68,10 +68,6 @@ ifeq ($(CONFIG_USBMSC),y)
|
|||
CSRCS += stm32_usbmsc.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USBDEV_COMPOSITE),y)
|
||||
CSRCS += stm32_composite.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CAN),y)
|
||||
CSRCS += stm32_can.c
|
||||
endif
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
/****************************************************************************
|
||||
* configs/shenzhou/src/stm32_composite.c
|
||||
*
|
||||
* Copyright (C) 2012, 2016 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Configure and register the STM32 SPI-based MMC/SD block driver.
|
||||
*
|
||||
* 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 <nuttx/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shenzhou.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
/* Device minor number */
|
||||
|
||||
#ifndef CONFIG_SYSTEM_COMPOSITE_DEVMINOR1
|
||||
# define CONFIG_SYSTEM_COMPOSITE_DEVMINOR1 0
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_composite_initialize
|
||||
*
|
||||
* Description:
|
||||
* Perform architecture specific initialization of a composite USB device.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int board_composite_initialize(int port)
|
||||
{
|
||||
/* If system/composite is built as an NSH command, then SD slot should
|
||||
* already have been initialized in board_app_initialize() (see
|
||||
* stm32_appinit.c). In this case, there is nothing further to be done here.
|
||||
*
|
||||
* NOTE: CONFIG_NSH_BUILTIN_APPS is not a fool-proof indication that NSH
|
||||
* was built.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_NSH_BUILTIN_APPS
|
||||
return sd_mount(CONFIG_SYSTEM_COMPOSITE_DEVMINOR1);
|
||||
#else
|
||||
return OK;
|
||||
#endif /* CONFIG_NSH_BUILTIN_APPS */
|
||||
}
|
|
@ -98,8 +98,6 @@ CONFIG_STM32_SPI_DMA=y
|
|||
CONFIG_STM32_USART2=y
|
||||
CONFIG_STM32_USB=y
|
||||
CONFIG_SYMTAB_ORDEREDBYNAME=y
|
||||
CONFIG_SYSTEM_COMPOSITE_DEVPATH1="/dev/mtdblock0"
|
||||
CONFIG_SYSTEM_COMPOSITE_DEVPATH2="/dev/mtdblock1"
|
||||
CONFIG_SYSTEM_COMPOSITE=y
|
||||
CONFIG_TASK_NAME_SIZE=7
|
||||
CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=768
|
||||
|
@ -110,8 +108,6 @@ CONFIG_USBDEV_COMPOSITE=y
|
|||
CONFIG_USBDEV_TRACE_NRECORDS=32
|
||||
CONFIG_USBDEV_TRACE=y
|
||||
CONFIG_USBMSC_COMPOSITE=y
|
||||
CONFIG_USBMSC_EPBULKIN=5
|
||||
CONFIG_USBMSC_EPBULKOUT=4
|
||||
CONFIG_USBMSC_NRDREQS=2
|
||||
CONFIG_USBMSC_NWRREQS=2
|
||||
CONFIG_USBMSC_SCSI_STACKSIZE=340
|
||||
|
|
|
@ -54,6 +54,11 @@
|
|||
# include <sys/mount.h>
|
||||
#endif
|
||||
|
||||
#include <nuttx/usb/usbdev.h>
|
||||
#include <nuttx/usb/cdcacm.h>
|
||||
#include <nuttx/usb/usbmsc.h>
|
||||
#include <nuttx/usb/composite.h>
|
||||
|
||||
#ifdef CONFIG_USBMONITOR
|
||||
# include <nuttx/usb/usbmonitor.h>
|
||||
#endif
|
||||
|
@ -65,6 +70,8 @@
|
|||
#include "stm32.h"
|
||||
#include "spark.h"
|
||||
|
||||
#if defined(CONFIG_BOARDCTL_USBDEVCTRL) && defined(CONFIG_USBDEV_COMPOSITE)
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
@ -116,6 +123,14 @@
|
|||
# undef HAVE_USBMONITOR
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static FAR void *g_mschandle;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
@ -280,6 +295,270 @@ static int stm32_composite_initialize(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_mscclassobject
|
||||
*
|
||||
* Description:
|
||||
* If the mass storage class driver is part of composite device, then
|
||||
* its instantiation and configuration is a multi-step, board-specific,
|
||||
* process (See comments for usbmsc_configure below). In this case,
|
||||
* board-specific logic must provide board_mscclassobject().
|
||||
*
|
||||
* board_mscclassobject() is called from the composite driver. It must
|
||||
* encapsulate the instantiation and configuration of the mass storage
|
||||
* class and the return the mass storage device's class driver instance
|
||||
* to the composite driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* classdev - The location to return the mass storage class' device
|
||||
* instance.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static int board_mscclassobject(int minor,
|
||||
FAR struct usbdev_description_s *devdesc,
|
||||
FAR struct usbdevclass_driver_s **classdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(g_mschandle == NULL);
|
||||
|
||||
/* Configure the mass storage device */
|
||||
|
||||
uinfo("Configuring with NLUNS=1\n");
|
||||
ret = usbmsc_configure(1, &g_mschandle);
|
||||
if (ret < 0)
|
||||
{
|
||||
uerr("ERROR: usbmsc_configure failed: %d\n", -ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uinfo("MSC handle=%p\n", g_mschandle);
|
||||
|
||||
/* Bind the LUN(s) */
|
||||
|
||||
uinfo("Bind LUN=0 to /dev/mtdblock0\n");
|
||||
ret = usbmsc_bindlun(g_mschandle, "/dev/mtdblock0", 0, 0, 0, false);
|
||||
if (ret < 0)
|
||||
{
|
||||
uerr("ERROR: usbmsc_bindlun failed for LUN 1 at /dev/mtdblock0: %d\n",
|
||||
ret);
|
||||
usbmsc_uninitialize(g_mschandle);
|
||||
g_mschandle = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get the mass storage device's class object */
|
||||
|
||||
ret = usbmsc_classobject(g_mschandle, devdesc, classdev);
|
||||
if (ret < 0)
|
||||
{
|
||||
uerr("ERROR: usbmsc_classobject failed: %d\n", -ret);
|
||||
usbmsc_uninitialize(g_mschandle);
|
||||
g_mschandle = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_mscuninitialize
|
||||
*
|
||||
* Description:
|
||||
* Un-initialize the USB storage class driver. This is just an application-
|
||||
* specific wrapper aboutn usbmsc_unitialize() that is called form the
|
||||
* composite device logic.
|
||||
*
|
||||
* Input Parameters:
|
||||
* classdev - The class driver instrance previously give to the composite
|
||||
* driver by board_mscclassobject().
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static void board_mscuninitialize(FAR struct usbdevclass_driver_s *classdev)
|
||||
{
|
||||
DEBUGASSERT(g_mschandle != NULL);
|
||||
usbmsc_uninitialize(g_mschandle);
|
||||
g_mschandle = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_composite0_connect
|
||||
*
|
||||
* Description:
|
||||
* Connect the USB composite device on the specified USB device port for
|
||||
* configuration 0.
|
||||
*
|
||||
* Input Parameters:
|
||||
* port - The USB device port.
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL handle value is returned on success. NULL is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static FAR void *board_composite0_connect(int port)
|
||||
{
|
||||
/* Here we are composing the configuration of the usb composite device.
|
||||
*
|
||||
* The standard is to use one CDC/ACM and one USB mass storage device.
|
||||
*/
|
||||
|
||||
struct composite_devdesc_s dev[2];
|
||||
int ifnobase = 0;
|
||||
int strbase = COMPOSITE_NSTRIDS;
|
||||
|
||||
/* Configure the CDC/ACM device */
|
||||
|
||||
/* Ask the cdcacm driver to fill in the constants we didn't
|
||||
* know here.
|
||||
*/
|
||||
|
||||
cdcacm_get_composite_devdesc(&dev[0]);
|
||||
|
||||
/* Overwrite and correct some values... */
|
||||
/* The callback functions for the CDC/ACM class */
|
||||
|
||||
dev[0].classobject = cdcacm_classobject;
|
||||
dev[0].uninitialize = cdcacm_uninitialize;
|
||||
|
||||
/* Interfaces */
|
||||
|
||||
dev[0].devdesc.ifnobase = ifnobase; /* Offset to Interface-IDs */
|
||||
dev[0].minor = 0; /* The minor interface number */
|
||||
|
||||
/* Strings */
|
||||
|
||||
dev[0].devdesc.strbase = strbase; /* Offset to String Numbers */
|
||||
|
||||
/* Endpoints */
|
||||
|
||||
dev[0].devdesc.epno[CDCACM_EP_INTIN_IDX] = 1;
|
||||
dev[0].devdesc.epno[CDCACM_EP_BULKIN_IDX] = 2;
|
||||
dev[0].devdesc.epno[CDCACM_EP_BULKOUT_IDX] = 3;
|
||||
|
||||
/* Count up the base numbers */
|
||||
|
||||
ifnobase += dev[0].devdesc.ninterfaces;
|
||||
strbase += dev[0].devdesc.nstrings;
|
||||
|
||||
/* Configure the mass storage device device */
|
||||
/* Ask the usbmsc driver to fill in the constants we didn't
|
||||
* know here.
|
||||
*/
|
||||
|
||||
usbmsc_get_composite_devdesc(&dev[1]);
|
||||
|
||||
/* Overwrite and correct some values... */
|
||||
/* The callback functions for the USBMSC class */
|
||||
|
||||
dev[1].classobject = board_mscclassobject;
|
||||
dev[1].uninitialize = board_mscuninitialize;
|
||||
|
||||
/* Interfaces */
|
||||
|
||||
dev[1].devdesc.ifnobase = ifnobase; /* Offset to Interface-IDs */
|
||||
dev[1].minor = 0; /* The minor interface number */
|
||||
|
||||
/* Strings */
|
||||
|
||||
dev[1].devdesc.strbase = strbase; /* Offset to String Numbers */
|
||||
|
||||
/* Endpoints */
|
||||
|
||||
dev[1].devdesc.epno[USBMSC_EP_BULKIN_IDX] = 5;
|
||||
dev[1].devdesc.epno[USBMSC_EP_BULKOUT_IDX] = 4;
|
||||
|
||||
/* Count up the base numbers */
|
||||
|
||||
ifnobase += dev[1].devdesc.ninterfaces;
|
||||
strbase += dev[1].devdesc.nstrings;
|
||||
|
||||
return composite_initialize(2, dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_composite1_connect
|
||||
*
|
||||
* Description:
|
||||
* Connect the USB composite device on the specified USB device port for
|
||||
* configuration 1.
|
||||
*
|
||||
* Input Parameters:
|
||||
* port - The USB device port.
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL handle value is returned on success. NULL is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static FAR void *board_composite1_connect(int port)
|
||||
{
|
||||
/* REVISIT: This configuration currently fails. stm32_epallocpma() fails
|
||||
* allocate a buffer for the 6th endpoint. Currenlty it supports 7x64 byte
|
||||
* buffers, two required for EP0, leaving only buffers for 5 additional
|
||||
* endpoints.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
struct composite_devdesc_s dev[2];
|
||||
int strbase = COMPOSITE_NSTRIDS;
|
||||
int ifnobase = 0;
|
||||
int epno;
|
||||
int i;
|
||||
|
||||
for (i = 0, epno = 1; i < 2; i++)
|
||||
{
|
||||
/* Ask the cdcacm driver to fill in the constants we didn't know here */
|
||||
|
||||
cdcacm_get_composite_devdesc(&dev[i]);
|
||||
|
||||
/* Overwrite and correct some values... */
|
||||
/* The callback functions for the CDC/ACM class */
|
||||
|
||||
dev[i].classobject = cdcacm_classobject;
|
||||
dev[i].uninitialize = cdcacm_uninitialize;
|
||||
|
||||
dev[i].minor = i; /* The minor interface number */
|
||||
|
||||
/* Interfaces */
|
||||
|
||||
dev[i].devdesc.ifnobase = ifnobase; /* Offset to Interface-IDs */
|
||||
|
||||
/* Strings */
|
||||
|
||||
dev[i].devdesc.strbase = strbase; /* Offset to String Numbers */
|
||||
|
||||
/* Endpoints */
|
||||
|
||||
dev[i].devdesc.epno[CDCACM_EP_INTIN_IDX] = epno++;
|
||||
dev[i].devdesc.epno[CDCACM_EP_BULKIN_IDX] = epno++;
|
||||
dev[i].devdesc.epno[CDCACM_EP_BULKOUT_IDX] = epno++;
|
||||
|
||||
ifnobase += dev[i].devdesc.ninterfaces;
|
||||
strbase += dev[i].devdesc.nstrings;
|
||||
}
|
||||
|
||||
return composite_initialize(2, dev);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -300,3 +579,43 @@ int board_composite_initialize(int port)
|
|||
return stm32_composite_initialize();
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_composite_connect
|
||||
*
|
||||
* Description:
|
||||
* Connect the USB composite device on the specified USB device port using
|
||||
* the specified configuration. The interpretation of the configid is
|
||||
* board specific.
|
||||
*
|
||||
* Input Parameters:
|
||||
* port - The USB device port.
|
||||
* configid - The USB composite configuration
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL handle value is returned on success. NULL is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR void *board_composite_connect(int port, int configid)
|
||||
{
|
||||
if (configid == 0)
|
||||
{
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
return board_composite0_connect(port);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
else if (configid == 1)
|
||||
{
|
||||
return board_composite1_connect(port);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BOARDCTL_USBDEVCTRL && CONFIG_USBDEV_COMPOSITE */
|
||||
|
|
|
@ -58,11 +58,8 @@ CONFIG_USBDEV_COMPOSITE=y
|
|||
CONFIG_USBMSC_BULKINREQLEN=256
|
||||
CONFIG_USBMSC_BULKOUTREQLEN=256
|
||||
CONFIG_USBMSC_COMPOSITE=y
|
||||
CONFIG_USBMSC_EPBULKIN=5
|
||||
CONFIG_USBMSC_EPBULKOUT=4
|
||||
CONFIG_USBMSC_NRDREQS=2
|
||||
CONFIG_USBMSC_NWRREQS=2
|
||||
CONFIG_USBMSC_PRODUCTSTR="USBdev Storage"
|
||||
CONFIG_USBMSC_REMOVABLE=y
|
||||
CONFIG_USBMSC_VERSIONNO=0x0399
|
||||
CONFIG_USBMSC=y
|
||||
|
|
|
@ -48,22 +48,23 @@
|
|||
#include <nuttx/sdio.h>
|
||||
#include <nuttx/mmcsd.h>
|
||||
#include <nuttx/board.h>
|
||||
#include <nuttx/usb/usbdev.h>
|
||||
#include <nuttx/usb/cdcacm.h>
|
||||
#include <nuttx/usb/usbmsc.h>
|
||||
#include <nuttx/usb/composite.h>
|
||||
|
||||
#include "stm32.h"
|
||||
|
||||
/* There is nothing to do here if SDIO support is not selected. */
|
||||
|
||||
#if defined(CONFIG_STM32_SDIO) && defined(CONFIG_USBDEV_COMPOSITE)
|
||||
#if defined(CONFIG_BOARDCTL_USBDEVCTRL) && defined(CONFIG_USBDEV_COMPOSITE)
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Configuration ************************************************************/
|
||||
/* No SDIO? Then no USB MSC device in composite */
|
||||
|
||||
#ifndef CONFIG_SYSTEM_COMPOSITE_DEVMINOR1
|
||||
# define CONFIG_SYSTEM_COMPOSITE_DEVMINOR1 0
|
||||
#ifndef CONFIG_STM32_SDIO
|
||||
# undef CONFIG_USBMSC_COMPOSITE
|
||||
#endif
|
||||
|
||||
/* SLOT number(s) could depend on the board configuration */
|
||||
|
@ -76,6 +77,282 @@
|
|||
# error "Unrecognized STM32 board"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static FAR void *g_mschandle;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_mscclassobject
|
||||
*
|
||||
* Description:
|
||||
* If the mass storage class driver is part of composite device, then
|
||||
* its instantiation and configuration is a multi-step, board-specific,
|
||||
* process (See comments for usbmsc_configure below). In this case,
|
||||
* board-specific logic must provide board_mscclassobject().
|
||||
*
|
||||
* board_mscclassobject() is called from the composite driver. It must
|
||||
* encapsulate the instantiation and configuration of the mass storage
|
||||
* class and the return the mass storage device's class driver instance
|
||||
* to the composite driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* classdev - The location to return the mass storage class' device
|
||||
* instance.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static int board_mscclassobject(int minor,
|
||||
FAR struct usbdev_description_s *devdesc,
|
||||
FAR struct usbdevclass_driver_s **classdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(g_mschandle == NULL);
|
||||
|
||||
/* Configure the mass storage device */
|
||||
|
||||
uinfo("Configuring with NLUNS=1\n");
|
||||
ret = usbmsc_configure(1, &g_mschandle);
|
||||
if (ret < 0)
|
||||
{
|
||||
uerr("ERROR: usbmsc_configure failed: %d\n", -ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uinfo("MSC handle=%p\n", g_mschandle);
|
||||
|
||||
/* Bind the LUN(s) */
|
||||
|
||||
uinfo("Bind LUN=0 to /dev/mmcsd0\n");
|
||||
ret = usbmsc_bindlun(g_mschandle, "/dev/mmcsd0", 0, 0, 0, false);
|
||||
if (ret < 0)
|
||||
{
|
||||
uerr("ERROR: usbmsc_bindlun failed for LUN 1 at /dev/mmcsd0: %d\n",
|
||||
ret);
|
||||
usbmsc_uninitialize(g_mschandle);
|
||||
g_mschandle = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get the mass storage device's class object */
|
||||
|
||||
ret = usbmsc_classobject(g_mschandle, devdesc, classdev);
|
||||
if (ret < 0)
|
||||
{
|
||||
uerr("ERROR: usbmsc_classobject failed: %d\n", -ret);
|
||||
usbmsc_uninitialize(g_mschandle);
|
||||
g_mschandle = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_mscuninitialize
|
||||
*
|
||||
* Description:
|
||||
* Un-initialize the USB storage class driver. This is just an application-
|
||||
* specific wrapper aboutn usbmsc_unitialize() that is called form the
|
||||
* composite device logic.
|
||||
*
|
||||
* Input Parameters:
|
||||
* classdev - The class driver instrance previously give to the composite
|
||||
* driver by board_mscclassobject().
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static void board_mscuninitialize(FAR struct usbdevclass_driver_s *classdev)
|
||||
{
|
||||
DEBUGASSERT(g_mschandle != NULL);
|
||||
usbmsc_uninitialize(g_mschandle);
|
||||
g_mschandle = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_composite0_connect
|
||||
*
|
||||
* Description:
|
||||
* Connect the USB composite device on the specified USB device port for
|
||||
* configuration 0.
|
||||
*
|
||||
* Input Parameters:
|
||||
* port - The USB device port.
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL handle value is returned on success. NULL is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
static FAR void *board_composite0_connect(int port)
|
||||
{
|
||||
/* Here we are composing the configuration of the usb composite device.
|
||||
*
|
||||
* The standard is to use one CDC/ACM and one USB mass storage device.
|
||||
*/
|
||||
|
||||
struct composite_devdesc_s dev[2];
|
||||
int ifnobase = 0;
|
||||
int strbase = COMPOSITE_NSTRIDS;
|
||||
|
||||
/* Configure the CDC/ACM device */
|
||||
|
||||
/* Ask the cdcacm driver to fill in the constants we didn't
|
||||
* know here.
|
||||
*/
|
||||
|
||||
cdcacm_get_composite_devdesc(&dev[0]);
|
||||
|
||||
/* Overwrite and correct some values... */
|
||||
/* The callback functions for the CDC/ACM class */
|
||||
|
||||
dev[0].classobject = cdcacm_classobject;
|
||||
dev[0].uninitialize = cdcacm_uninitialize;
|
||||
|
||||
/* Interfaces */
|
||||
|
||||
dev[0].devdesc.ifnobase = ifnobase; /* Offset to Interface-IDs */
|
||||
dev[0].minor = 0; /* The minor interface number */
|
||||
|
||||
/* Strings */
|
||||
|
||||
dev[0].devdesc.strbase = strbase; /* Offset to String Numbers */
|
||||
|
||||
/* Endpoints */
|
||||
|
||||
dev[0].devdesc.epno[CDCACM_EP_INTIN_IDX] = 1;
|
||||
dev[0].devdesc.epno[CDCACM_EP_BULKIN_IDX] = 2;
|
||||
dev[0].devdesc.epno[CDCACM_EP_BULKOUT_IDX] = 3;
|
||||
|
||||
/* Count up the base numbers */
|
||||
|
||||
ifnobase += dev[0].devdesc.ninterfaces;
|
||||
strbase += dev[0].devdesc.nstrings;
|
||||
|
||||
/* Configure the mass storage device device */
|
||||
/* Ask the usbmsc driver to fill in the constants we didn't
|
||||
* know here.
|
||||
*/
|
||||
|
||||
usbmsc_get_composite_devdesc(&dev[1]);
|
||||
|
||||
/* Overwrite and correct some values... */
|
||||
/* The callback functions for the USBMSC class */
|
||||
|
||||
dev[1].classobject = board_mscclassobject;
|
||||
dev[1].uninitialize = board_mscuninitialize;
|
||||
|
||||
/* Interfaces */
|
||||
|
||||
dev[1].devdesc.ifnobase = ifnobase; /* Offset to Interface-IDs */
|
||||
dev[1].minor = 0; /* The minor interface number */
|
||||
|
||||
/* Strings */
|
||||
|
||||
dev[1].devdesc.strbase = strbase; /* Offset to String Numbers */
|
||||
|
||||
/* Endpoints */
|
||||
|
||||
dev[1].devdesc.epno[USBMSC_EP_BULKIN_IDX] = 5;
|
||||
dev[1].devdesc.epno[USBMSC_EP_BULKOUT_IDX] = 4;
|
||||
|
||||
/* Count up the base numbers */
|
||||
|
||||
ifnobase += dev[1].devdesc.ninterfaces;
|
||||
strbase += dev[1].devdesc.nstrings;
|
||||
|
||||
return composite_initialize(2, dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_composite1_connect
|
||||
*
|
||||
* Description:
|
||||
* Connect the USB composite device on the specified USB device port for
|
||||
* configuration 1.
|
||||
*
|
||||
* Input Parameters:
|
||||
* port - The USB device port.
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL handle value is returned on success. NULL is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static FAR void *board_composite1_connect(int port)
|
||||
{
|
||||
/* REVISIT: This configuration currently fails. stm32_epallocpma() fails
|
||||
* allocate a buffer for the 6th endpoint. Currenlty it supports 7x64 byte
|
||||
* buffers, two required for EP0, leaving only buffers for 5 additional
|
||||
* endpoints.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
struct composite_devdesc_s dev[2];
|
||||
int strbase = COMPOSITE_NSTRIDS;
|
||||
int ifnobase = 0;
|
||||
int epno;
|
||||
int i;
|
||||
|
||||
for (i = 0, epno = 1; i < 2; i++)
|
||||
{
|
||||
/* Ask the cdcacm driver to fill in the constants we didn't know here */
|
||||
|
||||
cdcacm_get_composite_devdesc(&dev[i]);
|
||||
|
||||
/* Overwrite and correct some values... */
|
||||
/* The callback functions for the CDC/ACM class */
|
||||
|
||||
dev[i].classobject = cdcacm_classobject;
|
||||
dev[i].uninitialize = cdcacm_uninitialize;
|
||||
|
||||
dev[i].minor = i; /* The minor interface number */
|
||||
|
||||
/* Interfaces */
|
||||
|
||||
dev[i].devdesc.ifnobase = ifnobase; /* Offset to Interface-IDs */
|
||||
|
||||
/* Strings */
|
||||
|
||||
dev[i].devdesc.strbase = strbase; /* Offset to String Numbers */
|
||||
|
||||
/* Endpoints */
|
||||
|
||||
dev[i].devdesc.epno[CDCACM_EP_INTIN_IDX] = epno++;
|
||||
dev[i].devdesc.epno[CDCACM_EP_BULKIN_IDX] = epno++;
|
||||
dev[i].devdesc.epno[CDCACM_EP_BULKOUT_IDX] = epno++;
|
||||
|
||||
ifnobase += dev[i].devdesc.ninterfaces;
|
||||
strbase += dev[i].devdesc.nstrings;
|
||||
}
|
||||
|
||||
return composite_initialize(2, dev);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -116,10 +393,9 @@ int board_composite_initialize(int port)
|
|||
|
||||
/* Now bind the SDIO interface to the MMC/SD driver */
|
||||
|
||||
syslog(LOG_INFO, "Bind SDIO to the MMC/SD driver, minor=%d\n",
|
||||
CONFIG_SYSTEM_COMPOSITE_DEVMINOR1);
|
||||
syslog(LOG_INFO, "Bind SDIO to the MMC/SD driver, minor=0\n");
|
||||
|
||||
ret = mmcsd_slotinitialize(CONFIG_SYSTEM_COMPOSITE_DEVMINOR1, sdio);
|
||||
ret = mmcsd_slotinitialize(0, sdio);
|
||||
if (ret != OK)
|
||||
{
|
||||
syslog(LOG_ERR,
|
||||
|
@ -142,4 +418,42 @@ int board_composite_initialize(int port)
|
|||
return OK;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_STM32_SDIO && CONFIG_USBDEV_COMPOSITE */
|
||||
/****************************************************************************
|
||||
* Name: board_composite_connect
|
||||
*
|
||||
* Description:
|
||||
* Connect the USB composite device on the specified USB device port using
|
||||
* the specified configuration. The interpretation of the configid is
|
||||
* board specific.
|
||||
*
|
||||
* Input Parameters:
|
||||
* port - The USB device port.
|
||||
* configid - The USB composite configuration
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL handle value is returned on success. NULL is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR void *board_composite_connect(int port, int configid)
|
||||
{
|
||||
if (configid == 0)
|
||||
{
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
return board_composite0_connect(port);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
else if (configid == 1)
|
||||
{
|
||||
return board_composite1_connect(port);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BOARDCTL_USBDEVCTRL && CONFIG_USBDEV_COMPOSITE */
|
||||
|
|
|
@ -322,33 +322,10 @@ menuconfig CDCACM_COMPOSITE
|
|||
Configure the CDC serial driver as part of a composite driver
|
||||
(only if USBDEV_COMPOSITE is also defined)
|
||||
|
||||
if CDCACM_COMPOSITE
|
||||
if !CDCACM_COMPOSITE
|
||||
|
||||
config CDCACM_IFNOBASE
|
||||
int "Offset the CDC/ACM interface numbers"
|
||||
default 0
|
||||
---help---
|
||||
If the CDC driver is part of a composite device, then this may need to
|
||||
be defined to offset the CDC/ACM interface numbers so that they are
|
||||
unique and contiguous. When used with the Mass Storage driver, the
|
||||
correct value for this offset is zero.
|
||||
|
||||
config CDCACM_STRBASE
|
||||
int "Offset the CDC/ACM string numbers"
|
||||
default 4
|
||||
---help---
|
||||
If the CDC driver is part of a composite device, then this may need to
|
||||
be defined to offset the CDC/ACM string numbers so that they are
|
||||
unique and contiguous. When used with the Mass Storage driver, the
|
||||
correct value for this offset is four (this value actuallly only needs
|
||||
to be defined if names are provided for the Notification interface,
|
||||
config CDCACM_NOTIFSTR, or the data interface, CDCACM_DATAIFSTR).
|
||||
|
||||
The default of four accounts for strings IDs 0-3 used by the composite
|
||||
descriptors. Any additional CDC/ACM string descripts must then begin
|
||||
with string index four.
|
||||
|
||||
endif
|
||||
# In a composite device the EP0 config comes from the composite device
|
||||
# and the EP-Number is configured dynamically via composite_initialize
|
||||
|
||||
config CDCACM_EP0MAXPACKET
|
||||
int "Endpoint 0 max packet size"
|
||||
|
@ -363,6 +340,8 @@ config CDCACM_EPINTIN
|
|||
The logical 7-bit address of a hardware endpoint that supports
|
||||
interrupt IN operation. Default 1.
|
||||
|
||||
endif
|
||||
|
||||
config CDCACM_EPINTIN_FSSIZE
|
||||
int "Interupt IN full speed MAXPACKET size"
|
||||
default 64
|
||||
|
@ -377,6 +356,11 @@ config CDCACM_EPINTIN_HSSIZE
|
|||
Max package size for the interrupt IN endpoint if high speed mode.
|
||||
Default 64.
|
||||
|
||||
if !CDCACM_COMPOSITE
|
||||
|
||||
# In a composite device the EP-Number is configured dynamically via
|
||||
# composite_initialize
|
||||
|
||||
config CDCACM_EPBULKOUT
|
||||
int "Bulk OUT endpoint number"
|
||||
default 3
|
||||
|
@ -384,6 +368,8 @@ config CDCACM_EPBULKOUT
|
|||
The logical 7-bit address of a hardware endpoint that supports
|
||||
bulk OUT operation. Default: 3
|
||||
|
||||
endif
|
||||
|
||||
config CDCACM_EPBULKOUT_FSSIZE
|
||||
int "Bulk OUT full speed MAXPACKET size"
|
||||
default 64
|
||||
|
@ -398,6 +384,11 @@ config CDCACM_EPBULKOUT_HSSIZE
|
|||
Max package size for the bulk OUT endpoint if high speed mode.
|
||||
Default 512.
|
||||
|
||||
if !CDCACM_COMPOSITE
|
||||
|
||||
# In a composite device the EP-Number is configured dynamically via
|
||||
# composite_initialize
|
||||
|
||||
config CDCACM_EPBULKIN
|
||||
int "Bulk IN endpoint number"
|
||||
default 2
|
||||
|
@ -405,6 +396,8 @@ config CDCACM_EPBULKIN
|
|||
The logical 7-bit address of a hardware endpoint that supports
|
||||
bulk IN operation. Default: 2
|
||||
|
||||
endif
|
||||
|
||||
config CDCACM_EPBULKIN_FSSIZE
|
||||
int "Bulk IN full speed MAXPACKET size"
|
||||
default 64
|
||||
|
@ -468,6 +461,11 @@ config CDCACM_TXBUFSIZE
|
|||
will hold one request of size 768; a buffer size of 193 will hold
|
||||
two requests of size 96 bytes.
|
||||
|
||||
if !CDCACM_COMPOSITE
|
||||
|
||||
# In a composite device the Vendor- and Product-ID is given by the composite
|
||||
# device
|
||||
|
||||
config CDCACM_VENDORID
|
||||
hex "Vendor ID"
|
||||
default 0x0525
|
||||
|
@ -493,6 +491,7 @@ config CDCACM_PRODUCTSTR
|
|||
string "Product string"
|
||||
default "CDC/ACM Serial"
|
||||
|
||||
endif # !CDCACM_COMPOSITE
|
||||
endif # CDCACM
|
||||
|
||||
menuconfig USBMSC
|
||||
|
@ -530,38 +529,17 @@ config USBMSC_COMPOSITE
|
|||
Configure the mass storage driver as part of a composite driver
|
||||
(only if USBDEV_COMPOSITE is also defined)
|
||||
|
||||
config USBMSC_IFNOBASE
|
||||
int "Offset the mass storage interface number"
|
||||
default 2
|
||||
depends on USBMSC_COMPOSITE
|
||||
---help---
|
||||
If the CDC driver is part of a composite device, then this may need to
|
||||
be defined to offset the mass storage interface number so that it is
|
||||
unique and contiguous. When used with the CDC/ACM driver, the
|
||||
correct value for this offset is two (because of the two CDC/ACM
|
||||
interfaces that will precede it).
|
||||
|
||||
config USBMSC_STRBASE
|
||||
int "Offset the mass storage string numbers"
|
||||
default 4
|
||||
depends on USBMSC_COMPOSITE
|
||||
---help---
|
||||
If the CDC driver is part of a composite device, then this may need to
|
||||
be defined to offset the mass storage string numbers so that they are
|
||||
unique and contiguous. When used with the CDC/ACM driver, the
|
||||
correct value for this offset is four (or perhaps 5 or 6, depending
|
||||
on if CDCACM_NOTIFSTR or CDCACM_DATAIFSTR are defined).
|
||||
|
||||
String IDS 0-3 are used by the composite descriptors. This amount
|
||||
may need to be incremented to account for string IDs used by other
|
||||
members of the composite.
|
||||
|
||||
config USBMSC_EP0MAXPACKET
|
||||
int "Max packet size for endpoint 0"
|
||||
default 64
|
||||
---help---
|
||||
Max packet size for endpoint 0
|
||||
|
||||
if !USBMSC_COMPOSITE
|
||||
|
||||
# In a composite device the EP-Number and STR-Number is configured
|
||||
# dynamically via composite_initialize
|
||||
|
||||
config USBMSC_EPBULKOUT
|
||||
int "Bulk OUT endpoint number"
|
||||
default 2
|
||||
|
@ -576,6 +554,8 @@ config USBMSC_EPBULKIN
|
|||
The logical 7-bit address of a hardware endpoints that support
|
||||
bulk OUT and IN operations
|
||||
|
||||
endif
|
||||
|
||||
config USBMSC_NWRREQS
|
||||
int "The number of write requests that can be in flight"
|
||||
default 4
|
||||
|
@ -613,6 +593,11 @@ config USBMSC_BULKOUTREQLEN
|
|||
beyond the maximum size of one packet. Default: 512 or 64 bytes
|
||||
(depending upon if dual speed operation is supported or not).
|
||||
|
||||
if !USBMSC_COMPOSITE
|
||||
|
||||
# In a composite device the Vendor- and Product-IDs are handled by the
|
||||
# composite device
|
||||
|
||||
config USBMSC_VENDORID
|
||||
hex "Mass storage Vendor ID"
|
||||
default 0x584e
|
||||
|
@ -638,6 +623,8 @@ config USBMSC_PRODUCTSTR
|
|||
string "Mass storage product string"
|
||||
default "Mass Storage"
|
||||
|
||||
endif # !USBMSC_COMPOSITE
|
||||
|
||||
config USBMSC_VERSIONNO
|
||||
hex "USB MSC Version Number"
|
||||
default "0x399"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* drivers/usbdev/cdcacm.c
|
||||
*
|
||||
* Copyright (C) 2011-2013, 2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011-2013, 2016-2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -64,7 +64,7 @@
|
|||
|
||||
#include "cdcacm.h"
|
||||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
#ifdef CONFIG_CDCACM_COMPOSITE
|
||||
# include <nuttx/usb/composite.h>
|
||||
# include "composite.h"
|
||||
#endif
|
||||
|
@ -105,6 +105,8 @@ struct cdcacm_dev_s
|
|||
FAR struct usbdev_req_s *ctrlreq; /* Allocated control request */
|
||||
struct sq_queue_s reqlist; /* List of write request containers */
|
||||
|
||||
struct usbdev_description_s devdesc;
|
||||
|
||||
/* Pre-allocated write request containers. The write requests will
|
||||
* be linked in a free list (reqlist), and used to send requests to
|
||||
* EPBULKIN; Read requests will be queued in the EBULKOUT.
|
||||
|
@ -157,10 +159,10 @@ static void cdcacm_freereq(FAR struct usbdev_ep_s *ep,
|
|||
/* Configuration ***********************************************************/
|
||||
|
||||
static void cdcacm_resetconfig(FAR struct cdcacm_dev_s *priv);
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
static int cdcacm_epconfigure(FAR struct usbdev_ep_s *ep,
|
||||
enum cdcacm_epdesc_e epid, uint16_t mxpacket, bool last);
|
||||
#endif
|
||||
enum cdcacm_epdesc_e epid, bool last,
|
||||
FAR struct usbdev_description_s *devdesc,
|
||||
bool hispeed);
|
||||
static int cdcacm_setconfig(FAR struct cdcacm_dev_s *priv,
|
||||
uint8_t config);
|
||||
|
||||
|
@ -211,6 +213,7 @@ static bool cdcuart_txempty(FAR struct uart_dev_s *dev);
|
|||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* USB class device *********************************************************/
|
||||
|
||||
static const struct usbdevclass_driverops_s g_driverops =
|
||||
|
@ -275,7 +278,8 @@ static const struct uart_ops_s g_uartops =
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint16_t cdcacm_fillrequest(FAR struct cdcacm_dev_s *priv, uint8_t *reqbuf,
|
||||
static uint16_t cdcacm_fillrequest(FAR struct cdcacm_dev_s *priv,
|
||||
FAR uint8_t *reqbuf,
|
||||
uint16_t reqlen)
|
||||
{
|
||||
FAR uart_dev_t *serdev = &priv->serdev;
|
||||
|
@ -287,7 +291,9 @@ static uint16_t cdcacm_fillrequest(FAR struct cdcacm_dev_s *priv, uint8_t *reqbu
|
|||
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Transfer bytes while we have bytes available and there is room in the request */
|
||||
/* Transfer bytes while we have bytes available and there is room in the
|
||||
* request.
|
||||
*/
|
||||
|
||||
while (xmit->head != xmit->tail && nbytes < reqlen)
|
||||
{
|
||||
|
@ -302,8 +308,8 @@ static uint16_t cdcacm_fillrequest(FAR struct cdcacm_dev_s *priv, uint8_t *reqbu
|
|||
}
|
||||
}
|
||||
|
||||
/* When all of the characters have been sent from the buffer
|
||||
* disable the "TX interrupt".
|
||||
/* When all of the characters have been sent from the buffer disable the
|
||||
* "TX interrupt".
|
||||
*/
|
||||
|
||||
if (xmit->head == xmit->tail)
|
||||
|
@ -311,8 +317,8 @@ static uint16_t cdcacm_fillrequest(FAR struct cdcacm_dev_s *priv, uint8_t *reqbu
|
|||
uart_disabletxint(serdev);
|
||||
}
|
||||
|
||||
/* If any bytes were removed from the buffer, inform any waiters
|
||||
* there there is space available.
|
||||
/* If any bytes were removed from the buffer, inform any waiters that
|
||||
* there is space available.
|
||||
*/
|
||||
|
||||
if (nbytes)
|
||||
|
@ -329,9 +335,9 @@ static uint16_t cdcacm_fillrequest(FAR struct cdcacm_dev_s *priv, uint8_t *reqbu
|
|||
*
|
||||
* Description:
|
||||
* This function obtains write requests, transfers the TX data into the
|
||||
* request, and submits the requests to the USB controller. This continues
|
||||
* until either (1) there are no further packets available, or (2) there is
|
||||
* no further data to send.
|
||||
* request, and submits the requests to the USB controller. This
|
||||
* continues until either (1) there are no further packets available, or
|
||||
* (2) there is no further data to send.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
@ -359,9 +365,9 @@ static int cdcacm_sndpacket(FAR struct cdcacm_dev_s *priv)
|
|||
|
||||
ep = priv->epbulkin;
|
||||
|
||||
/* Loop until either (1) we run out or write requests, or (2) cdcacm_fillrequest()
|
||||
* is unable to fill the request with data (i.e., until there is no more data
|
||||
* to be sent).
|
||||
/* Loop until either (1) we run out or write requests, or (2)
|
||||
* cdcacm_fillrequest() is unable to fill the request with data (i.e.,
|
||||
* until there is no more data to be sent).
|
||||
*/
|
||||
|
||||
uinfo("head=%d tail=%d nwrq=%d empty=%d\n",
|
||||
|
@ -425,7 +431,7 @@ static int cdcacm_sndpacket(FAR struct cdcacm_dev_s *priv)
|
|||
****************************************************************************/
|
||||
|
||||
static inline int cdcacm_recvpacket(FAR struct cdcacm_dev_s *priv,
|
||||
uint8_t *reqbuf, uint16_t reqlen)
|
||||
FAR uint8_t *reqbuf, uint16_t reqlen)
|
||||
{
|
||||
FAR uart_dev_t *serdev = &priv->serdev;
|
||||
FAR struct uart_buffer_s *recv = &serdev->recv;
|
||||
|
@ -436,11 +442,12 @@ static inline int cdcacm_recvpacket(FAR struct cdcacm_dev_s *priv,
|
|||
uinfo("head=%d tail=%d nrdq=%d reqlen=%d\n",
|
||||
priv->serdev.recv.head, priv->serdev.recv.tail, priv->nrdq, reqlen);
|
||||
|
||||
/* Get the next head index. During the time that RX interrupts are disabled, the
|
||||
* the serial driver will be extracting data from the circular buffer and modifying
|
||||
* recv.tail. During this time, we should avoid modifying recv.head; Instead we will
|
||||
* use a shadow copy of the index. When interrupts are restored, the real recv.head
|
||||
* will be updated with this index.
|
||||
/* Get the next head index. During the time that RX interrupts are
|
||||
* disabled, the the serial driver will be extracting data from the
|
||||
* circular buffer and modifying recv.tail. During this time, we should
|
||||
* avoid modifying recv.head; Instead we will use a shadow copy of the
|
||||
* index. When interrupts are restored, the real recv.head will be
|
||||
* updated with this index.
|
||||
*/
|
||||
|
||||
if (priv->rxenabled)
|
||||
|
@ -452,9 +459,9 @@ static inline int cdcacm_recvpacket(FAR struct cdcacm_dev_s *priv,
|
|||
currhead = priv->rxhead;
|
||||
}
|
||||
|
||||
/* Pre-calculate the head index and check for wrap around. We need to do this
|
||||
* so that we can determine if the circular buffer will overrun BEFORE we
|
||||
* overrun the buffer!
|
||||
/* Pre-calculate the head index and check for wrap around. We need to do
|
||||
* this so that we can determine if the circular buffer will overrun
|
||||
* BEFORE we overrun the buffer!
|
||||
*/
|
||||
|
||||
nexthead = currhead + 1;
|
||||
|
@ -463,17 +470,17 @@ static inline int cdcacm_recvpacket(FAR struct cdcacm_dev_s *priv,
|
|||
nexthead = 0;
|
||||
}
|
||||
|
||||
/* Then copy data into the RX buffer until either: (1) all of the data has been
|
||||
* copied, or (2) the RX buffer is full.
|
||||
/* Then copy data into the RX buffer until either: (1) all of the data has
|
||||
* been copied, or (2) the RX buffer is full.
|
||||
*
|
||||
* NOTE: If the RX buffer becomes full, then we have overrun the serial driver
|
||||
* and data will be lost. This is the correct behavior for a proper emulation
|
||||
* of a serial link. It should not NAK, it should drop data like a physical
|
||||
* serial port.
|
||||
* NOTE: If the RX buffer becomes full, then we have overrun the serial
|
||||
* driver and data will be lost. This is the correct behavior for a
|
||||
* proper emulation of a serial link. It should not NAK, it should drop
|
||||
* data like a physical serial port.
|
||||
*
|
||||
* If you don't like that behavior. DO NOT change it here. Instead, you should
|
||||
* finish the implementation of RX flow control which is the only proper way
|
||||
* to throttle a serial device.
|
||||
* If you don't like that behavior. DO NOT change it here. Instead, you
|
||||
* should finish the implementation of RX flow control which is the only
|
||||
* proper way to throttle a serial device.
|
||||
*/
|
||||
|
||||
while (nexthead != recv->tail && nbytes < reqlen)
|
||||
|
@ -527,6 +534,7 @@ static inline int cdcacm_recvpacket(FAR struct cdcacm_dev_s *priv,
|
|||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RXOVERRUN), 0);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
@ -575,6 +583,7 @@ static void cdcacm_freereq(FAR struct usbdev_ep_s *ep,
|
|||
{
|
||||
EP_FREEBUFFER(ep, req->buf);
|
||||
}
|
||||
|
||||
EP_FREEREQ(ep, req);
|
||||
}
|
||||
}
|
||||
|
@ -623,16 +632,15 @@ static void cdcacm_resetconfig(FAR struct cdcacm_dev_s *priv)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
static int cdcacm_epconfigure(FAR struct usbdev_ep_s *ep,
|
||||
enum cdcacm_epdesc_e epid, uint16_t mxpacket,
|
||||
bool last)
|
||||
enum cdcacm_epdesc_e epid, bool last,
|
||||
FAR struct usbdev_description_s *devdesc,
|
||||
bool hispeed)
|
||||
{
|
||||
struct usb_epdesc_s epdesc;
|
||||
cdcacm_mkepdesc(epid, mxpacket, &epdesc);
|
||||
cdcacm_copy_epdesc(epid, &epdesc, devdesc, hispeed);
|
||||
return EP_CONFIGURE(ep, &epdesc, last);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_setconfig
|
||||
|
@ -690,14 +698,14 @@ static int cdcacm_setconfig(FAR struct cdcacm_dev_s *priv, uint8_t config)
|
|||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
if (priv->usbdev->speed == USB_SPEED_HIGH)
|
||||
{
|
||||
ret = cdcacm_epconfigure(priv->epintin, CDCACM_EPINTIN,
|
||||
CONFIG_CDCACM_EPINTIN_HSSIZE, false);
|
||||
ret = cdcacm_epconfigure(priv->epintin, CDCACM_EPINTIN, false,
|
||||
&priv->devdesc, true);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret = EP_CONFIGURE(priv->epintin,
|
||||
cdcacm_getepdesc(CDCACM_EPINTIN), false);
|
||||
ret = cdcacm_epconfigure(priv->epintin, CDCACM_EPINTIN, false,
|
||||
&priv->devdesc, false);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
|
@ -713,14 +721,14 @@ static int cdcacm_setconfig(FAR struct cdcacm_dev_s *priv, uint8_t config)
|
|||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
if (priv->usbdev->speed == USB_SPEED_HIGH)
|
||||
{
|
||||
ret = cdcacm_epconfigure(priv->epbulkin, CDCACM_EPBULKIN,
|
||||
CONFIG_CDCACM_EPBULKIN_HSSIZE, false);
|
||||
ret = cdcacm_epconfigure(priv->epbulkin, CDCACM_EPBULKIN, false,
|
||||
&priv->devdesc, true);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret = EP_CONFIGURE(priv->epbulkin,
|
||||
cdcacm_getepdesc(CDCACM_EPBULKIN), false);
|
||||
ret = cdcacm_epconfigure(priv->epbulkin, CDCACM_EPBULKIN, false,
|
||||
&priv->devdesc, false);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
|
@ -736,14 +744,14 @@ static int cdcacm_setconfig(FAR struct cdcacm_dev_s *priv, uint8_t config)
|
|||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
if (priv->usbdev->speed == USB_SPEED_HIGH)
|
||||
{
|
||||
ret = cdcacm_epconfigure(priv->epbulkout, CDCACM_EPBULKOUT,
|
||||
CONFIG_CDCACM_EPBULKOUT_HSSIZE, true);
|
||||
ret = cdcacm_epconfigure(priv->epbulkout, CDCACM_EPBULKOUT, true,
|
||||
&priv->devdesc, true);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret = EP_CONFIGURE(priv->epbulkout,
|
||||
cdcacm_getepdesc(CDCACM_EPBULKOUT), true);
|
||||
ret = cdcacm_epconfigure(priv->epbulkout, CDCACM_EPBULKOUT, true,
|
||||
&priv->devdesc, false);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
|
@ -764,7 +772,8 @@ static int cdcacm_setconfig(FAR struct cdcacm_dev_s *priv, uint8_t config)
|
|||
ret = EP_SUBMIT(priv->epbulkout, req);
|
||||
if (ret != OK)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT), (uint16_t)-ret);
|
||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT),
|
||||
(uint16_t)-ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
|
@ -852,7 +861,8 @@ static void cdcacm_rdcomplete(FAR struct usbdev_ep_s *ep,
|
|||
return;
|
||||
|
||||
default: /* Some other error occurred */
|
||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDUNEXPECTED), (uint16_t)-req->result);
|
||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDUNEXPECTED),
|
||||
(uint16_t)-req->result);
|
||||
break;
|
||||
};
|
||||
|
||||
|
@ -862,7 +872,8 @@ static void cdcacm_rdcomplete(FAR struct usbdev_ep_s *ep,
|
|||
ret = EP_SUBMIT(ep, req);
|
||||
if (ret != OK)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT), (uint16_t)-req->result);
|
||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RDSUBMIT),
|
||||
(uint16_t)-req->result);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
@ -927,7 +938,8 @@ static void cdcacm_wrcomplete(FAR struct usbdev_ep_s *ep,
|
|||
|
||||
default: /* Some other error occurred */
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_WRUNEXPECTED), (uint16_t)-req->result);
|
||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_WRUNEXPECTED),
|
||||
(uint16_t)-req->result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -967,7 +979,7 @@ static int cdcacm_bind(FAR struct usbdevclass_driver_s *driver,
|
|||
* EP0).
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
dev->ep0->priv = priv;
|
||||
#endif
|
||||
|
||||
|
@ -992,7 +1004,8 @@ static int cdcacm_bind(FAR struct usbdevclass_driver_s *driver,
|
|||
|
||||
/* Pre-allocate the IN interrupt endpoint */
|
||||
|
||||
priv->epintin = DEV_ALLOCEP(dev, CDCACM_EPINTIN_ADDR, true, USB_EP_ATTR_XFER_INT);
|
||||
priv->epintin = DEV_ALLOCEP(dev, CDCACM_MKEPINTIN(&priv->devdesc),
|
||||
true, USB_EP_ATTR_XFER_INT);
|
||||
if (!priv->epintin)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPINTINALLOCFAIL), 0);
|
||||
|
@ -1004,7 +1017,8 @@ static int cdcacm_bind(FAR struct usbdevclass_driver_s *driver,
|
|||
|
||||
/* Pre-allocate the IN bulk endpoint */
|
||||
|
||||
priv->epbulkin = DEV_ALLOCEP(dev, CDCACM_EPINBULK_ADDR, true, USB_EP_ATTR_XFER_BULK);
|
||||
priv->epbulkin = DEV_ALLOCEP(dev, CDCACM_MKEPBULKIN(&priv->devdesc),
|
||||
true, USB_EP_ATTR_XFER_BULK);
|
||||
if (!priv->epbulkin)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPBULKINALLOCFAIL), 0);
|
||||
|
@ -1016,7 +1030,8 @@ static int cdcacm_bind(FAR struct usbdevclass_driver_s *driver,
|
|||
|
||||
/* Pre-allocate the OUT bulk endpoint */
|
||||
|
||||
priv->epbulkout = DEV_ALLOCEP(dev, CDCACM_EPOUTBULK_ADDR, false, USB_EP_ATTR_XFER_BULK);
|
||||
priv->epbulkout = DEV_ALLOCEP(dev, CDCACM_MKEPBULKOUT(&priv->devdesc),
|
||||
false, USB_EP_ATTR_XFER_BULK);
|
||||
if (!priv->epbulkout)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPBULKOUTALLOCFAIL), 0);
|
||||
|
@ -1205,6 +1220,7 @@ static void cdcacm_unbind(FAR struct usbdevclass_driver_s *driver,
|
|||
|
||||
flags = enter_critical_section();
|
||||
DEBUGASSERT(priv->nwrq == CONFIG_CDCACM_NWRREQS);
|
||||
|
||||
while (!sq_empty(&priv->reqlist))
|
||||
{
|
||||
reqcontainer = (struct cdcacm_req_s *)sq_remfirst(&priv->reqlist);
|
||||
|
@ -1274,6 +1290,7 @@ static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
ctrlreq = priv->ctrlreq;
|
||||
|
||||
/* Extract the little-endian 16-bit values to host order */
|
||||
|
@ -1287,23 +1304,24 @@ static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
|
||||
if ((ctrl->type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_STANDARD)
|
||||
{
|
||||
/***********************************************************************
|
||||
/**********************************************************************
|
||||
* Standard Requests
|
||||
***********************************************************************/
|
||||
**********************************************************************/
|
||||
|
||||
switch (ctrl->req)
|
||||
{
|
||||
case USB_REQ_GETDESCRIPTOR:
|
||||
{
|
||||
/* The value field specifies the descriptor type in the MS byte and the
|
||||
* descriptor index in the LS byte (order is little endian)
|
||||
/* The value field specifies the descriptor type in the MS byte
|
||||
* and the descriptor index in the LS byte (order is little
|
||||
* endian)
|
||||
*/
|
||||
|
||||
switch (ctrl->value[1])
|
||||
{
|
||||
/* If the serial device is used in as part of a composite device,
|
||||
* then the device descriptor is provided by logic in the composite
|
||||
* device implementation.
|
||||
/* If the serial device is used in as part of a composite
|
||||
* device, then the device descriptor is provided by logic in
|
||||
* the composite device implementation.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
|
@ -1315,9 +1333,9 @@ static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
break;
|
||||
#endif
|
||||
|
||||
/* If the serial device is used in as part of a composite device,
|
||||
* then the device qualifier descriptor is provided by logic in the
|
||||
* composite device implementation.
|
||||
/* If the serial device is used in as part of a composite
|
||||
* device, then the device qualifier descriptor is provided by
|
||||
* logic in the composite device implementation.
|
||||
*/
|
||||
|
||||
#if !defined(CONFIG_CDCACM_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED)
|
||||
|
@ -1331,26 +1349,27 @@ static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
case USB_DESC_TYPE_OTHERSPEEDCONFIG:
|
||||
#endif
|
||||
|
||||
/* If the serial device is used in as part of a composite device,
|
||||
* then the configuration descriptor is provided by logic in the
|
||||
* composite device implementation.
|
||||
/* If the serial device is used in as part of a composite
|
||||
* device, then the configuration descriptor is provided by
|
||||
* logic in the composite device implementation.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
case USB_DESC_TYPE_CONFIG:
|
||||
{
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
ret = cdcacm_mkcfgdesc(ctrlreq->buf, dev->speed, ctrl->req);
|
||||
ret = cdcacm_mkcfgdesc(ctrlreq->buf, dev->speed,
|
||||
ctrl->req);
|
||||
#else
|
||||
ret = cdcacm_mkcfgdesc(ctrlreq->buf);
|
||||
ret = cdcacm_mkcfgdesc(ctrlreq->buf, 0);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* If the serial device is used in as part of a composite device,
|
||||
* then the language string descriptor is provided by logic in the
|
||||
* composite device implementation.
|
||||
/* If the serial device is used in as part of a composite
|
||||
* device, then the language string descriptor is provided by
|
||||
* logic in the composite device implementation.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
|
@ -1358,7 +1377,10 @@ static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
{
|
||||
/* index == language code. */
|
||||
|
||||
ret = cdcacm_mkstrdesc(ctrl->value[0], (struct usb_strdesc_s *)ctrlreq->buf);
|
||||
ret =
|
||||
cdcacm_mkstrdesc(ctrl->value[0],
|
||||
(FAR struct usb_strdesc_s *)
|
||||
ctrlreq->buf);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
@ -1403,8 +1425,10 @@ static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
if (ctrl->type == USB_REQ_RECIPIENT_INTERFACE &&
|
||||
priv->config == CDCACM_CONFIGID)
|
||||
{
|
||||
if ((index == CDCACM_NOTIFID && value == CDCACM_NOTALTIFID) ||
|
||||
(index == CDCACM_DATAIFID && value == CDCACM_DATAALTIFID))
|
||||
if ((index == priv->devdesc.ifnobase &&
|
||||
value == CDCACM_NOTALTIFID) ||
|
||||
(index == (priv->devdesc.ifnobase + 1) &&
|
||||
value == CDCACM_DATAALTIFID))
|
||||
{
|
||||
cdcacm_resetconfig(priv);
|
||||
cdcacm_setconfig(priv, priv->config);
|
||||
|
@ -1419,8 +1443,10 @@ static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
if (ctrl->type == (USB_DIR_IN | USB_REQ_RECIPIENT_INTERFACE) &&
|
||||
priv->config == CDCACM_CONFIGIDNONE)
|
||||
{
|
||||
if ((index == CDCACM_NOTIFID && value == CDCACM_NOTALTIFID) ||
|
||||
(index == CDCACM_DATAIFID && value == CDCACM_DATAALTIFID))
|
||||
if ((index == priv->devdesc.ifnobase &&
|
||||
value == CDCACM_NOTALTIFID) ||
|
||||
(index == (priv->devdesc.ifnobase + 1) &&
|
||||
value == CDCACM_DATAALTIFID))
|
||||
{
|
||||
*(FAR uint8_t *) ctrlreq->buf = value;
|
||||
ret = 1;
|
||||
|
@ -1441,29 +1467,33 @@ static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
|
||||
else if ((ctrl->type & USB_REQ_TYPE_MASK) == USB_REQ_TYPE_CLASS)
|
||||
{
|
||||
/***********************************************************************
|
||||
/**********************************************************************
|
||||
* CDC ACM-Specific Requests
|
||||
***********************************************************************/
|
||||
**********************************************************************/
|
||||
|
||||
switch (ctrl->req)
|
||||
{
|
||||
/* ACM_GET_LINE_CODING requests current DTE rate, stop-bits, parity, and
|
||||
* number-of-character bits. (Optional)
|
||||
/* ACM_GET_LINE_CODING requests current DTE rate, stop-bits, parity,
|
||||
* and number-of-character bits. (Optional)
|
||||
*/
|
||||
|
||||
case ACM_GET_LINE_CODING:
|
||||
{
|
||||
if (ctrl->type == (USB_DIR_IN | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE) &&
|
||||
index == CDCACM_NOTIFID)
|
||||
index == priv->devdesc.ifnobase)
|
||||
{
|
||||
/* Return the current line status from the private data structure */
|
||||
/* Return the current line status from the private data
|
||||
* structure.
|
||||
*/
|
||||
|
||||
memcpy(ctrlreq->buf, &priv->linecoding, SIZEOF_CDC_LINECODING);
|
||||
memcpy(ctrlreq->buf, &priv->linecoding,
|
||||
SIZEOF_CDC_LINECODING);
|
||||
ret = SIZEOF_CDC_LINECODING;
|
||||
}
|
||||
else
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UNSUPPORTEDCLASSREQ), ctrl->type);
|
||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_UNSUPPORTEDCLASSREQ),
|
||||
ctrl->type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1476,12 +1506,12 @@ static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
{
|
||||
if (ctrl->type == (USB_DIR_OUT | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE) &&
|
||||
len == SIZEOF_CDC_LINECODING && /* dataout && len == outlen && */
|
||||
index == CDCACM_NOTIFID)
|
||||
index == priv->devdesc.ifnobase)
|
||||
{
|
||||
/* Save the new line coding in the private data structure. NOTE:
|
||||
* that this is conditional now because not all device controller
|
||||
* drivers supported provision of EP0 OUT data with the setup
|
||||
* command.
|
||||
/* Save the new line coding in the private data structure.
|
||||
* NOTE: that this is conditional now because not all device
|
||||
* controller drivers supported provision of EP0 OUT data
|
||||
* with the setup command.
|
||||
*/
|
||||
|
||||
if (dataout && len <= SIZEOF_CDC_LINECODING) /* REVISIT */
|
||||
|
@ -1493,8 +1523,8 @@ static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
|
||||
ret = 0;
|
||||
|
||||
/* If there is a registered callback to receive line status info, then
|
||||
* callout now.
|
||||
/* If there is a registered callback to receive line status
|
||||
* info, then callout now.
|
||||
*/
|
||||
|
||||
if (priv->callback)
|
||||
|
@ -1509,24 +1539,25 @@ static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
}
|
||||
break;
|
||||
|
||||
/* ACM_SET_CTRL_LINE_STATE: RS-232 signal used to tell the DCE device the
|
||||
* DTE device is now present. (Optional)
|
||||
/* ACM_SET_CTRL_LINE_STATE: RS-232 signal used to tell the DCE
|
||||
* device the DTE device is now present. (Optional)
|
||||
*/
|
||||
|
||||
case ACM_SET_CTRL_LINE_STATE:
|
||||
{
|
||||
if (ctrl->type == (USB_DIR_OUT | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE) &&
|
||||
index == CDCACM_NOTIFID)
|
||||
index == priv->devdesc.ifnobase)
|
||||
{
|
||||
/* Save the control line state in the private data structure. Only bits
|
||||
* 0 and 1 have meaning. Respond with a zero length packet.
|
||||
/* Save the control line state in the private data
|
||||
* structure. Only bits 0 and 1 have meaning. Respond with
|
||||
* a zero length packet.
|
||||
*/
|
||||
|
||||
priv->ctrlline = value & 3;
|
||||
ret = 0;
|
||||
|
||||
/* If there is a registered callback to receive control line status info,
|
||||
* then callout now.
|
||||
/* If there is a registered callback to receive control line
|
||||
* status info, then callout now.
|
||||
*/
|
||||
|
||||
if (priv->callback)
|
||||
|
@ -1546,10 +1577,11 @@ static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
case ACM_SEND_BREAK:
|
||||
{
|
||||
if (ctrl->type == (USB_DIR_OUT | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE) &&
|
||||
index == CDCACM_NOTIFID)
|
||||
index == priv->devdesc.ifnobase)
|
||||
{
|
||||
/* If there is a registered callback to handle the SendBreak request,
|
||||
* then callout now. Respond with a zero length packet.
|
||||
/* If there is a registered callback to handle the SendBreak
|
||||
* request, then callout now. Respond with a zero length
|
||||
* packet.
|
||||
*/
|
||||
|
||||
ret = 0;
|
||||
|
@ -1922,9 +1954,9 @@ static int cdcuart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||
|
||||
/* CAIOC_NOTIFY
|
||||
* Send a serial state to the host via the Interrupt IN endpoint.
|
||||
* Argument: int. This includes the current state of the carrier detect,
|
||||
* DSR, break, and ring signal. See "Table 69: UART State Bitmap Values"
|
||||
* and CDC_UART_definitions in include/nuttx/usb/cdc.h.
|
||||
* Argument: int. This includes the current state of the carrier
|
||||
* detect, DSR, break, and ring signal. See "Table 69: UART State
|
||||
* Bitmap Values" and CDC_UART_definitions in include/nuttx/usb/cdc.h.
|
||||
*/
|
||||
|
||||
case CAIOC_NOTIFY:
|
||||
|
@ -1937,7 +1969,8 @@ static int cdcuart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||
* 1. Format and send a request header with:
|
||||
*
|
||||
* bmRequestType:
|
||||
* USB_REQ_DIR_IN | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE
|
||||
* USB_REQ_DIR_IN | USB_REQ_TYPE_CLASS |
|
||||
* USB_REQ_RECIPIENT_INTERFACE
|
||||
* bRequest: ACM_SERIAL_STATE
|
||||
* wValue: 0
|
||||
* wIndex: 0
|
||||
|
@ -2166,6 +2199,7 @@ static void cdcuart_rxint(FAR struct uart_dev_s *dev, bool enable)
|
|||
priv->rxhead = serdev->recv.head;
|
||||
priv->rxenabled = false;
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
|
@ -2312,7 +2346,8 @@ static bool cdcuart_txempty(FAR struct uart_dev_s *dev)
|
|||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
static
|
||||
#endif
|
||||
int cdcacm_classobject(int minor, FAR struct usbdevclass_driver_s **classdev)
|
||||
int cdcacm_classobject(int minor, FAR struct usbdev_description_s *devdesc,
|
||||
FAR struct usbdevclass_driver_s **classdev)
|
||||
{
|
||||
FAR struct cdcacm_alloc_s *alloc;
|
||||
FAR struct cdcacm_dev_s *priv;
|
||||
|
@ -2322,7 +2357,9 @@ int cdcacm_classobject(int minor, FAR struct usbdevclass_driver_s **classdev)
|
|||
|
||||
/* Allocate the structures needed */
|
||||
|
||||
alloc = (FAR struct cdcacm_alloc_s *)kmm_malloc(sizeof(struct cdcacm_alloc_s));
|
||||
alloc = (FAR struct cdcacm_alloc_s *)
|
||||
kmm_malloc(sizeof(struct cdcacm_alloc_s));
|
||||
|
||||
if (!alloc)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_ALLOCDEVSTRUCT), 0);
|
||||
|
@ -2340,6 +2377,8 @@ int cdcacm_classobject(int minor, FAR struct usbdevclass_driver_s **classdev)
|
|||
sq_init(&priv->reqlist);
|
||||
|
||||
priv->minor = minor;
|
||||
memcpy(&priv->devdesc, devdesc,
|
||||
sizeof(struct usbdev_description_s));
|
||||
|
||||
/* Fake line status */
|
||||
|
||||
|
@ -2368,12 +2407,12 @@ int cdcacm_classobject(int minor, FAR struct usbdevclass_driver_s **classdev)
|
|||
/* Initialize the USB class driver structure */
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
drvr->drvr.speed = USB_SPEED_HIGH;
|
||||
drvr->drvr.speed = USB_SPEED_HIGH;
|
||||
#else
|
||||
drvr->drvr.speed = USB_SPEED_FULL;
|
||||
drvr->drvr.speed = USB_SPEED_FULL;
|
||||
#endif
|
||||
drvr->drvr.ops = &g_driverops;
|
||||
drvr->dev = priv;
|
||||
drvr->drvr.ops = &g_driverops;
|
||||
drvr->dev = priv;
|
||||
|
||||
/* Register the USB serial console */
|
||||
|
||||
|
@ -2427,11 +2466,35 @@ errout_with_class:
|
|||
int cdcacm_initialize(int minor, FAR void **handle)
|
||||
{
|
||||
FAR struct usbdevclass_driver_s *drvr = NULL;
|
||||
struct usbdev_description_s devdesc;
|
||||
int ret;
|
||||
|
||||
memset(&devdesc, 0, sizeof(struct usbdev_description_s));
|
||||
|
||||
/* Interfaces.
|
||||
*
|
||||
* ifnobase must be provided by board-specific logic
|
||||
*/
|
||||
|
||||
devdesc.ninterfaces = CDCACM_NINTERFACES; /* Number of interfaces in the configuration */
|
||||
|
||||
/* Strings.
|
||||
*
|
||||
* strbase must be provided by board-specific logic
|
||||
*/
|
||||
|
||||
devdesc.nstrings = CDCACM_NSTRIDS; /* Number of Strings */
|
||||
|
||||
/* Endpoints.
|
||||
*
|
||||
* Endpoint numbers must be provided by board-specific logic.
|
||||
*/
|
||||
|
||||
devdesc.nendpoints = CDCACM_NUM_EPS;
|
||||
|
||||
/* Get an instance of the serial driver class object */
|
||||
|
||||
ret = cdcacm_classobject(minor, &drvr);
|
||||
ret = cdcacm_classobject(minor, &devdesc, &drvr);
|
||||
if (ret == OK)
|
||||
{
|
||||
/* Register the USB serial class driver */
|
||||
|
@ -2439,7 +2502,8 @@ int cdcacm_initialize(int minor, FAR void **handle)
|
|||
ret = usbdev_register(drvr);
|
||||
if (ret < 0)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_DEVREGISTER), (uint16_t)-ret);
|
||||
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_DEVREGISTER),
|
||||
(uint16_t)-ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2470,8 +2534,7 @@ int cdcacm_initialize(int minor, FAR void **handle)
|
|||
* CDC/ACM driver is an internal part of a composite device, or a standalone
|
||||
* USB driver:
|
||||
*
|
||||
* classdev - The class object returned by board_cdcclassobject() or
|
||||
* cdcacm_classobject()
|
||||
* classdev - The class object returned by cdcacm_classobject()
|
||||
* handle - The opaque handle representing the class object returned by
|
||||
* a previous call to cdcacm_initialize().
|
||||
*
|
||||
|
@ -2549,3 +2612,68 @@ void cdcacm_uninitialize(FAR void *handle)
|
|||
priv->minor = (uint8_t)-1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_get_composite_devdesc
|
||||
*
|
||||
* Description:
|
||||
* Helper function to fill in some constants into the composite
|
||||
* configuration struct.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - Pointer to the configuration struct we should fill
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_USBDEV_COMPOSITE) && defined(CONFIG_CDCACM_COMPOSITE)
|
||||
void cdcacm_get_composite_devdesc(struct composite_devdesc_s *dev)
|
||||
{
|
||||
memset(dev, 0, sizeof(struct composite_devdesc_s));
|
||||
|
||||
/* The callback functions for the CDC/ACM class.
|
||||
*
|
||||
* classobject() and uninitialize() must be provided by board-specific
|
||||
* logic
|
||||
*/
|
||||
|
||||
dev->mkconfdesc = cdcacm_mkcfgdesc;
|
||||
dev->mkstrdesc = cdcacm_mkstrdesc;
|
||||
|
||||
dev->nconfigs = CDCACM_NCONFIGS; /* Number of configurations supported */
|
||||
dev->configid = CDCACM_CONFIGID; /* The only supported configuration ID */
|
||||
|
||||
/* Let the construction function calculate the size of the config descriptor */
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
dev->cfgdescsize = cdcacm_mkcfgdesc(NULL, NULL, USB_SPEED_UNKNOWN, 0);
|
||||
#else
|
||||
dev->cfgdescsize = cdcacm_mkcfgdesc(NULL, NULL);
|
||||
#endif
|
||||
|
||||
/* Board-specific logic must provide the device minor */
|
||||
|
||||
/* Interfaces.
|
||||
*
|
||||
* ifnobase must be provided by board-specific logic
|
||||
*/
|
||||
|
||||
dev->devdesc.ninterfaces = CDCACM_NINTERFACES; /* Number of interfaces in the configuration */
|
||||
|
||||
/* Strings.
|
||||
*
|
||||
* strbase must be provided by board-specific logic
|
||||
*/
|
||||
|
||||
dev->devdesc.nstrings = CDCACM_NSTRIDS; /* Number of Strings */
|
||||
|
||||
/* Endpoints.
|
||||
*
|
||||
* Endpoint numbers must be provided by board-specific logic.
|
||||
*/
|
||||
|
||||
dev->devdesc.nendpoints = CDCACM_NUM_EPS;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* drivers/usbdev/cdcacm.h
|
||||
*
|
||||
* Copyright (C) 2011-2012, 2015 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011-2012, 2015, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -104,16 +104,9 @@
|
|||
* CDCACM_DATAALTIFID No alternate for the data interface
|
||||
*/
|
||||
|
||||
#define CDCACM_NINTERFACES (2) /* Number of interfaces in the configuration */
|
||||
#define CDCACM_NOTIFID (CONFIG_CDCACM_IFNOBASE+0)
|
||||
#define CDCACM_NOTALTIFID (0)
|
||||
#define CDCACM_DATAIFID (CONFIG_CDCACM_IFNOBASE+1)
|
||||
#define CDCACM_DATAALTIFID (0)
|
||||
|
||||
/* Configuration descriptor values */
|
||||
|
||||
#define CDCACM_CONFIGID (1) /* The only supported configuration ID */
|
||||
|
||||
/* Buffer big enough for any of our descriptors (the config descriptor is the
|
||||
* biggest).
|
||||
*/
|
||||
|
@ -124,7 +117,6 @@
|
|||
/* Device descriptor values */
|
||||
|
||||
#define CDCACM_VERSIONNO (0x0101) /* Device version number 1.1 (BCD) */
|
||||
#define CDCACM_NCONFIGS (1) /* Number of configurations supported */
|
||||
|
||||
/* String language */
|
||||
|
||||
|
@ -165,62 +157,16 @@
|
|||
#define CDCACM_LASTSTRID CDCACM_DATAIFSTRID
|
||||
#define CDCACM_NSTRIDS (CDCACM_LASTSTRID - CDCACM_STRBASE)
|
||||
|
||||
/* Configuration descriptor size */
|
||||
|
||||
#if !defined(CONFIG_CDCACM_COMPOSITE)
|
||||
|
||||
/* Number of individual descriptors in the configuration descriptor:
|
||||
* Configuration descriptor + (2) interface descriptors + (3) endpoint
|
||||
* descriptors + (3) ACM descriptors.
|
||||
*/
|
||||
|
||||
# define CDCACM_CFGGROUP_SIZE (9)
|
||||
|
||||
/* The size of the config descriptor: (9 + 2*9 + 3*7 + 4 + 5 + 5) = 62 */
|
||||
|
||||
# define SIZEOF_CDCACM_CFGDESC \
|
||||
(USB_SIZEOF_CFGDESC + 2*USB_SIZEOF_IFDESC + 3*USB_SIZEOF_EPDESC + \
|
||||
SIZEOF_ACM_FUNCDESC + SIZEOF_HDR_FUNCDESC + SIZEOF_UNION_FUNCDESC(1))
|
||||
|
||||
#elif defined(CONFIG_COMPOSITE_IAD)
|
||||
|
||||
/* Number of individual descriptors in the configuration descriptor:
|
||||
* (1) interface association descriptor + (2) interface descriptors +
|
||||
* (3) endpoint descriptors + (3) ACM descriptors.
|
||||
*/
|
||||
|
||||
# define CDCACM_CFGGROUP_SIZE (9)
|
||||
|
||||
/* The size of the config descriptor: (8 + 2*9 + 3*7 + 4 + 5 + 5) = 61 */
|
||||
|
||||
# define SIZEOF_CDCACM_CFGDESC \
|
||||
(USB_SIZEOF_IADDESC +2*USB_SIZEOF_IFDESC + 3*USB_SIZEOF_EPDESC + \
|
||||
SIZEOF_ACM_FUNCDESC + SIZEOF_HDR_FUNCDESC + SIZEOF_UNION_FUNCDESC(1))
|
||||
|
||||
#else
|
||||
|
||||
/* Number of individual descriptors in the configuration descriptor:
|
||||
* (2) interface descriptors + (3) endpoint descriptors + (3) ACM descriptors.
|
||||
*/
|
||||
|
||||
# define CDCACM_CFGGROUP_SIZE (8)
|
||||
|
||||
/* The size of the config descriptor: (2*9 + 3*7 + 4 + 5 + 5) = 53 */
|
||||
|
||||
# define SIZEOF_CDCACM_CFGDESC \
|
||||
(2*USB_SIZEOF_IFDESC + 3*USB_SIZEOF_EPDESC + SIZEOF_ACM_FUNCDESC + \
|
||||
SIZEOF_HDR_FUNCDESC + SIZEOF_UNION_FUNCDESC(1))
|
||||
#endif
|
||||
|
||||
/* Endpoint configuration ****************************************************/
|
||||
|
||||
#define CDCACM_EPINTIN_ADDR (USB_DIR_IN | CONFIG_CDCACM_EPINTIN)
|
||||
#define CDCACM_MKEPINTIN(desc) (USB_DIR_IN | (desc)->epno[CDCACM_EP_INTIN_IDX])
|
||||
#define CDCACM_EPINTIN_ATTR (USB_EP_ATTR_XFER_INT)
|
||||
|
||||
#define CDCACM_EPOUTBULK_ADDR (CONFIG_CDCACM_EPBULKOUT)
|
||||
#define CDCACM_MKEPBULKIN(desc) (USB_DIR_IN | (desc)->epno[CDCACM_EP_BULKIN_IDX])
|
||||
#define CDCACM_EPOUTBULK_ATTR (USB_EP_ATTR_XFER_BULK)
|
||||
|
||||
#define CDCACM_EPINBULK_ADDR (USB_DIR_IN | CONFIG_CDCACM_EPBULKIN)
|
||||
#define CDCACM_MKEPBULKOUT(desc) ((desc)->epno[CDCACM_EP_BULKOUT_IDX])
|
||||
#define CDCACM_EPINBULK_ATTR (USB_EP_ATTR_XFER_BULK)
|
||||
|
||||
/* Device driver definitions ************************************************/
|
||||
|
@ -287,7 +233,7 @@ enum cdcacm_epdesc_e
|
|||
int cdcacm_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_getepdesc
|
||||
* Name: cdcacm_getdevdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw device descriptor
|
||||
|
@ -299,28 +245,18 @@ FAR const struct usb_devdesc_s *cdcacm_getdevdesc(void);
|
|||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_getepdesc
|
||||
* Name: cdcacm_copy_epdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw endpoint descriptor (used for configuring
|
||||
* endpoints)
|
||||
* Copies the requested Endpoint Description into the buffer given.
|
||||
* Returns the number of Bytes filled in (sizeof(struct usb_epdesc_s)).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR const struct usb_epdesc_s *cdcacm_getepdesc(enum cdcacm_epdesc_e epid);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_mkepdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct the endpoint descriptor using the correct max packet size.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
void cdcacm_mkepdesc(enum cdcacm_epdesc_e epid,
|
||||
uint16_t mxpacket, FAR struct usb_epdesc_s *outdesc);
|
||||
#endif
|
||||
int cdcacm_copy_epdesc(enum cdcacm_epdesc_e epid,
|
||||
FAR struct usb_epdesc_s *epdesc,
|
||||
FAR struct usbdev_description_s *devdesc,
|
||||
bool hispeed);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_mkcfgdesc
|
||||
|
@ -331,9 +267,12 @@ void cdcacm_mkepdesc(enum cdcacm_epdesc_e epid,
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf, uint8_t speed, uint8_t type);
|
||||
int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf,
|
||||
FAR struct usbdev_description_s *devdesc,
|
||||
uint8_t speed, uint8_t type);
|
||||
#else
|
||||
int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf);
|
||||
int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf,
|
||||
FAR struct usbdev_description_s *devdesc);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* drivers/usbdev/cdcacm_desc.c
|
||||
*
|
||||
* Copyright (C) 2011-2012, 2015 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011-2012, 2015, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -46,35 +46,13 @@
|
|||
#include <debug.h>
|
||||
|
||||
#include <nuttx/usb/usb.h>
|
||||
#include <nuttx/usb/usbdev.h>
|
||||
#include <nuttx/usb/cdc.h>
|
||||
#include <nuttx/usb/cdcacm.h>
|
||||
#include <nuttx/usb/usbdev_trace.h>
|
||||
|
||||
#include "cdcacm.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* Describes one description in the group of descriptors forming the
|
||||
* total configuration descriptor.
|
||||
*/
|
||||
|
||||
struct cfgdecsc_group_s
|
||||
{
|
||||
uint16_t descsize; /* Size of the descriptor in bytes */
|
||||
uint16_t hsepsize; /* High speed max packet size */
|
||||
FAR void *desc; /* A pointer to the descriptor */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
@ -117,241 +95,6 @@ static const struct usb_devdesc_s g_devdesc =
|
|||
};
|
||||
#endif
|
||||
|
||||
/* Configuration descriptor. If the USB serial device is configured as part of
|
||||
* composite device, then the configuration descriptor will be provided by the
|
||||
* composite device logic.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
static const struct usb_cfgdesc_s g_cfgdesc =
|
||||
{
|
||||
USB_SIZEOF_CFGDESC, /* len */
|
||||
USB_DESC_TYPE_CONFIG, /* type */
|
||||
{
|
||||
LSBYTE(SIZEOF_CDCACM_CFGDESC), /* LS totallen */
|
||||
MSBYTE(SIZEOF_CDCACM_CFGDESC) /* MS totallen */
|
||||
},
|
||||
CDCACM_NINTERFACES, /* ninterfaces */
|
||||
CDCACM_CONFIGID, /* cfgvalue */
|
||||
CDCACM_CONFIGSTRID, /* icfg */
|
||||
USB_CONFIG_ATTR_ONE | /* attr */
|
||||
CDCACM_SELFPOWERED |
|
||||
CDCACM_REMOTEWAKEUP,
|
||||
(CONFIG_USBDEV_MAXPOWER + 1) / 2 /* mxpower */
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Interface association descriptor */
|
||||
|
||||
#if defined(CONFIG_CDCACM_COMPOSITE) && defined(CONFIG_COMPOSITE_IAD)
|
||||
static const struct usb_iaddesc_s g_iaddesc =
|
||||
{
|
||||
USB_SIZEOF_IADDESC, /* len */
|
||||
USB_DESC_TYPE_INTERFACEASSOCIATION, /* type */
|
||||
CONFIG_CDCACM_IFNOBASE, /* firstif */
|
||||
CDCACM_NINTERFACES, /* nifs */
|
||||
USB_CLASS_CDC, /* class */
|
||||
CDC_SUBCLASS_ACM, /* subclass */
|
||||
CDC_PROTO_NONE, /* protocol */
|
||||
0 /* ifunction */
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Notification interface */
|
||||
|
||||
static const struct usb_ifdesc_s g_notifdesc =
|
||||
{
|
||||
USB_SIZEOF_IFDESC, /* len */
|
||||
USB_DESC_TYPE_INTERFACE, /* type */
|
||||
CDCACM_NOTIFID, /* ifno */
|
||||
CDCACM_NOTALTIFID, /* alt */
|
||||
1, /* neps */
|
||||
USB_CLASS_CDC, /* class */
|
||||
CDC_SUBCLASS_ACM, /* subclass */
|
||||
CDC_PROTO_ATM, /* proto */
|
||||
#ifdef CONFIG_CDCACM_NOTIFSTR
|
||||
CDCACM_NOTIFSTRID /* iif */
|
||||
#else
|
||||
0 /* iif */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Header functional descriptor */
|
||||
|
||||
static const struct cdc_hdr_funcdesc_s g_funchdr =
|
||||
{
|
||||
SIZEOF_HDR_FUNCDESC, /* size */
|
||||
USB_DESC_TYPE_CSINTERFACE, /* type */
|
||||
CDC_DSUBTYPE_HDR, /* subtype */
|
||||
{
|
||||
LSBYTE(CDC_VERSIONNO), /* LS cdc */
|
||||
MSBYTE(CDC_VERSIONNO) /* MS cdc */
|
||||
}
|
||||
};
|
||||
|
||||
/* ACM functional descriptor */
|
||||
|
||||
static const struct cdc_acm_funcdesc_s g_acmfunc =
|
||||
{
|
||||
SIZEOF_ACM_FUNCDESC, /* size */
|
||||
USB_DESC_TYPE_CSINTERFACE, /* type */
|
||||
CDC_DSUBTYPE_ACM, /* subtype */
|
||||
0x06 /* caps */
|
||||
};
|
||||
|
||||
/* Union functional descriptor */
|
||||
|
||||
static const struct cdc_union_funcdesc_s g_unionfunc =
|
||||
{
|
||||
SIZEOF_UNION_FUNCDESC(1), /* size */
|
||||
USB_DESC_TYPE_CSINTERFACE, /* type */
|
||||
CDC_DSUBTYPE_UNION, /* subtype */
|
||||
0, /* master */
|
||||
{1} /* slave[0] */
|
||||
};
|
||||
|
||||
/* Interrupt IN endpoint descriptor */
|
||||
|
||||
static const struct usb_epdesc_s g_epintindesc =
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* len */
|
||||
USB_DESC_TYPE_ENDPOINT, /* type */
|
||||
CDCACM_EPINTIN_ADDR, /* addr */
|
||||
CDCACM_EPINTIN_ATTR, /* attr */
|
||||
{
|
||||
LSBYTE(CONFIG_CDCACM_EPINTIN_FSSIZE), /* maxpacket (full speed) */
|
||||
MSBYTE(CONFIG_CDCACM_EPINTIN_FSSIZE)
|
||||
},
|
||||
10 /* interval */
|
||||
};
|
||||
|
||||
/* Data interface descriptor */
|
||||
|
||||
static const struct usb_ifdesc_s g_dataifdesc =
|
||||
{
|
||||
USB_SIZEOF_IFDESC, /* len */
|
||||
USB_DESC_TYPE_INTERFACE, /* type */
|
||||
CDCACM_DATAIFID, /* ifno */
|
||||
CDCACM_DATAALTIFID, /* alt */
|
||||
2, /* neps */
|
||||
USB_CLASS_CDC_DATA, /* class */
|
||||
CDC_DATA_SUBCLASS_NONE, /* subclass */
|
||||
CDC_DATA_PROTO_NONE, /* proto */
|
||||
#ifdef CONFIG_CDCACM_DATAIFSTR
|
||||
CDCACM_DATAIFSTRID /* iif */
|
||||
#else
|
||||
0 /* iif */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Bulk OUT endpoint descriptor */
|
||||
|
||||
static const struct usb_epdesc_s g_epbulkoutdesc =
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* len */
|
||||
USB_DESC_TYPE_ENDPOINT, /* type */
|
||||
CDCACM_EPOUTBULK_ADDR, /* addr */
|
||||
CDCACM_EPOUTBULK_ATTR, /* attr */
|
||||
{
|
||||
LSBYTE(CONFIG_CDCACM_EPBULKOUT_FSSIZE), /* maxpacket (full speed) */
|
||||
MSBYTE(CONFIG_CDCACM_EPBULKOUT_FSSIZE)
|
||||
},
|
||||
1 /* interval */
|
||||
};
|
||||
|
||||
/* Bulk IN endpoint descriptor */
|
||||
|
||||
static const struct usb_epdesc_s g_epbulkindesc =
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* len */
|
||||
USB_DESC_TYPE_ENDPOINT, /* type */
|
||||
CDCACM_EPINBULK_ADDR, /* addr */
|
||||
CDCACM_EPINBULK_ATTR, /* attr */
|
||||
{
|
||||
LSBYTE(CONFIG_CDCACM_EPBULKIN_FSSIZE), /* maxpacket (full speed) */
|
||||
MSBYTE(CONFIG_CDCACM_EPBULKIN_FSSIZE)
|
||||
},
|
||||
1 /* interval */
|
||||
};
|
||||
|
||||
/* The components of the configuration descriptor are maintained as
|
||||
* a collection of separate descriptor structure coordinated by the
|
||||
* following array. These descriptors could have been combined into
|
||||
* one larger "super" configuration descriptor structure. However, I
|
||||
* have concerns about compiler-dependent alignment and packing. Since
|
||||
* the individual structures consist only of byte types, alignment and
|
||||
* packing is not an issue. And since the are concatentated at run time
|
||||
* instead of compile time, there should no issues there either.
|
||||
*/
|
||||
|
||||
static const struct cfgdecsc_group_s g_cfggroup[CDCACM_CFGGROUP_SIZE] =
|
||||
{
|
||||
/* Configuration Descriptor. If the serial device is used in as part
|
||||
* or a composite device, then the configuration descriptor is
|
||||
* provided by the composite device logic.
|
||||
*/
|
||||
|
||||
#if !defined(CONFIG_CDCACM_COMPOSITE)
|
||||
{
|
||||
USB_SIZEOF_CFGDESC, /* 1. Configuration descriptor */
|
||||
0,
|
||||
(FAR void *)&g_cfgdesc
|
||||
},
|
||||
|
||||
/* If the serial device is part of a composite device, then it should
|
||||
* begin with an interface association descriptor (IAD) because the
|
||||
* CDC/ACM device consists of more than one interface. The IAD associates
|
||||
* the two CDC/ACM interfaces with the same CDC/ACM device.
|
||||
*/
|
||||
|
||||
#elif defined(CONFIG_COMPOSITE_IAD)
|
||||
{
|
||||
USB_SIZEOF_IADDESC, /* 1. Interface association descriptor */
|
||||
0,
|
||||
(FAR void *)&g_iaddesc
|
||||
},
|
||||
#endif
|
||||
{
|
||||
USB_SIZEOF_IFDESC, /* 2. Notification interface */
|
||||
0,
|
||||
(FAR void *)&g_notifdesc
|
||||
},
|
||||
{
|
||||
SIZEOF_HDR_FUNCDESC, /* 3. Header functional descriptor */
|
||||
0,
|
||||
(FAR void *)&g_funchdr
|
||||
},
|
||||
{
|
||||
SIZEOF_ACM_FUNCDESC, /* 4. ACM functional descriptor */
|
||||
0,
|
||||
(FAR void *)&g_acmfunc
|
||||
},
|
||||
{
|
||||
SIZEOF_UNION_FUNCDESC(1), /* 5. Union functional descriptor */
|
||||
0,
|
||||
(FAR void *)&g_unionfunc
|
||||
},
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* 6. Interrupt IN endpoint descriptor */
|
||||
CONFIG_CDCACM_EPINTIN_HSSIZE,
|
||||
(FAR void *)&g_epintindesc
|
||||
},
|
||||
{
|
||||
USB_SIZEOF_IFDESC, /* 7. Data interface descriptor */
|
||||
0,
|
||||
(FAR void *)&g_dataifdesc
|
||||
},
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* 8. Bulk OUT endpoint descriptor */
|
||||
CONFIG_CDCACM_EPBULKOUT_HSSIZE,
|
||||
(FAR void *)&g_epbulkoutdesc
|
||||
},
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* 9. Bulk OUT endpoint descriptor */
|
||||
CONFIG_CDCACM_EPBULKIN_HSSIZE,
|
||||
(FAR void *)&g_epbulkindesc
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(CONFIG_CDCACM_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED)
|
||||
static const struct usb_qualdesc_s g_qualdesc =
|
||||
|
@ -375,29 +118,6 @@ static const struct usb_qualdesc_s g_qualdesc =
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_cpepdesc
|
||||
*
|
||||
* Description:
|
||||
* Copy an endpoint descriptor using the correct max packet size.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
void cdcacm_cpepdesc(FAR const struct usb_epdesc_s *indesc, uint16_t mxpacket,
|
||||
FAR struct usb_epdesc_s *outdesc)
|
||||
{
|
||||
/* Copy the "canned" descriptor */
|
||||
|
||||
memcpy(outdesc, indesc, USB_SIZEOF_EPDESC);
|
||||
|
||||
/* Then add the correct max packet size */
|
||||
|
||||
outdesc->mxpacketsize[0] = LSBYTE(mxpacket);
|
||||
outdesc->mxpacketsize[1] = MSBYTE(mxpacket);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -507,51 +227,115 @@ FAR const struct usb_devdesc_s *cdcacm_getdevdesc(void)
|
|||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_getepdesc
|
||||
* Name: cdcacm_copy_epdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw endpoint struct (used for configuring
|
||||
* endpoints)
|
||||
* Copies the requested Endpoint Description into the buffer given.
|
||||
* Returns the number of Bytes filled in (sizeof(struct usb_epdesc_s)).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR const struct usb_epdesc_s *cdcacm_getepdesc(enum cdcacm_epdesc_e epid)
|
||||
int cdcacm_copy_epdesc(enum cdcacm_epdesc_e epid,
|
||||
FAR struct usb_epdesc_s *epdesc,
|
||||
FAR struct usbdev_description_s *devdesc,
|
||||
bool hispeed)
|
||||
{
|
||||
switch (epid)
|
||||
#ifndef CONFIG_USBDEV_DUALSPEED
|
||||
/* unused */
|
||||
(void)hispeed;
|
||||
#endif
|
||||
|
||||
switch (epid)
|
||||
{
|
||||
case CDCACM_EPINTIN: /* Interrupt IN endpoint */
|
||||
return &g_epintindesc;
|
||||
|
||||
case CDCACM_EPBULKOUT: /* Bulk OUT endpoint */
|
||||
return &g_epbulkoutdesc;
|
||||
|
||||
case CDCACM_EPBULKIN: /* Bulk IN endpoint */
|
||||
return &g_epbulkindesc;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_mkepdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct the endpoint descriptor using the correct max packet size.
|
||||
*
|
||||
****************************************************************************/
|
||||
case CDCACM_EPINTIN: /* Interrupt IN endpoint */
|
||||
{
|
||||
epdesc->len = USB_SIZEOF_EPDESC; /* Descriptor length */
|
||||
epdesc->type = USB_DESC_TYPE_ENDPOINT; /* Descriptor type */
|
||||
epdesc->addr = CDCACM_MKEPINTIN(devdesc); /* Endpoint address */
|
||||
epdesc->attr = CDCACM_EPINTIN_ATTR; /* Endpoint attributes */
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
void cdcacm_mkepdesc(enum cdcacm_epdesc_e epid, uint16_t mxpacket,
|
||||
FAR struct usb_epdesc_s *outdesc)
|
||||
{
|
||||
/* Map the ID to the correct endpoint and let cdcacm_cpepdesc to the real
|
||||
* work.
|
||||
*/
|
||||
if (hispeed)
|
||||
{
|
||||
/* Maximum packet size (high speed) */
|
||||
|
||||
cdcacm_cpepdesc(cdcacm_getepdesc(epid), mxpacket, outdesc);
|
||||
}
|
||||
epdesc->mxpacketsize[0] = LSBYTE(CONFIG_CDCACM_EPINTIN_HSSIZE);
|
||||
epdesc->mxpacketsize[1] = MSBYTE(CONFIG_CDCACM_EPINTIN_HSSIZE);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Maximum packet size (full speed) */
|
||||
|
||||
epdesc->mxpacketsize[0] = LSBYTE(CONFIG_CDCACM_EPINTIN_FSSIZE);
|
||||
epdesc->mxpacketsize[1] = MSBYTE(CONFIG_CDCACM_EPINTIN_FSSIZE);
|
||||
}
|
||||
|
||||
epdesc->interval = 10; /* Interval */
|
||||
}
|
||||
break;
|
||||
|
||||
case CDCACM_EPBULKOUT: /* Bulk OUT endpoint */
|
||||
{
|
||||
epdesc->len = USB_SIZEOF_EPDESC; /* Descriptor length */
|
||||
epdesc->type = USB_DESC_TYPE_ENDPOINT; /* Descriptor type */
|
||||
epdesc->addr = CDCACM_MKEPBULKOUT(devdesc); /* Endpoint address */
|
||||
epdesc->attr = CDCACM_EPOUTBULK_ATTR; /* Endpoint attributes */
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
if (hispeed)
|
||||
{
|
||||
/* Maximum packet size (high speed) */
|
||||
|
||||
epdesc->mxpacketsize[0] = LSBYTE(CONFIG_CDCACM_EPBULKOUT_HSSIZE);
|
||||
epdesc->mxpacketsize[1] = MSBYTE(CONFIG_CDCACM_EPBULKOUT_HSSIZE);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Maximum packet size (full speed) */
|
||||
|
||||
epdesc->mxpacketsize[0] = LSBYTE(CONFIG_CDCACM_EPBULKOUT_FSSIZE);
|
||||
epdesc->mxpacketsize[1] = MSBYTE(CONFIG_CDCACM_EPBULKOUT_FSSIZE);
|
||||
}
|
||||
|
||||
epdesc->interval = 1; /* Interval */
|
||||
}
|
||||
break;
|
||||
|
||||
case CDCACM_EPBULKIN: /* Bulk IN endpoint */
|
||||
{
|
||||
epdesc->len = USB_SIZEOF_EPDESC; /* Descriptor length */
|
||||
epdesc->type = USB_DESC_TYPE_ENDPOINT; /* Descriptor type */
|
||||
epdesc->addr = CDCACM_MKEPBULKIN(devdesc); /* Endpoint address */
|
||||
epdesc->attr = CDCACM_EPINBULK_ATTR; /* Endpoint attributes */
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
if (hispeed)
|
||||
{
|
||||
/* Maximum packet size (high speed) */
|
||||
|
||||
epdesc->mxpacketsize[0] = LSBYTE(CONFIG_CDCACM_EPBULKIN_HSSIZE);
|
||||
epdesc->mxpacketsize[1] = MSBYTE(CONFIG_CDCACM_EPBULKIN_HSSIZE);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Maximum packet size (full speed) */
|
||||
|
||||
epdesc->mxpacketsize[0] = LSBYTE(CONFIG_CDCACM_EPBULKIN_FSSIZE);
|
||||
epdesc->mxpacketsize[1] = MSBYTE(CONFIG_CDCACM_EPBULKIN_FSSIZE);
|
||||
}
|
||||
|
||||
epdesc->interval = 1; /* Interval */
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sizeof(struct usb_epdesc_s);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_mkcfgdesc
|
||||
|
@ -562,17 +346,19 @@ void cdcacm_mkepdesc(enum cdcacm_epdesc_e epid, uint16_t mxpacket,
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf, uint8_t speed, uint8_t type)
|
||||
int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf,
|
||||
FAR struct usbdev_description_s *devdesc,
|
||||
uint8_t speed, uint8_t type)
|
||||
#else
|
||||
int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf)
|
||||
int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf,
|
||||
FAR struct usbdev_description_s *devdesc)
|
||||
#endif
|
||||
{
|
||||
FAR const struct cfgdecsc_group_s *group;
|
||||
FAR uint8_t *dest = buf;
|
||||
int i;
|
||||
int length = 0;
|
||||
bool hispeed = false;
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
bool hispeed = (speed == USB_SPEED_HIGH);
|
||||
hispeed = (speed == USB_SPEED_HIGH);
|
||||
|
||||
/* Check for switches between high and full speed */
|
||||
|
||||
|
@ -582,44 +368,226 @@ int16_t cdcacm_mkcfgdesc(FAR uint8_t *buf)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Copy all of the descriptors in the group */
|
||||
/* fill in all descriptors directly to the buf */
|
||||
|
||||
for (i = 0, dest = buf; i < CDCACM_CFGGROUP_SIZE; i++)
|
||||
/* Configuration Descriptor. If the serial device is used in as part
|
||||
* or a composite device, then the configuration descriptor is
|
||||
* provided by the composite device logic.
|
||||
*/
|
||||
|
||||
#if !defined(CONFIG_CDCACM_COMPOSITE)
|
||||
if (buf != NULL)
|
||||
{
|
||||
group = &g_cfggroup[i];
|
||||
|
||||
/* The "canned" descriptors all have full speed endpoint maxpacket
|
||||
* sizes. If high speed is selected, we will have to change the
|
||||
* endpoint maxpacket size.
|
||||
*
|
||||
* Is there a alternative high speed maxpacket size in the table?
|
||||
* If so, that is sufficient proof that the descriptor that we
|
||||
* just copied is an endpoint descriptor and needs the fixup
|
||||
/* Configuration descriptor. If the USB serial device is configured as part of
|
||||
* composite device, then the configuration descriptor will be provided by the
|
||||
* composite device logic.
|
||||
*/
|
||||
|
||||
FAR struct usb_cfgdesc_s *dest = (FAR struct usb_cfgdesc_s *)buf;
|
||||
|
||||
/* Let's calculate the size... */
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
if (hispeed && group->hsepsize != 0)
|
||||
{
|
||||
cdcacm_cpepdesc((FAR const struct usb_epdesc_s *)group->desc,
|
||||
group->hsepsize,
|
||||
(FAR struct usb_epdesc_s *)dest);
|
||||
}
|
||||
else
|
||||
int16_t size = cdcacm_mkcfgdesc(NULL, NULL, speed, type);
|
||||
#else
|
||||
int16_t size = cdcacm_mkcfgdesc(NULL, NULL);
|
||||
#endif
|
||||
/* Copy the "canned" descriptor with the full speed max packet
|
||||
* size
|
||||
*/
|
||||
|
||||
{
|
||||
memcpy(dest, group->desc, group->descsize);
|
||||
}
|
||||
dest->len = USB_SIZEOF_CFGDESC; /* Descriptor length */
|
||||
dest->type = USB_DESC_TYPE_CONFIG; /* Descriptor type */
|
||||
dest->totallen[0] = LSBYTE(size); /* LS Total length */
|
||||
dest->totallen[1] = MSBYTE(size); /* MS Total length */
|
||||
dest->ninterfaces = CDCACM_NINTERFACES; /* Number of interfaces */
|
||||
dest->cfgvalue = CDCACM_CONFIGID; /* Configuration value */
|
||||
dest->icfg = CDCACM_CONFIGSTRID; /* Configuration */
|
||||
dest->attr = USB_CONFIG_ATTR_ONE | /* Attributes */
|
||||
CDCACM_SELFPOWERED |
|
||||
CDCACM_REMOTEWAKEUP;
|
||||
dest->mxpower = (CONFIG_USBDEV_MAXPOWER + 1) / 2; /* Max power (mA/2) */
|
||||
|
||||
/* Advance to the destination location for the next descriptor */
|
||||
|
||||
dest += group->descsize;
|
||||
buf += sizeof(struct usb_cfgdesc_s);
|
||||
}
|
||||
|
||||
return SIZEOF_CDCACM_CFGDESC;
|
||||
length += sizeof(struct usb_cfgdesc_s);
|
||||
|
||||
/* If the serial device is part of a composite device, then it should
|
||||
* begin with an interface association descriptor (IAD) because the
|
||||
* CDC/ACM device consists of more than one interface. The IAD associates
|
||||
* the two CDC/ACM interfaces with the same CDC/ACM device.
|
||||
*/
|
||||
|
||||
#elif defined(CONFIG_COMPOSITE_IAD)
|
||||
/* Interface association descriptor */
|
||||
|
||||
if (buf != NULL)
|
||||
{
|
||||
FAR struct usb_iaddesc_s *dest = (FAR struct usb_iaddesc_s *)buf;
|
||||
|
||||
dest->len = USB_SIZEOF_IADDESC; /* Descriptor length */
|
||||
dest->type = USB_DESC_TYPE_INTERFACEASSOCIATION; /* Descriptor type */
|
||||
dest->firstif = devdesc->ifnobase; /* Number of first interface of the function */
|
||||
dest->nifs = devdesc->ninterfaces; /* Number of interfaces associated with the function */
|
||||
dest->classid = USB_CLASS_CDC; /* Class code */
|
||||
dest->subclass = CDC_SUBCLASS_ACM; /* Sub-class code */
|
||||
dest->protocol = CDC_PROTO_NONE; /* Protocol code */
|
||||
dest->ifunction = 0; /* Index to string identifying the function */
|
||||
|
||||
buf += sizeof(struct usb_iaddesc_s);
|
||||
}
|
||||
length += sizeof(struct usb_iaddesc_s);
|
||||
#endif
|
||||
|
||||
/* Notification interface */
|
||||
|
||||
if (buf != NULL)
|
||||
{
|
||||
FAR struct usb_ifdesc_s *dest = (FAR struct usb_ifdesc_s *)buf;
|
||||
|
||||
dest->len = USB_SIZEOF_IFDESC; /* Descriptor length */
|
||||
dest->type = USB_DESC_TYPE_INTERFACE; /* Descriptor type */
|
||||
dest->ifno = devdesc->ifnobase; /* Interface number */
|
||||
dest->alt = CDCACM_NOTALTIFID; /* Alternate setting */
|
||||
dest->neps = 1; /* Number of endpoints */
|
||||
dest->classid = USB_CLASS_CDC; /* Interface class */
|
||||
dest->subclass = CDC_SUBCLASS_ACM; /* Interface sub-class */
|
||||
dest->protocol = CDC_PROTO_ATM; /* Interface protocol */
|
||||
#ifdef CONFIG_CDCACM_NOTIFSTR
|
||||
dest->iif = devdesc->strbase + CDCACM_NOTIFSTRID; /* iInterface */
|
||||
#else
|
||||
dest->iif = 0; /* iInterface */
|
||||
#endif
|
||||
|
||||
buf += sizeof(struct usb_ifdesc_s);
|
||||
}
|
||||
|
||||
length += sizeof(struct usb_ifdesc_s);
|
||||
|
||||
/* Header functional descriptor */
|
||||
|
||||
if (buf != NULL)
|
||||
{
|
||||
FAR struct cdc_hdr_funcdesc_s *dest = (FAR struct cdc_hdr_funcdesc_s *)buf;
|
||||
|
||||
dest->size = SIZEOF_HDR_FUNCDESC; /* Descriptor length */
|
||||
dest->type = USB_DESC_TYPE_CSINTERFACE; /* Descriptor type */
|
||||
dest->subtype = CDC_DSUBTYPE_HDR; /* Descriptor sub-type */
|
||||
dest->cdc[0] = LSBYTE(CDC_VERSIONNO); /* CDC release number in BCD */
|
||||
dest->cdc[1] = MSBYTE(CDC_VERSIONNO);
|
||||
|
||||
buf += sizeof(struct cdc_hdr_funcdesc_s);
|
||||
}
|
||||
|
||||
length += sizeof(struct cdc_hdr_funcdesc_s);
|
||||
|
||||
|
||||
/* ACM functional descriptor */
|
||||
|
||||
if (buf != NULL)
|
||||
{
|
||||
FAR struct cdc_acm_funcdesc_s *dest = (FAR struct cdc_acm_funcdesc_s *)buf;
|
||||
|
||||
dest->size = SIZEOF_ACM_FUNCDESC; /* Descriptor length */
|
||||
dest->type = USB_DESC_TYPE_CSINTERFACE; /* Descriptor type */
|
||||
dest->subtype = CDC_DSUBTYPE_ACM; /* Descriptor sub-type */
|
||||
dest->caps = 0x06; /* Bit encoded capabilities */
|
||||
|
||||
buf += sizeof(struct cdc_acm_funcdesc_s);
|
||||
}
|
||||
|
||||
length += sizeof(struct cdc_acm_funcdesc_s);
|
||||
|
||||
/* This codeblock is just for future use - currently we didn't need it */
|
||||
|
||||
#ifdef OPTIONAL_UNION_FUNCTIONAL_DESCRIPTOR
|
||||
/* Union functional descriptor */
|
||||
if (buf != NULL)
|
||||
{
|
||||
FAR struct cdc_union_funcdesc_s *dest = (FAR struct cdc_union_funcdesc_s *)buf;
|
||||
|
||||
dest->size = SIZEOF_UNION_FUNCDESC(1); /* Descriptor length */
|
||||
dest->type = USB_DESC_TYPE_CSINTERFACE; /* Descriptor type */
|
||||
dest->subtype = CDC_DSUBTYPE_UNION; /* Descriptor sub-type */
|
||||
dest->master = devdesc->ifnobase; /* Master interface number */
|
||||
dest->slave[0] = devdesc->ifnobase + 1; /* Slave[0] interface number */
|
||||
|
||||
buf += sizeof(struct cdc_union_funcdesc_s);
|
||||
}
|
||||
|
||||
length += sizeof(struct cdc_union_funcdesc_s);
|
||||
#endif
|
||||
|
||||
/* Call Management functional descriptor */
|
||||
|
||||
if (buf != NULL)
|
||||
{
|
||||
FAR struct cdc_callmgmt_funcdesc_s *dest = (FAR struct cdc_callmgmt_funcdesc_s *)buf;
|
||||
|
||||
dest->size = SIZEOF_CALLMGMT_FUNCDESC; /* Descriptor length */
|
||||
dest->type = USB_DESC_TYPE_CSINTERFACE; /* Descriptor type */
|
||||
dest->subtype = CDC_DSUBTYPE_CALLMGMT; /* Descriptor sub-type */
|
||||
dest->caps = 3; /* Bit encoded capabilities */
|
||||
dest->ifno = devdesc->ifnobase + 1; /* Interface number of Data Class interface */
|
||||
|
||||
buf += sizeof(struct cdc_callmgmt_funcdesc_s);
|
||||
}
|
||||
|
||||
length += sizeof(struct cdc_callmgmt_funcdesc_s);
|
||||
|
||||
/* Interrupt IN endpoint descriptor */
|
||||
|
||||
if (buf != NULL)
|
||||
{
|
||||
cdcacm_copy_epdesc(CDCACM_EPINTIN, (struct usb_epdesc_s *)buf, devdesc, hispeed);
|
||||
|
||||
buf += USB_SIZEOF_EPDESC;
|
||||
}
|
||||
length += USB_SIZEOF_EPDESC;
|
||||
|
||||
/* Data interface descriptor */
|
||||
|
||||
if (buf != NULL)
|
||||
{
|
||||
FAR struct usb_ifdesc_s *dest = (FAR struct usb_ifdesc_s *)buf;
|
||||
|
||||
dest->len = USB_SIZEOF_IFDESC; /* Descriptor length */
|
||||
dest->type = USB_DESC_TYPE_INTERFACE; /* Descriptor type */
|
||||
dest->ifno = devdesc->ifnobase + 1; /* Interface number */
|
||||
dest->alt = CDCACM_DATAALTIFID; /* Alternate setting */
|
||||
dest->neps = 2; /* Number of endpoints */
|
||||
dest->classid = USB_CLASS_CDC_DATA; /* Interface class */
|
||||
dest->subclass = CDC_DATA_SUBCLASS_NONE; /* Interface sub-class */
|
||||
dest->protocol = CDC_DATA_PROTO_NONE; /* Interface protocol */
|
||||
#ifdef CONFIG_CDCACM_DATAIFSTR
|
||||
dest->iif = devdesc->strbase + CDCACM_DATAIFSTRID; /* iInterface */
|
||||
#else
|
||||
dest->iif = 0; /* iInterface */
|
||||
#endif
|
||||
|
||||
buf += sizeof(struct usb_ifdesc_s);
|
||||
}
|
||||
|
||||
length += sizeof(struct usb_ifdesc_s);
|
||||
|
||||
/* Bulk OUT endpoint descriptor */
|
||||
|
||||
if (buf != NULL)
|
||||
{
|
||||
cdcacm_copy_epdesc(CDCACM_EPBULKOUT, (struct usb_epdesc_s *)buf, devdesc, hispeed);
|
||||
buf += USB_SIZEOF_EPDESC;
|
||||
}
|
||||
|
||||
length += USB_SIZEOF_EPDESC;
|
||||
|
||||
/* Bulk IN endpoint descriptor */
|
||||
|
||||
if (buf != NULL)
|
||||
{
|
||||
cdcacm_copy_epdesc(CDCACM_EPBULKIN, (struct usb_epdesc_s *)buf, devdesc, hispeed);
|
||||
buf += USB_SIZEOF_EPDESC;
|
||||
}
|
||||
|
||||
length += USB_SIZEOF_EPDESC;
|
||||
return length;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -636,3 +604,5 @@ FAR const struct usb_qualdesc_s *cdcacm_getqualdesc(void)
|
|||
return &g_qualdesc;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* drivers/usbdev/composite.c
|
||||
*
|
||||
* Copyright (C) 2012, 2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2012, 2016-2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -60,17 +60,6 @@
|
|||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure describes the internal state of the driver */
|
||||
|
||||
struct composite_dev_s
|
||||
{
|
||||
FAR struct usbdev_s *usbdev; /* usbdev driver pointer */
|
||||
uint8_t config; /* Configuration number */
|
||||
FAR struct usbdev_req_s *ctrlreq; /* Allocated control request */
|
||||
struct usbdevclass_driver_s *dev1; /* Device 1 class object */
|
||||
struct usbdevclass_driver_s *dev2; /* Device 2 class object */
|
||||
};
|
||||
|
||||
/* The internal version of the class driver */
|
||||
|
||||
struct composite_driver_s
|
||||
|
@ -123,6 +112,7 @@ static void composite_resume(FAR struct usbdevclass_driver_s *driver,
|
|||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* USB class device *********************************************************/
|
||||
|
||||
static const struct usbdevclass_driverops_s g_driverops =
|
||||
|
@ -146,9 +136,6 @@ const char g_compserialstr[] = CONFIG_COMPOSITE_SERIALSTR;
|
|||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
/****************************************************************************
|
||||
* Helpers
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_ep0incomplete
|
||||
|
@ -165,7 +152,8 @@ static void composite_ep0incomplete(FAR struct usbdev_ep_s *ep,
|
|||
|
||||
if (req->result || req->xfrd != req->len)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_REQRESULT), (uint16_t)-req->result);
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_REQRESULT),
|
||||
(uint16_t)-req->result);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,17 +173,20 @@ static int composite_classsetup(FAR struct composite_dev_s *priv,
|
|||
uint16_t index;
|
||||
uint8_t interface;
|
||||
int ret = -EOPNOTSUPP;
|
||||
int i;
|
||||
|
||||
index = GETUINT16(ctrl->index);
|
||||
interface = (uint8_t)(index & 0xff);
|
||||
|
||||
if (interface >= DEV1_FIRSTINTERFACE && interface < (DEV1_FIRSTINTERFACE + DEV1_NINTERFACES))
|
||||
for (i = 0; i < priv->ndevices; i++)
|
||||
{
|
||||
ret = CLASS_SETUP(priv->dev1, dev, ctrl, dataout, outlen);
|
||||
}
|
||||
else if (interface >= DEV2_FIRSTINTERFACE && interface < (DEV2_FIRSTINTERFACE + DEV2_NINTERFACES))
|
||||
{
|
||||
ret = CLASS_SETUP(priv->dev2, dev, ctrl, dataout, outlen);
|
||||
if (interface >= priv->device[i].compdesc.devdesc.ifnobase &&
|
||||
interface < (priv->device[i].compdesc.devdesc.ifnobase +
|
||||
priv->device[i].compdesc.devdesc.ninterfaces))
|
||||
{
|
||||
ret = CLASS_SETUP(priv->device[i].dev, dev, ctrl, dataout, outlen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -225,6 +216,7 @@ static struct usbdev_req_s *composite_allocreq(FAR struct usbdev_ep_s *ep,
|
|||
req = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
|
@ -245,6 +237,7 @@ static void composite_freereq(FAR struct usbdev_ep_s *ep,
|
|||
{
|
||||
EP_FREEBUFFER(ep, req->buf);
|
||||
}
|
||||
|
||||
EP_FREEREQ(ep, req);
|
||||
}
|
||||
}
|
||||
|
@ -264,8 +257,11 @@ static void composite_freereq(FAR struct usbdev_ep_s *ep,
|
|||
static int composite_bind(FAR struct usbdevclass_driver_s *driver,
|
||||
FAR struct usbdev_s *dev)
|
||||
{
|
||||
FAR struct composite_dev_s *priv = ((FAR struct composite_driver_s *)driver)->dev;
|
||||
FAR struct composite_dev_s *priv =
|
||||
((FAR struct composite_driver_s *)driver)->dev;
|
||||
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
usbtrace(TRACE_CLASSBIND, 0);
|
||||
|
||||
|
@ -281,7 +277,7 @@ static int composite_bind(FAR struct usbdevclass_driver_s *driver,
|
|||
|
||||
/* Preallocate one control request */
|
||||
|
||||
priv->ctrlreq = composite_allocreq(dev->ep0, COMPOSITE_CFGDESCSIZE);
|
||||
priv->ctrlreq = composite_allocreq(dev->ep0, priv->cfgdescsize);
|
||||
if (priv->ctrlreq == NULL)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_ALLOCCTRLREQ), 0);
|
||||
|
@ -295,16 +291,13 @@ static int composite_bind(FAR struct usbdevclass_driver_s *driver,
|
|||
|
||||
/* Then bind each of the constituent class drivers */
|
||||
|
||||
ret = CLASS_BIND(priv->dev1, dev);
|
||||
if (ret < 0)
|
||||
for (i = 0; i < priv->ndevices; i++)
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ret = CLASS_BIND(priv->dev2, dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout;
|
||||
ret = CLASS_BIND(priv->device[i].dev, dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
/* Report if we are selfpowered */
|
||||
|
@ -363,11 +356,15 @@ static void composite_unbind(FAR struct usbdevclass_driver_s *driver,
|
|||
|
||||
if (priv != NULL)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Unbind the constituent class drivers */
|
||||
|
||||
flags = enter_critical_section();
|
||||
CLASS_UNBIND(priv->dev1, dev);
|
||||
CLASS_UNBIND(priv->dev2, dev);
|
||||
for (i = 0; i < priv->ndevices; i++)
|
||||
{
|
||||
CLASS_UNBIND(priv->device[i].dev, dev);
|
||||
}
|
||||
|
||||
/* Free the pre-allocated control request */
|
||||
|
||||
|
@ -377,6 +374,7 @@ static void composite_unbind(FAR struct usbdevclass_driver_s *driver,
|
|||
composite_freereq(dev->ep0, priv->ctrlreq);
|
||||
priv->ctrlreq = NULL;
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
}
|
||||
|
@ -423,6 +421,7 @@ static int composite_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
ctrlreq = priv->ctrlreq;
|
||||
|
||||
/* Extract the little-endian 16-bit values to host order */
|
||||
|
@ -472,10 +471,10 @@ static int composite_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
case USB_DESC_TYPE_CONFIG:
|
||||
{
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
ret = composite_mkcfgdesc(ctrlreq->buf, dev->speed,
|
||||
ret = composite_mkcfgdesc(priv, ctrlreq->buf, dev->speed,
|
||||
ctrl->value[1]);
|
||||
#else
|
||||
ret = composite_mkcfgdesc(ctrlreq->buf);
|
||||
ret = composite_mkcfgdesc(priv, ctrlreq->buf);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
@ -491,18 +490,21 @@ static int composite_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
{
|
||||
ret = composite_mkstrdesc(strid, buf);
|
||||
}
|
||||
#if DEV1_NSTRIDS > 0
|
||||
else if (strid <= DEV1_STRIDBASE + DEV1_NSTRIDS)
|
||||
else
|
||||
{
|
||||
ret = DEV1_MKSTRDESC(strid, buf);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->ndevices; i++)
|
||||
{
|
||||
if (strid >= priv->device[i].compdesc.devdesc.strbase &&
|
||||
strid < priv->device[i].compdesc.devdesc.strbase +
|
||||
priv->device[i].compdesc.devdesc.nstrings)
|
||||
{
|
||||
ret = priv->device[i].compdesc.mkstrdesc(strid - priv->device[i].compdesc.devdesc.strbase, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if DEV2_NSTRIDS > 0
|
||||
else if (strid <= DEV2_STRIDBASE + DEV2_NSTRIDS)
|
||||
{
|
||||
ret = DEV2_MKSTRDESC(strid, buf);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -519,19 +521,17 @@ static int composite_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
{
|
||||
if (ctrl->type == 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Save the configuration and inform the constituent classes */
|
||||
|
||||
ret = CLASS_SETUP(priv->dev1, dev, ctrl, dataout, outlen);
|
||||
dispatched = true;
|
||||
|
||||
if (ret >= 0)
|
||||
for (i = 0; i < priv->ndevices; i++)
|
||||
{
|
||||
ret = CLASS_SETUP(priv->dev2, dev, ctrl, dataout, outlen);
|
||||
if (ret >= 0)
|
||||
{
|
||||
priv->config = value;
|
||||
}
|
||||
ret = CLASS_SETUP(priv->device[i].dev, dev, ctrl, dataout, outlen);
|
||||
}
|
||||
|
||||
dispatched = true;
|
||||
priv->config = value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -593,10 +593,9 @@ static int composite_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Respond to the setup command if (1) data was returned, and (2) the request was
|
||||
* NOT successfully dispatched to the component class driver. On an error return
|
||||
* value (ret < 0), the USB driver will stall EP0.
|
||||
/* Respond to the setup command if (1) data was returned, and (2) the
|
||||
* request was NOT successfully dispatched to the component class driver.
|
||||
* On an error return value (ret < 0), the USB driver will stall EP0.
|
||||
*/
|
||||
|
||||
if (ret >= 0 && !dispatched)
|
||||
|
@ -635,6 +634,7 @@ static void composite_disconnect(FAR struct usbdevclass_driver_s *driver,
|
|||
{
|
||||
FAR struct composite_dev_s *priv;
|
||||
irqstate_t flags;
|
||||
int i;
|
||||
|
||||
usbtrace(TRACE_CLASSDISCONNECT, 0);
|
||||
|
||||
|
@ -664,8 +664,12 @@ static void composite_disconnect(FAR struct usbdevclass_driver_s *driver,
|
|||
|
||||
flags = enter_critical_section();
|
||||
priv->config = COMPOSITE_CONFIGIDNONE;
|
||||
CLASS_DISCONNECT(priv->dev1, dev);
|
||||
CLASS_DISCONNECT(priv->dev2, dev);
|
||||
|
||||
for (i = 0; i < priv->ndevices; i++)
|
||||
{
|
||||
CLASS_DISCONNECT(priv->device[i].dev, dev);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
|
||||
/* Perform the soft connect function so that we will we can be
|
||||
|
@ -688,6 +692,7 @@ static void composite_suspend(FAR struct usbdevclass_driver_s *driver,
|
|||
{
|
||||
FAR struct composite_dev_s *priv;
|
||||
irqstate_t flags;
|
||||
int i;
|
||||
|
||||
usbtrace(TRACE_CLASSSUSPEND, 0);
|
||||
|
||||
|
@ -714,8 +719,12 @@ static void composite_suspend(FAR struct usbdevclass_driver_s *driver,
|
|||
/* Forward the suspend event to the constituent devices */
|
||||
|
||||
flags = enter_critical_section();
|
||||
CLASS_SUSPEND(priv->dev1, priv->usbdev);
|
||||
CLASS_SUSPEND(priv->dev2, priv->usbdev);
|
||||
|
||||
for (i = 0; i < priv->ndevices; i++)
|
||||
{
|
||||
CLASS_SUSPEND(priv->device[i].dev, priv->usbdev);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
|
@ -732,6 +741,7 @@ static void composite_resume(FAR struct usbdevclass_driver_s *driver,
|
|||
{
|
||||
FAR struct composite_dev_s *priv = NULL;
|
||||
irqstate_t flags;
|
||||
int i;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
if (!dev)
|
||||
|
@ -756,8 +766,12 @@ static void composite_resume(FAR struct usbdevclass_driver_s *driver,
|
|||
/* Forward the resume event to the constituent devices */
|
||||
|
||||
flags = enter_critical_section();
|
||||
CLASS_RESUME(priv->dev1, priv->usbdev);
|
||||
CLASS_RESUME(priv->dev2, priv->usbdev);
|
||||
|
||||
for (i = 0; i < priv->ndevices; i++)
|
||||
{
|
||||
CLASS_RESUME(priv->device[i].dev, priv->usbdev);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
|
@ -770,8 +784,7 @@ static void composite_resume(FAR struct usbdevclass_driver_s *driver,
|
|||
* Description:
|
||||
* Register USB composite device as configured. This function will call
|
||||
* board-specific implementations in order to obtain the class objects for
|
||||
* each of the members of the composite (see board_mscclassobject(),
|
||||
* board_cdcclassobjec(), ...)
|
||||
* each of the members of the composite.
|
||||
*
|
||||
* Input Parameter:
|
||||
* None
|
||||
|
@ -786,16 +799,22 @@ static void composite_resume(FAR struct usbdevclass_driver_s *driver,
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR void *composite_initialize(void)
|
||||
FAR void *composite_initialize(uint8_t ndevices,
|
||||
FAR struct composite_devdesc_s *pdevices)
|
||||
{
|
||||
FAR struct composite_alloc_s *alloc;
|
||||
FAR struct composite_dev_s *priv;
|
||||
FAR struct composite_driver_s *drvr;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
DEBUGASSERT(pdevices != NULL && ndevices <= NUM_DEVICES_TO_HANDLE);
|
||||
|
||||
/* Allocate the structures needed */
|
||||
|
||||
alloc = (FAR struct composite_alloc_s *)kmm_malloc(sizeof(struct composite_alloc_s));
|
||||
alloc = (FAR struct composite_alloc_s *)
|
||||
kmm_malloc(sizeof(struct composite_alloc_s));
|
||||
|
||||
if (!alloc)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_ALLOCDEVSTRUCT), 0);
|
||||
|
@ -811,21 +830,32 @@ FAR void *composite_initialize(void)
|
|||
|
||||
memset(priv, 0, sizeof(struct composite_dev_s));
|
||||
|
||||
/* Get the constitueat class driver objects */
|
||||
priv->cfgdescsize = USB_SIZEOF_CFGDESC;
|
||||
priv->ninterfaces = 0;
|
||||
|
||||
ret = DEV1_CLASSOBJECT(&priv->dev1);
|
||||
if (ret < 0)
|
||||
/* Get the constituent class driver objects */
|
||||
|
||||
for (i = 0; i < ndevices; i++)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_CLASSOBJECT), (uint16_t)-ret);
|
||||
goto errout_with_alloc;
|
||||
memcpy(&priv->device[i].compdesc, &pdevices[i],
|
||||
sizeof(struct composite_devdesc_s));
|
||||
|
||||
ret =
|
||||
priv->device[i].compdesc.classobject(priv->device[i].compdesc.minor,
|
||||
&priv->device[i].compdesc.devdesc,
|
||||
&priv->device[i].dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_CLASSOBJECT),
|
||||
(uint16_t)-ret);
|
||||
goto errout_with_alloc;
|
||||
}
|
||||
|
||||
priv->cfgdescsize += priv->device[i].compdesc.cfgdescsize;
|
||||
priv->ninterfaces += priv->device[i].compdesc.devdesc.ninterfaces;
|
||||
}
|
||||
|
||||
ret = DEV2_CLASSOBJECT(&priv->dev2);
|
||||
if (ret < 0)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_CLASSOBJECT), (uint16_t)-ret);
|
||||
goto errout_with_alloc;
|
||||
}
|
||||
priv->ndevices = ndevices;
|
||||
|
||||
/* Initialize the USB class driver structure */
|
||||
|
||||
|
@ -840,9 +870,10 @@ FAR void *composite_initialize(void)
|
|||
/* Register the USB composite class driver */
|
||||
|
||||
ret = usbdev_register(&drvr->drvr);
|
||||
if (ret)
|
||||
if (ret < 0)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_DEVREGISTER), (uint16_t)-ret);
|
||||
usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_DEVREGISTER),
|
||||
(uint16_t)-ret);
|
||||
goto errout_with_alloc;
|
||||
}
|
||||
|
||||
|
@ -860,8 +891,7 @@ errout_with_alloc:
|
|||
* Un-initialize the USB composite driver. The handle is the USB composite
|
||||
* class' device object as was returned by composite_initialize(). This
|
||||
* function will call board-specific implementations in order to free the
|
||||
* class objects for each of the members of the composite (see
|
||||
* board_mscuninitialize(), board_cdcuninitialize(), ...)
|
||||
* class objects for each of the members of the composite.
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - The handle returned by a previous call to composite_initialize().
|
||||
|
@ -875,6 +905,7 @@ void composite_uninitialize(FAR void *handle)
|
|||
{
|
||||
FAR struct composite_alloc_s *alloc = (FAR struct composite_alloc_s *)handle;
|
||||
FAR struct composite_dev_s *priv;
|
||||
int i;
|
||||
|
||||
DEBUGASSERT(alloc != NULL);
|
||||
|
||||
|
@ -882,8 +913,10 @@ void composite_uninitialize(FAR void *handle)
|
|||
|
||||
priv = &alloc->dev;
|
||||
|
||||
DEV1_UNINITIALIZE(priv->dev1);
|
||||
DEV2_UNINITIALIZE(priv->dev2);
|
||||
for (i = 0; i < priv->ndevices; i++)
|
||||
{
|
||||
priv->device[i].compdesc.uninitialize(priv->device[i].dev);
|
||||
}
|
||||
|
||||
/* Then unregister and destroy the composite class */
|
||||
|
||||
|
@ -894,8 +927,10 @@ void composite_uninitialize(FAR void *handle)
|
|||
|
||||
/* Second phase uninitialization: Clean up all memory resources */
|
||||
|
||||
DEV1_UNINITIALIZE(priv->dev1);
|
||||
DEV2_UNINITIALIZE(priv->dev2);
|
||||
for (i = 0; i < priv->ndevices; i++)
|
||||
{
|
||||
priv->device[i].compdesc.uninitialize(priv->device[i].dev);
|
||||
}
|
||||
|
||||
/* Then free the composite driver state structure itself */
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* drivers/usbdev/composite.h
|
||||
*
|
||||
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011-2012, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -46,6 +46,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include <nuttx/usb/usb.h>
|
||||
#include <nuttx/usb/usbdev.h>
|
||||
#include <nuttx/usb/usbdev_trace.h>
|
||||
|
||||
#ifdef CONFIG_USBDEV_COMPOSITE
|
||||
|
@ -62,6 +63,7 @@
|
|||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Configuration ************************************************************/
|
||||
/* Packet sizes */
|
||||
|
||||
|
@ -106,136 +108,21 @@
|
|||
#ifdef CONFIG_USBDEV_SELFPOWERED
|
||||
# define COMPOSITE_SELFPOWERED USB_CONFIG_ATTR_SELFPOWER
|
||||
#else
|
||||
# define COMPOSITE_SELFPOWERED (0)
|
||||
# define COMPOSITE_SELFPOWERED (0)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USBDEV_REMOTEWAKEUP
|
||||
# define COMPOSITE_REMOTEWAKEUP USB_CONFIG_ATTR_WAKEUP
|
||||
#else
|
||||
# define COMPOSITE_REMOTEWAKEUP (0)
|
||||
# define COMPOSITE_REMOTEWAKEUP (0)
|
||||
#endif
|
||||
|
||||
/* Constituent devices ******************************************************/
|
||||
|
||||
#undef DEV1_IS_CDCACM
|
||||
#undef DEV1_IS_USBMSC
|
||||
|
||||
#undef DEV2_IS_CDCACM
|
||||
#undef DEV2_IS_USBMSC
|
||||
|
||||
/* Pick the first device in the composite. At present, this may only be
|
||||
* the CDC serial device or the mass storage device.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_CDCACM_COMPOSITE)
|
||||
# define DEV1_IS_CDCACM 1
|
||||
# define DEV1_MKCFGDESC cdcacm_mkcfgdesc
|
||||
# define DEV1_MKSTRDESC cdcacm_mkstrdesc
|
||||
# define DEV1_CLASSOBJECT board_cdcclassobject
|
||||
# define DEV1_UNINITIALIZE board_cdcuninitialize
|
||||
# define DEV1_NCONFIGS CDCACM_NCONFIGS
|
||||
# define DEV1_CONFIGID CDCACM_CONFIGID
|
||||
# define DEV1_FIRSTINTERFACE CONFIG_CDCACM_IFNOBASE
|
||||
# define DEV1_NINTERFACES CDCACM_NINTERFACES
|
||||
# define DEV1_STRIDBASE CONFIG_CDCACM_STRBASE
|
||||
# define DEV1_NSTRIDS CDCACM_NSTRIDS
|
||||
# define DEV1_CFGDESCSIZE SIZEOF_CDCACM_CFGDESC
|
||||
#elif defined(CONFIG_USBMSC_COMPOSITE)
|
||||
# define DEV1_IS_USBMSC 1
|
||||
# define DEV1_MKCFGDESC usbmsc_mkcfgdesc
|
||||
# define DEV1_MKSTRDESC usbmsc_mkstrdesc
|
||||
# define DEV1_CLASSOBJECT board_mscclassobject
|
||||
# define DEV1_UNINITIALIZE board_mscuninitialize
|
||||
# define DEV1_NCONFIGS USBMSC_NCONFIGS
|
||||
# define DEV1_CONFIGID USBMSC_CONFIGID
|
||||
# define DEV1_FIRSTINTERFACE CONFIG_USBMSC_IFNOBASE
|
||||
# define DEV1_NINTERFACES USBMSC_NINTERFACES
|
||||
# define DEV1_STRIDBASE CONFIG_USBMSC_IFNOBASE
|
||||
# define DEV1_NSTRIDS USBMSC_NSTRIDS
|
||||
# define DEV1_CFGDESCSIZE SIZEOF_USBMSC_CFGDESC
|
||||
#else
|
||||
# error "No members of the composite defined"
|
||||
#endif
|
||||
|
||||
/* Pick the second device in the composite. At present, this may only be
|
||||
* the CDC serial device or the mass storage device.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_CDCACM_COMPOSITE) && !defined(DEV1_IS_CDCACM)
|
||||
# define DEV2_IS_CDCACM 1
|
||||
# define DEV2_MKCFGDESC cdcacm_mkcfgdesc
|
||||
# define DEV2_MKSTRDESC cdcacm_mkstrdesc
|
||||
# define DEV2_CLASSOBJECT board_cdcclassobject
|
||||
# define DEV2_UNINITIALIZE board_cdcuninitialize
|
||||
# define DEV2_NCONFIGS CDCACM_NCONFIGS
|
||||
# define DEV2_CONFIGID CDCACM_CONFIGID
|
||||
# define DEV2_FIRSTINTERFACE CONFIG_CDCACM_IFNOBASE
|
||||
# define DEV2_NINTERFACES CDCACM_NINTERFACES
|
||||
# define DEV2_STRIDBASE CONFIG_CDCACM_STRBASE
|
||||
# define DEV2_NSTRIDS CDCACM_NSTRIDS
|
||||
# define DEV2_CFGDESCSIZE SIZEOF_CDCACM_CFGDESC
|
||||
#elif defined(CONFIG_USBMSC_COMPOSITE) && !defined(DEV1_IS_USBMSC)
|
||||
# define DEV2_IS_USBMSC 1
|
||||
# define DEV2_MKCFGDESC usbmsc_mkcfgdesc
|
||||
# define DEV2_MKSTRDESC usbmsc_mkstrdesc
|
||||
# define DEV2_UNINITIALIZE board_mscuninitialize
|
||||
# define DEV2_CLASSOBJECT board_mscclassobject
|
||||
# define DEV2_NCONFIGS USBMSC_NCONFIGS
|
||||
# define DEV2_CONFIGID USBMSC_CONFIGID
|
||||
# define DEV2_FIRSTINTERFACE CONFIG_USBMSC_IFNOBASE
|
||||
# define DEV2_NINTERFACES USBMSC_NINTERFACES
|
||||
# define DEV2_STRIDBASE CONFIG_USBMSC_STRBASE
|
||||
# define DEV2_NSTRIDS USBMSC_NSTRIDS
|
||||
# define DEV2_CFGDESCSIZE SIZEOF_USBMSC_CFGDESC
|
||||
#else
|
||||
# error "Insufficient members of the composite defined"
|
||||
#endif
|
||||
|
||||
/* Verify interface configuration */
|
||||
|
||||
#if DEV1_FIRSTINTERFACE != 0
|
||||
# warning "The first interface number should be zero"
|
||||
#endif
|
||||
|
||||
#if (DEV1_FIRSTINTERFACE + DEV1_NINTERFACES) != DEV2_FIRSTINTERFACE
|
||||
# warning "Interface numbers are not contiguous"
|
||||
#endif
|
||||
|
||||
/* Check if an IAD is needed */
|
||||
|
||||
#ifdef CONFIG_COMPOSITE_IAD
|
||||
# if DEV1_NINTERFACES == 1 && DEV2_NINTERFACES == 1
|
||||
# warning "CONFIG_COMPOSITE_IAD not needed"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_COMPOSITE_IAD) && DEV1_NINTERFACES > 1 && DEV2_NINTERFACES > 1
|
||||
# warning "CONFIG_COMPOSITE_IAD may be needed"
|
||||
#endif
|
||||
|
||||
/* Total size of the configuration descriptor: */
|
||||
|
||||
#define COMPOSITE_CFGDESCSIZE (USB_SIZEOF_CFGDESC + DEV1_CFGDESCSIZE + DEV2_CFGDESCSIZE)
|
||||
|
||||
/* The total number of interfaces */
|
||||
|
||||
#define COMPOSITE_NINTERFACES (DEV1_NINTERFACES + DEV2_NINTERFACES)
|
||||
|
||||
/* Composite configuration ID value */
|
||||
|
||||
#if DEV1_NCONFIGS != 1 || DEV1_CONFIGID != 1
|
||||
# error "DEV1: Only a single configuration is supported"
|
||||
#endif
|
||||
|
||||
#if DEV2_NCONFIGS != 1 || DEV2_CONFIGID != 1
|
||||
# error "DEV2: Only a single configuration is supported"
|
||||
#endif
|
||||
#define NUM_DEVICES_TO_HANDLE (4)
|
||||
|
||||
/* Descriptors **************************************************************/
|
||||
/* These settings are not modifiable via the NuttX configuration */
|
||||
|
||||
#define COMPOSITE_CONFIGIDNONE (0) /* Config ID = 0 means to return to address mode */
|
||||
#define COMPOSITE_NCONFIGS (1) /* The number of configurations supported */
|
||||
#define COMPOSITE_CONFIGID (1) /* The only supported configuration ID */
|
||||
|
||||
/* String language */
|
||||
|
@ -248,17 +135,6 @@
|
|||
#define COMPOSITE_PRODUCTSTRID (2)
|
||||
#define COMPOSITE_SERIALSTRID (3)
|
||||
#define COMPOSITE_CONFIGSTRID (4)
|
||||
#define COMPOSITE_NSTRIDS (4)
|
||||
|
||||
/* Verify string configuration */
|
||||
|
||||
#if COMPOSITE_NSTRIDS != DEV1_STRIDBASE
|
||||
# warning "The DEV1 string base should be COMPOSITE_NSTRIDS"
|
||||
#endif
|
||||
|
||||
#if (DEV1_STRIDBASE + DEV1_NSTRIDS) != DEV2_STRIDBASE
|
||||
# warning "String IDs are not contiguous"
|
||||
#endif
|
||||
|
||||
/* Everpresent MIN/MAX macros ***********************************************/
|
||||
|
||||
|
@ -274,6 +150,33 @@
|
|||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
struct composite_devobj_s
|
||||
{
|
||||
/* Device description given by the user code in the dynamic
|
||||
* configuration.
|
||||
*/
|
||||
|
||||
struct composite_devdesc_s compdesc;
|
||||
|
||||
/* Pointer to device class */
|
||||
|
||||
FAR struct usbdevclass_driver_s *dev;
|
||||
};
|
||||
|
||||
/* This structure describes the internal state of the driver */
|
||||
|
||||
struct composite_dev_s
|
||||
{
|
||||
FAR struct usbdev_s *usbdev; /* usbdev driver pointer */
|
||||
uint8_t config; /* Configuration number */
|
||||
FAR struct usbdev_req_s *ctrlreq; /* Allocated control request */
|
||||
uint8_t ndevices; /* Num devices in this composite device */
|
||||
int cfgdescsize; /* Total size of the configuration descriptor: */
|
||||
int ninterfaces; /* The total number of interfaces in this composite device */
|
||||
|
||||
struct composite_devobj_s device[NUM_DEVICES_TO_HANDLE]; /* Device class object */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
@ -317,9 +220,11 @@ FAR const struct usb_devdesc_s *composite_getdevdesc(void);
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
int16_t composite_mkcfgdesc(uint8_t *buf, uint8_t speed, uint8_t type);
|
||||
int16_t composite_mkcfgdesc(FAR struct composite_dev_s *priv,
|
||||
FAR uint8_t *buf, uint8_t speed, uint8_t type);
|
||||
#else
|
||||
int16_t composite_mkcfgdesc(uint8_t *buf);
|
||||
int16_t composite_mkcfgdesc(FAR struct composite_dev_s *priv,
|
||||
FAR uint8_t *buf);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* drivers/usbdev/composite_desc.c
|
||||
*
|
||||
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011-2012, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -61,12 +61,6 @@
|
|||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
typedef int16_t (*mkcfgdesc)(FAR uint8_t *buf, uint8_t speed, uint8_t type);
|
||||
#else
|
||||
typedef int16_t (*mkcfgdesc)(FAR uint8_t *buf);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
@ -74,6 +68,7 @@ typedef int16_t (*mkcfgdesc)(FAR uint8_t *buf);
|
|||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* Device Descriptor */
|
||||
|
||||
static const struct usb_devdesc_s g_devdesc =
|
||||
|
@ -84,7 +79,7 @@ static const struct usb_devdesc_s g_devdesc =
|
|||
LSBYTE(0x0200),
|
||||
MSBYTE(0x0200)
|
||||
},
|
||||
#ifdef CONFIG_COMPOSITE_IAD
|
||||
#ifndef CONFIG_COMPOSITE_IAD
|
||||
USB_CLASS_MISC, /* classid */
|
||||
2, /* subclass */
|
||||
1, /* protocol */
|
||||
|
@ -112,25 +107,6 @@ static const struct usb_devdesc_s g_devdesc =
|
|||
COMPOSITE_NCONFIGS /* nconfigs */
|
||||
};
|
||||
|
||||
/* Configuration descriptor for the composite device */
|
||||
|
||||
static const struct usb_cfgdesc_s g_cfgdesc =
|
||||
{
|
||||
USB_SIZEOF_CFGDESC, /* len */
|
||||
USB_DESC_TYPE_CONFIG, /* type */
|
||||
{
|
||||
LSBYTE(COMPOSITE_CFGDESCSIZE), /* LS totallen */
|
||||
MSBYTE(COMPOSITE_CFGDESCSIZE) /* MS totallen */
|
||||
},
|
||||
COMPOSITE_NINTERFACES, /* ninterfaces */
|
||||
COMPOSITE_CONFIGID, /* cfgvalue */
|
||||
COMPOSITE_CONFIGSTRID, /* icfg */
|
||||
USB_CONFIG_ATTR_ONE | /* attr */
|
||||
COMPOSITE_SELFPOWERED |
|
||||
COMPOSITE_REMOTEWAKEUP,
|
||||
(CONFIG_USBDEV_MAXPOWER + 1) / 2 /* mxpower */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
static const struct usb_qualdesc_s g_qualdesc =
|
||||
{
|
||||
|
@ -243,35 +219,55 @@ FAR const struct usb_devdesc_s *composite_getdevdesc(void)
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
int16_t composite_mkcfgdesc(uint8_t *buf, uint8_t speed, uint8_t type)
|
||||
int16_t composite_mkcfgdesc(FAR struct composite_dev_s *priv, FAR uint8_t *buf,
|
||||
uint8_t speed, uint8_t type)
|
||||
#else
|
||||
int16_t composite_mkcfgdesc(uint8_t *buf)
|
||||
int16_t composite_mkcfgdesc(FAR struct composite_dev_s *priv, FAR uint8_t *buf)
|
||||
#endif
|
||||
{
|
||||
FAR struct usb_cfgdesc_s *cfgdesc = (FAR struct usb_cfgdesc_s *)buf;
|
||||
int16_t len;
|
||||
int16_t total;
|
||||
int i;
|
||||
|
||||
/* Configuration descriptor -- Copy the canned configuration descriptor. */
|
||||
/* Configuration descriptor for the composite device */
|
||||
/* Fill in the values directly into the buf */
|
||||
|
||||
cfgdesc->len = USB_SIZEOF_CFGDESC; /* Descriptor length */
|
||||
cfgdesc->type = USB_DESC_TYPE_CONFIG; /* Descriptor type */
|
||||
cfgdesc->totallen[0] = LSBYTE(priv->cfgdescsize); /* Lower Byte of Total length */
|
||||
cfgdesc->totallen[1] = MSBYTE(priv->cfgdescsize); /* High Byte of Total length */
|
||||
cfgdesc->ninterfaces = priv->ninterfaces; /* Number of interfaces */
|
||||
cfgdesc->cfgvalue = COMPOSITE_CONFIGID; /* Configuration value */
|
||||
cfgdesc->icfg = COMPOSITE_CONFIGSTRID; /* Configuration */
|
||||
cfgdesc->attr = USB_CONFIG_ATTR_ONE | /* Attributes */
|
||||
COMPOSITE_SELFPOWERED |
|
||||
COMPOSITE_REMOTEWAKEUP;
|
||||
cfgdesc->mxpower = (CONFIG_USBDEV_MAXPOWER + 1) / 2; /* Max power (mA/2) */
|
||||
|
||||
/* increment the size and buf to point right behind the information filled in */
|
||||
|
||||
memcpy(buf, &g_cfgdesc, USB_SIZEOF_CFGDESC);
|
||||
total = USB_SIZEOF_CFGDESC;
|
||||
buf += USB_SIZEOF_CFGDESC;
|
||||
buf += USB_SIZEOF_CFGDESC;
|
||||
|
||||
/* Copy DEV1/DEV2 interface descriptors */
|
||||
/* Copy all contained interface descriptors into the buffer too */
|
||||
|
||||
for (i = 0; i < priv->ndevices; i++)
|
||||
{
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
len = DEV1_MKCFGDESC(buf, speed, type);
|
||||
total += len;
|
||||
buf += len;
|
||||
total += DEV2_MKCFGDESC(buf, speed, type);
|
||||
len = priv->device[i].compdesc.mkconfdesc(buf,
|
||||
&priv->device[i].compdesc.devdesc,
|
||||
speed, type);
|
||||
total += len;
|
||||
buf += len;
|
||||
#else
|
||||
len = DEV1_MKCFGDESC(buf);
|
||||
total += len;
|
||||
buf += len;
|
||||
total += DEV2_MKCFGDESC(buf);
|
||||
len = priv->device[i].compdesc.mkconfdesc(buf,
|
||||
&priv->device[i].compdesc.devdesc);
|
||||
total += len;
|
||||
buf += len;
|
||||
#endif
|
||||
}
|
||||
|
||||
DEBUGASSERT(total == COMPOSITE_CFGDESCSIZE);
|
||||
return total;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* drivers/usbdev/usbmsc.c
|
||||
*
|
||||
* Copyright (C) 2008-2012, 2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2008-2012, 2016-2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Mass storage class device. Bulk-only with SCSI subclass.
|
||||
|
@ -246,6 +246,7 @@ static void usbmsc_freereq(FAR struct usbdev_ep_s *ep, struct usbdev_req_s *req)
|
|||
/****************************************************************************
|
||||
* Class Driver Interfaces
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_bind
|
||||
*
|
||||
|
@ -267,7 +268,7 @@ static int usbmsc_bind(FAR struct usbdevclass_driver_s *driver,
|
|||
|
||||
/* Bind the structures */
|
||||
|
||||
priv->usbdev = dev;
|
||||
priv->usbdev = dev;
|
||||
|
||||
/* Save the reference to our private data structure in EP0 so that it
|
||||
* can be recovered in ep0 completion events (Unless we are part of
|
||||
|
@ -307,7 +308,8 @@ static int usbmsc_bind(FAR struct usbdevclass_driver_s *driver,
|
|||
|
||||
/* Pre-allocate the IN bulk endpoint */
|
||||
|
||||
priv->epbulkin = DEV_ALLOCEP(dev, USBMSC_EPINBULK_ADDR, true, USB_EP_ATTR_XFER_BULK);
|
||||
priv->epbulkin = DEV_ALLOCEP(dev, USBMSC_MKEPBULKIN(&priv->devdesc),
|
||||
true, USB_EP_ATTR_XFER_BULK);
|
||||
if (!priv->epbulkin)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EPBULKINALLOCFAIL), 0);
|
||||
|
@ -319,7 +321,8 @@ static int usbmsc_bind(FAR struct usbdevclass_driver_s *driver,
|
|||
|
||||
/* Pre-allocate the OUT bulk endpoint */
|
||||
|
||||
priv->epbulkout = DEV_ALLOCEP(dev, USBMSC_EPOUTBULK_ADDR, false, USB_EP_ATTR_XFER_BULK);
|
||||
priv->epbulkout = DEV_ALLOCEP(dev, USBMSC_MKEPBULKOUT(&priv->devdesc),
|
||||
false, USB_EP_ATTR_XFER_BULK);
|
||||
if (!priv->epbulkout)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EPBULKOUTALLOCFAIL), 0);
|
||||
|
@ -334,7 +337,8 @@ static int usbmsc_bind(FAR struct usbdevclass_driver_s *driver,
|
|||
for (i = 0; i < CONFIG_USBMSC_NRDREQS; i++)
|
||||
{
|
||||
reqcontainer = &priv->rdreqs[i];
|
||||
reqcontainer->req = usbmsc_allocreq(priv->epbulkout, CONFIG_USBMSC_BULKOUTREQLEN);
|
||||
reqcontainer->req = usbmsc_allocreq(priv->epbulkout,
|
||||
CONFIG_USBMSC_BULKOUTREQLEN);
|
||||
if (reqcontainer->req == NULL)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_RDALLOCREQ),
|
||||
|
@ -342,6 +346,7 @@ static int usbmsc_bind(FAR struct usbdevclass_driver_s *driver,
|
|||
ret = -ENOMEM;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
reqcontainer->req->priv = reqcontainer;
|
||||
reqcontainer->req->callback = usbmsc_rdcomplete;
|
||||
}
|
||||
|
@ -351,7 +356,8 @@ static int usbmsc_bind(FAR struct usbdevclass_driver_s *driver,
|
|||
for (i = 0; i < CONFIG_USBMSC_NWRREQS; i++)
|
||||
{
|
||||
reqcontainer = &priv->wrreqs[i];
|
||||
reqcontainer->req = usbmsc_allocreq(priv->epbulkin, CONFIG_USBMSC_BULKINREQLEN);
|
||||
reqcontainer->req = usbmsc_allocreq(priv->epbulkin,
|
||||
CONFIG_USBMSC_BULKINREQLEN);
|
||||
if (reqcontainer->req == NULL)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_WRALLOCREQ),
|
||||
|
@ -359,6 +365,7 @@ static int usbmsc_bind(FAR struct usbdevclass_driver_s *driver,
|
|||
ret = -ENOMEM;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
reqcontainer->req->priv = reqcontainer;
|
||||
reqcontainer->req->callback = usbmsc_wrcomplete;
|
||||
|
||||
|
@ -482,7 +489,9 @@ static void usbmsc_unbind(FAR struct usbdevclass_driver_s *driver,
|
|||
flags = enter_critical_section();
|
||||
while (!sq_empty(&priv->wrreqlist))
|
||||
{
|
||||
reqcontainer = (struct usbmsc_req_s *)sq_remfirst(&priv->wrreqlist);
|
||||
reqcontainer = (struct usbmsc_req_s *)
|
||||
sq_remfirst(&priv->wrreqlist);
|
||||
|
||||
if (reqcontainer->req != NULL)
|
||||
{
|
||||
usbmsc_freereq(priv->epbulkin, reqcontainer->req);
|
||||
|
@ -569,9 +578,9 @@ static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
|
||||
switch (ctrl->value[1])
|
||||
{
|
||||
/* If the mass storage device is used in as part of a composite
|
||||
* device, then the device descriptor is is provided by logic
|
||||
* in the composite device implementation.
|
||||
/* If the mass storage device is used in as part of a
|
||||
* composite device, then the device descriptor is is
|
||||
* provided by logic in the composite device implementation.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
|
@ -583,9 +592,9 @@ static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
break;
|
||||
#endif
|
||||
|
||||
/* If the mass storage device is used in as part of a composite device,
|
||||
* then the device qualifier descriptor is provided by logic in the
|
||||
* composite device implementation.
|
||||
/* If the mass storage device is used in as part of a
|
||||
* composite device, then the device qualifier descriptor is
|
||||
* provided by logic in the composite device implementation.
|
||||
*/
|
||||
|
||||
#if !defined(CONFIG_USBMSC_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED)
|
||||
|
@ -608,7 +617,8 @@ static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
case USB_DESC_TYPE_CONFIG:
|
||||
{
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
ret = usbmsc_mkcfgdesc(ctrlreq->buf, dev->speed, ctrl->value[1]);
|
||||
ret = usbmsc_mkcfgdesc(ctrlreq->buf, dev->speed,
|
||||
ctrl->value[1]);
|
||||
#else
|
||||
ret = usbmsc_mkcfgdesc(ctrlreq->buf);
|
||||
#endif
|
||||
|
@ -616,9 +626,9 @@ static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
break;
|
||||
#endif
|
||||
|
||||
/* If the mass storage device is used in as part of a composite device,
|
||||
* then the language string descriptor is provided by logic in the
|
||||
* composite device implementation.
|
||||
/* If the mass storage device is used in as part of a
|
||||
* composite device, then the language string descriptor is
|
||||
* provided by logic in the composite device implementation.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
|
@ -626,7 +636,8 @@ static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
{
|
||||
/* index == language code. */
|
||||
|
||||
ret = usbmsc_mkstrdesc(ctrl->value[0], (struct usb_strdesc_s *)ctrlreq->buf);
|
||||
ret = usbmsc_mkstrdesc(ctrl->value[0],
|
||||
(struct usb_strdesc_s *)ctrlreq->buf);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
@ -644,7 +655,9 @@ static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
{
|
||||
if (ctrl->type == 0)
|
||||
{
|
||||
/* Signal the worker thread to instantiate the new configuration */
|
||||
/* Signal the worker thread to instantiate the new
|
||||
* configuration.
|
||||
*/
|
||||
|
||||
priv->theventset |= USBMSC_EVENT_CFGCHANGE;
|
||||
priv->thvalue = value;
|
||||
|
@ -659,9 +672,9 @@ static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
}
|
||||
break;
|
||||
|
||||
/* If the mass storage device is used in as part of a composite device,
|
||||
* then the overall composite class configuration is managed by logic
|
||||
* in the composite device implementation.
|
||||
/* If the mass storage device is used in as part of a composite
|
||||
* device, then the overall composite class configuration is
|
||||
* managed by logic in the composite device implementation.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
|
@ -689,8 +702,8 @@ static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
priv->theventset |= USBMSC_EVENT_IFCHANGE;
|
||||
usbmsc_scsi_signal(priv);
|
||||
|
||||
/* Return here... the response will be provided later by the
|
||||
* worker thread.
|
||||
/* Return here... the response will be provided later by
|
||||
* the worker thread.
|
||||
*/
|
||||
|
||||
return OK;
|
||||
|
@ -751,13 +764,15 @@ static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Signal to stop the current operation and reinitialize state */
|
||||
/* Signal to stop the current operation and reinitialize
|
||||
* state.
|
||||
*/
|
||||
|
||||
priv->theventset |= USBMSC_EVENT_RESET;
|
||||
usbmsc_scsi_signal(priv);
|
||||
|
||||
/* Return here... the response will be provided later by the
|
||||
* worker thread.
|
||||
/* Return here... the response will be provided later by
|
||||
* the worker thread.
|
||||
*/
|
||||
|
||||
return OK;
|
||||
|
@ -891,6 +906,7 @@ static void usbmsc_disconnect(FAR struct usbdevclass_driver_s *driver,
|
|||
/****************************************************************************
|
||||
* Initialization/Un-Initialization
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_lununinitialize
|
||||
****************************************************************************/
|
||||
|
@ -912,6 +928,7 @@ static void usbmsc_lununinitialize(struct usbmsc_lun_s *lun)
|
|||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Internal Interfaces
|
||||
****************************************************************************/
|
||||
|
@ -929,10 +946,8 @@ int usbmsc_setconfig(FAR struct usbmsc_dev_s *priv, uint8_t config)
|
|||
{
|
||||
FAR struct usbmsc_req_s *privreq;
|
||||
FAR struct usbdev_req_s *req;
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
FAR const struct usb_epdesc_s *epdesc;
|
||||
bool hispeed = (priv->usbdev->speed == USB_SPEED_HIGH);
|
||||
#endif
|
||||
struct usb_epdesc_s epdesc;
|
||||
bool hispeed = false;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -952,6 +967,10 @@ int usbmsc_setconfig(FAR struct usbmsc_dev_s *priv, uint8_t config)
|
|||
return OK;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
hispeed = (priv->usbdev->speed == USB_SPEED_HIGH);
|
||||
#endif
|
||||
|
||||
/* Discard the previous configuration data */
|
||||
|
||||
usbmsc_resetconfig(priv);
|
||||
|
@ -974,13 +993,9 @@ int usbmsc_setconfig(FAR struct usbmsc_dev_s *priv, uint8_t config)
|
|||
|
||||
/* Configure the IN bulk endpoint */
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
epdesc = USBMSC_EPBULKINDESC(hispeed);
|
||||
ret = EP_CONFIGURE(priv->epbulkin, epdesc, false);
|
||||
#else
|
||||
ret = EP_CONFIGURE(priv->epbulkin,
|
||||
usbmsc_getepdesc(USBMSC_EPFSBULKIN), false);
|
||||
#endif
|
||||
usbmsc_copy_epdesc(USBMSC_EPBULKIN, &epdesc, &priv->devdesc,
|
||||
hispeed);
|
||||
ret = EP_CONFIGURE(priv->epbulkin, &epdesc, false);
|
||||
if (ret < 0)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EPBULKINCONFIGFAIL), 0);
|
||||
|
@ -991,13 +1006,9 @@ int usbmsc_setconfig(FAR struct usbmsc_dev_s *priv, uint8_t config)
|
|||
|
||||
/* Configure the OUT bulk endpoint */
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
epdesc = USBMSC_EPBULKOUTDESC(hispeed);
|
||||
ret = EP_CONFIGURE(priv->epbulkout, epdesc, true);
|
||||
#else
|
||||
ret = EP_CONFIGURE(priv->epbulkout,
|
||||
usbmsc_getepdesc(USBMSC_EPFSBULKOUT), true);
|
||||
#endif
|
||||
usbmsc_copy_epdesc(USBMSC_EPBULKOUT, &epdesc, &priv->devdesc,
|
||||
hispeed);
|
||||
ret = EP_CONFIGURE(priv->epbulkout, &epdesc, true);
|
||||
if (ret < 0)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EPBULKOUTCONFIGFAIL), 0);
|
||||
|
@ -1015,10 +1026,12 @@ int usbmsc_setconfig(FAR struct usbmsc_dev_s *priv, uint8_t config)
|
|||
req->len = CONFIG_USBMSC_BULKOUTREQLEN;
|
||||
req->priv = privreq;
|
||||
req->callback = usbmsc_rdcomplete;
|
||||
|
||||
ret = EP_SUBMIT(priv->epbulkout, req);
|
||||
if (ret < 0)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_RDSUBMIT), (uint16_t)-ret);
|
||||
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_RDSUBMIT),
|
||||
(uint16_t)-ret);
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
@ -1067,7 +1080,8 @@ void usbmsc_resetconfig(FAR struct usbmsc_dev_s *priv)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
void usbmsc_wrcomplete(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req)
|
||||
void usbmsc_wrcomplete(FAR struct usbdev_ep_s *ep,
|
||||
FAR struct usbdev_req_s *req)
|
||||
{
|
||||
FAR struct usbmsc_dev_s *priv;
|
||||
FAR struct usbmsc_req_s *privreq;
|
||||
|
@ -1127,7 +1141,8 @@ void usbmsc_wrcomplete(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
void usbmsc_rdcomplete(FAR struct usbdev_ep_s *ep, FAR struct usbdev_req_s *req)
|
||||
void usbmsc_rdcomplete(FAR struct usbdev_ep_s *ep,
|
||||
FAR struct usbdev_req_s *req)
|
||||
{
|
||||
FAR struct usbmsc_dev_s *priv;
|
||||
FAR struct usbmsc_req_s *privreq;
|
||||
|
@ -1290,6 +1305,7 @@ static inline void usbmsc_sync_wait(FAR struct usbmsc_dev_s *priv)
|
|||
/****************************************************************************
|
||||
* User Interfaces
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_configure
|
||||
*
|
||||
|
@ -1494,10 +1510,10 @@ int usbmsc_bindlun(FAR void *handle, FAR const char *drvrpath,
|
|||
|
||||
memset(lun, 0, sizeof(struct usbmsc_lun_s));
|
||||
|
||||
/* Allocate an I/O buffer big enough to hold one hardware sector. SCSI commands
|
||||
* are processed one at a time so all LUNs may share a single I/O buffer. The
|
||||
* I/O buffer will be allocated so that is it as large as the largest block
|
||||
* device sector size
|
||||
/* Allocate an I/O buffer big enough to hold one hardware sector. SCSI
|
||||
* commands are processed one at a time so all LUNs may share a single I/O
|
||||
* buffer. The I/O buffer will be allocated so that is it as large as the
|
||||
* largest block device sector size
|
||||
*/
|
||||
|
||||
if (!priv->iobuffer)
|
||||
|
@ -1513,8 +1529,9 @@ int usbmsc_bindlun(FAR void *handle, FAR const char *drvrpath,
|
|||
}
|
||||
else if (priv->iosize < geo.geo_sectorsize)
|
||||
{
|
||||
void *tmp;
|
||||
tmp = (FAR uint8_t *)kmm_realloc(priv->iobuffer, geo.geo_sectorsize);
|
||||
FAR void *tmp;
|
||||
|
||||
tmp = (FAR void *)kmm_realloc(priv->iobuffer, geo.geo_sectorsize);
|
||||
if (!tmp)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_REALLOCIOBUFFER), geo.geo_sectorsize);
|
||||
|
@ -1669,7 +1686,8 @@ int usbmsc_exportluns(FAR void *handle)
|
|||
usbmsc_scsi_main, NULL);
|
||||
if (priv->thpid <= 0)
|
||||
{
|
||||
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_THREADCREATE), (uint16_t)errno);
|
||||
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_THREADCREATE),
|
||||
(uint16_t)errno);
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
|
@ -1720,12 +1738,17 @@ errout_with_lock:
|
|||
|
||||
#ifdef CONFIG_USBMSC_COMPOSITE
|
||||
int usbmsc_classobject(FAR void *handle,
|
||||
FAR struct usbdev_description_s *devdesc,
|
||||
FAR struct usbdevclass_driver_s **classdev)
|
||||
{
|
||||
FAR struct usbmsc_alloc_s *alloc = (FAR struct usbmsc_alloc_s *)handle;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(handle && classdev);
|
||||
DEBUGASSERT(handle != NULL && classdev != NULL);
|
||||
|
||||
/* Save the device description */
|
||||
|
||||
memcpy(&alloc->dev.devdesc, devdesc, sizeof(struct usbdev_description_s));
|
||||
|
||||
/* Export the LUNs as with the "standalone" USB mass storage driver, but
|
||||
* don't register the class instance with the USB device infrastructure.
|
||||
|
@ -1762,9 +1785,6 @@ void usbmsc_uninitialize(FAR void *handle)
|
|||
FAR struct usbmsc_alloc_s *alloc = (FAR struct usbmsc_alloc_s *)handle;
|
||||
FAR struct usbmsc_dev_s *priv;
|
||||
irqstate_t flags;
|
||||
#if 0
|
||||
void *value;
|
||||
#endif
|
||||
int i;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
|
@ -1860,3 +1880,61 @@ void usbmsc_uninitialize(FAR void *handle)
|
|||
kmm_free(priv);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_get_composite_devdesc
|
||||
*
|
||||
* Description:
|
||||
* Helper function to fill in some constants into the composite
|
||||
* configuration struct.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - Pointer to the configuration struct we should fill
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_USBDEV_COMPOSITE) && defined(CONFIG_USBMSC_COMPOSITE)
|
||||
void usbmsc_get_composite_devdesc(FAR struct composite_devdesc_s *dev)
|
||||
{
|
||||
memset(dev, 0, sizeof(struct composite_devdesc_s));
|
||||
|
||||
/* The callback functions for the CDC/ACM class.
|
||||
*
|
||||
* classobject() and uninitializ() must be provided by board-specific
|
||||
* logic
|
||||
*/
|
||||
|
||||
dev->mkconfdesc = usbmsc_mkcfgdesc;
|
||||
dev->mkstrdesc = usbmsc_mkstrdesc;
|
||||
|
||||
dev->nconfigs = USBMSC_NCONFIGS; /* Number of configurations supported */
|
||||
dev->configid = USBMSC_CONFIGID; /* The only supported configuration ID */
|
||||
dev->cfgdescsize = SIZEOF_USBMSC_CFGDESC; /* The size of the config descriptor */
|
||||
|
||||
/* Board-specific logic must provide the device minor */
|
||||
|
||||
/* Interfaces.
|
||||
*
|
||||
* ifnobase must be provided by board-specific logic
|
||||
*/
|
||||
|
||||
dev->devdesc.ninterfaces = USBMSC_NINTERFACES; /* Number of interfaces in the configuration */
|
||||
|
||||
/* Strings.
|
||||
*
|
||||
* strbase must be provided by board-specific logic
|
||||
*/
|
||||
|
||||
dev->devdesc.nstrings = USBMSC_NSTRIDS; /* Number of Strings */
|
||||
|
||||
/* Endpoints.
|
||||
*
|
||||
* Endpoint numbers must be provided by board-specific logic.
|
||||
*/
|
||||
|
||||
dev->devdesc.nendpoints = USBMSC_NENDPOINTS;
|
||||
}
|
||||
#endif
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* drivers/usbdev/usbmsc.h
|
||||
*
|
||||
* Copyright (C) 2008-2013, 2015 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2008-2013, 2015, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Mass storage class device. Bulk-only with SCSI subclass.
|
||||
|
@ -57,6 +57,7 @@
|
|||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Configuration ************************************************************/
|
||||
/* If the USB mass storage device is configured as part of a composite device
|
||||
* then both CONFIG_USBDEV_COMPOSITE and CONFIG_USBMSC_COMPOSITE must be
|
||||
|
@ -98,14 +99,18 @@
|
|||
|
||||
/* Logical endpoint numbers / max packet sizes */
|
||||
|
||||
#ifndef CONFIG_USBMSC_EPBULKOUT
|
||||
# warning "EPBULKOUT not defined in the configuration"
|
||||
# define CONFIG_USBMSC_EPBULKOUT 2
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
# ifndef CONFIG_USBMSC_EPBULKOUT
|
||||
# warning "EPBULKOUT not defined in the configuration"
|
||||
# define CONFIG_USBMSC_EPBULKOUT 2
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_USBMSC_EPBULKIN
|
||||
# warning "EPBULKIN not defined in the configuration"
|
||||
# define CONFIG_USBMSC_EPBULKIN 3
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
# ifndef CONFIG_USBMSC_EPBULKIN
|
||||
# warning "EPBULKIN not defined in the configuration"
|
||||
# define CONFIG_USBMSC_EPBULKIN 3
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Packet and request buffer sizes */
|
||||
|
@ -293,27 +298,19 @@
|
|||
#define USBMSC_LASTSTRID USBMSC_INTERFACESTRID
|
||||
#define USBMSC_NSTRIDS (USBMSC_LASTSTRID - CONFIG_USBMSC_STRBASE)
|
||||
|
||||
#define USBMSC_NCONFIGS (1) /* Number of configurations supported */
|
||||
|
||||
/* Configuration Descriptor */
|
||||
|
||||
#define USBMSC_NINTERFACES (1) /* Number of interfaces in the configuration */
|
||||
#define USBMSC_INTERFACEID (CONFIG_USBMSC_IFNOBASE+0)
|
||||
#define USBMSC_ALTINTERFACEID (0)
|
||||
|
||||
#define USBMSC_CONFIGIDNONE (0) /* Config ID means to return to address mode */
|
||||
#define USBMSC_CONFIGID (1) /* The only supported configuration ID */
|
||||
|
||||
/* Interface description */
|
||||
|
||||
#define USBMSC_NENDPOINTS (2) /* Number of endpoints in the interface */
|
||||
|
||||
/* Endpoint configuration */
|
||||
|
||||
#define USBMSC_EPOUTBULK_ADDR (CONFIG_USBMSC_EPBULKOUT)
|
||||
#define USBMSC_MKEPBULKOUT(devDesc) ((devDesc)->epno[USBMSC_EP_BULKOUT_IDX])
|
||||
#define USBMSC_EPOUTBULK_ATTR (USB_EP_ATTR_XFER_BULK)
|
||||
|
||||
#define USBMSC_EPINBULK_ADDR (USB_DIR_IN|CONFIG_USBMSC_EPBULKIN)
|
||||
#define USBMSC_MKEPBULKIN(devDesc) (USB_DIR_IN | (devDesc)->epno[USBMSC_EP_BULKIN_IDX])
|
||||
#define USBMSC_EPINBULK_ATTR (USB_EP_ATTR_XFER_BULK)
|
||||
|
||||
#define USBMSC_HSBULKMAXPACKET (512)
|
||||
|
@ -323,38 +320,10 @@
|
|||
#define USBMSC_FSBULKMXPKTSHIFT (6)
|
||||
#define USBMSC_FSBULKMXPKTMASK (0x0000003f)
|
||||
|
||||
/* Macros for dual speed vs. full speed only operation */
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
# define USBMSC_EPBULKINDESC(hs) \
|
||||
usbmsc_getepdesc((hs) ? USBMSC_EPHSBULKIN : USBMSC_EPFSBULKIN)
|
||||
# define USBMSC_EPBULKOUTDESC(hs) \
|
||||
usbmsc_getepdesc((hs) ? USBMSC_EPHSBULKOUT : USBMSC_EPFSBULKOUT)
|
||||
# define USBMSC_BULKMAXPACKET(hs) \
|
||||
((hs) ? USBMSC_HSBULKMAXPACKET : USBMSC_FSBULKMAXPACKET)
|
||||
# define USBMSC_BULKMXPKTSHIFT(d) \
|
||||
(((d)->speed==USB_SPEED_HIGH) ? USBMSC_HSBULKMXPKTSHIFT : USBMSC_FSBULKMXPKTSHIFT)
|
||||
# define USBMSC_BULKMXPKTMASK(d) \
|
||||
(((d)->speed==USB_SPEED_HIGH) ? USBMSC_HSBULKMXPKTMASK : USBMSC_FSBULKMXPKTMASK)
|
||||
#else
|
||||
# define USBMSC_EPBULKINDESC(d) usbmsc_getepdesc(USBMSC_EPFSBULKIN)
|
||||
# define USBMSC_EPBULKOUTDESC(d) usbmsc_getepdesc(USBMSC_EPFSBULKOUT)
|
||||
# define USBMSC_BULKMAXPACKET(hs) USBMSC_FSBULKMAXPACKET
|
||||
# define USBMSC_BULKMXPKTSHIFT(d) USBMSC_FSBULKMXPKTSHIFT
|
||||
# define USBMSC_BULKMXPKTMASK(d) USBMSC_FSBULKMXPKTMASK
|
||||
#endif
|
||||
|
||||
/* Configuration descriptor size */
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
|
||||
/* Number of individual descriptors in the configuration descriptor:
|
||||
* (1) Configuration descriptor + (1) interface descriptor + (2) interface
|
||||
* descriptors.
|
||||
*/
|
||||
|
||||
# define USBMSC_CFGGROUP_SIZE (4)
|
||||
|
||||
/* The size of the config descriptor: (9 + 9 + 2*7) = 32 */
|
||||
|
||||
# define SIZEOF_USBMSC_CFGDESC \
|
||||
|
@ -362,12 +331,6 @@
|
|||
|
||||
#else
|
||||
|
||||
/* Number of individual descriptors in the configuration descriptor:
|
||||
* (1) interface descriptor + (2) interface descriptors.
|
||||
*/
|
||||
|
||||
# define USBMSC_CFGGROUP_SIZE (3)
|
||||
|
||||
/* The size of the config descriptor: (9 + 2*7) = 23 */
|
||||
|
||||
# define SIZEOF_USBMSC_CFGDESC \
|
||||
|
@ -377,9 +340,12 @@
|
|||
|
||||
/* Block driver helpers *****************************************************/
|
||||
|
||||
#define USBMSC_DRVR_READ(l,b,s,n) ((l)->inode->u.i_bops->read((l)->inode,b,s,n))
|
||||
#define USBMSC_DRVR_WRITE(l,b,s,n) ((l)->inode->u.i_bops->write((l)->inode,b,s,n))
|
||||
#define USBMSC_DRVR_GEOMETRY(l,g) ((l)->inode->u.i_bops->geometry((l)->inode,g))
|
||||
#define USBMSC_DRVR_READ(l,b,s,n) \
|
||||
((l)->inode->u.i_bops->read((l)->inode,b,s,n))
|
||||
#define USBMSC_DRVR_WRITE(l,b,s,n) \
|
||||
((l)->inode->u.i_bops->write((l)->inode,b,s,n))
|
||||
#define USBMSC_DRVR_GEOMETRY(l,g) \
|
||||
((l)->inode->u.i_bops->geometry((l)->inode,g))
|
||||
|
||||
/* Everpresent MIN/MAX macros ***********************************************/
|
||||
|
||||
|
@ -398,13 +364,8 @@
|
|||
|
||||
enum usbmsc_epdesc_e
|
||||
{
|
||||
USBMSC_EPFSBULKOUT = 0, /* Full speed bulk OUT endpoint descriptor */
|
||||
USBMSC_EPFSBULKIN /* Full speed bulk IN endpoint descriptor */
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
,
|
||||
USBMSC_EPHSBULKOUT, /* High speed bulk OUT endpoint descriptor */
|
||||
USBMSC_EPHSBULKIN /* High speed bulk IN endpoint descriptor */
|
||||
#endif
|
||||
USBMSC_EPBULKOUT = 0, /* Bulk OUT endpoint descriptor */
|
||||
USBMSC_EPBULKIN /* Bulk IN endpoint descriptor */
|
||||
};
|
||||
|
||||
/* Container to support a list of requests */
|
||||
|
@ -419,7 +380,7 @@ struct usbmsc_req_s
|
|||
|
||||
struct usbmsc_lun_s
|
||||
{
|
||||
struct inode *inode; /* Inode structure of open'ed block driver */
|
||||
FAR struct inode *inode; /* Inode structure of open'ed block driver */
|
||||
uint8_t readonly:1; /* Media is read-only */
|
||||
uint8_t locked:1; /* Media removal is prevented */
|
||||
uint16_t sectorsize; /* The size of one sector */
|
||||
|
@ -487,6 +448,8 @@ struct usbmsc_dev_s
|
|||
struct sq_queue_s wrreqlist; /* List of empty write request containers */
|
||||
struct sq_queue_s rdreqlist; /* List of filled read request containers */
|
||||
|
||||
struct usbdev_description_s devdesc;
|
||||
|
||||
/* Pre-allocated write request containers. The write requests will
|
||||
* be linked in a free list (wrreqlist), and used to send requests to
|
||||
* EPBULKIN; Read requests will be queued in the EBULKOUT.
|
||||
|
@ -536,11 +499,11 @@ EXTERN const char g_compserialstr[];
|
|||
|
||||
EXTERN FAR struct usbmsc_dev_s *g_usbmsc_handoff;
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_scsi_lock
|
||||
*
|
||||
* Description:
|
||||
|
@ -550,91 +513,95 @@ EXTERN FAR struct usbmsc_dev_s *g_usbmsc_handoff;
|
|||
|
||||
void usbmsc_scsi_lock(FAR struct usbmsc_dev_s *priv);
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_scsi_unlock
|
||||
*
|
||||
* Description:
|
||||
* Relinquish exclusive access to SCSI state data.
|
||||
*
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
#define usbmsc_scsi_unlock(priv) sem_post(&priv->thlock)
|
||||
|
||||
/************************************************************************************
|
||||
/*****************************************************************************
|
||||
* Name: usbmsc_scsi_signal
|
||||
*
|
||||
* Description:
|
||||
* Signal the SCSI worker thread that SCSI events need service.
|
||||
*
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
void usbmsc_scsi_signal(FAR struct usbmsc_dev_s *priv);
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_synch_signal
|
||||
*
|
||||
* Description:
|
||||
* ACK controlling tasks request for synchronization.
|
||||
*
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
#define usbmsc_synch_signal(priv) sem_post(&priv->thsynch)
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_mkstrdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct a string descriptor
|
||||
*
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
struct usb_strdesc_s;
|
||||
int usbmsc_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc);
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_getdevdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw device descriptor
|
||||
*
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
FAR const struct usb_devdesc_s *usbmsc_getdevdesc(void);
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Name: usbmsc_getepdesc
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_copy_epdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw endpoint descriptor (used for configuring endpoints)
|
||||
* Copies the requested Endpoint Description into the buffer given.
|
||||
* Returns the number of Bytes filled in ( sizeof(struct usb_epdesc_s) ).
|
||||
*
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
struct usb_epdesc_s;
|
||||
FAR const struct usb_epdesc_s *usbmsc_getepdesc(enum usbmsc_epdesc_e epid);
|
||||
int usbmsc_copy_epdesc(enum usbmsc_epdesc_e epid,
|
||||
FAR struct usb_epdesc_s *epdesc,
|
||||
FAR struct usbdev_description_s *devdesc,
|
||||
bool hispeed);
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_mkcfgdesc
|
||||
*
|
||||
* Description:
|
||||
* Construct the configuration descriptor
|
||||
*
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
int16_t usbmsc_mkcfgdesc(FAR uint8_t *buf, uint8_t speed, uint8_t type);
|
||||
int16_t usbmsc_mkcfgdesc(FAR uint8_t *buf, FAR struct usbdev_description_s *devdesc,
|
||||
uint8_t speed, uint8_t type);
|
||||
#else
|
||||
int16_t usbmsc_mkcfgdesc(FAR uint8_t *buf);
|
||||
int16_t usbmsc_mkcfgdesc(FAR uint8_t *buf, FAR struct usbdev_description_s *devdesc);
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_getqualdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw qual descriptor
|
||||
*
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_USBMSC_COMPOSITE) && defined(CONFIG_USBDEV_DUALSPEED)
|
||||
FAR const struct usb_qualdesc_s *usbmsc_getqualdesc(void);
|
||||
|
@ -725,4 +692,4 @@ void usbmsc_deferredresponse(FAR struct usbmsc_dev_s *priv, bool failed);
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif /* #define __DRIVERS_USBDEV_USBMSC_H */
|
||||
#endif /* __DRIVERS_USBDEV_USBMSC_H */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* drivers/usbdev/usbmsc_desc.c
|
||||
*
|
||||
* Copyright (C) 2011-2012, 2015 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011-2012, 2015, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -50,21 +50,10 @@
|
|||
|
||||
#include "usbmsc.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* Descriptors **************************************************************/
|
||||
/* Device descriptor. If the USB mass storage device is configured as part
|
||||
* of a composite device, then the device descriptor will be provided by the
|
||||
|
@ -92,79 +81,13 @@ static const struct usb_devdesc_s g_devdesc =
|
|||
LSBYTE(CONFIG_USBMSC_VERSIONNO),
|
||||
MSBYTE(CONFIG_USBMSC_VERSIONNO)
|
||||
},
|
||||
USBMSC_MANUFACTURERSTRID, /* imfgr */
|
||||
USBMSC_PRODUCTSTRID, /* iproduct */
|
||||
USBMSC_SERIALSTRID, /* serno */
|
||||
USBMSC_NCONFIGS /* nconfigs */
|
||||
USBMSC_MANUFACTURERSTRID, /* imfgr */
|
||||
USBMSC_PRODUCTSTRID, /* iproduct */
|
||||
USBMSC_SERIALSTRID, /* serno */
|
||||
USBMSC_NCONFIGS /* nconfigs */
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Configuration descriptor If the USB mass storage device is configured as part
|
||||
* of a composite device, then the configuration descriptor will be provided by the
|
||||
* composite device logic.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
static const struct usb_cfgdesc_s g_cfgdesc =
|
||||
{
|
||||
USB_SIZEOF_CFGDESC, /* len */
|
||||
USB_DESC_TYPE_CONFIG, /* type */
|
||||
{ /* totallen */
|
||||
LSBYTE(SIZEOF_USBMSC_CFGDESC),
|
||||
MSBYTE(SIZEOF_USBMSC_CFGDESC)
|
||||
},
|
||||
USBMSC_NINTERFACES, /* ninterfaces */
|
||||
USBMSC_CONFIGID, /* cfgvalue */
|
||||
USBMSC_CONFIGSTRID, /* icfg */
|
||||
USB_CONFIG_ATTR_ONE | /* attr */
|
||||
USBMSC_SELFPOWERED |
|
||||
USBMSC_REMOTEWAKEUP,
|
||||
(CONFIG_USBDEV_MAXPOWER + 1) / 2 /* mxpower */
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Single interface descriptor */
|
||||
|
||||
static const struct usb_ifdesc_s g_ifdesc =
|
||||
{
|
||||
USB_SIZEOF_IFDESC, /* len */
|
||||
USB_DESC_TYPE_INTERFACE, /* type */
|
||||
USBMSC_INTERFACEID, /* ifno */
|
||||
USBMSC_ALTINTERFACEID, /* alt */
|
||||
USBMSC_NENDPOINTS, /* neps */
|
||||
USB_CLASS_MASS_STORAGE, /* classid */
|
||||
USBMSC_SUBCLASS_SCSI, /* subclass */
|
||||
USBMSC_PROTO_BULKONLY, /* protocol */
|
||||
USBMSC_INTERFACESTRID /* iif */
|
||||
};
|
||||
|
||||
/* Endpoint descriptors */
|
||||
|
||||
static const struct usb_epdesc_s g_fsepbulkoutdesc =
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* len */
|
||||
USB_DESC_TYPE_ENDPOINT, /* type */
|
||||
USBMSC_EPOUTBULK_ADDR, /* addr */
|
||||
USBMSC_EPOUTBULK_ATTR, /* attr */
|
||||
{ /* maxpacket */
|
||||
LSBYTE(USBMSC_FSBULKMAXPACKET),
|
||||
MSBYTE(USBMSC_FSBULKMAXPACKET)
|
||||
},
|
||||
0 /* interval */
|
||||
};
|
||||
|
||||
static const struct usb_epdesc_s g_fsepbulkindesc =
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* len */
|
||||
USB_DESC_TYPE_ENDPOINT, /* type */
|
||||
USBMSC_EPINBULK_ADDR, /* addr */
|
||||
USBMSC_EPINBULK_ATTR, /* attr */
|
||||
{ /* maxpacket */
|
||||
LSBYTE(USBMSC_FSBULKMAXPACKET),
|
||||
MSBYTE(USBMSC_FSBULKMAXPACKET)
|
||||
},
|
||||
0 /* interval */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
|
@ -184,32 +107,6 @@ static const struct usb_qualdesc_s g_qualdesc =
|
|||
0, /* reserved */
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct usb_epdesc_s g_hsepbulkoutdesc =
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* len */
|
||||
USB_DESC_TYPE_ENDPOINT, /* type */
|
||||
USBMSC_EPOUTBULK_ADDR, /* addr */
|
||||
USBMSC_EPOUTBULK_ATTR, /* attr */
|
||||
{ /* maxpacket */
|
||||
LSBYTE(USBMSC_HSBULKMAXPACKET),
|
||||
MSBYTE(USBMSC_HSBULKMAXPACKET)
|
||||
},
|
||||
0 /* interval */
|
||||
};
|
||||
|
||||
static const struct usb_epdesc_s g_hsepbulkindesc =
|
||||
{
|
||||
USB_SIZEOF_EPDESC, /* len */
|
||||
USB_DESC_TYPE_ENDPOINT, /* type */
|
||||
USBMSC_EPINBULK_ADDR, /* addr */
|
||||
USBMSC_EPINBULK_ATTR, /* attr */
|
||||
{ /* maxpacket */
|
||||
LSBYTE(USBMSC_HSBULKMAXPACKET),
|
||||
MSBYTE(USBMSC_HSBULKMAXPACKET)
|
||||
},
|
||||
0 /* interval */
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -304,7 +201,7 @@ int usbmsc_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc)
|
|||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_getepdesc
|
||||
* Name: usbmsc_getdevdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw device descriptor
|
||||
|
@ -319,35 +216,89 @@ FAR const struct usb_devdesc_s *usbmsc_getdevdesc(void)
|
|||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_getepdesc
|
||||
* Name: usbmsc_copy_epdesc
|
||||
*
|
||||
* Description:
|
||||
* Return a pointer to the raw endpoint descriptor (used for configuring
|
||||
* endpoints)
|
||||
* Copies the requested Endpoint Description into the buffer given.
|
||||
* Returns the number of Bytes filled in ( sizeof(struct usb_epdesc_s) ).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR const struct usb_epdesc_s *usbmsc_getepdesc(enum usbmsc_epdesc_e epid)
|
||||
int usbmsc_copy_epdesc(enum usbmsc_epdesc_e epid,
|
||||
FAR struct usb_epdesc_s *epdesc,
|
||||
FAR struct usbdev_description_s *devdesc,
|
||||
bool hispeed)
|
||||
{
|
||||
switch (epid)
|
||||
{
|
||||
case USBMSC_EPFSBULKOUT: /* Full speed bulk OUT endpoint descriptor */
|
||||
return &g_fsepbulkoutdesc;
|
||||
#ifndef CONFIG_USBDEV_DUALSPEED
|
||||
/* unused */
|
||||
|
||||
case USBMSC_EPFSBULKIN: /* Full speed bulk IN endpoint descriptor */
|
||||
return &g_fsepbulkindesc;
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
case USBMSC_EPHSBULKOUT: /* High speed bulk OUT endpoint descriptor */
|
||||
return &g_hsepbulkoutdesc;
|
||||
|
||||
case USBMSC_EPHSBULKIN: /* High speed bulk IN endpoint descriptor */
|
||||
return &g_hsepbulkindesc;
|
||||
(void)hispeed;
|
||||
#endif
|
||||
default:
|
||||
return NULL;
|
||||
|
||||
switch (epid)
|
||||
{
|
||||
case USBMSC_EPBULKOUT: /* Bulk OUT endpoint */
|
||||
{
|
||||
epdesc->len = USB_SIZEOF_EPDESC; /* Descriptor length */
|
||||
epdesc->type = USB_DESC_TYPE_ENDPOINT; /* Descriptor type */
|
||||
epdesc->addr = USBMSC_MKEPBULKOUT(devdesc); /* Endpoint address */
|
||||
epdesc->attr = USBMSC_EPOUTBULK_ATTR; /* Endpoint attributes */
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
if (hispeed)
|
||||
{
|
||||
/* Maximum packet size (high speed) */
|
||||
|
||||
epdesc->mxpacketsize[0] = LSBYTE(USBMSC_HSBULKMAXPACKET);
|
||||
epdesc->mxpacketsize[1] = MSBYTE(USBMSC_HSBULKMAXPACKET);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Maximum packet size (full speed) */
|
||||
|
||||
epdesc->mxpacketsize[0] = LSBYTE(USBMSC_FSBULKMAXPACKET);
|
||||
epdesc->mxpacketsize[1] = MSBYTE(USBMSC_FSBULKMAXPACKET);
|
||||
}
|
||||
|
||||
epdesc->interval = 0; /* Interval */
|
||||
}
|
||||
break;
|
||||
|
||||
case USBMSC_EPBULKIN: /* Bulk IN endpoint */
|
||||
{
|
||||
epdesc->len = USB_SIZEOF_EPDESC; /* Descriptor length */
|
||||
epdesc->type = USB_DESC_TYPE_ENDPOINT; /* Descriptor type */
|
||||
epdesc->addr = USBMSC_MKEPBULKIN(devdesc); /* Endpoint address */
|
||||
epdesc->attr = USBMSC_EPINBULK_ATTR; /* Endpoint attributes */
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
if (hispeed)
|
||||
{
|
||||
/* Maximum packet size (high speed) */
|
||||
|
||||
epdesc->mxpacketsize[0] = LSBYTE(USBMSC_HSBULKMAXPACKET);
|
||||
epdesc->mxpacketsize[1] = MSBYTE(USBMSC_HSBULKMAXPACKET);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* Maximum packet size (full speed) */
|
||||
|
||||
epdesc->mxpacketsize[0] = LSBYTE(USBMSC_FSBULKMAXPACKET);
|
||||
epdesc->mxpacketsize[1] = MSBYTE(USBMSC_FSBULKMAXPACKET);
|
||||
}
|
||||
|
||||
epdesc->interval = 0; /* Interval */
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
return sizeof(struct usb_epdesc_s);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_mkcfgdesc
|
||||
|
@ -358,53 +309,104 @@ FAR const struct usb_epdesc_s *usbmsc_getepdesc(enum usbmsc_epdesc_e epid)
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
int16_t usbmsc_mkcfgdesc(uint8_t *buf, uint8_t speed, uint8_t type)
|
||||
int16_t usbmsc_mkcfgdesc(uint8_t *buf,
|
||||
FAR struct usbdev_description_s *devdesc,
|
||||
uint8_t speed, uint8_t type)
|
||||
#else
|
||||
int16_t usbmsc_mkcfgdesc(uint8_t *buf)
|
||||
int16_t usbmsc_mkcfgdesc(uint8_t *buf,
|
||||
FAR struct usbdev_description_s *devdesc)
|
||||
#endif
|
||||
{
|
||||
int length = 0;
|
||||
bool hispeed = false;
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
FAR const struct usb_epdesc_s *epdesc;
|
||||
bool hispeed;
|
||||
hispeed = (speed == USB_SPEED_HIGH);
|
||||
|
||||
/* Check for switches between high and full speed */
|
||||
|
||||
if (type == USB_DESC_TYPE_OTHERSPEEDCONFIG)
|
||||
{
|
||||
hispeed = !hispeed;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Fill in all descriptors directly to the buf */
|
||||
|
||||
/* Configuration descriptor. If the USB mass storage device is
|
||||
* configured as part of a composite device, then the configuration
|
||||
* descriptor will be provided by the composite device logic.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_USBMSC_COMPOSITE
|
||||
memcpy(buf, &g_cfgdesc, USB_SIZEOF_CFGDESC);
|
||||
buf += USB_SIZEOF_CFGDESC;
|
||||
{
|
||||
/* Configuration descriptor If the USB mass storage device is configured as part
|
||||
* of a composite device, then the configuration descriptor will be provided by the
|
||||
* composite device logic.
|
||||
*/
|
||||
|
||||
FAR struct usb_cfgdesc_s *dest = (FAR struct usb_cfgdesc_s *)buf;
|
||||
|
||||
dest->len = USB_SIZEOF_CFGDESC; /* Descriptor length */
|
||||
dest->type = USB_DESC_TYPE_CONFIG; /* Descriptor type */
|
||||
dest->totallen[0] = LSBYTE(SIZEOF_USBMSC_CFGDESC); /* LS Total length */
|
||||
dest->totallen[1] = MSBYTE(SIZEOF_USBMSC_CFGDESC); /* MS Total length */
|
||||
dest->ninterfaces = USBMSC_NINTERFACES; /* Number of interfaces */
|
||||
dest->cfgvalue = USBMSC_CONFIGID; /* Configuration value */
|
||||
dest->icfg = USBMSC_CONFIGSTRID; /* Configuration */
|
||||
dest->attr = USB_CONFIG_ATTR_ONE | /* Attributes */
|
||||
USBMSC_SELFPOWERED |
|
||||
USBMSC_REMOTEWAKEUP;
|
||||
dest->mxpower = (CONFIG_USBDEV_MAXPOWER + 1) / 2; /* Max power (mA/2) */
|
||||
|
||||
buf += sizeof(struct usb_cfgdesc_s);
|
||||
length += sizeof(struct usb_cfgdesc_s);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Copy the canned interface descriptor */
|
||||
|
||||
memcpy(buf, &g_ifdesc, USB_SIZEOF_IFDESC);
|
||||
buf += USB_SIZEOF_IFDESC;
|
||||
{
|
||||
/* Single interface descriptor */
|
||||
|
||||
FAR struct usb_ifdesc_s * dest = (struct usb_ifdesc_s *)buf;
|
||||
|
||||
dest->len = USB_SIZEOF_IFDESC; /* Descriptor length */
|
||||
dest->type = USB_DESC_TYPE_INTERFACE; /* Descriptor type */
|
||||
dest->ifno = devdesc->ifnobase; /* Interface number */
|
||||
dest->alt = USBMSC_ALTINTERFACEID; /* Alternate setting */
|
||||
dest->neps = USBMSC_NENDPOINTS; /* Number of endpoints */
|
||||
dest->classid = USB_CLASS_MASS_STORAGE; /* Interface class */
|
||||
dest->subclass = USBMSC_SUBCLASS_SCSI; /* Interface sub-class */
|
||||
dest->protocol = USBMSC_PROTO_BULKONLY; /* Interface protocol */
|
||||
dest->iif = devdesc->strbase + USBMSC_INTERFACESTRID; /* iInterface */
|
||||
|
||||
buf += sizeof(struct usb_ifdesc_s);
|
||||
length += sizeof(struct usb_ifdesc_s);
|
||||
}
|
||||
|
||||
/* Make the two endpoint configurations */
|
||||
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
/* Check for switches between high and full speed */
|
||||
/* Bulk IN endpoint descriptor */
|
||||
|
||||
hispeed = (speed == USB_SPEED_HIGH);
|
||||
if (type == USB_DESC_TYPE_OTHERSPEEDCONFIG)
|
||||
{
|
||||
hispeed = !hispeed;
|
||||
}
|
||||
{
|
||||
int len = usbmsc_copy_epdesc(USBMSC_EPBULKIN, (FAR struct usb_epdesc_s *)buf,
|
||||
devdesc, hispeed);
|
||||
|
||||
epdesc = USBMSC_EPBULKINDESC(hispeed);
|
||||
memcpy(buf, epdesc, USB_SIZEOF_EPDESC);
|
||||
buf += USB_SIZEOF_EPDESC;
|
||||
buf += len;
|
||||
length += len;
|
||||
}
|
||||
|
||||
epdesc = USBMSC_EPBULKOUTDESC(hispeed);
|
||||
memcpy(buf, epdesc, USB_SIZEOF_EPDESC);
|
||||
#else
|
||||
memcpy(buf, &g_fsepbulkoutdesc, USB_SIZEOF_EPDESC);
|
||||
buf += USB_SIZEOF_EPDESC;
|
||||
memcpy(buf, &g_fsepbulkindesc, USB_SIZEOF_EPDESC);
|
||||
#endif
|
||||
/* Bulk OUT endpoint descriptor */
|
||||
|
||||
{
|
||||
int len = usbmsc_copy_epdesc(USBMSC_EPBULKOUT,
|
||||
(FAR struct usb_epdesc_s *)buf, devdesc,
|
||||
hispeed);
|
||||
|
||||
buf += len;
|
||||
length += len;
|
||||
}
|
||||
|
||||
return SIZEOF_USBMSC_CFGDESC;
|
||||
}
|
||||
|
@ -423,4 +425,3 @@ FAR const struct usb_qualdesc_s *usbmsc_getqualdesc(void)
|
|||
return &g_qualdesc;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -263,6 +263,28 @@ int board_composite_initialize(int port);
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_composite_connect
|
||||
*
|
||||
* Description:
|
||||
* Connect the USB composite device on the specified USB device port using
|
||||
* the specified configuration. The interpretation of the configid is
|
||||
* board specific.
|
||||
*
|
||||
* Input Parameters:
|
||||
* port - The USB device port.
|
||||
* configid - The USB composite configuration
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL handle value is returned on success. NULL is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_BOARDCTL_USBDEVCTRL) && defined(CONFIG_USBDEV_COMPOSITE)
|
||||
FAR void *board_composite_connect(int port, int configid);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_tsc_setup
|
||||
*
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/********************************************************************************************
|
||||
* include/nuttx/usb/cdc.h
|
||||
*
|
||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* References: "Universal Serial Bus Class Definitions for Communication
|
||||
|
@ -73,7 +73,7 @@
|
|||
/* Table 17: Communication Interface Class Control Protocol Codes */
|
||||
|
||||
#define CDC_PROTO_NONE 0x00 /* No class specific protocol required */
|
||||
#define CDC_PROTO_ATM 0x01 /* Common AT commands (also known as Hayes compatible”) */
|
||||
#define CDC_PROTO_ATM 0x01 /* Common AT commands (also known as Hayes compatible) */
|
||||
/* 0x02-0xfe Reserved (future use) */
|
||||
#define CDC_PROTO_VENDOR 0xff /* Vendor-specific */
|
||||
|
||||
|
@ -242,12 +242,12 @@
|
|||
* (Optional)
|
||||
*/
|
||||
#define ECM_SET_MCAST_FILTERS 0x40 /* As applications are loaded and unloaded on the host,
|
||||
* the networking transport will instruct the device’s MAC
|
||||
* driver to change settings of the Networking device’s
|
||||
* the networking transport will instruct the device's MAC
|
||||
* driver to change settings of the Networking device's
|
||||
* multicast filters. (Optional)
|
||||
*/
|
||||
#define ECM_SET_PM_PAT_FILTER 0x41 /* Some hosts are able to conserve energy and stay quiet
|
||||
* in a “sleeping” state while not being used. USB
|
||||
* in a "sleeping" state while not being used. USB
|
||||
* Networking devices may provide special pattern filtering
|
||||
* hardware that enables it to wake up the attached host
|
||||
* on demand when something is attempting to contact the
|
||||
|
@ -593,9 +593,8 @@ struct cdc_hdr_funcdesc_s
|
|||
uint8_t size; /* bFunctionLength, Size of this descriptor */
|
||||
uint8_t type; /* bDescriptorType, USB_DESC_TYPE_CSINTERFACE */
|
||||
uint8_t subtype; /* bDescriptorSubType, CDC_DSUBTYPE_HDR as defined in Table 25 */
|
||||
uint8_t cdc[2]; /* bcdCDC, USB Class Definitions for Communication Devices Specification release
|
||||
* number in binary-coded decimal.
|
||||
*/
|
||||
uint8_t cdc[2]; /* bcdCDC, USB Class Definitions for Communication Devices Specification
|
||||
* release number in binary-coded decimal. */
|
||||
};
|
||||
#define SIZEOF_HDR_FUNCDESC 5
|
||||
|
||||
|
@ -788,7 +787,7 @@ struct cdc_capi_funcdesc_s
|
|||
};
|
||||
#define SIZEOF_CAPI_FUNCDESC 4
|
||||
|
||||
/* Table 41: Ethernet Networking Functional Descriptor*/
|
||||
/* Table 41: Ethernet Networking Functional Descriptor */
|
||||
|
||||
struct cdc_ecm_funcdesc_s
|
||||
{
|
||||
|
@ -833,7 +832,7 @@ struct cdc_atm_funcdesc_s
|
|||
* capable of supporting
|
||||
*/
|
||||
};
|
||||
#define SIZEOF_CALLMGMT_FUNCDESC 12
|
||||
#define SIZEOF_ATM_FUNCDESC 12
|
||||
|
||||
/* Descriptor Data Structures ***************************************************************/
|
||||
/* Table 50: Line Coding Structure */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
* include/nuttx/usb/cdcacm.h
|
||||
*
|
||||
* Copyright (C) 2011-2012, 2015 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011-2012, 2015, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -47,6 +47,7 @@
|
|||
/****************************************************************************
|
||||
* Preprocessor definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Configuration ************************************************************/
|
||||
/* CONFIG_CDCACM
|
||||
* Enable compilation of the USB serial driver
|
||||
|
@ -96,6 +97,22 @@
|
|||
* Size of the serial receive/transmit buffers. Default 256.
|
||||
*/
|
||||
|
||||
/* Informations needed in usbdev_description_s */
|
||||
|
||||
#define CDCACM_NUM_EPS (3)
|
||||
|
||||
#define CDCACM_EP_INTIN_IDX (0)
|
||||
#define CDCACM_EP_BULKIN_IDX (1)
|
||||
#define CDCACM_EP_BULKOUT_IDX (2)
|
||||
|
||||
#define CDCACM_NCONFIGS (1) /* Number of configurations supported */
|
||||
|
||||
/* Configuration descriptor values */
|
||||
|
||||
#define CDCACM_CONFIGID (1) /* The only supported configuration ID */
|
||||
|
||||
#define CDCACM_NINTERFACES (2) /* Number of interfaces in the configuration */
|
||||
|
||||
/* EP0 max packet size */
|
||||
|
||||
#ifndef CONFIG_CDCACM_EP0MAXPACKET
|
||||
|
@ -106,8 +123,10 @@
|
|||
* notification interrupt endpoint.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_CDCACM_EPINTIN
|
||||
# define CONFIG_CDCACM_EPINTIN 1
|
||||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
# ifndef CONFIG_CDCACM_EPINTIN
|
||||
# define CONFIG_CDCACM_EPINTIN 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_CDCACM_EPINTIN_FSSIZE
|
||||
|
@ -127,8 +146,10 @@
|
|||
* size will be followed by a NULL packet.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_CDCACM_EPBULKIN
|
||||
# define CONFIG_CDCACM_EPBULKIN 2
|
||||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
# ifndef CONFIG_CDCACM_EPBULKIN
|
||||
# define CONFIG_CDCACM_EPBULKIN 2
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_CDCACM_EPBULKIN_FSSIZE
|
||||
|
@ -155,8 +176,10 @@
|
|||
* maxpacket size.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_CDCACM_EPBULKOUT
|
||||
# define CONFIG_CDCACM_EPBULKOUT 3
|
||||
#ifndef CONFIG_CDCACM_COMPOSITE
|
||||
# ifndef CONFIG_CDCACM_EPBULKOUT
|
||||
# define CONFIG_CDCACM_EPBULKOUT 3
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_CDCACM_EPBULKOUT_FSSIZE
|
||||
|
@ -306,51 +329,6 @@ typedef FAR void (*cdcacm_callback_t)(enum cdcacm_event_e event);
|
|||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_cdcclassobject
|
||||
*
|
||||
* Description:
|
||||
* If the CDC serial class driver is part of composite device, then
|
||||
* board-specific logic must provide board_cdcclassobject(). In the
|
||||
* simplest case, board_cdcclassobject() is simply a wrapper around
|
||||
* cdcacm_classobject() that provides the correct device minor number.
|
||||
*
|
||||
* Input Parameters:
|
||||
* classdev - The location to return the CDC serial class' device
|
||||
* instance.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success; a negated errno on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_USBDEV_COMPOSITE) && defined(CONFIG_CDCACM_COMPOSITE)
|
||||
struct usbdevclass_driver_s;
|
||||
int board_cdcclassobject(FAR struct usbdevclass_driver_s **classdev);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_cdcuninitialize
|
||||
*
|
||||
* Description:
|
||||
* Un-initialize the USB serial class driver. This is just an application-
|
||||
* specific wrapper around cdcadm_unitialize() that is called form the
|
||||
* composite device logic.
|
||||
*
|
||||
* Input Parameters:
|
||||
* classdev - The class driver instance previously give to the composite
|
||||
* driver by board_cdcclassobject().
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_USBDEV_COMPOSITE) && defined(CONFIG_CDCACM_COMPOSITE)
|
||||
struct usbdevclass_driver_s;
|
||||
void board_cdcuninitialize(FAR struct usbdevclass_driver_s *classdev);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_classobject
|
||||
*
|
||||
|
@ -370,7 +348,10 @@ void board_cdcuninitialize(FAR struct usbdevclass_driver_s *classdev);
|
|||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_USBDEV_COMPOSITE) && defined(CONFIG_CDCACM_COMPOSITE)
|
||||
int cdcacm_classobject(int minor, FAR struct usbdevclass_driver_s **classdev);
|
||||
struct usbdev_description_s;
|
||||
struct usbdevclass_driver_s;
|
||||
int cdcacm_classobject(int minor, FAR struct usbdev_description_s *devdesc,
|
||||
FAR struct usbdevclass_driver_s **classdev);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -409,8 +390,7 @@ int cdcacm_initialize(int minor, FAR void **handle);
|
|||
* CDC/ACM driver is an internal part of a composite device, or a
|
||||
* standalone USB driver:
|
||||
*
|
||||
* classdev - The class object returned by board_cdcclassobject() or
|
||||
* cdcacm_classobject()
|
||||
* classdev - The class object returned by cdcacm_classobject()
|
||||
* handle - The opaque handle representing the class object returned by
|
||||
* a previous call to cdcacm_initialize().
|
||||
*
|
||||
|
@ -425,6 +405,26 @@ void cdcacm_uninitialize(FAR struct usbdevclass_driver_s *classdev);
|
|||
void cdcacm_uninitialize(FAR void *handle);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cdcacm_get_composite_devdesc
|
||||
*
|
||||
* Description:
|
||||
* Helper function to fill in some constants into the composite
|
||||
* configuration struct.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - Pointer to the configuration struct we should fill
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_USBDEV_COMPOSITE) && defined(CONFIG_CDCACM_COMPOSITE)
|
||||
struct composite_devdesc_s;
|
||||
void cdcacm_get_composite_devdesc(struct composite_devdesc_s *dev);
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/************************************************************************************
|
||||
* include/nuttx/usb/composite.h
|
||||
*
|
||||
* Copyright (C) 2008-2011, 2015 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2008-2011, 2015, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -41,12 +41,14 @@
|
|||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/usb/usbdev.h>
|
||||
|
||||
#ifdef CONFIG_USBDEV_COMPOSITE
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Configuration ************************************************************/
|
||||
/* CONFIG_USBDEV_COMPOSITE
|
||||
* Enables USB composite device support
|
||||
|
@ -70,6 +72,11 @@
|
|||
* Interface version number.
|
||||
*/
|
||||
|
||||
#define COMPOSITE_NSTRIDS (5) /* The numer of String-IDs to
|
||||
* reserve for the composite device */
|
||||
#define COMPOSITE_NCONFIGS (1) /* The number of configurations
|
||||
* supported */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
@ -97,8 +104,7 @@ extern "C"
|
|||
* Description:
|
||||
* Register USB composite device as configured. This function will call
|
||||
* board-specific implementations in order to obtain the class objects for
|
||||
* each of the members of the composite (see board_mscclassobject(),
|
||||
* board_cdcclassobjec(), ...)
|
||||
* each of the members of the composite.
|
||||
*
|
||||
* Input Parameter:
|
||||
* None
|
||||
|
@ -113,7 +119,8 @@ extern "C"
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR void *composite_initialize(void);
|
||||
FAR void *composite_initialize(uint8_t ndevices,
|
||||
FAR struct composite_devdesc_s *pdevices);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_uninitialize
|
||||
|
@ -122,8 +129,7 @@ FAR void *composite_initialize(void);
|
|||
* Un-initialize the USB composite driver. The handle is the USB composite
|
||||
* class' device object as was returned by composite_initialize(). This
|
||||
* function will call board-specific implementations in order to free the
|
||||
* class objects for each of the members of the composite (see
|
||||
* board_mscuninitialize(), board_cdcuninitialize(), ...)
|
||||
* class objects for each of the members of the composite.
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - The handle returned by a previous call to composite_initialize().
|
||||
|
@ -135,30 +141,6 @@ FAR void *composite_initialize(void);
|
|||
|
||||
void composite_uninitialize(FAR void *handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_initialize
|
||||
*
|
||||
* Description:
|
||||
* Register USB composite device as configured. This function will call
|
||||
* board-specific implementations in order to obtain the class objects for
|
||||
* each of the members of the composite (see board_mscclassobject(),
|
||||
* board_cdcclassobjec(), ...)
|
||||
*
|
||||
* Input Parameter:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* A non-NULL "handle" is returned on success. This handle may be used
|
||||
* later with composite_uninitialize() in order to removed the composite
|
||||
* device. This handle is the (untyped) internal representation of the
|
||||
* the class driver instance.
|
||||
*
|
||||
* NULL is returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR void *composite_initialize(void);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: composite_ep0submit
|
||||
*
|
||||
|
|
|
@ -196,6 +196,48 @@
|
|||
|
||||
/* USB Controller Structures ********************************************************/
|
||||
|
||||
/* usbdev_description_s - describes the low level bindings of an usb device */
|
||||
|
||||
struct usbdev_description_s
|
||||
{
|
||||
int ninterfaces; /* Number of interfaces in the configuration */
|
||||
int ifnobase; /* Offset to Interface-IDs */
|
||||
|
||||
int nstrings; /* Number of Strings */
|
||||
int strbase; /* Offset to String Numbers */
|
||||
|
||||
int nendpoints; /* Number of Endpoints referenced in the following allay */
|
||||
int epno[5]; /* Array holding the endpoint configuration for this device */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USBDEV_COMPOSITE
|
||||
struct composite_devdesc_s
|
||||
{
|
||||
#ifdef CONFIG_USBDEV_DUALSPEED
|
||||
CODE int16_t (*mkconfdesc)(FAR uint8_t *buf,
|
||||
FAR struct usbdev_description_s *devdesc,
|
||||
uint8_t speed, uint8_t type);
|
||||
#else
|
||||
CODE int16_t (*mkconfdesc)(FAR uint8_t *buf,
|
||||
FAR struct usbdev_description_s *devdesc);
|
||||
#endif
|
||||
|
||||
CODE int (*mkstrdesc)(uint8_t id, FAR struct usb_strdesc_s *strdesc);
|
||||
CODE int (*classobject)(int minor,
|
||||
FAR struct usbdev_description_s *devdesc,
|
||||
FAR struct usbdevclass_driver_s **classdev);
|
||||
CODE void (*uninitialize)(FAR struct usbdevclass_driver_s *classdev);
|
||||
|
||||
int nconfigs; /* Number of configurations supported */
|
||||
int configid; /* The only supported configuration ID */
|
||||
|
||||
int cfgdescsize; /* The size of the config descriptor */
|
||||
int minor;
|
||||
|
||||
struct usbdev_description_s devdesc;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* struct usbdev_req_s - describes one i/o request */
|
||||
|
||||
struct usbdev_ep_s;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* include/nuttx/usb/usbmsc.h
|
||||
*
|
||||
* Copyright (C) 2008-2010, 2012 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2008-2010, 2012, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* NOTE: This interface was inspired by the Linux gadget interface by
|
||||
|
@ -37,14 +37,14 @@
|
|||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_NUTTX_USB_USBMSC_H
|
||||
#define __INCLUDE_NUTTX_USB_USBMSC_H
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
|
@ -52,17 +52,28 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
/* Informations about the device needed in usbdev_description_s */
|
||||
|
||||
#define USBMSC_CONFIGID (1) /* The only supported configuration ID */
|
||||
#define USBMSC_NENDPOINTS (2) /* Number of endpoints in the interface */
|
||||
|
||||
#define USBMSC_EP_BULKIN_IDX (0)
|
||||
#define USBMSC_EP_BULKOUT_IDX (1)
|
||||
|
||||
#define USBMSC_NCONFIGS (1) /* Number of configurations supported */
|
||||
#define USBMSC_NINTERFACES (1) /* Number of interfaces in the configuration */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
|
@ -73,61 +84,11 @@ extern "C"
|
|||
# define EXTERN extern
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Public Functions
|
||||
************************************************************************************/
|
||||
|
||||
/************************************************************************************
|
||||
* Name: board_mscclassobject
|
||||
*
|
||||
* Description:
|
||||
* If the mass storage class driver is part of composite device, then
|
||||
* its instantiation and configuration is a multi-step, board-specific,
|
||||
* process (See comments for usbmsc_configure below). In this case,
|
||||
* board-specific logic must provide board_mscclassobject().
|
||||
*
|
||||
* board_mscclassobject() is called from the composite driver. It must
|
||||
* encapsulate the instantiation and configuration of the mass storage
|
||||
* class and the return the mass storage device's class driver instance
|
||||
* to the composite dirver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* classdev - The location to return the mass storage class' device
|
||||
* instance.
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success; a negated errno on failure
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
#if defined(CONFIG_USBDEV_COMPOSITE) && defined(CONFIG_USBMSC_COMPOSITE)
|
||||
struct usbdevclass_driver_s;
|
||||
int board_mscclassobject(FAR struct usbdevclass_driver_s **classdev);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_mscuninitialize
|
||||
*
|
||||
* Description:
|
||||
* Un-initialize the USB storage class driver. This is just an application-
|
||||
* specific wrapper aboutn usbmsc_unitialize() that is called form the composite
|
||||
* device logic.
|
||||
*
|
||||
* Input Parameters:
|
||||
* classdev - The class driver instrance previously give to the composite
|
||||
* driver by board_mscclassobject().
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_USBDEV_COMPOSITE) && defined(CONFIG_USBMSC_COMPOSITE)
|
||||
struct usbdevclass_driver_s;
|
||||
void board_mscuninitialize(FAR struct usbdevclass_driver_s *classdev);
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_configure
|
||||
*
|
||||
* Description:
|
||||
|
@ -145,20 +106,21 @@ void board_mscuninitialize(FAR struct usbdevclass_driver_s *classdev);
|
|||
*
|
||||
* Returned Value:
|
||||
* 0 on success; a negated errno on failure. The returned handle value is
|
||||
* an untyped equivalent to the usbmsc_classobject() or board_mscclassobject().
|
||||
* an untyped equivalent to the usbmsc_classobject().
|
||||
*
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
int usbmsc_configure(unsigned int nluns, void **handle);
|
||||
int usbmsc_configure(unsigned int nluns, FAR void **handle);
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_bindlun
|
||||
*
|
||||
* Description:
|
||||
* Bind the block driver specified by drvrpath to a USB storage LUN.
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - The handle returned by a previous call to usbmsc_configure().
|
||||
* handle - The handle returned by a previous call to
|
||||
* usbmsc_configure().
|
||||
* drvrpath - the full path to the block driver
|
||||
* startsector - A sector offset into the block driver to the start of the
|
||||
* partition on drvrpath (0 if no partitions)
|
||||
|
@ -169,12 +131,12 @@ int usbmsc_configure(unsigned int nluns, void **handle);
|
|||
* Returned Value:
|
||||
* 0 on success; a negated errno on failure.
|
||||
*
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
int usbmsc_bindlun(FAR void *handle, FAR const char *drvrpath, unsigned int lunno,
|
||||
off_t startsector, size_t nsectors, bool readonly);
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_unbindlun
|
||||
*
|
||||
* Description:
|
||||
|
@ -187,16 +149,16 @@ int usbmsc_bindlun(FAR void *handle, FAR const char *drvrpath, unsigned int lunn
|
|||
* Returned Value:
|
||||
* 0 on success; a negated errno on failure.
|
||||
*
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
int usbmsc_unbindlun(FAR void *handle, unsigned int lunno);
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_exportluns
|
||||
*
|
||||
* Description:
|
||||
* After all of the LUNs have been bound, this function may be called in order to
|
||||
* export those LUNs in the USB storage device.
|
||||
* After all of the LUNs have been bound, this function may be called in
|
||||
* order to export those LUNs in the USB storage device.
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - The handle returned by a previous call to usbmsc_configure().
|
||||
|
@ -204,13 +166,13 @@ int usbmsc_unbindlun(FAR void *handle, unsigned int lunno);
|
|||
* Returned Value:
|
||||
* 0 on success; a negated errno on failure
|
||||
*
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
#if !defined(CONFIG_USBDEV_COMPOSITE) || !defined(CONFIG_USBMSC_COMPOSITE)
|
||||
int usbmsc_exportluns(FAR void *handle);
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_classobject
|
||||
*
|
||||
* Description:
|
||||
|
@ -222,22 +184,22 @@ int usbmsc_exportluns(FAR void *handle);
|
|||
*
|
||||
* Returned Value:
|
||||
* 0 on success; a negated errno on failure
|
||||
|
||||
*
|
||||
************************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_USBDEV_COMPOSITE) && defined(CONFIG_USBMSC_COMPOSITE)
|
||||
struct usbdevclass_driver_s;
|
||||
int usbmsc_classobject(FAR void *handle, FAR struct usbdevclass_driver_s **classdev);
|
||||
int usbmsc_classobject(FAR void *handle, FAR struct usbdev_description_s *devdesc,
|
||||
FAR struct usbdevclass_driver_s **classdev);
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_uninitialize
|
||||
*
|
||||
* Description:
|
||||
* Un-initialize the USB storage class driver. The handle is the USB MSC
|
||||
* class' device object. This is the same value as returned by usbmsc_classobject
|
||||
* (typed) or by usbmsc_configure (untyped).
|
||||
* class' device object. This is the same value as returned by
|
||||
* usbmsc_classobject (typed) or by usbmsc_configure (untyped).
|
||||
*
|
||||
* Input Parameters:
|
||||
* handle - The handle returned by a previous call to usbmsc_configure()
|
||||
|
@ -246,10 +208,30 @@ int usbmsc_classobject(FAR void *handle, FAR struct usbdevclass_driver_s **class
|
|||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
***********************************************************************************/
|
||||
****************************************************************************/
|
||||
|
||||
void usbmsc_uninitialize(FAR void *handle);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: usbmsc_get_composite_devdesc
|
||||
*
|
||||
* Description:
|
||||
* Helper function to fill in some constants into the composite configuration
|
||||
* structure.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - Pointer to the configuration struct we should fill
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_USBDEV_COMPOSITE) && defined(CONFIG_USBMSC_COMPOSITE)
|
||||
struct composite_devdesc_s;
|
||||
void usbmsc_get_composite_devdesc(FAR struct composite_devdesc_s *dev);
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
|
|
@ -247,6 +247,7 @@ struct boardioc_usbdev_ctrl_s
|
|||
uint8_t usbdev; /* See enum boardioc_usbdev_identifier_e */
|
||||
uint8_t action; /* See enum boardioc_usbdev_action_e */
|
||||
uint8_t instance; /* Identifies the USB device class instance */
|
||||
uint8_t config; /* Configuration used with BOARDIOC_USBDEV_CONNECT */
|
||||
FAR void **handle; /* Connection handle */
|
||||
};
|
||||
#endif /* CONFIG_BOARDCTL_USBDEVCTRL */
|
||||
|
|
|
@ -109,9 +109,12 @@ fi
|
|||
WD=${PWD}
|
||||
|
||||
BOARDDIR=configs/$BOARDSUBDIR
|
||||
SCRIPTSDIR=$BOARDDIR/scripts
|
||||
MAKEDEFS1=$SCRIPTSDIR/Make.defs
|
||||
|
||||
CONFIGDIR=$BOARDDIR/$CONFIGSUBDIR
|
||||
DEFCONFIG=$CONFIGDIR/defconfig
|
||||
MAKEDEFS=$CONFIGDIR/Make.defs
|
||||
MAKEDEFS2=$CONFIGDIR/Make.defs
|
||||
|
||||
CMPCONFIG_TARGET=cmpconfig
|
||||
CMPCONFIG1=tools/cmpconfig
|
||||
|
@ -136,9 +139,15 @@ if [ ! -r "$DEFCONFIG" ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -r "$MAKEDEFS" ]; then
|
||||
echo "No readable Make.defs file at $MAKEDEFS"
|
||||
exit 1
|
||||
if [ -r "$MAKEDEFS1" ]; then
|
||||
MAKEDEFS=$MAKEDEFS1
|
||||
else
|
||||
if [ -r "$MAKEDEFS2" ]; then
|
||||
MAKEDEFS=$MAKEDEFS2
|
||||
else
|
||||
echo "No readable Make.defs file at $MAKEDEFS1 or $MAKEDEFS2"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# If the cmpconfig executable does not exist, then build it
|
||||
|
|
Loading…
Reference in a new issue