Необходимо получить список всех com-портов в системе, к одному из которых подключен купюроприемник CashCode. Подключаю пространство имен System.IO.Ports и выполняю код:
В итоге получаю в ComboBox массив из 35 элементов с именами: «dev/ttyS0», «dev/ttyS1», ..., «dev/ttyS31» - откуда такое количество(32шт) com-портов на моей системе с материнской платой GIGABYTE GA-X58A-UD7?
Делаю это для того, чтобы пользователь мог выбрать к какому порту подключен купюроприемник.
Объясните пожалуйста, откуда такое количество портов?
Это не из системы, это откуда-то из недр библиотек - количество возможных имен, имхо. Не все возможные ,кстати, бывают /dev/ttyACM.." , /dev/ttyUSB.." тоже последовательными вроде как считаются. А имен уже 64, только не найду ссылку никак.
Т.е. это «не то что есть», а «то что может быть»? Но как тогда получить имена реальных com-портов и как с ними работать? Про com-порты, про работу с ними в Linux нашел крайне мало(две капли), для Win на Хабре нашел статью Горского - «Работа с последовательными портами» - вроде бы все предельно просто, но... Попытался открыть порт с именем «dev/ttyS0» - закончилось крахом - в принципе правильно, т.к. де факто его просто не существует в указанной системе.
Каким все же образом возможно получить список фактически существующих com-портов и уж совсем было бы хорошо, если у них можно был бы запросить имя подключенного устройства?
Только что ради интереса выполнил в терминале: dmesg | grep tty
- как понимаю, выдает все данные об компонентах tty - таких у меня всего один:
[ 0.000000] console [tty0] enabled
, видимо какой-то виртуальный, так что GetPortNames() возвращает действительно гипотетически возможные имена портов
На моём компе /dev/tty, /dev/tty1.. /dev/tty64, /dev/ttyS0../dev/ttyS4 и всякая экзотика типа ttyACM, ttyUSB по мере поступления, хотя на маме порт один (или два , но второй не распаян). Четыре , так понимаю , это из-за зарезервированных в IBM PC 0x3f8, 0x2f8, 0x3e8, 0x2e8 COM-портов.
Одна из движущих сил в развитии человека это зависть, надеюсь хоть зависть к виндузятникам доведет линукс до ума, раз уж опенсоурс и за денег не берут. А вот такие ананимусы выйдут на площадь с табличками на шее - «нет расизму в любых проявлениях» и покаются. Да, я в это верю, хотя может не доживу.
На ней вобще есть последовательные порты? Что написано в документации по этому поводу?
Ни разу ни видел mono, но судя по исходникам его библиотек, SerialPort.GetPortNames() просто выводит список файлов из каталога /dev/, соответсвующих маске /dev/ttyS* и /dev/ttyUSB*.
Не знаю, почему в вашей системе столько файлов-устройств ttyS*. Обычно ttyS0-ttyS3.
«dev/ttyS0» - закончилось крахом
Ужос какой, исключения обрабатывать не получается?
4 порта обычно резервирует драйвер последовательных портов, хотя разные драйвера могут и меньше и больше.
В /proc/tty/driver/serial драйвер сообщает о фактически обнаруженных UART'ах.
Если смотреть исходники ядра в каталоге drivers/tty/serial, имён может быть великое можество. Возможно, что проще из /proc/tty/drivers убирать известные имена виртуальных консолей (tty,pty), а всё остальное считать последовательными портами.
Так я и говорю, что на моей GIGABYTE GA-X58A-UD7 вообще нет последовательных портов.
Насчет обработки исключений: разумеется я их буду обрабатывать, только суть вопроса не в том, что: «Ай-яй-яй, я обращаюсь к ttyS0 и генерится исключение... Как же так, что же мне делать, кроме как стучать в бубен?», а вопрос подразумевал: «Как можно получить физически существующие имена com-портов, к которым что-либо подключено, опросить их, и узнать что куда подключено?» - почитав по-подробнее про com-порты нарыл, что узнать «что куда подключено» будет по-меньшей мере проблематично - узнать что куда подключено можно только с помощью отправления команд на com-порты для каждого устройства. Однако, неужели нет никакого более рационального способа опросить хотя бы «к каким портам что-то подключено»? Согласись, что заставлять юЗверя гадать: «Как же мне узнать имя com-порта(куда смонтирован com-порт)?» - по-меньшей мере жестоко.
Все же как можно и вообще возможно ли получить имена реально задействованных в системе com-портов и если возможно, то как?
Через dmesg все-таки попроще будет и права не нужны.
И пофиг, что содержимое dmesg лежит в кольцевом буфере, а формат вывода может меняться при обновлениях. Настоящий профессионал, который с последовательными портами работал, когда они были размером с наши туго набитые памперсы, на такие мелочи просто не обращает внимание.
Если это — эмуляция RS232 через USB, том можно сделать так:
а) перебрать при помощи libusb все USB-устройства в поисках нужного (с нужными ID) и исходя из него уже найти соответствующее устройство
б) перебирать все /dev/ttySx и /dev/ttyUSBx (или как оно там), пока не получим нужный отклик.
В «/proc/tty/drivers» перечислены различные tty-устройства. Последовательные порты обозначены как «serial». У каждого драйвера (имя в начале строки в файле «/proc/tty/drivers») в каталоге «/proc/tty/driver/» есть свой файл (/proc/tty/driver/serial, /proc/tty/driver/usbserial). Из этих файлов можно извлечь информацию по фактически имеющимся в системе последовательным портам.
Чтение этих файлов требует прав root'а, как, впрочем и работа с портом. Если работать с портом сменив права на «/dev/tty(S|USB)» или добавив пользователя в группу uucp, то всё равно для смены прав/добавления пользователя нужен root.
В usbserial есть ещё немного информации по USB-устройству, создающему данный порт. lsusb выводит vendorID строкой текста, то есть какая-то информация есть.
В классическом для PC последовательном порту (у которого разъём 9 штырьков) информации по подключенному устройству нет. И вобще нет информации о том, подключенно ли что-то к нему или нет — такой протокол. В обычных компьютерах (x86) сейчас уже встроенных COM-портов нет, а когда были, их было один или два, и в книжечке от материнской платы показывался, какой порт COM-1 (ttyS0), а какой COM-2 (ttyS1), поэтому дисциплинированный пользователь, умеющих хранить и читать документацию мог определить куда он подключал устройство. А уж если устанавливалась мультипортовка с 4/8/16 последовательными портами, то там тоже была документация с нумерацией портов, и записывали какое устройство на какой порт подключено.
Ну не говори ерунды, fgets и strstr разбирают любой человекочитаемый текст, ну не капчи же туда напихают, и порты достаточно определить один раз при старте системы, никуда они не денутся.
Видно, GetPortNames реализован совсем уж по-идиотски. Можно попробовать открывать все сообщенные им устройства по очереди - есть в системе те, которые не вернут EIO или ENODEV. А можно сразу полезть куда-нибудь в /sys: например, /sys/bus/platform/devices/serial8250.
выдаёт нормальный список портов в данный момент, но ,сдаётся мне, что сейчас припомнят hal, который выпилен и закопан. Или раскопан и впилен, фик разберет.
Проверил как работает Serial.Port.GetPortNames() на машине, в которой реально имеются COM-порты - работа с ними проходит нормально, порты открываются, но сперва нужно наделить программу правами для открытия (придумал небольшое сравнение по этому поводу(прошу не закидать тухлыми яйцами): «В ОС Windows у нас открыто все, абсолютно все и чтобы закрыть что-либо, какой-либо порт и прочее, необходимо лазить в настройках, править реестр и т.д. Linux поступает практически так же, но диаметрально противоположно - у него доступ ко всем устройствам/портам для программ закрыт и открытие этого доступа возможно только руками пользователя»).
Программу с тестингом доступа к COM-портам проверял человек, который является более-менее знающим пользователем Linux (Debian) - написал пару строк в терминале, перезагрузил машину и все, но что делать, если предполагается использование этой программы и мифической «бабой Нюрой»? Возможно ли каким-то образом сделать так, чтобы при запуске программа обращалась к ОС и просила выделить ей тот или иной порт, Linux спрашивал бы у пользователя пароль root'а и если пользователь его знает, то ОС открывает доступ программе к указанным портам? Пару недель назад ставил, кажется Deluge из репозитория и Ubuntu спросила: «Для открытия программе Deluge xxx доступа к порту, введите пароль root» - хочется сделать что-то в этом роде
Возможно ли каким-то образом сделать так, чтобы при запуске программа обращалась к ОС и просила выделить ей тот или иной порт, Linux спрашивал бы у пользователя пароль root'а и если пользователь его знает, то ОС открывает доступ программе к указанным портам?
Возможно. Но лучше занести пользователя, работающего с программой, в группу dialout (или можно сделать программу sgid на группу dialout).
Если программа работает демоном и гарантированно запускается при старте системы, когда из dmesg строки не вытеснены другими сообщениями и постоянно прочитывается dmesg на предмет появления новых ttyUSB*, то способо более менее нормальный.
А так dmesg может заполнятся достаточно быстро, причём обычный пользователь об это может не знать, у меня один раз от usb мышки постоянно появлялись сообщения что она исчезла/появилась. Не знаю в чём там была проблема (мышка или материнка), но работать это не мешало, разве что dmesg за час-другой был только в этих сообщениях.
С паролем рута можно много что сделать, наверное проще всего сделать этого пользователя (бабу Нюру) владельцем файла-устройства /dev/ttyS... И это будет работать до следующей перезагрузки. А вносить изменения в конфиг на автомате это не очень правильно, если что-то будет неправильно, то потом может не взлететь другое устройство (допустим 3G-модем).
Только, именно, философия Un*x другая, она подразумевает что за компьютером работают много пользователей, причём может и одновременно и как-то их права должны быть согласованы.
++
первое, что пришло в голову.
А вот пытаться опрашивать все найденные порты в общем случае не слишком хорошая затея, т.к. если портов >1 и к одному подключен ваш купюроприемник, а ко второму еще какой-то девайс, то при опросе ваша программа может нарушить работу сторонней программы
А вот пытаться опрашивать все найденные порты в общем случае не слишком хорошая затея, т.к. если портов >1 и к одному подключен ваш купюроприемник, а ко второму еще какой-то девайс, то при опросе ваша программа может нарушить работу сторонней программы
я об этом: «Каким все же образом возможно получить список фактически существующих com-портов и уж совсем было бы хорошо, если у них можно был бы запросить имя подключенного устройства»