//----------------------------------------------------------------------------- // Basic USB communication class (Managed Code) -- // (C) Piero Giubilato 2008, Berkeley Lab -- //----------------------------------------------------------------------------- //_____________________________________________________________________________ // {Trace} // [File name] "cypr_USB.cpp" // [Author] "Piero Giubilato" // [Version] "1.0" // [Modified by] "Piero Giubilato" // [Last revision] "15 Dec 2008" // [Language] "C++ Managed" // [Compiler] "Visual C++ 9" // [Member of] "Cool SEAL" // [Project] "SEAL" // [Description] "This class is a managed C++ construct used to wrap" // "the original Cypress CyUSB.dll (which is managed C++). It provides" // "all the basic communication functionalities, but NOT multi-threading." // "For multi threading an external, non managed layer has to be provided." // [Key documentation] // "Visual C++ Reference Help" // "Cypress CyUSB.NET DLL Programmer's Reference (CyUsb.NET.chm)" // {Trace} //_____________________________________________________________________________ // App inclusion #include "global.h" #include "cypr_USB.h" // Standard libraries #include #include #include // Namespaces in use here using namespace std; using namespace CyUSB; using namespace System; using namespace System::Runtime::InteropServices; //______________________________________________________________________________ cypr_USB::cypr_USB () {} //______________________________________________________________________________ //comm_USB::~comm_USB () {} //______________________________________________________________________________ int cypr_USB::Open(int VendorID, int ProductID) { // Searches for USB devices and enumerates them, then try search for every // device into the list compliant with the provided Vendor and Product ID. // Debug dbg_Print("cypr_USB::Open: initializing device(s)...", DBG_LVL_MAKE); // Enumerates USB devices (Cypress devices only) USBDevice = gcnew USBDeviceList(CyConst::DEVICES_CYUSB); // Reset to 0 the number of compliant devices CMPDevice->Resize(CMPDevice, 0); // Scan through all the Cypress compatible devices for (int n = 0; n < USBDevice->Count; n++) { // Add a device as compliant if ut has the right Vendor and Product ID if (USBDevice[n]->VendorID == VendorID && USBDevice[n]->ProductID == ProductID) { // Increase CMP array size CMPDevice->Resize(CMPDevice, CMPDevice->Length + 1); // Assign the device as a compliant one from the devices list CMPDevice[CMPDevice->Length - 1] = (CyFX2Device^)USBDevice[n]; // Basic setting for the device CMPDevice[CMPDevice->Length - 1]->BulkInEndPt->TimeOut = 1500; } } // Exit returning the number of compliant devices found return USBDevice->Count; } //______________________________________________________________________________ int cypr_USB::Close() { // Close all opened devices... // Really nothing to do here! dbg_Print("cypr_USB::Close: closing device(s)...", DBG_LVL_MAKE); // Exit with no errors return 0; } //______________________________________________________________________________ int cypr_USB::Count() { // Returns the number of compliant devices actually running return CMPDevice->Length; } //______________________________________________________________________________ int cypr_USB::Reset(int devID) { // Resets the device (devID) dbg_Print("cypr_USB::Reset: resetting device...", DBG_LVL_MAKE); // Check device instantiation if (devID < 0 || devID >= CMPDevice->Length) return -1; // Reset all the transactions CMPDevice[devID]->BulkInEndPt->Abort(); CMPDevice[devID]->BulkOutEndPt->Abort(); CMPDevice[devID]->Reset(); // Exit with no error return 0; } //______________________________________________________________________________ int cypr_USB::buffer_Len(int devID) { // Retrieves the actual transfer buffer size (in words) dbg_Print("cypr_USB::buffer_Len: retriving buffer size...", DBG_LVL_MAKE); // Check device instantiation if (devID < 0 || devID >= CMPDevice->Length) return -1; // Returns return CMPDevice[devID]->BulkInEndPt->XferSize / 2; } //______________________________________________________________________________ int cypr_USB::buffer_Len(int devID, int* buffSize) { // Sets the protocol properties for a given device // buffSize: the size of the buffer in words (2 bytes each) dbg_Print("cypr_USB::buffer_Len: setting buffer...", DBG_LVL_MAKE); // Check device instantiation if (devID < 0 || devID >= CMPDevice->Length) return -1; // Check buffer dimension if (*buffSize % 256 != 0) { *buffSize = ((int)(*buffSize / 256) + 1) * 256; } // Set the parameters to the device endpoint CMPDevice[devID]->BulkInEndPt->XferSize = *buffSize * 2; // Exit with no error return 0; } //______________________________________________________________________________ int cypr_USB::timeout_Len(int devID) { // Sets the protocol properties for a given device // timeout: reading timeout in milliseconds dbg_Print("cypr_USB::timeout_Len: setting timeout...", DBG_LVL_MAKE); // Check device instantiation if (devID < 0 || devID >= CMPDevice->Length) return -1; // Exit with no error return CMPDevice[devID]->BulkInEndPt->TimeOut; } //______________________________________________________________________________ int cypr_USB::timeout_Len(int devID, int* timeout) { // Sets the protocol properties for a given device // timeout: reading timeout in milliseconds dbg_Print("cypr_USB::timeout_Len: setting timeout...", DBG_LVL_MAKE); // Check device instantiation if (devID < 0 || devID >= CMPDevice->Length) return -1; // Check for timeout if (*timeout < 0) *timeout = 500; // Set the timeout CMPDevice[devID]->BulkInEndPt->TimeOut = *timeout; // Exit with no error return 0; } //______________________________________________________________________________ int cypr_USB::Write(int devID, unsigned short* buffer, int* len) { // Writes buffer to the selected device. Waits to return until the write // has been completed. Returns -1 on error. // Nothe the bytes order: the provided word are sent with the First byte // being the LSB and the Second byte being the MSB, so to have them already // lined at the exit of the USB FIFO. // // Returns 0 on all ok, -1 on error // len is overwritten with the actual number of words read // Check device instantiation if (devID < 0 || devID >= CMPDevice->Length) return -1; // Allocate a managed array and copy the unmanaged one to it int req = 2 * *len; array^ mngBuffer = gcnew array(req); // Copy the buffer to the managed one for (int n = 0; n < *len; n++) { mngBuffer[n * 2] = *((char*)&buffer[n]); mngBuffer[n * 2 + 1] = *((char*)&buffer[n] + 1); } // Write the managed buffer if (CMPDevice[devID]->BulkOutEndPt->XferData(mngBuffer, req) == 0) return -1; // Adjust the value of len in case of timeout reading if (2 * *len != req) *len = (int)(req / 2); // Exit with no error return 0; } //______________________________________________________________________________ int cypr_USB::Read(int devID, unsigned short* buffer, int* len) { // Reads the requested amount of word from the specified device. // Len MUST be an integer multiple of 256 (as the internal USB FIFO is // organize in 512 bytes (256 words) blocks. // Note how the passed len is referred to a word (unsigned short) count, // while to the usb driver is passed a length expressed in bytes. // 'len' is overwritten with the actual number of words read. // Returns 0 on all ok, -1 on error. // Check device instantiation if (devID < 0 || devID >= CMPDevice->Length) return -1; // Allocate a managed array where to store the raw data int req = 2 * (*len); array^mngBuffer = gcnew array(req); // Read from the USB FIFO buffer if (CMPDevice[devID]->BulkInEndPt->XferData(mngBuffer, req) != true) { //*len = 0; //return -1; //std::cout << "Cypr USB: readed len is: " << req << "\n"; //std::cout << "Cypr USB: error code is: " << CMPDevice[devID]->BulkInEndPt->NtStatus << "\n"; //std::cout << "Cypr USB: error code is: " << CMPDevice[devID]->BulkInEndPt->UsbdStatus << "\n"; } // Reads from the USB FIFO buffer //CMPDevice[devID]->BulkInEndPt->XferData(mngBuffer, req); // Put the raw data (bytes) into the unmanaged buffer (words) for (int n = 0; n < *len; n++) { *((unsigned char*)&buffer[n]) = mngBuffer[n * 2]; *((unsigned char*)&buffer[n] + 1) = mngBuffer[n * 2 + 1]; } // Adjust the value of len in case of timeout reading if (2 * (*len) != req) *len = (int)(req / 2); // Exit with no error return 0; }