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