summaryrefslogtreecommitdiff
path: root/kernel/framework/include/audio_core.h
blob: 59aa3bcfb9fbb5b9ee43f99f990661695c8d10cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
#ifndef AUDIO_CORE_H
#define AUDIO_CORE_H
/*
 * Purpose: Internal definitions for the OS audio core
 *
 * IMPORTANT NOTICE!
 *
 * This file contains internal structures used by Open Sound Systems.
 * They will change without any notice between OSS versions. Care must be taken
 * to make sure any software using this header gets properly re-compiled before
 * use.
 *
 * 4Front Technologies (or anybody else) takes no responsibility of damages
 * caused by use of this file.
 */

/*
 *
 * 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.
 *
 */

/*
 * Max number of audio channels currently supported by the sample format converter.
 */
#define OSS_MAX_CONVERT_CHANNELS	64

/*
 * Size of the temporary buffer used for audio conversions.
 *
 * TMP_CONVERT_MAX defines how many bytes can be fed to the converter in
 * one call.
 *
 * TMP_CONVERT_BUF_SIZE defines how many bytes of buffer will be allocated.
 * This is larger than TMP_CONVERT_MAX because amount of data may get expanded
 * during the conversion (for example if the output sampling rate or #channels
 * is larger than in the input side).
 */
#define TMP_CONVERT_MAX		(16*1024)
#define TMP_CONVERT_BUF_SIZE	(8*TMP_CONVERT_MAX)

/*
 * open_flags (for opening audio devices)
 */
#define OF_MMAP		0x00000001	/* Opening application is known to use mmap() */
#define OF_BLOCK	0x00000002	/* Disable O_NONBLOCK */
#define OF_NOCONV	0x00000010	/* Disable all fmt/src conversions */
#define OF_DEVAUDIO	0x00000020	/* Solaris /dev/audio emulator */
#define OF_SMALLFRAGS	0x00000040	/* Use smaller fragments than requested */
#define OF_SMALLBUF	0x00000080	/* Allocate small (4k) buffer this time */
#define OF_MEDIUMBUF	0x00000100	/* Allocate moderate (16k) buffer */

#define CONVERTABLE_FORMATS \
	(AFMT_U8|AFMT_S8|AFMT_MU_LAW|AFMT_S16_LE|AFMT_S16_BE|\
	 AFMT_S24_LE|AFMT_S24_BE|AFMT_S32_LE|AFMT_S32_BE|AFMT_S24_PACKED)

#ifndef _KERNEL
typedef struct _audiodrv_t audiodrv_t;
#endif

typedef struct
{
  char *name;
  int fmt;
  unsigned char neutral_byte;
  char bits;
  char is_linear;
  char endianess;
#define ENDIAN_NONE		0
#define ENDIAN_LITTLE 	1
#define ENDIAN_BIG	  	2
#ifdef OSS_BIG_ENDIAN
# define ENDIAN_NATIVE ENDIAN_BIG
#else
# define ENDIAN_NATIVE ENDIAN_LITTLE
#endif

  char is_signed;
  char alignment;
#define ALIGN_MSB		0
#define ALIGN_LSB		1
  int no_convert;
}
audio_format_info_t, *audio_format_info_p;

typedef struct
{
  int fmt, rate, channels;
  int convert;
}
sample_parms;

typedef struct _adev_t adev_t, *adev_p;
typedef struct _dmap_t *dmap_p;
typedef int (*cnv_func_t) (adev_p adev, dmap_p dmap, unsigned char **srcp, int *srcl,
			   unsigned char **tgtp, sample_parms * source,
			   sample_parms * target);

