aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/metro-usb.c
diff options
context:
space:
mode:
authorAleksey Babahin <tamerlan311@gmail.com>2012-03-19 16:46:33 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-04-10 16:30:37 -0400
commit704577861d5e7408db59e182d8dca42e5bc4d506 (patch)
treed25a4b14b2bac2ffdd92d8844690f64b8ef3af80 /drivers/usb/serial/metro-usb.c
parent28a4b6a690dfc000e86c8e02a1e1c1a9832252ec (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.c53
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. */
57static bool debug; 57static 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
63inline 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
71static 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
59static void metrousb_read_int_callback(struct urb *urb) 100static 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__);
209exit: 262exit:
210 return result; 263 return result;