diff options
author | Aleksey Babahin <tamerlan311@gmail.com> | 2012-03-20 00:46:33 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-10 13:30:37 -0700 |
commit | 704577861d5e7408db59e182d8dca42e5bc4d506 (patch) | |
tree | d25a4b14b2bac2ffdd92d8844690f64b8ef3af80 /drivers/usb/serial | |
parent | 28a4b6a690dfc000e86c8e02a1e1c1a9832252ec (diff) |
USB: serial: metro-usb: get data from device in Uni-Directional mode.
We should send special control command to tell device start or stop
transmitting a data.
In Bi-Directional mode that cmd`s are not required.
Signed-off-by: Aleksey Babahin <tamerlan311@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/metro-usb.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 92b6f85ab4b9..2df22176515b 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -56,6 +56,47 @@ MODULE_DEVICE_TABLE(usb, id_table); /* Input parameter constants. */ static bool debug; +/* UNI-Directional mode commands for device configure */ +#define UNI_CMD_OPEN 0x80 +#define UNI_CMD_CLOSE 0xFF + +inline int metrousb_is_unidirectional_mode(struct usb_serial_port *port) +{ + __u16 product_id = le16_to_cpu( + port->serial->dev->descriptor.idProduct); + + return product_id == FOCUS_PRODUCT_ID_UNI; +} + +static int metrousb_send_unidirectional_cmd(u8 cmd, struct usb_serial_port *port) +{ + int ret; + int actual_len; + u8 *buffer_cmd = NULL; + + if (!metrousb_is_unidirectional_mode(port)) + return 0; + + buffer_cmd = kzalloc(sizeof(cmd), GFP_KERNEL); + if (!buffer_cmd) + return -ENOMEM; + + *buffer_cmd = cmd; + + ret = usb_interrupt_msg(port->serial->dev, + usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress), + buffer_cmd, sizeof(cmd), + &actual_len, USB_CTRL_SET_TIMEOUT); + + kfree(buffer_cmd); + + if (ret < 0) + return ret; + else if (actual_len != sizeof(cmd)) + return -EIO; + return 0; +} + static void metrousb_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; @@ -154,6 +195,9 @@ static void metrousb_cleanup(struct usb_serial_port *port) usb_unlink_urb(port->interrupt_in_urb); usb_kill_urb(port->interrupt_in_urb); } + + /* Send deactivate cmd to device */ + metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port); } } @@ -205,6 +249,15 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) goto exit; } + /* Send activate cmd to device */ + result = metrousb_send_unidirectional_cmd(UNI_CMD_OPEN, port); + if (result) { + dev_err(&port->dev, + "%s - failed to configure device for port number=%d, error code=%d\n", + __func__, port->number, result); + goto exit; + } + dev_dbg(&port->dev, "%s - port open\n", __func__); exit: return result; |