Пример #1
0
int main()                        //this function actually runs the karmarkar's algorithm, ie minimising objective funtion
{
    int n,m,i,j,k,L,ceil1,ceil2,K,q,cmp;
    float x1[50][1],x2[50][1],x0[50][1],P,c[50][50],c2[50][50],temp[50][50],log2,logP,logn,val,f1,f2;
    float valx,val0;
    float a[50][50],d[50][50],aintact[50][50];
    uint32_t         start, stop;

    printf("\n Enter the order of the linear program:");
    scanf("%d",&n);

    printf("\n Enter the number of constraints:");
    scanf("%d",&m);

    printf("\n Enter the coefficients of the variables in the objective funtion:");
    for(i=0;i<n;i++)                  //input of objective function
        scanf("%f",&c[i][0]);             //c actually behaves like a row matrix, inspite of its definition         

    printf("\n Enter the matrix of constraints rowwise:");
    for(i=0;i<m;i++)                 //loop for input of constarints
        for(j=0;j<n;j++)
        {
            scanf("%f",&a[i][j]); 
            aintact[i][j]=a[i][j];
        }

    start = stampstart();

    alpha=n-1;                        //initialising alpha
    alpha=(alpha)/(3*n);

    delta=alpha*alpha;                //calculation of delta
    delta=delta/(1-alpha);
    delta=alpha-delta;

    L=n*m;

    P=1.0;

    for(i=0;i<n;i++)                  //calculation of P,step needs review
    {
        if(c[i][0]!=0)
            P=P*c[i][0];
    }

    P=abs(P);

    log2=log(2);
    logP=log(P)/log2;
    logn=log(n)/log2;
    ceil1=(int)(logP);
    ceil1=ceil1+1;

    ceil2=(int)(logn);
    ceil2=ceil2+1;
    ceil2=ceil2*n;

    L=L+ceil1+ceil2;                  //L is an int, calculation of L
    K=(int)((2*n*L)/(delta));
    K++;                              // iteration bound K calculated

    val=(float)(n);
    val=1/val;                          //i dont know if it has type cast errors

    for(i=0;i<n;i++)                  //initialisation of x0
        x0[i][0]=val;
    
    for(i=0;i<n;i++)                 // c shall always be intact throughout the program,c2 is the temp c
        c2[i][0]=c[i][0];

    for(i=0;i<n;i++)                 //for compatibility in mul fn
        temp[i][0]=x0[i][0];

    transpose(c2,n,1);               //transposing the temporary c

    mul(c2,temp,1,n,n,1);              // the base case

    val=c2[0][0];

    if(val==0)                         //check if a0=x0 is the answer
    {
        display(c,x0,n);
        stop=stampstop(start);
        exit(0);
    }

    for(i=0;i<n;i++)                  //this loop initialises the first x1 as x0, ie the starting point
        x1[i][0]=x0[i][0];

    for(i=0;i<K;i++)                 //this is the actual loop to calculate the optimal point
    {

        for(j=0;j<n;j++)                 //x2 will now posses values of x1, x2 goes under transformation
        x2[j][0]=x1[j][0];

        for(j=0;j<n;j++)
        {
            for(k=0;k<n;k++)
            {
                if(k==j)
                    d[j][k]=x2[j][0];
                else
                    d[j][k]=0;
            }
        }

        phi(c,aintact,d,x2,n,m);               //here i am phi ing x2 while keeping the original point as x1 

        for(j=0;j<n;j++)                 // c shall always be intact throughout the program
             c2[j][0]=c[j][0];

        transpose(c2,n,1);               //transposing the temporary c

        for(j=0;j<n;j++)                 //because x2 is a column matrix and hence is unsuitable for multiplication
            temp[j][0]=x2[j][0];

        mul(c2,temp,1,n,n,1);

        if(val==0)
        {         
            display(c,x2,n);
            stop=stampstop(start);
            exit(0);
        }

        cmp=compvals(x1,x2,n);
        if(cmp==0)
        {
            display(c,x2,n);
            stop=stampstop(start);
            exit(0);
        }

        f2=f(x2,c,n);                    //the positive optimality test
        f1=f(x1,c,n);
        /*
        printf("\n x1 is:");
        for(j=0;j<n;j++)
        printf(" %f",x1[j][0]);

        printf("\n x2 is:");
        for(j=0;j<n;j++)
        printf(" %f",x2[j][0]);

        printf("\n Values of fx, fx-1 and delta  are resp %f %f %f",f2,f1,delta);
        exit(0);
        */

        if(f2>(f1-(0.01*delta)))                //needs reviewing
        {
            printf("\n The solution is unfeasible or unbounded, no finite optimal solution exists for it");
            stop=stampstop(start);
            exit(0);
        }
                                  //under repair

    //till here we have done as required till step2 of the linear programming book

        for(j=0;j<n;j++)
            x1[j][0]=x2[j][0];             //for continuance of the loop ie x1 becomes the generated x2, step needs review

        //the termination condition q as defined in the paper, i dont know what value it takes but i think its 2*L

        for(j=0;j<n;j++)                 // c shall always be intact throughout the program,c2 is the temp c
            c2[j][0]=c[j][0];

        transpose(c2,n,1);

        for(j=0;j<n;j++)
            temp[j][0]=x2[j][0];

        mul(c2,temp,1,n,n,1);
        valx=c2[0][0];

        for(j=0;j<n;j++)                 // c shall always be intact throughout the program,c2 is the temp c
            c2[j][0]=c[j][0];

        transpose(c2,n,1);

        for(j=0;j<n;j++)
            temp[j][0]=x0[j][0];

        mul(c2,temp,1,n,n,1);
        val0=c2[0][0];

        valx=valx/val0;

    }                               // end of principal loop

    display(c,x2,n);
    stop=stampstop(start);
}                                //end of main
Пример #2
0
/**
 * dun dun DUN
 */
