USB read failure with xboxdrv 0.8.7 - c++

I am using xboxdrv in version 0.8.7 and a XBox 360 Wireless controller on raspberrypi 3 (4.9.13-v7+).
It works sometimes a day, sometimes some minutes. But I get always:
[ERROR] USBController::on_read_data(): USB read failure: 32:
LIBUSB_TRANSFER_ERROR
The common suggestions in the forum didn't help me and I think there are still some people struggling with that.
I tried to contact the author but didn't get answer so far.
The software runs under GPL-3.0, so I had a look in the source code.
Project on GitHub:
https://github.com/xboxdrv/xboxdrv
I identified where it crashs (src/usb_controller.cpp, line 277 and below). That's the last else-section in the code below. Starting with log_error("USB read failure:
void
USBController::on_read_data(libusb_transfer* transfer)
{
assert(transfer);
if (transfer->status == LIBUSB_TRANSFER_COMPLETED)
{
// process data
XboxGenericMsg msg;
if (parse(transfer->buffer, transfer->actual_length, &msg))
{
submit_msg(msg);
}
int ret;
ret = libusb_submit_transfer(transfer);
if (ret != LIBUSB_SUCCESS) // could also check for LIBUSB_ERROR_NO_DEVICE
{
log_error("failed to resubmit USB transfer: " << usb_strerror(ret));
m_transfers.erase(transfer);
libusb_free_transfer(transfer);
send_disconnect();
}
}
else if (transfer->status == LIBUSB_TRANSFER_CANCELLED)
{
m_transfers.erase(transfer);
libusb_free_transfer(transfer);
}
else if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE)
{
m_transfers.erase(transfer);
libusb_free_transfer(transfer);
send_disconnect();
}
else
{
log_error("USB read failure: " << transfer->length << ": " << usb_transfer_strerror(transfer->status));
m_transfers.erase(transfer);
libusb_free_transfer(transfer);
}
}
My C++ knowledge is bad, further I haven't experience with libusb. Could you make a suggestion how I could fix that for me.
The problem is, as soon as the mentioned error occurs, xboxdrv is stopping and it will handle no more input from the XBOX 360 Wireless Controller.
It should just kind of ignore that wrong package and wait for a new one. But just don't stop working.
Thank you

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.

Why this code doesn't work when "cout"s are commented?

I'm writing a server for an online game based on IOCP, and the core codes handling game message is something like below:
CMessage ret;
int now_roomnum = recv_msg->para1;
int now_playernum = recv_msg->para2;
/*if(true)
{
cout<<"Received Game Message: "<<endl;
cout<<"type2 = "<<recv_msg->type2;
cout<<" player_num = "<<now_playernum<<" msg= "<<recv_msg->msg<<endl;
cout<<endl;
}*/
if(recv_msg->type2 == MSG_GAME_OPERATION)
{
ret.type1 = MSG_GAME;
ret.type2 = MSG_GAME_OPERATION;
while(game_host[now_roomnum].Ready(now_playernum) == true)
{
;
}
//cout<<"Entered from "<<now_playernum<<endl;
game_host[now_roomnum].SetMessage(now_playernum, recv_msg->msg);
game_host[now_roomnum].SetReady(now_playernum, true);
game_host[now_roomnum].SetUsed(now_playernum, false);
while(true)
{
bool tmp = game_host[now_roomnum].AllReady();
if(tmp == true)
break;
}
//cout<<"AllReady from"<<now_playernum<<endl;
string all_msg = game_host[now_roomnum].GetAllMessage();
game_host[now_roomnum].SetUsed(now_playernum, true);
while(!game_host[now_roomnum].AllUsed())
{
;
}
//cout<<"AllUsed from "<<now_playernum<<endl;
EnterCriticalSection(&cs);
game_host[now_roomnum].ClearReady();
LeaveCriticalSection(&cs);
strcpy_s(ret.msg, all_msg.c_str());
//cout<<"Return msg "<<now_playernum<<": "<<ret.msg<<endl;
}
return ret;
Now, the problem is: on a PC, when all cout are commented like above, the game freezes at once; but when I cancel the comments, the server works well.
What's more, when I run the server on my laptop, everything goes fine, no matter whether I comment the cout or not. The main difference between my laptop and PC is that my laptop's OS is Windows 8.1, while the PC is Windows 7.
I'm totally confused. It will be of great help if someone can tell me what to do. Thank you!
Looks like a multithreading issue.
By the way I see you use a Critical section around ClearReady but not when testing for AllReady. That call should be wrapped as well (or, better, write a LockedAllReady that makes use of the lock).
//cout<<"Return msg "<<now_playernum<<": "<<ret.msg<<endl;
What you mean by ret.msg? if msg is method you must do ret.msg(); , is it a field?
If you have this good then like they say above probably a timing problem, try to do cout without ret.msg and see what will happen, and then you know from where the problem is.

Why can't webrtc find the capturer it suggested?

