diff options
Diffstat (limited to 'drivers/usb/serial/omninet.c')
-rw-r--r-- | drivers/usb/serial/omninet.c | 130 |
1 files changed, 27 insertions, 103 deletions
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index dd706953b466..efcd7feed6f4 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -1,6 +1,8 @@ /* * USB ZyXEL omni.net LCD PLUS driver * + * Copyright (C) 2013,2017 Johan Hovold <johan@kernel.org> + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 as published by the Free Software Foundation. @@ -32,12 +34,10 @@ /* function prototypes */ static void omninet_process_read_urb(struct urb *urb); -static void omninet_write_bulk_callback(struct urb *urb); -static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, - const unsigned char *buf, int count); -static int omninet_write_room(struct tty_struct *tty); -static void omninet_disconnect(struct usb_serial *serial); -static int omninet_attach(struct usb_serial *serial); +static int omninet_prepare_write_buffer(struct usb_serial_port *port, + void *buf, size_t count); +static int omninet_calc_num_ports(struct usb_serial *serial, + struct usb_serial_endpoints *epds); static int omninet_port_probe(struct usb_serial_port *port); static int omninet_port_remove(struct usb_serial_port *port); @@ -55,15 +55,12 @@ static struct usb_serial_driver zyxel_omninet_device = { }, .description = "ZyXEL - omni.net lcd plus usb", .id_table = id_table, - .num_ports = 1, - .attach = omninet_attach, + .num_bulk_out = 2, + .calc_num_ports = omninet_calc_num_ports, .port_probe = omninet_port_probe, .port_remove = omninet_port_remove, - .write = omninet_write, - .write_room = omninet_write_room, - .write_bulk_callback = omninet_write_bulk_callback, .process_read_urb = omninet_process_read_urb, - .disconnect = omninet_disconnect, + .prepare_write_buffer = omninet_prepare_write_buffer, }; static struct usb_serial_driver * const serial_drivers[] = { @@ -104,15 +101,14 @@ struct omninet_data { __u8 od_outseq; /* Sequence number for bulk_out URBs */ }; -static int omninet_attach(struct usb_serial *serial) +static int omninet_calc_num_ports(struct usb_serial *serial, + struct usb_serial_endpoints *epds) { - /* The second bulk-out endpoint is used for writing. */ - if (serial->num_bulk_out < 2) { - dev_err(&serial->interface->dev, "missing endpoints\n"); - return -ENODEV; - } + /* We need only the second bulk-out for our single-port device. */ + epds->bulk_out[0] = epds->bulk_out[1]; + epds->num_bulk_out = 1; - return 0; + return 1; } static int omninet_port_probe(struct usb_serial_port *port) @@ -159,96 +155,24 @@ static void omninet_process_read_urb(struct urb *urb) tty_flip_buffer_push(&port->port); } -static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, - const unsigned char *buf, int count) +static int omninet_prepare_write_buffer(struct usb_serial_port *port, + void *buf, size_t count) { - struct usb_serial *serial = port->serial; - struct usb_serial_port *wport = serial->port[1]; - struct omninet_data *od = usb_get_serial_port_data(port); - struct omninet_header *header = (struct omninet_header *) - wport->write_urb->transfer_buffer; - - int result; - - if (count == 0) { - dev_dbg(&port->dev, "%s - write request of 0 bytes\n", __func__); - return 0; - } - - if (!test_and_clear_bit(0, &port->write_urbs_free)) { - dev_dbg(&port->dev, "%s - already writing\n", __func__); - return 0; - } - - count = (count > OMNINET_PAYLOADSIZE) ? OMNINET_PAYLOADSIZE : count; - - memcpy(wport->write_urb->transfer_buffer + OMNINET_HEADERLEN, - buf, count); - - usb_serial_debug_data(&port->dev, __func__, count, - wport->write_urb->transfer_buffer); - - header->oh_seq = od->od_outseq++; - header->oh_len = count; - header->oh_xxx = 0x03; - header->oh_pad = 0x00; - - /* send the data out the bulk port, always 64 bytes */ - wport->write_urb->transfer_buffer_length = OMNINET_BULKOUTSIZE; - - result = usb_submit_urb(wport->write_urb, GFP_ATOMIC); - if (result) { - set_bit(0, &wport->write_urbs_free); - dev_err_console(port, - "%s - failed submitting write urb, error %d\n", - __func__, result); - } else - result = count; - - return result; -} + struct omninet_header *header = buf; + count = min_t(size_t, count, OMNINET_PAYLOADSIZE); -static int omninet_write_room(struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - struct usb_serial *serial = port->serial; - struct usb_serial_port *wport = serial->port[1]; - - int room = 0; /* Default: no room */ - - if (test_bit(0, &wport->write_urbs_free)) - room = wport->bulk_out_size - OMNINET_HEADERLEN; - - dev_dbg(&port->dev, "%s - returns %d\n", __func__, room); - - return room; -} - -static void omninet_write_bulk_callback(struct urb *urb) -{ -/* struct omninet_header *header = (struct omninet_header *) - urb->transfer_buffer; */ - struct usb_serial_port *port = urb->context; - int status = urb->status; - - set_bit(0, &port->write_urbs_free); - if (status) { - dev_dbg(&port->dev, "%s - nonzero write bulk status received: %d\n", - __func__, status); - return; - } + count = kfifo_out_locked(&port->write_fifo, buf + OMNINET_HEADERLEN, + count, &port->lock); - usb_serial_port_softint(port); -} - - -static void omninet_disconnect(struct usb_serial *serial) -{ - struct usb_serial_port *wport = serial->port[1]; + header->oh_seq = od->od_outseq++; + header->oh_len = count; + header->oh_xxx = 0x03; + header->oh_pad = 0x00; - usb_kill_urb(wport->write_urb); + /* always 64 bytes */ + return OMNINET_BULKOUTSIZE; } module_usb_serial_driver(serial_drivers, id_table); |