usb: renesas_usbhs: add basic USB_REQ_GET_STATUS support
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Fri, 25 Nov 2011 01:28:04 +0000 (17:28 -0800)
committerFelipe Balbi <balbi@ti.com>
Mon, 12 Dec 2011 09:45:16 +0000 (11:45 +0200)
This patch adds basic get-status support for chapter 9 test.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/renesas_usbhs/mod_gadget.c

index 3130089eacff9db5f467f43f6c4419e797f9d677..812960ba95e15efd1a01b3d36e68f487c7b0ab5e 100644 (file)
@@ -304,6 +304,104 @@ struct usbhsg_recip_handle req_set_feature = {
        .endpoint       = usbhsg_recip_handler_std_set_endpoint,
 };
 
+/*
+ *             USB_TYPE_STANDARD / get status functions
+ */
+static void __usbhsg_recip_send_complete(struct usb_ep *ep,
+                                        struct usb_request *req)
+{
+       struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
+
+       /* free allocated recip-buffer/usb_request */
+       kfree(ureq->pkt.buf);
+       usb_ep_free_request(ep, req);
+}
+
+static void __usbhsg_recip_send_status(struct usbhsg_gpriv *gpriv,
+                                      unsigned short status)
+{
+       struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv);
+       struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(dcp);
+       struct device *dev = usbhsg_gpriv_to_dev(gpriv);
+       struct usb_request *req;
+       unsigned short *buf;
+
+       /* alloc new usb_request for recip */
+       req = usb_ep_alloc_request(&dcp->ep, GFP_ATOMIC);
+       if (!req) {
+               dev_err(dev, "recip request allocation fail\n");
+               return;
+       }
+
+       /* alloc recip data buffer */
+       buf = kmalloc(sizeof(*buf), GFP_ATOMIC);
+       if (!buf) {
+               usb_ep_free_request(&dcp->ep, req);
+               dev_err(dev, "recip data allocation fail\n");
+               return;
+       }
+
+       /* recip data is status */
+       *buf = cpu_to_le16(status);
+
+       /* allocated usb_request/buffer will be freed */
+       req->complete   = __usbhsg_recip_send_complete;
+       req->buf        = buf;
+       req->length     = sizeof(*buf);
+       req->zero       = 0;
+
+       /* push packet */
+       pipe->handler = &usbhs_fifo_pio_push_handler;
+       usbhsg_queue_push(dcp, usbhsg_req_to_ureq(req));
+}
+
+static int usbhsg_recip_handler_std_get_device(struct usbhs_priv *priv,
+                                              struct usbhsg_uep *uep,
+                                              struct usb_ctrlrequest *ctrl)
+{
+       struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
+       unsigned short status = 1 << USB_DEVICE_SELF_POWERED;
+
+       __usbhsg_recip_send_status(gpriv, status);
+
+       return 0;
+}
+
+static int usbhsg_recip_handler_std_get_interface(struct usbhs_priv *priv,
+                                                 struct usbhsg_uep *uep,
+                                                 struct usb_ctrlrequest *ctrl)
+{
+       struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
+       unsigned short status = 0;
+
+       __usbhsg_recip_send_status(gpriv, status);
+
+       return 0;
+}
+
+static int usbhsg_recip_handler_std_get_endpoint(struct usbhs_priv *priv,
+                                                struct usbhsg_uep *uep,
+                                                struct usb_ctrlrequest *ctrl)
+{
+       struct usbhsg_gpriv *gpriv = usbhsg_uep_to_gpriv(uep);
+       struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
+       unsigned short status = 0;
+
+       if (usbhs_pipe_is_stall(pipe))
+               status = 1 << USB_ENDPOINT_HALT;
+
+       __usbhsg_recip_send_status(gpriv, status);
+
+       return 0;
+}
+
+struct usbhsg_recip_handle req_get_status = {
+       .name           = "get status",
+       .device         = usbhsg_recip_handler_std_get_device,
+       .interface      = usbhsg_recip_handler_std_get_interface,
+       .endpoint       = usbhsg_recip_handler_std_get_endpoint,
+};
+
 /*
  *             USB_TYPE handler
  */
@@ -431,6 +529,9 @@ static int usbhsg_irq_ctrl_stage(struct usbhs_priv *priv,
                case USB_REQ_SET_FEATURE:
                        recip_handler = &req_set_feature;
                        break;
+               case USB_REQ_GET_STATUS:
+                       recip_handler = &req_get_status;
+                       break;
                }
        }