- reduced memory requirements a lot (from >100kb/controller to
560bytes/controller) - no need for the client of libpayload to implement usbdisk_{create,remove}, just because USB was compiled in. - usb hub support compiles, and works for some trivial cases (no device detach, trivial power management) - usb keyboard support works in qemu, though there are reports that it doesn't work on real hardware yet. - usb keyboard is integrated in both libc-getchar() and curses, if CONFIG_USB_HID is enabled Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de> Acked-by: Jordan Crouse <jordan.crouse@amd.com> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3662 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
parent
b1b071fe17
commit
4727c07446
|
@ -38,6 +38,7 @@
|
|||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <usb/usb.h>
|
||||
#include "local.h"
|
||||
|
||||
static int _halfdelay = 0;
|
||||
|
@ -145,6 +146,14 @@ static int curses_getchar(int delay)
|
|||
unsigned short c;
|
||||
|
||||
do {
|
||||
#ifdef CONFIG_USB_HID
|
||||
usb_poll();
|
||||
if ((curses_flags & F_ENABLE_CONSOLE) &&
|
||||
usbhid_havechar()) {
|
||||
c = usbhid_getchar();
|
||||
if (c != 0) return c;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_PC_KEYBOARD
|
||||
if ((curses_flags & F_ENABLE_CONSOLE) &&
|
||||
keyboard_havechar()) {
|
||||
|
|
|
@ -299,7 +299,7 @@ static void keyboard_set_mode(unsigned char mode)
|
|||
/**
|
||||
* Set keyboard layout
|
||||
* @param country string describing the keyboard layout language.
|
||||
* Valid values are "en", "de".
|
||||
* Valid values are "us", "de".
|
||||
*/
|
||||
|
||||
int keyboard_set_layout(char *country)
|
||||
|
|
|
@ -40,6 +40,9 @@ static int uhci_packet (usbdev_t *dev, int endp, int pid, int toggle,
|
|||
static int uhci_bulk (endpoint_t *ep, int size, u8 *data, int finalize);
|
||||
static int uhci_control (usbdev_t *dev, pid_t dir, int drlen, void *devreq,
|
||||
int dalen, u8 *data);
|
||||
static void* uhci_create_intr_queue (endpoint_t *ep, int reqsize, int reqcount, int reqtiming);
|
||||
static void uhci_destroy_intr_queue (endpoint_t *ep, void *queue);
|
||||
static u8* uhci_poll_intr_queue (void *queue);
|
||||
|
||||
#if 0
|
||||
/* dump uhci */
|
||||
|
@ -119,7 +122,14 @@ uhci_init (pcidev_t addr)
|
|||
controller->packet = uhci_packet;
|
||||
controller->bulk = uhci_bulk;
|
||||
controller->control = uhci_control;
|
||||
UHCI_INST (controller)->roothub = &(controller->devices[0]);
|
||||
controller->create_intr_queue = uhci_create_intr_queue;
|
||||
controller->destroy_intr_queue = uhci_destroy_intr_queue;
|
||||
controller->poll_intr_queue = uhci_poll_intr_queue;
|
||||
for (i = 1; i < 128; i++) {
|
||||
controller->devices[i] = 0;
|
||||
}
|
||||
init_device_entry (controller, 0);
|
||||
UHCI_INST (controller)->roothub = controller->devices[0];
|
||||
|
||||
controller->bus_address = addr;
|
||||
controller->reg_base = pci_read_config32 (controller->bus_address, 0x20) & ~1; /* ~1 clears the register type indicator that is set to 1 for IO space */
|
||||
|
@ -134,10 +144,27 @@ uhci_init (pcidev_t addr)
|
|||
memset (UHCI_INST (controller)->framelistptr, 0,
|
||||
1024 * sizeof (flistp_t));
|
||||
|
||||
/* According to the *BSD UHCI code, this one is needed on some
|
||||
PIIX chips, because otherwise they misbehave. It must be
|
||||
added to the last chain.
|
||||
|
||||
FIXME: this leaks, if the driver should ever be reinited
|
||||
for some reason. Not a problem now.
|
||||
*/
|
||||
td_t *antiberserk = memalign(16, sizeof(td_t));
|
||||
memset(antiberserk, 0, sizeof(td_t));
|
||||
|
||||
UHCI_INST (controller)->qh_prei = memalign (16, sizeof (qh_t));
|
||||
UHCI_INST (controller)->qh_intr = memalign (16, sizeof (qh_t));
|
||||
UHCI_INST (controller)->qh_data = memalign (16, sizeof (qh_t));
|
||||
UHCI_INST (controller)->qh_last = memalign (16, sizeof (qh_t));
|
||||
|
||||
UHCI_INST (controller)->qh_prei->headlinkptr.ptr =
|
||||
virt_to_phys (UHCI_INST (controller)->qh_intr);
|
||||
UHCI_INST (controller)->qh_prei->headlinkptr.queue_head = 1;
|
||||
UHCI_INST (controller)->qh_prei->elementlinkptr.ptr = 0;
|
||||
UHCI_INST (controller)->qh_prei->elementlinkptr.terminate = 1;
|
||||
|
||||
UHCI_INST (controller)->qh_intr->headlinkptr.ptr =
|
||||
virt_to_phys (UHCI_INST (controller)->qh_data);
|
||||
UHCI_INST (controller)->qh_intr->headlinkptr.queue_head = 1;
|
||||
|
@ -150,23 +177,20 @@ uhci_init (pcidev_t addr)
|
|||
UHCI_INST (controller)->qh_data->elementlinkptr.ptr = 0;
|
||||
UHCI_INST (controller)->qh_data->elementlinkptr.terminate = 1;
|
||||
|
||||
UHCI_INST (controller)->qh_last->headlinkptr.ptr = 0;
|
||||
UHCI_INST (controller)->qh_last->headlinkptr.ptr = virt_to_phys (UHCI_INST (controller)->qh_data);
|
||||
UHCI_INST (controller)->qh_last->headlinkptr.terminate = 1;
|
||||
UHCI_INST (controller)->qh_last->elementlinkptr.ptr = 0;
|
||||
UHCI_INST (controller)->qh_last->elementlinkptr.ptr = virt_to_phys (antiberserk);
|
||||
UHCI_INST (controller)->qh_last->elementlinkptr.terminate = 1;
|
||||
|
||||
for (i = 0; i < 1024; i++) {
|
||||
UHCI_INST (controller)->framelistptr[i].ptr =
|
||||
virt_to_phys (UHCI_INST (controller)->qh_intr);
|
||||
virt_to_phys (UHCI_INST (controller)->qh_prei);
|
||||
UHCI_INST (controller)->framelistptr[i].terminate = 0;
|
||||
UHCI_INST (controller)->framelistptr[i].queue_head = 1;
|
||||
}
|
||||
for (i = 1; i < 128; i++) {
|
||||
init_device_entry (controller, i);
|
||||
}
|
||||
controller->devices[0].controller = controller;
|
||||
controller->devices[0].init = uhci_rh_init;
|
||||
controller->devices[0].init (&controller->devices[0]);
|
||||
controller->devices[0]->controller = controller;
|
||||
controller->devices[0]->init = uhci_rh_init;
|
||||
controller->devices[0]->init (controller->devices[0]);
|
||||
uhci_reset (controller);
|
||||
return controller;
|
||||
}
|
||||
|
@ -181,6 +205,7 @@ uhci_shutdown (hci_t *controller)
|
|||
roothub);
|
||||
uhci_reg_mask16 (controller, USBCMD, 0, 0); // stop work
|
||||
free (UHCI_INST (controller)->framelistptr);
|
||||
free (UHCI_INST (controller)->qh_prei);
|
||||
free (UHCI_INST (controller)->qh_intr);
|
||||
free (UHCI_INST (controller)->qh_data);
|
||||
free (UHCI_INST (controller)->qh_last);
|
||||
|
@ -205,12 +230,12 @@ uhci_stop (hci_t *controller)
|
|||
static td_t *
|
||||
wait_for_completed_qh (hci_t *controller, qh_t *qh)
|
||||
{
|
||||
int timeout = 1000; /* max 30 ms. */
|
||||
int timeout = 1000000; /* max 30 ms. */
|
||||
void *current = GET_TD (qh->elementlinkptr.ptr);
|
||||
while ((qh->elementlinkptr.terminate == 0) && (timeout-- > 0)) {
|
||||
if (current != GET_TD (qh->elementlinkptr.ptr)) {
|
||||
current = GET_TD (qh->elementlinkptr.ptr);
|
||||
timeout = 1000;
|
||||
timeout = 1000000;
|
||||
}
|
||||
uhci_reg_mask16 (controller, USBSTS, ~0, 0); // clear resettable registers
|
||||
udelay (30);
|
||||
|
@ -449,6 +474,130 @@ uhci_bulk (endpoint_t *ep, int size, u8 *data, int finalize)
|
|||
return 0;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
qh_t *qh;
|
||||
td_t *tds;
|
||||
td_t *last_td;
|
||||
u8 *data;
|
||||
int lastread;
|
||||
int total;
|
||||
int reqsize;
|
||||
} intr_q;
|
||||
|
||||
/* create and hook-up an intr queue into device schedule */
|
||||
static void*
|
||||
uhci_create_intr_queue (endpoint_t *ep, int reqsize, int reqcount, int reqtiming)
|
||||
{
|
||||
u8 *data = malloc(reqsize*reqcount);
|
||||
td_t *tds = memalign(16, sizeof(td_t) * reqcount);
|
||||
qh_t *qh = memalign(16, sizeof(qh_t));
|
||||
|
||||
qh->elementlinkptr.ptr = virt_to_phys(tds);
|
||||
qh->elementlinkptr.terminate = 0;
|
||||
|
||||
intr_q *q = malloc(sizeof(intr_q));
|
||||
q->qh = qh;
|
||||
q->tds = tds;
|
||||
q->data = data;
|
||||
q->lastread = 0;
|
||||
q->total = reqcount;
|
||||
q->reqsize = reqsize;
|
||||
q->last_td = &tds[reqcount - 1];
|
||||
|
||||
memset (tds, 0, sizeof (td_t) * reqcount);
|
||||
int i;
|
||||
for (i = 0; i < reqcount; i++) {
|
||||
tds[i].ptr = virt_to_phys (&tds[i + 1]);
|
||||
tds[i].terminate = 0;
|
||||
tds[i].queue_head = 0;
|
||||
tds[i].depth_first = 0;
|
||||
|
||||
tds[i].pid = ep->direction;
|
||||
tds[i].dev_addr = ep->dev->address;
|
||||
tds[i].endp = ep->endpoint & 0xf;
|
||||
tds[i].maxlen = maxlen (reqsize);
|
||||
tds[i].counter = 0;
|
||||
tds[i].data_toggle = ep->toggle & 1;
|
||||
tds[i].lowspeed = ep->dev->lowspeed;
|
||||
tds[i].bufptr = virt_to_phys (data);
|
||||
tds[i].status_active = 1;
|
||||
ep->toggle ^= 1;
|
||||
data += reqsize;
|
||||
}
|
||||
tds[reqcount - 1].ptr = 0;
|
||||
tds[reqcount - 1].terminate = 1;
|
||||
tds[reqcount - 1].queue_head = 0;
|
||||
tds[reqcount - 1].depth_first = 0;
|
||||
for (i = reqtiming; i < 1024; i += reqtiming) {
|
||||
/* FIXME: wrap in another qh, one for each occurance of the qh in the framelist */
|
||||
qh->headlinkptr.ptr = UHCI_INST (ep->dev->controller)->framelistptr[i].ptr;
|
||||
qh->headlinkptr.terminate = 0;
|
||||
UHCI_INST (ep->dev->controller)->framelistptr[i].ptr = virt_to_phys(qh);
|
||||
UHCI_INST (ep->dev->controller)->framelistptr[i].terminate = 0;
|
||||
UHCI_INST (ep->dev->controller)->framelistptr[i].queue_head = 1;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
/* remove queue from device schedule, dropping all data that came in */
|
||||
static void
|
||||
uhci_destroy_intr_queue (endpoint_t *ep, void *q_)
|
||||
{
|
||||
intr_q *q = (intr_q*)q_;
|
||||
u32 val = virt_to_phys (q->qh);
|
||||
u32 end = virt_to_phys (UHCI_INST (ep->dev->controller)->qh_intr);
|
||||
int i;
|
||||
for (i=0; i<1024; i++) {
|
||||
u32 oldptr = 0;
|
||||
u32 ptr = UHCI_INST (ep->dev->controller)->framelistptr[i].ptr;
|
||||
while (ptr != end) {
|
||||
if (((qh_t*)phys_to_virt(ptr))->elementlinkptr.ptr == val) {
|
||||
((qh_t*)phys_to_virt(oldptr))->headlinkptr.ptr = ((qh_t*)phys_to_virt(ptr))->headlinkptr.ptr;
|
||||
free(phys_to_virt(ptr));
|
||||
break;
|
||||
}
|
||||
oldptr = ptr;
|
||||
ptr = ((qh_t*)phys_to_virt(ptr))->headlinkptr.ptr;
|
||||
}
|
||||
}
|
||||
free(q->data);
|
||||
free(q->tds);
|
||||
free(q->qh);
|
||||
free(q);
|
||||
}
|
||||
|
||||
/* read one intr-packet from queue, if available. extend the queue for new input.
|
||||
return NULL if nothing new available.
|
||||
Recommended use: while (data=poll_intr_queue(q)) process(data);
|
||||
*/
|
||||
static u8*
|
||||
uhci_poll_intr_queue (void *q_)
|
||||
{
|
||||
intr_q *q = (intr_q*)q_;
|
||||
if (q->tds[q->lastread].status_active == 0) {
|
||||
/* FIXME: handle errors */
|
||||
int current = q->lastread;
|
||||
int previous;
|
||||
if (q->lastread == 0) {
|
||||
previous = q->total - 1;
|
||||
} else {
|
||||
previous = q->lastread - 1;
|
||||
}
|
||||
q->tds[previous].status = 0;
|
||||
q->tds[previous].ptr = 0;
|
||||
q->tds[previous].terminate = 1;
|
||||
if (q->last_td != &q->tds[previous]) {
|
||||
q->last_td->ptr = virt_to_phys(&q->tds[previous]);
|
||||
q->last_td->terminate = 0;
|
||||
q->last_td = &q->tds[previous];
|
||||
}
|
||||
q->tds[previous].status_active = 1;
|
||||
q->lastread = (q->lastread + 1) % q->total;
|
||||
return &q->data[current*q->reqsize];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
uhci_reg_write32 (hci_t *ctrl, usbreg reg, u32 value)
|
||||
{
|
||||
|
|
|
@ -111,7 +111,7 @@ typedef struct {
|
|||
|
||||
typedef struct uhci {
|
||||
flistp_t *framelistptr;
|
||||
qh_t *qh_intr, *qh_data, *qh_last;
|
||||
qh_t *qh_prei, *qh_intr, *qh_data, *qh_last;
|
||||
usbdev_t *roothub;
|
||||
} uhci_t;
|
||||
|
||||
|
|
|
@ -88,17 +88,13 @@ uhci_rh_scanport (usbdev_t *dev, int port)
|
|||
} else
|
||||
return;
|
||||
int devno = RH_INST (dev)->port[offset];
|
||||
if (devno != -1) {
|
||||
dev->controller->devices[devno].destroy (&dev->controller->
|
||||
devices[devno]);
|
||||
init_device_entry (dev->controller, devno);
|
||||
if ((dev->controller->devices[devno] != 0) && (devno != -1)) {
|
||||
usb_detach_device(dev->controller, devno);
|
||||
RH_INST (dev)->port[offset] = -1;
|
||||
}
|
||||
uhci_reg_mask16 (dev->controller, portsc, ~0, (1 << 3) | (1 << 2)); // clear port state change, enable port
|
||||
|
||||
if ((uhci_reg_read16 (dev->controller, portsc) & 1) != 0) {
|
||||
int newdev;
|
||||
usbdev_t *newdev_t;
|
||||
// device attached
|
||||
|
||||
uhci_rh_disable_port (dev, port);
|
||||
|
@ -106,18 +102,8 @@ uhci_rh_scanport (usbdev_t *dev, int port)
|
|||
|
||||
int lowspeed =
|
||||
(uhci_reg_read16 (dev->controller, portsc) >> 8) & 1;
|
||||
printf ("%sspeed device\n", (lowspeed == 1) ? "low" : "full");
|
||||
|
||||
newdev = set_address (dev->controller, lowspeed);
|
||||
if (newdev == -1)
|
||||
return;
|
||||
newdev_t = &dev->controller->devices[newdev];
|
||||
RH_INST (dev)->port[offset] = newdev;
|
||||
newdev_t->address = newdev;
|
||||
newdev_t->hub = dev->address;
|
||||
newdev_t->port = portsc;
|
||||
// determine responsible driver
|
||||
newdev_t->init (newdev_t);
|
||||
RH_INST (dev)->port[offset] = usb_attach_device(dev->controller, dev->address, portsc, lowspeed);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -75,8 +75,8 @@ usb_poll ()
|
|||
while (controller != 0) {
|
||||
int i;
|
||||
for (i = 0; i < 128; i++) {
|
||||
if (controller->devices[i].address != -1) {
|
||||
controller->devices[i].poll (&controller->
|
||||
if (controller->devices[i] != 0) {
|
||||
controller->devices[i]->poll (controller->
|
||||
devices[i]);
|
||||
}
|
||||
}
|
||||
|
@ -87,12 +87,15 @@ usb_poll ()
|
|||
void
|
||||
init_device_entry (hci_t *controller, int i)
|
||||
{
|
||||
controller->devices[i].controller = controller;
|
||||
controller->devices[i].address = -1;
|
||||
controller->devices[i].hub = -1;
|
||||
controller->devices[i].port = -1;
|
||||
controller->devices[i].init = usb_nop_init;
|
||||
controller->devices[i].init (&controller->devices[i]);
|
||||
if (controller->devices[i] != 0)
|
||||
printf("warning: device %d reassigned?\n", i);
|
||||
controller->devices[i] = malloc(sizeof(usbdev_t));
|
||||
controller->devices[i]->controller = controller;
|
||||
controller->devices[i]->address = -1;
|
||||
controller->devices[i]->hub = -1;
|
||||
controller->devices[i]->port = -1;
|
||||
controller->devices[i]->init = usb_nop_init;
|
||||
controller->devices[i]->init (controller->devices[i]);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -208,7 +211,7 @@ get_free_address (hci_t *controller)
|
|||
{
|
||||
int i;
|
||||
for (i = 1; i < 128; i++) {
|
||||
if (controller->devices[i].address != i)
|
||||
if (controller->devices[i] == 0)
|
||||
return i;
|
||||
}
|
||||
printf ("no free address found\n");
|
||||
|
@ -232,7 +235,8 @@ set_address (hci_t *controller, int lowspeed)
|
|||
dr.wIndex = 0;
|
||||
dr.wLength = 0;
|
||||
|
||||
usbdev_t *dev = &controller->devices[adr];
|
||||
init_device_entry(controller, adr);
|
||||
usbdev_t *dev = controller->devices[adr];
|
||||
// dummy values for registering the address
|
||||
dev->address = 0;
|
||||
dev->lowspeed = lowspeed;
|
||||
|
@ -325,7 +329,7 @@ set_address (hci_t *controller, int lowspeed)
|
|||
if (class == hub_device) {
|
||||
printf ("hub found\n");
|
||||
#ifdef CONFIG_USB_HUB
|
||||
controller->devices[adr].init = usb_hub_init;
|
||||
controller->devices[adr]->init = usb_hub_init;
|
||||
#else
|
||||
printf ("support not compiled in\n");
|
||||
#endif
|
||||
|
@ -333,7 +337,7 @@ set_address (hci_t *controller, int lowspeed)
|
|||
if (class == hid_device) {
|
||||
printf ("HID found\n");
|
||||
#ifdef CONFIG_USB_HID
|
||||
controller->devices[adr].init = usb_hid_init;
|
||||
controller->devices[adr]->init = usb_hid_init;
|
||||
#else
|
||||
printf ("support not compiled in\n");
|
||||
#endif
|
||||
|
@ -341,10 +345,35 @@ set_address (hci_t *controller, int lowspeed)
|
|||
if (class == msc_device) {
|
||||
printf ("MSC found\n");
|
||||
#ifdef CONFIG_USB_MSC
|
||||
controller->devices[adr].init = usb_msc_init;
|
||||
controller->devices[adr]->init = usb_msc_init;
|
||||
#else
|
||||
printf ("support not compiled in\n");
|
||||
#endif
|
||||
}
|
||||
return adr;
|
||||
}
|
||||
|
||||
void
|
||||
usb_detach_device(hci_t *controller, int devno)
|
||||
{
|
||||
controller->devices[devno]->destroy (controller->devices[devno]);
|
||||
free(controller->devices[devno]);
|
||||
controller->devices[devno] = 0;
|
||||
}
|
||||
|
||||
int
|
||||
usb_attach_device(hci_t *controller, int hubaddress, int port, int lowspeed)
|
||||
{
|
||||
printf ("%sspeed device\n", (lowspeed == 1) ? "low" : "full");
|
||||
int newdev = set_address (controller, lowspeed);
|
||||
if (newdev == -1)
|
||||
return -1;
|
||||
usbdev_t *newdev_t = controller->devices[newdev];
|
||||
|
||||
newdev_t->address = newdev;
|
||||
newdev_t->hub = hubaddress;
|
||||
newdev_t->port = port;
|
||||
// determine responsible driver - current done in set_address
|
||||
newdev_t->init (newdev_t);
|
||||
return newdev;
|
||||
}
|
||||
|
|
|
@ -28,9 +28,10 @@
|
|||
*/
|
||||
|
||||
#include <usb/usb.h>
|
||||
#include <curses.h>
|
||||
|
||||
enum { hid_subclass_none = 0, hid_subclass_boot = 1 };
|
||||
enum { hid_proto_boot = 0, hid_proto_report = 1 };
|
||||
typedef enum { hid_proto_boot = 0, hid_proto_report = 1 } hid_proto;
|
||||
enum { hid_boot_proto_none = 0, hid_boot_proto_keyboard =
|
||||
1, hid_boot_proto_mouse = 2
|
||||
};
|
||||
|
@ -42,23 +43,42 @@ enum { GET_REPORT = 0x1, GET_IDLE = 0x2, GET_PROTOCOL = 0x3, SET_REPORT =
|
|||
static void
|
||||
usb_hid_destroy (usbdev_t *dev)
|
||||
{
|
||||
free (dev->data);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
void* queue;
|
||||
} usbhid_inst_t;
|
||||
|
||||
#define HID_INST(dev) ((usbhid_inst_t*)(dev)->data)
|
||||
|
||||
/* buffer is global to all keyboard drivers */
|
||||
int count;
|
||||
short keybuffer[16];
|
||||
|
||||
int keypress;
|
||||
char keymap[256] = {
|
||||
-1, -1, -1, -1, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
|
||||
'l',
|
||||
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'1', '2',
|
||||
'3', '4', '5', '6', '7', '8', '9', '0', '\n', TERM_ESC,
|
||||
TERM_BACKSPACE, TERM_TAB, ' ', '-', '=', '[',
|
||||
']', '\\', -1, ';', '\'', '`', ',', '.', '/', -1, -1, -1, -1, -1, -1,
|
||||
-1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, TERM_HOME, TERM_PPAGE, -1,
|
||||
TERM_END, TERM_NPAGE, TERM_RIGHT,
|
||||
TERM_LEFT, TERM_DOWN, TERM_UP, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
short keymap[256] = {
|
||||
-1, -1, -1, -1, 'a', 'b', 'c', 'd',
|
||||
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
|
||||
|
||||
'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
|
||||
'u', 'v', 'w', 'x', 'y', 'z', '1', '2',
|
||||
|
||||
'3', '4', '5', '6', '7', '8', '9', '0',
|
||||
'\n', '\e', '\b', '\t', ' ', '-', '=', '[',
|
||||
|
||||
']', '\\', -1, ';', '\'', '`', ',', '.',
|
||||
'/', -1, KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6),
|
||||
|
||||
KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10), KEY_F(11), KEY_F(12), -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
/* 50 */
|
||||
-1, -1, -1, -1, -1, '*', '-', '+',
|
||||
-1, KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, -1, KEY_RIGHT, KEY_HOME,
|
||||
|
||||
KEY_UP, KEY_PPAGE, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
|
@ -74,64 +94,105 @@ char keymap[256] = {
|
|||
static void
|
||||
usb_hid_poll (usbdev_t *dev)
|
||||
{
|
||||
char buf[8];
|
||||
static int toggle = 0;
|
||||
// hardcode to endpoint 1, 8 bytes
|
||||
dev->controller->packet (dev, 1, IN, toggle, 8, buf);
|
||||
toggle ^= 1;
|
||||
// FIXME: manage buf[0]=special keys, too
|
||||
keypress = keymap[buf[2]];
|
||||
if ((keypress == -1) && (buf[2] != 0)) {
|
||||
printf ("%x %x %x %x %x %x %x %x\n", buf[0], buf[1], buf[2],
|
||||
buf[3], buf[4], buf[5], buf[6], buf[7]);
|
||||
u8* buf;
|
||||
while ((buf=dev->controller->poll_intr_queue (HID_INST(dev)->queue))) {
|
||||
// FIXME: manage buf[0]=special keys, too
|
||||
int i;
|
||||
keypress = 0;
|
||||
for (i=2; i<9; i++) {
|
||||
if (buf[i] != 0)
|
||||
keypress = keymap[buf[i]];
|
||||
else
|
||||
break;
|
||||
}
|
||||
if ((keypress == -1) && (buf[2] != 0)) {
|
||||
printf ("%x %x %x %x %x %x %x %x\n", buf[0], buf[1], buf[2],
|
||||
buf[3], buf[4], buf[5], buf[6], buf[7]);
|
||||
}
|
||||
if (keypress != -1) {
|
||||
/* ignore key presses if buffer full */
|
||||
if (count < 16)
|
||||
keybuffer[count++] = keypress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int (*oldhook) (void);
|
||||
|
||||
int
|
||||
hookfunc (void)
|
||||
static void
|
||||
usb_hid_set_idle (usbdev_t *dev, interface_descriptor_t *interface, u16 duration)
|
||||
{
|
||||
int key;
|
||||
if (oldhook != 0)
|
||||
key = oldhook ();
|
||||
if (key == -1)
|
||||
key = keypress;
|
||||
return key;
|
||||
dev_req_t dr;
|
||||
dr.data_dir = host_to_device;
|
||||
dr.req_type = class_type;
|
||||
dr.req_recp = iface_recp;
|
||||
dr.bRequest = SET_IDLE;
|
||||
dr.wValue = (duration >> 2) << 8;
|
||||
dr.wIndex = interface->bInterfaceNumber;
|
||||
dr.wLength = 0;
|
||||
dev->controller->control (dev, OUT, sizeof (dev_req_t), &dr, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
usb_hid_set_protocol (usbdev_t *dev, interface_descriptor_t *interface, hid_proto proto)
|
||||
{
|
||||
dev_req_t dr;
|
||||
dr.data_dir = host_to_device;
|
||||
dr.req_type = class_type;
|
||||
dr.req_recp = iface_recp;
|
||||
dr.bRequest = SET_PROTOCOL;
|
||||
dr.wValue = proto;
|
||||
dr.wIndex = interface->bInterfaceNumber;
|
||||
dr.wLength = 0;
|
||||
dev->controller->control (dev, OUT, sizeof (dev_req_t), &dr, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
usb_hid_init (usbdev_t *dev)
|
||||
{
|
||||
|
||||
configuration_descriptor_t *cd = dev->configuration;
|
||||
interface_descriptor_t *interface = ((char *) cd) + cd->bLength;
|
||||
configuration_descriptor_t *cd = (configuration_descriptor_t*)dev->configuration;
|
||||
interface_descriptor_t *interface = (interface_descriptor_t*)(((char *) cd) + cd->bLength);
|
||||
|
||||
if (interface->bInterfaceSubClass == hid_subclass_boot) {
|
||||
printf (" supports boot interface..\n");
|
||||
printf (" it's a %s\n",
|
||||
boot_protos[interface->bInterfaceProtocol]);
|
||||
if (interface->bInterfaceProtocol == hid_boot_proto_keyboard) {
|
||||
dev->data = malloc (sizeof (usbhid_inst_t));
|
||||
printf (" configuring...\n");
|
||||
usb_hid_set_protocol(dev, interface, hid_proto_boot);
|
||||
usb_hid_set_idle(dev, interface, 0);
|
||||
printf (" activating...\n");
|
||||
dev_req_t dr;
|
||||
// set_protocol(hid_proto_boot)
|
||||
dr.data_dir = host_to_device;
|
||||
dr.req_type = class_type;
|
||||
dr.req_recp = iface_recp;
|
||||
dr.bRequest = SET_PROTOCOL;
|
||||
dr.wValue = hid_proto_boot;
|
||||
dr.wIndex = interface->bInterfaceNumber;
|
||||
dr.wLength = 0;
|
||||
dev->controller->control (dev, OUT,
|
||||
sizeof (dev_req_t), &dr, 0,
|
||||
0);
|
||||
|
||||
// only add here, because we only support boot-keyboard HID devices
|
||||
// FIXME: make this a real console input driver instead, once the API is there
|
||||
dev->destroy = usb_hid_destroy;
|
||||
dev->poll = usb_hid_poll;
|
||||
oldhook = getkey_hook;
|
||||
getkey_hook = hookfunc;
|
||||
int i;
|
||||
for (i = 1; i <= dev->num_endp; i++) {
|
||||
if (dev->endpoints[i].endpoint == 0)
|
||||
continue;
|
||||
if (dev->endpoints[i].type != INTERRUPT)
|
||||
continue;
|
||||
if (dev->endpoints[i].direction != IN)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
/* 20 buffers of 8 bytes, for every 10 msecs */
|
||||
HID_INST(dev)->queue = dev->controller->create_intr_queue (&dev->endpoints[i], 8, 20, 10);
|
||||
count = 0;
|
||||
printf (" configuration done.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int usbhid_havechar (void)
|
||||
{
|
||||
return (count != 0);
|
||||
}
|
||||
|
||||
int usbhid_getchar (void)
|
||||
{
|
||||
if (count == 0) return 0;
|
||||
short ret = keybuffer[0];
|
||||
memmove (keybuffer, keybuffer+1, --count);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -53,9 +53,7 @@ usb_hub_destroy (usbdev_t *dev)
|
|||
static void
|
||||
usb_hub_scanport (usbdev_t *dev, int port)
|
||||
{
|
||||
int newdev;
|
||||
unsigned short buf[2];
|
||||
usbdev_t *newdev_t;
|
||||
|
||||
get_status (dev, port, DR_PORT, 4, buf);
|
||||
int portstatus = ((buf[0] & 1) == 0);
|
||||
|
@ -67,9 +65,7 @@ usb_hub_scanport (usbdev_t *dev, int port)
|
|||
int devno = HUB_INST (dev)->ports[port];
|
||||
if (devno == -1)
|
||||
fatal ("FATAL: illegal devno!\n");
|
||||
dev->controller->devices[devno].destroy (&dev->controller->
|
||||
devices[devno]);
|
||||
init_device_entry (dev->controller, devno);
|
||||
usb_detach_device(dev->controller, devno);
|
||||
HUB_INST (dev)->ports[port] = -1;
|
||||
return;
|
||||
}
|
||||
|
@ -80,17 +76,7 @@ usb_hub_scanport (usbdev_t *dev, int port)
|
|||
get_status (dev, port, DR_PORT, 4, buf);
|
||||
int lowspeed = (buf[0] >> 9) & 1;
|
||||
|
||||
newdev = set_address (dev->controller, lowspeed);
|
||||
if (newdev == -1)
|
||||
return;
|
||||
newdev_t = &dev->controller->devices[newdev];
|
||||
|
||||
HUB_INST (dev)->ports[port] = newdev;
|
||||
newdev_t->address = newdev;
|
||||
newdev_t->hub = dev->address;
|
||||
newdev_t->port = port;
|
||||
// determine responsible driver
|
||||
newdev_t->init (newdev_t);
|
||||
HUB_INST (dev)->ports[port] = usb_attach_device(dev->controller, dev->address, port, lowspeed);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -69,7 +69,8 @@ static const char *msc_protocol_strings[0x51] = {
|
|||
static void
|
||||
usb_msc_destroy (usbdev_t *dev)
|
||||
{
|
||||
usbdisk_remove (dev);
|
||||
if (usbdisk_remove)
|
||||
usbdisk_remove (dev);
|
||||
free (dev->data);
|
||||
dev->data = 0;
|
||||
}
|
||||
|
@ -393,5 +394,6 @@ usb_msc_init (usbdev_t *dev)
|
|||
printf ("\n");
|
||||
|
||||
read_capacity (dev);
|
||||
usbdisk_create (dev);
|
||||
if (usbdisk_create)
|
||||
usbdisk_create (dev);
|
||||
}
|
||||
|
|
|
@ -114,6 +114,8 @@ void rtc_read_clock(struct tm *tm);
|
|||
* @{
|
||||
*/
|
||||
int usb_initialize(void);
|
||||
int usbhid_havechar(void);
|
||||
int usbhid_getchar(void);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
|
|
@ -114,7 +114,7 @@ struct usbdev_hc {
|
|||
struct usbdev_hc *next;
|
||||
pcidev_t bus_address;
|
||||
u32 reg_base;
|
||||
usbdev_t devices[128]; // dev 0 is root hub, 127 is last addressable
|
||||
usbdev_t *devices[128]; // dev 0 is root hub, 127 is last addressable
|
||||
void (*start) (hci_t *controller);
|
||||
void (*stop) (hci_t *controller);
|
||||
void (*reset) (hci_t *controller);
|
||||
|
@ -124,6 +124,9 @@ struct usbdev_hc {
|
|||
int (*bulk) (endpoint_t *ep, int size, u8 *data, int finalize);
|
||||
int (*control) (usbdev_t *dev, pid_t pid, int dr_length,
|
||||
void *devreq, int data_length, u8 *data);
|
||||
void* (*create_intr_queue) (endpoint_t *ep, int reqsize, int reqcount, int reqtiming);
|
||||
void (*destroy_intr_queue) (endpoint_t *ep, void *queue);
|
||||
u8* (*poll_intr_queue) (void *queue);
|
||||
void *instance;
|
||||
};
|
||||
|
||||
|
@ -221,4 +224,6 @@ gen_bmRequestType (dev_req_dir dir, dev_req_type type, dev_req_recp recp)
|
|||
return (dir << 7) | (type << 5) | recp;
|
||||
}
|
||||
|
||||
void usb_detach_device(hci_t *controller, int devno);
|
||||
int usb_attach_device(hci_t *controller, int hubaddress, int port, int lowspeed);
|
||||
#endif
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
*
|
||||
* @param dev descriptor for the USB storage device
|
||||
*/
|
||||
void usbdisk_create (usbdev_t *dev);
|
||||
void __attribute__((weak)) usbdisk_create (usbdev_t *dev);
|
||||
|
||||
/**
|
||||
* To be implemented by libpayload-client. It's called by the USB stack
|
||||
|
@ -46,6 +46,6 @@ void usbdisk_create (usbdev_t *dev);
|
|||
*
|
||||
* @param dev descriptor for the USB storage device
|
||||
*/
|
||||
void usbdisk_remove (usbdev_t *dev);
|
||||
void __attribute__((weak)) usbdisk_remove (usbdev_t *dev);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include <config.h>
|
||||
#include <libpayload.h>
|
||||
#include <usb/usb.h>
|
||||
|
||||
void console_init(void)
|
||||
{
|
||||
|
@ -77,6 +78,11 @@ int puts(const char *s)
|
|||
|
||||
int havekey(void)
|
||||
{
|
||||
#ifdef CONFIG_USB_HID
|
||||
usb_poll();
|
||||
if (usbhid_havechar())
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef CONFIG_SERIAL_CONSOLE
|
||||
if (serial_havechar())
|
||||
return 1;
|
||||
|
@ -95,6 +101,11 @@ int havekey(void)
|
|||
int getchar(void)
|
||||
{
|
||||
while (1) {
|
||||
#ifdef CONFIG_USB_HID
|
||||
usb_poll();
|
||||
if (usbhid_havechar())
|
||||
return usbhid_getchar();
|
||||
#endif
|
||||
#ifdef CONFIG_SERIAL_CONSOLE
|
||||
if (serial_havechar())
|
||||
return serial_getchar();
|
||||
|
|
Loading…
Reference in New Issue