dvb_usb_urb.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * DVB USB framework
  4. *
  5. * Copyright (C) 2004-6 Patrick Boettcher <patrick.boettcher@posteo.de>
  6. * Copyright (C) 2012 Antti Palosaari <crope@iki.fi>
  7. */
  8. #include "dvb_usb_common.h"
  9. static int dvb_usb_v2_generic_io(struct dvb_usb_device *d,
  10. u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
  11. {
  12. int ret, actual_length;
  13. if (!wbuf || !wlen || !d->props->generic_bulk_ctrl_endpoint ||
  14. !d->props->generic_bulk_ctrl_endpoint_response) {
  15. dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, -EINVAL);
  16. return -EINVAL;
  17. }
  18. dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, wlen, wbuf);
  19. ret = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev,
  20. d->props->generic_bulk_ctrl_endpoint), wbuf, wlen,
  21. &actual_length, 2000);
  22. if (ret) {
  23. dev_err(&d->udev->dev, "%s: usb_bulk_msg() failed=%d\n",
  24. KBUILD_MODNAME, ret);
  25. return ret;
  26. }
  27. if (actual_length != wlen) {
  28. dev_err(&d->udev->dev, "%s: usb_bulk_msg() write length=%d, actual=%d\n",
  29. KBUILD_MODNAME, wlen, actual_length);
  30. return -EIO;
  31. }
  32. /* an answer is expected */
  33. if (rbuf && rlen) {
  34. if (d->props->generic_bulk_ctrl_delay)
  35. usleep_range(d->props->generic_bulk_ctrl_delay,
  36. d->props->generic_bulk_ctrl_delay
  37. + 20000);
  38. ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
  39. d->props->generic_bulk_ctrl_endpoint_response),
  40. rbuf, rlen, &actual_length, 2000);
  41. if (ret)
  42. dev_err(&d->udev->dev,
  43. "%s: 2nd usb_bulk_msg() failed=%d\n",
  44. KBUILD_MODNAME, ret);
  45. dev_dbg(&d->udev->dev, "%s: <<< %*ph\n", __func__,
  46. actual_length, rbuf);
  47. }
  48. return ret;
  49. }
  50. int dvb_usbv2_generic_rw(struct dvb_usb_device *d,
  51. u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
  52. {
  53. int ret;
  54. mutex_lock(&d->usb_mutex);
  55. ret = dvb_usb_v2_generic_io(d, wbuf, wlen, rbuf, rlen);
  56. mutex_unlock(&d->usb_mutex);
  57. return ret;
  58. }
  59. EXPORT_SYMBOL(dvb_usbv2_generic_rw);
  60. int dvb_usbv2_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len)
  61. {
  62. int ret;
  63. mutex_lock(&d->usb_mutex);
  64. ret = dvb_usb_v2_generic_io(d, buf, len, NULL, 0);
  65. mutex_unlock(&d->usb_mutex);
  66. return ret;
  67. }
  68. EXPORT_SYMBOL(dvb_usbv2_generic_write);
  69. int dvb_usbv2_generic_rw_locked(struct dvb_usb_device *d,
  70. u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
  71. {
  72. return dvb_usb_v2_generic_io(d, wbuf, wlen, rbuf, rlen);
  73. }
  74. EXPORT_SYMBOL(dvb_usbv2_generic_rw_locked);
  75. int dvb_usbv2_generic_write_locked(struct dvb_usb_device *d, u8 *buf, u16 len)
  76. {
  77. return dvb_usb_v2_generic_io(d, buf, len, NULL, 0);
  78. }
  79. EXPORT_SYMBOL(dvb_usbv2_generic_write_locked);