slime@2
|
1 |
/*********************************************************************
|
slime@2
|
2 |
*
|
slime@2
|
3 |
* Microchip USB C18 Firmware - CDC Version 1.0
|
slime@2
|
4 |
*
|
slime@2
|
5 |
*********************************************************************
|
slime@2
|
6 |
* FileName: cdc.c
|
slime@2
|
7 |
* Dependencies: See INCLUDES section below
|
slime@2
|
8 |
* Processor: PIC18
|
slime@2
|
9 |
* Compiler: C18 2.30.01+
|
slime@2
|
10 |
* Company: Microchip Technology, Inc.
|
slime@2
|
11 |
*
|
slime@2
|
12 |
* Software License Agreement
|
slime@2
|
13 |
*
|
slime@2
|
14 |
* The software supplied herewith by Microchip Technology Incorporated
|
slime@2
|
15 |
* (the “Company”) for its PICmicro® Microcontroller is intended and
|
slime@2
|
16 |
* supplied to you, the Company’s customer, for use solely and
|
slime@2
|
17 |
* exclusively on Microchip PICmicro Microcontroller products. The
|
slime@2
|
18 |
* software is owned by the Company and/or its supplier, and is
|
slime@2
|
19 |
* protected under applicable copyright laws. All rights are reserved.
|
slime@2
|
20 |
* Any use in violation of the foregoing restrictions may subject the
|
slime@2
|
21 |
* user to criminal sanctions under applicable laws, as well as to
|
slime@2
|
22 |
* civil liability for the breach of the terms and conditions of this
|
slime@2
|
23 |
* license.
|
slime@2
|
24 |
*
|
slime@2
|
25 |
* THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
|
slime@2
|
26 |
* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
|
slime@2
|
27 |
* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
slime@2
|
28 |
* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
|
slime@2
|
29 |
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
|
slime@2
|
30 |
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
|
slime@2
|
31 |
*
|
slime@2
|
32 |
* Author Date Comment
|
slime@2
|
33 |
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
slime@2
|
34 |
* Rawin Rojvanit 11/19/04 Original. RS-232 Emulation Subset
|
slime@2
|
35 |
********************************************************************/
|
slime@2
|
36 |
|
slime@2
|
37 |
/** I N C L U D E S **********************************************************/
|
slime@2
|
38 |
#include <p18cxxx.h>
|
slime@2
|
39 |
#include "typedefs.h"
|
slime@2
|
40 |
#include "usb.h"
|
slime@2
|
41 |
|
slime@2
|
42 |
#ifdef USB_USE_CDC
|
slime@2
|
43 |
|
slime@2
|
44 |
/** V A R I A B L E S ********************************************************/
|
slime@2
|
45 |
#pragma udata
|
slime@2
|
46 |
byte cdc_rx_len; // total rx length
|
slime@2
|
47 |
|
slime@2
|
48 |
byte cdc_trf_state; // States are defined cdc.h
|
slime@2
|
49 |
POINTER pCDCSrc; // Dedicated source pointer
|
slime@2
|
50 |
POINTER pCDCDst; // Dedicated destination pointer
|
slime@2
|
51 |
byte cdc_tx_len; // total tx length
|
slime@2
|
52 |
byte cdc_mem_type; // _ROM, _RAM
|
slime@2
|
53 |
|
slime@2
|
54 |
LINE_CODING line_coding; // Buffer to store line coding information
|
slime@2
|
55 |
CONTROL_SIGNAL_BITMAP control_signal_bitmap;
|
slime@2
|
56 |
|
slime@2
|
57 |
/*
|
slime@2
|
58 |
* SEND_ENCAPSULATED_COMMAND and GET_ENCAPSULATED_RESPONSE are required
|
slime@2
|
59 |
* requests according to the CDC specification.
|
slime@2
|
60 |
* However, it is not really being used here, therefore a dummy buffer is
|
slime@2
|
61 |
* used for conformance.
|
slime@2
|
62 |
*/
|
slime@2
|
63 |
#define dummy_length 0x08
|
slime@2
|
64 |
byte dummy_encapsulated_cmd_response[dummy_length];
|
slime@2
|
65 |
|
slime@2
|
66 |
/** P R I V A T E P R O T O T Y P E S ***************************************/
|
slime@2
|
67 |
|
slime@2
|
68 |
/** D E C L A R A T I O N S **************************************************/
|
slime@2
|
69 |
#pragma code
|
slime@2
|
70 |
|
slime@2
|
71 |
/** C L A S S S P E C I F I C R E Q ****************************************/
|
slime@2
|
72 |
/******************************************************************************
|
slime@2
|
73 |
* Function: void USBCheckCDCRequest(void)
|
slime@2
|
74 |
*
|
slime@2
|
75 |
* PreCondition: None
|
slime@2
|
76 |
*
|
slime@2
|
77 |
* Input: None
|
slime@2
|
78 |
*
|
slime@2
|
79 |
* Output: None
|
slime@2
|
80 |
*
|
slime@2
|
81 |
* Side Effects: None
|
slime@2
|
82 |
*
|
slime@2
|
83 |
* Overview: This routine checks the setup data packet to see if it
|
slime@2
|
84 |
* knows how to handle it
|
slime@2
|
85 |
*
|
slime@2
|
86 |
* Note: None
|
slime@2
|
87 |
*****************************************************************************/
|
slime@2
|
88 |
void USBCheckCDCRequest(void)
|
slime@2
|
89 |
{
|
slime@2
|
90 |
/*
|
slime@2
|
91 |
* If request recipient is not an interface then return
|
slime@2
|
92 |
*/
|
slime@2
|
93 |
if(SetupPkt.Recipient != RCPT_INTF) return;
|
slime@2
|
94 |
|
slime@2
|
95 |
/*
|
slime@2
|
96 |
* If request type is not class-specific then return
|
slime@2
|
97 |
*/
|
slime@2
|
98 |
if(SetupPkt.RequestType != CLASS) return;
|
slime@2
|
99 |
|
slime@2
|
100 |
/*
|
slime@2
|
101 |
* Interface ID must match interface numbers associated with
|
slime@2
|
102 |
* CDC class, else return
|
slime@2
|
103 |
*/
|
slime@2
|
104 |
if((SetupPkt.bIntfID != CDC_COMM_INTF_ID)&&
|
slime@2
|
105 |
(SetupPkt.bIntfID != CDC_DATA_INTF_ID)) return;
|
slime@2
|
106 |
|
slime@2
|
107 |
switch(SetupPkt.bRequest)
|
slime@2
|
108 |
{
|
slime@2
|
109 |
case SEND_ENCAPSULATED_COMMAND:
|
slime@2
|
110 |
ctrl_trf_session_owner = MUID_CDC;
|
slime@2
|
111 |
pSrc.bRam = (byte*)&dummy_encapsulated_cmd_response;
|
slime@2
|
112 |
usb_stat.ctrl_trf_mem = _RAM;
|
slime@2
|
113 |
LSB(wCount) = dummy_length;
|
slime@2
|
114 |
break;
|
slime@2
|
115 |
case GET_ENCAPSULATED_RESPONSE:
|
slime@2
|
116 |
ctrl_trf_session_owner = MUID_CDC;
|
slime@2
|
117 |
// Populate dummy_encapsulated_cmd_response first.
|
slime@2
|
118 |
pDst.bRam = (byte*)&dummy_encapsulated_cmd_response;
|
slime@2
|
119 |
break;
|
slime@2
|
120 |
case SET_COMM_FEATURE: // Optional
|
slime@2
|
121 |
break;
|
slime@2
|
122 |
case GET_COMM_FEATURE: // Optional
|
slime@2
|
123 |
break;
|
slime@2
|
124 |
case CLEAR_COMM_FEATURE: // Optional
|
slime@2
|
125 |
break;
|
slime@2
|
126 |
case SET_LINE_CODING:
|
slime@2
|
127 |
ctrl_trf_session_owner = MUID_CDC;
|
slime@2
|
128 |
pDst.bRam = (byte*)&line_coding; // Set destination
|
slime@2
|
129 |
break;
|
slime@2
|
130 |
case GET_LINE_CODING:
|
slime@2
|
131 |
ctrl_trf_session_owner = MUID_CDC;
|
slime@2
|
132 |
pSrc.bRam = (byte*)&line_coding; // Set source
|
slime@2
|
133 |
usb_stat.ctrl_trf_mem = _RAM; // Set memory type
|
slime@2
|
134 |
LSB(wCount) = LINE_CODING_LENGTH; // Set data count
|
slime@2
|
135 |
break;
|
slime@2
|
136 |
case SET_CONTROL_LINE_STATE:
|
slime@2
|
137 |
ctrl_trf_session_owner = MUID_CDC;
|
slime@2
|
138 |
control_signal_bitmap._byte = LSB(SetupPkt.W_Value);
|
slime@2
|
139 |
break;
|
slime@2
|
140 |
case SEND_BREAK: // Optional
|
slime@2
|
141 |
break;
|
slime@2
|
142 |
default:
|
slime@2
|
143 |
break;
|
slime@2
|
144 |
}//end switch(SetupPkt.bRequest)
|
slime@2
|
145 |
|
slime@2
|
146 |
}//end USBCheckCDCRequest
|
slime@2
|
147 |
|
slime@2
|
148 |
/** U S E R A P I ***********************************************************/
|
slime@2
|
149 |
|
slime@2
|
150 |
/******************************************************************************
|
slime@2
|
151 |
* Function: void CDCInitEP(void)
|
slime@2
|
152 |
*
|
slime@2
|
153 |
* PreCondition: None
|
slime@2
|
154 |
*
|
slime@2
|
155 |
* Input: None
|
slime@2
|
156 |
*
|
slime@2
|
157 |
* Output: None
|
slime@2
|
158 |
*
|
slime@2
|
159 |
* Side Effects: None
|
slime@2
|
160 |
*
|
slime@2
|
161 |
* Overview: CDCInitEP initializes CDC endpoints, buffer descriptors,
|
slime@2
|
162 |
* internal state-machine, and variables.
|
slime@2
|
163 |
* It should be called after the USB host has sent out a
|
slime@2
|
164 |
* SET_CONFIGURATION request.
|
slime@2
|
165 |
* See USBStdSetCfgHandler() in usb9.c for examples.
|
slime@2
|
166 |
*
|
slime@2
|
167 |
* Note: None
|
slime@2
|
168 |
*****************************************************************************/
|
slime@2
|
169 |
void CDCInitEP(void)
|
slime@2
|
170 |
{
|
slime@2
|
171 |
//Abstract line coding information
|
slime@2
|
172 |
line_coding.dwDTERate._dword = 115200; // baud rate
|
slime@2
|
173 |
line_coding.bCharFormat = 0x00; // 1 stop bit
|
slime@2
|
174 |
line_coding.bParityType = 0x00; // None
|
slime@2
|
175 |
line_coding.bDataBits = 0x08; // 5,6,7,8, or 16
|
slime@2
|
176 |
|
slime@2
|
177 |
cdc_trf_state = CDC_TX_READY;
|
slime@2
|
178 |
cdc_rx_len = 0;
|
slime@2
|
179 |
|
slime@2
|
180 |
CDC_COMM_UEP = EP_IN|HSHK_EN; // Enable 1 Comm pipe
|
slime@2
|
181 |
CDC_DATA_UEP = EP_OUT_IN|HSHK_EN; // Enable 2 data pipes
|
slime@2
|
182 |
|
slime@2
|
183 |
/*
|
slime@2
|
184 |
* Do not have to init Cnt of IN pipes here.
|
slime@2
|
185 |
* Reason: Number of bytes to send to the host
|
slime@2
|
186 |
* varies from one transaction to
|
slime@2
|
187 |
* another. Cnt should equal the exact
|
slime@2
|
188 |
* number of bytes to transmit for
|
slime@2
|
189 |
* a given IN transaction.
|
slime@2
|
190 |
* This number of bytes will only
|
slime@2
|
191 |
* be known right before the data is
|
slime@2
|
192 |
* sent.
|
slime@2
|
193 |
*/
|
slime@2
|
194 |
CDC_INT_BD_IN.ADR = (byte*)&cdc_notice; // Set buffer address
|
slime@2
|
195 |
CDC_INT_BD_IN.Stat._byte = _UCPU|_DAT1; // Set status
|
slime@2
|
196 |
|
slime@2
|
197 |
CDC_BULK_BD_OUT.Cnt = sizeof(cdc_data_rx); // Set buffer size
|
slime@2
|
198 |
CDC_BULK_BD_OUT.ADR = (byte*)&cdc_data_rx; // Set buffer address
|
slime@2
|
199 |
CDC_BULK_BD_OUT.Stat._byte = _USIE|_DAT0|_DTSEN;// Set status
|
slime@2
|
200 |
|
slime@2
|
201 |
CDC_BULK_BD_IN.ADR = (byte*)&cdc_data_tx; // Set buffer size
|
slime@2
|
202 |
CDC_BULK_BD_IN.Stat._byte = _UCPU|_DAT1; // Set buffer address
|
slime@2
|
203 |
|
slime@2
|
204 |
}//end CDCInitEP
|
slime@2
|
205 |
|
slime@2
|
206 |
/******************************************************************************
|
slime@2
|
207 |
* Function: byte getsUSBUSART(char *buffer,
|
slime@2
|
208 |
* byte len)
|
slime@2
|
209 |
*
|
slime@2
|
210 |
* PreCondition: Value of input argument 'len' should be smaller than the
|
slime@2
|
211 |
* maximum endpoint size responsible for receiving bulk
|
slime@2
|
212 |
* data from USB host for CDC class.
|
slime@2
|
213 |
* Input argument 'buffer' should point to a buffer area that
|
slime@2
|
214 |
* is bigger or equal to the size specified by 'len'.
|
slime@2
|
215 |
*
|
slime@2
|
216 |
* Input: buffer : Pointer to where received bytes are to be stored
|
slime@2
|
217 |
* len : The number of bytes expected.
|
slime@2
|
218 |
*
|
slime@2
|
219 |
* Output: The number of bytes copied to buffer.
|
slime@2
|
220 |
*
|
slime@2
|
221 |
* Side Effects: Publicly accessible variable cdc_rx_len is updated with
|
slime@2
|
222 |
* the number of bytes copied to buffer.
|
slime@2
|
223 |
* Once getsUSBUSART is called, subsequent retrieval of
|
slime@2
|
224 |
* cdc_rx_len can be done by calling macro mCDCGetRxLength().
|
slime@2
|
225 |
*
|
slime@2
|
226 |
* Overview: getsUSBUSART copies a string of bytes received through
|
slime@2
|
227 |
* USB CDC Bulk OUT endpoint to a user's specified location.
|
slime@2
|
228 |
* It is a non-blocking function. It does not wait
|
slime@2
|
229 |
* for data if there is no data available. Instead it returns
|
slime@2
|
230 |
* '0' to notify the caller that there is no data available.
|
slime@2
|
231 |
*
|
slime@2
|
232 |
* Note: If the actual number of bytes received is larger than the
|
slime@2
|
233 |
* number of bytes expected (len), only the expected number
|
slime@2
|
234 |
* of bytes specified will be copied to buffer.
|
slime@2
|
235 |
* If the actual number of bytes received is smaller than the
|
slime@2
|
236 |
* number of bytes expected (len), only the actual number
|
slime@2
|
237 |
* of bytes received will be copied to buffer.
|
slime@2
|
238 |
*****************************************************************************/
|
slime@2
|
239 |
byte getsUSBUSART(char *buffer, byte len)
|
slime@2
|
240 |
{
|
slime@2
|
241 |
cdc_rx_len = 0;
|
slime@2
|
242 |
|
slime@2
|
243 |
if(!mCDCUsartRxIsBusy())
|
slime@2
|
244 |
{
|
slime@2
|
245 |
/*
|
slime@2
|
246 |
* Adjust the expected number of bytes to equal
|
slime@2
|
247 |
* the actual number of bytes received.
|
slime@2
|
248 |
*/
|
slime@2
|
249 |
if(len > CDC_BULK_BD_OUT.Cnt)
|
slime@2
|
250 |
len = CDC_BULK_BD_OUT.Cnt;
|
slime@2
|
251 |
|
slime@2
|
252 |
/*
|
slime@2
|
253 |
* Copy data from dual-ram buffer to user's buffer
|
slime@2
|
254 |
*/
|
slime@2
|
255 |
for(cdc_rx_len = 0; cdc_rx_len < len; cdc_rx_len++)
|
slime@2
|
256 |
buffer[cdc_rx_len] = cdc_data_rx[cdc_rx_len];
|
slime@2
|
257 |
|
slime@2
|
258 |
/*
|
slime@2
|
259 |
* Prepare dual-ram buffer for next OUT transaction
|
slime@2
|
260 |
*/
|
slime@2
|
261 |
CDC_BULK_BD_OUT.Cnt = sizeof(cdc_data_rx);
|
slime@2
|
262 |
mUSBBufferReady(CDC_BULK_BD_OUT);
|
slime@2
|
263 |
}//end if
|
slime@2
|
264 |
|
slime@2
|
265 |
return cdc_rx_len;
|
slime@2
|
266 |
|
slime@2
|
267 |
}//end getsUSBUSART
|
slime@2
|
268 |
|
slime@2
|
269 |
/******************************************************************************
|
slime@2
|
270 |
* Function: void putsUSBUSART(char *data)
|
slime@2
|
271 |
*
|
slime@2
|
272 |
* PreCondition: cdc_trf_state must be in the CDC_TX_READY state.
|
slime@2
|
273 |
*
|
slime@2
|
274 |
* The string of characters pointed to by 'data' must equal
|
slime@2
|
275 |
* to or smaller than 255 bytes.
|
slime@2
|
276 |
*
|
slime@2
|
277 |
* Input: data : Pointer to a null-terminated string of data.
|
slime@2
|
278 |
* If a null character is not found, 255 bytes
|
slime@2
|
279 |
* of data will be transferred to the host.
|
slime@2
|
280 |
*
|
slime@2
|
281 |
* Output: None
|
slime@2
|
282 |
*
|
slime@2
|
283 |
* Side Effects: None
|
slime@2
|
284 |
*
|
slime@2
|
285 |
* Overview: putsUSBUSART writes a string of data to the USB including
|
slime@2
|
286 |
* the null character. Use this version, 'puts', to transfer
|
slime@2
|
287 |
* data located in data memory.
|
slime@2
|
288 |
*
|
slime@2
|
289 |
* Note: The transfer mechanism for device-to-host(put) is more
|
slime@2
|
290 |
* flexible than host-to-device(get). It can handle
|
slime@2
|
291 |
* a string of data larger than the maximum size of bulk IN
|
slime@2
|
292 |
* endpoint. A state machine is used to transfer a long
|
slime@2
|
293 |
* string of data over multiple USB transactions.
|
slime@2
|
294 |
* See CDCTxService() for more details.
|
slime@2
|
295 |
*****************************************************************************/
|
slime@2
|
296 |
void putsUSBUSART(char *data)
|
slime@2
|
297 |
{
|
slime@2
|
298 |
byte len;
|
slime@2
|
299 |
|
slime@2
|
300 |
/*
|
slime@2
|
301 |
* User should have checked that cdc_trf_state is in CDC_TX_READY state
|
slime@2
|
302 |
* before calling this function.
|
slime@2
|
303 |
* As a safety precaution, this fuction checks the state one more time
|
slime@2
|
304 |
* to make sure it does not override any pending transactions.
|
slime@2
|
305 |
*
|
slime@2
|
306 |
* Currently it just quits the routine without reporting any errors back
|
slime@2
|
307 |
* to the user.
|
slime@2
|
308 |
*
|
slime@2
|
309 |
* Bottomline: User MUST make sure that mUSBUSARTIsTxTrfReady()==1
|
slime@2
|
310 |
* before calling this function!
|
slime@2
|
311 |
* Example:
|
slime@2
|
312 |
* if(mUSBUSARTIsTxTrfReady())
|
slime@2
|
313 |
* putsUSBUSART(pData);
|
slime@2
|
314 |
*
|
slime@2
|
315 |
* IMPORTANT: Never use the following blocking while loop to wait:
|
slime@2
|
316 |
* while(!mUSBUSARTIsTxTrfReady())
|
slime@2
|
317 |
* putsUSBUSART(pData);
|
slime@2
|
318 |
*
|
slime@2
|
319 |
* The whole firmware framework is written based on cooperative
|
slime@2
|
320 |
* multi-tasking and a blocking code is not acceptable.
|
slime@2
|
321 |
* Use a state machine instead.
|
slime@2
|
322 |
*/
|
slime@2
|
323 |
if(cdc_trf_state != CDC_TX_READY) return;
|
slime@2
|
324 |
|
slime@2
|
325 |
/*
|
slime@2
|
326 |
* While loop counts the number of bytes to send including the
|
slime@2
|
327 |
* null character.
|
slime@2
|
328 |
*/
|
slime@2
|
329 |
len = 0;
|
slime@2
|
330 |
do
|
slime@2
|
331 |
{
|
slime@2
|
332 |
len++;
|
slime@2
|
333 |
if(len == 255) break; // Break loop once max len is reached.
|
slime@2
|
334 |
}while(*data++);
|
slime@2
|
335 |
|
slime@2
|
336 |
/*
|
slime@2
|
337 |
* Re-adjust pointer to its initial location
|
slime@2
|
338 |
*/
|
slime@2
|
339 |
data-=len;
|
slime@2
|
340 |
|
slime@2
|
341 |
/*
|
slime@2
|
342 |
* Second piece of information (length of data to send) is ready.
|
slime@2
|
343 |
* Call mUSBUSARTTxRam to setup the transfer.
|
slime@2
|
344 |
* The actual transfer process will be handled by CDCTxService(),
|
slime@2
|
345 |
* which should be called once per Main Program loop.
|
slime@2
|
346 |
*/
|
slime@2
|
347 |
mUSBUSARTTxRam((byte*)data,len); // See cdc.h
|
slime@2
|
348 |
}//end putsUSBUSART
|
slime@2
|
349 |
|
slime@2
|
350 |
/******************************************************************************
|
slime@2
|
351 |
* Function: void putrsUSBUSART(const rom char *data)
|
slime@2
|
352 |
*
|
slime@2
|
353 |
* PreCondition: cdc_trf_state must be in the CDC_TX_READY state.
|
slime@2
|
354 |
*
|
slime@2
|
355 |
* The string of characters pointed to by 'data' must equal
|
slime@2
|
356 |
* to or smaller than 255 bytes.
|
slime@2
|
357 |
*
|
slime@2
|
358 |
* Input: data : Pointer to a null-terminated string of data.
|
slime@2
|
359 |
* If a null character is not found, 255 bytes
|
slime@2
|
360 |
* of data will be transferred to the host.
|
slime@2
|
361 |
*
|
slime@2
|
362 |
* Output: None
|
slime@2
|
363 |
*
|
slime@2
|
364 |
* Side Effects: None
|
slime@2
|
365 |
*
|
slime@2
|
366 |
* Overview: putrsUSBUSART writes a string of data to the USB including
|
slime@2
|
367 |
* the null character. Use this version, 'putrs', to transfer
|
slime@2
|
368 |
* data literals and data located in program memory.
|
slime@2
|
369 |
*
|
slime@2
|
370 |
* Note: The transfer mechanism for device-to-host(put) is more
|
slime@2
|
371 |
* flexible than host-to-device(get). It can handle
|
slime@2
|
372 |
* a string of data larger than the maximum size of bulk IN
|
slime@2
|
373 |
* endpoint. A state machine is used to transfer a long
|
slime@2
|
374 |
* string of data over multiple USB transactions.
|
slime@2
|
375 |
* See CDCTxService() for more details.
|
slime@2
|
376 |
*****************************************************************************/
|
slime@2
|
377 |
void putrsUSBUSART(const rom char *data)
|
slime@2
|
378 |
{
|
slime@2
|
379 |
byte len;
|
slime@2
|
380 |
|
slime@2
|
381 |
/*
|
slime@2
|
382 |
* User should have checked that cdc_trf_state is in CDC_TX_READY state
|
slime@2
|
383 |
* before calling this function.
|
slime@2
|
384 |
* As a safety precaution, this fuction checks the state one more time
|
slime@2
|
385 |
* to make sure it does not override any pending transactions.
|
slime@2
|
386 |
*
|
slime@2
|
387 |
* Currently it just quits the routine without reporting any errors back
|
slime@2
|
388 |
* to the user.
|
slime@2
|
389 |
*
|
slime@2
|
390 |
* Bottomline: User MUST make sure that mUSBUSARTIsTxTrfReady()
|
slime@2
|
391 |
* before calling this function!
|
slime@2
|
392 |
* Example:
|
slime@2
|
393 |
* if(mUSBUSARTIsTxTrfReady())
|
slime@2
|
394 |
* putsUSBUSART(pData);
|
slime@2
|
395 |
*
|
slime@2
|
396 |
* IMPORTANT: Never use the following blocking while loop to wait:
|
slime@2
|
397 |
* while(cdc_trf_state != CDC_TX_READY)
|
slime@2
|
398 |
* putsUSBUSART(pData);
|
slime@2
|
399 |
*
|
slime@2
|
400 |
* The whole firmware framework is written based on cooperative
|
slime@2
|
401 |
* multi-tasking and a blocking code is not acceptable.
|
slime@2
|
402 |
* Use a state machine instead.
|
slime@2
|
403 |
*/
|
slime@2
|
404 |
if(cdc_trf_state != CDC_TX_READY) return;
|
slime@2
|
405 |
|
slime@2
|
406 |
/*
|
slime@2
|
407 |
* While loop counts the number of bytes to send including the
|
slime@2
|
408 |
* null character.
|
slime@2
|
409 |
*/
|
slime@2
|
410 |
len = 0;
|
slime@2
|
411 |
do
|
slime@2
|
412 |
{
|
slime@2
|
413 |
len++;
|
slime@2
|
414 |
if(len == 255) break; // Break loop once max len is reached.
|
slime@2
|
415 |
}while(*data++);
|
slime@2
|
416 |
|
slime@2
|
417 |
/*
|
slime@2
|
418 |
* Re-adjust pointer to its initial location
|
slime@2
|
419 |
*/
|
slime@2
|
420 |
data-=len;
|
slime@2
|
421 |
|
slime@2
|
422 |
/*
|
slime@2
|
423 |
* Second piece of information (length of data to send) is ready.
|
slime@2
|
424 |
* Call mUSBUSARTTxRom to setup the transfer.
|
slime@2
|
425 |
* The actual transfer process will be handled by CDCTxService(),
|
slime@2
|
426 |
* which should be called once per Main Program loop.
|
slime@2
|
427 |
*/
|
slime@2
|
428 |
mUSBUSARTTxRom((rom byte*)data,len); // See cdc.h
|
slime@2
|
429 |
|
slime@2
|
430 |
}//end putrsUSBUSART
|
slime@2
|
431 |
|
slime@2
|
432 |
/******************************************************************************
|
slime@2
|
433 |
* Function: void CDCTxService(void)
|
slime@2
|
434 |
*
|
slime@2
|
435 |
* PreCondition: None
|
slime@2
|
436 |
*
|
slime@2
|
437 |
* Input: None
|
slime@2
|
438 |
*
|
slime@2
|
439 |
* Output: None
|
slime@2
|
440 |
*
|
slime@2
|
441 |
* Side Effects: None
|
slime@2
|
442 |
*
|
slime@2
|
443 |
* Overview: CDCTxService handles device-to-host transaction(s).
|
slime@2
|
444 |
* This function should be called once per Main Program loop.
|
slime@2
|
445 |
*
|
slime@2
|
446 |
* Note: None
|
slime@2
|
447 |
*****************************************************************************/
|
slime@2
|
448 |
void CDCTxService(void)
|
slime@2
|
449 |
{
|
slime@2
|
450 |
byte byte_to_send;
|
slime@2
|
451 |
|
slime@2
|
452 |
if(mCDCUsartTxIsBusy()) return;
|
slime@2
|
453 |
/*
|
slime@2
|
454 |
* Completing stage is necessary while [ mCDCUSartTxIsBusy()==1 ].
|
slime@2
|
455 |
* By having this stage, user can always check cdc_trf_state,
|
slime@2
|
456 |
* and not having to call mCDCUsartTxIsBusy() directly.
|
slime@2
|
457 |
*/
|
slime@2
|
458 |
if(cdc_trf_state == CDC_TX_COMPLETING)
|
slime@2
|
459 |
cdc_trf_state = CDC_TX_READY;
|
slime@2
|
460 |
|
slime@2
|
461 |
/*
|
slime@2
|
462 |
* If CDC_TX_READY state, nothing to do, just return.
|
slime@2
|
463 |
*/
|
slime@2
|
464 |
if(cdc_trf_state == CDC_TX_READY) return;
|
slime@2
|
465 |
|
slime@2
|
466 |
/*
|
slime@2
|
467 |
* If CDC_TX_BUSY_ZLP state, send zero length packet
|
slime@2
|
468 |
*/
|
slime@2
|
469 |
if(cdc_trf_state == CDC_TX_BUSY_ZLP)
|
slime@2
|
470 |
{
|
slime@2
|
471 |
CDC_BULK_BD_IN.Cnt = 0;
|
slime@2
|
472 |
cdc_trf_state = CDC_TX_COMPLETING;
|
slime@2
|
473 |
}
|
slime@2
|
474 |
else if(cdc_trf_state == CDC_TX_BUSY)
|
slime@2
|
475 |
{
|
slime@2
|
476 |
/*
|
slime@2
|
477 |
* First, have to figure out how many byte of data to send.
|
slime@2
|
478 |
*/
|
slime@2
|
479 |
if(cdc_tx_len > sizeof(cdc_data_tx))
|
slime@2
|
480 |
byte_to_send = sizeof(cdc_data_tx);
|
slime@2
|
481 |
else
|
slime@2
|
482 |
byte_to_send = cdc_tx_len;
|
slime@2
|
483 |
|
slime@2
|
484 |
/*
|
slime@2
|
485 |
* Next, load the number of bytes to send to Cnt in buffer descriptor
|
slime@2
|
486 |
*/
|
slime@2
|
487 |
CDC_BULK_BD_IN.Cnt = byte_to_send;
|
slime@2
|
488 |
|
slime@2
|
489 |
/*
|
slime@2
|
490 |
* Subtract the number of bytes just about to be sent from the total.
|
slime@2
|
491 |
*/
|
slime@2
|
492 |
cdc_tx_len = cdc_tx_len - byte_to_send;
|
slime@2
|
493 |
|
slime@2
|
494 |
pCDCDst.bRam = (byte*)&cdc_data_tx; // Set destination pointer
|
slime@2
|
495 |
|
slime@2
|
496 |
if(cdc_mem_type == _ROM) // Determine type of memory source
|
slime@2
|
497 |
{
|
slime@2
|
498 |
while(byte_to_send)
|
slime@2
|
499 |
{
|
slime@2
|
500 |
*pCDCDst.bRam = *pCDCSrc.bRom;
|
slime@2
|
501 |
pCDCDst.bRam++;
|
slime@2
|
502 |
pCDCSrc.bRom++;
|
slime@2
|
503 |
byte_to_send--;
|
slime@2
|
504 |
}//end while(byte_to_send)
|
slime@2
|
505 |
}
|
slime@2
|
506 |
else // _RAM
|
slime@2
|
507 |
{
|
slime@2
|
508 |
while(byte_to_send)
|
slime@2
|
509 |
{
|
slime@2
|
510 |
*pCDCDst.bRam = *pCDCSrc.bRam;
|
slime@2
|
511 |
pCDCDst.bRam++;
|
slime@2
|
512 |
pCDCSrc.bRam++;
|
slime@2
|
513 |
byte_to_send--;
|
slime@2
|
514 |
}//end while(byte_to_send._word)
|
slime@2
|
515 |
}//end if(cdc_mem_type...)
|
slime@2
|
516 |
|
slime@2
|
517 |
/*
|
slime@2
|
518 |
* Lastly, determine if a zero length packet state is necessary.
|
slime@2
|
519 |
* See explanation in USB Specification 2.0: Section 5.8.3
|
slime@2
|
520 |
*/
|
slime@2
|
521 |
if(cdc_tx_len == 0)
|
slime@2
|
522 |
{
|
slime@2
|
523 |
if(CDC_BULK_BD_IN.Cnt == sizeof(cdc_data_tx))
|
slime@2
|
524 |
cdc_trf_state = CDC_TX_BUSY_ZLP;
|
slime@2
|
525 |
else
|
slime@2
|
526 |
cdc_trf_state = CDC_TX_COMPLETING;
|
slime@2
|
527 |
}//end if(cdc_tx_len...)
|
slime@2
|
528 |
|
slime@2
|
529 |
}//end if(cdc_tx_sate == CDC_TX_BUSY)
|
slime@2
|
530 |
|
slime@2
|
531 |
/*
|
slime@2
|
532 |
* Both CDC_TX_BUSY and CDC_TX_BUSY_ZLP states use the following macro
|
slime@2
|
533 |
*/
|
slime@2
|
534 |
mUSBBufferReady(CDC_BULK_BD_IN);
|
slime@2
|
535 |
|
slime@2
|
536 |
}//end CDCTxService
|
slime@2
|
537 |
|
slime@2
|
538 |
#endif //USB_USE_CDC
|
slime@2
|
539 |
|
slime@2
|
540 |
/** EOF cdc.c ****************************************************************/
|