static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,

               int request, int value, int index, int length, uint8_t *data)

{

    USBHubState *s = (USBHubState *)dev;

    int ret;



    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);

    if (ret >= 0) {

        return ret;

    }



    switch(request) {

    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:

        if (value == 0 && index != 0x81) { /* clear ep halt */

            goto fail;

        }

        ret = 0;

        break;

    case DeviceRequest | USB_REQ_GET_INTERFACE:

        data[0] = 0;

        ret = 1;

        break;

    case DeviceOutRequest | USB_REQ_SET_INTERFACE:

        ret = 0;

        break;

        /* usb specific requests */

    case GetHubStatus:

        data[0] = 0;

        data[1] = 0;

        data[2] = 0;

        data[3] = 0;

        ret = 4;

        break;

    case GetPortStatus:

        {

            unsigned int n = index - 1;

            USBHubPort *port;

            if (n >= NUM_PORTS) {

                goto fail;

            }

            port = &s->ports[n];

            data[0] = port->wPortStatus;

            data[1] = port->wPortStatus >> 8;

            data[2] = port->wPortChange;

            data[3] = port->wPortChange >> 8;

            ret = 4;

        }

        break;

    case SetHubFeature:

    case ClearHubFeature:

        if (value == 0 || value == 1) {

        } else {

            goto fail;

        }

        ret = 0;

        break;

    case SetPortFeature:

        {

            unsigned int n = index - 1;

            USBHubPort *port;

            USBDevice *dev;

            if (n >= NUM_PORTS) {

                goto fail;

            }

            port = &s->ports[n];

            dev = port->port.dev;

            switch(value) {

            case PORT_SUSPEND:

                port->wPortStatus |= PORT_STAT_SUSPEND;

                break;

            case PORT_RESET:

                if (dev) {

                    usb_send_msg(dev, USB_MSG_RESET);

                    port->wPortChange |= PORT_STAT_C_RESET;

                    /* set enable bit */

                    port->wPortStatus |= PORT_STAT_ENABLE;

                }

                break;

            case PORT_POWER:

                break;

            default:

                goto fail;

            }

            ret = 0;

        }

        break;

    case ClearPortFeature:

        {

            unsigned int n = index - 1;

            USBHubPort *port;



            if (n >= NUM_PORTS) {

                goto fail;

            }

            port = &s->ports[n];

            switch(value) {

            case PORT_ENABLE:

                port->wPortStatus &= ~PORT_STAT_ENABLE;

                break;

            case PORT_C_ENABLE:

                port->wPortChange &= ~PORT_STAT_C_ENABLE;

                break;

            case PORT_SUSPEND:

                port->wPortStatus &= ~PORT_STAT_SUSPEND;

                break;

            case PORT_C_SUSPEND:

                port->wPortChange &= ~PORT_STAT_C_SUSPEND;

                break;

            case PORT_C_CONNECTION:

                port->wPortChange &= ~PORT_STAT_C_CONNECTION;

                break;

            case PORT_C_OVERCURRENT:

                port->wPortChange &= ~PORT_STAT_C_OVERCURRENT;

                break;

            case PORT_C_RESET:

                port->wPortChange &= ~PORT_STAT_C_RESET;

                break;

            default:

                goto fail;

            }

            ret = 0;

        }

        break;

    case GetHubDescriptor:

        {

            unsigned int n, limit, var_hub_size = 0;

            memcpy(data, qemu_hub_hub_descriptor,

                   sizeof(qemu_hub_hub_descriptor));

            data[2] = NUM_PORTS;



            /* fill DeviceRemovable bits */

            limit = ((NUM_PORTS + 1 + 7) / 8) + 7;

            for (n = 7; n < limit; n++) {

                data[n] = 0x00;

                var_hub_size++;

            }



            /* fill PortPwrCtrlMask bits */

            limit = limit + ((NUM_PORTS + 7) / 8);

            for (;n < limit; n++) {

                data[n] = 0xff;

                var_hub_size++;

            }



            ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size;

            data[0] = ret;

            break;

        }

    default:

    fail:

        ret = USB_RET_STALL;

        break;

    }

    return ret;

}

static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,

               int request, int value, int index, int length, uint8_t *data)

