--- /dev/null
+/**
+ * cpfactory.c
+ *
+ * Reset the cp2103 IO registers back to factory defaults.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* 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? */
+
+
+typedef struct {
+ uint16_t mode;
+ uint16_t lowPower;
+ uint16_t latch;
+} cp2103_port_state_t;
+
+typedef struct {
+ cp2103_port_state_t reset;
+ cp2103_port_state_t suspend;
+ uint8_t enhancedFxn;
+} cp2103_port_config_t;
+
+int cpConnect(char* device)
+{
+ int ret, ioval;
+ int fd = open(device, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "cannot open tty\n");
+ return -1;
+ }
+ printf("tty opened\n");
+ return fd;
+}
+
+void cpDisconnect(int fd)
+{
+ if (fd >= 0)
+ close(fd);
+}
+
+int main(int argc, char* argv[])
+{
+ int fd;
+ cp2103_port_config_t config;
+ cp2103_port_config_t saveConfig;
+ uint8_t saveGpio;
+ int ret;
+ int i;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s <tty>\n", argv[0]);
+ return 1;
+ }
+
+ /* open */
+ if ((fd = cpConnect(argv[1])) < 0)
+ return 1;
+
+ /* Read the current port configuration */
+ if ((ret = ioctl(fd, IOCTL_PORTCONFGET, &config))) {
+ fprintf(stderr, "portconfget ioctl failed %d\n", ret);
+ return 1;
+ }
+ printf("port config received\n");
+
+ /* Mode and latch bit to pin assignments. See AN223 from SiLabs:
+ * https://www.silabs.com/Support Documents/TechnicalDocs/an223.pdf
+ *
+ * 15 - /SUSPEND
+ * 14 - SUSPEND (maybe)
+ * 13 - unused (or SUSPEND)
+ * 12 - unused (or SUSPEND)
+ * 11 - GPIO_3
+ * 10 - GPIO_2
+ * 9 - GPIO_1
+ * 8 - GPIO_0
+ * 7 - /CTS
+ * 6 - /RTS
+ * 5 - RXD Note: set latch value to '1' for proper operation.
+ * 4 - TXD
+ * 3 - /DSR
+ * 2 - /DTR
+ * 1 - /DCD
+ * 0 - /RI
+ *
+ * Mode bit values:
+ * 1 - A value of one in a bit places the corresponding IO pin in push-
+ * pull output mode.
+ * 0 - A value of zero in a bit places the corresponding IO pin in open-
+ * drain output mode.
+ *
+ * Latch bit values:
+ * 1 - A value of one in a bit sets the corresponding IO pin's value to
+ * output high. If the mode is push-pull, the pin sources current
+ * from VIO. If the mode is open-drain, the pin driver is in high
+ * impedance.
+ * 0 - A value of zero in a bit sets the corresponding IO pin's value to
+ * output low. In either mode, push-pull or open-drain, the pin
+ * driver sinks current to ground.
+ *
+ * Enhanced function bits:
+ * 7 - maybe dynamic suspend for UART or GPIO
+ * 6 - maybe dynamic suspend for UART or GPIO
+ * 5 - maybe dynamic suspend for UART or GPIO
+ * 4 - Enable weak pull-ups
+ * 3 - unused
+ * 2 - /RS485_TX on GPIO_2
+ * 1 - /RXACT on GPIO_1
+ * 0 - /TXACT on GPIO_0
+ */
+ config.reset.mode = 0xf054;
+ config.suspend.mode = 0xf054;
+ config.reset.latch = 0x0fff; /* RXD must be 1 for some reason */
+ config.suspend.latch = 0x0fff; /* RXD must be 1 for some reason */
+ config.enhancedFxn = 0x00;
+
+ if ((ret = ioctl(fd, IOCTL_PORTCONFSET, &config))) {
+ fprintf(stderr, "portconfset ioctl failed %d\n", ret);
+ return 1;
+ }
+ printf("port config altered\n");
+
+ /* Reset the part */
+ if ((ret = ioctl(fd, IOCTL_DEVICERESET, 0))) {
+ fprintf(stderr, "device reset ioctl failed %d\n", ret);
+ return 1;
+ }
+ printf("device reset\n");
+
+ /* Disconnect then reconnect */
+ cpDisconnect(fd);
+ return 0;
+}