Exemplo n.º 1
0
static int32
ohci_std_ops(int32 op, ...)
{
	switch (op)	{
		case B_MODULE_INIT:
			TRACE_MODULE("init module\n");
			return B_OK;
		case B_MODULE_UNINIT:
			TRACE_MODULE("uninit module\n");
			return B_OK;
	}

	return EINVAL;
}
Exemplo n.º 2
0
const usb_configuration_info *
get_configuration(usb_device device)
{
	TRACE_MODULE("get_configuration(%" B_PRId32 ")\n", device);
	Object *object = gUSBStack->GetObject(device);
	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
		return NULL;

	return ((Device *)object)->Configuration();
}
Exemplo n.º 3
0
const usb_device_descriptor *
get_device_descriptor(usb_device device)
{
	TRACE_MODULE("get_device_descriptor(%" B_PRId32 ")\n", device);
	Object *object = gUSBStack->GetObject(device);
	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
		return NULL;

	return ((Device *)object)->DeviceDescriptor();
}
Exemplo n.º 4
0
status_t
clear_feature(usb_id handle, uint16 selector)
{
	TRACE_MODULE("clear_feature(%" B_PRId32 ", %d)\n", handle, selector);
	Object *object = gUSBStack->GetObject(handle);
	if (!object)
		return B_DEV_INVALID_PIPE;

	return object->ClearFeature(selector);
}
Exemplo n.º 5
0
status_t
set_alt_interface(usb_device device, const usb_interface_info *interface)
{
	TRACE_MODULE("set_alt_interface(%" B_PRId32 ", %p)\n", device, interface);
	Object *object = gUSBStack->GetObject(device);
	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
		return B_DEV_INVALID_PIPE;

	return ((Device *)object)->SetAltInterface(interface);
}
Exemplo n.º 6
0
status_t
cancel_queued_transfers(usb_pipe pipe)
{
	TRACE_MODULE("cancel_queued_transfers(%" B_PRId32 ")\n", pipe);
	Object *object = gUSBStack->GetObject(pipe);
	if (!object || (object->Type() & USB_OBJECT_PIPE) == 0)
		return B_DEV_INVALID_PIPE;

	return ((Pipe *)object)->CancelQueuedTransfers(false);
}
Exemplo n.º 7
0
status_t
set_configuration(usb_device device,
	const usb_configuration_info *configuration)
{
	TRACE_MODULE("set_configuration(%" B_PRId32 ", %p)\n", device,
		configuration);
	Object *object = gUSBStack->GetObject(device);
	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
		return B_DEV_INVALID_PIPE;

	return ((Device *)object)->SetConfiguration(configuration);
}
Exemplo n.º 8
0
status_t
get_status(usb_id handle, uint16 *status)
{
	TRACE_MODULE("get_status(%" B_PRId32 ", %p)\n", handle, status);
	if (!status)
		return B_BAD_VALUE;

	Object *object = gUSBStack->GetObject(handle);
	if (!object)
		return B_DEV_INVALID_PIPE;

	return object->GetStatus(status);
}
Exemplo n.º 9
0
status_t
set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets,
	uint16 maxBufferDurationMS, uint16 sampleSize)
{
	TRACE_MODULE("set_pipe_policy(%" B_PRId32 ", %d, %d, %d)\n", pipe,
		maxQueuedPackets, maxBufferDurationMS, sampleSize);
	Object *object = gUSBStack->GetObject(pipe);
	if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0)
		return B_DEV_INVALID_PIPE;

	return ((IsochronousPipe *)object)->SetPipePolicy(maxQueuedPackets,
		maxBufferDurationMS, sampleSize);
}
Exemplo n.º 10
0
status_t
queue_bulk_v_physical(usb_pipe pipe, iovec *vector, size_t vectorCount,
	usb_callback_func callback, void *callbackCookie)
{
	TRACE_MODULE("queue_bulk_v_physical(%" B_PRId32 ", %p, %" B_PRIuSIZE
		", %p, %p)\n", pipe, vector, vectorCount, callback, callbackCookie);
	Object *object = gUSBStack->GetObject(pipe);
	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
		return B_DEV_INVALID_PIPE;

	return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback,
		callbackCookie, true);
}
Exemplo n.º 11
0
status_t
queue_interrupt(usb_pipe pipe, void *data, size_t dataLength,
	usb_callback_func callback, void *callbackCookie)
{
	TRACE_MODULE("queue_interrupt(%" B_PRId32 ", %p, %ld, %p, %p)\n",
		pipe, data, dataLength, callback, callbackCookie);
	Object *object = gUSBStack->GetObject(pipe);
	if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0)
		return B_DEV_INVALID_PIPE;

	return ((InterruptPipe *)object)->QueueInterrupt(data, dataLength, callback,
		callbackCookie);
}
Exemplo n.º 12
0
status_t
queue_bulk(usb_pipe pipe, void *data, size_t dataLength,
	usb_callback_func callback, void *callbackCookie)
{
	TRACE_MODULE("queue_bulk(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, %p)\n",
		pipe, data, dataLength, callback, callbackCookie);
	Object *object = gUSBStack->GetObject(pipe);
	if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0)
		return B_DEV_INVALID_PIPE;

	return ((BulkPipe *)object)->QueueBulk(data, dataLength, callback,
		callbackCookie);
}
Exemplo n.º 13
0
status_t
get_descriptor(usb_device device, uint8 type, uint8 index, uint16 languageID,
	void *data, size_t dataLength, size_t *actualLength)
{
	TRACE_MODULE("get_descriptor(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, %p, "
		"%" B_PRIuSIZE ", %p)\n",
		device, type, index, languageID, data, dataLength, actualLength);
	Object *object = gUSBStack->GetObject(device);
	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
		return B_DEV_INVALID_PIPE;

	return ((Device *)object)->GetDescriptor(type, index, languageID,
		data, dataLength, actualLength);
}
Exemplo n.º 14
0
status_t
send_request(usb_device device, uint8 requestType, uint8 request,
	uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength)
{
	TRACE_MODULE("send_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x, "
		"%d, %p, %p)\n", device, requestType, request, value, index, length,
		data, actualLength);
	Object *object = gUSBStack->GetObject(device);
	if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
		return B_DEV_INVALID_PIPE;

	return ((Device *)object)->DefaultPipe()->SendRequest(requestType, request,
		value, index, length, data, length, actualLength);
}
Exemplo n.º 15
0
status_t
queue_request(usb_device device, uint8 requestType, uint8 request,
	uint16 value, uint16 index, uint16 length, void *data,
	usb_callback_func callback, void *callbackCookie)
{
	TRACE_MODULE("queue_request(%" B_PRId32 ", 0x%02x, 0x%02x, 0x%04x, 0x%04x,"
		" %u, %p, %p, %p)\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_DEV_INVALID_PIPE;

	return ((Device *)object)->DefaultPipe()->QueueRequest(requestType,
		request, value, index, length, data, length, callback, callbackCookie);
}
Exemplo n.º 16
0
status_t
queue_isochronous(usb_pipe pipe, void *data, size_t dataLength,
	usb_iso_packet_descriptor *packetDesc, uint32 packetCount,
	uint32 *startingFrameNumber, uint32 flags, usb_callback_func callback,
	void *callbackCookie)
{
	TRACE_MODULE("queue_isochronous(%" B_PRId32 ", %p, %" B_PRIuSIZE ", %p, "
		"%" B_PRId32 ", %p, 0x%08" B_PRIx32 ", %p, %p)\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_DEV_INVALID_PIPE;

	return ((IsochronousPipe *)object)->QueueIsochronous(data, dataLength,
		packetDesc, packetCount, startingFrameNumber, flags, callback,
		callbackCookie);
}
Exemplo n.º 17
0
status_t
usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize)
{
	TRACE_MODULE("usb_ioctl(%" B_PRIu32 ", %p, %" B_PRIuSIZE ")\n", opcode,
		buffer, bufferSize);

	switch (opcode) {
		case 'DNAM': {
			Object *object = gUSBStack->GetObject(*(usb_id *)buffer);
			if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0)
				return B_BAD_VALUE;

			uint32 index = 0;
			return ((Device *)object)->BuildDeviceName((char *)buffer, &index,
				bufferSize, NULL);
		}
	}

	return B_DEV_INVALID_IOCTL;
}
Exemplo n.º 18
0
status_t
OHCI::AddTo(Stack *stack)
{
#ifdef TRACE_USB
	set_dprintf_enabled(true);
#ifndef ANTARES_TARGET_PLATFORM_ANTARES
	load_driver_symbols("ohci");
#endif
#endif

	if (!sPCIModule) {
		status_t status = get_module(B_PCI_MODULE_NAME, (module_info **)&sPCIModule);
		if (status < B_OK) {
			TRACE_MODULE_ERROR("getting pci module failed! 0x%08lx\n", status);
			return status;
		}
	}

	TRACE_MODULE("searching devices\n");
	bool found = false;
	pci_info *item = new(std::nothrow) pci_info;
	if (!item) {
		sPCIModule = NULL;
		put_module(B_PCI_MODULE_NAME);
		return B_NO_MEMORY;
	}

	for (uint32 i = 0 ; sPCIModule->get_nth_pci_info(i, item) >= B_OK; i++) {
		if (item->class_base == PCI_serial_bus && item->class_sub == PCI_usb
			&& item->class_api == PCI_usb_ohci) {
			if (item->u.h0.interrupt_line == 0
				|| item->u.h0.interrupt_line == 0xFF) {
				TRACE_MODULE_ERROR("found device with invalid IRQ -"
					" check IRQ assignement\n");
				continue;
			}

			TRACE_MODULE("found device at IRQ %u\n",
				item->u.h0.interrupt_line);
			OHCI *bus = new(std::nothrow) OHCI(item, stack);
			if (!bus) {
				delete item;
				sPCIModule = NULL;
				put_module(B_PCI_MODULE_NAME);
				return B_NO_MEMORY;
			}

			if (bus->InitCheck() < B_OK) {
				TRACE_MODULE_ERROR("bus failed init check\n");
				delete bus;
				continue;
			}

			// the bus took it away
			item = new(std::nothrow) pci_info;

			bus->Start();
			stack->AddBusManager(bus);
			found = true;
		}
	}

	if (!found) {
		TRACE_MODULE_ERROR("no devices found\n");
		delete item;
		sPCIModule = NULL;
		put_module(B_PCI_MODULE_NAME);
		return ENODEV;
	}

	delete item;
	return B_OK;
}
Exemplo n.º 19
0
int32
OHCI::_Interrupt()
{
	static spinlock lock = B_SPINLOCK_INITIALIZER;
	acquire_spinlock(&lock);

	uint32 status = 0;
	uint32 acknowledge = 0;
	bool finishTransfers = false;
	int32 result = B_HANDLED_INTERRUPT;

	// The LSb of done_head is used to inform the HCD that an interrupt
	// condition exists for both the done list and for another event recorded in
	// the HcInterruptStatus register. If done_head is 0, then the interrupt
	// was caused by other than the HccaDoneHead update and the
	// HcInterruptStatus register needs to be accessed to determine that exact
	// interrupt cause. If HccDoneHead is nonzero, then a done list update
	// interrupt is indicated and if the LSb of the Dword is nonzero, then an
	// additional interrupt event is indicated and HcInterruptStatus should be
	// checked to determine its cause.
	uint32 doneHead = fHcca->done_head;
	if (doneHead != 0) {
		status = OHCI_WRITEBACK_DONE_HEAD;
		if (doneHead & OHCI_DONE_INTERRUPTS)
			status |= _ReadReg(OHCI_INTERRUPT_STATUS)
				& _ReadReg(OHCI_INTERRUPT_ENABLE);
	} else {
		status = _ReadReg(OHCI_INTERRUPT_STATUS) & _ReadReg(OHCI_INTERRUPT_ENABLE)
			& ~OHCI_WRITEBACK_DONE_HEAD;
		if (status == 0) {
			// Nothing to be done (PCI shared interrupt)
			release_spinlock(&lock);
			return B_UNHANDLED_INTERRUPT;
		}
	}

	if (status & OHCI_SCHEDULING_OVERRUN) {
		TRACE_MODULE("scheduling overrun occured\n");
		acknowledge |= OHCI_SCHEDULING_OVERRUN;
	}

	if (status & OHCI_WRITEBACK_DONE_HEAD) {
		TRACE_MODULE("transfer descriptors processed\n");
		fHcca->done_head = 0;
		acknowledge |= OHCI_WRITEBACK_DONE_HEAD;
		result = B_INVOKE_SCHEDULER;
		finishTransfers = true;
	}

	if (status & OHCI_RESUME_DETECTED) {
		TRACE_MODULE("resume detected\n");
		acknowledge |= OHCI_RESUME_DETECTED;
	}

	if (status & OHCI_UNRECOVERABLE_ERROR) {
		TRACE_MODULE_ERROR("unrecoverable error - controller halted\n");
		_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
		// TODO: clear all pending transfers, reset and resetup the controller
	}

	if (status & OHCI_ROOT_HUB_STATUS_CHANGE) {
		TRACE_MODULE("root hub status change\n");
		// Disable the interrupt as it will otherwise be retriggered until the
		// port has been reset and the change is cleared explicitly.
		// TODO: renable it once we use status changes instead of polling
		_WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ROOT_HUB_STATUS_CHANGE);
		acknowledge |= OHCI_ROOT_HUB_STATUS_CHANGE;
	}

	if (acknowledge != 0)
		_WriteReg(OHCI_INTERRUPT_STATUS, acknowledge);

	release_spinlock(&lock);

	if (finishTransfers)
		release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);

	return result;
}
Exemplo n.º 20
0
static int32
bus_std_ops(int32 op, ...)
{
	switch (op) {
		case B_MODULE_INIT: {
			TRACE_MODULE("init\n");
			if (gUSBStack)
				return B_OK;

#ifdef HAIKU_TARGET_PLATFORM_BEOS
			// This code is to handle plain R5 (non-BONE) where the same module
			// gets loaded multiple times (once for each exported module
			// interface, the USB v2 and v3 API in our case). We don't want to
			// ever create multiple stacks however, so we "share" the same stack
			// for both modules by storing it's address in a shared area.
			void *address = NULL;
			area_id shared = find_area("shared usb stack");
			if (shared >= B_OK && clone_area("usb stack clone", &address,
				B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, shared) >= B_OK) {
				gUSBStack = *((Stack **)address);
				TRACE_MODULE("found shared stack at %p\n", gUSBStack);
				return B_OK;
			}
#endif

#ifdef TRACE_USB
			set_dprintf_enabled(true);
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
			load_driver_symbols("usb");
#endif
#endif
			Stack *stack = new(std::nothrow) Stack();
			TRACE_MODULE("usb_module: stack created %p\n", stack);
			if (!stack)
				return B_NO_MEMORY;

			if (stack->InitCheck() != B_OK) {
				delete stack;
				return ENODEV;
			}

			gUSBStack = stack;

#ifdef HAIKU_TARGET_PLATFORM_HAIKU
			add_debugger_command("get_usb_pipe_for_id",
				&debug_get_pipe_for_id,
				"Gets the config for a USB pipe");
#elif HAIKU_TARGET_PLATFORM_BEOS
			// Plain R5 workaround, see comment above.
			shared = create_area("shared usb stack", &address,
				B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_NO_LOCK,
				B_KERNEL_WRITE_AREA);
			if (shared >= B_OK)
				*((Stack **)address) = gUSBStack;
#endif
			break;
		}

		case B_MODULE_UNINIT:
			TRACE_MODULE("uninit\n");
			delete gUSBStack;
			gUSBStack = NULL;

#ifdef HAIKU_TARGET_PLATFORM_HAIKU
			remove_debugger_command("get_usb_pipe_for_id",
				&debug_get_pipe_for_id);
#endif
			break;

		default:
			return EINVAL;
	}

	return B_OK;
}
Exemplo n.º 21
0
status_t
OHCIRootHub::ProcessTransfer(OHCI *ohci, Transfer *transfer)
{
	if ((transfer->TransferPipe()->Type() & USB_OBJECT_CONTROL_PIPE) == 0)
		return B_ERROR;

	usb_request_data *request = transfer->RequestData();
	TRACE_MODULE("request: %d\n", request->Request);

	status_t status = B_TIMED_OUT;
	size_t actualLength = 0;
	switch (request->Request) {
		case USB_REQUEST_GET_STATUS: {
			if (request->Index == 0) {
				// get hub status
				actualLength = MIN(sizeof(usb_port_status),
					transfer->DataLength());
				// the hub reports whether the local power failed (bit 0)
				// and if there is a over-current condition (bit 1).
				// everything as 0 means all is ok.
				memset(transfer->Data(), 0, actualLength);
				status = B_OK;
				break;
			}

			usb_port_status portStatus;
			if (ohci->GetPortStatus(request->Index - 1, &portStatus) >= B_OK) {
				actualLength = MIN(sizeof(usb_port_status), transfer->DataLength());
				memcpy(transfer->Data(), (void *)&portStatus, actualLength);
				status = B_OK;
			}

			break;
		}

		case USB_REQUEST_SET_ADDRESS:
			if (request->Value >= 128) {
				status = B_TIMED_OUT;
				break;
			}

			TRACE_MODULE("set address: %d\n", request->Value);
			status = B_OK;
			break;

		case USB_REQUEST_GET_DESCRIPTOR:
			TRACE_MODULE("get descriptor: %d\n", request->Value >> 8);

			switch (request->Value >> 8) {
				case USB_DESCRIPTOR_DEVICE: {
					actualLength = MIN(sizeof(usb_device_descriptor),
						transfer->DataLength());
					memcpy(transfer->Data(), (void *)&sOHCIRootHubDevice,
						actualLength);
					status = B_OK;
					break;
				}

				case USB_DESCRIPTOR_CONFIGURATION: {
					actualLength = MIN(sizeof(ohci_root_hub_configuration_s),
						transfer->DataLength());
					sOHCIRootHubConfig.hub.num_ports = ohci->PortCount();
					memcpy(transfer->Data(), (void *)&sOHCIRootHubConfig,
						actualLength);
					status = B_OK;
					break;
				}

				case USB_DESCRIPTOR_STRING: {
					uint8 index = request->Value & 0x00ff;
					if (index > 2)
						break;

					actualLength = MIN(sOHCIRootHubStrings[index].length,
						transfer->DataLength());
					memcpy(transfer->Data(), (void *)&sOHCIRootHubStrings[index],
						actualLength);
					status = B_OK;
					break;
				}

				case USB_DESCRIPTOR_HUB: {
					actualLength = MIN(sizeof(usb_hub_descriptor),
						transfer->DataLength());
					sOHCIRootHubConfig.hub.num_ports = ohci->PortCount();
					memcpy(transfer->Data(), (void *)&sOHCIRootHubConfig.hub,
						actualLength);
					status = B_OK;
					break;
				}
			}
			break;

		case USB_REQUEST_SET_CONFIGURATION:
			status = B_OK;
			break;

		case USB_REQUEST_CLEAR_FEATURE: {
			if (request->Index == 0) {
				// we don't support any hub changes
				TRACE_MODULE_ERROR("clear feature: no hub changes\n");
				break;
			}

			TRACE_MODULE("clear feature: %d\n", request->Value);
			if (ohci->ClearPortFeature(request->Index - 1, request->Value) >= B_OK)
				status = B_OK;
			break;
		}

		case USB_REQUEST_SET_FEATURE: {
			if (request->Index == 0) {
				// we don't support any hub changes
				TRACE_MODULE_ERROR("set feature: no hub changes\n");
				break;
			}

			TRACE_MODULE("set feature: %d\n", request->Value);
			if (ohci->SetPortFeature(request->Index - 1, request->Value) >= B_OK)
				status = B_OK;
			break;
		}
	}

	transfer->Finished(status, actualLength);
	delete transfer;
	return B_OK;
}