mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-11-18 07:44:57 +00:00
406 lines
8.8 KiB
C
406 lines
8.8 KiB
C
|
/*
|
||
|
* Code from: USRP - Universal Software Radio Peripheral (GNU Radio)
|
||
|
*
|
||
|
* Initial modifications by:
|
||
|
*
|
||
|
* Stephan Esterhuizen, Aerospace Engineering Sciences
|
||
|
* University of Colorado at Boulder
|
||
|
* Boulder CO, USA
|
||
|
*
|
||
|
* Further modifications for use with the SiGe USB module to accompany
|
||
|
* the textbook: "A Software-Defined GPS and Galileo Receiver: A
|
||
|
* Single-Frequency Approach" by Kai Borre, Dennis Akos, et.al. by:
|
||
|
*
|
||
|
* Marcus Junered, GNSS Research Group
|
||
|
* Lulea University of Technology
|
||
|
* Lulea, Sweden
|
||
|
*
|
||
|
* http://ccar.colorado.edu/gnss
|
||
|
*
|
||
|
* ---------------------------------------------------------------------
|
||
|
*
|
||
|
* GN3S - GNSS IF Streamer for Windows
|
||
|
* Copyright (C) 2006 Marcus Junered
|
||
|
*
|
||
|
* This program 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.
|
||
|
*
|
||
|
* This program 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; if not, write to the Free Software
|
||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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"
|
||
|
#include "gn3s_regs.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[];
|
||
|
|
||
|
#define bRequestType SETUPDAT[0]
|
||
|
#define bRequest SETUPDAT[1]
|
||
|
#define wValueL SETUPDAT[2]
|
||
|
#define wValueH SETUPDAT[3]
|
||
|
#define wIndexL SETUPDAT[4]
|
||
|
#define wIndexH SETUPDAT[5]
|
||
|
#define wLengthL SETUPDAT[6]
|
||
|
#define wLengthH SETUPDAT[7]
|
||
|
|
||
|
#define MSB(x) (((unsigned short) x) >> 8)
|
||
|
#define LSB(x) (((unsigned short) x) & 0xff)
|
||
|
|
||
|
volatile bit _usb_got_SUDAV;
|
||
|
volatile bit _usb_rx_overrun;
|
||
|
|
||
|
unsigned char _usb_config = 0;
|
||
|
unsigned char _usb_alt_setting = 0; // FIXME really 1/interface
|
||
|
|
||
|
xdata unsigned char *current_device_descr;
|
||
|
xdata unsigned char *current_devqual_descr;
|
||
|
xdata unsigned char *current_config_descr;
|
||
|
xdata unsigned char *other_config_descr;
|
||
|
|
||
|
static void
|
||
|
setup_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 void
|
||
|
isr_SUDAV (void) interrupt
|
||
|
{
|
||
|
clear_usb_irq ();
|
||
|
_usb_got_SUDAV = 1;
|
||
|
//usb_handle_setup_packet();
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
isr_USBRESET (void) interrupt
|
||
|
{
|
||
|
clear_usb_irq ();
|
||
|
setup_descriptors ();
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
isr_HIGHSPEED (void) interrupt
|
||
|
{
|
||
|
clear_usb_irq ();
|
||
|
setup_descriptors ();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
usb_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 enabled
|
||
|
|
||
|
unsigned char
|
||
|
plausible_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_endpoints
|
||
|
|
||
|
xdata 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
|
||
|
}
|
||
|
|
||
|
void
|
||
|
usb_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] = bmGSDA_SELF_POWERED; // FIXME app should handle
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
// --------------------------------
|
||
|
|
||
|
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;
|
||
|
}
|