firmware/cdc.c
author cpresser@rika
Thu, 07 Feb 2008 00:18:02 +0000
changeset 10 9798f65f2f35
parent 2 2f55e5dd591d
permissions -rw-r--r--
thx @arghgra. defined variable != declared variable
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 ****************************************************************/