1 /*********************************************************************
3 * Microchip USB C18 Firmware - CDC Version 1.0
5 *********************************************************************
7 * Dependencies: See INCLUDES section below
9 * Compiler: C18 2.30.01+
10 * Company: Microchip Technology, Inc.
12 * Software License Agreement
14 * The software supplied herewith by Microchip Technology Incorporated
15 * (the “Company”) for its PICmicro® Microcontroller is intended and
16 * supplied to you, the Company’s customer, for use solely and
17 * exclusively on Microchip PICmicro Microcontroller products. The
18 * software is owned by the Company and/or its supplier, and is
19 * protected under applicable copyright laws. All rights are reserved.
20 * Any use in violation of the foregoing restrictions may subject the
21 * user to criminal sanctions under applicable laws, as well as to
22 * civil liability for the breach of the terms and conditions of this
25 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
26 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
27 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
28 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
29 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
30 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
33 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
34 * Rawin Rojvanit 11/19/04 Original. RS-232 Emulation Subset
35 ********************************************************************/
37 /** I N C L U D E S **********************************************************/
44 /** V A R I A B L E S ********************************************************/
46 byte cdc_rx_len; // total rx length
48 byte cdc_trf_state; // States are defined cdc.h
49 POINTER pCDCSrc; // Dedicated source pointer
50 POINTER pCDCDst; // Dedicated destination pointer
51 byte cdc_tx_len; // total tx length
52 byte cdc_mem_type; // _ROM, _RAM
54 LINE_CODING line_coding; // Buffer to store line coding information
55 CONTROL_SIGNAL_BITMAP control_signal_bitmap;
58 * SEND_ENCAPSULATED_COMMAND and GET_ENCAPSULATED_RESPONSE are required
59 * requests according to the CDC specification.
60 * However, it is not really being used here, therefore a dummy buffer is
61 * used for conformance.
63 #define dummy_length 0x08
64 byte dummy_encapsulated_cmd_response[dummy_length];
66 /** P R I V A T E P R O T O T Y P E S ***************************************/
68 /** D E C L A R A T I O N S **************************************************/
71 /** C L A S S S P E C I F I C R E Q ****************************************/
72 /******************************************************************************
73 * Function: void USBCheckCDCRequest(void)
83 * Overview: This routine checks the setup data packet to see if it
84 * knows how to handle it
87 *****************************************************************************/
88 void USBCheckCDCRequest(void)
91 * If request recipient is not an interface then return
93 if(SetupPkt.Recipient != RCPT_INTF) return;
96 * If request type is not class-specific then return
98 if(SetupPkt.RequestType != CLASS) return;
101 * Interface ID must match interface numbers associated with
102 * CDC class, else return
104 if((SetupPkt.bIntfID != CDC_COMM_INTF_ID)&&
105 (SetupPkt.bIntfID != CDC_DATA_INTF_ID)) return;
107 switch(SetupPkt.bRequest)
109 case SEND_ENCAPSULATED_COMMAND:
110 ctrl_trf_session_owner = MUID_CDC;
111 pSrc.bRam = (byte*)&dummy_encapsulated_cmd_response;
112 usb_stat.ctrl_trf_mem = _RAM;
113 LSB(wCount) = dummy_length;
115 case GET_ENCAPSULATED_RESPONSE:
116 ctrl_trf_session_owner = MUID_CDC;
117 // Populate dummy_encapsulated_cmd_response first.
118 pDst.bRam = (byte*)&dummy_encapsulated_cmd_response;
120 case SET_COMM_FEATURE: // Optional
122 case GET_COMM_FEATURE: // Optional
124 case CLEAR_COMM_FEATURE: // Optional
126 case SET_LINE_CODING:
127 ctrl_trf_session_owner = MUID_CDC;
128 pDst.bRam = (byte*)&line_coding; // Set destination
130 case GET_LINE_CODING:
131 ctrl_trf_session_owner = MUID_CDC;
132 pSrc.bRam = (byte*)&line_coding; // Set source
133 usb_stat.ctrl_trf_mem = _RAM; // Set memory type
134 LSB(wCount) = LINE_CODING_LENGTH; // Set data count
136 case SET_CONTROL_LINE_STATE:
137 ctrl_trf_session_owner = MUID_CDC;
138 control_signal_bitmap._byte = LSB(SetupPkt.W_Value);
140 case SEND_BREAK: // Optional
144 }//end switch(SetupPkt.bRequest)
146 }//end USBCheckCDCRequest
148 /** U S E R A P I ***********************************************************/
150 /******************************************************************************
151 * Function: void CDCInitEP(void)
161 * Overview: CDCInitEP initializes CDC endpoints, buffer descriptors,
162 * internal state-machine, and variables.
163 * It should be called after the USB host has sent out a
164 * SET_CONFIGURATION request.
165 * See USBStdSetCfgHandler() in usb9.c for examples.
168 *****************************************************************************/
171 //Abstract line coding information
172 line_coding.dwDTERate._dword = 115200; // baud rate
173 line_coding.bCharFormat = 0x00; // 1 stop bit
174 line_coding.bParityType = 0x00; // None
175 line_coding.bDataBits = 0x08; // 5,6,7,8, or 16
177 cdc_trf_state = CDC_TX_READY;
180 CDC_COMM_UEP = EP_IN|HSHK_EN; // Enable 1 Comm pipe
181 CDC_DATA_UEP = EP_OUT_IN|HSHK_EN; // Enable 2 data pipes
184 * Do not have to init Cnt of IN pipes here.
185 * Reason: Number of bytes to send to the host
186 * varies from one transaction to
187 * another. Cnt should equal the exact
188 * number of bytes to transmit for
189 * a given IN transaction.
190 * This number of bytes will only
191 * be known right before the data is
194 CDC_INT_BD_IN.ADR = (byte*)&cdc_notice; // Set buffer address
195 CDC_INT_BD_IN.Stat._byte = _UCPU|_DAT1; // Set status
197 CDC_BULK_BD_OUT.Cnt = sizeof(cdc_data_rx); // Set buffer size
198 CDC_BULK_BD_OUT.ADR = (byte*)&cdc_data_rx; // Set buffer address
199 CDC_BULK_BD_OUT.Stat._byte = _USIE|_DAT0|_DTSEN;// Set status
201 CDC_BULK_BD_IN.ADR = (byte*)&cdc_data_tx; // Set buffer size
202 CDC_BULK_BD_IN.Stat._byte = _UCPU|_DAT1; // Set buffer address
206 /******************************************************************************
207 * Function: byte getsUSBUSART(char *buffer,
210 * PreCondition: Value of input argument 'len' should be smaller than the
211 * maximum endpoint size responsible for receiving bulk
212 * data from USB host for CDC class.
213 * Input argument 'buffer' should point to a buffer area that
214 * is bigger or equal to the size specified by 'len'.
216 * Input: buffer : Pointer to where received bytes are to be stored
217 * len : The number of bytes expected.
219 * Output: The number of bytes copied to buffer.
221 * Side Effects: Publicly accessible variable cdc_rx_len is updated with
222 * the number of bytes copied to buffer.
223 * Once getsUSBUSART is called, subsequent retrieval of
224 * cdc_rx_len can be done by calling macro mCDCGetRxLength().
226 * Overview: getsUSBUSART copies a string of bytes received through
227 * USB CDC Bulk OUT endpoint to a user's specified location.
228 * It is a non-blocking function. It does not wait
229 * for data if there is no data available. Instead it returns
230 * '0' to notify the caller that there is no data available.
232 * Note: If the actual number of bytes received is larger than the
233 * number of bytes expected (len), only the expected number
234 * of bytes specified will be copied to buffer.
235 * If the actual number of bytes received is smaller than the
236 * number of bytes expected (len), only the actual number
237 * of bytes received will be copied to buffer.
238 *****************************************************************************/
239 byte getsUSBUSART(char *buffer, byte len)
243 if(!mCDCUsartRxIsBusy())
246 * Adjust the expected number of bytes to equal
247 * the actual number of bytes received.
249 if(len > CDC_BULK_BD_OUT.Cnt)
250 len = CDC_BULK_BD_OUT.Cnt;
253 * Copy data from dual-ram buffer to user's buffer
255 for(cdc_rx_len = 0; cdc_rx_len < len; cdc_rx_len++)
256 buffer[cdc_rx_len] = cdc_data_rx[cdc_rx_len];
259 * Prepare dual-ram buffer for next OUT transaction
261 CDC_BULK_BD_OUT.Cnt = sizeof(cdc_data_rx);
262 mUSBBufferReady(CDC_BULK_BD_OUT);
269 /******************************************************************************
270 * Function: void putsUSBUSART(char *data)
272 * PreCondition: cdc_trf_state must be in the CDC_TX_READY state.
274 * The string of characters pointed to by 'data' must equal
275 * to or smaller than 255 bytes.
277 * Input: data : Pointer to a null-terminated string of data.
278 * If a null character is not found, 255 bytes
279 * of data will be transferred to the host.
285 * Overview: putsUSBUSART writes a string of data to the USB including
286 * the null character. Use this version, 'puts', to transfer
287 * data located in data memory.
289 * Note: The transfer mechanism for device-to-host(put) is more
290 * flexible than host-to-device(get). It can handle
291 * a string of data larger than the maximum size of bulk IN
292 * endpoint. A state machine is used to transfer a long
293 * string of data over multiple USB transactions.
294 * See CDCTxService() for more details.
295 *****************************************************************************/
296 void putsUSBUSART(char *data)
301 * User should have checked that cdc_trf_state is in CDC_TX_READY state
302 * before calling this function.
303 * As a safety precaution, this fuction checks the state one more time
304 * to make sure it does not override any pending transactions.
306 * Currently it just quits the routine without reporting any errors back
309 * Bottomline: User MUST make sure that mUSBUSARTIsTxTrfReady()==1
310 * before calling this function!
312 * if(mUSBUSARTIsTxTrfReady())
313 * putsUSBUSART(pData);
315 * IMPORTANT: Never use the following blocking while loop to wait:
316 * while(!mUSBUSARTIsTxTrfReady())
317 * putsUSBUSART(pData);
319 * The whole firmware framework is written based on cooperative
320 * multi-tasking and a blocking code is not acceptable.
321 * Use a state machine instead.
323 if(cdc_trf_state != CDC_TX_READY) return;
326 * While loop counts the number of bytes to send including the
333 if(len == 255) break; // Break loop once max len is reached.
337 * Re-adjust pointer to its initial location
342 * Second piece of information (length of data to send) is ready.
343 * Call mUSBUSARTTxRam to setup the transfer.
344 * The actual transfer process will be handled by CDCTxService(),
345 * which should be called once per Main Program loop.
347 mUSBUSARTTxRam((byte*)data,len); // See cdc.h
350 /******************************************************************************
351 * Function: void putrsUSBUSART(const rom char *data)
353 * PreCondition: cdc_trf_state must be in the CDC_TX_READY state.
355 * The string of characters pointed to by 'data' must equal
356 * to or smaller than 255 bytes.
358 * Input: data : Pointer to a null-terminated string of data.
359 * If a null character is not found, 255 bytes
360 * of data will be transferred to the host.
366 * Overview: putrsUSBUSART writes a string of data to the USB including
367 * the null character. Use this version, 'putrs', to transfer
368 * data literals and data located in program memory.
370 * Note: The transfer mechanism for device-to-host(put) is more
371 * flexible than host-to-device(get). It can handle
372 * a string of data larger than the maximum size of bulk IN
373 * endpoint. A state machine is used to transfer a long
374 * string of data over multiple USB transactions.
375 * See CDCTxService() for more details.
376 *****************************************************************************/
377 void putrsUSBUSART(const rom char *data)
382 * User should have checked that cdc_trf_state is in CDC_TX_READY state
383 * before calling this function.
384 * As a safety precaution, this fuction checks the state one more time
385 * to make sure it does not override any pending transactions.
387 * Currently it just quits the routine without reporting any errors back
390 * Bottomline: User MUST make sure that mUSBUSARTIsTxTrfReady()
391 * before calling this function!
393 * if(mUSBUSARTIsTxTrfReady())
394 * putsUSBUSART(pData);
396 * IMPORTANT: Never use the following blocking while loop to wait:
397 * while(cdc_trf_state != CDC_TX_READY)
398 * putsUSBUSART(pData);
400 * The whole firmware framework is written based on cooperative
401 * multi-tasking and a blocking code is not acceptable.
402 * Use a state machine instead.
404 if(cdc_trf_state != CDC_TX_READY) return;
407 * While loop counts the number of bytes to send including the
414 if(len == 255) break; // Break loop once max len is reached.
418 * Re-adjust pointer to its initial location
423 * Second piece of information (length of data to send) is ready.
424 * Call mUSBUSARTTxRom to setup the transfer.
425 * The actual transfer process will be handled by CDCTxService(),
426 * which should be called once per Main Program loop.
428 mUSBUSARTTxRom((rom byte*)data,len); // See cdc.h
432 /******************************************************************************
433 * Function: void CDCTxService(void)
443 * Overview: CDCTxService handles device-to-host transaction(s).
444 * This function should be called once per Main Program loop.
447 *****************************************************************************/
448 void CDCTxService(void)
452 if(mCDCUsartTxIsBusy()) return;
454 * Completing stage is necessary while [ mCDCUSartTxIsBusy()==1 ].
455 * By having this stage, user can always check cdc_trf_state,
456 * and not having to call mCDCUsartTxIsBusy() directly.
458 if(cdc_trf_state == CDC_TX_COMPLETING)
459 cdc_trf_state = CDC_TX_READY;
462 * If CDC_TX_READY state, nothing to do, just return.
464 if(cdc_trf_state == CDC_TX_READY) return;
467 * If CDC_TX_BUSY_ZLP state, send zero length packet
469 if(cdc_trf_state == CDC_TX_BUSY_ZLP)
471 CDC_BULK_BD_IN.Cnt = 0;
472 cdc_trf_state = CDC_TX_COMPLETING;
474 else if(cdc_trf_state == CDC_TX_BUSY)
477 * First, have to figure out how many byte of data to send.
479 if(cdc_tx_len > sizeof(cdc_data_tx))
480 byte_to_send = sizeof(cdc_data_tx);
482 byte_to_send = cdc_tx_len;
485 * Next, load the number of bytes to send to Cnt in buffer descriptor
487 CDC_BULK_BD_IN.Cnt = byte_to_send;
490 * Subtract the number of bytes just about to be sent from the total.
492 cdc_tx_len = cdc_tx_len - byte_to_send;
494 pCDCDst.bRam = (byte*)&cdc_data_tx; // Set destination pointer
496 if(cdc_mem_type == _ROM) // Determine type of memory source
500 *pCDCDst.bRam = *pCDCSrc.bRom;
504 }//end while(byte_to_send)
510 *pCDCDst.bRam = *pCDCSrc.bRam;
514 }//end while(byte_to_send._word)
515 }//end if(cdc_mem_type...)
518 * Lastly, determine if a zero length packet state is necessary.
519 * See explanation in USB Specification 2.0: Section 5.8.3
523 if(CDC_BULK_BD_IN.Cnt == sizeof(cdc_data_tx))
524 cdc_trf_state = CDC_TX_BUSY_ZLP;
526 cdc_trf_state = CDC_TX_COMPLETING;
527 }//end if(cdc_tx_len...)
529 }//end if(cdc_tx_sate == CDC_TX_BUSY)
532 * Both CDC_TX_BUSY and CDC_TX_BUSY_ZLP states use the following macro
534 mUSBBufferReady(CDC_BULK_BD_IN);
540 /** EOF cdc.c ****************************************************************/