Line 1... |
Line 1... |
// $Id: RlinkPortCuff.cpp 516 2013-05-05 21:24:52Z mueller $
|
// $Id: RlinkPortCuff.cpp 524 2013-06-30 19:10:30Z mueller $
|
//
|
//
|
// Copyright 2012-2013 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
// Copyright 2012-2013 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
//
|
//
|
// This program is free software; you may redistribute and/or modify it under
|
// This program is free software; you may redistribute and/or modify it under
|
// the terms of the GNU General Public License as published by the Free
|
// the terms of the GNU General Public License as published by the Free
|
Line 11... |
Line 11... |
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
// for complete details.
|
// for complete details.
|
//
|
//
|
// Revision History:
|
// Revision History:
|
// Date Rev Version Comment
|
// Date Rev Version Comment
|
|
// 2013-05-17 521 1.1.1 use Rtools::String2Long
|
// 2013-02-23 492 1.1 use RparseUrl
|
// 2013-02-23 492 1.1 use RparseUrl
|
// 2013-02-10 485 1.0.3 add static const defs
|
// 2013-02-10 485 1.0.3 add static const defs
|
// 2013-02-03 481 1.0.2 use Rexception
|
// 2013-02-03 481 1.0.2 use Rexception
|
// 2013-01-02 467 1.0.1 get cleanup code right; add USBErrorName()
|
// 2013-01-02 467 1.0.1 get cleanup code right; add USBErrorName()
|
// 2012-12-26 465 1.0 Initial version
|
// 2012-12-26 465 1.0 Initial version
|
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
|
|
/*!
|
/*!
|
\file
|
\file
|
\version $Id: RlinkPortCuff.cpp 516 2013-05-05 21:24:52Z mueller $
|
\version $Id: RlinkPortCuff.cpp 524 2013-06-30 19:10:30Z mueller $
|
\brief Implemenation of RlinkPortCuff.
|
\brief Implemenation of RlinkPortCuff.
|
*/
|
*/
|
|
|
#include <errno.h>
|
#include <errno.h>
|
#include <unistd.h>
|
#include <unistd.h>
|
Line 37... |
Line 38... |
#include <sstream>
|
#include <sstream>
|
|
|
#include "RlinkPortCuff.hpp"
|
#include "RlinkPortCuff.hpp"
|
|
|
#include "librtools/Rexception.hpp"
|
#include "librtools/Rexception.hpp"
|
|
#include "librtools/Rtools.hpp"
|
|
|
using namespace std;
|
using namespace std;
|
|
|
/*!
|
/*!
|
\class Retro::RlinkPortCuff
|
\class Retro::RlinkPortCuff
|
Line 139... |
Line 141... |
libusb_device* mydev = 0;
|
libusb_device* mydev = 0;
|
// path syntax: /bus/dev
|
// path syntax: /bus/dev
|
if (fUrl.Path().length()==8 && fUrl.Path()[0]=='/' && fUrl.Path()[4]=='/') {
|
if (fUrl.Path().length()==8 && fUrl.Path()[0]=='/' && fUrl.Path()[4]=='/') {
|
string busnam = fUrl.Path().substr(1,3);
|
string busnam = fUrl.Path().substr(1,3);
|
string devnam = fUrl.Path().substr(5,3);
|
string devnam = fUrl.Path().substr(5,3);
|
char* endptr;
|
unsigned long busnum;
|
uint8_t busnum = ::strtol(busnam.c_str(), &endptr, 10);
|
unsigned long devnum;
|
uint8_t devnum = ::strtol(devnam.c_str(), &endptr, 10);
|
if (!Rtools::String2Long(busnam, busnum, emsg) ||
|
|
!Rtools::String2Long(devnam, devnum, emsg)) {
|
|
Cleanup();
|
|
return false;
|
|
}
|
for (ssize_t idev=0; idev<fUsbDevCount; idev++) {
|
for (ssize_t idev=0; idev<fUsbDevCount; idev++) {
|
libusb_device* udev = fpUsbDevList[idev];
|
libusb_device* udev = fpUsbDevList[idev];
|
if (libusb_get_bus_number(udev) == busnum &&
|
if (libusb_get_bus_number(udev) == busnum &&
|
libusb_get_device_address(udev) == devnum) {
|
libusb_get_device_address(udev) == devnum) {
|
mydev = udev;
|
mydev = udev;
|
Line 153... |
Line 159... |
}
|
}
|
// path syntax: vend:prod
|
// path syntax: vend:prod
|
} else if (fUrl.Path().length()==9 && fUrl.Path()[4]==':') {
|
} else if (fUrl.Path().length()==9 && fUrl.Path()[4]==':') {
|
string vennam = fUrl.Path().substr(0,4);
|
string vennam = fUrl.Path().substr(0,4);
|
string pronam = fUrl.Path().substr(5,4);
|
string pronam = fUrl.Path().substr(5,4);
|
char* endptr;
|
unsigned long vennum;
|
uint16_t vennum = ::strtol(vennam.c_str(), &endptr, 16);
|
unsigned long pronum;
|
uint16_t pronum = ::strtol(pronam.c_str(), &endptr, 16);
|
if (!Rtools::String2Long(vennam, vennum, emsg, 16) ||
|
|
!Rtools::String2Long(pronam, pronum, emsg, 16)) {
|
|
Cleanup();
|
|
return false;
|
|
}
|
for (ssize_t idev=0; idev<fUsbDevCount; idev++) {
|
for (ssize_t idev=0; idev<fUsbDevCount; idev++) {
|
libusb_device* udev = fpUsbDevList[idev];
|
libusb_device* udev = fpUsbDevList[idev];
|
libusb_device_descriptor devdsc;
|
libusb_device_descriptor devdsc;
|
libusb_get_device_descriptor(udev, &devdsc);
|
libusb_get_device_descriptor(udev, &devdsc);
|
if (devdsc.idVendor==vennum && devdsc.idProduct==pronum) {
|
if (devdsc.idVendor==vennum && devdsc.idProduct==pronum) {
|
Line 171... |
Line 181... |
string("invalid usb path '") + fUrl.Path() +
|
string("invalid usb path '") + fUrl.Path() +
|
"', not '/bus/dev' or 'vend:prod'");
|
"', not '/bus/dev' or 'vend:prod'");
|
Cleanup();
|
Cleanup();
|
return false;
|
return false;
|
}
|
}
|
|
|
if (mydev == 0) {
|
if (mydev == 0) {
|
emsg.Init("RlinkPortCuff::Open()",
|
emsg.Init("RlinkPortCuff::Open()",
|
string("no usb device '") + fUrl.Path() + "', found'");
|
string("no usb device '") + fUrl.Path() + "', found'");
|
Cleanup();
|
Cleanup();
|
return false;
|
return false;
|
Line 328... |
Line 339... |
t->flags = LIBUSB_TRANSFER_FREE_BUFFER;
|
t->flags = LIBUSB_TRANSFER_FREE_BUFFER;
|
t->endpoint = (unsigned char) (kUSBReadEP|0x80);
|
t->endpoint = (unsigned char) (kUSBReadEP|0x80);
|
t->type = LIBUSB_TRANSFER_TYPE_BULK;
|
t->type = LIBUSB_TRANSFER_TYPE_BULK;
|
t->timeout = 0;
|
t->timeout = 0;
|
t->status = LIBUSB_TRANSFER_COMPLETED;
|
t->status = LIBUSB_TRANSFER_COMPLETED;
|
t->buffer = (unsigned char*) malloc(kUSBBufferSize);
|
t->buffer = (unsigned char*) ::malloc(kUSBBufferSize);
|
t->length = kUSBBufferSize;
|
t->length = kUSBBufferSize;
|
t->actual_length = 0;
|
t->actual_length = 0;
|
t->callback = ThunkUSBReadDone;
|
t->callback = ThunkUSBReadDone;
|
t->user_data = this;
|
t->user_data = this;
|
|
|
Line 344... |
Line 355... |
|
|
// event loop
|
// event loop
|
if (TraceOn()) cout << "event loop started" << endl;
|
if (TraceOn()) cout << "event loop started" << endl;
|
fLoopState = kLoopStateRunning;
|
fLoopState = kLoopStateRunning;
|
while(fLoopState == kLoopStateRunning) {
|
while(fLoopState == kLoopStateRunning) {
|
int irc = poll(fPollFds.data(), fPollFds.size(), 1000);
|
int irc = ::poll(fPollFds.data(), fPollFds.size(), 1000);
|
if (irc==-1 && errno==EINTR) continue;
|
if (irc==-1 && errno==EINTR) continue;
|
if (irc!=0 && TraceOn()) {
|
if (irc!=0 && TraceOn()) {
|
cout << "poll() -> " << irc << " :";
|
cout << "poll() -> " << irc << " :";
|
for (size_t i=0; i<fPollFds.size(); i++)
|
for (size_t i=0; i<fPollFds.size(); i++)
|
if (fPollFds[i].revents) cout << " (" << fPollFds[i].fd << ","
|
if (fPollFds[i].revents) cout << " (" << fPollFds[i].fd << ","
|
Line 377... |
Line 388... |
libusb_cancel_transfer(fReadQueuePending[i]);
|
libusb_cancel_transfer(fReadQueuePending[i]);
|
}
|
}
|
|
|
while(fLoopState == kLoopStateStopping &&
|
while(fLoopState == kLoopStateStopping &&
|
fWriteQueuePending.size() + fReadQueuePending.size() > 0) {
|
fWriteQueuePending.size() + fReadQueuePending.size() > 0) {
|
int irc = poll(fPollFds.data()+1, fPollFds.size()-1, 1000);
|
int irc = ::poll(fPollFds.data()+1, fPollFds.size()-1, 1000);
|
if (irc==-1 && errno==EINTR) continue;
|
if (irc==-1 && errno==EINTR) continue;
|
if (irc==0) break;
|
if (irc==0) break;
|
if (irc < 0) BadSysCall("RlinkPortCuff::Driver()", "poll()", irc);
|
if (irc < 0) BadSysCall("RlinkPortCuff::Driver()", "poll()", irc);
|
DriverEventUSB();
|
DriverEventUSB();
|
}
|
}
|
Line 393... |
Line 404... |
|
|
} catch (exception& e) {
|
} catch (exception& e) {
|
cout << "exception caught in RlinkPortCuff::Driver(): '" << e.what()
|
cout << "exception caught in RlinkPortCuff::Driver(): '" << e.what()
|
<< "'" << endl;
|
<< "'" << endl;
|
// close read pipe at driver end -> that causes main thread to respond
|
// close read pipe at driver end -> that causes main thread to respond
|
close(fFdReadDriver);
|
::close(fFdReadDriver);
|
fFdReadDriver = -1;
|
fFdReadDriver = -1;
|
}
|
}
|
|
|
return;
|
return;
|
}
|
}
|
Line 407... |
Line 418... |
|
|
void RlinkPortCuff::DriverEventWritePipe()
|
void RlinkPortCuff::DriverEventWritePipe()
|
{
|
{
|
libusb_transfer* t = NewWriteTransfer();
|
libusb_transfer* t = NewWriteTransfer();
|
|
|
ssize_t ircs = read(fFdWriteDriver, t->buffer, kUSBBufferSize);
|
ssize_t ircs = ::read(fFdWriteDriver, t->buffer, kUSBBufferSize);
|
if (TraceOn()) cout << "write pipe read() -> " << ircs << endl;
|
if (TraceOn()) cout << "write pipe read() -> " << ircs << endl;
|
if (ircs < 0) BadSysCall("RlinkPortCuff::DriverEventWritePipe()",
|
if (ircs < 0) BadSysCall("RlinkPortCuff::DriverEventWritePipe()",
|
"read()", ircs);
|
"read()", ircs);
|
|
|
// pipe closed... end driver event loop
|
// pipe closed... end driver event loop
|
Line 459... |
Line 470... |
t->dev_handle = fpUsbDevHdl;
|
t->dev_handle = fpUsbDevHdl;
|
t->flags = LIBUSB_TRANSFER_FREE_BUFFER;
|
t->flags = LIBUSB_TRANSFER_FREE_BUFFER;
|
t->endpoint = (unsigned char) (kUSBWriteEP);
|
t->endpoint = (unsigned char) (kUSBWriteEP);
|
t->type = LIBUSB_TRANSFER_TYPE_BULK;
|
t->type = LIBUSB_TRANSFER_TYPE_BULK;
|
t->timeout = 1000;
|
t->timeout = 1000;
|
t->buffer = (unsigned char*) malloc(kUSBBufferSize);
|
t->buffer = (unsigned char*) ::malloc(kUSBBufferSize);
|
t->callback = ThunkUSBWriteDone;
|
t->callback = ThunkUSBWriteDone;
|
t->user_data = this;
|
t->user_data = this;
|
}
|
}
|
|
|
t->status = LIBUSB_TRANSFER_COMPLETED;
|
t->status = LIBUSB_TRANSFER_COMPLETED;
|
Line 645... |
Line 656... |
|
|
if (fLoopState == kLoopStateRunning) {
|
if (fLoopState == kLoopStateRunning) {
|
CheckUSBTransfer("RlinkPortCuff::USBReadDone()", t);
|
CheckUSBTransfer("RlinkPortCuff::USBReadDone()", t);
|
fStats.Inc(kStatNUSBRead);
|
fStats.Inc(kStatNUSBRead);
|
if (t->actual_length>0) {
|
if (t->actual_length>0) {
|
ssize_t ircs = write(fFdReadDriver, t->buffer, (size_t) t->actual_length);
|
ssize_t ircs = ::write(fFdReadDriver, t->buffer,
|
|
(size_t) t->actual_length);
|
if (ircs < 0) BadSysCall("RlinkPortCuff::USBReadDone()",
|
if (ircs < 0) BadSysCall("RlinkPortCuff::USBReadDone()",
|
"write()", ircs);
|
"write()", ircs);
|
}
|
}
|
|
|
t->status = LIBUSB_TRANSFER_COMPLETED;
|
t->status = LIBUSB_TRANSFER_COMPLETED;
|