libmanta
A cross-platform API for the Snyderphonics Manta
|
00001 #include "extern/hidapi/hidapi/hidapi.h" 00002 #include <cassert> 00003 #include "MantaUSB.h" 00004 #include "MantaExceptions.h" 00005 #include <cstdlib> 00006 #include <cstring> 00007 #include <wchar.h> 00008 00009 MantaUSB::MantaUSB(void) : 00010 SerialNumber(0), 00011 DeviceHandle(NULL) 00012 { 00013 mantaList.push_back(this); 00014 MantaIndex = mantaList.size(); 00015 00016 DebugPrint("%s-%d: Manta %d initialized", __FILE__, __LINE__, MantaIndex); 00017 } 00018 00019 MantaUSB::~MantaUSB(void) 00020 { 00021 Disconnect(); 00022 mantaList.remove(this); 00023 if(mantaList.empty()) 00024 { 00025 hid_exit(); 00026 } 00027 } 00028 00029 bool MantaUSB::MessageQueued(void) 00030 { 00031 return GetQueuedTxMessage() != NULL; 00032 } 00033 00034 /************************************************************************/ 00053 void MantaUSB::WriteFrame(uint8_t *frame, bool forceQueued) 00054 { 00055 int status; 00056 if(NULL == DeviceHandle) 00057 { 00058 throw(MantaNotConnectedException(this)); 00059 } 00060 MantaTxQueueEntry *queuedMessage = GetQueuedTxMessage(); 00061 if(queuedMessage && !forceQueued) 00062 { 00063 /* replace the queued packet payload with the new one */ 00064 for(int i = 0; i < OutPacketLen; ++i) 00065 { 00066 /* the first byte of the report is the report ID (0x00) */ 00067 queuedMessage->OutFrame[i+1] = frame[i]; 00068 } 00069 DebugPrint("%s-%d: (WriteFrame) Queued Transfer overwritten on Manta %d", 00070 __FILE__, __LINE__, GetSerialNumber()); 00071 } 00072 else 00073 { 00074 /* no transfer in progress, queue up a new one */ 00075 MantaTxQueueEntry *newMessage = new MantaTxQueueEntry; 00076 newMessage->OutFrame[0] = 0; 00077 newMessage->TargetManta = this; 00078 /* the first byte of the report is the report ID (0x00) */ 00079 memcpy(newMessage->OutFrame + 1, frame, OutPacketLen); 00080 txQueue.push_back(newMessage); 00081 DebugPrint("%s-%d: (WriteFrame) Transfer Queued on Manta %d", 00082 __FILE__, __LINE__, GetSerialNumber()); 00083 } 00084 } 00085 00086 /************************************************************************/ 00092 bool MantaUSB::IsConnected(void) 00093 { 00094 return DeviceHandle != NULL; 00095 } 00096 00097 /************************************************************************/ 00108 void MantaUSB::Connect(int connectionSerial) 00109 { 00110 #define SERIAL_STRING_SIZE 32 00111 wchar_t serialString[SERIAL_STRING_SIZE]; 00112 00113 if(IsConnected()) 00114 { 00115 return; 00116 } 00117 00118 DebugPrint("%s-%d: Attempting to Connect to Manta %d...", 00119 __FILE__, __LINE__, connectionSerial); 00120 if(connectionSerial) 00121 { 00122 swprintf(serialString, SERIAL_STRING_SIZE, L"%d", connectionSerial); 00123 DeviceHandle = hid_open(VendorID, ProductID, serialString); 00124 } 00125 else 00126 { 00127 DeviceHandle = hid_open(VendorID, ProductID, NULL); 00128 } 00129 if(NULL == DeviceHandle) 00130 throw(MantaNotFoundException()); 00131 hid_get_serial_number_string(DeviceHandle, serialString, SERIAL_STRING_SIZE); 00132 SerialNumber = wcstol(serialString, NULL, 10); 00133 hid_set_nonblocking(DeviceHandle, 1); 00134 } 00135 00136 /************************************************************************/ 00139 void MantaUSB::Disconnect(void) 00140 { 00141 if(! IsConnected()) 00142 { 00143 return; 00144 } 00145 00146 DebugPrint("%s-%d: Manta %d Disconnecting...", __FILE__, __LINE__, GetSerialNumber()); 00147 hid_close(DeviceHandle); 00148 DeviceHandle = NULL; 00149 } 00150 00151 /************************************************************************/ 00164 void MantaUSB::HandleEvents(void) 00165 { 00166 list<MantaUSB *>::iterator i = mantaList.begin(); 00167 /* read from each manta and trigger any events */ 00168 while(mantaList.end() != i) 00169 { 00170 MantaUSB *current = *i; 00171 if(current->IsConnected()) 00172 { 00173 int bytesRead; 00174 int8_t inFrame[InPacketLen]; 00175 00176 bytesRead = hid_read(current->DeviceHandle, 00177 reinterpret_cast<uint8_t *>(inFrame), InPacketLen); 00178 if(bytesRead < 0) 00179 { 00180 current->DebugPrint("%s-%d: Read error on Manta %d", 00181 __FILE__, __LINE__, current->GetSerialNumber()); 00182 throw(MantaCommunicationException(current)); 00183 } 00184 else if(bytesRead) 00185 { 00186 current->FrameReceived(inFrame); 00187 } 00188 } 00189 ++i; 00190 } 00191 00192 /* pop one item off the transmit queue and send down to its target */ 00193 if(! txQueue.empty()) 00194 { 00195 int bytesWritten; 00196 MantaTxQueueEntry *txMessage = txQueue.front(); 00197 txQueue.pop_front(); 00198 bytesWritten = hid_write(txMessage->TargetManta->DeviceHandle, 00199 txMessage->OutFrame, OutPacketLen + 1); 00200 txMessage->TargetManta->DebugPrint("%s-%d: Frame Written to Manta %d", 00201 __FILE__, __LINE__, txMessage->TargetManta->GetSerialNumber()); 00202 for(int i = 0; i < 16; i += 8) 00203 { 00204 uint8_t *frame = txMessage->OutFrame + 1; 00205 txMessage->TargetManta->DebugPrint("\t\t%x %x %x %x %x %x %x %x", 00206 frame[i], frame[i+1], frame[i+2], frame[i+3], frame[i+4], 00207 frame[i+5], frame[i+6], frame[i+7]); 00208 } 00209 delete txMessage; 00210 if(bytesWritten < 0) 00211 { 00212 txMessage->TargetManta->DebugPrint("%s-%d: Write error on Manta %d", 00213 __FILE__, __LINE__, txMessage->TargetManta->GetSerialNumber()); 00214 throw(MantaCommunicationException(txMessage->TargetManta)); 00215 } 00216 } 00217 } 00218 00219 /************************************************************************/ 00224 int MantaUSB::GetSerialNumber(void) 00225 { 00226 /* TODO: get serial number */ 00227 return SerialNumber; 00228 } 00229 00230 MantaUSB::MantaTxQueueEntry *MantaUSB::GetQueuedTxMessage() 00231 { 00232 list<MantaTxQueueEntry *>::iterator i = txQueue.begin(); 00233 /* look for the first queued message matching this manta */ 00234 while(txQueue.end() != i) 00235 { 00236 if((*i)->TargetManta == this) 00237 { 00238 return *i; 00239 } 00240 ++i; 00241 } 00242 return NULL; 00243 } 00244 00245 /* define static class members */ 00246 list<MantaUSB *> MantaUSB::mantaList; 00247 list<MantaUSB::MantaTxQueueEntry *> MantaUSB::txQueue;