Re: [PATCH 4/4] plugins/policy: Try reconnect Control/Target services

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Marcin,

On Wed, Mar 11, 2015 at 8:11 PM, Marcin Kraglak
<marcin.kraglak@xxxxxxxxx> wrote:
> If state of Control/Remote services changed from CONNECTING to
> DISCONNECTED, and error is set to -EAGAIN, set random timer and try
> reconnect. This approach is described in AVRCP Spec 1.5 4.1.1:
> "If both devices open an AVCTP channel at the same time both channels
> shall be closed and each device shall wait a random time
> (not more than 1 s and not less than 100ms) and then try to open
> the AVCTP channel again."
> ---
>  plugins/policy.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 80 insertions(+)
>
> diff --git a/plugins/policy.c b/plugins/policy.c
> index 9cbf146..306a7a3 100644
> --- a/plugins/policy.c
> +++ b/plugins/policy.c
> @@ -50,6 +50,16 @@
>  #define SINK_RETRY_TIMEOUT SOURCE_RETRY_TIMEOUT
>  #define SOURCE_RETRIES 1
>  #define SINK_RETRIES SOURCE_RETRIES
> +#define CT_RETRIES 1
> +#define TG_RETRIES CT_RETRIES
> +
> +/*
> + * AVRCP Spec 1.5 says that reconnect timeout after connection collision
> + * should be random value between 100 ms and 1000 ms. To improve user experience
> + * we linit MAX value to 500 ms
> + */
> +#define RECONNECT_MAX_TIMEOUT 500
> +#define RECONNECT_MIN_TIMEOUT 100

Im not sure we should use sub seconds values, g_timeout_add_seconds
allows group wake-up whereas g_timeout_add doesn't (see
g_timeout_add_seconds_full documentation), so perhaps going with 1
sec. for reconnect is fine here since by design g_timeout_add_seconds
will not be precise so you have some randomness already.

>  /* Tracking of remote services to be auto-reconnected upon link loss */
>
> @@ -82,7 +92,9 @@ struct policy_data {
>         guint sink_timer;
>         uint8_t sink_retries;
>         guint ct_timer;
> +       uint8_t ct_retries;
>         guint tg_timer;
> +       uint8_t tg_retries;
>  };
>
>  static void policy_connect(struct policy_data *data,
> @@ -111,6 +123,7 @@ static gboolean policy_connect_ct(gpointer user_data)
>         struct btd_service *service;
>
>         data->ct_timer = 0;
> +       data->ct_retries++;
>
>         service = btd_device_get_service(data->dev, AVRCP_REMOTE_UUID);
>         if (service != NULL)
> @@ -128,6 +141,23 @@ static void policy_set_ct_timer(struct policy_data *data)
>                                                 policy_connect_ct, data);
>  }
>
> +static void policy_set_random_ct_timer(struct policy_data *data)
> +{
> +       GRand *rand;
> +       int timeout;
> +
> +       rand = g_rand_new();
> +       timeout = g_rand_int_range(rand, RECONNECT_MIN_TIMEOUT,
> +                                                       RECONNECT_MAX_TIMEOUT);
> +
> +       if (data->ct_timer > 0)
> +               g_source_remove(data->ct_timer);
> +
> +       data->ct_timer = g_timeout_add(timeout, policy_connect_ct, data);
> +
> +       g_rand_free(rand);
> +}
> +
>  static struct policy_data *find_data(struct btd_device *dev)
>  {
>         GSList *l;
> @@ -273,6 +303,7 @@ static gboolean policy_connect_tg(gpointer user_data)
>         struct btd_service *service;
>
>         data->tg_timer = 0;
> +       data->tg_retries++;
>
>         service = btd_device_get_service(data->dev, AVRCP_TARGET_UUID);
>         if (service != NULL)
> @@ -291,6 +322,23 @@ static void policy_set_tg_timer(struct policy_data *data)
>                                                         data);
>  }
>
> +static void policy_set_random_tg_timer(struct policy_data *data)
> +{
> +       GRand *rand;
> +       int timeout;
> +
> +       rand = g_rand_new();
> +       timeout = g_rand_int_range(rand, RECONNECT_MIN_TIMEOUT,
> +                                                       RECONNECT_MAX_TIMEOUT);
> +
> +       if (data->tg_timer > 0)
> +               g_source_remove(data->tg_timer);
> +
> +       data->tg_timer = g_timeout_add(timeout, policy_connect_tg, data);
> +
> +       g_rand_free(rand);
> +}
> +
>  static gboolean policy_connect_source(gpointer user_data)
>  {
>         struct policy_data *data = user_data;
> @@ -401,6 +449,22 @@ static void controller_cb(struct btd_service *service,
>                 }
>                 break;
>         case BTD_SERVICE_STATE_DISCONNECTED:
> +               if (old_state == BTD_SERVICE_STATE_CONNECTING) {
> +                       int err = btd_service_get_error(service);
> +
> +                       if (err == -EAGAIN) {
> +                               if (data->ct_retries < CT_RETRIES)
> +                                       policy_set_random_ct_timer(data);
> +                               else
> +                                       data->ct_retries = 0;
> +                               break;
> +                       } else if (data->ct_timer > 0) {
> +                               g_source_remove(data->ct_timer);
> +                               data->ct_timer = 0;
> +                       }
> +               } else if (old_state == BTD_SERVICE_STATE_CONNECTED) {
> +                       data->ct_retries = 0;
> +               }
>                 break;
>         case BTD_SERVICE_STATE_CONNECTING:
>                 break;
> @@ -434,6 +498,22 @@ static void target_cb(struct btd_service *service,
>                 }
>                 break;
>         case BTD_SERVICE_STATE_DISCONNECTED:
> +               if (old_state == BTD_SERVICE_STATE_CONNECTING) {
> +                       int err = btd_service_get_error(service);
> +
> +                       if (err == -EAGAIN) {
> +                               if (data->tg_retries < TG_RETRIES)
> +                                       policy_set_random_tg_timer(data);
> +                               else
> +                                       data->tg_retries = 0;
> +                               break;
> +                       } else if (data->tg_timer > 0) {
> +                               g_source_remove(data->tg_timer);
> +                               data->tg_timer = 0;
> +                       }
> +               } else if (old_state == BTD_SERVICE_STATE_CONNECTED) {
> +                       data->tg_retries = 0;
> +               }
>                 break;
>         case BTD_SERVICE_STATE_CONNECTING:
>                 break;
> --
> 2.1.0
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Luiz Augusto von Dentz
--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux