dev_t rsrcdbmgr_devno_attach(const char *name, int minor_guess, int flags) { iov_t iovout[3], iovin[1]; rsrc_cmd_t request; rsrc_minor_request_t data; if (name && strchr(name, '/')) { errno = EINVAL; return((dev_t)-1); } if (!name) name = " "; request.i.type = RSRCDBMGR_RSRC_CMD; request.i.subtype = RSRCDBMGR_REQ_ATTACH | RSRCDBMGR_MINOR_NUM; request.i.pid = 0; request.i.count = 1; request.i.nbytes = sizeof(data) + strlen(name) +1; data.major = 0; data.minor = minor_guess; data.flags = flags; data.name = NULL; SETIOV(&iovout[0], &request, sizeof(request)); SETIOV(&iovout[1], &data, sizeof(data)); SETIOV(&iovout[2], name, strlen(name) +1); SETIOV(&iovin[0], &data, sizeof(data)); if (MsgSendv(RSRCDBMGR_COID, iovout, 3, iovin, 1) == -1) { return((dev_t)-1); } return(makedev(0, data.major, data.minor)); }
ssize_t write(int fd, const void *buff, size_t nbytes) { io_write_t msg; iov_t iov[2]; msg.i.type = _IO_WRITE; msg.i.combine_len = sizeof msg.i; msg.i.xtype = _IO_XTYPE_NONE; msg.i.nbytes = nbytes; msg.i.zero = 0; SETIOV(iov + 0, &msg.i, sizeof msg.i); SETIOV(iov + 1, buff, nbytes); return MsgSendv(fd, iov, 2, 0, 0); }
ssize_t _writexv(int fd, iov_t *iov, int nparts, unsigned xtype, void *xdata, size_t xdatalen, size_t nbytes) { io_write_t msg; if(nparts < 1 || (int)xdatalen < 0) { errno = EINVAL; return -1; } msg.i.type = _IO_WRITE; msg.i.combine_len = sizeof msg.i; msg.i.xtype = xtype; msg.i.zero = 0; SETIOV(iov + 0, &msg.i, sizeof msg.i); if((msg.i.nbytes = nbytes) == 0) { int i; for(i = 1; i < nparts; i++) { msg.i.nbytes += GETIOVLEN(&iov[i]); } } /* If the parts is negative, then the iov points to -nparts bytes of data */ return MsgSendv(fd, iov, nparts, xdata, -xdatalen); }
int ioctl(int fd, int cmd, ...) { va_list vl; void *data; struct termios ltermios; #ifdef NOT_USED struct termios *ptermios; struct termio ltermio; #endif struct termio *ptermio; int match, tempint; //Pull out the command and the data va_start(vl, cmd); data = va_arg(vl, void *); va_end(vl); /* These calls have significantly different inputs or outputs that we have to manipulate (or re-direct entirely) */ switch ((unsigned)cmd) { /**** These calls map to fcntl's ****/ //Set/Clear FD_CLOEXEC state case FIOCLEX: return(fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC)); case FIONCLEX: return(fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) & ~FD_CLOEXEC)); //These are undoced uses for fcntl case SIOCGPGRP: case FIOGETOWN: if ( (tempint = fcntl (fd, F_GETOWN)) != -1) *(int *)data = tempint; return(tempint); case SIOCSPGRP: case FIOSETOWN: return(fcntl(fd, F_SETOWN, *(int *)data)); //Set the non-blocking state for reads on and off case FIONBIO: if (*(int *)data) return(fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK)); else return(fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK)); //Set the async state on and off case FIOASYNC: if (*(int *)data) return(fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_ASYNC)); else return(fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_ASYNC)); //Set/Clear exclusive mode case TIOCEXCL: { struct flock lflock; memset(&lflock, 0, sizeof(lflock)); lflock.l_type = F_WRLCK; //Fails if file opened read only? lflock.l_whence = SEEK_SET; lflock.l_start = 0; lflock.l_len = 0; lflock.l_pid = getpid(); return(__fcntl2ioctl(fcntl(fd, F_SETLK, &lflock))); } case TIOCNXCL: { struct flock lflock; memset(&lflock, 0, sizeof(lflock)); lflock.l_type = F_UNLCK; lflock.l_whence = SEEK_SET; lflock.l_start = 0; lflock.l_len = 0; lflock.l_pid = getpid(); (void)fcntl(fd, F_GETLK, &lflock); return(__fcntl2ioctl(fcntl(fd, F_SETLK, &lflock))); } //Make the terminal the controlling terminal for the process case TIOCSCTTY: return(tcsetsid(fd, getpid())); //Dis-associate this terminal as the controlling terminal case TIOCNOTTY: return(tcsetsid(-1, getpid())); /**** These calls translate from one type to another using tc[s|g]etattr ****/ //Terminal properties w/ termio case TCGETA: { ptermio = (struct termio *)data; if (tcgetattr(fd, <ermios) == -1) return(-1); termios2termio(<ermios, ptermio); return(EOK); } case TCSETA: { ptermio = (struct termio *)data; if (tcgetattr(fd, <ermios) == -1) return(-1); termio2termios(ptermio, <ermios); return(tcsetattr(fd, TCSANOW, <ermios)); } case TCSETAW: { ptermio = (struct termio *)data; if (tcgetattr(fd, <ermios) == -1) return(-1); termio2termios(ptermio, <ermios); return(tcsetattr(fd, TCSADRAIN, <ermios)); } case TCSETAF: { ptermio = (struct termio *)data; if (tcgetattr(fd, <ermios) == -1) return(-1); termio2termios(ptermio, <ermios); return(tcsetattr(fd, TCSAFLUSH, <ermios)); } //Set terminal state in an sgttyb structure (incomplete) case TIOCGETP: { struct sgttyb *psgttyb = (struct sgttyb *)data; if (tcgetattr(fd, <ermios) == -1) return(-1); termios2sgttyb(<ermios, psgttyb); return(EOK); } case TIOCSETP: { struct sgttyb *psgttyb = (struct sgttyb *)data; if (tcgetattr(fd, <ermios) == -1) return(-1); sgttyb2termios(psgttyb, <ermios); return(tcsetattr(fd, TCSAFLUSH, <ermios)); } case TIOCSETN: { struct sgttyb *psgttyb = (struct sgttyb *)data; if (tcgetattr(fd, <ermios) == -1) return(-1); sgttyb2termios(psgttyb, <ermios); return(tcsetattr(fd, TCSANOW, <ermios)); } //Terminal state in tchars structure case TIOCGETC: { struct tchars *ptchars = (struct tchars *)data; if (tcgetattr(fd, <ermios) == -1) return(-1); termios2tchars(<ermios, ptchars); return(EOK); } case TIOCSETC: { struct tchars *ptchars = (struct tchars *)data; if (tcgetattr(fd, <ermios) == -1) return(-1); tchars2termios(ptchars, <ermios); return(tcsetattr(fd, TCSANOW, <ermios)); } //Terminal state in an ltchars structure case TIOCGLTC: { struct ltchars *pltchars = (struct ltchars *)data; if (tcgetattr(fd, <ermios) == -1) return(-1); termios2ltchars(<ermios, pltchars); return(EOK); } case TIOCSLTC: { struct ltchars *pltchars = (struct ltchars *)data; if (tcgetattr(fd, <ermios) == -1) return(-1); ltchars2termios(pltchars, <ermios); return(tcsetattr(fd, TCSANOW, <ermios)); } //Set/Get the local flags structure case TIOCLGET: { if (tcgetattr(fd, <ermios) == -1) return(-1); *((int *)data) = (int)ltermios.c_lflag; return(EOK); } case TIOCLSET: { if (tcgetattr(fd, <ermios) == -1) return(-1); ltermios.c_lflag &= ~0xffff; ltermios.c_lflag |= *((int*)data); return(tcsetattr(fd, TCSANOW, <ermios)); } //Clear the break flag (implement TIOCSBRK?) case TIOCCBRK: { if (tcgetattr(fd, <ermios) == -1) return(-1); ltermios.c_iflag &= ~(BRKINT); ltermios.c_iflag |= IGNBRK; return(tcsetattr(fd, TCSANOW, <ermios)); } //Set the HUPCL flag case TIOCHPCL: { if (tcgetattr(fd, <ermios) != -1) { ltermios.c_cflag |= HUPCL; return(tcsetattr(fd, TCSANOW, <ermios)); } } /**** These calls map to devctl's, but need serious data munging ****/ //Inject a character into the stream case TIOCSTI: { return(tcinject(fd, (char*)data, sizeof(char))); } //Send a break for a period of time case TCSBRK: { int *duration = (int *) data; //Duration is measured in ms return(tcsendbreak(fd, *duration)); //tempint = (((*duration) ? *duration : 300) << 16) | _SERCTL_BRK_CHG | _SERCTL_BRK; //return(devctl(fd, DCMD_CHR_SERCTL, &tempint, sizeof(tempint), &ret)); } /**** Modem control operations (via devctl) ****/ //Clear the state of the modem by ~AND'ing in the int argument case TIOCMBIC: { int tmpmodem; if (_devctl(fd, DCMD_CHR_LINESTATUS, &tmpmodem, sizeof(tmpmodem), _DEVCTL_FLAG_NOTTY) == -1) return(-1); tmpmodem &= ~(*((int*)data)); tempint = 0; modem2serctl(&tmpmodem, &tempint); return(_devctl(fd, DCMD_CHR_SERCTL, &tempint, sizeof(tempint), _DEVCTL_FLAG_NOTTY)); } //Set the state of the modem by OR'ing in the int argument case TIOCMBIS: { int tmpmodem; if (_devctl(fd, DCMD_CHR_LINESTATUS, &tmpmodem, sizeof(tmpmodem), _DEVCTL_FLAG_NOTTY) == -1) return(-1); tmpmodem |= *((int*)data); tempint = 0; modem2serctl(&tmpmodem, &tempint); return(_devctl(fd, DCMD_CHR_SERCTL, &tempint, sizeof(tempint), _DEVCTL_FLAG_NOTTY)); } //Set the state of the modem lines case TIOCMSET: { tempint = 0; modem2serctl((int*)data, &tempint); return(_devctl(fd, DCMD_CHR_SERCTL, &tempint, sizeof(tempint), _DEVCTL_FLAG_NOTTY)); } //Set/Clear DTR lines case TIOCCDTR: { int status; if (_devctl(fd, DCMD_CHR_LINESTATUS, &status, sizeof(status), _DEVCTL_FLAG_NOTTY) == -1) return(-1); if (status & _LINESTATUS_SER_DTR) { status = _SERCTL_DTR_CHG; return(_devctl(fd, DCMD_CHR_SERCTL, &status, sizeof(status), _DEVCTL_FLAG_NOTTY)); } return(EOK); } case TIOCSDTR: { int status; if (_devctl(fd, DCMD_CHR_LINESTATUS, &status, sizeof(status), _DEVCTL_FLAG_NOTTY) == -1) return(-1); if (!(status & _LINESTATUS_SER_DTR)) { status = _SERCTL_DTR | _SERCTL_DTR_CHG; return(_devctl(fd, DCMD_CHR_SERCTL, &status, sizeof(status), _DEVCTL_FLAG_NOTTY)); } return(EOK); } default: break; } /* * The following block can go away when 6.4 is released * and <sys/sockio.h> from the networking project is * generally available. */ #ifndef NOSIOCGIFCONF /* Define these as in the latest <sys/sockio.h> */ #define NOSIOCGIFCONF _IOWR('i', 36, struct ifconf) #undef SIOCGIFCONF #define SIOCGIFCONF _IOWR('i', 38, struct ifconf) #endif /* Generic handling for all but SIOCGIFCONF networking IOCTL's */ if ((unsigned)cmd == SIOCGIFCONF || (unsigned)cmd == NOSIOCGIFCONF) { io_devctl_t msg; iov_t wiov[2], riov[3]; struct ifconf *ifconfp = (struct ifconf *)data; msg.i.type = _IO_DEVCTL; msg.i.combine_len = sizeof(msg.i); msg.i.dcmd = cmd; msg.i.zero = 0; msg.i.nbytes = ifconfp->ifc_len; SETIOV (wiov + 0, &msg, sizeof (msg.i)); SETIOV (wiov + 1, data, IOCPARM_LEN((unsigned)cmd)); SETIOV (riov + 0, &msg, sizeof (msg.o)); SETIOV (riov + 1, ifconfp, sizeof (ifconfp->ifc_len)); SETIOV (riov + 2, ifconfp->ifc_buf, ifconfp->ifc_len); return MsgSendv(fd, wiov, 2, riov, 3); } /* These calls require their command types to be translated */ switch ((unsigned)cmd) { case TCGETS: //Not on NetBSD SETNEWNUM(cmd, TIOCGETA); match = 1; break; case TCSETS: //Not on NetBSD SETNEWNUM(cmd, TIOCSETA); match = 1; break; case TCSETSW: //Not on NetBSD SETNEWNUM(cmd, TIOCSETAW); match = 1; break; case TCSETSF: //Not on NetBSD SETNEWNUM(cmd, TIOCSETAF); match = 1; break; case TIOCSETPGRP: //Not on Sun SETNEWNUM(cmd, TIOCSPGRP); match = 1; break; case TIOCGETPGRP: //Not on Sun SETNEWNUM(cmd, TIOCGPGRP); match = 1; break; case TIOCSTOP: case TIOCSTART: //These functions pass in void but we need to pass an int so ... data = &tempint; tempint = (cmd == TIOCSTOP) ? TCOOFF : TIOCSTART; cmd = _IOW(_DCMD_CHR,TCXONC,int); //Create new command case TCXONC: //Not on NetBSD //Assume incoming data already looks like: //data = 0= suspend output = TCOOFF, 1= restart output = TCOON // 2= suspend input = TCIOFF, 3= restart input = TCION SETNEWNUM(cmd, TCXONC); match = 1; break; case TIOCFLUSH: //Need to re-map 0 -> 2, FREAD -> 0, FWRITE -> 1 switch (*((int*)data)) { case 0: *((int*)data) = TCIOFLUSH; break; case FREAD: *((int*)data) = TCIFLUSH; break; case FWRITE: *((int*)data) = TCOFLUSH; break; default: break; } /* Fall Through */ case TCFLSH: //Not on NetBSD //Assume input data looks like: //data = 0 = flush in, 1 = flush output, 2 = flush both SETNEWNUM(cmd, TIOCFLUSH); match = 1; break; default: break; } //If you got this far then out you go as a generic devctl return(_devctl(fd, cmd, data, IOCPARM_LEN((unsigned)cmd), _DEVCTL_FLAG_NOTTY)); /* Returns different things for different commands: - GETPRGRP returns pid_t - FIOREAD returns number of chars in input queue - TIOCOUTQ returns number of chars in output queue - 0 for all other cases */ }
void service_message(struct _Ph_msg_forward *msg, input_region_data_t *regdat) { input_module_t *module; iov_t smx[3], rmx[1]; io_devctl_t devhdr; struct { struct _Ph_msg_forward fwd; int result; } reply; SETIOV(rmx, &reply, sizeof(reply)); memset(&reply, '\0', sizeof(reply)); devhdr.i.type = _IO_DEVCTL; devhdr.i.combine_len = 0; devhdr.i.dcmd = _Ph_REPLY; devhdr.i.zero = 0; SETIOV(&smx[0], &devhdr.i, sizeof(devhdr.i)); reply.fwd.hdr.type = _Ph_REPLY; reply.fwd.pid = msg->pid; reply.fwd.len = sizeof(reply.result); reply.result = EOK; SETIOV(&smx[1], &reply, sizeof(reply)); switch(msg->hdr.subtype) { case _INTERACTTYPE & 0xffff: { struct _interact_device *interact = (struct _interact_device *)((char *)msg + sizeof(struct _Ph_msg_forward)); module = interact->handle; switch(module->type & DEVI_CLASS_MASK) { case DEVI_CLASS_REL: case DEVI_CLASS_ABS: interact->type = _INTERACT_TYPE_POINTER; break; case DEVI_CLASS_KBD: interact->type = _INTERACT_TYPE_KEY; break; default: break; } reply.fwd.hdr.subtype = msg->hdr.subtype; reply.fwd.len += sizeof(*interact); SETIOV(&smx[2], interact, sizeof(*interact)); break; } case _POINTERGETINFO & 0xffff: { unsigned long flags; struct _pointer_info *ctrl = (struct _pointer_info *)((char *)msg + sizeof(struct _Ph_msg_forward)); struct devctl_coord_range range; module = ctrl->type.handle; if(!module) { break; } memset(ctrl, '\0', sizeof(*ctrl)); ctrl->type.type = _INTERACT_TYPE_POINTER; if(module->devctrl) { (module->devctrl)(module, DEVCTL_GETPTRBTNS, &ctrl->buttons); (module->devctrl)(module, DEVCTL_GETDEVFLAGS, &flags); } ctrl->flags = 0U; if(flags & ABSOLUTE) { ctrl->flags |= _POINTER_FLAG_TOUCH; if(flags & ABS_PRESS_DATA) { ctrl->flags |= _POINTER_FLAG_PRESSURE; } } else { ctrl->flags |= _POINTER_FLAG_MOUSE; } if(ctrl->buttons) { ctrl->flags |= _POINTER_FLAG_BUTTON; } if(module->devctrl) { if((module->devctrl)(module, DEVCTL_GETPTRCOORD, &ctrl->num_coord) != -1) { if(flags & ABSOLUTE) { for(range.which = 0; range.which < ctrl->num_coord; range.which++) { (module->devctrl)(module, DEVCTL_GETCOORDRNG, &range); ctrl->range[range.which].min = range.min; ctrl->range[range.which].max = range.max; } } } else { ctrl->num_coord = 0; } } else { ctrl->num_coord = 0; } if(module->devctrl) { if((module->devctrl)(module, DEVCTL_GETPTRPRESS, &ctrl->num_pressure) != -1) { for(range.which = 0; range.which < ctrl->num_pressure; range.which++) { (module->devctrl)(module, DEVCTL_GETPRESSRNG, &range); ctrl->range[range.which+ ctrl->num_coord].min = range.min; ctrl->range[range.which+ ctrl->num_coord].max = range.max; } } else { ctrl->num_pressure = 0; } } else { ctrl->num_pressure = 0; } reply.fwd.hdr.subtype = msg->hdr.subtype; reply.fwd.len += sizeof(*ctrl); SETIOV(&smx[2], ctrl, sizeof(*ctrl)); break; } case _POINTERGETCTRL & 0xffff: { struct _pointer_ctrl *ctrl = (struct _pointer_ctrl *)((char *)msg + sizeof(struct _Ph_msg_forward)); if (verbosity) printf("POINTERGETCTRL\n"); module = ctrl->type.handle; if(!module) { reply.result = ESRCH; goto reply; } memset(ctrl, '\0', sizeof(*ctrl)); if(module->devctrl) { struct devctl_rel_accel accel; struct devctl_wheel_accel wheel_accel; if(module) { unsigned swap = 0, wheel = 0; if((module->devctrl)(module, DEVCTL_GETACCEL, &accel) == -1) { reply.result = ENOTSUP; } if((module->devctrl)(module, DEVCTL_GETWHEEL_ACCEL, &wheel_accel) == -1) { reply.result = ENOTSUP; } if((module->devctrl)(module, DEVCTL_GETSWAP, &swap) == -1) { reply.result = ENOTSUP; } if((module->devctrl)(module, DEVCTL_GETWHEEL, &wheel) == -1) { reply.result = ENOTSUP; } ctrl->flags = (swap << _POINTER_FLAG_SWAP_POS) | (wheel & 3) << 20; ctrl->gain = accel.gain; ctrl->threshold = accel.threshold; } else { reply.result = ESRCH; } } reply: reply.fwd.hdr.subtype = msg->hdr.subtype; reply.fwd.len += sizeof(*ctrl); SETIOV(&smx[2], ctrl, sizeof(*ctrl)); break; } case _POINTERSETCTRL & 0xffff: { struct _pointer_ctrl *ctrl = (struct _pointer_ctrl *)((char *)msg + sizeof(struct _Ph_msg_forward)); module = ctrl->type.handle; if(!module) { break; } if(module->devctrl) { struct devctl_rel_accel accel; unsigned swap, wheel; accel.gain = ctrl->gain; accel.threshold = ctrl->threshold; swap = (ctrl->flags & _POINTER_FLAG_SWAP_MASK) >> _POINTER_FLAG_SWAP_POS; wheel = (ctrl->flags & 0x00300000) >> 20; if(module) { if((module->devctrl)(module, DEVCTL_SETACCEL, &accel) == -1) { reply.result = ENOTSUP; } if((module->devctrl)(module, DEVCTL_SETSWAP, &swap) == -1) { reply.result = ENOTSUP; } if((module->devctrl)(module, DEVCTL_SETWHEEL, &wheel) == -1) reply.result = ENOTSUP; } else { reply.result = ESRCH; } } reply.fwd.hdr.subtype = msg->hdr.subtype; reply.fwd.len += sizeof(*ctrl); SETIOV(&smx[2], ctrl, sizeof(*ctrl)); break; } case _POINTERSETMATRIX & 0xffff: { struct _pointer_transform *transform = (struct _pointer_transform *)((char *)msg + sizeof(struct _Ph_msg_forward)); module = transform->type.handle; if(!module) { break; } switch(module->type & DEVI_CLASS_MASK) { case DEVI_CLASS_ABS: { struct devctl_disparea_res new_res; new_res.xl = transform->xy_coord.xoffset.number; new_res.yl = transform->xy_coord.yoffset.number; new_res.xh = transform->xy_coord.xscale.number; new_res.yh = transform->xy_coord.yscale.number; if(module && module->devctrl) { (module->devctrl)(module, DEVCTL_RESCHG, &new_res); } } default: reply.result = EINVAL; break; } reply.fwd.hdr.subtype = msg->hdr.subtype; reply.fwd.len += sizeof(*transform); SETIOV(&smx[2], transform, sizeof(*transform)); break; } case _KEYBOARDGETCTRL & 0xffff: { struct _keyboard_ctrl *kbctrl = (struct _keyboard_ctrl *)((char *)msg + sizeof(struct _Ph_msg_forward)); module = (kbctrl) ? kbctrl->type.handle : NULL; if(!module) { break; } switch(module->type & DEVI_CLASS_MASK) { case DEVI_CLASS_KBD: { struct devctl_getkbd info; (module->devctrl)(module, DEVCTL_GETKBD, &info); kbctrl->rate = info.rate; kbctrl->delay = info.delay; break; } default: reply.result = EINVAL; break; } reply.fwd.hdr.subtype = msg->hdr.subtype; reply.fwd.len += sizeof(*kbctrl); SETIOV(&smx[2], kbctrl, sizeof(*kbctrl)); break; } case _KEYBOARDSETCTRL & 0xffff: { struct _keyboard_ctrl *kbctrl = (struct _keyboard_ctrl *)((char *)msg + sizeof(struct _Ph_msg_forward)); module = kbctrl->type.handle; if(!module) { break; } switch(module->type & DEVI_CLASS_MASK) { case DEVI_CLASS_KBD: { if(module->devctrl) { struct devctl_setkbd devctl; if(verbosity) { printf("%s: setting kb ctrl parms [rate %d, delay %d]\n", module->name, kbctrl->rate, kbctrl->delay); } devctl.delay = kbctrl->delay; devctl.rate = kbctrl->rate; if((module->devctrl)(module, DEVCTL_SETKBD, &devctl) == -1) { reply.result = ENOTSUP; } } break; } default: reply.result = EINVAL; break; } reply.fwd.hdr.subtype = msg->hdr.subtype; reply.fwd.len += sizeof(*kbctrl); SETIOV(&smx[2], kbctrl, sizeof(*kbctrl)); break; } case _KEYBOARDGETKEYMAPPATH & 0xffff: { struct _keyboard_ctrl *keymap = (struct _keyboard_ctrl *)((char *)msg + sizeof(struct _Ph_msg_forward)); if (verbosity) printf("devctl: KEYBOARDGETKEYMAPPATH\n"); module = keymap->type.handle; if(!module || !keymap) { break; } switch(module->type & DEVI_CLASS_MASK) { case DEVI_CLASS_KBD: { char *kmf = keymap->mapfile; if(kmf) { if((module->devctrl)(module, DEVCTL_GETKEYF, kmf) == -1) { reply.result = ENOTSUP; } } break; } default: reply.result = EINVAL; break; } reply.fwd.hdr.subtype = msg->hdr.subtype; reply.fwd.len += sizeof(*keymap); SETIOV(&smx[2], keymap, sizeof(*keymap)); break; } case _KEYBOARDSETKEYMAPPATH & 0xffff: { struct _keyboard_ctrl *keymap = (struct _keyboard_ctrl *)((char *)msg + sizeof(struct _Ph_msg_forward)); if (verbosity) printf("devctl: KEYBOARDSETKEYMAPPATH\n"); module = keymap->type.handle; if(!module) { break; } switch(module->type & DEVI_CLASS_MASK) { case DEVI_CLASS_KBD: { char *kmf = keymap->mapfile; if((module->devctrl)(module, DEVCTL_SETKEYF, kmf) == -1) { reply.result=ENOTSUP; } break; } default: reply.result = EINVAL; break; } reply.fwd.hdr.subtype = msg->hdr.subtype; reply.fwd.len += sizeof(*keymap); SETIOV(&smx[2], keymap, sizeof(*keymap)); break; } case _FEEDBACKGETLEDMASK & 0xffff: { struct _feedback_led *led = (struct _feedback_led *)((char *)msg + sizeof(struct _Ph_msg_forward)); module = led->type.handle; if(!module) break; switch(module->type & DEVI_CLASS_MASK) { case DEVI_CLASS_KBD: { if(led) { (module->devctrl)(module, DEVCTL_GETLEDMASK, led); } break; } default: reply.result = EINVAL; break; } reply.fwd.hdr.subtype = msg->hdr.subtype; reply.fwd.len += sizeof(*led); SETIOV(&smx[2], led, sizeof(*led)); break; } case _FEEDBACKGETLED & 0xffff: { struct _feedback_led *led = (struct _feedback_led *)((char *)msg + sizeof(struct _Ph_msg_forward)); module = led->type.handle; if(!module) { break; } switch(module->type & DEVI_CLASS_MASK) { case DEVI_CLASS_KBD: { if(led) { struct devctl_led led2; (module->devctrl)(module, DEVCTL_GETLED, &led2); led->value = led2.value; led->mask = led2.mask; } break; } default: reply.result = EINVAL; break; } reply.fwd.hdr.subtype = msg->hdr.subtype; reply.fwd.len += sizeof(*led); SETIOV(&smx[2], led, sizeof(*led)); break; } case _FEEDBACKSETLED & 0xffff: { struct _feedback_led *led = (struct _feedback_led *)((char *)msg + sizeof(struct _Ph_msg_forward)); module = led->type.handle; if(!module) { break; } switch(module->type & DEVI_CLASS_MASK) { case DEVI_CLASS_KBD: { reply.result=(module->devctrl)(module, DEVCTL_SETLED, led); break; } default: reply.result = EINVAL; break; } reply.fwd.hdr.subtype = msg->hdr.subtype; reply.fwd.len += sizeof(*led); SETIOV(&smx[2], led, sizeof(*led)); break; } default: reply.result = EINVAL; break; } devhdr.i.nbytes = sizeof(reply) + reply.fwd.len; if (MsgSendv(IpCurrentFd, smx, 3, rmx, 1) < 0) perror("MsgSendv"); }
int _vfcntl(int fd, int cmd, va_list ap) { union { io_dup_t dup; io_space_t space; io_lock_t lock; } msg; iov_t iov[4]; int arg; pid_t pid; switch(cmd) { case F_DUPFD: { struct _server_info info; int fd2; if(fd == -1 || (fd & _NTO_SIDE_CHANNEL) || ConnectServerInfo(0, fd, &info) != fd) { errno = EBADF; return -1; } if((fd2 = va_arg(ap, int)) < 0 || (fd2 & _NTO_SIDE_CHANNEL)) { errno = EINVAL; return -1; } if((fd2 = ConnectAttach(info.nd, info.pid, info.chid, fd2, _NTO_COF_CLOEXEC)) == -1) { return -1; } msg.dup.i.type = _IO_DUP; msg.dup.i.combine_len = sizeof msg.dup; msg.dup.i.info.nd = netmgr_remote_nd(info.nd, ND_LOCAL_NODE); msg.dup.i.info.pid = getpid(); msg.dup.i.info.chid = info.chid; msg.dup.i.info.scoid = info.scoid; msg.dup.i.info.coid = fd; if(MsgSendnc(fd2, &msg.dup.i, sizeof msg.dup.i, 0, 0) == -1) { ConnectDetach_r(fd2); return -1; } ConnectFlags_r(0, fd2, FD_CLOEXEC, 0); return fd2; } case F_GETFD: return ConnectFlags(0, fd, 0, 0); case F_SETFD: return ConnectFlags(0, fd, ~0, va_arg(ap, int)); case F_GETFL: if(_devctl(fd, DCMD_ALL_GETFLAGS, &arg, sizeof arg, 0) == -1) { return -1; } return arg; case F_SETFL: arg = va_arg(ap, int); return _devctl(fd, DCMD_ALL_SETFLAGS, &arg, sizeof arg, _DEVCTL_FLAG_NORETVAL); case F_GETOWN: if(_devctl(fd, DCMD_ALL_GETOWN, &pid, sizeof pid, 0) == -1) { return -1; } return pid; case F_SETOWN: pid = va_arg(ap, pid_t); return _devctl(fd, DCMD_ALL_SETOWN, &pid, sizeof pid, _DEVCTL_FLAG_NORETVAL); case F_ALLOCSP64: case F_FREESP64: { flock64_t *area = va_arg(ap, flock64_t *); msg.space.i.start = area->l_start; msg.space.i.len = area->l_len; msg.space.i.whence = area->l_whence; goto common; } case F_ALLOCSP: cmd = F_ALLOCSP64; /* Always pass the 64 bit values */ goto stuff; case F_FREESP: cmd = F_FREESP64; /* Always pass the 64 bit values */ stuff: { flock_t *area = va_arg(ap, flock_t *); msg.space.i.start = area->l_start; msg.space.i.len = area->l_len; msg.space.i.whence = area->l_whence; } common: msg.space.i.type = _IO_SPACE; msg.space.i.combine_len = sizeof msg.space.i; msg.space.i.subtype = cmd; return MsgSend(fd, &msg.space.i, sizeof msg.space.i, 0, 0); case F_GETLK: case F_SETLK: case F_SETLKW: case F_GETLK64: case F_SETLK64: case F_SETLKW64: msg.lock.i.type = _IO_LOCK; msg.lock.i.combine_len = sizeof msg.lock.i; msg.lock.i.subtype = cmd; SETIOV(iov + 0, &msg.lock.i, sizeof msg.lock.i); SETIOV(iov + 1, va_arg(ap, flock_t *), sizeof(flock_t)); iov[3] = iov[1]; SETIOV(iov + 2, &msg.lock.o, sizeof msg.lock.o); return MsgSendv(fd, iov + 0, 2, iov + 2, (cmd == F_GETLK || cmd == F_GETLK64) ? 2 : 1); default: break; } errno = EINVAL; return -1; }
static int _aio_handler(struct _aio_context *ctp) { struct aiocb *curr; io_lseek_t lmsg; union { io_read_t rmsg; io_write_t wmsg; } msg; iov_t iov[3]; int niov; if (!ctp) return -1; while ((curr = ctp->curr_list) != NULL) { /* see if we need to change sched_param */ if (ctp->policy != curr->_aio_policy || memcmp(&ctp->param, &curr->_aio_param, sizeof(ctp->param))) { curr->_aio_error = pthread_setschedparam(ctp->tid, curr->_aio_policy, (struct sched_param *)&curr->_aio_param); if (curr->_aio_error != EOK) { curr->_aio_result = (unsigned)-1; _aio_wakeup(curr); continue; } ctp->policy = curr->_aio_policy; memcpy(&ctp->param, &curr->_aio_param, sizeof ctp->param); } niov = 0; switch (curr->_aio_iotype) { case _AIO_OPCODE_READ: case _AIO_OPCODE_WRITE: /* creat a lseek + read/write combined message */ lmsg.i.type = _IO_LSEEK; lmsg.i.combine_len = sizeof(lmsg) | _IO_COMBINE_FLAG; lmsg.i.offset = curr->aio_offset; lmsg.i.whence = SEEK_SET; lmsg.i.zero = 0; SETIOV(iov + niov, &lmsg, sizeof(lmsg)); niov++; if (curr->_aio_iotype == _AIO_OPCODE_READ) { msg.rmsg.i.type = _IO_READ; msg.rmsg.i.combine_len = sizeof(msg.rmsg); msg.rmsg.i.nbytes = curr->aio_nbytes; msg.rmsg.i.xtype = _IO_XTYPE_NONE; msg.rmsg.i.zero = 0; SETIOV(iov + niov, &msg, sizeof(msg.rmsg)); niov++; curr->_aio_result = MsgSendvs(curr->aio_fildes, iov, niov, (void *)curr->aio_buf, curr->aio_nbytes); } else { msg.wmsg.i.type = _IO_WRITE; msg.wmsg.i.combine_len = sizeof(msg.wmsg); msg.wmsg.i.xtype = _IO_XTYPE_NONE; msg.wmsg.i.nbytes = curr->aio_nbytes; msg.wmsg.i.zero = 0; SETIOV(iov + niov, &msg, sizeof(msg.wmsg)); SETIOV(iov + niov + 1, curr->aio_buf, curr->aio_nbytes); niov += 2; curr->_aio_result = MsgSendv(curr->aio_fildes, iov, niov, 0, 0); } break; case _AIO_OPCODE_SYNC: curr->_aio_result = fsync(curr->aio_fildes); break; case _AIO_OPCODE_DSYNC: curr->_aio_result = fdatasync(curr->aio_fildes); break; default: break; } _mutex_lock(&_aio_cb->cb_mutex); ctp->curr_list = curr->_aio_next; curr->_aio_next = NULL; _mutex_unlock(&_aio_cb->cb_mutex); if (curr->_aio_result == -1U) { curr->_aio_error = errno; } else { curr->_aio_error = EOK; } _aio_wakeup(curr); } return 0; }