Merge remote-tracking branch 'origin/master' into beacon802154

This commit is contained in:
Gregory Nutt 2017-07-16 08:59:33 -06:00
commit f95de69f67
4 changed files with 95 additions and 311 deletions

View File

@ -15,72 +15,17 @@ menuconfig SYSTEM_COMPOSITE
disconn: Disconnect the mass storage device to the host
if SYSTEM_COMPOSITE
if USBMSC_COMPOSITE
config SYSTEM_COMPOSITE_NLUNS
int "Number of LUNs"
default 1
---help---
Defines the number of logical units (LUNs) exported by the USB
storage driver. Each LUN corresponds to one exported block driver
(or partition of a block driver). May be 1, 2, or 3. Default is 1.
config SYSTEM_COMPOSITE_DEVMINOR1
int "LUN1 Minor Device Number"
config SYSTEM_COMPOSITE_DEFCONFIG
int "Default composite configuration"
default 0
---help---
The minor device number of the block driver for the first LUN. For
example, N in /dev/mmcsdN. Used for registering the block driver.
Default is zero.
config SYSTEM_COMPOSITE_DEVPATH1
string "LUN1 Device Path"
default "/dev/mmcsd0"
---help---
The full path to the registered block driver. Default is
"/dev/mmcsd0"
config SYSTEM_COMPOSITE_DEVMINOR2
int "LUN2 Minor Device Number"
default 1
---help---
The minor device number of the block driver for the second LUN. For
example, N in /dev/mmcsdN. Used for registering the block driver.
Ignored if SYSTEM_COMPOSITE_NLUNS < 2. Default is one.
config SYSTEM_COMPOSITE_DEVPATH2
string "LUN2 Device Path"
default "/dev/mmcsd1"
---help---
The full path to the registered block driver. Ignored if
SYSTEM_COMPOSITE_NLUNS < 2. Default is "/dev/mmcsd1"
config SYSTEM_COMPOSITE_DEVMINOR3
int "LUN3 Minor Device Number"
default 2
---help---
The minor device number of the block driver for the third LUN. For
example, N in /dev/mmcsdN. Used for registering the block driver.
Ignored if SYSTEM_COMPOSITE_NLUNS < 2. Default is two.
config SYSTEM_COMPOSITE_DEVPATH3
string "LUN3 Device Path"
default "/dev/mmcsd2"
---help---
The full path to the registered block driver. Ignored if
SYSTEM_COMPOSITE_NLUNS < 2. Default is "/dev/mmcsd2"
endif # USBMSC_COMPOSITE
Boards may support multiple composite configurations. If so, then
this is the default configuration that the conn command will use if
no configuration ID is provided on the command line.
if CDCACM_COMPOSITE
config SYSTEM_COMPOSITE_TTYUSB
int "USB serial device minor number"
default 0
---help---
The minor number of the USB serial device. Default is zero
(corresponding to /dev/ttyUSB0 or /dev/ttyACM0).
config SYSTEM_COMPOSITE_SERDEV
string "USB serial device path"
default "/dev/ttyACM0"

View File

