1/* $FreeBSD: head/sys/dev/usb2/serial/umoscom2.c 187259 2009-01-15 02:35:40Z thompsa $ */ |
2/* $OpenBSD: umoscom.c,v 1.2 2006/10/26 06:02:43 jsg Exp $ */ 3 4/* 5 * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. --- 29 unchanged lines hidden (view full) --- 39static int umoscom_debug = 0; 40 41SYSCTL_NODE(_hw_usb2, OID_AUTO, umoscom, CTLFLAG_RW, 0, "USB umoscom"); 42SYSCTL_INT(_hw_usb2_umoscom, OID_AUTO, debug, CTLFLAG_RW, 43 &umoscom_debug, 0, "Debug level"); 44#endif 45 46#define UMOSCOM_BUFSIZE 1024 /* bytes */ |
47 48#define UMOSCOM_CONFIG_INDEX 0 49#define UMOSCOM_IFACE_INDEX 0 50 51/* interrupt packet */ 52#define UMOSCOM_IIR_RLS 0x06 53#define UMOSCOM_IIR_RDA 0x04 54#define UMOSCOM_IIR_CTI 0x0c --- 93 unchanged lines hidden (view full) --- 148#define UMOSCOM_MSR_CD_CHG 0x08 149#define UMOSCOM_MSR_CTS 0x10 150#define UMOSCOM_MSR_RTS 0x20 151#define UMOSCOM_MSR_RI 0x40 152#define UMOSCOM_MSR_CD 0x80 153 154#define UMOSCOM_BAUD_REF 115200 155 |
156enum { 157 UMOSCOM_BULK_DT_WR, 158 UMOSCOM_BULK_DT_RD, 159 UMOSCOM_BULK_CS_WR, 160 UMOSCOM_BULK_CS_RD, 161 UMOSCOM_INTR_DT_RD, 162 UMOSCOM_INTR_CS_RD, 163 UMOSCOM_N_TRANSFER = 6, 164}; 165 |
166struct umoscom_softc { 167 struct usb2_com_super_softc sc_super_ucom; 168 struct usb2_com_softc sc_ucom; 169 |
170 struct usb2_xfer *sc_xfer[UMOSCOM_N_TRANSFER]; |
171 struct usb2_device *sc_udev; 172 173 uint8_t sc_mcr; 174 uint8_t sc_lcr; 175 uint8_t sc_flags; 176#define UMOSCOM_FLAG_READ_STALL 0x01 177#define UMOSCOM_FLAG_WRITE_STALL 0x02 178#define UMOSCOM_FLAG_INTR_STALL 0x04 --- 25 unchanged lines hidden (view full) --- 204static uint8_t umoscom_cfg_read(struct umoscom_softc *, uint16_t); 205static void umoscom_cfg_do_request(struct umoscom_softc *, 206 struct usb2_device_request *, void *); 207static void umoscom_start_read(struct usb2_com_softc *); 208static void umoscom_stop_read(struct usb2_com_softc *); 209static void umoscom_start_write(struct usb2_com_softc *); 210static void umoscom_stop_write(struct usb2_com_softc *); 211 |
212static const struct usb2_config umoscom_config_data[UMOSCOM_N_TRANSFER] = { |
213 |
214 [UMOSCOM_BULK_DT_WR] = { |
215 .type = UE_BULK, 216 .endpoint = UE_ADDR_ANY, 217 .direction = UE_DIR_OUT, 218 .mh.bufsize = UMOSCOM_BUFSIZE, 219 .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 220 .mh.callback = &umoscom_write_callback, 221 }, 222 |
223 [UMOSCOM_BULK_DT_RD] = { |
224 .type = UE_BULK, 225 .endpoint = UE_ADDR_ANY, 226 .direction = UE_DIR_IN, 227 .mh.bufsize = UMOSCOM_BUFSIZE, 228 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 229 .mh.callback = &umoscom_read_callback, 230 }, 231 |
232 [UMOSCOM_BULK_CS_WR] = { |
233 .type = UE_CONTROL, 234 .endpoint = 0x00, /* Control pipe */ 235 .direction = UE_DIR_ANY, 236 .mh.bufsize = sizeof(struct usb2_device_request), 237 .mh.callback = &umoscom_write_clear_stall_callback, 238 .mh.timeout = 1000, /* 1 second */ 239 .mh.interval = 50, /* 50ms */ 240 }, 241 |
242 [UMOSCOM_BULK_CS_RD] = { |
243 .type = UE_CONTROL, 244 .endpoint = 0x00, /* Control pipe */ 245 .direction = UE_DIR_ANY, 246 .mh.bufsize = sizeof(struct usb2_device_request), 247 .mh.callback = &umoscom_read_clear_stall_callback, 248 .mh.timeout = 1000, /* 1 second */ 249 .mh.interval = 50, /* 50ms */ 250 }, 251 |
252 [UMOSCOM_INTR_DT_RD] = { |
253 .type = UE_INTERRUPT, 254 .endpoint = UE_ADDR_ANY, 255 .direction = UE_DIR_IN, 256 .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 257 .mh.bufsize = 0, /* use wMaxPacketSize */ 258 .mh.callback = &umoscom_intr_callback, 259 }, 260 |
261 [UMOSCOM_INTR_CS_RD] = { |
262 .type = UE_CONTROL, 263 .endpoint = 0x00, /* Control pipe */ 264 .direction = UE_DIR_ANY, 265 .mh.bufsize = sizeof(struct usb2_device_request), 266 .mh.callback = &umoscom_intr_clear_stall_callback, 267 .mh.timeout = 1000, /* 1 second */ 268 .mh.interval = 50, /* 50ms */ 269 }, --- 72 unchanged lines hidden (view full) --- 342 sc->sc_mcr = 0x08; /* enable interrupts */ 343 344 /* XXX the device doesn't provide any ID string, so set a static one */ 345 device_set_desc(dev, "MOSCHIP USB Serial Port Adapter"); 346 device_printf(dev, "<MOSCHIP USB Serial Port Adapter>\n"); 347 348 iface_index = UMOSCOM_IFACE_INDEX; 349 error = usb2_transfer_setup(uaa->device, &iface_index, |
350 sc->sc_xfer, umoscom_config_data, 351 UMOSCOM_N_TRANSFER, sc, &Giant); |
352 353 if (error) { 354 goto detach; 355 } 356 /* clear stall at first run */ 357 sc->sc_flags |= (UMOSCOM_FLAG_READ_STALL | 358 UMOSCOM_FLAG_WRITE_STALL); 359 --- 16 unchanged lines hidden (view full) --- 376 struct umoscom_softc *sc = device_get_softc(dev); 377 378 mtx_lock(&Giant); 379 380 mtx_unlock(&Giant); 381 382 usb2_com_detach(&sc->sc_super_ucom, &sc->sc_ucom, 1); 383 |
384 usb2_transfer_unsetup(sc->sc_xfer, UMOSCOM_N_TRANSFER); |
385 386 return (0); 387} 388 389static void 390umoscom_cfg_open(struct usb2_com_softc *ucom) 391{ 392 struct umoscom_softc *sc = ucom->sc_parent; --- 217 unchanged lines hidden (view full) --- 610 611static void 612umoscom_start_read(struct usb2_com_softc *ucom) 613{ 614 struct umoscom_softc *sc = ucom->sc_parent; 615 616#if 0 617 /* start interrupt endpoint */ |
618 usb2_transfer_start(sc->sc_xfer[UMOSCOM_INTR_DT_RD]); |
619#endif 620 /* start read endpoint */ |
621 usb2_transfer_start(sc->sc_xfer[UMOSCOM_BULK_DT_RD]); |
622} 623 624static void 625umoscom_stop_read(struct usb2_com_softc *ucom) 626{ 627 struct umoscom_softc *sc = ucom->sc_parent; 628 629 /* stop interrupt transfer */ |
630 usb2_transfer_stop(sc->sc_xfer[UMOSCOM_INTR_CS_RD]); 631 usb2_transfer_stop(sc->sc_xfer[UMOSCOM_INTR_DT_RD]); |
632 633 /* stop read endpoint */ |
634 usb2_transfer_stop(sc->sc_xfer[UMOSCOM_BULK_CS_RD]); 635 usb2_transfer_stop(sc->sc_xfer[UMOSCOM_BULK_DT_RD]); |
636} 637 638static void 639umoscom_start_write(struct usb2_com_softc *ucom) 640{ 641 struct umoscom_softc *sc = ucom->sc_parent; 642 |
643 usb2_transfer_start(sc->sc_xfer[UMOSCOM_BULK_DT_WR]); |
644} 645 646static void 647umoscom_stop_write(struct usb2_com_softc *ucom) 648{ 649 struct umoscom_softc *sc = ucom->sc_parent; 650 |
651 usb2_transfer_stop(sc->sc_xfer[UMOSCOM_BULK_CS_WR]); 652 usb2_transfer_stop(sc->sc_xfer[UMOSCOM_BULK_DT_WR]); |
653} 654 655static void 656umoscom_write_callback(struct usb2_xfer *xfer) 657{ 658 struct umoscom_softc *sc = xfer->priv_sc; 659 uint32_t actlen; 660 661 switch (USB_GET_STATE(xfer)) { 662 case USB_ST_SETUP: 663 case USB_ST_TRANSFERRED: 664 DPRINTF("\n"); 665 666 if (sc->sc_flags & UMOSCOM_FLAG_WRITE_STALL) { |
667 usb2_transfer_start(sc->sc_xfer[UMOSCOM_BULK_CS_WR]); |
668 return; 669 } 670 if (usb2_com_get_data(&sc->sc_ucom, xfer->frbuffers, 0, 671 UMOSCOM_BUFSIZE, &actlen)) { 672 673 xfer->frlengths[0] = actlen; 674 usb2_start_hardware(xfer); 675 } 676 return; 677 678 default: /* Error */ 679 if (xfer->error != USB_ERR_CANCELLED) { 680 DPRINTFN(0, "transfer failed\n"); 681 sc->sc_flags |= UMOSCOM_FLAG_WRITE_STALL; |
682 usb2_transfer_start(sc->sc_xfer[UMOSCOM_BULK_CS_WR]); |
683 } 684 return; 685 } 686} 687 688static void 689umoscom_write_clear_stall_callback(struct usb2_xfer *xfer) 690{ 691 struct umoscom_softc *sc = xfer->priv_sc; |
692 struct usb2_xfer *xfer_other = sc->sc_xfer[UMOSCOM_BULK_DT_WR]; |
693 694 if (usb2_clear_stall_callback(xfer, xfer_other)) { 695 DPRINTF("stall cleared\n"); 696 sc->sc_flags &= ~UMOSCOM_FLAG_WRITE_STALL; 697 usb2_transfer_start(xfer_other); 698 } 699} 700 --- 6 unchanged lines hidden (view full) --- 707 case USB_ST_TRANSFERRED: 708 DPRINTF("got %d bytes\n", xfer->actlen); 709 usb2_com_put_data(&sc->sc_ucom, xfer->frbuffers, 0, xfer->actlen); 710 711 case USB_ST_SETUP: 712 DPRINTF("\n"); 713 714 if (sc->sc_flags & UMOSCOM_FLAG_READ_STALL) { |
715 usb2_transfer_start(sc->sc_xfer[UMOSCOM_BULK_CS_RD]); |
716 } else { 717 xfer->frlengths[0] = xfer->max_data_length; 718 usb2_start_hardware(xfer); 719 } 720 return; 721 722 default: /* Error */ 723 if (xfer->error != USB_ERR_CANCELLED) { 724 DPRINTFN(0, "transfer failed\n"); 725 sc->sc_flags |= UMOSCOM_FLAG_READ_STALL; |
726 usb2_transfer_start(sc->sc_xfer[UMOSCOM_BULK_CS_RD]); |
727 } 728 return; 729 730 } 731} 732 733static void 734umoscom_read_clear_stall_callback(struct usb2_xfer *xfer) 735{ 736 struct umoscom_softc *sc = xfer->priv_sc; |
737 struct usb2_xfer *xfer_other = sc->sc_xfer[UMOSCOM_BULK_DT_RD]; |
738 739 if (usb2_clear_stall_callback(xfer, xfer_other)) { 740 DPRINTF("stall cleared\n"); 741 sc->sc_flags &= ~UMOSCOM_FLAG_READ_STALL; 742 usb2_transfer_start(xfer_other); 743 } 744} 745 --- 8 unchanged lines hidden (view full) --- 754 DPRINTF("too short message\n"); 755 goto tr_setup; 756 } 757 usb2_com_status_change(&sc->sc_ucom); 758 759 case USB_ST_SETUP: 760tr_setup: 761 if (sc->sc_flags & UMOSCOM_FLAG_INTR_STALL) { |
762 usb2_transfer_start(sc->sc_xfer[UMOSCOM_INTR_CS_RD]); |
763 } else { 764 xfer->frlengths[0] = xfer->max_data_length; 765 usb2_start_hardware(xfer); 766 } 767 return; 768 769 default: /* Error */ 770 if (xfer->error != USB_ERR_CANCELLED) { 771 DPRINTFN(0, "transfer failed\n"); 772 sc->sc_flags |= UMOSCOM_FLAG_INTR_STALL; |
773 usb2_transfer_start(sc->sc_xfer[UMOSCOM_INTR_CS_RD]); |
774 } 775 return; 776 } 777} 778 779static void 780umoscom_intr_clear_stall_callback(struct usb2_xfer *xfer) 781{ 782 struct umoscom_softc *sc = xfer->priv_sc; |
783 struct usb2_xfer *xfer_other = sc->sc_xfer[UMOSCOM_INTR_DT_RD]; |
784 785 if (usb2_clear_stall_callback(xfer, xfer_other)) { 786 DPRINTF("stall cleared\n"); 787 sc->sc_flags &= ~UMOSCOM_FLAG_INTR_STALL; 788 usb2_transfer_start(xfer_other); 789 } 790} |