xref: /haiku/src/add-ons/kernel/bus_managers/usb/BusManager.cpp (revision d1d811ec7007913f727f6b44d2d730554eacfa19)
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