Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Получение списка доступных последовательных портов (Boost.Asio) #567

Open
ksrp1984 opened this issue Jul 1, 2023 · 10 comments

Comments

@ksrp1984
Copy link

ksrp1984 commented Jul 1, 2023

<Описание вашей идеи>
Метод получения доступных последовательных портов в системе
<Примеры, где ваша идея будет полезна. Чем больше примеров и чем большую аудиторию они охватывают - тем лучше>
Будет полезно в любом приложение работающее с COM портами
<Код c реализацией вашей идеи, если есть>
В качестве референса можно использовать реализацию в QT: "QList QSerialPortInfo::availablePorts()"(qserialportinfo_unix.cpp, qserialportinfo_win.cpp)

Полезные ссылки:

@kov-serg
Copy link

kov-serg commented Jul 1, 2023

Чтоб далеко не бегать:

int enum_comports( void (*handler)(void* ctx, const char* name, const char* desc), void *ctx );

#ifdef WIN32

#include <windows.h>

int enum_comports( void (*handler)(void* ctx, const char* name,const char* desc), void *ctx ) {
	const char* path1="HARDWARE\\DEVICEMAP\\SERIALCOMM";
	LSTATUS st; DWORD nvalues=0; HKEY key=0;

	st=RegOpenKeyExA(HKEY_LOCAL_MACHINE,path1,0,KEY_READ,&key);
	if (st) {
		// fprintf(stderr,"no com ports. unable to open %s\n",path1);
		return 1;
	}
	st=RegQueryInfoKeyA(key,0,0,0,0,0,0,&nvalues,0,0,0,0);
	if (st) {
		// fprintf(stderr,"unable to get values count\n");
		nvalues=256;
	}
	for(int i=0;i<(int)nvalues;i++) {
		enum { name_max=256, value_max=256 };
		char name[name_max], value[value_max];
		DWORD name_len=name_max, value_len=value_max, val_type=0;
		name[0]=0; value[0]=0;
		st=RegEnumValueA(key,i,name,&name_len,0,&val_type,(LPBYTE)value,&value_len);
		if (st) {
			if (st==ERROR_NO_MORE_ITEMS) break;
			// fprintf(stderr,"error enum values %d\n",st);
			break;
		}
		if (val_type==REG_SZ ||
			val_type==REG_EXPAND_SZ ||
			val_type==REG_MULTI_SZ) {
				const char* desc=name;
				const char* prefix="\\Device\\";
				int i=0; while(prefix[i] && *desc==prefix[i]) { i++; desc++; }
				handler(ctx,value,desc);
		} else {
			// fprintf(stderr,"unexpected value type %d\n",val_type);
		}
	}
	RegCloseKey(key);
	return 0;
}

#else // linux

#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>

#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <linux/serial.h>
#include <string>
using std::string;

static string comport_get_driver(const string& dir) {
	struct stat st;
	string devicedir = dir;

	devicedir += "/device";
	if (lstat(devicedir.c_str(), &st)==0 && S_ISLNK(st.st_mode)) {
		enum { buffer_max=1024 }; char buffer[buffer_max];
		memset(buffer, 0, sizeof(buffer));
		devicedir += "/driver";
		if (readlink(devicedir.c_str(), buffer, sizeof(buffer)) > 0) {
			return basename(buffer);
		}
	}
	return "";
}

static int comport_probe(const char *name) {
	struct serial_struct serinfo;
	int rc=1;
	int fd=open(name, O_RDWR | O_NONBLOCK | O_NOCTTY);
	if (fd>=0) {
		if (ioctl(fd, TIOCGSERIAL, &serinfo)==0) {
			if (serinfo.type!=PORT_UNKNOWN) rc=0;
		}
		close(fd);
	}
	return rc;
}

int enum_comports( void (*handler)(void* ctx, const char* name,const char* desc), void *ctx ) {
	int n; struct dirent **namelist;
	const char* sysdir = "/sys/class/tty/";

	n = scandir(sysdir, &namelist, NULL, NULL);
	if (n<0) perror("scandir");
	else {
		while (n--) {
			if (strcmp(namelist[n]->d_name,"..") && strcmp(namelist[n]->d_name,".")) {
				string devicedir = sysdir;
				devicedir += namelist[n]->d_name;
				string driver = comport_get_driver(devicedir.c_str());
				if (driver.size() > 0) {
					string devfile = string("/dev/") + basename(devicedir.c_str());
					bool invalid=0;
					if (driver == "serial8250") {
						invalid=comport_probe(devfile.c_str());
					}
					if (!invalid) handler(ctx,devfile.c_str(),driver.c_str());
				}
			}
			free(namelist[n]);
		}
		free(namelist);
	}
	return 1;
}

#endif

@GitSparTV
Copy link

А много ли приложений пользуется COM портами? Звучит слишком ОС-зависимо и тем более у нас нет понятия устройств и прочего, в какую библиотеку это войдёт?

@ksrp1984
Copy link
Author

ksrp1984 commented Jul 2, 2023

В промышленности последовательные порты повсеместно используются. Логичнее всего чтобы вошло в boost asio, т.к. в стандартной библиотеке ничего подобного нет. В boost же работа с последовательными портами реализована, а вот функции для получения доступных портов нет. По поводу "ОС-зависимо" - в Qt же реализовали, недавно собрал на Ubuntu одно свое приложение, которое изначально разрабатывалось под Windows, проблем не обнаружил, без каких либо изменений в коде приложение собралось и работало на Linux, список всех портов отображался корректно. Понятно что внутри в Qt код разный под разные платформы, но пользователь библиотеки об этом знать не должен.

@GitSparTV
Copy link

Не знал, что сюда и для буста идеи можно кидать

@ksrp1984
Copy link
Author

ksrp1984 commented Jul 3, 2023

Если подскажите можно куда перенести

@incoder1
Copy link

incoder1 commented Jul 8, 2023

Зачем это в стандарте? Это функции операционной системы. Какие COM порты скажем в Rabsbery Pi ? Получится что нет портов - зничит и нельзя раработать полностьтю удовлятеворяющую стандарту стандартную библиотеку.

@kov-serg
Copy link

kov-serg commented Jul 8, 2023

Rasbery PI обычные последовательные порты, даже в arduino они есть.

@ksrp1984
Copy link
Author

ksrp1984 commented Jul 8, 2023

Зачем это в стандарте? Это функции операционной системы. Какие COM порты скажем в Rabsbery Pi ? Получится что нет портов - зничит и нельзя раработать полностьтю удовлятеворяющую стандарту стандартную библиотеку.
А какие потоки, исключения, динамическая память на 8 битном МК (а вот последовательные порты даже там есть)? По этой логике много чего в стандарте лишнее. И речь все же не про стандартную библиотеку, а про boost в котором уже реализована работа с последовательными портами.

@ksrp1984
Copy link
Author

Не знал, что сюда и для буста идеи можно кидать

Вроде бы планируется в C++ добавить Networking, не знаю подразумевает ли он работу с последовательными портами, но логично было бы что ДА.

@ksrp1984
Copy link
Author

Зачем это в стандарте? Это функции операционной системы. Какие COM порты скажем в Rabsbery Pi ? Получится что нет портов - зничит и нельзя раработать полностьтю удовлятеворяющую стандарту стандартную библиотеку.

Для популярных ОС можно полноценно реализовать этот функционал. Для систем без ОС можно просто оставить стандартный интерфейс который должен реализовать пользователь.
Rabsbery Pi вродебы на Linux работает? Какие там могут быть проблемы?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants