Summary: Continued work on hub initialisation
Keywords: Patches applied: * [email protected]/usb-busmanager--development--0.1--patch-5 Commit (in between) because of a switch of development-machines * [email protected]/usb-busmanager--development--0.1--patch-6 Implement basic hub init * [email protected]/usb-busmanager--development--0.1--patch-7 Implement a bit more of hub operation git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7193 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -21,6 +21,25 @@
|
||||
|
||||
#include "usb_p.h"
|
||||
|
||||
|
||||
/* +++++++++
|
||||
This is the 'main' function of the explore thread, which keeps track of
|
||||
the hub statuses.
|
||||
+++++++++ */
|
||||
int32 usb_explore_thread( void *data )
|
||||
{
|
||||
Hub *roothub = (Hub *)data;
|
||||
|
||||
while (true )
|
||||
{
|
||||
//Go to the hubs
|
||||
roothub->Explore();
|
||||
snooze(10000); //Wait one second before continueing
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
BusManager::BusManager( host_controller_info *info )
|
||||
{
|
||||
hcpointer = info;
|
||||
@@ -41,6 +60,11 @@ BusManager::BusManager( host_controller_info *info )
|
||||
|
||||
if( m_roothub == 0 )
|
||||
return;
|
||||
|
||||
// Start the 'explore thread'
|
||||
m_explore_thread = spawn_kernel_thread( usb_explore_thread , "usb_busmanager_explore" ,
|
||||
B_LOW_PRIORITY , (void *)m_roothub );
|
||||
resume_thread( m_explore_thread );
|
||||
|
||||
m_initok = true;
|
||||
}
|
||||
|
||||
@@ -121,4 +121,7 @@ status_t Device::SetConfiguration( uint8 value )
|
||||
NULL , //Buffer
|
||||
0 , //Bufferlength
|
||||
0 ); //length
|
||||
|
||||
//Set current configuration
|
||||
m_current_configuration = m_configurations + value;
|
||||
}
|
||||
|
||||
@@ -24,5 +24,128 @@
|
||||
Hub::Hub( BusManager *bus , Device *parent , usb_device_descriptor &desc , int8 devicenum )
|
||||
: Device ( bus , parent , desc , devicenum )
|
||||
{
|
||||
dprintf( "USB Hub::Attach()\n" );
|
||||
}
|
||||
dprintf( "USB Hub is being initialised\n" );
|
||||
m_initok = false; // We're not yet ready!
|
||||
size_t actual_length;
|
||||
|
||||
|
||||
if( m_device_descriptor.device_subclass != 0 || m_device_descriptor.device_protocol != 0 )
|
||||
{
|
||||
dprintf( "USB Hub: wrong class/subclass/protocol! Bailing out\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_current_configuration->number_interfaces > 1 )
|
||||
{
|
||||
dprintf( "USB Hub: too much interfaces! Bailing out\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
dprintf( "USB Hub this: %p" , this );
|
||||
|
||||
if ( GetDescriptor( USB_DESCRIPTOR_INTERFACE , 0 ,
|
||||
(void *)&m_interrupt_interface ,
|
||||
sizeof (usb_interface_descriptor) ) != sizeof( usb_interface_descriptor ) )
|
||||
{
|
||||
dprintf( "USB Hub: error getting the interrupt interface! Bailing out.\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_interrupt_interface.num_endpoints > 1 )
|
||||
{
|
||||
dprintf( "USB Hub: too much endpoints! Bailing out.\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( GetDescriptor( USB_DESCRIPTOR_ENDPOINT , 0 ,
|
||||
(void *)&m_interrupt_endpoint ,
|
||||
sizeof (usb_endpoint_descriptor) ) != sizeof (usb_endpoint_descriptor ) )
|
||||
{
|
||||
dprintf( "USB Hub: Error getting the endpoint. Bailing out\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_interrupt_endpoint.attributes != 0x03 ) //interrupt transfer
|
||||
{
|
||||
dprintf( "USB Hub: Not an interrupt endpoint. Bailing out\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
dprintf( "USB Hub: Getting hub descriptor...\n" );
|
||||
if ( GetDescriptor( USB_DESCRIPTOR_HUB , 0 ,
|
||||
(void *)&m_hub_descriptor ,
|
||||
sizeof (usb_hub_descriptor) ) != sizeof (usb_hub_descriptor ) )
|
||||
{
|
||||
dprintf( "USB Hub: Error getting hub descriptor\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
// Enable port power on all ports
|
||||
for ( int i = 0 ; i < m_hub_descriptor.bNbrPorts ; i++ )
|
||||
m_bus->SendRequest( this , USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT ,
|
||||
USB_REQUEST_SET_FEATURE ,
|
||||
PORT_POWER ,
|
||||
i + 1 , //index
|
||||
0 ,
|
||||
NULL ,
|
||||
0 ,
|
||||
&actual_length );
|
||||
//Wait for power to stabilize
|
||||
snooze( m_hub_descriptor.bPwrOn2PwrGood * 2 );
|
||||
|
||||
//We're basically done now
|
||||
m_initok = true;
|
||||
}
|
||||
|
||||
void Hub::Explore()
|
||||
{
|
||||
size_t actual_length;
|
||||
|
||||
for ( int i = 0 ; i < m_hub_descriptor.bNbrPorts ; i++ )
|
||||
{
|
||||
// Get the current port status
|
||||
m_bus->SendRequest( this , USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_IN ,
|
||||
USB_REQUEST_GET_STATUS ,
|
||||
0 , //Value
|
||||
i + 1 , //Index
|
||||
4 , //length
|
||||
(void *)&m_port_status[i],
|
||||
4 ,
|
||||
&actual_length );
|
||||
if ( actual_length < 4 )
|
||||
{
|
||||
dprintf( "USB Hub: ERROR getting port status" );
|
||||
return;
|
||||
}
|
||||
|
||||
//We need to test the port change against a number of things
|
||||
if ( m_port_status[i].change & PORT_STATUS_CONNECTION )
|
||||
{
|
||||
if ( m_port_status[i].status & PORT_STATUS_CONNECTION )
|
||||
{
|
||||
//New device attached!
|
||||
//DO something
|
||||
dprintf( "USB Hub Explore(): New device connected\n" );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//Device removed...
|
||||
//DO something
|
||||
dprintf( "USB Hub Explore(): Device removed\n" );
|
||||
|
||||
}
|
||||
|
||||
//Clear status
|
||||
m_bus->SendRequest( this , USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT ,
|
||||
USB_REQUEST_CLEAR_FEATURE ,
|
||||
C_PORT_CONNECTION ,
|
||||
i + 1 , //index
|
||||
0 ,
|
||||
NULL ,
|
||||
0 ,
|
||||
&actual_length );
|
||||
} // PORT_STATUS_CONNECTION
|
||||
}//for (...)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ SubDir OBOS_TOP src add-ons kernel bus_managers usb ;
|
||||
|
||||
UsePrivateHeaders [ FDirName kernel ] ;
|
||||
|
||||
AddResources usb : usb.rdef ;
|
||||
|
||||
R5KernelAddon usb : [ FDirName kernel bus_managers ] :
|
||||
usb.cpp
|
||||
Stack.cpp
|
||||
|
||||
@@ -1,6 +1,55 @@
|
||||
#ifndef HOST_CONTROLLER_INFO_H
|
||||
#define HOST_CONTROLLER_INFO_H
|
||||
|
||||
/* +++++++++
|
||||
USB Spec definitions (not interesting for the outside world
|
||||
+++++++++ */
|
||||
typedef struct
|
||||
{
|
||||
uint8 bDescLength;
|
||||
uint8 bDescriptorType;
|
||||
uint8 bNbrPorts;
|
||||
uint16 wHubCharacteristics;
|
||||
uint8 bPwrOn2PwrGood;
|
||||
uint8 bHucContrCurrent;
|
||||
uint8 DeviceRemovable; //Should be variable!!!
|
||||
uint8 PortPwrCtrlMask; //Deprecated
|
||||
} usb_hub_descriptor;
|
||||
|
||||
#define USB_DESCRIPTOR_HUB 0x29
|
||||
|
||||
// USB Spec 1.1 page 273
|
||||
typedef struct
|
||||
{
|
||||
uint16 status;
|
||||
uint16 change;
|
||||
} usb_port_status;
|
||||
|
||||
//The bits in the usb_port_status struct
|
||||
// USB 1.1 spec page 274
|
||||
#define PORT_STATUS_CONNECTION 0x1
|
||||
#define PORT_STATUS_ENABLE 0x2
|
||||
#define PORT_STATUS_SUSPEND 0x4
|
||||
#define PORT_STATUS_OVER_CURRENT 0x8
|
||||
#define PORT_STATUS_RESET 0x10
|
||||
#define PORT_STATUS_POWER 0x100
|
||||
#define PORT_STATUS_LOW_SPEED 0x200
|
||||
|
||||
//The feature requests with ports
|
||||
// USB 1.1 spec page 268
|
||||
#define PORT_CONNECTION 0
|
||||
#define PORT_ENABLE 1
|
||||
#define PORT_SUSPEND 2
|
||||
#define PORT_OVER_CURRENT 3
|
||||
#define PORT_RESET 4
|
||||
#define PORT_POWER 8
|
||||
#define PORT_LOW_SPEED 9
|
||||
#define C_PORT_CONNECTION 16
|
||||
#define C_PORT_ENABLE 17
|
||||
#define C_PORT_SUSPEND 18
|
||||
#define C_PORT_OVER_CURRENT 19
|
||||
#define C_PORT_RESET 20
|
||||
|
||||
/* ++++++++++
|
||||
Internally used types
|
||||
++++++++++ */
|
||||
|
||||
@@ -34,6 +34,12 @@ Forward declarations
|
||||
class Device;
|
||||
class BusManager;
|
||||
|
||||
/* ++++++++++
|
||||
Important data from the USB spec (not interesting for drivers)
|
||||
++++++++++ */
|
||||
|
||||
#define POWER_DELAY
|
||||
|
||||
/* ++++++++++
|
||||
Internal classes
|
||||
++++++++++ */
|
||||
@@ -81,6 +87,14 @@ class Hub : public Device
|
||||
public:
|
||||
Hub( BusManager *bus , Device *parent , usb_device_descriptor &desc , int8 devicenum);
|
||||
virtual bool IsHub() { return true; };
|
||||
|
||||
void Explore();
|
||||
private:
|
||||
usb_interface_descriptor m_interrupt_interface;
|
||||
usb_endpoint_descriptor m_interrupt_endpoint;
|
||||
usb_hub_descriptor m_hub_descriptor;
|
||||
|
||||
usb_port_status m_port_status[8]; //Max of 8 ports, for the moment
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -99,8 +113,8 @@ public:
|
||||
|
||||
Device *AllocateNewDevice( Device *parent );
|
||||
int8 AllocateAddress();
|
||||
status_t SendRequest( Device *dev, uint8 request_type , uint8 request , uint16 value ,
|
||||
uint16 index , uint16 length , void *data ,
|
||||
status_t SendRequest( Device *dev, uint8 request_type , uint8 request ,
|
||||
uint16 value , uint16 index , uint16 length , void *data ,
|
||||
size_t data_len , size_t *actual_len );
|
||||
private:
|
||||
status_t SendControlMessage( Device *dev , uint16 pipe ,
|
||||
@@ -113,8 +127,12 @@ private:
|
||||
bool m_devicemap[128];
|
||||
sem_id m_lock;
|
||||
Device *m_roothub;
|
||||
thread_id m_explore_thread;
|
||||
};
|
||||
|
||||
// Located in the BusManager.cpp
|
||||
int32 usb_explore_thread( void *data );
|
||||
|
||||
/*
|
||||
* This class is more like an utility class that performs all functions on
|
||||
* packets. The class is only used in the bus_manager: the host controllers
|
||||
|
||||
Reference in New Issue
Block a user