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