ubuntu下libusb调试usb接收,丢包问题调试记录

Libusb接收有两种方式,同步和异步。同步比异步用法简单多了,所以我首先用的也是同步。后一直有丢包问题,所以换异步接收了。

1 同步

部分代码:

bool UsbHelper::usbBulkTrans(unsigned char* data,libusb_device_handle* dev_handle,unsigned char endpoint,int len, int *actual_len,int timeout)
{
    int ret = -1;
    ret = libusb_bulk_transfer(dev_handle,endpoint, data, len, actual_len,timeout);
    if(ret < 0)
    {
        if(ret != LIBUSB_ERROR_TIMEOUT)
        {
            lastErroeMsg = libusb_error_name(ret);
            //lastErroeMsg = "usb bulk:"+ std::to_string(ret)+ libusb_error_name(ret);
            return false;
        }
       
    }
    return true;
}

void UsbDebug::startThread()
{
    while (isDoing)
    {
        if(!isRun)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
            continue;
        }

        unsigned char recvdata[512] = "\0";
        int len = 0;
       
        if(!usbHelper.usbBulkTrans(recvdata,dev_handle,usbSetting.EndPointOut,512,&len,0))
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(2));
            continue;
        }
        
        //memset(signalData,0,sizeof(signalData));
        if(len > 0)
        {
#ifdef DEBUG
            // logger->info("usb receive data:");
            // char hexValue[3];
            // std::string strval = "";
            // for(int i=0; i< len; i++)
            // {
            //     sprintf(hexValue,"%02X",recvdata[i]);
            //     strval = strval + hexValue;
            //     if(i%16==15 || i== len-1)
            //     {
            //         logger->info("data{}:{} ",i/16,strval);
            //         strval = "";
            //     }
                
            // }
#endif      

            SubPack(recvdata, len);
            
            
        }
        
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

2 异步部分代码

void UsbHelper::usbBulkTransSync(libusb_device_handle* dev_handle,unsigned char endpoint,

    int timeout,libusb_transfer_cb_fn callback)

{

    int ret = -1;

    for(int i=0; i< 50; i++) //此处一开始是100丢,加到200、1000都是丢,后改到50

    {

        libusb_transfer *transfer = libusb_alloc_transfer(0);

    

        transfer->actual_length = 0;

        unsigned char *recvdata = new unsigned char[BUFFERSIZE];//一定要new

        memset(recvdata,0,BUFFERSIZE);

        libusb_fill_bulk_transfer(transfer,dev_handle,endpoint,recvdata,BUFFERSIZE,callback, NULL,timeout);

   

        ret = libusb_submit_transfer(transfer);

        if(ret != 0)

        {

            lastErroeMsg = "usb submit transfer error:" + std::to_string(ret)+ libusb_error_name(ret);

            //libusb_cancel_transfer(transfer);

            libusb_free_transfer(transfer);

          

            continue;

        }

        transferList.push_back(transfer);

    }


    isRun = true;

    // libusb_cancel_transfer(transfer);

     //libusb_free_transfer(transfer);

     //libusb_release_interface(dev_handle,0);

     //libusb_close(dev_handle);

}

异步依然存在丢包问题。

void async_callback(libusb_transfer *transfer)
{
    if(transfer->status == LIBUSB_TRANSFER_COMPLETED)
    {
         if(transfer->actual_length > 0)
         {
            buffermtx.lock();
            std::array<unsigned char,BUFFERSIZE> buffer;
            std::copy(transfer->buffer,transfer->buffer+BUFFERSIZE, buffer.begin());
            transferlist.push_back(buffer);
            buffermtx.unlock();
         }

        // if (libusb_submit_transfer(transfer) < 0) 
        // {
        //     libusb_cancel_transfer(transfer);
        // }

    }
    else if(transfer->status == LIBUSB_TRANSFER_CANCELLED)
    {
        libusb_free_transfer(transfer);
    }
    else
    {
        if (libusb_submit_transfer(transfer) < 0) 
        {
            libusb_cancel_transfer(transfer);
        }
    }

    
}

3 调试工具

usbmon 是usb调试的一个内核工具,默认都是已安装的。

先查看需要监听的usb的bus端口和device号,用lsusb命令,查看,我需要监测的是bus 002,device 003

输入sudo cat /sys/kernel/debug/usb/usbmon/2u |grep "2:003",其中2u表示监测bus2,bus1就是1u, 后面表示过滤,只检测设备号3.

此时终端开始刷数,需要退出ctrl+C

监测查看可以看到接收到1024数据包,但是显示不全。不知道某些包是否接收到了。

使用tcpdump 可以显示全部数据。这个工具也是默认安装的,我一开始用的下面命令usbmon2 表示监测bus2,-s -0 表示显示全部数据 -A表示在终端显示,因为我的是byte包十六进制,在终端显示乱码,所以还得存储文件用wireshark查看。

安装wireshark

监听数据存文件

Wireshark打开文件,发现确实有的包没接收到。都是接收了连续的几个576的包,然后有几个64字节的包,不知道干啥的,中间就丢包了。

返回usbmon查看接收中间是什么过程。

下面前两个字段不用管,是设备码和时间戳,S 表示submit,提交transfer; C表示callback回调中读取数据。Ci表示control包input;Bi表示bulk包input; 我主要用这两个包。

分析下面先是提交了(S Bi 512< )好多条,然后C回调中读取数据,C后面又跟了几个S提交,这时候丢包了。我认为是处理不过来了,所以把回调函数里的重新提交buffer 去掉了,这时候丢包少了一点。既然提交buffer是占用资源的,一开始开辟的transfer数量也不能一味的大,太大也是会丢包,一开始我设置200丢包,设置为50就不丢了。实际中我只会用到13个包左右,只不过包间距基本没有,属于高频包。

我的包里有计数,每一个512第一个包比上一个包应该差8.

结论:

1、 提交transfer时 unsigned char *recvdata = new unsigned char[BUFFERSIZE];一定要new,因为需要后期释放。用数组为崩溃。

2、提交transfer数量只是1个时会丢包,也不能一味的大,太大也是会丢包,合适了最好。

异步编写感谢:

libusb异步接收数据丢包问题_专栏_易百纳技术社区

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值