1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Line 6 Linux USB driver 4 * 5 * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at) 6 */ 7 8 #include <linux/slab.h> 9 #include <sound/core.h> 10 #include <sound/pcm.h> 11 #include <sound/pcm_params.h> 12 13 #include "capture.h" 14 #include "driver.h" 15 #include "pcm.h" 16 17 /* 18 Find a free URB and submit it. 19 must be called in line6pcm->in.lock context 20 */ 21 static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm) 22 { 23 int index; 24 int i, urb_size; 25 int ret; 26 struct urb *urb_in; 27 28 index = find_first_zero_bit(&line6pcm->in.active_urbs, 29 line6pcm->line6->iso_buffers); 30 31 if (index < 0 || index >= line6pcm->line6->iso_buffers) { 32 dev_err(line6pcm->line6->ifcdev, "no free URB found\n"); 33 return -EINVAL; 34 } 35 36 urb_in = line6pcm->in.urbs[index]; 37 urb_size = 0; 38 39 for (i = 0; i < LINE6_ISO_PACKETS; ++i) { 40 struct usb_iso_packet_descriptor *fin = 41 &urb_in->iso_frame_desc[i]; 42 fin->offset = urb_size; 43 fin->length = line6pcm->max_packet_size_in; 44 urb_size += line6pcm->max_packet_size_in; 45 } 46 47 urb_in->transfer_buffer = 48 line6pcm->in.buffer + 49 index * LINE6_ISO_PACKETS * line6pcm->max_packet_size_in; 50 urb_in->transfer_buffer_length = urb_size; 51 urb_in->context = line6pcm; 52 53 ret = usb_submit_urb(urb_in, GFP_ATOMIC); 54 55 if (ret == 0) 56 set_bit(index, &line6pcm->in.active_urbs); 57 else 58 dev_err(line6pcm->line6->ifcdev, 59 "URB in #%d submission failed (%d)\n", index, ret); 60 61 return 0; 62 } 63 64 /* 65 Submit all currently available capture URBs. 66 must be called in line6pcm->in.lock context 67 */ 68 int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm) 69 { 70 int ret = 0, i; 71 72 for (i = 0; i < line6pcm->line6->iso_buffers; ++i) { 73 ret = submit_audio_in_urb(line6pcm); 74 if (ret < 0) 75 break; 76 } 77 78 return ret; 79 } 80 81 /* 82 Copy data into ALSA capture buffer. 83 */ 84 void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize) 85 { 86 struct snd_pcm_substream *substream = 87 get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE); 88 struct snd_pcm_runtime *runtime = substream->runtime; 89 const int bytes_per_frame = 90 line6pcm->properties->bytes_per_channel * 91 line6pcm->properties->capture_hw.channels_max; 92 int frames = fsize / bytes_per_frame; 93 94 if (runtime == NULL) 95 return; 96 97 if (line6pcm->in.pos_done + frames > runtime->buffer_size) { 98 /* 99 The transferred area goes over buffer boundary, 100 copy two separate chunks. 101 */ 102 int len; 103 104 len = runtime->buffer_size - line6pcm->in.pos_done; 105 106 if (len > 0) { 107 memcpy(runtime->dma_area + 108 line6pcm->in.pos_done * bytes_per_frame, fbuf, 109 len * bytes_per_frame); 110 memcpy(runtime->dma_area, fbuf + len * bytes_per_frame, 111 (frames - len) * bytes_per_frame); 112 } else { 113 /* this is somewhat paranoid */ 114 dev_err(line6pcm->line6->ifcdev, 115 "driver bug: len = %d\n", len); 116 } 117 } else { 118 /* copy single chunk */ 119 memcpy(runtime->dma_area + 120 line6pcm->in.pos_done * bytes_per_frame, fbuf, fsize); 121 } 122 123 line6pcm->in.pos_done += frames; 124 if (line6pcm->in.pos_done >= runtime->buffer_size) 125 line6pcm->in.pos_done -= runtime->buffer_size; 126 } 127 128 void line6_capture_check_period(struct snd_line6_pcm *line6pcm, int length) 129 { 130 struct snd_pcm_substream *substream = 131 get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE); 132 133 line6pcm->in.bytes += length; 134 if (line6pcm->in.bytes >= line6pcm->in.period) { 135 line6pcm->in.bytes %= line6pcm->in.period; 136 spin_unlock(&line6pcm->in.lock); 137 snd_pcm_period_elapsed(substream); 138 spin_lock(&line6pcm->in.lock); 139 } 140 } 141 142 /* 143 * Callback for completed capture URB. 144 */ 145 static void audio_in_callback(struct urb *urb) 146 { 147 int i, index, length = 0, shutdown = 0; 148 unsigned long flags; 149 150 struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context; 151 152 line6pcm->in.last_frame = urb->start_frame; 153 154 /* find index of URB */ 155 for (index = 0; index < line6pcm->line6->iso_buffers; ++index) 156 if (urb == line6pcm->in.urbs[index]) 157 break; 158 159 spin_lock_irqsave(&line6pcm->in.lock, flags); 160 161 for (i = 0; i < LINE6_ISO_PACKETS; ++i) { 162 char *fbuf; 163 int fsize; 164 struct usb_iso_packet_descriptor *fin = &urb->iso_frame_desc[i]; 165 166 if (fin->status == -EXDEV) { 167 shutdown = 1; 168 break; 169 } 170 171 fbuf = urb->transfer_buffer + fin->offset; 172 fsize = fin->actual_length; 173 174 if (fsize > line6pcm->max_packet_size_in) { 175 dev_err(line6pcm->line6->ifcdev, 176 "driver and/or device bug: packet too large (%d > %d)\n", 177 fsize, line6pcm->max_packet_size_in); 178 } 179 180 length += fsize; 181 182 BUILD_BUG_ON_MSG(LINE6_ISO_PACKETS != 1, 183 "The following code assumes LINE6_ISO_PACKETS == 1"); 184 /* TODO: 185 * Also, if iso_buffers != 2, the prev frame is almost random at 186 * playback side. 187 * This needs to be redesigned. It should be "stable", but we may 188 * experience sync problems on such high-speed configs. 189 */ 190 191 line6pcm->prev_fbuf = fbuf; 192 line6pcm->prev_fsize = fsize / 193 (line6pcm->properties->bytes_per_channel * 194 line6pcm->properties->capture_hw.channels_max); 195 196 if (!test_bit(LINE6_STREAM_IMPULSE, &line6pcm->in.running) && 197 test_bit(LINE6_STREAM_PCM, &line6pcm->in.running) && 198 fsize > 0) 199 line6_capture_copy(line6pcm, fbuf, fsize); 200 } 201 202 clear_bit(index, &line6pcm->in.active_urbs); 203 204 if (test_and_clear_bit(index, &line6pcm->in.unlink_urbs)) 205 shutdown = 1; 206 207 if (!shutdown) { 208 submit_audio_in_urb(line6pcm); 209 210 if (!test_bit(LINE6_STREAM_IMPULSE, &line6pcm->in.running) && 211 test_bit(LINE6_STREAM_PCM, &line6pcm->in.running)) 212 line6_capture_check_period(line6pcm, length); 213 } 214 215 spin_unlock_irqrestore(&line6pcm->in.lock, flags); 216 } 217 218 /* open capture callback */ 219 static int snd_line6_capture_open(struct snd_pcm_substream *substream) 220 { 221 int err; 222 struct snd_pcm_runtime *runtime = substream->runtime; 223 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); 224 225 err = snd_pcm_hw_constraint_ratdens(runtime, 0, 226 SNDRV_PCM_HW_PARAM_RATE, 227 &line6pcm->properties->rates); 228 if (err < 0) 229 return err; 230 231 line6_pcm_acquire(line6pcm, LINE6_STREAM_CAPTURE_HELPER, false); 232 233 runtime->hw = line6pcm->properties->capture_hw; 234 return 0; 235 } 236 237 /* close capture callback */ 238 static int snd_line6_capture_close(struct snd_pcm_substream *substream) 239 { 240 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); 241 242 line6_pcm_release(line6pcm, LINE6_STREAM_CAPTURE_HELPER); 243 return 0; 244 } 245 246 /* capture operators */ 247 const struct snd_pcm_ops snd_line6_capture_ops = { 248 .open = snd_line6_capture_open, 249 .close = snd_line6_capture_close, 250 .ioctl = snd_pcm_lib_ioctl, 251 .hw_params = snd_line6_hw_params, 252 .hw_free = snd_line6_hw_free, 253 .prepare = snd_line6_prepare, 254 .trigger = snd_line6_trigger, 255 .pointer = snd_line6_pointer, 256 }; 257 258 int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm) 259 { 260 struct usb_line6 *line6 = line6pcm->line6; 261 int i; 262 263 line6pcm->in.urbs = kcalloc(line6->iso_buffers, sizeof(struct urb *), 264 GFP_KERNEL); 265 if (line6pcm->in.urbs == NULL) 266 return -ENOMEM; 267 268 /* create audio URBs and fill in constant values: */ 269 for (i = 0; i < line6->iso_buffers; ++i) { 270 struct urb *urb; 271 272 /* URB for audio in: */ 273 urb = line6pcm->in.urbs[i] = 274 usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL); 275 276 if (urb == NULL) 277 return -ENOMEM; 278 279 urb->dev = line6->usbdev; 280 urb->pipe = 281 usb_rcvisocpipe(line6->usbdev, 282 line6->properties->ep_audio_r & 283 USB_ENDPOINT_NUMBER_MASK); 284 urb->transfer_flags = URB_ISO_ASAP; 285 urb->start_frame = -1; 286 urb->number_of_packets = LINE6_ISO_PACKETS; 287 urb->interval = LINE6_ISO_INTERVAL; 288 urb->error_count = 0; 289 urb->complete = audio_in_callback; 290 } 291 292 return 0; 293 } 294