@ -1,33 +1,58 @@
system/composite
^^^^^^^^^^^^^^^^^^
This logic adds a NXH command to control a USB composite device. The only
supported composite is CDC/ACM serial with a USB mass storage device.
This logic adds a NSH command to control a USB composite device. The only
supported devices in the composite are CDC/ACM serial and a USB mass storage
device. Which devices are enclosed in a composite device is configured with
an array of configuration-structs, handed over to the function
composite_initialize().
Required overall configuration:
CONFIG_USBDEV=y - USB device support
CONFIG_USBDEV_COMPOSITE=y - USB composite device support
CONFIG_COMPOSITE_IAD=y - Interface associate descriptor needed
Enable the USB Support of your Hardware / Processor e.g. SAMV7_USBDEVHS=y
CONFIG_CDCACM=y - USB CDC/ACM serial device support
CONFIG_CDCACM_COMPOSITE=y - USB CDC/ACM serial composite device support
CONFIG_CDCACM_IFNOBASE=0 - CDC/ACM interfaces start with number 0
CONFIG_CDCACM_STRBASE=4 - Base of string numbers (not really needed)
CONFIG_CDCACM_EPINTIN=1 - Endpoint numbers must be unique
CONFIG_CDCACM_EPBULKIN=2
CONFIG_CDCACM_EPBULKOUT=3
CONFIG_USBDEV=y - USB device support
CONFIG_USBDEV_COMPOSITE=y - USB composite device support
CONFIG_COMPOSITE_IAD=y - Interface associate descriptor needed
CONFIG_USBMSC - USB mass storage device support
CONFIG_USBMSC_COMPOSITE=y - USB mass storage composite device support
CONFIG_USBMSC_IFNOBASE=2 - USB mass storage interfaces start with number 2
CONFIG_USBMSC_STRBASE=4 - Base of string numbers (needed)
CONFIG_USBMSC_EPBULKOUT=4 - Endpoint numbers must be unique
CONFIG_USBMSC_EPBULKIN=5
CONFIG_CDCACM=y - USB CDC/ACM serial device support
CONFIG_CDCACM_COMPOSITE=y - USB CDC/ACM serial composite device support
The interface-, string-descriptor- and endpoint-numbers are configured via the
configuration-structs as noted above. The CDC/ACM serial device needs three
endpoints; one interrupt-driven and two bulk endpoints.
CONFIG_USBMSC=y - USB mass storage device support
CONFIG_USBMSC_COMPOSITE=y - USB mass storage composite device support
Like the configuration for the CDC/ACM, the descriptor- and endpoint-numbers
are configured via the configuration struct.
Depending on the configuration struct you need to configure different vendor-
and product-IDs. Each VID/PID is unique to a device and thus to a dedicated
configuration.
Linux tries to detect the device types and installs default drivers if the
VID/PID pair is unknown.
Windows insists on a known and installed configuration. With an Atmel
hardware and Atmel-Studio or the Atmel-USB-drivers installed, you can test
your configuration with Atmel Example Vendor- and Product-IDs.
If you have a USBMSC and a CDC/ACM configured in your combo, then you can try
to use
- VID = 0x03EB (ATMEL)
- PID = 0x2424 (ASF Example with MSC and CDC)
If for example you try to test a configuration with up to seven CDCs, then
- VID = 0x03EB (ATMEL)
- PID = 0x2426 (ASF Example with up to seven CDCs)
CONFIG_NSH_BUILTIN_APPS
This add-on can be built as two NSH "built-in" commands if this option
is selected: 'conn' will connect the USB composite device; 'msdis'
is selected: 'conn' will connect the USB composite device; 'disconn'
will disconnect the USB composite device.
Configuration options unique to this add-on:

View File

@ -186,7 +186,6 @@ struct composite_state_s
*/
FAR void *cmphandle; /* Composite device handle */
FAR void *mschandle; /* Mass storage device handle */
/* Serial file descriptors */

View File

