From: Andrew 'Necromant' Andrianov Date: Tue, 4 Nov 2014 17:35:47 +0000 (+0300) Subject: Initial commit X-Git-Tag: v0.1~25 X-Git-Url: http://git.linex4red.de/pub/pl2303-ft232-gpio.git/commitdiff_plain/5d1beba18b908012a40fa82bc61697c1a38e8239 Initial commit Signed-off-by: Andrew 'Necromant' Andrianov --- 5d1beba18b908012a40fa82bc61697c1a38e8239 diff --git a/10-pl2303userspace.rules b/10-pl2303userspace.rules new file mode 100755 index 0000000..fe6af93 --- /dev/null +++ b/10-pl2303userspace.rules @@ -0,0 +1,5 @@ +# PL2303 rules to allow userspace access to the dongle +# Copy this file to /etc/udev/rules.d, reload udev rules and replug + +SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTR{idVendor}=="67b", ATTR{idProduct}=="2303", GROUP="users", MODE="0666" + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c7f3d1f --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +CFLAGS = $(shell pkg-config --cflags libusb-1.0) +LDFLAGS = $(shell pkg-config --libs libusb-1.0) + +PREFIX?=/usr/local + +all: pl2303gpio + +OBJS=usb.c main.c +pl2303gpio: $(OBJS) + $(CC) $(CFLAGS) -Wall -Werror -I"../include" -o $(@) $(^) $(LDFLAGS) -lusb + +clean: + -rm pl2303gpio + +install: pl2303gpio + cp pl2303gpio $(PREFIX)/bin + cp 10-pl2303userspace.rules /etc/udev/rules.d \ No newline at end of file diff --git a/main.c b/main.c new file mode 100644 index 0000000..1a84c2d --- /dev/null +++ b/main.c @@ -0,0 +1,228 @@ +#include +#include +/* According to POSIX.1-2001 */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define _GNU_SOURCE +#include + + +#define I_VENDOR_NUM 0x67b +#define I_PRODUCT_NUM 0x2303 + + +#define VENDOR_READ_REQUEST_TYPE 0xc0 +#define VENDOR_READ_REQUEST 0x01 + +#define VENDOR_WRITE_REQUEST_TYPE 0x40 +#define VENDOR_WRITE_REQUEST 0x01 + + +void handle_error(int ret) +{ + if (ret<0) { + perror("Failed to write to PL2303 device"); + fprintf(stderr, "Have you installed the correct udev rules?\n"); + exit(1); + } +} + + +/* Get current GPIO register from PL2303 */ +char gpio_read_reg(usb_dev_handle *h) +{ + char buf; + int bytes = usb_control_msg( + 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 + 100 + ); + handle_error(bytes); + return buf; +} + +void gpio_write_reg(usb_dev_handle *h, unsigned char reg) +{ + int bytes = usb_control_msg( + h, // handle obtained with usb_open() + VENDOR_WRITE_REQUEST_TYPE, // bRequestType + VENDOR_WRITE_REQUEST, // bRequest + 1, // wValue + reg, // wIndex + 0, // pointer to destination buffer + 0, // wLength + 6000 + ); + 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_val_shift(int gpio) { + if (gpio == 0) + return 6; + if (gpio == 1) + return 7; + return 6; /* default to 0 */ +} + + +void gpio_out(usb_dev_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); +} + +void gpio_in(usb_dev_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); +} + +int gpio_read(usb_dev_handle *h, int gpio) +{ + unsigned char r = gpio_read_reg(h); + int shift = gpio_val_shift(gpio); + return (r & (1< +#include +#include +#include +#include +#include + +static int did_usb_init = 0; + + +static int usb_get_string_ascii(usb_dev_handle *dev, int index, int langid, char *buf, int buflen) +{ + char buffer[256]; + int rval, i; + + if((rval = usb_control_msg(dev, + USB_ENDPOINT_IN, + USB_REQ_GET_DESCRIPTOR, + (USB_DT_STRING << 8) + index, + langid, buffer, sizeof(buffer), + 1000)) < 0) + return rval; + if(buffer[1] != USB_DT_STRING) + return 0; + if((unsigned char)buffer[0] < rval) + rval = (unsigned char)buffer[0]; + rval /= 2; + /* lossy conversion to ISO Latin1 */ + for(i=1; i buflen) /* destination buffer overflow */ + break; + buf[i-1] = buffer[2 * i]; + if(buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */ + buf[i-1] = '?'; + } + buf[i-1] = 0; + return i-1; +} + + +int usb_match_string(usb_dev_handle *handle, int index, char* string) +{ + char tmp[256]; + if (string == NULL) + return 1; /* NULL matches anything */ + usb_get_string_ascii(handle, index, 0x409, tmp, 256); + return (strcmp(string,tmp)==0); +} + +usb_dev_handle *usb_check_device(struct usb_device *dev, + char *vendor_name, + char *product_name, + char *serial) +{ + usb_dev_handle *handle = usb_open(dev); + if(!handle) { + fprintf(stderr, "Warning: cannot open USB device: %s\n", usb_strerror()); + return NULL; + } + if ( + usb_match_string(handle, dev->descriptor.iManufacturer, vendor_name) && + usb_match_string(handle, dev->descriptor.iProduct, product_name) && + usb_match_string(handle, dev->descriptor.iSerialNumber, serial) + ) { + return handle; + } + usb_close(handle); + return NULL; + +} + +usb_dev_handle *nc_usb_open(int vendor, int product, char *vendor_name, char *product_name, char *serial) +{ + struct usb_bus *bus; + struct usb_device *dev; + usb_dev_handle *handle = NULL; + + if(!did_usb_init++) + usb_init(); + + usb_find_busses(); + usb_find_devices(); + + for(bus=usb_get_busses(); bus; bus=bus->next) { + for(dev=bus->devices; dev; dev=dev->next) { + if(dev->descriptor.idVendor == vendor && + dev->descriptor.idProduct == product) { + handle = usb_check_device(dev, vendor_name, product_name, serial); + if (handle) + return handle; + } + } + } + return NULL; +} +