The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/ufoma.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: umodem.c,v 1.45 2002/09/23 05:51:23 simonb Exp $       */
    2 
    3 
    4 #include <sys/cdefs.h>
    5 __FBSDID("$FreeBSD: releng/7.3/sys/dev/usb/ufoma.c 171614 2007-07-27 12:00:29Z takawata $");
    6 /*-
    7  * Copyright (c) 2005, Takanori Watanabe
    8  * Copyright (c) 2003, M. Warner Losh <imp@freebsd.org>.
    9  * All rights reserved.
   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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 
   33 /*-
   34  * Copyright (c) 1998 The NetBSD Foundation, Inc.
   35  * All rights reserved.
   36  *
   37  * This code is derived from software contributed to The NetBSD Foundation
   38  * by Lennart Augustsson (lennart@augustsson.net) at
   39  * Carlstedt Research & Technology.
   40  *
   41  * Redistribution and use in source and binary forms, with or without
   42  * modification, are permitted provided that the following conditions
   43  * are met:
   44  * 1. Redistributions of source code must retain the above copyright
   45  *    notice, this list of conditions and the following disclaimer.
   46  * 2. Redistributions in binary form must reproduce the above copyright
   47  *    notice, this list of conditions and the following disclaimer in the
   48  *    documentation and/or other materials provided with the distribution.
   49  * 3. All advertising materials mentioning features or use of this software
   50  *    must display the following acknowledgement:
   51  *        This product includes software developed by the NetBSD
   52  *        Foundation, Inc. and its contributors.
   53  * 4. Neither the name of The NetBSD Foundation nor the names of its
   54  *    contributors may be used to endorse or promote products derived
   55  *    from this software without specific prior written permission.
   56  *
   57  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   58  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   59  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   60  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   61  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   62  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   63  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   64  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   65  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   66  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   67  * POSSIBILITY OF SUCH DAMAGE.
   68  */
   69 
   70 /*
   71  * Comm Class spec:  http://www.usb.org/developers/devclass_docs/usbccs10.pdf
   72  *                   http://www.usb.org/developers/devclass_docs/usbcdc11.pdf
   73  */
   74 
   75 /*
   76  * TODO:
   77  * - Add error recovery in various places; the big problem is what
   78  *   to do in a callback if there is an error.
   79  * - Implement a Call Device for modems without multiplexed commands.
   80  *
   81  */
   82 
   83 #include <sys/param.h>
   84 #include <sys/systm.h>
   85 #include <sys/kernel.h>
   86 #include <sys/module.h>
   87 #include <sys/ioccom.h>
   88 #include <sys/conf.h>
   89 #include <sys/serial.h>
   90 #include <sys/tty.h>
   91 #include <sys/clist.h>
   92 #include <sys/file.h>
   93 #include <sys/select.h>
   94 #include <sys/sysctl.h>
   95 #include <sys/proc.h>
   96 #include <sys/bus.h>
   97 #include <sys/sbuf.h>
   98 #include <sys/poll.h>
   99 #include <sys/uio.h>
  100 #include <sys/taskqueue.h>
  101 
  102 #include <dev/usb/usb.h>
  103 #include <dev/usb/usbcdc.h>
  104 
  105 #include <dev/usb/usbdi.h>
  106 #include <dev/usb/usbdi_util.h>
  107 #include <dev/usb/usb_quirks.h>
  108 
  109 #include <dev/usb/ucomvar.h>
  110 
  111 #include "usbdevs.h"
  112 
  113 typedef struct ufoma_mobile_acm_descriptor{
  114         uByte bFunctionLength;
  115         uByte bDescriptorType;
  116         uByte bDescriptorSubtype;
  117         uByte bType;
  118         uByte bMode[1];
  119 }usb_mcpc_acm_descriptor;
  120 
  121 #define UISUBCLASS_MCPC 0x88
  122 
  123 #define UDESC_VS_INTERFACE 0x44
  124 #define UDESCSUB_MCPC_ACM  0x11
  125 
  126 #define UMCPC_ACM_TYPE_AB1 0x1
  127 #define UMCPC_ACM_TYPE_AB2 0x2
  128 #define UMCPC_ACM_TYPE_AB5 0x5
  129 #define UMCPC_ACM_TYPE_AB6 0x6
  130 
  131 #define UMCPC_ACM_MODE_DEACTIVATED 0x0
  132 #define UMCPC_ACM_MODE_MODEM 0x1
  133 #define UMCPC_ACM_MODE_ATCOMMAND 0x2
  134 #define UMCPC_ACM_MODE_OBEX 0x60
  135 #define UMCPC_ACM_MODE_VENDOR1 0xc0
  136 #define UMCPC_ACM_MODE_VENDOR2 0xfe
  137 #define UMCPC_ACM_MODE_UNLINKED 0xff
  138 
  139 #define UMCPC_CM_MOBILE_ACM 0x0
  140 
  141 #define UMCPC_ACTIVATE_MODE 0x60
  142 #define UMCPC_GET_MODETABLE 0x61
  143 #define UMCPC_SET_LINK 0x62
  144 #define UMCPC_CLEAR_LINK 0x63
  145 
  146 #define UMCPC_REQUEST_ACKNOLEDGE 0x31
  147 
  148 #define UFOMA_MAX_TIMEOUT 15 /*Standard says 10(sec)*/
  149 #define UFOMA_CMD_BUF_SIZE 64
  150 
  151 #define UMODEMIBUFSIZE 64
  152 #define UMODEMOBUFSIZE 256
  153 #define DPRINTF(a)
  154 
  155 struct ufoma_softc{
  156         struct ucom_softc sc_ucom;
  157         int sc_is_ucom;
  158         int sc_isopen;
  159 
  160         struct mtx sc_mtx;
  161         int sc_ctl_iface_no;
  162         usbd_interface_handle sc_ctl_iface;
  163         usbd_interface_handle   sc_data_iface;
  164         int sc_data_iface_no;
  165         int sc_cm_cap;
  166         int sc_acm_cap;
  167         usb_cdc_line_state_t    sc_line_state;  /* current line state */
  168         u_char                  sc_dtr;         /* current DTR state */
  169         u_char                  sc_rts;         /* current RTS state */
  170 
  171         usbd_pipe_handle sc_notify_pipe;
  172         usb_cdc_notification_t sc_notify_buf;
  173         u_char sc_lsr;
  174         u_char sc_msr;
  175         
  176         struct task sc_task;
  177         uByte *sc_modetable;
  178         uByte sc_modetoactivate;
  179         uByte sc_currentmode;
  180         char sc_resbuffer[UFOMA_CMD_BUF_SIZE+1];
  181         int sc_cmdbp;
  182         int sc_nummsg;
  183         usbd_xfer_handle sc_msgxf;
  184 };
  185 static usbd_status
  186 ufoma_set_line_coding(struct ufoma_softc *sc, usb_cdc_line_state_t *state);
  187 static device_probe_t ufoma_match;
  188 static device_attach_t ufoma_attach;
  189 static device_detach_t ufoma_detach;
  190 static void *ufoma_get_intconf(usb_config_descriptor_t *cd, usb_interface_descriptor_t *id,int type, int subtype);
  191 static void ufoma_notify(void * ,int count);
  192 static void ufoma_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
  193 static char *ufoma_mode_to_str(int);
  194 static int ufoma_str_to_mode(char *);
  195 
  196 /*Pseudo ucom stuff*/
  197 static int ufoma_init_pseudo_ucom(struct ufoma_softc *);
  198 static t_open_t ufomaopen;
  199 static t_close_t ufomaclose;
  200 static t_oproc_t ufomastart;
  201 
  202 /*umodem like stuff*/
  203 static int ufoma_init_modem(struct ufoma_softc *, struct usb_attach_arg *);
  204 static void ufoma_get_status(void *, int portno, u_char *lst, u_char *msr);
  205 static void ufoma_set(void *, int portno, int reg, int onoff);
  206 static int ufoma_param(void *, int portno, struct termios *);
  207 static int ufoma_ucom_open(void *, int portno);
  208 static void ufoma_ucom_close(void *, int portno);
  209 static void ufoma_break(struct ufoma_softc *sc, int onoff);
  210 static void ufoma_dtr(struct ufoma_softc *sc, int onoff);
  211 static void ufoma_rts(struct ufoma_softc *sc, int onoff);
  212 
  213 /*sysctl stuff*/
  214 static int ufoma_sysctl_support(SYSCTL_HANDLER_ARGS);
  215 static int ufoma_sysctl_current(SYSCTL_HANDLER_ARGS);
  216 static int ufoma_sysctl_open(SYSCTL_HANDLER_ARGS);
  217 
  218 
  219 static struct ucom_callback ufoma_callback = {
  220         ufoma_get_status,
  221         ufoma_set,
  222         ufoma_param,
  223         NULL,
  224         ufoma_ucom_open,
  225         ufoma_ucom_close,
  226         NULL,
  227         NULL,
  228 };
  229 
  230 
  231 static device_method_t ufoma_methods[] = { 
  232         /**/
  233         DEVMETHOD(device_probe, ufoma_match),
  234         DEVMETHOD(device_attach, ufoma_attach),
  235         DEVMETHOD(device_detach, ufoma_detach),
  236         {0, 0}
  237 };
  238 struct umcpc_modetostr_tab{
  239         int mode;
  240         char *str;
  241 }umcpc_modetostr_tab[]={
  242         {UMCPC_ACM_MODE_DEACTIVATED, "deactivated"},
  243         {UMCPC_ACM_MODE_MODEM, "modem"},
  244         {UMCPC_ACM_MODE_ATCOMMAND, "handsfree"},
  245         {UMCPC_ACM_MODE_OBEX, "obex"},
  246         {UMCPC_ACM_MODE_VENDOR1, "vendor1"},
  247         {UMCPC_ACM_MODE_VENDOR2, "vendor2"},
  248         {UMCPC_ACM_MODE_UNLINKED, "unlinked"},
  249         {0, NULL}
  250 };
  251 
  252 static driver_t ufoma_driver = {
  253         "ucom",
  254         ufoma_methods,
  255         sizeof(struct ufoma_softc)
  256 };
  257 
  258 
  259 DRIVER_MODULE(ufoma, uhub, ufoma_driver, ucom_devclass, usbd_driver_load, 0);
  260 MODULE_DEPEND(ufoma, usb, 1, 1, 1);
  261 MODULE_DEPEND(ufoma, ucom, UCOM_MINVER, UCOM_PREFVER, UCOM_MAXVER);
  262 
  263 static int
  264 ufoma_match(device_t self)
  265 {
  266         struct usb_attach_arg *uaa = device_get_ivars(self);
  267         usb_interface_descriptor_t *id;
  268         usb_config_descriptor_t *cd;
  269         usb_mcpc_acm_descriptor *mad;
  270         int ret;
  271 
  272         ret = UMATCH_NONE;
  273 
  274         if(uaa->iface == NULL)
  275                 return(UMATCH_NONE);
  276         id = usbd_get_interface_descriptor(uaa->iface);
  277         cd = usbd_get_config_descriptor(uaa->device);
  278 
  279         if(id == NULL || cd == NULL)
  280                 return (UMATCH_NONE);
  281         
  282         if( id->bInterfaceClass == UICLASS_CDC &&
  283             id->bInterfaceSubClass == UISUBCLASS_MCPC){
  284                 ret = (UMATCH_IFACECLASS_IFACESUBCLASS);
  285         }else{
  286                 return UMATCH_NONE;
  287         }
  288 
  289         mad = ufoma_get_intconf(cd, id , UDESC_VS_INTERFACE, UDESCSUB_MCPC_ACM);
  290         if(mad == NULL){
  291                 return (UMATCH_NONE);
  292         }
  293 
  294 #if 0
  295         if(mad->bType != UMCPC_ACM_TYPE_AB5){
  296                 return UMATCH_NONE;
  297         }
  298 #endif
  299         return ret;
  300 }
  301                         
  302 static int
  303 ufoma_attach(device_t self)
  304 {
  305         struct ufoma_softc *sc = device_get_softc(self);
  306         struct usb_attach_arg *uaa = device_get_ivars(self);
  307         usbd_device_handle dev = uaa->device;
  308         usb_config_descriptor_t *cd;
  309         usb_interface_descriptor_t *id;
  310         usb_endpoint_descriptor_t *ed;
  311         usb_mcpc_acm_descriptor *mad;
  312         struct ucom_softc *ucom = &sc->sc_ucom;
  313         const char *devname,*modename;
  314         int ctl_notify;
  315         int i,err;
  316         int elements;
  317         uByte *mode;
  318         struct sysctl_ctx_list *sctx;
  319         struct sysctl_oid *soid;
  320         
  321         ucom->sc_dev = self;
  322         ucom->sc_udev = dev;
  323         sc->sc_ctl_iface = uaa->iface;
  324         mtx_init(&sc->sc_mtx, "ufoma", NULL, MTX_DEF);  
  325 
  326         cd = usbd_get_config_descriptor(ucom->sc_udev);
  327         id = usbd_get_interface_descriptor(sc->sc_ctl_iface);
  328         sc->sc_ctl_iface_no = id->bInterfaceNumber;
  329         
  330         devname = device_get_nameunit(self);
  331         device_printf(self, "iclass %d/%d ifno:%d\n",
  332             id->bInterfaceClass, id->bInterfaceSubClass, sc->sc_ctl_iface_no);
  333 
  334         ctl_notify = -1;
  335         for (i = 0; i < id->bNumEndpoints; i++) {
  336                 ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i);
  337                 if (ed == NULL)
  338                         continue;
  339 
  340                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  341                     (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) {
  342                         ctl_notify = ed->bEndpointAddress;
  343                 }
  344         }
  345 
  346         if(ctl_notify== -1){
  347                 /*NOTIFY is mandatory.*/
  348                 printf("NOTIFY interface not found\n");
  349                 goto error;
  350         }
  351 
  352         err = usbd_open_pipe_intr(sc->sc_ctl_iface, ctl_notify, 
  353             USBD_SHORT_XFER_OK, &sc->sc_notify_pipe, sc, &sc->sc_notify_buf,
  354             sizeof(sc->sc_notify_buf), ufoma_intr, USBD_DEFAULT_INTERVAL);
  355         if(err){
  356                 printf("PIPE open error %d\n", err);
  357                 goto error;
  358         }
  359         mad = ufoma_get_intconf(cd, id , UDESC_VS_INTERFACE, UDESCSUB_MCPC_ACM);
  360         if(mad ==NULL){
  361                 goto error;
  362         }
  363 
  364         printf("%s:Supported Mode:", devname);
  365         for(mode = mad->bMode; 
  366             mode < ((uByte *)mad + mad->bFunctionLength); mode++){
  367                 modename = ufoma_mode_to_str(*mode);
  368                 if(modename){
  369                         printf("%s", ufoma_mode_to_str(*mode));
  370                 }else{
  371                         printf("(%x)", *mode);
  372                 }
  373                 if(mode != ((uByte*)mad + mad->bFunctionLength-1)){
  374                         printf(",");
  375                 }
  376         }
  377         printf("\n");
  378 
  379         if((mad->bType == UMCPC_ACM_TYPE_AB5)
  380            ||(mad->bType == UMCPC_ACM_TYPE_AB6)){
  381                 /*These does not have data interface*/
  382                 sc->sc_is_ucom = 0;
  383                 ufoma_init_pseudo_ucom(sc);
  384         }else{
  385                 if(ufoma_init_modem(sc, uaa)){
  386                         goto error;
  387                 }
  388         }
  389         elements = mad->bFunctionLength - sizeof(*mad)+1;
  390 
  391         sc->sc_msgxf = usbd_alloc_xfer(ucom->sc_udev);
  392         sc->sc_nummsg = 0;
  393 
  394         /*Initialize Mode vars.*/
  395         sc->sc_modetable = malloc(elements + 1, M_USBDEV, M_WAITOK);
  396         sc->sc_modetable[0] = elements + 1;
  397         bcopy(mad->bMode, &sc->sc_modetable[1], elements);
  398         sc->sc_currentmode = UMCPC_ACM_MODE_UNLINKED;
  399         sc->sc_modetoactivate = mad->bMode[0];
  400         /*Sysctls*/
  401         sctx = device_get_sysctl_ctx(self);
  402         soid = device_get_sysctl_tree(self);
  403 
  404         SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "supportmode",
  405                         CTLFLAG_RD|CTLTYPE_STRING, sc, 0, ufoma_sysctl_support,
  406                         "A", "Supporting port role");
  407 
  408         SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "currentmode",
  409                         CTLFLAG_RD|CTLTYPE_STRING, sc, 0, ufoma_sysctl_current,
  410                         "A", "Current port role");
  411 
  412         SYSCTL_ADD_PROC(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "openmode",
  413                         CTLFLAG_RW|CTLTYPE_STRING, sc, 0, ufoma_sysctl_open,
  414                         "A", "Mode to transit when port is opened");
  415         return 0;
  416  error:
  417         if(sc->sc_modetable)
  418                 free(sc->sc_modetable, M_USBDEV);
  419         return EIO;
  420 }
  421 
  422 static int
  423 ufoma_detach(device_t self)
  424 {
  425         struct ufoma_softc *sc = device_get_softc(self);
  426         int rv = 0;
  427 
  428         usbd_free_xfer(sc->sc_msgxf);
  429         sc->sc_ucom.sc_dying = 1;
  430         usbd_abort_pipe(sc->sc_notify_pipe);
  431         usbd_close_pipe(sc->sc_notify_pipe);
  432         if(sc->sc_is_ucom)
  433                 ucom_detach(&sc->sc_ucom);
  434         else
  435                 ttyfree(sc->sc_ucom.sc_tty);
  436         free(sc->sc_modetable, M_USBDEV);
  437         return rv;
  438 }
  439 
  440 
  441 static char *ufoma_mode_to_str(int mode)
  442 {
  443         int i;
  444         for(i = 0 ;umcpc_modetostr_tab[i].str != NULL; i++){
  445                 if(umcpc_modetostr_tab[i].mode == mode){
  446                         return umcpc_modetostr_tab[i].str;
  447                 }
  448         }
  449         return NULL;
  450 }
  451 
  452 static int ufoma_str_to_mode(char *str)
  453 {
  454         int i;
  455         for(i = 0 ;umcpc_modetostr_tab[i].str != NULL; i++){
  456                 if(strcmp(str, umcpc_modetostr_tab[i].str)==0){
  457                         return umcpc_modetostr_tab[i].mode;
  458                 }
  459         }
  460         return -1;
  461 }
  462 
  463 static void *ufoma_get_intconf( usb_config_descriptor_t *cd,
  464         usb_interface_descriptor_t *id, int type, int subtype)
  465 {
  466         uByte *p, *end;
  467         usb_descriptor_t *ud=NULL;
  468         int flag=0;
  469 
  470                                              
  471         for(p = (uByte *)cd,end = p + UGETW(cd->wTotalLength); p < end;
  472             p += ud->bLength){
  473                 ud = (usb_descriptor_t *)p;
  474                 if(flag && ud->bDescriptorType==UDESC_INTERFACE){
  475                         return NULL;
  476                 }
  477                 /*Read through this interface desc.*/
  478                 if(bcmp(p, id, sizeof(*id))==0){
  479                         flag=1;
  480                         continue;
  481                 }
  482                 if(flag==0)
  483                         continue;
  484                 if(ud->bDescriptorType == type 
  485                     && ud->bDescriptorSubtype == subtype){
  486                         break;
  487                 }
  488         }
  489         return ud;
  490 }
  491 
  492 
  493 
  494 static int ufoma_link_state(struct ufoma_softc *sc)
  495 {
  496         usb_device_request_t req;
  497         struct ucom_softc *ucom = &sc->sc_ucom;
  498         int err;
  499 
  500         req.bmRequestType = UT_WRITE_VENDOR_INTERFACE;
  501         req.bRequest = UMCPC_SET_LINK;
  502         USETW(req.wValue, UMCPC_CM_MOBILE_ACM);
  503         USETW(req.wIndex, sc->sc_ctl_iface_no);
  504         USETW(req.wLength, sc->sc_modetable[0]);        
  505         err = usbd_do_request(ucom->sc_udev, &req, sc->sc_modetable);
  506         if(err){
  507                 printf("SET_LINK:%d\n", err);
  508                 return EIO;
  509         }
  510         err = tsleep(&sc->sc_currentmode, PZERO|PCATCH, "fmalnk", hz);
  511         if(err){
  512                 printf("NO response");
  513                 return EIO;
  514         }
  515         if(sc->sc_currentmode != UMCPC_ACM_MODE_DEACTIVATED){
  516                 return EIO;
  517         }
  518         return 0;
  519 }
  520 
  521 static int ufoma_activate_state(struct ufoma_softc *sc, int state)
  522 {
  523         usb_device_request_t req;
  524         int err;
  525         struct ucom_softc *ucom = &sc->sc_ucom;
  526 
  527         req.bmRequestType = UT_WRITE_VENDOR_INTERFACE;
  528         req.bRequest = UMCPC_ACTIVATE_MODE;
  529         USETW(req.wValue, state);
  530         USETW(req.wIndex, sc->sc_ctl_iface_no);
  531         USETW(req.wLength, 0);  
  532         
  533         err = usbd_do_request(ucom->sc_udev, &req, NULL);
  534         if(err){
  535                 printf("%s:ACTIVATE:%s\n", device_get_nameunit(ucom->sc_dev), usbd_errstr(err));
  536                 return EIO;
  537         }
  538 
  539         err = tsleep(&sc->sc_currentmode, PZERO|PCATCH, "fmaact", UFOMA_MAX_TIMEOUT*hz);
  540         if(err){
  541                 printf("%s:NO response", device_get_nameunit(ucom->sc_dev));
  542                 return EIO;
  543         }
  544         if(sc->sc_currentmode != state){
  545                 return EIO;
  546         }
  547         return 0;
  548 }
  549 
  550 
  551 static inline void ufoma_setup_msg_req(struct ufoma_softc *sc, usb_device_request_t *req)
  552 {
  553                 req->bmRequestType = UT_READ_CLASS_INTERFACE;
  554                 req->bRequest = UCDC_GET_ENCAPSULATED_RESPONSE;
  555                 USETW(req->wIndex, sc->sc_ctl_iface_no);
  556                 USETW(req->wValue, 0);
  557                 USETW(req->wLength, UFOMA_CMD_BUF_SIZE);
  558 }
  559 
  560 
  561 static void ufoma_msg(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
  562 {
  563         usb_device_request_t req;
  564         struct ufoma_softc *sc = priv;
  565         int actlen,i;
  566         struct ucom_softc *ucom= &sc->sc_ucom;
  567         usbd_get_xfer_status(xfer, NULL, NULL, &actlen ,NULL);
  568         ufoma_setup_msg_req(sc, &req);
  569         mtx_lock(&sc->sc_mtx);
  570         for(i = 0;i < actlen; i++){
  571                 if(sc->sc_ucom.sc_tty->t_state & TS_ISOPEN)
  572                         ttyld_rint(sc->sc_ucom.sc_tty, sc->sc_resbuffer[i]);
  573         }
  574         sc->sc_nummsg--;
  575         if(sc->sc_nummsg){
  576                 usbd_setup_default_xfer(sc->sc_msgxf, ucom->sc_udev, 
  577                     priv, USBD_DEFAULT_TIMEOUT, &req,
  578                     sc->sc_resbuffer,
  579                     UFOMA_CMD_BUF_SIZE,
  580                     0, ufoma_msg);
  581                 usbd_transfer(sc->sc_msgxf);
  582         }
  583         mtx_unlock(&sc->sc_mtx);
  584 
  585 }
  586 
  587 static void ufoma_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
  588 {
  589         struct ufoma_softc *sc = priv;
  590         unsigned int a;
  591         struct ucom_softc *ucom =&sc->sc_ucom;
  592         usb_device_request_t req;
  593         ufoma_setup_msg_req(sc, &req);
  594         u_char mstatus;
  595 
  596         if (sc->sc_ucom.sc_dying)
  597                 return;
  598 
  599         if (status != USBD_NORMAL_COMPLETION) {
  600                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
  601                         return;
  602                 printf("%s: abnormal status: %s\n", device_get_nameunit(ucom->sc_dev),
  603                        usbd_errstr(status));
  604                 return;
  605         }
  606         if((sc->sc_notify_buf.bmRequestType == UT_READ_VENDOR_INTERFACE)&&
  607             (sc->sc_notify_buf.bNotification == UMCPC_REQUEST_ACKNOLEDGE)){
  608                 a =  UGETW(sc->sc_notify_buf.wValue);
  609                 sc->sc_currentmode = a>>8;
  610                 if(!(a&0xff)){
  611                         printf("%s:Mode change Failed\n", device_get_nameunit(ucom->sc_dev));
  612                 }
  613                 wakeup(&sc->sc_currentmode);
  614         }
  615         if(sc->sc_notify_buf.bmRequestType != UCDC_NOTIFICATION){
  616                 return;
  617         }
  618         switch(sc->sc_notify_buf.bNotification){
  619         case UCDC_N_RESPONSE_AVAILABLE:
  620                 if(sc->sc_is_ucom){
  621                         printf("%s:wrong response request?\n", device_get_nameunit(ucom->sc_dev));
  622                         break;
  623                 }
  624                 mtx_lock(&sc->sc_mtx);
  625                 if(!sc->sc_nummsg){
  626                         usbd_setup_default_xfer(sc->sc_msgxf, ucom->sc_udev, 
  627                             priv, USBD_DEFAULT_TIMEOUT, &req, sc->sc_resbuffer,
  628                             UFOMA_CMD_BUF_SIZE,
  629                             0, ufoma_msg);
  630                         usbd_transfer(sc->sc_msgxf);
  631                 }
  632                 sc->sc_nummsg++;
  633                 mtx_unlock(&sc->sc_mtx);
  634                 break;
  635         case UCDC_N_SERIAL_STATE:
  636                 if(!sc->sc_is_ucom){
  637                         printf("%s:wrong sereal request?\n",device_get_nameunit(ucom->sc_dev));
  638                         break;
  639                 }
  640 
  641                 /*
  642                  * Set the serial state in ucom driver based on
  643                  * the bits from the notify message
  644                  */
  645                 if (UGETW(sc->sc_notify_buf.wLength) != 2) {
  646                         printf("%s: Invalid notification length! (%d)\n",
  647                                device_get_nameunit(ucom->sc_dev),
  648                                UGETW(sc->sc_notify_buf.wLength));
  649                         break;
  650                 }
  651                 DPRINTF(("%s: notify bytes = %02x%02x\n",
  652                          device_get_nameunit(ucom->sc_dev),
  653                          sc->sc_notify_buf.data[0],
  654                          sc->sc_notify_buf.data[1]));
  655                 /* Currently, lsr is always zero. */
  656                 sc->sc_lsr = sc->sc_msr = 0;
  657                 mstatus = sc->sc_notify_buf.data[0];
  658 
  659                 if (ISSET(mstatus, UCDC_N_SERIAL_RI))
  660                         sc->sc_msr |= SER_RI;
  661                 if (ISSET(mstatus, UCDC_N_SERIAL_DSR))
  662                         sc->sc_msr |= SER_DSR;
  663                 if (ISSET(mstatus, UCDC_N_SERIAL_DCD))
  664                         sc->sc_msr |= SER_DCD;
  665                 /* Deferred notifying to the ucom layer */
  666                 taskqueue_enqueue(taskqueue_swi_giant, &sc->sc_task);
  667                 break;
  668         default:
  669                 break;
  670         }
  671 }
  672 
  673 static int ufoma_init_pseudo_ucom(struct ufoma_softc *sc)
  674 {
  675         struct tty *tp;
  676         struct ucom_softc *ucom = &sc->sc_ucom;
  677         tp = ucom->sc_tty = ttyalloc();
  678         tp->t_sc = sc;
  679         tp->t_oproc = ufomastart;
  680         tp->t_stop = nottystop;
  681         tp->t_open = ufomaopen;
  682         tp->t_close = ufomaclose;
  683         ttycreate(tp, TS_CALLOUT, "U%d", device_get_unit(ucom->sc_dev));
  684 
  685         return 0;
  686 }
  687 
  688 
  689 static int ufomaopen(struct tty * tty, struct cdev *cdev)
  690 {
  691 
  692         struct ufoma_softc *sc = tty->t_sc;
  693         
  694         if(sc->sc_ucom.sc_dying)
  695                 return (ENXIO);
  696         
  697         mtx_lock(&sc->sc_mtx);
  698         if(sc->sc_isopen){
  699                 mtx_unlock(&sc->sc_mtx);
  700                 return EBUSY;
  701         }
  702         mtx_unlock(&sc->sc_mtx);
  703 
  704         return  ufoma_ucom_open(sc, 0);
  705 }
  706 
  707 static void ufomaclose(struct tty *tty)
  708 {
  709         struct ufoma_softc *sc = tty->t_sc;
  710         ufoma_ucom_close(sc, 0);
  711 }
  712 
  713 static void ufomastart(struct tty *tp)
  714 {
  715         struct ufoma_softc *sc = tp->t_sc;
  716         struct ucom_softc *ucom = &sc->sc_ucom;
  717         usb_device_request_t req;
  718         int x;
  719         uByte c;
  720         x = spltty();
  721         if(tp->t_state  & (TS_TIMEOUT | TS_TTSTOP)){
  722                 ttwwakeup(tp);
  723                 return;
  724         }
  725 
  726         tp->t_state |= TS_BUSY;
  727         while(tp->t_outq.c_cc != 0){
  728                 c = getc(&tp->t_outq);
  729                 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  730                 req.bRequest = UCDC_SEND_ENCAPSULATED_COMMAND;
  731                 USETW(req.wIndex, sc->sc_ctl_iface_no);
  732                 USETW(req.wValue, 0);
  733                 USETW(req.wLength, 1);
  734                 usbd_do_request(ucom->sc_udev, &req, &c);
  735         }
  736         tp->t_state &= ~TS_BUSY;
  737         ttwwakeup(tp);
  738         splx(x);
  739 }
  740 
  741 static int ufoma_ucom_open(void *p, int portno)
  742 {
  743         struct ufoma_softc *sc = p;
  744         if(sc->sc_currentmode == UMCPC_ACM_MODE_UNLINKED){
  745                 ufoma_link_state(sc);
  746         }
  747         sc->sc_cmdbp = 0;
  748         if(sc->sc_currentmode == UMCPC_ACM_MODE_DEACTIVATED){
  749                 ufoma_activate_state(sc, sc->sc_modetoactivate);
  750         }
  751 
  752         return 0;
  753 }
  754 
  755 static void ufoma_ucom_close(void *p, int portno)
  756 {
  757         struct ufoma_softc *sc = p;
  758         ufoma_activate_state(sc, UMCPC_ACM_MODE_DEACTIVATED);
  759         return ;
  760 }
  761 
  762 void
  763 ufoma_break(struct ufoma_softc *sc, int onoff)
  764 {
  765         usb_device_request_t req;
  766         struct ucom_softc *ucom = &sc->sc_ucom;
  767         DPRINTF(("ufoma_break: onoff=%d\n", onoff));
  768 
  769         if (!(sc->sc_acm_cap & USB_CDC_ACM_HAS_BREAK))
  770                 return;
  771 
  772         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  773         req.bRequest = UCDC_SEND_BREAK;
  774         USETW(req.wValue, onoff ? UCDC_BREAK_ON : UCDC_BREAK_OFF);
  775         USETW(req.wIndex, sc->sc_ctl_iface_no);
  776         USETW(req.wLength, 0);
  777 
  778         (void)usbd_do_request(ucom->sc_udev, &req, 0);
  779 }
  780 
  781 void
  782 ufoma_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
  783 {
  784         struct ufoma_softc *sc = addr;
  785 
  786         if (lsr != NULL)
  787                 *lsr = sc->sc_lsr;
  788         if (msr != NULL)
  789                 *msr = sc->sc_msr;
  790 }
  791 
  792 static void ufoma_set(void * addr, int portno, int reg, int onoff)
  793 {
  794         struct ufoma_softc *sc = addr;
  795 
  796         switch (reg) {
  797         case UCOM_SET_DTR:
  798                 ufoma_dtr(sc, onoff);
  799                 break;
  800         case UCOM_SET_RTS:
  801                 ufoma_rts(sc, onoff);
  802                 break;
  803         case UCOM_SET_BREAK:
  804                 ufoma_break(sc, onoff);
  805                 break;
  806         default:
  807                 break;
  808         }
  809 
  810 }
  811 
  812 static void
  813 ufoma_set_line_state(struct ufoma_softc *sc)
  814 {
  815         usb_device_request_t req;
  816         struct ucom_softc *ucom = &sc->sc_ucom;
  817         int ls;
  818 
  819         ls = (sc->sc_dtr ? UCDC_LINE_DTR : 0) |
  820              (sc->sc_rts ? UCDC_LINE_RTS : 0);
  821         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  822         req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
  823         USETW(req.wValue, ls);
  824         USETW(req.wIndex, sc->sc_ctl_iface_no);
  825         USETW(req.wLength, 0);
  826 
  827         (void)usbd_do_request(ucom->sc_udev, &req, 0);
  828 
  829 }
  830 
  831 void
  832 ufoma_dtr(struct ufoma_softc *sc, int onoff)
  833 {
  834         DPRINTF(("ufoma_foma: onoff=%d\n", onoff));
  835 
  836         if (sc->sc_dtr == onoff)
  837                 return;
  838         sc->sc_dtr = onoff;
  839 
  840         ufoma_set_line_state(sc);
  841 }
  842 
  843 void
  844 ufoma_rts(struct ufoma_softc *sc, int onoff)
  845 {
  846         DPRINTF(("ufoma_foma: onoff=%d\n", onoff));
  847 
  848         if (sc->sc_rts == onoff)
  849                 return;
  850         sc->sc_rts = onoff;
  851 
  852         ufoma_set_line_state(sc);
  853 }
  854 
  855 usbd_status
  856 ufoma_set_line_coding(struct ufoma_softc *sc, usb_cdc_line_state_t *state)
  857 {
  858 
  859         usbd_status err;
  860         usb_device_request_t req;
  861         struct ucom_softc *ucom = &sc->sc_ucom;
  862 
  863         DPRINTF(("ufoma_set_line_coding: rate=%d fmt=%d parity=%d bits=%d\n",
  864                  UGETDW(state->dwDTERate), state->bCharFormat,
  865                  state->bParityType, state->bDataBits));
  866 
  867         if (memcmp(state, &sc->sc_line_state, UCDC_LINE_STATE_LENGTH) == 0) {
  868                 DPRINTF(("ufoma_set_line_coding: already set\n"));
  869                 return (USBD_NORMAL_COMPLETION);
  870         }
  871 
  872         req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
  873         req.bRequest = UCDC_SET_LINE_CODING;
  874         USETW(req.wValue, 0);
  875         USETW(req.wIndex, sc->sc_ctl_iface_no);
  876         USETW(req.wLength, UCDC_LINE_STATE_LENGTH);
  877 
  878         err = usbd_do_request(ucom->sc_udev, &req, state);
  879         if (err) {
  880                 DPRINTF(("ufoma_set_line_coding: failed, err=%s\n",
  881                          usbd_errstr(err)));
  882                 return (err);
  883         }
  884 
  885         sc->sc_line_state = *state;
  886 
  887         return (USBD_NORMAL_COMPLETION);
  888 }
  889 
  890 static int
  891 ufoma_param(void *addr, int portno, struct termios *t)
  892 {
  893 
  894         struct ufoma_softc *sc = addr;
  895         usbd_status err;
  896         usb_cdc_line_state_t ls;
  897 
  898         DPRINTF(("ufoma_param: sc=%p\n", sc));
  899 
  900         USETDW(ls.dwDTERate, t->c_ospeed);
  901         if (ISSET(t->c_cflag, CSTOPB))
  902                 ls.bCharFormat = UCDC_STOP_BIT_2;
  903         else
  904                 ls.bCharFormat = UCDC_STOP_BIT_1;
  905         if (ISSET(t->c_cflag, PARENB)) {
  906                 if (ISSET(t->c_cflag, PARODD))
  907                         ls.bParityType = UCDC_PARITY_ODD;
  908                 else
  909                         ls.bParityType = UCDC_PARITY_EVEN;
  910         } else
  911                 ls.bParityType = UCDC_PARITY_NONE;
  912         switch (ISSET(t->c_cflag, CSIZE)) {
  913         case CS5:
  914                 ls.bDataBits = 5;
  915                 break;
  916         case CS6:
  917                 ls.bDataBits = 6;
  918                 break;
  919         case CS7:
  920                 ls.bDataBits = 7;
  921                 break;
  922         case CS8:
  923                 ls.bDataBits = 8;
  924                 break;
  925         }
  926 
  927         err = ufoma_set_line_coding(sc, &ls);
  928         if (err) {
  929                 DPRINTF(("ufoma_param: err=%s\n", usbd_errstr(err)));
  930                 return (ENOTTY);
  931         }
  932 
  933         return (0);
  934 }
  935 
  936 static int ufoma_init_modem(struct ufoma_softc *sc,struct usb_attach_arg *uaa)
  937 {
  938         struct ucom_softc *ucom = &sc->sc_ucom;
  939         usb_config_descriptor_t *cd;
  940         usb_cdc_acm_descriptor_t *acm;
  941         usb_cdc_cm_descriptor_t *cmd;   
  942         usb_endpoint_descriptor_t *ed;
  943         usb_interface_descriptor_t *id;
  944         const char *devname = device_get_nameunit(ucom->sc_dev);
  945         int i;
  946         cd = usbd_get_config_descriptor(ucom->sc_udev);
  947         id = usbd_get_interface_descriptor(sc->sc_ctl_iface);
  948 
  949         sc->sc_is_ucom = 1;
  950 
  951         cmd = ufoma_get_intconf(cd, id, UDESC_CS_INTERFACE, UDESCSUB_CDC_CM);
  952         if(cmd == NULL)
  953                 return -1;
  954         sc->sc_cm_cap = cmd->bmCapabilities;
  955 
  956         acm = ufoma_get_intconf(cd, id, UDESC_CS_INTERFACE, UDESCSUB_CDC_ACM);
  957         if(acm == NULL)
  958                 return -1;
  959         sc->sc_acm_cap = acm->bmCapabilities;
  960         
  961         sc->sc_data_iface_no = cmd->bDataInterface;
  962         printf("%s: data interface %d, has %sCM over data, has %sbreak\n",
  963             devname, sc->sc_data_iface_no,
  964             sc->sc_cm_cap & USB_CDC_CM_OVER_DATA ? "" : "no ",
  965             sc->sc_acm_cap & USB_CDC_ACM_HAS_BREAK ? "" : "no ");
  966         
  967         for(i = 0; i < uaa->nifaces; i++){
  968                 if(!uaa->ifaces[i])
  969                         continue;
  970                 id = usbd_get_interface_descriptor(uaa->ifaces[i]);
  971                 if(id != NULL &&
  972                     id->bInterfaceNumber == sc->sc_data_iface_no){
  973                         sc->sc_data_iface = uaa->ifaces[i];
  974                         //uaa->ifaces[i] = NULL;
  975                 }
  976         }
  977 
  978         ucom->sc_iface = sc->sc_data_iface;
  979         ucom->sc_bulkin_no = ucom->sc_bulkout_no = -1;
  980         id = usbd_get_interface_descriptor(sc->sc_data_iface);
  981         for(i = 0 ; i < id->bNumEndpoints; i++){
  982                 ed = usbd_interface2endpoint_descriptor(sc->sc_data_iface, i);
  983                 if(ed == NULL){
  984                         printf("%s: endpoint descriptor for %d\n",
  985                             devname,i);
  986                         return -1;
  987                 }
  988                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
  989                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  990                         ucom->sc_bulkin_no = ed->bEndpointAddress;
  991                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
  992                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
  993                         ucom->sc_bulkout_no = ed->bEndpointAddress;
  994                 }
  995         }
  996         
  997         if (ucom->sc_bulkin_no == -1) {
  998                 printf("%s: Could not find data bulk in\n", devname);
  999                 return -1;
 1000         }
 1001         if (ucom->sc_bulkout_no == -1) {
 1002                 printf("%s: Could not find data bulk out\n", devname);
 1003                 return -1;
 1004         }
 1005         
 1006         sc->sc_dtr = -1;
 1007         
 1008         ucom->sc_parent = sc;
 1009         ucom->sc_portno = UCOM_UNK_PORTNO;
 1010         /* bulkin, bulkout set above */
 1011         ucom->sc_ibufsize = UMODEMIBUFSIZE;
 1012         ucom->sc_obufsize = UMODEMOBUFSIZE;
 1013         ucom->sc_ibufsizepad = UMODEMIBUFSIZE;
 1014         ucom->sc_opkthdrlen = 0;
 1015         ucom->sc_callback = &ufoma_callback;
 1016         TASK_INIT(&sc->sc_task, 0, ufoma_notify, sc);
 1017         ucom_attach(&sc->sc_ucom);
 1018         
 1019         return 0;
 1020 }
 1021 
 1022 static void
 1023 ufoma_notify(void *arg, int count)
 1024 {
 1025         struct ufoma_softc *sc;
 1026 
 1027         sc = (struct ufoma_softc *)arg;
 1028         if (sc->sc_ucom.sc_dying)
 1029                 return;
 1030         ucom_status_change(&sc->sc_ucom);
 1031 }
 1032 static int ufoma_sysctl_support(SYSCTL_HANDLER_ARGS)
 1033 {
 1034         struct ufoma_softc *sc = (struct ufoma_softc *)oidp->oid_arg1;
 1035         struct sbuf sb;
 1036         int i;
 1037         char *mode;
 1038 
 1039         sbuf_new(&sb, NULL, 1, SBUF_AUTOEXTEND);
 1040         for(i = 1; i < sc->sc_modetable[0]; i++){
 1041                 mode = ufoma_mode_to_str(sc->sc_modetable[i]);
 1042                 if(mode !=NULL){
 1043                         sbuf_cat(&sb, mode);
 1044                 }else{
 1045                         sbuf_printf(&sb, "(%02x)", sc->sc_modetable[i]);
 1046                 }
 1047                 if(i < (sc->sc_modetable[0]-1))
 1048                         sbuf_cat(&sb, ",");
 1049         }
 1050         sbuf_trim(&sb);
 1051         sbuf_finish(&sb);
 1052         sysctl_handle_string(oidp, sbuf_data(&sb), sbuf_len(&sb), req);
 1053         sbuf_delete(&sb);
 1054         
 1055         return 0;
 1056 }
 1057 static int ufoma_sysctl_current(SYSCTL_HANDLER_ARGS)
 1058 {
 1059         struct ufoma_softc *sc = (struct ufoma_softc *)oidp->oid_arg1;
 1060         char *mode;
 1061         char subbuf[]="(XXX)";
 1062         mode = ufoma_mode_to_str(sc->sc_currentmode);
 1063         if(!mode){
 1064                 mode = subbuf;
 1065                 snprintf(subbuf, sizeof(subbuf), "(%02x)", sc->sc_currentmode);
 1066         }
 1067         sysctl_handle_string(oidp, mode, strlen(mode), req);
 1068         
 1069         return 0;
 1070         
 1071 }
 1072 static int ufoma_sysctl_open(SYSCTL_HANDLER_ARGS)
 1073 {
 1074         struct ufoma_softc *sc = (struct ufoma_softc *)oidp->oid_arg1;
 1075         char *mode;
 1076         char subbuf[40];
 1077         int newmode;
 1078         int error;
 1079         int i;
 1080 
 1081         mode = ufoma_mode_to_str(sc->sc_modetoactivate);
 1082         if(mode){
 1083                 strncpy(subbuf, mode, sizeof(subbuf));
 1084         }else{
 1085                 snprintf(subbuf, sizeof(subbuf), "(%02x)", sc->sc_modetoactivate);
 1086         }
 1087         error = sysctl_handle_string(oidp, subbuf, sizeof(subbuf), req);
 1088         if(error != 0 || req->newptr == NULL){
 1089                 return error;
 1090         }
 1091         
 1092         if((newmode = ufoma_str_to_mode(subbuf)) == -1){
 1093                 return EINVAL;
 1094         }
 1095         
 1096         for(i = 1 ; i < sc->sc_modetable[0] ; i++){
 1097                 if(sc->sc_modetable[i] == newmode){
 1098                         sc->sc_modetoactivate = newmode;
 1099                         return 0;
 1100                 }
 1101         }
 1102         
 1103         return EINVAL;
 1104 }

Cache object: 93f58a5bc60ff8870833616c3ea55095


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.