diff --git a/headers/os/drivers/USB2.h b/headers/os/drivers/USB2.h index 2350fda09e..832b33360f 100644 --- a/headers/os/drivers/USB2.h +++ b/headers/os/drivers/USB2.h @@ -73,7 +73,7 @@ struct usb_configuration_info { usb_interface_list *interface; }; -typedef void (*usb_callback_func)(void *cookie, uint32 status, void *data, +typedef void (*usb_callback_func)(void *cookie, status_t status, void *data, size_t actualLength); @@ -203,24 +203,6 @@ struct usb_module_info { }; -/* - * These status are passed to the usb_callback_func callbacks. They indicate - * the status of a completed queued transfer. Multiple of these status codes - * may be combined. For example it is possible to have: - * B_USB_STATUS_DEVICE_TIMEOUT | B_USB_STATUS_DEVICE_STALLED - * This indicates that a timeout happened and that the used pipe is now - * stalled. - */ -#define B_USB_STATUS_SUCCESS 0x0000 -#define B_USB_STATUS_DEVICE_CRC_ERROR 0x0002 -#define B_USB_STATUS_DEVICE_TIMEOUT 0x0004 -#define B_USB_STATUS_DEVICE_STALLED 0x0008 -#define B_USB_STATUS_IRP_CANCELLED_BY_REQUEST 0x0010 -#define B_USB_STATUS_DRIVER_INTERNAL_ERROR 0x0020 -#define B_USB_STATUS_ADAPTER_HARDWARE_ERROR 0x0040 -#define B_USB_STATUS_ISOCH_IRP_ABORTED 0x0080 - - #define B_USB_MODULE_NAME "bus_managers/usb/v2" diff --git a/headers/os/drivers/USB3.h b/headers/os/drivers/USB3.h index 43730119fb..b4ca8b5d04 100644 --- a/headers/os/drivers/USB3.h +++ b/headers/os/drivers/USB3.h @@ -79,7 +79,7 @@ typedef struct { status_t status; } usb_iso_packet_descriptor; -typedef void (*usb_callback_func)(void *cookie, uint32 status, void *data, +typedef void (*usb_callback_func)(void *cookie, status_t status, void *data, size_t actualLength); @@ -214,24 +214,6 @@ struct usb_module_info { }; -/* - * These status are passed to the usb_callback_func callbacks. They indicate - * the status of a completed queued transfer. Multiple of these status codes - * may be combined. For example it is possible to have: - * B_USB_STATUS_DEVICE_TIMEOUT | B_USB_STATUS_DEVICE_STALLED - * This indicates that a timeout happened and that the used pipe is now - * stalled. - */ -#define B_USB_STATUS_SUCCESS 0x0000 -#define B_USB_STATUS_DEVICE_CRC_ERROR 0x0002 -#define B_USB_STATUS_DEVICE_TIMEOUT 0x0004 -#define B_USB_STATUS_DEVICE_STALLED 0x0008 -#define B_USB_STATUS_IRP_CANCELLED_BY_REQUEST 0x0010 -#define B_USB_STATUS_DRIVER_INTERNAL_ERROR 0x0020 -#define B_USB_STATUS_ADAPTER_HARDWARE_ERROR 0x0040 -#define B_USB_STATUS_ISOCH_IRP_ABORTED 0x0080 - - #define B_USB_MODULE_NAME "bus_managers/usb/v3" diff --git a/src/add-ons/kernel/bus_managers/usb/BeOSCompatibility.h b/src/add-ons/kernel/bus_managers/usb/BeOSCompatibility.h index 6b46f17f9f..4cb76bff63 100644 --- a/src/add-ons/kernel/bus_managers/usb/BeOSCompatibility.h +++ b/src/add-ons/kernel/bus_managers/usb/BeOSCompatibility.h @@ -10,6 +10,22 @@ #define IS_USER_ADDRESS(x) (((uint32)x & 0x80000000) > 0) #define IS_KERNEL_ADDRESS(x) (((uint32)x & 0x80000000) == 0) +#ifndef B_DEV_INVALID_PIPE +enum { + B_DEV_INVALID_PIPE = B_DEV_DOOR_OPEN + 1, + B_DEV_CRC_ERROR, + B_DEV_STALLED, + B_DEV_BAD_PID, + B_DEV_UNEXPECTED_PID, + B_DEV_DATA_OVERRUN, + B_DEV_DATA_UNDERRUN, + B_DEV_FIFO_OVERRUN, + B_DEV_FIFO_UNDERRUN, + B_DEV_PENDING, + B_DEV_MULTIPLE_ERRORS, + B_DEV_TOO_LATE, +}; +#endif inline status_t benaphore_init(benaphore *ben, const char *name) diff --git a/src/add-ons/kernel/bus_managers/usb/Hub.cpp b/src/add-ons/kernel/bus_managers/usb/Hub.cpp index 42950f2d66..c1326150d2 100644 --- a/src/add-ons/kernel/bus_managers/usb/Hub.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Hub.cpp @@ -230,7 +230,7 @@ Hub::Explore() void -Hub::InterruptCallback(void *cookie, uint32 status, void *data, +Hub::InterruptCallback(void *cookie, status_t status, void *data, size_t actualLength) { TRACE(("USB Hub: interrupt callback!\n")); diff --git a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp index 15fdd3ef03..cc6fa91736 100644 --- a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp @@ -204,9 +204,9 @@ IsochronousPipe::QueueIsochronous(void *data, size_t dataLength, typedef struct transfer_result_data_s { - sem_id notify_sem; - uint32 status; - size_t actual_length; + sem_id notify_sem; + status_t status; + size_t actual_length; } transfer_result_data; @@ -243,15 +243,12 @@ ControlPipe::SendRequest(uint8 requestType, uint8 request, uint16 value, if (actualLength) *actualLength = transferResult.actual_length; - if (transferResult.status == B_USB_STATUS_SUCCESS) - return B_OK; - - return B_ERROR; + return transferResult.status; } void -ControlPipe::SendRequestCallback(void *cookie, uint32 status, void *data, +ControlPipe::SendRequestCallback(void *cookie, status_t status, void *data, size_t actualLength) { transfer_result_data *transferResult = (transfer_result_data *)cookie; diff --git a/src/add-ons/kernel/bus_managers/usb/usb.cpp b/src/add-ons/kernel/bus_managers/usb/usb.cpp index 0574e62e04..ab55d9202b 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb.cpp +++ b/src/add-ons/kernel/bus_managers/usb/usb.cpp @@ -123,7 +123,7 @@ set_configuration(usb_device device, TRACE(("usb_module: set_configuration(0x%08x, 0x%08x)\n", device, configuration)); Object *object = gUSBStack->GetObject(device); if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) - return B_BAD_VALUE; + return B_DEV_INVALID_PIPE; return ((Device *)object)->SetConfiguration(configuration); } @@ -135,7 +135,7 @@ set_alt_interface(usb_device device, const usb_interface_info *interface) TRACE(("usb_module: set_alt_interface(0x%08x, 0x%08x)\n", device, interface)); Object *object = gUSBStack->GetObject(device); if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) - return B_BAD_VALUE; + return B_DEV_INVALID_PIPE; return B_ERROR; } @@ -147,7 +147,7 @@ set_feature(usb_id handle, uint16 selector) TRACE(("usb_module: set_feature(0x%08x, %d)\n", handle, selector)); Object *object = gUSBStack->GetObject(handle); if (!object) - return B_BAD_VALUE; + return B_DEV_INVALID_PIPE; return object->SetFeature(selector); } @@ -159,7 +159,7 @@ clear_feature(usb_id handle, uint16 selector) TRACE(("usb_module: clear_feature(0x%08x, %d)\n", handle, selector)); Object *object = gUSBStack->GetObject(handle); if (!object) - return B_BAD_VALUE; + return B_DEV_INVALID_PIPE; return object->ClearFeature(selector); } @@ -174,7 +174,7 @@ get_status(usb_id handle, uint16 *status) Object *object = gUSBStack->GetObject(handle); if (!object) - return B_BAD_VALUE; + return B_DEV_INVALID_PIPE; return object->GetStatus(status); } @@ -187,7 +187,7 @@ get_descriptor(usb_device device, uint8 type, uint8 index, uint16 languageID, TRACE(("usb_module: get_descriptor(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%08x, %d, 0x%08x)\n", device, type, index, languageID, data, dataLength, actualLength)); Object *object = gUSBStack->GetObject(device); if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) - return B_BAD_VALUE; + return B_DEV_INVALID_PIPE; return ((Device *)object)->GetDescriptor(type, index, languageID, data, dataLength, actualLength); @@ -201,7 +201,7 @@ send_request(usb_device device, uint8 requestType, uint8 request, TRACE(("usb_module: send_request(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, 0x%08x, 0x%08x)\n", device, requestType, request, value, index, length, data, actualLength)); Object *object = gUSBStack->GetObject(device); if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) - return B_BAD_VALUE; + return B_DEV_INVALID_PIPE; return ((Device *)object)->DefaultPipe()->SendRequest(requestType, request, value, index, length, data, length, actualLength); @@ -216,7 +216,7 @@ queue_request(usb_device device, uint8 requestType, uint8 request, TRACE(("usb_module: queue_request(0x%08x, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, 0x%08x, 0x%08x, 0x%08x)\n", device, requestType, request, value, index, length, data, callback, callbackCookie)); Object *object = gUSBStack->GetObject(device); if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) - return B_BAD_VALUE; + return B_DEV_INVALID_PIPE; return ((Device *)object)->DefaultPipe()->QueueRequest(requestType, request, value, index, length, data, length, callback, callbackCookie); @@ -230,7 +230,7 @@ queue_interrupt(usb_pipe pipe, void *data, size_t dataLength, TRACE(("usb_module: queue_interrupt(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, data, dataLength, callback, callbackCookie)); Object *object = gUSBStack->GetObject(pipe); if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0) - return B_BAD_VALUE; + return B_DEV_INVALID_PIPE; return ((InterruptPipe *)object)->QueueInterrupt(data, dataLength, callback, callbackCookie); @@ -244,7 +244,7 @@ queue_bulk(usb_pipe pipe, void *data, size_t dataLength, TRACE(("usb_module: queue_bulk(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, data, dataLength, callback, callbackCookie)); Object *object = gUSBStack->GetObject(pipe); if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) - return B_BAD_VALUE; + return B_DEV_INVALID_PIPE; return ((BulkPipe *)object)->QueueBulk(data, dataLength, callback, callbackCookie); @@ -258,7 +258,7 @@ queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount, TRACE(("usb_module: queue_bulk(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n", pipe, vector, vectorCount, callback, callbackCookie)); Object *object = gUSBStack->GetObject(pipe); if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) - return B_BAD_VALUE; + return B_DEV_INVALID_PIPE; return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback, callbackCookie); @@ -274,7 +274,7 @@ queue_isochronous(usb_pipe pipe, void *data, size_t dataLength, TRACE(("usb_module: queue_isochronous(0x%08x, 0x%08x, %d, 0x%08x, %d, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n", pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber, flags, callback, callbackCookie)); Object *object = gUSBStack->GetObject(pipe); if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0) - return B_BAD_VALUE; + return B_DEV_INVALID_PIPE; return ((IsochronousPipe *)object)->QueueIsochronous(data, dataLength, packetDesc, packetCount, startingFrameNumber, flags, callback, @@ -289,7 +289,7 @@ set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets, TRACE(("usb_module: set_pipe_policy(0x%08x, %d, %d, %d)\n", pipe, maxQueuedPackets, maxBufferDurationMS, sampleSize)); Object *object = gUSBStack->GetObject(pipe); if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0) - return B_BAD_VALUE; + return B_DEV_INVALID_PIPE; return B_ERROR; } @@ -301,7 +301,7 @@ cancel_queued_transfers(usb_pipe pipe) TRACE(("usb_module: cancel_queued_transfers(0x%08x)\n", pipe)); Object *object = gUSBStack->GetObject(pipe); if (!object || (object->Type() & USB_OBJECT_PIPE) == 0) - return B_BAD_VALUE; + return B_DEV_INVALID_PIPE; return ((Pipe *)object)->CancelQueuedTransfers(); } 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 7347d8f686..34a5e4aac0 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb_p.h +++ b/src/add-ons/kernel/bus_managers/usb/usb_p.h @@ -272,7 +272,7 @@ virtual void SetDataToggle(bool toggle) {}; void *data, size_t dataLength, size_t *actualLength); static void SendRequestCallback(void *cookie, - uint32 status, void *data, + status_t status, void *data, size_t actualLength); status_t QueueRequest(uint8 requestType, @@ -437,7 +437,7 @@ virtual status_t GetDescriptor(uint8 descriptorType, status_t ResetPort(uint8 index); void Explore(); static void InterruptCallback(void *cookie, - uint32 status, void *data, + status_t status, void *data, size_t actualLength); virtual status_t ReportDevice( diff --git a/src/add-ons/kernel/busses/scsi/usb/Jamfile b/src/add-ons/kernel/busses/scsi/usb/Jamfile index 254a259924..0afc7f4210 100644 --- a/src/add-ons/kernel/busses/scsi/usb/Jamfile +++ b/src/add-ons/kernel/busses/scsi/usb/Jamfile @@ -2,6 +2,10 @@ SubDir HAIKU_TOP src add-ons kernel busses scsi usb ; SetSubDirSupportedPlatformsBeOSCompatible ; +if $(TARGET_PLATFORM) != haiku { + UsePublicHeaders [ FDirName drivers ] ; +} + KernelAddon usb_scsi : usb_scsi.c tracing.c diff --git a/src/add-ons/kernel/busses/scsi/usb/proto_common.c b/src/add-ons/kernel/busses/scsi/usb/proto_common.c index e8d1ab3099..c4bcd23698 100644 --- a/src/add-ons/kernel/busses/scsi/usb/proto_common.c +++ b/src/add-ons/kernel/busses/scsi/usb/proto_common.c @@ -30,7 +30,7 @@ ??? */ -void bulk_callback(void *cookie, uint32 status, void* data, uint32 actual_len) +void bulk_callback(void *cookie, status_t status, void* data, uint32 actual_len) { TRACE_BULK_CALLBACK(status, actual_len); if(cookie){ diff --git a/src/add-ons/kernel/busses/scsi/usb/proto_common.h b/src/add-ons/kernel/busses/scsi/usb/proto_common.h index d2b65fb5dc..74f74d60bc 100644 --- a/src/add-ons/kernel/busses/scsi/usb/proto_common.h +++ b/src/add-ons/kernel/busses/scsi/usb/proto_common.h @@ -17,7 +17,7 @@ #include "device_info.h" #endif /* _DEVICE_INFO_H_ */ -void bulk_callback(void *cookie, uint32 status, void* data, uint32 actual_len); +void bulk_callback(void *cookie, status_t status, void* data, uint32 actual_len); status_t process_data_io(usb_device_info *udi, iovec *sg_data, int32 sg_count/*sg_buffer *sgb*/, EDirection dir); diff --git a/src/add-ons/kernel/busses/usb/ehci.cpp b/src/add-ons/kernel/busses/usb/ehci.cpp index c321860177..8cc407e4d8 100644 --- a/src/add-ons/kernel/busses/usb/ehci.cpp +++ b/src/add-ons/kernel/busses/usb/ehci.cpp @@ -106,6 +106,7 @@ EHCI::EHCI(pci_info *info, Stack *stack) fLastTransfer(NULL), fFinishThread(-1), fStopFinishThread(false), + fFreeListHead(NULL), fRootHub(NULL), fRootHubAddress(0), fPortCount(0), @@ -879,7 +880,7 @@ EHCI::CancelPendingTransfer(Transfer *transfer) transfer_data *current = fFirstTransfer; while (current) { if (current->transfer == transfer) { - current->transfer->Finished(B_USB_STATUS_IRP_CANCELLED_BY_REQUEST, 0); + current->transfer->Finished(B_CANCELED, 0); delete current->transfer; if (last) @@ -912,7 +913,7 @@ EHCI::CancelAllPendingTransfers() transfer_data *transfer = fFirstTransfer; while (transfer) { - transfer->transfer->Finished(B_USB_STATUS_IRP_CANCELLED_BY_REQUEST, 0); + transfer->transfer->Finished(B_CANCELED, 0); delete transfer->transfer; transfer_data *next = transfer->link; @@ -956,7 +957,6 @@ EHCI::FinishTransfers() transfer_data *transfer = fFirstTransfer; Unlock(); - ehci_qh *freeListHead = NULL; while (transfer) { bool transferDone = false; ehci_qtd *descriptor = (ehci_qtd *)transfer->queue_head->element_log; @@ -977,18 +977,34 @@ EHCI::FinishTransfers() // a transfer error occured TRACE_ERROR(("usb_ehci: qtd (0x%08lx) error: 0x%08lx\n", descriptor->this_phy, status)); - uint32 callbackStatus = 0; - if (status & EHCI_QTD_STATUS_HALTED) - callbackStatus |= B_USB_STATUS_DEVICE_STALLED; - if (status & EHCI_QTD_STATUS_BUFFER) - callbackStatus |= B_USB_STATUS_DEVICE_TIMEOUT; - if (status & EHCI_QTD_STATUS_BABBLE) - callbackStatus |= B_USB_STATUS_ADAPTER_HARDWARE_ERROR; - if (status & EHCI_QTD_STATUS_TERROR) - callbackStatus |= B_USB_STATUS_DRIVER_INTERNAL_ERROR; - // ToDo: define better error values! + status_t callbackStatus = B_ERROR; + uint8 errorCount = status >> EHCI_QTD_ERRCOUNT_SHIFT; + errorCount &= EHCI_QTD_ERRCOUNT_MASK; + if (errorCount == 0) { + // the error counter counted down to zero, report why + int32 reasons = 0; + if (status & EHCI_QTD_STATUS_BUFFER) { + callbackStatus = transfer->incoming ? B_DEV_DATA_OVERRUN : B_DEV_DATA_UNDERRUN; + reasons++; + } + if (status & EHCI_QTD_STATUS_TERROR) { + callbackStatus = B_DEV_CRC_ERROR; + reasons++; + } - UnlinkQueueHead(transfer->queue_head, &freeListHead); + if (reasons > 1) + callbackStatus = B_DEV_MULTIPLE_ERRORS; + } else if (status & EHCI_QTD_STATUS_BABBLE) { + // there is a babble condition + callbackStatus = transfer->incoming ? B_DEV_FIFO_OVERRUN : B_DEV_FIFO_UNDERRUN; + } else { + // if the error counter didn't count down to zero + // and there was no babble, then this halt was caused + // by a stall handshake + callbackStatus = B_DEV_STALLED; + } + + UnlinkQueueHead(transfer->queue_head, &fFreeListHead); transfer->transfer->Finished(callbackStatus, 0); transferDone = true; break; @@ -1038,9 +1054,9 @@ EHCI::FinishTransfers() &nextDataToggle); } - UnlinkQueueHead(transfer->queue_head, &freeListHead); + UnlinkQueueHead(transfer->queue_head, &fFreeListHead); transfer->transfer->TransferPipe()->SetDataToggle(nextDataToggle); - transfer->transfer->Finished(B_USB_STATUS_SUCCESS, actualLength); + transfer->transfer->Finished(B_OK, actualLength); transferDone = true; break; } @@ -1065,19 +1081,22 @@ EHCI::FinishTransfers() Unlock(); } } else { - lastTransfer = transfer; - transfer = transfer->link; + if (Lock()) { + lastTransfer = transfer; + transfer = transfer->link; + Unlock(); + } } } - if (freeListHead) { + if (fFreeListHead) { // set the doorbell and wait for the host controller to notify us WriteOpReg(EHCI_USBCMD, ReadOpReg(EHCI_USBCMD) | EHCI_USBCMD_INTONAAD); if (acquire_sem_etc(fAsyncAdvanceSem, 1, B_RELATIVE_TIMEOUT, 1000) == B_OK) { - while (freeListHead) { - ehci_qh *next = (ehci_qh *)freeListHead->next_log; - FreeQueueHead(freeListHead); - freeListHead = next; + while (fFreeListHead) { + ehci_qh *next = (ehci_qh *)fFreeListHead->next_log; + FreeQueueHead(fFreeListHead); + fFreeListHead = next; } } } diff --git a/src/add-ons/kernel/busses/usb/ehci.h b/src/add-ons/kernel/busses/usb/ehci.h index bb9acabe21..4e475a4525 100644 --- a/src/add-ons/kernel/busses/usb/ehci.h +++ b/src/add-ons/kernel/busses/usb/ehci.h @@ -142,6 +142,7 @@ static pci_module_info *sPCIModule; sem_id fFinishTransfersSem; thread_id fFinishThread; bool fStopFinishThread; + ehci_qh *fFreeListHead; // Root Hub EHCIRootHub *fRootHub; diff --git a/src/add-ons/kernel/busses/usb/ehci_hardware.h b/src/add-ons/kernel/busses/usb/ehci_hardware.h index 3b2d0cb6b9..b080e87c06 100644 --- a/src/add-ons/kernel/busses/usb/ehci_hardware.h +++ b/src/add-ons/kernel/busses/usb/ehci_hardware.h @@ -153,7 +153,7 @@ typedef struct { #define EHCI_QTD_PID_SETUP 0x02 #define EHCI_QTD_STATUS_SHIFT 0 #define EHCI_QTD_STATUS_MASK 0x7f -#define EHCI_QTD_STATUS_ERRMASK 0x70 +#define EHCI_QTD_STATUS_ERRMASK 0x50 #define EHCI_QTD_STATUS_ACTIVE (1 << 7) // Active #define EHCI_QTD_STATUS_HALTED (1 << 6) // Halted #define EHCI_QTD_STATUS_BUFFER (1 << 5) // Data Buffer Error diff --git a/src/add-ons/kernel/busses/usb/ehci_rh.cpp b/src/add-ons/kernel/busses/usb/ehci_rh.cpp index 3afe5e88ed..9ea157a659 100644 --- a/src/add-ons/kernel/busses/usb/ehci_rh.cpp +++ b/src/add-ons/kernel/busses/usb/ehci_rh.cpp @@ -136,8 +136,7 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer) usb_request_data *request = transfer->RequestData(); TRACE(("usb_ehci_roothub: request: %d\n", request->Request)); - // ToDo: define better status codes. We should return a request error. - uint32 status = B_USB_STATUS_DEVICE_TIMEOUT; + status_t status = B_TIMED_OUT; size_t actualLength = 0; switch (request->Request) { case USB_REQUEST_GET_STATUS: { @@ -149,7 +148,7 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer) // and if there is a over-current condition (bit 1). // everything as 0 means all is ok. memset(transfer->Data(), 0, actualLength); - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; } @@ -157,7 +156,7 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer) if (ehci->GetPortStatus(request->Index - 1, &portStatus) >= B_OK) { actualLength = MIN(sizeof(usb_port_status), transfer->DataLength()); memcpy(transfer->Data(), (void *)&portStatus, actualLength); - status = B_USB_STATUS_SUCCESS; + status = B_OK; } break; @@ -165,12 +164,12 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer) case USB_REQUEST_SET_ADDRESS: if (request->Value >= 128) { - status = B_USB_STATUS_DEVICE_TIMEOUT; + status = B_TIMED_OUT; break; } TRACE(("usb_ehci_roothub: set address: %d\n", request->Value)); - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; case USB_REQUEST_GET_DESCRIPTOR: @@ -182,7 +181,7 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer) transfer->DataLength()); memcpy(transfer->Data(), (void *)&sEHCIRootHubDevice, actualLength); - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; } @@ -192,7 +191,7 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer) sEHCIRootHubConfig.hub.num_ports = ehci->PortCount(); memcpy(transfer->Data(), (void *)&sEHCIRootHubConfig, actualLength); - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; } @@ -205,7 +204,7 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer) transfer->DataLength()); memcpy(transfer->Data(), (void *)&sEHCIRootHubStrings[index], actualLength); - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; } @@ -215,14 +214,14 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer) sEHCIRootHubConfig.hub.num_ports = ehci->PortCount(); memcpy(transfer->Data(), (void *)&sEHCIRootHubConfig.hub, actualLength); - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; } } break; case USB_REQUEST_SET_CONFIGURATION: - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; case USB_REQUEST_CLEAR_FEATURE: { @@ -234,7 +233,7 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer) TRACE(("usb_ehci_roothub: clear feature: %d\n", request->Value)); if (ehci->ClearPortFeature(request->Index - 1, request->Value) >= B_OK) - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; } @@ -247,7 +246,7 @@ EHCIRootHub::ProcessTransfer(EHCI *ehci, Transfer *transfer) TRACE(("usb_ehci_roothub: set feature: %d\n", request->Value)); if (ehci->SetPortFeature(request->Index - 1, request->Value) >= B_OK) - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; } } diff --git a/src/add-ons/kernel/busses/usb/uhci.cpp b/src/add-ons/kernel/busses/usb/uhci.cpp index dd0fdc74a8..b9c7231816 100644 --- a/src/add-ons/kernel/busses/usb/uhci.cpp +++ b/src/add-ons/kernel/busses/usb/uhci.cpp @@ -770,14 +770,39 @@ UHCI::FinishTransfers() // an error occured. we have to remove the // transfer from the queue and clean up - uint32 callbackStatus = 0; - if (status & TD_STATUS_ERROR_STALLED) - callbackStatus |= B_USB_STATUS_DEVICE_STALLED; - if (status & TD_STATUS_ERROR_TIMEOUT) { - if (transfer->incoming) - callbackStatus |= B_USB_STATUS_DEVICE_CRC_ERROR; - else - callbackStatus |= B_USB_STATUS_DEVICE_TIMEOUT; + status_t callbackStatus = B_ERROR; + uint8 errorCount = status >> TD_ERROR_COUNT_SHIFT; + errorCount &= TD_ERROR_COUNT_MASK; + if (errorCount == 0) { + // the error counter counted down to zero, report why + int32 reasons = 0; + if (status & TD_STATUS_ERROR_BUFFER) { + callbackStatus = transfer->incoming ? B_DEV_DATA_OVERRUN : B_DEV_DATA_UNDERRUN; + reasons++; + } + if (status & TD_STATUS_ERROR_TIMEOUT) { + callbackStatus = transfer->incoming ? B_DEV_CRC_ERROR : B_TIMED_OUT; + reasons++; + } + if (status & TD_STATUS_ERROR_NAK) { + callbackStatus = B_DEV_UNEXPECTED_PID; + reasons++; + } + if (status & TD_STATUS_ERROR_BITSTUFF) { + callbackStatus = B_DEV_CRC_ERROR; + reasons++; + } + + if (reasons > 1) + callbackStatus = B_DEV_MULTIPLE_ERRORS; + } else if (status & TD_STATUS_ERROR_BABBLE) { + // there is a babble condition + callbackStatus = transfer->incoming ? B_DEV_FIFO_OVERRUN : B_DEV_FIFO_UNDERRUN; + } else { + // if the error counter didn't count down to zero + // and there was no babble, then this halt was caused + // by a stall handshake + callbackStatus = B_DEV_STALLED; } transfer->queue->RemoveDescriptorChain( @@ -841,7 +866,7 @@ UHCI::FinishTransfers() FreeDescriptorChain(transfer->first_descriptor); transfer->transfer->TransferPipe()->SetDataToggle(lastDataToggle == 0); - transfer->transfer->Finished(B_USB_STATUS_SUCCESS, actualLength); + transfer->transfer->Finished(B_OK, actualLength); transferDone = true; break; } diff --git a/src/add-ons/kernel/busses/usb/uhci_hardware.h b/src/add-ons/kernel/busses/usb/uhci_hardware.h index 2174bb5ade..ec7e5e5fe0 100644 --- a/src/add-ons/kernel/busses/usb/uhci_hardware.h +++ b/src/add-ons/kernel/busses/usb/uhci_hardware.h @@ -128,7 +128,9 @@ typedef struct #define TD_DEPTH_FIRST 0x04 #define TD_TERMINATE 0x01 -#define TD_ERROR_MASK 0x7e0000 +#define TD_ERROR_MASK 0x440000 +#define TD_ERROR_COUNT_SHIFT 27 +#define TD_ERROR_COUNT_MASK 0x03 #define TD_LINK_MASK 0xfffffff0 diff --git a/src/add-ons/kernel/busses/usb/uhci_rh.cpp b/src/add-ons/kernel/busses/usb/uhci_rh.cpp index 7989714f25..a071b2f97b 100644 --- a/src/add-ons/kernel/busses/usb/uhci_rh.cpp +++ b/src/add-ons/kernel/busses/usb/uhci_rh.cpp @@ -140,8 +140,7 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer) usb_request_data *request = transfer->RequestData(); TRACE(("usb_uhci_roothub: request: %d\n", request->Request)); - // ToDo: define better status codes. We should return a request error. - uint32 status = B_USB_STATUS_DEVICE_TIMEOUT; + status_t status = B_TIMED_OUT; size_t actualLength = 0; switch (request->Request) { case USB_REQUEST_GET_STATUS: { @@ -150,7 +149,7 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer) actualLength = MIN(sizeof(usb_port_status), transfer->DataLength()); memset(transfer->Data(), 0, actualLength); - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; } @@ -158,19 +157,19 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer) if (uhci->GetPortStatus(request->Index - 1, &portStatus) >= B_OK) { actualLength = MIN(sizeof(usb_port_status), transfer->DataLength()); memcpy(transfer->Data(), (void *)&portStatus, actualLength); - status = B_USB_STATUS_SUCCESS; + status = B_OK; } break; } case USB_REQUEST_SET_ADDRESS: if (request->Value >= 128) { - status = B_USB_STATUS_DEVICE_TIMEOUT; + status = B_TIMED_OUT; break; } TRACE(("usb_uhci_roothub: set address: %d\n", request->Value)); - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; case USB_REQUEST_GET_DESCRIPTOR: @@ -182,7 +181,7 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer) transfer->DataLength()); memcpy(transfer->Data(), (void *)&sUHCIRootHubDevice, actualLength); - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; } @@ -191,7 +190,7 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer) transfer->DataLength()); memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig, actualLength); - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; } @@ -204,7 +203,7 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer) transfer->DataLength()); memcpy(transfer->Data(), (void *)&sUHCIRootHubStrings[index], actualLength); - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; } @@ -213,14 +212,14 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer) transfer->DataLength()); memcpy(transfer->Data(), (void *)&sUHCIRootHubConfig.hub, actualLength); - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; } } break; case USB_REQUEST_SET_CONFIGURATION: - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; case USB_REQUEST_CLEAR_FEATURE: { @@ -232,7 +231,7 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer) TRACE(("usb_uhci_roothub: clear feature: %d\n", request->Value)); if (uhci->ClearPortFeature(request->Index - 1, request->Value) >= B_OK) - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; } @@ -245,7 +244,7 @@ UHCIRootHub::ProcessTransfer(UHCI *uhci, Transfer *transfer) TRACE(("usb_uhci_roothub: set feature: %d!\n", request->Value)); if (uhci->SetPortFeature(request->Index - 1, request->Value) >= B_OK) - status = B_USB_STATUS_SUCCESS; + status = B_OK; break; } } diff --git a/src/add-ons/kernel/drivers/bus/usb/usb_raw.cpp b/src/add-ons/kernel/drivers/bus/usb/usb_raw.cpp index 1a889740dd..c76c232059 100644 --- a/src/add-ons/kernel/drivers/bus/usb/usb_raw.cpp +++ b/src/add-ons/kernel/drivers/bus/usb/usb_raw.cpp @@ -99,12 +99,13 @@ usb_raw_device_removed(void *cookie) gDeviceCount--; benaphore_unlock(&gDeviceListLock); - benaphore_lock(&device->lock); device->device = 0; - benaphore_destroy(&device->lock); - delete_sem(device->notify); - if (device->reference_count == 0) + if (device->reference_count == 0) { + benaphore_lock(&device->lock); + benaphore_destroy(&device->lock); + delete_sem(device->notify); free(device); + } return B_OK; } @@ -123,12 +124,6 @@ usb_raw_open(const char *name, uint32 flags, void **cookie) raw_device *element = gDeviceList; while (element) { if (strcmp(name, element->name) == 0) { - if (element->reference_count > 0) { - // device is already open - benaphore_unlock(&gDeviceListLock); - return B_BUSY; - } - element->reference_count++; *cookie = element; benaphore_unlock(&gDeviceListLock); @@ -159,8 +154,12 @@ usb_raw_free(void *cookie) raw_device *device = (raw_device *)cookie; device->reference_count--; - if (device->device == 0) + if (device->device == 0) { + benaphore_lock(&device->lock); + benaphore_destroy(&device->lock); + delete_sem(device->notify); free(device); + } benaphore_unlock(&gDeviceListLock); return B_OK; @@ -168,27 +167,27 @@ usb_raw_free(void *cookie) static void -usb_raw_callback(void *cookie, uint32 status, void *data, size_t actualLength) +usb_raw_callback(void *cookie, status_t status, void *data, size_t actualLength) { TRACE((DRIVER_NAME": callback()\n")); raw_device *device = (raw_device *)cookie; switch (status) { - case B_USB_STATUS_SUCCESS: + case B_OK: device->status = RAW_STATUS_SUCCESS; break; - case B_USB_STATUS_DEVICE_CRC_ERROR: - device->status = RAW_STATUS_CRC_ERROR; - break; - case B_USB_STATUS_DEVICE_TIMEOUT: + case B_TIMED_OUT: device->status = RAW_STATUS_TIMEOUT; break; - case B_USB_STATUS_DEVICE_STALLED: - device->status = RAW_STATUS_STALLED; - break; - case B_USB_STATUS_IRP_CANCELLED_BY_REQUEST: + case B_CANCELED: device->status = RAW_STATUS_ABORTED; break; + case B_DEV_CRC_ERROR: + device->status = RAW_STATUS_CRC_ERROR; + break; + case B_DEV_STALLED: + device->status = RAW_STATUS_STALLED; + break; default: device->status = RAW_STATUS_FAILED; break; diff --git a/src/add-ons/kernel/drivers/input/usb_hid/hid.c b/src/add-ons/kernel/drivers/input/usb_hid/hid.c index 623aac51d3..9867636654 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/hid.c +++ b/src/add-ons/kernel/drivers/input/usb_hid/hid.c @@ -592,11 +592,11 @@ usb_callback(void *cookie, uint32 busStatus, acquire_sem(device->sem_lock); device->actual_length = actualLength; device->bus_status = busStatus; /* B_USB_STATUS_* */ - if (busStatus != B_USB_STATUS_SUCCESS) { + if (busStatus != B_OK) { /* request failed */ release_sem(device->sem_lock); DPRINTF_ERR((MY_ID "bus status %d\n", (int)busStatus)); - if (busStatus == B_USB_STATUS_IRP_CANCELLED_BY_REQUEST) { + if (busStatus == B_CANCELED) { /* cancelled: device is unplugged */ return; } diff --git a/src/add-ons/kernel/drivers/midi/usb_midi/usb_midi.c b/src/add-ons/kernel/drivers/midi/usb_midi/usb_midi.c index b025b06b2c..82061df7ca 100644 --- a/src/add-ons/kernel/drivers/midi/usb_midi/usb_midi.c +++ b/src/add-ons/kernel/drivers/midi/usb_midi/usb_midi.c @@ -158,11 +158,11 @@ midi_usb_callback(void *cookie, uint32 status, acquire_sem (my_dev->sem_lock); my_dev->actual_length = actual_len; my_dev->bus_status = status; /* B_USB_STATUS_* */ - if (status != B_USB_STATUS_SUCCESS) { + if (status != B_OK) { /* request failed */ release_sem (my_dev->sem_lock); DPRINTF_ERR ((MY_ID "bus status %d\n", (int)status)); - if (status == B_USB_STATUS_IRP_CANCELLED_BY_REQUEST) { + if (status == B_CANCELED) { /* cancelled: device is unplugged */ return; }