Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
d700d70d
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
161
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
d700d70d
编写于
10年前
作者:
T
Takashi Iwai
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'topic/usb-audio' into for-next
上级
7c665932
b47a2229
master
alk-4.19.24
alk-4.19.30
alk-4.19.34
alk-4.19.36
alk-4.19.43
alk-4.19.48
alk-4.19.57
ck-4.19.67
ck-4.19.81
ck-4.19.91
github/fork/deepanshu1422/fix-typo-in-comment
github/fork/haosdent/fix-typo
linux-next
v4.19.91
v4.19.90
v4.19.89
v4.19.88
v4.19.87
v4.19.86
v4.19.85
v4.19.84
v4.19.83
v4.19.82
v4.19.81
v4.19.80
v4.19.79
v4.19.78
v4.19.77
v4.19.76
v4.19.75
v4.19.74
v4.19.73
v4.19.72
v4.19.71
v4.19.70
v4.19.69
v4.19.68
v4.19.67
v4.19.66
v4.19.65
v4.19.64
v4.19.63
v4.19.62
v4.19.61
v4.19.60
v4.19.59
v4.19.58
v4.19.57
v4.19.56
v4.19.55
v4.19.54
v4.19.53
v4.19.52
v4.19.51
v4.19.50
v4.19.49
v4.19.48
v4.19.47
v4.19.46
v4.19.45
v4.19.44
v4.19.43
v4.19.42
v4.19.41
v4.19.40
v4.19.39
v4.19.38
v4.19.37
v4.19.36
v4.19.35
v4.19.34
v4.19.33
v4.19.32
v4.19.31
v4.19.30
v4.19.29
v4.19.28
v4.19.27
v4.19.26
v4.19.25
v4.19.24
v4.19.23
v4.19.22
v4.19.21
v4.19.20
v4.19.19
v4.19.18
v4.19.17
v4.19.16
v4.19.15
v4.19.14
v4.19.13
v4.19.12
v4.19.11
v4.19.10
v4.19.9
v4.19.8
v4.19.7
v4.19.6
v4.19.5
v4.19.4
v4.19.3
v4.19.2
v4.19.1
v4.19
v4.19-rc8
v4.19-rc7
v4.19-rc6
v4.19-rc5
v4.19-rc4
v4.19-rc3
v4.19-rc2
v4.19-rc1
ck-release-21
ck-release-20
ck-release-19.2
ck-release-19.1
ck-release-19
ck-release-18
ck-release-17.2
ck-release-17.1
ck-release-17
ck-release-16
ck-release-15.1
ck-release-15
ck-release-14
ck-release-13.2
ck-release-13
ck-release-12
ck-release-11
ck-release-10
ck-release-9
ck-release-7
alk-release-15
alk-release-14
alk-release-13.2
alk-release-13
alk-release-12
alk-release-11
alk-release-10
alk-release-9
alk-release-7
无相关合并请求
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
478 addition
and
1 deletion
+478
-1
sound/usb/Kconfig
sound/usb/Kconfig
+13
-0
sound/usb/Makefile
sound/usb/Makefile
+1
-1
sound/usb/bcd2000/Makefile
sound/usb/bcd2000/Makefile
+3
-0
sound/usb/bcd2000/bcd2000.c
sound/usb/bcd2000/bcd2000.c
+461
-0
未找到文件。
sound/usb/Kconfig
浏览文件 @
d700d70d
...
...
@@ -147,5 +147,18 @@ config SND_USB_HIFACE
To compile this driver as a module, choose M here: the module
will be called snd-usb-hiface.
config SND_BCD2000
tristate "Behringer BCD2000 MIDI driver"
select SND_RAWMIDI
help
Say Y here to include MIDI support for the Behringer BCD2000 DJ
controller.
Audio support is still work-in-progress at
https://github.com/anyc/snd-usb-bcd2000
To compile this driver as a module, choose M here: the module
will be called snd-bcd2000.
endif # SND_USB
This diff is collapsed.
Click to expand it.
sound/usb/Makefile
浏览文件 @
d700d70d
...
...
@@ -23,4 +23,4 @@ obj-$(CONFIG_SND_USB_UA101) += snd-usbmidi-lib.o
obj-$(CONFIG_SND_USB_USX2Y)
+=
snd-usbmidi-lib.o
obj-$(CONFIG_SND_USB_US122L)
+=
snd-usbmidi-lib.o
obj-$(CONFIG_SND)
+=
misc/ usx2y/ caiaq/ 6fire/ hiface/
obj-$(CONFIG_SND)
+=
misc/ usx2y/ caiaq/ 6fire/ hiface/
bcd2000/
This diff is collapsed.
Click to expand it.
sound/usb/bcd2000/Makefile
0 → 100644
浏览文件 @
d700d70d
snd-bcd2000-y
:=
bcd2000.o
obj-$(CONFIG_SND_BCD2000)
+=
snd-bcd2000.o
\ No newline at end of file
This diff is collapsed.
Click to expand it.
sound/usb/bcd2000/bcd2000.c
0 → 100644
浏览文件 @
d700d70d
/*
* Behringer BCD2000 driver
*
* Copyright (C) 2014 Mario Kicherer (dev@kicherer.org)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/bitmap.h>
#include <linux/usb.h>
#include <linux/usb/audio.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/rawmidi.h>
#define PREFIX "snd-bcd2000: "
#define BUFSIZE 64
static
struct
usb_device_id
id_table
[]
=
{
{
USB_DEVICE
(
0x1397
,
0x00bd
)
},
{
},
};
static
unsigned
char
device_cmd_prefix
[]
=
{
0x03
,
0x00
};
static
unsigned
char
bcd2000_init_sequence
[]
=
{
0x07
,
0x00
,
0x00
,
0x00
,
0x78
,
0x48
,
0x1c
,
0x81
,
0xc4
,
0x00
,
0x00
,
0x00
,
0x5e
,
0x53
,
0x4a
,
0xf7
,
0x18
,
0xfa
,
0x11
,
0xff
,
0x6c
,
0xf3
,
0x90
,
0xff
,
0x00
,
0x00
,
0x00
,
0x00
,
0x01
,
0x00
,
0x00
,
0x00
,
0x18
,
0xfa
,
0x11
,
0xff
,
0x14
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0xf2
,
0x34
,
0x4a
,
0xf7
,
0x18
,
0xfa
,
0x11
,
0xff
};
struct
bcd2000
{
struct
usb_device
*
dev
;
struct
snd_card
*
card
;
struct
usb_interface
*
intf
;
int
card_index
;
int
midi_out_active
;
struct
snd_rawmidi
*
rmidi
;
struct
snd_rawmidi_substream
*
midi_receive_substream
;
struct
snd_rawmidi_substream
*
midi_out_substream
;
unsigned
char
midi_in_buf
[
BUFSIZE
];
unsigned
char
midi_out_buf
[
BUFSIZE
];
struct
urb
*
midi_out_urb
;
struct
urb
*
midi_in_urb
;
struct
usb_anchor
anchor
;
};
static
int
index
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_IDX
;
static
char
*
id
[
SNDRV_CARDS
]
=
SNDRV_DEFAULT_STR
;
static
DEFINE_MUTEX
(
devices_mutex
);
DECLARE_BITMAP
(
devices_used
,
SNDRV_CARDS
);
static
struct
usb_driver
bcd2000_driver
;
#ifdef CONFIG_SND_DEBUG
static
void
bcd2000_dump_buffer
(
const
char
*
prefix
,
const
char
*
buf
,
int
len
)
{
print_hex_dump
(
KERN_DEBUG
,
prefix
,
DUMP_PREFIX_NONE
,
16
,
1
,
buf
,
len
,
false
);
}
#else
static
void
bcd2000_dump_buffer
(
const
char
*
prefix
,
const
char
*
buf
,
int
len
)
{}
#endif
static
int
bcd2000_midi_input_open
(
struct
snd_rawmidi_substream
*
substream
)
{
return
0
;
}
static
int
bcd2000_midi_input_close
(
struct
snd_rawmidi_substream
*
substream
)
{
return
0
;
}
/* (de)register midi substream from client */
static
void
bcd2000_midi_input_trigger
(
struct
snd_rawmidi_substream
*
substream
,
int
up
)
{
struct
bcd2000
*
bcd2k
=
substream
->
rmidi
->
private_data
;
bcd2k
->
midi_receive_substream
=
up
?
substream
:
NULL
;
}
static
void
bcd2000_midi_handle_input
(
struct
bcd2000
*
bcd2k
,
const
unsigned
char
*
buf
,
unsigned
int
buf_len
)
{
unsigned
int
payload_length
,
tocopy
;
struct
snd_rawmidi_substream
*
midi_receive_substream
;
midi_receive_substream
=
ACCESS_ONCE
(
bcd2k
->
midi_receive_substream
);
if
(
!
midi_receive_substream
)
return
;
bcd2000_dump_buffer
(
PREFIX
"received from device: "
,
buf
,
buf_len
);
if
(
buf_len
<
2
)
return
;
payload_length
=
buf
[
0
];
/* ignore packets without payload */
if
(
payload_length
==
0
)
return
;
tocopy
=
min
(
payload_length
,
buf_len
-
1
);
bcd2000_dump_buffer
(
PREFIX
"sending to userspace: "
,
&
buf
[
1
],
tocopy
);
snd_rawmidi_receive
(
midi_receive_substream
,
&
buf
[
1
],
tocopy
);
}
static
void
bcd2000_midi_send
(
struct
bcd2000
*
bcd2k
)
{
int
len
,
ret
;
struct
snd_rawmidi_substream
*
midi_out_substream
;
BUILD_BUG_ON
(
sizeof
(
device_cmd_prefix
)
>=
BUFSIZE
);
midi_out_substream
=
ACCESS_ONCE
(
bcd2k
->
midi_out_substream
);
if
(
!
midi_out_substream
)
return
;
/* copy command prefix bytes */
memcpy
(
bcd2k
->
midi_out_buf
,
device_cmd_prefix
,
sizeof
(
device_cmd_prefix
));
/*
* get MIDI packet and leave space for command prefix
* and payload length
*/
len
=
snd_rawmidi_transmit
(
midi_out_substream
,
bcd2k
->
midi_out_buf
+
3
,
BUFSIZE
-
3
);
if
(
len
<
0
)
dev_err
(
&
bcd2k
->
dev
->
dev
,
"%s: snd_rawmidi_transmit error %d
\n
"
,
__func__
,
len
);
if
(
len
<=
0
)
return
;
/* set payload length */
bcd2k
->
midi_out_buf
[
2
]
=
len
;
bcd2k
->
midi_out_urb
->
transfer_buffer_length
=
BUFSIZE
;
bcd2000_dump_buffer
(
PREFIX
"sending to device: "
,
bcd2k
->
midi_out_buf
,
len
+
3
);
/* send packet to the BCD2000 */
ret
=
usb_submit_urb
(
bcd2k
->
midi_out_urb
,
GFP_ATOMIC
);
if
(
ret
<
0
)
dev_err
(
&
bcd2k
->
dev
->
dev
,
PREFIX
"%s (%p): usb_submit_urb() failed, ret=%d, len=%d
\n
"
,
__func__
,
midi_out_substream
,
ret
,
len
);
else
bcd2k
->
midi_out_active
=
1
;
}
static
int
bcd2000_midi_output_open
(
struct
snd_rawmidi_substream
*
substream
)
{
return
0
;
}
static
int
bcd2000_midi_output_close
(
struct
snd_rawmidi_substream
*
substream
)
{
struct
bcd2000
*
bcd2k
=
substream
->
rmidi
->
private_data
;
if
(
bcd2k
->
midi_out_active
)
{
usb_kill_urb
(
bcd2k
->
midi_out_urb
);
bcd2k
->
midi_out_active
=
0
;
}
return
0
;
}
/* (de)register midi substream from client */
static
void
bcd2000_midi_output_trigger
(
struct
snd_rawmidi_substream
*
substream
,
int
up
)
{
struct
bcd2000
*
bcd2k
=
substream
->
rmidi
->
private_data
;
if
(
up
)
{
bcd2k
->
midi_out_substream
=
substream
;
/* check if there is data userspace wants to send */
if
(
!
bcd2k
->
midi_out_active
)
bcd2000_midi_send
(
bcd2k
);
}
else
{
bcd2k
->
midi_out_substream
=
NULL
;
}
}
static
void
bcd2000_output_complete
(
struct
urb
*
urb
)
{
struct
bcd2000
*
bcd2k
=
urb
->
context
;
bcd2k
->
midi_out_active
=
0
;
if
(
urb
->
status
)
dev_warn
(
&
urb
->
dev
->
dev
,
PREFIX
"output urb->status: %d
\n
"
,
urb
->
status
);
if
(
urb
->
status
==
-
ESHUTDOWN
)
return
;
/* check if there is more data userspace wants to send */
bcd2000_midi_send
(
bcd2k
);
}
static
void
bcd2000_input_complete
(
struct
urb
*
urb
)
{
int
ret
;
struct
bcd2000
*
bcd2k
=
urb
->
context
;
if
(
urb
->
status
)
dev_warn
(
&
urb
->
dev
->
dev
,
PREFIX
"input urb->status: %i
\n
"
,
urb
->
status
);
if
(
!
bcd2k
||
urb
->
status
==
-
ESHUTDOWN
)
return
;
if
(
urb
->
actual_length
>
0
)
bcd2000_midi_handle_input
(
bcd2k
,
urb
->
transfer_buffer
,
urb
->
actual_length
);
/* return URB to device */
ret
=
usb_submit_urb
(
bcd2k
->
midi_in_urb
,
GFP_ATOMIC
);
if
(
ret
<
0
)
dev_err
(
&
bcd2k
->
dev
->
dev
,
PREFIX
"%s: usb_submit_urb() failed, ret=%d
\n
"
,
__func__
,
ret
);
}
static
struct
snd_rawmidi_ops
bcd2000_midi_output
=
{
.
open
=
bcd2000_midi_output_open
,
.
close
=
bcd2000_midi_output_close
,
.
trigger
=
bcd2000_midi_output_trigger
,
};
static
struct
snd_rawmidi_ops
bcd2000_midi_input
=
{
.
open
=
bcd2000_midi_input_open
,
.
close
=
bcd2000_midi_input_close
,
.
trigger
=
bcd2000_midi_input_trigger
,
};
static
void
bcd2000_init_device
(
struct
bcd2000
*
bcd2k
)
{
int
ret
;
init_usb_anchor
(
&
bcd2k
->
anchor
);
usb_anchor_urb
(
bcd2k
->
midi_out_urb
,
&
bcd2k
->
anchor
);
usb_anchor_urb
(
bcd2k
->
midi_in_urb
,
&
bcd2k
->
anchor
);
/* copy init sequence into buffer */
memcpy
(
bcd2k
->
midi_out_buf
,
bcd2000_init_sequence
,
52
);
bcd2k
->
midi_out_urb
->
transfer_buffer_length
=
52
;
/* submit sequence */
ret
=
usb_submit_urb
(
bcd2k
->
midi_out_urb
,
GFP_KERNEL
);
if
(
ret
<
0
)
dev_err
(
&
bcd2k
->
dev
->
dev
,
PREFIX
"%s: usb_submit_urb() out failed, ret=%d: "
,
__func__
,
ret
);
else
bcd2k
->
midi_out_active
=
1
;
/* pass URB to device to enable button and controller events */
ret
=
usb_submit_urb
(
bcd2k
->
midi_in_urb
,
GFP_KERNEL
);
if
(
ret
<
0
)
dev_err
(
&
bcd2k
->
dev
->
dev
,
PREFIX
"%s: usb_submit_urb() in failed, ret=%d: "
,
__func__
,
ret
);
/* ensure initialization is finished */
usb_wait_anchor_empty_timeout
(
&
bcd2k
->
anchor
,
1000
);
}
static
int
bcd2000_init_midi
(
struct
bcd2000
*
bcd2k
)
{
int
ret
;
struct
snd_rawmidi
*
rmidi
;
ret
=
snd_rawmidi_new
(
bcd2k
->
card
,
bcd2k
->
card
->
shortname
,
0
,
1
,
/* output */
1
,
/* input */
&
rmidi
);
if
(
ret
<
0
)
return
ret
;
strlcpy
(
rmidi
->
name
,
bcd2k
->
card
->
shortname
,
sizeof
(
rmidi
->
name
));
rmidi
->
info_flags
=
SNDRV_RAWMIDI_INFO_DUPLEX
;
rmidi
->
private_data
=
bcd2k
;
rmidi
->
info_flags
|=
SNDRV_RAWMIDI_INFO_OUTPUT
;
snd_rawmidi_set_ops
(
rmidi
,
SNDRV_RAWMIDI_STREAM_OUTPUT
,
&
bcd2000_midi_output
);
rmidi
->
info_flags
|=
SNDRV_RAWMIDI_INFO_INPUT
;
snd_rawmidi_set_ops
(
rmidi
,
SNDRV_RAWMIDI_STREAM_INPUT
,
&
bcd2000_midi_input
);
bcd2k
->
rmidi
=
rmidi
;
bcd2k
->
midi_in_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
bcd2k
->
midi_out_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
bcd2k
->
midi_in_urb
||
!
bcd2k
->
midi_out_urb
)
{
dev_err
(
&
bcd2k
->
dev
->
dev
,
PREFIX
"usb_alloc_urb failed
\n
"
);
return
-
ENOMEM
;
}
usb_fill_int_urb
(
bcd2k
->
midi_in_urb
,
bcd2k
->
dev
,
usb_rcvintpipe
(
bcd2k
->
dev
,
0x81
),
bcd2k
->
midi_in_buf
,
BUFSIZE
,
bcd2000_input_complete
,
bcd2k
,
1
);
usb_fill_int_urb
(
bcd2k
->
midi_out_urb
,
bcd2k
->
dev
,
usb_sndintpipe
(
bcd2k
->
dev
,
0x1
),
bcd2k
->
midi_out_buf
,
BUFSIZE
,
bcd2000_output_complete
,
bcd2k
,
1
);
bcd2000_init_device
(
bcd2k
);
return
0
;
}
static
void
bcd2000_free_usb_related_resources
(
struct
bcd2000
*
bcd2k
,
struct
usb_interface
*
interface
)
{
/* usb_kill_urb not necessary, urb is aborted automatically */
usb_free_urb
(
bcd2k
->
midi_out_urb
);
usb_free_urb
(
bcd2k
->
midi_in_urb
);
if
(
bcd2k
->
intf
)
{
usb_set_intfdata
(
bcd2k
->
intf
,
NULL
);
bcd2k
->
intf
=
NULL
;
}
}
static
int
bcd2000_probe
(
struct
usb_interface
*
interface
,
const
struct
usb_device_id
*
usb_id
)
{
struct
snd_card
*
card
;
struct
bcd2000
*
bcd2k
;
unsigned
int
card_index
;
char
usb_path
[
32
];
int
err
;
mutex_lock
(
&
devices_mutex
);
for
(
card_index
=
0
;
card_index
<
SNDRV_CARDS
;
++
card_index
)
if
(
!
test_bit
(
card_index
,
devices_used
))
break
;
if
(
card_index
>=
SNDRV_CARDS
)
{
mutex_unlock
(
&
devices_mutex
);
return
-
ENOENT
;
}
err
=
snd_card_new
(
&
interface
->
dev
,
index
[
card_index
],
id
[
card_index
],
THIS_MODULE
,
sizeof
(
*
bcd2k
),
&
card
);
if
(
err
<
0
)
{
mutex_unlock
(
&
devices_mutex
);
return
err
;
}
bcd2k
=
card
->
private_data
;
bcd2k
->
dev
=
interface_to_usbdev
(
interface
);
bcd2k
->
card
=
card
;
bcd2k
->
card_index
=
card_index
;
bcd2k
->
intf
=
interface
;
snd_card_set_dev
(
card
,
&
interface
->
dev
);
strncpy
(
card
->
driver
,
"snd-bcd2000"
,
sizeof
(
card
->
driver
));
strncpy
(
card
->
shortname
,
"BCD2000"
,
sizeof
(
card
->
shortname
));
usb_make_path
(
bcd2k
->
dev
,
usb_path
,
sizeof
(
usb_path
));
snprintf
(
bcd2k
->
card
->
longname
,
sizeof
(
bcd2k
->
card
->
longname
),
"Behringer BCD2000 at %s"
,
usb_path
);
err
=
bcd2000_init_midi
(
bcd2k
);
if
(
err
<
0
)
goto
probe_error
;
err
=
snd_card_register
(
card
);
if
(
err
<
0
)
goto
probe_error
;
usb_set_intfdata
(
interface
,
bcd2k
);
set_bit
(
card_index
,
devices_used
);
mutex_unlock
(
&
devices_mutex
);
return
0
;
probe_error:
dev_info
(
&
bcd2k
->
dev
->
dev
,
PREFIX
"error during probing"
);
bcd2000_free_usb_related_resources
(
bcd2k
,
interface
);
snd_card_free
(
card
);
mutex_unlock
(
&
devices_mutex
);
return
err
;
}
static
void
bcd2000_disconnect
(
struct
usb_interface
*
interface
)
{
struct
bcd2000
*
bcd2k
=
usb_get_intfdata
(
interface
);
if
(
!
bcd2k
)
return
;
mutex_lock
(
&
devices_mutex
);
/* make sure that userspace cannot create new requests */
snd_card_disconnect
(
bcd2k
->
card
);
bcd2000_free_usb_related_resources
(
bcd2k
,
interface
);
clear_bit
(
bcd2k
->
card_index
,
devices_used
);
snd_card_free_when_closed
(
bcd2k
->
card
);
mutex_unlock
(
&
devices_mutex
);
}
static
struct
usb_driver
bcd2000_driver
=
{
.
name
=
"snd-bcd2000"
,
.
probe
=
bcd2000_probe
,
.
disconnect
=
bcd2000_disconnect
,
.
id_table
=
id_table
,
};
module_usb_driver
(
bcd2000_driver
);
MODULE_DEVICE_TABLE
(
usb
,
id_table
);
MODULE_AUTHOR
(
"Mario Kicherer, dev@kicherer.org"
);
MODULE_DESCRIPTION
(
"Behringer BCD2000 driver"
);
MODULE_LICENSE
(
"GPL"
);
This diff is collapsed.
Click to expand it.
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录
反馈
建议
客服
返回
顶部