/* * streamable.c: streamable devices. /dev/gfx * (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx) * * Major 10 is the streams clone device. The IRIX Xsgi server just * opens /dev/gfx and closes it inmediately. * * $Id$ */ #include #include #include #include #include #include #include #include #include #include "graphics.h" extern struct kbd_struct kbd_table [MAX_NR_CONSOLES]; /* console number where forwarding is enabled */ int forward_chars; /* To which shmiq this keyboard is assigned */ int kbd_assigned_device; /* previous kbd_mode for the forward_chars terminal */ int kbd_prev_mode; /* Fetchs the strioctl information from user space for I_STR ioctls */ int get_sioc (struct strioctl *sioc, unsigned long arg) { int v; v = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct strioctl)); if (v) return v; if (copy_from_user (sioc, (void *) arg, sizeof (struct strioctl))) return -EFAULT; v = verify_area (VERIFY_WRITE, (void *) sioc->ic_dp, sioc->ic_len); if (v) return v; return 0; } /* /dev/gfx device */ static int sgi_gfx_open (struct inode *inode, struct file *file) { printk ("GFX: Opened by %d\n", current->pid); return 0; } static int sgi_gfx_close (struct inode *inode, struct file *file) { printk ("GFX: Closed by %d\n", current->pid); return 0; } static int sgi_gfx_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { printk ("GFX: ioctl 0x%x %ld called\n", cmd, arg); return 0; return -EINVAL; } struct file_operations sgi_gfx_fops = { NULL, /* llseek */ NULL, /* read */ NULL, /* write */ NULL, /* readdir */ NULL, /* poll */ sgi_gfx_ioctl, /* ioctl */ NULL, /* mmap */ sgi_gfx_open, /* open */ sgi_gfx_close, /* release */ NULL, /* fsync */ NULL, /* check_media_change */ NULL, /* revalidate */ NULL /* lock */ }; static struct miscdevice dev_gfx = { SGI_GFX_MINOR, "sgi-gfx", &sgi_gfx_fops }; /* /dev/input/keyboard streams device */ static idevDesc sgi_kbd_desc = { "keyboard", /* devName */ "KEYBOARD", /* devType */ 240, /* nButtons */ 0, /* nValuators */ 0, /* nLEDs */ 0, /* nStrDpys */ 0, /* nIntDpys */ 0, /* nBells */ IDEV_HAS_KEYMAP | IDEV_HAS_PCKBD }; static int sgi_kbd_sioc (idevInfo *dinfo, int cmd, int size, char *data, int *found) { *found = 1; switch (cmd){ case IDEVINITDEVICE: return 0; case IDEVGETDEVICEDESC: if (size >= sizeof (idevDesc)){ if (copy_to_user (data, &sgi_kbd_desc, sizeof (sgi_kbd_desc))) return -EFAULT; return 0; } return -EINVAL; case IDEVGETKEYMAPDESC: if (size >= sizeof (idevKeymapDesc)){ if (copy_to_user (data, "US", 3)) return -EFAULT; return 0; } return -EINVAL; } *found = 0; return -EINVAL; } static int sgi_keyb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct strioctl sioc; int f, v; /* IRIX calls I_PUSH on the opened device, go figure */ if (cmd == I_PUSH) return 0; if (cmd == I_STR){ v = get_sioc (&sioc, arg); if (v) return v; /* Why like this? Because this is a sample piece of code * that can be copied into other drivers and shows how to * call a stock IRIX xxx_wioctl routine * * The NULL is supposed to be a idevInfo, right now we * do not support this in our kernel. */ return sgi_kbd_sioc (NULL, sioc.ic_cmd, sioc.ic_len, sioc.ic_dp, &f); } if (cmd == SHMIQ_ON){ kbd_assigned_device = arg; forward_chars = fg_console + 1; kbd_prev_mode = kbd_table [fg_console].kbdmode; kbd_table [fg_console].kbdmode = VC_RAW; } else if (cmd == SHMIQ_OFF && forward_chars){ kbd_table [forward_chars-1].kbdmode = kbd_prev_mode; forward_chars = 0; } else return -EINVAL; return 0; } void kbd_forward_char (int ch) { static struct shmqevent ev; ev.data.flags = (ch & 0200) ? 0 : 1; ev.data.which = ch; ev.data.device = kbd_assigned_device + 0x11; shmiq_push_event (&ev); } static int sgi_keyb_open (struct inode *inode, struct file *file) { /* Nothing, but required by the misc driver */ return 0; } struct file_operations sgi_keyb_fops = { NULL, /* llseek */ NULL, /* read */ NULL, /* write */ NULL, /* readdir */ NULL, /* poll */ sgi_keyb_ioctl, /* ioctl */ NULL, /* mmap */ sgi_keyb_open, /* open */ NULL, /* release */ NULL, /* fsync */ NULL, /* check_media_change */ NULL, /* revalidate */ NULL /* lock */ }; static struct miscdevice dev_input_keyboard = { SGI_STREAMS_KEYBOARD, "streams-keyboard", &sgi_keyb_fops }; /* /dev/input/mouse streams device */ #define MOUSE_VALUATORS 2 static idevDesc sgi_mouse_desc = { "mouse", /* devName */ "MOUSE", /* devType */ 3, /* nButtons */ MOUSE_VALUATORS, /* nValuators */ 0, /* nLEDs */ 0, /* nStrDpys */ 0, /* nIntDpys */ 0, /* nBells */ 0 /* flags */ }; static idevValuatorDesc mouse_default_valuator = { 200, /* hwMinRes */ 200, /* hwMaxRes */ 0, /* hwMinVal */ 65000, /* hwMaxVal */ IDEV_EITHER, /* possibleModes */ IDEV_ABSOLUTE, /* default mode */ 200, /* resolution */ 0, /* minVal */ 65000 /* maxVal */ }; static int mouse_opened; static idevValuatorDesc mouse_valuators [MOUSE_VALUATORS]; int sgi_mouse_open (struct inode *inode, struct file *file) { int i; if (mouse_opened) return -EBUSY; mouse_opened = 1; for (i = 0; i < MOUSE_VALUATORS; i++) mouse_valuators [i] = mouse_default_valuator; return 0; } static int sgi_mouse_close (struct inode *inode, struct file *filp) { mouse_opened = 0; return 0; } static int sgi_mouse_sioc (idevInfo *dinfo, int cmd, int size, char *data, int *found) { *found = 1; switch (cmd){ case IDEVINITDEVICE: return 0; case IDEVGETDEVICEDESC: if (size >= sizeof (idevDesc)){ if (copy_to_user (data, &sgi_mouse_desc, sizeof (sgi_mouse_desc))) return -EFAULT; return 0; } return -EINVAL; case IDEVGETVALUATORDESC: { idevGetSetValDesc request, *ureq = (idevGetSetValDesc *) data; if (size < sizeof (idevGetSetValDesc)) return -EINVAL; if (copy_from_user (&request, data, sizeof (request))) return -EFAULT; if (request.valNum >= MOUSE_VALUATORS) return -EINVAL; if (copy_to_user ((void *)&ureq->desc, (void *)&mouse_valuators [request.valNum], sizeof (idevValuatorDesc))) return -EFAULT; return 0; } } *found = 0; return -EINVAL; } static int sgi_mouse_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct strioctl sioc; int f, v; /* IRIX calls I_PUSH on the opened device, go figure */ switch (cmd){ case I_PUSH: return 0; case I_STR: v = get_sioc (&sioc, arg); if (v) return v; /* Why like this? Because this is a sample piece of code * that can be copied into other drivers and shows how to * call a stock IRIX xxx_wioctl routine * * The NULL is supposed to be a idevInfo, right now we * do not support this in our kernel. */ return sgi_mouse_sioc (NULL, sioc.ic_cmd, sioc.ic_len, sioc.ic_dp, &f); case SHMIQ_ON: case SHMIQ_OFF: return 0; } return 0; } struct file_operations sgi_mouse_fops = { NULL, /* llseek */ NULL, /* read */ NULL, /* write */ NULL, /* readdir */ NULL, /* poll */ sgi_mouse_ioctl, /* ioctl */ NULL, /* mmap */ sgi_mouse_open, /* open */ sgi_mouse_close, /* release */ NULL, /* fsync */ NULL, /* check_media_change */ NULL, /* revalidate */ NULL /* lock */ }; /* /dev/input/mouse */ static struct miscdevice dev_input_mouse = { SGI_STREAMS_KEYBOARD, "streams-mouse", &sgi_mouse_fops }; __initfunc(void streamable_init (void)) { printk ("streamable misc devices registered (keyb:%d, gfx:%d)\n", SGI_STREAMS_KEYBOARD, SGI_GFX_MINOR); misc_register (&dev_gfx); misc_register (&dev_input_keyboard); misc_register (&dev_input_mouse); }