Files
super6502/sw/usb/HID.c
Byron Lathi 5d8c4aab44 Add USB code
Adds the usb code that we got in ECE 385. It will not work now, and
parts that involve the timer are disabled. It does compile though, with
a few warnings.

The goal will be to add USB MSD support, which is not actually given to
us so I will have to do myself or find some other code to base it off
of.
2022-03-10 16:15:08 -06:00

243 lines
9.2 KiB
C

/* HID class support functions */
#include <stdio.h>
#include "project_config.h"
BYTE bigbuf[256]; //256 bytes
extern DEV_RECORD devtable[];
HID_DEVICE hid_device = { { 0 } };
EP_RECORD hid_ep[2] = { { 0 } }; //HID class endpoints, 1 control, 1 interrupt-IN
//the third endpoint is not implemented
/* HID Mouse probe. Called from USB state machine. */
/* assumes configuration length is less than 256 bytes */
/* looks for Class:03, Subclass: 01, Protocol: 02 in interface descriptor */
/* sets mouse in boot protocol */
/* assumes single configuration and interface configuration 0 */
BOOL HIDMProbe(BYTE addr, DWORD flags) {
BYTE tmpbyte;
BYTE rcode;
BYTE confvalue;
WORD total_length;
USB_DESCR* data_ptr = (USB_DESCR *) &bigbuf;
BYTE* byte_ptr = bigbuf;
(void) flags;
rcode = XferGetConfDescr(addr, 0, CONF_DESCR_LEN, 0, bigbuf); //get configuration descriptor
if (rcode) { //error handling
//printf("unable to get configuration descriptor");
return (FALSE);
}
if (data_ptr->descr.config.wTotalLength > 256) {
total_length = 256;
} else {
total_length = data_ptr->descr.config.wTotalLength;
}
rcode = XferGetConfDescr(addr, 0, total_length, 0, bigbuf); //get the whole configuration
if (rcode) { //error handling
//printf("unable to get configuration");
return (FALSE);
}
confvalue = data_ptr->descr.config.bConfigurationValue;
//printf("checking configuration value (length: %d): ",
// data_ptr->descr.config.wTotalLength);
//for (int i = 0; i < data_ptr->descr.config.wTotalLength; i++) {
//printf("%x ", (unsigned char) (bigbuf[i] & 0xff));
//}
while (byte_ptr < bigbuf + total_length) {
if (data_ptr->descr.config.bDescriptorType != USB_DESCRIPTOR_INTERFACE) {
byte_ptr = byte_ptr + data_ptr->descr.config.bLength;
data_ptr = (USB_DESCR*) byte_ptr;
} // if( data_ptr->descr.config.bDescriptorType != USB_DESCRIPTOR_INTERFACE
else {
//printf("starting interface parsing at byte location %d\n",
// data_ptr->descr.config.bLength);
BYTE class = data_ptr->descr.interface.bInterfaceClass;
BYTE subclass = data_ptr->descr.interface.bInterfaceSubClass;
BYTE protocol = data_ptr->descr.interface.bInterfaceProtocol;
//printf("class %x, subclass %x, protocol %x,\n", class, subclass,
// protocol);
//interface descriptor
if (class == HID_INTF && subclass == BOOT_INTF_SUBCLASS
&& protocol == HID_PROTOCOL_MOUSE) {
//detected a mouse
devtable[addr].devclass = HID_M; //device class
tmpbyte = devtable[addr].epinfo->MaxPktSize;
HID_init(); //initialize data structures
devtable[addr].epinfo = hid_ep; //switch endpoint information structure
devtable[addr].epinfo[0].MaxPktSize = tmpbyte;
hid_device.interface =
data_ptr->descr.interface.bInterfaceNumber;
hid_device.addr = addr;
byte_ptr = byte_ptr + data_ptr->descr.config.bLength;
data_ptr = (USB_DESCR*) byte_ptr;
while (byte_ptr < bigbuf + total_length) {
if (data_ptr->descr.config.bDescriptorType
!= USB_DESCRIPTOR_ENDPOINT) { //skip to endpoint descriptor
byte_ptr = byte_ptr + data_ptr->descr.config.bLength;
data_ptr = (USB_DESCR*) byte_ptr;
} else {
/* fill endpoint information structure */
devtable[addr].epinfo[1].epAddr =
data_ptr->descr.endpoint.bEndpointAddress;
devtable[addr].epinfo[1].Attr =
data_ptr->descr.endpoint.bmAttributes;
devtable[addr].epinfo[1].MaxPktSize =
data_ptr->descr.endpoint.wMaxPacketSize;
devtable[addr].epinfo[1].Interval =
data_ptr->descr.endpoint.bInterval;
// devtable[ addr ].epinfo[ 1 ].rcvToggle = bmRCVTOG0;
/* configure device */
rcode = XferSetConf(addr, 0, confvalue); //set configuration
if (rcode) { //error handling
return (FALSE);
}
rcode = XferSetProto(addr, 0, hid_device.interface,
BOOT_PROTOCOL);
if (rcode) { //error handling
return (FALSE);
} else {
return (TRUE);
}
}
} //while( byte_ptr....
} //if (Class matches
else { //if class don't match; die on first interface. Not really correct
return (FALSE);
}
} //else if( data_ptr->
} // while( byte_ptr < &buf + total_length
return (FALSE);
}
/* HID Keyboard probe. Called from USB state machine. */
/* assumes configuration length is less than 256 bytes */
/* looks for Class:03, Subclass: 01, Protocol: 01 in interface descriptor */
/* sets keyboard in boot protocol */
/* assumes single configuration, single endpoint, and interface configuration 0 */
BOOL HIDKProbe(BYTE addr, DWORD flags) {
BYTE tmpbyte;
BYTE rcode;
BYTE confvalue;
WORD total_length;
USB_DESCR* data_ptr = (USB_DESCR *) &bigbuf;
BYTE* byte_ptr = bigbuf;
(void) flags;
rcode = XferGetConfDescr(addr, 0, CONF_DESCR_LEN, 0, bigbuf); //get configuration descriptor
if (rcode) { //error handling
return (FALSE);
}
if (data_ptr->descr.config.wTotalLength > 256) {
total_length = 256;
} else {
total_length = data_ptr->descr.config.wTotalLength;
}
rcode = XferGetConfDescr(addr, 0, total_length, 0, bigbuf); //get the whole configuration
if (rcode) { //error handling
return (FALSE);
}
confvalue = data_ptr->descr.config.bConfigurationValue; //save configuration value to use later
while (byte_ptr < bigbuf + total_length) { //parse configuration
if (data_ptr->descr.config.bDescriptorType != USB_DESCRIPTOR_INTERFACE) { //skip to the next descriptor
byte_ptr = byte_ptr + data_ptr->descr.config.bLength;
data_ptr = (USB_DESCR*) byte_ptr;
} // if( data_ptr->descr.config.bDescriptorType != USB_DESCRIPTOR_INTERFACE
else {
//printf("starting interface parsing at byte location %d\n",
// data_ptr->descr.config.bLength);
BYTE class = data_ptr->descr.interface.bInterfaceClass;
BYTE subclass = data_ptr->descr.interface.bInterfaceSubClass;
BYTE protocol = data_ptr->descr.interface.bInterfaceProtocol;
//printf("class %x, subclass %x, protocol %x,\n", class, subclass,
// protocol);
//interface descriptor
if (class == HID_INTF && subclass == BOOT_INTF_SUBCLASS
&& protocol == HID_PROTOCOL_KEYBOARD) {
//detected a keyboard
devtable[addr].devclass = HID_K; //fill device class
tmpbyte = devtable[addr].epinfo->MaxPktSize; //save max.packet size
HID_init(); //initialize data structures
devtable[addr].epinfo = hid_ep; //switch endpoint information structure
devtable[addr].epinfo[0].MaxPktSize = tmpbyte; //fill in max.packet size
hid_device.interface =
data_ptr->descr.interface.bInterfaceNumber; //fill in interface number to be used in HID requests
hid_device.addr = addr; //fill in address
byte_ptr = byte_ptr + data_ptr->descr.config.bLength; //skip to the next descriptor
data_ptr = (USB_DESCR*) byte_ptr;
while (byte_ptr < bigbuf + total_length) {
if (data_ptr->descr.config.bDescriptorType
!= USB_DESCRIPTOR_ENDPOINT) { //skip to endpoint descriptor
byte_ptr = byte_ptr + data_ptr->descr.config.bLength;
data_ptr = (USB_DESCR*) byte_ptr;
} else {
/* fill endpoint information structure */
devtable[addr].epinfo[1].epAddr =
data_ptr->descr.endpoint.bEndpointAddress;
devtable[addr].epinfo[1].Attr =
data_ptr->descr.endpoint.bmAttributes;
devtable[addr].epinfo[1].MaxPktSize =
data_ptr->descr.endpoint.wMaxPacketSize;
devtable[addr].epinfo[1].Interval =
data_ptr->descr.endpoint.bInterval;
/* configure device */
rcode = XferSetConf(addr, 0, confvalue); //set configuration
if (rcode) { //error handling
return (FALSE);
}
rcode = XferSetProto(addr, 0, hid_device.interface,
BOOT_PROTOCOL);
if (rcode) { //error handling
return (FALSE);
} else {
return (TRUE);
}
}
} //while( byte_ptr....
} //if (Class matches
else { //if class don't match; stop processing after first interface. Not really correct
return (FALSE);
}
} //else if( data_ptr->
} // while( byte_ptr < &buf + total_length
return (FALSE);
}
/* HID data structures initialization */
void HID_init(void) {
hid_ep[1].sndToggle = bmSNDTOG0;
hid_ep[1].rcvToggle = bmRCVTOG0;
}
/* poll boot mouse */
BYTE mousePoll(BOOT_MOUSE_REPORT* buf) {
BYTE rcode;
MAXreg_wr( rPERADDR, hid_device.addr); //set peripheral address
rcode = XferInTransfer(hid_device.addr, 1, 8, (BYTE*) buf,
devtable[hid_device.addr].epinfo[1].MaxPktSize);
return (rcode);
}
/* poll boot keyboard */
BYTE kbdPoll(BOOT_KBD_REPORT* buf) {
BYTE rcode;
MAXreg_wr( rPERADDR, hid_device.addr); //set peripheral address
rcode = XferInTransfer(hid_device.addr, 1, 8, (BYTE*) buf,
devtable[hid_device.addr].epinfo[1].MaxPktSize);
return (rcode);
}
BOOL HIDMEventHandler(BYTE address, BYTE event, void *data, DWORD size) {
(void) address;
(void) event;
(void) size;
(void) data;
return (FALSE);
}
BOOL HIDKEventHandler(BYTE address, BYTE event, void *data, DWORD size) {
(void) address;
(void) event;
(void) size;
(void) data;
return (FALSE);
}