int loadSecondaryFPGA(void) { int status; // primary FPGA image placed onto iCAT // Tell iCAT to reload FPGA, wait for about 5 seconds IPRINT(-1,"Rebooting iCAT\n"); icat_spi_write(iCAT_RebootAddressHigh,0xc); icat_spi_write(iCAT_RebootAddressLow,0); status = rebootIcat(); if (status == -1) // failed to boot { char errmsg[256]; // do not alter format of string prior to '\n' sprintf(errmsg,"iCAT_DNA: 0x%llx \nSecondary Image failed to load.",iCAT_DNA); createFailFile("sec_imageld.fail", errmsg); errLogRet(LOGIT,debugInfo, "transferFile2Icat(): iCAT FPGA reload, failed.\n"); return -1; } else { IPRINT(-1,"Reboot Successful\n"); /* set console type and transmitter mode and p2 registers appropriately */ setupRfType(); } }
/** * forgetDevice callback of driver ops */ static void ForgetDevice(vmk_Device device) { VMK_ReturnStatus vmkStatus; struct NvmeCtrlr *ctrlr; DPRINT_TEMP("enter."); #if NVME_DEBUG_INJECT_STATE_DELAYS IPRINT("--FORGET STARTED--"); vmk_WorldSleep(NVME_DEBUG_STATE_DELAY_US); #endif vmkStatus = vmk_DeviceGetAttachedDriverData(device, (vmk_AddrCookie *)&ctrlr); if (vmkStatus != VMK_OK) { EPRINT("failed to get controller instance, 0x%x.", vmkStatus); } #if EXC_HANDLER vmkStatus = NvmeExc_SignalExceptionAndWait(ctrlr, NVME_EXCEPTION_DEVICE_REMOVED, TASKMGMT_TIMEOUT); #else NvmeCtrlr_SetMissing(ctrlr); #endif #if NVME_DEBUG_INJECT_STATE_DELAYS IPRINT("--FORGET COMPLETED--"); vmk_WorldSleep(NVME_DEBUG_STATE_DELAY_US); #endif }
/** * removeDevice callback of device ops */ static VMK_ReturnStatus DriverRemoveDevice(vmk_Device device) { VMK_ReturnStatus vmkStatus; vmk_ScsiAdapter *adapter; struct NvmeCtrlr *ctrlr; DPRINT_TEMP("enter"); vmkStatus = vmk_DeviceGetRegistrationData(device, (vmk_AddrCookie *)&adapter); if (vmkStatus != VMK_OK || adapter == NULL) { EPRINT("failed to get logical device data, 0x%x.", vmkStatus); return VMK_BAD_PARAM; } ctrlr = (struct NvmeCtrlr *)adapter->clientData; vmkStatus = vmk_DeviceUnregister(device); IPRINT("removed logical device, 0x%x.", vmkStatus); vmkStatus = NvmeScsi_Destroy(ctrlr); IPRINT("cleaned up scsi layer, 0x%x.", vmkStatus); ctrlr->ctrlOsResources.logicalDevice = NULL; return VMK_OK; }
int input_init(input_parameter *param, int plugin_no) { int i; if(pthread_mutex_init(&controls_mutex, NULL) != 0) { IPRINT("could not initialize mutex variable\n"); exit(EXIT_FAILURE); } param->argv[0] = INPUT_PLUGIN_NAME; /* show all parameters for DBG purposes */ for(i = 0; i < param->argc; i++) { DBG("argv[%d]=%s\n", i, param->argv[i]); } init_mjpg_proxy( &proxy ); reset_getopt(); if (parse_cmd_line(&proxy, param->argc, param->argv)) return 1; pglobal = param->global; IPRINT("host.............: %s\n", proxy.hostname); IPRINT("port.............: %s\n", proxy.port); return 0; }
/** * detachDevice callback of driver ops */ static VMK_ReturnStatus DetachDevice(vmk_Device device) { VMK_ReturnStatus vmkStatus; struct NvmeCtrlr *ctrlr; DPRINT_TEMP("enter."); #if NVME_DEBUG_INJECT_STATE_DELAYS IPRINT("--DETACH STARTED--"); vmk_WorldSleep(NVME_DEBUG_STATE_DELAY_US); #endif vmkStatus = vmk_DeviceGetAttachedDriverData(device, (vmk_AddrCookie *)&ctrlr); if (vmkStatus != VMK_OK) { EPRINT("failed to get controller instance, 0x%x.", vmkStatus); return vmkStatus; } /** Remote the adapter from the global list */ vmk_SpinlockLock(NVME_DRIVER_RES_LOCK); vmk_ListRemove(&ctrlr->list); vmk_SpinlockUnlock(NVME_DRIVER_RES_LOCK); /* Destroy the management handle */ NvmeMgmt_CtrlrDestroy(ctrlr); #if ALLOW_IOS_IN_QUIESCED_STATE /* * Defer putting the controller in an idle state until * device driver is dettached. */ vmkStatus = NvmeCtrlr_Stop(ctrlr); #endif /* Controller should have been quiesced before destruction. * Destruction is handled by nvme_ctrlr, which executes opposite operations * from NvmeCtrlr_Attach. */ vmkStatus = NvmeCtrlr_Detach(ctrlr); DPRINT_CTRLR("nvme controller %p destructed, 0x%x.", ctrlr, vmkStatus); /* Should never reference ctrlr after detach. */ Nvme_Free(ctrlr); #if NVME_DEBUG_INJECT_STATE_DELAYS IPRINT("--DETACH COMPLETED--"); vmk_WorldSleep(NVME_DEBUG_STATE_DELAY_US); #endif return VMK_OK; }
void* capture(void* arg) { int res; int i = 0; CameraFile* file; pthread_cleanup_push(cleanup, NULL); while(!global->stop) { unsigned long int xsize; const char* xdata; pthread_mutex_lock(&control_mutex); res = gp_file_new(&file); CAMERA_CHECK_GP(res, "gp_file_new"); res = gp_camera_capture_preview(camera, file, context); CAMERA_CHECK_GP(res, "gp_camera_capture_preview"); pthread_mutex_lock(&global->in[plugin_id].db); res = gp_file_get_data_and_size(file, &xdata, &xsize); if(xsize == 0) { if(i++ > 3) { IPRINT("Restarted too many times; giving up\n"); return NULL; } int value = 0; IPRINT("Read 0 bytes from camera; restarting it\n"); camera_set("capture", &value); sleep(3); value = 1; camera_set("capture", &value); } else i = 0; CAMERA_CHECK_GP(res, "gp_file_get_data_and_size"); memcpy(global->in[plugin_id].buf, xdata, xsize); res = gp_file_unref(file); pthread_mutex_unlock(&control_mutex); CAMERA_CHECK_GP(res, "gp_file_unref"); global->in[plugin_id].size = xsize; DBG("Read %d bytes from camera.\n", global->in[plugin_id].size); pthread_cond_broadcast(&global->in[plugin_id].db_update); pthread_mutex_unlock(&global->in[plugin_id].db); usleep(delay); } pthread_cleanup_pop(1); return NULL; }
static int split_parameters(char *parameter_string, int *argc, char **argv) { int count = 1; argv[0] = NULL; // the plugin may set it to 'INPUT_PLUGIN_NAME' if(parameter_string != NULL && strlen(parameter_string) != 0) { char *arg = NULL, *saveptr = NULL, *token = NULL; arg = strdup(parameter_string); if(strchr(arg, ' ') != NULL) { token = strtok_r(arg, " ", &saveptr); if(token != NULL) { argv[count] = strdup(token); count++; while((token = strtok_r(NULL, " ", &saveptr)) != NULL) { argv[count] = strdup(token); count++; if(count >= MAX_PLUGIN_ARGUMENTS) { IPRINT("ERROR: too many arguments to input plugin\n"); return 0; } } } } free(arg); } *argc = count; return 1; }
/** * Enable bus-mastering for the device. See PR #1303185. * * @param [in] PCI Device instance */ static VMK_ReturnStatus PciSetMaster(vmk_PCIDevice dev) { vmk_uint32 pciCmd; VMK_ReturnStatus vmkStatus; vmkStatus = vmk_PCIReadConfig(vmk_ModuleCurrentID, dev, VMK_PCI_CONFIG_ACCESS_16, NVME_PCI_CMDREG_OFFSET, &pciCmd); if (vmkStatus != VMK_OK) { EPRINT("Unable to read PCI Command register (%s)", vmk_StatusToString(vmkStatus)); return vmkStatus; } pciCmd |= NVME_PCI_CMD_BUSMASTER; vmkStatus = vmk_PCIWriteConfig(vmk_ModuleCurrentID, dev, VMK_PCI_CONFIG_ACCESS_16, NVME_PCI_CMDREG_OFFSET, pciCmd); if (vmkStatus != VMK_OK) { EPRINT("Unable to write PCI Command register (%s)", vmk_StatusToString(vmkStatus)); return vmkStatus; } IPRINT("Enabled bus-mastering on device."); return vmkStatus; }
/****************************************************************************** Description.: copy a picture from testpictures.h and signal this to all output plugins, afterwards switch to the next frame of the animation. Input Value.: arg is not used Return Value: NULL ******************************************************************************/ void *worker_thread( void *arg ) { int i=0; /* set cleanup handler to cleanup allocated ressources */ pthread_cleanup_push(worker_cleanup, NULL); while( !pglobal->stop ) { /* copy JPG picture to global buffer */ pthread_mutex_lock( &pglobal->db ); i = (i + 1) % LENGTH_OF(pics->sequence); pglobal->size = pics->sequence[i].size; memcpy(pglobal->buf, pics->sequence[i].data, pglobal->size); /* signal fresh_frame */ pthread_cond_broadcast(&pglobal->db_update); pthread_mutex_unlock( &pglobal->db ); usleep(1000*delay); } IPRINT("leaving input thread, calling cleanup function now\n"); pthread_cleanup_pop(1); return NULL; }
int run() { IPRINT("--- Starting ---\n"); while (acc < MAX_VALUE) { /* do calculations to waste time */ acc *= 17; acc++; acc /= 17; acc++; if (acc % RATE == 0) { IPRINT("acc = %"PRIuPTR"\n", acc); seL4_Yield(); } } IPRINT("*** DONE %"PRIuPTR" ***\n", acc); return 0; }
void cleanup(void *arg) { int value = 0; // TODO check to see if we have already cleaned up? IPRINT("PTP2 capture - Cleaning up\n"); camera_set("capture", &value); gp_camera_exit(camera, context); gp_camera_unref(camera); gp_context_unref(context); free(global->in[plugin_id].buf); }
/** * startDevice callback of driver ops */ static VMK_ReturnStatus StartDevice(vmk_Device device) { VMK_ReturnStatus vmkStatus; struct NvmeCtrlr *ctrlr; DPRINT_TEMP("enter."); #if NVME_DEBUG_INJECT_STATE_DELAYS IPRINT("--START STARTED--"); vmk_WorldSleep(NVME_DEBUG_STATE_DELAY_US); #endif vmkStatus = vmk_DeviceGetAttachedDriverData(device, (vmk_AddrCookie *)&ctrlr); if (vmkStatus != VMK_OK) { EPRINT("failed to get controller instance, 0x%x.", vmkStatus); return vmkStatus; } #if ALLOW_IOS_IN_QUIESCED_STATE == 0 #if EXC_HANDLER vmkStatus = NvmeExc_SignalExceptionAndWait(ctrlr, NVME_EXCEPTION_TASK_START, TASKMGMT_TIMEOUT); #else /* * When this workaround switch is active, we would be enabling the controller early. * in AttachDevice instead of StartDevice. */ vmkStatus = NvmeCtrlr_Start(ctrlr); #endif #endif #if NVME_DEBUG_INJECT_STATE_DELAYS IPRINT("--START COMPLETED--"); vmk_WorldSleep(NVME_DEBUG_STATE_DELAY_US); #endif return vmkStatus; }
/****************************************************************************** Description.: copy a picture from testpictures.h and signal this to all output plugins, afterwards switch to the next frame of the animation. Input Value.: arg is not used Return Value: NULL ******************************************************************************/ void *worker_thread(void *arg) { int i = 0; int remaining ; char * fPointer ; int outlen = 0; int vsync = 0 ; /* set cleanup handler to cleanup allocated ressources */ pthread_cleanup_push(worker_cleanup, NULL); while(!pglobal->stop) { pthread_mutex_lock(&pglobal->in[plugin_number].db); //TODO: need to iterate to get the vsync signal and then grab a full frame fifo_reset(); fifo_read(grab_buffer, 320*240*3); i = 0 ; vsync = 0 ; while(!vsync && i < (320*240*3)){ unsigned short * shortVal ; shortVal = &grab_buffer[i]; if(*shortVal == 0xAA55){ i+=2 ; if( (i < (320*240*2)) && grab_buffer[i+(320*240)] == 0x55){ vsync = 1 ; fPointer = &grab_buffer[i]; break ; } } i ++ ; } if(vsync){ DBG("Vsync found !\n"); if(!write_jpegmem_gray(fPointer, 320, 240, &pglobal->in[plugin_number].buf, &outlen, 100)){ printf("compression error !\n"); exit(EXIT_FAILURE); } pglobal->in[plugin_number].size = outlen ; /* signal fresh_frame */ pthread_cond_broadcast(&pglobal->in[plugin_number].db_update); } pthread_mutex_unlock(&pglobal->in[plugin_number].db); } IPRINT("leaving input thread, calling cleanup function now\n"); pthread_cleanup_pop(1); return NULL; }
/** * quiesceDevice callback of driver ops */ static VMK_ReturnStatus QuiesceDevice(vmk_Device device) { VMK_ReturnStatus vmkStatus; struct NvmeCtrlr *ctrlr; DPRINT_TEMP("enter."); #if NVME_DEBUG_INJECT_STATE_DELAYS IPRINT("--QUIESCE STARTED--"); vmk_WorldSleep(NVME_DEBUG_STATE_DELAY_US); #endif vmkStatus = vmk_DeviceGetAttachedDriverData(device, (vmk_AddrCookie *)&ctrlr); if (vmkStatus != VMK_OK) { EPRINT("failed to get controller instance, 0x%x.", vmkStatus); return vmkStatus; } #if EXC_HANDLER vmkStatus = NvmeExc_SignalExceptionAndWait(ctrlr, NVME_EXCEPTION_QUIESCE, TASKMGMT_TIMEOUT); #else #if ALLOW_IOS_IN_QUIESCED_STATE vmkStatus = NvmeCtrlr_Quiesce(ctrlr); #else vmkStatus = NvmeCtrlr_Stop(ctrlr); #endif #endif #if NVME_DEBUG_INJECT_STATE_DELAYS IPRINT("--QUIESCE COMPLETED--"); vmk_WorldSleep(NVME_DEBUG_STATE_DELAY_US); #endif return vmkStatus; }
/** * Initialize interrupt handler. * * We will first try MSI-X, if MSI-X allocation is not successful, then * fallback to legacy intx. * * If MSI-X is used, the actual interrupt handler is NOT registered, until * qpair construct time. * * @param [in] ctrlr controller instance */ static VMK_ReturnStatus IntrInit(struct NvmeCtrlr *ctrlr) { VMK_ReturnStatus vmkStatus; /* try msi-x first, if nvme_force_intx is not set. */ if (!nvme_force_intx) { vmkStatus = MsixSetup(ctrlr); if (vmkStatus == VMK_OK) { IPRINT("using msi-x with %d vectors.", ctrlr->ctrlOsResources.numVectors); return VMK_OK; } } /* msi-x setup failed, fallback to intx */ vmkStatus = IntxSetup(ctrlr); if (vmkStatus == VMK_OK) { IPRINT("using intx."); return VMK_OK; } EPRINT("unable to initialize interrupt, 0x%x.", vmkStatus); return vmkStatus; }
void *worker_thread(void *arg) { /* set cleanup handler to cleanup allocated resources */ pthread_cleanup_push(worker_cleanup, NULL); proxy.on_image_received = on_image_received; proxy.should_stop = & pglobal->stop; connect_and_stream(&proxy); IPRINT("leaving input thread, calling cleanup function now\n"); pthread_cleanup_pop(1); return NULL; }
/****************************************************************************** Description.: Input Value.: Return Value: ******************************************************************************/ void cam_cleanup(void *arg) { static unsigned char first_run = 1; context *pcontext = (context*) arg; pglobal = pcontext->pglobal; if (!first_run) { DBG("already cleaned up ressources\n"); return; } first_run = 0; IPRINT("cleaning up ressources allocated by input thread\n"); close_v4l2(pcontext->videoIn); if (pcontext->videoIn->tmpbuffer != NULL) free(pcontext->videoIn->tmpbuffer); if (pcontext->videoIn != NULL) free(pcontext->videoIn); if (pglobal->in[pcontext->id].buf != NULL) free(pglobal->in[pcontext->id].buf); }
/****************************************************************************** Description.: Input Value.: Return Value: ******************************************************************************/ void cam_cleanup(void *arg) { static unsigned char first_run=1; if ( !first_run ) { DBG("already cleaned up ressources\n"); return; } first_run = 0; IPRINT("cleaning up ressources allocated by input thread\n"); /* restore behaviour of the LED to auto */ input_cmd(IN_CMD_LED_AUTO, 0); close_v4l2(videoIn); if (videoIn->tmpbuffer != NULL) free(videoIn->tmpbuffer); if (videoIn != NULL) free(videoIn); if (pglobal->buf != NULL) free(pglobal->buf); }
/****************************************************************************** Description.: parse input parameters Input Value.: param contains the command line string and a pointer to globals Return Value: 0 if everything is ok ******************************************************************************/ int input_init(input_parameter *param, int plugin_no) { int i; if(pthread_mutex_init(&controls_mutex, NULL) != 0) { IPRINT("could not initialize mutex variable\n"); exit(EXIT_FAILURE); } param->argv[0] = INPUT_PLUGIN_NAME; /* show all parameters for DBG purposes */ for(i = 0; i < param->argc; i++) { DBG("argv[%d]=%s\n", i, param->argv[i]); } pglobal = param->global; return 0; }
/****************************************************************************** Description.: Input Value.: Return Value: ******************************************************************************/ void cam_cleanup(void *arg) { int i; static unsigned char first_run = 1; context *activecam, *pcontext = arg; pglobal = pcontext->pglobal; if(!first_run) { DBG("already cleaned up ressources\n"); return; } first_run = 0; IPRINT("cleaning up ressources allocated by input thread\n"); for(i = 0; i < mcnt; i++) { activecam = &cams[pcontext->id + i]; close_v4l2(activecam->videoIn); if(activecam->videoIn->tmpbuffer != NULL) free(activecam->videoIn->tmpbuffer); if(activecam->videoIn != NULL) free(activecam->videoIn); } if(pglobal->in[pcontext->id].buf != NULL) free(pglobal->in[pcontext->id].buf); }
/****************************************************************************** Description.: this thread worker monitors the ctrl socket for commands Input Value.: unused Return Value: unused, always NULL ******************************************************************************/ void *ctrl_thread(void *arg) { struct sockaddr_in addr, cli_addr; socklen_t clen; char recvBuff[1024]; int id = (int)arg, sd = 0, connfd = 0, cam; context *pcontext = &cams[id]; pglobal = pcontext->pglobal; sd = socket(AF_INET, SOCK_STREAM, 0); if(sd < 0) { perror("ctrl socket"); return NULL; } bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(port); if(bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0) { perror("ctrl socket bind"); return NULL; } IPRINT("Listening on port.: %i\n", port); listen(sd, 5); while(!pglobal->stop) { connfd = accept(sd, (struct sockaddr*)&cli_addr, &clen); if(read(connfd, recvBuff, 1024) > 0) { if((strncmp(recvBuff, ";camera(", 8) == 0) && (sscanf(recvBuff, ";camera(%d);", &cam) == 1) && ((cam >= 0)&&(cam < mcnt))) { camera = cam; } } } return NULL; }
int input_cmd(in_cmd_type cmd, int value) { int res=0; static int pan=0; static int tilt=0; static int pan_tilt_valid=-1; const int one_degree = ONE_DEGREE; IPRINT("received command %d (value: %d) for input plugin\n", cmd, value); if ( cmd != IN_CMD_RESET_PAN_TILT_NO_MUTEX ) pthread_mutex_lock( &controls_mutex ); DBG("pan: %d, tilt: %d, valid: %d\n", pan, tilt, pan_tilt_valid); switch (cmd) { case IN_CMD_HELLO: fprintf(stderr, "Hello from input plugin\n"); break; case IN_CMD_RESET_PAN_TILT: case IN_CMD_RESET_PAN_TILT_NO_MUTEX: DBG("about to set all pan/tilt to default position\n"); DBG("uvcPanTilt(videoIn, 0, 0, 3) != 0 )\n"); pan_tilt_valid = 1; pan = tilt = 0; break; case IN_CMD_PAN_SET: DBG("set pan to %d\n", value); if ( pan_tilt_valid != 1 ) input_cmd(IN_CMD_RESET_PAN_TILT_NO_MUTEX, 0); /* limit pan-value to min and max */ value = MIN(MAX(value*one_degree, MIN_PAN), MAX_PAN); /* calculate the relative degrees to move to the desired absolute pan-value */ if( (res = value - pan) == 0 ) { /* do not move if this would mean to move by 0 degrees */ res = pan; break; } /* move it */ pan = value; DBG("res = uvcPanTilt(videoIn, %d, 0, 0)\n", res); DBG("pan: %d\n", pan); break; case IN_CMD_PAN_PLUS: DBG("pan +\n"); if ( pan_tilt_valid != 1 ) input_cmd(IN_CMD_RESET_PAN_TILT_NO_MUTEX, 0); if ( (MAX_PAN) > (pan+one_degree) ) { pan += one_degree; DBG("res = uvcPanTilt(videoIn, one_degree, 0, 0)\n"); } DBG("pan: %d\n", pan); break; case IN_CMD_PAN_MINUS: DBG("pan -\n"); if ( pan_tilt_valid != 1 ) input_cmd(IN_CMD_RESET_PAN_TILT_NO_MUTEX, 0); if ( (MIN_PAN) < (pan-one_degree) ) { pan -= one_degree; DBG("res = uvcPanTilt(videoIn, -one_degree, 0, 0)\n"); } DBG("pan: %d\n", pan); break; default: DBG("some other value, ignored\n"); } if ( cmd != IN_CMD_RESET_PAN_TILT_NO_MUTEX ) pthread_mutex_unlock( &controls_mutex ); return res; }
/****************************************************************************** Description.: parse input parameters Input Value.: param contains the command line string and a pointer to globals Return Value: 0 if everything is ok ******************************************************************************/ int input_init(input_parameter *param) { char *argv[MAX_ARGUMENTS]={NULL}; int argc=1, i; pics = &picture_lookup[1]; if( pthread_mutex_init(&controls_mutex, NULL) != 0 ) { IPRINT("could not initialize mutex variable\n"); exit(EXIT_FAILURE); } /* convert the single parameter-string to an array of strings */ argv[0] = INPUT_PLUGIN_NAME; if ( param->parameter_string != NULL && strlen(param->parameter_string) != 0 ) { char *arg=NULL, *saveptr=NULL, *token=NULL; arg=(char *)strdup(param->parameter_string); if ( strchr(arg, ' ') != NULL ) { token=strtok_r(arg, " ", &saveptr); if ( token != NULL ) { argv[argc] = strdup(token); argc++; while ( (token=strtok_r(NULL, " ", &saveptr)) != NULL ) { argv[argc] = strdup(token); argc++; if (argc >= MAX_ARGUMENTS) { IPRINT("ERROR: too many arguments to input plugin\n"); return 1; } } } } } /* show all parameters for DBG purposes */ for (i=0; i<argc; i++) { DBG("argv[%d]=%s\n", i, argv[i]); } reset_getopt(); while(1) { int option_index = 0, c=0; static struct option long_options[] = \ { {"h", no_argument, 0, 0}, {"help", no_argument, 0, 0}, {"d", required_argument, 0, 0}, {"delay", required_argument, 0, 0}, {"r", required_argument, 0, 0}, {"resolution", required_argument, 0, 0}, {0, 0, 0, 0} }; c = getopt_long_only(argc, argv, "", long_options, &option_index); /* no more options to parse */ if (c == -1) break; /* unrecognized option */ if (c == '?'){ help(); return 1; } switch (option_index) { /* h, help */ case 0: case 1: DBG("case 0,1\n"); help(); return 1; break; /* d, delay */ case 2: case 3: DBG("case 2,3\n"); delay = atoi(optarg); break; /* r, resolution */ case 4: case 5: DBG("case 4,5\n"); for ( i=0; i < LENGTH_OF(picture_lookup); i++ ) { if ( strcmp(picture_lookup[i].resolution, optarg) == 0 ) { pics = &picture_lookup[i]; break; } } break; default: DBG("default case\n"); help(); return 1; } } pglobal = param->global; IPRINT("delay.............: %i\n", delay); IPRINT("resolution........: %s\n", pics->resolution); return 0; }
/****************************************************************************** Description.: parse input parameters Input Value.: param contains the command line string and a pointer to globals Return Value: 0 if everything is ok ******************************************************************************/ int input_init(input_parameter *param, int plugin_no) { int i; pics = &picture_lookup[1]; if(pthread_mutex_init(&controls_mutex, NULL) != 0) { IPRINT("could not initialize mutex variable\n"); exit(EXIT_FAILURE); } param->argv[0] = INPUT_PLUGIN_NAME; /* show all parameters for DBG purposes */ for(i = 0; i < param->argc; i++) { DBG("argv[%d]=%s\n", i, param->argv[i]); } reset_getopt(); while(1) { int option_index = 0, c = 0; static struct option long_options[] = { {"h", no_argument, 0, 0 }, {"help", no_argument, 0, 0}, {"d", required_argument, 0, 0}, {"delay", required_argument, 0, 0}, {"r", required_argument, 0, 0}, {"resolution", required_argument, 0, 0}, {0, 0, 0, 0} }; c = getopt_long_only(param->argc, param->argv, "", long_options, &option_index); /* no more options to parse */ if(c == -1) break; /* unrecognized option */ if(c == '?') { help(); return 1; } switch(option_index) { /* h, help */ case 0: case 1: DBG("case 0,1\n"); help(); return 1; break; /* d, delay */ case 2: case 3: DBG("case 2,3\n"); delay = atoi(optarg); break; /* r, resolution */ case 4: case 5: DBG("case 4,5\n"); for(i = 0; i < LENGTH_OF(picture_lookup); i++) { if(strcmp(picture_lookup[i].resolution, optarg) == 0) { pics = &picture_lookup[i]; break; } } break; default: DBG("default case\n"); help(); return 1; } } pglobal = param->global; IPRINT("delay.............: %i\n", delay); IPRINT("resolution........: %s\n", pics->resolution); return 0; }
/** * Module entry point * * Initialize moduel-wide resources and register driver */ int init_module(void) { VMK_ReturnStatus vmkStatus; Nvme_LogNoHandle("Loading driver %s.", NVME_DRIVER_IDENT); Nvme_ValidateModuleParams(); #if VMKAPIDDK_VERSION >= 650 VMK_ASSERT(sizeof(NvmeIoRequest) <= vmk_ScsiCmdGetDriverFrameSize()); #endif /* Always initialize heap in the first place. */ vmkStatus = HeapCreate(); if (vmkStatus != VMK_OK) { Nvme_LogNoHandle("failed to create driver heap, 0x%x.", vmkStatus); return vmkStatus; } /* Initialize log components, and set default log level based on * module parameter. */ vmkStatus = LogHandleCreate(nvme_log_level); if (vmkStatus != VMK_OK) { Nvme_LogNoHandle("failed to create log handle, 0x%x.", vmkStatus); goto destroy_heap; } /* Initialize mem pool. mem pool is used for allocating large * physically contiguous memory. */ vmkStatus = MemPoolCreate(); if (vmkStatus != VMK_OK) { EPRINT("failed to create mem pool, 0x%x.", vmkStatus); goto destroy_log; } /** Initialize global management handle */ vmkStatus = NvmeMgmt_GlobalInitialize(); if (vmkStatus != VMK_OK) { EPRINT("failed to initialize global management interface, 0x%x.", vmkStatus); goto destroy_mpool; } /** Initialize global lock */ vmkStatus = OsLib_LockCreateNoRank(NVME_GLOBAL_LOCK_NAME, &NVME_DRIVER_RES_LOCK); if (vmkStatus != VMK_OK) { EPRINT("failed to initialize global lock, 0x%x.", vmkStatus); goto destroy_mgmt; } /** Initialize adapter list */ vmk_ListInit(&NVME_DRIVER_RES_ADAPTERLIST); /* TODO: Do we have other global resources to initialize here? */ /* Finally, register driver */ vmkStatus = NvmeDriver_Register(); if (vmkStatus != VMK_OK) { EPRINT("failed to register driver, 0x%x.", vmkStatus); goto destroy_lock; } IPRINT("module initialized successfully."); return 0; destroy_lock: OsLib_LockDestroy(&NVME_DRIVER_RES_LOCK); destroy_mgmt: NvmeMgmt_GlobalDestroy(); destroy_mpool: MemPoolDestroy(); destroy_log: LogHandleDestroy(); destroy_heap: HeapDestroy(); return vmkStatus; }
/****************************************************************************** Description.: This function ializes the plugin. It parses the commandline- parameter and stores the default and parsed values in the appropriate variables. Input Value.: param contains among others the command-line string Return Value: 0 if everything is fine 1 if "--help" was triggered, in this case the calling programm should stop running and leave. ******************************************************************************/ int input_init(input_parameter *param, int id) { char *dev = "/dev/video0", *s; int width = 640, height = 480, fps = 5, format = V4L2_PIX_FMT_MJPEG, i; /* initialize the mutes variable */ if(pthread_mutex_init(&cams[id].controls_mutex, NULL) != 0) { IPRINT("could not initialize mutex variable\n"); exit(EXIT_FAILURE); } param->argv[0] = INPUT_PLUGIN_NAME; /* show all parameters for DBG purposes */ for(i = 0; i < param->argc; i++) { DBG("argv[%d]=%s\n", i, param->argv[i]); } /* parse the parameters */ reset_getopt(); while(1) { int option_index = 0, c = 0; static struct option long_options[] = { {"h", no_argument, 0, 0 }, {"help", no_argument, 0, 0}, {"d", required_argument, 0, 0}, {"device", required_argument, 0, 0}, {"r", required_argument, 0, 0}, {"resolution", required_argument, 0, 0}, {"f", required_argument, 0, 0}, {"fps", required_argument, 0, 0}, {"y", no_argument, 0, 0}, {"yuv", no_argument, 0, 0}, {"q", required_argument, 0, 0}, {"quality", required_argument, 0, 0}, {"m", required_argument, 0, 0}, {"minimum_size", required_argument, 0, 0}, {"n", no_argument, 0, 0}, {"no_dynctrl", no_argument, 0, 0}, {"l", required_argument, 0, 0}, {"led", required_argument, 0, 0}, {"s", no_argument, 0, 0}, {"stop", no_argument, 0, 0}, {0, 0, 0, 0} }; /* parsing all parameters according to the list above is sufficent */ c = getopt_long_only(param->argc, param->argv, "", long_options, &option_index); /* no more options to parse */ if(c == -1) break; /* unrecognized option */ if(c == '?') { help(); return 1; } /* dispatch the given options */ switch(option_index) { /* h, help */ case 0: case 1: DBG("case 0,1\n"); help(); return 1; break; /* d, device */ case 2: case 3: DBG("case 2,3\n"); dev = strdup(optarg); break; /* r, resolution */ case 4: case 5: DBG("case 4,5\n"); width = -1; height = -1; /* try to find the resolution in lookup table "resolutions" */ for(i = 0; i < LENGTH_OF(resolutions); i++) { if(strcmp(resolutions[i].string, optarg) == 0) { width = resolutions[i].width; height = resolutions[i].height; } } /* done if width and height were set */ if(width != -1 && height != -1) break; /* parse value as decimal value */ width = strtol(optarg, &s, 10); height = strtol(s + 1, NULL, 10); break; /* f, fps */ case 6: case 7: DBG("case 6,7\n"); fps = atoi(optarg); break; /* y, yuv */ case 8: case 9: DBG("case 8,9\n"); format = V4L2_PIX_FMT_YUYV; break; /* q, quality */ case 10: case 11: DBG("case 10,11\n"); format = V4L2_PIX_FMT_YUYV; gquality = MIN(MAX(atoi(optarg), 0), 100); break; /* m, minimum_size */ case 12: case 13: DBG("case 12,13\n"); minimum_size = MAX(atoi(optarg), 0); break; /* n, no_dynctrl */ case 14: case 15: DBG("case 14,15\n"); dynctrls = 0; break; /* l, led */ case 16: case 17:/* DBG("case 16,17\n"); if ( strcmp("on", optarg) == 0 ) { led = IN_CMD_LED_ON; } else if ( strcmp("off", optarg) == 0 ) { led = IN_CMD_LED_OFF; } else if ( strcmp("auto", optarg) == 0 ) { led = IN_CMD_LED_AUTO; } else if ( strcmp("blink", optarg) == 0 ) { led = IN_CMD_LED_BLINK; }*/ break; /* s, stop */ case 18: case 19: DBG("case 18,19\n"); stop_camera = 1; break; default: DBG("default case\n"); help(); return 1; } } DBG("input id: %d\n", id); cams[id].id = id; cams[id].pglobal = param->global; /* allocate webcam datastructure */ cams[id].videoIn = malloc(sizeof(struct vdIn)); if(cams[id].videoIn == NULL) { IPRINT("not enough memory for videoIn\n"); exit(EXIT_FAILURE); } memset(cams[id].videoIn, 0, sizeof(struct vdIn)); /* display the parsed values */ IPRINT("Using V4L2 device.: %s\n", dev); IPRINT("Desired Resolution: %i x %i\n", width, height); IPRINT("Frames Per Second.: %i\n", fps); IPRINT("Format............: %s\n", (format == V4L2_PIX_FMT_YUYV) ? "YUV" : "MJPEG"); if(format == V4L2_PIX_FMT_YUYV) IPRINT("JPEG Quality......: %d\n", gquality); IPRINT("Stop camera feat..: %d\n", stop_camera); DBG("vdIn pn: %d\n", id); /* open video device and prepare data structure */ if(init_videoIn(cams[id].videoIn, dev, width, height, fps, format, 1, cams[id].pglobal, id) < 0) { IPRINT("init_VideoIn failed\n"); closelog(); exit(EXIT_FAILURE); } /* * recent linux-uvc driver (revision > ~#125) requires to use dynctrls * for pan/tilt/focus/... * dynctrls must get initialized */ if(dynctrls) initDynCtrls(cams[id].videoIn->fd); enumerateControls(cams[id].videoIn, cams[id].pglobal, id); // enumerate V4L2 controls after UVC extended mapping return 0; }
/****************************************************************************** Description.: this thread worker grabs a frame and copies it to the global buffer Input Value.: unused Return Value: unused, always NULL ******************************************************************************/ void *cam_thread(void *arg) { context *pcontext = arg; pglobal = pcontext->pglobal; /* set cleanup handler to cleanup allocated ressources */ pthread_cleanup_push(cam_cleanup, pcontext); while(!pglobal->stop) { while(pcontext->videoIn->streamingState == STREAMING_PAUSED) { usleep(1); // maybe not the best way so FIXME } if(stop_camera == 1) { /* check active outputs */ pthread_mutex_lock(&pglobal->in[pcontext->id].out); if(pglobal->in[pcontext->id].num_outs == 0) { /* stop camera */ uvcStopGrab(pcontext->videoIn); /* wait for active outputs */ pthread_cond_wait(&pglobal->in[pcontext->id].out_update, &pglobal->in[pcontext->id].out); } /* allow others to access the global buffer again */ pthread_mutex_unlock(&pglobal->in[pcontext->id].out); } /* grab a frame */ if(uvcGrab(pcontext->videoIn) < 0) { IPRINT("Error grabbing frames\n"); exit(EXIT_FAILURE); } DBG("received frame of size: %d from plugin: %d\n", pcontext->videoIn->buf.bytesused, pcontext->id); /* * Workaround for broken, corrupted frames: * Under low light conditions corrupted frames may get captured. * The good thing is such frames are quite small compared to the regular pictures. * For example a VGA (640x480) webcam picture is normally >= 8kByte large, * corrupted frames are smaller. */ if(pcontext->videoIn->buf.bytesused < minimum_size) { DBG("dropping too small frame, assuming it as broken\n"); continue; } /* copy JPG picture to global buffer */ pthread_mutex_lock(&pglobal->in[pcontext->id].db); /* * If capturing in YUV mode convert to JPEG now. * This compression requires many CPU cycles, so try to avoid YUV format. * Getting JPEGs straight from the webcam, is one of the major advantages of * Linux-UVC compatible devices. */ if(pcontext->videoIn->formatIn == V4L2_PIX_FMT_YUYV) { DBG("compressing frame from input: %d\n", (int)pcontext->id); pglobal->in[pcontext->id].size = compress_yuyv_to_jpeg(pcontext->videoIn, pglobal->in[pcontext->id].buf, pcontext->videoIn->framesizeIn, gquality); } else { DBG("copying frame from input: %d\n", (int)pcontext->id); pglobal->in[pcontext->id].size = memcpy_picture(pglobal->in[pcontext->id].buf, pcontext->videoIn->tmpbuffer, pcontext->videoIn->buf.bytesused); } #if 0 /* motion detection can be done just by comparing the picture size, but it is not very accurate!! */ if((prev_size - global->size)*(prev_size - global->size) > 4 * 1024 * 1024) { DBG("motion detected (delta: %d kB)\n", (prev_size - global->size) / 1024); } prev_size = global->size; #endif /* copy this frame's timestamp to user space */ pglobal->in[pcontext->id].timestamp = pcontext->videoIn->buf.timestamp; /* signal fresh_frame */ pthread_cond_broadcast(&pglobal->in[pcontext->id].db_update); pthread_mutex_unlock(&pglobal->in[pcontext->id].db); /* only use usleep if the fps is below 5, otherwise the overhead is too long */ if(pcontext->videoIn->fps < 5) { DBG("waiting for next frame for %d us\n", 1000 * 1000 / pcontext->videoIn->fps); usleep(1000 * 1000 / pcontext->videoIn->fps); } else { DBG("waiting for next frame\n"); } } DBG("leaving input thread, calling cleanup function now\n"); pthread_cleanup_pop(1); return NULL; }
/****************************************************************************** Description.: this thread worker grabs a frame and copies it to the global buffer Input Value.: unused Return Value: unused, always NULL ******************************************************************************/ void *cam_thread( void *arg ) { /* set cleanup handler to cleanup allocated ressources */ pthread_cleanup_push(cam_cleanup, NULL); while( !pglobal->stop ) { /* grab a frame */ if( uvcGrab(videoIn) < 0 ) { IPRINT("Error grabbing frames\n"); exit(EXIT_FAILURE); } DBG("received frame of size: %d\n", videoIn->buf.bytesused); /* * Workaround for broken, corrupted frames: * Under low light conditions corrupted frames may get captured. * The good thing is such frames are quite small compared to the regular pictures. * For example a VGA (640x480) webcam picture is normally >= 8kByte large, * corrupted frames are smaller. */ if ( videoIn->buf.bytesused < minimum_size ) { DBG("dropping too small frame, assuming it as broken\n"); continue; } /* copy JPG picture to global buffer */ pthread_mutex_lock( &pglobal->db ); /* * If capturing in YUV mode convert to JPEG now. * This compression requires many CPU cycles, so try to avoid YUV format. * Getting JPEGs straight from the webcam, is one of the major advantages of * Linux-UVC compatible devices. */ if (videoIn->formatIn != V4L2_PIX_FMT_MJPEG ) { DBG("compressing frame\n"); pglobal->size = compress_yuyv_to_jpeg(videoIn, pglobal->buf, videoIn->framesizeIn, gquality,videoIn->fmt.fmt.pix.pixelformat); } else { DBG("copying frame\n"); pglobal->size = memcpy_picture(pglobal->buf, videoIn->tmpbuffer, videoIn->buf.bytesused); } #if 0 /* motion detection can be done just by comparing the picture size, but it is not very accurate!! */ if ( (prev_size - global->size)*(prev_size - global->size) > 4*1024*1024 ) { DBG("motion detected (delta: %d kB)\n", (prev_size - global->size) / 1024); } prev_size = global->size; #endif /* signal fresh_frame */ pthread_cond_broadcast(&pglobal->db_update); pthread_mutex_unlock( &pglobal->db ); DBG("waiting for next frame\n"); /* only use usleep if the fps is below 5, otherwise the overhead is too long */ if ( videoIn->fps < 5 ) { usleep(1000*1000/videoIn->fps); } } DBG("leaving input thread, calling cleanup function now\n"); pthread_cleanup_pop(1); return NULL; }
/* * transfer an iCAT file from the controller's flash file system to the iCAT ISF * e.g. icat configuration files: icat_config00.tbl, icat_config01.tbl, etc.. * GMB */ int transferFile2Icat( char *filename ) { char md5sig[32 + 1]; char md5sig2[32 + 1]; char name[36], md5[36]; int result, ret, di; unsigned long size, nSize, sizeBytes, len; int tableIndex,dataOffset,status,OverWriteYes;; char *xferfileBuffer; char *pFileExtType; OverWriteYes = 1; size = getFFSize(filename); IPRINT2(-1,"transferFile2Icat: File: '%s', Bytes: %ld\n",filename,size); if (size < 1) /* return file not present */ return(0); // need this extra length (headersize) for the readback verification step xferfileBuffer = (char*) malloc(size + getISFFileHeaderSize() + 4); if ( (xferfileBuffer == NULL) ) { errLogRet(LOGIT,debugInfo, " ****** System Memory Malloc failed\n"); return(-1); } /* transfer FFS into buffer */ result = cpFF2Buf(filename,xferfileBuffer,&nSize); if (result < 0) { errLogRet(LOGIT,debugInfo, " ****** Read from Flash FileSystem failed\n"); free(xferfileBuffer); return(-1); } /* ---------------------------*/ /* calc MD5 checksum signiture */ calcMd5(xferfileBuffer, nSize, md5sig); IPRINT3(1,"transferFile2Icat: file: '%s', nSize: %ld, md5: '%s'\n", filename,nSize, md5sig); // determine if this file is a FPGA bitstream *.bit or configuration file *.tbl pFileExtType = (char*) strrchr(filename,'.') + 1; IPRINT1(1,"transferFile2Icat: File Ext Type: '%s'\n",pFileExtType); tableIndex = extractIndex(filename); IPRINT1(1,"transferFile2Icat: tableIndex; %ld\n", tableIndex); // ======================================================================= // Configuration table transfers // if ( (strcmp("tbl",pFileExtType) == 0) ) { // ======================================================================= // read conf file header from iCAT flash // If the file already exists on icat ISFlash don't re-copy to ISFlash tableIndex = getConfigTableByName(filename); // no longer use index encoded in name, just find it. IPRINT2(-11,"transferFile2Icat: filename: '%s', tableIndex: %d\n", filename, tableIndex); if (tableIndex != -1) // -1 means didn't find this named file { result = readConfigTableHeader(tableIndex, name, md5, (int*) &sizeBytes); if (result != -1) // -1 == invalid table index, no file present { IPRINT2(1,"transferFile2Icat: 2cp md5: '%s'\n\t\t\t\t\t\t vs present md5: '%s'\n", md5sig,md5); ret = strcmp(md5sig, md5); if (ret == 0) { IPRINT(-1,"transferFile2Icat: File already Present on Icat ISFlash\n\n"); free(xferfileBuffer); return(0); } } } // ======================================================================= result = writeIsfFile(filename, md5sig, nSize, xferfileBuffer, OverWriteYes); memset(xferfileBuffer,0,nSize); // now read it back and confirm proper writing to iCAT ISF len = nSize; // relocate file, there is no guarentee that same index was used. tableIndex = getConfigTableByName(filename); // no longer use index encoded in name, just find it. IPRINT2(-11,"transferFile2Icat: filename: '%s', tableIndex: %d\n", filename, tableIndex); result = readConfigTable(tableIndex, name, md5, (UINT32*) &len, xferfileBuffer, (int*) &dataOffset); IPRINT4(-12,"transferFile2Icat() name: '%s', md5: '%s', len: %ld, dataOffset: %ld\n",name,md5,len,dataOffset); } // ======================================================================= // iCAT FPAG file transfers // else if ( (strcmp("bit",pFileExtType) == 0) && ((tableIndex >= -1) && (tableIndex <= 1)) ) { IPRINT3(1,"transferFile2Icat() bitstream: '%s', md5: '%s', len: %ld \n", filename,md5sig,nSize); // ======================================================================= // read conf file header from iCAT flash // If file already exist on icat ISFlash don't re-copy to ISFlash if (tableIndex == -1) tableIndex = 0; result = readIcatFPGAHeader(tableIndex,name, md5, (int*) &sizeBytes); if (result != -1) // -1 == invalid table index, no file present { IPRINT2(1,"transferFile2Icat: 2cp md5: '%s'\n\t\t\t\t\t\t vs preset md5: '%s'\n", md5sig,md5); ret = strcmp(md5sig, md5); if (ret == 0) { IPRINT(-1,"transferFile2Icat: File already Present on Icat ISFlash\n\n"); free(xferfileBuffer); return(0); } } // ======================================================================= // transfer FPGA bit-stream result = writeIcatFPGA(tableIndex, filename, md5sig, nSize, xferfileBuffer); memset(xferfileBuffer,0,nSize); // now read it back confirm proper writing to iCAT ISF len = nSize; result = readIcatFPGA(tableIndex, name, md5, (UINT32*) &len, xferfileBuffer); dataOffset = 0; } /* calc MD5 checksum signiture */ calcMd5((xferfileBuffer + dataOffset), len, md5sig2); IPRINT3(1,"transferFile2Icat: file: '%s', written/read md5: '%s'\n\t\t\t\t\t\t\t vs '%s'\n", filename, md5sig, md5sig2); ret = strcmp(md5sig, md5sig2); if (ret != 0) { char errmsg[256]; // failure on Primary or Seconadary iCAT FPGA image, must mark failure via a small file if ( (strcmp("bit",pFileExtType) == 0) ) { // do not alter format of string prior to '\n' sprintf(errmsg,"iCAT_DNA: 0x%llx \nImage failed to copy.",iCAT_DNA); if ( (tableIndex >= -1) && (tableIndex <= 0) ) { createFailFile("pri_imagecp.fail", errmsg); // deleting primary image is probably un-necessary , it's just not going to boot anymore } else { createFailFile("sec_imagecp.fail", errmsg); isffpgadel(); // deleted secondary image } errLogRet(LOGIT,debugInfo, "transferFile2Icat(): '%s' iCAT FPGA image copy, failed.\n",filename); } else if ( (strcmp("tbl",pFileExtType) == 0) && ((tableIndex >= 0) && (tableIndex < 6)) ) { // maybe moot since we don't copy tables any more to the ISF flash isftbldel(tableIndex); // delete table that failed to copy } errLogRet(LOGIT,debugInfo, "transferFile2Icat(): ****** ERROR: MD5 Checksum do NOT match\n"); errLogRet(LOGIT,debugInfo, "transferFile2Icat(): True MD5 - '%s'\n",md5sig); errLogRet(LOGIT,debugInfo, "transferFile2Icat(): Calc MD5 - '%s'\n",md5sig2); free(xferfileBuffer); return(-1); } IPRINT(-1,"Transfer Succesful\n\n"); free(xferfileBuffer); return 0; }
/****************************************************************************** Description.: This function initializes the plugin. It parses the commandline- parameter and stores the default and parsed values in the appropriate variables. Input Value.: param contains among others the command-line string Return Value: 0 if everything is fine 1 if "--help" was triggered, in this case the calling programm should stop running and leave. ******************************************************************************/ int input_init(input_parameter *param) { char *argv[MAX_ARGUMENTS]={NULL}, *dev = "/dev/video0", *s; int argc=1, width=640, height=480, fps=5, format=V4L2_PIX_FMT_MJPEG, i; in_cmd_type led = IN_CMD_LED_AUTO; /* initialize the mutes variable */ if( pthread_mutex_init(&controls_mutex, NULL) != 0 ) { IPRINT("could not initialize mutex variable\n"); exit(EXIT_FAILURE); } /* convert the single parameter-string to an array of strings */ argv[0] = INPUT_PLUGIN_NAME; if ( param->parameter_string != NULL && strlen(param->parameter_string) != 0 ) { char *arg=NULL, *saveptr=NULL, *token=NULL; arg=(char *)strdup(param->parameter_string); if ( strchr(arg, ' ') != NULL ) { token=strtok_r(arg, " ", &saveptr); if ( token != NULL ) { argv[argc] = strdup(token); argc++; while ( (token=strtok_r(NULL, " ", &saveptr)) != NULL ) { argv[argc] = strdup(token); argc++; if (argc >= MAX_ARGUMENTS) { IPRINT("ERROR: too many arguments to input plugin\n"); return 1; } } } } } /* show all parameters for DBG purposes */ for (i=0; i<argc; i++) { DBG("argv[%d]=%s\n", i, argv[i]); } /* parse the parameters */ reset_getopt(); while(1) { int option_index = 0, c=0; static struct option long_options[] = \ { {"h", no_argument, 0, 0}, {"help", no_argument, 0, 0}, {"d", required_argument, 0, 0}, {"device", required_argument, 0, 0}, {"r", required_argument, 0, 0}, {"resolution", required_argument, 0, 0}, {"f", required_argument, 0, 0}, {"fps", required_argument, 0, 0}, {"y", no_argument, 0, 0}, {"yuv", no_argument, 0, 0}, {"q", required_argument, 0, 0}, {"quality", required_argument, 0, 0}, {"m", required_argument, 0, 0}, {"minimum_size", required_argument, 0, 0}, {"n", no_argument, 0, 0}, {"no_dynctrl", no_argument, 0, 0}, {"l", required_argument, 0, 0}, {"led", required_argument, 0, 0}, {0, 0, 0, 0} }; /* parsing all parameters according to the list above is sufficent */ c = getopt_long_only(argc, argv, "", long_options, &option_index); /* no more options to parse */ if (c == -1) break; /* unrecognized option */ if (c == '?'){ help(); return 1; } /* dispatch the given options */ switch (option_index) { /* h, help */ case 0: case 1: DBG("case 0,1\n"); help(); return 1; break; /* d, device */ case 2: case 3: DBG("case 2,3\n"); dev = strdup(optarg); break; /* r, resolution */ case 4: case 5: DBG("case 4,5\n"); width = -1; height = -1; /* try to find the resolution in lookup table "resolutions" */ for ( i=0; i < LENGTH_OF(resolutions); i++ ) { if ( strcmp(resolutions[i].string, optarg) == 0 ) { width = resolutions[i].width; height = resolutions[i].height; } } /* done if width and height were set */ if(width != -1 && height != -1) break; /* parse value as decimal value */ width = strtol(optarg, &s, 10); height = strtol(s+1, NULL, 10); break; /* f, fps */ case 6: case 7: DBG("case 6,7\n"); fps=atoi(optarg); break; /* y, yuv */ case 8: case 9: DBG("case 8,9\n"); format = V4L2_PIX_FMT_YUYV; break; /* q, quality */ case 10: case 11: DBG("case 10,11\n"); format = V4L2_PIX_FMT_YUYV; gquality = MIN(MAX(atoi(optarg), 0), 100); break; /* m, minimum_size */ case 12: case 13: DBG("case 12,13\n"); minimum_size = MAX(atoi(optarg), 0); break; /* n, no_dynctrl */ case 14: case 15: DBG("case 14,15\n"); dynctrls = 0; break; /* l, led */ case 16: case 17: DBG("case 16,17\n"); if ( strcmp("on", optarg) == 0 ) { led = IN_CMD_LED_ON; } else if ( strcmp("off", optarg) == 0 ) { led = IN_CMD_LED_OFF; } else if ( strcmp("auto", optarg) == 0 ) { led = IN_CMD_LED_AUTO; } else if ( strcmp("blink", optarg) == 0 ) { led = IN_CMD_LED_BLINK; } break; default: DBG("default case\n"); help(); return 1; } } /* keep a pointer to the global variables */ pglobal = param->global; /* allocate webcam datastructure */ videoIn = malloc(sizeof(struct vdIn)); if ( videoIn == NULL ) { IPRINT("not enough memory for videoIn\n"); exit(EXIT_FAILURE); } memset(videoIn, 0, sizeof(struct vdIn)); /* display the parsed values */ IPRINT("Using V4L2 device.: %s\n", dev); IPRINT("Desired Resolution: %i x %i\n", width, height); IPRINT("Frames Per Second.: %i\n", fps); IPRINT("Format............: %s\n", (format==V4L2_PIX_FMT_YUYV)?"YUV":"MJPEG"); if ( format == V4L2_PIX_FMT_YUYV ) IPRINT("JPEG Quality......: %d\n", gquality); /* open video device and prepare data structure */ if (init_videoIn(videoIn, dev, width, height, fps, format, 1) < 0) { IPRINT("init_VideoIn failed\n"); closelog(); exit(EXIT_FAILURE); } /* * recent linux-uvc driver (revision > ~#125) requires to use dynctrls * for pan/tilt/focus/... * dynctrls must get initialized */ if (dynctrls) initDynCtrls(videoIn->fd); /* * switch the LED according to the command line parameters (if any) */ input_cmd(led, 0); return 0; }