Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
56599bb0
Commit
56599bb0
authored
Apr 18, 2012
by
Takashi Iwai
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/usb-endpoint' into topic/misc
parents
7536c301
22026c1a
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1401 additions
and
825 deletions
+1401
-825
sound/usb/card.c
sound/usb/card.c
+9
-1
sound/usb/card.h
sound/usb/card.h
+62
-15
sound/usb/endpoint.c
sound/usb/endpoint.c
+894
-707
sound/usb/endpoint.h
sound/usb/endpoint.h
+20
-12
sound/usb/pcm.c
sound/usb/pcm.c
+365
-76
sound/usb/proc.c
sound/usb/proc.c
+21
-11
sound/usb/stream.c
sound/usb/stream.c
+28
-3
sound/usb/usbaudio.h
sound/usb/usbaudio.h
+2
-0
No files found.
sound/usb/card.c
View file @
56599bb0
...
@@ -131,8 +131,9 @@ static void snd_usb_stream_disconnect(struct list_head *head)
...
@@ -131,8 +131,9 @@ static void snd_usb_stream_disconnect(struct list_head *head)
subs
=
&
as
->
substream
[
idx
];
subs
=
&
as
->
substream
[
idx
];
if
(
!
subs
->
num_formats
)
if
(
!
subs
->
num_formats
)
continue
;
continue
;
snd_usb_release_substream_urbs
(
subs
,
1
);
subs
->
interface
=
-
1
;
subs
->
interface
=
-
1
;
subs
->
data_endpoint
=
NULL
;
subs
->
sync_endpoint
=
NULL
;
}
}
}
}
...
@@ -276,6 +277,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
...
@@ -276,6 +277,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
static
int
snd_usb_audio_free
(
struct
snd_usb_audio
*
chip
)
static
int
snd_usb_audio_free
(
struct
snd_usb_audio
*
chip
)
{
{
mutex_destroy
(
&
chip
->
mutex
);
kfree
(
chip
);
kfree
(
chip
);
return
0
;
return
0
;
}
}
...
@@ -336,6 +338,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
...
@@ -336,6 +338,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
mutex_init
(
&
chip
->
mutex
);
mutex_init
(
&
chip
->
shutdown_mutex
);
mutex_init
(
&
chip
->
shutdown_mutex
);
chip
->
index
=
idx
;
chip
->
index
=
idx
;
chip
->
dev
=
dev
;
chip
->
dev
=
dev
;
...
@@ -348,6 +351,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
...
@@ -348,6 +351,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
chip
->
usb_id
=
USB_ID
(
le16_to_cpu
(
dev
->
descriptor
.
idVendor
),
chip
->
usb_id
=
USB_ID
(
le16_to_cpu
(
dev
->
descriptor
.
idVendor
),
le16_to_cpu
(
dev
->
descriptor
.
idProduct
));
le16_to_cpu
(
dev
->
descriptor
.
idProduct
));
INIT_LIST_HEAD
(
&
chip
->
pcm_list
);
INIT_LIST_HEAD
(
&
chip
->
pcm_list
);
INIT_LIST_HEAD
(
&
chip
->
ep_list
);
INIT_LIST_HEAD
(
&
chip
->
midi_list
);
INIT_LIST_HEAD
(
&
chip
->
midi_list
);
INIT_LIST_HEAD
(
&
chip
->
mixer_list
);
INIT_LIST_HEAD
(
&
chip
->
mixer_list
);
...
@@ -565,6 +569,10 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
...
@@ -565,6 +569,10 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
list_for_each
(
p
,
&
chip
->
pcm_list
)
{
list_for_each
(
p
,
&
chip
->
pcm_list
)
{
snd_usb_stream_disconnect
(
p
);
snd_usb_stream_disconnect
(
p
);
}
}
/* release the endpoint resources */
list_for_each
(
p
,
&
chip
->
ep_list
)
{
snd_usb_endpoint_free
(
p
);
}
/* release the midi resources */
/* release the midi resources */
list_for_each
(
p
,
&
chip
->
midi_list
)
{
list_for_each
(
p
,
&
chip
->
midi_list
)
{
snd_usbmidi_disconnect
(
p
);
snd_usbmidi_disconnect
(
p
);
...
...
sound/usb/card.h
View file @
56599bb0
...
@@ -30,13 +30,17 @@ struct audioformat {
...
@@ -30,13 +30,17 @@ struct audioformat {
};
};
struct
snd_usb_substream
;
struct
snd_usb_substream
;
struct
snd_usb_endpoint
;
struct
snd_urb_ctx
{
struct
snd_urb_ctx
{
struct
urb
*
urb
;
struct
urb
*
urb
;
unsigned
int
buffer_size
;
/* size of data buffer, if data URB */
unsigned
int
buffer_size
;
/* size of data buffer, if data URB */
struct
snd_usb_substream
*
subs
;
struct
snd_usb_substream
*
subs
;
struct
snd_usb_endpoint
*
ep
;
int
index
;
/* index for urb array */
int
index
;
/* index for urb array */
int
packets
;
/* number of packets per urb */
int
packets
;
/* number of packets per urb */
int
packet_size
[
MAX_PACKS_HS
];
/* size of packets for next submission */
struct
list_head
ready_list
;
};
};
struct
snd_urb_ops
{
struct
snd_urb_ops
{
...
@@ -46,6 +50,60 @@ struct snd_urb_ops {
...
@@ -46,6 +50,60 @@ struct snd_urb_ops {
int
(
*
retire_sync
)(
struct
snd_usb_substream
*
subs
,
struct
snd_pcm_runtime
*
runtime
,
struct
urb
*
u
);
int
(
*
retire_sync
)(
struct
snd_usb_substream
*
subs
,
struct
snd_pcm_runtime
*
runtime
,
struct
urb
*
u
);
};
};
struct
snd_usb_endpoint
{
struct
snd_usb_audio
*
chip
;
int
use_count
;
int
ep_num
;
/* the referenced endpoint number */
int
type
;
/* SND_USB_ENDPOINT_TYPE_* */
unsigned
long
flags
;
void
(
*
prepare_data_urb
)
(
struct
snd_usb_substream
*
subs
,
struct
urb
*
urb
);
void
(
*
retire_data_urb
)
(
struct
snd_usb_substream
*
subs
,
struct
urb
*
urb
);
struct
snd_usb_substream
*
data_subs
;
struct
snd_usb_endpoint
*
sync_master
;
struct
snd_usb_endpoint
*
sync_slave
;
struct
snd_urb_ctx
urb
[
MAX_URBS
];
struct
snd_usb_packet_info
{
uint32_t
packet_size
[
MAX_PACKS_HS
];
int
packets
;
}
next_packet
[
MAX_URBS
];
int
next_packet_read_pos
,
next_packet_write_pos
;
struct
list_head
ready_playback_urbs
;
unsigned
int
nurbs
;
/* # urbs */
unsigned
long
active_mask
;
/* bitmask of active urbs */
unsigned
long
unlink_mask
;
/* bitmask of unlinked urbs */
char
*
syncbuf
;
/* sync buffer for all sync URBs */
dma_addr_t
sync_dma
;
/* DMA address of syncbuf */
unsigned
int
pipe
;
/* the data i/o pipe */
unsigned
int
freqn
;
/* nominal sampling rate in fs/fps in Q16.16 format */
unsigned
int
freqm
;
/* momentary sampling rate in fs/fps in Q16.16 format */
int
freqshift
;
/* how much to shift the feedback value to get Q16.16 */
unsigned
int
freqmax
;
/* maximum sampling rate, used for buffer management */
unsigned
int
phase
;
/* phase accumulator */
unsigned
int
maxpacksize
;
/* max packet size in bytes */
unsigned
int
maxframesize
;
/* max packet size in frames */
unsigned
int
curpacksize
;
/* current packet size in bytes (for capture) */
unsigned
int
curframesize
;
/* current packet size in frames (for capture) */
unsigned
int
syncmaxsize
;
/* sync endpoint packet size */
unsigned
int
fill_max
:
1
;
/* fill max packet size always */
unsigned
int
datainterval
;
/* log_2 of data packet interval */
unsigned
int
syncinterval
;
/* P for adaptive mode, 0 otherwise */
unsigned
char
silence_value
;
unsigned
int
stride
;
int
iface
,
alt_idx
;
spinlock_t
lock
;
struct
list_head
list
;
};
struct
snd_usb_substream
{
struct
snd_usb_substream
{
struct
snd_usb_stream
*
stream
;
struct
snd_usb_stream
*
stream
;
struct
usb_device
*
dev
;
struct
usb_device
*
dev
;
...
@@ -57,21 +115,6 @@ struct snd_usb_substream {
...
@@ -57,21 +115,6 @@ struct snd_usb_substream {
unsigned
int
cur_rate
;
/* current rate (for hw_params callback) */
unsigned
int
cur_rate
;
/* current rate (for hw_params callback) */
unsigned
int
period_bytes
;
/* current period bytes (for hw_params callback) */
unsigned
int
period_bytes
;
/* current period bytes (for hw_params callback) */
unsigned
int
altset_idx
;
/* USB data format: index of alternate setting */
unsigned
int
altset_idx
;
/* USB data format: index of alternate setting */
unsigned
int
datapipe
;
/* the data i/o pipe */
unsigned
int
syncpipe
;
/* 1 - async out or adaptive in */
unsigned
int
datainterval
;
/* log_2 of data packet interval */
unsigned
int
syncinterval
;
/* P for adaptive mode, 0 otherwise */
unsigned
int
freqn
;
/* nominal sampling rate in fs/fps in Q16.16 format */
unsigned
int
freqm
;
/* momentary sampling rate in fs/fps in Q16.16 format */
int
freqshift
;
/* how much to shift the feedback value to get Q16.16 */
unsigned
int
freqmax
;
/* maximum sampling rate, used for buffer management */
unsigned
int
phase
;
/* phase accumulator */
unsigned
int
maxpacksize
;
/* max packet size in bytes */
unsigned
int
maxframesize
;
/* max packet size in frames */
unsigned
int
curpacksize
;
/* current packet size in bytes (for capture) */
unsigned
int
curframesize
;
/* current packet size in frames (for capture) */
unsigned
int
syncmaxsize
;
/* sync endpoint packet size */
unsigned
int
fill_max
:
1
;
/* fill max packet size always */
unsigned
int
txfr_quirk
:
1
;
/* allow sub-frame alignment */
unsigned
int
txfr_quirk
:
1
;
/* allow sub-frame alignment */
unsigned
int
fmt_type
;
/* USB audio format type (1-3) */
unsigned
int
fmt_type
;
/* USB audio format type (1-3) */
...
@@ -87,6 +130,10 @@ struct snd_usb_substream {
...
@@ -87,6 +130,10 @@ struct snd_usb_substream {
struct
snd_urb_ctx
syncurb
[
SYNC_URBS
];
/* sync urb table */
struct
snd_urb_ctx
syncurb
[
SYNC_URBS
];
/* sync urb table */
char
*
syncbuf
;
/* sync buffer for all sync URBs */
char
*
syncbuf
;
/* sync buffer for all sync URBs */
dma_addr_t
sync_dma
;
/* DMA address of syncbuf */
dma_addr_t
sync_dma
;
/* DMA address of syncbuf */
/* data and sync endpoints for this stream */
struct
snd_usb_endpoint
*
data_endpoint
;
struct
snd_usb_endpoint
*
sync_endpoint
;
unsigned
long
flags
;
u64
formats
;
/* format bitmasks (all or'ed) */
u64
formats
;
/* format bitmasks (all or'ed) */
unsigned
int
num_formats
;
/* number of supported audio formats (list) */
unsigned
int
num_formats
;
/* number of supported audio formats (list) */
...
...
sound/usb/endpoint.c
View file @
56599bb0
This diff is collapsed.
Click to expand it.
sound/usb/endpoint.h
View file @
56599bb0
#ifndef __USBAUDIO_ENDPOINT_H
#ifndef __USBAUDIO_ENDPOINT_H
#define __USBAUDIO_ENDPOINT_H
#define __USBAUDIO_ENDPOINT_H
void
snd_usb_init_substream
(
struct
snd_usb_stream
*
as
,
#define SND_USB_ENDPOINT_TYPE_DATA 0
int
stream
,
#define SND_USB_ENDPOINT_TYPE_SYNC 1
struct
audioformat
*
fp
);
int
snd_usb_init_substream_urbs
(
struct
snd_usb_substream
*
subs
,
struct
snd_usb_endpoint
*
snd_usb_add_endpoint
(
struct
snd_usb_audio
*
chip
,
unsigned
int
period_bytes
,
struct
usb_host_interface
*
alts
,
unsigned
int
rate
,
int
ep_num
,
int
direction
,
int
type
);
unsigned
int
frame_bits
);
void
snd_usb_release_substream_urbs
(
struct
snd_usb_substream
*
subs
,
int
force
);
int
snd_usb_endpoint_set_params
(
struct
snd_usb_endpoint
*
ep
,
struct
snd_pcm_hw_params
*
hw_params
,
struct
audioformat
*
fmt
,
struct
snd_usb_endpoint
*
sync_ep
);
int
snd_usb_substream_prepare
(
struct
snd_usb_substream
*
subs
,
int
snd_usb_endpoint_start
(
struct
snd_usb_endpoint
*
ep
);
struct
snd_pcm_runtime
*
runtime
);
void
snd_usb_endpoint_stop
(
struct
snd_usb_endpoint
*
ep
,
int
force
,
int
can_sleep
,
int
wait
);
int
snd_usb_endpoint_activate
(
struct
snd_usb_endpoint
*
ep
);
int
snd_usb_endpoint_deactivate
(
struct
snd_usb_endpoint
*
ep
);
void
snd_usb_endpoint_free
(
struct
list_head
*
head
);
int
snd_usb_substream_playback_trigger
(
struct
snd_pcm_substream
*
substream
,
int
cmd
);
int
snd_usb_endpoint_implict_feedback_sink
(
struct
snd_usb_endpoint
*
ep
);
int
snd_usb_substream_capture_trigger
(
struct
snd_pcm_substream
*
substream
,
int
cmd
);
void
snd_usb_handle_sync_urb
(
struct
snd_usb_endpoint
*
ep
,
struct
snd_usb_endpoint
*
sender
,
const
struct
urb
*
urb
);
#endif
/* __USBAUDIO_ENDPOINT_H */
#endif
/* __USBAUDIO_ENDPOINT_H */
sound/usb/pcm.c
View file @
56599bb0
This diff is collapsed.
Click to expand it.
sound/usb/proc.c
View file @
56599bb0
...
@@ -115,6 +115,25 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
...
@@ -115,6 +115,25 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
}
}
}
}
static
void
proc_dump_ep_status
(
struct
snd_usb_substream
*
subs
,
struct
snd_usb_endpoint
*
ep
,
struct
snd_info_buffer
*
buffer
)
{
if
(
!
ep
)
return
;
snd_iprintf
(
buffer
,
" Packet Size = %d
\n
"
,
ep
->
curpacksize
);
snd_iprintf
(
buffer
,
" Momentary freq = %u Hz (%#x.%04x)
\n
"
,
snd_usb_get_speed
(
subs
->
dev
)
==
USB_SPEED_FULL
?
get_full_speed_hz
(
ep
->
freqm
)
:
get_high_speed_hz
(
ep
->
freqm
),
ep
->
freqm
>>
16
,
ep
->
freqm
&
0xffff
);
if
(
ep
->
freqshift
!=
INT_MIN
)
{
int
res
=
16
-
ep
->
freqshift
;
snd_iprintf
(
buffer
,
" Feedback Format = %d.%d
\n
"
,
(
ep
->
syncmaxsize
>
3
?
32
:
24
)
-
res
,
res
);
}
}
static
void
proc_dump_substream_status
(
struct
snd_usb_substream
*
subs
,
struct
snd_info_buffer
*
buffer
)
static
void
proc_dump_substream_status
(
struct
snd_usb_substream
*
subs
,
struct
snd_info_buffer
*
buffer
)
{
{
if
(
subs
->
running
)
{
if
(
subs
->
running
)
{
...
@@ -126,17 +145,8 @@ static void proc_dump_substream_status(struct snd_usb_substream *subs, struct sn
...
@@ -126,17 +145,8 @@ static void proc_dump_substream_status(struct snd_usb_substream *subs, struct sn
for
(
i
=
0
;
i
<
subs
->
nurbs
;
i
++
)
for
(
i
=
0
;
i
<
subs
->
nurbs
;
i
++
)
snd_iprintf
(
buffer
,
"%d "
,
subs
->
dataurb
[
i
].
packets
);
snd_iprintf
(
buffer
,
"%d "
,
subs
->
dataurb
[
i
].
packets
);
snd_iprintf
(
buffer
,
"]
\n
"
);
snd_iprintf
(
buffer
,
"]
\n
"
);
snd_iprintf
(
buffer
,
" Packet Size = %d
\n
"
,
subs
->
curpacksize
);
proc_dump_ep_status
(
subs
,
subs
->
data_endpoint
,
buffer
);
snd_iprintf
(
buffer
,
" Momentary freq = %u Hz (%#x.%04x)
\n
"
,
proc_dump_ep_status
(
subs
,
subs
->
sync_endpoint
,
buffer
);
snd_usb_get_speed
(
subs
->
dev
)
==
USB_SPEED_FULL
?
get_full_speed_hz
(
subs
->
freqm
)
:
get_high_speed_hz
(
subs
->
freqm
),
subs
->
freqm
>>
16
,
subs
->
freqm
&
0xffff
);
if
(
subs
->
freqshift
!=
INT_MIN
)
snd_iprintf
(
buffer
,
" Feedback Format = %d.%d
\n
"
,
(
subs
->
syncmaxsize
>
3
?
32
:
24
)
-
(
16
-
subs
->
freqshift
),
16
-
subs
->
freqshift
);
}
else
{
}
else
{
snd_iprintf
(
buffer
,
" Status: Stop
\n
"
);
snd_iprintf
(
buffer
,
" Status: Stop
\n
"
);
}
}
...
...
sound/usb/stream.c
View file @
56599bb0
...
@@ -73,6 +73,31 @@ static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
...
@@ -73,6 +73,31 @@ static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
}
}
}
}
/*
* initialize the substream instance.
*/
static
void
snd_usb_init_substream
(
struct
snd_usb_stream
*
as
,
int
stream
,
struct
audioformat
*
fp
)
{
struct
snd_usb_substream
*
subs
=
&
as
->
substream
[
stream
];
INIT_LIST_HEAD
(
&
subs
->
fmt_list
);
spin_lock_init
(
&
subs
->
lock
);
subs
->
stream
=
as
;
subs
->
direction
=
stream
;
subs
->
dev
=
as
->
chip
->
dev
;
subs
->
txfr_quirk
=
as
->
chip
->
txfr_quirk
;
snd_usb_set_pcm_ops
(
as
->
pcm
,
stream
);
list_add_tail
(
&
fp
->
list
,
&
subs
->
fmt_list
);
subs
->
formats
|=
fp
->
formats
;
subs
->
num_formats
++
;
subs
->
fmt_type
=
fp
->
fmt_type
;
}
/*
/*
* add this endpoint to the chip instance.
* add this endpoint to the chip instance.
...
@@ -94,9 +119,9 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
...
@@ -94,9 +119,9 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
if
(
as
->
fmt_type
!=
fp
->
fmt_type
)
if
(
as
->
fmt_type
!=
fp
->
fmt_type
)
continue
;
continue
;
subs
=
&
as
->
substream
[
stream
];
subs
=
&
as
->
substream
[
stream
];
if
(
!
subs
->
endpoint
)
if
(
!
subs
->
data_
endpoint
)
continue
;
continue
;
if
(
subs
->
endpoint
==
fp
->
endpoint
)
{
if
(
subs
->
data_endpoint
->
ep_num
==
fp
->
endpoint
)
{
list_add_tail
(
&
fp
->
list
,
&
subs
->
fmt_list
);
list_add_tail
(
&
fp
->
list
,
&
subs
->
fmt_list
);
subs
->
num_formats
++
;
subs
->
num_formats
++
;
subs
->
formats
|=
fp
->
formats
;
subs
->
formats
|=
fp
->
formats
;
...
@@ -109,7 +134,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
...
@@ -109,7 +134,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
if
(
as
->
fmt_type
!=
fp
->
fmt_type
)
if
(
as
->
fmt_type
!=
fp
->
fmt_type
)
continue
;
continue
;
subs
=
&
as
->
substream
[
stream
];
subs
=
&
as
->
substream
[
stream
];
if
(
subs
->
endpoint
)
if
(
subs
->
data_
endpoint
)
continue
;
continue
;
err
=
snd_pcm_new_stream
(
as
->
pcm
,
stream
,
1
);
err
=
snd_pcm_new_stream
(
as
->
pcm
,
stream
,
1
);
if
(
err
<
0
)
if
(
err
<
0
)
...
...
sound/usb/usbaudio.h
View file @
56599bb0
...
@@ -36,6 +36,7 @@ struct snd_usb_audio {
...
@@ -36,6 +36,7 @@ struct snd_usb_audio {
struct
snd_card
*
card
;
struct
snd_card
*
card
;
struct
usb_interface
*
pm_intf
;
struct
usb_interface
*
pm_intf
;
u32
usb_id
;
u32
usb_id
;
struct
mutex
mutex
;
struct
mutex
shutdown_mutex
;
struct
mutex
shutdown_mutex
;
unsigned
int
shutdown
:
1
;
unsigned
int
shutdown
:
1
;
unsigned
int
probing
:
1
;
unsigned
int
probing
:
1
;
...
@@ -46,6 +47,7 @@ struct snd_usb_audio {
...
@@ -46,6 +47,7 @@ struct snd_usb_audio {
int
num_suspended_intf
;
int
num_suspended_intf
;
struct
list_head
pcm_list
;
/* list of pcm streams */
struct
list_head
pcm_list
;
/* list of pcm streams */
struct
list_head
ep_list
;
/* list of audio-related endpoints */
int
pcm_devs
;
int
pcm_devs
;
struct
list_head
midi_list
;
/* list of midi interfaces */
struct
list_head
midi_list
;
/* list of midi interfaces */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment