2 * Line 6 Linux USB driver
4 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
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.
12 #include <linux/slab.h>
13 #include <sound/core.h>
14 #include <sound/pcm.h>
15 #include <sound/pcm_params.h>
22 Find a free URB and submit it.
23 must be called in line6pcm->in.lock context
25 static int submit_audio_in_urb(struct snd_line6_pcm
*line6pcm
)
33 find_first_zero_bit(&line6pcm
->in
.active_urbs
, LINE6_ISO_BUFFERS
);
35 if (index
< 0 || index
>= LINE6_ISO_BUFFERS
) {
36 dev_err(line6pcm
->line6
->ifcdev
, "no free URB found\n");
40 urb_in
= line6pcm
->in
.urbs
[index
];
43 for (i
= 0; i
< LINE6_ISO_PACKETS
; ++i
) {
44 struct usb_iso_packet_descriptor
*fin
=
45 &urb_in
->iso_frame_desc
[i
];
46 fin
->offset
= urb_size
;
47 fin
->length
= line6pcm
->max_packet_size
;
48 urb_size
+= line6pcm
->max_packet_size
;
51 urb_in
->transfer_buffer
=
53 index
* LINE6_ISO_PACKETS
* line6pcm
->max_packet_size
;
54 urb_in
->transfer_buffer_length
= urb_size
;
55 urb_in
->context
= line6pcm
;
57 ret
= usb_submit_urb(urb_in
, GFP_ATOMIC
);
60 set_bit(index
, &line6pcm
->in
.active_urbs
);
62 dev_err(line6pcm
->line6
->ifcdev
,
63 "URB in #%d submission failed (%d)\n", index
, ret
);
69 Submit all currently available capture URBs.
70 must be called in line6pcm->in.lock context
72 int line6_submit_audio_in_all_urbs(struct snd_line6_pcm
*line6pcm
)
76 for (i
= 0; i
< LINE6_ISO_BUFFERS
; ++i
) {
77 ret
= submit_audio_in_urb(line6pcm
);
86 Copy data into ALSA capture buffer.
88 void line6_capture_copy(struct snd_line6_pcm
*line6pcm
, char *fbuf
, int fsize
)
90 struct snd_pcm_substream
*substream
=
91 get_substream(line6pcm
, SNDRV_PCM_STREAM_CAPTURE
);
92 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
93 const int bytes_per_frame
= line6pcm
->properties
->bytes_per_frame
;
94 int frames
= fsize
/ bytes_per_frame
;
99 if (line6pcm
->in
.pos_done
+ frames
> runtime
->buffer_size
) {
101 The transferred area goes over buffer boundary,
102 copy two separate chunks.
106 len
= runtime
->buffer_size
- line6pcm
->in
.pos_done
;
109 memcpy(runtime
->dma_area
+
110 line6pcm
->in
.pos_done
* bytes_per_frame
, fbuf
,
111 len
* bytes_per_frame
);
112 memcpy(runtime
->dma_area
, fbuf
+ len
* bytes_per_frame
,
113 (frames
- len
) * bytes_per_frame
);
115 /* this is somewhat paranoid */
116 dev_err(line6pcm
->line6
->ifcdev
,
117 "driver bug: len = %d\n", len
);
120 /* copy single chunk */
121 memcpy(runtime
->dma_area
+
122 line6pcm
->in
.pos_done
* bytes_per_frame
, fbuf
, fsize
);
125 line6pcm
->in
.pos_done
+= frames
;
126 if (line6pcm
->in
.pos_done
>= runtime
->buffer_size
)
127 line6pcm
->in
.pos_done
-= runtime
->buffer_size
;
130 void line6_capture_check_period(struct snd_line6_pcm
*line6pcm
, int length
)
132 struct snd_pcm_substream
*substream
=
133 get_substream(line6pcm
, SNDRV_PCM_STREAM_CAPTURE
);
135 line6pcm
->in
.bytes
+= length
;
136 if (line6pcm
->in
.bytes
>= line6pcm
->in
.period
) {
137 line6pcm
->in
.bytes
%= line6pcm
->in
.period
;
138 spin_unlock(&line6pcm
->in
.lock
);
139 snd_pcm_period_elapsed(substream
);
140 spin_lock(&line6pcm
->in
.lock
);
145 * Callback for completed capture URB.
147 static void audio_in_callback(struct urb
*urb
)
149 int i
, index
, length
= 0, shutdown
= 0;
152 struct snd_line6_pcm
*line6pcm
= (struct snd_line6_pcm
*)urb
->context
;
154 line6pcm
->in
.last_frame
= urb
->start_frame
;
156 /* find index of URB */
157 for (index
= 0; index
< LINE6_ISO_BUFFERS
; ++index
)
158 if (urb
== line6pcm
->in
.urbs
[index
])
161 spin_lock_irqsave(&line6pcm
->in
.lock
, flags
);
163 for (i
= 0; i
< LINE6_ISO_PACKETS
; ++i
) {
166 struct usb_iso_packet_descriptor
*fin
= &urb
->iso_frame_desc
[i
];
168 if (fin
->status
== -EXDEV
) {
173 fbuf
= urb
->transfer_buffer
+ fin
->offset
;
174 fsize
= fin
->actual_length
;
176 if (fsize
> line6pcm
->max_packet_size
) {
177 dev_err(line6pcm
->line6
->ifcdev
,
178 "driver and/or device bug: packet too large (%d > %d)\n",
179 fsize
, line6pcm
->max_packet_size
);
184 /* the following assumes LINE6_ISO_PACKETS == 1: */
185 line6pcm
->prev_fbuf
= fbuf
;
186 line6pcm
->prev_fsize
= fsize
;
188 if (!test_bit(LINE6_STREAM_IMPULSE
, &line6pcm
->in
.running
) &&
189 test_bit(LINE6_STREAM_PCM
, &line6pcm
->in
.running
) &&
191 line6_capture_copy(line6pcm
, fbuf
, fsize
);
194 clear_bit(index
, &line6pcm
->in
.active_urbs
);
196 if (test_and_clear_bit(index
, &line6pcm
->in
.unlink_urbs
))
200 submit_audio_in_urb(line6pcm
);
202 if (!test_bit(LINE6_STREAM_IMPULSE
, &line6pcm
->in
.running
) &&
203 test_bit(LINE6_STREAM_PCM
, &line6pcm
->in
.running
))
204 line6_capture_check_period(line6pcm
, length
);
207 spin_unlock_irqrestore(&line6pcm
->in
.lock
, flags
);
210 /* open capture callback */
211 static int snd_line6_capture_open(struct snd_pcm_substream
*substream
)
214 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
215 struct snd_line6_pcm
*line6pcm
= snd_pcm_substream_chip(substream
);
217 err
= snd_pcm_hw_constraint_ratdens(runtime
, 0,
218 SNDRV_PCM_HW_PARAM_RATE
,
219 &line6pcm
->properties
->rates
);
223 runtime
->hw
= line6pcm
->properties
->capture_hw
;
227 /* close capture callback */
228 static int snd_line6_capture_close(struct snd_pcm_substream
*substream
)
233 /* capture operators */
234 struct snd_pcm_ops snd_line6_capture_ops
= {
235 .open
= snd_line6_capture_open
,
236 .close
= snd_line6_capture_close
,
237 .ioctl
= snd_pcm_lib_ioctl
,
238 .hw_params
= snd_line6_hw_params
,
239 .hw_free
= snd_line6_hw_free
,
240 .prepare
= snd_line6_prepare
,
241 .trigger
= snd_line6_trigger
,
242 .pointer
= snd_line6_pointer
,
245 int line6_create_audio_in_urbs(struct snd_line6_pcm
*line6pcm
)
247 struct usb_line6
*line6
= line6pcm
->line6
;
250 /* create audio URBs and fill in constant values: */
251 for (i
= 0; i
< LINE6_ISO_BUFFERS
; ++i
) {
254 /* URB for audio in: */
255 urb
= line6pcm
->in
.urbs
[i
] =
256 usb_alloc_urb(LINE6_ISO_PACKETS
, GFP_KERNEL
);
261 urb
->dev
= line6
->usbdev
;
263 usb_rcvisocpipe(line6
->usbdev
,
264 line6
->properties
->ep_audio_r
&
265 USB_ENDPOINT_NUMBER_MASK
);
266 urb
->transfer_flags
= URB_ISO_ASAP
;
267 urb
->start_frame
= -1;
268 urb
->number_of_packets
= LINE6_ISO_PACKETS
;
269 urb
->interval
= LINE6_ISO_INTERVAL
;
270 urb
->error_count
= 0;
271 urb
->complete
= audio_in_callback
;