1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Virtual ALSA driver for PCM testing/fuzzing 4 * 5 * Copyright 2023 Ivan Orlov <ivan.orlov0322@gmail.com> 6 * 7 * This is a simple virtual ALSA driver, which can be used for audio applications/PCM middle layer 8 * testing or fuzzing. 9 * It can: 10 * - Simulate 'playback' and 'capture' actions 11 * - Generate random or pattern-based capture data 12 * - Check playback buffer for containing looped template, and notify about the results 13 * through the debugfs entry 14 * - Inject delays into the playback and capturing processes. See 'inject_delay' parameter. 15 * - Inject errors during the PCM callbacks. 16 * - Register custom RESET ioctl and notify when it is called through the debugfs entry 17 * - Work in interleaved and non-interleaved modes 18 * - Support up to 8 substreams 19 * - Support up to 4 channels 20 * - Support framerates from 8 kHz to 48 kHz 21 * 22 * When driver works in the capture mode with multiple channels, it duplicates the looped 23 * pattern to each separate channel. For example, if we have 2 channels, format = U8, interleaved 24 * access mode and pattern 'abacaba', the DMA buffer will look like aabbccaabbaaaa..., so buffer for 25 * each channel will contain abacabaabacaba... Same for the non-interleaved mode. 26 * 27 * However, it may break the capturing on the higher framerates with small period size, so it is 28 * better to choose larger period sizes. 29 * 30 * You can find the corresponding selftest in the 'alsa' selftests folder. 31 */ 32 33 #include <linux/module.h> 34 #include <linux/init.h> 35 #include <sound/pcm.h> 36 #include <sound/core.h> 37 #include <linux/dma-mapping.h> 38 #include <linux/platform_device.h> 39 #include <linux/string.h> 40 #include <linux/timer.h> 41 #include <linux/random.h> 42 #include <linux/debugfs.h> 43 #include <linux/delay.h> 44 45 #define TIMER_PER_SEC 5 46 #define TIMER_INTERVAL (HZ / TIMER_PER_SEC) 47 #define DELAY_JIFFIES HZ 48 #define PLAYBACK_SUBSTREAM_CNT 8 49 #define CAPTURE_SUBSTREAM_CNT 8 50 #define MAX_CHANNELS_NUM 4 51 52 #define DEFAULT_PATTERN "abacaba" 53 #define DEFAULT_PATTERN_LEN 7 54 55 #define FILL_MODE_RAND 0 56 #define FILL_MODE_PAT 1 57 58 #define MAX_PATTERN_LEN 4096 59 60 static int index = -1; 61 static char *id = "pcmtest"; 62 static bool enable = true; 63 static int inject_delay; 64 static bool inject_hwpars_err; 65 static bool inject_prepare_err; 66 static bool inject_trigger_err; 67 static bool inject_open_err; 68 69 static short fill_mode = FILL_MODE_PAT; 70 71 static u8 playback_capture_test; 72 static u8 ioctl_reset_test; 73 static struct dentry *driver_debug_dir; 74 75 module_param(index, int, 0444); 76 MODULE_PARM_DESC(index, "Index value for pcmtest soundcard"); 77 module_param(id, charp, 0444); 78 MODULE_PARM_DESC(id, "ID string for pcmtest soundcard"); 79 module_param(enable, bool, 0444); 80 MODULE_PARM_DESC(enable, "Enable pcmtest soundcard."); 81 module_param(fill_mode, short, 0600); 82 MODULE_PARM_DESC(fill_mode, "Buffer fill mode: rand(0) or pattern(1)"); 83 module_param(inject_delay, int, 0600); 84 MODULE_PARM_DESC(inject_delay, "Inject delays during playback/capture (in jiffies)"); 85 module_param(inject_hwpars_err, bool, 0600); 86 MODULE_PARM_DESC(inject_hwpars_err, "Inject EBUSY error in the 'hw_params' callback"); 87 module_param(inject_prepare_err, bool, 0600); 88 MODULE_PARM_DESC(inject_prepare_err, "Inject EINVAL error in the 'prepare' callback"); 89 module_param(inject_trigger_err, bool, 0600); 90 MODULE_PARM_DESC(inject_trigger_err, "Inject EINVAL error in the 'trigger' callback"); 91 module_param(inject_open_err, bool, 0600); 92 MODULE_PARM_DESC(inject_open_err, "Inject EBUSY error in the 'open' callback"); 93 94 struct pcmtst { 95 struct snd_pcm *pcm; 96 struct snd_card *card; 97 struct platform_device *pdev; 98 }; 99 100 struct pcmtst_buf_iter { 101 size_t buf_pos; // position in the DMA buffer 102 size_t period_pos; // period-relative position 103 size_t b_rw; // Bytes to write on every timer tick 104 size_t s_rw_ch; // Samples to write to one channel on every tick 105 unsigned int sample_bytes; // sample_bits / 8 106 bool is_buf_corrupted; // playback test result indicator 107 size_t period_bytes; // bytes in a one period 108 bool interleaved; // Interleaved/Non-interleaved mode 109 size_t total_bytes; // Total bytes read/written 110 size_t chan_block; // Bytes in one channel buffer when non-interleaved 111 struct snd_pcm_substream *substream; 112 bool suspend; // We need to pause timer without shutting it down 113 struct timer_list timer_instance; 114 }; 115 116 static struct snd_pcm_hardware snd_pcmtst_hw = { 117 .info = (SNDRV_PCM_INFO_INTERLEAVED | 118 SNDRV_PCM_INFO_BLOCK_TRANSFER | 119 SNDRV_PCM_INFO_NONINTERLEAVED | 120 SNDRV_PCM_INFO_MMAP_VALID | 121 SNDRV_PCM_INFO_PAUSE), 122 .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, 123 .rates = SNDRV_PCM_RATE_8000_48000, 124 .rate_min = 8000, 125 .rate_max = 48000, 126 .channels_min = 1, 127 .channels_max = MAX_CHANNELS_NUM, 128 .buffer_bytes_max = 128 * 1024, 129 .period_bytes_min = 4096, 130 .period_bytes_max = 32768, 131 .periods_min = 1, 132 .periods_max = 1024, 133 }; 134 135 struct pattern_buf { 136 char *buf; 137 u32 len; 138 }; 139 140 static int buf_allocated; 141 static struct pattern_buf patt_bufs[MAX_CHANNELS_NUM]; 142 143 static inline void inc_buf_pos(struct pcmtst_buf_iter *v_iter, size_t by, size_t bytes) 144 { 145 v_iter->total_bytes += by; 146 v_iter->buf_pos += by; 147 if (v_iter->buf_pos >= bytes) 148 v_iter->buf_pos %= bytes; 149 } 150 151 /* 152 * Position in the DMA buffer when we are in the non-interleaved mode. We increment buf_pos 153 * every time we write a byte to any channel, so the position in the current channel buffer is 154 * (position in the DMA buffer) / count_of_channels + size_of_channel_buf * current_channel 155 */ 156 static inline size_t buf_pos_n(struct pcmtst_buf_iter *v_iter, unsigned int channels, 157 unsigned int chan_num) 158 { 159 return v_iter->buf_pos / channels + v_iter->chan_block * chan_num; 160 } 161 162 /* 163 * Get the count of bytes written for the current channel in the interleaved mode. 164 * This is (count of samples written for the current channel) * bytes_in_sample + 165 * (relative position in the current sample) 166 */ 167 static inline size_t ch_pos_i(size_t b_total, unsigned int channels, unsigned int b_sample) 168 { 169 return b_total / channels / b_sample * b_sample + (b_total % b_sample); 170 } 171 172 static void check_buf_block_i(struct pcmtst_buf_iter *v_iter, struct snd_pcm_runtime *runtime) 173 { 174 size_t i; 175 short ch_num; 176 u8 current_byte; 177 178 for (i = 0; i < v_iter->b_rw; i++) { 179 current_byte = runtime->dma_area[v_iter->buf_pos]; 180 if (!current_byte) 181 break; 182 ch_num = (v_iter->total_bytes / v_iter->sample_bytes) % runtime->channels; 183 if (current_byte != patt_bufs[ch_num].buf[ch_pos_i(v_iter->total_bytes, 184 runtime->channels, 185 v_iter->sample_bytes) 186 % patt_bufs[ch_num].len]) { 187 v_iter->is_buf_corrupted = true; 188 break; 189 } 190 inc_buf_pos(v_iter, 1, runtime->dma_bytes); 191 } 192 // If we broke during the loop, add remaining bytes to the buffer position. 193 inc_buf_pos(v_iter, v_iter->b_rw - i, runtime->dma_bytes); 194 } 195 196 static void check_buf_block_ni(struct pcmtst_buf_iter *v_iter, struct snd_pcm_runtime *runtime) 197 { 198 unsigned int channels = runtime->channels; 199 size_t i; 200 short ch_num; 201 u8 current_byte; 202 203 for (i = 0; i < v_iter->b_rw; i++) { 204 ch_num = i % channels; 205 current_byte = runtime->dma_area[buf_pos_n(v_iter, channels, ch_num)]; 206 if (!current_byte) 207 break; 208 if (current_byte != patt_bufs[ch_num].buf[(v_iter->total_bytes / channels) 209 % patt_bufs[ch_num].len]) { 210 v_iter->is_buf_corrupted = true; 211 break; 212 } 213 inc_buf_pos(v_iter, 1, runtime->dma_bytes); 214 } 215 inc_buf_pos(v_iter, v_iter->b_rw - i, runtime->dma_bytes); 216 } 217 218 /* 219 * Check one block of the buffer. Here we iterate the buffer until we find '0'. This condition is 220 * necessary because we need to detect when the reading/writing ends, so we assume that the pattern 221 * doesn't contain zeros. 222 */ 223 static void check_buf_block(struct pcmtst_buf_iter *v_iter, struct snd_pcm_runtime *runtime) 224 { 225 if (v_iter->interleaved) 226 check_buf_block_i(v_iter, runtime); 227 else 228 check_buf_block_ni(v_iter, runtime); 229 } 230 231 /* 232 * Fill buffer in the non-interleaved mode. The order of samples is C0, ..., C0, C1, ..., C1, C2... 233 * The channel buffers lay in the DMA buffer continuously (see default copy 234 * handlers in the pcm_lib.c file). 235 * 236 * Here we increment the DMA buffer position every time we write a byte to any channel 'buffer'. 237 * We need this to simulate the correct hardware pointer moving. 238 */ 239 static void fill_block_pattern_n(struct pcmtst_buf_iter *v_iter, struct snd_pcm_runtime *runtime) 240 { 241 size_t i; 242 unsigned int channels = runtime->channels; 243 short ch_num; 244 245 for (i = 0; i < v_iter->b_rw; i++) { 246 ch_num = i % channels; 247 runtime->dma_area[buf_pos_n(v_iter, channels, ch_num)] = 248 patt_bufs[ch_num].buf[(v_iter->total_bytes / channels) 249 % patt_bufs[ch_num].len]; 250 inc_buf_pos(v_iter, 1, runtime->dma_bytes); 251 } 252 } 253 254 // Fill buffer in the interleaved mode. The order of samples is C0, C1, C2, C0, C1, C2, ... 255 static void fill_block_pattern_i(struct pcmtst_buf_iter *v_iter, struct snd_pcm_runtime *runtime) 256 { 257 size_t sample; 258 size_t pos_in_ch, pos_pattern; 259 short ch, pos_sample; 260 261 pos_in_ch = ch_pos_i(v_iter->total_bytes, runtime->channels, v_iter->sample_bytes); 262 263 for (sample = 0; sample < v_iter->s_rw_ch; sample++) { 264 for (ch = 0; ch < runtime->channels; ch++) { 265 for (pos_sample = 0; pos_sample < v_iter->sample_bytes; pos_sample++) { 266 pos_pattern = (pos_in_ch + sample * v_iter->sample_bytes 267 + pos_sample) % patt_bufs[ch].len; 268 runtime->dma_area[v_iter->buf_pos] = patt_bufs[ch].buf[pos_pattern]; 269 inc_buf_pos(v_iter, 1, runtime->dma_bytes); 270 } 271 } 272 } 273 } 274 275 static void fill_block_pattern(struct pcmtst_buf_iter *v_iter, struct snd_pcm_runtime *runtime) 276 { 277 if (v_iter->interleaved) 278 fill_block_pattern_i(v_iter, runtime); 279 else 280 fill_block_pattern_n(v_iter, runtime); 281 } 282 283 static void fill_block_rand_n(struct pcmtst_buf_iter *v_iter, struct snd_pcm_runtime *runtime) 284 { 285 unsigned int channels = runtime->channels; 286 // Remaining space in all channel buffers 287 size_t bytes_remain = runtime->dma_bytes - v_iter->buf_pos; 288 unsigned int i; 289 290 for (i = 0; i < channels; i++) { 291 if (v_iter->b_rw <= bytes_remain) { 292 //b_rw - count of bytes must be written for all channels at each timer tick 293 get_random_bytes(runtime->dma_area + buf_pos_n(v_iter, channels, i), 294 v_iter->b_rw / channels); 295 } else { 296 // Write to the end of buffer and start from the beginning of it 297 get_random_bytes(runtime->dma_area + buf_pos_n(v_iter, channels, i), 298 bytes_remain / channels); 299 get_random_bytes(runtime->dma_area + v_iter->chan_block * i, 300 (v_iter->b_rw - bytes_remain) / channels); 301 } 302 } 303 inc_buf_pos(v_iter, v_iter->b_rw, runtime->dma_bytes); 304 } 305 306 static void fill_block_rand_i(struct pcmtst_buf_iter *v_iter, struct snd_pcm_runtime *runtime) 307 { 308 size_t in_cur_block = runtime->dma_bytes - v_iter->buf_pos; 309 310 if (v_iter->b_rw <= in_cur_block) { 311 get_random_bytes(&runtime->dma_area[v_iter->buf_pos], v_iter->b_rw); 312 } else { 313 get_random_bytes(&runtime->dma_area[v_iter->buf_pos], in_cur_block); 314 get_random_bytes(runtime->dma_area, v_iter->b_rw - in_cur_block); 315 } 316 inc_buf_pos(v_iter, v_iter->b_rw, runtime->dma_bytes); 317 } 318 319 static void fill_block_random(struct pcmtst_buf_iter *v_iter, struct snd_pcm_runtime *runtime) 320 { 321 if (v_iter->interleaved) 322 fill_block_rand_i(v_iter, runtime); 323 else 324 fill_block_rand_n(v_iter, runtime); 325 } 326 327 static void fill_block(struct pcmtst_buf_iter *v_iter, struct snd_pcm_runtime *runtime) 328 { 329 switch (fill_mode) { 330 case FILL_MODE_RAND: 331 fill_block_random(v_iter, runtime); 332 break; 333 case FILL_MODE_PAT: 334 fill_block_pattern(v_iter, runtime); 335 break; 336 } 337 } 338 339 /* 340 * Here we iterate through the buffer by (buffer_size / iterates_per_second) bytes. 341 * The driver uses timer to simulate the hardware pointer moving, and notify the PCM middle layer 342 * about period elapsed. 343 */ 344 static void timer_timeout(struct timer_list *data) 345 { 346 struct pcmtst_buf_iter *v_iter; 347 struct snd_pcm_substream *substream; 348 349 v_iter = timer_container_of(v_iter, data, timer_instance); 350 substream = v_iter->substream; 351 352 if (v_iter->suspend) 353 return; 354 355 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !v_iter->is_buf_corrupted) 356 check_buf_block(v_iter, substream->runtime); 357 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 358 fill_block(v_iter, substream->runtime); 359 else 360 inc_buf_pos(v_iter, v_iter->b_rw, substream->runtime->dma_bytes); 361 362 v_iter->period_pos += v_iter->b_rw; 363 if (v_iter->period_pos >= v_iter->period_bytes) { 364 v_iter->period_pos %= v_iter->period_bytes; 365 snd_pcm_period_elapsed(substream); 366 } 367 368 if (!v_iter->suspend) 369 mod_timer(&v_iter->timer_instance, jiffies + TIMER_INTERVAL + inject_delay); 370 } 371 372 static int snd_pcmtst_pcm_open(struct snd_pcm_substream *substream) 373 { 374 struct snd_pcm_runtime *runtime = substream->runtime; 375 struct pcmtst_buf_iter *v_iter; 376 377 if (inject_open_err) 378 return -EBUSY; 379 380 v_iter = kzalloc(sizeof(*v_iter), GFP_KERNEL); 381 if (!v_iter) 382 return -ENOMEM; 383 384 v_iter->substream = substream; 385 runtime->hw = snd_pcmtst_hw; 386 runtime->private_data = v_iter; 387 388 playback_capture_test = 0; 389 ioctl_reset_test = 0; 390 391 timer_setup(&v_iter->timer_instance, timer_timeout, 0); 392 393 return 0; 394 } 395 396 static int snd_pcmtst_pcm_close(struct snd_pcm_substream *substream) 397 { 398 struct pcmtst_buf_iter *v_iter = substream->runtime->private_data; 399 400 timer_shutdown_sync(&v_iter->timer_instance); 401 playback_capture_test = !v_iter->is_buf_corrupted; 402 kfree(v_iter); 403 return 0; 404 } 405 406 static inline void reset_buf_iterator(struct pcmtst_buf_iter *v_iter) 407 { 408 v_iter->buf_pos = 0; 409 v_iter->is_buf_corrupted = false; 410 v_iter->period_pos = 0; 411 v_iter->total_bytes = 0; 412 } 413 414 static inline void start_pcmtest_timer(struct pcmtst_buf_iter *v_iter) 415 { 416 v_iter->suspend = false; 417 mod_timer(&v_iter->timer_instance, jiffies + TIMER_INTERVAL); 418 } 419 420 static int snd_pcmtst_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 421 { 422 struct pcmtst_buf_iter *v_iter = substream->runtime->private_data; 423 424 if (inject_trigger_err) 425 return -EINVAL; 426 switch (cmd) { 427 case SNDRV_PCM_TRIGGER_START: 428 reset_buf_iterator(v_iter); 429 start_pcmtest_timer(v_iter); 430 break; 431 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 432 start_pcmtest_timer(v_iter); 433 break; 434 case SNDRV_PCM_TRIGGER_STOP: 435 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 436 // We can't call timer_shutdown_sync here, as it is forbidden to sleep here 437 v_iter->suspend = true; 438 timer_delete(&v_iter->timer_instance); 439 break; 440 } 441 442 return 0; 443 } 444 445 static snd_pcm_uframes_t snd_pcmtst_pcm_pointer(struct snd_pcm_substream *substream) 446 { 447 struct pcmtst_buf_iter *v_iter = substream->runtime->private_data; 448 449 return bytes_to_frames(substream->runtime, v_iter->buf_pos); 450 } 451 452 static int snd_pcmtst_free(struct pcmtst *pcmtst) 453 { 454 if (!pcmtst) 455 return 0; 456 kfree(pcmtst); 457 return 0; 458 } 459 460 // These callbacks are required, but empty - all freeing occurs in pdev_remove 461 static int snd_pcmtst_dev_free(struct snd_device *device) 462 { 463 return 0; 464 } 465 466 static void pcmtst_pdev_release(struct device *dev) 467 { 468 } 469 470 static int snd_pcmtst_pcm_prepare(struct snd_pcm_substream *substream) 471 { 472 struct snd_pcm_runtime *runtime = substream->runtime; 473 struct pcmtst_buf_iter *v_iter = runtime->private_data; 474 475 if (inject_prepare_err) 476 return -EINVAL; 477 478 v_iter->sample_bytes = samples_to_bytes(runtime, 1); 479 v_iter->period_bytes = snd_pcm_lib_period_bytes(substream); 480 v_iter->interleaved = true; 481 if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED || 482 runtime->access == SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED) { 483 v_iter->chan_block = snd_pcm_lib_buffer_bytes(substream) / runtime->channels; 484 v_iter->interleaved = false; 485 } 486 // We want to record RATE * ch_cnt samples per sec, it is rate * sample_bytes * ch_cnt bytes 487 v_iter->s_rw_ch = runtime->rate / TIMER_PER_SEC; 488 v_iter->b_rw = v_iter->s_rw_ch * v_iter->sample_bytes * runtime->channels; 489 490 return 0; 491 } 492 493 static int snd_pcmtst_pcm_hw_params(struct snd_pcm_substream *substream, 494 struct snd_pcm_hw_params *params) 495 { 496 if (inject_hwpars_err) 497 return -EBUSY; 498 return 0; 499 } 500 501 static int snd_pcmtst_pcm_hw_free(struct snd_pcm_substream *substream) 502 { 503 return 0; 504 } 505 506 static int snd_pcmtst_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg) 507 { 508 switch (cmd) { 509 case SNDRV_PCM_IOCTL1_RESET: 510 ioctl_reset_test = 1; 511 break; 512 } 513 return snd_pcm_lib_ioctl(substream, cmd, arg); 514 } 515 516 static int snd_pcmtst_sync_stop(struct snd_pcm_substream *substream) 517 { 518 struct pcmtst_buf_iter *v_iter = substream->runtime->private_data; 519 520 timer_delete_sync(&v_iter->timer_instance); 521 522 return 0; 523 } 524 525 static const struct snd_pcm_ops snd_pcmtst_playback_ops = { 526 .open = snd_pcmtst_pcm_open, 527 .close = snd_pcmtst_pcm_close, 528 .trigger = snd_pcmtst_pcm_trigger, 529 .hw_params = snd_pcmtst_pcm_hw_params, 530 .ioctl = snd_pcmtst_ioctl, 531 .sync_stop = snd_pcmtst_sync_stop, 532 .hw_free = snd_pcmtst_pcm_hw_free, 533 .prepare = snd_pcmtst_pcm_prepare, 534 .pointer = snd_pcmtst_pcm_pointer, 535 }; 536 537 static const struct snd_pcm_ops snd_pcmtst_capture_ops = { 538 .open = snd_pcmtst_pcm_open, 539 .close = snd_pcmtst_pcm_close, 540 .trigger = snd_pcmtst_pcm_trigger, 541 .hw_params = snd_pcmtst_pcm_hw_params, 542 .hw_free = snd_pcmtst_pcm_hw_free, 543 .ioctl = snd_pcmtst_ioctl, 544 .sync_stop = snd_pcmtst_sync_stop, 545 .prepare = snd_pcmtst_pcm_prepare, 546 .pointer = snd_pcmtst_pcm_pointer, 547 }; 548 549 static int snd_pcmtst_new_pcm(struct pcmtst *pcmtst) 550 { 551 struct snd_pcm *pcm; 552 int err; 553 554 err = snd_pcm_new(pcmtst->card, "PCMTest", 0, PLAYBACK_SUBSTREAM_CNT, 555 CAPTURE_SUBSTREAM_CNT, &pcm); 556 if (err < 0) 557 return err; 558 pcm->private_data = pcmtst; 559 strscpy(pcm->name, "PCMTest"); 560 pcmtst->pcm = pcm; 561 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_pcmtst_playback_ops); 562 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_pcmtst_capture_ops); 563 564 err = snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &pcmtst->pdev->dev, 565 0, 128 * 1024); 566 return err; 567 } 568 569 static int snd_pcmtst_create(struct snd_card *card, struct platform_device *pdev, 570 struct pcmtst **r_pcmtst) 571 { 572 struct pcmtst *pcmtst; 573 int err; 574 static const struct snd_device_ops ops = { 575 .dev_free = snd_pcmtst_dev_free, 576 }; 577 578 pcmtst = kzalloc(sizeof(*pcmtst), GFP_KERNEL); 579 if (!pcmtst) 580 return -ENOMEM; 581 pcmtst->card = card; 582 pcmtst->pdev = pdev; 583 584 err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, pcmtst, &ops); 585 if (err < 0) 586 goto _err_free_chip; 587 588 err = snd_pcmtst_new_pcm(pcmtst); 589 if (err < 0) 590 goto _err_free_chip; 591 592 *r_pcmtst = pcmtst; 593 return 0; 594 595 _err_free_chip: 596 snd_pcmtst_free(pcmtst); 597 return err; 598 } 599 600 static int pcmtst_probe(struct platform_device *pdev) 601 { 602 struct snd_card *card; 603 struct pcmtst *pcmtst; 604 int err; 605 606 err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 607 if (err) 608 return err; 609 610 err = snd_devm_card_new(&pdev->dev, index, id, THIS_MODULE, 0, &card); 611 if (err < 0) 612 return err; 613 err = snd_pcmtst_create(card, pdev, &pcmtst); 614 if (err < 0) 615 return err; 616 617 strscpy(card->driver, "PCM-TEST Driver"); 618 strscpy(card->shortname, "PCM-Test"); 619 strscpy(card->longname, "PCM-Test virtual driver"); 620 621 err = snd_card_register(card); 622 if (err < 0) 623 return err; 624 625 platform_set_drvdata(pdev, pcmtst); 626 627 return 0; 628 } 629 630 static void pdev_remove(struct platform_device *pdev) 631 { 632 struct pcmtst *pcmtst = platform_get_drvdata(pdev); 633 634 snd_pcmtst_free(pcmtst); 635 } 636 637 static struct platform_device pcmtst_pdev = { 638 .name = "pcmtest", 639 .dev.release = pcmtst_pdev_release, 640 }; 641 642 static struct platform_driver pcmtst_pdrv = { 643 .probe = pcmtst_probe, 644 .remove = pdev_remove, 645 .driver = { 646 .name = "pcmtest", 647 }, 648 }; 649 650 static ssize_t pattern_write(struct file *file, const char __user *u_buff, size_t len, loff_t *off) 651 { 652 struct pattern_buf *patt_buf = file->f_inode->i_private; 653 ssize_t to_write = len; 654 655 if (*off + to_write > MAX_PATTERN_LEN) 656 to_write = MAX_PATTERN_LEN - *off; 657 658 // Crop silently everything over the buffer 659 if (to_write <= 0) 660 return len; 661 662 if (copy_from_user(patt_buf->buf + *off, u_buff, to_write)) 663 return -EFAULT; 664 665 patt_buf->len = *off + to_write; 666 *off += to_write; 667 668 return to_write; 669 } 670 671 static ssize_t pattern_read(struct file *file, char __user *u_buff, size_t len, loff_t *off) 672 { 673 struct pattern_buf *patt_buf = file->f_inode->i_private; 674 ssize_t to_read = len; 675 676 if (*off + to_read >= MAX_PATTERN_LEN) 677 to_read = MAX_PATTERN_LEN - *off; 678 if (to_read <= 0) 679 return 0; 680 681 if (copy_to_user(u_buff, patt_buf->buf + *off, to_read)) 682 to_read = 0; 683 else 684 *off += to_read; 685 686 return to_read; 687 } 688 689 static const struct file_operations fill_pattern_fops = { 690 .read = pattern_read, 691 .write = pattern_write, 692 }; 693 694 static int setup_patt_bufs(void) 695 { 696 size_t i; 697 698 for (i = 0; i < ARRAY_SIZE(patt_bufs); i++) { 699 patt_bufs[i].buf = kzalloc(MAX_PATTERN_LEN, GFP_KERNEL); 700 if (!patt_bufs[i].buf) 701 break; 702 strcpy(patt_bufs[i].buf, DEFAULT_PATTERN); 703 patt_bufs[i].len = DEFAULT_PATTERN_LEN; 704 } 705 706 return i; 707 } 708 709 static const char * const pattern_files[] = { "fill_pattern0", "fill_pattern1", 710 "fill_pattern2", "fill_pattern3"}; 711 static int init_debug_files(int buf_count) 712 { 713 size_t i; 714 char len_file_name[32]; 715 716 driver_debug_dir = debugfs_create_dir("pcmtest", NULL); 717 if (IS_ERR(driver_debug_dir)) 718 return PTR_ERR(driver_debug_dir); 719 debugfs_create_u8("pc_test", 0444, driver_debug_dir, &playback_capture_test); 720 debugfs_create_u8("ioctl_test", 0444, driver_debug_dir, &ioctl_reset_test); 721 722 for (i = 0; i < buf_count; i++) { 723 debugfs_create_file(pattern_files[i], 0600, driver_debug_dir, 724 &patt_bufs[i], &fill_pattern_fops); 725 snprintf(len_file_name, sizeof(len_file_name), "%s_len", pattern_files[i]); 726 debugfs_create_u32(len_file_name, 0444, driver_debug_dir, &patt_bufs[i].len); 727 } 728 729 return 0; 730 } 731 732 static void free_pattern_buffers(void) 733 { 734 int i; 735 736 for (i = 0; i < buf_allocated; i++) 737 kfree(patt_bufs[i].buf); 738 } 739 740 static void clear_debug_files(void) 741 { 742 debugfs_remove_recursive(driver_debug_dir); 743 } 744 745 static int __init mod_init(void) 746 { 747 int err = 0; 748 749 buf_allocated = setup_patt_bufs(); 750 if (!buf_allocated) 751 return -ENOMEM; 752 753 snd_pcmtst_hw.channels_max = buf_allocated; 754 755 err = init_debug_files(buf_allocated); 756 if (err) 757 return err; 758 err = platform_device_register(&pcmtst_pdev); 759 if (err) 760 return err; 761 err = platform_driver_register(&pcmtst_pdrv); 762 if (err) 763 platform_device_unregister(&pcmtst_pdev); 764 return err; 765 } 766 767 static void __exit mod_exit(void) 768 { 769 clear_debug_files(); 770 free_pattern_buffers(); 771 772 platform_driver_unregister(&pcmtst_pdrv); 773 platform_device_unregister(&pcmtst_pdev); 774 } 775 776 MODULE_DESCRIPTION("Virtual ALSA driver for PCM testing/fuzzing"); 777 MODULE_LICENSE("GPL"); 778 MODULE_AUTHOR("Ivan Orlov"); 779 module_init(mod_init); 780 module_exit(mod_exit); 781