Date: Fri, 3 Sep 2010 15:56:49 +0200 From: Piet Skiet <tuksgig@gmail.com> To: Hans Petter Selasky <hselasky@c2i.net> Cc: freebsd-usb@freebsd.org Subject: Re: USB synchronous control transfers (for usb-to-serial) Message-ID: <AANLkTi=Erhq_2kYg5D5teQoOoOLE=3BSEF=yE==BoM-a@mail.gmail.com> In-Reply-To: <201008310947.07460.hselasky@c2i.net> References: <AANLkTinr3KbWOqgQoKVvF84H2c02fHh9SQRDeUkSRn4B@mail.gmail.com> <201008302113.33960.hselasky@c2i.net> <AANLkTinuHO1-23K6BW%2Bta3xZ4a6ObKzPyRd6=xAmE0S2@mail.gmail.com> <201008310947.07460.hselasky@c2i.net>
index | next in thread | previous in thread | raw e-mail
[-- Attachment #1 --] On Tue, Aug 31, 2010 at 9:47 AM, Hans Petter Selasky <hselasky@c2i.net> wrote: > On Tuesday 31 August 2010 09:39:46 Piet Skiet wrote: >> On Mon, Aug 30, 2010 at 9:13 PM, Hans Petter Selasky <hselasky@c2i.net> > wrote: >> > On Monday 30 August 2010 14:41:56 Piet Skiet wrote: >> >> On Mon, Aug 30, 2010 at 10:51 AM, Piet Skiet <tuksgig@gmail.com> wrote: >> >> > Hi, >> >> > >> >> > Can anyone clarify how to go about doing a synchronous usb control >> >> > transfer, similar to Linux's usb_control_msg? I want to implement the >> >> > TIOCMGET ioctl on a usb-to-serial converter. The Linux driver uses >> >> > synchronous control messages to read DCE and CTS serial pin status, >> >> > and I want to do something similar in FreeBSD. The usbdi(9) manpage >> >> > talks about control transfers using usbd_transfer_submit, but they're >> >> > not synchronous. What about using usbd_transfer_drain? Is there an >> >> > example driver showing setting up and doing control transfers? >> >> > >> >> > The ucom driver seems to only implement TIOCSBRK and TIOCCBRK iotcls >> >> > at the moment. >> >> > >> >> > Thanks >> >> >> >> Scanning through the ucom code, it seems to me that the >> >> usbd_do_request_proc has somehting to do with blocking control >> >> transfers. Am I on the right track here? >> > >> > Yes, this is correct. You have to re-format the do request information a >> > little bit compared with Linux. This function is supposed to be called >> > from a UCOM callback. Please also check recent changes in USB P4: >> > >> > http://p4web.freebsd.org/@md=d&cd=//depot/projects/usb/src/sys/dev/usb/co >> > ntroller/&cdf=//depot/projects/usb/src/sys/dev/usb/serial/usb_serial.c&c= >> > LJN@//depot/projects/usb/src/sys/dev/usb/serial/usb_serial.c?ac=22 >> > >> > --HPS >> >> OK, but I'm still a bit confused. I'm not sure in which callback to >> put the usb_do_request. For instance, the driver that I'm interested >> in is the uslcom.c driver for the cp210x usb-to-serial converter. It >> has two usb_config structs defined of type UE_BULK for read and write >> transfers. Do I need to add a third usb_config struct for UE_CONTROL? >> Should the usb_do_request then be called from the UE_CONTROL callback? > > Hi, > > The usb_config's are for asynchronous operation. The usbd_do_request_proc() > function is synchronous. I.E. it completes when it returns. The reason we have > this variant is to allow smooth exit and entry of the mutex which is locked > when you get callbacks from UCOM. All UCOM callbacks are pre-locked, and if > you don't exit the lock the kernel will complain. > >> The plan is to add a .ucom_ioctl to the uslcom.c driver and implement >> the TIOCMGET directly in the driver ioctl using synchronous usb >> transfers. I've already tested the .ucom_ioctl override and it works, >> now I just need to figure out how to do the usb transfers. >> >> BTW, the FTDI driver (uftdi.c) does things differently. It updates the >> msr (modem status register?) in the bulk read callback and then calls >> ucom_status_change to update any changes to ucom. > > The FTDI driver uses another mechanism to transfer that information. Probably > what you want to do is to add a timer/watchdog to poll that information > regularly. Then you can use a single asynchronous control transfer, and set > the interval of the transfer to 250ms, for example, so that you don't need to > allocate a separate timer to do this. Or maybe 100ms is better. You need to > test this. > > --HPS > Hi, Attached is the patch adding a 250ms polling control transfer to update the port status flags. I've also added CRTSCTS hardware flow control. I did some tests with minicom and with gtkterm. Minicom works perfectly, but gtkterm has problems at baud 115200 and also with hardware flow control. I also testes the Prolific driver (uplcom) with minicom and gtkterm, and gtkterm has the same problems at 115200 baud, so I'm assuming it's a gtkterm bug (not maintained anymore). BTW, do the usb-to-serial drivers need the force_short_xfer usb transfer flag? gtkterm seems to work slightly better without the flag... Anyway, thanks for the help so far [-- Attachment #2 --] 67d66 < /* Request types */ 71d69 < /* Request codes */ 77,78d74 < #define USLCOM_RCTRL 0x08 < #define USLCOM_SET_FLOWCTRL 0x13 80d75 < /* USLCOM_UART values */ 84d78 < /* USLCOM_CTRL/USLCOM_RCTRL values */ 91d84 < #define USLCOM_CTRL_RI 0x0040 94d86 < /* USLCOM_BAUD_RATE values */ 97d88 < /* USLCOM_DATA values */ 99a91 > 106d97 < /* USLCOM_BREAK values */ 110,117d100 < /* USLCOM_SET_FLOWCTRL values - 1st word */ < #define USLCOM_FLOW_DTR_ON 0x00000001 < #define USLCOM_FLOW_CTS_HS 0x00000008 /* CTS handshake */ < #define USLCOM_FLOW_RESERVED 0xFFFFFF80 < /* USLCOM_SET_FLOWCTRL values - 2nd word */ < #define USLCOM_FLOW_RTS_ON 0x00000040 < #define USLCOM_FLOW_RTS_HS 0x00000080 /* RTS handshake */ < 121d103 < USLCOM_CTRL_DT_RD, 143d124 < static usb_callback_t uslcom_control_callback; 166c147 < .flags = {.pipe_bof = 1,/*.force_short_xfer = 1,*/}, --- > .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 178,186d158 < [USLCOM_CTRL_DT_RD] = { < .type = UE_CONTROL, < .endpoint = 0x00, < .direction = UE_DIR_ANY, < .interval = 250, /* poll status every 250 ms */ < .bufsize = USLCOM_BULK_BUF_SIZE, < .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, < .callback = &uslcom_control_callback, < }, 293d264 < usbd_xfer_set_stall(sc->sc_xfer[USLCOM_CTRL_DT_RD]); 338,339d308 < /* Start polling status */ < usbd_transfer_start(sc->sc_xfer[USLCOM_CTRL_DT_RD]); 348,350d316 < /* Stop polling status */ < usbd_transfer_stop(sc->sc_xfer[USLCOM_CTRL_DT_RD]); < 425d390 < uint32_t flowctrl[4]; 476,495d440 < < if (t->c_cflag & CRTSCTS) { < flowctrl[0] = USLCOM_FLOW_RESERVED | USLCOM_FLOW_DTR_ON | < USLCOM_FLOW_CTS_HS; < flowctrl[1] = USLCOM_FLOW_RTS_HS; < } else { < flowctrl[0] = USLCOM_FLOW_RESERVED | USLCOM_FLOW_DTR_ON; < flowctrl[1] = USLCOM_FLOW_RTS_ON; < } < req.bmRequestType = USLCOM_WRITE; < req.bRequest = USLCOM_SET_FLOWCTRL; < USETW(req.wValue, 0); < USETW(req.wIndex, USLCOM_PORT_NO); < USETW(req.wLength, sizeof(flowctrl)); < < if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, < &req, flowctrl, 0, 1000)) { < DPRINTF("Set flowcontrol failed (ignored)\n"); < } < 592,646d536 < uslcom_control_callback(struct usb_xfer *xfer, usb_error_t error) < { < struct uslcom_softc *sc = usbd_xfer_softc(xfer); < struct usb_page_cache *pc; < uint8_t buf; < struct usb_device_request req; < uint8_t msr = 0; < < switch (USB_GET_STATE(xfer)) { < case USB_ST_TRANSFERRED: < pc = usbd_xfer_get_frame(xfer, 1); < usbd_copy_out(pc, 0, &buf, sizeof(buf)); < if (buf & USLCOM_CTRL_CTS) < msr |= SER_CTS; < if (buf & USLCOM_CTRL_DSR) < msr |= SER_DSR; < if (buf & USLCOM_CTRL_RI) < msr |= SER_RI; < if (buf & USLCOM_CTRL_DCD) < msr |= SER_DCD; < < if (msr != sc->sc_msr) { < DPRINTF("status change msr=0x%02x (was 0x%02x)\n", msr, sc->sc_msr); < sc->sc_msr = msr; < ucom_status_change(&sc->sc_ucom); < } < /* no break */ < case USB_ST_SETUP: < tr_setup: < req.bmRequestType = USLCOM_READ; < req.bRequest = USLCOM_RCTRL; < USETW(req.wValue, 0); < USETW(req.wIndex, 0); < USETW(req.wLength, sizeof(buf)); < < usbd_xfer_set_frames(xfer, 2); < usbd_xfer_set_frame_len(xfer, 0, sizeof(req)); < usbd_xfer_set_frame_len(xfer, 1, sizeof(buf)); < < pc = usbd_xfer_get_frame(xfer, 0); < usbd_copy_in(pc, 0, &req, sizeof(req)); < usbd_transfer_submit(xfer); < return; < < default: /* Error */ < if (error != USB_ERR_CANCELLED) { < /* try to clear stall first */ < usbd_xfer_set_stall(xfer); < goto tr_setup; < } < return; < } < } < < static voidhelp
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?AANLkTi=Erhq_2kYg5D5teQoOoOLE=3BSEF=yE==BoM-a>
