1 /* libsst.c - SPARC sound tools library
3 ** Copyright (C) 1989 by Jef Poskanzer.
5 ** Permission to use, copy, modify, and distribute this software and its
6 ** documentation for any purpose and without fee is hereby granted, provided
7 ** that the above copyright notice appear in all copies and that both that
8 ** copyright notice and this permission notice appear in supporting
9 ** documentation. This software is provided "as is" without express or
12 ** Hacked on by jwz for emacs.
16 /* Synched up with: Not in FSF. */
35 int sst_open(play_level, record_level)
36 int play_level, record_level;
38 int fd, i, gr, ger, gx;
39 struct audio_ioctl ai;
42 fd = open("/dev/audio", O_RDWR);
44 perror("sst_open: open /dev/audio");
47 #ifdef AUDIOSETQSIZE /* This no longer exists as of 4.1.2. */
49 /* Shrink audio device's queue size, to cut down time delay. */
51 if (ioctl(fd, AUDIOSETQSIZE, &i) < 0) {
52 perror("sst_open: SETQSIZE");
55 #endif /* AUDIOSETQSIZE */
57 /* Set gains. -10 <= ger <= 18, -18 <= gr <= 12, -18 <= gx <= 12. */
60 if ((ep = getenv("SST_PLAY")) != NULL) {
61 play_level = atoi(ep);
62 if (play_level < 0 || play_level > 99) {
63 warn("sst_open: SST_PLAY must be between 0 and 99");
70 if ((ep = getenv("SST_RECORD")) != NULL) {
71 record_level = atoi(ep);
72 if (record_level < 0 || record_level > 99) {
73 warn("sst_open: SST_RECORD must be between 0 and 99");
79 play_level = play_level * 59 / 100 - 28;
81 gr = play_level - ger;
84 gr = play_level - ger;
88 ger = play_level - gr;
90 gx = record_level * 31 / 100 - 18;
95 /* Initialize the MMR2 register to send the output to either
96 ** the speaker or the earphone jack, depending on SST_EARPHONES.
98 ai.control = AUDIO_MAP_MMR2;
99 if (ioctl(fd, AUDIOGETREG, &ai) < 0) {
100 perror("sst_open: GETREG MMR2");
103 if ((ep = getenv("SST_EARPHONES")) != NULL)
104 ai.data[0] &= ~AUDIO_MMR2_BITS_LS;
106 ai.data[0] |= AUDIO_MMR2_BITS_LS;
107 if (ioctl(fd, AUDIOSETREG, &ai) < 0) {
108 perror("sst_open: SETREG MMR2");
118 struct audio_ioctl ai;
120 ai.control = AUDIO_MAP_MMR1;
122 if (ioctl(fd, AUDIOSETREG, &ai) < 0) {
123 perror("sst_close: SETREG MMR1");
125 ai.control = AUDIO_MAP_MMR2;
127 if (ioctl(fd, AUDIOSETREG, &ai) < 0) {
128 perror("sst_close: SETREG MMR2");
133 /* These are tables of values to be loaded into various gain registers.
136 static unsigned char ger_table[][2] = {
137 0xaa, 0xaa, /* -10db */
141 0x74, 0x9c, /* -6db */
147 0x00, 0x99, /* 0db */
153 0x40, 0xdd, /* 6db */
159 0x42, 0x10, /* 12db */
165 0x00, 0x0f, /* 18db */
168 static unsigned char gr_gx_table[][2] = {
169 0x8b, 0x7c, /* -18db */
175 0x91, 0xf9, /* -12db */
181 0x9f, 0x91, /* -6db */
187 0x08, 0x08, /* 0db */
193 0x10, 0xf2, /* 6db */
199 0x00, 0x0e, /* 12db */
202 void sst_set_ger(fd, value)
205 struct audio_ioctl ai;
207 if ((value < -10) || (value > 18)) {
209 sprintf(buf, "sst_set_ger: GER %d out of range", value);
214 /* Add 10 to the value to get the index into the table. */
215 ai.control = AUDIO_MAP_GER;
216 ai.data[0] = ger_table[value + 10][1];
217 ai.data[1] = ger_table[value + 10][0];
219 if (ioctl(fd, AUDIOSETREG, &ai) < 0) {
220 perror("sst_set_ger: SETREG GER");
223 ai.control = AUDIO_MAP_MMR1;
224 if (ioctl(fd, AUDIOGETREG, &ai) < 0) {
225 perror("sst_set_ger: GETREG MMR1");
227 ai.data[0] |= AUDIO_MMR1_BITS_LOAD_GER;
228 if (ioctl(fd, AUDIOSETREG, &ai) < 0) {
229 perror("sst_set_ger: SETREG MMR1");
233 void sst_set_gr(fd, value)
236 struct audio_ioctl ai;
238 if ((value < -18) || (value > 12)) {
240 sprintf(buf, "sst_set_gr: GR %d out of range", value);
245 ai.control = AUDIO_MAP_GR;
246 ai.data[0] = gr_gx_table[value + 18][1];
247 ai.data[1] = gr_gx_table[value + 18][0];
249 if (ioctl(fd, AUDIOSETREG, &ai) < 0) {
250 perror("sst_set_gr: SETREG GR");
253 ai.control = AUDIO_MAP_MMR1;
254 if (ioctl(fd, AUDIOGETREG, &ai) < 0) {
255 perror("sst_set_gr: GETREG MMR1");
257 ai.data[0] |= AUDIO_MMR1_BITS_LOAD_GR;
258 if (ioctl(fd, AUDIOSETREG, &ai) < 0) {
259 perror("sst_set_gr: SETREG MMR1");
263 void sst_set_gx(fd, value)
266 struct audio_ioctl ai;
269 if ((value < -18) || (value > 12)) {
270 sprintf(buf, "sst_set_gx: GX %d out of range", value);
275 /* We add 18 to get the index into the table, since entry 0 represents
278 ai.control = AUDIO_MAP_GX;
279 ai.data[0] = gr_gx_table[value + 18][1];
280 ai.data[1] = gr_gx_table[value + 18][0];
282 if (ioctl(fd, AUDIOSETREG, &ai) < 0) {
283 perror("sst_set_gx: SETREG GX");
286 ai.control = AUDIO_MAP_MMR1;
287 if (ioctl(fd, AUDIOGETREG, &ai) < 0) {
288 perror("sst_set_gx: GETREG MMR1");
290 ai.data[0] |= AUDIO_MMR1_BITS_LOAD_GX;
291 if (ioctl(fd, AUDIOSETREG, &ai) < 0) {
292 perror("sst_set_gx: SETREG MMR1");
296 void sst_tones(fd, dhz1, dhz2, thz, rhz, usec)
297 int fd, dhz1, dhz2, thz, rhz, usec;
300 struct audio_ioctl ai;
301 int dval1, dval2, tval, rval;
302 unsigned char oldmmr2, newmmr2;
307 dval1 = (dhz1 * 128 + 63) / 1000;
308 if ((dval1 < 1) || (dval1 > 255)) {
309 sprintf(buf, "sst_tones: dhz1 %d out of range", dhz1);
318 dval2 = (dhz2 * 128 + 63) / 1000;
319 if ((dval2 < 1) || (dval2 > 255)) {
320 sprintf(buf, "sst_tones: dhz2 %d out of range", dhz2);
329 tval = (thz * 128 + 63) / 2000;
330 if ((tval < 1) || (tval > 255)) {
331 sprintf(buf, "sst_tones: thz %d out of range", thz);
340 rval = (rhz * 128 + 63) / 2000;
341 if ((rval < 1) || (rval > 255)) {
342 sprintf(buf, "sst_tones: rhz %d out of range", dhz2);
348 if ((dval1 != 0 || dval2 != 0) && (tval != 0 || rval != 0)) {
350 "sst_tones: cannot use DTMF and TONE or RINGER at the same time",
356 if (tval != 0 && rval != 0) {
358 "sst_tones: cannot use TONE and RINGER at the same time",
364 ai.control = AUDIO_MAP_MMR2;
365 if (ioctl(fd, AUDIOGETREG, &ai) < 0) {
366 perror("sst_tones: GETREG MMR2");
368 oldmmr2 = newmmr2 = ai.data[0];
370 if (dval1 != 0 || dval2 != 0) {
371 newmmr2 |= AUDIO_MMR2_BITS_DTMF;
372 ai.control = AUDIO_MAP_FTGR;
375 if (ioctl(fd, AUDIOSETREG, &ai) < 0) {
376 perror("sst_tones: SETREG FTGR");
381 newmmr2 |= AUDIO_MMR2_BITS_TONE;
382 ai.control = AUDIO_MAP_FTGR;
385 if (ioctl(fd, AUDIOSETREG, &ai) < 0) {
386 perror("sst_tones: SETREG FTGR");
391 newmmr2 |= AUDIO_MMR2_BITS_RINGER;
392 ai.control = AUDIO_MAP_FTGR;
395 if (ioctl(fd, AUDIOSETREG, &ai) < 0) {
396 perror("sst_tones: SETREG FTGR");
400 ai.control = AUDIO_MAP_MMR2;
401 ai.data[0] = newmmr2;
402 if (ioctl(fd, AUDIOSETREG, &ai) < 0) {
403 perror("sst_tones: SETREG MMR2");
408 ai.data[0] = oldmmr2;
409 if (ioctl(fd, AUDIOSETREG, &ai) < 0) {
410 perror("sst_tones: SETREG MMR2");
414 void sst_dtmf(fd, dial, usecper, usecpause)
415 int fd, usecper, usecpause;
420 for (cp = dial; *cp != '\0'; cp++) {
423 sst_tones(fd, 703, 1211, 0, 0, usecper);
426 sst_tones(fd, 703, 1336, 0, 0, usecper);
429 sst_tones(fd, 703, 1492, 0, 0, usecper);
432 sst_tones(fd, 703, 1648, 0, 0, usecper);
435 sst_tones(fd, 773, 1211, 0, 0, usecper);
438 sst_tones(fd, 773, 1336, 0, 0, usecper);
441 sst_tones(fd, 773, 1492, 0, 0, usecper);
444 sst_tones(fd, 773, 1648, 0, 0, usecper);
447 sst_tones(fd, 859, 1211, 0, 0, usecper);
450 sst_tones(fd, 859, 1336, 0, 0, usecper);
453 sst_tones(fd, 859, 1492, 0, 0, usecper);
456 sst_tones(fd, 859, 1648, 0, 0, usecper);
459 sst_tones(fd, 945, 1211, 0, 0, usecper);
462 sst_tones(fd, 945, 1336, 0, 0, usecper);
465 sst_tones(fd, 945, 1492, 0, 0, usecper);
468 sst_tones(fd, 945, 1648, 0, 0, usecper);
476 continue; /* ignore */
480 break; /* big pause */
486 "sst_dtmf: unknown dialing code '%c'",