This source file includes following definitions.
- Connected
- OnFileCanReadWithoutBlocking
- OnFileCanWriteWithoutBlocking
- Create
- Disconnect
- BrlapiError
- BrlapiStrError
- GetDisplaySize
- WriteDots
- ReadKey
- CheckConnected
- ConnectResultForError
#include "chrome/browser/extensions/api/braille_display_private/brlapi_connection.h"
#include <errno.h>
#include "base/message_loop/message_loop.h"
#include "base/sys_info.h"
namespace extensions {
using base::MessageLoopForIO;
namespace api {
namespace braille_display_private {
namespace {
static const int kDefaultTtyLinux = 7;
#if defined(OS_CHROMEOS)
static const int kDefaultTtyChromeOS = 1;
#endif
}
class BrlapiConnectionImpl : public BrlapiConnection,
MessageLoopForIO::Watcher {
public:
explicit BrlapiConnectionImpl(LibBrlapiLoader* loader) :
libbrlapi_loader_(loader) {}
virtual ~BrlapiConnectionImpl() {
Disconnect();
}
virtual ConnectResult Connect(const OnDataReadyCallback& on_data_ready)
OVERRIDE;
virtual void Disconnect() OVERRIDE;
virtual bool Connected() OVERRIDE { return handle_; }
virtual brlapi_error_t* BrlapiError() OVERRIDE;
virtual std::string BrlapiStrError() OVERRIDE;
virtual bool GetDisplaySize(size_t* size) OVERRIDE;
virtual bool WriteDots(const unsigned char* cells) OVERRIDE;
virtual int ReadKey(brlapi_keyCode_t* keyCode) OVERRIDE;
virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE {
on_data_ready_.Run();
}
virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {}
private:
bool CheckConnected();
ConnectResult ConnectResultForError();
LibBrlapiLoader* libbrlapi_loader_;
scoped_ptr<brlapi_handle_t, base::FreeDeleter> handle_;
MessageLoopForIO::FileDescriptorWatcher fd_controller_;
OnDataReadyCallback on_data_ready_;
DISALLOW_COPY_AND_ASSIGN(BrlapiConnectionImpl);
};
BrlapiConnection::BrlapiConnection() {
}
BrlapiConnection::~BrlapiConnection() {
}
scoped_ptr<BrlapiConnection> BrlapiConnection::Create(
LibBrlapiLoader* loader) {
DCHECK(loader->loaded());
return scoped_ptr<BrlapiConnection>(new BrlapiConnectionImpl(loader));
}
BrlapiConnection::ConnectResult BrlapiConnectionImpl::Connect(
const OnDataReadyCallback& on_data_ready) {
DCHECK(!handle_);
handle_.reset((brlapi_handle_t*) malloc(
libbrlapi_loader_->brlapi_getHandleSize()));
int fd = libbrlapi_loader_->brlapi__openConnection(handle_.get(), NULL, NULL);
if (fd < 0) {
handle_.reset();
VLOG(1) << "Error connecting to brlapi: " << BrlapiStrError();
return ConnectResultForError();
}
int path[2] = {0, 0};
int pathElements = 0;
#if defined(OS_CHROMEOS)
if (base::SysInfo::IsRunningOnChromeOS())
path[pathElements++] = kDefaultTtyChromeOS;
#endif
if (pathElements == 0 && getenv("WINDOWPATH") == NULL)
path[pathElements++] = kDefaultTtyLinux;
if (libbrlapi_loader_->brlapi__enterTtyModeWithPath(
handle_.get(), path, pathElements, NULL) < 0) {
LOG(ERROR) << "brlapi: couldn't enter tty mode: " << BrlapiStrError();
Disconnect();
return CONNECT_ERROR_RETRY;
}
size_t size;
if (!GetDisplaySize(&size)) {
Disconnect();
return CONNECT_ERROR_RETRY;
}
if (size == 0) {
VLOG(1) << "No braille display connected";
Disconnect();
return CONNECT_ERROR_RETRY;
}
const brlapi_keyCode_t extraKeys[] = {
BRLAPI_KEY_TYPE_CMD | BRLAPI_KEY_CMD_OFFLINE,
};
if (libbrlapi_loader_->brlapi__acceptKeys(
handle_.get(), brlapi_rangeType_command, extraKeys,
arraysize(extraKeys)) < 0) {
LOG(ERROR) << "Couldn't acceptKeys: " << BrlapiStrError();
Disconnect();
return CONNECT_ERROR_RETRY;
}
if (!MessageLoopForIO::current()->WatchFileDescriptor(
fd, true, MessageLoopForIO::WATCH_READ, &fd_controller_, this)) {
LOG(ERROR) << "Couldn't watch file descriptor " << fd;
Disconnect();
return CONNECT_ERROR_RETRY;
}
on_data_ready_ = on_data_ready;
return CONNECT_SUCCESS;
}
void BrlapiConnectionImpl::Disconnect() {
if (!handle_) {
return;
}
fd_controller_.StopWatchingFileDescriptor();
libbrlapi_loader_->brlapi__closeConnection(
handle_.get());
handle_.reset();
}
brlapi_error_t* BrlapiConnectionImpl::BrlapiError() {
return libbrlapi_loader_->brlapi_error_location();
}
std::string BrlapiConnectionImpl::BrlapiStrError() {
return libbrlapi_loader_->brlapi_strerror(BrlapiError());
}
bool BrlapiConnectionImpl::GetDisplaySize(size_t* size) {
if (!CheckConnected()) {
return false;
}
unsigned int columns, rows;
if (libbrlapi_loader_->brlapi__getDisplaySize(
handle_.get(), &columns, &rows) < 0) {
LOG(ERROR) << "Couldn't get braille display size " << BrlapiStrError();
return false;
}
*size = columns * rows;
return true;
}
bool BrlapiConnectionImpl::WriteDots(const unsigned char* cells) {
if (!CheckConnected())
return false;
if (libbrlapi_loader_->brlapi__writeDots(handle_.get(), cells) < 0) {
VLOG(1) << "Couldn't write to brlapi: " << BrlapiStrError();
return false;
}
return true;
}
int BrlapiConnectionImpl::ReadKey(brlapi_keyCode_t* key_code) {
if (!CheckConnected())
return -1;
return libbrlapi_loader_->brlapi__readKey(
handle_.get(), 0 , key_code);
}
bool BrlapiConnectionImpl::CheckConnected() {
if (!handle_) {
BrlapiError()->brlerrno = BRLAPI_ERROR_ILLEGAL_INSTRUCTION;
return false;
}
return true;
}
BrlapiConnection::ConnectResult BrlapiConnectionImpl::ConnectResultForError() {
const brlapi_error_t* error = BrlapiError();
if (error->brlerrno == BRLAPI_ERROR_LIBCERR
&& error->libcerrno == ENOENT) {
return CONNECT_ERROR_NO_RETRY;
}
return CONNECT_ERROR_RETRY;
}
}
}
}