toneport.c revision 6353773b5230514d4f1d3dc98a84a72e3a954e87
1/* 2 * Line6 Linux USB driver - 0.8.0 3 * 4 * Copyright (C) 2004-2009 Markus Grabner (grabner@icg.tugraz.at) 5 * Emil Myhrman (emil.myhrman@gmail.com) 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation, version 2. 10 * 11 */ 12 13#include "driver.h" 14 15#include "audio.h" 16#include "capture.h" 17#include "playback.h" 18#include "toneport.h" 19 20 21static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2); 22 23 24static struct snd_ratden toneport_ratden = { 25 .num_min = 44100, 26 .num_max = 44100, 27 .num_step = 1, 28 .den = 1 29}; 30 31static struct line6_pcm_properties toneport_pcm_properties = { 32 .snd_line6_playback_hw = { 33 .info = (SNDRV_PCM_INFO_MMAP | 34 SNDRV_PCM_INFO_INTERLEAVED | 35 SNDRV_PCM_INFO_BLOCK_TRANSFER | 36 SNDRV_PCM_INFO_MMAP_VALID | 37 SNDRV_PCM_INFO_PAUSE | 38 SNDRV_PCM_INFO_SYNC_START), 39 .formats = SNDRV_PCM_FMTBIT_S16_LE, 40 .rates = SNDRV_PCM_RATE_KNOT, 41 .rate_min = 44100, 42 .rate_max = 44100, 43 .channels_min = 2, 44 .channels_max = 2, 45 .buffer_bytes_max = 60000, 46 .period_bytes_min = 180 * 4, 47 .period_bytes_max = 8192, 48 .periods_min = 1, 49 .periods_max = 1024 50 }, 51 .snd_line6_capture_hw = { 52 .info = (SNDRV_PCM_INFO_MMAP | 53 SNDRV_PCM_INFO_INTERLEAVED | 54 SNDRV_PCM_INFO_BLOCK_TRANSFER | 55 SNDRV_PCM_INFO_MMAP_VALID | 56 SNDRV_PCM_INFO_SYNC_START), 57 .formats = SNDRV_PCM_FMTBIT_S16_LE, 58 .rates = SNDRV_PCM_RATE_KNOT, 59 .rate_min = 44100, 60 .rate_max = 44100, 61 .channels_min = 2, 62 .channels_max = 2, 63 .buffer_bytes_max = 60000, 64 .period_bytes_min = 188 * 4, 65 .period_bytes_max = 8192, 66 .periods_min = 1, 67 .periods_max = 1024 68 }, 69 .snd_line6_rates = { 70 .nrats = 1, 71 .rats = &toneport_ratden 72 }, 73 .bytes_per_frame = 4 74}; 75 76/* 77 For the led on Guitarport. 78 Brightness goes from 0x00 to 0x26. Set a value above this to have led 79 blink. 80 (void cmd_0x02(byte red, byte green) 81*/ 82static int led_red = 0x00; 83static int led_green = 0x26; 84 85static void toneport_update_led(struct device *dev) 86{ 87 struct usb_interface *interface = to_usb_interface(dev); 88 struct usb_line6_toneport *tp = usb_get_intfdata(interface); 89 struct usb_line6 *line6; 90 91 if (!tp) 92 return; 93 94 line6 = &tp->line6; 95 if (line6) 96 toneport_send_cmd(line6->usbdev, (led_red << 8) | 0x0002, 97 led_green); 98} 99 100static ssize_t toneport_set_led_red(struct device *dev, 101 struct device_attribute *attr, 102 const char *buf, size_t count) 103{ 104 char *c; 105 led_red = simple_strtol(buf, &c, 10); 106 toneport_update_led(dev); 107 return count; 108} 109 110static ssize_t toneport_set_led_green(struct device *dev, 111 struct device_attribute *attr, 112 const char *buf, size_t count) 113{ 114 char *c; 115 led_green = simple_strtol(buf, &c, 10); 116 toneport_update_led(dev); 117 return count; 118} 119 120static DEVICE_ATTR(led_red, S_IWUGO | S_IRUGO, line6_nop_read, toneport_set_led_red); 121static DEVICE_ATTR(led_green, S_IWUGO | S_IRUGO, line6_nop_read, toneport_set_led_green); 122 123 124static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2) 125{ 126 int ret; 127 128 ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, 129 USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 130 cmd1, cmd2, NULL, 0, LINE6_TIMEOUT * HZ); 131 132 if (ret < 0) { 133 err("send failed (error %d)\n", ret); 134 return ret; 135 } 136 137 return 0; 138} 139 140/* 141 Toneport destructor. 142*/ 143static void toneport_destruct(struct usb_interface *interface) 144{ 145 struct usb_line6_toneport *toneport = usb_get_intfdata(interface); 146 struct usb_line6 *line6; 147 148 if (toneport == NULL) 149 return; 150 line6 = &toneport->line6; 151 if (line6 == NULL) 152 return; 153 line6_cleanup_audio(line6); 154} 155 156/* 157 Init Toneport device. 158*/ 159int toneport_init(struct usb_interface *interface, 160 struct usb_line6_toneport *toneport) 161{ 162 int err, ticks; 163 struct usb_line6 *line6 = &toneport->line6; 164 struct usb_device *usbdev; 165 166 if ((interface == NULL) || (toneport == NULL)) 167 return -ENODEV; 168 169 /* initialize audio system: */ 170 err = line6_init_audio(line6); 171 if (err < 0) { 172 toneport_destruct(interface); 173 return err; 174 } 175 176 /* initialize PCM subsystem: */ 177 err = line6_init_pcm(line6, &toneport_pcm_properties); 178 if (err < 0) { 179 toneport_destruct(interface); 180 return err; 181 } 182 183 /* register audio system: */ 184 err = line6_register_audio(line6); 185 if (err < 0) { 186 toneport_destruct(interface); 187 return err; 188 } 189 190 usbdev = line6->usbdev; 191 line6_read_serial_number(line6, &toneport->serial_number); 192 line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1); 193 194 /* sync time on device with host: */ 195 ticks = (int)get_seconds(); 196 line6_write_data(line6, 0x80c6, &ticks, 4); 197 198 /* 199 seems to work without the first two... 200 */ 201 /* toneport_send_cmd(usbdev, 0x0201, 0x0002); */ 202 /* toneport_send_cmd(usbdev, 0x0801, 0x0000); */ 203 /* only one that works for me; on GP, TP might be different? */ 204 toneport_send_cmd(usbdev, 0x0301, 0x0000); 205 206 if (usbdev->descriptor.idProduct != LINE6_DEVID_GUITARPORT) { 207 CHECK_RETURN(device_create_file(&interface->dev, &dev_attr_led_red)); 208 CHECK_RETURN(device_create_file(&interface->dev, &dev_attr_led_green)); 209 toneport_update_led(&usbdev->dev); 210 } 211 212 return 0; 213} 214 215/* 216 Toneport device disconnected. 217*/ 218void toneport_disconnect(struct usb_interface *interface) 219{ 220 struct usb_line6_toneport *toneport; 221 222 if (interface == NULL) 223 return; 224 toneport = usb_get_intfdata(interface); 225 226 if (toneport->line6.usbdev->descriptor.idProduct != LINE6_DEVID_GUITARPORT) { 227 device_remove_file(&interface->dev, &dev_attr_led_red); 228 device_remove_file(&interface->dev, &dev_attr_led_green); 229 } 230 231 if (toneport != NULL) { 232 struct snd_line6_pcm *line6pcm = toneport->line6.line6pcm; 233 234 if (line6pcm != NULL) { 235 unlink_wait_clear_audio_out_urbs(line6pcm); 236 unlink_wait_clear_audio_in_urbs(line6pcm); 237 } 238 } 239 240 toneport_destruct(interface); 241} 242