⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vt.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	/*	 * To have permissions to do most of the vt ioctls, we either have	 * to be the owner of the tty, or super-user.	 */	perm = 0;	if (current->tty == tty || suser())		perm = 1; 	kbd = kbd_table + console;	switch (cmd) {	case KIOCSOUND:		if (!perm)			return -EPERM;		if (arg)			arg = 1193180 / arg;		kd_mksound(arg, 0);		return 0;	case KDMKTONE:		if (!perm)			return -EPERM;	{		unsigned int ticks, count;				/*		 * Generate the tone for the appropriate number of ticks.		 * If the time is zero, turn off sound ourselves.		 */		ticks = HZ * ((arg >> 16) & 0xffff) / 1000;		count = ticks ? (arg & 0xffff) : 0;		if (count)			count = 1193180 / count;		kd_mksound(count, ticks);		return 0;	}	case KDGKBTYPE:		/*		 * this is naive.		 */		ucval = keyboard_type;		goto setchar;#ifndef __alpha__		/*		 * These cannot be implemented on any machine that implements		 * ioperm() in user level (such as Alpha PCs).		 */	case KDADDIO:	case KDDELIO:		/*		 * KDADDIO and KDDELIO may be able to add ports beyond what		 * we reject here, but to be safe...		 */		if (arg < GPFIRST || arg > GPLAST)			return -EINVAL;		return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;	case KDENABIO:	case KDDISABIO:		return sys_ioperm(GPFIRST, GPNUM,				  (cmd == KDENABIO)) ? -ENXIO : 0;#endif	case KDSETMODE:		/*		 * currently, setting the mode from KD_TEXT to KD_GRAPHICS		 * doesn't do a whole lot. i'm not sure if it should do any		 * restoration of modes or what...		 */		if (!perm)			return -EPERM;		switch (arg) {		case KD_GRAPHICS:			break;		case KD_TEXT0:		case KD_TEXT1:			arg = KD_TEXT;		case KD_TEXT:			break;		default:			return -EINVAL;		}		if (vt_cons[console]->vc_mode == (unsigned char) arg)			return 0;		vt_cons[console]->vc_mode = (unsigned char) arg;		if (console != fg_console)			return 0;		/*		 * explicitly blank/unblank the screen if switching modes		 */		if (arg == KD_TEXT)			unblank_screen();		else			do_blank_screen(1);		return 0;	case KDGETMODE:		ucval = vt_cons[console]->vc_mode;		goto setint;	case KDMAPDISP:	case KDUNMAPDISP:		/*		 * these work like a combination of mmap and KDENABIO.		 * this could be easily finished.		 */		return -EINVAL;	case KDSKBMODE:		if (!perm)			return -EPERM;		switch(arg) {		  case K_RAW:			kbd->kbdmode = VC_RAW;			break;		  case K_MEDIUMRAW:			kbd->kbdmode = VC_MEDIUMRAW;			break;		  case K_XLATE:			kbd->kbdmode = VC_XLATE;			compute_shiftstate();			break;		  case K_UNICODE:			kbd->kbdmode = VC_UNICODE;			compute_shiftstate();			break;		  default:			return -EINVAL;		}		if (tty->ldisc.flush_buffer)			tty->ldisc.flush_buffer(tty);		return 0;	case KDGKBMODE:		ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :				 (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :				 (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :				 K_XLATE);		goto setint;	/* this could be folded into KDSKBMODE, but for compatibility	   reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */	case KDSKBMETA:		switch(arg) {		  case K_METABIT:			clr_vc_kbd_mode(kbd, VC_META);			break;		  case K_ESCPREFIX:			set_vc_kbd_mode(kbd, VC_META);			break;		  default:			return -EINVAL;		}		return 0;	case KDGKBMETA:		ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT);	setint:		return put_user(ucval, (int *)arg); 	case KDGETKEYCODE:	case KDSETKEYCODE:		return do_kbkeycode_ioctl(cmd, (struct kbkeycode *)arg, perm);	case KDGKBENT:	case KDSKBENT:		return do_kdsk_ioctl(cmd, (struct kbentry *)arg, perm, kbd);	case KDGKBSENT:	case KDSKBSENT:		return do_kdgkb_ioctl(cmd, (struct kbsentry *)arg, perm);	case KDGKBDIACR:	{		struct kbdiacrs *a = (struct kbdiacrs *)arg;		if (put_user(accent_table_size, &a->kb_cnt))			return -EFAULT;		if (copy_to_user(a->kbdiacr, accent_table, accent_table_size*sizeof(struct kbdiacr)))			return -EFAULT;		return 0;	}	case KDSKBDIACR:	{		struct kbdiacrs *a = (struct kbdiacrs *)arg;		unsigned int ct;		if (!perm)			return -EPERM;		if (get_user(ct,&a->kb_cnt))			return -EFAULT;		if (ct >= MAX_DIACR)			return -EINVAL;		accent_table_size = ct;		if (copy_from_user(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr)))			return -EFAULT;		return 0;	}	/* the ioctls below read/set the flags usually shown in the leds */	/* don't use them - they will go away without warning */	case KDGKBLED:		ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4);		goto setchar;	case KDSKBLED:		if (!perm)			return -EPERM;		if (arg & ~0x77)			return -EINVAL;		kbd->ledflagstate = (arg & 7);		kbd->default_ledflagstate = ((arg >> 4) & 7);		set_leds();		return 0;	/* the ioctls below only set the lights, not the functions */	/* for those, see KDGKBLED and KDSKBLED above */	case KDGETLED:		ucval = getledstate();	setchar:		return put_user(ucval, (char*)arg);	case KDSETLED:		if (!perm)		  return -EPERM;		setledstate(kbd, arg);		return 0;	/*	 * A process can indicate its willingness to accept signals	 * generated by pressing an appropriate key combination.	 * Thus, one can have a daemon that e.g. spawns a new console	 * upon a keypress and then changes to it.	 * Probably init should be changed to do this (and have a	 * field ks (`keyboard signal') in inittab describing the	 * desired action), so that the number of background daemons	 * does not increase.	 */	case KDSIGACCEPT:	{		extern int spawnpid, spawnsig;		if (!perm)		  return -EPERM;		if (arg < 1 || arg > _NSIG || arg == SIGKILL)		  return -EINVAL;		spawnpid = current->pid;		spawnsig = arg;		return 0;	}	case VT_SETMODE:	{		struct vt_mode tmp;		if (!perm)			return -EPERM;		if (copy_from_user(&tmp, (void*)arg, sizeof(struct vt_mode)))			return -EFAULT;		if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS)			return -EINVAL;		vt_cons[console]->vt_mode = tmp;		/* the frsig is ignored, so we set it to 0 */		vt_cons[console]->vt_mode.frsig = 0;		vt_cons[console]->vt_pid = current->pid;		/* no switch is required -- saw@shade.msu.ru */		vt_cons[console]->vt_newvt = -1; 		return 0;	}	case VT_GETMODE:		return copy_to_user((void*)arg, &(vt_cons[console]->vt_mode), 							sizeof(struct vt_mode)) ? -EFAULT : 0; 	/*	 * Returns global vt state. Note that VT 0 is always open, since	 * it's an alias for the current VT, and people can't use it here.	 * We cannot return state for more than 16 VTs, since v_state is short.	 */	case VT_GETSTATE:	{		struct vt_stat *vtstat = (struct vt_stat *)arg;		unsigned short state, mask;		i = verify_area(VERIFY_WRITE,(void *)vtstat, sizeof(struct vt_stat));		if (i)			return i;		put_user(fg_console + 1, &vtstat->v_active);		state = 1;	/* /dev/tty0 is always open */		for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)			if (VT_IS_IN_USE(i))				state |= mask;		return put_user(state, &vtstat->v_state);	}	/*	 * Returns the first available (non-opened) console.	 */	case VT_OPENQRY:		for (i = 0; i < MAX_NR_CONSOLES; ++i)			if (! VT_IS_IN_USE(i))				break;		ucval = i < MAX_NR_CONSOLES ? (i+1) : -1;		goto setint;		 	/*	 * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,	 * with num >= 1 (switches to vt 0, our console, are not allowed, just	 * to preserve sanity).	 */	case VT_ACTIVATE:		if (!perm)			return -EPERM;		if (arg == 0 || arg > MAX_NR_CONSOLES)			return -ENXIO;		arg--;		i = vc_allocate(arg);		if (i)			return i;		set_console(arg);		return 0;	/*	 * wait until the specified VT has been activated	 */	case VT_WAITACTIVE:		if (!perm)			return -EPERM;		if (arg == 0 || arg > MAX_NR_CONSOLES)			return -ENXIO;		return vt_waitactive(arg-1);	/*	 * If a vt is under process control, the kernel will not switch to it	 * immediately, but postpone the operation until the process calls this	 * ioctl, allowing the switch to complete.	 *	 * According to the X sources this is the behavior:	 *	0:	pending switch-from not OK	 *	1:	pending switch-from OK	 *	2:	completed switch-to OK	 */	case VT_RELDISP:		if (!perm)			return -EPERM;		if (vt_cons[console]->vt_mode.mode != VT_PROCESS)			return -EINVAL;		/*		 * Switching-from response		 */		if (vt_cons[console]->vt_newvt >= 0)		{			if (arg == 0)				/*				 * Switch disallowed, so forget we were trying				 * to do it.				 */				vt_cons[console]->vt_newvt = -1;			else			{				/*				 * The current vt has been released, so				 * complete the switch.				 */				int newvt = vt_cons[console]->vt_newvt;				vt_cons[console]->vt_newvt = -1;				i = vc_allocate(newvt);				if (i)					return i;				/*				 * When we actually do the console switch,				 * make sure we are atomic with respect to				 * other console switches..				 */				start_bh_atomic();				complete_change_console(newvt);				end_bh_atomic();			}		}		/*		 * Switched-to response		 */		else		{			/*			 * If it's just an ACK, ignore it			 */			if (arg != VT_ACKACQ)				return -EINVAL;		}		return 0;	 /*	  * Disallocate memory associated to VT (but leave VT1)	  */	 case VT_DISALLOCATE:		if (arg > MAX_NR_CONSOLES)			return -ENXIO;		if (arg == 0) {		    /* disallocate all unused consoles, but leave 0 */		    for (i=1; i<MAX_NR_CONSOLES; i++)		      if (! VT_BUSY(i))			vc_disallocate(i);		} else {		    /* disallocate a single console, if possible */		    arg--;		    if (VT_BUSY(arg))		      return -EBUSY;		    if (arg)			      /* leave 0 */		      vc_disallocate(arg);		}		return 0;	case VT_RESIZE:	{		struct vt_sizes *vtsizes = (struct vt_sizes *) arg;		ushort ll,cc;		if (!perm)			return -EPERM;		i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));		if (i)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -