petzval / btferret

Python and C Bluetooth Library
MIT License
127 stars 22 forks source link

Race condition when btferret starts for the first time #26

Closed gregoiregentil closed 8 months ago

gregoiregentil commented 1 year ago

During the boot sequence of my embedded device on which I run btferret, I need to run a Broadcom script to load the Bluetooth firmware. In my app, I wait for hci0 to come up:

socket(31, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, BTPROTO_HCI);
while (failure) {
    ioctl(dd, HCIGETDEVINFO, (void*) &di);
    check di info
}
init_blue();
le_server(le_callback, 0);

Then, the device advertises correctly and I can see the advertisement on a phone or a PC. btferret outputs "Listening for LE clients to connect (x=stop server)". No problem so far.

But if I connect from that phone or PC, nothing is received by btferret. log doesn't show any "< HCI OGF=08 OCF=0A" when the connection is tried from the phone.

I need to insert a sleep between 1 and 5 seconds before calling init_blue and then btferret can successfully receive data from the adapter.

Obviously, If I start my app manually a "long time" after boot, everything works correctly including a device connection.

How could I debug this situation? Or more interestingly, what do I need to check to confirm it's not too early to start btferret during the boot sequence?

petzval commented 1 year ago

A client device running btferret connects immediately to a server that calls init_blue/le_server. Advertisement starts immediately when le_server is called, and the server will then accept a connection immediately. So the problem would seem to be with Android. With Android and Windows I have noticed large delays in seeing a device when they scan for LE devices. The advertising interval may have an effect. It is currently set to 320ms. Change to 30ms by editing leadparam:


leadparam[] = .....  00 02 00 02        200=320ms
change to
leadparam[] = ..... 30 00 30 00         30=30ms
petzval commented 1 year ago

Another point. When an LE server connects, it disables advertising but btferret immediately re-enables it so that multiple clients can connect simultaneously. This may be using resources. Stop btferret doing it as follows:

line 3220 in le_server()

if(op == LE_CONNECT)
  {
  VPRINT ....
  mesh_on();   ****   REMOVE this - it re-enables advertising