Bind a homemade char driver with an existing device

krystalkarma06

New Member
Joined
Apr 11, 2024
Messages
3
Reaction score
2
Credits
84
Hello Anyone,

I'm now aware of my own ignorance regarding the implementation of a new char driver that would replace an existing driver. Can somedy help me understand what is wrong in the process ?

From A ubuntu 18.04, kernel 4.15.0-213-generic, I plug a transcend device which can be seen from url https://fr.rs-online.com/web/p/lecteurs-de-cartes/1863398.

When I plug it, three devices appears in /dev : sdb, sdc and sdd, relative to the three different devices that can be plugged through the transcend device.

/dev/sdb is detected as a block and is accessed through a block driver, with major 8:16. Command "udevadm info -a /dev/sdb" gives the following information:
looking at device '/devices/pci0000:00/0000:00:0b.0/usb1/1-1/1-1:1.0/host3/target3:0:0/3:0:0:0/block/sdb':
KERNEL=="sdb"
SUBSYSTEM=="block"
DRIVER==""
ATTR{alignment_offset}=="0"
ATTR{capability}=="51"
ATTR{discard_alignment}=="0"
ATTR{events}=="media_change"
ATTR{events_async}==""
ATTR{events_poll_msecs}=="-1"
ATTR{ext_range}=="256"
ATTR{hidden}=="0"
ATTR{inflight}==" 0 0"
ATTR{range}=="16"
ATTR{removable}=="1"
ATTR{ro}=="0"
ATTR{size}=="31717728"
ATTR{stat}==" 47 0 2144 1176 0 0 0 0 0 876 1176"

looking at parent device '/devices/pci0000:00/0000:00:0b.0/usb1/1-1/1-1:1.0/host3/target3:0:0/3:0:0:0':
KERNELS=="3:0:0:0"
SUBSYSTEMS=="scsi"
DRIVERS=="sd"
ATTRS{blacklist}=="FORCELUN"
ATTRS{device_blocked}=="0"
ATTRS{device_busy}=="0"
ATTRS{dh_state}=="detached"
ATTRS{eh_timeout}=="10"
ATTRS{evt_capacity_change_reported}=="0"
ATTRS{evt_inquiry_change_reported}=="0"
ATTRS{evt_lun_change_reported}=="0"
ATTRS{evt_media_change}=="0"
ATTRS{evt_mode_parameter_change_reported}=="0"
ATTRS{evt_soft_threshold_reached}=="0"
ATTRS{inquiry}==""
ATTRS{iocounterbits}=="32"
ATTRS{iodone_cnt}=="0x2c8"
ATTRS{ioerr_cnt}=="0x2"
ATTRS{iorequest_cnt}=="0x2c8"
ATTRS{max_sectors}=="240"
ATTRS{model}=="CF Transcend "
ATTRS{queue_depth}=="1"
ATTRS{queue_type}=="none"
ATTRS{rev}=="TS2A"
ATTRS{scsi_level}=="7"
ATTRS{state}=="running"
ATTRS{timeout}=="30"
ATTRS{type}=="0"
ATTRS{vendor}=="TS-RDF8 "

looking at parent device '/devices/pci0000:00/0000:00:0b.0/usb1/1-1/1-1:1.0/host3/target3:0:0':
KERNELS=="target3:0:0"
SUBSYSTEMS=="scsi"
DRIVERS==""

looking at parent device '/devices/pci0000:00/0000:00:0b.0/usb1/1-1/1-1:1.0/host3':
KERNELS=="host3"
SUBSYSTEMS=="scsi"
DRIVERS==""

looking at parent device '/devices/pci0000:00/0000:00:0b.0/usb1/1-1/1-1:1.0':
KERNELS=="1-1:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="usb-storage"
ATTRS{authorized}=="1"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceClass}=="08"
ATTRS{bInterfaceNumber}=="00"
ATTRS{bInterfaceProtocol}=="50"
ATTRS{bInterfaceSubClass}=="06"
ATTRS{bNumEndpoints}=="02"
ATTRS{supports_autosuspend}=="1"

looking at parent device '/devices/pci0000:00/0000:00:0b.0/usb1/1-1':
KERNELS=="1-1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="00"
ATTRS{bDeviceProtocol}=="00"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{bMaxPower}=="500mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="002a"
ATTRS{bmAttributes}=="80"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="8"
ATTRS{devpath}=="1"
ATTRS{idProduct}=="4000"
ATTRS{idVendor}=="8564"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="TS-RDF8 "
ATTRS{maxchild}=="0"
ATTRS{product}=="Transcend "
ATTRS{quirks}=="0x0"
ATTRS{removable}=="unknown"
ATTRS{serial}=="000000079"
ATTRS{speed}=="480"
ATTRS{urbnum}=="6387"
ATTRS{version}==" 2.10"

looking at parent device '/devices/pci0000:00/0000:00:0b.0/usb1':
KERNELS=="usb1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{authorized_default}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="09"
ATTRS{bDeviceProtocol}=="00"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{bMaxPower}=="0mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0415"
ATTRS{bmAttributes}=="e0"
ATTRS{busnum}=="1"
ATTRS{configuration}==""
ATTRS{devnum}=="1"
ATTRS{devpath}=="0"
ATTRS{idProduct}=="0002"
ATTRS{idVendor}=="1d6b"
ATTRS{interface_authorized_default}=="1"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Linux 4.15.0-213-generic ehci_hcd"
ATTRS{maxchild}=="12"
ATTRS{product}=="EHCI Host Controller"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="unknown"
ATTRS{serial}=="0000:00:0b.0"
ATTRS{speed}=="480"
ATTRS{urbnum}=="189"
ATTRS{version}==" 2.00"

looking at parent device '/devices/pci0000:00/0000:00:0b.0':
KERNELS=="0000:00:0b.0"
SUBSYSTEMS=="pci"
DRIVERS=="ehci-pci"
ATTRS{broken_parity_status}=="0"
ATTRS{class}=="0x0c0320"
ATTRS{companion}==""
ATTRS{consistent_dma_mask_bits}=="32"
ATTRS{d3cold_allowed}=="0"
ATTRS{device}=="0x265c"
ATTRS{dma_mask_bits}=="32"
ATTRS{driver_override}=="(null)"
ATTRS{enable}=="1"
ATTRS{irq}=="19"
ATTRS{local_cpulist}=="0"
ATTRS{local_cpus}=="1"
ATTRS{msi_bus}=="1"
ATTRS{numa_node}=="-1"
ATTRS{revision}=="0x00"
ATTRS{subsystem_device}=="0x0000"
ATTRS{subsystem_vendor}=="0x0000"
ATTRS{uframe_periodic_max}=="100"
ATTRS{vendor}=="0x8086"

looking at parent device '/devices/pci0000:00':
KERNELS=="pci0000:00"
SUBSYSTEMS==""
DRIVERS==""
Ok, the device is the following : /devices/pci0000:00/0000:00:0b.0/usb1/1-1/1-1:1.0/host3/target3:0:0/3:0:0:0 and we see that the driver is "sd". But I don't want the device to be recognized as a block device and use this driver, I want it to be recognized as a char device and use a homemade char driver to that purpose. First I develop a simple car driver with major / minor 440:1 and the thing is I want to bind it to the device. So I supposed I had to unbind the block driver and bind the new driver (not a big deal), but after registering a new char driver (I see it appear in the /proc/devices section with the good major number), I don't know how to bind it to the transcend device.

Does anydoby can explain me what I'm missing please ?

Thank you.
Greetings.
 
Last edited:


Maybe try renaming the device and see if that helps it to be seen as a char device.

IF it doesn't use the char driver that you want it to use you may have to blacklist the driver of the original device in order for it to comply.
I could be wrong, however....it's more likely that the transcend device is competing with the driver for the block device.

In order for a device to bind successfully with a driver, that driver must already support that device. This is why you can not just arbitrarily bind any device to any driver.

To bind a device to a driver, the device must first not be controlled by any other driver. To ensure this, look for the "driver" symlink in the device directory:

 
Good info here too:


Here's an article I wrote to assist with renaming a device.
 
Maybe try renaming the device and see if that helps it to be seen as a char device.

IF it doesn't use the char driver that you want it to use you may have to blacklist the driver of the original device in order for it to comply.
I could be wrong, however....it's more likely that the transcend device is competing with the driver for the block device.

In order for a device to bind successfully with a driver, that driver must already support that device. This is why you can not just arbitrarily bind any device to any driver.