int main(int argc, char **argv)
{
    usbDevice_t *dev = NULL ;
    int err;

    // this needs to be a global int for getopt_long
    static int cmd  = CMD_NONE;
    int16_t arg  = 0;
    char addr = 0;
    //long color  = 0;
    //int num = 1;
    int millis  = 100;
    char file[255];

    uint8_t buffer[65];  // room for dummy report ID  (this will go away soon?)
    uint8_t cmdbuf[64];  // blinkm command buffer
    uint8_t recvbuf[64];
    int len;

    memset(cmdbuf,0,sizeof(cmdbuf));  // zero out for debugging ease

    srand( time(0) );    // a good enough seeding for our purposes

    if(argc < 2){
        usage(argv[0]);
    }

    // parse options
    int option_index = 0, opt;
    char* opt_str = "a:df:m:v";
    static struct option loptions[] = {
        {"addr",       required_argument, 0,      'a'},
        {"debug",      optional_argument, 0,      'd'},
        {"file",       required_argument, 0,      'f'},
        {"millis",     required_argument, 0,      'm'},
        {"verbose",    optional_argument, 0,      'v'},
        {"linkmread",  no_argument,       &cmd,   CMD_LINKM_READ },
        {"linkmwrite", required_argument, &cmd,   CMD_LINKM_WRITE },
        {"linkmcmd",   required_argument, &cmd,   CMD_LINKM_CMD },
        {"linkmversion",no_argument,      &cmd,   CMD_LINKM_VERSIONGET },
        {"linkmeesave",no_argument,       &cmd,   CMD_LINKM_EESAVE },
        {"linkmeeload",no_argument,       &cmd,   CMD_LINKM_EELOAD },
        {"statled",    required_argument, &cmd,   CMD_LINKM_STATLEDSET },
        {"i2cscan",    no_argument,       &cmd,   CMD_LINKM_I2CSCAN },
        {"i2cenable",  required_argument, &cmd,   CMD_LINKM_I2CENABLE },
        {"i2cinit",    no_argument,       &cmd,   CMD_LINKM_I2CINIT },
        {"cmd",        required_argument, &cmd,   CMD_BLINKM_CMD },
        {"off",        no_argument,       &cmd,   CMD_BLINKM_OFF },
        {"on",         no_argument,       &cmd,   CMD_BLINKM_ON },
        {"stop",       no_argument,       &cmd,   CMD_BLINKM_STOP },
        {"play",       required_argument, &cmd,   CMD_BLINKM_PLAY },
        {"fadespeed",  required_argument, &cmd,   CMD_BLINKM_FADESPEED },
        {"color",      required_argument, &cmd,   CMD_BLINKM_COLOR },
        {"upload",     required_argument, &cmd,   CMD_BLINKM_UPLOAD },
        {"download",   required_argument, &cmd,   CMD_BLINKM_DOWNLOAD },
        {"readinputs", optional_argument, &cmd,   CMD_BLINKM_READINPUTS },
        {"random",     required_argument, &cmd,   CMD_BLINKM_RANDOM },
        {"flash",      optional_argument, &cmd,   CMD_BLINKM_FLASH },
        {"setaddr",    required_argument, &cmd,   CMD_BLINKM_SETADDR },
        {"getversion", no_argument,       &cmd,   CMD_BLINKM_GETVERSION },
        {"playset",    required_argument, &cmd,   CMD_LINKM_PLAYSET },
        {"playget",    no_argument,       &cmd,   CMD_LINKM_PLAYGET },
        {"gobootload", no_argument,       &cmd,   CMD_LINKM_BOOTLOADGO },
#if ADDBOOTLOAD == 1
        {"bootloadreset",no_argument,       &cmd,   CMD_LINKM_BOOTLOADRESET },
        {"bootload",     required_argument, &cmd,   CMD_LINKM_BOOTLOAD },
#endif
        {NULL,         0,                 0,      0}
    };

    while(1) {
        opt = getopt_long (argc, argv, opt_str, loptions, &option_index);
        if (opt==-1) break; // parsed all the args
        switch (opt) {
        case 0:             // deal with long opts that have no short opts
            switch(cmd) { 
            case CMD_LINKM_PLAYSET:
            case CMD_LINKM_WRITE:
            case CMD_LINKM_CMD:
            case CMD_BLINKM_CMD:
            case CMD_BLINKM_COLOR:
                hexread(cmdbuf, optarg, sizeof(cmdbuf));  // cmd w/ hexlist arg
                break;
            case CMD_LINKM_STATLEDSET:
            case CMD_LINKM_I2CENABLE:
            case CMD_BLINKM_RANDOM:
            case CMD_BLINKM_FLASH:
            case CMD_BLINKM_SETADDR:
            case CMD_BLINKM_PLAY:
            case CMD_BLINKM_FADESPEED:
            case CMD_BLINKM_READINPUTS:
                if( optarg ) 
                    arg = strtol(optarg,NULL,0);   // cmd w/ number arg
                break;
            case CMD_LINKM_BOOTLOAD:
                strcpy(file,optarg);
                break;
            }
            break;
        case 'a':
            addr = strtol(optarg,NULL,0);
            break;
        case 'f':
            strcpy(file,optarg);
            break;
        case 'm':
            millis = strtol(optarg,NULL,10);
            break;
        case 'v':
        case 'd':
            if( optarg==NULL ) debug++;
            else debug = strtol(optarg,NULL,0);
        default:
            break;
        }
    }
    
    if( cmd == CMD_NONE ) usage(argv[0]);   // just in case
    linkm_debug = debug;


#if ADDBOOTLOAD == 1
    if( cmd == CMD_LINKM_BOOTLOAD ) {
        printf("linkmboot uploading firmware: %s\n",file);
        int rc = linkmboot_uploadFromFile(file, 0);
        if( rc == -1 ) {
            return 1;
        }
        if( rc == -2 ) {
            fprintf(stderr, "No data in input file, exiting.\n");
            return 0;
        }
        else if( rc == -3 ) { 
            fprintf(stderr,"error uploading\n");
        }
        printf("Flashing done.\n");
        return 1;
    }

    if( cmd == CMD_LINKM_BOOTLOADRESET ) {
        printf("linkmboot resetting bootloader:\n");
        if( linkmboot_reset() ) {
            exit(1);
        }
        printf("reset done\n");
        exit(0);
    }
#endif

    // open up linkm, get back a 'dev' to pass around
    if( (err = linkm_open( &dev )) ) {
        fprintf(stderr, "Error opening LinkM: %s\n", linkm_error_msg(err));
        exit(1);
    }
    
    if( cmd == CMD_LINKM_BOOTLOADGO ) {
        printf("linkm switching to bootloader:\n");
        err = linkm_command(dev, LINKM_CMD_GOBOOTLOAD, 0, 0, NULL, NULL);
        //if( err ) {
        //    fprintf(stderr,"error on linkm cmd: %s\n",linkm_error_msg(err));
        //}
        printf("linkm is now in bootloader mode\n");
    }
    else if( cmd == CMD_LINKM_VERSIONGET ) {
        printf("linkm version: ");
        err = linkm_command(dev, LINKM_CMD_VERSIONGET, 0, 2, NULL, recvbuf);
        if( err ) {
            fprintf(stderr,"error on linkm cmd: %s\n",linkm_error_msg(err));
        }
        else {  // success
            hexdump("", recvbuf, 2);
        }
    }
    else if( cmd == CMD_LINKM_PLAYSET ) {   // control LinkM's state machine
        printf("linkm play set: ");
        err = linkm_command(dev, LINKM_CMD_PLAYSET, 7,0, cmdbuf, NULL);
        if( err ) {
            fprintf(stderr,"error on linkm cmd: %s\n",linkm_error_msg(err));
        }
        printf("done\n");
    }
    else if( cmd == CMD_LINKM_PLAYGET ) {   // read LinkM's state machine
        printf("linkm play get: ");
        err = linkm_command(dev, LINKM_CMD_PLAYGET, 0,7, NULL, recvbuf);
        if( err ) {
            fprintf(stderr,"error on linkm cmd: %s\n",linkm_error_msg(err));
        }
        else {  // success
            hexdump("", recvbuf, 7);
        }
    }
    else if( cmd == CMD_LINKM_EESAVE ) {  // tell linkm to save params to eeprom
        printf("linkm eeprom save: done\n");
        err = linkm_command(dev, LINKM_CMD_EESAVE, 0,0, NULL, NULL);
        if( err ) {
            fprintf(stderr,"error on linkm cmd: %s\n",linkm_error_msg(err));
        }
    }
    else if( cmd == CMD_LINKM_EELOAD ) {  // tell linkm to load params to eeprom
        printf("linkm eeprom load: done\n");
        err = linkm_command(dev, LINKM_CMD_EELOAD, 0,0, NULL, NULL);
        if( err ) {
            fprintf(stderr,"error on linkm cmd: %s\n",linkm_error_msg(err));
        }
    }
    else if( cmd == CMD_LINKM_STATLEDSET ) {    // control LinkM's status LED 
        err = linkm_command(dev, LINKM_CMD_STATLEDSET, 1,0,(uint8_t*)&arg,NULL);
        if( err ) {
            fprintf(stderr,"error on linkm cmd: %s\n",linkm_error_msg(err));
        }
    }
    else if( cmd == CMD_LINKM_I2CENABLE ) {    // enable/disable i2c buffer
        err = linkm_command(dev, LINKM_CMD_I2CCONN, 1,0,  (uint8_t*)&arg,NULL);
        if( err ) {
            fprintf(stderr,"error on linkm cmd: %s\n",linkm_error_msg(err));
        }
    }
    else if( cmd == CMD_LINKM_I2CINIT ) {     // restart LinkM's I2C software
        err = linkm_command(dev, LINKM_CMD_I2CINIT, 0,0,  NULL,NULL);
        if( err ) {
            fprintf(stderr,"error on linkm cmd: %s\n",linkm_error_msg(err));
        }
    }
    else if( cmd == CMD_LINKM_I2CSCAN ) { 
        //if( addr == 0 ) addr = 1;
        printf("i2c scan from addresses %d - %d\n", 1, 113);
        int saddr = addr;
        for( int i=0; i < 7; i++ ) { 
            saddr = i*16 + 1;
            cmdbuf[0] = saddr;    // start address: 01
            cmdbuf[1] = saddr+16; // end address:   16 // FIXME: allow arbitrary
            err = linkm_command(dev, LINKM_CMD_I2CSCAN, 2, 16, cmdbuf, recvbuf);
            if( err ) {
                fprintf(stderr,"error on i2c scan: %s\n",linkm_error_msg(err));
            }
            else {
                if(debug) hexdump("recvbuf:", recvbuf, 16);
                int cnt = recvbuf[0];
                if( cnt != 0 ) {
                    for( int i=0; i< cnt; i++ ) {
                        printf("device found at address %d\n",recvbuf[1+i]);
                    }
                }
            }
        } // for
    }
    else if( cmd == CMD_BLINKM_CMD ) {   // send arbitrary blinkm command
        printf("addr %d: sending cmd:%c,0x%02x,0x%02x,0x%02x\n",addr,
               cmdbuf[0],cmdbuf[1],cmdbuf[2],cmdbuf[3]);
        // fixme: check that 'b'yte array arg was used
        memmove( cmdbuf+1, cmdbuf, sizeof(cmdbuf)-1 );  // move over for addr
        cmdbuf[0] = addr;
        // do i2c transaction (0x01) with no recv
        err = linkm_command(dev, LINKM_CMD_I2CTRANS, 5,0, cmdbuf, NULL );
        if( err ) {
            fprintf(stderr,"error on blinkm cmd: %s\n",linkm_error_msg(err));
        }
    }
    else if( cmd == CMD_BLINKM_GETVERSION ) {
        if( addr == 0 ) {
            printf("Must specify non-zero address for download\n");
            goto shutdown;
        }
        printf("addr:%d: getting version\n", addr );
        cmdbuf[0] = addr;
        cmdbuf[1] = 'Z';
        err = linkm_command(dev, LINKM_CMD_I2CTRANS, 2, 2, cmdbuf, recvbuf);
        if( err ) {
            fprintf(stderr,"error on getversion: %s\n",linkm_error_msg(err));
        }
        else { 
            printf("version: %c,%c\n", recvbuf[0],recvbuf[1]);
        }
    }
    else if( cmd == CMD_BLINKM_SETADDR ) { 
        printf("setting addr from %d to %d\n", addr, arg );
        cmdbuf[0] = addr; // send to old address (or zero for broadcast)
        cmdbuf[1] = 'A';
        cmdbuf[2] = arg;  // arg is new address
        cmdbuf[3] = 0xd0;
        cmdbuf[4] = 0x0d;
        cmdbuf[5] = arg;
        err = linkm_command(dev, LINKM_CMD_I2CTRANS, 6,0,cmdbuf, NULL);
        if( err ) {
            fprintf(stderr,"error on setatt cmd: %s\n",linkm_error_msg(err));
        }
    }
    else if( cmd == CMD_BLINKM_COLOR ) {
        uint8_t r = cmdbuf[0];     // this is kind of dumb
        uint8_t g = cmdbuf[1];
        uint8_t b = cmdbuf[2];
        printf("addr %d: fading to color 0x%02x,0x%02x,0x%02x\n",addr,r,g,b);
        cmdbuf[0] = addr;
        cmdbuf[1] = 'c';
        cmdbuf[2] = r;
        cmdbuf[3] = g;
        cmdbuf[4] = b;
        err = linkm_command(dev, LINKM_CMD_I2CTRANS, 5,0, cmdbuf, NULL );
        if( err ) {
            fprintf(stderr,"error on color cmd: %s\n",linkm_error_msg(err));
        }
    }
    else if( cmd == CMD_BLINKM_RANDOM  ) {
        printf("addr %d: %d random every %d millis\n", addr,arg,millis);
        uint32_t start = stampstart();
        for( int j=0; j< arg; j++ ) {
            uint8_t r = rand() % 255;    // random() not avail on MinGWindows
            uint8_t g = rand() % 255;
            uint8_t b = rand() % 255;
            cmdbuf[0] = addr;
            cmdbuf[1] = 'n';    // go to color now
            cmdbuf[2] = r;
            cmdbuf[3] = g;
            cmdbuf[4] = b;
            err = linkm_command(dev, LINKM_CMD_I2CTRANS, 5,0, cmdbuf, NULL );
            if( err ) {
                fprintf(stderr,"error on rand cmd: %s\n",linkm_error_msg(err));
                break;
            }
            usleep(millis * 1000 ); // sleep milliseconds
        }
        stampstop(start);
    }
    else if( cmd == CMD_BLINKM_FLASH  ) {
        printf("addr %d: %d flashing every %d millis\n", addr,arg,millis);
        uint8_t r,g,b;
        if( arg == 0 ) arg = 10000;
        for( int j=0; j< arg; j++ ) {
            r = 255; g = 255; b = 255;
            cmdbuf[0] = addr;
            cmdbuf[1] = 'n';    // go to color now
            cmdbuf[2] = r;
            cmdbuf[3] = g;
            cmdbuf[4] = b;
            err = linkm_command(dev, LINKM_CMD_I2CTRANS, 5,0, cmdbuf, NULL );
            if( err ) {
                fprintf(stderr,"error on rand cmd: %s\n",linkm_error_msg(err));
                break;
            }
            usleep(millis * 1000 ); // sleep milliseconds

            r = 0; g = 0; b = 0;
            cmdbuf[0] = addr;
            cmdbuf[1] = 'n';    // go to color now
            cmdbuf[2] = r;
            cmdbuf[3] = g;
            cmdbuf[4] = b;
            err = linkm_command(dev, LINKM_CMD_I2CTRANS, 5,0, cmdbuf, NULL );
            if( err ) {
                fprintf(stderr,"error on rand cmd: %s\n",linkm_error_msg(err));
                break;
            }
            usleep(millis * 1000 ); // sleep milliseconds
        }
    }
    else if( cmd == CMD_BLINKM_PLAY  ) {
        printf("addr %d: playing script #%d\n", addr,arg);
        cmdbuf[0] = addr; 
        cmdbuf[1] = 'p';  // play script
        cmdbuf[2] = arg;
        cmdbuf[3] = 0;
        cmdbuf[4] = 0;
        if( (err = linkm_command(dev, LINKM_CMD_I2CTRANS, 5,0, cmdbuf, NULL))) 
            fprintf(stderr,"error on play: %s\n",linkm_error_msg(err));
    }
    else if( cmd == CMD_BLINKM_STOP  ) {
        printf("addr %d: stopping script\n", addr);
        cmdbuf[0] = addr; 
        cmdbuf[1] = 'o';  // stop script
        if( (err = linkm_command(dev, LINKM_CMD_I2CTRANS, 2,0, cmdbuf, NULL))) 
            fprintf(stderr,"error on stop: %s\n",linkm_error_msg(err));
    }
    else if( cmd == CMD_BLINKM_OFF  ) {
        printf("addr %d: turning off\n", addr);
        cmdbuf[0] = addr; 
        cmdbuf[1] = 'o';  // stop script
        if( (err = linkm_command(dev, LINKM_CMD_I2CTRANS, 2,0, cmdbuf, NULL))) 
            fprintf(stderr,"error on blinkmoff cmd: %s\n",linkm_error_msg(err));
        cmdbuf[1] = 'n';  // set rgb color now now
        cmdbuf[2] = cmdbuf[3] = cmdbuf[4] = 0x00;   // to zeros
        if( (err = linkm_command(dev, LINKM_CMD_I2CTRANS, 5,0, cmdbuf, NULL))) 
            fprintf(stderr,"error on blinkmoff cmd: %s\n",linkm_error_msg(err));
    }
    else if( cmd == CMD_BLINKM_ON  ) {
        printf("addr %d: turning on\n", addr);
        cmdbuf[0] = addr; 
        cmdbuf[1] = 'p';  // play script
        cmdbuf[2] = 0;
        cmdbuf[3] = 0;
        cmdbuf[4] = 0;
        if( (err = linkm_command(dev, LINKM_CMD_I2CTRANS, 5,0, cmdbuf, NULL))) 
            fprintf(stderr,"error on play: %s\n",linkm_error_msg(err));
    }
    else if( cmd == CMD_BLINKM_FADESPEED  ) {
        printf("addr %d: setting fadespeed to %d\n", addr,arg);
        cmdbuf[0] = addr; 
        cmdbuf[1] = 'f';  // set fadespeed
        cmdbuf[2] = arg;
        if( (err = linkm_command(dev, LINKM_CMD_I2CTRANS, 3,0, cmdbuf, NULL))) 
            fprintf(stderr,"error on play: %s\n",linkm_error_msg(err));
    }
    else if( cmd == CMD_BLINKM_DOWNLOAD ) { 
        if( addr == 0 ) {
            printf("Must specify non-zero address for download\n");
            goto shutdown;
        }
        printf("addr %d: downloading script %d\n", addr,arg);
        uint8_t pos = 0;
        while( pos < 49 ) {
            cmdbuf[0] = addr;
            cmdbuf[1] = 'R';    // go to color now
            cmdbuf[2] = arg;
            cmdbuf[3] = pos;
            err = linkm_command(dev, LINKM_CMD_I2CTRANS, 4,5, cmdbuf,recvbuf );
            if( err ) {
                fprintf(stderr,"error on download cmd: %s\n",
                        linkm_error_msg(err));
                break;
            }
            else { 
                hexdump("scriptline: ", recvbuf, 5);
            }
            pos++;
        }
    }
    else if( cmd == CMD_BLINKM_UPLOAD ) {
        printf("unsupported right now\n");
    }
    else if( cmd == CMD_BLINKM_READINPUTS ) {
        if( addr == 0 ) {
            printf("Must specify non-zero address for readinputs\n");
            goto shutdown;
        }
        arg = (arg==0) ? 1 : arg;
        for( uint8_t i = 0; i< arg; i++ ) {
            cmdbuf[0] = addr + i;
            cmdbuf[1] = 'i';
            err = linkm_command(dev, LINKM_CMD_I2CTRANS, 2,4, cmdbuf, recvbuf );
            if( err ) {
                fprintf(stderr,"error readinputs: %s\n",linkm_error_msg(err));
            }
            else { 
                hexdump("inputs: ", recvbuf, 5);
            }
            usleep(millis * 1000 ); // sleep milliseconds
        }
    }
    // low-level linkm cmd
    else if( cmd == CMD_LINKM_CMD ) {   // low-level linkm command
        printf("linkm command:\n");
        char cmdbyte  = cmdbuf[0];     // this is kind of dumb
        char num_send = cmdbuf[1];
        char num_recv = cmdbuf[2];
        uint8_t* cmdbufp = cmdbuf + 3;  // move along nothing to see here
        err = linkm_command(dev, cmdbyte, num_send,num_recv, cmdbufp,recvbuf);
        if( err ) {
            fprintf(stderr,"error on linkm cmd: %s\n",linkm_error_msg(err));
        }
        else {  // success
            if( num_recv ) hexdump("recv: ", recvbuf, 16);
        }
    }
    // low-level read
    else if( cmd == CMD_LINKM_READ ) {  // low-level read linkm buffer
        printf("linkm read:\n");
        memset( buffer, 0, sizeof(buffer));
        len = sizeof(buffer);
        if((err = usbhidGetReport(dev, 0, (char*)buffer, &len)) != 0) {
            fprintf(stderr, "error reading data: %s\n", linkm_error_msg(err));
        } else {
            hexdump("", buffer + 1, sizeof(buffer) - 1);
        }
    } // low-level write
    else if( cmd == CMD_LINKM_WRITE ) {  // low-level write linkm buffer
        printf("linkm write:\n");
        memset( buffer, 0, sizeof(buffer));
        memcpy( buffer+1, cmdbuf, sizeof(cmdbuf) );
        if(debug) hexdump("linkm write: ", buffer, 16); // print first bytes 
        if((err = usbhidSetReport(dev, (char*)buffer, sizeof(buffer))) != 0) {
            fprintf(stderr, "error writing data: %s\n", linkm_error_msg(err));
        }
    }

 shutdown:
    linkm_close(dev);

    return 0;
}