Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
capture.c
Go to the documentation of this file.
1 /*
2  * Line6 Linux USB driver - 0.9.1beta
3  *
4  * Copyright (C) 2004-2010 Markus Grabner ([email protected])
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 <sound/core.h>
14 #include <sound/pcm.h>
15 #include <sound/pcm_params.h>
16 
17 #include "audio.h"
18 #include "capture.h"
19 #include "driver.h"
20 #include "pcm.h"
21 #include "pod.h"
22 
23 /*
24  Find a free URB and submit it.
25 */
26 static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
27 {
28  int index;
29  unsigned long flags;
30  int i, urb_size;
31  int ret;
32  struct urb *urb_in;
33 
34  spin_lock_irqsave(&line6pcm->lock_audio_in, flags);
35  index =
37 
38  if (index < 0 || index >= LINE6_ISO_BUFFERS) {
39  spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags);
40  dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
41  return -EINVAL;
42  }
43 
44  urb_in = line6pcm->urb_audio_in[index];
45  urb_size = 0;
46 
47  for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
48  struct usb_iso_packet_descriptor *fin =
49  &urb_in->iso_frame_desc[i];
50  fin->offset = urb_size;
51  fin->length = line6pcm->max_packet_size;
52  urb_size += line6pcm->max_packet_size;
53  }
54 
55  urb_in->transfer_buffer =
56  line6pcm->buffer_in +
57  index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
58  urb_in->transfer_buffer_length = urb_size;
59  urb_in->context = line6pcm;
60 
61  ret = usb_submit_urb(urb_in, GFP_ATOMIC);
62 
63  if (ret == 0)
64  set_bit(index, &line6pcm->active_urb_in);
65  else
66  dev_err(line6pcm->line6->ifcdev,
67  "URB in #%d submission failed (%d)\n", index, ret);
68 
69  spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags);
70  return 0;
71 }
72 
73 /*
74  Submit all currently available capture URBs.
75 */
77 {
78  int ret, i;
79 
80  for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
81  ret = submit_audio_in_urb(line6pcm);
82  if (ret < 0)
83  return ret;
84  }
85 
86  return 0;
87 }
88 
89 /*
90  Unlink all currently active capture URBs.
91 */
93 {
94  unsigned int i;
95 
96  for (i = LINE6_ISO_BUFFERS; i--;) {
97  if (test_bit(i, &line6pcm->active_urb_in)) {
98  if (!test_and_set_bit(i, &line6pcm->unlink_urb_in)) {
99  struct urb *u = line6pcm->urb_audio_in[i];
100  usb_unlink_urb(u);
101  }
102  }
103  }
104 }
105 
106 /*
107  Wait until unlinking of all currently active capture URBs has been
108  finished.
109 */
111 {
112  int timeout = HZ;
113  unsigned int i;
114  int alive;
115 
116  do {
117  alive = 0;
118  for (i = LINE6_ISO_BUFFERS; i--;) {
119  if (test_bit(i, &line6pcm->active_urb_in))
120  alive++;
121  }
122  if (!alive)
123  break;
125  schedule_timeout(1);
126  } while (--timeout > 0);
127  if (alive)
128  snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
129 }
130 
131 /*
132  Unlink all currently active capture URBs, and wait for finishing.
133 */
135 {
136  line6_unlink_audio_in_urbs(line6pcm);
138 }
139 
140 /*
141  Copy data into ALSA capture buffer.
142 */
143 void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize)
144 {
145  struct snd_pcm_substream *substream =
147  struct snd_pcm_runtime *runtime = substream->runtime;
148  const int bytes_per_frame = line6pcm->properties->bytes_per_frame;
149  int frames = fsize / bytes_per_frame;
150 
151  if (runtime == NULL)
152  return;
153 
154  if (line6pcm->pos_in_done + frames > runtime->buffer_size) {
155  /*
156  The transferred area goes over buffer boundary,
157  copy two separate chunks.
158  */
159  int len;
160  len = runtime->buffer_size - line6pcm->pos_in_done;
161 
162  if (len > 0) {
163  memcpy(runtime->dma_area +
164  line6pcm->pos_in_done * bytes_per_frame, fbuf,
165  len * bytes_per_frame);
166  memcpy(runtime->dma_area, fbuf + len * bytes_per_frame,
167  (frames - len) * bytes_per_frame);
168  } else {
169  /* this is somewhat paranoid */
170  dev_err(line6pcm->line6->ifcdev,
171  "driver bug: len = %d\n", len);
172  }
173  } else {
174  /* copy single chunk */
175  memcpy(runtime->dma_area +
176  line6pcm->pos_in_done * bytes_per_frame, fbuf, fsize);
177  }
178 
179  line6pcm->pos_in_done += frames;
180  if (line6pcm->pos_in_done >= runtime->buffer_size)
181  line6pcm->pos_in_done -= runtime->buffer_size;
182 }
183 
185 {
186  struct snd_pcm_substream *substream =
188 
189  line6pcm->bytes_in += length;
190  if (line6pcm->bytes_in >= line6pcm->period_in) {
191  line6pcm->bytes_in %= line6pcm->period_in;
192  snd_pcm_period_elapsed(substream);
193  }
194 }
195 
197 {
198  kfree(line6pcm->buffer_in);
199  line6pcm->buffer_in = NULL;
200 }
201 
202 /*
203  * Callback for completed capture URB.
204  */
205 static void audio_in_callback(struct urb *urb)
206 {
207  int i, index, length = 0, shutdown = 0;
208  unsigned long flags;
209 
210  struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context;
211 
212  line6pcm->last_frame_in = urb->start_frame;
213 
214  /* find index of URB */
215  for (index = 0; index < LINE6_ISO_BUFFERS; ++index)
216  if (urb == line6pcm->urb_audio_in[index])
217  break;
218 
219 #ifdef CONFIG_LINE6_USB_DUMP_PCM
220  for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
221  struct usb_iso_packet_descriptor *fout =
222  &urb->iso_frame_desc[i];
223  line6_write_hexdump(line6pcm->line6, 'C',
224  urb->transfer_buffer + fout->offset,
225  fout->length);
226  }
227 #endif
228 
229  spin_lock_irqsave(&line6pcm->lock_audio_in, flags);
230 
231  for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
232  char *fbuf;
233  int fsize;
234  struct usb_iso_packet_descriptor *fin = &urb->iso_frame_desc[i];
235 
236  if (fin->status == -EXDEV) {
237  shutdown = 1;
238  break;
239  }
240 
241  fbuf = urb->transfer_buffer + fin->offset;
242  fsize = fin->actual_length;
243 
244  if (fsize > line6pcm->max_packet_size) {
245  dev_err(line6pcm->line6->ifcdev,
246  "driver and/or device bug: packet too large (%d > %d)\n",
247  fsize, line6pcm->max_packet_size);
248  }
249 
250  length += fsize;
251 
252  /* the following assumes LINE6_ISO_PACKETS == 1: */
253  line6pcm->prev_fbuf = fbuf;
254  line6pcm->prev_fsize = fsize;
255 
256 #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
257  if (!(line6pcm->flags & LINE6_BITS_PCM_IMPULSE))
258 #endif
260  && (fsize > 0))
261  line6_capture_copy(line6pcm, fbuf, fsize);
262  }
263 
264  clear_bit(index, &line6pcm->active_urb_in);
265 
266  if (test_and_clear_bit(index, &line6pcm->unlink_urb_in))
267  shutdown = 1;
268 
269  spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags);
270 
271  if (!shutdown) {
272  submit_audio_in_urb(line6pcm);
273 
274 #ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
275  if (!(line6pcm->flags & LINE6_BITS_PCM_IMPULSE))
276 #endif
278  line6_capture_check_period(line6pcm, length);
279  }
280 }
281 
282 /* open capture callback */
283 static int snd_line6_capture_open(struct snd_pcm_substream *substream)
284 {
285  int err;
286  struct snd_pcm_runtime *runtime = substream->runtime;
287  struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
288 
289  err = snd_pcm_hw_constraint_ratdens(runtime, 0,
291  (&line6pcm->
292  properties->snd_line6_rates));
293  if (err < 0)
294  return err;
295 
296  runtime->hw = line6pcm->properties->snd_line6_capture_hw;
297  return 0;
298 }
299 
300 /* close capture callback */
301 static int snd_line6_capture_close(struct snd_pcm_substream *substream)
302 {
303  return 0;
304 }
305 
306 /* hw_params capture callback */
307 static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream,
308  struct snd_pcm_hw_params *hw_params)
309 {
310  int ret;
311  struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
312 
313  /* -- Florian Demski [FD] */
314  /* don't ask me why, but this fixes the bug on my machine */
315  if (line6pcm == NULL) {
316  if (substream->pcm == NULL)
317  return -ENOMEM;
318  if (substream->pcm->private_data == NULL)
319  return -ENOMEM;
320  substream->private_data = substream->pcm->private_data;
321  line6pcm = snd_pcm_substream_chip(substream);
322  }
323  /* -- [FD] end */
324 
325  ret = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER);
326 
327  if (ret < 0)
328  return ret;
329 
330  ret = snd_pcm_lib_malloc_pages(substream,
331  params_buffer_bytes(hw_params));
332  if (ret < 0) {
333  line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER);
334  return ret;
335  }
336 
337  line6pcm->period_in = params_period_bytes(hw_params);
338  return 0;
339 }
340 
341 /* hw_free capture callback */
342 static int snd_line6_capture_hw_free(struct snd_pcm_substream *substream)
343 {
344  struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
345  line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER);
346  return snd_pcm_lib_free_pages(substream);
347 }
348 
349 /* trigger callback */
350 int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd)
351 {
352  int err;
353 
354  switch (cmd) {
356 #ifdef CONFIG_PM
358 #endif
359  err = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_STREAM);
360 
361  if (err < 0)
362  return err;
363 
364  break;
365 
367 #ifdef CONFIG_PM
369 #endif
370  err = line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_STREAM);
371 
372  if (err < 0)
373  return err;
374 
375  break;
376 
377  default:
378  return -EINVAL;
379  }
380 
381  return 0;
382 }
383 
384 /* capture pointer callback */
385 static snd_pcm_uframes_t
386 snd_line6_capture_pointer(struct snd_pcm_substream *substream)
387 {
388  struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
389  return line6pcm->pos_in_done;
390 }
391 
392 /* capture operators */
394  .open = snd_line6_capture_open,
395  .close = snd_line6_capture_close,
396  .ioctl = snd_pcm_lib_ioctl,
397  .hw_params = snd_line6_capture_hw_params,
398  .hw_free = snd_line6_capture_hw_free,
399  .prepare = snd_line6_prepare,
400  .trigger = snd_line6_trigger,
401  .pointer = snd_line6_capture_pointer,
402 };
403 
405 {
406  int i;
407 
408  /* create audio URBs and fill in constant values: */
409  for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
410  struct urb *urb;
411 
412  /* URB for audio in: */
413  urb = line6pcm->urb_audio_in[i] =
414  usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL);
415 
416  if (urb == NULL) {
417  dev_err(line6pcm->line6->ifcdev, "Out of memory\n");
418  return -ENOMEM;
419  }
420 
421  urb->dev = line6pcm->line6->usbdev;
422  urb->pipe =
423  usb_rcvisocpipe(line6pcm->line6->usbdev,
424  line6pcm->ep_audio_read &
426  urb->transfer_flags = URB_ISO_ASAP;
427  urb->start_frame = -1;
428  urb->number_of_packets = LINE6_ISO_PACKETS;
429  urb->interval = LINE6_ISO_INTERVAL;
430  urb->error_count = 0;
431  urb->complete = audio_in_callback;
432  }
433 
434  return 0;
435 }