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
20static ssize_t kHeaderSize = sizeof(wacom_device_header);
21
22// constructor
23DeviceReader::DeviceReader()
24	:
25	fDevicePath(NULL),
26	fDeviceFile(NULL),
27	fVendorID(0),
28	fProductID(0),
29	fMaxPacketSize(0)
30{
31}
32
33// destructor
34DeviceReader::~DeviceReader()
35{
36	_Unset();
37}
38
39// SetTo
40status_t
41DeviceReader::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
68status_t
69DeviceReader::InitCheck() const
70{
71	return fDeviceFile && fDevicePath ? fDeviceFile->InitCheck() : B_NO_INIT;
72}
73
74// DevicePath
75const char*
76DeviceReader::DevicePath() const
77{
78	return fDevicePath;
79}
80
81// DeviceFile
82BFile*
83DeviceReader::DeviceFile() const
84{
85	return fDeviceFile;
86}
87
88// VendorID
89uint16
90DeviceReader::VendorID() const
91{
92	return fVendorID;
93}
94
95// ProductID
96uint16
97DeviceReader::ProductID() const
98{
99	return fProductID;
100}
101
102// MaxPacketSize
103size_t
104DeviceReader::MaxPacketSize() const
105{
106	return fMaxPacketSize;
107}
108
109// ReadData
110ssize_t
111DeviceReader::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);
125PRINT(("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
150void
151DeviceReader::_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