I'm creating a webrtc-based voip app for windows in C++. I'm trying to initialize a peerconnection. I'm stuck at the part to fetch a camera. I'm using the following code to find a camera to start streaming media from (copied from the peerconnection client example):
rtc::scoped_ptr<cricket::DeviceManagerInterface> dev_manager(cricket::DeviceManagerFactory::Create());
if (!dev_manager->Init()) {
LOG(LS_ERROR) << "Can't create device manager";
return NULL;
}
std::vector<cricket::Device> devs;
if (!dev_manager->GetVideoCaptureDevices(&devs)) {
LOG(LS_ERROR) << "Can't enumerate video devices";
return NULL;
}
std::vector<cricket::Device>::iterator dev_it = devs.begin();
cricket::VideoCapturer* capturer = NULL;
for (; dev_it != devs.end(); ++dev_it) {
capturer = dev_manager->CreateVideoCapturer(*dev_it);
if (capturer != NULL)
break;
}
capturer is empty after this procedure. I stepped through the code to see what was wrong. dev_manager is succesfully intialized, devs gets a single entry (my webcam) with a name:
"logitech HD webcam c270"
And an id:
"\\\\?\\usb#vid_046d&pid_0825&mi_00#7&2dbd1a82&1&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\\{bbefb6c7-2fc4-4139-bb8b-a58bba724083}"
But after the CreateVideoCapturer() call, capturer is still empty. I get a warning in the console saying:
Warning(webrtcvideocapturer.cc:175): Failed to find capturer for id: \\?\usb#vid_046d&pid_0825&mi_00#7&2dbd1a82&1&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\{bbefb6c7-2fc4-4139-bb8b-a58bba724083}
I checked if the id I get in devs and this one match and they do. The entire log for my app can be found in this pastebin. As you can see, right after trying to assign the camera as capturer and failing, the app crashes on an assert(capturer != NULL) call somewhere in videosource.cc.
The camera is not in use, nor is it defect. The peerconnection client example works perfectly and uses the same code. I think I'm missing some step in the initialization of webrtc, but I can't find which step.
edit with additional info
I'm debug stepping through the library now. In webrtcvideocapturer.cc around line 160 is the following code:
int num_cams = info->NumberOfDevices();
char vcm_id[256] = "";
bool found = false;
for (int index = 0; index < num_cams; ++index) {
char vcm_name[256];
int32 i = info->GetDeviceName(index, vcm_name, ARRAY_SIZE(vcm_name), vcm_id, ARRAY_SIZE(vcm_id));
if (i != -1) {
if (device.name == reinterpret_cast<char*>(vcm_name)) {
found = true;
break;
}
}
}
if (!found) {
LOG(LS_WARNING) << "Failed to find capturer for id: " << device.id;
factory_->DestroyDeviceInfo(info);
return false;
}
There are two problems with this part. First of all, if I step into info->NumberOfDevices() it shows me that that function's only content is the line return 0;. I tried hard-coding 1 there, to at least get into the for loop. Then when I step into the info->GetDeviceName() call it shows me that the content of that function is return -1;.
These two functions are meant to be implemented by a class that inherits from webrtc::VideoCaptureModule::DeviceInfo, so there is clearly something not initialized that does needs to be initialized. What do I still need to do before trying to get a camera?
What libraries did you link?
Because Google WebRTC source codes are changing rapidly, it is difficult to track down issues to the source level.
But I remember the almost same problem occurred when I accidentally linked external capture module library (video_capture_module_impl ??) or (I'm not sure) omitted internal impl (video_capture_module_internal_impl ??).

requested the Runtime to terminate it in an unusual way

My problem is:
I built a c++ code for simulating a communication network (using OMNeT++ discrete event simulator) until there is no errors and the simulation completed, when I tried to increase the number of simulated entities, in any run at some point of time the simulation stops with a message printed in the command prompt says “This application has requested the Runtime to terminate it in an unusual way. Please contact the application’s support team for more information” and an error message displayed in a dedicated window under the title Application error says ”The exception unknown software exception (0x40000015) occurred in the application at location ....... ”
I think the problem, i.e., the simulation stops at and due to this part " ((cMessage *)msg->dup() " in the following code (but that may not be correct):
********
`void ChannelAccess::sendToChannel(AirFrame *msg)
{
const ChannelControl::ModuleList& neighbors = cc->getNeighbors(myHostRef);
coreEV << "sendToChannel: sending to gates\n";
// loop through all hosts in range
ChannelControl::ModuleList::const_iterator it;
for (it = neighbors.begin(); it != neighbors.end(); ++it)
{
cModule *mod = *it;
// we need to send to each radioIn[] gate
cGate *radioGate = mod->gate("radioIn");
if (radioGate == NULL)
error("module %s must have a gate called radioIn", mod->fullPath().c_str());
for (int i = 0; i < radioGate->size(); i++)
{
ChannelControl::HostRef h = cc->lookupHost(mod);
if (h == NULL)
error("cannot find module in channel control");
if (h->channel == msg->getChannelNumber())
{
coreEV << "sending message to host listening on the same channel\n";
// account for propagation delay, based on distance in meters
// Over 300m, dt=1us=10 bit times # 10Mbps
sendDirect((cMessage *)msg->dup(),myHostRef->pos.distance(h->pos) / LIGHT_SPEED, mod, radioGate->id() + i);
}
else
coreEV << "skipping host listening on a different channel\n";
}
}
// register transmission in ChannelControl
cc->addOngoingTransmission(myHostRef, msg);
}
`
*********
So, any help will be appreciated as I would like to run the simulation for large number of nodes.
For knowledge I use win xp SP3 and win 7, OMNet++ 3.3, Microsoft visual c++ 2005 express edition, one of the computers I ran the simulation on is i7 processor with 8G RAM.
Thank you in advance.

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).