LCOV - code coverage report
Current view: top level - dev/usb - ucycom.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 176 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 11 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ucycom.c,v 1.37 2017/12/30 20:46:59 guenther Exp $    */
       2             : /*      $NetBSD: ucycom.c,v 1.3 2005/08/05 07:27:47 skrll Exp $ */
       3             : 
       4             : /*
       5             :  * Copyright (c) 2005 The NetBSD Foundation, Inc.
       6             :  * All rights reserved.
       7             :  *
       8             :  * This code is derived from software contributed to The NetBSD Foundation
       9             :  * by Nick Hudson
      10             :  *
      11             :  * Redistribution and use in source and binary forms, with or without
      12             :  * modification, are permitted provided that the following conditions
      13             :  * are met:
      14             :  * 1. Redistributions of source code must retain the above copyright
      15             :  *    notice, this list of conditions and the following disclaimer.
      16             :  * 2. Redistributions in binary form must reproduce the above copyright
      17             :  *    notice, this list of conditions and the following disclaimer in the
      18             :  *    documentation and/or other materials provided with the distribution.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
      21             :  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      22             :  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      23             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
      24             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      25             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      26             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      27             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      28             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      29             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      30             :  * POSSIBILITY OF SUCH DAMAGE.
      31             :  */
      32             : /*
      33             :  * This code is based on the ucom driver.
      34             :  */
      35             : 
      36             : /*
      37             :  * Device driver for Cypress CY7C637xx and CY7C640/1xx series USB to
      38             :  * RS232 bridges.
      39             :  */
      40             : 
      41             : #include <sys/param.h>
      42             : #include <sys/systm.h>
      43             : #include <sys/conf.h>
      44             : #include <sys/kernel.h>
      45             : #include <sys/malloc.h>
      46             : #include <sys/device.h>
      47             : #include <sys/tty.h>
      48             : 
      49             : #include <dev/usb/usb.h>
      50             : #include <dev/usb/usbhid.h>
      51             : 
      52             : #include <dev/usb/usbdi.h>
      53             : #include <dev/usb/usbdi_util.h>
      54             : #include <dev/usb/usbdevs.h>
      55             : #include <dev/usb/uhidev.h>
      56             : 
      57             : #include <dev/usb/ucomvar.h>
      58             : 
      59             : #ifdef UCYCOM_DEBUG
      60             : #define DPRINTF(x)      if (ucycomdebug) printf x
      61             : #define DPRINTFN(n, x)  if (ucycomdebug > (n)) printf x
      62             : int     ucycomdebug = 200;
      63             : #else
      64             : #define DPRINTF(x)
      65             : #define DPRINTFN(n,x)
      66             : #endif
      67             : 
      68             : /* Configuration Byte */
      69             : #define UCYCOM_RESET            0x80
      70             : #define UCYCOM_PARITY_TYPE_MASK 0x20
      71             : #define  UCYCOM_PARITY_ODD       0x20
      72             : #define  UCYCOM_PARITY_EVEN      0x00
      73             : #define UCYCOM_PARITY_MASK      0x10
      74             : #define  UCYCOM_PARITY_ON        0x10
      75             : #define  UCYCOM_PARITY_OFF       0x00
      76             : #define UCYCOM_STOP_MASK        0x08
      77             : #define  UCYCOM_STOP_BITS_2      0x08
      78             : #define  UCYCOM_STOP_BITS_1      0x00
      79             : #define UCYCOM_DATA_MASK        0x03
      80             : #define  UCYCOM_DATA_BITS_8      0x03
      81             : #define  UCYCOM_DATA_BITS_7      0x02
      82             : #define  UCYCOM_DATA_BITS_6      0x01
      83             : #define  UCYCOM_DATA_BITS_5      0x00
      84             : 
      85             : /* Modem (Input) status byte */
      86             : #define UCYCOM_RI       0x80
      87             : #define UCYCOM_DCD      0x40
      88             : #define UCYCOM_DSR      0x20
      89             : #define UCYCOM_CTS      0x10
      90             : #define UCYCOM_ERROR    0x08
      91             : #define UCYCOM_LMASK    0x07
      92             : 
      93             : /* Modem (Output) control byte */
      94             : #define UCYCOM_DTR      0x20
      95             : #define UCYCOM_RTS      0x10
      96             : #define UCYCOM_ORESET   0x08
      97             : 
      98             : struct ucycom_softc {
      99             :         struct uhidev            sc_hdev;
     100             :         struct usbd_device      *sc_udev;
     101             : 
     102             :         /* uhidev parameters */
     103             :         size_t                   sc_flen;       /* feature report length */
     104             :         size_t                   sc_ilen;       /* input report length */
     105             :         size_t                   sc_olen;       /* output report length */
     106             : 
     107             :         uint8_t                 *sc_obuf;
     108             : 
     109             :         uint8_t                 *sc_ibuf;
     110             :         uint32_t                 sc_icnt;
     111             : 
     112             :         /* settings */
     113             :         uint32_t                 sc_baud;
     114             :         uint8_t                  sc_cfg;        /* Data format */
     115             :         uint8_t                  sc_mcr;        /* Modem control */
     116             :         uint8_t                  sc_msr;        /* Modem status */
     117             :         uint8_t                  sc_newmsr;     /* from HID intr */
     118             :         int                      sc_swflags;
     119             : 
     120             :         struct device           *sc_subdev;
     121             : };
     122             : 
     123             : /* Callback routines */
     124             : void    ucycom_set(void *, int, int, int);
     125             : int     ucycom_param(void *, int, struct termios *);
     126             : void    ucycom_get_status(void *, int, u_char *, u_char *);
     127             : int     ucycom_open(void *, int);
     128             : void    ucycom_close(void *, int);
     129             : void    ucycom_write(void *, int, u_char *, u_char *, u_int32_t *);
     130             : void    ucycom_read(void *, int, u_char **, u_int32_t *);
     131             : 
     132             : struct ucom_methods ucycom_methods = {
     133             :         NULL, /* ucycom_get_status, */
     134             :         ucycom_set,
     135             :         ucycom_param,
     136             :         NULL,
     137             :         ucycom_open,
     138             :         ucycom_close,
     139             :         ucycom_read,
     140             :         ucycom_write,
     141             : };
     142             : 
     143             : void ucycom_intr(struct uhidev *, void *, u_int);
     144             : 
     145             : const struct usb_devno ucycom_devs[] = {
     146             :         { USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_USBRS232 },
     147             :         { USB_VENDOR_DELORME, USB_PRODUCT_DELORME_EMUSB },
     148             :         { USB_VENDOR_DELORME, USB_PRODUCT_DELORME_EMLT20 },
     149             : };
     150             : 
     151             : int ucycom_match(struct device *, void *, void *);
     152             : void ucycom_attach(struct device *, struct device *, void *);
     153             : int ucycom_detach(struct device *, int);
     154             : 
     155             : struct cfdriver ucycom_cd = {
     156             :         NULL, "ucycom", DV_DULL
     157             : };
     158             : 
     159             : const struct cfattach ucycom_ca = {
     160             :         sizeof(struct ucycom_softc), ucycom_match, ucycom_attach, ucycom_detach
     161             : };
     162             : 
     163             : int
     164           0 : ucycom_match(struct device *parent, void *match, void *aux)
     165             : {
     166           0 :         struct uhidev_attach_arg *uha = aux;
     167             : 
     168           0 :         if (uha->reportid == UHIDEV_CLAIM_ALLREPORTID)
     169           0 :                 return (UMATCH_NONE);
     170             : 
     171           0 :         return (usb_lookup(ucycom_devs, uha->uaa->vendor, uha->uaa->product) != NULL ?
     172             :             UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
     173           0 : }
     174             : 
     175             : void
     176           0 : ucycom_attach(struct device *parent, struct device *self, void *aux)
     177             : {
     178           0 :         struct ucycom_softc *sc = (struct ucycom_softc *)self;
     179           0 :         struct usb_attach_arg *uaa = aux;
     180           0 :         struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
     181           0 :         struct usbd_device *dev = uha->parent->sc_udev;
     182           0 :         struct ucom_attach_args uca;
     183           0 :         int size, repid, err;
     184           0 :         void *desc;
     185             : 
     186           0 :         sc->sc_hdev.sc_intr = ucycom_intr;
     187           0 :         sc->sc_hdev.sc_parent = uha->parent;
     188           0 :         sc->sc_hdev.sc_report_id = uha->reportid;
     189             : 
     190           0 :         uhidev_get_report_desc(uha->parent, &desc, &size);
     191           0 :         repid = uha->reportid;
     192           0 :         sc->sc_ilen = hid_report_size(desc, size, hid_input, repid);
     193           0 :         sc->sc_olen = hid_report_size(desc, size, hid_output, repid);
     194           0 :         sc->sc_flen = hid_report_size(desc, size, hid_feature, repid);
     195             : 
     196             :         DPRINTF(("ucycom_open: olen %d ilen %d flen %d\n", sc->sc_ilen,
     197             :             sc->sc_olen, sc->sc_flen));
     198             : 
     199           0 :         printf("\n");
     200             : 
     201           0 :         sc->sc_udev = dev;
     202             : 
     203           0 :         err = uhidev_open(&sc->sc_hdev);
     204           0 :         if (err) {
     205             :                 DPRINTF(("ucycom_open: uhidev_open %d\n", err));
     206           0 :                 return;
     207             :         }
     208             : 
     209             :         DPRINTF(("ucycom attach: sc %p opipe %p ipipe %p report_id %d\n",
     210             :             sc, sc->sc_hdev.sc_parent->sc_opipe, sc->sc_hdev.sc_parent->sc_ipipe,
     211             :             uha->reportid));
     212             : 
     213             :         /* bulkin, bulkout set above */
     214           0 :         bzero(&uca, sizeof uca);
     215           0 :         uca.bulkin = uca.bulkout = -1;
     216           0 :         uca.ibufsize = sc->sc_ilen - 1;
     217           0 :         uca.obufsize = sc->sc_olen - 1;
     218           0 :         uca.ibufsizepad = 1;
     219           0 :         uca.opkthdrlen = 0;
     220           0 :         uca.uhidev = sc->sc_hdev.sc_parent;
     221           0 :         uca.device = uaa->device;
     222           0 :         uca.iface = uaa->iface;
     223           0 :         uca.methods = &ucycom_methods;
     224           0 :         uca.arg = sc;
     225           0 :         uca.info = NULL;
     226             : 
     227           0 :         sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
     228             :         DPRINTF(("ucycom_attach: complete %p\n", sc->sc_subdev));
     229           0 : }
     230             : 
     231             : void
     232           0 : ucycom_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
     233             : {
     234           0 :         struct ucycom_softc *sc = addr;
     235             : 
     236             :         DPRINTF(("ucycom_get_status:\n"));
     237             : 
     238             : #if 0
     239             :         if (lsr != NULL)
     240             :                 *lsr = sc->sc_lsr;
     241             : #endif
     242           0 :         if (msr != NULL)
     243           0 :                 *msr = sc->sc_msr;
     244           0 : }
     245             : 
     246             : int
     247           0 : ucycom_open(void *addr, int portno)
     248             : {
     249           0 :         struct ucycom_softc *sc = addr;
     250           0 :         struct termios t;
     251             :         int err;
     252             : 
     253             :         DPRINTF(("ucycom_open: complete\n"));
     254             : 
     255           0 :         if (usbd_is_dying(sc->sc_udev))
     256           0 :                 return (EIO);
     257             : 
     258             :         /* Allocate an output report buffer */
     259           0 :         sc->sc_obuf = malloc(sc->sc_olen, M_USBDEV, M_WAITOK | M_ZERO);
     260             : 
     261             :         /* Allocate an input report buffer */
     262           0 :         sc->sc_ibuf = malloc(sc->sc_ilen, M_USBDEV, M_WAITOK);
     263             : 
     264             :         DPRINTF(("ucycom_open: sc->sc_ibuf=%p sc->sc_obuf=%p \n",
     265             :             sc->sc_ibuf, sc->sc_obuf));
     266             : 
     267           0 :         t.c_ospeed = 9600;
     268           0 :         t.c_cflag = CSTOPB | CS8;
     269           0 :         (void)ucycom_param(sc, portno, &t);
     270             : 
     271           0 :         sc->sc_mcr = UCYCOM_DTR | UCYCOM_RTS;
     272           0 :         sc->sc_obuf[0] = sc->sc_mcr;
     273           0 :         err = uhidev_write(sc->sc_hdev.sc_parent, sc->sc_obuf, sc->sc_olen);
     274           0 :         if (err) {
     275             :                 DPRINTF(("ucycom_open: set RTS err=%d\n", err));
     276           0 :                 return (EIO);
     277             :         }
     278             : 
     279           0 :         return (0);
     280           0 : }
     281             : 
     282             : void
     283           0 : ucycom_close(void *addr, int portno)
     284             : {
     285           0 :         struct ucycom_softc *sc = addr;
     286             :         int s;
     287             : 
     288           0 :         if (usbd_is_dying(sc->sc_udev))
     289           0 :                 return;
     290             : 
     291           0 :         s = splusb();
     292           0 :         if (sc->sc_obuf != NULL) {
     293           0 :                 free(sc->sc_obuf, M_USBDEV, sc->sc_olen);
     294           0 :                 sc->sc_obuf = NULL;
     295           0 :         }
     296           0 :         if (sc->sc_ibuf != NULL) {
     297           0 :                 free(sc->sc_ibuf, M_USBDEV, sc->sc_ilen);
     298           0 :                 sc->sc_ibuf = NULL;
     299           0 :         }
     300           0 :         splx(s);
     301           0 : }
     302             : 
     303             : void
     304           0 : ucycom_read(void *addr, int portno, u_char **ptr, u_int32_t *count)
     305             : {
     306           0 :         struct ucycom_softc *sc = addr;
     307             : 
     308           0 :         if (sc->sc_newmsr ^ sc->sc_msr) {
     309             :                 DPRINTF(("ucycom_read: msr %d new %d\n",
     310             :                     sc->sc_msr, sc->sc_newmsr));
     311           0 :                 sc->sc_msr = sc->sc_newmsr;
     312           0 :                 ucom_status_change((struct ucom_softc *)sc->sc_subdev);
     313           0 :         }
     314             : 
     315             :         DPRINTF(("ucycom_read: buf %p chars %d\n", sc->sc_ibuf, sc->sc_icnt));
     316           0 :         *ptr = sc->sc_ibuf;
     317           0 :         *count = sc->sc_icnt;
     318           0 : }
     319             : 
     320             : void
     321           0 : ucycom_write(void *addr, int portno, u_char *to, u_char *data, u_int32_t *cnt)
     322             : {
     323           0 :         struct ucycom_softc *sc = addr;
     324             :         u_int32_t len;
     325             : #ifdef UCYCOM_DEBUG
     326             :         u_int32_t want = *cnt;
     327             : #endif
     328             : 
     329             :         /*
     330             :          * The 8 byte output report uses byte 0 for control and byte
     331             :          * count.
     332             :          *
     333             :          * The 32 byte output report uses byte 0 for control. Byte 1
     334             :          * is used for byte count.
     335             :          */
     336           0 :         len = sc->sc_olen;
     337           0 :         memset(to, 0, len);
     338           0 :         switch (sc->sc_olen) {
     339             :         case 8:
     340           0 :                 to[0] = *cnt | sc->sc_mcr;
     341           0 :                 memcpy(&to[1], data, *cnt);
     342             :                 DPRINTF(("ucycomstart(8): to[0] = %d | %d = %d\n",
     343             :                     *cnt, sc->sc_mcr, to[0]));
     344           0 :                 break;
     345             : 
     346             :         case 32:
     347           0 :                 to[0] = sc->sc_mcr;
     348           0 :                 to[1] = *cnt;
     349           0 :                 memcpy(&to[2], data, *cnt);
     350             :                 DPRINTF(("ucycomstart(32): to[0] = %d\nto[1] = %d\n",
     351             :                     to[0], to[1]));
     352           0 :                 break;
     353             :         }
     354             : 
     355             : #ifdef UCYCOM_DEBUG
     356             :         if (ucycomdebug > 5) {
     357             :                 int i;
     358             : 
     359             :                 if (len != 0) {
     360             :                         DPRINTF(("ucycomstart: to[0..%d) =", len-1));
     361             :                         for (i = 0; i < len; i++)
     362             :                                 DPRINTF((" %02x", to[i]));
     363             :                         DPRINTF(("\n"));
     364             :                 }
     365             :         }
     366             : #endif
     367           0 :         *cnt = len;
     368             : 
     369             :         DPRINTFN(4,("ucycomstart: req %d chars did %d chars\n", want, len));
     370           0 : }
     371             : 
     372             : int
     373           0 : ucycom_param(void *addr, int portno, struct termios *t)
     374             : {
     375           0 :         struct ucycom_softc *sc = addr;
     376           0 :         uint8_t report[5];
     377             :         uint32_t baud = 0;
     378             :         uint8_t cfg;
     379             : 
     380           0 :         if (usbd_is_dying(sc->sc_udev))
     381           0 :                 return (EIO);
     382             : 
     383           0 :         switch (t->c_ospeed) {
     384             :         case 600:
     385             :         case 1200:
     386             :         case 2400:
     387             :         case 4800:
     388             :         case 9600:
     389             :         case 19200:
     390             :         case 38400:
     391             :         case 57600:
     392             : #if 0
     393             :         /*
     394             :          * Stock chips only support standard baud rates in the 600 - 57600
     395             :          * range, but higher rates can be achieved using custom firmware.
     396             :          */
     397             :         case 115200:
     398             :         case 153600:
     399             :         case 192000:
     400             : #endif
     401           0 :                 baud = t->c_ospeed;
     402             :                 break;
     403             :         default:
     404           0 :                 return (EINVAL);
     405             :         }
     406             : 
     407           0 :         if (t->c_cflag & CIGNORE) {
     408           0 :                 cfg = sc->sc_cfg;
     409           0 :         } else {
     410             :                 cfg = 0;
     411           0 :                 switch (t->c_cflag & CSIZE) {
     412             :                 case CS8:
     413             :                         cfg |= UCYCOM_DATA_BITS_8;
     414           0 :                         break;
     415             :                 case CS7:
     416             :                         cfg |= UCYCOM_DATA_BITS_7;
     417           0 :                         break;
     418             :                 case CS6:
     419             :                         cfg |= UCYCOM_DATA_BITS_6;
     420           0 :                         break;
     421             :                 case CS5:
     422             :                         cfg |= UCYCOM_DATA_BITS_5;
     423           0 :                         break;
     424             :                 default:
     425             :                         return (EINVAL);
     426             :                 }
     427           0 :                 cfg |= ISSET(t->c_cflag, CSTOPB) ?
     428             :                     UCYCOM_STOP_BITS_2 : UCYCOM_STOP_BITS_1;
     429           0 :                 cfg |= ISSET(t->c_cflag, PARENB) ?
     430             :                     UCYCOM_PARITY_ON : UCYCOM_PARITY_OFF;
     431           0 :                 cfg |= ISSET(t->c_cflag, PARODD) ?
     432             :                     UCYCOM_PARITY_ODD : UCYCOM_PARITY_EVEN;
     433             :         }
     434             : 
     435             :         DPRINTF(("ucycom_param: setting %d baud, %d-%c-%d (%d)\n", baud,
     436             :             5 + (cfg & UCYCOM_DATA_MASK),
     437             :             (cfg & UCYCOM_PARITY_MASK) ?
     438             :                 ((cfg & UCYCOM_PARITY_TYPE_MASK) ? 'O' : 'E') : 'N',
     439             :             (cfg & UCYCOM_STOP_MASK) ? 2 : 1, cfg));
     440             : 
     441           0 :         report[0] = baud & 0xff;
     442           0 :         report[1] = (baud >> 8) & 0xff;
     443           0 :         report[2] = (baud >> 16) & 0xff;
     444           0 :         report[3] = (baud >> 24) & 0xff;
     445           0 :         report[4] = cfg;
     446           0 :         if (uhidev_set_report(sc->sc_hdev.sc_parent, UHID_FEATURE_REPORT,
     447           0 :             sc->sc_hdev.sc_report_id, report, sc->sc_flen) != sc->sc_flen)
     448           0 :                 return EIO;
     449           0 :         sc->sc_baud = baud;
     450           0 :         return (0);
     451           0 : }
     452             : 
     453             : void
     454           0 : ucycom_intr(struct uhidev *addr, void *ibuf, u_int len)
     455             : {
     456             :         extern void ucomreadcb(struct usbd_xfer *, void *, usbd_status);
     457           0 :         struct ucycom_softc *sc = (struct ucycom_softc *)addr;
     458             :         uint8_t *cp = ibuf;
     459             :         int n, st, s;
     460             : 
     461             :         /* not accepting data anymore.. */
     462           0 :         if (sc->sc_ibuf == NULL)
     463           0 :                 return;
     464             : 
     465             :         /* We understand 8 byte and 32 byte input records */
     466           0 :         switch (len) {
     467             :         case 8:
     468           0 :                 n = cp[0] & UCYCOM_LMASK;
     469           0 :                 st = cp[0] & ~UCYCOM_LMASK;
     470           0 :                 cp++;
     471           0 :                 break;
     472             : 
     473             :         case 32:
     474           0 :                 st = cp[0];
     475           0 :                 n = cp[1];
     476           0 :                 cp += 2;
     477           0 :                 break;
     478             : 
     479             :         default:
     480             :                 DPRINTFN(3,("ucycom_intr: Unknown input report length\n"));
     481           0 :                 return;
     482             :         }
     483             : 
     484             : #ifdef UCYCOM_DEBUG
     485             :         if (ucycomdebug > 5) {
     486             :                 u_int32_t i;
     487             : 
     488             :                 if (n != 0) {
     489             :                         DPRINTF(("ucycom_intr: ibuf[0..%d) =", n));
     490             :                         for (i = 0; i < n; i++)
     491             :                                 DPRINTF((" %02x", cp[i]));
     492             :                         DPRINTF(("\n"));
     493             :                 }
     494             :         }
     495             : #endif
     496             : 
     497           0 :         if (n > 0 || st != sc->sc_msr) {
     498           0 :                 s = spltty();
     499           0 :                 sc->sc_newmsr = st;
     500           0 :                 bcopy(cp, sc->sc_ibuf, n);
     501           0 :                 sc->sc_icnt = n;
     502           0 :                 ucomreadcb(addr->sc_parent->sc_ixfer, sc->sc_subdev,
     503             :                     USBD_NORMAL_COMPLETION);
     504           0 :                 splx(s);
     505           0 :         }
     506           0 : }
     507             : 
     508             : void
     509           0 : ucycom_set(void *addr, int portno, int reg, int onoff)
     510             : {
     511           0 :         struct ucycom_softc *sc = addr;
     512             :         int err;
     513             : 
     514           0 :         switch (reg) {
     515             :         case UCOM_SET_DTR:
     516           0 :                 if (onoff)
     517           0 :                         SET(sc->sc_mcr, UCYCOM_DTR);
     518             :                 else
     519           0 :                         CLR(sc->sc_mcr, UCYCOM_DTR);
     520             :                 break;
     521             :         case UCOM_SET_RTS:
     522           0 :                 if (onoff)
     523           0 :                         SET(sc->sc_mcr, UCYCOM_RTS);
     524             :                 else
     525           0 :                         CLR(sc->sc_mcr, UCYCOM_RTS);
     526             :                 break;
     527             :         case UCOM_SET_BREAK:
     528             :                 break;
     529             :         }
     530             : 
     531           0 :         memset(sc->sc_obuf, 0, sc->sc_olen);
     532           0 :         sc->sc_obuf[0] = sc->sc_mcr;
     533             : 
     534           0 :         err = uhidev_write(sc->sc_hdev.sc_parent, sc->sc_obuf, sc->sc_olen);
     535             :         if (err)
     536             :                 DPRINTF(("ucycom_set_status: err=%d\n", err));
     537           0 : }
     538             : 
     539             : int
     540           0 : ucycom_detach(struct device *self, int flags)
     541             : {
     542           0 :         struct ucycom_softc *sc = (struct ucycom_softc *)self;
     543             : 
     544             :         DPRINTF(("ucycom_detach: sc=%p flags=%d\n", sc, flags));
     545           0 :         if (sc->sc_subdev != NULL) {
     546           0 :                 config_detach(sc->sc_subdev, flags);
     547           0 :                 sc->sc_subdev = NULL;
     548           0 :         }
     549             : 
     550           0 :         if (sc->sc_hdev.sc_state & UHIDEV_OPEN)
     551           0 :                 uhidev_close(&sc->sc_hdev);
     552             : 
     553           0 :         return (0);
     554             : }

Generated by: LCOV version 1.13