[email protected]/usb-busmanager--development--0.1--patch-1
   Implement basic Busmanager loader modules
 *
[email protected]/usb-busmanager--development--0.1--patch-2
   Continue shaping up some things
 *
[email protected]/usb-busmanager--development--0.1--patch-3
   Continued device initialisation
 *
[email protected]/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
This commit is contained in:
Niels Sascha Reedijk
2003-12-30 14:59:45 +00:00
parent 07b15fef0c
commit a8e3915591
8 changed files with 553 additions and 7 deletions
@@ -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;
}
@@ -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
}
@@ -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" );
}
+5 -1
View File
@@ -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
;
@@ -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;
}
@@ -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<module_info *>::Iterator i = m_busmodules.Begin() ; i != m_busmodules.End() ; i++ )
put_module( (*i)->name );
for( Vector<BusManager *>::Iterator i = m_busmodules.Begin() ; i != m_busmodules.End() ; i++ )
delete (*i);
}
@@ -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
+100 -1
View File
@@ -24,6 +24,19 @@
#include <KernelExport.h>
#include <util/Vector.h>
#include <USB.h>
#include "host_controller.h"
#include <util/kernel_cpp.h>
/* ++++++++++
Forward declarations
++++++++++ */
class Device;
class BusManager;
/* ++++++++++
Internal classes
++++++++++ */
class Stack
{
@@ -32,11 +45,97 @@ public:
~Stack();
status_t InitCheck();
private:
Vector<module_info *> m_busmodules; //Stores all the bus modules
Vector<BusManager *> 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