From patchwork Thu Aug 19 11:13:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Loic Poulain X-Patchwork-Id: 499731 Delivered-To: patch@linaro.org Received: by 2002:a02:6f15:0:0:0:0:0 with SMTP id x21csp406132jab; Thu, 19 Aug 2021 04:02:48 -0700 (PDT) X-Google-Smtp-Source: ABdhPJztb6LKBH7f+nSjno4sJOscM08E45CRR9Qyl40/yGD+MloGQbubcnRCsTGcM4Prv4MyNifZ X-Received: by 2002:a17:906:cb99:: with SMTP id mf25mr15122091ejb.441.1629370968418; Thu, 19 Aug 2021 04:02:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1629370968; cv=none; d=google.com; s=arc-20160816; b=o/CznlliYoMxvlKyDXNmslBrRaEJsrYcnqGUYQ5LgdXhAKc2V6C4OmDEMkOpHXOj0c T3zaDy0YGltExzwV/nDai/Nv2YtHovT526so6NlEAKrnvDH+AJYGzrk26ZUnb1KYETBJ N3NcTn6Uhq7LUwRCcD79ocGdaAjDuP79DVEf9fuFSRvsdcbOF8BA1wT685gqjx4j0D+x njzWHC2NNccRpaPvJ4z1zXc4v5MIdnU1S6YscGMKAL+dKxpArxzNNVjPuLE46PdeZlSk AR+PTgrIGh03pwWDBFYsMU/3PgwHMjyV2n//LirR2kER8ysZOBXMpdyayuwnZt1CoOCS Ydew== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:message-id:date:subject:cc:to :from:dkim-signature; bh=1GxHIdTJ9bLTkBzyGG12Iq5o9eH+I3P3+ODLSSyLBhg=; b=gnO3OZ/AFaE11h3PefMoR2eTA2TyGBz9r1EWHQ4OTjaDnXdSXcJx4yazIsvoc1W/5R KXjC4Ts4q83xPsmB6jCxcTwHlObXcPzHVaFjd9y1t+Y5g7xW5rSRM+9qiYKo3beH/YjN ZrTjS2cRg2eW0i/0Qge4CORU5hCj3tF7oTd46fnIel0iNUwCuEXjidkL2VCasI2Fk1J3 X2sDo24C6EQPCg5HkEi9xIStD+o6vtBjsNvTyL890QSfCccKMDwaQBqMnPQnGW4DLlkR nOSH/c1WCy5gyp2GDa60/k4V9WFCXJ0XU2znKaL2ueEFdzo2WZMrfQ4v031kdYwFMnLo DEzg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=sq92RYil; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [85.214.62.61]) by mx.google.com with ESMTPS id v4si2800537edy.547.2021.08.19.04.02.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Aug 2021 04:02:48 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) client-ip=85.214.62.61; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=sq92RYil; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6E93D82DB2; Thu, 19 Aug 2021 13:02:44 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="sq92RYil"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 6DCAF82E1B; Thu, 19 Aug 2021 13:02:41 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wm1-x32e.google.com (mail-wm1-x32e.google.com [IPv6:2a00:1450:4864:20::32e]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 68C5282C39 for ; Thu, 19 Aug 2021 13:02:37 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=loic.poulain@linaro.org Received: by mail-wm1-x32e.google.com with SMTP id w21-20020a7bc1150000b02902e69ba66ce6so3797819wmi.1 for ; Thu, 19 Aug 2021 04:02:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=1GxHIdTJ9bLTkBzyGG12Iq5o9eH+I3P3+ODLSSyLBhg=; b=sq92RYillYM4bkx0zwc91On4LL15/pA3VayU67hX+JqAeLkJXHEi2Nsh2VG2s5b4LA frrLbRSOWlsnEq23vOFuiY977iCZOM/LD/34Rt3riUxSQNg4TeuXI9AlVsg9NtT7E2+X AQ4SzwuhCbc+bV0U8VYVlvVpiNI9AahKbhLl1pmdPSlSUkRclqZXBOrrHr+rMJt7QTJp R6XFa1kCzsDXINuqgwmubh+w6uHtnjh7XhVMQyr9KMTsYSQputHlColZeRrGvfJz36tY 8clqCeKjxi976QcQI/62P/0Vro5WbXc1b9qXiqhJyKOCY6d7tJhxcLMFDkGJ/z68S00U liWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=1GxHIdTJ9bLTkBzyGG12Iq5o9eH+I3P3+ODLSSyLBhg=; b=rMm1vP9eC5SR4PciyQu2aOwR6iaOLd4eAsJG4g2fpE3spZ/ES+1UOuPp50mplq8oah y/+glPQ9EgvvuOCsxwPrx11jqLxdmHb19m4+EER7q1w3T6sZo7EnZmC9PEIgS06nRmnC uwbIw9plV2yTRU2ZPNN4xU8shvhQnleK3Y+ziG8SWLUpCs66vapq6RJgFyLrTETRAo/E ZJpMzjUssNqvOy/2hDZcg+qIJRb6obgRQ2KziHb1DiS7nIYff1XKFIbEOs6WyG5kb2uR oiAezKgacLVlJkjHrK4W1EmaM36f5r0x82F8xnc/stiXzpr+fvRApZ72MRYo5cMzGngO QFFA== X-Gm-Message-State: AOAM530j83YiBrNdYzj4SnXgl3PV/zc27qLKjC++kcSKp3q4qZjwv/80 q+Vg8Rmw25ZSPOuUR6kt8i7tKw== X-Received: by 2002:a1c:10e:: with SMTP id 14mr13139775wmb.93.1629370956896; Thu, 19 Aug 2021 04:02:36 -0700 (PDT) Received: from lpoulain-ThinkPad-T470p.passengers.t31.sncf ([109.190.253.13]) by smtp.gmail.com with ESMTPSA id d8sm2705696wrv.20.2021.08.19.04.02.30 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 19 Aug 2021 04:02:36 -0700 (PDT) From: Loic Poulain To: marex@denx.de Cc: u-boot@lists.denx.de, lukma@denx.de, Loic Poulain Subject: [PATCH 1/3] lib/circbuf: Make circbuf selectable symbol Date: Thu, 19 Aug 2021 13:13:04 +0200 Message-Id: <1629371586-9349-1-git-send-email-loic.poulain@linaro.org> X-Mailer: git-send-email 2.7.4 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean It is currenly only used from usbtty driver but make it properly selectable via Kconfig symbol, for future usage. Signed-off-by: Loic Poulain --- lib/Kconfig | 3 +++ lib/Makefile | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) -- 2.7.4 diff --git a/lib/Kconfig b/lib/Kconfig index c535147..1bd54d8 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -290,6 +290,9 @@ config TRACE_EARLY_ADDR the size is too small then the message which says the amount of early data being coped will the the same as the +config CIRCBUF + bool + source lib/dhry/Kconfig menu "Security support" diff --git a/lib/Makefile b/lib/Makefile index 8ba745f..4daeee2 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -29,7 +29,13 @@ ifneq ($(CONFIG_CHARSET),) obj-y += charset.o endif endif -obj-$(CONFIG_USB_TTY) += circbuf.o + +ifdef CONFIG_USB_TTY +obj-y += circbuf.o +else +obj-$(CONFIG_CIRCBUF) += circbuf.o +endif + obj-y += crc8.o obj-y += crc16.o obj-$(CONFIG_ERRNO_STR) += errno_str.o From patchwork Thu Aug 19 11:13:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Loic Poulain X-Patchwork-Id: 499732 Delivered-To: patch@linaro.org Received: by 2002:a02:6f15:0:0:0:0:0 with SMTP id x21csp406322jab; Thu, 19 Aug 2021 04:03:04 -0700 (PDT) X-Google-Smtp-Source: ABdhPJz8d6dn4tyQrh/pOKBf6noM8//GhXotNdpAPbIwmrsNY+uRtx8kZgVmkl5h/v2pm2je8G3Z X-Received: by 2002:a17:906:ecb3:: with SMTP id qh19mr15347267ejb.413.1629370983812; Thu, 19 Aug 2021 04:03:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1629370983; cv=none; d=google.com; s=arc-20160816; b=OARNz1wnORtaIRBisopcQFcKZRBEdUB4DgRX+xHHdRFcdWn1OE7cbFwtok8URImNwv tRnPkapyGbh2uREn3yyRp/RM+wvB+HPOx9iIo/0ly3LhgAJ1HzMPThFCKswtCFp09yPH jOfhrxUGoINz2N5UiT8czaQF0/hHpR2yjiVuHgtuO/ZSlzueZEQEXVRA7/QnktAd1lgC Vn8z4ZyZHMM6g7RlDLmIX1YmyB1W0NXVFcZ0dEPnq6IKvpwBWXEoN6YrKmNeU9EonCMK OmheoENhO3mK4VIeC5V6NICnsUTj0EtOh6t9QY5FCD3TI+vIn5b1EMhcPyJWiBKssddn clfg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=t0NB/gNqNEwhWn74CITQoVKOSs8r49CKK7rATOFs4YM=; b=ZwUgb7ctRy0kWkuV2H4aOcMOF9ldI0dIgFck/cIvqRod39xNGFTuJV4o3dcVghJwoy src15DA8McTLXN7582GxVyZV16oqcH7rCt0+uQhx455fpPdBF4uhauTz/RJQB6Mv6G0s A1yBF/BhFOKsuNG7etpJvFL8MzA4a0d7Xo8Ml/qZXyhzDBDDSCnF3Dr7WItqck1N5sCR XrR1PRDljiP6GX/v3Y+TBkCNvbROkmWUVhni8LI0Uh7oPfUEzDWN2toN8maIJ4ezgaRp PE7A2cu/EWR4I4w242ZrdzMnlDU2zAZ4MinWp0gaNvRXVK1caK+i7flixZAwPIN7QacM SZiw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=rO9JOwzz; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id a25si3226121edj.71.2021.08.19.04.03.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Aug 2021 04:03:03 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=rO9JOwzz; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id C4CD782E7A; Thu, 19 Aug 2021 13:03:02 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="rO9JOwzz"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9B91C82E08; Thu, 19 Aug 2021 13:03:01 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.2 Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com [IPv6:2a00:1450:4864:20::432]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 5A1BE82EBB for ; Thu, 19 Aug 2021 13:02:55 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=loic.poulain@linaro.org Received: by mail-wr1-x432.google.com with SMTP id x10so8446208wrt.8 for ; Thu, 19 Aug 2021 04:02:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=t0NB/gNqNEwhWn74CITQoVKOSs8r49CKK7rATOFs4YM=; b=rO9JOwzz6yRkGZV6xC0a872vQY9FYeFYqRo2FHt5r1Nw6/JAP04XzQFvrRsiR3snpv 7NnpHyWCtQEOL435u3UrBHoPCmB97tkLXZJ/It06Du3g47b59HSzyC+UpLOy+Xhwd4ry 5Njk8NJHqSCRo9Yz0inIS8MVEE83uOVNaC6NlGVLzDT3HPwe/PdWde1HXp1xM16uceeq LPSjJyo5VrGVPrY9ZBf6UeQQVx4wAfTz1+4SSpehKNQVL6qP6FM3UWhe7s+/a0zVeykJ it10jcx1yz2SxfFz2rQPJZEW3TVrtsT3RNrp+yEh5WsD6UhUA/NxG7NKyPhXSWld9Vyh eaSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=t0NB/gNqNEwhWn74CITQoVKOSs8r49CKK7rATOFs4YM=; b=X9yrVsk5kmkN1W+AAk1k9Dunz72CqetmqA2nYX5uU/TLHB+xhF8Vk3IodIRZU58ujC GCZgEk811L7dozH4RC5qKE1lYcfroNLU0UvpC/OGxu4VsPyWYv2oM1Yu7FfkR3uCsGYp TnPenitEkfZ5LWmU3l4USg9GqGIafcO+48yLFhmG4QjWhPfYxVjqsAwMK7qaowYYa40y 19TkwnjdhGEij7oaCQSgU4J+lhGshrFBk1kq+m1kdY1YZ/HoAaH2O+jPze7TByiFz5+i wsTtfcmNcIbyYe0l/0fhFC1W13IMbjHWF71X1DZczoxFqO3oORYTmTDBPk4M5uqDeMrV e4Tw== X-Gm-Message-State: AOAM531DOAqViqhiin3lbgPuNMl1QZvYyDzIbOvgMXroiKWjXAEuCKVk QyvK9ooBL0XW9n7Eu5S7j1cAGA== X-Received: by 2002:a5d:69c3:: with SMTP id s3mr3095889wrw.393.1629370974737; Thu, 19 Aug 2021 04:02:54 -0700 (PDT) Received: from lpoulain-ThinkPad-T470p.passengers.t31.sncf ([109.190.253.13]) by smtp.gmail.com with ESMTPSA id d8sm2705696wrv.20.2021.08.19.04.02.41 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 19 Aug 2021 04:02:54 -0700 (PDT) From: Loic Poulain To: marex@denx.de Cc: u-boot@lists.denx.de, lukma@denx.de, Loic Poulain Subject: [PATCH 2/3] usb: gadget: Add CDC ACM function Date: Thu, 19 Aug 2021 13:13:05 +0200 Message-Id: <1629371586-9349-2-git-send-email-loic.poulain@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1629371586-9349-1-git-send-email-loic.poulain@linaro.org> References: <1629371586-9349-1-git-send-email-loic.poulain@linaro.org> X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Add support for CDC ACM using the new UDC and gadget API. This protocol can be used for serial over USB data transfer and is widely supported by various OS (GNU/Linux, MS-Windows, OSX...). The usual purpose of such link is to access device debug console and can be useful for products not exposing regular UART to the user. Signed-off-by: Loic Poulain --- drivers/usb/gadget/Kconfig | 9 + drivers/usb/gadget/Makefile | 1 + drivers/usb/gadget/f_acm.c | 663 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 673 insertions(+) create mode 100644 drivers/usb/gadget/f_acm.c -- 2.7.4 diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 327ea86..d81a9c5 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -182,6 +182,15 @@ config USB_FUNCTION_THOR Enable Tizen's THOR download protocol support in U-Boot. It allows downloading images into memory and flash them to target device. +config USB_FUNCTION_ACM + bool "Enable CDC ACM gadget" + select SYS_STDIO_DEREGISTER + select CIRCBUF + help + ACM serial link. This function can be used to create a stdio device to + interoperate with MS-Windows hosts or with the Linux-USB "cdc-acm" + driver. + endif # USB_GADGET_DOWNLOAD config USB_ETHER diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index f560068..d5d891b 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o obj-$(CONFIG_USB_FUNCTION_SDP) += f_sdp.o obj-$(CONFIG_USB_FUNCTION_ROCKUSB) += f_rockusb.o +obj-$(CONFIG_USB_FUNCTION_ACM) += f_acm.o endif endif ifdef CONFIG_USB_ETHER diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c new file mode 100644 index 0000000..5115f1d --- /dev/null +++ b/drivers/usb/gadget/f_acm.c @@ -0,0 +1,663 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * USB CDC serial (ACM) function driver + * + * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com) + * Copyright (C) 2008 by David Brownell + * Copyright (C) 2008 by Nokia Corporation + * Copyright (C) 2009 by Samsung Electronics + * Copyright (c) 2021, Linaro Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define REQ_SIZE_MAX 512 + +struct f_acm { + int ctrl_id; + int data_id; + + struct usb_ep *ep_in; + struct usb_ep *ep_out; + struct usb_ep *ep_notify; + + struct usb_request *req_in; + struct usb_request *req_out; + + bool connected; + bool tx_on; + + circbuf_t rx_buf; + circbuf_t tx_buf; + + struct stdio_dev stdio; + struct usb_function usb_function; + + struct usb_cdc_line_coding line_coding; + u16 handshake_bits; +#define ACM_CTRL_RTS BIT(1) /* unused with full duplex */ +#define ACM_CTRL_DTR BIT(0) /* host is ready for data r/w */ + + int controller_index; +}; + +static inline struct f_acm *func_to_acm(struct usb_function *f) +{ + return container_of(f, struct f_acm, usb_function); +} + +static inline struct f_acm *stdio_to_acm(struct stdio_dev *s) +{ + /* stdio dev is cloned on registration, do not use container_of */ + return s->priv; +} + +static struct usb_interface_assoc_descriptor +acm_iad_descriptor = { + .bLength = sizeof(acm_iad_descriptor), + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 0, + .bInterfaceCount = 2, // control + data + .bFunctionClass = USB_CLASS_COMM, + .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, + .bFunctionProtocol = USB_CDC_ACM_PROTO_AT_V25TER, +}; + +static struct usb_interface_descriptor acm_control_intf_desc = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_ACM_PROTO_AT_V25TER, +}; + +static struct usb_interface_descriptor acm_data_intf_desc = { + .bLength = sizeof(acm_data_intf_desc), + .bDescriptorType = USB_DT_INTERFACE, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_CDC_DATA, +}; + +static struct usb_cdc_header_desc acm_header_desc = { + .bLength = sizeof(acm_header_desc), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_HEADER_TYPE, + .bcdCDC = cpu_to_le16(0x0110), +}; + +static struct usb_cdc_call_mgmt_descriptor acm_call_mgmt_desc = { + .bLength = sizeof(acm_call_mgmt_desc), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, + .bmCapabilities = 0, + .bDataInterface = 0x01, +}; + +static struct usb_cdc_acm_descriptor acm_desc = { + .bLength = sizeof(acm_desc), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_ACM_TYPE, + .bmCapabilities = USB_CDC_CAP_LINE, +}; + +static struct usb_cdc_union_desc acm_union_desc = { + .bLength = sizeof(acm_union_desc), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_UNION_TYPE, + .bMasterInterface0 = 0x00, + .bSlaveInterface0 = 0x01, +}; + +static struct usb_endpoint_descriptor acm_fs_notify_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 3 | USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(64), + .bInterval = 32, +}; + +static struct usb_endpoint_descriptor acm_fs_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_endpoint_descriptor acm_fs_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_descriptor_header *acm_fs_function[] = { + (struct usb_descriptor_header *)&acm_iad_descriptor, + (struct usb_descriptor_header *)&acm_control_intf_desc, + (struct usb_descriptor_header *)&acm_header_desc, + (struct usb_descriptor_header *)&acm_call_mgmt_desc, + (struct usb_descriptor_header *)&acm_desc, + (struct usb_descriptor_header *)&acm_union_desc, + (struct usb_descriptor_header *)&acm_fs_notify_desc, + (struct usb_descriptor_header *)&acm_data_intf_desc, + (struct usb_descriptor_header *)&acm_fs_in_desc, + (struct usb_descriptor_header *)&acm_fs_out_desc, + NULL, +}; + +static struct usb_endpoint_descriptor acm_hs_notify_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(64), + .bInterval = 11, +}; + +static struct usb_endpoint_descriptor acm_hs_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(512), +}; + +static struct usb_endpoint_descriptor acm_hs_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(512), +}; + +static struct usb_descriptor_header *acm_hs_function[] = { + (struct usb_descriptor_header *)&acm_iad_descriptor, + (struct usb_descriptor_header *)&acm_control_intf_desc, + (struct usb_descriptor_header *)&acm_header_desc, + (struct usb_descriptor_header *)&acm_call_mgmt_desc, + (struct usb_descriptor_header *)&acm_desc, + (struct usb_descriptor_header *)&acm_union_desc, + (struct usb_descriptor_header *)&acm_hs_notify_desc, + (struct usb_descriptor_header *)&acm_data_intf_desc, + (struct usb_descriptor_header *)&acm_hs_in_desc, + (struct usb_descriptor_header *)&acm_hs_out_desc, + NULL, +}; + +static inline struct usb_endpoint_descriptor * +ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs, + struct usb_endpoint_descriptor *fs) +{ + if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) + return hs; + return fs; +} + +static int acm_bind(struct usb_configuration *c, struct usb_function *f) +{ + struct usb_gadget *gadget = c->cdev->gadget; + struct f_acm *f_acm = func_to_acm(f); + struct usb_ep *ep; + int id; + + id = usb_interface_id(c, f); + if (id < 0) + return id; + + acm_iad_descriptor.bFirstInterface = id; + acm_control_intf_desc.bInterfaceNumber = id; + acm_union_desc.bMasterInterface0 = id; + + f_acm->ctrl_id = id; + + id = usb_interface_id(c, f); + if (id < 0) + return id; + + acm_data_intf_desc.bInterfaceNumber = id; + acm_union_desc.bSlaveInterface0 = id; + acm_call_mgmt_desc.bDataInterface = id; + + f_acm->data_id = id; + + /* allocate instance-specific endpoints */ + ep = usb_ep_autoconfig(gadget, &acm_fs_in_desc); + if (!ep) + return -ENODEV; + + f_acm->ep_in = ep; + + ep = usb_ep_autoconfig(gadget, &acm_fs_out_desc); + if (!ep) + return -ENODEV; + + f_acm->ep_out = ep; + + ep = usb_ep_autoconfig(gadget, &acm_fs_notify_desc); + if (!ep) + return -ENODEV; + + f_acm->ep_notify = ep; + + if (gadget_is_dualspeed(gadget)) { + /* Assume endpoint addresses are the same for both speeds */ + acm_hs_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress; + acm_hs_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress; + acm_hs_notify_desc.bEndpointAddress = acm_fs_notify_desc.bEndpointAddress; + } + + return 0; +} + +static void acm_unbind(struct usb_configuration *c, struct usb_function *f) +{ + struct f_acm *f_acm = func_to_acm(f); + struct stdio_dev *stdio; + + stdio = stdio_get_by_name(f_acm->stdio.name); + stdio_deregister_dev(stdio, 1); + + buf_free(&f_acm->rx_buf); + buf_free(&f_acm->tx_buf); + + free(f_acm); +} + +static void acm_notify_complete(struct usb_ep *ep, struct usb_request *req) +{ + if (req->status) + printf("CDC ACM notify failed (%d)\n", req->status); + + /* nothing to do */ +} + +static void acm_tx_complete(struct usb_ep *ep, struct usb_request *req) +{ + static int once; /* prevent infinite recursion */ + + if (req->status && !once++) + printf("CDC ACM TX failed (%d)\n", req->status); + + struct f_acm *f_acm = req->context; + + f_acm->tx_on = true; +} + +static void acm_rx_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct f_acm *f_acm = req->context; + + if (req->status != 0) + printf("CDC ACM RX failed (%d)\n", req->status); + + buf_push(&f_acm->rx_buf, req->buf, req->actual); + + /* Queue RX req again */ + req->actual = 0; + usb_ep_queue(ep, req, 0); +} + +static struct usb_request *acm_start_ep(struct usb_ep *ep, void *complete_cb, + void *context) +{ + struct usb_request *req; + + req = usb_ep_alloc_request(ep, 0); + if (!req) + return NULL; + + req->length = REQ_SIZE_MAX; + req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, REQ_SIZE_MAX); + if (!req->buf) { + usb_ep_free_request(ep, req); + return NULL; + } + + memset(req->buf, 0, req->length); + req->complete = complete_cb; + req->context = context; + + return req; +} + +static int acm_start_data(struct f_acm *f_acm, struct usb_gadget *gadget) +{ + const struct usb_endpoint_descriptor *d; + int ret; + + /* EP IN */ + d = ep_desc(gadget, &acm_hs_in_desc, &acm_fs_in_desc); + ret = usb_ep_enable(f_acm->ep_in, d); + if (ret) + return ret; + + f_acm->req_in = acm_start_ep(f_acm->ep_in, acm_tx_complete, f_acm); + + /* EP OUT */ + d = ep_desc(gadget, &acm_hs_out_desc, &acm_fs_out_desc); + ret = usb_ep_enable(f_acm->ep_out, d); + if (ret) + return ret; + + f_acm->req_out = acm_start_ep(f_acm->ep_out, acm_rx_complete, f_acm); + + /* Start OUT transfer (EP OUT) */ + ret = usb_ep_queue(f_acm->ep_out, f_acm->req_out, 0); + if (ret) + return ret; + + return 0; +} + +static int acm_start_ctrl(struct f_acm *f_acm, struct usb_gadget *gadget) +{ + const struct usb_endpoint_descriptor *d; + + usb_ep_disable(f_acm->ep_notify); + + d = ep_desc(gadget, &acm_hs_notify_desc, &acm_fs_notify_desc); + usb_ep_enable(f_acm->ep_notify, d); + + acm_start_ep(f_acm->ep_notify, acm_notify_complete, f_acm); + + return 0; +} + +static int acm_set_alt(struct usb_function *f, unsigned int intf, unsigned int alt) +{ + struct usb_gadget *gadget = f->config->cdev->gadget; + struct f_acm *f_acm = func_to_acm(f); + + if (intf == f_acm->ctrl_id) { + return acm_start_ctrl(f_acm, gadget); + } else if (intf == f_acm->data_id) { + acm_start_data(f_acm, gadget); + f_acm->connected = true; + f_acm->tx_on = true; + return 0; + } + + return -EINVAL; +} + +static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) +{ + struct usb_gadget *gadget = f->config->cdev->gadget; + struct usb_request *req = f->config->cdev->req; + u16 w_index = le16_to_cpu(ctrl->wIndex); + u16 w_value = le16_to_cpu(ctrl->wValue); + u16 w_length = le16_to_cpu(ctrl->wLength); + struct f_acm *f_acm = func_to_acm(f); + int value = -1; + + switch ((ctrl->bRequestType << 8) | ctrl->bRequest) { + case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) + | USB_CDC_REQ_SET_LINE_CODING: + { + /* SET_LINE_CODING */ + + if (w_length != sizeof(f_acm->line_coding) || w_index != f_acm->ctrl_id) + goto invalid; + + value = w_length; + + memcpy(&f_acm->line_coding, req->buf, value); + + break; + } + case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) + | USB_CDC_REQ_GET_LINE_CODING: + { + /* GET_LINE_CODING */ + + if (w_length != sizeof(f_acm->line_coding) || w_index != f_acm->ctrl_id) + goto invalid; + + value = w_length; + + memcpy(req->buf, &f_acm->line_coding, value); + + break; + } + case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) + | USB_CDC_REQ_SET_CONTROL_LINE_STATE: + { + /* SET_CONTROL_LINE_STATE */ + + if (w_index != f_acm->ctrl_id) + goto invalid; + + value = 0; + + f_acm->handshake_bits = w_value; + + break; + } + default: +invalid: + printf("invalid control req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, w_value, w_index, + w_length); + } + + /* respond with data transfer or status phase? */ + if (value >= 0) { + req->zero = 0; + req->length = value; + usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); + } + + return 0; +} + +static void acm_disable(struct usb_function *f) +{ + struct f_acm *f_acm = func_to_acm(f); + + usb_ep_disable(f_acm->ep_out); + usb_ep_disable(f_acm->ep_in); + usb_ep_disable(f_acm->ep_notify); + + if (f_acm->req_out) { + free(f_acm->req_out->buf); + usb_ep_free_request(f_acm->ep_out, f_acm->req_out); + f_acm->req_out = NULL; + } + + if (f_acm->req_in) { + free(f_acm->req_in->buf); + usb_ep_free_request(f_acm->ep_in, f_acm->req_in); + f_acm->req_in = NULL; + } +} + +/* static strings, in UTF-8 */ +static struct usb_string acm_string_defs[] = { + [0].s = "CDC Abstract Control Model (ACM)", + [1].s = "CDC ACM Data", + [2].s = "CDC Serial", + { } /* end of list */ +}; + +static struct usb_gadget_strings acm_string_table = { + .language = 0x0409, /* en-us */ + .strings = acm_string_defs, +}; + +static struct usb_gadget_strings *acm_strings[] = { + &acm_string_table, + NULL, +}; + +void __acm_tx(struct f_acm *f_acm) +{ + int len, ret; + + do { + usb_gadget_handle_interrupts(f_acm->controller_index); + + if (!(f_acm->handshake_bits & ACM_CTRL_DTR)) + break; + + if (!f_acm->tx_on) + continue; + + len = buf_pop(&f_acm->tx_buf, f_acm->req_in->buf, REQ_SIZE_MAX); + if (!len) + break; + + f_acm->req_in->length = len; + + ret = usb_ep_queue(f_acm->ep_in, f_acm->req_in, 0); + if (ret) + break; + + f_acm->tx_on = false; + + /* Do not reset the watchdog, if TX is stuck there is probably + * a real issue. + */ + } while (1); +} + +static bool acm_connected(struct stdio_dev *dev) +{ + struct f_acm *f_acm = stdio_to_acm(dev); + + /* give a chance to process udc irq */ + usb_gadget_handle_interrupts(f_acm->controller_index); + + return f_acm->connected; +} + +/* STDIO */ +static int acm_stdio_tstc(struct stdio_dev *dev) +{ + struct f_acm *f_acm = stdio_to_acm(dev); + + usb_gadget_handle_interrupts(f_acm->controller_index); + + return (f_acm->rx_buf.size > 0); +} + +static int acm_stdio_getc(struct stdio_dev *dev) +{ + struct f_acm *f_acm = stdio_to_acm(dev); + char c; + + /* Wait for a character to arrive. */ + while (!acm_stdio_tstc(dev)) + WATCHDOG_RESET(); + + buf_pop(&f_acm->rx_buf, &c, 1); + + return c; +} + +static void acm_stdio_putc(struct stdio_dev *dev, const char c) +{ + struct f_acm *f_acm = stdio_to_acm(dev); + + buf_push(&f_acm->tx_buf, &c, 1); + + if (!f_acm->connected) + return; + + __acm_tx(f_acm); +} + +static void acm_stdio_puts(struct stdio_dev *dev, const char *str) +{ + struct f_acm *f_acm = stdio_to_acm(dev); + + buf_push(&f_acm->tx_buf, str, strlen(str)); + + if (!f_acm->connected) + return; + + __acm_tx(f_acm); +} + +static int acm_stdio_start(struct stdio_dev *dev) +{ + while (!acm_connected(dev)) { + if (ctrlc()) + return -ECANCELED; + + WATCHDOG_RESET(); + } + + return 0; +} + +static int acm_stdio_stop(struct stdio_dev *dev) +{ + /* nothing to do */ + return 0; +} + +int acm_add(struct usb_configuration *c) +{ + struct stdio_dev *stdio; + struct f_acm *f_acm; + int status; + + f_acm = calloc(1, sizeof(*f_acm)); + if (!f_acm) + return -ENOMEM; + + f_acm->usb_function.name = "f_acm"; + f_acm->usb_function.bind = acm_bind; + f_acm->usb_function.unbind = acm_unbind; + f_acm->usb_function.set_alt = acm_set_alt; + f_acm->usb_function.disable = acm_disable; + f_acm->usb_function.strings = acm_strings; + f_acm->usb_function.descriptors = acm_fs_function; + f_acm->usb_function.hs_descriptors = acm_hs_function; + f_acm->usb_function.setup = acm_setup; + f_acm->controller_index = 0; + + status = usb_add_function(c, &f_acm->usb_function); + if (status) { + free(f_acm); + return status; + } + + stdio = &f_acm->stdio; + + buf_init(&f_acm->rx_buf, 2048); + buf_init(&f_acm->tx_buf, 2048); + + strcpy(stdio->name, "stdio_acm"); + stdio->flags = DEV_FLAGS_INPUT | DEV_FLAGS_OUTPUT; + stdio->tstc = acm_stdio_tstc; + stdio->getc = acm_stdio_getc; + stdio->putc = acm_stdio_putc; + stdio->puts = acm_stdio_puts; + stdio->start = acm_stdio_start; + stdio->stop = acm_stdio_stop; + stdio->priv = f_acm; + stdio->ext = 0; + + status = stdio_register(&f_acm->stdio); + if (status) { + buf_free(&f_acm->rx_buf); + buf_free(&f_acm->tx_buf); + } + + return status; +} + +DECLARE_GADGET_BIND_CALLBACK(usb_serial_acm, acm_add); From patchwork Thu Aug 19 11:13:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Loic Poulain X-Patchwork-Id: 499733 Delivered-To: patch@linaro.org Received: by 2002:a02:6f15:0:0:0:0:0 with SMTP id x21csp406518jab; Thu, 19 Aug 2021 04:03:15 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzLVKET9XPAwna8YxyJvXgHLLhx83grBv0UZ6b6moQDqjbDafyvw96YdD/ySWD5CC3nFcmZ X-Received: by 2002:a05:6402:22c7:: with SMTP id dm7mr15801243edb.105.1629370995144; Thu, 19 Aug 2021 04:03:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1629370995; cv=none; d=google.com; s=arc-20160816; b=MhG2flLY9jJIv1WSd39yfWdlSrD82WWkG9xz/6A14QLBjXFauUcbg3eMKqOLpwdJYa Xm/Ou0fik7HmcysjpvH8wfpDGSQNU7SdYiMkBhMmxdA/hpyZbkQZU6c9Dz1vVo5yL7hi 55st3lBbJPEUs2DT7F74QI7WACv4hSsOK23+fAIpNG3UGG6B3N0JEeytj8eVwi3qq1Rn 3nlBS2r03vn8niGB7xEZlzByKAtKClwVOVxngEPJX6QkLifQINOoV+bE9qlWhvg+i1Tv eHRqlA7NiAknJyfFbN6S1J8s3liVUJpaRsH3m1ggsczAhLhQGP5gp2Zyzw5GhxgLJ7N2 RYMw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=tqD6ZTG8O5lPeoFr6RnWUeEuI9k5uQ7/FI/HfufL1cE=; b=0OGB5uhaUx5sbHDqe8AjTOh5JPHtrn4Zw6vbCJGSoY63wouSQqzlxkhpPH/WTMl+JE eXTrMPJf5iFDpT9sVO5phUmS8IpCh6grN+gJLbVgPsjW4Ty7YSIiQEv0rRPltEn/VClu pQUt2+tjEIAZlSQ57hf/1SD4QGzK0zLF8GfLLmtCyLxCzzmn3aX5CeFtjlPN3EiNkmYQ acGqKHU00UvYjg65xcbUirWJWv3no6T2yZFqSXn45n5k6QzCM/1SCMJpk04oRbKUQDQ2 uxRBNnjjOS/YfnMl8qLJ29yXLTUd+iOJBRGKsMwW6HVi7ZlXQzVC7LbivpPEvymg39TG IdIA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=QLU2Q+GB; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id g17si3165313ejo.93.2021.08.19.04.03.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 19 Aug 2021 04:03:15 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=QLU2Q+GB; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 35C1582E7D; Thu, 19 Aug 2021 13:03:14 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="QLU2Q+GB"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9CCAE83131; Thu, 19 Aug 2021 13:03:11 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wm1-x334.google.com (mail-wm1-x334.google.com [IPv6:2a00:1450:4864:20::334]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 965FD8312F for ; Thu, 19 Aug 2021 13:03:06 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=loic.poulain@linaro.org Received: by mail-wm1-x334.google.com with SMTP id l7-20020a1c2507000000b002e6be5d86b3so3788336wml.3 for ; Thu, 19 Aug 2021 04:03:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=tqD6ZTG8O5lPeoFr6RnWUeEuI9k5uQ7/FI/HfufL1cE=; b=QLU2Q+GBApsSOqrtM02sjUmJ3ynV69uonk7F3l4JYINY5k1pRWgd+nTkZcFKwJfDly 3vKjeFaRBR53vK4Td4XqmapJhWvJo4GqN2g2aJBAmyxsQQbYUr79SSYH+PmjnJ/P6fk0 3TmSQXg/fzqYjK1YPxV9KNL8YbpQici9dClmnssVIX+FS5r3zdfn+0axal9YGLEv4Jxp LupmrFcy/tTkK/LAUaW1TWx1N9/dwlBJZEtHORNqZWG/00dZYsu5zp/tyWsQPYuhYL1Z 4iH5/LlynPmrzyZ6UV2ZbXID3PzEQrqTFE3z+x1KBzOyE2HIB0/ikK48/hS/Cx4L3Nb+ Qdew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=tqD6ZTG8O5lPeoFr6RnWUeEuI9k5uQ7/FI/HfufL1cE=; b=XYJ90c3tfOoEWw4/50M6BHJlu5lW+kWq4VrmEViIpZ5DQYf2NfkPHbVgDclc/YWdR0 HcnxdIVL+7dwoapb9H8O0EXFjRQcsBBuYnRg1RNwv5w8zkah5HrDGEyVkelUhZwlzopp 12BfNwVl1v1vj8kMt614bIaIo8/kuRrnmuGkkG3zsR4f3BbfOnTzHLOSoTOLzqCaaV+n Cz1jimpNcljd1pnFocb6Ur8898vxKB+OFTucM0Cf3i+h3d2tv1wmhgs9NCQKHBsi2o86 l8gyRdp58p10UwxQHwpvufJ04JP9pg33UlV6t5y5cBFVqz3V5BWCuoKH66NdiuLGP1pI Jiuw== X-Gm-Message-State: AOAM530On9Yy6/lYya9yD1RU9yQ/eK5OTJ4JMKlpcpTXOW8N69KXtZWy WqJrYUd2YcZsxKEFC9/qCT59Ug== X-Received: by 2002:a1c:751a:: with SMTP id o26mr12913602wmc.94.1629370985802; Thu, 19 Aug 2021 04:03:05 -0700 (PDT) Received: from lpoulain-ThinkPad-T470p.passengers.t31.sncf ([109.190.253.13]) by smtp.gmail.com with ESMTPSA id d8sm2705696wrv.20.2021.08.19.04.02.57 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 19 Aug 2021 04:03:05 -0700 (PDT) From: Loic Poulain To: marex@denx.de Cc: u-boot@lists.denx.de, lukma@denx.de, Loic Poulain Subject: [PATCH 3/3] cmd: add acmconsole command Date: Thu, 19 Aug 2021 13:13:06 +0200 Message-Id: <1629371586-9349-3-git-send-email-loic.poulain@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1629371586-9349-1-git-send-email-loic.poulain@linaro.org> References: <1629371586-9349-1-git-send-email-loic.poulain@linaro.org> X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean This command allows to start CDC ACM function and redirect console (stdin, stdout, stderr) to USB (acmconsole start). The console can then be accessed through the USB host for debugging purpose. The host can stop the session (acmconsole stop) to revert back console to serial and unregister CDC ACM USB function. Signed-off-by: Loic Poulain --- cmd/Kconfig | 8 ++++++++ cmd/Makefile | 2 ++ cmd/acmconsole.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 cmd/acmconsole.c -- 2.7.4 diff --git a/cmd/Kconfig b/cmd/Kconfig index ffef3cc..7cc9b1c 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1382,6 +1382,14 @@ config CMD_AXI Interface) busses, a on-chip interconnect specification for managing functional blocks in SoC designs, which is also often used in designs involving FPGAs (e.g. communication with IP cores in Xilinx FPGAs). + +config CMD_USB_ACM_CONSOLE + bool "ACM USB console" + select USB_FUNCTION_ACM + help + Enable the command "acmconsole" for accessing u-boot console from a + USB host through CDC ACM protocol. + endmenu diff --git a/cmd/Makefile b/cmd/Makefile index ed36694..c116091 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_CMD_BOOTMENU) += bootmenu.o obj-$(CONFIG_CMD_BOOTSTAGE) += bootstage.o obj-$(CONFIG_CMD_BOOTZ) += bootz.o obj-$(CONFIG_CMD_BOOTI) += booti.o +ob-y += acmconsole.o obj-$(CONFIG_CMD_BTRFS) += btrfs.o obj-$(CONFIG_CMD_BUTTON) += button.o obj-$(CONFIG_CMD_CACHE) += cache.o @@ -174,6 +175,7 @@ obj-$(CONFIG_CMD_FS_UUID) += fs_uuid.o obj-$(CONFIG_CMD_USB_MASS_STORAGE) += usb_mass_storage.o obj-$(CONFIG_CMD_USB_SDP) += usb_gadget_sdp.o obj-$(CONFIG_CMD_THOR_DOWNLOAD) += thordown.o +obj-$(CONFIG_CMD_USB_ACM_CONSOLE) += acmconsole.o obj-$(CONFIG_CMD_XIMG) += ximg.o obj-$(CONFIG_CMD_YAFFS2) += yaffs2.o obj-$(CONFIG_CMD_SPL) += spl.o diff --git a/cmd/acmconsole.c b/cmd/acmconsole.c new file mode 100644 index 0000000..dac8136 --- /dev/null +++ b/cmd/acmconsole.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * acmconsole.c -- Console over USB CDC serial (ACM) function gadget function + * + * Copyright (c) 2021, Linaro Ltd + */ + +#include +#include +#include +#include +#include +#include +#include + +int do_usb_acmconsole(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int ret; + + if (argc != 2) + return CMD_RET_USAGE; + + if (!strcmp(argv[1], "start")) { + ret = g_dnl_register("usb_serial_acm"); + if (ret) + return ret; + + /* ACM function creates a stdio device name 'stdio_acm' */ + console_assign(stdin, "stdio_acm"); + console_assign(stdout, "stdio_acm"); + console_assign(stderr, "stdio_acm"); + } else if (!strcmp(argv[1], "stop")) { + /* default to serial (TODO: restore initial devices) */ + console_assign(stdin, "serial"); + console_assign(stdout, "serial"); + console_assign(stderr, "serial"); + + g_dnl_unregister(); + g_dnl_clear_detach(); + } else { + return CMD_RET_USAGE; + } + + return 0; +} + +U_BOOT_CMD(acmconsole, CONFIG_SYS_MAXARGS, 1, do_usb_acmconsole, + "Console over USB CDC ACM", + "start - start console over USB CDC ACM gadget function\n" \ + "acmconsole stop - stop USB console");