Commit 871f1f07 authored by Oleg Dzhimiev's avatar Oleg Dzhimiev

updated drvier for kernels 4.9+ where usb_control_msg cannot be fed with...

updated drvier for kernels 4.9+ where usb_control_msg cannot be fed with statically allocated buffer
parent f71e5c8d
......@@ -3,8 +3,6 @@
CP210X_NAME="cp210x.c"
CP210X_ADDRESS="https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/plain/drivers/usb/serial/cp210x.c?id=refs/tags/v"
PATCH_NAME="cp210x.patch"
LINUX_KERNEL_VERSION=$(uname -r | cut -f1 -d"-")
LKV_P1=$(echo $LINUX_KERNEL_VERSION | cut -f1 -d".")
LKV_P2=$(echo $LINUX_KERNEL_VERSION | cut -f2 -d".")
......@@ -16,6 +14,14 @@ else
CP210X_VERSION=$(echo "$LKV_P1.$LKV_P2.$LKV_P3")
fi
if [ $LKV_P1 -le 4 ] && [ $LKV_P2 -lt 9 ]; then
echo "Selecting patch for kernel <4.9.0!"
PATCH_NAME="cp210x.patch"
else
echo "Selecting patch for kernel 4.9+!"
PATCH_NAME="cp210x_kernel_4.9.x+.patch"
fi
#uncomment if patch doesn't work
#CP210X_VERSION="3.8.0"
......
--- a/cp210x.c 2019-07-18 13:10:09.000000000 -0600
+++ b/cp210x.c 2019-07-18 13:06:25.000000000 -0600
@@ -31,6 +31,8 @@
*/
static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *);
static void cp210x_close(struct usb_serial_port *);
+static int cp210x_ioctl(struct tty_struct *tty,
+ unsigned int cmd, unsigned long arg);
static void cp210x_get_termios(struct tty_struct *, struct usb_serial_port *);
static void cp210x_get_termios_port(struct usb_serial_port *port,
tcflag_t *cflagp, unsigned int *baudp);
@@ -245,6 +247,7 @@
.bulk_out_size = 256,
.open = cp210x_open,
.close = cp210x_close,
+ .ioctl = cp210x_ioctl,
.break_ctl = cp210x_break_ctl,
.set_termios = cp210x_set_termios,
.tx_empty = cp210x_tx_empty,
@@ -262,6 +265,10 @@
&cp210x_device, NULL
};
+/* IOCTLs */
+#define IOCTL_GPIOGET 0x8000
+#define IOCTL_GPIOSET 0x8001
+
/* Config request types */
#define REQTYPE_HOST_TO_INTERFACE 0x41
#define REQTYPE_INTERFACE_TO_HOST 0xc1
@@ -867,6 +874,66 @@
return !count;
}
+// Elphel
+static int cp210x_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
+{
+ struct usb_serial_port *port = tty->driver_data;
+ struct usb_serial *serial = port->serial;
+
+ int result = 0;
+ unsigned int latch_setting = 0;
+ int bufsize = 1;
+
+ // usb_control_msg used to be able to read to statically allocated buffer
+ // now it does not, have to create this buffer
+ // https://stackoverflow.com/questions/52685669/usb-control-msg-returns-eagain
+ void *dmabuf;
+
+ dmabuf = kmalloc(bufsize, GFP_KERNEL);
+ if (!dmabuf)
+ return -ENOMEM;
+
+ switch (cmd) {
+ case IOCTL_GPIOGET:
+ result = usb_control_msg(
+ serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ CP210X_VENDOR_SPECIFIC,
+ REQTYPE_DEVICE_TO_HOST,
+ CP210X_READ_LATCH,
+ cp210x_interface_num(serial),
+ dmabuf, bufsize,
+ USB_CTRL_GET_TIMEOUT);
+ if (result != bufsize)
+ return -EPROTO;
+ memcpy(&latch_setting, dmabuf, bufsize);
+ *(unsigned long *)arg = (unsigned long)latch_setting;
+ return 0;
+ break;
+ case IOCTL_GPIOSET:
+ latch_setting = *(unsigned int *)arg & 0x000000FF;
+ //why [23:16] bits are taken for value is unknown
+ latch_setting |= (*(unsigned int *)arg & 0x00FF0000) >> 8;
+
+ result = usb_control_msg(
+ serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ CP210X_VENDOR_SPECIFIC,
+ REQTYPE_HOST_TO_DEVICE,
+ CP210X_WRITE_LATCH,
+ latch_setting,
+ NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+ if (result != 0)
+ return -EPROTO;
+ return 0;
+ break;
+ default:
+ break;
+ }
+ return -ENOIOCTLCMD;
+}
+
/*
* cp210x_get_termios
* Reads the baud rate, data bits, parity, stop bits and flow control mode
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment