1 /* usb-urb.c is part of the DVB USB library. 2 * 3 * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de) 4 * see dvb-usb-init.c for copyright information. 5 * 6 * This file keeps functions for initializing and handling the 7 * BULK and ISOC USB data transfers in a generic way. 8 * Can be used for DVB-only and also, that's the plan, for 9 * Hybrid USB devices (analog and DVB). 10 */ 11 #include "dvb_usb_common.h" 12 13 /* URB stuff for streaming */ 14 15 int usb_urb_reconfig(struct usb_data_stream *stream, 16 struct usb_data_stream_properties *props); 17 18 static void usb_urb_complete(struct urb *urb) 19 { 20 struct usb_data_stream *stream = urb->context; 21 int ptype = usb_pipetype(urb->pipe); 22 int i; 23 u8 *b; 24 25 dev_dbg(&stream->udev->dev, "%s: %s urb completed status=%d " \ 26 "length=%d/%d pack_num=%d errors=%d\n", __func__, 27 ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk", 28 urb->status, urb->actual_length, 29 urb->transfer_buffer_length, 30 urb->number_of_packets, urb->error_count); 31 32 switch (urb->status) { 33 case 0: /* success */ 34 case -ETIMEDOUT: /* NAK */ 35 break; 36 case -ECONNRESET: /* kill */ 37 case -ENOENT: 38 case -ESHUTDOWN: 39 return; 40 default: /* error */ 41 dev_dbg(&stream->udev->dev, "%s: urb completition failed=%d\n", 42 __func__, urb->status); 43 break; 44 } 45 46 b = (u8 *) urb->transfer_buffer; 47 switch (ptype) { 48 case PIPE_ISOCHRONOUS: 49 for (i = 0; i < urb->number_of_packets; i++) { 50 if (urb->iso_frame_desc[i].status != 0) 51 dev_dbg(&stream->udev->dev, "%s: iso frame " \ 52 "descriptor has an error=%d\n", 53 __func__, 54 urb->iso_frame_desc[i].status); 55 else if (urb->iso_frame_desc[i].actual_length > 0) 56 stream->complete(stream, 57 b + urb->iso_frame_desc[i].offset, 58 urb->iso_frame_desc[i].actual_length); 59 60 urb->iso_frame_desc[i].status = 0; 61 urb->iso_frame_desc[i].actual_length = 0; 62 } 63 break; 64 case PIPE_BULK: 65 if (urb->actual_length > 0) 66 stream->complete(stream, b, urb->actual_length); 67 break; 68 default: 69 dev_err(&stream->udev->dev, "%s: unknown endpoint type in " \ 70 "completition handler\n", KBUILD_MODNAME); 71 return; 72 } 73 usb_submit_urb(urb, GFP_ATOMIC); 74 } 75 76 int usb_urb_killv2(struct usb_data_stream *stream) 77 { 78 int i; 79 for (i = 0; i < stream->urbs_submitted; i++) { 80 dev_dbg(&stream->udev->dev, "%s: kill urb=%d\n", __func__, i); 81 /* stop the URB */ 82 usb_kill_urb(stream->urb_list[i]); 83 } 84 stream->urbs_submitted = 0; 85 return 0; 86 } 87 88 int usb_urb_submitv2(struct usb_data_stream *stream, 89 struct usb_data_stream_properties *props) 90 { 91 int i, ret; 92 93 if (props) { 94 ret = usb_urb_reconfig(stream, props); 95 if (ret < 0) 96 return ret; 97 } 98 99 for (i = 0; i < stream->urbs_initialized; i++) { 100 dev_dbg(&stream->udev->dev, "%s: submit urb=%d\n", __func__, i); 101 ret = usb_submit_urb(stream->urb_list[i], GFP_ATOMIC); 102 if (ret) { 103 dev_err(&stream->udev->dev, "%s: could not submit " \ 104 "urb no. %d - get them all back\n", 105 KBUILD_MODNAME, i); 106 usb_urb_killv2(stream); 107 return ret; 108 } 109 stream->urbs_submitted++; 110 } 111 return 0; 112 } 113 114 int usb_urb_free_urbs(struct usb_data_stream *stream) 115 { 116 int i; 117 118 usb_urb_killv2(stream); 119 120 for (i = stream->urbs_initialized - 1; i >= 0; i--) { 121 if (stream->urb_list[i]) { 122 dev_dbg(&stream->udev->dev, "%s: free urb=%d\n", 123 __func__, i); 124 /* free the URBs */ 125 usb_free_urb(stream->urb_list[i]); 126 } 127 } 128 stream->urbs_initialized = 0; 129 130 return 0; 131 } 132 133 static int usb_urb_alloc_bulk_urbs(struct usb_data_stream *stream) 134 { 135 int i, j; 136 137 /* allocate the URBs */ 138 for (i = 0; i < stream->props.count; i++) { 139 dev_dbg(&stream->udev->dev, "%s: alloc urb=%d\n", __func__, i); 140 stream->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC); 141 if (!stream->urb_list[i]) { 142 dev_dbg(&stream->udev->dev, "%s: failed\n", __func__); 143 for (j = 0; j < i; j++) 144 usb_free_urb(stream->urb_list[j]); 145 return -ENOMEM; 146 } 147 usb_fill_bulk_urb(stream->urb_list[i], 148 stream->udev, 149 usb_rcvbulkpipe(stream->udev, 150 stream->props.endpoint), 151 stream->buf_list[i], 152 stream->props.u.bulk.buffersize, 153 usb_urb_complete, stream); 154 155 stream->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; 156 stream->urb_list[i]->transfer_dma = stream->dma_addr[i]; 157 stream->urbs_initialized++; 158 } 159 return 0; 160 } 161 162 static int usb_urb_alloc_isoc_urbs(struct usb_data_stream *stream) 163 { 164 int i, j; 165 166 /* allocate the URBs */ 167 for (i = 0; i < stream->props.count; i++) { 168 struct urb *urb; 169 int frame_offset = 0; 170 dev_dbg(&stream->udev->dev, "%s: alloc urb=%d\n", __func__, i); 171 stream->urb_list[i] = usb_alloc_urb( 172 stream->props.u.isoc.framesperurb, GFP_ATOMIC); 173 if (!stream->urb_list[i]) { 174 dev_dbg(&stream->udev->dev, "%s: failed\n", __func__); 175 for (j = 0; j < i; j++) 176 usb_free_urb(stream->urb_list[j]); 177 return -ENOMEM; 178 } 179 180 urb = stream->urb_list[i]; 181 182 urb->dev = stream->udev; 183 urb->context = stream; 184 urb->complete = usb_urb_complete; 185 urb->pipe = usb_rcvisocpipe(stream->udev, 186 stream->props.endpoint); 187 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; 188 urb->interval = stream->props.u.isoc.interval; 189 urb->number_of_packets = stream->props.u.isoc.framesperurb; 190 urb->transfer_buffer_length = stream->props.u.isoc.framesize * 191 stream->props.u.isoc.framesperurb; 192 urb->transfer_buffer = stream->buf_list[i]; 193 urb->transfer_dma = stream->dma_addr[i]; 194 195 for (j = 0; j < stream->props.u.isoc.framesperurb; j++) { 196 urb->iso_frame_desc[j].offset = frame_offset; 197 urb->iso_frame_desc[j].length = 198 stream->props.u.isoc.framesize; 199 frame_offset += stream->props.u.isoc.framesize; 200 } 201 202 stream->urbs_initialized++; 203 } 204 return 0; 205 } 206 207 int usb_free_stream_buffers(struct usb_data_stream *stream) 208 { 209 if (stream->state & USB_STATE_URB_BUF) { 210 while (stream->buf_num) { 211 stream->buf_num--; 212 dev_dbg(&stream->udev->dev, "%s: free buf=%d\n", 213 __func__, stream->buf_num); 214 usb_free_coherent(stream->udev, stream->buf_size, 215 stream->buf_list[stream->buf_num], 216 stream->dma_addr[stream->buf_num]); 217 } 218 } 219 220 stream->state &= ~USB_STATE_URB_BUF; 221 222 return 0; 223 } 224 225 int usb_alloc_stream_buffers(struct usb_data_stream *stream, int num, 226 unsigned long size) 227 { 228 stream->buf_num = 0; 229 stream->buf_size = size; 230 231 dev_dbg(&stream->udev->dev, "%s: all in all I will use %lu bytes for " \ 232 "streaming\n", __func__, num * size); 233 234 for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) { 235 stream->buf_list[stream->buf_num] = usb_alloc_coherent( 236 stream->udev, size, GFP_ATOMIC, 237 &stream->dma_addr[stream->buf_num]); 238 if (!stream->buf_list[stream->buf_num]) { 239 dev_dbg(&stream->udev->dev, "%s: alloc buf=%d failed\n", 240 __func__, stream->buf_num); 241 usb_free_stream_buffers(stream); 242 return -ENOMEM; 243 } 244 245 dev_dbg(&stream->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n", 246 __func__, stream->buf_num, 247 stream->buf_list[stream->buf_num], 248 (long long)stream->dma_addr[stream->buf_num]); 249 memset(stream->buf_list[stream->buf_num], 0, size); 250 stream->state |= USB_STATE_URB_BUF; 251 } 252 253 return 0; 254 } 255 256 int usb_urb_reconfig(struct usb_data_stream *stream, 257 struct usb_data_stream_properties *props) 258 { 259 int buf_size; 260 261 if (!props) 262 return 0; 263 264 /* check allocated buffers are large enough for the request */ 265 if (props->type == USB_BULK) { 266 buf_size = stream->props.u.bulk.buffersize; 267 } else if (props->type == USB_ISOC) { 268 buf_size = props->u.isoc.framesize * props->u.isoc.framesperurb; 269 } else { 270 dev_err(&stream->udev->dev, "%s: invalid endpoint type=%d\n", 271 KBUILD_MODNAME, props->type); 272 return -EINVAL; 273 } 274 275 if (stream->buf_num < props->count || stream->buf_size < buf_size) { 276 dev_err(&stream->udev->dev, "%s: cannot reconfigure as " \ 277 "allocated buffers are too small\n", 278 KBUILD_MODNAME); 279 return -EINVAL; 280 } 281 282 /* check if all fields are same */ 283 if (stream->props.type == props->type && 284 stream->props.count == props->count && 285 stream->props.endpoint == props->endpoint) { 286 if (props->type == USB_BULK && 287 props->u.bulk.buffersize == 288 stream->props.u.bulk.buffersize) 289 return 0; 290 else if (props->type == USB_ISOC && 291 props->u.isoc.framesperurb == 292 stream->props.u.isoc.framesperurb && 293 props->u.isoc.framesize == 294 stream->props.u.isoc.framesize && 295 props->u.isoc.interval == 296 stream->props.u.isoc.interval) 297 return 0; 298 } 299 300 dev_dbg(&stream->udev->dev, "%s: re-alloc urbs\n", __func__); 301 302 usb_urb_free_urbs(stream); 303 memcpy(&stream->props, props, sizeof(*props)); 304 if (props->type == USB_BULK) 305 return usb_urb_alloc_bulk_urbs(stream); 306 else if (props->type == USB_ISOC) 307 return usb_urb_alloc_isoc_urbs(stream); 308 309 return 0; 310 } 311 312 int usb_urb_initv2(struct usb_data_stream *stream, 313 const struct usb_data_stream_properties *props) 314 { 315 int ret; 316 317 if (!stream || !props) 318 return -EINVAL; 319 320 memcpy(&stream->props, props, sizeof(*props)); 321 322 if (!stream->complete) { 323 dev_err(&stream->udev->dev, "%s: there is no data callback - " \ 324 "this doesn't make sense\n", KBUILD_MODNAME); 325 return -EINVAL; 326 } 327 328 switch (stream->props.type) { 329 case USB_BULK: 330 ret = usb_alloc_stream_buffers(stream, stream->props.count, 331 stream->props.u.bulk.buffersize); 332 if (ret < 0) 333 return ret; 334 335 return usb_urb_alloc_bulk_urbs(stream); 336 case USB_ISOC: 337 ret = usb_alloc_stream_buffers(stream, stream->props.count, 338 stream->props.u.isoc.framesize * 339 stream->props.u.isoc.framesperurb); 340 if (ret < 0) 341 return ret; 342 343 return usb_urb_alloc_isoc_urbs(stream); 344 default: 345 dev_err(&stream->udev->dev, "%s: unknown urb-type for data " \ 346 "transfer\n", KBUILD_MODNAME); 347 return -EINVAL; 348 } 349 } 350 351 int usb_urb_exitv2(struct usb_data_stream *stream) 352 { 353 usb_urb_free_urbs(stream); 354 usb_free_stream_buffers(stream); 355 356 return 0; 357 } 358