<name>:conn=<spec>" example, that is why the dense form and the use
of dashes for separation are supported)
additional parameter keywords can be: channel, handle_rx, handle_tx,
- handle_cccd, value_cccd
+ handle_cccd, value_cccd, mtu
Some of the drivers implement a default for the connection. Some of the
drivers can auto-detect USB connected devices.
#define CONNECT_RFCOMM_TRIES 3
#define CONNECT_RFCOMM_RETRY_MS 100
-/* Silence warning about (currently) unused routine. */
-#define WITH_WRITE_TYPE_HANDLE 0
-
/* {{{ compat decls */
/*
* The availability of conversion helpers in <bluetooth/bluetooth.h>
uint16_t write_handle;
uint16_t cccd_handle;
uint16_t cccd_value;
+ uint16_t ble_mtu;
/* Internal state. */
int devid;
int fd;
static void sr_bt_desc_close(struct sr_bt_desc *desc);
static int sr_bt_check_socket_usable(struct sr_bt_desc *desc);
static ssize_t sr_bt_write_type(struct sr_bt_desc *desc, uint8_t type);
-#if WITH_WRITE_TYPE_HANDLE
static ssize_t sr_bt_write_type_handle(struct sr_bt_desc *desc,
uint8_t type, uint16_t handle);
-#endif
static ssize_t sr_bt_write_type_handle_bytes(struct sr_bt_desc *desc,
uint8_t type, uint16_t handle, const uint8_t *data, size_t len);
static ssize_t sr_bt_char_write_req(struct sr_bt_desc *desc,
SR_PRIV int sr_bt_config_notify(struct sr_bt_desc *desc,
uint16_t read_handle, uint16_t write_handle,
- uint16_t cccd_handle, uint16_t cccd_value)
+ uint16_t cccd_handle, uint16_t cccd_value,
+ uint16_t ble_mtu)
{
if (!desc)
desc->write_handle = write_handle;
desc->cccd_handle = cccd_handle;
desc->cccd_value = cccd_value;
+ desc->ble_mtu = ble_mtu;
return 0;
}
size_t packet_dlen;
const char *type_text;
int ret;
+ uint16_t mtu;
if (!desc)
return -1;
/* Dispatch according to the message type. */
switch (packet_type) {
+ case BLE_ATT_EXCHANGE_MTU_REQ:
+ type_text = "MTU exchange request";
+ if (buflen < sizeof(uint16_t)) {
+ sr_dbg("%s, invalid (size)", type_text);
+ break;
+ }
+ mtu = read_u16le_inc_len(&bufptr, &buflen);
+ sr_dbg("%s, peripheral value %" PRIu16, type_text, mtu);
+ if (desc->ble_mtu) {
+ mtu = desc->ble_mtu;
+ sr_dbg("%s, central value %" PRIu16, type_text, mtu);
+ sr_bt_write_type_handle(desc,
+ BLE_ATT_EXCHANGE_MTU_RESP, mtu);
+ break;
+ }
+ sr_warn("Unhandled BLE %s.", type_text);
+ break;
case BLE_ATT_ERROR_RESP:
type_text = "error response";
if (!buflen) {
return 0;
}
-#if WITH_WRITE_TYPE_HANDLE
static ssize_t sr_bt_write_type_handle(struct sr_bt_desc *desc,
uint8_t type, uint16_t handle)
{
return sr_bt_write_type_handle_bytes(desc, type, handle, NULL, 0);
}
-#endif
static ssize_t sr_bt_write_type_handle_bytes(struct sr_bt_desc *desc,
uint8_t type, uint16_t handle, const uint8_t *data, size_t len)
* descr - handle: 0x0016, uuid: 00002902-0000-1000-8000-00805f9b34fb
* descr - handle: 0x0017, uuid: 00002901-0000-1000-8000-00805f9b34fb
*/
- ret = sr_bt_config_notify(desc, 0x0015, 0x0012, 0x0016, 0x0001);
+ ret = sr_bt_config_notify(desc, 0x0015, 0x0012, 0x0016, 0x0001, 0);
if (ret < 0)
goto err;
uint16_t bt_notify_handle_write;
uint16_t bt_notify_handle_cccd;
uint16_t bt_notify_value_cccd;
+ uint16_t bt_ble_mtu;
struct sr_bt_desc *bt_desc;
GSList *bt_source_args;
#endif
SR_PRIV int sr_bt_config_rfcomm(struct sr_bt_desc *desc, size_t channel);
SR_PRIV int sr_bt_config_notify(struct sr_bt_desc *desc,
uint16_t read_handle, uint16_t write_handle,
- uint16_t cccd_handle, uint16_t cccd_value);
+ uint16_t cccd_handle, uint16_t cccd_value,
+ uint16_t ble_mtu);
SR_PRIV int sr_bt_scan_le(struct sr_bt_desc *desc, int duration);
SR_PRIV int sr_bt_scan_bt(struct sr_bt_desc *desc, int duration);
#define SER_BT_PARAM_PREFIX_HDL_TX "handle_tx="
#define SER_BT_PARAM_PREFIX_HDL_CCCD "handle_cccd="
#define SER_BT_PARAM_PREFIX_VAL_CCCD "value_cccd="
+#define SER_BT_PARAM_PREFIX_BLE_MTU "mtu="
/**
* @file
enum ser_bt_conn_t *conn_type, const char **remote_addr,
size_t *rfcomm_channel,
uint16_t *read_hdl, uint16_t *write_hdl,
- uint16_t *cccd_hdl, uint16_t *cccd_val)
+ uint16_t *cccd_hdl, uint16_t *cccd_val,
+ uint16_t *ble_mtu)
{
char **fields, *field;
enum ser_bt_conn_t type;
*cccd_hdl = 0;
if (cccd_val)
*cccd_val = 0;
+ if (ble_mtu)
+ *ble_mtu = 0;
if (!serial || !spec || !spec[0])
return SR_ERR_ARG;
*cccd_val = parm_val;
continue;
}
+ if (g_str_has_prefix(field, SER_BT_PARAM_PREFIX_BLE_MTU)) {
+ field += strlen(SER_BT_PARAM_PREFIX_BLE_MTU);
+ endp = NULL;
+ ret = sr_atoul_base(field, &parm_val, &endp, 0);
+ if (ret != SR_OK || !endp || *endp != '\0') {
+ ret_parse = SR_ERR_ARG;
+ break;
+ }
+ if (ble_mtu)
+ *ble_mtu = parm_val;
+ continue;
+ }
return SR_ERR_DATA;
}
const char *remote_addr;
size_t rfcomm_channel;
uint16_t read_hdl, write_hdl, cccd_hdl, cccd_val;
+ uint16_t ble_mtu;
int rc;
struct sr_bt_desc *desc;
&conn_type, &remote_addr,
&rfcomm_channel,
&read_hdl, &write_hdl,
- &cccd_hdl, &cccd_val);
+ &cccd_hdl, &cccd_val,
+ &ble_mtu);
if (rc != SR_OK)
return SR_ERR_ARG;
case SER_BT_CONN_CC254x:
case SER_BT_CONN_AC6328:
rc = sr_bt_config_notify(desc,
- read_hdl, write_hdl, cccd_hdl, cccd_val);
+ read_hdl, write_hdl, cccd_hdl, cccd_val,
+ ble_mtu);
if (rc < 0)
return SR_ERR;
serial->bt_notify_handle_read = read_hdl;
serial->bt_notify_handle_write = write_hdl;
serial->bt_notify_handle_cccd = cccd_hdl;
serial->bt_notify_value_cccd = cccd_val;
+ serial->bt_ble_mtu = ble_mtu;
break;
default:
/* Unsupported type, or incomplete implementation. */