edrosten / libblepp

Modern clean C++ Bluetooth Low Energy on Linux without the Bluez DBUS API
Other
239 stars 62 forks source link

Add MTU Renegotiaton #38

Closed dylanetaft closed 5 years ago

dylanetaft commented 5 years ago

I am working on adding MTU negotiation See issue #31

In the PDUResponse handling code in the state machine, we need to add code to setsockopt with new MTU values. However, when I try this, I get errno 22.

I created a test case outside of libblepp, and get the same errors. That end bit - setsockopt - that is where it runs into trouble. Anyone have any thoughts on this, or can someone try it? You can update the code for your needs devaddr - hci device address you want to use per hciconfig connectto - gatt server device address.

include

include

include <sys/types.h>

include <sys/socket.h>

include <bluetooth/bluetooth.h>

include <bluetooth/l2cap.h>

include <bluetooth/hci.h>

include <bluetooth/hci_lib.h>

include

int main() { sockaddr_l2 sba; sockaddr_l2 addr; bdaddr_t btsrc_addr; int sock; int retval; memset(&sba, 0, sizeof(sba)); std::string devaddr = "00:15:83:EA:57:D8"; std::string connectto = "00:0B:57:7F:72:BF"; sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); int dev_id = hci_devid(devaddr.c_str()); //obtain device id from HCI device name hci_devba(dev_id, &btsrc_addr); bacpy(&sba.l2_bdaddr,&btsrc_addr); //lifted from bluez example, populate src sockaddr with address of desired device sba.l2_family=AF_BLUETOOTH; sba.l2_cid = htobs(4); //Spec 4.0 G.5.2.2 sba.l2_bdaddr_type = BDADDR_LE_PUBLIC; retval = bind(sock, (sockaddr)&sba , sizeof(sba)); std::cout << retval << "\n"; memset(&addr, 0, sizeof(addr)); addr.l2_family = AF_BLUETOOTH; addr.l2_psm = 0; addr.l2_cid = htobs(4); //Spec 4.0 G.5.2.2 addr.l2_bdaddr_type = BDADDR_LE_PUBLIC; int rr = str2ba(connectto.c_str(), &addr.l2_bdaddr); retval = connect(sock, (sockaddr)&addr, sizeof(addr)); std::cout << retval << "\n";

//set socket options
l2cap_options options;
socklen_t len = sizeof(options);
memset(&options, 0, len);
retval = getsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, &options, &len);
socklen_t len2 = sizeof(options);

int checksock = 0;
socklen_t errlen;
errlen = sizeof(checksock);
getsockopt(sock, SOL_SOCKET, SO_ERROR, &checksock, &errlen);
std::cout << strerror(checksock) << "\n"; //confirm socket is in an OK state
int s_status = setsockopt(sock, SOL_L2CAP, L2CAP_OPTIONS, &options, sizeof(options));

std::cout << errno << "," << strerror(errno) << "\n";

}

dylanetaft commented 5 years ago

Soooo.... I mailed the Linux Kernel Bluetooth mailing list. There's a kernel thing preventing implementing this - setsockopt(sock, SOL_BLUETOOTH, BT_RCVMTU, &options, len) is the new way to do this in BT4, but it's blocked on open connections, and BT_SNDMTU can't be set at all.

dylanetaft commented 5 years ago

Yikes I am dumb. This is for ATT, so the negotiation is in userspace. Nothing to do with sockopts. This library is using the ATT default MTU so it’s just a matter of sending over the lower value and adding a //TODO support larger ATT MTUs

dylanetaft commented 5 years ago

Pull request #39 submitted!

edrosten commented 5 years ago

merged.