📄 main.c
字号:
/* Name: main.c * Project: AVR USB driver for CDC interface on Low-Speed USB
* - Simple parallel port controller * Author: Osamu Tamura * Creation Date: 2007-01-06 * Tabsize: 4 * Copyright: (c) 2007 by Recursion Co., Ltd. * License: Proprietary, free under certain conditions. See Documentation. *
*/#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"#define HW_CDC_PACKET_SIZE1 1
#define HW_CDC_PACKET_SIZE2 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 */ 100, /* 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_PACKET_SIZE1, 0, /* maximum packet size 8->6 */ 0, /* in ms */ /* Endpoint Descriptor */ 7, /* sizeof(usbDescrEndpoint) */ USBDESCR_ENDPOINT, /* descriptor type = endpoint */ 0x81, /* IN endpoint number 1 */ 0x02, /* attrib: Bulk endpoint */ HW_CDC_PACKET_SIZE2, 0, /* maximum packet size */
0, /* in ms */};
uchar usbFunctionDescriptor(usbRequest_t *rq){uchar *p = NULL, len = 0; if(rq->wValue.bytes[1] == USBDESCR_DEVICE){ p = (uchar *)deviceDescrCDC; len = sizeof(deviceDescrCDC); }else{ /* must be config descriptor */ p = (uchar *)configDescrCDC; len = sizeof(configDescrCDC); }
usbMsgPtr = p; return len;}static uchar requestType;static uchar modeBuffer[7];static uchar intr3Status; /* used to control interrupt endpoint transmissions *//* ------------------------------------------------------------------------- *//* ----------------------------- 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 ){ requestType = rq->bRequest; 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. */ intr3Status = 2; } } return 0;}/*---------------------------------------------------------------------------*//* usbFunctionRead *//*---------------------------------------------------------------------------*/uchar usbFunctionRead( uchar *data, uchar len ){
if(requestType == GET_LINE_CODING){ memcpy( data, modeBuffer, 7 ); return 7;
} return 0; /* error -> terminate transfer */}/*---------------------------------------------------------------------------*//* usbFunctionWrite *//*---------------------------------------------------------------------------*/uchar usbFunctionWrite( uchar *data, uchar len ){ if(requestType == SET_LINE_CODING){ /* enforce DATA0 token for next transfer */
USB_SET_DATATOKEN1(USBPID_DATA1);
memcpy( modeBuffer, data, 7 ); return 1;
}
return 1; /* error -> accept everything until end */}
static uchar tos, val;
static uchar rcnt, tcnt;
static char rbuf[8], tbuf[8];
void usbFunctionWriteOut( uchar *data, uchar len ){ /* usb -> rs232c: request */ do {
// delimiter?
if( *data>0x20 ) {
char c;
c = *data++;
if( 'a'<=c && c<='z' )
c -= 0x20; // to upper case
rbuf[rcnt++] = c;
rcnt &= 7;
rbuf[rcnt] = 0;
continue;
}
if( rcnt==0 )
continue;
// command
if( rcnt==1 ) {
uchar *addr = (uchar *)((unsigned int)tos);
uchar h, x;
switch( rbuf[0] ) {
case '?': // get
x = *addr;
h = x >> 4;
tbuf[tcnt++] = h<=9? h+'0':h-10+'A';
h = x & 0x0f;
tbuf[tcnt++] = h<=9? h+'0':h-10+'A';
break;
case '=': // set
cli();
*addr = val;
sei();
break;
case '&': // and & set
cli();
*addr &= val;
sei();
break;
case '|': // or & set
cli();
*addr |= val;
sei();
break;
case '^': // xor & set
cli();
*addr ^= val;
sei();
break;
default: // error
tbuf[tcnt++] = '!';
}
tbuf[tcnt++] = '\r';
tbuf[tcnt++] = '\n';
rcnt = 0;
continue;
}
// number
if( rcnt==2 ) {
val = tos;
tos = rbuf[0]<='9'? rbuf[0]-'0':rbuf[0]-'A'+10;
tos = (tos<<4) | (rbuf[1]<='9'? rbuf[1]-'0':rbuf[1]-'A'+10);
rcnt = 0;
continue;
}
// sfr
if( rcnt>=4 ) {
val = tos;
#if defined URSEL
tos = 0x30 + ( 'D' - rbuf[--rcnt] ) * 3;
#else
tos = 0x20 + ( rbuf[--rcnt] - 'A' ) * 3;
#endif
rbuf[rcnt] = 0;
if( !strcmp(rbuf,"PIN") )
tos += 0;
else if( !strcmp(rbuf,"DDR") )
tos += 1;
else if( !strcmp(rbuf,"PORT") )
tos += 2;
else
tos = 0x20; // error
rcnt = 0;
} } while(--len);}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
}int main(void){
wdt_enable(WDTO_1S); odDebugInit(); hardwareInit(); usbInit();
rcnt = 0;
tcnt = 0;
sei(); for(;;){ /* main event loop */ wdt_reset(); usbPoll();
/* rs232c -> usb: transmit char */ if( usbInterruptIsReady() ) {
static uchar sendEmptyFrame = 1;
if( tcnt || sendEmptyFrame ) { usbSetInterrupt((uchar *)tbuf, tcnt); /* send an empty block after last data block to indicate transfer end */
sendEmptyFrame = tcnt==HW_CDC_PACKET_SIZE2? 1:0;
}
tcnt = 0; }
/* 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 + -