zoukankan      html  css  js  c++  java
  • BLE建立L2CAP Socket连接remote提示connect refused

    最近在全志r329 上面编写和某个remote设备建立BLE连接的程序,发现创建socket以后,和remote设备连接时候,提示connect refused。

    最后分析原因是:没有设置LE_HOST_SUPPORTED。 

    在此记录问题原因和解决方法:

    int __host_create_gatt_socket( char *slave_macaddr ) //XX:XX:XX:XX:XX:XX
    {
        int sk = 0;
        struct sockaddr_l2 master_addr;
        struct sockaddr_l2 slave_addr;
        struct bt_security btsec;
    
        //创建gatt层的socket
        sk = socket( AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP );
    //    sk = socket( AF_BLUETOOTH, SOCK_SEQPACKET | SOCK_NONBLOCK, BTPROTO_L2CAP );
        printf( "sock = %d
    ",sk );
           if ( sk<0 )
           {
            pt_error( "Can't create seqpacket socket: %s
    ", strerror(errno) );
            return -1;
        }
    
        
        //绑定socket
        memset( &master_addr,0,sizeof(master_addr) );
        master_addr.l2_family = AF_BLUETOOTH;
        master_addr.l2_cid = 0x0004;
        master_addr.l2_bdaddr_type=0x01;
        
        if( bind(sk, (struct sockaddr *)&master_addr, sizeof(master_addr))<0 )
        {
            pt_error( "[con] bind error: %s
    ", strerror(errno) );
            close( sk );
            return -1;
        }
        printf( "bind success
    " );
    
    
        
        //slave 的mac 地址
        memset( &slave_addr, 0, sizeof(slave_addr) );
        slave_addr.l2_family = AF_BLUETOOTH;
        slave_addr.l2_cid = 0x0004;
        slave_addr.l2_bdaddr_type = 0x01;
        str2ba( slave_macaddr, (bdaddr_t*)&slave_addr.l2_bdaddr );
    
    
    
        if( connect( sk, (struct sockaddr *)&slave_addr, sizeof(slave_addr))<0 )
        {
            pt_error( "[con] connect error: %s-%d", strerror(errno),errno );
            close( sk );
            return -1;
        }
    
        printf( "connect to slave success
    " );
        return sk;
    }

    创建L2CAP socket以后,调用connect()接口,提示connect refused。

    添加如下接口:

    int hci_read_le_host_supported(int dd,int *le,int *simul, int to);
    int hci_write_le_host_supported(int dd, uint8_t leEnable,uint8_t simulEnable , int to)
     
    int hci_read_le_host_supported(int dd,int *le,int *simul, int to)
    {
        read_le_host_supported_rp rp;
        struct hci_request rq;
    
        memset(&rq, 0, sizeof(rq));
        rq.ogf    = OGF_HOST_CTL;
        rq.ocf    = OCF_READ_LE_HOST_SUPPORTED;
        rq.rparam = &rp;
        rq.rlen   = READ_LE_HOST_SUPPORTED_RP_SIZE;
    
        if (hci_send_req(dd, &rq, to) < 0)
            return -1;
    
        if (rp.status) {
            errno = EIO;
            return -1;
        }
    
        if(le)
            *le = rp.le;
        if(simul)
            *simul = rp.simul;
    
        return 0;
    }
    
    int hci_write_le_host_supported(int dd, uint8_t leEnable,uint8_t simulEnable , int to)
    {
        write_le_host_supported_cp cp;
        struct hci_request rq;
    
        memset(&cp, 0, sizeof(cp));
        cp.le = leEnable;
        cp.simul = simulEnable;
    
        memset(&rq, 0, sizeof(rq));
        rq.ogf    = OGF_HOST_CTL;
        rq.ocf    = OCF_WRITE_LE_HOST_SUPPORTED;
        rq.cparam = &cp;
        rq.clen   = WRITE_LE_HOST_SUPPORTED_CP_SIZE;
    
        if (hci_send_req(dd, &rq, to) < 0)
            return -1;
    
        return 0;
    }
    ble_host_scan( int enable )
    {
       int m_advsock ;
    int le=0,simul=0;
    if( enable ) { m_advsock = hci_open_dev(0) ; //hci0 if( m_advsock>0 ) { hci_read_le_host_supported(m_ble_advsock,&le,&simul,5000); printf( "le=%d simul=%d... ",le, simul ); hci_write_le_host_supported(m_ble_advsock, 1,simul , 5000); hci_read_le_host_supported(m_ble_advsock,&le,&simul,5000); printf( " le=%d simul=%d... ",le, simul );

    //设置LE扫描参数,使能扫描
           ble_hci_lescan( m_advsock, enable ); } }
    else
    {
        ble_hci_lescan( m_advsock, enable );

    }
    
    }
    int ble_hci_lescan( int s, int enable )
    {
        printf( "ble_hci_lescan=%d %d
    ", s, enable );
        if( s >= 0 )
        {
            int err=-1;
            m_is_enable = enable;
            if( m_is_enable==0 )
            {
                uint8_t filter_dup = 0x01;
                setsockopt( s, SOL_HCI, HCI_FILTER, &m_orig_filter, sizeof(m_orig_filter) );
                err = hci_le_set_scan_enable( s, 0x00, filter_dup, 10000 );
                if (err < 0)
                {
                    pt_error("Disable scan failed ->%s", strerror(errno) );
                    return -1;
                }
                printf( "hci le set scan disable
    " );
            }
            else
            {
    
                uint8_t own_type = LE_PUBLIC_ADDRESS;
                uint8_t scan_type = 0x00;
                uint8_t filter_policy = 0x00;
                uint16_t interval = htobs(0x0050);
                uint16_t window = htobs(0x0020);
                uint8_t filter_dup = 0x00;//过滤掉相同的 1
    
        
    //            uint16_t interval = htobs(ble_scan_paramter_interval);
    //            uint16_t window = htobs(ble_scan_paramter_windows);
    
                printf( "interval = %d, window = %d
    ", interval, window );
    
                err = hci_le_set_scan_parameters( s, scan_type, interval, window, own_type, filter_policy, 10000 );
                if (err < 0)
                {
                    pt_error("Set scan parameters failed ->%s", strerror(errno) );
                    return -1;
                }
                printf( "set scan prameter succ:%d %d
    ",interval, window );
                err = hci_le_set_scan_enable(s, 0x01, filter_dup, 10000);
                if (err < 0)
                {
                    pt_error("Enable scan failed ->%s", strerror(errno) );
                    return -1;
                }
    struct hci_filter nf;
                socklen_t olen;
    
                olen = sizeof(m_orig_filter);
                if (getsockopt(s, SOL_HCI, HCI_FILTER, &m_orig_filter, &olen) < 0)
                {
                    pt_error("Could not get socket options
    ");
                    return -1;
                }
    
                hci_filter_clear(&nf);
                hci_filter_set_ptype(HCI_EVENT_PKT, &nf);
                hci_filter_set_event(EVT_LE_META_EVENT, &nf);
                //try to get disconnect event!!!
                hci_filter_set_event(EVT_DISCONN_COMPLETE, &nf);
                if (setsockopt(s, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0)
                {
                    pt_error("Could not set socket options
    ");
                    setsockopt(s, SOL_HCI, HCI_FILTER, &m_orig_filter, sizeof(m_orig_filter));
                    return -1;
                }
            }
            return 0;
        }
        return -1;
    }

    设置了LE_HOST_SUPPORT后,即可正常连接remote 设备。

    注:

    1. 在测试中发现,如果启动bluetoothd,不需要设置LE_HOST_SUPPORT,也可以连接成功。怀疑是Bluetoothd启动中,设置了LE_HOST_SUPPORT。 

    2. LE_HOST_SUPPORT feature 开发板每次启动都需要设置。该feature应该是设置到了内核中。

    3. 跟踪到了内核代码中,初步发现在mgmt.c中的set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)接口中有设置LE_HOST_SUPPORT

  • 相关阅读:
    给文章生成二维码
    用HTML5 Canvas做一个画图板
    失败多少次不要紧,人们只会记住你成功的那一次
    关于读大学的意义
    卸载Anaconda
    Anaconda基本命令
    plt.imshow()
    matplotlib不显示图片
    在Anaconda环境下使用Jupyter Notebook
    join()
  • 原文地址:https://www.cnblogs.com/hjj801006/p/14436473.html
Copyright © 2011-2022 走看看