1 // SPDX-License-Identifier: GPL-2.0 2 /* dvb-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 * USB and URB stuff. 9 */ 10 #include "dvb-usb-common.h" 11 12 int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, 13 u16 rlen, int delay_ms) 14 { 15 int actlen,ret = -ENOMEM; 16 17 if (!d || wbuf == NULL || wlen == 0) 18 return -EINVAL; 19 20 if (d->props.generic_bulk_ctrl_endpoint == 0) { 21 err("endpoint for generic control not specified."); 22 return -EINVAL; 23 } 24 25 if ((ret = mutex_lock_interruptible(&d->usb_mutex))) 26 return ret; 27 28 deb_xfer(">>> "); 29 debug_dump(wbuf,wlen,deb_xfer); 30 31 ret = usb_bulk_msg(d->udev,usb_sndbulkpipe(d->udev, 32 d->props.generic_bulk_ctrl_endpoint), wbuf,wlen,&actlen, 33 2000); 34 35 if (ret) 36 err("bulk message failed: %d (%d/%d)",ret,wlen,actlen); 37 else 38 ret = actlen != wlen ? -1 : 0; 39 40 /* an answer is expected, and no error before */ 41 if (!ret && rbuf && rlen) { 42 if (delay_ms) 43 msleep(delay_ms); 44 45 ret = usb_bulk_msg(d->udev,usb_rcvbulkpipe(d->udev, 46 d->props.generic_bulk_ctrl_endpoint_response ? 47 d->props.generic_bulk_ctrl_endpoint_response : 48 d->props.generic_bulk_ctrl_endpoint),rbuf,rlen,&actlen, 49 2000); 50 51 if (ret) 52 err("recv bulk message failed: %d",ret); 53 else { 54 deb_xfer("<<< "); 55 debug_dump(rbuf,actlen,deb_xfer); 56 } 57 } 58 59 mutex_unlock(&d->usb_mutex); 60 return ret; 61 } 62 EXPORT_SYMBOL(dvb_usb_generic_rw); 63 64 int dvb_usb_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len) 65 { 66 return dvb_usb_generic_rw(d,buf,len,NULL,0,0); 67 } 68 EXPORT_SYMBOL(dvb_usb_generic_write); 69 70 static void dvb_usb_data_complete(struct usb_data_stream *stream, u8 *buffer, size_t length) 71 { 72 struct dvb_usb_adapter *adap = stream->user_priv; 73 if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB) 74 dvb_dmx_swfilter(&adap->demux, buffer, length); 75 } 76 77 static void dvb_usb_data_complete_204(struct usb_data_stream *stream, u8 *buffer, size_t length) 78 { 79 struct dvb_usb_adapter *adap = stream->user_priv; 80 if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB) 81 dvb_dmx_swfilter_204(&adap->demux, buffer, length); 82 } 83 84 static void dvb_usb_data_complete_raw(struct usb_data_stream *stream, 85 u8 *buffer, size_t length) 86 { 87 struct dvb_usb_adapter *adap = stream->user_priv; 88 if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB) 89 dvb_dmx_swfilter_raw(&adap->demux, buffer, length); 90 } 91 92 int dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap) 93 { 94 int i, ret = 0; 95 for (i = 0; i < adap->props.num_frontends; i++) { 96 97 adap->fe_adap[i].stream.udev = adap->dev->udev; 98 if (adap->props.fe[i].caps & DVB_USB_ADAP_RECEIVES_204_BYTE_TS) 99 adap->fe_adap[i].stream.complete = 100 dvb_usb_data_complete_204; 101 else 102 if (adap->props.fe[i].caps & DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD) 103 adap->fe_adap[i].stream.complete = 104 dvb_usb_data_complete_raw; 105 else 106 adap->fe_adap[i].stream.complete = dvb_usb_data_complete; 107 adap->fe_adap[i].stream.user_priv = adap; 108 ret = usb_urb_init(&adap->fe_adap[i].stream, 109 &adap->props.fe[i].stream); 110 if (ret < 0) 111 break; 112 } 113 return ret; 114 } 115 116 int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap) 117 { 118 int i; 119 for (i = 0; i < adap->props.num_frontends; i++) 120 usb_urb_exit(&adap->fe_adap[i].stream); 121 return 0; 122 } 123