18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * oxfw_proc.c - a part of driver for OXFW970/971 based devices
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2014 Takashi Sakamoto
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include "./oxfw.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_cistatic void proc_read_formation(struct snd_info_entry *entry,
118c2ecf20Sopenharmony_ci				struct snd_info_buffer *buffer)
128c2ecf20Sopenharmony_ci{
138c2ecf20Sopenharmony_ci	struct snd_oxfw *oxfw = entry->private_data;
148c2ecf20Sopenharmony_ci	struct snd_oxfw_stream_formation formation, curr;
158c2ecf20Sopenharmony_ci	u8 *format;
168c2ecf20Sopenharmony_ci	char flag;
178c2ecf20Sopenharmony_ci	int i, err;
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci	/* Show input. */
208c2ecf20Sopenharmony_ci	err = snd_oxfw_stream_get_current_formation(oxfw,
218c2ecf20Sopenharmony_ci						    AVC_GENERAL_PLUG_DIR_IN,
228c2ecf20Sopenharmony_ci						    &curr);
238c2ecf20Sopenharmony_ci	if (err < 0)
248c2ecf20Sopenharmony_ci		return;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	snd_iprintf(buffer, "Input Stream to device:\n");
278c2ecf20Sopenharmony_ci	snd_iprintf(buffer, "\tRate\tPCM\tMIDI\n");
288c2ecf20Sopenharmony_ci	for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
298c2ecf20Sopenharmony_ci		format = oxfw->rx_stream_formats[i];
308c2ecf20Sopenharmony_ci		if (format == NULL)
318c2ecf20Sopenharmony_ci			continue;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci		err = snd_oxfw_stream_parse_format(format, &formation);
348c2ecf20Sopenharmony_ci		if (err < 0)
358c2ecf20Sopenharmony_ci			continue;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci		if (memcmp(&formation, &curr, sizeof(curr)) == 0)
388c2ecf20Sopenharmony_ci			flag = '*';
398c2ecf20Sopenharmony_ci		else
408c2ecf20Sopenharmony_ci			flag = ' ';
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci		snd_iprintf(buffer, "%c\t%d\t%d\t%d\n", flag,
438c2ecf20Sopenharmony_ci			    formation.rate, formation.pcm, formation.midi);
448c2ecf20Sopenharmony_ci	}
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	if (!oxfw->has_output)
478c2ecf20Sopenharmony_ci		return;
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	/* Show output. */
508c2ecf20Sopenharmony_ci	err = snd_oxfw_stream_get_current_formation(oxfw,
518c2ecf20Sopenharmony_ci						    AVC_GENERAL_PLUG_DIR_OUT,
528c2ecf20Sopenharmony_ci						    &curr);
538c2ecf20Sopenharmony_ci	if (err < 0)
548c2ecf20Sopenharmony_ci		return;
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	snd_iprintf(buffer, "Output Stream from device:\n");
578c2ecf20Sopenharmony_ci	snd_iprintf(buffer, "\tRate\tPCM\tMIDI\n");
588c2ecf20Sopenharmony_ci	for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
598c2ecf20Sopenharmony_ci		format = oxfw->tx_stream_formats[i];
608c2ecf20Sopenharmony_ci		if (format == NULL)
618c2ecf20Sopenharmony_ci			continue;
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci		err = snd_oxfw_stream_parse_format(format, &formation);
648c2ecf20Sopenharmony_ci		if (err < 0)
658c2ecf20Sopenharmony_ci			continue;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci		if (memcmp(&formation, &curr, sizeof(curr)) == 0)
688c2ecf20Sopenharmony_ci			flag = '*';
698c2ecf20Sopenharmony_ci		else
708c2ecf20Sopenharmony_ci			flag = ' ';
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci		snd_iprintf(buffer, "%c\t%d\t%d\t%d\n", flag,
738c2ecf20Sopenharmony_ci			    formation.rate, formation.pcm, formation.midi);
748c2ecf20Sopenharmony_ci	}
758c2ecf20Sopenharmony_ci}
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_cistatic void add_node(struct snd_oxfw *oxfw, struct snd_info_entry *root,
788c2ecf20Sopenharmony_ci		     const char *name,
798c2ecf20Sopenharmony_ci		     void (*op)(struct snd_info_entry *e,
808c2ecf20Sopenharmony_ci				struct snd_info_buffer *b))
818c2ecf20Sopenharmony_ci{
828c2ecf20Sopenharmony_ci	struct snd_info_entry *entry;
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	entry = snd_info_create_card_entry(oxfw->card, name, root);
858c2ecf20Sopenharmony_ci	if (entry)
868c2ecf20Sopenharmony_ci		snd_info_set_text_ops(entry, oxfw, op);
878c2ecf20Sopenharmony_ci}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_civoid snd_oxfw_proc_init(struct snd_oxfw *oxfw)
908c2ecf20Sopenharmony_ci{
918c2ecf20Sopenharmony_ci	struct snd_info_entry *root;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	/*
948c2ecf20Sopenharmony_ci	 * All nodes are automatically removed at snd_card_disconnect(),
958c2ecf20Sopenharmony_ci	 * by following to link list.
968c2ecf20Sopenharmony_ci	 */
978c2ecf20Sopenharmony_ci	root = snd_info_create_card_entry(oxfw->card, "firewire",
988c2ecf20Sopenharmony_ci					  oxfw->card->proc_root);
998c2ecf20Sopenharmony_ci	if (root == NULL)
1008c2ecf20Sopenharmony_ci		return;
1018c2ecf20Sopenharmony_ci	root->mode = S_IFDIR | 0555;
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	add_node(oxfw, root, "formation", proc_read_formation);
1048c2ecf20Sopenharmony_ci}
105