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