From: "Eric Bénard" <eric@eukrea.com>
To: barebox@lists.infradead.org
Subject: [PATCH v4 3/5] serial gadget: enable/disable on request
Date: Wed, 4 Jan 2012 10:36:47 +0100 [thread overview]
Message-ID: <1325669809-32637-3-git-send-email-eric@eukrea.com> (raw)
In-Reply-To: <1325669809-32637-1-git-send-email-eric@eukrea.com>
- add a usbserial command to enable/disable the serial gadget
- allow dfu and usbserial to cohexist in the same barebox
- add a timeout in u_serial so that we don't get locked if the user
enable usbserial from a UART console but doesn't consume the data
on the usbserial port created on the PC
- remove debug or verbose printf
- tested on i.MX25 & i.MX35 & usb-a926x
Signed-off-by: Eric Bénard <eric@eukrea.com>
Tested-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
v4 : introduce HAVE_OBEX as suggested by Sascha
v3 : fix comment in usbserial.c and add usbserial.h
v2 : always recompile after fixing checkpatch notes ...
commands/Makefile | 1 +
commands/usbserial.c | 108 +++++++++++++++++++++++++++++++++++++++++
drivers/usb/gadget/Kconfig | 5 +--
drivers/usb/gadget/f_acm.c | 4 +-
drivers/usb/gadget/serial.c | 48 ++++++++++++++++--
drivers/usb/gadget/u_serial.c | 22 +++++---
include/usb/usbserial.h | 19 +++++++
7 files changed, 188 insertions(+), 19 deletions(-)
create mode 100644 commands/usbserial.c
create mode 100644 include/usb/usbserial.h
diff --git a/commands/Makefile b/commands/Makefile
index 24753be..43630e1 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_CMD_LSMOD) += lsmod.o
obj-$(CONFIG_CMD_INSMOD) += insmod.o
obj-$(CONFIG_CMD_BMP) += bmp.o
obj-$(CONFIG_USB_GADGET_DFU) += dfu.o
+obj-$(CONFIG_USB_GADGET_SERIAL) += usbserial.o
obj-$(CONFIG_CMD_GPIO) += gpio.o
obj-$(CONFIG_CMD_UNCOMPRESS) += uncompress.o
obj-$(CONFIG_CMD_I2C) += i2c.o
diff --git a/commands/usbserial.c b/commands/usbserial.c
new file mode 100644
index 0000000..eb31934
--- /dev/null
+++ b/commands/usbserial.c
@@ -0,0 +1,108 @@
+/*
+ * usbserial.c - usb serial gadget command
+ *
+ * Copyright (c) 2011 Eric Bénard <eric@eukrea.com>, Eukréa Electromatique
+ * based on dfu.c which is :
+ * Copyright (c) 2009 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <common.h>
+#include <command.h>
+#include <errno.h>
+#include <malloc.h>
+#include <getopt.h>
+#include <fs.h>
+#include <xfuncs.h>
+#include <usb/usbserial.h>
+
+static int do_usbserial(struct command *cmdtp, int argc, char *argv[])
+{
+ int opt;
+ struct usb_serial_pdata pdata;
+ char *argstr;
+ char *manufacturer = "barebox";
+ char *productname = CONFIG_BOARDINFO;
+ u16 idVendor = 0, idProduct = 0;
+ int mode = 0;
+
+ while ((opt = getopt(argc, argv, "m:p:V:P:asd")) > 0) {
+ switch (opt) {
+ case 'm':
+ manufacturer = optarg;
+ break;
+ case 'p':
+ productname = optarg;
+ break;
+ case 'V':
+ idVendor = simple_strtoul(optarg, NULL, 0);
+ break;
+ case 'P':
+ idProduct = simple_strtoul(optarg, NULL, 0);
+ break;
+ case 'a':
+ mode = 0;
+ break;
+#ifdef HAVE_OBEX
+ case 'o':
+ mode = 1;
+ break;
+#endif
+ case 's':
+ mode = 2;
+ break;
+ case 'd':
+ usb_serial_unregister();
+ return 0;
+ }
+ }
+
+ argstr = argv[optind];
+
+ pdata.manufacturer = manufacturer;
+ pdata.productname = productname;
+ pdata.idVendor = idVendor;
+ pdata.idProduct = idProduct;
+ pdata.mode = mode;
+
+ return usb_serial_register(&pdata);
+}
+
+BAREBOX_CMD_HELP_START(usbserial)
+BAREBOX_CMD_HELP_USAGE("usbserial [OPTIONS] <description>\n")
+BAREBOX_CMD_HELP_SHORT("Enable/disable a serial gadget on the USB device interface.\n")
+BAREBOX_CMD_HELP_OPT ("-m <str>", "Manufacturer string (barebox)\n")
+BAREBOX_CMD_HELP_OPT ("-p <str>", "product string (" CONFIG_BOARDINFO ")\n")
+BAREBOX_CMD_HELP_OPT ("-V <id>", "vendor id\n")
+BAREBOX_CMD_HELP_OPT ("-P <id>", "product id\n")
+BAREBOX_CMD_HELP_OPT ("-a", "CDC ACM (default)\n")
+#ifdef HAVE_OBEX
+BAREBOX_CMD_HELP_OPT ("-o", "CDC OBEX\n")
+#endif
+BAREBOX_CMD_HELP_OPT ("-s", "Generic Serial\n")
+BAREBOX_CMD_HELP_OPT ("-d", "Disable the serial gadget\n")
+BAREBOX_CMD_HELP_END
+
+/**
+ * @page usbserial_command
+ */
+
+BAREBOX_CMD_START(usbserial)
+ .cmd = do_usbserial,
+ .usage = "Serial gadget enable/disable",
+ BAREBOX_CMD_HELP(cmd_usbserial_help)
+BAREBOX_CMD_END
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index fd471c0..797d19f 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -30,8 +30,7 @@ config USB_GADGET_DRIVER_PXA27X
select POLLER
endchoice
-choice
- prompt "USB Gadget drivers"
+comment "USB Gadget drivers"
config USB_GADGET_DFU
bool
@@ -42,7 +41,5 @@ config USB_GADGET_SERIAL
depends on EXPERIMENTAL
prompt "Serial Gadget"
-endchoice
-
endif
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 43b4992..218aed2 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -407,7 +407,7 @@ static void acm_disable(struct usb_function *f)
{
struct f_acm *acm = func_to_acm(f);
- printf("acm ttyGS%d deactivated\n", acm->port_num);
+ VDBG(cdev, "acm ttyGS%d deactivated\n", acm->port_num);
gserial_disconnect(&acm->port);
usb_ep_disable(acm->notify);
acm->notify->driver_data = NULL;
@@ -473,7 +473,7 @@ static int acm_notify_serial_state(struct f_acm *acm)
int status;
if (acm->notify_req) {
- printf("acm ttyGS%d serial state %04x\n",
+ VDBG(cdev, "acm ttyGS%d serial state %04x\n",
acm->port_num, acm->serial_state);
status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE,
0, &acm->serial_state, sizeof(acm->serial_state));
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 8ba9ab5..98a501b 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -4,6 +4,7 @@
#include <usb/ch9.h>
#include <usb/gadget.h>
#include <usb/composite.h>
+#include <usb/usbserial.h>
#include <asm/byteorder.h>
#include "u_serial.h"
@@ -52,7 +53,9 @@ static struct usb_gadget_strings *dev_strings[] = {
};
static int use_acm = 1;
+#ifdef HAVE_OBEX
static int use_obex = 0;
+#endif
static unsigned n_ports = 1;
static int serial_bind_config(struct usb_configuration *c)
@@ -63,8 +66,10 @@ static int serial_bind_config(struct usb_configuration *c)
for (i = 0; i < n_ports && status == 0; i++) {
if (use_acm)
status = acm_bind_config(c, i);
+#ifdef HAVE_OBEX
else if (use_obex)
status = obex_bind_config(c, i);
+#endif
else
status = gser_bind_config(c, i);
}
@@ -100,7 +105,7 @@ static int gs_bind(struct usb_composite_dev *cdev)
int gcnum;
struct usb_gadget *gadget = cdev->gadget;
int status;
-printf("%s\n", __func__);
+
status = gserial_setup(cdev->gadget, n_ports);
if (status < 0)
return status;
@@ -174,7 +179,7 @@ static struct usb_composite_driver gserial_driver = {
.bind = gs_bind,
};
-static int __init gserial_init(void)
+int usb_serial_register(struct usb_serial_pdata *pdata)
{
/* We *could* export two configs; that'd be much cleaner...
* but neither of these product IDs was defined that way.
@@ -187,19 +192,43 @@ static int __init gserial_init(void)
#ifdef CONFIG_ARCH_PXA2XX
use_acm = 0;
#endif
+ switch (pdata->mode) {
+ case 1:
+#ifdef HAVE_OBEX
+ use_obex = 1;
+#endif
+ use_acm = 0;
+ break;
+ case 2:
+#ifdef HAVE_OBEX
+ use_obex = 1;
+#endif
+ use_acm = 0;
+ break;
+ default:
+#ifdef HAVE_OBEX
+ use_obex = 0;
+#endif
+ use_acm = 1;
+ }
+
if (use_acm) {
serial_config_driver.label = "CDC ACM config";
serial_config_driver.bConfigurationValue = 2;
device_desc.bDeviceClass = USB_CLASS_COMM;
device_desc.idProduct =
cpu_to_le16(GS_CDC_PRODUCT_ID);
- } else if (use_obex) {
+ }
+#ifdef HAVE_OBEX
+ else if (use_obex) {
serial_config_driver.label = "CDC OBEX config";
serial_config_driver.bConfigurationValue = 3;
device_desc.bDeviceClass = USB_CLASS_COMM;
device_desc.idProduct =
cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID);
- } else {
+ }
+#endif
+ else {
serial_config_driver.label = "Generic Serial config";
serial_config_driver.bConfigurationValue = 1;
device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
@@ -207,8 +236,17 @@ static int __init gserial_init(void)
cpu_to_le16(GS_PRODUCT_ID);
}
strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label;
+ if (pdata->idVendor)
+ device_desc.idVendor = pdata->idVendor;
+ if (pdata->idProduct)
+ device_desc.idProduct = pdata->idProduct;
+ strings_dev[STRING_MANUFACTURER_IDX].s = pdata->manufacturer;
+ strings_dev[STRING_PRODUCT_IDX].s = pdata->productname;
return usb_composite_register(&gserial_driver);
}
-late_initcall(gserial_init);
+void usb_serial_unregister(void)
+{
+ usb_composite_unregister(&gserial_driver);
+}
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 49aedc2..e310c3a 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -20,6 +20,7 @@
#include <common.h>
#include <usb/cdc.h>
#include <kfifo.h>
+#include <clock.h>
#include "u_serial.h"
@@ -107,8 +108,6 @@ static unsigned n_ports;
#define GS_CLOSE_TIMEOUT 15 /* seconds */
-
-
#ifdef VERBOSE_DEBUG
#define pr_vdebug(fmt, arg...) \
pr_debug(fmt, ##arg)
@@ -370,6 +369,7 @@ static void serial_putc(struct console_device *cdev, char c)
struct usb_ep *in;
struct usb_request *req;
int status;
+ uint64_t to;
if (list_empty(pool))
return;
@@ -382,8 +382,12 @@ static void serial_putc(struct console_device *cdev, char c)
*(unsigned char *)req->buf = c;
status = usb_ep_queue(in, req);
- while (status >= 0 && list_empty(pool))
+ to = get_time_ns();
+ while (status >= 0 && list_empty(pool)) {
status = usb_gadget_poll();
+ if (is_timeout(to, 300 * MSECOND))
+ break;
+ }
}
static int serial_tstc(struct console_device *cdev)
@@ -399,11 +403,16 @@ static int serial_getc(struct console_device *cdev)
struct gs_port *port = container_of(cdev,
struct gs_port, cdev);
unsigned char ch;
+ uint64_t to;
if (!port->port_usb)
return -EIO;
- while (kfifo_getc(port->recv_fifo, &ch))
+ to = get_time_ns();
+ while (kfifo_getc(port->recv_fifo, &ch)) {
usb_gadget_poll();
+ if (is_timeout(to, 300 * MSECOND))
+ break;
+ }
return ch;
}
@@ -420,8 +429,6 @@ int gserial_connect(struct gserial *gser, u8 port_num)
int status;
struct console_device *cdev;
- printf("%s %p %d\n", __func__, gser, port_num);
-
/* we "know" gserial_cleanup() hasn't been called */
port = ports[port_num].port;
@@ -451,7 +458,7 @@ int gserial_connect(struct gserial *gser, u8 port_num)
port->recv_fifo = kfifo_alloc(1024);
- printf("gserial_connect: start ttyGS%d\n", port->port_num);
+ /*printf("gserial_connect: start ttyGS%d\n", port->port_num);*/
gs_start_io(port);
if (gser->connect)
gser->connect(gser);
@@ -508,7 +515,6 @@ void gserial_disconnect(struct gserial *gser)
struct gs_port *port = gser->ioport;
struct console_device *cdev;
- printf("%s\n", __func__);
if (!port)
return;
diff --git a/include/usb/usbserial.h b/include/usb/usbserial.h
new file mode 100644
index 0000000..43c839c
--- /dev/null
+++ b/include/usb/usbserial.h
@@ -0,0 +1,19 @@
+#ifndef _USB_SERIAL_H
+#define _USB_SERIAL_H
+
+struct usb_serial_pdata {
+ char *manufacturer;
+ char *productname;
+ u16 idVendor;
+ u16 idProduct;
+ int mode;
+};
+
+int usb_serial_register(struct usb_serial_pdata *pdata);
+void usb_serial_unregister(void);
+
+/* OBEX support is missing in barebox */
+/* #define HAVE_OBEX */
+
+#endif /* _USB_SERIAL_H */
+
--
1.7.7.5
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2012-01-04 9:37 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-01-04 9:36 [PATCH v4 1/5] fsl_udc: update and fix Eric Bénard
2012-01-04 9:36 ` [PATCH v4 2/5] dfu: fill bwPollTimeout and better handle detach Eric Bénard
2012-01-04 9:36 ` Eric Bénard [this message]
2012-01-04 9:36 ` [PATCH v4 4/5] timeout: add poller_call Eric Bénard
2012-01-04 10:47 ` Jean-Christophe PLAGNIOL-VILLARD
2012-01-04 11:10 ` Eric Bénard
2012-01-04 11:44 ` Jean-Christophe PLAGNIOL-VILLARD
2012-01-04 13:32 ` Eric Bénard
2012-01-04 15:31 ` Eric Bénard
2012-01-04 9:36 ` [PATCH v4 5/5] eukrea_cpuimx35: fix compilation when CONFIG_USB_GADGET is enabled Eric Bénard
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1325669809-32637-3-git-send-email-eric@eukrea.com \
--to=eric@eukrea.com \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.