summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2014-09-20 07:59:34 +0000
committerhselasky <hselasky@FreeBSD.org>2014-09-20 07:59:34 +0000
commita3656a12d1a2e16dead50e4dd7f0ad26403a469b (patch)
tree083ef636dee38c4d76820dd2cf07e20a7794438f /sys/dev
parentb462b88810e3c403b0297489af2b79f055a26640 (diff)
downloadFreeBSD-src-a3656a12d1a2e16dead50e4dd7f0ad26403a469b.zip
FreeBSD-src-a3656a12d1a2e16dead50e4dd7f0ad26403a469b.tar.gz
MFC r271492:
Workaround for receiving Voice Calls using the E1750 dongle from Huawei. It might appear as if the firmware is allocating memory blocks according to the USB transfer size and if there is initially a lot of data, like at the answering machine prompt, it simply dies without any apparent reason. The simple workaround for this is to force a zero length packet at hardware level after every 512 bytes of data. This will force the other side to use smaller memory blocks aswell. Approved by: re, gjb
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/serial/u3g.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/sys/dev/usb/serial/u3g.c b/sys/dev/usb/serial/u3g.c
index 125c104..b32cb53 100644
--- a/sys/dev/usb/serial/u3g.c
+++ b/sys/dev/usb/serial/u3g.c
@@ -75,6 +75,8 @@ SYSCTL_INT(_hw_usb_u3g, OID_AUTO, debug, CTLFLAG_RW,
#define U3G_MAXPORTS 12
#define U3G_CONFIG_INDEX 0
#define U3G_BSIZE 2048
+#define U3G_TXSIZE (U3G_BSIZE / U3G_TXFRAMES)
+#define U3G_TXFRAMES 4
#define U3GSP_GPRS 0
#define U3GSP_EDGE 1
@@ -153,6 +155,7 @@ static const struct usb_config u3g_config[U3G_N_TRANSFER] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = U3G_BSIZE,/* bytes */
+ .frames = U3G_TXFRAMES,
.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
.callback = &u3g_write_callback,
},
@@ -1012,14 +1015,22 @@ u3g_write_callback(struct usb_xfer *xfer, usb_error_t error)
struct ucom_softc *ucom = usbd_xfer_softc(xfer);
struct usb_page_cache *pc;
uint32_t actlen;
+ uint32_t frame;
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
case USB_ST_SETUP:
tr_setup:
- pc = usbd_xfer_get_frame(xfer, 0);
- if (ucom_get_data(ucom, pc, 0, U3G_BSIZE, &actlen)) {
- usbd_xfer_set_frame_len(xfer, 0, actlen);
+ for (frame = 0; frame != U3G_TXFRAMES; frame++) {
+ usbd_xfer_set_frame_offset(xfer, frame * U3G_TXSIZE, frame);
+
+ pc = usbd_xfer_get_frame(xfer, frame);
+ if (ucom_get_data(ucom, pc, 0, U3G_TXSIZE, &actlen) == 0)
+ break;
+ usbd_xfer_set_frame_len(xfer, frame, actlen);
+ }
+ if (frame != 0) {
+ usbd_xfer_set_frames(xfer, frame);
usbd_transfer_submit(xfer);
}
break;
OpenPOWER on IntegriCloud