ATMEL: usb_host_enum.c Source File

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

# 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