1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2003, 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 while (true ) 34 { 35 //Go to the hubs 36 roothub->Explore(); 37 snooze(10000); //Wait one second before continueing 38 } 39 return B_OK; 40 } 41 42 43 BusManager::BusManager( host_controller_info *info ) 44 { 45 hcpointer = info; 46 m_initok = false; 47 m_roothub = 0; 48 49 // Set up the semaphore 50 m_lock = create_sem( 1 , "buslock" ); 51 if( m_lock < B_OK ) 52 return; 53 set_sem_owner( B_SYSTEM_TEAM , m_lock ); 54 55 // Clear the device map 56 memset( &m_devicemap , false , 128 ); 57 58 // Set up the new root hub 59 AllocateNewDevice( 0 ); 60 61 if( m_roothub == 0 ) 62 return; 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 put_module( hcpointer->info.name ); 75 } 76 77 status_t BusManager::InitCheck() 78 { 79 if ( m_initok == true ) 80 return B_OK; 81 else 82 return B_ERROR; 83 } 84 85 Device * BusManager::AllocateNewDevice( Device *parent ) 86 { 87 int8 devicenum; 88 status_t retval; 89 usb_device_descriptor device_descriptor; 90 91 //1. Check if there is a free entry in the device map (for the device number) 92 devicenum = AllocateAddress(); 93 if ( devicenum < 0 ) 94 { 95 dprintf( "usb Busmanager [new device]: could not get a new address\n" ); 96 return 0; 97 } 98 99 //2. Set the address of the device USB 1.1 spec p202 (bepdf) 100 retval = SendRequest( 0 , 101 USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD , //host->device 102 USB_REQUEST_SET_ADDRESS , //request 103 devicenum , //value 104 0 , //index 105 0 , //length 106 NULL , //data 107 0 , //data_len 108 0 ); //actual len 109 110 if ( retval < B_OK ) 111 { 112 dprintf( "usb busmanager [new device]: error with commmunicating the right address\n" ); 113 return 0; 114 } 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 SendRequest( 0 , 124 USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD , //Type 125 USB_REQUEST_GET_DESCRIPTOR , //Request 126 ( USB_DESCRIPTOR_DEVICE << 8 ), //Value 127 0 , //Index 128 8 , //Length 129 (void *)&device_descriptor , //Buffer 130 8 , //Bufferlength 131 &actual_length ); //length 132 133 if ( actual_length != 8 ) 134 { 135 dprintf( "usb busmanager [new device]: error while getting the device descriptor\n" ); 136 return 0; 137 } 138 139 //4. Create a new instant based on the type (Hub or Device); 140 if ( device_descriptor.device_class == 0x09 ) 141 { 142 dprintf( "usb Busmanager [new device]: New hub\n" ); 143 Device *ret = new Hub( this , parent , device_descriptor , devicenum ); 144 if ( parent == 0 ) //root hub!! 145 m_roothub = ret; 146 return ret; 147 } 148 149 dprintf( "usb Busmanager [new device]: New normal device\n" ); 150 return new Device( this , parent , device_descriptor , devicenum ); 151 } 152 153 int8 BusManager::AllocateAddress() 154 { 155 acquire_sem_etc( m_lock , 1 , B_CAN_INTERRUPT , 0 ); 156 int8 devicenum = -1; 157 for( int i = 0 ; i < 128 ; i++ ) 158 { 159 if ( m_devicemap[i] == false ) 160 { 161 devicenum = i; 162 m_devicemap[i] = true; 163 break; 164 } 165 } 166 release_sem( m_lock ); 167 return devicenum; 168 } 169 170 status_t BusManager::SendRequest( Device * dev , uint8 request_type , uint8 request , uint16 value , 171 uint16 index , uint16 length , void *data , 172 size_t data_len , size_t *actual_len ) 173 { 174 //todo: het moet speciaal soort geheugen worden 175 usb_request_data *req = (usb_request_data *)malloc( sizeof( usb_request_data) ); 176 177 req->RequestType = request_type; 178 req->Request = request; 179 req->Value = value; 180 req->Index = index; 181 req->Length = length; 182 183 //Nicen up the second argument: the default pipe 184 //1) set up the pipe stuff a little nicer 185 //2) don't assume it's a low speed device :-( 186 return SendControlMessage( dev , ( 2 << 30 | 1 << 26 ) , req , 187 data , data_len , actual_len , 3 * 1000 * 1000 ); 188 } 189 190 status_t BusManager::SendControlMessage( Device *dev , uint16 pipe , 191 usb_request_data *command , void *data , 192 size_t data_length , size_t *actual_length , 193 bigtime_t timeout ) 194 { 195 // this method should build an usb packet (new class) with the needed data 196 Packet packet; 197 198 packet.SetPipe( pipe ); 199 packet.SetRequestData( (uint8 *)command ); 200 packet.SetBuffer( (uint8 *)data ); 201 packet.SetBufferLength( data_length ); 202 packet.SetActualLength( actual_length ); 203 packet.SetAddress( 0 ); 204 205 status_t retval = hcpointer->SubmitPacket( packet.GetData() ); 206 return retval; 207 } 208 209