Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70457786 authored by Aleksey Babahin's avatar Aleksey Babahin Committed by Greg Kroah-Hartman
Browse files

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: default avatarAleksey Babahin <tamerlan311@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 28a4b6a6
Loading
Loading
Loading
Loading
+53 −0
Original line number Diff line number Diff line
@@ -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;