【问题标题】:Running two Bluetooth programs on one machine using two adapters使用两个适配器在一台机器上运行两个蓝牙程序
【发布时间】:2020-10-05 09:16:37
【问题描述】:

新帖子

我现在对我的问题有了更好的理解,与其创建一个新线程,我只更新这个线程。

所以使用hci_open_dev 是错误的,因为它只打开本地BT 适配器的套接字。它不能帮助我建立与远程设备的连接。

总而言之 - 我的笔记本电脑中有一个内置的 BT 适配器,我买了一个小型 USB BT 适配器,我已将它插入同一台笔记本电脑。现在我想在这台可以通信的机器上运行两个程序。为此,他们需要使用不同的适配器。

bind 的第二个参数是 struct sockaddr*,我只是将之前的 struct sockaddr_rc* 转换为。 listening 套接字的struct sockaddrbdaddr_t 字段指定使用哪个BT 适配器,允许我这样做:

struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
// address of the built in BT adapter on my machine
const char* adapter = "60:F2:62:1B:9C:74";
// converting it to a bdaddr_t*
bdaddr_t* adapterbdadd = strtoba(adapter);

// allocate socket
int s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);

// bind socket to port 1
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = *adapterbdadd;
loc_addr.rc_channel = (uint8_t) 1;
bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));

// set the socket to listening mode
listen(s, 1);

// accept one connection
client = accept(s, (struct sockaddr *)&rem_addr, &opt);

// convert the bdaddr to a char* (just assume buf is defined elsewhere)
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf(stderr, "accepted connection from %s\n", buf);

// free socket resources
close(client);
close(s);

但是,对于传出连接,我不确定如何指定要使用的适配器。代码大致如下:

struct sockaddr_rc addr = { 0 };
// This is the same address that should be used by the listening program above
char dest[18] = "60:F2:62:1B:9C:74";

// allocate a socket
int s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);

// set the connection parameters. Want to connect to the listening program
// and connect through port 1. If I change both programs to use port 0 I
// get an Invalid Argument error from this program.
addr.rc_family = AF_BLUETOOTH;
addr.rc_channel = (uint8_t) 1;
str2ba( dest, &addr.rc_bdaddr );

// connect to listening program
int status = connect(s, (struct sockaddr *)&addr, sizeof(addr));

// This program never reaches beyond this point
if( status == 0 ) {
    printf("successfully connected\n");
} else {
    perror("error connecting");
}

close(s);

如上所示,我只能指定要连接到哪个设备,使用哪个设备。当我第一次启动客户端后面的监听程序时,连接永远不会建立。运行 hciconfig 的输出如下所示:

hci1:   Type: Primary  Bus: USB
    BD Address: 60:F2:62:1B:9C:74  ACL MTU: 1021:4  SCO MTU: 96:6
    UP RUNNING 
    RX bytes:16967 acl:0 sco:0 events:2751 errors:0
    TX bytes:678007 acl:0 sco:0 commands:2749 errors:0

hci0:   Type: Primary  Bus: USB
    BD Address: 5C:F3:70:9D:BC:07  ACL MTU: 1021:8  SCO MTU: 64:1
    UP RUNNING 
    RX bytes:1016 acl:0 sco:0 events:57 errors:0
    TX bytes:3679 acl:0 sco:0 commands:57 errors:0

我不是 BT 专家,但我没有看到任何让我感到震惊的东西。还有其他人吗? 如果有人能指出为什么这两个程序不能互相交流,我将非常感激


旧帖

我正在笔记本电脑上开发一些蓝牙 (BT)(普通蓝牙,而不是蓝牙低功耗)软件,为了在一台机器上测试它们,我购买了第二个 BT 适配器(华硕 USB-BT400)。插入后,我可以立即使用 hciconfig 看到它。

我尝试调整我的程序以使用正确的适配器,但它不起作用,我不知道为什么。我对BT编程很陌生,所以我可能误解了一些东西。为了让程序 A 使用地址为addr1 的适配器,我跑了

int dev_id = hci_devid("60:F2:62:1B:9C:74");
int err = hci_open_dev(dev_id);    
if(err < 0) {
    printf("error opening adapter device\n");
}

其中"60:F2:62:1B:9C:74"addr1。配套程序做了同样的事情,但使用了其他适配器地址。

当我运行这两个程序时,没有打印错误(意味着适配器被成功选择?)但程序什么也不做。过了一会儿,客户端程序打印出Uh Oh! The Host is Down如果有人能解释我在选择适配器时做错了什么,我将不胜感激。我还尝试在一台笔记本电脑上运行服务器,在另一台笔记本电脑上运行客户端,但那里也没有任何反应。在这种情况下,我没有明确选择 BT 适配器,因为我希望它默认为唯一可用的适配器。我没有考虑到示例代码可能是错误的,但如果有人看到任何错误,请指出。

完整的代码如下所示。我正在尝试使用服务器和客户端之间的 RFCOMM 连接运行一个简单的示例。该示例是从 Albert S. Huang 和 Larry Rudolph 的《Bluetooth Essentials for Programmers》一书中借用的,之后我尝试对其进行修改。


服务器程序

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>

int main(int argc, char **argv)
{
    struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
    char buf[1024] = { 0 };
    int s, client, bytes_read;
    socklen_t opt = sizeof(rem_addr);

    int dev_id = hci_devid("60:F2:62:1B:9C:74");
    int err = hci_open_dev(dev_id);    
    if(err < 0) {
        printf("error opening laptop device\n");
    }


    // allocate socket
    s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);

    // bind socket to port 1 of the first available 
    // local bluetooth adapter
    loc_addr.rc_family = AF_BLUETOOTH;
    loc_addr.rc_bdaddr = *BDADDR_ANY;
    loc_addr.rc_channel = (uint8_t) 1;
    bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));

    // put socket into listening mode
    listen(s, 1);

    // accept one connection
    client = accept(s, (struct sockaddr *)&rem_addr, &opt);

    ba2str( &rem_addr.rc_bdaddr, buf );
    fprintf(stderr, "accepted connection from %s\n", buf);
    memset(buf, 0, sizeof(buf));

    // read data from the client
    bytes_read = read(client, buf, sizeof(buf));
    if( bytes_read > 0 ) {
        printf("received [%s]\n", buf);
    }

    // close connection
    close(client);
    close(s);
    return 0;
}

客户端程序

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>

int main(int argc, char **argv)
{
    struct sockaddr_rc addr = { 0 };
    int s, status;
    char dest[18] = "60:F2:62:1B:9C:74";

    int dev_id = hci_devid("5C:F3:70:9D:BC:07");
    int err = hci_open_dev(dev_id);    
    if(err < 0) {
        printf("error opening adapter device\n");
    }

    // allocate a socket
    s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);

    // set the connection parameters (who to connect to)
    addr.rc_family = AF_BLUETOOTH;
    addr.rc_channel = (uint8_t) 1;
    str2ba( dest, &addr.rc_bdaddr );

    // connect to server
    status = connect(s, (struct sockaddr *)&addr, sizeof(addr));

    // send a message
    if( status == 0 ) {
        status = write(s, "hello!", 6);
    }

    if( status < 0 ) perror("uh oh");

    close(s);
    return 0;
}

【问题讨论】:

    标签: server bluetooth client adapter rfcomm


    【解决方案1】:

    好的,我在 Zephyr 的 slack 频道中从用户 @hje 和 @sjanc 那里得到了一些帮助。有几件事我必须改变。首先,我对strtoba 的用法改为str2bastrtoba 做了一些奇怪的交换。

    其次,即使是客户端程序也可以通过bind 指定使用哪个BT 适配器,类似于服务器程序的操作方式。在我的例子中,我首先启动服务器,然后客户端将被分配任何一个空闲的适配器。我不需要明确说明是哪个。

    最后,但绝对是最重要的一点,事实证明您必须指示 Linux 使 BT 适配器可被发现。我通过运行 hciconfig hci0 piscanhciconfig hci1 piscan 来做到这一点。

    最后完成程序:

    客户

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <bluetooth/bluetooth.h>
    #include <bluetooth/rfcomm.h>
    
    int main(int argc, char **argv)
    {
        struct sockaddr_rc addr = { 0 }, laddr = {0};
        int s, status;
        char dest[18]       = "60:F2:62:1B:9C:74";
    
        // allocate a socket
        s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
    
        // set the connection parameters (who to connect to)
        addr.rc_family = AF_BLUETOOTH;
        addr.rc_channel = (uint8_t) 1;
        str2ba( dest, &addr.rc_bdaddr );
    
        // connect to server
        status = connect(s, (struct sockaddr *)&addr, sizeof(addr));
    
        // send a message
        if( status == 0 ) {
            printf("successfully connected\n");
        }
    
        close(s);
        return 0;
    }
    
    

    服务器

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <bluetooth/bluetooth.h>
    #include <bluetooth/rfcomm.h>
    
    int main(int argc, char **argv)
    {
        struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
        char buf[1024] = { 0 };
        int s, client, bytes_read;
        socklen_t opt = sizeof(rem_addr);
    
        // I want to use the built in BT adapter
        const char* adapter = "60:F2:62:1B:9C:74";
    
        // allocate socket
        s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
    
        // bind socket to port 1 of the first available 
        // local bluetooth adapter
        loc_addr.rc_family = AF_BLUETOOTH;
        str2ba(adapter, &loc_addr.rc_bdaddr);
        loc_addr.rc_channel = (uint8_t) 1;
        bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
    
        // put socket into listening mode
        listen(s, 1);
    
        // accept one connection
        client = accept(s, (struct sockaddr *)&rem_addr, &opt);
    
        ba2str( &rem_addr.rc_bdaddr, buf );
        fprintf(stderr, "accepted connection from %s\n", buf);
        memset(buf, 0, sizeof(buf));
    
        // close connection
        close(client);
        close(s);
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-13
      • 1970-01-01
      • 2015-03-09
      • 1970-01-01
      • 1970-01-01
      • 2015-02-24
      • 2012-10-26
      • 2013-04-17
      相关资源
      最近更新 更多