Deleted Added
full compact
1/* $NetBSD: uchcom.c,v 1.1 2007/09/03 17:57:37 tshiozak Exp $ */
2
3/*-
4 * Copyright (c) 2007, Takanori Watanabe
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 49 unchanged lines hidden (view full) ---

58 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
59 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
60 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
61 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
62 * POSSIBILITY OF SUCH DAMAGE.
63 */
64
65#include <sys/cdefs.h>
66__FBSDID("$FreeBSD: head/sys/dev/usb2/serial/uchcom2.c 187970 2009-02-01 00:51:25Z thompsa $");
66__FBSDID("$FreeBSD: head/sys/dev/usb2/serial/uchcom2.c 188413 2009-02-09 22:05:25Z thompsa $");
67
68/*
69 * driver for WinChipHead CH341/340, the worst USB-serial chip in the world.
70 */
71
72#include <dev/usb2/include/usb2_devid.h>
73#include <dev/usb2/include/usb2_standard.h>
74#include <dev/usb2/include/usb2_mfunc.h>

--- 68 unchanged lines hidden (view full) ---

143#define UCHCOM_INTR_STAT2 0x03
144#define UCHCOM_INTR_LEAST 4
145
146#define UCHCOM_BULK_BUF_SIZE 1024 /* bytes */
147
148enum {
149 UCHCOM_BULK_DT_WR,
150 UCHCOM_BULK_DT_RD,
151 UCHCOM_BULK_CS_WR,
152 UCHCOM_BULK_CS_RD,
151 UCHCOM_INTR_DT_RD,
154 UCHCOM_INTR_CS_RD,
155 UCHCOM_N_TRANSFER = 6,
152 UCHCOM_N_TRANSFER,
153};
154
155struct uchcom_softc {
156 struct usb2_com_super_softc sc_super_ucom;
157 struct usb2_com_softc sc_ucom;
158
159 struct usb2_xfer *sc_xfer[UCHCOM_N_TRANSFER];
160 struct usb2_device *sc_udev;
161
162 uint8_t sc_dtr; /* local copy */
163 uint8_t sc_rts; /* local copy */
164 uint8_t sc_version;
165 uint8_t sc_msr;
166 uint8_t sc_lsr; /* local status register */
170 uint8_t sc_flag;
171#define UCHCOM_FLAG_INTR_STALL 0x01
172#define UCHCOM_FLAG_READ_STALL 0x02
173#define UCHCOM_FLAG_WRITE_STALL 0x04
167};
168
169struct uchcom_divider {
170 uint8_t dv_prescaler;
171 uint8_t dv_div;
172 uint8_t dv_mod;
173};
174

--- 43 unchanged lines hidden (view full) ---