To bind a device to a driver, the device must first not be controlled by any other driver. To ensure this, look for the "driver" symlink in the device directory:


thanks. Eventually, Renaming the device is not helpful.
The point is that, once a specific driver is bounded to the device, I first need to unbind it. Things are easy with udev rules.
After that, I need to access the to parent of the struct device that is related to the device itself. Once I get the parent, I can properly register a new device, and bind it to the new driver.

The biggest difficulty is to get the parent of the device as seen when the hotplug occurs. In the previous post, this is devices/pci0000:00/0000:00:0b.0/usb1/1-1/1-1:1.0/host3/target3:0:0/3:0:0:0. I can't find in the kernel any helful function to get a device from its name or the bus number ...

Does somebody know how to do that ?

Thanks.
 
Try running this command with root privileges.

Code:
cat /sys/kernel/debug/usb/devices


There are a lot of developers that hang out on Git Hub maybe have a look there.

Also our Moderator @KGIII is on the Lubuntu Team he may know a way around the issue you are having.

We also have a Open Suse dev here, sorry, I'm not recalling his name at the moment.
 
@krystalkarma06 wrote in post #1:
First I develop a simple car driver with major / minor 440:1 and the thing is I want to bind it to the device. So I supposed I had to unbind the block driver and bind the new driver (not a big deal), but after registering a new char driver (I see it appear in the /proc/devices section with the good major number), I don't know how to bind it to the transcend device.
I take it from this quote that "car driver' is a typo and is really "card driver"

The Transcend device that has been plugged in, is a usb card reader, which is a block device. When it's plugged in to a computer, the kernel creates a block device for each port in which a card can be inserted, e.g. /dev/sda, /dev/sdb etc.

When a card is plugged into the card reader, normally one mounts the card somewhere into the filesystem of the installation, and accesses it as a file. More exactly, mounts a partition from the card. As a file it can have all the functions normally available to manipulate files, e.g. read, write, delete, link etc. all involving character device functions. The file is not itself a character device.

I wonder why you would need a "card driver" to read/write characters on a mounted file, or is there some other process that you are wanting to execute?

The character devices on the system can be seen at: /sys/dev/char, and are typically the mouse, keyboard, serial devices, terminals etc.

As an example of a usb character device, a usb modem will be seen as a character device by the kernel, but they are not given a device name in /dev, rather they are given an interface name like wlp0s20... which can be seen with the ip command. In any case though, they are not plugged into card readers.

My curiosity is: what is it that you are plugging into the card reader that needs a "card driver"?
 
Last edited:
@krystalkarma06 wrote in post #1:

I take it from this quote that "car driver' is a typo and is really "card driver"

The Transcend device that has been plugged in, is a usb card reader, which is a block device. When it's plugged in to a computer, the kernel creates a block device for each port in which a card can be inserted, e.g. /dev/sda, /dev/sdb etc.

When a card is plugged into the card reader, normally one mounts the card somewhere into the filesystem of the installation, and accesses it as a file. More exactly, mounts a partition from the card. As a file it can have all the functions normally available to manipulate files, e.g. read, write, delete, link etc. all involving character device functions. The file is not itself a character device.

I wonder why you would need a "card driver" to read/write characters on a mounted file, or is there some other process that you are wanting to execute?

The character devices on the system can be seen at: /sys/dev/char, and are typically the mouse, keyboard, serial devices, terminals etc.

As an example of a usb character device, a usb modem will be seen as a character device by the kernel, but they are not given a device name in /dev, rather they are given an interface name like wlp0s20... which can be seen with the ip command. In any case though, they are not plugged into card readers.

My curiosity is: what is it that you are plugging into the card reader that needs a "card driver"?
Actually, I wanted to write "char driver".

What I actually mean is: When I plugged the transcent, Linux automatically determines it as a block device, and creates three nodes /dev/sd[b,c,d]. The driver associated is the sd driver, so a block driver. What if I don't want the system to associate this particular device with a block driver, but I want to use it with a char driver. Is it possible to do so ? Maybe my understanding of the drivers are wrong.

Let's suppose on the other hand I want the device to be recognized as a block device, but I want to use another block driver. I have to register this new driver, but how am I supposed to do that ?

Many thanks, the already posted comments are really helpful.
 

Staff online

Members online


Latest posts

Top