¿Cuándo se llama a la función de sonda en el controlador del dispositivo spi de Linux?
Me he vuelto loco con los archivos del dispositivo estos últimos dos días y me culpo por no saber mucho al respecto. Después de trabajar en ello durante unos días, finalmente pude ordenar el dispositivo. registro un poco. Resumámoslo tomando como ejemplo el registro del subdispositivo spi, para no olvidarlo.
Primero, tome el registro de un dispositivo spidev como ejemplo:
static struct spi_board_info imx5_spi_printer_device[] __initdata =
{
{
p>
.modalias = "spidev",
.max_speed_hz = 8000000,
.bus_num = 1,
. chip_select = 1,
p>
.mode = SPI_MODE_0,
},
}; spi_register_board_info(imx5_spi_printer_device, ARRAY_SIZE(imx5_spi_printer_device));
Agregue la estructura anterior spi_board_info al archivo mx5_loco.c. Modalias debe especificar un controlador existente. En cuanto a bus_num y chip_select, si no sabe qué es bus_num, puede hacerlo. imprímalo en su controlador principal. Bus_num aquí debe ser coherente con el bus_num de la clase principal; de lo contrario, no se podrá generar el archivo del dispositivo. Si spi no tiene señal de reloj, es probable que bus_num esté incorrecto.
Después de iniciar el sistema, aparecerá un archivo de dispositivo llamado spidev1.1 en el directorio /dev. Leer y escribir este archivo puede realizar operaciones spi.
También existe el siguiente caso. :
estructura estática spi_board_info prt_spi_device[] __initdata = {
{
.modalias = "HotPRT",
.max_speed_hz = 12500000 , /* velocidad máxima del reloj spi (SCK) en HZ */
.bus_num = 1,
.chip_select = 1,
// mode =. SPI_MODE_0,
.platform_data = 0,
},
};
spi_register_board_info(prt_spi_device, ARRAY_SIZE(prt_spi_device));
Yo mismo implementé un controlador spi y luego necesito crear un archivo de dispositivo. La creación del archivo de dispositivo se completa en la sonda.
estructura estática spi_driver prt_driver = {
.driver = {
.name = "HotPRT",
.bus = amp; spi_bus_type,
.owner = ESTE_MODULE,
},
.probe = prt_probe,
.remove = __devexit_p(prt_remove),
};
spi_register_driver(amp;prt_driver);
Pero no pude activar la sonda al principio, así que busqué y busqué, y finalmente conocía el proceso de llamada de la sonda, de la siguiente manera:
int spi_register_driver(struct spi_driver *sdrv)
{
sdrv-gt; amp; spi_bus_type;
if (sdrv-gt; sonda)
sdrv-gt; driver.probe = spi_drv_probe;
if (sdrv-gt; eliminar )
sdrv -gt; driver.remove = spi_drv_remove;
if (sdrv-gt; apagado)
sdrv-gt;
return driver_register (amp; sdrv-gt; driver);
}
Luego llame a driver_register
lt; código" class="cpp"gt; int driver_register(struct dispositivo_driver *drv)
{
int ret;
struct dispositivo_driver *otro;
BUG_ON(!drv- gt; bus-gt; p);
if ((drv-gt; bus-gt; sonda amp; amp; drv-gt; sonda) ||
(drv- gt; bus-gt; eliminar amp; amp; drv-gt; eliminar) ||
(drv-gt; bus-gt; apagar amp; amp; drv -gt; apagado))
printk(KERN_WARNING "El controlador necesita actualización; utilice "
"métodos tipo_bus\n", drv-gt;nombre); p>
otro = driver_find( drv-gt; nombre, drv-gt; bus);
if (otro) {
put_driver(otro);
printk(KERN_ERR "Error: El controlador ya está registrado, "
p>
"abortando...\n", drv-gt;
return -EBUSY
}
ret = bus_add_driver; (drv);
if (ret)
return ret
ret = driver_add_groups(drv, drv-gt; grupos
<); p> if (ret)bus_remove_driver(drv);
return ret;
}
Ver bus_add_driver directamente
klist_init(& priv-gt; klist_devices, NULL, NULL);
priv-gt; controlador = drv drv-gt; > p>priv-gt;kobj.kset = bus-gt;p-gt;drivers_kset;
error = kobject_init_and_add(amp;priv-gt;kobj, amp;driver_ktype, NULL,
p>
"s", drv-gt;nombre);
si (error)
ir a out_unregister;
if (drv-gt; bus-gt;p-gt;drivers_autoprobe) {
error = driver_attach(drv);
if (error)
ir a out_unregister;
}
klist_add_tail(amp;priv-gt;knode_bus, amp;bus-gt;p-gt;klist_drivers);
module_add_driver(drv -gt;propietario, drv);
Aquí solo se intercepta una parte y la última llamada es driver_attach
int driver_attach(struct device_driver * drv)
{
return bus_for_each_dev(drv-gt; bus, NULL, drv, __driver_attach);
}
Lo que realmente funciona es __driver_attach:
static int __driver_attach(struct dispositivo * dev, void * datos)
{
. . .
if (!dev-gt; controlador)
driver_probe_device(drv, dev);
. . .
}
int driver_probe_device(struct dispositivo_driver * drv, struct dispositivo * dev)
{
. . .
//1. Primero determine si el bus coincide:
if (drv-gt; bus-gt; match amp; amp; !drv-gt; bus-gt; match ( dev, drv))
ir a hacer;
//2 Ejecutar la sonda específicamente:
ret = Actually_probe(dev, drv);
. . .
}
really_probe es la función que estamos buscando:
static int Actually_probe(struct device *dev, struct device_driver *drv)
{
. . .
//1. Primero llame a la función de sonda del autobús al que pertenece el conductor:
if (dev-gt; bus-gt; probe) {
ret = dev-gt; bus-gt; probe(dev);
if (ret)
ir a probe_failed; -gt; probe ) {
//2. Luego llame a la función de sonda en su controlador:
ret = drv-gt; probe(dev);
si (ret)
ir a probe_failed;
}
. . .
}
Entre ellos, drv-gt; probe(dev) es la función de sonda específica que realmente llama a la implementación de su controlador. En este punto se llama a la función de sonda.
Agregue spi_board_info al archivo del tablero y agregue spi_board_info al archivo del tablero