Changeset 2303


Ignore:
Timestamp:
06/19/07 15:16:05 (6 years ago)
Author:
andrew
Message:

Emulate a USB HID keyboard.

Location:
trunk/src/host/qemu-neo1973
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/host/qemu-neo1973/hw/usb-hid.c

    r1948 r2303  
    33 *  
    44 * Copyright (c) 2005 Fabrice Bellard 
     5 * Copyright (c) 2007 OpenMoko, Inc.  (andrew@openedhand.com) 
    56 *  
    67 * Permission is hereby granted, free of charge, to any person obtaining a copy 
     
    2829#define GET_IDLE     0xa102 
    2930#define GET_PROTOCOL 0xa103 
     31#define SET_REPORT   0x2101 
    3032#define SET_IDLE     0x210a 
    3133#define SET_PROTOCOL 0x210b 
    3234 
    33 #define USB_MOUSE  1 
    34 #define USB_TABLET 2 
     35#define USB_MOUSE    1 
     36#define USB_TABLET   2 
     37#define USB_KEYBOARD 3 
    3538 
    3639typedef struct USBMouseState { 
    37     USBDevice dev; 
    3840    int dx, dy, dz, buttons_state; 
    3941    int x, y; 
    40     int kind; 
    4142    int mouse_grabbed; 
    4243    QEMUPutMouseEntry *eh_entry; 
    4344} USBMouseState; 
     45 
     46typedef struct USBKeyboardState { 
     47    uint16_t modifiers; 
     48    uint8_t leds; 
     49    uint8_t key[16]; 
     50    int keys; 
     51} USBKeyboardState; 
     52 
     53typedef struct USBHIDState { 
     54    USBDevice dev; 
     55    union { 
     56        USBMouseState ptr; 
     57        USBKeyboardState kbd; 
     58    }; 
     59    int kind; 
     60    int protocol; 
     61    int idle; 
     62} USBHIDState; 
    4463 
    4564/* mostly the same values as the Bochs USB Mouse device */ 
     
    172191        0x08, 0x00, /*  u16 ep_wMaxPacketSize; */ 
    173192        0x0a,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */ 
     193}; 
     194 
     195static const uint8_t qemu_keyboard_config_descriptor[] = { 
     196        /* one configuration */ 
     197        0x09,       /*  u8  bLength; */ 
     198        0x02,       /*  u8  bDescriptorType; Configuration */ 
     199        0x22, 0x00, /*  u16 wTotalLength; */ 
     200        0x01,       /*  u8  bNumInterfaces; (1) */ 
     201        0x01,       /*  u8  bConfigurationValue; */ 
     202        0x04,       /*  u8  iConfiguration; */ 
     203        0xa0,       /*  u8  bmAttributes;  
     204                                 Bit 7: must be set, 
     205                                     6: Self-powered, 
     206                                     5: Remote wakeup, 
     207                                     4..0: resvd */ 
     208        0x32,       /*  u8  MaxPower; */ 
     209 
     210        /* USB 1.1: 
     211         * USB 2.0, single TT organization (mandatory): 
     212         *      one interface, protocol 0 
     213         * 
     214         * USB 2.0, multiple TT organization (optional): 
     215         *      two interfaces, protocols 1 (like single TT) 
     216         *      and 2 (multiple TT mode) ... config is 
     217         *      sometimes settable 
     218         *      NOT IMPLEMENTED 
     219         */ 
     220 
     221        /* one interface */ 
     222        0x09,       /*  u8  if_bLength; */ 
     223        0x04,       /*  u8  if_bDescriptorType; Interface */ 
     224        0x00,       /*  u8  if_bInterfaceNumber; */ 
     225        0x00,       /*  u8  if_bAlternateSetting; */ 
     226        0x01,       /*  u8  if_bNumEndpoints; */ 
     227        0x03,       /*  u8  if_bInterfaceClass; HID */ 
     228        0x01,       /*  u8  if_bInterfaceSubClass; Boot */ 
     229        0x01,       /*  u8  if_bInterfaceProtocol; Keyboard */ 
     230        0x05,       /*  u8  if_iInterface; */ 
     231 
     232        /* HID descriptor */ 
     233        0x09,        /*  u8  bLength; */ 
     234        0x21,        /*  u8  bDescriptorType; */ 
     235        0x01, 0x11,  /*  u16 HID_class */ 
     236        0x00,        /*  u8  country_code */ 
     237        0x01,        /*  u8  num_descriptors */ 
     238        0x22,        /*  u8  type; Report */ 
     239        0x3f, 0x00,  /*  u16 len */ 
     240 
     241        /* one endpoint (status change endpoint) */ 
     242        0x07,       /*  u8  ep_bLength; */ 
     243        0x05,       /*  u8  ep_bDescriptorType; Endpoint */ 
     244        0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */ 
     245        0x03,       /*  u8  ep_bmAttributes; Interrupt */ 
     246        0x08, 0x00, /*  u16 ep_wMaxPacketSize; */ 
     247        0x0a,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */ 
    174248}; 
    175249 
     
    224298}; 
    225299 
     300static const uint8_t qemu_keyboard_hid_report_descriptor[] = { 
     301    0x05, 0x01,         /* Usage Page (Generic Desktop) */ 
     302    0x09, 0x06,         /* Usage (Keyboard) */ 
     303    0xa1, 0x01,         /* Collection (Application) */ 
     304    0x75, 0x01,         /*   Report Size (1) */ 
     305    0x95, 0x08,         /*   Report Count (8) */ 
     306    0x05, 0x07,         /*   Usage Page (Key Codes) */ 
     307    0x19, 0xe0,         /*   Usage Minimum (224) */ 
     308    0x29, 0xe7,         /*   Usage Maximum (231) */ 
     309    0x15, 0x00,         /*   Logical Minimum (0) */ 
     310    0x25, 0x01,         /*   Logical Maximum (1) */ 
     311    0x81, 0x02,         /*   Input (Data, Variable, Absolute) */ 
     312    0x95, 0x01,         /*   Report Count (1) */ 
     313    0x75, 0x08,         /*   Report Size (8) */ 
     314    0x81, 0x01,         /*   Input (Constant) */ 
     315    0x95, 0x05,         /*   Report Count (5) */ 
     316    0x75, 0x01,         /*   Report Size (1) */ 
     317    0x05, 0x08,         /*   Usage Page (LEDs) */ 
     318    0x19, 0x01,         /*   Usage Minimum (1) */ 
     319    0x29, 0x05,         /*   Usage Maximum (5) */ 
     320    0x91, 0x02,         /*   Output (Data, Variable, Absolute) */ 
     321    0x95, 0x01,         /*   Report Count (1) */ 
     322    0x75, 0x03,         /*   Report Size (3) */ 
     323    0x91, 0x01,         /*   Output (Constant) */ 
     324    0x95, 0x06,         /*   Report Count (6) */ 
     325    0x75, 0x08,         /*   Report Size (8) */ 
     326    0x15, 0x00,         /*   Logical Minimum (0) */ 
     327    0x25, 0xff,         /*   Logical Maximum (255) */ 
     328    0x05, 0x07,         /*   Usage Page (Key Codes) */ 
     329    0x19, 0x00,         /*   Usage Minimum (0) */ 
     330    0x29, 0xff,         /*   Usage Maximum (255) */ 
     331    0x81, 0x00,         /*   Input (Data, Array) */ 
     332    0xc0,               /* End Collection */ 
     333}; 
     334 
     335#define USB_HID_USAGE_ERROR_ROLLOVER    0x01 
     336#define USB_HID_USAGE_POSTFAIL          0x02 
     337#define USB_HID_USAGE_ERROR_UNDEFINED   0x03 
     338 
     339/* Indices are QEMU keycodes, values are from HID Usage Table.  Indices 
     340 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d.  */ 
     341static const uint8_t usb_hid_usage_keys[0x100] = { 
     342    0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 
     343    0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b, 
     344    0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c, 
     345    0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16, 
     346    0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33, 
     347    0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19, 
     348    0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55, 
     349    0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 
     350    0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f, 
     351    0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59, 
     352    0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44, 
     353    0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 
     354    0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00, 
     355    0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, 
     356    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     357    0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 
     358 
     359    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     360    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     361    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     362    0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00, 
     363    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     364    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     365    0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46, 
     366    0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     367    0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a, 
     368    0x52, 0x4b, 0x00, 0x50, 0x4f, 0x00, 0x00, 0x4d, 
     369    0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00, 
     370    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     371    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     372    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     373    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     374    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
     375}; 
     376 
    226377static void usb_mouse_event(void *opaque, 
    227378                            int dx1, int dy1, int dz1, int buttons_state) 
     
    244395    s->dz += dz; 
    245396    s->buttons_state = buttons_state; 
     397} 
     398 
     399static void usb_keyboard_event(void *opaque, int keycode) 
     400{ 
     401    USBKeyboardState *s = opaque; 
     402    uint8_t hid_code, key; 
     403    int i; 
     404 
     405    key = keycode & 0x7f; 
     406    hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))]; 
     407    s->modifiers &= ~(1 << 8); 
     408 
     409    switch (hid_code) { 
     410    case 0x00: 
     411        return; 
     412 
     413    case 0xe0: 
     414        if (s->modifiers & (1 << 9)) { 
     415            s->modifiers ^= 3 << 8; 
     416            return; 
     417        } 
     418    case 0xe1 ... 0xe7: 
     419        if (keycode & (1 << 7)) { 
     420            s->modifiers &= ~(1 << (hid_code & 0x0f)); 
     421            return; 
     422        } 
     423    case 0xe8 ... 0xef: 
     424        s->modifiers |= 1 << (hid_code & 0x0f); 
     425        return; 
     426 
     427    default: 
     428        if (keycode & (1 << 7)) { 
     429            s->keys --; 
     430            for (i = 0; i <= s->keys; i ++) 
     431                if (s->key[i] == hid_code) { 
     432                    s->key[i] = s->key[s->keys]; 
     433                    s->key[s->keys] = 0x00; 
     434                    return; 
     435                } 
     436        } else { 
     437            for (i = 0; i < s->keys; i ++) 
     438                if (s->key[i] == hid_code) 
     439                    return; 
     440            if (s->keys < sizeof(s->key)) 
     441                s->key[s->keys] = hid_code; 
     442            s->keys ++; 
     443        } 
     444    } 
    246445} 
    247446 
     
    327526} 
    328527 
     528static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len) 
     529{ 
     530    if (len < 2) 
     531        return 0; 
     532 
     533    buf[0] = s->modifiers & 0xff; 
     534    buf[1] = 0; 
     535    if (s->keys > 6) 
     536        memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2); 
     537    else 
     538        memcpy(buf + 2, s->key, MIN(8, len) - 2); 
     539 
     540    return MIN(8, len); 
     541} 
     542 
     543static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len) 
     544{ 
     545    if (len > 0) { 
     546        /* 0x01: Num Lock LED 
     547         * 0x02: Caps Lock LED 
     548         * 0x04: Scroll Lock LED 
     549         * 0x08: Compose LED 
     550         * 0x10: Kana LED */ 
     551        s->leds = buf[0]; 
     552    } 
     553    return 0; 
     554} 
     555 
    329556static void usb_mouse_handle_reset(USBDevice *dev) 
    330557{ 
    331     USBMouseState *s = (USBMouseState *)dev; 
    332  
    333     s->dx = 0; 
    334     s->dy = 0; 
    335     s->dz = 0; 
    336     s->x = 0; 
    337     s->y = 0; 
    338     s->buttons_state = 0; 
    339 } 
    340  
    341 static int usb_mouse_handle_control(USBDevice *dev, int request, int value, 
     558    USBHIDState *s = (USBHIDState *)dev; 
     559 
     560    s->ptr.dx = 0; 
     561    s->ptr.dy = 0; 
     562    s->ptr.dz = 0; 
     563    s->ptr.x = 0; 
     564    s->ptr.y = 0; 
     565    s->ptr.buttons_state = 0; 
     566    s->protocol = 1; 
     567} 
     568 
     569static void usb_keyboard_handle_reset(USBDevice *dev) 
     570{ 
     571    USBHIDState *s = (USBHIDState *)dev; 
     572 
     573    s->protocol = 1; 
     574} 
     575 
     576static int usb_hid_handle_control(USBDevice *dev, int request, int value, 
    342577                                  int index, int length, uint8_t *data) 
    343578{ 
    344     USBMouseState *s = (USBMouseState *)dev; 
     579    USBHIDState *s = (USBHIDState *)dev; 
    345580    int ret = 0; 
    346581 
     
    388623                       sizeof(qemu_tablet_config_descriptor)); 
    389624                ret = sizeof(qemu_tablet_config_descriptor); 
    390             }            
     625            } else if (s->kind == USB_KEYBOARD) { 
     626                memcpy(data, qemu_keyboard_config_descriptor,  
     627                       sizeof(qemu_keyboard_config_descriptor)); 
     628                ret = sizeof(qemu_keyboard_config_descriptor); 
     629            }            
    391630            break; 
    392631        case USB_DT_STRING: 
     
    406645            case 2: 
    407646                /* product description */ 
    408                 if (s->kind == USB_MOUSE) 
    409                     ret = set_usb_string(data, "QEMU USB Mouse"); 
    410                 else if (s->kind == USB_TABLET) 
    411                     ret = set_usb_string(data, "QEMU USB Tablet"); 
     647                ret = set_usb_string(data, s->dev.devname); 
    412648                break; 
    413649            case 3: 
     
    455691                       sizeof(qemu_tablet_hid_report_descriptor)); 
    456692                ret = sizeof(qemu_tablet_hid_report_descriptor); 
    457             } 
    458             break; 
     693            } else if (s->kind == USB_KEYBOARD) { 
     694                memcpy(data, qemu_keyboard_hid_report_descriptor,  
     695                       sizeof(qemu_keyboard_hid_report_descriptor)); 
     696                ret = sizeof(qemu_keyboard_hid_report_descriptor); 
     697            } 
     698            break; 
    459699        default: 
    460700            goto fail; 
     
    463703    case GET_REPORT: 
    464704        if (s->kind == USB_MOUSE) 
    465             ret = usb_mouse_poll(s, data, length); 
     705            ret = usb_mouse_poll(&s->ptr, data, length); 
    466706        else if (s->kind == USB_TABLET) 
    467             ret = usb_tablet_poll(s, data, length); 
     707            ret = usb_tablet_poll(&s->ptr, data, length); 
     708        else if (s->kind == USB_KEYBOARD) 
     709            ret = usb_keyboard_poll(&s->kbd, data, length); 
     710        break; 
     711    case SET_REPORT: 
     712        if (s->kind == USB_KEYBOARD) 
     713            ret = usb_keyboard_write(&s->kbd, data, length); 
     714        else 
     715            goto fail; 
     716        break; 
     717    case GET_PROTOCOL: 
     718        if (s->kind != USB_KEYBOARD) 
     719            goto fail; 
     720        ret = 1; 
     721        data[0] = s->protocol; 
     722        break; 
     723    case SET_PROTOCOL: 
     724        if (s->kind != USB_KEYBOARD) 
     725            goto fail; 
     726        ret = 0; 
     727        s->protocol = value; 
     728        break; 
     729    case GET_IDLE: 
     730        ret = 1; 
     731        data[0] = s->idle; 
    468732        break; 
    469733    case SET_IDLE: 
     734        s->idle = value; 
    470735        ret = 0; 
    471736        break; 
     
    478743} 
    479744 
    480 static int usb_mouse_handle_data(USBDevice *dev, USBPacket *p) 
    481 { 
    482     USBMouseState *s = (USBMouseState *)dev; 
     745static int usb_hid_handle_data(USBDevice *dev, USBPacket *p) 
     746{ 
     747    USBHIDState *s = (USBHIDState *)dev; 
    483748    int ret = 0; 
    484749 
     
    486751    case USB_TOKEN_IN: 
    487752        if (p->devep == 1) { 
    488             if (s->kind == USB_MOUSE) 
    489                 ret = usb_mouse_poll(s, p->data, p->len); 
    490             else if (s->kind == USB_TABLET) 
    491                 ret = usb_tablet_poll(s, p->data, p->len); 
     753            if (s->kind == USB_MOUSE) 
     754                ret = usb_mouse_poll(&s->ptr, p->data, p->len); 
     755            else if (s->kind == USB_TABLET) 
     756                ret = usb_tablet_poll(&s->ptr, p->data, p->len); 
     757            else if (s->kind == USB_KEYBOARD) 
     758                ret = usb_keyboard_poll(&s->kbd, p->data, p->len); 
    492759        } else { 
    493760            goto fail; 
     
    503770} 
    504771 
    505 static void usb_mouse_handle_destroy(USBDevice *dev) 
    506 { 
    507     USBMouseState *s = (USBMouseState *)dev; 
    508  
    509     qemu_remove_mouse_event_handler(s->eh_entry); 
     772static void usb_hid_handle_destroy(USBDevice *dev) 
     773{ 
     774    USBHIDState *s = (USBHIDState *)dev; 
     775 
     776    if (!s->kind == USB_KEYBOARD) 
     777        qemu_remove_mouse_event_handler(s->ptr.eh_entry); 
     778    /* TODO: else */ 
    510779    qemu_free(s); 
    511780} 
     
    513782USBDevice *usb_tablet_init(void) 
    514783{ 
    515     USBMouseState *s; 
    516  
    517     s = qemu_mallocz(sizeof(USBMouseState)); 
     784    USBHIDState *s; 
     785 
     786    s = qemu_mallocz(sizeof(USBHIDState)); 
    518787    if (!s) 
    519788        return NULL; 
     
    522791 
    523792    s->dev.handle_reset = usb_mouse_handle_reset; 
    524     s->dev.handle_control = usb_mouse_handle_control; 
    525     s->dev.handle_data = usb_mouse_handle_data; 
    526     s->dev.handle_destroy = usb_mouse_handle_destroy; 
     793    s->dev.handle_control = usb_hid_handle_control; 
     794    s->dev.handle_data = usb_hid_handle_data; 
     795    s->dev.handle_destroy = usb_hid_handle_destroy; 
    527796    s->kind = USB_TABLET; 
    528797 
     
    534803USBDevice *usb_mouse_init(void) 
    535804{ 
    536     USBMouseState *s; 
    537  
    538     s = qemu_mallocz(sizeof(USBMouseState)); 
     805    USBHIDState *s; 
     806 
     807    s = qemu_mallocz(sizeof(USBHIDState)); 
    539808    if (!s) 
    540809        return NULL; 
     
    543812 
    544813    s->dev.handle_reset = usb_mouse_handle_reset; 
    545     s->dev.handle_control = usb_mouse_handle_control; 
    546     s->dev.handle_data = usb_mouse_handle_data; 
    547     s->dev.handle_destroy = usb_mouse_handle_destroy; 
     814    s->dev.handle_control = usb_hid_handle_control; 
     815    s->dev.handle_data = usb_hid_handle_data; 
     816    s->dev.handle_destroy = usb_hid_handle_destroy; 
    548817    s->kind = USB_MOUSE; 
    549818 
     
    552821    return (USBDevice *)s; 
    553822} 
     823 
     824USBDevice *usb_keyboard_init(void) 
     825{ 
     826    USBHIDState *s; 
     827 
     828    s = qemu_mallocz(sizeof(USBHIDState)); 
     829    if (!s) 
     830        return NULL; 
     831    s->dev.speed = USB_SPEED_FULL; 
     832    s->dev.handle_packet = usb_generic_handle_packet; 
     833 
     834    s->dev.handle_reset = usb_keyboard_handle_reset; 
     835    s->dev.handle_control = usb_hid_handle_control; 
     836    s->dev.handle_data = usb_hid_handle_data; 
     837    s->dev.handle_destroy = usb_hid_handle_destroy; 
     838    s->kind = USB_KEYBOARD; 
     839 
     840    pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Keyboard"); 
     841 
     842    qemu_add_kbd_event_handler(usb_keyboard_event, &s->kbd); 
     843 
     844    return (USBDevice *) s; 
     845} 
  • trunk/src/host/qemu-neo1973/hw/usb.h

    r2289 r2303  
    224224USBDevice *usb_mouse_init(void); 
    225225USBDevice *usb_tablet_init(void); 
     226USBDevice *usb_keyboard_init(void); 
    226227 
    227228/* usb-msd.c */ 
  • trunk/src/host/qemu-neo1973/vl.c

    r2289 r2303  
    43714371        dev = usb_mouse_init(); 
    43724372    } else if (!strcmp(devname, "tablet")) { 
    4373         dev = usb_tablet_init(); 
     4373        dev = usb_tablet_init(); 
     4374    } else if (!strcmp(devname, "keyboard")) { 
     4375        dev = usb_keyboard_init(); 
    43744376    } else if (strstart(devname, "disk:", &p)) { 
    43754377        dev = usb_msd_init(p); 
Note: See TracChangeset for help on using the changeset viewer.