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 , false , 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 // Start the 'explore thread' 65 m_explore_thread = spawn_kernel_thread( usb_explore_thread , "usb_busmanager_explore" , 66 B_LOW_PRIORITY , (void *)m_roothub ); 67 resume_thread( m_explore_thread ); 68 69 m_initok = true; 70 } 71 72 BusManager::~BusManager() 73 { 74 } 75 76 status_t BusManager::InitCheck() 77 { 78 if ( m_initok == true ) 79 return B_OK; 80 else 81 return B_ERROR; 82 } 83 84 Device * BusManager::AllocateNewDevice( Device *parent , bool lowspeed ) 85 { 86 int8 devicenum; 87 status_t retval; 88 usb_device_descriptor device_descriptor; 89 90 //1. Check if there is a free entry in the device map (for the device number) 91 devicenum = AllocateAddress(); 92 if ( devicenum < 0 ) 93 { 94 dprintf( "usb Busmanager [new device]: could not get a new address\n" ); 95 return 0; 96 } 97 98 99 //2. Set the address of the device USB 1.1 spec p202 (bepdf) 100 retval = m_defaultPipe->SendRequest( USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD , //host->device 101 USB_REQUEST_SET_ADDRESS , //request 102 devicenum , //value 103 0 , //index 104 0 , //length 105 NULL , //data 106 0 , //data_len 107 0 ); //actual len 108 109 if ( retval < B_OK ) 110 { 111 dprintf( "usb busmanager [new device]: error with commmunicating the right address\n" ); 112 return 0; 113 } 114 115 //Create a temporary pipe 116 ControlPipe pipe( this , devicenum , Pipe::Default , Pipe::LowSpeed , 0 ); 117 118 //3. Get the device descriptor 119 // Just retrieve the first 8 bytes of the descriptor -> minimum supported 120 // size of any device, plus it is enough, because the device type is in 121 // there too 122 123 size_t actual_length; 124 125 pipe.SendRequest( USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD , //Type 126 USB_REQUEST_GET_DESCRIPTOR , //Request 127 ( USB_DESCRIPTOR_DEVICE << 8 ), //Value 128 0 , //Index 129 8 , //Length 130 (void *)&device_descriptor , //Buffer 131 8 , //Bufferlength 132 &actual_length ); //length 133 134 if ( actual_length != 8 ) 135 { 136 dprintf( "usb busmanager [new device]: error while getting the device descriptor\n" ); 137 return 0; 138 } 139 140 //4. Create a new instant based on the type (Hub or Device); 141 if ( device_descriptor.device_class == 0x09 ) 142 { 143 dprintf( "usb Busmanager [new device]: New hub\n" ); 144 Device *ret = new Hub( this , parent , device_descriptor , devicenum , lowspeed ); 145 if ( parent == 0 ) //root hub!! 146 m_roothub = ret; 147 return ret; 148 } 149 150 dprintf( "usb Busmanager [new device]: New normal device\n" ); 151 return new Device( this , parent , device_descriptor , devicenum , lowspeed); 152 } 153 154 int8 BusManager::AllocateAddress() 155 { 156 acquire_sem_etc( m_lock , 1 , B_CAN_INTERRUPT , 0 ); 157 int8 devicenum = -1; 158 for( int i = 1 ; i < 128 ; i++ ) 159 { 160 if ( m_devicemap[i] == false ) 161 { 162 devicenum = i; 163 m_devicemap[i] = true; 164 break; 165 } 166 } 167 release_sem( m_lock ); 168 return devicenum; 169 } 170 171 status_t BusManager::Start() 172 { 173 if ( InitCheck() != B_OK ) 174 return InitCheck(); 175 176 // Start the 'explore thread' 177 m_explore_thread = spawn_kernel_thread( usb_explore_thread , "usb_busmanager_explore" , 178 B_LOW_PRIORITY , (void *)m_roothub ); 179 return resume_thread( m_explore_thread ); 180 } 181 182 status_t BusManager::SubmitTransfer( Transfer &t ) 183 { 184 return B_ERROR; 185 }; 186