diff options
Diffstat (limited to 'qemu/roms/SLOF/lib/libusb/usb-core.c')
-rw-r--r-- | qemu/roms/SLOF/lib/libusb/usb-core.c | 559 |
1 files changed, 0 insertions, 559 deletions
diff --git a/qemu/roms/SLOF/lib/libusb/usb-core.c b/qemu/roms/SLOF/lib/libusb/usb-core.c deleted file mode 100644 index 4c720ce2f..000000000 --- a/qemu/roms/SLOF/lib/libusb/usb-core.c +++ /dev/null @@ -1,559 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2013 IBM Corporation - * All rights reserved. - * This program and the accompanying materials - * are made available under the terms of the BSD License - * which accompanies this distribution, and is available at - * http://www.opensource.org/licenses/bsd-license.php - * - * Contributors: - * IBM Corporation - initial implementation - *****************************************************************************/ - -#include <string.h> -#include "usb-core.h" - -#undef DEBUG -//#define DEBUG -#ifdef DEBUG -#define dprintf(_x ...) do { printf(_x); } while(0) -#else -#define dprintf(_x ...) -#endif - -#define __unused __attribute__((unused)) - -struct usb_hcd_ops *head; -struct usb_dev *devpool; -#define USB_DEVPOOL_SIZE 4096 - -static struct usb_dev *usb_alloc_devpool(void) -{ - struct usb_dev *head, *curr, *prev; - unsigned int dev_count = 0, i; - - head = SLOF_alloc_mem(USB_DEVPOOL_SIZE); - if (!head) - return NULL; - - dev_count = USB_DEVPOOL_SIZE/sizeof(struct usb_dev); - dprintf("%s: %d number of devices\n", __func__, dev_count); - /* Although an array, link them*/ - for (i = 0, curr = head, prev = NULL; i < dev_count; i++, curr++) { - if (prev) - prev->next = curr; - curr->next = NULL; - prev = curr; - } - -#ifdef DEBUG - for (i = 0, curr = head; curr; curr = curr->next) - printf("%s: %d dev %p\n", __func__, i++, curr); -#endif - - return head; -} - -struct usb_dev *usb_devpool_get(void) -{ - struct usb_dev *new; - - if (!devpool) { - devpool = usb_alloc_devpool(); - if (!devpool) - return NULL; - } - - new = devpool; - devpool = devpool->next; - memset(new, 0, sizeof(*new)); - new->next = NULL; - return new; -} - -void usb_devpool_put(struct usb_dev *dev) -{ - struct usb_dev *curr; - if (!dev && !devpool) - return; - - curr = devpool; - while (curr->next) - curr = curr->next; - curr->next = dev; - dev->next = NULL; -} - -#ifndef DEBUG -#define validate_hcd_ops(dev) (dev && dev->hcidev && dev->hcidev->ops) -#else -int validate_hcd_ops(struct usb_dev *dev) -{ - int ret = true; - - if (!dev) { - printf("dev is NULL\n"); - ret = false; - } else if (!dev->hcidev) { - printf("hcidev is NULL\n"); - ret = false; - } else if (!dev->hcidev->ops) { - printf("ops is NULL\n"); - ret = false; - } - return ret; -} -#endif - -struct usb_pipe *usb_get_pipe(struct usb_dev *dev, struct usb_ep_descr *ep, - char *buf, size_t len) -{ - if (validate_hcd_ops(dev) && dev->hcidev->ops->get_pipe) - return dev->hcidev->ops->get_pipe(dev, ep, buf, len); - else { - printf("%s: Failed\n", __func__); - return NULL; - } -} - -void usb_put_pipe(struct usb_pipe *pipe) -{ - struct usb_dev *dev = NULL; - if (pipe && pipe->dev) { - dev = pipe->dev; - if (validate_hcd_ops(dev) && dev->hcidev->ops->put_pipe) - dev->hcidev->ops->put_pipe(pipe); - } -} - -int usb_poll_intr(struct usb_pipe *pipe, uint8_t *buf) -{ - struct usb_dev *dev = NULL; - if (pipe && pipe->dev) { - dev = pipe->dev; - if (validate_hcd_ops(dev) && dev->hcidev->ops->poll_intr) - return dev->hcidev->ops->poll_intr(pipe, buf); - } - return 0; -} - -void usb_hcd_register(struct usb_hcd_ops *ops) -{ - struct usb_hcd_ops *list; - - if (!ops) - printf("Error"); - dprintf("Registering %s %d\n", ops->name, ops->usb_type); - - if (head) { - list = head; - while (list->next) - list = list->next; - list->next = ops; - } else - head = ops; -} - -void usb_hcd_init(void *hcidev) -{ - struct usb_hcd_dev *dev = hcidev; - struct usb_hcd_ops *list = head; - - if (!dev) { - printf("Device Error"); - return; - } - - while (list) { - if (list->usb_type == dev->type) { - dprintf("usb_ops(%p) for the controller found\n", list); - dev->ops = list; - dev->ops->init(dev); - return; - } - list = list->next; - } - - dprintf("usb_ops for the controller not found\n"); -} - -void usb_hcd_exit(void *_hcidev) -{ - struct usb_hcd_dev *hcidev = _hcidev; - - dprintf("%s: enter \n", __func__); - if (!hcidev) { - printf("Device Error"); - return; - } - - if (hcidev->ops->exit) - hcidev->ops->exit(hcidev); -} - -int usb_send_ctrl(struct usb_pipe *pipe, struct usb_dev_req *req, void *data) -{ - struct usb_dev *dev = NULL; - if (!pipe) - return false; - dev = pipe->dev; - if (validate_hcd_ops(dev) && dev->hcidev->ops->send_ctrl) - return dev->hcidev->ops->send_ctrl(pipe, req, data); - else { - printf("%s: Failed\n", __func__); - return false; - } -} - -int usb_transfer_ctrl(void *dev, void *req, void *data) -{ - struct usb_pipe *pipe = NULL; - struct usb_dev *usbdev; - - if (!dev) - return false; - usbdev = (struct usb_dev *)dev; - pipe = usbdev->control; - return usb_send_ctrl(pipe, req, data); -} - -int usb_transfer_bulk(void *dev, int dir, void *td, void *td_phys, void *data, int size) -{ - struct usb_pipe *pipe = NULL; - struct usb_dev *usbdev; - - if (!dev) - return false; - usbdev = (struct usb_dev *)dev; - pipe = (dir == USB_PIPE_OUT) ? usbdev->bulk_out : usbdev->bulk_in; - if (!pipe) - return false; - if (validate_hcd_ops(usbdev) && usbdev->hcidev->ops->transfer_bulk) - return usbdev->hcidev->ops->transfer_bulk(pipe, td, td_phys, data, size); - else { - printf("%s: Failed\n", __func__); - return false; - } -} - -/* - * USB Specification 1.1 - * 9.3 USB Device Requests - * 9.4 Standard Device Requests - */ -static int usb_set_address(struct usb_dev *dev, uint32_t port) -{ - struct usb_dev_req req; - struct usb_hcd_dev *hcidev; - - if (!dev) - return false; - - hcidev = dev->hcidev; - req.bmRequestType = 0; - req.bRequest = REQ_SET_ADDRESS; - req.wIndex = 0; - req.wLength = 0; - req.wValue = cpu_to_le16((uint16_t)(hcidev->nextaddr)); - if (usb_send_ctrl(dev->control, &req, NULL)) { - dev->addr = hcidev->nextaddr++; - return true; - } else - return false; -} - -static int usb_get_device_descr(struct usb_dev *dev, void *data, size_t size) -{ - struct usb_dev_req req; - - if (!dev) - return false; - - req.bmRequestType = 0x80; - req.bRequest = REQ_GET_DESCRIPTOR; - req.wIndex = 0; - req.wLength = cpu_to_le16((uint16_t) size); - req.wValue = cpu_to_le16(DESCR_TYPE_DEVICE << 8); - return usb_send_ctrl(dev->control, &req, data); -} - -static int usb_get_config_descr(struct usb_dev *dev, void *data, size_t size) -{ - struct usb_dev_req req; - - if (!dev) - return false; - - req.bmRequestType = 0x80; - req.bRequest = REQ_GET_DESCRIPTOR; - req.wIndex = 0; - req.wLength = cpu_to_le16((uint16_t) size); - req.wValue = cpu_to_le16(DESCR_TYPE_CONFIGURATION << 8); - return usb_send_ctrl(dev->control, &req, data); - -} - -static int usb_set_config(struct usb_dev *dev, uint8_t cfg_value) -{ - struct usb_dev_req req; - - if (!dev) - return false; - - req.bmRequestType = 0x00; - req.bRequest = REQ_SET_CONFIGURATION; - req.wIndex = 0; - req.wLength = 0; - req.wValue = cpu_to_le16(0x00FF & cfg_value); - return usb_send_ctrl(dev->control, &req, NULL); -} - -static int usb_clear_halt(struct usb_pipe *pipe) -{ - struct usb_dev_req req; - struct usb_dev *dev; - - if (pipe && pipe->dev) { - dev = pipe->dev; - dprintf("Clearing port %d dir %d type %d\n", - pipe->epno, pipe->dir, pipe->type); - req.bmRequestType = REQT_DIR_OUT | REQT_REC_EP; - req.bRequest = REQ_CLEAR_FEATURE; - req.wValue = FEATURE_ENDPOINT_HALT; - req.wIndex = cpu_to_le16(pipe->epno | pipe->dir); - req.wLength = 0; - return usb_send_ctrl(dev->control, &req, NULL); - } - return false; -} - -int usb_dev_populate_pipe(struct usb_dev *dev, struct usb_ep_descr *ep, - void *buf, size_t len) -{ - uint8_t dir, type; - - dir = (ep->bEndpointAddress & 0x80) >> 7; - type = ep->bmAttributes & USB_EP_TYPE_MASK; - - dprintf("EP: %s: %d size %d type %d\n", dir ? "IN " : "OUT", - ep->bEndpointAddress & 0xF, le16_to_cpu(ep->wMaxPacketSize), - type); - if (type == USB_EP_TYPE_BULK) { - if (dir) - dev->bulk_in = usb_get_pipe(dev, ep, buf, len); - else - dev->bulk_out = usb_get_pipe(dev, ep, buf, len); - } else if (type == USB_EP_TYPE_INTR) - dev->intr = usb_get_pipe(dev, ep, buf, len); - - return true; -} - -static void usb_dev_copy_epdesc(struct usb_dev *dev, struct usb_ep_descr *ep) -{ - uint32_t ep_cnt; - - ep_cnt = dev->ep_cnt; - if (ep_cnt < USB_DEV_EP_MAX) - memcpy((void *)&dev->ep[ep_cnt], ep, sizeof(*ep)); - else - dprintf("usb-core: only %d EPs supported\n", USB_DEV_EP_MAX); - dev->ep_cnt++; -} - -int usb_hid_init(void *vdev) -{ - struct usb_dev *dev; - dev = (struct usb_dev *) vdev; - if (!dev) - return false; - if (dev->class == DEV_HID_KEYB) - usb_hid_kbd_init(dev); - return true; -} - -int usb_hid_exit(void *vdev) -{ - struct usb_dev *dev; - dev = (struct usb_dev *) vdev; - if (!dev) - return false; - if (dev->class == DEV_HID_KEYB) - usb_hid_kbd_exit(dev); - return true; -} - -int usb_msc_init(void *vdev) -{ - struct usb_dev *dev; - int i; - - dev = (struct usb_dev *) vdev; - dprintf("%s: enter %x\n", __func__, dev->class); - if (!dev) - return false; - if (usb_get_intf_class(dev->class) == 8) { - for (i = 0; i < dev->ep_cnt; i++) { - if ((dev->ep[i].bmAttributes & USB_EP_TYPE_MASK) - == USB_EP_TYPE_BULK) - usb_dev_populate_pipe(dev, &dev->ep[i], NULL, 0); - } - } - return true; -} - -int usb_msc_exit(void *vdev) -{ - struct usb_dev *dev; - dev = (struct usb_dev *) vdev; - dprintf("%s: enter %x\n", __func__, dev->class); - if (!dev) - return false; - if (usb_get_intf_class(dev->class) == 8) { - if (dev->bulk_in) - usb_put_pipe(dev->bulk_in); - if (dev->bulk_out) - usb_put_pipe(dev->bulk_out); - } - return true; -} - -int usb_msc_reset(struct usb_dev *dev) -{ - struct usb_dev_req req; - - if (!dev) - return false; - - req.bmRequestType = REQT_TYPE_CLASS | REQT_REC_INTERFACE | REQT_DIR_OUT; - req.bRequest = 0xFF; - req.wLength = 0; - req.wValue = 0; - req.wIndex = cpu_to_le16(dev->intf_num); - return usb_send_ctrl(dev->control, &req, NULL); -} - -void usb_msc_resetrecovery(struct usb_dev *dev) -{ - // usb_msc_reset(dev); - usb_clear_halt(dev->bulk_in); - usb_clear_halt(dev->bulk_out); - SLOF_msleep(2); -} - -static int usb_handle_device(struct usb_dev *dev, struct usb_dev_config_descr *cfg, - uint8_t *ptr, uint16_t len) -{ - struct usb_dev_intf_descr *intf = NULL; - struct usb_ep_descr *ep = NULL; - struct usb_dev_hid_descr *hid __unused = NULL; - uint8_t desc_len, desc_type; - - len -= sizeof(struct usb_dev_config_descr); - ptr = (uint8_t *)(ptr + sizeof(struct usb_dev_config_descr)); - - while (len > 0) { - desc_len = *ptr; - desc_type = *(ptr + 1); - switch (desc_type) { - case DESCR_TYPE_INTERFACE: - intf = (struct usb_dev_intf_descr *)ptr; - dev->class = intf->bInterfaceClass << 16 | - intf->bInterfaceSubClass << 8 | - intf->bInterfaceProtocol; - break; - case DESCR_TYPE_ENDPOINT: - ep = (struct usb_ep_descr *)ptr; - dev->intf_num = intf->bInterfaceNumber; - usb_dev_copy_epdesc(dev, ep); - break; - case DESCR_TYPE_HID: - hid = (struct usb_dev_hid_descr *)ptr; - dprintf("hid-report %d size %d\n", - hid->bReportType, le16_to_cpu(hid->wReportLength)); - break; - case DESCR_TYPE_HUB: - break; - default: - dprintf("ptr %p desc_type %d\n", ptr, desc_type); - } - ptr += desc_len; - len -= desc_len; - } - return true; -} - -int usb_setup_new_device(struct usb_dev *dev, unsigned int port) -{ - struct usb_dev_descr descr; - struct usb_dev_config_descr cfg; - struct usb_ep_descr ep; - uint16_t len; - void *data = NULL; - - dprintf("usb: %s - port %d\n", __func__, port); - - dev->addr = 0; - dev->port = port; - ep.bEndpointAddress = 0; - ep.bmAttributes = USB_EP_TYPE_CONTROL; - ep.wMaxPacketSize = cpu_to_le16(8); - dev->control = usb_get_pipe(dev, &ep, NULL, 0); - - if (!usb_get_device_descr(dev, &descr, 8)) - goto fail; - dev->control->mps = descr.bMaxPacketSize0; - - /* - * For USB3.0 ADDRESS-SLOT command takes care of setting - * address, skip this during generic device setup for USB3.0 - * devices - */ - if (dev->speed != USB_SUPER_SPEED) { - /* - * Qemu starts the port number from 1 which was - * revealed in bootindex and resulted in mismatch for - * storage devices names. Adjusting this here for - * compatibility. - */ - dev->port = port + 1; - if(!usb_set_address(dev, dev->port)) - goto fail; - } - mb(); - SLOF_msleep(100); - - if (!usb_get_device_descr(dev, &descr, sizeof(struct usb_dev_descr))) - goto fail; - - if (!usb_get_config_descr(dev, &cfg, sizeof(struct usb_dev_config_descr))) - goto fail; - - len = le16_to_cpu(cfg.wTotalLength); - /* No device config descriptor present */ - if (len == sizeof(struct usb_dev_config_descr)) - goto fail; - - data = SLOF_dma_alloc(len); - if (!data) { - printf("%s: alloc failed %d\n", __func__, port); - goto fail; - } - - if (!usb_get_config_descr(dev, data, len)) - goto fail_mem_free; - if (!usb_set_config(dev, cfg.bConfigurationValue)) - goto fail_mem_free; - mb(); - SLOF_msleep(100); - - if (!usb_handle_device(dev, &cfg, data, len)) - goto fail_mem_free; - - SLOF_dma_free(data, len); - return true; -fail_mem_free: - SLOF_dma_free(data, len); -fail: - return false; -} |