2010-03-04 21:46:13 +03:00
/*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include <linux/init.h>
2010-03-29 09:02:50 +04:00
# include <linux/slab.h>
2010-03-04 21:46:13 +03:00
# include <linux/usb.h>
# include <linux/usb/audio.h>
2011-05-25 11:09:01 +04:00
# include <sound/control.h>
2010-03-04 21:46:13 +03:00
# include <sound/core.h>
# include <sound/info.h>
# include <sound/pcm.h>
# include "usbaudio.h"
# include "card.h"
2010-03-11 23:13:23 +03:00
# include "mixer.h"
2010-03-11 23:13:22 +03:00
# include "mixer_quirks.h"
2010-03-04 21:46:13 +03:00
# include "midi.h"
# include "quirks.h"
# include "helper.h"
# include "endpoint.h"
# include "pcm.h"
2010-06-16 19:57:31 +04:00
# include "clock.h"
2011-09-12 20:54:12 +04:00
# include "stream.h"
2010-03-04 21:46:13 +03:00
/*
* handle the quirks for the contained interfaces
*/
static int create_composite_quirk ( struct snd_usb_audio * chip ,
struct usb_interface * iface ,
struct usb_driver * driver ,
const struct snd_usb_audio_quirk * quirk )
{
int probed_ifnum = get_iface_desc ( iface - > altsetting ) - > bInterfaceNumber ;
int err ;
for ( quirk = quirk - > data ; quirk - > ifnum > = 0 ; + + quirk ) {
iface = usb_ifnum_to_if ( chip - > dev , quirk - > ifnum ) ;
if ( ! iface )
continue ;
if ( quirk - > ifnum ! = probed_ifnum & &
usb_interface_claimed ( iface ) )
continue ;
err = snd_usb_create_quirk ( chip , iface , driver , quirk ) ;
if ( err < 0 )
return err ;
if ( quirk - > ifnum ! = probed_ifnum )
usb_driver_claim_interface ( driver , iface , ( void * ) - 1L ) ;
}
return 0 ;
}
static int ignore_interface_quirk ( struct snd_usb_audio * chip ,
struct usb_interface * iface ,
struct usb_driver * driver ,
const struct snd_usb_audio_quirk * quirk )
{
return 0 ;
}
/*
* Allow alignment on audio sub - slot ( channel samples ) rather than
* on audio slots ( audio frames )
*/
static int create_align_transfer_quirk ( struct snd_usb_audio * chip ,
struct usb_interface * iface ,
struct usb_driver * driver ,
const struct snd_usb_audio_quirk * quirk )
{
chip - > txfr_quirk = 1 ;
return 1 ; /* Continue with creating streams and mixer */
}
static int create_any_midi_quirk ( struct snd_usb_audio * chip ,
struct usb_interface * intf ,
struct usb_driver * driver ,
const struct snd_usb_audio_quirk * quirk )
{
return snd_usbmidi_create ( chip - > card , intf , & chip - > midi_list , quirk ) ;
}
/*
* create a stream for an interface with proper descriptors
*/
static int create_standard_audio_quirk ( struct snd_usb_audio * chip ,
struct usb_interface * iface ,
struct usb_driver * driver ,
const struct snd_usb_audio_quirk * quirk )
{
struct usb_host_interface * alts ;
struct usb_interface_descriptor * altsd ;
int err ;
alts = & iface - > altsetting [ 0 ] ;
altsd = get_iface_desc ( alts ) ;
2011-09-12 20:54:12 +04:00
err = snd_usb_parse_audio_interface ( chip , altsd - > bInterfaceNumber ) ;
2010-03-04 21:46:13 +03:00
if ( err < 0 ) {
snd_printk ( KERN_ERR " cannot setup if %d: error %d \n " ,
altsd - > bInterfaceNumber , err ) ;
return err ;
}
/* reset the current interface */
usb_set_interface ( chip - > dev , altsd - > bInterfaceNumber , 0 ) ;
return 0 ;
}
/*
* create a stream for an endpoint / altsetting without proper descriptors
*/
static int create_fixed_stream_quirk ( struct snd_usb_audio * chip ,
struct usb_interface * iface ,
struct usb_driver * driver ,
const struct snd_usb_audio_quirk * quirk )
{
struct audioformat * fp ;
struct usb_host_interface * alts ;
int stream , err ;
unsigned * rate_table = NULL ;
fp = kmemdup ( quirk - > data , sizeof ( * fp ) , GFP_KERNEL ) ;
2012-02-14 14:18:48 +04:00
if ( ! fp ) {
2010-03-04 21:46:13 +03:00
snd_printk ( KERN_ERR " cannot memdup \n " ) ;
return - ENOMEM ;
}
2012-02-14 14:18:48 +04:00
if ( fp - > nr_rates > MAX_NR_RATES ) {
kfree ( fp ) ;
return - EINVAL ;
}
2010-03-04 21:46:13 +03:00
if ( fp - > nr_rates > 0 ) {
2011-11-10 22:38:43 +04:00
rate_table = kmemdup ( fp - > rate_table ,
sizeof ( int ) * fp - > nr_rates , GFP_KERNEL ) ;
2010-03-04 21:46:13 +03:00
if ( ! rate_table ) {
kfree ( fp ) ;
return - ENOMEM ;
}
fp - > rate_table = rate_table ;
}
stream = ( fp - > endpoint & USB_DIR_IN )
? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK ;
2011-09-12 20:54:12 +04:00
err = snd_usb_add_audio_stream ( chip , stream , fp ) ;
2010-03-04 21:46:13 +03:00
if ( err < 0 ) {
kfree ( fp ) ;
kfree ( rate_table ) ;
return err ;
}
if ( fp - > iface ! = get_iface_desc ( & iface - > altsetting [ 0 ] ) - > bInterfaceNumber | |
fp - > altset_idx > = iface - > num_altsetting ) {
kfree ( fp ) ;
kfree ( rate_table ) ;
return - EINVAL ;
}
alts = & iface - > altsetting [ fp - > altset_idx ] ;
fp - > datainterval = snd_usb_parse_datainterval ( chip , alts ) ;
fp - > maxpacksize = le16_to_cpu ( get_endpoint ( alts , 0 ) - > wMaxPacketSize ) ;
usb_set_interface ( chip - > dev , fp - > iface , 0 ) ;
2010-03-04 21:46:17 +03:00
snd_usb_init_pitch ( chip , fp - > iface , alts , fp ) ;
snd_usb_init_sample_rate ( chip , fp - > iface , alts , fp , fp - > rate_max ) ;
2010-03-04 21:46:13 +03:00
return 0 ;
}
/*
* Create a stream for an Edirol UA - 700 / UA - 25 / UA - 4F X interface .
* The only way to detect the sample rate is by looking at wMaxPacketSize .
*/
static int create_uaxx_quirk ( struct snd_usb_audio * chip ,
struct usb_interface * iface ,
struct usb_driver * driver ,
const struct snd_usb_audio_quirk * quirk )
{
static const struct audioformat ua_format = {
2010-03-04 21:46:15 +03:00
. formats = SNDRV_PCM_FMTBIT_S24_3LE ,
2010-03-04 21:46:13 +03:00
. channels = 2 ,
. fmt_type = UAC_FORMAT_TYPE_I ,
. altsetting = 1 ,
. altset_idx = 1 ,
. rates = SNDRV_PCM_RATE_CONTINUOUS ,
} ;
struct usb_host_interface * alts ;
struct usb_interface_descriptor * altsd ;
struct audioformat * fp ;
int stream , err ;
/* both PCM and MIDI interfaces have 2 or more altsettings */
if ( iface - > num_altsetting < 2 )
return - ENXIO ;
alts = & iface - > altsetting [ 1 ] ;
altsd = get_iface_desc ( alts ) ;
if ( altsd - > bNumEndpoints = = 2 ) {
static const struct snd_usb_midi_endpoint_info ua700_ep = {
. out_cables = 0x0003 ,
. in_cables = 0x0003
} ;
static const struct snd_usb_audio_quirk ua700_quirk = {
. type = QUIRK_MIDI_FIXED_ENDPOINT ,
. data = & ua700_ep
} ;
static const struct snd_usb_midi_endpoint_info uaxx_ep = {
. out_cables = 0x0001 ,
. in_cables = 0x0001
} ;
static const struct snd_usb_audio_quirk uaxx_quirk = {
. type = QUIRK_MIDI_FIXED_ENDPOINT ,
. data = & uaxx_ep
} ;
const struct snd_usb_audio_quirk * quirk =
chip - > usb_id = = USB_ID ( 0x0582 , 0x002b )
? & ua700_quirk : & uaxx_quirk ;
return snd_usbmidi_create ( chip - > card , iface ,
& chip - > midi_list , quirk ) ;
}
if ( altsd - > bNumEndpoints ! = 1 )
return - ENXIO ;
2011-11-10 22:38:43 +04:00
fp = kmemdup ( & ua_format , sizeof ( * fp ) , GFP_KERNEL ) ;
2010-03-04 21:46:13 +03:00
if ( ! fp )
return - ENOMEM ;
fp - > iface = altsd - > bInterfaceNumber ;
fp - > endpoint = get_endpoint ( alts , 0 ) - > bEndpointAddress ;
fp - > ep_attr = get_endpoint ( alts , 0 ) - > bmAttributes ;
fp - > datainterval = 0 ;
fp - > maxpacksize = le16_to_cpu ( get_endpoint ( alts , 0 ) - > wMaxPacketSize ) ;
switch ( fp - > maxpacksize ) {
case 0x120 :
fp - > rate_max = fp - > rate_min = 44100 ;
break ;
case 0x138 :
case 0x140 :
fp - > rate_max = fp - > rate_min = 48000 ;
break ;
case 0x258 :
case 0x260 :
fp - > rate_max = fp - > rate_min = 96000 ;
break ;
default :
snd_printk ( KERN_ERR " unknown sample rate \n " ) ;
kfree ( fp ) ;
return - ENXIO ;
}
stream = ( fp - > endpoint & USB_DIR_IN )
? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK ;
2011-09-12 20:54:12 +04:00
err = snd_usb_add_audio_stream ( chip , stream , fp ) ;
2010-03-04 21:46:13 +03:00
if ( err < 0 ) {
kfree ( fp ) ;
return err ;
}
usb_set_interface ( chip - > dev , fp - > iface , 0 ) ;
return 0 ;
}
2011-05-25 11:09:02 +04:00
/*
* Create a standard mixer for the specified interface .
*/
static int create_standard_mixer_quirk ( struct snd_usb_audio * chip ,
struct usb_interface * iface ,
struct usb_driver * driver ,
const struct snd_usb_audio_quirk * quirk )
{
if ( quirk - > ifnum < 0 )
return 0 ;
return snd_usb_create_mixer ( chip , quirk - > ifnum , 0 ) ;
}
2010-03-04 21:46:13 +03:00
/*
* audio - interface quirks
*
* returns zero if no standard audio / MIDI parsing is needed .
2011-03-31 05:57:33 +04:00
* returns a positive value if standard audio / midi interfaces are parsed
2010-03-04 21:46:13 +03:00
* after this .
* returns a negative value at error .
*/
int snd_usb_create_quirk ( struct snd_usb_audio * chip ,
struct usb_interface * iface ,
struct usb_driver * driver ,
const struct snd_usb_audio_quirk * quirk )
{
typedef int ( * quirk_func_t ) ( struct snd_usb_audio * ,
struct usb_interface * ,
struct usb_driver * ,
const struct snd_usb_audio_quirk * ) ;
static const quirk_func_t quirk_funcs [ ] = {
[ QUIRK_IGNORE_INTERFACE ] = ignore_interface_quirk ,
[ QUIRK_COMPOSITE ] = create_composite_quirk ,
[ QUIRK_MIDI_STANDARD_INTERFACE ] = create_any_midi_quirk ,
[ QUIRK_MIDI_FIXED_ENDPOINT ] = create_any_midi_quirk ,
[ QUIRK_MIDI_YAMAHA ] = create_any_midi_quirk ,
[ QUIRK_MIDI_MIDIMAN ] = create_any_midi_quirk ,
[ QUIRK_MIDI_NOVATION ] = create_any_midi_quirk ,
2010-10-22 20:20:48 +04:00
[ QUIRK_MIDI_RAW_BYTES ] = create_any_midi_quirk ,
2010-03-04 21:46:13 +03:00
[ QUIRK_MIDI_EMAGIC ] = create_any_midi_quirk ,
[ QUIRK_MIDI_CME ] = create_any_midi_quirk ,
2010-05-20 23:31:10 +04:00
[ QUIRK_MIDI_AKAI ] = create_any_midi_quirk ,
2011-08-26 15:19:49 +04:00
[ QUIRK_MIDI_FTDI ] = create_any_midi_quirk ,
2010-03-04 21:46:13 +03:00
[ QUIRK_AUDIO_STANDARD_INTERFACE ] = create_standard_audio_quirk ,
[ QUIRK_AUDIO_FIXED_ENDPOINT ] = create_fixed_stream_quirk ,
[ QUIRK_AUDIO_EDIROL_UAXX ] = create_uaxx_quirk ,
2011-05-25 11:09:02 +04:00
[ QUIRK_AUDIO_ALIGN_TRANSFER ] = create_align_transfer_quirk ,
[ QUIRK_AUDIO_STANDARD_MIXER ] = create_standard_mixer_quirk ,
2010-03-04 21:46:13 +03:00
} ;
if ( quirk - > type < QUIRK_TYPE_COUNT ) {
return quirk_funcs [ quirk - > type ] ( chip , iface , driver , quirk ) ;
} else {
snd_printd ( KERN_ERR " invalid quirk type %d \n " , quirk - > type ) ;
return - ENXIO ;
}
}
/*
* boot quirks
*/
# define EXTIGY_FIRMWARE_SIZE_OLD 794
# define EXTIGY_FIRMWARE_SIZE_NEW 483
static int snd_usb_extigy_boot_quirk ( struct usb_device * dev , struct usb_interface * intf )
{
struct usb_host_config * config = dev - > actconfig ;
int err ;
if ( le16_to_cpu ( get_cfg_desc ( config ) - > wTotalLength ) = = EXTIGY_FIRMWARE_SIZE_OLD | |
le16_to_cpu ( get_cfg_desc ( config ) - > wTotalLength ) = = EXTIGY_FIRMWARE_SIZE_NEW ) {
snd_printdd ( " sending Extigy boot sequence... \n " ) ;
/* Send message to force it to reconnect with full interface. */
err = snd_usb_ctl_msg ( dev , usb_sndctrlpipe ( dev , 0 ) ,
2011-09-26 23:15:27 +04:00
0x10 , 0x43 , 0x0001 , 0x000a , NULL , 0 ) ;
2010-03-04 21:46:13 +03:00
if ( err < 0 ) snd_printdd ( " error sending boot message: %d \n " , err ) ;
err = usb_get_descriptor ( dev , USB_DT_DEVICE , 0 ,
& dev - > descriptor , sizeof ( dev - > descriptor ) ) ;
config = dev - > actconfig ;
if ( err < 0 ) snd_printdd ( " error usb_get_descriptor: %d \n " , err ) ;
err = usb_reset_configuration ( dev ) ;
if ( err < 0 ) snd_printdd ( " error usb_reset_configuration: %d \n " , err ) ;
snd_printdd ( " extigy_boot: new boot length = %d \n " ,
le16_to_cpu ( get_cfg_desc ( config ) - > wTotalLength ) ) ;
return - ENODEV ; /* quit this anyway */
}
return 0 ;
}
static int snd_usb_audigy2nx_boot_quirk ( struct usb_device * dev )
{
u8 buf = 1 ;
snd_usb_ctl_msg ( dev , usb_rcvctrlpipe ( dev , 0 ) , 0x2a ,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER ,
2011-09-26 23:15:27 +04:00
0 , 0 , & buf , 1 ) ;
2010-03-04 21:46:13 +03:00
if ( buf = = 0 ) {
snd_usb_ctl_msg ( dev , usb_sndctrlpipe ( dev , 0 ) , 0x29 ,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER ,
2011-09-26 23:15:27 +04:00
1 , 2000 , NULL , 0 ) ;
2010-03-04 21:46:13 +03:00
return - ENODEV ;
}
return 0 ;
}
2011-07-12 20:13:46 +04:00
static int snd_usb_fasttrackpro_boot_quirk ( struct usb_device * dev )
{
int err ;
if ( dev - > actconfig - > desc . bConfigurationValue = = 1 ) {
snd_printk ( KERN_INFO " usb-audio: "
" Fast Track Pro switching to config #2 \n " ) ;
/* This function has to be available by the usb core module.
* if it is not avialable the boot quirk has to be left out
* and the configuration has to be set by udev or hotplug
* rules
*/
err = usb_driver_set_configuration ( dev , 2 ) ;
2013-01-04 20:02:18 +04:00
if ( err < 0 )
2011-07-12 20:13:46 +04:00
snd_printdd ( " error usb_driver_set_configuration: %d \n " ,
err ) ;
2013-01-04 20:02:18 +04:00
/* Always return an error, so that we stop creating a device
that will just be destroyed and recreated with a new
configuration */
return - ENODEV ;
2011-07-12 20:13:46 +04:00
} else
snd_printk ( KERN_INFO " usb-audio: Fast Track Pro config OK \n " ) ;
return 0 ;
}
2010-03-04 21:46:13 +03:00
/*
* C - Media CM106 / CM106 + have four 16 - bit internal registers that are nicely
* documented in the device ' s data sheet .
*/
static int snd_usb_cm106_write_int_reg ( struct usb_device * dev , int reg , u16 value )
{
u8 buf [ 4 ] ;
buf [ 0 ] = 0x20 ;
buf [ 1 ] = value & 0xff ;
buf [ 2 ] = ( value > > 8 ) & 0xff ;
buf [ 3 ] = reg ;
return snd_usb_ctl_msg ( dev , usb_sndctrlpipe ( dev , 0 ) , USB_REQ_SET_CONFIGURATION ,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT ,
2011-09-26 23:15:27 +04:00
0 , 0 , & buf , 4 ) ;
2010-03-04 21:46:13 +03:00
}
static int snd_usb_cm106_boot_quirk ( struct usb_device * dev )
{
/*
* Enable line - out driver mode , set headphone source to front
* channels , enable stereo mic .
*/
return snd_usb_cm106_write_int_reg ( dev , 2 , 0x8004 ) ;
}
/*
* C - Media CM6206 is based on CM106 with two additional
* registers that are not documented in the data sheet .
* Values here are chosen based on sniffing USB traffic
* under Windows .
*/
static int snd_usb_cm6206_boot_quirk ( struct usb_device * dev )
{
2011-08-06 02:23:18 +04:00
int err = 0 , reg ;
2011-05-28 02:16:52 +04:00
int val [ ] = { 0x2004 , 0x3000 , 0xf800 , 0x143f , 0x0000 , 0x3000 } ;
2010-03-04 21:46:13 +03:00
for ( reg = 0 ; reg < ARRAY_SIZE ( val ) ; reg + + ) {
err = snd_usb_cm106_write_int_reg ( dev , reg , val [ reg ] ) ;
if ( err < 0 )
return err ;
}
return err ;
}
/*
* This call will put the synth in " USB send " mode , i . e it will send MIDI
* messages through USB ( this is disabled at startup ) . The synth will
* acknowledge by sending a sysex on endpoint 0x85 and by displaying a USB
* sign on its LCD . Values here are chosen based on sniffing USB traffic
* under Windows .
*/
static int snd_usb_accessmusic_boot_quirk ( struct usb_device * dev )
{
int err , actual_length ;
/* "midi send" enable */
static const u8 seq [ ] = { 0x4e , 0x73 , 0x52 , 0x01 } ;
void * buf = kmemdup ( seq , ARRAY_SIZE ( seq ) , GFP_KERNEL ) ;
if ( ! buf )
return - ENOMEM ;
err = usb_interrupt_msg ( dev , usb_sndintpipe ( dev , 0x05 ) , buf ,
ARRAY_SIZE ( seq ) , & actual_length , 1000 ) ;
kfree ( buf ) ;
if ( err < 0 )
return err ;
return 0 ;
}
2011-02-11 14:08:06 +03:00
/*
* Some sound cards from Native Instruments are in fact compliant to the USB
* audio standard of version 2 and other approved USB standards , even though
* they come up as vendor - specific device when first connected .
*
* However , they can be told to come up with a new set of descriptors
* upon their next enumeration , and the interfaces announced by the new
* descriptors will then be handled by the kernel ' s class drivers . As the
* product ID will also change , no further checks are required .
*/
static int snd_usb_nativeinstruments_boot_quirk ( struct usb_device * dev )
{
int ret = usb_control_msg ( dev , usb_sndctrlpipe ( dev , 0 ) ,
0xaf , USB_TYPE_VENDOR | USB_RECIP_DEVICE ,
cpu_to_le16 ( 1 ) , 0 , NULL , 0 , 1000 ) ;
if ( ret < 0 )
return ret ;
usb_reset_device ( dev ) ;
/* return -EAGAIN, so the creation of an audio interface for this
* temporary device is aborted . The device will reconnect with a
* new product ID */
return - EAGAIN ;
}
2012-12-19 14:27:22 +04:00
static void mbox2_setup_48_24_magic ( struct usb_device * dev )
{
u8 srate [ 3 ] ;
u8 temp [ 12 ] ;
/* Choose 48000Hz permanently */
srate [ 0 ] = 0x80 ;
srate [ 1 ] = 0xbb ;
srate [ 2 ] = 0x00 ;
/* Send the magic! */
snd_usb_ctl_msg ( dev , usb_rcvctrlpipe ( dev , 0 ) ,
0x01 , 0x22 , 0x0100 , 0x0085 , & temp , 0x0003 ) ;
snd_usb_ctl_msg ( dev , usb_sndctrlpipe ( dev , 0 ) ,
0x81 , 0xa2 , 0x0100 , 0x0085 , & srate , 0x0003 ) ;
snd_usb_ctl_msg ( dev , usb_sndctrlpipe ( dev , 0 ) ,
0x81 , 0xa2 , 0x0100 , 0x0086 , & srate , 0x0003 ) ;
snd_usb_ctl_msg ( dev , usb_sndctrlpipe ( dev , 0 ) ,
0x81 , 0xa2 , 0x0100 , 0x0003 , & srate , 0x0003 ) ;
return ;
}
/* Digidesign Mbox 2 needs to load firmware onboard
* and driver must wait a few seconds for initialisation .
*/
# define MBOX2_FIRMWARE_SIZE 646
# define MBOX2_BOOT_LOADING 0x01 /* Hard coded into the device */
# define MBOX2_BOOT_READY 0x02 /* Hard coded into the device */
2013-01-04 12:51:44 +04:00
static int snd_usb_mbox2_boot_quirk ( struct usb_device * dev )
2012-12-19 14:27:22 +04:00
{
struct usb_host_config * config = dev - > actconfig ;
int err ;
2013-01-04 12:51:44 +04:00
u8 bootresponse [ 12 ] ;
2012-12-19 14:27:22 +04:00
int fwsize ;
int count ;
fwsize = le16_to_cpu ( get_cfg_desc ( config ) - > wTotalLength ) ;
if ( fwsize ! = MBOX2_FIRMWARE_SIZE ) {
snd_printk ( KERN_ERR " usb-audio: Invalid firmware size=%d. \n " , fwsize ) ;
return - ENODEV ;
}
snd_printd ( " usb-audio: Sending Digidesign Mbox 2 boot sequence... \n " ) ;
count = 0 ;
2013-01-04 12:51:44 +04:00
bootresponse [ 0 ] = MBOX2_BOOT_LOADING ;
while ( ( bootresponse [ 0 ] = = MBOX2_BOOT_LOADING ) & & ( count < 10 ) ) {
2012-12-19 14:27:22 +04:00
msleep ( 500 ) ; /* 0.5 second delay */
snd_usb_ctl_msg ( dev , usb_rcvctrlpipe ( dev , 0 ) ,
/* Control magic - load onboard firmware */
0x85 , 0xc0 , 0x0001 , 0x0000 , & bootresponse , 0x0012 ) ;
2013-01-04 12:51:44 +04:00
if ( bootresponse [ 0 ] = = MBOX2_BOOT_READY )
2012-12-19 14:27:22 +04:00
break ;
snd_printd ( " usb-audio: device not ready, resending boot sequence... \n " ) ;
count + + ;
}
2013-01-04 12:51:44 +04:00
if ( bootresponse [ 0 ] ! = MBOX2_BOOT_READY ) {
snd_printk ( KERN_ERR " usb-audio: Unknown bootresponse=%d, or timed out, ignoring device. \n " , bootresponse [ 0 ] ) ;
2012-12-19 14:27:22 +04:00
return - ENODEV ;
}
snd_printdd ( " usb-audio: device initialised! \n " ) ;
err = usb_get_descriptor ( dev , USB_DT_DEVICE , 0 ,
& dev - > descriptor , sizeof ( dev - > descriptor ) ) ;
config = dev - > actconfig ;
if ( err < 0 )
snd_printd ( " error usb_get_descriptor: %d \n " , err ) ;
err = usb_reset_configuration ( dev ) ;
if ( err < 0 )
snd_printd ( " error usb_reset_configuration: %d \n " , err ) ;
snd_printdd ( " mbox2_boot: new boot length = %d \n " ,
le16_to_cpu ( get_cfg_desc ( config ) - > wTotalLength ) ) ;
mbox2_setup_48_24_magic ( dev ) ;
snd_printk ( KERN_INFO " usb-audio: Digidesign Mbox 2: 24bit 48kHz " ) ;
return 0 ; /* Successful boot */
}
2010-03-04 21:46:13 +03:00
/*
* Setup quirks
*/
2011-07-12 20:13:46 +04:00
# define MAUDIO_SET 0x01 /* parse device_setup */
# define MAUDIO_SET_COMPATIBLE 0x80 /* use only "win-compatible" interfaces */
# define MAUDIO_SET_DTS 0x02 /* enable DTS Digital Output */
# define MAUDIO_SET_96K 0x04 /* 48-96KHz rate if set, 8-48KHz otherwise */
# define MAUDIO_SET_24B 0x08 /* 24bits sample if set, 16bits otherwise */
# define MAUDIO_SET_DI 0x10 /* enable Digital Input */
# define MAUDIO_SET_MASK 0x1f /* bit mask for setup value */
# define MAUDIO_SET_24B_48K_DI 0x19 /* 24bits+48KHz+Digital Input */
# define MAUDIO_SET_24B_48K_NOTDI 0x09 /* 24bits+48KHz+No Digital Input */
# define MAUDIO_SET_16B_48K_DI 0x11 /* 16bits+48KHz+Digital Input */
# define MAUDIO_SET_16B_48K_NOTDI 0x01 /* 16bits+48KHz+No Digital Input */
static int quattro_skip_setting_quirk ( struct snd_usb_audio * chip ,
int iface , int altno )
{
/* Reset ALL ifaces to 0 altsetting.
* Call it for every possible altsetting of every interface .
*/
usb_set_interface ( chip - > dev , iface , 0 ) ;
if ( chip - > setup & MAUDIO_SET ) {
if ( chip - > setup & MAUDIO_SET_COMPATIBLE ) {
if ( iface ! = 1 & & iface ! = 2 )
return 1 ; /* skip all interfaces but 1 and 2 */
} else {
unsigned int mask ;
if ( iface = = 1 | | iface = = 2 )
return 1 ; /* skip interfaces 1 and 2 */
if ( ( chip - > setup & MAUDIO_SET_96K ) & & altno ! = 1 )
return 1 ; /* skip this altsetting */
mask = chip - > setup & MAUDIO_SET_MASK ;
if ( mask = = MAUDIO_SET_24B_48K_DI & & altno ! = 2 )
return 1 ; /* skip this altsetting */
if ( mask = = MAUDIO_SET_24B_48K_NOTDI & & altno ! = 3 )
return 1 ; /* skip this altsetting */
if ( mask = = MAUDIO_SET_16B_48K_NOTDI & & altno ! = 4 )
return 1 ; /* skip this altsetting */
}
}
snd_printdd ( KERN_INFO
" using altsetting %d for interface %d config %d \n " ,
altno , iface , chip - > setup ) ;
return 0 ; /* keep this altsetting */
}
2010-03-04 21:46:13 +03:00
static int audiophile_skip_setting_quirk ( struct snd_usb_audio * chip ,
int iface ,
int altno )
{
/* Reset ALL ifaces to 0 altsetting.
* Call it for every possible altsetting of every interface .
*/
usb_set_interface ( chip - > dev , iface , 0 ) ;
2011-07-12 20:13:46 +04:00
if ( chip - > setup & MAUDIO_SET ) {
unsigned int mask ;
if ( ( chip - > setup & MAUDIO_SET_DTS ) & & altno ! = 6 )
2010-03-04 21:46:13 +03:00
return 1 ; /* skip this altsetting */
2011-07-12 20:13:46 +04:00
if ( ( chip - > setup & MAUDIO_SET_96K ) & & altno ! = 1 )
2010-03-04 21:46:13 +03:00
return 1 ; /* skip this altsetting */
2011-07-12 20:13:46 +04:00
mask = chip - > setup & MAUDIO_SET_MASK ;
if ( mask = = MAUDIO_SET_24B_48K_DI & & altno ! = 2 )
2010-03-04 21:46:13 +03:00
return 1 ; /* skip this altsetting */
2011-07-12 20:13:46 +04:00
if ( mask = = MAUDIO_SET_24B_48K_NOTDI & & altno ! = 3 )
2010-03-04 21:46:13 +03:00
return 1 ; /* skip this altsetting */
2011-07-12 20:13:46 +04:00
if ( mask = = MAUDIO_SET_16B_48K_DI & & altno ! = 4 )
2010-03-04 21:46:13 +03:00
return 1 ; /* skip this altsetting */
2011-07-12 20:13:46 +04:00
if ( mask = = MAUDIO_SET_16B_48K_NOTDI & & altno ! = 5 )
2010-03-04 21:46:13 +03:00
return 1 ; /* skip this altsetting */
}
return 0 ; /* keep this altsetting */
}
2011-07-12 20:13:46 +04:00
static int fasttrackpro_skip_setting_quirk ( struct snd_usb_audio * chip ,
int iface , int altno )
{
/* Reset ALL ifaces to 0 altsetting.
* Call it for every possible altsetting of every interface .
*/
usb_set_interface ( chip - > dev , iface , 0 ) ;
/* possible configuration where both inputs and only one output is
* used is not supported by the current setup
*/
if ( chip - > setup & ( MAUDIO_SET | MAUDIO_SET_24B ) ) {
if ( chip - > setup & MAUDIO_SET_96K ) {
if ( altno ! = 3 & & altno ! = 6 )
return 1 ;
} else if ( chip - > setup & MAUDIO_SET_DI ) {
if ( iface = = 4 )
return 1 ; /* no analog input */
if ( altno ! = 2 & & altno ! = 5 )
return 1 ; /* enable only altsets 2 and 5 */
} else {
if ( iface = = 5 )
return 1 ; /* disable digialt input */
if ( altno ! = 2 & & altno ! = 5 )
return 1 ; /* enalbe only altsets 2 and 5 */
}
} else {
/* keep only 16-Bit mode */
if ( altno ! = 1 )
return 1 ;
}
snd_printdd ( KERN_INFO
" using altsetting %d for interface %d config %d \n " ,
altno , iface , chip - > setup ) ;
return 0 ; /* keep this altsetting */
}
2010-03-04 21:46:13 +03:00
int snd_usb_apply_interface_quirk ( struct snd_usb_audio * chip ,
int iface ,
int altno )
{
/* audiophile usb: skip altsets incompatible with device_setup */
if ( chip - > usb_id = = USB_ID ( 0x0763 , 0x2003 ) )
return audiophile_skip_setting_quirk ( chip , iface , altno ) ;
2011-07-12 20:13:46 +04:00
/* quattro usb: skip altsets incompatible with device_setup */
if ( chip - > usb_id = = USB_ID ( 0x0763 , 0x2001 ) )
return quattro_skip_setting_quirk ( chip , iface , altno ) ;
/* fasttrackpro usb: skip altsets incompatible with device_setup */
if ( chip - > usb_id = = USB_ID ( 0x0763 , 0x2012 ) )
return fasttrackpro_skip_setting_quirk ( chip , iface , altno ) ;
2010-03-04 21:46:13 +03:00
return 0 ;
}
int snd_usb_apply_boot_quirk ( struct usb_device * dev ,
struct usb_interface * intf ,
const struct snd_usb_audio_quirk * quirk )
{
u32 id = USB_ID ( le16_to_cpu ( dev - > descriptor . idVendor ) ,
le16_to_cpu ( dev - > descriptor . idProduct ) ) ;
2011-02-11 14:34:12 +03:00
switch ( id ) {
case USB_ID ( 0x041e , 0x3000 ) :
/* SB Extigy needs special boot-up sequence */
/* if more models come, this will go to the quirk list. */
2010-03-04 21:46:13 +03:00
return snd_usb_extigy_boot_quirk ( dev , intf ) ;
2011-02-11 14:34:12 +03:00
case USB_ID ( 0x041e , 0x3020 ) :
/* SB Audigy 2 NX needs its own boot-up magic, too */
2010-03-04 21:46:13 +03:00
return snd_usb_audigy2nx_boot_quirk ( dev ) ;
2011-02-11 14:34:12 +03:00
case USB_ID ( 0x10f5 , 0x0200 ) :
/* C-Media CM106 / Turtle Beach Audio Advantage Roadie */
2010-03-04 21:46:13 +03:00
return snd_usb_cm106_boot_quirk ( dev ) ;
2011-02-11 14:34:12 +03:00
case USB_ID ( 0x0d8c , 0x0102 ) :
/* C-Media CM6206 / CM106-Like Sound Device */
2011-04-28 18:18:40 +04:00
case USB_ID ( 0x0ccd , 0x00b1 ) : /* Terratec Aureon 7.1 USB */
2010-03-04 21:46:13 +03:00
return snd_usb_cm6206_boot_quirk ( dev ) ;
2012-12-19 14:27:22 +04:00
case USB_ID ( 0x0dba , 0x3000 ) :
/* Digidesign Mbox 2 */
return snd_usb_mbox2_boot_quirk ( dev ) ;
2011-02-11 14:34:12 +03:00
case USB_ID ( 0x133e , 0x0815 ) :
/* Access Music VirusTI Desktop */
2010-03-04 21:46:13 +03:00
return snd_usb_accessmusic_boot_quirk ( dev ) ;
2011-05-18 13:28:41 +04:00
case USB_ID ( 0x17cc , 0x1000 ) : /* Komplete Audio 6 */
2011-02-11 14:34:12 +03:00
case USB_ID ( 0x17cc , 0x1010 ) : /* Traktor Audio 6 */
case USB_ID ( 0x17cc , 0x1020 ) : /* Traktor Audio 10 */
2011-02-11 14:08:06 +03:00
return snd_usb_nativeinstruments_boot_quirk ( dev ) ;
2011-07-12 20:13:46 +04:00
case USB_ID ( 0x0763 , 0x2012 ) : /* M-Audio Fast Track Pro USB */
return snd_usb_fasttrackpro_boot_quirk ( dev ) ;
2011-02-11 14:34:12 +03:00
}
2011-02-11 14:08:06 +03:00
2010-03-04 21:46:13 +03:00
return 0 ;
}
/*
* check if the device uses big - endian samples
*/
int snd_usb_is_big_endian_format ( struct snd_usb_audio * chip , struct audioformat * fp )
{
2012-09-20 05:48:00 +04:00
/* it depends on altsetting whether the device is big-endian or not */
2010-03-04 21:46:13 +03:00
switch ( chip - > usb_id ) {
case USB_ID ( 0x0763 , 0x2001 ) : /* M-Audio Quattro: captured data only */
2011-07-12 20:13:46 +04:00
if ( fp - > altsetting = = 2 | | fp - > altsetting = = 3 | |
fp - > altsetting = = 5 | | fp - > altsetting = = 6 )
2010-03-04 21:46:13 +03:00
return 1 ;
break ;
case USB_ID ( 0x0763 , 0x2003 ) : /* M-Audio Audiophile USB */
if ( chip - > setup = = 0x00 | |
2011-07-12 20:13:46 +04:00
fp - > altsetting = = 1 | | fp - > altsetting = = 2 | |
fp - > altsetting = = 3 )
return 1 ;
break ;
case USB_ID ( 0x0763 , 0x2012 ) : /* M-Audio Fast Track Pro */
if ( fp - > altsetting = = 2 | | fp - > altsetting = = 3 | |
fp - > altsetting = = 5 | | fp - > altsetting = = 6 )
2010-03-04 21:46:13 +03:00
return 1 ;
2011-07-12 20:13:46 +04:00
break ;
2010-03-04 21:46:13 +03:00
}
return 0 ;
}
/*
2011-02-08 09:22:36 +03:00
* For E - Mu 0404U SB / 0202U SB / TrackerPre / 0204 sample rate should be set for device ,
2010-03-04 21:46:13 +03:00
* not for interface .
*/
enum {
EMU_QUIRK_SR_44100HZ = 0 ,
EMU_QUIRK_SR_48000HZ ,
EMU_QUIRK_SR_88200HZ ,
EMU_QUIRK_SR_96000HZ ,
EMU_QUIRK_SR_176400HZ ,
EMU_QUIRK_SR_192000HZ
} ;
static void set_format_emu_quirk ( struct snd_usb_substream * subs ,
struct audioformat * fmt )
{
unsigned char emu_samplerate_id = 0 ;
/* When capture is active
* sample rate shouldn ' t be changed
* by playback substream
*/
if ( subs - > direction = = SNDRV_PCM_STREAM_PLAYBACK ) {
if ( subs - > stream - > substream [ SNDRV_PCM_STREAM_CAPTURE ] . interface ! = - 1 )
return ;
}
switch ( fmt - > rate_min ) {
case 48000 :
emu_samplerate_id = EMU_QUIRK_SR_48000HZ ;
break ;
case 88200 :
emu_samplerate_id = EMU_QUIRK_SR_88200HZ ;
break ;
case 96000 :
emu_samplerate_id = EMU_QUIRK_SR_96000HZ ;
break ;
case 176400 :
emu_samplerate_id = EMU_QUIRK_SR_176400HZ ;
break ;
case 192000 :
emu_samplerate_id = EMU_QUIRK_SR_192000HZ ;
break ;
default :
emu_samplerate_id = EMU_QUIRK_SR_44100HZ ;
break ;
}
snd_emuusb_set_samplerate ( subs - > stream - > chip , emu_samplerate_id ) ;
}
void snd_usb_set_format_quirk ( struct snd_usb_substream * subs ,
struct audioformat * fmt )
{
switch ( subs - > stream - > chip - > usb_id ) {
case USB_ID ( 0x041e , 0x3f02 ) : /* E-Mu 0202 USB */
case USB_ID ( 0x041e , 0x3f04 ) : /* E-Mu 0404 USB */
case USB_ID ( 0x041e , 0x3f0a ) : /* E-Mu Tracker Pre */
2011-02-08 09:22:36 +03:00
case USB_ID ( 0x041e , 0x3f19 ) : /* E-Mu 0204 USB */
2010-03-04 21:46:13 +03:00
set_format_emu_quirk ( subs , fmt ) ;
break ;
}
}
2012-09-04 12:23:07 +04:00
void snd_usb_endpoint_start_quirk ( struct snd_usb_endpoint * ep )
{
/*
* " Playback Design " products send bogus feedback data at the start
* of the stream . Ignore them .
*/
if ( ( le16_to_cpu ( ep - > chip - > dev - > descriptor . idVendor ) = = 0x23ba ) & &
ep - > type = = SND_USB_ENDPOINT_TYPE_SYNC )
ep - > skip_packets = 4 ;
2013-01-14 02:02:03 +04:00
/*
* M - Audio Fast Track C400 - when packets are not skipped , real world
* latency varies by approx . + / - 50 frames ( at 96 KHz ) each time the
* stream is ( re ) started . When skipping packets 16 at endpoint start
* up , the real world latency is stable within + / - 1 frame ( also
* across power cycles ) .
*/
if ( ep - > chip - > usb_id = = USB_ID ( 0x0763 , 0x2030 ) & &
ep - > type = = SND_USB_ENDPOINT_TYPE_DATA )
ep - > skip_packets = 16 ;
2012-09-04 12:23:07 +04:00
}
void snd_usb_ctl_msg_quirk ( struct usb_device * dev , unsigned int pipe ,
__u8 request , __u8 requesttype , __u16 value ,
__u16 index , void * data , __u16 size )
{
/*
* " Playback Design " products need a 20 ms delay after each
* class compliant request
*/
if ( ( le16_to_cpu ( dev - > descriptor . idVendor ) = = 0x23ba ) & &
( requesttype & USB_TYPE_MASK ) = = USB_TYPE_CLASS )
mdelay ( 20 ) ;
}