?? usb.c
字號:
/*
Turbo BDM Light ColdFire - USB stack
Copyright (C) 2005 Daniel Malik
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 "hidef.h"
#include "MC68HC908JB16.h"
#include "commands.h"
#include "usb.h"
#include "cmd_processing.h"
#include "main.h"
/* Data transfer format: two possibilities exist
1. Bulk transfer over EP2 (non standard for low speed devices!) - read block commands do not work properly for bulk transfers at the moment as command_size is wrong in that case
Data format: 1 byte: size (of cmd+data)
1 byte: cmd
size-1 bytes: data
Returns at least one packet with status, but possibly more data depending on command executed.
When the data is returned the command has finished.
Start of transfer of another message into EP2 will discard any data ready to be transmitted back out of EP2
Performance: ~20kB/s, roundtrip (8B IN & 8B OUT) ~ 4ms
2. Control transfer over EP0 (standard approach and the only standard option for JB8/16)
Data format:
- Setup frame: bmRequestType = 0x41 if data is to be transfered to the device
bmRequestType = 0xC1 if data is to be transfered out of the device
bRequest = cmd
wValue.lo = data0
wValue.hi = data1
wIndex.lo = data2
wIndex.hi = data3
wLength.hi = 0
wLength.lo = # of bytes in data stage
cmd, data0-3 is always transferred from host to device.
If the command parameters fit into 4 bytes, bmRequestType = 0xC1 can be used to read results of the command being transferred
If more than 4 bytes of parameters are needed, bmRequestType = 0x41 is used and data5,... is transferred in data stage
New setup frame will discard data ready to be transmitted out of the device stored at the beginning of the buffer
Performance: ~6.7kB/s, short command (5B IN, no data out) ~3ms, ave command (5B IN, 8B OUT) ~4ms, longer cmd (5B IN, 16B OUT) ~5ms
*/
/* global and static variables, buffers, etc. */
#pragma DATA_SEG Z_RAM
/* near variables (short addressing mode) */
static near unsigned char *usb_dptr; /* pointer to first empty location in buffer (Rx) or to the first char to transmit (Tx) */
static near unsigned char usb_ep0_dcntT; /* data count to transmit */
static near unsigned char usb_ep0_dcntR; /* data count to receive */
static near unsigned char usb_ep2_dcntT; /* data count to transmit */
static near unsigned char usb_ep2_dcntR; /* data count to receive */
static near unsigned char usb_ep0_zeroterm=0; /* when non-zero it tells the EP0 Tx routine to terminate transfers by zero-length packet because the host has requested more data than available */
#pragma DATA_SEG DEFAULT
unsigned char command_buffer[COMMAND_BUFFER_SIZE]; /* buffer for Rx and Tx of commands & results */
/* data is always received starting at command_buffer+1 and transmitted starting at command_buffer+0 */
/* this is to make sure that status of the last command is preserved when receving the next command from the host */
unsigned char command_size; /* this variable holds the number of bytes of results/parameters for the current command (i.e. excluding the command itself or the command status) */
static unsigned char USB_State = US_ATTACHED;
/* USB descriptors */
const device_descriptor DeviceDesc = {
sizeof(device_descriptor), /* size */
DT_DEVICE, /* Descriptor Type (=1) */
{0x10, 0x01}, /* USB Spec Release Number in BCD = 1.10 */
0xff, /* Device Class Code (vendor specific) */
0xff, /* Device Subclass Code (vendor specific) */
0xff, /* Device Protocol Code (vendor specific) */
8, /* Maximum Packet Size for EP0 */
{0x25, 0x04}, /* Vendor ID - it is a Freescale micro, so lets use Freescale ID :-) */
{0x01, 0x10}, /* Product ID */
{0x01, 0x00}, /* Device Release Number in BCD */
1, /* Index of String Desc for Manufacturer */
2, /* Index of String Desc for Product */
2, /* Index of String Desc for SerNo */
1 /* Number of possible Configurations */
};
/* Configuration: Control EP0, Bulk IN EP2 & Bulk OUT EP2 */
/* Bulk transfers are not allowed for low speed devices by the spec, but seem to work and much faster! */
/* There will be several transactions per frame and the throughput is very high */
/* There are 2 options: either to use Bulk EP2 or Contol EP0 (in case Bulk on EP2 does not work on the specific machine) */
const struct {
configuration_descriptor ConfigDesc;
interface_descriptor InterfaceDesc0;
endpoint_descriptor Endpoint2INDesc;
endpoint_descriptor Endpoint2OUTDesc;
} config_data = {
{ /* configuration descriptor */
sizeof(configuration_descriptor), /* size */
DT_CONFIGURATION, /* Descriptor Type (=2) */
{sizeof(config_data),0x00}, /* Total Length of Data for this Configuration */
1, /* Number of Interfaces supported by this Configuration */
1, /* Designator Value for this Configuration */
2, /* Index of String Desc for this Configuration */
0x80, /* Bus powered, no wakeup */
150 /* Max. Power Consumption in this Configuration (in 2mA steps) = 250mA current for the target if needed... */
},
{ /* interface 0 descriptor (EP0) */
sizeof(interface_descriptor), /* size */
DT_INTERFACE, /* Descriptor Type (=4) */
0, /* Number of this Interface (0..) */
0, /* Alternative for this Interface (if any) */
2, /* No of EPs used by this IF (excl. EP0) */
0xff, /* IF Class Code */
0xff, /* Interface Subclass Code */
0xff, /* IF Protocol Code */
2 /* Index of String Desc for this Interface */
},
{ /* EP2 IN descriptor */
sizeof(endpoint_descriptor), /* size */
DT_ENDPOINT, /* Descriptor Type (=5) */
0x82, /* Endpoint Address (EP2) */
0x02, /* Bulk IN endpoint */
{0x08, 0x00}, /* Max. Endpoint Packet Size */
1 /* Polling Interval in frames/microframes */
},
{ /* EP2 OUT descriptor */
sizeof(endpoint_descriptor), /* size */
DT_ENDPOINT, /* Descriptor Type (=5) */
0x02, /* Endpoint Address (EP2) */
0x02, /* Bulk OUT endpoint */
{0x08, 0x00}, /* Max. Endpoint Packet Size */
1 /* Polling Interval in frames/microframes */
}
};
const char StringDesc0[]={0x04,DT_STRING,0x08,0x04,0x00}; /* Lang ID: 0x08 0x04 = 0x0408 = English (UK) */
const char StringDesc1[]="Freescale"; /* we are using Freescale VID so it is only fair to say that this is a Freescale product :-) */
const char StringDesc2[]="Turbo BDM Light ColdFire v0.4"; /* product version */
const char * far const StringDescTable[]={StringDesc0,StringDesc1,StringDesc2}; /* pointers to the descriptors */
/* Functions */
/* copies data from flash to the USB buffer */
void copy(unsigned char count, unsigned char * src, unsigned char * dest) {
while(count--) *(dest++) = *(src++); /* copy data while count lasts... */
}
/* Copies string from flash to the buffer */
unsigned char copystring(unsigned char index, unsigned char * dest) {
unsigned char cnt=0;
const unsigned char * src;
if (index) {
/* unicode copy */
if (index<(sizeof(StringDescTable)/2)) { /* if the string exists, copy it */
unsigned char * dest_orig=dest;
dest+=2;
src = StringDescTable[index];
while (*src) {
*(dest++) = *(src++); /* copy byte */
*(dest++) = 0; /* unicode */
cnt+=2; /* increment count */
}
cnt+=2; /* account for the header */
*(dest_orig++) = cnt; /* create the header */
*(dest_orig) = DT_STRING;
}
} else {
/* plain copy (string 0), it has the header already */
src = StringDescTable[0];
while (*src) {
*(dest++) = *(src++); /* copy byte */
cnt++; /* inrement count */
}
}
return(cnt);
}
/* EP0 Tx */
void USB_ep0_tx(void) {
UCR0_TX0E=0; /* disable EP0 transmitter */
UIR2_TXD0FR = 1; /* clear the interrupt flag to make sure the packet transmits */
if (usb_ep0_dcntT!=0xff) {
/* transmit data from the buffer */
UE0D0 = *(usb_dptr+0); /* copy all 8 bytes, packet might be shorter than 8 bytes */
UE0D1 = *(usb_dptr+1);
UE0D2 = *(usb_dptr+2);
UE0D3 = *(usb_dptr+3);
UE0D4 = *(usb_dptr+4);
UE0D5 = *(usb_dptr+5);
UE0D6 = *(usb_dptr+6);
UE0D7 = *(usb_dptr+7);
usb_dptr+=8;
if ((usb_ep0_dcntT>8)||((usb_ep0_dcntT==8)&&(usb_ep0_zeroterm))) {
UCR0 = ((UCR0^UCR0_T0SEQ_MASK)&UCR0_T0SEQ_MASK) | UCR0_TX0E_MASK | UCR0_RX0E_MASK + 8; /* enable transmission on EP0, toggle DATA0/1, length 8 (more data in buffer) */
usb_ep0_dcntT-=8;
} else {
UCR0 = ((UCR0^UCR0_T0SEQ_MASK)&UCR0_T0SEQ_MASK) | UCR0_TX0E_MASK | UCR0_RX0E_MASK + usb_ep0_dcntT; /* enable transmission on EP0, toggle DATA0/1, length according to count */
usb_ep0_dcntT = 0xff; /* no more transmission the next time */
usb_ep0_zeroterm=0; /* just finished transmission, switch zero-length termination off */
}
} else {
/* there is no data to transmit, but the interrupt occured anyway - this must be a special case or end of transmit condition */
if ((USR0_SETUP)&&(((*(setup_packet*)&UE0D0).bmRequestType&0x60)==0)) {
/* the special case is a Setup frame of standard request which was received previously, now detemine what to do */
switch ((*(setup_packet*)&UE0D0).bRequest) {
case SET_ADDRESS:
UADDR = UADDR_USBEN_MASK | (*(setup_packet*)&UE0D0).wValue.lo; /* set the new address (confirmation of reception was just transmitted) */
if ((*(setup_packet*)&UE0D0).wValue.lo) USB_State = US_ADDRESSED; else USB_State = US_DEFAULT;
case CLEAR_FEATURE:
case SET_CONFIGURATION:
case GET_CONFIGURATION:
break;
}
}
}
}
/* EP2 Tx */
void USB_ep2_tx(void) {
UCR2_TX2E=0; /* disable EP2 transmitter */
UIR2_TXD2FR = 1; /* clear the interrupt flag to make sure the packet transmits */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -