add lib
This commit is contained in:
1833
Lib/projector/LC4500API/API.cpp
Normal file
1833
Lib/projector/LC4500API/API.cpp
Normal file
File diff suppressed because it is too large
Load Diff
259
Lib/projector/LC4500API/API.h
Normal file
259
Lib/projector/LC4500API/API.h
Normal file
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* API.h
|
||||
*
|
||||
* This module provides C callable APIs for each of the command supported by LightCrafter4500 platform and detailed in the programmer's guide.
|
||||
*
|
||||
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* ALL RIGHTS RESERVED
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef API_H
|
||||
#define API_H
|
||||
|
||||
/* Bit masks. */
|
||||
#define BIT0 0x01
|
||||
#define BIT1 0x02
|
||||
#define BIT2 0x04
|
||||
#define BIT3 0x08
|
||||
#define BIT4 0x10
|
||||
#define BIT5 0x20
|
||||
#define BIT6 0x40
|
||||
#define BIT7 0x80
|
||||
#define BIT8 0x0100
|
||||
#define BIT9 0x0200
|
||||
#define BIT10 0x0400
|
||||
#define BIT11 0x0800
|
||||
#define BIT12 0x1000
|
||||
#define BIT13 0x2000
|
||||
#define BIT14 0x4000
|
||||
#define BIT15 0x8000
|
||||
#define BIT16 0x00010000
|
||||
#define BIT17 0x00020000
|
||||
#define BIT18 0x00040000
|
||||
#define BIT19 0x00080000
|
||||
#define BIT20 0x00100000
|
||||
#define BIT21 0x00200000
|
||||
#define BIT22 0x00400000
|
||||
#define BIT23 0x00800000
|
||||
#define BIT24 0x01000000
|
||||
#define BIT25 0x02000000
|
||||
#define BIT26 0x04000000
|
||||
#define BIT27 0x08000000
|
||||
#define BIT28 0x10000000
|
||||
#define BIT29 0x20000000
|
||||
#define BIT30 0x40000000
|
||||
#define BIT31 0x80000000
|
||||
|
||||
#define STAT_BIT_FLASH_BUSY BIT3
|
||||
#define HID_MESSAGE_MAX_SIZE 512
|
||||
|
||||
typedef struct _hidmessageStruct
|
||||
{
|
||||
struct _hidhead
|
||||
{
|
||||
struct _packetcontrolStruct
|
||||
{
|
||||
unsigned char dest :3; /* 0 - ProjCtrl; 1 - RFC; 7 - Debugmsg */
|
||||
unsigned char reserved :2;
|
||||
unsigned char nack :1; /* Command Handler Error */
|
||||
unsigned char reply :1; /* Host wants a reply from device */
|
||||
unsigned char rw :1; /* Write = 0; Read = 1 */
|
||||
}flags;
|
||||
unsigned char seq;
|
||||
unsigned short length;
|
||||
}head;
|
||||
union
|
||||
{
|
||||
unsigned short cmd;
|
||||
unsigned char data[HID_MESSAGE_MAX_SIZE];
|
||||
}text;
|
||||
}hidMessageStruct;
|
||||
|
||||
typedef struct _readCmdData
|
||||
{
|
||||
unsigned char CMD2;
|
||||
unsigned char CMD3;
|
||||
unsigned short len;
|
||||
}CmdFormat;
|
||||
|
||||
typedef struct _rectangle
|
||||
{
|
||||
unsigned short firstPixel;
|
||||
unsigned short firstLine;
|
||||
unsigned short pixelsPerLine;
|
||||
unsigned short linesPerFrame;
|
||||
}rectangle;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SOURCE_SEL,
|
||||
PIXEL_FORMAT,
|
||||
CLK_SEL,
|
||||
CHANNEL_SWAP,
|
||||
FPD_MODE,
|
||||
CURTAIN_COLOR,
|
||||
POWER_CONTROL,
|
||||
FLIP_LONG,
|
||||
FLIP_SHORT,
|
||||
TPG_SEL,
|
||||
PWM_INVERT,
|
||||
LED_ENABLE,
|
||||
GET_VERSION,
|
||||
SW_RESET,
|
||||
DMD_PARK,
|
||||
BUFFER_FREEZE,
|
||||
STATUS_HW,
|
||||
STATUS_SYS,
|
||||
STATUS_MAIN,
|
||||
CSC_DATA,
|
||||
GAMMA_CTL,
|
||||
BC_CTL,
|
||||
PWM_ENABLE,
|
||||
PWM_SETUP,
|
||||
PWM_CAPTURE_CONFIG,
|
||||
GPIO_CONFIG,
|
||||
LED_CURRENT,
|
||||
DISP_CONFIG,
|
||||
TEMP_CONFIG,
|
||||
TEMP_READ,
|
||||
MEM_CONTROL,
|
||||
I2C_CONTROL,
|
||||
LUT_VALID,
|
||||
DISP_MODE,
|
||||
TRIG_OUT1_CTL,
|
||||
TRIG_OUT2_CTL,
|
||||
RED_STROBE_DLY,
|
||||
GRN_STROBE_DLY,
|
||||
BLU_STROBE_DLY,
|
||||
PAT_DISP_MODE,
|
||||
PAT_TRIG_MODE,
|
||||
PAT_START_STOP,
|
||||
BUFFER_SWAP,
|
||||
BUFFER_WR_DISABLE,
|
||||
CURRENT_RD_BUFFER,
|
||||
PAT_EXPO_PRD,
|
||||
INVERT_DATA,
|
||||
PAT_CONFIG,
|
||||
MBOX_ADDRESS,
|
||||
MBOX_CONTROL,
|
||||
MBOX_DATA,
|
||||
TRIG_IN1_DELAY,
|
||||
TRIG_IN2_CONTROL,
|
||||
SPLASH_LOAD,
|
||||
SPLASH_LOAD_TIMING,
|
||||
GPCLK_CONFIG,
|
||||
PULSE_GPIO_23,
|
||||
ENABLE_LCR_DEBUG,
|
||||
TPG_COLOR,
|
||||
PWM_CAPTURE_READ,
|
||||
PROG_MODE,
|
||||
BL_STATUS,
|
||||
BL_SPL_MODE,
|
||||
BL_GET_MANID,
|
||||
BL_GET_DEVID,
|
||||
BL_GET_CHKSUM,
|
||||
BL_SET_SECTADDR,
|
||||
BL_SECT_ERASE,
|
||||
BL_SET_DNLDSIZE,
|
||||
BL_DNLD_DATA,
|
||||
BL_FLASH_TYPE,
|
||||
BL_CALC_CHKSUM,
|
||||
BL_PROG_MODE,
|
||||
}LCR_CMD;
|
||||
|
||||
int LCR_SetInputSource(unsigned int source, unsigned int portWidth);
|
||||
int LCR_GetInputSource(unsigned int *pSource, unsigned int *portWidth);
|
||||
int LCR_SetPixelFormat(unsigned int format);
|
||||
int LCR_GetPixelFormat(unsigned int *pFormat);
|
||||
int LCR_SetPortClock(unsigned int clock);
|
||||
int LCR_GetPortClock(unsigned int *pClock);
|
||||
int LCR_SetDataChannelSwap(unsigned int port, unsigned int swap);
|
||||
int LCR_GetDataChannelSwap(unsigned int *pPort, unsigned int *pSwap);
|
||||
int LCR_SetFPD_Mode_Field(unsigned int PixelMappingMode, bool SwapPolarity, unsigned int FieldSignalSelect);
|
||||
int LCR_GetFPD_Mode_Field(unsigned int *pPixelMappingMode, bool *pSwapPolarity, unsigned int *pFieldSignalSelect);
|
||||
int LCR_SetPowerMode(bool);
|
||||
int LCR_SetLongAxisImageFlip(bool);
|
||||
bool LCR_GetLongAxisImageFlip();
|
||||
int LCR_SetShortAxisImageFlip(bool);
|
||||
bool LCR_GetShortAxisImageFlip();
|
||||
int LCR_SetTPGSelect(unsigned int pattern);
|
||||
int LCR_GetTPGSelect(unsigned int *pPattern);
|
||||
int LCR_SetPWMInvert(bool invert);
|
||||
int LCR_GetPWMInvert(bool *inverted);
|
||||
int LCR_SetLedEnables(bool SeqCtrl, bool Red, bool Green, bool Blue);
|
||||
int LCR_GetLedEnables(bool *pSeqCtrl, bool *pRed, bool *pGreen, bool *pBlue);
|
||||
int LCR_GetVersion(unsigned int *pApp_ver, unsigned int *pAPI_ver, unsigned int *pSWConfig_ver, unsigned int *pSeqConfig_ver);
|
||||
int LCR_SoftwareReset(void);
|
||||
int LCR_GetStatus(unsigned char *pHWStatus, unsigned char *pSysStatus, unsigned char *pMainStatus);
|
||||
int LCR_SetPWMEnable(unsigned int channel, bool Enable);
|
||||
int LCR_GetPWMEnable(unsigned int channel, bool *pEnable);
|
||||
int LCR_SetPWMConfig(unsigned int channel, unsigned int pulsePeriod, unsigned int dutyCycle);
|
||||
int LCR_GetPWMConfig(unsigned int channel, unsigned int *pPulsePeriod, unsigned int *pDutyCycle);
|
||||
int LCR_SetPWMCaptureConfig(unsigned int channel, bool enable, unsigned int sampleRate);
|
||||
int LCR_GetPWMCaptureConfig(unsigned int channel, bool *pEnabled, unsigned int *pSampleRate);
|
||||
int LCR_SetGPIOConfig(unsigned int pinNum, bool enAltFunc, bool altFunc1, bool dirOutput, bool outTypeOpenDrain, bool pinState);
|
||||
int LCR_GetGPIOConfig(unsigned int pinNum, bool *pEnAltFunc, bool *pAltFunc1, bool *pDirOutput, bool *pOutTypeOpenDrain, bool *pState);
|
||||
int LCR_GetLedCurrents(unsigned char *pRed, unsigned char *pGreen, unsigned char *pBlue);
|
||||
int LCR_SetLedCurrents(unsigned char RedCurrent, unsigned char GreenCurrent, unsigned char BlueCurrent);
|
||||
int LCR_SetDisplay(rectangle croppedArea, rectangle displayArea);
|
||||
int LCR_GetDisplay(rectangle *pCroppedArea, rectangle *pDisplayArea);
|
||||
int LCR_MemRead(unsigned int addr, unsigned int *readWord);
|
||||
int LCR_MemWrite(unsigned int addr, unsigned int data);
|
||||
int LCR_ValidatePatLutData(unsigned int *pStatus);
|
||||
int LCR_SetPatternDisplayMode(bool external);
|
||||
int LCR_GetPatternDisplayMode(bool *external);
|
||||
int LCR_SetTrigOutConfig(unsigned int trigOutNum, bool invert, unsigned int rising, unsigned int falling);
|
||||
int LCR_GetTrigOutConfig(unsigned int trigOutNum, bool *pInvert,unsigned int *pRising, unsigned int *pFalling);
|
||||
int LCR_SetRedLEDStrobeDelay(unsigned char rising, unsigned char falling);
|
||||
int LCR_SetGreenLEDStrobeDelay(unsigned char rising, unsigned char falling);
|
||||
int LCR_SetBlueLEDStrobeDelay(unsigned char rising, unsigned char falling);
|
||||
int LCR_GetRedLEDStrobeDelay(unsigned char *, unsigned char *);
|
||||
int LCR_GetGreenLEDStrobeDelay(unsigned char *, unsigned char *);
|
||||
int LCR_GetBlueLEDStrobeDelay(unsigned char *, unsigned char *);
|
||||
int LCR_SetProgrammingMode(bool EnterProgMode);
|
||||
int LCR_ExitProgrammingMode(void);
|
||||
int LCR_GetProgrammingMode(bool *ProgMode);
|
||||
int LCR_GetFlashManID(unsigned short *manID);
|
||||
int LCR_GetFlashDevID(unsigned long long *devID);
|
||||
int LCR_GetBLStatus(unsigned char *BL_Status);
|
||||
int LCR_BLSpecialMode(unsigned int Mode);
|
||||
int LCR_SetFlashAddr(unsigned int Addr);
|
||||
int LCR_FlashSectorErase(void);
|
||||
int LCR_SetDownloadSize(unsigned int dataLen);
|
||||
int LCR_DownloadData(unsigned char *pByteArray, unsigned int dataLen);
|
||||
void LCR_WaitForFlashReady(void);
|
||||
int LCR_SetFlashType(unsigned char Type);
|
||||
int LCR_CalculateFlashChecksum(void);
|
||||
int LCR_GetFlashChecksum(unsigned int*checksum);
|
||||
int LCR_SetMode(bool SLmode);
|
||||
int LCR_GetMode(bool *pMode);
|
||||
int LCR_LoadSplash(unsigned int index);
|
||||
int LCR_GetSplashIndex(unsigned int *pIndex);
|
||||
int LCR_SetTPGColor(unsigned short redFG, unsigned short greenFG, unsigned short blueFG, unsigned short redBG, unsigned short greenBG, unsigned short blueBG);
|
||||
int LCR_GetTPGColor(unsigned short *pRedFG, unsigned short *pGreenFG, unsigned short *pBlueFG, unsigned short *pRedBG, unsigned short *pGreenBG, unsigned short *pBlueBG);
|
||||
int LCR_ClearPatLut(void);
|
||||
int LCR_AddToPatLut(int TrigType, int PatNum,int BitDepth,int LEDSelect,bool InvertPat, bool InsertBlack,bool BufSwap, bool trigOutPrev);
|
||||
int LCR_GetPatLutItem(int index, int *pTrigType, int *pPatNum,int *pBitDepth,int *pLEDSelect,bool *pInvertPat, bool *pInsertBlack,bool *pBufSwap, bool *pTrigOutPrev);
|
||||
int LCR_SendPatLut(void);
|
||||
int LCR_SendSplashLut(unsigned char *lutEntries, unsigned int numEntries);
|
||||
int LCR_GetPatLut(int numEntries);
|
||||
int LCR_GetSplashLut(unsigned char *pLut, int numEntries);
|
||||
int LCR_SetPatternTriggerMode(bool);
|
||||
int LCR_GetPatternTriggerMode(bool *);
|
||||
int LCR_PatternDisplay(int Action);
|
||||
int LCR_SetPatternConfig(unsigned int numLutEntries, bool repeat, unsigned int numPatsForTrigOut2, unsigned int numSplash);
|
||||
int LCR_GetPatternConfig(unsigned int *pNumLutEntries, bool *pRepeat, unsigned int *pNumPatsForTrigOut2, unsigned int *pNumSplash);
|
||||
int LCR_SetExpsosure_FramePeriod(unsigned int exposurePeriod, unsigned int framePeriod);
|
||||
int LCR_GetExposure_FramePeriod(unsigned int *pExposure, unsigned int *pFramePeriod);
|
||||
int LCR_SetTrigIn1Delay(unsigned int Delay);
|
||||
int LCR_GetTrigIn1Delay(unsigned int *pDelay);
|
||||
int LCR_SetInvertData(bool invert);
|
||||
int LCR_PWMCaptureRead(unsigned int channel, unsigned int *pLowPeriod, unsigned int *pHighPeriod);
|
||||
int LCR_SetGeneralPurposeClockOutFreq(unsigned int clkId, bool enable, unsigned int clkDivider);
|
||||
int LCR_GetGeneralPurposeClockOutFreq(unsigned int clkId, bool *pEnabled, unsigned int *pClkDivider);
|
||||
int LCR_MeasureSplashLoadTiming(unsigned int startIndex, unsigned int numSplash);
|
||||
int LCR_ReadSplashLoadTiming(unsigned int *pTimingData);
|
||||
|
||||
|
||||
#endif // API_H
|
||||
108
Lib/projector/LC4500API/Common.h
Normal file
108
Lib/projector/LC4500API/Common.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Common.h
|
||||
*
|
||||
* This module provides the common defines used by all the modules.
|
||||
*
|
||||
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* ALL RIGHTS RESERVED
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COMMON_H_
|
||||
#define COMMON_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IMAGE_PIX_FORMAT_RGB32,
|
||||
IMAGE_PIX_FORMAT_GREY8,
|
||||
IMAGE_PIX_FORMAT_GREY10,
|
||||
IMAGE_PIX_FORMAT_UYVY16,
|
||||
IMAGE_PIX_FORMAT_RGB16,
|
||||
IMAGE_PIX_FORMAT_SBGGR,
|
||||
IMAGE_PIX_FORMAT_RGB24,
|
||||
} ImagePixFormat_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char *Buffer;
|
||||
unsigned Width;
|
||||
unsigned Height;
|
||||
unsigned LineWidth;
|
||||
ImagePixFormat_t PixFormat;
|
||||
}Image_t;
|
||||
|
||||
|
||||
typedef int BOOL;
|
||||
typedef unsigned uint32;
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
|
||||
typedef uint16 PatternCount_t;
|
||||
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define ALIGN_BYTES_PREV(x, b) ((x) & ~(uint32)((b) - 1))
|
||||
#define ALIGN_BYTES_NEXT(x, b) (((x) + ((b)-1)) & ~(uint32)((b) - 1))
|
||||
|
||||
#define GET_BYTE0(x) ((x) & 0xFF)
|
||||
#define GET_BYTE1(x) (((x) >> 8) & 0xFF)
|
||||
#define GET_BYTE2(x) (((x) >> 16) & 0xFF)
|
||||
#define GET_BYTE3(x) (((x) >> 24) & 0xFF)
|
||||
|
||||
#define PARSE_WORD16_LE(Arr) MAKE_WORD16((Arr)[1], (Arr)[0])
|
||||
#define PARSE_WORD16_BE(Arr) MAKE_WORD16((Arr)[0], (Arr)[1])
|
||||
#define PARSE_WORD24_LE(Arr) MAKE_WORD32(0, (Arr)[2], (Arr)[1], (Arr)[0])
|
||||
#define PARSE_WORD24_BE(Arr) MAKE_WORD32(0, (Arr)[0], (Arr)[1], (Arr)[2])
|
||||
#define PARSE_WORD32_LE(Arr) MAKE_WORD32((Arr)[3], (Arr)[2], (Arr)[1], (Arr)[0])
|
||||
#define PARSE_WORD32_BE(Arr) MAKE_WORD32((Arr)[0], (Arr)[1], (Arr)[2], (Arr)[3])
|
||||
|
||||
#define MAKE_WORD16(b1, b0) (((b1) << 8) | (b0))
|
||||
#define MAKE_WORD32(b3, b2, b1, b0) (((uint32)(b3)<<24)|((uint32)(b2)<<16)|((uint32)(b1)<<8)|(b0))
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
|
||||
#define DIV_ROUND(x, y) (((x)+(y)/2)/(y))
|
||||
#define DIV_CEIL(x, y) (((x)+(y)-1)/(y))
|
||||
#define POW_OF_2(x) (1ul << (x))
|
||||
|
||||
#define IS_POW_OF_2(x) (((x) & ((x)-1)) == 0)
|
||||
|
||||
// Generate bit mask of n bits starting from s bit
|
||||
#define GEN_BIT_MASK(s, n) (((1ul << (n)) - 1) << (s))
|
||||
|
||||
// Merge bits b into a according to mask
|
||||
#define MERGE_BITS(a, b, mask) ((a) ^ (((a) ^ (b)) & (mask)))
|
||||
|
||||
#define STRUCT_CLEAR(s) (memset(&(s), 0, sizeof(s)))
|
||||
#define BIT_REVERSE(x) CMN_BitRevLUT[(uint8)(x)]
|
||||
|
||||
#define STR(x) STR_(x)
|
||||
#define STR_(x) #x
|
||||
|
||||
extern const uint8 CMN_BitRevLUT[];
|
||||
void PrintArray(char const *Prefix, uint8 const *Array, unsigned Size, BOOL Hex);
|
||||
uint32 GetImagePixel(Image_t *Image, int x, int y);
|
||||
uint32 Next2Power(uint32 Value);
|
||||
unsigned Hex2BinArray(char *HexStr, unsigned Size, uint8 *BinArray);
|
||||
int TrimString(char const *Input, char *Output);
|
||||
int WriteTextToFile(char const *File, int Num, char const *Text);
|
||||
int ReadTextFromFile(char const *File, int Num, char *Text, int Len);
|
||||
BOOL FileExist(char const *File, int Num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* COMMON_H_ */
|
||||
936
Lib/projector/LC4500API/hid.Win.c
Normal file
936
Lib/projector/LC4500API/hid.Win.c
Normal file
@@ -0,0 +1,936 @@
|
||||
/*******************************************************
|
||||
HIDAPI - Multi-Platform library for
|
||||
communication with HID devices.
|
||||
Alan Ott
|
||||
Signal 11 Software
|
||||
8/22/2009
|
||||
Copyright 2009, All Rights Reserved.
|
||||
|
||||
At the discretion of the user of this library,
|
||||
this software may be licensed under the terms of the
|
||||
GNU General Public License v3, a BSD-Style license, or the
|
||||
original HIDAPI license as outlined in the LICENSE.txt,
|
||||
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
|
||||
files located at the root of the source distribution.
|
||||
These files may also be found in the public source
|
||||
code repository located at:
|
||||
http://github.com/signal11/hidapi .
|
||||
********************************************************/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#ifndef _NTDEF_
|
||||
typedef LONG NTSTATUS;
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <ntdef.h>
|
||||
#include <winbase.h>
|
||||
#endif
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
#include <ntdef.h>
|
||||
#define _wcsdup wcsdup
|
||||
#endif
|
||||
|
||||
/*#define HIDAPI_USE_DDK*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <setupapi.h>
|
||||
#include <winioctl.h>
|
||||
#ifdef HIDAPI_USE_DDK
|
||||
#include <hidsdi.h>
|
||||
#endif
|
||||
|
||||
/* Copied from inc/ddk/hidclass.h, part of the Windows DDK. */
|
||||
#define HID_OUT_CTL_CODE(id) \
|
||||
CTL_CODE(FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
#define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#include "hidapi.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/* Thanks Microsoft, but I know how to use strncpy(). */
|
||||
#pragma warning(disable:4996)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef HIDAPI_USE_DDK
|
||||
/* Since we're not building with the DDK, and the HID header
|
||||
files aren't part of the SDK, we have to define all this
|
||||
stuff here. In lookup_functions(), the function pointers
|
||||
defined below are set. */
|
||||
typedef struct _HIDD_ATTRIBUTES{
|
||||
ULONG Size;
|
||||
USHORT VendorID;
|
||||
USHORT ProductID;
|
||||
USHORT VersionNumber;
|
||||
} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
|
||||
|
||||
typedef USHORT USAGE;
|
||||
typedef struct _HIDP_CAPS {
|
||||
USAGE Usage;
|
||||
USAGE UsagePage;
|
||||
USHORT InputReportByteLength;
|
||||
USHORT OutputReportByteLength;
|
||||
USHORT FeatureReportByteLength;
|
||||
USHORT Reserved[17];
|
||||
USHORT fields_not_used_by_hidapi[10];
|
||||
} HIDP_CAPS, *PHIDP_CAPS;
|
||||
typedef void* PHIDP_PREPARSED_DATA;
|
||||
#define HIDP_STATUS_SUCCESS 0x110000
|
||||
|
||||
typedef BOOLEAN (__stdcall *HidD_GetAttributes_)(HANDLE device, PHIDD_ATTRIBUTES attrib);
|
||||
typedef BOOLEAN (__stdcall *HidD_GetSerialNumberString_)(HANDLE device, PVOID buffer, ULONG buffer_len);
|
||||
typedef BOOLEAN (__stdcall *HidD_GetManufacturerString_)(HANDLE handle, PVOID buffer, ULONG buffer_len);
|
||||
typedef BOOLEAN (__stdcall *HidD_GetProductString_)(HANDLE handle, PVOID buffer, ULONG buffer_len);
|
||||
typedef BOOLEAN (__stdcall *HidD_SetFeature_)(HANDLE handle, PVOID data, ULONG length);
|
||||
typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length);
|
||||
typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len);
|
||||
typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data);
|
||||
typedef BOOLEAN (__stdcall *HidD_FreePreparsedData_)(PHIDP_PREPARSED_DATA preparsed_data);
|
||||
typedef NTSTATUS (__stdcall *HidP_GetCaps_)(PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps);
|
||||
typedef BOOLEAN (__stdcall *HidD_SetNumInputBuffers_)(HANDLE handle, ULONG number_buffers);
|
||||
|
||||
static HidD_GetAttributes_ HidD_GetAttributes;
|
||||
static HidD_GetSerialNumberString_ HidD_GetSerialNumberString;
|
||||
static HidD_GetManufacturerString_ HidD_GetManufacturerString;
|
||||
static HidD_GetProductString_ HidD_GetProductString;
|
||||
static HidD_SetFeature_ HidD_SetFeature;
|
||||
static HidD_GetFeature_ HidD_GetFeature;
|
||||
static HidD_GetIndexedString_ HidD_GetIndexedString;
|
||||
static HidD_GetPreparsedData_ HidD_GetPreparsedData;
|
||||
static HidD_FreePreparsedData_ HidD_FreePreparsedData;
|
||||
static HidP_GetCaps_ HidP_GetCaps;
|
||||
static HidD_SetNumInputBuffers_ HidD_SetNumInputBuffers;
|
||||
|
||||
static HMODULE lib_handle = NULL;
|
||||
static BOOLEAN initialized = FALSE;
|
||||
#endif /* HIDAPI_USE_DDK */
|
||||
|
||||
struct hid_device_ {
|
||||
HANDLE device_handle;
|
||||
BOOL blocking;
|
||||
USHORT output_report_length;
|
||||
size_t input_report_length;
|
||||
void *last_error_str;
|
||||
DWORD last_error_num;
|
||||
BOOL read_pending;
|
||||
char *read_buf;
|
||||
OVERLAPPED ol;
|
||||
};
|
||||
|
||||
static hid_device *new_hid_device()
|
||||
{
|
||||
hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
|
||||
dev->device_handle = INVALID_HANDLE_VALUE;
|
||||
dev->blocking = TRUE;
|
||||
dev->output_report_length = 0;
|
||||
dev->input_report_length = 0;
|
||||
dev->last_error_str = NULL;
|
||||
dev->last_error_num = 0;
|
||||
dev->read_pending = FALSE;
|
||||
dev->read_buf = NULL;
|
||||
memset(&dev->ol, 0, sizeof(dev->ol));
|
||||
dev->ol.hEvent = CreateEvent(NULL, FALSE, FALSE /*inital state f=nonsignaled*/, NULL);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
static void free_hid_device(hid_device *dev)
|
||||
{
|
||||
CloseHandle(dev->ol.hEvent);
|
||||
CloseHandle(dev->device_handle);
|
||||
LocalFree(dev->last_error_str);
|
||||
free(dev->read_buf);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void register_error(hid_device *device, const char *op)
|
||||
{
|
||||
WCHAR *ptr, *msg;
|
||||
|
||||
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPVOID)&msg, 0/*sz*/,
|
||||
NULL);
|
||||
|
||||
/* Get rid of the CR and LF that FormatMessage() sticks at the
|
||||
end of the message. Thanks Microsoft! */
|
||||
ptr = msg;
|
||||
while (*ptr) {
|
||||
if (*ptr == '\r') {
|
||||
*ptr = 0x0000;
|
||||
break;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
|
||||
/* Store the message off in the Device entry so that
|
||||
the hid_error() function can pick it up. */
|
||||
LocalFree(device->last_error_str);
|
||||
device->last_error_str = msg;
|
||||
}
|
||||
|
||||
#ifndef HIDAPI_USE_DDK
|
||||
static int lookup_functions()
|
||||
{
|
||||
lib_handle = LoadLibraryA("hid.dll");
|
||||
if (lib_handle) {
|
||||
#define RESOLVE(x) x = (x##_)GetProcAddress(lib_handle, #x); if (!x) return -1;
|
||||
RESOLVE(HidD_GetAttributes);
|
||||
RESOLVE(HidD_GetSerialNumberString);
|
||||
RESOLVE(HidD_GetManufacturerString);
|
||||
RESOLVE(HidD_GetProductString);
|
||||
RESOLVE(HidD_SetFeature);
|
||||
RESOLVE(HidD_GetFeature);
|
||||
RESOLVE(HidD_GetIndexedString);
|
||||
RESOLVE(HidD_GetPreparsedData);
|
||||
RESOLVE(HidD_FreePreparsedData);
|
||||
RESOLVE(HidP_GetCaps);
|
||||
RESOLVE(HidD_SetNumInputBuffers);
|
||||
#undef RESOLVE
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static HANDLE open_device(const char *path, BOOL enumerate)
|
||||
{
|
||||
HANDLE handle;
|
||||
DWORD desired_access = (enumerate)? 0: (GENERIC_WRITE | GENERIC_READ);
|
||||
DWORD share_mode = (enumerate)?
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE:
|
||||
FILE_SHARE_READ;
|
||||
|
||||
handle = CreateFileA(path,
|
||||
desired_access,
|
||||
share_mode,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OVERLAPPED,/*FILE_ATTRIBUTE_NORMAL,*/
|
||||
0);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT hid_init(void)
|
||||
{
|
||||
#ifndef HIDAPI_USE_DDK
|
||||
if (!initialized) {
|
||||
if (lookup_functions() < 0) {
|
||||
hid_exit();
|
||||
return -1;
|
||||
}
|
||||
initialized = TRUE;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT hid_exit(void)
|
||||
{
|
||||
#ifndef HIDAPI_USE_DDK
|
||||
if (lib_handle)
|
||||
FreeLibrary(lib_handle);
|
||||
lib_handle = NULL;
|
||||
initialized = FALSE;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id)
|
||||
{
|
||||
BOOL res;
|
||||
struct hid_device_info *root = NULL; /* return object */
|
||||
struct hid_device_info *cur_dev = NULL;
|
||||
|
||||
/* Windows objects for interacting with the driver. */
|
||||
GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} };
|
||||
SP_DEVINFO_DATA devinfo_data;
|
||||
SP_DEVICE_INTERFACE_DATA device_interface_data;
|
||||
SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL;
|
||||
HDEVINFO device_info_set = INVALID_HANDLE_VALUE;
|
||||
int device_index = 0;
|
||||
int i;
|
||||
|
||||
if (hid_init() < 0)
|
||||
return NULL;
|
||||
|
||||
/* Initialize the Windows objects. */
|
||||
memset(&devinfo_data, 0x0, sizeof(devinfo_data));
|
||||
devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
|
||||
/* Get information for all the devices belonging to the HID class. */
|
||||
device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
|
||||
/* Iterate over each device in the HID class, looking for the right one. */
|
||||
|
||||
for (;;) {
|
||||
HANDLE write_handle = INVALID_HANDLE_VALUE;
|
||||
DWORD required_size = 0;
|
||||
HIDD_ATTRIBUTES attrib;
|
||||
|
||||
res = SetupDiEnumDeviceInterfaces(device_info_set,
|
||||
NULL,
|
||||
&InterfaceClassGuid,
|
||||
device_index,
|
||||
&device_interface_data);
|
||||
|
||||
if (!res) {
|
||||
/* A return of FALSE from this function means that
|
||||
there are no more devices. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Call with 0-sized detail size, and let the function
|
||||
tell us how long the detail struct needs to be. The
|
||||
size is put in &required_size. */
|
||||
res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
|
||||
&device_interface_data,
|
||||
NULL,
|
||||
0,
|
||||
&required_size,
|
||||
NULL);
|
||||
|
||||
/* Allocate a long enough structure for device_interface_detail_data. */
|
||||
device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size);
|
||||
device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
|
||||
|
||||
/* Get the detailed data for this device. The detail data gives us
|
||||
the device path for this device, which is then passed into
|
||||
CreateFile() to get a handle to the device. */
|
||||
res = SetupDiGetDeviceInterfaceDetailA(device_info_set,
|
||||
&device_interface_data,
|
||||
device_interface_detail_data,
|
||||
required_size,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (!res) {
|
||||
/* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail");
|
||||
Continue to the next device. */
|
||||
goto cont;
|
||||
}
|
||||
|
||||
/* Make sure this device is of Setup Class "HIDClass" and has a
|
||||
driver bound to it. */
|
||||
for (i = 0; ; i++) {
|
||||
char driver_name[256];
|
||||
|
||||
/* Populate devinfo_data. This function will return failure
|
||||
when there are no more interfaces left. */
|
||||
res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data);
|
||||
if (!res)
|
||||
goto cont;
|
||||
|
||||
res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data,
|
||||
SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL);
|
||||
if (!res)
|
||||
goto cont;
|
||||
|
||||
if (strcmp(driver_name, "HIDClass") == 0) {
|
||||
/* See if there's a driver bound. */
|
||||
res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data,
|
||||
SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL);
|
||||
if (res)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath);
|
||||
|
||||
/* Open a handle to the device */
|
||||
write_handle = open_device(device_interface_detail_data->DevicePath, TRUE);
|
||||
|
||||
/* Check validity of write_handle. */
|
||||
if (write_handle == INVALID_HANDLE_VALUE) {
|
||||
/* Unable to open the device. */
|
||||
//register_error(dev, "CreateFile");
|
||||
goto cont_close;
|
||||
}
|
||||
|
||||
|
||||
/* Get the Vendor ID and Product ID for this device. */
|
||||
attrib.Size = sizeof(HIDD_ATTRIBUTES);
|
||||
HidD_GetAttributes(write_handle, &attrib);
|
||||
//wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID);
|
||||
|
||||
/* Check the VID/PID to see if we should add this
|
||||
device to the enumeration list. */
|
||||
if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) &&
|
||||
(product_id == 0x0 || attrib.ProductID == product_id)) {
|
||||
|
||||
#define WSTR_LEN 512
|
||||
const char *str;
|
||||
struct hid_device_info *tmp;
|
||||
PHIDP_PREPARSED_DATA pp_data = NULL;
|
||||
HIDP_CAPS caps;
|
||||
BOOLEAN res;
|
||||
NTSTATUS nt_res;
|
||||
wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */
|
||||
size_t len;
|
||||
|
||||
/* VID/PID match. Create the record. */
|
||||
tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info));
|
||||
if (cur_dev) {
|
||||
cur_dev->next = tmp;
|
||||
}
|
||||
else {
|
||||
root = tmp;
|
||||
}
|
||||
cur_dev = tmp;
|
||||
|
||||
/* Get the Usage Page and Usage for this device. */
|
||||
res = HidD_GetPreparsedData(write_handle, &pp_data);
|
||||
if (res) {
|
||||
nt_res = HidP_GetCaps(pp_data, &caps);
|
||||
if (nt_res == HIDP_STATUS_SUCCESS) {
|
||||
cur_dev->usage_page = caps.UsagePage;
|
||||
cur_dev->usage = caps.Usage;
|
||||
}
|
||||
|
||||
HidD_FreePreparsedData(pp_data);
|
||||
}
|
||||
|
||||
/* Fill out the record */
|
||||
cur_dev->next = NULL;
|
||||
str = device_interface_detail_data->DevicePath;
|
||||
if (str) {
|
||||
len = strlen(str);
|
||||
cur_dev->path = (char*) calloc(len+1, sizeof(char));
|
||||
strncpy(cur_dev->path, str, len+1);
|
||||
cur_dev->path[len] = '\0';
|
||||
}
|
||||
else
|
||||
cur_dev->path = NULL;
|
||||
|
||||
/* Serial Number */
|
||||
res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr));
|
||||
wstr[WSTR_LEN-1] = 0x0000;
|
||||
if (res) {
|
||||
cur_dev->serial_number = _wcsdup(wstr);
|
||||
}
|
||||
|
||||
/* Manufacturer String */
|
||||
res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr));
|
||||
wstr[WSTR_LEN-1] = 0x0000;
|
||||
if (res) {
|
||||
cur_dev->manufacturer_string = _wcsdup(wstr);
|
||||
}
|
||||
|
||||
/* Product String */
|
||||
res = HidD_GetProductString(write_handle, wstr, sizeof(wstr));
|
||||
wstr[WSTR_LEN-1] = 0x0000;
|
||||
if (res) {
|
||||
cur_dev->product_string = _wcsdup(wstr);
|
||||
}
|
||||
|
||||
/* VID/PID */
|
||||
cur_dev->vendor_id = attrib.VendorID;
|
||||
cur_dev->product_id = attrib.ProductID;
|
||||
|
||||
/* Release Number */
|
||||
cur_dev->release_number = attrib.VersionNumber;
|
||||
|
||||
/* Interface Number. It can sometimes be parsed out of the path
|
||||
on Windows if a device has multiple interfaces. See
|
||||
http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or
|
||||
search for "Hardware IDs for HID Devices" at MSDN. If it's not
|
||||
in the path, it's set to -1. */
|
||||
cur_dev->interface_number = -1;
|
||||
if (cur_dev->path) {
|
||||
char *interface_component = strstr(cur_dev->path, "&mi_");
|
||||
if (interface_component) {
|
||||
char *hex_str = interface_component + 4;
|
||||
char *endptr = NULL;
|
||||
cur_dev->interface_number = strtol(hex_str, &endptr, 16);
|
||||
if (endptr == hex_str) {
|
||||
/* The parsing failed. Set interface_number to -1. */
|
||||
cur_dev->interface_number = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cont_close:
|
||||
CloseHandle(write_handle);
|
||||
cont:
|
||||
/* We no longer need the detail data. It can be freed */
|
||||
free(device_interface_detail_data);
|
||||
|
||||
device_index++;
|
||||
|
||||
}
|
||||
|
||||
/* Close the device information handle. */
|
||||
SetupDiDestroyDeviceInfoList(device_info_set);
|
||||
|
||||
return root;
|
||||
|
||||
}
|
||||
|
||||
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs)
|
||||
{
|
||||
/* TODO: Merge this with the Linux version. This function is platform-independent. */
|
||||
struct hid_device_info *d = devs;
|
||||
while (d) {
|
||||
struct hid_device_info *next = d->next;
|
||||
free(d->path);
|
||||
free(d->serial_number);
|
||||
free(d->manufacturer_string);
|
||||
free(d->product_string);
|
||||
free(d);
|
||||
d = next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number)
|
||||
{
|
||||
/* TODO: Merge this functions with the Linux version. This function should be platform independent. */
|
||||
struct hid_device_info *devs, *cur_dev;
|
||||
const char *path_to_open = NULL;
|
||||
hid_device *handle = NULL;
|
||||
|
||||
devs = hid_enumerate(vendor_id, product_id);
|
||||
cur_dev = devs;
|
||||
while (cur_dev) {
|
||||
if (cur_dev->vendor_id == vendor_id &&
|
||||
cur_dev->product_id == product_id) {
|
||||
if (serial_number) {
|
||||
if (wcscmp(serial_number, cur_dev->serial_number) == 0) {
|
||||
path_to_open = cur_dev->path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
path_to_open = cur_dev->path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cur_dev = cur_dev->next;
|
||||
}
|
||||
|
||||
if (path_to_open) {
|
||||
/* Open the device */
|
||||
handle = hid_open_path(path_to_open);
|
||||
}
|
||||
|
||||
hid_free_enumeration(devs);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path)
|
||||
{
|
||||
hid_device *dev;
|
||||
HIDP_CAPS caps;
|
||||
PHIDP_PREPARSED_DATA pp_data = NULL;
|
||||
BOOLEAN res;
|
||||
NTSTATUS nt_res;
|
||||
|
||||
if (hid_init() < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev = new_hid_device();
|
||||
|
||||
/* Open a handle to the device */
|
||||
dev->device_handle = open_device(path, FALSE);
|
||||
|
||||
/* Check validity of write_handle. */
|
||||
if (dev->device_handle == INVALID_HANDLE_VALUE) {
|
||||
/* Unable to open the device. */
|
||||
register_error(dev, "CreateFile");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Set the Input Report buffer size to 64 reports. */
|
||||
res = HidD_SetNumInputBuffers(dev->device_handle, 64);
|
||||
if (!res) {
|
||||
register_error(dev, "HidD_SetNumInputBuffers");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Get the Input Report length for the device. */
|
||||
res = HidD_GetPreparsedData(dev->device_handle, &pp_data);
|
||||
if (!res) {
|
||||
register_error(dev, "HidD_GetPreparsedData");
|
||||
goto err;
|
||||
}
|
||||
nt_res = HidP_GetCaps(pp_data, &caps);
|
||||
if (nt_res != HIDP_STATUS_SUCCESS) {
|
||||
register_error(dev, "HidP_GetCaps");
|
||||
goto err_pp_data;
|
||||
}
|
||||
dev->output_report_length = caps.OutputReportByteLength;
|
||||
dev->input_report_length = caps.InputReportByteLength;
|
||||
HidD_FreePreparsedData(pp_data);
|
||||
|
||||
dev->read_buf = (char*) malloc(dev->input_report_length);
|
||||
|
||||
return dev;
|
||||
|
||||
err_pp_data:
|
||||
HidD_FreePreparsedData(pp_data);
|
||||
err:
|
||||
free_hid_device(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length)
|
||||
{
|
||||
DWORD bytes_written;
|
||||
BOOL res;
|
||||
|
||||
OVERLAPPED ol;
|
||||
unsigned char *buf;
|
||||
memset(&ol, 0, sizeof(ol));
|
||||
|
||||
/* Make sure the right number of bytes are passed to WriteFile. Windows
|
||||
expects the number of bytes which are in the _longest_ report (plus
|
||||
one for the report number) bytes even if the data is a report
|
||||
which is shorter than that. Windows gives us this value in
|
||||
caps.OutputReportByteLength. If a user passes in fewer bytes than this,
|
||||
create a temporary buffer which is the proper size. */
|
||||
if (length >= dev->output_report_length) {
|
||||
/* The user passed the right number of bytes. Use the buffer as-is. */
|
||||
buf = (unsigned char *) data;
|
||||
} else {
|
||||
/* Create a temporary buffer and copy the user's data
|
||||
into it, padding the rest with zeros. */
|
||||
buf = (unsigned char *) malloc(dev->output_report_length);
|
||||
memcpy(buf, data, length);
|
||||
memset(buf + length, 0, dev->output_report_length - length);
|
||||
length = dev->output_report_length;
|
||||
}
|
||||
|
||||
res = WriteFile(dev->device_handle, buf, length, NULL, &ol);
|
||||
|
||||
if (!res) {
|
||||
if (GetLastError() != ERROR_IO_PENDING) {
|
||||
/* WriteFile() failed. Return error. */
|
||||
register_error(dev, "WriteFile");
|
||||
bytes_written = -1;
|
||||
goto end_of_function;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait here until the write is done. This makes
|
||||
hid_write() synchronous. */
|
||||
res = GetOverlappedResult(dev->device_handle, &ol, &bytes_written, TRUE/*wait*/);
|
||||
if (!res) {
|
||||
/* The Write operation failed. */
|
||||
register_error(dev, "WriteFile");
|
||||
bytes_written = -1;
|
||||
goto end_of_function;
|
||||
}
|
||||
|
||||
end_of_function:
|
||||
if (buf != data)
|
||||
free(buf);
|
||||
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
|
||||
{
|
||||
DWORD bytes_read = 0;
|
||||
size_t copy_len = 0;
|
||||
BOOL res;
|
||||
|
||||
/* Copy the handle for convenience. */
|
||||
HANDLE ev = dev->ol.hEvent;
|
||||
|
||||
if (!dev->read_pending) {
|
||||
/* Start an Overlapped I/O read. */
|
||||
dev->read_pending = TRUE;
|
||||
memset(dev->read_buf, 0, dev->input_report_length);
|
||||
ResetEvent(ev);
|
||||
res = ReadFile(dev->device_handle, dev->read_buf, dev->input_report_length, &bytes_read, &dev->ol);
|
||||
|
||||
if (!res) {
|
||||
if (GetLastError() != ERROR_IO_PENDING) {
|
||||
/* ReadFile() has failed.
|
||||
Clean up and return error. */
|
||||
CancelIo(dev->device_handle);
|
||||
dev->read_pending = FALSE;
|
||||
goto end_of_function;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (milliseconds >= 0) {
|
||||
/* See if there is any data yet. */
|
||||
res = WaitForSingleObject(ev, milliseconds);
|
||||
if (res != WAIT_OBJECT_0) {
|
||||
/* There was no data this time. Return zero bytes available,
|
||||
but leave the Overlapped I/O running. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Either WaitForSingleObject() told us that ReadFile has completed, or
|
||||
we are in non-blocking mode. Get the number of bytes read. The actual
|
||||
data has been copied to the data[] array which was passed to ReadFile(). */
|
||||
res = GetOverlappedResult(dev->device_handle, &dev->ol, &bytes_read, TRUE/*wait*/);
|
||||
|
||||
/* Set pending back to false, even if GetOverlappedResult() returned error. */
|
||||
dev->read_pending = FALSE;
|
||||
|
||||
if (res && bytes_read > 0) {
|
||||
if (dev->read_buf[0] == 0x0) {
|
||||
/* If report numbers aren't being used, but Windows sticks a report
|
||||
number (0x0) on the beginning of the report anyway. To make this
|
||||
work like the other platforms, and to make it work more like the
|
||||
HID spec, we'll skip over this byte. */
|
||||
bytes_read--;
|
||||
copy_len = length > bytes_read ? bytes_read : length;
|
||||
memcpy(data, dev->read_buf+1, copy_len);
|
||||
}
|
||||
else {
|
||||
/* Copy the whole buffer, report number and all. */
|
||||
copy_len = length > bytes_read ? bytes_read : length;
|
||||
memcpy(data, dev->read_buf, copy_len);
|
||||
}
|
||||
}
|
||||
|
||||
end_of_function:
|
||||
if (!res) {
|
||||
register_error(dev, "GetOverlappedResult");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return copy_len;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length)
|
||||
{
|
||||
return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0);
|
||||
}
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock)
|
||||
{
|
||||
dev->blocking = !nonblock;
|
||||
return 0; /* Success */
|
||||
}
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
|
||||
{
|
||||
BOOL res = HidD_SetFeature(dev->device_handle, (PVOID)data, length);
|
||||
if (!res) {
|
||||
register_error(dev, "HidD_SetFeature");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
|
||||
{
|
||||
BOOL res;
|
||||
#if 0
|
||||
res = HidD_GetFeature(dev->device_handle, data, length);
|
||||
if (!res) {
|
||||
register_error(dev, "HidD_GetFeature");
|
||||
return -1;
|
||||
}
|
||||
return 0; /* HidD_GetFeature() doesn't give us an actual length, unfortunately */
|
||||
#else
|
||||
DWORD bytes_returned;
|
||||
|
||||
OVERLAPPED ol;
|
||||
memset(&ol, 0, sizeof(ol));
|
||||
|
||||
res = DeviceIoControl(dev->device_handle,
|
||||
IOCTL_HID_GET_FEATURE,
|
||||
data, length,
|
||||
data, length,
|
||||
&bytes_returned, &ol);
|
||||
|
||||
if (!res) {
|
||||
if (GetLastError() != ERROR_IO_PENDING) {
|
||||
/* DeviceIoControl() failed. Return error. */
|
||||
register_error(dev, "Send Feature Report DeviceIoControl");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait here until the write is done. This makes
|
||||
hid_get_feature_report() synchronous. */
|
||||
res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/);
|
||||
if (!res) {
|
||||
/* The operation failed. */
|
||||
register_error(dev, "Send Feature Report GetOverLappedResult");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* bytes_returned does not include the first byte which contains the
|
||||
report ID. The data buffer actually contains one more byte than
|
||||
bytes_returned. */
|
||||
bytes_returned++;
|
||||
|
||||
return bytes_returned;
|
||||
#endif
|
||||
}
|
||||
|
||||
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev)
|
||||
{
|
||||
if (!dev)
|
||||
return;
|
||||
CancelIo(dev->device_handle);
|
||||
free_hid_device(dev);
|
||||
}
|
||||
|
||||
int HID_API_EXPORT_CALL HID_API_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
|
||||
{
|
||||
BOOL res;
|
||||
|
||||
res = HidD_GetManufacturerString(dev->device_handle, string, sizeof(wchar_t) * maxlen);
|
||||
if (!res) {
|
||||
register_error(dev, "HidD_GetManufacturerString");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT_CALL HID_API_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
|
||||
{
|
||||
BOOL res;
|
||||
|
||||
res = HidD_GetProductString(dev->device_handle, string, sizeof(wchar_t) * maxlen);
|
||||
if (!res) {
|
||||
register_error(dev, "HidD_GetProductString");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT_CALL HID_API_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
|
||||
{
|
||||
BOOL res;
|
||||
|
||||
res = HidD_GetSerialNumberString(dev->device_handle, string, sizeof(wchar_t) * maxlen);
|
||||
if (!res) {
|
||||
register_error(dev, "HidD_GetSerialNumberString");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HID_API_EXPORT_CALL HID_API_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
|
||||
{
|
||||
BOOL res;
|
||||
|
||||
res = HidD_GetIndexedString(dev->device_handle, string_index, string, sizeof(wchar_t) * maxlen);
|
||||
if (!res) {
|
||||
register_error(dev, "HidD_GetIndexedString");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
|
||||
{
|
||||
return (wchar_t*)dev->last_error_str;
|
||||
}
|
||||
|
||||
|
||||
/*#define PICPGM*/
|
||||
/*#define S11*/
|
||||
#define P32
|
||||
#ifdef S11
|
||||
unsigned short VendorID = 0xa0a0;
|
||||
unsigned short ProductID = 0x0001;
|
||||
#endif
|
||||
|
||||
#ifdef P32
|
||||
unsigned short VendorID = 0x04d8;
|
||||
unsigned short ProductID = 0x3f;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PICPGM
|
||||
unsigned short VendorID = 0x04d8;
|
||||
unsigned short ProductID = 0x0033;
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
int __cdecl main(int argc, char* argv[])
|
||||
{
|
||||
int res;
|
||||
unsigned char buf[65];
|
||||
|
||||
UNREFERENCED_PARAMETER(argc);
|
||||
UNREFERENCED_PARAMETER(argv);
|
||||
|
||||
/* Set up the command buffer. */
|
||||
memset(buf,0x00,sizeof(buf));
|
||||
buf[0] = 0;
|
||||
buf[1] = 0x81;
|
||||
|
||||
|
||||
/* Open the device. */
|
||||
int handle = open(VendorID, ProductID, L"12345");
|
||||
if (handle < 0)
|
||||
printf("unable to open device\n");
|
||||
|
||||
|
||||
/* Toggle LED (cmd 0x80) */
|
||||
buf[1] = 0x80;
|
||||
res = write(handle, buf, 65);
|
||||
if (res < 0)
|
||||
printf("Unable to write()\n");
|
||||
|
||||
/* Request state (cmd 0x81) */
|
||||
buf[1] = 0x81;
|
||||
write(handle, buf, 65);
|
||||
if (res < 0)
|
||||
printf("Unable to write() (2)\n");
|
||||
|
||||
/* Read requested state */
|
||||
read(handle, buf, 65);
|
||||
if (res < 0)
|
||||
printf("Unable to read()\n");
|
||||
|
||||
/* Print out the returned buffer. */
|
||||
for (int i = 0; i < 4; i++)
|
||||
printf("buf[%d]: %d\n", i, buf[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
385
Lib/projector/LC4500API/hidapi.h
Normal file
385
Lib/projector/LC4500API/hidapi.h
Normal file
@@ -0,0 +1,385 @@
|
||||
/*******************************************************
|
||||
HIDAPI - Multi-Platform library for
|
||||
communication with HID devices.
|
||||
|
||||
Alan Ott
|
||||
Signal 11 Software
|
||||
|
||||
8/22/2009
|
||||
|
||||
Copyright 2009, All Rights Reserved.
|
||||
|
||||
At the discretion of the user of this library,
|
||||
this software may be licensed under the terms of the
|
||||
GNU Public License v3, a BSD-Style license, or the
|
||||
original HIDAPI license as outlined in the LICENSE.txt,
|
||||
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
|
||||
files located at the root of the source distribution.
|
||||
These files may also be found in the public source
|
||||
code repository located at:
|
||||
http://github.com/signal11/hidapi .
|
||||
********************************************************/
|
||||
|
||||
/** @file
|
||||
* @defgroup API hidapi API
|
||||
*/
|
||||
|
||||
#ifndef HIDAPI_H__
|
||||
#define HIDAPI_H__
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define HID_API_EXPORT __declspec(dllexport)
|
||||
#define HID_API_CALL
|
||||
#else
|
||||
#define HID_API_EXPORT /**< API export macro */
|
||||
#define HID_API_CALL /**< API call macro */
|
||||
#endif
|
||||
|
||||
#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
struct hid_device_;
|
||||
typedef struct hid_device_ hid_device; /**< opaque hidapi structure */
|
||||
|
||||
/** hidapi info structure */
|
||||
struct hid_device_info {
|
||||
/** Platform-specific device path */
|
||||
char *path;
|
||||
/** Device Vendor ID */
|
||||
unsigned short vendor_id;
|
||||
/** Device Product ID */
|
||||
unsigned short product_id;
|
||||
/** Serial Number */
|
||||
wchar_t *serial_number;
|
||||
/** Device Release Number in binary-coded decimal,
|
||||
also known as Device Version Number */
|
||||
unsigned short release_number;
|
||||
/** Manufacturer String */
|
||||
wchar_t *manufacturer_string;
|
||||
/** Product string */
|
||||
wchar_t *product_string;
|
||||
/** Usage Page for this Device/Interface
|
||||
(Windows/Mac only). */
|
||||
unsigned short usage_page;
|
||||
/** Usage for this Device/Interface
|
||||
(Windows/Mac only).*/
|
||||
unsigned short usage;
|
||||
/** The USB interface which this logical device
|
||||
represents. Valid on both Linux implementations
|
||||
in all cases, and valid on the Windows implementation
|
||||
only if the device contains more than one interface. */
|
||||
int interface_number;
|
||||
|
||||
/** Pointer to the next device */
|
||||
struct hid_device_info *next;
|
||||
};
|
||||
|
||||
|
||||
/** @brief Initialize the HIDAPI library.
|
||||
|
||||
This function initializes the HIDAPI library. Calling it is not
|
||||
strictly necessary, as it will be called automatically by
|
||||
hid_enumerate() and any of the hid_open_*() functions if it is
|
||||
needed. This function should be called at the beginning of
|
||||
execution however, if there is a chance of HIDAPI handles
|
||||
being opened by different threads simultaneously.
|
||||
|
||||
@ingroup API
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_init(void);
|
||||
|
||||
/** @brief Finalize the HIDAPI library.
|
||||
|
||||
This function frees all of the static data associated with
|
||||
HIDAPI. It should be called at the end of execution to avoid
|
||||
memory leaks.
|
||||
|
||||
@ingroup API
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_exit(void);
|
||||
|
||||
/** @brief Enumerate the HID Devices.
|
||||
|
||||
This function returns a linked list of all the HID devices
|
||||
attached to the system which match vendor_id and product_id.
|
||||
If @p vendor_id is set to 0 then any vendor matches.
|
||||
If @p product_id is set to 0 then any product matches.
|
||||
If @p vendor_id and @p product_id are both set to 0, then
|
||||
all HID devices will be returned.
|
||||
|
||||
@ingroup API
|
||||
@param vendor_id The Vendor ID (VID) of the types of device
|
||||
to open.
|
||||
@param product_id The Product ID (PID) of the types of
|
||||
device to open.
|
||||
|
||||
@returns
|
||||
This function returns a pointer to a linked list of type
|
||||
struct #hid_device, containing information about the HID devices
|
||||
attached to the system, or NULL in the case of failure. Free
|
||||
this linked list by calling hid_free_enumeration().
|
||||
*/
|
||||
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id);
|
||||
|
||||
/** @brief Free an enumeration Linked List
|
||||
|
||||
This function frees a linked list created by hid_enumerate().
|
||||
|
||||
@ingroup API
|
||||
@param devs Pointer to a list of struct_device returned from
|
||||
hid_enumerate().
|
||||
*/
|
||||
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs);
|
||||
|
||||
/** @brief Open a HID device using a Vendor ID (VID), Product ID
|
||||
(PID) and optionally a serial number.
|
||||
|
||||
If @p serial_number is NULL, the first device with the
|
||||
specified VID and PID is opened.
|
||||
|
||||
@ingroup API
|
||||
@param vendor_id The Vendor ID (VID) of the device to open.
|
||||
@param product_id The Product ID (PID) of the device to open.
|
||||
@param serial_number The Serial Number of the device to open
|
||||
(Optionally NULL).
|
||||
|
||||
@returns
|
||||
This function returns a pointer to a #hid_device object on
|
||||
success or NULL on failure.
|
||||
*/
|
||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number);
|
||||
|
||||
/** @brief Open a HID device by its path name.
|
||||
|
||||
The path name be determined by calling hid_enumerate(), or a
|
||||
platform-specific path name can be used (eg: /dev/hidraw0 on
|
||||
Linux).
|
||||
|
||||
@ingroup API
|
||||
@param path The path name of the device to open
|
||||
|
||||
@returns
|
||||
This function returns a pointer to a #hid_device object on
|
||||
success or NULL on failure.
|
||||
*/
|
||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path);
|
||||
|
||||
/** @brief Write an Output report to a HID device.
|
||||
|
||||
The first byte of @p data[] must contain the Report ID. For
|
||||
devices which only support a single report, this must be set
|
||||
to 0x0. The remaining bytes contain the report data. Since
|
||||
the Report ID is mandatory, calls to hid_write() will always
|
||||
contain one more byte than the report contains. For example,
|
||||
if a hid report is 16 bytes long, 17 bytes must be passed to
|
||||
hid_write(), the Report ID (or 0x0, for devices with a
|
||||
single report), followed by the report data (16 bytes). In
|
||||
this example, the length passed in would be 17.
|
||||
|
||||
hid_write() will send the data on the first OUT endpoint, if
|
||||
one exists. If it does not, it will send the data through
|
||||
the Control Endpoint (Endpoint 0).
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param data The data to send, including the report number as
|
||||
the first byte.
|
||||
@param length The length in bytes of the data to send.
|
||||
|
||||
@returns
|
||||
This function returns the actual number of bytes written and
|
||||
-1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Read an Input report from a HID device with timeout.
|
||||
|
||||
Input reports are returned
|
||||
to the host through the INTERRUPT IN endpoint. The first byte will
|
||||
contain the Report number if the device uses numbered reports.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param data A buffer to put the read data into.
|
||||
@param length The number of bytes to read. For devices with
|
||||
multiple reports, make sure to read an extra byte for
|
||||
the report number.
|
||||
@param milliseconds timeout in milliseconds or -1 for blocking wait.
|
||||
|
||||
@returns
|
||||
This function returns the actual number of bytes read and
|
||||
-1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds);
|
||||
|
||||
/** @brief Read an Input report from a HID device.
|
||||
|
||||
Input reports are returned
|
||||
to the host through the INTERRUPT IN endpoint. The first byte will
|
||||
contain the Report number if the device uses numbered reports.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param data A buffer to put the read data into.
|
||||
@param length The number of bytes to read. For devices with
|
||||
multiple reports, make sure to read an extra byte for
|
||||
the report number.
|
||||
|
||||
@returns
|
||||
This function returns the actual number of bytes read and
|
||||
-1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Set the device handle to be non-blocking.
|
||||
|
||||
In non-blocking mode calls to hid_read() will return
|
||||
immediately with a value of 0 if there is no data to be
|
||||
read. In blocking mode, hid_read() will wait (block) until
|
||||
there is data to read before returning.
|
||||
|
||||
Nonblocking can be turned on and off at any time.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param nonblock enable or not the nonblocking reads
|
||||
- 1 to enable nonblocking
|
||||
- 0 to disable nonblocking.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock);
|
||||
|
||||
/** @brief Send a Feature report to the device.
|
||||
|
||||
Feature reports are sent over the Control endpoint as a
|
||||
Set_Report transfer. The first byte of @p data[] must
|
||||
contain the Report ID. For devices which only support a
|
||||
single report, this must be set to 0x0. The remaining bytes
|
||||
contain the report data. Since the Report ID is mandatory,
|
||||
calls to hid_send_feature_report() will always contain one
|
||||
more byte than the report contains. For example, if a hid
|
||||
report is 16 bytes long, 17 bytes must be passed to
|
||||
hid_send_feature_report(): the Report ID (or 0x0, for
|
||||
devices which do not use numbered reports), followed by the
|
||||
report data (16 bytes). In this example, the length passed
|
||||
in would be 17.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param data The data to send, including the report number as
|
||||
the first byte.
|
||||
@param length The length in bytes of the data to send, including
|
||||
the report number.
|
||||
|
||||
@returns
|
||||
This function returns the actual number of bytes written and
|
||||
-1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Get a feature report from a HID device.
|
||||
|
||||
Make sure to set the first byte of @p data[] to the Report
|
||||
ID of the report to be read. Make sure to allow space for
|
||||
this extra byte in @p data[].
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param data A buffer to put the read data into, including
|
||||
the Report ID. Set the first byte of @p data[] to the
|
||||
Report ID of the report to be read.
|
||||
@param length The number of bytes to read, including an
|
||||
extra byte for the report ID. The buffer can be longer
|
||||
than the actual report.
|
||||
|
||||
@returns
|
||||
This function returns the number of bytes read and
|
||||
-1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Close a HID device.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
*/
|
||||
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device);
|
||||
|
||||
/** @brief Get The Manufacturer String from a HID device.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param string A wide string buffer to put the data into.
|
||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get The Product String from a HID device.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param string A wide string buffer to put the data into.
|
||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get The Serial Number String from a HID device.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param string A wide string buffer to put the data into.
|
||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get a string from a HID device, based on its string index.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param string_index The index of the string to get.
|
||||
@param string A wide string buffer to put the data into.
|
||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get a string describing the last error which occurred.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
|
||||
@returns
|
||||
This function returns a string containing the last error
|
||||
which occurred or NULL if none has occurred.
|
||||
*/
|
||||
HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
85
Lib/projector/LC4500API/usb.cpp
Normal file
85
Lib/projector/LC4500API/usb.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* usb.cpp
|
||||
*
|
||||
* This module has the wrapper functions to access USB driver functions.
|
||||
*
|
||||
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* ALL RIGHTS RESERVED
|
||||
*
|
||||
*/
|
||||
|
||||
//#ifdef Q_OS_WIN32
|
||||
//#include <setupapi.h>
|
||||
//#endif
|
||||
//#include <QMessageBox>
|
||||
//#include <QTimer>
|
||||
#include "usb.h"
|
||||
//#include <stdio.h>
|
||||
//#include <stdlib.h>
|
||||
#include "hidapi.h"
|
||||
|
||||
/***************************************************
|
||||
* GLOBAL VARIABLES
|
||||
****************************************************/
|
||||
static hid_device *DeviceHandle; //Handle to write
|
||||
//In/Out buffers equal to HID endpoint size + 1
|
||||
//First byte is for Windows internal use and it is always 0
|
||||
unsigned char OutputBuffer[USB_MAX_PACKET_SIZE+1];
|
||||
unsigned char InputBuffer[USB_MAX_PACKET_SIZE+1];
|
||||
|
||||
static bool USBConnected = false; //Boolean true when device is connected
|
||||
|
||||
bool USB_IsConnected()
|
||||
{
|
||||
return USBConnected;
|
||||
}
|
||||
|
||||
int USB_Init(void)
|
||||
{
|
||||
return hid_init();
|
||||
}
|
||||
|
||||
int USB_Exit(void)
|
||||
{
|
||||
return hid_exit();
|
||||
}
|
||||
|
||||
int USB_Open()
|
||||
{
|
||||
// Open the device using the VID, PID,
|
||||
// and optionally the Serial number.
|
||||
DeviceHandle = hid_open(MY_VID, MY_PID, NULL);
|
||||
|
||||
if(DeviceHandle == NULL)
|
||||
{
|
||||
USBConnected = false;
|
||||
return -1;
|
||||
}
|
||||
USBConnected = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int USB_Write()
|
||||
{
|
||||
if(DeviceHandle == NULL)
|
||||
return -1;
|
||||
|
||||
return hid_write(DeviceHandle, OutputBuffer, USB_MIN_PACKET_SIZE+1);
|
||||
|
||||
}
|
||||
|
||||
int USB_Read()
|
||||
{
|
||||
if(DeviceHandle == NULL)
|
||||
return -1;
|
||||
|
||||
return hid_read_timeout(DeviceHandle, InputBuffer, USB_MIN_PACKET_SIZE+1, 2000);
|
||||
}
|
||||
|
||||
int USB_Close()
|
||||
{
|
||||
hid_close(DeviceHandle);
|
||||
USBConnected = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
28
Lib/projector/LC4500API/usb.h
Normal file
28
Lib/projector/LC4500API/usb.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* usb.h
|
||||
*
|
||||
* This module has the wrapper functions to access USB driver functions.
|
||||
*
|
||||
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* ALL RIGHTS RESERVED
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef USB_H
|
||||
#define USB_H
|
||||
|
||||
#define USB_MIN_PACKET_SIZE 64
|
||||
#define USB_MAX_PACKET_SIZE 64
|
||||
|
||||
#define MY_VID 0x0451
|
||||
#define MY_PID 0x6401
|
||||
|
||||
int USB_Open(void);
|
||||
bool USB_IsConnected();
|
||||
int USB_Write();
|
||||
int USB_Read();
|
||||
int USB_Close();
|
||||
int USB_Init();
|
||||
int USB_Exit();
|
||||
|
||||
#endif //USB_H
|
||||
24
Lib/projector/Projector.h
Normal file
24
Lib/projector/Projector.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef PROJECTOR_H
|
||||
#define PROJECTOR_H
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
// Abstract Projector base class
|
||||
class Projector {
|
||||
public:
|
||||
// Interface function
|
||||
Projector(){}
|
||||
// Define preset pattern sequence
|
||||
virtual void setPattern(unsigned int patternNumber , const unsigned char *tex , unsigned int texWidth , unsigned int texHeight) = 0;
|
||||
virtual void displayPattern(unsigned int patternNumber) = 0;
|
||||
// Upload and display pattern on the fly
|
||||
virtual void displayTexture(const unsigned char *tex , unsigned int width , unsigned int height) = 0;
|
||||
// Monochrome color display
|
||||
virtual void displayBlack() = 0;
|
||||
virtual void displayWhite() = 0;
|
||||
virtual void getScreenRes(unsigned int *nx , unsigned int *ny) = 0;
|
||||
virtual ~Projector(){}
|
||||
};
|
||||
|
||||
#endif
|
||||
83
Lib/projector/ProjectorLC4500.cpp
Normal file
83
Lib/projector/ProjectorLC4500.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#include "ProjectorLC4500.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "LC4500API/API.h"
|
||||
#include "LC4500API/usb.h"
|
||||
|
||||
void showError(std::string err){
|
||||
std::cerr << "lc4500startup: " << err.c_str() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
ProjectorLC4500::ProjectorLC4500(unsigned int): nPatterns(0) , isRunning(false){
|
||||
|
||||
std::cout << "ProjectorLC4500: preparing LightCrafter 4500 for duty... " << std::endl;
|
||||
|
||||
// Initialize usb connection
|
||||
if(USB_Init()){
|
||||
showError("Could not init USB!");
|
||||
}
|
||||
if(USB_Open()){
|
||||
showError("Could not connect!");
|
||||
}
|
||||
if(!USB_IsConnected()){
|
||||
showError("Could not connect.");
|
||||
}
|
||||
|
||||
// Make sure LC is not in standby
|
||||
const bool standby = false;
|
||||
if(!LCR_SetPowerMode(standby)){
|
||||
showError("Error Setting Power Mode");
|
||||
}
|
||||
|
||||
LCR_SetMode(false);
|
||||
LCR_SetInputSource(2 , 0);
|
||||
LCR_SetPixelFormat(0);
|
||||
}
|
||||
|
||||
void ProjectorLC4500::setPattern(unsigned int patternNumber , const unsigned char *tex , unsigned int texWidth ,unsigned int texHeight){
|
||||
|
||||
}
|
||||
|
||||
void ProjectorLC4500::displayPattern(unsigned int PatNum){
|
||||
LCR_LoadSplash(PatNum);
|
||||
rectangle croppedArea , displayArea;
|
||||
croppedArea.firstPixel = 0;
|
||||
croppedArea.firstLine = 0;
|
||||
croppedArea.pixelsPerLine = 912;
|
||||
croppedArea.linesPerFrame = 1140;
|
||||
displayArea.firstPixel = 0;
|
||||
displayArea.firstLine = 0;
|
||||
displayArea.pixelsPerLine = 1280;
|
||||
displayArea.linesPerFrame = 800;
|
||||
LCR_SetDisplay(croppedArea , displayArea);
|
||||
}
|
||||
|
||||
void ProjectorLC4500::displayTexture(const unsigned char *tex , unsigned int texWidth , unsigned int texHeight){
|
||||
|
||||
}
|
||||
|
||||
void ProjectorLC4500::displayBlack(){
|
||||
|
||||
}
|
||||
|
||||
void ProjectorLC4500::displayWhite(){
|
||||
|
||||
}
|
||||
|
||||
void ProjectorLC4500::getScreenRes(unsigned int *nx , unsigned int *ny){
|
||||
*nx = 912;
|
||||
*ny = 1140;
|
||||
}
|
||||
|
||||
ProjectorLC4500::~ProjectorLC4500(){
|
||||
|
||||
// Stop pattern sequence
|
||||
LCR_PatternDisplay(0);
|
||||
|
||||
USB_Close();
|
||||
USB_Exit();
|
||||
|
||||
}
|
||||
|
||||
29
Lib/projector/ProjectorLC4500.h
Normal file
29
Lib/projector/ProjectorLC4500.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef PROJECTORLC4500_H
|
||||
#define PROJECTORLC4500_H
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "Projector.h"
|
||||
|
||||
// Projecotr implementation for LightCrafter 4500 USB Api
|
||||
class ProjectorLC4500 : public Projector {
|
||||
public:
|
||||
// Interface function
|
||||
ProjectorLC4500(unsigned int);
|
||||
// Define preset pattern sequence and upload to GPU
|
||||
void setPattern(unsigned int patternNumber ,const unsigned char *tex ,unsigned int texWidth , unsigned int texHeight);
|
||||
void displayPattern(unsigned int patternNumber);
|
||||
// Upload and display pattern on the fly
|
||||
void displayTexture(const unsigned char *tex , unsigned int width , unsigned int height);
|
||||
void displayBlack();
|
||||
void displayWhite();
|
||||
void getScreenRes(unsigned int *nx , unsigned int *ny);
|
||||
~ProjectorLC4500();
|
||||
private:
|
||||
unsigned int nPatterns;
|
||||
bool isRunning;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user