Cancelling retransmissions on a L2CAP socket

1.9k Views Asked by At

I was wondering if anyone can assist me with a problem that I have with C Bluetooth programming (Linux Bluez). I am using Ubuntu 10.04, BlueZ 4.60. My goal is to have a L2CAP socket in which there will be minimal delay for sending data between 2 computers. So far I managed to open an L2CAP socket, but this socket has endless retransmissions and I'm trying to change it. I want to have no retransmissions at all because I need the data to be transfer fast with minimal delay and the reliability of the data is not important.

I found an example online that deals with changing the flush timout for the socket and by that causing that if a packet is not acked after a certain period of time it is dropped and the next data in the buffer is sent. The problem is that this example doesn't work :-(

Here is my code, this method is called after the bind command:

    int set_flush_timeout(bdaddr_t *ba, int timeout)
    {
    int err = 0, dd, dev_id;
    struct hci_conn_info_req *cr = 0;
    struct hci_request rq = { 0 };

    struct {
        uint16_t handle;
        uint16_t flush_timeout;
    } cmd_param;

    struct {
        uint8_t  status;
        uint16_t handle;
    } cmd_response;

    // find the connection handle to the specified bluetooth device
    cr = (struct hci_conn_info_req*) malloc(
                sizeof(struct hci_conn_info_req) +
                sizeof(struct hci_conn_info));
    bacpy( &cr->bdaddr, ba );
    cr->type = ACL_LINK;
    dev_id = hci_get_route( NULL);
    dd = hci_open_dev( dev_id );
    if( dd < 0 ) {
        err = dd;
        goto cleanup;
    }

    err = ioctl(dd, HCIGETCONNINFO, (unsigned long) cr );
    if( err ) goto cleanup;

    // build a command packet to send to the bluetooth microcontroller
    cmd_param.handle = cr->conn_info->handle;
    cmd_param.flush_timeout = htobs(timeout);
    rq.ogf = OGF_HOST_CTL;
    rq.ocf = 0x28;
    rq.cparam = &cmd_param;
    rq.clen = sizeof(cmd_param);
    rq.rparam = &cmd_response;
    rq.rlen = sizeof(cmd_response);
    rq.event = EVT_CMD_COMPLETE;

    // send the command and wait for the response
    err = hci_send_req( dd, &rq, 1 );
    if( err ) goto cleanup;

    if( cmd_response.status ) {
        err = -1;
        errno = bt_error(cmd_response.status);
    }

cleanup:
    free(cr);
    if( dd >= 0) close(dd);
    return err;
}

What is my mistake? Does anyone know another option that will solve my problem. Code examples will also be great!!

1

There are 1 best solutions below

4
On

This code to set the automatic flush time out seems to be correct. You can make sure by ensuring that you are getting "Success" in response to this command's command complete event.

I suspect that the issue might be in your packet sending code, note that for the automatic flush timeout to take effect the individual packets should be marked as automatically flushable, The HCI data packet has the Packet_Boundary_Flag which you can sent to indicate if individual packets are flushable.

Also note that the Flush timeout has to be large enough to allow for enough time so that the packets gets a transmission attempt, the way the flush timeout are defined can cause the packet to be flushed even without the packet being transmitted even once, so you need to tune it. By definition Flush timeout start when the packet is Queued for transmission.