host_cdc_task.c

Go to the documentation of this file.
00001 /*This file is prepared for Doxygen automatic documentation generation.*/
00013 
00014 /* Copyright (c) 2009 Atmel Corporation. All rights reserved.
00015  *
00016  * Redistribution and use in source and binary forms, with or without
00017  * modification, are permitted provided that the following conditions are met:
00018  *
00019  * 1. Redistributions of source code must retain the above copyright notice,
00020  * this list of conditions and the following disclaimer.
00021  *
00022  * 2. Redistributions in binary form must reproduce the above copyright notice,
00023  * this list of conditions and the following disclaimer in the documentation
00024  * and/or other materials provided with the distribution.
00025  *
00026  * 3. The name of Atmel may not be used to endorse or promote products derived
00027  * from this software without specific prior written permission.
00028  *
00029  * 4. This software may only be redistributed and used in connection with an Atmel
00030  * AVR product.
00031  *
00032  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
00033  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00034  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY AND
00035  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
00036  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00037  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00038  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00039  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00040  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00041  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00042  */
00043 
00044 //_____  I N C L U D E S ___________________________________________________
00045 
00046 #include "config.h"
00047 #include "conf_usb.h"
00048 #include "host_cdc_task.h"
00049 #include "modules/usb/host_chap9/usb_host_task.h"
00050 #include "modules/usb/host_chap9/usb_host_enum.h"
00051 #include "lib_mcu/usb/usb_drv.h"
00052 #ifdef CDC_USE_UART
00053    #include "lib_mcu/uart/uart_lib.h"
00054 #endif
00055 
00056 //_____ M A C R O S ________________________________________________________
00057 
00058 #ifndef LOG_STR_CODE
00059 #define LOG_STR_CODE(str)
00060 #else
00061 U8 code log_cdc_connect[]="CDC Connected";
00062 #endif
00063 
00064 //_____ D E F I N I T I O N S ______________________________________________
00065 
00066 
00067 //_____ D E C L A R A T I O N S ____________________________________________
00068 
00069 U8  cdc_connected;
00070 U8  cdc_interface_comm;
00071 U8  cdc_cpt_sof;
00072 
00073 U8  pipe_cdc_comm_int;
00074 U8  pipe_cdc_data_bulkin;
00075 U8  pipe_cdc_data_bulkout;
00076 
00077 U8  tx_counter;
00078 U8  rx_counter;
00079 U8  cdc_stream_out_array[CDC_STREAM_OUT_SIZE];
00080 U8  cdc_stream_in_array[CDC_STREAM_IN_SIZE];
00081 
00082 
00085 void host_cdc_task_init(void)
00086 {
00087 #ifdef CDC_USE_UART
00088    uart_init();
00089 #endif
00090    Leds_init();
00091    cdc_connected = 0;
00092    cdc_interface_comm = 0;
00093    Joy_init();
00094 }
00095 
00096 
00099 void host_cdc_task(void)
00100 {
00101    U8 i, ep;
00102 
00103    if(Is_host_ready())
00104    {
00105       if(Is_new_device_connection_event())
00106       {
00107          cdc_connected=0;
00108          for(i=0;i<Get_nb_supported_interface();i++)
00109          {
00110             // Data Interface
00111             if((Get_class(i)==CDC_DATA_CLASS) && (Get_subclass(i)==CDC_DATA_SUBCLASS) && (Get_protocol(i)==CDC_DATA_PROTOCOL))
00112             {
00113                cdc_connected=1;
00114                Host_enable_sof_interrupt();
00115                LOG_STR_CODE(log_cdc_connect);
00116                if(Is_ep_addr_in(Get_ep_addr(i,0)))
00117                {  // Yes associate it to the CDC Data IN pipe
00118                   pipe_cdc_data_bulkin = host_get_hwd_pipe_nb(Get_ep_addr(i,0));
00119                   pipe_cdc_data_bulkout = host_get_hwd_pipe_nb(Get_ep_addr(i,1));
00120                }
00121                else
00122                {  // No, invert...
00123                   pipe_cdc_data_bulkin = host_get_hwd_pipe_nb(Get_ep_addr(i,1));
00124                   pipe_cdc_data_bulkout = host_get_hwd_pipe_nb(Get_ep_addr(i,0));
00125                }
00126                Host_select_pipe(PIPE_CDC_DATA_IN);
00127                Host_continuous_in_mode();
00128                Host_unfreeze_pipe();
00129                break;
00130             }
00131             // Management Interface
00132 #ifdef   CDC_USE_MANAGEMENT_INTERFACE
00133             if(((Get_class(i)==CDC_COMM_CLASS) && (Get_subclass(i)==CDC_COMM_SUBCLASS) && (Get_protocol(i)==CDC_COMM_PROTOCOL))
00134 #ifdef   CDC_USE_ACTIVE_SYNC_INTERFACE               
00135             || ((Get_class(i)==0xEF) && (Get_subclass(i)==0x01) && (Get_protocol(i)==0x01)) )   // Active Sync Class Interface
00136 #else
00137             )
00138 #endif
00139             {
00140                cdc_interface_comm = i;      // store interface number
00141                pipe_cdc_comm_int = host_get_hwd_pipe_nb(Get_ep_addr(i,0));
00142                Host_select_pipe(PIPE_CDC_COMM);
00143                Host_continuous_in_mode();
00144                Host_unfreeze_pipe();
00145             }
00146 #endif
00147 
00148 #ifdef CDC_USE_SPECIFIC_VENDOR_INTERFACE         // Force specific vendor interface like CDC Device
00149             // Specific interface vendor include all endpoints (3) in only one Interface
00150             if((Get_class(i)==0xFF) && (Get_subclass(i)==0x00) && (Get_protocol(i)==0x00) && (Get_nb_ep(i)==3) )
00151             {
00152                cdc_connected=1;
00153                Host_enable_sof_interrupt();
00154                LOG_STR_CODE(log_cdc_connect);
00155 
00156                for( ep=0; ep<3; ep++){
00157                   if(TYPE_INTERRUPT == usb_tree.device[selected_device].interface[i].ep[ep].ep_type) {
00158                      cdc_interface_comm = i;      // store interface number
00159                      pipe_cdc_comm_int = host_get_hwd_pipe_nb(Get_ep_addr(i,ep));
00160                      Host_select_pipe(PIPE_CDC_COMM);
00161                      Host_continuous_in_mode();
00162                      Host_unfreeze_pipe();
00163                   }
00164                   if(TYPE_BULK == usb_tree.device[selected_device].interface[i].ep[ep].ep_type) {
00165                      if(Is_ep_addr_in(Get_ep_addr(i,ep)))
00166                      {  // Yes associate it to the CDC Data IN pipe
00167                         pipe_cdc_data_bulkin = host_get_hwd_pipe_nb(Get_ep_addr(i,ep));
00168                         Host_select_pipe(PIPE_CDC_DATA_IN);
00169                         Host_continuous_in_mode();
00170                         Host_unfreeze_pipe();
00171                      }else{  // No, invert...
00172                         pipe_cdc_data_bulkout = host_get_hwd_pipe_nb(Get_ep_addr(i,ep));
00173                      }
00174                   }
00175                }
00176             }
00177 #endif
00178 
00179          }
00180          // Open port (according cdc spec 1.1 chapter 6.2.14)
00181          usb_request.bmRequestType = USB_SETUP_SET_CLASS_INTER;
00182          usb_request.bRequest      = SETUP_CDC_SET_CONTROL_LINE_STATE;
00183          usb_request.wValue        = 0x03;   // Bit 1 :  Activate carrier / Bit 0 : Indicates to DCE that DTE is present.
00184          usb_request.wIndex        = 0;   // Interface number
00185          usb_request.wLength       = 0;
00186          usb_request.uncomplete_read = FALSE;
00187          if( CONTROL_GOOD == host_send_control(0))
00188          {
00189          
00190             U8 u8_LineCoding[7];
00191             usb_request.bmRequestType = USB_SETUP_SET_CLASS_INTER;
00192             usb_request.bRequest      = SETUP_CDC_SET_LINE_CODING;
00193             usb_request.wValue        = 0;   // 0
00194             usb_request.wIndex        = 0;   // Interface number
00195             usb_request.wLength       = 7;   // Size of Line Coding Structure
00196             usb_request.uncomplete_read = FALSE;
00197             u8_LineCoding[0] = 0xFF&(BAUDRATE>>0);
00198             u8_LineCoding[1] = 0xFF&(BAUDRATE>>8);
00199             u8_LineCoding[2] = 0xFF&(BAUDRATE>>16);
00200             u8_LineCoding[3] = 0xFF&(BAUDRATE>>24);
00201             u8_LineCoding[4] = 0;   // 1 Stop bit
00202             u8_LineCoding[5] = 0;   // No parity
00203             u8_LineCoding[6] = 8;   // 8 Data bits
00204             
00205             if( CONTROL_GOOD == host_send_control(u8_LineCoding))
00206             {
00207                Led1_on();
00208             }
00209          }
00210       }
00211 
00212       if(cdc_connected)
00213       {
00214          // Check DATA_PIPE_IN for incoming data
00215          // ************************************
00216          // 1 -> UART-USB Mode
00217          //   Data received is automatically sent on the UART
00218          // 2 -> Normal Mode
00219          //   Data received is stored in the "cdc_stream_in_array[CDC_STREAM_IN_SIZE]" array and may be read by firmware
00220          //   When firmware reads the array it must do it entirely and then set "rx_counter" variable to 0
00221          //   It must not partially read the array and decrement rx_counter (will lead to array overflow)
00222          Host_select_pipe(PIPE_CDC_DATA_IN);
00223          if (Is_host_in_received() && (Is_host_stall()==FALSE))
00224          {
00225 #ifdef CDC_USE_UART
00226             while (Host_data_length_U8() != 0)
00227             {
00228               uart_putchar(Host_read_byte());
00229             }
00230             Host_ack_in_received();    // pipe is empty
00231             Host_send_in();            // ready to receive more data
00232 #else
00233             while ((rx_counter != CDC_STREAM_IN_SIZE) && (Host_data_length_U8() != 0))
00234             {
00235               cdc_stream_in_array[rx_counter] = Host_read_byte();
00236               rx_counter++;
00237             }
00238             if (Host_data_length_U8() == 0)
00239             {
00240                Host_ack_in_received();    // pipe is empty
00241                Host_send_in();            // ready to receive more data
00242             }
00243 #endif
00244          }
00245 
00246 
00247          // Check if data to send on DATA_PIPE_OUT state
00248          // ********************************************
00249          // Data to be sent is stored in the "cdc_stream_out_array[CDC_STREAM_OUT_SIZE]" array
00250          // Data may come indifferently from neither UART or RAM (firmware)
00251          // Data is sent to CDC Device when :
00252          //    - user requires it, by calling "cdc_pipe_out_usb_flush()" function
00253          //    - time-out period is elapsed (CDC_NB_MS_BEFORE_FLUSH = number of SOF seen)
00254          //    - buffer is full (tx_counter = CDC_STREAM_OUT_SIZE)
00255 
00256 #ifdef CDC_USE_UART
00257          // Check if new byte in USART, to be stored for USB
00258          if (uart_test_hit() && (tx_counter != CDC_STREAM_OUT_SIZE))
00259          {
00260            cdc_stream_out_array[tx_counter] = uart_getchar();
00261            tx_counter++;
00262          }
00263 #endif
00264 
00265          // Check if pipe flush is needed (buffer full or time-out period elapsed)
00266          if(((cdc_cpt_sof>=CDC_NB_MS_BEFORE_FLUSH) && (tx_counter!=0)) || (tx_counter == CDC_STREAM_OUT_SIZE))  //Flush buffer by Timeout
00267          {
00268             cdc_cpt_sof=0;
00269             cdc_pipe_out_usb_flush();
00270          }
00271 
00272 
00273          // Check in COMM_PIPE_IN for incoming notifications
00274          // ************************************************
00275          Host_select_pipe(PIPE_CDC_COMM);
00276          if (Is_host_in_received())
00277          {
00278             // Handle here notification messages sent by device
00279             // Notifications messages have the following structure :
00280             //  bmRequestType - bNotification - wValue - wIndex - wLength - Data     (wLength is the number of bytes of the Data field)
00281 
00282             //   - NETWORK_CONNECTION : indicates that device has connected to network
00283             //   - RESPONSE_AVAILABLE : indicates that device has a ready encapsulated response (wait for host request)
00284             //   - SERIAL_STATE : indicates state of device' UART (errors, carriers and misc. signals)
00285             //   - etc...
00286 
00287             // ...and now...just coding...
00288             Host_ack_in_received();
00289             Host_send_in();
00290          }
00291       }
00292    }
00293 
00294    // Device disconnection...
00295    if(Is_device_disconnection_event())
00296    {
00297       Leds_off();
00298       cdc_connected=0;
00299       cdc_interface_comm = 0;
00300    }
00301 }
00302 
00303 
00308 void sof_action(void)
00309 {
00310    cdc_cpt_sof++;
00311 }
00312 
00313 
00317 void cdc_pipe_out_usb_flush (void)
00318 {
00319    Host_select_pipe(PIPE_CDC_DATA_IN);    // BULK IN must be frozen else BULK OUT may not be sent
00320    Host_freeze_pipe();
00321    if (PIPE_GOOD == host_send_data(PIPE_CDC_DATA_OUT, tx_counter, cdc_stream_out_array))
00322    {
00323       tx_counter = 0;                     // if frame not sent, will try again next time (no data loss)
00324    }
00325    Host_select_pipe(PIPE_CDC_DATA_IN);
00326    Host_unfreeze_pipe();
00327 }
00328 
00329 

Generated on Wed Sep 23 09:41:07 2009 for ATMEL by  doxygen 1.5.3