Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/usb/proc.c
10814 views
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 */
31
static 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 */
37
static 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
*/
45
static 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
52
static 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
61
void 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
*/
73
static 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
snd_pcm_format_t fmt;
83
fp = list_entry(p, struct audioformat, list);
84
snd_iprintf(buffer, " Interface %d\n", fp->iface);
85
snd_iprintf(buffer, " Altset %d\n", fp->altsetting);
86
snd_iprintf(buffer, " Format:");
87
for (fmt = 0; fmt <= SNDRV_PCM_FORMAT_LAST; ++fmt)
88
if (fp->formats & (1uLL << fmt))
89
snd_iprintf(buffer, " %s",
90
snd_pcm_format_name(fmt));
91
snd_iprintf(buffer, "\n");
92
snd_iprintf(buffer, " Channels: %d\n", fp->channels);
93
snd_iprintf(buffer, " Endpoint: %d %s (%s)\n",
94
fp->endpoint & USB_ENDPOINT_NUMBER_MASK,
95
fp->endpoint & USB_DIR_IN ? "IN" : "OUT",
96
sync_types[(fp->ep_attr & USB_ENDPOINT_SYNCTYPE) >> 2]);
97
if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) {
98
snd_iprintf(buffer, " Rates: %d - %d (continuous)\n",
99
fp->rate_min, fp->rate_max);
100
} else {
101
unsigned int i;
102
snd_iprintf(buffer, " Rates: ");
103
for (i = 0; i < fp->nr_rates; i++) {
104
if (i > 0)
105
snd_iprintf(buffer, ", ");
106
snd_iprintf(buffer, "%d", fp->rate_table[i]);
107
}
108
snd_iprintf(buffer, "\n");
109
}
110
if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
111
snd_iprintf(buffer, " Data packet interval: %d us\n",
112
125 * (1 << fp->datainterval));
113
// snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize);
114
// snd_iprintf(buffer, " EP Attribute = %#x\n", fp->attributes);
115
}
116
}
117
118
static void proc_dump_substream_status(struct snd_usb_substream *subs, struct snd_info_buffer *buffer)
119
{
120
if (subs->running) {
121
unsigned int i;
122
snd_iprintf(buffer, " Status: Running\n");
123
snd_iprintf(buffer, " Interface = %d\n", subs->interface);
124
snd_iprintf(buffer, " Altset = %d\n", subs->altset_idx);
125
snd_iprintf(buffer, " URBs = %d [ ", subs->nurbs);
126
for (i = 0; i < subs->nurbs; i++)
127
snd_iprintf(buffer, "%d ", subs->dataurb[i].packets);
128
snd_iprintf(buffer, "]\n");
129
snd_iprintf(buffer, " Packet Size = %d\n", subs->curpacksize);
130
snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n",
131
snd_usb_get_speed(subs->dev) == USB_SPEED_FULL
132
? get_full_speed_hz(subs->freqm)
133
: get_high_speed_hz(subs->freqm),
134
subs->freqm >> 16, subs->freqm & 0xffff);
135
if (subs->freqshift != INT_MIN)
136
snd_iprintf(buffer, " Feedback Format = %d.%d\n",
137
(subs->syncmaxsize > 3 ? 32 : 24)
138
- (16 - subs->freqshift),
139
16 - subs->freqshift);
140
} else {
141
snd_iprintf(buffer, " Status: Stop\n");
142
}
143
}
144
145
static void proc_pcm_format_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
146
{
147
struct snd_usb_stream *stream = entry->private_data;
148
149
snd_iprintf(buffer, "%s : %s\n", stream->chip->card->longname, stream->pcm->name);
150
151
if (stream->substream[SNDRV_PCM_STREAM_PLAYBACK].num_formats) {
152
snd_iprintf(buffer, "\nPlayback:\n");
153
proc_dump_substream_status(&stream->substream[SNDRV_PCM_STREAM_PLAYBACK], buffer);
154
proc_dump_substream_formats(&stream->substream[SNDRV_PCM_STREAM_PLAYBACK], buffer);
155
}
156
if (stream->substream[SNDRV_PCM_STREAM_CAPTURE].num_formats) {
157
snd_iprintf(buffer, "\nCapture:\n");
158
proc_dump_substream_status(&stream->substream[SNDRV_PCM_STREAM_CAPTURE], buffer);
159
proc_dump_substream_formats(&stream->substream[SNDRV_PCM_STREAM_CAPTURE], buffer);
160
}
161
}
162
163
void snd_usb_proc_pcm_format_add(struct snd_usb_stream *stream)
164
{
165
struct snd_info_entry *entry;
166
char name[32];
167
struct snd_card *card = stream->chip->card;
168
169
sprintf(name, "stream%d", stream->pcm_index);
170
if (!snd_card_proc_new(card, name, &entry))
171
snd_info_set_text_ops(entry, stream, proc_pcm_format_read);
172
}
173
174
175