162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* dvb-usb-urb.c is part of the DVB USB library. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@posteo.de) 562306a36Sopenharmony_ci * see dvb-usb-init.c for copyright information. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * This file keeps functions for initializing and handling the 862306a36Sopenharmony_ci * USB and URB stuff. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci#include "dvb-usb-common.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ciint dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, 1362306a36Sopenharmony_ci u16 rlen, int delay_ms) 1462306a36Sopenharmony_ci{ 1562306a36Sopenharmony_ci int actlen = 0, ret = -ENOMEM; 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci if (!d || wbuf == NULL || wlen == 0) 1862306a36Sopenharmony_ci return -EINVAL; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci if (d->props.generic_bulk_ctrl_endpoint == 0) { 2162306a36Sopenharmony_ci err("endpoint for generic control not specified."); 2262306a36Sopenharmony_ci return -EINVAL; 2362306a36Sopenharmony_ci } 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci if ((ret = mutex_lock_interruptible(&d->usb_mutex))) 2662306a36Sopenharmony_ci return ret; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci deb_xfer(">>> "); 2962306a36Sopenharmony_ci debug_dump(wbuf,wlen,deb_xfer); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci ret = usb_bulk_msg(d->udev,usb_sndbulkpipe(d->udev, 3262306a36Sopenharmony_ci d->props.generic_bulk_ctrl_endpoint), wbuf,wlen,&actlen, 3362306a36Sopenharmony_ci 2000); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci if (ret) 3662306a36Sopenharmony_ci err("bulk message failed: %d (%d/%d)",ret,wlen,actlen); 3762306a36Sopenharmony_ci else 3862306a36Sopenharmony_ci ret = actlen != wlen ? -1 : 0; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci /* an answer is expected, and no error before */ 4162306a36Sopenharmony_ci if (!ret && rbuf && rlen) { 4262306a36Sopenharmony_ci if (delay_ms) 4362306a36Sopenharmony_ci msleep(delay_ms); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci ret = usb_bulk_msg(d->udev,usb_rcvbulkpipe(d->udev, 4662306a36Sopenharmony_ci d->props.generic_bulk_ctrl_endpoint_response ? 4762306a36Sopenharmony_ci d->props.generic_bulk_ctrl_endpoint_response : 4862306a36Sopenharmony_ci d->props.generic_bulk_ctrl_endpoint),rbuf,rlen,&actlen, 4962306a36Sopenharmony_ci 2000); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci if (ret) 5262306a36Sopenharmony_ci err("recv bulk message failed: %d",ret); 5362306a36Sopenharmony_ci else { 5462306a36Sopenharmony_ci deb_xfer("<<< "); 5562306a36Sopenharmony_ci debug_dump(rbuf,actlen,deb_xfer); 5662306a36Sopenharmony_ci } 5762306a36Sopenharmony_ci } 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci mutex_unlock(&d->usb_mutex); 6062306a36Sopenharmony_ci return ret; 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ciEXPORT_SYMBOL(dvb_usb_generic_rw); 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ciint dvb_usb_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci return dvb_usb_generic_rw(d,buf,len,NULL,0,0); 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ciEXPORT_SYMBOL(dvb_usb_generic_write); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic void dvb_usb_data_complete(struct usb_data_stream *stream, u8 *buffer, size_t length) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci struct dvb_usb_adapter *adap = stream->user_priv; 7362306a36Sopenharmony_ci if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB) 7462306a36Sopenharmony_ci dvb_dmx_swfilter(&adap->demux, buffer, length); 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic void dvb_usb_data_complete_204(struct usb_data_stream *stream, u8 *buffer, size_t length) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci struct dvb_usb_adapter *adap = stream->user_priv; 8062306a36Sopenharmony_ci if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB) 8162306a36Sopenharmony_ci dvb_dmx_swfilter_204(&adap->demux, buffer, length); 8262306a36Sopenharmony_ci} 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic void dvb_usb_data_complete_raw(struct usb_data_stream *stream, 8562306a36Sopenharmony_ci u8 *buffer, size_t length) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci struct dvb_usb_adapter *adap = stream->user_priv; 8862306a36Sopenharmony_ci if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB) 8962306a36Sopenharmony_ci dvb_dmx_swfilter_raw(&adap->demux, buffer, length); 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ciint dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci int i, ret = 0; 9562306a36Sopenharmony_ci for (i = 0; i < adap->props.num_frontends; i++) { 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci adap->fe_adap[i].stream.udev = adap->dev->udev; 9862306a36Sopenharmony_ci if (adap->props.fe[i].caps & DVB_USB_ADAP_RECEIVES_204_BYTE_TS) 9962306a36Sopenharmony_ci adap->fe_adap[i].stream.complete = 10062306a36Sopenharmony_ci dvb_usb_data_complete_204; 10162306a36Sopenharmony_ci else 10262306a36Sopenharmony_ci if (adap->props.fe[i].caps & DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD) 10362306a36Sopenharmony_ci adap->fe_adap[i].stream.complete = 10462306a36Sopenharmony_ci dvb_usb_data_complete_raw; 10562306a36Sopenharmony_ci else 10662306a36Sopenharmony_ci adap->fe_adap[i].stream.complete = dvb_usb_data_complete; 10762306a36Sopenharmony_ci adap->fe_adap[i].stream.user_priv = adap; 10862306a36Sopenharmony_ci ret = usb_urb_init(&adap->fe_adap[i].stream, 10962306a36Sopenharmony_ci &adap->props.fe[i].stream); 11062306a36Sopenharmony_ci if (ret < 0) 11162306a36Sopenharmony_ci break; 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci return ret; 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ciint dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci int i; 11962306a36Sopenharmony_ci for (i = 0; i < adap->props.num_frontends; i++) 12062306a36Sopenharmony_ci usb_urb_exit(&adap->fe_adap[i].stream); 12162306a36Sopenharmony_ci return 0; 12262306a36Sopenharmony_ci} 123