1dc1bdabbSStephan Aßmus /*
2*29ae0e0fSCodeforEvolution * Copyright 2005-2008 Stephan Aßmus <superstippi@gmx.de>
3*29ae0e0fSCodeforEvolution * Copyright 2020 Jacob Secunda <secundaja@gmail.com>
4*29ae0e0fSCodeforEvolution * All rights reserved. Distributed under the terms of the MIT license.
5dc1bdabbSStephan Aßmus */
6*29ae0e0fSCodeforEvolution
7*29ae0e0fSCodeforEvolution
8dc1bdabbSStephan Aßmus #include "DeviceReader.h"
9dc1bdabbSStephan Aßmus
10dc1bdabbSStephan Aßmus #include <malloc.h>
11dc1bdabbSStephan Aßmus #include <string.h>
12dc1bdabbSStephan Aßmus
13dc1bdabbSStephan Aßmus #include <File.h>
14dc1bdabbSStephan Aßmus
15*29ae0e0fSCodeforEvolution #include <wacom_driver.h>
16*29ae0e0fSCodeforEvolution
17d4122828SStephan Aßmus #include "MasterServerDevice.h"
18d4122828SStephan Aßmus
19d4122828SStephan Aßmus
20*29ae0e0fSCodeforEvolution static ssize_t kHeaderSize = sizeof(wacom_device_header);
21dc1bdabbSStephan Aßmus
22dc1bdabbSStephan Aßmus // constructor
DeviceReader()23dc1bdabbSStephan Aßmus DeviceReader::DeviceReader()
24*29ae0e0fSCodeforEvolution :
25*29ae0e0fSCodeforEvolution fDevicePath(NULL),
26dc1bdabbSStephan Aßmus fDeviceFile(NULL),
27dc1bdabbSStephan Aßmus fVendorID(0),
28dc1bdabbSStephan Aßmus fProductID(0),
29*29ae0e0fSCodeforEvolution fMaxPacketSize(0)
30dc1bdabbSStephan Aßmus {
31dc1bdabbSStephan Aßmus }
32dc1bdabbSStephan Aßmus
33dc1bdabbSStephan Aßmus // destructor
~DeviceReader()34dc1bdabbSStephan Aßmus DeviceReader::~DeviceReader()
35dc1bdabbSStephan Aßmus {
36dc1bdabbSStephan Aßmus _Unset();
37dc1bdabbSStephan Aßmus }
38dc1bdabbSStephan Aßmus
39dc1bdabbSStephan Aßmus // SetTo
40dc1bdabbSStephan Aßmus status_t
SetTo(const char * path)41dc1bdabbSStephan Aßmus DeviceReader::SetTo(const char* path)
42dc1bdabbSStephan Aßmus {
43dc1bdabbSStephan Aßmus status_t ret = B_BAD_VALUE;
44*29ae0e0fSCodeforEvolution if (path != NULL) {
45dc1bdabbSStephan Aßmus _Unset();
46dc1bdabbSStephan Aßmus fDevicePath = strdup(path);
47dc1bdabbSStephan Aßmus fDeviceFile = new BFile(path, B_READ_ONLY);
48dc1bdabbSStephan Aßmus ret = fDeviceFile->InitCheck();
49dc1bdabbSStephan Aßmus if (ret >= B_OK) {
50*29ae0e0fSCodeforEvolution // read the wacom_device_header from the file and initialize
51dc1bdabbSStephan Aßmus // the rest of the object variables
52*29ae0e0fSCodeforEvolution wacom_device_header device_header;
53*29ae0e0fSCodeforEvolution ret = fDeviceFile->Read(&device_header, kHeaderSize);
54d4122828SStephan Aßmus if (ret == kHeaderSize) {
55dc1bdabbSStephan Aßmus ret = B_OK;
56*29ae0e0fSCodeforEvolution fVendorID = device_header.vendor_id;
57*29ae0e0fSCodeforEvolution fProductID = device_header.product_id;
58*29ae0e0fSCodeforEvolution fMaxPacketSize = device_header.max_packet_size;
59dc1bdabbSStephan Aßmus } else {
60dc1bdabbSStephan Aßmus _Unset();
61dc1bdabbSStephan Aßmus }
62dc1bdabbSStephan Aßmus }
63dc1bdabbSStephan Aßmus }
64dc1bdabbSStephan Aßmus return ret;
65dc1bdabbSStephan Aßmus }
66dc1bdabbSStephan Aßmus
67dc1bdabbSStephan Aßmus // InitCheck
68dc1bdabbSStephan Aßmus status_t
InitCheck() const69dc1bdabbSStephan Aßmus DeviceReader::InitCheck() const
70dc1bdabbSStephan Aßmus {
71dc1bdabbSStephan Aßmus return fDeviceFile && fDevicePath ? fDeviceFile->InitCheck() : B_NO_INIT;
72dc1bdabbSStephan Aßmus }
73dc1bdabbSStephan Aßmus
74dc1bdabbSStephan Aßmus // DevicePath
75dc1bdabbSStephan Aßmus const char*
DevicePath() const76dc1bdabbSStephan Aßmus DeviceReader::DevicePath() const
77dc1bdabbSStephan Aßmus {
78dc1bdabbSStephan Aßmus return fDevicePath;
79dc1bdabbSStephan Aßmus }
80dc1bdabbSStephan Aßmus
81dc1bdabbSStephan Aßmus // DeviceFile
82dc1bdabbSStephan Aßmus BFile*
DeviceFile() const83dc1bdabbSStephan Aßmus DeviceReader::DeviceFile() const
84dc1bdabbSStephan Aßmus {
85dc1bdabbSStephan Aßmus return fDeviceFile;
86dc1bdabbSStephan Aßmus }
87dc1bdabbSStephan Aßmus
88dc1bdabbSStephan Aßmus // VendorID
89dc1bdabbSStephan Aßmus uint16
VendorID() const90dc1bdabbSStephan Aßmus DeviceReader::VendorID() const
91dc1bdabbSStephan Aßmus {
92dc1bdabbSStephan Aßmus return fVendorID;
93dc1bdabbSStephan Aßmus }
94dc1bdabbSStephan Aßmus
95dc1bdabbSStephan Aßmus // ProductID
96dc1bdabbSStephan Aßmus uint16
ProductID() const97dc1bdabbSStephan Aßmus DeviceReader::ProductID() const
98dc1bdabbSStephan Aßmus {
99dc1bdabbSStephan Aßmus return fProductID;
100dc1bdabbSStephan Aßmus }
101dc1bdabbSStephan Aßmus
102dc1bdabbSStephan Aßmus // MaxPacketSize
103dc1bdabbSStephan Aßmus size_t
MaxPacketSize() const104dc1bdabbSStephan Aßmus DeviceReader::MaxPacketSize() const
105dc1bdabbSStephan Aßmus {
106*29ae0e0fSCodeforEvolution return fMaxPacketSize;
107dc1bdabbSStephan Aßmus }
108dc1bdabbSStephan Aßmus
109dc1bdabbSStephan Aßmus // ReadData
110d4122828SStephan Aßmus ssize_t
ReadData(uint8 * data,const size_t size) const111d4122828SStephan Aßmus DeviceReader::ReadData(uint8* data, const size_t size) const
112dc1bdabbSStephan Aßmus {
113*29ae0e0fSCodeforEvolution if (!fDeviceFile || fMaxPacketSize <= 0 || fMaxPacketSize > 128)
114d4122828SStephan Aßmus return B_NO_INIT;
115d4122828SStephan Aßmus status_t ret = fDeviceFile->InitCheck();
116d4122828SStephan Aßmus if (ret < B_OK)
117d4122828SStephan Aßmus return (ssize_t)ret;
118d4122828SStephan Aßmus
119*29ae0e0fSCodeforEvolution ssize_t requested = fMaxPacketSize + kHeaderSize;
120d4122828SStephan Aßmus uint8 buffer[requested];
121d4122828SStephan Aßmus ssize_t read = fDeviceFile->Read(buffer, requested);
122d4122828SStephan Aßmus if (read > kHeaderSize) {
123dc1bdabbSStephan Aßmus // make sure we don't copy too many bytes
124d4122828SStephan Aßmus size_t bytesToCopy = min_c(size, read - (size_t)kHeaderSize);
125d4122828SStephan Aßmus PRINT(("requested: %ld, read: %ld, user wants: %lu, copy bytes: %ld\n",
126d4122828SStephan Aßmus requested, read, size, bytesToCopy));
127d4122828SStephan Aßmus memcpy(data, buffer + kHeaderSize, bytesToCopy);
128dc1bdabbSStephan Aßmus // zero out any remaining bytes
129d4122828SStephan Aßmus if (size > bytesToCopy)
130d4122828SStephan Aßmus memset(data + bytesToCopy, 0, size - bytesToCopy);
131dc1bdabbSStephan Aßmus // operation could be considered successful
132d4122828SStephan Aßmus // read = bytesToCopy;
133d4122828SStephan Aßmus // if (read != (ssize_t)size)
134d4122828SStephan Aßmus // PRINT(("user wanted: %lu, returning: %ld\n", size, read));
135d4122828SStephan Aßmus read = size;
136d4122828SStephan Aßmus // pretend we could read as many bytes as requested
137d4122828SStephan Aßmus } else if (read == kHeaderSize || (status_t)read == B_TIMED_OUT) {
138dc1bdabbSStephan Aßmus // it's ok if the operation timed out
139dc1bdabbSStephan Aßmus memset(data, 0, size);
140d4122828SStephan Aßmus read = (size_t)B_OK;
141d4122828SStephan Aßmus } else {
142d4122828SStephan Aßmus PRINT(("requested: %ld, read: %ld, user wants: %lu\n",
143d4122828SStephan Aßmus requested, read, size));
144dc1bdabbSStephan Aßmus }
145d4122828SStephan Aßmus
146d4122828SStephan Aßmus return read;
147dc1bdabbSStephan Aßmus }
148dc1bdabbSStephan Aßmus
149dc1bdabbSStephan Aßmus // _Unset
150dc1bdabbSStephan Aßmus void
_Unset()151dc1bdabbSStephan Aßmus DeviceReader::_Unset()
152dc1bdabbSStephan Aßmus {
153dc1bdabbSStephan Aßmus free(fDevicePath);
154dc1bdabbSStephan Aßmus fDevicePath = NULL;
155dc1bdabbSStephan Aßmus delete fDeviceFile;
156dc1bdabbSStephan Aßmus fDeviceFile = NULL;
157dc1bdabbSStephan Aßmus fVendorID = 0;
158dc1bdabbSStephan Aßmus fProductID = 0;
159*29ae0e0fSCodeforEvolution fMaxPacketSize = 0;
160dc1bdabbSStephan Aßmus }
161