svn commit: r186885 - head/sys/dev/usb2/serial

Takanori Watanabe takawata at FreeBSD.org
Wed Jan 7 21:10:04 PST 2009


Author: takawata
Date: Thu Jan  8 05:10:03 2009
New Revision: 186885
URL: http://svn.freebsd.org/changeset/base/186885

Log:
  Make ufoma2 driver work.
  1.Sync TD on close to ensure USB request in close callback issued.
  2.Add sysctls to indicate device role.
  3.Enable handsfree port support.
  
  Now modem port and obex port works well.
  Handsfree port works but not with good response.

Modified:
  head/sys/dev/usb2/serial/ufoma2.c
  head/sys/dev/usb2/serial/usb2_serial.c

Modified: head/sys/dev/usb2/serial/ufoma2.c
==============================================================================
--- head/sys/dev/usb2/serial/ufoma2.c	Thu Jan  8 04:26:44 2009	(r186884)
+++ head/sys/dev/usb2/serial/ufoma2.c	Thu Jan  8 05:10:03 2009	(r186885)
@@ -2,6 +2,7 @@
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
+#define UFOMA_HANDSFREE
 
 /*-
  * Copyright (c) 2005, Takanori Watanabe
@@ -101,6 +102,8 @@ __FBSDID("$FreeBSD$");
 #include <dev/usb2/core/usb2_busdma.h>
 
 #include <dev/usb2/serial/usb2_serial.h>
+#include <sys/sysctl.h>
+#include <sys/sbuf.h>
 
 typedef struct ufoma_mobile_acm_descriptor {
 	uint8_t	bFunctionLength;
@@ -217,6 +220,12 @@ static void	ufoma_stop_read(struct usb2_
 static void	ufoma_start_write(struct usb2_com_softc *);
 static void	ufoma_stop_write(struct usb2_com_softc *);
 
+/*sysctl stuff*/
+static int ufoma_sysctl_support(SYSCTL_HANDLER_ARGS);
+static int ufoma_sysctl_current(SYSCTL_HANDLER_ARGS);
+static int ufoma_sysctl_open(SYSCTL_HANDLER_ARGS);
+
+
 static const struct usb2_config
 	ufoma_ctrl_config[UFOMA_CTRL_ENDPT_MAX] = {
 
@@ -380,6 +389,9 @@ ufoma_attach(device_t dev)
 	struct ufoma_softc *sc = device_get_softc(dev);
 	struct usb2_config_descriptor *cd;
 	struct usb2_interface_descriptor *id;
+	struct sysctl_ctx_list *sctx;
+	struct sysctl_oid *soid;
+
 	usb2_mcpc_acm_descriptor *mad;
 	uint8_t elements;
 	int32_t error;
@@ -459,6 +471,23 @@ ufoma_attach(device_t dev)
 		DPRINTF("usb2_com_attach failed\n");
 		goto detach;
 	}
+	/*Sysctls*/
+	sctx = device_get_sysctl_ctx(dev);
+	soid = device_get_sysctl_tree(dev);
+
+	SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "supportmode",
+			CTLFLAG_RD|CTLTYPE_STRING, sc, 0, ufoma_sysctl_support,
+			"A", "Supporting port role");
+
+	SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "currentmode",
+			CTLFLAG_RD|CTLTYPE_STRING, sc, 0, ufoma_sysctl_current,
+			"A", "Current port role");
+
+	SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "openmode",
+			CTLFLAG_RW|CTLTYPE_STRING, sc, 0, ufoma_sysctl_open,
+			"A", "Mode to transit when port is opened");
+
+
 	return (0);			/* success */
 
 detach:
@@ -910,7 +939,8 @@ ufoma_cfg_set_break(struct usb2_com_soft
 	struct usb2_device_request req;
 	uint16_t wValue;
 
-	if (sc->sc_is_pseudo) {
+	if (sc->sc_is_pseudo ||
+	    (sc->sc_currentmode == UMCPC_ACM_MODE_OBEX)) {
 		return;
 	}
 	if (!(sc->sc_acm_cap & USB_CDC_ACM_HAS_BREAK)) {
@@ -1181,3 +1211,113 @@ ufoma_stop_write(struct usb2_com_softc *
 		usb2_transfer_stop(sc->sc_bulk_xfer[0]);
 	}
 }
+
+struct umcpc_modetostr_tab{
+	int mode;
+	char *str;
+}umcpc_modetostr_tab[]={
+	{UMCPC_ACM_MODE_DEACTIVATED, "deactivated"},
+	{UMCPC_ACM_MODE_MODEM, "modem"},
+	{UMCPC_ACM_MODE_ATCOMMAND, "handsfree"},
+	{UMCPC_ACM_MODE_OBEX, "obex"},
+	{UMCPC_ACM_MODE_VENDOR1, "vendor1"},
+	{UMCPC_ACM_MODE_VENDOR2, "vendor2"},
+	{UMCPC_ACM_MODE_UNLINKED, "unlinked"},
+	{0, NULL}
+};
+
+static char *ufoma_mode_to_str(int mode)
+{
+	int i;
+	for(i = 0 ;umcpc_modetostr_tab[i].str != NULL; i++){
+		if(umcpc_modetostr_tab[i].mode == mode){
+			return umcpc_modetostr_tab[i].str;
+		}
+	}
+	return NULL;
+}
+
+static int ufoma_str_to_mode(char *str)
+{
+	int i;
+	for(i = 0 ;umcpc_modetostr_tab[i].str != NULL; i++){
+		if(strcmp(str, umcpc_modetostr_tab[i].str)==0){
+			return umcpc_modetostr_tab[i].mode;
+		}
+	}
+	return -1;
+}
+
+static int ufoma_sysctl_support(SYSCTL_HANDLER_ARGS)
+{
+	struct ufoma_softc *sc = (struct ufoma_softc *)oidp->oid_arg1;
+	struct sbuf sb;
+	int i;
+	char *mode;
+
+	sbuf_new(&sb, NULL, 1, SBUF_AUTOEXTEND);
+	for(i = 1; i < sc->sc_modetable[0]; i++){
+		mode = ufoma_mode_to_str(sc->sc_modetable[i]);
+		if(mode !=NULL){
+			sbuf_cat(&sb, mode);
+		}else{
+			sbuf_printf(&sb, "(%02x)", sc->sc_modetable[i]);
+		}
+		if(i < (sc->sc_modetable[0]-1))
+			sbuf_cat(&sb, ",");
+	}
+	sbuf_trim(&sb);
+	sbuf_finish(&sb);
+	sysctl_handle_string(oidp, sbuf_data(&sb), sbuf_len(&sb), req);
+	sbuf_delete(&sb);
+	
+	return 0;
+}
+static int ufoma_sysctl_current(SYSCTL_HANDLER_ARGS)
+{
+	struct ufoma_softc *sc = (struct ufoma_softc *)oidp->oid_arg1;
+	char *mode;
+	char subbuf[]="(XXX)";
+	mode = ufoma_mode_to_str(sc->sc_currentmode);
+	if(!mode){
+		mode = subbuf;
+		snprintf(subbuf, sizeof(subbuf), "(%02x)", sc->sc_currentmode);
+	}
+	sysctl_handle_string(oidp, mode, strlen(mode), req);
+	
+	return 0;
+	
+}
+static int ufoma_sysctl_open(SYSCTL_HANDLER_ARGS)
+{
+	struct ufoma_softc *sc = (struct ufoma_softc *)oidp->oid_arg1;
+	char *mode;
+	char subbuf[40];
+	int newmode;
+	int error;
+	int i;
+
+	mode = ufoma_mode_to_str(sc->sc_modetoactivate);
+	if(mode){
+		strncpy(subbuf, mode, sizeof(subbuf));
+	}else{
+		snprintf(subbuf, sizeof(subbuf), "(%02x)", sc->sc_modetoactivate);
+	}
+	error = sysctl_handle_string(oidp, subbuf, sizeof(subbuf), req);
+	if(error != 0 || req->newptr == NULL){
+		return error;
+	}
+	
+	if((newmode = ufoma_str_to_mode(subbuf)) == -1){
+		return EINVAL;
+	}
+	
+	for(i = 1 ; i < sc->sc_modetable[0] ; i++){
+		if(sc->sc_modetable[i] == newmode){
+			sc->sc_modetoactivate = newmode;
+			return 0;
+		}
+	}
+	
+	return EINVAL;
+}

Modified: head/sys/dev/usb2/serial/usb2_serial.c
==============================================================================
--- head/sys/dev/usb2/serial/usb2_serial.c	Thu Jan  8 04:26:44 2009	(r186884)
+++ head/sys/dev/usb2/serial/usb2_serial.c	Thu Jan  8 05:10:03 2009	(r186885)
@@ -588,7 +588,8 @@ static void
 usb2_com_close(struct tty *tp)
 {
 	struct usb2_com_softc *sc = tty_softc(tp);
-
+	struct usb2_com_super_softc *ssc = sc->sc_super;
+	
 	mtx_assert(sc->sc_parent_mtx, MA_OWNED);
 
 	DPRINTF("tp=%p\n", tp);
@@ -600,6 +601,7 @@ usb2_com_close(struct tty *tp)
 	usb2_com_shutdown(sc);
 
 	usb2_com_queue_command(sc, &usb2_com_cfg_close, 0);
+	usb2_config_td_sync(&ssc->sc_config_td);
 
 	sc->sc_flag &= ~(UCOM_FLAG_HL_READY |
 	    UCOM_FLAG_WR_START |


More information about the svn-src-head mailing list