@ -1,7 +1,7 @@
/****************************************************************************
* system/composite/composite_main.c
*
* Copyright (C) 2012-2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2012-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -404,7 +404,7 @@ static int open_serial(void)
if (g_composite.outfd < 0)
{
errcode = errno;
printf("open_serial: ERROR: Failed to open %s for writing: %d\n",
fprintf(stderr, "open_serial: ERROR: Failed to open %s for writing: %d\n",
CONFIG_SYSTEM_COMPOSITE_SERDEV, errcode);
/* ENOTCONN means that the USB device is not yet connected */
@ -443,7 +443,7 @@ static int open_serial(void)
if (g_composite.infd < 0)
{
errcode = errno;
printf("open_serial: ERROR: Failed to open%s for reading: %d\n",
fprintf(stderr, "open_serial: ERROR: Failed to open%s for reading: %d\n",
CONFIG_SYSTEM_COMPOSITE_SERDEV, errcode);
close(g_composite.outfd);
return -errcode;
@ -471,7 +471,7 @@ static int echo_serial(void)
errcode = errno;
if (errcode != EAGAIN)
{
printf("echo_serial: ERROR: read failed: %d\n", errcode);
fprintf(stderr, "echo_serial: ERROR: read failed: %d\n", errcode);
return -errcode;
}
return OK;
@ -483,12 +483,12 @@ static int echo_serial(void)
if (byteswritten < 0)
{
errcode = errno;
printf("echo_serial: ERROR: write failed: %d\n", errcode);
fprintf(stderr, "echo_serial: ERROR: write failed: %d\n", errcode);
return -errcode;
}
else if (byteswritten != bytesread)
{
printf("echo_serial: ERROR: read size: %d write size: %d\n",
fprintf(stderr, "echo_serial: ERROR: read size: %d write size: %d\n",
bytesread, byteswritten);
}
@ -496,229 +496,10 @@ static int echo_serial(void)
}
#endif
/****************************************************************************
* Name: usbmsc_disconnect
*
* Description:
* Disconnect the USB MSC device
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
static void usbmsc_disconnect(void)
{
struct boardioc_usbdev_ctrl_s ctrl;
ctrl.usbdev = BOARDIOC_USBDEV_MSC;
ctrl.action = BOARDIOC_USBDEV_DISCONNECT;
ctrl.instance = 0;
ctrl.handle = &g_composite.mschandle;
(void)boardctl(BOARDIOC_USBDEV_CONTROL, (uintptr_t)&ctrl);
}
/****************************************************************************
* 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 driver.
*
* Input Parameters:
* classdev - The location to return the mass storage class' device
* instance.
*
* Returned Value:
* 0 on success; a negated errno on failure
*
****************************************************************************/
int board_mscclassobject(FAR struct usbdevclass_driver_s **classdev)
{
int ret;
DEBUGASSERT(g_composite.mschandle == NULL);
/* Initialize USB trace output IDs */
usbtrace_enable(TRACE_BITSET);
check_test_memory_usage("After usbtrace_enable()");
/* Configure the mass storage device */
printf("board_mscclassobject: Configuring with NLUNS=%d\n", CONFIG_SYSTEM_COMPOSITE_NLUNS);
ret = usbmsc_configure(CONFIG_SYSTEM_COMPOSITE_NLUNS, &g_composite.mschandle);
if (ret < 0)
{
printf("board_mscclassobject: usbmsc_configure failed: %d\n", -ret);
return ret;
}
printf("board_mscclassobject: MSC handle=%p\n", g_composite.mschandle);
check_test_memory_usage("After usbmsc_configure()");
/* Bind the LUN(s) */
printf("board_mscclassobject: Bind LUN=0 to %s\n", CONFIG_SYSTEM_COMPOSITE_DEVPATH1);
ret = usbmsc_bindlun(g_composite.mschandle, CONFIG_SYSTEM_COMPOSITE_DEVPATH1, 0, 0, 0, false);
if (ret < 0)
{
printf("board_mscclassobject: usbmsc_bindlun failed for LUN 1 using %s: %d\n",
CONFIG_SYSTEM_COMPOSITE_DEVPATH1, -ret);
usbmsc_disconnect();
return ret;
}
check_test_memory_usage("After usbmsc_bindlun()");
#if CONFIG_SYSTEM_COMPOSITE_NLUNS > 1
printf("board_mscclassobject: Bind LUN=1 to %s\n", CONFIG_SYSTEM_COMPOSITE_DEVPATH2);
ret = usbmsc_bindlun(g_composite.mschandle, CONFIG_SYSTEM_COMPOSITE_DEVPATH2, 1, 0, 0, false);
if (ret < 0)
{
printf("board_mscclassobject: usbmsc_bindlun failed for LUN 2 using %s: %d\n",
CONFIG_SYSTEM_COMPOSITE_DEVPATH2, -ret);
usbmsc_disconnect();
return ret;
}
check_test_memory_usage("After usbmsc_bindlun() #2");
#if CONFIG_SYSTEM_COMPOSITE_NLUNS > 2
printf("board_mscclassobject: Bind LUN=2 to %s\n", CONFIG_SYSTEM_COMPOSITE_DEVPATH3);
ret = usbmsc_bindlun(g_composite.mschandle, CONFIG_SYSTEM_COMPOSITE_DEVPATH3, 2, 0, 0, false);
if (ret < 0)
{
printf("board_mscclassobject: usbmsc_bindlun failed for LUN 3 using %s: %d\n",
CONFIG_SYSTEM_COMPOSITE_DEVPATH3, -ret);
usbmsc_disconnect();
return ret;
}
check_test_memory_usage("After usbmsc_bindlun() #3");
#endif
#endif
/* Get the mass storage device's class object */
ret = usbmsc_classobject(g_composite.mschandle, classdev);
if (ret < 0)
{
printf("board_mscclassobject: usbmsc_classobject failed: %d\n", -ret);
usbmsc_disconnect();
}
check_test_memory_usage("After usbmsc_classobject()");
return ret;
}
/****************************************************************************
* 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
*
****************************************************************************/
void board_mscuninitialize(FAR struct usbdevclass_driver_s *classdev)
{
DEBUGASSERT(g_composite.mschandle != NULL);
usbmsc_disconnect();
}
/****************************************************************************
* 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
*
****************************************************************************/
int board_cdcclassobject(FAR struct usbdevclass_driver_s **classdev)
{
int ret;
/* Initialize the USB serial driver */
printf("board_cdcclassobject: Initializing USB serial driver\n");
ret = cdcacm_classobject(CONFIG_SYSTEM_COMPOSITE_TTYUSB, classdev);
if (ret < 0)
{
printf("board_cdcclassobject: ERROR: Failed to create the USB serial device: %d\n", -ret);
}
return ret;
}
/****************************************************************************
* Name: board_cdcuninitialize
*
* Description:
* Un-initialize the USB serial class driver. This is just an application-
* specific wrapper aboutn cdcadm_unitialize() that is called form the composite
* device logic.
*
* Input Parameters:
* classdev - The class driver instrance previously give to the composite
* driver by board_cdcclassobject().
*
* Returned Value:
* None
*
****************************************************************************/
void board_cdcuninitialize(FAR struct usbdevclass_driver_s *classdev)
{
struct boardioc_usbdev_ctrl_s ctrl;
DEBUGASSERT(classdev != NULL);
ctrl.usbdev = BOARDIOC_USBDEV_CDCACM;
ctrl.action = BOARDIOC_USBDEV_DISCONNECT;
ctrl.instance = CONFIG_SYSTEM_COMPOSITE_TTYUSB;
ctrl.handle = (FAR void **)&classdev;
(void)boardctl(BOARDIOC_USBDEV_CONTROL, (uintptr_t)&ctrl);
}
/****************************************************************************
* conn_main
*
@ -737,6 +518,7 @@ int conn_main(int argc, char *argv[])
#endif
{
struct boardioc_usbdev_ctrl_s ctrl;
int config = CONFIG_SYSTEM_COMPOSITE_DEFCONFIG;
int ret;
/* If this program is implemented as the NSH 'conn' command, then we need to
@ -748,13 +530,29 @@ int conn_main(int argc, char *argv[])
* USB mass storage device is already configured).
*/
if (g_composite.cmphandle)
{
printf("conn_main: ERROR: Already connected\n");
return 1;
}
if (g_composite.cmphandle)
{
fprintf(stderr, "conn_main: ERROR: Already connected\n");
return 1;
}
#endif
/* There is one optional argument.. the interface configuration ID */
if (argc == 2)
{
config = atoi(argv[1]);
}
else if (argc > 2)
{
fprintf(stderr, "conn_main: ERROR: Too many arguments: %d\n", argc);
return EXIT_FAILURE;
}
/* Initialize USB trace output IDs */
usbtrace_enable(TRACE_BITSET);
#ifdef CONFIG_SYSTEM_COMPOSITE_DEBUGMM
# ifdef CONFIG_CAN_PASS_STRUCTS
g_composite.mmstart = mallinfo();
@ -772,6 +570,7 @@ int conn_main(int argc, char *argv[])
ctrl.usbdev = BOARDIOC_USBDEV_COMPOSITE;
ctrl.action = BOARDIOC_USBDEV_INITIALIZE;
ctrl.instance = 0;
ctrl.config = config;
ctrl.handle = NULL;
ret = boardctl(BOARDIOC_USBDEV_CONTROL, (uintptr_t)&ctrl);
@ -788,6 +587,7 @@ int conn_main(int argc, char *argv[])
ctrl.usbdev = BOARDIOC_USBDEV_COMPOSITE;
ctrl.action = BOARDIOC_USBDEV_CONNECT;
ctrl.instance = 0;
ctrl.config = config;
ctrl.handle = &g_composite.cmphandle;
ret = boardctl(BOARDIOC_USBDEV_CONTROL, (uintptr_t)&ctrl);
@ -892,6 +692,7 @@ errout:
ctrl.usbdev = BOARDIOC_USBDEV_COMPOSITE;
ctrl.action = BOARDIOC_USBDEV_DISCONNECT;
ctrl.instance = 0;
ctrl.config = config;
ctrl.handle = &g_composite.cmphandle;
(void)boardctl(BOARDIOC_USBDEV_CONTROL, (uintptr_t)&ctrl);
@ -918,22 +719,36 @@ int disconn_main(int argc, char *argv[])
#endif
{
struct boardioc_usbdev_ctrl_s ctrl;
int config = CONFIG_SYSTEM_COMPOSITE_DEFCONFIG;
/* First check if the USB mass storage device is already connected */
if (!g_composite.cmphandle)
{
printf("disconn_main: ERROR: Not connected\n");
fprintf(stderr, "disconn_main: ERROR: Not connected\n");
return 1;
}
check_test_memory_usage("Since MS connection");
/* There is one optional argument.. the interface configuration ID */
if (argc == 2)
{
config = atoi(argv[1]);
}
else if (argc > 2)
{
fprintf(stderr, "conn_main: ERROR: Too many arguments: %d\n", argc);
return EXIT_FAILURE;
}
/* Then disconnect the device and uninitialize the USB mass storage driver */
ctrl.usbdev = BOARDIOC_USBDEV_COMPOSITE;
ctrl.action = BOARDIOC_USBDEV_DISCONNECT;
ctrl.instance = 0;
ctrl.config = config;
ctrl.handle = &g_composite.cmphandle;
(void)boardctl(BOARDIOC_USBDEV_CONTROL, (uintptr_t)&ctrl);