* Cleaned up / applied style to the BusManager class
* Fixed some copy&paste errors I introduced earlier * Removed the "one UHCI bus only" limit * Other fixes The hub now sees when a new device is connected but failes when getting its descriptor. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17611 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
76e69839f7
commit
26f34d1c06
@ -1,186 +1,200 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2003-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.
|
||||
/*
|
||||
* Copyright 2003-2006, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Niels S. Reedijk
|
||||
*/
|
||||
|
||||
#include "usb_p.h"
|
||||
|
||||
|
||||
/* +++++++++
|
||||
This is the 'main' function of the explore thread, which keeps track of
|
||||
the hub statuses.
|
||||
+++++++++ */
|
||||
int32 usb_explore_thread( void *data )
|
||||
{
|
||||
Hub *roothub = (Hub *)data;
|
||||
|
||||
if ( roothub == 0 )
|
||||
return B_ERROR;
|
||||
|
||||
while ( true )
|
||||
{
|
||||
//Go to the hubs
|
||||
roothub->Explore();
|
||||
snooze(1000000); //Wait one second before continueing
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
#define TRACE_BUSMANAGER
|
||||
#ifdef TRACE_BUSMANAGER
|
||||
#define TRACE(x) dprintf(x)
|
||||
#else
|
||||
#define TRACE(x) /* nothing */
|
||||
#endif
|
||||
|
||||
|
||||
BusManager::BusManager()
|
||||
{
|
||||
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 , 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 );
|
||||
|
||||
// Clear the 'explore thread'
|
||||
m_explore_thread = 0;
|
||||
fInitOK = false;
|
||||
fRootHub = NULL;
|
||||
|
||||
m_initok = true;
|
||||
// Set up the semaphore
|
||||
fLock = create_sem(1, "bus manager lock");
|
||||
if (fLock < B_OK)
|
||||
return;
|
||||
|
||||
set_sem_owner(B_SYSTEM_TEAM, fLock);
|
||||
|
||||
// Clear the device map
|
||||
for (int32 i = 0; i < 128; i++)
|
||||
fDeviceMap[i] = false;
|
||||
|
||||
// Set up the default pipes
|
||||
fDefaultPipe = new ControlPipe(this, 0, Pipe::Default, Pipe::NormalSpeed, 0);
|
||||
fDefaultPipeLowSpeed = new ControlPipe(this, 0, Pipe::Default,
|
||||
Pipe::LowSpeed, 0);
|
||||
|
||||
fExploreThread = -1;
|
||||
fInitOK = true;
|
||||
}
|
||||
|
||||
|
||||
BusManager::~BusManager()
|
||||
{
|
||||
}
|
||||
|
||||
status_t BusManager::InitCheck()
|
||||
|
||||
status_t
|
||||
BusManager::InitCheck()
|
||||
{
|
||||
if ( m_initok == true )
|
||||
if (fInitOK)
|
||||
return B_OK;
|
||||
else
|
||||
return B_ERROR;
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
Device * BusManager::AllocateNewDevice( Device *parent , bool lowspeed )
|
||||
|
||||
/*
|
||||
This is the 'main' function of the explore thread, which keeps track of
|
||||
the hub states.
|
||||
*/
|
||||
int32
|
||||
BusManager::ExploreThread(void *data)
|
||||
{
|
||||
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;
|
||||
Hub *rootHub = (Hub *)data;
|
||||
if (!rootHub)
|
||||
return B_ERROR;
|
||||
|
||||
while (true) {
|
||||
rootHub->Explore();
|
||||
snooze(1000000);
|
||||
}
|
||||
|
||||
|
||||
//2. Set the address of the device USB 1.1 spec p202 (bepdf)
|
||||
retval = m_defaultPipe->SendRequest( 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;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
Device *
|
||||
BusManager::AllocateNewDevice(Device *parent, bool lowSpeed)
|
||||
{
|
||||
// Check if there is a free entry in the device map (for the device number)
|
||||
int8 deviceNum = AllocateAddress();
|
||||
if (deviceNum < 0) {
|
||||
TRACE(("usb BusManager::AllocateNewDevice(): could not get a new address\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Create a temporary pipe
|
||||
ControlPipe pipe( this , devicenum , Pipe::Default , Pipe::LowSpeed , 0 );
|
||||
|
||||
//3. Get the device descriptor
|
||||
|
||||
// Set the address of the device USB 1.1 spec p202
|
||||
status_t result = fDefaultPipeLowSpeed->SendRequest(
|
||||
USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_STANDARD, // type
|
||||
USB_REQUEST_SET_ADDRESS, // request
|
||||
deviceNum, // value
|
||||
0, // index
|
||||
0, // length
|
||||
NULL, // buffer
|
||||
0, // buffer length
|
||||
NULL); // actual length
|
||||
|
||||
if (result < B_OK) {
|
||||
TRACE(("usb BusManager::AllocateNewDevice(): error while setting device address\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create a temporary pipe
|
||||
ControlPipe pipe(this, deviceNum, Pipe::Default, Pipe::LowSpeed, 0);
|
||||
|
||||
// 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;
|
||||
|
||||
pipe.SendRequest( 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;
|
||||
// there too
|
||||
|
||||
size_t actualLength = 0;
|
||||
usb_device_descriptor deviceDescriptor;
|
||||
|
||||
pipe.SendRequest(
|
||||
USB_REQTYPE_DEVICE_IN | USB_REQTYPE_STANDARD, // type
|
||||
USB_REQUEST_GET_DESCRIPTOR, // request
|
||||
USB_DESCRIPTOR_DEVICE << 8, // value
|
||||
0, // index
|
||||
8, // length
|
||||
(void *)&deviceDescriptor, // buffer
|
||||
8, // buffer length
|
||||
&actualLength); // actual length
|
||||
|
||||
if (actualLength != 8) {
|
||||
TRACE(("usb BusManager::AllocateNewDevice(): error while getting the device descriptor\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//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 , lowspeed );
|
||||
if ( parent == 0 ) //root hub!!
|
||||
m_roothub = ret;
|
||||
return 0;
|
||||
// Create a new instance based on the type (Hub or Device)
|
||||
if (deviceDescriptor.device_class == 0x09) {
|
||||
TRACE(("usb BusManager::AllocateNewDevice(): creating new hub\n"));
|
||||
Device *ret = new Hub(this, parent, deviceDescriptor, deviceNum,
|
||||
lowSpeed);
|
||||
|
||||
if (parent == NULL) {
|
||||
// root hub
|
||||
fRootHub = ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
dprintf( "usb Busmanager [new device]: New normal device\n" );
|
||||
return new Device( this , parent , device_descriptor , devicenum , lowspeed);
|
||||
|
||||
TRACE(("usb BusManager::AllocateNewDevice(): creating new device\n"));
|
||||
return new Device(this, parent, deviceDescriptor, deviceNum, lowSpeed);
|
||||
}
|
||||
|
||||
int8 BusManager::AllocateAddress()
|
||||
|
||||
int8
|
||||
BusManager::AllocateAddress()
|
||||
{
|
||||
acquire_sem_etc( m_lock , 1 , B_CAN_INTERRUPT , 0 );
|
||||
int8 devicenum = -1;
|
||||
for( int i = 1 ; i < 128 ; i++ )
|
||||
{
|
||||
if ( m_devicemap[i] == false )
|
||||
{
|
||||
devicenum = i;
|
||||
m_devicemap[i] = true;
|
||||
acquire_sem_etc(fLock, 1, B_CAN_INTERRUPT, 0);
|
||||
|
||||
int8 deviceNum = -1;
|
||||
for (int32 i = 1; i < 128; i++) {
|
||||
if (fDeviceMap[i] == false) {
|
||||
deviceNum = i;
|
||||
fDeviceMap[i] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
release_sem( m_lock );
|
||||
return devicenum;
|
||||
|
||||
release_sem(fLock);
|
||||
return deviceNum;
|
||||
}
|
||||
|
||||
status_t BusManager::Start()
|
||||
|
||||
status_t
|
||||
BusManager::Start()
|
||||
{
|
||||
dprintf( "USB: BusManager::Start()\n" );
|
||||
if ( InitCheck() != B_OK )
|
||||
TRACE(("usb BusManager::Start()\n"));
|
||||
if (InitCheck() != B_OK)
|
||||
return InitCheck();
|
||||
|
||||
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 );
|
||||
|
||||
if (fExploreThread < 0) {
|
||||
fExploreThread = spawn_kernel_thread(ExploreThread,
|
||||
"usb busmanager explore", B_LOW_PRIORITY, (void *)fRootHub);
|
||||
}
|
||||
|
||||
return resume_thread(fExploreThread);
|
||||
}
|
||||
|
||||
status_t BusManager::SubmitTransfer( Transfer *t )
|
||||
|
||||
status_t
|
||||
BusManager::Stop()
|
||||
{
|
||||
// ToDo: implement (should end the explore thread)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BusManager::SubmitTransfer(Transfer *transfer)
|
||||
{
|
||||
// virtual function to be overridden
|
||||
return B_ERROR;
|
||||
};
|
||||
}
|
||||
|
@ -128,37 +128,42 @@ private:
|
||||
* after a host controller gives positive feedback on whether the hardware
|
||||
* is found.
|
||||
*/
|
||||
class BusManager
|
||||
{
|
||||
friend class Device;
|
||||
friend class ControlPipe;
|
||||
class BusManager {
|
||||
public:
|
||||
BusManager();
|
||||
virtual ~BusManager();
|
||||
|
||||
virtual status_t InitCheck();
|
||||
|
||||
Device *AllocateNewDevice( Device *parent , bool speed );
|
||||
int8 AllocateAddress();
|
||||
|
||||
virtual status_t Start();
|
||||
// virtual status_t Stop();
|
||||
virtual status_t SubmitTransfer( Transfer *t );
|
||||
protected:
|
||||
void SetRootHub( Hub *hub ) { m_roothub = hub; };
|
||||
Device* GetRootHub() { return m_roothub; };
|
||||
bool m_initok;
|
||||
private:
|
||||
bool m_devicemap[128];
|
||||
ControlPipe *m_defaultLowSpeedPipe;
|
||||
ControlPipe *m_defaultPipe;
|
||||
sem_id m_lock;
|
||||
Device *m_roothub;
|
||||
thread_id m_explore_thread;
|
||||
};
|
||||
BusManager();
|
||||
virtual ~BusManager();
|
||||
|
||||
// Located in the BusManager.cpp
|
||||
int32 usb_explore_thread( void *data );
|
||||
virtual status_t InitCheck();
|
||||
|
||||
Device *AllocateNewDevice(Device *parent,
|
||||
bool lowSpeed);
|
||||
|
||||
int8 AllocateAddress();
|
||||
|
||||
virtual status_t Start();
|
||||
virtual status_t Stop();
|
||||
|
||||
virtual status_t SubmitTransfer(Transfer *transfer);
|
||||
|
||||
protected:
|
||||
void SetRootHub(Hub *hub) { fRootHub = hub; };
|
||||
Device *GetRootHub() { return fRootHub; };
|
||||
|
||||
bool fInitOK;
|
||||
|
||||
private:
|
||||
friend class Device;
|
||||
friend class ControlPipe;
|
||||
|
||||
static int32 ExploreThread(void *data);
|
||||
|
||||
sem_id fLock;
|
||||
bool fDeviceMap[128];
|
||||
ControlPipe *fDefaultPipe;
|
||||
ControlPipe *fDefaultPipeLowSpeed;
|
||||
Device *fRootHub;
|
||||
thread_id fExploreThread;
|
||||
};
|
||||
|
||||
/*
|
||||
* The Pipe class is the communication management between the hardware and\
|
||||
|
@ -99,7 +99,7 @@ UHCI::UHCI(pci_info *info, Stack *stack)
|
||||
GlobalReset();
|
||||
if (Reset() < B_OK) {
|
||||
TRACE(("usb_uhci: host failed to reset\n"));
|
||||
m_initok = false;
|
||||
fInitOK = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ UHCI::UHCI(pci_info *info, Stack *stack)
|
||||
|
||||
if (fFrameArea < B_OK) {
|
||||
TRACE(("usb_uhci: unable to create an area for the frame pointer list\n"));
|
||||
m_initok = false;
|
||||
fInitOK = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -126,7 +126,7 @@ UHCI::UHCI(pci_info *info, Stack *stack)
|
||||
if (fStack->AllocateChunk((void **)&strayDescriptor, &physicalAddress, 32) != B_OK) {
|
||||
TRACE(("usb_uhci: failed to allocate a stray transfer descriptor\n"));
|
||||
delete_area(fFrameArea);
|
||||
m_initok = false;
|
||||
fInitOK = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -151,7 +151,7 @@ UHCI::UHCI(pci_info *info, Stack *stack)
|
||||
&physicalAddress, 32) != B_OK) {
|
||||
TRACE(("usb_uhci: failed allocation of skeleton queue head %i, aborting\n", i));
|
||||
delete_area(fFrameArea);
|
||||
m_initok = false;
|
||||
fInitOK = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -246,22 +246,13 @@ UHCI::Start()
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
TRACE(("usb_uhci: controller is started. status: %u curframe: %u\n",
|
||||
ReadReg16(UHCI_USBSTS), ReadReg16(UHCI_FRNUM)));
|
||||
return BusManager::Start();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
UHCI::SetupRootHub()
|
||||
{
|
||||
TRACE(("usb_uhci: setting up root hub\n"));
|
||||
|
||||
fRootHubAddress = AllocateAddress();
|
||||
fRootHub = new UHCIRootHub(this, fRootHubAddress);
|
||||
SetRootHub(fRootHub);
|
||||
|
||||
return B_OK;
|
||||
TRACE(("usb_uhci: controller is started. status: %u curframe: %u\n",
|
||||
ReadReg16(UHCI_USBSTS), ReadReg16(UHCI_FRNUM)));
|
||||
return BusManager::Start();
|
||||
}
|
||||
|
||||
|
||||
@ -377,10 +368,6 @@ UHCI::InsertControl(Transfer *transfer)
|
||||
TRACE(("usb_uhci: InsertControl() frnum %u, usbsts reg %u\n",
|
||||
ReadReg16(UHCI_FRNUM), ReadReg16(UHCI_USBSTS)));
|
||||
|
||||
// HACK: this one is to prevent rogue transfers from happening
|
||||
if (!transfer->GetBuffer())
|
||||
return B_ERROR;
|
||||
|
||||
// Please note that any data structures must be aligned on a 16 byte boundary
|
||||
// Also, due to the strange ways of C++' void* handling, this code is much messier
|
||||
// than it actually should be. Forgive me. Or blame the compiler.
|
||||
@ -423,7 +410,8 @@ UHCI::InsertControl(Transfer *transfer)
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(transferDescriptor->buffer_log, transfer->GetRequestData(), sizeof(usb_request_data));
|
||||
memcpy(transferDescriptor->buffer_log, transfer->GetRequestData(),
|
||||
sizeof(usb_request_data));
|
||||
|
||||
// Link this to the queue head
|
||||
topQueueHead->element_phy = transferDescriptor->this_phy;
|
||||
@ -470,11 +458,11 @@ UHCI::InsertControl(Transfer *transfer)
|
||||
transfer->GetHostPrivate()->lasttd = statusDescriptor;
|
||||
fTransfers.PushBack(transfer);
|
||||
|
||||
// Secondly, append the qh to the control list
|
||||
// Secondly, append the queue head to the control list
|
||||
if (fQueueHeadControl->element_phy & QH_TERMINATE) {
|
||||
// the control queue is empty, make this the first element
|
||||
fQueueHeadControl->element_phy = topQueueHead->this_phy;
|
||||
fQueueHeadControl->link_log = (void *)topQueueHead;
|
||||
fQueueHeadControl->link_log = topQueueHead;
|
||||
TRACE(("usb_uhci: first transfer in queue\n"));
|
||||
} else {
|
||||
// there are control transfers linked, append to the queue
|
||||
@ -483,7 +471,7 @@ UHCI::InsertControl(Transfer *transfer)
|
||||
queueHead = (uhci_qh *)queueHead->link_log;
|
||||
|
||||
queueHead->link_phy = topQueueHead->this_phy;
|
||||
queueHead->link_log = (void *)topQueueHead;
|
||||
queueHead->link_log = topQueueHead;
|
||||
TRACE(("usb_uhci: appended transfer to queue\n"));
|
||||
}
|
||||
|
||||
@ -510,7 +498,6 @@ UHCI::AddTo(Stack &stack)
|
||||
|
||||
TRACE(("usb_uhci: AddTo(): setting up hardware\n"));
|
||||
|
||||
// TODO: in the future we might want to support multiple host controllers.
|
||||
bool found = false;
|
||||
pci_info *item = new pci_info;
|
||||
for (int32 i = 0; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
|
||||
@ -532,10 +519,8 @@ UHCI::AddTo(Stack &stack)
|
||||
}
|
||||
|
||||
bus->Start();
|
||||
bus->SetupRootHub();
|
||||
stack.AddBusManager(bus);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@ public:
|
||||
UHCI(pci_info *info, Stack *stack);
|
||||
|
||||
status_t Start();
|
||||
status_t SetupRootHub();
|
||||
status_t SubmitTransfer(Transfer *transfer);
|
||||
|
||||
static bool AddTo(Stack &stack);
|
||||
|
@ -77,7 +77,7 @@ usb_hub_descriptor uhci_hubd =
|
||||
{
|
||||
0x09, //Including deprecated powerctrlmask
|
||||
USB_DESCRIPTOR_HUB,
|
||||
1, //Number of ports
|
||||
2, //Number of ports
|
||||
0x02 | 0x01, //Hub characteristics FIXME
|
||||
50, //Power on to power good
|
||||
0, // Current
|
||||
@ -228,25 +228,25 @@ UHCIRootHub::SubmitTransfer(Transfer *transfer)
|
||||
void
|
||||
UHCIRootHub::UpdatePortStatus()
|
||||
{
|
||||
for (int32 i = 0; i < 2; i++) {
|
||||
for (int32 i = 0; i < uhci_hubd.bNbrPorts; i++) {
|
||||
uint16 newStatus = 0;
|
||||
uint16 newChange = 0;
|
||||
|
||||
uint16 portStatus = UHCI::sPCIModule->read_io_16(fUHCI->fRegisterBase + UHCI_PORTSC1 + i * 2);
|
||||
TRACE(("usb_uhci_roothub: port: %d status: 0x%04x\n", UHCI_PORTSC1 + i * 2, portStatus));
|
||||
TRACE(("usb_uhci_roothub: port: %d status: 0x%04x\n", i, portStatus));
|
||||
|
||||
// Set all individual bits
|
||||
if (portStatus & UHCI_PORTSC_CURSTAT)
|
||||
newStatus |= PORT_STATUS_CONNECTION;
|
||||
|
||||
if (portStatus & UHCI_PORTSC_STATCHA)
|
||||
newStatus |= PORT_STATUS_CONNECTION;
|
||||
newChange |= PORT_STATUS_CONNECTION;
|
||||
|
||||
if (portStatus & UHCI_PORTSC_ENABLED)
|
||||
newStatus |= PORT_STATUS_ENABLE;
|
||||
|
||||
if (portStatus & UHCI_PORTSC_ENABCHA)
|
||||
newStatus |= PORT_STATUS_ENABLE;
|
||||
newChange |= PORT_STATUS_ENABLE;
|
||||
|
||||
// TODO: work out suspended/resume
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user