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
86b5f3ec
Commit
86b5f3ec
authored
Jan 20, 2015
by
Takashi Iwai
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'topic/line6' into for-next
parents
2a52b6ee
c078a4aa
Changes
26
Hide whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
946 additions
and
1428 deletions
+946
-1428
sound/usb/Makefile
sound/usb/Makefile
+1
-1
sound/usb/line6/Kconfig
sound/usb/line6/Kconfig
+22
-20
sound/usb/line6/Makefile
sound/usb/line6/Makefile
+13
-9
sound/usb/line6/audio.c
sound/usb/line6/audio.c
+0
-71
sound/usb/line6/audio.h
sound/usb/line6/audio.h
+0
-21
sound/usb/line6/capture.c
sound/usb/line6/capture.c
+2
-14
sound/usb/line6/capture.h
sound/usb/line6/capture.h
+1
-1
sound/usb/line6/driver.c
sound/usb/line6/driver.c
+87
-539
sound/usb/line6/driver.h
sound/usb/line6/driver.h
+18
-51
sound/usb/line6/midi.c
sound/usb/line6/midi.c
+28
-50
sound/usb/line6/midi.h
sound/usb/line6/midi.h
+2
-2
sound/usb/line6/midibuf.c
sound/usb/line6/midibuf.c
+2
-2
sound/usb/line6/midibuf.h
sound/usb/line6/midibuf.h
+1
-1
sound/usb/line6/pcm.c
sound/usb/line6/pcm.c
+106
-146
sound/usb/line6/pcm.h
sound/usb/line6/pcm.h
+5
-23
sound/usb/line6/playback.c
sound/usb/line6/playback.c
+2
-18
sound/usb/line6/playback.h
sound/usb/line6/playback.h
+1
-1
sound/usb/line6/pod.c
sound/usb/line6/pod.c
+226
-48
sound/usb/line6/pod.h
sound/usb/line6/pod.h
+0
-92
sound/usb/line6/podhd.c
sound/usb/line6/podhd.c
+115
-62
sound/usb/line6/podhd.h
sound/usb/line6/podhd.h
+0
-29
sound/usb/line6/toneport.c
sound/usb/line6/toneport.c
+182
-69
sound/usb/line6/toneport.h
sound/usb/line6/toneport.h
+0
-51
sound/usb/line6/usbdefs.h
sound/usb/line6/usbdefs.h
+1
-1
sound/usb/line6/variax.c
sound/usb/line6/variax.c
+131
-36
sound/usb/line6/variax.h
sound/usb/line6/variax.h
+0
-70
No files found.
sound/usb/Makefile
View file @
86b5f3ec
...
...
@@ -25,4 +25,4 @@ 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/ bcd2000/
obj-$(CONFIG_
LINE6_USB)
+=
line6/
obj-$(CONFIG_
SND_USB_LINE6)
+=
line6/
sound/usb/line6/Kconfig
View file @
86b5f3ec
menuconfig LINE6_USB
tristate "Line6 USB support"
depends on USB && SND
config SND_USB_LINE6
tristate
select SND_RAWMIDI
select SND_PCM
config SND_USB_POD
tristate "Line 6 POD USB support"
select SND_USB_LINE6
help
This is a driver for the guitar amp, cab, and effects modeller
PODxt Pro by Line6 (and similar devices), supporting the
following features:
This is a driver for PODxt and other similar devices,
supporting the following features:
* Reading/writing individual parameters
* Reading/writing complete channel, effects setup, and amp
setup data
...
...
@@ -18,21 +20,21 @@ menuconfig LINE6_USB
* Signal routing (record clean/processed guitar signal,
re-amping)
Preliminary support for the Variax Workbench and TonePort
devices is included.
if LINE6_USB
config SND_USB_PODHD
tristate "Line 6 POD HD300/400/500 USB support"
select SND_USB_LINE6
help
This is a driver for POD HD300, 400 and 500 devices.
config
LINE6_USB_IMPULSE_RESPONSE
bool "measure impulse response
"
default n
config
SND_USB_TONEPORT
tristate "TonePort GX, UX1 and UX2 USB support
"
select SND_USB_LINE6
help
Say Y here to add code to measure the impulse response of a Line6
device. This is more accurate than user-space methods since it
bypasses any PCM data buffering (e.g., by ALSA or jack). This is
useful for assessing the performance of new devices, but is not
required for normal operation.
This is a driver for TonePort GX, UX1 and UX2 devices.
If unsure, say N.
config SND_USB_VARIAX
tristate "Variax Workbench USB support"
select SND_USB_LINE6
help
This is a driver for Variax Workbench device.
endif # LINE6_USB
sound/usb/line6/Makefile
View file @
86b5f3ec
obj-$(CONFIG_LINE6_USB)
+=
line6usb.o
line6usb-y
:=
\
audio.o
\
snd-usb-line6-y
:=
\
capture.o
\
driver.o
\
midi.o
\
midibuf.o
\
pcm.o
\
playback.o
\
pod.o
\
toneport.o
\
variax.o
\
podhd.o
playback.o
snd-usb-pod-y
:=
pod.o
snd-usb-podhd-y
:=
podhd.o
snd-usb-toneport-y
:=
toneport.o
snd-usb-variax-y
:=
variax.o
obj-$(CONFIG_SND_USB_LINE6)
+=
snd-usb-line6.o
obj-$(CONFIG_SND_USB_POD)
+=
snd-usb-pod.o
obj-$(CONFIG_SND_USB_PODHD)
+=
snd-usb-podhd.o
obj-$(CONFIG_SND_USB_TONEPORT)
+=
snd-usb-toneport.o
obj-$(CONFIG_SND_USB_VARIAX)
+=
snd-usb-variax.o
sound/usb/line6/audio.c
deleted
100644 → 0
View file @
2a52b6ee
/*
* Line6 Linux USB driver - 0.9.1beta
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
* 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, version 2.
*
*/
#include <sound/core.h>
#include <sound/initval.h>
#include <linux/export.h>
#include "driver.h"
#include "audio.h"
/*
Initialize the Line6 USB audio system.
*/
int
line6_init_audio
(
struct
usb_line6
*
line6
)
{
struct
snd_card
*
card
;
int
err
;
err
=
snd_card_new
(
line6
->
ifcdev
,
SNDRV_DEFAULT_IDX1
,
SNDRV_DEFAULT_STR1
,
THIS_MODULE
,
0
,
&
card
);
if
(
err
<
0
)
return
err
;
line6
->
card
=
card
;
strcpy
(
card
->
id
,
line6
->
properties
->
id
);
strcpy
(
card
->
driver
,
DRIVER_NAME
);
strcpy
(
card
->
shortname
,
line6
->
properties
->
name
);
/* longname is 80 chars - see asound.h */
sprintf
(
card
->
longname
,
"Line6 %s at USB %s"
,
line6
->
properties
->
name
,
dev_name
(
line6
->
ifcdev
));
return
0
;
}
/*
Register the Line6 USB audio system.
*/
int
line6_register_audio
(
struct
usb_line6
*
line6
)
{
int
err
;
err
=
snd_card_register
(
line6
->
card
);
if
(
err
<
0
)
return
err
;
return
0
;
}
/*
Cleanup the Line6 USB audio system.
*/
void
line6_cleanup_audio
(
struct
usb_line6
*
line6
)
{
struct
snd_card
*
card
=
line6
->
card
;
if
(
card
==
NULL
)
return
;
snd_card_disconnect
(
card
);
snd_card_free
(
card
);
line6
->
card
=
NULL
;
}
sound/usb/line6/audio.h
deleted
100644 → 0
View file @
2a52b6ee
/*
* Line6 Linux USB driver - 0.9.1beta
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
* 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, version 2.
*
*/
#ifndef AUDIO_H
#define AUDIO_H
#include "driver.h"
extern
void
line6_cleanup_audio
(
struct
usb_line6
*
);
extern
int
line6_init_audio
(
struct
usb_line6
*
);
extern
int
line6_register_audio
(
struct
usb_line6
*
);
#endif
sound/usb/line6/capture.c
View file @
86b5f3ec
/*
* Line
6 Linux USB driver - 0.9.1beta
* Line
6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
...
...
@@ -14,11 +14,9 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include "audio.h"
#include "capture.h"
#include "driver.h"
#include "pcm.h"
#include "pod.h"
/*
Find a free URB and submit it.
...
...
@@ -245,9 +243,7 @@ static void audio_in_callback(struct urb *urb)
line6pcm
->
prev_fbuf
=
fbuf
;
line6pcm
->
prev_fsize
=
fsize
;
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
if
(
!
(
line6pcm
->
flags
&
LINE6_BITS_PCM_IMPULSE
))
#endif
if
(
test_bit
(
LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM
,
&
line6pcm
->
flags
)
&&
(
fsize
>
0
))
line6_capture_copy
(
line6pcm
,
fbuf
,
fsize
);
...
...
@@ -263,9 +259,7 @@ static void audio_in_callback(struct urb *urb)
if
(
!
shutdown
)
{
submit_audio_in_urb
(
line6pcm
);
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
if
(
!
(
line6pcm
->
flags
&
LINE6_BITS_PCM_IMPULSE
))
#endif
if
(
test_bit
(
LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM
,
&
line6pcm
->
flags
))
line6_capture_check_period
(
line6pcm
,
length
);
...
...
@@ -347,9 +341,7 @@ int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd)
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
#ifdef CONFIG_PM
case
SNDRV_PCM_TRIGGER_RESUME
:
#endif
err
=
line6_pcm_acquire
(
line6pcm
,
LINE6_BIT_PCM_ALSA_CAPTURE_STREAM
);
...
...
@@ -359,9 +351,7 @@ int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd)
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
#ifdef CONFIG_PM
case
SNDRV_PCM_TRIGGER_SUSPEND
:
#endif
err
=
line6_pcm_release
(
line6pcm
,
LINE6_BIT_PCM_ALSA_CAPTURE_STREAM
);
...
...
@@ -411,10 +401,8 @@ int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm)
urb
=
line6pcm
->
urb_audio_in
[
i
]
=
usb_alloc_urb
(
LINE6_ISO_PACKETS
,
GFP_KERNEL
);
if
(
urb
==
NULL
)
{
dev_err
(
line6
->
ifcdev
,
"Out of memory
\n
"
);
if
(
urb
==
NULL
)
return
-
ENOMEM
;
}
urb
->
dev
=
line6
->
usbdev
;
urb
->
pipe
=
...
...
sound/usb/line6/capture.h
View file @
86b5f3ec
/*
* Line
6 Linux USB driver - 0.9.1beta
* Line
6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
...
...
sound/usb/line6/driver.c
View file @
86b5f3ec
/*
* Line
6 Linux USB driver - 0.9.1beta
* Line
6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
...
...
@@ -11,277 +11,30 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/usb.h>
#include "audio.h"
#include <sound/core.h>
#include <sound/initval.h>
#include "capture.h"
#include "driver.h"
#include "midi.h"
#include "playback.h"
#include "pod.h"
#include "podhd.h"
#include "revision.h"
#include "toneport.h"
#include "usbdefs.h"
#include "variax.h"
#define DRIVER_AUTHOR "Markus Grabner <grabner@icg.tugraz.at>"
#define DRIVER_DESC "Line6 USB Driver"
#define DRIVER_VERSION "0.9.1beta" DRIVER_REVISION
#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
/* table of devices that work with this driver */
static
const
struct
usb_device_id
line6_id_table
[]
=
{
{
LINE6_DEVICE
(
0x4250
),
.
driver_info
=
LINE6_BASSPODXT
},
{
LINE6_DEVICE
(
0x4642
),
.
driver_info
=
LINE6_BASSPODXTLIVE
},
{
LINE6_DEVICE
(
0x4252
),
.
driver_info
=
LINE6_BASSPODXTPRO
},
{
LINE6_DEVICE
(
0x4750
),
.
driver_info
=
LINE6_GUITARPORT
},
{
LINE6_IF_NUM
(
0x5051
,
1
),
.
driver_info
=
LINE6_POCKETPOD
},
{
LINE6_DEVICE
(
0x5057
),
.
driver_info
=
LINE6_PODHD300
},
{
LINE6_DEVICE
(
0x5058
),
.
driver_info
=
LINE6_PODHD400
},
{
LINE6_IF_NUM
(
0x414D
,
0
),
.
driver_info
=
LINE6_PODHD500_0
},
{
LINE6_IF_NUM
(
0x414D
,
1
),
.
driver_info
=
LINE6_PODHD500_1
},
{
LINE6_DEVICE
(
0x4153
),
.
driver_info
=
LINE6_PODSTUDIO_GX
},
{
LINE6_DEVICE
(
0x4150
),
.
driver_info
=
LINE6_PODSTUDIO_UX1
},
{
LINE6_IF_NUM
(
0x4151
,
0
),
.
driver_info
=
LINE6_PODSTUDIO_UX2
},
{
LINE6_DEVICE
(
0x5044
),
.
driver_info
=
LINE6_PODXT
},
{
LINE6_IF_NUM
(
0x4650
,
0
),
.
driver_info
=
LINE6_PODXTLIVE_POD
},
{
LINE6_IF_NUM
(
0x4650
,
1
),
.
driver_info
=
LINE6_PODXTLIVE_VARIAX
},
{
LINE6_DEVICE
(
0x5050
),
.
driver_info
=
LINE6_PODXTPRO
},
{
LINE6_DEVICE
(
0x4147
),
.
driver_info
=
LINE6_TONEPORT_GX
},
{
LINE6_DEVICE
(
0x4141
),
.
driver_info
=
LINE6_TONEPORT_UX1
},
{
LINE6_IF_NUM
(
0x4142
,
0
),
.
driver_info
=
LINE6_TONEPORT_UX2
},
{
LINE6_DEVICE
(
0x534d
),
.
driver_info
=
LINE6_VARIAX
},
{}
};
MODULE_DEVICE_TABLE
(
usb
,
line6_id_table
);
static
const
struct
line6_properties
line6_properties_table
[]
=
{
[
LINE6_BASSPODXT
]
=
{
.
id
=
"BassPODxt"
,
.
name
=
"BassPODxt"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
5
,
.
ep_ctrl_r
=
0x84
,
.
ep_ctrl_w
=
0x03
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_BASSPODXTLIVE
]
=
{
.
id
=
"BassPODxtLive"
,
.
name
=
"BassPODxt Live"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
1
,
.
ep_ctrl_r
=
0x84
,
.
ep_ctrl_w
=
0x03
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_BASSPODXTPRO
]
=
{
.
id
=
"BassPODxtPro"
,
.
name
=
"BassPODxt Pro"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
5
,
.
ep_ctrl_r
=
0x84
,
.
ep_ctrl_w
=
0x03
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_GUITARPORT
]
=
{
.
id
=
"GuitarPort"
,
.
name
=
"GuitarPort"
,
.
capabilities
=
LINE6_CAP_PCM
,
.
altsetting
=
2
,
/* 1..4 seem to be ok */
/* no control channel */
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_POCKETPOD
]
=
{
.
id
=
"PocketPOD"
,
.
name
=
"Pocket POD"
,
.
capabilities
=
LINE6_CAP_CONTROL
,
.
altsetting
=
0
,
.
ep_ctrl_r
=
0x82
,
.
ep_ctrl_w
=
0x02
,
/* no audio channel */
},
[
LINE6_PODHD300
]
=
{
.
id
=
"PODHD300"
,
.
name
=
"POD HD300"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
5
,
.
ep_ctrl_r
=
0x84
,
.
ep_ctrl_w
=
0x03
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_PODHD400
]
=
{
.
id
=
"PODHD400"
,
.
name
=
"POD HD400"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
5
,
.
ep_ctrl_r
=
0x84
,
.
ep_ctrl_w
=
0x03
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_PODHD500_0
]
=
{
.
id
=
"PODHD500"
,
.
name
=
"POD HD500"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
1
,
.
ep_ctrl_r
=
0x81
,
.
ep_ctrl_w
=
0x01
,
.
ep_audio_r
=
0x86
,
.
ep_audio_w
=
0x02
,
},
[
LINE6_PODHD500_1
]
=
{
.
id
=
"PODHD500"
,
.
name
=
"POD HD500"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
1
,
.
ep_ctrl_r
=
0x81
,
.
ep_ctrl_w
=
0x01
,
.
ep_audio_r
=
0x86
,
.
ep_audio_w
=
0x02
,
},
[
LINE6_PODSTUDIO_GX
]
=
{
.
id
=
"PODStudioGX"
,
.
name
=
"POD Studio GX"
,
.
capabilities
=
LINE6_CAP_PCM
,
.
altsetting
=
2
,
/* 1..4 seem to be ok */
/* no control channel */
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_PODSTUDIO_UX1
]
=
{
.
id
=
"PODStudioUX1"
,
.
name
=
"POD Studio UX1"
,
.
capabilities
=
LINE6_CAP_PCM
,
.
altsetting
=
2
,
/* 1..4 seem to be ok */
/* no control channel */
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_PODSTUDIO_UX2
]
=
{
.
id
=
"PODStudioUX2"
,
.
name
=
"POD Studio UX2"
,
.
capabilities
=
LINE6_CAP_PCM
,
.
altsetting
=
2
,
/* defaults to 44.1kHz, 16-bit */
/* no control channel */
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_PODXT
]
=
{
.
id
=
"PODxt"
,
.
name
=
"PODxt"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
5
,
.
ep_ctrl_r
=
0x84
,
.
ep_ctrl_w
=
0x03
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_PODXTLIVE_POD
]
=
{
.
id
=
"PODxtLive"
,
.
name
=
"PODxt Live"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
1
,
.
ep_ctrl_r
=
0x84
,
.
ep_ctrl_w
=
0x03
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_PODXTLIVE_VARIAX
]
=
{
.
id
=
"PODxtLive"
,
.
name
=
"PODxt Live"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
1
,
.
ep_ctrl_r
=
0x86
,
.
ep_ctrl_w
=
0x05
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_PODXTPRO
]
=
{
.
id
=
"PODxtPro"
,
.
name
=
"PODxt Pro"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
5
,
.
ep_ctrl_r
=
0x84
,
.
ep_ctrl_w
=
0x03
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_TONEPORT_GX
]
=
{
.
id
=
"TonePortGX"
,
.
name
=
"TonePort GX"
,
.
capabilities
=
LINE6_CAP_PCM
,
.
altsetting
=
2
,
/* 1..4 seem to be ok */
/* no control channel */
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_TONEPORT_UX1
]
=
{
.
id
=
"TonePortUX1"
,
.
name
=
"TonePort UX1"
,
.
capabilities
=
LINE6_CAP_PCM
,
.
altsetting
=
2
,
/* 1..4 seem to be ok */
/* no control channel */
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_TONEPORT_UX2
]
=
{
.
id
=
"TonePortUX2"
,
.
name
=
"TonePort UX2"
,
.
capabilities
=
LINE6_CAP_PCM
,
.
altsetting
=
2
,
/* defaults to 44.1kHz, 16-bit */
/* no control channel */
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_VARIAX
]
=
{
.
id
=
"Variax"
,
.
name
=
"Variax Workbench"
,
.
capabilities
=
LINE6_CAP_CONTROL
,
.
altsetting
=
1
,
.
ep_ctrl_r
=
0x82
,
.
ep_ctrl_w
=
0x01
,
/* no audio channel */
}
};
#define DRIVER_DESC "Line 6 USB Driver"
/*
This is Line6's MIDI manufacturer ID.
This is Line
6's MIDI manufacturer ID.
*/
const
unsigned
char
line6_midi_id
[]
=
{
0x00
,
0x01
,
0x0c
};
EXPORT_SYMBOL_GPL
(
line6_midi_id
);
/*
Code to request version of POD, Variax interface
...
...
@@ -335,8 +88,8 @@ static void line6_stop_listen(struct usb_line6 *line6)
/*
Send raw message in pieces of wMaxPacketSize bytes.
*/
int
line6_send_raw_message
(
struct
usb_line6
*
line6
,
const
char
*
buffer
,
int
size
)
static
int
line6_send_raw_message
(
struct
usb_line6
*
line6
,
const
char
*
buffer
,
int
size
)
{
int
i
,
done
=
0
;
...
...
@@ -415,9 +168,9 @@ void line6_start_timer(struct timer_list *timer, unsigned int msecs,
void
(
*
function
)(
unsigned
long
),
unsigned
long
data
)
{
setup_timer
(
timer
,
function
,
data
);
timer
->
expires
=
jiffies
+
msecs
*
HZ
/
1000
;
add_timer
(
timer
);
mod_timer
(
timer
,
jiffies
+
msecs
*
HZ
/
1000
);
}
EXPORT_SYMBOL_GPL
(
line6_start_timer
);
/*
Asynchronously send raw message.
...
...
@@ -438,7 +191,6 @@ int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer,
if
(
urb
==
NULL
)
{
kfree
(
msg
);
dev_err
(
line6
->
ifcdev
,
"Out of memory
\n
"
);
return
-
ENOMEM
;
}
...
...
@@ -451,6 +203,7 @@ int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer,
/* start sending: */
return
line6_send_raw_message_async_part
(
msg
,
urb
);
}
EXPORT_SYMBOL_GPL
(
line6_send_raw_message_async
);
/*
Send asynchronous device version request.
...
...
@@ -462,16 +215,15 @@ int line6_version_request_async(struct usb_line6 *line6)
buffer
=
kmemdup
(
line6_request_version
,
sizeof
(
line6_request_version
),
GFP_ATOMIC
);
if
(
buffer
==
NULL
)
{
dev_err
(
line6
->
ifcdev
,
"Out of memory"
);
if
(
buffer
==
NULL
)
return
-
ENOMEM
;
}
retval
=
line6_send_raw_message_async
(
line6
,
buffer
,
sizeof
(
line6_request_version
));
kfree
(
buffer
);
return
retval
;
}
EXPORT_SYMBOL_GPL
(
line6_version_request_async
);
/*
Send sysex message in pieces of wMaxPacketSize bytes.
...
...
@@ -483,6 +235,7 @@ int line6_send_sysex_message(struct usb_line6 *line6, const char *buffer,
size
+
SYSEX_EXTRA_SIZE
)
-
SYSEX_EXTRA_SIZE
;
}
EXPORT_SYMBOL_GPL
(
line6_send_sysex_message
);
/*
Allocate buffer for sysex message and prepare header.
...
...
@@ -504,9 +257,10 @@ char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1, int code2,
buffer
[
sizeof
(
line6_midi_id
)
+
3
+
size
]
=
LINE6_SYSEX_END
;
return
buffer
;
}
EXPORT_SYMBOL_GPL
(
line6_alloc_sysex_buffer
);
/*
Notification of data received from the Line6 device.
Notification of data received from the Line
6 device.
*/
static
void
line6_data_received
(
struct
urb
*
urb
)
{
...
...
@@ -544,65 +298,6 @@ static void line6_data_received(struct urb *urb)
line6_start_listen
(
line6
);
}
/*
Send channel number (i.e., switch to a different sound).
*/
int
line6_send_program
(
struct
usb_line6
*
line6
,
u8
value
)
{
int
retval
;
unsigned
char
*
buffer
;
int
partial
;
buffer
=
kmalloc
(
2
,
GFP_KERNEL
);
if
(
!
buffer
)
return
-
ENOMEM
;
buffer
[
0
]
=
LINE6_PROGRAM_CHANGE
|
LINE6_CHANNEL_HOST
;
buffer
[
1
]
=
value
;
retval
=
usb_interrupt_msg
(
line6
->
usbdev
,
usb_sndintpipe
(
line6
->
usbdev
,
line6
->
properties
->
ep_ctrl_w
),
buffer
,
2
,
&
partial
,
LINE6_TIMEOUT
*
HZ
);
if
(
retval
)
dev_err
(
line6
->
ifcdev
,
"usb_interrupt_msg failed (%d)
\n
"
,
retval
);
kfree
(
buffer
);
return
retval
;
}
/*
Transmit Line6 control parameter.
*/
int
line6_transmit_parameter
(
struct
usb_line6
*
line6
,
int
param
,
u8
value
)
{
int
retval
;
unsigned
char
*
buffer
;
int
partial
;
buffer
=
kmalloc
(
3
,
GFP_KERNEL
);
if
(
!
buffer
)
return
-
ENOMEM
;
buffer
[
0
]
=
LINE6_PARAM_CHANGE
|
LINE6_CHANNEL_HOST
;
buffer
[
1
]
=
param
;
buffer
[
2
]
=
value
;
retval
=
usb_interrupt_msg
(
line6
->
usbdev
,
usb_sndintpipe
(
line6
->
usbdev
,
line6
->
properties
->
ep_ctrl_w
),
buffer
,
3
,
&
partial
,
LINE6_TIMEOUT
*
HZ
);
if
(
retval
)
dev_err
(
line6
->
ifcdev
,
"usb_interrupt_msg failed (%d)
\n
"
,
retval
);
kfree
(
buffer
);
return
retval
;
}
/*
Read data from device.
*/
...
...
@@ -659,6 +354,7 @@ int line6_read_data(struct usb_line6 *line6, int address, void *data,
return
0
;
}
EXPORT_SYMBOL_GPL
(
line6_read_data
);
/*
Write data to device.
...
...
@@ -703,9 +399,10 @@ int line6_write_data(struct usb_line6 *line6, int address, void *data,
return
0
;
}
EXPORT_SYMBOL_GPL
(
line6_write_data
);
/*
Read Line6 device serial number.
Read Line
6 device serial number.
(POD, TonePort, GuitarPort)
*/
int
line6_read_serial_number
(
struct
usb_line6
*
line6
,
int
*
serial_number
)
...
...
@@ -713,6 +410,7 @@ int line6_read_serial_number(struct usb_line6 *line6, int *serial_number)
return
line6_read_data
(
line6
,
0x80d0
,
serial_number
,
sizeof
(
*
serial_number
));
}
EXPORT_SYMBOL_GPL
(
line6_read_serial_number
);
/*
No operation (i.e., unsupported).
...
...
@@ -722,19 +420,19 @@ ssize_t line6_nop_read(struct device *dev, struct device_attribute *attr,
{
return
0
;
}
EXPORT_SYMBOL_GPL
(
line6_nop_read
);
/*
Generic
destructor.
Card
destructor.
*/
static
void
line6_destruct
(
struct
usb_interface
*
interface
)
static
void
line6_destruct
(
struct
snd_card
*
card
)
{
struct
usb_line6
*
line6
;
struct
usb_line6
*
line6
=
card
->
private_data
;
struct
usb_device
*
usbdev
;
if
(
interface
==
NULL
)
return
;
line6
=
usb_get_intfdata
(
interface
);
if
(
line6
==
NULL
)
if
(
!
line6
)
return
;
usbdev
=
line6
->
usbdev
;
/* free buffer memory first: */
kfree
(
line6
->
buffer_message
);
...
...
@@ -743,44 +441,34 @@ static void line6_destruct(struct usb_interface *interface)
/* then free URBs: */
usb_free_urb
(
line6
->
urb_listen
);
/* make sure the device isn't destructed twice: */
usb_set_intfdata
(
interface
,
NULL
);
/* free interface data: */
kfree
(
line6
);
/* decrement reference counters: */
usb_put_dev
(
usbdev
);
}
/*
Probe USB device.
*/
static
int
line6_probe
(
struct
usb_interface
*
interface
,
const
struct
usb_device_id
*
id
)
int
line6_probe
(
struct
usb_interface
*
interface
,
struct
usb_line6
*
line6
,
const
struct
line6_properties
*
properties
,
int
(
*
private_init
)(
struct
usb_interface
*
,
struct
usb_line6
*
))
{
enum
line6_device_type
devtype
;
struct
usb_device
*
usbdev
;
struct
usb_line6
*
line6
;
const
struct
line6_properties
*
properties
;
struct
usb_device
*
usbdev
=
interface_to_usbdev
(
interface
);
struct
snd_card
*
card
;
int
interface_number
;
int
size
=
0
;
int
ret
;
if
(
interface
==
NULL
)
return
-
ENODEV
;
usbdev
=
interface_to_usbdev
(
interface
);
if
(
usbdev
==
NULL
)
return
-
ENODEV
;
/* we don't handle multiple configurations */
if
(
usbdev
->
descriptor
.
bNumConfigurations
!=
1
)
{
ret
=
-
ENODEV
;
goto
err_put
;
}
devtype
=
id
->
driver_info
;
/* initialize device info: */
properties
=
&
line6_properties_table
[
devtype
];
dev_info
(
&
interface
->
dev
,
"Line6 %s found
\n
"
,
properties
->
name
);
dev_info
(
&
interface
->
dev
,
"Line 6 %s found
\n
"
,
properties
->
name
);
/* query interface number */
interface_number
=
interface
->
cur_altsetting
->
desc
.
bInterfaceNumber
;
...
...
@@ -792,76 +480,10 @@ static int line6_probe(struct usb_interface *interface,
goto
err_put
;
}
/* initialize device data based on device: */
switch
(
devtype
)
{
case
LINE6_BASSPODXT
:
case
LINE6_BASSPODXTLIVE
:
case
LINE6_BASSPODXTPRO
:
case
LINE6_PODXT
:
case
LINE6_PODXTPRO
:
size
=
sizeof
(
struct
usb_line6_pod
);
break
;
case
LINE6_PODHD300
:
case
LINE6_PODHD400
:
size
=
sizeof
(
struct
usb_line6_podhd
);
break
;
case
LINE6_PODHD500_0
:
case
LINE6_PODHD500_1
:
size
=
sizeof
(
struct
usb_line6_podhd
);
break
;
case
LINE6_POCKETPOD
:
size
=
sizeof
(
struct
usb_line6_pod
);
break
;
case
LINE6_PODSTUDIO_GX
:
case
LINE6_PODSTUDIO_UX1
:
case
LINE6_PODSTUDIO_UX2
:
case
LINE6_TONEPORT_GX
:
case
LINE6_TONEPORT_UX1
:
case
LINE6_TONEPORT_UX2
:
case
LINE6_GUITARPORT
:
size
=
sizeof
(
struct
usb_line6_toneport
);
break
;
case
LINE6_PODXTLIVE_POD
:
size
=
sizeof
(
struct
usb_line6_pod
);
break
;
case
LINE6_PODXTLIVE_VARIAX
:
size
=
sizeof
(
struct
usb_line6_variax
);
break
;
case
LINE6_VARIAX
:
size
=
sizeof
(
struct
usb_line6_variax
);
break
;
default:
MISSING_CASE
;
ret
=
-
ENODEV
;
goto
err_put
;
}
if
(
size
==
0
)
{
dev_err
(
&
interface
->
dev
,
"driver bug: interface data size not set
\n
"
);
ret
=
-
ENODEV
;
goto
err_put
;
}
line6
=
kzalloc
(
size
,
GFP_KERNEL
);
if
(
line6
==
NULL
)
{
ret
=
-
ENODEV
;
goto
err_put
;
}
/* store basic data: */
line6
->
properties
=
properties
;
line6
->
usbdev
=
usbdev
;
line6
->
ifcdev
=
&
interface
->
dev
;
line6
->
type
=
devtype
;
/* get data from endpoint descriptor (see usb_maxpacket): */
{
...
...
@@ -882,8 +504,26 @@ static int line6_probe(struct usb_interface *interface,
}
}
ret
=
snd_card_new
(
line6
->
ifcdev
,
SNDRV_DEFAULT_IDX1
,
SNDRV_DEFAULT_STR1
,
THIS_MODULE
,
0
,
&
card
);
if
(
ret
<
0
)
goto
err_put
;
line6
->
card
=
card
;
strcpy
(
card
->
id
,
line6
->
properties
->
id
);
strcpy
(
card
->
driver
,
DRIVER_NAME
);
strcpy
(
card
->
shortname
,
line6
->
properties
->
name
);
sprintf
(
card
->
longname
,
"Line 6 %s at USB %s"
,
line6
->
properties
->
name
,
dev_name
(
line6
->
ifcdev
));
card
->
private_data
=
line6
;
card
->
private_free
=
line6_destruct
;
usb_set_intfdata
(
interface
,
line6
);
/* increment reference counters: */
usb_get_dev
(
usbdev
);
if
(
properties
->
capabilities
&
LINE6_CAP_CONTROL
)
{
/* initialize USB buffers: */
line6
->
buffer_listen
=
...
...
@@ -903,8 +543,6 @@ static int line6_probe(struct usb_interface *interface,
line6
->
urb_listen
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
line6
->
urb_listen
==
NULL
)
{
dev_err
(
&
interface
->
dev
,
"Out of memory
\n
"
);
line6_destruct
(
interface
);
ret
=
-
ENOMEM
;
goto
err_destruct
;
}
...
...
@@ -918,79 +556,28 @@ static int line6_probe(struct usb_interface *interface,
}
/* initialize device data based on device: */
switch
(
devtype
)
{
case
LINE6_BASSPODXT
:
case
LINE6_BASSPODXTLIVE
:
case
LINE6_BASSPODXTPRO
:
case
LINE6_POCKETPOD
:
case
LINE6_PODXT
:
case
LINE6_PODXTPRO
:
ret
=
line6_pod_init
(
interface
,
line6
);
break
;
case
LINE6_PODHD300
:
case
LINE6_PODHD400
:
case
LINE6_PODHD500_0
:
case
LINE6_PODHD500_1
:
ret
=
line6_podhd_init
(
interface
,
line6
);
break
;
case
LINE6_PODXTLIVE_POD
:
ret
=
line6_pod_init
(
interface
,
line6
);
break
;
case
LINE6_PODXTLIVE_VARIAX
:
ret
=
line6_variax_init
(
interface
,
line6
);
break
;
case
LINE6_VARIAX
:
ret
=
line6_variax_init
(
interface
,
line6
);
break
;
case
LINE6_PODSTUDIO_GX
:
case
LINE6_PODSTUDIO_UX1
:
case
LINE6_PODSTUDIO_UX2
:
case
LINE6_TONEPORT_GX
:
case
LINE6_TONEPORT_UX1
:
case
LINE6_TONEPORT_UX2
:
case
LINE6_GUITARPORT
:
ret
=
line6_toneport_init
(
interface
,
line6
);
break
;
default:
MISSING_CASE
;
ret
=
-
ENODEV
;
}
if
(
ret
<
0
)
goto
err_destruct
;
ret
=
sysfs_create_link
(
&
interface
->
dev
.
kobj
,
&
usbdev
->
dev
.
kobj
,
"usb_device"
);
ret
=
private_init
(
interface
,
line6
);
if
(
ret
<
0
)
goto
err_destruct
;
/* creation of additional special files should go here */
dev_info
(
&
interface
->
dev
,
"Line6 %s now attached
\n
"
,
dev_info
(
&
interface
->
dev
,
"Line
6 %s now attached
\n
"
,
line6
->
properties
->
name
);
/* increment reference counters: */
usb_get_intf
(
interface
);
usb_get_dev
(
usbdev
);
return
0
;
err_destruct:
line6_destruct
(
interface
);
err_put:
err_destruct:
snd_card_free
(
card
);
err_put:
return
ret
;
}
EXPORT_SYMBOL_GPL
(
line6_probe
);
/*
Line6 device disconnected.
Line
6 device disconnected.
*/
static
void
line6_disconnect
(
struct
usb_interface
*
interface
)
void
line6_disconnect
(
struct
usb_interface
*
interface
)
{
struct
usb_line6
*
line6
;
struct
usb_device
*
usbdev
;
...
...
@@ -1002,40 +589,39 @@ static void line6_disconnect(struct usb_interface *interface)
if
(
usbdev
==
NULL
)
return
;
/* removal of additional special files should go here */
sysfs_remove_link
(
&
interface
->
dev
.
kobj
,
"usb_device"
);
interface_number
=
interface
->
cur_altsetting
->
desc
.
bInterfaceNumber
;
line6
=
usb_get_intfdata
(
interface
);
if
(
!
line6
)
return
;
if
(
line6
!=
NULL
)
{
if
(
line6
->
urb_listen
!=
NULL
)
line6_stop_listen
(
line6
);
if
(
line6
->
urb_listen
!=
NULL
)
line6_stop_listen
(
line6
);
if
(
usbdev
!=
line6
->
usbdev
)
dev_err
(
line6
->
ifcdev
,
"driver bug: inconsistent usb device
\n
"
);
if
(
usbdev
!=
line6
->
usbdev
)
dev_err
(
line6
->
ifcdev
,
"driver bug: inconsistent usb device
\n
"
);
snd_card_disconnect
(
line6
->
card
);
if
(
line6
->
line6pcm
)
line6_pcm_disconnect
(
line6
->
line6pcm
);
if
(
line6
->
disconnect
)
line6
->
disconnect
(
interface
);
dev_info
(
&
interface
->
dev
,
"Line6 %s now disconnected
\n
"
,
line6
->
properties
->
name
);
}
dev_info
(
&
interface
->
dev
,
"Line 6 %s now disconnected
\n
"
,
line6
->
properties
->
name
);
line6_destruct
(
interface
);
/* make sure the device isn't destructed twice: */
usb_set_intfdata
(
interface
,
NULL
);
/* decrement reference counters: */
usb_put_intf
(
interface
);
usb_put_dev
(
usbdev
);
snd_card_free_when_closed
(
line6
->
card
);
}
EXPORT_SYMBOL_GPL
(
line6_disconnect
);
#ifdef CONFIG_PM
/*
Suspend Line6 device.
Suspend Line
6 device.
*/
static
int
line6_suspend
(
struct
usb_interface
*
interface
,
pm_message_t
message
)
int
line6_suspend
(
struct
usb_interface
*
interface
,
pm_message_t
message
)
{
struct
usb_line6
*
line6
=
usb_get_intfdata
(
interface
);
struct
snd_line6_pcm
*
line6pcm
=
line6
->
line6pcm
;
...
...
@@ -1047,17 +633,17 @@ static int line6_suspend(struct usb_interface *interface, pm_message_t message)
if
(
line6pcm
!=
NULL
)
{
snd_pcm_suspend_all
(
line6pcm
->
pcm
);
line6_pcm_disconnect
(
line6pcm
);
line6pcm
->
flags
=
0
;
}
return
0
;
}
EXPORT_SYMBOL_GPL
(
line6_suspend
);
/*
Resume Line6 device.
Resume Line
6 device.
*/
static
int
line6_resume
(
struct
usb_interface
*
interface
)
int
line6_resume
(
struct
usb_interface
*
interface
)
{
struct
usb_line6
*
line6
=
usb_get_intfdata
(
interface
);
...
...
@@ -1067,48 +653,10 @@ static int line6_resume(struct usb_interface *interface)
snd_power_change_state
(
line6
->
card
,
SNDRV_CTL_POWER_D0
);
return
0
;
}
/*
Resume Line6 device after reset.
*/
static
int
line6_reset_resume
(
struct
usb_interface
*
interface
)
{
struct
usb_line6
*
line6
=
usb_get_intfdata
(
interface
);
switch
(
line6
->
type
)
{
case
LINE6_PODSTUDIO_GX
:
case
LINE6_PODSTUDIO_UX1
:
case
LINE6_PODSTUDIO_UX2
:
case
LINE6_TONEPORT_GX
:
case
LINE6_TONEPORT_UX1
:
case
LINE6_TONEPORT_UX2
:
case
LINE6_GUITARPORT
:
line6_toneport_reset_resume
((
struct
usb_line6_toneport
*
)
line6
);
default:
break
;
}
return
line6_resume
(
interface
);
}
EXPORT_SYMBOL_GPL
(
line6_resume
);
#endif
/* CONFIG_PM */
static
struct
usb_driver
line6_driver
=
{
.
name
=
DRIVER_NAME
,
.
probe
=
line6_probe
,
.
disconnect
=
line6_disconnect
,
#ifdef CONFIG_PM
.
suspend
=
line6_suspend
,
.
resume
=
line6_resume
,
.
reset_resume
=
line6_reset_resume
,
#endif
.
id_table
=
line6_id_table
,
};
module_usb_driver
(
line6_driver
);
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
MODULE_VERSION
(
DRIVER_VERSION
);
sound/usb/line6/driver.h
View file @
86b5f3ec
/*
* Line
6 Linux USB driver - 0.9.1beta
* Line
6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
...
...
@@ -20,35 +20,12 @@
#define DRIVER_NAME "line6usb"
enum
line6_device_type
{
LINE6_BASSPODXT
,
LINE6_BASSPODXTLIVE
,
LINE6_BASSPODXTPRO
,
LINE6_GUITARPORT
,
LINE6_POCKETPOD
,
LINE6_PODHD300
,
LINE6_PODHD400
,
LINE6_PODHD500_0
,
LINE6_PODHD500_1
,
LINE6_PODSTUDIO_GX
,
LINE6_PODSTUDIO_UX1
,
LINE6_PODSTUDIO_UX2
,
LINE6_PODXT
,
LINE6_PODXTLIVE_POD
,
LINE6_PODXTLIVE_VARIAX
,
LINE6_PODXTPRO
,
LINE6_TONEPORT_GX
,
LINE6_TONEPORT_UX1
,
LINE6_TONEPORT_UX2
,
LINE6_VARIAX
};
#define LINE6_TIMEOUT 1
#define LINE6_BUFSIZE_LISTEN 32
#define LINE6_MESSAGE_MAXLEN 256
/*
Line6 MIDI control commands
Line
6 MIDI control commands
*/
#define LINE6_PARAM_CHANGE 0xb0
#define LINE6_PROGRAM_CHANGE 0xc0
...
...
@@ -71,17 +48,6 @@ enum line6_device_type {
#define LINE6_CHANNEL_MASK 0x0f
#define MISSING_CASE \
pr_err("line6usb driver bug: missing case in %s:%d\n", \
__FILE__, __LINE__)
#define CHECK_RETURN(x) \
do { \
err = x; \
if (err < 0) \
return err; \
} while (0)
#define CHECK_STARTUP_PROGRESS(x, n) \
do { \
if ((x) >= (n)) \
...
...
@@ -95,7 +61,7 @@ static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3;
static
const
int
SYSEX_EXTRA_SIZE
=
sizeof
(
line6_midi_id
)
+
4
;
/**
Common properties of Line6 devices.
Common properties of Line
6 devices.
*/
struct
line6_properties
{
/**
...
...
@@ -125,7 +91,7 @@ struct line6_properties {
};
/**
Common data shared by all Line6 devices.
Common data shared by all Line
6 devices.
Corresponds to a pair of USB endpoints.
*/
struct
usb_line6
{
...
...
@@ -134,11 +100,6 @@ struct usb_line6 {
*/
struct
usb_device
*
usbdev
;
/**
Device type.
*/
enum
line6_device_type
type
;
/**
Properties.
*/
...
...
@@ -160,18 +121,18 @@ struct usb_line6 {
struct
device
*
ifcdev
;
/**
Line6 sound card data structure.
Line
6 sound card data structure.
Each device has at least MIDI or PCM.
*/
struct
snd_card
*
card
;
/**
Line6 PCM device data structure.
Line
6 PCM device data structure.
*/
struct
snd_line6_pcm
*
line6pcm
;
/**
Line6 MIDI device data structure.
Line
6 MIDI device data structure.
*/
struct
snd_line6_midi
*
line6midi
;
...
...
@@ -207,9 +168,6 @@ extern int line6_read_data(struct usb_line6 *line6, int address, void *data,
size_t
datalen
);
extern
int
line6_read_serial_number
(
struct
usb_line6
*
line6
,
int
*
serial_number
);
extern
int
line6_send_program
(
struct
usb_line6
*
line6
,
u8
value
);
extern
int
line6_send_raw_message
(
struct
usb_line6
*
line6
,
const
char
*
buffer
,
int
size
);
extern
int
line6_send_raw_message_async
(
struct
usb_line6
*
line6
,
const
char
*
buffer
,
int
size
);
extern
int
line6_send_sysex_message
(
struct
usb_line6
*
line6
,
...
...
@@ -219,10 +177,19 @@ extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,
extern
void
line6_start_timer
(
struct
timer_list
*
timer
,
unsigned
int
msecs
,
void
(
*
function
)(
unsigned
long
),
unsigned
long
data
);
extern
int
line6_transmit_parameter
(
struct
usb_line6
*
line6
,
int
param
,
u8
value
);
extern
int
line6_version_request_async
(
struct
usb_line6
*
line6
);
extern
int
line6_write_data
(
struct
usb_line6
*
line6
,
int
address
,
void
*
data
,
size_t
datalen
);
int
line6_probe
(
struct
usb_interface
*
interface
,
struct
usb_line6
*
line6
,
const
struct
line6_properties
*
properties
,
int
(
*
private_init
)(
struct
usb_interface
*
,
struct
usb_line6
*
));
void
line6_disconnect
(
struct
usb_interface
*
interface
);
#ifdef CONFIG_PM
int
line6_suspend
(
struct
usb_interface
*
interface
,
pm_message_t
message
);
int
line6_resume
(
struct
usb_interface
*
interface
);
#endif
#endif
sound/usb/line6/midi.c
View file @
86b5f3ec
/*
* Line
6 Linux USB driver - 0.9.1beta
* Line
6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
...
...
@@ -11,13 +11,12 @@
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/export.h>
#include <sound/core.h>
#include <sound/rawmidi.h>
#include "audio.h"
#include "driver.h"
#include "midi.h"
#include "pod.h"
#include "usbdefs.h"
#define line6_rawmidi_substream_midi(substream) \
...
...
@@ -121,16 +120,13 @@ static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
urb
=
usb_alloc_urb
(
0
,
GFP_ATOMIC
);
if
(
urb
==
NULL
)
{
dev_err
(
line6
->
ifcdev
,
"Out of memory
\n
"
);
if
(
urb
==
NULL
)
return
-
ENOMEM
;
}
transfer_buffer
=
kmemdup
(
data
,
length
,
GFP_ATOMIC
);
if
(
transfer_buffer
==
NULL
)
{
usb_free_urb
(
urb
);
dev_err
(
line6
->
ifcdev
,
"Out of memory
\n
"
);
return
-
ENOMEM
;
}
...
...
@@ -223,28 +219,20 @@ static struct snd_rawmidi_ops line6_midi_input_ops = {
.
trigger
=
line6_midi_input_trigger
,
};
/*
Cleanup the Line6 MIDI device.
*/
static
void
line6_cleanup_midi
(
struct
snd_rawmidi
*
rmidi
)
{
}
/* Create a MIDI device */
static
int
snd_line6_new_midi
(
struct
snd_line6_midi
*
line6midi
)
static
int
snd_line6_new_midi
(
struct
usb_line6
*
line6
,
struct
snd_rawmidi
**
rmidi_ret
)
{
struct
snd_rawmidi
*
rmidi
;
int
err
;
err
=
snd_rawmidi_new
(
line6midi
->
line6
->
card
,
"Line6 MIDI"
,
0
,
1
,
1
,
&
rmidi
);
err
=
snd_rawmidi_new
(
line6
->
card
,
"Line 6 MIDI"
,
0
,
1
,
1
,
rmidi_ret
);
if
(
err
<
0
)
return
err
;
rmidi
->
private_data
=
line6midi
;
rmidi
->
private_free
=
line6_cleanup_midi
;
strcpy
(
rmidi
->
id
,
line6midi
->
line6
->
properties
->
id
);
strcpy
(
rmidi
->
name
,
line6midi
->
line6
->
properties
->
name
);
rmidi
=
*
rmidi_ret
;
strcpy
(
rmidi
->
id
,
line6
->
properties
->
id
);
strcpy
(
rmidi
->
name
,
line6
->
properties
->
name
);
rmidi
->
info_flags
=
SNDRV_RAWMIDI_INFO_OUTPUT
|
...
...
@@ -258,25 +246,22 @@ static int snd_line6_new_midi(struct snd_line6_midi *line6midi)
}
/* MIDI device destructor */
static
int
snd_line6_midi_free
(
struct
snd_device
*
device
)
static
void
snd_line6_midi_free
(
struct
snd_rawmidi
*
rmidi
)
{
struct
snd_line6_midi
*
line6midi
=
device
->
devic
e_data
;
struct
snd_line6_midi
*
line6midi
=
rmidi
->
privat
e_data
;
line6_midibuf_destroy
(
&
line6midi
->
midibuf_in
);
line6_midibuf_destroy
(
&
line6midi
->
midibuf_out
);
return
0
;
kfree
(
line6midi
)
;
}
/*
Initialize the Line6 MIDI subsystem.
Initialize the Line
6 MIDI subsystem.
*/
int
line6_init_midi
(
struct
usb_line6
*
line6
)
{
static
struct
snd_device_ops
midi_ops
=
{
.
dev_free
=
snd_line6_midi_free
,
};
int
err
;
struct
snd_rawmidi
*
rmidi
;
struct
snd_line6_midi
*
line6midi
;
if
(
!
(
line6
->
properties
->
capabilities
&
LINE6_CAP_CONTROL
))
{
...
...
@@ -284,38 +269,31 @@ int line6_init_midi(struct usb_line6 *line6)
return
0
;
}
line6midi
=
kzalloc
(
sizeof
(
struct
snd_line6_midi
),
GFP_KERNEL
);
err
=
snd_line6_new_midi
(
line6
,
&
rmidi
);
if
(
err
<
0
)
return
err
;
if
(
line6midi
==
NULL
)
line6midi
=
kzalloc
(
sizeof
(
struct
snd_line6_midi
),
GFP_KERNEL
);
if
(
!
line6midi
)
return
-
ENOMEM
;
err
=
line6_midibuf_init
(
&
line6midi
->
midibuf_in
,
MIDI_BUFFER_SIZE
,
0
);
if
(
err
<
0
)
{
kfree
(
line6midi
);
return
err
;
}
err
=
line6_midibuf_init
(
&
line6midi
->
midibuf_out
,
MIDI_BUFFER_SIZE
,
1
);
if
(
err
<
0
)
{
kfree
(
line6midi
->
midibuf_in
.
buf
);
kfree
(
line6midi
);
return
err
;
}
rmidi
->
private_data
=
line6midi
;
rmidi
->
private_free
=
snd_line6_midi_free
;
init_waitqueue_head
(
&
line6midi
->
send_wait
);
spin_lock_init
(
&
line6midi
->
send_urb_lock
);
spin_lock_init
(
&
line6midi
->
midi_transmit_lock
);
line6midi
->
line6
=
line6
;
line6
->
line6midi
=
line6midi
;
err
=
snd_device_new
(
line6
->
card
,
SNDRV_DEV_RAWMIDI
,
line6midi
,
&
midi_ops
);
err
=
line6_midibuf_init
(
&
line6midi
->
midibuf_in
,
MIDI_BUFFER_SIZE
,
0
);
if
(
err
<
0
)
return
err
;
err
=
snd_line6_new_midi
(
line6midi
);
err
=
line6_midibuf_init
(
&
line6midi
->
midibuf_out
,
MIDI_BUFFER_SIZE
,
1
);
if
(
err
<
0
)
return
err
;
init_waitqueue_head
(
&
line6midi
->
send_wait
);
spin_lock_init
(
&
line6midi
->
send_urb_lock
);
spin_lock_init
(
&
line6midi
->
midi_transmit_lock
);
line6
->
line6midi
=
line6midi
;
return
0
;
}
EXPORT_SYMBOL_GPL
(
line6_init_midi
);
sound/usb/line6/midi.h
View file @
86b5f3ec
/*
* Line
6 Linux USB driver - 0.9.1beta
* Line
6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
...
...
@@ -20,7 +20,7 @@
struct
snd_line6_midi
{
/**
Pointer back to the Line6 driver data structure.
Pointer back to the Line
6 driver data structure.
*/
struct
usb_line6
*
line6
;
...
...
sound/usb/line6/midibuf.c
View file @
86b5f3ec
/*
* Line
6 Linux USB driver - 0.9.1beta
* Line
6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
...
...
@@ -26,7 +26,7 @@ static int midibuf_message_length(unsigned char code)
}
else
{
/*
Note that according to the MIDI specification 0xf2 is
the "Song Position Pointer", but this is used by Line6
the "Song Position Pointer", but this is used by Line
6
to send sysex messages to the host.
*/
static
const
int
length
[]
=
{
-
1
,
2
,
-
1
,
2
,
-
1
,
-
1
,
1
,
1
,
1
,
1
,
...
...
sound/usb/line6/midibuf.h
View file @
86b5f3ec
/*
* Line
6 Linux USB driver - 0.9.1beta
* Line
6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
...
...
sound/usb/line6/pcm.c
View file @
86b5f3ec
/*
* Line
6 Linux USB driver - 0.9.1beta
* Line
6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
...
...
@@ -10,91 +10,85 @@
*/
#include <linux/slab.h>
#include <linux/export.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include "audio.h"
#include "capture.h"
#include "driver.h"
#include "playback.h"
#include "pod.h"
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
static
struct
snd_line6_pcm
*
dev2pcm
(
struct
device
*
dev
)
/* impulse response volume controls */
static
int
snd_line6_impulse_volume_info
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
{
struct
usb_interface
*
interface
=
to_usb_interface
(
dev
);
struct
usb_line6
*
line6
=
usb_get_intfdata
(
interface
);
struct
snd_line6_pcm
*
line6pcm
=
line6
->
line6pcm
;
return
line6pcm
;
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_INTEGER
;
uinfo
->
count
=
1
;
uinfo
->
value
.
integer
.
min
=
0
;
uinfo
->
value
.
integer
.
max
=
255
;
return
0
;
}
/*
"read" request on "impulse_volume" special file.
*/
static
ssize_t
impulse_volume_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
static
int
snd_line6_impulse_volume_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
return
sprintf
(
buf
,
"%d
\n
"
,
dev2pcm
(
dev
)
->
impulse_volume
);
struct
snd_line6_pcm
*
line6pcm
=
snd_kcontrol_chip
(
kcontrol
);
ucontrol
->
value
.
integer
.
value
[
0
]
=
line6pcm
->
impulse_volume
;
return
0
;
}
/*
"write" request on "impulse_volume" special file.
*/
static
ssize_t
impulse_volume_store
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
static
int
snd_line6_impulse_volume_put
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_line6_pcm
*
line6pcm
=
dev2pcm
(
dev
);
int
value
;
int
ret
;
struct
snd_line6_pcm
*
line6pcm
=
snd_kcontrol_chip
(
kcontrol
);
int
value
=
ucontrol
->
value
.
integer
.
value
[
0
];
ret
=
kstrtoint
(
buf
,
10
,
&
value
);
if
(
ret
<
0
)
return
ret
;
if
(
line6pcm
->
impulse_volume
==
value
)
return
0
;
line6pcm
->
impulse_volume
=
value
;
if
(
value
>
0
)
line6_pcm_acquire
(
line6pcm
,
LINE6_BITS_PCM_IMPULSE
);
else
line6_pcm_release
(
line6pcm
,
LINE6_BITS_PCM_IMPULSE
);
return
1
;
}
return
count
;
/* impulse response period controls */
static
int
snd_line6_impulse_period_info
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_INTEGER
;
uinfo
->
count
=
1
;
uinfo
->
value
.
integer
.
min
=
0
;
uinfo
->
value
.
integer
.
max
=
2000
;
return
0
;
}
static
DEVICE_ATTR_RW
(
impulse_volume
);
/*
"read" request on "impulse_period" special file.
*/
static
ssize_t
impulse_period_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
static
int
snd_line6_impulse_period_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
return
sprintf
(
buf
,
"%d
\n
"
,
dev2pcm
(
dev
)
->
impulse_period
);
struct
snd_line6_pcm
*
line6pcm
=
snd_kcontrol_chip
(
kcontrol
);
ucontrol
->
value
.
integer
.
value
[
0
]
=
line6pcm
->
impulse_period
;
return
0
;
}
/*
"write" request on "impulse_period" special file.
*/
static
ssize_t
impulse_period_store
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
const
char
*
buf
,
size_t
count
)
static
int
snd_line6_impulse_period_put
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
int
value
;
int
ret
;
struct
snd_line6_pcm
*
line6pcm
=
snd_kcontrol_chip
(
kcontrol
)
;
int
value
=
ucontrol
->
value
.
integer
.
value
[
0
]
;
ret
=
kstrtoint
(
buf
,
10
,
&
value
);
if
(
ret
<
0
)
return
ret
;
if
(
line6pcm
->
impulse_period
==
value
)
return
0
;
dev2pcm
(
dev
)
->
impulse_period
=
value
;
return
count
;
line6pcm
->
impulse_period
=
value
;
return
1
;
}
static
DEVICE_ATTR_RW
(
impulse_period
);
#endif
static
bool
test_flags
(
unsigned
long
flags0
,
unsigned
long
flags1
,
unsigned
long
mask
)
...
...
@@ -195,6 +189,7 @@ int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels)
line6_pcm_release
(
line6pcm
,
flags_final
&
channels
);
return
err
;
}
EXPORT_SYMBOL_GPL
(
line6_pcm_acquire
);
int
line6_pcm_release
(
struct
snd_line6_pcm
*
line6pcm
,
int
channels
)
{
...
...
@@ -223,6 +218,7 @@ int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels)
return
0
;
}
EXPORT_SYMBOL_GPL
(
line6_pcm_release
);
/* trigger callback */
int
snd_line6_trigger
(
struct
snd_pcm_substream
*
substream
,
int
cmd
)
...
...
@@ -230,19 +226,19 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
struct
snd_line6_pcm
*
line6pcm
=
snd_pcm_substream_chip
(
substream
);
struct
snd_pcm_substream
*
s
;
int
err
;
unsigned
long
flags
;
spin_lock
_irqsave
(
&
line6pcm
->
lock_trigger
,
flags
);
spin_lock
(
&
line6pcm
->
lock_trigger
);
clear_bit
(
LINE6_INDEX_PREPARED
,
&
line6pcm
->
flags
);
snd_pcm_group_for_each_entry
(
s
,
substream
)
{
if
(
s
->
pcm
->
card
!=
substream
->
pcm
->
card
)
continue
;
switch
(
s
->
stream
)
{
case
SNDRV_PCM_STREAM_PLAYBACK
:
err
=
snd_line6_playback_trigger
(
line6pcm
,
cmd
);
if
(
err
<
0
)
{
spin_unlock_irqrestore
(
&
line6pcm
->
lock_trigger
,
flags
);
spin_unlock
(
&
line6pcm
->
lock_trigger
);
return
err
;
}
...
...
@@ -252,8 +248,7 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
err
=
snd_line6_capture_trigger
(
line6pcm
,
cmd
);
if
(
err
<
0
)
{
spin_unlock_irqrestore
(
&
line6pcm
->
lock_trigger
,
flags
);
spin_unlock
(
&
line6pcm
->
lock_trigger
);
return
err
;
}
...
...
@@ -265,7 +260,7 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
}
}
spin_unlock
_irqrestore
(
&
line6pcm
->
lock_trigger
,
flags
);
spin_unlock
(
&
line6pcm
->
lock_trigger
);
return
0
;
}
...
...
@@ -312,14 +307,28 @@ static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol,
}
/* control definition */
static
struct
snd_kcontrol_new
line6_control_playback
=
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"PCM Playback Volume"
,
.
index
=
0
,
.
access
=
SNDRV_CTL_ELEM_ACCESS_READWRITE
,
.
info
=
snd_line6_control_playback_info
,
.
get
=
snd_line6_control_playback_get
,
.
put
=
snd_line6_control_playback_put
static
struct
snd_kcontrol_new
line6_controls
[]
=
{
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"PCM Playback Volume"
,
.
info
=
snd_line6_control_playback_info
,
.
get
=
snd_line6_control_playback_get
,
.
put
=
snd_line6_control_playback_put
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"Impulse Response Volume"
,
.
info
=
snd_line6_impulse_volume_info
,
.
get
=
snd_line6_impulse_volume_get
,
.
put
=
snd_line6_impulse_volume_put
},
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"Impulse Response Period"
,
.
info
=
snd_line6_impulse_period_info
,
.
get
=
snd_line6_impulse_period_get
,
.
put
=
snd_line6_impulse_period_put
},
};
/*
...
...
@@ -330,11 +339,6 @@ static void line6_cleanup_pcm(struct snd_pcm *pcm)
int
i
;
struct
snd_line6_pcm
*
line6pcm
=
snd_pcm_chip
(
pcm
);
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
device_remove_file
(
line6pcm
->
line6
->
ifcdev
,
&
dev_attr_impulse_volume
);
device_remove_file
(
line6pcm
->
line6
->
ifcdev
,
&
dev_attr_impulse_period
);
#endif
for
(
i
=
LINE6_ISO_BUFFERS
;
i
--
;)
{
if
(
line6pcm
->
urb_audio_out
[
i
])
{
usb_kill_urb
(
line6pcm
->
urb_audio_out
[
i
]);
...
...
@@ -345,24 +349,21 @@ static void line6_cleanup_pcm(struct snd_pcm *pcm)
usb_free_urb
(
line6pcm
->
urb_audio_in
[
i
]);
}
}
kfree
(
line6pcm
);
}
/* create a PCM device */
static
int
snd_line6_new_pcm
(
struct
snd_line6_pcm
*
line6pcm
)
static
int
snd_line6_new_pcm
(
struct
usb_line6
*
line6
,
struct
snd_pcm
**
pcm_ret
)
{
struct
snd_pcm
*
pcm
;
int
err
;
err
=
snd_pcm_new
(
line6pcm
->
line6
->
card
,
(
char
*
)
line6pcm
->
line6
->
properties
->
name
,
0
,
1
,
1
,
&
pcm
);
err
=
snd_pcm_new
(
line6
->
card
,
(
char
*
)
line6
->
properties
->
name
,
0
,
1
,
1
,
pcm_ret
);
if
(
err
<
0
)
return
err
;
pcm
->
private_data
=
line6pcm
;
pcm
->
private_free
=
line6_cleanup_pcm
;
line6pcm
->
pcm
=
pcm
;
strcpy
(
pcm
->
name
,
line6pcm
->
line6
->
properties
->
name
);
pcm
=
*
pcm_ret
;
strcpy
(
pcm
->
name
,
line6
->
properties
->
name
);
/* set operators */
snd_pcm_set_ops
(
pcm
,
SNDRV_PCM_STREAM_PLAYBACK
,
...
...
@@ -374,37 +375,14 @@ static int snd_line6_new_pcm(struct snd_line6_pcm *line6pcm)
snd_dma_continuous_data
(
GFP_KERNEL
),
64
*
1024
,
128
*
1024
);
return
0
;
}
/* PCM device destructor */
static
int
snd_line6_pcm_free
(
struct
snd_device
*
device
)
{
return
0
;
}
/*
Stop substream if still running.
*/
static
void
pcm_disconnect_substream
(
struct
snd_pcm_substream
*
substream
)
{
if
(
substream
->
runtime
&&
snd_pcm_running
(
substream
))
{
snd_pcm_stream_lock_irq
(
substream
);
snd_pcm_stop
(
substream
,
SNDRV_PCM_STATE_DISCONNECTED
);
snd_pcm_stream_unlock_irq
(
substream
);
}
}
/*
Stop PCM stream.
Sync with PCM stream stops.
*/
void
line6_pcm_disconnect
(
struct
snd_line6_pcm
*
line6pcm
)
{
pcm_disconnect_substream
(
get_substream
(
line6pcm
,
SNDRV_PCM_STREAM_CAPTURE
));
pcm_disconnect_substream
(
get_substream
(
line6pcm
,
SNDRV_PCM_STREAM_PLAYBACK
));
line6_unlink_wait_clear_audio_out_urbs
(
line6pcm
);
line6_unlink_wait_clear_audio_in_urbs
(
line6pcm
);
}
...
...
@@ -416,23 +394,25 @@ void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)
int
line6_init_pcm
(
struct
usb_line6
*
line6
,
struct
line6_pcm_properties
*
properties
)
{
static
struct
snd_device_ops
pcm_ops
=
{
.
dev_free
=
snd_line6_pcm_free
,
};
int
err
;
int
i
,
err
;
unsigned
ep_read
=
line6
->
properties
->
ep_audio_r
;
unsigned
ep_write
=
line6
->
properties
->
ep_audio_w
;
struct
snd_pcm
*
pcm
;
struct
snd_line6_pcm
*
line6pcm
;
if
(
!
(
line6
->
properties
->
capabilities
&
LINE6_CAP_PCM
))
return
0
;
/* skip PCM initialization and report success */
line6pcm
=
kzalloc
(
sizeof
(
*
line6pcm
),
GFP_KERNEL
);
err
=
snd_line6_new_pcm
(
line6
,
&
pcm
);
if
(
err
<
0
)
return
err
;
if
(
line6pcm
==
NULL
)
line6pcm
=
kzalloc
(
sizeof
(
*
line6pcm
),
GFP_KERNEL
);
if
(
!
line6pcm
)
return
-
ENOMEM
;
line6pcm
->
pcm
=
pcm
;
line6pcm
->
properties
=
properties
;
line6pcm
->
volume_playback
[
0
]
=
line6pcm
->
volume_playback
[
1
]
=
255
;
line6pcm
->
volume_monitor
=
255
;
line6pcm
->
line6
=
line6
;
...
...
@@ -444,21 +424,15 @@ int line6_init_pcm(struct usb_line6 *line6,
usb_maxpacket
(
line6
->
usbdev
,
usb_sndisocpipe
(
line6
->
usbdev
,
ep_write
),
1
));
line6pcm
->
properties
=
properties
;
line6
->
line6pcm
=
line6pcm
;
/* PCM device: */
err
=
snd_device_new
(
line6
->
card
,
SNDRV_DEV_PCM
,
line6
,
&
pcm_ops
);
if
(
err
<
0
)
return
err
;
err
=
snd_line6_new_pcm
(
line6pcm
);
if
(
err
<
0
)
return
err
;
spin_lock_init
(
&
line6pcm
->
lock_audio_out
);
spin_lock_init
(
&
line6pcm
->
lock_audio_in
);
spin_lock_init
(
&
line6pcm
->
lock_trigger
);
line6pcm
->
impulse_period
=
LINE6_IMPULSE_DEFAULT_PERIOD
;
line6
->
line6pcm
=
line6pcm
;
pcm
->
private_data
=
line6pcm
;
pcm
->
private_free
=
line6_cleanup_pcm
;
err
=
line6_create_audio_out_urbs
(
line6pcm
);
if
(
err
<
0
)
...
...
@@ -469,27 +443,16 @@ int line6_init_pcm(struct usb_line6 *line6,
return
err
;
/* mixer: */
err
=
snd_ctl_add
(
line6
->
card
,
snd_ctl_new1
(
&
line6_control_playback
,
line6pcm
));
if
(
err
<
0
)
return
err
;
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
/* impulse response test: */
err
=
device_create_file
(
line6
->
ifcdev
,
&
dev_attr_impulse_volume
);
if
(
err
<
0
)
return
err
;
err
=
device_create_file
(
line6
->
ifcdev
,
&
dev_attr_impulse_period
);
if
(
err
<
0
)
return
err
;
line6pcm
->
impulse_period
=
LINE6_IMPULSE_DEFAULT_PERIOD
;
#endif
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
line6_controls
);
i
++
)
{
err
=
snd_ctl_add
(
line6
->
card
,
snd_ctl_new1
(
&
line6_controls
[
i
],
line6pcm
));
if
(
err
<
0
)
return
err
;
}
return
0
;
}
EXPORT_SYMBOL_GPL
(
line6_init_pcm
);
/* prepare pcm callback */
int
snd_line6_prepare
(
struct
snd_pcm_substream
*
substream
)
...
...
@@ -508,9 +471,6 @@ int snd_line6_prepare(struct snd_pcm_substream *substream)
line6_unlink_wait_clear_audio_in_urbs
(
line6pcm
);
break
;
default:
MISSING_CASE
;
}
if
(
!
test_and_set_bit
(
LINE6_INDEX_PREPARED
,
&
line6pcm
->
flags
))
{
...
...
sound/usb/line6/pcm.h
View file @
86b5f3ec
/*
* Line
6 Linux USB driver - 0.9.1beta
* Line
6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
...
...
@@ -26,7 +26,7 @@
/*
number of USB frames per URB
The Line6 Windows driver always transmits two frames per packet, but
The Line
6 Windows driver always transmits two frames per packet, but
the Linux driver performs significantly better (i.e., lower latency)
with only one frame per packet.
*/
...
...
@@ -35,12 +35,10 @@
/* in a "full speed" device (such as the PODxt Pro) this means 1ms */
#define LINE6_ISO_INTERVAL 1
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
#define LINE6_IMPULSE_DEFAULT_PERIOD 100
#endif
/*
Get substream from Line6 PCM data structure
Get substream from Line
6 PCM data structure
*/
#define get_substream(line6pcm, stream) \
(line6pcm->pcm->streams[stream].substream)
...
...
@@ -48,7 +46,7 @@
/*
PCM mode bits.
There are several features of the Line6 USB driver which require PCM
There are several features of the Line
6 USB driver which require PCM
data to be exchanged with the device:
*) PCM playback and capture via ALSA
*) software monitoring (for devices without hardware monitoring)
...
...
@@ -89,12 +87,10 @@ enum {
LINE6_INDEX_PCM_MONITOR_PLAYBACK_STREAM
,
LINE6_INDEX_PCM_MONITOR_CAPTURE_BUFFER
,
LINE6_INDEX_PCM_MONITOR_CAPTURE_STREAM
,
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
LINE6_INDEX_PCM_IMPULSE_PLAYBACK_BUFFER
,
LINE6_INDEX_PCM_IMPULSE_PLAYBACK_STREAM
,
LINE6_INDEX_PCM_IMPULSE_CAPTURE_BUFFER
,
LINE6_INDEX_PCM_IMPULSE_CAPTURE_STREAM
,
#endif
LINE6_INDEX_PAUSE_PLAYBACK
,
LINE6_INDEX_PREPARED
,
...
...
@@ -109,12 +105,10 @@ enum {
LINE6_BIT
(
PCM_MONITOR_PLAYBACK_STREAM
),
LINE6_BIT
(
PCM_MONITOR_CAPTURE_BUFFER
),
LINE6_BIT
(
PCM_MONITOR_CAPTURE_STREAM
),
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
LINE6_BIT
(
PCM_IMPULSE_PLAYBACK_BUFFER
),
LINE6_BIT
(
PCM_IMPULSE_PLAYBACK_STREAM
),
LINE6_BIT
(
PCM_IMPULSE_CAPTURE_BUFFER
),
LINE6_BIT
(
PCM_IMPULSE_CAPTURE_STREAM
),
#endif
LINE6_BIT
(
PAUSE_PLAYBACK
),
LINE6_BIT
(
PREPARED
),
...
...
@@ -133,40 +127,30 @@ enum {
LINE6_BIT_PCM_MONITOR_CAPTURE_BUFFER
|
LINE6_BIT_PCM_MONITOR_CAPTURE_STREAM
,
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
LINE6_BITS_PCM_IMPULSE
=
LINE6_BIT_PCM_IMPULSE_PLAYBACK_BUFFER
|
LINE6_BIT_PCM_IMPULSE_PLAYBACK_STREAM
|
LINE6_BIT_PCM_IMPULSE_CAPTURE_BUFFER
|
LINE6_BIT_PCM_IMPULSE_CAPTURE_STREAM
,
#endif
/* combined bit masks (by direction): */
LINE6_BITS_PLAYBACK_BUFFER
=
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
LINE6_BIT_PCM_IMPULSE_PLAYBACK_BUFFER
|
#endif
LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER
|
LINE6_BIT_PCM_MONITOR_PLAYBACK_BUFFER
,
LINE6_BITS_PLAYBACK_STREAM
=
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
LINE6_BIT_PCM_IMPULSE_PLAYBACK_STREAM
|
#endif
LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM
|
LINE6_BIT_PCM_MONITOR_PLAYBACK_STREAM
,
LINE6_BITS_CAPTURE_BUFFER
=
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
LINE6_BIT_PCM_IMPULSE_CAPTURE_BUFFER
|
#endif
LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER
|
LINE6_BIT_PCM_MONITOR_CAPTURE_BUFFER
,
LINE6_BITS_CAPTURE_STREAM
=
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
LINE6_BIT_PCM_IMPULSE_CAPTURE_STREAM
|
#endif
LINE6_BIT_PCM_ALSA_CAPTURE_STREAM
|
LINE6_BIT_PCM_MONITOR_CAPTURE_STREAM
,
...
...
@@ -183,7 +167,7 @@ struct line6_pcm_properties {
struct
snd_line6_pcm
{
/**
Pointer back to the Line6 driver data structure.
Pointer back to the Line
6 driver data structure.
*/
struct
usb_line6
*
line6
;
...
...
@@ -338,7 +322,6 @@ struct snd_line6_pcm {
*/
int
volume_monitor
;
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
/**
Volume of impulse response test signal (if zero, test is disabled).
*/
...
...
@@ -353,7 +336,6 @@ struct snd_line6_pcm {
Counter for impulse response test signal.
*/
int
impulse_count
;
#endif
/**
Several status bits (see LINE6_BIT_*).
...
...
sound/usb/line6/playback.c
View file @
86b5f3ec
/*
* Line
6 Linux USB driver - 0.9.1beta
* Line
6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
...
...
@@ -14,11 +14,9 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include "audio.h"
#include "capture.h"
#include "driver.h"
#include "pcm.h"
#include "pod.h"
#include "playback.h"
/*
...
...
@@ -61,8 +59,6 @@ static void change_volume(struct urb *urb_out, int volume[],
}
}
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
/*
Create signal for impulse response test.
*/
...
...
@@ -106,8 +102,6 @@ static void create_impulse_test_signal(struct snd_line6_pcm *line6pcm,
}
}
#endif
/*
Add signal to buffer for software monitoring.
*/
...
...
@@ -244,7 +238,6 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
change_volume
(
urb_out
,
line6pcm
->
volume_playback
,
bytes_per_frame
);
if
(
line6pcm
->
prev_fbuf
!=
NULL
)
{
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
if
(
line6pcm
->
flags
&
LINE6_BITS_PCM_IMPULSE
)
{
create_impulse_test_signal
(
line6pcm
,
urb_out
,
bytes_per_frame
);
...
...
@@ -258,7 +251,6 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
urb_out
->
transfer_buffer_length
);
}
}
else
{
#endif
if
(
!
(
line6pcm
->
line6
->
properties
->
capabilities
&
LINE6_CAP_HWMON
)
...
...
@@ -267,9 +259,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
add_monitor_signal
(
urb_out
,
line6pcm
->
prev_fbuf
,
line6pcm
->
volume_monitor
,
bytes_per_frame
);
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
}
#endif
}
ret
=
usb_submit_urb
(
urb_out
,
GFP_ATOMIC
);
...
...
@@ -499,9 +489,7 @@ int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd)
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
#ifdef CONFIG_PM
case
SNDRV_PCM_TRIGGER_RESUME
:
#endif
err
=
line6_pcm_acquire
(
line6pcm
,
LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM
);
...
...
@@ -511,9 +499,7 @@ int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd)
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
#ifdef CONFIG_PM
case
SNDRV_PCM_TRIGGER_SUSPEND
:
#endif
err
=
line6_pcm_release
(
line6pcm
,
LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM
);
...
...
@@ -571,10 +557,8 @@ int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm)
urb
=
line6pcm
->
urb_audio_out
[
i
]
=
usb_alloc_urb
(
LINE6_ISO_PACKETS
,
GFP_KERNEL
);
if
(
urb
==
NULL
)
{
dev_err
(
line6
->
ifcdev
,
"Out of memory
\n
"
);
if
(
urb
==
NULL
)
return
-
ENOMEM
;
}
urb
->
dev
=
line6
->
usbdev
;
urb
->
pipe
=
...
...
sound/usb/line6/playback.h
View file @
86b5f3ec
/*
* Line
6 Linux USB driver - 0.9.1beta
* Line
6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
...
...
sound/usb/line6/pod.c
View file @
86b5f3ec
/*
* Line
6 Linux USB driver - 0.9.1beta
* Line
6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
...
...
@@ -11,13 +11,93 @@
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <sound/core.h>
#include <sound/control.h>
#include "audio.h"
#include "capture.h"
#include "driver.h"
#include "playback.h"
#include "pod.h"
#include "usbdefs.h"
/*
Locate name in binary program dump
*/
#define POD_NAME_OFFSET 0
#define POD_NAME_LENGTH 16
/*
Other constants
*/
#define POD_CONTROL_SIZE 0x80
#define POD_BUFSIZE_DUMPREQ 7
#define POD_STARTUP_DELAY 1000
/*
Stages of POD startup procedure
*/
enum
{
POD_STARTUP_INIT
=
1
,
POD_STARTUP_VERSIONREQ
,
POD_STARTUP_WORKQUEUE
,
POD_STARTUP_SETUP
,
POD_STARTUP_LAST
=
POD_STARTUP_SETUP
-
1
};
enum
{
LINE6_BASSPODXT
,
LINE6_BASSPODXTLIVE
,
LINE6_BASSPODXTPRO
,
LINE6_POCKETPOD
,
LINE6_PODXT
,
LINE6_PODXTLIVE_POD
,
LINE6_PODXTPRO
,
};
struct
usb_line6_pod
{
/**
Generic Line 6 USB data.
*/
struct
usb_line6
line6
;
/**
Instrument monitor level.
*/
int
monitor_level
;
/**
Timer for device initializaton.
*/
struct
timer_list
startup_timer
;
/**
Work handler for device initializaton.
*/
struct
work_struct
startup_work
;
/**
Current progress in startup procedure.
*/
int
startup_progress
;
/**
Serial number of device.
*/
int
serial_number
;
/**
Firmware version (x 100).
*/
int
firmware_version
;
/**
Device ID.
*/
int
device_id
;
};
#define POD_SYSEX_CODE 3
#define POD_BYTES_PER_FRAME 6
/* 24bit audio (stereo) */
...
...
@@ -72,9 +152,6 @@ static struct line6_pcm_properties pod_pcm_properties = {
SNDRV_PCM_INFO_BLOCK_TRANSFER
|
SNDRV_PCM_INFO_MMAP_VALID
|
SNDRV_PCM_INFO_PAUSE
|
#ifdef CONFIG_PM
SNDRV_PCM_INFO_RESUME
|
#endif
SNDRV_PCM_INFO_SYNC_START
),
.
formats
=
SNDRV_PCM_FMTBIT_S24_3LE
,
.
rates
=
SNDRV_PCM_RATE_KNOT
,
...
...
@@ -92,9 +169,6 @@ static struct line6_pcm_properties pod_pcm_properties = {
SNDRV_PCM_INFO_INTERLEAVED
|
SNDRV_PCM_INFO_BLOCK_TRANSFER
|
SNDRV_PCM_INFO_MMAP_VALID
|
#ifdef CONFIG_PM
SNDRV_PCM_INFO_RESUME
|
#endif
SNDRV_PCM_INFO_SYNC_START
),
.
formats
=
SNDRV_PCM_FMTBIT_S24_3LE
,
.
rates
=
SNDRV_PCM_RATE_KNOT
,
...
...
@@ -265,7 +339,7 @@ static void pod_startup4(struct work_struct *work)
line6_read_serial_number
(
&
pod
->
line6
,
&
pod
->
serial_number
);
/* ALSA audio interface: */
line6_register_audio
(
line6
);
snd_card_register
(
line6
->
card
);
}
/* POD special files: */
...
...
@@ -322,21 +396,6 @@ static struct snd_kcontrol_new pod_control_monitor = {
.
put
=
snd_pod_control_monitor_put
};
/*
POD destructor.
*/
static
void
pod_destruct
(
struct
usb_interface
*
interface
)
{
struct
usb_line6_pod
*
pod
=
usb_get_intfdata
(
interface
);
if
(
pod
==
NULL
)
return
;
line6_cleanup_audio
(
&
pod
->
line6
);
del_timer
(
&
pod
->
startup_timer
);
cancel_work_sync
(
&
pod
->
startup_work
);
}
/*
POD device disconnected.
*/
...
...
@@ -349,21 +408,18 @@ static void line6_pod_disconnect(struct usb_interface *interface)
pod
=
usb_get_intfdata
(
interface
);
if
(
pod
!=
NULL
)
{
struct
snd_line6_pcm
*
line6pcm
=
pod
->
line6
.
line6pcm
;
struct
device
*
dev
=
&
interface
->
dev
;
if
(
line6pcm
!=
NULL
)
line6_pcm_disconnect
(
line6pcm
);
if
(
dev
!=
NULL
)
{
/* remove sysfs entries: */
device_remove_file
(
dev
,
&
dev_attr_device_id
);
device_remove_file
(
dev
,
&
dev_attr_firmware_version
);
device_remove_file
(
dev
,
&
dev_attr_serial_number
);
}
}
pod_destruct
(
interface
);
del_timer_sync
(
&
pod
->
startup_timer
);
cancel_work_sync
(
&
pod
->
startup_work
);
}
}
/*
...
...
@@ -373,17 +429,23 @@ static int pod_create_files2(struct device *dev)
{
int
err
;
CHECK_RETURN
(
device_create_file
(
dev
,
&
dev_attr_device_id
));
CHECK_RETURN
(
device_create_file
(
dev
,
&
dev_attr_firmware_version
));
CHECK_RETURN
(
device_create_file
(
dev
,
&
dev_attr_serial_number
));
err
=
device_create_file
(
dev
,
&
dev_attr_device_id
);
if
(
err
<
0
)
return
err
;
err
=
device_create_file
(
dev
,
&
dev_attr_firmware_version
);
if
(
err
<
0
)
return
err
;
err
=
device_create_file
(
dev
,
&
dev_attr_serial_number
);
if
(
err
<
0
)
return
err
;
return
0
;
}
/*
Try to init POD device.
*/
static
int
pod_
try_
init
(
struct
usb_interface
*
interface
,
struct
usb_line6
*
line6
)
static
int
pod_init
(
struct
usb_interface
*
interface
,
struct
usb_line6
*
line6
)
{
int
err
;
struct
usb_line6_pod
*
pod
=
(
struct
usb_line6_pod
*
)
line6
;
...
...
@@ -402,11 +464,6 @@ static int pod_try_init(struct usb_interface *interface,
if
(
err
<
0
)
return
err
;
/* initialize audio system: */
err
=
line6_init_audio
(
line6
);
if
(
err
<
0
)
return
err
;
/* initialize MIDI subsystem: */
err
=
line6_init_midi
(
line6
);
if
(
err
<
0
)
...
...
@@ -439,15 +496,136 @@ static int pod_try_init(struct usb_interface *interface,
return
0
;
}
#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
/* table of devices that work with this driver */
static
const
struct
usb_device_id
pod_id_table
[]
=
{
{
LINE6_DEVICE
(
0x4250
),
.
driver_info
=
LINE6_BASSPODXT
},
{
LINE6_DEVICE
(
0x4642
),
.
driver_info
=
LINE6_BASSPODXTLIVE
},
{
LINE6_DEVICE
(
0x4252
),
.
driver_info
=
LINE6_BASSPODXTPRO
},
{
LINE6_IF_NUM
(
0x5051
,
1
),
.
driver_info
=
LINE6_POCKETPOD
},
{
LINE6_DEVICE
(
0x5044
),
.
driver_info
=
LINE6_PODXT
},
{
LINE6_IF_NUM
(
0x4650
,
0
),
.
driver_info
=
LINE6_PODXTLIVE_POD
},
{
LINE6_DEVICE
(
0x5050
),
.
driver_info
=
LINE6_PODXTPRO
},
{}
};
MODULE_DEVICE_TABLE
(
usb
,
pod_id_table
);
static
const
struct
line6_properties
pod_properties_table
[]
=
{
[
LINE6_BASSPODXT
]
=
{
.
id
=
"BassPODxt"
,
.
name
=
"BassPODxt"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
5
,
.
ep_ctrl_r
=
0x84
,
.
ep_ctrl_w
=
0x03
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_BASSPODXTLIVE
]
=
{
.
id
=
"BassPODxtLive"
,
.
name
=
"BassPODxt Live"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
1
,
.
ep_ctrl_r
=
0x84
,
.
ep_ctrl_w
=
0x03
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_BASSPODXTPRO
]
=
{
.
id
=
"BassPODxtPro"
,
.
name
=
"BassPODxt Pro"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
5
,
.
ep_ctrl_r
=
0x84
,
.
ep_ctrl_w
=
0x03
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_POCKETPOD
]
=
{
.
id
=
"PocketPOD"
,
.
name
=
"Pocket POD"
,
.
capabilities
=
LINE6_CAP_CONTROL
,
.
altsetting
=
0
,
.
ep_ctrl_r
=
0x82
,
.
ep_ctrl_w
=
0x02
,
/* no audio channel */
},
[
LINE6_PODXT
]
=
{
.
id
=
"PODxt"
,
.
name
=
"PODxt"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
5
,
.
ep_ctrl_r
=
0x84
,
.
ep_ctrl_w
=
0x03
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_PODXTLIVE_POD
]
=
{
.
id
=
"PODxtLive"
,
.
name
=
"PODxt Live"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
1
,
.
ep_ctrl_r
=
0x84
,
.
ep_ctrl_w
=
0x03
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_PODXTPRO
]
=
{
.
id
=
"PODxtPro"
,
.
name
=
"PODxt Pro"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
5
,
.
ep_ctrl_r
=
0x84
,
.
ep_ctrl_w
=
0x03
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
};
/*
Init POD device (and clean up in case of failure)
.
Probe USB device
.
*/
int
line6_pod_init
(
struct
usb_interface
*
interface
,
struct
usb_line6
*
line6
)
static
int
pod_probe
(
struct
usb_interface
*
interface
,
const
struct
usb_device_id
*
id
)
{
int
err
=
pod_try_init
(
interface
,
line6
);
if
(
err
<
0
)
pod_destruct
(
interface
);
struct
usb_line6_pod
*
pod
;
return
err
;
pod
=
kzalloc
(
sizeof
(
*
pod
),
GFP_KERNEL
);
if
(
!
pod
)
return
-
ENODEV
;
return
line6_probe
(
interface
,
&
pod
->
line6
,
&
pod_properties_table
[
id
->
driver_info
],
pod_init
);
}
static
struct
usb_driver
pod_driver
=
{
.
name
=
KBUILD_MODNAME
,
.
probe
=
pod_probe
,
.
disconnect
=
line6_disconnect
,
#ifdef CONFIG_PM
.
suspend
=
line6_suspend
,
.
resume
=
line6_resume
,
.
reset_resume
=
line6_resume
,
#endif
.
id_table
=
pod_id_table
,
};
module_usb_driver
(
pod_driver
);
MODULE_DESCRIPTION
(
"Line 6 POD USB driver"
);
MODULE_LICENSE
(
"GPL"
);
sound/usb/line6/pod.h
deleted
100644 → 0
View file @
2a52b6ee
/*
* Line6 Linux USB driver - 0.9.1beta
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
* 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, version 2.
*
*/
#ifndef POD_H
#define POD_H
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/usb.h>
#include <sound/core.h>
#include "driver.h"
/*
Locate name in binary program dump
*/
#define POD_NAME_OFFSET 0
#define POD_NAME_LENGTH 16
/*
Other constants
*/
#define POD_CONTROL_SIZE 0x80
#define POD_BUFSIZE_DUMPREQ 7
#define POD_STARTUP_DELAY 1000
/*
Stages of POD startup procedure
*/
enum
{
POD_STARTUP_INIT
=
1
,
POD_STARTUP_VERSIONREQ
,
POD_STARTUP_WORKQUEUE
,
POD_STARTUP_SETUP
,
POD_STARTUP_LAST
=
POD_STARTUP_SETUP
-
1
};
struct
usb_line6_pod
{
/**
Generic Line6 USB data.
*/
struct
usb_line6
line6
;
/**
Instrument monitor level.
*/
int
monitor_level
;
/**
Timer for device initializaton.
*/
struct
timer_list
startup_timer
;
/**
Work handler for device initializaton.
*/
struct
work_struct
startup_work
;
/**
Current progress in startup procedure.
*/
int
startup_progress
;
/**
Serial number of device.
*/
int
serial_number
;
/**
Firmware version (x 100).
*/
int
firmware_version
;
/**
Device ID.
*/
int
device_id
;
};
extern
int
line6_pod_init
(
struct
usb_interface
*
interface
,
struct
usb_line6
*
line6
);
#endif
sound/usb/line6/podhd.c
View file @
86b5f3ec
/*
* Line6 Pod HD
* Line
6 Pod HD
*
* Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com>
*
...
...
@@ -9,13 +9,29 @@
*
*/
#include <linux/usb.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include "audio.h"
#include "driver.h"
#include "pcm.h"
#include "podhd.h"
#include "usbdefs.h"
enum
{
LINE6_PODHD300
,
LINE6_PODHD400
,
LINE6_PODHD500_0
,
LINE6_PODHD500_1
,
};
struct
usb_line6_podhd
{
/**
Generic Line 6 USB data.
*/
struct
usb_line6
line6
;
};
#define PODHD_BYTES_PER_FRAME 6
/* 24bit audio (stereo) */
...
...
@@ -33,9 +49,6 @@ static struct line6_pcm_properties podhd_pcm_properties = {
SNDRV_PCM_INFO_BLOCK_TRANSFER
|
SNDRV_PCM_INFO_MMAP_VALID
|
SNDRV_PCM_INFO_PAUSE
|
#ifdef CONFIG_PM
SNDRV_PCM_INFO_RESUME
|
#endif
SNDRV_PCM_INFO_SYNC_START
),
.
formats
=
SNDRV_PCM_FMTBIT_S24_3LE
,
.
rates
=
SNDRV_PCM_RATE_48000
,
...
...
@@ -53,9 +66,6 @@ static struct line6_pcm_properties podhd_pcm_properties = {
SNDRV_PCM_INFO_INTERLEAVED
|
SNDRV_PCM_INFO_BLOCK_TRANSFER
|
SNDRV_PCM_INFO_MMAP_VALID
|
#ifdef CONFIG_PM
SNDRV_PCM_INFO_RESUME
|
#endif
SNDRV_PCM_INFO_SYNC_START
),
.
formats
=
SNDRV_PCM_FMTBIT_S24_3LE
,
.
rates
=
SNDRV_PCM_RATE_48000
,
...
...
@@ -74,58 +84,18 @@ static struct line6_pcm_properties podhd_pcm_properties = {
.
bytes_per_frame
=
PODHD_BYTES_PER_FRAME
};
/*
POD HD destructor.
*/
static
void
podhd_destruct
(
struct
usb_interface
*
interface
)
{
struct
usb_line6_podhd
*
podhd
=
usb_get_intfdata
(
interface
);
if
(
podhd
==
NULL
)
return
;
line6_cleanup_audio
(
&
podhd
->
line6
);
}
/*
POD HD device disconnected.
*/
static
void
line6_podhd_disconnect
(
struct
usb_interface
*
interface
)
{
struct
usb_line6_podhd
*
podhd
;
if
(
interface
==
NULL
)
return
;
podhd
=
usb_get_intfdata
(
interface
);
if
(
podhd
!=
NULL
)
{
struct
snd_line6_pcm
*
line6pcm
=
podhd
->
line6
.
line6pcm
;
if
(
line6pcm
!=
NULL
)
line6_pcm_disconnect
(
line6pcm
);
}
podhd_destruct
(
interface
);
}
/*
Try to init POD HD device.
*/
static
int
podhd_
try_
init
(
struct
usb_interface
*
interface
,
struct
usb_line6_podhd
*
podhd
)
static
int
podhd_init
(
struct
usb_interface
*
interface
,
struct
usb_line6
*
line6
)
{
struct
usb_line6_podhd
*
podhd
=
(
struct
usb_line6_podhd
*
)
line6
;
int
err
;
struct
usb_line6
*
line6
=
&
podhd
->
line6
;
if
((
interface
==
NULL
)
||
(
podhd
==
NULL
))
return
-
ENODEV
;
line6
->
disconnect
=
line6_podhd_disconnect
;
/* initialize audio system: */
err
=
line6_init_audio
(
line6
);
if
(
err
<
0
)
return
err
;
/* initialize MIDI subsystem: */
err
=
line6_init_midi
(
line6
);
if
(
err
<
0
)
...
...
@@ -137,20 +107,103 @@ static int podhd_try_init(struct usb_interface *interface,
return
err
;
/* register USB audio system: */
err
=
line6_register_audio
(
line6
);
return
err
;
return
snd_card_register
(
line6
->
card
);
}
#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
/* table of devices that work with this driver */
static
const
struct
usb_device_id
podhd_id_table
[]
=
{
{
LINE6_DEVICE
(
0x5057
),
.
driver_info
=
LINE6_PODHD300
},
{
LINE6_DEVICE
(
0x5058
),
.
driver_info
=
LINE6_PODHD400
},
{
LINE6_IF_NUM
(
0x414D
,
0
),
.
driver_info
=
LINE6_PODHD500_0
},
{
LINE6_IF_NUM
(
0x414D
,
1
),
.
driver_info
=
LINE6_PODHD500_1
},
{}
};
MODULE_DEVICE_TABLE
(
usb
,
podhd_id_table
);
static
const
struct
line6_properties
podhd_properties_table
[]
=
{
[
LINE6_PODHD300
]
=
{
.
id
=
"PODHD300"
,
.
name
=
"POD HD300"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
5
,
.
ep_ctrl_r
=
0x84
,
.
ep_ctrl_w
=
0x03
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_PODHD400
]
=
{
.
id
=
"PODHD400"
,
.
name
=
"POD HD400"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
5
,
.
ep_ctrl_r
=
0x84
,
.
ep_ctrl_w
=
0x03
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_PODHD500_0
]
=
{
.
id
=
"PODHD500"
,
.
name
=
"POD HD500"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
1
,
.
ep_ctrl_r
=
0x81
,
.
ep_ctrl_w
=
0x01
,
.
ep_audio_r
=
0x86
,
.
ep_audio_w
=
0x02
,
},
[
LINE6_PODHD500_1
]
=
{
.
id
=
"PODHD500"
,
.
name
=
"POD HD500"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
1
,
.
ep_ctrl_r
=
0x81
,
.
ep_ctrl_w
=
0x01
,
.
ep_audio_r
=
0x86
,
.
ep_audio_w
=
0x02
,
},
};
/*
Init POD HD device (and clean up in case of failure)
.
Probe USB device
.
*/
int
line6_podhd_init
(
struct
usb_interface
*
interface
,
struct
usb_line6
*
line6
)
static
int
podhd_probe
(
struct
usb_interface
*
interface
,
const
struct
usb_device_id
*
id
)
{
struct
usb_line6_podhd
*
podhd
=
(
struct
usb_line6_podhd
*
)
line6
;
int
err
=
podhd_try_init
(
interface
,
podhd
);
if
(
err
<
0
)
podhd_destruct
(
interface
);
struct
usb_line6_podhd
*
podhd
;
return
err
;
podhd
=
kzalloc
(
sizeof
(
*
podhd
),
GFP_KERNEL
);
if
(
!
podhd
)
return
-
ENODEV
;
return
line6_probe
(
interface
,
&
podhd
->
line6
,
&
podhd_properties_table
[
id
->
driver_info
],
podhd_init
);
}
static
struct
usb_driver
podhd_driver
=
{
.
name
=
KBUILD_MODNAME
,
.
probe
=
podhd_probe
,
.
disconnect
=
line6_disconnect
,
#ifdef CONFIG_PM
.
suspend
=
line6_suspend
,
.
resume
=
line6_resume
,
.
reset_resume
=
line6_resume
,
#endif
.
id_table
=
podhd_id_table
,
};
module_usb_driver
(
podhd_driver
);
MODULE_DESCRIPTION
(
"Line 6 PODHD USB driver"
);
MODULE_LICENSE
(
"GPL"
);
sound/usb/line6/podhd.h
deleted
100644 → 0
View file @
2a52b6ee
/*
* Line6 Pod HD
*
* Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.com>
*
* 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, version 2.
*
*/
#ifndef PODHD_H
#define PODHD_H
#include <linux/usb.h>
#include "driver.h"
struct
usb_line6_podhd
{
/**
Generic Line6 USB data.
*/
struct
usb_line6
line6
;
};
extern
int
line6_podhd_init
(
struct
usb_interface
*
interface
,
struct
usb_line6
*
line6
);
#endif
/* PODHD_H */
sound/usb/line6/toneport.c
View file @
86b5f3ec
/*
* Line
6 Linux USB driver - 0.9.1beta
* Line
6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* Emil Myhrman (emil.myhrman@gmail.com)
...
...
@@ -11,13 +11,58 @@
*/
#include <linux/wait.h>
#include <linux/usb.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
#include "audio.h"
#include "capture.h"
#include "driver.h"
#include "playback.h"
#include "toneport.h"
#include "usbdefs.h"
enum
line6_device_type
{
LINE6_GUITARPORT
,
LINE6_PODSTUDIO_GX
,
LINE6_PODSTUDIO_UX1
,
LINE6_PODSTUDIO_UX2
,
LINE6_TONEPORT_GX
,
LINE6_TONEPORT_UX1
,
LINE6_TONEPORT_UX2
,
};
struct
usb_line6_toneport
{
/**
Generic Line 6 USB data.
*/
struct
usb_line6
line6
;
/**
Source selector.
*/
int
source
;
/**
Serial number of device.
*/
int
serial_number
;
/**
Firmware version (x 100).
*/
int
firmware_version
;
/**
Timer for delayed PCM startup.
*/
struct
timer_list
timer
;
/**
Device type.
*/
enum
line6_device_type
type
;
};
static
int
toneport_send_cmd
(
struct
usb_device
*
usbdev
,
int
cmd1
,
int
cmd2
);
...
...
@@ -37,9 +82,6 @@ static struct line6_pcm_properties toneport_pcm_properties = {
SNDRV_PCM_INFO_BLOCK_TRANSFER
|
SNDRV_PCM_INFO_MMAP_VALID
|
SNDRV_PCM_INFO_PAUSE
|
#ifdef CONFIG_PM
SNDRV_PCM_INFO_RESUME
|
#endif
SNDRV_PCM_INFO_SYNC_START
),
.
formats
=
SNDRV_PCM_FMTBIT_S16_LE
,
.
rates
=
SNDRV_PCM_RATE_KNOT
,
...
...
@@ -57,9 +99,6 @@ static struct line6_pcm_properties toneport_pcm_properties = {
SNDRV_PCM_INFO_INTERLEAVED
|
SNDRV_PCM_INFO_BLOCK_TRANSFER
|
SNDRV_PCM_INFO_MMAP_VALID
|
#ifdef CONFIG_PM
SNDRV_PCM_INFO_RESUME
|
#endif
SNDRV_PCM_INFO_SYNC_START
),
.
formats
=
SNDRV_PCM_FMTBIT_S16_LE
,
.
rates
=
SNDRV_PCM_RATE_KNOT
,
...
...
@@ -290,18 +329,6 @@ static struct snd_kcontrol_new toneport_control_source = {
.
put
=
snd_toneport_source_put
};
/*
Toneport destructor.
*/
static
void
toneport_destruct
(
struct
usb_interface
*
interface
)
{
struct
usb_line6_toneport
*
toneport
=
usb_get_intfdata
(
interface
);
if
(
toneport
==
NULL
)
return
;
line6_cleanup_audio
(
&
toneport
->
line6
);
}
/*
Setup Toneport device.
*/
...
...
@@ -319,7 +346,7 @@ static void toneport_setup(struct usb_line6_toneport *toneport)
toneport_send_cmd
(
usbdev
,
0x0301
,
0x0000
);
/* initialize source select: */
switch
(
line6
->
type
)
{
switch
(
toneport
->
type
)
{
case
LINE6_TONEPORT_UX1
:
case
LINE6_TONEPORT_UX2
:
case
LINE6_PODSTUDIO_UX1
:
...
...
@@ -331,7 +358,7 @@ static void toneport_setup(struct usb_line6_toneport *toneport)
break
;
}
if
(
toneport_has_led
(
line6
->
type
))
if
(
toneport_has_led
(
toneport
->
type
))
toneport_update_led
(
&
usbdev
->
dev
);
}
...
...
@@ -354,25 +381,14 @@ static void line6_toneport_disconnect(struct usb_interface *interface)
device_remove_file
(
&
interface
->
dev
,
&
dev_attr_led_red
);
device_remove_file
(
&
interface
->
dev
,
&
dev_attr_led_green
);
}
if
(
toneport
!=
NULL
)
{
struct
snd_line6_pcm
*
line6pcm
=
toneport
->
line6
.
line6pcm
;
if
(
line6pcm
!=
NULL
)
{
line6_pcm_release
(
line6pcm
,
LINE6_BITS_PCM_MONITOR
);
line6_pcm_disconnect
(
line6pcm
);
}
}
toneport_destruct
(
interface
);
}
/*
Try to init Toneport device.
*/
static
int
toneport_
try_
init
(
struct
usb_interface
*
interface
,
struct
usb_line6
*
line6
)
static
int
toneport_init
(
struct
usb_interface
*
interface
,
struct
usb_line6
*
line6
)
{
int
err
;
struct
usb_line6_toneport
*
toneport
=
(
struct
usb_line6_toneport
*
)
line6
;
...
...
@@ -382,11 +398,6 @@ static int toneport_try_init(struct usb_interface *interface,
line6
->
disconnect
=
line6_toneport_disconnect
;
/* initialize audio system: */
err
=
line6_init_audio
(
line6
);
if
(
err
<
0
)
return
err
;
/* initialize PCM subsystem: */
err
=
line6_init_pcm
(
line6
,
&
toneport_pcm_properties
);
if
(
err
<
0
)
...
...
@@ -400,7 +411,7 @@ static int toneport_try_init(struct usb_interface *interface,
return
err
;
/* register source select control: */
switch
(
line6
->
type
)
{
switch
(
toneport
->
type
)
{
case
LINE6_TONEPORT_UX1
:
case
LINE6_TONEPORT_UX2
:
case
LINE6_PODSTUDIO_UX1
:
...
...
@@ -416,50 +427,152 @@ static int toneport_try_init(struct usb_interface *interface,
break
;
}
/* register audio system: */
err
=
line6_register_audio
(
line6
);
if
(
err
<
0
)
return
err
;
line6_read_serial_number
(
line6
,
&
toneport
->
serial_number
);
line6_read_data
(
line6
,
0x80c2
,
&
toneport
->
firmware_version
,
1
);
if
(
toneport_has_led
(
line6
->
type
))
{
CHECK_RETURN
(
device_create_file
(
&
interface
->
dev
,
&
dev_attr_led_red
));
CHECK_RETURN
(
device_create_file
(
&
interface
->
dev
,
&
dev_attr_led_green
));
if
(
toneport_has_led
(
toneport
->
type
))
{
err
=
device_create_file
(
&
interface
->
dev
,
&
dev_attr_led_red
);
if
(
err
<
0
)
return
err
;
err
=
device_create_file
(
&
interface
->
dev
,
&
dev_attr_led_green
);
if
(
err
<
0
)
return
err
;
}
toneport_setup
(
toneport
);
init_timer
(
&
toneport
->
timer
);
toneport
->
timer
.
expires
=
jiffies
+
TONEPORT_PCM_DELAY
*
HZ
;
toneport
->
timer
.
function
=
toneport_start_pcm
;
toneport
->
timer
.
data
=
(
unsigned
long
)
toneport
;
add_timer
(
&
toneport
->
timer
);
setup_timer
(
&
toneport
->
timer
,
toneport_start_pcm
,
(
unsigned
long
)
toneport
);
mod_timer
(
&
toneport
->
timer
,
jiffies
+
TONEPORT_PCM_DELAY
*
HZ
);
return
0
;
/* register audio system: */
return
snd_card_register
(
line6
->
card
);
}
#ifdef CONFIG_PM
/*
Init Toneport device (and clean up in case of failure)
.
Resume Toneport device after reset
.
*/
int
line6_toneport_init
(
struct
usb_interface
*
interface
,
struct
usb_line6
*
line6
)
static
int
toneport_reset_resume
(
struct
usb_interface
*
interface
)
{
int
err
=
toneport_try_init
(
interface
,
line6
);
toneport_setup
(
usb_get_intfdata
(
interface
));
return
line6_resume
(
interface
);
}
#endif
if
(
err
<
0
)
toneport_destruct
(
interface
);
#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
/* table of devices that work with this driver */
static
const
struct
usb_device_id
toneport_id_table
[]
=
{
{
LINE6_DEVICE
(
0x4750
),
.
driver_info
=
LINE6_GUITARPORT
},
{
LINE6_DEVICE
(
0x4153
),
.
driver_info
=
LINE6_PODSTUDIO_GX
},
{
LINE6_DEVICE
(
0x4150
),
.
driver_info
=
LINE6_PODSTUDIO_UX1
},
{
LINE6_IF_NUM
(
0x4151
,
0
),
.
driver_info
=
LINE6_PODSTUDIO_UX2
},
{
LINE6_DEVICE
(
0x4147
),
.
driver_info
=
LINE6_TONEPORT_GX
},
{
LINE6_DEVICE
(
0x4141
),
.
driver_info
=
LINE6_TONEPORT_UX1
},
{
LINE6_IF_NUM
(
0x4142
,
0
),
.
driver_info
=
LINE6_TONEPORT_UX2
},
{}
};
return
err
;
}
MODULE_DEVICE_TABLE
(
usb
,
toneport_id_table
);
static
const
struct
line6_properties
toneport_properties_table
[]
=
{
[
LINE6_GUITARPORT
]
=
{
.
id
=
"GuitarPort"
,
.
name
=
"GuitarPort"
,
.
capabilities
=
LINE6_CAP_PCM
,
.
altsetting
=
2
,
/* 1..4 seem to be ok */
/* no control channel */
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_PODSTUDIO_GX
]
=
{
.
id
=
"PODStudioGX"
,
.
name
=
"POD Studio GX"
,
.
capabilities
=
LINE6_CAP_PCM
,
.
altsetting
=
2
,
/* 1..4 seem to be ok */
/* no control channel */
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_PODSTUDIO_UX1
]
=
{
.
id
=
"PODStudioUX1"
,
.
name
=
"POD Studio UX1"
,
.
capabilities
=
LINE6_CAP_PCM
,
.
altsetting
=
2
,
/* 1..4 seem to be ok */
/* no control channel */
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_PODSTUDIO_UX2
]
=
{
.
id
=
"PODStudioUX2"
,
.
name
=
"POD Studio UX2"
,
.
capabilities
=
LINE6_CAP_PCM
,
.
altsetting
=
2
,
/* defaults to 44.1kHz, 16-bit */
/* no control channel */
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_TONEPORT_GX
]
=
{
.
id
=
"TonePortGX"
,
.
name
=
"TonePort GX"
,
.
capabilities
=
LINE6_CAP_PCM
,
.
altsetting
=
2
,
/* 1..4 seem to be ok */
/* no control channel */
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_TONEPORT_UX1
]
=
{
.
id
=
"TonePortUX1"
,
.
name
=
"TonePort UX1"
,
.
capabilities
=
LINE6_CAP_PCM
,
.
altsetting
=
2
,
/* 1..4 seem to be ok */
/* no control channel */
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_TONEPORT_UX2
]
=
{
.
id
=
"TonePortUX2"
,
.
name
=
"TonePort UX2"
,
.
capabilities
=
LINE6_CAP_PCM
,
.
altsetting
=
2
,
/* defaults to 44.1kHz, 16-bit */
/* no control channel */
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
};
/*
Resume Toneport device after reset
.
Probe USB device
.
*/
void
line6_toneport_reset_resume
(
struct
usb_line6_toneport
*
toneport
)
static
int
toneport_probe
(
struct
usb_interface
*
interface
,
const
struct
usb_device_id
*
id
)
{
toneport_setup
(
toneport
);
struct
usb_line6_toneport
*
toneport
;
toneport
=
kzalloc
(
sizeof
(
*
toneport
),
GFP_KERNEL
);
if
(
!
toneport
)
return
-
ENODEV
;
toneport
->
type
=
id
->
driver_info
;
return
line6_probe
(
interface
,
&
toneport
->
line6
,
&
toneport_properties_table
[
id
->
driver_info
],
toneport_init
);
}
static
struct
usb_driver
toneport_driver
=
{
.
name
=
KBUILD_MODNAME
,
.
probe
=
toneport_probe
,
.
disconnect
=
line6_disconnect
,
#ifdef CONFIG_PM
.
suspend
=
line6_suspend
,
.
resume
=
line6_resume
,
.
reset_resume
=
toneport_reset_resume
,
#endif
.
id_table
=
toneport_id_table
,
};
module_usb_driver
(
toneport_driver
);
MODULE_DESCRIPTION
(
"TonePort USB driver"
);
MODULE_LICENSE
(
"GPL"
);
sound/usb/line6/toneport.h
deleted
100644 → 0
View file @
2a52b6ee
/*
* Line6 Linux USB driver - 0.9.1beta
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
* 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, version 2.
*
*/
#ifndef TONEPORT_H
#define TONEPORT_H
#include <linux/usb.h>
#include <sound/core.h>
#include "driver.h"
struct
usb_line6_toneport
{
/**
Generic Line6 USB data.
*/
struct
usb_line6
line6
;
/**
Source selector.
*/
int
source
;
/**
Serial number of device.
*/
int
serial_number
;
/**
Firmware version (x 100).
*/
int
firmware_version
;
/**
Timer for delayed PCM startup.
*/
struct
timer_list
timer
;
};
extern
int
line6_toneport_init
(
struct
usb_interface
*
interface
,
struct
usb_line6
*
line6
);
extern
void
line6_toneport_reset_resume
(
struct
usb_line6_toneport
*
toneport
);
#endif
sound/usb/line6/usbdefs.h
View file @
86b5f3ec
/*
* Line
6 Linux USB driver - 0.9.1beta
* Line
6 Linux USB driver
*
* Copyright (C) 2005-2008 Markus Grabner (grabner@icg.tugraz.at)
*
...
...
sound/usb/line6/variax.c
View file @
86b5f3ec
/*
* Line
6 Linux USB driver - 0.9.1beta
* Line
6 Linux USB driver
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
...
...
@@ -10,10 +10,64 @@
*/
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/usb.h>
#include <linux/wait.h>
#include <linux/module.h>
#include <sound/core.h>
#include "audio.h"
#include "driver.h"
#include "variax.h"
#include "usbdefs.h"
#define VARIAX_STARTUP_DELAY1 1000
#define VARIAX_STARTUP_DELAY3 100
#define VARIAX_STARTUP_DELAY4 100
/*
Stages of Variax startup procedure
*/
enum
{
VARIAX_STARTUP_INIT
=
1
,
VARIAX_STARTUP_VERSIONREQ
,
VARIAX_STARTUP_WAIT
,
VARIAX_STARTUP_ACTIVATE
,
VARIAX_STARTUP_WORKQUEUE
,
VARIAX_STARTUP_SETUP
,
VARIAX_STARTUP_LAST
=
VARIAX_STARTUP_SETUP
-
1
};
enum
{
LINE6_PODXTLIVE_VARIAX
,
LINE6_VARIAX
};
struct
usb_line6_variax
{
/**
Generic Line 6 USB data.
*/
struct
usb_line6
line6
;
/**
Buffer for activation code.
*/
unsigned
char
*
buffer_activate
;
/**
Handler for device initializaton.
*/
struct
work_struct
startup_work
;
/**
Timers for device initializaton.
*/
struct
timer_list
startup_timer1
;
struct
timer_list
startup_timer2
;
/**
Current progress in startup procedure.
*/
int
startup_progress
;
};
#define VARIAX_OFFSET_ACTIVATE 7
...
...
@@ -124,7 +178,7 @@ static void variax_startup6(struct work_struct *work)
CHECK_STARTUP_PROGRESS
(
variax
->
startup_progress
,
VARIAX_STARTUP_SETUP
);
/* ALSA audio interface: */
line6_register_audio
(
&
variax
->
line6
);
snd_card_register
(
variax
->
line6
.
card
);
}
/*
...
...
@@ -156,13 +210,16 @@ static void line6_variax_process_message(struct usb_line6 *line6)
/*
Variax destructor.
*/
static
void
variax_destru
ct
(
struct
usb_interface
*
interface
)
static
void
line6_variax_disconne
ct
(
struct
usb_interface
*
interface
)
{
struct
usb_line6_variax
*
variax
=
usb_get_intfdata
(
interface
)
;
struct
usb_line6_variax
*
variax
;
if
(
variax
==
NULL
)
if
(
!
interface
)
return
;
variax
=
usb_get_intfdata
(
interface
);
if
(
!
variax
)
return
;
line6_cleanup_audio
(
&
variax
->
line6
);
del_timer
(
&
variax
->
startup_timer1
);
del_timer
(
&
variax
->
startup_timer2
);
...
...
@@ -171,22 +228,11 @@ static void variax_destruct(struct usb_interface *interface)
kfree
(
variax
->
buffer_activate
);
}
/*
Workbench device disconnected.
*/
static
void
line6_variax_disconnect
(
struct
usb_interface
*
interface
)
{
if
(
interface
==
NULL
)
return
;
variax_destruct
(
interface
);
}
/*
Try to init workbench device.
*/
static
int
variax_
try_
init
(
struct
usb_interface
*
interface
,
struct
usb_line6
*
line6
)
static
int
variax_init
(
struct
usb_interface
*
interface
,
struct
usb_line6
*
line6
)
{
struct
usb_line6_variax
*
variax
=
(
struct
usb_line6_variax
*
)
line6
;
int
err
;
...
...
@@ -205,15 +251,8 @@ static int variax_try_init(struct usb_interface *interface,
variax
->
buffer_activate
=
kmemdup
(
variax_activate
,
sizeof
(
variax_activate
),
GFP_KERNEL
);
if
(
variax
->
buffer_activate
==
NULL
)
{
dev_err
(
&
interface
->
dev
,
"Out of memory
\n
"
);
if
(
variax
->
buffer_activate
==
NULL
)
return
-
ENOMEM
;
}
/* initialize audio system: */
err
=
line6_init_audio
(
&
variax
->
line6
);
if
(
err
<
0
)
return
err
;
/* initialize MIDI subsystem: */
err
=
line6_init_midi
(
&
variax
->
line6
);
...
...
@@ -225,15 +264,71 @@ static int variax_try_init(struct usb_interface *interface,
return
0
;
}
#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
/* table of devices that work with this driver */
static
const
struct
usb_device_id
variax_id_table
[]
=
{
{
LINE6_IF_NUM
(
0x4650
,
1
),
.
driver_info
=
LINE6_PODXTLIVE_VARIAX
},
{
LINE6_DEVICE
(
0x534d
),
.
driver_info
=
LINE6_VARIAX
},
{}
};
MODULE_DEVICE_TABLE
(
usb
,
variax_id_table
);
static
const
struct
line6_properties
variax_properties_table
[]
=
{
[
LINE6_PODXTLIVE_VARIAX
]
=
{
.
id
=
"PODxtLive"
,
.
name
=
"PODxt Live"
,
.
capabilities
=
LINE6_CAP_CONTROL
|
LINE6_CAP_PCM
|
LINE6_CAP_HWMON
,
.
altsetting
=
1
,
.
ep_ctrl_r
=
0x86
,
.
ep_ctrl_w
=
0x05
,
.
ep_audio_r
=
0x82
,
.
ep_audio_w
=
0x01
,
},
[
LINE6_VARIAX
]
=
{
.
id
=
"Variax"
,
.
name
=
"Variax Workbench"
,
.
capabilities
=
LINE6_CAP_CONTROL
,
.
altsetting
=
1
,
.
ep_ctrl_r
=
0x82
,
.
ep_ctrl_w
=
0x01
,
/* no audio channel */
}
};
/*
Init workbench device (and clean up in case of failure)
.
Probe USB device
.
*/
int
line6_variax_init
(
struct
usb_interface
*
interface
,
struct
usb_line6
*
line6
)
static
int
variax_probe
(
struct
usb_interface
*
interface
,
const
struct
usb_device_id
*
id
)
{
int
err
=
variax_try_init
(
interface
,
line6
)
;
struct
usb_line6_variax
*
variax
;
if
(
err
<
0
)
variax_destruct
(
interface
);
return
err
;
variax
=
kzalloc
(
sizeof
(
*
variax
),
GFP_KERNEL
);
if
(
!
variax
)
return
-
ENODEV
;
return
line6_probe
(
interface
,
&
variax
->
line6
,
&
variax_properties_table
[
id
->
driver_info
],
variax_init
);
}
static
struct
usb_driver
variax_driver
=
{
.
name
=
KBUILD_MODNAME
,
.
probe
=
variax_probe
,
.
disconnect
=
line6_disconnect
,
#ifdef CONFIG_PM
.
suspend
=
line6_suspend
,
.
resume
=
line6_resume
,
.
reset_resume
=
line6_resume
,
#endif
.
id_table
=
variax_id_table
,
};
module_usb_driver
(
variax_driver
);
MODULE_DESCRIPTION
(
"Vairax Workbench USB driver"
);
MODULE_LICENSE
(
"GPL"
);
sound/usb/line6/variax.h
deleted
100644 → 0
View file @
2a52b6ee
/*
* Line6 Linux USB driver - 0.9.1beta
*
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
*
* 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, version 2.
*
*/
#ifndef VARIAX_H
#define VARIAX_H
#include <linux/spinlock.h>
#include <linux/usb.h>
#include <linux/wait.h>
#include <sound/core.h>
#include "driver.h"
#define VARIAX_STARTUP_DELAY1 1000
#define VARIAX_STARTUP_DELAY3 100
#define VARIAX_STARTUP_DELAY4 100
/*
Stages of Variax startup procedure
*/
enum
{
VARIAX_STARTUP_INIT
=
1
,
VARIAX_STARTUP_VERSIONREQ
,
VARIAX_STARTUP_WAIT
,
VARIAX_STARTUP_ACTIVATE
,
VARIAX_STARTUP_WORKQUEUE
,
VARIAX_STARTUP_SETUP
,
VARIAX_STARTUP_LAST
=
VARIAX_STARTUP_SETUP
-
1
};
struct
usb_line6_variax
{
/**
Generic Line6 USB data.
*/
struct
usb_line6
line6
;
/**
Buffer for activation code.
*/
unsigned
char
*
buffer_activate
;
/**
Handler for device initializaton.
*/
struct
work_struct
startup_work
;
/**
Timers for device initializaton.
*/
struct
timer_list
startup_timer1
;
struct
timer_list
startup_timer2
;
/**
Current progress in startup procedure.
*/
int
startup_progress
;
};
extern
int
line6_variax_init
(
struct
usb_interface
*
interface
,
struct
usb_line6
*
line6
);
#endif
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