1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * oxfw_proc.c - a part of driver for OXFW970/971 based devices
4  *
5  * Copyright (c) 2014 Takashi Sakamoto
6  */
7 
8 #include "./oxfw.h"
9 
proc_read_formation(struct snd_info_entry * entry,struct snd_info_buffer * buffer)10 static void proc_read_formation(struct snd_info_entry *entry,
11 				struct snd_info_buffer *buffer)
12 {
13 	struct snd_oxfw *oxfw = entry->private_data;
14 	struct snd_oxfw_stream_formation formation, curr;
15 	u8 *format;
16 	char flag;
17 	int i, err;
18 
19 	/* Show input. */
20 	err = snd_oxfw_stream_get_current_formation(oxfw,
21 						    AVC_GENERAL_PLUG_DIR_IN,
22 						    &curr);
23 	if (err < 0)
24 		return;
25 
26 	snd_iprintf(buffer, "Input Stream to device:\n");
27 	snd_iprintf(buffer, "\tRate\tPCM\tMIDI\n");
28 	for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
29 		format = oxfw->rx_stream_formats[i];
30 		if (format == NULL)
31 			continue;
32 
33 		err = snd_oxfw_stream_parse_format(format, &formation);
34 		if (err < 0)
35 			continue;
36 
37 		if (memcmp(&formation, &curr, sizeof(curr)) == 0)
38 			flag = '*';
39 		else
40 			flag = ' ';
41 
42 		snd_iprintf(buffer, "%c\t%d\t%d\t%d\n", flag,
43 			    formation.rate, formation.pcm, formation.midi);
44 	}
45 
46 	if (!oxfw->has_output)
47 		return;
48 
49 	/* Show output. */
50 	err = snd_oxfw_stream_get_current_formation(oxfw,
51 						    AVC_GENERAL_PLUG_DIR_OUT,
52 						    &curr);
53 	if (err < 0)
54 		return;
55 
56 	snd_iprintf(buffer, "Output Stream from device:\n");
57 	snd_iprintf(buffer, "\tRate\tPCM\tMIDI\n");
58 	for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
59 		format = oxfw->tx_stream_formats[i];
60 		if (format == NULL)
61 			continue;
62 
63 		err = snd_oxfw_stream_parse_format(format, &formation);
64 		if (err < 0)
65 			continue;
66 
67 		if (memcmp(&formation, &curr, sizeof(curr)) == 0)
68 			flag = '*';
69 		else
70 			flag = ' ';
71 
72 		snd_iprintf(buffer, "%c\t%d\t%d\t%d\n", flag,
73 			    formation.rate, formation.pcm, formation.midi);
74 	}
75 }
76 
add_node(struct snd_oxfw * oxfw,struct snd_info_entry * root,const char * name,void (* op)(struct snd_info_entry * e,struct snd_info_buffer * b))77 static void add_node(struct snd_oxfw *oxfw, struct snd_info_entry *root,
78 		     const char *name,
79 		     void (*op)(struct snd_info_entry *e,
80 				struct snd_info_buffer *b))
81 {
82 	struct snd_info_entry *entry;
83 
84 	entry = snd_info_create_card_entry(oxfw->card, name, root);
85 	if (entry)
86 		snd_info_set_text_ops(entry, oxfw, op);
87 }
88 
snd_oxfw_proc_init(struct snd_oxfw * oxfw)89 void snd_oxfw_proc_init(struct snd_oxfw *oxfw)
90 {
91 	struct snd_info_entry *root;
92 
93 	/*
94 	 * All nodes are automatically removed at snd_card_disconnect(),
95 	 * by following to link list.
96 	 */
97 	root = snd_info_create_card_entry(oxfw->card, "firewire",
98 					  oxfw->card->proc_root);
99 	if (root == NULL)
100 		return;
101 	root->mode = S_IFDIR | 0555;
102 
103 	add_node(oxfw, root, "formation", proc_read_formation);
104 }
105