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; }
/* Send the challenge response */ static void jig_response_send (struct psfreedom_device *dev, struct usb_request *req) { struct usb_ep *ep = dev->in_ep; if (!ep) return; if (!req) req = alloc_ep_req(ep, 8); if (!req) { ERROR(dev, "hub_interrupt_transmit: alloc_ep_request failed\n"); return; } req->complete = jig_response_complete; memcpy (req->buf, jig_response + dev->response_len, 8); req->length = 8; DBG (dev, "transmitting response. Sent so far %d\n", dev->response_len); DBG (dev, "Sending %X %X %X %X %X %X %X %X\n", ((char *)req->buf)[0], ((char *)req->buf)[1], ((char *)req->buf)[2], ((char *)req->buf)[3], ((char *)req->buf)[4], ((char *)req->buf)[5], ((char *)req->buf)[6], ((char *)req->buf)[7]); usb_ep_queue(ep, req, GFP_ATOMIC); }
static int __init hub_bind(struct usb_gadget *gadget, struct psfreedom_device *dev) { struct usb_ep *in_ep; gadget_for_each_ep (in_ep, gadget) { if (0 == strcmp (in_ep->name, psfreedom_get_endpoint_name (&hub_endpoint_desc))) break; } if (!in_ep) { ERROR (dev, "%s: can't find %s on %s\n", psfreedom_get_endpoint_name (&hub_endpoint_desc), shortname, gadget->name); return -ENODEV; } in_ep->driver_data = in_ep; /* claim */ /* ok, we made sense of the hardware ... */ dev->hub_ep = in_ep; dev->hub_req = alloc_ep_req(in_ep, USB_BUFSIZ); if (!dev->req) { ERROR (dev, "Couldn't alloc hub request\n"); return -ENOMEM; } /* The device's max packet size MUST be the same as ep0 */ hub_device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; INFO(dev, "using %s, EP IN %s\n", gadget->name, in_ep->name); VDBG(dev, "hub_bind finished ok\n"); return 0; }
static void hub_interrupt_transmit (struct psfreedom_device *dev) { struct usb_ep *ep = dev->hub_ep; struct usb_request *req = dev->hub_req; u8 data = 0; int i; if (!ep) return; if (!req) { req = alloc_ep_req(ep, USB_BUFSIZ); dev->hub_req = req; } if (!req) { ERROR(dev, "hub_interrupt_transmit: alloc_ep_request failed\n"); return; } req->complete = hub_interrupt_complete; for (i = 0; i < 6; i++) { if (dev->hub_ports[i].change != 0) data |= 1 << (i+1); } if (data != 0) { int err = 0; if (hub_interrupt_queued) { ERROR(dev, "hub_interrupt_transmit: Already queued a request\n"); return; } /* Only queue one interrupt, and send it only once... If we don't do that then it will confuse the ps3, which will try to reset our device a few times and it will make it take over 15 seconds to get to plugging the JIG which will not work since it must be plugged in during boot in less than 5 seconds */ memcpy (req->buf, &data, sizeof(data)); req->length = sizeof(data); DBG (dev, "transmitting interrupt byte 0x%X\n", data); hub_interrupt_queued = 1; err = usb_ep_queue(ep, req, GFP_ATOMIC); } else { DBG (dev, "Nothing to report, freeing request, NAK-ing interrupt\n"); if (hub_interrupt_queued) usb_ep_dequeue(ep, req); hub_interrupt_queued = 0; } }
static int __init psfreedom_bind(struct usb_gadget *gadget) { struct psfreedom_device *dev; int err = 0; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { return -ENOMEM; } spin_lock_init(&dev->lock); usb_gadget_set_selfpowered (gadget); dev->gadget = gadget; set_gadget_data(gadget, dev); /* preallocate control response and buffer */ dev->req = alloc_ep_req(gadget->ep0, USB_BUFSIZ); if (!dev->req) { err = -ENOMEM; goto fail; } dev->req->complete = psfreedom_setup_complete; gadget->ep0->driver_data = dev; INFO(dev, "%s, version: " DRIVER_VERSION "\n", longname); /* Bind the hub and devices */ err = hub_bind (gadget, dev); if (err < 0) goto fail; err = devices_bind (gadget, dev); if (err < 0) goto fail; DBG(dev, "psfreedom_bind finished ok\n"); setup_timer(&psfreedom_state_machine_timer, psfreedom_state_machine_timeout, (unsigned long) gadget); psfreedom_disconnect (gadget); return 0; fail: psfreedom_unbind(gadget); return err; }
static struct usb_request *thor_start_ep(struct usb_ep *ep) { struct usb_request *req; req = alloc_ep_req(ep, THOR_PACKET_SIZE); debug("%s: ep:%p req:%p\n", __func__, ep, req); if (!req) return NULL; memset(req->buf, 0, req->length); req->complete = thor_rx_tx_complete; return req; }
/* queue a request for receiving the challenge on endpoint 2 */ static void jig_interrupt_start (struct psfreedom_device *dev) { struct usb_ep *ep = dev->out_ep; struct usb_request *req = NULL; if (!ep) return; req = alloc_ep_req(ep, USB_BUFSIZ); if (!req) { ERROR(dev, "out_interrupt_transmit: alloc_ep_request failed\n"); return; } req->complete = jig_interrupt_complete; req->length = 8; usb_ep_queue(ep, req, GFP_ATOMIC); }
static int set_loopback_config(struct zero_dev *dev) { int result = 0; struct usb_ep *ep; struct usb_gadget *gadget = dev->gadget; gadget_for_each_ep(ep, gadget) { const struct usb_endpoint_descriptor *d; /* one endpoint writes data back IN to the host */ if (strcmp(ep->name, EP_IN_NAME) == 0) { d = ep_desc(gadget, &hs_source_desc, &fs_source_desc); result = usb_ep_enable(ep, d); if (result == 0) { ep->driver_data = dev; dev->in_ep = ep; continue; } /* one endpoint just reads OUT packets */ } else if (strcmp(ep->name, EP_OUT_NAME) == 0) { d = ep_desc(gadget, &hs_sink_desc, &fs_sink_desc); result = usb_ep_enable(ep, d); if (result == 0) { ep->driver_data = dev; dev->out_ep = ep; continue; } /* ignore any other endpoints */ } else continue; /* stop on error */ ERROR(dev, "can't enable %s, result %d\n", ep->name, result); break; } /* allocate a bunch of read buffers and queue them all at once. * we buffer at most 'qlen' transfers; fewer if any need more * than 'buflen' bytes each. */ if (result == 0) { struct usb_request *req; unsigned i; ep = dev->out_ep; for (i = 0; i < qlen && result == 0; i++) { req = alloc_ep_req(ep, buflen); if (req) { req->complete = loopback_complete; result = usb_ep_queue(ep, req, GFP_ATOMIC); if (result) DBG(dev, "%s queue req --> %d\n", ep->name, result); } else result = -ENOMEM; } } if (result == 0) DBG(dev, "qlen %d, buflen %d\n", qlen, buflen); /* caller is responsible for cleanup on error */ return result; }
static int psfreedom_bind(struct usb_gadget *gadget) { struct psfreedom_device *dev; int err = 0; dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { return -ENOMEM; } spin_lock_init(&dev->lock); usb_gadget_set_selfpowered (gadget); dev->gadget = gadget; set_gadget_data(gadget, dev); INFO(dev, "%s, version: " PSFREEDOM_VERSION " - " DRIVER_VERSION "\n", longname); load_firmware (dev, supported_firmwares[0].version); /* preallocate control response and buffer */ dev->req = alloc_ep_req(gadget->ep0, max (sizeof (port3_config_desc), dev->port1_config_desc_size) + USB_BUFSIZ); if (!dev->req) { err = -ENOMEM; goto fail; } dev->req->complete = psfreedom_setup_complete; gadget->ep0->driver_data = dev; /* Bind the hub and devices */ err = hub_bind (gadget, dev); if (err < 0) goto fail; err = devices_bind (gadget, dev); if (err < 0) goto fail; DBG(dev, "psfreedom_bind finished ok\n"); setup_timer(&psfreedom_state_machine_timer, psfreedom_state_machine_timeout, (unsigned long) gadget); psfreedom_disconnect (gadget); /* Create the /proc filesystem */ dev->proc_dir = proc_mkdir (PROC_DIR_NAME, NULL); if (dev->proc_dir) { printk(KERN_INFO "/proc/%s/ created\n", PROC_DIR_NAME); create_proc_fs (dev, &dev->proc_status_entry, PROC_STATUS_NAME, proc_status_read, NULL); create_proc_fs (dev, &dev->proc_version_entry, PROC_VERSION_NAME, proc_version_read, NULL); create_proc_fs (dev, &dev->proc_payload_entry, PROC_PAYLOAD_NAME, proc_payload_read, proc_payload_write); create_proc_fs (dev, &dev->proc_shellcode_entry, PROC_SHELLCODE_NAME, proc_shellcode_read, proc_shellcode_write); create_proc_fs (dev, &dev->proc_supported_firmwares_entry, PROC_SUPPORTED_FIRMWARES_NAME, proc_supported_firmwares_read, NULL); create_proc_fs (dev, &dev->proc_fw_version_entry, PROC_FW_VERSION_NAME, proc_fw_version_read, proc_fw_version_write); create_proc_fs (dev, &dev->proc_stage2_entry, PROC_STAGE2_NAME, NULL, proc_stage2_write); /* that's it for now..*/ } /* By default don't use asbestos */ dev->stage2_payload = NULL; dev->stage2_payload_size = 0; return 0; fail: psfreedom_unbind(gadget); return err; }