1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Line 6 Linux USB driver 4 * 5 * Copyright (C) 2004-2010 Markus Grabner (line6@grabner-graz.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 struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context; 149 150 line6pcm->in.last_frame = urb->start_frame; 151 152 /* find index of URB */ 153 for (index = 0; index < line6pcm->line6->iso_buffers; ++index) 154 if (urb == line6pcm->in.urbs[index]) 155 break; 156 157 guard(spinlock_irqsave)(&line6pcm->in.lock); 158 159 for (i = 0; i < LINE6_ISO_PACKETS; ++i) { 160 char *fbuf; 161 int fsize; 162 struct usb_iso_packet_descriptor *fin = &urb->iso_frame_desc[i]; 163 164 if (fin->status == -EXDEV) { 165 shutdown = 1; 166 break; 167 } 168 169 fbuf = urb->transfer_buffer + fin->offset; 170 fsize = fin->actual_length; 171 172 if (fsize > line6pcm->max_packet_size_in) { 173 dev_err(line6pcm->line6->ifcdev, 174 "driver and/or device bug: packet too large (%d > %d)\n", 175 fsize, line6pcm->max_packet_size_in); 176 } 177 178 length += fsize; 179 180 BUILD_BUG_ON_MSG(LINE6_ISO_PACKETS != 1, 181 "The following code assumes LINE6_ISO_PACKETS == 1"); 182 /* TODO: 183 * Also, if iso_buffers != 2, the prev frame is almost random at 184 * playback side. 185 * This needs to be redesigned. It should be "stable", but we may 186 * experience sync problems on such high-speed configs. 187 */ 188 189 line6pcm->prev_fbuf = fbuf; 190 line6pcm->prev_fsize = fsize / 191 (line6pcm->properties->bytes_per_channel * 192 line6pcm->properties->capture_hw.channels_max); 193 194 if (!test_bit(LINE6_STREAM_IMPULSE, &line6pcm->in.running) && 195 test_bit(LINE6_STREAM_PCM, &line6pcm->in.running) && 196 fsize > 0) 197 line6_capture_copy(line6pcm, fbuf, fsize); 198 } 199 200 clear_bit(index, &line6pcm->in.active_urbs); 201 202 if (test_and_clear_bit(index, &line6pcm->in.unlink_urbs)) 203 shutdown = 1; 204 205 if (!shutdown) { 206 submit_audio_in_urb(line6pcm); 207 208 if (!test_bit(LINE6_STREAM_IMPULSE, &line6pcm->in.running) && 209 test_bit(LINE6_STREAM_PCM, &line6pcm->in.running)) 210 line6_capture_check_period(line6pcm, length); 211 } 212 } 213 214 /* open capture callback */ 215 static int snd_line6_capture_open(struct snd_pcm_substream *substream) 216 { 217 int err; 218 struct snd_pcm_runtime *runtime = substream->runtime; 219 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); 220 221 err = snd_pcm_hw_constraint_ratdens(runtime, 0, 222 SNDRV_PCM_HW_PARAM_RATE, 223 &line6pcm->properties->rates); 224 if (err < 0) 225 return err; 226 227 line6_pcm_acquire(line6pcm, LINE6_STREAM_CAPTURE_HELPER, false); 228 229 runtime->hw = line6pcm->properties->capture_hw; 230 return 0; 231 } 232 233 /* close capture callback */ 234 static int snd_line6_capture_close(struct snd_pcm_substream *substream) 235 { 236 struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream); 237 238 line6_pcm_release(line6pcm, LINE6_STREAM_CAPTURE_HELPER); 239 return 0; 240 } 241 242 /* capture operators */ 243 const struct snd_pcm_ops snd_line6_capture_ops = { 244 .open = snd_line6_capture_open, 245 .close = snd_line6_capture_close, 246 .hw_params = snd_line6_hw_params, 247 .hw_free = snd_line6_hw_free, 248 .prepare = snd_line6_prepare, 249 .trigger = snd_line6_trigger, 250 .pointer = snd_line6_pointer, 251 }; 252 253 int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm) 254 { 255 struct usb_line6 *line6 = line6pcm->line6; 256 int i; 257 258 line6pcm->in.urbs = kcalloc(line6->iso_buffers, sizeof(struct urb *), 259 GFP_KERNEL); 260 if (line6pcm->in.urbs == NULL) 261 return -ENOMEM; 262 263 /* create audio URBs and fill in constant values: */ 264 for (i = 0; i < line6->iso_buffers; ++i) { 265 struct urb *urb; 266 267 /* URB for audio in: */ 268 urb = line6pcm->in.urbs[i] = 269 usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL); 270 271 if (urb == NULL) 272 return -ENOMEM; 273 274 urb->dev = line6->usbdev; 275 urb->pipe = 276 usb_rcvisocpipe(line6->usbdev, 277 line6->properties->ep_audio_r & 278 USB_ENDPOINT_NUMBER_MASK); 279 urb->transfer_flags = URB_ISO_ASAP; 280 urb->start_frame = -1; 281 urb->number_of_packets = LINE6_ISO_PACKETS; 282 urb->interval = LINE6_ISO_INTERVAL; 283 urb->error_count = 0; 284 urb->complete = audio_in_callback; 285 if (usb_urb_ep_type_check(urb)) 286 return -EINVAL; 287 } 288 289 return 0; 290 } 291