I have a custom multi-function device hanging off an LPC bus. Works fine with hardcoded addresses in a force-loaded kernel module, but longer-term I'd like to move towards per-function modules (there are about ten miscellaneous functions in there).
The recommended way seems to be to create a module that checks if the hardware is there and has the right version, then creates device tree entries for the functions, causing hot-plug events for the subunits.
Does this work on x86_64?
Does that give me any advantage over a single force-loaded module, given that I still need to load the detection module?
Does it make sense to instead create an ACPI table describing the device, and pass that to the kernel from the BIOS?
Related
I have a special disk image format (compressed and with extra information such as bad blocks) and would like to make that available as a block device (e.g. under /dev/rdisk) in macOS.
I am looking for pointers on how to write a read-only block level userspace driver.
I believe I need to do this with IOKit, but the docs are quite sparse in that area, and provide no sample code for this as far as I can tell.
I've had a look at Amit Singh's Mac OS Internals, but that only goes about filerting existing blocks that get routed through the added driver. But I need to read the data from a separate file, i.e. I need to use the file system, and I also want to do this in a userspace app if possible because making a kext is both hard to debug and is getting deprecated now, too.
Ideally, this should work on current macOS versions, including 10.15, but I'd also be happy with a solution that only works on older macOS versions, starting at 10.6.
Maybe I am still misunderstanding some things here. I was under the impression that it was possible even before 10.15 to write userspace IOKit drivers. But maybe that's not possible with Block Storage devices? Any clarifications would be welcome. I feel quite lost.
Update June 22, 2020
I also asked the question on the OSXFUSE support forum, and got a negative reply there.
Maybe I am still misunderstanding some things here. I was under the impression that it was possible even before 10.15 to write userspace IOKit drivers.
This is a true statement, but it does not mean it's possible to write all types of drivers in userspace, even with 10.15. The confusion likely stems from the fact that "IOKit" is used to mean subtly different things in different contexts:
Fundamentally, it is the OOP-based driver stack technology which is built into the XNU kernel (macOS, iOS, etc.), written in C++. Its core data structure is the I/O Kit registry, which is a directed graph of objects representing devices, device (sub-)functions, virtual device, service, drivers, user space client connections, etc. (most of it has properties of it, but nodes can technically have multiple "parent" nodes, and some actually do so on your typical Mac system)
The IOKit user space libraries. (a.k.a. IOKit.framework a.k.a. IOKitLib + various IOCFPlugins) These provide a view of the kernel's I/O Registry to user space programs, and allow them to perform certain interactions with IOKit objects. This is essentially limited to:
Iterating over the registry graph and matching services based on matching rules. Both return handles to specific I/O Registry entries to the user space program.
Getting properties on I/O Registry entries, and if the object explicitly supports it, setting (some) properties.
Creating a user client connection. This is the only way to create an entry in the I/O Registry from regular user space, and these are always IOUserClient subclasses, and only if the parent object specfically permits it.
The IOKit view available to DriverKit based System Extension processes (new in 10.15), which allows instantiation of entirely user space backed registry entry objects, for subclassing a (bounded) selection of super class types.
To answer the question of your specific case:
To implement a driver for a block storage device which will appear to the system as any other, you need to subclass IOStorage or one of its subclasses (typically IOBlockStorageDevice).
IOKit.framework allows you to create user space drivers which will only be used by that user space process or other user space processes. It is therefore not possible to use it to create drivers that will be used by some part of the kernel. For example, it is not possible to create a block device driver which will be used by the kernel's VFS system.
DriverKit currently (as of macOS 10.15.4 SDK) does not allow dext-backed subclasses of any of the storage stack's classes. So a dext will not solve the problem.
The only way to do what you're trying to do, as far as I'm aware, is to have a 2-part driver: a kext implementing an IOBlockStorageDevice subclass, as well as a service which offers a user client interface for some user space process to connect to for creating instances of block devices, and which will handle the I/O requests for the device. This is a sort of analog to the FUSE mechanism which works at the VFS layer instead of the block layer.This is exactly how macOS's built-in disk image mounting system works. Unfortunately, neither the kext nor user space parts of this are open source, documented, or a public API. So unless you reverse engineer it and find a boundary which doesn't enforce the requirement of an Apple code signature, you basically have to reimplement this.
I'm not currently aware of an existing open source system that does this, but I haven't looked very hard. Especially for read-only access, it shouldn't be terribly hard to do if you know what you're doing, but it comes with the usual downsides of developing and distributing kexts.
Note that you could also use FUSE to open your disk image if the block device it represents hosts a file system you wish to mount, and a FUSE implementation for that file system exists.
This might be obvious for some but not to me so I'll ask =)
I'm having an issue that I have build an embedded Linux stack for some piece of hardware (NVidia TX2 + ConnectTech Astro carrier). I use a PCIe card from EPIX
If I use Ubuntu's official distribution for tegra, the PCIe card is properly detected.
With identical kernel and device tree blob, and the same HW unit, the detection fails with embedded Linux.
I thought that detecting PCIe devices would be kernel's job and not be influence by the distro, unless the drivers are built as kernel modules and inserted at different times. But in my case they are build in kernel.
Could someone elaborate why the detection would work with one distro but not the order?
Here is a link to what I tried to do to fix the detection
tx2-pcie-does-not-detect-endpoint-on-connecttech-carrier-board
Thanks!
A Linux distribution contains a kernel that usually differs from the vanilla kernel of the same release. Most of the time a distribution kernel contains lots of back ports of bug fixes that were discovered and fixed later in micro releases. There may be other features that a specific vendor includes and the vanilla kernel does not, like more recent version of certain drivers, etc. What makes this even more confusing is that sets of these back ports are often different in distributions from different vendors. As a side effect, this makes it difficult to depend on something like KERNEL_VERSION() macro in custom kernel code or in custom device drivers.
I can't say about the specific issue that you're having. The topic is pretty generic, and I hope that this explanation helps.
I have a Linux kernel module that implements a character device driver. I've read through Linux Device Drivers and followed several tutorials. At this point, I have a simple module that provides open, release, and write file operations.
I'm trying to use the Generic DMA Layer to create a streaming DMA mapping. I'm confused by the following excerpt from LDD:
Many of the functions below require a struct device. This structure
is the low-level representation of a device within the Linux device
model. It is not something that drivers often have to work with
directly, but you do need ot when using the generic DMA layer.
Usually, you can find this structure buried inside the bus specific
that describes your device. For example, it can be found as the dev
field in struct pci_device or struct usb_device.
I read further into the Linux device model, and encountered the following:
At the lowest level, every device in a Linux system is represented by
an instance of struct device.
How can I get the struct device for my character device? Is there one being created for me behind the scenes, or do I need to create it?
I tried manually creating a class with class_create() and then using that to create a device with device_create(), but when I used that device to set up DMA mappings I think I just got a bogus address. Is this the correct approach?
For a little bit more information about my platform, I'm working on the Altera SoCFPGA platform (ARM), so my device isn't a true hardware device like a USB or PCI device, but rather logic implemented in an FPGA.
I found a lot of info in Chapter 14 of LDD that I think may be relevant (buses, devices, drivers, etc.), but I'm just not sure when or how to use it. To me, it seems like that chapter is discussing a lot of data structures that all devices and drivers use, but I'm confused because I haven't had to make use of any of it.
I ended up creating a platform driver and platform device. The platform device struct has it's own struct device associated with the platform bus, which is a 'pseudo-bus' designed exactly for things like this. The official documentation for platform drivers was helpful here.
In the end, my module ended up implementing both a platform driver and a character device driver. The part that gave me the most trouble was creating a platform device and associating it with my platform driver. I started by just manually creating the device (at module install time) with platform_device_alloc and platform_device_register. Once I had this working I ended up removing the manual device creation and instead relying on a device tree entry to create my device.
It depends. In one cases you may get device created by core, in other you have to do that. (I think you are at first group)
Device pointer you are using for DMA should represent the device which does actual DMA in hardware. So, your approach is wrong there.
It might be good to pre-order LDD4.
I ran into exactly this as well. This is hardly a complete answer, but it seems that the underlying assumption in most of these docs is that basic character devices (that aren't instantiated by some higher-level bus driver etc.) won't need access to DMA. I found another shortcut to get what I needed without a struct device, but it looked like you could create your own device using device_register() or similar.
It is maybe a six years old the answer, but because you are doing your own driver, you could later use the function device_create from Linux header include/linux/device.h to create dynamically not only your device in /dev/ folder, but it would also return a pointer to a struct device that you can use later on in the creation of a DMA mapping as the book suggest.
I found particular useful this video in case that the information of the book is not enough to get the variables that you need for the device_create function. How to create a Linux Character Driver
How would I go about creating a "gamepad" which appears to DirectInput applications as a normal game controller but the state of its controls is actually defined by software?
Write a device driver to pretend to be one.
Specifically, Windows device drivers handle what are called Interrupt Requests via the Interrupt Request Protocol - which boils down to a wrapped up structure and a set of buffers internally in the driver.
Now the next thing you need to know is that many drivers are actually layered, or stacked, or whichever name you want to use. So for example to write a disk driver, you might interface with the driver above it (as a disk class) but use a driver below it (scsi port, for example) to actually send commands to your devices.
That's how real devices work. Fake devices need to conform to the top level interface requirements, e.g. a disk, or a controller, or a mouse, or whatever it is. However, underneath they can do anything they like - return whatever values they like.
This opens up the possibility of controlling a driver via a user-mode application and pretending to "be" a device. To send a driver messages, you can DeviceIoControl to it; then to actually get those messages you can either:
Stuff them in the Irp that makes up that DeviceIoControl.
Have the driver read them out of your process' memory space.
Drivers can also access \\Registry\\Machine and various other, non-user-specific non-explorer registry areas, so it is possible to communicate that way.
Finally, there's no saying you can't filter existing IO, rather than make it all up via a new device. There are a great many options and ways you can go about doing this.
If you're going to do this, you'll need:
VirtualKD or an expensive debugger cable and two PCs.
You probably also want to start with the references on this blog post. You'll find that there are essentially a bazillion different names for driver code, so I'll interpret some of them:
WDM = Windows Driver Model, basically the NT driver model mixed with (some of) Windows 9x.
KMDF = Kernel mode driver framework - drivers of the above type use this, plus additionally WDF (Windows Driver Foundation) which is a set of libraries on top of WDM to make it quicker to use.
UMDF = User mode driver framework - write a driver without the danger of kernel mode. If you can, use this, as kernel mode drivers that go wrong will bluescreen (in driver parlance, bugcheck) your system.
Edit: I'm not massively knowledgeable on DirectInput - there may be a way to override the various API controls in use via DLL redirection and the like, which may be simpler than the way I've described.
There is vJoy opensource project: http://sourceforge.net/projects/vjoystick/ - can be worth looking at.
The easiest solution may be to emulate an XInput device (Xbox 360 and One). These are supported in most modern games and the set up is very simple. Here is a C++ project here that provides this without any installed drivers or external dependencies: https://github.com/shauleiz/vXboxInterface/
I know it is an old question but for anyone which is interested in this topic it is also worth looking at this project called ViGEm.
You can emulate some well known gamepads like Microsoft Xbox 360 Controller, Sony DualShock 4 Controller and Microsoft Xbox One Controller. The project offers also some API to interact with these virtual controllers. E.g. the C# API can be found here
The simplest solution I found was using vJoy and its C# wrapper.
You need to download the vJoy driver from here.
You can use the vJoy SDK for implementing a feeder program: https://github.com/njz3/vJoy/tree/master/SDK/c%23
Use the C# starter project for this, or simply add the two .dll-s to your existing project as references from the x86 or x64 folder.
You can find instructions on how to use the api in the readme.odt file.
I know this probably is not the easiest thing to do, but I am trying to connect Microcontroller and PC using USB. I dont want to use internal USART of Microcontroller or USB to RS232 converted, its project indended to help me understand various principles.
So, getting the communication done from the Microcontroller side is piece of cake - I mean, when I know he protocol, its relativelly easy to implement it on Micro, becouse I am in direct control of evrything, even precise timing.
But this is not the case of PC. I am not very familiar with concept of Windows handling the devices connected. In one of my previous question I ask about how Windows works with devices thru drivers. I understood that for internal use of Windows, drivers must have some default set of functions available to OS. I mean, when OS wants to access HDD, it calls HDD driver (which is probably internal in OS), with specific "questions" so that means that HDD driver has to be written to cooperate with Windows, to have write function in the proper place to be called by the OS. Something similiar is for GPU, Even DirectX, I mean DirectX must call specific functions from drivers, so drivers must be written to work with DX. I know, many functions from WinAPI works on their own, but even "simple" window must be in the end written into framebuffer, using MMIO to adress specified by drivers. Am I right?
So, I expected that Windows have internal functions, parts of WinAPI designed to work with certain comonly used things. To call manufacturer-designed drivers. But this seems to not be entirely true becouse Windows has no way to communicate thru Paralel port. I mean, there is no function in the WinAPI to work with serial port, but there are funcions to work with HDD,GPU and so.
But now there comes the part I am getting very lost at. So, I think Windows must have some built-in functions to communicate thru USB, becouse for example it handles USB flash memory. So, is there any WinAPI function designed to let user to operate USB thru that function, or when I want to use USB myself, do I have to call desired USB-driver function myself? Becouse all you need to send to USB controller is device adress and the infromation right? I mean, I don´t have to write any new drivers, am I right? Just to call WinAPI function if there is such, or directly call original USB driver. Does any of this make some sense?
To make your life easier, and avoid writing your own driver, try using the HID (Human Interface Device) API on top of USB. Although it says "Human Interface", it doesn't actually have to be for devices that a human controls. The advantage is that modern OSes already come with a HID driver and you can use sample code such as what you can find here to get started. Many microcontroller manufacturers provide suitable code for the embedded of the protocol.
Because OSes already understand HID, if you build a device using the HID interface you'll find that not only can you read from it from any OS, you may also find that many applications can already talk to your device if its communication is restricted to a small enough subset of HID. (For example, I built an input device for a music app, but amazingly I found I could literally plug it straight into a 3D animation app we use at work, running on a different OS, and have it work right away without writing a single additional line of code!)
This answer might aim you in the right direction.
The first answer here might also be helpful.
The answers to this have some actual code and links to yet other resources.
USB includes a set of stock functionality, much like supporting USB flash drives (USB Mass Storage class). The two most interesting for microcontroller interfacing are HID and CDC. CDC is easiest to use as it directly emulates an old fashioned serial port.
If you configure the microcontroller to act as a CDC device, Windows will enumerate it as a serial port, and all the old serial APIs will work on it.