218static void uchcom_clear_chip(struct uchcom_softc *);
219static void uchcom_reset_chip(struct uchcom_softc *);
220
221static device_probe_t uchcom_probe;
222static device_attach_t uchcom_attach;
223static device_detach_t uchcom_detach;
224
225static usb2_callback_t uchcom_intr_callback;
233static usb2_callback_t uchcom_intr_clear_stall_callback;
226static usb2_callback_t uchcom_write_callback;
235static usb2_callback_t uchcom_write_clear_stall_callback;
227static usb2_callback_t uchcom_read_callback;
237static usb2_callback_t uchcom_read_clear_stall_callback;
228
229static const struct usb2_config uchcom_config_data[UCHCOM_N_TRANSFER] = {
230
231 [UCHCOM_BULK_DT_WR] = {
232 .type = UE_BULK,
233 .endpoint = UE_ADDR_ANY,
234 .direction = UE_DIR_OUT,
235 .mh.bufsize = UCHCOM_BULK_BUF_SIZE,

--- 5 unchanged lines hidden (view full) ---

241 .type = UE_BULK,
242 .endpoint = UE_ADDR_ANY,
243 .direction = UE_DIR_IN,
244 .mh.bufsize = UCHCOM_BULK_BUF_SIZE,
245 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
246 .mh.callback = &uchcom_read_callback,
247 },
248
259 [UCHCOM_BULK_CS_WR] = {
260 .type = UE_CONTROL,
261 .endpoint = 0x00, /* Control pipe */
262 .direction = UE_DIR_ANY,
263 .mh.bufsize = sizeof(struct usb2_device_request),
264 .mh.callback = &uchcom_write_clear_stall_callback,
265 .mh.timeout = 1000, /* 1 second */
266 .mh.interval = 50, /* 50ms */
267 },
268
269 [UCHCOM_BULK_CS_RD] = {
270 .type = UE_CONTROL,
271 .endpoint = 0x00, /* Control pipe */
272 .direction = UE_DIR_ANY,
273 .mh.bufsize = sizeof(struct usb2_device_request),
274 .mh.callback = &uchcom_read_clear_stall_callback,
275 .mh.timeout = 1000, /* 1 second */
276 .mh.interval = 50, /* 50ms */
277 },
278
249 [UCHCOM_INTR_DT_RD] = {
250 .type = UE_INTERRUPT,
251 .endpoint = UE_ADDR_ANY,
252 .direction = UE_DIR_IN,
253 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
254 .mh.bufsize = 0, /* use wMaxPacketSize */
255 .mh.callback = &uchcom_intr_callback,
256 },
287
288 [UCHCOM_INTR_CS_RD] = {
289 .type = UE_CONTROL,
290 .endpoint = 0x00, /* Control pipe */
291 .direction = UE_DIR_ANY,
292 .mh.bufsize = sizeof(struct usb2_device_request),
293 .mh.callback = &uchcom_intr_clear_stall_callback,
294 .mh.timeout = 1000, /* 1 second */
295 .mh.interval = 50, /* 50ms */
296 },
257};
258
259struct usb2_com_callback uchcom_callback = {
260 .usb2_com_cfg_get_status = &uchcom_cfg_get_status,
261 .usb2_com_cfg_set_dtr = &uchcom_cfg_set_dtr,
262 .usb2_com_cfg_set_rts = &uchcom_cfg_set_rts,
263 .usb2_com_cfg_set_break = &uchcom_cfg_set_break,
264 .usb2_com_cfg_param = &uchcom_cfg_param,

--- 68 unchanged lines hidden (view full) ---

333 uchcom_clear_chip(sc);
334 uchcom_reset_chip(sc);
335 uchcom_update_status(sc);
336
337 sc->sc_dtr = 1;
338 sc->sc_rts = 1;
339
340 /* clear stall at first run */
381 sc->sc_flag |= (UCHCOM_FLAG_READ_STALL |
382 UCHCOM_FLAG_WRITE_STALL);
341 usb2_transfer_set_stall(sc->sc_xfer[UCHCOM_BULK_DT_WR]);
342 usb2_transfer_set_stall(sc->sc_xfer[UCHCOM_BULK_DT_RD]);
343
344 error = usb2_com_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
345 &uchcom_callback, &Giant);
346 if (error) {
347 goto detach;
348 }
349 return (0);
350

--- 16 unchanged lines hidden (view full) ---

367 return (0);
368}
369
370/* ----------------------------------------------------------------------
371 * low level i/o
372 */
373
374static void
415uchcom_do_request(struct uchcom_softc *sc,
416 struct usb2_device_request *req, void *data)
417{
418 uint16_t length;
419 uint16_t actlen;
420 usb2_error_t err;
421
422 length = UGETW(req->wLength);
423 actlen = 0;
424
425 if (usb2_com_cfg_is_gone(&sc->sc_ucom)) {
426 goto done;
427 }
428 err = usb2_do_request_flags(sc->sc_udev, &Giant, req,
429 data, USB_SHORT_XFER_OK, &actlen, 1000);
430
431 if (err) {
432 DPRINTFN(0, "device request failed, err=%s "
433 "(ignored)\n", usb2_errstr(err));
434 }
435done:
436 if (length != actlen) {
437 if (req->bmRequestType & UT_READ) {
438 bzero(USB_ADD_BYTES(data, actlen), length - actlen);
439 }
440 }
441}
442
443static void
375uchcom_ctrl_write(struct uchcom_softc *sc, uint8_t reqno,
376 uint16_t value, uint16_t index)
377{
378 struct usb2_device_request req;
379
380 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
381 req.bRequest = reqno;
382 USETW(req.wValue, value);
383 USETW(req.wIndex, index);
384 USETW(req.wLength, 0);
385
455 uchcom_do_request(sc, &req, NULL);
386 usb2_com_cfg_do_request(sc->sc_udev,
387 &sc->sc_ucom, &req, NULL, 0, 1000);
388}
389
390static void
391uchcom_ctrl_read(struct uchcom_softc *sc, uint8_t reqno,
392 uint16_t value, uint16_t index, void *buf, uint16_t buflen)
393{
394 struct usb2_device_request req;
395
396 req.bmRequestType = UT_READ_VENDOR_DEVICE;
397 req.bRequest = reqno;
398 USETW(req.wValue, value);
399 USETW(req.wIndex, index);
400 USETW(req.wLength, buflen);
401
470 uchcom_do_request(sc, &req, buf);
402 usb2_com_cfg_do_request(sc->sc_udev,
403 &sc->sc_ucom, &req, buf, USB_SHORT_XFER_OK, 1000);
404}
405
406static void
407uchcom_write_reg(struct uchcom_softc *sc,
408 uint8_t reg1, uint8_t val1, uint8_t reg2, uint8_t val2)
409{
410 DPRINTF("0x%02X<-0x%02X, 0x%02X<-0x%02X\n",
411 (unsigned)reg1, (unsigned)val1,

--- 328 unchanged lines hidden (view full) ---

740uchcom_stop_read(struct usb2_com_softc *ucom)
741{
742 struct uchcom_softc *sc = ucom->sc_parent;
743
744 /* stop interrupt endpoint */
745 usb2_transfer_stop(sc->sc_xfer[UCHCOM_INTR_DT_RD]);
746
747 /* stop read endpoint */
815 usb2_transfer_stop(sc->sc_xfer[UCHCOM_BULK_CS_RD]);
748 usb2_transfer_stop(sc->sc_xfer[UCHCOM_BULK_DT_RD]);
749}
750
751static void
752uchcom_start_write(struct usb2_com_softc *ucom)
753{
754 struct uchcom_softc *sc = ucom->sc_parent;
755
756 usb2_transfer_start(sc->sc_xfer[UCHCOM_BULK_DT_WR]);
757}
758
759static void
760uchcom_stop_write(struct usb2_com_softc *ucom)
761{
762 struct uchcom_softc *sc = ucom->sc_parent;
763
832 usb2_transfer_stop(sc->sc_xfer[UCHCOM_BULK_CS_WR]);
764 usb2_transfer_stop(sc->sc_xfer[UCHCOM_BULK_DT_WR]);
765}
766
767/* ----------------------------------------------------------------------
768 * callback when the modem status is changed.
769 */
770static void
771uchcom_intr_callback(struct usb2_xfer *xfer)

--- 13 unchanged lines hidden (view full) ---

785 DPRINTF("data = 0x%02X 0x%02X 0x%02X 0x%02X\n",
786 (unsigned)buf[0], (unsigned)buf[1],
787 (unsigned)buf[2], (unsigned)buf[3]);
788
789 uchcom_convert_status(sc, buf[UCHCOM_INTR_STAT1]);
790 usb2_com_status_change(&sc->sc_ucom);
791 }
792 case USB_ST_SETUP:
862 if (sc->sc_flag & UCHCOM_FLAG_INTR_STALL) {
863 usb2_transfer_start(sc->sc_xfer[UCHCOM_INTR_CS_RD]);
864 } else {
865 xfer->frlengths[0] = xfer->max_data_length;
866 usb2_start_hardware(xfer);
867 }
793tr_setup:
794 xfer->frlengths[0] = xfer->max_data_length;
795 usb2_start_hardware(xfer);
796 break;
797
798 default: /* Error */
799 if (xfer->error != USB_ERR_CANCELLED) {
872 sc->sc_flag |= UCHCOM_FLAG_INTR_STALL;
873 usb2_transfer_start(sc->sc_xfer[UCHCOM_INTR_CS_RD]);
800 /* try to clear stall first */
801 xfer->flags.stall_pipe = 1;
802 goto tr_setup;
803 }
804 break;
805 }
806}
807
808static void
880uchcom_intr_clear_stall_callback(struct usb2_xfer *xfer)
881{
882 struct uchcom_softc *sc = xfer->priv_sc;
883 struct usb2_xfer *xfer_other = sc->sc_xfer[UCHCOM_INTR_DT_RD];
884
885 if (usb2_clear_stall_callback(xfer, xfer_other)) {
886 DPRINTF("stall cleared\n");
887 sc->sc_flag &= ~UCHCOM_FLAG_INTR_STALL;
888 usb2_transfer_start(xfer_other);
889 }
890}
891
892static void
809uchcom_write_callback(struct usb2_xfer *xfer)
810{
811 struct uchcom_softc *sc = xfer->priv_sc;
812 uint32_t actlen;
813
814 switch (USB_GET_STATE(xfer)) {
815 case USB_ST_SETUP:
816 case USB_ST_TRANSFERRED:
901 if (sc->sc_flag & UCHCOM_FLAG_WRITE_STALL) {
902 usb2_transfer_start(sc->sc_xfer[UCHCOM_BULK_CS_WR]);
903 return;
904 }
817tr_setup:
818 if (usb2_com_get_data(&sc->sc_ucom, xfer->frbuffers, 0,
819 UCHCOM_BULK_BUF_SIZE, &actlen)) {
820
821 DPRINTF("actlen = %d\n", actlen);
822
823 xfer->frlengths[0] = actlen;
824 usb2_start_hardware(xfer);
825 }
826 return;
827
828 default: /* Error */
829 if (xfer->error != USB_ERR_CANCELLED) {
917 sc->sc_flag |= UCHCOM_FLAG_WRITE_STALL;
918 usb2_transfer_start(sc->sc_xfer[UCHCOM_BULK_CS_WR]);
830 /* try to clear stall first */
831 xfer->flags.stall_pipe = 1;
832 goto tr_setup;
833 }
834 return;
835
836 }
837}
838
839static void
926uchcom_write_clear_stall_callback(struct usb2_xfer *xfer)
927{
928 struct uchcom_softc *sc = xfer->priv_sc;
929 struct usb2_xfer *xfer_other = sc->sc_xfer[UCHCOM_BULK_DT_WR];
930
931 if (usb2_clear_stall_callback(xfer, xfer_other)) {
932 DPRINTF("stall cleared\n");
933 sc->sc_flag &= ~UCHCOM_FLAG_WRITE_STALL;
934 usb2_transfer_start(xfer_other);
935 }
936}
937
938static void
840uchcom_read_callback(struct usb2_xfer *xfer)
841{
842 struct uchcom_softc *sc = xfer->priv_sc;
843
844 switch (USB_GET_STATE(xfer)) {
845 case USB_ST_TRANSFERRED:
846 usb2_com_put_data(&sc->sc_ucom, xfer->frbuffers, 0, xfer->actlen);
847
848 case USB_ST_SETUP:
948 if (sc->sc_flag & UCHCOM_FLAG_READ_STALL) {
949 usb2_transfer_start(sc->sc_xfer[UCHCOM_BULK_CS_RD]);
950 } else {
951 xfer->frlengths[0] = xfer->max_data_length;
952 usb2_start_hardware(xfer);
953 }
849tr_setup:
850 xfer->frlengths[0] = xfer->max_data_length;
851 usb2_start_hardware(xfer);
852 return;
853
854 default: /* Error */
855 if (xfer->error != USB_ERR_CANCELLED) {
958 sc->sc_flag |= UCHCOM_FLAG_READ_STALL;
959 usb2_transfer_start(sc->sc_xfer[UCHCOM_BULK_CS_RD]);
856 /* try to clear stall first */
857 xfer->flags.stall_pipe = 1;
858 goto tr_setup;
859 }
860 return;
962
861 }
862}
863
966static void
967uchcom_read_clear_stall_callback(struct usb2_xfer *xfer)
968{
969 struct uchcom_softc *sc = xfer->priv_sc;
970 struct usb2_xfer *xfer_other = sc->sc_xfer[UCHCOM_BULK_DT_RD];
971
972 if (usb2_clear_stall_callback(xfer, xfer_other)) {
973 DPRINTF("stall cleared\n");
974 sc->sc_flag &= ~UCHCOM_FLAG_READ_STALL;
975 usb2_transfer_start(xfer_other);
976 }
977}
978
864static device_method_t uchcom_methods[] = {
865 /* Device interface */
866 DEVMETHOD(device_probe, uchcom_probe),
867 DEVMETHOD(device_attach, uchcom_attach),
868 DEVMETHOD(device_detach, uchcom_detach),
869
870 {0, 0}
871};

--- 12 unchanged lines hidden ---