bluetooth icon indicating copy to clipboard operation
bluetooth copied to clipboard

CYW43439 adapter cannot be configured in conjunction with WiFi via x/bluetooth API

Open kortschak opened this issue 1 year ago • 4 comments

The CYW43439 adapter can have one of three firmwares flashed: bluetooth, wifi and both. The way that the driver package is written at the moment means that the last call to (*cyw43439.Device).Init wins; the returned device from cyw43439.NewPicoWDevice() is local, but shares the backing flashed firmware, resulting in unexpected behaviour. This mixed scope needs some way to be resolved and this would need to happen in the cyw43439 package, but the issue is surfaced here, so this is why I'm raising it here.

ISTM that the best way to do this would be to expose the firmware flash operation in the API and make it so that multiple calls to flash can only succeed if they flash compatible firmware, subsequent valid flash calls would be no-ops. This would allow the client code to flash the desired firmware and then the flash call that come from calling bluetooth.Default.Adapter would either succeed (if the bluetooth or the wifi+bluetooth firmware had already been flashed, or none had been flashed) or fail (if only the wifi firmware had been flashed).

/cc @soypat

kortschak avatar Jan 01 '25 21:01 kortschak

A demonstrator is available here.

To demonstrate, first show that the code works in Bluetooth only mode:

  1. In one terminal
    $ tinygo flash -target pico-w -stack-size=8kb -monitor -x ./receiver
    
  2. In another
    $ go run ./sender
    
  3. Confirm that the Pico W emits the expected text (this requires that the local code run at least twice), and the local code behaves as expected (does not require a second run).

Then taking note of the comment here try the same thing as above, but either with the dev := cyw43439.NewPicoWDevice(); dev.Init(cyw43439.DefaultWifiBluetoothConfig()) before or after the adapter.Enable(), and note that neither work.

kortschak avatar Jan 08 '25 00:01 kortschak

I designed the CYW43439 driver to easily interface with wifi/bluetooth stacks. I believe ideally this issue and many future ones could be solved by exposing the BT adapter creation API. Automatic hardware initialization simplifies user experience but also makes other things very difficult or impossible to do. It seems there is a workaround in this case due to how the CYW43439 hardware works but this might not always be the case for every future hardware! This issue needs to be solved on the bluetooth package side by exposing a hardware abstraction layer that does no automatic initialization and expects an already initialized HCI BT device. This should also be MUCH easier to test!

func (d *Device) ReadHCI(b []byte) (int,error)
func (d *Device) WriteHCI(b []byte) (int,error)
func (d *Device) BufferedHCI() int

// These two function calls are what the bluetooth API does automatically with some build tag magic. Ideally users 
// should be able to choose whether to let an external package do hardware initialization or to do it themselves.

var d *Device = NewDevice()
d.InitWithWifiAndBluetooth()

var adapter bluetooth.Adapter = bluetooth.NewHCIAdapter(d)
// use adapter below.

soypat avatar Jan 17 '25 12:01 soypat

It seems there is a workaround in this case due to how the CYW43439 hardware works

I looked in the margin, but could not find this work-around. Do you mean a work-around that requires changes to the bluetooth/cyw43439 packages, or one that works now?

kortschak avatar Jan 17 '25 20:01 kortschak

The workaround I refer to is editing cyw43439 package so that the last call is the persistent one (your suggested edit)

soypat avatar Jan 18 '25 12:01 soypat