staticvoid hvsi_cd_change(struct hvsi_priv *pv, int cd)
{ if (cd)
pv->mctrl |= TIOCM_CD; else {
pv->mctrl &= ~TIOCM_CD;
/* We copy the existing hvsi driver semantics * here which are to trigger a hangup when * we get a carrier loss. * Closing our connection to the server will * do just that.
*/ if (!pv->is_console && pv->opened) {
pr_devel("HVSI@%x Carrier lost, hanging up !\n",
pv->termno);
hvsi_send_close(pv);
}
}
}
/* Check header validity. If it's invalid, we ditch * the whole buffer and hope we eventually resync
*/ if (pv->inbuf[0] < 0xfc) {
pv->inbuf_len = pv->inbuf_pktlen = 0; return 0;
}
type = pv->inbuf[0];
len = pv->inbuf[1];
pr_devel("HVSI@%x: Got packet type %x len %d bytes:\n",
pv->termno, type, len);
/* We have a packet, yay ! Handle it */ switch(type) { case VS_DATA_PACKET_HEADER:
pv->inbuf_pktlen = len - 4;
pv->inbuf_cur = 4; return 1; case VS_CONTROL_PACKET_HEADER:
hvsi_got_control(pv); break; case VS_QUERY_PACKET_HEADER:
hvsi_got_query(pv); break; case VS_QUERY_RESPONSE_PACKET_HEADER:
hvsi_got_response(pv); break;
}
staticint hvsi_get_packet(struct hvsi_priv *pv)
{ /* If we have room in the buffer, ask HV for more */ if (pv->inbuf_len < HVSI_INBUF_SIZE)
pv->inbuf_len += pv->get_chars(pv->termno,
&pv->inbuf[pv->inbuf_len],
HVSI_INBUF_SIZE - pv->inbuf_len); /* * If we have at least 4 bytes in the buffer, check for * a full packet and retry
*/ if (pv->inbuf_len >= 4) return hvsi_check_packet(pv); return 0;
}
/* If we aren't open, don't do anything in order to avoid races * with connection establishment. The hvc core will call this * before we have returned from notifier_add(), and we need to * avoid multiple users playing with the receive buffer
*/ if (!pv->opened) return 0;
/* We try twice, once with what data we have and once more * after we try to fetch some more from the hypervisor
*/ for (tries = 1; count && tries < 2; tries++) { /* Consume existing data packet */ if (pv->inbuf_pktlen) {
size_t l = min(count, pv->inbuf_pktlen);
memcpy(&buf[read], &pv->inbuf[pv->inbuf_cur], l);
pv->inbuf_cur += l;
pv->inbuf_pktlen -= l;
count -= l;
read += l;
} if (count == 0) break;
/* Data packet fully consumed, move down remaning data */ if (pv->inbuf_cur) {
pv->inbuf_len -= pv->inbuf_cur;
memmove(pv->inbuf, &pv->inbuf[pv->inbuf_cur],
pv->inbuf_len);
pv->inbuf_cur = 0;
}
/* Try to get another packet */ if (hvsi_get_packet(pv))
tries--;
} if (!pv->established) {
pr_devel("HVSI@%x: returning -EPIPE\n", pv->termno); return -EPIPE;
} return read;
}
/* Try for up to 200ms */ for (timeout = 0; timeout < 20; timeout++) { if (!pv->established) return -ENXIO; if (pv->mctrl_update) return 0; if (!hvsi_get_packet(pv))
maybe_msleep(10);
} return -EIO;
}
int hvsilib_write_mctrl(struct hvsi_priv *pv, int dtr)
{ struct hvsi_control ctrl; unsignedshort mctrl;
/* Try for up to 200ms, there can be a packet to * start the process waiting for us...
*/ for (timeout = 0; timeout < 20; timeout++) { if (pv->established) goto established; if (!hvsi_get_packet(pv))
maybe_msleep(10);
}
/* Failed, send a close connection packet just * in case
*/
pr_devel("HVSI@%x: ... sending close\n", pv->termno);
/* Try for up to 400ms */ for (timeout = 0; timeout < 40; timeout++) { if (pv->established) goto established; if (!hvsi_get_packet(pv))
maybe_msleep(10);
}
if (!pv->established) {
pr_devel("HVSI@%x: Timeout handshaking, giving up !\n",
pv->termno); return;
}
established: /* Query modem control lines */
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.