root/drivers/media/usb/dvb-usb/usb-urb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usb_urb_complete
  2. usb_urb_kill
  3. usb_urb_submit
  4. usb_free_stream_buffers
  5. usb_allocate_stream_buffers
  6. usb_bulk_urb_init
  7. usb_isoc_urb_init
  8. usb_urb_init
  9. usb_urb_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* usb-urb.c is part of the DVB USB library.
   3  *
   4  * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de)
   5  * see dvb-usb-init.c for copyright information.
   6  *
   7  * This file keeps functions for initializing and handling the
   8  * BULK and ISOC USB data transfers in a generic way.
   9  * Can be used for DVB-only and also, that's the plan, for
  10  * Hybrid USB devices (analog and DVB).
  11  */
  12 #include "dvb-usb-common.h"
  13 
  14 /* URB stuff for streaming */
  15 static void usb_urb_complete(struct urb *urb)
  16 {
  17         struct usb_data_stream *stream = urb->context;
  18         int ptype = usb_pipetype(urb->pipe);
  19         int i;
  20         u8 *b;
  21 
  22         deb_uxfer("'%s' urb completed. status: %d, length: %d/%d, pack_num: %d, errors: %d\n",
  23                 ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk",
  24                 urb->status,urb->actual_length,urb->transfer_buffer_length,
  25                 urb->number_of_packets,urb->error_count);
  26 
  27         switch (urb->status) {
  28                 case 0:         /* success */
  29                 case -ETIMEDOUT:    /* NAK */
  30                         break;
  31                 case -ECONNRESET:   /* kill */
  32                 case -ENOENT:
  33                 case -ESHUTDOWN:
  34                         return;
  35                 default:        /* error */
  36                         deb_ts("urb completion error %d.\n", urb->status);
  37                         break;
  38         }
  39 
  40         b = (u8 *) urb->transfer_buffer;
  41         switch (ptype) {
  42                 case PIPE_ISOCHRONOUS:
  43                         for (i = 0; i < urb->number_of_packets; i++) {
  44 
  45                                 if (urb->iso_frame_desc[i].status != 0)
  46                                         deb_ts("iso frame descriptor has an error: %d\n",urb->iso_frame_desc[i].status);
  47                                 else if (urb->iso_frame_desc[i].actual_length > 0)
  48                                         stream->complete(stream, b + urb->iso_frame_desc[i].offset, urb->iso_frame_desc[i].actual_length);
  49 
  50                                 urb->iso_frame_desc[i].status = 0;
  51                                 urb->iso_frame_desc[i].actual_length = 0;
  52                         }
  53                         debug_dump(b,20,deb_uxfer);
  54                         break;
  55                 case PIPE_BULK:
  56                         if (urb->actual_length > 0)
  57                                 stream->complete(stream, b, urb->actual_length);
  58                         break;
  59                 default:
  60                         err("unknown endpoint type in completion handler.");
  61                         return;
  62         }
  63         usb_submit_urb(urb,GFP_ATOMIC);
  64 }
  65 
  66 int usb_urb_kill(struct usb_data_stream *stream)
  67 {
  68         int i;
  69         for (i = 0; i < stream->urbs_submitted; i++) {
  70                 deb_ts("killing URB no. %d.\n",i);
  71 
  72                 /* stop the URB */
  73                 usb_kill_urb(stream->urb_list[i]);
  74         }
  75         stream->urbs_submitted = 0;
  76         return 0;
  77 }
  78 
  79 int usb_urb_submit(struct usb_data_stream *stream)
  80 {
  81         int i,ret;
  82         for (i = 0; i < stream->urbs_initialized; i++) {
  83                 deb_ts("submitting URB no. %d\n",i);
  84                 if ((ret = usb_submit_urb(stream->urb_list[i],GFP_ATOMIC))) {
  85                         err("could not submit URB no. %d - get them all back",i);
  86                         usb_urb_kill(stream);
  87                         return ret;
  88                 }
  89                 stream->urbs_submitted++;
  90         }
  91         return 0;
  92 }
  93 
  94 static int usb_free_stream_buffers(struct usb_data_stream *stream)
  95 {
  96         if (stream->state & USB_STATE_URB_BUF) {
  97                 while (stream->buf_num) {
  98                         stream->buf_num--;
  99                         deb_mem("freeing buffer %d\n",stream->buf_num);
 100                         usb_free_coherent(stream->udev, stream->buf_size,
 101                                           stream->buf_list[stream->buf_num],
 102                                           stream->dma_addr[stream->buf_num]);
 103                 }
 104         }
 105 
 106         stream->state &= ~USB_STATE_URB_BUF;
 107 
 108         return 0;
 109 }
 110 
 111 static int usb_allocate_stream_buffers(struct usb_data_stream *stream, int num, unsigned long size)
 112 {
 113         stream->buf_num = 0;
 114         stream->buf_size = size;
 115 
 116         deb_mem("all in all I will use %lu bytes for streaming\n",num*size);
 117 
 118         for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) {
 119                 deb_mem("allocating buffer %d\n",stream->buf_num);
 120                 if (( stream->buf_list[stream->buf_num] =
 121                                         usb_alloc_coherent(stream->udev, size, GFP_KERNEL,
 122                                         &stream->dma_addr[stream->buf_num]) ) == NULL) {
 123                         deb_mem("not enough memory for urb-buffer allocation.\n");
 124                         usb_free_stream_buffers(stream);
 125                         return -ENOMEM;
 126                 }
 127                 deb_mem("buffer %d: %p (dma: %Lu)\n",
 128                         stream->buf_num,
 129 stream->buf_list[stream->buf_num], (long long)stream->dma_addr[stream->buf_num]);
 130                 memset(stream->buf_list[stream->buf_num],0,size);
 131                 stream->state |= USB_STATE_URB_BUF;
 132         }
 133         deb_mem("allocation successful\n");
 134 
 135         return 0;
 136 }
 137 
 138 static int usb_bulk_urb_init(struct usb_data_stream *stream)
 139 {
 140         int i, j;
 141 
 142         if ((i = usb_allocate_stream_buffers(stream,stream->props.count,
 143                                         stream->props.u.bulk.buffersize)) < 0)
 144                 return i;
 145 
 146         /* allocate the URBs */
 147         for (i = 0; i < stream->props.count; i++) {
 148                 stream->urb_list[i] = usb_alloc_urb(0, GFP_KERNEL);
 149                 if (!stream->urb_list[i]) {
 150                         deb_mem("not enough memory for urb_alloc_urb!.\n");
 151                         for (j = 0; j < i; j++)
 152                                 usb_free_urb(stream->urb_list[j]);
 153                         return -ENOMEM;
 154                 }
 155                 usb_fill_bulk_urb( stream->urb_list[i], stream->udev,
 156                                 usb_rcvbulkpipe(stream->udev,stream->props.endpoint),
 157                                 stream->buf_list[i],
 158                                 stream->props.u.bulk.buffersize,
 159                                 usb_urb_complete, stream);
 160 
 161                 stream->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
 162                 stream->urb_list[i]->transfer_dma = stream->dma_addr[i];
 163                 stream->urbs_initialized++;
 164         }
 165         return 0;
 166 }
 167 
 168 static int usb_isoc_urb_init(struct usb_data_stream *stream)
 169 {
 170         int i,j;
 171 
 172         if ((i = usb_allocate_stream_buffers(stream,stream->props.count,
 173                                         stream->props.u.isoc.framesize*stream->props.u.isoc.framesperurb)) < 0)
 174                 return i;
 175 
 176         /* allocate the URBs */
 177         for (i = 0; i < stream->props.count; i++) {
 178                 struct urb *urb;
 179                 int frame_offset = 0;
 180 
 181                 stream->urb_list[i] = usb_alloc_urb(stream->props.u.isoc.framesperurb, GFP_KERNEL);
 182                 if (!stream->urb_list[i]) {
 183                         deb_mem("not enough memory for urb_alloc_urb!\n");
 184                         for (j = 0; j < i; j++)
 185                                 usb_free_urb(stream->urb_list[j]);
 186                         return -ENOMEM;
 187                 }
 188 
 189                 urb = stream->urb_list[i];
 190 
 191                 urb->dev = stream->udev;
 192                 urb->context = stream;
 193                 urb->complete = usb_urb_complete;
 194                 urb->pipe = usb_rcvisocpipe(stream->udev,stream->props.endpoint);
 195                 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
 196                 urb->interval = stream->props.u.isoc.interval;
 197                 urb->number_of_packets = stream->props.u.isoc.framesperurb;
 198                 urb->transfer_buffer_length = stream->buf_size;
 199                 urb->transfer_buffer = stream->buf_list[i];
 200                 urb->transfer_dma = stream->dma_addr[i];
 201 
 202                 for (j = 0; j < stream->props.u.isoc.framesperurb; j++) {
 203                         urb->iso_frame_desc[j].offset = frame_offset;
 204                         urb->iso_frame_desc[j].length = stream->props.u.isoc.framesize;
 205                         frame_offset += stream->props.u.isoc.framesize;
 206                 }
 207 
 208                 stream->urbs_initialized++;
 209         }
 210         return 0;
 211 }
 212 
 213 int usb_urb_init(struct usb_data_stream *stream, struct usb_data_stream_properties *props)
 214 {
 215         if (stream == NULL || props == NULL)
 216                 return -EINVAL;
 217 
 218         memcpy(&stream->props, props, sizeof(*props));
 219 
 220         usb_clear_halt(stream->udev,usb_rcvbulkpipe(stream->udev,stream->props.endpoint));
 221 
 222         if (stream->complete == NULL) {
 223                 err("there is no data callback - this doesn't make sense.");
 224                 return -EINVAL;
 225         }
 226 
 227         switch (stream->props.type) {
 228                 case USB_BULK:
 229                         return usb_bulk_urb_init(stream);
 230                 case USB_ISOC:
 231                         return usb_isoc_urb_init(stream);
 232                 default:
 233                         err("unknown URB-type for data transfer.");
 234                         return -EINVAL;
 235         }
 236 }
 237 
 238 int usb_urb_exit(struct usb_data_stream *stream)
 239 {
 240         int i;
 241 
 242         usb_urb_kill(stream);
 243 
 244         for (i = 0; i < stream->urbs_initialized; i++) {
 245                 if (stream->urb_list[i] != NULL) {
 246                         deb_mem("freeing URB no. %d.\n",i);
 247                         /* free the URBs */
 248                         usb_free_urb(stream->urb_list[i]);
 249                 }
 250         }
 251         stream->urbs_initialized = 0;
 252 
 253         usb_free_stream_buffers(stream);
 254         return 0;
 255 }

/* [<][>][^][v][top][bottom][index][help] */