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
Kirill Smelkov
linux
Commits
9ce3db4e
Commit
9ce3db4e
authored
May 20, 2010
by
Takashi Iwai
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/usb' into for-linus
parents
20406f9b
e213e9cf
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
115 additions
and
16 deletions
+115
-16
include/linux/usb/audio-v2.h
include/linux/usb/audio-v2.h
+12
-0
include/linux/usb/audio.h
include/linux/usb/audio.h
+17
-2
sound/usb/mixer.c
sound/usb/mixer.c
+86
-14
No files found.
include/linux/usb/audio-v2.h
View file @
9ce3db4e
...
@@ -105,6 +105,17 @@ struct uac_as_header_descriptor_v2 {
...
@@ -105,6 +105,17 @@ struct uac_as_header_descriptor_v2 {
__u8
iChannelNames
;
__u8
iChannelNames
;
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
/* 6.1 Interrupt Data Message */
#define UAC2_INTERRUPT_DATA_MSG_VENDOR (1 << 0)
#define UAC2_INTERRUPT_DATA_MSG_EP (1 << 1)
struct
uac2_interrupt_data_msg
{
__u8
bInfo
;
__u8
bAttribute
;
__le16
wValue
;
__le16
wIndex
;
}
__attribute__
((
packed
));
/* A.7 Audio Function Category Codes */
/* A.7 Audio Function Category Codes */
#define UAC2_FUNCTION_SUBCLASS_UNDEFINED 0x00
#define UAC2_FUNCTION_SUBCLASS_UNDEFINED 0x00
...
@@ -153,6 +164,7 @@ struct uac_as_header_descriptor_v2 {
...
@@ -153,6 +164,7 @@ struct uac_as_header_descriptor_v2 {
/* A.14 Audio Class-Specific Request Codes */
/* A.14 Audio Class-Specific Request Codes */
#define UAC2_CS_CUR 0x01
#define UAC2_CS_CUR 0x01
#define UAC2_CS_RANGE 0x02
#define UAC2_CS_RANGE 0x02
#define UAC2_CS_MEM 0x03
/* A.15 Encoder Type Codes */
/* A.15 Encoder Type Codes */
#define UAC2_ENCODER_UNDEFINED 0x00
#define UAC2_ENCODER_UNDEFINED 0x00
...
...
include/linux/usb/audio.h
View file @
9ce3db4e
...
@@ -244,7 +244,7 @@ struct uac_selector_unit_descriptor {
...
@@ -244,7 +244,7 @@ struct uac_selector_unit_descriptor {
static
inline
__u8
uac_selector_unit_iSelector
(
struct
uac_selector_unit_descriptor
*
desc
)
static
inline
__u8
uac_selector_unit_iSelector
(
struct
uac_selector_unit_descriptor
*
desc
)
{
{
__u8
*
raw
=
(
__u8
*
)
desc
;
__u8
*
raw
=
(
__u8
*
)
desc
;
return
raw
[
desc
->
bLength
-
1
];
return
raw
[
9
+
desc
->
bLength
-
1
];
}
}
/* 4.3.2.5 Feature Unit Descriptor */
/* 4.3.2.5 Feature Unit Descriptor */
...
@@ -456,7 +456,7 @@ struct uac_iso_endpoint_descriptor {
...
@@ -456,7 +456,7 @@ struct uac_iso_endpoint_descriptor {
__u8
bmAttributes
;
__u8
bmAttributes
;
__u8
bLockDelayUnits
;
__u8
bLockDelayUnits
;
__le16
wLockDelay
;
__le16
wLockDelay
;
};
}
__attribute__
((
packed
))
;
#define UAC_ISO_ENDPOINT_DESC_SIZE 7
#define UAC_ISO_ENDPOINT_DESC_SIZE 7
#define UAC_EP_CS_ATTR_SAMPLE_RATE 0x01
#define UAC_EP_CS_ATTR_SAMPLE_RATE 0x01
...
@@ -488,6 +488,21 @@ struct uac_iso_endpoint_descriptor {
...
@@ -488,6 +488,21 @@ struct uac_iso_endpoint_descriptor {
#define UAC_FU_BASS_BOOST (1 << (UAC_BASS_BOOST_CONTROL - 1))
#define UAC_FU_BASS_BOOST (1 << (UAC_BASS_BOOST_CONTROL - 1))
#define UAC_FU_LOUDNESS (1 << (UAC_LOUDNESS_CONTROL - 1))
#define UAC_FU_LOUDNESS (1 << (UAC_LOUDNESS_CONTROL - 1))
/* status word format (3.7.1.1) */
#define UAC1_STATUS_TYPE_ORIG_MASK 0x0f
#define UAC1_STATUS_TYPE_ORIG_AUDIO_CONTROL_IF 0x0
#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_IF 0x1
#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_EP 0x2
#define UAC1_STATUS_TYPE_IRQ_PENDING (1 << 7)
#define UAC1_STATUS_TYPE_MEM_CHANGED (1 << 6)
struct
uac1_status_word
{
__u8
bStatusType
;
__u8
bOriginator
;
}
__attribute__
((
packed
));
#ifdef __KERNEL__
#ifdef __KERNEL__
struct
usb_audio_control
{
struct
usb_audio_control
{
...
...
sound/usb/mixer.c
View file @
9ce3db4e
...
@@ -656,7 +656,7 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
...
@@ -656,7 +656,7 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
case
UAC_FEATURE_UNIT
:
{
case
UAC_FEATURE_UNIT
:
{
/* the header is the same for v1 and v2 */
/* the header is the same for v1 and v2 */
struct
uac_feature_unit_descriptor
*
d
=
p1
;
struct
uac_feature_unit_descriptor
*
d
=
p1
;
id
=
d
->
b
Unit
ID
;
id
=
d
->
b
Source
ID
;
break
;
/* continue to parse */
break
;
/* continue to parse */
}
}
case
UAC_MIXER_UNIT
:
{
case
UAC_MIXER_UNIT
:
{
...
@@ -1443,8 +1443,8 @@ static struct procunit_info procunits[] = {
...
@@ -1443,8 +1443,8 @@ static struct procunit_info procunits[] = {
* predefined data for extension units
* predefined data for extension units
*/
*/
static
struct
procunit_value_info
clock_rate_xu_info
[]
=
{
static
struct
procunit_value_info
clock_rate_xu_info
[]
=
{
{
USB_XU_CLOCK_RATE_SELECTOR
,
"Selector"
,
USB_MIXER_U8
,
0
},
{
USB_XU_CLOCK_RATE_SELECTOR
,
"Selector"
,
USB_MIXER_U8
,
0
},
{
0
}
{
0
}
};
};
static
struct
procunit_value_info
clock_source_xu_info
[]
=
{
static
struct
procunit_value_info
clock_source_xu_info
[]
=
{
{
USB_XU_CLOCK_SOURCE_SELECTOR
,
"External"
,
USB_MIXER_BOOLEAN
},
{
USB_XU_CLOCK_SOURCE_SELECTOR
,
"External"
,
USB_MIXER_BOOLEAN
},
...
@@ -1967,26 +1967,98 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
...
@@ -1967,26 +1967,98 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
}
}
}
}
static
void
snd_usb_mixer_status_complete
(
struct
urb
*
urb
)
static
void
snd_usb_mixer_interrupt_v2
(
struct
usb_mixer_interface
*
mixer
,
int
attribute
,
int
value
,
int
index
)
{
struct
usb_mixer_elem_info
*
info
;
__u8
unitid
=
(
index
>>
8
)
&
0xff
;
__u8
control
=
(
value
>>
8
)
&
0xff
;
__u8
channel
=
value
&
0xff
;
if
(
channel
>=
MAX_CHANNELS
)
{
snd_printk
(
KERN_DEBUG
"%s(): bogus channel number %d
\n
"
,
__func__
,
channel
);
return
;
}
for
(
info
=
mixer
->
id_elems
[
unitid
];
info
;
info
=
info
->
next_id_elem
)
{
if
(
info
->
control
!=
control
)
continue
;
switch
(
attribute
)
{
case
UAC2_CS_CUR
:
/* invalidate cache, so the value is read from the device */
if
(
channel
)
info
->
cached
&=
~
(
1
<<
channel
);
else
/* master channel */
info
->
cached
=
0
;
snd_ctl_notify
(
mixer
->
chip
->
card
,
SNDRV_CTL_EVENT_MASK_VALUE
,
info
->
elem_id
);
break
;
case
UAC2_CS_RANGE
:
/* TODO */
break
;
case
UAC2_CS_MEM
:
/* TODO */
break
;
default:
snd_printk
(
KERN_DEBUG
"unknown attribute %d in interrupt
\n
"
,
attribute
);
break
;
}
/* switch */
}
}
static
void
snd_usb_mixer_interrupt
(
struct
urb
*
urb
)
{
{
struct
usb_mixer_interface
*
mixer
=
urb
->
context
;
struct
usb_mixer_interface
*
mixer
=
urb
->
context
;
int
len
=
urb
->
actual_length
;
if
(
urb
->
status
!=
0
)
goto
requeue
;
if
(
urb
->
status
==
0
)
{
if
(
mixer
->
protocol
==
UAC_VERSION_1
)
{
u8
*
buf
=
urb
->
transfer_buffer
;
struct
uac1_status_word
*
status
;
int
i
;
for
(
i
=
urb
->
actual_length
;
i
>=
2
;
buf
+=
2
,
i
-=
2
)
{
for
(
status
=
urb
->
transfer_buffer
;
len
>=
sizeof
(
*
status
);
len
-=
sizeof
(
*
status
),
status
++
)
{
snd_printd
(
KERN_DEBUG
"status interrupt: %02x %02x
\n
"
,
snd_printd
(
KERN_DEBUG
"status interrupt: %02x %02x
\n
"
,
buf
[
0
],
buf
[
1
]);
status
->
bStatusType
,
status
->
bOriginator
);
/* ignore any notifications not from the control interface */
/* ignore any notifications not from the control interface */
if
((
buf
[
0
]
&
0x0f
)
!=
0
)
if
((
status
->
bStatusType
&
UAC1_STATUS_TYPE_ORIG_MASK
)
!=
UAC1_STATUS_TYPE_ORIG_AUDIO_CONTROL_IF
)
continue
;
continue
;
if
(
!
(
buf
[
0
]
&
0x40
))
snd_usb_mixer_notify_id
(
mixer
,
buf
[
1
]);
if
(
status
->
bStatusType
&
UAC1_STATUS_TYPE_MEM_CHANGED
)
snd_usb_mixer_rc_memory_change
(
mixer
,
status
->
bOriginator
);
else
else
snd_usb_mixer_rc_memory_change
(
mixer
,
buf
[
1
]);
snd_usb_mixer_notify_id
(
mixer
,
status
->
bOriginator
);
}
}
else
{
/* UAC_VERSION_2 */
struct
uac2_interrupt_data_msg
*
msg
;
for
(
msg
=
urb
->
transfer_buffer
;
len
>=
sizeof
(
*
msg
);
len
-=
sizeof
(
*
msg
),
msg
++
)
{
/* drop vendor specific and endpoint requests */
if
((
msg
->
bInfo
&
UAC2_INTERRUPT_DATA_MSG_VENDOR
)
||
(
msg
->
bInfo
&
UAC2_INTERRUPT_DATA_MSG_EP
))
continue
;
snd_usb_mixer_interrupt_v2
(
mixer
,
msg
->
bAttribute
,
le16_to_cpu
(
msg
->
wValue
),
le16_to_cpu
(
msg
->
wIndex
));
}
}
}
}
requeue:
if
(
urb
->
status
!=
-
ENOENT
&&
urb
->
status
!=
-
ECONNRESET
)
{
if
(
urb
->
status
!=
-
ENOENT
&&
urb
->
status
!=
-
ECONNRESET
)
{
urb
->
dev
=
mixer
->
chip
->
dev
;
urb
->
dev
=
mixer
->
chip
->
dev
;
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
...
@@ -2023,7 +2095,7 @@ static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
...
@@ -2023,7 +2095,7 @@ static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
usb_fill_int_urb
(
mixer
->
urb
,
mixer
->
chip
->
dev
,
usb_fill_int_urb
(
mixer
->
urb
,
mixer
->
chip
->
dev
,
usb_rcvintpipe
(
mixer
->
chip
->
dev
,
epnum
),
usb_rcvintpipe
(
mixer
->
chip
->
dev
,
epnum
),
transfer_buffer
,
buffer_length
,
transfer_buffer
,
buffer_length
,
snd_usb_mixer_
status_complete
,
mixer
,
ep
->
bInterval
);
snd_usb_mixer_
interrupt
,
mixer
,
ep
->
bInterval
);
usb_submit_urb
(
mixer
->
urb
,
GFP_KERNEL
);
usb_submit_urb
(
mixer
->
urb
,
GFP_KERNEL
);
return
0
;
return
0
;
}
}
...
...
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