在项目中遇到一个usb摄像头无法正常录音的问题,而其他usb camera都可以正常工作。因此查询这个usb camera在录音的时候有什么不同的地方,发现用这个usb camera录音的时候总是打印 “cannot get freq at ep 0x84 ", 在kernel中grep了一把,是sound/usb/clock.c中打印的一句warning:
static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
struct usb_host_interface *alts,
struct audioformat *fmt, int rate)
{
struct usb_device *dev = chip->dev;
unsigned int ep;
unsigned char data[3];
int err, crate;
ep = get_endpoint(alts, 0)->bEndpointAddress;
/* if endpoint doesn't have sampling rate control, bail out */
if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE))
return 0;
data[0] = rate;
data[1] = rate >> 8;
data[2] = rate >> 16;
if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
data, sizeof(data), 1000)) < 0) {
snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
dev->devnum, iface, fmt->altsetting, rate, ep);
return err;
}
if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN,
UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
data, sizeof(data), 1000)) < 0) {
snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
dev->devnum, iface, fmt->altsetting, ep);
return 0; /* some devices don't support reading */
}
crate = data[0] | (data[1] << 8) | (data[2] << 16);
if (crate != rate) {
snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
// runtime->rate = crate;
}
return 0;
}
虽然usb_audio功能在平台实现了,但是对usb的知识还是有所欠缺,因此向google求助。
http://comments.gmane.org/gmane.linux.alsa.user/36523
在这个讨论交流里我了解问题大概是usb camera 本身的firmware 有buggy, 只要将其对应的mixer设置正确就可以了。
因此我在串口中输入了命令:
tinymix -D 1
root@android:/proc/asound # tinymix -D 1
Number of controls: 2
ctl type num name value
0 BOOL 1 Mic Capture Switch On
1 INT 1 Mic Capture Volume 8191
然后再去录音就可以正常录音了,因此看了一下tinymix -D 1所走的code流程:
int main(int argc, char **argv)
{
struct mixer *mixer;
int card = 0;
if ((argc > 2) && (strcmp(argv[1], "-D") == 0)) {
argv++;
if (argv[1]) {
card = atoi(argv[1]);
argv++;
argc -= 2;
} else {
argc -= 1;
}
}
mixer = mixer_open(card);
if (!mixer) {
fprintf(stderr, "Failed to open mixer\n");
return EXIT_FAILURE;
}
if (argc == 1)
tinymix_list_controls(mixer);
else if (argc == 2)
tinymix_detail_control(mixer, atoi(argv[1]), 1);
else if (argc == 3)
tinymix_set_value(mixer, atoi(argv[1]), argv[2]);
else
printf("Usage: tinymix [-D card] [control id] [value to set]\n");
mixer_close(mixer);
return 0;
}
因此我在usb_audio的HAL层也去做了相同的操作:
<strong>capture:</strong>
static int adev_open_input_stream(struct audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
struct audio_config *config,
struct audio_stream_in **stream_in)
{
…………
…………
struct mixer *usb_mixer;
…………
usb_mixer = mixer_open(adev->card);
if (!usb_mixer) {
ALOGE("Unable to open the mixer, aborting.");
goto err_open;
}
…………
err_open:
…………
mixer_close(usb_mixer);
…………
return ret;
}
<strong>playback:</strong>
static int adev_open_output_stream(struct audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
audio_output_flags_t flags,
struct audio_config *config,
struct audio_stream_out **stream_out)
{
…………
struct mixer *usb_mixer;
…………
usb_mixer = mixer_open(adev->card);
if (!usb_mixer) {
ALOGE("Unable to open the mixer, aborting.");
goto err_open;
}
…………
err_open:
mixer_close(usb_mixer);
…………
return ret;
}
*********************************欢迎各位交流指正********************************************************