I have to modify a driver that runs on linux to add a callback function that is invoked from an external application. I already have the code implemented but when it is executed when the computer starts up, the system gives an error and is blocked.
This is my new code on the driver side:
typedef void (*callbackFunctionNoParams) ();
typedef struct T_EXI_CONFIGURE_BUS_
{
T_mode mode;
unsigned short NumeroRT;
T_SA_Enable SA_Enable;
unsigned short MINOR_CYCLE;
callbackFunctionNoParams callback;
} T_EXI_CONFIGURE_BUS;
typedef struct PciExiDev_
{
/**
* It represents a char device to read/write
*/
struct cdev charDevice;
/**
* IRQ assigned
*/
unsigned int irq;
/**
* Callback function to be invoked
*/
callbackFunctionNoParams callback;
/**
* Device control block
*/
EXI_DCB theDCB;
} PciExiDev;
Execution code on driver side:
static long exi_ioctl( struct file * filep, unsigned int cmd, unsigned long arg )
{
PciExiDev * aPciExiDev = (PciExiDev *) filep->private_data;
int result = SUCCESS;
int i, j;
long ret = 0;
//printk("Ioctl received %d.\n",cmd);
switch( cmd )
{
case FIO_EXI_CONFIGURE_BUS:
{
T_EXI_CONFIGURE_BUS config;
T_LISTA_TRANS *auxTrans1, *auxTrans2;
T_TRANSACTION_DCB *transDCB1;
T_OPI opi;
T_EXIS exis;
unsigned short dato;
unsigned short datolong[2];
unsigned short ControlBlock[12];
// printk("Exi configure bus initiated.\n");
printk("TNB. Exi ioctl CONFIGURE BUS.\n");
copy_from_user( &config, (T_EXI_CONFIGURE_BUS *) arg, sizeof(T_EXI_CONFIGURE_BUS) );
LeerDatos( &aPciExiDev->theDCB, OPI_ADDRESS, 1, (unsigned short *) &opi, 1 );
aPciExiDev->callback = config.callback;
aPciExiDev->theDCB.modo = config.mode;
aPciExiDev->theDCB.CicloMenor = config.MINOR_CYCLE;
(*aPciExiDev->callback)();
...
New code on client side:
if( theHWConfiguration.existExi() )
{
T_EXI_CONFIGURE_BUS bus_config;
// Configura la tarjega exi en modo Bus Controller.
bus_config.mode = BC;
bus_config.NumeroRT = 28;
bus_config.MINOR_CYCLE = 20;
bus_config.callback = &bcInterruptHandler2;
status = ioctl( A_fd_exi, FIO_EXI_CONFIGURE_BUS, reinterpret_cast<long>( &bus_config ) );
}
return status;
}
void C_EXI::bcInterruptHandler2()
{
std::cout<< "bcInterruptHandler2" << endl;
}
And this is the execution code result:
If someone could help me or propose an alternative way of doing this I would be very grateful.
CodePudding user response:
The crash image suggests that somewhere in your code you have an invalid pointer that you are trying to access. I am afraid I cannot debug your code with the little context provided, but I can give you some suggestions:
- Try to avoid casting until is strictly necessary.
- When you are casting to a pointer, double-check that this is exactly what you need to do.
- In the error message there is also the call stack: take a look at it in order to identify where is the error.
- You can simply add some printk("%p", pointer) in your code to debug the content of your variables.
CodePudding user response:
Your callback is bound to run at kernel space and then you write it to std::cout. While going through your code, it tells that there is a conflict between kernel mode address space and userside process address space. This means that if the callback function is declared in the userside but instead called in the kernel space, there would be an error.
