summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortakawata <takawata@FreeBSD.org>2009-01-08 05:10:03 +0000
committertakawata <takawata@FreeBSD.org>2009-01-08 05:10:03 +0000
commit002f6ee5fca92be1ff3dbce38758b7bdd5bd3f91 (patch)
tree286ed9fde22022a81d76fe4c512c357e4044efba
parent8adb645b16ddc506b4b9e5ce06c08af2a1b524ed (diff)
downloadFreeBSD-src-002f6ee5fca92be1ff3dbce38758b7bdd5bd3f91.zip
FreeBSD-src-002f6ee5fca92be1ff3dbce38758b7bdd5bd3f91.tar.gz
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.
-rw-r--r--sys/dev/usb2/serial/ufoma2.c142
-rw-r--r--sys/dev/usb2/serial/usb2_serial.c4
2 files changed, 144 insertions, 2 deletions
diff --git a/sys/dev/usb2/serial/ufoma2.c b/sys/dev/usb2/serial/ufoma2.c
index 52d8a90..21a58e2 100644
--- a/sys/dev/usb2/serial/ufoma2.c
+++ b/sys/dev/usb2/serial/ufoma2.c
@@ -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_com_softc *);
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_softc *ucom, uint8_t onoff)
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 *ucom)
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;
+}
diff --git a/sys/dev/usb2/serial/usb2_serial.c b/sys/dev/usb2/serial/usb2_serial.c
index 8872c79..7a2f2e1 100644
--- a/sys/dev/usb2/serial/usb2_serial.c
+++ b/sys/dev/usb2/serial/usb2_serial.c
@@ -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 |
OpenPOWER on IntegriCloud