Loading Documentation/kernel-parameters.txt +1 −1 Original line number Diff line number Diff line Loading @@ -1115,7 +1115,7 @@ running once the system is up. See Documentation/ramdisk.txt. psmouse.proto= [HW,MOUSE] Highest PS2 mouse protocol extension to probe for (bare|imps|exps). probe for (bare|imps|exps|lifebook|any). psmouse.rate= [HW,MOUSE] Set desired mouse report rate, in reports per second. psmouse.resetafter= Loading drivers/input/evdev.c +327 −80 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <linux/smp_lock.h> #include <linux/device.h> #include <linux/devfs_fs_kernel.h> #include <linux/compat.h> struct evdev { int exist; Loading Loading @@ -145,6 +146,41 @@ static int evdev_open(struct inode * inode, struct file * file) return 0; } #ifdef CONFIG_COMPAT struct input_event_compat { struct compat_timeval time; __u16 type; __u16 code; __s32 value; }; #ifdef CONFIG_X86_64 # define COMPAT_TEST test_thread_flag(TIF_IA32) #elif defined(CONFIG_IA64) # define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current)) #elif defined(CONFIG_ARCH_S390) # define COMPAT_TEST test_thread_flag(TIF_31BIT) #else # define COMPAT_TEST test_thread_flag(TIF_32BIT) #endif static ssize_t evdev_write_compat(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) { struct evdev_list *list = file->private_data; struct input_event_compat event; int retval = 0; while (retval < count) { if (copy_from_user(&event, buffer + retval, sizeof(struct input_event_compat))) return -EFAULT; input_event(list->evdev->handle.dev, event.type, event.code, event.value); retval += sizeof(struct input_event_compat); } return retval; } #endif static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) { struct evdev_list *list = file->private_data; Loading @@ -153,6 +189,11 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_ if (!list->evdev->exist) return -ENODEV; #ifdef CONFIG_COMPAT if (COMPAT_TEST) return evdev_write_compat(file, buffer, count, ppos); #endif while (retval < count) { if (copy_from_user(&event, buffer + retval, sizeof(struct input_event))) Loading @@ -164,11 +205,56 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_ return retval; } #ifdef CONFIG_COMPAT static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_t count, loff_t *ppos) { struct evdev_list *list = file->private_data; int retval; if (count < sizeof(struct input_event_compat)) return -EINVAL; if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK)) return -EAGAIN; retval = wait_event_interruptible(list->evdev->wait, list->head != list->tail || (!list->evdev->exist)); if (retval) return retval; if (!list->evdev->exist) return -ENODEV; while (list->head != list->tail && retval + sizeof(struct input_event_compat) <= count) { struct input_event *event = (struct input_event *) list->buffer + list->tail; struct input_event_compat event_compat; event_compat.time.tv_sec = event->time.tv_sec; event_compat.time.tv_usec = event->time.tv_usec; event_compat.type = event->type; event_compat.code = event->code; event_compat.value = event->value; if (copy_to_user(buffer + retval, &event_compat, sizeof(struct input_event_compat))) return -EFAULT; list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); retval += sizeof(struct input_event_compat); } return retval; } #endif static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) { struct evdev_list *list = file->private_data; int retval; #ifdef CONFIG_COMPAT if (COMPAT_TEST) return evdev_read_compat(file, buffer, count, ppos); #endif if (count < sizeof(struct input_event)) return -EINVAL; Loading Loading @@ -203,7 +289,7 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait) (list->evdev->exist ? 0 : (POLLHUP | POLLERR)); } static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct evdev_list *list = file->private_data; struct evdev *evdev = list->evdev; Loading Loading @@ -285,9 +371,11 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, default: if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ) if (_IOC_TYPE(cmd) != 'E') return -EINVAL; if (_IOC_DIR(cmd) == _IOC_READ) { if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { long *bits; Loading Loading @@ -370,6 +458,160 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return 0; } } if (_IOC_DIR(cmd) == _IOC_WRITE) { if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { int t = _IOC_NR(cmd) & ABS_MAX; if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) return -EFAULT; dev->abs[t] = abs.value; dev->absmin[t] = abs.minimum; dev->absmax[t] = abs.maximum; dev->absfuzz[t] = abs.fuzz; dev->absflat[t] = abs.flat; return 0; } } } return -EINVAL; } #ifdef CONFIG_COMPAT #define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8) #define NBITS_COMPAT(x) ((((x)-1)/BITS_PER_LONG_COMPAT)+1) #define OFF_COMPAT(x) ((x)%BITS_PER_LONG_COMPAT) #define BIT_COMPAT(x) (1UL<<OFF_COMPAT(x)) #define LONG_COMPAT(x) ((x)/BITS_PER_LONG_COMPAT) #define test_bit_compat(bit, array) ((array[LONG_COMPAT(bit)] >> OFF_COMPAT(bit)) & 1) #ifdef __BIG_ENDIAN #define bit_to_user(bit, max) \ do { \ int i; \ int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ for (i = 0; i < len / sizeof(compat_long_t); i++) \ if (copy_to_user((compat_long_t*) p + i, \ (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \ sizeof(compat_long_t))) \ return -EFAULT; \ return len; \ } while (0) #else #define bit_to_user(bit, max) \ do { \ int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ return copy_to_user(p, (bit), len) ? -EFAULT : len; \ } while (0) #endif static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) { struct evdev_list *list = file->private_data; struct evdev *evdev = list->evdev; struct input_dev *dev = evdev->handle.dev; struct input_absinfo abs; void __user *p = compat_ptr(arg); if (!evdev->exist) return -ENODEV; switch (cmd) { case EVIOCGVERSION: case EVIOCGID: case EVIOCGKEYCODE: case EVIOCSKEYCODE: case EVIOCSFF: case EVIOCRMFF: case EVIOCGEFFECTS: case EVIOCGRAB: return evdev_ioctl(file, cmd, (unsigned long) p); default: if (_IOC_TYPE(cmd) != 'E') return -EINVAL; if (_IOC_DIR(cmd) == _IOC_READ) { if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { long *bits; int max; switch (_IOC_NR(cmd) & EV_MAX) { case 0: bits = dev->evbit; max = EV_MAX; break; case EV_KEY: bits = dev->keybit; max = KEY_MAX; break; case EV_REL: bits = dev->relbit; max = REL_MAX; break; case EV_ABS: bits = dev->absbit; max = ABS_MAX; break; case EV_MSC: bits = dev->mscbit; max = MSC_MAX; break; case EV_LED: bits = dev->ledbit; max = LED_MAX; break; case EV_SND: bits = dev->sndbit; max = SND_MAX; break; case EV_FF: bits = dev->ffbit; max = FF_MAX; break; default: return -EINVAL; } bit_to_user(bits, max); } if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) bit_to_user(dev->key, KEY_MAX); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) bit_to_user(dev->led, LED_MAX); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) bit_to_user(dev->snd, SND_MAX); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { int len; if (!dev->name) return -ENOENT; len = strlen(dev->name) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); return copy_to_user(p, dev->name, len) ? -EFAULT : len; } if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { int len; if (!dev->phys) return -ENOENT; len = strlen(dev->phys) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); return copy_to_user(p, dev->phys, len) ? -EFAULT : len; } if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { int len; if (!dev->uniq) return -ENOENT; len = strlen(dev->uniq) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; } if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { int t = _IOC_NR(cmd) & ABS_MAX; abs.value = dev->abs[t]; abs.minimum = dev->absmin[t]; abs.maximum = dev->absmax[t]; abs.fuzz = dev->absfuzz[t]; abs.flat = dev->absflat[t]; if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) return -EFAULT; return 0; } } if (_IOC_DIR(cmd) == _IOC_WRITE) { if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { int t = _IOC_NR(cmd) & ABS_MAX; Loading @@ -386,8 +628,10 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return 0; } } } return -EINVAL; } #endif static struct file_operations evdev_fops = { .owner = THIS_MODULE, Loading @@ -396,7 +640,10 @@ static struct file_operations evdev_fops = { .poll = evdev_poll, .open = evdev_open, .release = evdev_release, .ioctl = evdev_ioctl, .unlocked_ioctl = evdev_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = evdev_ioctl_compat, #endif .fasync = evdev_fasync, .flush = evdev_flush }; Loading drivers/input/gameport/Kconfig +0 −14 Original line number Diff line number Diff line Loading @@ -49,22 +49,8 @@ config GAMEPORT_EMU10K1 To compile this driver as a module, choose M here: the module will be called emu10k1-gp. config GAMEPORT_VORTEX tristate "Aureal Vortex, Vortex 2 gameport support" depends on PCI help Say Y here if you have an Aureal Vortex 1 or 2 card and want to use its gameport. To compile this driver as a module, choose M here: the module will be called vortex. config GAMEPORT_FM801 tristate "ForteMedia FM801 gameport support" depends on PCI config GAMEPORT_CS461X tristate "Crystal SoundFusion gameport support" depends on PCI endif drivers/input/gameport/Makefile +0 −2 Original line number Diff line number Diff line Loading @@ -5,9 +5,7 @@ # Each configuration option enables a list of files. obj-$(CONFIG_GAMEPORT) += gameport.o obj-$(CONFIG_GAMEPORT_CS461X) += cs461x.o obj-$(CONFIG_GAMEPORT_EMU10K1) += emu10k1-gp.o obj-$(CONFIG_GAMEPORT_FM801) += fm801-gp.o obj-$(CONFIG_GAMEPORT_L4) += lightning.o obj-$(CONFIG_GAMEPORT_NS558) += ns558.o obj-$(CONFIG_GAMEPORT_VORTEX) += vortex.o drivers/input/gameport/cs461x.cdeleted 100644 → 0 +0 −322 Original line number Diff line number Diff line /* The all defines and part of code (such as cs461x_*) are contributed from ALSA 0.5.8 sources. See http://www.alsa-project.org/ for sources Tested on Linux 686 2.4.0-test9, ALSA 0.5.8a and CS4610 */ #include <asm/io.h> #include <linux/module.h> #include <linux/ioport.h> #include <linux/config.h> #include <linux/init.h> #include <linux/gameport.h> #include <linux/slab.h> #include <linux/pci.h> MODULE_AUTHOR("Victor Krapivin"); MODULE_LICENSE("GPL"); /* These options are experimental #define CS461X_FULL_MAP */ #ifndef PCI_VENDOR_ID_CIRRUS #define PCI_VENDOR_ID_CIRRUS 0x1013 #endif #ifndef PCI_DEVICE_ID_CIRRUS_4610 #define PCI_DEVICE_ID_CIRRUS_4610 0x6001 #endif #ifndef PCI_DEVICE_ID_CIRRUS_4612 #define PCI_DEVICE_ID_CIRRUS_4612 0x6003 #endif #ifndef PCI_DEVICE_ID_CIRRUS_4615 #define PCI_DEVICE_ID_CIRRUS_4615 0x6004 #endif /* Registers */ #define BA0_JSPT 0x00000480 #define BA0_JSCTL 0x00000484 #define BA0_JSC1 0x00000488 #define BA0_JSC2 0x0000048C #define BA0_JSIO 0x000004A0 /* Bits for JSPT */ #define JSPT_CAX 0x00000001 #define JSPT_CAY 0x00000002 #define JSPT_CBX 0x00000004 #define JSPT_CBY 0x00000008 #define JSPT_BA1 0x00000010 #define JSPT_BA2 0x00000020 #define JSPT_BB1 0x00000040 #define JSPT_BB2 0x00000080 /* Bits for JSCTL */ #define JSCTL_SP_MASK 0x00000003 #define JSCTL_SP_SLOW 0x00000000 #define JSCTL_SP_MEDIUM_SLOW 0x00000001 #define JSCTL_SP_MEDIUM_FAST 0x00000002 #define JSCTL_SP_FAST 0x00000003 #define JSCTL_ARE 0x00000004 /* Data register pairs masks */ #define JSC1_Y1V_MASK 0x0000FFFF #define JSC1_X1V_MASK 0xFFFF0000 #define JSC1_Y1V_SHIFT 0 #define JSC1_X1V_SHIFT 16 #define JSC2_Y2V_MASK 0x0000FFFF #define JSC2_X2V_MASK 0xFFFF0000 #define JSC2_Y2V_SHIFT 0 #define JSC2_X2V_SHIFT 16 /* JS GPIO */ #define JSIO_DAX 0x00000001 #define JSIO_DAY 0x00000002 #define JSIO_DBX 0x00000004 #define JSIO_DBY 0x00000008 #define JSIO_AXOE 0x00000010 #define JSIO_AYOE 0x00000020 #define JSIO_BXOE 0x00000040 #define JSIO_BYOE 0x00000080 /* The card initialization code is obfuscated; the module cs461x need to be loaded after ALSA modules initialized and something played on the CS 4610 chip (see sources for details of CS4610 initialization code from ALSA) */ /* Card specific definitions */ #define CS461X_BA0_SIZE 0x2000 #define CS461X_BA1_DATA0_SIZE 0x3000 #define CS461X_BA1_DATA1_SIZE 0x3800 #define CS461X_BA1_PRG_SIZE 0x7000 #define CS461X_BA1_REG_SIZE 0x0100 #define BA1_SP_DMEM0 0x00000000 #define BA1_SP_DMEM1 0x00010000 #define BA1_SP_PMEM 0x00020000 #define BA1_SP_REG 0x00030000 #define BA1_DWORD_SIZE (13 * 1024 + 512) #define BA1_MEMORY_COUNT 3 /* Only one CS461x card is still suppoted; the code requires redesign to avoid this limitatuion. */ static unsigned long ba0_addr; static unsigned int __iomem *ba0; #ifdef CS461X_FULL_MAP static unsigned long ba1_addr; static union ba1_t { struct { unsigned int __iomem *data0; unsigned int __iomem *data1; unsigned int __iomem *pmem; unsigned int __iomem *reg; } name; unsigned int __iomem *idx[4]; } ba1; static void cs461x_poke(unsigned long reg, unsigned int val) { writel(val, &ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]); } static unsigned int cs461x_peek(unsigned long reg) { return readl(&ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]); } #endif static void cs461x_pokeBA0(unsigned long reg, unsigned int val) { writel(val, &ba0[reg >> 2]); } static unsigned int cs461x_peekBA0(unsigned long reg) { return readl(&ba0[reg >> 2]); } static int cs461x_free(struct pci_dev *pdev) { struct gameport *port = pci_get_drvdata(pdev); if (port) gameport_unregister_port(port); if (ba0) iounmap(ba0); #ifdef CS461X_FULL_MAP if (ba1.name.data0) iounmap(ba1.name.data0); if (ba1.name.data1) iounmap(ba1.name.data1); if (ba1.name.pmem) iounmap(ba1.name.pmem); if (ba1.name.reg) iounmap(ba1.name.reg); #endif return 0; } static void cs461x_gameport_trigger(struct gameport *gameport) { cs461x_pokeBA0(BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF); } static unsigned char cs461x_gameport_read(struct gameport *gameport) { return cs461x_peekBA0(BA0_JSPT); //inb(gameport->io); } static int cs461x_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons) { unsigned js1, js2, jst; js1 = cs461x_peekBA0(BA0_JSC1); js2 = cs461x_peekBA0(BA0_JSC2); jst = cs461x_peekBA0(BA0_JSPT); *buttons = (~jst >> 4) & 0x0F; axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF; axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF; axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF; axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF; for(jst=0;jst<4;++jst) if(axes[jst]==0xFFFF) axes[jst] = -1; return 0; } static int cs461x_gameport_open(struct gameport *gameport, int mode) { switch (mode) { case GAMEPORT_MODE_COOKED: case GAMEPORT_MODE_RAW: return 0; default: return -1; } return 0; } static struct pci_device_id cs461x_pci_tbl[] = { { PCI_VENDOR_ID_CIRRUS, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4610 */ { PCI_VENDOR_ID_CIRRUS, 0x6003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4612 */ { PCI_VENDOR_ID_CIRRUS, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4615 */ { 0, } }; MODULE_DEVICE_TABLE(pci, cs461x_pci_tbl); static int __devinit cs461x_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int rc; struct gameport* port; rc = pci_enable_device(pdev); if (rc) { printk(KERN_ERR "cs461x: Cannot enable PCI gameport (bus %d, devfn %d) error=%d\n", pdev->bus->number, pdev->devfn, rc); return rc; } ba0_addr = pci_resource_start(pdev, 0); #ifdef CS461X_FULL_MAP ba1_addr = pci_resource_start(pdev, 1); #endif if (ba0_addr == 0 || ba0_addr == ~0 #ifdef CS461X_FULL_MAP || ba1_addr == 0 || ba1_addr == ~0 #endif ) { printk(KERN_ERR "cs461x: wrong address - ba0 = 0x%lx\n", ba0_addr); #ifdef CS461X_FULL_MAP printk(KERN_ERR "cs461x: wrong address - ba1 = 0x%lx\n", ba1_addr); #endif cs461x_free(pdev); return -ENOMEM; } ba0 = ioremap(ba0_addr, CS461X_BA0_SIZE); #ifdef CS461X_FULL_MAP ba1.name.data0 = ioremap(ba1_addr + BA1_SP_DMEM0, CS461X_BA1_DATA0_SIZE); ba1.name.data1 = ioremap(ba1_addr + BA1_SP_DMEM1, CS461X_BA1_DATA1_SIZE); ba1.name.pmem = ioremap(ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE); ba1.name.reg = ioremap(ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE); if (ba0 == NULL || ba1.name.data0 == NULL || ba1.name.data1 == NULL || ba1.name.pmem == NULL || ba1.name.reg == NULL) { cs461x_free(pdev); return -ENOMEM; } #else if (ba0 == NULL) { cs461x_free(pdev); return -ENOMEM; } #endif if (!(port = gameport_allocate_port())) { printk(KERN_ERR "cs461x: Memory allocation failed\n"); cs461x_free(pdev); return -ENOMEM; } pci_set_drvdata(pdev, port); port->open = cs461x_gameport_open; port->trigger = cs461x_gameport_trigger; port->read = cs461x_gameport_read; port->cooked_read = cs461x_gameport_cooked_read; gameport_set_name(port, "CS416x"); gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev)); port->dev.parent = &pdev->dev; cs461x_pokeBA0(BA0_JSIO, 0xFF); // ? cs461x_pokeBA0(BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW); gameport_register_port(port); return 0; } static void __devexit cs461x_pci_remove(struct pci_dev *pdev) { cs461x_free(pdev); } static struct pci_driver cs461x_pci_driver = { .name = "CS461x_gameport", .id_table = cs461x_pci_tbl, .probe = cs461x_pci_probe, .remove = __devexit_p(cs461x_pci_remove), }; static int __init cs461x_init(void) { return pci_register_driver(&cs461x_pci_driver); } static void __exit cs461x_exit(void) { pci_unregister_driver(&cs461x_pci_driver); } module_init(cs461x_init); module_exit(cs461x_exit); Loading
Documentation/kernel-parameters.txt +1 −1 Original line number Diff line number Diff line Loading @@ -1115,7 +1115,7 @@ running once the system is up. See Documentation/ramdisk.txt. psmouse.proto= [HW,MOUSE] Highest PS2 mouse protocol extension to probe for (bare|imps|exps). probe for (bare|imps|exps|lifebook|any). psmouse.rate= [HW,MOUSE] Set desired mouse report rate, in reports per second. psmouse.resetafter= Loading
drivers/input/evdev.c +327 −80 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <linux/smp_lock.h> #include <linux/device.h> #include <linux/devfs_fs_kernel.h> #include <linux/compat.h> struct evdev { int exist; Loading Loading @@ -145,6 +146,41 @@ static int evdev_open(struct inode * inode, struct file * file) return 0; } #ifdef CONFIG_COMPAT struct input_event_compat { struct compat_timeval time; __u16 type; __u16 code; __s32 value; }; #ifdef CONFIG_X86_64 # define COMPAT_TEST test_thread_flag(TIF_IA32) #elif defined(CONFIG_IA64) # define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current)) #elif defined(CONFIG_ARCH_S390) # define COMPAT_TEST test_thread_flag(TIF_31BIT) #else # define COMPAT_TEST test_thread_flag(TIF_32BIT) #endif static ssize_t evdev_write_compat(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) { struct evdev_list *list = file->private_data; struct input_event_compat event; int retval = 0; while (retval < count) { if (copy_from_user(&event, buffer + retval, sizeof(struct input_event_compat))) return -EFAULT; input_event(list->evdev->handle.dev, event.type, event.code, event.value); retval += sizeof(struct input_event_compat); } return retval; } #endif static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) { struct evdev_list *list = file->private_data; Loading @@ -153,6 +189,11 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_ if (!list->evdev->exist) return -ENODEV; #ifdef CONFIG_COMPAT if (COMPAT_TEST) return evdev_write_compat(file, buffer, count, ppos); #endif while (retval < count) { if (copy_from_user(&event, buffer + retval, sizeof(struct input_event))) Loading @@ -164,11 +205,56 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_ return retval; } #ifdef CONFIG_COMPAT static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_t count, loff_t *ppos) { struct evdev_list *list = file->private_data; int retval; if (count < sizeof(struct input_event_compat)) return -EINVAL; if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK)) return -EAGAIN; retval = wait_event_interruptible(list->evdev->wait, list->head != list->tail || (!list->evdev->exist)); if (retval) return retval; if (!list->evdev->exist) return -ENODEV; while (list->head != list->tail && retval + sizeof(struct input_event_compat) <= count) { struct input_event *event = (struct input_event *) list->buffer + list->tail; struct input_event_compat event_compat; event_compat.time.tv_sec = event->time.tv_sec; event_compat.time.tv_usec = event->time.tv_usec; event_compat.type = event->type; event_compat.code = event->code; event_compat.value = event->value; if (copy_to_user(buffer + retval, &event_compat, sizeof(struct input_event_compat))) return -EFAULT; list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); retval += sizeof(struct input_event_compat); } return retval; } #endif static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) { struct evdev_list *list = file->private_data; int retval; #ifdef CONFIG_COMPAT if (COMPAT_TEST) return evdev_read_compat(file, buffer, count, ppos); #endif if (count < sizeof(struct input_event)) return -EINVAL; Loading Loading @@ -203,7 +289,7 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait) (list->evdev->exist ? 0 : (POLLHUP | POLLERR)); } static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct evdev_list *list = file->private_data; struct evdev *evdev = list->evdev; Loading Loading @@ -285,9 +371,11 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, default: if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ) if (_IOC_TYPE(cmd) != 'E') return -EINVAL; if (_IOC_DIR(cmd) == _IOC_READ) { if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { long *bits; Loading Loading @@ -370,6 +458,160 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return 0; } } if (_IOC_DIR(cmd) == _IOC_WRITE) { if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { int t = _IOC_NR(cmd) & ABS_MAX; if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) return -EFAULT; dev->abs[t] = abs.value; dev->absmin[t] = abs.minimum; dev->absmax[t] = abs.maximum; dev->absfuzz[t] = abs.fuzz; dev->absflat[t] = abs.flat; return 0; } } } return -EINVAL; } #ifdef CONFIG_COMPAT #define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8) #define NBITS_COMPAT(x) ((((x)-1)/BITS_PER_LONG_COMPAT)+1) #define OFF_COMPAT(x) ((x)%BITS_PER_LONG_COMPAT) #define BIT_COMPAT(x) (1UL<<OFF_COMPAT(x)) #define LONG_COMPAT(x) ((x)/BITS_PER_LONG_COMPAT) #define test_bit_compat(bit, array) ((array[LONG_COMPAT(bit)] >> OFF_COMPAT(bit)) & 1) #ifdef __BIG_ENDIAN #define bit_to_user(bit, max) \ do { \ int i; \ int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ for (i = 0; i < len / sizeof(compat_long_t); i++) \ if (copy_to_user((compat_long_t*) p + i, \ (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \ sizeof(compat_long_t))) \ return -EFAULT; \ return len; \ } while (0) #else #define bit_to_user(bit, max) \ do { \ int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ return copy_to_user(p, (bit), len) ? -EFAULT : len; \ } while (0) #endif static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) { struct evdev_list *list = file->private_data; struct evdev *evdev = list->evdev; struct input_dev *dev = evdev->handle.dev; struct input_absinfo abs; void __user *p = compat_ptr(arg); if (!evdev->exist) return -ENODEV; switch (cmd) { case EVIOCGVERSION: case EVIOCGID: case EVIOCGKEYCODE: case EVIOCSKEYCODE: case EVIOCSFF: case EVIOCRMFF: case EVIOCGEFFECTS: case EVIOCGRAB: return evdev_ioctl(file, cmd, (unsigned long) p); default: if (_IOC_TYPE(cmd) != 'E') return -EINVAL; if (_IOC_DIR(cmd) == _IOC_READ) { if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { long *bits; int max; switch (_IOC_NR(cmd) & EV_MAX) { case 0: bits = dev->evbit; max = EV_MAX; break; case EV_KEY: bits = dev->keybit; max = KEY_MAX; break; case EV_REL: bits = dev->relbit; max = REL_MAX; break; case EV_ABS: bits = dev->absbit; max = ABS_MAX; break; case EV_MSC: bits = dev->mscbit; max = MSC_MAX; break; case EV_LED: bits = dev->ledbit; max = LED_MAX; break; case EV_SND: bits = dev->sndbit; max = SND_MAX; break; case EV_FF: bits = dev->ffbit; max = FF_MAX; break; default: return -EINVAL; } bit_to_user(bits, max); } if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) bit_to_user(dev->key, KEY_MAX); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) bit_to_user(dev->led, LED_MAX); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) bit_to_user(dev->snd, SND_MAX); if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { int len; if (!dev->name) return -ENOENT; len = strlen(dev->name) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); return copy_to_user(p, dev->name, len) ? -EFAULT : len; } if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { int len; if (!dev->phys) return -ENOENT; len = strlen(dev->phys) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); return copy_to_user(p, dev->phys, len) ? -EFAULT : len; } if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { int len; if (!dev->uniq) return -ENOENT; len = strlen(dev->uniq) + 1; if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; } if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { int t = _IOC_NR(cmd) & ABS_MAX; abs.value = dev->abs[t]; abs.minimum = dev->absmin[t]; abs.maximum = dev->absmax[t]; abs.fuzz = dev->absfuzz[t]; abs.flat = dev->absflat[t]; if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) return -EFAULT; return 0; } } if (_IOC_DIR(cmd) == _IOC_WRITE) { if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { int t = _IOC_NR(cmd) & ABS_MAX; Loading @@ -386,8 +628,10 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return 0; } } } return -EINVAL; } #endif static struct file_operations evdev_fops = { .owner = THIS_MODULE, Loading @@ -396,7 +640,10 @@ static struct file_operations evdev_fops = { .poll = evdev_poll, .open = evdev_open, .release = evdev_release, .ioctl = evdev_ioctl, .unlocked_ioctl = evdev_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = evdev_ioctl_compat, #endif .fasync = evdev_fasync, .flush = evdev_flush }; Loading
drivers/input/gameport/Kconfig +0 −14 Original line number Diff line number Diff line Loading @@ -49,22 +49,8 @@ config GAMEPORT_EMU10K1 To compile this driver as a module, choose M here: the module will be called emu10k1-gp. config GAMEPORT_VORTEX tristate "Aureal Vortex, Vortex 2 gameport support" depends on PCI help Say Y here if you have an Aureal Vortex 1 or 2 card and want to use its gameport. To compile this driver as a module, choose M here: the module will be called vortex. config GAMEPORT_FM801 tristate "ForteMedia FM801 gameport support" depends on PCI config GAMEPORT_CS461X tristate "Crystal SoundFusion gameport support" depends on PCI endif
drivers/input/gameport/Makefile +0 −2 Original line number Diff line number Diff line Loading @@ -5,9 +5,7 @@ # Each configuration option enables a list of files. obj-$(CONFIG_GAMEPORT) += gameport.o obj-$(CONFIG_GAMEPORT_CS461X) += cs461x.o obj-$(CONFIG_GAMEPORT_EMU10K1) += emu10k1-gp.o obj-$(CONFIG_GAMEPORT_FM801) += fm801-gp.o obj-$(CONFIG_GAMEPORT_L4) += lightning.o obj-$(CONFIG_GAMEPORT_NS558) += ns558.o obj-$(CONFIG_GAMEPORT_VORTEX) += vortex.o
drivers/input/gameport/cs461x.cdeleted 100644 → 0 +0 −322 Original line number Diff line number Diff line /* The all defines and part of code (such as cs461x_*) are contributed from ALSA 0.5.8 sources. See http://www.alsa-project.org/ for sources Tested on Linux 686 2.4.0-test9, ALSA 0.5.8a and CS4610 */ #include <asm/io.h> #include <linux/module.h> #include <linux/ioport.h> #include <linux/config.h> #include <linux/init.h> #include <linux/gameport.h> #include <linux/slab.h> #include <linux/pci.h> MODULE_AUTHOR("Victor Krapivin"); MODULE_LICENSE("GPL"); /* These options are experimental #define CS461X_FULL_MAP */ #ifndef PCI_VENDOR_ID_CIRRUS #define PCI_VENDOR_ID_CIRRUS 0x1013 #endif #ifndef PCI_DEVICE_ID_CIRRUS_4610 #define PCI_DEVICE_ID_CIRRUS_4610 0x6001 #endif #ifndef PCI_DEVICE_ID_CIRRUS_4612 #define PCI_DEVICE_ID_CIRRUS_4612 0x6003 #endif #ifndef PCI_DEVICE_ID_CIRRUS_4615 #define PCI_DEVICE_ID_CIRRUS_4615 0x6004 #endif /* Registers */ #define BA0_JSPT 0x00000480 #define BA0_JSCTL 0x00000484 #define BA0_JSC1 0x00000488 #define BA0_JSC2 0x0000048C #define BA0_JSIO 0x000004A0 /* Bits for JSPT */ #define JSPT_CAX 0x00000001 #define JSPT_CAY 0x00000002 #define JSPT_CBX 0x00000004 #define JSPT_CBY 0x00000008 #define JSPT_BA1 0x00000010 #define JSPT_BA2 0x00000020 #define JSPT_BB1 0x00000040 #define JSPT_BB2 0x00000080 /* Bits for JSCTL */ #define JSCTL_SP_MASK 0x00000003 #define JSCTL_SP_SLOW 0x00000000 #define JSCTL_SP_MEDIUM_SLOW 0x00000001 #define JSCTL_SP_MEDIUM_FAST 0x00000002 #define JSCTL_SP_FAST 0x00000003 #define JSCTL_ARE 0x00000004 /* Data register pairs masks */ #define JSC1_Y1V_MASK 0x0000FFFF #define JSC1_X1V_MASK 0xFFFF0000 #define JSC1_Y1V_SHIFT 0 #define JSC1_X1V_SHIFT 16 #define JSC2_Y2V_MASK 0x0000FFFF #define JSC2_X2V_MASK 0xFFFF0000 #define JSC2_Y2V_SHIFT 0 #define JSC2_X2V_SHIFT 16 /* JS GPIO */ #define JSIO_DAX 0x00000001 #define JSIO_DAY 0x00000002 #define JSIO_DBX 0x00000004 #define JSIO_DBY 0x00000008 #define JSIO_AXOE 0x00000010 #define JSIO_AYOE 0x00000020 #define JSIO_BXOE 0x00000040 #define JSIO_BYOE 0x00000080 /* The card initialization code is obfuscated; the module cs461x need to be loaded after ALSA modules initialized and something played on the CS 4610 chip (see sources for details of CS4610 initialization code from ALSA) */ /* Card specific definitions */ #define CS461X_BA0_SIZE 0x2000 #define CS461X_BA1_DATA0_SIZE 0x3000 #define CS461X_BA1_DATA1_SIZE 0x3800 #define CS461X_BA1_PRG_SIZE 0x7000 #define CS461X_BA1_REG_SIZE 0x0100 #define BA1_SP_DMEM0 0x00000000 #define BA1_SP_DMEM1 0x00010000 #define BA1_SP_PMEM 0x00020000 #define BA1_SP_REG 0x00030000 #define BA1_DWORD_SIZE (13 * 1024 + 512) #define BA1_MEMORY_COUNT 3 /* Only one CS461x card is still suppoted; the code requires redesign to avoid this limitatuion. */ static unsigned long ba0_addr; static unsigned int __iomem *ba0; #ifdef CS461X_FULL_MAP static unsigned long ba1_addr; static union ba1_t { struct { unsigned int __iomem *data0; unsigned int __iomem *data1; unsigned int __iomem *pmem; unsigned int __iomem *reg; } name; unsigned int __iomem *idx[4]; } ba1; static void cs461x_poke(unsigned long reg, unsigned int val) { writel(val, &ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]); } static unsigned int cs461x_peek(unsigned long reg) { return readl(&ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]); } #endif static void cs461x_pokeBA0(unsigned long reg, unsigned int val) { writel(val, &ba0[reg >> 2]); } static unsigned int cs461x_peekBA0(unsigned long reg) { return readl(&ba0[reg >> 2]); } static int cs461x_free(struct pci_dev *pdev) { struct gameport *port = pci_get_drvdata(pdev); if (port) gameport_unregister_port(port); if (ba0) iounmap(ba0); #ifdef CS461X_FULL_MAP if (ba1.name.data0) iounmap(ba1.name.data0); if (ba1.name.data1) iounmap(ba1.name.data1); if (ba1.name.pmem) iounmap(ba1.name.pmem); if (ba1.name.reg) iounmap(ba1.name.reg); #endif return 0; } static void cs461x_gameport_trigger(struct gameport *gameport) { cs461x_pokeBA0(BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF); } static unsigned char cs461x_gameport_read(struct gameport *gameport) { return cs461x_peekBA0(BA0_JSPT); //inb(gameport->io); } static int cs461x_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons) { unsigned js1, js2, jst; js1 = cs461x_peekBA0(BA0_JSC1); js2 = cs461x_peekBA0(BA0_JSC2); jst = cs461x_peekBA0(BA0_JSPT); *buttons = (~jst >> 4) & 0x0F; axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF; axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF; axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF; axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF; for(jst=0;jst<4;++jst) if(axes[jst]==0xFFFF) axes[jst] = -1; return 0; } static int cs461x_gameport_open(struct gameport *gameport, int mode) { switch (mode) { case GAMEPORT_MODE_COOKED: case GAMEPORT_MODE_RAW: return 0; default: return -1; } return 0; } static struct pci_device_id cs461x_pci_tbl[] = { { PCI_VENDOR_ID_CIRRUS, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4610 */ { PCI_VENDOR_ID_CIRRUS, 0x6003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4612 */ { PCI_VENDOR_ID_CIRRUS, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4615 */ { 0, } }; MODULE_DEVICE_TABLE(pci, cs461x_pci_tbl); static int __devinit cs461x_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int rc; struct gameport* port; rc = pci_enable_device(pdev); if (rc) { printk(KERN_ERR "cs461x: Cannot enable PCI gameport (bus %d, devfn %d) error=%d\n", pdev->bus->number, pdev->devfn, rc); return rc; } ba0_addr = pci_resource_start(pdev, 0); #ifdef CS461X_FULL_MAP ba1_addr = pci_resource_start(pdev, 1); #endif if (ba0_addr == 0 || ba0_addr == ~0 #ifdef CS461X_FULL_MAP || ba1_addr == 0 || ba1_addr == ~0 #endif ) { printk(KERN_ERR "cs461x: wrong address - ba0 = 0x%lx\n", ba0_addr); #ifdef CS461X_FULL_MAP printk(KERN_ERR "cs461x: wrong address - ba1 = 0x%lx\n", ba1_addr); #endif cs461x_free(pdev); return -ENOMEM; } ba0 = ioremap(ba0_addr, CS461X_BA0_SIZE); #ifdef CS461X_FULL_MAP ba1.name.data0 = ioremap(ba1_addr + BA1_SP_DMEM0, CS461X_BA1_DATA0_SIZE); ba1.name.data1 = ioremap(ba1_addr + BA1_SP_DMEM1, CS461X_BA1_DATA1_SIZE); ba1.name.pmem = ioremap(ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE); ba1.name.reg = ioremap(ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE); if (ba0 == NULL || ba1.name.data0 == NULL || ba1.name.data1 == NULL || ba1.name.pmem == NULL || ba1.name.reg == NULL) { cs461x_free(pdev); return -ENOMEM; } #else if (ba0 == NULL) { cs461x_free(pdev); return -ENOMEM; } #endif if (!(port = gameport_allocate_port())) { printk(KERN_ERR "cs461x: Memory allocation failed\n"); cs461x_free(pdev); return -ENOMEM; } pci_set_drvdata(pdev, port); port->open = cs461x_gameport_open; port->trigger = cs461x_gameport_trigger; port->read = cs461x_gameport_read; port->cooked_read = cs461x_gameport_cooked_read; gameport_set_name(port, "CS416x"); gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev)); port->dev.parent = &pdev->dev; cs461x_pokeBA0(BA0_JSIO, 0xFF); // ? cs461x_pokeBA0(BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW); gameport_register_port(port); return 0; } static void __devexit cs461x_pci_remove(struct pci_dev *pdev) { cs461x_free(pdev); } static struct pci_driver cs461x_pci_driver = { .name = "CS461x_gameport", .id_table = cs461x_pci_tbl, .probe = cs461x_pci_probe, .remove = __devexit_p(cs461x_pci_remove), }; static int __init cs461x_init(void) { return pci_register_driver(&cs461x_pci_driver); } static void __exit cs461x_exit(void) { pci_unregister_driver(&cs461x_pci_driver); } module_init(cs461x_init); module_exit(cs461x_exit);