First support PL2303-HXD GPIO 2 & 3
[pub/pl2303-ft232-gpio.git] / pl2303.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 /* According to POSIX.1-2001 */
4 #include <sys/select.h>
5 #include <string.h>
6 #include <sys/time.h>
7 #include <sys/types.h>
8 #include <unistd.h>
9 #include <termios.h>
10 #include <fcntl.h>
11 #include <signal.h>
12 #include <libusb.h>
13 #include <getopt.h>
14
15
16 #define _GNU_SOURCE
17 #include <getopt.h>
18
19
20 #define I_VENDOR_NUM 0x67b
21 #define I_PRODUCT_NUM 0x2303
22
23
24 #define VENDOR_READ_REQUEST_TYPE 0xc0
25 #define VENDOR_READ_REQUEST 0x01
26
27 #define VENDOR_WRITE_REQUEST_TYPE 0x40
28 #define VENDOR_WRITE_REQUEST 0x01
29
30 #define GPIO_01_RD_CTRL 0x0081
31 #define GPIO_01_WR_CTRL 0x0001
32 #define GPIO_23_DIR_RD_CTRL 0x8c8c
33 #define GPIO_23_DIR_WR_CTRL 0x0c0c
34 #define GPIO_23_VAL_RD_CTRL 0x8d8d
35 #define GPIO_23_VAL_WR_CTRL 0x0d0d
36
37 int get_device_vid()
38 {
39 return I_VENDOR_NUM;
40 }
41
42 int get_device_pid()
43 {
44 return I_PRODUCT_NUM;
45 }
46
47 /* Get current GPIO register from PL2303 */
48 char gpio_read_reg(libusb_device_handle *h, unsigned short ctrl)
49 {
50 char buf;
51 int bytes = libusb_control_transfer(
52 h, // handle obtained with usb_open()
53 VENDOR_READ_REQUEST_TYPE, // bRequestType
54 VENDOR_READ_REQUEST, // bRequest
55 ctrl, // wValue
56 0, // wIndex
57 &buf, // pointer to destination buffer
58 1, // wLength
59 1000
60 );
61 handle_error(bytes);
62 return buf;
63 }
64
65 void gpio_write_reg(libusb_device_handle *h, unsigned short ctrl, unsigned char reg)
66 {
67 int bytes = libusb_control_transfer(
68 h, // handle obtained with usb_open()
69 VENDOR_WRITE_REQUEST_TYPE, // bRequestType
70 VENDOR_WRITE_REQUEST, // bRequest
71 ctrl, // wValue
72 reg, // wIndex
73 0, // pointer to destination buffer
74 0, // wLength
75 1000
76 );
77 handle_error(bytes);
78 }
79
80 int gpio_dir_mask(int gpio) {
81 switch (gpio) {
82 case 0: return 0x10;
83 case 1: return 0x20;
84 case 2: return 0x03;
85 case 3: return 0x0c;
86 }
87 return 0x10; /* default to gpio 0 */
88 }
89
90 int gpio_val_shift(int gpio) {
91 switch (gpio) {
92 case 0: return 6;
93 case 1: return 7;
94 case 2: return 0;
95 case 3: return 1;
96 }
97 return 6; /* default to gpio 0 */
98 }
99
100
101 void gpio_out(libusb_device_handle *h, int gpio, int value)
102 {
103 int shift_val = gpio_val_shift(gpio);
104 unsigned char reg;
105
106 if (2 > gpio) {
107 reg = gpio_read_reg(h, GPIO_01_RD_CTRL);
108 reg |= gpio_dir_mask(gpio); /* set output direction */
109 reg &= ~(1 << shift_val); /* reset gpio */
110 reg |= (value << shift_val); /* set gpio to value */
111 gpio_write_reg(h, GPIO_01_WR_CTRL, reg);
112 } else {
113 reg = gpio_read_reg(h, GPIO_23_VAL_RD_CTRL);
114 reg &= ~(1 << shift_val); /* reset gpio */
115 reg |= (value << shift_val); /* set gpio to value */
116 gpio_write_reg(h, GPIO_23_VAL_WR_CTRL, reg);
117
118 reg = gpio_read_reg(h, GPIO_23_DIR_RD_CTRL);
119 reg |= gpio_dir_mask(gpio); /* set output direction */
120 gpio_write_reg(h, GPIO_23_DIR_WR_CTRL, reg);
121 }
122 }
123
124 void gpio_in(libusb_device_handle *h, int gpio, int pullup)
125 {
126 int shift_val = gpio_val_shift(gpio);
127 unsigned char reg;
128
129 if (2 > gpio) {
130 reg = gpio_read_reg(h, GPIO_01_RD_CTRL);
131 reg &= ~(gpio_dir_mask(gpio)); /* set input direction */
132 reg &= ~(1 << shift_val); /* reset gpio value */
133 reg |= (pullup << shift_val); /* pullup gpio value */
134 gpio_write_reg(h, GPIO_01_WR_CTRL, reg);
135 } else {
136 reg = gpio_read_reg(h, GPIO_23_DIR_RD_CTRL);
137 reg &= ~(gpio_dir_mask(gpio)); /* set input direction */
138 gpio_write_reg(h, GPIO_23_DIR_WR_CTRL, reg);
139
140 reg = gpio_read_reg(h, GPIO_23_VAL_RD_CTRL);
141 reg &= ~(1 << shift_val); /* reset gpio value */
142 reg |= (pullup << shift_val); /* pullup gpio value */
143 gpio_write_reg(h, GPIO_23_VAL_WR_CTRL, reg);
144 }
145 }
146
147 int gpio_read(libusb_device_handle *h, int gpio)
148 {
149 unsigned char r = gpio_read_reg(h, (2 > gpio) ? GPIO_01_RD_CTRL : GPIO_23_VAL_RD_CTRL);
150 int shift = gpio_val_shift(gpio);
151 return (r & (1 << shift));
152 }
153