#include #include "equates.h" #include "usb.h" unsigned char* responseAddress; //used in sending back control request responses int responseBytesRemaining; //used in sending back control request responses int USBState; //used in sending back control request responses int newAddressReceived; //used in setting the address from the interrupt extern int wMaxPacketSize0; //Callback functions void HandleConnected(); void HandleSetAddress(int address); void HandleHubSetFeature(int feature, int index); void HandleHubClearFeature(int feature, int index); void HandleHubGetStatus(unsigned char* data, int index); int HandleDescriptorRequest(int wValue, int wLength, unsigned char** descAddress); int HandleHubDescriptorRequest(int wLength, unsigned char** descAddress); void HandleIncomingData(); void HandleUnknownControlRequest(int bmRequestType, int bRequest); void ReadPayloadData(unsigned char* buffer, unsigned int count); void ClosePayloadData(); void HandleUSBInterrupt() { unsigned char status1 = *USB_INT_STATUS1_ADDR; unsigned char status2 = *USB_INT_STATUS2_ADDR; if ((status1 & 0x04) == 0) { //Need to check offset 0x56 for what happened if ((status2 & 0x40) != 0) { //Handle USB B-cable connect USBState = 0; *USB_DEVICE_ADDRESS = 0; newAddressReceived = 0; HandleConnected(); USB_PeripheralInitialize(); OSTimerRestart(2); }else if ((status2 && 0x80) != 0) { //Handle USB B-cable disconnect USB_PeripheralKill(); OSTimerRestart(2); } else { //Unknown 0x56 event } } else if ((status1 & 0x10) == 0) { //Data waiting (or something else involving data) unsigned char outgoingDataSuccess = *USB_OUTGOING_DATA_SUCCESS_ADDR & 0xFF; unsigned char incomingDataReady = *USB_INCOMING_DATA_READY_ADDR & 0xFF; unsigned char dataStatus = *USB_DATA_STATUS_ADDR & 0xFF; unsigned char mode = *USB_MODE_ADDR & 0xFF; if (incomingDataReady & 0xFE) { //Handle incoming bulk/interrupt data HandleIncomingData(); } else { if ((mode & 0x04) == 1) { //Calculator is in host mode, handle data waiting accordingly USB_HandleHostDataWaiting(); OSTimerRestart(2); } else { //Calculator is in peripheral mode, handle data waiting accordingly if (dataStatus & 0x04) { //Error indicates control pipe is not enabled for output, so enable it *USB_INT_ENABLE_ADDR = (char)1; *USB_DATA_OUT_EN_ADDR |= (char)1; } else if (outgoingDataSuccess & 0x01) { *USB_SELECTED_ENDPOINT_ADDR = 0x00; char outgoingValue = *USB_OUTGOING_CMD_ADDR; if (!(outgoingValue & 0x04)) { if (outgoingValue & 0x10) { //I'm not exactly sure what this is... *USB_OUTGOING_CMD_ADDR = (outgoingValue | 0x80); } //If we're not busy doing something else... if (USBState == 0x00) { if (outgoingValue & 0x01) { //Receive and handle this control packet unsigned char controlPacket[8]; unsigned int i; for (i = 0; i < 8; i++) controlPacket[i] = (*USB_ENDPOINT0_DATA_ADDR & 0xFF); USB_HandleControlPacket(controlPacket); } else { if (newAddressReceived > 0) { //So apparently now we set the function address newAddressReceived = 0; USB_SetFunctionAddress(*USB_DEVICE_ADDRESS); HandleSetAddress(*USB_DEVICE_ADDRESS); } } } //See if we need to send more data for a control request's response if (USBState == 1) { //We do, so get to it unsigned int count = (responseBytesRemaining > wMaxPacketSize0)? wMaxPacketSize0 : responseBytesRemaining; unsigned int i; //Buffer the data unsigned char dataBuffer[count]; for (i = 0; i < count; i++) dataBuffer[i] = responseAddress[i]; ReadPayloadData(dataBuffer, count); //Send the data for (i = 0; i < count; i++) { *USB_ENDPOINT0_DATA_ADDR = dataBuffer[i]; } responseAddress += count; responseBytesRemaining -= count; if (responseBytesRemaining > 0) { //If there's still data to send, send the continuation command *USB_SELECTED_ENDPOINT_ADDR = (char)0x00; *USB_OUTGOING_CMD_ADDR |= (char)0x02; } else { USB_FinishControlOutput(); USBState = 0; ClosePayloadData(); } } } else { //I'm not exactly sure what this is... *USB_OUTGOING_CMD_ADDR = (outgoingValue & 0xFB); } } } } OSTimerRestart(2); } else { //Unknown USB event } } void USB_HandleControlPacket(unsigned char* packet) { int bmRequestType = packet[0] & 0xFF; int bRequest = packet[1]; int wValue = (packet[3] << 8) | (packet[2] & 0xFF); int wIndex = (packet[5] << 8) | (packet[4] & 0xFF); int wLength = (packet[7] << 8) | (packet[6] & 0xFF); switch(bmRequestType) { case 0xA3: case 0x23: { switch(bRequest) { case 0x03: //hub set feature { USB_FinishControlRequest(); HandleHubSetFeature(wValue, wIndex); break; } case 0x01: //hub clear feature { USB_FinishControlRequest(); HandleHubClearFeature(wValue, wIndex); break; } case 0x00: //hub get status { unsigned char data[4]; HandleHubGetStatus(data, wIndex); USB_StartControlOutput(); USB_SendControlData(data, 4); USB_FinishControlOutput(); break; } } break; } case 0x00: { switch(bRequest) { case 0x05: //set address { USB_FinishControlRequest(); *USB_DEVICE_ADDRESS = (wValue & 0xFF); newAddressReceived = 1; HandleSetAddress(*USB_DEVICE_ADDRESS); break; } case 0x09: //set configuration { USB_FinishControlRequest(); } } break; } case 0x01: { switch(bRequest) { case 0x0B: //set interface { USB_FinishControlRequest(); break; } } break; } case 0x80: { switch(bRequest) { case 0x06: //get descriptor { responseBytesRemaining = HandleDescriptorRequest(wValue, wLength, &responseAddress); USB_StartControlOutput(); USBState = 1; //Is this a device descriptor? if ((wValue >> 8) == 1) { //Yes, so get the max packet size for this device descriptor wMaxPacketSize0 = responseAddress[7]; } } } break; } case 0xA0: { switch(bRequest) { case 0x06: //get class descriptor { responseBytesRemaining = HandleHubDescriptorRequest(wLength, &responseAddress); USB_StartControlOutput(); USBState = 1; } } break; } default: { HandleUnknownControlRequest(bmRequestType, bRequest); break; } } }