2019-05-27 09:55:05 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2005-04-17 02:20:36 +04:00
/*
* Hardware dependent layer
2007-10-15 11:50:19 +04:00
* Copyright ( c ) by Jaroslav Kysela < perex @ perex . cz >
2005-04-17 02:20:36 +04:00
*/
# include <linux/major.h>
# include <linux/init.h>
# include <linux/slab.h>
# include <linux/time.h>
2006-01-16 18:29:08 +03:00
# include <linux/mutex.h>
2011-07-15 20:38:28 +04:00
# include <linux/module.h>
2017-02-02 21:15:33 +03:00
# include <linux/sched/signal.h>
2005-04-17 02:20:36 +04:00
# include <sound/core.h>
# include <sound/control.h>
# include <sound/minors.h>
# include <sound/hwdep.h>
# include <sound/info.h>
2007-10-15 11:50:19 +04:00
MODULE_AUTHOR ( " Jaroslav Kysela <perex@perex.cz> " ) ;
2005-04-17 02:20:36 +04:00
MODULE_DESCRIPTION ( " Hardware dependent layer " ) ;
MODULE_LICENSE ( " GPL " ) ;
2005-11-20 16:06:59 +03:00
static LIST_HEAD ( snd_hwdep_devices ) ;
2006-01-16 18:29:08 +03:00
static DEFINE_MUTEX ( register_mutex ) ;
2005-04-17 02:20:36 +04:00
2005-11-17 15:58:21 +03:00
static int snd_hwdep_dev_free ( struct snd_device * device ) ;
static int snd_hwdep_dev_register ( struct snd_device * device ) ;
2006-06-23 16:38:23 +04:00
static int snd_hwdep_dev_disconnect ( struct snd_device * device ) ;
2005-04-17 02:20:36 +04:00
2005-11-20 16:06:59 +03:00
static struct snd_hwdep * snd_hwdep_search ( struct snd_card * card , int device )
{
struct snd_hwdep * hwdep ;
2006-10-05 18:02:22 +04:00
list_for_each_entry ( hwdep , & snd_hwdep_devices , list )
2005-11-20 16:06:59 +03:00
if ( hwdep - > card = = card & & hwdep - > device = = device )
return hwdep ;
return NULL ;
}
2005-04-17 02:20:36 +04:00
static loff_t snd_hwdep_llseek ( struct file * file , loff_t offset , int orig )
{
2005-11-17 15:58:21 +03:00
struct snd_hwdep * hw = file - > private_data ;
2005-04-17 02:20:36 +04:00
if ( hw - > ops . llseek )
return hw - > ops . llseek ( hw , file , offset , orig ) ;
return - ENXIO ;
}
2005-11-17 15:58:21 +03:00
static ssize_t snd_hwdep_read ( struct file * file , char __user * buf ,
size_t count , loff_t * offset )
2005-04-17 02:20:36 +04:00
{
2005-11-17 15:58:21 +03:00
struct snd_hwdep * hw = file - > private_data ;
2005-04-17 02:20:36 +04:00
if ( hw - > ops . read )
return hw - > ops . read ( hw , buf , count , offset ) ;
return - ENXIO ;
}
2005-11-17 15:58:21 +03:00
static ssize_t snd_hwdep_write ( struct file * file , const char __user * buf ,
size_t count , loff_t * offset )
2005-04-17 02:20:36 +04:00
{
2005-11-17 15:58:21 +03:00
struct snd_hwdep * hw = file - > private_data ;
2005-04-17 02:20:36 +04:00
if ( hw - > ops . write )
return hw - > ops . write ( hw , buf , count , offset ) ;
return - ENXIO ;
}
static int snd_hwdep_open ( struct inode * inode , struct file * file )
{
int major = imajor ( inode ) ;
2005-11-17 15:58:21 +03:00
struct snd_hwdep * hw ;
2005-04-17 02:20:36 +04:00
int err ;
2017-06-20 13:06:13 +03:00
wait_queue_entry_t wait ;
2005-04-17 02:20:36 +04:00
2005-10-24 19:05:03 +04:00
if ( major = = snd_major ) {
2005-11-20 16:06:59 +03:00
hw = snd_lookup_minor_data ( iminor ( inode ) ,
SNDRV_DEVICE_TYPE_HWDEP ) ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_SND_OSSEMUL
2005-10-24 19:05:03 +04:00
} else if ( major = = SOUND_MAJOR ) {
2005-11-20 16:06:59 +03:00
hw = snd_lookup_oss_minor_data ( iminor ( inode ) ,
SNDRV_OSS_DEVICE_TYPE_DMFM ) ;
2005-04-17 02:20:36 +04:00
# endif
2005-10-24 19:05:03 +04:00
} else
2005-04-17 02:20:36 +04:00
return - ENXIO ;
if ( hw = = NULL )
return - ENODEV ;
2012-10-16 15:05:59 +04:00
if ( ! try_module_get ( hw - > card - > module ) ) {
snd_card_unref ( hw - > card ) ;
2005-04-17 02:20:36 +04:00
return - EFAULT ;
2012-10-16 15:05:59 +04:00
}
2005-04-17 02:20:36 +04:00
init_waitqueue_entry ( & wait , current ) ;
add_wait_queue ( & hw - > open_wait , & wait ) ;
2006-01-16 18:29:08 +03:00
mutex_lock ( & hw - > open_mutex ) ;
2005-04-17 02:20:36 +04:00
while ( 1 ) {
if ( hw - > exclusive & & hw - > used > 0 ) {
err = - EBUSY ;
break ;
}
2009-02-05 11:10:20 +03:00
if ( ! hw - > ops . open ) {
err = 0 ;
break ;
}
2005-04-17 02:20:36 +04:00
err = hw - > ops . open ( hw , file ) ;
if ( err > = 0 )
break ;
if ( err = = - EAGAIN ) {
if ( file - > f_flags & O_NONBLOCK ) {
err = - EBUSY ;
break ;
}
} else
break ;
set_current_state ( TASK_INTERRUPTIBLE ) ;
2006-01-16 18:29:08 +03:00
mutex_unlock ( & hw - > open_mutex ) ;
2005-04-17 02:20:36 +04:00
schedule ( ) ;
2006-01-16 18:29:08 +03:00
mutex_lock ( & hw - > open_mutex ) ;
2012-10-16 18:43:39 +04:00
if ( hw - > card - > shutdown ) {
err = - ENODEV ;
break ;
}
2005-04-17 02:20:36 +04:00
if ( signal_pending ( current ) ) {
err = - ERESTARTSYS ;
break ;
}
}
remove_wait_queue ( & hw - > open_wait , & wait ) ;
if ( err > = 0 ) {
err = snd_card_file_add ( hw - > card , file ) ;
if ( err > = 0 ) {
file - > private_data = hw ;
hw - > used + + ;
} else {
if ( hw - > ops . release )
hw - > ops . release ( hw , file ) ;
}
}
2006-01-16 18:29:08 +03:00
mutex_unlock ( & hw - > open_mutex ) ;
2005-04-17 02:20:36 +04:00
if ( err < 0 )
module_put ( hw - > card - > module ) ;
2012-10-16 15:05:59 +04:00
snd_card_unref ( hw - > card ) ;
2005-04-17 02:20:36 +04:00
return err ;
}
static int snd_hwdep_release ( struct inode * inode , struct file * file )
{
2009-02-05 11:10:20 +03:00
int err = 0 ;
2005-11-17 15:58:21 +03:00
struct snd_hwdep * hw = file - > private_data ;
2006-09-29 14:55:25 +04:00
struct module * mod = hw - > card - > module ;
2007-01-31 12:05:30 +03:00
2006-01-16 18:29:08 +03:00
mutex_lock ( & hw - > open_mutex ) ;
2007-01-31 12:05:30 +03:00
if ( hw - > ops . release )
2005-04-17 02:20:36 +04:00
err = hw - > ops . release ( hw , file ) ;
if ( hw - > used > 0 )
hw - > used - - ;
2006-01-16 18:29:08 +03:00
mutex_unlock ( & hw - > open_mutex ) ;
2007-01-31 12:05:30 +03:00
wake_up ( & hw - > open_wait ) ;
snd_card_file_remove ( hw - > card , file ) ;
2006-09-29 14:55:25 +04:00
module_put ( mod ) ;
2005-04-17 02:20:36 +04:00
return err ;
}
2017-07-03 06:27:36 +03:00
static __poll_t snd_hwdep_poll ( struct file * file , poll_table * wait )
2005-04-17 02:20:36 +04:00
{
2005-11-17 15:58:21 +03:00
struct snd_hwdep * hw = file - > private_data ;
2005-04-17 02:20:36 +04:00
if ( hw - > ops . poll )
return hw - > ops . poll ( hw , file , wait ) ;
return 0 ;
}
2005-11-17 15:58:21 +03:00
static int snd_hwdep_info ( struct snd_hwdep * hw ,
struct snd_hwdep_info __user * _info )
2005-04-17 02:20:36 +04:00
{
2005-11-17 15:58:21 +03:00
struct snd_hwdep_info info ;
2005-04-17 02:20:36 +04:00
memset ( & info , 0 , sizeof ( info ) ) ;
info . card = hw - > card - > number ;
ALSA: Convert strlcpy to strscpy when return value is unused
strlcpy is deprecated. see: Documentation/process/deprecated.rst
Change the calls that do not use the strlcpy return value to the
preferred strscpy.
Done with cocci script:
@@
expression e1, e2, e3;
@@
- strlcpy(
+ strscpy(
e1, e2, e3);
This cocci script leaves the instances where the return value is
used unchanged.
After this patch, sound/ has 3 uses of strlcpy() that need to be
manually inspected for conversion and changed one day.
$ git grep -w strlcpy sound/
sound/usb/card.c: len = strlcpy(card->longname, s, sizeof(card->longname));
sound/usb/mixer.c: return strlcpy(buf, p->name, buflen);
sound/usb/mixer.c: return strlcpy(buf, p->names[index], buflen);
Miscellenea:
o Remove trailing whitespace in conversion of sound/core/hwdep.c
Link: https://lore.kernel.org/lkml/CAHk-=wgfRnXz0W3D37d01q3JFkr_i_uTL=V6A6G1oUZcprmknw@mail.gmail.com/
Signed-off-by: Joe Perches <joe@perches.com>
Acked-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/22b393d1790bb268769d0bab7bacf0866dcb0c14.camel@perches.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2021-01-04 20:17:34 +03:00
strscpy ( info . id , hw - > id , sizeof ( info . id ) ) ;
strscpy ( info . name , hw - > name , sizeof ( info . name ) ) ;
2005-04-17 02:20:36 +04:00
info . iface = hw - > iface ;
if ( copy_to_user ( _info , & info , sizeof ( info ) ) )
return - EFAULT ;
return 0 ;
}
2005-11-17 15:58:21 +03:00
static int snd_hwdep_dsp_status ( struct snd_hwdep * hw ,
struct snd_hwdep_dsp_status __user * _info )
2005-04-17 02:20:36 +04:00
{
2005-11-17 15:58:21 +03:00
struct snd_hwdep_dsp_status info ;
2005-04-17 02:20:36 +04:00
int err ;
if ( ! hw - > ops . dsp_status )
return - ENXIO ;
memset ( & info , 0 , sizeof ( info ) ) ;
info . dsp_loaded = hw - > dsp_loaded ;
if ( ( err = hw - > ops . dsp_status ( hw , & info ) ) < 0 )
return err ;
if ( copy_to_user ( _info , & info , sizeof ( info ) ) )
return - EFAULT ;
return 0 ;
}
2005-11-17 15:58:21 +03:00
static int snd_hwdep_dsp_load ( struct snd_hwdep * hw ,
2020-09-18 12:56:19 +03:00
struct snd_hwdep_dsp_image * info )
2005-04-17 02:20:36 +04:00
{
int err ;
if ( ! hw - > ops . dsp_load )
return - ENXIO ;
2020-09-18 12:56:19 +03:00
if ( info - > index > = 32 )
2017-09-14 02:01:16 +03:00
return - EINVAL ;
2005-04-17 02:20:36 +04:00
/* check whether the dsp was already loaded */
2020-09-18 12:56:19 +03:00
if ( hw - > dsp_loaded & ( 1u < < info - > index ) )
2005-04-17 02:20:36 +04:00
return - EBUSY ;
2020-09-18 12:56:19 +03:00
err = hw - > ops . dsp_load ( hw , info ) ;
2005-04-17 02:20:36 +04:00
if ( err < 0 )
return err ;
2020-09-18 12:56:19 +03:00
hw - > dsp_loaded | = ( 1u < < info - > index ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2020-09-18 12:56:19 +03:00
static int snd_hwdep_dsp_load_user ( struct snd_hwdep * hw ,
struct snd_hwdep_dsp_image __user * _info )
{
struct snd_hwdep_dsp_image info = { } ;
if ( copy_from_user ( & info , _info , sizeof ( info ) ) )
return - EFAULT ;
return snd_hwdep_dsp_load ( hw , & info ) ;
}
2005-11-17 15:58:21 +03:00
static long snd_hwdep_ioctl ( struct file * file , unsigned int cmd ,
unsigned long arg )
2005-04-17 02:20:36 +04:00
{
2005-11-17 15:58:21 +03:00
struct snd_hwdep * hw = file - > private_data ;
2005-04-17 02:20:36 +04:00
void __user * argp = ( void __user * ) arg ;
switch ( cmd ) {
case SNDRV_HWDEP_IOCTL_PVERSION :
return put_user ( SNDRV_HWDEP_VERSION , ( int __user * ) argp ) ;
case SNDRV_HWDEP_IOCTL_INFO :
return snd_hwdep_info ( hw , argp ) ;
case SNDRV_HWDEP_IOCTL_DSP_STATUS :
return snd_hwdep_dsp_status ( hw , argp ) ;
case SNDRV_HWDEP_IOCTL_DSP_LOAD :
2020-09-18 12:56:19 +03:00
return snd_hwdep_dsp_load_user ( hw , argp ) ;
2005-04-17 02:20:36 +04:00
}
if ( hw - > ops . ioctl )
return hw - > ops . ioctl ( hw , file , cmd , arg ) ;
return - ENOTTY ;
}
static int snd_hwdep_mmap ( struct file * file , struct vm_area_struct * vma )
{
2005-11-17 15:58:21 +03:00
struct snd_hwdep * hw = file - > private_data ;
2005-04-17 02:20:36 +04:00
if ( hw - > ops . mmap )
return hw - > ops . mmap ( hw , file , vma ) ;
return - ENXIO ;
}
2005-11-17 15:58:21 +03:00
static int snd_hwdep_control_ioctl ( struct snd_card * card ,
struct snd_ctl_file * control ,
2005-04-17 02:20:36 +04:00
unsigned int cmd , unsigned long arg )
{
switch ( cmd ) {
case SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE :
{
int device ;
if ( get_user ( device , ( int __user * ) arg ) )
return - EFAULT ;
2006-01-16 18:29:08 +03:00
mutex_lock ( & register_mutex ) ;
2011-10-28 10:46:01 +04:00
if ( device < 0 )
device = 0 ;
else if ( device < SNDRV_MINOR_HWDEPS )
device + + ;
else
device = SNDRV_MINOR_HWDEPS ;
2005-04-17 02:20:36 +04:00
while ( device < SNDRV_MINOR_HWDEPS ) {
2005-11-20 16:06:59 +03:00
if ( snd_hwdep_search ( card , device ) )
2005-04-17 02:20:36 +04:00
break ;
device + + ;
}
if ( device > = SNDRV_MINOR_HWDEPS )
device = - 1 ;
2006-01-16 18:29:08 +03:00
mutex_unlock ( & register_mutex ) ;
2005-04-17 02:20:36 +04:00
if ( put_user ( device , ( int __user * ) arg ) )
return - EFAULT ;
return 0 ;
}
case SNDRV_CTL_IOCTL_HWDEP_INFO :
{
2005-11-17 15:58:21 +03:00
struct snd_hwdep_info __user * info = ( struct snd_hwdep_info __user * ) arg ;
2005-11-20 16:06:59 +03:00
int device , err ;
2005-11-17 15:58:21 +03:00
struct snd_hwdep * hwdep ;
2005-04-17 02:20:36 +04:00
if ( get_user ( device , & info - > device ) )
return - EFAULT ;
2006-01-16 18:29:08 +03:00
mutex_lock ( & register_mutex ) ;
2005-11-20 16:06:59 +03:00
hwdep = snd_hwdep_search ( card , device ) ;
if ( hwdep )
err = snd_hwdep_info ( hwdep , info ) ;
else
err = - ENXIO ;
2006-01-16 18:29:08 +03:00
mutex_unlock ( & register_mutex ) ;
2005-11-20 16:06:59 +03:00
return err ;
2005-04-17 02:20:36 +04:00
}
}
return - ENOIOCTLCMD ;
}
# ifdef CONFIG_COMPAT
# include "hwdep_compat.c"
# else
# define snd_hwdep_ioctl_compat NULL
# endif
/*
*/
2007-02-12 11:55:37 +03:00
static const struct file_operations snd_hwdep_f_ops =
2005-04-17 02:20:36 +04:00
{
. owner = THIS_MODULE ,
. llseek = snd_hwdep_llseek ,
. read = snd_hwdep_read ,
. write = snd_hwdep_write ,
. open = snd_hwdep_open ,
. release = snd_hwdep_release ,
. poll = snd_hwdep_poll ,
. unlocked_ioctl = snd_hwdep_ioctl ,
. compat_ioctl = snd_hwdep_ioctl_compat ,
. mmap = snd_hwdep_mmap ,
} ;
2015-01-29 19:13:32 +03:00
static void release_hwdep_device ( struct device * dev )
{
kfree ( container_of ( dev , struct snd_hwdep , dev ) ) ;
}
2005-04-17 02:20:36 +04:00
/**
* snd_hwdep_new - create a new hwdep instance
* @ card : the card instance
* @ id : the id string
* @ device : the device index ( zero - based )
* @ rhwdep : the pointer to store the new hwdep instance
*
* Creates a new hwdep instance with the given index on the card .
* The callbacks ( hwdep - > ops ) must be set on the returned instance
* after this call manually by the caller .
*
2013-03-12 01:05:14 +04:00
* Return : Zero if successful , or a negative error code on failure .
2005-04-17 02:20:36 +04:00
*/
2005-11-17 15:58:21 +03:00
int snd_hwdep_new ( struct snd_card * card , char * id , int device ,
struct snd_hwdep * * rhwdep )
2005-04-17 02:20:36 +04:00
{
2005-11-17 15:58:21 +03:00
struct snd_hwdep * hwdep ;
2005-04-17 02:20:36 +04:00
int err ;
2020-01-03 11:16:20 +03:00
static const struct snd_device_ops ops = {
2005-04-17 02:20:36 +04:00
. dev_free = snd_hwdep_dev_free ,
. dev_register = snd_hwdep_dev_register ,
2006-06-23 16:38:23 +04:00
. dev_disconnect = snd_hwdep_dev_disconnect ,
2005-04-17 02:20:36 +04:00
} ;
2008-08-08 19:09:09 +04:00
if ( snd_BUG_ON ( ! card ) )
return - ENXIO ;
if ( rhwdep )
* rhwdep = NULL ;
2005-09-09 16:20:23 +04:00
hwdep = kzalloc ( sizeof ( * hwdep ) , GFP_KERNEL ) ;
2015-03-10 17:42:14 +03:00
if ( ! hwdep )
2005-04-17 02:20:36 +04:00
return - ENOMEM ;
2015-01-29 19:13:32 +03:00
init_waitqueue_head ( & hwdep - > open_wait ) ;
mutex_init ( & hwdep - > open_mutex ) ;
2005-04-17 02:20:36 +04:00
hwdep - > card = card ;
hwdep - > device = device ;
2005-11-17 19:44:01 +03:00
if ( id )
ALSA: Convert strlcpy to strscpy when return value is unused
strlcpy is deprecated. see: Documentation/process/deprecated.rst
Change the calls that do not use the strlcpy return value to the
preferred strscpy.
Done with cocci script:
@@
expression e1, e2, e3;
@@
- strlcpy(
+ strscpy(
e1, e2, e3);
This cocci script leaves the instances where the return value is
used unchanged.
After this patch, sound/ has 3 uses of strlcpy() that need to be
manually inspected for conversion and changed one day.
$ git grep -w strlcpy sound/
sound/usb/card.c: len = strlcpy(card->longname, s, sizeof(card->longname));
sound/usb/mixer.c: return strlcpy(buf, p->name, buflen);
sound/usb/mixer.c: return strlcpy(buf, p->names[index], buflen);
Miscellenea:
o Remove trailing whitespace in conversion of sound/core/hwdep.c
Link: https://lore.kernel.org/lkml/CAHk-=wgfRnXz0W3D37d01q3JFkr_i_uTL=V6A6G1oUZcprmknw@mail.gmail.com/
Signed-off-by: Joe Perches <joe@perches.com>
Acked-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/22b393d1790bb268769d0bab7bacf0866dcb0c14.camel@perches.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
2021-01-04 20:17:34 +03:00
strscpy ( hwdep - > id , id , sizeof ( hwdep - > id ) ) ;
2015-01-29 19:13:32 +03:00
snd_device_initialize ( & hwdep - > dev , card ) ;
hwdep - > dev . release = release_hwdep_device ;
dev_set_name ( & hwdep - > dev , " hwC%iD%i " , card - > number , device ) ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_SND_OSSEMUL
hwdep - > oss_type = - 1 ;
# endif
2015-01-29 19:13:32 +03:00
err = snd_device_new ( card , SNDRV_DEV_HWDEP , hwdep , & ops ) ;
if ( err < 0 ) {
put_device ( & hwdep - > dev ) ;
2005-04-17 02:20:36 +04:00
return err ;
}
2015-01-29 19:13:32 +03:00
2008-08-08 19:09:09 +04:00
if ( rhwdep )
* rhwdep = hwdep ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2014-02-27 19:00:17 +04:00
EXPORT_SYMBOL ( snd_hwdep_new ) ;
2005-04-17 02:20:36 +04:00
2015-01-29 19:13:32 +03:00
static int snd_hwdep_dev_free ( struct snd_device * device )
2005-04-17 02:20:36 +04:00
{
2015-01-29 19:13:32 +03:00
struct snd_hwdep * hwdep = device - > device_data ;
2008-08-08 19:09:09 +04:00
if ( ! hwdep )
return 0 ;
2005-04-17 02:20:36 +04:00
if ( hwdep - > private_free )
hwdep - > private_free ( hwdep ) ;
2015-01-29 19:13:32 +03:00
put_device ( & hwdep - > dev ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2005-11-17 15:58:21 +03:00
static int snd_hwdep_dev_register ( struct snd_device * device )
2005-04-17 02:20:36 +04:00
{
2005-11-17 15:58:21 +03:00
struct snd_hwdep * hwdep = device - > device_data ;
2014-02-04 21:21:54 +04:00
struct snd_card * card = hwdep - > card ;
2005-11-20 16:06:59 +03:00
int err ;
2005-04-17 02:20:36 +04:00
2006-01-16 18:29:08 +03:00
mutex_lock ( & register_mutex ) ;
2014-02-04 21:21:54 +04:00
if ( snd_hwdep_search ( card , hwdep - > device ) ) {
2006-01-16 18:29:08 +03:00
mutex_unlock ( & register_mutex ) ;
2005-04-17 02:20:36 +04:00
return - EBUSY ;
}
2005-11-20 16:06:59 +03:00
list_add_tail ( & hwdep - > list , & snd_hwdep_devices ) ;
2015-01-30 10:34:58 +03:00
err = snd_register_device ( SNDRV_DEVICE_TYPE_HWDEP ,
hwdep - > card , hwdep - > device ,
& snd_hwdep_f_ops , hwdep , & hwdep - > dev ) ;
2014-02-25 11:05:21 +04:00
if ( err < 0 ) {
2015-01-29 19:13:32 +03:00
dev_err ( & hwdep - > dev , " unable to register \n " ) ;
2005-11-20 16:06:59 +03:00
list_del ( & hwdep - > list ) ;
2006-01-16 18:29:08 +03:00
mutex_unlock ( & register_mutex ) ;
2005-04-17 02:20:36 +04:00
return err ;
}
2014-02-25 11:30:50 +04:00
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_SND_OSSEMUL
hwdep - > ossreg = 0 ;
if ( hwdep - > oss_type > = 0 ) {
2015-01-29 19:13:32 +03:00
if ( hwdep - > oss_type = = SNDRV_OSS_DEVICE_TYPE_DMFM & &
hwdep - > device )
dev_warn ( & hwdep - > dev ,
2014-02-04 21:21:54 +04:00
" only hwdep device 0 can be registered as OSS direct FM device! \n " ) ;
2015-01-29 19:13:32 +03:00
else if ( snd_register_oss_device ( hwdep - > oss_type ,
card , hwdep - > device ,
& snd_hwdep_f_ops , hwdep ) < 0 )
dev_warn ( & hwdep - > dev ,
" unable to register OSS compatibility device \n " ) ;
else
hwdep - > ossreg = 1 ;
2005-04-17 02:20:36 +04:00
}
# endif
2006-01-16 18:29:08 +03:00
mutex_unlock ( & register_mutex ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2006-06-23 16:38:23 +04:00
static int snd_hwdep_dev_disconnect ( struct snd_device * device )
2005-04-17 02:20:36 +04:00
{
2005-11-17 15:58:21 +03:00
struct snd_hwdep * hwdep = device - > device_data ;
2005-04-17 02:20:36 +04:00
2008-08-08 19:09:09 +04:00
if ( snd_BUG_ON ( ! hwdep ) )
return - ENXIO ;
2006-01-16 18:29:08 +03:00
mutex_lock ( & register_mutex ) ;
2005-11-20 16:06:59 +03:00
if ( snd_hwdep_search ( hwdep - > card , hwdep - > device ) ! = hwdep ) {
2006-01-16 18:29:08 +03:00
mutex_unlock ( & register_mutex ) ;
2005-04-17 02:20:36 +04:00
return - EINVAL ;
}
2012-10-16 18:43:39 +04:00
mutex_lock ( & hwdep - > open_mutex ) ;
wake_up ( & hwdep - > open_wait ) ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_SND_OSSEMUL
if ( hwdep - > ossreg )
snd_unregister_oss_device ( hwdep - > oss_type , hwdep - > card , hwdep - > device ) ;
# endif
2015-01-30 10:34:58 +03:00
snd_unregister_device ( & hwdep - > dev ) ;
2006-06-23 16:38:23 +04:00
list_del_init ( & hwdep - > list ) ;
2012-10-16 18:43:39 +04:00
mutex_unlock ( & hwdep - > open_mutex ) ;
2006-01-16 18:29:08 +03:00
mutex_unlock ( & register_mutex ) ;
2006-06-23 16:38:23 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
2015-05-27 14:45:45 +03:00
# ifdef CONFIG_SND_PROC_FS
2005-04-17 02:20:36 +04:00
/*
* Info interface
*/
2005-11-17 15:58:21 +03:00
static void snd_hwdep_proc_read ( struct snd_info_entry * entry ,
struct snd_info_buffer * buffer )
2005-04-17 02:20:36 +04:00
{
2005-11-17 15:58:21 +03:00
struct snd_hwdep * hwdep ;
2005-04-17 02:20:36 +04:00
2006-01-16 18:29:08 +03:00
mutex_lock ( & register_mutex ) ;
2006-10-05 18:02:22 +04:00
list_for_each_entry ( hwdep , & snd_hwdep_devices , list )
2005-04-17 02:20:36 +04:00
snd_iprintf ( buffer , " %02i-%02i: %s \n " ,
2005-11-20 16:06:59 +03:00
hwdep - > card - > number , hwdep - > device , hwdep - > name ) ;
2006-01-16 18:29:08 +03:00
mutex_unlock ( & register_mutex ) ;
2005-04-17 02:20:36 +04:00
}
2005-12-01 12:42:42 +03:00
static struct snd_info_entry * snd_hwdep_proc_entry ;
2005-04-17 02:20:36 +04:00
2005-12-01 12:42:42 +03:00
static void __init snd_hwdep_proc_init ( void )
2005-04-17 02:20:36 +04:00
{
2005-11-17 15:58:21 +03:00
struct snd_info_entry * entry ;
2005-04-17 02:20:36 +04:00
if ( ( entry = snd_info_create_module_entry ( THIS_MODULE , " hwdep " , NULL ) ) ! = NULL ) {
entry - > c . text . read = snd_hwdep_proc_read ;
if ( snd_info_register ( entry ) < 0 ) {
snd_info_free_entry ( entry ) ;
entry = NULL ;
}
}
snd_hwdep_proc_entry = entry ;
2005-12-01 12:42:42 +03:00
}
static void __exit snd_hwdep_proc_done ( void )
{
2006-06-23 16:37:59 +04:00
snd_info_free_entry ( snd_hwdep_proc_entry ) ;
2005-12-01 12:42:42 +03:00
}
2015-05-27 14:45:45 +03:00
# else /* !CONFIG_SND_PROC_FS */
2005-12-01 12:42:42 +03:00
# define snd_hwdep_proc_init()
# define snd_hwdep_proc_done()
2015-05-27 14:45:45 +03:00
# endif /* CONFIG_SND_PROC_FS */
2005-12-01 12:42:42 +03:00
/*
* ENTRY functions
*/
static int __init alsa_hwdep_init ( void )
{
snd_hwdep_proc_init ( ) ;
2005-04-17 02:20:36 +04:00
snd_ctl_register_ioctl ( snd_hwdep_control_ioctl ) ;
snd_ctl_register_ioctl_compat ( snd_hwdep_control_ioctl ) ;
return 0 ;
}
static void __exit alsa_hwdep_exit ( void )
{
snd_ctl_unregister_ioctl ( snd_hwdep_control_ioctl ) ;
snd_ctl_unregister_ioctl_compat ( snd_hwdep_control_ioctl ) ;
2005-12-01 12:42:42 +03:00
snd_hwdep_proc_done ( ) ;
2005-04-17 02:20:36 +04:00
}
module_init ( alsa_hwdep_init )
module_exit ( alsa_hwdep_exit )