DF-4710 / eqchurn.c
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 | /* * eqchurn.c — kernel-side churn against the live feeder_eq (guest /dev/dsp, * /dev/mixer) as an unprivileged user. Hammers the FEEDEQ state machine via * every unpriv-reachable input: * - dsp format/channel/rate reconfigs (feeder chain rebuilds incl. EQ) * - mixer SOUND_MIXER_TREBLE/BASS (mixer_set_eq -> FEEDEQ_TREBLE/BASS), * including out-of-range 101..127 values * - sustained write()s with EQ enabled (biquad hot loop in-kernel) * - concurrent threads to shake the sysctl-walk vs feed paths */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <pthread.h> #include <sys/ioctl.h> #include <sys/soundcard.h> static volatile int stop; static int open_dsp(void) { int fd = open("/dev/dsp", O_RDWR | O_NONBLOCK); if (fd < 0) fd = open("/dev/dsp", O_WRONLY | O_NONBLOCK); return (fd); } static void * dsp_thr(void *arg) { short buf[2048]; int fd, iter = 0, i; static const int chns[] = { 1, 2, 4, 6, 8, 3, 5, 7, 2 }; static const int rates[] = { 44100, 48000, 22050, 96000, 8000, 192000, 46050, 46051, 11025 }; static const int fmts[] = { AFMT_S16_LE, AFMT_S32_LE, AFMT_S16_BE, AFMT_U16_LE }; (void)arg; for (i = 0; i < 2048; i++) buf[i] = (short)(i * 2654435761u); while (!stop) { fd = open_dsp(); if (fd < 0) { usleep(10000); continue; } int ch = chns[iter % 9]; int rate = rates[iter % 9]; int fmt = fmts[iter % 4]; ioctl(fd, SNDCTL_DSP_RESET, NULL); int v = fmt; ioctl(fd, SNDCTL_DSP_SETFMT, &v); v = ch; ioctl(fd, SNDCTL_DSP_CHANNELS, &v); v = rate; ioctl(fd, SNDCTL_DSP_SPEED, &v); int trig = 0; ioctl(fd, SNDCTL_DSP_SETTRIGGER, &trig); trig = PCM_ENABLE_OUTPUT; ioctl(fd, SNDCTL_DSP_SETTRIGGER, &trig); for (i = 0; i < 40 && !stop; i++) { ssize_t n = write(fd, buf, sizeof(buf)); (void)n; } /* partial-block writes with odd sizes */ for (i = 0; i < 20 && !stop; i++) { size_t sz = 1 + ((size_t)(iter * 131 + i * 7) % 8192); ssize_t n = write(fd, buf, sz > sizeof(buf) ? sizeof(buf) : sz); (void)n; } close(fd); iter++; } return (NULL); } static void * mix_thr(void *arg) { int fd, iter = 0; static const int levs[] = { 0, 50, 100, 101, 127, 128, 255, 0x7f7f, 0x6565, 0x6464, 0x6b6b, -1 }; (void)arg; while (!stop) { fd = open("/dev/mixer", O_RDWR); if (fd < 0) { usleep(20000); continue; } for (int i = 0; i < 16 && !stop; i++) { int lev = levs[(iter + i) % 12]; ioctl(fd, MIXER_WRITE(SOUND_MIXER_TREBLE), &lev); ioctl(fd, MIXER_WRITE(SOUND_MIXER_BASS), &lev); ioctl(fd, MIXER_WRITE(SOUND_MIXER_PCM), &lev); } close(fd); iter++; } return (NULL); } int main(int argc, char **argv) { int secs = argc > 1 ? atoi(argv[1]) : 20; pthread_t t[4]; for (int i = 0; i < 3; i++) pthread_create(&t[i], NULL, dsp_thr, NULL); pthread_create(&t[3], NULL, mix_thr, NULL); sleep(secs); stop = 1; for (int i = 0; i < 4; i++) pthread_join(t[i], NULL); printf("eqchurn done (%d s), errno last=%d\n", secs, errno); return (0); } |