📄 audio.c
字号:
printk(KERN_DEBUG "usbout_start: device %d ufmt 0x%08x dfmt 0x%08x srate %d\n", dev->devnum, u->format, u->dma.format, u->dma.srate);#endif /* allocate USB storage if not already done */ spin_lock_irqsave(&as->lock, flags); if (!(u->flags & FLG_CONNECTED)) { spin_unlock_irqrestore(&as->lock, flags); return -EIO; } if (!(u->flags & FLG_RUNNING)) { spin_unlock_irqrestore(&as->lock, flags); u->freqn = u->freqm = ((u->dma.srate << 11) + 62) / 125; /* this will overflow at approx 2MSPS */ u->freqmax = u->freqn + (u->freqn >> 2); u->phase = 0; maxsze = (u->freqmax + 0x3fff) >> (14 - AFMT_BYTESSHIFT(u->format)); bufsz = DESCFRAMES * maxsze; if (u->durb[0].urb.transfer_buffer) kfree(u->durb[0].urb.transfer_buffer); u->durb[0].urb.transfer_buffer = kmalloc(bufsz, GFP_KERNEL); u->durb[0].urb.transfer_buffer_length = bufsz; if (u->durb[1].urb.transfer_buffer) kfree(u->durb[1].urb.transfer_buffer); u->durb[1].urb.transfer_buffer = kmalloc(bufsz, GFP_KERNEL); u->durb[1].urb.transfer_buffer_length = bufsz; if (u->syncpipe) { if (u->surb[0].urb.transfer_buffer) kfree(u->surb[0].urb.transfer_buffer); u->surb[0].urb.transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); u->surb[0].urb.transfer_buffer_length = 3*SYNCFRAMES; if (u->surb[1].urb.transfer_buffer) kfree(u->surb[1].urb.transfer_buffer); u->surb[1].urb.transfer_buffer = kmalloc(3*SYNCFRAMES, GFP_KERNEL); u->surb[1].urb.transfer_buffer_length = 3*SYNCFRAMES; } if (!u->durb[0].urb.transfer_buffer || !u->durb[1].urb.transfer_buffer || (u->syncpipe && (!u->surb[0].urb.transfer_buffer || !u->surb[1].urb.transfer_buffer))) { printk(KERN_ERR "usbaudio: cannot start playback device %d\n", dev->devnum); return 0; } spin_lock_irqsave(&as->lock, flags); } u->flags |= FLG_RUNNING; if (!(u->flags & FLG_URB0RUNNING)) { urb = &u->durb[0].urb; urb->dev = dev; urb->pipe = u->datapipe; urb->transfer_flags = USB_ISO_ASAP; urb->number_of_packets = DESCFRAMES; urb->context = as; urb->complete = usbout_completed; if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb)) u->flags |= FLG_URB0RUNNING; else u->flags &= ~FLG_RUNNING; } if (u->flags & FLG_RUNNING && !(u->flags & FLG_URB1RUNNING)) { urb = &u->durb[1].urb; urb->dev = dev; urb->pipe = u->datapipe; urb->transfer_flags = USB_ISO_ASAP; urb->number_of_packets = DESCFRAMES; urb->context = as; urb->complete = usbout_completed; if (!usbout_prepare_desc(u, urb) && !usb_submit_urb(urb)) u->flags |= FLG_URB1RUNNING; else u->flags &= ~FLG_RUNNING; } if (u->syncpipe) { if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC0RUNNING)) { urb = &u->surb[0].urb; urb->dev = dev; urb->pipe = u->syncpipe; urb->transfer_flags = USB_ISO_ASAP; urb->number_of_packets = SYNCFRAMES; urb->context = as; urb->complete = usbout_sync_completed; /* stride: u->syncinterval */ if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb)) u->flags |= FLG_SYNC0RUNNING; else u->flags &= ~FLG_RUNNING; } if (u->flags & FLG_RUNNING && !(u->flags & FLG_SYNC1RUNNING)) { urb = &u->surb[1].urb; urb->dev = dev; urb->pipe = u->syncpipe; urb->transfer_flags = USB_ISO_ASAP; urb->number_of_packets = SYNCFRAMES; urb->context = as; urb->complete = usbout_sync_completed; /* stride: u->syncinterval */ if (!usbout_sync_prepare_desc(u, urb) && !usb_submit_urb(urb)) u->flags |= FLG_SYNC1RUNNING; else u->flags &= ~FLG_RUNNING; } } spin_unlock_irqrestore(&as->lock, flags); return 0;}/* --------------------------------------------------------------------- */static unsigned int find_format(struct audioformat *afp, unsigned int nr, unsigned int fmt){ unsigned int i; /* first find an exact match */ for (i = 0; i < nr; i++) if (afp[i].format == fmt) return i; /* second find a match with the same stereo/mono and 8bit/16bit property */ for (i = 0; i < nr; i++) if (!AFMT_ISSTEREO(afp[i].format) == !AFMT_ISSTEREO(fmt) && !AFMT_IS16BIT(afp[i].format) == !AFMT_IS16BIT(fmt)) return i; /* third find a match with the same number of channels */ for (i = 0; i < nr; i++) if (!AFMT_ISSTEREO(afp[i].format) == !AFMT_ISSTEREO(fmt)) return i; /* return anything */ return 0;}static int set_format_in(struct usb_audiodev *as){ struct usb_device *dev = as->state->usbdev; struct usb_config_descriptor *config = dev->actconfig; struct usb_interface_descriptor *alts; struct usb_interface *iface; struct usbin *u = &as->usbin; struct dmabuf *d = &u->dma; struct audioformat *fmt; unsigned int fmtnr, ep; unsigned char data[3]; int ret; if (u->interface < 0 || u->interface >= config->bNumInterfaces) return 0; iface = &config->interface[u->interface]; fmtnr = find_format(as->fmtin, as->numfmtin, d->format); fmt = as->fmtin + fmtnr; alts = &iface->altsetting[fmt->altsetting]; u->format = fmt->format; u->datapipe = usb_rcvisocpipe(dev, alts->endpoint[0].bEndpointAddress & 0xf); u->syncpipe = u->syncinterval = 0; if ((alts->endpoint[0].bmAttributes & 0x0c) == 0x08) { if (alts->bNumEndpoints < 2 || alts->endpoint[1].bmAttributes != 0x01 || alts->endpoint[1].bSynchAddress != 0 || alts->endpoint[1].bEndpointAddress != (alts->endpoint[0].bSynchAddress & 0x7f)) { printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n", dev->devnum, u->interface, fmt->altsetting); return -1; } u->syncpipe = usb_sndisocpipe(dev, alts->endpoint[1].bEndpointAddress & 0xf); u->syncinterval = alts->endpoint[1].bRefresh; } if (d->srate < fmt->sratelo) d->srate = fmt->sratelo; if (d->srate > fmt->sratehi) d->srate = fmt->sratehi;printk(KERN_DEBUG "usb_audio: set_format_in: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting); if (usb_set_interface(dev, alts->bInterfaceNumber, fmt->altsetting) < 0) { printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n", dev->devnum, u->interface, fmt->altsetting); return -1; } if (fmt->sratelo == fmt->sratehi) return 0; ep = usb_pipeendpoint(u->datapipe) | (u->datapipe & USB_DIR_IN); /* if endpoint has pitch control, enable it */ if (fmt->attributes & 0x02) { data[0] = 1; if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) { printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n", ret, dev->devnum, u->interface, ep, d->srate); return -1; } } /* if endpoint has sampling rate control, set it */ if (fmt->attributes & 0x01) { data[0] = d->srate; data[1] = d->srate >> 8; data[2] = d->srate >> 16; if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) { printk(KERN_ERR "usbaudio: failure (error %d) to set input sampling frequency device %d interface %u endpoint 0x%x to %u\n", ret, dev->devnum, u->interface, ep, d->srate); return -1; } if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN, SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) { printk(KERN_ERR "usbaudio: failure (error %d) to get input sampling frequency device %d interface %u endpoint 0x%x\n", ret, dev->devnum, u->interface, ep); return -1; } printk(KERN_DEBUG "usbaudio: set_format_in: device %d interface %d altsetting %d srate req: %u real %u\n", dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16)); d->srate = data[0] | (data[1] << 8) | (data[2] << 16); } return 0;}static int set_format_out(struct usb_audiodev *as){ struct usb_device *dev = as->state->usbdev; struct usb_config_descriptor *config = dev->actconfig; struct usb_interface_descriptor *alts; struct usb_interface *iface; struct usbout *u = &as->usbout; struct dmabuf *d = &u->dma; struct audioformat *fmt; unsigned int fmtnr, ep; unsigned char data[3]; int ret; if (u->interface < 0 || u->interface >= config->bNumInterfaces) return 0; iface = &config->interface[u->interface]; fmtnr = find_format(as->fmtout, as->numfmtout, d->format); fmt = as->fmtout + fmtnr; u->format = fmt->format; alts = &iface->altsetting[fmt->altsetting]; u->datapipe = usb_sndisocpipe(dev, alts->endpoint[0].bEndpointAddress & 0xf); u->syncpipe = u->syncinterval = 0; if ((alts->endpoint[0].bmAttributes & 0x0c) == 0x04) {#if 0 printk(KERN_DEBUG "bNumEndpoints 0x%02x endpoint[1].bmAttributes 0x%02x\n" KERN_DEBUG "endpoint[1].bSynchAddress 0x%02x endpoint[1].bEndpointAddress 0x%02x\n" KERN_DEBUG "endpoint[0].bSynchAddress 0x%02x\n", alts->bNumEndpoints, alts->endpoint[1].bmAttributes, alts->endpoint[1].bSynchAddress, alts->endpoint[1].bEndpointAddress, alts->endpoint[0].bSynchAddress);#endif if (alts->bNumEndpoints < 2 || alts->endpoint[1].bmAttributes != 0x01 || alts->endpoint[1].bSynchAddress != 0 || alts->endpoint[1].bEndpointAddress != (alts->endpoint[0].bSynchAddress | 0x80)) { printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n", dev->devnum, u->interface, fmt->altsetting); return -1; } u->syncpipe = usb_rcvisocpipe(dev, alts->endpoint[1].bEndpointAddress & 0xf); u->syncinterval = alts->endpoint[1].bRefresh; } if (d->srate < fmt->sratelo) d->srate = fmt->sratelo; if (d->srate > fmt->sratehi) d->srate = fmt->sratehi;printk(KERN_DEBUG "usb_audio: set_format_out: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting); if (usb_set_interface(dev, u->interface, fmt->altsetting) < 0) { printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n", dev->devnum, u->interface, fmt->altsetting); return -1; } if (fmt->sratelo == fmt->sratehi) return 0; ep = usb_pipeendpoint(u->datapipe) | (u->datapipe & USB_DIR_IN); /* if endpoint has pitch control, enable it */ if (fmt->attributes & 0x02) { data[0] = 1; if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) { printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n", ret, dev->devnum, u->interface, ep, d->srate); return -1; } } /* if endpoint has sampling rate control, set it */ if (fmt->attributes & 0x01) { data[0] = d->srate; data[1] = d->srate >> 8; data[2] = d->srate >> 16; if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) { printk(KERN_ERR "usbaudio: failure (error %d) to set output sampling frequency device %d interface %u endpoint 0x%x to %u\n", ret, dev->devnum, u->interface, ep, d->srate); return -1; } if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN, SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) { printk(KERN_ERR "usbaudio: failure (error %d) to get output sampling frequency device %d interface %u endpoint 0x%x\n", ret, dev->devnum, u->interface, ep); return -1; } printk(KERN_DEBUG "usbaudio: set_format_out: device %d interface %d altsetting %d srate req: %u real %u\n", dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16)); d->srate = data[0] | (data[1] << 8) | (data[2] << 16); } return 0;}static int set_format(struct usb_audiodev *s, unsigned int fmode, unsigned int fmt, unsigned int srate){ int ret1 = 0, ret2 = 0; if (!(fmode & (FMODE_READ|FMODE_WRITE))) return -EINVAL; if (fmode & FMODE_READ) { usbin_stop(s); s->usbin.dma.ready = 0; if (fmt == AFMT_QUERY) fmt = s->usbin.dma.format; else s->usbin.dma.format = fmt; if (!srate) srate = s->usbin.dma.srate; else s->usbin.dma.srate = srate; } if (fmode & FMODE_WRITE) { usbout_stop(s); s->usbout.dma.ready = 0; if (fmt == AFMT_QUERY) fmt = s->usbout.dma.format; else s->usbout.dma.format = fmt; if (!srate) srate = s->usbout.dma.srate; else s->usbout.dma.srate = srate; } if (fmode & FMODE_READ) ret1 = set_format_in(s); if (fmode & FMODE_WRITE) ret2 = set_format_out(s); return ret1 ? ret1 : ret2;}/* --------------------------------------------------------------------- */static int wrmixer(struct usb_mixerdev *ms, unsigned mixch, unsigned value){ struct usb_device *dev = ms->state->usbdev; unsigned char data[2]; struct mixerchannel *ch; int v1, v2, v3; if (mixch >= ms->numch) return -1; ch = &ms->ch[mixch]; v3 = ch->maxval - ch->minval; v1 = value & 0xff; v2 = (value >> 8) & 0xff; if (v1 > 100) v1 = 100; if (v2 > 100) v2 = 100; if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))) v2 = v1; ch->value = v1 | (v2 << 8); v1 = (v1 * v3) / 100 + ch->minval; v2 = (v2 * v3) / 100 + ch->minval; switch (ch->selector) { case 0: /* mixer unit request */ data[0] = v1; data[1] = v1 >> 8; if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, (ch->chnum << 8) | 1, ms->iface | (ch->unitid << 8), data, 2, HZ) < 0) goto err; if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT))) return 0; data[0] = v2; data[1] = v2 >> 8; if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, ((ch->chnum + !!(ch->flags & MIXFLG_STEREOIN)) << 8) | (1 + !!(ch->flags & MIXFLG_STEREOOUT)), ms->iface | (ch->unitid << 8), data, 2, HZ) < 0) goto err; return 0; /* various feature unit controls */ case VOLUME_CONTROL: data[0] = v1; data[1] = v1 >> 8; if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 2, HZ) < 0) goto err; if (ch->chnum == 0) return 0; data[0] = v2; data[1] = v2 >> 8; if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 2, HZ) < 0) goto err; return 0; case BASS_CONTROL: case MID_CONTROL: case TREBLE_CONTROL: data[0] = v1 >> 8; if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 1, HZ) < 0) goto err; if (ch->chnum == 0) return 0; data[0] = v2 >> 8; if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 1, HZ) < 0) goto err; return 0; default: return -1; } return 0; err: printk(KERN_ERR "usbaudio: mixer request device %u if %u unit %u ch %u selector %u failed\n", dev->devnum, ms->iface, ch->unitid, ch->chnum, ch->selector); return -1;}/* --------------------------------------------------------------------- *//* * should be called with open_sem hold, so that no new processes * look at the audio device to be destroyed */static void release(struct usb_audio_state *s){ struct usb_audiodev *as; struct usb_mixerdev *ms; s->count--; if (s->count) { up(&open_sem); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -