Serial Port Driver-Got stuck in SerialISR () routine - c++

I am writing windows device driver first time for multiport serial pci card.May be this one is stupid question but i got stuck.Need someone's help.Let me first explain what I have done yet.I have bus driver which creates number of child (2/4/8/16) depends on card. Now I have to write function driver for it.The bus driver creates interrupt which I have to use.Now in my driver I got bus interface,interrupt created in bus driver and related information.I am using Serial Port Driver Sample for reference.Now in SerialISR () routine my driver got stuck in while loop.
ServicedAnInterrupt = TRUE;
do {
InterruptIdReg &= (~SERIAL_IIR_FIFOS_ENABLED);
switch (InterruptIdReg) {
case SERIAL_IIR_RLS: {
READ_LINE_STATUS(Extension, Extension->Controller);
break;
}
case SERIAL_IIR_RDA:
case SERIAL_IIR_CTI: {
READ_RECEIVE_BUFFER(Extension, Extension->Controller);
break;
}
case SERIAL_IIR_THR: {
//
// Alread clear from reading the iir.
//
// We want to keep close track of whether
// the holding register is empty.
//
Extension->HoldingEmpty = TRUE;
break;
}
case SERIAL_IIR_MS: {
READ_MODEM_STATUS(Extension, Extension->Controller);
break;
}
default: {
ASSERT(FALSE);
break;
}
}
} while (!((InterruptIdReg =
READ_INTERRUPT_ID_REG(Extension, Extension->Controller))
& SERIAL_IIR_NO_INTERRUPT_PENDING));
Every time it goes into case SERIAL_IIR_MS. This process continue for some time about 1 min & then test pc will crash.What can be the reason behind that & what should I do to overcome this problem?I have gone through msdn library information. Also read issues regarding this on OSR website.

Related

QT -- QTLowEnergyService->discoverDetails() does not discover non standard characteristics

I am writing a QT application for BLE on windows 10. The windows application is a BLE central, while the peripheral is running on an iOS device (tablet or phone). I pretty much followed the low energy scanner example and I can find the iOS device with the UUID of interest. The problem is that when the service is discovered and after issuing the discoverDetails() to get a list of the characteristics, the QT state machine goes from DiscoveryRequired, DiscoveringServices, Invalid Service, and then it disconnects.
I know this is a QT problem because
I can connect and interact with the peripheral using other applications
https://apps.apple.com/us/app/lightblue/id557428110
https://www.microsoft.com/en-us/p/ble-scanner/9nblggh0j7m0#activetab=pivot:overviewtab
The BLE scanner app (written in C#) from Microsoft, when compiled and run on the same machine as QT, also is able to connect and interact with the iOS peripheral.
I have noticed that other people are had/have the same problem, but I don't see where/if a resolution/workaround was eventually found.
Qt - Cannot read descriptor of the characteristic - BLE
Here is my handler for the QLowEnergyService::ServiceState signal
void BleClient::serviceStateChanged(QLowEnergyService::ServiceState newState)
{
switch (newState)
{
case QLowEnergyService::DiscoveringServices) :
{
// Nothing to do here, just note that we got into this state
qDebug() << "Discovering services";
break;
}
case QLowEnergyService::ServiceDiscovered:
{
qDebug() << "Service discovered";
const QList<QLowEnergyCharacteristic> chars = m_currentService->characteristics();
for (const QLowEnergyCharacteristic& ch : chars) {
auto cInfo = new CharacteristicInfo(ch);
m_characteristics.append(cInfo);
}
if (!chars.isValid()) {
setMessage("Value for characteristic not found.");
break;
}
m_notificationDesc = chars.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
if (m_notificationDesc.isValid()) {
m_service->writeDescriptor(m_notificationDesc, QByteArray::fromHex("0100"));
setMessage("Characteristic enabled");
m_start = QDateTime::currentDateTime();
}
break;
}
default:
qDebug() << "Unhandled state received : (" << newState << ")";
}
}
Ok, figured it out. Added more debug code and saw that a very descriptive error was being logged:
QLowEnergyService error: UnknownError
Looking further, seems like , the QLowEnergyController needs a queued connection callback for the serviceDiscovered event to work as expected. So I changed
connect(controller, &QLowEnergyController::discoveryFinished, this, &BleClient::serviceScanDone);
to
connect(controller, &QLowEnergyController::discoveryFinished, this, &BleClient::serviceScanDone, Qt::QueuedConnection);
..and lo and behold, now I see all services with all the characteristics.

WIN API - Programm getting stuck while a button is selected

