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