Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* usb-urb.c is part of the DVB USB library.
0003  *
0004  * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de)
0005  * see dvb-usb-init.c for copyright information.
0006  *
0007  * This file keeps functions for initializing and handling the
0008  * BULK and ISOC USB data transfers in a generic way.
0009  * Can be used for DVB-only and also, that's the plan, for
0010  * Hybrid USB devices (analog and DVB).
0011  */
0012 #include "dvb-usb-common.h"
0013 
0014 /* URB stuff for streaming */
0015 static void usb_urb_complete(struct urb *urb)
0016 {
0017     struct usb_data_stream *stream = urb->context;
0018     int ptype = usb_pipetype(urb->pipe);
0019     int i;
0020     u8 *b;
0021 
0022     deb_uxfer("'%s' urb completed. status: %d, length: %d/%d, pack_num: %d, errors: %d\n",
0023         ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk",
0024         urb->status,urb->actual_length,urb->transfer_buffer_length,
0025         urb->number_of_packets,urb->error_count);
0026 
0027     switch (urb->status) {
0028         case 0:         /* success */
0029         case -ETIMEDOUT:    /* NAK */
0030             break;
0031         case -ECONNRESET:   /* kill */
0032         case -ENOENT:
0033         case -ESHUTDOWN:
0034             return;
0035         default:        /* error */
0036             deb_ts("urb completion error %d.\n", urb->status);
0037             break;
0038     }
0039 
0040     b = (u8 *) urb->transfer_buffer;
0041     switch (ptype) {
0042         case PIPE_ISOCHRONOUS:
0043             for (i = 0; i < urb->number_of_packets; i++) {
0044 
0045                 if (urb->iso_frame_desc[i].status != 0)
0046                     deb_ts("iso frame descriptor has an error: %d\n",urb->iso_frame_desc[i].status);
0047                 else if (urb->iso_frame_desc[i].actual_length > 0)
0048                     stream->complete(stream, b + urb->iso_frame_desc[i].offset, urb->iso_frame_desc[i].actual_length);
0049 
0050                 urb->iso_frame_desc[i].status = 0;
0051                 urb->iso_frame_desc[i].actual_length = 0;
0052             }
0053             debug_dump(b,20,deb_uxfer);
0054             break;
0055         case PIPE_BULK:
0056             if (urb->actual_length > 0)
0057                 stream->complete(stream, b, urb->actual_length);
0058             break;
0059         default:
0060             err("unknown endpoint type in completion handler.");
0061             return;
0062     }
0063     usb_submit_urb(urb,GFP_ATOMIC);
0064 }
0065 
0066 int usb_urb_kill(struct usb_data_stream *stream)
0067 {
0068     int i;
0069     for (i = 0; i < stream->urbs_submitted; i++) {
0070         deb_ts("killing URB no. %d.\n",i);
0071 
0072         /* stop the URB */
0073         usb_kill_urb(stream->urb_list[i]);
0074     }
0075     stream->urbs_submitted = 0;
0076     return 0;
0077 }
0078 
0079 int usb_urb_submit(struct usb_data_stream *stream)
0080 {
0081     int i,ret;
0082     for (i = 0; i < stream->urbs_initialized; i++) {
0083         deb_ts("submitting URB no. %d\n",i);
0084         if ((ret = usb_submit_urb(stream->urb_list[i],GFP_ATOMIC))) {
0085             err("could not submit URB no. %d - get them all back",i);
0086             usb_urb_kill(stream);
0087             return ret;
0088         }
0089         stream->urbs_submitted++;
0090     }
0091     return 0;
0092 }
0093 
0094 static int usb_free_stream_buffers(struct usb_data_stream *stream)
0095 {
0096     if (stream->state & USB_STATE_URB_BUF) {
0097         while (stream->buf_num) {
0098             stream->buf_num--;
0099             deb_mem("freeing buffer %d\n",stream->buf_num);
0100             usb_free_coherent(stream->udev, stream->buf_size,
0101                       stream->buf_list[stream->buf_num],
0102                       stream->dma_addr[stream->buf_num]);
0103         }
0104     }
0105 
0106     stream->state &= ~USB_STATE_URB_BUF;
0107 
0108     return 0;
0109 }
0110 
0111 static int usb_allocate_stream_buffers(struct usb_data_stream *stream, int num, unsigned long size)
0112 {
0113     stream->buf_num = 0;
0114     stream->buf_size = size;
0115 
0116     deb_mem("all in all I will use %lu bytes for streaming\n",num*size);
0117 
0118     for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) {
0119         deb_mem("allocating buffer %d\n",stream->buf_num);
0120         if (( stream->buf_list[stream->buf_num] =
0121                     usb_alloc_coherent(stream->udev, size, GFP_KERNEL,
0122                     &stream->dma_addr[stream->buf_num]) ) == NULL) {
0123             deb_mem("not enough memory for urb-buffer allocation.\n");
0124             usb_free_stream_buffers(stream);
0125             return -ENOMEM;
0126         }
0127         deb_mem("buffer %d: %p (dma: %Lu)\n",
0128             stream->buf_num,
0129 stream->buf_list[stream->buf_num], (long long)stream->dma_addr[stream->buf_num]);
0130         memset(stream->buf_list[stream->buf_num],0,size);
0131         stream->state |= USB_STATE_URB_BUF;
0132     }
0133     deb_mem("allocation successful\n");
0134 
0135     return 0;
0136 }
0137 
0138 static int usb_bulk_urb_init(struct usb_data_stream *stream)
0139 {
0140     int i, j;
0141 
0142     if ((i = usb_allocate_stream_buffers(stream,stream->props.count,
0143                     stream->props.u.bulk.buffersize)) < 0)
0144         return i;
0145 
0146     /* allocate the URBs */
0147     for (i = 0; i < stream->props.count; i++) {
0148         stream->urb_list[i] = usb_alloc_urb(0, GFP_KERNEL);
0149         if (!stream->urb_list[i]) {
0150             deb_mem("not enough memory for urb_alloc_urb!.\n");
0151             for (j = 0; j < i; j++)
0152                 usb_free_urb(stream->urb_list[j]);
0153             return -ENOMEM;
0154         }
0155         usb_fill_bulk_urb( stream->urb_list[i], stream->udev,
0156                 usb_rcvbulkpipe(stream->udev,stream->props.endpoint),
0157                 stream->buf_list[i],
0158                 stream->props.u.bulk.buffersize,
0159                 usb_urb_complete, stream);
0160 
0161         stream->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
0162         stream->urb_list[i]->transfer_dma = stream->dma_addr[i];
0163         stream->urbs_initialized++;
0164     }
0165     return 0;
0166 }
0167 
0168 static int usb_isoc_urb_init(struct usb_data_stream *stream)
0169 {
0170     int i,j;
0171 
0172     if ((i = usb_allocate_stream_buffers(stream,stream->props.count,
0173                     stream->props.u.isoc.framesize*stream->props.u.isoc.framesperurb)) < 0)
0174         return i;
0175 
0176     /* allocate the URBs */
0177     for (i = 0; i < stream->props.count; i++) {
0178         struct urb *urb;
0179         int frame_offset = 0;
0180 
0181         stream->urb_list[i] = usb_alloc_urb(stream->props.u.isoc.framesperurb, GFP_KERNEL);
0182         if (!stream->urb_list[i]) {
0183             deb_mem("not enough memory for urb_alloc_urb!\n");
0184             for (j = 0; j < i; j++)
0185                 usb_free_urb(stream->urb_list[j]);
0186             return -ENOMEM;
0187         }
0188 
0189         urb = stream->urb_list[i];
0190 
0191         urb->dev = stream->udev;
0192         urb->context = stream;
0193         urb->complete = usb_urb_complete;
0194         urb->pipe = usb_rcvisocpipe(stream->udev,stream->props.endpoint);
0195         urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
0196         urb->interval = stream->props.u.isoc.interval;
0197         urb->number_of_packets = stream->props.u.isoc.framesperurb;
0198         urb->transfer_buffer_length = stream->buf_size;
0199         urb->transfer_buffer = stream->buf_list[i];
0200         urb->transfer_dma = stream->dma_addr[i];
0201 
0202         for (j = 0; j < stream->props.u.isoc.framesperurb; j++) {
0203             urb->iso_frame_desc[j].offset = frame_offset;
0204             urb->iso_frame_desc[j].length = stream->props.u.isoc.framesize;
0205             frame_offset += stream->props.u.isoc.framesize;
0206         }
0207 
0208         stream->urbs_initialized++;
0209     }
0210     return 0;
0211 }
0212 
0213 int usb_urb_init(struct usb_data_stream *stream, struct usb_data_stream_properties *props)
0214 {
0215     if (stream == NULL || props == NULL)
0216         return -EINVAL;
0217 
0218     memcpy(&stream->props, props, sizeof(*props));
0219 
0220     usb_clear_halt(stream->udev,usb_rcvbulkpipe(stream->udev,stream->props.endpoint));
0221 
0222     if (stream->complete == NULL) {
0223         err("there is no data callback - this doesn't make sense.");
0224         return -EINVAL;
0225     }
0226 
0227     switch (stream->props.type) {
0228         case USB_BULK:
0229             return usb_bulk_urb_init(stream);
0230         case USB_ISOC:
0231             return usb_isoc_urb_init(stream);
0232         default:
0233             err("unknown URB-type for data transfer.");
0234             return -EINVAL;
0235     }
0236 }
0237 
0238 int usb_urb_exit(struct usb_data_stream *stream)
0239 {
0240     int i;
0241 
0242     usb_urb_kill(stream);
0243 
0244     for (i = 0; i < stream->urbs_initialized; i++) {
0245         if (stream->urb_list[i] != NULL) {
0246             deb_mem("freeing URB no. %d.\n",i);
0247             /* free the URBs */
0248             usb_free_urb(stream->urb_list[i]);
0249         }
0250     }
0251     stream->urbs_initialized = 0;
0252 
0253     usb_free_stream_buffers(stream);
0254     return 0;
0255 }