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