Zaman dahulu kala, Kita menggunakan serial port untuk menghubungkan peralatan pada komputer Kita. Serial port memiliki alamat tersendiri setiap portnya, jadi Kita yakin ketika melakukan koneksi ke COM-1, maka pasti akan konek kesana.

Sekarang, serial port sudah obsolete pada PC, dan digantikan oleh USB yang lebih superior. Tetapi banyak sekali peralatan yang masih menggunakan serial port untuk melakukan konektivitas, terutapa peralatan-peralatan industrial. Oleh sebab itulah Kita menggunakan interface USB to Serial.

Permasalahan dengan USB to Serial adalah tidak adanya kepastian lokasi port yang akan didapatkan. Lokasi port ditentukan oleh banyak faktor, seperti posisi pada Hub, atau USB to Serial mana yang lebih dulu bisa berkomunikasi dengan kernel, dan bahkan tidak jarang lokasi portnya berubah-ubah secara acak.

Untuk seorang programmer, hal ini sangat menjengkelkan, dan berharap ada cara untuk menentukan posisi port tanpa harus melakukan konfigurasi sistem pada OS yang begitu merepotkan.

Untungnya pada Linux Kita dapat melakukan deteksi slot yang diberikan oleh OS pada USB to Serial dengan melihat isi dari /proc/tty/driver/usbserial

Terdapat banyak informasi yang berguna yang dapat Kita manfaatkan, terutama info Vendor ID dan Product ID dari USB to Serial tersebut.

Berikut adalah contoh isi dari /proc/tty/driver/usbserial

usbserinfo:1.0 driver:2.0
0: module:pl2303 name:"pl2303" vendor:0557 product:2008 num_ports:1 port:0 path:usb-3f980000.usb-1.1.2.3
1: module:ftdi_sio name:"FTDI USB Serial Device" vendor:0403 product:6011 num_ports:1 port:0 path:usb-xhci-hcd.3.auto-1.2.1

Pada informasi tersebut dapat Kita lihat, terdapat 3 Baris informasi, dan dua informasi tentang modul USB to Serial yang terpasang.

Yang berguna adalah baris ke-2 dan selanjutnya, disana diketahui bahwa modul pl2303 dengan Vendor-ID 0557 dan Product-ID 2008 berada pada port 0, maka Kita dapat mengaksesnya pada /dev/ttyUSB0. Sedangkan untuk modul ftdi dengan Vendor-ID 0403 dan Product-ID 6011 berada pada port 1, maka dapat di akses pada /dev/ttyUSB1.

Dengan informasi tersebut, Kita dapat memulai membuat sebuah fungsi untuk menentukan /dev/ttyUSB yang mana kah yang harus digunakan. Berikut adalah fungsi yang Saya buat dan digunakan untuk berbagai kebutuhan:

/*
 * Copyright 2022 Ahmad Amarullah (https://amarullz.com/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/**
 * Fungsi untuk mencari lokasi ttyUSB
 * Bila return >= 0, berhasil, selain itu gagal.
 */
int find_ttyusb(const char *name, const char *vid, const char *pid) {
  FILE *fp;
  char *line = NULL;
  size_t len = 0;
  ssize_t read;
  int line_num = -1;

  // Buka usbserial
  fp = fopen("/proc/tty/driver/usbserial", "r");
  if (fp == NULL) return -1;

  char find_name[128];
  char find_pid[32];
  char find_tid[32];

  // Buat string untuk pencarian
  snprintf(find_name, 128, "name:\"%s", name ? name : "");
  snprintf(find_pid, 32, "vendor:%s", vid ? vid : "");
  snprintf(find_tid, 32, "product:%s", pid ? pid : "");

  // baris pertama dianggap -1
  int match = -1;

  // Baca per baris
  while ((read = getline(&line, &len, fp)) != -1) {
    // Acuhkan baris pertama
    if (line_num >= 0) {
      // set posisi device berdasarkan baris
      match = line_num;

      // cari string name,pid,tid pada baris tersebut
      if (!strstr(line, find_name)) match = -1;
      if (!strstr(line, find_pid)) match = -1;
      if (!strstr(line, find_tid)) match = -1;

      // bila match tidak di set -1, berarti cocok
      // dan langsung break loop
      if (match >= 0) {
        printf("ttyUSB(VID=%s,PID=%s,NAME=%s) ditemukan pada /dev/ttyUSB%i",
               vid, pid, name, match);
        break;
      }
    }
    line_num++;
  }
  fclose(fp);

  // getline akan melakukan alokasi memory
  // free terlebih dahulu
  if (line) free(line);

  // bila match < 0, return -2, tidak ditemukan
  if (match < 0) {
    printf("ttyUSB(VID=%s,PID=%s,NAME=%s) tidak ditemukan\n", vid, pid, name);
    return -2;
  }
  return match;
}

Fungsi tersebut dapat digunakan seperti berikut:

int main() {
  char dev_path[64];

  // cari pid:0557 dan vid:2008
  int ttyusbn = find_ttyusb("", "0557", "2008");

  // bila ditemukan, buat device path
  if (ttyusbn>=0){
    snprintf(dev_path,64,"/dev/ttyUSB%i", ttyusbn);
    
    int fd = open(dev_path, O_RDWR);
    // ...
    // sisa program lainnya
  }
  else
    printf("Tidak Ditemukan\n");
  return 0;
}

Penutup

Dengan adanya cara diatas, permasalahan posisi ttyUSB sedikitnya dapat diatasi, walaupun fungsi tersebut masih belum bisa mengatasi masalah ketika menggunakan dua atau lebih USB to Serial dengan model yang identik.

Mudah-mudahan informasi ini berguna. Selamat Mencoba.