Related
I try to write Windows server app that accepts requests. I wan to use select() function to receive new connections and requests -- to monitor listen socket and previously established connections.
The problem is that FD_ISSET always returns 0. Here's the code. Can you please point me the mistake?
WORD wVersionRequested;
WSADATA wsaData;
int iResult;
// Initializing WSA
wVersionRequested = MAKEWORD( 2, 2 );
iResult = WSAStartup( wVersionRequested, &wsaData );
if ( iResult != 0 )
{
std::cout << "WSAStartup failed with error: " << WSAGetLastError() << std::endl;
return false;
}
if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 )
{
WSACleanup();
std::cout << "Could not find a usable version of Winsock.dll" << std::endl;
return false;
}
int iResult;
struct addrinfo *result = NULL;
struct addrinfo hints;
std::stringstream ss;
ss << DEFAULT_PORT;
memset( &hints, 0, sizeof( hints ) );
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo( NULL, ss.str().c_str(), &hints, &result );
if ( iResult != 0 )
{
std::cout << "getaddrinfo() failed with error: " << WSAGetLastError() << std::endl;
return false;
}
// Create a SOCKET for connecting to server
m_listenSocket = socket( result->ai_family, result->ai_socktype, result->ai_protocol );
if ( m_listenSocket == INVALID_SOCKET )
{
std::cout << "socket() failed with error: " << WSAGetLastError() << std::endl;
return false;
}
// Setup the TCP listening socket
iResult = bind( m_listenSocket, result->ai_addr, ( int ) result->ai_addrlen );
if ( iResult == SOCKET_ERROR )
{
std::cout << "bind() failed with error: " << WSAGetLastError() << std::endl;
freeaddrinfo( result );
return false;
}
freeaddrinfo( result );
// Listen for the TCP listening socket
if ( listen( m_listenSocket, SOMAXCONN ) == SOCKET_ERROR )
{
std::cout << "listen() failed with error: " << WSAGetLastError() << std::endl;
return false;
}
fd_set active_fd_set;
fd_set read_fd_set;
// Initialize the set of active sockets.
FD_ZERO( &active_fd_set );
FD_SET( m_listenSocket, &active_fd_set );
while ( !m_forceStopMessages )
{
read_fd_set = active_fd_set;
int retVal = select( FD_SETSIZE, &read_fd_set, NULL, NULL, NULL );
if ( retVal < 0 )
{
std::cout << "select() failed with error: " << WSAGetLastError() << std::endl;
}
int readySockets = ( FD_SETSIZE < retVal ) ? FD_SETSIZE : retVal;
// Service all the sockets with input pending.
for ( int i = 0; i < readySockets; ++i )
{
if ( FD_ISSET( i, &read_fd_set ) )
{
if ( i == m_listenSocket )
{
// Accept a client socket
FD_SET( clientSocket, &active_fd_set );
}
else
{
/* Data arriving on an already-connected socket. */
FD_CLR( i, &active_fd_set );
}
}
}
}
FD_ISSET takes a socket handle as the first parameter, not an index.
I'm learning Windows Registered I/O, I found a sample project from the website "https://github.com/zeliard/RIOEchoServer", It does well on my computer.
However, if I change this code from the listening server side to the actively sending client side, I find that connect + RIOSend works fine, but RIOSendEx will definitely give an error code of 10022!
#include <WinSock2.h>
#include <MSWsock.h>
#include <WS2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
int main(int argc, char * argv[])
{
static const wchar_t SERVER[] = L"127.0.0.1";
static const unsigned short PORTNUM = 54321;
static const DWORD RIO_PENDING_RECVS = 1;
static const DWORD RIO_PENDING_SENDS = 1;
static const DWORD RECV_BUFFER_SIZE = 1024;
static const DWORD SEND_BUFFER_SIZE = 1024;
static const DWORD ADDR_BUFFER_SIZE = 64;
static const DWORD RIO_MAX_RESULTS = 1;
WSADATA wsadata;
if (0 != ::WSAStartup(0x202, &wsadata))
{
printf_s("WSAStartup Error: %d\n", GetLastError());
exit(0);
}
/// RIO socket
SOCKET socket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, WSA_FLAG_REGISTERED_IO);
if (socket == INVALID_SOCKET)
{
printf_s("WSASocket Error: %d\n", GetLastError());
exit(0);
}
/// RIO function table
GUID functionTableId = WSAID_MULTIPLE_RIO;
DWORD dwBytes = 0;
RIO_EXTENSION_FUNCTION_TABLE rio;
if (NULL != WSAIoctl(socket, SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER, &functionTableId, sizeof(GUID), (void**)&rio, sizeof(rio), &dwBytes, NULL, NULL))
{
printf_s("WSAIoctl Error: %d\n", GetLastError());
exit(0);
}
/// rio's completion manner: iocp
HANDLE hIOCP = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
if (NULL == hIOCP)
{
printf_s("CreateIoCompletionPort Error: %d\n", GetLastError());
exit(0);
}
OVERLAPPED overlapped;
RIO_NOTIFICATION_COMPLETION completionType;
completionType.Type = RIO_IOCP_COMPLETION;
completionType.Iocp.IocpHandle = hIOCP;
completionType.Iocp.CompletionKey = NULL;
completionType.Iocp.Overlapped = &overlapped;
/// creating RIO CQ, which is bigger than (or equal to) RQ size
RIO_CQ completionQueue = rio.RIOCreateCompletionQueue(RIO_PENDING_RECVS + RIO_PENDING_SENDS, &completionType);
if (completionQueue == RIO_INVALID_CQ)
{
printf_s("RIOCreateCompletionQueue Error: %d\n", GetLastError());
exit(0);
}
/// creating RIO RQ
/// SEND and RECV within one CQ (you can do with two CQs, seperately)
RIO_RQ requestQueue = rio.RIOCreateRequestQueue(socket, RIO_PENDING_RECVS, 1, RIO_PENDING_SENDS, 1, completionQueue, completionQueue, NULL);
if (requestQueue == RIO_INVALID_RQ)
{
printf_s("RIOCreateRequestQueue Error: %d\n", GetLastError());
exit(0);
}
/// registering RIO buffers for SEND
char sendBuffer[SEND_BUFFER_SIZE];
RIO_BUFFERID sendRioBufferId = rio.RIORegisterBuffer(sendBuffer, static_cast<DWORD>(sizeof(sendBuffer)));
if (sendRioBufferId == RIO_INVALID_BUFFERID)
{
printf_s("RIORegisterBuffer Error: %d\n", GetLastError());
exit(0);
}
RIO_BUF sendRioBuffer;
sendRioBuffer.BufferId = sendRioBufferId;
sendRioBuffer.Offset = 0;
sendRioBuffer.Length = SEND_BUFFER_SIZE;
/// registering RIO buffers for ADDR
char addrBuffer[ADDR_BUFFER_SIZE];
RIO_BUFFERID addrRioBufferId = rio.RIORegisterBuffer(addrBuffer, static_cast<DWORD>(sizeof(addrBuffer)));
if (addrRioBufferId == RIO_INVALID_BUFFERID)
{
printf_s("RIORegisterBuffer Error: %d\n", GetLastError());
exit(0);
}
RIO_BUF addrRioBuffer;
addrRioBuffer.BufferId = addrRioBufferId;
addrRioBuffer.Offset = 0;
addrRioBuffer.Length = ADDR_BUFFER_SIZE;
/// registering RIO buffers for RECV and then, post pre-RECV
char recvBuffer[RECV_BUFFER_SIZE];
RIO_BUFFERID recvRioBufferId = rio.RIORegisterBuffer(recvBuffer, static_cast<DWORD>(sizeof(recvBuffer)));
if (recvRioBufferId == RIO_INVALID_BUFFERID)
{
printf_s("RIORegisterBuffer Error: %d\n", GetLastError());
exit(0);
}
RIO_BUF recvRioBuffer;
recvRioBuffer.BufferId = recvRioBufferId;
recvRioBuffer.Offset = 0;
recvRioBuffer.Length = RECV_BUFFER_SIZE;
/// posting pre RECVs
if (!rio.RIOReceiveEx(requestQueue, &recvRioBuffer, 1, NULL, &addrRioBuffer, NULL, 0, 0, &recvRioBuffer))
{
printf_s("RIOReceive Error: %d\n", GetLastError());
exit(0);
}
//////////////////////////////////////////////////////////////////////////
// active send code begin ...
//////////////////////////////////////////////////////////////////////////
sendRioBuffer.Length = 5;
memcpy_s(sendBuffer, RECV_BUFFER_SIZE, "hello", sendRioBuffer.Length);
sockaddr_in * address = reinterpret_cast<sockaddr_in *>(addrBuffer);
memset(address, 0x0, ADDR_BUFFER_SIZE);
address->sin_family = AF_INET;
address->sin_port = htons(PORTNUM);
if (::InetPton(AF_INET, SERVER, &address->sin_addr) <= 0)
{
printf_s("inet_pton Error: %d\n", GetLastError());
exit(0);
}
#if 0 // connect + RIOSend is OK
if (SOCKET_ERROR == ::connect(socket, reinterpret_cast<struct sockaddr *>(address), sizeof(*address)))
{
printf_s("Connect Error: %d\n", GetLastError());
exit(0);
}
if (!rio.RIOSend(requestQueue, &sendRioBuffer, 1, 0, &sendRioBuffer))
{
printf_s("RIOSend Error: %d\n", GetLastError());
exit(0);
}
#else // RIOSendEx not work
if (!rio.RIOSendEx(requestQueue, &sendRioBuffer, 1, NULL, &addrRioBuffer, NULL, NULL, 0, &sendRioBuffer))
{
printf_s("RIOSendEx Error: %d\n", GetLastError());
exit(0);
}
#endif // 0
INT notifyResult = rio.RIONotify(completionQueue);
if (notifyResult != ERROR_SUCCESS)
{
printf_s("RIONotify Error: %d\n", GetLastError());
exit(0);
}
DWORD numberOfBytes = 0;
ULONG_PTR completionKey = 0;
OVERLAPPED* pOverlapped = 0;
RIORESULT results[RIO_MAX_RESULTS];
if (!::GetQueuedCompletionStatus(hIOCP, &numberOfBytes, &completionKey, &pOverlapped, INFINITE))
{
printf_s("GetQueuedCompletionStatus Error: %d\n", GetLastError());
exit(0);
}
memset(results, 0, sizeof(results));
ULONG numResults = rio.RIODequeueCompletion(completionQueue, results, RIO_MAX_RESULTS);
if (0 == numResults || RIO_CORRUPT_CQ == numResults)
{
printf_s("RIODequeueCompletion Error: %d\n", GetLastError());
exit(0);
}
const RIORESULT & res = results[0];
if (0 != res.Status)
{
printf_s("RIOSend(Ex) Error: %d\n", res.Status);
exit(0);
}
printf_s("RIOSend(Ex) OK\n");
//////////////////////////////////////////////////////////////////////////
// active send code end ...
//////////////////////////////////////////////////////////////////////////
if (SOCKET_ERROR == ::closesocket(socket))
{
printf_s("closesocket Error: %d\n", GetLastError());
}
rio.RIOCloseCompletionQueue(completionQueue);
rio.RIODeregisterBuffer(sendRioBufferId);
rio.RIODeregisterBuffer(recvRioBufferId);
rio.RIODeregisterBuffer(addrRioBufferId);
return 0;
}
wish your help, Thanks!
yanrk
From RIOSendEx documentation:
sends network data on ... a bound ... UDP socket
Your example will work if you add those lines before calling RIOSendEx:
sockaddr_in addr{}; // zero-initialized
addr.sin_family = AF_INET;
if (SOCKET_ERROR == ::bind(socket, (struct sockaddr *)&addr, sizeof(addr)))
{
printf("bind failed\n");
exit(0);
}
if (!rio.RIOSendEx(requestQueue ...
You can bind to some particular port (not recommended):
addr.sin_port = htons(5001);
Or leave it zero for OS to choose.
Aparently, RIOSendEx do not perform an implicit bind (unlike WSASendTo).
The reason for this might be that bind is a complicated process that might involve waiting and APC and all kinds of stuff, while whole idea of RIO is to pay upfront.
connect + RIOSendEx doesn't make sense. Since you specified remote address with connect function you can't send data through that socket anywhere else. RIOSendEx is supposed to be used with datagrams.
You have not set the Destination IP-Address in the RioSendEx-Function:
Copy the content of your address-Buffer into the associated Buffer of addrRioBuffer.
e.g.:
memcpy_s(addrBuffer, ADDR_BUFFER_SIZE, address, sizeof(sockaddr_in));
if (!rio.RIOSendEx(requestQueue, &sendRioBuffer, 1, NULL, &addrRioBuffer, NULL, NULL, 0, &sendRioBuffer))
{
printf_s("RIOSendEx Error: %d\n", GetLastError());
exit(0);
}
// […]
I will post a working exampel in the next day´s.
http://www.thbweb.eu
my goal:
I`m writing an application which writes a file to the serial port 128 bytes at a time (137 total, with ModBUS header and CRC) and waits for the reply. The writing I have managed to implement successfully. After sending a 137 byte packet I would like to wait on the serial com for a reply and process it, in case that modbus exception is thrown.
my problem:
The ReadFile function returns 170 which, from windows documentation, is 170 (0xAA) - The requested resource is in use. The only resource I am actually using is the serial port handle, which I doubt that it is this, the error is referring to.
Note -
- not using available ModBUS libraries because I use the address registers in a specific way, needing full control
- I am using overlapped I/O only because (according to WinApi doc) ReadFile never returns if no bytes come at the serial port; If timeouts are require overlapped access is a must (correct me if I`m wrong).
- I have a 2 sec max timeout (timeout for actually waiting for the reply) and 20 ms between bytes; if more than 20 ms between bytes pass I assume that no more bytes are coming;
Has anyone had any previous experience working with ReadFile and possibly Erro 170? Appreciate all the help I can get.
part of my code:
u8 WaitModBusReply(void)
{
u8 i = 0;
u8 ReplyStatus = 0xAA;
u8 ReplyBuff[ReplyBuffSize];
u8 * ptr = &ReplyBuff[0];
static u16 TotalRX_Bytes;
DWORD dwCommEvent;
DWORD dwBytesRead;
COMSTAT ComStatus;
DWORD comErrors = 0;
OVERLAPPED read_s = {0};
read_s.hEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // not signaled
NULL // no name
);
for (int z=0; z< ReplyBuffSize; z++)
ReplyBuff[z] = 0;
ClearCommError(ModBUS_Port, &comErrors, &ComStatus);
ResetEvent(read_s.hEvent);
if ( !WaitCommEvent(ModBUS_Port, &dwCommEvent, &read_s) )
{
//byte_timeout += MCU_Getms_TimeConsumption();
if ( (ReadFile(ModBUS_Port, ptr+TotalRX_Bytes, ReplyBuffSize-
TotalRX_Bytes, &dwBytesRead, NULL) )) //&dwBytesRead &modbus_reply
{
fprintf(stderr, "\n EXEC 3");
// ReadFile(PC_TestCenterPort, pBufPtr+TotalRX_Bytes, BufSize-
TotalRX_Bytes, &BytesRead, NULL);
TotalRX_Bytes += dwBytesRead;
i++;
ReplyStatus = Reply_Received;
}
}
else
printf("Error setting Com event mask:%d ", GetLastError());
if ( ReplyStatus == Reply_Received)
{
fprintf(stderr, "\nExit error3: %d\n", GetLastError() );
if ( (i == 4) ) // Exception returned. Parse it
{
if ( !ModBus_CRC16 (&ReplyBuff[0], i, READ) )
ReplyStatus = Reply_CRCError;
else
ReplyStatus = ReplyBuff[i-2];
}
else if ( (i == 7) ) // Reply returned
{
if ( !ModBus_CRC16 (&ReplyBuff[0], i, READ) )
ReplyStatus = Reply_CRCError;
else
ReplyStatus = Reply_OK;
}
}
/*
for ( int j=0; j<= 256; j++)
printf("\nReplyBuff[%d]: %X", j, ReplyBuff[j]); */
return ReplyStatus;
}
The logic for checking the reply array is not implemented so ignore that part.
This function is called by:
u8 SerialDataSend(void)
{
u8 t_status = BufferSent;
int write_status = -1;
int read_status = -1;
DWORD bytes_written = 0;
OVERLAPPED write_s;
memset(&write_s, 0, sizeof(write_s));
write_s.Internal = 0;
write_s.InternalHigh = 0;
write_s.Offset = 0;
write_s.OffsetHigh = 0;
write_s.hEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // not signaled
NULL // no name
);
if ( !SerialInit() )
{
while (!t_status)
{
fprintf(stderr, "Starting transmission -\n");
while(packages_left > 0 && !t_status)
{
write_status = WriteFile(ModBUS_Port, ModBUS_Buffer(), 137,
&bytes_written, &write_s); //&write_s
fprintf(stderr,"\r ModBUS transaction - Packages left:%4d",
packages_left);
if( write_status ) // Return values for success and
overlapped access ongoing
{
fprintf(stderr, "Error :%d.\n", GetLastError());
t_status = BufferFailed;
CloseHandle(ModBUS_Port);
break;
}
//FlushFileBuffers(ModBUS_Port);
read_status = WaitModBusReply();
printf("READ STATUS: %d\n", read_status);
if ( !read_status && !write_status )
{
fprintf(stderr, "\n------------------------------------------------------------");
fprintf(stderr, "\n Exception occurred: %X\n",
read_status);
t_status = BufferFailed;
Sleep(1);
break;
}
packages_left--;
Sleep(200);
}
//printf("EXEC 1\n");
if (!t_status)
{
fprintf(stderr, "\n\nTransaction Complete. Bytes written :
%d\n", FileSize);
packages_left = 10;
}
break;
}
fclose(HMI_Program);
if ( t_status != BufferFailed )
{
fprintf(stderr, "Closing serial port - ");
if ( !CloseHandle(ModBUS_Port) )
fprintf(stderr, "Error :%d.\n", GetLastError());
else
fprintf(stderr, "OK.\n");
}
}
fflush(stdout);
fflush(stderr);
return t_status;
}
and the function which initializes the Serial port:
u8 SerialInit(void)
{
memset(&SerialSettings,0,sizeof(SerialSettings));
SerialSettings.DCBlength = sizeof(SerialSettings);
SerialSettings.BaudRate = CBR_115200;
SerialSettings.ByteSize = 8;
SerialSettings.StopBits = TWOSTOPBITS;
SerialSettings.Parity = NOPARITY;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
timeouts.ReadIntervalTimeout = 20;
timeouts.ReadTotalTimeoutConstant = 2000;
timeouts.ReadTotalTimeoutMultiplier = 1 ;
memset(&timeouts,0,sizeof(timeouts));
fprintf(stderr, "Opening serial port - ");
sprintf(COM_Port, "\\\\.\\COM%d", port_no);
ModBUS_Port = CreateFile(COM_Port, GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );
if (ModBUS_Port == INVALID_HANDLE_VALUE)
fprintf(stderr, "Error\n\n");
else
fprintf(stderr, "OK\n");
if ( !GetCommState(ModBUS_Port, &SerialSettings) )
{
fprintf(stderr, "Error getting device state.");
CloseHandle(ModBUS_Port);
}
else if( !SetCommState(ModBUS_Port, &SerialSettings) )
{
fprintf(stderr, "Error setting device parameters.");
CloseHandle(ModBUS_Port);
}
else if ( !SetCommTimeouts(ModBUS_Port, &timeouts) )
{
fprintf(stderr, "Error setting timeouts.");
CloseHandle(ModBUS_Port);
}
else if ( !SetCommMask(ModBUS_Port, EV_RXCHAR | EV_ERR ) )
{
fprintf(stderr, "\nError setting com mask.");
CloseHandle(ModBUS_Port);
}
return GetLastError();
}
Thanks.
I am writing my own char driver for a USB devices which needs a simple write using ctrl transport and read using interrupt transport. My device have 2 interfaces , in which for zero interface i can get interrupt endpoint , so basically i didn't need to handle for second interface which contains bulk , ISCO , so i am return -ENODEV from the probe function when the bInterfaceNumber is 1 . Below is the code snippet
static int USBTestMode_Probe(struct usb_interface *interface, const struct usb_device_id *id)
{
if(interface->cur_altsetting->desc.bInterfaceNumber != 0)
{
return -ENODEV;
}
struct usb_device *udev = interface_to_usbdev(interface);
struct usb_test_mode_dev * testModeDev = NULL;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
int i, int_end_size;
int retval = -ENODEV;
TestModeclass.name = "testmode%d";
TestModeclass.fops = &USBTestModefops;
testModeDev = kzalloc(sizeof(struct usb_test_mode_dev),GFP_KERNEL);
strcpy(testModeDev->buffer , "mydata");
printk("size::%d\n", sizeof(struct usb_test_mode_dev));
printk("testModeDev size::%d\n", sizeof(testModeDev));
printk("name :%s\n",testModeDev->buffer);
if(testModeDev == NULL)
{
printk("No Memory ):");
goto exit;
}
testModeDev->udev = usb_get_dev(udev);
testModeDev->interface = interface;
iface_desc = interface->cur_altsetting;
testModeDev->int_in_endpoint = kzalloc(sizeof(struct usb_endpoint_descriptor),GFP_KERNEL);
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
== USB_DIR_IN)
&& ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
== USB_ENDPOINT_XFER_INT))
memcpy(testModeDev->int_in_endpoint , endpoint ,sizeof(endpoint));
}
if (! testModeDev->int_in_endpoint) {
printk("could not find interrupt in endpoint");
goto error;
}
printk("endpoint packetSize :%d\n",testModeDev->int_in_endpoint->wMaxPacketSize);
printk("endpoint value :%d\n",testModeDev->int_in_endpoint->bEndpointAddress);
int_end_size = le16_to_cpu(testModeDev->int_in_endpoint->wMaxPacketSize);
testModeDev->int_in_buffer = kzalloc(int_end_size, GFP_KERNEL);
printk("endpoint packetSize :%d\n",testModeDev->int_in_endpoint->wMaxPacketSize);
printk("endpoint value :%d\n",testModeDev->int_in_endpoint->bEndpointAddress);
if (! testModeDev->int_in_buffer) {
printk("could not allocate int_in_buffer");
retval = -ENOMEM;
goto error;
}
testModeDev->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (! testModeDev->int_in_urb) {
printk("could not allocate int_in_urb");
retval = -ENOMEM;
goto error;
}
printk("endpoint packetSize :%d\n",testModeDev->int_in_endpoint->wMaxPacketSize);
printk("endpoint value :%d\n",testModeDev->int_in_endpoint->bEndpointAddress);
// Save our data pointer in this interface device.
usb_set_intfdata(interface, testModeDev);
printk("endpoint packetSize :%d\n",testModeDev->int_in_endpoint->wMaxPacketSize);
printk("endpoint value :%d\n",testModeDev->int_in_endpoint->bEndpointAddress);
// We can register the device now, as it is ready.
retval = usb_register_dev(interface, &TestModeclass);
if (retval) {
printk("not able to get a minor for this device.");
usb_set_intfdata(interface, NULL);
goto error;
}
testModeDev->minor = interface->minor;
printk("TestUSB now attached to /dev/TestMode%d\n",
interface->minor - 0);
error:
TestMode_delete(testModeDev);
exit:
return retval;
return 0;
}
when ever i am trying to access the usb_test_mode_dev data saved in probe in open Method below , i am getting BUG: unable to handle kernel NULL pointer dereference at 0000000000000048
static int TestMode_open(struct inode *inode, struct file *file)
{
struct usb_test_mode_dev *dev = NULL;
struct usb_interface *interface;
int subminor;
int retval = 0;
subminor = iminor(inode);
printk(" i came here %d\n" , subminor);
interface = usb_find_interface(&USBTestMode_driver, subminor);
printk("interface->cur_altsetting->desc.bInterfaceNumber : %d \n" ,interface->cur_altsetting->desc.bInterfaceNumber);
if (! interface) {
printk("can't find device for minor %d", subminor);
retval = -ENODEV;
return retval;
}
printk(" i came here .....1\n");
dev = usb_get_intfdata(interface);
printk("name :%s\n",dev->buffer);
if (! dev) {
retval = -ENODEV;
return retval;
}
printk("Dev size::%d\n", sizeof(*dev));
printk(" i came here .....2\n");
//dev->int_in_endpoint->bEndpointAddress = 129;
//dev->int_in_endpoint->wMaxPacketSize = 64;
if( dev->int_in_endpoint != NULL)
{
printk(" i came here .....8\n");
printk("endpoint value :%d\n",dev->int_in_endpoint->bEndpointAddress);
printk("endpoint value :%d\n",dev->int_in_endpoint->wMaxPacketSize);
}
printk(" i came here .....7\n");
if(!dev->int_in_endpoint->bEndpointAddress || !dev->int_in_endpoint->wMaxPacketSize )
return -1;
/* Initialize interrupt URB. */
usb_fill_int_urb(dev->int_in_urb, dev->udev,
usb_rcvintpipe(dev->udev,
dev->int_in_endpoint->bEndpointAddress),
dev->int_in_buffer,
le16_to_cpu(dev->int_in_endpoint->wMaxPacketSize),
TestMode_init_callback,
dev,
dev->int_in_endpoint->bInterval);
printk(" i came here .....3\n");
mb();
printk(" i came here .....6\n");
retval = usb_submit_urb(dev->int_in_urb, GFP_KERNEL);
if (retval) {
printk("submitting int urb failed (%d)", retval);
return retval;
}
printk(" i came here .....4\n");
/* Save our object in the file's private structure. */
file->private_data = dev;
printk(" i came here .....5\n");
return retval;
}
The module gets crash when i am try to access dev->int_in_endpoint , even the buffer continues empty. why is my data structure saved in probe is getting overwritten . Is this due to multiple interface of my device . Please help me. In case if you want the data structure of my char device below is the code .
struct usb_test_mode_dev {
struct usb_device *udev;
unsigned char *int_in_buffer;
struct usb_interface *interface;
struct usb_endpoint_descriptor *int_in_endpoint;
struct urb *int_in_urb;
unsigned char minor;
char buffer[20];
};
Thanks in advance.
usb_set_intfdata(interface, testModeDev); is at wrong place , should be called before return in probe method
I have read many posts about this same topic, but I am unable to find out what is exactly wrong with my sysfs implementation in my kernel module. I am trying to make a userspace program block on a poll untill the value changes in a sysfs file. Most people seem to not get blocking, I seem to not be able to get out of my blocking. Here is the relevent code:
kernel module:
static int sysfs_test = 88;
static ssize_t test_interrupts_show(struct device* dev, struct device_attribute* attr, const char* buf)
{
return scnprintf(buf, PAGE_SIZE, "%d\n", sysfs_test);
}
static ssize_t test_interrupts_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count)
{
kstrtol(buf, 10, &sysfs_test);
return count;
}
static DEVICE_ATTR(interrupts, S_IWUSR | S_IRUGO, test_interrupts_show, test_interrupts_store);
static int __init test_init(void)
{
int result;
if(dev_major)
{
dev = MKDEV(dev_major, dev_minor);
result = register_chrdev_region(dev, NUM_DEVICES, name);
} else {
result = alloc_chrdev_region(&dev, dev_minor, NUM_DEVICES, name);
dev_major = MAJOR(dev);
dev_minor = MINOR(dev);
}
if(result < 0) {
printk(KERN_WARNING "%s: can't get major %d\n", name, dev_major);
return -1;
}
printk(KERN_NOTICE "%s: Major = %d, Minor = %d\n", name, dev_major, dev_minor);
// Register as character device
test_cdev = cdev_alloc();
cdev_init(cajun_cdev, &test_fops); // Initialize cdev structure
test_cdev->owner = THIS_MODULE; // Add owner
result = cdev_add(test_cdev, dev,1); // Tell kernel about our device
if(result)
{
printk(KERN_NOTICE "Error %d adding cdev\n", result);
goto OUT2;
}
// This stuff relates to sysfs:
ctest_class = class_create(THIS_MODULE, NAME);
if(IS_ERR(test_class))
{
printk(KERN_ALERT "Failed to register device class\n");
goto OUT2;
}
test_device = device_create(test_class, NULL, dev, NULL, NAME);
if(IS_ERR(test_device))
{
printk(KERN_ALERT "Failed to create device\n");
goto OUT3;
}
result = device_create_file(test_device, &dev_attr_interrupts);
if (result < 0)
{
printk(KERN_ALERT "failed\n");
}
OUT3:
class_unregister(test_class);
class_destroy(test_class);
OUT2:
cdev_del(test_cdev);
OUT1:
unregister_chrdev_region(dev, NUM_DEVICES);
return -1;
}
Relevent userspace code:
char interrupts_path[] = "/sys/class/test_module/test_module/interrupts";
int main()
{
struct pollfd fds;
fds.fd = open(interrupts_path, O_RDWR | O_SYNC);
char dummy_buff[1];
read(fds.fd, dummy_buff, 1);
lseek(fds.fd, 0, SEEK_SET);
fds.events = POLLPRI;
printf("Polling for interrupt\n");
poll(&fds,1,-1);
printf("Interrupt occured\n");
return 0;
}
I run my userspace code in the background (./test &) and then I echo a new value into the sysfs file for interrupts. I am hopping for my userspace program to unblock and return when the value changes. What am I doing wrong here?
edit:
struct file_operations test_fops = {
.owner = THIS_MODULE,
.llseek = test_llseek,
.read = test_read,
.write = test_write,
.unlocked_ioctl = test_ioctl,
.open = test_open,
.release = test_release
};