Re: [patch 1/2] add support for capture (microphone) to g_audio

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

 



Hi Robin,

thanks for the patch.

On Monday 21 September 2009 20:15:19 Robin Callender wrote:
> On Fri, 2009-09-18 at 12:59 -0700, Robin Callender wrote:
> > This patch section contains (among other things) the modification to
> > composite.c/h to support routing of setup(endpoint) to the function.
> >
> >
> > Signed-off-by: Robin Callender <robin_callender@xxxxxxxxxxx>
> > ---
> 
> There was a cut&paste error when the patch text was copied into the
> original email. It omitted the update to u_audio.h to include hid.h
> This updated patch fixes this problem.
> 
> BTW, is there a tool for splitting up a large patch into the ~40K limit
> size? I have been manually creating the emails, which lead to this
> error.  Seems there ought to be some script for handling this.
> 
> Signed-off-by: Robin Callender <robin_callender@xxxxxxxxxxx>
> ---

[snip]

> diff -Naur linux-2.6.31.orig/drivers/usb/gadget/composite.c
>     linux-2.6.31.new/drivers/usb/gadget/composite.c
> --- linux-2.6.31.orig/drivers/usb/gadget/composite.c	2009-09-12
>     11:51:48.000000000 -0700
> +++ linux-2.6.31.new/drivers/usb/gadget/composite.c	2009-09-18
>     10:18:54.000000000 -0700

[snip]

> @@ -810,9 +831,29 @@
>  		 */
>  		if ((ctrl->bRequestType & USB_RECIP_MASK)
>  				== USB_RECIP_INTERFACE) {
> -			f = cdev->config->interface[intf];
> -			if (f && f->setup)
> -				value = f->setup(f, ctrl);
> +			if (intf < MAX_CONFIG_INTERFACES) {
> +				f = cdev->config->interface[intf];
> +				if (f && f->setup) {
> +					value = f->setup(f, ctrl);
> +				}
> +				else
> +					f = NULL;
> +			}
> +			else
> +				f = NULL;
> +
> +		}
> +		if ((ctrl->bRequestType & USB_RECIP_MASK)
> +				== USB_RECIP_ENDPOINT) {
> +			u8 epaddr = w_index & ~USB_DIR_IN;
> +			if (epaddr < MAX_CONFIG_ENDPOINTS) {
> +				f = cdev->config->endpoint[epaddr];
> +				if (f && f->setup) {
> +					value = f->setup(f, ctrl);
> +				}
> +				else
> +					f = NULL;
> +			}
>  			else
>  				f = NULL;
>  		}

This issue has already been fixed in two patches I sent to the linux-usb 
mailing list. Greg applied them to this tree. You should rebase your patches 
on top of that and resubmit them.

> diff -Naur linux-2.6.31.orig/drivers/usb/gadget/u_audio.c
>  linux-2.6.31.new/drivers/usb/gadget/u_audio.c ---
>  linux-2.6.31.orig/drivers/usb/gadget/u_audio.c	2009-09-18
>  10:43:41.000000000 -0700 +++
>  linux-2.6.31.new/drivers/usb/gadget/u_audio.c	2009-09-18
>  10:51:39.000000000 -0700 @@ -109,6 +109,71 @@
>  /**
>   * Set default hardware params
>   */
> +static int capture_default_hw_params(struct gaudio_snd_dev *snd)
> +{
> +	struct snd_pcm_substream *substream = snd->substream;
> +	struct snd_pcm_runtime   *runtime = substream->runtime;
> +	struct snd_pcm_hw_params *params;
> +	snd_pcm_sframes_t result;
> +
> +	/*
> +	 * SNDRV_PCM_ACCESS_RW_INTERLEAVED,
> +	 * SNDRV_PCM_FORMAT_S16_LE
> +	 * CHANNELS: 1
> +	 * RATE: 48000
> +	 */
> +	snd->access = SNDRV_PCM_ACCESS_RW_INTERLEAVED;
> +	snd->format = SNDRV_PCM_FORMAT_S16_LE;
> +	snd->channels = 1;
> +	snd->rate = 48000;
> +
> +	params = kzalloc(sizeof(*params), GFP_KERNEL);
> +	if (!params)
> +		return -ENOMEM;
> +
> +	_snd_pcm_hw_params_any(params);
> +	_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS,
> +			snd->access, 0);
> +	_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT,
> +			snd->format, 0);
> +	_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS,
> +			snd->channels, 0);
> +	_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE,
> +			snd->rate, 0);
> +
> +	snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
> +	snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_HW_PARAMS, params);
> +
> +	result = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE,
> +					NULL);
> +	if (result < 0) {
> +		ERROR(snd->card,
> +			"Preparing sound card failed: %d\n", (int)result);
> +		kfree(params);
> +		return result;
> +	}
> +
> +	/* Store the hardware parameters */
> +	snd->access = params_access(params);
> +	snd->format = params_format(params);
> +	snd->channels = params_channels(params);
> +	snd->rate = params_rate(params);
> +
> +	runtime->frame_bits = snd_pcm_format_physical_width(runtime->format);
> +
> +	kfree(params);
> +
> +	INFO(snd->card,
> +		"Capture hardware params: access %x, format %x, "
> +		"channels %d, rate %d\n",
> +		snd->access, snd->format, snd->channels, snd->rate);
> +
> +	return 0;
> +}
> +
> +/**
> + * Set default hardware params
> + */
>  static int playback_default_hw_params(struct gaudio_snd_dev *snd)
>  {
>  	struct snd_pcm_substream *substream = snd->substream;
> @@ -160,13 +225,55 @@
>  	kfree(params);
> 
>  	INFO(snd->card,
> -		"Hardware params: access %x, format %x, channels %d, rate %d\n",
> +		"Playback hardware params: access %x, format %x, "
> +		"channels %d, rate %d\n",
>  		snd->access, snd->format, snd->channels, snd->rate);
> 
>  	return 0;
>  }
> 
>  /**
> + * Capture audio buffer data by ALSA PCM device
> + */
> +static size_t u_audio_capture(struct gaudio *card, void *buf, size_t
>  count) +{
> +	ssize_t result;
> +	mm_segment_t old_fs;
> +	snd_pcm_sframes_t frames;
> +
> +	struct gaudio_snd_dev	 *snd = &card->capture;
> +	struct snd_pcm_substream *substream = snd->substream;
> +	struct snd_pcm_runtime   *runtime = substream->runtime;
> +
> +try_again:
> +	if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
> +	    runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
> +		result = snd_pcm_kernel_ioctl(substream,
> +				SNDRV_PCM_IOCTL_PREPARE, NULL);
> +		if (result < 0) {
> +			ERROR(card, "Preparing sound card failed: %d\n",
> +					(int)result);
> +			return result;
> +		}
> +	}
> +	frames = bytes_to_frames(runtime, count);
> +
> +	old_fs = get_fs();
> +	set_fs(KERNEL_DS);
> +
> +	result = snd_pcm_lib_read(substream, buf, frames);
> +	if (result != frames) {
> +		ERROR(card, "Capture error: %d\n", (int)result);
> +		set_fs(old_fs);
> +		goto try_again;
> +	}
> +
> +	set_fs(old_fs);
> +
> +	return 0;
> +}
> +
> +/**
>   * Playback audio buffer data by ALSA PCM device
>   */
>  static size_t u_audio_playback(struct gaudio *card, void *buf, size_t
>  count) @@ -214,6 +321,16 @@
>  	return card->playback.rate;
>  }
> 
> +static int u_audio_get_capture_channels(struct gaudio *card)
> +{
> +	return card->capture.channels;
> +}
> +
> +static int u_audio_get_capture_rate(struct gaudio *card)
> +{
> +	return card->capture.rate;
> +}
> +
>  /**
>   * Open ALSA PCM and control device files
>   * Initial the PCM or control device
> @@ -233,7 +350,6 @@
>  		int ret = PTR_ERR(snd->filp);
>  		ERROR(card, "unable to open sound control device file: %s\n",
>  				fn_cntl);
> -		snd->filp = NULL;
>  		return ret;
>  	}
>  	snd->card = card;
> @@ -243,24 +359,23 @@
>  	snd->filp = filp_open(fn_play, O_WRONLY, 0);
>  	if (IS_ERR(snd->filp)) {
>  		ERROR(card, "No such PCM playback device: %s\n", fn_play);
> -		snd->filp = NULL;
> +	} else {
> +		pcm_file = snd->filp->private_data;
> +		snd->substream = pcm_file->substream;
> +		snd->card = card;
> +		playback_default_hw_params(snd);
>  	}
> -	pcm_file = snd->filp->private_data;
> -	snd->substream = pcm_file->substream;
> -	snd->card = card;
> -	playback_default_hw_params(snd);
> 
>  	/* Open PCM capture device and setup substream */
>  	snd = &card->capture;
>  	snd->filp = filp_open(fn_cap, O_RDONLY, 0);
>  	if (IS_ERR(snd->filp)) {
>  		ERROR(card, "No such PCM capture device: %s\n", fn_cap);
> -		snd->substream = NULL;
> -		snd->card = NULL;
>  	} else {
>  		pcm_file = snd->filp->private_data;
>  		snd->substream = pcm_file->substream;
>  		snd->card = card;
> +		capture_default_hw_params(snd);
>  	}
> 
>  	return 0;
> diff -Naur linux-2.6.31.orig/drivers/usb/gadget/u_audio.h
>  linux-2.6.31.new/drivers/usb/gadget/u_audio.h ---
>  linux-2.6.31.orig/drivers/usb/gadget/u_audio.h	2009-09-09
>  15:13:59.000000000 -0700 +++
>  linux-2.6.31.new/drivers/usb/gadget/u_audio.h	2009-09-21
>  10:58:22.000000000 -0700 @@ -14,6 +14,7 @@
> 
>  #include <linux/device.h>
>  #include <linux/err.h>
> +#include <linux/hid.h>
>  #include <linux/usb/audio.h>
>  #include <linux/usb/composite.h>

Why is that required ? I can't see anything requiring linux/hid.h in 
drivers/usb/gadget/u_audio.h.

> diff -Naur linux-2.6.31.orig/include/linux/usb/audio.h
>  linux-2.6.31.new/include/linux/usb/audio.h ---
>  linux-2.6.31.orig/include/linux/usb/audio.h	2009-09-12 11:51:48.000000000
>  -0700 +++ linux-2.6.31.new/include/linux/usb/audio.h	2009-09-16
>  10:55:02.000000000 -0700 @@ -43,6 +43,12 @@
>  /* A.8 Audio Class-Specific Endpoint Descriptor Subtypes */
>  #define UAC_EP_GENERAL			0x01
> 
> +/* endpoint attributes */
> +#define UAC_EP_ATTR_MASK		0x0c
> +#define UAC_EP_ATTR_ASYNC		0x04
> +#define UAC_EP_ATTR_ADAPTIVE		0x08
> +#define UAC_EP_ATTR_SYNC		0x0c
> +

linux/usb/ch9.h (2.6.32-rc1) already defines those:

#define USB_ENDPOINT_SYNC_NONE          (0 << 2)
#define USB_ENDPOINT_SYNC_ASYNC         (1 << 2)
#define USB_ENDPOINT_SYNC_ADAPTIVE      (2 << 2)
#define USB_ENDPOINT_SYNC_SYNC          (3 << 2)

>  /* A.9 Audio Class-Specific Request Codes */
>  #define UAC_SET_			0x00
>  #define UAC_GET_			0x80
> @@ -154,22 +160,48 @@
>  #define UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER	0x306
>  #define UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER	0x307
> 
> +#define UAC_CHANNEL_CONFIG_L		0x0001
> +#define UAC_CHANNEL_CONFIG_R		0x0002
> +#define UAC_CHANNEL_CONFIG_C		0x0004
> +#define UAC_CHANNEL_CONFIG_LFE		0x0008
> +#define UAC_CHANNEL_CONFIG_LS		0x0010
> +#define UAC_CHANNEL_CONFIG_RS		0x0020
> +#define UAC_CHANNEL_CONFIG_LC		0x0040
> +#define UAC_CHANNEL_CONFIG_RC		0x0080
> +#define UAC_CHANNEL_CONFIG_S		0x0100
> +#define UAC_CHANNEL_CONFIG_SL		0x0200
> +#define UAC_CHANNEL_CONFIG_SR		0x0400
> +#define UAC_CHANNEL_CONFIG_T		0x0800
> +
>  /* Set bControlSize = 2 as default setting */
> -#define UAC_DT_FEATURE_UNIT_SIZE(ch)		(7 + ((ch) + 1) * 2)
> +#define UAC_FEATURE_UNIT_SIZE(ch,n)	(7+(((ch)+1)*n))

