struct input_handle handle;
wait_queue_head_t wait;
struct list_head list;
- struct js_corr corr[ABS_MAX];
+ struct js_corr corr[ABS_MAX + 1];
struct JS_DATA_SAVE_TYPE glue;
int nabs;
int nkey;
- __u16 keymap[KEY_MAX - BTN_MISC];
- __u16 keypam[KEY_MAX - BTN_MISC];
- __u8 absmap[ABS_MAX];
- __u8 abspam[ABS_MAX];
- __s16 abs[ABS_MAX];
+ __u16 keymap[KEY_MAX - BTN_MISC + 1];
+ __u16 keypam[KEY_MAX - BTN_MISC + 1];
+ __u8 absmap[ABS_MAX + 1];
+ __u8 abspam[ABS_MAX + 1];
+ __s16 abs[ABS_MAX + 1];
};
struct joydev_list {
{
struct joydev_list *list = file->private_data;
poll_wait(file, &list->joydev->wait, wait);
- if (list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey)
- return POLLIN | POLLRDNORM;
- return 0;
+ return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ?
+ (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR));
}
static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
return copy_to_user(argp, joydev->corr,
sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0;
case JSIOCSAXMAP:
- if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * ABS_MAX))
+ if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1)))
return -EFAULT;
for (i = 0; i < joydev->nabs; i++) {
if (joydev->abspam[i] > ABS_MAX) return -EINVAL;
return 0;
case JSIOCGAXMAP:
return copy_to_user(argp, joydev->abspam,
- sizeof(__u8) * ABS_MAX) ? -EFAULT : 0;
+ sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0;
case JSIOCSBTNMAP:
- if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC)))
+ if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)))
return -EFAULT;
for (i = 0; i < joydev->nkey; i++) {
if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) return -EINVAL;
return 0;
case JSIOCGBTNMAP:
return copy_to_user(argp, joydev->keypam,
- sizeof(__u16) * (KEY_MAX - BTN_MISC)) ? -EFAULT : 0;
+ sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0;
default:
if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) {
int len;
joydev->handle.private = joydev;
sprintf(joydev->name, "js%d", minor);
- for (i = 0; i < ABS_MAX; i++)
+ for (i = 0; i < ABS_MAX + 1; i++)
if (test_bit(i, dev->absbit)) {
joydev->absmap[i] = joydev->nabs;
joydev->abspam[joydev->nabs] = i;
joydev->nabs++;
}
- for (i = BTN_JOYSTICK - BTN_MISC; i < KEY_MAX - BTN_MISC; i++)
+ for (i = BTN_JOYSTICK - BTN_MISC; i < KEY_MAX - BTN_MISC + 1; i++)
if (test_bit(i + BTN_MISC, dev->keybit)) {
joydev->keymap[i] = joydev->nkey;
joydev->keypam[joydev->nkey] = i + BTN_MISC;
static void joydev_disconnect(struct input_handle *handle)
{
struct joydev *joydev = handle->private;
+ struct joydev_list *list;
class_simple_device_remove(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
devfs_remove("input/js%d", joydev->minor);
joydev->exist = 0;
- if (joydev->open)
+ if (joydev->open) {
input_close_device(handle);
- else
+ wake_up_interruptible(&joydev->wait);
+ list_for_each_entry(list, &joydev->list, node)
+ kill_fasync(&list->fasync, SIGIO, POLL_HUP);
+ } else
joydev_free(joydev);
}