Main Page | Data Structures | Directories | File List | Data Fields | Globals

cdc.c

Go to the documentation of this file.
00001 /*********************************************************************
00002  *
00003  *             Microchip USB C18 Firmware -  CDC Version 1.0
00004  *
00005  *********************************************************************
00006  * FileName:        cdc.c
00007  * Dependencies:    See INCLUDES section below
00008  * Processor:       PIC18
00009  * Compiler:        C18 2.30.01+
00010  * Company:         Microchip Technology, Inc.
00011  *
00012  * Software License Agreement
00013  *
00014  * The software supplied herewith by Microchip Technology Incorporated
00015  * (the “Company”) for its PICmicro® Microcontroller is intended and
00016  * supplied to you, the Company’s customer, for use solely and
00017  * exclusively on Microchip PICmicro Microcontroller products. The
00018  * software is owned by the Company and/or its supplier, and is
00019  * protected under applicable copyright laws. All rights are reserved.
00020  * Any use in violation of the foregoing restrictions may subject the
00021  * user to criminal sanctions under applicable laws, as well as to
00022  * civil liability for the breach of the terms and conditions of this
00023  * license.
00024  *
00025  * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
00026  * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
00027  * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00028  * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
00029  * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
00030  * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
00031  *
00032  * Author               Date        Comment
00033  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00034  * Rawin Rojvanit       11/19/04    Original. RS-232 Emulation Subset
00035  ********************************************************************/
00036 
00037 /** I N C L U D E S **********************************************************/
00038 #include <p18cxxx.h>
00039 #include "system\typedefs.h"
00040 #include "system\usb\usb.h"
00041 
00042 #ifdef USB_USE_CDC
00043 
00044 /** V A R I A B L E S ********************************************************/
00045 #pragma udata
00046 byte cdc_rx_len;            // total rx length
00047 
00048 byte cdc_trf_state;         // States are defined cdc.h
00049 POINTER pCDCSrc;            // Dedicated source pointer
00050 POINTER pCDCDst;            // Dedicated destination pointer
00051 byte cdc_tx_len;            // total tx length
00052 byte cdc_mem_type;          // _ROM, _RAM
00053 
00054 LINE_CODING line_coding;    // Buffer to store line coding information
00055 CONTROL_SIGNAL_BITMAP control_signal_bitmap;
00056 
00057 /*
00058  * SEND_ENCAPSULATED_COMMAND and GET_ENCAPSULATED_RESPONSE are required
00059  * requests according to the CDC specification.
00060  * However, it is not really being used here, therefore a dummy buffer is
00061  * used for conformance.
00062  */
00063 #define dummy_length    0x08
00064 byte dummy_encapsulated_cmd_response[dummy_length];
00065 
00066 /** P R I V A T E  P R O T O T Y P E S ***************************************/
00067 
00068 /** D E C L A R A T I O N S **************************************************/
00069 #pragma code
00070 
00071 /** C L A S S  S P E C I F I C  R E Q ****************************************/
00072 /******************************************************************************
00073  * Function:        void USBCheckCDCRequest(void)
00074  *
00075  * PreCondition:    None
00076  *
00077  * Input:           None
00078  *
00079  * Output:          None
00080  *
00081  * Side Effects:    None
00082  *
00083  * Overview:        This routine checks the setup data packet to see if it
00084  *                  knows how to handle it
00085  *
00086  * Note:            None
00087  *****************************************************************************/
00088 void USBCheckCDCRequest(void)
00089 {
00090     /*
00091      * If request recipient is not an interface then return
00092      */
00093     if(SetupPkt.Recipient != RCPT_INTF) return;
00094 
00095     /*
00096      * If request type is not class-specific then return
00097      */
00098     if(SetupPkt.RequestType != CLASS) return;
00099 
00100     /*
00101      * Interface ID must match interface numbers associated with
00102      * CDC class, else return
00103      */
00104     if((SetupPkt.bIntfID != CDC_COMM_INTF_ID)&&
00105        (SetupPkt.bIntfID != CDC_DATA_INTF_ID)) return;
00106     
00107     switch(SetupPkt.bRequest)
00108     {
00109         case SEND_ENCAPSULATED_COMMAND:
00110             ctrl_trf_session_owner = MUID_CDC;
00111             pSrc.bRam = (byte*)&dummy_encapsulated_cmd_response;
00112             usb_stat.ctrl_trf_mem = _RAM;
00113             LSB(wCount) = dummy_length;
00114             break;
00115         case GET_ENCAPSULATED_RESPONSE:
00116             ctrl_trf_session_owner = MUID_CDC;
00117             // Populate dummy_encapsulated_cmd_response first.
00118             pDst.bRam = (byte*)&dummy_encapsulated_cmd_response;
00119             break;
00120         case SET_COMM_FEATURE:                  // Optional
00121             break;
00122         case GET_COMM_FEATURE:                  // Optional
00123             break;
00124         case CLEAR_COMM_FEATURE:                // Optional
00125             break;
00126         case SET_LINE_CODING:
00127             ctrl_trf_session_owner = MUID_CDC;
00128             pDst.bRam = (byte*)&line_coding;    // Set destination
00129             break;
00130         case GET_LINE_CODING:
00131             ctrl_trf_session_owner = MUID_CDC;
00132             pSrc.bRam = (byte*)&line_coding;    // Set source
00133             usb_stat.ctrl_trf_mem = _RAM;       // Set memory type
00134             LSB(wCount) = LINE_CODING_LENGTH;   // Set data count
00135             break;
00136         case SET_CONTROL_LINE_STATE:
00137             ctrl_trf_session_owner = MUID_CDC;
00138             control_signal_bitmap._byte = LSB(SetupPkt.W_Value);
00139             break;
00140         case SEND_BREAK:                        // Optional
00141             break;
00142         default:
00143             break;
00144     }//end switch(SetupPkt.bRequest)
00145 
00146 }//end USBCheckCDCRequest
00147 
00148 /** U S E R  A P I ***********************************************************/
00149 
00150 /******************************************************************************
00151  * Function:        void CDCInitEP(void)
00152  *
00153  * PreCondition:    None
00154  *
00155  * Input:           None
00156  *
00157  * Output:          None
00158  *
00159  * Side Effects:    None
00160  *
00161  * Overview:        CDCInitEP initializes CDC endpoints, buffer descriptors,
00162  *                  internal state-machine, and variables.
00163  *                  It should be called after the USB host has sent out a
00164  *                  SET_CONFIGURATION request.
00165  *                  See USBStdSetCfgHandler() in usb9.c for examples.
00166  *
00167  * Note:            None
00168  *****************************************************************************/
00169 void CDCInitEP(void)
00170 {
00171     //Abstract line coding information
00172     line_coding.dwDTERate._dword = 115200;      // baud rate
00173     line_coding.bCharFormat = 0x00;             // 1 stop bit
00174     line_coding.bParityType = 0x00;             // None
00175     line_coding.bDataBits = 0x08;               // 5,6,7,8, or 16
00176 
00177     cdc_trf_state = CDC_TX_READY;
00178     cdc_rx_len = 0;
00179     
00180     CDC_COMM_UEP = EP_IN|HSHK_EN;               // Enable 1 Comm pipe
00181     CDC_DATA_UEP = EP_OUT_IN|HSHK_EN;           // Enable 2 data pipes
00182 
00183     /*
00184      * Do not have to init Cnt of IN pipes here.
00185      * Reason:  Number of bytes to send to the host
00186      *          varies from one transaction to
00187      *          another. Cnt should equal the exact
00188      *          number of bytes to transmit for
00189      *          a given IN transaction.
00190      *          This number of bytes will only
00191      *          be known right before the data is
00192      *          sent.
00193      */
00194     CDC_INT_BD_IN.ADR = (byte*)&cdc_notice;     // Set buffer address
00195     CDC_INT_BD_IN.Stat._byte = _UCPU|_DAT1;     // Set status
00196 
00197     CDC_BULK_BD_OUT.Cnt = sizeof(cdc_data_rx);  // Set buffer size
00198     CDC_BULK_BD_OUT.ADR = (byte*)&cdc_data_rx;  // Set buffer address
00199     CDC_BULK_BD_OUT.Stat._byte = _USIE|_DAT0|_DTSEN;// Set status
00200 
00201     CDC_BULK_BD_IN.ADR = (byte*)&cdc_data_tx;   // Set buffer size
00202     CDC_BULK_BD_IN.Stat._byte = _UCPU|_DAT1;    // Set buffer address
00203 
00204 }//end CDCInitEP
00205 
00206 /******************************************************************************
00207  * Function:        byte getsUSBUSART(char *buffer,
00208  *                                    byte len)
00209  *
00210  * PreCondition:    Value of input argument 'len' should be smaller than the
00211  *                  maximum endpoint size responsible for receiving bulk
00212  *                  data from USB host for CDC class.
00213  *                  Input argument 'buffer' should point to a buffer area that
00214  *                  is bigger or equal to the size specified by 'len'.
00215  *
00216  * Input:           buffer  : Pointer to where received bytes are to be stored
00217  *                  len     : The number of bytes expected.
00218  *
00219  * Output:          The number of bytes copied to buffer.
00220  *
00221  * Side Effects:    Publicly accessible variable cdc_rx_len is updated with
00222  *                  the number of bytes copied to buffer.
00223  *                  Once getsUSBUSART is called, subsequent retrieval of
00224  *                  cdc_rx_len can be done by calling macro mCDCGetRxLength().
00225  *
00226  * Overview:        getsUSBUSART copies a string of bytes received through
00227  *                  USB CDC Bulk OUT endpoint to a user's specified location. 
00228  *                  It is a non-blocking function. It does not wait
00229  *                  for data if there is no data available. Instead it returns
00230  *                  '0' to notify the caller that there is no data available.
00231  *
00232  * Note:            If the actual number of bytes received is larger than the
00233  *                  number of bytes expected (len), only the expected number
00234  *                  of bytes specified will be copied to buffer.
00235  *                  If the actual number of bytes received is smaller than the
00236  *                  number of bytes expected (len), only the actual number
00237  *                  of bytes received will be copied to buffer.
00238  *****************************************************************************/
00239 byte getsUSBUSART(char *buffer, byte len)
00240 {
00241     cdc_rx_len = 0;
00242     
00243     if(!mCDCUsartRxIsBusy())
00244     {
00245         /*
00246          * Adjust the expected number of bytes to equal
00247          * the actual number of bytes received.
00248          */
00249         if(len > CDC_BULK_BD_OUT.Cnt)
00250             len = CDC_BULK_BD_OUT.Cnt;
00251         
00252         /*
00253          * Copy data from dual-ram buffer to user's buffer
00254          */
00255         for(cdc_rx_len = 0; cdc_rx_len < len; cdc_rx_len++)
00256             buffer[cdc_rx_len] = cdc_data_rx[cdc_rx_len];
00257 
00258         /*
00259          * Prepare dual-ram buffer for next OUT transaction
00260          */
00261         CDC_BULK_BD_OUT.Cnt = sizeof(cdc_data_rx);
00262         mUSBBufferReady(CDC_BULK_BD_OUT);
00263     }//end if
00264     
00265     return cdc_rx_len;
00266     
00267 }//end getsUSBUSART
00268 
00269 /******************************************************************************
00270  * Function:        void putsUSBUSART(char *data)
00271  *
00272  * PreCondition:    cdc_trf_state must be in the CDC_TX_READY state.
00273  *                  
00274  *                  The string of characters pointed to by 'data' must equal
00275  *                  to or smaller than 255 bytes.
00276  *
00277  * Input:           data    : Pointer to a null-terminated string of data.
00278  *                            If a null character is not found, 255 bytes
00279  *                            of data will be transferred to the host.
00280  *
00281  * Output:          None
00282  *
00283  * Side Effects:    None
00284  *
00285  * Overview:        putsUSBUSART writes a string of data to the USB including
00286  *                  the null character. Use this version, 'puts', to transfer
00287  *                  data located in data memory.
00288  *
00289  * Note:            The transfer mechanism for device-to-host(put) is more
00290  *                  flexible than host-to-device(get). It can handle
00291  *                  a string of data larger than the maximum size of bulk IN
00292  *                  endpoint. A state machine is used to transfer a long
00293  *                  string of data over multiple USB transactions.
00294  *                  See CDCTxService() for more details.
00295  *****************************************************************************/
00296 void putsUSBUSART(char *data)
00297 {
00298     byte len;
00299 
00300     /*
00301      * User should have checked that cdc_trf_state is in CDC_TX_READY state
00302      * before calling this function.
00303      * As a safety precaution, this fuction checks the state one more time
00304      * to make sure it does not override any pending transactions.
00305      *
00306      * Currently it just quits the routine without reporting any errors back
00307      * to the user.
00308      *
00309      * Bottomline: User MUST make sure that mUSBUSARTIsTxTrfReady()==1
00310      *             before calling this function!
00311      * Example:
00312      * if(mUSBUSARTIsTxTrfReady())
00313      *     putsUSBUSART(pData);
00314      *
00315      * IMPORTANT: Never use the following blocking while loop to wait:
00316      * while(!mUSBUSARTIsTxTrfReady())
00317      *     putsUSBUSART(pData);
00318      *
00319      * The whole firmware framework is written based on cooperative
00320      * multi-tasking and a blocking code is not acceptable.
00321      * Use a state machine instead.
00322      */
00323     if(cdc_trf_state != CDC_TX_READY) return;
00324     
00325     /*
00326      * While loop counts the number of bytes to send including the
00327      * null character.
00328      */
00329     len = 0;
00330     do
00331     {
00332         len++;
00333         if(len == 255) break;       // Break loop once max len is reached.
00334     }while(*data++);
00335     
00336     /*
00337      * Re-adjust pointer to its initial location
00338      */
00339     data-=len;
00340     
00341     /*
00342      * Second piece of information (length of data to send) is ready.
00343      * Call mUSBUSARTTxRam to setup the transfer.
00344      * The actual transfer process will be handled by CDCTxService(),
00345      * which should be called once per Main Program loop.
00346      */
00347     mUSBUSARTTxRam((byte*)data,len);     // See cdc.h
00348 }//end putsUSBUSART
00349 
00350 /******************************************************************************
00351  * Function:        void putrsUSBUSART(const rom char *data)
00352  *
00353  * PreCondition:    cdc_trf_state must be in the CDC_TX_READY state.
00354  *                  
00355  *                  The string of characters pointed to by 'data' must equal
00356  *                  to or smaller than 255 bytes.
00357  *
00358  * Input:           data    : Pointer to a null-terminated string of data.
00359  *                            If a null character is not found, 255 bytes
00360  *                            of data will be transferred to the host.
00361  *
00362  * Output:          None
00363  *
00364  * Side Effects:    None
00365  *
00366  * Overview:        putrsUSBUSART writes a string of data to the USB including
00367  *                  the null character. Use this version, 'putrs', to transfer
00368  *                  data literals and data located in program memory.
00369  *
00370  * Note:            The transfer mechanism for device-to-host(put) is more
00371  *                  flexible than host-to-device(get). It can handle
00372  *                  a string of data larger than the maximum size of bulk IN
00373  *                  endpoint. A state machine is used to transfer a long
00374  *                  string of data over multiple USB transactions.
00375  *                  See CDCTxService() for more details.
00376  *****************************************************************************/
00377 void putrsUSBUSART(const rom char *data)
00378 {
00379     byte len;
00380 
00381     /*
00382      * User should have checked that cdc_trf_state is in CDC_TX_READY state
00383      * before calling this function.
00384      * As a safety precaution, this fuction checks the state one more time
00385      * to make sure it does not override any pending transactions.
00386      *
00387      * Currently it just quits the routine without reporting any errors back
00388      * to the user.
00389      *
00390      * Bottomline: User MUST make sure that mUSBUSARTIsTxTrfReady()
00391      *             before calling this function!
00392      * Example:
00393      * if(mUSBUSARTIsTxTrfReady())
00394      *     putsUSBUSART(pData);
00395      *
00396      * IMPORTANT: Never use the following blocking while loop to wait:
00397      * while(cdc_trf_state != CDC_TX_READY)
00398      *     putsUSBUSART(pData);
00399      *
00400      * The whole firmware framework is written based on cooperative
00401      * multi-tasking and a blocking code is not acceptable.
00402      * Use a state machine instead.
00403      */
00404     if(cdc_trf_state != CDC_TX_READY) return;
00405     
00406     /*
00407      * While loop counts the number of bytes to send including the
00408      * null character.
00409      */
00410     len = 0;
00411     do
00412     {
00413         len++;
00414         if(len == 255) break;       // Break loop once max len is reached.
00415     }while(*data++);
00416     
00417     /*
00418      * Re-adjust pointer to its initial location
00419      */
00420     data-=len;
00421     
00422     /*
00423      * Second piece of information (length of data to send) is ready.
00424      * Call mUSBUSARTTxRom to setup the transfer.
00425      * The actual transfer process will be handled by CDCTxService(),
00426      * which should be called once per Main Program loop.
00427      */
00428     mUSBUSARTTxRom((rom byte*)data,len); // See cdc.h
00429 
00430 }//end putrsUSBUSART
00431 
00432 /******************************************************************************
00433  * Function:        void CDCTxService(void)
00434  *
00435  * PreCondition:    None
00436  *
00437  * Input:           None
00438  *
00439  * Output:          None
00440  *
00441  * Side Effects:    None
00442  *
00443  * Overview:        CDCTxService handles device-to-host transaction(s).
00444  *                  This function should be called once per Main Program loop.
00445  *
00446  * Note:            None
00447  *****************************************************************************/
00448 void CDCTxService(void)
00449 {
00450     byte byte_to_send;
00451     
00452     if(mCDCUsartTxIsBusy()) return;
00453     /*
00454      * Completing stage is necessary while [ mCDCUSartTxIsBusy()==1 ].
00455      * By having this stage, user can always check cdc_trf_state,
00456      * and not having to call mCDCUsartTxIsBusy() directly.
00457      */
00458     if(cdc_trf_state == CDC_TX_COMPLETING)
00459         cdc_trf_state = CDC_TX_READY;
00460     
00461     /*
00462      * If CDC_TX_READY state, nothing to do, just return.
00463      */
00464     if(cdc_trf_state == CDC_TX_READY) return;
00465     
00466     /*
00467      * If CDC_TX_BUSY_ZLP state, send zero length packet
00468      */
00469     if(cdc_trf_state == CDC_TX_BUSY_ZLP)
00470     {
00471         CDC_BULK_BD_IN.Cnt = 0;
00472         cdc_trf_state = CDC_TX_COMPLETING;
00473     }
00474     else if(cdc_trf_state == CDC_TX_BUSY)
00475     {
00476         /*
00477          * First, have to figure out how many byte of data to send.
00478          */
00479         if(cdc_tx_len > sizeof(cdc_data_tx))
00480             byte_to_send = sizeof(cdc_data_tx);
00481         else
00482             byte_to_send = cdc_tx_len;
00483 
00484         /*
00485          * Next, load the number of bytes to send to Cnt in buffer descriptor
00486          */
00487         CDC_BULK_BD_IN.Cnt = byte_to_send;
00488 
00489         /*
00490          * Subtract the number of bytes just about to be sent from the total.
00491          */
00492         cdc_tx_len = cdc_tx_len - byte_to_send;
00493                 
00494         pCDCDst.bRam = (byte*)&cdc_data_tx; // Set destination pointer
00495         
00496         if(cdc_mem_type == _ROM)            // Determine type of memory source
00497         {
00498             while(byte_to_send)
00499             {
00500                 *pCDCDst.bRam = *pCDCSrc.bRom;
00501                 pCDCDst.bRam++;
00502                 pCDCSrc.bRom++;
00503                 byte_to_send--;
00504             }//end while(byte_to_send)
00505         }
00506         else // _RAM
00507         {
00508             while(byte_to_send)
00509             {
00510                 *pCDCDst.bRam = *pCDCSrc.bRam;
00511                 pCDCDst.bRam++;
00512                 pCDCSrc.bRam++;
00513                 byte_to_send--;
00514             }//end while(byte_to_send._word)
00515         }//end if(cdc_mem_type...)
00516         
00517         /*
00518          * Lastly, determine if a zero length packet state is necessary.
00519          * See explanation in USB Specification 2.0: Section 5.8.3
00520          */
00521         if(cdc_tx_len == 0)
00522         {
00523             if(CDC_BULK_BD_IN.Cnt == sizeof(cdc_data_tx))
00524                 cdc_trf_state = CDC_TX_BUSY_ZLP;
00525             else
00526                 cdc_trf_state = CDC_TX_COMPLETING;
00527         }//end if(cdc_tx_len...)
00528             
00529     }//end if(cdc_tx_sate == CDC_TX_BUSY)
00530     
00531     /*
00532      * Both CDC_TX_BUSY and CDC_TX_BUSY_ZLP states use the following macro
00533      */
00534     mUSBBufferReady(CDC_BULK_BD_IN);
00535 
00536 }//end CDCTxService
00537 
00538 #endif //USB_USE_CDC
00539 
00540 /** EOF cdc.c ****************************************************************/

Generated on Wed Jun 8 03:49:39 2005 for cdc by  doxygen 1.4.2