From 8b485af8749e8e3385cf0607eca2baa530ed5eef Mon Sep 17 00:00:00 2001 From: Niels Sascha Reedijk Date: Tue, 13 Apr 2004 06:27:32 +0000 Subject: [PATCH] Summary: Continued work on hub initialisation Keywords: Patches applied: * n.reedijk@planet.nl--nielx-2003/usb-busmanager--development--0.1--patch-5 Commit (in between) because of a switch of development-machines * n.reedijk@planet.nl--nielx-2003/usb-busmanager--development--0.1--patch-6 Implement basic hub init * n.reedijk@planet.nl--nielx-2003/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 --- .../kernel/bus_managers/usb/BusManager.cpp | 24 ++++ .../kernel/bus_managers/usb/Device.cpp | 3 + src/add-ons/kernel/bus_managers/usb/Hub.cpp | 127 +++++++++++++++++- src/add-ons/kernel/bus_managers/usb/Jamfile | 2 + .../kernel/bus_managers/usb/host_controller.h | 49 +++++++ src/add-ons/kernel/bus_managers/usb/usb_p.h | 22 ++- 6 files changed, 223 insertions(+), 4 deletions(-) diff --git a/src/add-ons/kernel/bus_managers/usb/BusManager.cpp b/src/add-ons/kernel/bus_managers/usb/BusManager.cpp index 7ed041f7e0..8d9440eaf3 100644 --- a/src/add-ons/kernel/bus_managers/usb/BusManager.cpp +++ b/src/add-ons/kernel/bus_managers/usb/BusManager.cpp @@ -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; } diff --git a/src/add-ons/kernel/bus_managers/usb/Device.cpp b/src/add-ons/kernel/bus_managers/usb/Device.cpp index 1b6f151e66..348db76da1 100644 --- a/src/add-ons/kernel/bus_managers/usb/Device.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Device.cpp @@ -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; } diff --git a/src/add-ons/kernel/bus_managers/usb/Hub.cpp b/src/add-ons/kernel/bus_managers/usb/Hub.cpp index b565ce7a93..8fcb786fba 100644 --- a/src/add-ons/kernel/bus_managers/usb/Hub.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Hub.cpp @@ -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 (...) +} + \ No newline at end of file diff --git a/src/add-ons/kernel/bus_managers/usb/Jamfile b/src/add-ons/kernel/bus_managers/usb/Jamfile index e2680df19c..b7b1f57417 100644 --- a/src/add-ons/kernel/bus_managers/usb/Jamfile +++ b/src/add-ons/kernel/bus_managers/usb/Jamfile @@ -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 diff --git a/src/add-ons/kernel/bus_managers/usb/host_controller.h b/src/add-ons/kernel/bus_managers/usb/host_controller.h index b609737599..fe600fdbc3 100644 --- a/src/add-ons/kernel/bus_managers/usb/host_controller.h +++ b/src/add-ons/kernel/bus_managers/usb/host_controller.h @@ -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 ++++++++++ */ diff --git a/src/add-ons/kernel/bus_managers/usb/usb_p.h b/src/add-ons/kernel/bus_managers/usb/usb_p.h index 4c0136aeee..08f8a023b2 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb_p.h +++ b/src/add-ons/kernel/bus_managers/usb/usb_p.h @@ -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