From: "José Antonio Santos Cadenas" <jcaden@libresoft.es>
To: Santiago Carot Nemesio <scarot@libresoft.es>
Cc: linux-bluetooth@vger.kernel.org
Subject: Re: [PATCH] Added support for deleting all MDLS in MCAP
Date: Tue, 4 May 2010 10:20:32 +0200 [thread overview]
Message-ID: <201005041020.33342.jcaden@libresoft.es> (raw)
In-Reply-To: <201004091344.41686.jcaden@libresoft.es>
Hi all,
El Friday 09 April 2010 13:44:41 José Antonio Santos Cadenas escribió:
> Also fixed some bugs in mcl state transitions
>
> Signed-off-by: Jose Antonio Santos Cadenas <santoscadenas@gmail.com>
> Reviewed-by: Santiago Carot Nemesio <sancane@gmail.com>
> ---
> mcap/mcap.c | 133
> +++++++++++++++++++++++++++++++++++++++---------------- mcap/mcap_lib.h |
> 2 +
> 2 files changed, 97 insertions(+), 38 deletions(-)
>
> diff --git a/mcap/mcap.c b/mcap/mcap.c
> index 28c586c..e76c565 100644
> --- a/mcap/mcap.c
> +++ b/mcap/mcap.c
> @@ -33,7 +33,6 @@
> #include "mcap.h"
> #include "mcap_lib.h"
>
> -//#define STATE2STR(_mcl) state2str(_mcl->state)
> #define MCAP_ERROR mcap_error_quark()
> #define SET_DEFAULT_MCL_CB(__mcl) do { \
> __mcl->cb->mdl_connected = default_mdl_connected_cb; \
> @@ -71,7 +70,8 @@ typedef enum {
> typedef enum {
> MDL_WAITING,
> MDL_CONNECTED,
> - MDL_CLOSED
> + MDL_DELETING,
> + MDL_CLOSED,
> } MDLState;
>
> struct mcap_mcl_cb {
> @@ -79,7 +79,7 @@ struct mcap_mcl_cb {
> mcap_mdl_event_cb mdl_closed; /* Remote device has closed an
mdl */
> mcap_mdl_event_cb mdl_deleted; /* Remote device deleted an
mdl */
> mcap_remote_mdl_conn_req_cb mdl_conn_req; /* Remote deive requested
> create an mdl */ - mcap_remote_mdl_reconn_req_cb mdl_reconn_req; /*
> Remote device requested reconnect previus mdl */
> + mcap_remote_mdl_reconn_req_cb mdl_reconn_req; /* Remote device
> requested reconnect previous mdl */ gpointer user_data; /*
user data */
> };
>
> @@ -240,6 +240,9 @@ static void update_mcl_state(struct mcap_mcl *mcl)
> GSList *l;
> struct mcap_mdl *mdl;
>
> + if (mcl->state == MCL_PENDING)
> + return;
> +
> for (l = mcl->mdls; l; l = l->next) {
> mdl = l->data;
>
> @@ -280,6 +283,12 @@ static void mcap_send_std_opcode(struct mcap_mcl *mcl,
> const uint8_t *buf, return;
> }
>
> + if (mcl->state == MCL_PENDING) {
> + g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
> + "Not Std Op. Codes can be sent in PENDING State");
> + return;
> + }
> +
> if (mcap_send_data(g_io_channel_unix_get_fd(mcl->cc), buf, size) < 0)
> g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
> "Data can't be sent, write error");
> @@ -394,17 +403,10 @@ static gint compare_mdl(gconstpointer a,
> gconstpointer b) static gboolean wait_response_timer(gpointer data)
> {
> struct mcap_mcl *mcl = data;
> - struct mcap_mdl_op_cb *con = mcl->priv_data;
> - struct mcap_mdl *mdl = con->mdl;
>
> GError *gerr = NULL;
>
> RELEASE_TIMER(mcl);
> - mcl->mdls = g_slist_remove(mcl->mdls, mdl);
> - g_free(mdl);
> -
> - mcl->req = MCL_AVAILABLE;
> - update_mcl_state(mcl);
>
> g_set_error(&gerr, MCAP_ERROR, MCAP_ERROR_FAILED,
> "Timeout waiting response");
> @@ -494,6 +496,26 @@ void mcap_req_mdl_reconnect(struct mcap_mdl *mdl,
> con->cb.op = reconnect_cb;
> con->user_data = user_data;
>
> + mcl->state = MCL_ACTIVE;
> + mcl->lcmd = cmd;
> + mcl->req = MCL_WAITING_RSP;
> + mcl->priv_data = con;
> +
> + mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer,
> mcl); +}
> +
> +static void send_delete_req(GError **err, struct mcap_mcl *mcl,
> + struct mcap_mdl_op_cb *con, uint16_t mdlid)
> +{
> + uint8_t *cmd;
> +
> + cmd = create_req(MCAP_MD_DELETE_MDL_REQ, mdlid);
> + mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_req), err);
> + if (*err) {
> + g_free(cmd);
> + return;
> + }
> +
> mcl->lcmd = cmd;
> mcl->req = MCL_WAITING_RSP;
> mcl->priv_data = con;
> @@ -501,13 +523,43 @@ void mcap_req_mdl_reconnect(struct mcap_mdl *mdl,
> mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer,
> mcl); }
>
> +void mcap_req_mdl_delete_all(struct mcap_mcl *mcl, GError **err,
> + mcap_mdl_del_cb delete_cb, gpointer user_data)
> +{
> + GSList *l;
> + struct mcap_mdl *mdl;
> + struct mcap_mdl_op_cb *con;
> +
> + debug("MCL in state: %d", mcl->state);
> + if (!mcl->mdls) {
> + g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
> + "There are not MDLs created");
> + return;
> + }
> +
> + for (l = mcl->mdls; l; l = l->next) {
> + mdl = l->data;
> + if (mdl->state != MDL_WAITING)
> + mdl->state = MDL_DELETING;
> + }
> +
> + con = g_new0(struct mcap_mdl_op_cb, 1);
> + con->mdl = NULL;
> + con->cb.del = delete_cb;
> + con->user_data = user_data;
> +
> + send_delete_req(err, mcl, con, MCAP_ALL_MDLIDS);
> + if (*err)
> + g_free(con);
> + debug("exiting MCL in state: %d", mcl->state);
> +}
> +
> void mcap_req_mdl_deletion(struct mcap_mdl *mdl, GError **err,
> mcap_mdl_del_cb delete_cb, gpointer user_data)
> {
> struct mcap_mcl *mcl= mdl->mcl;
> struct mcap_mdl_op_cb *con;
> GSList *l;
> - uint8_t *cmd;
>
> l = g_slist_find(mcl->mdls, mdl);
>
> @@ -519,28 +571,19 @@ void mcap_req_mdl_deletion(struct mcap_mdl *mdl,
> GError **err,
>
> if (mdl->state == MDL_WAITING) {
> g_set_error(err, MCAP_ERROR, MCAP_ERROR_FAILED,
> - "Not valid petition in this mdl state");
> + "Mdl is not created");
> return;
> }
> + mdl->state = MDL_DELETING;
>
> con = g_new0(struct mcap_mdl_op_cb, 1);
> con->mdl = mdl;
> con->cb.del = delete_cb;
> con->user_data = user_data;
>
> - cmd = create_req(MCAP_MD_DELETE_MDL_REQ, mdl->mdlid);
> - mcap_send_std_opcode(mcl, cmd, sizeof(mcap_md_req), err);
> - if (*err) {
> + send_delete_req(err, mcl, con, mdl->mdlid);
> + if (*err)
> g_free(con);
> - g_free(cmd);
> - return;
> - }
> -
> - mcl->lcmd = cmd;
> - mcl->req = MCL_WAITING_RSP;
> - mcl->priv_data = con;
> -
> - mcl->tid = g_timeout_add_seconds(RESPONSE_TIMER, wait_response_timer,
> mcl); }
>
> void mcap_mdl_abort(struct mcap_mdl *mdl, GError **err,
> @@ -688,7 +731,7 @@ static gboolean parse_set_opts(struct mcap_mcl_cb
> *mcl_cb, GError **err, cb = va_arg(args, int);
> }
>
> - /* Set new callbacks set */
> + /* Set new callbacks */
> if (c->mdl_connected)
> mcl_cb->mdl_connected = c->mdl_connected;
> if (c->mdl_closed)
> @@ -825,7 +868,7 @@ static void process_md_create_mdl_req(struct mcap_mcl
> *mcl, uint8_t *cmd, int le if ((cfga != 0) && (cfga != conf)) {
> /* Remote device set default configuration but upper profile */
> /* has changed it. Protocol Error: force closing the MCL by */
> - /* using remote device using UNESPECIFIED_ERROR response*/
> + /* using remote device using UNESPECIFIED_ERROR response */
> send4B_cmd(mcl, MCAP_MD_CREATE_MDL_RSP, MCAP_UNESPECIFIED_ERROR,
> mdl_id);
> return;
> @@ -844,8 +887,8 @@ static void process_md_create_mdl_req(struct mcap_mcl
> *mcl, uint8_t *cmd, int le shutdown_mdl(mdl);
> mcl->cb->mdl_closed(mdl, mcl->cb->user_data);
> }
> - mdl->state = MDL_WAITING;
> mdl->mdep_id = mdep_id;
> + mdl->state = MDL_WAITING;
> mcl->mdls = g_slist_insert_sorted(mcl->mdls, mdl, compare_mdl);
>
> mcl->state = MCL_PENDING;
> @@ -934,7 +977,7 @@ static void process_md_abort_mdl_req(struct mcap_mcl
> *mcl, uint8_t *cmd, int len g_free(del);
> send4B_cmd(mcl, MCAP_MD_ABORT_MDL_RSP, MCAP_SUCCESS, mdl_id);
> }
> -/* Functions used to process responses */
> +
> static gboolean check_err_rsp(uint16_t rmdl, uint16_t smdl, uint8_t rc,
> int rlen, int len, GError **gerr)
> {
> @@ -1089,15 +1132,26 @@ static void mcap_delete_mdl(gpointer elem, gpointer
> user_data) {
> struct mcap_mdl *mdl = elem;
> gboolean notify = *(gboolean *)user_data;
> - if (mdl->state == MDL_CONNECTED) {
> - debug("MDL %d already connected, closing it", mdl->mdlid);
> - shutdown_mdl(mdl);
> - }
> +
> + shutdown_mdl(mdl);
> if (notify)
> mdl->mcl->cb->mdl_deleted(mdl, mdl->mcl->cb->user_data);
> g_free(mdl);
> }
>
> +static void restore_mdl(gpointer elem, gpointer data)
> +{
> + struct mcap_mdl *mdl = elem;
> +
> + if (mdl->state == MDL_DELETING) {
> + if (mdl->dc)
> + mdl->state = MDL_CONNECTED;
> + else
> + mdl->state = MDL_CLOSED;
> + } else if (mdl->state == MDL_CLOSED)
> + mdl->mcl->cb->mdl_closed(mdl, mdl->mcl->cb->user_data);
> +}
> +
> static gboolean process_md_delete_mdl_rsp(struct mcap_mcl *mcl, uint8_t
> *cmd, int len)
> {
> @@ -1124,6 +1178,10 @@ static gboolean process_md_delete_mdl_rsp(struct
> mcap_mcl *mcl, uint8_t *cmd, mcl->lcmd = NULL;
> mcl->req = MCL_AVAILABLE;
> if (gerr) {
> + if (mdl)
> + restore_mdl(mdl, NULL);
> + else
> + g_slist_foreach(mcl->mdls, restore_mdl, NULL);
> deleted_cb(gerr, user_data);
> g_error_free(gerr);
> return close;
> @@ -1158,8 +1216,8 @@ static void process_md_delete_mdl_req(struct mcap_mcl
> *mcl, mcap_md_req *req) notify = FALSE;
> g_slist_foreach(mcl->mdls, mcap_delete_mdl, ¬ify);
> g_slist_free(mcl->mdls);
> - mcl->state = MCL_CONNECTED;
> mcl->mdls = NULL;
> + mcl->state = MCL_CONNECTED;
> /* NULL mdl means ALL_MDLS */
> mcl->cb->mdl_deleted(NULL, mcl->cb->user_data);
> goto resp;
> @@ -1178,11 +1236,10 @@ static void process_md_delete_mdl_req(struct
> mcap_mcl *mcl, mcap_md_req *req) }
> }
>
> - if (!mdl) {
> + if (!mdl || (mdl->state == MDL_WAITING)) {
> send4B_cmd(mcl, MCAP_MD_DELETE_MDL_RSP, MCAP_INVALID_MDL, mdlid);
> return;
> }
> -
> mcl->mdls = g_slist_remove(mcl->mdls, mdl);
> update_mcl_state(mcl);
> notify = TRUE;
> @@ -1400,16 +1457,16 @@ static gboolean mdl_closing_cb(GIOChannel *chan,
> GIOCondition cond, gpointer dat {
>
> struct mcap_mdl *mdl = data;
> - gboolean open;
> + gboolean notify;
>
> debug("Close MDL %d", mdl->mdlid);
>
> - open = (mdl->state == MDL_CONNECTED);
> + notify = (mdl->state == MDL_CONNECTED);
> shutdown_mdl(mdl);
>
> update_mcl_state(mdl->mcl);
>
> - if (open)
> + if (notify)
> /*Callback to upper layer */
> mdl->mcl->cb->mdl_closed(mdl, mdl->mcl->cb->user_data);
>
> diff --git a/mcap/mcap_lib.h b/mcap/mcap_lib.h
> index 530f03a..867a53d 100644
> --- a/mcap/mcap_lib.h
> +++ b/mcap/mcap_lib.h
> @@ -92,6 +92,8 @@ void mcap_req_mdl_creation(struct mcap_mcl *mcl,
> void mcap_req_mdl_reconnect(struct mcap_mdl *mdl, GError **err,
> mcap_mdl_operation_cb reconnect_cb,
> gpointer user_data);
> +void mcap_req_mdl_delete_all(struct mcap_mcl *mcl, GError **err,
> + mcap_mdl_del_cb delete_cb, gpointer user_data);
> void mcap_req_mdl_deletion(struct mcap_mdl *mdl, GError **err,
> mcap_mdl_del_cb delete_cb, gpointer user_data);
> void mcap_mdl_connect(struct mcap_mdl *mdl,
Please, dismiss this patches we are sending new ones shortly.
Regards
prev parent reply other threads:[~2010-05-04 8:20 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-04-06 14:00 [PATCH] Multi-Channel Adaptation Protocol Santiago Carot Nemesio
2010-04-09 11:44 ` [PATCH] Added support for deleting all MDLS in MCAP José Antonio Santos Cadenas
2010-04-20 16:44 ` Elvis Pfützenreuter
2010-05-04 8:20 ` José Antonio Santos Cadenas [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=201005041020.33342.jcaden@libresoft.es \
--to=jcaden@libresoft.es \
--cc=linux-bluetooth@vger.kernel.org \
--cc=scarot@libresoft.es \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).