diff options
author | Aleksey Babahin <tamerlan311@gmail.com> | 2012-03-19 16:46:33 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-10 16:30:37 -0400 |
commit | 704577861d5e7408db59e182d8dca42e5bc4d506 (patch) | |
tree | d25a4b14b2bac2ffdd92d8844690f64b8ef3af80 /drivers/usb/serial/metro-usb.c | |
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/metro-usb.c')
-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); | |||
56 | /* Input parameter constants. */ | 56 | /* Input parameter constants. */ |
57 | static bool debug; | 57 | static bool debug; |
58 | 58 | ||
59 | /* UNI-Directional mode commands for device configure */ | ||
60 | #define UNI_CMD_OPEN 0x80 | ||
61 | #define UNI_CMD_CLOSE 0xFF | ||
62 | |||
63 | inline int metrousb_is_unidirectional_mode(struct usb_serial_port *port) | ||
64 | { | ||
65 | __u16 product_id = le16_to_cpu( | ||
66 | port->serial->dev->descriptor.idProduct); | ||
67 | |||
68 | return product_id == FOCUS_PRODUCT_ID_UNI; | ||
69 | } | ||
70 | |||
71 | static int metrousb_send_unidirectional_cmd(u8 cmd, struct usb_serial_port *port) | ||
72 | { | ||
73 | int ret; | ||
74 | int actual_len; | ||
75 | u8 *buffer_cmd = NULL; | ||
76 | |||
77 | if (!metrousb_is_unidirectional_mode(port)) | ||
78 | return 0; | ||
79 | |||
80 | buffer_cmd = kzalloc(sizeof(cmd), GFP_KERNEL); | ||
81 | if (!buffer_cmd) | ||
82 | return -ENOMEM; | ||
83 | |||
84 | *buffer_cmd = cmd; | ||
85 | |||
86 | ret = usb_interrupt_msg(port->serial->dev, | ||
87 | usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress), | ||
88 | buffer_cmd, sizeof(cmd), | ||
89 | &actual_len, USB_CTRL_SET_TIMEOUT); | ||
90 | |||
91 | kfree(buffer_cmd); | ||
92 | |||
93 | if (ret < 0) | ||
94 | return ret; | ||
95 | else if (actual_len != sizeof(cmd)) | ||
96 | return -EIO; | ||
97 | return 0; | ||
98 | } | ||
99 | |||
59 | static void metrousb_read_int_callback(struct urb *urb) | 100 | static void metrousb_read_int_callback(struct urb *urb) |
60 | { | 101 | { |
61 | struct usb_serial_port *port = urb->context; | 102 | struct usb_serial_port *port = urb->context; |
@@ -154,6 +195,9 @@ static void metrousb_cleanup(struct usb_serial_port *port) | |||
154 | usb_unlink_urb(port->interrupt_in_urb); | 195 | usb_unlink_urb(port->interrupt_in_urb); |
155 | usb_kill_urb(port->interrupt_in_urb); | 196 | usb_kill_urb(port->interrupt_in_urb); |
156 | } | 197 | } |
198 | |||
199 | /* Send deactivate cmd to device */ | ||
200 | metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port); | ||
157 | } | 201 | } |
158 | } | 202 | } |
159 | 203 | ||
@@ -205,6 +249,15 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
205 | goto exit; | 249 | goto exit; |
206 | } | 250 | } |
207 | 251 | ||
252 | /* Send activate cmd to device */ | ||
253 | result = metrousb_send_unidirectional_cmd(UNI_CMD_OPEN, port); | ||
254 | if (result) { | ||
255 | dev_err(&port->dev, | ||
256 | "%s - failed to configure device for port number=%d, error code=%d\n", | ||
257 | __func__, port->number, result); | ||
258 | goto exit; | ||
259 | } | ||
260 | |||
208 | dev_dbg(&port->dev, "%s - port open\n", __func__); | 261 | dev_dbg(&port->dev, "%s - port open\n", __func__); |
209 | exit: | 262 | exit: |
210 | return result; | 263 | return result; |