xref: /openbmc/linux/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c (revision 0898782247ae533d1f4e47a06bc5d4870931b284)
116216333SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2786baecfSMauro Carvalho Chehab /*
3786baecfSMauro Carvalho Chehab  * DVB USB framework
4786baecfSMauro Carvalho Chehab  *
599e44da7SPatrick Boettcher  * Copyright (C) 2004-6 Patrick Boettcher <patrick.boettcher@posteo.de>
6786baecfSMauro Carvalho Chehab  * Copyright (C) 2012 Antti Palosaari <crope@iki.fi>
7786baecfSMauro Carvalho Chehab  */
8786baecfSMauro Carvalho Chehab 
9786baecfSMauro Carvalho Chehab #include "dvb_usb_common.h"
10786baecfSMauro Carvalho Chehab 
dvb_usb_v2_generic_io(struct dvb_usb_device * d,u8 * wbuf,u16 wlen,u8 * rbuf,u16 rlen)1113828c61SWei Yongjun static int dvb_usb_v2_generic_io(struct dvb_usb_device *d,
12acb0549aSAntti Palosaari 		u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
13786baecfSMauro Carvalho Chehab {
14786baecfSMauro Carvalho Chehab 	int ret, actual_length;
15786baecfSMauro Carvalho Chehab 
16206ace22SAntti Palosaari 	if (!wbuf || !wlen || !d->props->generic_bulk_ctrl_endpoint ||
17786baecfSMauro Carvalho Chehab 			!d->props->generic_bulk_ctrl_endpoint_response) {
18786baecfSMauro Carvalho Chehab 		dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, -EINVAL);
19786baecfSMauro Carvalho Chehab 		return -EINVAL;
20786baecfSMauro Carvalho Chehab 	}
21786baecfSMauro Carvalho Chehab 
22786baecfSMauro Carvalho Chehab 	dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, wlen, wbuf);
23786baecfSMauro Carvalho Chehab 
24786baecfSMauro Carvalho Chehab 	ret = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev,
25786baecfSMauro Carvalho Chehab 			d->props->generic_bulk_ctrl_endpoint), wbuf, wlen,
26786baecfSMauro Carvalho Chehab 			&actual_length, 2000);
27*dd5f551bSStefan Brüns 	if (ret) {
28786baecfSMauro Carvalho Chehab 		dev_err(&d->udev->dev, "%s: usb_bulk_msg() failed=%d\n",
29786baecfSMauro Carvalho Chehab 				KBUILD_MODNAME, ret);
30*dd5f551bSStefan Brüns 		return ret;
31*dd5f551bSStefan Brüns 	}
32*dd5f551bSStefan Brüns 	if (actual_length != wlen) {
33*dd5f551bSStefan Brüns 		dev_err(&d->udev->dev, "%s: usb_bulk_msg() write length=%d, actual=%d\n",
34*dd5f551bSStefan Brüns 			KBUILD_MODNAME, wlen, actual_length);
35*dd5f551bSStefan Brüns 		return -EIO;
36*dd5f551bSStefan Brüns 	}
37786baecfSMauro Carvalho Chehab 
38*dd5f551bSStefan Brüns 	/* an answer is expected */
39*dd5f551bSStefan Brüns 	if (rbuf && rlen) {
40786baecfSMauro Carvalho Chehab 		if (d->props->generic_bulk_ctrl_delay)
41786baecfSMauro Carvalho Chehab 			usleep_range(d->props->generic_bulk_ctrl_delay,
42786baecfSMauro Carvalho Chehab 					d->props->generic_bulk_ctrl_delay
43786baecfSMauro Carvalho Chehab 					+ 20000);
44786baecfSMauro Carvalho Chehab 
45786baecfSMauro Carvalho Chehab 		ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
46786baecfSMauro Carvalho Chehab 				d->props->generic_bulk_ctrl_endpoint_response),
47786baecfSMauro Carvalho Chehab 				rbuf, rlen, &actual_length, 2000);
48786baecfSMauro Carvalho Chehab 		if (ret)
496d7cfec4SAntti Palosaari 			dev_err(&d->udev->dev,
506d7cfec4SAntti Palosaari 					"%s: 2nd usb_bulk_msg() failed=%d\n",
516d7cfec4SAntti Palosaari 					KBUILD_MODNAME, ret);
52786baecfSMauro Carvalho Chehab 
53786baecfSMauro Carvalho Chehab 		dev_dbg(&d->udev->dev, "%s: <<< %*ph\n", __func__,
54786baecfSMauro Carvalho Chehab 				actual_length, rbuf);
55786baecfSMauro Carvalho Chehab 	}
56786baecfSMauro Carvalho Chehab 
57acb0549aSAntti Palosaari 	return ret;
58acb0549aSAntti Palosaari }
59acb0549aSAntti Palosaari 
dvb_usbv2_generic_rw(struct dvb_usb_device * d,u8 * wbuf,u16 wlen,u8 * rbuf,u16 rlen)60acb0549aSAntti Palosaari int dvb_usbv2_generic_rw(struct dvb_usb_device *d,
61acb0549aSAntti Palosaari 		u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
62acb0549aSAntti Palosaari {
63acb0549aSAntti Palosaari 	int ret;
64acb0549aSAntti Palosaari 
65acb0549aSAntti Palosaari 	mutex_lock(&d->usb_mutex);
66acb0549aSAntti Palosaari 	ret = dvb_usb_v2_generic_io(d, wbuf, wlen, rbuf, rlen);
67786baecfSMauro Carvalho Chehab 	mutex_unlock(&d->usb_mutex);
68acb0549aSAntti Palosaari 
69786baecfSMauro Carvalho Chehab 	return ret;
70786baecfSMauro Carvalho Chehab }
71786baecfSMauro Carvalho Chehab EXPORT_SYMBOL(dvb_usbv2_generic_rw);
72786baecfSMauro Carvalho Chehab 
dvb_usbv2_generic_write(struct dvb_usb_device * d,u8 * buf,u16 len)73786baecfSMauro Carvalho Chehab int dvb_usbv2_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len)
74786baecfSMauro Carvalho Chehab {
75acb0549aSAntti Palosaari 	int ret;
76acb0549aSAntti Palosaari 
77acb0549aSAntti Palosaari 	mutex_lock(&d->usb_mutex);
78acb0549aSAntti Palosaari 	ret = dvb_usb_v2_generic_io(d, buf, len, NULL, 0);
79acb0549aSAntti Palosaari 	mutex_unlock(&d->usb_mutex);
80acb0549aSAntti Palosaari 
81acb0549aSAntti Palosaari 	return ret;
82786baecfSMauro Carvalho Chehab }
83786baecfSMauro Carvalho Chehab EXPORT_SYMBOL(dvb_usbv2_generic_write);
84acb0549aSAntti Palosaari 
dvb_usbv2_generic_rw_locked(struct dvb_usb_device * d,u8 * wbuf,u16 wlen,u8 * rbuf,u16 rlen)85acb0549aSAntti Palosaari int dvb_usbv2_generic_rw_locked(struct dvb_usb_device *d,
86acb0549aSAntti Palosaari 		u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
87acb0549aSAntti Palosaari {
88acb0549aSAntti Palosaari 	return dvb_usb_v2_generic_io(d, wbuf, wlen, rbuf, rlen);
89acb0549aSAntti Palosaari }
90acb0549aSAntti Palosaari EXPORT_SYMBOL(dvb_usbv2_generic_rw_locked);
91acb0549aSAntti Palosaari 
dvb_usbv2_generic_write_locked(struct dvb_usb_device * d,u8 * buf,u16 len)92acb0549aSAntti Palosaari int dvb_usbv2_generic_write_locked(struct dvb_usb_device *d, u8 *buf, u16 len)
93acb0549aSAntti Palosaari {
94acb0549aSAntti Palosaari 	return dvb_usb_v2_generic_io(d, buf, len, NULL, 0);
95acb0549aSAntti Palosaari }
96acb0549aSAntti Palosaari EXPORT_SYMBOL(dvb_usbv2_generic_write_locked);
97