345 lines
9.0 KiB
C
Executable File
345 lines
9.0 KiB
C
Executable File
|
|
/* Name: main.c
|
|
* Project: AVR USB driver for CDC interface on Low-Speed USB
|
|
* Author: Osamu Tamura
|
|
* Creation Date: 2006-05-12
|
|
* Tabsize: 4
|
|
* Copyright: (c) 2006 by Recursion Co., Ltd.
|
|
* License: Proprietary, free under certain conditions. See Documentation.
|
|
*
|
|
* 2006-07-08 removed zero-sized receive block
|
|
* 2006-07-08 adapted to higher baud rate by T.Kitazawa
|
|
*
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <avr/io.h>
|
|
#include <avr/interrupt.h>
|
|
#include <avr/pgmspace.h>
|
|
#include <avr/wdt.h>
|
|
#include <util/delay.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "oddebug.h"
|
|
#include "usbdrv.h"
|
|
#include "uart.h"
|
|
#include "hcs12ss59t/hcs12ss59t.h"
|
|
|
|
enum {
|
|
SEND_ENCAPSULATED_COMMAND = 0,
|
|
GET_ENCAPSULATED_RESPONSE,
|
|
SET_COMM_FEATURE,
|
|
GET_COMM_FEATURE,
|
|
CLEAR_COMM_FEATURE,
|
|
SET_LINE_CODING = 0x20,
|
|
GET_LINE_CODING,
|
|
SET_CONTROL_LINE_STATE,
|
|
SEND_BREAK
|
|
};
|
|
|
|
|
|
static const PROGMEM char configDescrCDC[] = { /* USB configuration descriptor */
|
|
9, /* sizeof(usbDescrConfig): length of descriptor in bytes */
|
|
USBDESCR_CONFIG, /* descriptor type */
|
|
67,
|
|
0, /* total length of data returned (including inlined descriptors) */
|
|
2, /* number of interfaces in this configuration */
|
|
1, /* index of this configuration */
|
|
0, /* configuration name string index */
|
|
#if USB_CFG_IS_SELF_POWERED
|
|
(1 << 7) | USBATTR_SELFPOWER, /* attributes */
|
|
#else
|
|
(1 << 7), /* attributes */
|
|
#endif
|
|
USB_CFG_MAX_BUS_POWER/2, /* max USB current in 2mA units */
|
|
|
|
/* interface descriptor follows inline: */
|
|
9, /* sizeof(usbDescrInterface): length of descriptor in bytes */
|
|
USBDESCR_INTERFACE, /* descriptor type */
|
|
0, /* index of this interface */
|
|
0, /* alternate setting for this interface */
|
|
USB_CFG_HAVE_INTRIN_ENDPOINT, /* endpoints excl 0: number of endpoint descriptors to follow */
|
|
USB_CFG_INTERFACE_CLASS,
|
|
USB_CFG_INTERFACE_SUBCLASS,
|
|
USB_CFG_INTERFACE_PROTOCOL,
|
|
0, /* string index for interface */
|
|
|
|
/* CDC Class-Specific descriptor */
|
|
5, /* sizeof(usbDescrCDC_HeaderFn): length of descriptor in bytes */
|
|
0x24, /* descriptor type */
|
|
0, /* header functional descriptor */
|
|
0x10, 0x01,
|
|
|
|
4, /* sizeof(usbDescrCDC_AcmFn): length of descriptor in bytes */
|
|
0x24, /* descriptor type */
|
|
2, /* abstract control management functional descriptor */
|
|
0x02, /* SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE */
|
|
|
|
5, /* sizeof(usbDescrCDC_UnionFn): length of descriptor in bytes */
|
|
0x24, /* descriptor type */
|
|
6, /* union functional descriptor */
|
|
0, /* CDC_COMM_INTF_ID */
|
|
1, /* CDC_DATA_INTF_ID */
|
|
|
|
5, /* sizeof(usbDescrCDC_CallMgtFn): length of descriptor in bytes */
|
|
0x24, /* descriptor type */
|
|
1, /* call management functional descriptor */
|
|
3, /* allow management on data interface, handles call management by itself */
|
|
1, /* CDC_DATA_INTF_ID */
|
|
|
|
/* Endpoint Descriptor */
|
|
7, /* sizeof(usbDescrEndpoint) */
|
|
USBDESCR_ENDPOINT, /* descriptor type = endpoint */
|
|
0x80|USB_CFG_EP3_NUMBER, /* IN endpoint number */
|
|
0x03, /* attrib: Interrupt endpoint */
|
|
8, 0, /* maximum packet size */
|
|
USB_CFG_INTR_POLL_INTERVAL, /* in ms */
|
|
|
|
/* Interface Descriptor */
|
|
9, /* sizeof(usbDescrInterface): length of descriptor in bytes */
|
|
USBDESCR_INTERFACE, /* descriptor type */
|
|
1, /* index of this interface */
|
|
0, /* alternate setting for this interface */
|
|
2, /* endpoints excl 0: number of endpoint descriptors to follow */
|
|
0x0A, /* Data Interface Class Codes */
|
|
0,
|
|
0, /* Data Interface Class Protocol Codes */
|
|
0, /* string index for interface */
|
|
|
|
/* Endpoint Descriptor */
|
|
7, /* sizeof(usbDescrEndpoint) */
|
|
USBDESCR_ENDPOINT, /* descriptor type = endpoint */
|
|
0x01, /* OUT endpoint number 1 */
|
|
0x02, /* attrib: Bulk endpoint */
|
|
8, 0, /* maximum packet size */
|
|
0, /* in ms */
|
|
|
|
/* Endpoint Descriptor */
|
|
7, /* sizeof(usbDescrEndpoint) */
|
|
USBDESCR_ENDPOINT, /* descriptor type = endpoint */
|
|
0x81, /* IN endpoint number 1 */
|
|
0x02, /* attrib: Bulk endpoint */
|
|
8, 0, /* maximum packet size */
|
|
0, /* in ms */
|
|
};
|
|
|
|
|
|
uchar usbFunctionDescriptor(usbRequest_t *rq)
|
|
{
|
|
|
|
if(rq->wValue.bytes[1] == USBDESCR_DEVICE){
|
|
usbMsgPtr = (uchar *)usbDescriptorDevice;
|
|
return usbDescriptorDevice[0];
|
|
}else{ /* must be config descriptor */
|
|
usbMsgPtr = (uchar *)configDescrCDC;
|
|
return sizeof(configDescrCDC);
|
|
}
|
|
}
|
|
|
|
|
|
uchar sendEmptyFrame;
|
|
static uchar intr3Status; /* used to control interrupt endpoint transmissions */
|
|
|
|
static uchar stopbit, parity, databit;
|
|
static usbDWord_t baud;
|
|
|
|
static void resetUart(void)
|
|
{
|
|
|
|
uartInit(baud.dword, parity, stopbit, databit);
|
|
tx_read_ptr = 0;
|
|
rx_write_ptr = 0;
|
|
rx_read_ptr = 0;
|
|
tx_write_ptr = 0;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
/* ----------------------------- USB interface ----------------------------- */
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
uchar usbFunctionSetup(uchar data[8])
|
|
{
|
|
usbRequest_t *rq = (void *)data;
|
|
|
|
if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */
|
|
|
|
if( rq->bRequest==GET_LINE_CODING || rq->bRequest==SET_LINE_CODING ){
|
|
return 0xff;
|
|
/* GET_LINE_CODING -> usbFunctionRead() */
|
|
/* SET_LINE_CODING -> usbFunctionWrite() */
|
|
}
|
|
if(rq->bRequest == SET_CONTROL_LINE_STATE){
|
|
|
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT3
|
|
/* Report serial state (carrier detect). On several Unix platforms,
|
|
* tty devices can only be opened when carrier detect is set.
|
|
*/
|
|
if( intr3Status==0 )
|
|
intr3Status = 2;
|
|
#endif
|
|
}
|
|
#if 1
|
|
/* Prepare bulk-in endpoint to respond to early termination */
|
|
if((rq->bmRequestType & USBRQ_DIR_MASK) == USBRQ_DIR_HOST_TO_DEVICE)
|
|
sendEmptyFrame = 1;
|
|
#endif
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* usbFunctionRead */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
uchar usbFunctionRead( uchar *data, uchar len )
|
|
{
|
|
|
|
data[0] = baud.bytes[0];
|
|
data[1] = baud.bytes[1];
|
|
data[2] = baud.bytes[2];
|
|
data[3] = baud.bytes[3];
|
|
data[4] = stopbit;
|
|
data[5] = parity;
|
|
data[6] = databit;
|
|
|
|
return 7;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* usbFunctionWrite */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
uchar usbFunctionWrite( uchar *data, uchar len )
|
|
{
|
|
|
|
/* SET_LINE_CODING */
|
|
baud.bytes[0] = data[0];
|
|
baud.bytes[1] = data[1];
|
|
baud.bytes[2] = data[2];
|
|
baud.bytes[3] = data[3];
|
|
|
|
stopbit = data[4];
|
|
parity = data[5];
|
|
databit = data[6];
|
|
|
|
if( parity>2 )
|
|
parity = 0;
|
|
if( stopbit==1 )
|
|
stopbit = 0;
|
|
|
|
resetUart();
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
void usbFunctionWriteOut( uchar *data, uchar len )
|
|
{
|
|
|
|
/* usb -> rs232c: transmit char */
|
|
for( ; len; len-- ) {
|
|
uchar uwnxt;
|
|
|
|
uwnxt = (tx_write_ptr+1) & TX_MASK;
|
|
if( uwnxt!=tx_read_ptr ) {
|
|
tx_buf[tx_write_ptr] = *data++;
|
|
tx_write_ptr = uwnxt;
|
|
}
|
|
}
|
|
|
|
/* postpone receiving next data */
|
|
if( uartTxBytesFree()<=HW_CDC_BULK_OUT_SIZE )
|
|
usbDisableAllRequests();
|
|
}
|
|
|
|
|
|
static void hardwareInit(void)
|
|
{
|
|
|
|
/* activate pull-ups except on USB lines */
|
|
USB_CFG_IOPORT = (uchar)~((1<<USB_CFG_DMINUS_BIT)|(1<<USB_CFG_DPLUS_BIT));
|
|
/* all pins input except USB (-> USB reset) */
|
|
#ifdef USB_CFG_PULLUP_IOPORT /* use usbDeviceConnect()/usbDeviceDisconnect() if available */
|
|
USBDDR = 0; /* we do RESET by deactivating pullup */
|
|
usbDeviceDisconnect();
|
|
#else
|
|
USBDDR = (1<<USB_CFG_DMINUS_BIT)|(1<<USB_CFG_DPLUS_BIT);
|
|
#endif
|
|
|
|
/* 250 ms disconnect */
|
|
wdt_reset();
|
|
_delay_ms(250);
|
|
|
|
#ifdef USB_CFG_PULLUP_IOPORT
|
|
usbDeviceConnect();
|
|
#else
|
|
USBDDR = 0; /* remove USB reset condition */
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
void waitboot()
|
|
{
|
|
PORTD |= 1 << PD7;
|
|
while (!(PIND & (1 << PD7)));
|
|
return;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
waitboot();
|
|
wdt_enable(WDTO_1S);
|
|
odDebugInit();
|
|
hardwareInit();
|
|
usbInit();
|
|
|
|
DDRD |= (1 << PD0);
|
|
DDRD &= ~(1 << PD7);
|
|
PORTD |= (1 << PD7); // Pullup for button
|
|
|
|
// Setup
|
|
FILAMENT_EN;
|
|
wdt_reset();
|
|
hcs12ss59t_init();
|
|
hcs12ss59t_set_brightness(8);
|
|
hcs12ss59t_set_text(" HCS12SS59T ");
|
|
|
|
intr3Status = 0;
|
|
sendEmptyFrame = 0;
|
|
|
|
sei();
|
|
for(;;){ /* main event loop */
|
|
if (!(PIND & (1 << PD7))) {
|
|
cli();
|
|
hcs12ss59t_set_text("-BOOTLOADER-");
|
|
FILAMENT_DIS;
|
|
wdt_enable(WDTO_15MS);
|
|
while (1); // WD Timeout -> CPU reset
|
|
}
|
|
wdt_reset();
|
|
usbPoll();
|
|
uartPoll();
|
|
|
|
#if USB_CFG_HAVE_INTRIN_ENDPOINT3
|
|
/* We need to report rx and tx carrier after open attempt */
|
|
if(intr3Status != 0 && usbInterruptIsReady3()){
|
|
static uchar serialStateNotification[10] = {0xa1, 0x20, 0, 0, 0, 0, 2, 0, 3, 0};
|
|
|
|
if(intr3Status == 2){
|
|
usbSetInterrupt3(serialStateNotification, 8);
|
|
}else{
|
|
usbSetInterrupt3(serialStateNotification+8, 2);
|
|
}
|
|
intr3Status--;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|