diff --git a/board-qemu/slof/Makefile b/board-qemu/slof/Makefile index ea76c42..dedccf7 100644 --- a/board-qemu/slof/Makefile +++ b/board-qemu/slof/Makefile @@ -48,6 +48,7 @@ USB_FFS_FILES = \ $(SLOFCMNDIR)/fs/devices/pci-class_0c.fs \ $(SLOFCMNDIR)/fs/usb/dev-hci.fs \ $(SLOFCMNDIR)/fs/usb/slofdev.fs \ + $(SLOFCMNDIR)/fs/usb/dev-parent-calls.fs \ $(SLOFCMNDIR)/fs/usb/dev-keyb.fs \ $(SLOFCMNDIR)/fs/usb/dev-mouse.fs \ $(SLOFCMNDIR)/fs/usb/dev-storage.fs diff --git a/lib/libusb/Makefile b/lib/libusb/Makefile index ca3a8fa..7c8b317 100644 --- a/lib/libusb/Makefile +++ b/lib/libusb/Makefile @@ -22,7 +22,7 @@ TARGET = ../libusb.a all: $(TARGET) -SRCS = usb-core.c usb-ohci.c usb-ehci.c usb-slof.c +SRCS = usb-core.c usb-ohci.c usb-ehci.c usb-slof.c usb-key.c usb-hid.c OBJS = $(SRCS:%.c=%.o) diff --git a/lib/libusb/usb-core.c b/lib/libusb/usb-core.c index 3a96795..8207adc 100644 --- a/lib/libusb/usb-core.c +++ b/lib/libusb/usb-core.c @@ -124,6 +124,17 @@ void usb_put_pipe(struct usb_pipe *pipe) } } +int usb_poll_intr(struct usb_pipe *pipe, uint8_t *buf) +{ + struct usb_dev *dev = NULL; + if (pipe && pipe->dev) { + dev = pipe->dev; + if (validate_hcd_ops(dev) && dev->hcidev->ops->poll_intr) + return dev->hcidev->ops->poll_intr(pipe, buf); + } + return 0; +} + void usb_hcd_register(struct usb_hcd_ops *ops) { struct usb_hcd_ops *list; @@ -272,6 +283,40 @@ int usb_dev_populate_pipe(struct usb_dev *dev, struct usb_ep_descr *ep, return true; } +static void usb_dev_copy_epdesc(struct usb_dev *dev, struct usb_ep_descr *ep) +{ + uint32_t ep_cnt; + + ep_cnt = dev->ep_cnt; + if (ep_cnt < USB_DEV_EP_MAX) + memcpy((void *)&dev->ep[ep_cnt], ep, sizeof(*ep)); + else + dprintf("usb-core: only %d EPs supported\n", USB_DEV_EP_MAX); + dev->ep_cnt++; +} + +int usb_hid_init(void *vdev) +{ + struct usb_dev *dev; + dev = (struct usb_dev *) vdev; + if (!dev) + return false; + if (dev->class == DEV_HID_KEYB) + usb_hid_kbd_init(dev); + return true; +} + +int usb_hid_exit(void *vdev) +{ + struct usb_dev *dev; + dev = (struct usb_dev *) vdev; + if (!dev) + return false; + if (dev->class == DEV_HID_KEYB) + usb_hid_kbd_exit(dev); + return true; +} + static int usb_handle_device(struct usb_dev *dev, struct usb_dev_config_descr *cfg, uint8_t *ptr, uint16_t len) { @@ -296,7 +341,7 @@ static int usb_handle_device(struct usb_dev *dev, struct usb_dev_config_descr *c case DESCR_TYPE_ENDPOINT: ep = (struct usb_ep_descr *)ptr; dev->intf_num = intf->bInterfaceNumber; - /* usb_dev_populate_pipe(dev, ep, NULL, 0); */ + usb_dev_copy_epdesc(dev, ep); break; case DESCR_TYPE_HID: hid = (struct usb_dev_hid_descr *)ptr; diff --git a/lib/libusb/usb-core.h b/lib/libusb/usb-core.h index ca3b627..a44b23d 100644 --- a/lib/libusb/usb-core.h +++ b/lib/libusb/usb-core.h @@ -238,6 +238,7 @@ struct usb_hcd_ops { struct usb_pipe* (*get_pipe)(struct usb_dev *dev, struct usb_ep_descr *ep, char *buf, size_t len); void (*put_pipe)(struct usb_pipe *); + int (*poll_intr)(struct usb_pipe *, uint8_t *); struct usb_hcd_ops *next; unsigned int usb_type; }; @@ -246,6 +247,7 @@ extern void usb_hcd_register(struct usb_hcd_ops *ops); extern struct usb_pipe *usb_get_pipe(struct usb_dev *dev, struct usb_ep_descr *ep, char *buf, size_t len); extern void usb_put_pipe(struct usb_pipe *pipe); +extern int usb_poll_intr(struct usb_pipe *pipe, uint8_t *buf); extern int usb_send_ctrl(struct usb_pipe *pipe, struct usb_dev_req *req, void *data); extern struct usb_dev *usb_devpool_get(void); extern void usb_devpool_put(struct usb_dev *); @@ -253,5 +255,7 @@ extern int setup_new_device(struct usb_dev *dev, unsigned int port); extern int slof_usb_handle(struct usb_dev *dev); extern int usb_dev_populate_pipe(struct usb_dev *dev, struct usb_ep_descr *ep, void *buf, size_t len); +extern int usb_hid_kbd_init(struct usb_dev *dev); +extern int usb_hid_kbd_exit(struct usb_dev *dev); #endif diff --git a/lib/libusb/usb-hid.c b/lib/libusb/usb-hid.c new file mode 100644 index 0000000..af0c683 --- /dev/null +++ b/lib/libusb/usb-hid.c @@ -0,0 +1,420 @@ +/***************************************************************************** + * Copyright (c) 2013 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include +#include +#include + +#include "usb-core.h" +#include "usb-key.h" + +/* + * HID Spec Version 1.11 + */ + +#define HID_REQ_GET_REPORT 0x01 +#define HID_REQ_GET_IDLE 0x02 +#define HID_REQ_GET_PROTOCOL 0x03 +#define HID_REQ_SET_REPORT 0x09 +#define HID_REQ_SET_IDLE 0x0A +#define HID_REQ_SET_PROTOCOL 0x0B + +//#define KEY_DEBUG + +/* HID SPEC - 7.2.6 Set_Protocol Request */ +static int usb_hid_set_protocol(struct usb_dev *dev, uint16_t value) +{ + struct usb_dev_req req; + if (!dev) + return false; + req.bmRequestType = REQT_TYPE_CLASS | REQT_REC_INTERFACE | REQT_DIR_OUT; + req.bRequest = HID_REQ_SET_PROTOCOL; + write_reg16(&req.wValue, value); + write_reg16(&req.wIndex, dev->intf_num); + req.wLength = 0; + return usb_send_ctrl(dev->control, &req, NULL); +} + +/* HID SPEC - 7.2.4 Set_Idle Request */ +static int usb_hid_set_idle(struct usb_dev *dev, uint16_t ms_delay) +{ + struct usb_dev_req req; + if (!dev) + return false; + req.bmRequestType = REQT_TYPE_CLASS | REQT_REC_INTERFACE | REQT_DIR_OUT; + req.bRequest = HID_REQ_SET_IDLE; + write_reg16(&req.wValue, (ms_delay/4) << 8); + write_reg16(&req.wIndex, dev->intf_num); + req.wLength = 0; + return usb_send_ctrl(dev->control, &req, NULL); +} + +/* ring buffer with RD/WR indices for key buffering */ +static uint8_t keybuf[256]; /* size fixed to byte range ! */ +uint8_t r_ptr = 0; /* RD-index for Keyboard-Buffer */ +uint8_t w_ptr = 0; /* WR-index for Keyboard-Buffer */ + +/* variables for LED status */ +uint8_t set_leds; +const uint8_t *key_std = NULL; +const uint8_t *key_std_shift = NULL; + +/** + * read character from Keyboard-Buffer + * + * @param - + * @return > 0 Keycode + * = 0 if no key available + */ +static int read_key(void) +{ + if (r_ptr != w_ptr) + return (int)keybuf[r_ptr++]; + else + return false; +} + +/** + * Store character into Keyboard-Buffer + * + * @param Key = detected ASCII-Key (> 0) + * @return - + */ +static void write_key(uint8_t key) +{ + if ((w_ptr + 1) != r_ptr) + keybuf[w_ptr++] = key; +} + +/** + * Convert keyboard usage-ID to ANSI-Code + * + * @param Ctrl=Modifier Byte + * Key =Usage ID from USB Keyboard + * @return - + */ +static void get_char(uint8_t ctrl, uint8_t keypos) +{ + uint8_t ch; + +#ifdef KEY_DEBUG + printf("pos %02X\n", keypos); +#endif + + if (set_leds & LED_CAPS_LOCK) /* is CAPS Lock set ? */ + ctrl |= MODIFIER_SHIFT; /* simulate shift */ + + if (ctrl == 0) { + ch = key_std[keypos]; + if (ch != 0) + write_key(ch); + return; + } + + if (ctrl & MODIFIER_SHIFT) { + ch = key_std_shift[keypos]; + if (ch != 0) + write_key(ch); + return; + } + + if (ctrl & MODIFIER_CTRL) { + ch = keycodes_ctrl[keypos]; + if (ch != 0) + write_key(ch); + return; + } + + if (ctrl == MODIFIER_ALT_GR) { + ch = keycodes_alt_GR[keypos]; + if (ch != 0) + write_key(ch); + return; + } +} + +static void check_key_code(uint8_t *buf) +{ + static uint8_t key_last[6]; /* list of processed keys */ + uint8_t i, j, key_pos; + + /* set translation table to defaults */ + if ((key_std == NULL) || (key_std_shift == NULL)) { + key_std = keycodes_std_US; + key_std_shift = keycodes_shift_US; + } + + if (buf[0] & MODIFIER_SHIFT) /* any shift key pressed ? */ + set_leds &= ~LED_CAPS_LOCK; /* CAPS-LOCK-LED always off */ + + i = 2; /* skip modifier byte and reserved byte */ + while (i < 8) { + key_pos = buf[i]; + if ((key_pos != 0) && (key_pos <= 100)) { /* support for 101 keys */ + j = 0; + /* search if already processed */ + while ((j < 6) && (key_pos != key_last[j])) + j++; + + if (j >= 6) { /* not found (= not processed) */ + switch (key_pos) { + case 0x39: /* caps-lock key ? */ + case 0x32: /* caps-lock key ? */ + set_leds ^= LED_CAPS_LOCK; + break; + + case 0x3a: /* F1 */ + write_key(0x1b); + write_key(0x5b); + write_key(0x31); + write_key(0x31); + write_key(0x7e); + break; + + case 0x3b: /* F2 */ + write_key(0x1b); + write_key(0x5b); + write_key(0x31); + write_key(0x32); + write_key(0x7e); + break; + + case 0x3c: + write_key(0x1b); /* F3 */ + write_key(0x5b); + write_key(0x31); + write_key(0x33); + write_key(0x7e); + break; + + case 0x3d: + write_key(0x1b); /* F4 */ + write_key(0x5b); + write_key(0x31); + write_key(0x34); + write_key(0x7e); + break; + + case 0x3e: + write_key(0x1b); /* F5 */ + write_key(0x5b); + write_key(0x31); + write_key(0x35); + write_key(0x7e); + break; + + case 0x3f: + write_key(0x1b); /* F6 */ + write_key(0x5b); + write_key(0x31); + write_key(0x37); + write_key(0x7e); + break; + + case 0x40: + write_key(0x1b); /* F7 */ + write_key(0x5b); + write_key(0x31); + write_key(0x38); + write_key(0x7e); + break; + + case 0x41: + write_key(0x1b); /* F8 */ + write_key(0x5b); + write_key(0x31); + write_key(0x39); + write_key(0x7e); + break; + + case 0x42: + write_key(0x1b); /* F9 */ + write_key(0x5b); + write_key(0x31); + write_key(0x30); + write_key(0x7e); + break; + + case 0x43: + write_key(0x1b); /* F10 */ + write_key(0x5b); + write_key(0x31); + write_key(0x31); + write_key(0x7e); + break; + + case 0x44: + write_key(0x1b); /* F11 */ + write_key(0x5b); + write_key(0x31); + write_key(0x33); + write_key(0x7e); + break; + + case 0x45: + write_key(0x1b); /* F12 */ + write_key(0x5b); + write_key(0x31); + write_key(0x34); + write_key(0x7e); + break; + + case 0x47: /* scroll-lock key ? */ + set_leds ^= LED_SCROLL_LOCK; + break; + + case 0x49: + write_key(0x1b); /* INS */ + write_key(0x5b); + write_key(0x31); + write_key(0x7e); + break; + + case 0x4a: + write_key(0x1b); /* HOME */ + write_key(0x5b); + write_key(0x32); + write_key(0x7e); + break; + + case 0x4b: + write_key(0x1b); /* PgUp */ + write_key(0x5b); + write_key(0x33); + write_key(0x7e); + break; + + case 0x4c: + write_key(0x1b); /* DEL */ + write_key(0x5b); + write_key(0x34); + write_key(0x7e); + break; + + case 0x4d: + write_key(0x1b); /* END */ + write_key(0x5b); + write_key(0x35); + write_key(0x7e); + break; + + case 0x4e: + write_key(0x1b); /* PgDn */ + write_key(0x5b); + write_key(0x36); + write_key(0x7e); + break; + + case 0x4f: + write_key(0x1b); /* R-Arrow */ + write_key(0x5b); + write_key(0x43); + break; + + case 0x50: + write_key(0x1b); /* L-Arrow */ + write_key(0x5b); + write_key(0x44); + break; + + case 0x51: + write_key(0x1b); /* D-Arrow */ + write_key(0x5b); + write_key(0x42); + break; + + case 0x52: + write_key(0x1b); /* U-Arrow */ + write_key(0x5b); + write_key(0x41); + break; + + case 0x53: /* num-lock key ? */ + set_leds ^= LED_NUM_LOCK; + break; + + default: + /* convert key position to ASCII code */ + get_char(buf[0], key_pos); + break; + } + } + } + i++; + } + /*****************************************/ + /* all keys are processed, create a copy */ + /* to flag them as processed */ + /*****************************************/ + for (i = 2, j = 0; j < 6; i++, j++) + key_last[j] = buf[i]; /* copy all actual keys to last */ +} + +#define USB_HID_SIZE 128 +uint32_t *kbd_buffer; + +int usb_hid_kbd_init(struct usb_dev *dev) +{ + int i; + usb_hid_set_protocol(dev, 0); + usb_hid_set_idle(dev, 500); + + kbd_buffer = SLOF_dma_alloc(USB_HID_SIZE); + if (!kbd_buffer) { + printf("%s: unable to allocate keyboard buffer\n", __func__); + return false; + } + +#ifdef KEY_DEBUG + printf("HID kbd init %d\n", dev->ep_cnt); +#endif + for (i = 0; i < dev->ep_cnt; i++) { + if ((dev->ep[i].bmAttributes & USB_EP_TYPE_MASK) + == USB_EP_TYPE_INTR) + usb_dev_populate_pipe(dev, &dev->ep[i], kbd_buffer, USB_HID_SIZE); + } + return true; +} + +int usb_hid_kbd_exit(struct usb_dev *dev) +{ + if (dev->intr) { + usb_put_pipe(dev->intr); + dev->intr = NULL; + } + SLOF_dma_free(kbd_buffer, USB_HID_SIZE); + return true; +} + +unsigned char usb_key_available(void *dev) +{ + if (dev && r_ptr != w_ptr) + return true; + else + return false; +} + +unsigned char usb_read_keyb(void *vdev) +{ + struct usb_dev *dev = vdev; + uint8_t key[8]; + + if (!dev) + return false; + + memset(key, 0, 8); + while (usb_poll_intr(dev->intr, key)) { + check_key_code(key); + memset(key, 0, 8); + } + return read_key(); +} diff --git a/lib/libusb/usb-key.c b/lib/libusb/usb-key.c new file mode 100644 index 0000000..7fb45da --- /dev/null +++ b/lib/libusb/usb-key.c @@ -0,0 +1,446 @@ +/***************************************************************************** + * Copyright (c) 2013 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include + +/***********************************/ +/* Keycodes for US Keyboard */ +/* - no control keys pressed - */ +/***********************************/ +const uint8_t keycodes_std_US[] = { + 0, /* 0 00 Reserved (no event indicated) */ + 0, /* 1 01 Keyboard ErrorRollOver */ + 0, /* 2 02 Keyboard POSTFail */ + 0, /* 3 03 Keyboard ErrorUndefined */ + 'a', /* 4 04 Keyboard a and A 31 */ + 'b', /* 5 05 Keyboard b and B 50 */ + 'c', /* 6 06 Keyboard c and C 48 */ + 'd', /* 7 07 Keyboard d and D 33 */ + 'e', /* 8 08 Keyboard e and E 19 */ + 'f', /* 9 09 Keyboard f and F 34 */ + 'g', /* 10 0A Keyboard g and G 35 */ + 'h', /* 11 0B Keyboard h and H 36 */ + 'i', /* 12 0C Keyboard i and I 24 */ + 'j', /* 13 0D Keyboard j and J 37 */ + 'k', /* 14 0E Keyboard k and K 38 */ + 'l', /* 15 0F Keyboard l and L 39 */ + 'm', /* 16 10 Keyboard m and M 52 */ + 'n', /* 17 11 Keyboard n and N 51 */ + 'o', /* 18 12 Keyboard o and O 25 */ + 'p', /* 19 13 Keyboard p and P 26 */ + 'q', /* 20 14 Keyboard q and Q 17 */ + 'r', /* 21 15 Keyboard r and R 20 */ + 's', /* 22 16 Keyboard s and S 32 */ + 't', /* 23 17 Keyboard t and T 21 */ + 'u', /* 24 18 Keyboard u and U 23 */ + 'v', /* 25 19 Keyboard v and V 49 */ + 'w', /* 26 1A Keyboard w and W 18 */ + 'x', /* 27 1B Keyboard x and X 47 */ + 'y', /* 28 1C Keyboard y and Y 22 */ + 'z', /* 29 1D Keyboard z and Z 46 */ + '1', /* 30 1E Keyboard 1 and ! 2 */ + '2', /* 31 1F Keyboard 2 and @ 3 */ + '3', /* 32 20 Keyboard 3 and # 4 */ + '4', /* 33 21 Keyboard 4 and $ 5 */ + '5', /* 34 22 Keyboard 5 and % 6 */ + '6', /* 35 23 Keyboard 6 and ^ 7 */ + '7', /* 36 24 Keyboard 7 and & 8 */ + '8', /* 37 25 Keyboard 8 and * 9 */ + '9', /* 38 26 Keyboard 9 and ( 10 */ + '0', /* 39 27 Keyboard 0 and ) 11 */ + 13, /* 40 28 Keyboard Return (ENTER) 43 */ + 27, /* 41 29 Keyboard ESCAPE 110 */ + 8, /* 42 2A Keyboard DELETE (BS) 15 */ + 9, /* 43 2B Keyboard Tab 16 */ + ' ', /* 44 2C Keyboard Spacebar 61 */ + '-', /* 45 2D Keyboard - and (underscore) 12 */ + '=', /* 46 2E Keyboard = and + 13 */ + '[', /* 47 2F Keyboard [ and { 27 */ + ']', /* 48 30 Keyboard ] and } 28 */ + '\\', /* 49 31 Keyboard \ and | 29 */ + '\\', /* 50 32 Keyboard \ and | 42 */ + ';', /* 51 33 Keyboard ; and : 40 */ + 39, /* 52 34 Keyboard ' and " 41 */ + 96, /* 53 35 Keyboard Grave Accent and Tilde 1 */ + ',', /* 54 36 Keyboard , and < 53 */ + '.', /* 55 37 Keyboard . and > 54 */ + '/', /* 56 38 Keyboard / and ? 55 */ + 0, /* 57 39 Keyboard Caps Lock 30 */ + 0, /* 58 3A Keyboard F1 112 */ + 0, /* 59 3B Keyboard F2 113 */ + 0, /* 60 3C Keyboard F3 114 */ + 0, /* 61 3D Keyboard F4 115 */ + 0, /* 62 3E Keyboard F5 116 */ + 0, /* 63 3F Keyboard F6 117 */ + 0, /* 64 40 Keyboard F7 118 */ + 0, /* 65 41 Keyboard F8 119 */ + 0, /* 66 42 Keyboard F9 120 */ + 0, /* 67 43 Keyboard F10 121 */ + 0, /* 68 44 Keyboard F11 122 */ + 0, /* 69 45 Keyboard F12 123 */ + 0, /* 70 46 Keyboard PrintScreen 124 */ + 0, /* 71 47 Keyboard Scroll Lock 125 */ + 0, /* 72 48 Keyboard Pause 126 */ + 0, /* 73 49 Keyboard Insert 75 */ + 0, /* 74 4A Keyboard Home 80 */ + 0, /* 75 4B Keyboard PageUp 85 */ + 0, /* 76 4C Keyboard Delete Forward 76 */ + 0, /* 77 4D Keyboard End 81 */ + 0, /* 78 4E Keyboard PageDown 86 */ + 0, /* 79 4F Keyboard RightArrow 89 */ + 0, /* 80 50 Keyboard LeftArrow 79 */ + 0, /* 81 51 Keyboard DownArrow 84 */ + 0, /* 82 52 Keyboard UpArrow 83 */ + 0, /* 83 53 Keypad Num Lock and Clear 90 */ + '/', /* 84 54 Keypad / 95 */ + '*', /* 85 55 Keypad * 100 */ + '-', /* 86 56 Keypad - 105 */ + '+', /* 87 57 Keypad + 106 */ + 13, /* 88 58 Keypad ENTER 108 */ + '1', /* 89 59 Keypad 1 and End 93 */ + '2', /* 90 5A Keypad 2 and Down Arrow 98 */ + '3', /* 91 5B Keypad 3 and PageDn 103 */ + '4', /* 92 5C Keypad 4 and Left Arrow 92 */ + '5', /* 93 5D Keypad 5 97 */ + '6', /* 94 5E Keypad 6 and Right Arrow 102 */ + '7', /* 95 5F Keypad 7 and Home 91 */ + '8', /* 96 60 Keypad 8 and Up Arrow 96 */ + '9', /* 97 61 Keypad 9 and PageUp 101 */ + '0', /* 98 62 Keypad 0 and Insert 99 */ + '.', /* 99 63 Keypad . and Delete 104 */ + '\\' /* 100 64 Keyboard Non-US \ and | 45 */ +}; + +/***********************************/ +/* Keycodes for US Keyboard */ +/* - SHIFT-KEY pressed - */ +/***********************************/ +const uint8_t keycodes_shift_US[] = { + 0, /* 0 00 Reserved (no event indicated) */ + 0, /* 1 01 Keyboard ErrorRollOver */ + 0, /* 2 02 Keyboard POSTFail */ + 0, /* 3 03 Keyboard ErrorUndefined */ + 'A', /* 4 04 Keyboard a and A 31 */ + 'B', /* 5 05 Keyboard b and B 50 */ + 'C', /* 6 06 Keyboard c and C 48 */ + 'D', /* 7 07 Keyboard d and D 33 */ + 'E', /* 8 08 Keyboard e and E 19 */ + 'F', /* 9 09 Keyboard f and F 34 */ + 'G', /* 10 0A Keyboard g and G 35 */ + 'H', /* 11 0B Keyboard h and H 36 */ + 'I', /* 12 0C Keyboard i and I 24 */ + 'J', /* 13 0D Keyboard j and J 37 */ + 'K', /* 14 0E Keyboard k and K 38 */ + 'L', /* 15 0F Keyboard l and L 39 */ + 'M', /* 16 10 Keyboard m and M 52 */ + 'N', /* 17 11 Keyboard n and N 51 */ + 'O', /* 18 12 Keyboard o and O 25 */ + 'P', /* 19 13 Keyboard p and P 26 */ + 'Q', /* 20 14 Keyboard q and Q 17 */ + 'R', /* 21 15 Keyboard r and R 20 */ + 'S', /* 22 16 Keyboard s and S 32 */ + 'T', /* 23 17 Keyboard t and T 21 */ + 'U', /* 24 18 Keyboard u and U 23 */ + 'V', /* 25 19 Keyboard v and V 49 */ + 'W', /* 26 1A Keyboard w and W 18 */ + 'X', /* 27 1B Keyboard x and X 47 */ + 'Y', /* 28 1C Keyboard y and Y 22 */ + 'Z', /* 29 1D Keyboard z and Z 46 */ + '!', /* 30 1E Keyboard 1 and ! 2 */ + '@', /* 31 1F Keyboard 2 and @ 3 */ + '#', /* 32 20 Keyboard 3 and # 4 */ + '$', /* 33 21 Keyboard 4 and $ 5 */ + '%', /* 34 22 Keyboard 5 and % 6 */ + '^', /* 35 23 Keyboard 6 and ^ 7 */ + '&', /* 36 24 Keyboard 7 and & 8 */ + '*', /* 37 25 Keyboard 8 and * 9 */ + '(', /* 38 26 Keyboard 9 and ( 10 */ + ')', /* 39 27 Keyboard 0 and ) 11 */ + 13, /* 40 28 Keyboard Return (ENTER) 43 */ + 27, /* 41 29 Keyboard ESCAPE 110 */ + 8, /* 42 2A Keyboard DELETE (BS) 15 */ + 9, /* 43 2B Keyboard Tab 16 */ + ' ', /* 44 2C Keyboard Spacebar 61 */ + '_', /* 45 2D Keyboard - and (underscore) 12 */ + '+', /* 46 2E Keyboard = and + 13 */ + '{', /* 47 2F Keyboard [ and { 27 */ + '}', /* 48 30 Keyboard ] and } 28 */ + '|', /* 49 31 Keyboard \ and | 29 */ + '|', /* 50 32 Keyboard \ and | 42 */ + ':', /* 51 33 Keyboard ; and : 40 */ + '"', /* 52 34 Keyboard ' and " 41 */ + '~', /* 53 35 Keyboard Grave Accent and Tilde 1 */ + '<', /* 54 36 Keyboard , and < 53 */ + '>', /* 55 37 Keyboard . and > 54 */ + '?', /* 56 38 Keyboard / and ? 55 */ + 0, /* 57 39 Keyboard Caps Lock 30 */ + 0, /* 58 3A Keyboard F1 112 */ + 0, /* 59 3B Keyboard F2 113 */ + 0, /* 60 3C Keyboard F3 114 */ + 0, /* 61 3D Keyboard F4 115 */ + 0, /* 62 3E Keyboard F5 116 */ + 0, /* 63 3F Keyboard F6 117 */ + 0, /* 64 40 Keyboard F7 118 */ + 0, /* 65 41 Keyboard F8 119 */ + 0, /* 66 42 Keyboard F9 120 */ + 0, /* 67 43 Keyboard F10 121 */ + 0, /* 68 44 Keyboard F11 122 */ + 0, /* 69 45 Keyboard F12 123 */ + 0, /* 70 46 Keyboard PrintScreen 124 */ + 0, /* 71 47 Keyboard Scroll Lock 125 */ + 0, /* 72 48 Keyboard Pause 126 */ + 48, /* 73 49 Keyboard Insert 75 */ + 55, /* 74 4A Keyboard Home 80 */ + 57, /* 75 4B Keyboard PageUp 85 */ + 46, /* 76 4C Keyboard Delete Forward 76 */ + 49, /* 77 4D Keyboard End 81 */ + 51, /* 78 4E Keyboard PageDown 86 */ + 54, /* 79 4F Keyboard RightArrow 89 */ + 52, /* 80 50 Keyboard LeftArrow 79 */ + 50, /* 81 51 Keyboard DownArrow 84 */ + 56, /* 82 52 Keyboard UpArrow 83 */ + 0, /* 83 53 Keypad Num Lock and Clear 90 */ + '/', /* 84 54 Keypad / 95 */ + '*', /* 85 55 Keypad * 100 */ + '-', /* 86 56 Keypad - 105 */ + '+', /* 87 57 Keypad + 106 */ + 13, /* 88 58 Keypad ENTER 108 */ + '1', /* 89 59 Keypad 1 and End 93 */ + '2', /* 90 5A Keypad 2 and Down Arrow 98 */ + '3', /* 91 5B Keypad 3 and PageDn 103 */ + '4', /* 92 5C Keypad 4 and Left Arrow 92 */ + '5', /* 93 5D Keypad 5 97 */ + '6', /* 94 5E Keypad 6 and Right Arrow 102 */ + '7', /* 95 5F Keypad 7 and Home 91 */ + '8', /* 96 60 Keypad 8 and Up Arrow 96 */ + '9', /* 97 61 Keypad 9 and PageUp 101 */ + '0', /* 98 62 Keypad 0 and Insert 99 */ + '.', /* 99 63 Keypad . and Delete 104 */ + '|' /* 100 64 Keyboard Non-US \ and | 45 */ +}; + +/***********************************/ +/* Keycodes for 1 byte translation */ +/* - CONTROL-KEY pressed - */ +/***********************************/ +const uint8_t keycodes_alt_GR[] = { + 0, /* 0 00 Reserved (no event indicated) */ + 0, /* 1 01 Keyboard ErrorRollOver */ + 0, /* 2 02 Keyboard POSTFail */ + 0, /* 3 03 Keyboard ErrorUndefined */ + 0, /* 4 04 Keyboard a and A 31 */ + 0, /* 5 05 Keyboard b and B 50 */ + 0, /* 6 06 Keyboard c and C 48 */ + 0, /* 7 07 Keyboard d and D 33 */ + 0, /* 8 08 Keyboard e and E 19 */ + 0, /* 9 09 Keyboard f and F 34 */ + 0, /* 10 0A Keyboard g and G 35 */ + 0, /* 11 0B Keyboard h and H 36 */ + 0, /* 12 0C Keyboard i and I 24 */ + 0, /* 13 0D Keyboard j and J 37 */ + 0, /* 14 0E Keyboard k and K 38 */ + 0, /* 15 0F Keyboard l and L 39 */ + 0, /* 16 10 Keyboard m and M 52 */ + 0, /* 17 11 Keyboard n and N 51 */ + 0, /* 18 12 Keyboard o and O 25 */ + 0, /* 19 13 Keyboard p and P 26 */ + '@', /* 20 14 Keyboard q and Q 17 */ + 0, /* 21 15 Keyboard r and R 20 */ + 0, /* 22 16 Keyboard s and S 32 */ + 0, /* 23 17 Keyboard t and T 21 */ + 0, /* 24 18 Keyboard u and U 23 */ + 0, /* 25 19 Keyboard v and V 49 */ + 0, /* 26 1A Keyboard w and W 18 */ + 0, /* 27 1B Keyboard x and X 47 */ + 0, /* 28 1C Keyboard y and Y 22 */ + 0, /* 29 1D Keyboard z and Z 46 */ + 0, /* 30 1E Keyboard 1 and ! 2 */ + 0, /* 31 1F Keyboard 2 and @ 3 */ + 0, /* 32 20 Keyboard 3 and # 4 */ + 0, /* 33 21 Keyboard 4 and $ 5 */ + 0, /* 34 22 Keyboard 5 and % 6 */ + 0, /* 35 23 Keyboard 6 and ^ 7 */ + '{', /* 36 24 Keyboard 7 and & 8 */ + '[', /* 37 25 Keyboard 8 and * 9 */ + ']', /* 38 26 Keyboard 9 and ( 10 */ + '}', /* 39 27 Keyboard 0 and ) 11 */ + 0, /* 40 28 Keyboard Return (ENTER) 43 */ + 0, /* 41 29 Keyboard ESCAPE 110 */ + 0, /* 42 2A Keyboard DELETE (BS) 15 */ + 0, /* 43 2B Keyboard Tab 16 */ + 0, /* 44 2C Keyboard Spacebar 61 */ + '\\', /* 45 2D Keyboard - and (underscore) 12 */ + 0, /* 46 2E Keyboard = and + 13 */ + 0, /* 47 2F Keyboard [ and { 27 */ + '~', /* 48 30 Keyboard ] and } 28 */ + 0, /* 49 31 Keyboard \ and | 29 */ + 0, /* 50 32 Keyboard Non-US # and ~ 42 */ + 0, /* 51 33 Keyboard ; and : 40 */ + 0, /* 52 34 Keyboard ' and " 41 */ + 0, /* 53 35 Keyboard Grave Accent and Tilde 1 */ + 0, /* 54 36 Keyboard , and < 53 */ + 0, /* 55 37 Keyboard . and > 54 */ + 0, /* 56 38 Keyboard / and ? 55 */ + 0, /* 57 39 Keyboard Caps Lock 30 */ + 0, /* 58 3A Keyboard F1 112 */ + 0, /* 59 3B Keyboard F2 113 */ + 0, /* 60 3C Keyboard F3 114 */ + 0, /* 61 3D Keyboard F4 115 */ + 0, /* 62 3E Keyboard F5 116 */ + 0, /* 63 3F Keyboard F6 117 */ + 0, /* 64 40 Keyboard F7 118 */ + 0, /* 65 41 Keyboard F8 119 */ + 0, /* 66 42 Keyboard F9 120 */ + 0, /* 67 43 Keyboard F10 121 */ + 0, /* 68 44 Keyboard F11 122 */ + 0, /* 69 45 Keyboard F12 123 */ + 0, /* 70 46 Keyboard PrintScreen 124 */ + 0, /* 71 47 Keyboard Scroll Lock 125 */ + 0, /* 72 48 Keyboard Pause 126 */ + 0, /* 73 49 Keyboard Insert 75 */ + 0, /* 74 4A Keyboard Home 80 */ + 0, /* 75 4B Keyboard PageUp 85 */ + 0, /* 76 4C Keyboard Delete Forward 76 */ + 0, /* 77 4D Keyboard End 81 */ + 0, /* 78 4E Keyboard PageDown 86 */ + 0, /* 79 4F Keyboard RightArrow 89 */ + 0, /* 80 50 Keyboard LeftArrow 79 */ + 0, /* 81 51 Keyboard DownArrow 84 */ + 0, /* 82 52 Keyboard UpArrow 83 */ + 0, /* 83 53 Keypad Num Lock and Clear 90 */ + 0, /* 84 54 Keypad / 95 */ + 0, /* 85 55 Keypad * 100 */ + 0, /* 86 56 Keypad - 105 */ + 0, /* 87 57 Keypad + 106 */ + 0, /* 88 58 Keypad ENTER 108 */ + 0, /* 89 59 Keypad 1 and End 93 */ + 0, /* 90 5A Keypad 2 and Down Arrow 98 */ + 0, /* 91 5B Keypad 3 and PageDn 103 */ + 0, /* 92 5C Keypad 4 and Left Arrow 92 */ + 0, /* 93 5D Keypad 5 97 */ + 0, /* 94 5E Keypad 6 and Right Arrow 102 */ + 0, /* 95 5F Keypad 7 and Home 91 */ + 0, /* 96 60 Keypad 8 and Up Arrow 96 */ + 0, /* 97 61 Keypad 9 and PageUp 101 */ + 0, /* 98 62 Keypad 0 and Insert 99 */ + 0, /* 99 63 Keypad . and Delete 104 */ + '|' /* 100 64 Keyboard Non-US \ and | 45 */ +}; + + +/***********************************/ +/* Keycodes for 1 byte translation */ +/* - CONTROL-KEY pressed - */ +/***********************************/ +const uint8_t keycodes_ctrl[] = { + 0, /* 0 00 Reserved (no event indicated) */ + 0, /* 1 01 Keyboard ErrorRollOver */ + 0, /* 2 02 Keyboard POSTFail */ + 0, /* 3 03 Keyboard ErrorUndefined */ + 1, /* 4 04 Keyboard a and A 31 */ + 2, /* 5 05 Keyboard b and B 50 */ + 3, /* 6 06 Keyboard c and C 48 */ + 4, /* 7 07 Keyboard d and D 33 */ + 5, /* 8 08 Keyboard e and E 19 */ + 6, /* 9 09 Keyboard f and F 34 */ + 7, /* 10 0A Keyboard g and G 35 */ + 8, /* 11 0B Keyboard h and H 36 */ + 9, /* 12 0C Keyboard i and I 24 */ + 10, /* 13 0D Keyboard j and J 37 */ + 11, /* 14 0E Keyboard k and K 38 */ + 12, /* 15 0F Keyboard l and L 39 */ + 13, /* 16 10 Keyboard m and M 52 */ + 14, /* 17 11 Keyboard n and N 51 */ + 15, /* 18 12 Keyboard o and O 25 */ + 16, /* 19 13 Keyboard p and P 26 */ + 17, /* 20 14 Keyboard q and Q 17 */ + 18, /* 21 15 Keyboard r and R 20 */ + 19, /* 22 16 Keyboard s and S 32 */ + 20, /* 23 17 Keyboard t and T 21 */ + 21, /* 24 18 Keyboard u and U 23 */ + 22, /* 25 19 Keyboard v and V 49 */ + 23, /* 26 1A Keyboard w and W 18 */ + 24, /* 27 1B Keyboard x and X 47 */ + 25, /* 28 1C Keyboard y and Y 22 */ + 26, /* 29 1D Keyboard z and Z 46 */ + 0, /* 30 1E Keyboard 1 and ! 2 */ + 0, /* 31 1F Keyboard 2 and @ 3 */ + 0, /* 32 20 Keyboard 3 and # 4 */ + 0, /* 33 21 Keyboard 4 and $ 5 */ + 0, /* 34 22 Keyboard 5 and % 6 */ + 0, /* 35 23 Keyboard 6 and ^ 7 */ + 0, /* 36 24 Keyboard 7 and & 8 */ + 0, /* 37 25 Keyboard 8 and * 9 */ + 0, /* 38 26 Keyboard 9 and ( 10 */ + 0, /* 39 27 Keyboard 0 and ) 11 */ + 0, /* 40 28 Keyboard Return (ENTER) 43 */ + 0, /* 41 29 Keyboard ESCAPE 110 */ + 0, /* 42 2A Keyboard DELETE (BS) 15 */ + 0, /* 43 2B Keyboard Tab 16 */ + 0, /* 44 2C Keyboard Spacebar 61 */ + 0, /* 45 2D Keyboard - and (underscore) 12 */ + 0, /* 46 2E Keyboard = and + 13 */ + 0, /* 47 2F Keyboard [ and { 27 */ + 0, /* 48 30 Keyboard ] and } 28 */ + 0, /* 49 31 Keyboard \ and | 29 */ + 0, /* 50 32 Keyboard Non-US # and ~ 42 */ + 0, /* 51 33 Keyboard ; and : 40 */ + 0, /* 52 34 Keyboard ' and " 41 */ + 0, /* 53 35 Keyboard Grave Accent and Tilde 1 */ + 0, /* 54 36 Keyboard , and < 53 */ + 0, /* 55 37 Keyboard . and > 54 */ + 0, /* 56 38 Keyboard / and ? 55 */ + 0, /* 57 39 Keyboard Caps Lock 30 */ + 0, /* 58 3A Keyboard F1 112 */ + 0, /* 59 3B Keyboard F2 113 */ + 0, /* 60 3C Keyboard F3 114 */ + 0, /* 61 3D Keyboard F4 115 */ + 0, /* 62 3E Keyboard F5 116 */ + 0, /* 63 3F Keyboard F6 117 */ + 0, /* 64 40 Keyboard F7 118 */ + 0, /* 65 41 Keyboard F8 119 */ + 0, /* 66 42 Keyboard F9 120 */ + 0, /* 67 43 Keyboard F10 121 */ + 0, /* 68 44 Keyboard F11 122 */ + 0, /* 69 45 Keyboard F12 123 */ + 0, /* 70 46 Keyboard PrintScreen 124 */ + 0, /* 71 47 Keyboard Scroll Lock 125 */ + 0, /* 72 48 Keyboard Pause 126 */ + 0, /* 73 49 Keyboard Insert 75 */ + 0, /* 74 4A Keyboard Home 80 */ + 0, /* 75 4B Keyboard PageUp 85 */ + 0, /* 76 4C Keyboard Delete Forward 76 */ + 0, /* 77 4D Keyboard End 81 */ + 0, /* 78 4E Keyboard PageDown 86 */ + 0, /* 79 4F Keyboard RightArrow 89 */ + 0, /* 80 50 Keyboard LeftArrow 79 */ + 0, /* 81 51 Keyboard DownArrow 84 */ + 0, /* 82 52 Keyboard UpArrow 83 */ + 0, /* 83 53 Keypad Num Lock and Clear 90 */ + 0, /* 84 54 Keypad / 95 */ + 0, /* 85 55 Keypad * 100 */ + 0, /* 86 56 Keypad - 105 */ + 0, /* 87 57 Keypad + 106 */ + 0, /* 88 58 Keypad ENTER 108 */ + 0, /* 89 59 Keypad 1 and End 93 */ + 0, /* 90 5A Keypad 2 and Down Arrow 98 */ + 0, /* 91 5B Keypad 3 and PageDn 103 */ + 0, /* 92 5C Keypad 4 and Left Arrow 92 */ + 0, /* 93 5D Keypad 5 97 */ + 0, /* 94 5E Keypad 6 and Right Arrow 102 */ + 0, /* 95 5F Keypad 7 and Home 91 */ + 0, /* 96 60 Keypad 8 and Up Arrow 96 */ + 0, /* 97 61 Keypad 9 and PageUp 101 */ + 0, /* 98 62 Keypad 0 and Insert 99 */ + 0, /* 99 63 Keypad . and Delete 104 */ + 0 /* 100 64 Keyboard Non-US \ and | 45 */ +}; diff --git a/lib/libusb/usb-key.h b/lib/libusb/usb-key.h new file mode 100644 index 0000000..1871a99 --- /dev/null +++ b/lib/libusb/usb-key.h @@ -0,0 +1,42 @@ +#ifndef _USB_KEYB_H +#define _USB_KEYB_H + +/***************************************************************************** + * Copyright (c) 2013 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#define BIT_0 1 +#define BIT_1 (BIT_0 << 1) +#define BIT_2 (BIT_0 << 2) +#define BIT_3 (BIT_0 << 3) +#define BIT_4 (BIT_0 << 4) +#define BIT_5 (BIT_0 << 5) +#define BIT_6 (BIT_0 << 6) +#define BIT_7 (BIT_0 << 7) + +/* bits from modifier input */ +#define MODIFIER_CTRL (BIT_0 | BIT_4) +#define MODIFIER_SHIFT (BIT_1 | BIT_5) +#define MODIFIER_ALT (BIT_2 | BIT_6) +#define MODIFIER_GUI (BIT_3 | BIT_7) +#define MODIFIER_ALT_GR BIT_6 + +/* bits representing Keyboard-LEDs */ +#define LED_NUM_LOCK BIT_0 +#define LED_CAPS_LOCK BIT_1 +#define LED_SCROLL_LOCK BIT_2 + +extern const uint8_t keycodes_std_US[]; +extern const uint8_t keycodes_shift_US[]; +extern const uint8_t keycodes_alt_GR[]; +extern const uint8_t keycodes_ctrl[]; + +#endif diff --git a/lib/libusb/usb-ohci.c b/lib/libusb/usb-ohci.c index 22f23e0..2e24760 100644 --- a/lib/libusb/usb-ohci.c +++ b/lib/libusb/usb-ohci.c @@ -184,7 +184,6 @@ static void ohci_hub_check_ports(struct ohci_hcd *ohcd) static inline struct ohci_ed *ohci_pipe_get_ed(struct usb_pipe *pipe) { struct ohci_pipe *opipe; - opipe = container_of(pipe, struct ohci_pipe, pipe); dprintf("%s: ed is %p\n", __func__, &opipe->ed); return &opipe->ed; @@ -193,12 +192,19 @@ static inline struct ohci_ed *ohci_pipe_get_ed(struct usb_pipe *pipe) static inline long ohci_pipe_get_ed_phys(struct usb_pipe *pipe) { struct ohci_pipe *opipe; - opipe = container_of(pipe, struct ohci_pipe, pipe); dprintf("%s: ed_phys is %x\n", __func__, opipe->ed_phys); return opipe->ed_phys; } +static inline struct ohci_pipe *ohci_pipe_get_opipe(struct usb_pipe *pipe) +{ + struct ohci_pipe *opipe; + opipe = container_of(pipe, struct ohci_pipe, pipe); + dprintf("%s: opipe is %p\n", __func__, opipe); + return opipe; +} + static int ohci_alloc_pipe_pool(struct ohci_hcd *ohcd) { struct ohci_pipe *opipe, *curr, *prev; @@ -418,6 +424,141 @@ static int ohci_send_ctrl(struct usb_pipe *pipe, struct usb_dev_req *req, void * return ret; } +/* Populate the hcca intr region with periodic intr */ +static int ohci_get_pipe_intr(struct usb_pipe *pipe, struct ohci_hcd *ohcd, + char *buf, size_t buflen) +{ + struct ohci_hcca *hcca; + struct ohci_pipe *opipe; + struct ohci_ed *ed; + struct usb_dev *dev; + struct ohci_td *tds, *td; + int32_t count, i; + uint8_t *ptr; + uint16_t mps; + long ed_phys, td_phys, td_next, buf_phys; + + if (!pipe || !ohcd) + return false; + + hcca = ohcd->hcca; + dev = pipe->dev; + if (dev->class != DEV_HID_KEYB) + return false; + + opipe = ohci_pipe_get_opipe(pipe); + ed = &(opipe->ed); + ed_phys = opipe->ed_phys; + mps = pipe->mps; + write_reg(&ed->attr, EDA_DIR_IN | EDA_FADDR(dev->addr) | dev->speed | + EDA_MPS(pipe->mps) | EDA_SKIP | EDA_EP(pipe->epno)); + dprintf("%s: pipe %p ed %p dev %p opipe %p\n", __func__, pipe, ed, dev, opipe); + count = (buflen/mps) + 1; + tds = td = SLOF_dma_alloc(sizeof(*td) * count); + if (!tds) { + printf("%s: alloc failed\n", __func__); + return false; + } + td_phys = SLOF_dma_map_in(td, sizeof(*td) * count, false); + + memset(tds, 0, sizeof(*tds) * count); + memset(buf, 0, buflen); + buf_phys = SLOF_dma_map_in(buf, buflen, false); + opipe->td = td; + opipe->td_phys = td_phys; + opipe->count = count; + opipe->buf = buf; + opipe->buflen = buflen; + opipe->buf_phys = buf_phys; + + ptr = (uint8_t *)buf_phys; + for (i = 0; i < count - 1; i++, ptr += mps) { + td = &tds[i]; + td_next = ohci_get_td_phys(td + 1, &tds[0], td_phys); + write_reg(&td->cbp, PTR_U32(ptr)); + write_reg(&td->attr, TDA_DP_IN | TDA_ROUNDING | TDA_CC); + write_reg(&td->next_td, td_next); + write_reg(&td->be, PTR_U32(ptr) + mps - 1); + dprintf("td %x td++ %x ptr %x be %x\n", + td, read_reg(&td->next_td), ptr, (PTR_U32(ptr) + mps - 1)); + } + td->next_td = 0; + td_next = ohci_get_td_phys(td, &tds[0], td_phys); + write_reg(&ed->headp, td_phys); + write_reg(&ed->tailp, td_next); + + dprintf("%s: head %08X tail %08X, count %d, mps %d\n", __func__, + read_reg(&ed->headp), + read_reg(&ed->tailp), + count, mps); + ed->next_ed = 0; + + + switch (dev->class) { + case DEV_HID_KEYB: + dprintf("%s: Keyboard class %d\n", __func__, dev->class); + write_reg(&hcca->intr_table[0], ed_phys); + write_reg(&hcca->intr_table[8], ed_phys); + write_reg(&hcca->intr_table[16], ed_phys); + write_reg(&hcca->intr_table[24], ed_phys); + write_reg(&ed->attr, read_reg(&ed->attr) & ~EDA_SKIP); + break; + case DEV_HUB: + default: + dprintf("%s: unhandled class %d\n", __func__, dev->class); + } + return true; +} + +static int ohci_put_pipe_intr(struct usb_pipe *pipe, struct ohci_hcd *ohcd) +{ + struct ohci_hcca *hcca; + struct ohci_pipe *opipe; + struct ohci_ed *ed; + struct usb_dev *dev; + struct ohci_td *td; + long ed_phys; + + if (!pipe || !ohcd) + return false; + + hcca = ohcd->hcca; + dev = pipe->dev; + + if (dev->class != DEV_HID_KEYB) + return false; + + opipe = ohci_pipe_get_opipe(pipe); + ed = &(opipe->ed); + ed_phys = opipe->ed_phys; + dprintf("%s: td %p td_phys %08lx buf %p buf_phys %08lx\n", __func__, + opipe->td, opipe->td_phys, opipe->buf, opipe->buf_phys); + + write_reg(&ed->attr, read_reg(&ed->attr) | EDA_SKIP); + barrier(); + ed->headp = 0; + ed->tailp = 0; + ed->next_ed = 0; + SLOF_dma_map_out(opipe->buf_phys, opipe->buf, opipe->buflen); + SLOF_dma_map_out(opipe->td_phys, opipe->td, sizeof(*td) * opipe->count); + SLOF_dma_free(opipe->td, sizeof(*td) * opipe->count); + + switch (dev->class) { + case DEV_HID_KEYB: + dprintf("%s: Keyboard class %d\n", __func__, dev->class); + write_reg(&hcca->intr_table[0], ed_phys); + write_reg(&hcca->intr_table[8], ed_phys); + write_reg(&hcca->intr_table[16], ed_phys); + write_reg(&hcca->intr_table[24], ed_phys); + break; + + case DEV_HUB: + default: + dprintf("%s: unhandled class %d\n", __func__, dev->class); + } + return true; +} + static struct usb_pipe *ohci_get_pipe(struct usb_dev *dev, struct usb_ep_descr *ep, char *buf, size_t buflen) { @@ -446,7 +587,13 @@ static struct usb_pipe *ohci_get_pipe(struct usb_dev *dev, struct usb_ep_descr * new->type = ep->bmAttributes & USB_EP_TYPE_MASK; new->speed = dev->speed; new->mps = read_reg16(&ep->wMaxPacketSize); + new->epno = ep->bEndpointAddress & 0xF; new->dir = ep->bEndpointAddress & 0x80; + if (new->type == USB_EP_TYPE_INTR) + if (!ohci_get_pipe_intr(new, ohcd, buf, buflen)) + dprintf("usb-ohci: %s alloc_intr failed %p\n", + __func__, new); + dprintf("usb-ohci: %s exit %p\n", __func__, new); return new; } @@ -464,6 +611,11 @@ static void ohci_put_pipe(struct usb_pipe *pipe) else ohcd->freelist = pipe; + if (pipe->type == USB_EP_TYPE_INTR) + if (!ohci_put_pipe_intr(pipe, ohcd)) + dprintf("usb-ohci: %s alloc_intr failed %p\n", + __func__, new); + ohcd->end = pipe; pipe->next = NULL; pipe->dev = NULL; @@ -471,6 +623,80 @@ static void ohci_put_pipe(struct usb_pipe *pipe) dprintf("usb-ohci: %s exit\n", __func__); } +static uint16_t ohci_get_last_frame(struct usb_dev *dev) +{ + struct ohci_hcd *ohcd; + struct ohci_regs *regs; + + ohcd = dev->hcidev->priv; + regs = ohcd->regs; + return read_reg(®s->fm_num); +} + +static int ohci_poll_intr(struct usb_pipe *pipe, uint8_t *data) +{ + struct ohci_pipe *opipe; + struct ohci_ed *ed; + struct ohci_td *head, *tail, *curr, *next; + struct ohci_td *head_phys, *tail_phys, *curr_phys; + uint8_t *ptr; + unsigned int i, pos; + static uint16_t last_frame; + long ptr_phys = 0; + long td_next; + + if (!pipe || last_frame == ohci_get_last_frame(pipe->dev)) + return 0; + + dprintf("%s: enter\n", __func__); + + last_frame = ohci_get_last_frame(pipe->dev); + opipe = ohci_pipe_get_opipe(pipe); + ed = &opipe->ed; + + head_phys = (struct ohci_td *)(long)(read_reg32(&ed->headp) & EDA_HEADP_MASK); + tail_phys = (struct ohci_td *)(long) read_reg32(&ed->tailp); + curr_phys = (struct ohci_td *) opipe->td_phys; + pos = (tail_phys - curr_phys + 1) % (opipe->count - 1); + dprintf("pos %d %ld -- %d\n", pos, (tail_phys - curr_phys + 1), + opipe->count); + curr = opipe->td + pos; + head = opipe->td + (head_phys - (struct ohci_td *) opipe->td_phys); + tail = opipe->td + (tail_phys - (struct ohci_td *) opipe->td_phys); + + /* dprintf("%08X %08X %08X %08X\n", + opipe->td_phys, head_phys, tail_phys, curr_phys); + dprintf("%08X %08X %08X %08X\n", opipe->td, head, tail, curr); */ + + if (curr != head) { + ptr = (uint8_t *) ((long)opipe->buf + pipe->mps * pos); + ptr_phys = opipe->buf_phys + pipe->mps * pos; + if (read_reg((uint32_t *)ptr) != 0) { + for (i = 0; i < 8; i++) + data[i] = *(ptr + i); + } + + next = curr + 1; + if (next == (opipe->td + opipe->count - 1)) + next = opipe->td; + + write_reg(&curr->attr, TDA_DP_IN | TDA_ROUNDING | TDA_CC); + write_reg(&curr->next_td, 0); + write_reg(&curr->cbp, PTR_U32(ptr_phys)); + write_reg(&curr->be, PTR_U32(ptr_phys + pipe->mps - 1)); + td_next = ohci_get_td_phys(curr, opipe->td, opipe->td_phys); + dprintf("Connecting %p to %p(phys %08lx) ptr %p, ptr_phys %08lx\n", + tail, curr, td_next, ptr, ptr_phys); + write_reg(&tail->next_td, td_next); + barrier(); + write_reg(&ed->tailp, td_next); + } else + return 0; + + dprintf("%s: exit\n", __func__); + return 1; +} + struct usb_hcd_ops ohci_ops = { .name = "ohci-hcd", .init = ohci_init, @@ -479,6 +705,7 @@ struct usb_hcd_ops ohci_ops = { .get_pipe = ohci_get_pipe, .put_pipe = ohci_put_pipe, .send_ctrl = ohci_send_ctrl, + .poll_intr = ohci_poll_intr, .usb_type = USB_OHCI, .next = NULL, }; diff --git a/lib/libusb/usb-ohci.h b/lib/libusb/usb-ohci.h index 75d8c8f..f153bb2 100644 --- a/lib/libusb/usb-ohci.h +++ b/lib/libusb/usb-ohci.h @@ -99,8 +99,14 @@ struct ohci_hcca { struct ohci_pipe { struct ohci_ed ed; /* has to be aligned at 16 byte address*/ struct usb_pipe pipe; + struct ohci_td *td; + void *buf; long ed_phys; - uint8_t pad[8]; + long td_phys; + long buf_phys; + uint32_t buflen; + uint32_t count; + uint8_t pad[0]; }__attribute__((packed)); #define OHCI_PIPE_POOL_SIZE 4096 diff --git a/lib/libusb/usb.code b/lib/libusb/usb.code index 44339af..55a1908 100644 --- a/lib/libusb/usb.code +++ b/lib/libusb/usb.code @@ -43,3 +43,45 @@ PRIM(USB_X2d_HCD_X2d_INIT) void *hcidev = TOS.a; POP; usb_hcd_init(hcidev); MIRP + +/************************************************/ +/* Initialize hid */ +/* SLOF: USB-HID-INIT ( dev -- true | false )*/ +/* LIBNEWUSB: usb_hid_init(hcidev) */ +/************************************************/ +PRIM(USB_X2d_HID_X2d_INIT) + void *dev = TOS.a; + TOS.n = usb_hid_init(dev); +MIRP + +/************************************************/ +/* Exit hid */ +/* SLOF: USB-HID-EXIT ( dev -- true | false )*/ +/* LIBNEWUSB: usb_hid_exit(hcidev) */ +/************************************************/ +PRIM(USB_X2d_HID_X2d_EXIT) + void *dev = TOS.a; + TOS.n = usb_hid_exit(dev); +MIRP + +/************************************************/ +/* Read usb keyboard for key */ +/* SLOF: USB-READ-KEYB ( dev -- */ +/* ( key | false )) */ +/* LIBNEWUSB: usb_read_keyb */ +/************************************************/ +PRIM(USB_X2d_READ_X2d_KEYB) + void *dev = TOS.a; + TOS.n = usb_read_keyb(dev); +MIRP + +/************************************************/ +/* Is USB KEY available */ +/* SLOF: USB-KEY-AVAILABLE ( dev -- ( true | */ +/* false ))*/ +/* LIBNEWUSB: usb_key_available */ +/************************************************/ +PRIM(USB_X2d_KEY_X2d_AVAILABLE) + void *dev = TOS.a; + TOS.n = usb_key_available(dev); +MIRP diff --git a/lib/libusb/usb.h b/lib/libusb/usb.h index c5ecf87..16787a7 100644 --- a/lib/libusb/usb.h +++ b/lib/libusb/usb.h @@ -1,4 +1,3 @@ - /****************************************************************************** * Copyright (c) 2006, 2012, 2013 IBM Corporation * All rights reserved. @@ -29,6 +28,21 @@ extern void usb_ehci_register(void); /* SLOF: USB-HCD-INIT */ /*******************************************/ extern void usb_hcd_init(void *hcidev); +/*******************************************/ +/* SLOF: USB-HID-INIT */ +/*******************************************/ +extern int usb_hid_init(void *dev); +/*******************************************/ +/* SLOF: USB-HID-EXIT */ +/*******************************************/ +extern int usb_hid_exit(void *dev); +/*******************************************/ +/* SLOF: USB-READ-KEYB */ +/*******************************************/ +extern unsigned char usb_read_keyb(void *dev); +/*******************************************/ +/* SLOF: USB-KEY-AVAILABLE */ +/*******************************************/ +extern unsigned char usb_key_available(void *dev); #endif - diff --git a/lib/libusb/usb.in b/lib/libusb/usb.in index 0efc9c2..34e006e 100644 --- a/lib/libusb/usb.in +++ b/lib/libusb/usb.in @@ -16,3 +16,7 @@ cod(USB-OHCI-REGISTER) cod(USB-EHCI-REGISTER) cod(USB-HCD-INIT) +cod(USB-HID-INIT) +cod(USB-HID-EXIT) +cod(USB-READ-KEYB) +cod(USB-KEY-AVAILABLE) diff --git a/slof/fs/usb/dev-keyb.fs b/slof/fs/usb/dev-keyb.fs index b445733..f0415fc 100644 --- a/slof/fs/usb/dev-keyb.fs +++ b/slof/fs/usb/dev-keyb.fs @@ -1,6 +1,7 @@ new-device VALUE sudev +false VALUE usb-keyb-debug? s" slofdev.fs" included sudev slof-dev>port l@ dup set-unit encode-phys " reg" property @@ -11,18 +12,45 @@ s" keyboard" device-type s" EN" encode-string s" language" property s" keyboard" get-node node>path set-alias +s" dev-parent-calls.fs" included + +0 VALUE open-count + : open ( -- true | false ) - TRUE + usb-keyb-debug? IF ." USB-KEYB: Opening (count is " open-count . ." )" cr THEN + open-count 0= IF + udev USB-HID-INIT 0= IF + ." USB keyboard setup failed " pwd cr false EXIT + ELSE + \ drop all the keys + begin udev USB-READ-KEYB 0 = until + THEN + THEN + open-count 1 + to open-count + true +; + +: close + usb-keyb-debug? IF ." USB-KEYB: Closing (count is " open-count . ." )" cr THEN + open-count 0> IF + open-count 1 - dup to open-count + 0= IF + my-phandle set-node + udev USB-HID-EXIT drop + 0 set-node + THEN + THEN ; \ method to check if a key is present in output buffer \ used by 'term-io.fs' : key-available? ( -- true|false ) - false + udev USB-KEY-AVAILABLE IF TRUE ELSE FALSE THEN ; : read ( addr len -- actual ) - 2drop 0 + 0= IF drop 0 EXIT THEN + udev USB-READ-KEYB ?dup IF swap c! 1 ELSE 0 swap c! 0 then ; ." USB Keyboard " cr diff --git a/slof/fs/usb/dev-parent-calls.fs b/slof/fs/usb/dev-parent-calls.fs new file mode 100644 index 0000000..b77f9bc --- /dev/null +++ b/slof/fs/usb/dev-parent-calls.fs @@ -0,0 +1,17 @@ +\ ****************************************************************************/ +\ * Copyright (c) 2011 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ * IBM Corporation - initial implementation +\ ****************************************************************************/ + +get-node CONSTANT my-phandle +: dma-alloc s" dma-alloc" my-phandle parent $call-static ; +: dma-map-in s" dma-map-in" my-phandle parent $call-static ; +: dma-map-out s" dma-map-out" my-phandle parent $call-static ; +: dma-free s" dma-free" my-phandle parent $call-static ;