Annotation of qemu/roms/seabios/src/usb-hid.c, revision 1.1.1.5

1.1       root        1: // Code for handling USB Human Interface Devices (HID).
                      2: //
                      3: // Copyright (C) 2009  Kevin O'Connor <[email protected]>
                      4: //
                      5: // This file may be distributed under the terms of the GNU LGPLv3 license.
                      6: 
                      7: #include "util.h" // dprintf
                      8: #include "usb-hid.h" // usb_keyboard_setup
                      9: #include "config.h" // CONFIG_*
                     10: #include "usb.h" // usb_ctrlrequest
                     11: #include "biosvar.h" // GET_GLOBAL
1.1.1.3   root       12: #include "ps2port.h" // ATKBD_CMD_GETID
1.1       root       13: 
                     14: struct usb_pipe *keyboard_pipe VAR16VISIBLE;
1.1.1.3   root       15: struct usb_pipe *mouse_pipe VAR16VISIBLE;
1.1       root       16: 
                     17: 
                     18: /****************************************************************
                     19:  * Setup
                     20:  ****************************************************************/
                     21: 
1.1.1.3   root       22: // Send USB HID protocol message.
1.1       root       23: static int
1.1.1.3   root       24: set_protocol(struct usb_pipe *pipe, u16 val)
1.1       root       25: {
                     26:     struct usb_ctrlrequest req;
                     27:     req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
                     28:     req.bRequest = HID_REQ_SET_PROTOCOL;
                     29:     req.wValue = val;
                     30:     req.wIndex = 0;
                     31:     req.wLength = 0;
1.1.1.3   root       32:     return send_default_control(pipe, &req, NULL);
1.1       root       33: }
                     34: 
1.1.1.3   root       35: // Send USB HID SetIdle request.
1.1       root       36: static int
1.1.1.3   root       37: set_idle(struct usb_pipe *pipe, int ms)
1.1       root       38: {
                     39:     struct usb_ctrlrequest req;
                     40:     req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
                     41:     req.bRequest = HID_REQ_SET_IDLE;
1.1.1.3   root       42:     req.wValue = (ms/4)<<8;
1.1       root       43:     req.wIndex = 0;
                     44:     req.wLength = 0;
1.1.1.3   root       45:     return send_default_control(pipe, &req, NULL);
1.1       root       46: }
                     47: 
1.1.1.3   root       48: #define KEYREPEATWAITMS 500
                     49: #define KEYREPEATMS 33
                     50: 
                     51: static int
1.1.1.5 ! root       52: usb_kbd_init(struct usbdevice_s *usbdev
        !            53:              , struct usb_endpoint_descriptor *epdesc)
1.1       root       54: {
                     55:     if (! CONFIG_USB_KEYBOARD)
                     56:         return -1;
                     57:     if (keyboard_pipe)
                     58:         // XXX - this enables the first found keyboard (could be random)
                     59:         return -1;
                     60: 
1.1.1.3   root       61:     if (epdesc->wMaxPacketSize != 8)
                     62:         return -1;
1.1       root       63: 
                     64:     // Enable "boot" protocol.
1.1.1.5 ! root       65:     int ret = set_protocol(usbdev->defpipe, 0);
1.1       root       66:     if (ret)
                     67:         return -1;
1.1.1.3   root       68:     // Periodically send reports to enable key repeat.
1.1.1.5 ! root       69:     ret = set_idle(usbdev->defpipe, KEYREPEATMS);
1.1       root       70:     if (ret)
                     71:         return -1;
                     72: 
1.1.1.5 ! root       73:     keyboard_pipe = usb_alloc_pipe(usbdev, epdesc);
1.1.1.3   root       74:     if (!keyboard_pipe)
                     75:         return -1;
                     76: 
                     77:     dprintf(1, "USB keyboard initialized\n");
                     78:     return 0;
                     79: }
                     80: 
                     81: static int
1.1.1.5 ! root       82: usb_mouse_init(struct usbdevice_s *usbdev
        !            83:                , struct usb_endpoint_descriptor *epdesc)
1.1.1.3   root       84: {
                     85:     if (! CONFIG_USB_MOUSE)
                     86:         return -1;
                     87:     if (mouse_pipe)
                     88:         // XXX - this enables the first found mouse (could be random)
                     89:         return -1;
                     90: 
                     91:     if (epdesc->wMaxPacketSize < 3 || epdesc->wMaxPacketSize > 8)
                     92:         return -1;
                     93: 
                     94:     // Enable "boot" protocol.
1.1.1.5 ! root       95:     int ret = set_protocol(usbdev->defpipe, 0);
1.1.1.3   root       96:     if (ret)
                     97:         return -1;
                     98: 
1.1.1.5 ! root       99:     mouse_pipe = usb_alloc_pipe(usbdev, epdesc);
1.1.1.3   root      100:     if (!mouse_pipe)
1.1       root      101:         return -1;
                    102: 
1.1.1.3   root      103:     dprintf(1, "USB mouse initialized\n");
1.1       root      104:     return 0;
                    105: }
                    106: 
1.1.1.3   root      107: // Initialize a found USB HID device (if applicable).
                    108: int
1.1.1.5 ! root      109: usb_hid_init(struct usbdevice_s *usbdev)
1.1.1.3   root      110: {
                    111:     if (! CONFIG_USB_KEYBOARD || ! CONFIG_USB_MOUSE)
                    112:         return -1;
1.1.1.5 ! root      113:     dprintf(2, "usb_hid_init %p\n", usbdev->defpipe);
1.1.1.3   root      114: 
1.1.1.5 ! root      115:     struct usb_interface_descriptor *iface = usbdev->iface;
1.1.1.3   root      116:     if (iface->bInterfaceSubClass != USB_INTERFACE_SUBCLASS_BOOT)
                    117:         // Doesn't support boot protocol.
                    118:         return -1;
                    119: 
                    120:     // Find intr in endpoint.
                    121:     struct usb_endpoint_descriptor *epdesc = findEndPointDesc(
1.1.1.5 ! root      122:         usbdev, USB_ENDPOINT_XFER_INT, USB_DIR_IN);
1.1.1.3   root      123:     if (!epdesc) {
                    124:         dprintf(1, "No usb hid intr in?\n");
                    125:         return -1;
                    126:     }
                    127: 
                    128:     if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD)
1.1.1.5 ! root      129:         return usb_kbd_init(usbdev, epdesc);
1.1.1.3   root      130:     if (iface->bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)
1.1.1.5 ! root      131:         return usb_mouse_init(usbdev, epdesc);
1.1.1.3   root      132:     return -1;
                    133: }
                    134: 
1.1       root      135: 
                    136: /****************************************************************
                    137:  * Keyboard events
                    138:  ****************************************************************/
                    139: 
1.1.1.3   root      140: // Mapping from USB key id to ps2 key sequence.
1.1       root      141: static u16 KeyToScanCode[] VAR16 = {
                    142:     0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020,
                    143:     0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026,
                    144:     0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014,
                    145:     0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003,
                    146:     0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
                    147:     0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a,
                    148:     0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034,
                    149:     0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
                    150:     0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046,
                    151:     0xe11d, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
                    152:     0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e,
                    153:     0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
                    154:     0x0048, 0x0049, 0x0052, 0x0053
                    155: };
                    156: 
1.1.1.3   root      157: // Mapping from USB modifier id to ps2 key sequence.
1.1       root      158: static u16 ModifierToScanCode[] VAR16 = {
                    159:     //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui
                    160:     0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c
                    161: };
                    162: 
1.1.1.3   root      163: #define RELEASEBIT 0x80
                    164: 
                    165: // Format of USB keyboard event data
1.1       root      166: struct keyevent {
                    167:     u8 modifiers;
                    168:     u8 reserved;
                    169:     u8 keys[6];
                    170: };
                    171: 
1.1.1.3   root      172: // Translate data from KeyToScanCode[] to calls to process_key().
1.1       root      173: static void
                    174: prockeys(u16 keys)
                    175: {
                    176:     if (keys > 0xff) {
                    177:         u8 key = keys>>8;
                    178:         if (key == 0xe1) {
                    179:             // Pause key
                    180:             process_key(0xe1);
1.1.1.3   root      181:             process_key(0x1d | (keys & RELEASEBIT));
                    182:             process_key(0x45 | (keys & RELEASEBIT));
1.1       root      183:             return;
                    184:         }
                    185:         process_key(key);
                    186:     }
                    187:     process_key(keys);
                    188: }
                    189: 
1.1.1.3   root      190: // Handle a USB key press/release event.
                    191: static void
                    192: procscankey(u8 key, u8 flags)
                    193: {
                    194:     if (key >= ARRAY_SIZE(KeyToScanCode))
                    195:         return;
                    196:     u16 keys = GET_GLOBAL(KeyToScanCode[key]);
                    197:     if (keys)
                    198:         prockeys(keys | flags);
                    199: }
                    200: 
                    201: // Handle a USB modifier press/release event.
1.1       root      202: static void
1.1.1.3   root      203: procmodkey(u8 mods, u8 flags)
                    204: {
                    205:     int i;
                    206:     for (i=0; mods; i++)
                    207:         if (mods & (1<<i)) {
                    208:             // Modifier key change.
                    209:             prockeys(GET_GLOBAL(ModifierToScanCode[i]) | flags);
                    210:             mods &= ~(1<<i);
                    211:         }
                    212: }
                    213: 
                    214: // Process USB keyboard data.
                    215: static void noinline
1.1       root      216: handle_key(struct keyevent *data)
                    217: {
1.1.1.3   root      218:     dprintf(9, "Got key %x %x\n", data->modifiers, data->keys[0]);
                    219: 
                    220:     // Load old keys.
                    221:     u16 ebda_seg = get_ebda_seg();
                    222:     struct usbkeyinfo old;
                    223:     old.data = GET_EBDA2(ebda_seg, usbkey_last.data);
                    224: 
                    225:     // Check for keys no longer pressed.
                    226:     int addpos = 0;
1.1       root      227:     int i;
1.1.1.3   root      228:     for (i=0; i<ARRAY_SIZE(old.keys); i++) {
                    229:         u8 key = old.keys[i];
                    230:         if (!key)
                    231:             break;
                    232:         int j;
                    233:         for (j=0;; j++) {
                    234:             if (j>=ARRAY_SIZE(data->keys)) {
                    235:                 // Key released.
                    236:                 procscankey(key, RELEASEBIT);
                    237:                 if (i+1 >= ARRAY_SIZE(old.keys) || !old.keys[i+1])
                    238:                     // Last pressed key released - disable repeat.
                    239:                     old.repeatcount = 0xff;
                    240:                 break;
                    241:             }
                    242:             if (data->keys[j] == key) {
                    243:                 // Key still pressed.
                    244:                 data->keys[j] = 0;
                    245:                 old.keys[addpos++] = key;
                    246:                 break;
                    247:             }
                    248:         }
                    249:     }
                    250:     procmodkey(old.modifiers & ~data->modifiers, RELEASEBIT);
                    251: 
                    252:     // Process new keys
                    253:     procmodkey(data->modifiers & ~old.modifiers, 0);
                    254:     old.modifiers = data->modifiers;
1.1       root      255:     for (i=0; i<ARRAY_SIZE(data->keys); i++) {
                    256:         u8 key = data->keys[i];
                    257:         if (!key)
                    258:             continue;
1.1.1.3   root      259:         // New key pressed.
                    260:         procscankey(key, 0);
                    261:         old.keys[addpos++] = key;
                    262:         old.repeatcount = KEYREPEATWAITMS / KEYREPEATMS + 1;
                    263:     }
                    264:     if (addpos < ARRAY_SIZE(old.keys))
                    265:         old.keys[addpos] = 0;
                    266: 
                    267:     // Check for key repeat event.
                    268:     if (addpos) {
                    269:         if (!old.repeatcount)
                    270:             procscankey(old.keys[addpos-1], 0);
                    271:         else if (old.repeatcount != 0xff)
                    272:             old.repeatcount--;
1.1       root      273:     }
1.1.1.3   root      274: 
                    275:     // Update old keys
                    276:     SET_EBDA2(ebda_seg, usbkey_last.data, old.data);
1.1       root      277: }
                    278: 
1.1.1.3   root      279: // Check if a USB keyboard event is pending and process it if so.
                    280: static void
1.1.1.2   root      281: usb_check_key(void)
1.1       root      282: {
                    283:     if (! CONFIG_USB_KEYBOARD)
                    284:         return;
                    285:     struct usb_pipe *pipe = GET_GLOBAL(keyboard_pipe);
                    286:     if (!pipe)
                    287:         return;
                    288: 
                    289:     for (;;) {
                    290:         struct keyevent data;
                    291:         int ret = usb_poll_intr(pipe, &data);
                    292:         if (ret)
                    293:             break;
                    294:         handle_key(&data);
                    295:     }
                    296: }
1.1.1.3   root      297: 
                    298: // Test if USB keyboard is active.
                    299: inline int
                    300: usb_kbd_active(void)
                    301: {
                    302:     if (! CONFIG_USB_KEYBOARD)
                    303:         return 0;
                    304:     return GET_GLOBAL(keyboard_pipe) != NULL;
                    305: }
                    306: 
                    307: // Handle a ps2 style keyboard command.
                    308: inline int
                    309: usb_kbd_command(int command, u8 *param)
                    310: {
                    311:     if (! CONFIG_USB_KEYBOARD)
                    312:         return -1;
                    313:     dprintf(9, "usb keyboard cmd=%x\n", command);
                    314:     switch (command) {
                    315:     case ATKBD_CMD_GETID:
                    316:         // Return the id of a standard AT keyboard.
                    317:         param[0] = 0xab;
                    318:         param[1] = 0x83;
                    319:         return 0;
                    320:     default:
                    321:         return -1;
                    322:     }
                    323: }
                    324: 
                    325: 
                    326: /****************************************************************
                    327:  * Mouse events
                    328:  ****************************************************************/
                    329: 
                    330: // Format of USB mouse event data
                    331: struct mouseevent {
                    332:     u8 buttons;
                    333:     u8 x, y;
                    334:     u8 reserved[5];
                    335: };
                    336: 
                    337: // Process USB mouse data.
                    338: static void
                    339: handle_mouse(struct mouseevent *data)
                    340: {
                    341:     dprintf(9, "Got mouse b=%x x=%x y=%x\n", data->buttons, data->x, data->y);
                    342: 
                    343:     s8 x = data->x, y = -data->y;
                    344:     u8 flag = ((data->buttons & 0x7) | (1<<3)
                    345:                | (x & 0x80 ? (1<<4) : 0) | (y & 0x80 ? (1<<5) : 0));
                    346:     process_mouse(flag);
                    347:     process_mouse(x);
                    348:     process_mouse(y);
                    349: }
                    350: 
                    351: // Check if a USB mouse event is pending and process it if so.
                    352: static void
                    353: usb_check_mouse(void)
                    354: {
                    355:     if (! CONFIG_USB_MOUSE)
                    356:         return;
                    357:     struct usb_pipe *pipe = GET_GLOBAL(mouse_pipe);
                    358:     if (!pipe)
                    359:         return;
                    360: 
                    361:     for (;;) {
                    362:         struct mouseevent data;
                    363:         int ret = usb_poll_intr(pipe, &data);
                    364:         if (ret)
                    365:             break;
                    366:         handle_mouse(&data);
                    367:     }
                    368: }
                    369: 
                    370: // Test if USB mouse is active.
                    371: inline int
                    372: usb_mouse_active(void)
                    373: {
                    374:     if (! CONFIG_USB_MOUSE)
                    375:         return 0;
                    376:     return GET_GLOBAL(mouse_pipe) != NULL;
                    377: }
                    378: 
                    379: // Handle a ps2 style mouse command.
                    380: inline int
                    381: usb_mouse_command(int command, u8 *param)
                    382: {
                    383:     if (! CONFIG_USB_MOUSE)
                    384:         return -1;
                    385:     dprintf(9, "usb mouse cmd=%x\n", command);
                    386:     switch (command) {
                    387:     case PSMOUSE_CMD_ENABLE:
                    388:     case PSMOUSE_CMD_DISABLE:
                    389:     case PSMOUSE_CMD_SETSCALE11:
                    390:         return 0;
                    391:     case PSMOUSE_CMD_SETSCALE21:
                    392:     case PSMOUSE_CMD_SETRATE:
                    393:     case PSMOUSE_CMD_SETRES:
                    394:         // XXX
                    395:         return 0;
                    396:     case PSMOUSE_CMD_RESET_BAT:
                    397:     case PSMOUSE_CMD_GETID:
                    398:         // Return the id of a standard AT mouse.
                    399:         param[0] = 0xaa;
                    400:         param[1] = 0x00;
                    401:         return 0;
                    402: 
                    403:     case PSMOUSE_CMD_GETINFO:
                    404:         param[0] = 0x00;
                    405:         param[1] = 4;
                    406:         param[2] = 100;
                    407:         return 0;
                    408: 
                    409:     default:
                    410:         return -1;
                    411:     }
                    412: }
                    413: 
                    414: // Check for USB events pending - called periodically from timer interrupt.
                    415: void
                    416: usb_check_event(void)
                    417: {
                    418:     usb_check_key();
                    419:     usb_check_mouse();
                    420: }

unix.superglobalmegacorp.com

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