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 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_INTR_DT_RD, |
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 */ |
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; |
226static usb2_callback_t uchcom_write_callback; |
227static usb2_callback_t uchcom_read_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 |
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 }, |
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 */ |
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 |
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 |
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 |
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 */ |
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 |
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: |
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) { |
800 /* try to clear stall first */ 801 xfer->flags.stall_pipe = 1; 802 goto tr_setup; |
803 } 804 break; 805 } 806} 807 808static 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: |
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) { |
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 |
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: |
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) { |
856 /* try to clear stall first */ 857 xfer->flags.stall_pipe = 1; 858 goto tr_setup; |
859 } 860 return; |
861 } 862} 863 |
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 --- |