struct _dmap_t
{
/*
 * Static fields (not to be cleared during open)
 */
#ifdef _KERNEL
  oss_mutex_t mutex;
#endif
  oss_device_t *osdev;
  oss_device_t *master_osdev;	/* The osdev pointer of the master (for virtual drivers) */
  adev_t *adev;
  unsigned char *dmabuf;
  oss_native_word dmabuf_phys;
  oss_dma_handle_t dmabuf_dma_handle;
  int buffsize;
  int buffer_protected;		/* Buffer is shared - don't modify/clear */
  unsigned char *tmpbuf1, *tmpbuf2;
  void *driver_use_ptr;
  long driver_use_value;
  /* Interrupt callback stuff */
  void (*audio_callback) (int dev, int parm);
  int callback_parm;

#ifdef OS_DMA_PARMS
    OS_DMA_PARMS
#endif
/*
 * Dynamic fields (will be zeroed during open)
 * Don't add anything before flags.
 */
  void *srcstate[OSS_MAX_CONVERT_CHANNELS];
  oss_native_word flags;
#define DMAP_NOTIMEOUT	0x00000001
#define DMAP_POST		0x00000002
#define DMAP_PREPARED	0x00000004
#define DMAP_FRAGFIXED	0x00000008	/* Fragment size fixed */
#define DMAP_STARTED	0x00000010
#define DMAP_COOKED		0x00000020
#define DMAP_SMALLBUF     0x00000040	/* Allocate small buffers */
#define DMAP_MEDIUMBUF     0x00000040	/* Allocate 16k buffers */
  int dma_mode;			/* PCM_ENABLE_INPUT, PCM_ENABLE_OUTPUT or 0 */

  /*
   * Queue parameters.
   */
  int nfrags;
  int fragment_size;
  int bytes_in_use;
  int data_rate;		/* Bytes/second */
  int frame_size;		/* Device frame size */
  int user_frame_size;		/* Application frame size */
  int fragsize_rq;
  int low_water, low_water_rq;
  volatile oss_uint64_t byte_counter;
  volatile oss_uint64_t user_counter;
  int interrupt_count;
  int fragment_counter;
  int expand_factor;

  int mapping_flags;
#define			DMA_MAP_MAPPED		0x00000001
  char neutral_byte;

  int error;
  int play_underruns, rec_overruns;
  int underrun_flag;
  int num_errors;
#define MAX_AUDIO_ERRORS	5
  int errors[MAX_AUDIO_ERRORS];
  int error_parms[MAX_AUDIO_ERRORS];

  unsigned char *leftover_buf;
  int leftover_bytes;
  int tmpbuf_len, tmpbuf_ptr;
  cnv_func_t convert_func;
  unsigned int convert_mode;
  struct audio_buffer *(*user_import) (adev_t * adev,
				       dmap_t * dmap,
				       sample_parms * parms,
				       unsigned char *cbuf, int len);
  int (*user_export) (adev_t * adev,
		      dmap_t * dmap, sample_parms * parms,
		      struct audio_buffer * buf, unsigned char *cbuf,
		      int maxbytes);
  struct audio_buffer *(*device_read) (adev_t * adev,
				       dmap_t * dmap,
				       sample_parms * parms,
				       unsigned char *cbuf, int len);
  int (*device_write) (adev_t * adev,
		       dmap_t * dmap,
		       void *frombuf, void *tobuf,
		       int maxspace, int *fromlen, int *tolen);
};
extern int dmap_get_qlen (dmap_t * dmap);
extern int dmap_get_qhead (dmap_t * dmap);
extern int dmap_get_qtail (dmap_t * dmap);

struct _adev_t
{
  char name[64];
  char handle[32];
  int engine_num;		/* Audio engine number */
  int audio_devfile;		/* Audio device file number */
  int enabled;
  int unloaded;
  struct _adev_t *next_in, *next_out;	/* Links to the next "shadow" devices */
  long long flags;
  int open_flags;
  int src_quality;
  int caps;
  int magic;			/* Secret low level driver ID */
  int latency;			/* In usecs, -1=unknown */


  /*
   * Sampling parameters
   */

  sample_parms user_parms, hw_parms;
  int iformat_mask, oformat_mask;	/* Bitmasks for supported audio formats */
  int min_rate, max_rate;	/* Sampling rate limits */
  int min_channels, max_channels;
  char *inch_names, *outch_names;
  int xformat_mask;		/* Format mask for current open mode */
  int binding;
  void *devc;			/* Driver specific info */
  audiodrv_t *d;
  void *portc, *portc_play, *portc_record;	/* Driver specific info */
  dmap_t *dmap_in, *dmap_out;
  int mixer_dev;
  int open_mode;
  int go;
  int enable_bits;
  int parent_dev;		/* 0 -> no parent, 1 to n -> parent=parent_dev+1 */
  int max_block;		/* Maximum fragment size to be accepted */
  int min_block;		/* Minimum fragment size */
  int min_fragments;		/* Minimum number of fragments */
  int max_fragments;		/* Maximum number of fragments */
  int max_intrate;		/* Another form of min_block */
  int dmabuf_alloc_flags;
  oss_uint64_t dmabuf_maxaddr;
  int fixed_rate;
  int vmix_flags;		/* special flags sent to virtual mixer */
#define VMIX_MULTIFRAG	0x00000001	/* More than 2 fragments required (causes longer latencies) */
#define VMIX_DISABLED	0x00000002	/* Not compatible with vmix */
#define VMIX_NOINPUT	0x00000004	/* Disable input capability */
#define VMIX_NOMAINVOL	0x00000008	/* No main volume sliders/meters please */
  pid_t pid;
  char cmd[16];
  oss_device_t *osdev;
  oss_device_t *master_osdev;	/* The osdev pointer of the master (for virtual drivers) */
  int setfragment_warned;
  int getispace_error_count;
  int redirect_in, redirect_out;
  int dmask;			/* Open dmaps */
#define DMASK_OUT		0x01
#define DMASK_IN		0x02
  int nonblock;
  int forced_nonblock;
  int ossd_registered;
  int sync_flags;
#define SYNC_MASTER		0x01
#define SYNC_SLAVE		0x02
  int sync_group;
  int sync_mode;
  adev_t *sync_next;		/* Next device in sync group */

  int rate_source;
  unsigned int nrates, rates[OSS_MAX_SAMPLE_RATES + 1];

#ifdef _KERNEL
  oss_mutex_t mutex;
  oss_wait_queue_t *out_wq, *in_wq;
#endif

  int card_number;
  int port_number;
  int real_dev;

/*
 * By default OSS will let applications to use sampling rates and formats
 * that are not supported by the hardware. Instead OSS performs the necessary
 * format conversions in software. Applications that don't tolerate this kind
 * of conversions usually disable them by using features of the OSS API
 * (SNDCTL_DSP_COOKEDMODE). If this option is set to 0 then the format
 * conversions will be disabled for all applications and devices unless the
 * application explicitly enables them.
 *
 * cooked_enable is a global variable (int) defined in oss_core_options.c. The current
 * value of this global variable will be copied to adev->cooked_enable when
 * an audio engine is opened.
 */
  int cooked_enable;
  int timeout_count;

  void (*outputintr) (int dev, int intr_flags);
  void (*inputintr) (int dev, int intr_flags);

  int policy;
  void *os_id;			/* The device ID (dip) given by the system. */
  oss_longname_t song_name;
  oss_label_t label;
  oss_devnode_t devnode;
  void *vmix_mixer;		/* Pointer to the vmix_mixer_t structure for this device */
  void *prev_vmix_mixer;	/* Reserved for vmix_core */
};

#define UNIT_EXPAND		1024

/*
 * The audio_devfiles and audio_engines tables contain pointers to
 * the (same) adev_t structures. The difference is that
 * audio_engines contains an entry for all audio devices/engines in the system
 * (including hidden and shadow devices). The 'dev' parameter of most audio
 * core routines and audio driver methods are indexes to this array.
 *
 * The audio_devfiles array is a "parallel" structure that contains only
 * the audio engines that have a device file in /dev/oss (and usually also
 * an legacy /dev/dsp# device file). This audio_devfiles array doesn't contain
 * "hidden" audio engines.
 *
 * Each audio operations structure in audio_devfiles will also be in
 * audio_engines but the indexes are different. Both arrays contain pointer to
 * the same structure in memory (not a copy).
 *
 * For example the 6th audio device file (usually but not always /dev/dsp5) is
 * audio_devfiles[5]. However it may be (say) audio_engines[11] if there are
 * hidden devices created before it.
 *
 *  /dev/dsp5 -> audio_devfile[5] == audio_engines[11]
 *
 * The next field of the adev_t structure contains a pointer
 * to the next "identical" device. Most OSS implementations will
 * try to open one of the subsequent devices in the next chain if
 * the original device was busy. "Identical" means that the device suports
 * multiple identical (hw mixing) engines or the vmix driver is used to
 * add software mixing capability to the device.
 */

