Exemple #1
0
static ssize_t ds_write FOPS(struct inode *inode,
			     struct file *file, const char *buf,
			     size_t count, loff_t *ppos)
{
    socket_t i = MINOR(F_INODE(file)->i_rdev);
    socket_info_t *s;
    user_info_t *user;

    DEBUG(2, "ds_write(socket %d)\n", i);
    
    if ((i >= sockets) || (sockets == 0))
	return -ENODEV;
    if (count != 4)
	return -EINVAL;
    if ((file->f_flags & O_ACCMODE) == O_RDONLY)
	return -EBADF;
    s = &socket_table[i];
    user = file->private_data;
    if (CHECK_USER(user))
	return -EIO;

    if (s->req_pending) {
	s->req_pending--;
	get_user(s->req_result, (int *)buf);
	if ((s->req_result != 0) || (s->req_pending == 0))
	    wake_up_interruptible(&s->request);
    } else
	return -EIO;

    return 4;
} /* ds_write */
Exemple #2
0
static FS_RELEASE_T ds_release(struct inode *inode, struct file *file)
{
    socket_t i = MINOR(inode->i_rdev);
    socket_info_t *s;
    user_info_t *user, **link;

    DEBUG(0, "ds_release(socket %d)\n", i);
    if ((i >= sockets) || (sockets == 0))
	return (FS_RELEASE_T)0;
    s = &socket_table[i];
    user = file->private_data;
    if (CHECK_USER(user))
	return (FS_RELEASE_T)0;

    /* Unlink user data structure */
    if ((file->f_flags & O_ACCMODE) != O_RDONLY)
	s->state &= ~SOCKET_BUSY;
    file->private_data = NULL;
    for (link = &s->user; *link; link = &(*link)->next)
	if (*link == user) break;
    if (link == NULL)
	return (FS_RELEASE_T)0;
    *link = user->next;
    user->user_magic = 0;
    kfree(user);
    
    MOD_DEC_USE_COUNT;
    return (FS_RELEASE_T)0;
} /* ds_release */
Exemple #3
0
static ssize_t ds_read FOPS(struct inode *inode,
			    struct file *file, char *buf,
			    size_t count, loff_t *ppos)
{
    socket_t i = MINOR(F_INODE(file)->i_rdev);
    socket_info_t *s;
    user_info_t *user;

    DEBUG(2, "ds_read(socket %d)\n", i);
    
    if ((i >= sockets) || (sockets == 0))
	return -ENODEV;
    if (count < 4)
	return -EINVAL;
    s = &socket_table[i];
    user = file->private_data;
    if (CHECK_USER(user))
	return -EIO;
    
    if (queue_empty(user)) {
	interruptible_sleep_on(&s->queue);
	if (signal_pending(current))
	    return -EINTR;
    }
    put_user(get_queued_event(user), (int *)buf);
    return 4;
} /* ds_read */
Exemple #4
0
static ssize_t ds_write(struct file *file, const char __user *buf,
                        size_t count, loff_t *ppos)
{
    struct pcmcia_bus_socket *s;
    user_info_t *user;

    ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_dentry->d_inode));

    if (count != 4)
        return -EINVAL;
    if ((file->f_flags & O_ACCMODE) == O_RDONLY)
        return -EBADF;

    user = file->private_data;
    if (CHECK_USER(user))
        return -EIO;

    s = user->socket;
    if (s->state & DS_SOCKET_DEAD)
        return -EIO;

    if (s->req_pending) {
        s->req_pending--;
        get_user(s->req_result, (int __user *)buf);
        if ((s->req_result != 0) || (s->req_pending == 0))
            wake_up_interruptible(&s->request);
    } else
        return -EIO;

    return 4;
} /* ds_write */
Exemple #5
0
static ssize_t ds_read(struct file *file, char __user *buf,
                       size_t count, loff_t *ppos)
{
    struct pcmcia_bus_socket *s;
    user_info_t *user;
    int ret;

    ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_dentry->d_inode));

    if (count < 4)
        return -EINVAL;

    user = file->private_data;
    if (CHECK_USER(user))
        return -EIO;

    s = user->socket;
    if (s->state & DS_SOCKET_DEAD)
        return -EIO;

    ret = wait_event_interruptible(s->queue, !queue_empty(user));
    if (ret == 0)
        ret = put_user(get_queued_event(user), (int __user *)buf) ? -EFAULT : 4;

    return ret;
} /* ds_read */
Exemple #6
0
static int ds_release(struct inode *inode, struct file *file)
{
    struct pcmcia_bus_socket *s;
    user_info_t *user, **link;

    ds_dbg(0, "ds_release(socket %d)\n", iminor(inode));

    user = file->private_data;
    if (CHECK_USER(user))
        goto out;

    s = user->socket;

    /* Unlink user data structure */
    if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
        s->state &= ~DS_SOCKET_BUSY;
        s->req_pending = 0;
        wake_up_interruptible(&s->request);
    }
    file->private_data = NULL;
    for (link = &s->user; *link; link = &(*link)->next)
        if (*link == user) break;
    if (link == NULL)
        goto out;
    *link = user->next;
    user->user_magic = 0;
    kfree(user);
    pcmcia_put_bus_socket(s);
out:
    return 0;
} /* ds_release */
Exemple #7
0
static u_int ds_poll(struct file *file, poll_table *wait)
{
    socket_t i = MINOR(F_INODE(file)->i_rdev);
    socket_info_t *s;
    user_info_t *user;

    DEBUG(2, "ds_poll(socket %d)\n", i);
    
    if ((i >= sockets) || (sockets == 0))
	return POLLERR;
    s = &socket_table[i];
    user = file->private_data;
    if (CHECK_USER(user))
	return POLLERR;
    POLL_WAIT(file, &s->queue, wait);
    if (!queue_empty(user))
	return POLLIN | POLLRDNORM;
    return 0;
} /* ds_poll */
Exemple #8
0
/* No kernel lock - fine */
static u_int ds_poll(struct file *file, poll_table *wait)
{
    struct pcmcia_bus_socket *s;
    user_info_t *user;

    ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_dentry->d_inode));

    user = file->private_data;
    if (CHECK_USER(user))
        return POLLERR;
    s = user->socket;
    /*
     * We don't check for a dead socket here since that
     * will send cardmgr into an endless spin.
     */
    poll_wait(file, &s->queue, wait);
    if (!queue_empty(user))
        return POLLIN | POLLRDNORM;
    return 0;
} /* ds_poll */
Exemple #9
0
static int ds_select(struct inode *inode, struct file *file,
		     int sel_type, select_table *wait)
{
    socket_t i = MINOR(inode->i_rdev);
    socket_info_t *s;
    user_info_t *user;

    DEBUG(2, "ds_select(socket %d)\n", i);
    
    if ((i >= sockets) || (sockets == 0))
	return -ENODEV;
    s = &socket_table[i];
    user = file->private_data;
    if (CHECK_USER(user))
	return -EIO;
    if (sel_type != SEL_IN)
	return 0;
    if (!queue_empty(user))
	return 1;
    select_wait(&s->queue, wait);
    return 0;
} /* ds_select */
Exemple #10
0
static int ds_ioctl(struct inode * inode, struct file * file,
                    u_int cmd, u_long arg)
{
    struct pcmcia_bus_socket *s;
    void __user *uarg = (char __user *)arg;
    u_int size;
    int ret, err;
    ds_ioctl_arg_t buf;
    user_info_t *user;

    ds_dbg(2, "ds_ioctl(socket %d, %#x, %#lx)\n", iminor(inode), cmd, arg);

    user = file->private_data;
    if (CHECK_USER(user))
        return -EIO;

    s = user->socket;
    if (s->state & DS_SOCKET_DEAD)
        return -EIO;

    size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
    if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL;

    /* Permission check */
    if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN))
        return -EPERM;

    if (cmd & IOC_IN) {
        err = verify_area(VERIFY_READ, uarg, size);
        if (err) {
            ds_dbg(3, "ds_ioctl(): verify_read = %d\n", err);
            return err;
        }
    }
    if (cmd & IOC_OUT) {
        err = verify_area(VERIFY_WRITE, uarg, size);
        if (err) {
            ds_dbg(3, "ds_ioctl(): verify_write = %d\n", err);
            return err;
        }
    }

    err = ret = 0;

    if (cmd & IOC_IN) __copy_from_user((char *)&buf, uarg, size);

    switch (cmd) {
    case DS_ADJUST_RESOURCE_INFO:
        ret = pcmcia_adjust_resource_info(s->handle, &buf.adjust);
        break;
    case DS_GET_CARD_SERVICES_INFO:
        ret = pcmcia_get_card_services_info(&buf.servinfo);
        break;
    case DS_GET_CONFIGURATION_INFO:
        ret = pcmcia_get_configuration_info(s->handle, &buf.config);
        break;
    case DS_GET_FIRST_TUPLE:
        ret = pcmcia_get_first_tuple(s->handle, &buf.tuple);
        break;
    case DS_GET_NEXT_TUPLE:
        ret = pcmcia_get_next_tuple(s->handle, &buf.tuple);
        break;
    case DS_GET_TUPLE_DATA:
        buf.tuple.TupleData = buf.tuple_parse.data;
        buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data);
        ret = pcmcia_get_tuple_data(s->handle, &buf.tuple);
        break;
    case DS_PARSE_TUPLE:
        buf.tuple.TupleData = buf.tuple_parse.data;
        ret = pcmcia_parse_tuple(s->handle, &buf.tuple, &buf.tuple_parse.parse);
        break;
    case DS_RESET_CARD:
        ret = pcmcia_reset_card(s->handle, NULL);
        break;
    case DS_GET_STATUS:
        ret = pcmcia_get_status(s->handle, &buf.status);
        break;
    case DS_VALIDATE_CIS:
        ret = pcmcia_validate_cis(s->handle, &buf.cisinfo);
        break;
    case DS_SUSPEND_CARD:
        ret = pcmcia_suspend_card(s->parent);
        break;
    case DS_RESUME_CARD:
        ret = pcmcia_resume_card(s->parent);
        break;
    case DS_EJECT_CARD:
        ret = pcmcia_eject_card(s->parent);
        break;
    case DS_INSERT_CARD:
        ret = pcmcia_insert_card(s->parent);
        break;
    case DS_ACCESS_CONFIGURATION_REGISTER:
        if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN))
            return -EPERM;
        ret = pcmcia_access_configuration_register(s->handle, &buf.conf_reg);
        break;
    case DS_GET_FIRST_REGION:
        ret = pcmcia_get_first_region(s->handle, &buf.region);
        break;
    case DS_GET_NEXT_REGION:
        ret = pcmcia_get_next_region(s->handle, &buf.region);
        break;
    case DS_GET_FIRST_WINDOW:
        buf.win_info.handle = (window_handle_t)s->handle;
        ret = pcmcia_get_first_window(&buf.win_info.handle, &buf.win_info.window);
        break;
    case DS_GET_NEXT_WINDOW:
        ret = pcmcia_get_next_window(&buf.win_info.handle, &buf.win_info.window);
        break;
    case DS_GET_MEM_PAGE:
        ret = pcmcia_get_mem_page(buf.win_info.handle,
                                  &buf.win_info.map);
        break;
    case DS_REPLACE_CIS:
        ret = pcmcia_replace_cis(s->handle, &buf.cisdump);
        break;
    case DS_BIND_REQUEST:
        if (!capable(CAP_SYS_ADMIN)) return -EPERM;
        err = bind_request(s, &buf.bind_info);
        break;
    case DS_GET_DEVICE_INFO:
        err = get_device_info(s, &buf.bind_info, 1);
        break;
    case DS_GET_NEXT_DEVICE:
        err = get_device_info(s, &buf.bind_info, 0);
        break;
    case DS_UNBIND_REQUEST:
        err = unbind_request(s, &buf.bind_info);
        break;
    case DS_BIND_MTD:
        if (!capable(CAP_SYS_ADMIN)) return -EPERM;
        err = bind_mtd(s, &buf.mtd_info);
        break;
    default:
        err = -EINVAL;
    }

    if ((err == 0) && (ret != CS_SUCCESS)) {
        ds_dbg(2, "ds_ioctl: ret = %d\n", ret);
        switch (ret) {
        case CS_BAD_SOCKET:
        case CS_NO_CARD:
            err = -ENODEV;
            break;
        case CS_BAD_ARGS:
        case CS_BAD_ATTRIBUTE:
        case CS_BAD_IRQ:
        case CS_BAD_TUPLE:
            err = -EINVAL;
            break;
        case CS_IN_USE:
            err = -EBUSY;
            break;
        case CS_OUT_OF_RESOURCE:
            err = -ENOSPC;
            break;
        case CS_NO_MORE_ITEMS:
            err = -ENODATA;
            break;
        case CS_UNSUPPORTED_FUNCTION:
            err = -ENOSYS;
            break;
        default:
            err = -EIO;
            break;
        }
    }

    if (cmd & IOC_OUT) __copy_to_user(uarg, (char *)&buf, size);

    return err;
} /* ds_ioctl */