- code USB device 'keypad' rewritten and old-style USB device handling removed

- makefile dependencies regerated after USB device code rewrite
- improved error reporting in the new USB device code
This commit is contained in:
Volker Ruppert 2007-03-25 17:37:59 +00:00
parent 58ba0172bb
commit 324250ccb4
6 changed files with 1182 additions and 1816 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: pciusb.cc,v 1.53 2007-03-24 11:43:41 vruppert Exp $
// $Id: pciusb.cc,v 1.54 2007-03-25 17:37:59 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2004 MandrakeSoft S.A.
@ -226,9 +226,6 @@ void bx_pciusb_c::reset(unsigned type)
// reset locals
BX_USB_THIS busy = 0;
BX_USB_THIS global_reset = 0;
BX_USB_THIS set_address_stk = 0;
memset(BX_USB_THIS saved_key, 0, 8);
memset(BX_USB_THIS key_pad_packet, 0, 8);
// Put the USB registers into their RESET state
for (i=0; i<BX_USB_CONFDEV; i++) {
@ -272,17 +269,8 @@ void bx_pciusb_c::reset(unsigned type)
}
}
// First, clear out the device(s)
for (i=0; i<BX_USB_CONFDEV; i++)
for (j=0; j<USB_CUR_DEVS; j++) {
memset(&BX_USB_THIS hub[i].device[j], 0, sizeof(USB_DEVICE));
}
BX_USB_THIS keyboard_connected = 0;
BX_USB_THIS mousedev = NULL;
// include the device(s) initialize code
#include "pciusb_devs.h"
BX_USB_THIS keybdev = NULL;
init_device(0, SIM->get_param_string(BXPN_USB1_PORT1)->getptr());
init_device(1, SIM->get_param_string(BXPN_USB1_PORT2)->getptr());
@ -292,7 +280,7 @@ void bx_pciusb_c::reset(unsigned type)
void bx_pciusb_c::register_state(void)
{
unsigned i, j;
char hubnum[8], portnum[8], name[6];
char hubnum[8], portnum[8];
bx_list_c *hub, *usb_cmd, *usb_st, *usb_en, *port;
bx_list_c *list = new bx_list_c(SIM->get_sr_root(), "pciusb", "PCI USB Controller State", BX_USB_CONFDEV + 15);
@ -341,23 +329,7 @@ void bx_pciusb_c::register_state(void)
}
new bx_shadow_bool_c(list, "busy", &BX_USB_THIS busy);
new bx_shadow_num_c(list, "global_reset", &BX_USB_THIS global_reset);
bx_list_c *svkey = new bx_list_c(list, "saved_key", 8);
for (i=0; i<8; i++) {
sprintf(name, "%d", i);
new bx_shadow_num_c(svkey, name, &BX_USB_THIS saved_key[i]);
}
bx_list_c *kppkt = new bx_list_c(list, "key_pad_packet", 8);
for (i=0; i<8; i++) {
sprintf(name, "%d", i);
new bx_shadow_num_c(kppkt, name, &BX_USB_THIS key_pad_packet[i]);
}
new bx_shadow_data_c(list, "device_buffer", BX_USB_THIS device_buffer, 65536);
new bx_shadow_num_c(list, "set_address_stk", &BX_USB_THIS set_address_stk);
bx_list_c *setaddr = new bx_list_c(list, "set_address", 128);
for (i=0; i<128; i++) {
sprintf(name, "0x%02x", i);
new bx_shadow_num_c(setaddr, name, &BX_USB_THIS set_address[i], BASE_HEX);
}
}
void bx_pciusb_c::after_restore_state(void)
@ -396,7 +368,10 @@ void bx_pciusb_c::init_device(Bit8u port, const char *devname)
} else if (!strcmp(devname, "keypad")) {
type = USB_DEV_TYPE_KEYPAD;
connected = 1;
BX_USB_THIS keyboard_connected = 1;
BX_USB_THIS hub[0].usb_port[port].device = new usb_hid_device_t(type);
if (BX_USB_THIS keybdev == NULL) {
BX_USB_THIS keybdev = (usb_hid_device_t*)BX_USB_THIS hub[0].usb_port[port].device;
}
} else if (!strncmp(devname, "disk:", 5)) {
type = USB_DEV_TYPE_DISK;
connected = 1;
@ -405,14 +380,6 @@ void bx_pciusb_c::init_device(Bit8u port, const char *devname)
BX_PANIC(("unknown USB device: %s", devname));
return;
}
if (BX_USB_THIS hub[0].usb_port[port].device == NULL) {
for (int i=0; i<USB_CUR_DEVS; i++) {
if (BX_USB_THIS hub[0].device[i].dev_type == type) {
BX_USB_THIS hub[0].usb_port[port].device_num = i;
BX_USB_THIS hub[0].device[i].stall_once &= ~0x80; // clear out the "stall once bit has happened"
}
}
}
usb_set_connect_status(port, type, connected);
}
@ -560,9 +527,6 @@ void bx_pciusb_c::write(Bit32u address, Bit32u value, unsigned io_len)
if (BX_USB_THIS hub[0].usb_port[i].status) {
if (BX_USB_THIS hub[0].usb_port[i].device != NULL) {
BX_USB_THIS usb_send_msg(BX_USB_THIS hub[0].usb_port[i].device, USB_MSG_RESET);
} else {
usb_set_connect_status(i, BX_USB_THIS hub[0].device[BX_USB_THIS hub[0].usb_port[i].device_num].dev_type,
BX_USB_THIS hub[0].device[BX_USB_THIS hub[0].usb_port[i].device_num].connect_status);
}
}
BX_USB_THIS hub[0].usb_port[i].connect_changed = 1;
@ -705,9 +669,6 @@ void bx_pciusb_c::write(Bit32u address, Bit32u value, unsigned io_len)
(BX_USB_THIS hub[0].usb_port[port].device->get_speed() == USB_SPEED_LOW);
usb_set_connect_status(port, BX_USB_THIS hub[0].usb_port[port].device->get_type(), 1);
BX_USB_THIS usb_send_msg(BX_USB_THIS hub[0].usb_port[port].device, USB_MSG_RESET);
} else {
BX_USB_THIS hub[0].device[BX_USB_THIS hub[0].usb_port[port].device_num].connect_status = 0;
usb_set_connect_status(port, BX_USB_THIS hub[0].device[BX_USB_THIS hub[0].usb_port[port].device_num].dev_type, 1);
}
}
BX_INFO(("Port%d: Reset", port+1));
@ -900,23 +861,13 @@ void bx_pciusb_c::usb_timer(void)
bx_bool bx_pciusb_c::DoTransfer(Bit32u address, Bit32u queue_num, struct TD *td) {
int i, j, len = 0, ret = 0;
Bit8u protocol = 0;
bx_bool fnd;
usb_device_t *newdev = NULL;
int i, len = 0, ret = 0;
usb_device_t *dev = NULL;
Bit16u maxlen = (td->dword2 >> 21);
Bit8u addr = (td->dword2 >> 8) & 0x7F;
Bit8u endpt = (td->dword2 >> 15) & 0x0F;
Bit8u pid = td->dword2 & 0xFF;
Bit8u data[64];
struct REQUEST_PACKET *rp = (struct REQUEST_PACKET *) data;
// if packet, read in the packet data
if (pid == USB_TOKEN_SETUP) {
if (td->dword3) DEV_MEM_READ_PHYSICAL(td->dword3, 8, data);
// the '8' above may need to be maxlen (unless maxlen == 0)
}
BX_DEBUG(("QH%03i:TD found at address: 0x%08X", queue_num, address));
BX_DEBUG((" %08X %08X %08X %08X", td->dword0, td->dword1, td->dword2, td->dword3));
@ -933,20 +884,12 @@ bx_bool bx_pciusb_c::DoTransfer(Bit32u address, Bit32u queue_num, struct TD *td)
// find device address
bx_bool at_least_one = 0;
struct USB_DEVICE *dev = NULL;
for (i=0; i<USB_CUR_DEVS; i++) {
if (BX_USB_THIS hub[0].device[i].connect_status) at_least_one = 1;
if ((BX_USB_THIS hub[0].device[i].address == addr) && BX_USB_THIS hub[0].device[i].connect_status) {
dev = &BX_USB_THIS hub[0].device[i];
break;
}
}
for (i=0; i<USB_NUM_PORTS; i++) {
if (BX_USB_THIS hub[0].usb_port[i].device != NULL) {
if (BX_USB_THIS hub[0].usb_port[i].device->get_connected()) {
at_least_one = 1;
if (BX_USB_THIS hub[0].usb_port[i].device->get_address() == addr) {
newdev = BX_USB_THIS hub[0].usb_port[i].device;
dev = BX_USB_THIS hub[0].usb_port[i].device;
break;
}
}
@ -956,7 +899,7 @@ bx_bool bx_pciusb_c::DoTransfer(Bit32u address, Bit32u queue_num, struct TD *td)
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
return 1;
}
if ((dev == NULL) && (newdev == NULL)) {
if (dev == NULL) {
if ((pid == USB_TOKEN_OUT) && (maxlen == 0x7FF) && (addr == 0)) {
// This is the "keep awake" packet that Windows sends once a schedule cycle.
// For now, let it pass through to the code below.
@ -975,7 +918,7 @@ bx_bool bx_pciusb_c::DoTransfer(Bit32u address, Bit32u queue_num, struct TD *td)
maxlen++;
maxlen &= 0x7FF;
if (newdev != NULL) {
if (dev != NULL) {
BX_USB_THIS usb_packet.pid = pid;
BX_USB_THIS usb_packet.devaddr = addr;
BX_USB_THIS usb_packet.devep = endpt;
@ -987,11 +930,11 @@ bx_bool bx_pciusb_c::DoTransfer(Bit32u address, Bit32u queue_num, struct TD *td)
if (maxlen > 0) {
DEV_MEM_READ_PHYSICAL(td->dword3, maxlen, device_buffer);
}
ret = newdev->handle_packet(&BX_USB_THIS usb_packet);
ret = dev->handle_packet(&BX_USB_THIS usb_packet);
len = maxlen;
break;
case USB_TOKEN_IN:
ret = newdev->handle_packet(&BX_USB_THIS usb_packet);
ret = dev->handle_packet(&BX_USB_THIS usb_packet);
if (ret >= 0) {
len = ret;
if (len > maxlen) {
@ -1016,549 +959,7 @@ bx_bool bx_pciusb_c::DoTransfer(Bit32u address, Bit32u queue_num, struct TD *td)
}
return 1;
}
if (dev) {
if (maxlen > dev->function.device_descr.max_packet_size)
maxlen = dev->function.device_descr.max_packet_size;
} else
maxlen = 0;
// parse and get command
Bit16u cnt;
switch (pid) {
case USB_TOKEN_IN: // Data came from HC to Host
// if an interrupt in / bulk in, do the protocol packet.
if (endpt > 0) {
fnd = 0;
for (i=0; (i<dev->function.device_config[dev->config].interfaces) && !fnd; i++) {
for (j=0; j<dev->function.device_config[dev->config].Interface[i].num_endpts; j++) {
if (endpt == (dev->function.device_config[dev->config].Interface[i].endpts[j].endpt & 0x7F)) {
protocol = dev->function.device_config[dev->config].Interface[i].protocol;
fnd = 1;
break;
}
}
}
if (fnd) {
cnt = dev->function.device_config[dev->config].Interface[dev->Interface].endpts[0].max_size;
switch (protocol) {
case 1: // keypad
memcpy(device_buffer, BX_USB_THIS key_pad_packet, 8);
DEV_MEM_WRITE_PHYSICAL(td->dword3, cnt, device_buffer);
BX_USB_THIS set_status(td, 0, 0, 0, 0, 0, 0, cnt-1);
break;
default:
BX_PANIC(("Unknown/unsupported endpt protocol issued an Interrupt In / Bulk packet. protocol %i", protocol));
}
} else {
BX_PANIC(("Unknown endpt issued an Interrupt In / Bulk packet. ID 0x%04x Interface %i endpt %i", i, endpt, dev->function.device_descr.vendorid));
}
} else {
BX_DEBUG(("TOKEN_IN: len = %i", maxlen));
BX_DEBUG((" address = 0x%08X, Depth = %i, QH = %i, Terminate = %i\n"
" spd=%i, c_err=%i, LS=%i, IOS=%i, IOC=%i, status=0x%02X, act_len=0x%03X\n"
" max_len=0x%03X, D=%i, EndPt=%i, addr=%i, PID=0x%02X\n"
" buffer address = 0x%08X",
td->dword0 & ~0x0000000F, (td->dword0 & 0x00000004)?1:0, (td->dword0 & 0x00000002)?1:0, (td->dword0 & 0x00000001)?1:0,
(td->dword1 & 0x20000000)?1:0, (td->dword1 & 0x18000000)>>27, (td->dword1 & 0x04000000)?1:0, (td->dword1 & 0x02000000)?1:0, (td->dword1 & 0x01000000)?1:0, (td->dword1 & 0x00FF0000)>>16, td->dword1 & 0x000007FF,
(td->dword2 & 0xFFE00000)>>21, (td->dword2 & 0x00080000)?1:0, (td->dword2 & 0x00078000)>>15, (td->dword2 & 0x00007F00)>>8, td->dword2 & 0x000000FF,
td->dword3));
// After a set address, the Host will send an empty IN packet for the status stage.
// The address on the IN packet will still be zero (0).
// So we need to set the address for this device *after* the in packet.
if (maxlen == 0) {
BX_USB_THIS set_status(td, 0, 0, 0, 0, 0, 0, 0x7FF);
if (BX_USB_THIS set_address_stk && (addr == 0)) {
BX_USB_THIS set_address_stk--;
dev->address = BX_USB_THIS set_address[BX_USB_THIS set_address_stk];
dev->state = STATE_ADDRESS;
}
break;
}
if (dev->function.in_cnt > 0) {
bx_gui->statusbar_setitem(BX_USB_THIS hub[0].statusbar_id[0], 1);
cnt = (dev->function.in_cnt < maxlen) ? dev->function.in_cnt : maxlen;
DEV_MEM_WRITE_PHYSICAL(td->dword3, cnt, dev->function.in);
usb_dump_packet(dev->function.in, cnt);
dev->function.in += cnt;
dev->function.in_cnt -= cnt;
BX_USB_THIS set_status(td, 0, 0, 0, 0, 0, 0, cnt-1);
} else
BX_USB_THIS set_status(td, 0, 0, 0, 0, 0, 0, 0x7FF);
bx_gui->statusbar_setitem(BX_USB_THIS hub[0].statusbar_id[0], 0);
}
break;
case USB_TOKEN_OUT: // data should go from Host to HC
// (remember that we will get an out once in a while with dev==NULL)
if ((addr > 0) && (endpt > 0)) {
fnd = 0;
for (i=0; (i<dev->function.device_config[dev->config].interfaces) && !fnd; i++) {
for (j=0; j<dev->function.device_config[dev->config].Interface[i].num_endpts; j++) {
if (endpt == (dev->function.device_config[dev->config].Interface[i].endpts[j].endpt & 0x7F)) {
protocol = dev->function.device_config[dev->config].Interface[i].protocol;
fnd = 1;
break;
}
}
}
if (fnd) {
// Read in the packet
Bit8u bulk_int_packet[1024];
DEV_MEM_READ_PHYSICAL(td->dword3, maxlen, bulk_int_packet);
// now do the task
switch (protocol) {
case 1: // keypad
BX_PANIC(("Keyboard received and OUT packet!"));
break;
default:
BX_PANIC(("Unknown/unsupported endpt protocol issued an Interrupt Out / Bulk packet. protocol %i", protocol));
}
} else {
BX_PANIC(("Unknown endpt issued an Interrupt Out / Bulk packet. ID 0x%04x Interface %i endpt %i", i, endpt, dev->function.device_descr.vendorid));
}
} else {
BX_DEBUG(("TOKEN_OUT: maxlen = 0x%03X", maxlen));
BX_DEBUG((" address = 0x%08X, Depth = %i, QH = %i, Terminate = %i\n"
" spd=%i, c_err=%i, LS=%i, IOS=%i, IOC=%i, status=0x%02X, act_len=0x%03X\n"
" max_len=0x%03X, D=%i, EndPt=%i, addr=%i, PID=0x%02X\n"
" buffer address = 0x%08X",
td->dword0 & ~0x0000000F, (td->dword0 & 0x00000004)?1:0, (td->dword0 & 0x00000002)?1:0, (td->dword0 & 0x00000001)?1:0,
(td->dword1 & 0x20000000)?1:0, (td->dword1 & 0x18000000)>>27, (td->dword1 & 0x04000000)?1:0, (td->dword1 & 0x02000000)?1:0, (td->dword1 & 0x01000000)?1:0, (td->dword1 & 0x00FF0000)>>16, td->dword1 & 0x000007FF,
(td->dword2 & 0xFFE00000)>>21, (td->dword2 & 0x00080000)?1:0, (td->dword2 & 0x00078000)>>15, (td->dword2 & 0x00007F00)>>8, td->dword2 & 0x000000FF,
td->dword3));
if (maxlen == 0) {
BX_USB_THIS set_status(td, 0, 0, 0, 0, 0, 0, 0x7FF);
} else {
BX_ERROR(("Got to this position and shouldn't have...000"));
}
}
bx_gui->statusbar_setitem(BX_USB_THIS hub[0].statusbar_id[0], 0);
break;
case USB_TOKEN_SETUP:
if (dev) dev->in_stall = 0;
// as a debug check, stall on the first setup packet after boot up.
if (dev && (dev->stall_once & 0x01) && !(dev->stall_once & 0x80)) {
dev->stall_once |= 0x80;
BX_USB_THIS set_status(td, 1, 0, 0, 0, 1, 0, 0x007);
BX_INFO((" Stalling once one first setup packet after bootup"));
break;
}
BX_DEBUG((" SETUP packet: %02X %02X %02X %02X %02X %02X %02X %02X",
data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]));
switch (rp->request) {
case GET_STATUS:
switch (dev->state) {
case STATE_DEFAULT:
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
BX_ERROR(("Request: GET_STATUS returned an error"));
break;
case STATE_ADDRESS:
if (rp->index > 0) {
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
BX_ERROR(("Request: GET_STATUS returned an error"));
break;
} // else fall through
case STATE_CONFIGURED:
// If the interface or endpoint does not exist, return error
device_buffer[0] = 0;
device_buffer[1] = 0;
dev->function.in = device_buffer;
dev->function.in_cnt = 2;
BX_INFO(("Request: GET_STATUS"));
BX_USB_THIS set_status(td, 0, 0, 0, 0, 0, 0, 0x007); // an 8 byte packet was received
}
break;
case CLEAR_FEATURE:
switch (dev->state) {
case STATE_DEFAULT:
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
BX_ERROR(("Request: CLEAR_FEATURE returned an error"));
break;
case STATE_ADDRESS:
if (rp->index > 0) {
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
BX_ERROR(("Request: CLEAR_FEATURE returned an error"));
break;
} // else fall through
case STATE_CONFIGURED:
if (rp->length) {
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
BX_ERROR(("Request: CLEAR_FEATURE returned an error: length > 0"));
break;
}
// At this point, we don't implement features. So until we do, there isn't anything
// to clear. Just log an error and continue.
BX_ERROR(("Request: CLEAR_FEATURE: Not implemented yet."));
BX_USB_THIS set_status(td, 0, 0, 0, 0, 0, 0, 0x007); // an 8 byte packet was received
break;
}
break;
case SET_FEATURE:
switch (dev->state) {
case STATE_DEFAULT:
if (((rp->index >> 8) == SET_FEATURE_TEST_MODE) && (rp->request_type == 0) && ((rp->index & 0xFF) == 0)) {
BX_DEBUG(("Request: SET_FEATURE in TEST MODE"));
} else {
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
BX_ERROR(("Request: SET_FEATURE returned an error"));
}
break;
case STATE_ADDRESS:
if ((rp->index & 0xFF) > 0) {
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
BX_ERROR(("Request: SET_FEATURE returned an error"));
break;
} // else fall through
case STATE_CONFIGURED:
// At this point, we don't implement features. So until we do, there isn't anything
// to set. Just log an error and continue.
BX_ERROR(("Request: SET_FEATURE: Not implemented yet."));
BX_USB_THIS set_status(td, 0, 0, 0, 0, 0, 0, 0x007); // an 8 byte packet was received
}
break;
case SET_ADDRESS:
BX_DEBUG(("Request: SET_ADDRESS: %04x", rp->value));
BX_DEBUG((" address = 0x%08X, Depth = %i, QH = %i, Terminate = %i\n"
" spd=%i, c_err=%i, LS=%i, IOS=%i, IOC=%i, status=0x%02X, act_len=0x%03X\n"
" max_len=0x%03X, D=%i, EndPt=%i, addr=%i, PID=0x%02X\n"
" buffer address = 0x%08X",
td->dword0 & ~0x0000000F, (td->dword0 & 0x00000004)?1:0, (td->dword0 & 0x00000002)?1:0, (td->dword0 & 0x00000001)?1:0,
(td->dword1 & 0x20000000)?1:0, (td->dword1 & 0x18000000)>>27, (td->dword1 & 0x04000000)?1:0, (td->dword1 & 0x02000000)?1:0, (td->dword1 & 0x01000000)?1:0, (td->dword1 & 0x00FF0000)>>16, td->dword1 & 0x000007FF,
(td->dword2 & 0xFFE00000)>>21, (td->dword2 & 0x00080000)?1:0, (td->dword2 & 0x00078000)>>15, (td->dword2 & 0x00007F00)>>8, td->dword2 & 0x000000FF,
td->dword3));
if ((rp->value > 127) || rp->index || rp->length) {
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
BX_ERROR(("Request: SET_ADDRESS returned an error"));
} else {
switch (dev->state) {
case STATE_DEFAULT:
BX_USB_THIS set_address[BX_USB_THIS set_address_stk] = (Bit8u) rp->value;
BX_USB_THIS set_address_stk++;
BX_USB_THIS set_status(td, 0, 0, 0, 0, 0, 0, 0x007);
break;
case STATE_ADDRESS:
if (rp->value > 0) {
BX_USB_THIS set_address[BX_USB_THIS set_address_stk] = (Bit8u) rp->value;
BX_USB_THIS set_address_stk++;
} else {
BX_USB_THIS set_address[BX_USB_THIS set_address_stk] = 0;
BX_USB_THIS set_address_stk++;
dev->state = STATE_DEFAULT;
}
BX_USB_THIS set_status(td, 0, 0, 0, 0, 0, 0, 0x007);
break;
case STATE_CONFIGURED:
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
BX_ERROR(("Request: SET_ADDRESS returned an error"));
}
}
break;
case GET_DESCRIPTOR:
BX_DEBUG(("Request: GET_DESCRIPTOR: 0x%02x 0x%02x %i", rp->value >> 8, rp->value & 0xFF, rp->length));
BX_DEBUG((" address = 0x%08X, Depth = %i, QH = %i, Terminate = %i\n"
" spd=%i, c_err=%i, LS=%i, IOS=%i, IOC=%i, status=0x%02X, act_len=0x%03X\n"
" max_len=0x%03X, D=%i, EndPt=%i, addr=%i, PID=0x%02X\n"
" buffer address = 0x%08X",
td->dword0 & ~0x0000000F, (td->dword0 & 0x00000004)?1:0, (td->dword0 & 0x00000002)?1:0, (td->dword0 & 0x00000001)?1:0,
(td->dword1 & 0x20000000)?1:0, (td->dword1 & 0x18000000)>>27, (td->dword1 & 0x04000000)?1:0, (td->dword1 & 0x02000000)?1:0, (td->dword1 & 0x01000000)?1:0, (td->dword1 & 0x00FF0000)>>16, td->dword1 & 0x000007FF,
(td->dword2 & 0xFFE00000)>>21, (td->dword2 & 0x00080000)?1:0, (td->dword2 & 0x00078000)>>15, (td->dword2 & 0x00007F00)>>8, td->dword2 & 0x000000FF,
td->dword3));
switch (dev->state) {
case STATE_DEFAULT:
case STATE_ADDRESS:
case STATE_CONFIGURED:
unsigned ret;
ret = BX_USB_THIS GetDescriptor(dev, rp);
BX_USB_THIS set_status(td, ret, 0, 0, 0, (ret && pid==USB_TOKEN_SETUP)?1:0, 0, 0x007);
}
break;
case SET_DESCRIPTOR:
switch (dev->state) {
case STATE_DEFAULT:
BX_ERROR(("Request: SET_DESCRIPTOR returned an error"));
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
break;
case STATE_ADDRESS:
case STATE_CONFIGURED:
BX_PANIC(("Request: SET_DESCRIPTOR not implemented yet"));
//dev->descriptor = (Bit8u) rp->value >> 8;
BX_DEBUG(("Request: SET_DESCRIPTOR: %02x", rp->value >> 8));
BX_USB_THIS set_status(td, 0, 0, 0, 0, 0, 0, 0x007); // an 8 byte packet was received
}
break;
case GET_CONFIGURATION:
BX_DEBUG(("Request: GET_CONFIGURATION"));
BX_DEBUG((" address = 0x%08X, Depth = %i, QH = %i, Terminate = %i\n"
" spd=%i, c_err=%i, LS=%i, IOS=%i, IOC=%i, status=0x%02X, act_len=0x%03X\n"
" max_len=0x%03X, D=%i, EndPt=%i, addr=%i, PID=0x%02X\n"
" buffer address = 0x%08X",
td->dword0 & ~0x0000000F, (td->dword0 & 0x00000004)?1:0, (td->dword0 & 0x00000002)?1:0, (td->dword0 & 0x00000001)?1:0,
(td->dword1 & 0x20000000)?1:0, (td->dword1 & 0x18000000)>>27, (td->dword1 & 0x04000000)?1:0, (td->dword1 & 0x02000000)?1:0, (td->dword1 & 0x01000000)?1:0, (td->dword1 & 0x00FF0000)>>16, td->dword1 & 0x000007FF,
(td->dword2 & 0xFFE00000)>>21, (td->dword2 & 0x00080000)?1:0, (td->dword2 & 0x00078000)>>15, (td->dword2 & 0x00007F00)>>8, td->dword2 & 0x000000FF,
td->dword3));
switch (dev->state) {
case STATE_DEFAULT:
BX_ERROR(("Request: GET_CONFIGURATION returned an error"));
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
break;
case STATE_ADDRESS:
// must return zero if in the address state
*device_buffer = 0;
break;
case STATE_CONFIGURED:
*device_buffer = dev->function.device_config[dev->config].config_val;
}
dev->function.in = device_buffer;
dev->function.in_cnt = 1;
BX_DEBUG(("Request: GET_CONFIGURATION"));
BX_USB_THIS set_status(td, 0, 0, 0, 0, 0, 0, 0x007); // an 8 byte packet was received
break;
case SET_CONFIGURATION:
switch (dev->state) {
case STATE_DEFAULT:
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
BX_ERROR(("Request: SET_CONFIGURATION: returned an error"));
break;
case STATE_CONFIGURED:
if ((rp->value & 0xFF) == 0) {
dev->state = STATE_DEFAULT;
BX_DEBUG(("Request: SET_CONFIGURATION = 0 (set to default state)"));
BX_USB_THIS set_status(td, 0, 0, 0, 0, 0, 0, 0x007); // an 8 byte packet was received
break;
} // else fall through ????
case STATE_ADDRESS:
dev->config = 0xFF;
unsigned configs;
for (configs=0; configs<dev->function.configs; configs++) {
if ((rp->value & 0xFF) == dev->function.device_config[configs].config_val) {
dev->config = configs;
dev->state = STATE_CONFIGURED;
break;
}
}
if (dev->config == 0xFF) {
dev->config = 0;
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
BX_ERROR(("Request: SET_CONFIGURATION: returned an error"));
} else {
BX_USB_THIS set_status(td, 0, 0, 0, 0, 0, 0, 0x007); // an 8 byte packet was received
BX_DEBUG(("Request: SET_CONFIGURATION: %02x", rp->value));
}
break;
}
break;
case GET_INTERFACE:
switch (dev->state) {
case STATE_DEFAULT:
case STATE_ADDRESS:
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
BX_ERROR(("Request: GET_INTERFACE returned and error: not in configured state"));
break;
case STATE_CONFIGURED:
if ((unsigned)(rp->index + 1) > dev->function.device_config[dev->config].interfaces) {
BX_PANIC(("GET_INTERFACE: wanted interface number is greater than interface count."));
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
}
// The USB specs say that I can return a STALL if only one interface is used. (ie, no alternate)
// However, Win98SE doesn't like it at all....
//if (dev->function.device_config[dev->config].interfaces > 1) {
*device_buffer = dev->function.device_config[dev->config].Interface[rp->value & 0xFF].alternate;
dev->function.in = device_buffer;
dev->function.in_cnt = 1;
if (dev->function.in_cnt > rp->length)
dev->function.in_cnt = rp->length;
BX_DEBUG(("Request: GET_INTERFACE %02X %02X %02X", rp->value >> 8, rp->value & 0xFF, rp->length));
BX_USB_THIS set_status(td, 0, 0, 0, 0, 0, 0, 0x007); // an 8 byte packet was received
//} else {
// BX_DEBUG(("Request: GET_INTERFACE %02X %02X %02X (Only 1 interface, returning STALL)", rp->value >> 8, rp->value & 0xFF, rp->length));
// BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
//}
break;
}
break;
case SET_INTERFACE:
switch (dev->state) {
case STATE_DEFAULT:
case STATE_ADDRESS:
BX_ERROR(("Request: SET_INTERFACE returned and error: not in configured state"));
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
break;
case STATE_CONFIGURED:
if ((unsigned)(rp->index + 1) > dev->function.device_config[dev->config].interfaces) {
BX_PANIC(("SET_INTERFACE: wanted interface number is greater than interface count."));
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
}
dev->Interface = (Bit8u) rp->index;
dev->alt_interface = (Bit8u) rp->value;
BX_DEBUG(("Request: SET_INTERFACE: %02x (alt %02x)", rp->index, rp->value));
BX_USB_THIS set_status(td, 0, 0, 0, 0, 0, 0, 0x007); // an 8 byte packet was received
}
break;
case SYNCH_FRAME:
switch (dev->state) {
case STATE_DEFAULT:
case STATE_ADDRESS:
BX_ERROR(("Request: SYNCH_FRAME returned and error: not in configured state"));
BX_USB_THIS set_status(td, 1, 0, 0, 0, (pid==USB_TOKEN_SETUP)?1:0, 0, 0x007); // an 8 byte packet was received, but stalled
break;
case STATE_CONFIGURED:
BX_PANIC(("Request: SYNCH_FRAME not implemented yet"));
BX_DEBUG(("Request: SYNCH_FRAME"));
BX_USB_THIS set_status(td, 0, 0, 0, 0, 0, 0, 0x007); // an 8 byte packet was received
}
break;
default:
BX_PANIC((" **** illegal or unknown REQUEST sent to Host Controller: %02x", data[1]));
}
break;
default:
BX_PANIC(("illegal PID sent to Host Controller: %02x", pid));
}
// did it stall?, then set the "in_stall" state
if (td->dword1 & (1<<22))
if (dev) dev->in_stall = 1;
return 1;
}
unsigned bx_pciusb_c::GetDescriptor(struct USB_DEVICE *dev, struct REQUEST_PACKET *packet)
{
Bit8u *p = device_buffer;
unsigned i, j, fnd, ret = 0; // ret = 0 = no error
BX_DEBUG(("GET DESCRIPTOR 0x%02X 0x%02X value=0x%04X len=%i index=%i",
packet->request, packet->request_type, packet->value, packet->length, packet->index));
switch (packet->value >> 8) {
case USB_DT_DEVICE:
dev->function.in = (Bit8u *) &dev->function.device_descr;
dev->function.in_cnt = dev->function.device_descr.len;
ret = 0;
break;
case USB_DT_CONFIG:
memcpy(p, &dev->function.device_config[dev->config], 9); p += 9; // config descriptor
for (i=0; i<dev->function.device_config[dev->config].interfaces; i++) {
memcpy(p, &dev->function.device_config[dev->config].Interface[i], 9); p += 9;
for (j=0; j<dev->function.device_config[dev->config].Interface[i].num_endpts; j++) {
memcpy(p, &dev->function.device_config[dev->config].Interface[i].endpts[j], 7); p += 7;
}
memcpy(p, &dev->function.device_config[dev->config].Interface[i].dev_hid_descript, 6); p += 6;
for (j=0; j<dev->function.device_config[dev->config].Interface[i].dev_hid_descript.num_descriptors; j++) {
memcpy(p, &dev->function.device_config[dev->config].Interface[i].dev_hid_descript.descriptor[j], 3); p += 3;
}
}
dev->function.in = device_buffer;
dev->function.in_cnt = (p - device_buffer);
ret = 0;
break;
case USB_DT_STRING:
switch (packet->value & 0xFF) {
case 0: // string descriptor table
dev->function.in = (Bit8u *) &dev->function.str_descriptor;
dev->function.in_cnt = dev->function.str_descriptor.size;
ret = 0;
break;
case 1: case 2: case 3:
case 4: case 5: case 6:
dev->function.in = (Bit8u *) &dev->function.string[(packet->value & 0xFF)-1];
dev->function.in_cnt = dev->function.string[(packet->value & 0xFF)-1].size;
break;
ret = 0;
default:
BX_ERROR(("STRING: %i", packet->value & 0xFF));
ret = 1;
}
break;
case USB_DT_INTERFACE:
BX_PANIC(("GET_DESCRIPTOR: INTERFACE not implemented yet."));
ret = 1;
break;
case USB_DT_ENDPOINT:
BX_PANIC(("GET_DESCRIPTOR: ENDPOINT not implemented yet."));
ret = 1;
break;
case USB_DT_DEVICE_QUALIFIER:
device_buffer[0] = 10;
device_buffer[1] = USB_DT_DEVICE_QUALIFIER;
memcpy(device_buffer+2, &dev->function.device_descr+2, 6);
device_buffer[8] = 1;
device_buffer[9] = 0;
dev->function.in = device_buffer;
dev->function.in_cnt = 10;
ret = 0;
break;
case USB_DT_OTHER_SPEED_CONFIG:
BX_PANIC(("GET_DESCRIPTOR: OTHER_SPEED_CONFIG not implemented yet."));
ret = 1;
break;
case USB_DT_INTERFACE_POWER:
BX_PANIC(("GET_DESCRIPTOR: INTERFACE_POWER not implemented yet."));
ret = 1;
break;
case 0x21: // (HID device descriptor)
dev->function.in = (Bit8u *) &dev->function.device_config[dev->config].Interface[packet->index-1].dev_hid_descript;
dev->function.in_cnt = dev->function.device_config[dev->config].Interface[packet->index-1].dev_hid_descript.size;
ret = 0;
break;
case 0x22: // (HID report descriptor)
// Win98SE passes packet->index as endpoint number (packet->request_type = 0x82)
// SuSE Linux passes packet->index as interface number (packet->request_type = 0x81)
switch (packet->request_type & 0x1F) {
case 2: // endpoint
fnd = 0;
for (i=0; (i<dev->function.device_config[dev->config].interfaces) && !fnd; i++) {
for (j=0; (j<dev->function.device_config[dev->config].Interface[i].num_endpts) && !fnd; j++) {
if ((dev->function.device_config[dev->config].Interface[i].endpts[j].endpt & ~0x80) == packet->index) {
packet->index = i;
fnd = 1;
}
}
}
if (!fnd) {
BX_ERROR(("Get Descriptor: HID Report: index = endpint. did not find endpoint"));
ret = 1;
break;
} // else fall through to interface
case 1: // interface
for (i=0; i<dev->function.device_config[dev->config].Interface[packet->index].dev_hid_descript.num_descriptors; i++) {
if (dev->function.device_config[dev->config].Interface[packet->index].dev_hid_descript.descriptor[i].type == 0x22) {
dev->function.in = dev->function.device_config[dev->config].Interface[packet->index].dev_hid_descript.descriptor[i].dev_hid_descript_report;
dev->function.in_cnt = dev->function.device_config[dev->config].Interface[packet->index].dev_hid_descript.descriptor[i].len;
break;
}
}
ret = 0;
break;
case 0: // device
case 3: // other
default: // reserved
BX_ERROR(("Get Descriptor: HID Report: index = reserved. Should be Interface or Endpoint"));
ret = 1;
break;
}
break;
default:
BX_PANIC((" **** illegal or unknown GET_DESCRIPTOR::DEVICE sent to Host Controller: %02x", packet->value >> 8));
return 1;
}
if (dev->function.in_cnt > packet->length)
dev->function.in_cnt = packet->length;
return ret;
return 0;
}
// If the request fails, set the stall bit ????
@ -1770,7 +1171,9 @@ void bx_pciusb_c::usb_set_connect_status(Bit8u port, int type, bx_bool connected
BX_USB_THIS mousedev = NULL;
}
} else if (type == USB_DEV_TYPE_KEYPAD) {
BX_USB_THIS keyboard_connected = 0;
if (BX_USB_THIS hub[0].usb_port[port].device == BX_USB_THIS keybdev) {
BX_USB_THIS keybdev = NULL;
}
}
if (BX_USB_THIS hub[0].usb_port[port].device != NULL) {
delete BX_USB_THIS hub[0].usb_port[port].device;
@ -1779,53 +1182,6 @@ void bx_pciusb_c::usb_set_connect_status(Bit8u port, int type, bx_bool connected
}
}
}
if (BX_USB_THIS hub[0].usb_port[port].device_num > -1) {
if (BX_USB_THIS hub[0].device[BX_USB_THIS hub[0].usb_port[port].device_num].dev_type == type) {
if (connected) {
if (!BX_USB_THIS hub[0].device[BX_USB_THIS hub[0].usb_port[port].device_num].connect_status) {
BX_USB_THIS hub[0].device[BX_USB_THIS hub[0].usb_port[port].device_num].state = STATE_DEFAULT;
BX_USB_THIS hub[0].device[BX_USB_THIS hub[0].usb_port[port].device_num].address = 0;
BX_USB_THIS hub[0].device[BX_USB_THIS hub[0].usb_port[port].device_num].alt_interface = 0;
BX_USB_THIS hub[0].device[BX_USB_THIS hub[0].usb_port[port].device_num].Interface = 0;
BX_USB_THIS hub[0].device[BX_USB_THIS hub[0].usb_port[port].device_num].config = 0;
BX_USB_THIS hub[0].usb_port[port].low_speed =
BX_USB_THIS hub[0].device[BX_USB_THIS hub[0].usb_port[port].device_num].low_speed;
}
if (BX_USB_THIS hub[0].usb_port[port].low_speed) {
BX_USB_THIS hub[0].usb_port[port].line_dminus = 1; // dminus=1 & dplus=0 = low speed (at idle time)
BX_USB_THIS hub[0].usb_port[port].line_dplus = 0; // dminus=0 & dplus=1 = high speed (at idle time)
} else {
BX_USB_THIS hub[0].usb_port[port].line_dminus = 0; // dminus=1 & dplus=0 = low speed (at idle time)
BX_USB_THIS hub[0].usb_port[port].line_dplus = 1; // dminus=0 & dplus=1 = high speed (at idle time)
}
BX_USB_THIS hub[0].usb_port[port].status = 1; //
BX_USB_THIS hub[0].usb_port[port].connect_changed = 1;
BX_USB_THIS hub[0].usb_port[port].able_changed = 1;
BX_USB_THIS hub[0].device[BX_USB_THIS hub[0].usb_port[port].device_num].connect_status = 1;
// if in suspend state, signal resume
if (BX_USB_THIS hub[0].usb_command.suspend) {
BX_USB_THIS hub[0].usb_port[port].resume = 1;
BX_USB_THIS hub[0].usb_status.resume = 1;
if (BX_USB_THIS hub[0].usb_enable.resume) {
BX_USB_THIS hub[0].usb_status.interrupt = 1;
set_irq_level(1);
}
}
} else {
BX_USB_THIS hub[0].usb_port[port].status = 0;
BX_USB_THIS hub[0].usb_port[port].connect_changed = 1;
BX_USB_THIS hub[0].usb_port[port].enabled = 0;
BX_USB_THIS hub[0].usb_port[port].able_changed = 1;
BX_USB_THIS hub[0].usb_port[port].low_speed = 0;
BX_USB_THIS hub[0].usb_port[port].line_dminus = 0; // dminus=1 & dplus=0 = low speed (at idle time)
BX_USB_THIS hub[0].usb_port[port].line_dplus = 0; // dminus=0 & dplus=1 = high speed (at idle time)
if (type == USB_DEV_TYPE_KEYPAD) {
BX_USB_THIS keyboard_connected = 0;
}
}
}
}
}
void bx_pciusb_c::usb_mouse_enq(int delta_x, int delta_y, int delta_z, unsigned button_state)
@ -1837,84 +1193,15 @@ void bx_pciusb_c::usb_mouse_enq(int delta_x, int delta_y, int delta_z, unsigned
bx_bool bx_pciusb_c::usb_key_enq(Bit8u *scan_code)
{
bx_bool is_break_code = 0;
Bit8u our_scan_code[8];
memset(our_scan_code, 0, 8);
int os = 0;
for (int s=0; s<8; s++) {
if ((scan_code[s] == 0xF0) && ((s == 0) || ((s == 1) && (scan_code[0] == 0xE0)))) {
is_break_code = 1;
} else {
if (!(our_scan_code[os++] = scan_code[s])) break;
}
if (BX_USB_THIS keybdev != NULL) {
return keybdev->key_enq(scan_code);
}
// if it is the break code of the saved key, then clear our packet key.
if (is_break_code && !memcmp(BX_USB_THIS saved_key, our_scan_code, 8)) {
memset(BX_USB_THIS saved_key, 0, 8);
memset(BX_USB_THIS key_pad_packet, 0, 8);
return 1; // tell the keyboard handler that we used it, and to return with out processing key
}
// find an attached keyboard device and one that has a conversion table filled.
// we assume the (bochs) user has only one device attached with these specs.
bx_bool fnd = 0;
struct USB_DEVICE *dev;
for (int i=0; i<BX_USB_CONFDEV && !fnd; i++) {
for (int j=0; j<USB_NUM_PORTS && !fnd; j++) {
// is there something plugged in to this port?
if (BX_USB_THIS hub[i].usb_port[j].status) {
if (BX_USB_THIS hub[i].usb_port[j].device_num < 0)
BX_PANIC(("USB internal error at line %i", __LINE__));
dev = &BX_USB_THIS hub[i].device[BX_USB_THIS hub[i].usb_port[j].device_num];
for (int k=0; k<dev->function.device_descr.configs && !fnd; k++) {
for (int l=0; l<dev->function.device_config[k].interfaces && !fnd; l++) {
if ((dev->function.device_config[k].Interface[l].protocol == 1)
&& dev->function.device_config[k].Interface[l].lookup_cnt) {
// Only do this if the keypad is in the configured state
if (dev->state == STATE_CONFIGURED) {
for (int m=0; m<dev->function.device_config[k].Interface[l].lookup_cnt; m++) {
if (!memcmp(dev->function.device_config[k].Interface[l].lookup[m].scan_code, our_scan_code, 8)) {
memcpy(BX_USB_THIS key_pad_packet, dev->function.device_config[k].Interface[l].lookup[m].keypad_packet, 8);
fnd = 1;
break;
}
}
} else {
memset(BX_USB_THIS saved_key, 0, 8);
return 0; // if keypad is not configured, it can't send scan codes.
}
}
}
}
}
}
}
if (!fnd) {
memset(BX_USB_THIS key_pad_packet, 0, 8);
memset(BX_USB_THIS saved_key, 0, 8);
} else {
memcpy(BX_USB_THIS saved_key, our_scan_code, 8);
// print a debug line to the log file
char bx_debug_code[128] = "";
char value[8];
for (unsigned i=0; i<strlen((char *) our_scan_code); i++) {
sprintf(value, "0x%02x", our_scan_code[i]);
if (i) strcat(bx_debug_code, " ");
strcat(bx_debug_code, value);
}
BX_DEBUG(("Re-routing scan code (%s) to USB keypad", bx_debug_code));
}
// tell the keyboard handler whether we used it or not. (0 = no, 1 = yes and keyboard.cc ignores keystoke)
return fnd;
return 0;
}
bx_bool bx_pciusb_c::usb_keyboard_connected()
{
return BX_USB_THIS keyboard_connected;
return (BX_USB_THIS keybdev != NULL);
}
bx_bool bx_pciusb_c::usb_mouse_connected()
@ -2080,7 +1367,7 @@ int usb_device_t::handle_packet(USBPacket *p)
const char *bx_pciusb_c::usb_param_handler(bx_param_string_c *param, int set, const char *val, int maxlen)
{
Bit8u type;
usbdev_type type = USB_DEV_TYPE_NONE;
// handler for USB runtime parameters
if (set) {
@ -2091,8 +1378,6 @@ const char *bx_pciusb_c::usb_param_handler(bx_param_string_c *param, int set, co
if (!strcmp(val, "none") && BX_USB_THIS hub[0].usb_port[0].status) {
if (BX_USB_THIS hub[0].usb_port[0].device != NULL) {
type = BX_USB_THIS hub[0].usb_port[0].device->get_type();
} else {
type = BX_USB_THIS hub[0].device[BX_USB_THIS hub[0].usb_port[0].device_num].dev_type;
}
usb_set_connect_status(0, type, 0);
} else if (strcmp(val, "none") && !BX_USB_THIS hub[0].usb_port[0].status) {
@ -2103,8 +1388,6 @@ const char *bx_pciusb_c::usb_param_handler(bx_param_string_c *param, int set, co
if (!strcmp(val, "none") && BX_USB_THIS hub[0].usb_port[1].status) {
if (BX_USB_THIS hub[0].usb_port[1].device != NULL) {
type = BX_USB_THIS hub[0].usb_port[1].device->get_type();
} else {
type = BX_USB_THIS hub[0].device[BX_USB_THIS hub[0].usb_port[1].device_num].dev_type;
}
usb_set_connect_status(1, type, 0);
} else if (strcmp(val, "none") && !BX_USB_THIS hub[0].usb_port[1].status) {

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: pciusb.h,v 1.24 2007-03-21 18:54:41 vruppert Exp $
// $Id: pciusb.h,v 1.25 2007-03-25 17:37:59 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2004 MandrakeSoft S.A.
@ -42,7 +42,6 @@
#define BX_USB_CONFDEV 1 /* only 1 USB hub currently */
#define USB_NUM_PORTS 2 /* UHCI supports 2 ports per root hub */
#define USB_CUR_DEVS 1 /* old-style devices (keypad only) */
#define USB_TOKEN_IN 0x69
#define USB_TOKEN_OUT 0xE1
@ -129,21 +128,6 @@ struct USBPacket {
int len;
};
// device requests
enum { GET_STATUS=0, CLEAR_FEATURE, SET_FEATURE=3, SET_ADDRESS=5, GET_DESCRIPTOR=6, SET_DESCRIPTOR,
GET_CONFIGURATION, SET_CONFIGURATION,
// interface requests
GET_INTERFACE, SET_INTERFACE,
// standard endpoint requests
SYNCH_FRAME
};
#define SET_FEATURE_TEST_MODE 0 /////////TODO: I don't know yet what this value is to be
#define STATE_DEFAULT 0
#define STATE_ADDRESS 1
#define STATE_CONFIGURED 2
// setup packets
struct REQUEST_PACKET {
Bit8u request_type;
@ -153,12 +137,6 @@ struct REQUEST_PACKET {
Bit16u length;
};
#define KEYPAD_LEN 128
struct KEYPAD {
Bit8u scan_code[8];
Bit8u keypad_packet[8];
};
enum usbdev_type {
USB_DEV_TYPE_NONE=0,
USB_DEV_TYPE_MOUSE,
@ -207,101 +185,6 @@ protected:
} d;
};
// set it to 1 (align on byte) and save so we can pop it
#pragma pack(push, 1)
struct USB_DEVICE {
int dev_type; // our device type
bx_bool connect_status; // is device connected
Bit8u address; // 7 bit address
Bit8u config; // which configuration to use
Bit8u Interface; // which interface to use
Bit8u alt_interface; // which alt interface to use
Bit8u endpt; // which endpt to use
unsigned state; // the state the device is in. DEFAULT, ADDRESS, or CONFIGURED
bx_bool low_speed; // 1 = ls
Bit32u scratch; // 32-bit scratch area
bx_bool in_stall; // is this device in a stall state?
Bit8u stall_once; // some devices stall on the first setup packet after powerup
struct {
Bit8u direction;
Bit8u *in;
Bit8u *out;
Bit16u in_cnt;
Bit16u out_cnt;
unsigned configs; ///// this is the same as configs below??????
struct {
Bit8u len;
Bit8u type;
Bit16u usb_ver;
Bit8u _class;
Bit8u subclass;
Bit8u protocol;
Bit8u max_packet_size;
Bit16u vendorid;
Bit16u productid;
Bit16u device_rel;
Bit8u manuf_indx;
Bit8u prod_indx;
Bit8u serial_indx;
Bit8u configs;
} device_descr;
struct {
Bit8u len;
Bit8u type;
Bit16u tot_len;
Bit8u interfaces;
Bit8u config_val;
Bit8u config_indx;
Bit8u attrbs;
Bit8u max_power;
struct {
Bit8u size;
Bit8u type;
Bit8u interface_num;
Bit8u alternate;
Bit8u num_endpts;
Bit8u iclass;
Bit8u subclass;
Bit8u protocol;
Bit8u str_indx;
struct {
Bit8u size;
Bit8u type;
Bit8u endpt;
Bit8u attrib;
Bit16u max_size;
Bit8u interval;
} endpts[4];
struct {
Bit8u size;
Bit8u type;
Bit16u HID_class;
Bit8u country_code;
Bit8u num_descriptors;
struct {
Bit8u type;
Bit16u len;
Bit8u dev_hid_descript_report[128];
} descriptor[16];
} dev_hid_descript;
int lookup_cnt;
struct KEYPAD lookup[KEYPAD_LEN];
} Interface[4];
} device_config[4];
struct {
Bit8u size;
Bit8u type;
Bit16u langid[3];
} str_descriptor;
struct {
Bit8u size;
Bit8u type;
Bit8u unicode_str[64];
} string[6];
} function; // currently, we only support 1 function
};
#pragma pack(pop)
typedef struct {
Bit32u base_ioaddr;
int timer_index;
@ -430,8 +313,6 @@ typedef struct {
Bit8u pci_conf[256];
Bit8u devfunc;
struct USB_DEVICE device[USB_CUR_DEVS]; // two ports per hub, 127 devices per port (max)
int statusbar_id[2]; // IDs of the status LEDs
} bx_usb_t;
@ -481,17 +362,11 @@ private:
bx_usb_t hub[BX_USB_CONFDEV];
Bit8u global_reset;
Bit8u saved_key[8];
Bit8u key_pad_packet[8];
static void set_irq_level(bx_bool level);
Bit8u *device_buffer;
unsigned set_address_stk;
Bit8u set_address[128];
bx_bool keyboard_connected;
usb_hid_device_t *mousedev;
usb_hid_device_t *keybdev;
USBPacket usb_packet;
@ -501,7 +376,6 @@ private:
static void usb_timer_handler(void *);
void usb_timer(void);
bx_bool DoTransfer(Bit32u address, Bit32u queue_num, struct TD *);
unsigned GetDescriptor(struct USB_DEVICE *, struct REQUEST_PACKET *);
void set_status(struct TD *td, bx_bool stalled, bx_bool data_buffer_error, bx_bool babble,
bx_bool nak, bx_bool crc_time_out, bx_bool bitstuff_error, Bit16u act_len);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: usb_hid.cc,v 1.2 2007-03-24 11:43:41 vruppert Exp $
// $Id: usb_hid.cc,v 1.3 2007-03-25 17:37:59 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2007 Volker Ruppert
@ -26,8 +26,10 @@
// is used to know when we are exporting symbols and when we are importing.
#define BX_PLUGGABLE
#define NO_DEVICE_INCLUDES
#include "iodev.h"
#if BX_SUPPORT_PCI && BX_SUPPORT_PCIUSB
#include "pciusb.h"
#include "usb_hid.h"
#define LOG_THIS
@ -36,9 +38,16 @@
#define GET_REPORT 0xa101
#define GET_IDLE 0xa102
#define GET_PROTOCOL 0xa103
#define SET_REPORT 0x2109
#define SET_IDLE 0x210a
#define SET_PROTOCOL 0x210b
#define KEYPAD_LEN 128
struct KEYPAD {
Bit8u scan_code[8];
Bit8u keypad_packet[8];
};
static const Bit8u bx_mouse_dev_descriptor[] = {
0x12, /* u8 bLength; */
0x01, /* u8 bDescriptorType; Device */
@ -114,6 +123,16 @@ static const Bit8u bx_mouse_config_descriptor[] = {
0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
};
static const Bit8u bx_mouse_hid_report_descriptor[] = {
0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01,
0xA1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03,
0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01,
0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01,
0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x15, 0x81,
0x25, 0x7F, 0x75, 0x08, 0x95, 0x02, 0x81, 0x06,
0xC0, 0xC0,
};
static const Bit8u bx_tablet_config_descriptor[] = {
/* one configuration */
0x09, /* u8 bLength; */
@ -129,17 +148,6 @@ static const Bit8u bx_tablet_config_descriptor[] = {
4..0: resvd */
50, /* u8 MaxPower; */
/* USB 1.1:
* USB 2.0, single TT organization (mandatory):
* one interface, protocol 0
*
* USB 2.0, multiple TT organization (optional):
* two interfaces, protocols 1 (like single TT)
* and 2 (multiple TT mode) ... config is
* sometimes settable
* NOT IMPLEMENTED
*/
/* one interface */
0x09, /* u8 if_bLength; */
0x04, /* u8 if_bDescriptorType; Interface */
@ -169,16 +177,6 @@ static const Bit8u bx_tablet_config_descriptor[] = {
0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
};
static const Bit8u bx_mouse_hid_report_descriptor[] = {
0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01,
0xA1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03,
0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01,
0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01,
0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x15, 0x81,
0x25, 0x7F, 0x75, 0x08, 0x95, 0x02, 0x81, 0x06,
0xC0, 0xC0,
};
static const Bit8u bx_tablet_hid_report_descriptor[] = {
0x05, 0x01, /* Usage Page Generic Desktop */
0x09, 0x01, /* Usage Mouse */
@ -219,14 +217,150 @@ static const Bit8u bx_tablet_hid_report_descriptor[] = {
0xC0, /* End Collection */
};
static const Bit8u bx_keypad_dev_descriptor[] = {
0x12, /* u8 bLength; */
0x01, /* u8 bDescriptorType; Device */
0x10, 0x01, /* u16 bcdUSB; v1.1 */
0x00, /* u8 bDeviceClass; */
0x00, /* u8 bDeviceSubClass; */
0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
0x08, /* u8 bMaxPacketSize0; 8 Bytes */
0xB4, 0x04, /* u16 idVendor; */
0x01, 0x01, /* u16 idProduct; */
0x01, 0x00, /* u16 bcdDevice */
0x03, /* u8 iManufacturer; */
0x02, /* u8 iProduct; */
0x01, /* u8 iSerialNumber; */
0x01 /* u8 bNumConfigurations; */
};
static const Bit8u bx_keypad_config_descriptor[] = {
/* one configuration */
0x09, /* u8 bLength; */
0x02, /* u8 bDescriptorType; Configuration */
0x3B, 0x00, /* u16 wTotalLength; */
0x02, /* u8 bNumInterfaces; (2) */
0x01, /* u8 bConfigurationValue; */
0x04, /* u8 iConfiguration; */
0xa0, /* u8 bmAttributes;
Bit 7: must be set,
6: Self-powered,
5: Remote wakeup,
4..0: resvd */
50, /* u8 MaxPower; */
/* interface #1 of 2 */
0x09, /* u8 if_bLength; */
0x04, /* u8 if_bDescriptorType; Interface */
0x00, /* u8 if_bInterfaceNumber; */
0x00, /* u8 if_bAlternateSetting; */
0x01, /* u8 if_bNumEndpoints; */
0x03, /* u8 if_bInterfaceClass; */
0x01, /* u8 if_bInterfaceSubClass; */
0x01, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
0x05, /* u8 if_iInterface; */
/* HID descriptor */
0x09, /* u8 bLength; */
0x21, /* u8 bDescriptorType; */
0x00, 0x01, /* u16 HID_class */
0x00, /* u8 country_code */
0x01, /* u8 num_descriptors */
0x22, /* u8 type; Report */
65, 0, /* u16 len */
/* one endpoint (status change endpoint) */
0x07, /* u8 ep_bLength; */
0x05, /* u8 ep_bDescriptorType; Endpoint */
0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
0x03, /* u8 ep_bmAttributes; Interrupt */
0x08, 0x00, /* u16 ep_wMaxPacketSize; */
0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
/* interface #2 of 2 */
0x09, /* u8 if_bLength; */
0x04, /* u8 if_bDescriptorType; Interface */
0x01, /* u8 if_bInterfaceNumber; */
0x00, /* u8 if_bAlternateSetting; */
0x01, /* u8 if_bNumEndpoints; */
0x03, /* u8 if_bInterfaceClass; */
0x01, /* u8 if_bInterfaceSubClass; */
0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
0x06, /* u8 if_iInterface; */
/* HID descriptor */
0x09, /* u8 bLength; */
0x21, /* u8 bDescriptorType; */
0x00, 0x01, /* u16 HID_class */
0x00, /* u8 country_code */
0x01, /* u8 num_descriptors */
0x22, /* u8 type; Report */
50, 0, /* u16 len */
/* one endpoint (status change endpoint) */
0x07, /* u8 ep_bLength; */
0x05, /* u8 ep_bDescriptorType; Endpoint */
0x82, /* u8 ep_bEndpointAddress; IN Endpoint 2 */
0x03, /* u8 ep_bmAttributes; Interrupt */
0x08, 0x00, /* u16 ep_wMaxPacketSize; */
0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
};
static const Bit8u bx_keypad_hid_report_descriptor1[] = {
0x05, 0x01, 0x09, 0x06, 0xA1, 0x01, 0x05, 0x07,
0x19, 0xE0, 0x29, 0xE7, 0x15, 0x00, 0x25, 0x01,
0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01,
0x75, 0x08, 0x81, 0x01, 0x95, 0x03, 0x75, 0x01,
0x05, 0x08, 0x19, 0x01, 0x29, 0x03, 0x91, 0x02,
0x95, 0x05, 0x75, 0x01, 0x91, 0x01, 0x95, 0x06,
0x75, 0x08, 0x15, 0x00, 0x26, 0xFF, 0x00, 0x05,
0x07, 0x19, 0x00, 0x2A, 0xFF, 0x00, 0x81, 0x00,
0xC0
};
static const Bit8u bx_keypad_hid_report_descriptor2[] = {
0x05, 0x0C, 0x09, 0x01, 0xA1, 0x01, 0x85, 0x01,
0x19, 0x00, 0x2A, 0x3C, 0x02, 0x15, 0x00, 0x26,
0x3C, 0x02, 0x95, 0x01, 0x75, 0x10, 0x81, 0x00,
0xC0, 0x05, 0x01, 0x09, 0x80, 0xA1, 0x01, 0x85,
0x02, 0x19, 0x81, 0x29, 0x83, 0x25, 0x01, 0x75,
0x01, 0x95, 0x03, 0x81, 0x02, 0x95, 0x05, 0x81,
0x01, 0xC0
};
// this interface has a key conversion table of len = 18
struct KEYPAD keypad_lookup[KEYPAD_LEN] = {
{ { 0x6C, }, { 0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00 } }, // 7
{ { 0x6B, }, { 0x00, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00 } }, // 4
{ { 0x69, }, { 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00 } }, // 1
{ { 0x70, }, { 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00 } }, // 0
{ { 0xE0, 0x4A, }, { 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00 } }, // /
{ { 0x75, }, { 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00 } }, // 8
{ { 0x73, }, { 0x00, 0x00, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00 } }, // 5
{ { 0x72, }, { 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00 } }, // 2
{ { 0x7C, }, { 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00 } }, // *
{ { 0x7D, }, { 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00 } }, // 9
{ { 0x74, }, { 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x00 } }, // 6
{ { 0x7A, }, { 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00 } }, // 3
{ { 0x71, }, { 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00 } }, // -
{ { 0x7B, }, { 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00 } }, // +
{ { 0x79, }, { 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00 } }, // .
{ { 0xE0, 0x5A }, { 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00 } }, // Enter
};
usb_hid_device_t::usb_hid_device_t(usbdev_type type)
{
d.type = type;
d.speed = USB_SPEED_FULL;
d.speed = USB_SPEED_LOW;
if (d.type == USB_DEV_TYPE_MOUSE) {
strcpy(d.devname, "BOCHS USB Mouse");
strcpy(d.devname, "USB Mouse");
} else if (d.type == USB_DEV_TYPE_TABLET) {
strcpy(d.devname, "BOCHS USB Tablet");
strcpy(d.devname, "USB Tablet");
} else if (d.type == USB_DEV_TYPE_KEYPAD) {
strcpy(d.devname, "USB/PS2 Keypad");
}
d.connected = 1;
memset((void*)&s, 0, sizeof(s));
@ -284,6 +418,10 @@ int usb_hid_device_t::handle_control(int request, int value, int index, int leng
memcpy(data, bx_mouse_dev_descriptor,
sizeof(bx_mouse_dev_descriptor));
ret = sizeof(bx_mouse_dev_descriptor);
} else if (d.type == USB_DEV_TYPE_KEYPAD) {
memcpy(data, bx_keypad_dev_descriptor,
sizeof(bx_keypad_dev_descriptor));
ret = sizeof(bx_keypad_dev_descriptor);
} else {
goto fail;
}
@ -291,15 +429,19 @@ int usb_hid_device_t::handle_control(int request, int value, int index, int leng
case USB_DT_CONFIG:
if (d.type == USB_DEV_TYPE_MOUSE) {
memcpy(data, bx_mouse_config_descriptor,
sizeof(bx_mouse_config_descriptor));
sizeof(bx_mouse_config_descriptor));
ret = sizeof(bx_mouse_config_descriptor);
} else if (d.type == USB_DEV_TYPE_TABLET) {
memcpy(data, bx_tablet_config_descriptor,
sizeof(bx_tablet_config_descriptor));
sizeof(bx_tablet_config_descriptor));
ret = sizeof(bx_tablet_config_descriptor);
} else {
} else if (d.type == USB_DEV_TYPE_KEYPAD) {
memcpy(data, bx_keypad_config_descriptor,
sizeof(bx_keypad_config_descriptor));
ret = sizeof(bx_keypad_config_descriptor);
} else {
goto fail;
}
}
break;
case USB_DT_STRING:
switch(value & 0xff) {
@ -334,10 +476,12 @@ int usb_hid_device_t::handle_control(int request, int value, int index, int leng
ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
break;
default:
BX_ERROR(("USB HID handle_control: unknown descriptor 0x%02x", value & 0xff));
goto fail;
}
break;
default:
BX_ERROR(("USB HID handle_control: unknown descriptor 0x%02x", value & 0xff));
goto fail;
}
break;
@ -367,11 +511,22 @@ int usb_hid_device_t::handle_control(int request, int value, int index, int leng
memcpy(data, bx_tablet_hid_report_descriptor,
sizeof(bx_tablet_hid_report_descriptor));
ret = sizeof(bx_tablet_hid_report_descriptor);
} else if (d.type == USB_DEV_TYPE_KEYPAD) {
if (index == 0) {
memcpy(data, bx_keypad_hid_report_descriptor1,
sizeof(bx_keypad_hid_report_descriptor1));
ret = sizeof(bx_keypad_hid_report_descriptor1);
} else {
memcpy(data, bx_keypad_hid_report_descriptor2,
sizeof(bx_keypad_hid_report_descriptor2));
ret = sizeof(bx_keypad_hid_report_descriptor2);
}
} else {
goto fail;
}
break;
}
break;
default:
BX_ERROR(("USB HID handle_control: unknown HID descriptor 0x%02x", value & 0xff));
goto fail;
}
break;
@ -379,15 +534,26 @@ int usb_hid_device_t::handle_control(int request, int value, int index, int leng
if ((d.type == USB_DEV_TYPE_MOUSE) ||
(d.type == USB_DEV_TYPE_TABLET)) {
ret = mouse_poll(data, length);
} else if (d.type == USB_DEV_TYPE_KEYPAD) {
ret = keypad_poll(data, length);
} else {
goto fail;
}
break;
case SET_REPORT:
if ((d.type == USB_DEV_TYPE_KEYPAD) && (value = 0x200)) {
BX_INFO(("keypad NUMLOCK %s", (data[0] & 0x01) ? "on" : "off"));
ret = 0;
} else {
goto fail;
}
break;
case SET_IDLE:
case SET_PROTOCOL:
ret = 0;
break;
default:
BX_ERROR(("USB HID handle_control: unknown request"));
BX_ERROR(("USB HID handle_control: unknown request 0x%04x", request));
fail:
ret = USB_RET_STALL;
break;
@ -405,6 +571,14 @@ int usb_hid_device_t::handle_data(USBPacket *p)
if ((d.type == USB_DEV_TYPE_MOUSE) ||
(d.type == USB_DEV_TYPE_TABLET)) {
ret = mouse_poll(p->data, p->len);
} else if (d.type == USB_DEV_TYPE_KEYPAD) {
ret = keypad_poll(p->data, p->len);
} else {
goto fail;
}
} else if (p->devep == 2) {
if (d.type == USB_DEV_TYPE_KEYPAD) {
ret = mouse_poll(p->data, p->len);
} else {
goto fail;
}
@ -413,6 +587,7 @@ int usb_hid_device_t::handle_data(USBPacket *p)
}
break;
case USB_TOKEN_OUT:
BX_ERROR(("USB HID handle_data: unexpected pid TOKEN_OUT"));
default:
fail:
ret = USB_RET_STALL;
@ -425,7 +600,8 @@ int usb_hid_device_t::mouse_poll(Bit8u *buf, int len)
{
int l = 0;
if (d.type == USB_DEV_TYPE_MOUSE) {
if ((d.type == USB_DEV_TYPE_MOUSE) ||
(d.type == USB_DEV_TYPE_KEYPAD)) {
if (!s.mouse_x && !s.mouse_y) {
// if there's no new movement, handle delayed one
mouse_enq(0, 0, s.mouse_z, s.b_state);
@ -508,4 +684,66 @@ void usb_hid_device_t::mouse_enq(int delta_x, int delta_y, int delta_z, unsigned
s.b_state = (Bit8u) button_state;
}
int usb_hid_device_t::keypad_poll(Bit8u *buf, int len)
{
int l = 0;
if (d.type == USB_DEV_TYPE_KEYPAD) {
memcpy(buf, s.key_pad_packet, len);
l = 8;
}
return l;
}
bx_bool usb_hid_device_t::key_enq(Bit8u *scan_code)
{
bx_bool is_break_code = 0;
Bit8u our_scan_code[8];
memset(our_scan_code, 0, 8);
int os = 0;
for (int sc=0; sc<8; sc++) {
if ((scan_code[sc] == 0xF0) && ((sc == 0) || ((sc == 1) && (scan_code[0] == 0xE0)))) {
is_break_code = 1;
} else {
if (!(our_scan_code[os++] = scan_code[sc])) break;
}
}
// if it is the break code of the saved key, then clear our packet key.
if (is_break_code && !memcmp(s.saved_key, our_scan_code, 8)) {
memset(s.saved_key, 0, 8);
memset(s.key_pad_packet, 0, 8);
return 1; // tell the keyboard handler that we used it, and to return with out processing key
}
bx_bool fnd = 0;
for (int m = 0; m < 18; m++) {
if (!memcmp(keypad_lookup[m].scan_code, our_scan_code, 8)) {
memcpy(s.key_pad_packet, keypad_lookup[m].keypad_packet, 8);
fnd = 1;
break;
}
}
if (!fnd) {
memset(s.key_pad_packet, 0, 8);
memset(s.saved_key, 0, 8);
} else {
memcpy(s.saved_key, our_scan_code, 8);
// print a debug line to the log file
char bx_debug_code[128] = "";
char value[8];
for (unsigned i=0; i<strlen((char *) our_scan_code); i++) {
sprintf(value, "0x%02x", our_scan_code[i]);
if (i) strcat(bx_debug_code, " ");
strcat(bx_debug_code, value);
}
BX_DEBUG(("Re-routing scan code (%s) to USB keypad", bx_debug_code));
}
// tell the keyboard handler whether we used it or not. (0 = no, 1 = yes and keyboard.cc ignores keystoke)
return fnd;
}
#endif // BX_SUPPORT_PCI && BX_SUPPORT_PCIUSB

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: usb_hid.h,v 1.2 2007-03-24 11:43:41 vruppert Exp $
// $Id: usb_hid.h,v 1.3 2007-03-25 17:37:59 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2007 Volker Ruppert
@ -33,8 +33,10 @@ public:
virtual int handle_control(int request, int value, int index, int length, Bit8u *data);
virtual int handle_data(USBPacket *p);
void mouse_enq(int delta_x, int delta_y, int delta_z, unsigned button_state);
bx_bool key_enq(Bit8u *scan_code);
protected:
int mouse_poll(Bit8u *buf, int len);
int keypad_poll(Bit8u *buf, int len);
private:
struct {
@ -45,6 +47,8 @@ private:
Bit16s mouse_y;
Bit8s mouse_z;
Bit8u b_state;
Bit8u saved_key[8];
Bit8u key_pad_packet[8];
} s;
};

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: usb_msd.cc,v 1.2 2007-03-24 11:43:41 vruppert Exp $
// $Id: usb_msd.cc,v 1.3 2007-03-25 17:37:59 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2007 Volker Ruppert
@ -26,8 +26,10 @@
// is used to know when we are exporting symbols and when we are importing.
#define BX_PLUGGABLE
#define NO_DEVICE_INCLUDES
#include "iodev.h"
#if BX_SUPPORT_PCI && BX_SUPPORT_PCIUSB
#include "pciusb.h"
#include "hdimage.h"
#include "scsi_device.h"
#include "usb_msd.h"
@ -226,6 +228,7 @@ int usb_msd_device_t::handle_control(int request, int value, int index, int leng
ret = set_usb_string(data, "1");
break;
default:
BX_ERROR(("USB MSD handle_control: unknown descriptor 0x%02x", value & 0xff));
goto fail;
}
break;
@ -272,7 +275,7 @@ int usb_msd_device_t::handle_control(int request, int value, int index, int leng
ret = 1;
break;
default:
BX_ERROR(("USB MSD handle_control: unknown request"));
BX_ERROR(("USB MSD handle_control: unknown request 0x%04x", request));
fail:
ret = USB_RET_STALL;
break;