From adcc360e576188af96b2dd22be2bed75e151d769 Mon Sep 17 00:00:00 2001 From: "R. Steve McKown" Date: Mon, 17 May 2010 14:39:52 -0600 Subject: [PATCH] Several fixes. * cp210x.h serves kernel module and userspace apps * IOCTL_ -> CP210x_IOCTL_ to prevent collisions in userspace * Fix defect in cp210x_usbstr_from_user * cpmfg working with new changes --- src/cp210x.c | 45 +++++++++++++++------------- src/cp210x.c.karmic | 45 +++++++++++++++------------- src/cp210x.h | 35 +++++++++++++--------- src/examples/cpmfg.c | 70 ++++++++------------------------------------ 4 files changed, 81 insertions(+), 114 deletions(-) diff --git a/src/cp210x.c b/src/cp210x.c index b7de40f..1ec4b8e 100644 --- a/src/cp210x.c +++ b/src/cp210x.c @@ -252,19 +252,21 @@ static size_t cp210x_usbstr_from_user(char *kbuf, unsigned long ubuf, size_t kle { struct cp210x_buffer t; char* str; + size_t slen; if (!kbuf || !ubuf || !klen) return 0; if (copy_from_user(&t, (struct cp210x_buffer __user *)ubuf, sizeof(t))) return 0; - if (!t.buf || !t.len) + if (!t.buf || !t.len || USBSTRLEN(t.len) > klen) return 0; - if (t.len < klen) - klen = t.len; - str = kbuf + klen - t.len; - if (copy_from_user(kbuf + klen - t.len, (u8 __user *)t.buf, klen)) + slen = (klen - 2) / 2; + if (t.len < slen) + slen = t.len; + str = kbuf + klen - slen; + if (copy_from_user(str, (u8 __user *)t.buf, slen)) return 0; - return make_usb_string(kbuf, klen, str, t.len); + return make_usb_string(kbuf, klen, str, slen); } /* cp210x_has_setmfg @@ -695,7 +697,7 @@ static int cp210x_ioctl(struct usb_serial_port *port, struct file *file, } break; - case IOCTL_GPIOGET: + case CP210x_IOCTL_GPIOGET: if (cp210x_get_partnum(port) == CP210x_PART_CP2103) { u8 gpio = 0; if (!cp210x_gpioget(port, &gpio) && !copy_to_user( @@ -705,27 +707,28 @@ static int cp210x_ioctl(struct usb_serial_port *port, struct file *file, return -EFAULT; break; - case IOCTL_GPIOSET: + case CP210x_IOCTL_GPIOSET: if (cp210x_get_partnum(port) == CP210x_PART_CP2103 && !cp210x_gpioset(port, arg)) return 0; return -EFAULT; break; - case IOCTL_GPIOBIC: - case IOCTL_GPIOBIS: + case CP210x_IOCTL_GPIOBIC: + case CP210x_IOCTL_GPIOBIS: if (cp210x_get_partnum(port) == CP210x_PART_CP2103 && - !cp210x_gpiosetb(port, (cmd==IOCTL_GPIOBIC) ? 0 : arg, - (cmd==IOCTL_GPIOBIC) ? arg : 0)) + !cp210x_gpiosetb(port, + (cmd==CP210x_IOCTL_GPIOBIC) ? 0 : arg, + (cmd==CP210x_IOCTL_GPIOBIC) ? arg : 0)) return 0; return -EFAULT; break; - case IOCTL_DEVICERESET: + case CP210x_IOCTL_DEVICERESET: return cp210x_reset(port); break; - case IOCTL_PORTCONFGET: + case CP210x_IOCTL_PORTCONFGET: { struct cp210x_port_config config; if (!cp210x_portconfget(port, &config) && !copy_to_user( @@ -736,7 +739,7 @@ static int cp210x_ioctl(struct usb_serial_port *port, struct file *file, return -EFAULT; break; - case IOCTL_PORTCONFSET: + case CP210x_IOCTL_PORTCONFSET: { struct cp210x_port_config config; if (!copy_from_user(&config, (struct cp210x_port_config __user *)arg, @@ -747,7 +750,7 @@ static int cp210x_ioctl(struct usb_serial_port *port, struct file *file, } break; - case IOCTL_SETVID: + case CP210x_IOCTL_SETVID: { unsigned int vid; if (!copy_from_user(&vid, (unsigned int __user *)arg, @@ -758,7 +761,7 @@ static int cp210x_ioctl(struct usb_serial_port *port, struct file *file, } break; - case IOCTL_SETPID: + case CP210x_IOCTL_SETPID: { unsigned int pid; if (!copy_from_user(&pid, (unsigned int __user *)arg, @@ -769,7 +772,7 @@ static int cp210x_ioctl(struct usb_serial_port *port, struct file *file, } break; - case IOCTL_SETMFG: + case CP210x_IOCTL_SETMFG: if (cp210x_has_setmfg()) { char usbstr[USBSTRLEN(CP210x_MAX_MFG_STRLEN)]; size_t len = cp210x_usbstr_from_user(usbstr, arg, @@ -780,7 +783,7 @@ static int cp210x_ioctl(struct usb_serial_port *port, struct file *file, return -EFAULT; break; - case IOCTL_SETPRODUCT: + case CP210x_IOCTL_SETPRODUCT: { char usbstr[USBSTRLEN(CP210x_MAX_PRODUCT_STRLEN)]; size_t len = cp210x_usbstr_from_user(usbstr, arg, @@ -791,7 +794,7 @@ static int cp210x_ioctl(struct usb_serial_port *port, struct file *file, } break; - case IOCTL_SETSERIAL: + case CP210x_IOCTL_SETSERIAL: { char usbstr[USBSTRLEN(CP210x_MAX_SERIAL_STRLEN)]; size_t len = cp210x_usbstr_from_user(usbstr, arg, @@ -802,7 +805,7 @@ static int cp210x_ioctl(struct usb_serial_port *port, struct file *file, } break; - case IOCTL_SETDEVVER: + case CP210x_IOCTL_SETDEVVER: { unsigned int ver; if (!copy_from_user(&ver, (unsigned int __user *)arg, diff --git a/src/cp210x.c.karmic b/src/cp210x.c.karmic index 6188b8a..7076657 100644 --- a/src/cp210x.c.karmic +++ b/src/cp210x.c.karmic @@ -273,19 +273,21 @@ static size_t cp210x_usbstr_from_user(char *kbuf, unsigned long ubuf, size_t kle { struct cp210x_buffer t; char* str; + size_t slen; if (!kbuf || !ubuf || !klen) return 0; if (copy_from_user(&t, (struct cp210x_buffer __user *)ubuf, sizeof(t))) return 0; - if (!t.buf || !t.len) + if (!t.buf || !t.len || USBSTRLEN(t.len) > klen) return 0; - if (t.len < klen) - klen = t.len; - str = kbuf + klen - t.len; - if (copy_from_user(kbuf + klen - t.len, (u8 __user *)t.buf, klen)) + slen = (klen - 2) / 2; + if (t.len < slen) + slen = t.len; + str = kbuf + klen - slen; + if (copy_from_user(str, (u8 __user *)t.buf, slen)) return 0; - return make_usb_string(kbuf, klen, str, t.len); + return make_usb_string(kbuf, klen, str, slen); } /* cp210x_has_setmfg @@ -762,7 +764,7 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, } break; - case IOCTL_GPIOGET: + case CP210x_IOCTL_GPIOGET: if (cp210x_get_partnum(port) == CP210x_PART_CP2103) { u8 gpio = 0; if (!cp210x_gpioget(port, &gpio) && !copy_to_user( @@ -772,27 +774,28 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, return -EFAULT; break; - case IOCTL_GPIOSET: + case CP210x_IOCTL_GPIOSET: if (cp210x_get_partnum(port) == CP210x_PART_CP2103 && !cp210x_gpioset(port, arg)) return 0; return -EFAULT; break; - case IOCTL_GPIOBIC: - case IOCTL_GPIOBIS: + case CP210x_IOCTL_GPIOBIC: + case CP210x_IOCTL_GPIOBIS: if (cp210x_get_partnum(port) == CP210x_PART_CP2103 && - !cp210x_gpiosetb(port, (cmd==IOCTL_GPIOBIC) ? 0 : arg, - (cmd==IOCTL_GPIOBIC) ? arg : 0)) + !cp210x_gpiosetb(port, + (cmd==CP210x_IOCTL_GPIOBIC) ? 0 : arg, + (cmd==CP210x_IOCTL_GPIOBIC) ? arg : 0)) return 0; return -EFAULT; break; - case IOCTL_DEVICERESET: + case CP210x_IOCTL_DEVICERESET: return cp210x_reset(port); break; - case IOCTL_PORTCONFGET: + case CP210x_IOCTL_PORTCONFGET: { struct cp210x_port_config config; if (!cp210x_portconfget(port, &config) && !copy_to_user( @@ -803,7 +806,7 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, return -EFAULT; break; - case IOCTL_PORTCONFSET: + case CP210x_IOCTL_PORTCONFSET: { struct cp210x_port_config config; if (!copy_from_user(&config, (struct cp210x_port_config __user *)arg, @@ -814,7 +817,7 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, } break; - case IOCTL_SETVID: + case CP210x_IOCTL_SETVID: { unsigned int vid; if (!copy_from_user(&vid, (unsigned int __user *)arg, @@ -825,7 +828,7 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, } break; - case IOCTL_SETPID: + case CP210x_IOCTL_SETPID: { unsigned int pid; if (!copy_from_user(&pid, (unsigned int __user *)arg, @@ -836,7 +839,7 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, } break; - case IOCTL_SETMFG: + case CP210x_IOCTL_SETMFG: if (cp210x_has_setmfg()) { char usbstr[USBSTRLEN(CP210x_MAX_MFG_STRLEN)]; size_t len = cp210x_usbstr_from_user(usbstr, arg, @@ -847,7 +850,7 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, return -EFAULT; break; - case IOCTL_SETPRODUCT: + case CP210x_IOCTL_SETPRODUCT: { char usbstr[USBSTRLEN(CP210x_MAX_PRODUCT_STRLEN)]; size_t len = cp210x_usbstr_from_user(usbstr, arg, @@ -858,7 +861,7 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, } break; - case IOCTL_SETSERIAL: + case CP210x_IOCTL_SETSERIAL: { char usbstr[USBSTRLEN(CP210x_MAX_SERIAL_STRLEN)]; size_t len = cp210x_usbstr_from_user(usbstr, arg, @@ -869,7 +872,7 @@ static int cp210x_ioctl(struct tty_struct *tty, struct file *file, } break; - case IOCTL_SETDEVVER: + case CP210x_IOCTL_SETDEVVER: { unsigned int ver; if (!copy_from_user(&ver, (unsigned int __user *)arg, diff --git a/src/cp210x.h b/src/cp210x.h index 2de79d3..f3c96a8 100644 --- a/src/cp210x.h +++ b/src/cp210x.h @@ -14,29 +14,36 @@ #if !defined(CP210X_H) #define CP210X_H +#if defined(__KERNEL__) +#include +#else +#include +#include +#endif + /* CP2103 GPIO ioctls */ -#define IOCTL_GPIOGET 0x8000 /* Get gpio bits */ -#define IOCTL_GPIOSET 0x8001 /* Set gpio bits */ -#define IOCTL_GPIOBIC 0x8002 /* Clear specific gpio bit(s) */ -#define IOCTL_GPIOBIS 0x8003 /* Set specific gpio bit(s) */ +#define CP210x_IOCTL_GPIOGET (SIOCDEVPRIVATE + 0) /* Get gpio bits */ +#define CP210x_IOCTL_GPIOSET (SIOCDEVPRIVATE + 1) /* Set gpio bits */ +#define CP210x_IOCTL_GPIOBIC (SIOCDEVPRIVATE + 2) /* Clear specific gpio bit(s) */ +#define CP210x_IOCTL_GPIOBIS (SIOCDEVPRIVATE + 3) /* Set specific gpio bit(s) */ /* CP210x ioctls principally used during initial device configuration */ -#define IOCTL_DEVICERESET 0x8004 /* Reset the cp210x */ -#define IOCTL_PORTCONFGET 0x8005 /* Get port configuration */ -#define IOCTL_PORTCONFSET 0x8006 /* Set port configuration */ -#define IOCTL_SETVID 0x8007 /* Set vendor id */ -#define IOCTL_SETPID 0x8008 /* Set product id */ -#define IOCTL_SETMFG 0x8009 /* Set manufacturer string */ -#define IOCTL_SETPRODUCT 0x800a /* Set product string */ -#define IOCTL_SETSERIAL 0x800b /* Set serial number string */ -#define IOCTL_SETDEVVER 0x800c /* Set device version id */ +#define CP210x_IOCTL_DEVICERESET (SIOCDEVPRIVATE + 4) /* Reset the cp210x */ +#define CP210x_IOCTL_PORTCONFGET (SIOCDEVPRIVATE + 5) /* Get port configuration */ +#define CP210x_IOCTL_PORTCONFSET (SIOCDEVPRIVATE + 6) /* Set port configuration */ +#define CP210x_IOCTL_SETVID (SIOCDEVPRIVATE + 7) /* Set vendor id */ +#define CP210x_IOCTL_SETPID (SIOCDEVPRIVATE + 8) /* Set product id */ +#define CP210x_IOCTL_SETMFG (SIOCDEVPRIVATE + 9) /* Set manufacturer string */ +#define CP210x_IOCTL_SETPRODUCT (SIOCDEVPRIVATE + 10) /* Set product string */ +#define CP210x_IOCTL_SETSERIAL (SIOCDEVPRIVATE + 11) /* Set serial number string */ +#define CP210x_IOCTL_SETDEVVER (SIOCDEVPRIVATE + 12) /* Set device version id */ /* CP2103 GPIO bit positions */ #define GPIO_0 0x01 #define GPIO_1 0x02 #define GPIO_2 0x04 #define GPIO_3 0x08 -#define GPIO_MASK (GPIO_0|GPIO_1|GPIO_2|GPIO_3) +#define GPIO_MASK (GPIO_3|GPIO_2|GPIO_1|GPIO_0) /* USB descriptor sizes */ #define CP210x_MAX_MFG_STRLEN 255 diff --git a/src/examples/cpmfg.c b/src/examples/cpmfg.c index a8a94d8..f4c5401 100644 --- a/src/examples/cpmfg.c +++ b/src/examples/cpmfg.c @@ -5,68 +5,22 @@ * device. */ +#include #include #include #include +#include #include #include #include -#include +#include +#include "../cp210x.h" #define VID 0x10c4 #define PID 0xea60 -/* CP2103 ioctls */ -#define IOCTL_GPIOGET 0x8000 /* Get gpio bits */ -#define IOCTL_GPIOSET 0x8001 /* Set gpio bits */ -#define IOCTL_GPIOBIC 0x8002 /* Clear specific gpio bit(s) */ -#define IOCTL_GPIOBIS 0x8003 /* Set specific gpio bit(s) */ - -/* CP210x ioctls principally used during initial device configuration */ -#define IOCTL_DEVICERESET 0x8004 /* Reset the cp210x */ -#define IOCTL_PORTCONFGET 0x8005 /* Get port configuration */ -#define IOCTL_PORTCONFSET 0x8006 /* Set port configuration */ -#define IOCTL_SETVID 0x8007 /* Set vendor id */ -#define IOCTL_SETPID 0x8008 /* Set product id */ -#define IOCTL_SETMFG 0x8009 /* Set manufacturer string */ -#define IOCTL_SETPRODUCT 0x800a /* Set product string */ -#define IOCTL_SETSERIAL 0x800b /* Set serial number string */ -#define IOCTL_SETDEVVER 0x800c /* set device version id */ -/* FIXME: where is IOCTL_SETMFG? */ - -/* CP2103 GPIO */ -#define GPIO_0 0x01 -#define GPIO_1 0x02 -#define GPIO_2 0x04 -#define GPIO_3 0x08 -#define GPIO_MASK (GPIO_0|GPIO_1|GPIO_2|GPIO_3) - -/* Port config definitions */ -typedef struct { - uint16_t mode; /* Push-pull = 1, Open-drain = 0 */ - uint16_t lowPower; - uint16_t latch; /* Logic high = 1, Logic low = 0 */ -} cp2101_port_state_t; - -typedef struct { - cp2101_port_state_t reset; - cp2101_port_state_t suspend; - uint8_t enhancedFxn; -} cp2101_port_config_t; - -#define PORT_CONFIG_LEN 13 /* Because sizeof() will pad to full words */ - -/* Used to pass variable sized buffers between user and kernel space (ioctls) */ -typedef struct { - char* buf; - size_t len; -} cp210x_buffer_t; - -void exit(int); - int cpConnect(char* device) { - int ret, ioval; int fd = open(device, O_RDWR); if (fd < 0) { fprintf(stderr, "cannot open %s\n", device); @@ -85,7 +39,7 @@ void cpDisconnect(int fd) void cpSetStr(int fd, unsigned int ioctlno, char* string, size_t len) { int ret; - cp210x_buffer_t buf = { buf: string, len: len }; + struct cp210x_buffer buf = { buf: (unsigned char *)string, len: len }; ret = ioctl(fd, ioctlno, &buf); if (ret) { @@ -98,10 +52,10 @@ void cpSetStr(int fd, unsigned int ioctlno, char* string, size_t len) void cpSetPortConf(int fd, int nopullups) { int ret; - cp2101_port_config_t config; + struct cp210x_port_config config; /* Read the current port configuration */ - if ((ret = ioctl(fd, IOCTL_PORTCONFGET, &config))) { + if ((ret = ioctl(fd, CP210x_IOCTL_PORTCONFGET, &config))) { fprintf(stderr, "portconfget ioctl failed %d\n", ret); exit(1); } @@ -122,7 +76,7 @@ void cpSetPortConf(int fd, int nopullups) if (nopullups) config.enhancedFxn &= ~0x10; - if ((ret = ioctl(fd, IOCTL_PORTCONFSET, &config))) { + if ((ret = ioctl(fd, CP210x_IOCTL_PORTCONFSET, &config))) { fprintf(stderr, "portconfset ioctl failed %d\n", ret); exit(1); } @@ -133,7 +87,7 @@ void cpReset(int fd) int ret; /* Reset the part */ - if ((ret = ioctl(fd, IOCTL_DEVICERESET, 0))) { + if ((ret = ioctl(fd, CP210x_IOCTL_DEVICERESET, 0))) { fprintf(stderr, "device reset ioctl %d\n", ret); exit(1); } @@ -175,10 +129,10 @@ int main(int argc, char* argv[]) strcpy(newsn, argv[nopullups + 4]); fd = cpConnect(argv[nopullups + 1]); /* SiLabs doesn't allow set of mfg string on cp210x. - * cpSetStr(fd, IOCTL_SETMFG, newmfg, strlen(newmfg)); + * cpSetStr(fd, CP210x_IOCTL_SETMFG, newmfg, strlen(newmfg)); */ - cpSetStr(fd, IOCTL_SETPRODUCT, newprod, strlen(newprod)); - cpSetStr(fd, IOCTL_SETSERIAL, newsn, strlen(newsn)); + cpSetStr(fd, CP210x_IOCTL_SETPRODUCT, newprod, strlen(newprod)); + cpSetStr(fd, CP210x_IOCTL_SETSERIAL, newsn, strlen(newsn)); cpSetPortConf(fd, nopullups); cpReset(fd); cpDisconnect(fd); -- 2.39.2