目的:读取 /dev/ 目录下 USB 串口设备名称
提醒: 因 USB 接口松动或其它原因,会导致 USB 设备于 linux 系统中的通道号会改变! 如正确处理异常退出,则 USB 通道号不会增加
硬件: RPI 3B+, NORDIC nRF52840 USB Dongle
系统: Linux raspberrypi 4.19.118-v7+
个人收获: 重写此模块,再次体会严谨错误处理、功能解藕~~
文件: ttyacm-check.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#define DIR_READ_SLEEP_INTERVAL 5
#define TTYACM_NAME_LEN 15
static DIR *dir;
static struct dirent *dev_file;
static const char dev_dir[] = "/dev/";
static const char dev_check[] = "ttyACM";
void *ttyacm_check(void *p)
{
char tmp_dev[TTYACM_NAME_LEN];
while ( 1 )
{
if ( (dir=opendir(dev_dir)) == NULL )
{
perror( strerror(errno) );
pthread_exit( &errno );
}
errno = 0;
while ( (dev_file = readdir(dir)) != NULL )
{
if ( strstr(dev_file->d_name,dev_check) != NULL ) // get the USB-ttyACM channel
{
memset( tmp_dev,0x00,TTYACM_NAME_LEN );
strcat( tmp_dev,dev_dir );
strcat( tmp_dev,dev_file->d_name );
fprintf( stdout,"GOT USB: %s\n",tmp_dev );
// ttyacm_channel_operation( tmp_dev );
}
errno = 0;
// signal to normal exit
}
if ( errno )
{
perror( strerror(errno) );
if ( closedir(dir) )
{
perror( strerror(errno) );
}
pthread_exit( &errno );
}
if ( closedir(dir) )
{
perror( strerror(errno) );
pthread_exit( &errno );
}
fprintf( stdout,"%s(),%s",__FUNCTION__,"circle read dir /dev/.\n" );
sleep( DIR_READ_SLEEP_INTERVAL );
}
// ?? normal exit by signal ..
pthread_exit( 0 );
}
测试主文件
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <error.h>
#include <string.h>
#include "chk-ttyacm.h"
int main( int argc,char * argv[] )
{
pthread_t tid_rx_ttyacm;
ttyacm_tid_init();
int err = pthread_create( &tid_rx_ttyacm,NULL,ttyacm_check,NULL );
if ( err )
{
fprintf( stderr,"%s(): %s\n",__FUNCTION__,strerror(err) );
exit(1);
}
pthread_join( tid_rx_ttyacm,NULL );
exit(0);
}
Makefile 文件
CC = gcc
CFLAGS += -c -Wall -g
OBJS = usb-ttyacm-communication.o ttyacm-check.o
ttyacm:$(OBJS)
$(CC) $^ -lpthread -o $@
*.o:*.c
$(CC) $(CFLAGS) $^
.PHONY:clean
clean:
$(RM) $(OBJS) ttyacm
相关技术扩展
DIR 结构体
struct __dirstream
{
void *__fd;
char *__data;
int __entry_data;
char *__ptr;
int __entry_ptr;
size_t __allocation;
size_t __size;
__libc_lock_define (, __lock)
};
typedef struct __dirstream DIR;
dirent 结构体
struct dirent
{
long d_ino; /* inode number 索引节点号 */
off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
unsigned short d_reclen; /* length of this d_name 文件名长 */
unsigned char d_type; /* the type of d_name 文件类型 */
char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
}
d_type 文件类型
enum
{
DT_UNKNOWN = 0, //未知类型
# define DT_UNKNOWN DT_UNKNOWN
DT_FIFO = 1, //管道
# define DT_FIFO DT_FIFO
DT_CHR = 2, //字符设备
# define DT_CHR DT_CHR
DT_DIR = 4, //目录
# define DT_DIR DT_DIR
DT_BLK = 6, //块设备
# define DT_BLK DT_BLK
DT_REG = 8, //常规文件
# define DT_REG DT_REG
DT_LNK = 10, //符号链接
# define DT_LNK DT_LNK
DT_SOCK = 12, //套接字
# define DT_SOCK DT_SOCK
DT_WHT = 14 //链接
# define DT_WHT DT_WHT
};
Bash shell 文件: 间隔 10 秒, 获取当前所有的 USB 通道 (/dev/ttyACM*),并存储于 log-ttyACM.txt
#!/bin/bash
times=0
while true
do
times=`expr $times + 1`
echo -ne "item: $times, " >> log-ttyACM.txt
date "+%Y-%d-%d %H:%M:%S" >> log-ttyACM.txt
ls /dev/ttyACM* >> log-ttyACM.txt
sleep 5
done