From a8e39155919845b80f7a27ffbc279dc6e019a0a0 Mon Sep 17 00:00:00 2001 From: Niels Sascha Reedijk Date: Tue, 30 Dec 2003 14:59:45 +0000 Subject: [PATCH] * n.reedijk@planet.nl--nielx-2003/usb-busmanager--development--0.1--patch-1 Implement basic Busmanager loader modules * n.reedijk@planet.nl--nielx-2003/usb-busmanager--development--0.1--patch-2 Continue shaping up some things * n.reedijk@planet.nl--nielx-2003/usb-busmanager--development--0.1--patch-3 Continued device initialisation * n.reedijk@planet.nl--nielx-2003/usb-busmanager--development--0.1--patch-4 Finalised the device initialisation git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5832 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/bus_managers/usb/BusManager.cpp | 184 ++++++++++++++++++ .../kernel/bus_managers/usb/Device.cpp | 124 ++++++++++++ src/add-ons/kernel/bus_managers/usb/Hub.cpp | 28 +++ src/add-ons/kernel/bus_managers/usb/Jamfile | 6 +- .../kernel/bus_managers/usb/Packet.cpp | 67 +++++++ src/add-ons/kernel/bus_managers/usb/Stack.cpp | 14 +- .../kernel/bus_managers/usb/host_controller.h | 36 ++++ src/add-ons/kernel/bus_managers/usb/usb_p.h | 101 +++++++++- 8 files changed, 553 insertions(+), 7 deletions(-) create mode 100644 src/add-ons/kernel/bus_managers/usb/BusManager.cpp create mode 100644 src/add-ons/kernel/bus_managers/usb/Device.cpp create mode 100644 src/add-ons/kernel/bus_managers/usb/Hub.cpp create mode 100644 src/add-ons/kernel/bus_managers/usb/Packet.cpp create mode 100644 src/add-ons/kernel/bus_managers/usb/host_controller.h diff --git a/src/add-ons/kernel/bus_managers/usb/BusManager.cpp b/src/add-ons/kernel/bus_managers/usb/BusManager.cpp new file mode 100644 index 0000000000..7ed041f7e0 --- /dev/null +++ b/src/add-ons/kernel/bus_managers/usb/BusManager.cpp @@ -0,0 +1,184 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2003, Niels S. Reedijk +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#include "usb_p.h" + +BusManager::BusManager( host_controller_info *info ) +{ + hcpointer = info; + m_initok = false; + m_roothub = 0; + + // Set up the semaphore + m_lock = create_sem( 1 , "buslock" ); + if( m_lock < B_OK ) + return; + set_sem_owner( B_SYSTEM_TEAM , m_lock ); + + // Clear the device map + memset( &m_devicemap , false , 128 ); + + // Set up the new root hub + AllocateNewDevice( 0 ); + + if( m_roothub == 0 ) + return; + + m_initok = true; +} + +BusManager::~BusManager() +{ + put_module( hcpointer->info.name ); +} + +status_t BusManager::InitCheck() +{ + if ( m_initok == true ) + return B_OK; + else + return B_ERROR; +} + +Device * BusManager::AllocateNewDevice( Device *parent ) +{ + int8 devicenum; + status_t retval; + usb_device_descriptor device_descriptor; + + //1. Check if there is a free entry in the device map (for the device number) + devicenum = AllocateAddress(); + if ( devicenum < 0 ) + { + dprintf( "usb Busmanager [new device]: could not get a new address\n" ); + return 0; + } + + //2. Set the address of the device USB 1.1 spec p202 (bepdf) + retval = SendRequest( 0 , + USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD , //host->device + USB_REQUEST_SET_ADDRESS , //request + devicenum , //value + 0 , //index + 0 , //length + NULL , //data + 0 , //data_len + 0 ); //actual len + + if ( retval < B_OK ) + { + dprintf( "usb busmanager [new device]: error with commmunicating the right address\n" ); + return 0; + } + + //3. Get the device descriptor + // Just retrieve the first 8 bytes of the descriptor -> minimum supported + // size of any device, plus it is enough, because the device type is in + // there too + + size_t actual_length; + + SendRequest( 0 , + USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD , //Type + USB_REQUEST_GET_DESCRIPTOR , //Request + ( USB_DESCRIPTOR_DEVICE << 8 ), //Value + 0 , //Index + 8 , //Length + (void *)&device_descriptor , //Buffer + 8 , //Bufferlength + &actual_length ); //length + + if ( actual_length != 8 ) + { + dprintf( "usb busmanager [new device]: error while getting the device descriptor\n" ); + return 0; + } + + //4. Create a new instant based on the type (Hub or Device); + if ( device_descriptor.device_class == 0x09 ) + { + dprintf( "usb Busmanager [new device]: New hub\n" ); + Device *ret = new Hub( this , parent , device_descriptor , devicenum ); + if ( parent == 0 ) //root hub!! + m_roothub = ret; + return ret; + } + + dprintf( "usb Busmanager [new device]: New normal device\n" ); + return new Device( this , parent , device_descriptor , devicenum ); +} + +int8 BusManager::AllocateAddress() +{ + acquire_sem_etc( m_lock , 1 , B_CAN_INTERRUPT , 0 ); + int8 devicenum = -1; + for( int i = 0 ; i < 128 ; i++ ) + { + if ( m_devicemap[i] == false ) + { + devicenum = i; + m_devicemap[i] = true; + break; + } + } + release_sem( m_lock ); + return devicenum; +} + +status_t BusManager::SendRequest( Device * dev , uint8 request_type , uint8 request , uint16 value , + uint16 index , uint16 length , void *data , + size_t data_len , size_t *actual_len ) +{ + //todo: het moet speciaal soort geheugen worden + usb_request_data *req = (usb_request_data *)malloc( sizeof( usb_request_data) ); + + req->RequestType = request_type; + req->Request = request; + req->Value = value; + req->Index = index; + req->Length = length; + + //Nicen up the second argument: the default pipe + //1) set up the pipe stuff a little nicer + //2) don't assume it's a low speed device :-( + return SendControlMessage( dev , ( 2 << 30 | 1 << 26 ) , req , + data , data_len , actual_len , 3 * 1000 * 1000 ); +} + +status_t BusManager::SendControlMessage( Device *dev , uint16 pipe , + usb_request_data *command , void *data , + size_t data_length , size_t *actual_length , + bigtime_t timeout ) +{ + // this method should build an usb packet (new class) with the needed data + Packet packet; + + packet.SetPipe( pipe ); + packet.SetRequestData( (uint8 *)command ); + packet.SetBuffer( (uint8 *)data ); + packet.SetBufferLength( data_length ); + packet.SetActualLength( actual_length ); + packet.SetAddress( 0 ); + + status_t retval = hcpointer->SubmitPacket( packet.GetData() ); + return retval; +} + diff --git a/src/add-ons/kernel/bus_managers/usb/Device.cpp b/src/add-ons/kernel/bus_managers/usb/Device.cpp new file mode 100644 index 0000000000..1b6f151e66 --- /dev/null +++ b/src/add-ons/kernel/bus_managers/usb/Device.cpp @@ -0,0 +1,124 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2003, Niels S. Reedijk +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#include "usb_p.h" + +Device::Device( BusManager *bus , Device *parent , usb_device_descriptor &desc , int8 devicenum ) +{ + status_t retval; + + m_bus = bus; + m_parent = parent; + m_initok = false; + m_configurations = 0; + m_current_configuration = 0; + + dprintf( "USB Device: new device\n" ); + + //1. Create the semaphore + m_lock = create_sem( 1 , "device_sem" ); + if ( m_lock < B_OK ) + { + dprintf( "usb Device: could not create semaphore\n" ); + return; + } + set_sem_owner( m_lock , B_SYSTEM_TEAM ); + + //2. Set the free entry free entry in the device map (for the device number) + m_devicenum = devicenum; + + //3. Get the device descriptor + // We already have a part of it, but we want it all + m_device_descriptor = desc; + + //Set the maximum transfer numbers for the incoming and the outgoing packets on endpoint 0 + m_maxpacketin[0] = m_maxpacketout[0] = m_device_descriptor.max_packet_size_0; + + retval = GetDescriptor( USB_DESCRIPTOR_DEVICE , 0 , + (void *)&m_device_descriptor , sizeof(m_device_descriptor ) ); + + if ( retval != sizeof( m_device_descriptor ) ) + { + dprintf( "usb Device: error while getting the device descriptor\n" ); + return; + } + + dprintf( "usb Device %d: Vendor id: %d , Product id: %d\n" , devicenum , + m_device_descriptor.vendor_id , m_device_descriptor.product_id ); + + + // 4. Get the configurations + m_configurations = (usb_configuration_descriptor *)malloc( m_device_descriptor.num_configurations * sizeof (usb_configuration_descriptor) ); + if ( m_configurations == 0 ) + { + dprintf( "usb Device: out of memory during config creations!\n" ); + return; + } + + for ( int i = 0 ; i < m_device_descriptor.num_configurations ; i++ ) + { + if ( GetDescriptor( USB_DESCRIPTOR_CONFIGURATION , i , + (void *)( m_configurations + i ) , sizeof (usb_configuration_descriptor ) ) != sizeof( usb_configuration_descriptor ) ) + { + dprintf( "usb Device %d: error fetching configuration %d ...\n" , m_devicenum , i ); + return; + } + } + + // 5. Set the default configuration + dprintf( "usb Device %d: setting configuration %d\n" , m_devicenum , 0 ); + SetConfiguration( 0 ); + + //6. TODO: Find drivers for the device +} + +//Returns the length that was copied (index gives the number of the config) +int16 Device::GetDescriptor( uint8 descriptor_type , uint16 index , + void *buffer , size_t size ) +{ + size_t actual_length; + m_bus->SendRequest( this , + USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD , //Type + USB_REQUEST_GET_DESCRIPTOR , //Request + ( descriptor_type << 8 ) | index , //Value + 0 , //Index + size , //Length + buffer , //Buffer + size , //Bufferlength + &actual_length ); //length + return actual_length; +} + +status_t Device::SetConfiguration( uint8 value ) +{ + if ( value >= m_device_descriptor.num_configurations ) + return EINVAL; + + m_bus->SendRequest( this , + USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD , //Type + USB_REQUEST_SET_CONFIGURATION , //Request + value , //Value + 0 , //Index + 0 , //Length + NULL , //Buffer + 0 , //Bufferlength + 0 ); //length +} diff --git a/src/add-ons/kernel/bus_managers/usb/Hub.cpp b/src/add-ons/kernel/bus_managers/usb/Hub.cpp new file mode 100644 index 0000000000..b565ce7a93 --- /dev/null +++ b/src/add-ons/kernel/bus_managers/usb/Hub.cpp @@ -0,0 +1,28 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2003, Niels S. Reedijk +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#include "usb_p.h" + +Hub::Hub( BusManager *bus , Device *parent , usb_device_descriptor &desc , int8 devicenum ) + : Device ( bus , parent , desc , devicenum ) +{ + dprintf( "USB Hub::Attach()\n" ); +} diff --git a/src/add-ons/kernel/bus_managers/usb/Jamfile b/src/add-ons/kernel/bus_managers/usb/Jamfile index 7a23b299ca..e2680df19c 100644 --- a/src/add-ons/kernel/bus_managers/usb/Jamfile +++ b/src/add-ons/kernel/bus_managers/usb/Jamfile @@ -1,8 +1,12 @@ SubDir OBOS_TOP src add-ons kernel bus_managers usb ; -UsePrivateHeaders kernel ; +UsePrivateHeaders [ FDirName kernel ] ; R5KernelAddon usb : [ FDirName kernel bus_managers ] : usb.cpp Stack.cpp + Device.cpp + Hub.cpp + BusManager.cpp + Packet.cpp ; diff --git a/src/add-ons/kernel/bus_managers/usb/Packet.cpp b/src/add-ons/kernel/bus_managers/usb/Packet.cpp new file mode 100644 index 0000000000..13345bdffc --- /dev/null +++ b/src/add-ons/kernel/bus_managers/usb/Packet.cpp @@ -0,0 +1,67 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2003, Niels S. Reedijk +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#include "usb_p.h" + +Packet::Packet() +{ + d = new usb_packet_t; +} + +Packet::~Packet() +{ + delete d; +} + +void Packet::SetPipe( uint16 pipe ) +{ + d->pipe = pipe; +} + +void Packet::SetAddress( uint8 address ) +{ + d->address = address; +} + +void Packet::SetRequestData( uint8 *data ) +{ + d->requestdata = data; +} + +void Packet::SetBuffer( uint8 *buffer ) +{ + d->buffer = buffer; +} + +void Packet::SetBufferLength( int16 length ) +{ + d->bufferlength = length; +} + +void Packet::SetActualLength( size_t *actual_length ) +{ + d->actual_length = actual_length; +}; + +usb_packet_t * Packet::GetData() +{ + return d; +} \ No newline at end of file diff --git a/src/add-ons/kernel/bus_managers/usb/Stack.cpp b/src/add-ons/kernel/bus_managers/usb/Stack.cpp index d68daf4ac6..3c598a7613 100644 --- a/src/add-ons/kernel/bus_managers/usb/Stack.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Stack.cpp @@ -30,6 +30,10 @@ Stack::Stack() m_master = create_sem( 0 , "usb master lock" ); set_sem_owner( m_master , B_SYSTEM_TEAM ); + //Create the data lock + m_datalock = create_sem( 0 , "usb data lock" ); + set_sem_owner( m_datalock , B_SYSTEM_TEAM ); + //Check for host controller modules void *list = open_module_list( "busses/usb" ); char modulename[B_PATH_NAME_LENGTH]; @@ -38,10 +42,10 @@ Stack::Stack() while( read_next_module_name( list , modulename , &buffersize ) == B_OK ) { dprintf( "USB: Found module %s\n" , modulename ); - module_info *module = 0; - if ( get_module( modulename , &module ) != B_OK ) + host_controller_info *module = 0; + if ( get_module( modulename , (module_info **)&module ) != B_OK ) continue; - m_busmodules.Insert( module , 0 ); + m_busmodules.Insert( new BusManager( module ) , 0 ); dprintf( "USB: module %s successfully loaded\n" , modulename ); } @@ -52,8 +56,8 @@ Stack::Stack() Stack::~Stack() { //Release the bus modules - for( Vector::Iterator i = m_busmodules.Begin() ; i != m_busmodules.End() ; i++ ) - put_module( (*i)->name ); + for( Vector::Iterator i = m_busmodules.Begin() ; i != m_busmodules.End() ; i++ ) + delete (*i); } diff --git a/src/add-ons/kernel/bus_managers/usb/host_controller.h b/src/add-ons/kernel/bus_managers/usb/host_controller.h new file mode 100644 index 0000000000..b609737599 --- /dev/null +++ b/src/add-ons/kernel/bus_managers/usb/host_controller.h @@ -0,0 +1,36 @@ +#ifndef HOST_CONTROLLER_INFO_H +#define HOST_CONTROLLER_INFO_H + +/* ++++++++++ +Internally used types +++++++++++ */ + +//This embodies a request that can be send +typedef struct +{ + uint8 RequestType; + uint8 Request; + uint16 Value; + uint16 Index; + uint16 Length; +} usb_request_data; + +// Describes the internal organs of an usb packet +typedef struct usb_packet_t +{ + uint16 pipe; + uint8 *requestdata; + uint8 *buffer; + int16 bufferlength; + size_t *actual_length; + int16 address; //!!!! TEMPORARY ... or is it? +} usb_packet_t; + +typedef struct host_controller_info +{ + module_info info; + status_t (*hwstart)(void); + status_t (*SubmitPacket)(usb_packet_t *); +} host_controller_info; + +#endif //HOST_CONTROLLER_INFO_H \ No newline at end of file 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 f4038eb3e9..4c0136aeee 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb_p.h +++ b/src/add-ons/kernel/bus_managers/usb/usb_p.h @@ -24,6 +24,19 @@ #include #include +#include +#include "host_controller.h" +#include + +/* ++++++++++ +Forward declarations +++++++++++ */ +class Device; +class BusManager; + +/* ++++++++++ +Internal classes +++++++++++ */ class Stack { @@ -32,11 +45,97 @@ public: ~Stack(); status_t InitCheck(); private: - Vector m_busmodules; //Stores all the bus modules + Vector m_busmodules;//Stores all the bus modules sem_id m_master; //The master lock + sem_id m_datalock; //Lock that controls data transfers }; extern "C" Stack *data; +class Device +{ +public: + Device( BusManager *bus , Device *parent , usb_device_descriptor &desc , int8 devicenum ); + virtual bool IsHub() { return false; }; + status_t InitCheck(); + + uint8 GetAddress() { return m_devicenum; }; + int16 GetDescriptor( uint8 descriptor_type , uint16 index , void *buffer , + size_t size ); + status_t SetConfiguration( uint8 value ); +protected: + usb_device_descriptor m_device_descriptor; + usb_configuration_descriptor * m_configurations; + usb_configuration_descriptor * m_current_configuration; + bool m_initok; + BusManager * m_bus; + Device * m_parent; + int8 m_devicenum; + uint8 m_maxpacketin[16]; //Max. size of input + uint8 m_maxpacketout[16]; //Max size of output + sem_id m_lock; +}; + +class Hub : public Device +{ +public: + Hub( BusManager *bus , Device *parent , usb_device_descriptor &desc , int8 devicenum); + virtual bool IsHub() { return true; }; +}; + +/* + * This class manages a bus. It is created by the Stack object + * after a host controller gives positive feedback on whether the hardware + * is found. + */ +class BusManager +{ + friend class Device; +public: + BusManager( host_controller_info *info ); + ~BusManager(); + + status_t InitCheck(); + + Device *AllocateNewDevice( Device *parent ); + int8 AllocateAddress(); + 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 , + usb_request_data *command , void *data , + size_t data_length , size_t *actual_length , + bigtime_t timeout ); + + host_controller_info *hcpointer; + bool m_initok; + bool m_devicemap[128]; + sem_id m_lock; + Device *m_roothub; +}; + +/* + * 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 + * receive the internal data structures. + */ + +class Packet +{ +public: + Packet(); + ~Packet(); + void SetPipe( uint16 pipe ); + void SetRequestData( uint8 *data ); + void SetBuffer( uint8 *buffer ); + void SetBufferLength( int16 length ); + void SetAddress( uint8 address ); + void SetActualLength( size_t * ); + + usb_packet_t *GetData(); +private: + usb_packet_t *d; +}; #endif