1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2003-2004, Niels S. Reedijk 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 // DEALINGS IN THE SOFTWARE. 21 22 #include "usb_p.h" 23 24 25 /* +++++++++ 26 This is the 'main' function of the explore thread, which keeps track of 27 the hub statuses. 28 +++++++++ */ 29 int32 usb_explore_thread( void *data ) 30 { 31 Hub *roothub = (Hub *)data; 32 33 if ( roothub == 0 ) 34 return B_ERROR; 35 36 while ( true ) 37 { 38 //Go to the hubs 39 roothub->Explore(); 40 snooze(1000000); //Wait one second before continueing 41 } 42 return B_OK; 43 } 44 45 46 BusManager::BusManager() 47 { 48 m_initok = false; 49 m_roothub = 0; 50 51 // Set up the semaphore 52 m_lock = create_sem( 1 , "buslock" ); 53 if( m_lock < B_OK ) 54 return; 55 set_sem_owner( B_SYSTEM_TEAM , m_lock ); 56 57 // Clear the device map 58 memset( &m_devicemap , 0 , 128 ); 59 60 // Set up the default pipes 61 m_defaultPipe = new ControlPipe( this , 0 , Pipe::Default , Pipe::NormalSpeed , 0 ); 62 m_defaultLowSpeedPipe = new ControlPipe( this , 0 , Pipe::Default , Pipe::LowSpeed , 0 ); 63 64 // Clear the 'explore thread' 65 m_explore_thread = 0; 66 67 m_initok = true; 68 } 69 70 BusManager::~BusManager() 71 { 72 } 73 74 status_t BusManager::InitCheck() 75 { 76 if ( m_initok == true ) 77 return B_OK; 78 else 79 return B_ERROR; 80 } 81 82 Device * BusManager::AllocateNewDevice( Device *parent , bool lowspeed ) 83 { 84 int8 devicenum; 85 status_t retval; 86 usb_device_descriptor device_descriptor; 87 88 //1. Check if there is a free entry in the device map (for the device number) 89 devicenum = AllocateAddress(); 90 if ( devicenum < 0 ) 91 { 92 dprintf( "usb Busmanager [new device]: could not get a new address\n" ); 93 return 0; 94 } 95 96 97 //2. Set the address of the device USB 1.1 spec p202 (bepdf) 98 retval = m_defaultPipe->SendRequest( USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD , //host->device 99 USB_REQUEST_SET_ADDRESS , //request 100 devicenum , //value 101 0 , //index 102 0 , //length 103 NULL , //data 104 0 , //data_len 105 0 ); //actual len 106 107 if ( retval < B_OK ) 108 { 109 dprintf( "usb busmanager [new device]: error with commmunicating the right address\n" ); 110 return 0; 111 } 112 113 //Create a temporary pipe 114 ControlPipe pipe( this , devicenum , Pipe::Default , Pipe::LowSpeed , 0 ); 115 116 //3. Get the device descriptor 117 // Just retrieve the first 8 bytes of the descriptor -> minimum supported 118 // size of any device, plus it is enough, because the device type is in 119 // there too 120 121 size_t actual_length; 122 123 pipe.SendRequest( USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD , //Type 124 USB_REQUEST_GET_DESCRIPTOR , //Request 125 ( USB_DESCRIPTOR_DEVICE << 8 ), //Value 126 0 , //Index 127 8 , //Length 128 (void *)&device_descriptor , //Buffer 129 8 , //Bufferlength 130 &actual_length ); //length 131 132 if ( actual_length != 8 ) 133 { 134 dprintf( "usb busmanager [new device]: error while getting the device descriptor\n" ); 135 return 0; 136 } 137 138 //4. Create a new instant based on the type (Hub or Device); 139 if ( device_descriptor.device_class == 0x09 ) 140 { 141 dprintf( "usb Busmanager [new device]: New hub\n" ); 142 Device *ret = new Hub( this , parent , device_descriptor , devicenum , lowspeed ); 143 if ( parent == 0 ) //root hub!! 144 m_roothub = ret; 145 return 0; 146 } 147 148 dprintf( "usb Busmanager [new device]: New normal device\n" ); 149 return new Device( this , parent , device_descriptor , devicenum , lowspeed); 150 } 151 152 int8 BusManager::AllocateAddress() 153 { 154 acquire_sem_etc( m_lock , 1 , B_CAN_INTERRUPT , 0 ); 155 int8 devicenum = -1; 156 for( int i = 1 ; i < 128 ; i++ ) 157 { 158 if ( m_devicemap[i] == false ) 159 { 160 devicenum = i; 161 m_devicemap[i] = true; 162 break; 163 } 164 } 165 release_sem( m_lock ); 166 return devicenum; 167 } 168 169 status_t BusManager::Start() 170 { 171 dprintf( "USB: BusManager::Start()\n" ); 172 if ( InitCheck() != B_OK ) 173 return InitCheck(); 174 175 if ( m_explore_thread == 0 ) 176 m_explore_thread = spawn_kernel_thread( usb_explore_thread , "usb_busmanager_explore" , 177 B_LOW_PRIORITY , (void *)m_roothub ); 178 179 // Start the 'explore thread' 180 return resume_thread( m_explore_thread ); 181 } 182 183 status_t BusManager::SubmitTransfer( Transfer *t ) 184 { 185 return B_ERROR; 186 }; 187