Annotation of qemu/hw/usb/dev-hid.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * QEMU USB HID devices
        !             3:  *
        !             4:  * Copyright (c) 2005 Fabrice Bellard
        !             5:  * Copyright (c) 2007 OpenMoko, Inc.  ([email protected])
        !             6:  *
        !             7:  * Permission is hereby granted, free of charge, to any person obtaining a copy
        !             8:  * of this software and associated documentation files (the "Software"), to deal
        !             9:  * in the Software without restriction, including without limitation the rights
        !            10:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        !            11:  * copies of the Software, and to permit persons to whom the Software is
        !            12:  * furnished to do so, subject to the following conditions:
        !            13:  *
        !            14:  * The above copyright notice and this permission notice shall be included in
        !            15:  * all copies or substantial portions of the Software.
        !            16:  *
        !            17:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        !            18:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        !            19:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
        !            20:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        !            21:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        !            22:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        !            23:  * THE SOFTWARE.
        !            24:  */
        !            25: #include "hw/hw.h"
        !            26: #include "console.h"
        !            27: #include "hw/usb.h"
        !            28: #include "hw/usb/desc.h"
        !            29: #include "qemu-timer.h"
        !            30: #include "hw/hid.h"
        !            31: 
        !            32: /* HID interface requests */
        !            33: #define GET_REPORT   0xa101
        !            34: #define GET_IDLE     0xa102
        !            35: #define GET_PROTOCOL 0xa103
        !            36: #define SET_REPORT   0x2109
        !            37: #define SET_IDLE     0x210a
        !            38: #define SET_PROTOCOL 0x210b
        !            39: 
        !            40: /* HID descriptor types */
        !            41: #define USB_DT_HID    0x21
        !            42: #define USB_DT_REPORT 0x22
        !            43: #define USB_DT_PHY    0x23
        !            44: 
        !            45: typedef struct USBHIDState {
        !            46:     USBDevice dev;
        !            47:     USBEndpoint *intr;
        !            48:     HIDState hid;
        !            49: } USBHIDState;
        !            50: 
        !            51: enum {
        !            52:     STR_MANUFACTURER = 1,
        !            53:     STR_PRODUCT_MOUSE,
        !            54:     STR_PRODUCT_TABLET,
        !            55:     STR_PRODUCT_KEYBOARD,
        !            56:     STR_SERIALNUMBER,
        !            57:     STR_CONFIG_MOUSE,
        !            58:     STR_CONFIG_TABLET,
        !            59:     STR_CONFIG_KEYBOARD,
        !            60: };
        !            61: 
        !            62: static const USBDescStrings desc_strings = {
        !            63:     [STR_MANUFACTURER]     = "QEMU " QEMU_VERSION,
        !            64:     [STR_PRODUCT_MOUSE]    = "QEMU USB Mouse",
        !            65:     [STR_PRODUCT_TABLET]   = "QEMU USB Tablet",
        !            66:     [STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
        !            67:     [STR_SERIALNUMBER]     = "42", /* == remote wakeup works */
        !            68:     [STR_CONFIG_MOUSE]     = "HID Mouse",
        !            69:     [STR_CONFIG_TABLET]    = "HID Tablet",
        !            70:     [STR_CONFIG_KEYBOARD]  = "HID Keyboard",
        !            71: };
        !            72: 
        !            73: static const USBDescIface desc_iface_mouse = {
        !            74:     .bInterfaceNumber              = 0,
        !            75:     .bNumEndpoints                 = 1,
        !            76:     .bInterfaceClass               = USB_CLASS_HID,
        !            77:     .bInterfaceSubClass            = 0x01, /* boot */
        !            78:     .bInterfaceProtocol            = 0x02,
        !            79:     .ndesc                         = 1,
        !            80:     .descs = (USBDescOther[]) {
        !            81:         {
        !            82:             /* HID descriptor */
        !            83:             .data = (uint8_t[]) {
        !            84:                 0x09,          /*  u8  bLength */
        !            85:                 USB_DT_HID,    /*  u8  bDescriptorType */
        !            86:                 0x01, 0x00,    /*  u16 HID_class */
        !            87:                 0x00,          /*  u8  country_code */
        !            88:                 0x01,          /*  u8  num_descriptors */
        !            89:                 USB_DT_REPORT, /*  u8  type: Report */
        !            90:                 52, 0,         /*  u16 len */
        !            91:             },
        !            92:         },
        !            93:     },
        !            94:     .eps = (USBDescEndpoint[]) {
        !            95:         {
        !            96:             .bEndpointAddress      = USB_DIR_IN | 0x01,
        !            97:             .bmAttributes          = USB_ENDPOINT_XFER_INT,
        !            98:             .wMaxPacketSize        = 4,
        !            99:             .bInterval             = 0x0a,
        !           100:         },
        !           101:     },
        !           102: };
        !           103: 
        !           104: static const USBDescIface desc_iface_tablet = {
        !           105:     .bInterfaceNumber              = 0,
        !           106:     .bNumEndpoints                 = 1,
        !           107:     .bInterfaceClass               = USB_CLASS_HID,
        !           108:     .bInterfaceProtocol            = 0x02,
        !           109:     .ndesc                         = 1,
        !           110:     .descs = (USBDescOther[]) {
        !           111:         {
        !           112:             /* HID descriptor */
        !           113:             .data = (uint8_t[]) {
        !           114:                 0x09,          /*  u8  bLength */
        !           115:                 USB_DT_HID,    /*  u8  bDescriptorType */
        !           116:                 0x01, 0x00,    /*  u16 HID_class */
        !           117:                 0x00,          /*  u8  country_code */
        !           118:                 0x01,          /*  u8  num_descriptors */
        !           119:                 USB_DT_REPORT, /*  u8  type: Report */
        !           120:                 74, 0,         /*  u16 len */
        !           121:             },
        !           122:         },
        !           123:     },
        !           124:     .eps = (USBDescEndpoint[]) {
        !           125:         {
        !           126:             .bEndpointAddress      = USB_DIR_IN | 0x01,
        !           127:             .bmAttributes          = USB_ENDPOINT_XFER_INT,
        !           128:             .wMaxPacketSize        = 8,
        !           129:             .bInterval             = 0x0a,
        !           130:         },
        !           131:     },
        !           132: };
        !           133: 
        !           134: static const USBDescIface desc_iface_keyboard = {
        !           135:     .bInterfaceNumber              = 0,
        !           136:     .bNumEndpoints                 = 1,
        !           137:     .bInterfaceClass               = USB_CLASS_HID,
        !           138:     .bInterfaceSubClass            = 0x01, /* boot */
        !           139:     .bInterfaceProtocol            = 0x01, /* keyboard */
        !           140:     .ndesc                         = 1,
        !           141:     .descs = (USBDescOther[]) {
        !           142:         {
        !           143:             /* HID descriptor */
        !           144:             .data = (uint8_t[]) {
        !           145:                 0x09,          /*  u8  bLength */
        !           146:                 USB_DT_HID,    /*  u8  bDescriptorType */
        !           147:                 0x11, 0x01,    /*  u16 HID_class */
        !           148:                 0x00,          /*  u8  country_code */
        !           149:                 0x01,          /*  u8  num_descriptors */
        !           150:                 USB_DT_REPORT, /*  u8  type: Report */
        !           151:                 0x3f, 0,       /*  u16 len */
        !           152:             },
        !           153:         },
        !           154:     },
        !           155:     .eps = (USBDescEndpoint[]) {
        !           156:         {
        !           157:             .bEndpointAddress      = USB_DIR_IN | 0x01,
        !           158:             .bmAttributes          = USB_ENDPOINT_XFER_INT,
        !           159:             .wMaxPacketSize        = 8,
        !           160:             .bInterval             = 0x0a,
        !           161:         },
        !           162:     },
        !           163: };
        !           164: 
        !           165: static const USBDescDevice desc_device_mouse = {
        !           166:     .bcdUSB                        = 0x0100,
        !           167:     .bMaxPacketSize0               = 8,
        !           168:     .bNumConfigurations            = 1,
        !           169:     .confs = (USBDescConfig[]) {
        !           170:         {
        !           171:             .bNumInterfaces        = 1,
        !           172:             .bConfigurationValue   = 1,
        !           173:             .iConfiguration        = STR_CONFIG_MOUSE,
        !           174:             .bmAttributes          = 0xa0,
        !           175:             .bMaxPower             = 50,
        !           176:             .nif = 1,
        !           177:             .ifs = &desc_iface_mouse,
        !           178:         },
        !           179:     },
        !           180: };
        !           181: 
        !           182: static const USBDescDevice desc_device_tablet = {
        !           183:     .bcdUSB                        = 0x0100,
        !           184:     .bMaxPacketSize0               = 8,
        !           185:     .bNumConfigurations            = 1,
        !           186:     .confs = (USBDescConfig[]) {
        !           187:         {
        !           188:             .bNumInterfaces        = 1,
        !           189:             .bConfigurationValue   = 1,
        !           190:             .iConfiguration        = STR_CONFIG_TABLET,
        !           191:             .bmAttributes          = 0xa0,
        !           192:             .bMaxPower             = 50,
        !           193:             .nif = 1,
        !           194:             .ifs = &desc_iface_tablet,
        !           195:         },
        !           196:     },
        !           197: };
        !           198: 
        !           199: static const USBDescDevice desc_device_keyboard = {
        !           200:     .bcdUSB                        = 0x0100,
        !           201:     .bMaxPacketSize0               = 8,
        !           202:     .bNumConfigurations            = 1,
        !           203:     .confs = (USBDescConfig[]) {
        !           204:         {
        !           205:             .bNumInterfaces        = 1,
        !           206:             .bConfigurationValue   = 1,
        !           207:             .iConfiguration        = STR_CONFIG_KEYBOARD,
        !           208:             .bmAttributes          = 0xa0,
        !           209:             .bMaxPower             = 50,
        !           210:             .nif = 1,
        !           211:             .ifs = &desc_iface_keyboard,
        !           212:         },
        !           213:     },
        !           214: };
        !           215: 
        !           216: static const USBDesc desc_mouse = {
        !           217:     .id = {
        !           218:         .idVendor          = 0x0627,
        !           219:         .idProduct         = 0x0001,
        !           220:         .bcdDevice         = 0,
        !           221:         .iManufacturer     = STR_MANUFACTURER,
        !           222:         .iProduct          = STR_PRODUCT_MOUSE,
        !           223:         .iSerialNumber     = STR_SERIALNUMBER,
        !           224:     },
        !           225:     .full = &desc_device_mouse,
        !           226:     .str  = desc_strings,
        !           227: };
        !           228: 
        !           229: static const USBDesc desc_tablet = {
        !           230:     .id = {
        !           231:         .idVendor          = 0x0627,
        !           232:         .idProduct         = 0x0001,
        !           233:         .bcdDevice         = 0,
        !           234:         .iManufacturer     = STR_MANUFACTURER,
        !           235:         .iProduct          = STR_PRODUCT_TABLET,
        !           236:         .iSerialNumber     = STR_SERIALNUMBER,
        !           237:     },
        !           238:     .full = &desc_device_tablet,
        !           239:     .str  = desc_strings,
        !           240: };
        !           241: 
        !           242: static const USBDesc desc_keyboard = {
        !           243:     .id = {
        !           244:         .idVendor          = 0x0627,
        !           245:         .idProduct         = 0x0001,
        !           246:         .bcdDevice         = 0,
        !           247:         .iManufacturer     = STR_MANUFACTURER,
        !           248:         .iProduct          = STR_PRODUCT_KEYBOARD,
        !           249:         .iSerialNumber     = STR_SERIALNUMBER,
        !           250:     },
        !           251:     .full = &desc_device_keyboard,
        !           252:     .str  = desc_strings,
        !           253: };
        !           254: 
        !           255: static const uint8_t qemu_mouse_hid_report_descriptor[] = {
        !           256:     0x05, 0x01,                /* Usage Page (Generic Desktop) */
        !           257:     0x09, 0x02,                /* Usage (Mouse) */
        !           258:     0xa1, 0x01,                /* Collection (Application) */
        !           259:     0x09, 0x01,                /*   Usage (Pointer) */
        !           260:     0xa1, 0x00,                /*   Collection (Physical) */
        !           261:     0x05, 0x09,                /*     Usage Page (Button) */
        !           262:     0x19, 0x01,                /*     Usage Minimum (1) */
        !           263:     0x29, 0x03,                /*     Usage Maximum (3) */
        !           264:     0x15, 0x00,                /*     Logical Minimum (0) */
        !           265:     0x25, 0x01,                /*     Logical Maximum (1) */
        !           266:     0x95, 0x03,                /*     Report Count (3) */
        !           267:     0x75, 0x01,                /*     Report Size (1) */
        !           268:     0x81, 0x02,                /*     Input (Data, Variable, Absolute) */
        !           269:     0x95, 0x01,                /*     Report Count (1) */
        !           270:     0x75, 0x05,                /*     Report Size (5) */
        !           271:     0x81, 0x01,                /*     Input (Constant) */
        !           272:     0x05, 0x01,                /*     Usage Page (Generic Desktop) */
        !           273:     0x09, 0x30,                /*     Usage (X) */
        !           274:     0x09, 0x31,                /*     Usage (Y) */
        !           275:     0x09, 0x38,                /*     Usage (Wheel) */
        !           276:     0x15, 0x81,                /*     Logical Minimum (-0x7f) */
        !           277:     0x25, 0x7f,                /*     Logical Maximum (0x7f) */
        !           278:     0x75, 0x08,                /*     Report Size (8) */
        !           279:     0x95, 0x03,                /*     Report Count (3) */
        !           280:     0x81, 0x06,                /*     Input (Data, Variable, Relative) */
        !           281:     0xc0,              /*   End Collection */
        !           282:     0xc0,              /* End Collection */
        !           283: };
        !           284: 
        !           285: static const uint8_t qemu_tablet_hid_report_descriptor[] = {
        !           286:     0x05, 0x01,                /* Usage Page (Generic Desktop) */
        !           287:     0x09, 0x01,                /* Usage (Pointer) */
        !           288:     0xa1, 0x01,                /* Collection (Application) */
        !           289:     0x09, 0x01,                /*   Usage (Pointer) */
        !           290:     0xa1, 0x00,                /*   Collection (Physical) */
        !           291:     0x05, 0x09,                /*     Usage Page (Button) */
        !           292:     0x19, 0x01,                /*     Usage Minimum (1) */
        !           293:     0x29, 0x03,                /*     Usage Maximum (3) */
        !           294:     0x15, 0x00,                /*     Logical Minimum (0) */
        !           295:     0x25, 0x01,                /*     Logical Maximum (1) */
        !           296:     0x95, 0x03,                /*     Report Count (3) */
        !           297:     0x75, 0x01,                /*     Report Size (1) */
        !           298:     0x81, 0x02,                /*     Input (Data, Variable, Absolute) */
        !           299:     0x95, 0x01,                /*     Report Count (1) */
        !           300:     0x75, 0x05,                /*     Report Size (5) */
        !           301:     0x81, 0x01,                /*     Input (Constant) */
        !           302:     0x05, 0x01,                /*     Usage Page (Generic Desktop) */
        !           303:     0x09, 0x30,                /*     Usage (X) */
        !           304:     0x09, 0x31,                /*     Usage (Y) */
        !           305:     0x15, 0x00,                /*     Logical Minimum (0) */
        !           306:     0x26, 0xff, 0x7f,  /*     Logical Maximum (0x7fff) */
        !           307:     0x35, 0x00,                /*     Physical Minimum (0) */
        !           308:     0x46, 0xff, 0x7f,  /*     Physical Maximum (0x7fff) */
        !           309:     0x75, 0x10,                /*     Report Size (16) */
        !           310:     0x95, 0x02,                /*     Report Count (2) */
        !           311:     0x81, 0x02,                /*     Input (Data, Variable, Absolute) */
        !           312:     0x05, 0x01,                /*     Usage Page (Generic Desktop) */
        !           313:     0x09, 0x38,                /*     Usage (Wheel) */
        !           314:     0x15, 0x81,                /*     Logical Minimum (-0x7f) */
        !           315:     0x25, 0x7f,                /*     Logical Maximum (0x7f) */
        !           316:     0x35, 0x00,                /*     Physical Minimum (same as logical) */
        !           317:     0x45, 0x00,                /*     Physical Maximum (same as logical) */
        !           318:     0x75, 0x08,                /*     Report Size (8) */
        !           319:     0x95, 0x01,                /*     Report Count (1) */
        !           320:     0x81, 0x06,                /*     Input (Data, Variable, Relative) */
        !           321:     0xc0,              /*   End Collection */
        !           322:     0xc0,              /* End Collection */
        !           323: };
        !           324: 
        !           325: static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
        !           326:     0x05, 0x01,                /* Usage Page (Generic Desktop) */
        !           327:     0x09, 0x06,                /* Usage (Keyboard) */
        !           328:     0xa1, 0x01,                /* Collection (Application) */
        !           329:     0x75, 0x01,                /*   Report Size (1) */
        !           330:     0x95, 0x08,                /*   Report Count (8) */
        !           331:     0x05, 0x07,                /*   Usage Page (Key Codes) */
        !           332:     0x19, 0xe0,                /*   Usage Minimum (224) */
        !           333:     0x29, 0xe7,                /*   Usage Maximum (231) */
        !           334:     0x15, 0x00,                /*   Logical Minimum (0) */
        !           335:     0x25, 0x01,                /*   Logical Maximum (1) */
        !           336:     0x81, 0x02,                /*   Input (Data, Variable, Absolute) */
        !           337:     0x95, 0x01,                /*   Report Count (1) */
        !           338:     0x75, 0x08,                /*   Report Size (8) */
        !           339:     0x81, 0x01,                /*   Input (Constant) */
        !           340:     0x95, 0x05,                /*   Report Count (5) */
        !           341:     0x75, 0x01,                /*   Report Size (1) */
        !           342:     0x05, 0x08,                /*   Usage Page (LEDs) */
        !           343:     0x19, 0x01,                /*   Usage Minimum (1) */
        !           344:     0x29, 0x05,                /*   Usage Maximum (5) */
        !           345:     0x91, 0x02,                /*   Output (Data, Variable, Absolute) */
        !           346:     0x95, 0x01,                /*   Report Count (1) */
        !           347:     0x75, 0x03,                /*   Report Size (3) */
        !           348:     0x91, 0x01,                /*   Output (Constant) */
        !           349:     0x95, 0x06,                /*   Report Count (6) */
        !           350:     0x75, 0x08,                /*   Report Size (8) */
        !           351:     0x15, 0x00,                /*   Logical Minimum (0) */
        !           352:     0x25, 0xff,                /*   Logical Maximum (255) */
        !           353:     0x05, 0x07,                /*   Usage Page (Key Codes) */
        !           354:     0x19, 0x00,                /*   Usage Minimum (0) */
        !           355:     0x29, 0xff,                /*   Usage Maximum (255) */
        !           356:     0x81, 0x00,                /*   Input (Data, Array) */
        !           357:     0xc0,              /* End Collection */
        !           358: };
        !           359: 
        !           360: static void usb_hid_changed(HIDState *hs)
        !           361: {
        !           362:     USBHIDState *us = container_of(hs, USBHIDState, hid);
        !           363: 
        !           364:     usb_wakeup(us->intr);
        !           365: }
        !           366: 
        !           367: static void usb_hid_handle_reset(USBDevice *dev)
        !           368: {
        !           369:     USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
        !           370: 
        !           371:     hid_reset(&us->hid);
        !           372: }
        !           373: 
        !           374: static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
        !           375:                int request, int value, int index, int length, uint8_t *data)
        !           376: {
        !           377:     USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
        !           378:     HIDState *hs = &us->hid;
        !           379:     int ret;
        !           380: 
        !           381:     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
        !           382:     if (ret >= 0) {
        !           383:         return ret;
        !           384:     }
        !           385: 
        !           386:     ret = 0;
        !           387:     switch (request) {
        !           388:         /* hid specific requests */
        !           389:     case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
        !           390:         switch (value >> 8) {
        !           391:         case 0x22:
        !           392:             if (hs->kind == HID_MOUSE) {
        !           393:                memcpy(data, qemu_mouse_hid_report_descriptor,
        !           394:                       sizeof(qemu_mouse_hid_report_descriptor));
        !           395:                ret = sizeof(qemu_mouse_hid_report_descriptor);
        !           396:             } else if (hs->kind == HID_TABLET) {
        !           397:                 memcpy(data, qemu_tablet_hid_report_descriptor,
        !           398:                       sizeof(qemu_tablet_hid_report_descriptor));
        !           399:                ret = sizeof(qemu_tablet_hid_report_descriptor);
        !           400:             } else if (hs->kind == HID_KEYBOARD) {
        !           401:                 memcpy(data, qemu_keyboard_hid_report_descriptor,
        !           402:                        sizeof(qemu_keyboard_hid_report_descriptor));
        !           403:                 ret = sizeof(qemu_keyboard_hid_report_descriptor);
        !           404:             }
        !           405:             break;
        !           406:         default:
        !           407:             goto fail;
        !           408:         }
        !           409:         break;
        !           410:     case GET_REPORT:
        !           411:         if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
        !           412:             ret = hid_pointer_poll(hs, data, length);
        !           413:         } else if (hs->kind == HID_KEYBOARD) {
        !           414:             ret = hid_keyboard_poll(hs, data, length);
        !           415:         }
        !           416:         break;
        !           417:     case SET_REPORT:
        !           418:         if (hs->kind == HID_KEYBOARD) {
        !           419:             ret = hid_keyboard_write(hs, data, length);
        !           420:         } else {
        !           421:             goto fail;
        !           422:         }
        !           423:         break;
        !           424:     case GET_PROTOCOL:
        !           425:         if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
        !           426:             goto fail;
        !           427:         }
        !           428:         ret = 1;
        !           429:         data[0] = hs->protocol;
        !           430:         break;
        !           431:     case SET_PROTOCOL:
        !           432:         if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
        !           433:             goto fail;
        !           434:         }
        !           435:         ret = 0;
        !           436:         hs->protocol = value;
        !           437:         break;
        !           438:     case GET_IDLE:
        !           439:         ret = 1;
        !           440:         data[0] = hs->idle;
        !           441:         break;
        !           442:     case SET_IDLE:
        !           443:         hs->idle = (uint8_t) (value >> 8);
        !           444:         hid_set_next_idle(hs, qemu_get_clock_ns(vm_clock));
        !           445:         if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
        !           446:             hid_pointer_activate(hs);
        !           447:         }
        !           448:         ret = 0;
        !           449:         break;
        !           450:     default:
        !           451:     fail:
        !           452:         ret = USB_RET_STALL;
        !           453:         break;
        !           454:     }
        !           455:     return ret;
        !           456: }
        !           457: 
        !           458: static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
        !           459: {
        !           460:     USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
        !           461:     HIDState *hs = &us->hid;
        !           462:     uint8_t buf[p->iov.size];
        !           463:     int ret = 0;
        !           464: 
        !           465:     switch (p->pid) {
        !           466:     case USB_TOKEN_IN:
        !           467:         if (p->ep->nr == 1) {
        !           468:             int64_t curtime = qemu_get_clock_ns(vm_clock);
        !           469:             if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
        !           470:                 hid_pointer_activate(hs);
        !           471:             }
        !           472:             if (!hid_has_events(hs) &&
        !           473:                 (!hs->idle || hs->next_idle_clock - curtime > 0)) {
        !           474:                 return USB_RET_NAK;
        !           475:             }
        !           476:             hid_set_next_idle(hs, curtime);
        !           477:             if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
        !           478:                 ret = hid_pointer_poll(hs, buf, p->iov.size);
        !           479:             } else if (hs->kind == HID_KEYBOARD) {
        !           480:                 ret = hid_keyboard_poll(hs, buf, p->iov.size);
        !           481:             }
        !           482:             usb_packet_copy(p, buf, ret);
        !           483:         } else {
        !           484:             goto fail;
        !           485:         }
        !           486:         break;
        !           487:     case USB_TOKEN_OUT:
        !           488:     default:
        !           489:     fail:
        !           490:         ret = USB_RET_STALL;
        !           491:         break;
        !           492:     }
        !           493:     return ret;
        !           494: }
        !           495: 
        !           496: static void usb_hid_handle_destroy(USBDevice *dev)
        !           497: {
        !           498:     USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
        !           499: 
        !           500:     hid_free(&us->hid);
        !           501: }
        !           502: 
        !           503: static int usb_hid_initfn(USBDevice *dev, int kind)
        !           504: {
        !           505:     USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
        !           506: 
        !           507:     usb_desc_init(dev);
        !           508:     us->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
        !           509:     hid_init(&us->hid, kind, usb_hid_changed);
        !           510:     return 0;
        !           511: }
        !           512: 
        !           513: static int usb_tablet_initfn(USBDevice *dev)
        !           514: {
        !           515:     return usb_hid_initfn(dev, HID_TABLET);
        !           516: }
        !           517: 
        !           518: static int usb_mouse_initfn(USBDevice *dev)
        !           519: {
        !           520:     return usb_hid_initfn(dev, HID_MOUSE);
        !           521: }
        !           522: 
        !           523: static int usb_keyboard_initfn(USBDevice *dev)
        !           524: {
        !           525:     return usb_hid_initfn(dev, HID_KEYBOARD);
        !           526: }
        !           527: 
        !           528: static int usb_ptr_post_load(void *opaque, int version_id)
        !           529: {
        !           530:     USBHIDState *s = opaque;
        !           531: 
        !           532:     if (s->dev.remote_wakeup) {
        !           533:         hid_pointer_activate(&s->hid);
        !           534:     }
        !           535:     return 0;
        !           536: }
        !           537: 
        !           538: static const VMStateDescription vmstate_usb_ptr = {
        !           539:     .name = "usb-ptr",
        !           540:     .version_id = 1,
        !           541:     .minimum_version_id = 1,
        !           542:     .post_load = usb_ptr_post_load,
        !           543:     .fields = (VMStateField []) {
        !           544:         VMSTATE_USB_DEVICE(dev, USBHIDState),
        !           545:         VMSTATE_HID_POINTER_DEVICE(hid, USBHIDState),
        !           546:         VMSTATE_END_OF_LIST()
        !           547:     }
        !           548: };
        !           549: 
        !           550: static const VMStateDescription vmstate_usb_kbd = {
        !           551:     .name = "usb-kbd",
        !           552:     .version_id = 1,
        !           553:     .minimum_version_id = 1,
        !           554:     .fields = (VMStateField []) {
        !           555:         VMSTATE_USB_DEVICE(dev, USBHIDState),
        !           556:         VMSTATE_HID_KEYBOARD_DEVICE(hid, USBHIDState),
        !           557:         VMSTATE_END_OF_LIST()
        !           558:     }
        !           559: };
        !           560: 
        !           561: static void usb_hid_class_initfn(ObjectClass *klass, void *data)
        !           562: {
        !           563:     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
        !           564: 
        !           565:     uc->handle_reset   = usb_hid_handle_reset;
        !           566:     uc->handle_control = usb_hid_handle_control;
        !           567:     uc->handle_data    = usb_hid_handle_data;
        !           568:     uc->handle_destroy = usb_hid_handle_destroy;
        !           569: }
        !           570: 
        !           571: static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
        !           572: {
        !           573:     DeviceClass *dc = DEVICE_CLASS(klass);
        !           574:     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
        !           575: 
        !           576:     usb_hid_class_initfn(klass, data);
        !           577:     uc->init           = usb_tablet_initfn;
        !           578:     uc->product_desc   = "QEMU USB Tablet";
        !           579:     uc->usb_desc       = &desc_tablet;
        !           580:     dc->vmsd = &vmstate_usb_ptr;
        !           581: }
        !           582: 
        !           583: static TypeInfo usb_tablet_info = {
        !           584:     .name          = "usb-tablet",
        !           585:     .parent        = TYPE_USB_DEVICE,
        !           586:     .instance_size = sizeof(USBHIDState),
        !           587:     .class_init    = usb_tablet_class_initfn,
        !           588: };
        !           589: 
        !           590: static void usb_mouse_class_initfn(ObjectClass *klass, void *data)
        !           591: {
        !           592:     DeviceClass *dc = DEVICE_CLASS(klass);
        !           593:     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
        !           594: 
        !           595:     usb_hid_class_initfn(klass, data);
        !           596:     uc->init           = usb_mouse_initfn;
        !           597:     uc->product_desc   = "QEMU USB Mouse";
        !           598:     uc->usb_desc       = &desc_mouse;
        !           599:     dc->vmsd = &vmstate_usb_ptr;
        !           600: }
        !           601: 
        !           602: static TypeInfo usb_mouse_info = {
        !           603:     .name          = "usb-mouse",
        !           604:     .parent        = TYPE_USB_DEVICE,
        !           605:     .instance_size = sizeof(USBHIDState),
        !           606:     .class_init    = usb_mouse_class_initfn,
        !           607: };
        !           608: 
        !           609: static void usb_keyboard_class_initfn(ObjectClass *klass, void *data)
        !           610: {
        !           611:     DeviceClass *dc = DEVICE_CLASS(klass);
        !           612:     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
        !           613: 
        !           614:     usb_hid_class_initfn(klass, data);
        !           615:     uc->init           = usb_keyboard_initfn;
        !           616:     uc->product_desc   = "QEMU USB Keyboard";
        !           617:     uc->usb_desc       = &desc_keyboard;
        !           618:     dc->vmsd = &vmstate_usb_kbd;
        !           619: }
        !           620: 
        !           621: static TypeInfo usb_keyboard_info = {
        !           622:     .name          = "usb-kbd",
        !           623:     .parent        = TYPE_USB_DEVICE,
        !           624:     .instance_size = sizeof(USBHIDState),
        !           625:     .class_init    = usb_keyboard_class_initfn,
        !           626: };
        !           627: 
        !           628: static void usb_hid_register_types(void)
        !           629: {
        !           630:     type_register_static(&usb_tablet_info);
        !           631:     usb_legacy_register("usb-tablet", "tablet", NULL);
        !           632:     type_register_static(&usb_mouse_info);
        !           633:     usb_legacy_register("usb-mouse", "mouse", NULL);
        !           634:     type_register_static(&usb_keyboard_info);
        !           635:     usb_legacy_register("usb-kbd", "keyboard", NULL);
        !           636: }
        !           637: 
        !           638: type_init(usb_hid_register_types)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.