···11-config LINE6_USB11+menuconfig LINE6_USB22 tristate "Line6 USB support"33 depends on USB && SND44 select SND_RAWMIDI···1818 * Signal routing (record clean/processed guitar signal,1919 re-amping)20202121- Preliminary support for the Variax Workbench is included.2121+ Preliminary support for the Variax Workbench and TonePort2222+ devices is included.22232424+if LINE6_USB2525+2626+config LINE6_USB_DEBUG2727+ bool "print debug messages"2828+ default n2929+ help3030+ Say Y here to write debug messages to the syslog.3131+3232+ If unsure, say N.3333+3434+config LINE6_USB_DUMP_CTRL3535+ bool "dump control messages"3636+ default n3737+ help3838+ Say Y here to write control messages sent to and received from3939+ Line6 devices to the syslog.4040+4141+ If unsure, say N.4242+4343+config LINE6_USB_DUMP_MIDI4444+ bool "dump MIDI messages"4545+ default n4646+ help4747+ Say Y here to write MIDI messages sent to and received from4848+ Line6 devices to the syslog.4949+5050+ If unsure, say N.5151+5252+config LINE6_USB_DUMP_PCM5353+ bool "dump PCM data"5454+ default n5555+ help5656+ Say Y here to write PCM data sent to and received from Line65757+ devices to the syslog. This will produce a huge amount of5858+ syslog data during playback and capture.5959+6060+ If unsure, say N.6161+6262+config LINE6_USB_RAW6363+ bool "raw data communication"6464+ default n6565+ help6666+ Say Y here to create special files which allow to send raw data6767+ to the device. This bypasses any sanity checks, so if you discover6868+ the code to erase the firmware, feel free to render your device6969+ useless, but only after reading the GPL section "NO WARRANTY".7070+7171+ If unsure, say N.7272+7373+config LINE6_USB_IMPULSE_RESPONSE7474+ bool "measure impulse response"7575+ default n7676+ help7777+ Say Y here to add code to measure the impulse response of a Line67878+ device. This is more accurate than user-space methods since it7979+ bypasses any PCM data buffering (e.g., by ALSA or jack). This is8080+ useful for assessing the performance of new devices, but is not8181+ required for normal operation.8282+8383+ If unsure, say N.8484+8585+endif # LINE6_USB
+7-6
drivers/staging/line6/audio.c
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···99 *1010 */11111212-#include "driver.h"1313-#include "audio.h"1414-1512#include <sound/core.h>1613#include <sound/initval.h>1414+1515+#include "driver.h"1616+#include "audio.h"171718181919static int line6_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;···36363737 line6->card = card;38383939+ strcpy(card->id, line6->properties->id);3940 strcpy(card->driver, DRIVER_NAME);4040- strcpy(card->shortname, "Line6-USB");4141+ strcpy(card->shortname, line6->properties->name);4142 sprintf(card->longname, "Line6 %s at USB %s", line6->properties->name,4243 dev_name(line6->ifcdev)); /* 80 chars - see asound.h */4344 return 0;
+2-2
drivers/staging/line6/audio.h
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as
+117-113
drivers/staging/line6/capture.c
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···99 *1010 */11111212-#include "driver.h"1313-1414-#include <linux/slab.h>1515-1612#include <sound/core.h>1713#include <sound/pcm.h>1814#include <sound/pcm_params.h>19152016#include "audio.h"1717+#include "capture.h"1818+#include "driver.h"2119#include "pcm.h"2220#include "pod.h"2323-#include "capture.h"2121+24222523/*2624 Find a free URB and submit it.2725*/2828-static int submit_audio_in_urb(struct snd_pcm_substream *substream)2626+static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)2927{3030- unsigned int index;2828+ int index;3129 unsigned long flags;3232- struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);3330 int i, urb_size;3431 struct urb *urb_in;3532···3437 index =3538 find_first_zero_bit(&line6pcm->active_urb_in, LINE6_ISO_BUFFERS);36393737- if (index >= LINE6_ISO_BUFFERS) {4040+ if (index < 0 || index >= LINE6_ISO_BUFFERS) {3841 spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags);3939- dev_err(s2m(substream), "no free URB found\n");4242+ dev_err(line6pcm->line6->ifcdev, "no free URB found\n");4043 return -EINVAL;4144 }4245···5558 line6pcm->buffer_in +5659 index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;5760 urb_in->transfer_buffer_length = urb_size;5858- urb_in->context = substream;6161+ urb_in->context = line6pcm;59626063 if (usb_submit_urb(urb_in, GFP_ATOMIC) == 0)6164 set_bit(index, &line6pcm->active_urb_in);6265 else6363- dev_err(s2m(substream), "URB in #%d submission failed\n",6464- index);6666+ dev_err(line6pcm->line6->ifcdev,6767+ "URB in #%d submission failed\n", index);65686669 spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags);6770 return 0;···7073/*7174 Submit all currently available capture URBs.7275*/7373-static int submit_audio_in_all_urbs(struct snd_pcm_substream *substream)7676+int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm)7477{7578 int ret, i;76797780 for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {7878- ret = submit_audio_in_urb(substream);8181+ ret = submit_audio_in_urb(line6pcm);7982 if (ret < 0)8083 return ret;8184 }···8689/*8790 Unlink all currently active capture URBs.8891*/8989-static void unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm)9292+void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm)9093{9194 unsigned int i;9295···123126 } while (--timeout > 0);124127 if (alive)125128 snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);126126-127127- line6pcm->active_urb_in = 0;128128- line6pcm->unlink_urb_in = 0;129129}130130131131/*132132 Unlink all currently active capture URBs, and wait for finishing.133133*/134134-void unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm)134134+void line6_unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm)135135{136136- unlink_audio_in_urbs(line6pcm);136136+ line6_unlink_audio_in_urbs(line6pcm);137137 wait_clear_audio_in_urbs(line6pcm);138138}139139140140/*141141- Callback for completed capture URB.141141+ Copy data into ALSA capture buffer.142142+*/143143+void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize)144144+{145145+ struct snd_pcm_substream *substream =146146+ get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE);147147+ struct snd_pcm_runtime *runtime = substream->runtime;148148+ const int bytes_per_frame = line6pcm->properties->bytes_per_frame;149149+ int frames = fsize / bytes_per_frame;150150+151151+ if (line6pcm->pos_in_done + frames > runtime->buffer_size) {152152+ /*153153+ The transferred area goes over buffer boundary,154154+ copy two separate chunks.155155+ */156156+ int len;157157+ len = runtime->buffer_size - line6pcm->pos_in_done;158158+159159+ if (len > 0) {160160+ memcpy(runtime->dma_area +161161+ line6pcm->pos_in_done * bytes_per_frame, fbuf,162162+ len * bytes_per_frame);163163+ memcpy(runtime->dma_area, fbuf + len * bytes_per_frame,164164+ (frames - len) * bytes_per_frame);165165+ } else166166+ dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n", len); /* this is somewhat paranoid */167167+ } else {168168+ /* copy single chunk */169169+ memcpy(runtime->dma_area +170170+ line6pcm->pos_in_done * bytes_per_frame, fbuf, fsize);171171+ }172172+173173+ if ((line6pcm->pos_in_done += frames) >= runtime->buffer_size)174174+ line6pcm->pos_in_done -= runtime->buffer_size;175175+}176176+177177+void line6_capture_check_period(struct snd_line6_pcm *line6pcm, int length)178178+{179179+ struct snd_pcm_substream *substream =180180+ get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE);181181+182182+ if ((line6pcm->bytes_in += length) >= line6pcm->period_in) {183183+ line6pcm->bytes_in %= line6pcm->period_in;184184+ snd_pcm_period_elapsed(substream);185185+ }186186+}187187+188188+/*189189+ Callback for completed capture URB.142190*/143191static void audio_in_callback(struct urb *urb)144192{145193 int i, index, length = 0, shutdown = 0;146146- int frames;147194 unsigned long flags;148195149149- struct snd_pcm_substream *substream =150150- (struct snd_pcm_substream *)urb->context;151151- struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);152152- const int bytes_per_frame = line6pcm->properties->bytes_per_frame;153153- struct snd_pcm_runtime *runtime = substream->runtime;196196+ struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context;197197+198198+ line6pcm->last_frame_in = urb->start_frame;154199155200 /* find index of URB */156201 for (index = 0; index < LINE6_ISO_BUFFERS; ++index)157202 if (urb == line6pcm->urb_audio_in[index])158203 break;159204160160-#if DO_DUMP_PCM_RECEIVE205205+#ifdef CONFIG_LINE6_USB_DUMP_PCM161206 for (i = 0; i < LINE6_ISO_PACKETS; ++i) {162207 struct usb_iso_packet_descriptor *fout =163208 &urb->iso_frame_desc[i];···223184224185 fbuf = urb->transfer_buffer + fin->offset;225186 fsize = fin->actual_length;187187+188188+ if (fsize > line6pcm->max_packet_size) {189189+ dev_err(line6pcm->line6->ifcdev,190190+ "driver and/or device bug: packet too large (%d > %d)\n",191191+ fsize, line6pcm->max_packet_size);192192+ }193193+226194 length += fsize;227195228228- if (fsize > 0) {229229- frames = fsize / bytes_per_frame;196196+ /* the following assumes LINE6_ISO_PACKETS == 1: */197197+#if LINE6_BACKUP_MONITOR_SIGNAL198198+ memcpy(line6pcm->prev_fbuf, fbuf, fsize);199199+#else200200+ line6pcm->prev_fbuf = fbuf;201201+#endif202202+ line6pcm->prev_fsize = fsize;230203231231- if (line6pcm->pos_in_done + frames >232232- runtime->buffer_size) {233233- /*234234- The transferred area goes over buffer235235- boundary, copy two separate chunks.236236- */237237- int len;238238- len =239239- runtime->buffer_size -240240- line6pcm->pos_in_done;241241-242242- if (len > 0) {243243- memcpy(runtime->dma_area +244244- line6pcm->pos_in_done *245245- bytes_per_frame, fbuf,246246- len * bytes_per_frame);247247- memcpy(runtime->dma_area,248248- fbuf + len * bytes_per_frame,249249- (frames -250250- len) * bytes_per_frame);251251- } else {252252- /* this is somewhat paranoid */253253- dev_err(s2m(substream),254254- "driver bug: len = %d\n", len);255255- }256256- } else {257257- /* copy single chunk */258258- memcpy(runtime->dma_area +259259- line6pcm->pos_in_done * bytes_per_frame,260260- fbuf, fsize * bytes_per_frame);261261- }262262-263263- line6pcm->pos_in_done += frames;264264- if (line6pcm->pos_in_done >= runtime->buffer_size)265265- line6pcm->pos_in_done -= runtime->buffer_size;266266- }204204+#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE205205+ if (!(line6pcm->flags & MASK_PCM_IMPULSE))206206+#endif207207+ if (test_bit(BIT_PCM_ALSA_CAPTURE, &line6pcm->flags)208208+ && (fsize > 0))209209+ line6_capture_copy(line6pcm, fbuf, fsize);267210 }268211269212 clear_bit(index, &line6pcm->active_urb_in);270213271271- if (test_bit(index, &line6pcm->unlink_urb_in))214214+ if (test_and_clear_bit(index, &line6pcm->unlink_urb_in))272215 shutdown = 1;273216274217 spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags);275218276219 if (!shutdown) {277277- submit_audio_in_urb(substream);220220+ submit_audio_in_urb(line6pcm);278221279279- line6pcm->bytes_in += length;280280- if (line6pcm->bytes_in >= line6pcm->period_in) {281281- line6pcm->bytes_in -= line6pcm->period_in;282282- snd_pcm_period_elapsed(substream);283283- }222222+ if (test_bit(BIT_PCM_ALSA_CAPTURE, &line6pcm->flags))223223+ line6_capture_check_period(line6pcm, length);284224 }285225}286226···312294 return ret;313295314296 line6pcm->period_in = params_period_bytes(hw_params);315315- line6pcm->buffer_in =316316- kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *317317- LINE6_ISO_PACKET_SIZE_MAX, GFP_KERNEL);318318-319319- if (!line6pcm->buffer_in) {320320- dev_err(s2m(substream), "cannot malloc buffer_in\n");321321- return -ENOMEM;322322- }323323-324297 return 0;325298}326299327300/* hw_free capture callback */328301static int snd_line6_capture_hw_free(struct snd_pcm_substream *substream)329302{330330- struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);331331- unlink_wait_clear_audio_in_urbs(line6pcm);332332-333333- kfree(line6pcm->buffer_in);334334- line6pcm->buffer_in = NULL;335335-336303 return snd_pcm_lib_free_pages(substream);337304}338305339306/* trigger callback */340340-int snd_line6_capture_trigger(struct snd_pcm_substream *substream, int cmd)307307+int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd)341308{342342- struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);343309 int err;344344- line6pcm->count_in = 0;345310346311 switch (cmd) {347312 case SNDRV_PCM_TRIGGER_START:348348- if (!test_and_set_bit(BIT_RUNNING_CAPTURE, &line6pcm->flags)) {349349- err = submit_audio_in_all_urbs(substream);313313+#ifdef CONFIG_PM314314+ case SNDRV_PCM_TRIGGER_RESUME:315315+#endif316316+ err = line6_pcm_start(line6pcm, MASK_PCM_ALSA_CAPTURE);350317351351- if (err < 0) {352352- clear_bit(BIT_RUNNING_CAPTURE,353353- &line6pcm->flags);354354- return err;355355- }356356- }318318+ if (err < 0)319319+ return err;357320358321 break;359322360323 case SNDRV_PCM_TRIGGER_STOP:361361- if (test_and_clear_bit(BIT_RUNNING_CAPTURE, &line6pcm->flags))362362- unlink_audio_in_urbs(line6pcm);324324+#ifdef CONFIG_PM325325+ case SNDRV_PCM_TRIGGER_SUSPEND:326326+#endif327327+ err = line6_pcm_stop(line6pcm, MASK_PCM_ALSA_CAPTURE);328328+329329+ if (err < 0)330330+ return err;363331364332 break;365333···366362367363/* capture operators */368364struct snd_pcm_ops snd_line6_capture_ops = {369369- .open = snd_line6_capture_open,370370- .close = snd_line6_capture_close,371371- .ioctl = snd_pcm_lib_ioctl,372372- .hw_params = snd_line6_capture_hw_params,373373- .hw_free = snd_line6_capture_hw_free,374374- .prepare = snd_line6_prepare,375375- .trigger = snd_line6_trigger,376376- .pointer = snd_line6_capture_pointer,365365+ .open = snd_line6_capture_open,366366+ .close = snd_line6_capture_close,367367+ .ioctl = snd_pcm_lib_ioctl,368368+ .hw_params = snd_line6_capture_hw_params,369369+ .hw_free = snd_line6_capture_hw_free,370370+ .prepare = snd_line6_prepare,371371+ .trigger = snd_line6_trigger,372372+ .pointer = snd_line6_capture_pointer,377373};378374379379-int create_audio_in_urbs(struct snd_line6_pcm *line6pcm)375375+int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm)380376{381377 int i;382378
+11-10
drivers/staging/line6/capture.h
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···1313#define CAPTURE_H141415151616-#include "driver.h"1717-1816#include <sound/pcm.h>19171818+#include "driver.h"2019#include "pcm.h"212022212322extern struct snd_pcm_ops snd_line6_capture_ops;24232525-2626-extern int create_audio_in_urbs(struct snd_line6_pcm *line6pcm);2727-extern int snd_line6_capture_trigger(struct snd_pcm_substream *substream,2828- int cmd);2929-extern void unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm);3030-2424+extern void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf,2525+ int fsize);2626+extern int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm);2727+extern int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm);2828+extern void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm);2929+extern void line6_unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm3030+ *line6pcm);3131+extern int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd);31323233#endif
+24-22
drivers/staging/line6/control.c
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···99 *1010 */11111212-#include "driver.h"1313-1412#include <linux/usb.h>15131614#include "control.h"1515+#include "driver.h"1716#include "pod.h"1817#include "usbdefs.h"1918#include "variax.h"···4445{4546 struct usb_interface *interface = to_usb_interface(dev);4647 struct usb_line6_pod *pod = usb_get_intfdata(interface);4747- int retval = line6_wait_dump(&pod->dumpreq, 0);4848+ int retval = line6_dump_wait_interruptible(&pod->dumpreq);4849 if (retval < 0)4950 return retval;5051 return sprintf(buf, "%d\n", pod->prog_data.control[param]);···6263 if (retval)6364 return retval;64656565- pod_transmit_parameter(pod, param, value);6666+ line6_pod_transmit_parameter(pod, param, value);6667 return count;6768}6869···7071{7172 struct usb_interface *interface = to_usb_interface(dev);7273 struct usb_line6_variax *variax = usb_get_intfdata(interface);7373- int retval = line6_wait_dump(&variax->dumpreq, 0);7474+ int retval = line6_dump_wait_interruptible(&variax->dumpreq);7475 if (retval < 0)7576 return retval;7677 return sprintf(buf, "%d\n", variax->model_data.control[param]);···7980static ssize_t variax_get_param_float(struct device *dev, char *buf, int param)8081{8182 /*8282- We do our own floating point handling here since floats in the8383- kernel are problematic for at least two reasons: - many distros8484- are still shipped with binary kernels optimized for the ancient8585- 80386 without FPU8686- - there isn't a printf("%f")8787- (see http://www.kernelthread.com/publications/faq/335.html)8383+ We do our own floating point handling here since at the time8484+ this code was written (Jan 2006) it was highly discouraged to8585+ use floating point arithmetic in the kernel. If you think that8686+ this no longer applies, feel free to replace this by generic8787+ floating point code.8888 */89899090 static const int BIAS = 0x7f;···9597 struct usb_interface *interface = to_usb_interface(dev);9698 struct usb_line6_variax *variax = usb_get_intfdata(interface);9799 const unsigned char *p = variax->model_data.control + param;9898- int retval = line6_wait_dump(&variax->dumpreq, 0);100100+ int retval = line6_dump_wait_interruptible(&variax->dumpreq);99101 if (retval < 0)100102 return retval;101103···528530static DEVICE_ATTR(pickup_wiring, S_IRUGO, variax_get_pickup_wiring,529531 line6_nop_write);530532531531-int pod_create_files(int firmware, int type, struct device *dev)533533+int line6_pod_create_files(int firmware, int type, struct device *dev)532534{533535 int err;534536 CHECK_RETURN(device_create_file(dev, &dev_attr_tweak));···731733 (dev, &dev_attr_band_6_gain__bass));732734 return 0;733735}734734-EXPORT_SYMBOL(pod_create_files);735736736736-void pod_remove_files(int firmware, int type, struct device *dev)737737+EXPORT_SYMBOL(line6_pod_create_files);738738+739739+void line6_pod_remove_files(int firmware, int type, struct device *dev)737740{738741 device_remove_file(dev, &dev_attr_tweak);739742 device_remove_file(dev, &dev_attr_wah_position);···907908 if (firmware >= 200)908909 device_remove_file(dev, &dev_attr_band_6_gain__bass);909910}910910-EXPORT_SYMBOL(pod_remove_files);911911912912-int variax_create_files(int firmware, int type, struct device *dev)912912+EXPORT_SYMBOL(line6_pod_remove_files);913913+914914+int line6_variax_create_files(int firmware, int type, struct device *dev)913915{914916 int err;915917 CHECK_RETURN(device_create_file(dev, &dev_attr_body));···954954 CHECK_RETURN(device_create_file(dev, &dev_attr_pickup_wiring));955955 return 0;956956}957957-EXPORT_SYMBOL(variax_create_files);958957959959-void variax_remove_files(int firmware, int type, struct device *dev)958958+EXPORT_SYMBOL(line6_variax_create_files);959959+960960+void line6_variax_remove_files(int firmware, int type, struct device *dev)960961{961962 device_remove_file(dev, &dev_attr_body);962963 device_remove_file(dev, &dev_attr_pickup1_enable);···999998 device_remove_file(dev, &dev_attr_mix1);1000999 device_remove_file(dev, &dev_attr_pickup_wiring);10011000}10021002-EXPORT_SYMBOL(variax_remove_files);10011001+10021002+EXPORT_SYMBOL(line6_variax_remove_files);
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as88 * published by the Free Software Foundation, version 2.99 *1010 */1111-1212-#include "driver.h"13111412#include <linux/kernel.h>1513#include <linux/module.h>···1719#include "audio.h"1820#include "capture.h"1921#include "control.h"2222+#include "driver.h"2023#include "midi.h"2124#include "playback.h"2225#include "pod.h"···29303031#define DRIVER_AUTHOR "Markus Grabner <grabner@icg.tugraz.at>"3132#define DRIVER_DESC "Line6 USB Driver"3232-#define DRIVER_VERSION "0.8.0"3333+#define DRIVER_VERSION "0.9.0"333434353536/* table of devices that work with this driver */···3940 { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXTPRO) },4041 { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_GUITARPORT) },4142 { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_POCKETPOD) },4343+ { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_GX) },4444+ { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_UX1) },4545+ { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_UX2) },4246 { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODX3) },4347 { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODX3LIVE) },4448 { USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODXT) },···5654MODULE_DEVICE_TABLE(usb, line6_id_table);57555856static struct line6_properties line6_properties_table[] = {5959- { "BassPODxt", LINE6_BIT_BASSPODXT, LINE6_BIT_CONTROL_PCM },6060- { "BassPODxt Live", LINE6_BIT_BASSPODXTLIVE, LINE6_BIT_CONTROL_PCM },6161- { "BassPODxt Pro", LINE6_BIT_BASSPODXTPRO, LINE6_BIT_CONTROL_PCM },6262- { "GuitarPort", LINE6_BIT_GUITARPORT, LINE6_BIT_PCM },6363- { "Pocket POD", LINE6_BIT_POCKETPOD, LINE6_BIT_CONTROL_PCM },6464- { "POD X3", LINE6_BIT_PODX3, LINE6_BIT_PCM },6565- { "POD X3 Live", LINE6_BIT_PODX3LIVE, LINE6_BIT_PCM },6666- { "PODxt", LINE6_BIT_PODXT, LINE6_BIT_CONTROL_PCM },6767- { "PODxt Live", LINE6_BIT_PODXTLIVE, LINE6_BIT_CONTROL_PCM },6868- { "PODxt Pro", LINE6_BIT_PODXTPRO, LINE6_BIT_CONTROL_PCM },6969- { "TonePort GX", LINE6_BIT_TONEPORT_GX, LINE6_BIT_PCM },7070- { "TonePort UX1", LINE6_BIT_TONEPORT_UX1, LINE6_BIT_PCM },7171- { "TonePort UX2", LINE6_BIT_TONEPORT_UX2, LINE6_BIT_PCM },7272- { "Variax Workbench", LINE6_BIT_VARIAX, LINE6_BIT_CONTROL }5757+ { "BassPODxt", "BassPODxt", LINE6_BIT_BASSPODXT, LINE6_BIT_CONTROL_PCM_HWMON },5858+ { "BassPODxtLive", "BassPODxt Live", LINE6_BIT_BASSPODXTLIVE, LINE6_BIT_CONTROL_PCM_HWMON },5959+ { "BassPODxtPro", "BassPODxt Pro", LINE6_BIT_BASSPODXTPRO, LINE6_BIT_CONTROL_PCM_HWMON },6060+ { "GuitarPort", "GuitarPort", LINE6_BIT_GUITARPORT, LINE6_BIT_PCM },6161+ { "PocketPOD", "Pocket POD", LINE6_BIT_POCKETPOD, LINE6_BIT_CONTROL },6262+ { "PODStudioGX", "POD Studio GX", LINE6_BIT_PODSTUDIO_GX, LINE6_BIT_PCM },6363+ { "PODStudioUX1", "POD Studio UX1", LINE6_BIT_PODSTUDIO_UX1, LINE6_BIT_PCM },6464+ { "PODStudioUX2", "POD Studio UX2", LINE6_BIT_PODSTUDIO_UX2, LINE6_BIT_PCM },6565+ { "PODX3", "POD X3", LINE6_BIT_PODX3, LINE6_BIT_PCM },6666+ { "PODX3Live", "POD X3 Live", LINE6_BIT_PODX3LIVE, LINE6_BIT_PCM },6767+ { "PODxt", "PODxt", LINE6_BIT_PODXT, LINE6_BIT_CONTROL_PCM_HWMON },6868+ { "PODxtLive", "PODxt Live", LINE6_BIT_PODXTLIVE, LINE6_BIT_CONTROL_PCM_HWMON },6969+ { "PODxtPro", "PODxt Pro", LINE6_BIT_PODXTPRO, LINE6_BIT_CONTROL_PCM_HWMON },7070+ { "TonePortGX", "TonePort GX", LINE6_BIT_TONEPORT_GX, LINE6_BIT_PCM },7171+ { "TonePortUX1", "TonePort UX1", LINE6_BIT_TONEPORT_UX1, LINE6_BIT_PCM },7272+ { "TonePortUX2", "TonePort UX2", LINE6_BIT_TONEPORT_UX2, LINE6_BIT_PCM },7373+ { "Variax", "Variax Workbench", LINE6_BIT_VARIAX, LINE6_BIT_CONTROL }7374};747575767677/*7778 This is Line6's MIDI manufacturer ID.7879*/7979-const unsigned char line6_midi_id[] = { 0x00, 0x01, 0x0c };8080+const unsigned char line6_midi_id[] = {8181+ 0x00, 0x01, 0x0c8282+};8383+8484+/*8585+ Code to request version of POD, Variax interface8686+ (and maybe other devices).8787+*/8888+static const char line6_request_version0[] = {8989+ 0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf79090+};9191+9292+/*9393+ Copy of version request code with GFP_KERNEL flag for use in URB.9494+*/9595+static const char *line6_request_version;9696+80978198struct usb_line6 *line6_devices[LINE6_MAX_DEVICES];8282-struct workqueue_struct *line6_workqueue;83998410085101/**···124104*/125105static int line6_start_listen(struct usb_line6 *line6)126106{107107+ int err;127108 usb_fill_int_urb(line6->urb_listen, line6->usbdev,128109 usb_rcvintpipe(line6->usbdev, line6->ep_control_read),129110 line6->buffer_listen, LINE6_BUFSIZE_LISTEN,130111 line6_data_received, line6, line6->interval);131112 line6->urb_listen->actual_length = 0;132132- return usb_submit_urb(line6->urb_listen, GFP_KERNEL);113113+ err = usb_submit_urb(line6->urb_listen, GFP_KERNEL);114114+ return err;133115}134116135135-#if DO_DUMP_ANY117117+/*118118+ Stop listening on endpoint.119119+*/120120+static void line6_stop_listen(struct usb_line6 *line6)121121+{122122+ usb_kill_urb(line6->urb_listen);123123+}124124+125125+#ifdef CONFIG_LINE6_USB_DUMP_ANY136126/*137127 Write hexdump to syslog.138128*/···182152}183153#endif184154185185-#if DO_DUMP_URB_RECEIVE155155+#ifdef CONFIG_LINE6_USB_DUMP_CTRL186156/*187157 Dump URB data to syslog.188158*/···199169#endif200170201171/*202202- Send raw message in pieces of max_packet_size bytes.172172+ Send raw message in pieces of wMaxPacketSize bytes.203173*/204174int line6_send_raw_message(struct usb_line6 *line6, const char *buffer,205175 int size)206176{207177 int i, done = 0;208208- int actual_size;209178210210-#if DO_DUMP_URB_SEND179179+#ifdef CONFIG_LINE6_USB_DUMP_CTRL211180 line6_write_hexdump(line6, 'S', buffer, size);212181#endif213182214214- for (i = 0; i < size; i += actual_size) {183183+ for (i = 0; i < size; i += line6->max_packet_size) {184184+ int partial;215185 const char *frag_buf = buffer + i;216186 int frag_size = min(line6->max_packet_size, size - i);217187 int retval;···220190 usb_sndintpipe(line6->usbdev,221191 line6->ep_control_write),222192 (char *)frag_buf, frag_size,223223- &actual_size, LINE6_TIMEOUT * HZ);193193+ &partial, LINE6_TIMEOUT * HZ);224194225195 if (retval) {226196 dev_err(line6->ifcdev,···228198 break;229199 }230200231231- done += actual_size;201201+ done += frag_size;232202 }233203234204 return done;···264234 (char *)msg->buffer + done, bytes,265235 line6_async_request_sent, msg, line6->interval);266236267267-#if DO_DUMP_URB_SEND237237+#ifdef CONFIG_LINE6_USB_DUMP_CTRL268238 line6_write_hexdump(line6, 'S', (char *)msg->buffer + done, bytes);269239#endif270240···280250 }281251282252 return 0;253253+}254254+255255+/*256256+ Setup and start timer.257257+*/258258+void line6_start_timer(struct timer_list *timer, unsigned int msecs,259259+ void (*function)(unsigned long), unsigned long data)260260+{261261+ setup_timer(timer, function, data);262262+ timer->expires = jiffies + msecs * HZ / 1000;263263+ add_timer(timer);283264}284265285266/*···330289}331290332291/*292292+ Send asynchronous device version request.293293+*/294294+int line6_version_request_async(struct usb_line6 *line6)295295+{296296+ return line6_send_raw_message_async(line6, line6_request_version, sizeof(line6_request_version0));297297+}298298+299299+/*333300 Send sysex message in pieces of wMaxPacketSize bytes.334301*/335302int line6_send_sysex_message(struct usb_line6 *line6, const char *buffer,336303 int size)337304{338305 return line6_send_raw_message(line6, buffer, size + SYSEX_EXTRA_SIZE) - SYSEX_EXTRA_SIZE;306306+}307307+308308+/*309309+ Send sysex message in pieces of wMaxPacketSize bytes.310310+*/311311+int line6_send_sysex_message_async(struct usb_line6 *line6, const char *buffer,312312+ int size)313313+{314314+ return line6_send_raw_message_async(line6, buffer, size + SYSEX_EXTRA_SIZE) - SYSEX_EXTRA_SIZE;339315}340316341317/*···363305char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1, int code2,364306 int size)365307{366366- char *buffer = kmalloc(size + SYSEX_EXTRA_SIZE, GFP_KERNEL);308308+ char *buffer = kmalloc(size + SYSEX_EXTRA_SIZE, GFP_ATOMIC);367309368310 if (!buffer) {369311 dev_err(line6->ifcdev, "out of memory\n");···390332 if (urb->status == -ESHUTDOWN)391333 return;392334393393-#if DO_DUMP_URB_RECEIVE335335+#ifdef CONFIG_LINE6_USB_DUMP_CTRL394336 line6_dump_urb(urb);395337#endif396338397397- done = midibuf_write(mb, urb->transfer_buffer, urb->actual_length);339339+ done = line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length);398340399341 if (done < urb->actual_length) {400400- midibuf_ignore(mb, done);342342+ line6_midibuf_ignore(mb, done);401343 DEBUG_MESSAGES(dev_err(line6->ifcdev, "%d %d buffer overflow - message skipped\n", done, urb->actual_length));402344 }403345404346 for (;;) {405405- done = midibuf_read(mb, line6->buffer_message, LINE6_MESSAGE_MAXLEN);347347+ done = line6_midibuf_read(mb, line6->buffer_message, LINE6_MESSAGE_MAXLEN);406348407349 if (done == 0)408350 break;409351410352 /* MIDI input filter */411411- if (midibuf_skip_message(mb, line6->line6midi->midi_mask_receive))353353+ if (line6_midibuf_skip_message(mb, line6->line6midi->midi_mask_receive))412354 continue;413355414356 line6->message_length = done;415415-#if DO_DUMP_MIDI_RECEIVE357357+#ifdef CONFIG_LINE6_USB_DUMP_MIDI416358 line6_write_hexdump(line6, 'r', line6->buffer_message, done);417359#endif418360 line6_midi_receive(line6, line6->buffer_message, done);···424366 case LINE6_DEVID_PODXT:425367 case LINE6_DEVID_PODXTPRO:426368 case LINE6_DEVID_POCKETPOD:427427- pod_process_message((struct usb_line6_pod *)line6);369369+ line6_pod_process_message((struct usb_line6_pod *)line6);428370 break;429371430372 case LINE6_DEVID_PODXTLIVE:431373 switch (line6->interface_number) {432374 case PODXTLIVE_INTERFACE_POD:433433- pod_process_message((struct usb_line6_pod *)line6);375375+ line6_pod_process_message((struct usb_line6_pod *)line6);434376 break;435377436378 case PODXTLIVE_INTERFACE_VARIAX:437437- variax_process_message((struct usb_line6_variax *)line6);379379+ line6_variax_process_message((struct usb_line6_variax *)line6);438380 break;439381440382 default:···443385 break;444386445387 case LINE6_DEVID_VARIAX:446446- variax_process_message((struct usb_line6_variax *)line6);388388+ line6_variax_process_message((struct usb_line6_variax *)line6);447389 break;448390449391 default:···454396 line6_start_listen(line6);455397}456398457457-static int line6_send(struct usb_line6 *line6, unsigned char *buf, size_t len)458458-{459459- int retval;460460- int partial;461461-462462-#if DO_DUMP_URB_SEND463463- line6_write_hexdump(line6, 'S', buf, len);464464-#endif465465-466466- retval = usb_interrupt_msg(line6->usbdev,467467- usb_sndintpipe(line6->usbdev,468468- line6->ep_control_write),469469- buf, len, &partial,470470- LINE6_TIMEOUT * HZ);471471-472472- if (retval) {473473- dev_err(line6->ifcdev,474474- "usb_interrupt_msg failed (%d)\n", retval);475475- }476476-477477- if (partial != len) {478478- dev_err(line6->ifcdev,479479- "usb_interrupt_msg sent partial message (%d)\n",480480- retval);481481- }482482-483483- return retval;484484-}485485-486399/*487400 Send channel number (i.e., switch to a different sound).488401*/489402int line6_send_program(struct usb_line6 *line6, int value)490403{404404+ int retval;491405 unsigned char *buffer;492492- size_t len = 2;406406+ int partial;493407494494- buffer = kmalloc(len, GFP_KERNEL);408408+ buffer = kmalloc(2, GFP_KERNEL);409409+495410 if (!buffer) {496411 dev_err(line6->ifcdev, "out of memory\n");497412 return -ENOMEM;···473442 buffer[0] = LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST;474443 buffer[1] = value;475444476476- return line6_send(line6, buffer, len);445445+#ifdef CONFIG_LINE6_USB_DUMP_CTRL446446+ line6_write_hexdump(line6, 'S', buffer, 2);447447+#endif448448+449449+ retval = usb_interrupt_msg(line6->usbdev,450450+ usb_sndintpipe(line6->usbdev,451451+ line6->ep_control_write),452452+ buffer, 2, &partial, LINE6_TIMEOUT * HZ);453453+454454+ if (retval)455455+ dev_err(line6->ifcdev, "usb_interrupt_msg failed (%d)\n", retval);456456+457457+ kfree(buffer);458458+ return retval;477459}478460479461/*···494450*/495451int line6_transmit_parameter(struct usb_line6 *line6, int param, int value)496452{453453+ int retval;497454 unsigned char *buffer;498498- size_t len = 3;455455+ int partial;499456500500- buffer = kmalloc(len, GFP_KERNEL);457457+ buffer = kmalloc(3, GFP_KERNEL);458458+501459 if (!buffer) {502460 dev_err(line6->ifcdev, "out of memory\n");503461 return -ENOMEM;···509463 buffer[1] = param;510464 buffer[2] = value;511465512512- return line6_send(line6, buffer, len);466466+#ifdef CONFIG_LINE6_USB_DUMP_CTRL467467+ line6_write_hexdump(line6, 'S', buffer, 3);468468+#endif469469+470470+ retval = usb_interrupt_msg(line6->usbdev,471471+ usb_sndintpipe(line6->usbdev, line6->ep_control_write),472472+ buffer, 3, &partial, LINE6_TIMEOUT * HZ);473473+474474+ if (retval)475475+ dev_err(line6->ifcdev, "usb_interrupt_msg failed (%d)\n", retval);476476+477477+ kfree(buffer);478478+ return retval;513479}514480515481/*···535477536478 /* query the serial number: */537479 ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,538538- USB_TYPE_VENDOR | USB_RECIP_DEVICE539539- | USB_DIR_OUT,540540- (datalen << 8) | 0x21, address,541541- NULL, 0, LINE6_TIMEOUT * HZ);480480+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,481481+ (datalen << 8) | 0x21, address,482482+ NULL, 0, LINE6_TIMEOUT * HZ);542483543484 if (ret < 0) {544485 dev_err(line6->ifcdev, "read request failed (error %d)\n", ret);···656599/*657600 "write" request on "raw" special file.658601*/659659-#if CREATE_RAW_FILE602602+#ifdef CONFIG_LINE6_USB_RAW660603ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,661604 const char *buf, size_t count)662605{···694637 kfree(line6);695638}696639697697-static void line6_list_devices(void)698698-{699699- int i;700700-701701- for (i = 0; i < LINE6_MAX_DEVICES; ++i) {702702- struct usb_line6 *dev = line6_devices[i];703703- printk(KERN_INFO "Line6 device %d: ", i);704704-705705- if (dev == NULL)706706- printk("(not used)\n");707707- else708708- printk("%s:%d\n", dev->properties->name, dev->interface_number);709709- }710710-}711711-712640/*713641 Probe USB device.714642*/···716674 if (usbdev == NULL)717675 return -ENODEV;718676719719- /* increment reference counters: */720720- usb_get_intf(interface);721721- usb_get_dev(usbdev);722722-723677 /* we don't handle multiple configurations */724678 if (usbdev->descriptor.bNumConfigurations != 1) {725679 ret = -ENODEV;···727689 u16 idVendor = le16_to_cpu(usbdev->descriptor.idVendor);728690 u16 idProduct = le16_to_cpu(usbdev->descriptor.idProduct);729691730730- if (idVendor == line6_id_table[devtype].idVendor731731- && idProduct == line6_id_table[devtype].idProduct)692692+ if (idVendor == line6_id_table[devtype].idVendor &&693693+ idProduct == line6_id_table[devtype].idProduct)732694 break;733695 }734696···757719758720 switch (product) {759721 case LINE6_DEVID_BASSPODXTLIVE:760760- case LINE6_DEVID_POCKETPOD:761722 case LINE6_DEVID_PODXTLIVE:762723 case LINE6_DEVID_VARIAX:763724 alternate = 1;725725+ break;726726+727727+ case LINE6_DEVID_POCKETPOD:728728+ switch (interface_number) {729729+ case 0:730730+ return 0; /* this interface has no endpoints */731731+ case 1:732732+ alternate = 0;733733+ break;734734+ default:735735+ MISSING_CASE;736736+ }764737 break;765738766739 case LINE6_DEVID_PODX3:···795746 alternate = 5;796747 break;797748798798- case LINE6_DEVID_TONEPORT_GX:799749 case LINE6_DEVID_GUITARPORT:750750+ case LINE6_DEVID_PODSTUDIO_GX:751751+ case LINE6_DEVID_PODSTUDIO_UX1:752752+ case LINE6_DEVID_TONEPORT_GX:753753+ case LINE6_DEVID_TONEPORT_UX1:800754 alternate = 2; /* 1..4 seem to be ok */801755 break;802756803803- case LINE6_DEVID_TONEPORT_UX1:804757 case LINE6_DEVID_TONEPORT_UX2:758758+ case LINE6_DEVID_PODSTUDIO_UX2:805759 switch (interface_number) {806760 case 0:807761 /* defaults to 44.1kHz, 16-bit */808762 alternate = 2;809763 break;810764 case 1:811811- alternate = 0;765765+ /* don't know yet what this is ...766766+ alternate = 1;812767 break;768768+ */769769+ return -ENODEV;813770 default:814771 MISSING_CASE;815772 }···838783 case LINE6_DEVID_BASSPODXT:839784 case LINE6_DEVID_BASSPODXTLIVE:840785 case LINE6_DEVID_BASSPODXTPRO:841841- case LINE6_DEVID_POCKETPOD:842786 case LINE6_DEVID_PODXT:843787 case LINE6_DEVID_PODXTPRO:844788 size = sizeof(struct usb_line6_pod);845789 ep_read = 0x84;846790 ep_write = 0x03;791791+ break;792792+793793+ case LINE6_DEVID_POCKETPOD:794794+ size = sizeof(struct usb_line6_pod);795795+ ep_read = 0x82;796796+ ep_write = 0x02;847797 break;848798849799 case LINE6_DEVID_PODX3:···859799 ep_write = 0x01;860800 break;861801802802+ case LINE6_DEVID_PODSTUDIO_GX:803803+ case LINE6_DEVID_PODSTUDIO_UX1:804804+ case LINE6_DEVID_PODSTUDIO_UX2:862805 case LINE6_DEVID_TONEPORT_GX:863806 case LINE6_DEVID_TONEPORT_UX1:864807 case LINE6_DEVID_TONEPORT_UX2:···988925 case LINE6_DEVID_PODX3LIVE:989926 case LINE6_DEVID_PODXT:990927 case LINE6_DEVID_PODXTPRO:991991- ret = pod_init(interface, (struct usb_line6_pod *)line6);928928+ ret = line6_pod_init(interface, (struct usb_line6_pod *)line6);992929 break;993930994931 case LINE6_DEVID_PODXTLIVE:995932 switch (interface_number) {996933 case PODXTLIVE_INTERFACE_POD:997997- ret = pod_init(interface, (struct usb_line6_pod *)line6);934934+ ret = line6_pod_init(interface, (struct usb_line6_pod *)line6);998935 break;9999361000937 case PODXTLIVE_INTERFACE_VARIAX:10011001- ret = variax_init(interface, (struct usb_line6_variax *)line6);938938+ ret = line6_variax_init(interface, (struct usb_line6_variax *)line6);1002939 break;10039401004941 default:···1011948 break;10129491013950 case LINE6_DEVID_VARIAX:10141014- ret = variax_init(interface, (struct usb_line6_variax *)line6);951951+ ret = line6_variax_init(interface, (struct usb_line6_variax *)line6);1015952 break;1016953954954+ case LINE6_DEVID_PODSTUDIO_GX:955955+ case LINE6_DEVID_PODSTUDIO_UX1:956956+ case LINE6_DEVID_PODSTUDIO_UX2:1017957 case LINE6_DEVID_TONEPORT_GX:1018958 case LINE6_DEVID_TONEPORT_UX1:1019959 case LINE6_DEVID_TONEPORT_UX2:1020960 case LINE6_DEVID_GUITARPORT:10211021- ret = toneport_init(interface, (struct usb_line6_toneport *)line6);961961+ ret = line6_toneport_init(interface, (struct usb_line6_toneport *)line6);1022962 break;10239631024964 default:···1037971 if (ret < 0)1038972 goto err_destruct;1039973974974+ /* creation of additional special files should go here */975975+1040976 dev_info(&interface->dev, "Line6 %s now attached\n",1041977 line6->properties->name);1042978 line6_devices[devnum] = line6;10431043- line6_list_devices();979979+980980+ switch(product) {981981+ case LINE6_DEVID_PODX3:982982+ case LINE6_DEVID_PODX3LIVE:983983+ dev_info(&interface->dev, "NOTE: the Line6 %s is detected, but not yet supported\n",984984+ line6->properties->name);985985+ }986986+987987+ /* increment reference counters: */988988+ usb_get_intf(interface);989989+ usb_get_dev(usbdev);990990+1044991 return 0;10459921046993err_destruct:···10791000 if (usbdev == NULL)10801001 return;1081100210031003+ /* removal of additional special files should go here */10041004+10821005 sysfs_remove_link(&interface->dev.kobj, "usb_device");1083100610841007 interface_number = interface->cur_altsetting->desc.bInterfaceNumber;···1088100710891008 if (line6 != NULL) {10901009 if (line6->urb_listen != NULL)10911091- usb_kill_urb(line6->urb_listen);10101010+ line6_stop_listen(line6);1092101110931012 if (usbdev != line6->usbdev)10941013 dev_err(line6->ifcdev,···11031022 case LINE6_DEVID_PODX3LIVE:11041023 case LINE6_DEVID_PODXT:11051024 case LINE6_DEVID_PODXTPRO:11061106- pod_disconnect(interface);10251025+ line6_pod_disconnect(interface);11071026 break;1108102711091028 case LINE6_DEVID_PODXTLIVE:11101029 switch (interface_number) {11111030 case PODXTLIVE_INTERFACE_POD:11121112- pod_disconnect(interface);10311031+ line6_pod_disconnect(interface);11131032 break;1114103311151034 case PODXTLIVE_INTERFACE_VARIAX:11161116- variax_disconnect(interface);10351035+ line6_variax_disconnect(interface);11171036 break;11181037 }1119103811201039 break;1121104011221041 case LINE6_DEVID_VARIAX:11231123- variax_disconnect(interface);10421042+ line6_variax_disconnect(interface);11241043 break;1125104410451045+ case LINE6_DEVID_PODSTUDIO_GX:10461046+ case LINE6_DEVID_PODSTUDIO_UX1:10471047+ case LINE6_DEVID_PODSTUDIO_UX2:11261048 case LINE6_DEVID_TONEPORT_GX:11271049 case LINE6_DEVID_TONEPORT_UX1:11281050 case LINE6_DEVID_TONEPORT_UX2:11291051 case LINE6_DEVID_GUITARPORT:11301130- toneport_disconnect(interface);10521052+ line6_toneport_disconnect(interface);11311053 break;1132105411331055 default:···1139105511401056 dev_info(&interface->dev, "Line6 %s now disconnected\n", line6->properties->name);1141105711421142- for (i = LINE6_MAX_DEVICES; i--;) {10581058+ for (i = LINE6_MAX_DEVICES; i--;)11431059 if (line6_devices[i] == line6)11441060 line6_devices[i] = NULL;11451145- }11461061 }1147106211481063 line6_destruct(interface);···11491066 /* decrement reference counters: */11501067 usb_put_intf(interface);11511068 usb_put_dev(usbdev);11521152-11531153- line6_list_devices();11541069}10701070+10711071+#ifdef CONFIG_PM10721072+10731073+/*10741074+ Suspend Line6 device.10751075+*/10761076+static int line6_suspend(struct usb_interface *interface, pm_message_t message)10771077+{10781078+ struct usb_line6 *line6 = usb_get_intfdata(interface);10791079+ struct snd_line6_pcm *line6pcm = line6->line6pcm;10801080+10811081+ snd_power_change_state(line6->card, SNDRV_CTL_POWER_D3hot);10821082+10831083+ if (line6->properties->capabilities & LINE6_BIT_CONTROL)10841084+ line6_stop_listen(line6);10851085+10861086+ if (line6pcm != NULL) {10871087+ snd_pcm_suspend_all(line6pcm->pcm);10881088+ line6_pcm_disconnect(line6pcm);10891089+ line6pcm->flags = 0;10901090+ }10911091+10921092+ return 0;10931093+}10941094+10951095+/*10961096+ Resume Line6 device.10971097+*/10981098+static int line6_resume(struct usb_interface *interface)10991099+{11001100+ struct usb_line6 *line6 = usb_get_intfdata(interface);11011101+11021102+ if (line6->properties->capabilities & LINE6_BIT_CONTROL)11031103+ line6_start_listen(line6);11041104+11051105+ snd_power_change_state(line6->card, SNDRV_CTL_POWER_D0);11061106+ return 0;11071107+}11081108+11091109+/*11101110+ Resume Line6 device after reset.11111111+*/11121112+static int line6_reset_resume(struct usb_interface *interface)11131113+{11141114+ struct usb_line6 *line6 = usb_get_intfdata(interface);11151115+11161116+ switch (line6->usbdev->descriptor.idProduct) {11171117+ case LINE6_DEVID_PODSTUDIO_GX:11181118+ case LINE6_DEVID_PODSTUDIO_UX1:11191119+ case LINE6_DEVID_PODSTUDIO_UX2:11201120+ case LINE6_DEVID_TONEPORT_GX:11211121+ case LINE6_DEVID_TONEPORT_UX1:11221122+ case LINE6_DEVID_TONEPORT_UX2:11231123+ case LINE6_DEVID_GUITARPORT:11241124+ line6_toneport_reset_resume((struct usb_line6_toneport *)line6);11251125+ }11261126+11271127+ return line6_resume(interface);11281128+}11291129+11301130+#endif /* CONFIG_PM */1155113111561132static struct usb_driver line6_driver = {11571133 .name = DRIVER_NAME,11581134 .probe = line6_probe,11591135 .disconnect = line6_disconnect,11361136+#ifdef CONFIG_PM11371137+ .suspend = line6_suspend,11381138+ .resume = line6_resume,11391139+ .reset_resume = line6_reset_resume,11401140+#endif11601141 .id_table = line6_id_table,11611142};11621143···1233108612341087 printk(KERN_INFO "%s driver version %s%s\n",12351088 DRIVER_NAME, DRIVER_VERSION, DRIVER_REVISION);12361236- line6_workqueue = create_workqueue(DRIVER_NAME);12371237-12381238- if (line6_workqueue == NULL) {12391239- err("couldn't create workqueue");12401240- return -EINVAL;12411241- }1242108912431090 for (i = LINE6_MAX_DEVICES; i--;)12441091 line6_devices[i] = NULL;1245109212461093 retval = usb_register(&line6_driver);1247109412481248- if (retval)10951095+ if (retval) {12491096 err("usb_register failed. Error number %d", retval);10971097+ return retval;10981098+ }10991099+11001100+ line6_request_version = kmalloc(sizeof(line6_request_version0),11011101+ GFP_KERNEL);11021102+11031103+ if (line6_request_version == NULL) {11041104+ err("Out of memory");11051105+ return -ENOMEM;11061106+ }11071107+11081108+ memcpy((char *)line6_request_version, line6_request_version0,11091109+ sizeof(line6_request_version0));1250111012511111 return retval;12521112}···12631109*/12641110static void __exit line6_exit(void)12651111{12661266- destroy_workqueue(line6_workqueue);11121112+ kfree(line6_request_version);12671113 usb_deregister(&line6_driver);12681114}12691115
+45-7
drivers/staging/line6/driver.h
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···1313#define DRIVER_H141415151616-#include "config.h"1717-1816#include <linux/spinlock.h>1917#include <linux/usb.h>2020-#include <linux/wait.h>2118#include <sound/core.h>22192320#include "midi.h"24212222+2523#define DRIVER_NAME "line6usb"2424+2525+#if defined(CONFIG_LINE6_USB_DUMP_CTRL) || defined(CONFIG_LINE6_USB_DUMP_MIDI) || defined(CONFIG_LINE6_USB_DUMP_PCM)2626+#define CONFIG_LINE6_USB_DUMP_ANY2727+#endif26282729#define LINE6_TIMEOUT 12830#define LINE6_MAX_DEVICES 82931#define LINE6_BUFSIZE_LISTEN 323032#define LINE6_MESSAGE_MAXLEN 2563131-32333334/*3435 Line6 MIDI control commands···55545655#define LINE6_CHANNEL_MASK 0x0f57565757+#ifdef CONFIG_LINE6_USB_DEBUG5858+#define DEBUG_MESSAGES(x) (x)5959+#else6060+#define DEBUG_MESSAGES(x)6161+#endif6262+58635964#define MISSING_CASE \6065 printk(KERN_ERR "line6usb driver bug: missing case in %s:%d\n", \···7467 return err; \7568} while (0)76697070+#define CHECK_STARTUP_PROGRESS(x, n) \7171+ if((x) >= (n)) \7272+ return; \7373+ x = (n);7474+77757876extern const unsigned char line6_midi_id[3];7977extern struct usb_line6 *line6_devices[LINE6_MAX_DEVICES];8080-extern struct workqueue_struct *line6_workqueue;81788279static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3;8380static const int SYSEX_EXTRA_SIZE = sizeof(line6_midi_id) + 4;···9180 Common properties of Line6 devices.9281*/9382struct line6_properties {8383+ /**8484+ Card id string (maximum 16 characters).8585+ This can be used to address the device in ALSA programs as8686+ "default:CARD=<id>"8787+ */8888+ const char *id;8989+9090+ /**9191+ Card short name (maximum 32 characters).9292+ */9493 const char *name;9494+9595+ /**9696+ Bit identifying this device in the line6usb driver.9797+ */9598 int device_bit;9999+100100+ /**101101+ Bit vector defining this device's capabilities in the102102+ line6usb driver.103103+ */96104 int capabilities;97105};98106···221191 const char *buffer, int size);222192extern int line6_send_sysex_message(struct usb_line6 *line6,223193 const char *buffer, int size);194194+extern int line6_send_sysex_message_async(struct usb_line6 *line6,195195+ const char *buffer, int size);224196extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,225197 const char *buf, size_t count);198198+extern void line6_start_timer(struct timer_list *timer, unsigned int msecs,199199+ void (*function)(unsigned long), unsigned long data);226200extern int line6_transmit_parameter(struct usb_line6 *line6, int param,227201 int value);202202+extern int line6_version_request_async(struct usb_line6 *line6);228203extern int line6_write_data(struct usb_line6 *line6, int address, void *data,229204 size_t datalen);205205+206206+#ifdef CONFIG_LINE6_USB_DUMP_ANY230207extern void line6_write_hexdump(struct usb_line6 *line6, char dir,231208 const unsigned char *buffer, int size);209209+#endif232210233211234212#endif
+18-38
drivers/staging/line6/dumprequest.c
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···99 *1010 */11111212-#include "driver.h"1313-1412#include <linux/slab.h>15131414+#include "driver.h"1615#include "dumprequest.h"17161817···3839void line6_dump_finished(struct line6_dump_request *l6dr)3940{4041 l6dr->in_progress = LINE6_DUMP_NONE;4141- wake_up_interruptible(&l6dr->wait);4242+ wake_up(&l6dr->wait);4243}43444445/*4546 Send an asynchronous channel dump request.4647*/4748int line6_dump_request_async(struct line6_dump_request *l6dr,4848- struct usb_line6 *line6, int num)4949+ struct usb_line6 *line6, int num, int dest)4950{5051 int ret;5151- line6_invalidate_current(l6dr);5252+ line6_dump_started(l6dr, dest);5253 ret = line6_send_raw_message_async(line6, l6dr->reqbufs[num].buffer,5354 l6dr->reqbufs[num].length);5455···5960}60616162/*6262- Send an asynchronous dump request after a given interval.6363+ Wait for completion (interruptible).6364*/6464-void line6_startup_delayed(struct line6_dump_request *l6dr, int seconds,6565- void (*function)(unsigned long), void *data)6565+int line6_dump_wait_interruptible(struct line6_dump_request *l6dr)6666{6767- l6dr->timer.expires = jiffies + seconds * HZ;6868- l6dr->timer.function = function;6969- l6dr->timer.data = (unsigned long)data;7070- add_timer(&l6dr->timer);6767+ return wait_event_interruptible(l6dr->wait, l6dr->in_progress == LINE6_DUMP_NONE);7168}72697370/*7471 Wait for completion.7572*/7676-int line6_wait_dump(struct line6_dump_request *l6dr, int nonblock)7373+void line6_dump_wait(struct line6_dump_request *l6dr)7774{7878- int retval = 0;7979- DECLARE_WAITQUEUE(wait, current);8080- add_wait_queue(&l6dr->wait, &wait);8181- current->state = TASK_INTERRUPTIBLE;7575+ wait_event(l6dr->wait, l6dr->in_progress == LINE6_DUMP_NONE);7676+}82778383- while (l6dr->in_progress) {8484- if (nonblock) {8585- retval = -EAGAIN;8686- break;8787- }8888-8989- if (signal_pending(current)) {9090- retval = -ERESTARTSYS;9191- break;9292- } else9393- schedule();9494- }9595-9696- current->state = TASK_RUNNING;9797- remove_wait_queue(&l6dr->wait, &wait);9898- return retval;7878+/*7979+ Wait for completion (with timeout).8080+*/8181+int line6_dump_wait_timeout(struct line6_dump_request *l6dr, long timeout)8282+{8383+ return wait_event_timeout(l6dr->wait, l6dr->in_progress == LINE6_DUMP_NONE, timeout);9984}1008510186/*···106123 if (ret < 0)107124 return ret;108125 init_waitqueue_head(&l6dr->wait);109109- init_timer(&l6dr->timer);110126 return 0;111127}112128···130148 if (l6dr->reqbufs[0].buffer == NULL)131149 return;132150 line6_dumpreq_destructbuf(l6dr, 0);133133- l6dr->ok = 1;134134- del_timer_sync(&l6dr->timer);135151}
+7-17
drivers/staging/line6/dumprequest.h
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···15151616#include <linux/usb.h>1717#include <linux/wait.h>1818-1918#include <sound/core.h>20192120···5556 int in_progress;56575758 /**5858- Timer for delayed dump request.5959- */6060- struct timer_list timer;6161-6262- /**6363- Flag if initial dump request has been successful.6464- */6565- char ok;6666-6767- /**6859 Dump request buffers6960 */7061 struct line6_dump_reqbuf reqbufs[1];···62736374extern void line6_dump_finished(struct line6_dump_request *l6dr);6475extern int line6_dump_request_async(struct line6_dump_request *l6dr,6565- struct usb_line6 *line6, int num);7676+ struct usb_line6 *line6, int num, int dest);6677extern void line6_dump_started(struct line6_dump_request *l6dr, int dest);6778extern void line6_dumpreq_destruct(struct line6_dump_request *l6dr);6879extern void line6_dumpreq_destructbuf(struct line6_dump_request *l6dr, int num);···7182extern int line6_dumpreq_initbuf(struct line6_dump_request *l6dr,7283 const void *buf, size_t len, int num);7384extern void line6_invalidate_current(struct line6_dump_request *l6dr);7474-extern void line6_startup_delayed(struct line6_dump_request *l6dr, int seconds,7575- void (*function)(unsigned long), void *data);7676-extern int line6_wait_dump(struct line6_dump_request *l6dr, int nonblock);8585+extern void line6_dump_wait(struct line6_dump_request *l6dr);8686+extern int line6_dump_wait_interruptible(struct line6_dump_request *l6dr);8787+extern int line6_dump_wait_timeout(struct line6_dump_request *l6dr,8888+ long timeout);778978907991#endif
+20-36
drivers/staging/line6/midi.c
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···99 *1010 */11111212-#include "driver.h"1313-1414-#include <linux/usb.h>1512#include <linux/slab.h>1616-1313+#include <linux/usb.h>1714#include <sound/core.h>1815#include <sound/rawmidi.h>19162017#include "audio.h"1818+#include "driver.h"2119#include "midi.h"2220#include "pod.h"2321#include "usbdefs.h"2424-2525-2626-#define USE_MIDIBUF 12727-#define OUTPUT_DUMP_ONLY 0282229233024#define line6_rawmidi_substream_midi(substream) \···5561 spin_lock_irqsave(&line6->line6midi->midi_transmit_lock, flags);56625763 for (;;) {5858- req = min(midibuf_bytes_free(mb), line6->max_packet_size);6464+ req = min(line6_midibuf_bytes_free(mb), line6->max_packet_size);5965 done = snd_rawmidi_transmit_peek(substream, chunk, req);60666167 if (done == 0)6268 break;63696464-#if DO_DUMP_MIDI_SEND7070+#ifdef CONFIG_LINE6_USB_DUMP_MIDI6571 line6_write_hexdump(line6, 's', chunk, done);6672#endif6767- midibuf_write(mb, chunk, done);7373+ line6_midibuf_write(mb, chunk, done);6874 snd_rawmidi_transmit_ack(substream, done);6975 }70767177 for (;;) {7272- done = midibuf_read(mb, chunk, line6->max_packet_size);7878+ done = line6_midibuf_read(mb, chunk, line6->max_packet_size);73797480 if (done == 0)7581 break;76827777- if (midibuf_skip_message(mb, line6midi->midi_mask_transmit))8383+ if (line6_midibuf_skip_message(mb, line6midi->midi_mask_transmit))7884 continue;79858086 send_midi_async(line6, chunk, done);···109115 }110116111117 if (num == 0)112112- wake_up_interruptible(&line6->line6midi->send_wait);118118+ wake_up(&line6->line6midi->send_wait);113119114120 spin_unlock_irqrestore(&line6->line6midi->send_urb_lock, flags);115121}···133139 return -ENOMEM;134140 }135141136136-#if DO_DUMP_URB_SEND142142+#ifdef CONFIG_LINE6_USB_DUMP_CTRL137143 line6_write_hexdump(line6, 'S', data, length);138144#endif139145···170176 case LINE6_DEVID_PODXTLIVE:171177 case LINE6_DEVID_PODXTPRO:172178 case LINE6_DEVID_POCKETPOD:173173- pod_midi_postprocess((struct usb_line6_pod *)line6, data,174174- length);179179+ line6_pod_midi_postprocess((struct usb_line6_pod *)line6, data,180180+ length);175181 break;176182177183 default:···209215static void line6_midi_output_drain(struct snd_rawmidi_substream *substream)210216{211217 struct usb_line6 *line6 = line6_rawmidi_substream_midi(substream)->line6;212212- wait_queue_head_t *head = &line6->line6midi->send_wait;213213- DECLARE_WAITQUEUE(wait, current);214214- add_wait_queue(head, &wait);215215- current->state = TASK_INTERRUPTIBLE;216216-217217- while (line6->line6midi->num_active_send_urbs > 0)218218- if (signal_pending(current))219219- break;220220- else221221- schedule();222222-223223- current->state = TASK_RUNNING;224224- remove_wait_queue(head, &wait);218218+ struct snd_line6_midi *midi = line6->line6midi;219219+ wait_event_interruptible(midi->send_wait, midi->num_active_send_urbs == 0);225220}226221227222static int line6_midi_input_open(struct snd_rawmidi_substream *substream)···267284268285 rmidi->private_data = line6midi;269286 rmidi->private_free = line6_cleanup_midi;287287+ strcpy(rmidi->id, line6midi->line6->properties->id);270288 strcpy(rmidi->name, line6midi->line6->properties->name);271289272290 rmidi->info_flags =···355371 struct snd_line6_midi *line6midi = device->device_data;356372 device_remove_file(line6midi->line6->ifcdev, &dev_attr_midi_mask_transmit);357373 device_remove_file(line6midi->line6->ifcdev, &dev_attr_midi_mask_receive);358358- midibuf_destroy(&line6midi->midibuf_in);359359- midibuf_destroy(&line6midi->midibuf_out);374374+ line6_midibuf_destroy(&line6midi->midibuf_in);375375+ line6_midibuf_destroy(&line6midi->midibuf_out);360376 return 0;361377}362378···380396 if (line6midi == NULL)381397 return -ENOMEM;382398383383- err = midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0);399399+ err = line6_midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0);384400 if (err < 0)385401 return err;386402387387- err = midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1);403403+ err = line6_midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1);388404 if (err < 0)389405 return err;390406
+2-2
drivers/staging/line6/midi.h
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as
+41-43
drivers/staging/line6/midibuf.c
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as88 * published by the Free Software Foundation, version 2.99 *1010 */1111-1212-#include "config.h"13111412#include <linux/slab.h>1513···2325 return length[(code >> 4) - 8];2426 } else {2527 /*2626- Note that according to the MIDI specification 0xf2 is2727- the "Song Position Pointer", but this is used by Line62828- to send sysex messages to the host.2828+ Note that according to the MIDI specification 0xf2 is2929+ the "Song Position Pointer", but this is used by Line63030+ to send sysex messages to the host.2931 */3032 static const int length[] = { -1, 2, -1, 2, -1, -1, 1, 1, 1, 1,3133 1, 1, 1, -1, 1, 1 };3234 return length[code & 0x0f];3335 }3434-}3535-3636-void midibuf_reset(struct MidiBuffer *this)3737-{3838- this->pos_read = this->pos_write = this->full = 0;3939- this->command_prev = -1;4040-}4141-4242-int midibuf_init(struct MidiBuffer *this, int size, int split)4343-{4444- this->buf = kmalloc(size, GFP_KERNEL);4545-4646- if (this->buf == NULL)4747- return -ENOMEM;4848-4949- this->size = size;5050- this->split = split;5151- midibuf_reset(this);5252- return 0;5353-}5454-5555-void midibuf_status(struct MidiBuffer *this)5656-{5757- printk(KERN_DEBUG "midibuf size=%d split=%d pos_read=%d pos_write=%d "5858- "full=%d command_prev=%02x\n", this->size, this->split,5959- this->pos_read, this->pos_write, this->full, this->command_prev);6036}61376238static int midibuf_is_empty(struct MidiBuffer *this)···4371 return this->full;4472}45734646-int midibuf_bytes_free(struct MidiBuffer *this)7474+void line6_midibuf_reset(struct MidiBuffer *this)7575+{7676+ this->pos_read = this->pos_write = this->full = 0;7777+ this->command_prev = -1;7878+}7979+8080+int line6_midibuf_init(struct MidiBuffer *this, int size, int split)8181+{8282+ this->buf = kmalloc(size, GFP_KERNEL);8383+8484+ if (this->buf == NULL)8585+ return -ENOMEM;8686+8787+ this->size = size;8888+ this->split = split;8989+ line6_midibuf_reset(this);9090+ return 0;9191+}9292+9393+void line6_midibuf_status(struct MidiBuffer *this)9494+{9595+ printk(KERN_DEBUG "midibuf size=%d split=%d pos_read=%d pos_write=%d "9696+ "full=%d command_prev=%02x\n", this->size, this->split,9797+ this->pos_read, this->pos_write, this->full, this->command_prev);9898+}9999+100100+int line6_midibuf_bytes_free(struct MidiBuffer *this)47101{48102 return49103 midibuf_is_full(this) ?···7779 (this->pos_read - this->pos_write + this->size - 1) % this->size + 1;7880}79818080-int midibuf_bytes_used(struct MidiBuffer *this)8282+int line6_midibuf_bytes_used(struct MidiBuffer *this)8183{8284 return8385 midibuf_is_empty(this) ?···8587 (this->pos_write - this->pos_read + this->size - 1) % this->size + 1;8688}87898888-int midibuf_write(struct MidiBuffer *this, unsigned char *data, int length)9090+int line6_midibuf_write(struct MidiBuffer *this, unsigned char *data, int length)8991{9092 int bytes_free;9193 int length1, length2;···100102 skip_active_sense = 1;101103 }102104103103- bytes_free = midibuf_bytes_free(this);105105+ bytes_free = line6_midibuf_bytes_free(this);104106105107 if (length > bytes_free)106108 length = bytes_free;···127129 return length + skip_active_sense;128130}129131130130-int midibuf_read(struct MidiBuffer *this, unsigned char *data, int length)132132+int line6_midibuf_read(struct MidiBuffer *this, unsigned char *data, int length)131133{132134 int bytes_used;133135 int length1, length2;···143145 if (midibuf_is_empty(this))144146 return 0;145147146146- bytes_used = midibuf_bytes_used(this);148148+ bytes_used = line6_midibuf_bytes_used(this);147149148150 if (length > bytes_used)149151 length = bytes_used;···230232 return length + repeat;231233}232234233233-int midibuf_ignore(struct MidiBuffer *this, int length)235235+int line6_midibuf_ignore(struct MidiBuffer *this, int length)234236{235235- int bytes_used = midibuf_bytes_used(this);237237+ int bytes_used = line6_midibuf_bytes_used(this);236238237239 if (length > bytes_used)238240 length = bytes_used;···242244 return length;243245}244246245245-int midibuf_skip_message(struct MidiBuffer *this, unsigned short mask)247247+int line6_midibuf_skip_message(struct MidiBuffer *this, unsigned short mask)246248{247249 int cmd = this->command_prev;248250···253255 return 0;254256}255257256256-void midibuf_destroy(struct MidiBuffer *this)258258+void line6_midibuf_destroy(struct MidiBuffer *this)257259{258260 kfree(this->buf);259261 this->buf = NULL;
+13-13
drivers/staging/line6/midibuf.h
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···2323};242425252626-extern int midibuf_bytes_used(struct MidiBuffer *mb);2727-extern int midibuf_bytes_free(struct MidiBuffer *mb);2828-extern void midibuf_destroy(struct MidiBuffer *mb);2929-extern int midibuf_ignore(struct MidiBuffer *mb, int length);3030-extern int midibuf_init(struct MidiBuffer *mb, int size, int split);3131-extern int midibuf_read(struct MidiBuffer *mb, unsigned char *data, int length);3232-extern void midibuf_reset(struct MidiBuffer *mb);3333-extern int midibuf_skip_message(struct MidiBuffer *mb, unsigned short mask);3434-extern void midibuf_status(struct MidiBuffer *mb);3535-extern int midibuf_write(struct MidiBuffer *mb, unsigned char *data,3636- int length);2626+extern int line6_midibuf_bytes_used(struct MidiBuffer *mb);2727+extern int line6_midibuf_bytes_free(struct MidiBuffer *mb);2828+extern void line6_midibuf_destroy(struct MidiBuffer *mb);2929+extern int line6_midibuf_ignore(struct MidiBuffer *mb, int length);3030+extern int line6_midibuf_init(struct MidiBuffer *mb, int size, int split);3131+extern int line6_midibuf_read(struct MidiBuffer *mb, unsigned char *data, int length);3232+extern void line6_midibuf_reset(struct MidiBuffer *mb);3333+extern int line6_midibuf_skip_message(struct MidiBuffer *mb, unsigned short mask);3434+extern void line6_midibuf_status(struct MidiBuffer *mb);3535+extern int line6_midibuf_write(struct MidiBuffer *mb, unsigned char *data,3636+ int length);373738383939#endif
+241-35
drivers/staging/line6/pcm.c
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···99 *1010 */11111212-#include "driver.h"1313-1412#include <linux/slab.h>1515-1613#include <sound/core.h>1714#include <sound/control.h>1815#include <sound/pcm.h>···17201821#include "audio.h"1922#include "capture.h"2323+#include "driver.h"2024#include "playback.h"2125#include "pod.h"22262727+2828+#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE2929+3030+static struct snd_line6_pcm* dev2pcm(struct device *dev)3131+{3232+ struct usb_interface *interface = to_usb_interface(dev);3333+ struct usb_line6 *line6 = usb_get_intfdata(interface);3434+ struct snd_line6_pcm *line6pcm = line6->line6pcm;3535+ return line6pcm;3636+}3737+3838+/*3939+ "read" request on "impulse_volume" special file.4040+*/4141+static ssize_t pcm_get_impulse_volume(struct device *dev,4242+ struct device_attribute *attr,4343+ char *buf)4444+{4545+ return sprintf(buf, "%d\n", dev2pcm(dev)->impulse_volume);4646+}4747+4848+/*4949+ "write" request on "impulse_volume" special file.5050+*/5151+static ssize_t pcm_set_impulse_volume(struct device *dev,5252+ struct device_attribute *attr,5353+ const char *buf, size_t count)5454+{5555+ struct snd_line6_pcm *line6pcm = dev2pcm(dev);5656+ int value = simple_strtoul(buf, NULL, 10);5757+ line6pcm->impulse_volume = value;5858+5959+ if(value > 0)6060+ line6_pcm_start(line6pcm, MASK_PCM_IMPULSE);6161+ else6262+ line6_pcm_stop(line6pcm, MASK_PCM_IMPULSE);6363+6464+ return count;6565+}6666+6767+/*6868+ "read" request on "impulse_period" special file.6969+*/7070+static ssize_t pcm_get_impulse_period(struct device *dev,7171+ struct device_attribute *attr,7272+ char *buf)7373+{7474+ return sprintf(buf, "%d\n", dev2pcm(dev)->impulse_period);7575+}7676+7777+/*7878+ "write" request on "impulse_period" special file.7979+*/8080+static ssize_t pcm_set_impulse_period(struct device *dev,8181+ struct device_attribute *attr,8282+ const char *buf, size_t count)8383+{8484+ dev2pcm(dev)->impulse_period = simple_strtoul(buf, NULL, 10);8585+ return count;8686+}8787+8888+static DEVICE_ATTR(impulse_volume, S_IWUGO | S_IRUGO, pcm_get_impulse_volume, pcm_set_impulse_volume);8989+static DEVICE_ATTR(impulse_period, S_IWUGO | S_IRUGO, pcm_get_impulse_period, pcm_set_impulse_period);9090+9191+#endif9292+9393+int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels)9494+{9595+ unsigned long flags_old = __sync_fetch_and_or(&line6pcm->flags, channels);9696+ unsigned long flags_new = flags_old | channels;9797+ int err = 0;9898+9999+#if LINE6_BACKUP_MONITOR_SIGNAL100100+ if (!(line6pcm->line6->properties->capabilities & LINE6_BIT_HWMON)) {101101+ line6pcm->prev_fbuf = kmalloc(LINE6_ISO_PACKETS * line6pcm->max_packet_size, GFP_KERNEL);102102+103103+ if (!line6pcm->prev_fbuf) {104104+ dev_err(line6pcm->line6->ifcdev, "cannot malloc monitor buffer\n");105105+ return -ENOMEM;106106+ }107107+ }108108+#else109109+ line6pcm->prev_fbuf = NULL;110110+#endif111111+112112+ if (((flags_old & MASK_CAPTURE) == 0) &&113113+ ((flags_new & MASK_CAPTURE) != 0)) {114114+ /*115115+ Waiting for completion of active URBs in the stop handler is116116+ a bug, we therefore report an error if capturing is restarted117117+ too soon.118118+ */119119+ if(line6pcm->active_urb_in | line6pcm->unlink_urb_in)120120+ return -EBUSY;121121+122122+ line6pcm->buffer_in = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * line6pcm->max_packet_size, GFP_KERNEL);123123+124124+ if (!line6pcm->buffer_in) {125125+ dev_err(line6pcm->line6->ifcdev, "cannot malloc capture buffer\n");126126+ return -ENOMEM;127127+ }128128+129129+ line6pcm->count_in = 0;130130+ line6pcm->prev_fsize = 0;131131+ err = line6_submit_audio_in_all_urbs(line6pcm);132132+133133+ if (err < 0) {134134+ __sync_fetch_and_and(&line6pcm->flags, ~channels);135135+ return err;136136+ }137137+ }138138+139139+ if (((flags_old & MASK_PLAYBACK) == 0) &&140140+ ((flags_new & MASK_PLAYBACK) != 0)) {141141+ /*142142+ See comment above regarding PCM restart.143143+ */144144+ if(line6pcm->active_urb_out | line6pcm->unlink_urb_out)145145+ return -EBUSY;146146+147147+ line6pcm->buffer_out = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS * line6pcm->max_packet_size, GFP_KERNEL);148148+149149+ if (!line6pcm->buffer_out) {150150+ dev_err(line6pcm->line6->ifcdev, "cannot malloc playback buffer\n");151151+ return -ENOMEM;152152+ }153153+154154+ line6pcm->count_out = 0;155155+ err = line6_submit_audio_out_all_urbs(line6pcm);156156+157157+ if (err < 0) {158158+ __sync_fetch_and_and(&line6pcm->flags, ~channels);159159+ return err;160160+ }161161+ }162162+163163+ return 0;164164+}165165+166166+int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels)167167+{168168+ unsigned long flags_old = __sync_fetch_and_and(&line6pcm->flags, ~channels);169169+ unsigned long flags_new = flags_old & ~channels;170170+171171+ if (((flags_old & MASK_CAPTURE) != 0) &&172172+ ((flags_new & MASK_CAPTURE) == 0)) {173173+ line6_unlink_audio_in_urbs(line6pcm);174174+ kfree(line6pcm->buffer_in);175175+ line6pcm->buffer_in = NULL;176176+ }177177+178178+ if (((flags_old & MASK_PLAYBACK) != 0) &&179179+ ((flags_new & MASK_PLAYBACK) == 0)) {180180+ line6_unlink_audio_out_urbs(line6pcm);181181+ kfree(line6pcm->buffer_out);182182+ line6pcm->buffer_out = NULL;183183+ }184184+185185+#if LINE6_BACKUP_MONITOR_SIGNAL186186+ if (line6pcm->prev_fbuf != NULL)187187+ kfree(line6pcm->prev_fbuf);188188+#endif189189+190190+ return 0;191191+}2319224193/* trigger callback */25194int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)···20138 snd_pcm_group_for_each_entry(s, substream) {20239 switch (s->stream) {20340 case SNDRV_PCM_STREAM_PLAYBACK:204204- err = snd_line6_playback_trigger(s, cmd);4141+ err = snd_line6_playback_trigger(line6pcm, cmd);2054220643 if (err < 0) {20744 spin_unlock_irqrestore(&line6pcm->lock_trigger,···21249 break;2135021451 case SNDRV_PCM_STREAM_CAPTURE:215215- err = snd_line6_capture_trigger(s, cmd);5252+ err = snd_line6_capture_trigger(line6pcm, cmd);2165321754 if (err < 0) {21855 spin_unlock_irqrestore(&line6pcm->lock_trigger,···22360 break;2246122562 default:226226- dev_err(s2m(substream), "Unknown stream direction %d\n",6363+ dev_err(line6pcm->line6->ifcdev, "Unknown stream direction %d\n",22764 s->stream);22865 }22966 }···23370}2347123572/* control info callback */236236-static int snd_line6_control_info(struct snd_kcontrol *kcontrol,237237- struct snd_ctl_elem_info *uinfo)7373+static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol,7474+ struct snd_ctl_elem_info *uinfo)23875{23976 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;24077 uinfo->count = 2;···24481}2458224683/* control get callback */247247-static int snd_line6_control_get(struct snd_kcontrol *kcontrol,248248- struct snd_ctl_elem_value *ucontrol)8484+static int snd_line6_control_playback_get(struct snd_kcontrol *kcontrol,8585+ struct snd_ctl_elem_value *ucontrol)24986{25087 int i;25188 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);2528925390 for (i = 2; i--;)254254- ucontrol->value.integer.value[i] = line6pcm->volume[i];9191+ ucontrol->value.integer.value[i] = line6pcm->volume_playback[i];2559225693 return 0;25794}2589525996/* control put callback */260260-static int snd_line6_control_put(struct snd_kcontrol *kcontrol,261261- struct snd_ctl_elem_value *ucontrol)9797+static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol,9898+ struct snd_ctl_elem_value *ucontrol)26299{263100 int i, changed = 0;264101 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);265102266103 for (i = 2; i--;)267267- if (line6pcm->volume[i] != ucontrol->value.integer.value[i]) {268268- line6pcm->volume[i] = ucontrol->value.integer.value[i];104104+ if (line6pcm->volume_playback[i] != ucontrol->value.integer.value[i]) {105105+ line6pcm->volume_playback[i] = ucontrol->value.integer.value[i];269106 changed = 1;270107 }271108···273110}274111275112/* control definition */276276-static struct snd_kcontrol_new line6_control = {113113+static struct snd_kcontrol_new line6_control_playback = {277114 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,278115 .name = "PCM Playback Volume",279116 .index = 0,280117 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,281281- .info = snd_line6_control_info,282282- .get = snd_line6_control_get,283283- .put = snd_line6_control_put118118+ .info = snd_line6_control_playback_info,119119+ .get = snd_line6_control_playback_get,120120+ .put = snd_line6_control_playback_put284121};285122286123/*···290127{291128 int i;292129 struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);130130+131131+#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE132132+ device_remove_file(line6pcm->line6->ifcdev, &dev_attr_impulse_volume);133133+ device_remove_file(line6pcm->line6->ifcdev, &dev_attr_impulse_period);134134+#endif293135294136 for (i = LINE6_ISO_BUFFERS; i--;) {295137 if (line6pcm->urb_audio_out[i]) {···328160 /* set operators */329161 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,330162 &snd_line6_playback_ops);331331- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops);163163+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,164164+ &snd_line6_capture_ops);332165333166 /* pre-allocation of buffers */334167 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,···343174static int snd_line6_pcm_free(struct snd_device *device)344175{345176 return 0;177177+}178178+179179+/*180180+ Stop substream if still running.181181+*/182182+static void pcm_disconnect_substream(struct snd_pcm_substream *substream)183183+{184184+ if(substream->runtime && snd_pcm_running(substream)) {185185+ snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);186186+ }187187+}188188+189189+/*190190+ Stop PCM stream.191191+*/192192+void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)193193+{194194+ pcm_disconnect_substream(get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE));195195+ pcm_disconnect_substream(get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK));196196+ line6_unlink_wait_clear_audio_out_urbs(line6pcm);197197+ line6_unlink_wait_clear_audio_in_urbs(line6pcm);346198}347199348200/*···408218 break;409219410220 case LINE6_DEVID_GUITARPORT:221221+ case LINE6_DEVID_PODSTUDIO_GX:222222+ case LINE6_DEVID_PODSTUDIO_UX1:223223+ case LINE6_DEVID_PODSTUDIO_UX2:411224 case LINE6_DEVID_TONEPORT_GX:225225+ case LINE6_DEVID_TONEPORT_UX1:226226+ case LINE6_DEVID_TONEPORT_UX2:412227 ep_read = 0x82;413228 ep_write = 0x01;414229 break;415230416416- case LINE6_DEVID_TONEPORT_UX1:417417- ep_read = 0x00;418418- ep_write = 0x00;419419- break;420420-231231+ /* this is for interface_number == 1:421232 case LINE6_DEVID_TONEPORT_UX2:233233+ case LINE6_DEVID_PODSTUDIO_UX2:422234 ep_read = 0x87;423235 ep_write = 0x00;424236 break;237237+ */425238426239 default:427240 MISSING_CASE;···435242 if (line6pcm == NULL)436243 return -ENOMEM;437244438438- line6pcm->volume[0] = line6pcm->volume[1] = 128;245245+ line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255;246246+ line6pcm->volume_monitor = 255;439247 line6pcm->line6 = line6;440248 line6pcm->ep_audio_read = ep_read;441249 line6pcm->ep_audio_write = ep_write;442250 line6pcm->max_packet_size = usb_maxpacket(line6->usbdev,443443- usb_rcvintpipe(line6->usbdev,251251+ usb_rcvintpipe(line6->usbdev,444252 ep_read),445253 0);446254 line6pcm->properties = properties;···462268 spin_lock_init(&line6pcm->lock_audio_in);463269 spin_lock_init(&line6pcm->lock_trigger);464270465465- err = create_audio_out_urbs(line6pcm);271271+ err = line6_create_audio_out_urbs(line6pcm);466272 if (err < 0)467273 return err;468274469469- err = create_audio_in_urbs(line6pcm);275275+ err = line6_create_audio_in_urbs(line6pcm);470276 if (err < 0)471277 return err;472278473279 /* mixer: */474474- err = snd_ctl_add(line6->card, snd_ctl_new1(&line6_control, line6pcm));280280+ err = snd_ctl_add(line6->card, snd_ctl_new1(&line6_control_playback, line6pcm));475281 if (err < 0)476282 return err;283283+284284+#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE285285+ /* impulse response test: */286286+ err = device_create_file(line6->ifcdev, &dev_attr_impulse_volume);287287+ if (err < 0)288288+ return err;289289+290290+ err = device_create_file(line6->ifcdev, &dev_attr_impulse_period);291291+ if (err < 0)292292+ return err;293293+294294+ line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;295295+#endif477296478297 return 0;479298}···497290 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);498291499292 if (!test_and_set_bit(BIT_PREPARED, &line6pcm->flags)) {500500- unlink_wait_clear_audio_out_urbs(line6pcm);293293+ line6pcm->count_out = 0;501294 line6pcm->pos_out = 0;502295 line6pcm->pos_out_done = 0;503503-504504- unlink_wait_clear_audio_in_urbs(line6pcm);505296 line6pcm->bytes_out = 0;297297+ line6pcm->count_in = 0;506298 line6pcm->pos_in_done = 0;507299 line6pcm->bytes_in = 0;508300 }
+119-16
drivers/staging/line6/pcm.h
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···242425252626/* number of URBs */2727-#define LINE6_ISO_BUFFERS 82727+#define LINE6_ISO_BUFFERS 228282929-/* number of USB frames per URB */3030-#define LINE6_ISO_PACKETS 22929+/*3030+ number of USB frames per URB3131+ The Line6 Windows driver always transmits two frames per packet, but3232+ the Linux driver performs significantly better (i.e., lower latency)3333+ with only one frame per packet.3434+*/3535+#define LINE6_ISO_PACKETS 131363237/* in a "full speed" device (such as the PODxt Pro) this means 1ms */3338#define LINE6_ISO_INTERVAL 134393535-/* this should be queried dynamically from the USB interface! */3636-#define LINE6_ISO_PACKET_SIZE_MAX 2524040+#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE4141+#define LINE6_IMPULSE_DEFAULT_PERIOD 1004242+#endif4343+4444+#define LINE6_BACKUP_MONITOR_SIGNAL 04545+#define LINE6_REUSE_DMA_AREA_FOR_PLAYBACK 0374638473948/*4040- Extract the messaging device from the substream instance4949+ Get substream from Line6 PCM data structure4150*/4242-#define s2m(s) (((struct snd_line6_pcm *) \4343- snd_pcm_substream_chip(s))->line6->ifcdev)5151+#define get_substream(line6pcm, stream) (line6pcm->pcm->streams[stream].substream)445245535454+/*5555+ PCM mode bits and masks.5656+ "ALSA": operations triggered by applications via ALSA5757+ "MONITOR": software monitoring5858+ "IMPULSE": optional impulse response operation5959+*/4660enum {4747- BIT_RUNNING_PLAYBACK,4848- BIT_RUNNING_CAPTURE,6161+ /* individual bits: */6262+ BIT_PCM_ALSA_PLAYBACK,6363+ BIT_PCM_ALSA_CAPTURE,6464+ BIT_PCM_MONITOR_PLAYBACK,6565+ BIT_PCM_MONITOR_CAPTURE,6666+#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE6767+ BIT_PCM_IMPULSE_PLAYBACK,6868+ BIT_PCM_IMPULSE_CAPTURE,6969+#endif4970 BIT_PAUSE_PLAYBACK,5050- BIT_PREPARED7171+ BIT_PREPARED,7272+7373+ /* individual masks: */7474+ MASK_PCM_ALSA_PLAYBACK = 1 << BIT_PCM_ALSA_PLAYBACK,7575+ MASK_PCM_ALSA_CAPTURE = 1 << BIT_PCM_ALSA_CAPTURE,7676+ MASK_PCM_MONITOR_PLAYBACK = 1 << BIT_PCM_MONITOR_PLAYBACK,7777+ MASK_PCM_MONITOR_CAPTURE = 1 << BIT_PCM_MONITOR_CAPTURE,7878+#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE7979+ MASK_PCM_IMPULSE_PLAYBACK = 1 << BIT_PCM_IMPULSE_PLAYBACK,8080+ MASK_PCM_IMPULSE_CAPTURE = 1 << BIT_PCM_IMPULSE_CAPTURE,8181+#endif8282+ MASK_PAUSE_PLAYBACK = 1 << BIT_PAUSE_PLAYBACK,8383+ MASK_PREPARED = 1 << BIT_PREPARED,8484+8585+ /* combined masks (by operation): */8686+ MASK_PCM_ALSA = MASK_PCM_ALSA_PLAYBACK | MASK_PCM_ALSA_CAPTURE,8787+ MASK_PCM_MONITOR = MASK_PCM_MONITOR_PLAYBACK | MASK_PCM_MONITOR_CAPTURE,8888+#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE8989+ MASK_PCM_IMPULSE = MASK_PCM_IMPULSE_PLAYBACK | MASK_PCM_IMPULSE_CAPTURE,9090+#endif9191+9292+ /* combined masks (by direction): */9393+#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE9494+ MASK_PLAYBACK = MASK_PCM_ALSA_PLAYBACK | MASK_PCM_MONITOR_PLAYBACK | MASK_PCM_IMPULSE_PLAYBACK,9595+ MASK_CAPTURE = MASK_PCM_ALSA_CAPTURE | MASK_PCM_MONITOR_CAPTURE | MASK_PCM_IMPULSE_CAPTURE9696+#else9797+ MASK_PLAYBACK = MASK_PCM_ALSA_PLAYBACK | MASK_PCM_MONITOR_PLAYBACK,9898+ MASK_CAPTURE = MASK_PCM_ALSA_CAPTURE | MASK_PCM_MONITOR_CAPTURE9999+#endif51100};5210153102struct line6_pcm_properties {···13283 struct urb *urb_audio_in[LINE6_ISO_BUFFERS];1338413485 /**135135- Temporary buffer to hold data when playback buffer wraps.8686+ Temporary buffer for playback.8787+ Since the packet size is not known in advance, this buffer is8888+ large enough to store maximum size packets.13689 */137137- unsigned char *wrap_out;9090+ unsigned char *buffer_out;1389113992 /**14093 Temporary buffer for capture.···14493 large enough to store maximum size packets.14594 */14695 unsigned char *buffer_in;9696+9797+ /**9898+ Temporary buffer index for playback.9999+ */100100+ int index_out;101101+102102+ /**103103+ Previously captured frame (for software monitoring).104104+ */105105+ unsigned char *prev_fbuf;106106+107107+ /**108108+ Size of previously captured frame (for software monitoring).109109+ */110110+ int prev_fsize;147111148112 /**149113 Free frame position in the playback buffer.···270204 /**271205 PCM playback volume (left and right).272206 */273273- int volume[2];207207+ int volume_playback[2];208208+209209+ /**210210+ PCM monitor volume.211211+ */212212+ int volume_monitor;213213+214214+#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE215215+ /**216216+ Volume of impulse response test signal (if zero, test is disabled).217217+ */218218+ int impulse_volume;219219+220220+ /**221221+ Period of impulse response test signal.222222+ */223223+ int impulse_period;224224+225225+ /**226226+ Counter for impulse response test signal.227227+ */228228+ int impulse_count;229229+#endif274230275231 /**276232 Several status bits (see BIT_*).277233 */278234 unsigned long flags;235235+236236+ int last_frame_in, last_frame_out;279237};280238281239···307217 struct line6_pcm_properties *properties);308218extern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd);309219extern int snd_line6_prepare(struct snd_pcm_substream *substream);220220+extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm);221221+extern int line6_pcm_start(struct snd_line6_pcm *line6pcm, int channels);222222+extern int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels);223223+224224+225225+#define PRINT_FRAME_DIFF(op) { \226226+ static int diff_prev = 1000; \227227+ int diff = line6pcm->last_frame_out - line6pcm->last_frame_in; \228228+ if((diff != diff_prev) && (abs(diff) < 100)) { \229229+ printk("%s frame diff = %d\n", op, diff); \230230+ diff_prev = diff; \231231+ } \232232+ }310233311234312235#endif
+206-96
drivers/staging/line6/playback.c
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···99 *1010 */11111212-#include "driver.h"1313-1414-#include <linux/slab.h>1515-1612#include <sound/core.h>1713#include <sound/pcm.h>1814#include <sound/pcm_params.h>19152016#include "audio.h"1717+#include "capture.h"1818+#include "driver.h"2119#include "pcm.h"2220#include "pod.h"2321#include "playback.h"···5759 }5860}59616262+#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE6363+6464+/*6565+ Create signal for impulse response test.6666+*/6767+static void create_impulse_test_signal(struct snd_line6_pcm *line6pcm,6868+ struct urb *urb_out, int bytes_per_frame)6969+{7070+ int frames = urb_out->transfer_buffer_length / bytes_per_frame;7171+7272+ if (bytes_per_frame == 4) {7373+ /* TODO: add code for TonePort etc. */7474+ } else if (bytes_per_frame == 6) {7575+ int i, j;7676+ unsigned char *pi = line6pcm->prev_fbuf;7777+ unsigned char *po = urb_out->transfer_buffer;7878+7979+ for (i = 0; i < frames; ++i) {8080+ for (j = 0; j < bytes_per_frame / 2; ++j)8181+ po[j] = pi[j];8282+8383+ for (; j < bytes_per_frame; ++j)8484+ po[j] = 0;8585+8686+ pi += bytes_per_frame;8787+ po += bytes_per_frame;8888+ }8989+9090+ if (--line6pcm->impulse_count <= 0) {9191+ ((unsigned char *)(urb_out->9292+ transfer_buffer))[bytes_per_frame -9393+ 1] =9494+ line6pcm->impulse_volume;9595+ line6pcm->impulse_count = line6pcm->impulse_period;9696+ }9797+ }9898+}9999+100100+#endif101101+102102+/*103103+ Add signal to buffer for software monitoring.104104+*/105105+static void add_monitor_signal(struct urb *urb_out, unsigned char *signal,106106+ int volume, int bytes_per_frame)107107+{108108+ if (volume == 0)109109+ return; /* zero volume - no change */110110+111111+ if (bytes_per_frame == 4) {112112+ short *pi, *po, *buf_end;113113+ pi = (short *)signal;114114+ po = (short *)urb_out->transfer_buffer;115115+ buf_end = po + urb_out->transfer_buffer_length / sizeof(*po);116116+117117+ for (; po < buf_end; ++pi, ++po)118118+ *po += (*pi * volume) >> 8;119119+ }120120+121121+ /*122122+ We don't need to handle devices with 6 bytes per frame here123123+ since they all support hardware monitoring.124124+ */125125+}126126+60127/*61128 Find a free URB, prepare audio data, and submit URB.62129*/6363-static int submit_audio_out_urb(struct snd_pcm_substream *substream)130130+static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)64131{65132 int index;66133 unsigned long flags;67134 int i, urb_size, urb_frames;6868- struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);69135 const int bytes_per_frame = line6pcm->properties->bytes_per_frame;70136 const int frame_increment =71137 line6pcm->properties->snd_line6_rates.rats[0].num_min;72138 const int frame_factor =73139 line6pcm->properties->snd_line6_rates.rats[0].den *74140 (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL);7575- struct snd_pcm_runtime *runtime = substream->runtime;76141 struct urb *urb_out;7714278143 spin_lock_irqsave(&line6pcm->lock_audio_out, flags);···1448314584 if (index < 0 || index >= LINE6_ISO_BUFFERS) {14685 spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);147147- dev_err(s2m(substream), "no free URB found\n");8686+ dev_err(line6pcm->line6->ifcdev, "no free URB found\n");14887 return -EINVAL;14988 }15089···1539215493 for (i = 0; i < LINE6_ISO_PACKETS; ++i) {15594 /* compute frame size for given sampling rate */156156- int n, fs;9595+ int fsize = 0;15796 struct usb_iso_packet_descriptor *fout =15897 &urb_out->iso_frame_desc[i];159159- line6pcm->count_out += frame_increment;160160- n = line6pcm->count_out / frame_factor;161161- line6pcm->count_out -= n * frame_factor;162162- fs = n * bytes_per_frame;9898+9999+ if (line6pcm->flags & MASK_CAPTURE) {100100+ fsize = line6pcm->prev_fsize;101101+ }102102+103103+ if (fsize == 0) {104104+ int n;105105+ line6pcm->count_out += frame_increment;106106+ n = line6pcm->count_out / frame_factor;107107+ line6pcm->count_out -= n * frame_factor;108108+ fsize = n * bytes_per_frame;109109+ }110110+163111 fout->offset = urb_size;164164- fout->length = fs;165165- urb_size += fs;112112+ fout->length = fsize;113113+ urb_size += fsize;114114+ }115115+116116+ if (urb_size == 0) {117117+ /* can't determine URB size */118118+ spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);119119+ dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n"); /* this is somewhat paranoid */120120+ return -EINVAL;166121 }167122168123 urb_frames = urb_size / bytes_per_frame;124124+ urb_out->transfer_buffer =125125+ line6pcm->buffer_out +126126+ line6pcm->max_packet_size * line6pcm->index_out;127127+ urb_out->transfer_buffer_length = urb_size;128128+ urb_out->context = line6pcm;169129170170- if (test_bit(BIT_PAUSE_PLAYBACK, &line6pcm->flags)) {171171- urb_out->transfer_buffer = line6pcm->wrap_out;172172- memset(line6pcm->wrap_out, 0, urb_size);173173- } else {130130+ if (++line6pcm->index_out == LINE6_ISO_BUFFERS)131131+ line6pcm->index_out = 0;132132+133133+ if (test_bit(BIT_PCM_ALSA_PLAYBACK, &line6pcm->flags) &&134134+ !test_bit(BIT_PAUSE_PLAYBACK, &line6pcm->flags)) {135135+ struct snd_pcm_runtime *runtime =136136+ get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime;137137+174138 if (line6pcm->pos_out + urb_frames > runtime->buffer_size) {175139 /*176140 The transferred area goes over buffer boundary,···203117 */204118 int len;205119 len = runtime->buffer_size - line6pcm->pos_out;206206- urb_out->transfer_buffer = line6pcm->wrap_out;207120208121 if (len > 0) {209209- memcpy(line6pcm->wrap_out,122122+ memcpy(urb_out->transfer_buffer,210123 runtime->dma_area +211124 line6pcm->pos_out * bytes_per_frame,212125 len * bytes_per_frame);213213- memcpy(line6pcm->wrap_out +126126+ memcpy(urb_out->transfer_buffer +214127 len * bytes_per_frame, runtime->dma_area,215128 (urb_frames - len) * bytes_per_frame);216216- } else {217217- /* this is somewhat paranoid */218218- dev_err(s2m(substream),219219- "driver bug: len = %d\n", len);220220- }129129+ } else130130+ dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n", len); /* this is somewhat paranoid */221131 } else {132132+#if LINE6_REUSE_DMA_AREA_FOR_PLAYBACK222133 /* set the buffer pointer */223134 urb_out->transfer_buffer =224135 runtime->dma_area +225136 line6pcm->pos_out * bytes_per_frame;137137+#else138138+ /* copy data */139139+ memcpy(urb_out->transfer_buffer,140140+ runtime->dma_area +141141+ line6pcm->pos_out * bytes_per_frame,142142+ urb_out->transfer_buffer_length);143143+#endif226144 }145145+146146+ if ((line6pcm->pos_out += urb_frames) >= runtime->buffer_size)147147+ line6pcm->pos_out -= runtime->buffer_size;148148+ } else {149149+ memset(urb_out->transfer_buffer, 0,150150+ urb_out->transfer_buffer_length);227151 }228152229229- line6pcm->pos_out += urb_frames;230230- if (line6pcm->pos_out >= runtime->buffer_size)231231- line6pcm->pos_out -= runtime->buffer_size;153153+ change_volume(urb_out, line6pcm->volume_playback, bytes_per_frame);232154233233- urb_out->transfer_buffer_length = urb_size;234234- urb_out->context = substream;235235- change_volume(urb_out, line6pcm->volume, bytes_per_frame);236236-237237-#if DO_DUMP_PCM_SEND155155+ if (line6pcm->prev_fbuf != 0) {156156+#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE157157+ if (line6pcm->flags & MASK_PCM_IMPULSE) {158158+ create_impulse_test_signal(line6pcm, urb_out,159159+ bytes_per_frame);160160+ if (line6pcm->flags & MASK_PCM_ALSA_CAPTURE) {161161+ line6_capture_copy(line6pcm, urb_out->transfer_buffer,162162+ urb_out->transfer_buffer_length);163163+ }164164+ } else {165165+#endif166166+ if (!167167+ (line6pcm->line6->properties->168168+ capabilities & LINE6_BIT_HWMON)169169+ && (line6pcm->flags & MASK_PLAYBACK)170170+ && (line6pcm->flags & MASK_CAPTURE))171171+ add_monitor_signal(urb_out, line6pcm->prev_fbuf,172172+ line6pcm->volume_monitor,173173+ bytes_per_frame);174174+#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE175175+ }176176+#endif177177+ }178178+#ifdef CONFIG_LINE6_USB_DUMP_PCM238179 for (i = 0; i < LINE6_ISO_PACKETS; ++i) {239180 struct usb_iso_packet_descriptor *fout =240181 &urb_out->iso_frame_desc[i];···274161 if (usb_submit_urb(urb_out, GFP_ATOMIC) == 0)275162 set_bit(index, &line6pcm->active_urb_out);276163 else277277- dev_err(s2m(substream), "URB out #%d submission failed\n",278278- index);164164+ dev_err(line6pcm->line6->ifcdev,165165+ "URB out #%d submission failed\n", index);279166280167 spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);281168 return 0;···284171/*285172 Submit all currently available playback URBs.286173*/287287-static int submit_audio_out_all_urbs(struct snd_pcm_substream *substream)174174+int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm)288175{289176 int ret, i;290177291178 for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {292292- ret = submit_audio_out_urb(substream);179179+ ret = submit_audio_out_urb(line6pcm);293180 if (ret < 0)294181 return ret;295182 }···300187/*301188 Unlink all currently active playback URBs.302189*/303303-static void unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm)190190+void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm)304191{305192 unsigned int i;306193···315202}316203317204/*318318- Wait until unlinking of all currently active playback URBs has been finished.205205+ Wait until unlinking of all currently active playback URBs has been finished.319206*/320207static void wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm)321208{···336223 } while (--timeout > 0);337224 if (alive)338225 snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);339339-340340- line6pcm->active_urb_out = 0;341341- line6pcm->unlink_urb_out = 0;342226}343227344228/*345229 Unlink all currently active playback URBs, and wait for finishing.346230*/347347-void unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm)231231+void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm)348232{349349- unlink_audio_out_urbs(line6pcm);233233+ line6_unlink_audio_out_urbs(line6pcm);350234 wait_clear_audio_out_urbs(line6pcm);351235}352236···355245 int i, index, length = 0, shutdown = 0;356246 unsigned long flags;357247248248+ struct snd_line6_pcm *line6pcm =249249+ (struct snd_line6_pcm *)urb->context;358250 struct snd_pcm_substream *substream =359359- (struct snd_pcm_substream *)urb->context;360360- struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);361361- struct snd_pcm_runtime *runtime = substream->runtime;251251+ get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK);252252+253253+#if USE_CLEAR_BUFFER_WORKAROUND254254+ memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);255255+#endif256256+257257+ line6pcm->last_frame_out = urb->start_frame;362258363259 /* find index of URB */364260 for (index = LINE6_ISO_BUFFERS; index--;)···378262 length += urb->iso_frame_desc[i].length;379263380264 spin_lock_irqsave(&line6pcm->lock_audio_out, flags);381381- line6pcm->pos_out_done +=382382- length / line6pcm->properties->bytes_per_frame;383265384384- if (line6pcm->pos_out_done >= runtime->buffer_size)385385- line6pcm->pos_out_done -= runtime->buffer_size;266266+ if (test_bit(BIT_PCM_ALSA_PLAYBACK, &line6pcm->flags)) {267267+ struct snd_pcm_runtime *runtime = substream->runtime;268268+ line6pcm->pos_out_done +=269269+ length / line6pcm->properties->bytes_per_frame;270270+271271+ if (line6pcm->pos_out_done >= runtime->buffer_size)272272+ line6pcm->pos_out_done -= runtime->buffer_size;273273+ }386274387275 clear_bit(index, &line6pcm->active_urb_out);388276···396276 break;397277 }398278399399- if (test_bit(index, &line6pcm->unlink_urb_out))279279+ if (test_and_clear_bit(index, &line6pcm->unlink_urb_out))400280 shutdown = 1;401281402282 spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);403283404284 if (!shutdown) {405405- submit_audio_out_urb(substream);285285+ submit_audio_out_urb(line6pcm);406286407407- line6pcm->bytes_out += length;408408- if (line6pcm->bytes_out >= line6pcm->period_out) {409409- line6pcm->bytes_out -= line6pcm->period_out;410410- snd_pcm_period_elapsed(substream);287287+ if (test_bit(BIT_PCM_ALSA_PLAYBACK, &line6pcm->flags)) {288288+ if ((line6pcm->bytes_out +=289289+ length) >= line6pcm->period_out) {290290+ line6pcm->bytes_out %= line6pcm->period_out;291291+ snd_pcm_period_elapsed(substream);292292+ }411293 }412294 }413295}···462340 return ret;463341464342 line6pcm->period_out = params_period_bytes(hw_params);465465- line6pcm->wrap_out = kmalloc(2 * LINE6_ISO_PACKET_SIZE_MAX, GFP_KERNEL);466466-467467- if (!line6pcm->wrap_out) {468468- dev_err(s2m(substream), "cannot malloc wrap_out\n");469469- return -ENOMEM;470470- }471471-472343 return 0;473344}474345475346/* hw_free playback callback */476347static int snd_line6_playback_hw_free(struct snd_pcm_substream *substream)477348{478478- struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);479479- unlink_wait_clear_audio_out_urbs(line6pcm);480480-481481- kfree(line6pcm->wrap_out);482482- line6pcm->wrap_out = NULL;483483-484349 return snd_pcm_lib_free_pages(substream);485350}486351487352/* trigger playback callback */488488-int snd_line6_playback_trigger(struct snd_pcm_substream *substream, int cmd)353353+int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd)489354{490490- struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);491355 int err;492492- line6pcm->count_out = 0;493356494357 switch (cmd) {495358 case SNDRV_PCM_TRIGGER_START:496496- if (!test_and_set_bit(BIT_RUNNING_PLAYBACK, &line6pcm->flags)) {497497- err = submit_audio_out_all_urbs(substream);359359+#ifdef CONFIG_PM360360+ case SNDRV_PCM_TRIGGER_RESUME:361361+#endif362362+ err = line6_pcm_start(line6pcm, MASK_PCM_ALSA_PLAYBACK);498363499499- if (err < 0) {500500- clear_bit(BIT_RUNNING_PLAYBACK,501501- &line6pcm->flags);502502- return err;503503- }504504- }364364+ if (err < 0)365365+ return err;505366506367 break;507368508369 case SNDRV_PCM_TRIGGER_STOP:509509- if (test_and_clear_bit(BIT_RUNNING_PLAYBACK, &line6pcm->flags))510510- unlink_audio_out_urbs(line6pcm);370370+#ifdef CONFIG_PM371371+ case SNDRV_PCM_TRIGGER_SUSPEND:372372+#endif373373+ err = line6_pcm_stop(line6pcm, MASK_PCM_ALSA_PLAYBACK);374374+375375+ if (err < 0)376376+ return err;511377512378 break;513379···524414525415/* playback operators */526416struct snd_pcm_ops snd_line6_playback_ops = {527527- .open = snd_line6_playback_open,528528- .close = snd_line6_playback_close,529529- .ioctl = snd_pcm_lib_ioctl,530530- .hw_params = snd_line6_playback_hw_params,531531- .hw_free = snd_line6_playback_hw_free,532532- .prepare = snd_line6_prepare,533533- .trigger = snd_line6_trigger,534534- .pointer = snd_line6_playback_pointer,417417+ .open = snd_line6_playback_open,418418+ .close = snd_line6_playback_close,419419+ .ioctl = snd_pcm_lib_ioctl,420420+ .hw_params = snd_line6_playback_hw_params,421421+ .hw_free = snd_line6_playback_hw_free,422422+ .prepare = snd_line6_prepare,423423+ .trigger = snd_line6_trigger,424424+ .pointer = snd_line6_playback_pointer,535425};536426537537-int create_audio_out_urbs(struct snd_line6_pcm *line6pcm)427427+int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm)538428{539429 int i;540430
+20-9
drivers/staging/line6/playback.h
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···1313#define PLAYBACK_H141415151616+#include <sound/pcm.h>1717+1618#include "driver.h"17191818-#include <sound/pcm.h>2020+2121+/*2222+ When the TonePort is used with jack in full duplex mode and the outputs are2323+ not connected, the software monitor produces an ugly noise since everything2424+ written to the output buffer (i.e., the input signal) will be repeated in the2525+ next period (sounds like a delay effect). As a workaround, the output buffer2626+ is cleared after the data have been read, but there must be a better2727+ solution. Until one is found, this workaround can be used to fix the problem.2828+*/2929+#define USE_CLEAR_BUFFER_WORKAROUND 1193020312132extern struct snd_pcm_ops snd_line6_playback_ops;22332323-2424-extern int create_audio_out_urbs(struct snd_line6_pcm *line6pcm);2525-extern int snd_line6_playback_trigger(struct snd_pcm_substream *substream,2626- int cmd);2727-extern void unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm);2828-3434+extern int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm);3535+extern int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm);3636+extern void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm);3737+extern void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm3838+ *line6pcm);3939+extern int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd);29403041#endif
+272-204
drivers/staging/line6/pod.c
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···99 *1010 */11111212-#include "driver.h"1313-1412#include <linux/slab.h>1313+#include <linux/wait.h>1414+#include <sound/control.h>15151616#include "audio.h"1717#include "capture.h"1818#include "control.h"1919+#include "driver.h"1920#include "playback.h"2021#include "pod.h"2122···4645 POD_tuner_freq = 0x15,4746 POD_tuner_note = 0x16,4847 POD_tuner_pitch = 0x17,4949- POD_system_invalid = 0x7fff4848+ POD_system_invalid = 0x100005049};51505251enum {···7069};71707271static struct line6_pcm_properties pod_pcm_properties = {7373- .snd_line6_playback_hw = {7272+ .snd_line6_playback_hw = {7473 .info = (SNDRV_PCM_INFO_MMAP |7575- SNDRV_PCM_INFO_INTERLEAVED |7676- SNDRV_PCM_INFO_BLOCK_TRANSFER |7777- SNDRV_PCM_INFO_MMAP_VALID |7878- SNDRV_PCM_INFO_PAUSE |7979- SNDRV_PCM_INFO_SYNC_START),7474+ SNDRV_PCM_INFO_INTERLEAVED |7575+ SNDRV_PCM_INFO_BLOCK_TRANSFER |7676+ SNDRV_PCM_INFO_MMAP_VALID |7777+ SNDRV_PCM_INFO_PAUSE |7878+#ifdef CONFIG_PM7979+ SNDRV_PCM_INFO_RESUME |8080+#endif8181+ SNDRV_PCM_INFO_SYNC_START),8082 .formats = SNDRV_PCM_FMTBIT_S24_3LE,8183 .rates = SNDRV_PCM_RATE_KNOT,8284 .rate_min = 39062,···8783 .channels_min = 2,8884 .channels_max = 2,8985 .buffer_bytes_max = 60000,9090- .period_bytes_min = LINE6_ISO_PACKET_SIZE_MAX * POD_BYTES_PER_FRAME, /* at least one URB must fit into one period */8686+ .period_bytes_min = 64,9187 .period_bytes_max = 8192,9288 .periods_min = 1,9389 .periods_max = 10249490 },9595- .snd_line6_capture_hw = {9191+ .snd_line6_capture_hw = {9692 .info = (SNDRV_PCM_INFO_MMAP |9797- SNDRV_PCM_INFO_INTERLEAVED |9898- SNDRV_PCM_INFO_BLOCK_TRANSFER |9999- SNDRV_PCM_INFO_MMAP_VALID |100100- SNDRV_PCM_INFO_SYNC_START),9393+ SNDRV_PCM_INFO_INTERLEAVED |9494+ SNDRV_PCM_INFO_BLOCK_TRANSFER |9595+ SNDRV_PCM_INFO_MMAP_VALID |9696+#ifdef CONFIG_PM9797+ SNDRV_PCM_INFO_RESUME |9898+#endif9999+ SNDRV_PCM_INFO_SYNC_START),101100 .formats = SNDRV_PCM_FMTBIT_S24_3LE,102101 .rates = SNDRV_PCM_RATE_KNOT,103102 .rate_min = 39062,···108101 .channels_min = 2,109102 .channels_max = 2,110103 .buffer_bytes_max = 60000,111111- .period_bytes_min = LINE6_ISO_PACKET_SIZE_MAX * POD_BYTES_PER_FRAME, /* at least one URB must fit into one period */104104+ .period_bytes_min = 64,112105 .period_bytes_max = 8192,113106 .periods_min = 1,114107 .periods_max = 1024···120113 .bytes_per_frame = POD_BYTES_PER_FRAME121114};122115123123-static const char pod_request_version[] = { 0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7 };124124-static const char pod_request_channel[] = { 0xf0, 0x00, 0x01, 0x0c, 0x03, 0x75, 0xf7 };125125-static const char pod_version_header[] = { 0xf2, 0x7e, 0x7f, 0x06, 0x02 };116116+static const char pod_request_channel[] = {117117+ 0xf0, 0x00, 0x01, 0x0c, 0x03, 0x75, 0xf7118118+};119119+120120+static const char pod_version_header[] = {121121+ 0xf2, 0x7e, 0x7f, 0x06, 0x02122122+};123123+124124+125125+/* forward declarations: */126126+static void pod_startup2(unsigned long data);127127+static void pod_startup3(struct usb_line6_pod *pod);128128+static void pod_startup4(struct usb_line6_pod *pod);126129127130128131/*···144127145128 for (i = 0; i < POD_CONTROL_SIZE; i++)146129 set_bit(i, pod->param_dirty);147147-}148148-149149-/*150150- Send an asynchronous request for the POD firmware version and device ID.151151-*/152152-static int pod_version_request_async(struct usb_line6_pod *pod)153153-{154154- return line6_send_raw_message_async(&pod->line6, pod->buffer_versionreq, sizeof(pod_request_version));155155-}156156-157157-static void pod_create_files_work(struct work_struct *work)158158-{159159- struct usb_line6_pod *pod = container_of(work, struct usb_line6_pod, create_files_work);160160-161161- pod_create_files(pod->firmware_version, pod->line6.properties->device_bit, pod->line6.ifcdev);162162-}163163-164164-static void pod_startup_timeout(unsigned long arg)165165-{166166- enum {167167- REQUEST_NONE,168168- REQUEST_DUMP,169169- REQUEST_VERSION170170- };171171-172172- int request = REQUEST_NONE;173173- struct usb_line6_pod *pod = (struct usb_line6_pod *)arg;174174-175175- if (pod->dumpreq.ok) {176176- if (!pod->versionreq_ok)177177- request = REQUEST_VERSION;178178- } else {179179- if (pod->versionreq_ok)180180- request = REQUEST_DUMP;181181- else if (pod->startup_count++ & 1)182182- request = REQUEST_DUMP;183183- else184184- request = REQUEST_VERSION;185185- }186186-187187- switch (request) {188188- case REQUEST_DUMP:189189- line6_dump_request_async(&pod->dumpreq, &pod->line6, 0);190190- break;191191-192192- case REQUEST_VERSION:193193- pod_version_request_async(pod);194194- break;195195-196196- default:197197- return;198198- }199199-200200- line6_startup_delayed(&pod->dumpreq, 1, pod_startup_timeout, pod);201130}202131203132static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code, int size)···181218}182219183220/*184184- Handle SAVE button221221+ Handle SAVE button.185222*/186223static void pod_save_button_pressed(struct usb_line6_pod *pod, int type, int index)187224{···192229/*193230 Process a completely received message.194231*/195195-void pod_process_message(struct usb_line6_pod *pod)232232+void line6_pod_process_message(struct usb_line6_pod *pod)196233{197234 const unsigned char *buf = pod->line6.buffer_message;198235···217254 if ((buf[1] == POD_amp_model_setup) ||218255 (buf[1] == POD_effect_setup))219256 /* these also affect other settings */220220- line6_dump_request_async(&pod->dumpreq, &pod->line6, 0);257257+ line6_dump_request_async(&pod->dumpreq, &pod->line6, 0, LINE6_DUMP_CURRENT);221258222259 break;223260···226263 pod->channel_num = buf[1];227264 pod->dirty = 0;228265 set_bit(POD_CHANNEL_DIRTY, &pod->atomic_flags);229229- line6_dump_request_async(&pod->dumpreq, &pod->line6, 0);266266+ line6_dump_request_async(&pod->dumpreq, &pod->line6, 0, LINE6_DUMP_CURRENT);230267 break;231268232269 case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE:···239276 case LINE6_DUMP_CURRENT:240277 memcpy(&pod->prog_data, buf + 7, sizeof(pod->prog_data));241278 pod_mark_batch_all_dirty(pod);242242- pod->dumpreq.ok = 1;243279 break;244280245281 case POD_DUMP_MEMORY:···250288 }251289252290 line6_dump_finished(&pod->dumpreq);291291+ pod_startup3(pod);253292 } else254293 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "wrong size of channel dump message (%d instead of %d)\n",255294 pod->line6.message_length, (int)sizeof(pod->prog_data) + 7));···263300#define PROCESS_SYSTEM_PARAM(x) \264301 case POD_ ## x: \265302 pod->x.value = value; \266266- wake_up_interruptible(&pod->x.wait); \303303+ wake_up(&pod->x.wait); \267304 break;268305269306 switch (buf[6]) {···294331 case POD_SYSEX_CLIP:295332 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "audio clipped\n"));296333 pod->clipping.value = 1;297297- wake_up_interruptible(&pod->clipping.wait);334334+ wake_up(&pod->clipping.wait);298335 break;299336300337 case POD_SYSEX_STORE:···305342 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown sysex message %02X\n", buf[5]));306343 }307344 } else if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {308308- if (pod->versionreq_ok == 0) {309309- pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];310310- pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) | (int)buf[10];311311- pod->versionreq_ok = 1;312312-313313- /* Now we know the firmware version, so we schedule a bottom half314314- handler to create the special files: */315315- INIT_WORK(&pod->create_files_work, pod_create_files_work);316316- queue_work(line6_workqueue, &pod->create_files_work);317317- } else318318- DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "multiple firmware version message\n"));345345+ pod->firmware_version = buf[13] * 100 + buf[14] * 10 + buf[15];346346+ pod->device_id = ((int)buf[8] << 16) | ((int)buf[9] << 8) | (int)buf[10];347347+ pod_startup4(pod);319348 } else320349 DEBUG_MESSAGES(dev_err(pod->line6.ifcdev, "unknown sysex header\n"));321350···332377 *) This method fails if a param change message is "chopped" after the first333378 byte.334379*/335335-void pod_midi_postprocess(struct usb_line6_pod *pod, unsigned char *data, int length)380380+void line6_pod_midi_postprocess(struct usb_line6_pod *pod, unsigned char *data, int length)336381{337382 int i;338383···367412/*368413 Transmit PODxt Pro control parameter.369414*/370370-void pod_transmit_parameter(struct usb_line6_pod *pod, int param, int value)415415+void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param, int value)371416{372417 if (line6_transmit_parameter(&pod->line6, param, value) == 0)373418 pod_store_parameter(pod, param, value);···466511 char *p2;467512 char *last_non_space = buf;468513469469- int retval = line6_wait_dump(&pod->dumpreq, 0);514514+ int retval = line6_dump_wait_interruptible(&pod->dumpreq);470515 if (retval < 0)471516 return retval;472517···543588{544589 struct usb_interface *interface = to_usb_interface(dev);545590 struct usb_line6_pod *pod = usb_get_intfdata(interface);546546- int retval = line6_wait_dump(&pod->dumpreq, 0);591591+ int retval = line6_dump_wait_interruptible(&pod->dumpreq);547592 if (retval < 0)548593 return retval;549594 memcpy(buf, &pod->prog_data, sizeof(pod->prog_data));···561606562607 if (count != sizeof(pod->prog_data)) {563608 dev_err(pod->line6.ifcdev,564564- "data block must be exactly %zu bytes\n",565565- sizeof(pod->prog_data));609609+ "data block must be exactly %d bytes\n",610610+ (int)sizeof(pod->prog_data));566611 return -EINVAL;567612 }568613···571616}572617573618/*574574- Request system parameter.619619+ Identify system parameters related to the tuner.620620+*/621621+static bool pod_is_tuner(int code)622622+{623623+ return624624+ (code == POD_tuner_mute) ||625625+ (code == POD_tuner_freq) ||626626+ (code == POD_tuner_note) ||627627+ (code == POD_tuner_pitch);628628+}629629+630630+/*631631+ Get system parameter (as integer).575632 @param tuner non-zero, if code refers to a tuner parameter576633*/577577-static ssize_t pod_get_system_param(struct usb_line6_pod *pod, char *buf, int code, struct ValueWait *param, int tuner, int sign)634634+static int pod_get_system_param_int(struct usb_line6_pod *pod, int *value, int code,635635+ struct ValueWait *param, int sign)578636{579637 char *sysex;580580- int value;581638 static const int size = 1;582639 int retval = 0;583583- DECLARE_WAITQUEUE(wait, current);584640585585- if (((pod->prog_data.control[POD_tuner] & 0x40) == 0) && tuner)641641+ if (((pod->prog_data.control[POD_tuner] & 0x40) == 0) && pod_is_tuner(code))586642 return -ENODEV;587643588588- /* send value request to tuner: */644644+ /* send value request to device: */589645 param->value = POD_system_invalid;590646 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEMREQ, size);647647+591648 if (!sysex)592592- return 0;649649+ return -ENOMEM;650650+593651 sysex[SYSEX_DATA_OFS] = code;594652 line6_send_sysex_message(&pod->line6, sysex, size);595653 kfree(sysex);596654597597- /* wait for tuner to respond: */598598- add_wait_queue(¶m->wait, &wait);599599- current->state = TASK_INTERRUPTIBLE;600600-601601- while (param->value == POD_system_invalid) {602602- if (signal_pending(current)) {603603- retval = -ERESTARTSYS;604604- break;605605- } else606606- schedule();607607- }608608-609609- current->state = TASK_RUNNING;610610- remove_wait_queue(¶m->wait, &wait);655655+ /* wait for device to respond: */656656+ retval = wait_event_interruptible(param->wait, param->value != POD_system_invalid);611657612658 if (retval < 0)613659 return retval;614660615615- value = sign ? (int)(signed short)param->value : (int)(unsigned short)param->value;661661+ *value = sign ? (int)(signed short)param->value : (int)(unsigned short)param->value;662662+663663+ if(*value == POD_system_invalid)664664+ *value = 0; /* don't report uninitialized values */665665+666666+ return 0;667667+}668668+669669+/*670670+ Get system parameter (as string).671671+ @param tuner non-zero, if code refers to a tuner parameter672672+*/673673+static ssize_t pod_get_system_param_string(struct usb_line6_pod *pod, char *buf, int code,674674+ struct ValueWait *param, int sign)675675+{676676+ int retval, value = 0;677677+ retval = pod_get_system_param_int(pod, &value, code, param, sign);678678+679679+ if(retval < 0)680680+ return retval;681681+616682 return sprintf(buf, "%d\n", value);617683}618684619685/*620620- Send system parameter.686686+ Send system parameter (from integer).621687 @param tuner non-zero, if code refers to a tuner parameter622688*/623623-static ssize_t pod_set_system_param(struct usb_line6_pod *pod, const char *buf,624624- int count, int code, unsigned short mask,625625- int tuner)689689+static int pod_set_system_param_int(struct usb_line6_pod *pod, int value, int code)626690{627691 char *sysex;628692 static const int size = 5;629629- unsigned short value;630630- unsigned long result;631631- int ret;632693633633- if (((pod->prog_data.control[POD_tuner] & 0x40) == 0) && tuner)694694+ if (((pod->prog_data.control[POD_tuner] & 0x40) == 0) && pod_is_tuner(code))634695 return -EINVAL;635696636697 /* send value to tuner: */637698 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size);638699 if (!sysex)639639- return 0;640640-641641- ret = strict_strtoul(buf, 10, &result);642642- if (ret)643643- return ret;644644-645645- value = result & mask;700700+ return -ENOMEM;646701 sysex[SYSEX_DATA_OFS] = code;647702 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f;648703 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f;···660695 sysex[SYSEX_DATA_OFS + 4] = (value ) & 0x0f;661696 line6_send_sysex_message(&pod->line6, sysex, size);662697 kfree(sysex);663663- return count;698698+ return 0;699699+}700700+701701+/*702702+ Send system parameter (from string).703703+ @param tuner non-zero, if code refers to a tuner parameter704704+*/705705+static ssize_t pod_set_system_param_string(struct usb_line6_pod *pod, const char *buf,706706+ int count, int code, unsigned short mask)707707+{708708+ int retval;709709+ unsigned short value = simple_strtoul(buf, NULL, 10) & mask;710710+ retval = pod_set_system_param_int(pod, value, code);711711+ return (retval < 0) ? retval : count;664712}665713666714/*···684706{685707 struct usb_interface *interface = to_usb_interface(dev);686708 struct usb_line6_pod *pod = usb_get_intfdata(interface);687687- int retval = line6_wait_dump(&pod->dumpreq, 0);709709+ int retval = line6_dump_wait_interruptible(&pod->dumpreq);688710 if (retval < 0)689711 return retval;690712 memcpy(buf, &pod->prog_data_buf, sizeof(pod->prog_data_buf));···703725704726 if (count != sizeof(pod->prog_data)) {705727 dev_err(pod->line6.ifcdev,706706- "data block must be exactly %zu bytes\n",707707- sizeof(pod->prog_data));728728+ "data block must be exactly %d bytes\n",729729+ (int)sizeof(pod->prog_data));708730 return -EINVAL;709731 }710732···878900{879901 struct usb_interface *interface = to_usb_interface(dev);880902 struct usb_line6_pod *pod = usb_get_intfdata(interface);881881- int err = 0;882882- DECLARE_WAITQUEUE(wait, current);883883- pod->clipping.value = 0;884884- add_wait_queue(&pod->clipping.wait, &wait);885885- current->state = TASK_INTERRUPTIBLE;886886-887887- while (pod->clipping.value == 0) {888888- if (signal_pending(current)) {889889- err = -ERESTARTSYS;890890- break;891891- } else892892- schedule();893893- }894894-895895- current->state = TASK_RUNNING;896896- remove_wait_queue(&pod->clipping.wait, &wait);897897- return err;903903+ return wait_event_interruptible(pod->clipping.wait, pod->clipping.value != 0);898904}899905900900-#define POD_GET_SYSTEM_PARAM(code, tuner, sign) \906906+/*907907+ POD startup procedure.908908+ This is a sequence of functions with special requirements (e.g., must909909+ not run immediately after initialization, must not run in interrupt910910+ context). After the last one has finished, the device is ready to use.911911+*/912912+913913+static void pod_startup1(struct usb_line6_pod *pod)914914+{915915+ CHECK_STARTUP_PROGRESS(pod->startup_progress, 1);916916+917917+ /* delay startup procedure: */918918+ line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2, (unsigned long)pod);919919+}920920+921921+static void pod_startup2(unsigned long data)922922+{923923+ struct usb_line6_pod *pod = (struct usb_line6_pod *)data;924924+ CHECK_STARTUP_PROGRESS(pod->startup_progress, 2);925925+926926+ /* current channel dump: */927927+ line6_dump_request_async(&pod->dumpreq, &pod->line6, 0, LINE6_DUMP_CURRENT);928928+}929929+930930+static void pod_startup3(struct usb_line6_pod *pod)931931+{932932+ struct usb_line6 *line6 = &pod->line6;933933+ CHECK_STARTUP_PROGRESS(pod->startup_progress, 3);934934+935935+ /* request firmware version: */936936+ line6_version_request_async(line6);937937+}938938+939939+static void pod_startup4(struct usb_line6_pod *pod)940940+{941941+ CHECK_STARTUP_PROGRESS(pod->startup_progress, 4);942942+943943+ /* schedule work for global work queue: */944944+ schedule_work(&pod->startup_work);945945+}946946+947947+static void pod_startup5(struct work_struct *work)948948+{949949+ struct usb_line6_pod *pod = container_of(work, struct usb_line6_pod, startup_work);950950+ struct usb_line6 *line6 = &pod->line6;951951+952952+ CHECK_STARTUP_PROGRESS(pod->startup_progress, 5);953953+954954+ /* serial number: */955955+ line6_read_serial_number(&pod->line6, &pod->serial_number);956956+957957+ /* ALSA audio interface: */958958+ line6_register_audio(line6);959959+960960+ /* device files: */961961+ line6_pod_create_files(pod->firmware_version, line6->properties->device_bit, line6->ifcdev);962962+}963963+964964+#define POD_GET_SYSTEM_PARAM(code, sign) \901965static ssize_t pod_get_ ## code(struct device *dev, \902966 struct device_attribute *attr, char *buf) \903967{ \904968 struct usb_interface *interface = to_usb_interface(dev); \905969 struct usb_line6_pod *pod = usb_get_intfdata(interface); \906906- return pod_get_system_param(pod, buf, POD_ ## code, &pod->code, \907907- tuner, sign); \970970+ return pod_get_system_param_string(pod, buf, POD_ ## code, \971971+ &pod->code, sign); \908972}909973910910-#define POD_GET_SET_SYSTEM_PARAM(code, mask, tuner, sign) \911911-POD_GET_SYSTEM_PARAM(code, tuner, sign) \974974+#define POD_GET_SET_SYSTEM_PARAM(code, mask, sign) \975975+POD_GET_SYSTEM_PARAM(code, sign) \912976static ssize_t pod_set_ ## code(struct device *dev, \913977 struct device_attribute *attr, \914978 const char *buf, size_t count) \915979{ \916980 struct usb_interface *interface = to_usb_interface(dev); \917981 struct usb_line6_pod *pod = usb_get_intfdata(interface); \918918- return pod_set_system_param(pod, buf, count, POD_ ## code, mask, \919919- tuner); \982982+ return pod_set_system_param_string(pod, buf, count, POD_ ## code, mask); \920983}921984922922-POD_GET_SET_SYSTEM_PARAM(monitor_level, 0xffff, 0, 0);923923-POD_GET_SET_SYSTEM_PARAM(routing, 0x0003, 0, 0);924924-POD_GET_SET_SYSTEM_PARAM(tuner_mute, 0x0001, 1, 0);925925-POD_GET_SET_SYSTEM_PARAM(tuner_freq, 0xffff, 1, 0);926926-POD_GET_SYSTEM_PARAM(tuner_note, 1, 1);927927-POD_GET_SYSTEM_PARAM(tuner_pitch, 1, 1);985985+POD_GET_SET_SYSTEM_PARAM(monitor_level, 0xffff, 0);986986+POD_GET_SET_SYSTEM_PARAM(routing, 0x0003, 0);987987+POD_GET_SET_SYSTEM_PARAM(tuner_mute, 0x0001, 0);988988+POD_GET_SET_SYSTEM_PARAM(tuner_freq, 0xffff, 0);989989+POD_GET_SYSTEM_PARAM(tuner_note, 1);990990+POD_GET_SYSTEM_PARAM(tuner_pitch, 1);928991929992#undef GET_SET_SYSTEM_PARAM930993#undef GET_SYSTEM_PARAM···996977static DEVICE_ATTR(tuner_note, S_IRUGO, pod_get_tuner_note, line6_nop_write);997978static DEVICE_ATTR(tuner_pitch, S_IRUGO, pod_get_tuner_pitch, line6_nop_write);998979999999-#if CREATE_RAW_FILE980980+#ifdef CONFIG_LINE6_USB_RAW1000981static DEVICE_ATTR(raw, S_IWUGO, line6_nop_read, line6_set_raw);1001982#endif983983+984984+/* control info callback */985985+static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol,986986+ struct snd_ctl_elem_info *uinfo)987987+{988988+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;989989+ uinfo->count = 1;990990+ uinfo->value.integer.min = 0;991991+ uinfo->value.integer.max = 65535;992992+ return 0;993993+}994994+995995+/* control get callback */996996+static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol,997997+ struct snd_ctl_elem_value *ucontrol)998998+{999999+ struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);10001000+ struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;10011001+ ucontrol->value.integer.value[0] = pod->monitor_level.value;10021002+ return 0;10031003+}10041004+10051005+/* control put callback */10061006+static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol,10071007+ struct snd_ctl_elem_value *ucontrol)10081008+{10091009+ struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);10101010+ struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6;10111011+10121012+ if(ucontrol->value.integer.value[0] == pod->monitor_level.value)10131013+ return 0;10141014+10151015+ pod->monitor_level.value = ucontrol->value.integer.value[0];10161016+ pod_set_system_param_int(pod, ucontrol->value.integer.value[0], POD_monitor_level);10171017+ return 1;10181018+}10191019+10201020+/* control definition */10211021+static struct snd_kcontrol_new pod_control_monitor = {10221022+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,10231023+ .name = "Monitor Playback Volume",10241024+ .index = 0,10251025+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,10261026+ .info = snd_pod_control_monitor_info,10271027+ .get = snd_pod_control_monitor_get,10281028+ .put = snd_pod_control_monitor_put10291029+};1002103010031031/*10041032 POD destructor.···10649981065999 /* free dump request data: */10661000 line6_dumpreq_destruct(&pod->dumpreq);10671067-10681068- kfree(pod->buffer_versionreq);10691001}1070100210711003/*···10981034 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_note));10991035 CHECK_RETURN(device_create_file(dev, &dev_attr_tuner_pitch));1100103611011101-#if CREATE_RAW_FILE10371037+#ifdef CONFIG_LINE6_USB_RAW11021038 CHECK_RETURN(device_create_file(dev, &dev_attr_raw));11031039#endif11041040···11061042}1107104311081044/*11091109- Init POD device.10451045+ Try to init POD device.11101046*/11111111-int pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)10471047+static int pod_try_init(struct usb_interface *interface, struct usb_line6_pod *pod)11121048{11131049 int err;11141050 struct usb_line6 *line6 = &pod->line6;···11261062 init_waitqueue_head(&pod->tuner_note.wait);11271063 init_waitqueue_head(&pod->tuner_pitch.wait);11281064 init_waitqueue_head(&pod->clipping.wait);10651065+ init_timer(&pod->startup_timer);10661066+ INIT_WORK(&pod->startup_work, pod_startup5);1129106711301068 memset(pod->param_dirty, 0xff, sizeof(pod->param_dirty));11311069···11361070 sizeof(pod_request_channel));11371071 if (err < 0) {11381072 dev_err(&interface->dev, "Out of memory\n");11391139- pod_destruct(interface);11401140- return -ENOMEM;11411141- }11421142-11431143- pod->buffer_versionreq = kmemdup(pod_request_version,11441144- sizeof(pod_request_version),11451145- GFP_KERNEL);11461146-11471147- if (pod->buffer_versionreq == NULL) {11481148- dev_err(&interface->dev, "Out of memory\n");11491149- pod_destruct(interface);11501073 return -ENOMEM;11511074 }1152107511531076 /* create sysfs entries: */11541077 err = pod_create_files2(&interface->dev);11551078 if (err < 0) {11561156- pod_destruct(interface);11571079 return err;11581080 }1159108111601082 /* initialize audio system: */11611083 err = line6_init_audio(line6);11621084 if (err < 0) {11631163- pod_destruct(interface);11641085 return err;11651086 }1166108711671088 /* initialize MIDI subsystem: */11681089 err = line6_init_midi(line6);11691090 if (err < 0) {11701170- pod_destruct(interface);11711091 return err;11721092 }1173109311741094 /* initialize PCM subsystem: */11751095 err = line6_init_pcm(line6, &pod_pcm_properties);11761096 if (err < 0) {11771177- pod_destruct(interface);11781097 return err;11791098 }1180109911811181- /* register audio system: */11821182- err = line6_register_audio(line6);11001100+ /* register monitor control: */11011101+ err = snd_ctl_add(line6->card, snd_ctl_new1(&pod_control_monitor, line6->line6pcm));11831102 if (err < 0) {11841184- pod_destruct(interface);11851103 return err;11861104 }11051105+11061106+ /*11071107+ When the sound card is registered at this point, the PODxt Live11081108+ displays "Invalid Code Error 07", so we do it later in the event11091109+ handler.11101110+ */1187111111881112 if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {11891189- /* query some data: */11901190- line6_startup_delayed(&pod->dumpreq, POD_STARTUP_DELAY,11911191- pod_startup_timeout, pod);11921192- line6_read_serial_number(&pod->line6, &pod->serial_number);11131113+ pod->monitor_level.value = POD_system_invalid;11141114+11151115+ /* initiate startup procedure: */11161116+ pod_startup1(pod);11931117 }1194111811951119 return 0;11961120}1197112111981122/*11231123+ Init POD device (and clean up in case of failure).11241124+*/11251125+int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)11261126+{11271127+ int err = pod_try_init(interface, pod);11281128+11291129+ if (err < 0) {11301130+ pod_destruct(interface);11311131+ }11321132+11331133+ return err;11341134+}11351135+11361136+/*11991137 POD device disconnected.12001138*/12011201-void pod_disconnect(struct usb_interface *interface)11391139+void line6_pod_disconnect(struct usb_interface *interface)12021140{12031141 struct usb_line6_pod *pod;12041142···12151145 struct device *dev = &interface->dev;1216114612171147 if (line6pcm != NULL) {12181218- unlink_wait_clear_audio_out_urbs(line6pcm);12191219- unlink_wait_clear_audio_in_urbs(line6pcm);11481148+ line6_pcm_disconnect(line6pcm);12201149 }1221115012221151 if (dev != NULL) {12231152 /* remove sysfs entries: */12241224- if (pod->versionreq_ok)12251225- pod_remove_files(pod->firmware_version, pod->line6.properties->device_bit, dev);11531153+ line6_pod_remove_files(pod->firmware_version, pod->line6.properties->device_bit, dev);1226115412271155 device_remove_file(dev, &dev_attr_channel);12281156 device_remove_file(dev, &dev_attr_clip);···12471179 device_remove_file(dev, &dev_attr_tuner_note);12481180 device_remove_file(dev, &dev_attr_tuner_pitch);1249118112501250-#if CREATE_RAW_FILE11821182+#ifdef CONFIG_LINE6_USB_RAW12511183 device_remove_file(dev, &dev_attr_raw);12521184#endif12531185 }
+53-61
drivers/staging/line6/pod.h
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···1313#define POD_H141415151616-#include "driver.h"1717-1616+#include <linux/interrupt.h>1817#include <linux/spinlock.h>1918#include <linux/usb.h>2019#include <linux/wait.h>2121-#include <linux/workqueue.h>22202321#include <sound/core.h>24222323+#include "driver.h"2524#include "dumprequest.h"26252726···4142*/4243#define POD_CONTROL_SIZE 0x804344#define POD_BUFSIZE_DUMPREQ 74444-#define POD_STARTUP_DELAY 34545-4545+#define POD_STARTUP_DELAY 300046464747/**4848- Data structure for values that need to be requested explicitly.4949- This is the case for system and tuner settings.4848+ Data structure for values that need to be requested explicitly.4949+ This is the case for system and tuner settings.5050*/5151struct ValueWait {5252- unsigned short value;5252+ int value;5353 wait_queue_head_t wait;5454};55555656/**5757- Binary PodXT Pro program dump5757+ Binary PODxt Pro program dump5858*/5959struct pod_program {6060 /**6161- Header information (including program name).6161+ Header information (including program name).6262 */6363 unsigned char header[0x20];64646565 /**6666- Program parameters.6666+ Program parameters.6767 */6868 unsigned char control[POD_CONTROL_SIZE];6969};70707171struct usb_line6_pod {7272 /**7373- Generic Line6 USB data.7373+ Generic Line6 USB data.7474 */7575 struct usb_line6 line6;76767777 /**7878- Dump request structure.7878+ Dump request structure.7979 */8080 struct line6_dump_request dumpreq;81818282 /**8383- Current program number.8383+ Current program number.8484 */8585 unsigned char channel_num;86868787 /**8888- Current program settings.8888+ Current program settings.8989 */9090 struct pod_program prog_data;91919292 /**9393- Buffer for data retrieved from or to be stored on PODxt Pro.9393+ Buffer for data retrieved from or to be stored on PODxt Pro.9494 */9595 struct pod_program prog_data_buf;96969797 /**9898- Buffer for requesting version number.9999- */100100- unsigned char *buffer_versionreq;101101-102102- /**103103- Tuner mute mode.9898+ Tuner mute mode.10499 */105100 struct ValueWait tuner_mute;106101107102 /**108108- Tuner base frequency (typically 440Hz).103103+ Tuner base frequency (typically 440Hz).109104 */110105 struct ValueWait tuner_freq;111106112107 /**113113- Note received from tuner.108108+ Note received from tuner.114109 */115110 struct ValueWait tuner_note;116111117112 /**118118- Pitch value received from tuner.113113+ Pitch value received from tuner.119114 */120115 struct ValueWait tuner_pitch;121116122117 /**123123- Instrument monitor level.118118+ Instrument monitor level.124119 */125120 struct ValueWait monitor_level;126121127122 /**128128- Audio routing mode.129129- 0: send processed guitar130130- 1: send clean guitar131131- 2: send clean guitar re-amp playback132132- 3: send re-amp playback123123+ Audio routing mode.124124+ 0: send processed guitar125125+ 1: send clean guitar126126+ 2: send clean guitar re-amp playback127127+ 3: send re-amp playback133128 */134129 struct ValueWait routing;135130136131 /**137137- Wait for audio clipping event.132132+ Wait for audio clipping event.138133 */139134 struct ValueWait clipping;140135141136 /**142142- Bottom-half for creation of sysfs special files.137137+ Timer for device initializaton.143138 */144144- struct work_struct create_files_work;139139+ struct timer_list startup_timer;145140146141 /**147147- Dirty flags for access to parameter data.142142+ Work handler for device initializaton.143143+ */144144+ struct work_struct startup_work;145145+146146+ /**147147+ Current progress in startup procedure.148148+ */149149+ int startup_progress;150150+151151+ /**152152+ Dirty flags for access to parameter data.148153 */149154 unsigned long param_dirty[POD_CONTROL_SIZE / sizeof(unsigned long)];150155151156 /**152152- Some atomic flags.157157+ Some atomic flags.153158 */154159 unsigned long atomic_flags;155160156161 /**157157- Counter for startup process.158158- */159159- int startup_count;160160-161161- /**162162- Serial number of device.162162+ Serial number of device.163163 */164164 int serial_number;165165166166 /**167167- Firmware version (x 100).167167+ Firmware version (x 100).168168 */169169 int firmware_version;170170171171 /**172172- Device ID.172172+ Device ID.173173 */174174 int device_id;175175176176 /**177177- Flag to indicate modification of current program settings.177177+ Flag to indicate modification of current program settings.178178 */179179 char dirty;180180181181 /**182182- Flag if initial firmware version request has been successful.183183- */184184- char versionreq_ok;185185-186186- /**187187- Flag to enable MIDI postprocessing.182182+ Flag to enable MIDI postprocessing.188183 */189184 char midi_postprocess;190185};191186192187193193-extern void pod_disconnect(struct usb_interface *interface);194194-extern int pod_init(struct usb_interface *interface, struct usb_line6_pod *pod);195195-extern void pod_midi_postprocess(struct usb_line6_pod *pod,196196- unsigned char *data, int length);197197-extern void pod_process_message(struct usb_line6_pod *pod);198198-extern void pod_receive_parameter(struct usb_line6_pod *pod, int param);199199-extern void pod_transmit_parameter(struct usb_line6_pod *pod, int param,200200- int value);188188+extern void line6_pod_disconnect(struct usb_interface *interface);189189+extern int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod);190190+extern void line6_pod_midi_postprocess(struct usb_line6_pod *pod,191191+ unsigned char *data, int length);192192+extern void line6_pod_process_message(struct usb_line6_pod *pod);193193+extern void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,194194+ int value);201195202196203197#endif
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···1313#define TONEPORT_H141415151616-#include "driver.h"1717-1816#include <linux/usb.h>1917#include <sound/core.h>1818+1919+#include "driver.h"202021212222struct usb_line6_toneport {2323 /**2424- Generic Line6 USB data.2424+ Generic Line6 USB data.2525 */2626 struct usb_line6 line6;27272828 /**2929- Serial number of device.2929+ Source selector.3030+ */3131+ int source;3232+3333+ /**3434+ Serial number of device.3035 */3136 int serial_number;32373338 /**3434- Firmware version (x 100).3939+ Firmware version (x 100).3540 */3641 int firmware_version;4242+4343+ /**4444+ Timer for delayed PCM startup.4545+ */4646+ struct timer_list timer;3747};384839494040-extern void toneport_disconnect(struct usb_interface *interface);4141-extern int toneport_init(struct usb_interface *interface,4242- struct usb_line6_toneport *toneport);5050+extern void line6_toneport_disconnect(struct usb_interface *interface);5151+extern int line6_toneport_init(struct usb_interface *interface,5252+ struct usb_line6_toneport *toneport);5353+extern void line6_toneport_reset_resume(struct usb_line6_toneport *toneport);435444554556#endif
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···99 *1010 */11111212-#include "driver.h"1313-1412#include <linux/slab.h>15131614#include "audio.h"1715#include "control.h"1616+#include "driver.h"1817#include "variax.h"19182019···2526#define VARIAX_OFFSET_ACTIVATE 7262727282929+/*3030+ This message is sent by the device during initialization and identifies3131+ the connected guitar model.3232+*/3333+static const char variax_init_model[] = {3434+ 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x69, 0x02,3535+ 0x003636+};3737+3838+/*3939+ This message is sent by the device during initialization and identifies4040+ the connected guitar version.4141+*/4242+static const char variax_init_version[] = {4343+ 0xf0, 0x7e, 0x7f, 0x06, 0x02, 0x00, 0x01, 0x0c,4444+ 0x07, 0x00, 0x00, 0x004545+};4646+4747+/*4848+ This message is the last one sent by the device during initialization.4949+*/5050+static const char variax_init_done[] = {5151+ 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6b5252+};5353+2854static const char variax_activate[] = {2955 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x2a, 0x01,3056 0xf73157};5858+3259static const char variax_request_bank[] = {3360 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6d, 0xf73461};6262+3563static const char variax_request_model1[] = {3664 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x3c, 0x00,3765 0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x05, 0x03,3866 0x00, 0x00, 0x00, 0xf73967};6868+4069static const char variax_request_model2[] = {4170 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x3c, 0x00,4271 0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x03,4372 0x00, 0x00, 0x00, 0xf74473};7474+7575+7676+/* forward declarations: */7777+static int variax_create_files2(struct device *dev);7878+static void variax_startup2(unsigned long data);7979+static void variax_startup4(unsigned long data);8080+static void variax_startup5(unsigned long data);458146824783/*···9460 }9561}96629797-static void variax_activate_timeout(unsigned long arg)6363+static void variax_activate_async(struct usb_line6_variax *variax, int a)9864{9999- struct usb_line6_variax *variax = (struct usb_line6_variax *)arg;100100- variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = 1;6565+ variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a;10166 line6_send_raw_message_async(&variax->line6, variax->buffer_activate,10267 sizeof(variax_activate));10368}1046910570/*106106- Send an asynchronous activation request after a given interval.7171+ Variax startup procedure.7272+ This is a sequence of functions with special requirements (e.g., must7373+ not run immediately after initialization, must not run in interrupt7474+ context). After the last one has finished, the device is ready to use.10775*/108108-static void variax_activate_delayed(struct usb_line6_variax *variax,109109- int seconds)7676+7777+static void variax_startup1(struct usb_line6_variax *variax)11078{111111- variax->activate_timer.expires = jiffies + seconds * HZ;112112- variax->activate_timer.function = variax_activate_timeout;113113- variax->activate_timer.data = (unsigned long)variax;114114- add_timer(&variax->activate_timer);7979+ CHECK_STARTUP_PROGRESS(variax->startup_progress, 1);8080+8181+ /* delay startup procedure: */8282+ line6_start_timer(&variax->startup_timer, VARIAX_STARTUP_DELAY1, variax_startup2, (unsigned long)variax);11583}11684117117-static void variax_startup_timeout(unsigned long arg)8585+static void variax_startup2(unsigned long data)11886{119119- struct usb_line6_variax *variax = (struct usb_line6_variax *)arg;8787+ struct usb_line6_variax *variax = (struct usb_line6_variax *)data;8888+ struct usb_line6 *line6 = &variax->line6;8989+ CHECK_STARTUP_PROGRESS(variax->startup_progress, 2);12090121121- if (variax->dumpreq.ok)122122- return;9191+ /* request firmware version: */9292+ line6_version_request_async(line6);9393+}12394124124- line6_dump_request_async(&variax->dumpreq, &variax->line6, 0);125125- line6_startup_delayed(&variax->dumpreq, 1, variax_startup_timeout,126126- variax);9595+static void variax_startup3(struct usb_line6_variax *variax)9696+{9797+ CHECK_STARTUP_PROGRESS(variax->startup_progress, 3);9898+9999+ /* delay startup procedure: */100100+ line6_start_timer(&variax->startup_timer, VARIAX_STARTUP_DELAY3, variax_startup4, (unsigned long)variax);101101+}102102+103103+static void variax_startup4(unsigned long data)104104+{105105+ struct usb_line6_variax *variax = (struct usb_line6_variax *)data;106106+ CHECK_STARTUP_PROGRESS(variax->startup_progress, 4);107107+108108+ /* activate device: */109109+ variax_activate_async(variax, 1);110110+ line6_start_timer(&variax->startup_timer, VARIAX_STARTUP_DELAY4, variax_startup5, (unsigned long)variax);111111+}112112+113113+static void variax_startup5(unsigned long data)114114+{115115+ struct usb_line6_variax *variax = (struct usb_line6_variax *)data;116116+ CHECK_STARTUP_PROGRESS(variax->startup_progress, 5);117117+118118+ /* current model dump: */119119+ line6_dump_request_async(&variax->dumpreq, &variax->line6, 0, VARIAX_DUMP_PASS1);120120+ /* passes 2 and 3 are performed implicitly before entering variax_startup6 */121121+}122122+123123+static void variax_startup6(struct usb_line6_variax *variax)124124+{125125+ CHECK_STARTUP_PROGRESS(variax->startup_progress, 6);126126+127127+ /* schedule work for global work queue: */128128+ schedule_work(&variax->startup_work);129129+}130130+131131+static void variax_startup7(struct work_struct *work)132132+{133133+ struct usb_line6_variax *variax = container_of(work, struct usb_line6_variax, startup_work);134134+ struct usb_line6 *line6 = &variax->line6;135135+136136+ CHECK_STARTUP_PROGRESS(variax->startup_progress, 7);137137+138138+ /* ALSA audio interface: */139139+ line6_register_audio(&variax->line6);140140+141141+ /* device files: */142142+ line6_variax_create_files(0, 0, line6->ifcdev);143143+ variax_create_files2(line6->ifcdev);127144}128145129146/*130147 Process a completely received message.131148*/132132-void variax_process_message(struct usb_line6_variax *variax)149149+void line6_variax_process_message(struct usb_line6_variax *variax)133150{134151 const unsigned char *buf = variax->line6.buffer_message;135152···200115 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE:201116 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST:202117 variax->model = buf[1];203203- line6_dump_request_async(&variax->dumpreq, &variax->line6, 0);118118+ line6_dump_request_async(&variax->dumpreq, &variax->line6, 0, VARIAX_DUMP_PASS1);204119 break;205120206121 case LINE6_RESET:207122 dev_info(variax->line6.ifcdev, "VARIAX reset\n");208208- variax_activate_delayed(variax, VARIAX_ACTIVATE_DELAY);209123 break;210124211125 case LINE6_SYSEX_BEGIN:···216132 case VARIAX_DUMP_PASS1:217133 variax_decode(buf + VARIAX_MODEL_HEADER_LENGTH, (unsigned char *)&variax->model_data,218134 (sizeof(variax->model_data.name) + sizeof(variax->model_data.control) / 2) * 2);219219- line6_dump_request_async(&variax->dumpreq, &variax->line6, 1);220220- line6_dump_started(&variax->dumpreq, VARIAX_DUMP_PASS2);135135+ line6_dump_request_async(&variax->dumpreq, &variax->line6, 1, VARIAX_DUMP_PASS2);221136 break;222137223138 case VARIAX_DUMP_PASS2:···224141 variax_decode(buf + VARIAX_MODEL_HEADER_LENGTH,225142 (unsigned char *)&variax->model_data.control + sizeof(variax->model_data.control) / 2,226143 sizeof(variax->model_data.control) / 2 * 2);227227- variax->dumpreq.ok = 1;228228- line6_dump_request_async(&variax->dumpreq, &variax->line6, 2);229229- line6_dump_started(&variax->dumpreq, VARIAX_DUMP_PASS3);144144+ line6_dump_request_async(&variax->dumpreq, &variax->line6, 2, VARIAX_DUMP_PASS3);230145 }231146 } else {232147 DEBUG_MESSAGES(dev_err(variax->line6.ifcdev, "illegal length %d of model data\n", variax->line6.message_length));233148 line6_dump_finished(&variax->dumpreq);234149 }235150 } else if (memcmp(buf + 1, variax_request_bank + 1,236236- sizeof(variax_request_bank) - 2) == 0) {151151+ sizeof(variax_request_bank) - 2) == 0) {237152 memcpy(variax->bank,238153 buf + sizeof(variax_request_bank) - 1,239154 sizeof(variax->bank));240240- variax->dumpreq.ok = 1;241155 line6_dump_finished(&variax->dumpreq);156156+ variax_startup6(variax);157157+ } else if (memcmp(buf + 1, variax_init_model + 1,158158+ sizeof(variax_init_model) - 1) == 0) {159159+ memcpy(variax->guitar,160160+ buf + sizeof(variax_init_model),161161+ sizeof(variax->guitar));162162+ } else if (memcmp(buf + 1, variax_init_version + 1,163163+ sizeof(variax_init_version) - 1) == 0) {164164+ variax_startup3(variax);165165+ } else if (memcmp(buf + 1, variax_init_done + 1,166166+ sizeof(variax_init_done) - 1) == 0) {167167+ /* notify of complete initialization: */168168+ variax_startup4((unsigned long)variax);242169 }243170244171 break;···349256 if (ret)350257 return ret;351258352352- variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = value ? 1 : 0;353353- line6_send_raw_message_async(&variax->line6, variax->buffer_activate,354354- sizeof(variax_activate));259259+ variax_activate_async(variax, value ? 1 : 0);355260 return count;356261}357262···408317 struct device_attribute *attr, char *buf)409318{410319 struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev));411411- line6_wait_dump(&variax->dumpreq, 0);320320+ line6_dump_wait_interruptible(&variax->dumpreq);412321 return get_string(buf, variax->model_data.name,413322 sizeof(variax->model_data.name));414323}···420329 struct device_attribute *attr, char *buf)421330{422331 struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev));423423- line6_wait_dump(&variax->dumpreq, 0);332332+ line6_dump_wait_interruptible(&variax->dumpreq);424333 return get_string(buf, variax->bank, sizeof(variax->bank));425334}426335···432341{433342 struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev));434343 int retval;435435- retval = line6_wait_dump(&variax->dumpreq, 0);344344+ retval = line6_dump_wait_interruptible(&variax->dumpreq);436345 if (retval < 0)437346 return retval;438347 memcpy(buf, &variax->model_data.control,···440349 return sizeof(variax->model_data.control);441350}442351443443-#if CREATE_RAW_FILE352352+/*353353+ "read" request on "guitar" special file.354354+*/355355+static ssize_t variax_get_guitar(struct device *dev,356356+ struct device_attribute *attr, char *buf)357357+{358358+ struct usb_line6_variax *variax = usb_get_intfdata(to_usb_interface(dev));359359+ return sprintf(buf, "%s\n", variax->guitar);360360+}361361+362362+#ifdef CONFIG_LINE6_USB_RAW363363+364364+static char *variax_alloc_sysex_buffer(struct usb_line6_variax *variax, int code, int size)365365+{366366+ return line6_alloc_sysex_buffer(&variax->line6, VARIAX_SYSEX_CODE, code, size);367367+}444368445369/*446370 "write" request on "raw" special file.···502396static DEVICE_ATTR(bank, S_IRUGO, variax_get_bank, line6_nop_write);503397static DEVICE_ATTR(dump, S_IRUGO, variax_get_dump, line6_nop_write);504398static DEVICE_ATTR(active, S_IWUGO | S_IRUGO, variax_get_active, variax_set_active);399399+static DEVICE_ATTR(guitar, S_IRUGO, variax_get_guitar, line6_nop_write);505400506506-#if CREATE_RAW_FILE401401+#ifdef CONFIG_LINE6_USB_RAW507402static DEVICE_ATTR(raw, S_IWUGO, line6_nop_read, line6_set_raw);508403static DEVICE_ATTR(raw2, S_IWUGO, line6_nop_read, variax_set_raw2);509404#endif···531424 line6_dumpreq_destruct(&variax->dumpreq);532425533426 kfree(variax->buffer_activate);534534- del_timer_sync(&variax->activate_timer);535427}536428537429/*···546440 CHECK_RETURN(device_create_file(dev, &dev_attr_bank));547441 CHECK_RETURN(device_create_file(dev, &dev_attr_dump));548442 CHECK_RETURN(device_create_file(dev, &dev_attr_active));549549-#if CREATE_RAW_FILE443443+ CHECK_RETURN(device_create_file(dev, &dev_attr_guitar));444444+#ifdef CONFIG_LINE6_USB_RAW550445 CHECK_RETURN(device_create_file(dev, &dev_attr_raw));551446 CHECK_RETURN(device_create_file(dev, &dev_attr_raw2));552447#endif···555448}556449557450/*558558- Init workbench device.451451+ Try to init workbench device.559452*/560560-int variax_init(struct usb_interface *interface,561561- struct usb_line6_variax *variax)453453+static int variax_try_init(struct usb_interface *interface,454454+ struct usb_line6_variax *variax)562455{563456 int err;564457565458 if ((interface == NULL) || (variax == NULL))566459 return -ENODEV;460460+461461+ init_timer(&variax->startup_timer);462462+ INIT_WORK(&variax->startup_work, variax_startup7);567463568464 /* initialize USB buffers: */569465 err = line6_dumpreq_init(&variax->dumpreq, variax_request_model1,···574464575465 if (err < 0) {576466 dev_err(&interface->dev, "Out of memory\n");577577- variax_destruct(interface);578467 return err;579468 }580469···582473583474 if (err < 0) {584475 dev_err(&interface->dev, "Out of memory\n");585585- variax_destruct(interface);586476 return err;587477 }588478···590482591483 if (err < 0) {592484 dev_err(&interface->dev, "Out of memory\n");593593- variax_destruct(interface);594485 return err;595486 }596487···598491599492 if (variax->buffer_activate == NULL) {600493 dev_err(&interface->dev, "Out of memory\n");601601- variax_destruct(interface);602494 return -ENOMEM;603603- }604604-605605- init_timer(&variax->activate_timer);606606-607607- /* create sysfs entries: */608608- err = variax_create_files(0, 0, &interface->dev);609609- if (err < 0) {610610- variax_destruct(interface);611611- return err;612612- }613613-614614- err = variax_create_files2(&interface->dev);615615- if (err < 0) {616616- variax_destruct(interface);617617- return err;618495 }619496620497 /* initialize audio system: */621498 err = line6_init_audio(&variax->line6);622499 if (err < 0) {623623- variax_destruct(interface);624500 return err;625501 }626502627503 /* initialize MIDI subsystem: */628504 err = line6_init_midi(&variax->line6);629505 if (err < 0) {630630- variax_destruct(interface);631506 return err;632507 }633508634634- /* register audio system: */635635- err = line6_register_audio(&variax->line6);509509+ /* initiate startup procedure: */510510+ variax_startup1(variax);511511+ return 0;512512+}513513+514514+/*515515+ Init workbench device (and clean up in case of failure).516516+*/517517+int line6_variax_init(struct usb_interface *interface,518518+ struct usb_line6_variax *variax)519519+{520520+ int err = variax_try_init(interface, variax);521521+636522 if (err < 0) {637523 variax_destruct(interface);638638- return err;639524 }640525641641- variax_activate_delayed(variax, VARIAX_ACTIVATE_DELAY);642642- line6_startup_delayed(&variax->dumpreq, VARIAX_STARTUP_DELAY,643643- variax_startup_timeout, variax);644644- return 0;526526+ return err;645527}646528647529/*648530 Workbench device disconnected.649531*/650650-void variax_disconnect(struct usb_interface *interface)532532+void line6_variax_disconnect(struct usb_interface *interface)651533{652534 struct device *dev;653535···646550647551 if (dev != NULL) {648552 /* remove sysfs entries: */649649- variax_remove_files(0, 0, dev);553553+ line6_variax_remove_files(0, 0, dev);650554 device_remove_file(dev, &dev_attr_model);651555 device_remove_file(dev, &dev_attr_volume);652556 device_remove_file(dev, &dev_attr_tone);···654558 device_remove_file(dev, &dev_attr_bank);655559 device_remove_file(dev, &dev_attr_dump);656560 device_remove_file(dev, &dev_attr_active);657657-#if CREATE_RAW_FILE561561+ device_remove_file(dev, &dev_attr_guitar);562562+#ifdef CONFIG_LINE6_USB_RAW658563 device_remove_file(dev, &dev_attr_raw);659564 device_remove_file(dev, &dev_attr_raw2);660565#endif
+39-25
drivers/staging/line6/variax.h
···11/*22- * Line6 Linux USB driver - 0.8.022+ * Line6 Linux USB driver - 0.9.033 *44- * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at)44+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)55 *66 * This program is free software; you can redistribute it and/or77 * modify it under the terms of the GNU General Public License as···1313#define VARIAX_H141415151616-#include "driver.h"1717-1816#include <linux/spinlock.h>1917#include <linux/usb.h>2018#include <linux/wait.h>2121-2219#include <sound/core.h>23202121+#include "driver.h"2422#include "dumprequest.h"252326242727-#define VARIAX_ACTIVATE_DELAY 102828-#define VARIAX_STARTUP_DELAY 32525+#define VARIAX_STARTUP_DELAY1 10002626+#define VARIAX_STARTUP_DELAY3 1002727+#define VARIAX_STARTUP_DELAY4 100292830293130enum {···353636373738/**3838- Binary Variax model dump3939+ Binary Variax model dump3940*/4041struct variax_model {4142 /**4242- Header information (including program name).4343+ Header information (including program name).4344 */4445 unsigned char name[18];45464647 /**4747- Model parameters.4848+ Model parameters.4849 */4950 unsigned char control[78 * 2];5051};51525253struct usb_line6_variax {5354 /**5454- Generic Line6 USB data.5555+ Generic Line6 USB data.5556 */5657 struct usb_line6 line6;57585859 /**5959- Dump request structure.6060- Append two extra buffers for 3-pass data query.6060+ Dump request structure.6161+ Append two extra buffers for 3-pass data query.6162 */6263 struct line6_dump_request dumpreq; struct line6_dump_reqbuf extrabuf[2];63646465 /**6565- Buffer for activation code.6666+ Buffer for activation code.6667 */6768 unsigned char *buffer_activate;68696970 /**7070- Model number.7171+ Model number.7172 */7273 int model;73747475 /**7575- Current model settings.7676+ Current model settings.7677 */7778 struct variax_model model_data;78797980 /**8080- Name of current model bank.8181+ Name of connected guitar.8282+ */8383+ unsigned char guitar[18];8484+8585+ /**8686+ Name of current model bank.8187 */8288 unsigned char bank[18];83898490 /**8585- Position of volume dial.9191+ Position of volume dial.8692 */8793 int volume;88948995 /**9090- Position of tone control dial.9696+ Position of tone control dial.9197 */9298 int tone;939994100 /**9595- Timer for delayed activation request.101101+ Handler for device initializaton.96102 */9797- struct timer_list activate_timer;103103+ struct work_struct startup_work;104104+105105+ /**106106+ Timer for device initializaton.107107+ */108108+ struct timer_list startup_timer;109109+110110+ /**111111+ Current progress in startup procedure.112112+ */113113+ int startup_progress;98114};99115100116101101-extern void variax_disconnect(struct usb_interface *interface);102102-extern int variax_init(struct usb_interface *interface,103103- struct usb_line6_variax *variax);104104-extern void variax_process_message(struct usb_line6_variax *variax);117117+extern void line6_variax_disconnect(struct usb_interface *interface);118118+extern int line6_variax_init(struct usb_interface *interface,119119+ struct usb_line6_variax *variax);120120+extern void line6_variax_process_message(struct usb_line6_variax *variax);105121106122107123#endif