How do you interpret a bit string using sharp snmp lib (hrPrinterDetectedErrorState)? - sharp-snmp

How do you interpret hrPrinterDetectedErrorState (http://cric.grenoble.cnrs.fr/Administrateurs/Outils/MIBS/?oid=1.3.6.1.2.1.25.3.5.1.2) or something like it using Sharp Snmp lib? Is there some kind of bit string type? It's kind of a bitmask, but you may only receive one byte instead of two (or I've seen four bytes).

Did it on my own in powershell.
[flags()] Enum hrPrinterDetectedErrorState
{
lowPaper = 0x8000
noPaper = 0x4000
lowToner = 0x2000
noToner = 0x1000
doorOpen = 0x0800
jammed = 0x0400
Offline = 0x0200
serviceRequested = 0x0100
inputTrayMissing = 0x0080
outputTrayMissing = 0x0040
markerSupplyMissing = 0x0020
outputNearFull = 0x0010
outputFull = 0x0008
inputTrayEmpty = 0x0004
overduePreventMaint = 0x0002
notUsed = 0x0001
}
function snmpmessage($data) {
$bytes = [byte[]][char[]]$data
# pack up to two bytes into an int left to right
$code = [int]$bytes[0]
$code = $code -shl 8
if ($bytes[1]) { $code = $code + $bytes[1] }
[hrPrinterDetectedErrorState]$code
}
PS C:\> snmpmessage -join [char[]](0x91,0x04)
inputTrayEmpty, serviceRequested, noToner, lowPaper

Related

Is fdisk divides address space for created partition?

On my system, it has one mem node created already in /dev (/dev/pmem). then i use fdisk command for creating a partition
After creating partition I apply lsblk command and my result is
pmem1 259:4 0 15.8G 0 disk
└─pmem1p2 259:7 0 14.3G 0 part
After that, I write mmap code (Refer devmam library) just like
off_t address = 0x00;
int width = 10;
void *virtladdr, *phyaddr;
int a = 5;
int *lendata = &a;
int main(void)
{
int mode = 0x0777;
char *filename = "/dev/pmem0";
int fdout;
if ((fdout = open (filename, O_RDWR | O_CREAT | O_TRUNC, mode )) < 0)//edited here
{
printf ("can't create file");
return 0;
}
mapped_size = page_size = getpagesize();
offset_in_page = (uint64_t)address & (page_size - 1);
if (offset_in_page + (width * 8) > page_size) {
mapped_size *= 2;
}
printf("map size %ld\n", mapped_size);
phyaddr = mmap(0, mapped_size, (PROT_READ | PROT_WRITE), MAP_SHARED, fdout, address & ~(off_t)(page_size - 1));
1 = I write value 10 on 0x00 address for /dev/pmem1
2 = I write value 20 on 0x00 address for /dev/pmem1p2
Then after I Read mmap
off_t address = 0x00;
int width = 10;
int main(void)
{
int retVal = -1;
int fd;
unsigned long mapped_size, page_size, offset_in_page;
void *virtladdr, *phyaddr;
fd = open("/dev/pmem0", O_RDWR | O_SYNC);
if(fd < 0)
{
printf("file not open \n");
}
mapped_size = page_size = getpagesize();
offset_in_page = (uint64_t)address & (page_size - 1);
if (offset_in_page + (width * 8) > page_size) {
mapped_size *= 2;
}
/* Map one page */
phyaddr = mmap(0, mapped_size, PROT_READ,MAP_PRIVATE , fd, address & ~(off_t)(page_size - 1));
1 = Read 0x00 address from /dev/pmem1 My output is 10
2 = Read 0x00 address from /dev/pmem1p2 My output is 20
So what happened here why 0th address value is different? Is fdisk create two partitions which address starts from 0x00? Or I am in the wrong way?

Shifting set bits in a UInt64 to the right of their respective bytes

I have a UInt64 value with some bits on and some off e.g.:
01010101 01010101 01010101 01010101 01010101 01010101 01010101 01010101
How can I easily shift the set bits to the right, such they are to the right end of their respective bytes e.g:
00001111 00001111 00001111 00001111 00001111 00001111 00001111 00001111
I've seen questions which move the on bits all the way to the right of the 64 bit unsigned integer, but I only want to shift them to the right of the byte in which they lie if possible.
Thanks.
using System;
using System.Linq;
namespace ConsoleApplication5
{
public class Program
{
public static void Main(String[] args)
{
var inputAsBinaryString = "01010101 01010101 01010101 01010101 01010101 01010101 01010101 01010101";
var inputAsUInt64 = GetBinaryStringAsUInt64(inputAsBinaryString);
var actualAsUInt64 = GetRightAlignedBytes(inputAsUInt64);
var actualAsBinaryString = GetAsBinaryString(actualAsUInt64);
var expectedAsBinaryString = "00001111 00001111 00001111 00001111 00001111 00001111 00001111 00001111";
var expectedAsUInt64 = GetBinaryStringAsUInt64(expectedAsBinaryString);
} // <-- Set a breakpoint here and inspect the values.
/* Bit-manipulation methods. */
private static UInt64 GetRightAlignedBytes(UInt64 n)
{
var rightAlignedByteArray =
BitConverter
.GetBytes(n)
.Select(b => GetRightAlignedByte(b))
.ToArray();
return BitConverter.ToUInt64(rightAlignedByteArray, 0);
}
/* Shove all of a byte's bits to the right. */
private static Byte GetRightAlignedByte(Byte b)
{
/* The << operator only works on 32 and 64 bit values.
This requires treating the result as an Int32 until it's returned. */
Int32 result = 0;
var numberOfSetBits = GetNumberOfSetBits(b);
for (Byte n = 1; n <= numberOfSetBits; n++)
{
/* Need to set n bits, but only perform n - 1 left shifts. */
result |= 1;
if (n < numberOfSetBits)
result = result << 1;
}
return (Byte) result;
}
private static Byte GetNumberOfSetBits(Byte b)
{
/* There are many ways to count the number of "set" bits in a byte.
This StackOverflow question
http://stackoverflow.com/questions/109023/how-to-count-the-number-of-set-bits-in-a-32-bit-integer
has a mind-numbing collection of answers.
Most of them are probably more efficient than this method. */
Int32 result = 0;
/* The >> operator only works on 32 and 64 bit values.
This requires converting the Byte parameter "b" to an Int32. */
Int32 n = b;
while (n > 0)
{
result += (n & 1);
n = n >> 1;
}
return (Byte) result;
}
/* GetBinaryStringAs* methods */
private static Int32 GetBinaryStringAsInt32(String s)
{
return Convert.ToInt32(String.Join("", s.Trim().Where(c => (c == '0') || (c == '1'))), 2);
}
private static UInt64 GetBinaryStringAsUInt64(String s)
{
return Convert.ToUInt64(String.Join("", s.Trim().Where(c => (c == '0') || (c == '1'))), 2);
}
/* GetAsBinaryString methods. */
private static String GetAsBinaryString_Helper(Byte[] bytes)
{
/* The order of the bytes returned by System.BitConverter.GetBytes()
depends on the CPU architecture. The returned byte array
will round-trip with other BitConverter methods, like its
ToInt32() method. But those same bytes will not round-trip
with any of the System.Convert methods, like ToInt32(String, Int32).
The System.Convert.To* methods expect the order of the bytes they
receive to be the *reverse* of the order returned by
System.BitConverter.GetBytes().
The value returned by this method can - after stripping off the spaces -
be fed into a System.Convert.To*() method.
For example, this round-trip test should print "True":
// Hi byte Lo byte
Int32 n = 257; // 00000000 00000000 00000001 00000001
Console.WriteLine(GetBinaryStringAsInt32(GetAsBinaryString(n)) == n);
*/
return String.Join(" ", bytes.Reverse().Select(b => GetAsBinaryString(b)));
}
private static String GetAsBinaryString(Int32 n)
{
/* Note that signed integers use two's complement
binary representation for negative numbers.
For example, calling this method with a parameter
of -42 returns this string:
11111111 11111111 11111111 11010110
*/
return GetAsBinaryString_Helper(BitConverter.GetBytes(n));
}
private static String GetAsBinaryString(UInt64 n)
{
return GetAsBinaryString_Helper(BitConverter.GetBytes(n));
}
private static String GetAsBinaryString(Byte n)
{
return Convert.ToString(n, 2).PadLeft(8, '0');
}
}
}

Programatically Change Attributes of Windows File with Wild Cards (*.jpg) in VFP

Hoping to use a windows shell API call that can accept wild cards to change attributes programmatically. Utmost thanks/blessings for any/all thoughts.
Borrowing code from http://www.resolvinghere.com/sm/how-do-i-change-an-attribute-of-a-file-from-within-a-visual-foxpro-program.shtml
RUN /N ATTRIB +H "c:\test.txt" && Hidden causes dos window to noise itself
RUN /N ATTRIB -H "c:\test.txt" && UnHidden
Tom recalled this ... but it does not take wild-cards:
*------------CHAR-------HEX------------------BIN---------NUM
* READONLY R 0x00000001 00000000 00000001 1
* HIDDEN H 0x00000002 00000000 00000010 2
* SYSTEM S 0x00000004 00000000 00000100 4
* DIRECTORY D 0x00000010 00000000 00010000 16
* ARCHIVE A 0x00000020 00000000 00100000 32
* NORMAL N 0x00000080 00000000 10000000 128
* TEMPORARY T 0x00000100 00000001 00000000 256
* COMPRESS C 0x00000800 00001000 00000000 2048
* NOINDEX I 0x00002000 00100000 00000000 8192
* CHIPHER P 0x00004000 01000000 00000000 16384
* ERROR 0xFFFFFFFF REPL("1",32) 4294967295
* ----------------------------------------------------------------------
LPARAMETER vFilename as String, vNewAttribute as String
LOCAL liFlag as Integer, llResult, liAttributes, lnNewAttribute, cDummy, nBitPos, cBitMap
DECLARE INTEGER SetFileAttributes IN Win32API STRING, INTEGER
DECLARE INTEGER GetFileAttributes IN Win32API STRING
llResult = .F.
IF !EMPTY(vFilename)
IF VARTYPE(vNewAttribute) = [C]
lnNewAttribute = 0
* 1234567890123456
cBitMap = [RHS DA NT C IP ]
FOR i = 1 TO LEN(vNewAttribute)
cDummy = SUBSTR(vNewAttribute,i,1)
nBitPos = AT(cDummy,cBitMap)
IF nBitPos > 0
lnNewAttribute = BITSET(lnNewAttribute, nBitPos -1 )
ENDIF
ENDFOR
ELSE
lnNewAttribute = vNewAttribute
ENDIF
liAttributes = GetFileAttributes(vFilename)
IF (liAttributes # -1)
lnNewAttribute = BITXOR(liAttributes, lnNewAttribute)
llResult = (SetFileAttributes(vFilename, lnNewAttribute) = 1 )
ENDIF
ENDIF
RETURN llResult
Of course RUN ... should not be one of your selections to accomplish a procedure where you don't need to shell to DOS at all.
Your question is two fold:
How do get a list of files using a wildcard + in all subdirectories.
For this one you can use a bunch of alternatives such as FileSystemObject, Adir() or Filer.dll that ships with VFP and maybe more. Here I will sample with the Filer.dll (which is also the DLL used in HOME()+'tools\filer\filer.scx' ). Here is one enhanced wildcard match using filer:
*GetTree.prg
Lparameters tcStartDir,tcSkeleton,tcCursorName,;
tlSubfolders,;
tlWholeWords,tlIgnoreCase,tlSearchAnd,tcSearch1,tcSearch2,tcSearch3
Create Cursor (m.tcCursorName) ;
(filepath m, filename m, ;
FileSize i, fattr c(8), createtime T, lastacc T, lastwrite T)
Local oFiler, lnFound
oFiler = Createobject('filer.fileutil')
With m.oFiler
.SearchPath = m.tcStartDir
.FileExpression = m.tcSkeleton && Search for skeleton
.Subfolder = Iif(m.tlSubfolders,1,0) && Check subfolders
.IgnoreCase = Iif(m.tlIgnoreCase,1,0)
.WholeWords = Iif(m.tlWholeWords,1,0)
.SearchAnd = Iif(m.tlSearchAnd,1,0)
.SearchText1 = Iif(Empty(m.tcSearch1),"",m.tcSearch1)
.SearchText2 = Iif(Empty(m.tcSearch2),"",m.tcSearch2)
.SearchText3 = Iif(Empty(m.tcSearch3),"",m.tcSearch3)
lnFound = .Find(0)
For ix=1 To m.lnFound
With .Files(m.ix)
If !(Bittest(.Attr,4) And .Name = '.')
Insert Into (m.tcCursorName) ;
(filepath, filename, FileSize, fattr, createtime, lastacc, lastwrite) ;
values ;
(.Path, .Name, .Size, Attr2Char(.Attr), ;
Num2Time(.Datetime), Num2Time(.LastAccessTime), Num2Time(.LastWriteTime))
Endif
Endwith
Endfor
Endwith
Return m.lnFound
Function Num2Time
Lparameters tnFloat
Return Dtot({^1899/12/30}+Int(m.tnFloat))+86400*(m.tnFloat-Int(m.tnFloat))
Function Attr2Char
Lparameters tnAttr
Return ;
IIF(Bittest(m.tnAttr,0),'RO','RW')+;
IIF(Bittest(m.tnAttr,1),'H','_')+;
IIF(Bittest(m.tnAttr,2),'S','_')+;
IIF(Bittest(m.tnAttr,4),'D','_')+;
IIF(Bittest(m.tnAttr,5),'A','_')+;
IIF(Bittest(m.tnAttr,6),'E','_')+;
IIF(Bittest(m.tnAttr,7),'N','_')
How do I set the attributes.
If you are not after those fancy attributes, that are rarely used, here is the function I have written for myself:
*SetFAttributes.prg
lparameters tcFileName, tlReadOnly, tlHidden, tlSystem
#define FILE_ATTRIBUTE_READONLY 0x00000001
#define FILE_ATTRIBUTE_HIDDEN 0x00000002
#define FILE_ATTRIBUTE_SYSTEM 0x00000004
local lnNewAttr
lnNewAttr = iif(m.tlReadonly,FILE_ATTRIBUTE_READONLY,0)+;
iif(m.tlHidden,FILE_ATTRIBUTE_HIDDEN,0)+;
iif(m.tlSystem,FILE_ATTRIBUTE_SYSTEM,0)
declare integer SetFileAttributes in Win32API ;
string # lpFileName, integer dwFileAttributes
declare integer GetFileAttributes in Win32API ;
string # lpFileName
return ( SetFileAttributes(#tcFilename, ;
bitor(bitand(GetFileAttributes(#tcFilename),0xFFFFFFF8),m.lnNewAttr)) = 1)
Having the above prg files on hand, lets say you want to set all .txt files under c:\MyFolder and its subfolders to readonly, (not hidden, not system) you would be doing this:
Local lcFileName
GetTree('c:\MyFolder','*.txt', 'myCursor', .T.)
Select myCursor
scan for Atc('D',fAttr) = 0
lcFileName = Addbs(Trim(FilePath))+Trim(FileName)
SetFAttributes(m.lcFileName, .T., .F., .F.)
endscan

How to print 'flags' field in 'struct page' in Linux-based user program

Hi,
I am trying to write a user program to print the value of the 'flags' field of all the pages in the 'mem_map' array. I then want to see if the reserved bit is set.
For starters, I wrote a kernel module to print the value of the first 20 pages in the 'mem_map' array, their respective 'flags' fields and the output of the PageReserved macro.
for (;i < 20; ++i) {
unsigned long *value = &(mem_map[i].flags);
printk("i = %u page->flags value = %u phy address = %#x isReserved = %d\n", i,mem_map[i].flags, virt_to_phys(&(mem_map[i].flags)),PageReserved(&mem_map[i]));
}
When I run "dmesg | tail -50", I see the following values:
[ 2858.387520] i = 0 page->flags value = 0 phy address = 0x36840000 isReserved = 0
[ 2858.387520] i = 1 page->flags value = 1024 phy address = 0x36840020 isReserved = 1
[ 2858.387520] i = 2 page->flags value = 1024 phy address = 0x36840040 isReserved = 1
[ 2858.387520] i = 3 page->flags value = 1024 phy address = 0x36840060 isReserved = 1
Note that I am printing the Physical address of the 'flags' field along with the value.
I want to reproduce the above result in a user program by just looking at the addresses via pointers.
I opened '/dev/mem', with the offset of the first page's 'flag' field: 0x36840000 . I made sure I compiled the kernel with STRICT_DEVMEM off and added a default 'return 1' in 'devmem_is_allowed()' function.
/* create the offset for mmap() using the physical address of the
mem_map[] array*/
off_t offset = 0x36840000;
/* /dev/mem contains the physical memory map */
if ((fd = open("/dev/mem", O_RDONLY)) == -1) {
printf("/dev/mem could not be opened.\n");
perror("open");
exit(1);
else {
printf("/dev/mem opened.\n");
}
starting_page = (char*)mmap(0, MAP_SIZE, PROT_READ,MAP_SHARED, fd,offset);
if (starting_page == MAP_FAILED) {
perror("mmap");
return -1;
}
else {
printf("Memory mapped at address %p.\n", starting_page);
}
mapped_page = starting_page;
for (i=0;i<10;++i,mapped_page+=32) {
printf("\npage i = %u flags value %ul ", i, *(mapped_page));
}
However, when I simply print out the value of the "flags value" ,I get zeros. Any suggestions on what I am getting zeroes and how to debug this?
Thanks!
-RR

MCP2200 linux settings

Im want to control MCP2200 in linux.
I found Text Link and set everything.
For example:
I type in console
GP3-1
It will sets pin 3 to 1. But i dont know what to type in console
for controlling the mcp2200 you will need a program doing the stuff for you.
The USBtoUART didn't work for me, maybe you'll have to do some coding yourself - but you can use it to understand how to connect to the mcp2200 hid.
For controlling the IOs, just set up a 16-byte array, filled with the data described here:
http://ww1.microchip.com/downloads/en/DeviceDoc/93066A.pdf
If you want to control some more stuff but gpios, you'll have to do some more - it is possible to control more than just the gpios of the mcp2200 from linux.
I did a little usb trace of the communication of the windows config tool, extracted some informations and - tadaah, there you go with your own pID/vID, Manufacturer and Product strings.
Note: you'll probably need the HIDAPI MikeF was talking about.
First of all, some definitions:
// NOTE: max. string length for manufacturer / product string is 63 bytes!!
// from usb trace of mcp2200 config tool
#define MCP2200_SECRET_CONFIGURE 0x01
#define MCP2200_CFG_PID_VID 0x00
#define MCP2200_CFG_MANU 0x01
#define MCP2200_CFG_PROD 0x02
... and some variables:
unsigned char **mcp2200_manu_string;
unsigned char **mcp2200_prod_string;
The output message for manufacturer string looks like
/* configure manufacturer string (16 x 16 bytes):
* output buffer:
* #0: [01 01 00 16 03 58 00 4B 00 72 00 FF FF FF FF FF]
* | | | | | | | | | | | +-----------+--> Always FF
* | | | | | | +-----+-----+-----------------> Always 00
* | | | | | +-----+-----+--------------------> First 3 Chars of Manufacturer Name / Product Name
* | | | | +-----------------------------------> In #0: 0x03, After #0: 0x00
* | | | +--------------------------------------> (Length (Manufacturer Name) * 2) + 2 (after #0: chars of manufacturer name)
* | | +-----------------------------------------> Counter 0x00 .. 0x0F
* | +--------------------------------------------> MCP2200 Config Bit (MCP2200_CFG_MANU / PROD / VID_PID)
* +-----------------------------------------------> MCP2200_SECRET_CONFIGURE from usb trace
*/
if you put all this in a function, it could look like this:
void prepare_cfg_strings (char* manu, char* prod) {
char manuStr[64];
char prodStr[64];
unsigned int i, k = 0;
unsigned char tmp = 0;
memset (manuStr, 0x00, sizeof(manuStr));
memset (prodStr, 0x00, sizeof(prodStr));
// allocate mcp2200_{manu,prod}_string buffer, 2-dim array with 16 x 16 chars
if (( mcp2200_manu_string = ( unsigned char** )malloc( 16*sizeof( unsigned char* ))) == NULL ) {
// error
}
if (( mcp2200_prod_string = ( unsigned char** )malloc( 16*sizeof( unsigned char* ))) == NULL ) {
// error
}
for ( i = 0; i < 16; i++ )
{
if (( mcp2200_manu_string[i] = ( unsigned char* )malloc( 16 )) == NULL ) {
/* error */
}
if (( mcp2200_prod_string[i] = ( unsigned char* )malloc( 16 )) == NULL ) {
/* error */
}
/* init the rows here */
memset (mcp2200_manu_string[i], 0x00, sizeof(&mcp2200_manu_string[i]));
memset (mcp2200_prod_string[i], 0x00, sizeof(&mcp2200_prod_string[i]));
}
// manuStr holds (strlen(manuStr) * 2) + 2 in byte[0] and manufacturer string from byte[1] on
strcpy (&manuStr[1], manu);
manuStr[0] = ((strlen (&manuStr[1]) * 2) + 2);
// prodStr holds (strlen(prodStr) * 2) + 2 in byte[0] and product string from byte[1] on
strcpy (&prodStr[1], prod);
prodStr[0] = ((strlen (&prodStr[1]) * 2) + 2);
// build manufacturer / product strings
for (i=0, k=0; i<16; i++, k+=4) {
if (i==0) {
tmp = 0x03;
} else {
tmp = 0x00;
}
// manufacturer string
mcp2200_manu_string[i][0] = MCP2200_SECRET_CONFIGURE;
mcp2200_manu_string[i][1] = MCP2200_CFG_MANU;
mcp2200_manu_string[i][2] = i;
mcp2200_manu_string[i][3] = manuStr[k];
mcp2200_manu_string[i][4] = tmp;
mcp2200_manu_string[i][5] = manuStr[k+1];
mcp2200_manu_string[i][6] = 0x00;
mcp2200_manu_string[i][7] = manuStr[k+2];
mcp2200_manu_string[i][8] = 0x00;
mcp2200_manu_string[i][9] = manuStr[k+3];
mcp2200_manu_string[i][10] = 0x00;
mcp2200_manu_string[i][11] = 0xff;
mcp2200_manu_string[i][12] = 0xff;
mcp2200_manu_string[i][13] = 0xff;
mcp2200_manu_string[i][14] = 0xff;
mcp2200_manu_string[i][15] = 0xff;
// product string
mcp2200_prod_string[i][0] = MCP2200_SECRET_CONFIGURE;
mcp2200_prod_string[i][1] = MCP2200_CFG_PROD;
mcp2200_prod_string[i][2] = i;
mcp2200_prod_string[i][3] = prodStr[k];
mcp2200_prod_string[i][4] = tmp;
mcp2200_prod_string[i][5] = prodStr[k+1];
mcp2200_prod_string[i][6] = 0x00;
mcp2200_prod_string[i][7] = prodStr[k+2];
mcp2200_prod_string[i][8] = 0x00;
mcp2200_prod_string[i][9] = prodStr[k+3];
mcp2200_prod_string[i][10] = 0x00;
mcp2200_prod_string[i][11] = 0xff;
mcp2200_prod_string[i][12] = 0xff;
mcp2200_prod_string[i][13] = 0xff;
mcp2200_prod_string[i][14] = 0xff;
mcp2200_prod_string[i][15] = 0xff;
}
}
Call this function in your main loop:
prepare_cfg_strings ("MyManufacturerName, "MyProductName");
Open a hid handle to your mcp2200 and put this stuff on the bus:
// write manufacturer string configuration to usb device
for (i=0; i<16; i++) {
hid_write (handle, mcp2200_manu_string[i], 16);
}
// write product string configuration to usb device
for (i=0; i<16; i++) {
hid_write (handle, mcp2200_prod_string[i], 16);
}
If you want to flash the mcp2200 with your own VendorID / ProductID configure your message:
// Microchip VID: 0x04d8
// MCP2200 PID: 0x00df
mcp2200_pid_vid_cfg[] = 01 00 D8 04 DF 00 00 00 00 00 00 00 00 00 00 00
| | +---+ +---+--------------------------------> Product ID (bytes swapped)
| | +--------------------------------------> Vendor ID (bytes swapped)
| +--------------------------------------------> MCP2200 Config Bit (MCP2200_CFG_VID_PID)
+-----------------------------------------------> MCP2200_SECRET_CONFIGURE from usb trace
and put it on the bus:
hid_write (handle, mcp2200_pid_vid_cfg, 16);
Have Fun!
n.
You will not be able to control the GPIO ports from the console/terminal via USB tty...
The USB to serial/UART converter is one of the features of MCP2200, to control the GPIO, you need to send commands via USB & HID driver. to achieve this, you will need the following.
HIDAPI:
https://github.com/signal11/hidapi
USBtoUART:
https://github.com/Miceuz/USBtoUART
USBtoUART requires hid.o from the HIDAPI package.... so start with HIDAPI first...
good luck!
MikeF
ps: I made a few modifications to the code, to accept binary format for controlling the GPIO ports, etc... it has been compiled fine on x86 and ARM ( Raspberry Pi )

Resources