/* -*- c++ -*- */\r
-\r
/*-----------------------------------------------------------------------------\r
-\r
* Common USB code for FX2\r
-\r
*-----------------------------------------------------------------------------\r
-\r
* Code taken from USRP2 firmware (GNU Radio Project), version 3.0.2,\r
-\r
* Copyright 2003 Free Software Foundation, Inc.\r
-\r
*-----------------------------------------------------------------------------\r
-\r
* This code is part of usbjtag. usbjtag is free software; you can redistribute\r
-\r
* it and/or modify it under the terms of the GNU General Public License as\r
-\r
* published by the Free Software Foundation; either version 2 of the License,\r
-\r
* or (at your option) any later version. usbjtag is distributed in the hope\r
-\r
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied\r
-\r
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-\r
* GNU General Public License for more details. You should have received a\r
-\r
* copy of the GNU General Public License along with this program in the file\r
-\r
* COPYING; if not, write to the Free Software Foundation, Inc., 51 Franklin\r
-\r
* St, Fifth Floor, Boston, MA 02110-1301 USA\r
-\r
*-----------------------------------------------------------------------------\r
-\r
*/\r
\r
-\r
-\r
#include "usb_common.h"\r
-\r
#include "fx2regs.h"\r
-\r
#include "syncdelay.h"\r
-\r
#include "fx2utils.h"\r
-\r
#include "isr.h"\r
-\r
#include "usb_descriptors.h"\r
-\r
#include "usb_requests.h"\r
\r
-\r
-\r
extern xdata char str0[];\r
-\r
extern xdata char str1[];\r
-\r
extern xdata char str2[];\r
-\r
extern xdata char str3[];\r
-\r
extern xdata char str4[];\r
-\r
extern xdata char str5[];\r
\r
-\r
-\r
volatile bit _usb_got_SUDAV;\r
\r
-\r
-\r
unsigned char _usb_config = 0;\r
-\r
unsigned char _usb_alt_setting = 0; // FIXME really 1/interface\r
\r
-\r
-\r
xdata unsigned char *current_device_descr;\r
-\r
xdata unsigned char *current_devqual_descr;\r
-\r
xdata unsigned char *current_config_descr;\r
-\r
xdata unsigned char *other_config_descr;\r
\r
-\r
-\r
static void\r
-\r
setup_descriptors (void)\r
-\r
{\r
-\r
if (USBCS & bmHSM){ // high speed mode\r
-\r
current_device_descr = high_speed_device_descr;\r
-\r
current_devqual_descr = high_speed_devqual_descr;\r
-\r
current_config_descr = high_speed_config_descr;\r
-\r
other_config_descr = full_speed_config_descr;\r
-\r
EP8AUTOINLENH = 0x02; SYNCDELAY; // Size in bytes of the IN data automatically commited (512 bytes here)\r
-\r
EP8AUTOINLENL = 0x00; SYNCDELAY; // Can use signal PKTEND if you want to commit a shorter packet\r
-\r
}\r
-\r
else {\r
-\r
current_device_descr = full_speed_device_descr;\r
-\r
current_devqual_descr = full_speed_devqual_descr;\r
-\r
current_config_descr = full_speed_config_descr;\r
-\r
other_config_descr = high_speed_config_descr;\r
-\r
EP8AUTOINLENH = 0x00; SYNCDELAY; // Size in bytes of the IN data automatically commited (64 bytes here)\r
-\r
EP8AUTOINLENL = 0x40; SYNCDELAY; // Can use signal PKTEND if you want to commit a shorter packet\r
-\r
}\r
\r
-\r
-\r
// whack the type fields\r
-\r
// FIXME, may not be required.\r
-\r
// current_config_descr[1] = DT_CONFIG;\r
-\r
// other_config_descr[1] = DT_OTHER_SPEED;\r
-\r
}\r
\r
-\r
-\r
static void\r
-\r
isr_SUDAV (void) interrupt\r
-\r
{\r
-\r
clear_usb_irq ();\r
-\r
_usb_got_SUDAV = 1;\r
-\r
}\r
\r
-\r
-\r
static void\r
-\r
isr_USBRESET (void) interrupt\r
-\r
{\r
-\r
clear_usb_irq ();\r
-\r
setup_descriptors ();\r
-\r
}\r
\r
-\r
-\r
static void\r
-\r
isr_HIGHSPEED (void) interrupt\r
-\r
{\r
-\r
clear_usb_irq ();\r
-\r
setup_descriptors ();\r
-\r
}\r
\r
-\r
-\r
void\r
-\r
usb_install_handlers (void)\r
-\r
{\r
-\r
setup_descriptors (); // ensure that they're set before use\r
\r
-\r
-\r
hook_uv (UV_SUDAV, (unsigned short) isr_SUDAV);\r
-\r
hook_uv (UV_USBRESET, (unsigned short) isr_USBRESET);\r
-\r
hook_uv (UV_HIGHSPEED, (unsigned short) isr_HIGHSPEED);\r
\r
-\r
-\r
USBIE = bmSUDAV | bmURES | bmHSGRANT;\r
-\r
}\r
\r
-\r
-\r
// On the FX2 the only plausible endpoints are 0, 1, 2, 4, 6, 8\r
-\r
// This doesn't check to see that they're enabled\r
\r
-\r
-\r
unsigned char\r
-\r
plausible_endpoint (unsigned char ep)\r
-\r
{\r
-\r
ep &= ~0x80; // ignore direction bit\r
\r
-\r
-\r
if (ep > 8)\r
-\r
return 0;\r
\r
-\r
-\r
if (ep == 1)\r
-\r
return 1;\r
\r
-\r
-\r
return (ep & 0x1) == 0; // must be even\r
-\r
}\r
\r
-\r
-\r
// return pointer to control and status register for endpoint.\r
-\r
// only called with plausible_endpoints\r
\r
-\r
-\r
xdata volatile unsigned char *\r
-\r
epcs (unsigned char ep)\r
-\r
{\r
-\r
if (ep == 0x01) // ep1 has different in and out CS regs\r
-\r
return EP1OUTCS;\r
\r
-\r
-\r
if (ep == 0x81)\r
-\r
return EP1INCS;\r
\r
-\r
-\r
ep &= ~0x80; // ignore direction bit\r
\r
-\r
-\r
if (ep == 0x00) // ep0\r
-\r
return EP0CS;\r
\r
-\r
-\r
return EP2CS + (ep >> 1); // 2, 4, 6, 8 are consecutive\r
-\r
}\r
\r
-\r
-\r
void\r
-\r
usb_handle_setup_packet (void)\r
-\r
{\r
-\r
_usb_got_SUDAV = 0;\r
\r
-\r
-\r
// handle the standard requests...\r
\r
-\r
-\r
switch (bRequestType & bmRT_TYPE_MASK){\r
\r
-\r
-\r
case bmRT_TYPE_CLASS:\r
-\r
case bmRT_TYPE_RESERVED:\r
-\r
fx2_stall_ep0 (); // we don't handle these. indicate error\r
-\r
break;\r
-\r
\r
-\r
case bmRT_TYPE_VENDOR:\r
-\r
// call the application code.\r
-\r
// If it handles the command it returns non-zero\r
\r
-\r
-\r
if (!app_vendor_cmd ()) \r
-\r
fx2_stall_ep0 ();\r
-\r
break;\r
\r
-\r
-\r
case bmRT_TYPE_STD:\r
-\r
// these are the standard requests...\r
\r
-\r
-\r
if ((bRequestType & bmRT_DIR_MASK) == bmRT_DIR_IN){\r
\r
-\r
-\r
////////////////////////////////////\r
-\r
// handle the IN requests\r
-\r
////////////////////////////////////\r
\r
-\r
-\r
switch (bRequest){\r
\r
-\r
-\r
case RQ_GET_CONFIG:\r
-\r
EP0BUF[0] = _usb_config; // FIXME app should handle\r
-\r
EP0BCH = 0;\r
-\r
EP0BCL = 1;\r
-\r
break;\r
-\r
\r
-\r
// --------------------------------\r
\r
-\r
-\r
case RQ_GET_INTERFACE:\r
-\r
EP0BUF[0] = _usb_alt_setting; // FIXME app should handle\r
-\r
EP0BCH = 0;\r
-\r
EP0BCL = 1;\r
-\r
break;\r
\r
-\r
-\r
// --------------------------------\r
\r
-\r
-\r
case RQ_GET_DESCR:\r
-\r
switch (wValueH){\r
\r
-\r
-\r
case DT_DEVICE:\r
-\r
SUDPTRH = MSB (current_device_descr);\r
-\r
SUDPTRL = LSB (current_device_descr);\r
-\r
break;\r
-\r
\r
-\r
case DT_DEVQUAL:\r
-\r
SUDPTRH = MSB (current_devqual_descr);\r
-\r
SUDPTRL = LSB (current_devqual_descr);\r
-\r
break;\r
\r
-\r
-\r
case DT_CONFIG:\r
-\r
if (0 && wValueL != 1) // FIXME only a single configuration\r
-\r
fx2_stall_ep0 ();\r
-\r
else {\r
-\r
SUDPTRH = MSB (current_config_descr);\r
-\r
SUDPTRL = LSB (current_config_descr);\r
-\r
}\r
-\r
break;\r
\r
-\r
-\r
case DT_OTHER_SPEED:\r
-\r
if (0 && wValueL != 1) // FIXME only a single configuration\r
-\r
fx2_stall_ep0 ();\r
-\r
else {\r
-\r
SUDPTRH = MSB (other_config_descr);\r
-\r
SUDPTRL = LSB (other_config_descr);\r
-\r
}\r
-\r
break;\r
\r
-\r
-\r
case DT_STRING:\r
-\r
if (wValueL >= nstring_descriptors)\r
-\r
fx2_stall_ep0 ();\r
-\r
else {\r
-\r
xdata char *p = string_descriptors[wValueL];\r
-\r
SUDPTRH = MSB (p);\r
-\r
SUDPTRL = LSB (p);\r
-\r
}\r
-\r
break;\r
\r
-\r
-\r
default:\r
-\r
fx2_stall_ep0 (); // invalid request\r
-\r
break;\r
-\r
}\r
-\r
break;\r
-\r
\r
-\r
// --------------------------------\r
\r
-\r
-\r
case RQ_GET_STATUS:\r
-\r
switch (bRequestType & bmRT_RECIP_MASK){\r
-\r
case bmRT_RECIP_DEVICE:\r
-\r
EP0BUF[0] = 0;\r
-\r
EP0BUF[1] = 0;\r
-\r
EP0BCH = 0;\r
-\r
EP0BCL = 2;\r
-\r
break;\r
\r
-\r
-\r
case bmRT_RECIP_INTERFACE:\r
-\r
EP0BUF[0] = 0;\r
-\r
EP0BUF[1] = 0;\r
-\r
EP0BCH = 0;\r
-\r
EP0BCL = 2;\r
-\r
break;\r
\r
-\r
-\r
case bmRT_RECIP_ENDPOINT:\r
-\r
if (plausible_endpoint (wIndexL)){\r
-\r
EP0BUF[0] = *epcs (wIndexL) & bmEPSTALL;\r
-\r
EP0BUF[1] = 0;\r
-\r
EP0BCH = 0;\r
-\r
EP0BCL = 2;\r
-\r
}\r
-\r
else\r
-\r
fx2_stall_ep0 ();\r
-\r
break;\r
\r
-\r
-\r
default:\r
-\r
fx2_stall_ep0 ();\r
-\r
break;\r
-\r
}\r
-\r
break;\r
\r
-\r
-\r
// --------------------------------\r
\r
-\r
-\r
case RQ_SYNCH_FRAME: // not implemented\r
-\r
default:\r
-\r
fx2_stall_ep0 ();\r
-\r
break;\r
-\r
}\r
-\r
}\r
\r
-\r
-\r
else {\r
\r
-\r
-\r
////////////////////////////////////\r
-\r
// handle the OUT requests\r
-\r
////////////////////////////////////\r
\r
-\r
-\r
switch (bRequest){\r
\r
-\r
-\r
case RQ_SET_CONFIG:\r
-\r
IOE &= ~(1 << 6);\r
-\r
_usb_config = wValueL; // FIXME app should handle\r
-\r
break;\r
\r
-\r
-\r
case RQ_SET_INTERFACE:\r
-\r
_usb_alt_setting = wValueL; // FIXME app should handle\r
-\r
break;\r
\r
-\r
-\r
// --------------------------------\r
\r
-\r
-\r
case RQ_CLEAR_FEATURE:\r
-\r
switch (bRequestType & bmRT_RECIP_MASK){\r
\r
-\r
-\r
case bmRT_RECIP_DEVICE:\r
-\r
switch (wValueL){\r
-\r
case FS_DEV_REMOTE_WAKEUP:\r
-\r
default:\r
-\r
fx2_stall_ep0 ();\r
-\r
}\r
-\r
break;\r
\r
-\r
-\r
case bmRT_RECIP_ENDPOINT:\r
-\r
if (wValueL == FS_ENDPOINT_HALT && plausible_endpoint (wIndexL)){\r
-\r
*epcs (wIndexL) &= ~bmEPSTALL;\r
-\r
fx2_reset_data_toggle (wIndexL);\r
-\r
}\r
-\r
else\r
-\r
fx2_stall_ep0 ();\r
-\r
break;\r
\r
-\r
-\r
default:\r
-\r
fx2_stall_ep0 ();\r
-\r
break;\r
-\r
}\r
-\r
break;\r
\r
-\r
-\r
// --------------------------------\r
\r
-\r
-\r
case RQ_SET_FEATURE:\r
-\r
switch (bRequestType & bmRT_RECIP_MASK){\r
\r
-\r
-\r
case bmRT_RECIP_DEVICE:\r
-\r
switch (wValueL){\r
-\r
case FS_TEST_MODE:\r
-\r
// hardware handles this after we complete SETUP phase handshake\r
-\r
break;\r
\r
-\r
-\r
case FS_DEV_REMOTE_WAKEUP:\r
-\r
default:\r
-\r
fx2_stall_ep0 ();\r
-\r
break;\r
-\r
}\r
-\r
}\r
-\r
break;\r
\r
-\r
-\r
case bmRT_RECIP_ENDPOINT:\r
-\r
switch (wValueL){\r
-\r
case FS_ENDPOINT_HALT:\r
-\r
if (plausible_endpoint (wIndexL))\r
-\r
*epcs (wIndexL) |= bmEPSTALL;\r
-\r
else\r
-\r
fx2_stall_ep0 ();\r
-\r
break;\r
\r
-\r
-\r
default:\r
-\r
fx2_stall_ep0 ();\r
-\r
break;\r
-\r
}\r
-\r
break;\r
\r
-\r
-\r
// --------------------------------\r
\r
-\r
-\r
case RQ_SET_ADDRESS: // handled by fx2 hardware\r
-\r
case RQ_SET_DESCR: // not implemented\r
-\r
default:\r
-\r
fx2_stall_ep0 ();\r
-\r
}\r
\r
-\r
-\r
}\r
-\r
break;\r
\r
-\r
-\r
} // bmRT_TYPE_MASK\r
\r
-\r
-\r
// ack handshake phase of device request\r
-\r
EP0CS |= bmHSNAK;\r
-\r
}\r
-\r