Merge branch 'topic/line6-cleanup' into for-next
Pull LINE6 driver cleanups and fixes. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
commit
968e8e9fde
|
@ -195,17 +195,6 @@ static int line6_send_raw_message_async_part(struct message *msg,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
Setup and start timer.
|
||||
*/
|
||||
void line6_start_timer(struct timer_list *timer, unsigned long msecs,
|
||||
void (*function)(struct timer_list *t))
|
||||
{
|
||||
timer->function = function;
|
||||
mod_timer(timer, jiffies + msecs_to_jiffies(msecs));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(line6_start_timer);
|
||||
|
||||
/*
|
||||
Asynchronously send raw message.
|
||||
*/
|
||||
|
@ -720,6 +709,15 @@ static int line6_init_cap_control(struct usb_line6 *line6)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void line6_startup_work(struct work_struct *work)
|
||||
{
|
||||
struct usb_line6 *line6 =
|
||||
container_of(work, struct usb_line6, startup_work.work);
|
||||
|
||||
if (line6->startup)
|
||||
line6->startup(line6);
|
||||
}
|
||||
|
||||
/*
|
||||
Probe USB device.
|
||||
*/
|
||||
|
@ -755,6 +753,7 @@ int line6_probe(struct usb_interface *interface,
|
|||
line6->properties = properties;
|
||||
line6->usbdev = usbdev;
|
||||
line6->ifcdev = &interface->dev;
|
||||
INIT_DELAYED_WORK(&line6->startup_work, line6_startup_work);
|
||||
|
||||
strcpy(card->id, properties->id);
|
||||
strcpy(card->driver, driver_name);
|
||||
|
@ -825,6 +824,8 @@ void line6_disconnect(struct usb_interface *interface)
|
|||
if (WARN_ON(usbdev != line6->usbdev))
|
||||
return;
|
||||
|
||||
cancel_delayed_work(&line6->startup_work);
|
||||
|
||||
if (line6->urb_listen != NULL)
|
||||
line6_stop_listen(line6);
|
||||
|
||||
|
|
|
@ -68,13 +68,6 @@
|
|||
|
||||
#define LINE6_CHANNEL_MASK 0x0f
|
||||
|
||||
#define CHECK_STARTUP_PROGRESS(x, n) \
|
||||
do { \
|
||||
if ((x) >= (n)) \
|
||||
return; \
|
||||
x = (n); \
|
||||
} while (0)
|
||||
|
||||
extern const unsigned char line6_midi_id[3];
|
||||
|
||||
static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3;
|
||||
|
@ -178,11 +171,15 @@ struct usb_line6 {
|
|||
fifo;
|
||||
} messages;
|
||||
|
||||
/* Work for delayed PCM startup */
|
||||
struct delayed_work startup_work;
|
||||
|
||||
/* If MIDI is supported, buffer_message contains the pre-processed data;
|
||||
* otherwise the data is only in urb_listen (buffer_incoming).
|
||||
*/
|
||||
void (*process_message)(struct usb_line6 *);
|
||||
void (*disconnect)(struct usb_line6 *line6);
|
||||
void (*startup)(struct usb_line6 *line6);
|
||||
};
|
||||
|
||||
extern char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1,
|
||||
|
@ -197,8 +194,6 @@ extern int line6_send_sysex_message(struct usb_line6 *line6,
|
|||
const char *buffer, int size);
|
||||
extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
extern void line6_start_timer(struct timer_list *timer, unsigned long msecs,
|
||||
void (*function)(struct timer_list *t));
|
||||
extern int line6_version_request_async(struct usb_line6 *line6);
|
||||
extern int line6_write_data(struct usb_line6 *line6, unsigned address,
|
||||
void *data, unsigned datalen);
|
||||
|
|
|
@ -39,11 +39,9 @@
|
|||
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
|
||||
POD_STARTUP_DONE,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -63,12 +61,6 @@ struct usb_line6_pod {
|
|||
/* Instrument monitor level */
|
||||
int monitor_level;
|
||||
|
||||
/* Timer for device initialization */
|
||||
struct timer_list startup_timer;
|
||||
|
||||
/* Work handler for device initialization */
|
||||
struct work_struct startup_work;
|
||||
|
||||
/* Current progress in startup procedure */
|
||||
int startup_progress;
|
||||
|
||||
|
@ -82,6 +74,8 @@ struct usb_line6_pod {
|
|||
int device_id;
|
||||
};
|
||||
|
||||
#define line6_to_pod(x) container_of(x, struct usb_line6_pod, line6)
|
||||
|
||||
#define POD_SYSEX_CODE 3
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
|
@ -173,10 +167,6 @@ static const char pod_version_header[] = {
|
|||
0xf2, 0x7e, 0x7f, 0x06, 0x02
|
||||
};
|
||||
|
||||
/* forward declarations: */
|
||||
static void pod_startup2(struct timer_list *t);
|
||||
static void pod_startup3(struct usb_line6_pod *pod);
|
||||
|
||||
static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
|
||||
int size)
|
||||
{
|
||||
|
@ -189,14 +179,17 @@ static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
|
|||
*/
|
||||
static void line6_pod_process_message(struct usb_line6 *line6)
|
||||
{
|
||||
struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
|
||||
struct usb_line6_pod *pod = line6_to_pod(line6);
|
||||
const unsigned char *buf = pod->line6.buffer_message;
|
||||
|
||||
if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
|
||||
pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];
|
||||
pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) |
|
||||
(int) buf[10];
|
||||
pod_startup3(pod);
|
||||
if (pod->startup_progress == POD_STARTUP_VERSIONREQ) {
|
||||
pod->startup_progress = POD_STARTUP_SETUP;
|
||||
schedule_delayed_work(&line6->startup_work, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -281,47 +274,27 @@ static ssize_t device_id_show(struct device *dev,
|
|||
context). After the last one has finished, the device is ready to use.
|
||||
*/
|
||||
|
||||
static void pod_startup1(struct usb_line6_pod *pod)
|
||||
static void pod_startup(struct usb_line6 *line6)
|
||||
{
|
||||
CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
|
||||
struct usb_line6_pod *pod = line6_to_pod(line6);
|
||||
|
||||
/* delay startup procedure: */
|
||||
line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2);
|
||||
}
|
||||
switch (pod->startup_progress) {
|
||||
case POD_STARTUP_VERSIONREQ:
|
||||
/* request firmware version: */
|
||||
line6_version_request_async(line6);
|
||||
break;
|
||||
case POD_STARTUP_SETUP:
|
||||
/* serial number: */
|
||||
line6_read_serial_number(&pod->line6, &pod->serial_number);
|
||||
|
||||
static void pod_startup2(struct timer_list *t)
|
||||
{
|
||||
struct usb_line6_pod *pod = from_timer(pod, t, startup_timer);
|
||||
struct usb_line6 *line6 = &pod->line6;
|
||||
|
||||
CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
|
||||
|
||||
/* request firmware version: */
|
||||
line6_version_request_async(line6);
|
||||
}
|
||||
|
||||
static void pod_startup3(struct usb_line6_pod *pod)
|
||||
{
|
||||
CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
|
||||
|
||||
/* schedule work for global work queue: */
|
||||
schedule_work(&pod->startup_work);
|
||||
}
|
||||
|
||||
static void pod_startup4(struct work_struct *work)
|
||||
{
|
||||
struct usb_line6_pod *pod =
|
||||
container_of(work, struct usb_line6_pod, startup_work);
|
||||
struct usb_line6 *line6 = &pod->line6;
|
||||
|
||||
CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
|
||||
|
||||
/* serial number: */
|
||||
line6_read_serial_number(&pod->line6, &pod->serial_number);
|
||||
|
||||
/* ALSA audio interface: */
|
||||
if (snd_card_register(line6->card))
|
||||
dev_err(line6->ifcdev, "Failed to register POD card.\n");
|
||||
/* ALSA audio interface: */
|
||||
if (snd_card_register(line6->card))
|
||||
dev_err(line6->ifcdev, "Failed to register POD card.\n");
|
||||
pod->startup_progress = POD_STARTUP_DONE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* POD special files: */
|
||||
|
@ -357,7 +330,7 @@ static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
|
||||
struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
|
||||
struct usb_line6_pod *pod = line6_to_pod(line6pcm->line6);
|
||||
|
||||
ucontrol->value.integer.value[0] = pod->monitor_level;
|
||||
return 0;
|
||||
|
@ -368,7 +341,7 @@ static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
|
||||
struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;
|
||||
struct usb_line6_pod *pod = line6_to_pod(line6pcm->line6);
|
||||
|
||||
if (ucontrol->value.integer.value[0] == pod->monitor_level)
|
||||
return 0;
|
||||
|
@ -390,17 +363,6 @@ static const struct snd_kcontrol_new pod_control_monitor = {
|
|||
.put = snd_pod_control_monitor_put
|
||||
};
|
||||
|
||||
/*
|
||||
POD device disconnected.
|
||||
*/
|
||||
static void line6_pod_disconnect(struct usb_line6 *line6)
|
||||
{
|
||||
struct usb_line6_pod *pod = (struct usb_line6_pod *)line6;
|
||||
|
||||
del_timer_sync(&pod->startup_timer);
|
||||
cancel_work_sync(&pod->startup_work);
|
||||
}
|
||||
|
||||
/*
|
||||
Try to init POD device.
|
||||
*/
|
||||
|
@ -408,13 +370,10 @@ static int pod_init(struct usb_line6 *line6,
|
|||
const struct usb_device_id *id)
|
||||
{
|
||||
int err;
|
||||
struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
|
||||
struct usb_line6_pod *pod = line6_to_pod(line6);
|
||||
|
||||
line6->process_message = line6_pod_process_message;
|
||||
line6->disconnect = line6_pod_disconnect;
|
||||
|
||||
timer_setup(&pod->startup_timer, NULL, 0);
|
||||
INIT_WORK(&pod->startup_work, pod_startup4);
|
||||
line6->startup = pod_startup;
|
||||
|
||||
/* create sysfs entries: */
|
||||
err = snd_card_add_dev_attr(line6->card, &pod_dev_attr_group);
|
||||
|
@ -447,7 +406,8 @@ static int pod_init(struct usb_line6 *line6,
|
|||
pod->monitor_level = POD_SYSTEM_INVALID;
|
||||
|
||||
/* initiate startup procedure: */
|
||||
pod_startup1(pod);
|
||||
schedule_delayed_work(&line6->startup_work,
|
||||
msecs_to_jiffies(POD_STARTUP_DELAY));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -22,16 +22,6 @@
|
|||
|
||||
#define PODHD_STARTUP_DELAY 500
|
||||
|
||||
/*
|
||||
* Stages of POD startup procedure
|
||||
*/
|
||||
enum {
|
||||
PODHD_STARTUP_INIT = 1,
|
||||
PODHD_STARTUP_SCHEDULE_WORKQUEUE,
|
||||
PODHD_STARTUP_SETUP,
|
||||
PODHD_STARTUP_LAST = PODHD_STARTUP_SETUP - 1
|
||||
};
|
||||
|
||||
enum {
|
||||
LINE6_PODHD300,
|
||||
LINE6_PODHD400,
|
||||
|
@ -47,15 +37,6 @@ struct usb_line6_podhd {
|
|||
/* Generic Line 6 USB data */
|
||||
struct usb_line6 line6;
|
||||
|
||||
/* Timer for device initialization */
|
||||
struct timer_list startup_timer;
|
||||
|
||||
/* Work handler for device initialization */
|
||||
struct work_struct startup_work;
|
||||
|
||||
/* Current progress in startup procedure */
|
||||
int startup_progress;
|
||||
|
||||
/* Serial number of device */
|
||||
u32 serial_number;
|
||||
|
||||
|
@ -63,6 +44,8 @@ struct usb_line6_podhd {
|
|||
int firmware_version;
|
||||
};
|
||||
|
||||
#define line6_to_podhd(x) container_of(x, struct usb_line6_podhd, line6)
|
||||
|
||||
static struct snd_ratden podhd_ratden = {
|
||||
.num_min = 48000,
|
||||
.num_max = 48000,
|
||||
|
@ -158,10 +141,6 @@ static struct line6_pcm_properties podx3_pcm_properties = {
|
|||
};
|
||||
static struct usb_driver podhd_driver;
|
||||
|
||||
static void podhd_startup_start_workqueue(struct timer_list *t);
|
||||
static void podhd_startup_workqueue(struct work_struct *work);
|
||||
static int podhd_startup_finalize(struct usb_line6_podhd *pod);
|
||||
|
||||
static ssize_t serial_number_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
@ -202,26 +181,6 @@ static const struct attribute_group podhd_dev_attr_group = {
|
|||
* audio nor bulk interfaces to work.
|
||||
*/
|
||||
|
||||
static void podhd_startup(struct usb_line6_podhd *pod)
|
||||
{
|
||||
CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_INIT);
|
||||
|
||||
/* delay startup procedure: */
|
||||
line6_start_timer(&pod->startup_timer, PODHD_STARTUP_DELAY,
|
||||
podhd_startup_start_workqueue);
|
||||
}
|
||||
|
||||
static void podhd_startup_start_workqueue(struct timer_list *t)
|
||||
{
|
||||
struct usb_line6_podhd *pod = from_timer(pod, t, startup_timer);
|
||||
|
||||
CHECK_STARTUP_PROGRESS(pod->startup_progress,
|
||||
PODHD_STARTUP_SCHEDULE_WORKQUEUE);
|
||||
|
||||
/* schedule work for global work queue: */
|
||||
schedule_work(&pod->startup_work);
|
||||
}
|
||||
|
||||
static int podhd_dev_start(struct usb_line6_podhd *pod)
|
||||
{
|
||||
int ret;
|
||||
|
@ -272,37 +231,23 @@ exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void podhd_startup_workqueue(struct work_struct *work)
|
||||
static void podhd_startup(struct usb_line6 *line6)
|
||||
{
|
||||
struct usb_line6_podhd *pod =
|
||||
container_of(work, struct usb_line6_podhd, startup_work);
|
||||
|
||||
CHECK_STARTUP_PROGRESS(pod->startup_progress, PODHD_STARTUP_SETUP);
|
||||
struct usb_line6_podhd *pod = line6_to_podhd(line6);
|
||||
|
||||
podhd_dev_start(pod);
|
||||
line6_read_serial_number(&pod->line6, &pod->serial_number);
|
||||
|
||||
podhd_startup_finalize(pod);
|
||||
}
|
||||
|
||||
static int podhd_startup_finalize(struct usb_line6_podhd *pod)
|
||||
{
|
||||
struct usb_line6 *line6 = &pod->line6;
|
||||
|
||||
/* ALSA audio interface: */
|
||||
return snd_card_register(line6->card);
|
||||
if (snd_card_register(line6->card))
|
||||
dev_err(line6->ifcdev, "Failed to register POD HD card.\n");
|
||||
}
|
||||
|
||||
static void podhd_disconnect(struct usb_line6 *line6)
|
||||
{
|
||||
struct usb_line6_podhd *pod = (struct usb_line6_podhd *)line6;
|
||||
struct usb_line6_podhd *pod = line6_to_podhd(line6);
|
||||
|
||||
if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO) {
|
||||
struct usb_interface *intf;
|
||||
|
||||
del_timer_sync(&pod->startup_timer);
|
||||
cancel_work_sync(&pod->startup_work);
|
||||
|
||||
intf = usb_ifnum_to_if(line6->usbdev,
|
||||
pod->line6.properties->ctrl_if);
|
||||
if (intf)
|
||||
|
@ -317,13 +262,11 @@ static int podhd_init(struct usb_line6 *line6,
|
|||
const struct usb_device_id *id)
|
||||
{
|
||||
int err;
|
||||
struct usb_line6_podhd *pod = (struct usb_line6_podhd *) line6;
|
||||
struct usb_line6_podhd *pod = line6_to_podhd(line6);
|
||||
struct usb_interface *intf;
|
||||
|
||||
line6->disconnect = podhd_disconnect;
|
||||
|
||||
timer_setup(&pod->startup_timer, NULL, 0);
|
||||
INIT_WORK(&pod->startup_work, podhd_startup_workqueue);
|
||||
line6->startup = podhd_startup;
|
||||
|
||||
if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
|
||||
/* claim the data interface */
|
||||
|
@ -362,11 +305,12 @@ static int podhd_init(struct usb_line6 *line6,
|
|||
|
||||
if (!(pod->line6.properties->capabilities & LINE6_CAP_CONTROL_INFO)) {
|
||||
/* register USB audio system directly */
|
||||
return podhd_startup_finalize(pod);
|
||||
return snd_card_register(line6->card);
|
||||
}
|
||||
|
||||
/* init device and delay registering */
|
||||
podhd_startup(pod);
|
||||
schedule_delayed_work(&line6->startup_work,
|
||||
msecs_to_jiffies(PODHD_STARTUP_DELAY));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,9 +54,6 @@ struct usb_line6_toneport {
|
|||
/* Firmware version (x 100) */
|
||||
u8 firmware_version;
|
||||
|
||||
/* Work for delayed PCM startup */
|
||||
struct delayed_work pcm_work;
|
||||
|
||||
/* Device type */
|
||||
enum line6_device_type type;
|
||||
|
||||
|
@ -64,6 +61,8 @@ struct usb_line6_toneport {
|
|||
struct toneport_led leds[2];
|
||||
};
|
||||
|
||||
#define line6_to_toneport(x) container_of(x, struct usb_line6_toneport, line6)
|
||||
|
||||
static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2);
|
||||
|
||||
#define TONEPORT_PCM_DELAY 1
|
||||
|
@ -214,8 +213,8 @@ static int snd_toneport_source_get(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
|
||||
struct usb_line6_toneport *toneport =
|
||||
(struct usb_line6_toneport *)line6pcm->line6;
|
||||
struct usb_line6_toneport *toneport = line6_to_toneport(line6pcm->line6);
|
||||
|
||||
ucontrol->value.enumerated.item[0] = toneport->source;
|
||||
return 0;
|
||||
}
|
||||
|
@ -225,8 +224,7 @@ static int snd_toneport_source_put(struct snd_kcontrol *kcontrol,
|
|||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
|
||||
struct usb_line6_toneport *toneport =
|
||||
(struct usb_line6_toneport *)line6pcm->line6;
|
||||
struct usb_line6_toneport *toneport = line6_to_toneport(line6pcm->line6);
|
||||
unsigned int source;
|
||||
|
||||
source = ucontrol->value.enumerated.item[0];
|
||||
|
@ -241,12 +239,8 @@ static int snd_toneport_source_put(struct snd_kcontrol *kcontrol,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void toneport_start_pcm(struct work_struct *work)
|
||||
static void toneport_startup(struct usb_line6 *line6)
|
||||
{
|
||||
struct usb_line6_toneport *toneport =
|
||||
container_of(work, struct usb_line6_toneport, pcm_work.work);
|
||||
struct usb_line6 *line6 = &toneport->line6;
|
||||
|
||||
line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR, true);
|
||||
}
|
||||
|
||||
|
@ -394,7 +388,7 @@ static int toneport_setup(struct usb_line6_toneport *toneport)
|
|||
if (toneport_has_led(toneport))
|
||||
toneport_update_led(toneport);
|
||||
|
||||
schedule_delayed_work(&toneport->pcm_work,
|
||||
schedule_delayed_work(&toneport->line6.startup_work,
|
||||
msecs_to_jiffies(TONEPORT_PCM_DELAY * 1000));
|
||||
return 0;
|
||||
}
|
||||
|
@ -404,10 +398,7 @@ static int toneport_setup(struct usb_line6_toneport *toneport)
|
|||
*/
|
||||
static void line6_toneport_disconnect(struct usb_line6 *line6)
|
||||
{
|
||||
struct usb_line6_toneport *toneport =
|
||||
(struct usb_line6_toneport *)line6;
|
||||
|
||||
cancel_delayed_work_sync(&toneport->pcm_work);
|
||||
struct usb_line6_toneport *toneport = line6_to_toneport(line6);
|
||||
|
||||
if (toneport_has_led(toneport))
|
||||
toneport_remove_leds(toneport);
|
||||
|
@ -421,12 +412,12 @@ static int toneport_init(struct usb_line6 *line6,
|
|||
const struct usb_device_id *id)
|
||||
{
|
||||
int err;
|
||||
struct usb_line6_toneport *toneport = (struct usb_line6_toneport *) line6;
|
||||
struct usb_line6_toneport *toneport = line6_to_toneport(line6);
|
||||
|
||||
toneport->type = id->driver_info;
|
||||
INIT_DELAYED_WORK(&toneport->pcm_work, toneport_start_pcm);
|
||||
|
||||
line6->disconnect = line6_toneport_disconnect;
|
||||
line6->startup = toneport_startup;
|
||||
|
||||
/* initialize PCM subsystem: */
|
||||
err = line6_init_pcm(line6, &toneport_pcm_properties);
|
||||
|
|
|
@ -26,13 +26,9 @@
|
|||
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 {
|
||||
|
@ -47,17 +43,12 @@ struct usb_line6_variax {
|
|||
/* Buffer for activation code */
|
||||
unsigned char *buffer_activate;
|
||||
|
||||
/* Handler for device initialization */
|
||||
struct work_struct startup_work;
|
||||
|
||||
/* Timers for device initialization */
|
||||
struct timer_list startup_timer1;
|
||||
struct timer_list startup_timer2;
|
||||
|
||||
/* Current progress in startup procedure */
|
||||
int startup_progress;
|
||||
};
|
||||
|
||||
#define line6_to_variax(x) container_of(x, struct usb_line6_variax, line6)
|
||||
|
||||
#define VARIAX_OFFSET_ACTIVATE 7
|
||||
|
||||
/*
|
||||
|
@ -81,11 +72,6 @@ static const char variax_activate[] = {
|
|||
0xf7
|
||||
};
|
||||
|
||||
/* forward declarations: */
|
||||
static void variax_startup2(struct timer_list *t);
|
||||
static void variax_startup4(struct timer_list *t);
|
||||
static void variax_startup5(struct timer_list *t);
|
||||
|
||||
static void variax_activate_async(struct usb_line6_variax *variax, int a)
|
||||
{
|
||||
variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a;
|
||||
|
@ -100,74 +86,30 @@ static void variax_activate_async(struct usb_line6_variax *variax, int a)
|
|||
context). After the last one has finished, the device is ready to use.
|
||||
*/
|
||||
|
||||
static void variax_startup1(struct usb_line6_variax *variax)
|
||||
static void variax_startup(struct usb_line6 *line6)
|
||||
{
|
||||
CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_INIT);
|
||||
struct usb_line6_variax *variax = line6_to_variax(line6);
|
||||
|
||||
/* delay startup procedure: */
|
||||
line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
|
||||
variax_startup2);
|
||||
}
|
||||
|
||||
static void variax_startup2(struct timer_list *t)
|
||||
{
|
||||
struct usb_line6_variax *variax = from_timer(variax, t, startup_timer1);
|
||||
struct usb_line6 *line6 = &variax->line6;
|
||||
|
||||
/* schedule another startup procedure until startup is complete: */
|
||||
if (variax->startup_progress >= VARIAX_STARTUP_LAST)
|
||||
return;
|
||||
|
||||
variax->startup_progress = VARIAX_STARTUP_VERSIONREQ;
|
||||
line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
|
||||
variax_startup2);
|
||||
|
||||
/* request firmware version: */
|
||||
line6_version_request_async(line6);
|
||||
}
|
||||
|
||||
static void variax_startup3(struct usb_line6_variax *variax)
|
||||
{
|
||||
CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_WAIT);
|
||||
|
||||
/* delay startup procedure: */
|
||||
line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY3,
|
||||
variax_startup4);
|
||||
}
|
||||
|
||||
static void variax_startup4(struct timer_list *t)
|
||||
{
|
||||
struct usb_line6_variax *variax = from_timer(variax, t, startup_timer2);
|
||||
|
||||
CHECK_STARTUP_PROGRESS(variax->startup_progress,
|
||||
VARIAX_STARTUP_ACTIVATE);
|
||||
|
||||
/* activate device: */
|
||||
variax_activate_async(variax, 1);
|
||||
line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY4,
|
||||
variax_startup5);
|
||||
}
|
||||
|
||||
static void variax_startup5(struct timer_list *t)
|
||||
{
|
||||
struct usb_line6_variax *variax = from_timer(variax, t, startup_timer2);
|
||||
|
||||
CHECK_STARTUP_PROGRESS(variax->startup_progress,
|
||||
VARIAX_STARTUP_WORKQUEUE);
|
||||
|
||||
/* schedule work for global work queue: */
|
||||
schedule_work(&variax->startup_work);
|
||||
}
|
||||
|
||||
static void variax_startup6(struct work_struct *work)
|
||||
{
|
||||
struct usb_line6_variax *variax =
|
||||
container_of(work, struct usb_line6_variax, startup_work);
|
||||
|
||||
CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP);
|
||||
|
||||
/* ALSA audio interface: */
|
||||
snd_card_register(variax->line6.card);
|
||||
switch (variax->startup_progress) {
|
||||
case VARIAX_STARTUP_VERSIONREQ:
|
||||
/* repeat request until getting the response */
|
||||
schedule_delayed_work(&line6->startup_work,
|
||||
msecs_to_jiffies(VARIAX_STARTUP_DELAY1));
|
||||
/* request firmware version: */
|
||||
line6_version_request_async(line6);
|
||||
break;
|
||||
case VARIAX_STARTUP_ACTIVATE:
|
||||
/* activate device: */
|
||||
variax_activate_async(variax, 1);
|
||||
variax->startup_progress = VARIAX_STARTUP_SETUP;
|
||||
schedule_delayed_work(&line6->startup_work,
|
||||
msecs_to_jiffies(VARIAX_STARTUP_DELAY4));
|
||||
break;
|
||||
case VARIAX_STARTUP_SETUP:
|
||||
/* ALSA audio interface: */
|
||||
snd_card_register(variax->line6.card);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -175,7 +117,7 @@ static void variax_startup6(struct work_struct *work)
|
|||
*/
|
||||
static void line6_variax_process_message(struct usb_line6 *line6)
|
||||
{
|
||||
struct usb_line6_variax *variax = (struct usb_line6_variax *) line6;
|
||||
struct usb_line6_variax *variax = line6_to_variax(line6);
|
||||
const unsigned char *buf = variax->line6.buffer_message;
|
||||
|
||||
switch (buf[0]) {
|
||||
|
@ -186,11 +128,19 @@ static void line6_variax_process_message(struct usb_line6 *line6)
|
|||
case LINE6_SYSEX_BEGIN:
|
||||
if (memcmp(buf + 1, variax_init_version + 1,
|
||||
sizeof(variax_init_version) - 1) == 0) {
|
||||
variax_startup3(variax);
|
||||
if (variax->startup_progress >= VARIAX_STARTUP_ACTIVATE)
|
||||
break;
|
||||
variax->startup_progress = VARIAX_STARTUP_ACTIVATE;
|
||||
cancel_delayed_work(&line6->startup_work);
|
||||
schedule_delayed_work(&line6->startup_work,
|
||||
msecs_to_jiffies(VARIAX_STARTUP_DELAY3));
|
||||
} else if (memcmp(buf + 1, variax_init_done + 1,
|
||||
sizeof(variax_init_done) - 1) == 0) {
|
||||
/* notify of complete initialization: */
|
||||
variax_startup4(&variax->startup_timer2);
|
||||
if (variax->startup_progress >= VARIAX_STARTUP_SETUP)
|
||||
break;
|
||||
cancel_delayed_work(&line6->startup_work);
|
||||
schedule_delayed_work(&line6->startup_work, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -201,11 +151,7 @@ static void line6_variax_process_message(struct usb_line6 *line6)
|
|||
*/
|
||||
static void line6_variax_disconnect(struct usb_line6 *line6)
|
||||
{
|
||||
struct usb_line6_variax *variax = (struct usb_line6_variax *)line6;
|
||||
|
||||
del_timer(&variax->startup_timer1);
|
||||
del_timer(&variax->startup_timer2);
|
||||
cancel_work_sync(&variax->startup_work);
|
||||
struct usb_line6_variax *variax = line6_to_variax(line6);
|
||||
|
||||
kfree(variax->buffer_activate);
|
||||
}
|
||||
|
@ -216,15 +162,12 @@ static void line6_variax_disconnect(struct usb_line6 *line6)
|
|||
static int variax_init(struct usb_line6 *line6,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct usb_line6_variax *variax = (struct usb_line6_variax *) line6;
|
||||
struct usb_line6_variax *variax = line6_to_variax(line6);
|
||||
int err;
|
||||
|
||||
line6->process_message = line6_variax_process_message;
|
||||
line6->disconnect = line6_variax_disconnect;
|
||||
|
||||
timer_setup(&variax->startup_timer1, NULL, 0);
|
||||
timer_setup(&variax->startup_timer2, NULL, 0);
|
||||
INIT_WORK(&variax->startup_work, variax_startup6);
|
||||
line6->startup = variax_startup;
|
||||
|
||||
/* initialize USB buffers: */
|
||||
variax->buffer_activate = kmemdup(variax_activate,
|
||||
|
@ -239,7 +182,8 @@ static int variax_init(struct usb_line6 *line6,
|
|||
return err;
|
||||
|
||||
/* initiate startup procedure: */
|
||||
variax_startup1(variax);
|
||||
schedule_delayed_work(&line6->startup_work,
|
||||
msecs_to_jiffies(VARIAX_STARTUP_DELAY1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue