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

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

unix.superglobalmegacorp.com

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