-/* $OpenBSD: uchcom.c,v 1.19 2013/11/15 10:17:39 pirofti Exp $ */
+/* $OpenBSD: uchcom.c,v 1.20 2014/05/16 14:05:39 sasano Exp $ */
/* $NetBSD: uchcom.c,v 1.1 2007/09/03 17:57:37 tshiozak Exp $ */
/*
#define UCHCOM_BRK1_MASK 0x01
#define UCHCOM_BRK2_MASK 0x40
-#define UCHCOM_LCR1_MASK 0xAF
-#define UCHCOM_LCR2_MASK 0x07
-#define UCHCOM_LCR1_PARENB 0x80
-#define UCHCOM_LCR2_PAREVEN 0x07
-#define UCHCOM_LCR2_PARODD 0x06
-#define UCHCOM_LCR2_PARMARK 0x05
-#define UCHCOM_LCR2_PARSPACE 0x04
-
#define UCHCOM_INTR_STAT1 0x02
#define UCHCOM_INTR_STAT2 0x03
#define UCHCOM_INTR_LEAST 4
+/*
+ * XXX - these magic numbers come from Linux (drivers/usb/serial/ch341.c).
+ * The manufacturer was unresponsive when asked for documentation.
+ */
+#define UCHCOM_RESET_VALUE 0x501F /* line mode? */
+#define UCHCOM_RESET_INDEX 0xD90A /* baud rate? */
+
#define UCHCOMIBUFSIZE 256
#define UCHCOMOBUFSIZE 256
int
uchcom_set_line_control(struct uchcom_softc *sc, tcflag_t cflag)
{
- usbd_status err;
- uint8_t lcr1 = 0, lcr2 = 0;
-
- err = uchcom_read_reg(sc, UCHCOM_REG_LCR1, &lcr1, UCHCOM_REG_LCR2,
- &lcr2);
- if (err) {
- printf("%s: cannot get LCR: %s\n",
- sc->sc_dev.dv_xname, usbd_errstr(err));
- return EIO;
- }
-
- lcr1 &= ~UCHCOM_LCR1_MASK;
- lcr2 &= ~UCHCOM_LCR2_MASK;
-
/*
* XXX: it is difficult to handle the line control appropriately:
- * - CS8, !CSTOPB and any parity mode seems ok, but
- * - the chip doesn't have the function to calculate parity
- * in !CS8 mode.
- * - it is unclear that the chip supports CS5,6 mode.
- * - it is unclear how to handle stop bits.
+ * work as chip default - CS8, no parity, !CSTOPB
+ * other modes are not supported.
*/
switch (ISSET(cflag, CSIZE)) {
break;
}
- if (ISSET(cflag, PARENB)) {
- lcr1 |= UCHCOM_LCR1_PARENB;
- if (ISSET(cflag, PARODD))
- lcr2 |= UCHCOM_LCR2_PARODD;
- else
- lcr2 |= UCHCOM_LCR2_PAREVEN;
- }
-
- err = uchcom_write_reg(sc, UCHCOM_REG_LCR1, lcr1, UCHCOM_REG_LCR2,
- lcr2);
- if (err) {
- printf("%s: cannot set LCR: %s\n",
- sc->sc_dev.dv_xname, usbd_errstr(err));
- return EIO;
- }
+ if (ISSET(cflag, PARENB) || ISSET(cflag, CSTOPB))
+ return EINVAL;
return 0;
}
uchcom_reset_chip(struct uchcom_softc *sc)
{
usbd_status err;
- uint8_t lcr1, lcr2, pre, div, mod;
- uint16_t val=0, idx=0;
-
- err = uchcom_read_reg(sc, UCHCOM_REG_LCR1, &lcr1, UCHCOM_REG_LCR2, &lcr2);
- if (err)
- goto failed;
-
- err = uchcom_read_reg(sc, UCHCOM_REG_BPS_PRE, &pre, UCHCOM_REG_BPS_DIV,
- &div);
- if (err)
- goto failed;
- err = uchcom_read_reg(sc, UCHCOM_REG_BPS_MOD, &mod, UCHCOM_REG_BPS_PAD,
- NULL);
- if (err)
- goto failed;
+ DPRINTF(("%s: reset\n", sc->sc_dev.dv_xname));
- val |= (uint16_t)(lcr1&0xF0) << 8;
- val |= 0x01;
- val |= (uint16_t)(lcr2&0x0F) << 8;
- val |= 0x02;
- idx |= pre & 0x07;
- val |= 0x04;
- idx |= (uint16_t)div << 8;
- val |= 0x08;
- idx |= mod & 0xF8;
- val |= 0x10;
-
- DPRINTF(("%s: reset v=0x%04X, i=0x%04X\n",
- sc->sc_dev.dv_xname, val, idx));
-
- err = uchcom_generic_control_out(sc, UCHCOM_REQ_RESET, val, idx);
+ err = uchcom_generic_control_out(sc, UCHCOM_REQ_RESET,
+ UCHCOM_RESET_VALUE,
+ UCHCOM_RESET_INDEX);
if (err)
goto failed;