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
|
/*
* Purpose: A program that prints the S/PDIF receiver status.
* Copyright (C) 4Front Technologies, 2002-2004. Released under GPLv2/CDDL.
*
* Description:
* This program demonstrates use of the {!nlink SNDCTL_DSP_READCTL}
* call. It's actually a low cost digital (S/PDIF) input analyzer.
*
* {!notice This program will work just with a bunch of sound cards because
* most devices are not able to return this information. AT this moment the
* only card that is verified is M Audio Audiophile 2496. It's possible that
* some other M Audio Delta models work too. It's almost certain that
* "ordinary" sound cards will never have a digital receiver chip capable to
* return this information.}
*
* Please read the "{!link spdif_control}" section of the OSS Developer's
* manual for more info.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <time.h>
#include <soundcard.h>
#undef SHOW_DATA
#define SHOW_STATUS
#define RATE 48000
#define CHANNELS 2
#define BUFSZ (CHANNELS*RATE)
#ifdef SHOW_STATUS
static int
xbits (unsigned char b, int first, int last)
{
int v, i;
v = 0;
for (i = first; i <= last; i++)
{
v <<= 1;
if (b & (1 << i))
v |= 1;
}
return v;
}
static void
decode_pro_mode (unsigned char *bits)
{
printf ("Professional mode (PRO=1)\n");
}
static void
decode_consumer_mode (unsigned char *bits)
{
int tmp, tmp2, tmp3;
printf ("Consumer mode (PRO=0)\n");
printf ("Byte 00=%02x: ", bits[0]);
if (bits[0] & 0x02)
printf ("Data (not audio) ");
else
printf ("Audio (not data) ");
if (bits[0] & 0x04)
printf ("Copy permitted ");
else
printf ("Copy inhibited ");
tmp = xbits (bits[0], 3, 5);
if (bits[0] & 0x02)
printf ("Non-audio=0x%x ", tmp);
else
printf ("Pre-emph=0x%x ", tmp);
tmp = xbits (bits[0], 6, 7);
printf ("Mode=0x%x ", tmp);
printf ("\n");
printf ("Byte 01=%02x: ", bits[1]);
tmp = xbits (bits[1], 0, 2);
tmp2 = xbits (bits[1], 3, 6);
tmp3 = xbits (bits[1], 7, 7);
printf ("Category code = %x:%x, L=%d ", tmp, tmp2, tmp3);
printf ("\n");
printf ("Byte 02=%02x: ", bits[2]);
tmp = xbits (bits[2], 0, 3);
tmp2 = xbits (bits[2], 4, 7);
printf ("Source number=0x%x Channel number=0x%x ", tmp, tmp2);
printf ("\n");
printf ("Byte 03=%02x: ", bits[3]);
tmp = xbits (bits[3], 0, 3);
tmp2 = xbits (bits[3], 4, 5);
printf ("Sample rate=0x%x Clock accuracy=0x%x ", tmp, tmp2);
printf ("\n");
}
#endif
int
main (int argc, char *argv[])
{
char *devname = "/dev/dsp";
unsigned short buf[BUFSZ], expected = 0;
int fd, parm, l, i;
int bcount = 0;
if (argc > 1)
devname = argv[1];
if ((fd = open (devname, O_RDONLY, 0)) == -1)
{
perror (devname);
exit (-1);
}
parm = AFMT_S16_NE;
if (ioctl (fd, SNDCTL_DSP_SETFMT, &parm) == -1)
{
perror ("SETFMT");
close (fd);
exit (-1);
}
if (parm != AFMT_S16_NE)
{
printf
("Error: 16 bit sample format is not supported by the device\n");
printf ("%08x/%08x\n", parm, AFMT_S16_LE);
close (fd);
exit (-1);
}
parm = CHANNELS;
if (ioctl (fd, SNDCTL_DSP_CHANNELS, &parm) == -1)
{
perror ("CHANNELS");
close (fd);
exit (-1);
}
parm = RATE;
if (ioctl (fd, SNDCTL_DSP_SPEED, &parm) == -1)
{
perror ("SPEED");
close (fd);
exit (-1);
}
if (parm != RATE)
{
printf
("Warning: %d Hz sampling rate is not supported by the device. Will use %d)\n",
RATE, parm);
}
#ifdef SHOW_DATA
while ((l = read (fd, buf, sizeof (buf))) > 0)
#else
while (1)
#endif
{
#ifdef SHOW_STATUS
time_t t;
oss_digital_control c;
c.valid = VAL_CBITIN | VAL_ISTATUS;
if (ioctl (fd, SNDCTL_DSP_READCTL, &c) == -1)
{
perror ("SNDCTL_DSP_READCTL");
exit (-1);
}
time (&t);
printf ("\n%s\n", ctime (&t));
if (c.valid & VAL_ISTATUS)
{
switch (c.in_locked)
{
case LOCK_NOT_INDICATED:
printf ("Receiver locked: Status unknown\n");
break;
case LOCK_UNLOCKED:
printf ("receiver locked: *** NOT LOCKED ***\n");
break;
case LOCK_LOCKED:
printf ("receiver locked: Locked OK\n");
break;
}
switch (c.in_quality)
{
case IN_QUAL_NOT_INDICATED:
printf ("Signal quality: Unknown\n");
break;
case IN_QUAL_POOR:
printf ("Signal quality: *** POOR ***\n");
break;
case IN_QUAL_GOOD:
printf ("Signal quality: Good\n");
break;
}
switch (c.in_vbit)
{
case VBIT_NOT_INDICATED:
printf ("V-bit: Unknown\n");
break;
case VBIT_ON:
printf ("V-bit: On (not valid audio)\n");
break;
case VBIT_OFF:
printf ("V-bit: Off (valid audio signal)\n");
break;
}
switch (c.in_data)
{
case IND_UNKNOWN:
printf ("Audio/data: Unknown\n");
break;
case IND_AUDIO:
printf ("Audio/data: Audio\n");
break;
case IND_DATA:
printf ("Audio/data: Data\n");
break;
}
printf ("Errors: ");
if (c.in_errors & INERR_CRC)
printf ("CRC ");
if (c.in_errors & INERR_QCODE_CRC)
printf ("QCODE_CRC ");
if (c.in_errors & INERR_PARITY)
printf ("PARITY ");
if (c.in_errors & INERR_BIPHASE)
printf ("BIPHASE ");
printf ("\n");
}
else
printf ("No input status information available\n");
if (c.valid & VAL_CBITIN && c.in_locked != LOCK_UNLOCKED)
{
printf ("\n");
printf ("Control bits: ");
for (i = 0; i < 24; i++)
printf ("%02x ", c.cbitin[i]);
printf ("\n");
if (c.cbitin[0] & 0x01)
decode_pro_mode (c.cbitin);
else
decode_consumer_mode (c.cbitin);
}
else
printf ("No incoming control bit information available\n");
#endif
#ifdef SHOW_DATA
# ifdef SHOW_STATUS
if (c.in_locked != LOCK_UNLOCKED)
# endif
{
for (i = 0; i < l / 2; i++)
{
if (buf[i] == expected)
{
printf ("%04x\n", buf[i]);
}
else
{
printf ("Error %04x != %04x (%4x), c=%d/%x\n", buf[i],
expected, buf[i] ^ expected, bcount, bcount);
}
expected = buf[i] + 1;
bcount++;
}
}
#else
sleep (1);
#endif
}
perror (devname);
exit (-1);
}
|