LinuxボードUSBシリアル通信の挿抜検査

2062 ワード

プロジェクト開発では、linuxシステムを搭載したARM 9ボードにおいて、USBポートとWindowsクライアントとの接続と切断状況をリアルタイムで検出し、コマンドの送信を中断する必要がある.serial.koのモジュールは、devディレクトリの下でttyGS 0のポート番号を生成します.シリアル通信が中断してもポートアドレスは消えないので、一定時間以内にポートの読み書き状態を検出することでシリアル通信が正常であると判断し、タイムアウトした場合は接続が切断されていると判断する.
まず、シリアルポートを開きます
//       usb,  5 
int fd = -1;
for(int i=0;i<5;i++)
{
    fd = open("/dev/ttyGS0",  O_RDWR|O_NOCTTY);
    if(fd<=0) 
        continue;//retry until reach 5 times
    else 
        break;
}

g_を使用するためserial.koはシリアルポートモジュールをロードし、シリアルポートパラメータを追加する必要はありません.
ポートキャッシュをクリア
tcflush(fd, TCIOFLUSH); //clear port caches

スレッド送受信ポートデータの作成
//  USB    
pthread_t tid;
pthread_create(&tid, NULL, Thread_USB_SendRecv, this);

スレッド関数は次のとおりです.
void* Thread_USB_SendRecv(void *pData)
{
    usbserial* pUSBSerial = (usbserial*) pData;
    while(true)
    {
	int nRet =  pUSBSerial->ProcData();
	if(nRet < 0)
        {
	    //  USB
	    pUSBSerial->ResetUSB();
	}
    }
    QPRINT("Thread_USB_SendRecv DEAD!!!!");
    return 0;
}

シリアル通信で使用されるブロックIOのモードにより、戻ったnRet<0の場合、usb通信エラーまたは接続が切れたと判断したため、USBを再起動する必要があり、再起動操作は/dev/ttyGS 0ポートを再開し、正常な通信ができればデータの送受信を継続し、ここではUSBの切断または抜去の判断としない.
USB抜去の判断は、他のモニタスレッド処理がタイムアウトした場合、すなわち、所定時間以内にデータが読み取られなかった場合に通信が切断されたか、USB線が抜去されたと判断するしかない.ここではカウンタを使用して設定し、readからデータに達した後にカウンタをリセットします.
ssize_t ReadForUSBHost(int fd, void* buf, size_t nbytes)
{
    ssize_t nRead = read(fd, buf, nbytes);
    if(nRead>0) m_nIdleCount = 0;//reset counter
    return nRead;
}

モニタスレッドが1つのスレッドを再開し、1秒おきにカウンタを比較します.
int usbserial::CheckUSBPortConStatus()
{
    //use m_nIdleCount to set timeout.
    bool bRet = (m_nIdleCount++) < m_nTimeout;//    ,  s
    if( bRet != USB_GetLink() )
    {
	USB_SetLink( bRet );
	if(bRet == false) // lose link
	    QPRINT("USB link timeout, only set flag....");
	else // link again
	    QPRINT("USB get data again, ...");
	}
    return 1;
}