summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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