Exemplo n.º 1
0
int mtp_function_init(void)
{
    int ret;
#if !defined(CONFIG_LGE_USB_GADGET_MTP_DRIVER)
    struct proc_dir_entry *mtp_proc = NULL;
#endif
    ret = misc_register(&mtp_device);
    if (ret)
    {
	    printk(KERN_ERR "mtp device failed to initialize\n");
    }
    ret = misc_register(&mtp_csr_device);
    
    if (ret)
    {
	    printk(KERN_ERR "mtp csr device failed to initialize\n");
    }
    
#if !defined(CONFIG_LGE_USB_GADGET_MTP_DRIVER)
    mtp_proc = create_proc_entry("mtpctl", 0666, 0);
    if (!mtp_proc) {
	   mtp_err("creating /proc/mtpctl failed\n");
         return 1;
    }
    mtp_proc->proc_fops = &mtp_ctl_fops;
#endif
    return ret;
}
Exemplo n.º 2
0
static void mtp_int_complete(struct usb_ep *ep, struct usb_request *req)
{
	mtp_debug("status is %d %d\n", req->status, req->actual);

	if (req->status == -ECONNRESET)
		usb_ep_fifo_flush(ep);

	if (req->status != 0)
		mtp_err("status is %d %p len=%d\n",
		req->status, req, req->actual);

	g_usb_mtp_context.intr_in_busy = 0;
	return;
}
Exemplo n.º 3
0
static void mtp_in_complete(struct usb_ep *ep, struct usb_request *req)
{
	mtp_debug("status is %d %p %d\n", req->status, req, req->actual);
	if (req->status == -ECONNRESET)
		usb_ep_fifo_flush(ep);

	if (req->status != 0) {
		g_usb_mtp_context.error = 1;
		mtp_err("status is %d %p len=%d\n",
		req->status, req, req->actual);
	}

	req_put(&g_usb_mtp_context.tx_reqs, req);
	wake_up(&g_usb_mtp_context.tx_wq);
}
Exemplo n.º 4
0
static void start_out_receive(void)
{
	struct usb_request *req;
	int ret;

	/* if we have idle read requests, get them queued */
	while ((req = req_get(&g_usb_mtp_context.rx_reqs))) {
		req->length = BULK_BUFFER_SIZE;
		ret = usb_ep_queue(g_usb_mtp_context.bulk_out, req, GFP_ATOMIC);
		if (ret < 0) {
			mtp_err("error %d\n", ret);
			g_usb_mtp_context.error = 1;
			req_put(&g_usb_mtp_context.rx_reqs, req);
		}
	}
}
Exemplo n.º 5
0
int mtp_bind_config(struct usb_configuration *c)
{
	int ret = 0;
	int status;

	printk(KERN_INFO "Gadget Usb: mtp_bind_config\n");
	init_waitqueue_head(&g_usb_mtp_context.rx_wq);
	init_waitqueue_head(&g_usb_mtp_context.tx_wq);
	init_waitqueue_head(&g_usb_mtp_context.ctl_rx_wq);
	init_waitqueue_head(&g_usb_mtp_context.ctl_tx_wq);

	INIT_LIST_HEAD(&g_usb_mtp_context.rx_reqs);
	INIT_LIST_HEAD(&g_usb_mtp_context.rx_done_reqs);
	INIT_LIST_HEAD(&g_usb_mtp_context.tx_reqs);
	INIT_LIST_HEAD(&g_usb_mtp_context.ctl_rx_reqs);
	INIT_LIST_HEAD(&g_usb_mtp_context.ctl_rx_done_reqs);

	status = usb_string_id(c->cdev);
	if (status >= 0) {
		mtp_string_defs1[STRING_INTERFACE].id = status;
		intf_desc.iInterface = status;
	}

	mtp_string_defs2[STRING_MTP].id = mtp_ext_str_idx;

	g_usb_mtp_context.cdev = c->cdev;
	g_usb_mtp_context.function.name = "mtp";
	g_usb_mtp_context.function.descriptors = fs_mtp_descs;
	g_usb_mtp_context.function.hs_descriptors = hs_mtp_descs;
	g_usb_mtp_context.function.strings = mtp_strings;
	g_usb_mtp_context.function.bind = mtp_function_bind;
	g_usb_mtp_context.function.unbind = mtp_function_unbind;
	g_usb_mtp_context.function.setup = mtp_function_setup;
	g_usb_mtp_context.function.set_alt = mtp_function_set_alt;
	g_usb_mtp_context.function.disable = mtp_function_disable;

	/* start disabled */
	g_usb_mtp_context.function.hidden = 1;

	ret = usb_add_function(c, &g_usb_mtp_context.function);
	if (ret) {
		mtp_err("MTP gadget driver failed to initialize\n");
		return ret;
	}

	return 0;
}
Exemplo n.º 6
0
static void mtp_out_complete(struct usb_ep *ep, struct usb_request *req)
{
	mtp_debug("status is %d %p %d\n", req->status, req, req->actual);
	if (req->status == 0) {
		req_put(&g_usb_mtp_context.rx_done_reqs, req);
	} else {
		mtp_err("status is %d %p len=%d\n",
		req->status, req, req->actual);
		g_usb_mtp_context.error = 1;
		if (req->status == -ECONNRESET)
		{
#ifdef CONFIG_LGE_USB_GADGET_MTP_DRIVER
		  lg_mtp_debug("LG_FW : BULK OUT DATA Flush!!\n");
#endif
		  usb_ep_fifo_flush(ep);
		}
		req_put(&g_usb_mtp_context.rx_reqs, req);
	}
	wake_up(&g_usb_mtp_context.rx_wq);
}
Exemplo n.º 7
0
static int
mtp_function_bind(struct usb_configuration *c, struct usb_function *f)
{
	int n, rc, id;
	struct usb_ep *ep;
	struct usb_request *req;
	struct proc_dir_entry *mtp_proc = NULL;

	spin_lock_init(&g_usb_mtp_context.lock);
	g_usb_mtp_context.cdev = c->cdev;
	/* allocate interface ID(s) */
	id = usb_interface_id(c, f);
	if (id < 0)
		return id;
	intf_desc.bInterfaceNumber = id;

	/* Find all the endpoints we will use */
	ep = usb_ep_autoconfig(g_usb_mtp_context.cdev->gadget,
						&fs_bulk_in_desc);
	if (!ep) {
		mtp_err("auto-configure hs_bulk_in_desc error\n");
		goto autoconf_fail;
	}
	ep->driver_data = &g_usb_mtp_context;
	g_usb_mtp_context.bulk_in = ep;

	ep = usb_ep_autoconfig(g_usb_mtp_context.cdev->gadget,
						&fs_bulk_out_desc);
	if (!ep) {
		mtp_err("auto-configure hs_bulk_out_desc error\n");
		goto autoconf_fail;
	}
	ep->driver_data = &g_usb_mtp_context;
	g_usb_mtp_context.bulk_out = ep;

	ep = usb_ep_autoconfig(g_usb_mtp_context.cdev->gadget,
						&fs_intr_in_desc);
	if (!ep) {
		mtp_err("auto-configure hs_intr_in_desc error\n");
		goto autoconf_fail;
	}
	ep->driver_data = &g_usb_mtp_context;
	g_usb_mtp_context.intr_in = ep;

	if (gadget_is_dualspeed(g_usb_mtp_context.cdev->gadget)) {
		/* Assume endpoint addresses are the same for both speeds */
		hs_bulk_in_desc.bEndpointAddress =
		    fs_bulk_in_desc.bEndpointAddress;
		hs_bulk_out_desc.bEndpointAddress =
		    fs_bulk_out_desc.bEndpointAddress;
		hs_intr_in_desc.bEndpointAddress =
		    fs_intr_in_desc.bEndpointAddress;
	}

	rc = -ENOMEM;

	for (n = 0; n < MAX_BULK_RX_REQ_NUM; n++) {
		req = req_new(g_usb_mtp_context.bulk_out, BULK_BUFFER_SIZE);
		if (!req)
			goto autoconf_fail;

		pending_reqs[n] = req;

		req->complete = mtp_out_complete;
		req_put(&g_usb_mtp_context.rx_reqs, req);
	}
	for (n = 0; n < MAX_BULK_TX_REQ_NUM; n++) {
		req = req_new(g_usb_mtp_context.bulk_in, BULK_BUFFER_SIZE);
		if (!req)
			goto autoconf_fail;

		req->complete = mtp_in_complete;
		req_put(&g_usb_mtp_context.tx_reqs, req);
	}

	for (n = 0; n < MAX_CTL_RX_REQ_NUM; n++)
		ctl_req_put(&g_usb_mtp_context.ctl_rx_reqs, &ctl_reqs[n]);

	g_usb_mtp_context.int_tx_req =
		req_new(g_usb_mtp_context.intr_in, BULK_BUFFER_SIZE);
	if (!g_usb_mtp_context.int_tx_req)
		goto autoconf_fail;
	g_usb_mtp_context.intr_in_busy = 0;
	g_usb_mtp_context.int_tx_req->complete = mtp_int_complete;

	g_usb_mtp_context.ctl_tx_req =
		req_new(g_usb_mtp_context.cdev->gadget->ep0, 512);
	if (!g_usb_mtp_context.ctl_tx_req)
		goto autoconf_fail;

	misc_register(&mtp_device);

	mtp_proc = create_proc_entry("mtpctl", 0666, 0);
	if (!mtp_proc) {
		mtp_err("creating /proc/mtpctl failed\n");
		goto autoconf_fail;
    }
    mtp_proc->proc_fops = &mtp_ctl_fops;

	return 0;

autoconf_fail:
	rc = -ENOTSUPP;
	mtp_function_unbind(c, f);
	return rc;
}
Exemplo n.º 8
0
static ssize_t mtp_ctl_write(struct file *file, const char *buf,
	size_t count, loff_t *pos)
{
    struct mtp_ctl_msg_header msg;
	struct usb_request *req = NULL;
	struct usb_ep *ep0;
	int ret;

	mtp_debug("count=%d\n", count);

	ret = wait_event_interruptible(g_usb_mtp_context.ctl_tx_wq,
		(g_usb_mtp_context.online || g_usb_mtp_context.ctl_cancel));
	if (g_usb_mtp_context.ctl_cancel) {
		mtp_debug("ctl_cancel return in mtp_ctl_write 1\n");
		g_usb_mtp_context.ctl_cancel = 0;
		return -EINVAL;
	}
	if (ret < 0)
		return ret;

	ep0 = g_usb_mtp_context.cdev->gadget->ep0;
    if (count > ep0->maxpacket || count < MTP_CTL_MSG_HEADER_SIZE) {
		mtp_err("size invalid\n");
		return -ENOMEM;
    }

    /* msg info */
    if (copy_from_user(&msg, buf, MTP_CTL_MSG_HEADER_SIZE))
		return -EINVAL;

    mtp_debug("msg len = %d, msg id = %d", msg.msg_len, msg.msg_id);
    if (msg.msg_id != MTP_CTL_CLASS_REPLY) {
		mtp_err("invalid id %d", msg.msg_id);
		return -EINVAL;
    }

    /* sending the data */
	req = g_usb_mtp_context.ctl_tx_req;
	if (!req)
		return -ENOMEM;
    req->length = count - MTP_CTL_MSG_HEADER_SIZE;
	req->complete = mtp_ctl_write_complete;
    if (copy_from_user(req->buf,
		(u8 *)buf + MTP_CTL_MSG_HEADER_SIZE, req->length)) {
		return -EINVAL;
	}
	ctl_tx_done = 0;
	if (usb_ep_queue(ep0, req, GFP_ATOMIC)) {
		req->status = 0;
		mtp_ctl_write_complete(ep0, req);
		return -EIO;
	}
	ret = wait_event_interruptible(g_usb_mtp_context.ctl_tx_wq,
		(ctl_tx_done || g_usb_mtp_context.ctl_cancel));
	ctl_tx_done = 0;
	if (g_usb_mtp_context.ctl_cancel) {
		mtp_debug("ctl_cancel return in mtp_ctl_write\n");
		g_usb_mtp_context.ctl_cancel = 0;
		return -EINVAL;
	}
	if (ret < 0)
		return ret;

	mtp_debug("return count=%d\n", count);
    return count;
}
Exemplo n.º 9
0
static ssize_t mtp_ctl_read(struct file *file, char *buf,
	size_t count, loff_t *pos)
{
    int ret, size = sizeof(struct usb_ctrlrequest);
	struct mtp_ctl_msg_header msg;

	mtp_debug("count=%d\n", count);

	if (!g_usb_mtp_context.online)
		return -EINVAL;

	if (!cur_creq) {
		ret = wait_event_interruptible(g_usb_mtp_context.ctl_rx_wq,
		((cur_creq = ctl_req_get(&g_usb_mtp_context.ctl_rx_done_reqs))
		 || g_usb_mtp_context.ctl_cancel
		 || g_usb_mtp_context.reset));
		if (g_usb_mtp_context.ctl_cancel) {
			mtp_debug("ctl_cancel return in mtp_ctl_read\n");
			if (cur_creq) {
				ctl_req_put(&g_usb_mtp_context.ctl_rx_reqs,
					    cur_creq);
				if (g_usb_mtp_context.reset)
					cur_creq = NULL;
			}
			g_usb_mtp_context.ctl_cancel = 0;
			if (!g_usb_mtp_context.reset)
				return -EINVAL;
		}
		if (g_usb_mtp_context.reset) {
			mtp_debug("ctl_reset return in mtp_ctl_read\n");
			if (cur_creq)
				ctl_req_put(&g_usb_mtp_context.ctl_rx_reqs,
					    cur_creq);
			g_usb_mtp_context.reset = 0;
			return -EHOSTRESET;
		}
		if (ret < 0) {
			mtp_err("wait_event_interruptible return %d\n", ret);
			return ret;
		}
	}

	msg.msg_id = MTP_CTL_CLASS_REQ;
	msg.msg_len = MTP_CTL_MSG_SIZE;
	if (cur_creq->creq.bRequest == MTP_CLASS_CANCEL_REQ)
		msg.msg_len = MTP_CTL_MSG_SIZE + MTP_CANCEL_REQ_DATA_SIZE;

	if (cur_creq->header == 1) {
		cur_creq->header = 0;
		if (copy_to_user(buf, &msg, MTP_CTL_MSG_HEADER_SIZE))
			goto ctl_read_fail;
		ret = MTP_CTL_MSG_HEADER_SIZE;
		mtp_debug("msg header return %d\n", ret);
	} else {
		if (copy_to_user(buf, &cur_creq->creq, size))
			goto ctl_read_fail;
		ret = size;
		if (cur_creq->creq.bRequest == MTP_CLASS_CANCEL_REQ) {
			if (copy_to_user(buf + size, &cur_creq->cancel_data,
				MTP_CANCEL_REQ_DATA_SIZE))
				goto ctl_read_fail;
			ret += MTP_CANCEL_REQ_DATA_SIZE;
		}
		mtp_debug("prepare %d %x\n", ret, cur_creq->creq.bRequest);
		ctl_req_put(&g_usb_mtp_context.ctl_rx_reqs, cur_creq);
		cur_creq = NULL;
	}

	mtp_debug("return %d\n", ret);
    return ret;

ctl_read_fail:
	ctl_req_put(&g_usb_mtp_context.ctl_rx_reqs, cur_creq);
	cur_creq = NULL;
	mtp_debug("return -EFAULT\n");
    return -EFAULT;
}
Exemplo n.º 10
0
static int mtp_ioctl(struct inode *inode, struct file *file,
		unsigned int cmd, unsigned long arg)
{
	int len, clen, count, n;
	struct usb_request *req;
	struct mtp_event_data event;

	if (!g_usb_mtp_context.online)
		return -EINVAL;

	switch (cmd) {
	case MTP_IOC_EVENT:
		if (g_usb_mtp_context.intr_in_busy) {
			mtp_err("interrupt in request busy\n");
			return -EBUSY;
		}

		count = MIN(_IOC_SIZE(cmd), MTP_EVENT_SIZE);
		if (copy_from_user(event.data, (void *)arg,  count))
			return -EINVAL;

		/* length is in little endian */
		memcpy(&len, event.data, sizeof(len));
		clen = le32_to_cpu(len);
		mtp_debug("len=%d cpu len=%d\n", len, clen);
		/* send event through interrupt in */
		req = g_usb_mtp_context.int_tx_req;
		if (!req)
			return -EINVAL;
		count = MIN(MTP_EVENT_SIZE, clen);
		memcpy(req->buf, event.data, count);
		req->length = count;
		req->zero = 0;
		g_usb_mtp_context.intr_in_busy = 1;
		if (usb_ep_queue(g_usb_mtp_context.intr_in, req, GFP_ATOMIC)) {
			g_usb_mtp_context.intr_in_busy = 0;
			return -EINVAL;
		}
		break;
	case MTP_IOC_SEND_ZLP:
		req = req_get(&g_usb_mtp_context.tx_reqs);
		if (!req)
			return -EINVAL;
		req->length = 0;
		req->zero = 0;
		if (usb_ep_queue(g_usb_mtp_context.bulk_in, req, GFP_ATOMIC)) {
			req_put(&g_usb_mtp_context.tx_reqs, req);
			return -EINVAL;
		}
		break;
	case MTP_IOC_GET_EP_SIZE_IN:
		/* get endpoint buffer size for bulk in */
		len = BULK_BUFFER_SIZE;
		if (copy_to_user((void *)arg, &len, sizeof(int)))
			return -EINVAL;
		break;
	case MTP_IOC_CANCEL_IO:
		mtp_debug("MTP_IOC_CANCEL_IO:\n");
		g_usb_mtp_context.cancel = 1;
		for (n = 0; n < MAX_BULK_RX_REQ_NUM; n++) {
			req = pending_reqs[n];
			if (req && req->actual) {
				mtp_err("n=%d %p %d\n", n, req, req->actual);
				req->actual = 0;
			}
		}
		/* we've cancelled the recv urb, start new one */
		mtp_debug("MTP_IOC_CANCEL_IO end:\n");
		wake_up(&g_usb_mtp_context.rx_wq);
		wake_up(&g_usb_mtp_context.tx_wq);
		break;
	case MTP_IOC_DEVICE_RESET:
		g_usb_mtp_context.cancel = 1;
		g_usb_mtp_context.ctl_cancel = 1;
		wake_up(&g_usb_mtp_context.rx_wq);
		wake_up(&g_usb_mtp_context.tx_wq);
		wake_up(&g_usb_mtp_context.ctl_rx_wq);
		wake_up(&g_usb_mtp_context.ctl_tx_wq);
		break;
	}
	return 0;
}
Exemplo n.º 11
0
static ssize_t mtp_write(struct file *fp, const char __user *buf,
				 size_t count, loff_t *pos)
{
	struct usb_request *req;
	int rc = count, xfer;
	int ret;

	while (count > 0) {
		mtp_debug("count=%d\n", count);
		if (g_usb_mtp_context.error)
			return -EIO;

		/* get an idle tx request to use */
		ret = wait_event_interruptible(g_usb_mtp_context.tx_wq,
			(g_usb_mtp_context.online || g_usb_mtp_context.cancel));

		if (g_usb_mtp_context.cancel) {
			mtp_debug("cancel return in mtp_write at beginning\n");
			g_usb_mtp_context.cancel = 0;
			return -EINVAL;
		}
		if (ret < 0) {
			mtp_err("wait_event_interruptible return %d\n", ret);
			rc = ret;
			break;
		}

		req = 0;
		mtp_debug("get tx req\n");
		ret = wait_event_interruptible(g_usb_mtp_context.tx_wq,
			((req = req_get(&g_usb_mtp_context.tx_reqs))
			 || g_usb_mtp_context.cancel));

		mtp_debug("got tx req\n");
		if (g_usb_mtp_context.cancel) {
			mtp_debug("cancel return in mtp_write get req\n");
			if (req != 0)
				req_put(&g_usb_mtp_context.tx_reqs, req);
			g_usb_mtp_context.cancel = 0;
			return -EINVAL;
		}
		if (ret < 0) {
			mtp_err("wait_event_interruptible return(2) %d\n", ret);
			rc = ret;
			break;
		}

		if (req != 0) {
			if (count > BULK_BUFFER_SIZE)
				xfer = BULK_BUFFER_SIZE;
			else
				xfer = count;
			if (copy_from_user(req->buf, buf, xfer)) {
				req_put(&g_usb_mtp_context.tx_reqs, req);
				rc = -EFAULT;
				break;
			}

			req->length = xfer;
			ret = usb_ep_queue(g_usb_mtp_context.bulk_in,
				req, GFP_ATOMIC);
			if (ret < 0) {
				mtp_err("error %d\n", ret);
				g_usb_mtp_context.error = 1;
				req_put(&g_usb_mtp_context.tx_reqs, req);
				rc = ret;
				break;
			}

			buf += xfer;
			count -= xfer;
			mtp_debug("xfer=%d\n", xfer);
		}
	}

	mtp_debug("mtp_write returning %d\n", rc);
	return rc;
}
Exemplo n.º 12
0
static ssize_t mtp_read(struct file *fp, char __user *buf,
				size_t count, loff_t *pos)
{
	struct usb_request *req = 0;
	int xfer, rc = count;
	int ret;

	while (count > 0) {
		mtp_debug("count=%d\n", count);
		if (g_usb_mtp_context.error)
			return -EIO;

		/* we will block until we're online */
		ret = wait_event_interruptible(g_usb_mtp_context.rx_wq,
			(g_usb_mtp_context.online || g_usb_mtp_context.cancel));
		if (g_usb_mtp_context.cancel) {
			mtp_debug("cancel return in mtp_read at beginning\n");
			g_usb_mtp_context.cancel = 0;
			return -EINVAL;
		}
		if (ret < 0) {
			mtp_err("wait_event_interruptible return %d\n", ret);
			rc = ret;
			break;
		}

		/* if we have idle read requests, get them queued */
		while (1) {
			req = req_get(&g_usb_mtp_context.rx_reqs);
			if (!req)
				break;
requeue_req:
			req->length = BULK_BUFFER_SIZE;
			mtp_debug("rx %p queue\n", req);
			ret = usb_ep_queue(g_usb_mtp_context.bulk_out,
				req, GFP_ATOMIC);

			if (ret < 0) {
				mtp_err("queue error %d\n", ret);
				g_usb_mtp_context.error = 1;
				req_put(&g_usb_mtp_context.rx_reqs, req);
				return ret;
			}
		}

		/* if we have data pending, give it to userspace */
		if (g_usb_mtp_context.data_len > 0) {
			if (g_usb_mtp_context.data_len < count)
				xfer = g_usb_mtp_context.data_len;
			else
				xfer = count;

			if (copy_to_user(buf, g_usb_mtp_context.read_buf,
								xfer)) {
				rc = -EFAULT;
				break;
			}
			g_usb_mtp_context.read_buf += xfer;
			g_usb_mtp_context.data_len -= xfer;
			buf += xfer;
			count -= xfer;
			mtp_debug("xfer=%d\n", xfer);

			/* if we've emptied the buffer, release the request */
			if (g_usb_mtp_context.data_len == 0) {
				req_put(&g_usb_mtp_context.rx_reqs,
						g_usb_mtp_context.cur_read_req);
				g_usb_mtp_context.cur_read_req = 0;
			}
			continue;
		}

		/* wait for a request to complete */
		req = 0;
		mtp_debug("wait req finish\n");
		ret = wait_event_interruptible(g_usb_mtp_context.rx_wq,
		((req = req_get(&g_usb_mtp_context.rx_done_reqs))
			|| g_usb_mtp_context.cancel));
		mtp_debug("req finished\n");
		if (g_usb_mtp_context.cancel) {
			if (req != 0)
				req_put(&g_usb_mtp_context.rx_reqs, req);
			mtp_debug("cancel return in mtp_read at complete\n");
			g_usb_mtp_context.cancel = 0;
			return -EINVAL;
		}
		if (ret < 0) {
			mtp_err("wait_event_interruptible(2) return %d\n", ret);
			rc = ret;
			break;
		}
		if (req != 0) {
			/* if we got a 0-len one we need to put it back into
			** service.  if we made it the current read req we'd
			** be stuck forever
			*/
			if (req->actual == 0)
				goto requeue_req;

			g_usb_mtp_context.cur_read_req = req;
			g_usb_mtp_context.data_len = req->actual;
			g_usb_mtp_context.read_buf = req->buf;
			mtp_debug("rx %p done actual=%d\n", req, req->actual);
		}
	}

	mtp_debug("mtp_read returning %d\n", rc);
	return rc;
}
Exemplo n.º 13
0
static int mtp_function_setup(struct usb_function *f,
					const struct usb_ctrlrequest *ctrl)
{
	int	value = -EOPNOTSUPP;
	u16     wIndex = le16_to_cpu(ctrl->wIndex);
	u16     wLength = le16_to_cpu(ctrl->wLength);
	struct usb_composite_dev *cdev = f->config->cdev;
	struct usb_request	*req = cdev->req;
	struct ctl_req_wrapper	*ctl_req;

	if (f->hidden == 1)
		return value;

	mtp_debug("bRequestType=0x%x bRequest=0x%x wIndex=0x%x wLength=0x%x\n",
		ctrl->bRequestType, ctrl->bRequest, wIndex, wLength);

	switch (ctrl->bRequestType & USB_TYPE_MASK) {
	case USB_TYPE_VENDOR:
		switch (ctrl->bRequest) {
		case MTP_MOD_VENDOR_CODE:
			if (wIndex == mtp_ext_id) {
				memcpy(req->buf, mtp_ext_desc,
						sizeof(mtp_ext_desc));
				if (wLength < mtp_ext_desc[0])
					value = wLength;
				else
					value = mtp_ext_desc[0];

				req->zero = 0;
				req->length = value;
				if (usb_ep_queue(cdev->gadget->ep0, req,
					GFP_ATOMIC))
					mtp_err("ep0 in queue failed\n");
			}
			break;
		default:
			break;
		}
		break;
	case USB_TYPE_CLASS:
		switch (ctrl->bRequest) {
		case MTP_CLASS_CANCEL_REQ:
		case MTP_CLASS_GET_EXTEND_EVEVT_DATA:
		case MTP_CLASS_GET_DEVICE_STATUS:
			mtp_debug("ctl request=0x%x\n", ctrl->bRequest);
			ctl_req = ctl_req_get(&g_usb_mtp_context.ctl_rx_reqs);
			if (!ctl_req) {
				mtp_err("get free ctl req failed\n");
				break;
			}
			memcpy(&ctl_req->creq, ctrl,
					sizeof(struct usb_ctrlrequest));
			ctl_req->header = 1;
			ctl_req_put(&g_usb_mtp_context.ctl_rx_done_reqs,
				ctl_req);
			value = 0;
			if ((ctrl->bRequest  == MTP_CLASS_CANCEL_REQ)
				&& wLength == MTP_CANCEL_REQ_DATA_SIZE) {

				memset(&ctl_req->cancel_data, 0,
					MTP_CANCEL_REQ_DATA_SIZE);
				value = wLength;
				cdev->gadget->ep0->driver_data = ctl_req;
				req->complete = mtp_ctl_read_complete;
				req->zero = 0;
				req->length = wLength;

				if (usb_ep_queue(cdev->gadget->ep0,
						req, GFP_ATOMIC)) {
					mtp_err("ep0 out queue failed\n");
					mtp_ctl_read_complete(cdev->gadget->ep0,
							req);
				}
			} else
				wake_up(&g_usb_mtp_context.ctl_rx_wq);
			break;
		default:
			break;
		}
	}

	mtp_debug("return value=%d\n", value);
	return value;
}
Exemplo n.º 14
0
int  mtp_function_add(struct usb_composite_dev *cdev,
	struct usb_configuration *c)
#endif
{
	int ret = 0;
	int status;

	init_waitqueue_head(&g_usb_mtp_context.rx_wq);
	init_waitqueue_head(&g_usb_mtp_context.tx_wq);
	init_waitqueue_head(&g_usb_mtp_context.ctl_rx_wq);
	init_waitqueue_head(&g_usb_mtp_context.ctl_tx_wq);

	INIT_LIST_HEAD(&g_usb_mtp_context.rx_reqs);
	INIT_LIST_HEAD(&g_usb_mtp_context.rx_done_reqs);
	INIT_LIST_HEAD(&g_usb_mtp_context.tx_reqs);
	INIT_LIST_HEAD(&g_usb_mtp_context.ctl_rx_reqs);
	INIT_LIST_HEAD(&g_usb_mtp_context.ctl_rx_done_reqs);

	status = usb_string_id(c->cdev);
	if (status >= 0) {
		mtp_string_defs[STRING_INTERFACE].id = status;
        intf_desc.iInterface = status;
	}

	mtp_string_defs[STRING_MTP].id = mtp_ext_str_idx;

#ifdef CONFIG_LGE_USB_GADGET_FUNC_BIND_ONLY_INIT
    g_usb_mtp_context.cdev = c->cdev;
#else
	g_usb_mtp_context.cdev = cdev;
#endif
	g_usb_mtp_context.function.name = "mtp";
	g_usb_mtp_context.function.descriptors = fs_mtp_descs;
	g_usb_mtp_context.function.hs_descriptors = hs_mtp_descs;
	g_usb_mtp_context.function.strings = mtp_strings;
	g_usb_mtp_context.function.bind = mtp_function_bind;
	g_usb_mtp_context.function.unbind = mtp_function_unbind;
	g_usb_mtp_context.function.setup = mtp_function_setup;
	g_usb_mtp_context.function.set_alt = mtp_function_set_alt;
	g_usb_mtp_context.function.disable = mtp_function_disable;

#ifndef CONFIG_LGE_USB_GADGET_FUNC_BIND_ONLY_INIT
	ret = mtp_function_init();
	if (ret)
		goto mtp_exit;

	ret = misc_register(&mtp_enable_device);
	if (ret)
		goto misc_deregister;
#endif

#ifdef CONFIG_LGE_USB_GADGET_FUNC_BIND_ONLY_INIT
	/* start disabled */
	g_usb_mtp_context.function.disabled = 1;
#endif

	ret = usb_add_function(c, &g_usb_mtp_context.function);
	if (ret) {
		mtp_err("MTP gadget driver failed to initialize\n");
		return ret;
	}

	return 0;

#ifndef CONFIG_LGE_USB_GADGET_FUNC_BIND_ONLY_INIT
mtp_misc_deregister:
	misc_deregister(&mtp_enable_device);
mtp_exit:
	mtp_function_exit();
	return ret;
#endif

}
Exemplo n.º 15
0
static int mtp_function_setup(struct usb_function *f,
					const struct usb_ctrlrequest *ctrl)
{
	int	value = -EOPNOTSUPP;
	u16     wIndex = le16_to_cpu(ctrl->wIndex);
	u16     wLength = le16_to_cpu(ctrl->wLength);
	struct usb_composite_dev *cdev = f->config->cdev;
	struct usb_request	*req = cdev->req;

//    int result = -EOPNOTSUPP;

	mtp_debug("bRequestType=0x%x bRequest=0x%x wIndex=0x%x wLength=0x%x\n",
		ctrl->bRequestType, ctrl->bRequest, wIndex, wLength);

	switch (ctrl->bRequestType & USB_TYPE_MASK) {
	case USB_TYPE_VENDOR:
		switch (ctrl->bRequest) {
		case MTP_MOD_VENDOR_CODE:
			if (wIndex == mtp_ext_id) {
				memcpy(req->buf, mtp_ext_desc,
						sizeof(mtp_ext_desc));
				if (wLength < mtp_ext_desc[0])
					value = wLength;
				else
					value = mtp_ext_desc[0];

				req->zero = 0;
				req->length = value;
				if (usb_ep_queue(cdev->gadget->ep0, req,
					GFP_ATOMIC))
					mtp_err("ep0 in queue failed\n");
			}
			break;
		default:
			break;
		}
		break;
	case USB_TYPE_CLASS:
		switch (ctrl->bRequest) {
		case MTP_CLASS_CANCEL_REQ:
		case MTP_CLASS_GET_EXTEND_EVEVT_DATA:
		case MTP_CLASS_RESET_REQ:
		case MTP_CLASS_GET_DEVICE_STATUS:
#ifdef CONFIG_LGE_USB_GADGET_MTP_DRIVER
         g_bRequest = ctrl->bRequest;

		 if(g_bRequest == MTP_CLASS_CANCEL_REQ)
		 {
		   lg_mtp_debug("LG_FW : MTP CANCEL Request PC => Device!!\n");
		   cancel_noti = 1;
		 }
		 else if(g_bRequest == MTP_CLASS_GET_DEVICE_STATUS)
		 {
		   lg_mtp_debug("LG_FW : MTP GET DEVICE Request PC => Device!!\n");
		 }
#endif
			mtp_debug("ctl request=0x%x\n", ctrl->bRequest);

			value = 0;
			if ((ctrl->bRequest  == MTP_CLASS_CANCEL_REQ)
				&& wLength == MTP_CANCEL_REQ_DATA_SIZE) {
				value = wLength;
				req->zero = 0;
				req->length = wLength;

                lg_mtp_debug("LG_FW : MTP Cancel Request Length [%d] \n", wLength);
				if (usb_ep_queue(cdev->gadget->ep0,
						req, GFP_ATOMIC)) {
					mtp_err("ep0 out queue failed\n");
				}
			} 
			break;

		default:
			break;
		}
	}

	mtp_debug("return value=%d\n", value);
	return value;

}