Date: Mon, 27 Oct 2014 20:03:13 -0700 From: Nidal Khalil <nedmath@gmail.com> To: freebsd-usb@freebsd.org Subject: USB stack driver options for the receive side question Message-ID: <CADoY-6if1KiLvQWTM89JL0GFOcmOUx7Gqg%2B9VVLEdaVyU-t58A@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
Hello All, I am setting up usb to transfer 3 frames on the bulk read descriptor but all I get is one frame transferred? Basically aframe = 1 However if I use .short_frames_ok = 1, then the transfer will pend till the three frames are received. This code is part of a network driver I would like to receive the one buffer it is the only one available and at most three buffers at a time if the transfer is complete. The one frame a time to respond to ping and three frame at time when the transfer load is heavy. Is this a limitation of FreeBSD. I searched all the drivers in the 9.3 release and I can not find a driver that is setup to receive multiple buffers? Below is my sample code: BWL_BULK_RD] = { .type = UE_BULK, .endpoint = UE_ADDR_ANY, .direction = UE_DIR_IN, .bufsize = 2000 * HW_IN_PENDING_FRAMES, .flags = { .pipe_bof = 1, .short_xfer_ok = 1, .ext_buffer = 1 }, .callback = dbus_usbos_recv_callback, .timeout = 0, /* no timeout */ .frames = HW_IN_PENDING_FRAMES }, static void dbus_usbos_recv_callback(CALLBACK_ARGS) { usbos_info_t *usbos_info = usbd_xfer_softc(xfer); struct bwl_rx_data *data; int actlen, sumlen, aframes, nframes, datalen, nr_frames; uint8 *buf; struct timespec tp; DBUSTRACE(("%s(): Enter \n", __FUNCTION__)); usbd_xfer_status(xfer, &actlen, &sumlen, &aframes, &nframes); switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: for (nr_frames = 0; nr_frames != aframes; nr_frames++) { FETCH_LIST_HEAD_ITEM(rx_q_lock, rx_q); if (!data) { DBUSERR(("got xfer frame but the rx_q till end ?? \n")); ASSERT(0); } usbd_xfer_frame_data(xfer, nr_frames, (void**)&buf, &datalen); kern_clock_gettime(curthread, CLOCK_UPTIME_PRECISE, &tp); mylog(&glog, "T %p: %d-%d:%u\n", buf, datalen, tp.tv_sec, tp.tv_nsec); if ((data->rxirb->buf != buf) || (data->rxirb->buf_len < datalen)) { DBUSERR(("the buff or data length not match ?? \n")); ASSERT(0); } MUTEX_UNLOCK(usbos_info); dbus_usbos_recv_complete(data, datalen, DBUS_OK); MUTEX_LOCK(usbos_info); } __transfered += nr_frames; /* no break, FALLTHROUGH */ case USB_ST_SETUP: SET_UP_XFER: nr_frames = 0; mtx_lock(&usbos_info->rx_q_lock); STAILQ_FOREACH(data, &usbos_info->rx_q, next) { if (data->rxirb == NULL) break; kern_clock_gettime(curthread, CLOCK_UPTIME_PRECISE, &tp); mylog(&glog, "S %p:%d-%d:%u\n", data->rxirb->buf, data->rxirb->buf_len, tp.tv_sec, tp.tv_nsec); usbd_xfer_set_frame_data(xfer, nr_frames, data->rxirb->buf, data->rxirb->buf_len); ++nr_frames; if (nr_frames >= BCMWL_HW_IN_PENDING_FRAMES) break; /* break out from STAILQ_FOREACH */ } mtx_unlock(&usbos_info->rx_q_lock); if (nr_frames) { usbd_xfer_set_frames(xfer, nr_frames); usbd_transfer_submit(xfer); } else { printf("%s(): end of rx_q \n", __FUNCTION__); } __setup += nr_frames; break; default: DBUSERR(("%s(): error = %s with %d bytes transfered\n", __FUNCTION__, usbd_errstr(error), actlen)); if (error == USB_ERR_STALLED || error == USB_ERR_IOERROR) { printf("%s(): calling DBUS_STATE_DOWN for %s\n", __FUNCTION__, usbd_errstr(error)); dbus_usbos_state_change(usbos_info, DBUS_STATE_DOWN); } if ((error != USB_ERR_CANCELLED) && (error != USB_ERR_STALLED)) { usbd_xfer_set_stall(xfer); goto SET_UP_XFER; } else { /* return all rxirb in the queue */ MUTEX_UNLOCK(usbos_info); mtx_lock(&usbos_info->rx_q_lock); while ((data = STAILQ_FIRST(&usbos_info->rx_q)) != NULL) { STAILQ_REMOVE_HEAD(&usbos_info->rx_q, next); dbus_usbos_recv_complete(data, 0, DBUS_ERR_RXFAIL); } STAILQ_INIT(&usbos_info->rx_q); mtx_unlock(&usbos_info->rx_q_lock); MUTEX_LOCK(usbos_info); } break; } }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CADoY-6if1KiLvQWTM89JL0GFOcmOUx7Gqg%2B9VVLEdaVyU-t58A>