* Added simplified possibility to schedule UHCI transfers from within KDL.
* Added debugger commands to resolve usb_ids to pipes. * Adjusted the physical memory allocator to be usable in a slimmed down mode when running inside the kernel debugger. * Implemented USB keyboard support for KDL through a kernel debugger add-on. * Added kgetc() and made use of it where previously individual methods were used to ensure that reading characters always goes through the kernel debugger add-ons and the other methods. This has some preconditions to meet though: 1) The keyboard must be in the boot protocol (currently the case but needs to be revisited once we have a full usb_hid). 2) The keyboard must be attached to a UHCI root port (i.e. not use EHCI or OHCI, also not through hubs unless those are USB 1.1). 3) the usb_hid driver has to be opened for this to work. This means that for the time between initializing USB and when usb_hid is opened by the input_server there is no keyboard support. Also note that this has no way of detecting hot-plug, meaning that you can't re-attach your USB keyboard from the hub to the root port once in KDL. On the bright side of things, since this is a non-destructive mechanism it is possible to enter and leave KDL without loosing the USB state. Tested OK in QEMU, not tested on real hardware yet, will see in a few minutes. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29291 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -156,7 +156,8 @@ AddFilesToHaikuImage beos system add-ons kernel busses usb
|
|||||||
: <usb>uhci <usb>ohci <usb>ehci ;
|
: <usb>uhci <usb>ohci <usb>ehci ;
|
||||||
AddFilesToHaikuImage beos system add-ons kernel console : vga_text ;
|
AddFilesToHaikuImage beos system add-ons kernel console : vga_text ;
|
||||||
AddFilesToHaikuImage beos system add-ons kernel debugger
|
AddFilesToHaikuImage beos system add-ons kernel debugger
|
||||||
: $(X86_ONLY)<kdebug>disasm <kdebug>hangman <kdebug>invalidate_on_exit ;
|
: $(X86_ONLY)<kdebug>disasm <kdebug>hangman <kdebug>invalidate_on_exit
|
||||||
|
<kdebug>usb_keyboard ;
|
||||||
AddFilesToHaikuImage beos system add-ons kernel file_systems
|
AddFilesToHaikuImage beos system add-ons kernel file_systems
|
||||||
: $(BEOS_ADD_ONS_FILE_SYSTEMS) ;
|
: $(BEOS_ADD_ONS_FILE_SYSTEMS) ;
|
||||||
AddFilesToHaikuImage beos system add-ons kernel generic
|
AddFilesToHaikuImage beos system add-ons kernel generic
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ extern void debug_set_page_fault_info(addr_t faultAddress, addr_t pc,
|
|||||||
extern debug_page_fault_info* debug_get_page_fault_info();
|
extern debug_page_fault_info* debug_get_page_fault_info();
|
||||||
extern void debug_trap_cpu_in_kdl(bool returnIfHandedOver);
|
extern void debug_trap_cpu_in_kdl(bool returnIfHandedOver);
|
||||||
|
|
||||||
|
extern char kgetc(void);
|
||||||
extern void kputs(const char *string);
|
extern void kputs(const char *string);
|
||||||
extern void kputs_unfiltered(const char *string);
|
extern void kputs_unfiltered(const char *string);
|
||||||
extern void kprintf_unfiltered(const char *format, ...)
|
extern void kprintf_unfiltered(const char *format, ...)
|
||||||
|
|||||||
@@ -66,6 +66,12 @@ PhysicalMemoryAllocator::PhysicalMemoryAllocator(const char *name,
|
|||||||
fManagedMemory = fBlockSize[0] * fArrayLength[0];
|
fManagedMemory = fBlockSize[0] * fArrayLength[0];
|
||||||
|
|
||||||
size_t roundedSize = biggestSize * minCountPerBlock;
|
size_t roundedSize = biggestSize * minCountPerBlock;
|
||||||
|
#if KDEBUG
|
||||||
|
fDebugBase = roundedSize;
|
||||||
|
fDebugChunkSize = 64;
|
||||||
|
fDebugUseMap = 0;
|
||||||
|
roundedSize += sizeof(fDebugUseMap) * 8 * fDebugChunkSize;
|
||||||
|
#endif
|
||||||
roundedSize = (roundedSize + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
|
roundedSize = (roundedSize + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
|
||||||
|
|
||||||
fArea = create_area(fName, &fLogicalBase, B_ANY_KERNEL_ADDRESS,
|
fArea = create_area(fName, &fLogicalBase, B_ANY_KERNEL_ADDRESS,
|
||||||
@@ -122,6 +128,24 @@ status_t
|
|||||||
PhysicalMemoryAllocator::Allocate(size_t size, void **logicalAddress,
|
PhysicalMemoryAllocator::Allocate(size_t size, void **logicalAddress,
|
||||||
void **physicalAddress)
|
void **physicalAddress)
|
||||||
{
|
{
|
||||||
|
#if KDEBUG
|
||||||
|
if (debug_debugger_running()) {
|
||||||
|
for (int32 i = 0; i < 64; i++) {
|
||||||
|
uint64 mask = 1LL << i;
|
||||||
|
if ((fDebugUseMap & mask) == 0) {
|
||||||
|
fDebugUseMap |= mask;
|
||||||
|
*logicalAddress = (void *)((uint8 *)fLogicalBase + fDebugBase
|
||||||
|
+ i * fDebugChunkSize);
|
||||||
|
*physicalAddress = (void *)((uint8 *)fPhysicalBase + fDebugBase
|
||||||
|
+ i * fDebugChunkSize);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (size == 0 || size > fBlockSize[fArrayCount - 1]) {
|
if (size == 0 || size > fBlockSize[fArrayCount - 1]) {
|
||||||
TRACE_ERROR(("PMA: bad value for allocate (%ld bytes)\n", size));
|
TRACE_ERROR(("PMA: bad value for allocate (%ld bytes)\n", size));
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -198,6 +222,15 @@ status_t
|
|||||||
PhysicalMemoryAllocator::Deallocate(size_t size, void *logicalAddress,
|
PhysicalMemoryAllocator::Deallocate(size_t size, void *logicalAddress,
|
||||||
void *physicalAddress)
|
void *physicalAddress)
|
||||||
{
|
{
|
||||||
|
#if KDEBUG
|
||||||
|
if (debug_debugger_running()) {
|
||||||
|
uint32 index = ((uint8 *)logicalAddress - (uint8 *)fLogicalBase
|
||||||
|
- fDebugBase) / fDebugChunkSize;
|
||||||
|
fDebugUseMap &= ~(1LL << index);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (size == 0 || size > fBlockSize[fArrayCount - 1]) {
|
if (size == 0 || size > fBlockSize[fArrayCount - 1]) {
|
||||||
TRACE_ERROR(("PMA: bad value for deallocate (%ld bytes)\n", size));
|
TRACE_ERROR(("PMA: bad value for deallocate (%ld bytes)\n", size));
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|||||||
@@ -57,6 +57,12 @@ private:
|
|||||||
size_t *fArrayLength;
|
size_t *fArrayLength;
|
||||||
size_t *fArrayOffset;
|
size_t *fArrayOffset;
|
||||||
uint8 **fArray;
|
uint8 **fArray;
|
||||||
|
|
||||||
|
#if KDEBUG
|
||||||
|
uint32 fDebugBase;
|
||||||
|
uint32 fDebugChunkSize;
|
||||||
|
uint64 fDebugUseMap;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // !_PHYSICAL_MEMORY_ALLOCATOR_H_
|
#endif // !_PHYSICAL_MEMORY_ALLOCATOR_H_
|
||||||
|
|||||||
@@ -206,6 +206,15 @@ Stack::GetObject(usb_id id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Object *
|
||||||
|
Stack::GetObjectNoLock(usb_id id)
|
||||||
|
{
|
||||||
|
if (id >= fObjectMaxCount)
|
||||||
|
return NULL;
|
||||||
|
return fObjectArray[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
Stack::ExploreThread(void *data)
|
Stack::ExploreThread(void *data)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,6 +16,25 @@
|
|||||||
Stack *gUSBStack = NULL;
|
Stack *gUSBStack = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
debug_get_pipe_for_id(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (gUSBStack == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!is_debug_variable_defined("_usbPipeID"))
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
uint64 id = get_debug_variable("_usbPipeID", 0);
|
||||||
|
Object *object = gUSBStack->GetObjectNoLock((usb_id)id);
|
||||||
|
if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
set_debug_variable("_usbPipe", (uint64)object);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int32
|
static int32
|
||||||
bus_std_ops(int32 op, ...)
|
bus_std_ops(int32 op, ...)
|
||||||
{
|
{
|
||||||
@@ -58,6 +77,9 @@ bus_std_ops(int32 op, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gUSBStack = stack;
|
gUSBStack = stack;
|
||||||
|
add_debugger_command("get_usb_pipe_for_id",
|
||||||
|
&debug_get_pipe_for_id,
|
||||||
|
"Gets the config for a USB pipe");
|
||||||
#ifndef __HAIKU__
|
#ifndef __HAIKU__
|
||||||
// Plain R5 workaround, see comment above.
|
// Plain R5 workaround, see comment above.
|
||||||
shared = create_area("shared usb stack", &address,
|
shared = create_area("shared usb stack", &address,
|
||||||
@@ -73,6 +95,8 @@ bus_std_ops(int32 op, ...)
|
|||||||
TRACE_MODULE("uninit\n");
|
TRACE_MODULE("uninit\n");
|
||||||
delete gUSBStack;
|
delete gUSBStack;
|
||||||
gUSBStack = NULL;
|
gUSBStack = NULL;
|
||||||
|
remove_debugger_command("get_usb_pipe_for_id",
|
||||||
|
&debug_get_pipe_for_id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -126,6 +126,9 @@ public:
|
|||||||
void PutUSBID(usb_id id);
|
void PutUSBID(usb_id id);
|
||||||
Object * GetObject(usb_id id);
|
Object * GetObject(usb_id id);
|
||||||
|
|
||||||
|
// only for the kernel debugger
|
||||||
|
Object * GetObjectNoLock(usb_id id);
|
||||||
|
|
||||||
void AddBusManager(BusManager *bus);
|
void AddBusManager(BusManager *bus);
|
||||||
int32 IndexOfBusManager(BusManager *bus);
|
int32 IndexOfBusManager(BusManager *bus);
|
||||||
BusManager * BusManagerAt(int32 index);
|
BusManager * BusManagerAt(int32 index);
|
||||||
|
|||||||
@@ -19,6 +19,33 @@
|
|||||||
|
|
||||||
pci_module_info *UHCI::sPCIModule = NULL;
|
pci_module_info *UHCI::sPCIModule = NULL;
|
||||||
|
|
||||||
|
static int32 sDebuggerCommandAdded = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
debug_process_transfer(int argc, char **argv)
|
||||||
|
{
|
||||||
|
Pipe *pipe = (Pipe *)get_debug_variable("_usbPipe", 0);
|
||||||
|
if (pipe == NULL)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
// check if we have a UHCI bus at all
|
||||||
|
if (pipe->GetBusManager()->TypeName()[0] != 'u')
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
uint8 *data = (uint8 *)get_debug_variable("_usbTransferData", 0);
|
||||||
|
if (data == NULL)
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
size_t length = (size_t)get_debug_variable("_usbTransferLength", 0);
|
||||||
|
if (length == 0)
|
||||||
|
return 5;
|
||||||
|
|
||||||
|
Transfer transfer(pipe);
|
||||||
|
transfer.SetData(data, length);
|
||||||
|
return ((UHCI *)pipe->GetBusManager())->ProcessDebugTransfer(&transfer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int32
|
static int32
|
||||||
uhci_std_ops(int32 op, ...)
|
uhci_std_ops(int32 op, ...)
|
||||||
@@ -197,9 +224,9 @@ Queue::TerminateByStrayDescriptor()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Queue::AppendTransfer(uhci_qh *transfer)
|
Queue::AppendTransfer(uhci_qh *transfer, bool lock)
|
||||||
{
|
{
|
||||||
if (!Lock())
|
if (lock && !Lock())
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
transfer->link_log = NULL;
|
transfer->link_log = NULL;
|
||||||
@@ -219,15 +246,16 @@ Queue::AppendTransfer(uhci_qh *transfer)
|
|||||||
element->link_phy = transfer->this_phy | QH_NEXT_IS_QH;
|
element->link_phy = transfer->this_phy | QH_NEXT_IS_QH;
|
||||||
}
|
}
|
||||||
|
|
||||||
Unlock();
|
if (lock)
|
||||||
|
Unlock();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Queue::RemoveTransfer(uhci_qh *transfer)
|
Queue::RemoveTransfer(uhci_qh *transfer, bool lock)
|
||||||
{
|
{
|
||||||
if (!Lock())
|
if (lock && !Lock())
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
if (fQueueTop == transfer) {
|
if (fQueueTop == transfer) {
|
||||||
@@ -241,7 +269,8 @@ Queue::RemoveTransfer(uhci_qh *transfer)
|
|||||||
fQueueHead->element_phy = transfer->link_phy;
|
fQueueHead->element_phy = transfer->link_phy;
|
||||||
}
|
}
|
||||||
|
|
||||||
Unlock();
|
if (lock)
|
||||||
|
Unlock();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
} else {
|
} else {
|
||||||
uhci_qh *element = fQueueTop;
|
uhci_qh *element = fQueueTop;
|
||||||
@@ -249,7 +278,8 @@ Queue::RemoveTransfer(uhci_qh *transfer)
|
|||||||
if (element->link_log == transfer) {
|
if (element->link_log == transfer) {
|
||||||
element->link_log = transfer->link_log;
|
element->link_log = transfer->link_log;
|
||||||
element->link_phy = transfer->link_phy;
|
element->link_phy = transfer->link_phy;
|
||||||
Unlock();
|
if (lock)
|
||||||
|
Unlock();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,7 +287,8 @@ Queue::RemoveTransfer(uhci_qh *transfer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Unlock();
|
if (lock)
|
||||||
|
Unlock();
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,8 +405,9 @@ UHCI::UHCI(pci_info *info, Stack *stack)
|
|||||||
// 1: low speed control transfers
|
// 1: low speed control transfers
|
||||||
// 2: full speed control transfers
|
// 2: full speed control transfers
|
||||||
// 3: bulk transfers
|
// 3: bulk transfers
|
||||||
|
// 4: debug queue
|
||||||
// TODO: 4: bandwidth reclamation queue
|
// TODO: 4: bandwidth reclamation queue
|
||||||
fQueueCount = 4;
|
fQueueCount = 5;
|
||||||
fQueues = new(std::nothrow) Queue *[fQueueCount];
|
fQueues = new(std::nothrow) Queue *[fQueueCount];
|
||||||
if (!fQueues) {
|
if (!fQueues) {
|
||||||
delete_area(fFrameArea);
|
delete_area(fFrameArea);
|
||||||
@@ -462,6 +494,12 @@ UHCI::UHCI(pci_info *info, Stack *stack)
|
|||||||
WriteReg16(UHCI_USBINTR, UHCI_USBINTR_CRC | UHCI_USBINTR_IOC
|
WriteReg16(UHCI_USBINTR, UHCI_USBINTR_CRC | UHCI_USBINTR_IOC
|
||||||
| UHCI_USBINTR_SHORT);
|
| UHCI_USBINTR_SHORT);
|
||||||
|
|
||||||
|
if (atomic_add(&sDebuggerCommandAdded, 1) == 0) {
|
||||||
|
add_debugger_command("uhci_process_transfer",
|
||||||
|
&debug_process_transfer,
|
||||||
|
"Processes a USB transfer with the given variables");
|
||||||
|
}
|
||||||
|
|
||||||
TRACE("UHCI host controller driver constructed\n");
|
TRACE("UHCI host controller driver constructed\n");
|
||||||
fInitOK = true;
|
fInitOK = true;
|
||||||
}
|
}
|
||||||
@@ -469,6 +507,11 @@ UHCI::UHCI(pci_info *info, Stack *stack)
|
|||||||
|
|
||||||
UHCI::~UHCI()
|
UHCI::~UHCI()
|
||||||
{
|
{
|
||||||
|
if (atomic_add(&sDebuggerCommandAdded, -1) == 1) {
|
||||||
|
remove_debugger_command("uhci_process_transfer",
|
||||||
|
&debug_process_transfer);
|
||||||
|
}
|
||||||
|
|
||||||
int32 result = 0;
|
int32 result = 0;
|
||||||
fStopFinishThread = true;
|
fStopFinishThread = true;
|
||||||
fStopFinishIsochronousThread = true;
|
fStopFinishIsochronousThread = true;
|
||||||
@@ -607,6 +650,77 @@ UHCI::SubmitTransfer(Transfer *transfer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
UHCI::ProcessDebugTransfer(Transfer *transfer)
|
||||||
|
{
|
||||||
|
uhci_td *firstDescriptor = NULL;
|
||||||
|
uhci_qh *transferQueue = NULL;
|
||||||
|
status_t result = CreateFilledTransfer(transfer, &firstDescriptor,
|
||||||
|
&transferQueue);
|
||||||
|
if (result < B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
fQueues[UHCI_DEBUG_QUEUE]->AppendTransfer(transferQueue, false);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
bool transferOK = false;
|
||||||
|
bool transferError = false;
|
||||||
|
uhci_td *descriptor = firstDescriptor;
|
||||||
|
|
||||||
|
while (descriptor) {
|
||||||
|
uint32 status = descriptor->status;
|
||||||
|
if (status & TD_STATUS_ACTIVE)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (status & TD_ERROR_MASK) {
|
||||||
|
transferError = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((descriptor->link_phy & TD_TERMINATE)
|
||||||
|
|| (descriptor->status & TD_STATUS_ACTLEN_MASK)
|
||||||
|
< (descriptor->token >> TD_TOKEN_MAXLEN_SHIFT)) {
|
||||||
|
transferOK = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptor = (uhci_td *)descriptor->link_log;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!transferOK && !transferError) {
|
||||||
|
spin(200);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transferOK) {
|
||||||
|
size_t actualLength = 0;
|
||||||
|
uint8 lastDataToggle = 0;
|
||||||
|
if (transfer->TransferPipe()->Direction() == Pipe::In) {
|
||||||
|
// data to read out
|
||||||
|
iovec *vector = transfer->Vector();
|
||||||
|
size_t vectorCount = transfer->VectorCount();
|
||||||
|
|
||||||
|
actualLength = ReadDescriptorChain(firstDescriptor,
|
||||||
|
vector, vectorCount, &lastDataToggle);
|
||||||
|
} else {
|
||||||
|
// read the actual length that was sent
|
||||||
|
actualLength = ReadActualLength(firstDescriptor,
|
||||||
|
&lastDataToggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
transfer->TransferPipe()->SetDataToggle(lastDataToggle == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fQueues[UHCI_DEBUG_QUEUE]->RemoveTransfer(transferQueue, false);
|
||||||
|
FreeDescriptorChain(firstDescriptor);
|
||||||
|
FreeTransferQueue(transferQueue);
|
||||||
|
return transferOK ? B_OK : B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
UHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
|
UHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#define UHCI_FULL_SPEED_CONTROL_QUEUE 2
|
#define UHCI_FULL_SPEED_CONTROL_QUEUE 2
|
||||||
#define UHCI_BULK_QUEUE 3
|
#define UHCI_BULK_QUEUE 3
|
||||||
#define UHCI_BANDWIDTH_RECLAMATION_QUEUE 4
|
#define UHCI_BANDWIDTH_RECLAMATION_QUEUE 4
|
||||||
|
#define UHCI_DEBUG_QUEUE 4
|
||||||
|
|
||||||
struct pci_info;
|
struct pci_info;
|
||||||
struct pci_module_info;
|
struct pci_module_info;
|
||||||
@@ -39,8 +40,10 @@ public:
|
|||||||
status_t LinkTo(Queue *other);
|
status_t LinkTo(Queue *other);
|
||||||
status_t TerminateByStrayDescriptor();
|
status_t TerminateByStrayDescriptor();
|
||||||
|
|
||||||
status_t AppendTransfer(uhci_qh *transfer);
|
status_t AppendTransfer(uhci_qh *transfer,
|
||||||
status_t RemoveTransfer(uhci_qh *transfer);
|
bool lock = true);
|
||||||
|
status_t RemoveTransfer(uhci_qh *transfer,
|
||||||
|
bool lock = true);
|
||||||
|
|
||||||
addr_t PhysicalAddress();
|
addr_t PhysicalAddress();
|
||||||
|
|
||||||
@@ -94,6 +97,7 @@ public:
|
|||||||
|
|
||||||
status_t Start();
|
status_t Start();
|
||||||
virtual status_t SubmitTransfer(Transfer *transfer);
|
virtual status_t SubmitTransfer(Transfer *transfer);
|
||||||
|
status_t ProcessDebugTransfer(Transfer *transfer);
|
||||||
virtual status_t CancelQueuedTransfers(Pipe *pipe, bool force);
|
virtual status_t CancelQueuedTransfers(Pipe *pipe, bool force);
|
||||||
status_t CancelQueuedIsochronousTransfers(Pipe *pipe, bool force);
|
status_t CancelQueuedIsochronousTransfers(Pipe *pipe, bool force);
|
||||||
status_t SubmitRequest(Transfer *transfer);
|
status_t SubmitRequest(Transfer *transfer);
|
||||||
|
|||||||
@@ -7,3 +7,4 @@ SubInclude HAIKU_TOP src add-ons kernel debugger disasm ;
|
|||||||
SubInclude HAIKU_TOP src add-ons kernel debugger hangman ;
|
SubInclude HAIKU_TOP src add-ons kernel debugger hangman ;
|
||||||
SubInclude HAIKU_TOP src add-ons kernel debugger invalidate_on_exit ;
|
SubInclude HAIKU_TOP src add-ons kernel debugger invalidate_on_exit ;
|
||||||
SubInclude HAIKU_TOP src add-ons kernel debugger laplinkll ;
|
SubInclude HAIKU_TOP src add-ons kernel debugger laplinkll ;
|
||||||
|
SubInclude HAIKU_TOP src add-ons kernel debugger usb_keyboard ;
|
||||||
|
|||||||
@@ -10,11 +10,26 @@
|
|||||||
#include "KeyboardDevice.h"
|
#include "KeyboardDevice.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <usb/USB_hid.h>
|
#include <usb/USB_hid.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
// input server private for raw_key_info, KB_READ, etc...
|
// input server private for raw_key_info, KB_READ, etc...
|
||||||
#include "kb_mouse_driver.h"
|
#include "kb_mouse_driver.h"
|
||||||
|
|
||||||
|
|
||||||
|
static usb_id sDebugKeyboardPipe = 0;
|
||||||
|
static size_t sDebugKeyboardReportSize = 0;
|
||||||
|
static int32 sDebuggerCommandAdded = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
debug_get_keyboard_config(int argc, char **argv)
|
||||||
|
{
|
||||||
|
set_debug_variable("_usbPipeID", (uint64)sDebugKeyboardPipe);
|
||||||
|
set_debug_variable("_usbReportSize", (uint64)sDebugKeyboardReportSize);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
KeyboardDevice::KeyboardDevice(usb_device device, usb_pipe interruptPipe,
|
KeyboardDevice::KeyboardDevice(usb_device device, usb_pipe interruptPipe,
|
||||||
size_t interfaceIndex, report_insn *instructions, size_t instructionCount,
|
size_t interfaceIndex, report_insn *instructions, size_t instructionCount,
|
||||||
size_t totalReportSize)
|
size_t totalReportSize)
|
||||||
@@ -34,12 +49,23 @@ KeyboardDevice::KeyboardDevice(usb_device device, usb_pipe interruptPipe,
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetBaseName("input/keyboard/usb/");
|
SetBaseName("input/keyboard/usb/");
|
||||||
|
|
||||||
|
if (atomic_add(&sDebuggerCommandAdded, 1) == 0) {
|
||||||
|
add_debugger_command("get_usb_keyboard_config",
|
||||||
|
&debug_get_keyboard_config,
|
||||||
|
"Gets the required config of the USB keyboard");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
KeyboardDevice::~KeyboardDevice()
|
KeyboardDevice::~KeyboardDevice()
|
||||||
{
|
{
|
||||||
free(fLastTransferBuffer);
|
free(fLastTransferBuffer);
|
||||||
|
|
||||||
|
if (atomic_add(&sDebuggerCommandAdded, -1) == 1) {
|
||||||
|
remove_debugger_command("get_usb_keyboard_config",
|
||||||
|
&debug_get_keyboard_config);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -410,9 +436,13 @@ KeyboardDevice::_InterpretBuffer()
|
|||||||
key = KEY_Break;
|
key = KEY_Break;
|
||||||
else if (key == 0xe && (current[0] & 1))
|
else if (key == 0xe && (current[0] & 1))
|
||||||
key = KEY_SysRq;
|
key = KEY_SysRq;
|
||||||
#if 0
|
#if 1
|
||||||
else if (keyDown && key == 0x0d) // ToDo: remove again
|
else if (keyDown && key == 0x0d) {
|
||||||
|
// ToDo: remove again
|
||||||
|
sDebugKeyboardPipe = fInterruptPipe;
|
||||||
|
sDebugKeyboardReportSize = fTotalReportSize;
|
||||||
panic("keyboard requested halt.\n");
|
panic("keyboard requested halt.\n");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
else if (key == 0) {
|
else if (key == 0) {
|
||||||
// unmapped key
|
// unmapped key
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
#include <frame_buffer_console.h>
|
#include <frame_buffer_console.h>
|
||||||
#include <console.h>
|
#include <console.h>
|
||||||
|
#include <debug.h>
|
||||||
#include <arch/debug_console.h>
|
#include <arch/debug_console.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -139,7 +140,7 @@ next_line(void)
|
|||||||
text[i], sScreen.boot_debug_output ? 0x6f : 0xf6);
|
text[i], sScreen.boot_debug_output ? 0x6f : 0xf6);
|
||||||
}
|
}
|
||||||
|
|
||||||
char c = blue_screen_getchar();
|
char c = kgetc();
|
||||||
if (c == 's') {
|
if (c == 's') {
|
||||||
sScreen.ignore_output = true;
|
sScreen.ignore_output = true;
|
||||||
} else if (c == 'q' && in_command_invocation()) {
|
} else if (c == 'q' && in_command_invocation()) {
|
||||||
|
|||||||
@@ -408,27 +408,8 @@ read_line(char* buffer, int32 maxLength,
|
|||||||
bool done = false;
|
bool done = false;
|
||||||
char c = 0;
|
char c = 0;
|
||||||
|
|
||||||
char (*readChar)(void);
|
|
||||||
if (sBlueScreenOutput)
|
|
||||||
readChar = blue_screen_getchar;
|
|
||||||
else
|
|
||||||
readChar = arch_debug_serial_getchar;
|
|
||||||
|
|
||||||
while (!done) {
|
while (!done) {
|
||||||
bool hasChar = false;
|
c = kgetc();
|
||||||
for (uint32 i = 0; i < kMaxDebuggerModules; i++) {
|
|
||||||
if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_getchar) {
|
|
||||||
int getChar = sDebuggerModules[i]->debugger_getchar();
|
|
||||||
if (getChar >= 0) {
|
|
||||||
hasChar = true;
|
|
||||||
c = (char)getChar;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasChar)
|
|
||||||
c = readChar();
|
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '\n':
|
case '\n':
|
||||||
@@ -487,12 +468,12 @@ read_line(char* buffer, int32 maxLength,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 27: // escape sequence
|
case 27: // escape sequence
|
||||||
c = readChar();
|
c = kgetc();
|
||||||
if (c != '[') {
|
if (c != '[') {
|
||||||
// ignore broken escape sequence
|
// ignore broken escape sequence
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
c = readChar();
|
c = kgetc();
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'C': // right arrow
|
case 'C': // right arrow
|
||||||
if (position < length) {
|
if (position < length) {
|
||||||
@@ -548,7 +529,7 @@ read_line(char* buffer, int32 maxLength,
|
|||||||
case '5': // if "5~", it's PAGE UP
|
case '5': // if "5~", it's PAGE UP
|
||||||
case '6': // if "6~", it's PAGE DOWN
|
case '6': // if "6~", it's PAGE DOWN
|
||||||
{
|
{
|
||||||
if (readChar() != '~')
|
if (kgetc() != '~')
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// PAGE UP: search backward, PAGE DOWN: forward
|
// PAGE UP: search backward, PAGE DOWN: forward
|
||||||
@@ -603,7 +584,7 @@ read_line(char* buffer, int32 maxLength,
|
|||||||
}
|
}
|
||||||
case '3': // if "3~", it's DEL
|
case '3': // if "3~", it's DEL
|
||||||
{
|
{
|
||||||
if (readChar() != '~')
|
if (kgetc() != '~')
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (position < length)
|
if (position < length)
|
||||||
@@ -649,6 +630,25 @@ read_line(char* buffer, int32 maxLength,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char
|
||||||
|
kgetc(void)
|
||||||
|
{
|
||||||
|
// give the kernel debugger modules a chance first
|
||||||
|
for (uint32 i = 0; i < kMaxDebuggerModules; i++) {
|
||||||
|
if (sDebuggerModules[i] && sDebuggerModules[i]->debugger_getchar) {
|
||||||
|
int getChar = sDebuggerModules[i]->debugger_getchar();
|
||||||
|
if (getChar >= 0)
|
||||||
|
return (char)getChar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sBlueScreenOutput)
|
||||||
|
return blue_screen_getchar();
|
||||||
|
|
||||||
|
return arch_debug_serial_getchar();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
kgets(char* buffer, int length)
|
kgets(char* buffer, int length)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user