/* Biopod control program * Programmed by: Micah Villmow * Version: 0.5 * Purpose: To send various commands and tests to the APC Biopod to test out * the biopod driver and to reverse engineer the various byte patterns to * activate the device. * Copyright 2005 - Micah Villmow - All rights reserved */ #include #include #include #include #include #include #include #include #include #include #include "biopod.h" #define MAX_REGISTERS 38 #define REG_OFFET 128 #define BUF_SIZE 8192 #define LAST_REG MAX_REGISTERS #define Argument_is_out_of_argument_range(high,low,value) (value > high || value < low) #define test_set_range(high,low,device,i,value)\ { \ if(Argument_is_out_of_argument_range(high,low,value)){ \ fprintf(stderr,"Invalid range for %d %d: value " \ "must be between %d and %d\n",i,value,high,low); \ exit(EXIT_FAILURE); \ } \ device->range[i][0] = high; \ device->range[i][1] = low; \ } #define test_device(S) \ { \ struct stat st; \ if(-1 == stat(S, &st)) { \ fprintf(stderr,"Cannot identify '%s' : %d, %s\n", \ S,errno, strerror(errno)); \ exit(EXIT_FAILURE); \ } \ \ if(!S_ISCHR(st.st_mode)){ \ fprintf(stderr,"%s is no device\n",S); \ exit(EXIT_FAILURE); \ } \ } #define send_to_device(device,i) \ { \ sprintf(device->buffer,"%c%c",device->number[i], \ device->values[i]); \ if(write(device->device_fd,&device->buffer,strlen(device->buffer)) == -1) \ fprintf(stderr,"error in writing to device! %s", \ strerror(errno)); \ } #define repeat_ioctl_if_int(device,command,i) \ { \ int r; \ if(!Argument_is_out_of_argument_range(device->range[i][0], \ device->range[i][1],device->values[i])){ \ do{ \ r = ioctl(device->device_fd,command,device->values[i]); \ }while(r == -1 && EINTR == errno); \ } \ } #define INPUT_REG(dev, num) \ { #dev, required_argument, NULL, num } typedef struct device_param { int values[MAX_REGISTERS + 1]; int number[MAX_REGISTERS+ 1]; int range[MAX_REGISTERS+1][2]; int device_fd; int use_ioctl[MAX_REGISTERS+1]; char buffer[BUF_SIZE]; char *file; } device; void convert_to_string(device *biopod); static void clear_registers(device *); static void short_help(char *filename); static void long_help(char *filename); static device *switch_statement(device *,char *, int ); static device *send_device(device *,int); static const char short_options [] = "s:c:r:d:n:a:hxg:m:e:"; static const struct option long_options [] = { { "expert-help", required_argument, NULL, 0 }, { "sensor-gain-one", required_argument, NULL, 1 }, { "sensor-gain-two", required_argument, NULL, 2 }, { "sensor-gain", required_argument, NULL, 3 }, { "set-carrier-null", required_argument, NULL, 4 }, { "carrier-null", required_argument, NULL, 5 }, { "ad-ref-hi", required_argument, NULL, 6 }, { "ad-ref-low", required_argument, NULL, 7 }, { "detect-finger", required_argument, NULL, 8 }, { "measure-freq", required_argument, NULL, 9 }, { "measure-drive", required_argument, NULL, 10}, { "detect-freq", required_argument, NULL, 11}, { "detect-drive", required_argument, NULL, 12}, { "max-res", required_argument, NULL, 13}, { "column-scan-rate", required_argument, NULL, 14}, { "detect-capacitor", required_argument, NULL, 15}, { "detect-resistor", required_argument, NULL, 16}, { "z-matrix", required_argument, NULL, 17}, { "demodulation-phase", required_argument, NULL, 18}, { "chip-type", required_argument, NULL, 19}, { "start-row-scan", required_argument, NULL, 20}, { "stop-row-scan", required_argument, NULL, 21}, { "drive-boost", required_argument, NULL, 22}, { "normalize-phase", required_argument, NULL, 23}, { "disable-image-data", required_argument, NULL, 24}, { "row-histogram", required_argument, NULL, 25}, { "master-reset", required_argument, NULL, 26}, { "single-scan", required_argument, NULL, 27}, { "read-register", required_argument, NULL, 28}, { "continuous-scan", required_argument, NULL, 29}, { "async-register-update",required_argument, NULL, 30}, { "excitation-bias", required_argument, NULL, 31}, { "detect-debound-delay",required_argument, NULL, 32}, { "integration-time", required_argument, NULL, 33}, { "sensor-amp-bias", required_argument, NULL, 34}, { "z-matrix-vpatt", required_argument, NULL, 35}, { "z-matrix-hpatt", required_argument, NULL, 36}, { "demod-phase-one", required_argument, NULL, 37}, { "demod-phase-two", required_argument, NULL, 38}, { "z-matrix-power", required_argument, NULL, 39}, { "sample-current-bias",required_argument, NULL, 40}, { "analog-current-bias",required_argument, NULL, 41}, { "start-col-num", required_argument, NULL, 42}, { "end-col-num", required_argument, NULL, 43}, { "data-format", required_argument, NULL, 44}, { "binary-threshhold", required_argument, NULL, 45}, { "test-registers", required_argument, NULL, 46}, { "full-histogram", required_argument, NULL, 47}, { "enable-histogram", required_argument, NULL, 48}, { "led-one", required_argument, NULL, 49}, { "led-two", required_argument, NULL, 50}, { "usb-reset", required_argument, NULL, 51}, { "led-four", required_argument, NULL, 52}, { "z-matrix-doubler", required_argument, NULL, 53}, { "challenge-word-one", required_argument, NULL, 54}, { "challenge-word-two", required_argument, NULL, 55}, { "challenge-word-three",required_argument, NULL, 56}, { "challenge-word-four",required_argument, NULL, 57}, { "challenge-word-five",required_argument, NULL, 58}, { "square-wave", required_argument, NULL, 59}, { "force-finger-detect",required_argument, NULL, 60}, { "sync-serial-int", required_argument, NULL, 61}, { "channel-bias", required_argument, NULL, 62}, { "image-data-bit-4", required_argument, NULL, 63}, INPUT_REG(reg-A1,64), INPUT_REG(reg-A7,65), INPUT_REG(reg-A9,66), INPUT_REG(reg-B4,67), INPUT_REG(reg-BB,68), INPUT_REG(reg-83,69), { "device", required_argument, NULL, 'd'}, { 0, 0, 0, 0} }; int main(int argc, char *argv[]) { device *biopod; int i; biopod = calloc(1,sizeof *biopod); clear_registers(biopod); if(argc == 1){ short_help(argv[0]); perror("no arguments specified!\n"); exit(EXIT_FAILURE); } for(;;) { int index; int c = getopt_long(argc, argv, short_options, long_options, &index); if(c == -1) break; else if(c == ':') { short_help(argv[0]); perror(":"); exit(EXIT_FAILURE); } else if(c == '?') { fprintf(stderr,"c= %d",c); short_help(argv[0]); perror("?"); exit(EXIT_FAILURE); } biopod = switch_statement(biopod,argv[0],c); } biopod->device_fd = open(biopod->file,O_WRONLY); if(biopod->device_fd == -1) { fprintf(stderr,"Device cannot be opened! %s\n",strerror(errno)); exit(EXIT_FAILURE); } for(i = 0; i < MAX_REGISTERS; i++) send_device(biopod,i); convert_to_string(biopod); close(biopod->device_fd); free(biopod); return 1; } static void clear_registers(device *biopod) { int i = 0; for(i = 0; i < MAX_REGISTERS; i++) { biopod->values[i] = 0; } } static void short_help(char *filename) { fprintf(stderr, "Usage: %s [options]\n\n" "Options:\n" "\t-d | --device name Biometric device name [/dev/biopod0]\n" "\t-e Enable scanning of the device(0,1)\n" "\t-s | --single-scan Set a single scan(0/1)\n" "\t-c | --continuous-scan Set continuous scanning(0/1)\n" "\t-r | --read-register Read register values(0/1)\n" "\t-n | --set-carrier-null Set the carrier null bit(0/1)\n" "\t-a | --async-register-update Update the registers asynchronously(0/1)\n",filename); fprintf(stderr, "\t-h show this help menu\n" "\t-m | --master-reset reset the device to defaults\n" "\t-x | --expert-help show the expert help\n" "\t-g | --enablehistogram enable the histogram imaging(0/1)\n" ""); } static void long_help(char *filename) { fprintf(stderr,"%snot yet supported!\n",filename); } static device *switch_statement(device *biopod, char *argv, int c) { int value; if(c != 'x' && c != 'h' && c != 0) value = atoi(optarg); switch(c) { case 'x': case 0: long_help(argv); break; case 1: test_set_range(3,0,biopod,14,value) biopod->values[14] |= value; biopod->number[14] = 0x8E; break; case 2: test_set_range(3,0,biopod,14,value) biopod->values[14] |= (value << 4) ; biopod->number[14] = 0x8E; break; case 3: test_set_range(1,0,biopod,c,value) fprintf(stderr,"not supported!\n"); break; case 4: test_set_range(15,0,biopod,16,value) biopod->values[16] |= value; biopod->number[16] = 0x90; break; case 'n': case 5: test_set_range(1,0,biopod,16,value) biopod->values[16] |= (value << 4); biopod->number[16] = 0x90; break; case 6: test_set_range(127,0,biopod,17,value) biopod->values[17] |= value; biopod->number[17] = 0x91; break; case 7: test_set_range(127,0,biopod,18,value) biopod->values[18] |= value; biopod->number[18] = 0x92; break; case 8: test_set_range(1,0,biopod,27,value) biopod->values[27] |= value; biopod->number[27] = 0x9B; break; case 9: test_set_range(7,0,biopod,10,value) biopod->values[10] |= value; biopod->number[10] = 0x8A; break; case 10: test_set_range(3,0,biopod,9,value) biopod->values[9] |= value; biopod->number[9] = 0x89; break; case 11: test_set_range(7,0,biopod,7,value) biopod->values[7] |= value; biopod->number[7] = 0x87; break; case 12: test_set_range(3,0,biopod,6,value) biopod->values[6] |= value; biopod->number[6] = 0x86; break; case 13: test_set_range(1,0,biopod,LAST_REG,value) biopod->values[LAST_REG] |= value; biopod->number[LAST_REG] = 0x00; break; case 14: test_set_range(7,0,biopod,8,value) biopod->values[8] |= value; biopod->number[8] = 0x88; break; case 15: test_set_range(127,0,biopod,5,value) biopod->values[5] |= value; biopod->number[5] = 0x85; break; case 16: test_set_range(7,0,biopod,4,value) biopod->values[4] |= value; biopod->number[4] = 0x84; break; case 17: test_set_range(1,0,biopod,11,value) biopod->values[11] |= (value << 4); biopod->number[11] = 0x8B; break; case 18: test_set_range(127,0,biopod,12,value) biopod->values[12] |= value; biopod->number[12] = 0x8C; break; case 19: test_set_range(127,0,biopod,29,value) biopod->values[29] |= value; biopod->number[29] = 0x9D; break; case 20: test_set_range(15,0,biopod,19,value) biopod->values[19] |= value; biopod->number[19] = 0x93; break; case 21: test_set_range(15,0,biopod,20,value) biopod->values[20] |= value; biopod->number[20] = 0x94; break; case 22: test_set_range(1,0,biopod,2,value) biopod->values[2] |= (value << 4); biopod->number[2] = 0x82; break; case 23: test_set_range(1,0,biopod,LAST_REG,value) biopod->values[LAST_REG] |= value; biopod->number[LAST_REG] = 0xFF; break; case 24: test_set_range(1,0,biopod,24,value) biopod->values[24] |= value; biopod->number[24] = 0x98; break; case 25: test_set_range(1,0,biopod,24,value) biopod->values[24] |= (value << 2); biopod->number[24] = 0x98; break; case 'm': biopod->use_ioctl[0] = 1; case 26: test_set_range(1,0,biopod,0,value) biopod->values[0] |= (value); biopod->number[0] = 0x80; break; case 's': biopod->use_ioctl[1] = 1; case 27: test_set_range(1,0,biopod,1,value) biopod->values[1] |= (value << 2); biopod->number[1] = 0x81; break; case 'r': biopod->use_ioctl[28] = 1; case 28: test_set_range(1,0,biopod,1,value) biopod->values[1] |= (value << 1); biopod->number[1] = 0x81; break; case 'c': biopod->use_ioctl[29] = 1; case 29: test_set_range(1,0,biopod,1,value) biopod->values[1] |= (value); biopod->number[1] = 0x81; break; case 'a': case 30: test_set_range(1,0,biopod,0,value) biopod->values[0] |= (value << 2); biopod->number[0] = 0x80; break; case 31: test_set_range(1,0,biopod,LAST_REG,value) biopod->values[LAST_REG] |= value ; biopod->number[LAST_REG] = 0x00; break; case 32: test_set_range(3,0,biopod,3,value) biopod->values[3] |= (value << 4); biopod->number[3] = 0x83; break; case 33: test_set_range(1,0,biopod,LAST_REG,value) biopod->values[LAST_REG] |= value; biopod->number[LAST_REG] = 0x00; break; case 34: test_set_range(1,0,biopod,LAST_REG,value) biopod->values[LAST_REG] |= value; biopod->number[LAST_REG] = 0x00; break; case 35: test_set_range(3,0,biopod,11,value) biopod->values[11] |= (value << 2); biopod->number[11] = 0x8B; break; case 36: test_set_range(3,0,biopod,11,value) biopod->values[11] |= (value); biopod->number[11] = 0x8B; break; case 37: test_set_range(127,0,biopod,13,value) biopod->values[13] |= value; biopod->number[13] = 0x8D; break; case 38: test_set_range(127,0,biopod,12,value) biopod->values[12] |= value; biopod->number[12] = 0x8C; break; case 39: test_set_range(1,0,biopod,LAST_REG,value) biopod->values[LAST_REG] |= value; biopod->number[LAST_REG] = 0x00; break; case 40: test_set_range(1,0,biopod,LAST_REG,value) biopod->number[LAST_REG] = 0x00; biopod->values[LAST_REG] |= value; break; case 41: test_set_range(1,0,biopod,LAST_REG,value) biopod->values[LAST_REG] |= value; biopod->number[LAST_REG] = 0x00; break; case 42: test_set_range(127,0,biopod,21,value) biopod->values[21] |= value; biopod->number[21] = 0x95; break; case 43: test_set_range(127,0,biopod,22,value) biopod->values[22] |= value; biopod->number[22] = 0x96; break; case 44: test_set_range(15,0,biopod,23,value) biopod->values[23] |= value; biopod->number[23] = 0x97; break; case 45: test_set_range(15,0,biopod,23,value) biopod->values[23] |= value; biopod->number[23] = 0x97; break; case 46: test_set_range(1,0,biopod,24,value) biopod->number[24] = 0x98; biopod->values[24] |= (value << 5); break; case 47: test_set_range(1,0,biopod,24,value) biopod->number[24] = 0x98; biopod->values[24] |= (value << 3); break; case 'g': biopod->use_ioctl[24] = 1; case 48: test_set_range(1,0,biopod,24,value) biopod->number[24] = 0x98; biopod->values[24] |= (value << 1); break; case 49: test_set_range(1,0,biopod,25,value) biopod->values[25] |= value; biopod->number[25] = 0x99; break; case 50: test_set_range(1,0,biopod,25,value) biopod->values[25] |= (value << 1); biopod->number[25] = 0x99; break; case 51: test_set_range(1,0,biopod,25,value) biopod->values[25] |= (value << 2); biopod->number[25] = 0x99; break; case 52: test_set_range(1,0,biopod,25,value) biopod->values[25] |= (value << 3); biopod->number[25] = 0x99; break; case 53: test_set_range(1,0,biopod,11,value) biopod->values[11] |= (value << 5); biopod->number[11] = 0x8B; break; case 54: test_set_range(127,0,biopod,27,value) biopod->values[27] |= value; biopod->number[27] = 0x9b; break; case 55: test_set_range(127,0,biopod,28,value) biopod->values[28] |= value; biopod->number[28] = 0x9C; break; case 56: test_set_range(127,0,biopod,29,value) biopod->number[29] = 0x9D; biopod->values[29] |= value; break; case 57: test_set_range(127,0,biopod,30,value) biopod->number[30] = 0x9E; biopod->values[30] |= value; break; case 58: test_set_range(127,0,biopod,31,value) biopod->values[31] |= value; biopod->number[31] = 0x9F; break; case 59: test_set_range(1,0,biopod,2,value) biopod->values[2] |= (value << 5); biopod->number[2] = 0x82; break; case 60: test_set_range(1,0,biopod,32,value) biopod->values[32] |= (value << 1); biopod->number[32] = 0xA2; break; case 61: test_set_range(1,0,biopod,1,value) biopod->values[1] |= (value << 6); biopod->number[1] = 0x81; break; case 'd': test_device(optarg) biopod->file = optarg; break; case 'h': fprintf(stderr,"ran into help!\n"); short_help(argv); exit(EXIT_SUCCESS); break; case 'e': test_set_range(7,0,biopod,2,value) biopod->values[2] |= (value << 0); biopod->number[2] = 0x82; break; case 62: test_set_range(127,0,biopod,15,value) biopod->values[15] |= value; biopod->number[15] = 0x8F; break; case 63: test_set_range(1,0,biopod,24,value) biopod->values[24] |= (value << 4); biopod->number[24] = 0x98; break; case 64: test_set_range(127,0,biopod,33,value) biopod->values[33] |= value; biopod->number[33] = 0xA1; break; case 65: test_set_range(127,0,biopod,34,value) biopod->values[34] |= value; biopod->number[34] = 0xA7; break; case 66: test_set_range(127,0,biopod,35,value) biopod->values[35] |= value; biopod->number[35] = 0xA9; break; case 67: test_set_range(127,0,biopod,36,value) biopod->values[36] |= value; biopod->number[36] = 0xB4; break; case 68: test_set_range(127,0,biopod,37,value) biopod->values[37] |= value; biopod->number[37] = 0xBB; break; case 69: test_set_range(15,0,biopod,3,value) biopod->values[3] |= value; biopod->number[3] = 0x83; break; default: fprintf(stderr,"default value found for %d\n",value); short_help(argv); exit(EXIT_FAILURE); break; } return biopod; } static device *send_device(device *biopod, int c) { if(biopod->use_ioctl[c] == 2){ switch(c) { case 26: repeat_ioctl_if_int(biopod,BIOPOD_IOCRESET,c); break; case 27: repeat_ioctl_if_int(biopod,BIOPOD_IOCSINGLE,c); break; case 28: send_to_device(biopod,c); break; case 30: repeat_ioctl_if_int(biopod,BIOPOD_IOCASYNC,c); break; case 62: if(biopod->values[c] == 1) { repeat_ioctl_if_int(biopod,BIOPOD_IOCSTART,c); } else { repeat_ioctl_if_int(biopod,BIOPOD_IOCSTOP,c); } break; default: send_to_device(biopod,c); break; }; } else { send_to_device(biopod,c); } return biopod; } void convert_to_string(device *biopod) { int x = 0; for(x = 0; x < MAX_REGISTERS; x++) { fprintf(stderr,"%X %X ",biopod->number[x],biopod->values[x]); } fprintf(stderr,"\n"); }