xref: /haiku/src/add-ons/kernel/bus_managers/usb/Hub.cpp (revision 67bce78b48ed6d01b5a8eef89f5694c372b7e0a1)
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 Hub::Hub(  BusManager *bus , Device *parent , usb_device_descriptor &desc , int8 devicenum )
25    : Device ( bus , parent , desc , devicenum )
26 {
27 	dprintf( "USB Hub is being initialised\n" );
28 	m_initok = false; // We're not yet ready!
29 	size_t actual_length;
30 
31 
32 	if( m_device_descriptor.device_subclass != 0 || m_device_descriptor.device_protocol != 0 )
33 	{
34 		dprintf( "USB Hub: wrong class/subclass/protocol! Bailing out\n" );
35 		return;
36 	}
37 
38 	if ( m_current_configuration->number_interfaces > 1 )
39 	{
40 		dprintf( "USB Hub: too much interfaces! Bailing out\n" );
41 		return;
42 	}
43 
44 	dprintf( "USB Hub this: %p" , this );
45 
46 	if ( GetDescriptor( USB_DESCRIPTOR_INTERFACE , 0 ,
47 	                    (void *)&m_interrupt_interface ,
48 	                    sizeof (usb_interface_descriptor) ) != sizeof( usb_interface_descriptor ) )
49 	{
50 		dprintf( "USB Hub: error getting the interrupt interface! Bailing out.\n" );
51 		return;
52 	}
53 
54 	if ( m_interrupt_interface.num_endpoints > 1 )
55 	{
56 		dprintf( "USB Hub: too much endpoints! Bailing out.\n" );
57 		return;
58 	}
59 
60 	if ( GetDescriptor( USB_DESCRIPTOR_ENDPOINT , 0 ,
61 	                    (void *)&m_interrupt_endpoint ,
62 	                    sizeof (usb_endpoint_descriptor) ) != sizeof (usb_endpoint_descriptor ) )
63 	{
64 		dprintf( "USB Hub: Error getting the endpoint. Bailing out\n" );
65 		return;
66 	}
67 
68 	if ( m_interrupt_endpoint.attributes != 0x03 ) //interrupt transfer
69 	{
70 		dprintf( "USB Hub: Not an interrupt endpoint. Bailing out\n" );
71 		return;
72 	}
73 
74 	dprintf( "USB Hub: Getting hub descriptor...\n" );
75 	if ( GetDescriptor( USB_DESCRIPTOR_HUB , 0 ,
76 						(void *)&m_hub_descriptor ,
77 						sizeof (usb_hub_descriptor) ) != sizeof (usb_hub_descriptor ) )
78 	{
79 		dprintf( "USB Hub: Error getting hub descriptor\n" );
80 		return;
81 	}
82 
83 	// Enable port power on all ports
84 	for ( int i = 0 ; i < m_hub_descriptor.bNbrPorts ; i++ )
85 		m_bus->SendRequest( this , USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT ,
86 		                    USB_REQUEST_SET_FEATURE ,
87 		                    PORT_POWER ,
88 		                    i + 1 , //index
89 		                    0 ,
90 		                    NULL ,
91 		                    0 ,
92 		                    &actual_length );
93 	//Wait for power to stabilize
94 	snooze( m_hub_descriptor.bPwrOn2PwrGood * 2 );
95 
96 	//We're basically done now
97 	m_initok = true;
98 }
99 
100 void Hub::Explore()
101 {
102 	size_t actual_length;
103 
104 	for ( int i = 0 ; i < m_hub_descriptor.bNbrPorts ; i++ )
105 	{
106 		// Get the current port status
107 		m_bus->SendRequest( this , USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_IN ,
108 		                    USB_REQUEST_GET_STATUS ,
109 		                    0 , //Value
110 		                    i + 1 , //Index
111 		                    4 ,  //length
112 		                    (void *)&m_port_status[i],
113 		                    4 ,
114 		                    &actual_length );
115 		if ( actual_length < 4 )
116 		{
117 			dprintf( "USB Hub: ERROR getting port status" );
118 			return;
119 		}
120 
121 		//We need to test the port change against a number of things
122 		if ( m_port_status[i].change & PORT_STATUS_CONNECTION )
123 		{
124 			if ( m_port_status[i].status & PORT_STATUS_CONNECTION )
125 			{
126 				//New device attached!
127 				//DO something
128 				dprintf( "USB Hub Explore(): New device connected\n" );
129 
130 			}
131 			else
132 			{
133 				//Device removed...
134 				//DO something
135 				dprintf( "USB Hub Explore(): Device removed\n" );
136 
137 			}
138 
139 			//Clear status
140 			m_bus->SendRequest( this , USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT ,
141 		                    USB_REQUEST_CLEAR_FEATURE ,
142 		                    C_PORT_CONNECTION ,
143 		                    i + 1 , //index
144 		                    0 ,
145 		                    NULL ,
146 		                    0 ,
147 		                    &actual_length );
148 		} // PORT_STATUS_CONNECTION
149 	}//for (...)
150 }
151