{

    USBHubState *s = (USBHubState *)dev;

    int ret;



    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);

    if (ret >= 0) {

        return ret;

    }



    switch(request) {

    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:

        if (value == 0 && index != 0x81) { 

            goto fail;

        }

        ret = 0;

        break;

    case DeviceRequest | USB_REQ_GET_INTERFACE:

        data[0] = 0;

        ret = 1;

        break;

    case DeviceOutRequest | USB_REQ_SET_INTERFACE:

        ret = 0;

        break;

        

    case GetHubStatus:

        data[0] = 0;

        data[1] = 0;

        data[2] = 0;

        data[3] = 0;

        ret = 4;

        break;

    case GetPortStatus:

        {

            unsigned int n = index - 1;

            USBHubPort *port;

            if (n >= NUM_PORTS) {

                goto fail;

            }

            port = &s->ports[n];

            data[0] = port->wPortStatus;

            data[1] = port->wPortStatus >> 8;

            data[2] = port->wPortChange;

            data[3] = port->wPortChange >> 8;

            ret = 4;

        }

        break;

    case SetHubFeature:

    case ClearHubFeature:

        if (value == 0 || value == 1) {

        } else {

            goto fail;

        }

        ret = 0;

        break;

    case SetPortFeature:

        {

            unsigned int n = index - 1;

            USBHubPort *port;

            USBDevice *dev;

            if (n >= NUM_PORTS) {

                goto fail;

            }

            port = &s->ports[n];

            dev = port->port.dev;

            switch(value) {

            case PORT_SUSPEND:

                port->wPortStatus |= PORT_STAT_SUSPEND;

                break;

            case PORT_RESET:

                if (dev) {

                    usb_send_msg(dev, USB_MSG_RESET);

                    port->wPortChange |= PORT_STAT_C_RESET;

                    

                    port->wPortStatus |= PORT_STAT_ENABLE;

                }

                break;

            case PORT_POWER:

                break;

            default:

                goto fail;

            }

            ret = 0;

        }

        break;

    case ClearPortFeature:

        {

            unsigned int n = index - 1;

            USBHubPort *port;



            if (n >= NUM_PORTS) {

                goto fail;

            }

            port = &s->ports[n];

            switch(value) {

            case PORT_ENABLE:

                port->wPortStatus &= ~PORT_STAT_ENABLE;

                break;

            case PORT_C_ENABLE:

                port->wPortChange &= ~PORT_STAT_C_ENABLE;

                break;

            case PORT_SUSPEND:

                port->wPortStatus &= ~PORT_STAT_SUSPEND;

                break;

            case PORT_C_SUSPEND:

                port->wPortChange &= ~PORT_STAT_C_SUSPEND;

                break;

            case PORT_C_CONNECTION:

                port->wPortChange &= ~PORT_STAT_C_CONNECTION;

                break;

            case PORT_C_OVERCURRENT:

                port->wPortChange &= ~PORT_STAT_C_OVERCURRENT;

                break;

            case PORT_C_RESET:

                port->wPortChange &= ~PORT_STAT_C_RESET;

                break;

            default:

                goto fail;

            }

            ret = 0;

        }

        break;

    case GetHubDescriptor:

        {

            unsigned int n, limit, var_hub_size = 0;

            memcpy(data, qemu_hub_hub_descriptor,

                   sizeof(qemu_hub_hub_descriptor));

            data[2] = NUM_PORTS;



            

            limit = ((NUM_PORTS + 1 + 7) / 8) + 7;

            for (n = 7; n < limit; n++) {

                data[n] = 0x00;

                var_hub_size++;

            }



            

            limit = limit + ((NUM_PORTS + 7) / 8);

            for (;n < limit; n++) {

                data[n] = 0xff;

                var_hub_size++;

            }



            ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size;

            data[0] = ret;

            break;

        }

    default:

    fail:

        ret = USB_RET_STALL;

        break;

    }

    return ret;

}

static int FUNC_0(USBDevice *VAR_0, USBPacket *VAR_1,

               int VAR_2, int VAR_3, int VAR_4, int VAR_5, uint8_t *VAR_6)

{

    USBHubState *s = (USBHubState *)VAR_0;

    int VAR_7;



    VAR_7 = usb_desc_handle_control(VAR_0, VAR_1, VAR_2, VAR_3, VAR_4, VAR_5, VAR_6);

    if (VAR_7 >= 0) {

        return VAR_7;

    }



    switch(VAR_2) {

    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:

        if (VAR_3 == 0 && VAR_4 != 0x81) { 

            goto fail;

        }

        VAR_7 = 0;

        break;

    case DeviceRequest | USB_REQ_GET_INTERFACE:

        VAR_6[0] = 0;

        VAR_7 = 1;

        break;

    case DeviceOutRequest | USB_REQ_SET_INTERFACE:

        VAR_7 = 0;

        break;

        

    case GetHubStatus:

        VAR_6[0] = 0;

        VAR_6[1] = 0;

        VAR_6[2] = 0;

        VAR_6[3] = 0;

        VAR_7 = 4;

        break;

    case GetPortStatus:

        {

            unsigned int VAR_9 = VAR_4 - 1;

            USBHubPort *port;

            if (VAR_9 >= NUM_PORTS) {

                goto fail;

            }

            port = &s->ports[VAR_9];

            VAR_6[0] = port->wPortStatus;

            VAR_6[1] = port->wPortStatus >> 8;

            VAR_6[2] = port->wPortChange;

            VAR_6[3] = port->wPortChange >> 8;

            VAR_7 = 4;

        }

        break;

    case SetHubFeature:

    case ClearHubFeature:

        if (VAR_3 == 0 || VAR_3 == 1) {

        } else {

            goto fail;

        }

        VAR_7 = 0;

        break;

    case SetPortFeature:

        {

            unsigned int VAR_9 = VAR_4 - 1;

            USBHubPort *port;

            USBDevice *VAR_0;

            if (VAR_9 >= NUM_PORTS) {

                goto fail;

            }

            port = &s->ports[VAR_9];

            VAR_0 = port->port.VAR_0;

            switch(VAR_3) {

            case PORT_SUSPEND:

                port->wPortStatus |= PORT_STAT_SUSPEND;

                break;

            case PORT_RESET:

                if (VAR_0) {

                    usb_send_msg(VAR_0, USB_MSG_RESET);

                    port->wPortChange |= PORT_STAT_C_RESET;

                    

                    port->wPortStatus |= PORT_STAT_ENABLE;

                }

                break;

            case PORT_POWER:

                break;

            default:

                goto fail;

            }

            VAR_7 = 0;

        }

        break;

    case ClearPortFeature:

        {

            unsigned int VAR_9 = VAR_4 - 1;

            USBHubPort *port;



            if (VAR_9 >= NUM_PORTS) {

                goto fail;

            }

            port = &s->ports[VAR_9];

            switch(VAR_3) {

            case PORT_ENABLE:

                port->wPortStatus &= ~PORT_STAT_ENABLE;

                break;

            case PORT_C_ENABLE:

                port->wPortChange &= ~PORT_STAT_C_ENABLE;

                break;

            case PORT_SUSPEND:

                port->wPortStatus &= ~PORT_STAT_SUSPEND;

                break;

            case PORT_C_SUSPEND:

                port->wPortChange &= ~PORT_STAT_C_SUSPEND;

                break;

            case PORT_C_CONNECTION:

                port->wPortChange &= ~PORT_STAT_C_CONNECTION;

                break;

            case PORT_C_OVERCURRENT:

                port->wPortChange &= ~PORT_STAT_C_OVERCURRENT;

                break;

            case PORT_C_RESET:

                port->wPortChange &= ~PORT_STAT_C_RESET;

                break;

            default:

                goto fail;

            }

            VAR_7 = 0;

        }

        break;

    case GetHubDescriptor:

        {

            unsigned int VAR_9, VAR_9, VAR_10 = 0;

            memcpy(VAR_6, qemu_hub_hub_descriptor,

                   sizeof(qemu_hub_hub_descriptor));

            VAR_6[2] = NUM_PORTS;



            

            VAR_9 = ((NUM_PORTS + 1 + 7) / 8) + 7;

            for (VAR_9 = 7; VAR_9 < VAR_9; VAR_9++) {

                VAR_6[VAR_9] = 0x00;

                VAR_10++;

            }



            

            VAR_9 = VAR_9 + ((NUM_PORTS + 7) / 8);

            for (;VAR_9 < VAR_9; VAR_9++) {

                VAR_6[VAR_9] = 0xff;

                VAR_10++;

            }



            VAR_7 = sizeof(qemu_hub_hub_descriptor) + VAR_10;

            VAR_6[0] = VAR_7;

            break;

        }

    default:

    fail:

        VAR_7 = USB_RET_STALL;

        break;

    }

    return VAR_7;

}

