static void /* __init_or_exit */ psfreedom_unbind(struct usb_gadget *gadget) { struct psfreedom_device *dev = get_gadget_data(gadget); INFO (dev, "unbind\n"); if (timer_added) del_timer (&psfreedom_state_machine_timer); timer_added = 0; /* we've already been disconnected ... no i/o is active */ if (dev) { if (dev->port1_config_desc) kfree(dev->port1_config_desc); if (dev->req) free_ep_req(gadget->ep0, dev->req); if (dev->hub_req) free_ep_req(dev->hub_ep, dev->hub_req); if (dev->proc_status_entry) remove_proc_entry(PROC_STATUS_NAME, dev->proc_dir); if (dev->proc_version_entry) remove_proc_entry(PROC_VERSION_NAME, dev->proc_dir); if (dev->proc_payload_entry) remove_proc_entry(PROC_PAYLOAD_NAME, dev->proc_dir); if (dev->proc_shellcode_entry) remove_proc_entry(PROC_SHELLCODE_NAME, dev->proc_dir); if (dev->proc_dir) remove_proc_entry(PROC_DIR_NAME, NULL); kfree(dev); set_gadget_data(gadget, NULL); } }
static struct usb_request *source_sink_start_ep(struct usb_ep *ep) { struct usb_request *req; int status; req = alloc_ep_req(ep, buflen); if (!req) return NULL; memset(req->buf, 0, req->length); req->complete = source_sink_complete; if (strcmp(ep->name, EP_IN_NAME) == 0) reinit_write_data(ep, req); else memset(req->buf, 0x55, req->length); status = usb_ep_queue(ep, req, GFP_ATOMIC); if (status) { struct zero_dev *dev = ep->driver_data; ERROR(dev, "start %s --> %d\n", ep->name, status); free_ep_req(ep, req); req = NULL; } return req; }
static void thor_func_disable(struct usb_function *f) { struct f_thor *f_thor = func_to_thor(f); struct thor_dev *dev = f_thor->dev; debug("%s:\n", __func__); /* Avoid freeing memory when ep is still claimed */ if (dev->in_ep->driver_data) { free_ep_req(dev->in_ep, dev->in_req); usb_ep_disable(dev->in_ep); dev->in_ep->driver_data = NULL; } if (dev->out_ep->driver_data) { if (out_req_buf) free(out_req_buf); dev->out_req->buf = NULL; usb_ep_free_request(dev->out_ep, dev->out_req); usb_ep_disable(dev->out_ep); dev->out_ep->driver_data = NULL; } if (dev->int_ep->driver_data) { usb_ep_disable(dev->int_ep); dev->int_ep->driver_data = NULL; } }
static void zero_unbind(struct usb_gadget *gadget) { struct zero_dev *dev = get_gadget_data(gadget); DBG(dev, "unbind\n"); /* we've already been disconnected ... no i/o is active */ if (dev->req) { dev->req->length = USB_BUFSIZ; free_ep_req(gadget->ep0, dev->req); } del_timer_sync(&dev->resume); kfree(dev); set_gadget_data(gadget, NULL); }
static void loopback_complete(struct usb_ep *ep, struct usb_request *req) { struct zero_dev *dev = ep->driver_data; int status = req->status; switch (status) { case 0: /* normal completion? */ if (ep == dev->out_ep) { /* loop this OUT packet back IN to the host */ req->zero = (req->actual < req->length); req->length = req->actual; status = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC); if (status == 0) return; /* "should never get here" */ ERROR(dev, "can't loop %s to %s: %d\n", ep->name, dev->in_ep->name, status); } /* queue the buffer for some later OUT packet */ req->length = buflen; status = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC); if (status == 0) return; /* "should never get here" */ /* FALLTHROUGH */ default: ERROR(dev, "%s loop complete --> %d, %d/%d\n", ep->name, status, req->actual, req->length); /* FALLTHROUGH */ /* NOTE: since this driver doesn't maintain an explicit record * of requests it submitted (just maintains qlen count), we * rely on the hardware driver to clean up on disconnect or * endpoint disable. */ case -ECONNABORTED: /* hardware forced ep reset */ case -ECONNRESET: /* request dequeued */ case -ESHUTDOWN: /* disconnect from host */ free_ep_req(ep, req); return; } }
/* if there is only one request in the queue, there'll always be an * irq delay between end of one request and start of the next. * that prevents using hardware dma queues. */ static void source_sink_complete(struct usb_ep *ep, struct usb_request *req) { struct zero_dev *dev = ep->driver_data; int status = req->status; switch (status) { case 0: /* normal completion? */ if (ep == dev->out_ep) { check_read_data(dev, ep, req); memset(req->buf, 0x55, req->length); } else reinit_write_data(ep, req); break; /* this endpoint is normally active while we're configured */ case -ECONNABORTED: /* hardware forced ep reset */ case -ECONNRESET: /* request dequeued */ case -ESHUTDOWN: /* disconnect from host */ VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status, req->actual, req->length); if (ep == dev->out_ep) check_read_data(dev, ep, req); free_ep_req(ep, req); return; case -EOVERFLOW: /* buffer overrun on read means that * we didn't provide a big enough * buffer. */ default: #if 1 DBG(dev, "%s complete --> %d, %d/%d\n", ep->name, status, req->actual, req->length); #endif case -EREMOTEIO: /* short read */ break; } status = usb_ep_queue(ep, req, GFP_ATOMIC); if (status) { ERROR(dev, "kill %s: resubmit %d bytes --> %d\n", ep->name, req->length, status); usb_ep_set_halt(ep); /* FIXME recover later ... somehow */ } }
static void /* __init_or_exit */ psfreedom_unbind(struct usb_gadget *gadget) { struct psfreedom_device *dev = get_gadget_data(gadget); DBG(dev, "unbind\n"); if (timer_added) del_timer (&psfreedom_state_machine_timer); timer_added = 0; /* we've already been disconnected ... no i/o is active */ if (dev) { if (dev->req) { dev->req->length = USB_BUFSIZ; free_ep_req(gadget->ep0, dev->req); } kfree(dev); set_gadget_data(gadget, NULL); } }