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