Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* dvb-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  * USB and URB stuff.
0009  */
0010 #include "dvb-usb-common.h"
0011 
0012 int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
0013     u16 rlen, int delay_ms)
0014 {
0015     int actlen = 0, ret = -ENOMEM;
0016 
0017     if (!d || wbuf == NULL || wlen == 0)
0018         return -EINVAL;
0019 
0020     if (d->props.generic_bulk_ctrl_endpoint == 0) {
0021         err("endpoint for generic control not specified.");
0022         return -EINVAL;
0023     }
0024 
0025     if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
0026         return ret;
0027 
0028     deb_xfer(">>> ");
0029     debug_dump(wbuf,wlen,deb_xfer);
0030 
0031     ret = usb_bulk_msg(d->udev,usb_sndbulkpipe(d->udev,
0032             d->props.generic_bulk_ctrl_endpoint), wbuf,wlen,&actlen,
0033             2000);
0034 
0035     if (ret)
0036         err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);
0037     else
0038         ret = actlen != wlen ? -1 : 0;
0039 
0040     /* an answer is expected, and no error before */
0041     if (!ret && rbuf && rlen) {
0042         if (delay_ms)
0043             msleep(delay_ms);
0044 
0045         ret = usb_bulk_msg(d->udev,usb_rcvbulkpipe(d->udev,
0046                 d->props.generic_bulk_ctrl_endpoint_response ?
0047                 d->props.generic_bulk_ctrl_endpoint_response :
0048                 d->props.generic_bulk_ctrl_endpoint),rbuf,rlen,&actlen,
0049                 2000);
0050 
0051         if (ret)
0052             err("recv bulk message failed: %d",ret);
0053         else {
0054             deb_xfer("<<< ");
0055             debug_dump(rbuf,actlen,deb_xfer);
0056         }
0057     }
0058 
0059     mutex_unlock(&d->usb_mutex);
0060     return ret;
0061 }
0062 EXPORT_SYMBOL(dvb_usb_generic_rw);
0063 
0064 int dvb_usb_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len)
0065 {
0066     return dvb_usb_generic_rw(d,buf,len,NULL,0,0);
0067 }
0068 EXPORT_SYMBOL(dvb_usb_generic_write);
0069 
0070 static void dvb_usb_data_complete(struct usb_data_stream *stream, u8 *buffer, size_t length)
0071 {
0072     struct dvb_usb_adapter *adap = stream->user_priv;
0073     if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB)
0074         dvb_dmx_swfilter(&adap->demux, buffer, length);
0075 }
0076 
0077 static void dvb_usb_data_complete_204(struct usb_data_stream *stream, u8 *buffer, size_t length)
0078 {
0079     struct dvb_usb_adapter *adap = stream->user_priv;
0080     if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB)
0081         dvb_dmx_swfilter_204(&adap->demux, buffer, length);
0082 }
0083 
0084 static void dvb_usb_data_complete_raw(struct usb_data_stream *stream,
0085                       u8 *buffer, size_t length)
0086 {
0087     struct dvb_usb_adapter *adap = stream->user_priv;
0088     if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB)
0089         dvb_dmx_swfilter_raw(&adap->demux, buffer, length);
0090 }
0091 
0092 int dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap)
0093 {
0094     int i, ret = 0;
0095     for (i = 0; i < adap->props.num_frontends; i++) {
0096 
0097         adap->fe_adap[i].stream.udev      = adap->dev->udev;
0098         if (adap->props.fe[i].caps & DVB_USB_ADAP_RECEIVES_204_BYTE_TS)
0099             adap->fe_adap[i].stream.complete =
0100                 dvb_usb_data_complete_204;
0101         else
0102         if (adap->props.fe[i].caps & DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD)
0103             adap->fe_adap[i].stream.complete =
0104                 dvb_usb_data_complete_raw;
0105         else
0106         adap->fe_adap[i].stream.complete  = dvb_usb_data_complete;
0107         adap->fe_adap[i].stream.user_priv = adap;
0108         ret = usb_urb_init(&adap->fe_adap[i].stream,
0109                    &adap->props.fe[i].stream);
0110         if (ret < 0)
0111             break;
0112     }
0113     return ret;
0114 }
0115 
0116 int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap)
0117 {
0118     int i;
0119     for (i = 0; i < adap->props.num_frontends; i++)
0120         usb_urb_exit(&adap->fe_adap[i].stream);
0121     return 0;
0122 }