Example #1
0
status_t
device_node::_GetNextDriverPath(void*& cookie, KPath& _path)
{
	Stack<KPath*>* stack = NULL;

	if (cookie == NULL) {
		// find all paths and add them
		stack = new(std::nothrow) Stack<KPath*>();
		if (stack == NULL)
			return B_NO_MEMORY;

		StackDeleter<KPath*> stackDeleter(stack);

		bool generic = false;
		uint16 type = 0;
		uint16 subType = 0;
		uint16 interface = 0;
		if (get_attr_uint16(this, B_DEVICE_TYPE, &type, false) != B_OK
			|| get_attr_uint16(this, B_DEVICE_SUB_TYPE, &subType, false)
					!= B_OK)
			generic = true;

		get_attr_uint16(this, B_DEVICE_INTERFACE, &interface, false);

		// TODO: maybe make this extendible via settings file?
		switch (type) {
			case PCI_mass_storage:
				switch (subType) {
					case PCI_scsi:
						_AddPath(*stack, "busses", "scsi");
						_AddPath(*stack, "busses", "virtio");
						break;
					case PCI_ide:
						_AddPath(*stack, "busses", "ata");
						_AddPath(*stack, "busses", "ide");
						break;
					case PCI_sata:
						// TODO: check for ahci interface
						_AddPath(*stack, "busses", "scsi");
						_AddPath(*stack, "busses", "ata");
						_AddPath(*stack, "busses", "ide");
						break;
					default:
						_AddPath(*stack, "busses");
						break;
				}
				break;
			case PCI_serial_bus:
				switch (subType) {
					case PCI_firewire:
						_AddPath(*stack, "busses", "firewire");
						break;
					case PCI_usb:
						_AddPath(*stack, "busses", "usb");
						break;
					default:
						_AddPath(*stack, "busses");
						break;
				}
				break;
			case PCI_network:
				_AddPath(*stack, "drivers", "net");
				_AddPath(*stack, "busses", "virtio");
				break;
			case PCI_display:
				_AddPath(*stack, "drivers", "graphics");
				break;
			case PCI_multimedia:
				switch (subType) {
					case PCI_audio:
					case PCI_hd_audio:
						_AddPath(*stack, "drivers", "audio");
						break;
					case PCI_video:
						_AddPath(*stack, "drivers", "video");
						break;
					default:
						_AddPath(*stack, "drivers");
						break;
				}
				break;
			default:
				if (sRootNode == this) {
					_AddPath(*stack, "busses/pci");
					_AddPath(*stack, "bus_managers");
				} else if (!generic) {
					_AddPath(*stack, "busses", "virtio");
					_AddPath(*stack, "drivers");
				} else {
					// For generic drivers, we only allow busses when the
					// request is more specified
					if (sGenericContextPath != NULL
						&& (!strcmp(sGenericContextPath, "disk")
							|| !strcmp(sGenericContextPath, "ports")
							|| !strcmp(sGenericContextPath, "bus"))) {
						_AddPath(*stack, "busses");
					}
					_AddPath(*stack, "drivers", sGenericContextPath);
					_AddPath(*stack, "busses/scsi");
					_AddPath(*stack, "busses/random");
				}
				break;
		}

		stackDeleter.Detach();

		cookie = (void*)stack;
	} else
		stack = static_cast<Stack<KPath*>*>(cookie);

	KPath* path;
	if (stack->Pop(&path)) {
		_path.Adopt(*path);
		delete path;
		return B_OK;
	}

	delete stack;
	return B_ENTRY_NOT_FOUND;
}