Don't issue CDC request before negotiate the interface role.
This commit is contained in:
parent
272de45514
commit
d24ab9bd6f
@ -148,9 +148,9 @@ typedef struct ufoma_mobile_acm_descriptor{
|
||||
#define UFOMA_MAX_TIMEOUT 15 /*Standard says 10(sec)*/
|
||||
#define UFOMA_CMD_BUF_SIZE 64
|
||||
|
||||
#define UMODEMIBUFSIZE 64
|
||||
#define UMODEMOBUFSIZE 256
|
||||
#define DPRINTF(a)
|
||||
#define UMODEMIBUFSIZE 1024
|
||||
#define UMODEMOBUFSIZE 1024
|
||||
#define DPRINTF(a)
|
||||
|
||||
struct ufoma_softc{
|
||||
struct ucom_softc sc_ucom;
|
||||
@ -165,6 +165,7 @@ struct ufoma_softc{
|
||||
int sc_cm_cap;
|
||||
int sc_acm_cap;
|
||||
usb_cdc_line_state_t sc_line_state; /* current line state */
|
||||
usb_cdc_line_state_t sc_line_state_init; /* pre open line state*/
|
||||
u_char sc_dtr; /* current DTR state */
|
||||
u_char sc_rts; /* current RTS state */
|
||||
|
||||
@ -196,9 +197,10 @@ static int ufoma_str_to_mode(char *);
|
||||
#ifdef UFOMA_HANDSFREE
|
||||
/*Pseudo ucom stuff(for Handsfree interface)*/
|
||||
static int ufoma_init_pseudo_ucom(struct ufoma_softc *);
|
||||
static t_open_t ufomaopen;
|
||||
static t_close_t ufomaclose;
|
||||
static t_oproc_t ufomastart;
|
||||
static tsw_open_t ufoma_open;
|
||||
static tsw_close_t ufoma_close;
|
||||
static tsw_outwakeup_t ufoma_outwakeup;
|
||||
static tsw_free_t ufoma_free;
|
||||
#endif
|
||||
|
||||
/*umodem like stuff*/
|
||||
@ -216,17 +218,14 @@ static void ufoma_rts(struct ufoma_softc *sc, int onoff);
|
||||
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 void ufoma_set_line_state(struct ufoma_softc *sc);
|
||||
|
||||
static struct ucom_callback ufoma_callback = {
|
||||
ufoma_get_status,
|
||||
ufoma_set,
|
||||
ufoma_param,
|
||||
NULL,
|
||||
ufoma_ucom_open,
|
||||
ufoma_ucom_close,
|
||||
NULL,
|
||||
NULL,
|
||||
.ucom_get_status = ufoma_get_status,
|
||||
.ucom_set = ufoma_set,
|
||||
.ucom_param = ufoma_param,
|
||||
.ucom_open = ufoma_ucom_open,
|
||||
.ucom_close = ufoma_ucom_close,
|
||||
};
|
||||
|
||||
|
||||
@ -395,7 +394,6 @@ ufoma_attach(device_t self)
|
||||
}
|
||||
}
|
||||
elements = mad->bFunctionLength - sizeof(*mad)+1;
|
||||
|
||||
sc->sc_msgxf = usbd_alloc_xfer(ucom->sc_udev);
|
||||
sc->sc_nummsg = 0;
|
||||
|
||||
@ -405,6 +403,7 @@ ufoma_attach(device_t self)
|
||||
bcopy(mad->bMode, &sc->sc_modetable[1], elements);
|
||||
sc->sc_currentmode = UMCPC_ACM_MODE_UNLINKED;
|
||||
sc->sc_modetoactivate = mad->bMode[0];
|
||||
|
||||
/*Sysctls*/
|
||||
sctx = device_get_sysctl_ctx(self);
|
||||
soid = device_get_sysctl_tree(self);
|
||||
@ -420,6 +419,7 @@ ufoma_attach(device_t self)
|
||||
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;
|
||||
error:
|
||||
if(sc->sc_modetable)
|
||||
@ -442,7 +442,8 @@ ufoma_detach(device_t self)
|
||||
}
|
||||
#ifdef UFOMA_HANDSFREE
|
||||
else{
|
||||
ttyfree(sc->sc_ucom.sc_tty);
|
||||
tty_lock(sc->sc_ucom.sc_tty);
|
||||
tty_rel_gone(sc->sc_ucom.sc_tty);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -509,15 +510,16 @@ static int ufoma_link_state(struct ufoma_softc *sc)
|
||||
usb_device_request_t req;
|
||||
struct ucom_softc *ucom = &sc->sc_ucom;
|
||||
int err;
|
||||
|
||||
|
||||
req.bmRequestType = UT_WRITE_VENDOR_INTERFACE;
|
||||
req.bRequest = UMCPC_SET_LINK;
|
||||
USETW(req.wValue, UMCPC_CM_MOBILE_ACM);
|
||||
USETW(req.wIndex, sc->sc_ctl_iface_no);
|
||||
USETW(req.wLength, sc->sc_modetable[0]);
|
||||
|
||||
err = usbd_do_request(ucom->sc_udev, &req, sc->sc_modetable);
|
||||
if(err){
|
||||
printf("SET_LINK:%d\n", err);
|
||||
printf("SET_LINK:%s\n",usbd_errstr(err));
|
||||
return EIO;
|
||||
}
|
||||
err = tsleep(&sc->sc_currentmode, PZERO|PCATCH, "fmalnk", hz);
|
||||
@ -581,9 +583,15 @@ static void ufoma_msg(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_stat
|
||||
ufoma_setup_msg_req(sc, &req);
|
||||
mtx_lock(&sc->sc_mtx);
|
||||
for(i = 0;i < actlen; i++){
|
||||
if(sc->sc_ucom.sc_tty->t_state & TS_ISOPEN)
|
||||
ttyld_rint(sc->sc_ucom.sc_tty, sc->sc_resbuffer[i]);
|
||||
|
||||
if(ttydisc_rint(sc->sc_ucom.sc_tty, sc->sc_resbuffer[i], 0)
|
||||
== -1){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ttydisc_rint_done(sc->sc_ucom.sc_tty);
|
||||
|
||||
sc->sc_nummsg--;
|
||||
if(sc->sc_nummsg){
|
||||
usbd_setup_default_xfer(sc->sc_msgxf, ucom->sc_udev,
|
||||
@ -603,6 +611,7 @@ static void ufoma_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_sta
|
||||
unsigned int a;
|
||||
struct ucom_softc *ucom =&sc->sc_ucom;
|
||||
u_char mstatus;
|
||||
|
||||
#ifdef UFOMA_HANDSFREE
|
||||
usb_device_request_t req;
|
||||
|
||||
@ -689,27 +698,33 @@ static void ufoma_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_sta
|
||||
}
|
||||
|
||||
#ifdef UFOMA_HANDSFREE
|
||||
struct ttydevsw ufomatty_class ={
|
||||
.tsw_flags = TF_INITLOCK|TF_CALLOUT,
|
||||
.tsw_open = ufoma_open,
|
||||
.tsw_close = ufoma_close,
|
||||
.tsw_outwakeup = ufoma_outwakeup,
|
||||
.tsw_free = ufoma_free
|
||||
};
|
||||
static void ufoma_free(void *sc)
|
||||
{
|
||||
|
||||
}
|
||||
static int ufoma_init_pseudo_ucom(struct ufoma_softc *sc)
|
||||
{
|
||||
struct tty *tp;
|
||||
struct ucom_softc *ucom = &sc->sc_ucom;
|
||||
tp = ucom->sc_tty = ttyalloc();
|
||||
tp->t_sc = sc;
|
||||
tp->t_oproc = ufomastart;
|
||||
tp->t_stop = nottystop;
|
||||
tp->t_open = ufomaopen;
|
||||
tp->t_close = ufomaclose;
|
||||
ttycreate(tp, TS_CALLOUT, "U%d", device_get_unit(ucom->sc_dev));
|
||||
tp = ucom->sc_tty = tty_alloc(&ufomatty_class, sc, &Giant);
|
||||
tty_makedev(tp, NULL, "U%d", device_get_unit(ucom->sc_dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ufomaopen(struct tty * tty, struct cdev *cdev)
|
||||
static int ufoma_open(struct tty * tty)
|
||||
{
|
||||
|
||||
struct ufoma_softc *sc = tty->t_sc;
|
||||
|
||||
struct ufoma_softc *sc = tty_softc(tty);
|
||||
|
||||
if(sc->sc_ucom.sc_dying)
|
||||
return (ENXIO);
|
||||
|
||||
@ -723,38 +738,46 @@ static int ufomaopen(struct tty * tty, struct cdev *cdev)
|
||||
return ufoma_ucom_open(sc, 0);
|
||||
}
|
||||
|
||||
static void ufomaclose(struct tty *tty)
|
||||
static void ufoma_close(struct tty *tty)
|
||||
{
|
||||
struct ufoma_softc *sc = tty->t_sc;
|
||||
struct ufoma_softc *sc = tty_softc(tty);
|
||||
|
||||
ufoma_ucom_close(sc, 0);
|
||||
}
|
||||
|
||||
static void ufomastart(struct tty *tp)
|
||||
static void ufoma_outwakeup(struct tty *tp)
|
||||
{
|
||||
struct ufoma_softc *sc = tp->t_sc;
|
||||
struct ufoma_softc *sc = tty_softc(tp);
|
||||
struct ucom_softc *ucom = &sc->sc_ucom;
|
||||
usb_device_request_t req;
|
||||
int x;
|
||||
uByte c;
|
||||
x = spltty();
|
||||
if(tp->t_state & (TS_TIMEOUT | TS_TTSTOP)){
|
||||
ttwwakeup(tp);
|
||||
return;
|
||||
}
|
||||
int len,i;
|
||||
unsigned char buf[128];
|
||||
|
||||
tp->t_state |= TS_BUSY;
|
||||
while(tp->t_outq.c_cc != 0){
|
||||
c = getc(&tp->t_outq);
|
||||
req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
|
||||
req.bRequest = UCDC_SEND_ENCAPSULATED_COMMAND;
|
||||
USETW(req.wIndex, sc->sc_ctl_iface_no);
|
||||
USETW(req.wValue, 0);
|
||||
USETW(req.wLength, 1);
|
||||
usbd_do_request(ucom->sc_udev, &req, &c);
|
||||
uByte c;
|
||||
if(ucom->sc_dying)
|
||||
return;
|
||||
if(ucom->sc_state &UCS_TXBUSY)
|
||||
return;
|
||||
|
||||
ucom->sc_state |= UCS_TXBUSY;
|
||||
for(;;){
|
||||
len = ttydisc_getc(tp, buf, sizeof(buf));
|
||||
if(len == 0){
|
||||
break;
|
||||
}
|
||||
|
||||
for(i=0; i < len; i++){
|
||||
req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
|
||||
c = buf[i];
|
||||
req.bRequest = UCDC_SEND_ENCAPSULATED_COMMAND;
|
||||
USETW(req.wIndex, sc->sc_ctl_iface_no);
|
||||
USETW(req.wValue, 0);
|
||||
USETW(req.wLength, 1);
|
||||
usbd_do_request(ucom->sc_udev, &req, &c);
|
||||
}
|
||||
}
|
||||
tp->t_state &= ~TS_BUSY;
|
||||
ttwwakeup(tp);
|
||||
splx(x);
|
||||
ucom->sc_state |= UCS_TXBUSY;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -762,14 +785,28 @@ static void ufomastart(struct tty *tp)
|
||||
static int ufoma_ucom_open(void *p, int portno)
|
||||
{
|
||||
struct ufoma_softc *sc = p;
|
||||
int res;
|
||||
|
||||
if(sc->sc_currentmode == UMCPC_ACM_MODE_UNLINKED){
|
||||
ufoma_link_state(sc);
|
||||
if((res = ufoma_link_state(sc))){
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
sc->sc_cmdbp = 0;
|
||||
if(sc->sc_currentmode == UMCPC_ACM_MODE_DEACTIVATED){
|
||||
ufoma_activate_state(sc, sc->sc_modetoactivate);
|
||||
if((res = ufoma_activate_state(sc, sc->sc_modetoactivate))){
|
||||
return res;
|
||||
}
|
||||
}
|
||||
mtx_lock(&sc->sc_mtx);
|
||||
sc->sc_isopen = 1;
|
||||
mtx_unlock(&sc->sc_mtx);
|
||||
/*Now line coding should be set.*/
|
||||
if(sc->sc_is_ucom){
|
||||
ufoma_set_line_state(sc);
|
||||
ufoma_set_line_coding(sc, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -777,6 +814,9 @@ static void ufoma_ucom_close(void *p, int portno)
|
||||
{
|
||||
struct ufoma_softc *sc = p;
|
||||
ufoma_activate_state(sc, UMCPC_ACM_MODE_DEACTIVATED);
|
||||
mtx_lock(&sc->sc_mtx);
|
||||
sc->sc_isopen = 0;
|
||||
mtx_unlock(&sc->sc_mtx);
|
||||
return ;
|
||||
}
|
||||
|
||||
@ -837,6 +877,10 @@ ufoma_set_line_state(struct ufoma_softc *sc)
|
||||
struct ucom_softc *ucom = &sc->sc_ucom;
|
||||
int ls;
|
||||
|
||||
if(!sc->sc_isopen){
|
||||
return ; /*Set it later*/
|
||||
}
|
||||
|
||||
ls = (sc->sc_dtr ? UCDC_LINE_DTR : 0) |
|
||||
(sc->sc_rts ? UCDC_LINE_RTS : 0);
|
||||
req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
|
||||
@ -880,12 +924,17 @@ ufoma_set_line_coding(struct ufoma_softc *sc, usb_cdc_line_state_t *state)
|
||||
usbd_status err;
|
||||
usb_device_request_t req;
|
||||
struct ucom_softc *ucom = &sc->sc_ucom;
|
||||
|
||||
if(!sc->sc_isopen){
|
||||
sc->sc_line_state_init = *state;
|
||||
return (USBD_NORMAL_COMPLETION);
|
||||
}
|
||||
DPRINTF(("ufoma_set_line_coding: rate=%d fmt=%d parity=%d bits=%d\n",
|
||||
UGETDW(state->dwDTERate), state->bCharFormat,
|
||||
state->bParityType, state->bDataBits));
|
||||
|
||||
if (memcmp(state, &sc->sc_line_state, UCDC_LINE_STATE_LENGTH) == 0) {
|
||||
if(state == NULL){
|
||||
state = &sc->sc_line_state_init;
|
||||
}else if (memcmp(state, &sc->sc_line_state,
|
||||
UCDC_LINE_STATE_LENGTH) == 0) {
|
||||
DPRINTF(("ufoma_set_line_coding: already set\n"));
|
||||
return (USBD_NORMAL_COMPLETION);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user