- 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:
parent
58ba0172bb
commit
324250ccb4
File diff suppressed because it is too large
Load Diff
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user