Project

General

Profile

Statistics
| Branch: | Revision:

root / arduino-1.0 / hardware / arduino / cores / arduino / CDC.cpp @ 58d82c77

History | View | Annotate | Download (4.37 KB)

1

    
2

    
3
/* Copyright (c) 2011, Peter Barrett  
4
**  
5
** Permission to use, copy, modify, and/or distribute this software for  
6
** any purpose with or without fee is hereby granted, provided that the  
7
** above copyright notice and this permission notice appear in all copies.  
8
** 
9
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL  
10
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED  
11
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR  
12
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES  
13
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,  
14
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  
15
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS  
16
** SOFTWARE.  
17
*/
18

    
19
#include "Platform.h"
20
#include "USBAPI.h"
21
#include <avr/wdt.h>
22

    
23
#if defined(USBCON)
24
#ifdef CDC_ENABLED
25

    
26
void Reboot()
27
{
28
        USB.detach();
29
        cli();
30
        asm volatile("jmp 0x7800");                // jump to bootloader - DiskLoader takes up last 2 kB
31
}
32

    
33
typedef struct
34
{
35
        u32        dwDTERate;
36
        u8        bCharFormat;
37
        u8         bParityType;
38
        u8         bDataBits;
39
        u8        lineState;
40
} LineInfo;
41

    
42
static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 };
43

    
44
#define WEAK __attribute__ ((weak))
45

    
46
extern const CDCDescriptor _cdcInterface PROGMEM;
47
const CDCDescriptor _cdcInterface =
48
{
49
        D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1),
50

    
51
        //        CDC communication interface
52
        D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0),
53
        D_CDCCS(CDC_HEADER,0x10,0x01),                                                                // Header (1.10 bcd)
54
        D_CDCCS(CDC_CALL_MANAGEMENT,1,1),                                                        // Device handles call management (not)
55
        D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,6),                                // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
56
        D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE),        // Communication interface is master, data interface is slave 0
57
        D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10,0x40),
58

    
59
        //        CDC data interface
60
        D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0),
61
        D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,0x40,0),
62
        D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40,0)
63
};
64

    
65
int WEAK CDC_GetInterface(u8* interfaceNum)
66
{
67
        interfaceNum[0] += 2;        // uses 2
68
        return USB_SendControl(TRANSFER_PGM,&_cdcInterface,sizeof(_cdcInterface));
69
}
70

    
71
bool WEAK CDC_Setup(Setup& setup)
72
{
73
        u8 r = setup.bRequest;
74
        u8 requestType = setup.bmRequestType;
75

    
76
        if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
77
        {
78
                if (CDC_GET_LINE_CODING == r)
79
                {
80
                        USB_SendControl(0,(void*)&_usbLineInfo,7);
81
                        return true;
82
                }
83
        }
84

    
85
        if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
86
        {
87
                if (CDC_SET_LINE_CODING == r)
88
                {
89
                        USB_RecvControl((void*)&_usbLineInfo,7);
90
                        return true;
91
                }
92

    
93
                if (CDC_SET_CONTROL_LINE_STATE == r)
94
                {
95
                        if (0 != _usbLineInfo.lineState && 1200 == _usbLineInfo.dwDTERate)        // auto-reset is triggered when the port, already open at 1200 bps, is closed
96
                                Reboot();
97
                        _usbLineInfo.lineState = setup.wValueL;
98
                        return true;
99
                }
100
        }
101
        return false;
102
}
103

    
104

    
105
int _serialPeek = -1;
106
void Serial_::begin(uint16_t baud_count)
107
{
108
}
109

    
110
void Serial_::end(void)
111
{
112
}
113

    
114
int Serial_::available(void)
115
{
116
        u8 avail = USB_Available(CDC_RX);
117
        if (_serialPeek != -1)
118
                avail++;
119
        return avail;
120
}
121

    
122
//        peek is nasty
123
int Serial_::peek(void)
124
{
125
        if (_serialPeek == -1)
126
                _serialPeek = read();
127
        return _serialPeek;
128
}
129

    
130
int Serial_::read(void)
131
{
132
        int c;
133
        if (_serialPeek != -1)
134
        {
135
                c = _serialPeek;
136
                _serialPeek = -1;
137
        } else {
138
                c = USB_Recv(CDC_RX);
139
        }
140
        return c;
141
}
142

    
143
void Serial_::flush(void)
144
{
145
        USB_Flush(CDC_TX);
146
}
147

    
148
size_t Serial_::write(uint8_t c)
149
{
150
        /* only try to send bytes if the high-level CDC connection itself 
151
         is open (not just the pipe) - the OS should set lineState when the port
152
         is opened and clear lineState when the port is closed.
153
         bytes sent before the user opens the connection or after
154
         the connection is closed are lost - just like with a UART. */
155
        
156
        // TODO - ZE - check behavior on different OSes and test what happens if an
157
        // open connection isn't broken cleanly (cable is yanked out, host dies
158
        // or locks up, or host virtual serial port hangs)
159
        if (_usbLineInfo.lineState > 0)        {
160
                int r = USB_Send(CDC_TX,&c,1);
161
                if (r > 0) {
162
                        return r;
163
                } else {
164
                        setWriteError();
165
                        return 0;
166
                }
167
        }
168
        setWriteError();
169
        return 0;
170
}
171

    
172
Serial_ Serial;
173

    
174
#endif
175
#endif /* if defined(USBCON) */