From: Peter Henn Date: Mon, 23 Apr 2018 22:58:44 +0000 (+0000) Subject: First support PL2303-HXD GPIO 2 & 3 X-Git-Url: http://git.linex4red.de/pub/pl2303-ft232-gpio.git/commitdiff_plain?ds=inline First support PL2303-HXD GPIO 2 & 3 - extend pl2303 to support GPIO 2 & 3 - adjust TODO file --- diff --git a/TODO b/TODO index cf3e410..b1a8717 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,5 @@ TODO: -- add support for GPIO2 and GPIO3 of PL2303, see also - https://patchwork.kernel.org/patch/4815351/ +- add GPIO number range check, depending on device - add debug code for testing FT232R, especially reading GPIO configuration - test mixed input and output with FT232R and PL2303 - ... diff --git a/pl2303.c b/pl2303.c index fb17c19..d1ddcc6 100644 --- a/pl2303.c +++ b/pl2303.c @@ -27,6 +27,12 @@ #define VENDOR_WRITE_REQUEST_TYPE 0x40 #define VENDOR_WRITE_REQUEST 0x01 +#define GPIO_01_RD_CTRL 0x0081 +#define GPIO_01_WR_CTRL 0x0001 +#define GPIO_23_DIR_RD_CTRL 0x8c8c +#define GPIO_23_DIR_WR_CTRL 0x0c0c +#define GPIO_23_VAL_RD_CTRL 0x8d8d +#define GPIO_23_VAL_WR_CTRL 0x0d0d int get_device_vid() { @@ -39,83 +45,109 @@ int get_device_pid() } /* Get current GPIO register from PL2303 */ -char gpio_read_reg(libusb_device_handle *h) +char gpio_read_reg(libusb_device_handle *h, unsigned short ctrl) { char buf; int bytes = libusb_control_transfer( h, // handle obtained with usb_open() VENDOR_READ_REQUEST_TYPE, // bRequestType VENDOR_READ_REQUEST, // bRequest - 0x0081, // wValue - 0, // wIndex - &buf, // pointer to destination buffer - 1, // wLength + ctrl, // wValue + 0, // wIndex + &buf, // pointer to destination buffer + 1, // wLength 1000 ); handle_error(bytes); return buf; } -void gpio_write_reg(libusb_device_handle *h, unsigned char reg) +void gpio_write_reg(libusb_device_handle *h, unsigned short ctrl, unsigned char reg) { int bytes = libusb_control_transfer( h, // handle obtained with usb_open() VENDOR_WRITE_REQUEST_TYPE, // bRequestType VENDOR_WRITE_REQUEST, // bRequest - 1, // wValue - reg, // wIndex + ctrl, // wValue + reg, // wIndex 0, // pointer to destination buffer - 0, // wLength + 0, // wLength 1000 ); handle_error(bytes); - } -int gpio_dir_shift(int gpio) { - if (gpio == 0) - return 4; - if (gpio == 1) - return 5; - return 4; /* default to 0 */ +int gpio_dir_mask(int gpio) { + switch (gpio) { + case 0: return 0x10; + case 1: return 0x20; + case 2: return 0x03; + case 3: return 0x0c; + } + return 0x10; /* default to gpio 0 */ } int gpio_val_shift(int gpio) { - if (gpio == 0) - return 6; - if (gpio == 1) - return 7; - return 6; /* default to 0 */ + switch (gpio) { + case 0: return 6; + case 1: return 7; + case 2: return 0; + case 3: return 1; + } + return 6; /* default to gpio 0 */ } void gpio_out(libusb_device_handle *h, int gpio, int value) { - int shift_dir = gpio_dir_shift(gpio); int shift_val = gpio_val_shift(gpio); - unsigned char reg = gpio_read_reg(h); - reg |= (1 << shift_dir); - reg &= ~(1 << shift_val); - reg |= (value << shift_val); - gpio_write_reg(h, reg); + unsigned char reg; + + if (2 > gpio) { + reg = gpio_read_reg(h, GPIO_01_RD_CTRL); + reg |= gpio_dir_mask(gpio); /* set output direction */ + reg &= ~(1 << shift_val); /* reset gpio */ + reg |= (value << shift_val); /* set gpio to value */ + gpio_write_reg(h, GPIO_01_WR_CTRL, reg); + } else { + reg = gpio_read_reg(h, GPIO_23_VAL_RD_CTRL); + reg &= ~(1 << shift_val); /* reset gpio */ + reg |= (value << shift_val); /* set gpio to value */ + gpio_write_reg(h, GPIO_23_VAL_WR_CTRL, reg); + + reg = gpio_read_reg(h, GPIO_23_DIR_RD_CTRL); + reg |= gpio_dir_mask(gpio); /* set output direction */ + gpio_write_reg(h, GPIO_23_DIR_WR_CTRL, reg); + } } void gpio_in(libusb_device_handle *h, int gpio, int pullup) { - int shift_dir = gpio_dir_shift(gpio); int shift_val = gpio_val_shift(gpio); - - unsigned char reg = gpio_read_reg(h); - reg &= ~(1 << shift_dir); - reg &= ~(1 << shift_val); - reg |= (pullup << shift_val); - gpio_write_reg(h, reg); + unsigned char reg; + + if (2 > gpio) { + reg = gpio_read_reg(h, GPIO_01_RD_CTRL); + reg &= ~(gpio_dir_mask(gpio)); /* set input direction */ + reg &= ~(1 << shift_val); /* reset gpio value */ + reg |= (pullup << shift_val); /* pullup gpio value */ + gpio_write_reg(h, GPIO_01_WR_CTRL, reg); + } else { + reg = gpio_read_reg(h, GPIO_23_DIR_RD_CTRL); + reg &= ~(gpio_dir_mask(gpio)); /* set input direction */ + gpio_write_reg(h, GPIO_23_DIR_WR_CTRL, reg); + + reg = gpio_read_reg(h, GPIO_23_VAL_RD_CTRL); + reg &= ~(1 << shift_val); /* reset gpio value */ + reg |= (pullup << shift_val); /* pullup gpio value */ + gpio_write_reg(h, GPIO_23_VAL_WR_CTRL, reg); + } } int gpio_read(libusb_device_handle *h, int gpio) { - unsigned char r = gpio_read_reg(h); + unsigned char r = gpio_read_reg(h, (2 > gpio) ? GPIO_01_RD_CTRL : GPIO_23_VAL_RD_CTRL); int shift = gpio_val_shift(gpio); - return (r & (1<