All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Mack <zonque@gmail.com>
To: alsa-devel@alsa-project.org
Cc: gdiffey@gmail.com, tiwai@suse.de, clemens@ladisch.de,
	linuxaudio@showlabor.de, Daniel Mack <zonque@gmail.com>,
	blablack@gmail.com
Subject: [PATCH 6/6] ALSA: snd-usb: add some documentation
Date: Fri, 23 Dec 2011 17:15:47 +0100	[thread overview]
Message-ID: <1324656947-23169-7-git-send-email-zonque@gmail.com> (raw)
In-Reply-To: <1324656947-23169-1-git-send-email-zonque@gmail.com>

Document the new streaming code and some of the functions so that
contributers can catch up easier.

Signed-off-by: Daniel Mack <zonque@gmail.com>
---
 sound/usb/endpoint.c |  182 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 171 insertions(+), 11 deletions(-)

diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 78d9eb6..9edeace 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -35,6 +35,32 @@
 #define EP_FLAG_RUNNING		1
 
 /*
+ * snd_usb_endpoint is a model that abstracts everything related to an
+ * USB endpoint and its streaming.
+ *
+ * There are functions to activate and deactivate the streaming URBs and
+ * optinal callbacks to let the pcm logic handle the actual content of the
+ * packets for playback and record. Thus, the bus streaming and the audio
+ * handlers are fully decoupled.
+ *
+ * There are two different types of endpoints in for audio applications.
+ *
+ * SND_USB_ENDPOINT_TYPE_DATA handles full audio data payload for both
+ * inbound and outbound traffic.
+ *
+ * SND_USB_ENDPOINT_TYPE_SYNC are for inbound traffic only and expect the
+ * payload to carry Q16.16 formatted sync information (3 or 4 bytes).
+ *
+ * Each endpoint has to be configured (by calling
+ * snd_usb_endpoint_set_params()) before it can be used.
+ *
+ * The model incorporates a reference counting, so that multiple users
+ * can call snd_usb_endpoint_start() and snd_usb_endpoint_stop(), and
+ * only the first user will effectively start the URBs, and only the last
+ * one will tear them down again.
+ */
+
+/*
  * convert a sampling rate into our full speed format (fs/1000 in Q16.16)
  * this will overflow at approx 524 kHz
  */
@@ -93,6 +119,14 @@ static const char *usb_error_string(int err)
 	}
 }
 
+/**
+ * snd_usb_endpoint_implicit_feedback_sink: Report endpoint usage type
+ *
+ * @ep: The endpoint
+ *
+ * Determine whether an endpoint is driven by an implicit feedback
+ * data endpoint source.
+ */
 int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep)
 {
 	return  ep->sync_master &&
@@ -101,7 +135,13 @@ int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep)
 		usb_pipeout(ep->pipe);
 }
 
-/* determine the number of frames in the next packet */
+/*
+ * For streaming based on information derived from sync endpoints,
+ * prepare_outbound_urb_sizes() will call next_packet_size() to
+ * determine the number of samples to be sent in the next packet.
+ *
+ * For implicit feedback, next_packet_size() is unused.
+ */
 static int next_packet_size(struct snd_usb_endpoint *ep)
 {
 	unsigned long flags;
@@ -239,6 +279,19 @@ static inline void prepare_inbound_urb(struct snd_usb_endpoint *ep,
 	}
 }
 
+/*
+ * Send output urbs that have been prepared previously. Urbs are dequeued
+ * from ep->ready_playback_urbs and in case there there aren't any available
+ * or there are no packets that have been prepared, this function does
+ * nothing.
+ *
+ * The reason why the functionality of sending and preparing urbs is separated
+ * is that host controllers don't guarantee an ordering in returing inbound
+ * and outbound packets to their submitters.
+ *
+ * This function is only used for implicit feedback endpoints. For endpoints
+ * driven by sync endpoints, urbs are submitted from their completion handler.
+ */
 static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
 {
 	unsigned long flags;
@@ -268,6 +321,7 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
 		for (i = 0; i < packet->packets; i++)
 			ctx->packet_size[i] = packet->packet_size[i];
 
+		/* call the data handler to fill in playback data */
 		prepare_outbound_urb(ep, ctx);
 
 		err = usb_submit_urb(ctx->urb, GFP_ATOMIC);
@@ -335,6 +389,22 @@ exit_clear:
 	clear_bit(ctx->index, &ep->active_mask);
 }
 
