xref: /openbsd-src/usr.bin/sndiod/dev.h (revision 7b6392009e6e5a7f8e494c162a4d259ea5e13a62)
1*7b639200Sratchov /*	$OpenBSD: dev.h,v 1.47 2024/12/20 07:35:56 ratchov Exp $	*/
287bc9f6aSratchov /*
387bc9f6aSratchov  * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
487bc9f6aSratchov  *
587bc9f6aSratchov  * Permission to use, copy, modify, and distribute this software for any
687bc9f6aSratchov  * purpose with or without fee is hereby granted, provided that the above
787bc9f6aSratchov  * copyright notice and this permission notice appear in all copies.
887bc9f6aSratchov  *
987bc9f6aSratchov  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1087bc9f6aSratchov  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1187bc9f6aSratchov  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1287bc9f6aSratchov  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1387bc9f6aSratchov  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1487bc9f6aSratchov  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1587bc9f6aSratchov  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1687bc9f6aSratchov  */
1787bc9f6aSratchov #ifndef DEV_H
1887bc9f6aSratchov #define DEV_H
1987bc9f6aSratchov 
2087bc9f6aSratchov #include "abuf.h"
2187bc9f6aSratchov #include "dsp.h"
2287bc9f6aSratchov #include "siofile.h"
23d07fece6Sratchov #include "dev_sioctl.h"
245fb8f3c9Sratchov #include "opt.h"
25d07fece6Sratchov 
2687bc9f6aSratchov /*
270600d38bSratchov  * preallocated audio clients
280600d38bSratchov  */
290600d38bSratchov #define DEV_NSLOT	8
300600d38bSratchov 
310600d38bSratchov /*
32e5be4cb8Sratchov  * preallocated control clients
33e5be4cb8Sratchov  */
34e5be4cb8Sratchov #define DEV_NCTLSLOT 8
35e5be4cb8Sratchov 
36e5be4cb8Sratchov /*
3787bc9f6aSratchov  * audio stream state structure
3887bc9f6aSratchov  */
3987bc9f6aSratchov 
4087bc9f6aSratchov struct slotops
4187bc9f6aSratchov {
426f413563Sratchov 	void (*onmove)(void *);			/* clock tick */
434182f7f9Sratchov 	void (*onvol)(void *);			/* tell client vol changed */
4487bc9f6aSratchov 	void (*fill)(void *);			/* request to fill a play block */
4587bc9f6aSratchov 	void (*flush)(void *);			/* request to flush a rec block */
4687bc9f6aSratchov 	void (*eof)(void *);			/* notify that play drained */
4787bc9f6aSratchov 	void (*exit)(void *);			/* delete client */
4887bc9f6aSratchov };
4987bc9f6aSratchov 
50d07fece6Sratchov struct ctlops
51d07fece6Sratchov {
52d07fece6Sratchov 	void (*exit)(void *);			/* delete client */
53e575fbdeSratchov 	void (*sync)(void *);			/* description ready */
54d07fece6Sratchov };
55d07fece6Sratchov 
5687bc9f6aSratchov struct slot {
5787bc9f6aSratchov 	struct slotops *ops;			/* client callbacks */
5887bc9f6aSratchov 	struct slot *next;			/* next on the play list */
59f218ca2bSratchov 	struct opt *opt;			/* config used */
6087bc9f6aSratchov 	void *arg;				/* user data for callbacks */
6187bc9f6aSratchov 	struct aparams par;			/* socket side params */
6287bc9f6aSratchov 	struct {
6387bc9f6aSratchov 		int weight;			/* dynamic range */
6487bc9f6aSratchov 		unsigned int vol;		/* volume within the vol */
6587bc9f6aSratchov 		struct abuf buf;		/* socket side buffer */
6687bc9f6aSratchov 		int bpf;			/* byte per frame */
6723321a5cSratchov 		int nch;			/* number of play chans */
6887bc9f6aSratchov 		struct cmap cmap;		/* channel mapper state */
6987bc9f6aSratchov 		struct resamp resamp;		/* resampler state */
7087bc9f6aSratchov 		struct conv dec;		/* format decoder params */
7187bc9f6aSratchov 		int join;			/* channel join factor */
7287bc9f6aSratchov 		int expand;			/* channel expand factor */
7387bc9f6aSratchov 		void *resampbuf, *decbuf;	/* tmp buffers */
7487bc9f6aSratchov 	} mix;
7587bc9f6aSratchov 	struct {
7687bc9f6aSratchov 		struct abuf buf;		/* socket side buffer */
77f75a7ae7Sratchov 		int prime;			/* initial cycles to skip */
7887bc9f6aSratchov 		int bpf;			/* byte per frame */
7923321a5cSratchov 		int nch;			/* number of rec chans */
8087bc9f6aSratchov 		struct cmap cmap;		/* channel mapper state */
8187bc9f6aSratchov 		struct resamp resamp;		/* buffer for resampling */
8287bc9f6aSratchov 		struct conv enc;		/* buffer for encoding */
8387bc9f6aSratchov 		int join;			/* channel join factor */
8487bc9f6aSratchov 		int expand;			/* channel expand factor */
8587bc9f6aSratchov 		void *resampbuf, *encbuf;	/* tmp buffers */
8687bc9f6aSratchov 	} sub;
8787bc9f6aSratchov 	int xrun;				/* underrun policy */
88f75a7ae7Sratchov 	int skip;				/* cycles to skip (for xrun) */
8987bc9f6aSratchov #define SLOT_BUFSZ(s) \
90c67d5b9aSratchov 	((s)->appbufsz + (s)->opt->dev->bufsz / (s)->opt->dev->round * (s)->round)
9187bc9f6aSratchov 	int appbufsz;				/* slot-side buffer size */
9287bc9f6aSratchov 	int round;				/* slot-side block size */
9387bc9f6aSratchov 	int rate;				/* slot-side sample rate */
9487bc9f6aSratchov 	int delta;				/* pending clock ticks */
9587bc9f6aSratchov 	int delta_rem;				/* remainder for delta */
9687bc9f6aSratchov 	int mode;				/* MODE_{PLAY,REC} */
9787bc9f6aSratchov #define SLOT_INIT	0			/* not trying to do anything */
9887bc9f6aSratchov #define SLOT_START	1			/* buffer allocated */
9987bc9f6aSratchov #define SLOT_READY	2			/* buffer filled enough */
10087bc9f6aSratchov #define SLOT_RUN	3			/* buffer attached to device */
10187bc9f6aSratchov #define SLOT_STOP	4			/* draining */
10287bc9f6aSratchov 	int pstate;
10387bc9f6aSratchov 
10487bc9f6aSratchov #define SLOT_NAMEMAX	8
10587bc9f6aSratchov 	char name[SLOT_NAMEMAX];		/* name matching [a-z]+ */
10687bc9f6aSratchov 	unsigned int unit;			/* instance of name */
10787bc9f6aSratchov 	unsigned int serial;			/* global unique number */
10887bc9f6aSratchov 	unsigned int vol;			/* current (midi) volume */
1092988007fSratchov 	unsigned int id;			/* process id */
11087bc9f6aSratchov };
11187bc9f6aSratchov 
11287bc9f6aSratchov /*
113d07fece6Sratchov  * subset of channels of a stream
114d07fece6Sratchov  */
115d07fece6Sratchov 
116d07fece6Sratchov struct ctl {
117d07fece6Sratchov 	struct ctl *next;
11899580020Sratchov 
119d07fece6Sratchov #define CTL_NONE	0		/* deleted */
120d07fece6Sratchov #define CTL_NUM		2		/* number (aka integer value) */
121d07fece6Sratchov #define CTL_SW		3		/* on/off switch, only bit 7 counts */
122d07fece6Sratchov #define CTL_VEC		4		/* number, element of vector */
123d07fece6Sratchov #define CTL_LIST	5		/* switch, element of a list */
12449f67e12Sratchov #define CTL_SEL		6		/* element of a selector */
125d07fece6Sratchov 	unsigned int type;		/* one of above */
12699580020Sratchov 
12799580020Sratchov #define CTL_HW		0
12899580020Sratchov #define CTL_DEV_MASTER	1
12936355b88Sratchov #define CTL_OPT_DEV	2
13099580020Sratchov #define CTL_SLOT_LEVEL	3
13199580020Sratchov 	unsigned int scope;
13299580020Sratchov 	union {
13399580020Sratchov 		struct {
13499580020Sratchov 			void *arg0;
13599580020Sratchov 			void *arg1;
13699580020Sratchov 		} any;
13799580020Sratchov 		struct {
13899580020Sratchov 			struct dev *dev;
13999580020Sratchov 			unsigned int addr;
14099580020Sratchov 		} hw;
14199580020Sratchov 		struct {
14299580020Sratchov 			struct dev *dev;
14399580020Sratchov 		} dev_master;
14499580020Sratchov 		struct {
14599580020Sratchov 			struct slot *slot;
14699580020Sratchov 		} slot_level;
14736355b88Sratchov 		struct {
14836355b88Sratchov 			struct slot *slot;
14936355b88Sratchov 			struct opt *opt;
15036355b88Sratchov 		} slot_opt;
15136355b88Sratchov 		struct {
15236355b88Sratchov 			struct opt *opt;
15336355b88Sratchov 			struct dev *dev;
15436355b88Sratchov 		} opt_dev;
15599580020Sratchov 	} u;
15699580020Sratchov 
15799580020Sratchov 	unsigned int addr;		/* slot side control address */
1584d8b188fSratchov #define CTL_NAMEMAX	12		/* max name length */
1594d8b188fSratchov #define CTL_DISPLAYMAX	24		/* max name length */
160d07fece6Sratchov 	char func[CTL_NAMEMAX];		/* parameter function name */
161d07fece6Sratchov 	char group[CTL_NAMEMAX];	/* group aka namespace */
1624d8b188fSratchov 	char display[CTL_DISPLAYMAX];	/* free-format hint */
163d07fece6Sratchov 	struct ctl_node {
164d07fece6Sratchov 		char name[CTL_NAMEMAX];	/* stream name */
165d07fece6Sratchov 		int unit;
166d07fece6Sratchov 	} node0, node1;			/* affected channels */
167d07fece6Sratchov #define CTL_DEVMASK		(1 << 31)
168d07fece6Sratchov #define CTL_SLOTMASK(i)		(1 << (i))
169d07fece6Sratchov 	unsigned int val_mask;
170d07fece6Sratchov 	unsigned int desc_mask;
171d07fece6Sratchov 	unsigned int refs_mask;
172d07fece6Sratchov 	unsigned int maxval;
173d07fece6Sratchov 	unsigned int curval;
174d07fece6Sratchov 	int dirty;
175d07fece6Sratchov };
176d07fece6Sratchov 
177d07fece6Sratchov struct ctlslot {
178d07fece6Sratchov 	struct ctlops *ops;
179d07fece6Sratchov 	void *arg;
180bb6cfcd4Sratchov 	struct opt *opt;
181c7054416Sratchov 	unsigned int self;		/* equal to (1 << index) */
182d07fece6Sratchov 	unsigned int mode;
183d07fece6Sratchov };
184d07fece6Sratchov 
185d07fece6Sratchov /*
1860e6be583Sratchov  * MIDI time code (MTC)
1870e6be583Sratchov  */
1880e6be583Sratchov struct mtc {
1890e6be583Sratchov 	/*
1900e6be583Sratchov 	 * MIDI time code (MTC) states
1910e6be583Sratchov 	 */
1920e6be583Sratchov #define MTC_STOP	1		/* stopped, can't start */
1930e6be583Sratchov #define MTC_START	2		/* attempting to start */
1940e6be583Sratchov #define MTC_RUN		3		/* started */
1950e6be583Sratchov 	unsigned int tstate;		/* one of MTC_* constants */
1960e6be583Sratchov 	struct dev *dev;
1970e6be583Sratchov 
1980e6be583Sratchov 	unsigned int origin;		/* MTC start time */
1990e6be583Sratchov 	unsigned int fps;		/* MTC frames per second */
2000e6be583Sratchov #define MTC_FPS_24	0
2010e6be583Sratchov #define MTC_FPS_25	1
2020e6be583Sratchov #define MTC_FPS_30	3
2030e6be583Sratchov 	unsigned int fps_id;		/* one of above */
2040e6be583Sratchov 	unsigned int hr;		/* MTC hours */
2050e6be583Sratchov 	unsigned int min;		/* MTC minutes */
2060e6be583Sratchov 	unsigned int sec;		/* MTC seconds */
2070e6be583Sratchov 	unsigned int fr;		/* MTC frames */
2080e6be583Sratchov 	unsigned int qfr;		/* MTC quarter frames */
2090e6be583Sratchov 	int delta;			/* rel. to the last MTC tick */
2100e6be583Sratchov 	int refs;
2110e6be583Sratchov };
2120e6be583Sratchov 
2130e6be583Sratchov /*
21487bc9f6aSratchov  * audio device with plenty of slots
21587bc9f6aSratchov  */
21687bc9f6aSratchov struct dev {
21787bc9f6aSratchov 	struct dev *next;
21887bc9f6aSratchov 	struct slot *slot_list;			/* audio streams attached */
21987bc9f6aSratchov 
22087bc9f6aSratchov 	/*
22199580020Sratchov 	 * name used for various controls
22299580020Sratchov 	 */
22399580020Sratchov 	char name[CTL_NAMEMAX];
22499580020Sratchov 
22599580020Sratchov 	/*
22636355b88Sratchov 	 * next to try if this fails
22736355b88Sratchov 	 */
22836355b88Sratchov 	struct dev *alt_next;
22936355b88Sratchov 
23036355b88Sratchov 	/*
23187bc9f6aSratchov 	 * audio device (while opened)
23287bc9f6aSratchov 	 */
23367db5a8cSratchov 	struct dev_sio sio;
234d07fece6Sratchov 	struct dev_sioctl sioctl;
23587bc9f6aSratchov 	struct aparams par;			/* encoding */
23687bc9f6aSratchov 	int pchan, rchan;			/* play & rec channels */
23787bc9f6aSratchov 	adata_t *rbuf;				/* rec buffer */
23887bc9f6aSratchov 	adata_t *pbuf;				/* array of play buffers */
23987bc9f6aSratchov #define DEV_PBUF(d) ((d)->pbuf + (d)->poffs * (d)->pchan)
24087bc9f6aSratchov 	int poffs;				/* index of current play buf */
2418aadda71Sratchov 	int psize;				/* size of play buffer */
24287bc9f6aSratchov 	struct conv enc;			/* native->device format */
24387bc9f6aSratchov 	struct conv dec;			/* device->native format */
24487bc9f6aSratchov 	unsigned char *encbuf;			/* buffer for encoding */
24587bc9f6aSratchov 	unsigned char *decbuf;			/* buffer for decoding */
24687bc9f6aSratchov 
24787bc9f6aSratchov 	/*
248f75a7ae7Sratchov 	 * current position, relative to the current cycle
249f75a7ae7Sratchov 	 */
250f75a7ae7Sratchov 	int delta;
251f75a7ae7Sratchov 
252f75a7ae7Sratchov 	/*
25387bc9f6aSratchov 	 * desired parameters
25487bc9f6aSratchov 	 */
25587bc9f6aSratchov 	unsigned int reqmode;			/* mode */
25687bc9f6aSratchov 	struct aparams reqpar;			/* parameters */
25787bc9f6aSratchov 	int reqpchan, reqrchan;			/* play & rec chans */
25887bc9f6aSratchov 	unsigned int reqbufsz;			/* buffer size */
25987bc9f6aSratchov 	unsigned int reqround;			/* block size */
26087bc9f6aSratchov 	unsigned int reqrate;			/* sample rate */
26187bc9f6aSratchov 	unsigned int hold;			/* hold the device open ? */
26287bc9f6aSratchov 	unsigned int autovol;			/* auto adjust playvol ? */
26387bc9f6aSratchov 	unsigned int refcnt;			/* number of openers */
26487bc9f6aSratchov #define DEV_NMAX	16			/* max number of devices */
26587bc9f6aSratchov 	unsigned int num;			/* device serial number */
26687bc9f6aSratchov #define DEV_CFG		0			/* closed */
26787bc9f6aSratchov #define DEV_INIT	1			/* stopped */
268489212eaSratchov #define DEV_RUN		2			/* playin & recording */
26987bc9f6aSratchov 	unsigned int pstate;			/* one of above */
27036355b88Sratchov 	char *path;
27187bc9f6aSratchov 
27287bc9f6aSratchov 	/*
27387bc9f6aSratchov 	 * actual parameters and runtime state (i.e. once opened)
27487bc9f6aSratchov 	 */
27587bc9f6aSratchov 	unsigned int mode;			/* bitmap of MODE_xxx */
27687bc9f6aSratchov 	unsigned int bufsz, round, rate;
27787bc9f6aSratchov 	unsigned int prime;
2780add8717Sratchov 	unsigned int idle;			/* cycles with no client */
27987bc9f6aSratchov 
280f08c7e02Sratchov 	unsigned int master;			/* software vol. knob */
281f08c7e02Sratchov 	unsigned int master_enabled;		/* 1 if h/w has no vo. knob */
28287bc9f6aSratchov };
28387bc9f6aSratchov 
28487bc9f6aSratchov extern struct dev *dev_list;
28599580020Sratchov extern struct ctl *ctl_list;
2860600d38bSratchov extern struct slot slot_array[DEV_NSLOT];
287e5be4cb8Sratchov extern struct ctlslot ctlslot_array[DEV_NCTLSLOT];
2880e6be583Sratchov extern struct mtc mtc_array[1];
2890600d38bSratchov 
2900600d38bSratchov void slot_array_init(void);
291*7b639200Sratchov size_t chans_fmt(char *, size_t, int, int, int, int, int);
29236355b88Sratchov int dev_open(struct dev *);
29336355b88Sratchov void dev_close(struct dev *);
2944a2af8d6Sratchov void dev_abort(struct dev *);
29536355b88Sratchov struct dev *dev_migrate(struct dev *);
29687bc9f6aSratchov struct dev *dev_new(char *, struct aparams *, unsigned int, unsigned int,
29787bc9f6aSratchov     unsigned int, unsigned int, unsigned int, unsigned int);
29887bc9f6aSratchov struct dev *dev_bynum(int);
29987bc9f6aSratchov void dev_del(struct dev *);
3004182f7f9Sratchov void dev_adjpar(struct dev *, int, int, int);
30187bc9f6aSratchov int  dev_init(struct dev *);
30287bc9f6aSratchov void dev_done(struct dev *);
303eb88882fSratchov int dev_ref(struct dev *);
304eb88882fSratchov void dev_unref(struct dev *);
30587bc9f6aSratchov unsigned int dev_roundof(struct dev *, unsigned int);
30636355b88Sratchov int dev_iscompat(struct dev *, struct dev *);
30787bc9f6aSratchov 
30887bc9f6aSratchov /*
30987bc9f6aSratchov  * interface to hardware device
31087bc9f6aSratchov  */
31187bc9f6aSratchov void dev_onmove(struct dev *, int);
31287bc9f6aSratchov void dev_cycle(struct dev *);
31387bc9f6aSratchov 
31487bc9f6aSratchov /*
31587bc9f6aSratchov  * midi & midi call-backs
31687bc9f6aSratchov  */
3175fb8f3c9Sratchov void dev_master(struct dev *, unsigned int);
3185fb8f3c9Sratchov void dev_midi_send(struct dev *, void *, int);
3195fb8f3c9Sratchov void dev_midi_vol(struct dev *, struct slot *);
3205fb8f3c9Sratchov void dev_midi_master(struct dev *);
3215fb8f3c9Sratchov void dev_midi_slotdesc(struct dev *, struct slot *);
3225fb8f3c9Sratchov void dev_midi_dump(struct dev *);
3235fb8f3c9Sratchov 
3240e6be583Sratchov void mtc_midi_qfr(struct mtc *, int);
3250e6be583Sratchov void mtc_midi_full(struct mtc *);
3260e6be583Sratchov void mtc_trigger(struct mtc *);
3270e6be583Sratchov void mtc_start(struct mtc *);
3280e6be583Sratchov void mtc_stop(struct mtc *);
3290e6be583Sratchov void mtc_loc(struct mtc *, unsigned int);
3300e6be583Sratchov void mtc_setdev(struct mtc *, struct dev *);
33187bc9f6aSratchov 
33287bc9f6aSratchov /*
33387bc9f6aSratchov  * sio_open(3) like interface for clients
33487bc9f6aSratchov  */
335c67d5b9aSratchov struct slot *slot_new(struct opt *, unsigned int, char *,
336f94911feSratchov     struct slotops *, void *, int);
33787bc9f6aSratchov void slot_del(struct slot *);
33887bc9f6aSratchov void slot_setvol(struct slot *, unsigned int);
33936355b88Sratchov void slot_setopt(struct slot *, struct opt *);
34087bc9f6aSratchov void slot_start(struct slot *);
341dff6ad49Sratchov void slot_stop(struct slot *, int);
34287bc9f6aSratchov void slot_read(struct slot *);
34387bc9f6aSratchov void slot_write(struct slot *);
344bd219fc7Sratchov void slot_initconv(struct slot *);
345bd219fc7Sratchov void slot_attach(struct slot *);
346bd219fc7Sratchov void slot_detach(struct slot *);
34787bc9f6aSratchov 
348d07fece6Sratchov /*
349d07fece6Sratchov  * control related functions
350d07fece6Sratchov  */
35199580020Sratchov 
35299580020Sratchov struct ctl *ctl_new(int, void *, void *,
3534d8b188fSratchov     int, char *, char *, char *, int, char *, char *, int, int, int);
354ea04d488Sratchov int ctl_del(int, void *, void *);
355*7b639200Sratchov size_t ctl_node_fmt(char *, size_t, struct ctl_node *);
356*7b639200Sratchov size_t ctl_scope_fmt(char *, size_t, struct ctl *);
357*7b639200Sratchov size_t ctl_fmt(char *, size_t, struct ctl *);
35899580020Sratchov int ctl_setval(struct ctl *c, int val);
35999580020Sratchov int ctl_match(struct ctl *, int, void *, void *);
36099580020Sratchov struct ctl *ctl_find(int, void *, void *);
36199580020Sratchov void ctl_update(struct ctl *);
36299580020Sratchov int ctl_onval(int, void *, void *, int);
36399580020Sratchov 
364bb6cfcd4Sratchov struct ctlslot *ctlslot_new(struct opt *, struct ctlops *, void *);
365d07fece6Sratchov void ctlslot_del(struct ctlslot *);
36699580020Sratchov int ctlslot_visible(struct ctlslot *, struct ctl *);
36799580020Sratchov struct ctl *ctlslot_lookup(struct ctlslot *, int);
36836355b88Sratchov void ctlslot_update(struct ctlslot *);
36936355b88Sratchov 
3704d8b188fSratchov char *dev_getdisplay(struct dev *);
371e575fbdeSratchov void dev_ctlsync(struct dev *);
372d07fece6Sratchov 
37387bc9f6aSratchov #endif /* !defined(DEV_H) */
374