Open Sound System |
Do you have problems with sound/audio application development? Don't panic! Click here for help! |
This file is part of Open Sound System.
Copyright (C) 4Front Technologies 1996-2008.
This this source file is released under GPL v2 license (no other versions). See the COPYING file included in the main directory of this source distribution for the license terms and conditions.
#include "oss_userdev_cfg.h" #include <oss_userdev_exports.h> #include "userdev.h" oss_device_t *userdev_osdev = NULL; static int client_dev = -1, server_dev = -1; /* Control devces */ char *userdev_client_devnode = "/dev/oss/oss_userdev0/client"; char *userdev_server_devnode = "/dev/oss/oss_userdev0/server";
Global device lists and the mutex that protects them.
oss_mutex_t userdev_global_mutex;
The oss_userdev driver creates new device pairs on-demand. All device pairs that are not in use will be kept in the userdev_free_device_list (linked) list. If this list contains any entries then they will be reused whenever a new device pair is required.
userdev_devc_t *userdev_free_device_list = NULL;
Linked list for device pairs that have a server attached. These device pairs are available for the clients.
userdev_devc_t *userdev_active_device_list = NULL; /*ARGSUSED*/ static int userdev_server_redirect (int dev, int mode, int open_flags) {
int server_engine; if ((server_engine=usrdev_find_free_device_pair()) >= 0) { userdev_devc_t *devc = audio_engines[server_engine]->devc; userdev_reinit_instance(devc); return server_engine; } return userdev_create_device_pair(); } /*ARGSUSED*/ static int userdev_client_redirect (int dev, int mode, int open_flags) {
userdev_devc_t *devc; oss_native_word flags; uid_t uid; uid = oss_get_procinfo(OSS_GET_PROCINFO_UID); MUTEX_ENTER_IRQDISABLE(userdev_global_mutex, flags); devc=userdev_active_device_list; while (devc != NULL) { int ok=1; switch (devc->match_method) { case UD_MATCH_UID: if (devc->match_key != uid) /* Wrong UID */ ok=0; break; } if (ok) { MUTEX_EXIT_IRQRESTORE(userdev_global_mutex, flags); return devc->client_portc.audio_dev; } devc = devc->next_instance; } MUTEX_EXIT_IRQRESTORE(userdev_global_mutex, flags); return OSS_EIO; }
Dummy audio driver entrypoint functions.
Functionality of the control device is handled by userdev_[client|server]_redirect(). The other entry points are not used for any purpose but the audio core framework expects to see them.
/*ARGSUSED*/ static int userdev_control_set_rate (int dev, int arg) { /* Dumy routine - Not actually used */ return 48000; } /*ARGSUSED*/ static short userdev_control_set_channels (int dev, short arg) { /* Dumy routine - Not actually used */ return 2; } /*ARGSUSED*/ static unsigned int userdev_control_set_format (int dev, unsigned int arg) { /* Dumy routine - Not actually used */ return AFMT_S16_NE; } static void userdev_control_reset (int dev) { /* Dumy routine - Not actually used */ } /*ARGSUSED*/ static int userdev_control_open (int dev, int mode, int open_flags) { /* Dumy routine - Not actually used */ return OSS_EIO; } /*ARGSUSED*/ static void userdev_control_close (int dev, int mode) { /* Dumy routine - Not actually used */ } /*ARGSUSED*/ static int userdev_control_ioctl (int dev, unsigned int cmd, ioctl_arg arg) { /* Dumy routine - Not actually used */ return OSS_EINVAL; } /*ARGSUSED*/ static void userdev_control_output_block (int dev, oss_native_word buf, int count, int fragsize, int intrflag) { /* Dumy routine - Not actually used */ } /*ARGSUSED*/ static void userdev_control_start_input (int dev, oss_native_word buf, int count, int fragsize, int intrflag) { /* Dumy routine - Not actually used */ } /*ARGSUSED*/ static int userdev_control_prepare_for_input (int dev, int bsize, int bcount) { /* Dumy routine - Not actually used */ return OSS_EIO; } /*ARGSUSED*/ static int userdev_control_prepare_for_output (int dev, int bsize, int bcount) { /* Dumy routine - Not actually used */ return OSS_EIO; } static audiodrv_t userdev_server_control_driver = { userdev_control_open, userdev_control_close, userdev_control_output_block, userdev_control_start_input, userdev_control_ioctl, userdev_control_prepare_for_input, userdev_control_prepare_for_output, userdev_control_reset, NULL, NULL, NULL, NULL, NULL, /* trigger */ userdev_control_set_rate, userdev_control_set_format, userdev_control_set_channels, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, userdev_server_redirect }; static audiodrv_t userdev_client_control_driver = { userdev_control_open, userdev_control_close, userdev_control_output_block, userdev_control_start_input, userdev_control_ioctl, userdev_control_prepare_for_input, userdev_control_prepare_for_output, userdev_control_reset, NULL, NULL, NULL, NULL, NULL, /* trigger */ userdev_control_set_rate, userdev_control_set_format, userdev_control_set_channels, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, userdev_client_redirect }; static void attach_control_device(void) {
Create the control device files that are used to create client/server device pairs and to redirect access to them.
userdev_devc_t *devc = (userdev_devc_t*)0xdeadcafe; /* This should never get referenced */ if ((client_dev = oss_install_audiodev_with_devname (OSS_AUDIO_DRIVER_VERSION, userdev_osdev, userdev_osdev, "User space audio device client side", &userdev_client_control_driver, sizeof (audiodrv_t), ADEV_AUTOMODE, AFMT_S16_NE, devc, -1, "client")) < 0) { return; } userdev_server_devnode = audio_engines[server_dev]->devnode; audio_engines[client_dev]->vmix_mixer=NULL; if ((server_dev = oss_install_audiodev_with_devname (OSS_AUDIO_DRIVER_VERSION, userdev_osdev, userdev_osdev, "User space audio device server side", &userdev_server_control_driver, sizeof (audiodrv_t), ADEV_AUTOMODE, AFMT_S16_NE, devc, -1, "server")) < 0) { return; } audio_engines[server_dev]->caps |= PCM_CAP_HIDDEN; audio_engines[server_dev]->vmix_mixer=NULL; userdev_client_devnode = audio_engines[client_dev]->devnode; } int oss_userdev_attach (oss_device_t * osdev) { userdev_osdev = osdev; osdev->devc = NULL; MUTEX_INIT (osdev, userdev_global_mutex, MH_DRV); oss_register_device (osdev, "User space audio driver subsystem"); attach_control_device(); return 1; } int oss_userdev_detach (oss_device_t * osdev) { userdev_devc_t *devc; if (oss_disable_device (osdev) < 0) return 0; devc = userdev_free_device_list; while (devc != NULL) { userdev_devc_t *next = devc->next_instance; userdev_delete_device_pair(devc); devc = next; } oss_unregister_device (osdev); MUTEX_CLEANUP(userdev_global_mutex); return 1; }