+/**
+ * snd_usb_add_endpoint: Add an endpoint to an audio chip
+ *
+ * @chip: The chip
+ * @alts: The USB host interface
+ * @ep_num: The number of the endpoint to use
+ * @direction: SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE
+ * @type: SND_USB_ENDPOINT_TYPE_DATA or SND_USB_ENDPOINT_TYPE_SYNC
+ *
+ * If the requested endpoint has not been added to the given chip before,
+ * a new instance is created. Otherwise, a pointer to the previoulsy
+ * created instance is returned. In case of any error, NULL is returned.
+ *
+ * New endpoints will be added to chip->ep_list and must be freed by
+ * calling snd_usb_endpoint_free().
+ */
 struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
 					      struct usb_host_interface *alts,
 					      int ep_num, int direction, int type)
@@ -507,6 +577,9 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force)
 	ep->nurbs = 0;
 }
 
+/*
+ * configure a data endpoint
+ */
 static int data_ep_set_params(struct snd_usb_endpoint *ep,
 			      struct snd_pcm_hw_params *hw_params,
 			      struct audioformat *fmt,
@@ -629,6 +702,9 @@ out_of_memory:
 	return -ENOMEM;
 }
 
+/*
+ * configure a sync endpoint
+ */
 static int sync_ep_set_params(struct snd_usb_endpoint *ep,
 			      struct snd_pcm_hw_params *hw_params,
 			      struct audioformat *fmt)
@@ -669,6 +745,15 @@ out_of_memory:
 	return -ENOMEM;
 }
 
+/**
+ * snd_usb_endpoint_set_params: configure an snd_endpoint
+ *
+ * @ep: the endpoint to configure
+ *
+ * Determine the number of of URBs to be used on this endpoint.
+ * An endpoint must be configured before it can be started.
+ * An endpoint that is already running can not be reconfigured.
+ */
 int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
 				struct snd_pcm_hw_params *hw_params,
 				struct audioformat *fmt,
@@ -717,6 +802,19 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
 	return err;
 }
 
+/**
+ * snd_usb_endpoint_start: start an snd_usb_endpoint
+ *
+ * @ep: the endpoint to start
+ *
+ * A call to this function will increment the use count of the endpoint.
+ * In case this not already running, the URBs for this endpoint will be
+ * submitted. Otherwise, this function does nothing.
+ *
+ * Must be balanced to calls of snd_usb_endpoint_stop().
+ *
+ * Returns an error if the URB submission failed, 0 in all other cases.
+ */
 int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
 {
 	int err;
@@ -788,6 +886,17 @@ __error:
 	return -EPIPE;
 }
 
+/**
+ * snd_usb_endpoint_stop: stop an snd_usb_endpoint
+ *
+ * @ep: the endpoint to stop (may be NULL)
+ *
+ * A call to this function will decrement the use count of the endpoint.
+ * In case the last user has requested the endpoint stop, the URBs will
+ * actually deactivated.
+ *
+ * Must be balanced to calls of snd_usb_endpoint_start().
+ */
 void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
 			   int force, int can_sleep, int wait)
 {
@@ -812,6 +921,19 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
 	}
 }
 
+/**
+ * snd_usb_endpoint_activate: activate an snd_usb_endpoint
+ *
+ * @ep: the endpoint to activate
+ *
+ * If the endpoint is not currently in use, this functions will select the
+ * correct alternate interface setting for the interface of this endpoint.
+ *
+ * In case of any active users, this functions does nothing.
+ *
+ * Returns an error if usb_set_interface() failed, 0 in all other
+ * cases.
+ */
 int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep)
 {
 	if (ep->use_count != 0)
@@ -835,6 +957,19 @@ int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep)
 	return -EBUSY;
 }
 
+/**
+ * snd_usb_endpoint_deactivate: deactivate an snd_usb_endpoint
+ *
+ * @ep: the endpoint to deactivate
+ *
+ * If the endpoint is not currently in use, this functions will select the
+ * alternate interface setting 0 for the interface of this endpoint.
+ *
+ * In case of any active users, this functions does nothing.
+ *
+ * Returns an error if usb_set_interface() failed, 0 in all other
+ * cases.
+ */
 int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep)
 {
 	if (!ep)
@@ -860,6 +995,13 @@ int snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep)
 	return -EBUSY;
 }
 
+/** snd_usb_endpoint_free: Free the resources of an snd_usb_endpoint
+ *
+ * @ep: the list header of the endpoint to free
+ *
+ * This function does not care for the endpoint's use count but will tear
+ * down all the streaming URBs immediately and free all resources.
+ */
 void snd_usb_endpoint_free(struct list_head *head)
 {
 	struct snd_usb_endpoint *ep;
@@ -869,15 +1011,15 @@ void snd_usb_endpoint_free(struct list_head *head)
 	kfree(ep);
 }
 
-/*
- * process after playback sync complete
- *
- * Full speed devices report feedback values in 10.14 format as samples per
- * frame, high speed devices in 16.16 format as samples per microframe.
- * Because the Audio Class 1 spec was written before USB 2.0, many high speed
- * devices use a wrong interpretation, some others use an entirely different
- * format.  Therefore, we cannot predict what format any particular device uses
- * and must detect it automatically.
+/**
+ * snd_usb_handle_sync_urb: parse an USB sync packet
+ *
+ * @ep: the endpoint to handle the packet
+ * @sender: the sending endpoint
+ * @urb: the received packet
+ *
+ * This function is called from the context of an endpoint that received
+ * the packet and is used to let another endpoint object handle the payload.
  */
 void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
 			     struct snd_usb_endpoint *sender,
@@ -889,6 +1031,11 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
 
 	snd_BUG_ON(ep == sender);
 
+	/*
+	 * In case the endpoint is operating in implicit feedback mode, prepare
+	 * and a new outbound URB that has the same layout as the received
+	 * packet and add it to the list of pending urbs.
+	 */
 	if (snd_usb_endpoint_implict_feedback_sink(ep) &&
 	    ep->use_count != 0) {
 
@@ -938,7 +1085,20 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
 		return;
 	}
 
-	/* parse sync endpoint packet */
+	/*
+	 * process after playback sync complete
+	 *
+	 * Full speed devices report feedback values in 10.14 format as samples
+	 * per frame, high speed devices in 16.16 format as samples per
+	 * microframe.
+	 *
+	 * Because the Audio Class 1 spec was written before USB 2.0, many high
+	 * speed devices use a wrong interpretation, some others use an
+	 * entirely different format.
+	 *
+	 * Therefore, we cannot predict what format any particular device uses
+	 * and must detect it automatically.
+	 */
 
 	if (urb->iso_frame_desc[0].status != 0 ||
 	    urb->iso_frame_desc[0].actual_length < 3)
-- 
1.7.7.4

  parent reply	other threads:[~2011-12-23 16:16 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-12-23 16:15 [PATCH 0/6] snd-usb endpoint rework, version 6 Daniel Mack
2011-12-23 16:15 ` [PATCH 1/6] ALSA: snd-usb: add snd_usb_audio-wide mutex Daniel Mack
2011-12-23 16:15 ` [PATCH 2/6] ALSA: snd-usb: implement new endpoint streaming model Daniel Mack
2011-12-23 16:15 ` [PATCH 3/6] ALSA: snd-usb: switch over to new endpoint streaming logic Daniel Mack
2011-12-23 16:15 ` [PATCH 4/6] ALSA: snd-usb: remove old " Daniel Mack
2011-12-23 16:15 ` [PATCH 5/6] ALSA: snd-usb: add support for implicit feedback Daniel Mack
2011-12-23 16:15 ` Daniel Mack [this message]
2011-12-30 13:56 ` [PATCH 0/6] snd-usb endpoint rework, version 6 Daniel Mack
2011-12-30 15:22   ` Felix Homann
     [not found]   ` <CAFz=ag6XNJSXvYQnAEbx=M+zXVH7sEw=_CJQKx63MmdQBWFuwA@mail.gmail.com>
2011-12-30 15:24     ` Daniel Mack
     [not found]       ` <CACckToWP-C5H2xhvdJ5ykNf4BcuNCa4cMyFh2hppcwW0u33fQQ@mail.gmail.com>
     [not found]         ` <4EFE6E52.4050503@gmail.com>
2011-12-31  4:35           ` Grant Diffey
2011-12-31  8:04             ` Grant Diffey
2011-12-31 14:23   ` Felix Homann
2011-12-31 15:02     ` Aurélien Leblond
2011-12-31 15:39       ` Felix Homann
     [not found]   ` <CAFz=ag7_qzPJq44havp=EbFVKud5VvKaOLJk0i0dM43X3urp9Q@mail.gmail.com>
2012-01-01 17:09     ` Felix Homann
2012-01-16 20:26       ` Grant Diffey
2012-01-16 20:27         ` Grant Diffey
2012-04-09 19:21         ` Daniel Mack
2012-04-10 15:35           ` Grant Diffey
2012-04-10 18:52           ` Felix Homann
2012-04-11 15:08             ` Daniel Mack
2012-04-12  9:05               ` Felix Homann
2012-04-12 11:45                 ` Daniel Mack
2012-04-10 15:40       ` Grant Diffey
  -- strict thread matches above, loose matches on Subject: below --
2012-04-12 11:51 [PATCH 0/6] snd-usb endpoint rework, version 7 Daniel Mack
2012-04-12 11:51 ` [PATCH 6/6] ALSA: snd-usb: add some documentation Daniel Mack

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=1324656947-23169-7-git-send-email-zonque@gmail.com \
    --to=zonque@gmail.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=blablack@gmail.com \
    --cc=clemens@ladisch.de \
    --cc=gdiffey@gmail.com \
    --cc=linuxaudio@showlabor.de \
    --cc=tiwai@suse.de \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.