使用libusb获取usb串口设备名

使用libusb自动获取usb串口设备名

原理

tty设备会在/sys/class/tty目录下生成对应的设备名文件,该文件是一个软连接, 由于软连接路径中包含了usb的端口号,所以我们可以通过读取tty目录下文件的软链接查询某个usb端口的tty设备名。

/sys/class/tty # ls -lh
total 0
lrwxrwxrwx    1 root     root           0 Jan  2 05:56 console -> ../../devices/virtual/tty/console
lrwxrwxrwx    1 root     root           0 Jan  2 05:56 ptmx -> ../../devices/virtual/tty/ptmx
lrwxrwxrwx    1 root     root           0 Jan  2 05:56 tty -> ../../devices/virtual/tty/tty
lrwxrwxrwx    1 root     root           0 Jan  2 05:56 tty0 -> ../../devices/virtual/tty/tty0
lrwxrwxrwx    1 root     root           0 Jan  2 05:56 tty1 -> ../../devices/virtual/tty/tty1
lrwxrwxrwx    1 root     root           0 Jan  2 05:56 ttyAMA4 -> ../../devices/platform/soc/soc:amba/120a4000.uart/tty/ttyAMA4
...
lrwxrwxrwx    1 root     root           0 Jan  2 06:35 ttyUSB0 -> ../../devices/platform/soc/100e0000.xhci_0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0/tty/ttyUSB0

libusb提供了监听usb设备插拔检测的接口,可以获取到(已)插入设备的vid,pid和端口号,所以我们可以通过libusb提供的接口使用vid,pid,或者端口号方式获取usb tty设备名。当然,用了libusb可以直接其相关api去读写设备,不用走open方式,这里就不介绍。

代码比较简单,就没注释了。另外,libusb.so需要自己编译,我使用的是海思的编译工具(CROSS_COMPILE = arm-himix200-linux-),所以.so可能跟你的不一样,libusb如何编译自行搜索,这里就不介绍了。

调用usb_tty_detect_init注册回调即可监听usb tty设备,如果不是tty设备, ttyName将返回null。具体设备名需要自己根据vid pid或者端口号去判断usb设备名。

注意注册usb_arrived_callback时的flag要设置为LIBUSB_HOTPLUG_ENUMERATE,已插入的设备才会触发回调。

在这里插入图片描述

如果端口有多个设备,设备名以空格隔开,“ttyUSB0 ttyUSB1"。

由于触发回调时可能还未在/sys/class/tty生成软连接,生成速度也不一样,所以这里我sleep了1s。

  • usb_tty_detect.c
// #include <jni.h>
#include <pthread.h>
#include <dirent.h>

#include <unistd.h>
#include <string.h>
#include <linux/limits.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#include "libusb.h"
#include "usb_tty_detect.h"


struct usb_tty_detect {
    int usb_handle_task_exit;
    libusb_context *usb_context;
    pthread_t usb_handle_thread;
    libusb_hotplug_callback_handle usb_attached_handle;
    libusb_hotplug_callback_handle usb_detached_handle;
    int (*g_usb_attached_callback)(int vid, int pid, const char *port_num, const char *ttyName);
    int (*g_usb_detached_callback)(int vid, int pid, const char *port_num);
};

void *usb_handle_events_task(void *param)
{
    usb_tty_detect_t *tty_handle = (usb_tty_detect_t *)param;

    while (tty_handle && tty_handle->usb_handle_task_exit != 1) {
        usleep(100*1000);
        libusb_handle_events_completed(tty_handle->usb_context, NULL);
    }

    return (void *)0;
}

int is_slink(char *file)
{
	struct stat file_stat= {0};

	if (lstat(file, &file_stat) == -1)
			return 0;

	return S_ISLNK(file_stat.st_mode) ? 1 : 0;
}

static int LIBUSB_CALL usb_arrived_callback(struct libusb_context *ctx,
                                            struct libusb_device *dev,
                                            libusb_hotplug_event event, void *userdata)
{
    DIR *dir;
    struct dirent *ptr;
    char file[PATH_MAX] = {0};
    char link_path[PATH_MAX] = {0};

	struct libusb_device_descriptor desc;
	int bus_num;
	uint8_t port_num[32] = {0};
	char port_num_path_key[128] = {0};
	uint8_t i, port_num_len = 0;
	static char port_num_path[32] = {0};
	static char ttyName[256] = {0};
	char *p_ttyName = NULL;

    usb_tty_detect_t *tty_handle = (usb_tty_detect_t *)userdata;

	libusb_get_device_descriptor(dev, &desc);
	bus_num = libusb_get_bus_number(dev);

	sprintf(port_num_path_key, "/%d", bus_num);

	memset(port_num_path, 0, sizeof(port_num_path));
	sprintf(port_num_path, "%d", bus_num);

	port_num_len = libusb_get_port_numbers(dev, port_num, 32);
	if (port_num_len) {
		sprintf(port_num_path, "%s-", port_num_path);
		sprintf(port_num_path_key, "%s-", port_num_path_key);
		for (i = 0; i < port_num_len; ++i) {
		//		LOG_D("port_num[%d]: %d\r\n", i, port_num[i]);
			sprintf(port_num_path_key, "%s%d", port_num_path_key, port_num[i]);
			sprintf(port_num_path, "%s%d", port_num_path, port_num[i]);
			if (i+1 < port_num_len) {
				sprintf(port_num_path_key, "%s.", port_num_path_key);
				sprintf(port_num_path, "%s.", port_num_path);
			}
		}

	}
	sprintf(port_num_path_key, "%s/", port_num_path_key);

	if (desc.bDeviceClass == LIBUSB_CLASS_HUB) {
		goto OUT;
	}

	if ((dir=opendir("/sys/class/tty")) == NULL)  {
		goto OUT;
	}
//	usleep(1000*500);	//等待生成软链接
	sleep(1);
	memset(ttyName, 0, sizeof(ttyName));
	while ((ptr=readdir(dir)) != NULL) {
		if(strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0)    ///current dir OR parrent dir
			continue;
		sprintf(file, "/sys/class/tty/%s", ptr->d_name);

		memset(link_path, 0, PATH_MAX);
		if (is_slink(file) && readlink(file, link_path, PATH_MAX)) {
			if (strstr(link_path, port_num_path_key)) {
				printf("dev is tty: %s\r\n", ptr->d_name);
				if (p_ttyName == NULL) {
					sprintf(ttyName, "%s", ptr->d_name);
				} else {
					sprintf(ttyName, "%s %s", ttyName, ptr->d_name);
				}
				p_ttyName = ttyName;
			}
		}
	}
	closedir(dir);
	if (p_ttyName)
		printf("ttyName: %s\r\n", p_ttyName);
OUT:
	if (tty_handle->g_usb_attached_callback)
		tty_handle->g_usb_attached_callback(desc.idVendor, desc.idProduct, port_num_path, p_ttyName);
	return 0;
}

static int LIBUSB_CALL usb_left_callback(struct libusb_context *ctx,
                                         struct libusb_device *dev,
                                         libusb_hotplug_event event, void *userdata)
{
	struct libusb_device_descriptor desc;
	int bus_num;
	uint8_t port_num[32] = {0};
	static char port_num_path[32] = {0};
	uint8_t i, port_num_len = 0;

    usb_tty_detect_t *tty_handle = (usb_tty_detect_t *)userdata;

	libusb_get_device_descriptor(dev, &desc);
	bus_num = libusb_get_bus_number(dev);


	sprintf(port_num_path, "%d", bus_num);

	port_num_len = libusb_get_port_numbers(dev, port_num, 32);
	if (port_num_len) {
		sprintf(port_num_path, "%s-", port_num_path);
		for (i = 0; i < port_num_len; ++i) {
			sprintf(port_num_path, "%s%d", port_num_path, port_num[i]);
			if (i+1 < port_num_len)
				sprintf(port_num_path, "%s.", port_num_path);
		}
	}
	if (tty_handle->g_usb_detached_callback)
		tty_handle->g_usb_detached_callback(desc.idVendor, desc.idProduct, port_num_path);
	return 0;
}

usb_tty_detect_t *usb_tty_detect_init(int (*usb_attached_callback)(int vid, int pid, const char *port_num, const char *ttyName),
						int (*usb_detached_callback)(int vid, int pid, const char *port_num))
{
	int ret = -1;
    usb_tty_detect_t *tty_handle;

	tty_handle = (usb_tty_detect_t *)malloc(sizeof(usb_tty_detect_t));
    if (NULL == tty_handle) {
        goto ERR1;
    }
    memset(tty_handle, 0x0, sizeof(usb_tty_detect_t));

	tty_handle->g_usb_attached_callback = usb_attached_callback;

	tty_handle->g_usb_detached_callback = usb_detached_callback;

	if (libusb_init(&tty_handle->usb_context) != 0) {
		printf("libusb_init failed!");
		goto ERR2;
	}

	if (pthread_create(&tty_handle->usb_handle_thread, NULL, usb_handle_events_task, tty_handle) != 0) {
		printf("pthread_create failed!");
		goto ERR3;
	}
	/*flag需要设置为LIBUSB_HOTPLUG_ENUMERATE才能检测到已插入的设备*/
	ret = libusb_hotplug_register_callback(tty_handle->usb_context,
										   LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED,
										   LIBUSB_HOTPLUG_ENUMERATE,
										   LIBUSB_HOTPLUG_MATCH_ANY,
										   LIBUSB_HOTPLUG_MATCH_ANY,
										   LIBUSB_HOTPLUG_MATCH_ANY,
										   usb_arrived_callback,
										   tty_handle,
										   &tty_handle->usb_attached_handle);
	if (LIBUSB_SUCCESS != ret) {
		printf("Error to register usb arrived callback");
		goto ERR4;
	}

	ret = libusb_hotplug_register_callback(tty_handle->usb_context,
											LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
											LIBUSB_HOTPLUG_NO_FLAGS,
											LIBUSB_HOTPLUG_MATCH_ANY,
											LIBUSB_HOTPLUG_MATCH_ANY,
											LIBUSB_HOTPLUG_MATCH_ANY,
											usb_left_callback,
											tty_handle,
											&tty_handle->usb_detached_handle);
	if (LIBUSB_SUCCESS != ret) {
		printf("Error to register usb left callback");
		goto ERR5;
	}

	return tty_handle;
ERR5:
	libusb_hotplug_deregister_callback(tty_handle->usb_context, tty_handle->usb_attached_handle);
ERR4:
	tty_handle->usb_handle_task_exit = 1;
	pthread_join(tty_handle->usb_handle_thread, NULL);
ERR3:
	libusb_exit(tty_handle->usb_context);
ERR2:
    free(tty_handle);
ERR1:
	return NULL;
}

int usb_tty_detect_exit(usb_tty_detect_t * tty_handle)
{
	if (tty_handle) {
		libusb_hotplug_deregister_callback(tty_handle->usb_context, tty_handle->usb_attached_handle);
		tty_handle->usb_handle_task_exit = 1;
		pthread_join(tty_handle->usb_handle_thread, NULL);
		libusb_exit(tty_handle->usb_context);

		tty_handle->g_usb_attached_callback = NULL;
		tty_handle->g_usb_detached_callback = NULL;
        free(tty_handle);
	    return 0;
	}
    return -1;
}

  • main.c
#include <stdio.h>
#include "usb_tty_detect.h"

int usb_attached_callback(int vid, int pid, const char *port_num, const char *ttyName)
{
    printf("usb dev attached. vid: %x, pid: %x, port: %s\r\n", vid, pid, port_num);
    if (ttyName)
        printf("tty: %s\r\n", ttyName);
    return 0;
}

int usb_detached_callback(int vid, int pid, const char *port_num)
{
    printf("usb dev detached. vid: %x, pid: %x, port: %s\r\n", vid, pid, port_num);
    return 0;
}

int main(int agrc, char *agrv[])
{
    usb_tty_detect_t *tty_handle = usb_tty_detect_init(usb_attached_callback, 
                                                        usb_detached_callback);
    
    getchar();
    
    usb_tty_detect_exit(tty_handle);
    return 0;
}
  • Makefile
CROSS_COMPILE = arm-himix200-linux-

CC = $(CROSS_COMPILE)gcc
AR = $(CROSS_COMPILE)ar

CFLAGS =  -Wall -I./include

LINKFLAGS =

LINKLIBS = -lpthread -L./ -lttydetect -L./libusb -lusb-1.0

tty_detect_srcs := usb_tty_detect.c 
tty_detect_objs := $(patsubst %.c, %.o, $(tty_detect_srcs))

tty_detect_static_objs := $(tty_detect_objs)
tty_detect_shared_objs := $(tty_detect_objs)

# tty_detect_static_lib := libttydetect.a
tty_detect_shared_lib := libttydetect.so


tty_detect_sample_srcs := main.c 
tty_detect_sample_objs := $(patsubst %.c, %.o, $(tty_detect_sample_srcs))


tty_detect_sample = ttydetect 

all: $(tty_detect_shared_lib) $(tty_detect_sample)

$(tty_detect_shared_lib): $(tty_detect_shared_objs)
	$(CC) $^ -shared   $(LINKFLAGS) -o $@

$(tty_detect_shared_objs): %.o:%.c 
	$(CC) -c -fPIC $<  $(CFLAGS) $(INC) -o $@



$(tty_detect_sample): $(tty_detect_sample_objs)
	$(CC) $^ $(LINKLIBS) -o $@

$(tty_detect_sample_objs): %.o:%.c 
	$(CC) -c $<  $(CFLAGS) $(INC) -o $@

.PHONY:clean
clean:
	-rm $(tty_detect_shared_objs)
	-rm $(tty_detect_shared_lib)
	-rm $(tty_detect_sample_objs)
	-rm $(tty_detect_sample)



FORCE:

源码

https://github.com/hongguangli/ttyDetect

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值