diff --git a/src/add-ons/kernel/bus_managers/usb/BusManager.cpp b/src/add-ons/kernel/bus_managers/usb/BusManager.cpp index 7c3eafdb80..7444662709 100644 --- a/src/add-ons/kernel/bus_managers/usb/BusManager.cpp +++ b/src/add-ons/kernel/bus_managers/usb/BusManager.cpp @@ -33,7 +33,7 @@ int32 usb_explore_thread( void *data ) if ( roothub == 0 ) return B_ERROR; - while (true ) + while ( true ) { //Go to the hubs roothub->Explore(); @@ -55,17 +55,15 @@ BusManager::BusManager() set_sem_owner( B_SYSTEM_TEAM , m_lock ); // Clear the device map - memset( &m_devicemap , false , 128 ); + memset( &m_devicemap , 0 , 128 ); // Set up the default pipes m_defaultPipe = new ControlPipe( this , 0 , Pipe::Default , Pipe::NormalSpeed , 0 ); m_defaultLowSpeedPipe = new ControlPipe( this , 0 , Pipe::Default , Pipe::LowSpeed , 0 ); - // 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 ); - + // Clear the 'explore thread' + m_explore_thread = 0; + m_initok = true; } @@ -144,7 +142,7 @@ Device * BusManager::AllocateNewDevice( Device *parent , bool lowspeed ) Device *ret = new Hub( this , parent , device_descriptor , devicenum , lowspeed ); if ( parent == 0 ) //root hub!! m_roothub = ret; - return ret; + return 0; } dprintf( "usb Busmanager [new device]: New normal device\n" ); @@ -170,16 +168,19 @@ int8 BusManager::AllocateAddress() status_t BusManager::Start() { + dprintf( "USB: BusManager::Start()\n" ); if ( InitCheck() != B_OK ) return InitCheck(); - // Start the 'explore thread' - m_explore_thread = spawn_kernel_thread( usb_explore_thread , "usb_busmanager_explore" , + if ( m_explore_thread == 0 ) + m_explore_thread = spawn_kernel_thread( usb_explore_thread , "usb_busmanager_explore" , B_LOW_PRIORITY , (void *)m_roothub ); + + // Start the 'explore thread' return resume_thread( m_explore_thread ); } -status_t BusManager::SubmitTransfer( Transfer &t ) +status_t BusManager::SubmitTransfer( Transfer *t ) { return B_ERROR; }; diff --git a/src/add-ons/kernel/bus_managers/usb/Hub.cpp b/src/add-ons/kernel/bus_managers/usb/Hub.cpp index 0d5ec73834..35156aaa65 100644 --- a/src/add-ons/kernel/bus_managers/usb/Hub.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Hub.cpp @@ -146,9 +146,14 @@ void Hub::Explore() if ( m_port_status[i].status & PORT_STATUS_CONNECTION ) { //New device attached! - //DO something dprintf( "USB Hub Explore(): New device connected\n" ); - + Device *newdev; + if ( m_port_status[i].status & PORT_STATUS_LOW_SPEED ) + newdev = m_bus->AllocateNewDevice( this , true ); + else + newdev = m_bus->AllocateNewDevice( this , false ); + if ( newdev != 0 ) + m_children[i] = newdev; } else { diff --git a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp index 0e445febdd..72831cfff8 100644 --- a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp @@ -53,10 +53,7 @@ ControlPipe::ControlPipe( BusManager *bus , int8 dev_address , Direction dir , S { m_bus = bus; m_deviceaddress = dev_address; - if ( speed == LowSpeed ) - m_lowspeed = true; - else - m_lowspeed = false; + m_speed = speed; } int8 ControlPipe::GetDeviceAddress() @@ -71,19 +68,15 @@ status_t ControlPipe::SendRequest( uint8 request_type , uint8 request , uint16 v 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) ); + usb_request_data req; - req->RequestType = request_type; - req->Request = request; - req->Value = value; - req->Index = index; - req->Length = length; + 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 ); + return SendControlMessage( &req , data , data_len , actual_len , 3 * 1000 * 1000 ); } status_t ControlPipe::SendControlMessage( usb_request_data *command , void *data , @@ -91,12 +84,12 @@ status_t ControlPipe::SendControlMessage( usb_request_data *command , void *data bigtime_t timeout ) { // this method should build an usb packet (new class) with the needed data - Transfer transfer( this ); + Transfer *transfer = new Transfer( this , true ); - transfer.SetRequestData( command ); - transfer.SetBuffer( (uint8 *)data ); - transfer.SetBufferLength( data_length ); - transfer.SetActualLength( actual_length ); + transfer->SetRequestData( command ); + transfer->SetBuffer( (uint8 *)data ); + transfer->SetBufferLength( data_length ); + transfer->SetActualLength( actual_length ); status_t retval = m_bus->SubmitTransfer( transfer ); return retval; diff --git a/src/add-ons/kernel/bus_managers/usb/Stack.cpp b/src/add-ons/kernel/bus_managers/usb/Stack.cpp index 7662690a92..1f2aff8618 100644 --- a/src/add-ons/kernel/bus_managers/usb/Stack.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Stack.cpp @@ -55,14 +55,14 @@ Stack::Stack() return; } - m_8_listhead = m_logical[0]; + m_8_listhead = (addr_t)m_logical[0]; for ( int i = 0 ; i < B_PAGE_SIZE/8 ; i++ ) { memory_chunk *chunk = (memory_chunk *)((addr_t)m_logical[0] + 8 * i); - chunk->physical = (void *)((addr_t)m_physical[0] + 8 * i); + chunk->physical = (addr_t)m_physical[0] + 8 * i; if ( i != B_PAGE_SIZE / 8 - 1 ) - chunk->next_item = (void *)((addr_t)m_logical[0] + 8 * ( i + 1 ) ); + chunk->next_item = (addr_t)m_logical[0] + 8 * ( i + 1 ); else chunk->next_item = NULL; } @@ -77,14 +77,14 @@ Stack::Stack() return; } - m_16_listhead = m_logical[1]; + m_16_listhead = (addr_t)m_logical[1]; for ( int i = 0 ; i < B_PAGE_SIZE/16 ; i++ ) { memory_chunk *chunk = (memory_chunk *)((addr_t)m_logical[1] + 16 * i); - chunk->physical = (void *)((addr_t)m_physical[1] + 16 * i); + chunk->physical = (addr_t)m_physical[1] + 16 * i; if ( i != B_PAGE_SIZE / 16 - 1 ) - chunk->next_item = (void *)((addr_t)m_logical[1] + 16 * ( i + 1 )); + chunk->next_item = (addr_t)m_logical[1] + 16 * ( i + 1 ); else chunk->next_item = NULL; } @@ -99,14 +99,14 @@ Stack::Stack() return; } - m_32_listhead = m_logical[2]; + m_32_listhead = (addr_t)m_logical[2]; for ( int i = 0 ; i < B_PAGE_SIZE/32 ; i++ ) { memory_chunk *chunk = (memory_chunk *)((addr_t)m_logical[2] + 32 * i); - chunk->physical = (void *)((addr_t)m_physical[2] + 32 * i); + chunk->physical = (addr_t)m_physical[2] + 32 * i; if ( i != B_PAGE_SIZE / 32 - 1 ) - chunk->next_item = (void *)((addr_t)m_logical[2] + 32 * ( i + 1 )); + chunk->next_item = (addr_t)m_logical[2] + 32 * ( i + 1 ); else chunk->next_item = NULL; } @@ -170,7 +170,7 @@ status_t Stack::AllocateChunk( void **log , void **phy , uint8 size ) { Lock(); - void *listhead; + addr_t listhead; if ( size <= 8 ) listhead = m_8_listhead; else if ( size <= 16 ) @@ -187,17 +187,29 @@ status_t Stack::AllocateChunk( void **log , void **phy , uint8 size ) if ( listhead == NULL ) { Unlock(); + dprintf( "USB Stack: Out of memory on this list\n" ); return B_ERROR; } + dprintf( "USB Stack::Allocate() listhead: %l\n" , listhead ); + memory_chunk *chunk = (memory_chunk *)listhead; - *log = listhead; - *phy = chunk->physical; + *log = (void *)listhead; + *phy = (void *)(chunk->physical); if ( chunk->next_item == NULL ) //TODO: allocate more memory listhead = NULL; else - m_8_listhead = chunk->next_item; + listhead = chunk->next_item; + + //Update our listhead pointers + if ( size <= 8 ) + m_8_listhead = listhead; + else if ( size <= 16 ) + m_16_listhead = listhead; + else if ( size <= 32 ) + m_32_listhead = listhead; + Unlock(); dprintf( "USB Stack: allocated a new chunk with size %u\n" , size ); return B_OK; @@ -206,7 +218,7 @@ status_t Stack::AllocateChunk( void **log , void **phy , uint8 size ) status_t Stack::FreeChunk( void *log , void *phy , uint8 size ) { Lock(); - void *listhead; + addr_t listhead; if ( size <= 8 ) listhead = m_8_listhead; else if ( size <= 16 ) @@ -223,8 +235,15 @@ status_t Stack::FreeChunk( void *log , void *phy , uint8 size ) memory_chunk *chunk = (memory_chunk *)log; chunk->next_item = listhead; - chunk->physical = phy; - listhead = log; + chunk->physical = (addr_t)phy; + + if ( size <= 8 ) + m_8_listhead = (addr_t)log; + else if ( size <= 16 ) + m_16_listhead = (addr_t)log; + else if ( size <= 32 ) + m_32_listhead = (addr_t)log; + Unlock(); return B_OK; } @@ -239,7 +258,7 @@ area_id Stack::AllocateArea( void **log , void **phy , size_t size , const char 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); + areaid = create_area(name, &logadr, B_ANY_KERNEL_ADDRESS,size,B_FULL_LOCK | B_CONTIGUOUS, 0 ); if (areaid < B_OK) { dprintf("couldn't allocate area %s\n",name); return B_ERROR; diff --git a/src/add-ons/kernel/bus_managers/usb/Transfer.cpp b/src/add-ons/kernel/bus_managers/usb/Transfer.cpp index 3b50ed0c84..7524680049 100644 --- a/src/add-ons/kernel/bus_managers/usb/Transfer.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Transfer.cpp @@ -21,13 +21,28 @@ #include "usb_p.h" -Transfer::Transfer( Pipe *pipe ) +Transfer::Transfer( Pipe *pipe , bool synchronous ) { m_pipe = pipe; + m_buffer = 0; + m_bufferlength = 0; + m_actual_length = 0; + m_timeout = 0; + m_status = 0; + m_sem = B_ERROR; + m_hcpriv = 0; + + if ( synchronous == true ) + { + m_sem = create_sem( 0 , "USB Transfer" ); + set_sem_owner ( m_sem , B_SYSTEM_TEAM ); + } } Transfer::~Transfer() { + if ( m_sem > B_OK ) + delete_sem( m_sem ); } void Transfer::SetRequestData( usb_request_data *data ) @@ -49,3 +64,32 @@ void Transfer::SetActualLength( size_t *actual_length ) { m_actual_length = actual_length; }; + +void Transfer::SetCallbackFunction( usb_callback_func callback ) +{ + m_callback = callback; +} + +void Transfer::SetHostPrivate( hostcontroller_priv *priv ) +{ + m_hcpriv = priv; +} + +void Transfer::WaitForFinish() +{ + if ( m_sem > B_OK ) + acquire_sem( m_sem ); +} + +void Transfer::TransferDone() +{ + if ( m_sem > B_OK ) + release_sem( m_sem ); +} + +void Transfer::Finish() +{ + //If we are synchronous, release a sem + if ( m_sem > B_OK ) + release_sem( m_sem ); +} 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 9057241c32..e55a1b6294 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb_p.h +++ b/src/add-ons/kernel/bus_managers/usb/usb_p.h @@ -22,11 +22,7 @@ #ifndef USB_P #define USB_P -#include -#include -#include -#include - +#include /* ++++++++++ Forward declarations @@ -37,20 +33,6 @@ class Transfer; 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) -++++++++++ */ - -#define POWER_DELAY - /* ++++++++++ The host_controller_info ++++++++++ */ @@ -61,61 +43,6 @@ struct host_controller_info bool (*add_to)(Stack &stack); }; -struct usb_request_data -{ - uint8 RequestType; - uint8 Request; - uint16 Value; - uint16 Index; - uint16 Length; -}; - -struct usb_hub_descriptor -{ - uint8 bDescLength; - uint8 bDescriptorType; - uint8 bNbrPorts; - uint16 wHubCharacteristics; - uint8 bPwrOn2PwrGood; - uint8 bHucContrCurrent; - uint8 DeviceRemovable; //Should be variable!!! - uint8 PortPwrCtrlMask; //Deprecated -}; - -#define USB_DESCRIPTOR_HUB 0x29 - -// USB Spec 1.1 page 273 -struct usb_port_status -{ - uint16 status; - uint16 change; -}; - -//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 - /* ++++++++++ Internal classes @@ -145,9 +72,9 @@ private: 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; + addr_t m_8_listhead; + addr_t m_16_listhead; + addr_t m_32_listhead; }; extern "C" Stack *data; @@ -193,6 +120,7 @@ private: usb_hub_descriptor m_hub_descriptor; usb_port_status m_port_status[8]; //Max of 8 ports, for the moment + Device *m_children[8]; }; /* @@ -215,7 +143,7 @@ public: virtual status_t Start(); // virtual status_t Stop(); - virtual status_t SubmitTransfer( Transfer &t ); + virtual status_t SubmitTransfer( Transfer *t ); protected: void SetRootHub( Hub *hub ) { m_roothub = hub; }; Device* GetRootHub() { return m_roothub; }; @@ -243,11 +171,15 @@ class Pipe public: enum Direction { In , Out , Default }; enum Speed { LowSpeed , NormalSpeed }; + enum Type { Control , Bulk , Isochronous , Interrupt , Invalid }; Pipe( Device *dev , Direction &dir , uint8 &endpointaddress ); virtual ~Pipe(); virtual int8 GetDeviceAddress(); + virtual Type GetType() { return Invalid; }; + virtual Speed GetSpeed() { return LowSpeed; }; //Provide a default: should never be called + virtual int8 GetEndpointAddress() { return m_endpoint; }; protected: Device *m_device; BusManager *m_bus; @@ -262,6 +194,8 @@ public: //Special constructor for default control pipe ControlPipe( BusManager *bus , int8 dev_address , Direction dir , Speed speed , uint8 endpointaddress ); virtual int8 GetDeviceAddress(); + virtual Type GetType() { return Control; }; + virtual Speed GetSpeed() { return m_speed; }; status_t SendRequest( uint8 request_type , uint8 request , uint16 value , uint16 index , uint16 length , void *data , size_t data_len , size_t *actual_len ); @@ -269,9 +203,17 @@ public: size_t data_length , size_t *actual_length , bigtime_t timeout ); private: int8 m_deviceaddress; - bool m_lowspeed; + Speed m_speed; }; +/* + * This is a forward definition of a struct that is defined in the individual + * host controller modules + */ + +struct hostcontroller_priv; + + /* * 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 @@ -281,26 +223,38 @@ private: class Transfer { public: - Transfer( Pipe *pipe ); + Transfer( Pipe *pipe , bool synchronous ); ~Transfer(); void SetRequestData( usb_request_data *data ); void SetBuffer( uint8 *buffer ); void SetBufferLength( size_t length ); void SetActualLength( size_t * ); + void SetCallbackFunction( usb_callback_func callback ); + + void SetHostPrivate( hostcontroller_priv *priv ); + + void WaitForFinish(); + void TransferDone(); + void Finish(); Pipe *GetPipe() { return m_pipe; }; uint8 *GetBuffer() { return m_buffer; }; size_t GetBufferLength() { return m_bufferlength; }; size_t *GetActualLength() { return m_actual_length; }; - usb_request_data *GetRequestData() {return m_request;}; + usb_request_data *GetRequestData() { return m_request; }; + hostcontroller_priv *GetHostPrivate() { return m_hcpriv; }; private: //Data that is related to the transfer - Pipe *m_pipe; - uint8 *m_buffer; - size_t m_bufferlength; - size_t *m_actual_length; - bigtime_t m_timeout; - status_t m_status; + Pipe *m_pipe; + uint8 *m_buffer; + size_t m_bufferlength; + size_t *m_actual_length; + bigtime_t m_timeout; + status_t m_status; + + usb_callback_func m_callback; + sem_id m_sem; + hostcontroller_priv *m_hcpriv; //For control transfers usb_request_data *m_request; diff --git a/src/add-ons/kernel/bus_managers/usb/usbspec_p.h b/src/add-ons/kernel/bus_managers/usb/usbspec_p.h new file mode 100644 index 0000000000..40b94de8ee --- /dev/null +++ b/src/add-ons/kernel/bus_managers/usb/usbspec_p.h @@ -0,0 +1,98 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2003-2005, 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. + +#ifndef USBSPEC_P +#define USBSPEC_P + +#include +#include +#include +#include + +#define USB_MAX_AREAS 8 +struct memory_chunk +{ + addr_t next_item; + addr_t physical; +}; + +/* ++++++++++ +Important data from the USB spec (not interesting for drivers) +++++++++++ */ + +#define POWER_DELAY + +struct usb_request_data +{ + uint8 RequestType; + uint8 Request; + uint16 Value; + uint16 Index; + uint16 Length; +}; + +struct usb_hub_descriptor +{ + uint8 bDescLength; + uint8 bDescriptorType; + uint8 bNbrPorts; + uint16 wHubCharacteristics; + uint8 bPwrOn2PwrGood; + uint8 bHucContrCurrent; + uint8 DeviceRemovable; //Should be variable!!! + uint8 PortPwrCtrlMask; //Deprecated +}; + +#define USB_DESCRIPTOR_HUB 0x29 + +// USB Spec 1.1 page 273 +struct usb_port_status +{ + uint16 status; + uint16 change; +}; + +//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 + +#endif \ No newline at end of file