* [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 * [email protected]/usb-busmanager--development--0.1--patch-8 Device Adress 0 is reserved for the default pipe! * [email protected]/usb-busmanager--development--0.1--patch-9 Implement basic Pipe stuff * [email protected]/usb-busmanager--development--0.1--patch-10 Create basic chunk allocation * [email protected]/usb-busmanager--development--0.1--patch-11 Add Required util.c/util.h * [email protected]/usb-busmanager--development--0.1--patch-12 Provide locking for the stack and make AllocateChunk thread-safe * [email protected]/usb-busmanager--development--0.1--patch-13 Integrated util.c in stack class (cleans up a little) * [email protected]/usb-busmanager--development--0.1--patch-14 Improve Pipe and give the Busmanager its default pipe * [email protected]/usb-busmanager--development--0.1--patch-15 Make the Device class speed aware * [email protected]/usb-busmanager--development--0.1--patch-16 Make Chunk allocation code more dynamic * [email protected]/usb-busmanager--development--0.1--patch-17 Small test-commit to test if webdav is working -- ignore * [email protected]/usb-busmanager--development--0.1--patch-18 Changed Packets into Transfers * [email protected]/usb-busmanager--development--0.1--patch-19 Fix mistakes in host_controller.c * [email protected]/usb-busmanager--development--0.1--patch-20 Advanced a little more in the Pipe stuff * [email protected]/usb-busmanager--development--0.1--patch-21 Merge with mainline and add newlines at the end of files git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7668 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -34,7 +34,7 @@ int32 usb_explore_thread( void *data )
|
|||||||
{
|
{
|
||||||
//Go to the hubs
|
//Go to the hubs
|
||||||
roothub->Explore();
|
roothub->Explore();
|
||||||
snooze(10000); //Wait one second before continueing
|
snooze(1000000); //Wait one second before continueing
|
||||||
}
|
}
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -55,8 +55,12 @@ BusManager::BusManager( host_controller_info *info )
|
|||||||
// Clear the device map
|
// Clear the device map
|
||||||
memset( &m_devicemap , false , 128 );
|
memset( &m_devicemap , false , 128 );
|
||||||
|
|
||||||
|
// Set up the default pipes
|
||||||
|
m_defaultPipe = new ControlPipe( this , 0 , Default , NormalSpeed , 0 );
|
||||||
|
m_defaultLowSpeedPipe = new ControlPipe( this , 0 , Default , LowSpeed , 0 );
|
||||||
|
|
||||||
// Set up the new root hub
|
// Set up the new root hub
|
||||||
AllocateNewDevice( 0 );
|
AllocateNewDevice( 0 , false );
|
||||||
|
|
||||||
if( m_roothub == 0 )
|
if( m_roothub == 0 )
|
||||||
return;
|
return;
|
||||||
@@ -82,7 +86,7 @@ status_t BusManager::InitCheck()
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
Device * BusManager::AllocateNewDevice( Device *parent )
|
Device * BusManager::AllocateNewDevice( Device *parent , bool lowspeed )
|
||||||
{
|
{
|
||||||
int8 devicenum;
|
int8 devicenum;
|
||||||
status_t retval;
|
status_t retval;
|
||||||
@@ -96,9 +100,9 @@ Device * BusManager::AllocateNewDevice( Device *parent )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//2. Set the address of the device USB 1.1 spec p202 (bepdf)
|
//2. Set the address of the device USB 1.1 spec p202 (bepdf)
|
||||||
retval = SendRequest( 0 ,
|
retval = m_defaultPipe->SendRequest( USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD , //host->device
|
||||||
USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD , //host->device
|
|
||||||
USB_REQUEST_SET_ADDRESS , //request
|
USB_REQUEST_SET_ADDRESS , //request
|
||||||
devicenum , //value
|
devicenum , //value
|
||||||
0 , //index
|
0 , //index
|
||||||
@@ -113,6 +117,9 @@ Device * BusManager::AllocateNewDevice( Device *parent )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Create a temporary pipe
|
||||||
|
ControlPipe pipe( this , devicenum , Default , LowSpeed , 0 );
|
||||||
|
|
||||||
//3. Get the device descriptor
|
//3. Get the device descriptor
|
||||||
// Just retrieve the first 8 bytes of the descriptor -> minimum supported
|
// 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
|
// size of any device, plus it is enough, because the device type is in
|
||||||
@@ -120,8 +127,7 @@ Device * BusManager::AllocateNewDevice( Device *parent )
|
|||||||
|
|
||||||
size_t actual_length;
|
size_t actual_length;
|
||||||
|
|
||||||
SendRequest( 0 ,
|
pipe.SendRequest( USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD , //Type
|
||||||
USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD , //Type
|
|
||||||
USB_REQUEST_GET_DESCRIPTOR , //Request
|
USB_REQUEST_GET_DESCRIPTOR , //Request
|
||||||
( USB_DESCRIPTOR_DEVICE << 8 ), //Value
|
( USB_DESCRIPTOR_DEVICE << 8 ), //Value
|
||||||
0 , //Index
|
0 , //Index
|
||||||
@@ -140,21 +146,21 @@ Device * BusManager::AllocateNewDevice( Device *parent )
|
|||||||
if ( device_descriptor.device_class == 0x09 )
|
if ( device_descriptor.device_class == 0x09 )
|
||||||
{
|
{
|
||||||
dprintf( "usb Busmanager [new device]: New hub\n" );
|
dprintf( "usb Busmanager [new device]: New hub\n" );
|
||||||
Device *ret = new Hub( this , parent , device_descriptor , devicenum );
|
Device *ret = new Hub( this , parent , device_descriptor , devicenum , lowspeed );
|
||||||
if ( parent == 0 ) //root hub!!
|
if ( parent == 0 ) //root hub!!
|
||||||
m_roothub = ret;
|
m_roothub = ret;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
dprintf( "usb Busmanager [new device]: New normal device\n" );
|
dprintf( "usb Busmanager [new device]: New normal device\n" );
|
||||||
return new Device( this , parent , device_descriptor , devicenum );
|
return new Device( this , parent , device_descriptor , devicenum , lowspeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
int8 BusManager::AllocateAddress()
|
int8 BusManager::AllocateAddress()
|
||||||
{
|
{
|
||||||
acquire_sem_etc( m_lock , 1 , B_CAN_INTERRUPT , 0 );
|
acquire_sem_etc( m_lock , 1 , B_CAN_INTERRUPT , 0 );
|
||||||
int8 devicenum = -1;
|
int8 devicenum = -1;
|
||||||
for( int i = 0 ; i < 128 ; i++ )
|
for( int i = 1 ; i < 128 ; i++ )
|
||||||
{
|
{
|
||||||
if ( m_devicemap[i] == false )
|
if ( m_devicemap[i] == false )
|
||||||
{
|
{
|
||||||
@@ -167,42 +173,3 @@ int8 BusManager::AllocateAddress()
|
|||||||
return devicenum;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#include "usb_p.h"
|
#include "usb_p.h"
|
||||||
|
|
||||||
Device::Device( BusManager *bus , Device *parent , usb_device_descriptor &desc , int8 devicenum )
|
Device::Device( BusManager *bus , Device *parent , usb_device_descriptor &desc , int8 devicenum , bool lowspeed )
|
||||||
{
|
{
|
||||||
status_t retval;
|
status_t retval;
|
||||||
|
|
||||||
@@ -45,13 +45,15 @@ Device::Device( BusManager *bus , Device *parent , usb_device_descriptor &desc ,
|
|||||||
//2. Set the free entry free entry in the device map (for the device number)
|
//2. Set the free entry free entry in the device map (for the device number)
|
||||||
m_devicenum = devicenum;
|
m_devicenum = devicenum;
|
||||||
|
|
||||||
//3. Get the device descriptor
|
//3. Set up the pipe stuff
|
||||||
// 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
|
//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;
|
m_maxpacketin[0] = m_maxpacketout[0] = m_device_descriptor.max_packet_size_0;
|
||||||
|
m_device_descriptor = desc;
|
||||||
|
m_lowspeed = lowspeed;
|
||||||
|
m_defaultPipe = new ControlPipe( this , Default , 0 );
|
||||||
|
|
||||||
|
//4. Get the device descriptor
|
||||||
|
// We already have a part of it, but we want it all
|
||||||
retval = GetDescriptor( USB_DESCRIPTOR_DEVICE , 0 ,
|
retval = GetDescriptor( USB_DESCRIPTOR_DEVICE , 0 ,
|
||||||
(void *)&m_device_descriptor , sizeof(m_device_descriptor ) );
|
(void *)&m_device_descriptor , sizeof(m_device_descriptor ) );
|
||||||
|
|
||||||
@@ -95,8 +97,7 @@ int16 Device::GetDescriptor( uint8 descriptor_type , uint16 index ,
|
|||||||
void *buffer , size_t size )
|
void *buffer , size_t size )
|
||||||
{
|
{
|
||||||
size_t actual_length;
|
size_t actual_length;
|
||||||
m_bus->SendRequest( this ,
|
m_defaultPipe->SendRequest(USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD , //Type
|
||||||
USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD , //Type
|
|
||||||
USB_REQUEST_GET_DESCRIPTOR , //Request
|
USB_REQUEST_GET_DESCRIPTOR , //Request
|
||||||
( descriptor_type << 8 ) | index , //Value
|
( descriptor_type << 8 ) | index , //Value
|
||||||
0 , //Index
|
0 , //Index
|
||||||
@@ -112,8 +113,7 @@ status_t Device::SetConfiguration( uint8 value )
|
|||||||
if ( value >= m_device_descriptor.num_configurations )
|
if ( value >= m_device_descriptor.num_configurations )
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
m_bus->SendRequest( this ,
|
m_defaultPipe->SendRequest( USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD , //Type
|
||||||
USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD , //Type
|
|
||||||
USB_REQUEST_SET_CONFIGURATION , //Request
|
USB_REQUEST_SET_CONFIGURATION , //Request
|
||||||
value , //Value
|
value , //Value
|
||||||
0 , //Index
|
0 , //Index
|
||||||
|
|||||||
@@ -21,8 +21,8 @@
|
|||||||
|
|
||||||
#include "usb_p.h"
|
#include "usb_p.h"
|
||||||
|
|
||||||
Hub::Hub( BusManager *bus , Device *parent , usb_device_descriptor &desc , int8 devicenum )
|
Hub::Hub( BusManager *bus , Device *parent , usb_device_descriptor &desc , int8 devicenum , bool lowspeed )
|
||||||
: Device ( bus , parent , desc , devicenum )
|
: Device ( bus , parent , desc , devicenum , lowspeed )
|
||||||
{
|
{
|
||||||
dprintf( "USB Hub is being initialised\n" );
|
dprintf( "USB Hub is being initialised\n" );
|
||||||
m_initok = false; // We're not yet ready!
|
m_initok = false; // We're not yet ready!
|
||||||
@@ -82,7 +82,7 @@ Hub::Hub( BusManager *bus , Device *parent , usb_device_descriptor &desc , int8
|
|||||||
|
|
||||||
// Enable port power on all ports
|
// Enable port power on all ports
|
||||||
for ( int i = 0 ; i < m_hub_descriptor.bNbrPorts ; i++ )
|
for ( int i = 0 ; i < m_hub_descriptor.bNbrPorts ; i++ )
|
||||||
m_bus->SendRequest( this , USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT ,
|
m_defaultPipe->SendRequest( USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT ,
|
||||||
USB_REQUEST_SET_FEATURE ,
|
USB_REQUEST_SET_FEATURE ,
|
||||||
PORT_POWER ,
|
PORT_POWER ,
|
||||||
i + 1 , //index
|
i + 1 , //index
|
||||||
@@ -104,7 +104,7 @@ void Hub::Explore()
|
|||||||
for ( int i = 0 ; i < m_hub_descriptor.bNbrPorts ; i++ )
|
for ( int i = 0 ; i < m_hub_descriptor.bNbrPorts ; i++ )
|
||||||
{
|
{
|
||||||
// Get the current port status
|
// Get the current port status
|
||||||
m_bus->SendRequest( this , USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_IN ,
|
m_defaultPipe->SendRequest( USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_IN ,
|
||||||
USB_REQUEST_GET_STATUS ,
|
USB_REQUEST_GET_STATUS ,
|
||||||
0 , //Value
|
0 , //Value
|
||||||
i + 1 , //Index
|
i + 1 , //Index
|
||||||
@@ -119,6 +119,21 @@ void Hub::Explore()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//We need to test the port change against a number of things
|
//We need to test the port change against a number of things
|
||||||
|
|
||||||
|
if ( m_port_status[i].status & PORT_RESET )
|
||||||
|
{
|
||||||
|
//We didn't do this!
|
||||||
|
m_defaultPipe->SendRequest( USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT ,
|
||||||
|
USB_REQUEST_CLEAR_FEATURE ,
|
||||||
|
PORT_RESET ,
|
||||||
|
i + 1 , //index
|
||||||
|
0 ,
|
||||||
|
NULL ,
|
||||||
|
0 ,
|
||||||
|
&actual_length );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( m_port_status[i].change & PORT_STATUS_CONNECTION )
|
if ( m_port_status[i].change & PORT_STATUS_CONNECTION )
|
||||||
{
|
{
|
||||||
if ( m_port_status[i].status & PORT_STATUS_CONNECTION )
|
if ( m_port_status[i].status & PORT_STATUS_CONNECTION )
|
||||||
@@ -137,7 +152,7 @@ void Hub::Explore()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Clear status
|
//Clear status
|
||||||
m_bus->SendRequest( this , USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT ,
|
m_defaultPipe->SendRequest( USB_REQTYPE_CLASS | USB_REQTYPE_OTHER_OUT ,
|
||||||
USB_REQUEST_CLEAR_FEATURE ,
|
USB_REQUEST_CLEAR_FEATURE ,
|
||||||
C_PORT_CONNECTION ,
|
C_PORT_CONNECTION ,
|
||||||
i + 1 , //index
|
i + 1 , //index
|
||||||
|
|||||||
@@ -10,5 +10,6 @@ R5KernelAddon usb : [ FDirName kernel bus_managers ] :
|
|||||||
Device.cpp
|
Device.cpp
|
||||||
Hub.cpp
|
Hub.cpp
|
||||||
BusManager.cpp
|
BusManager.cpp
|
||||||
Packet.cpp
|
Transfer.cpp
|
||||||
|
Pipe.cpp
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2004, 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"
|
||||||
|
|
||||||
|
Pipe::Pipe( Device *dev , Direction &dir , uint8 &endpointaddress )
|
||||||
|
{
|
||||||
|
d = new usb_pipe_t;
|
||||||
|
|
||||||
|
d->direction = dir;
|
||||||
|
m_device = dev;
|
||||||
|
|
||||||
|
if ( m_device != NULL ) //Default pipe
|
||||||
|
{
|
||||||
|
d->deviceid = dev->m_devicenum;
|
||||||
|
if ( dev->m_lowspeed == true )
|
||||||
|
d->speed = LowSpeed;
|
||||||
|
else
|
||||||
|
d->speed = NormalSpeed;
|
||||||
|
m_bus = m_device->m_bus;
|
||||||
|
}
|
||||||
|
d->endpoint = endpointaddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pipe::~Pipe()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlPipe::ControlPipe( Device *dev , Direction dir , uint8 endpointaddress )
|
||||||
|
: Pipe( dev , dir , endpointaddress )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlPipe::ControlPipe( BusManager *bus , int8 dev_id , Direction dir , Speed speed , uint8 endpointaddress )
|
||||||
|
: Pipe( NULL , dir , endpointaddress )
|
||||||
|
{
|
||||||
|
m_bus = bus;
|
||||||
|
d->deviceid = dev_id;
|
||||||
|
d->speed = speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t ControlPipe::SendRequest( 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( req , data , data_len , actual_len , 3 * 1000 * 1000 );
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t ControlPipe::SendControlMessage( 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
|
||||||
|
Transfer transfer( *this );
|
||||||
|
|
||||||
|
transfer.SetRequestData( command );
|
||||||
|
transfer.SetBuffer( (uint8 *)data );
|
||||||
|
transfer.SetBufferLength( data_length );
|
||||||
|
transfer.SetActualLength( actual_length );
|
||||||
|
|
||||||
|
status_t retval = m_bus->hcpointer->SubmitPacket( transfer.GetData() );
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Copyright (c) 2003, Niels S. Reedijk
|
// Copyright (c) 2003, Niels S. Reedijk
|
||||||
//
|
//
|
||||||
|
// AllocArea implementation (c) 2002 Marcus Overhagen <[email protected]>
|
||||||
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
// to deal in the Software without restriction, including without limitation
|
// to deal in the Software without restriction, including without limitation
|
||||||
@@ -51,6 +53,57 @@ Stack::Stack()
|
|||||||
|
|
||||||
if( m_busmodules.Count() == 0 )
|
if( m_busmodules.Count() == 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
//Initialise the memory chunks: create 8, 16 and 32 byte-heaps
|
||||||
|
//NOTE: This is probably the most ugly code you will see in the
|
||||||
|
//whole stack. Unfortunately this is needed because of the fact
|
||||||
|
//that the compiler doesn't like us to apply pointer arithmethic
|
||||||
|
//to (void *) pointers.
|
||||||
|
|
||||||
|
|
||||||
|
uint16 size = 0;
|
||||||
|
for ( int i = 0 ; i < 3 ; i++ )
|
||||||
|
{
|
||||||
|
size = 2^(3+i);
|
||||||
|
dprintf( "USB: Initialising %u-byte chunk area\n" , size );
|
||||||
|
m_areafreecount[i] = 0;
|
||||||
|
|
||||||
|
if ( AllocArea(0) < B_OK )
|
||||||
|
{
|
||||||
|
dprintf( "USB: %u-byte chunk area failed to initialise\n" , size );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *listhead;
|
||||||
|
|
||||||
|
switch (size)
|
||||||
|
{
|
||||||
|
case 8:
|
||||||
|
listhead = m_8_listhead;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
listhead = m_16_listhead;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
listhead = m_32_listhead;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dprintf( "USB: Strange error: %u-byte chunks don't exist\n", size );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
listhead = m_logical[i];
|
||||||
|
|
||||||
|
for ( int j = 0 ; j < B_PAGE_SIZE/size ; j++ )
|
||||||
|
{
|
||||||
|
memory_chunk *chunk = (memory_chunk *)((uint32)m_logical[i] + size * j);
|
||||||
|
chunk->physical = (void *)((uint32)m_physical[i] + size * j);
|
||||||
|
if ( j != B_PAGE_SIZE / size - 1 )
|
||||||
|
chunk->next_item = (void *)((uint32)m_logical[i] + size * ( j + 1 ) );
|
||||||
|
else
|
||||||
|
chunk->next_item = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Stack::~Stack()
|
Stack::~Stack()
|
||||||
@@ -68,4 +121,119 @@ status_t Stack::InitCheck()
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Stack::Lock()
|
||||||
|
{
|
||||||
|
acquire_sem( m_master );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Stack::Unlock()
|
||||||
|
{
|
||||||
|
release_sem( m_master );
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t Stack::AllocateChunk( void **log , void **phy , uint8 size )
|
||||||
|
{
|
||||||
|
Lock();
|
||||||
|
|
||||||
|
void *listhead;
|
||||||
|
if ( size <= 8 )
|
||||||
|
listhead = m_8_listhead;
|
||||||
|
else if ( size <= 16 )
|
||||||
|
listhead = m_16_listhead;
|
||||||
|
else if ( size <= 32 )
|
||||||
|
listhead = m_32_listhead;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dprintf ( "USB Stack: Chunk size %i to big\n" , size );
|
||||||
|
Unlock();
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( listhead == NULL )
|
||||||
|
{
|
||||||
|
Unlock();
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
memory_chunk *chunk = (memory_chunk *)listhead;
|
||||||
|
*log = listhead;
|
||||||
|
*phy = chunk->physical;
|
||||||
|
if ( chunk->next_item == NULL )
|
||||||
|
//TODO: allocate more memory
|
||||||
|
listhead = NULL;
|
||||||
|
else
|
||||||
|
m_8_listhead = chunk->next_item;
|
||||||
|
Unlock();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t Stack::FreeChunk( void *log , void *phy , uint8 size )
|
||||||
|
{
|
||||||
|
Lock();
|
||||||
|
void *listhead;
|
||||||
|
if ( size <= 8 )
|
||||||
|
listhead = m_8_listhead;
|
||||||
|
else if ( size <= 16 )
|
||||||
|
listhead = m_16_listhead;
|
||||||
|
else if ( size <= 32 )
|
||||||
|
listhead = m_32_listhead;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dprintf ( "USB Stack: Chunk size %i invalid\n" , size );
|
||||||
|
Unlock();
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
memory_chunk *chunk = (memory_chunk *)log;
|
||||||
|
|
||||||
|
chunk->next_item = listhead;
|
||||||
|
chunk->physical = phy;
|
||||||
|
listhead = log;
|
||||||
|
Unlock();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
area_id Stack::AllocArea( void **log , void **phy , size_t size , const char *name )
|
||||||
|
{
|
||||||
|
physical_entry pe;
|
||||||
|
void * logadr;
|
||||||
|
area_id areaid;
|
||||||
|
status_t rv;
|
||||||
|
|
||||||
|
dprintf("allocating %ld bytes for %s\n",size,name);
|
||||||
|
|
||||||
|
size = (size + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
|
||||||
|
areaid = create_area(name, &logadr, B_ANY_KERNEL_ADDRESS,size,B_FULL_LOCK | B_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA);
|
||||||
|
if (areaid < B_OK) {
|
||||||
|
dprintf("couldn't allocate area %s\n",name);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
rv = get_memory_map(logadr,size,&pe,1);
|
||||||
|
if (rv < B_OK) {
|
||||||
|
delete_area(areaid);
|
||||||
|
dprintf("couldn't map %s\n",name);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
memset(logadr,0,size);
|
||||||
|
if (log)
|
||||||
|
*log = logadr;
|
||||||
|
if (phy)
|
||||||
|
*phy = pe.address;
|
||||||
|
dprintf("area = %ld, size = %ld, log = %#08lX, phy = %#08lX\n",areaid,size,(uint32)logadr,(uint32)(pe.address));
|
||||||
|
return areaid;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Wrapper for the above, but it works on our internal data structures
|
||||||
|
status_t Stack::AllocArea( uint8 id )
|
||||||
|
{
|
||||||
|
if ( id > USB_MAX_AREAS )
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
m_areas[id] = AllocArea( &m_logical[id] , &m_physical[id] , B_PAGE_SIZE , "internal USB stack area" );
|
||||||
|
|
||||||
|
if ( m_areas[id] < B_OK )
|
||||||
|
return B_ERROR;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
Stack *data = 0;
|
Stack *data = 0;
|
||||||
|
|||||||
+10
-19
@@ -21,47 +21,38 @@
|
|||||||
|
|
||||||
#include "usb_p.h"
|
#include "usb_p.h"
|
||||||
|
|
||||||
Packet::Packet()
|
Transfer::Transfer( Pipe &pipe )
|
||||||
{
|
{
|
||||||
d = new usb_packet_t;
|
d = new usb_transfer_t;
|
||||||
|
d->pipe = pipe.d;
|
||||||
}
|
}
|
||||||
|
|
||||||
Packet::~Packet()
|
Transfer::~Transfer()
|
||||||
{
|
{
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Packet::SetPipe( uint16 pipe )
|
void Transfer::SetRequestData( usb_request_data *data )
|
||||||
{
|
{
|
||||||
d->pipe = pipe;
|
d->request = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Packet::SetAddress( uint8 address )
|
void Transfer::SetBuffer( uint8 *buffer )
|
||||||
{
|
|
||||||
d->address = address;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Packet::SetRequestData( uint8 *data )
|
|
||||||
{
|
|
||||||
d->requestdata = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Packet::SetBuffer( uint8 *buffer )
|
|
||||||
{
|
{
|
||||||
d->buffer = buffer;
|
d->buffer = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Packet::SetBufferLength( int16 length )
|
void Transfer::SetBufferLength( int16 length )
|
||||||
{
|
{
|
||||||
d->bufferlength = length;
|
d->bufferlength = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Packet::SetActualLength( size_t *actual_length )
|
void Transfer::SetActualLength( size_t *actual_length )
|
||||||
{
|
{
|
||||||
d->actual_length = actual_length;
|
d->actual_length = actual_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
usb_packet_t * Packet::GetData()
|
usb_transfer_t * Transfer::GetData()
|
||||||
{
|
{
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
@@ -64,22 +64,42 @@ typedef struct
|
|||||||
uint16 Length;
|
uint16 Length;
|
||||||
} usb_request_data;
|
} usb_request_data;
|
||||||
|
|
||||||
// Describes the internal organs of an usb packet
|
// Describes the internals of a pipe
|
||||||
typedef struct usb_packet_t
|
enum Direction { In , Out , Default };
|
||||||
{
|
enum Speed { LowSpeed , NormalSpeed };
|
||||||
uint16 pipe;
|
|
||||||
uint8 *requestdata;
|
|
||||||
uint8 *buffer;
|
|
||||||
int16 bufferlength;
|
|
||||||
size_t *actual_length;
|
|
||||||
int16 address; //!!!! TEMPORARY ... or is it?
|
|
||||||
} usb_packet_t;
|
|
||||||
|
|
||||||
|
typedef struct usb_pipe_t
|
||||||
|
{
|
||||||
|
enum Direction direction;
|
||||||
|
enum Speed speed;
|
||||||
|
int8 deviceid;
|
||||||
|
uint8 endpoint;
|
||||||
|
} usb_pipe_t;
|
||||||
|
|
||||||
|
|
||||||
|
// Describes the internal organs of an usb packet
|
||||||
|
typedef struct usb_transfer_t
|
||||||
|
{
|
||||||
|
//Data that is related to the transfer
|
||||||
|
usb_pipe_t *pipe;
|
||||||
|
uint8 *buffer;
|
||||||
|
size_t bufferlength;
|
||||||
|
size_t *actual_length;
|
||||||
|
bigtime_t timeout;
|
||||||
|
status_t status;
|
||||||
|
|
||||||
|
//For control transfers
|
||||||
|
usb_request_data *request;
|
||||||
|
} usb_transfer_t;
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
typedef struct host_controller_info
|
typedef struct host_controller_info
|
||||||
{
|
{
|
||||||
module_info info;
|
module_info info;
|
||||||
status_t (*hwstart)(void);
|
status_t (*hwstart)(void);
|
||||||
status_t (*SubmitPacket)(usb_packet_t *);
|
status_t (*SubmitPacket)(usb_transfer_t *);
|
||||||
} host_controller_info;
|
} host_controller_info;
|
||||||
|
|
||||||
#endif //HOST_CONTROLLER_INFO_H
|
#endif //HOST_CONTROLLER_INFO_H
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ resource app_version {
|
|||||||
middle = 0,
|
middle = 0,
|
||||||
minor = 1,
|
minor = 1,
|
||||||
variety = 0,
|
variety = 0,
|
||||||
internal = 0,
|
internal = 1,
|
||||||
short_info = "USB system software",
|
short_info = "USB system software",
|
||||||
long_info = "OpenBeOS - This driver is (c) 2003-2004 Niels Sascha Reedijk"
|
long_info = "OpenBeOS - This driver is (c) 2003-2004 Niels Sascha Reedijk"
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// Copyright (c) 2003, Niels S. Reedijk
|
// Copyright (c) 2004, Niels S. Reedijk
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
// copy of this software and associated documentation files (the "Software"),
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
@@ -28,11 +28,20 @@
|
|||||||
#include "host_controller.h"
|
#include "host_controller.h"
|
||||||
#include <util/kernel_cpp.h>
|
#include <util/kernel_cpp.h>
|
||||||
|
|
||||||
|
|
||||||
/* ++++++++++
|
/* ++++++++++
|
||||||
Forward declarations
|
Forward declarations
|
||||||
++++++++++ */
|
++++++++++ */
|
||||||
class Device;
|
class Device;
|
||||||
class BusManager;
|
class BusManager;
|
||||||
|
class ControlPipe;
|
||||||
|
|
||||||
|
#define USB_MAX_AREAS 8
|
||||||
|
struct memory_chunk
|
||||||
|
{
|
||||||
|
void *next_item;
|
||||||
|
void *physical;
|
||||||
|
};
|
||||||
|
|
||||||
/* ++++++++++
|
/* ++++++++++
|
||||||
Important data from the USB spec (not interesting for drivers)
|
Important data from the USB spec (not interesting for drivers)
|
||||||
@@ -50,18 +59,38 @@ public:
|
|||||||
Stack();
|
Stack();
|
||||||
~Stack();
|
~Stack();
|
||||||
status_t InitCheck();
|
status_t InitCheck();
|
||||||
|
|
||||||
|
void Lock();
|
||||||
|
void Unlock();
|
||||||
|
|
||||||
|
status_t AllocateChunk( void **log , void **phy , uint8 size );
|
||||||
|
status_t FreeChunk( void *log , void *phy , uint8 size );
|
||||||
|
|
||||||
|
area_id AllocArea( void **log , void **phy , size_t size , const char *name );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
//Small wrapper around AllocArea
|
||||||
|
status_t AllocArea( uint8 id );
|
||||||
|
|
||||||
Vector<BusManager *> 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_master; //The master lock
|
||||||
sem_id m_datalock; //Lock that controls data transfers
|
sem_id m_datalock; //Lock that controls data transfers
|
||||||
|
area_id m_areas[USB_MAX_AREAS]; //Stores the area_id for the memory pool
|
||||||
|
void *m_logical[USB_MAX_AREAS];//Stores the logical base addresses
|
||||||
|
void *m_physical[USB_MAX_AREAS];//Stores the physical base addresses
|
||||||
|
uint16 m_areafreecount[USB_MAX_AREAS]; //Keeps track of how many free chunks there are
|
||||||
|
void *m_8_listhead;
|
||||||
|
void *m_16_listhead;
|
||||||
|
void *m_32_listhead;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" Stack *data;
|
extern "C" Stack *data;
|
||||||
|
|
||||||
class Device
|
class Device
|
||||||
{
|
{
|
||||||
|
friend class Pipe;
|
||||||
public:
|
public:
|
||||||
Device( BusManager *bus , Device *parent , usb_device_descriptor &desc , int8 devicenum );
|
Device( BusManager *bus , Device *parent , usb_device_descriptor &desc , int8 devicenum , bool speed);
|
||||||
virtual bool IsHub() { return false; };
|
virtual bool IsHub() { return false; };
|
||||||
status_t InitCheck();
|
status_t InitCheck();
|
||||||
|
|
||||||
@@ -73,7 +102,9 @@ protected:
|
|||||||
usb_device_descriptor m_device_descriptor;
|
usb_device_descriptor m_device_descriptor;
|
||||||
usb_configuration_descriptor * m_configurations;
|
usb_configuration_descriptor * m_configurations;
|
||||||
usb_configuration_descriptor * m_current_configuration;
|
usb_configuration_descriptor * m_current_configuration;
|
||||||
|
ControlPipe * m_defaultPipe;
|
||||||
bool m_initok;
|
bool m_initok;
|
||||||
|
bool m_lowspeed;
|
||||||
BusManager * m_bus;
|
BusManager * m_bus;
|
||||||
Device * m_parent;
|
Device * m_parent;
|
||||||
int8 m_devicenum;
|
int8 m_devicenum;
|
||||||
@@ -85,7 +116,7 @@ protected:
|
|||||||
class Hub : public Device
|
class Hub : public Device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Hub( BusManager *bus , Device *parent , usb_device_descriptor &desc , int8 devicenum);
|
Hub( BusManager *bus , Device *parent , usb_device_descriptor &desc , int8 devicenum , bool lowspeed );
|
||||||
virtual bool IsHub() { return true; };
|
virtual bool IsHub() { return true; };
|
||||||
|
|
||||||
void Explore();
|
void Explore();
|
||||||
@@ -105,26 +136,21 @@ private:
|
|||||||
class BusManager
|
class BusManager
|
||||||
{
|
{
|
||||||
friend class Device;
|
friend class Device;
|
||||||
|
friend class ControlPipe;
|
||||||
public:
|
public:
|
||||||
BusManager( host_controller_info *info );
|
BusManager( host_controller_info *info );
|
||||||
~BusManager();
|
~BusManager();
|
||||||
|
|
||||||
status_t InitCheck();
|
status_t InitCheck();
|
||||||
|
|
||||||
Device *AllocateNewDevice( Device *parent );
|
Device *AllocateNewDevice( Device *parent , bool speed );
|
||||||
int8 AllocateAddress();
|
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:
|
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;
|
host_controller_info *hcpointer;
|
||||||
bool m_initok;
|
bool m_initok;
|
||||||
bool m_devicemap[128];
|
bool m_devicemap[128];
|
||||||
|
ControlPipe *m_defaultLowSpeedPipe;
|
||||||
|
ControlPipe *m_defaultPipe;
|
||||||
sem_id m_lock;
|
sem_id m_lock;
|
||||||
Device *m_roothub;
|
Device *m_roothub;
|
||||||
thread_id m_explore_thread;
|
thread_id m_explore_thread;
|
||||||
@@ -133,27 +159,56 @@ private:
|
|||||||
// Located in the BusManager.cpp
|
// Located in the BusManager.cpp
|
||||||
int32 usb_explore_thread( void *data );
|
int32 usb_explore_thread( void *data );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The Pipe class is the communication management between the hardware and\
|
||||||
|
* the stack. It creates packets, manages these and performs callbacks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Pipe
|
||||||
|
{
|
||||||
|
friend class Transfer;
|
||||||
|
public:
|
||||||
|
Pipe( Device *dev , Direction &dir , uint8 &endpointaddress );
|
||||||
|
virtual ~Pipe();
|
||||||
|
protected:
|
||||||
|
Device *m_device;
|
||||||
|
BusManager *m_bus;
|
||||||
|
usb_pipe_t *d;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ControlPipe : public Pipe
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ControlPipe( Device *dev , Direction dir , uint8 endpointaddress );
|
||||||
|
//Special constructor for default control pipe
|
||||||
|
ControlPipe( BusManager *bus , int8 dev_id , Direction dir , Speed speed , uint8 endpointaddress );
|
||||||
|
status_t SendRequest( uint8 request_type , uint8 request ,
|
||||||
|
uint16 value , uint16 index , uint16 length , void *data ,
|
||||||
|
size_t data_len , size_t *actual_len );
|
||||||
|
status_t SendControlMessage( usb_request_data *command , void *data ,
|
||||||
|
size_t data_length , size_t *actual_length , bigtime_t timeout );
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This class is more like an utility class that performs all functions on
|
* 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
|
* packets. The class is only used in the bus_manager: the host controllers
|
||||||
* receive the internal data structures.
|
* receive the internal data structures.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Packet
|
class Transfer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Packet();
|
Transfer( Pipe &pipe );
|
||||||
~Packet();
|
~Transfer();
|
||||||
void SetPipe( uint16 pipe );
|
void SetRequestData( usb_request_data *data );
|
||||||
void SetRequestData( uint8 *data );
|
|
||||||
void SetBuffer( uint8 *buffer );
|
void SetBuffer( uint8 *buffer );
|
||||||
void SetBufferLength( int16 length );
|
void SetBufferLength( int16 length );
|
||||||
void SetAddress( uint8 address );
|
|
||||||
void SetActualLength( size_t * );
|
void SetActualLength( size_t * );
|
||||||
|
|
||||||
usb_packet_t *GetData();
|
usb_transfer_t *GetData();
|
||||||
private:
|
private:
|
||||||
usb_packet_t *d;
|
usb_transfer_t *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user