Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.18-rc2 235 lines 6.0 kB view raw
1/* 2 * Line6 Linux USB driver - 0.9.1beta 3 * 4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation, version 2. 9 * 10 */ 11 12#include <linux/slab.h> 13 14#include "audio.h" 15#include "driver.h" 16#include "variax.h" 17 18#define VARIAX_OFFSET_ACTIVATE 7 19 20/* 21 This message is sent by the device during initialization and identifies 22 the connected guitar version. 23*/ 24static const char variax_init_version[] = { 25 0xf0, 0x7e, 0x7f, 0x06, 0x02, 0x00, 0x01, 0x0c, 26 0x07, 0x00, 0x00, 0x00 27}; 28 29/* 30 This message is the last one sent by the device during initialization. 31*/ 32static const char variax_init_done[] = { 33 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x6b 34}; 35 36static const char variax_activate[] = { 37 0xf0, 0x00, 0x01, 0x0c, 0x07, 0x00, 0x2a, 0x01, 38 0xf7 39}; 40 41/* forward declarations: */ 42static void variax_startup2(unsigned long data); 43static void variax_startup4(unsigned long data); 44static void variax_startup5(unsigned long data); 45 46static void variax_activate_async(struct usb_line6_variax *variax, int a) 47{ 48 variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = a; 49 line6_send_raw_message_async(&variax->line6, variax->buffer_activate, 50 sizeof(variax_activate)); 51} 52 53/* 54 Variax startup procedure. 55 This is a sequence of functions with special requirements (e.g., must 56 not run immediately after initialization, must not run in interrupt 57 context). After the last one has finished, the device is ready to use. 58*/ 59 60static void variax_startup1(struct usb_line6_variax *variax) 61{ 62 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_INIT); 63 64 /* delay startup procedure: */ 65 line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1, 66 variax_startup2, (unsigned long)variax); 67} 68 69static void variax_startup2(unsigned long data) 70{ 71 struct usb_line6_variax *variax = (struct usb_line6_variax *)data; 72 struct usb_line6 *line6 = &variax->line6; 73 74 /* schedule another startup procedure until startup is complete: */ 75 if (variax->startup_progress >= VARIAX_STARTUP_LAST) 76 return; 77 78 variax->startup_progress = VARIAX_STARTUP_VERSIONREQ; 79 line6_start_timer(&variax->startup_timer1, VARIAX_STARTUP_DELAY1, 80 variax_startup2, (unsigned long)variax); 81 82 /* request firmware version: */ 83 line6_version_request_async(line6); 84} 85 86static void variax_startup3(struct usb_line6_variax *variax) 87{ 88 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_WAIT); 89 90 /* delay startup procedure: */ 91 line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY3, 92 variax_startup4, (unsigned long)variax); 93} 94 95static void variax_startup4(unsigned long data) 96{ 97 struct usb_line6_variax *variax = (struct usb_line6_variax *)data; 98 99 CHECK_STARTUP_PROGRESS(variax->startup_progress, 100 VARIAX_STARTUP_ACTIVATE); 101 102 /* activate device: */ 103 variax_activate_async(variax, 1); 104 line6_start_timer(&variax->startup_timer2, VARIAX_STARTUP_DELAY4, 105 variax_startup5, (unsigned long)variax); 106} 107 108static void variax_startup5(unsigned long data) 109{ 110 struct usb_line6_variax *variax = (struct usb_line6_variax *)data; 111 112 CHECK_STARTUP_PROGRESS(variax->startup_progress, 113 VARIAX_STARTUP_WORKQUEUE); 114 115 /* schedule work for global work queue: */ 116 schedule_work(&variax->startup_work); 117} 118 119static void variax_startup6(struct work_struct *work) 120{ 121 struct usb_line6_variax *variax = 122 container_of(work, struct usb_line6_variax, startup_work); 123 124 CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP); 125 126 /* ALSA audio interface: */ 127 line6_register_audio(&variax->line6); 128} 129 130/* 131 Process a completely received message. 132*/ 133void line6_variax_process_message(struct usb_line6_variax *variax) 134{ 135 const unsigned char *buf = variax->line6.buffer_message; 136 137 switch (buf[0]) { 138 case LINE6_RESET: 139 dev_info(variax->line6.ifcdev, "VARIAX reset\n"); 140 break; 141 142 case LINE6_SYSEX_BEGIN: 143 if (memcmp(buf + 1, variax_init_version + 1, 144 sizeof(variax_init_version) - 1) == 0) { 145 variax_startup3(variax); 146 } else if (memcmp(buf + 1, variax_init_done + 1, 147 sizeof(variax_init_done) - 1) == 0) { 148 /* notify of complete initialization: */ 149 variax_startup4((unsigned long)variax); 150 } 151 break; 152 } 153} 154 155/* 156 Variax destructor. 157*/ 158static void variax_destruct(struct usb_interface *interface) 159{ 160 struct usb_line6_variax *variax = usb_get_intfdata(interface); 161 162 if (variax == NULL) 163 return; 164 line6_cleanup_audio(&variax->line6); 165 166 del_timer(&variax->startup_timer1); 167 del_timer(&variax->startup_timer2); 168 cancel_work_sync(&variax->startup_work); 169 170 kfree(variax->buffer_activate); 171} 172 173/* 174 Try to init workbench device. 175*/ 176static int variax_try_init(struct usb_interface *interface, 177 struct usb_line6_variax *variax) 178{ 179 int err; 180 181 init_timer(&variax->startup_timer1); 182 init_timer(&variax->startup_timer2); 183 INIT_WORK(&variax->startup_work, variax_startup6); 184 185 if ((interface == NULL) || (variax == NULL)) 186 return -ENODEV; 187 188 /* initialize USB buffers: */ 189 variax->buffer_activate = kmemdup(variax_activate, 190 sizeof(variax_activate), GFP_KERNEL); 191 192 if (variax->buffer_activate == NULL) { 193 dev_err(&interface->dev, "Out of memory\n"); 194 return -ENOMEM; 195 } 196 197 /* initialize audio system: */ 198 err = line6_init_audio(&variax->line6); 199 if (err < 0) 200 return err; 201 202 /* initialize MIDI subsystem: */ 203 err = line6_init_midi(&variax->line6); 204 if (err < 0) 205 return err; 206 207 /* initiate startup procedure: */ 208 variax_startup1(variax); 209 return 0; 210} 211 212/* 213 Init workbench device (and clean up in case of failure). 214*/ 215int line6_variax_init(struct usb_interface *interface, 216 struct usb_line6_variax *variax) 217{ 218 int err = variax_try_init(interface, variax); 219 220 if (err < 0) 221 variax_destruct(interface); 222 223 return err; 224} 225 226/* 227 Workbench device disconnected. 228*/ 229void line6_variax_disconnect(struct usb_interface *interface) 230{ 231 if (interface == NULL) 232 return; 233 234 variax_destruct(interface); 235}