usb_host_enum.c

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

Generated on Mon Nov 3 10:08:24 2008 for ATMEL by  doxygen 1.5.3