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