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.8-rc7 512 lines 13 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#include <linux/wait.h> 14#include <sound/control.h> 15 16#include "audio.h" 17#include "capture.h" 18#include "driver.h" 19#include "playback.h" 20#include "pod.h" 21 22#define POD_SYSEX_CODE 3 23#define POD_BYTES_PER_FRAME 6 /* 24bit audio (stereo) */ 24 25/* *INDENT-OFF* */ 26 27enum { 28 POD_SYSEX_SAVE = 0x24, 29 POD_SYSEX_SYSTEM = 0x56, 30 POD_SYSEX_SYSTEMREQ = 0x57, 31 /* POD_SYSEX_UPDATE = 0x6c, */ /* software update! */ 32 POD_SYSEX_STORE = 0x71, 33 POD_SYSEX_FINISH = 0x72, 34 POD_SYSEX_DUMPMEM = 0x73, 35 POD_SYSEX_DUMP = 0x74, 36 POD_SYSEX_DUMPREQ = 0x75 37 /* POD_SYSEX_DUMPMEM2 = 0x76 */ /* dumps entire internal memory of PODxt Pro */ 38}; 39 40enum { 41 POD_monitor_level = 0x04, 42 POD_system_invalid = 0x10000 43}; 44 45/* *INDENT-ON* */ 46 47enum { 48 POD_DUMP_MEMORY = 2 49}; 50 51enum { 52 POD_BUSY_READ, 53 POD_BUSY_WRITE, 54 POD_CHANNEL_DIRTY, 55 POD_SAVE_PRESSED, 56 POD_BUSY_MIDISEND 57}; 58 59static struct snd_ratden pod_ratden = { 60 .num_min = 78125, 61 .num_max = 78125, 62 .num_step = 1, 63 .den = 2 64}; 65 66static struct line6_pcm_properties pod_pcm_properties = { 67 .snd_line6_playback_hw = { 68 .info = (SNDRV_PCM_INFO_MMAP | 69 SNDRV_PCM_INFO_INTERLEAVED | 70 SNDRV_PCM_INFO_BLOCK_TRANSFER | 71 SNDRV_PCM_INFO_MMAP_VALID | 72 SNDRV_PCM_INFO_PAUSE | 73#ifdef CONFIG_PM 74 SNDRV_PCM_INFO_RESUME | 75#endif 76 SNDRV_PCM_INFO_SYNC_START), 77 .formats = SNDRV_PCM_FMTBIT_S24_3LE, 78 .rates = SNDRV_PCM_RATE_KNOT, 79 .rate_min = 39062, 80 .rate_max = 39063, 81 .channels_min = 2, 82 .channels_max = 2, 83 .buffer_bytes_max = 60000, 84 .period_bytes_min = 64, 85 .period_bytes_max = 8192, 86 .periods_min = 1, 87 .periods_max = 1024}, 88 .snd_line6_capture_hw = { 89 .info = (SNDRV_PCM_INFO_MMAP | 90 SNDRV_PCM_INFO_INTERLEAVED | 91 SNDRV_PCM_INFO_BLOCK_TRANSFER | 92 SNDRV_PCM_INFO_MMAP_VALID | 93#ifdef CONFIG_PM 94 SNDRV_PCM_INFO_RESUME | 95#endif 96 SNDRV_PCM_INFO_SYNC_START), 97 .formats = SNDRV_PCM_FMTBIT_S24_3LE, 98 .rates = SNDRV_PCM_RATE_KNOT, 99 .rate_min = 39062, 100 .rate_max = 39063, 101 .channels_min = 2, 102 .channels_max = 2, 103 .buffer_bytes_max = 60000, 104 .period_bytes_min = 64, 105 .period_bytes_max = 8192, 106 .periods_min = 1, 107 .periods_max = 1024}, 108 .snd_line6_rates = { 109 .nrats = 1, 110 .rats = &pod_ratden}, 111 .bytes_per_frame = POD_BYTES_PER_FRAME 112}; 113 114static const char pod_version_header[] = { 115 0xf2, 0x7e, 0x7f, 0x06, 0x02 116}; 117 118/* forward declarations: */ 119static void pod_startup2(unsigned long data); 120static void pod_startup3(struct usb_line6_pod *pod); 121 122static char *pod_alloc_sysex_buffer(struct usb_line6_pod *pod, int code, 123 int size) 124{ 125 return line6_alloc_sysex_buffer(&pod->line6, POD_SYSEX_CODE, code, 126 size); 127} 128 129/* 130 Process a completely received message. 131*/ 132void line6_pod_process_message(struct usb_line6_pod *pod) 133{ 134 const unsigned char *buf = pod->line6.buffer_message; 135 136 /* filter messages by type */ 137 switch (buf[0] & 0xf0) { 138 case LINE6_PARAM_CHANGE: 139 case LINE6_PROGRAM_CHANGE: 140 case LINE6_SYSEX_BEGIN: 141 break; /* handle these further down */ 142 143 default: 144 return; /* ignore all others */ 145 } 146 147 /* process all remaining messages */ 148 switch (buf[0]) { 149 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_DEVICE: 150 case LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST: 151 break; 152 153 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_DEVICE: 154 case LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST: 155 break; 156 157 case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_DEVICE: 158 case LINE6_SYSEX_BEGIN | LINE6_CHANNEL_UNKNOWN: 159 if (memcmp(buf + 1, line6_midi_id, sizeof(line6_midi_id)) == 0) { 160 switch (buf[5]) { 161 case POD_SYSEX_DUMP: 162 break; 163 164 case POD_SYSEX_SYSTEM:{ 165 short value = 166 ((int)buf[7] << 12) | ((int)buf[8] 167 << 8) | 168 ((int)buf[9] << 4) | (int)buf[10]; 169 170 if (buf[6] == POD_monitor_level) 171 pod->monitor_level = value; 172 break; 173 } 174 175 case POD_SYSEX_FINISH: 176 /* do we need to respond to this? */ 177 break; 178 179 case POD_SYSEX_SAVE: 180 break; 181 182 case POD_SYSEX_STORE: 183 dev_dbg(pod->line6.ifcdev, 184 "message %02X not yet implemented\n", 185 buf[5]); 186 break; 187 188 default: 189 dev_dbg(pod->line6.ifcdev, 190 "unknown sysex message %02X\n", 191 buf[5]); 192 } 193 } else 194 if (memcmp 195 (buf, pod_version_header, 196 sizeof(pod_version_header)) == 0) { 197 pod->firmware_version = 198 buf[13] * 100 + buf[14] * 10 + buf[15]; 199 pod->device_id = 200 ((int)buf[8] << 16) | ((int)buf[9] << 8) | (int) 201 buf[10]; 202 pod_startup3(pod); 203 } else 204 dev_dbg(pod->line6.ifcdev, "unknown sysex header\n"); 205 206 break; 207 208 case LINE6_SYSEX_END: 209 break; 210 211 default: 212 dev_dbg(pod->line6.ifcdev, "POD: unknown message %02X\n", 213 buf[0]); 214 } 215} 216 217/* 218 Transmit PODxt Pro control parameter. 219*/ 220void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param, 221 u8 value) 222{ 223 line6_transmit_parameter(&pod->line6, param, value); 224} 225 226/* 227 Send system parameter (from integer). 228*/ 229static int pod_set_system_param_int(struct usb_line6_pod *pod, int value, 230 int code) 231{ 232 char *sysex; 233 static const int size = 5; 234 235 sysex = pod_alloc_sysex_buffer(pod, POD_SYSEX_SYSTEM, size); 236 if (!sysex) 237 return -ENOMEM; 238 sysex[SYSEX_DATA_OFS] = code; 239 sysex[SYSEX_DATA_OFS + 1] = (value >> 12) & 0x0f; 240 sysex[SYSEX_DATA_OFS + 2] = (value >> 8) & 0x0f; 241 sysex[SYSEX_DATA_OFS + 3] = (value >> 4) & 0x0f; 242 sysex[SYSEX_DATA_OFS + 4] = (value) & 0x0f; 243 line6_send_sysex_message(&pod->line6, sysex, size); 244 kfree(sysex); 245 return 0; 246} 247 248/* 249 "read" request on "serial_number" special file. 250*/ 251static ssize_t pod_get_serial_number(struct device *dev, 252 struct device_attribute *attr, char *buf) 253{ 254 struct usb_interface *interface = to_usb_interface(dev); 255 struct usb_line6_pod *pod = usb_get_intfdata(interface); 256 return sprintf(buf, "%d\n", pod->serial_number); 257} 258 259/* 260 "read" request on "firmware_version" special file. 261*/ 262static ssize_t pod_get_firmware_version(struct device *dev, 263 struct device_attribute *attr, 264 char *buf) 265{ 266 struct usb_interface *interface = to_usb_interface(dev); 267 struct usb_line6_pod *pod = usb_get_intfdata(interface); 268 return sprintf(buf, "%d.%02d\n", pod->firmware_version / 100, 269 pod->firmware_version % 100); 270} 271 272/* 273 "read" request on "device_id" special file. 274*/ 275static ssize_t pod_get_device_id(struct device *dev, 276 struct device_attribute *attr, char *buf) 277{ 278 struct usb_interface *interface = to_usb_interface(dev); 279 struct usb_line6_pod *pod = usb_get_intfdata(interface); 280 return sprintf(buf, "%d\n", pod->device_id); 281} 282 283/* 284 POD startup procedure. 285 This is a sequence of functions with special requirements (e.g., must 286 not run immediately after initialization, must not run in interrupt 287 context). After the last one has finished, the device is ready to use. 288*/ 289 290static void pod_startup1(struct usb_line6_pod *pod) 291{ 292 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_INIT); 293 294 /* delay startup procedure: */ 295 line6_start_timer(&pod->startup_timer, POD_STARTUP_DELAY, pod_startup2, 296 (unsigned long)pod); 297} 298 299static void pod_startup2(unsigned long data) 300{ 301 struct usb_line6_pod *pod = (struct usb_line6_pod *)data; 302 struct usb_line6 *line6 = &pod->line6; 303 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_VERSIONREQ); 304 305 /* request firmware version: */ 306 line6_version_request_async(line6); 307} 308 309static void pod_startup3(struct usb_line6_pod *pod) 310{ 311 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_WORKQUEUE); 312 313 /* schedule work for global work queue: */ 314 schedule_work(&pod->startup_work); 315} 316 317static void pod_startup4(struct work_struct *work) 318{ 319 struct usb_line6_pod *pod = 320 container_of(work, struct usb_line6_pod, startup_work); 321 struct usb_line6 *line6 = &pod->line6; 322 323 CHECK_STARTUP_PROGRESS(pod->startup_progress, POD_STARTUP_SETUP); 324 325 /* serial number: */ 326 line6_read_serial_number(&pod->line6, &pod->serial_number); 327 328 /* ALSA audio interface: */ 329 line6_register_audio(line6); 330} 331 332/* POD special files: */ 333static DEVICE_ATTR(device_id, S_IRUGO, pod_get_device_id, line6_nop_write); 334static DEVICE_ATTR(firmware_version, S_IRUGO, pod_get_firmware_version, 335 line6_nop_write); 336static DEVICE_ATTR(serial_number, S_IRUGO, pod_get_serial_number, 337 line6_nop_write); 338 339/* control info callback */ 340static int snd_pod_control_monitor_info(struct snd_kcontrol *kcontrol, 341 struct snd_ctl_elem_info *uinfo) 342{ 343 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 344 uinfo->count = 1; 345 uinfo->value.integer.min = 0; 346 uinfo->value.integer.max = 65535; 347 return 0; 348} 349 350/* control get callback */ 351static int snd_pod_control_monitor_get(struct snd_kcontrol *kcontrol, 352 struct snd_ctl_elem_value *ucontrol) 353{ 354 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); 355 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6; 356 ucontrol->value.integer.value[0] = pod->monitor_level; 357 return 0; 358} 359 360/* control put callback */ 361static int snd_pod_control_monitor_put(struct snd_kcontrol *kcontrol, 362 struct snd_ctl_elem_value *ucontrol) 363{ 364 struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol); 365 struct usb_line6_pod *pod = (struct usb_line6_pod *)line6pcm->line6; 366 367 if (ucontrol->value.integer.value[0] == pod->monitor_level) 368 return 0; 369 370 pod->monitor_level = ucontrol->value.integer.value[0]; 371 pod_set_system_param_int(pod, ucontrol->value.integer.value[0], 372 POD_monitor_level); 373 return 1; 374} 375 376/* control definition */ 377static struct snd_kcontrol_new pod_control_monitor = { 378 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 379 .name = "Monitor Playback Volume", 380 .index = 0, 381 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 382 .info = snd_pod_control_monitor_info, 383 .get = snd_pod_control_monitor_get, 384 .put = snd_pod_control_monitor_put 385}; 386 387/* 388 POD destructor. 389*/ 390static void pod_destruct(struct usb_interface *interface) 391{ 392 struct usb_line6_pod *pod = usb_get_intfdata(interface); 393 394 if (pod == NULL) 395 return; 396 line6_cleanup_audio(&pod->line6); 397 398 del_timer(&pod->startup_timer); 399 cancel_work_sync(&pod->startup_work); 400} 401 402/* 403 Create sysfs entries. 404*/ 405static int pod_create_files2(struct device *dev) 406{ 407 int err; 408 409 CHECK_RETURN(device_create_file(dev, &dev_attr_device_id)); 410 CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version)); 411 CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number)); 412 return 0; 413} 414 415/* 416 Try to init POD device. 417*/ 418static int pod_try_init(struct usb_interface *interface, 419 struct usb_line6_pod *pod) 420{ 421 int err; 422 struct usb_line6 *line6 = &pod->line6; 423 424 init_timer(&pod->startup_timer); 425 INIT_WORK(&pod->startup_work, pod_startup4); 426 427 if ((interface == NULL) || (pod == NULL)) 428 return -ENODEV; 429 430 /* create sysfs entries: */ 431 err = pod_create_files2(&interface->dev); 432 if (err < 0) 433 return err; 434 435 /* initialize audio system: */ 436 err = line6_init_audio(line6); 437 if (err < 0) 438 return err; 439 440 /* initialize MIDI subsystem: */ 441 err = line6_init_midi(line6); 442 if (err < 0) 443 return err; 444 445 /* initialize PCM subsystem: */ 446 err = line6_init_pcm(line6, &pod_pcm_properties); 447 if (err < 0) 448 return err; 449 450 /* register monitor control: */ 451 err = snd_ctl_add(line6->card, 452 snd_ctl_new1(&pod_control_monitor, line6->line6pcm)); 453 if (err < 0) 454 return err; 455 456 /* 457 When the sound card is registered at this point, the PODxt Live 458 displays "Invalid Code Error 07", so we do it later in the event 459 handler. 460 */ 461 462 if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) { 463 pod->monitor_level = POD_system_invalid; 464 465 /* initiate startup procedure: */ 466 pod_startup1(pod); 467 } 468 469 return 0; 470} 471 472/* 473 Init POD device (and clean up in case of failure). 474*/ 475int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod) 476{ 477 int err = pod_try_init(interface, pod); 478 479 if (err < 0) 480 pod_destruct(interface); 481 482 return err; 483} 484 485/* 486 POD device disconnected. 487*/ 488void line6_pod_disconnect(struct usb_interface *interface) 489{ 490 struct usb_line6_pod *pod; 491 492 if (interface == NULL) 493 return; 494 pod = usb_get_intfdata(interface); 495 496 if (pod != NULL) { 497 struct snd_line6_pcm *line6pcm = pod->line6.line6pcm; 498 struct device *dev = &interface->dev; 499 500 if (line6pcm != NULL) 501 line6_pcm_disconnect(line6pcm); 502 503 if (dev != NULL) { 504 /* remove sysfs entries: */ 505 device_remove_file(dev, &dev_attr_device_id); 506 device_remove_file(dev, &dev_attr_firmware_version); 507 device_remove_file(dev, &dev_attr_serial_number); 508 } 509 } 510 511 pod_destruct(interface); 512}