Пример #1
2
int main() {
	Five arr[50000];
	int idx = 0;
	FILE * fp;
	char * line = NULL;
	size_t len = 0;
	size_t read;
	int begin = stampstart();
	fp = fopen("50000.csv", "r");
	if (fp == NULL) {
		exit(EXIT_FAILURE);
	}
	char* buf = (char*)malloc(sizeof(char)*128);
	while((read = getline(&line, &len, fp)) != -1) {
		Five five;
		five.firstname = (char*)malloc(sizeof(char)*128);
		five.lastname = (char*)malloc(sizeof(char)*128);
		five.company = (char*)malloc(sizeof(char)*128);
		five.road = (char*)malloc(sizeof(char)*128);
		five.city = (char*)malloc(sizeof(char)*128);
		five.state = (char*)malloc(sizeof(char)*128);
		five.stateaka = (char*)malloc(sizeof(char)*128);
		five.telefon = (char*)malloc(sizeof(char)*128);
		five.fax = (char*)malloc(sizeof(char)*128);
		five.email = (char*)malloc(sizeof(char)*128);
		five.web = (char*)malloc(sizeof(char)*128);
		int r = sscanf(line, "%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],\"%[^,],%[^,],%[^,],%[^,],%[^,]\n",
			five.firstname, five.lastname, five.company, five.road, five.city, five.state, five.stateaka, 
			buf, five.telefon, five.fax, five.email, five.web);
		five.zip = atoi(buf);
		five.firstname = five.firstname+1;
		five.firstname[strlen(five.firstname)-1] = '\0';
		five.lastname = five.lastname+1;
		five.lastname[strlen(five.lastname)-1] = '\0';
		five.company = five.company+1;
		five.company[strlen(five.company)-1] = '\0';
		five.road = five.road+1;
		five.road[strlen(five.road)-1] = '\0';
		five.city = five.city+1;
		five.city[strlen(five.city)-1] = '\0';
		five.state = five.state+1;
		five.state[strlen(five.state)-1] = '\0';
		five.stateaka = five.stateaka+1;
		five.stateaka[strlen(five.stateaka)-1] = '\0';
		five.telefon = five.telefon+1;
		five.telefon[strlen(five.telefon)-1] = '\0';
		five.fax = five.fax+1;
		five.fax[strlen(five.fax)-1] = '\0';
		five.email = five.email+1;
		five.email[strlen(five.email)-1] = '\0';
		five.web = five.web+1;
		five.web[strlen(five.web)-1] = '\0';
		if(r != 12) {
			printf("%d %s\n", r, line);
			return 1;
		}

		arr[idx++] = five;
	}
	free(buf);
	if (line) {
		free(line);
	}
	//printf("csv time %d\n", stampstop(begin));
	begin = stampstart();

	sqlite3 *db;
	int ret = sqlite3_open("testtable.db",&db);
	assert(ret == SQLITE_OK);
	//gettimeofday(&start, NULL);

	ret = sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL);
	assert(ret == SQLITE_OK);

	const char* istmt  = "INSERT INTO Person(Firstname, Lastname, Company, Address, County, City, State, Zip, PhoneWork, PhonePrivat, Mail, Www) Values(?,?,?,?,?,?,?,?,?,?,?,?);";
	//const char* istmt2  = "INSERT INTO Person(Firstname, Lastname, Company, Address, County, City, State, Zip, PhoneWork, PhonePrivat, Mail, Www) Values(%s,%s,%s,%s,%s,%s,%s,%d,%s,%s,%s,%s);\n";
	sqlite3_stmt* stmt;
	const char* ozTest;
	ret = sqlite3_prepare_v2(db, istmt, strlen(istmt), &stmt, &ozTest);
	assert(ret == SQLITE_OK);
	for(int i = 0; i < idx; ++i) {
		int j = 1;
		/*printf(istmt2, arr[i].firstname, arr[i].lastname, 
			arr[i].company, arr[i].road, arr[i].city, arr[i].state, arr[i].stateaka, arr[i].zip, 
			arr[i].telefon, arr[i].fax, arr[i].email, arr[i].web
		);*/
		sqlite3_bind_text(stmt, j++, arr[i].firstname, strlen(arr[i].firstname), NULL);
		sqlite3_bind_text(stmt, j++, arr[i].lastname, strlen(arr[i].lastname), NULL);
		sqlite3_bind_text(stmt, j++, arr[i].company, strlen(arr[i].company), NULL);
		sqlite3_bind_text(stmt, j++, arr[i].road, strlen(arr[i].road), NULL);
		sqlite3_bind_text(stmt, j++, arr[i].city, strlen(arr[i].city), NULL);
		sqlite3_bind_text(stmt, j++, arr[i].state, strlen(arr[i].state), NULL);
		sqlite3_bind_text(stmt, j++, arr[i].stateaka, strlen(arr[i].stateaka), NULL);
		sqlite3_bind_int(stmt, j++, arr[i].zip);
		sqlite3_bind_text(stmt, j++, arr[i].telefon, strlen(arr[i].telefon), NULL);
		sqlite3_bind_text(stmt, j++, arr[i].fax, strlen(arr[i].fax), NULL);
		sqlite3_bind_text(stmt, j++, arr[i].email, strlen(arr[i].email), NULL);
		sqlite3_bind_text(stmt, j++, arr[i].web, strlen(arr[i].web), NULL);
		assert(j == 13);
		ret = sqlite3_step(stmt);
		if(ret != SQLITE_DONE) {
			printf("%d \"%s\"\n", ret, sqlite3_errmsg(db));
			printf("%s %s %s %s %s %s %s %d %s %s %s %s\n", arr[i].firstname, arr[i].lastname, 
				arr[i].company, arr[i].road, arr[i].city, arr[i].state, arr[i].stateaka, arr[i].zip, 
				arr[i].telefon, arr[i].fax, arr[i].email, arr[i].web
			);
			return 1;
		}
		sqlite3_reset(stmt);
	}
	sqlite3_exec(db, "END TRANSACTION;", NULL, NULL, NULL);
	printf("%d\n", stampstop(begin));
	sqlite3_close(db);
	return 0;
}
Пример #2
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
Пример #3
0
void runVideoLoop()
{
	int iFramesDecoded = 0, pOutBufferVid_size=0;

	//int cnt=1;
	uint8_t *packetBufferVid;
	packetBufferVid = (uint8_t *) av_malloc(100000 * sizeof(uint8_t));  // alloc output buffer for encoded datastream
	
	int frame_id=0, framerate_drop=1; // these are used to drop camera frames if needed, set to 1 for no drops
	while(av_read_frame(pFormatCtxVidDec, &packetVidDec)>=0) {
		if( StopExecution == true ) {
			cout << "Child Thread Stop Execution Requested; terminating..." << endl;
			break;
		}
		start=stampstart();
		
		// Only drop frames with TCP/H264
		if ( (cliOpts.transport==USE_TCP) && (cliOpts.vcodec==USE_H264) ) {
			frame_id++;
			if (frame_id>204800000)
				frame_id=0;
		
			if ((frame_id % framerate_drop) != 0)
				packetVidDec.stream_index = -1;
		}
		
		// Is this a packetVidDec from the video stream?
		if(packetVidDec.stream_index == iVideoStream) {
			
			  start = stampstart();
			
			// Decode video frame
			if (cliOpts.verbose >= 2) {
				cout << "Decode new packetVidDec" << "\n";
			}
			avcodec_decode_video2(pCodecCtxVidDec, pFrameDec, &iFrameFinished, &packetVidDec);
			
			// Did we get a video frame?
			if(iFrameFinished) {
				if (cliOpts.verbose >= 2) {
					cout << "Got a new video frame: " << iFramesDecoded << "\n";
				}
				
				// Convert the image from its native format to RGB to save as ppm
				if (swsC_RGB == NULL) 
				{
					if (cliOpts.verbose >= 2) 
					{
						cerr << "Setting up conversion context for RGB:\n ";
						cerr << " Input type: " << pCodecCtxVidDec->width << "x" << pCodecCtxVidDec->height << " in "; 
						PIX_FMT_LOOKUP(pCodecCtxVidDec->pix_fmt); 
						cerr << " format\n";
						cerr << "  Output type: " << pCodecCtxVidEnc->width << "x" << pCodecCtxVidEnc->height << " in "; 
						PIX_FMT_LOOKUP(PIX_FMT_RGB24); 
						cerr << " format\n";
					}
					
					// Setup image converter...  Convert from what we get to RGB24 to save as image
					swsC_RGB = sws_getContext(	pCodecCtxVidDec->width,	//	Source width
												pCodecCtxVidDec->height,	//	Source height
												pCodecCtxVidDec->pix_fmt, //	Source format
												pCodecCtxVidDec->width,	//	Dest width
												pCodecCtxVidDec->height,	//	Dest height
												PIX_FMT_RGB24,		//	Dest format
												SWS_FAST_BILINEAR,	//	Transform Type (choose from SWS FLAGS)
												NULL, NULL, NULL);	//	Filters & Pointer Setup (NULL chooses defaults for last 3 options)
				}
				
				if (swsC_RGB == NULL) {	fail("sws_getContext RGB", "Couldn't setup a format conversion.", TRUE); }
				if (cliOpts.verbose >= 2) { cout << "Calling sws_scale for colourspace conversion RGB\n"; }
				
				swsR_RGB = sws_scale( swsC_RGB,									//	SwsContext - Setup for scaling
									(const uint8_t* const*)	pFrameDec->data,	//	Source frame data (cast to required type)
									pFrameDec->linesize,						//	Source frame stride
									0,										//	Source frame slice width (raster, so no width slicing)
									pCodecCtxVidDec->height,						//	Source frame slice height
									pFrameRGB->data,						//	Dest frame data
									pFrameRGB->linesize);					//	Dest frame stride

				if (swsR_RGB <= 0) { fail("sws_scale RGB", "Couldn't determine output slice size.", TRUE); }
				
				// Convert the image from its native format to YUV420P for encoder
				if (swsC_YUV == NULL) {
					if (cliOpts.verbose >= 2) {
						cerr << "Setting up conversion context for YUV:\n "; 
						cerr << " Input type: " << pCodecCtxVidDec->width << "x" << pCodecCtxVidDec->height << " in ";
						PIX_FMT_LOOKUP(pCodecCtxVidDec->pix_fmt); 
						cerr << " format\n";
						cerr << "  Output type: " << pCodecCtxVidEnc->width << "x" << pCodecCtxVidEnc->height << " in "; 
						PIX_FMT_LOOKUP(pCodecCtxVidEnc->pix_fmt); 
						cerr << " format\n";
					}
					
					// Setup image converter...  Convert from what we get to YUV420P for Encoder
					swsC_YUV = sws_getContext(	pCodecCtxVidDec->width,	//	Source width
												pCodecCtxVidDec->height,	//	Source height
												pCodecCtxVidDec->pix_fmt, //	Source format
												pCodecCtxVidDec->width,	//	Dest width
												pCodecCtxVidDec->height,	//	Dest height
												PIX_FMT_YUV420P,		//	Dest format
												SWS_FAST_BILINEAR,	//	Transform Type (choose from SWS FLAGS)
												NULL, NULL, NULL);	//	Filters & Pointer Setup (NULL chooses defaults for last 3 options)
				}
				
				if (swsC_YUV == NULL) {	fail("sws_getContext YUV", "Couldn't setup a format conversion.", TRUE); }
				if (cliOpts.verbose >= 2) { cout << "Calling sws_scale for colourspace conversion YUV" << "\n"; }
				
				swsR_YUV = sws_scale( swsC_YUV,									//	SwsContext - Setup for scaling
									(const uint8_t* const*)	pFrameDec->data,	//	Source frame data (cast to required type)
									pFrameDec->linesize,						//	Source frame stride
									0,											//	Source frame slice width (raster, so no width slicing)
									pCodecCtxVidDec->height,					//	Source frame slice height
									pFrameEnc->data,							//	Dest frame data
									pFrameEnc->linesize);						//	Dest frame stride

				if (swsR_YUV <= 0) {
					fail("sws_scale YUV", "Couldn't determine output slice size.", TRUE);
				}
				
				// Save frame to disk PPM ( if the user wants it, and if it's the nth frame )
				if ((cliOpts.saveframes > 0) && (iFramesDecoded%cliOpts.saveframes == 0)) {
					if (cliOpts.verbose >= 2) { cout << "Saving this frame, as requested." << "\n"; }
					SaveFrame(pFrameRGB, pCodecCtxVidDec->width, pCodecCtxVidDec->height, iFramesDecoded);
				}
				
				// Encode the video
				if (cliOpts.verbose >= 2) {
					cout << "Calling avcodec_encode_video(): ";
				}
				
				iEncodedBytes = avcodec_encode_video(pCodecCtxVidEnc, packetBufferVid, iOutBufferSize, pFrameEnc);
				
				if (iEncodedBytes > 0) {
					
					if(cliOpts.networkport > 0) {	
						stop = stampstop(start);
						double dt=stop-start;
						sum=sum+dt;
						if(counter==10) {
							cout<<"The average delay is(/10 frames): "<<sum/10<<" ms"<<endl;
							sum=0;
							counter=0;
						}
						counter++;
						
						while(slp) {
							sleep(1);
						}
						
						if ( (cliOpts.transport==USE_UDP) && (cliOpts.vcodec==USE_MJPEG) ) {
							// Fragmentation code: This is used to separate packets into chunks of predefined size MAX_FLUSH_BUFF_SIZE
							// Currently commented out for H.264 as it is still in testing phase and it is not needed under normal circumstances
							// (i.e. the codec produces small enough packets)
						  
							for (int i=pOutBufferVid_size; i<pOutBufferVid_size+iEncodedBytes; i++) {
								if (pOutBufferVid_size==0) {
									pOutBufferVid[i+1]=packetBufferVid[i];
								} else {
									pOutBufferVid[i]=packetBufferVid[i-pOutBufferVid_size];
								}
							}  // FOR
							
							if (pOutBufferVid_size==0) {
								pOutBufferVid_size+=iEncodedBytes+1; // this includes the 1st byte that is the dependencies byte
							} else {
								pOutBufferVid_size+=iEncodedBytes;
							} //IF/ELSE
							
							if (pOutBufferVid_size>MIN_FLUSH_BUFF_SIZE) {
								cout<<"\n Going to deal with a packet of size: "<<pOutBufferVid_size<<endl;
								if (pOutBufferVid_size>MAX_FLUSH_BUFF_SIZE) {
									// first chunk here
									pOutBufferVid[0]=0; // chunk num
									// if we requested networking, do it.
									if (!cliOpts.savevideo) {
										addFrame((char *)(pOutBufferVid), MAX_FLUSH_BUFF_SIZE, cliOpts.transport);
									} else {
										unsigned char *tmp;
										tmp=(pOutBufferVid+1);
										fwrite(tmp, sizeof(uint8_t), MAX_FLUSH_BUFF_SIZE-1, pOutputVideo);
									}
							
									for (int i=1; i<pOutBufferVid_size/MAX_FLUSH_BUFF_SIZE; i++) { // all intermediate chunks
										pOutBufferVid[i*MAX_FLUSH_BUFF_SIZE-1]=i; // chunk num
								
										if (!cliOpts.savevideo) {
											addFrame((char *)(pOutBufferVid+i*MAX_FLUSH_BUFF_SIZE-1), MAX_FLUSH_BUFF_SIZE+1, cliOpts.transport);
										} else {
											unsigned char *tmp;
											tmp=(pOutBufferVid+i*MAX_FLUSH_BUFF_SIZE);
											fwrite(tmp, sizeof(uint8_t), MAX_FLUSH_BUFF_SIZE, pOutputVideo);
								  
										}
									}
									if (pOutBufferVid_size%MAX_FLUSH_BUFF_SIZE>0) { // last chunk
										pOutBufferVid[(pOutBufferVid_size/MAX_FLUSH_BUFF_SIZE)*MAX_FLUSH_BUFF_SIZE-1]=127; // no dependencies
										// if we requested networking, do it.
										if (!cliOpts.savevideo) {
											addFrame((char *)(pOutBufferVid+(pOutBufferVid_size/MAX_FLUSH_BUFF_SIZE)*MAX_FLUSH_BUFF_SIZE-1), (pOutBufferVid_size%MAX_FLUSH_BUFF_SIZE)+1, cliOpts.transport);
										} else {
											unsigned char *tmp;
											tmp=(pOutBufferVid+(pOutBufferVid_size/MAX_FLUSH_BUFF_SIZE)*MAX_FLUSH_BUFF_SIZE);
											fwrite(tmp, sizeof(uint8_t), (pOutBufferVid_size%MAX_FLUSH_BUFF_SIZE), pOutputVideo);
										}								
										pOutBufferVid_size=0;
									}
								} else {
									pOutBufferVid[0]=127; // no dependencies
									if (!cliOpts.savevideo) {
										addFrame((char *)pOutBufferVid, pOutBufferVid_size, cliOpts.transport);
									} else {
										fwrite(packetBufferVid, sizeof(uint8_t), iEncodedBytes, pOutputVideo);
									}
									pOutBufferVid_size=0;
								}
							}
						
						//Sleep so that file is not read all to memory instantly
						if ((strcmp(cliOpts.mode, "FILE")==0)||(strcmp(cliOpts.mode, "FIL")==0)) {
							usleep(33000); //Sleep for 33 miliseconds
						}
						
						if (cliOpts.verbose >= 2) {
							cout << "Network ";
						}

						} else {
							// don't use fragmentation code if it's not MJPEG/UDP.
							addFrame((char *)(packetBufferVid), iEncodedBytes, cliOpts.transport);
						}
					}
					if (cliOpts.savevideo) {
						// if we want video saved to file
						// Write first iEncodedBytes of pOutBufferVid (buffer) to pOutputVideo (file handle)
			
						fwrite(packetBufferVid, sizeof(uint8_t), iEncodedBytes, test);
					 
						if (cliOpts.verbose >= 2) {
							cout << "File ";
						}
					} else {
						if (cliOpts.verbose >= 2) {
						cout << "Buffer ";
					}
				}
				  
				if (cliOpts.verbose >= 2) {
					printf("%06d bytes\n", iEncodedBytes);
				}
				
				fprintf(pStatisticsFile, "%d,%d\n", iFramesDecoded, iEncodedBytes);
			} else {
				if (cliOpts.verbose >= 2) { cout << "Codec buffered frame" << "\n"; }
			}

			if (iEncodedBytes < 0) {
				AVERROR_LOOKUP(iEncodedBytes);
				fail("avcodec_encode_video()", "Encoder returned fault", FALSE);
			}
			
			if (cliOpts.verbose >= 2) {
				fflush(stdout);
			}  // flush stdout if we're pritning to it
			
			// Stop after cliOpts.maxframes frames
			if ((cliOpts.maxframes > 0) && (iFramesDecoded >= cliOpts.maxframes)) {
				break;
			}
			
			iFramesDecoded++;
		}
	}
	// Free the packetVidDec that was allocated by av_read_frame
	av_free_packet(&packetVidDec);
	}
	free(packetBufferVid);
	cout << "Child Thread Execution Haulted!" << endl;
}
Пример #4
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;
}