static long rmnet_ctrl_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
{
	struct rmnet_ctrl_qti_port *port = fp->private_data;
	int val, ret = 0;

	pr_debug("%s: Received command %d", __func__, cmd);

	if (rmnet_ctrl_lock(&port->ioctl_excl))
		return -EBUSY;

	switch (cmd) {
	case FRMNET_CTRL_GET_LINE_STATE:
		val = atomic_read(&port->line_state);
		ret = copy_to_user((void __user *)arg, &val, sizeof(val));
		if (ret) {
			pr_err("copying to user space failed");
			ret = -EFAULT;
		}
		pr_debug("%s: Sent line_state: %d", __func__,
				 atomic_read(&port->line_state));
		break;
	default:
		pr_err("wrong parameter");
		ret = -EINVAL;
	}

	rmnet_ctrl_unlock(&port->ioctl_excl);

	return ret;
}
Ejemplo n.º 2
0
static int rmnet_ctrl_open(struct inode *ip, struct file *fp)
{
	unsigned long		flags;
	struct rmnet_ctrl_qti_port *port = container_of(fp->private_data,
						struct rmnet_ctrl_qti_port,
						rmnet_device);

	pr_debug("Open rmnet_ctrl_qti device file name=%s(index=%d)\n",
		port->name, port->index);

	if (rmnet_ctrl_lock(&port->open_excl)) {
		pr_err("Already opened\n");
		return -EBUSY;
	}

	spin_lock_irqsave(&port->lock, flags);
	port->is_open = true;
	spin_unlock_irqrestore(&port->lock, flags);

	return 0;
}
static ssize_t
rmnet_ctrl_write(struct file *fp, const char __user *buf, size_t count,
		   loff_t *pos)
{
	struct rmnet_ctrl_qti_port *port = fp->private_data;
	void *kbuf;
	unsigned long flags;
	int ret = 0;

	pr_debug("%s: Enter(%d) port_index=%d", __func__, count, port->index);

	if (!count) {
		pr_debug("zero length ctrl pkt\n");
		return -EINVAL;
	}

	if (count > MAX_QTI_PKT_SIZE) {
		pr_debug("given pkt size too big:%d > max_pkt_size:%d\n",
				count, MAX_QTI_PKT_SIZE);
		return -EINVAL;
	}

	if (rmnet_ctrl_lock(&port->write_excl)) {
		pr_err("Previous writing not finished yet\n");
		return -EBUSY;
	}

	if (!atomic_read(&port->connected)) {
		pr_debug("USB cable not connected\n");
		rmnet_ctrl_unlock(&port->write_excl);
		return -EPIPE;
	}

	kbuf = kmalloc(count, GFP_KERNEL);
	if (!kbuf) {
		pr_err("failed to allocate ctrl pkt\n");
		rmnet_ctrl_unlock(&port->write_excl);
		return -ENOMEM;
	}
	ret = copy_from_user(kbuf, buf, count);
	if (ret) {
		pr_err("copy_from_user failed err:%d\n", ret);
		kfree(kbuf);
		rmnet_ctrl_unlock(&port->write_excl);
		return -EFAULT;
	}

	spin_lock_irqsave(&port->lock, flags);
	if (port->port_usb && port->port_usb->send_cpkt_response) {
		ret = port->port_usb->send_cpkt_response(port->port_usb,
							kbuf, count);
		if (ret) {
			pr_err("failed to send ctrl packet. error=%d\n", ret);
			spin_unlock_irqrestore(&port->lock, flags);
			kfree(kbuf);
			rmnet_ctrl_unlock(&port->write_excl);
			return ret;
		}
	} else {
		pr_err("send_cpkt_response callback is NULL\n");
		spin_unlock_irqrestore(&port->lock, flags);
		kfree(kbuf);
		rmnet_ctrl_unlock(&port->write_excl);
		return -EINVAL;
	}
	spin_unlock_irqrestore(&port->lock, flags);

	kfree(kbuf);
	rmnet_ctrl_unlock(&port->write_excl);

	pr_debug("%s: Exit(%d)", __func__, count);

	return count;

}
static ssize_t
rmnet_ctrl_read(struct file *fp, char __user *buf, size_t count, loff_t *pos)
{
	struct rmnet_ctrl_qti_port *port = fp->private_data;
	struct rmnet_ctrl_pkt *cpkt = NULL;
	unsigned long flags;
	int ret = 0;

	pr_debug("%s: Enter(%d)\n", __func__, count);

	if (count > MAX_QTI_PKT_SIZE) {
		pr_err("Buffer size is too big %d, should be at most %d\n",
			count, MAX_QTI_PKT_SIZE);
		return -EINVAL;
	}

	if (rmnet_ctrl_lock(&port->read_excl)) {
		pr_err("Previous reading is not finished yet\n");
		return -EBUSY;
	}

	/* block until a new packet is available */
	do {
		spin_lock_irqsave(&port->lock, flags);
		if (!list_empty(&port->cpkt_req_q))
			break;
		spin_unlock_irqrestore(&port->lock, flags);

		pr_debug("%s: Requests list is empty. Wait.\n", __func__);
		ret = wait_event_interruptible(port->read_wq,
					!list_empty(&port->cpkt_req_q));
		if (ret < 0) {
			pr_debug("Waiting failed\n");
			rmnet_ctrl_unlock(&port->read_excl);
			return -ERESTARTSYS;
		}
	} while (1);

	cpkt = list_first_entry(&port->cpkt_req_q, struct rmnet_ctrl_pkt,
							list);
	list_del(&cpkt->list);
	spin_unlock_irqrestore(&port->lock, flags);

	if (cpkt->len > count) {
		pr_err("cpkt size too big:%d > buf size:%d\n",
				cpkt->len, count);
		rmnet_ctrl_unlock(&port->read_excl);
		free_rmnet_ctrl_pkt(cpkt);
		return -ENOMEM;
	}

	pr_debug("%s: cpkt size:%d\n", __func__, cpkt->len);


	rmnet_ctrl_unlock(&port->read_excl);

	ret = copy_to_user(buf, cpkt->buf, cpkt->len);
	if (ret) {
		pr_err("copy_to_user failed: err %d\n", ret);
		ret = -EFAULT;
	} else {
		pr_debug("%s: copied %d bytes to user\n", __func__, cpkt->len);
		ret = cpkt->len;
	}

	free_rmnet_ctrl_pkt(cpkt);

	return ret;
}
Ejemplo n.º 5
0
static long rmnet_ctrl_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
{
	struct rmnet_ctrl_qti_port *port = container_of(fp->private_data,
						struct rmnet_ctrl_qti_port,
						rmnet_device);
	struct grmnet *gr = NULL;
	struct ep_info info;
	int val, ret = 0;

	pr_debug("%s: Received command %d", __func__, cmd);

	if (rmnet_ctrl_lock(&port->ioctl_excl))
		return -EBUSY;

	switch (cmd) {
	case FRMNET_CTRL_MODEM_OFFLINE:
		if (port && port->port_usb)
			gr = port->port_usb;

		if (gr && gr->disconnect)
			gr->disconnect(gr);
		break;
	case FRMNET_CTRL_MODEM_ONLINE:
		if (port && port->port_usb)
			gr = port->port_usb;

		if (gr && gr->connect)
			gr->connect(gr);
		break;
	case FRMNET_CTRL_GET_LINE_STATE:
		val = atomic_read(&port->line_state);
		ret = copy_to_user((void __user *)arg, &val, sizeof(val));
		if (ret) {
			pr_err("copying to user space failed");
			ret = -EFAULT;
		}
		pr_debug("%s: Sent line_state: %d", __func__,
				 atomic_read(&port->line_state));
		break;
	case FRMNET_CTRL_EP_LOOKUP:
		val = atomic_read(&port->connected);
		if (!val) {
			pr_err("EP_LOOKUP failed - not connected");
			ret = -EAGAIN;
			break;
		}

		if (port->ipa_prod_idx == -1 ||  port->ipa_cons_idx == -1) {
			pr_err("EP_LOOKUP failed - ipa pipes were not updated");
			ret = -EAGAIN;
			break;

		}

		info.ph_ep_info.ep_type = DATA_EP_TYPE_HSUSB;
		info.ph_ep_info.peripheral_iface_id = port->intf;
		info.ipa_ep_pair.cons_pipe_num = port->ipa_cons_idx;
		info.ipa_ep_pair.prod_pipe_num = port->ipa_prod_idx;

		ret = copy_to_user((void __user *)arg, &info,
			sizeof(info));
		if (ret) {
			pr_err("copying to user space failed");
			ret = -EFAULT;
		}
		break;
	default:
		pr_err("wrong parameter");
		ret = -EINVAL;
	}

	rmnet_ctrl_unlock(&port->ioctl_excl);

	return ret;
}