extern adev_t **audio_engines;
extern int num_audio_engines;
extern adev_t **audio_devfiles;
extern int num_audio_devfiles;

#if 0
typedef struct
{
  int ndevs;
  unsigned short devices[MAX_AUDIO_DEVFILES];
}
oss_devlist_t;

extern oss_devlist_t dspoutlist, dspoutlist2, dspinlist, dspinoutlist;
#endif

int oss_install_audiodev (int vers,
			  oss_device_t * osdev,
			  oss_device_t * master_osdev,
			  char *name,
			  const audiodrv_t * driver,
			  int driver_size,
			  unsigned long long flags,
			  unsigned int format_mask, void *devc, int parent);

int oss_install_audiodev_with_devname (int vers,
			  oss_device_t * osdev,
			  oss_device_t * master_osdev,
			  char *name,
			  const audiodrv_t * driver,
			  int driver_size,
			  int flags,
			  unsigned int format_mask, void *devc, int parent,
			  const char *devfile_name);
extern void install_vdsp (oss_device_t * osdev);
extern int *load_mixer_volumes (char *name, int *levels, int present);

#ifdef _KERNEL
int oss_audio_read (int dev, struct fileinfo *file, uio_t * buf, int count);
int oss_audio_write (int dev, struct fileinfo *file, uio_t * buf, int count);
int oss_audio_open_engine (int dev, int dev_class, struct fileinfo *file,
			   int recursive, int open_flags, int *newdev);
int oss_audio_open_devfile (int dev, int dev_class, struct fileinfo *file,
			    int recursive, int open_flags, int *newdev);
int oss_open_vdsp (int dev, int dev_type, struct fileinfo *file,
		   int recursive, int open_flags, int *newdev);
void oss_audio_release (int dev, struct fileinfo *file);
int oss_audio_ioctl (int dev, struct fileinfo *file,
		     unsigned int cmd, ioctl_arg arg);
int oss_audio_set_format (int dev, int fmt, int format_mask);
int oss_audio_set_channels (int dev, int ch);
int oss_audio_set_rate (int dev, int val);
void audio_uninit_device (int dev);
int oss_audio_mmap (int dev, int direction);
#endif

/* From audiofmt.c */
int setup_format_conversions (adev_p adev, dmap_p dmap, sample_parms * source,
			      sample_parms * target,
			      sample_parms * user,
			      sample_parms * device, int format_mask);
audio_format_info_p oss_find_format (unsigned int fmt);


#define oss_audio_outputintr(dev, flags) audio_engines[dev]->outputintr(dev, flags)
#define oss_audio_inputintr(dev, flags) audio_engines[dev]->inputintr(dev, flags)
void oss_audio_reset (int dev);
void oss_audio_start_syncgroup (unsigned int syncgroup);
typedef int (*oss_audio_startup_func) (void *devc);
extern void oss_audio_register_client (oss_audio_startup_func func,
				       void *devc, oss_device_t * osdev);

extern int oss_encode_enum (oss_mixer_enuminfo * ei, const char *s,
			    int version);
extern char *audio_show_latency (int dev);
extern void oss_audio_inc_byte_counter (dmap_t * dmap, int increment);
extern void oss_add_audio_devlist (int list, int devfile);

#ifndef SMALL_DMABUF_SIZE
#define SMALL_DMABUF_SIZE (4*1024)
#endif

#define MEDIUM_DMABUF_SIZE (16*1024)
#endif