usb_host_enum.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 "lib_mcu/usb/usb_drv.h"
00049 #include "usb_host_enum.h"
00050 #include "modules/usb/usb_task.h"
00051 #include "usb_host_task.h"
00052 
00053 //_____ M A C R O S ________________________________________________________
00054 
00055 
00056 //_____ D E F I N I T I O N ________________________________________________
00057 
00058 //_____ P R I V A T E   D E C L A R A T I O N ______________________________
00059 
00060 #if (USB_HOST_FEATURE == DISABLED)
00061    #warning trying to compile a file used with the USB HOST without USB_HOST_FEATURE enabled
00062 #endif
00063 
00064 
00065 #ifndef SAVE_INTERRUPT_PIPE_FOR_DMS_INTERFACE
00066    #define SAVE_INTERRUPT_PIPE_FOR_DMS_INTERFACE   ENABLE
00067 #endif
00068       
00069 #if (USB_HOST_FEATURE == ENABLED)
00070 extern S_usb_setup_data usb_request;
00071 
00072 
00073 
00074 #ifndef VID_PID_TABLE
00075    #error VID_PID_TABLE shoud be defined somewhere (conf_usb.h)
00076   /*   VID_PID_TABLE format definition:
00077   //   #define VID_PID_TABLE      {VID1, number_of_pid_for_this_VID1, PID11_value,..., PID1X_Value \
00078   //                              ...\
00079   //                              ,VIDz, number_of_pid_for_this_VIDz, PIDz1_value,..., PIDzX_Value}
00080   */
00081 #endif
00082 
00083 #ifndef CLASS_SUBCLASS_PROTOCOL
00084    #error CLASS_SUBCLASS_PROTOCOL shoud be defined somewhere (conf_usb.h)
00085   /*   CLASS_SUBCLASS_PROTOCOL format definition:
00086   //   #define CLASS_SUBCLASS_PROTOCOL  {CLASS1, SUB_CLASS1,PROTOCOL1, \
00087   //                                     ...\
00088   //                                     CLASSz, SUB_CLASSz,PROTOCOLz}
00089   */
00090 #endif
00091 
00092 
00094 U16 registered_VID_PID[]   = VID_PID_TABLE;
00095 
00097 U8  registered_class[]     = CLASS_SUBCLASS_PROTOCOL;
00098 
00100 S_usb_tree usb_tree;
00101 
00102 #if (USB_HUB_SUPPORT==ENABLE && USER_PERIODIC_PIPE==ENABLE)
00103 U8 user_periodic_pipe=0;
00104 U8 user_periodic_pipe_freeze_state=0;
00105 U8 user_periodic_pipe_device_index=0;
00106 #endif
00107 
00108 
00109 
00110 U8 selected_device=0;
00111 
00112 
00113 
00114 //_____ D E C L A R A T I O N ______________________________________________
00115 
00126 U8 host_check_VID_PID(void)
00127 {
00128 U8  c,d;
00129 
00130    // Rebuild VID PID from data stage
00131    LSB(usb_tree.device[selected_device].vid) = data_stage[OFFSET_FIELD_LSB_VID];
00132    MSB(usb_tree.device[selected_device].vid) = data_stage[OFFSET_FIELD_MSB_VID];
00133    LSB(usb_tree.device[selected_device].pid) = data_stage[OFFSET_FIELD_LSB_PID];
00134    MSB(usb_tree.device[selected_device].pid) = data_stage[OFFSET_FIELD_MSB_PID];
00135 
00136    // Compare detected VID PID with supported table
00137    c=0;
00138    while (c< sizeof(registered_VID_PID)/2)   // /2 because registered_VID_PID table is U16...
00139    {
00140       if (registered_VID_PID[c] == Get_VID())   // VID is correct
00141       {
00142          d = (U8)registered_VID_PID[c+1];    // store nb of PID for this VID
00143          while (d != 0)
00144          {
00145             if (registered_VID_PID[c+d+1] == Get_PID())
00146             {
00147                return HOST_TRUE;
00148             }
00149             d--;
00150          }
00151       }
00152       c+=registered_VID_PID[c+1]+2;
00153    }
00154    return HOST_FALSE;
00155 }
00156 
00168 U8 host_check_class(void)
00169 {
00170 U8  c;
00171 T_DESC_OFFSET  descriptor_offset;
00172 T_DESC_OFFSET  conf_offset_end;
00173 U16  config_size;
00174 U8  device_class;
00175 U8  device_subclass;
00176 U8  device_protocol;
00177 U8  nb_interface_supported;
00178 
00179 
00180    nb_interface_supported=0;   //First asumes ,no interface is supported!
00181    if (data_stage[OFFSET_FIELD_DESCRIPTOR_TYPE] != DESCRIPTOR_CONFIGURATION)           // check if configuration descriptor
00182    { return HOST_FALSE;}
00183    LSB(config_size) = data_stage[OFFSET_FIELD_TOTAL_LENGHT];
00184    MSB(config_size) = data_stage[OFFSET_FIELD_TOTAL_LENGHT+1];
00185    usb_tree.device[selected_device].bmattributes = data_stage[OFFSET_FIELD_BMATTRIBUTES];
00186    usb_tree.device[selected_device].maxpower = data_stage[OFFSET_FIELD_MAXPOWER];
00187    descriptor_offset = 0;
00188    conf_offset_end = descriptor_offset + config_size;
00189 
00190    // Look in all interfaces declared in the configuration
00191    while(descriptor_offset < conf_offset_end)
00192    {
00193       // Find next interface descriptor
00194       while (data_stage[descriptor_offset+OFFSET_FIELD_DESCRIPTOR_TYPE] != DESCRIPTOR_INTERFACE)
00195       {
00196          descriptor_offset += data_stage[descriptor_offset];
00197          if(descriptor_offset >= conf_offset_end)
00198          {
00199             if(nb_interface_supported)
00200             {
00201                return HOST_TRUE;
00202             }
00203             else return HOST_FALSE;
00204          }
00205       }
00206       // Found an interface descriptor
00207       // Get charateristics of this interface
00208       device_class    = data_stage[descriptor_offset + OFFSET_FIELD_CLASS];
00209       device_subclass = data_stage[descriptor_offset + OFFSET_FIELD_SUB_CLASS];
00210       device_protocol = data_stage[descriptor_offset + OFFSET_FIELD_PROTOCOL];
00211       // Look in registered class table for match
00212       c=0;
00213       while (c< sizeof(registered_class))
00214       {
00215          if (registered_class[c] == device_class)                 // class is correct!
00216          {
00217             if (registered_class[c+1] == device_subclass)         // sub class is correct!
00218             {
00219                if (registered_class[c+2] == device_protocol)      // protocol is correct!
00220                {
00221                   // Prepare for another item CLASS/SUB_CLASS/PROTOCOL in table
00222                   c+=3;
00223                   // Store this interface as supported interface
00224                   // Memorize its interface nb
00225                   usb_tree.device[selected_device].interface[nb_interface_supported].interface_nb=data_stage[descriptor_offset+OFFSET_FIELD_INTERFACE_NB];
00226                   //          its alternate setting
00227                   usb_tree.device[selected_device].interface[nb_interface_supported].altset_nb=data_stage[descriptor_offset+OFFSET_FIELD_ALT];
00228                   //          its USB class
00229                   usb_tree.device[selected_device].interface[nb_interface_supported].class=device_class;
00230                   //          its USB subclass
00231                   usb_tree.device[selected_device].interface[nb_interface_supported].subclass=device_subclass;
00232                   //          its USB protocol
00233                   usb_tree.device[selected_device].interface[nb_interface_supported].protocol=device_protocol;
00234                   //          the number of endpoints associated to this interface
00235                   //          Note: The associated endpoints addresses are stored during pipe attribution...
00236                   usb_tree.device[selected_device].interface[nb_interface_supported].nb_ep=data_stage[descriptor_offset+OFFSET_FIELS_NB_OF_EP];
00237                   // Update the number of interface supported
00238                   nb_interface_supported++;
00239                   // Update the number of interface supported for the device
00240                   usb_tree.device[selected_device].nb_interface++;
00241                   // Check the maximum number of interfaces we can support
00242                   if(nb_interface_supported>=MAX_INTERFACE_FOR_DEVICE)
00243                   {
00244                      return HOST_TRUE;
00245                   }
00246                }
00247             }
00248          }
00249          c+=3; // Check other item CLASS/SUB_CLASS/PROTOCOL in table
00250       }
00251       descriptor_offset += data_stage[descriptor_offset]; // Next descriptor
00252       if(descriptor_offset > SIZEOF_DATA_STAGE)           // Check overflow
00253       {
00254          if(nb_interface_supported)
00255          {
00256             return HOST_TRUE;
00257          }
00258          else return HOST_FALSE;
00259       }
00260    }
00261    if(nb_interface_supported)
00262    { 
00263       return HOST_TRUE; 
00264    }
00265    else return HOST_FALSE;
00266 }
00267 
00275 U8 host_auto_configure_endpoint()
00276 {
00277 U8  nb_endpoint_to_configure;
00278 T_DESC_OFFSET  descriptor_offset;
00279 U8  physical_pipe=1;   // =1 cause lookup table assumes that physical pipe 0 is reserved for control
00280 U8 i;
00281 U8 ep_index;
00282 U8 device,interface,alt_interface;
00283 U8 nb_interface;
00284 
00285    // Get the last device number to configure
00286    device = usb_tree.nb_device-1;
00287    
00288    // Get the nulber of interface to configure for the last device connected
00289    nb_interface = usb_tree.device[device].nb_interface;
00290    
00291    // Look for first physical pipe free
00292    // TODO improve allocation mechanism...
00293    i = Host_get_selected_pipe();    // Save current selected pipe
00294    for(physical_pipe=1;physical_pipe<MAX_EP_NB-1;physical_pipe++)
00295    {
00296       Host_select_pipe(physical_pipe);
00297       if(Is_host_pipe_memory_allocated()==FALSE) break; // Pipe already allocated try next one
00298    }
00299    Host_select_pipe(i); //Restore previous selected pipe
00300 
00301    // For all interfaces to configure...
00302    for(i=0;i<nb_interface;i++)
00303    {
00304       ep_index=0;
00305       // Look for the target interface descriptor offset
00306       interface = usb_tree.device[device].interface[i].interface_nb;
00307       alt_interface = usb_tree.device[device].interface[i].altset_nb;
00308       descriptor_offset = get_interface_descriptor_offset(interface,alt_interface);
00309       // Get the number of endpoint to configure for this interface
00310       nb_endpoint_to_configure = usb_tree.device[device].interface[i].nb_ep;
00311       // Get the first Endpoint descriptor offset to configure
00312       descriptor_offset += data_stage[descriptor_offset+OFFSET_DESCRIPTOR_LENGHT];  // pointing on endpoint descriptor
00313 
00314       // While there is at least one pipe to configure
00315       while (nb_endpoint_to_configure)
00316       {
00317          // Check and look for an Endpoint descriptor
00318          while (data_stage[descriptor_offset+OFFSET_FIELD_DESCRIPTOR_TYPE] != DESCRIPTOR_ENDPOINT)
00319          {
00320             descriptor_offset += data_stage[descriptor_offset];
00321             if(descriptor_offset > SIZEOF_DATA_STAGE)   // No more endpoint descriptor found -> Errror !
00322             {  return HOST_FALSE; }
00323          }
00324 #if (SAVE_INTERRUPT_PIPE_FOR_DMS_INTERFACE==ENABLE)
00325          // @TODO HUB support & INTERRUPT PIPE No validated
00326          if(data_stage[descriptor_offset+OFFSET_FIELD_EP_TYPE]==TYPE_INTERRUPT && usb_tree.device[device].interface[i].class==0x08)
00327          {
00328             nb_endpoint_to_configure--;
00329             usb_tree.device[device].interface[i].nb_ep--;
00330             continue;
00331          }
00332 #endif         
00333 
00334          // Select the new physical pipe to configure and get ride of any previous configuration for this physical pipe
00335          Host_select_pipe(physical_pipe);
00336          Host_disable_pipe();
00337          Host_unallocate_memory();
00338          Host_enable_pipe();
00339 
00340          // Build the pipe configuration according to the endpoint descriptors fields received
00341          //
00342          // host_configure_pipe(
00343          //    physical_pipe,                                                                    // pipe nb in USB interface
00344          //    data_stage[descriptor_offset+OFFSET_FIELD_EP_TYPE],                               // pipe type (interrupt/BULK/ISO)
00345          //    Get_pipe_token(data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR]),               // pipe addr
00346          //    (data_stage[descriptor_offset+2] & MSK_EP_DIR),                                   // pipe dir (IN/OUT)
00347          //    host_determine_pipe_size((U16)data_stage[descriptor_offset+OFFSET_FIELD_EP_SIZE]),// pipe size
00348          //    ONE_BANK,                                                                         // bumber of bank to allocate for pipe
00349          //    data_stage[descriptor_offset+OFFSET_FIELD_EP_INTERVAL]                            // interrupt period (for interrupt pipe)
00350          //  );
00351 
00352 #if (USB_HUB_SUPPORT==ENABLE)
00353          // For USB hub move from interupt type to bulk type
00354          if(data_stage[descriptor_offset+OFFSET_FIELD_EP_TYPE]==TYPE_INTERRUPT && usb_tree.device[device].interface[i].class==0x09)
00355          {
00356                host_configure_pipe(physical_pipe, \
00357                              TYPE_BULK, \
00358                              TOKEN_IN,  \
00359                              1,   \
00360                              SIZE_8,      \
00361                              ONE_BANK,     \
00362                              0             );  
00363          }
00364          else // The device connected is not a hub
00365          {
00366             if( nb_hub_present==0) // No hub already exist in the USB tree
00367             {
00368                host_configure_pipe(                                                          \
00369                   physical_pipe,                                                             \
00370                   data_stage[descriptor_offset+OFFSET_FIELD_EP_TYPE],                        \
00371                   Get_pipe_token(data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR]),        \
00372                   (data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR] & MSK_EP_DIR),                            \
00373                   host_determine_pipe_size((U16)data_stage[descriptor_offset+OFFSET_FIELD_EP_SIZE]),\
00374                   TWO_BANKS,                                                                  \
00375                   data_stage[descriptor_offset+OFFSET_FIELD_EP_INTERVAL]                     \
00376                );
00377             }
00378             else // At least one hub is present in the usb tree
00379             {
00380                if(data_stage[descriptor_offset+OFFSET_FIELD_EP_TYPE]==TYPE_BULK ) // If BULK type : OK
00381                {
00382                      host_configure_pipe(                                                          \
00383                      physical_pipe,                                                             \
00384                      data_stage[descriptor_offset+OFFSET_FIELD_EP_TYPE],                        \
00385                      Get_pipe_token(data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR]),        \
00386                      (data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR] & MSK_EP_DIR),                            \
00387                      host_determine_pipe_size((U16)data_stage[descriptor_offset+OFFSET_FIELD_EP_SIZE]),\
00388                      TWO_BANKS,                                                                  \
00389                      data_stage[descriptor_offset+OFFSET_FIELD_EP_INTERVAL]                     \
00390                   ); 
00391                }
00392                #if (USER_PERIODIC_PIPE==ENABLE)
00393                else
00394                if(user_periodic_pipe==0 )                  
00395                {
00396                   user_periodic_pipe=physical_pipe;
00397                   user_periodic_pipe_device_index=device;
00398                   host_configure_pipe(                                                          \
00399                      physical_pipe,                                                             \
00400                      data_stage[descriptor_offset+OFFSET_FIELD_EP_TYPE],                        \
00401                      Get_pipe_token(data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR]),        \
00402                      (data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR] & MSK_EP_DIR),                            \
00403                      host_determine_pipe_size((U16)data_stage[descriptor_offset+OFFSET_FIELD_EP_SIZE]),\
00404                      ONE_BANK,                                                                  \
00405                      data_stage[descriptor_offset+OFFSET_FIELD_EP_INTERVAL]                     \
00406                   );                  
00407                }
00408                else
00409                {
00410                   nb_endpoint_to_configure--;
00411                   usb_tree.device[device].interface[i].nb_ep--;
00412                   continue;                  
00413                }
00414                #endif
00415             }
00416          }
00417 #else // NO HUB SUPPORT
00418          host_configure_pipe(                                                          \
00419             physical_pipe,                                                             \
00420             data_stage[descriptor_offset+OFFSET_FIELD_EP_TYPE],                        \
00421             Get_pipe_token(data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR]),        \
00422             (data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR] & MSK_EP_DIR),                            \
00423             host_determine_pipe_size((U16)data_stage[descriptor_offset+OFFSET_FIELD_EP_SIZE]),\
00424             TWO_BANKS,                                                                 \
00425             data_stage[descriptor_offset+OFFSET_FIELD_EP_INTERVAL]                     \
00426          );
00427 #endif          
00428          
00429          // Update endpoint addr table in supported interface structure
00430          usb_tree.device[device].interface[i].ep[ep_index].ep_addr = data_stage[descriptor_offset+OFFSET_FIELD_EP_ADDR];
00431          // Update physical pipe number used for this endpoint
00432          usb_tree.device[device].interface[i].ep[ep_index].pipe_number = physical_pipe;
00433          // Update endpoint size in supported interface structure
00434          usb_tree.device[device].interface[i].ep[ep_index].ep_size = data_stage[descriptor_offset+OFFSET_FIELD_EP_SIZE];
00435          // Update endpoint type in supported interface structure
00436          usb_tree.device[device].interface[i].ep[ep_index].ep_type = data_stage[descriptor_offset+OFFSET_FIELD_EP_TYPE];
00437          // point on next descriptor
00438          descriptor_offset += data_stage[descriptor_offset];        
00439          // Use next physical pipe
00440          if (physical_pipe++>=MAX_EP_NB)
00441          {
00442              return HOST_FALSE;
00443          }
00444          // To configure next endpoint 
00445          ep_index++;
00446          // All target endpoints configured ?
00447          nb_endpoint_to_configure--;
00448       } //for(i=0;i<nb_interface;i++)
00449    }
00450    Host_set_configured();
00451    return HOST_TRUE;
00452 }
00453 
00465 T_DESC_OFFSET get_interface_descriptor_offset(U8 interface, U8 alt)
00466 {
00467    U8 nb_interface;
00468    T_DESC_OFFSET descriptor_offset;
00469 
00470    nb_interface = data_stage[OFFSET_FIELD_NB_INTERFACE];      // Detects the number of interfaces in this configuration
00471    descriptor_offset = data_stage[OFFSET_DESCRIPTOR_LENGHT];  // now pointing on next descriptor
00472 
00473    while(descriptor_offset < SIZEOF_DATA_STAGE)            // Look in all interfaces declared in the configuration
00474    {
00475       while (data_stage[descriptor_offset+OFFSET_FIELD_DESCRIPTOR_TYPE] != DESCRIPTOR_INTERFACE)
00476       {
00477          descriptor_offset += data_stage[descriptor_offset];
00478          if(descriptor_offset > SIZEOF_DATA_STAGE)
00479          {  return HOST_FALSE;  }
00480       }
00481       if (data_stage[descriptor_offset+OFFSET_FIELD_INTERFACE_NB]==interface
00482           && data_stage[descriptor_offset+OFFSET_FIELD_ALT]==alt)
00483       {
00484         return  descriptor_offset;
00485       }
00486       descriptor_offset += data_stage[descriptor_offset];
00487    }
00488    return descriptor_offset;
00489 }
00490 
00501 U8 host_get_hwd_pipe_nb(U8 ep_addr)
00502 {
00503    U8 i,j;
00504    for(j=0;j<MAX_INTERFACE_FOR_DEVICE;j++)
00505    {
00506       for(i=0;i<MAX_EP_PER_INTERFACE;i++)
00507       {
00508          if(usb_tree.device[selected_device].interface[j].ep[i].ep_addr==ep_addr)
00509          { return usb_tree.device[selected_device].interface[j].ep[i].pipe_number; }
00510       }
00511    }
00512    return 0;
00513 }
00514 
00531 U8 host_send_control(U8* data_pointer)
00532 {
00533 U16 data_length;
00534 U8 sav_int_sof_enable;
00535 U8 c;
00536 U8 ep_size_max;
00537 
00538 #if (USB_HUB_SUPPORT==ENABLE && USER_PERIODIC_PIPE==ENABLE)
00539    freeze_user_periodic_pipe();
00540 #endif 
00541 
00542    ep_size_max = usb_tree.device[selected_device].ep_ctrl_size;
00543    Host_configure_address(usb_tree.device[selected_device].device_address);
00544 
00545    Usb_ack_event(EVT_HOST_SOF);
00546    sav_int_sof_enable=Is_host_sof_interrupt_enabled();
00547    Host_enable_sof_interrupt();                   // SOF software detection is in interrupt sub-routine
00548    while(Is_not_usb_event(EVT_HOST_SOF))          // Wait 1 sof
00549    {
00550       if (Is_host_emergency_exit())
00551       {
00552          c=CONTROL_TIMEOUT;
00553          Host_freeze_pipe();
00554          Host_reset_pipe(0);
00555          goto host_send_control_end;
00556       }
00557    }
00558    if (sav_int_sof_enable==FALSE)
00559    {
00560       Host_disable_sof_interrupt();
00561    }
00562 
00563    Host_select_pipe(0);
00564    Host_set_token_setup();
00565    Host_ack_setup();
00566    Host_unfreeze_pipe();
00567   // Build the setup request fields
00568    Host_write_byte(usb_request.bmRequestType);
00569    Host_write_byte(usb_request.bRequest);
00570    Host_write_byte(LSB(usb_request.wValue));
00571    Host_write_byte(MSB(usb_request.wValue));
00572    Host_write_byte(LSB(usb_request.wIndex));
00573    Host_write_byte(MSB(usb_request.wIndex));
00574    Host_write_byte(LSB(usb_request.wLength));
00575    Host_write_byte(MSB(usb_request.wLength));
00576 
00577    Host_send_setup();
00578    while(Is_host_setup_sent() == FALSE)  // wait for SETUP ack
00579    {
00580       if (Is_host_emergency_exit())
00581       {
00582          c=CONTROL_TIMEOUT;
00583          Host_freeze_pipe();
00584          Host_reset_pipe(0);
00585          goto host_send_control_end;
00586       }
00587       if(Is_host_pipe_error())           // Any error ?
00588       {
00589          c = Host_error_status();
00590          Host_ack_all_errors();
00591          goto host_send_control_end;     // Send error status
00592       }
00593    }
00594   // Setup token sent now send In or OUT token
00595   // Before just wait one SOF
00596    Usb_ack_event(EVT_HOST_SOF);
00597    sav_int_sof_enable=Is_host_sof_interrupt_enabled();
00598    Host_enable_sof_interrupt();
00599    Host_freeze_pipe();
00600    data_length = usb_request.wLength;
00601    while(Is_not_usb_event(EVT_HOST_SOF))         // Wait 1 sof
00602    {
00603       if (Is_host_emergency_exit())
00604       {
00605          c=CONTROL_TIMEOUT;
00606          Host_freeze_pipe();
00607          Host_reset_pipe(0);
00608          goto host_send_control_end;
00609       }
00610    }
00611    if (sav_int_sof_enable==FALSE)
00612    {  Host_disable_sof_interrupt();  }   // Restore SOF interrupt enable
00613 
00614   // IN request management ---------------------------------------------
00615    if(usb_request.bmRequestType & USB_SETUP_DIR_DEVICE_TO_HOST)
00616    {
00617       Host_standard_in_mode();
00618       Host_set_token_in();
00619       Host_ack_control_in();
00620       while(data_length != 0)
00621       {
00622          Host_unfreeze_pipe();
00623          while(!Is_host_control_in_received())
00624          {
00625             if (Is_host_emergency_exit())
00626             {
00627                c=CONTROL_TIMEOUT;
00628                Host_freeze_pipe();
00629                Host_reset_pipe(0);
00630                goto host_send_control_end;
00631             }
00632             if(Is_host_pipe_error())
00633             {
00634                c = Host_error_status();
00635                Host_ack_all_errors();
00636                goto host_send_control_end;
00637             }
00638             if(Is_host_stall())
00639             {
00640                c=CONTROL_STALL;
00641                Host_ack_stall();
00642                goto host_send_control_end;
00643             }
00644          }
00645          c = Host_data_length_U8();
00646          if (c == ep_size_max)
00647          {
00648             data_length -= c;
00649             if (usb_request.uncomplete_read == TRUE)           // uncomplete_read
00650             {
00651                data_length = 0;
00652             }
00653          }
00654          else
00655          {
00656             data_length = 0;
00657          }
00658          while (c!=0)
00659          {
00660             *data_pointer = Host_read_byte();
00661             data_pointer++;
00662             c--;
00663          }
00664          Host_freeze_pipe();
00665          Host_ack_control_in();
00666          Host_send_control_in();
00667       }                                // end of IN data stage
00668 
00669       Host_set_token_out();
00670       Host_ack_control_out();
00671       Host_unfreeze_pipe();
00672       Host_send_control_out();
00673       while(!Is_host_control_out_sent())
00674       {
00675          if (Is_host_emergency_exit())
00676          {
00677             c=CONTROL_TIMEOUT;
00678             Host_freeze_pipe();
00679             Host_reset_pipe(0);
00680             goto host_send_control_end;
00681          }
00682          if(Is_host_pipe_error())
00683          {
00684             c = Host_error_status();
00685             Host_ack_all_errors();
00686             goto host_send_control_end;
00687          }
00688          if(Is_host_stall())
00689          {
00690             c=CONTROL_STALL;
00691             Host_ack_stall();
00692             goto host_send_control_end;
00693          }
00694       }
00695       Host_ack_control_out();
00696       c=(CONTROL_GOOD);
00697       goto host_send_control_end;
00698    }
00699 
00700   // OUT request management ---------------------------------------------
00701    else                                 // Data stage OUT (bmRequestType==0)
00702    {
00703       Host_set_token_out();
00704       Host_ack_control_out();
00705       while(data_length != 0)
00706       {
00707          Host_unfreeze_pipe();
00708          c = ep_size_max;
00709          if ( ep_size_max > data_length)
00710          {
00711             c = (U8)data_length;
00712             data_length = 0;
00713          }
00714          else
00715          {
00716             data_length -= c;
00717          }
00718          while (c!=0)
00719          {
00720             Host_write_byte(*data_pointer);
00721             data_pointer++;
00722             c--;
00723          }
00724          Host_send_control_out();
00725          while (!Is_host_control_out_sent())
00726          {
00727             if (Is_host_emergency_exit())
00728             {
00729                c=CONTROL_TIMEOUT;
00730                Host_freeze_pipe();
00731                Host_reset_pipe(0);
00732                goto host_send_control_end;
00733             }
00734             if(Is_host_pipe_error())
00735             {
00736                c = Host_error_status();
00737                Host_ack_all_errors();
00738                goto host_send_control_end;
00739             }
00740             if(Is_host_stall())
00741             {
00742                c=CONTROL_STALL;
00743                Host_ack_stall();
00744                goto host_send_control_end;
00745             }
00746          }
00747          Host_ack_control_out();
00748       }                                // end of OUT data stage
00749       Host_freeze_pipe();
00750       Host_set_token_in();
00751       Host_ack_in_received();
00752       Host_unfreeze_pipe();
00753       while(!Is_host_control_in_received())
00754       {
00755          if (Is_host_emergency_exit())
00756          {
00757             c=CONTROL_TIMEOUT;
00758             Host_freeze_pipe();
00759             Host_reset_pipe(0);
00760             goto host_send_control_end;
00761          }
00762          if(Is_host_pipe_error())
00763          {
00764             c = Host_error_status();
00765             Host_ack_all_errors();
00766             goto host_send_control_end;
00767          }
00768          if(Is_host_stall())
00769          {
00770             c=CONTROL_STALL;
00771             Host_ack_stall();
00772             goto host_send_control_end;
00773          }
00774       }
00775       Host_ack_control_in();
00776       Host_freeze_pipe();
00777       Host_send_control_in();
00778       c=(CONTROL_GOOD);
00779       goto host_send_control_end;
00780    }
00781 host_send_control_end:
00782 #if(USB_HUB_SUPPORT==ENABLE && USER_PERIODIC_PIPE==ENABLE)
00783    unfreeze_user_periodic_pipe();
00784 #endif  
00785    return ((U8)c);
00786 }
00787 
00795 void init_usb_tree(void)
00796 {
00797    U8 i;
00798   
00799    // Clear all device entry
00800    for(i=0;i<MAX_DEVICE_IN_USB_TREE;i++)
00801    {
00802       remove_device_entry(i);
00803    }
00804    // By default select device 0 (connected to root port)
00805    Host_select_device(0);
00806 
00807 #if (USB_HUB_SUPPORT==ENABLE)
00808    #if (USER_PERIODIC_PIPE==ENABLE)
00809    user_periodic_pipe=0;
00810    user_periodic_pipe_device_index=0;
00811    #endif
00812    for(i=0;i<HUB_MAX_NB_PORT;i++)
00813    hub_init(i);
00814    for(i=0;i<USB_MAX_HUB_NUMBER;i++)   
00815    hub_device_address[i]=0;
00816 #endif
00817 
00818    // Clear the number of device in the tree
00819    usb_tree.nb_device=0;
00820 
00821 }
00822 
00836 void remove_device_entry(U8 device_index)
00837 {
00838    U8 i,j,k,m;
00839    
00840 #if (USB_HUB_SUPPORT==ENABLE)   
00841    // Check if the disconnected device is a hub
00842    if(usb_tree.device[device_index].interface[0].class==HUB_CLASS)
00843    {
00844       nb_hub_present--; 
00845       for(i=0;i<USB_MAX_HUB_NUMBER;i++)      // For entire hub table
00846       {  // Find the hub number that deconnects
00847          if(hub_device_address[i]==usb_tree.device[device_index].device_address)
00848          {  // Reset its port state machine
00849             for(j=0;j<HUB_MAX_NB_PORT;j++)  // For all ports 
00850             {         
00851                hub_port_state[i][j]=HUB_DEVICE_POWERED; 
00852             }
00853             // Look devices previously connected to this hub and remove ther entries
00854             for(j=0;j<MAX_DEVICE_IN_USB_TREE;j++)
00855             {
00856                if(usb_tree.device[j].parent_hub_number==(i+1))
00857                {
00858                   usb_tree.nb_device--;
00859                   // Caution recursive function !!!!
00860                   remove_device_entry(j);                  
00861                }
00862             }
00863             hub_device_address[i]=0;
00864             break;
00865          }
00866       }
00867    }
00868 #endif   
00869 
00870    // Unallocate USB pipe memory only if the device disconnection is the last device 
00871    // enumerated
00872    // TODO: Improve it for devices removing from hub.
00873    // But cannot unallocate USB DPRAM if there is an active pipe number > current pipe for the removed device....
00874    if(usb_tree.nb_device==device_index+1)
00875    {
00876       for(j=0;j<MAX_INTERFACE_FOR_DEVICE;j++)
00877       {
00878          for(k=0;k<MAX_EP_PER_INTERFACE;k++)
00879          {
00880             m=usb_tree.device[device_index].interface[j].ep[k].pipe_number;
00881             if(m!=0)
00882             {
00883                i = Host_get_selected_pipe();
00884                Host_select_pipe(m);
00885                Host_unallocate_memory();
00886                Host_select_pipe(i);
00887             }
00888          }
00889       }
00890    }
00891    // Reset device entry fields ...
00892    usb_tree.device[device_index].device_address = 0;
00893    usb_tree.device[device_index].ep_ctrl_size = 0;
00894    usb_tree.device[device_index].hub_port_nb = 0;
00895    usb_tree.device[device_index].parent_hub_number = 0;
00896    usb_tree.device[device_index].nb_interface = 0;
00897    usb_tree.device[device_index].pid = 0;
00898    usb_tree.device[device_index].vid = 0;
00899    usb_tree.device[device_index].bmattributes = 0;   
00900    usb_tree.device[device_index].maxpower = 0;   
00901    
00902    for(j=0;j<MAX_INTERFACE_FOR_DEVICE;j++)
00903    {
00904       usb_tree.device[device_index].interface[j].interface_nb = 0;
00905       usb_tree.device[device_index].interface[j].altset_nb = 0;
00906       usb_tree.device[device_index].interface[j].class = 0;
00907       usb_tree.device[device_index].interface[j].subclass = 0;
00908       usb_tree.device[device_index].interface[j].protocol = 0;
00909       usb_tree.device[device_index].interface[j].nb_ep = 0;
00910       for(k=0;k<MAX_EP_PER_INTERFACE;k++)
00911       {
00912          usb_tree.device[device_index].interface[j].ep[k].ep_addr = 0;
00913          usb_tree.device[device_index].interface[j].ep[k].pipe_number = 0;
00914          usb_tree.device[device_index].interface[j].ep[k].ep_size = 0;
00915          usb_tree.device[device_index].interface[j].ep[k].ep_type = 0;
00916       }
00917    }   
00918 }
00919 
00920 
00921 // @TODO USER_PERIODIC_PIPE==ENABLE not validated
00922 #if (USB_HUB_SUPPORT==ENABLE && USER_PERIODIC_PIPE==ENABLE)
00923 void freeze_user_periodic_pipe(void)
00924 {
00925    if(user_periodic_pipe)
00926    {
00927       Host_select_pipe(user_periodic_pipe);
00928       if(Is_host_pipe_freeze()) 
00929       {
00930          user_periodic_pipe_freeze_state=0;
00931       }
00932       else
00933       {
00934          user_periodic_pipe_freeze_state=1;
00935          Host_freeze_pipe();
00936       }
00937    } 
00938 }
00939 #endif
00940 
00941 #if (USB_HUB_SUPPORT==ENABLE && USER_PERIODIC_PIPE==ENABLE)
00942 void unfreeze_user_periodic_pipe(void)
00943 {
00944    if(user_periodic_pipe)
00945    {
00946       if(user_periodic_pipe_freeze_state)
00947       {   
00948          Host_select_pipe(user_periodic_pipe);
00949          Host_unfreeze_pipe();
00950       }
00951       Host_select_device(user_periodic_pipe_device_index);
00952    }   
00953 }
00954 #endif
00955 
00956 #if (USB_HUB_SUPPORT==ENABLE && USER_PERIODIC_PIPE==ENABLE)
00957 void host_select_device(U8 i)
00958 {
00959    freeze_user_periodic_pipe();
00960    selected_device=i;
00961    Host_configure_address(usb_tree.device[i].device_address);
00962 }
00963 #endif
00964 
00965 
00966 #endif   //(USB_HOST_FEATURE == ENABLED)
00967 

Generated on Mon Sep 14 13:24:11 2009 for ATMEL by  doxygen 1.5.3