Why do you rename the macro ?

And please add a space after the coma in the parameters list (this applies to 
all other macros in the file as well).

>  /* As above, but more useful for defining your own descriptors: */
> -#define DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(ch) 		\
> -struct uac_feature_unit_descriptor_##ch {			\
> +#define DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(suffix,ch) 		\
> +struct uac_feature_unit_descriptor_##suffix {			\

Why do you need both a suffix and the number of channels ? The same question 
applies for other descriptor definitions in this file.

>  	__u8  bLength;						\
>  	__u8  bDescriptorType;					\
>  	__u8  bDescriptorSubtype;				\
>  	__u8  bUnitID;						\
>  	__u8  bSourceID;					\
>  	__u8  bControlSize;					\
> -	__le16 bmaControls[ch + 1];				\
> +	__u8  bmaControls[ch + 1];				\

That's not correct, it should be __u8 bmaControls[ch + 1][n];

>  	__u8  iFeature;						\
>  } __attribute__ ((packed))
> 
> +#define UAC_SELECTOR_UNIT_SIZE(pins)	(6 + pins)

That should be UAC_DT_SELECTOR_UNIT_SIZE to be consistent with other 
definitions.

> +#define DECLARE_UAC_SELECTOR_UNIT_DESCRIPTOR(suffix,pins)	\
> +struct uac_selector_unit_descriptor_##suffix {			\
> +	__u8  bLength;						\
> +	__u8  bDescriptorType;					\
> +	__u8  bDescriptorSubtype;				\
> +	__u8  bUnitID;						\
> +	__u8  bNrInPins;					\
> +	__u8  baSourceID[pins];					\
> +	__u8  iSelector;					\
> +} __attribute__ ((packed))
> +
>  /* 4.5.2 Class-Specific AS Interface Descriptor */
>  struct uac_as_header_descriptor {
>  	__u8  bLength;			/* in bytes: 7 */
> @@ -238,6 +270,10 @@
>  #define UAC_FORMAT_TYPE_II		0x2
>  #define UAC_FORMAT_TYPE_III		0x3
> 
> +#define UAS_ENDPOINT_ASYNC		(1 << 2)
> +#define UAS_ENDPOINT_ADAPTIVE		(2 << 2)
> +#define UAS_ENDPOINT_SYNC		(3 << 2)
> +

You can reuse the linux/usb/ch9.h definitions.

>  struct uac_iso_endpoint_descriptor {
>  	__u8  bLength;			/* in bytes: 7 */
>  	__u8  bDescriptorType;		/* USB_DT_CS_ENDPOINT */
> @@ -245,13 +281,16 @@
>  	__u8  bmAttributes;
>  	__u8  bLockDelayUnits;
>  	__le16 wLockDelay;
> -};
> +} __attribute__ ((packed));
>  #define UAC_ISO_ENDPOINT_DESC_SIZE	7
> 
>  #define UAC_EP_CS_ATTR_SAMPLE_RATE	0x01
>  #define UAC_EP_CS_ATTR_PITCH_CONTROL	0x02
>  #define UAC_EP_CS_ATTR_FILL_MAX		0x80
> 
> +#define UAC_EP_SAMPLE_FREQ	(1 << (UAC_EP_CS_ATTR_SAMPLE_RATE - 1))
> +#define UAC_EP_PITCH_CONTROL	(1 << (UAC_EP_CS_ATTR_PITCH_CONTROL - 1))
> +
>  /* A.10.2 Feature Unit Control Selectors */
>  #define UAC_FU_CONTROL_UNDEFINED	0x00
>  #define UAC_MUTE_CONTROL		0x01

-- 
Regards,

Laurent Pinchart
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux