mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
bluez5: better error/malformed input handling
Safer parsing of AT commands, additional null and error checks.
This commit is contained in:
parent
f0a2b6d01f
commit
f330446291
5 changed files with 56 additions and 21 deletions
|
|
@ -724,8 +724,11 @@ static DBusHandlerResult hsphfpd_new_audio_connection(DBusConnection *conn, DBus
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (r) {
|
if (r) {
|
||||||
dbus_connection_send(backend->conn, r, NULL);
|
DBusHandlerResult res = DBUS_HANDLER_RESULT_HANDLED;
|
||||||
dbus_message_unref(r);
|
if (!dbus_connection_send(backend->conn, r, NULL))
|
||||||
|
res = DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||||
|
dbus_message_unref(r);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DBUS_HANDLER_RESULT_HANDLED;
|
return DBUS_HANDLER_RESULT_HANDLED;
|
||||||
|
|
@ -1069,6 +1072,11 @@ static DBusHandlerResult hsphfpd_parse_endpoint_properties(struct impl *backend,
|
||||||
if (!endpoint->valid && endpoint->local_address && endpoint->remote_address && endpoint->profile && endpoint->role)
|
if (!endpoint->valid && endpoint->local_address && endpoint->remote_address && endpoint->profile && endpoint->role)
|
||||||
endpoint->valid = true;
|
endpoint->valid = true;
|
||||||
|
|
||||||
|
if (!endpoint->remote_address || !endpoint->local_address) {
|
||||||
|
spa_log_debug(backend->log, NAME": Missing addresses for %s", endpoint->path);
|
||||||
|
return DBUS_HANDLER_RESULT_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
d = spa_bt_device_find_by_address(backend->monitor, endpoint->remote_address, endpoint->local_address);
|
d = spa_bt_device_find_by_address(backend->monitor, endpoint->remote_address, endpoint->local_address);
|
||||||
if (!d) {
|
if (!d) {
|
||||||
spa_log_debug(backend->log, NAME": No device for %s", endpoint->path);
|
spa_log_debug(backend->log, NAME": No device for %s", endpoint->path);
|
||||||
|
|
|
||||||
|
|
@ -336,7 +336,7 @@ static bool rfcomm_hfp_ag(struct spa_source *source, char* buf)
|
||||||
struct impl *backend = rfcomm->backend;
|
struct impl *backend = rfcomm->backend;
|
||||||
unsigned int features;
|
unsigned int features;
|
||||||
unsigned int gain;
|
unsigned int gain;
|
||||||
unsigned int len, k, v;
|
unsigned int len;
|
||||||
unsigned int selected_codec;
|
unsigned int selected_codec;
|
||||||
|
|
||||||
if (sscanf(buf, "AT+BRSF=%u", &features) == 1) {
|
if (sscanf(buf, "AT+BRSF=%u", &features) == 1) {
|
||||||
|
|
@ -423,9 +423,10 @@ static bool rfcomm_hfp_ag(struct spa_source *source, char* buf)
|
||||||
if (rfcomm->transport == NULL) {
|
if (rfcomm->transport == NULL) {
|
||||||
spa_log_warn(backend->log, NAME": can't create transport: %m");
|
spa_log_warn(backend->log, NAME": can't create transport: %m");
|
||||||
// TODO: We should manage the missing transport
|
// TODO: We should manage the missing transport
|
||||||
|
} else {
|
||||||
|
rfcomm->transport->codec = HFP_AUDIO_CODEC_CVSD;
|
||||||
|
spa_bt_device_connect_profile(rfcomm->device, rfcomm->profile);
|
||||||
}
|
}
|
||||||
rfcomm->transport->codec = HFP_AUDIO_CODEC_CVSD;
|
|
||||||
spa_bt_device_connect_profile(rfcomm->device, rfcomm->profile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (!rfcomm->slc_configured) {
|
} else if (!rfcomm->slc_configured) {
|
||||||
|
|
@ -489,21 +490,32 @@ static bool rfcomm_hfp_ag(struct spa_source *source, char* buf)
|
||||||
// We expect battery status only (bitmask 10)
|
// We expect battery status only (bitmask 10)
|
||||||
rfcomm_send_reply(source, "+XAPL: iPhone,2");
|
rfcomm_send_reply(source, "+XAPL: iPhone,2");
|
||||||
rfcomm_send_reply(source, "OK");
|
rfcomm_send_reply(source, "OK");
|
||||||
} else if (sscanf(buf, "AT+IPHONEACCEV=%d", &len) == 1) {
|
} else if (sscanf(buf, "AT+IPHONEACCEV=%u", &len) == 1) {
|
||||||
if (len < 1) {
|
unsigned int i;
|
||||||
return false;
|
int k, v;
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned int i = 1; i <= len; i++) {
|
if (len < 1 || len > 100)
|
||||||
buf = strchr(buf, ',') + 1;
|
return false;
|
||||||
if (sscanf(buf, "%d", &k) != 1) return false;
|
|
||||||
buf = strchr(buf, ',') + 1;
|
for (i = 1; i <= len; i++) {
|
||||||
if (sscanf(buf, "%d", &v) != 1) return false;
|
buf = strchr(buf, ',');
|
||||||
|
if (buf == NULL)
|
||||||
|
return false;
|
||||||
|
++buf;
|
||||||
|
if (sscanf(buf, "%d", &k) != 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
buf = strchr(buf, ',');
|
||||||
|
if (buf == NULL)
|
||||||
|
return false;
|
||||||
|
++buf;
|
||||||
|
if (sscanf(buf, "%d", &v) != 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (k == SPA_BT_HFP_HF_IPHONEACCEV_KEY_BATTERY) {
|
if (k == SPA_BT_HFP_HF_IPHONEACCEV_KEY_BATTERY) {
|
||||||
// Battery level is reported in range of 0-9, convert to 0-100%
|
// Battery level is reported in range of 0-9, convert to 0-100%
|
||||||
uint8_t level = (v + 1) * 10;
|
uint8_t level = (SPA_CLAMP(v, 0, 9) + 1) * 10;
|
||||||
spa_log_debug(backend->log, NAME": battery level: %d%%", level);
|
spa_log_debug(backend->log, NAME": battery level: %d%%", (int)level);
|
||||||
|
|
||||||
// TODO: report without Battery Provider (using props)
|
// TODO: report without Battery Provider (using props)
|
||||||
spa_bt_device_report_battery_level(rfcomm->device, level);
|
spa_bt_device_report_battery_level(rfcomm->device, level);
|
||||||
|
|
@ -625,9 +637,10 @@ static bool rfcomm_hfp_hf(struct spa_source *source, char* buf)
|
||||||
if (rfcomm->transport == NULL) {
|
if (rfcomm->transport == NULL) {
|
||||||
spa_log_warn(backend->log, NAME": can't create transport: %m");
|
spa_log_warn(backend->log, NAME": can't create transport: %m");
|
||||||
// TODO: We should manage the missing transport
|
// TODO: We should manage the missing transport
|
||||||
|
} else {
|
||||||
|
rfcomm->transport->codec = HFP_AUDIO_CODEC_CVSD;
|
||||||
|
spa_bt_device_connect_profile(rfcomm->device, rfcomm->profile);
|
||||||
}
|
}
|
||||||
rfcomm->transport->codec = HFP_AUDIO_CODEC_CVSD;
|
|
||||||
spa_bt_device_connect_profile(rfcomm->device, rfcomm->profile);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -351,6 +351,11 @@ static DBusHandlerResult ofono_audio_card_found(struct impl *backend, char *path
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!remote_address || !local_address) {
|
||||||
|
spa_log_error(backend->log, NAME": Missing addresses for %s", path);
|
||||||
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
d = spa_bt_device_find_by_address(backend->monitor, remote_address, local_address);
|
d = spa_bt_device_find_by_address(backend->monitor, remote_address, local_address);
|
||||||
if (!d) {
|
if (!d) {
|
||||||
spa_log_error(backend->log, NAME": Device doesn’t exist for %s", path);
|
spa_log_error(backend->log, NAME": Device doesn’t exist for %s", path);
|
||||||
|
|
@ -449,8 +454,11 @@ static DBusHandlerResult ofono_new_audio_connection(DBusConnection *conn, DBusMe
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (r) {
|
if (r) {
|
||||||
dbus_connection_send(backend->conn, r, NULL);
|
DBusHandlerResult res = DBUS_HANDLER_RESULT_HANDLED;
|
||||||
dbus_message_unref(r);
|
if (!dbus_connection_send(backend->conn, r, NULL))
|
||||||
|
res = DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||||
|
dbus_message_unref(r);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DBUS_HANDLER_RESULT_HANDLED;
|
return DBUS_HANDLER_RESULT_HANDLED;
|
||||||
|
|
|
||||||
|
|
@ -1474,6 +1474,9 @@ static int impl_set_param(void *object,
|
||||||
uint32_t profile;
|
uint32_t profile;
|
||||||
enum spa_bluetooth_audio_codec codec;
|
enum spa_bluetooth_audio_codec codec;
|
||||||
|
|
||||||
|
if (param == NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
if ((res = spa_pod_parse_object(param,
|
if ((res = spa_pod_parse_object(param,
|
||||||
SPA_TYPE_OBJECT_ParamProfile, NULL,
|
SPA_TYPE_OBJECT_ParamProfile, NULL,
|
||||||
SPA_PARAM_PROFILE_index, SPA_POD_Int(&id))) < 0) {
|
SPA_PARAM_PROFILE_index, SPA_POD_Int(&id))) < 0) {
|
||||||
|
|
@ -1496,6 +1499,9 @@ static int impl_set_param(void *object,
|
||||||
struct spa_pod *props = NULL;
|
struct spa_pod *props = NULL;
|
||||||
struct node *node;
|
struct node *node;
|
||||||
|
|
||||||
|
if (param == NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
if ((res = spa_pod_parse_object(param,
|
if ((res = spa_pod_parse_object(param,
|
||||||
SPA_TYPE_OBJECT_ParamRoute, NULL,
|
SPA_TYPE_OBJECT_ParamRoute, NULL,
|
||||||
SPA_PARAM_ROUTE_index, SPA_POD_Int(&id),
|
SPA_PARAM_ROUTE_index, SPA_POD_Int(&id),
|
||||||
|
|
|
||||||
|
|
@ -692,7 +692,7 @@ static int impl_node_send_command(void *object, const struct spa_command *comman
|
||||||
|
|
||||||
static void emit_node_info(struct impl *this, bool full)
|
static void emit_node_info(struct impl *this, bool full)
|
||||||
{
|
{
|
||||||
bool is_ag = (this->transport->profile & SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY);
|
bool is_ag = this->transport && (this->transport->profile & SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY);
|
||||||
struct spa_dict_item ag_node_info_items[] = {
|
struct spa_dict_item ag_node_info_items[] = {
|
||||||
{ SPA_KEY_DEVICE_API, "bluez5" },
|
{ SPA_KEY_DEVICE_API, "bluez5" },
|
||||||
{ SPA_KEY_MEDIA_CLASS, "Stream/Output/Audio" },
|
{ SPA_KEY_MEDIA_CLASS, "Stream/Output/Audio" },
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue