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