summaryrefslogtreecommitdiffstats
path: root/qemu/roms/SLOF/lib/libusb/usb-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/SLOF/lib/libusb/usb-core.c')
-rw-r--r--qemu/roms/SLOF/lib/libusb/usb-core.c559
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;
-}