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