Commit e1a164d7 authored by Markus Grabner's avatar Markus Grabner Committed by Greg Kroah-Hartman

Staging: line6: another upstream sync

Everything should be in sync now.
Signed-off-by: default avatarMarkus Grabner <grabner@icg.tugraz.at>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 1027f476
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -15,11 +15,9 @@ ...@@ -15,11 +15,9 @@
#include "driver.h" #include "driver.h"
#include "audio.h" #include "audio.h"
static int line6_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; static int line6_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *line6_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; static char *line6_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
/* /*
Initialize the Line6 USB audio system. Initialize the Line6 USB audio system.
*/ */
...@@ -39,8 +37,7 @@ int line6_init_audio(struct usb_line6 *line6) ...@@ -39,8 +37,7 @@ int line6_init_audio(struct usb_line6 *line6)
strcpy(card->id, line6->properties->id); strcpy(card->id, line6->properties->id);
strcpy(card->driver, DRIVER_NAME); strcpy(card->driver, DRIVER_NAME);
strcpy(card->shortname, line6->properties->name); strcpy(card->shortname, line6->properties->name);
sprintf(card->longname, "Line6 %s at USB %s", line6->properties->name, sprintf(card->longname, "Line6 %s at USB %s", line6->properties->name, dev_name(line6->ifcdev)); /* 80 chars - see asound.h */
dev_name(line6->ifcdev)); /* 80 chars - see asound.h */
return 0; return 0;
} }
......
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -12,13 +12,10 @@ ...@@ -12,13 +12,10 @@
#ifndef AUDIO_H #ifndef AUDIO_H
#define AUDIO_H #define AUDIO_H
#include "driver.h" #include "driver.h"
extern void line6_cleanup_audio(struct usb_line6 *); extern void line6_cleanup_audio(struct usb_line6 *);
extern int line6_init_audio(struct usb_line6 *); extern int line6_init_audio(struct usb_line6 *);
extern int line6_register_audio(struct usb_line6 *); extern int line6_register_audio(struct usb_line6 *);
#endif #endif
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include "pcm.h" #include "pcm.h"
#include "pod.h" #include "pod.h"
/* /*
Find a free URB and submit it. Find a free URB and submit it.
*/ */
...@@ -28,6 +27,7 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm) ...@@ -28,6 +27,7 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
int index; int index;
unsigned long flags; unsigned long flags;
int i, urb_size; int i, urb_size;
int ret;
struct urb *urb_in; struct urb *urb_in;
spin_lock_irqsave(&line6pcm->lock_audio_in, flags); spin_lock_irqsave(&line6pcm->lock_audio_in, flags);
...@@ -57,11 +57,13 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm) ...@@ -57,11 +57,13 @@ static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
urb_in->transfer_buffer_length = urb_size; urb_in->transfer_buffer_length = urb_size;
urb_in->context = line6pcm; urb_in->context = line6pcm;
if (usb_submit_urb(urb_in, GFP_ATOMIC) == 0) ret = usb_submit_urb(urb_in, GFP_ATOMIC);
if (ret == 0)
set_bit(index, &line6pcm->active_urb_in); set_bit(index, &line6pcm->active_urb_in);
else else
dev_err(line6pcm->line6->ifcdev, dev_err(line6pcm->line6->ifcdev,
"URB in #%d submission failed\n", index); "URB in #%d submission failed (%d)\n", index, ret);
spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags); spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags);
return 0; return 0;
...@@ -216,7 +218,7 @@ static void audio_in_callback(struct urb *urb) ...@@ -216,7 +218,7 @@ static void audio_in_callback(struct urb *urb)
int fsize; int fsize;
struct usb_iso_packet_descriptor *fin = &urb->iso_frame_desc[i]; struct usb_iso_packet_descriptor *fin = &urb->iso_frame_desc[i];
if (fin->status == -18) { if (fin->status == -EXDEV) {
shutdown = 1; shutdown = 1;
break; break;
} }
...@@ -258,6 +260,9 @@ static void audio_in_callback(struct urb *urb) ...@@ -258,6 +260,9 @@ static void audio_in_callback(struct urb *urb)
if (!shutdown) { if (!shutdown) {
submit_audio_in_urb(line6pcm); submit_audio_in_urb(line6pcm);
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
if (!(line6pcm->flags & MASK_PCM_IMPULSE))
#endif
if (test_bit(BIT_PCM_ALSA_CAPTURE, &line6pcm->flags)) if (test_bit(BIT_PCM_ALSA_CAPTURE, &line6pcm->flags))
line6_capture_check_period(line6pcm, length); line6_capture_check_period(line6pcm, length);
} }
...@@ -272,8 +277,8 @@ static int snd_line6_capture_open(struct snd_pcm_substream *substream) ...@@ -272,8 +277,8 @@ static int snd_line6_capture_open(struct snd_pcm_substream *substream)
err = snd_pcm_hw_constraint_ratdens(runtime, 0, err = snd_pcm_hw_constraint_ratdens(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE, SNDRV_PCM_HW_PARAM_RATE,
(&line6pcm->properties-> (&line6pcm->
snd_line6_rates)); properties->snd_line6_rates));
if (err < 0) if (err < 0)
return err; return err;
...@@ -396,8 +401,8 @@ int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm) ...@@ -396,8 +401,8 @@ int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm)
urb->dev = line6pcm->line6->usbdev; urb->dev = line6pcm->line6->usbdev;
urb->pipe = urb->pipe =
usb_rcvisocpipe(line6pcm->line6->usbdev, usb_rcvisocpipe(line6pcm->line6->usbdev,
line6pcm-> line6pcm->ep_audio_read &
ep_audio_read & USB_ENDPOINT_NUMBER_MASK); USB_ENDPOINT_NUMBER_MASK);
urb->transfer_flags = URB_ISO_ASAP; urb->transfer_flags = URB_ISO_ASAP;
urb->start_frame = -1; urb->start_frame = -1;
urb->number_of_packets = LINE6_ISO_PACKETS; urb->number_of_packets = LINE6_ISO_PACKETS;
......
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -12,17 +12,17 @@ ...@@ -12,17 +12,17 @@
#ifndef CAPTURE_H #ifndef CAPTURE_H
#define CAPTURE_H #define CAPTURE_H
#include <sound/pcm.h> #include <sound/pcm.h>
#include "driver.h" #include "driver.h"
#include "pcm.h" #include "pcm.h"
extern struct snd_pcm_ops snd_line6_capture_ops; extern struct snd_pcm_ops snd_line6_capture_ops;
extern void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, extern void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf,
int fsize); int fsize);
extern void line6_capture_check_period(struct snd_line6_pcm *line6pcm,
int length);
extern int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm); extern int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm);
extern int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm); extern int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm);
extern void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm); extern void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm);
......
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
......
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -22,7 +22,9 @@ ...@@ -22,7 +22,9 @@
from "control.h", and this process depends on the exact formatting of the from "control.h", and this process depends on the exact formatting of the
code and the comments below! code and the comments below!
*/ */
/* *INDENT-OFF* */ /* *INDENT-OFF* */
enum { enum {
POD_tweak = 1, POD_tweak = 1,
POD_wah_position = 4, POD_wah_position = 4,
...@@ -181,11 +183,13 @@ enum { ...@@ -181,11 +183,13 @@ enum {
VARIAXMIDI_tone = 79, VARIAXMIDI_tone = 79,
}; };
/* *INDENT-ON* */
extern int line6_pod_create_files(int firmware, int type, struct device *dev); extern int line6_pod_create_files(int firmware, int type, struct device *dev);
extern void line6_pod_remove_files(int firmware, int type, struct device *dev); extern void line6_pod_remove_files(int firmware, int type, struct device *dev);
extern int line6_variax_create_files(int firmware, int type, struct device *dev); extern int line6_variax_create_files(int firmware, int type,
extern void line6_variax_remove_files(int firmware, int type, struct device *dev); struct device *dev);
extern void line6_variax_remove_files(int firmware, int type,
struct device *dev);
#endif #endif
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -26,35 +26,35 @@ ...@@ -26,35 +26,35 @@
#include "usbdefs.h" #include "usbdefs.h"
#include "variax.h" #include "variax.h"
#define DRIVER_AUTHOR "Markus Grabner <grabner@icg.tugraz.at>" #define DRIVER_AUTHOR "Markus Grabner <grabner@icg.tugraz.at>"
#define DRIVER_DESC "Line6 USB Driver" #define DRIVER_DESC "Line6 USB Driver"
#define DRIVER_VERSION "0.9.0" #define DRIVER_VERSION "0.9.1beta" DRIVER_REVISION
/* table of devices that work with this driver */ /* table of devices that work with this driver */
static const struct usb_device_id line6_id_table[] = { static const struct usb_device_id line6_id_table[] = {
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXT) }, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXT)},
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXTLIVE) }, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXTLIVE)},
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXTPRO) }, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXTPRO)},
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_GUITARPORT) }, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_GUITARPORT)},
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_POCKETPOD) }, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_POCKETPOD)},
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_GX) }, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_GX)},
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_UX1) }, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_UX1)},
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_UX2) }, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_UX2)},
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODX3) }, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODX3)},
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODX3LIVE) }, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODX3LIVE)},
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODXT) }, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODXT)},
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODXTLIVE) }, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODXTLIVE)},
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODXTPRO) }, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODXTPRO)},
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_TONEPORT_GX) }, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_TONEPORT_GX)},
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_TONEPORT_UX1) }, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_TONEPORT_UX1)},
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_TONEPORT_UX2) }, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_TONEPORT_UX2)},
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_VARIAX) }, {USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_VARIAX)},
{ }, {},
}; };
MODULE_DEVICE_TABLE(usb, line6_id_table); MODULE_DEVICE_TABLE(usb, line6_id_table);
/* *INDENT-OFF* */
static struct line6_properties line6_properties_table[] = { static struct line6_properties line6_properties_table[] = {
{ "BassPODxt", "BassPODxt", LINE6_BIT_BASSPODXT, LINE6_BIT_CONTROL_PCM_HWMON }, { "BassPODxt", "BassPODxt", LINE6_BIT_BASSPODXT, LINE6_BIT_CONTROL_PCM_HWMON },
{ "BassPODxtLive", "BassPODxt Live", LINE6_BIT_BASSPODXTLIVE, LINE6_BIT_CONTROL_PCM_HWMON }, { "BassPODxtLive", "BassPODxt Live", LINE6_BIT_BASSPODXTLIVE, LINE6_BIT_CONTROL_PCM_HWMON },
...@@ -74,7 +74,7 @@ static struct line6_properties line6_properties_table[] = { ...@@ -74,7 +74,7 @@ static struct line6_properties line6_properties_table[] = {
{ "TonePortUX2", "TonePort UX2", LINE6_BIT_TONEPORT_UX2, LINE6_BIT_PCM }, { "TonePortUX2", "TonePort UX2", LINE6_BIT_TONEPORT_UX2, LINE6_BIT_PCM },
{ "Variax", "Variax Workbench", LINE6_BIT_VARIAX, LINE6_BIT_CONTROL } { "Variax", "Variax Workbench", LINE6_BIT_VARIAX, LINE6_BIT_CONTROL }
}; };
/* *INDENT-ON* */
/* /*
This is Line6's MIDI manufacturer ID. This is Line6's MIDI manufacturer ID.
...@@ -96,10 +96,8 @@ static const char line6_request_version0[] = { ...@@ -96,10 +96,8 @@ static const char line6_request_version0[] = {
*/ */
static const char *line6_request_version; static const char *line6_request_version;
struct usb_line6 *line6_devices[LINE6_MAX_DEVICES]; struct usb_line6 *line6_devices[LINE6_MAX_DEVICES];
/** /**
Class for asynchronous messages. Class for asynchronous messages.
*/ */
...@@ -110,7 +108,6 @@ struct message { ...@@ -110,7 +108,6 @@ struct message {
int done; int done;
}; };
/* /*
Forward declarations. Forward declarations.
*/ */
...@@ -118,7 +115,6 @@ static void line6_data_received(struct urb *urb); ...@@ -118,7 +115,6 @@ static void line6_data_received(struct urb *urb);
static int line6_send_raw_message_async_part(struct message *msg, static int line6_send_raw_message_async_part(struct message *msg,
struct urb *urb); struct urb *urb);
/* /*
Start to listen on endpoint. Start to listen on endpoint.
*/ */
...@@ -130,7 +126,7 @@ static int line6_start_listen(struct usb_line6 *line6) ...@@ -130,7 +126,7 @@ static int line6_start_listen(struct usb_line6 *line6)
line6->buffer_listen, LINE6_BUFSIZE_LISTEN, line6->buffer_listen, LINE6_BUFSIZE_LISTEN,
line6_data_received, line6, line6->interval); line6_data_received, line6, line6->interval);
line6->urb_listen->actual_length = 0; line6->urb_listen->actual_length = 0;
err = usb_submit_urb(line6->urb_listen, GFP_KERNEL); err = usb_submit_urb(line6->urb_listen, GFP_ATOMIC);
return err; return err;
} }
...@@ -166,7 +162,8 @@ void line6_write_hexdump(struct usb_line6 *line6, char dir, ...@@ -166,7 +162,8 @@ void line6_write_hexdump(struct usb_line6 *line6, char dir,
if (j < n) { if (j < n) {
unsigned char val = buffer[i + j]; unsigned char val = buffer[i + j];
bytes = snprintf(p, hexdumpsize, " %02X", val); bytes = snprintf(p, hexdumpsize, " %02X", val);
asc[j] = ((val >= 0x20) && (val < 0x7f)) ? val : '.'; asc[j] = ((val >= 0x20)
&& (val < 0x7f)) ? val : '.';
} else } else
bytes = snprintf(p, hexdumpsize, " "); bytes = snprintf(p, hexdumpsize, " ");
...@@ -286,7 +283,7 @@ static int line6_send_raw_message_async_part(struct message *msg, ...@@ -286,7 +283,7 @@ static int line6_send_raw_message_async_part(struct message *msg,
Setup and start timer. Setup and start timer.
*/ */
void line6_start_timer(struct timer_list *timer, unsigned int msecs, void line6_start_timer(struct timer_list *timer, unsigned int msecs,
void (*function)(unsigned long), unsigned long data) void (*function) (unsigned long), unsigned long data)
{ {
setup_timer(timer, function, data); setup_timer(timer, function, data);
timer->expires = jiffies + msecs * HZ / 1000; timer->expires = jiffies + msecs * HZ / 1000;
...@@ -334,7 +331,8 @@ int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer, ...@@ -334,7 +331,8 @@ int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer,
*/ */
int line6_version_request_async(struct usb_line6 *line6) int line6_version_request_async(struct usb_line6 *line6)
{ {
return line6_send_raw_message_async(line6, line6_request_version, sizeof(line6_request_version0)); return line6_send_raw_message_async(line6, line6_request_version,
sizeof(line6_request_version0));
} }
/* /*
...@@ -343,7 +341,9 @@ int line6_version_request_async(struct usb_line6 *line6) ...@@ -343,7 +341,9 @@ int line6_version_request_async(struct usb_line6 *line6)
int line6_send_sysex_message(struct usb_line6 *line6, const char *buffer, int line6_send_sysex_message(struct usb_line6 *line6, const char *buffer,
int size) int size)
{ {
return line6_send_raw_message(line6, buffer, size + SYSEX_EXTRA_SIZE) - SYSEX_EXTRA_SIZE; return line6_send_raw_message(line6, buffer,
size + SYSEX_EXTRA_SIZE) -
SYSEX_EXTRA_SIZE;
} }
/* /*
...@@ -352,7 +352,9 @@ int line6_send_sysex_message(struct usb_line6 *line6, const char *buffer, ...@@ -352,7 +352,9 @@ int line6_send_sysex_message(struct usb_line6 *line6, const char *buffer,
int line6_send_sysex_message_async(struct usb_line6 *line6, const char *buffer, int line6_send_sysex_message_async(struct usb_line6 *line6, const char *buffer,
int size) int size)
{ {
return line6_send_raw_message_async(line6, buffer, size + SYSEX_EXTRA_SIZE) - SYSEX_EXTRA_SIZE; return line6_send_raw_message_async(line6, buffer,
size + SYSEX_EXTRA_SIZE) -
SYSEX_EXTRA_SIZE;
} }
/* /*
...@@ -394,21 +396,28 @@ static void line6_data_received(struct urb *urb) ...@@ -394,21 +396,28 @@ static void line6_data_received(struct urb *urb)
line6_dump_urb(urb); line6_dump_urb(urb);
#endif #endif
done = line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length); done =
line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length);
if (done < urb->actual_length) { if (done < urb->actual_length) {
line6_midibuf_ignore(mb, done); line6_midibuf_ignore(mb, done);
DEBUG_MESSAGES(dev_err(line6->ifcdev, "%d %d buffer overflow - message skipped\n", done, urb->actual_length)); DEBUG_MESSAGES(dev_err
(line6->ifcdev,
"%d %d buffer overflow - message skipped\n",
done, urb->actual_length));
} }
for (;;) { for (;;) {
done = line6_midibuf_read(mb, line6->buffer_message, LINE6_MESSAGE_MAXLEN); done =
line6_midibuf_read(mb, line6->buffer_message,
LINE6_MESSAGE_MAXLEN);
if (done == 0) if (done == 0)
break; break;
/* MIDI input filter */ /* MIDI input filter */
if (line6_midibuf_skip_message(mb, line6->line6midi->midi_mask_receive)) if (line6_midibuf_skip_message
(mb, line6->line6midi->midi_mask_receive))
continue; continue;
line6->message_length = done; line6->message_length = done;
...@@ -424,26 +433,33 @@ static void line6_data_received(struct urb *urb) ...@@ -424,26 +433,33 @@ static void line6_data_received(struct urb *urb)
case LINE6_DEVID_PODXT: case LINE6_DEVID_PODXT:
case LINE6_DEVID_PODXTPRO: case LINE6_DEVID_PODXTPRO:
case LINE6_DEVID_POCKETPOD: case LINE6_DEVID_POCKETPOD:
line6_pod_process_message((struct usb_line6_pod *)line6); line6_pod_process_message((struct usb_line6_pod *)
line6);
break; break;
case LINE6_DEVID_PODXTLIVE: case LINE6_DEVID_PODXTLIVE:
switch (line6->interface_number) { switch (line6->interface_number) {
case PODXTLIVE_INTERFACE_POD: case PODXTLIVE_INTERFACE_POD:
line6_pod_process_message((struct usb_line6_pod *)line6); line6_pod_process_message((struct usb_line6_pod
*)line6);
break; break;
case PODXTLIVE_INTERFACE_VARIAX: case PODXTLIVE_INTERFACE_VARIAX:
line6_variax_process_message((struct usb_line6_variax *)line6); line6_variax_process_message((struct
usb_line6_variax
*)line6);
break; break;
default: default:
dev_err(line6->ifcdev, "PODxt Live interface %d not supported\n", line6->interface_number); dev_err(line6->ifcdev,
"PODxt Live interface %d not supported\n",
line6->interface_number);
} }
break; break;
case LINE6_DEVID_VARIAX: case LINE6_DEVID_VARIAX:
line6_variax_process_message((struct usb_line6_variax *)line6); line6_variax_process_message((struct usb_line6_variax *)
line6);
break; break;
default: default:
...@@ -483,7 +499,8 @@ int line6_send_program(struct usb_line6 *line6, int value) ...@@ -483,7 +499,8 @@ int line6_send_program(struct usb_line6 *line6, int value)
buffer, 2, &partial, LINE6_TIMEOUT * HZ); buffer, 2, &partial, LINE6_TIMEOUT * HZ);
if (retval) if (retval)
dev_err(line6->ifcdev, "usb_interrupt_msg failed (%d)\n", retval); dev_err(line6->ifcdev, "usb_interrupt_msg failed (%d)\n",
retval);
kfree(buffer); kfree(buffer);
return retval; return retval;
...@@ -514,11 +531,13 @@ int line6_transmit_parameter(struct usb_line6 *line6, int param, int value) ...@@ -514,11 +531,13 @@ int line6_transmit_parameter(struct usb_line6 *line6, int param, int value)
#endif #endif
retval = usb_interrupt_msg(line6->usbdev, retval = usb_interrupt_msg(line6->usbdev,
usb_sndintpipe(line6->usbdev, line6->ep_control_write), usb_sndintpipe(line6->usbdev,
line6->ep_control_write),
buffer, 3, &partial, LINE6_TIMEOUT * HZ); buffer, 3, &partial, LINE6_TIMEOUT * HZ);
if (retval) if (retval)
dev_err(line6->ifcdev, "usb_interrupt_msg failed (%d)\n", retval); dev_err(line6->ifcdev, "usb_interrupt_msg failed (%d)\n",
retval);
kfree(buffer); kfree(buffer);
return retval; return retval;
...@@ -527,7 +546,8 @@ int line6_transmit_parameter(struct usb_line6 *line6, int param, int value) ...@@ -527,7 +546,8 @@ int line6_transmit_parameter(struct usb_line6 *line6, int param, int value)
/* /*
Read data from device. Read data from device.
*/ */
int line6_read_data(struct usb_line6 *line6, int address, void *data, size_t datalen) int line6_read_data(struct usb_line6 *line6, int address, void *data,
size_t datalen)
{ {
struct usb_device *usbdev = line6->usbdev; struct usb_device *usbdev = line6->usbdev;
int ret; int ret;
...@@ -615,8 +635,7 @@ int line6_write_data(struct usb_line6 *line6, int address, void *data, ...@@ -615,8 +635,7 @@ int line6_write_data(struct usb_line6 *line6, int address, void *data,
return ret; return ret;
} }
} }
while (status == 0xff) while (status == 0xff);
;
if (status != 0) { if (status != 0) {
dev_err(line6->ifcdev, "write failed (error %d)\n", ret); dev_err(line6->ifcdev, "write failed (error %d)\n", ret);
...@@ -632,7 +651,8 @@ int line6_write_data(struct usb_line6 *line6, int address, void *data, ...@@ -632,7 +651,8 @@ int line6_write_data(struct usb_line6 *line6, int address, void *data,
*/ */
int line6_read_serial_number(struct usb_line6 *line6, int *serial_number) int line6_read_serial_number(struct usb_line6 *line6, int *serial_number)
{ {
return line6_read_data(line6, 0x80d0, serial_number, sizeof(*serial_number)); return line6_read_data(line6, 0x80d0, serial_number,
sizeof(*serial_number));
} }
/* /*
...@@ -647,7 +667,7 @@ ssize_t line6_nop_read(struct device *dev, struct device_attribute *attr, ...@@ -647,7 +667,7 @@ ssize_t line6_nop_read(struct device *dev, struct device_attribute *attr,
/* /*
No operation (i.e., unsupported). No operation (i.e., unsupported).
*/ */
ssize_t line6_nop_write(struct device *dev, struct device_attribute *attr, ssize_t line6_nop_write(struct device * dev, struct device_attribute * attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
return count; return count;
...@@ -657,7 +677,7 @@ ssize_t line6_nop_write(struct device *dev, struct device_attribute *attr, ...@@ -657,7 +677,7 @@ ssize_t line6_nop_write(struct device *dev, struct device_attribute *attr,
"write" request on "raw" special file. "write" request on "raw" special file.
*/ */
#ifdef CONFIG_LINE6_USB_RAW #ifdef CONFIG_LINE6_USB_RAW
ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr, ssize_t line6_set_raw(struct device * dev, struct device_attribute * attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct usb_interface *interface = to_usb_interface(dev); struct usb_interface *interface = to_usb_interface(dev);
...@@ -697,7 +717,8 @@ static void line6_destruct(struct usb_interface *interface) ...@@ -697,7 +717,8 @@ static void line6_destruct(struct usb_interface *interface)
/* /*
Probe USB device. Probe USB device.
*/ */
static int line6_probe(struct usb_interface *interface, const struct usb_device_id *id) static int line6_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{ {
int devtype; int devtype;
struct usb_device *usbdev = NULL; struct usb_device *usbdev = NULL;
...@@ -903,7 +924,8 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_ ...@@ -903,7 +924,8 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_
} }
if (size == 0) { if (size == 0) {
dev_err(line6->ifcdev, "driver bug: interface data size not set\n"); dev_err(line6->ifcdev,
"driver bug: interface data size not set\n");
ret = -ENODEV; ret = -ENODEV;
goto err_put; goto err_put;
} }
...@@ -928,16 +950,19 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_ ...@@ -928,16 +950,19 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_
/* get data from endpoint descriptor (see usb_maxpacket): */ /* get data from endpoint descriptor (see usb_maxpacket): */
{ {
struct usb_host_endpoint *ep; struct usb_host_endpoint *ep;
unsigned epnum = usb_pipeendpoint(usb_rcvintpipe(usbdev, ep_read)); unsigned epnum =
usb_pipeendpoint(usb_rcvintpipe(usbdev, ep_read));
ep = usbdev->ep_in[epnum]; ep = usbdev->ep_in[epnum];
if (ep != NULL) { if (ep != NULL) {
line6->interval = ep->desc.bInterval; line6->interval = ep->desc.bInterval;
line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); line6->max_packet_size =
le16_to_cpu(ep->desc.wMaxPacketSize);
} else { } else {
line6->interval = LINE6_FALLBACK_INTERVAL; line6->interval = LINE6_FALLBACK_INTERVAL;
line6->max_packet_size = LINE6_FALLBACK_MAXPACKETSIZE; line6->max_packet_size = LINE6_FALLBACK_MAXPACKETSIZE;
dev_err(line6->ifcdev, "endpoint not available, using fallback values"); dev_err(line6->ifcdev,
"endpoint not available, using fallback values");
} }
} }
...@@ -945,7 +970,8 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_ ...@@ -945,7 +970,8 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_
if (properties->capabilities & LINE6_BIT_CONTROL) { if (properties->capabilities & LINE6_BIT_CONTROL) {
/* initialize USB buffers: */ /* initialize USB buffers: */
line6->buffer_listen = kmalloc(LINE6_BUFSIZE_LISTEN, GFP_KERNEL); line6->buffer_listen =
kmalloc(LINE6_BUFSIZE_LISTEN, GFP_KERNEL);
if (line6->buffer_listen == NULL) { if (line6->buffer_listen == NULL) {
dev_err(&interface->dev, "Out of memory\n"); dev_err(&interface->dev, "Out of memory\n");
...@@ -953,7 +979,8 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_ ...@@ -953,7 +979,8 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_
goto err_destruct; goto err_destruct;
} }
line6->buffer_message = kmalloc(LINE6_MESSAGE_MAXLEN, GFP_KERNEL); line6->buffer_message =
kmalloc(LINE6_MESSAGE_MAXLEN, GFP_KERNEL);
if (line6->buffer_message == NULL) { if (line6->buffer_message == NULL) {
dev_err(&interface->dev, "Out of memory\n"); dev_err(&interface->dev, "Out of memory\n");
...@@ -994,11 +1021,15 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_ ...@@ -994,11 +1021,15 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_
case LINE6_DEVID_PODXTLIVE: case LINE6_DEVID_PODXTLIVE:
switch (interface_number) { switch (interface_number) {
case PODXTLIVE_INTERFACE_POD: case PODXTLIVE_INTERFACE_POD:
ret = line6_pod_init(interface, (struct usb_line6_pod *)line6); ret =
line6_pod_init(interface,
(struct usb_line6_pod *)line6);
break; break;
case PODXTLIVE_INTERFACE_VARIAX: case PODXTLIVE_INTERFACE_VARIAX:
ret = line6_variax_init(interface, (struct usb_line6_variax *)line6); ret =
line6_variax_init(interface,
(struct usb_line6_variax *)line6);
break; break;
default: default:
...@@ -1011,7 +1042,9 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_ ...@@ -1011,7 +1042,9 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_
break; break;
case LINE6_DEVID_VARIAX: case LINE6_DEVID_VARIAX:
ret = line6_variax_init(interface, (struct usb_line6_variax *)line6); ret =
line6_variax_init(interface,
(struct usb_line6_variax *)line6);
break; break;
case LINE6_DEVID_PODSTUDIO_GX: case LINE6_DEVID_PODSTUDIO_GX:
...@@ -1021,7 +1054,9 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_ ...@@ -1021,7 +1054,9 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_
case LINE6_DEVID_TONEPORT_UX1: case LINE6_DEVID_TONEPORT_UX1:
case LINE6_DEVID_TONEPORT_UX2: case LINE6_DEVID_TONEPORT_UX2:
case LINE6_DEVID_GUITARPORT: case LINE6_DEVID_GUITARPORT:
ret = line6_toneport_init(interface, (struct usb_line6_toneport *)line6); ret =
line6_toneport_init(interface,
(struct usb_line6_toneport *)line6);
break; break;
default: default:
...@@ -1043,10 +1078,11 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_ ...@@ -1043,10 +1078,11 @@ static int line6_probe(struct usb_interface *interface, const struct usb_device_
line6->properties->name); line6->properties->name);
line6_devices[devnum] = line6; line6_devices[devnum] = line6;
switch(product) { switch (product) {
case LINE6_DEVID_PODX3: case LINE6_DEVID_PODX3:
case LINE6_DEVID_PODX3LIVE: case LINE6_DEVID_PODX3LIVE:
dev_info(&interface->dev, "NOTE: the Line6 %s is detected, but not yet supported\n", dev_info(&interface->dev,
"NOTE: the Line6 %s is detected, but not yet supported\n",
line6->properties->name); line6->properties->name);
} }
...@@ -1137,7 +1173,8 @@ static void line6_disconnect(struct usb_interface *interface) ...@@ -1137,7 +1173,8 @@ static void line6_disconnect(struct usb_interface *interface)
MISSING_CASE; MISSING_CASE;
} }
dev_info(&interface->dev, "Line6 %s now disconnected\n", line6->properties->name); dev_info(&interface->dev, "Line6 %s now disconnected\n",
line6->properties->name);
for (i = LINE6_MAX_DEVICES; i--;) for (i = LINE6_MAX_DEVICES; i--;)
if (line6_devices[i] == line6) if (line6_devices[i] == line6)
...@@ -1231,8 +1268,7 @@ static int __init line6_init(void) ...@@ -1231,8 +1268,7 @@ static int __init line6_init(void)
{ {
int i, retval; int i, retval;
printk(KERN_INFO "%s driver version %s%s\n", printk(KERN_INFO "%s driver version %s\n", DRIVER_NAME, DRIVER_VERSION);
DRIVER_NAME, DRIVER_VERSION, DRIVER_REVISION);
for (i = LINE6_MAX_DEVICES; i--;) for (i = LINE6_MAX_DEVICES; i--;)
line6_devices[i] = NULL; line6_devices[i] = NULL;
...@@ -1263,8 +1299,27 @@ static int __init line6_init(void) ...@@ -1263,8 +1299,27 @@ static int __init line6_init(void)
*/ */
static void __exit line6_exit(void) static void __exit line6_exit(void)
{ {
kfree(line6_request_version); int i;
struct usb_line6 *line6;
struct snd_line6_pcm *line6pcm;
/* stop all PCM channels */
for (i = LINE6_MAX_DEVICES; i--;) {
line6 = line6_devices[i];
if (line6 == NULL)
continue;
line6pcm = line6->line6pcm;
if (line6pcm == NULL)
continue;
line6_pcm_stop(line6pcm, ~0);
}
usb_deregister(&line6_driver); usb_deregister(&line6_driver);
kfree(line6_request_version);
} }
module_init(line6_init); module_init(line6_init);
......
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -12,14 +12,12 @@ ...@@ -12,14 +12,12 @@
#ifndef DRIVER_H #ifndef DRIVER_H
#define DRIVER_H #define DRIVER_H
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <sound/core.h> #include <sound/core.h>
#include "midi.h" #include "midi.h"
#define DRIVER_NAME "line6usb" #define DRIVER_NAME "line6usb"
#if defined(CONFIG_LINE6_USB_DUMP_CTRL) || defined(CONFIG_LINE6_USB_DUMP_MIDI) || defined(CONFIG_LINE6_USB_DUMP_PCM) #if defined(CONFIG_LINE6_USB_DUMP_CTRL) || defined(CONFIG_LINE6_USB_DUMP_MIDI) || defined(CONFIG_LINE6_USB_DUMP_PCM)
...@@ -61,12 +59,10 @@ ...@@ -61,12 +59,10 @@
#define DEBUG_MESSAGES(x) #define DEBUG_MESSAGES(x)
#endif #endif
#define MISSING_CASE \ #define MISSING_CASE \
printk(KERN_ERR "line6usb driver bug: missing case in %s:%d\n", \ printk(KERN_ERR "line6usb driver bug: missing case in %s:%d\n", \
__FILE__, __LINE__) __FILE__, __LINE__)
#define CHECK_RETURN(x) \ #define CHECK_RETURN(x) \
do { \ do { \
err = x; \ err = x; \
...@@ -79,14 +75,12 @@ do { \ ...@@ -79,14 +75,12 @@ do { \
return; \ return; \
x = (n); x = (n);
extern const unsigned char line6_midi_id[3]; extern const unsigned char line6_midi_id[3];
extern struct usb_line6 *line6_devices[LINE6_MAX_DEVICES]; extern struct usb_line6 *line6_devices[LINE6_MAX_DEVICES];
static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3; static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3;
static const int SYSEX_EXTRA_SIZE = sizeof(line6_midi_id) + 4; static const int SYSEX_EXTRA_SIZE = sizeof(line6_midi_id) + 4;
/** /**
Common properties of Line6 devices. Common properties of Line6 devices.
*/ */
...@@ -202,7 +196,6 @@ struct usb_line6 { ...@@ -202,7 +196,6 @@ struct usb_line6 {
int message_length; int message_length;
}; };
extern char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1, extern char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1,
int code2, int size); int code2, int size);
extern ssize_t line6_nop_read(struct device *dev, extern ssize_t line6_nop_read(struct device *dev,
...@@ -226,7 +219,8 @@ extern int line6_send_sysex_message_async(struct usb_line6 *line6, ...@@ -226,7 +219,8 @@ extern int line6_send_sysex_message_async(struct usb_line6 *line6,
extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr, extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count); const char *buf, size_t count);
extern void line6_start_timer(struct timer_list *timer, unsigned int msecs, extern void line6_start_timer(struct timer_list *timer, unsigned int msecs,
void (*function)(unsigned long), unsigned long data); void (*function) (unsigned long),
unsigned long data);
extern int line6_transmit_parameter(struct usb_line6 *line6, int param, extern int line6_transmit_parameter(struct usb_line6 *line6, int param,
int value); int value);
extern int line6_version_request_async(struct usb_line6 *line6); extern int line6_version_request_async(struct usb_line6 *line6);
...@@ -238,5 +232,4 @@ extern void line6_write_hexdump(struct usb_line6 *line6, char dir, ...@@ -238,5 +232,4 @@ extern void line6_write_hexdump(struct usb_line6 *line6, char dir,
const unsigned char *buffer, int size); const unsigned char *buffer, int size);
#endif #endif
#endif #endif
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include "driver.h" #include "driver.h"
#include "dumprequest.h" #include "dumprequest.h"
/* /*
Set "dump in progress" flag. Set "dump in progress" flag.
*/ */
...@@ -63,7 +62,8 @@ int line6_dump_request_async(struct line6_dump_request *l6dr, ...@@ -63,7 +62,8 @@ int line6_dump_request_async(struct line6_dump_request *l6dr,
*/ */
int line6_dump_wait_interruptible(struct line6_dump_request *l6dr) int line6_dump_wait_interruptible(struct line6_dump_request *l6dr)
{ {
return wait_event_interruptible(l6dr->wait, l6dr->in_progress == LINE6_DUMP_NONE); return wait_event_interruptible(l6dr->wait,
l6dr->in_progress == LINE6_DUMP_NONE);
} }
/* /*
...@@ -79,7 +79,9 @@ void line6_dump_wait(struct line6_dump_request *l6dr) ...@@ -79,7 +79,9 @@ void line6_dump_wait(struct line6_dump_request *l6dr)
*/ */
int line6_dump_wait_timeout(struct line6_dump_request *l6dr, long timeout) int line6_dump_wait_timeout(struct line6_dump_request *l6dr, long timeout)
{ {
return wait_event_timeout(l6dr->wait, l6dr->in_progress == LINE6_DUMP_NONE, timeout); return wait_event_timeout(l6dr->wait,
l6dr->in_progress == LINE6_DUMP_NONE,
timeout);
} }
/* /*
......
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -12,18 +12,15 @@ ...@@ -12,18 +12,15 @@
#ifndef DUMPREQUEST_H #ifndef DUMPREQUEST_H
#define DUMPREQUEST_H #define DUMPREQUEST_H
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <sound/core.h> #include <sound/core.h>
enum { enum {
LINE6_DUMP_NONE, LINE6_DUMP_NONE,
LINE6_DUMP_CURRENT LINE6_DUMP_CURRENT
}; };
struct line6_dump_reqbuf { struct line6_dump_reqbuf {
/** /**
Buffer for dump requests. Buffer for dump requests.
...@@ -76,5 +73,4 @@ extern int line6_dump_wait_interruptible(struct line6_dump_request *l6dr); ...@@ -76,5 +73,4 @@ extern int line6_dump_wait_interruptible(struct line6_dump_request *l6dr);
extern int line6_dump_wait_timeout(struct line6_dump_request *l6dr, extern int line6_dump_wait_timeout(struct line6_dump_request *l6dr,
long timeout); long timeout);
#endif #endif
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -20,15 +20,12 @@ ...@@ -20,15 +20,12 @@
#include "pod.h" #include "pod.h"
#include "usbdefs.h" #include "usbdefs.h"
#define line6_rawmidi_substream_midi(substream) \ #define line6_rawmidi_substream_midi(substream) \
((struct snd_line6_midi *)((substream)->rmidi->private_data)) ((struct snd_line6_midi *)((substream)->rmidi->private_data))
static int send_midi_async(struct usb_line6 *line6, unsigned char *data, static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
int length); int length);
/* /*
Pass data received via USB to MIDI. Pass data received via USB to MIDI.
*/ */
...@@ -45,7 +42,8 @@ void line6_midi_receive(struct usb_line6 *line6, unsigned char *data, ...@@ -45,7 +42,8 @@ void line6_midi_receive(struct usb_line6 *line6, unsigned char *data,
*/ */
static void line6_midi_transmit(struct snd_rawmidi_substream *substream) static void line6_midi_transmit(struct snd_rawmidi_substream *substream)
{ {
struct usb_line6 *line6 = line6_rawmidi_substream_midi(substream)->line6; struct usb_line6 *line6 =
line6_rawmidi_substream_midi(substream)->line6;
struct snd_line6_midi *line6midi = line6->line6midi; struct snd_line6_midi *line6midi = line6->line6midi;
struct MidiBuffer *mb = &line6midi->midibuf_out; struct MidiBuffer *mb = &line6midi->midibuf_out;
unsigned long flags; unsigned long flags;
...@@ -74,7 +72,8 @@ static void line6_midi_transmit(struct snd_rawmidi_substream *substream) ...@@ -74,7 +72,8 @@ static void line6_midi_transmit(struct snd_rawmidi_substream *substream)
if (done == 0) if (done == 0)
break; break;
if (line6_midibuf_skip_message(mb, line6midi->midi_mask_transmit)) if (line6_midibuf_skip_message
(mb, line6midi->midi_mask_transmit))
continue; continue;
send_midi_async(line6, chunk, done); send_midi_async(line6, chunk, done);
...@@ -132,7 +131,6 @@ static int send_midi_async(struct usb_line6 *line6, unsigned char *data, ...@@ -132,7 +131,6 @@ static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
dev_err(line6->ifcdev, "Out of memory\n"); dev_err(line6->ifcdev, "Out of memory\n");
return -ENOMEM; return -ENOMEM;
} }
#ifdef CONFIG_LINE6_USB_DUMP_CTRL #ifdef CONFIG_LINE6_USB_DUMP_CTRL
line6_write_hexdump(line6, 'S', data, length); line6_write_hexdump(line6, 'S', data, length);
#endif #endif
...@@ -174,6 +172,9 @@ static int send_midi_async(struct usb_line6 *line6, unsigned char *data, ...@@ -174,6 +172,9 @@ static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
length); length);
break; break;
case LINE6_DEVID_VARIAX:
break;
default: default:
MISSING_CASE; MISSING_CASE;
} }
...@@ -195,7 +196,8 @@ static void line6_midi_output_trigger(struct snd_rawmidi_substream *substream, ...@@ -195,7 +196,8 @@ static void line6_midi_output_trigger(struct snd_rawmidi_substream *substream,
int up) int up)
{ {
unsigned long flags; unsigned long flags;
struct usb_line6 *line6 = line6_rawmidi_substream_midi(substream)->line6; struct usb_line6 *line6 =
line6_rawmidi_substream_midi(substream)->line6;
line6->line6midi->substream_transmit = substream; line6->line6midi->substream_transmit = substream;
spin_lock_irqsave(&line6->line6midi->send_urb_lock, flags); spin_lock_irqsave(&line6->line6midi->send_urb_lock, flags);
...@@ -208,9 +210,11 @@ static void line6_midi_output_trigger(struct snd_rawmidi_substream *substream, ...@@ -208,9 +210,11 @@ static void line6_midi_output_trigger(struct snd_rawmidi_substream *substream,
static void line6_midi_output_drain(struct snd_rawmidi_substream *substream) static void line6_midi_output_drain(struct snd_rawmidi_substream *substream)
{ {
struct usb_line6 *line6 = line6_rawmidi_substream_midi(substream)->line6; struct usb_line6 *line6 =
line6_rawmidi_substream_midi(substream)->line6;
struct snd_line6_midi *midi = line6->line6midi; struct snd_line6_midi *midi = line6->line6midi;
wait_event_interruptible(midi->send_wait, midi->num_active_send_urbs == 0); wait_event_interruptible(midi->send_wait,
midi->num_active_send_urbs == 0);
} }
static int line6_midi_input_open(struct snd_rawmidi_substream *substream) static int line6_midi_input_open(struct snd_rawmidi_substream *substream)
...@@ -226,7 +230,8 @@ static int line6_midi_input_close(struct snd_rawmidi_substream *substream) ...@@ -226,7 +230,8 @@ static int line6_midi_input_close(struct snd_rawmidi_substream *substream)
static void line6_midi_input_trigger(struct snd_rawmidi_substream *substream, static void line6_midi_input_trigger(struct snd_rawmidi_substream *substream,
int up) int up)
{ {
struct usb_line6 *line6 = line6_rawmidi_substream_midi(substream)->line6; struct usb_line6 *line6 =
line6_rawmidi_substream_midi(substream)->line6;
if (up) if (up)
line6->line6midi->substream_receive = substream; line6->line6midi->substream_receive = substream;
...@@ -272,8 +277,7 @@ static int snd_line6_new_midi(struct snd_line6_midi *line6midi) ...@@ -272,8 +277,7 @@ static int snd_line6_new_midi(struct snd_line6_midi *line6midi)
rmidi->info_flags = rmidi->info_flags =
SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_OUTPUT |
SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
SNDRV_RAWMIDI_INFO_DUPLEX;
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
&line6_midi_output_ops); &line6_midi_output_ops);
...@@ -346,15 +350,19 @@ static ssize_t midi_set_midi_mask_receive(struct device *dev, ...@@ -346,15 +350,19 @@ static ssize_t midi_set_midi_mask_receive(struct device *dev,
return count; return count;
} }
static DEVICE_ATTR(midi_mask_transmit, S_IWUGO | S_IRUGO, midi_get_midi_mask_transmit, midi_set_midi_mask_transmit); static DEVICE_ATTR(midi_mask_transmit, S_IWUGO | S_IRUGO,
static DEVICE_ATTR(midi_mask_receive, S_IWUGO | S_IRUGO, midi_get_midi_mask_receive, midi_set_midi_mask_receive); midi_get_midi_mask_transmit, midi_set_midi_mask_transmit);
static DEVICE_ATTR(midi_mask_receive, S_IWUGO | S_IRUGO,
midi_get_midi_mask_receive, midi_set_midi_mask_receive);
/* MIDI device destructor */ /* MIDI device destructor */
static int snd_line6_midi_free(struct snd_device *device) static int snd_line6_midi_free(struct snd_device *device)
{ {
struct snd_line6_midi *line6midi = device->device_data; struct snd_line6_midi *line6midi = device->device_data;
device_remove_file(line6midi->line6->ifcdev, &dev_attr_midi_mask_transmit); device_remove_file(line6midi->line6->ifcdev,
device_remove_file(line6midi->line6->ifcdev, &dev_attr_midi_mask_receive); &dev_attr_midi_mask_transmit);
device_remove_file(line6midi->line6->ifcdev,
&dev_attr_midi_mask_receive);
line6_midibuf_destroy(&line6midi->midibuf_in); line6_midibuf_destroy(&line6midi->midibuf_in);
line6_midibuf_destroy(&line6midi->midibuf_out); line6_midibuf_destroy(&line6midi->midibuf_out);
return 0; return 0;
......
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -12,15 +12,12 @@ ...@@ -12,15 +12,12 @@
#ifndef MIDI_H #ifndef MIDI_H
#define MIDI_H #define MIDI_H
#include <sound/rawmidi.h> #include <sound/rawmidi.h>
#include "midibuf.h" #include "midibuf.h"
#define MIDI_BUFFER_SIZE 1024 #define MIDI_BUFFER_SIZE 1024
struct snd_line6_midi { struct snd_line6_midi {
/** /**
Pointer back to the Line6 driver data structure. Pointer back to the Line6 driver data structure.
...@@ -78,10 +75,8 @@ struct snd_line6_midi { ...@@ -78,10 +75,8 @@ struct snd_line6_midi {
struct MidiBuffer midibuf_out; struct MidiBuffer midibuf_out;
}; };
extern int line6_init_midi(struct usb_line6 *line6); extern int line6_init_midi(struct usb_line6 *line6);
extern void line6_midi_receive(struct usb_line6 *line6, unsigned char *data, extern void line6_midi_receive(struct usb_line6 *line6, unsigned char *data,
int length); int length);
#endif #endif
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include "midibuf.h" #include "midibuf.h"
static int midibuf_message_length(unsigned char code) static int midibuf_message_length(unsigned char code)
{ {
if (code < 0x80) if (code < 0x80)
...@@ -28,7 +27,8 @@ static int midibuf_message_length(unsigned char code) ...@@ -28,7 +27,8 @@ static int midibuf_message_length(unsigned char code)
to send sysex messages to the host. to send sysex messages to the host.
*/ */
static const int length[] = { -1, 2, -1, 2, -1, -1, 1, 1, 1, 1, static const int length[] = { -1, 2, -1, 2, -1, -1, 1, 1, 1, 1,
1, 1, 1, -1, 1, 1 }; 1, 1, 1, -1, 1, 1
};
return length[code & 0x0f]; return length[code & 0x0f];
} }
} }
...@@ -74,7 +74,8 @@ int line6_midibuf_bytes_free(struct MidiBuffer *this) ...@@ -74,7 +74,8 @@ int line6_midibuf_bytes_free(struct MidiBuffer *this)
return return
midibuf_is_full(this) ? midibuf_is_full(this) ?
0 : 0 :
(this->pos_read - this->pos_write + this->size - 1) % this->size + 1; (this->pos_read - this->pos_write + this->size - 1) % this->size +
1;
} }
int line6_midibuf_bytes_used(struct MidiBuffer *this) int line6_midibuf_bytes_used(struct MidiBuffer *this)
...@@ -82,10 +83,12 @@ int line6_midibuf_bytes_used(struct MidiBuffer *this) ...@@ -82,10 +83,12 @@ int line6_midibuf_bytes_used(struct MidiBuffer *this)
return return
midibuf_is_empty(this) ? midibuf_is_empty(this) ?
0 : 0 :
(this->pos_write - this->pos_read + this->size - 1) % this->size + 1; (this->pos_write - this->pos_read + this->size - 1) % this->size +
1;
} }
int line6_midibuf_write(struct MidiBuffer *this, unsigned char *data, int length) int line6_midibuf_write(struct MidiBuffer *this, unsigned char *data,
int length)
{ {
int bytes_free; int bytes_free;
int length1, length2; int length1, length2;
...@@ -158,7 +161,8 @@ int line6_midibuf_read(struct MidiBuffer *this, unsigned char *data, int length) ...@@ -158,7 +161,8 @@ int line6_midibuf_read(struct MidiBuffer *this, unsigned char *data, int length)
this->command_prev = command; this->command_prev = command;
} else { } else {
if (this->command_prev > 0) { if (this->command_prev > 0) {
int midi_length_prev = midibuf_message_length(this->command_prev); int midi_length_prev =
midibuf_message_length(this->command_prev);
if (midi_length_prev > 0) { if (midi_length_prev > 0) {
midi_length = midi_length_prev - 1; midi_length = midi_length_prev - 1;
......
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#ifndef MIDIBUF_H #ifndef MIDIBUF_H
#define MIDIBUF_H #define MIDIBUF_H
struct MidiBuffer { struct MidiBuffer {
unsigned char *buf; unsigned char *buf;
int size; int size;
...@@ -22,18 +21,18 @@ struct MidiBuffer { ...@@ -22,18 +21,18 @@ struct MidiBuffer {
int command_prev; int command_prev;
}; };
extern int line6_midibuf_bytes_used(struct MidiBuffer *mb); extern int line6_midibuf_bytes_used(struct MidiBuffer *mb);
extern int line6_midibuf_bytes_free(struct MidiBuffer *mb); extern int line6_midibuf_bytes_free(struct MidiBuffer *mb);
extern void line6_midibuf_destroy(struct MidiBuffer *mb); extern void line6_midibuf_destroy(struct MidiBuffer *mb);
extern int line6_midibuf_ignore(struct MidiBuffer *mb, int length); extern int line6_midibuf_ignore(struct MidiBuffer *mb, int length);
extern int line6_midibuf_init(struct MidiBuffer *mb, int size, int split); extern int line6_midibuf_init(struct MidiBuffer *mb, int size, int split);
extern int line6_midibuf_read(struct MidiBuffer *mb, unsigned char *data, int length); extern int line6_midibuf_read(struct MidiBuffer *mb, unsigned char *data,
int length);
extern void line6_midibuf_reset(struct MidiBuffer *mb); extern void line6_midibuf_reset(struct MidiBuffer *mb);
extern int line6_midibuf_skip_message(struct MidiBuffer *mb, unsigned short mask); extern int line6_midibuf_skip_message(struct MidiBuffer *mb,
unsigned short mask);
extern void line6_midibuf_status(struct MidiBuffer *mb); extern void line6_midibuf_status(struct MidiBuffer *mb);
extern int line6_midibuf_write(struct MidiBuffer *mb, unsigned char *data, extern int line6_midibuf_write(struct MidiBuffer *mb, unsigned char *data,
int length); int length);
#endif #endif
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -21,10 +21,9 @@ ...@@ -21,10 +21,9 @@
#include "playback.h" #include "playback.h"
#include "pod.h" #include "pod.h"
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
static struct snd_line6_pcm* dev2pcm(struct device *dev) static struct snd_line6_pcm *dev2pcm(struct device *dev)
{ {
struct usb_interface *interface = to_usb_interface(dev); struct usb_interface *interface = to_usb_interface(dev);
struct usb_line6 *line6 = usb_get_intfdata(interface); struct usb_line6 *line6 = usb_get_intfdata(interface);
...@@ -36,8 +35,7 @@ static struct snd_line6_pcm* dev2pcm(struct device *dev) ...@@ -36,8 +35,7 @@ static struct snd_line6_pcm* dev2pcm(struct device *dev)
"read" request on "impulse_volume" special file. "read" request on "impulse_volume" special file.
*/ */
static ssize_t pcm_get_impulse_volume(struct device *dev, static ssize_t pcm_get_impulse_volume(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr, char *buf)
char *buf)
{ {
return sprintf(buf, "%d\n", dev2pcm(dev)->impulse_volume); return sprintf(buf, "%d\n", dev2pcm(dev)->impulse_volume);
} }
...@@ -53,7 +51,7 @@ static ssize_t pcm_set_impulse_volume(struct device *dev, ...@@ -53,7 +51,7 @@ static ssize_t pcm_set_impulse_volume(struct device *dev,
int value = simple_strtoul(buf, NULL, 10); int value = simple_strtoul(buf, NULL, 10);
line6pcm->impulse_volume = value; line6pcm->impulse_volume = value;
if(value > 0) if (value > 0)
line6_pcm_start(line6pcm, MASK_PCM_IMPULSE); line6_pcm_start(line6pcm, MASK_PCM_IMPULSE);
else else
line6_pcm_stop(line6pcm, MASK_PCM_IMPULSE); line6_pcm_stop(line6pcm, MASK_PCM_IMPULSE);
...@@ -65,8 +63,7 @@ static ssize_t pcm_set_impulse_volume(struct device *dev, ...@@ -65,8 +63,7 @@ static ssize_t pcm_set_impulse_volume(struct device *dev,
"read" request on "impulse_period" special file. "read" request on "impulse_period" special file.
*/ */
static ssize_t pcm_get_impulse_period(struct device *dev, static ssize_t pcm_get_impulse_period(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr, char *buf)
char *buf)
{ {
return sprintf(buf, "%d\n", dev2pcm(dev)->impulse_period); return sprintf(buf, "%d\n", dev2pcm(dev)->impulse_period);
} }
...@@ -82,23 +79,29 @@ static ssize_t pcm_set_impulse_period(struct device *dev, ...@@ -82,23 +79,29 @@ static ssize_t pcm_set_impulse_period(struct device *dev,
return count; return count;
} }
static DEVICE_ATTR(impulse_volume, S_IWUGO | S_IRUGO, pcm_get_impulse_volume, pcm_set_impulse_volume); static DEVICE_ATTR(impulse_volume, S_IWUGO | S_IRUGO, pcm_get_impulse_volume,
static DEVICE_ATTR(impulse_period, S_IWUGO | S_IRUGO, pcm_get_impulse_period, pcm_set_impulse_period); pcm_set_impulse_volume);
static DEVICE_ATTR(impulse_period, S_IWUGO | S_IRUGO, pcm_get_impulse_period,
pcm_set_impulse_period);
#endif #endif
int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels) int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)
{ {
unsigned long flags_old = __sync_fetch_and_or(&line6pcm->flags, channels); unsigned long flags_old =
__sync_fetch_and_or(&line6pcm->flags, channels);
unsigned long flags_new = flags_old | channels; unsigned long flags_new = flags_old | channels;
int err = 0; int err = 0;
#if LINE6_BACKUP_MONITOR_SIGNAL #if LINE6_BACKUP_MONITOR_SIGNAL
if (!(line6pcm->line6->properties->capabilities & LINE6_BIT_HWMON)) { if (!(line6pcm->line6->properties->capabilities & LINE6_BIT_HWMON)) {
line6pcm->prev_fbuf = kmalloc(LINE6_ISO_PACKETS * line6pcm->max_packet_size, GFP_KERNEL); line6pcm->prev_fbuf =
kmalloc(LINE6_ISO_PACKETS * line6pcm->max_packet_size,
GFP_KERNEL);
if (!line6pcm->prev_fbuf) { if (!line6pcm->prev_fbuf) {
dev_err(line6pcm->line6->ifcdev, "cannot malloc monitor buffer\n"); dev_err(line6pcm->line6->ifcdev,
"cannot malloc monitor buffer\n");
return -ENOMEM; return -ENOMEM;
} }
} }
...@@ -113,13 +116,16 @@ int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels) ...@@ -113,13 +116,16 @@ int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)
a bug, we therefore report an error if capturing is restarted a bug, we therefore report an error if capturing is restarted
too soon. too soon.
*/ */
if(line6pcm->active_urb_in | line6pcm->unlink_urb_in) if (line6pcm->active_urb_in | line6pcm->unlink_urb_in)
return -EBUSY; return -EBUSY;
line6pcm->buffer_in = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * line6pcm->max_packet_size, GFP_KERNEL); line6pcm->buffer_in =
kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
line6pcm->max_packet_size, GFP_KERNEL);
if (!line6pcm->buffer_in) { if (!line6pcm->buffer_in) {
dev_err(line6pcm->line6->ifcdev, "cannot malloc capture buffer\n"); dev_err(line6pcm->line6->ifcdev,
"cannot malloc capture buffer\n");
return -ENOMEM; return -ENOMEM;
} }
...@@ -138,13 +144,16 @@ int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels) ...@@ -138,13 +144,16 @@ int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)
/* /*
See comment above regarding PCM restart. See comment above regarding PCM restart.
*/ */
if(line6pcm->active_urb_out | line6pcm->unlink_urb_out) if (line6pcm->active_urb_out | line6pcm->unlink_urb_out)
return -EBUSY; return -EBUSY;
line6pcm->buffer_out = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * line6pcm->max_packet_size, GFP_KERNEL); line6pcm->buffer_out =
kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
line6pcm->max_packet_size, GFP_KERNEL);
if (!line6pcm->buffer_out) { if (!line6pcm->buffer_out) {
dev_err(line6pcm->line6->ifcdev, "cannot malloc playback buffer\n"); dev_err(line6pcm->line6->ifcdev,
"cannot malloc playback buffer\n");
return -ENOMEM; return -ENOMEM;
} }
...@@ -162,7 +171,8 @@ int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels) ...@@ -162,7 +171,8 @@ int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)
int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels) int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels)
{ {
unsigned long flags_old = __sync_fetch_and_and(&line6pcm->flags, ~channels); unsigned long flags_old =
__sync_fetch_and_and(&line6pcm->flags, ~channels);
unsigned long flags_new = flags_old & ~channels; unsigned long flags_new = flags_old & ~channels;
if (((flags_old & MASK_CAPTURE) != 0) && if (((flags_old & MASK_CAPTURE) != 0) &&
...@@ -178,7 +188,6 @@ int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels) ...@@ -178,7 +188,6 @@ int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels)
kfree(line6pcm->buffer_out); kfree(line6pcm->buffer_out);
line6pcm->buffer_out = NULL; line6pcm->buffer_out = NULL;
} }
#if LINE6_BACKUP_MONITOR_SIGNAL #if LINE6_BACKUP_MONITOR_SIGNAL
if (line6pcm->prev_fbuf != NULL) if (line6pcm->prev_fbuf != NULL)
kfree(line6pcm->prev_fbuf); kfree(line6pcm->prev_fbuf);
...@@ -223,8 +232,8 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd) ...@@ -223,8 +232,8 @@ int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
break; break;
default: default:
dev_err(line6pcm->line6->ifcdev, "Unknown stream direction %d\n", dev_err(line6pcm->line6->ifcdev,
s->stream); "Unknown stream direction %d\n", s->stream);
} }
} }
...@@ -264,8 +273,10 @@ static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol, ...@@ -264,8 +273,10 @@ static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol,
struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
for (i = 2; i--;) for (i = 2; i--;)
if (line6pcm->volume_playback[i] != ucontrol->value.integer.value[i]) { if (line6pcm->volume_playback[i] !=
line6pcm->volume_playback[i] = ucontrol->value.integer.value[i]; ucontrol->value.integer.value[i]) {
line6pcm->volume_playback[i] =
ucontrol->value.integer.value[i];
changed = 1; changed = 1;
} }
...@@ -328,13 +339,13 @@ static int snd_line6_new_pcm(struct snd_line6_pcm *line6pcm) ...@@ -328,13 +339,13 @@ static int snd_line6_new_pcm(struct snd_line6_pcm *line6pcm)
/* set operators */ /* set operators */
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
&snd_line6_playback_ops); &snd_line6_playback_ops);
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops);
&snd_line6_capture_ops);
/* pre-allocation of buffers */ /* pre-allocation of buffers */
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
snd_dma_continuous_data(GFP_KERNEL), snd_dma_continuous_data
64 * 1024, 128 * 1024); (GFP_KERNEL), 64 * 1024,
128 * 1024);
return 0; return 0;
} }
...@@ -350,7 +361,7 @@ static int snd_line6_pcm_free(struct snd_device *device) ...@@ -350,7 +361,7 @@ static int snd_line6_pcm_free(struct snd_device *device)
*/ */
static void pcm_disconnect_substream(struct snd_pcm_substream *substream) static void pcm_disconnect_substream(struct snd_pcm_substream *substream)
{ {
if(substream->runtime && snd_pcm_running(substream)) { if (substream->runtime && snd_pcm_running(substream)) {
snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
} }
} }
...@@ -360,8 +371,10 @@ static void pcm_disconnect_substream(struct snd_pcm_substream *substream) ...@@ -360,8 +371,10 @@ static void pcm_disconnect_substream(struct snd_pcm_substream *substream)
*/ */
void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm) void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)
{ {
pcm_disconnect_substream(get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE)); pcm_disconnect_substream(get_substream
pcm_disconnect_substream(get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)); (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_out_urbs(line6pcm);
line6_unlink_wait_clear_audio_in_urbs(line6pcm); line6_unlink_wait_clear_audio_in_urbs(line6pcm);
} }
...@@ -442,8 +455,7 @@ int line6_init_pcm(struct usb_line6 *line6, ...@@ -442,8 +455,7 @@ int line6_init_pcm(struct usb_line6 *line6,
line6pcm->ep_audio_write = ep_write; line6pcm->ep_audio_write = ep_write;
line6pcm->max_packet_size = usb_maxpacket(line6->usbdev, line6pcm->max_packet_size = usb_maxpacket(line6->usbdev,
usb_rcvintpipe(line6->usbdev, usb_rcvintpipe(line6->usbdev,
ep_read), ep_read), 0);
0);
line6pcm->properties = properties; line6pcm->properties = properties;
line6->line6pcm = line6pcm; line6->line6pcm = line6pcm;
...@@ -471,7 +483,9 @@ int line6_init_pcm(struct usb_line6 *line6, ...@@ -471,7 +483,9 @@ int line6_init_pcm(struct usb_line6 *line6,
return err; return err;
/* mixer: */ /* mixer: */
err = snd_ctl_add(line6->card, snd_ctl_new1(&line6_control_playback, line6pcm)); err =
snd_ctl_add(line6->card,
snd_ctl_new1(&line6_control_playback, line6pcm));
if (err < 0) if (err < 0)
return err; return err;
......
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -16,13 +16,11 @@ ...@@ -16,13 +16,11 @@
#ifndef PCM_H #ifndef PCM_H
#define PCM_H #define PCM_H
#include <sound/pcm.h> #include <sound/pcm.h>
#include "driver.h" #include "driver.h"
#include "usbdefs.h" #include "usbdefs.h"
/* number of URBs */ /* number of URBs */
#define LINE6_ISO_BUFFERS 2 #define LINE6_ISO_BUFFERS 2
...@@ -44,13 +42,11 @@ ...@@ -44,13 +42,11 @@
#define LINE6_BACKUP_MONITOR_SIGNAL 0 #define LINE6_BACKUP_MONITOR_SIGNAL 0
#define LINE6_REUSE_DMA_AREA_FOR_PLAYBACK 0 #define LINE6_REUSE_DMA_AREA_FOR_PLAYBACK 0
/* /*
Get substream from Line6 PCM data structure Get substream from Line6 PCM data structure
*/ */
#define get_substream(line6pcm, stream) (line6pcm->pcm->streams[stream].substream) #define get_substream(line6pcm, stream) (line6pcm->pcm->streams[stream].substream)
/* /*
PCM mode bits and masks. PCM mode bits and masks.
"ALSA": operations triggered by applications via ALSA "ALSA": operations triggered by applications via ALSA
...@@ -71,6 +67,7 @@ enum { ...@@ -71,6 +67,7 @@ enum {
BIT_PREPARED, BIT_PREPARED,
/* individual masks: */ /* individual masks: */
/* *INDENT-OFF* */
MASK_PCM_ALSA_PLAYBACK = 1 << BIT_PCM_ALSA_PLAYBACK, MASK_PCM_ALSA_PLAYBACK = 1 << BIT_PCM_ALSA_PLAYBACK,
MASK_PCM_ALSA_CAPTURE = 1 << BIT_PCM_ALSA_CAPTURE, MASK_PCM_ALSA_CAPTURE = 1 << BIT_PCM_ALSA_CAPTURE,
MASK_PCM_MONITOR_PLAYBACK = 1 << BIT_PCM_MONITOR_PLAYBACK, MASK_PCM_MONITOR_PLAYBACK = 1 << BIT_PCM_MONITOR_PLAYBACK,
...@@ -81,6 +78,7 @@ enum { ...@@ -81,6 +78,7 @@ enum {
#endif #endif
MASK_PAUSE_PLAYBACK = 1 << BIT_PAUSE_PLAYBACK, MASK_PAUSE_PLAYBACK = 1 << BIT_PAUSE_PLAYBACK,
MASK_PREPARED = 1 << BIT_PREPARED, MASK_PREPARED = 1 << BIT_PREPARED,
/* *INDENT-ON* */
/* combined masks (by operation): */ /* combined masks (by operation): */
MASK_PCM_ALSA = MASK_PCM_ALSA_PLAYBACK | MASK_PCM_ALSA_CAPTURE, MASK_PCM_ALSA = MASK_PCM_ALSA_PLAYBACK | MASK_PCM_ALSA_CAPTURE,
...@@ -91,8 +89,12 @@ enum { ...@@ -91,8 +89,12 @@ enum {
/* combined masks (by direction): */ /* combined masks (by direction): */
#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
MASK_PLAYBACK = MASK_PCM_ALSA_PLAYBACK | MASK_PCM_MONITOR_PLAYBACK | MASK_PCM_IMPULSE_PLAYBACK, MASK_PLAYBACK =
MASK_CAPTURE = MASK_PCM_ALSA_CAPTURE | MASK_PCM_MONITOR_CAPTURE | MASK_PCM_IMPULSE_CAPTURE MASK_PCM_ALSA_PLAYBACK | MASK_PCM_MONITOR_PLAYBACK |
MASK_PCM_IMPULSE_PLAYBACK,
MASK_CAPTURE =
MASK_PCM_ALSA_CAPTURE | MASK_PCM_MONITOR_CAPTURE |
MASK_PCM_IMPULSE_CAPTURE
#else #else
MASK_PLAYBACK = MASK_PCM_ALSA_PLAYBACK | MASK_PCM_MONITOR_PLAYBACK, MASK_PLAYBACK = MASK_PCM_ALSA_PLAYBACK | MASK_PCM_MONITOR_PLAYBACK,
MASK_CAPTURE = MASK_PCM_ALSA_CAPTURE | MASK_PCM_MONITOR_CAPTURE MASK_CAPTURE = MASK_PCM_ALSA_CAPTURE | MASK_PCM_MONITOR_CAPTURE
...@@ -302,7 +304,6 @@ struct snd_line6_pcm { ...@@ -302,7 +304,6 @@ struct snd_line6_pcm {
int last_frame_in, last_frame_out; int last_frame_in, last_frame_out;
}; };
extern int line6_init_pcm(struct usb_line6 *line6, extern int line6_init_pcm(struct usb_line6 *line6,
struct line6_pcm_properties *properties); struct line6_pcm_properties *properties);
extern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd); extern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd);
...@@ -311,7 +312,6 @@ extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm); ...@@ -311,7 +312,6 @@ extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm);
extern int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels); extern int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels);
extern int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels); extern int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels);
#define PRINT_FRAME_DIFF(op) { \ #define PRINT_FRAME_DIFF(op) { \
static int diff_prev = 1000; \ static int diff_prev = 1000; \
int diff = line6pcm->last_frame_out - line6pcm->last_frame_in; \ int diff = line6pcm->last_frame_out - line6pcm->last_frame_in; \
...@@ -321,5 +321,4 @@ extern int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels); ...@@ -321,5 +321,4 @@ extern int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels);
} \ } \
} }
#endif #endif
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -68,7 +68,16 @@ static void create_impulse_test_signal(struct snd_line6_pcm *line6pcm, ...@@ -68,7 +68,16 @@ static void create_impulse_test_signal(struct snd_line6_pcm *line6pcm,
int frames = urb_out->transfer_buffer_length / bytes_per_frame; int frames = urb_out->transfer_buffer_length / bytes_per_frame;
if (bytes_per_frame == 4) { if (bytes_per_frame == 4) {
/* TODO: add code for TonePort etc. */ int i;
short *pi = (short *)line6pcm->prev_fbuf;
short *po = (short *)urb_out->transfer_buffer;
for (i = 0; i < frames; ++i) {
po[0] = pi[0];
po[1] = 0;
pi += 2;
po += 2;
}
} else if (bytes_per_frame == 6) { } else if (bytes_per_frame == 6) {
int i, j; int i, j;
unsigned char *pi = line6pcm->prev_fbuf; unsigned char *pi = line6pcm->prev_fbuf;
...@@ -84,15 +93,13 @@ static void create_impulse_test_signal(struct snd_line6_pcm *line6pcm, ...@@ -84,15 +93,13 @@ static void create_impulse_test_signal(struct snd_line6_pcm *line6pcm,
pi += bytes_per_frame; pi += bytes_per_frame;
po += bytes_per_frame; po += bytes_per_frame;
} }
}
if (--line6pcm->impulse_count <= 0) { if (--line6pcm->impulse_count <= 0) {
((unsigned char *)(urb_out-> ((unsigned char *)(urb_out->transfer_buffer))[bytes_per_frame -
transfer_buffer))[bytes_per_frame -
1] = 1] =
line6pcm->impulse_volume; line6pcm->impulse_volume;
line6pcm->impulse_count = line6pcm->impulse_period; line6pcm->impulse_count = line6pcm->impulse_period;
} }
}
} }
#endif #endif
...@@ -130,6 +137,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) ...@@ -130,6 +137,7 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
int index; int index;
unsigned long flags; unsigned long flags;
int i, urb_size, urb_frames; int i, urb_size, urb_frames;
int ret;
const int bytes_per_frame = line6pcm->properties->bytes_per_frame; const int bytes_per_frame = line6pcm->properties->bytes_per_frame;
const int frame_increment = const int frame_increment =
line6pcm->properties->snd_line6_rates.rats[0].num_min; line6pcm->properties->snd_line6_rates.rats[0].num_min;
...@@ -244,16 +252,20 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) ...@@ -244,16 +252,20 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
create_impulse_test_signal(line6pcm, urb_out, create_impulse_test_signal(line6pcm, urb_out,
bytes_per_frame); bytes_per_frame);
if (line6pcm->flags & MASK_PCM_ALSA_CAPTURE) { if (line6pcm->flags & MASK_PCM_ALSA_CAPTURE) {
line6_capture_copy(line6pcm, urb_out->transfer_buffer, line6_capture_copy(line6pcm,
urb_out->transfer_buffer,
urb_out->
transfer_buffer_length);
line6_capture_check_period(line6pcm,
urb_out->transfer_buffer_length); urb_out->transfer_buffer_length);
} }
} else { } else {
#endif #endif
if (! if (!
(line6pcm->line6->properties-> (line6pcm->line6->
capabilities & LINE6_BIT_HWMON) properties->capabilities & LINE6_BIT_HWMON)
&& (line6pcm->flags & MASK_PLAYBACK) && (line6pcm->flags & MASK_PLAYBACK)
&& (line6pcm->flags & MASK_CAPTURE)) && (line6pcm->flags & MASK_CAPTURE))
add_monitor_signal(urb_out, line6pcm->prev_fbuf, add_monitor_signal(urb_out, line6pcm->prev_fbuf,
line6pcm->volume_monitor, line6pcm->volume_monitor,
bytes_per_frame); bytes_per_frame);
...@@ -271,11 +283,13 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm) ...@@ -271,11 +283,13 @@ static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
} }
#endif #endif
if (usb_submit_urb(urb_out, GFP_ATOMIC) == 0) ret = usb_submit_urb(urb_out, GFP_ATOMIC);
if (ret == 0)
set_bit(index, &line6pcm->active_urb_out); set_bit(index, &line6pcm->active_urb_out);
else else
dev_err(line6pcm->line6->ifcdev, dev_err(line6pcm->line6->ifcdev,
"URB out #%d submission failed\n", index); "URB out #%d submission failed (%d)\n", index, ret);
spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags); spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);
return 0; return 0;
...@@ -355,8 +369,7 @@ static void audio_out_callback(struct urb *urb) ...@@ -355,8 +369,7 @@ static void audio_out_callback(struct urb *urb)
int i, index, length = 0, shutdown = 0; int i, index, length = 0, shutdown = 0;
unsigned long flags; unsigned long flags;
struct snd_line6_pcm *line6pcm = struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context;
(struct snd_line6_pcm *)urb->context;
struct snd_pcm_substream *substream = struct snd_pcm_substream *substream =
get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK); get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK);
...@@ -391,7 +404,7 @@ static void audio_out_callback(struct urb *urb) ...@@ -391,7 +404,7 @@ static void audio_out_callback(struct urb *urb)
clear_bit(index, &line6pcm->active_urb_out); clear_bit(index, &line6pcm->active_urb_out);
for (i = LINE6_ISO_PACKETS; i--;) for (i = LINE6_ISO_PACKETS; i--;)
if (urb->iso_frame_desc[i].status == -ESHUTDOWN) { if (urb->iso_frame_desc[i].status == -EXDEV) {
shutdown = 1; shutdown = 1;
break; break;
} }
...@@ -422,8 +435,8 @@ static int snd_line6_playback_open(struct snd_pcm_substream *substream) ...@@ -422,8 +435,8 @@ static int snd_line6_playback_open(struct snd_pcm_substream *substream)
struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
err = snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, err = snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
(&line6pcm->properties-> (&line6pcm->
snd_line6_rates)); properties->snd_line6_rates));
if (err < 0) if (err < 0)
return err; return err;
...@@ -554,8 +567,8 @@ int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm) ...@@ -554,8 +567,8 @@ int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm)
urb->dev = line6pcm->line6->usbdev; urb->dev = line6pcm->line6->usbdev;
urb->pipe = urb->pipe =
usb_sndisocpipe(line6pcm->line6->usbdev, usb_sndisocpipe(line6pcm->line6->usbdev,
line6pcm-> line6pcm->ep_audio_write &
ep_audio_write & USB_ENDPOINT_NUMBER_MASK); USB_ENDPOINT_NUMBER_MASK);
urb->transfer_flags = URB_ISO_ASAP; urb->transfer_flags = URB_ISO_ASAP;
urb->start_frame = -1; urb->start_frame = -1;
urb->number_of_packets = LINE6_ISO_PACKETS; urb->number_of_packets = LINE6_ISO_PACKETS;
......
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -12,12 +12,10 @@ ...@@ -12,12 +12,10 @@
#ifndef PLAYBACK_H #ifndef PLAYBACK_H
#define PLAYBACK_H #define PLAYBACK_H
#include <sound/pcm.h> #include <sound/pcm.h>
#include "driver.h" #include "driver.h"
/* /*
When the TonePort is used with jack in full duplex mode and the outputs are When the TonePort is used with jack in full duplex mode and the outputs are
not connected, the software monitor produces an ugly noise since everything not connected, the software monitor produces an ugly noise since everything
...@@ -28,7 +26,6 @@ ...@@ -28,7 +26,6 @@
*/ */
#define USE_CLEAR_BUFFER_WORKAROUND 1 #define USE_CLEAR_BUFFER_WORKAROUND 1
extern struct snd_pcm_ops snd_line6_playback_ops; extern struct snd_pcm_ops snd_line6_playback_ops;
extern int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm); extern int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm);
......
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -20,10 +20,10 @@ ...@@ -20,10 +20,10 @@
#include "playback.h" #include "playback.h"
#include "pod.h" #include "pod.h"
#define POD_SYSEX_CODE 3 #define POD_SYSEX_CODE 3
#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */ #define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */
/* *INDENT-OFF* */
enum { enum {
POD_SYSEX_CLIP = 0x0f, POD_SYSEX_CLIP = 0x0f,
...@@ -49,6 +49,8 @@ enum { ...@@ -49,6 +49,8 @@ enum {
POD_system_invalid = 0x10000 POD_system_invalid = 0x10000
}; };
/* *INDENT-ON* */
enum { enum {
POD_DUMP_MEMORY = 2 POD_DUMP_MEMORY = 2
}; };
...@@ -61,7 +63,6 @@ enum { ...@@ -61,7 +63,6 @@ enum {
POD_BUSY_MIDISEND POD_BUSY_MIDISEND
}; };
static struct snd_ratden pod_ratden = { static struct snd_ratden pod_ratden = {
.num_min = 78125, .num_min = 78125,
.num_max = 78125, .num_max = 78125,
...@@ -90,8 +91,7 @@ static struct line6_pcm_properties pod_pcm_properties = { ...@@ -90,8 +91,7 @@ static struct line6_pcm_properties pod_pcm_properties = {
.period_bytes_min = 64, .period_bytes_min = 64,
.period_bytes_max = 8192, .period_bytes_max = 8192,
.periods_min = 1, .periods_min = 1,
.periods_max = 1024 .periods_max = 1024},
},
.snd_line6_capture_hw = { .snd_line6_capture_hw = {
.info = (SNDRV_PCM_INFO_MMAP | .info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_INTERLEAVED |
...@@ -111,12 +111,10 @@ static struct line6_pcm_properties pod_pcm_properties = { ...@@ -111,12 +111,10 @@ static struct line6_pcm_properties pod_pcm_properties = {
.period_bytes_min = 64, .period_bytes_min = 64,
.period_bytes_max = 8192, .period_bytes_max = 8192,
.periods_min = 1, .periods_min = 1,
.periods_max = 1024 .periods_max = 1024},
},
.snd_line6_rates = { .snd_line6_rates = {
.nrats = 1, .nrats = 1,
.rats = &pod_ratden .rats = &pod_ratden},
},
.bytes_per_frame = POD_BYTES_PER_FRAME .bytes_per_frame = POD_BYTES_PER_FRAME
}; };
...@@ -128,13 +126,11 @@ static const char pod_version_header[] = { ...@@ -128,13 +126,11 @@ static const char pod_version_header[] = {
0xf2, 0x7e, 0x7f, 0x06, 0x02 0xf2, 0x7e, 0x7f, 0x06, 0x02
}; };
/* forward declarations: */ /* forward declarations: */
static void pod_startup2(unsigned long data); static void pod_startup2(unsigned long data);
static void pod_startup3(struct usb_line6_pod *pod); static void pod_startup3(struct usb_line6_pod *pod);
static void pod_startup4(struct usb_line6_pod *pod); static void pod_startup4(struct usb_line6_pod *pod);
/* /*
Mark all parameters as dirty and notify waiting processes. Mark all parameters as dirty and notify waiting processes.
*/ */
...@@ -146,9 +142,11 @@ static void pod_mark_batch_all_dirty(struct usb_line6_pod *pod) ...@@ -146,9 +142,11 @@ static void pod_mark_batch_all_dirty(struct usb_line6_pod *pod)
set_bit(i, pod->param_dirty); set_bit(i, pod->param_dirty);
} }
static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code, int size) static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code,
int size)
{ {
return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code, size); return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code,
size);
} }
/* /*
...@@ -183,7 +181,8 @@ static void pod_store_parameter(struct usb_line6_pod *pod, int param, int value) ...@@ -183,7 +181,8 @@ static void pod_store_parameter(struct usb_line6_pod *pod, int param, int value)
/* /*
Handle SAVE button. Handle SAVE button.
*/ */
static void pod_save_button_pressed(struct usb_line6_pod *pod, int type, int index) static void pod_save_button_pressed(struct usb_line6_pod *pod, int type,
int index)
{ {
pod->dirty = 0; pod->dirty = 0;
set_bit(POD_SAVE_PRESSED, &pod->atomic_flags); set_bit(POD_SAVE_PRESSED, &pod->atomic_flags);
...@@ -217,7 +216,8 @@ void line6_pod_process_message(struct usb_line6_pod *pod) ...@@ -217,7 +216,8 @@ void line6_pod_process_message(struct usb_line6_pod *pod)
if ((buf[1] == POD_amp_model_setup) || if ((buf[1] == POD_amp_model_setup) ||
(buf[1] == POD_effect_setup)) (buf[1] == POD_effect_setup))
/* these also affect other settings */ /* these also affect other settings */
line6_dump_request_async(&pod->dumpreq, &pod->line6, 0, LINE6_DUMP_CURRENT); line6_dump_request_async(&pod->dumpreq, &pod->line6, 0,
LINE6_DUMP_CURRENT);
break; break;
...@@ -226,7 +226,8 @@ void line6_pod_process_message(struct usb_line6_pod *pod) ...@@ -226,7 +226,8 @@ void line6_pod_process_message(struct usb_line6_pod *pod)
pod->channel_num = buf[1]; pod->channel_num = buf[1];
pod->dirty = 0; pod->dirty = 0;
set_bit(POD_CHANNEL_DIRTY, &pod->atomic_flags); set_bit(POD_CHANNEL_DIRTY, &pod->atomic_flags);
line6_dump_request_async(&pod->dumpreq, &pod->line6, 0, LINE6_DUMP_CURRENT); line6_dump_request_async(&pod->dumpreq, &pod->line6, 0,
LINE6_DUMP_CURRENT);
break; break;
case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE: case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE:
...@@ -234,31 +235,50 @@ void line6_pod_process_message(struct usb_line6_pod *pod) ...@@ -234,31 +235,50 @@ void line6_pod_process_message(struct usb_line6_pod *pod)
if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) == 0) { if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) == 0) {
switch (buf[5]) { switch (buf[5]) {
case POD_SYSEX_DUMP: case POD_SYSEX_DUMP:
if (pod->line6.message_length == sizeof(pod->prog_data) + 7) { if (pod->line6.message_length ==
sizeof(pod->prog_data) + 7) {
switch (pod->dumpreq.in_progress) { switch (pod->dumpreq.in_progress) {
case LINE6_DUMP_CURRENT: case LINE6_DUMP_CURRENT:
memcpy(&pod->prog_data, buf + 7, sizeof(pod->prog_data)); memcpy(&pod->prog_data, buf + 7,
sizeof(pod->prog_data));
pod_mark_batch_all_dirty(pod); pod_mark_batch_all_dirty(pod);
break; break;
case POD_DUMP_MEMORY: case POD_DUMP_MEMORY:
memcpy(&pod->prog_data_buf, buf + 7, sizeof(pod->prog_data_buf)); memcpy(&pod->prog_data_buf,
buf + 7,
sizeof
(pod->prog_data_buf));
break; break;
default: default:
DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown dump code %02X\n", pod->dumpreq.in_progress)); DEBUG_MESSAGES(dev_err
(pod->
line6.ifcdev,
"unknown dump code %02X\n",
pod->
dumpreq.in_progress));
} }
line6_dump_finished(&pod->dumpreq); line6_dump_finished(&pod->dumpreq);
pod_startup3(pod); pod_startup3(pod);
} else } else
DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "wrong size of channel dump message (%d instead of %d)\n", DEBUG_MESSAGES(dev_err
pod->line6.message_length, (int)sizeof(pod->prog_data) + 7)); (pod->line6.ifcdev,
"wrong size of channel dump message (%d instead of %d)\n",
pod->
line6.message_length,
(int)
sizeof(pod->prog_data) +
7));
break; break;
case POD_SYSEX_SYSTEM: { case POD_SYSEX_SYSTEM:{
short value = ((int)buf[7] << 12) | ((int)buf[8] << 8) | ((int)buf[9] << 4) | (int)buf[10]; short value =
((int)buf[7] << 12) | ((int)buf[8]
<< 8) |
((int)buf[9] << 4) | (int)buf[10];
#define PROCESS_SYSTEM_PARAM(x) \ #define PROCESS_SYSTEM_PARAM(x) \
case POD_ ## x: \ case POD_ ## x: \
...@@ -267,17 +287,26 @@ void line6_pod_process_message(struct usb_line6_pod *pod) ...@@ -267,17 +287,26 @@ void line6_pod_process_message(struct usb_line6_pod *pod)
break; break;
switch (buf[6]) { switch (buf[6]) {
PROCESS_SYSTEM_PARAM(monitor_level); PROCESS_SYSTEM_PARAM
(monitor_level);
PROCESS_SYSTEM_PARAM(routing); PROCESS_SYSTEM_PARAM(routing);
PROCESS_SYSTEM_PARAM(tuner_mute); PROCESS_SYSTEM_PARAM
PROCESS_SYSTEM_PARAM(tuner_freq); (tuner_mute);
PROCESS_SYSTEM_PARAM(tuner_note); PROCESS_SYSTEM_PARAM
PROCESS_SYSTEM_PARAM(tuner_pitch); (tuner_freq);
PROCESS_SYSTEM_PARAM
(tuner_note);
PROCESS_SYSTEM_PARAM
(tuner_pitch);
#undef PROCESS_SYSTEM_PARAM #undef PROCESS_SYSTEM_PARAM
default: default:
DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown tuner/system response %02X\n", buf[6])); DEBUG_MESSAGES(dev_err
(pod->
line6.ifcdev,
"unknown tuner/system response %02X\n",
buf[6]));
} }
break; break;
...@@ -292,24 +321,40 @@ void line6_pod_process_message(struct usb_line6_pod *pod) ...@@ -292,24 +321,40 @@ void line6_pod_process_message(struct usb_line6_pod *pod)
break; break;
case POD_SYSEX_CLIP: case POD_SYSEX_CLIP:
DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "audio clipped\n")); DEBUG_MESSAGES(dev_err
(pod->line6.ifcdev,
"audio clipped\n"));
pod->clipping.value = 1; pod->clipping.value = 1;
wake_up(&pod->clipping.wait); wake_up(&pod->clipping.wait);
break; break;
case POD_SYSEX_STORE: case POD_SYSEX_STORE:
DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "message %02X not yet implemented\n", buf[5])); DEBUG_MESSAGES(dev_err
(pod->line6.ifcdev,
"message %02X not yet implemented\n",
buf[5]));
break; break;
default: default:
DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown sysex message %02X\n", buf[5])); DEBUG_MESSAGES(dev_err
(pod->line6.ifcdev,
"unknown sysex message %02X\n",
buf[5]));
} }
} else if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) { } else
pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15]; if (memcmp
pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) | (int)buf[10]; (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_startup4(pod); pod_startup4(pod);
} else } else
DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown sysex header\n")); DEBUG_MESSAGES(dev_err
(pod->line6.ifcdev,
"unknown sysex header\n"));
break; break;
...@@ -317,7 +362,9 @@ void line6_pod_process_message(struct usb_line6_pod *pod) ...@@ -317,7 +362,9 @@ void line6_pod_process_message(struct usb_line6_pod *pod)
break; break;
default: default:
DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "POD: unknown message %02X\n", buf[0])); DEBUG_MESSAGES(dev_err
(pod->line6.ifcdev,
"POD: unknown message %02X\n", buf[0]));
} }
} }
...@@ -332,7 +379,8 @@ void line6_pod_process_message(struct usb_line6_pod *pod) ...@@ -332,7 +379,8 @@ void line6_pod_process_message(struct usb_line6_pod *pod)
*) This method fails if a param change message is "chopped" after the first *) This method fails if a param change message is "chopped" after the first
byte. byte.
*/ */
void line6_pod_midi_postprocess(struct usb_line6_pod *pod, unsigned char *data, int length) void line6_pod_midi_postprocess(struct usb_line6_pod *pod, unsigned char *data,
int length)
{ {
int i; int i;
...@@ -343,8 +391,11 @@ void line6_pod_midi_postprocess(struct usb_line6_pod *pod, unsigned char *data, ...@@ -343,8 +391,11 @@ void line6_pod_midi_postprocess(struct usb_line6_pod *pod, unsigned char *data,
if (data[i] == (LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST)) { if (data[i] == (LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST)) {
line6_invalidate_current(&pod->dumpreq); line6_invalidate_current(&pod->dumpreq);
break; break;
} else if ((data[i] == (LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST)) && (i < length - 1)) } else
if ((data[i + 1] == POD_amp_model_setup) || (data[i + 1] == POD_effect_setup)) { if ((data[i] == (LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST))
&& (i < length - 1))
if ((data[i + 1] == POD_amp_model_setup)
|| (data[i + 1] == POD_effect_setup)) {
line6_invalidate_current(&pod->dumpreq); line6_invalidate_current(&pod->dumpreq);
break; break;
} }
...@@ -367,7 +418,8 @@ static void pod_send_channel(struct usb_line6_pod *pod, int value) ...@@ -367,7 +418,8 @@ static void pod_send_channel(struct usb_line6_pod *pod, int value)
/* /*
Transmit PODxt Pro control parameter. Transmit PODxt Pro control parameter.
*/ */
void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param, int value) void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,
int value)
{ {
if (line6_transmit_parameter(&pod->line6, param, value) == 0) if (line6_transmit_parameter(&pod->line6, param, value) == 0)
pod_store_parameter(pod, param, value); pod_store_parameter(pod, param, value);
...@@ -379,7 +431,8 @@ void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param, int valu ...@@ -379,7 +431,8 @@ void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param, int valu
/* /*
Resolve value to memory location. Resolve value to memory location.
*/ */
static int pod_resolve(const char *buf, short block0, short block1, unsigned char *location) static int pod_resolve(const char *buf, short block0, short block1,
unsigned char *location)
{ {
unsigned long value; unsigned long value;
short block; short block;
...@@ -399,7 +452,8 @@ static int pod_resolve(const char *buf, short block0, short block1, unsigned cha ...@@ -399,7 +452,8 @@ static int pod_resolve(const char *buf, short block0, short block1, unsigned cha
/* /*
Send command to store channel/effects setup/amp setup to PODxt Pro. Send command to store channel/effects setup/amp setup to PODxt Pro.
*/ */
static ssize_t pod_send_store_command(struct device *dev, const char *buf, size_t count, short block0, short block1) static ssize_t pod_send_store_command(struct device *dev, const char *buf,
size_t count, short block0, short block1)
{ {
struct usb_interface *interface = to_usb_interface(dev); struct usb_interface *interface = to_usb_interface(dev);
struct usb_line6_pod *pod = usb_get_intfdata(interface); struct usb_line6_pod *pod = usb_get_intfdata(interface);
...@@ -417,7 +471,8 @@ static ssize_t pod_send_store_command(struct device *dev, const char *buf, size_ ...@@ -417,7 +471,8 @@ static ssize_t pod_send_store_command(struct device *dev, const char *buf, size_
return ret; return ret;
} }
memcpy(sysex + SYSEX_DATA_OFS + 3, &pod->prog_data_buf, sizeof(pod->prog_data_buf)); memcpy(sysex + SYSEX_DATA_OFS + 3, &pod->prog_data_buf,
sizeof(pod->prog_data_buf));
line6_send_sysex_message(&pod->line6, sysex, size); line6_send_sysex_message(&pod->line6, sysex, size);
kfree(sysex); kfree(sysex);
...@@ -428,7 +483,9 @@ static ssize_t pod_send_store_command(struct device *dev, const char *buf, size_ ...@@ -428,7 +483,9 @@ static ssize_t pod_send_store_command(struct device *dev, const char *buf, size_
/* /*
Send command to retrieve channel/effects setup/amp setup to PODxt Pro. Send command to retrieve channel/effects setup/amp setup to PODxt Pro.
*/ */
static ssize_t pod_send_retrieve_command(struct device *dev, const char *buf, size_t count, short block0, short block1) static ssize_t pod_send_retrieve_command(struct device *dev, const char *buf,
size_t count, short block0,
short block1)
{ {
struct usb_interface *interface = to_usb_interface(dev); struct usb_interface *interface = to_usb_interface(dev);
struct usb_line6_pod *pod = usb_get_intfdata(interface); struct usb_line6_pod *pod = usb_get_intfdata(interface);
...@@ -459,7 +516,8 @@ static ssize_t pod_send_retrieve_command(struct device *dev, const char *buf, si ...@@ -459,7 +516,8 @@ static ssize_t pod_send_retrieve_command(struct device *dev, const char *buf, si
/* /*
Generic get name function. Generic get name function.
*/ */
static ssize_t get_name_generic(struct usb_line6_pod *pod, const char *str, char *buf) static ssize_t get_name_generic(struct usb_line6_pod *pod, const char *str,
char *buf)
{ {
int length = 0; int length = 0;
const char *p1; const char *p1;
...@@ -521,7 +579,8 @@ static ssize_t pod_get_name(struct device *dev, struct device_attribute *attr, ...@@ -521,7 +579,8 @@ static ssize_t pod_get_name(struct device *dev, struct device_attribute *attr,
{ {
struct usb_interface *interface = to_usb_interface(dev); struct usb_interface *interface = to_usb_interface(dev);
struct usb_line6_pod *pod = usb_get_intfdata(interface); struct usb_line6_pod *pod = usb_get_intfdata(interface);
return get_name_generic(pod, pod->prog_data.header + POD_NAME_OFFSET, buf); return get_name_generic(pod, pod->prog_data.header + POD_NAME_OFFSET,
buf);
} }
/* /*
...@@ -532,7 +591,9 @@ static ssize_t pod_get_name_buf(struct device *dev, ...@@ -532,7 +591,9 @@ static ssize_t pod_get_name_buf(struct device *dev,
{ {
struct usb_interface *interface = to_usb_interface(dev); struct usb_interface *interface = to_usb_interface(dev);
struct usb_line6_pod *pod = usb_get_intfdata(interface); struct usb_line6_pod *pod = usb_get_intfdata(interface);
return get_name_generic(pod, pod->prog_data_buf.header + POD_NAME_OFFSET, buf); return get_name_generic(pod,
pod->prog_data_buf.header + POD_NAME_OFFSET,
buf);
} }
/* /*
...@@ -578,22 +639,22 @@ static bool pod_is_tuner(int code) ...@@ -578,22 +639,22 @@ static bool pod_is_tuner(int code)
return return
(code == POD_tuner_mute) || (code == POD_tuner_mute) ||
(code == POD_tuner_freq) || (code == POD_tuner_freq) ||
(code == POD_tuner_note) || (code == POD_tuner_note) || (code == POD_tuner_pitch);
(code == POD_tuner_pitch);
} }
/* /*
Get system parameter (as integer). Get system parameter (as integer).
@param tuner non-zero, if code refers to a tuner parameter @param tuner non-zero, if code refers to a tuner parameter
*/ */
static int pod_get_system_param_int(struct usb_line6_pod *pod, int *value, int code, static int pod_get_system_param_int(struct usb_line6_pod *pod, int *value,
struct ValueWait *param, int sign) int code, struct ValueWait *param, int sign)
{ {
char *sysex; char *sysex;
static const int size = 1; static const int size = 1;
int retval = 0; int retval = 0;
if (((pod->prog_data.control[POD_tuner] & 0x40) == 0) && pod_is_tuner(code)) if (((pod->prog_data.control[POD_tuner] & 0x40) == 0)
&& pod_is_tuner(code))
return -ENODEV; return -ENODEV;
/* send value request to device: */ /* send value request to device: */
...@@ -608,14 +669,17 @@ static int pod_get_system_param_int(struct usb_line6_pod *pod, int *value, int c ...@@ -608,14 +669,17 @@ static int pod_get_system_param_int(struct usb_line6_pod *pod, int *value, int c
kfree(sysex); kfree(sysex);
/* wait for device to respond: */ /* wait for device to respond: */
retval = wait_event_interruptible(param->wait, param->value != POD_system_invalid); retval =
wait_event_interruptible(param->wait,
param->value != POD_system_invalid);
if (retval < 0) if (retval < 0)
return retval; return retval;
*value = sign ? (int)(signed short)param->value : (int)(unsigned short)param->value; *value = sign ? (int)(signed short)param->value : (int)(unsigned short)
param->value;
if(*value == POD_system_invalid) if (*value == POD_system_invalid)
*value = 0; /* don't report uninitialized values */ *value = 0; /* don't report uninitialized values */
return 0; return 0;
...@@ -625,13 +689,14 @@ static int pod_get_system_param_int(struct usb_line6_pod *pod, int *value, int c ...@@ -625,13 +689,14 @@ static int pod_get_system_param_int(struct usb_line6_pod *pod, int *value, int c
Get system parameter (as string). Get system parameter (as string).
@param tuner non-zero, if code refers to a tuner parameter @param tuner non-zero, if code refers to a tuner parameter
*/ */
static ssize_t pod_get_system_param_string(struct usb_line6_pod *pod, char *buf, int code, static ssize_t pod_get_system_param_string(struct usb_line6_pod *pod, char *buf,
struct ValueWait *param, int sign) int code, struct ValueWait *param,
int sign)
{ {
int retval, value = 0; int retval, value = 0;
retval = pod_get_system_param_int(pod, &value, code, param, sign); retval = pod_get_system_param_int(pod, &value, code, param, sign);
if(retval < 0) if (retval < 0)
return retval; return retval;
return sprintf(buf, "%d\n", value); return sprintf(buf, "%d\n", value);
...@@ -641,12 +706,14 @@ static ssize_t pod_get_system_param_string(struct usb_line6_pod *pod, char *buf, ...@@ -641,12 +706,14 @@ static ssize_t pod_get_system_param_string(struct usb_line6_pod *pod, char *buf,
Send system parameter (from integer). Send system parameter (from integer).
@param tuner non-zero, if code refers to a tuner parameter @param tuner non-zero, if code refers to a tuner parameter
*/ */
static int pod_set_system_param_int(struct usb_line6_pod *pod, int value, int code) static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
int code)
{ {
char *sysex; char *sysex;
static const int size = 5; static const int size = 5;
if (((pod->prog_data.control[POD_tuner] & 0x40) == 0) && pod_is_tuner(code)) if (((pod->prog_data.control[POD_tuner] & 0x40) == 0)
&& pod_is_tuner(code))
return -EINVAL; return -EINVAL;
/* send value to tuner: */ /* send value to tuner: */
...@@ -657,7 +724,7 @@ static int pod_set_system_param_int(struct usb_line6_pod *pod, int value, int co ...@@ -657,7 +724,7 @@ static int pod_set_system_param_int(struct usb_line6_pod *pod, int value, int co
sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f; sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;
sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f; sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;
sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f; sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f;
sysex[SYSEX_DATA_OFS + 4] = (value ) & 0x0f; sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f;
line6_send_sysex_message(&pod->line6, sysex, size); line6_send_sysex_message(&pod->line6, sysex, size);
kfree(sysex); kfree(sysex);
return 0; return 0;
...@@ -667,8 +734,9 @@ static int pod_set_system_param_int(struct usb_line6_pod *pod, int value, int co ...@@ -667,8 +734,9 @@ static int pod_set_system_param_int(struct usb_line6_pod *pod, int value, int co
Send system parameter (from string). Send system parameter (from string).
@param tuner non-zero, if code refers to a tuner parameter @param tuner non-zero, if code refers to a tuner parameter
*/ */
static ssize_t pod_set_system_param_string(struct usb_line6_pod *pod, const char *buf, static ssize_t pod_set_system_param_string(struct usb_line6_pod *pod,
int count, int code, unsigned short mask) const char *buf, int count, int code,
unsigned short mask)
{ {
int retval; int retval;
unsigned short value = simple_strtoul(buf, NULL, 10) & mask; unsigned short value = simple_strtoul(buf, NULL, 10) & mask;
...@@ -878,7 +946,8 @@ static ssize_t pod_wait_for_clip(struct device *dev, ...@@ -878,7 +946,8 @@ static ssize_t pod_wait_for_clip(struct device *dev,
{ {
struct usb_interface *interface = to_usb_interface(dev); struct usb_interface *interface = to_usb_interface(dev);
struct usb_line6_pod *pod = usb_get_intfdata(interface); struct usb_line6_pod *pod = usb_get_intfdata(interface);
return wait_event_interruptible(pod->clipping.wait, pod->clipping.value != 0); return wait_event_interruptible(pod->clipping.wait,
pod->clipping.value != 0);
} }
/* /*
...@@ -890,25 +959,34 @@ static ssize_t pod_wait_for_clip(struct device *dev, ...@@ -890,25 +959,34 @@ static ssize_t pod_wait_for_clip(struct device *dev,
static void pod_startup1(struct usb_line6_pod *pod) static void pod_startup1(struct usb_line6_pod *pod)
{ {
CHECK_STARTUP_PROGRESS(pod->startup_progress, 1); CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT);
/* delay startup procedure: */ /* delay startup procedure: */
line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2, (unsigned long)pod); line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
(unsigned long)pod);
} }
static void pod_startup2(unsigned long data) static void pod_startup2(unsigned long data)
{ {
struct usb_line6_pod *pod = (struct usb_line6_pod *)data; struct usb_line6_pod *pod = (struct usb_line6_pod *)data;
CHECK_STARTUP_PROGRESS(pod->startup_progress, 2);
/* schedule another startup procedure until startup is complete: */
if (pod->startup_progress >= POD_STARTUP_LAST)
return;
pod->startup_progress = POD_STARTUP_DUMPREQ;
line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2,
(unsigned long)pod);
/* current channel dump: */ /* current channel dump: */
line6_dump_request_async(&pod->dumpreq, &pod->line6, 0, LINE6_DUMP_CURRENT); line6_dump_request_async(&pod->dumpreq, &pod->line6, 0,
LINE6_DUMP_CURRENT);
} }
static void pod_startup3(struct usb_line6_pod *pod) static void pod_startup3(struct usb_line6_pod *pod)
{ {
struct usb_line6 *line6 = &pod->line6; struct usb_line6 *line6 = &pod->line6;
CHECK_STARTUP_PROGRESS(pod->startup_progress, 3); CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ);
/* request firmware version: */ /* request firmware version: */
line6_version_request_async(line6); line6_version_request_async(line6);
...@@ -916,7 +994,7 @@ static void pod_startup3(struct usb_line6_pod *pod) ...@@ -916,7 +994,7 @@ static void pod_startup3(struct usb_line6_pod *pod)
static void pod_startup4(struct usb_line6_pod *pod) static void pod_startup4(struct usb_line6_pod *pod)
{ {
CHECK_STARTUP_PROGRESS(pod->startup_progress, 4); CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE);
/* schedule work for global work queue: */ /* schedule work for global work queue: */
schedule_work(&pod->startup_work); schedule_work(&pod->startup_work);
...@@ -924,10 +1002,11 @@ static void pod_startup4(struct usb_line6_pod *pod) ...@@ -924,10 +1002,11 @@ static void pod_startup4(struct usb_line6_pod *pod)
static void pod_startup5(struct work_struct *work) static void pod_startup5(struct work_struct *work)
{ {
struct usb_line6_pod *pod = container_of(work, struct usb_line6_pod, startup_work); struct usb_line6_pod *pod =
container_of(work, struct usb_line6_pod, startup_work);
struct usb_line6 *line6 = &pod->line6; struct usb_line6 *line6 = &pod->line6;
CHECK_STARTUP_PROGRESS(pod->startup_progress, 5); CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP);
/* serial number: */ /* serial number: */
line6_read_serial_number(&pod->line6, &pod->serial_number); line6_read_serial_number(&pod->line6, &pod->serial_number);
...@@ -936,7 +1015,8 @@ static void pod_startup5(struct work_struct *work) ...@@ -936,7 +1015,8 @@ static void pod_startup5(struct work_struct *work)
line6_register_audio(line6); line6_register_audio(line6);
/* device files: */ /* device files: */
line6_pod_create_files(pod->firmware_version, line6->properties->device_bit, line6->ifcdev); line6_pod_create_files(pod->firmware_version,
line6->properties->device_bit, line6->ifcdev);
} }
#define POD_GET_SYSTEM_PARAM(code, sign) \ #define POD_GET_SYSTEM_PARAM(code, sign) \
...@@ -971,28 +1051,43 @@ POD_GET_SYSTEM_PARAM(tuner_pitch, 1); ...@@ -971,28 +1051,43 @@ POD_GET_SYSTEM_PARAM(tuner_pitch, 1);
#undef GET_SYSTEM_PARAM #undef GET_SYSTEM_PARAM
/* POD special files: */ /* POD special files: */
static DEVICE_ATTR(channel, S_IWUGO | S_IRUGO, pod_get_channel, pod_set_channel); static DEVICE_ATTR(channel, S_IWUGO | S_IRUGO, pod_get_channel,
pod_set_channel);
static DEVICE_ATTR(clip, S_IRUGO, pod_wait_for_clip, line6_nop_write); static DEVICE_ATTR(clip, S_IRUGO, pod_wait_for_clip, line6_nop_write);
static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write); static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write);
static DEVICE_ATTR(dirty, S_IRUGO, pod_get_dirty, line6_nop_write); static DEVICE_ATTR(dirty, S_IRUGO, pod_get_dirty, line6_nop_write);
static DEVICE_ATTR(dump, S_IWUGO | S_IRUGO, pod_get_dump, pod_set_dump); static DEVICE_ATTR(dump, S_IWUGO | S_IRUGO, pod_get_dump, pod_set_dump);
static DEVICE_ATTR(dump_buf, S_IWUGO | S_IRUGO, pod_get_dump_buf, pod_set_dump_buf); static DEVICE_ATTR(dump_buf, S_IWUGO | S_IRUGO, pod_get_dump_buf,
pod_set_dump_buf);
static DEVICE_ATTR(finish, S_IWUGO, line6_nop_read, pod_set_finish); static DEVICE_ATTR(finish, S_IWUGO, line6_nop_read, pod_set_finish);
static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version, line6_nop_write); static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version,
static DEVICE_ATTR(midi_postprocess, S_IWUGO | S_IRUGO, pod_get_midi_postprocess, pod_set_midi_postprocess); line6_nop_write);
static DEVICE_ATTR(monitor_level, S_IWUGO | S_IRUGO, pod_get_monitor_level, pod_set_monitor_level); static DEVICE_ATTR(midi_postprocess, S_IWUGO | S_IRUGO,
pod_get_midi_postprocess, pod_set_midi_postprocess);
static DEVICE_ATTR(monitor_level, S_IWUGO | S_IRUGO, pod_get_monitor_level,
pod_set_monitor_level);
static DEVICE_ATTR(name, S_IRUGO, pod_get_name, line6_nop_write); static DEVICE_ATTR(name, S_IRUGO, pod_get_name, line6_nop_write);
static DEVICE_ATTR(name_buf, S_IRUGO, pod_get_name_buf, line6_nop_write); static DEVICE_ATTR(name_buf, S_IRUGO, pod_get_name_buf, line6_nop_write);
static DEVICE_ATTR(retrieve_amp_setup, S_IWUGO, line6_nop_read, pod_set_retrieve_amp_setup); static DEVICE_ATTR(retrieve_amp_setup, S_IWUGO, line6_nop_read,
static DEVICE_ATTR(retrieve_channel, S_IWUGO, line6_nop_read, pod_set_retrieve_channel); pod_set_retrieve_amp_setup);
static DEVICE_ATTR(retrieve_effects_setup, S_IWUGO, line6_nop_read, pod_set_retrieve_effects_setup); static DEVICE_ATTR(retrieve_channel, S_IWUGO, line6_nop_read,
static DEVICE_ATTR(routing, S_IWUGO | S_IRUGO, pod_get_routing, pod_set_routing); pod_set_retrieve_channel);
static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number, line6_nop_write); static DEVICE_ATTR(retrieve_effects_setup, S_IWUGO, line6_nop_read,
static DEVICE_ATTR(store_amp_setup, S_IWUGO, line6_nop_read, pod_set_store_amp_setup); pod_set_retrieve_effects_setup);
static DEVICE_ATTR(store_channel, S_IWUGO, line6_nop_read, pod_set_store_channel); static DEVICE_ATTR(routing, S_IWUGO | S_IRUGO, pod_get_routing,
static DEVICE_ATTR(store_effects_setup, S_IWUGO, line6_nop_read, pod_set_store_effects_setup); pod_set_routing);
static DEVICE_ATTR(tuner_freq, S_IWUGO | S_IRUGO, pod_get_tuner_freq, pod_set_tuner_freq); static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number,
static DEVICE_ATTR(tuner_mute, S_IWUGO | S_IRUGO, pod_get_tuner_mute, pod_set_tuner_mute); line6_nop_write);
static DEVICE_ATTR(store_amp_setup, S_IWUGO, line6_nop_read,
pod_set_store_amp_setup);
static DEVICE_ATTR(store_channel, S_IWUGO, line6_nop_read,
pod_set_store_channel);
static DEVICE_ATTR(store_effects_setup, S_IWUGO, line6_nop_read,
pod_set_store_effects_setup);
static DEVICE_ATTR(tuner_freq, S_IWUGO | S_IRUGO, pod_get_tuner_freq,
pod_set_tuner_freq);
static DEVICE_ATTR(tuner_mute, S_IWUGO | S_IRUGO, pod_get_tuner_mute,
pod_set_tuner_mute);
static DEVICE_ATTR(tuner_note, S_IRUGO, pod_get_tuner_note, line6_nop_write); static DEVICE_ATTR(tuner_note, S_IRUGO, pod_get_tuner_note, line6_nop_write);
static DEVICE_ATTR(tuner_pitch, S_IRUGO, pod_get_tuner_pitch, line6_nop_write); static DEVICE_ATTR(tuner_pitch, S_IRUGO, pod_get_tuner_pitch, line6_nop_write);
...@@ -1028,11 +1123,12 @@ static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol, ...@@ -1028,11 +1123,12 @@ static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,
struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); 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 = (struct usb_line6_pod *)line6pcm->line6;
if(ucontrol->value.integer.value[0] == pod->monitor_level.value) if (ucontrol->value.integer.value[0] == pod->monitor_level.value)
return 0; return 0;
pod->monitor_level.value = ucontrol->value.integer.value[0]; pod->monitor_level.value = ucontrol->value.integer.value[0];
pod_set_system_param_int(pod, ucontrol->value.integer.value[0], POD_monitor_level); pod_set_system_param_int(pod, ucontrol->value.integer.value[0],
POD_monitor_level);
return 1; return 1;
} }
...@@ -1062,6 +1158,9 @@ static void pod_destruct(struct usb_interface *interface) ...@@ -1062,6 +1158,9 @@ static void pod_destruct(struct usb_interface *interface)
return; return;
line6_cleanup_audio(line6); line6_cleanup_audio(line6);
del_timer(&pod->startup_timer);
cancel_work_sync(&pod->startup_work);
/* free dump request data: */ /* free dump request data: */
line6_dumpreq_destruct(&pod->dumpreq); line6_dumpreq_destruct(&pod->dumpreq);
} }
...@@ -1108,11 +1207,15 @@ static int pod_create_files2(struct device *dev) ...@@ -1108,11 +1207,15 @@ static int pod_create_files2(struct device *dev)
/* /*
Try to init POD device. Try to init POD device.
*/ */
static int pod_try_init(struct usb_interface *interface, struct usb_line6_pod *pod) static int pod_try_init(struct usb_interface *interface,
struct usb_line6_pod *pod)
{ {
int err; int err;
struct usb_line6 *line6 = &pod->line6; struct usb_line6 *line6 = &pod->line6;
init_timer(&pod->startup_timer);
INIT_WORK(&pod->startup_work, pod_startup5);
if ((interface == NULL) || (pod == NULL)) if ((interface == NULL) || (pod == NULL))
return -ENODEV; return -ENODEV;
...@@ -1126,8 +1229,6 @@ static int pod_try_init(struct usb_interface *interface, struct usb_line6_pod *p ...@@ -1126,8 +1229,6 @@ static int pod_try_init(struct usb_interface *interface, struct usb_line6_pod *p
init_waitqueue_head(&pod->tuner_note.wait); init_waitqueue_head(&pod->tuner_note.wait);
init_waitqueue_head(&pod->tuner_pitch.wait); init_waitqueue_head(&pod->tuner_pitch.wait);
init_waitqueue_head(&pod->clipping.wait); init_waitqueue_head(&pod->clipping.wait);
init_timer(&pod->startup_timer);
INIT_WORK(&pod->startup_work, pod_startup5);
memset(pod->param_dirty, 0xff, sizeof(pod->param_dirty)); memset(pod->param_dirty, 0xff, sizeof(pod->param_dirty));
...@@ -1164,7 +1265,9 @@ static int pod_try_init(struct usb_interface *interface, struct usb_line6_pod *p ...@@ -1164,7 +1265,9 @@ static int pod_try_init(struct usb_interface *interface, struct usb_line6_pod *p
} }
/* register monitor control: */ /* register monitor control: */
err = snd_ctl_add(line6->card, snd_ctl_new1(&pod_control_monitor, line6->line6pcm)); err =
snd_ctl_add(line6->card,
snd_ctl_new1(&pod_control_monitor, line6->line6pcm));
if (err < 0) { if (err < 0) {
return err; return err;
} }
...@@ -1220,7 +1323,9 @@ void line6_pod_disconnect(struct usb_interface *interface) ...@@ -1220,7 +1323,9 @@ void line6_pod_disconnect(struct usb_interface *interface)
if (dev != NULL) { if (dev != NULL) {
/* remove sysfs entries: */ /* remove sysfs entries: */
line6_pod_remove_files(pod->firmware_version, pod->line6.properties->device_bit, dev); line6_pod_remove_files(pod->firmware_version,
pod->line6.
properties->device_bit, dev);
device_remove_file(dev, &dev_attr_channel); device_remove_file(dev, &dev_attr_channel);
device_remove_file(dev, &dev_attr_clip); device_remove_file(dev, &dev_attr_clip);
...@@ -1236,7 +1341,8 @@ void line6_pod_disconnect(struct usb_interface *interface) ...@@ -1236,7 +1341,8 @@ void line6_pod_disconnect(struct usb_interface *interface)
device_remove_file(dev, &dev_attr_name_buf); device_remove_file(dev, &dev_attr_name_buf);
device_remove_file(dev, &dev_attr_retrieve_amp_setup); device_remove_file(dev, &dev_attr_retrieve_amp_setup);
device_remove_file(dev, &dev_attr_retrieve_channel); device_remove_file(dev, &dev_attr_retrieve_channel);
device_remove_file(dev, &dev_attr_retrieve_effects_setup); device_remove_file(dev,
&dev_attr_retrieve_effects_setup);
device_remove_file(dev, &dev_attr_routing); device_remove_file(dev, &dev_attr_routing);
device_remove_file(dev, &dev_attr_serial_number); device_remove_file(dev, &dev_attr_serial_number);
device_remove_file(dev, &dev_attr_store_amp_setup); device_remove_file(dev, &dev_attr_store_amp_setup);
......
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#ifndef POD_H #ifndef POD_H
#define POD_H #define POD_H
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/usb.h> #include <linux/usb.h>
...@@ -23,7 +22,6 @@ ...@@ -23,7 +22,6 @@
#include "driver.h" #include "driver.h"
#include "dumprequest.h" #include "dumprequest.h"
/* /*
PODxt Live interfaces PODxt Live interfaces
*/ */
...@@ -41,7 +39,19 @@ ...@@ -41,7 +39,19 @@
*/ */
#define POD_CONTROL_SIZE 0x80 #define POD_CONTROL_SIZE 0x80
#define POD_BUFSIZE_DUMPREQ 7 #define POD_BUFSIZE_DUMPREQ 7
#define POD_STARTUP_DELAY 3000 #define POD_STARTUP_DELAY 1000
/*
Stages of POD startup procedure
*/
enum {
POD_STARTUP_INIT = 1,
POD_STARTUP_DUMPREQ,
POD_STARTUP_VERSIONREQ,
POD_STARTUP_WORKQUEUE,
POD_STARTUP_SETUP,
POD_STARTUP_LAST = POD_STARTUP_SETUP - 1
};
/** /**
Data structure for values that need to be requested explicitly. Data structure for values that need to be requested explicitly.
...@@ -183,14 +193,13 @@ struct usb_line6_pod { ...@@ -183,14 +193,13 @@ struct usb_line6_pod {
char midi_postprocess; char midi_postprocess;
}; };
extern void line6_pod_disconnect(struct usb_interface *interface); extern void line6_pod_disconnect(struct usb_interface *interface);
extern int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod); extern int line6_pod_init(struct usb_interface *interface,
struct usb_line6_pod *pod);
extern void line6_pod_midi_postprocess(struct usb_line6_pod *pod, extern void line6_pod_midi_postprocess(struct usb_line6_pod *pod,
unsigned char *data, int length); unsigned char *data, int length);
extern void line6_pod_process_message(struct usb_line6_pod *pod); extern void line6_pod_process_message(struct usb_line6_pod *pod);
extern void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param, extern void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,
int value); int value);
#endif #endif
#ifndef DRIVER_REVISION #ifndef DRIVER_REVISION
/* current subversion revision */ /* current subversion revision */
#define DRIVER_REVISION " (revision 665)" #define DRIVER_REVISION " (revision 684)"
#endif #endif
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* Emil Myhrman (emil.myhrman@gmail.com) * Emil Myhrman (emil.myhrman@gmail.com)
...@@ -19,13 +19,10 @@ ...@@ -19,13 +19,10 @@
#include "playback.h" #include "playback.h"
#include "toneport.h" #include "toneport.h"
static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2); static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2);
#define TONEPORT_PCM_DELAY 1 #define TONEPORT_PCM_DELAY 1
static struct snd_ratden toneport_ratden = { static struct snd_ratden toneport_ratden = {
.num_min = 44100, .num_min = 44100,
.num_max = 44100, .num_max = 44100,
...@@ -54,8 +51,7 @@ static struct line6_pcm_properties toneport_pcm_properties = { ...@@ -54,8 +51,7 @@ static struct line6_pcm_properties toneport_pcm_properties = {
.period_bytes_min = 64, .period_bytes_min = 64,
.period_bytes_max = 8192, .period_bytes_max = 8192,
.periods_min = 1, .periods_min = 1,
.periods_max = 1024 .periods_max = 1024},
},
.snd_line6_capture_hw = { .snd_line6_capture_hw = {
.info = (SNDRV_PCM_INFO_MMAP | .info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_INTERLEAVED |
...@@ -75,12 +71,10 @@ static struct line6_pcm_properties toneport_pcm_properties = { ...@@ -75,12 +71,10 @@ static struct line6_pcm_properties toneport_pcm_properties = {
.period_bytes_min = 64, .period_bytes_min = 64,
.period_bytes_max = 8192, .period_bytes_max = 8192,
.periods_min = 1, .periods_min = 1,
.periods_max = 1024 .periods_max = 1024},
},
.snd_line6_rates = { .snd_line6_rates = {
.nrats = 1, .nrats = 1,
.rats = &toneport_ratden .rats = &toneport_ratden},
},
.bytes_per_frame = 4 .bytes_per_frame = 4
}; };
...@@ -93,17 +87,16 @@ static struct line6_pcm_properties toneport_pcm_properties = { ...@@ -93,17 +87,16 @@ static struct line6_pcm_properties toneport_pcm_properties = {
static int led_red = 0x00; static int led_red = 0x00;
static int led_green = 0x26; static int led_green = 0x26;
struct ToneportSourceInfo struct ToneportSourceInfo {
{
const char *name; const char *name;
int code; int code;
}; };
static const struct ToneportSourceInfo toneport_source_info[] = { static const struct ToneportSourceInfo toneport_source_info[] = {
{ "Microphone", 0x0a01 }, {"Microphone", 0x0a01},
{ "Line" , 0x0801 }, {"Line", 0x0801},
{ "Instrument", 0x0b01 }, {"Instrument", 0x0b01},
{ "Inst & Mic", 0x0901 } {"Inst & Mic", 0x0901}
}; };
static bool toneport_has_led(short product) static bool toneport_has_led(short product)
...@@ -166,7 +159,6 @@ static DEVICE_ATTR(led_red, S_IWUGO | S_IRUGO, line6_nop_read, ...@@ -166,7 +159,6 @@ static DEVICE_ATTR(led_red, S_IWUGO | S_IRUGO, line6_nop_read,
static DEVICE_ATTR(led_green, S_IWUGO | S_IRUGO, line6_nop_read, static DEVICE_ATTR(led_green, S_IWUGO | S_IRUGO, line6_nop_read,
toneport_set_led_green); toneport_set_led_green);
static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2) static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2)
{ {
int ret; int ret;
...@@ -209,10 +201,16 @@ static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol, ...@@ -209,10 +201,16 @@ static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol,
{ {
struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
if(ucontrol->value.integer.value[0] == line6pcm->volume_monitor) if (ucontrol->value.integer.value[0] == line6pcm->volume_monitor)
return 0; return 0;
line6pcm->volume_monitor = ucontrol->value.integer.value[0]; line6pcm->volume_monitor = ucontrol->value.integer.value[0];
if (line6pcm->volume_monitor > 0)
line6_pcm_start(line6pcm, MASK_PCM_MONITOR);
else
line6_pcm_stop(line6pcm, MASK_PCM_MONITOR);
return 1; return 1;
} }
...@@ -225,7 +223,7 @@ static int snd_toneport_source_info(struct snd_kcontrol *kcontrol, ...@@ -225,7 +223,7 @@ static int snd_toneport_source_info(struct snd_kcontrol *kcontrol,
uinfo->count = 1; uinfo->count = 1;
uinfo->value.enumerated.items = size; uinfo->value.enumerated.items = size;
if(uinfo->value.enumerated.item >= size) if (uinfo->value.enumerated.item >= size)
uinfo->value.enumerated.item = size - 1; uinfo->value.enumerated.item = size - 1;
strcpy(uinfo->value.enumerated.name, strcpy(uinfo->value.enumerated.name,
...@@ -239,7 +237,8 @@ static int snd_toneport_source_get(struct snd_kcontrol *kcontrol, ...@@ -239,7 +237,8 @@ static int snd_toneport_source_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); 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 =
(struct usb_line6_toneport *)line6pcm->line6;
ucontrol->value.enumerated.item[0] = toneport->source; ucontrol->value.enumerated.item[0] = toneport->source;
return 0; return 0;
} }
...@@ -249,13 +248,15 @@ static int snd_toneport_source_put(struct snd_kcontrol *kcontrol, ...@@ -249,13 +248,15 @@ static int snd_toneport_source_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol) struct snd_ctl_elem_value *ucontrol)
{ {
struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); 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 =
(struct usb_line6_toneport *)line6pcm->line6;
if(ucontrol->value.enumerated.item[0] == toneport->source) if (ucontrol->value.enumerated.item[0] == toneport->source)
return 0; return 0;
toneport->source = ucontrol->value.enumerated.item[0]; toneport->source = ucontrol->value.enumerated.item[0];
toneport_send_cmd(toneport->line6.usbdev, toneport_source_info[toneport->source].code, 0x0000); toneport_send_cmd(toneport->line6.usbdev,
toneport_source_info[toneport->source].code, 0x0000);
return 1; return 1;
} }
...@@ -321,10 +322,12 @@ static void toneport_setup(struct usb_line6_toneport *toneport) ...@@ -321,10 +322,12 @@ static void toneport_setup(struct usb_line6_toneport *toneport)
toneport_send_cmd(usbdev, 0x0301, 0x0000); toneport_send_cmd(usbdev, 0x0301, 0x0000);
/* initialize source select: */ /* initialize source select: */
switch(usbdev->descriptor.idProduct) { switch (usbdev->descriptor.idProduct) {
case LINE6_DEVID_TONEPORT_UX1: case LINE6_DEVID_TONEPORT_UX1:
case LINE6_DEVID_PODSTUDIO_UX1: case LINE6_DEVID_PODSTUDIO_UX1:
toneport_send_cmd(usbdev, toneport_source_info[toneport->source].code, 0x0000); toneport_send_cmd(usbdev,
toneport_source_info[toneport->source].code,
0x0000);
} }
if (toneport_has_led(usbdev->descriptor.idProduct)) if (toneport_has_led(usbdev->descriptor.idProduct))
...@@ -357,16 +360,22 @@ static int toneport_try_init(struct usb_interface *interface, ...@@ -357,16 +360,22 @@ static int toneport_try_init(struct usb_interface *interface,
} }
/* register monitor control: */ /* register monitor control: */
err = snd_ctl_add(line6->card, snd_ctl_new1(&toneport_control_monitor, line6->line6pcm)); err =
snd_ctl_add(line6->card,
snd_ctl_new1(&toneport_control_monitor,
line6->line6pcm));
if (err < 0) { if (err < 0) {
return err; return err;
} }
/* register source select control: */ /* register source select control: */
switch(usbdev->descriptor.idProduct) { switch (usbdev->descriptor.idProduct) {
case LINE6_DEVID_TONEPORT_UX1: case LINE6_DEVID_TONEPORT_UX1:
case LINE6_DEVID_PODSTUDIO_UX1: case LINE6_DEVID_PODSTUDIO_UX1:
err = snd_ctl_add(line6->card, snd_ctl_new1(&toneport_control_source, line6->line6pcm)); err =
snd_ctl_add(line6->card,
snd_ctl_new1(&toneport_control_source,
line6->line6pcm));
if (err < 0) { if (err < 0) {
return err; return err;
} }
...@@ -382,8 +391,10 @@ static int toneport_try_init(struct usb_interface *interface, ...@@ -382,8 +391,10 @@ static int toneport_try_init(struct usb_interface *interface,
line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1); line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1);
if (toneport_has_led(usbdev->descriptor.idProduct)) { if (toneport_has_led(usbdev->descriptor.idProduct)) {
CHECK_RETURN(device_create_file(&interface->dev, &dev_attr_led_red)); CHECK_RETURN(device_create_file
CHECK_RETURN(device_create_file(&interface->dev, &dev_attr_led_green)); (&interface->dev, &dev_attr_led_red));
CHECK_RETURN(device_create_file
(&interface->dev, &dev_attr_led_green));
} }
toneport_setup(toneport); toneport_setup(toneport);
......
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -12,13 +12,11 @@ ...@@ -12,13 +12,11 @@
#ifndef TONEPORT_H #ifndef TONEPORT_H
#define TONEPORT_H #define TONEPORT_H
#include <linux/usb.h> #include <linux/usb.h>
#include <sound/core.h> #include <sound/core.h>
#include "driver.h" #include "driver.h"
struct usb_line6_toneport { struct usb_line6_toneport {
/** /**
Generic Line6 USB data. Generic Line6 USB data.
...@@ -46,11 +44,9 @@ struct usb_line6_toneport { ...@@ -46,11 +44,9 @@ struct usb_line6_toneport {
struct timer_list timer; struct timer_list timer;
}; };
extern void line6_toneport_disconnect(struct usb_interface *interface); extern void line6_toneport_disconnect(struct usb_interface *interface);
extern int line6_toneport_init(struct usb_interface *interface, extern int line6_toneport_init(struct usb_interface *interface,
struct usb_line6_toneport *toneport); struct usb_line6_toneport *toneport);
extern void line6_toneport_reset_resume(struct usb_line6_toneport *toneport); extern void line6_toneport_reset_resume(struct usb_line6_toneport *toneport);
#endif #endif
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2005-2008 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2005-2008 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#ifndef USBDEFS_H #ifndef USBDEFS_H
#define USBDEFS_H #define USBDEFS_H
#define LINE6_VENDOR_ID 0x0e41 #define LINE6_VENDOR_ID 0x0e41
#define USB_INTERVALS_PER_SECOND 1000 #define USB_INTERVALS_PER_SECOND 1000
...@@ -80,5 +79,4 @@ ...@@ -80,5 +79,4 @@
#define LINE6_FALLBACK_INTERVAL 10 #define LINE6_FALLBACK_INTERVAL 10
#define LINE6_FALLBACK_MAXPACKETSIZE 16 #define LINE6_FALLBACK_MAXPACKETSIZE 16
#endif #endif
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "driver.h" #include "driver.h"
#include "variax.h" #include "variax.h"
#define VARIAX_SYSEX_CODE 7 #define VARIAX_SYSEX_CODE 7
#define VARIAX_SYSEX_PARAM 0x3b #define VARIAX_SYSEX_PARAM 0x3b
#define VARIAX_SYSEX_ACTIVATE 0x2a #define VARIAX_SYSEX_ACTIVATE 0x2a
...@@ -24,7 +23,6 @@ ...@@ -24,7 +23,6 @@
#define VARIAX_MODEL_MESSAGE_LENGTH 199 #define VARIAX_MODEL_MESSAGE_LENGTH 199
#define VARIAX_OFFSET_ACTIVATE 7 #define VARIAX_OFFSET_ACTIVATE 7
/* /*
This message is sent by the device during initialization and identifies This message is sent by the device during initialization and identifies
the connected guitar model. the connected guitar model.
...@@ -71,14 +69,12 @@ static const char variax_request_model2[] = { ...@@ -71,14 +69,12 @@ static const char variax_request_model2[] = {
0x00, 0x00, 0x00, 0xf7 0x00, 0x00, 0x00, 0xf7
}; };
/* forward declarations: */ /* forward declarations: */
static int variax_create_files2(struct device *dev); static int variax_create_files2(struct device *dev);
static void variax_startup2(unsigned long data); static void variax_startup2(unsigned long data);
static void variax_startup4(unsigned long data); static void variax_startup4(unsigned long data);
static void variax_startup5(unsigned long data); static void variax_startup5(unsigned long data);
/* /*
Decode data transmitted by workbench. Decode data transmitted by workbench.
*/ */
...@@ -110,17 +106,25 @@ static void variax_activate_async(struct usb_line6_variax *variax, int a) ...@@ -110,17 +106,25 @@ static void variax_activate_async(struct usb_line6_variax *variax, int a)
static void variax_startup1(struct usb_line6_variax *variax) static void variax_startup1(struct usb_line6_variax *variax)
{ {
CHECK_STARTUP_PROGRESS(variax->startup_progress, 1); CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_INIT);
/* delay startup procedure: */ /* delay startup procedure: */
line6_start_timer(&variax->startup_timer, VARIAX_STARTUP_DELAY1, variax_startup2, (unsigned long)variax); line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1,
variax_startup2, (unsigned long)variax);
} }
static void variax_startup2(unsigned long data) static void variax_startup2(unsigned long data)
{ {
struct usb_line6_variax *variax = (struct usb_line6_variax *)data; struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
struct usb_line6 *line6 = &variax->line6; struct usb_line6 *line6 = &variax->line6;
CHECK_STARTUP_PROGRESS(variax->startup_progress, 2);
/* 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, (unsigned long)variax);
/* request firmware version: */ /* request firmware version: */
line6_version_request_async(line6); line6_version_request_async(line6);
...@@ -128,35 +132,41 @@ static void variax_startup2(unsigned long data) ...@@ -128,35 +132,41 @@ static void variax_startup2(unsigned long data)
static void variax_startup3(struct usb_line6_variax *variax) static void variax_startup3(struct usb_line6_variax *variax)
{ {
CHECK_STARTUP_PROGRESS(variax->startup_progress, 3); CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_WAIT);
/* delay startup procedure: */ /* delay startup procedure: */
line6_start_timer(&variax->startup_timer, VARIAX_STARTUP_DELAY3, variax_startup4, (unsigned long)variax); line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY3,
variax_startup4, (unsigned long)variax);
} }
static void variax_startup4(unsigned long data) static void variax_startup4(unsigned long data)
{ {
struct usb_line6_variax *variax = (struct usb_line6_variax *)data; struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
CHECK_STARTUP_PROGRESS(variax->startup_progress, 4); CHECK_STARTUP_PROGRESS(variax->startup_progress,
VARIAX_STARTUP_ACTIVATE);
/* activate device: */ /* activate device: */
variax_activate_async(variax, 1); variax_activate_async(variax, 1);
line6_start_timer(&variax->startup_timer, VARIAX_STARTUP_DELAY4, variax_startup5, (unsigned long)variax); line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY4,
variax_startup5, (unsigned long)variax);
} }
static void variax_startup5(unsigned long data) static void variax_startup5(unsigned long data)
{ {
struct usb_line6_variax *variax = (struct usb_line6_variax *)data; struct usb_line6_variax *variax = (struct usb_line6_variax *)data;
CHECK_STARTUP_PROGRESS(variax->startup_progress, 5); CHECK_STARTUP_PROGRESS(variax->startup_progress,
VARIAX_STARTUP_DUMPREQ);
/* current model dump: */ /* current model dump: */
line6_dump_request_async(&variax->dumpreq, &variax->line6, 0, VARIAX_DUMP_PASS1); line6_dump_request_async(&variax->dumpreq, &variax->line6, 0,
VARIAX_DUMP_PASS1);
/* passes 2 and 3 are performed implicitly before entering variax_startup6 */ /* passes 2 and 3 are performed implicitly before entering variax_startup6 */
} }
static void variax_startup6(struct usb_line6_variax *variax) static void variax_startup6(struct usb_line6_variax *variax)
{ {
CHECK_STARTUP_PROGRESS(variax->startup_progress, 6); CHECK_STARTUP_PROGRESS(variax->startup_progress,
VARIAX_STARTUP_WORKQUEUE);
/* schedule work for global work queue: */ /* schedule work for global work queue: */
schedule_work(&variax->startup_work); schedule_work(&variax->startup_work);
...@@ -164,10 +174,11 @@ static void variax_startup6(struct usb_line6_variax *variax) ...@@ -164,10 +174,11 @@ static void variax_startup6(struct usb_line6_variax *variax)
static void variax_startup7(struct work_struct *work) static void variax_startup7(struct work_struct *work)
{ {
struct usb_line6_variax *variax = container_of(work, struct usb_line6_variax, startup_work); struct usb_line6_variax *variax =
container_of(work, struct usb_line6_variax, startup_work);
struct usb_line6 *line6 = &variax->line6; struct usb_line6 *line6 = &variax->line6;
CHECK_STARTUP_PROGRESS(variax->startup_progress, 7); CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP);
/* ALSA audio interface: */ /* ALSA audio interface: */
line6_register_audio(&variax->line6); line6_register_audio(&variax->line6);
...@@ -200,7 +211,8 @@ void line6_variax_process_message(struct usb_line6_variax *variax) ...@@ -200,7 +211,8 @@ void line6_variax_process_message(struct usb_line6_variax *variax)
case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE: case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE:
case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST: case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST:
variax->model = buf[1]; variax->model = buf[1];
line6_dump_request_async(&variax->dumpreq, &variax->line6, 0, VARIAX_DUMP_PASS1); line6_dump_request_async(&variax->dumpreq, &variax->line6, 0,
VARIAX_DUMP_PASS1);
break; break;
case LINE6_RESET: case LINE6_RESET:
...@@ -214,20 +226,44 @@ void line6_variax_process_message(struct usb_line6_variax *variax) ...@@ -214,20 +226,44 @@ void line6_variax_process_message(struct usb_line6_variax *variax)
VARIAX_MODEL_MESSAGE_LENGTH) { VARIAX_MODEL_MESSAGE_LENGTH) {
switch (variax->dumpreq.in_progress) { switch (variax->dumpreq.in_progress) {
case VARIAX_DUMP_PASS1: case VARIAX_DUMP_PASS1:
variax_decode(buf + VARIAX_MODEL_HEADER_LENGTH, (unsigned char *)&variax->model_data, variax_decode(buf +
(sizeof(variax->model_data.name) + sizeof(variax->model_data.control) / 2) * 2); VARIAX_MODEL_HEADER_LENGTH,
line6_dump_request_async(&variax->dumpreq, &variax->line6, 1, VARIAX_DUMP_PASS2); (unsigned char *)
&variax->model_data,
(sizeof
(variax->model_data.
name) +
sizeof(variax->
model_data.
control)
/ 2) * 2);
line6_dump_request_async
(&variax->dumpreq, &variax->line6,
1, VARIAX_DUMP_PASS2);
break; break;
case VARIAX_DUMP_PASS2: case VARIAX_DUMP_PASS2:
/* model name is transmitted twice, so skip it here: */ /* model name is transmitted twice, so skip it here: */
variax_decode(buf + VARIAX_MODEL_HEADER_LENGTH, variax_decode(buf +
(unsigned char *)&variax->model_data.control + sizeof(variax->model_data.control) / 2, VARIAX_MODEL_HEADER_LENGTH,
sizeof(variax->model_data.control) / 2 * 2); (unsigned char *)
line6_dump_request_async(&variax->dumpreq, &variax->line6, 2, VARIAX_DUMP_PASS3); &variax->
model_data.control +
sizeof(variax->model_data.
control)
/ 2,
sizeof(variax->model_data.
control)
/ 2 * 2);
line6_dump_request_async
(&variax->dumpreq, &variax->line6,
2, VARIAX_DUMP_PASS3);
} }
} else { } else {
DEBUG_MESSAGES(dev_err(variax->line6.ifcdev, "illegal length %d of model data\n", variax->line6.message_length)); DEBUG_MESSAGES(dev_err
(variax->line6.ifcdev,
"illegal length %d of model data\n",
variax->line6.message_length));
line6_dump_finished(&variax->dumpreq); line6_dump_finished(&variax->dumpreq);
} }
} else if (memcmp(buf + 1, variax_request_bank + 1, } else if (memcmp(buf + 1, variax_request_bank + 1,
...@@ -257,7 +293,9 @@ void line6_variax_process_message(struct usb_line6_variax *variax) ...@@ -257,7 +293,9 @@ void line6_variax_process_message(struct usb_line6_variax *variax)
break; break;
default: default:
DEBUG_MESSAGES(dev_err(variax->line6.ifcdev, "Variax: unknown message %02X\n", buf[0])); DEBUG_MESSAGES(dev_err
(variax->line6.ifcdev,
"Variax: unknown message %02X\n", buf[0]));
} }
} }
...@@ -267,7 +305,8 @@ void line6_variax_process_message(struct usb_line6_variax *variax) ...@@ -267,7 +305,8 @@ void line6_variax_process_message(struct usb_line6_variax *variax)
static ssize_t variax_get_volume(struct device *dev, static ssize_t variax_get_volume(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); struct usb_line6_variax *variax =
usb_get_intfdata(to_usb_interface(dev));
return sprintf(buf, "%d\n", variax->volume); return sprintf(buf, "%d\n", variax->volume);
} }
...@@ -278,7 +317,8 @@ static ssize_t variax_set_volume(struct device *dev, ...@@ -278,7 +317,8 @@ static ssize_t variax_set_volume(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); struct usb_line6_variax *variax =
usb_get_intfdata(to_usb_interface(dev));
unsigned long value; unsigned long value;
int ret; int ret;
...@@ -299,7 +339,8 @@ static ssize_t variax_set_volume(struct device *dev, ...@@ -299,7 +339,8 @@ static ssize_t variax_set_volume(struct device *dev,
static ssize_t variax_get_model(struct device *dev, static ssize_t variax_get_model(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); struct usb_line6_variax *variax =
usb_get_intfdata(to_usb_interface(dev));
return sprintf(buf, "%d\n", variax->model); return sprintf(buf, "%d\n", variax->model);
} }
...@@ -310,7 +351,8 @@ static ssize_t variax_set_model(struct device *dev, ...@@ -310,7 +351,8 @@ static ssize_t variax_set_model(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); struct usb_line6_variax *variax =
usb_get_intfdata(to_usb_interface(dev));
unsigned long value; unsigned long value;
int ret; int ret;
...@@ -330,8 +372,10 @@ static ssize_t variax_set_model(struct device *dev, ...@@ -330,8 +372,10 @@ static ssize_t variax_set_model(struct device *dev,
static ssize_t variax_get_active(struct device *dev, static ssize_t variax_get_active(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); struct usb_line6_variax *variax =
return sprintf(buf, "%d\n", variax->buffer_activate[VARIAX_OFFSET_ACTIVATE]); usb_get_intfdata(to_usb_interface(dev));
return sprintf(buf, "%d\n",
variax->buffer_activate[VARIAX_OFFSET_ACTIVATE]);
} }
/* /*
...@@ -341,7 +385,8 @@ static ssize_t variax_set_active(struct device *dev, ...@@ -341,7 +385,8 @@ static ssize_t variax_set_active(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); struct usb_line6_variax *variax =
usb_get_intfdata(to_usb_interface(dev));
unsigned long value; unsigned long value;
int ret; int ret;
...@@ -359,7 +404,8 @@ static ssize_t variax_set_active(struct device *dev, ...@@ -359,7 +404,8 @@ static ssize_t variax_set_active(struct device *dev,
static ssize_t variax_get_tone(struct device *dev, static ssize_t variax_get_tone(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); struct usb_line6_variax *variax =
usb_get_intfdata(to_usb_interface(dev));
return sprintf(buf, "%d\n", variax->tone); return sprintf(buf, "%d\n", variax->tone);
} }
...@@ -370,7 +416,8 @@ static ssize_t variax_set_tone(struct device *dev, ...@@ -370,7 +416,8 @@ static ssize_t variax_set_tone(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); struct usb_line6_variax *variax =
usb_get_intfdata(to_usb_interface(dev));
unsigned long value; unsigned long value;
int ret; int ret;
...@@ -407,7 +454,8 @@ static ssize_t get_string(char *buf, const char *data, int length) ...@@ -407,7 +454,8 @@ static ssize_t get_string(char *buf, const char *data, int length)
static ssize_t variax_get_name(struct device *dev, static ssize_t variax_get_name(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); struct usb_line6_variax *variax =
usb_get_intfdata(to_usb_interface(dev));
line6_dump_wait_interruptible(&variax->dumpreq); line6_dump_wait_interruptible(&variax->dumpreq);
return get_string(buf, variax->model_data.name, return get_string(buf, variax->model_data.name,
sizeof(variax->model_data.name)); sizeof(variax->model_data.name));
...@@ -419,7 +467,8 @@ static ssize_t variax_get_name(struct device *dev, ...@@ -419,7 +467,8 @@ static ssize_t variax_get_name(struct device *dev,
static ssize_t variax_get_bank(struct device *dev, static ssize_t variax_get_bank(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); struct usb_line6_variax *variax =
usb_get_intfdata(to_usb_interface(dev));
line6_dump_wait_interruptible(&variax->dumpreq); line6_dump_wait_interruptible(&variax->dumpreq);
return get_string(buf, variax->bank, sizeof(variax->bank)); return get_string(buf, variax->bank, sizeof(variax->bank));
} }
...@@ -430,7 +479,8 @@ static ssize_t variax_get_bank(struct device *dev, ...@@ -430,7 +479,8 @@ static ssize_t variax_get_bank(struct device *dev,
static ssize_t variax_get_dump(struct device *dev, static ssize_t variax_get_dump(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); struct usb_line6_variax *variax =
usb_get_intfdata(to_usb_interface(dev));
int retval; int retval;
retval = line6_dump_wait_interruptible(&variax->dumpreq); retval = line6_dump_wait_interruptible(&variax->dumpreq);
if (retval < 0) if (retval < 0)
...@@ -446,15 +496,18 @@ static ssize_t variax_get_dump(struct device *dev, ...@@ -446,15 +496,18 @@ static ssize_t variax_get_dump(struct device *dev,
static ssize_t variax_get_guitar(struct device *dev, static ssize_t variax_get_guitar(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); struct usb_line6_variax *variax =
usb_get_intfdata(to_usb_interface(dev));
return sprintf(buf, "%s\n", variax->guitar); return sprintf(buf, "%s\n", variax->guitar);
} }
#ifdef CONFIG_LINE6_USB_RAW #ifdef CONFIG_LINE6_USB_RAW
static char *variax_alloc_sysex_buffer(struct usb_line6_variax *variax, int code, int size) static char *variax_alloc_sysex_buffer(struct usb_line6_variax *variax,
int code, int size)
{ {
return line6_alloc_sysex_buffer(&variax->line6, VARIAX_SYSEX_CODE, code, size); return line6_alloc_sysex_buffer(&variax->line6, VARIAX_SYSEX_CODE, code,
size);
} }
/* /*
...@@ -464,7 +517,8 @@ static ssize_t variax_set_raw2(struct device *dev, ...@@ -464,7 +517,8 @@ static ssize_t variax_set_raw2(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev)); struct usb_line6_variax *variax =
usb_get_intfdata(to_usb_interface(dev));
int size; int size;
int i; int i;
char *sysex; char *sysex;
...@@ -495,13 +549,16 @@ static ssize_t variax_set_raw2(struct device *dev, ...@@ -495,13 +549,16 @@ static ssize_t variax_set_raw2(struct device *dev,
#endif #endif
/* Variax workbench special files: */ /* Variax workbench special files: */
static DEVICE_ATTR(model, S_IWUGO | S_IRUGO, variax_get_model, variax_set_model); static DEVICE_ATTR(model, S_IWUGO | S_IRUGO, variax_get_model,
static DEVICE_ATTR(volume, S_IWUGO | S_IRUGO, variax_get_volume, variax_set_volume); variax_set_model);
static DEVICE_ATTR(volume, S_IWUGO | S_IRUGO, variax_get_volume,
variax_set_volume);
static DEVICE_ATTR(tone, S_IWUGO | S_IRUGO, variax_get_tone, variax_set_tone); static DEVICE_ATTR(tone, S_IWUGO | S_IRUGO, variax_get_tone, variax_set_tone);
static DEVICE_ATTR(name, S_IRUGO, variax_get_name, line6_nop_write); static DEVICE_ATTR(name, S_IRUGO, variax_get_name, line6_nop_write);
static DEVICE_ATTR(bank, S_IRUGO, variax_get_bank, line6_nop_write); static DEVICE_ATTR(bank, S_IRUGO, variax_get_bank, line6_nop_write);
static DEVICE_ATTR(dump, S_IRUGO, variax_get_dump, line6_nop_write); static DEVICE_ATTR(dump, S_IRUGO, variax_get_dump, line6_nop_write);
static DEVICE_ATTR(active, S_IWUGO | S_IRUGO, variax_get_active, variax_set_active); static DEVICE_ATTR(active, S_IWUGO | S_IRUGO, variax_get_active,
variax_set_active);
static DEVICE_ATTR(guitar, S_IRUGO, variax_get_guitar, line6_nop_write); static DEVICE_ATTR(guitar, S_IRUGO, variax_get_guitar, line6_nop_write);
#ifdef CONFIG_LINE6_USB_RAW #ifdef CONFIG_LINE6_USB_RAW
...@@ -509,7 +566,6 @@ static DEVICE_ATTR(raw, S_IWUGO, line6_nop_read, line6_set_raw); ...@@ -509,7 +566,6 @@ static DEVICE_ATTR(raw, S_IWUGO, line6_nop_read, line6_set_raw);
static DEVICE_ATTR(raw2, S_IWUGO, line6_nop_read, variax_set_raw2); static DEVICE_ATTR(raw2, S_IWUGO, line6_nop_read, variax_set_raw2);
#endif #endif
/* /*
Variax destructor. Variax destructor.
*/ */
...@@ -525,6 +581,10 @@ static void variax_destruct(struct usb_interface *interface) ...@@ -525,6 +581,10 @@ static void variax_destruct(struct usb_interface *interface)
return; return;
line6_cleanup_audio(line6); line6_cleanup_audio(line6);
del_timer(&variax->startup_timer1);
del_timer(&variax->startup_timer2);
cancel_work_sync(&variax->startup_work);
/* free dump request data: */ /* free dump request data: */
line6_dumpreq_destructbuf(&variax->dumpreq, 2); line6_dumpreq_destructbuf(&variax->dumpreq, 2);
line6_dumpreq_destructbuf(&variax->dumpreq, 1); line6_dumpreq_destructbuf(&variax->dumpreq, 1);
...@@ -562,12 +622,13 @@ static int variax_try_init(struct usb_interface *interface, ...@@ -562,12 +622,13 @@ static int variax_try_init(struct usb_interface *interface,
{ {
int err; int err;
init_timer(&variax->startup_timer1);
init_timer(&variax->startup_timer2);
INIT_WORK(&variax->startup_work, variax_startup7);
if ((interface == NULL) || (variax == NULL)) if ((interface == NULL) || (variax == NULL))
return -ENODEV; return -ENODEV;
init_timer(&variax->startup_timer);
INIT_WORK(&variax->startup_work, variax_startup7);
/* initialize USB buffers: */ /* initialize USB buffers: */
err = line6_dumpreq_init(&variax->dumpreq, variax_request_model1, err = line6_dumpreq_init(&variax->dumpreq, variax_request_model1,
sizeof(variax_request_model1)); sizeof(variax_request_model1));
......
/* /*
* Line6 Linux USB driver - 0.9.0 * Line6 Linux USB driver - 0.9.1beta
* *
* Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
* *
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#ifndef VARIAX_H #ifndef VARIAX_H
#define VARIAX_H #define VARIAX_H
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/wait.h> #include <linux/wait.h>
...@@ -21,11 +20,23 @@ ...@@ -21,11 +20,23 @@
#include "driver.h" #include "driver.h"
#include "dumprequest.h" #include "dumprequest.h"
#define VARIAX_STARTUP_DELAY1 1000 #define VARIAX_STARTUP_DELAY1 1000
#define VARIAX_STARTUP_DELAY3 100 #define VARIAX_STARTUP_DELAY3 100
#define VARIAX_STARTUP_DELAY4 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_DUMPREQ,
VARIAX_STARTUP_WORKQUEUE,
VARIAX_STARTUP_SETUP,
VARIAX_STARTUP_LAST = VARIAX_STARTUP_SETUP - 1
};
enum { enum {
VARIAX_DUMP_PASS1 = LINE6_DUMP_CURRENT, VARIAX_DUMP_PASS1 = LINE6_DUMP_CURRENT,
...@@ -33,7 +44,6 @@ enum { ...@@ -33,7 +44,6 @@ enum {
VARIAX_DUMP_PASS3 VARIAX_DUMP_PASS3
}; };
/** /**
Binary Variax model dump Binary Variax model dump
*/ */
...@@ -59,7 +69,8 @@ struct usb_line6_variax { ...@@ -59,7 +69,8 @@ struct usb_line6_variax {
Dump request structure. Dump request structure.
Append two extra buffers for 3-pass data query. Append two extra buffers for 3-pass data query.
*/ */
struct line6_dump_request dumpreq; struct line6_dump_reqbuf extrabuf[2]; struct line6_dump_request dumpreq;
struct line6_dump_reqbuf extrabuf[2];
/** /**
Buffer for activation code. Buffer for activation code.
...@@ -102,9 +113,10 @@ struct usb_line6_variax { ...@@ -102,9 +113,10 @@ struct usb_line6_variax {
struct work_struct startup_work; struct work_struct startup_work;
/** /**
Timer for device initializaton. Timers for device initializaton.
*/ */
struct timer_list startup_timer; struct timer_list startup_timer1;
struct timer_list startup_timer2;
/** /**
Current progress in startup procedure. Current progress in startup procedure.
...@@ -112,11 +124,9 @@ struct usb_line6_variax { ...@@ -112,11 +124,9 @@ struct usb_line6_variax {
int startup_progress; int startup_progress;
}; };
extern void line6_variax_disconnect(struct usb_interface *interface); extern void line6_variax_disconnect(struct usb_interface *interface);
extern int line6_variax_init(struct usb_interface *interface, extern int line6_variax_init(struct usb_interface *interface,
struct usb_line6_variax *variax); struct usb_line6_variax *variax);
extern void line6_variax_process_message(struct usb_line6_variax *variax); extern void line6_variax_process_message(struct usb_line6_variax *variax);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment