Re: connect() returning EINPROGRESS

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Marcel,

> do you have a dead simple proof-of-concept that can show this issue. I do not recall any of this issue. Have you tried it with the latest bluetooth-next kernel?

I have only tried it with bluez 5.37 under kernel "4.4.0-21-generic #37-Ubuntu
SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux", and
bluez 4.101 under kernel "3.13.0-85-generic #129-Ubuntu SMP Thu Mar 17
20:50:41 UTC 2016 i686 i686 i686 GNU/Linux".

I have created a test that I think is reasonably close to being as simple as
possible for showing the issue (or possible issue, I could certainly have some
misunderstanding of part of the API that just happens to not cause a problem
with the older bluez).  I have attached the test code, although it
finds and opens
a custom device which of course you won't have.  Probably modifying it to find
some other connectable device would show the same issue but I haven't tried
so can't say that for certain.

The output of the test code with bluez 4.101 is:
found device
hci_le_create_connn okay
Connected

And the output with bluez 5.37 is:
found device
hci_le_create_connn okay
attconnect failed errno 115: Operation now in progress

That last line, showing that attconnect failed, takes something on the order
of a minute to appear.


All of this came up when my client wanted to replicate a test system and
attempted to do so starting with a current ubuntu install.  They ended up
just installing an older ubuntu instead so they don't need this fixed.  This
also means I no longer have the bluez 5.37 install that showed the problem
since an older one has been installed over it, but if there's something
specific to look at I'll attempt to recreate that test when time permits.

allan


-- 
Allan Hessenflow            allan@xxxxxxxxxxxx
/* blueztest.c */


#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <errno.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/l2cap.h>



#define NIXIE_NAME              "Nixie_Engr_A"


#define EIR_FLAGS               0x01
#define EIR_UUID16_SOME         0x02
#define EIR_UUID16_ALL          0x03
#define EIR_NAME_SHORT          0x08
#define EIR_NAME_COMPLETE       0x09


static const char usage[] =
    "usage: %s [-j<dev>]\n"
    "    -i<ifnum>      use interface hci<ifnum>\n"
    ;



int main(int argc, char *argv[]) {
    int result;
    int hciInterface;
    int hcifd;
    uint16_t handle;
    int attSock;
    struct hci_filter filter;
    struct sockaddr_l2 src, dst;
    struct bt_security btsec;
    uint8_t devBdAddrType;
    bdaddr_t devBdAddr;
    int len;
    bool scanning;
    bool found;
    bool connected;
    hci_event_hdr *header;
    evt_le_meta_event *meta;
    le_advertising_info *info;
    uint8_t dataLen, dataType;
    unsigned char buf[HCI_MAX_EVENT_SIZE];
    int count;
    int i, j, k;

    result = 0;

    hciInterface = hci_get_route(NULL);
    hcifd = -1;
    attSock = -1;
    scanning = false;
    found = false;
    connected = false;

    for (i = 1; i < argc && result == 0; i++) {
        if (argv[i][0] == '-') {
            switch (argv[i][1]) {
            case 'i':
                hciInterface = atoi(&argv[i][2]);
                break;
            default:
                result = 1;
            }
        } else {
            result = 1;
        }
    }
    if (result)
        fprintf(stderr, usage, argv[0]);


    if (result == 0) {
        hcifd = hci_open_dev(hciInterface);
        if (hcifd < 0) {
            fprintf(stderr, "failed to open hci%d\n", hcifd);
            result = 1;
        }
    }
    if (result == 0) {
        if (hci_le_set_scan_parameters(hcifd, 0x01, htobs(0x0010),
                                       htobs(0x0010), 0x00, 0x00,
                                       1000) < 0) {
            fprintf(stderr, "failed to set scan parameters\n");
            result = 1;
        }
    }
    if (result == 0) {
        if (hci_le_set_scan_enable(hcifd, 0x01, 1, 1000) < 0) {
            fprintf(stderr, "failed to enable scan\n");
            result = 1;
        } else
            scanning = true;
    }
    if (result == 0) {
        hci_filter_clear(&filter);
        hci_filter_set_ptype(HCI_EVENT_PKT, &filter);
        hci_filter_set_event(EVT_LE_META_EVENT, &filter);
        if (setsockopt(hcifd, SOL_HCI, HCI_FILTER,
                       &filter, sizeof(filter)) < 0) {
            fprintf(stderr, "failed to set filter\n");
            result = 1;
        }
    }

    if (result == 0) {
        attSock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
        if (attSock < 0) {
            fprintf(stderr, "failed to create att socket\n");
            result = 1;
        }
    }
    if (result == 0) {
        memset(&src, 0, sizeof(src));
        src.l2_family = AF_BLUETOOTH;
        src.l2_cid = htobs(/*ATT_CID*/4);
        src.l2_bdaddr_type = BDADDR_LE_PUBLIC;
        memcpy(&src.l2_bdaddr, BDADDR_ANY, sizeof(src.l2_bdaddr));
        if (bind(attSock, (struct sockaddr *) &src, sizeof(src)) < 0) {
            fprintf(stderr, "failed to bind att socket\n");
            result = 1;
        }
    }
    if (result == 0) {
        memset(&btsec, 0, sizeof(btsec));
        btsec.level = BT_SECURITY_LOW;
        if (setsockopt(attSock, SOL_BLUETOOTH, BT_SECURITY, &btsec,
                       sizeof(btsec)) != 0) {
            fprintf(stderr, "failed to set att socket options\n");
            result = -1;
        }
    }

    while (result == 0 && !found) {
        len = read(hcifd, buf, sizeof(buf));
        if (len >= HCI_EVENT_HDR_SIZE) {
            header = (hci_event_hdr *) buf;
            switch (header->evt) {
            case HCI_EVENT_PKT:
                i = 1 + HCI_EVENT_HDR_SIZE;
                meta = (evt_le_meta_event *) &buf[i];
                i += 1 + EVT_LE_META_EVENT_SIZE;
                switch (meta->subevent) {
                case EVT_LE_ADVERTISING_REPORT:
                    count = meta->data[0];
                    while (count-- && !found) {
                        info = (le_advertising_info *) &buf[i];
                        j  = 0;
                        while (j + 1 < info->length && !connected &&
                               result == 0) {
                            dataLen = info->data[j];
                            dataType = info->data[j + 1];
                            if (j + dataLen + 1 <= info->length) {
                                switch (dataType) {
                                case EIR_NAME_SHORT:
                                case EIR_NAME_COMPLETE:
                                    k = dataLen - 1;
                                    if (k > sizeof(NIXIE_NAME) - 1)
                                        k = sizeof(NIXIE_NAME) - 1;
                                    if (k > 0 && memcmp(&info->data[j + 2],
                                                        NIXIE_NAME, k) == 0) {
                                        fprintf(stderr, "found device\n");
                                        found = true;
                                    }
                                    break;
                                }
                            }
                            j += dataLen + 1;
                        }
                        i += LE_ADVERTISING_INFO_SIZE + 2 + info->length;
                    }

                    break;
                default:
                    fprintf(stderr, "unhandled le meta subevent 0x%02x\n",
                            (unsigned int) meta->subevent);
                    break;
                }
                break;
            default:
                fprintf(stderr, "unhandled event 0x%02x\n",
                        (unsigned int) header->evt);
                break;
            }
        }
    }
    if (found && result == 0) {
        if (scanning) {
            if (hci_le_set_scan_enable(hcifd, 0x00, 1, 1000) < 0)
                fprintf(stderr, "stop scan failed\n");
            scanning = false;
        }
             
    }
    if (found && result == 0) {
        devBdAddrType = info->bdaddr_type;
        memcpy(&devBdAddr, &info->bdaddr,
               sizeof(devBdAddr));
        if (hci_le_create_conn(hcifd, htobs(4), htobs(4),
                               0, info->bdaddr_type,
                               info->bdaddr,
                               LE_PUBLIC_ADDRESS/*BISON*/,
                               htobs(15), htobs(15), htobs(0),
                               htobs(100), htobs(1), htobs(1),
                               &handle, 1000) >= 0) {
            fprintf(stderr, "hci_le_create_connn okay\n");
            connected = true;
            memset(&dst, 0, sizeof(dst));
            dst.l2_family = AF_BLUETOOTH;
            dst.l2_cid = htobs(/*ATT_CID*/4);
            dst.l2_bdaddr_type = devBdAddrType;
            memcpy(&dst.l2_bdaddr, &devBdAddr, sizeof(dst.l2_bdaddr));
            if (connect(attSock, (struct sockaddr *) &dst, sizeof(dst)) < 0) {
                fprintf(stderr, "attconnect failed errno %d: %s\n",
                        errno, strerror(errno));
                 result = 1;
            } else {
                fprintf(stderr, "Connected\n");
            }
        } else {
            fprintf(stderr, "hci_le_create_conn failed\n");
            result = 1;
        }
    }

    if (attSock != -1)
        close(attSock);
    if (scanning)
        hci_le_set_scan_enable(hcifd, 0x00, 1, 1000);
    if (connected)
        hci_disconnect(hcifd, handle,
                       HCI_OE_USER_ENDED_CONNECTION, 1000);

    if (hcifd != -1)
        hci_close_dev(hcifd);

    return result;
}

Attachment: Makefile
Description: Binary data


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux