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