Re: [PATCH] avctp: Add functionality for CT browsing commands

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

 



Hi Alexandros,

On Tue, Jan 22, 2013 at 12:32 PM, Alexandros Antonopoulos
<alexandros.antonopoulos@xxxxxxxxxxxxxxxx> wrote:
> Add the missing functionality for full support of browsing channel
> on the CT side. This is required for AVRCP >= 1.4
> The patch is based on the control channel functionality
>
> ---
>  profiles/audio/avctp.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++
>  profiles/audio/avctp.h |   6 +++
>  2 files changed, 146 insertions(+)
>
> diff --git a/profiles/audio/avctp.c b/profiles/audio/avctp.c
> index e65594d..02bee2b 100644
> --- a/profiles/audio/avctp.c
> +++ b/profiles/audio/avctp.c
> @@ -136,6 +136,14 @@ struct avctp_control_req {
>         void *user_data;
>  };
>
> +struct avctp_browsing_req {
> +       struct avctp_pending_req *p;
> +       uint8_t *operands;
> +       uint16_t operand_count;
> +       avctp_browsing_rsp_cb func;
> +       void *user_data;
> +};
> +
>  typedef int (*avctp_process_cb) (void *data);
>
>  struct avctp_pending_req {
> @@ -527,6 +535,44 @@ static int avctp_send(struct avctp_channel *control, uint8_t transaction,
>         return err;
>  }
>
> +static int avctp_browsing_send(struct avctp_channel *browsing,
> +                               uint8_t transaction, uint8_t cr,
> +                               uint8_t *operands, size_t operand_count)
> +{
> +       struct avctp_header *avctp;
> +       struct msghdr msg;
> +       struct iovec iov[2];
> +       int sk, err = 0;
> +
> +       iov[0].iov_base = browsing->buffer;
> +       iov[0].iov_len  = sizeof(*avctp);
> +       iov[1].iov_base = operands;
> +       iov[1].iov_len  = operand_count;
> +
> +       if (browsing->omtu < (iov[0].iov_len + iov[1].iov_len))
> +               return -EOVERFLOW;
> +
> +       sk = g_io_channel_unix_get_fd(browsing->io);
> +
> +       memset(browsing->buffer, 0, iov[0].iov_len);
> +
> +       avctp = (void *) browsing->buffer;
> +
> +       avctp->transaction = transaction;
> +       avctp->packet_type = AVCTP_PACKET_SINGLE;
> +       avctp->cr = cr;
> +       avctp->pid = htons(AV_REMOTE_SVCLASS_ID);
> +
> +       memset(&msg, 0, sizeof(msg));
> +       msg.msg_iov = iov;
> +       msg.msg_iovlen = 2;
> +
> +       if (sendmsg(sk, &msg, 0) < 0)
> +               err = -errno;
> +
> +       return err;
> +}
> +
>  static void control_req_destroy(void *data)
>  {
>         struct avctp_control_req *req = data;
> @@ -535,6 +581,14 @@ static void control_req_destroy(void *data)
>         g_free(req);
>  }
>
> +static void browsing_req_destroy(void *data)
> +{
> +       struct avctp_browsing_req *req = data;
> +
> +       g_free(req->operands);
> +       g_free(req);
> +}
> +
>  static gboolean req_timeout(gpointer user_data)
>  {
>         struct avctp_channel *chan = user_data;
> @@ -563,6 +617,15 @@ static int process_control(void *data)
>                                         req->operands, req->operand_count);
>  }
>
> +static int process_browsing(void *data)
> +{
> +       struct avctp_browsing_req *req = data;
> +       struct avctp_pending_req *p = req->p;
> +
> +       return avctp_browsing_send(p->chan, p->transaction, AVCTP_COMMAND,
> +                                       req->operands, req->operand_count);
> +}
> +
>  static gboolean process_queue(void *user_data)
>  {
>         struct avctp_channel *chan = user_data;
> @@ -636,6 +699,48 @@ static void control_response(struct avctp_channel *control,
>         }
>  }
>
> +static void browsing_response(struct avctp_channel *browsing,
> +                                       struct avctp_header *avctp,
> +                                       uint8_t *operands,
> +                                       size_t operand_count)
> +{
> +       struct avctp_pending_req *p = browsing->p;
> +       struct avctp_browsing_req *req;
> +       GSList *l;
> +
> +       if (p && p->transaction == avctp->transaction) {
> +               browsing->processed = g_slist_prepend(browsing->processed, p);
> +
> +               if (p->timeout > 0) {
> +                       g_source_remove(p->timeout);
> +                       p->timeout = 0;
> +               }
> +
> +               browsing->p = NULL;
> +
> +               if (browsing->process_id == 0)
> +                       browsing->process_id = g_idle_add(process_queue,
> +                                                               browsing);
> +       }
> +
> +       for (l = browsing->processed; l; l = l->next) {
> +               p = l->data;
> +               req = p->data;
> +
> +               if (p->transaction != avctp->transaction)
> +                       continue;
> +
> +               if (req->func && req->func(browsing->session,
> +                                               operands, operand_count,
> +                                               req->user_data))
> +                       return;
> +
> +               browsing->processed = g_slist_remove(browsing->processed, p);
> +
> +               return;
> +       }
> +}
> +
>  static gboolean session_browsing_cb(GIOChannel *chan, GIOCondition cond,
>                                 gpointer data)
>  {
> @@ -665,6 +770,11 @@ static gboolean session_browsing_cb(GIOChannel *chan, GIOCondition cond,
>         ret -= AVCTP_HEADER_LENGTH;
>         operand_count = ret;
>
> +       if (avctp->cr == AVCTP_RESPONSE) {
> +               browsing_response(browsing, avctp, operands, operand_count);
> +               return TRUE;
> +       }
> +
>         packet_size = AVCTP_HEADER_LENGTH;
>         avctp->cr = AVCTP_RESPONSE;
>
> @@ -1294,6 +1404,36 @@ static int avctp_send_req(struct avctp *session, uint8_t code,
>         return 0;
>  }
>
> +int avctp_send_browsing_req(struct avctp *session,
> +                               uint8_t *operands, size_t operand_count,
> +                               avctp_browsing_rsp_cb func, void *user_data)
> +{
> +       struct avctp_channel *browsing = session->browsing;
> +       struct avctp_pending_req *p;
> +       struct avctp_browsing_req *req;
> +
> +       if (browsing == NULL)
> +               return -ENOTCONN;
> +
> +       req = g_new0(struct avctp_browsing_req, 1);
> +       req->func = func;
> +       req->operands = g_memdup(operands, operand_count);
> +       req->operand_count = operand_count;
> +       req->user_data = user_data;
> +
> +       p = pending_create(browsing, process_browsing, req,
> +                       browsing_req_destroy);
> +
> +       req->p = p;
> +
> +       g_queue_push_tail(browsing->queue, p);
> +
> +       if (browsing->process_id == 0)
> +               browsing->process_id = g_idle_add(process_queue, browsing);
> +
> +       return 0;
> +}
> +
>  static char *op2str(uint8_t op)
>  {
>         switch (op & 0x7f) {
> diff --git a/profiles/audio/avctp.h b/profiles/audio/avctp.h
> index c25a3b3..b9107bd 100644
> --- a/profiles/audio/avctp.h
> +++ b/profiles/audio/avctp.h
> @@ -82,6 +82,9 @@ typedef size_t (*avctp_control_pdu_cb) (struct avctp *session,
>  typedef gboolean (*avctp_rsp_cb) (struct avctp *session, uint8_t code,
>                                         uint8_t subunit, uint8_t *operands,
>                                         size_t operand_count, void *user_data);
> +typedef gboolean (*avctp_browsing_rsp_cb) (struct avctp *session,
> +                                       uint8_t *operands, size_t operand_count,
> +                                       void *user_data);
>  typedef size_t (*avctp_browsing_pdu_cb) (struct avctp *session,
>                                         uint8_t transaction,
>                                         uint8_t *operands, size_t operand_count,
> @@ -116,3 +119,6 @@ int avctp_send_vendordep_req(struct avctp *session, uint8_t code,
>                                         uint8_t subunit, uint8_t *operands,
>                                         size_t operand_count,
>                                         avctp_rsp_cb func, void *user_data);
> +int avctp_send_browsing_req(struct avctp *session,
> +                               uint8_t *operands, size_t operand_count,
> +                               avctp_browsing_rsp_cb func, void *user_data);
> --
> 1.8.1

Patch applied, thanks.


--
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