* Switch to using USBKit instead of usb_printer kernel driver
* Implement new transport id/name listing git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36115 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
77b2080187
commit
c52f7982c9
@ -2,14 +2,14 @@ SubDir HAIKU_TOP src add-ons print transports usb_port ;
|
||||
|
||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
|
||||
UsePrivateHeaders print ;
|
||||
UsePrivateHeaders shared print ;
|
||||
|
||||
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits print ] ;
|
||||
|
||||
Addon USB\ Port :
|
||||
USBTransport.cpp
|
||||
PrintTransportAddOn.cpp
|
||||
: be $(TARGET_LIBSUPC++)
|
||||
: libshared.a libdevice.so be $(TARGET_LIBSUPC++)
|
||||
;
|
||||
|
||||
Package haiku-printingkit-cvs :
|
||||
|
@ -1,50 +1,68 @@
|
||||
/*****************************************************************************/
|
||||
// USB port transport add-on,
|
||||
// changes by Andreas Benzler, Philippe Houdoin
|
||||
//
|
||||
// Original from Parallel
|
||||
// port transport add-on.
|
||||
//
|
||||
// Author
|
||||
// Michael Pfeiffer
|
||||
//
|
||||
// This application and all source files used in its construction, except
|
||||
// where noted, are licensed under the MIT License, and have been written
|
||||
// and are:
|
||||
//
|
||||
// Copyright (c) 2001-2004 OpenBeOS Project
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <StorageKit.h>
|
||||
#include <SupportKit.h>
|
||||
|
||||
#include <USB_printer.h>
|
||||
/*
|
||||
* Copyright 2001-2010 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Originally written based on Parallel port addon by Michael Pfeiffer,
|
||||
* changes by Andreas Benzler, Philippe Houdoin
|
||||
* Rewritten to use the USBKit by Ithamar R. Adema.
|
||||
* (Using code from usb_printer.cpp by Michael Lotz)
|
||||
*
|
||||
* Authors:
|
||||
* Ithamar R. Adema, <ithamar.adema@team-embedded.nl>
|
||||
* Michael Pfeiffer,
|
||||
* Andreas Benzler,
|
||||
* Philippe Houdoin,
|
||||
*/
|
||||
|
||||
#include "PrintTransportAddOn.h"
|
||||
|
||||
#include <USBKit.h>
|
||||
#include <String.h>
|
||||
|
||||
#include <HashString.h>
|
||||
#include <HashMap.h>
|
||||
|
||||
#define PRINTER_INTERFACE_CLASS 0x07
|
||||
#define PRINTER_INTERFACE_SUBCLASS 0x01
|
||||
|
||||
// printer interface types
|
||||
#define PIT_UNIDIRECTIONAL 0x01
|
||||
#define PIT_BIDIRECTIONAL 0x02
|
||||
#define PIT_1284_4_COMPATIBLE 0x03
|
||||
#define PIT_VENDOR_SPECIFIC 0xff
|
||||
|
||||
class USBPrinter
|
||||
{
|
||||
public:
|
||||
USBPrinter(const BString& id, const BString& name,
|
||||
const BUSBInterface *intf, const BUSBEndpoint* in, const BUSBEndpoint* out);
|
||||
|
||||
ssize_t Write(const void *buf, size_t size);
|
||||
ssize_t Read(void *buf, size_t size);
|
||||
|
||||
const BUSBInterface *fInterface;
|
||||
const BUSBEndpoint *fOut;
|
||||
const BUSBEndpoint *fIn;
|
||||
BString fName;
|
||||
BString fID;
|
||||
};
|
||||
|
||||
|
||||
class USBPrinterRoster : public BUSBRoster {
|
||||
public:
|
||||
USBPrinterRoster();
|
||||
|
||||
status_t DeviceAdded(BUSBDevice* dev);
|
||||
void DeviceRemoved(BUSBDevice* dev);
|
||||
|
||||
USBPrinter *Printer(const BString& key);
|
||||
|
||||
status_t ListPrinters(BMessage *msg);
|
||||
private:
|
||||
typedef HashMap<HashString,USBPrinter*> PrinterMap;
|
||||
PrinterMap fPrinters;
|
||||
};
|
||||
|
||||
|
||||
class USBTransport : public BDataIO
|
||||
{
|
||||
@ -52,16 +70,152 @@ public:
|
||||
USBTransport(BDirectory *printer, BMessage *msg);
|
||||
~USBTransport();
|
||||
|
||||
status_t InitCheck() { return fFile > -1 ? B_OK : B_ERROR; };
|
||||
status_t InitCheck() { return fPrinter ? B_OK : B_ERROR; };
|
||||
|
||||
ssize_t Read(void *buffer, size_t size);
|
||||
ssize_t Write(const void *buffer, size_t size);
|
||||
|
||||
private:
|
||||
int fFile;
|
||||
USBPrinter *fPrinter;
|
||||
};
|
||||
|
||||
|
||||
// Set transport_features so we stay loaded
|
||||
uint32 transport_features = B_TRANSPORT_IS_HOTPLUG;
|
||||
|
||||
USBPrinterRoster gUSBPrinterRoster;
|
||||
|
||||
USBPrinterRoster::USBPrinterRoster()
|
||||
{
|
||||
Start();
|
||||
}
|
||||
|
||||
USBPrinter *USBPrinterRoster::Printer(const BString& key)
|
||||
{
|
||||
if (fPrinters.ContainsKey(key.String()))
|
||||
return fPrinters.Get(key.String());
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status_t USBPrinterRoster::DeviceAdded(BUSBDevice* dev)
|
||||
{
|
||||
const BUSBConfiguration *cfg = dev->ActiveConfiguration();
|
||||
const BUSBEndpoint *in = NULL, *out = NULL;
|
||||
const BUSBInterface *printer = NULL;
|
||||
|
||||
// Try to find a working printer interface in this device
|
||||
if (cfg) {
|
||||
for (uint32 idx=0; printer == NULL && idx < cfg->CountInterfaces(); idx++) {
|
||||
const BUSBInterface *intf=cfg->InterfaceAt(idx);
|
||||
if (intf->Class() == PRINTER_INTERFACE_CLASS &&
|
||||
intf->Subclass() == PRINTER_INTERFACE_SUBCLASS &&
|
||||
(intf->Protocol() == PIT_UNIDIRECTIONAL ||
|
||||
intf->Protocol() == PIT_BIDIRECTIONAL ||
|
||||
intf->Protocol() == PIT_1284_4_COMPATIBLE)) {
|
||||
// Found a usable Printer interface!
|
||||
for (uint32 eptidx=0; eptidx < intf->CountEndpoints(); eptidx++) {
|
||||
const BUSBEndpoint *ept = intf->EndpointAt(eptidx);
|
||||
if (!ept->IsBulk())
|
||||
continue;
|
||||
|
||||
if (ept->IsInput())
|
||||
in = ept;
|
||||
else if (ept->IsOutput())
|
||||
out = ept;
|
||||
|
||||
if (!in || !out)
|
||||
continue;
|
||||
|
||||
printer = intf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (printer != NULL) {
|
||||
// We found a working printer interface, lets determine a unique ID
|
||||
// for it now, and a user identification for display in the Printers
|
||||
// preference.
|
||||
BString port_id = dev->SerialNumberString();
|
||||
if (!port_id.Length()) {
|
||||
// No persistent unique ID available, use the vendor/product
|
||||
// ID for now. This will be unique as long as no two similar
|
||||
// devices are attached.
|
||||
port_id << dev->VendorID() << "/" << dev->ProductID();
|
||||
}
|
||||
|
||||
BString port_name = dev->ManufacturerString();
|
||||
if (port_name.Length())
|
||||
port_name << " ";
|
||||
port_name << dev->ProductString();
|
||||
|
||||
//TODO: Do we want to use usb.ids to find proper name if strings
|
||||
// are not supplied by USB?
|
||||
|
||||
fPrinters.Put(port_id.String(), new USBPrinter(port_id, port_name,
|
||||
printer, in, out));
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
void USBPrinterRoster::DeviceRemoved(BUSBDevice* dev)
|
||||
{
|
||||
PrinterMap::Iterator iterator = fPrinters.GetIterator();
|
||||
while (iterator.HasNext()) {
|
||||
const PrinterMap::Entry& entry = iterator.Next();
|
||||
// If the device is in the list, remove it
|
||||
if (entry.value->fInterface->Device() == dev) {
|
||||
fPrinters.Remove(entry.key);
|
||||
delete entry.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t USBPrinterRoster::ListPrinters(BMessage* msg)
|
||||
{
|
||||
PrinterMap::Iterator iterator = fPrinters.GetIterator();
|
||||
while (iterator.HasNext()) {
|
||||
const PrinterMap::Entry& entry = iterator.Next();
|
||||
msg->AddString("port_id", entry.value->fID);
|
||||
msg->AddString("port_name", entry.value->fName);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
USBPrinter::USBPrinter(const BString& id, const BString& name,
|
||||
const BUSBInterface *intf, const BUSBEndpoint* in, const BUSBEndpoint* out)
|
||||
: fInterface(intf), fOut(out), fIn(in), fName(name), fID(id)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//TODO: see usb_printer.cpp for error handling during read/write!
|
||||
ssize_t USBPrinter::Write(const void *buf, size_t size)
|
||||
{
|
||||
if (!buf || size <= 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// NOTE: we can safely cast below as we're sending data _out_
|
||||
return fOut->BulkTransfer((void*)buf, size);
|
||||
}
|
||||
|
||||
|
||||
ssize_t USBPrinter::Read(void *buf, size_t size)
|
||||
{
|
||||
if (!buf || size <= 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return fIn->BulkTransfer(buf, size);
|
||||
}
|
||||
|
||||
|
||||
// Implementation of transport add-on interface
|
||||
|
||||
BDataIO *
|
||||
@ -75,99 +229,48 @@ instantiate_transport(BDirectory *printer, BMessage *msg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// List detected printers
|
||||
status_t list_transport_ports(BMessage* msg)
|
||||
{
|
||||
BDirectory dir("/dev/printer/usb");
|
||||
status_t rc;
|
||||
|
||||
if ((rc=dir.InitCheck()) != B_OK)
|
||||
return rc;
|
||||
|
||||
if ((rc=dir.Rewind()) != B_OK)
|
||||
return rc;
|
||||
|
||||
entry_ref ref;
|
||||
while(dir.GetNextRef(&ref) == B_OK)
|
||||
msg->AddString("port_id", ref.name);
|
||||
|
||||
return B_OK;
|
||||
return gUSBPrinterRoster.ListPrinters(msg);
|
||||
}
|
||||
|
||||
|
||||
// Implementation of USBTransport
|
||||
|
||||
USBTransport::USBTransport(BDirectory *printer, BMessage *msg)
|
||||
: fFile(-1)
|
||||
: fPrinter(NULL)
|
||||
{
|
||||
char device_id[USB_PRINTER_DEVICE_ID_LENGTH + 1];
|
||||
char name[USB_PRINTER_DEVICE_ID_LENGTH + 1];
|
||||
char *desc;
|
||||
char *value;
|
||||
int ret;
|
||||
bool bidirectional = true;
|
||||
char *next_token;
|
||||
|
||||
// We support only one USB printer, so does BeOS R5.
|
||||
fFile = open("/dev/printer/usb/0", O_RDWR | O_EXCL | O_BINARY, 0);
|
||||
if (fFile < 0) {
|
||||
// Try unidirectional access mode
|
||||
bidirectional = false;
|
||||
fFile = open("/dev/printer/usb/0", O_WRONLY | O_EXCL | O_BINARY, 0);
|
||||
}
|
||||
|
||||
if (fFile < 0)
|
||||
BString key;
|
||||
|
||||
if (printer->ReadAttrString("transport_address", &key) < 0)
|
||||
return;
|
||||
|
||||
// Get printer's DEVICE ID string
|
||||
ret = ioctl(fFile, USB_PRINTER_GET_DEVICE_ID, device_id, sizeof(device_id));
|
||||
if (ret < 0) {
|
||||
close(fFile);
|
||||
fFile = -1;
|
||||
|
||||
fPrinter = gUSBPrinterRoster.Printer(key.String());
|
||||
if (!fPrinter)
|
||||
return;
|
||||
}
|
||||
|
||||
if (! msg)
|
||||
// Caller don't care about transport init message output content...
|
||||
|
||||
// If caller doesn't care...
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
|
||||
// Fill up the message
|
||||
msg->what = 'okok';
|
||||
|
||||
msg->AddBool("bidirectional", bidirectional);
|
||||
msg->AddString("device_id", device_id);
|
||||
|
||||
// parse and split the device_id string into separate parameters
|
||||
desc = strtok_r(device_id, ":", &next_token);
|
||||
while (desc) {
|
||||
snprintf(name, sizeof(name), "DEVID:%s", desc);
|
||||
value = strtok_r(NULL, ";", &next_token);
|
||||
if (!value)
|
||||
break;
|
||||
msg->AddString(name, value);
|
||||
|
||||
// next device descriptor
|
||||
desc = strtok_r(NULL, ":", &next_token);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
USBTransport::~USBTransport()
|
||||
{
|
||||
if (fFile > -1)
|
||||
close(fFile);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
USBTransport::Read(void *buffer, size_t size)
|
||||
{
|
||||
return read(fFile, buffer, size);
|
||||
return fPrinter ? fPrinter->Read(buffer, size) : B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
USBTransport::Write(const void *buffer, size_t size)
|
||||
{
|
||||
return write(fFile, buffer, size);
|
||||
return fPrinter ? fPrinter->Write(buffer, size) : B_ERROR;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user