- Main Page
- Modules
- Data Structures
- Files
- Related Pages

# 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, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 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       Host_ack_control_in();
    00617       while(data_length != 0)
    00618       {
    00619          Host_unfreeze_pipe();
    00620          while(!Is_host_control_in_received())
    00621          {
    00622             if (Is_host_emergency_exit())
    00623             {
    00624                c=CONTROL_TIMEOUT;
    00625                Host_freeze_pipe();
    00626                Host_reset_pipe(0);
    00627                goto host_send_control_end;
    00628             }
    00629             if(Is_host_pipe_error())
    00630             {
    00631                c = Host_error_status();
    00632                Host_ack_all_errors();
    00633                goto host_send_control_end;
    00634             }
    00635             if(Is_host_stall())
    00636             {
    00637                c=CONTROL_STALL;
    00638                Host_ack_stall();
    00639                goto host_send_control_end;
    00640             }
    00641          }
    00642          c = Host_data_length_U8();
    00643          if (c == ep_size_max)
    00644          {
    00645             data_length -= c;
    00646             if (usb_request.uncomplete_read == TRUE)           // uncomplete_read
    00647             {
    00648                data_length = 0;
    00649             }
    00650          }
    00651          else
    00652          {
    00653             data_length = 0;
    00654          }
    00655          while (c!=0)
    00656          {
    00657             *data_pointer = Host_read_byte();
    00658             data_pointer++;
    00659             c--;
    00660          }
    00661          Host_freeze_pipe();
    00662          Host_ack_control_in();
    00663          Host_send_control_in();
    00664       }                                // end of IN data stage
    00665
    00666       Host_set_token_out();
    00667       Host_ack_control_out();
    00668       Host_unfreeze_pipe();
    00669       Host_send_control_out();
    00670       while(!Is_host_control_out_sent())
    00671       {
    00672          if (Is_host_emergency_exit())
    00673          {
    00674             c=CONTROL_TIMEOUT;
    00675             Host_freeze_pipe();
    00676             Host_reset_pipe(0);
    00677             goto host_send_control_end;
    00678          }
    00679          if(Is_host_pipe_error())
    00680          {
    00681             c = Host_error_status();
    00682             Host_ack_all_errors();
    00683             goto host_send_control_end;
    00684          }
    00685          if(Is_host_stall())
    00686          {
    00687             c=CONTROL_STALL;
    00688             Host_ack_stall();
    00689             goto host_send_control_end;
    00690          }
    00691       }
    00692       Host_ack_control_out();
    00693       c=(CONTROL_GOOD);
    00694       goto host_send_control_end;
    00695    }
    00696
    00697   // OUT request management ---------------------------------------------
    00698    else                                 // Data stage OUT (bmRequestType==0)
    00699    {
    00700       Host_set_token_out();
    00701       Host_ack_control_out();
    00702       while(data_length != 0)
    00703       {
    00704          Host_unfreeze_pipe();
    00705          c = ep_size_max;
    00706          if ( ep_size_max > data_length)
    00707          {
    00708             c = (U8)data_length;
    00709             data_length = 0;
    00710          }
    00711          else
    00712          {
    00713             data_length -= c;
    00714          }
    00715          while (c!=0)
    00716          {
    00717             Host_write_byte(*data_pointer);
    00718             data_pointer++;
    00719             c--;
    00720          }
    00721          Host_send_control_out();
    00722          while (!Is_host_control_out_sent())
    00723          {
    00724             if (Is_host_emergency_exit())
    00725             {
    00726                c=CONTROL_TIMEOUT;
    00727                Host_freeze_pipe();
    00728                Host_reset_pipe(0);
    00729                goto host_send_control_end;
    00730             }
    00731             if(Is_host_pipe_error())
    00732             {
    00733                c = Host_error_status();
    00734                Host_ack_all_errors();
    00735                goto host_send_control_end;
    00736             }
    00737             if(Is_host_stall())
    00738             {
    00739                c=CONTROL_STALL;
    00740                Host_ack_stall();
    00741                goto host_send_control_end;
    00742             }
    00743          }
    00744          Host_ack_control_out();
    00745       }                                // end of OUT data stage
    00746       Host_freeze_pipe();
    00747       Host_set_token_in();
    00748       Host_ack_in_received();
    00749       Host_unfreeze_pipe();
    00750       while(!Is_host_control_in_received())
    00751       {
    00752          if (Is_host_emergency_exit())
    00753          {
    00754             c=CONTROL_TIMEOUT;
    00755             Host_freeze_pipe();
    00756             Host_reset_pipe(0);
    00757             goto host_send_control_end;
    00758          }
    00759          if(Is_host_pipe_error())
    00760          {
    00761             c = Host_error_status();
    00762             Host_ack_all_errors();
    00763             goto host_send_control_end;
    00764          }
    00765          if(Is_host_stall())
    00766          {
    00767             c=CONTROL_STALL;
    00768             Host_ack_stall();
    00769             goto host_send_control_end;
    00770          }
    00771       }
    00772       Host_ack_control_in();
    00773       Host_freeze_pipe();
    00774       Host_send_control_in();
    00775       c=(CONTROL_GOOD);
    00776       goto host_send_control_end;
    00777    }
    00778 host_send_control_end:
    00779 #if(USB_HUB_SUPPORT==ENABLE && USER_PERIODIC_PIPE==ENABLE)
    00780    unfreeze_user_periodic_pipe();
    00781 #endif
    00782    return ((U8)c);
    00783 }
    00784
    00792 void init_usb_tree(void)
    00793 {
    00794    U8 i;
    00795
    00796    // Clear all device entry
    00797    for(i=0;i<MAX_DEVICE_IN_USB_TREE;i++)
    00798    {
    00799       remove_device_entry(i);
    00800    }
    00801    // By default select device 0 (connected to root port)
    00802    Host_select_device(0);
    00803
    00804 #if (USB_HUB_SUPPORT==ENABLE)
    00805    #if (USER_PERIODIC_PIPE==ENABLE)
    00806    user_periodic_pipe=0;
    00807    user_periodic_pipe_device_index=0;
    00808    #endif
    00809    for(i=0;i<HUB_MAX_NB_PORT;i++)
    00810    hub_init(i);
    00811    for(i=0;i<USB_MAX_HUB_NUMBER;i++)
    00812    hub_device_address[i]=0;
    00813 #endif
    00814
    00815    // Clear the number of device in the tree
    00816    usb_tree.nb_device=0;
    00817
    00818 }
    00819
    00833 void remove_device_entry(U8 device_index)
    00834 {
    00835    U8 i,j,k,m;
    00836
    00837 #if (USB_HUB_SUPPORT==ENABLE)
    00838    // Check if the disconnected device is a hub
    00839    if(usb_tree.device[device_index].interface[0].class==HUB_CLASS)
    00840    {
    00841       nb_hub_present--;
    00842       for(i=0;i<USB_MAX_HUB_NUMBER;i++)      // For entire hub table
    00843       {  // Find the hub number that deconnects
    00844          if(hub_device_address[i]==usb_tree.device[device_index].device_address)
    00845          {  // Reset its port state machine
    00846             for(j=0;j<HUB_MAX_NB_PORT;j++)  // For all ports
    00847             {
    00848                hub_port_state[i][j]=HUB_DEVICE_POWERED;
    00849             }
    00850             // Look devices previously connected to this hub and remove ther entries
    00851             for(j=0;j<MAX_DEVICE_IN_USB_TREE;j++)
    00852             {
    00853                if(usb_tree.device[j].parent_hub_number==(i+1))
    00854                {
    00855                   usb_tree.nb_device--;
    00856                   // Caution recursive function !!!!
    00857                   remove_device_entry(j);
    00858                }
    00859             }
    00860             hub_device_address[i]=0;
    00861             break;
    00862          }
    00863       }
    00864    }
    00865 #endif
    00866
    00867    // Unallocate USB pipe memory only if the device disconnection is the last device
    00868    // enumerated
    00869    // TODO: Improve it for devices removing from hub.
    00870    // But cannot unallocate USB DPRAM if there is an active pipe number > current pipe for the removed device....
    00871    if(usb_tree.nb_device==device_index+1)
    00872    {
    00873       for(j=0;j<MAX_INTERFACE_FOR_DEVICE;j++)
    00874       {
    00875          for(k=0;k<MAX_EP_PER_INTERFACE;k++)
    00876          {
    00877             m=usb_tree.device[device_index].interface[j].ep[k].pipe_number;
    00878             if(m!=0)
    00879             {
    00880                i = Host_get_selected_pipe();
    00881                Host_select_pipe(m);
    00882                Host_unallocate_memory();
    00883                Host_select_pipe(i);
    00884             }
    00885          }
    00886       }
    00887    }
    00888    // Reset device entry fields ...
    00889    usb_tree.device[device_index].device_address = 0;
    00890    usb_tree.device[device_index].ep_ctrl_size = 0;
    00891    usb_tree.device[device_index].hub_port_nb = 0;
    00892    usb_tree.device[device_index].parent_hub_number = 0;
    00893    usb_tree.device[device_index].nb_interface = 0;
    00894    usb_tree.device[device_index].pid = 0;
    00895    usb_tree.device[device_index].vid = 0;
    00896    usb_tree.device[device_index].bmattributes = 0;
    00897    usb_tree.device[device_index].maxpower = 0;
    00898
    00899    for(j=0;j<MAX_INTERFACE_FOR_DEVICE;j++)
    00900    {
    00901       usb_tree.device[device_index].interface[j].interface_nb = 0;
    00902       usb_tree.device[device_index].interface[j].altset_nb = 0;
    00903       usb_tree.device[device_index].interface[j].class = 0;
    00904       usb_tree.device[device_index].interface[j].subclass = 0;
    00905       usb_tree.device[device_index].interface[j].protocol = 0;
    00906       usb_tree.device[device_index].interface[j].nb_ep = 0;
    00907       for(k=0;k<MAX_EP_PER_INTERFACE;k++)
    00908       {
    00909          usb_tree.device[device_index].interface[j].ep[k].ep_addr = 0;
    00910          usb_tree.device[device_index].interface[j].ep[k].pipe_number = 0;
    00911          usb_tree.device[device_index].interface[j].ep[k].ep_size = 0;
    00912          usb_tree.device[device_index].interface[j].ep[k].ep_type = 0;
    00913       }
    00914    }
    00915 }
    00916
    00917
    00918 // @TODO USER_PERIODIC_PIPE==ENABLE not validated
    00919 #if (USB_HUB_SUPPORT==ENABLE && USER_PERIODIC_PIPE==ENABLE)
    00920 void freeze_user_periodic_pipe(void)
    00921 {
    00922    if(user_periodic_pipe)
    00923    {
    00924       Host_select_pipe(user_periodic_pipe);
    00925       if(Is_host_pipe_freeze())
    00926       {
    00927          user_periodic_pipe_freeze_state=0;
    00928       }
    00929       else
    00930       {
    00931          user_periodic_pipe_freeze_state=1;
    00932          Host_freeze_pipe();
    00933       }
    00934    }
    00935 }
    00936 #endif
    00937
    00938 #if (USB_HUB_SUPPORT==ENABLE && USER_PERIODIC_PIPE==ENABLE)
    00939 void unfreeze_user_periodic_pipe(void)
    00940 {
    00941    if(user_periodic_pipe)
    00942    {
    00943       if(user_periodic_pipe_freeze_state)
    00944       {
    00945          Host_select_pipe(user_periodic_pipe);
    00946          Host_unfreeze_pipe();
    00947       }
    00948       Host_select_device(user_periodic_pipe_device_index);
    00949    }
    00950 }
    00951 #endif
    00952
    00953 #if (USB_HUB_SUPPORT==ENABLE && USER_PERIODIC_PIPE==ENABLE)
    00954 void host_select_device(U8 i)
    00955 {
    00956    freeze_user_periodic_pipe();
    00957    selected_device=i;
    00958    Host_configure_address(usb_tree.device[i].device_address);
    00959 }
    00960 #endif
    00961
    00962
    00963 #endif   //(USB_HOST_FEATURE == ENABLED)
    00964