I am creating a simple software using WINAPI that reads the data from a sensor connected to a computer via USB.
In this software, I am implementing some functions like read mode, test mode, etc.
The problem that I am facing is that I am getting stuck while I select the button for continuous reading, the code follows below:
case WM_COMMAND:
switch (wp)
{
case START_BUTTON:
printf("START_BUTTON");
while(SendDlgItemMessage(hWnd,START_BUTTON,BM_GETCHECK ,TRUE,0)== BST_CHECKED)
{
char* var = USB_Read(); //Get data from the sensor
SetWindowText(hLux, var); //Display the data
if (SendDlgItemMessage(hWnd,START_BUTTON,BM_GETCHECK ,TRUE,0)!= BST_CHECKED) //Check if the botton is no longer selected
break;
}
break;
}
break;
I know that the problem is in the while-loop, when I press it all the program gets stuck, only the data is being displayed correctly, the other controls get like frozen.
The question is: How could I display the data continuously and have access to the other controls at the same time?
You have to create a thread of execution that reads the usb while the start is checked.
So we create a thread that is started in the program initialization, which run continuosly and reads usb each time it founds the button checked.
Now in the message loop you simply check or uncheck the button.
DWORD WINAPI ThreadFunction( LPVOID lpParam )
{
(void)lpParam; //make happy compiler for unused variable
while (TRUE) //Once created the thread runs always
{
//If checked reads usb for each iteration
if(SendDlgItemMessage(hWnd,START_BUTTON,BM_GETCHECK ,0,0)== BST_CHECKED)
{
char* var = USB_Read(); //Get data from the sensor
SetWindowText(hLux, var); //Display the data
Sleep(1); //Why this? to don't have a furious CPU usage
}
}
}
.....
//Winmain
DWORD dwThreadId; //thread ID in case you'll need it
//Create and start the thread
CreateThread(
NULL, // default security attributes
0, // use default stack size
ThreadFunction, // thread function name
NULL, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier
......
case WM_COMMAND:
switch (wp)
{
case START_BUTTON:
printf("START_BUTTON");
if(SendDlgItemMessage(hWnd,START_BUTTON,BM_GETCHECK ,0,0)== BST_CHECKED)
SendDlgItemMessage(hWnd,START_BUTTON,BM_SETCHECK ,BST_UNCHECKED, 0);
else
SendDlgItemMessage(hWnd,START_BUTTON,BM_SETCHECK ,BST_CHECKED, 0);
break;
}
break;
EDIT: I modified the program to check/uncheck the radio button.
Please note the usage of the Sleep function with a minimal value of 1ms. It is used to give back control to the OS to smooth the CPU usage. If in the function that reads the usb there are enough OS synch primitives it can be omitted (check cpu usage).

send packet to UBX protocol

lately I have been working on a GPS reciever that supports both UBX and NEMA protocols. I am using serial programing on C++. I am trying to use UBX protocol, but it seems that I only recieve from NEMA. I downloaded the driver and I think I need to send a package first to recieve through UBX. Does anyone know a link or could tell me how could I send these packages the method I developed is stated below I think I need a small command before I start reading the data. Please someone help me here :D
void read_port(void)
{
unsigned char c='D';
while (c!='q')
{
if (read(fd, UBX_buffer, sizeof(UBX_buffer))>0)
{
data = read(fd, UBX_buffer, sizeof(UBX_buffer));
// write(fd,&UBX_buffer,1); // if new data is available on the serial port, print it out
cout<<"Data on the port = ";
for (unsigned i =0; i< sizeof(UBX_buffer) ;i++){
cout<<&UBX_buffer[i];
}
cout<<" "<<endl;
for (int i=0; i<fd; i++) // Process bytes received
{
switch(UBX_step) //we start from zero and increment as we go through the cases
{
case 0:
if(data==0xB5) UBX_step++; break; // UBX sync char 1 //check for the first data packet and go to next byte
case 1: if(data==0x62) UBX_step++;// UBX sync char 2 //check for the second data packet and go to the next byte
else UBX_step=0; break; //if first and second packets are not correct then go back and check again
case 2: UBX_class=data; checksum(UBX_class); UBX_step++; break;
case 3: UBX_id=data; checksum(UBX_id); UBX_step++; break;
case 4: UBX_payload_length_hi=data; checksum(UBX_payload_length_hi); UBX_step++; break;
case 5: UBX_payload_length_lo=data; checksum(UBX_payload_length_lo); UBX_step++; break;
case 6: // Payload data read...
if (UBX_payload_counter < UBX_payload_length_hi) // We stay in this state until we reach the payload_length
{
UBX_buffer[UBX_payload_counter] = data;
checksum(data);
UBX_payload_counter++;
}
else
UBX_step++;
break;
case 7: ck_a=data; UBX_step++; break; // First checksum byte
case 8: ck_b=data; // Second checksum byte
// We end the GPS read...
if((ck_a= ck_a)&&(ck_b= ck_a)) // Verify the received checksum with the generated checksum..
parse_ubx_gps(); // Parse new GPS packet...
UBX_step=0;
UBX_payload_counter=0;
ck_a=0;
ck_b=0;
GPS_timer=0; //Restarting timer...
break;
}
}
if (read(STDIN_FILENO,&c,1)>0) write(fd,&c,1); // if new data is available on the console, send it to the serial port
}
close(fd);
} // End Switch
} // End For
At the ublox Homepage you can Download the ublox protocoll specification. There, look at the cfg messages. For test purposes, you also can enable the ubx protocol via the tool u-Center.

How to check if CD drive is open or closed in linux?

I'm making an application that requires the knowledge of whether a CD drive is open or closed.
eject opens the CD drive, and checks how long it takes to open (a shorter amount of time says it's open, and a longer, well...), but I cannot use this technique, because the application actually opens the drive (and I do not want to re-open the drive if it's closed, neither do I want to close the drive if it is open).
How would I do this on linux? I saw that it is possible to do this under Windows (might be wrong though), but I haven't seen a way of doing this on linux.
If it's not possible using linux API calls, is it possible to implement a low-level function that could do this?
To make the example code work, you should do it this way:
#include <sys/ioctl.h>
#include <linux/cdrom.h>
int result=ioctl(fd, CDROM_DRIVE_STATUS, CDSL_NONE);
switch(result) {
case CDS_NO_INFO: ... break;
case CDS_NO_DISC: ... break;
case CDS_TRAY_OPEN: ... break;
case CDS_DRIVE_NOT_READY: ... break;
case CDS_DISC_OK: ... break;
default: /* error */
}
i.e. the result is returned as ioctl() function result, not into slot argument.
You can get tray state by using the CDROM_DRIVE_STATUS ioctl. All ioctls for CD-drives can be found in /usr/include/linux/cdrom.h
#define CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */
Taken from here
int slot;
ioctl(fd, CDROM_DRIVE_STATUS, slot);
switch(slot) {
case CDS_NO_INFO: ... break;
case CDS_NO_DISC: ... break;
case CDS_TRAY_OPEN: ... break;
case CDS_DRIVE_NOT_READY: ... break;
case CDS_DISC_OK: ... break;
default: /* error */
}

How do I read the pressure value from a graphics tablet stylus in Linux?

I am trying to add pressure sensitivity support to Synergy on Linux. I
believe the first step should be to detect the pressure value on the
server side. The stylus movement comes in as a MotionNotify event when
XNextEvent is called. However, this line does not output a pressure
value when the stylus is used:
case MotionNotify:
XDeviceMotionEvent* motionEvent = reinterpret_cast<XDeviceMotionEvent*>(xevent);
LOG((CLOG_INFO "tablet event: pressure=%d", motionEvent->axis_data[2]));
To solve this, I guessed that I might not be "subscribed" to such
info, so following some examples I found on the web, I have attempted
to open the Wacom device:
void
CXWindowsScreen::openWacom()
{
// init tablet (e.g. wacom)
int deviceCount;
XDeviceInfo* deviceInfo = XListInputDevices(m_display, &deviceCount);
for (int i = 0; i < deviceCount; ++i) {
if (CString(deviceInfo[i].name).find("stylus") != CString::npos) {
LOG((CLOG_INFO "tablet device: name='%s', id=%d",
deviceInfo[i].name, deviceInfo[i].id));
XDevice* tabletStylusDevice = XOpenDevice(m_display, deviceInfo[i].id);
if (tabletStylusDevice == NULL) {
LOG((CLOG_ERR "failed to open tablet device"));
return;
}
XEventClass eventClass;
DeviceMotionNotify(tabletStylusDevice, m_tabletMotionEvent, eventClass);
XSelectExtensionEvent(m_display, m_window, &eventClass, 1);
LOG((CLOG_INFO "tablet motion event=%d class=%d",
m_tabletMotionEvent, eventClass));
}
}
XFreeDeviceList(deviceInfo);
}
This does indeed detect a Wacom device...
2012-01-30T11:15:59 INFO: tablet device: name='Wacom Intuos4 6x9 stylus', id=8
/home/nick/Projects/synergy/1.4/src/lib/platform/CXWindowsScreen.cpp,1144
2012-01-30T11:15:59 INFO: tablet motion event=105 class=2153
/home/nick/Projects/synergy/1.4/src/lib/platform/CXWindowsScreen.cpp,1157
But I have so far never received the stylus event 105
(m_tabletMotionEvent) from XNextEvent...
if (xevent->type == m_tabletMotionEvent) {
XDeviceMotionEvent* motionEvent = reinterpret_cast<XDeviceMotionEvent*>(xevent);
LOG((CLOG_INFO "tablet event: pressure=%d", motionEvent->axis_data[2]));
return;
}
In other words, the above if never evaluates to true.
I hope someone can help me with this, I've been trying to solve it for weeks.
The next challenge will be to fake the pressure level on the Synergy
client so that programs like GIMP will receive it (and I'm not even sure where to
start with that).