{
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
}
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(
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(
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,
}
break;
- case IOCTL_SETVID:
+ case CP210x_IOCTL_SETVID:
{
unsigned int vid;
if (!copy_from_user(&vid, (unsigned int __user *)arg,
}
break;
- case IOCTL_SETPID:
+ case CP210x_IOCTL_SETPID:
{
unsigned int pid;
if (!copy_from_user(&pid, (unsigned int __user *)arg,
}
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,
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,
}
break;
- case IOCTL_SETSERIAL:
+ case CP210x_IOCTL_SETSERIAL:
{
char usbstr[USBSTRLEN(CP210x_MAX_SERIAL_STRLEN)];
size_t len = cp210x_usbstr_from_user(usbstr, arg,
}
break;
- case IOCTL_SETDEVVER:
+ case CP210x_IOCTL_SETDEVVER:
{
unsigned int ver;
if (!copy_from_user(&ver, (unsigned int __user *)arg,
{
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
}
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(
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(
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,
}
break;
- case IOCTL_SETVID:
+ case CP210x_IOCTL_SETVID:
{
unsigned int vid;
if (!copy_from_user(&vid, (unsigned int __user *)arg,
}
break;
- case IOCTL_SETPID:
+ case CP210x_IOCTL_SETPID:
{
unsigned int pid;
if (!copy_from_user(&pid, (unsigned int __user *)arg,
}
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,
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,
}
break;
- case IOCTL_SETSERIAL:
+ case CP210x_IOCTL_SETSERIAL:
{
char usbstr[USBSTRLEN(CP210x_MAX_SERIAL_STRLEN)];
size_t len = cp210x_usbstr_from_user(usbstr, arg,
}
break;
- case IOCTL_SETDEVVER:
+ case CP210x_IOCTL_SETDEVVER:
{
unsigned int ver;
if (!copy_from_user(&ver, (unsigned int __user *)arg,
#if !defined(CP210X_H)
#define CP210X_H
+#if defined(__KERNEL__)
+#include <linux/sockios.h>
+#else
+#include <asm/types.h>
+#include <sys/ioctl.h>
+#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
* device.
*/
+#include <fcntl.h>
#include <netinet/in.h>
#include <stdint.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <fcntl.h>
+#include <unistd.h>
+#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);
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) {
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);
}
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);
}
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);
}
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);