From 58cefb4d2e7f9c22a21fa8c8ba20e5f942e3676b Mon Sep 17 00:00:00 2001 From: Tasos Papalyras Date: Wed, 2 Oct 2024 00:43:35 +0300 Subject: [PATCH 1/7] MTU exchange --- adapter_nrf528xx-full.go | 32 ++++++++++++++++++++++++-- adapter_nrf528xx-peripheral.go | 2 +- adapter_nrf528xx.go | 37 ++++++++++++++++++++++++++++++ adapter_sd.go | 41 +++++++++++++++++++++++++++++++++- gap_nrf528xx-advertisement.go | 2 +- gap_nrf528xx-central.go | 9 +++++++- gatts_sd.go | 2 +- 7 files changed, 118 insertions(+), 7 deletions(-) diff --git a/adapter_nrf528xx-full.go b/adapter_nrf528xx-full.go index bdeaacf4..d0eabacd 100644 --- a/adapter_nrf528xx-full.go +++ b/adapter_nrf528xx-full.go @@ -17,6 +17,12 @@ import ( "unsafe" ) +// TODO: @rdnt cleanup +//var ( +// dataLenParams = &C.ble_gap_data_length_params_t{} +// dataLenLimitation = &C.ble_gap_data_length_limitation_t{} +//) + func handleEvent() { id := eventBuf.header.evt_id switch { @@ -63,7 +69,7 @@ func handleEvent() { // because it would need to be reconfigured as a non-connectable // advertisement. That's left as a future addition, if // necessary. - C.sd_ble_gap_adv_start(defaultAdvertisement.handle, C.BLE_CONN_CFG_TAG_DEFAULT) + C.sd_ble_gap_adv_start(defaultAdvertisement.handle, connCfgTag) } device := Device{ connectionHandle: gapEvent.conn_handle, @@ -159,7 +165,16 @@ func handleEvent() { case C.BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: // This event is generated by some devices. While we could support // larger MTUs, this default MTU is supported everywhere. - C.sd_ble_gatts_exchange_mtu_reply(gattsEvent.conn_handle, C.BLE_GATT_ATT_MTU_DEFAULT) + rsp := gattsEvent.params.unionfield_exchange_mtu_request() + effectiveMtu := min(DefaultAdapter.cfg.Gatt.AttMtu, uint16(rsp.client_rx_mtu)) + if debug { + println("mtu exchange requested. self:", DefaultAdapter.cfg.Gatt.AttMtu, ", peer:", rsp.client_rx_mtu, ", effective:", effectiveMtu) + } + + var errCode = C.sd_ble_gatts_exchange_mtu_reply(gattsEvent.conn_handle, C.uint16_t(effectiveMtu)) + if debug { + println("mtu exchange replied, err:", Error(errCode).Error()) + } case C.BLE_GATTS_EVT_HVN_TX_COMPLETE: // ignore confirmation of a notification successfully sent default: @@ -255,6 +270,12 @@ func handleEvent() { } } } + + case C.BLE_GATTC_EVT_EXCHANGE_MTU_RSP: + if debug { + rsp := gattcEvent.params.unionfield_exchange_mtu_rsp() + println("mtu exchanged, effective mtu:", rsp.server_rx_mtu) + } default: if debug { println("unknown GATTC event:", id, id-C.BLE_GATTC_EVT_BASE) @@ -266,3 +287,10 @@ func handleEvent() { } } } + +func min(a, b uint16) uint16 { + if a < b { + return a + } + return b +} diff --git a/adapter_nrf528xx-peripheral.go b/adapter_nrf528xx-peripheral.go index 00860df6..cd094a2a 100644 --- a/adapter_nrf528xx-peripheral.go +++ b/adapter_nrf528xx-peripheral.go @@ -47,7 +47,7 @@ func handleEvent() { // because it would need to be reconfigured as a non-connectable // advertisement. That's left as a future addition, if // necessary. - C.sd_ble_gap_adv_start(defaultAdvertisement.handle, C.BLE_CONN_CFG_TAG_DEFAULT) + C.sd_ble_gap_adv_start(defaultAdvertisement.handle, connCfgTag) } device := Device{ connectionHandle: gapEvent.conn_handle, diff --git a/adapter_nrf528xx.go b/adapter_nrf528xx.go index 557699d8..0cbd3f5d 100644 --- a/adapter_nrf528xx.go +++ b/adapter_nrf528xx.go @@ -31,6 +31,8 @@ var clockConfigXtal C.nrf_clock_lf_cfg_t = C.nrf_clock_lf_cfg_t{ accuracy: C.NRF_CLOCK_LF_ACCURACY_250_PPM, } +const connCfgTag uint8 = 1 + //go:extern __app_ram_base var appRAMBase [0]uint32 @@ -47,6 +49,41 @@ func (a *Adapter) enable() error { // Enable the BLE stack. appRAMBase := C.uint32_t(uintptr(unsafe.Pointer(&appRAMBase))) + + bleCfg := C.ble_cfg_t{} + + connCfg := bleCfg.unionfield_conn_cfg() + connCfg.conn_cfg_tag = connCfgTag + + gattCfg := connCfg.params.unionfield_gatt_conn_cfg() + gattCfg.att_mtu = a.cfg.Gatt.AttMtu + + errCode = C.sd_ble_cfg_set(C.uint32_t(C.BLE_CONN_CFG_GATT), &bleCfg, appRAMBase) + if debug { + println("gatt config updated, err:", Error(errCode).Error()) + } + + l2capCfg := connCfg.params.unionfield_l2cap_conn_cfg() + l2capCfg.rx_mps = a.cfg.L2cap.RxMps + l2capCfg.tx_mps = a.cfg.L2cap.TxMps + l2capCfg.rx_queue_size = a.cfg.L2cap.RxQueueSize + l2capCfg.tx_queue_size = a.cfg.L2cap.TxQueueSize + l2capCfg.ch_count = a.cfg.L2cap.ChCount // TODO: @rdnt max 18? 20 crashes + + errCode = C.sd_ble_cfg_set(C.uint32_t(C.BLE_CONN_CFG_L2CAP), &bleCfg, appRAMBase) + if debug { + println("l2cap config updated, err:", Error(errCode).Error()) + } + + gapCfg := connCfg.params.unionfield_gap_conn_cfg() + gapCfg.conn_count = a.cfg.Gapp.ConnCount + gapCfg.event_length = a.cfg.Gapp.EventLength + + errCode = C.sd_ble_cfg_set(C.uint32_t(C.BLE_CONN_CFG_GAP), &bleCfg, appRAMBase) + if debug { + println("gap config updated, err:", Error(errCode).Error()) + } + errCode = C.sd_ble_enable(&appRAMBase) return makeError(errCode) } diff --git a/adapter_sd.go b/adapter_sd.go index 4037ed9b..7aca9709 100644 --- a/adapter_sd.go +++ b/adapter_sd.go @@ -33,7 +33,7 @@ var currentConnection = volatileHandle{handle: volatile.Register16{C.BLE_CONN_HA // Globally allocated buffer for incoming SoftDevice events. var eventBuf struct { C.ble_evt_t - buf [23]byte + buf [247]byte } func init() { @@ -49,6 +49,8 @@ type Adapter struct { charWriteHandlers []charWriteHandler connectHandler func(device Device, connected bool) + + cfg Config } // DefaultAdapter is the default adapter on the current system. On Nordic chips, @@ -62,6 +64,39 @@ var DefaultAdapter = &Adapter{isDefault: true, var eventBufLen C.uint16_t +type Config struct { + Gapp GapConfig + Gatt GattConfig + L2cap L2capConfig +} + +type GapConfig struct { + ConnCount uint8 + EventLength uint16 +} + +type GattConfig struct { + AttMtu uint16 +} + +type L2capConfig struct { + RxMps uint16 + TxMps uint16 + RxQueueSize uint8 + TxQueueSize uint8 + ChCount uint8 +} + +func (a *Adapter) Configure(cfg Config) error { + if cfg.Gatt.AttMtu < 23 || cfg.Gatt.AttMtu > 247 { + cfg.Gatt.AttMtu = 23 + } + + a.cfg = cfg + + return nil +} + // Enable configures the BLE stack. It must be called before any // Bluetooth-related calls (unless otherwise indicated). func (a *Adapter) Enable() error { @@ -75,6 +110,10 @@ func (a *Adapter) Enable() error { eventBufLen = C.uint16_t(unsafe.Sizeof(eventBuf)) errCode := C.sd_ble_evt_get((*C.uint8_t)(unsafe.Pointer(&eventBuf)), &eventBufLen) if errCode != 0 { + // TODO: @rdnt remove + //if debug { + // println("sd_ble_evt_get failed, err:", Error(errCode).Error()) + //} // Possible error conditions: // * NRF_ERROR_NOT_FOUND: no events left, break // * NRF_ERROR_DATA_SIZE: retry with a bigger data buffer diff --git a/gap_nrf528xx-advertisement.go b/gap_nrf528xx-advertisement.go index 1d726042..d6ebf7d1 100644 --- a/gap_nrf528xx-advertisement.go +++ b/gap_nrf528xx-advertisement.go @@ -74,7 +74,7 @@ func (a *Advertisement) Configure(options AdvertisementOptions) error { // Start advertisement. May only be called after it has been configured. func (a *Advertisement) Start() error { a.isAdvertising.Set(1) - errCode := C.sd_ble_gap_adv_start(a.handle, C.BLE_CONN_CFG_TAG_DEFAULT) + errCode := C.sd_ble_gap_adv_start(a.handle, connCfgTag) return makeError(errCode) } diff --git a/gap_nrf528xx-central.go b/gap_nrf528xx-central.go index a0c8db78..d017eb51 100644 --- a/gap_nrf528xx-central.go +++ b/gap_nrf528xx-central.go @@ -12,6 +12,7 @@ import ( /* #include "ble_gap.h" +#include "ble_gattc.h" */ import "C" @@ -162,7 +163,7 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (Device, err connectionAttempt.state.Set(1) // Start the connection attempt. We'll get a signal in the event handler. - errCode := C.sd_ble_gap_connect(&addr, &scanParams, &connectionParams, C.BLE_CONN_CFG_TAG_DEFAULT) + errCode := C.sd_ble_gap_connect(&addr, &scanParams, &connectionParams, connCfgTag) if errCode != 0 { connectionAttempt.state.Set(0) return Device{}, Error(errCode) @@ -175,6 +176,12 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (Device, err // Successfully connected. connectionAttempt.state.Set(0) connectionHandle := connectionAttempt.connectionHandle + + errCode = C.sd_ble_gattc_exchange_mtu_request(connectionHandle, C.uint16_t(a.cfg.Gatt.AttMtu)) + if debug { + println("mtu requested, self:", a.cfg.Gatt.AttMtu, " err:", Error(errCode).Error()) + } + return Device{ connectionHandle: connectionHandle, }, nil diff --git a/gatts_sd.go b/gatts_sd.go index 602aa24d..db57c9a2 100644 --- a/gatts_sd.go +++ b/gatts_sd.go @@ -63,7 +63,7 @@ func (a *Adapter) AddService(service *Service) error { }, init_len: C.uint16_t(len(char.Value)), init_offs: 0, - max_len: 20, // This is a conservative maximum length. + max_len: C.BLE_GATTS_FIX_ATTR_LEN_MAX, } if len(char.Value) != 0 { value.p_value = (*C.uint8_t)(unsafe.Pointer(&char.Value[0])) From 7749d05dc143e45cf029539868732f47412f8ae9 Mon Sep 17 00:00:00 2001 From: Tasos Papalyras Date: Sat, 5 Oct 2024 17:33:43 +0300 Subject: [PATCH 2/7] Manual exchange request --- adapter_nrf528xx-full.go | 27 +++++++++++++++++++++- gap_nrf528xx-central.go | 49 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 71 insertions(+), 5 deletions(-) diff --git a/adapter_nrf528xx-full.go b/adapter_nrf528xx-full.go index d0eabacd..e1fd9a7a 100644 --- a/adapter_nrf528xx-full.go +++ b/adapter_nrf528xx-full.go @@ -48,6 +48,7 @@ func handleEvent() { } connectionAttempt.connectionHandle = gapEvent.conn_handle connectionAttempt.state.Set(2) // connection was successful + mtuExchangeAttempt.state.Set(0) DefaultAdapter.connectHandler(device, true) } case C.BLE_GAP_EVT_DISCONNECTED: @@ -270,12 +271,36 @@ func handleEvent() { } } } - case C.BLE_GATTC_EVT_EXCHANGE_MTU_RSP: + rsp := gattcEvent.params.unionfield_exchange_mtu_rsp() + if debug { + println("mtu exchanged, effective mtu:", rsp.server_rx_mtu) + } + + mtuExchangeAttempt.effectiveMtu = uint16(rsp.server_rx_mtu) + mtuExchangeAttempt.state.Set(2) // mtu exchange was successful + if debug { rsp := gattcEvent.params.unionfield_exchange_mtu_rsp() println("mtu exchanged, effective mtu:", rsp.server_rx_mtu) } + case C.BLE_GATTC_EVT_TIMEOUT: + timeoutEvt := gattcEvent.params.unionfield_timeout() + switch timeoutEvt.src { + case C.BLE_GATT_TIMEOUT_SRC_PROTOCOL: + // Failed to connect to a peripheral. + if debug { + println("gattc timeout: src protocol") + } + mtuExchangeAttempt.state.Set(3) // mtu exchange timed out + default: + // For example a scan timeout. + if debug { + println("gattc timeout: other") + } + } + case C.BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE: + // no op default: if debug { println("unknown GATTC event:", id, id-C.BLE_GATTC_EVT_BASE) diff --git a/gap_nrf528xx-central.go b/gap_nrf528xx-central.go index d017eb51..7d32531b 100644 --- a/gap_nrf528xx-central.go +++ b/gap_nrf528xx-central.go @@ -100,6 +100,11 @@ var connectionAttempt struct { connectionHandle C.uint16_t } +var mtuExchangeAttempt struct { + state volatile.Register8 // 0 means unused, 1 means in progress, 2 means exchanged, 3 means timeout + effectiveMtu uint16 +} + // Connect starts a connection attempt to the given peripheral device address. // // Limitations on Nordic SoftDevices inclue that you cannot do more than one @@ -177,10 +182,11 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (Device, err connectionAttempt.state.Set(0) connectionHandle := connectionAttempt.connectionHandle - errCode = C.sd_ble_gattc_exchange_mtu_request(connectionHandle, C.uint16_t(a.cfg.Gatt.AttMtu)) - if debug { - println("mtu requested, self:", a.cfg.Gatt.AttMtu, " err:", Error(errCode).Error()) - } + // TODO @rdnt: move into exchangeMTU function + //errCode = C.sd_ble_gattc_exchange_mtu_request(connectionHandle, C.uint16_t(a.cfg.Gatt.AttMtu)) + //if debug { + // println("mtu requested, self:", a.cfg.Gatt.AttMtu, " err:", Error(errCode).Error()) + //} return Device{ connectionHandle: connectionHandle, @@ -197,6 +203,41 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (Device, err } } +// ExchangeMTU starts an MTU exchange request procedure. The effective MTU +// (the maximum value supported by both parties) is returned. +func (d Device) ExchangeMTU(mtu uint16) (uint16, error) { + if mtuExchangeAttempt.state.Get() == 2 { + return 0, errors.New("mtu already exchanged") + } + + if mtuExchangeAttempt.state.Get() == 1 { + return 0, errors.New("mtu exchange in progress") + } + + mtuExchangeAttempt.state.Set(1) + + errCode := C.sd_ble_gattc_exchange_mtu_request(d.connectionHandle, C.uint16_t(mtu)) + if errCode != 0 { + mtuExchangeAttempt.state.Set(0) + return 0, Error(errCode) + } + + for { + state := mtuExchangeAttempt.state.Get() + if state == 2 { + return mtuExchangeAttempt.effectiveMtu, nil + } else if state == 3 { + // Timeout while exchanging mtu + mtuExchangeAttempt.state.Set(0) + return 0, errors.New("mtu exchange timeout") + } else { + // TODO: use some sort of condition variable once the scheduler + // supports them. + arm.Asm("wfe") + } + } +} + // Disconnect from the BLE device. func (d Device) Disconnect() error { errCode := C.sd_ble_gap_disconnect(d.connectionHandle, C.BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION) From 1388e50113a33e56fb874b883fa1ca8b2d2d2ffd Mon Sep 17 00:00:00 2001 From: Tasos Papalyras Date: Mon, 7 Oct 2024 00:09:58 +0300 Subject: [PATCH 3/7] Configure error handling, document fields --- adapter_nrf528xx.go | 28 ++++++++++++++-------------- adapter_sd.go | 35 +++++++++++++++++++++++++---------- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/adapter_nrf528xx.go b/adapter_nrf528xx.go index 0cbd3f5d..df89f3e5 100644 --- a/adapter_nrf528xx.go +++ b/adapter_nrf528xx.go @@ -55,12 +55,21 @@ func (a *Adapter) enable() error { connCfg := bleCfg.unionfield_conn_cfg() connCfg.conn_cfg_tag = connCfgTag + gapCfg := connCfg.params.unionfield_gap_conn_cfg() + gapCfg.conn_count = 1 + gapCfg.event_length = a.cfg.Gap.EventLength + + errCode = C.sd_ble_cfg_set(C.uint32_t(C.BLE_CONN_CFG_GAP), &bleCfg, appRAMBase) + if errCode != 0 { + return Error(errCode) + } + gattCfg := connCfg.params.unionfield_gatt_conn_cfg() gattCfg.att_mtu = a.cfg.Gatt.AttMtu errCode = C.sd_ble_cfg_set(C.uint32_t(C.BLE_CONN_CFG_GATT), &bleCfg, appRAMBase) - if debug { - println("gatt config updated, err:", Error(errCode).Error()) + if errCode != 0 { + return Error(errCode) } l2capCfg := connCfg.params.unionfield_l2cap_conn_cfg() @@ -68,20 +77,11 @@ func (a *Adapter) enable() error { l2capCfg.tx_mps = a.cfg.L2cap.TxMps l2capCfg.rx_queue_size = a.cfg.L2cap.RxQueueSize l2capCfg.tx_queue_size = a.cfg.L2cap.TxQueueSize - l2capCfg.ch_count = a.cfg.L2cap.ChCount // TODO: @rdnt max 18? 20 crashes + l2capCfg.ch_count = a.cfg.L2cap.ChCount errCode = C.sd_ble_cfg_set(C.uint32_t(C.BLE_CONN_CFG_L2CAP), &bleCfg, appRAMBase) - if debug { - println("l2cap config updated, err:", Error(errCode).Error()) - } - - gapCfg := connCfg.params.unionfield_gap_conn_cfg() - gapCfg.conn_count = a.cfg.Gapp.ConnCount - gapCfg.event_length = a.cfg.Gapp.EventLength - - errCode = C.sd_ble_cfg_set(C.uint32_t(C.BLE_CONN_CFG_GAP), &bleCfg, appRAMBase) - if debug { - println("gap config updated, err:", Error(errCode).Error()) + if errCode != 0 { + return Error(errCode) } errCode = C.sd_ble_enable(&appRAMBase) diff --git a/adapter_sd.go b/adapter_sd.go index 7aca9709..667e3ef7 100644 --- a/adapter_sd.go +++ b/adapter_sd.go @@ -33,7 +33,7 @@ var currentConnection = volatileHandle{handle: volatile.Register16{C.BLE_CONN_HA // Globally allocated buffer for incoming SoftDevice events. var eventBuf struct { C.ble_evt_t - buf [247]byte + buf [244]byte } func init() { @@ -64,34 +64,49 @@ var DefaultAdapter = &Adapter{isDefault: true, var eventBufLen C.uint16_t +// Config represents the settings that will be configured to the connection +// '1' of the SoftDevice. type Config struct { - Gapp GapConfig + Gap GapConfig Gatt GattConfig L2cap L2capConfig } type GapConfig struct { - ConnCount uint8 + // EventLength is the time set aside for this connection on every + // connection interval in 1.25 ms units. The minimum value is 2. EventLength uint16 } type GattConfig struct { + // AttMtu is the maximum size of ATT packet the SoftDevice can send or + // receive. The default and minimum value is 23. The maximum value is 247. + // Using ATT_MTU sizes that are multiples of 23 is ideal. AttMtu uint16 } +// L2capConfig is the L2CAP connection configuration. Leaving [ChCount] as 0 +// lets the L2CAP config be ignored. type L2capConfig struct { - RxMps uint16 - TxMps uint16 + // The maximum L2CAP PDU receive payload size. + // Valid range: 27 - 257. + RxMps uint16 + // The maximum L2CAP PDU transmit payload size. + // Valid range: 27 - 257. + TxMps uint16 + // Receive queue size. Minimum: 1 RxQueueSize uint8 + // Transmit queue size. Minimum: 1 TxQueueSize uint8 - ChCount uint8 + // Number of L2CAP channels the application can create. If this parameter + // is set to zero, all other parameters in the struct are ignored. + // Valid range: 1 - 64. + ChCount uint8 } +// Configure sets the configuration for this adapter. +// The configuration will be applied when the adapter is enabled. func (a *Adapter) Configure(cfg Config) error { - if cfg.Gatt.AttMtu < 23 || cfg.Gatt.AttMtu > 247 { - cfg.Gatt.AttMtu = 23 - } - a.cfg = cfg return nil From 8dc2b8e3f8e1fd47a91b5f65e632d1ca38d3cf07 Mon Sep 17 00:00:00 2001 From: Tasos Papalyras Date: Mon, 7 Oct 2024 00:13:44 +0300 Subject: [PATCH 4/7] Cleanup --- adapter_nrf528xx-full.go | 6 ------ adapter_sd.go | 4 ---- gap_nrf528xx-central.go | 6 ------ 3 files changed, 16 deletions(-) diff --git a/adapter_nrf528xx-full.go b/adapter_nrf528xx-full.go index e1fd9a7a..4b6fde7e 100644 --- a/adapter_nrf528xx-full.go +++ b/adapter_nrf528xx-full.go @@ -17,12 +17,6 @@ import ( "unsafe" ) -// TODO: @rdnt cleanup -//var ( -// dataLenParams = &C.ble_gap_data_length_params_t{} -// dataLenLimitation = &C.ble_gap_data_length_limitation_t{} -//) - func handleEvent() { id := eventBuf.header.evt_id switch { diff --git a/adapter_sd.go b/adapter_sd.go index 667e3ef7..06a2adf1 100644 --- a/adapter_sd.go +++ b/adapter_sd.go @@ -125,10 +125,6 @@ func (a *Adapter) Enable() error { eventBufLen = C.uint16_t(unsafe.Sizeof(eventBuf)) errCode := C.sd_ble_evt_get((*C.uint8_t)(unsafe.Pointer(&eventBuf)), &eventBufLen) if errCode != 0 { - // TODO: @rdnt remove - //if debug { - // println("sd_ble_evt_get failed, err:", Error(errCode).Error()) - //} // Possible error conditions: // * NRF_ERROR_NOT_FOUND: no events left, break // * NRF_ERROR_DATA_SIZE: retry with a bigger data buffer diff --git a/gap_nrf528xx-central.go b/gap_nrf528xx-central.go index 7d32531b..1e094856 100644 --- a/gap_nrf528xx-central.go +++ b/gap_nrf528xx-central.go @@ -182,12 +182,6 @@ func (a *Adapter) Connect(address Address, params ConnectionParams) (Device, err connectionAttempt.state.Set(0) connectionHandle := connectionAttempt.connectionHandle - // TODO @rdnt: move into exchangeMTU function - //errCode = C.sd_ble_gattc_exchange_mtu_request(connectionHandle, C.uint16_t(a.cfg.Gatt.AttMtu)) - //if debug { - // println("mtu requested, self:", a.cfg.Gatt.AttMtu, " err:", Error(errCode).Error()) - //} - return Device{ connectionHandle: connectionHandle, }, nil From 22f1116aeb682a822a991be2490e55bc95440e00 Mon Sep 17 00:00:00 2001 From: Tasos Papalyras Date: Mon, 7 Oct 2024 00:36:23 +0300 Subject: [PATCH 5/7] Add gap event length configure --- adapter_nrf528xx.go | 12 ------------ adapter_sd.go | 32 ++++++++++---------------------- 2 files changed, 10 insertions(+), 34 deletions(-) diff --git a/adapter_nrf528xx.go b/adapter_nrf528xx.go index df89f3e5..79b413a7 100644 --- a/adapter_nrf528xx.go +++ b/adapter_nrf528xx.go @@ -72,18 +72,6 @@ func (a *Adapter) enable() error { return Error(errCode) } - l2capCfg := connCfg.params.unionfield_l2cap_conn_cfg() - l2capCfg.rx_mps = a.cfg.L2cap.RxMps - l2capCfg.tx_mps = a.cfg.L2cap.TxMps - l2capCfg.rx_queue_size = a.cfg.L2cap.RxQueueSize - l2capCfg.tx_queue_size = a.cfg.L2cap.TxQueueSize - l2capCfg.ch_count = a.cfg.L2cap.ChCount - - errCode = C.sd_ble_cfg_set(C.uint32_t(C.BLE_CONN_CFG_L2CAP), &bleCfg, appRAMBase) - if errCode != 0 { - return Error(errCode) - } - errCode = C.sd_ble_enable(&appRAMBase) return makeError(errCode) } diff --git a/adapter_sd.go b/adapter_sd.go index 06a2adf1..3cbc72a3 100644 --- a/adapter_sd.go +++ b/adapter_sd.go @@ -67,9 +67,8 @@ var eventBufLen C.uint16_t // Config represents the settings that will be configured to the connection // '1' of the SoftDevice. type Config struct { - Gap GapConfig - Gatt GattConfig - L2cap L2capConfig + Gap GapConfig + Gatt GattConfig } type GapConfig struct { @@ -85,28 +84,17 @@ type GattConfig struct { AttMtu uint16 } -// L2capConfig is the L2CAP connection configuration. Leaving [ChCount] as 0 -// lets the L2CAP config be ignored. -type L2capConfig struct { - // The maximum L2CAP PDU receive payload size. - // Valid range: 27 - 257. - RxMps uint16 - // The maximum L2CAP PDU transmit payload size. - // Valid range: 27 - 257. - TxMps uint16 - // Receive queue size. Minimum: 1 - RxQueueSize uint8 - // Transmit queue size. Minimum: 1 - TxQueueSize uint8 - // Number of L2CAP channels the application can create. If this parameter - // is set to zero, all other parameters in the struct are ignored. - // Valid range: 1 - 64. - ChCount uint8 -} - // Configure sets the configuration for this adapter. // The configuration will be applied when the adapter is enabled. func (a *Adapter) Configure(cfg Config) error { + if cfg.Gap.EventLength < 2 { + return errors.New("invalid event length") + } + + if cfg.Gatt.AttMtu < 23 || cfg.Gatt.AttMtu > 247 { + return errors.New("invalid ATT MTU") + } + a.cfg = cfg return nil From a719fbf25d056feb08633ebd4638590b42777944 Mon Sep 17 00:00:00 2001 From: Tasos Papalyras Date: Mon, 7 Oct 2024 00:43:53 +0300 Subject: [PATCH 6/7] Cleanup, update s113v7 --- adapter_nrf528xx-full.go | 2 -- adapter_nrf528xx-peripheral.go | 20 +++++++++++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/adapter_nrf528xx-full.go b/adapter_nrf528xx-full.go index 4b6fde7e..0375ab31 100644 --- a/adapter_nrf528xx-full.go +++ b/adapter_nrf528xx-full.go @@ -158,8 +158,6 @@ func handleEvent() { // way to handle it, ignore it. C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, nil, 0, 0) case C.BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: - // This event is generated by some devices. While we could support - // larger MTUs, this default MTU is supported everywhere. rsp := gattsEvent.params.unionfield_exchange_mtu_request() effectiveMtu := min(DefaultAdapter.cfg.Gatt.AttMtu, uint16(rsp.client_rx_mtu)) if debug { diff --git a/adapter_nrf528xx-peripheral.go b/adapter_nrf528xx-peripheral.go index cd094a2a..f70749be 100644 --- a/adapter_nrf528xx-peripheral.go +++ b/adapter_nrf528xx-peripheral.go @@ -91,9 +91,16 @@ func handleEvent() { // way to handle it, ignore it. C.sd_ble_gatts_sys_attr_set(gattsEvent.conn_handle, nil, 0, 0) case C.BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: - // This event is generated by some devices. While we could support - // larger MTUs, this default MTU is supported everywhere. - C.sd_ble_gatts_exchange_mtu_reply(gattsEvent.conn_handle, C.BLE_GATT_ATT_MTU_DEFAULT) + rsp := gattsEvent.params.unionfield_exchange_mtu_request() + effectiveMtu := min(DefaultAdapter.cfg.Gatt.AttMtu, uint16(rsp.client_rx_mtu)) + if debug { + println("mtu exchange requested. self:", DefaultAdapter.cfg.Gatt.AttMtu, ", peer:", rsp.client_rx_mtu, ", effective:", effectiveMtu) + } + + var errCode = C.sd_ble_gatts_exchange_mtu_reply(gattsEvent.conn_handle, C.uint16_t(effectiveMtu)) + if debug { + println("mtu exchange replied, err:", Error(errCode).Error()) + } case C.BLE_GATTS_EVT_HVN_TX_COMPLETE: // ignore confirmation of a notification successfully sent default: @@ -107,3 +114,10 @@ func handleEvent() { } } } + +func min(a, b uint16) uint16 { + if a < b { + return a + } + return b +} From d21c51e6f3e2536f0e180c85db55a89fab6bbe0f Mon Sep 17 00:00:00 2001 From: Tasos Papalyras Date: Mon, 7 Oct 2024 18:15:20 +0300 Subject: [PATCH 7/7] Make Configure() optional, handle default configs --- adapter_nrf528xx.go | 8 ++++++++ adapter_sd.go | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/adapter_nrf528xx.go b/adapter_nrf528xx.go index 79b413a7..ebc97eee 100644 --- a/adapter_nrf528xx.go +++ b/adapter_nrf528xx.go @@ -55,6 +55,10 @@ func (a *Adapter) enable() error { connCfg := bleCfg.unionfield_conn_cfg() connCfg.conn_cfg_tag = connCfgTag + if a.cfg.Gap.EventLength == 0 { + a.cfg.Gap.EventLength = 2 + } + gapCfg := connCfg.params.unionfield_gap_conn_cfg() gapCfg.conn_count = 1 gapCfg.event_length = a.cfg.Gap.EventLength @@ -64,6 +68,10 @@ func (a *Adapter) enable() error { return Error(errCode) } + if a.cfg.Gatt.AttMtu == 0 { + a.cfg.Gatt.AttMtu = 23 + } + gattCfg := connCfg.params.unionfield_gatt_conn_cfg() gattCfg.att_mtu = a.cfg.Gatt.AttMtu diff --git a/adapter_sd.go b/adapter_sd.go index 3cbc72a3..eb24dcd1 100644 --- a/adapter_sd.go +++ b/adapter_sd.go @@ -87,11 +87,11 @@ type GattConfig struct { // Configure sets the configuration for this adapter. // The configuration will be applied when the adapter is enabled. func (a *Adapter) Configure(cfg Config) error { - if cfg.Gap.EventLength < 2 { + if cfg.Gap.EventLength != 0 && cfg.Gap.EventLength < 2 { return errors.New("invalid event length") } - if cfg.Gatt.AttMtu < 23 || cfg.Gatt.AttMtu > 247 { + if cfg.Gatt.AttMtu != 0 && (cfg.Gatt.AttMtu < 23 || cfg.Gatt.AttMtu > 247) { return errors.New("invalid ATT MTU") }