aboutsummaryrefslogtreecommitdiffstats
path: root/cphidget.c
diff options
context:
space:
mode:
authorJonathan McCrohan <jmccrohan@gmail.com>2012-05-09 00:47:30 +0100
committerJonathan McCrohan <jmccrohan@gmail.com>2012-05-09 00:47:30 +0100
commit260123716172d33f44bdc0e4e5422554d139215c (patch)
tree840e8e6387b96bd6f9afe3ffebc19c781a112f1b /cphidget.c
parent0b624384cd52be20e61284551d832b499d7b7707 (diff)
downloadlibphidget21-260123716172d33f44bdc0e4e5422554d139215c.tar.gz
Imported Upstream version 2.1.8.20120507upstream/2.1.8.20120507
Diffstat (limited to 'cphidget.c')
-rw-r--r--cphidget.c463
1 files changed, 411 insertions, 52 deletions
diff --git a/cphidget.c b/cphidget.c
index d8d5cb3..a408210 100644
--- a/cphidget.c
+++ b/cphidget.c
@@ -6,6 +6,8 @@
#include "cphidgetlist.h"
#include "utils.h"
+static int CPhidgetGPP_dataInput(CPhidgetHandle phid, unsigned char *buffer, int length);
+
int print_debug_messages = FALSE;
CPhidgetListHandle ActiveDevices = 0;
@@ -120,8 +122,8 @@ int CCONV CPhidget_areEqual(void *arg1, void *arg2)
if(phid1->specificDevice && phid2->specificDevice)
{
// If one is open serial and the other is open label
- if(phid1->specificDevice == PHIDGETOPEN_SERIAL && phid2->specificDevice == PHIDGETOPEN_LABEL ||
- phid1->specificDevice == PHIDGETOPEN_LABEL && phid2->specificDevice == PHIDGETOPEN_SERIAL)
+ if((phid1->specificDevice == PHIDGETOPEN_SERIAL && phid2->specificDevice == PHIDGETOPEN_LABEL) ||
+ (phid1->specificDevice == PHIDGETOPEN_LABEL && phid2->specificDevice == PHIDGETOPEN_SERIAL))
return PFALSE;
// If one is open serial but they have different serials
@@ -279,14 +281,14 @@ int CPhidget_read(CPhidgetHandle phid)
TESTPTR(phid)
- if (CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG)
- || CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHING_FLAG)) {
- result = CUSBReadPacket((CPhidgetHandle)phid,
- phid->lastReadPacket);
- if (result) return result;
- if (phid->fptrData)
- result= phid->fptrData((CPhidgetHandle)phid,
- phid->lastReadPacket, phid->inputReportByteLength);
+ if (CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG) || CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHING_FLAG))
+ {
+ if((result = CUSBReadPacket((CPhidgetHandle)phid, phid->lastReadPacket)) != EPHIDGET_OK)
+ return result;
+ if((phid->lastReadPacket[0] & PHID_USB_GENERAL_PACKET_FLAG) && deviceSupportsGeneralUSBProtocol(phid))
+ result = CPhidgetGPP_dataInput(phid, phid->lastReadPacket, phid->inputReportByteLength);
+ else if (phid->fptrData)
+ result= phid->fptrData(phid, phid->lastReadPacket, phid->inputReportByteLength);
return result;
}
return EPHIDGET_NOTATTACHED;
@@ -503,6 +505,10 @@ netdone:
if(!ActiveDevices && !ActivePhidgetManagers)
{
JoinCentralThread();
+ //Shut down USB
+#if defined(_LINUX) && !defined(_ANDROID)
+ CUSBUninit();
+#endif
}
}
CPhidget_clearStatusFlag(&phid->status, PHIDGET_OPENED_FLAG, &phid->lock);
@@ -572,7 +578,14 @@ CPhidget_getDeviceName(CPhidgetHandle phid, const char **buffer)
&& !CPhidget_statusFlagIsSet(phid->status, PHIDGET_DETACHING_FLAG))
return EPHIDGET_NOTATTACHED;
- *buffer = (char *)phid->deviceDef->pdd_name;
+ if(phid->deviceIDSpec == PHIDID_FIRMWARE_UPGRADE)
+ {
+ if(!phid->firmwareUpgradeName[0])
+ snprintf(phid->firmwareUpgradeName, 30, "%s %s", phid->usbProduct, phid->deviceDef->pdd_name);
+ *buffer = phid->firmwareUpgradeName;
+ }
+ else
+ *buffer = (char *)phid->deviceDef->pdd_name;
return EPHIDGET_OK;
}
@@ -719,7 +732,7 @@ CPhidget_setDeviceLabel(CPhidgetHandle phid, const char *buffer)
else
{
-#if defined(_WINDOWS) && !defined(WINCE)
+#if 0// defined(_WINDOWS) && !defined(WINCE)
//setLabel not supported on Windows only (Windows CE does support it)
return EPHIDGET_UNSUPPORTED;
#else
@@ -816,6 +829,9 @@ CPhidget_setDeviceLabel(CPhidgetHandle phid, const char *buffer)
}
else
{
+#if defined(_WINDOWS) && !defined(WINCE)
+ if(ret != EPHIDGET_UNSUPPORTED)
+#endif
LOG(PHIDGET_LOG_ERROR, "Something unexpected happened trying to set the label. Try again.");
return ret;
}
@@ -1261,6 +1277,7 @@ int attachActiveDevice(CPhidgetHandle activeDevice, CPhidgetHandle attachedDevic
activeDevice->CPhidgetFHandle = malloc(wcslen(attachedDevice->CPhidgetFHandle)*sizeof(WCHAR)+10);
wcsncpy((WCHAR *)activeDevice->CPhidgetFHandle, attachedDevice->CPhidgetFHandle, wcslen(attachedDevice->CPhidgetFHandle)+1);
activeDevice->deviceIDSpec = attachedDevice->deviceIDSpec;
+ activeDevice->deviceUID = attachedDevice->deviceUID;
activeDevice->deviceDef = attachedDevice->deviceDef;
#endif
#endif
@@ -1269,6 +1286,7 @@ int attachActiveDevice(CPhidgetHandle activeDevice, CPhidgetHandle attachedDevic
//Android also uses the file handle to open the device
activeDevice->CPhidgetFHandle = strdup(attachedDevice->CPhidgetFHandle);
activeDevice->deviceIDSpec = attachedDevice->deviceIDSpec;
+ activeDevice->deviceUID = attachedDevice->deviceUID;
activeDevice->deviceDef = attachedDevice->deviceDef;
#endif
@@ -1287,6 +1305,7 @@ int attachActiveDevice(CPhidgetHandle activeDevice, CPhidgetHandle attachedDevic
activeDevice->serialNumber = -1;
}
activeDevice->deviceIDSpec = 0;
+ activeDevice->deviceUID = 0;
return result;
}
@@ -1541,39 +1560,15 @@ int labelHasWrapError(int serialNumber, char *labelBuf)
return PFALSE;
}
-//takes the label string buffer from the USB device and outputs a UTF-8 version
-int decodeLabelString(char *labelBuf, char *out, int serialNumber)
+int UTF16toUTF8(char *in, int inLen, char *out)
{
- //out NEEDS to be zeroed out, or we'll end up with a UTF-8 string with no terminating NULL
- ZEROMEM(out, MAX_LABEL_STORAGE);
-
- //this returns true only if our descriptor is > 16 bytes and has the error, so we truncate
- if (labelHasWrapError(serialNumber, labelBuf))
- {
- int i;
- for(i=16;i<labelBuf[0];i++)
- labelBuf[i] = 0x00;
- labelBuf[0] = 16;
- LOG(PHIDGET_LOG_WARNING, "Detected getLabel error - label is being truncated to first 7 characters. Please setLabel again to correct this.");
- }
-
- //check if the label is stored as UTF-8 directly
- if(labelBuf[0] > 4 && labelBuf[2] == (char)0xFF && labelBuf[3] == (char)0xFF)
- {
- LOG(PHIDGET_LOG_DEBUG, "Found a wrap-around bug style label.");
- memcpy(out, &labelBuf[4], labelBuf[0]-4);
- out[labelBuf[0]-4] = '\0';
- }
- //otherwise it's stored as UTF-16LE
- else
- {
#ifdef USE_INTERNAL_UNICONV
- unsigned char *utf8label = (unsigned char *)out;
- unsigned char *utf8labelEnd = utf8label + MAX_LABEL_STORAGE;
- unichar *utf16label = (unichar *)&labelBuf[2];
- unichar *utf16labelEnd = utf16label + ((labelBuf[0]-2) / 2);
+ unsigned char *utf8string = (unsigned char *)out;
+ unsigned char *utf8stringEnd = utf8string + MAX_LABEL_STORAGE;
+ unichar *utf16string = (unichar *)in;
+ unichar *utf16stringEnd = utf16string + (inLen / 2);
ConversionResult resp;
- resp = NSConvertUTF16toUTF8(&utf16label, utf16labelEnd, &utf8label, utf8labelEnd);
+ resp = NSConvertUTF16toUTF8(&utf16string, utf16stringEnd, &utf8string, utf8stringEnd);
if(resp != ok)
{
@@ -1591,13 +1586,11 @@ int decodeLabelString(char *labelBuf, char *out, int serialNumber)
}
return EPHIDGET_INVALIDARG;
}
-
#else
-
#ifndef _WINDOWS
- char *utf16label = &labelBuf[2];
- char *utf8label = (char *)out;
- size_t inBytes = labelBuf[0]-2; // Up to MAX_LABEL_STORAGE bytes read
+ char *utf16string = in;
+ char *utf8string = (char *)out;
+ size_t inBytes = inLen; // Up to MAX_LABEL_STORAGE bytes read
size_t outBytes = (MAX_LABEL_STORAGE); //UTF-16 characters are two bytes each.
iconv_t conv;
size_t resp;
@@ -1605,7 +1598,7 @@ int decodeLabelString(char *labelBuf, char *out, int serialNumber)
if (conv == (iconv_t)(-1))
return EPHIDGET_UNEXPECTED;
- resp = iconv(conv, &utf16label, &inBytes, &utf8label, &outBytes);
+ resp = iconv(conv, &utf16string, &inBytes, &utf8string, &outBytes);
iconv_close(conv);
@@ -1615,23 +1608,389 @@ int decodeLabelString(char *labelBuf, char *out, int serialNumber)
case EINVAL:
case E2BIG:
default:
- LOG (PHIDGET_LOG_ERROR, "Unexpected error converting label to UTF-8: %s.", strerror (errno));
+ LOG (PHIDGET_LOG_ERROR, "Unexpected error converting string to UTF-8: %s.", strerror (errno));
return EPHIDGET_UNEXPECTED;
}
}
#else
- //labelData in NULL terminated
- int bytesWritten = WideCharToMultiByte(CP_UTF8, 0, (wchar_t *)&labelBuf[2], -1, out, MAX_LABEL_STORAGE+1, NULL, NULL);
+ //stringData in NULL terminated
+ int bytesWritten = WideCharToMultiByte(CP_UTF8, 0, (wchar_t *)in, -1, out, MAX_LABEL_STORAGE+1, NULL, NULL);
//Error
if(!bytesWritten)
{
- LOG(PHIDGET_LOG_ERROR, "Unable to convert label to UTF-8!");
+ LOG(PHIDGET_LOG_ERROR, "Unable to convert string to UTF-8!");
return EPHIDGET_UNEXPECTED;
}
#endif
#endif
+ return EPHIDGET_OK;
+}
+
+//takes the label string buffer from the USB device and outputs a UTF-8 version
+int decodeLabelString(char *labelBuf, char *out, int serialNumber)
+{
+ //out NEEDS to be zeroed out, or we'll end up with a UTF-8 string with no terminating NULL
+ ZEROMEM(out, MAX_LABEL_STORAGE);
+
+ //this returns true only if our descriptor is > 16 bytes and has the error, so we truncate
+ if (labelHasWrapError(serialNumber, labelBuf))
+ {
+ int i;
+ for(i=16;i<labelBuf[0];i++)
+ labelBuf[i] = 0x00;
+ labelBuf[0] = 16;
+ LOG(PHIDGET_LOG_WARNING, "Detected getLabel error - label is being truncated to first 7 characters. Please setLabel again to correct this.");
+ }
+
+ //check if the label is stored as UTF-8 directly
+ if(labelBuf[0] > 4 && labelBuf[2] == (char)0xFF && labelBuf[3] == (char)0xFF)
+ {
+ LOG(PHIDGET_LOG_DEBUG, "Found a wrap-around bug style label.");
+ memcpy(out, &labelBuf[4], labelBuf[0]-4);
+ out[labelBuf[0]-4] = '\0';
+ }
+ //otherwise it's stored as UTF-16LE
+ else
+ {
+ return UTF16toUTF8(&labelBuf[2], labelBuf[0]-2, out);
}
return EPHIDGET_OK;
}
+
+CPhidget_DeviceUID CPhidget_getUID(CPhidget_DeviceID id, int version)
+{
+ const CPhidgetUniqueDeviceDef *uidList = Phid_Unique_Device_Def;
+ int i = 0;
+
+ while (uidList->pdd_uid)
+ {
+ if(uidList->pdd_id == id && version >= uidList->pdd_vlow && version < uidList->pdd_vhigh)\
+ return uidList->pdd_uid;
+ i++;
+ uidList++;
+ }
+
+ //Should never get here!
+ LOG(PHIDGET_LOG_DEBUG, "We have a Phidgets that doesn't match and Device UID!");
+ return PHIDUID_NOTHING;
+}
+
+
+
+/**
+ * General Packet Protocol
+ *
+ * These are devices on the new M3. They all support this protocol.
+ * MSB is set is buf[0] for incoming and outgoing packets.
+ */
+
+int deviceSupportsGeneralUSBProtocol(CPhidgetHandle phid)
+{
+ switch(phid->deviceUID)
+ {
+ case PHIDUID_SPATIAL_ACCEL_3AXIS_1041:
+ case PHIDUID_SPATIAL_ACCEL_3AXIS_1043:
+ case PHIDUID_SPATIAL_ACCEL_GYRO_COMPASS_1042:
+ case PHIDUID_SPATIAL_ACCEL_GYRO_COMPASS_1044:
+ return PTRUE;
+
+ case PHIDUID_FIRMWARE_UPGRADE:
+ return PTRUE;
+
+ case PHIDUID_GENERIC:
+ return PTRUE;
+
+ default:
+ return PFALSE;
+ }
+}
+
+static int CPhidgetGPP_dataInput(CPhidgetHandle phid, unsigned char *buffer, int length)
+{
+ int result = EPHIDGET_OK;
+
+ //if response bits are set (0x00 is ignore), then store response
+ if(buffer[0] & 0x3f)
+ phid->GPPResponse = buffer[0];
+
+ return result;
+}
+
+int GPP_getResponse(CPhidgetHandle phid, int packetType, int timeout)
+{
+ while((phid->GPPResponse & 0x3f) != packetType && timeout > 0)
+ {
+ SLEEP(20);
+ timeout -= 20;
+ }
+
+ //Didn't get the response!
+ if((phid->GPPResponse & 0x3f) != packetType)
+ {
+ return EPHIDGET_TIMEOUT;
+ }
+
+ if(phid->GPPResponse & PHID_USB_GENERAL_PACKET_FAIL)
+ return EPHIDGET_UNEXPECTED;
+
+ return EPHIDGET_OK;
+}
+
+int CCONV CPhidgetGPP_upgradeFirmware(CPhidgetHandle phid, unsigned char *data, int length)
+{
+ int result, i, j, index, indexEnd;
+ unsigned char *buffer;
+ TESTPTR(phid)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ if(!deviceSupportsGeneralUSBProtocol(phid))
+ return EPHIDGET_UNSUPPORTED;
+
+ buffer = (unsigned char *) malloc(phid->outputReportByteLength);
+ ZEROMEM(buffer, phid->outputReportByteLength);
+
+ CThread_mutex_lock(&phid->writelock);
+
+ phid->GPPResponse = 0;
+
+ index = ((length & 0xf000) >> 12) + 1;
+ indexEnd = length & 0xfff;
+ j = 0;
+ while (index)
+ {
+ int secLength = length - ((index - 1) * 0x1000);
+ if(secLength > 0x1000) secLength = 0x1000;
+
+ buffer[0] = PHID_USB_GENERAL_PACKET_FLAG | PHID_USB_GENERAL_PACKET_FIRMWARE_UPGRADE_WRITE_SECTOR;
+ buffer[1] = index;
+ buffer[2] = secLength;
+ buffer[3] = secLength >> 8;
+
+ for(i=4;i<phid->outputReportByteLength && j<indexEnd;i++,j++)
+ buffer[i] = data[j];
+
+ if((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ goto done;
+
+ while(j<indexEnd && result == EPHIDGET_OK)
+ {
+ buffer[0] = PHID_USB_GENERAL_PACKET_FLAG | PHID_USB_GENERAL_PACKET_CONTINUATION;
+ for(i=1;i<phid->outputReportByteLength && j<indexEnd;i++,j++)
+ buffer[i] = data[j];
+
+ if((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ goto done;
+ }
+ index--;
+ indexEnd+=0x1000;
+ }
+
+done:
+
+ result = GPP_getResponse(phid, PHID_USB_GENERAL_PACKET_FIRMWARE_UPGRADE_WRITE_SECTOR, 200);
+
+ CThread_mutex_unlock(&phid->writelock);
+
+ free(buffer);
+
+ return result;
+}
+
+int CCONV CPhidgetGPP_eraseFirmware(CPhidgetHandle phid)
+{
+ int result;
+ unsigned char *buffer;
+ TESTPTR(phid)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ if(!deviceSupportsGeneralUSBProtocol(phid))
+ return EPHIDGET_UNSUPPORTED;
+
+ buffer = (unsigned char *) malloc(phid->outputReportByteLength);
+ ZEROMEM(buffer, phid->outputReportByteLength);
+
+ buffer[0] = PHID_USB_GENERAL_PACKET_FLAG | PHID_USB_GENERAL_PACKET_FIRMWARE_UPGRADE_ERASE;
+
+ CThread_mutex_lock(&phid->writelock);
+
+ phid->GPPResponse = 0;
+ if((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) == EPHIDGET_OK)
+ result = GPP_getResponse(phid, PHID_USB_GENERAL_PACKET_FIRMWARE_UPGRADE_ERASE, 200);
+
+ CThread_mutex_unlock(&phid->writelock);
+ free(buffer);
+
+ return result;
+}
+
+int CCONV CPhidgetGPP_reboot_firmwareUpgrade(CPhidgetHandle phid)
+{
+ int result;
+ unsigned char *buffer;
+ TESTPTR(phid)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ if(!deviceSupportsGeneralUSBProtocol(phid))
+ return EPHIDGET_UNSUPPORTED;
+
+ buffer = (unsigned char *) malloc(phid->outputReportByteLength);
+ ZEROMEM(buffer, phid->outputReportByteLength);
+
+ buffer[0] = PHID_USB_GENERAL_PACKET_FLAG | PHID_USB_GENERAL_PACKET_REBOOT_FIRMWARE_UPGRADE;
+
+ result = CUSBSendPacket((CPhidgetHandle)phid, buffer);
+
+ free(buffer);
+
+ return result;
+}
+
+int CCONV CPhidgetGPP_reboot_ISP(CPhidgetHandle phid)
+{
+ int result;
+ unsigned char *buffer;
+ TESTPTR(phid)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ if(!deviceSupportsGeneralUSBProtocol(phid))
+ return EPHIDGET_UNSUPPORTED;
+
+ buffer = (unsigned char *) malloc(phid->outputReportByteLength);
+ ZEROMEM(buffer, phid->outputReportByteLength);
+
+ buffer[0] = PHID_USB_GENERAL_PACKET_FLAG | PHID_USB_GENERAL_PACKET_REBOOT_ISP;
+
+ result = CUSBSendPacket((CPhidgetHandle)phid, buffer);
+
+ free(buffer);
+
+ return result;
+}
+
+int CCONV CPhidgetGPP_writeFlash(CPhidgetHandle phid)
+{
+ int result;
+ unsigned char *buffer;
+ TESTPTR(phid)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ if(!deviceSupportsGeneralUSBProtocol(phid))
+ return EPHIDGET_UNSUPPORTED;
+
+ buffer = (unsigned char *) malloc(phid->outputReportByteLength);
+ ZEROMEM(buffer, phid->outputReportByteLength);
+
+ buffer[0] = PHID_USB_GENERAL_PACKET_FLAG | PHID_USB_GENERAL_PACKET_WRITE_FLASH;
+
+ result = CUSBSendPacket((CPhidgetHandle)phid, buffer);
+
+ free(buffer);
+
+ return result;
+}
+
+int CCONV CPhidgetGPP_zeroConfig(CPhidgetHandle phid)
+{
+ int result;
+ unsigned char *buffer;
+ TESTPTR(phid)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ if(!deviceSupportsGeneralUSBProtocol(phid))
+ return EPHIDGET_UNSUPPORTED;
+
+ buffer = (unsigned char *) malloc(phid->outputReportByteLength);
+ ZEROMEM(buffer, phid->outputReportByteLength);
+
+ buffer[0] = PHID_USB_GENERAL_PACKET_FLAG | PHID_USB_GENERAL_PACKET_ZERO_CONFIG;
+
+ result = CUSBSendPacket((CPhidgetHandle)phid, buffer);
+
+ free(buffer);
+
+ return result;
+}
+
+int CCONV CPhidgetGPP_setLabel(CPhidgetHandle phid, const char *label)
+{
+ unsigned char buffer[26] = {0};
+ int result;
+ TESTPTR(phid)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ if(!deviceSupportsGeneralUSBProtocol(phid))
+ return EPHIDGET_UNSUPPORTED;
+
+ //Label Table Header is: 0x0010001A
+ buffer[3] = 0x00; //header high byte
+ buffer[2] = 0x10;
+ buffer[1] = 0x00;
+ buffer[0] = 0x1a; //header low byte
+
+ memcpy(buffer+4, label, label[0]);
+
+ //Label Table index is: 0
+ if((result=CPhidgetGPP_setDeviceWideConfigTable(phid, buffer, 26, 0))==EPHIDGET_OK)
+ return CPhidgetGPP_writeFlash(phid);
+ return result;
+}
+
+static int CPhidgetGPP_setConfigTable(CPhidgetHandle phid, unsigned char *data, int length, int index, int packetType)
+{
+ int result, i, j;
+ unsigned char *buffer;
+ TESTPTR(phid)
+ if (!CPhidget_statusFlagIsSet(phid->status, PHIDGET_ATTACHED_FLAG))
+ return EPHIDGET_NOTATTACHED;
+
+ if(!deviceSupportsGeneralUSBProtocol(phid))
+ return EPHIDGET_UNSUPPORTED;
+
+ buffer = (unsigned char *) malloc(phid->outputReportByteLength);
+ ZEROMEM(buffer, phid->outputReportByteLength);
+
+ buffer[0] = PHID_USB_GENERAL_PACKET_FLAG | packetType;
+ buffer[1] = index;
+ for(i=2,j=0;i<phid->outputReportByteLength && j<length;i++,j++)
+ buffer[i] = data[j];
+
+ CThread_mutex_lock(&phid->writelock);
+
+ if((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ goto done;
+
+ while(j<length && result == EPHIDGET_OK)
+ {
+ buffer[0] = PHID_USB_GENERAL_PACKET_FLAG | PHID_USB_GENERAL_PACKET_CONTINUATION;
+ for(i=1;i<phid->outputReportByteLength && j<length;i++,j++)
+ buffer[i] = data[j];
+ if((result = CUSBSendPacket((CPhidgetHandle)phid, buffer)) != EPHIDGET_OK)
+ goto done;
+ }
+
+done:
+ CThread_mutex_unlock(&phid->writelock);
+
+ free(buffer);
+
+ return result;
+}
+
+int CCONV CPhidgetGPP_setDeviceSpecificConfigTable(CPhidgetHandle phid, unsigned char *data, int length, int index)
+{
+ return CPhidgetGPP_setConfigTable(phid, data, length, index, PHID_USB_GENERAL_PACKET_SET_DS_TABLE);
+}
+
+int CCONV CPhidgetGPP_setDeviceWideConfigTable(CPhidgetHandle phid, unsigned char *data, int length, int index)
+{
+ return CPhidgetGPP_setConfigTable(phid, data, length, index, PHID_USB_GENERAL_PACKET_SET_DW_TABLE);
+} \ No newline at end of file