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