static int FUNC_0(USBDevice *VAR_0, USBPacket *VAR_1,
int VAR_2, int VAR_3, int VAR_4, int VAR_5, uint8_t *VAR_6)
{ USBHubState *s = (USBHubState *)VAR_0; int VAR_7; VAR_7 = usb_desc_handle_control(VAR_0, VAR_1, VAR_2, VAR_3, VAR_4, VAR_5, VAR_6); if (VAR_7 >= 0) { return VAR_7; } switch(VAR_2) { case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
if (VAR_3 == 0 && VAR_4 != 0x81) { goto fail; } VAR_7 = 0; break; case DeviceRequest | USB_REQ_GET_INTERFACE:
VAR_6[0] = 0; VAR_7 = 1; break; case DeviceOutRequest | USB_REQ_SET_INTERFACE:
VAR_7 = 0; break; case GetHubStatus:
VAR_6[0] = 0; VAR_6[1] = 0; VAR_6[2] = 0; VAR_6[3] = 0; VAR_7 = 4; break; case GetPortStatus:
{ unsigned int VAR_9 = VAR_4 - 1; USBHubPort *port; if (VAR_9 >= NUM_PORTS) { goto fail; } port = &s->ports[VAR_9]; VAR_6[0] = port->wPortStatus; VAR_6[1] = port->wPortStatus >> 8; VAR_6[2] = port->wPortChange; VAR_6[3] = port->wPortChange >> 8; VAR_7 = 4; } break; case SetHubFeature:
case ClearHubFeature:
if (VAR_3 == 0 || VAR_3 == 1) { } else { goto fail; } VAR_7 = 0; break; case SetPortFeature:
{ unsigned int VAR_9 = VAR_4 - 1; USBHubPort *port; USBDevice *VAR_0; if (VAR_9 >= NUM_PORTS) { goto fail; } port = &s->ports[VAR_9]; VAR_0 = port->port.VAR_0; switch(VAR_3) { case PORT_SUSPEND:
port->wPortStatus |= PORT_STAT_SUSPEND; break; case PORT_RESET:
if (VAR_0) { usb_send_msg(VAR_0, USB_MSG_RESET); port->wPortChange |= PORT_STAT_C_RESET; port->wPortStatus |= PORT_STAT_ENABLE; } break; case PORT_POWER:
break; default:
goto fail; } VAR_7 = 0; } break; case ClearPortFeature:
{ unsigned int VAR_9 = VAR_4 - 1; USBHubPort *port; if (VAR_9 >= NUM_PORTS) { goto fail; } port = &s->ports[VAR_9]; switch(VAR_3) { case PORT_ENABLE:
port->wPortStatus &= ~PORT_STAT_ENABLE; break; case PORT_C_ENABLE:
port->wPortChange &= ~PORT_STAT_C_ENABLE; break; case PORT_SUSPEND:
port->wPortStatus &= ~PORT_STAT_SUSPEND; break; case PORT_C_SUSPEND:
port->wPortChange &= ~PORT_STAT_C_SUSPEND; break; case PORT_C_CONNECTION:
port->wPortChange &= ~PORT_STAT_C_CONNECTION; break; case PORT_C_OVERCURRENT:
port->wPortChange &= ~PORT_STAT_C_OVERCURRENT; break; case PORT_C_RESET:
port->wPortChange &= ~PORT_STAT_C_RESET; break; default:
goto fail; } VAR_7 = 0; } break; case GetHubDescriptor:
{ unsigned int VAR_9, VAR_9, VAR_10 = 0; memcpy(VAR_6, qemu_hub_hub_descriptor,
sizeof(qemu_hub_hub_descriptor)); VAR_6[2] = NUM_PORTS; VAR_9 = ((NUM_PORTS + 1 + 7) / 8) + 7; for (VAR_9 = 7; VAR_9 < VAR_9; VAR_9++) { VAR_6[VAR_9] = 0x00; VAR_10++; } VAR_9 = VAR_9 + ((NUM_PORTS + 7) / 8); for (;VAR_9 < VAR_9; VAR_9++) { VAR_6[VAR_9] = 0xff; VAR_10++; } VAR_7 = sizeof(qemu_hub_hub_descriptor) + VAR_10; VAR_6[0] = VAR_7; break; } default:
fail:
VAR_7 = USB_RET_STALL; break; } return VAR_7; }