/*
 * QEMU USB emulation
 *
 * Copyright (c) 2005 Fabrice Bellard
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "qemu-common.h"
#include "usb.h"

void usb_attach(USBPort *port, USBDevice *dev)
{
    port->attach(port, dev);
}

/**********************/
/* generic USB device helpers (you are not forced to use them when
   writing your USB device driver, but they help handling the
   protocol)
*/

#define SETUP_STATE_IDLE 0
#define SETUP_STATE_DATA 1
#define SETUP_STATE_ACK  2

int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
{
    int l, ret = 0;
    int len = p->len;
    uint8_t *data = p->data;

    switch(p->pid) {
    case USB_MSG_ATTACH:
        s->state = USB_STATE_ATTACHED;
        break;
    case USB_MSG_DETACH:
        s->state = USB_STATE_NOTATTACHED;
        break;
    case USB_MSG_RESET:
        s->remote_wakeup = 0;
        s->addr = 0;
        s->state = USB_STATE_DEFAULT;
        s->handle_reset(s);
        break;
    case USB_TOKEN_SETUP:
        if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
            return USB_RET_NODEV;
        if (len != 8)
            goto fail;
        memcpy(s->setup_buf, data, 8);
        s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
        s->setup_index = 0;
        if (s->setup_buf[0] & USB_DIR_IN) {
            ret = s->handle_control(s,
                                    (s->setup_buf[0] << 8) | s->setup_buf[1],
                                    (s->setup_buf[3] << 8) | s->setup_buf[2],
                                    (s->setup_buf[5] << 8) | s->setup_buf[4],
                                    s->setup_len,
                                    s->data_buf);
            if (ret < 0)
                return ret;
            if (ret < s->setup_len)
                s->setup_len = ret;
            s->setup_state = SETUP_STATE_DATA;
        } else {
            if (s->setup_len == 0)
                s->setup_state = SETUP_STATE_ACK;
            else
                s->setup_state = SETUP_STATE_DATA;
        }
        break;
    case USB_TOKEN_IN:
        if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
            return USB_RET_NODEV;
        switch(p->devep) {
        case 0:
            switch(s->setup_state) {
            case SETUP_STATE_ACK:
                if (!(s->setup_buf[0] & USB_DIR_IN)) {
                    s->setup_state = SETUP_STATE_IDLE;
                    ret = s->handle_control(s,
                                      (s->setup_buf[0] << 8) | s->setup_buf[1],
                                      (s->setup_buf[3] << 8) | s->setup_buf[2],
                                      (s->setup_buf[5] << 8) | s->setup_buf[4],
                                      s->setup_len,
                                      s->data_buf);
                    if (ret > 0)
                        ret = 0;
                } else {
                    /* return 0 byte */
                }
                break;
            case SETUP_STATE_DATA:
                if (s->setup_buf[0] & USB_DIR_IN) {
                    l = s->setup_len - s->setup_index;
                    if (l > len)
                        l = len;
                    memcpy(data, s->data_buf + s->setup_index, l);
                    s->setup_index += l;
                    if (s->setup_index >= s->setup_len)
                        s->setup_state = SETUP_STATE_ACK;
                    ret = l;
                } else {
                    s->setup_state = SETUP_STATE_IDLE;
                    goto fail;
                }
                break;
            default:
                goto fail;
            }
            break;
        default:
            ret = s->handle_data(s, p);
            break;
        }
        break;
    case USB_TOKEN_OUT:
        if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
            return USB_RET_NODEV;
        switch(p->devep) {
        case 0:
            switch(s->setup_state) {
            case SETUP_STATE_ACK:
                if (s->setup_buf[0] & USB_DIR_IN) {
                    s->setup_state = SETUP_STATE_IDLE;
                    /* transfer OK */
                } else {
                    /* ignore additional output */
                }
                break;
            case SETUP_STATE_DATA:
                if (!(s->setup_buf[0] & USB_DIR_IN)) {
                    l = s->setup_len - s->setup_index;
                    if (l > len)
                        l = len;
                    memcpy(s->data_buf + s->setup_index, data, l);
                    s->setup_index += l;
                    if (s->setup_index >= s->setup_len)
                        s->setup_state = SETUP_STATE_ACK;
                    ret = l;
                } else {
                    s->setup_state = SETUP_STATE_IDLE;
                    goto fail;
                }
                break;
            default:
                goto fail;
            }
            break;
        default:
            ret = s->handle_data(s, p);
            break;
        }
        break;
    default:
    fail:
        ret = USB_RET_STALL;
        break;
    }
    return ret;
}

/* XXX: fix overflow */
int set_usb_string(uint8_t *buf, const char *str)
{
    int len, i;
    uint8_t *q;

    q = buf;
    len = strlen(str);
    *q++ = 2 * len + 2;
    *q++ = 3;
    for(i = 0; i < len; i++) {
        *q++ = str[i];
        *q++ = 0;
    }
    return q - buf;
}

/* Send an internal message to a USB device.  */
void usb_send_msg(USBDevice *dev, int msg)
{
    USBPacket p;
    memset(&p, 0, sizeof(p));
    p.pid = msg;
    dev->handle_packet(dev, &p);
}

