<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-cn">
		<id>http://wiki.ywrobot.net/index.php?action=history&amp;feed=atom&amp;title=USBCore.cpp</id>
		<title>USBCore.cpp - 版本历史</title>
		<link rel="self" type="application/atom+xml" href="http://wiki.ywrobot.net/index.php?action=history&amp;feed=atom&amp;title=USBCore.cpp"/>
		<link rel="alternate" type="text/html" href="http://wiki.ywrobot.net/index.php?title=USBCore.cpp&amp;action=history"/>
		<updated>2026-05-14T11:40:46Z</updated>
		<subtitle>本wiki的该页面的版本历史</subtitle>
		<generator>MediaWiki 1.26.2</generator>

	<entry>
		<id>http://wiki.ywrobot.net/index.php?title=USBCore.cpp&amp;diff=82&amp;oldid=prev</id>
		<title>YWrobot CYB：创建页面，内容为“&lt;pre style=&quot;color:blue&quot;&gt;   /* Copyright (c) 2010, Peter Barrett   **   ** Permission to use, copy, modify, and/or distribute this software for   ** any purpose with...”</title>
		<link rel="alternate" type="text/html" href="http://wiki.ywrobot.net/index.php?title=USBCore.cpp&amp;diff=82&amp;oldid=prev"/>
				<updated>2016-04-25T02:13:58Z</updated>
		
		<summary type="html">&lt;p&gt;创建页面，内容为“&amp;lt;pre style=&amp;quot;color:blue&amp;quot;&amp;gt;   /* Copyright (c) 2010, Peter Barrett   **   ** Permission to use, copy, modify, and/or distribute this software for   ** any purpose with...”&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;pre style=&amp;quot;color:blue&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Copyright (c) 2010, Peter Barrett  &lt;br /&gt;
**  &lt;br /&gt;
** Permission to use, copy, modify, and/or distribute this software for  &lt;br /&gt;
** any purpose with or without fee is hereby granted, provided that the  &lt;br /&gt;
** above copyright notice and this permission notice appear in all copies.  &lt;br /&gt;
** &lt;br /&gt;
** THE SOFTWARE IS PROVIDED &amp;quot;AS IS&amp;quot; AND THE AUTHOR DISCLAIMS ALL  &lt;br /&gt;
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED  &lt;br /&gt;
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR  &lt;br /&gt;
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES  &lt;br /&gt;
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,  &lt;br /&gt;
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  &lt;br /&gt;
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS  &lt;br /&gt;
** SOFTWARE.  &lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;Platform.h&amp;quot;&lt;br /&gt;
#include &amp;quot;USBAPI.h&amp;quot;&lt;br /&gt;
#include &amp;quot;USBDesc.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#if defined(USBCON)&lt;br /&gt;
&lt;br /&gt;
#define EP_TYPE_CONTROL				0x00&lt;br /&gt;
#define EP_TYPE_BULK_IN				0x81&lt;br /&gt;
#define EP_TYPE_BULK_OUT			0x80&lt;br /&gt;
#define EP_TYPE_INTERRUPT_IN		0xC1&lt;br /&gt;
#define EP_TYPE_INTERRUPT_OUT		0xC0&lt;br /&gt;
#define EP_TYPE_ISOCHRONOUS_IN		0x41&lt;br /&gt;
#define EP_TYPE_ISOCHRONOUS_OUT		0x40&lt;br /&gt;
&lt;br /&gt;
/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */&lt;br /&gt;
#define TX_RX_LED_PULSE_MS 100&lt;br /&gt;
volatile u8 TxLEDPulse; /**&amp;lt; Milliseconds remaining for data Tx LED pulse */&lt;br /&gt;
volatile u8 RxLEDPulse; /**&amp;lt; Milliseconds remaining for data Rx LED pulse */&lt;br /&gt;
&lt;br /&gt;
//==================================================================&lt;br /&gt;
//==================================================================&lt;br /&gt;
&lt;br /&gt;
extern const u16 STRING_LANGUAGE[] PROGMEM;&lt;br /&gt;
extern const u16 STRING_IPRODUCT[] PROGMEM;&lt;br /&gt;
extern const u16 STRING_IMANUFACTURER[] PROGMEM;&lt;br /&gt;
extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM;&lt;br /&gt;
extern const DeviceDescriptor USB_DeviceDescriptorA PROGMEM;&lt;br /&gt;
&lt;br /&gt;
const u16 STRING_LANGUAGE[2] = {&lt;br /&gt;
	(3&amp;lt;&amp;lt;8) | (2+2),&lt;br /&gt;
	0x0409	// English&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const u16 STRING_IPRODUCT[17] = {&lt;br /&gt;
	(3&amp;lt;&amp;lt;8) | (2+2*16),&lt;br /&gt;
#if USB_PID == 0x8036	&lt;br /&gt;
	'A','r','d','u','i','n','o',' ','L','e','o','n','a','r','d','o'&lt;br /&gt;
#elif USB_PID == 0x8037&lt;br /&gt;
	'A','r','d','u','i','n','o',' ','M','i','c','r','o',' ',' ',' '&lt;br /&gt;
#elif USB_PID == 0x803C&lt;br /&gt;
	'A','r','d','u','i','n','o',' ','E','s','p','l','o','r','a',' '&lt;br /&gt;
#elif USB_PID == 0x9208&lt;br /&gt;
	'L','i','l','y','P','a','d','U','S','B',' ',' ',' ',' ',' ',' '&lt;br /&gt;
#else&lt;br /&gt;
	'U','S','B',' ','I','O',' ','B','o','a','r','d',' ',' ',' ',' '&lt;br /&gt;
#endif&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
const u16 STRING_IMANUFACTURER[12] = {&lt;br /&gt;
	(3&amp;lt;&amp;lt;8) | (2+2*11),&lt;br /&gt;
#if USB_VID == 0x2341&lt;br /&gt;
	'A','r','d','u','i','n','o',' ','L','L','C'&lt;br /&gt;
#elif USB_VID == 0x1b4f&lt;br /&gt;
	'S','p','a','r','k','F','u','n',' ',' ',' '&lt;br /&gt;
#else&lt;br /&gt;
	'U','n','k','n','o','w','n',' ',' ',' ',' '&lt;br /&gt;
#endif&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
#ifdef CDC_ENABLED&lt;br /&gt;
#define DEVICE_CLASS 0x02&lt;br /&gt;
#else&lt;br /&gt;
#define DEVICE_CLASS 0x00&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//	DEVICE DESCRIPTOR&lt;br /&gt;
const DeviceDescriptor USB_DeviceDescriptor =&lt;br /&gt;
	D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);&lt;br /&gt;
&lt;br /&gt;
const DeviceDescriptor USB_DeviceDescriptorA =&lt;br /&gt;
	D_DEVICE(DEVICE_CLASS,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);&lt;br /&gt;
&lt;br /&gt;
//==================================================================&lt;br /&gt;
//==================================================================&lt;br /&gt;
&lt;br /&gt;
volatile u8 _usbConfiguration = 0;&lt;br /&gt;
&lt;br /&gt;
static inline void WaitIN(void)&lt;br /&gt;
{&lt;br /&gt;
	while (!(UEINTX &amp;amp; (1&amp;lt;&amp;lt;TXINI)));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline void ClearIN(void)&lt;br /&gt;
{&lt;br /&gt;
	UEINTX = ~(1&amp;lt;&amp;lt;TXINI);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline void WaitOUT(void)&lt;br /&gt;
{&lt;br /&gt;
	while (!(UEINTX &amp;amp; (1&amp;lt;&amp;lt;RXOUTI)))&lt;br /&gt;
		;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline u8 WaitForINOrOUT()&lt;br /&gt;
{&lt;br /&gt;
	while (!(UEINTX &amp;amp; ((1&amp;lt;&amp;lt;TXINI)|(1&amp;lt;&amp;lt;RXOUTI))))&lt;br /&gt;
		;&lt;br /&gt;
	return (UEINTX &amp;amp; (1&amp;lt;&amp;lt;RXOUTI)) == 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline void ClearOUT(void)&lt;br /&gt;
{&lt;br /&gt;
	UEINTX = ~(1&amp;lt;&amp;lt;RXOUTI);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void Recv(volatile u8* data, u8 count)&lt;br /&gt;
{&lt;br /&gt;
	while (count--)&lt;br /&gt;
		*data++ = UEDATX;&lt;br /&gt;
	&lt;br /&gt;
	RXLED1;					// light the RX LED&lt;br /&gt;
	RxLEDPulse = TX_RX_LED_PULSE_MS;	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline u8 Recv8()&lt;br /&gt;
{&lt;br /&gt;
	RXLED1;					// light the RX LED&lt;br /&gt;
	RxLEDPulse = TX_RX_LED_PULSE_MS;&lt;br /&gt;
&lt;br /&gt;
	return UEDATX;	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline void Send8(u8 d)&lt;br /&gt;
{&lt;br /&gt;
	UEDATX = d;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline void SetEP(u8 ep)&lt;br /&gt;
{&lt;br /&gt;
	UENUM = ep;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline u8 FifoByteCount()&lt;br /&gt;
{&lt;br /&gt;
	return UEBCLX;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline u8 ReceivedSetupInt()&lt;br /&gt;
{&lt;br /&gt;
	return UEINTX &amp;amp; (1&amp;lt;&amp;lt;RXSTPI);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline void ClearSetupInt()&lt;br /&gt;
{&lt;br /&gt;
	UEINTX = ~((1&amp;lt;&amp;lt;RXSTPI) | (1&amp;lt;&amp;lt;RXOUTI) | (1&amp;lt;&amp;lt;TXINI));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline void Stall()&lt;br /&gt;
{&lt;br /&gt;
	UECONX = (1&amp;lt;&amp;lt;STALLRQ) | (1&amp;lt;&amp;lt;EPEN);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline u8 ReadWriteAllowed()&lt;br /&gt;
{&lt;br /&gt;
	return UEINTX &amp;amp; (1&amp;lt;&amp;lt;RWAL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline u8 Stalled()&lt;br /&gt;
{&lt;br /&gt;
	return UEINTX &amp;amp; (1&amp;lt;&amp;lt;STALLEDI);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline u8 FifoFree()&lt;br /&gt;
{&lt;br /&gt;
	return UEINTX &amp;amp; (1&amp;lt;&amp;lt;FIFOCON);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline void ReleaseRX()&lt;br /&gt;
{&lt;br /&gt;
	UEINTX = 0x6B;	// FIFOCON=0 NAKINI=1 RWAL=1 NAKOUTI=0 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=1&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline void ReleaseTX()&lt;br /&gt;
{&lt;br /&gt;
	UEINTX = 0x3A;	// FIFOCON=0 NAKINI=0 RWAL=1 NAKOUTI=1 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=0&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static inline u8 FrameNumber()&lt;br /&gt;
{&lt;br /&gt;
	return UDFNUML;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//==================================================================&lt;br /&gt;
//==================================================================&lt;br /&gt;
&lt;br /&gt;
u8 USBGetConfiguration(void)&lt;br /&gt;
{&lt;br /&gt;
	return _usbConfiguration;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#define USB_RECV_TIMEOUT&lt;br /&gt;
class LockEP&lt;br /&gt;
{&lt;br /&gt;
	u8 _sreg;&lt;br /&gt;
public:&lt;br /&gt;
	LockEP(u8 ep) : _sreg(SREG)&lt;br /&gt;
	{&lt;br /&gt;
		cli();&lt;br /&gt;
		SetEP(ep &amp;amp; 7);&lt;br /&gt;
	}&lt;br /&gt;
	~LockEP()&lt;br /&gt;
	{&lt;br /&gt;
		SREG = _sreg;&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
//	Number of bytes, assumes a rx endpoint&lt;br /&gt;
u8 USB_Available(u8 ep)&lt;br /&gt;
{&lt;br /&gt;
	LockEP lock(ep);&lt;br /&gt;
	return FifoByteCount();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//	Non Blocking receive&lt;br /&gt;
//	Return number of bytes read&lt;br /&gt;
int USB_Recv(u8 ep, void* d, int len)&lt;br /&gt;
{&lt;br /&gt;
	if (!_usbConfiguration || len &amp;lt; 0)&lt;br /&gt;
		return -1;&lt;br /&gt;
	&lt;br /&gt;
	LockEP lock(ep);&lt;br /&gt;
	u8 n = FifoByteCount();&lt;br /&gt;
	len = min(n,len);&lt;br /&gt;
	n = len;&lt;br /&gt;
	u8* dst = (u8*)d;&lt;br /&gt;
	while (n--)&lt;br /&gt;
		*dst++ = Recv8();&lt;br /&gt;
	if (len &amp;amp;&amp;amp; !FifoByteCount())	// release empty buffer&lt;br /&gt;
		ReleaseRX();&lt;br /&gt;
	&lt;br /&gt;
	return len;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//	Recv 1 byte if ready&lt;br /&gt;
int USB_Recv(u8 ep)&lt;br /&gt;
{&lt;br /&gt;
	u8 c;&lt;br /&gt;
	if (USB_Recv(ep,&amp;amp;c,1) != 1)&lt;br /&gt;
		return -1;&lt;br /&gt;
	return c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//	Space in send EP&lt;br /&gt;
u8 USB_SendSpace(u8 ep)&lt;br /&gt;
{&lt;br /&gt;
	LockEP lock(ep);&lt;br /&gt;
	if (!ReadWriteAllowed())&lt;br /&gt;
		return 0;&lt;br /&gt;
	return 64 - FifoByteCount();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//	Blocking Send of data to an endpoint&lt;br /&gt;
int USB_Send(u8 ep, const void* d, int len)&lt;br /&gt;
{&lt;br /&gt;
	if (!_usbConfiguration)&lt;br /&gt;
		return -1;&lt;br /&gt;
&lt;br /&gt;
	int r = len;&lt;br /&gt;
	const u8* data = (const u8*)d;&lt;br /&gt;
	u8 zero = ep &amp;amp; TRANSFER_ZERO;&lt;br /&gt;
	u8 timeout = 250;		// 250ms timeout on send? TODO&lt;br /&gt;
	while (len)&lt;br /&gt;
	{&lt;br /&gt;
		u8 n = USB_SendSpace(ep);&lt;br /&gt;
		if (n == 0)&lt;br /&gt;
		{&lt;br /&gt;
			if (!(--timeout))&lt;br /&gt;
				return -1;&lt;br /&gt;
			delay(1);&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (n &amp;gt; len)&lt;br /&gt;
			n = len;&lt;br /&gt;
		len -= n;&lt;br /&gt;
		{&lt;br /&gt;
			LockEP lock(ep);&lt;br /&gt;
			if (ep &amp;amp; TRANSFER_ZERO)&lt;br /&gt;
			{&lt;br /&gt;
				while (n--)&lt;br /&gt;
					Send8(0);&lt;br /&gt;
			}&lt;br /&gt;
			else if (ep &amp;amp; TRANSFER_PGM)&lt;br /&gt;
			{&lt;br /&gt;
				while (n--)&lt;br /&gt;
					Send8(pgm_read_byte(data++));&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				while (n--)&lt;br /&gt;
					Send8(*data++);&lt;br /&gt;
			}&lt;br /&gt;
			if (!ReadWriteAllowed() || ((len == 0) &amp;amp;&amp;amp; (ep &amp;amp; TRANSFER_RELEASE)))	// Release full buffer&lt;br /&gt;
				ReleaseTX();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	TXLED1;					// light the TX LED&lt;br /&gt;
	TxLEDPulse = TX_RX_LED_PULSE_MS;&lt;br /&gt;
	return r;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
extern const u8 _initEndpoints[] PROGMEM;&lt;br /&gt;
const u8 _initEndpoints[] = &lt;br /&gt;
{&lt;br /&gt;
	0,&lt;br /&gt;
	&lt;br /&gt;
#ifdef CDC_ENABLED&lt;br /&gt;
	EP_TYPE_INTERRUPT_IN,		// CDC_ENDPOINT_ACM&lt;br /&gt;
	EP_TYPE_BULK_OUT,			// CDC_ENDPOINT_OUT&lt;br /&gt;
	EP_TYPE_BULK_IN,			// CDC_ENDPOINT_IN&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#ifdef HID_ENABLED&lt;br /&gt;
	EP_TYPE_INTERRUPT_IN		// HID_ENDPOINT_INT&lt;br /&gt;
#endif&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
#define EP_SINGLE_64 0x32	// EP0&lt;br /&gt;
#define EP_DOUBLE_64 0x36	// Other endpoints&lt;br /&gt;
&lt;br /&gt;
static&lt;br /&gt;
void InitEP(u8 index, u8 type, u8 size)&lt;br /&gt;
{&lt;br /&gt;
	UENUM = index;&lt;br /&gt;
	UECONX = 1;&lt;br /&gt;
	UECFG0X = type;&lt;br /&gt;
	UECFG1X = size;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static&lt;br /&gt;
void InitEndpoints()&lt;br /&gt;
{&lt;br /&gt;
	for (u8 i = 1; i &amp;lt; sizeof(_initEndpoints); i++)&lt;br /&gt;
	{&lt;br /&gt;
		UENUM = i;&lt;br /&gt;
		UECONX = 1;&lt;br /&gt;
		UECFG0X = pgm_read_byte(_initEndpoints+i);&lt;br /&gt;
		UECFG1X = EP_DOUBLE_64;&lt;br /&gt;
	}&lt;br /&gt;
	UERST = 0x7E;	// And reset them&lt;br /&gt;
	UERST = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//	Handle CLASS_INTERFACE requests&lt;br /&gt;
static&lt;br /&gt;
bool ClassInterfaceRequest(Setup&amp;amp; setup)&lt;br /&gt;
{&lt;br /&gt;
	u8 i = setup.wIndex;&lt;br /&gt;
&lt;br /&gt;
#ifdef CDC_ENABLED&lt;br /&gt;
	if (CDC_ACM_INTERFACE == i)&lt;br /&gt;
		return CDC_Setup(setup);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#ifdef HID_ENABLED&lt;br /&gt;
	if (HID_INTERFACE == i)&lt;br /&gt;
		return HID_Setup(setup);&lt;br /&gt;
#endif&lt;br /&gt;
	return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int _cmark;&lt;br /&gt;
int _cend;&lt;br /&gt;
void InitControl(int end)&lt;br /&gt;
{&lt;br /&gt;
	SetEP(0);&lt;br /&gt;
	_cmark = 0;&lt;br /&gt;
	_cend = end;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static&lt;br /&gt;
bool SendControl(u8 d)&lt;br /&gt;
{&lt;br /&gt;
	if (_cmark &amp;lt; _cend)&lt;br /&gt;
	{&lt;br /&gt;
		if (!WaitForINOrOUT())&lt;br /&gt;
			return false;&lt;br /&gt;
		Send8(d);&lt;br /&gt;
		if (!((_cmark + 1) &amp;amp; 0x3F))&lt;br /&gt;
			ClearIN();	// Fifo is full, release this packet&lt;br /&gt;
	}&lt;br /&gt;
	_cmark++;&lt;br /&gt;
	return true;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
//	Clipped by _cmark/_cend&lt;br /&gt;
int USB_SendControl(u8 flags, const void* d, int len)&lt;br /&gt;
{&lt;br /&gt;
	int sent = len;&lt;br /&gt;
	const u8* data = (const u8*)d;&lt;br /&gt;
	bool pgm = flags &amp;amp; TRANSFER_PGM;&lt;br /&gt;
	while (len--)&lt;br /&gt;
	{&lt;br /&gt;
		u8 c = pgm ? pgm_read_byte(data++) : *data++;&lt;br /&gt;
		if (!SendControl(c))&lt;br /&gt;
			return -1;&lt;br /&gt;
	}&lt;br /&gt;
	return sent;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//	Does not timeout or cross fifo boundaries&lt;br /&gt;
//	Will only work for transfers &amp;lt;= 64 bytes&lt;br /&gt;
//	TODO&lt;br /&gt;
int USB_RecvControl(void* d, int len)&lt;br /&gt;
{&lt;br /&gt;
	WaitOUT();&lt;br /&gt;
	Recv((u8*)d,len);&lt;br /&gt;
	ClearOUT();&lt;br /&gt;
	return len;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int SendInterfaces()&lt;br /&gt;
{&lt;br /&gt;
	int total = 0;&lt;br /&gt;
	u8 interfaces = 0;&lt;br /&gt;
&lt;br /&gt;
#ifdef CDC_ENABLED&lt;br /&gt;
	total = CDC_GetInterface(&amp;amp;interfaces);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#ifdef HID_ENABLED&lt;br /&gt;
	total += HID_GetInterface(&amp;amp;interfaces);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
	return interfaces;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//	Construct a dynamic configuration descriptor&lt;br /&gt;
//	This really needs dynamic endpoint allocation etc&lt;br /&gt;
//	TODO&lt;br /&gt;
static&lt;br /&gt;
bool SendConfiguration(int maxlen)&lt;br /&gt;
{&lt;br /&gt;
	//	Count and measure interfaces&lt;br /&gt;
	InitControl(0);	&lt;br /&gt;
	int interfaces = SendInterfaces();&lt;br /&gt;
	ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces);&lt;br /&gt;
&lt;br /&gt;
	//	Now send them&lt;br /&gt;
	InitControl(maxlen);&lt;br /&gt;
	USB_SendControl(0,&amp;amp;config,sizeof(ConfigDescriptor));&lt;br /&gt;
	SendInterfaces();&lt;br /&gt;
	return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
u8 _cdcComposite = 0;&lt;br /&gt;
&lt;br /&gt;
static&lt;br /&gt;
bool SendDescriptor(Setup&amp;amp; setup)&lt;br /&gt;
{&lt;br /&gt;
	u8 t = setup.wValueH;&lt;br /&gt;
	if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t)&lt;br /&gt;
		return SendConfiguration(setup.wLength);&lt;br /&gt;
&lt;br /&gt;
	InitControl(setup.wLength);&lt;br /&gt;
#ifdef HID_ENABLED&lt;br /&gt;
	if (HID_REPORT_DESCRIPTOR_TYPE == t)&lt;br /&gt;
		return HID_GetDescriptor(t);&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
	u8 desc_length = 0;&lt;br /&gt;
	const u8* desc_addr = 0;&lt;br /&gt;
	if (USB_DEVICE_DESCRIPTOR_TYPE == t)&lt;br /&gt;
	{&lt;br /&gt;
		if (setup.wLength == 8)&lt;br /&gt;
			_cdcComposite = 1;&lt;br /&gt;
		desc_addr = _cdcComposite ?  (const u8*)&amp;amp;USB_DeviceDescriptorA : (const u8*)&amp;amp;USB_DeviceDescriptor;&lt;br /&gt;
	}&lt;br /&gt;
	else if (USB_STRING_DESCRIPTOR_TYPE == t)&lt;br /&gt;
	{&lt;br /&gt;
		if (setup.wValueL == 0)&lt;br /&gt;
			desc_addr = (const u8*)&amp;amp;STRING_LANGUAGE;&lt;br /&gt;
		else if (setup.wValueL == IPRODUCT) &lt;br /&gt;
			desc_addr = (const u8*)&amp;amp;STRING_IPRODUCT;&lt;br /&gt;
		else if (setup.wValueL == IMANUFACTURER)&lt;br /&gt;
			desc_addr = (const u8*)&amp;amp;STRING_IMANUFACTURER;&lt;br /&gt;
		else&lt;br /&gt;
			return false;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (desc_addr == 0)&lt;br /&gt;
		return false;&lt;br /&gt;
	if (desc_length == 0)&lt;br /&gt;
		desc_length = pgm_read_byte(desc_addr);&lt;br /&gt;
&lt;br /&gt;
	USB_SendControl(TRANSFER_PGM,desc_addr,desc_length);&lt;br /&gt;
	return true;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//	Endpoint 0 interrupt&lt;br /&gt;
ISR(USB_COM_vect)&lt;br /&gt;
{&lt;br /&gt;
    SetEP(0);&lt;br /&gt;
	if (!ReceivedSetupInt())&lt;br /&gt;
		return;&lt;br /&gt;
&lt;br /&gt;
	Setup setup;&lt;br /&gt;
	Recv((u8*)&amp;amp;setup,8);&lt;br /&gt;
	ClearSetupInt();&lt;br /&gt;
&lt;br /&gt;
	u8 requestType = setup.bmRequestType;&lt;br /&gt;
	if (requestType &amp;amp; REQUEST_DEVICETOHOST)&lt;br /&gt;
		WaitIN();&lt;br /&gt;
	else&lt;br /&gt;
		ClearIN();&lt;br /&gt;
&lt;br /&gt;
    bool ok = true;&lt;br /&gt;
	if (REQUEST_STANDARD == (requestType &amp;amp; REQUEST_TYPE))&lt;br /&gt;
	{&lt;br /&gt;
		//	Standard Requests&lt;br /&gt;
		u8 r = setup.bRequest;&lt;br /&gt;
		if (GET_STATUS == r)&lt;br /&gt;
		{&lt;br /&gt;
			Send8(0);		// TODO&lt;br /&gt;
			Send8(0);&lt;br /&gt;
		}&lt;br /&gt;
		else if (CLEAR_FEATURE == r)&lt;br /&gt;
		{&lt;br /&gt;
		}&lt;br /&gt;
		else if (SET_FEATURE == r)&lt;br /&gt;
		{&lt;br /&gt;
		}&lt;br /&gt;
		else if (SET_ADDRESS == r)&lt;br /&gt;
		{&lt;br /&gt;
			WaitIN();&lt;br /&gt;
			UDADDR = setup.wValueL | (1&amp;lt;&amp;lt;ADDEN);&lt;br /&gt;
		}&lt;br /&gt;
		else if (GET_DESCRIPTOR == r)&lt;br /&gt;
		{&lt;br /&gt;
			ok = SendDescriptor(setup);&lt;br /&gt;
		}&lt;br /&gt;
		else if (SET_DESCRIPTOR == r)&lt;br /&gt;
		{&lt;br /&gt;
			ok = false;&lt;br /&gt;
		}&lt;br /&gt;
		else if (GET_CONFIGURATION == r)&lt;br /&gt;
		{&lt;br /&gt;
			Send8(1);&lt;br /&gt;
		}&lt;br /&gt;
		else if (SET_CONFIGURATION == r)&lt;br /&gt;
		{&lt;br /&gt;
			if (REQUEST_DEVICE == (requestType &amp;amp; REQUEST_RECIPIENT))&lt;br /&gt;
			{&lt;br /&gt;
				InitEndpoints();&lt;br /&gt;
				_usbConfiguration = setup.wValueL;&lt;br /&gt;
			} else&lt;br /&gt;
				ok = false;&lt;br /&gt;
		}&lt;br /&gt;
		else if (GET_INTERFACE == r)&lt;br /&gt;
		{&lt;br /&gt;
		}&lt;br /&gt;
		else if (SET_INTERFACE == r)&lt;br /&gt;
		{&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		InitControl(setup.wLength);		//	Max length of transfer&lt;br /&gt;
		ok = ClassInterfaceRequest(setup);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (ok)&lt;br /&gt;
		ClearIN();&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		Stall();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void USB_Flush(u8 ep)&lt;br /&gt;
{&lt;br /&gt;
	SetEP(ep);&lt;br /&gt;
	if (FifoByteCount())&lt;br /&gt;
		ReleaseTX();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//	General interrupt&lt;br /&gt;
ISR(USB_GEN_vect)&lt;br /&gt;
{&lt;br /&gt;
	u8 udint = UDINT;&lt;br /&gt;
	UDINT = 0;&lt;br /&gt;
&lt;br /&gt;
	//	End of Reset&lt;br /&gt;
	if (udint &amp;amp; (1&amp;lt;&amp;lt;EORSTI))&lt;br /&gt;
	{&lt;br /&gt;
		InitEP(0,EP_TYPE_CONTROL,EP_SINGLE_64);	// init ep0&lt;br /&gt;
		_usbConfiguration = 0;			// not configured yet&lt;br /&gt;
		UEIENX = 1 &amp;lt;&amp;lt; RXSTPE;			// Enable interrupts for ep0&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	//	Start of Frame - happens every millisecond so we use it for TX and RX LED one-shot timing, too&lt;br /&gt;
	if (udint &amp;amp; (1&amp;lt;&amp;lt;SOFI))&lt;br /&gt;
	{&lt;br /&gt;
#ifdef CDC_ENABLED&lt;br /&gt;
		USB_Flush(CDC_TX);				// Send a tx frame if found&lt;br /&gt;
		if (USB_Available(CDC_RX))	// Handle received bytes (if any)&lt;br /&gt;
			Serial.accept();&lt;br /&gt;
#endif&lt;br /&gt;
		&lt;br /&gt;
		// check whether the one-shot period has elapsed.  if so, turn off the LED&lt;br /&gt;
		if (TxLEDPulse &amp;amp;&amp;amp; !(--TxLEDPulse))&lt;br /&gt;
			TXLED0;&lt;br /&gt;
		if (RxLEDPulse &amp;amp;&amp;amp; !(--RxLEDPulse))&lt;br /&gt;
			RXLED0;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//	VBUS or counting frames&lt;br /&gt;
//	Any frame counting?&lt;br /&gt;
u8 USBConnected()&lt;br /&gt;
{&lt;br /&gt;
	u8 f = UDFNUML;&lt;br /&gt;
	delay(3);&lt;br /&gt;
	return f != UDFNUML;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//=======================================================================&lt;br /&gt;
//=======================================================================&lt;br /&gt;
&lt;br /&gt;
USBDevice_ USBDevice;&lt;br /&gt;
&lt;br /&gt;
USBDevice_::USBDevice_()&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void USBDevice_::attach()&lt;br /&gt;
{&lt;br /&gt;
	_usbConfiguration = 0;&lt;br /&gt;
	UHWCON = 0x01;						// power internal reg&lt;br /&gt;
	USBCON = (1&amp;lt;&amp;lt;USBE)|(1&amp;lt;&amp;lt;FRZCLK);		// clock frozen, usb enabled&lt;br /&gt;
#if F_CPU == 16000000UL&lt;br /&gt;
	PLLCSR = 0x12;						// Need 16 MHz xtal&lt;br /&gt;
#elif F_CPU == 8000000UL&lt;br /&gt;
	PLLCSR = 0x02;						// Need 8 MHz xtal&lt;br /&gt;
#endif&lt;br /&gt;
	while (!(PLLCSR &amp;amp; (1&amp;lt;&amp;lt;PLOCK)))		// wait for lock pll&lt;br /&gt;
		;&lt;br /&gt;
&lt;br /&gt;
	// Some tests on specific versions of macosx (10.7.3), reported some&lt;br /&gt;
	// strange behaviuors when the board is reset using the serial&lt;br /&gt;
	// port touch at 1200 bps. This delay fixes this behaviour.&lt;br /&gt;
	delay(1);&lt;br /&gt;
&lt;br /&gt;
	USBCON = ((1&amp;lt;&amp;lt;USBE)|(1&amp;lt;&amp;lt;OTGPADE));	// start USB clock&lt;br /&gt;
	UDIEN = (1&amp;lt;&amp;lt;EORSTE)|(1&amp;lt;&amp;lt;SOFE);		// Enable interrupts for EOR (End of Reset) and SOF (start of frame)&lt;br /&gt;
	UDCON = 0;							// enable attach resistor&lt;br /&gt;
	&lt;br /&gt;
	TX_RX_LED_INIT;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void USBDevice_::detach()&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//	Check for interrupts&lt;br /&gt;
//	TODO: VBUS detection&lt;br /&gt;
bool USBDevice_::configured()&lt;br /&gt;
{&lt;br /&gt;
	return _usbConfiguration;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void USBDevice_::poll()&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#endif /* if defined(USBCON) */&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>YWrobot CYB</name></author>	</entry>

	</feed>