Beispiel #1
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_debug("status is %d %p len=%d\n",
		req->status, req, req->actual);
		g_usb_mtp_context.error = 1;
		if (req->status == -ECONNRESET)
			usb_ep_fifo_flush(ep);
		req_put(&g_usb_mtp_context.rx_reqs, req);
	}
	wake_up(&g_usb_mtp_context.rx_wq);
}
Beispiel #2
0
static void mtp_ctl_write_complete(struct usb_ep *ep, struct usb_request *req)
{
	mtp_debug("mtp_ctl_write_complete --> %d, %d/%d\n",
	req->status, req->actual, req->length);

	ctl_tx_done = 1;

	wake_up(&g_usb_mtp_context.ctl_tx_wq);
}
Beispiel #3
0
static int mtp_ctl_open(struct inode *ip, struct file *fp)
{
	/*
	** clear reset variable to prevent
	** mtp server read last time reset signal
	*/
	mtp_debug("---mtp_ctl_open\n");
	g_usb_mtp_context.reset = 0;
	return 0;
}
Beispiel #4
0
static void mtp_ctl_read_complete(struct usb_ep *ep, struct usb_request *req)
{
	struct ctl_req_wrapper	*ctl_req = ep->driver_data;

	mtp_debug("mtp_ctl_read_complete --> %d, %d/%d\n",
	req->status, req->actual, req->length);

	if (req->status == 0)
		memcpy(ctl_req->cancel_data, req->buf, req->actual);

	wake_up(&g_usb_mtp_context.ctl_rx_wq);
}
Beispiel #5
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;
}
Beispiel #6
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);
}
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);
}
Beispiel #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;
}
Beispiel #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;
}
Beispiel #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;
}
Beispiel #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;
}
Beispiel #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;
}
Beispiel #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;
}
static int mtp_ioctl(struct inode *inode, struct file *file,
		unsigned int cmd, unsigned long arg)
{   
  u16 g_mtp_get_status;    
  struct usb_request	*req =g_usb_mtp_context.cdev->req;
  struct usb_ep *ep0;
  long ret;
  int usbconnect = 0;

/* LGE_CHANGES_S [[email protected]] 2010-09-18, Depense code for Null pointer access */

  /* When mtp_enable_open()/release()(in android.c) is invoked,
   * mtp_enable_flag is set/cleared. If enable flag is false(mtp is off),
   * we cut off the user's ioctl request.
   */
  if (!mtp_enable_flag)
	  return -ENODEV;

  if (product_id != lg_mtp_pid) {
	  printk(KERN_INFO "not MTP pid\n");
	  return -EFAULT;
  }

  if (g_usb_mtp_context.cdev->gadget == NULL) {
	  return -EFAULT;
  }

  ep0 = g_usb_mtp_context.cdev->gadget->ep0;

/* LGE_CHANGES_E [[email protected]]  */


  switch (cmd)  
  {      	       
	case USB_MTP_FUNC_IOC_CONTROL_REQUEST_GET:
		
      if(g_bRequest==MTP_CLASS_CANCEL_REQ||
        g_bRequest==MTP_CLASS_RESET_REQ||
        g_bRequest==MTP_CLASS_GET_DEVICE_STATUS
        )
      {
         mtp_debug("USB_MTP_FUNC_IOC_CONTROL_REQUEST_GET status = %d\n", g_bRequest);
         ret = copy_to_user ((void __user *)arg, &g_bRequest, sizeof(g_bRequest));
		 
		 if(g_bRequest == MTP_CLASS_CANCEL_REQ)
		 {
		   lg_mtp_debug("LG_FW : MTP CANCEL Request Device => App !!\n");
		   cancel_noti = 1;
		 }
		 else if(g_bRequest == MTP_CLASS_GET_DEVICE_STATUS)
		 {
		   lg_mtp_debug("LG_FW : MTP GET DEVICE Request Device => App!!\n");
		 }
      }
      else
      {
         mtp_debug("USB_MTP_FUNC_IOC_OTHER_CONTROL_REQUEST_GET status = %d\n", g_bRequest);
         usbconnect = mtp_get_usb_state();
         if(usbconnect == 0)
         {
           g_bRequest = MTP_OFFLINE; //offline
           ret = copy_to_user ((void __user *)arg, &g_bRequest, sizeof(g_bRequest));
         }
         else
         {
           if(g_usb_mtp_context.online == 1)
           {
              g_bRequest = MTP_ONLINE;//online
              ret = copy_to_user ((void __user *)arg, &g_bRequest, sizeof(g_bRequest));
           }
           else
           {
              g_bRequest = MTP_UNKOWN; //unkown
              ret = copy_to_user ((void __user *)arg, &g_bRequest, sizeof(g_bRequest));
           }
         }
      }
	  
	   g_bRequest = MTP_NO_INIT_STATUS;
	   
      if(ret >= 0)
        return ret;
      else
        return -EFAULT;   
	  break;
		
	case USB_MTP_FUNC_IOC_GET_DEVICE_STATUS_SET:
		 mtp_debug("USB_MTP_FUNC_IOC_GET_DEVICE_STATUS_SET status = %d\n", g_bRequest);
         ret = copy_from_user (&g_mtp_get_status, (void __user *)arg, sizeof(g_mtp_get_status));
         if(ret < 0)
           return -EFAULT;

         if(req == NULL)
         {
           mtp_debug("LG_FW :: req is NULL");
           return -EFAULT;
         }
		 lg_mtp_debug("LG_FW : MTP SET DEVICE STATUS App => Device [0x%x]!!\n",arg);
         *((u16 *)(req->buf)) = 0x0004;
         *((u16 *)(req->buf + 2)) = arg;
		 req->zero = 0;
		 req->length = 6;
         usb_ep_queue(ep0,req, GFP_ATOMIC);
		 
		 if(arg == 0x2001)
		 {
		   cancel_noti = 0;
		 }
		 break;
	                          
    default :
      mtp_debug("Invalid IOCTL  Processed!!\n");
      break; 
 	}  
  
	return 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;

}