rp23xx/raspberrypi-pico-2-w: CDC-ACM + CDC-NCM composite USB device

Add a composite USB device that presents a CDC-ACM serial console and a
CDC-NCM network interface (eth0) at once, for the Pico 2 W access
device: the host gets a console and a USB NIC over a single connection.

The two classes must use disjoint endpoint numbers or they collide, so
board_composite_connect() assigns CDC-ACM 1/2/3 and CDC-NCM 4/5/6.
Build the new rp23xx_composite.c under CONFIG_USBDEV_COMPOSITE (CMake
and Make.defs).

The common bringup optionally autostarts the "portalup" helper
(CONFIG_EXAMPLES_PORTALUP) which connects the composite, brings up the
interfaces and starts the mDNS responder.

Assisted-by: Claude (Anthropic Claude Code)
Signed-off-by: Ricard Rosson <ricard@groundbits.com>
This commit is contained in:
Ricard Rosson 2026-07-11 05:38:28 +01:00
parent 54f842cbf3
commit cd404022b4
4 changed files with 157 additions and 0 deletions

View file

@ -28,6 +28,11 @@
#include <stddef.h>
#include <string.h>
#include <sys/stat.h>
#ifdef CONFIG_EXAMPLES_PORTALUP
# include <spawn.h>
# include <syslog.h>
# include <errno.h>
#endif
#include <nuttx/fs/fs.h>
@ -74,6 +79,11 @@ int rp23xx_common_bringup(void)
{
int ret = 0;
#ifdef CONFIG_EXAMPLES_PORTALUP
FAR char *portalup_argv[2];
pid_t portalup_pid;
#endif
#ifdef CONFIG_RP23XX_I2C_DRIVER
#ifdef CONFIG_RP23XX_I2C0
ret = board_i2cdev_initialize(0);
@ -520,5 +530,21 @@ int rp23xx_common_bringup(void)
}
#endif
#ifdef CONFIG_EXAMPLES_PORTALUP
/* Autostart the access-device boot helper: bring up wlan0 and start the
* mDNS responder so the board is reachable by name at boot.
*/
portalup_argv[0] = "portalup";
portalup_argv[1] = NULL;
if (posix_spawn(&portalup_pid, "portalup", NULL, NULL,
portalup_argv, NULL) != 0)
{
syslog(LOG_ERR, "ERROR: failed to spawn portalup: %d\n", errno);
}
#endif
return ret;
}

View file

@ -38,6 +38,10 @@ if(CONFIG_BOARDCTL)
list(APPEND SRCS rp23xx_appinit.c)
endif()
if(CONFIG_USBDEV_COMPOSITE)
list(APPEND SRCS rp23xx_composite.c)
endif()
target_sources(board PRIVATE ${SRCS})
if(CONFIG_BOOT_RUNFROMFLASH)

View file

@ -89,3 +89,7 @@ distclean::
$(call DELFILE, board$(DELIM)cyw43439.firmware.image)
endif
ifeq ($(CONFIG_USBDEV_COMPOSITE),y)
CSRCS += rp23xx_composite.c
endif

View file

@ -0,0 +1,123 @@
/****************************************************************************
* boards/arm/rp23xx/raspberrypi-pico-2-w/src/rp23xx_composite.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <debug.h>
#include <assert.h>
#include <nuttx/usb/usbdev.h>
#include <nuttx/usb/composite.h>
#ifdef CONFIG_CDCACM_COMPOSITE
# include <nuttx/usb/cdcacm.h>
#endif
#ifdef CONFIG_CDCNCM_COMPOSITE
# include <nuttx/usb/cdcncm.h>
#endif
#if defined(CONFIG_BOARDCTL_USBDEVCTRL) && defined(CONFIG_USBDEV_COMPOSITE)
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: board_composite_initialize
****************************************************************************/
int board_composite_initialize(int port)
{
return OK;
}
/****************************************************************************
* Name: board_composite_connect
*
* Description:
* Connect the CDC/ACM serial console + CDC/NCM network composite device.
* The two classes use disjoint endpoint numbers (ACM: 1/2/3, NCM: 4/5/6)
* so they can coexist in one configuration.
*
****************************************************************************/
void *board_composite_connect(int port, int configid)
{
if (configid == 0)
{
struct composite_devdesc_s dev[2];
int ifnobase = 0;
int strbase = COMPOSITE_NSTRIDS;
int n = 0;
#ifdef CONFIG_CDCACM_COMPOSITE
/* CDC/ACM serial console */
cdcacm_get_composite_devdesc(&dev[n]);
dev[n].classobject = cdcacm_classobject;
dev[n].uninitialize = cdcacm_uninitialize;
dev[n].devinfo.ifnobase = ifnobase;
dev[n].minor = 0;
dev[n].devinfo.strbase = strbase;
dev[n].devinfo.epno[CDCACM_EP_INTIN_IDX] = 1;
dev[n].devinfo.epno[CDCACM_EP_BULKIN_IDX] = 2;
dev[n].devinfo.epno[CDCACM_EP_BULKOUT_IDX] = 3;
ifnobase += dev[n].devinfo.ninterfaces;
strbase += dev[n].devinfo.nstrings;
n++;
#endif
#ifdef CONFIG_CDCNCM_COMPOSITE
/* CDC/NCM network device */
cdcncm_get_composite_devdesc(&dev[n]);
dev[n].devinfo.ifnobase = ifnobase;
dev[n].minor = 0;
dev[n].devinfo.strbase = strbase;
dev[n].devinfo.epno[CDCNCM_EP_INTIN_IDX] = 4;
dev[n].devinfo.epno[CDCNCM_EP_BULKIN_IDX] = 5;
dev[n].devinfo.epno[CDCNCM_EP_BULKOUT_IDX] = 6;
ifnobase += dev[n].devinfo.ninterfaces;
strbase += dev[n].devinfo.nstrings;
n++;
#endif
return composite_initialize(composite_getdevdescs(), dev, n);
}
else
{
return NULL;
}
}
#endif /* CONFIG_BOARDCTL_USBDEVCTRL && CONFIG_USBDEV_COMPOSITE */