free(ci_req);
}
+static void request_complete(struct usb_ep *ep, struct ci_req *req, int status)
+{
+ if (req->req.status == -EINPROGRESS)
+ req->req.status = status;
+
+ DBG("%s: req %p complete: status %d, actual %u\n",
+ ep->name, req, req->req.status, req->req.actual);
+
+ req->req.complete(ep, &req->req);
+}
+
+static void request_complete_list(struct usb_ep *ep, struct list_head *list, int status)
+{
+ struct ci_req *req, *tmp_req;
+
+ list_for_each_entry_safe(req, tmp_req, list, queue) {
+ list_del_init(&req->queue);
+ request_complete(ep, req, status);
+ }
+}
+
static void ep_enable(int num, int in, int maxpacket)
{
struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
int num, in;
num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
in = (desc->bEndpointAddress & USB_DIR_IN) != 0;
+
+ if (ci_ep->desc) {
+ DBG("%s: endpoint num %d in %d already enabled\n", __func__, num, in);
+ return -EBUSY;
+ }
+
ci_ep->desc = desc;
ep->desc = desc;
static int ci_ep_disable(struct usb_ep *ep)
{
struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep);
+ LIST_HEAD(req_list);
int num, in, err;
+ if (!ci_ep->desc) {
+ DBG("%s: attempt to disable a not enabled yet endpoint\n", __func__);
+ err = -EBUSY;
+ goto nodesc;
+ }
+
num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0;
+ list_splice_init(&ci_ep->queue, &req_list);
+ request_complete_list(ep, &req_list, -ESHUTDOWN);
+
err = ep_disable(num, in);
if (err)
return err;
ci_ep->desc = NULL;
+ err = 0;
+
+nodesc:
ep->desc = NULL;
ci_ep->req_primed = false;
- return 0;
+ return err;
}
static int ci_bounce(struct ci_req *ci_req, int in)
int in, ret;
int __maybe_unused num;
+ if (!ci_ep->desc) {
+ DBG("%s: ci_ep->desc == NULL, nothing to do!\n", __func__);
+ return -EINVAL;
+ }
+
num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0;