假如Linux系統上沒有USB Serial Kernel Module,可以透過libusb + PTY做USB Bridge轉換
main.c
#define _GNU_SOURCE
#include <libusb-1.0/libusb.h>
#include <pty.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <poll.h>
#include <termios.h>
#define FT232_VID 0x0403
#define FT232_PID 0x6001
#define IFACE 0x00
#define EP_IN 0x81
#define EP_OUT 0x02
#define BUF_SIZE 512
static void set_raw(int fd)
{
struct termios tio;
tcgetattr(fd, &tio);
cfmakeraw(&tio);
tcsetattr(fd, TCSANOW, &tio);
}
static void ft232_init(libusb_device_handle *dev)
{
uint16_t divisor = 0x001a;
if (libusb_control_transfer(dev, 0x40, 0x03, divisor, 0, NULL, 0, 1000) < 0) {
perror("FT232 SET_BAUD");
exit(1);
}
if (libusb_control_transfer(dev, 0x40, 0x04, 8, 0, NULL, 0, 1000) < 0) {
perror("FT232 SET_DATA");
exit(1);
}
}
int main(void)
{
libusb_context *ctx = NULL;
libusb_device_handle *dev;
int pty_master;
int pty_slave;
char pty_name[64];
unsigned char buf[BUF_SIZE];
libusb_init(&ctx);
dev = libusb_open_device_with_vid_pid(ctx, FT232_VID, FT232_PID);
if (!dev) {
fprintf(stderr, "FT232 device not found\n");
return 1;
}
libusb_detach_kernel_driver(dev, IFACE);
libusb_claim_interface(dev, IFACE);
ft232_init(dev);
if (openpty(&pty_master, &pty_slave, pty_name, NULL, NULL) < 0) {
perror("openpty");
return 1;
}
set_raw(pty_master);
printf("FT232 PTY ready: %s\n", pty_name);
struct pollfd pfd = {
.fd = pty_master,
.events = POLLIN
};
while (1) {
if (poll(&pfd, 1, 5) > 0) {
int n = read(pty_master, buf, sizeof(buf));
if (n > 0) {
int sent;
libusb_bulk_transfer(dev, EP_OUT, buf, n, &sent, 0);
}
}
int received;
int rc = libusb_bulk_transfer(dev, EP_IN, buf, sizeof(buf), &received, 10);
if (rc == 0 && received > 2) {
write(pty_master, buf + 2, received - 2);
}
}
}
編譯、測試
$ gcc main.c -o usb_ft232_bridge -lusb-1.0
$ sudo ./usb_ft232_bridge &
FT232 PTY ready: /dev/pts/2
$ lsusb -v -d 0x0403:0x6001 | egrep -e "EP|Transfer"
bEndpointAddress 0x81 EP 1 IN
Transfer Type Bulk
bEndpointAddress 0x02 EP 2 OUT
Transfer Type Bulk
$ sudo ln -s /dev/pts/2 /dev/ttyUSB9999
$ sudo minicom -D /dev/ttyUSB9999 -b 115200