📄 main.c
字号:
/* 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 "usbdrv.h"
#include "oddebug.h"
#include "uart.h"
#if UART_CFG_HAVE_USART
#define HW_CDC_BULK_OUT_SIZE 8
#else
#define HW_CDC_BULK_OUT_SIZE 1
#endif
#define HW_CDC_BULK_IN_SIZE 8
/* Size of bulk transfer packets. The standard demands 8 bytes, but we may
* be better off with less. Try smaller values if the communication hangs.
*/
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 PROGMEM char deviceDescrCDC[] = { /* USB device descriptor */
18, /* sizeof(usbDescriptorDevice): length of descriptor in bytes */
USBDESCR_DEVICE, /* descriptor type */
0x01, 0x01, /* USB version supported */
0x02, /* device class: CDC */
0, /* subclass */
0, /* protocol */
8, /* max packet size */
USB_CFG_VENDOR_ID, /* 2 bytes */
0xe1, 0x05, /* 2 bytes: shared PID for CDC-ACM devices */
USB_CFG_DEVICE_VERSION, /* 2 bytes */
1, /* manufacturer string index */
2, /* product string index */
0, /* serial number string index */
1, /* number of configurations */
};
static 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
USBATTR_SELFPOWER, /* attributes */
#else
USBATTR_BUSPOWER, /* 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 */
0x83, /* IN endpoint number 3 */
0x03, /* attrib: Interrupt endpoint */
8, 0, /* maximum packet size */
2, /* 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 */
HW_CDC_BULK_OUT_SIZE, 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 */
HW_CDC_BULK_IN_SIZE, 0, /* maximum packet size */
0, /* in ms */
};
uchar usbFunctionDescriptor(usbRequest_t *rq)
{
if(rq->wValue.bytes[1] == USBDESCR_DEVICE){
usbMsgPtr = (uchar *)deviceDescrCDC;
return sizeof(deviceDescrCDC);
}else{ /* must be config descriptor */
usbMsgPtr = (uchar *)configDescrCDC;
return sizeof(configDescrCDC);
}
}
static 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);
irptr = 0;
iwptr = 0;
urptr = 0;
uwptr = 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){
/* 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;
}
/* Prepare bulk-in endpoint to respond to early termination */
if((rq->bmRequestType & USBRQ_DIR_MASK) == USBRQ_DIR_HOST_TO_DEVICE)
sendEmptyFrame = 1;
}
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];
#if USB_CFG_HAVE_USART
stopbit = data[4];
parity = data[5];
databit = data[6];
if( parity>2 )
parity = 0;
if( stopbit==1 )
stopbit = 0;
#endif
resetUart();
return 1;
}
void usbFunctionWriteOut( uchar *data, uchar len )
{
/* usb -> rs232c: transmit char */
for( ; len; len-- ) {
uartTxBufAppend(*data++);
}
/* postpone receiving next data */
if( uartTxBytesFree()<=8 )
usbDisableAllRequests();
}
static void hardwareInit(void)
{
uchar i, j;
/* 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
j = 0;
while(--j){ /* USB Reset by device only required on Watchdog Reset */
i = 0;
while(--i); /* delay >10ms for USB reset */
}
#ifdef USB_CFG_PULLUP_IOPORT
usbDeviceConnect();
#else
USBDDR = 0; /* remove USB reset condition */
#endif
/* USART configuration */
baud.dword = UART_DEFAULT_BPS;
stopbit = 0;
parity = 0;
databit = 8;
resetUart();
}
int main(void)
{
wdt_enable(WDTO_1S);
odDebugInit();
hardwareInit();
usbInit();
intr3Status = 0;
sendEmptyFrame = 0;
sei();
for(;;){ /* main event loop */
wdt_reset();
usbPoll();
uartPoll();
/* rs232c -> usb: transmit char */
if( usbInterruptIsReady() ) {
uchar bytesRead, *data;
bytesRead = uartRxBytesAvailable(&data);
if(bytesRead > 0 || sendEmptyFrame){
if(bytesRead >= HW_CDC_BULK_IN_SIZE) {
bytesRead = HW_CDC_BULK_IN_SIZE;
/* send an empty block after last data block to indicate transfer end */
sendEmptyFrame = 1;
}
else
sendEmptyFrame = 0;
usbSetInterrupt(data, bytesRead);
uartRxDidReadBytes(bytesRead);
}
}
/* 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--;
}
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -