static int ch341_set_baudrate(struct usb_device *dev, struct ch341_private *priv) { short a, b; int r; unsigned long factor; short divisor; if (!priv->baud_rate) return -EINVAL; factor = (CH341_BAUDBASE_FACTOR / priv->baud_rate); divisor = CH341_BAUDBASE_DIVMAX; while ((factor > 0xfff0) && divisor) { factor >>= 3; divisor--; } if (factor > 0xfff0) return -EINVAL; factor = 0x10000 - factor; a = (factor & 0xff00) | divisor; b = factor & 0xff; r = ch341_control_out(dev, 0x9a, 0x1312, a); if (!r) r = ch341_control_out(dev, 0x9a, 0x0f2c, b); return r; }
static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) { char *buffer; int r; const unsigned size = 8; dbg("ch341_configure()"); buffer = kmalloc(size, GFP_KERNEL); if (!buffer) return -ENOMEM; /* expect two bytes 0x27 0x00 */ r = ch341_control_in(dev, 0x5f, 0, 0, buffer, size); if (r < 0) goto out; r = ch341_control_out(dev, 0xa1, 0, 0); if (r < 0) goto out; r = ch341_set_baudrate(dev, priv); if (r < 0) goto out; /* expect two bytes 0x56 0x00 */ r = ch341_control_in(dev, 0x95, 0x2518, 0, buffer, size); if (r < 0) goto out; r = ch341_control_out(dev, 0x9a, 0x2518, 0x0050); if (r < 0) goto out; /* expect 0xff 0xee */ r = ch341_get_status(dev, priv); if (r < 0) goto out; r = ch341_control_out(dev, 0xa1, 0x501f, 0xd90a); if (r < 0) goto out; r = ch341_set_baudrate(dev, priv); if (r < 0) goto out; r = ch341_set_handshake(dev, priv->line_control); if (r < 0) goto out; /* expect 0x9f 0xee */ r = ch341_get_status(dev, priv); out: kfree(buffer); return r; }
static int ch341_set_handshake(struct usb_device *dev, struct ch341_private *priv) { dbg("ch341_set_handshake(%d,%d)", priv->dtr, priv->rts); return ch341_control_out(dev, 0xa4, ~((priv->dtr?1<<5:0)|(priv->rts?1<<6:0)), 0); }
static int ch341_set_baudrate(struct usb_device *dev, struct ch341_private *priv) { short a, b; int r; dbg("ch341_set_baudrate(%d)", priv->baud_rate); switch (priv->baud_rate) { case 2400: a = 0xd901; b = 0x0038; break; case 4800: a = 0x6402; b = 0x001f; break; case 9600: a = 0xb202; b = 0x0013; break; case 19200: a = 0xd902; b = 0x000d; break; case 38400: a = 0x6403; b = 0x000a; break; case 115200: a = 0xcc03; b = 0x0008; break; default: return -EINVAL; } r = ch341_control_out(dev, 0x9a, 0x1312, a); if (!r) r = ch341_control_out(dev, 0x9a, 0x0f2c, b); return r; }
static void ch341_break_ctl(struct tty_struct *tty, int break_state) { const uint16_t ch341_break_reg = CH341_REG_BREAK1 | ((uint16_t) CH341_REG_BREAK2 << 8); struct usb_serial_port *port = tty->driver_data; int r; uint16_t reg_contents; uint8_t *break_reg; dbg("%s()", __func__); break_reg = kmalloc(2, GFP_KERNEL); if (!break_reg) { dev_err(&port->dev, "%s - kmalloc failed\n", __func__); return; } r = ch341_control_in(port->serial->dev, CH341_REQ_READ_REG, ch341_break_reg, 0, break_reg, 2); if (r < 0) { dev_err(&port->dev, "%s - USB control read error (%d)\n", __func__, r); goto out; } dbg("%s - initial ch341 break register contents - reg1: %x, reg2: %x", __func__, break_reg[0], break_reg[1]); if (break_state != 0) { dbg("%s - Enter break state requested", __func__); break_reg[0] &= ~CH341_NBREAK_BITS_REG1; break_reg[1] &= ~CH341_NBREAK_BITS_REG2; } else { dbg("%s - Leave break state requested", __func__); break_reg[0] |= CH341_NBREAK_BITS_REG1; break_reg[1] |= CH341_NBREAK_BITS_REG2; } dbg("%s - New ch341 break register contents - reg1: %x, reg2: %x", __func__, break_reg[0], break_reg[1]); reg_contents = get_unaligned_le16(break_reg); r = ch341_control_out(port->serial->dev, CH341_REQ_WRITE_REG, ch341_break_reg, reg_contents); if (r < 0) dev_err(&port->dev, "%s - USB control write error (%d)\n", __func__, r); out: kfree(break_reg); }
static void ch341_break_ctl(struct tty_struct *tty, int break_state) { const uint16_t ch341_break_reg = CH341_REG_BREAK1 | ((uint16_t) CH341_REG_BREAK2 << 8); struct usb_serial_port *port = tty->driver_data; int r; uint16_t reg_contents; uint8_t break_reg[2]; dbg("%s()", __func__); r = ch341_control_in(port->serial->dev, CH341_REQ_READ_REG, ch341_break_reg, 0, break_reg, sizeof(break_reg)); if (r < 0) { printk(KERN_WARNING "%s: USB control read error whilst getting" " break register contents.\n", __FILE__); return; } dbg("%s - initial ch341 break register contents - reg1: %x, reg2: %x", __func__, break_reg[0], break_reg[1]); if (break_state != 0) { dbg("%s - Enter break state requested", __func__); break_reg[0] &= ~CH341_NBREAK_BITS_REG1; break_reg[1] &= ~CH341_NBREAK_BITS_REG2; } else { dbg("%s - Leave break state requested", __func__); break_reg[0] |= CH341_NBREAK_BITS_REG1; break_reg[1] |= CH341_NBREAK_BITS_REG2; } dbg("%s - New ch341 break register contents - reg1: %x, reg2: %x", __func__, break_reg[0], break_reg[1]); reg_contents = (uint16_t)break_reg[0] | ((uint16_t)break_reg[1] << 8); r = ch341_control_out(port->serial->dev, CH341_REQ_WRITE_REG, ch341_break_reg, reg_contents); if (r < 0) printk(KERN_WARNING "%s: USB control write error whilst setting" " break register contents.\n", __FILE__); }
static int ch341_set_handshake(struct usb_device *dev, u8 control) { return ch341_control_out(dev, 0xa4, ~control, 0); }
static int ch341_set_handshake(struct usb_device *dev, u8 control) { dbg("ch341_set_handshake(0x%02x)", control); return ch341_control_out(dev, 0xa4, ~control, 0); }