static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); struct usbhs_mod *mod = usbhs_mod_get_current(priv); struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv); struct device *dev = usbhs_priv_to_dev(priv); unsigned long flags; int ret = 0; /******************** spin lock ********************/ usbhs_lock(priv, flags); usbhsg_status_clr(gpriv, status); if (!usbhsg_status_has(gpriv, USBHSG_STATUS_STARTED) && !usbhsg_status_has(gpriv, USBHSG_STATUS_REGISTERD)) ret = -1; /* already done */ usbhs_unlock(priv, flags); /******************** spin unlock ********************/ if (ret < 0) return 0; /* already done is not error */ /* * disable interrupt and systems if 1st try */ usbhs_fifo_quit(priv); /* disable all irq */ mod->irq_dev_state = NULL; mod->irq_ctrl_stage = NULL; usbhs_irq_callback_update(priv, mod); gpriv->gadget.speed = USB_SPEED_UNKNOWN; /* disable sys */ usbhs_sys_set_test_mode(priv, 0); usbhs_sys_function_ctrl(priv, 0); usbhsg_ep_disable(&dcp->ep); dev_dbg(dev, "stop gadget\n"); return 0; }
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_irq_ctrl_stage(struct usbhs_priv *priv, struct usbhs_irq_state *irq_state) { struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); 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_ctrlrequest ctrl; struct usbhsg_recip_handle *recip_handler = NULL; int stage = usbhs_status_get_ctrl_stage(irq_state); int ret = 0; dev_dbg(dev, "stage = %d\n", stage); /* * see Manual * * "Operation" * - "Interrupt Function" * - "Control Transfer Stage Transition Interrupt" * - Fig. "Control Transfer Stage Transitions" */ switch (stage) { case READ_DATA_STAGE: dcp->handler = &usbhsg_handler_send_ctrl; break; case WRITE_DATA_STAGE: dcp->handler = &usbhsg_handler_recv_ctrl; break; case NODATA_STATUS_STAGE: dcp->handler = &usbhsg_handler_ctrl_stage_end; break; default: return ret; } /* * get usb request */ usbhs_usbreq_get_val(priv, &ctrl); switch (ctrl.bRequestType & USB_TYPE_MASK) { case USB_TYPE_STANDARD: switch (ctrl.bRequest) { case USB_REQ_CLEAR_FEATURE: recip_handler = &req_clear_feature; break; } } /* * setup stage / run recip */ if (recip_handler) ret = usbhsg_recip_run_handle(priv, recip_handler, &ctrl); else ret = gpriv->driver->setup(&gpriv->gadget, &ctrl); if (ret < 0) usbhs_fifo_stall(pipe); return ret; }