/* This file is part of Fennix Kernel. Fennix Kernel is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Fennix Kernel is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Fennix Kernel. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include "../../kernel.h" using namespace vfs; namespace Driver { dev_t Manager::RegisterDevice(dev_t DriverID, DeviceType Type, const InodeOperations *Operations) { std::unordered_map &drivers = DriverManager->GetDrivers(); const auto it = drivers.find(DriverID); if (it == drivers.end()) ReturnLogError(-EINVAL, "Driver %d not found", DriverID); const Driver::DriverObject *drv = &it->second; auto dop = drv->DeviceOperations; for (size_t i = 0; i < 128; i++) { const auto dOps = dop->find(i); const auto dOpsEnd = dop->end(); if (dOps != dOpsEnd) continue; DeviceType devType = (DeviceType)(Type & DEVICE_TYPE_MASK); switch (devType) { case DEVICE_TYPE_INPUT: { std::string prefix = "event"; for (size_t j = 0; j < 128; j++) { std::string deviceName = prefix + std::to_string(j); Node node = fs->Lookup(devInputNode, deviceName); if (node) continue; /* c rwx r-- r-- */ mode_t mode = S_IRWXU | S_IRGRP | S_IROTH | S_IFCHR; node = fs->Create(devInputNode, deviceName, mode); node->inode->SetDevice(DriverID, i); DriverHandlers dh{}; dh.Ops = Operations; dh.Node = node->inode; dh.InputReports = new RingBuffer(16); dop->insert({i, std::move(dh)}); return i; } ReturnLogError(-EOVERFLOW, "No available slots for device %d", DriverID); } default: ReturnLogError(-EINVAL, "Invalid device type %d", Type); } } ReturnLogError(-EOVERFLOW, "No available slots for device %d", DriverID); } dev_t Manager::CreateDeviceFile(dev_t DriverID, const char *name, mode_t mode, const InodeOperations *Operations) { std::unordered_map &drivers = DriverManager->GetDrivers(); const auto it = drivers.find(DriverID); if (it == drivers.end()) ReturnLogError(-EINVAL, "Driver %d not found", DriverID); const Driver::DriverObject *drv = &it->second; auto dop = drv->DeviceOperations; for (size_t i = 0; i < 128; i++) { const auto dOps = dop->find(i); if (dOps != dop->end()) continue; eNode node = fs->Lookup(devNode, name); if (node == true) ReturnLogError(-EEXIST, "Device file %s already exists", name); node = fs->Create(devNode, name, mode); if (node == false) ReturnLogError(-node.Error, "Failed to create device file %s; %s", name, node.what()); node.Value->inode->SetDevice(DriverID, i); DriverHandlers dh{}; dh.Ops = Operations; dh.Node = node.Value->inode; dh.InputReports = new RingBuffer(16); dop->insert({i, std::move(dh)}); return i; } ReturnLogError(-EOVERFLOW, "No available slots for device %d", DriverID); } int Manager::UnregisterDevice(dev_t DriverID, dev_t Device) { std::unordered_map &drivers = DriverManager->GetDrivers(); const auto it = drivers.find(DriverID); if (it == drivers.end()) ReturnLogError(-EINVAL, "Driver %d not found", DriverID); const Driver::DriverObject *drv = &it->second; auto dop = drv->DeviceOperations; const auto dOps = dop->find(Device); if (dOps == dop->end()) ReturnLogError(-EINVAL, "Device %d not found", Device); dop->erase(dOps); fixme("remove eventX from /dev/input"); fixme("delete InputReports"); return 0; } dev_t Manager::RegisterBlockDevice(dev_t DriverID, struct BlockDevice *Device) { std::unordered_map &drivers = DriverManager->GetDrivers(); const auto it = drivers.find(DriverID); if (it == drivers.end()) ReturnLogError(-EINVAL, "Driver %d not found", DriverID); const Driver::DriverObject *drv = &it->second; auto dop = drv->DeviceOperations; std::string prefix = Device->Name; for (size_t j = 0; j < 128; j++) { std::string deviceName = prefix + std::to_string(j); Node node = fs->Lookup(devBlockNode, deviceName); if (node) continue; debug("Creating \"%s\"", deviceName.c_str()); /* b rwx --- --- */ mode_t mode = S_IRWXU | S_IFBLK; node = fs->Create(devBlockNode, deviceName, mode); node->inode->SetDevice(DriverID, j); auto devNode = (Manager::DeviceInode *)node->inode; devNode->Size = Device->Size; devNode->BlockSize = Device->BlockSize; devNode->Blocks = Device->BlockCount; devNode->inode.PrivateData = Device->PrivateData; DriverHandlers dh{}; dh.Ops = Device->Ops; dh.Node = node->inode; dop->insert({j, std::move(dh)}); debug("dh ops:%#lx node:%#lx %d", dh.Ops, dh.Node, j); return j; } ReturnLogError(-EOVERFLOW, "No available slots for device %d", DriverID); } int Manager::UnregisterBlockDevice(dev_t DriverID, dev_t DeviceID) { std::unordered_map &drivers = DriverManager->GetDrivers(); const auto it = drivers.find(DriverID); if (it == drivers.end()) ReturnLogError(-EINVAL, "Driver %d not found", DriverID); const Driver::DriverObject *drv = &it->second; auto dop = drv->DeviceOperations; const auto dOps = dop->find(DeviceID); if (dOps == dop->end()) ReturnLogError(-EINVAL, "Device %d not found", DeviceID); dop->erase(dOps); return 0; } void *Manager::AllocateMemory(dev_t DriverID, size_t Pages) { auto itr = Drivers.find(DriverID); assert(itr != Drivers.end()); void *ptr = itr->second.vma->RequestPages(Pages); memset(ptr, 0, FROM_PAGES(Pages)); return ptr; } void Manager::FreeMemory(dev_t DriverID, void *Pointer, size_t Pages) { auto itr = Drivers.find(DriverID); assert(itr != Drivers.end()); itr->second.vma->FreePages(Pointer, Pages); } int Manager::ReportInputEvent(dev_t DriverID, InputReport *Report) { std::unordered_map &drivers = DriverManager->GetDrivers(); const auto it = drivers.find(DriverID); if (it == drivers.end()) ReturnLogError(-EINVAL, "Driver %d not found", DriverID); const Driver::DriverObject *drv = &it->second; auto dop = drv->DeviceOperations; auto dOps = dop->find(Report->Device); if (dOps == dop->end()) ReturnLogError(-EINVAL, "Device %d not found", Report->Device); dOps->second.InputReports->Write(Report, 1); switch (Report->Type) { case INPUT_TYPE_KEYBOARD: { KeyboardReport *kReport = &Report->Keyboard; GlobalKeyboardInputReports.Write(kReport, 1); break; } case INPUT_TYPE_MOUSE: { MouseReport *mReport = &Report->Mouse; GlobalMouseInputReports.Write(mReport, 1); break; } default: assert(!"Invalid input type"); } return 0; } }