aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb/proc.c
diff options
context:
space:
mode:
authorDaniel Mack <daniel@caiaq.de>2010-03-04 13:46:13 -0500
committerTakashi Iwai <tiwai@suse.de>2010-03-05 02:17:14 -0500
commite5779998bf8b70e48a6cc208c8b61b33bd6117ea (patch)
tree512568f0fc4b81eac8019522c10df5b81483bcca /sound/usb/proc.c
parent3e1aebef6fb55e35668d2d7cf608cf03f30c904f (diff)
ALSA: usb-audio: refactor code
Clean up the usb audio driver by factoring out a lot of functions to separate files. Code for procfs, quirks, urbs, format parsers etc all got a new home now. Moved almost all special quirk handling to quirks.c and introduced new generic functions to handle them, so the exceptions do not pollute the whole driver. Renamed usbaudio.c to card.c because this is what it actually does now. Renamed usbmidi.c to midi.c for namespace clarity. Removed more things from usbaudio.h. The non-standard drivers were adopted accordingly. Signed-off-by: Daniel Mack <daniel@caiaq.de> Cc: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/proc.c')
-rw-r--r--sound/usb/proc.c163
1 files changed, 163 insertions, 0 deletions
diff --git a/sound/usb/proc.c b/sound/usb/proc.c
new file mode 100644
index 000000000000..be3065ea1afa
--- /dev/null
+++ b/sound/usb/proc.c
@@ -0,0 +1,163 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 *
16 */
17
18#include <linux/init.h>
19#include <linux/usb.h>
20
21#include <sound/core.h>
22#include <sound/info.h>
23#include <sound/pcm.h>
24
25#include "usbaudio.h"
26#include "helper.h"
27#include "card.h"
28#include "proc.h"
29
30/* convert our full speed USB rate into sampling rate in Hz */
31static inline unsigned get_full_speed_hz(unsigned int usb_rate)
32{
33 return (usb_rate * 125 + (1 << 12)) >> 13;
34}
35
36/* convert our high speed USB rate into sampling rate in Hz */
37static inline unsigned get_high_speed_hz(unsigned int usb_rate)
38{
39 return (usb_rate * 125 + (1 << 9)) >> 10;
40}
41
42/*
43 * common proc files to show the usb device info
44 */
45static void proc_audio_usbbus_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
46{
47 struct snd_usb_audio *chip = entry->private_data;
48 if (!chip->shutdown)
49 snd_iprintf(buffer, "%03d/%03d\n", chip->dev->bus->busnum, chip->dev->devnum);
50}
51
52static void proc_audio_usbid_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
53{
54 struct snd_usb_audio *chip = entry->private_data;
55 if (!chip->shutdown)
56 snd_iprintf(buffer, "%04x:%04x\n",
57 USB_ID_VENDOR(chip->usb_id),
58 USB_ID_PRODUCT(chip->usb_id));
59}
60
61void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
62{
63 struct snd_info_entry *entry;
64 if (!snd_card_proc_new(chip->card, "usbbus", &entry))
65 snd_info_set_text_ops(entry, chip, proc_audio_usbbus_read);
66 if (!snd_card_proc_new(chip->card, "usbid", &entry))
67 snd_info_set_text_ops(entry, chip, proc_audio_usbid_read);
68}
69
70/*
71 * proc interface for list the supported pcm formats
72 */
73static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct snd_info_buffer *buffer)
74{
75 struct list_head *p;
76 static char *sync_types[4] = {
77 "NONE", "ASYNC", "ADAPTIVE", "SYNC"
78 };
79
80 list_for_each(p, &subs->fmt_list) {
81 struct audioformat *fp;
82 fp = list_entry(p, struct audioformat, list);
83 snd_iprintf(buffer, " Interface %d\n", fp->iface);
84 snd_iprintf(buffer, " Altset %d\n", fp->altsetting);
85 snd_iprintf(buffer, " Format: %s\n",
86 snd_pcm_format_name(fp->format));
87 snd_iprintf(buffer, " Channels: %d\n", fp->channels);
88 snd_iprintf(buffer, " Endpoint: %d %s (%s)\n",
89 fp->endpoint & USB_ENDPOINT_NUMBER_MASK,
90 fp->endpoint & USB_DIR_IN ? "IN" : "OUT",
91 sync_types[(fp->ep_attr & USB_ENDPOINT_SYNCTYPE) >> 2]);
92 if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) {
93 snd_iprintf(buffer, " Rates: %d - %d (continuous)\n",
94 fp->rate_min, fp->rate_max);
95 } else {
96 unsigned int i;
97 snd_iprintf(buffer, " Rates: ");
98 for (i = 0; i < fp->nr_rates; i++) {
99 if (i > 0)
100 snd_iprintf(buffer, ", ");
101 snd_iprintf(buffer, "%d", fp->rate_table[i]);
102 }
103 snd_iprintf(buffer, "\n");
104 }
105 if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH)
106 snd_iprintf(buffer, " Data packet interval: %d us\n",
107 125 * (1 << fp->datainterval));
108 // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize);
109 // snd_iprintf(buffer, " EP Attribute = %#x\n", fp->attributes);
110 }
111}
112
113static void proc_dump_substream_status(struct snd_usb_substream *subs, struct snd_info_buffer *buffer)
114{
115 if (subs->running) {
116 unsigned int i;
117 snd_iprintf(buffer, " Status: Running\n");
118 snd_iprintf(buffer, " Interface = %d\n", subs->interface);
119 snd_iprintf(buffer, " Altset = %d\n", subs->format);
120 snd_iprintf(buffer, " URBs = %d [ ", subs->nurbs);
121 for (i = 0; i < subs->nurbs; i++)
122 snd_iprintf(buffer, "%d ", subs->dataurb[i].packets);
123 snd_iprintf(buffer, "]\n");
124 snd_iprintf(buffer, " Packet Size = %d\n", subs->curpacksize);
125 snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n",
126 snd_usb_get_speed(subs->dev) == USB_SPEED_FULL
127 ? get_full_speed_hz(subs->freqm)
128 : get_high_speed_hz(subs->freqm),
129 subs->freqm >> 16, subs->freqm & 0xffff);
130 } else {
131 snd_iprintf(buffer, " Status: Stop\n");
132 }
133}
134
135static void proc_pcm_format_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
136{
137 struct snd_usb_stream *stream = entry->private_data;
138
139 snd_iprintf(buffer, "%s : %s\n", stream->chip->card->longname, stream->pcm->name);
140
141 if (stream->substream[SNDRV_PCM_STREAM_PLAYBACK].num_formats) {
142 snd_iprintf(buffer, "\nPlayback:\n");
143 proc_dump_substream_status(&stream->substream[SNDRV_PCM_STREAM_PLAYBACK], buffer);
144 proc_dump_substream_formats(&stream->substream[SNDRV_PCM_STREAM_PLAYBACK], buffer);
145 }
146 if (stream->substream[SNDRV_PCM_STREAM_CAPTURE].num_formats) {
147 snd_iprintf(buffer, "\nCapture:\n");
148 proc_dump_substream_status(&stream->substream[SNDRV_PCM_STREAM_CAPTURE], buffer);
149 proc_dump_substream_formats(&stream->substream[SNDRV_PCM_STREAM_CAPTURE], buffer);
150 }
151}
152
153void snd_usb_proc_pcm_format_add(struct snd_usb_stream *stream)
154{
155 struct snd_info_entry *entry;
156 char name[32];
157 struct snd_card *card = stream->chip->card;
158
159 sprintf(name, "stream%d", stream->pcm_index);
160 if (!snd_card_proc_new(card, name, &entry))
161 snd_info_set_text_ops(entry, stream, proc_pcm_format_read);
162}
163