#include <stdbool.h>
#include <windows.h>

#include <libinsane/constants.h>
#include <libinsane/util.h>

#include "capabilities.h"
#include "twain.h"


static struct lis_twain_cap_possible g_twain_boolean[] = {
	{ .str = "false", .twain_int = FALSE },
	{ .str = "true", .twain_int = TRUE },
	{ .eol = 1 },
};


static struct lis_twain_cap_possible g_twain_possible_pixel_types[] = {
	// value names have been changed to match Sane
	{ .str = OPT_VALUE_MODE_BW, .twain_int = TWPT_BW },
	{ .str = OPT_VALUE_MODE_GRAYSCALE, .twain_int = TWPT_GRAY },
	{ .str = OPT_VALUE_MODE_COLOR, .twain_int = TWPT_RGB },
	{ .str = "palette", .twain_int = TWPT_PALETTE },
	{ .str = "cmy", .twain_int = TWPT_CMY },
	{ .str = "cmyk", .twain_int = TWPT_CMYK },
	{ .str = "yuv", .twain_int = TWPT_YUV },
	{ .str = "yuvk", .twain_int = TWPT_YUVK },
	{ .str = "ciexyz", .twain_int = TWPT_CIEXYZ },
	{ .str = "lab", .twain_int = TWPT_LAB },
	{ .str = "srgb", .twain_int = TWPT_SRGB },
	{ .str = "scrgb", .twain_int = TWPT_SCRGB },
	{ .str = "infrared", .twain_int = TWPT_INFRARED },
	{ .str = "srgb64", .twain_int = TWPT_SRGB64 },
	{ .str = "bgr", .twain_int = TWPT_BGR, },
	{ .str = "cielab", .twain_int = TWPT_CIELAB },
	{ .str = "cieluv", .twain_int = TWPT_CIELUV },
	{ .str = "ycbcr", .twain_int = TWPT_YCBCR },
	{ .eol = 1 },
};


static struct lis_twain_cap_possible g_twain_possible_caps[] = {
	{ .str = "transfer_count", .twain_int = CAP_XFERCOUNT, },
	{ .str = "compression", .twain_int = ICAP_COMPRESSION, },
	{ .str = OPT_NAME_MODE, .twain_int = ICAP_PIXELTYPE, },
	{ .str = "units", .twain_int = ICAP_UNITS, },
	{ .str = "transfer_mechanism", .twain_int = ICAP_XFERMECH, },
	{ .str = "author", .twain_int = CAP_AUTHOR, },
	{ .str = "caption", .twain_int = CAP_CAPTION, },
	{ .str = "feeder_enabled", .twain_int = CAP_FEEDERENABLED, },
	{ .str = "feeder_loaded", .twain_int = CAP_FEEDERLOADED, },
	{ .str = "time_date", .twain_int = CAP_TIMEDATE, },
	{ .str = "supported_caps", .twain_int = CAP_SUPPORTEDCAPS, },
	{ .str = "extended_caps", .twain_int = CAP_EXTENDEDCAPS, },
	{ .str = "autofeed", .twain_int = CAP_AUTOFEED, },
	{ .str = "clear_page", .twain_int = CAP_CLEARPAGE, },
	{ .str = "feed_page", .twain_int = CAP_FEEDPAGE, },
	{ .str = "rewind_page", .twain_int = CAP_REWINDPAGE, },
	{ .str = "indicators", .twain_int = CAP_INDICATORS, },
	{ .str = "paper_detectable", .twain_int = CAP_PAPERDETECTABLE, },
	{ .str = "ui_controllable", .twain_int = CAP_UICONTROLLABLE, },
	{ .str = "device_online", .twain_int = CAP_DEVICEONLINE, },
	{ .str = "autoscan", .twain_int = CAP_AUTOSCAN, },
	{ .str = "thumbnails_enabled", .twain_int = CAP_THUMBNAILSENABLED, },
	{ .str = "duplex", .twain_int = CAP_DUPLEX, },
	{ .str = "duplex_enabled", .twain_int = CAP_DUPLEXENABLED, },
	{ .str = "enable_ds_ui_only", .twain_int = CAP_ENABLEDSUIONLY, },
	{ .str = "custom_ds_data", .twain_int = CAP_CUSTOMDSDATA, },
	{ .str = "endorser", .twain_int = CAP_ENDORSER, },
	{ .str = "job_control", .twain_int = CAP_JOBCONTROL, },
	{ .str = "alarms", .twain_int = CAP_ALARMS, },
	{ .str = "alarm_volume", .twain_int = CAP_ALARMVOLUME, },
	{ .str = "automatic_capture", .twain_int = CAP_AUTOMATICCAPTURE, },
	{ .str = "time_before_first_capture", .twain_int = CAP_TIMEBEFOREFIRSTCAPTURE, },
	{ .str = "time_between_captures", .twain_int = CAP_TIMEBETWEENCAPTURES, },
	{ .str = "max_batch_buffers", .twain_int = CAP_MAXBATCHBUFFERS, },
	{ .str = "device_time_date", .twain_int = CAP_DEVICETIMEDATE, },
	{ .str = "power_supply", .twain_int = CAP_POWERSUPPLY, },
	{ .str = "camera_preview_ui", .twain_int = CAP_CAMERAPREVIEWUI, },
	{ .str = "device_event", .twain_int = CAP_DEVICEEVENT, },
	{ .str = "serial_number", .twain_int = CAP_SERIALNUMBER, },
	{ .str = "printer", .twain_int = CAP_PRINTER, },
	{ .str = "printer_enabled", .twain_int = CAP_PRINTERENABLED, },
	{ .str = "printer_index", .twain_int = CAP_PRINTERINDEX, },
	{ .str = "printer_mode", .twain_int = CAP_PRINTERMODE, },
	{ .str = "printer_string", .twain_int = CAP_PRINTERSTRING, },
	{ .str = "printer_suffix", .twain_int = CAP_PRINTERSUFFIX, },
	{ .str = "language", .twain_int = CAP_LANGUAGE, },
	{ .str = "feeder_alignment", .twain_int = CAP_FEEDERALIGNMENT, },
	{ .str = "feeder_order", .twain_int = CAP_FEEDERORDER, },
	{ .str = "reacquire_allowed", .twain_int = CAP_REACQUIREALLOWED, },
	{ .str = "battery_minutes", .twain_int = CAP_BATTERYMINUTES, },
	{ .str = "battery_percentage", .twain_int = CAP_BATTERYPERCENTAGE, },
	{ .str = "camera_side", .twain_int = CAP_CAMERASIDE, },
	{ .str = "camera_enabled", .twain_int = CAP_CAMERAENABLED, },
	{ .str = "camera_order", .twain_int = CAP_CAMERAORDER, },
	{ .str = "micr_enabled", .twain_int = CAP_MICRENABLED, },
	{ .str = "feeder_prep", .twain_int = CAP_FEEDERPREP, },
	{ .str = "feeder_pocket", .twain_int = CAP_FEEDERPOCKET, },
	{ .str = "automatic_sense_medium", .twain_int = CAP_AUTOMATICSENSEMEDIUM, },
	{ .str = "custom_interface_guid", .twain_int = CAP_CUSTOMINTERFACEGUID, },
	{ .str = "supported_caps_segment_unique", .twain_int = CAP_SUPPORTEDCAPSSEGMENTUNIQUE, },
	{ .str = "supported_dats", .twain_int = CAP_SUPPORTEDDATS, },
	{ .str = "double_feed_detection", .twain_int = CAP_DOUBLEFEEDDETECTION, },
	{ .str = "double_feed_detection_length", .twain_int = CAP_DOUBLEFEEDDETECTIONLENGTH, },
	{ .str = "double_feed_detection_sensitivity", .twain_int = CAP_DOUBLEFEEDDETECTIONSENSITIVITY, },
	{ .str = "double_feed_detection_response", .twain_int = CAP_DOUBLEFEEDDETECTIONRESPONSE, },
	{ .str = "paper_handling", .twain_int = CAP_PAPERHANDLING, },
	{ .str = "indicators_mode", .twain_int = CAP_INDICATORSMODE, },
	{ .str = "printer_vertical_offset", .twain_int = CAP_PRINTERVERTICALOFFSET, },
	{ .str = "power_save_time", .twain_int = CAP_POWERSAVETIME, },
	{ .str = "printer_char_rotation", .twain_int = CAP_PRINTERCHARROTATION, },
	{ .str = "printer_font_style", .twain_int = CAP_PRINTERFONTSTYLE, },
	{ .str = "printer_index_lead_char", .twain_int = CAP_PRINTERINDEXLEADCHAR, },
	{ .str = "printer_index_max_value", .twain_int = CAP_PRINTERINDEXMAXVALUE, },
	{ .str = "printer_index_num_digits", .twain_int = CAP_PRINTERINDEXNUMDIGITS, },
	{ .str = "printer_index_step", .twain_int = CAP_PRINTERINDEXSTEP, },
	{ .str = "printer_index_trigger", .twain_int = CAP_PRINTERINDEXTRIGGER, },
	{ .str = "printer_string_preview", .twain_int = CAP_PRINTERSTRINGPREVIEW, },
	{ .str = "sheet_count", .twain_int = CAP_SHEETCOUNT, },
	{ .str = "autobright", .twain_int = ICAP_AUTOBRIGHT, },
	{ .str = "brightness", .twain_int = ICAP_BRIGHTNESS, },
	{ .str = "contrast", .twain_int = ICAP_CONTRAST, },
	{ .str = "custom_halftone", .twain_int = ICAP_CUSTHALFTONE, },
	{ .str = "exposure_time", .twain_int = ICAP_EXPOSURETIME, },
	{ .str = "filter", .twain_int = ICAP_FILTER, },
	{ .str = "flash_used", .twain_int = ICAP_FLASHUSED, },
	{ .str = "gamma", .twain_int = ICAP_GAMMA, },
	{ .str = "halftones", .twain_int = ICAP_HALFTONES, },
	{ .str = "highlight", .twain_int = ICAP_HIGHLIGHT, },
	{ .str = "image_file_format", .twain_int = ICAP_IMAGEFILEFORMAT, },
	{ .str = "lamp_state", .twain_int = ICAP_LAMPSTATE, },
	{ .str = "light_source", .twain_int = ICAP_LIGHTSOURCE, },
	{ .str = "orientation", .twain_int = ICAP_ORIENTATION, },
	{ .str = "physical_width", .twain_int = ICAP_PHYSICALWIDTH, },
	{ .str = "physical_height", .twain_int = ICAP_PHYSICALHEIGHT, },
	{ .str = "shadow", .twain_int = ICAP_SHADOW, },
	{ .str = "frames", .twain_int = ICAP_FRAMES, },
	{ .str = "x_native_resolution", .twain_int = ICAP_XNATIVERESOLUTION, },
	{ .str = "y_native_resolution", .twain_int = ICAP_YNATIVERESOLUTION, },
	{ .str = "x_resolution", .twain_int = ICAP_XRESOLUTION, },
	{ .str = "y_resolution", .twain_int = ICAP_YRESOLUTION, },
	{ .str = "max_frames", .twain_int = ICAP_MAXFRAMES, },
	{ .str = "tiles", .twain_int = ICAP_TILES, },
	{ .str = "bit_order", .twain_int = ICAP_BITORDER, },
	{ .str = "ccitt_k_factor", .twain_int = ICAP_CCITTKFACTOR, },
	{ .str = "light_path", .twain_int = ICAP_LIGHTPATH, },
	{ .str = "pixel_flavor", .twain_int = ICAP_PIXELFLAVOR, },
	{ .str = "planar_chunky", .twain_int = ICAP_PLANARCHUNKY, },
	{ .str = "rotation", .twain_int = ICAP_ROTATION, },
	{ .str = "supported_sizes", .twain_int = ICAP_SUPPORTEDSIZES, },
	{ .str = "threshold", .twain_int = ICAP_THRESHOLD, },
	{ .str = "x_scaling", .twain_int = ICAP_XSCALING, },
	{ .str = "y_scaling", .twain_int = ICAP_YSCALING, },
	{ .str = "bit_order_codes", .twain_int = ICAP_BITORDERCODES, },
	{ .str = "pixel_flavor_codes", .twain_int = ICAP_PIXELFLAVORCODES, },
	{ .str = "jpeg_pixel_type", .twain_int = ICAP_JPEGPIXELTYPE, },
	{ .str = "time_fill", .twain_int = ICAP_TIMEFILL, },
	{ .str = "bit_depth", .twain_int = ICAP_BITDEPTH, },
	{ .str = "bit_depth_reduction", .twain_int = ICAP_BITDEPTHREDUCTION, },
	{ .str = "undefined_image_size", .twain_int = ICAP_UNDEFINEDIMAGESIZE, },
	{ .str = "image_data_set", .twain_int = ICAP_IMAGEDATASET, },
	{ .str = "extra_image_info", .twain_int = ICAP_EXTIMAGEINFO, },
	{ .str = "minimum_height", .twain_int = ICAP_MINIMUMHEIGHT, },
	{ .str = "minimum_width", .twain_int = ICAP_MINIMUMWIDTH, },
	{ .str = "autodiscard_blank_pages", .twain_int = ICAP_AUTODISCARDBLANKPAGES, },
	{ .str = "flip_rotation", .twain_int = ICAP_FLIPROTATION, },
	{ .str = "barcode_detection_enabled", .twain_int = ICAP_BARCODEDETECTIONENABLED, },
	{ .str = "supported_barcode_types", .twain_int = ICAP_SUPPORTEDBARCODETYPES, },
	{ .str = "barcode_max_search_priorities", .twain_int = ICAP_BARCODEMAXSEARCHPRIORITIES, },
	{ .str = "barcode_search_priorities", .twain_int = ICAP_BARCODESEARCHPRIORITIES, },
	{ .str = "barcode_search_mode", .twain_int = ICAP_BARCODESEARCHMODE, },
	{ .str = "barcode_max_retries", .twain_int = ICAP_BARCODEMAXRETRIES, },
	{ .str = "barcode_timeout", .twain_int = ICAP_BARCODETIMEOUT, },
	{ .str = "zoom_factor", .twain_int = ICAP_ZOOMFACTOR, },
	{ .str = "patch_code_detection_enabled", .twain_int = ICAP_PATCHCODEDETECTIONENABLED, },
	{ .str = "supported_patch_code_types", .twain_int = ICAP_SUPPORTEDPATCHCODETYPES, },
	{ .str = "patch_code_max_search_priorities", .twain_int = ICAP_PATCHCODEMAXSEARCHPRIORITIES, },
	{ .str = "patch_code_search_priorities", .twain_int = ICAP_PATCHCODESEARCHPRIORITIES, },
	{ .str = "patch_code_search_mode", .twain_int = ICAP_PATCHCODESEARCHMODE, },
	{ .str = "patch_code_max_retries", .twain_int = ICAP_PATCHCODEMAXRETRIES, },
	{ .str = "patch_code_timeout", .twain_int = ICAP_PATCHCODETIMEOUT, },
	{ .str = "flash_used_2", .twain_int = ICAP_FLASHUSED2, },
	{ .str = "image_filter", .twain_int = ICAP_IMAGEFILTER, },
	{ .str = "noise_filter", .twain_int = ICAP_NOISEFILTER, },
	{ .str = "overscan", .twain_int = ICAP_OVERSCAN, },
	{ .str = "automatic_border_detection", .twain_int = ICAP_AUTOMATICBORDERDETECTION, },
	{ .str = "automatic_deskew", .twain_int = ICAP_AUTOMATICDESKEW, },
	{ .str = "automatic_rotate", .twain_int = ICAP_AUTOMATICROTATE, },
	{ .str = "jpeg_quality", .twain_int = ICAP_JPEGQUALITY, },
	{ .str = "feeder_type", .twain_int = ICAP_FEEDERTYPE, },
	{ .str = "icc_profile", .twain_int = ICAP_ICCPROFILE, },
	{ .str = "autosize", .twain_int = ICAP_AUTOSIZE, },
	{ .str = "automatic_crop_uses_frame", .twain_int = ICAP_AUTOMATICCROPUSESFRAME, },
	{ .str = "automatic_length_detection", .twain_int = ICAP_AUTOMATICLENGTHDETECTION, },
	{ .str = "automatic_color_enabled", .twain_int = ICAP_AUTOMATICCOLORENABLED, },
	{ .str = "automatic_color_noncolor_pixel_type", .twain_int = ICAP_AUTOMATICCOLORNONCOLORPIXELTYPE, },
	{ .str = "color_management_enabled", .twain_int = ICAP_COLORMANAGEMENTENABLED, },
	{ .str = "image_merge", .twain_int = ICAP_IMAGEMERGE, },
	{ .str = "image_merge_height_threshold", .twain_int = ICAP_IMAGEMERGEHEIGHTTHRESHOLD, },
	{ .str = "supported_extra_image_info", .twain_int = ICAP_SUPPORTEDEXTIMAGEINFO, },
	{ .str = "film_type", .twain_int = ICAP_FILMTYPE, },
	{ .str = "mirror", .twain_int = ICAP_MIRROR, },
	{ .str = "jpeg_subsampling", .twain_int = ICAP_JPEGSUBSAMPLING, },
	{ .str = "clear_buffers", .twain_int = CAP_CLEARBUFFERS, },
	{ .str = "supported_caps_extra", .twain_int = CAP_SUPPORTEDCAPSEXT, },
	{ .str = "page_multiple_acquire", .twain_int = CAP_PAGEMULTIPLEACQUIRE, },
	{ .str = "paper_binding", .twain_int = CAP_PAPERBINDING, },
	{ .str = "passthrough", .twain_int = CAP_PASSTHRU, },
	{ .str = "power_downtime", .twain_int = CAP_POWERDOWNTIME, },
	{ .eol = 1 },
};


static struct lis_twain_cap_possible g_twain_possible_barcodes[] = {
	{ .str = "2_of_5_datalogic", .twain_int = TWBT_2OF5DATALOGIC, },
	{ .str = "2_of_5_iata", .twain_int = TWBT_2OF5IATA, },
	{ .str = "2_of_5_industrial", .twain_int = TWBT_2OF5INDUSTRIAL, },
	{ .str = "2_of_5_interleaved", .twain_int = TWBT_2OF5INTERLEAVED, },
	{ .str = "2_of_5_matrix", .twain_int = TWBT_2OF5MATRIX, },
	{ .str = "2_of_5_noninterleaved", .twain_int = TWBT_2OF5NONINTERLEAVED, },
	{ .str = "3_of_9", .twain_int = TWBT_3OF9, },
	{ .str = "3_of_9_full_ascii", .twain_int = TWBT_3OF9FULLASCII, },
	{ .str = "codabar", .twain_int = TWBT_CODABAR, },
	{ .str = "codabar_with_start_stop", .twain_int = TWBT_CODABARWITHSTARTSTOP, },
	{ .str = "code_128", .twain_int = TWBT_CODE128, },
	{ .str = "code_93", .twain_int = TWBT_CODE93, },
	{ .str = "ean_13", .twain_int = TWBT_EAN13, },
	{ .str = "ean_8", .twain_int = TWBT_EAN8, },
	{ .str = "maxicode", .twain_int = TWBT_MAXICODE, },
	{ .str = "pdf_417", .twain_int = TWBT_PDF417, },
	{ .str = "postnet", .twain_int = TWBT_POSTNET, },
	{ .str = "qrcode", .twain_int = TWBT_QRCODE, },
	{ .str = "ucc128", .twain_int = TWBT_UCC128, },
	{ .str = "upca", .twain_int = TWBT_UPCA, },
	{ .str = "upce", .twain_int = TWBT_UPCE, },
	{ .eol = 1 },
};


static struct lis_twain_cap_possible g_twain_possible_patchcode[] = {
	{ .str = "patch_1", .twain_int = TWPCH_PATCH1, },
	{ .str = "patch_2", .twain_int = TWPCH_PATCH2, },
	{ .str = "patch_3", .twain_int = TWPCH_PATCH3, },
	{ .str = "patch_4", .twain_int = TWPCH_PATCH4, },
	{ .str = "patch_6", .twain_int = TWPCH_PATCH6, },
	{ .str = "patch_t", .twain_int = TWPCH_PATCHT, },
	{ .eol = 1 },
};


static struct lis_twain_cap_possible g_twain_possible_orientations[] = {
	{ .str = "horizontal", .twain_int = TWBD_HORZ, },
	{ .str = "vertical", .twain_int = TWBD_VERT, },
	{ .str = "horizontal_vertical", .twain_int = TWBD_HORZVERT, },
	{ .str = "vertical_horizontal", .twain_int = TWBD_VERTHORZ, },
	{ .eol = 1 },
};


static const struct lis_twain_cap g_twain_caps[] = {
	{
		.name = "transfer_count",
		.desc = "Number of pages accepted by application (-1 = inf.)",
		.readonly = FALSE,
		.id = CAP_XFERCOUNT,
		.type = TWTY_UINT16,
		.possibles = NULL
	},
	{
		.name = "compression",
		.desc = "Compression scheme",
		.readonly = FALSE,
		.id = ICAP_COMPRESSION,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "none", .twain_int = TWCP_NONE },
			{ .str = "packbits", .twain_int = TWCP_PACKBITS },
			{ .str = "group31d", .twain_int = TWCP_GROUP31D },
			{ .str = "group31deol", .twain_int = TWCP_GROUP31DEOL },
			{ .str = "group32d", .twain_int = TWCP_GROUP32D },
			{ .str = "group4", .twain_int = TWCP_GROUP4 },
			{ .str = "jpeg", .twain_int = TWCP_JPEG },
			{ .str = "lzw", .twain_int = TWCP_LZW },
			{ .str = "jbig", .twain_int = TWCP_JBIG },
			{ .str = "png", .twain_int = TWCP_PNG },
			{ .str = "rle4", .twain_int = TWCP_RLE4 },
			{ .str = "rle8", .twain_int = TWCP_RLE8 },
			{ .str = "bit_fields", .twain_int = TWCP_BITFIELDS },
			{ .str = "zip", .twain_int = TWCP_ZIP },
			{ .str = "jpeg2000", .twain_int = TWCP_JPEG2000 },
			{ .eol = 1 },
		},
	},
	{
		.name = "mode",
		.id = ICAP_PIXELTYPE,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = g_twain_possible_pixel_types,
	},
	{
		.name = "units",
		.id = ICAP_UNITS,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "inches", .twain_int = TWUN_INCHES },
			{ .str = "centimeters", .twain_int = TWUN_CENTIMETERS },
			{ .str = "picas", .twain_int = TWUN_PICAS },
			{ .str = "points", .twain_int = TWUN_POINTS },
			{ .str = "twips", .twain_int = TWUN_TWIPS },
			{ .str = "pixels", .twain_int = TWUN_PIXELS },
			{ .str = "millimeters", .twain_int = TWUN_MILLIMETERS },
			{ .eol = 1 },
		},
	},
	{
		.name = "transfer_mechanism",
		.id = ICAP_XFERMECH,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "native", .twain_int = TWSX_NATIVE },
			{ .str = "file", .twain_int = TWSX_FILE },
			{ .str = "memory", .twain_int = TWSX_MEMORY },
			{ .str = "memfile", .twain_int = TWSX_MEMFILE },
			{ .eol = 1 },
		},
	},
	{
		.name = "author",
		.id = CAP_AUTHOR,
		.readonly = TRUE,
		.type = TWTY_STR128,
		.possibles = NULL
	},
	{
		.name = "caption",
		.id = CAP_CAPTION,
		.readonly = TRUE,
		.type = TWTY_STR255,
		.possibles = NULL,
	},
	{
		.name = "feeder_enabled",
		.id = CAP_FEEDERENABLED,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "feeder_loaded",
		.id = CAP_FEEDERLOADED,
		.readonly = TRUE,
		.type = TWTY_UINT16,
		.possibles = g_twain_boolean,
	},
	{
		.name = "time_date",
		.id = CAP_TIMEDATE,
		.readonly = TRUE,
		.type = TWTY_STR32,
		.possibles = NULL,
	},
	{
		.name = "supported_caps",
		.id = CAP_SUPPORTEDCAPS,
		.readonly = TRUE,
		.type = TWTY_UINT16,
		.possibles = g_twain_possible_caps,
	},
	{
		.name = "extended_caps",
		.id = CAP_EXTENDEDCAPS,
		.readonly = TRUE,
		.type = TWTY_UINT16,
		.possibles = g_twain_possible_caps,
	},
	{
		.name = "autofeed",
		.id = CAP_AUTOFEED,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "clear_page",
		.id = CAP_CLEARPAGE,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "feed_page",
		.id = CAP_FEEDPAGE,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "rewind_page",
		.id = CAP_REWINDPAGE,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "indicators",
		.id = CAP_INDICATORS,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "paper_detectable",
		.id = CAP_PAPERDETECTABLE,
		.readonly = TRUE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "ui_controllable",
		.id = CAP_UICONTROLLABLE,
		.readonly = TRUE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "device_online",
		.id = CAP_DEVICEONLINE,
		.readonly = TRUE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "autoscan",
		.id = CAP_AUTOSCAN,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "thumbnails_enabled",
		.id = CAP_THUMBNAILSENABLED,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "duplex",
		.id = CAP_DUPLEX,
		.readonly = TRUE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "duplex_enabled",
		.id = CAP_DUPLEXENABLED,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "enable_ds_ui_only",
		.id = CAP_ENABLEDSUIONLY,
		.readonly = TRUE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "custom_ds_data",
		.id = CAP_CUSTOMDSDATA,
		.readonly = TRUE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "endorser",
		.id = CAP_ENDORSER,
		.readonly = FALSE,
		.type = TWTY_UINT32,
		.possibles = NULL,
	},
	{
		.name = "job_control",
		.id = CAP_JOBCONTROL,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "none", .twain_int = TWJC_NONE },
			{ .str = "jsic", .twain_int = TWJC_JSIC },
			{ .str = "jsis", .twain_int = TWJC_JSIS },
			{ .str = "jsxc", .twain_int = TWJC_JSXC },
			{ .str = "jsxs", .twain_int = TWJC_JSXS },
			{ .eol = 1 },
		},
	},
	{
		.name = "alarms",
		.id = CAP_ALARMS,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "alarm", .twain_int = TWAL_ALARM },
			{ .str = "feeder_error", .twain_int = TWAL_FEEDERERROR },
			{ .str = "feeder_warning", .twain_int = TWAL_FEEDERWARNING },
			{ .str = "barcode", .twain_int = TWAL_BARCODE },
			{ .str = "double_feed", .twain_int = TWAL_DOUBLEFEED },
			{ .str = "jam", .twain_int = TWAL_JAM },
			{ .str = "patch_code", .twain_int = TWAL_PATCHCODE },
			{ .str = "power", .twain_int = TWAL_POWER },
			{ .str = "skew", .twain_int = TWAL_SKEW },
			{ .eol = 1 },
		},
	},
	{
		.name = "alarm_volume",
		.id = CAP_ALARMVOLUME,
		.readonly = FALSE,
		.type = TWTY_INT32,
		.possibles = NULL,
	},
	{
		.name = "automatic_capture",
		.id = CAP_AUTOMATICCAPTURE,
		.readonly = FALSE,
		.type = TWTY_INT32,
		.possibles = NULL,
	},
	{
		.name = "time_before_first_capture",
		.id = CAP_TIMEBEFOREFIRSTCAPTURE,
		.readonly = FALSE,
		.type = TWTY_INT32,
		.possibles = NULL,
	},
	{
		.name = "time_between_captures",
		.id = CAP_TIMEBETWEENCAPTURES,
		.readonly = FALSE,
		.type = TWTY_INT32,
		.possibles = NULL,
	},
	{
		.name = "max_batch_buffers",
		.id = CAP_MAXBATCHBUFFERS,
		.readonly = FALSE,
		.type = TWTY_UINT32,
		.possibles = NULL,
	},
	{
		.name = "device_time_date",
		.id = CAP_DEVICETIMEDATE,
		.readonly = FALSE,
		.type = TWTY_STR32,
		.possibles = NULL,
	},
	{
		.name = "power_supply",
		.id = CAP_POWERSUPPLY,
		.readonly = TRUE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "external", .twain_int = TWPS_EXTERNAL },
			{ .str = "battery", .twain_int = TWPS_BATTERY },
			{ .eol = 1 },
		},
	},
	{
		.name = "camera_preview_ui",
		.id = CAP_CAMERAPREVIEWUI,
		.readonly = TRUE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "device_event",
		.id = CAP_DEVICEEVENT,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "check_automatic_capture", .twain_int = TWDE_CHECKAUTOMATICCAPTURE, },
			{ .str = "check_battery", .twain_int = TWDE_CHECKBATTERY, },
			{ .str = "check_device_online", .twain_int = TWDE_CHECKDEVICEONLINE, },
			{ .str = "check_flash", .twain_int = TWDE_CHECKFLASH, },
			{ .str = "check_power_supply", .twain_int = TWDE_CHECKPOWERSUPPLY, },
			{ .str = "check_resolution", .twain_int = TWDE_CHECKRESOLUTION, },
			{ .str = "device_added", .twain_int = TWDE_DEVICEADDED, },
			{ .str = "device_offline", .twain_int = TWDE_DEVICEOFFLINE, },
			{ .str = "device_ready", .twain_int = TWDE_DEVICEREADY, },
			{ .str = "device_removed", .twain_int = TWDE_DEVICEREMOVED, },
			{ .str = "image_captured", .twain_int = TWDE_IMAGECAPTURED, },
			{ .str = "image_deleted", .twain_int = TWDE_IMAGEDELETED, },
			{ .str = "paper_double_feed", .twain_int = TWDE_PAPERDOUBLEFEED, },
			{ .str = "paper_jam", .twain_int = TWDE_PAPERJAM, },
			{ .str = "lamp_failure", .twain_int = TWDE_LAMPFAILURE, },
			{ .str = "powersave", .twain_int = TWDE_POWERSAVE, },
			{ .str = "powersave_notify", .twain_int = TWDE_POWERSAVENOTIFY, },
			{ .eol = 1 },
		},
	},
	{
		.name = "serial_number",
		.id = CAP_SERIALNUMBER,
		.readonly = TRUE,
		.type = TWTY_STR255,
		.possibles = NULL,
	},
	{
		.name = "printer",
		.id = CAP_PRINTER,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "imprinter_top_before", .twain_int = TWPR_IMPRINTERTOPBEFORE, },
			{ .str = "imprinter_top_after", .twain_int = TWPR_IMPRINTERTOPAFTER, },
			{ .str = "imprinter_bottom_before", .twain_int = TWPR_IMPRINTERBOTTOMBEFORE, },
			{ .str = "imprinter_bottom_after", .twain_int = TWPR_IMPRINTERBOTTOMAFTER, },
			{ .str = "endorser_top_before", .twain_int = TWPR_ENDORSERTOPBEFORE, },
			{ .str = "endorser_top_after", .twain_int = TWPR_ENDORSERTOPAFTER, },
			{ .str = "endorser_bottom_before", .twain_int = TWPR_ENDORSERBOTTOMBEFORE, },
			{ .str = "endorser_bottom_after", .twain_int = TWPR_ENDORSERBOTTOMAFTER, },
			{ .eol = 1 },
		},
	},
	{
		.name = "printer_enabled",
		.id = CAP_PRINTERENABLED,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "printer_index",
		.id = CAP_PRINTERINDEX,
		.readonly = FALSE,
		.type = TWTY_UINT32,
		.possibles = NULL,
	},
	{
		.name = "printer_mode",
		.id = CAP_PRINTERMODE,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "single_string", .twain_int = TWPM_SINGLESTRING, },
			{ .str = "multiple_strings", .twain_int = TWPM_MULTISTRING, },
			{ .str = "compound_strings", .twain_int = TWPM_COMPOUNDSTRING, },
			{ .eol = 1 },
		},
	},
	{
		.name = "printer_string",
		.id = CAP_PRINTERSTRING,
		.readonly = FALSE,
		.type = TWTY_STR255,
		.possibles = NULL,
	},
	{
		.name = "printer_suffix",
		.id = CAP_PRINTERSUFFIX,
		.readonly = FALSE,
		.type = TWTY_STR255,
		.possibles = NULL,
	},
	{
		.name = "language",
		.id = CAP_LANGUAGE,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "user_locale", .twain_int = TWLG_USERLOCALE, },
			{ .str = "danish", .twain_int = TWLG_DAN, },
			{ .str = "dutch", .twain_int = TWLG_DUT, },
			{ .str = "english", .twain_int = TWLG_ENG, },
			{ .str = "fcf", .twain_int = TWLG_FCF, }, // TODO(Jflesch)
			{ .str = "finnish", .twain_int = TWLG_FIN, },
			{ .str = "french", .twain_int = TWLG_FRN, },
			{ .str = "german", .twain_int = TWLG_GER, },
			{ .str = "icelandic", .twain_int = TWLG_ICE, },
			{ .str = "italian", .twain_int = TWLG_ITN, },
			{ .str = "norwegian", .twain_int = TWLG_NOR, },
			{ .str = "portuguese", .twain_int = TWLG_POR, },
			{ .str = "spanish", .twain_int = TWLG_SPA, },
			{ .str = "swedish", .twain_int = TWLG_SWE, },
			{ .str = "english_usa", .twain_int = TWLG_USA, },
			{ .str = "afrikaans", .twain_int = TWLG_AFRIKAANS, },
			{ .str = "albania", .twain_int = TWLG_ALBANIA, },
			{ .str = "arabic", .twain_int = TWLG_ARABIC, },
			{ .str = "arabic_algeria", .twain_int = TWLG_ARABIC_ALGERIA, },
			{ .str = "arabic_bahrain", .twain_int = TWLG_ARABIC_BAHRAIN, },
			{ .str = "arabic_egypt", .twain_int = TWLG_ARABIC_EGYPT, },
			{ .str = "arabic_iraq", .twain_int = TWLG_ARABIC_IRAQ, },
			{ .str = "arabic_jordan", .twain_int = TWLG_ARABIC_JORDAN, },
			{ .str = "arabic_kuwait", .twain_int = TWLG_ARABIC_KUWAIT, },
			{ .str = "arabic_lebanon", .twain_int = TWLG_ARABIC_LEBANON, },
			{ .str = "arabic_libya", .twain_int = TWLG_ARABIC_LIBYA, },
			{ .str = "arabic_morocco", .twain_int = TWLG_ARABIC_MOROCCO, },
			{ .str = "arabic_oman", .twain_int = TWLG_ARABIC_OMAN, },
			{ .str = "arabic_qatar", .twain_int = TWLG_ARABIC_QATAR, },
			{ .str = "arabic_saudiarabia", .twain_int = TWLG_ARABIC_SAUDIARABIA, },
			{ .str = "arabic_syria", .twain_int = TWLG_ARABIC_SYRIA, },
			{ .str = "arabic_tunisia", .twain_int = TWLG_ARABIC_TUNISIA, },
			{ .str = "arabic_uae", .twain_int = TWLG_ARABIC_UAE, },
			{ .str = "arabic_yemen", .twain_int = TWLG_ARABIC_YEMEN, },
			{ .str = "basque", .twain_int = TWLG_BASQUE, },
			{ .str = "byelorussian", .twain_int = TWLG_BYELORUSSIAN, },
			{ .str = "bulgarian", .twain_int = TWLG_BULGARIAN, },
			{ .str = "catalan", .twain_int = TWLG_CATALAN, },
			{ .str = "chinese", .twain_int = TWLG_CHINESE, },
			{ .str = "chinese_hongkong", .twain_int = TWLG_CHINESE_HONGKONG, },
			{ .str = "chinese_prc", .twain_int = TWLG_CHINESE_PRC, },
			{ .str = "chinese_singapore", .twain_int = TWLG_CHINESE_SINGAPORE, },
			{ .str = "chinese_simplified", .twain_int = TWLG_CHINESE_SIMPLIFIED, },
			{ .str = "chinese_taiwan", .twain_int = TWLG_CHINESE_TAIWAN, },
			{ .str = "chinese_traditional", .twain_int = TWLG_CHINESE_TRADITIONAL, },
			{ .str = "croatia", .twain_int = TWLG_CROATIA, },
			{ .str = "czech", .twain_int = TWLG_CZECH, },
			{ .str = "dutch_belgian", .twain_int = TWLG_DUTCH_BELGIAN, },
			{ .str = "english_australian", .twain_int = TWLG_ENGLISH_AUSTRALIAN, },
			{ .str = "english_canadian", .twain_int = TWLG_ENGLISH_CANADIAN, },
			{ .str = "english_ireland", .twain_int = TWLG_ENGLISH_IRELAND, },
			{ .str = "english_newzealand", .twain_int = TWLG_ENGLISH_NEWZEALAND, },
			{ .str = "english_southafrica", .twain_int = TWLG_ENGLISH_SOUTHAFRICA, },
			{ .str = "english_uk", .twain_int = TWLG_ENGLISH_UK, },
			{ .str = "estonian", .twain_int = TWLG_ESTONIAN, },
			{ .str = "faeroese", .twain_int = TWLG_FAEROESE, },
			{ .str = "farsi", .twain_int = TWLG_FARSI, },
			{ .str = "finnish", .twain_int = TWLG_FINNISH, },
			{ .str = "french_belgian", .twain_int = TWLG_FRENCH_BELGIAN, },
			{ .str = "french_canadian", .twain_int = TWLG_FRENCH_CANADIAN, },
			{ .str = "french_luxembourg", .twain_int = TWLG_FRENCH_LUXEMBOURG, },
			{ .str = "french_swiss", .twain_int = TWLG_FRENCH_SWISS, },
			{ .str = "german_austrian", .twain_int = TWLG_GERMAN_AUSTRIAN, },
			{ .str = "german_luxembourg", .twain_int = TWLG_GERMAN_LUXEMBOURG, },
			{ .str = "german_liechtenstein", .twain_int = TWLG_GERMAN_LIECHTENSTEIN, },
			{ .str = "german_swiss", .twain_int = TWLG_GERMAN_SWISS, },
			{ .str = "greek", .twain_int = TWLG_GREEK, },
			{ .str = "hebrew", .twain_int = TWLG_HEBREW, },
			{ .str = "hungarian", .twain_int = TWLG_HUNGARIAN, },
			{ .str = "indonesian", .twain_int = TWLG_INDONESIAN, },
			{ .str = "italian_swiss", .twain_int = TWLG_ITALIAN_SWISS, },
			{ .str = "japanese", .twain_int = TWLG_JAPANESE, },
			{ .str = "korean", .twain_int = TWLG_KOREAN, },
			{ .str = "korean_johab", .twain_int = TWLG_KOREAN_JOHAB, },
			{ .str = "latvian", .twain_int = TWLG_LATVIAN, },
			{ .str = "lithuanian", .twain_int = TWLG_LITHUANIAN, },
			{ .str = "norwegian", .twain_int = TWLG_NORWEGIAN, },
			{ .str = "norwegian_bokmal", .twain_int = TWLG_NORWEGIAN_BOKMAL, },
			{ .str = "norwegian_nynorsk", .twain_int = TWLG_NORWEGIAN_NYNORSK, },
			{ .str = "polish", .twain_int = TWLG_POLISH, },
			{ .str = "portuguese_brazil", .twain_int = TWLG_PORTUGUESE_BRAZIL, },
			{ .str = "romanian", .twain_int = TWLG_ROMANIAN, },
			{ .str = "russian", .twain_int = TWLG_RUSSIAN, },
			{ .str = "serbian_latin", .twain_int = TWLG_SERBIAN_LATIN, },
			{ .str = "slovak", .twain_int = TWLG_SLOVAK, },
			{ .str = "slovenian", .twain_int = TWLG_SLOVENIAN, },
			{ .str = "spanish_mexican", .twain_int = TWLG_SPANISH_MEXICAN, },
			{ .str = "spanish_modern", .twain_int = TWLG_SPANISH_MODERN, },
			{ .str = "thai", .twain_int = TWLG_THAI, },
			{ .str = "turkish", .twain_int = TWLG_TURKISH, },
			{ .str = "ukranian", .twain_int = TWLG_UKRANIAN, },
			{ .str = "assamese", .twain_int = TWLG_ASSAMESE, },
			{ .str = "bengali", .twain_int = TWLG_BENGALI, },
			{ .str = "bihari", .twain_int = TWLG_BIHARI, },
			{ .str = "bodo", .twain_int = TWLG_BODO, },
			{ .str = "dogri", .twain_int = TWLG_DOGRI, },
			{ .str = "gujarati", .twain_int = TWLG_GUJARATI, },
			{ .str = "haryanvi", .twain_int = TWLG_HARYANVI, },
			{ .str = "hindi", .twain_int = TWLG_HINDI, },
			{ .str = "kannada", .twain_int = TWLG_KANNADA, },
			{ .str = "kashmiri", .twain_int = TWLG_KASHMIRI, },
			{ .str = "malayalam", .twain_int = TWLG_MALAYALAM, },
			{ .str = "marathi", .twain_int = TWLG_MARATHI, },
			{ .str = "marwari", .twain_int = TWLG_MARWARI, },
			{ .str = "meghalayan", .twain_int = TWLG_MEGHALAYAN, },
			{ .str = "mizo", .twain_int = TWLG_MIZO, },
			{ .str = "naga", .twain_int = TWLG_NAGA, },
			{ .str = "orissi", .twain_int = TWLG_ORISSI, },
			{ .str = "punjabi", .twain_int = TWLG_PUNJABI, },
			{ .str = "pushtu", .twain_int = TWLG_PUSHTU, },
			{ .str = "serbian_cyrillic", .twain_int = TWLG_SERBIAN_CYRILLIC, },
			{ .str = "sikkimi", .twain_int = TWLG_SIKKIMI, },
			{ .str = "swedish_finland", .twain_int = TWLG_SWEDISH_FINLAND, },
			{ .str = "tamil", .twain_int = TWLG_TAMIL, },
			{ .str = "telugu", .twain_int = TWLG_TELUGU, },
			{ .str = "tripuri", .twain_int = TWLG_TRIPURI, },
			{ .str = "urdu", .twain_int = TWLG_URDU, },
			{ .str = "vietnamese", .twain_int = TWLG_VIETNAMESE, },
			{ .eol = 1 },
		},
	},
	{
		.name = "feeder_alignment",
		.id = CAP_FEEDERALIGNMENT,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "none", .twain_int = TWFA_NONE },
			{ .str = "left", .twain_int = TWFA_LEFT },
			{ .str = "center", .twain_int = TWFA_CENTER },
			{ .str = "right", .twain_int = TWFA_RIGHT },
			{ .eol = 1 },
		},
	},
	{
		.name = "feeder_order",
		.id = CAP_FEEDERORDER,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "first_page_first", .twain_int = TWFO_FIRSTPAGEFIRST, },
			{ .str = "last_page_first", .twain_int = TWFO_LASTPAGEFIRST, },
			{ .eol = 1 },
		},
	},
	{
		.name = "reacquire_allowed",
		.id = CAP_REACQUIREALLOWED,
		.readonly = TRUE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "battery_minutes",
		.id = CAP_BATTERYMINUTES,
		.readonly = TRUE,
		.type = TWTY_INT32,
		.possibles = NULL,
	},
	{
		.name = "battery_percentage",
		.id = CAP_BATTERYPERCENTAGE,
		.readonly = TRUE,
		.type = TWTY_INT16,
		.possibles = NULL,
	},
	{
		.name = "camera_side",
		.id = CAP_CAMERASIDE,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "both", .twain_int = TWCS_BOTH, },
			{ .str = "top", .twain_int = TWCS_TOP, },
			{ .str = "bottom", .twain_int = TWCS_BOTTOM, },
			{ .eol = 1 },
		},
	},
	{
		.name = "segmented",
		.id = CAP_SEGMENTED,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "auto", .twain_int = TWSG_AUTO, },
			{ .str = "none", .twain_int = TWSG_NONE, },
			{ .str = "manual", .twain_int = TWSG_MANUAL, },
			{ .eol = 1 },
		},
	},
	{
		.name = "camera_enabled",
		.id = CAP_CAMERAENABLED,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = g_twain_boolean,
	},
	{
		.name = "camera_order",
		.id = CAP_CAMERAORDER,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = g_twain_possible_pixel_types,
	},
	{
		.name = "micr_enabled",
		.id = CAP_MICRENABLED,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "feeder_prep",
		.id = CAP_FEEDERPREP,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "feeder_pocket",
		.id = CAP_FEEDERPOCKET,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = NULL,
	},
	{
		.name = "automatic_sense_medium",
		.id = CAP_AUTOMATICSENSEMEDIUM,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "custom_interface_guid",
		.id = CAP_CUSTOMINTERFACEGUID,
		.readonly = TRUE,
		.type = TWTY_STR255,
		.possibles = NULL,
	},
	{
		.name = "supported_caps_segment_unique",
		.id = CAP_SUPPORTEDCAPSSEGMENTUNIQUE,
		.readonly = TRUE,
		.type = TWTY_UINT16,
		.possibles = NULL,
	},
	{
		.name = "supported_dats",
		.id = CAP_SUPPORTEDDATS,
		.readonly = TRUE,
		.type = TWTY_UINT32,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "null", .twain_int = DAT_NULL, },
			{ .str = "custom_base", .twain_int = DAT_CUSTOMBASE, },
			{ .str = "capability", .twain_int = DAT_CAPABILITY, },
			{ .str = "event", .twain_int = DAT_EVENT, },
			{ .str = "identity", .twain_int = DAT_IDENTITY, },
			{ .str = "parent", .twain_int = DAT_PARENT, },
			{ .str = "pending_transfers", .twain_int = DAT_PENDINGXFERS, },
			{ .str = "setup_memory_transfer", .twain_int = DAT_SETUPMEMXFER, },
			{ .str = "setup_file_transfer", .twain_int = DAT_SETUPFILEXFER, },
			{ .str = "status", .twain_int = DAT_STATUS, },
			{ .str = "user_interface", .twain_int = DAT_USERINTERFACE, },
			{ .str = "transfer_group", .twain_int = DAT_XFERGROUP, },
			{ .str = "custom_datasource_data", .twain_int = DAT_CUSTOMDSDATA, },
			{ .str = "device_event", .twain_int = DAT_DEVICEEVENT, },
			{ .str = "filesystem", .twain_int = DAT_FILESYSTEM, },
			{ .str = "passthrough", .twain_int = DAT_PASSTHRU, },
			{ .str = "callback", .twain_int = DAT_CALLBACK, },
			{ .str = "status_utf8", .twain_int = DAT_STATUSUTF8, },
			{ .str = "callback2", .twain_int = DAT_CALLBACK2, },
			{ .str = "metrics", .twain_int = DAT_METRICS, },
			{ .str = "twain_direct", .twain_int = DAT_TWAINDIRECT, },
			{ .str = "image_info", .twain_int = DAT_IMAGEINFO, },
			{ .str = "image_layout", .twain_int = DAT_IMAGELAYOUT, },
			{ .str = "image_memory_transfer", .twain_int = DAT_IMAGEMEMXFER, },
			{ .str = "image_native_transfer", .twain_int = DAT_IMAGENATIVEXFER, },
			{ .str = "image_file_transfer", .twain_int = DAT_IMAGEFILEXFER, },
			{ .str = "cie_color", .twain_int = DAT_CIECOLOR, },
			{ .str = "gray_response", .twain_int = DAT_GRAYRESPONSE, },
			{ .str = "rgb_response", .twain_int = DAT_RGBRESPONSE, },
			{ .str = "jpeg_compression", .twain_int = DAT_JPEGCOMPRESSION, },
			{ .str = "palette_8", .twain_int = DAT_PALETTE8, },
			{ .str = "extra_image_info", .twain_int = DAT_EXTIMAGEINFO, },
			{ .str = "filter", .twain_int = DAT_FILTER, },
			{ .str = "audio_file_transfer", .twain_int = DAT_AUDIOFILEXFER, },
			{ .str = "audio_info", .twain_int = DAT_AUDIOINFO, },
			{ .str = "audio_native_transfer", .twain_int = DAT_AUDIONATIVEXFER, },
			{ .str = "icc_profile", .twain_int = DAT_ICCPROFILE, },
			{ .str = "image_memory_file_transfer", .twain_int = DAT_IMAGEMEMFILEXFER, },
			{ .str = "entrypoint", .twain_int = DAT_ENTRYPOINT, },
			{ .eol = 1 },
		},
	},
	{
		.name = "double_feed_detection",
		.id = CAP_DOUBLEFEEDDETECTION,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "ultrasonic", .twain_int = TWDF_ULTRASONIC, },
			{ .str = "bylength", .twain_int = TWDF_BYLENGTH, },
			{ .str = "infrared", .twain_int = TWDF_INFRARED, },
			{ .eol = 1 },
		},
	},
	{
		.name = "double_feed_detection_length",
		.id = CAP_DOUBLEFEEDDETECTIONLENGTH,
		.readonly = FALSE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "double_feed_detection_sensitivity",
		.id = CAP_DOUBLEFEEDDETECTIONSENSITIVITY,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "low", .twain_int = TWUS_LOW, },
			{ .str = "medium", .twain_int = TWUS_MEDIUM, },
			{ .str = "high", .twain_int = TWUS_HIGH, },
			{ .eol = 1 },
		},
	},
	{
		.name = "double_feed_detection_response",
		.id = CAP_DOUBLEFEEDDETECTIONRESPONSE,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "stop", .twain_int = TWDP_STOP, },
			{ .str = "stop_and_wait", .twain_int = TWDP_STOPANDWAIT, },
			{ .str = "sound", .twain_int = TWDP_SOUND, },
			{ .str = "do_not_imprint", .twain_int = TWDP_DONOTIMPRINT, },
			{ .eol = 1 },
		},
	},
	{
		.name = "paper_handling",
		.id = CAP_PAPERHANDLING,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "normal", .twain_int = TWPH_NORMAL, },
			{ .str = "fragile", .twain_int = TWPH_FRAGILE, },
			{ .str = "thick", .twain_int = TWPH_THICK, },
			{ .str = "trifold", .twain_int = TWPH_TRIFOLD, },
			{ .str = "photograph", .twain_int = TWPH_PHOTOGRAPH, },
			{ .eol = 1 },
		},
	},
	{
		.name = "indicators_mode",
		.id = CAP_INDICATORSMODE,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "info", .twain_int = TWCI_INFO, },
			{ .str = "warning", .twain_int = TWCI_WARNING, },
			{ .str = "error", .twain_int = TWCI_ERROR, },
			{ .str = "warmup", .twain_int = TWCI_WARMUP, },
			{ .eol = 1 },
		},
	},
	{
		.name = "printer_vertical_offset",
		.id = CAP_PRINTERVERTICALOFFSET,
		.readonly = FALSE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "power_save_time",
		.id = CAP_POWERSAVETIME,
		.readonly = FALSE,
		.type = TWTY_INT32,
		.possibles = NULL,
	},
	{
		.name = "printer_char_rotation",
		.id = CAP_PRINTERCHARROTATION,
		.readonly = FALSE,
		.type = TWTY_UINT32,
		.possibles = NULL,
	},
	{
		.name = "printer_font_style",
		.id = CAP_PRINTERFONTSTYLE,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "normal", .twain_int = TWPF_NORMAL, },
			{ .str = "italic", .twain_int = TWPF_ITALIC, },
			{ .str = "bold", .twain_int = TWPF_BOLD, },
			{ .str = "small_size", .twain_int = TWPF_SMALLSIZE, },
			{ .str = "large_size", .twain_int = TWPF_LARGESIZE, },
			{ .eol = 1 },
		},
	},
	{
		.name = "printer_index_lead_char",
		.id = CAP_PRINTERINDEXLEADCHAR,
		.readonly = FALSE,
		.type = TWTY_STR32,
		.possibles = NULL,
	},
	{
		.name = "printer_index_max_value",
		.id = CAP_PRINTERINDEXMAXVALUE,
		.readonly = FALSE,
		.type = TWTY_UINT32,
		.possibles = NULL,
	},
	{
		.name = "printer_index_num_digits",
		.id = CAP_PRINTERINDEXNUMDIGITS,
		.readonly = FALSE,
		.type = TWTY_UINT32,
		.possibles = NULL,
	},
	{
		.name = "printer_index_step",
		.id = CAP_PRINTERINDEXSTEP,
		.readonly = FALSE,
		.type = TWTY_UINT32,
		.possibles = NULL,
	},
	{
		.name = "printer_index_trigger",
		.id = CAP_PRINTERINDEXTRIGGER,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = NULL,
	},
	{
		.name = "printer_string_preview",
		.id = CAP_PRINTERSTRINGPREVIEW,
		.readonly = TRUE,
		.type = TWTY_STR255,
		.possibles = NULL,
	},
	{
		.name = "sheet_count",
		.id = CAP_SHEETCOUNT,
		.readonly = FALSE,
		.type = TWTY_UINT32,
		.possibles = NULL,
	},
	{
		.name = "autobright",
		.id = ICAP_AUTOBRIGHT,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "brightness",
		.id = ICAP_BRIGHTNESS,
		.readonly = FALSE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "contrast",
		.id = ICAP_CONTRAST,
		.readonly = FALSE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "custom_halftone",
		.id = ICAP_CUSTHALFTONE,
		.readonly = FALSE,
		.type = TWTY_UINT8,
		.possibles = NULL,
	},
	{
		.name = "exposure_time",
		.id = ICAP_EXPOSURETIME,
		.readonly = FALSE,
		.type = TWTY_FIX32, /* s */
		.possibles = NULL,
	},
	{
		.name = "filter",
		.id = ICAP_FILTER,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "red", .twain_int = TWFT_RED, },
			{ .str = "green", .twain_int = TWFT_GREEN, },
			{ .str = "blue", .twain_int = TWFT_BLUE, },
			{ .str = "none", .twain_int = TWFT_NONE, },
			{ .str = "white", .twain_int = TWFT_WHITE, },
			{ .str = "cyan", .twain_int = TWFT_CYAN, },
			{ .str = "magenta", .twain_int = TWFT_MAGENTA, },
			{ .str = "yellow", .twain_int = TWFT_YELLOW, },
			{ .str = "black", .twain_int = TWFT_BLACK, },
			{ .eol = 1 },
		},
	},
	{
		.name = "flash_used",
		.id = ICAP_FLASHUSED,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "gamma",
		.id = ICAP_GAMMA,
		.readonly = FALSE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "halftones",
		.id = ICAP_HALFTONES,
		.readonly = FALSE,
		.type = TWTY_STR32,
		.possibles = NULL,
	},
	{
		.name = "highlight",
		.id = ICAP_HIGHLIGHT,
		.readonly = FALSE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "image_file_format",
		.id = ICAP_IMAGEFILEFORMAT,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "tiff", .twain_int = TWFF_TIFF, },
			{ .str = "pict", .twain_int = TWFF_PICT, },
			{ .str = "bmp", .twain_int = TWFF_BMP, },
			{ .str = "xbm", .twain_int = TWFF_XBM, },
			{ .str = "jfif", .twain_int = TWFF_JFIF, },
			{ .str = "fpx", .twain_int = TWFF_FPX, },
			{ .str = "tiff_multi", .twain_int = TWFF_TIFFMULTI, },
			{ .str = "png", .twain_int = TWFF_PNG, },
			{ .str = "spiff", .twain_int = TWFF_SPIFF, },
			{ .str = "exif", .twain_int = TWFF_EXIF, },
			{ .str = "pdf", .twain_int = TWFF_PDF, },
			{ .str = "jp2", .twain_int = TWFF_JP2, },
			{ .str = "jpx", .twain_int = TWFF_JPX, },
			{ .str = "dejavu", .twain_int = TWFF_DEJAVU, },
			{ .str = "pdfa", .twain_int = TWFF_PDFA, },
			{ .str = "pdfa2", .twain_int = TWFF_PDFA2, },
			{ .str = "pdf_raster", .twain_int = TWFF_PDFRASTER, },
			{ .eol = 1 },
		},
	},
	{
		.name = "lamp_state",
		.id = ICAP_LAMPSTATE,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "light_source",
		.id = ICAP_LIGHTSOURCE,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "red", .twain_int = TWLS_RED, },
			{ .str = "green", .twain_int = TWLS_GREEN, },
			{ .str = "blue", .twain_int = TWLS_BLUE, },
			{ .str = "none", .twain_int = TWLS_NONE, },
			{ .str = "white", .twain_int = TWLS_WHITE, },
			{ .str = "ultraviolet", .twain_int = TWLS_UV, },
			{ .str = "infrared", .twain_int = TWLS_IR, },
			{ .eol = 1 },
		},
	},
	{
		.name = "orientation",
		.id = ICAP_ORIENTATION,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "0", .twain_int = TWOR_ROT0, },
			{ .str = "90", .twain_int = TWOR_ROT90, },
			{ .str = "180", .twain_int = TWOR_ROT180, },
			{ .str = "270", .twain_int = TWOR_ROT270, },
			{ .str = "portrait", .twain_int = TWOR_PORTRAIT, },
			{ .str = "landscape", .twain_int = TWOR_LANDSCAPE, },
			{ .eol = 1 },
		},
	},
	{
		.name = "physical_width",
		.id = ICAP_PHYSICALWIDTH,
		.readonly = TRUE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "physical_height",
		.id = ICAP_PHYSICALHEIGHT,
		.readonly = TRUE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "shadow",
		.id = ICAP_SHADOW,
		.readonly = FALSE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "frames",
		.id = ICAP_FRAMES,
		.readonly = FALSE,
		.type = TWTY_FRAME,
		.possibles = NULL,
	},
	{
		.name = "x_native_resolution",
		.id = ICAP_XNATIVERESOLUTION,
		.readonly = TRUE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "y_native_resolution",
		.id = ICAP_YNATIVERESOLUTION,
		.readonly = TRUE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "x_resolution",
		.id = ICAP_XRESOLUTION,
		.readonly = FALSE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "y_resolution",
		.id = ICAP_YRESOLUTION,
		.readonly = FALSE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "max_frames",
		.id = ICAP_MAXFRAMES,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = NULL,
	},
	{
		.name = "tiles",
		.id = ICAP_TILES,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "bit_order",
		.id = ICAP_BITORDER,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = NULL,
	},
	{
		.name = "ccitt_k_factor",
		.id = ICAP_CCITTKFACTOR,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = NULL,
	},
	{
		.name = "light_path",
		.id = ICAP_LIGHTPATH,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = NULL,
	},
	{
		.name = "pixel_flavor",
		.id = ICAP_PIXELFLAVOR,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = NULL,
	},
	{
		.name = "planar_chunky",
		.id = ICAP_PLANARCHUNKY,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "chunky", .twain_int = TWPC_CHUNKY, },
			{ .str = "planar", .twain_int = TWPC_PLANAR, },
			{ .eol = 1 },
		},
	},
	{
		.name = "rotation",
		.id = ICAP_ROTATION,
		.readonly = FALSE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "supported_sizes",
		.id = ICAP_SUPPORTEDSIZES,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "none", .twain_int = TWSS_NONE, },
			{ .str = "a4", .twain_int = TWSS_A4, },
			{ .str = "jis_b5", .twain_int = TWSS_JISB5, },
			{ .str = "us_letter", .twain_int = TWSS_USLETTER, },
			{ .str = "us_legal", .twain_int = TWSS_USLEGAL, },
			{ .str = "a5", .twain_int = TWSS_A5, },
			{ .str = "iso_b4", .twain_int = TWSS_ISOB4, },
			{ .str = "iso_b6", .twain_int = TWSS_ISOB6, },
			{ .str = "us_ledger", .twain_int = TWSS_USLEDGER, },
			{ .str = "us_executive", .twain_int = TWSS_USEXECUTIVE, },
			{ .str = "a3", .twain_int = TWSS_A3, },
			{ .str = "iso_b3", .twain_int = TWSS_ISOB3, },
			{ .str = "a6", .twain_int = TWSS_A6, },
			{ .str = "c4", .twain_int = TWSS_C4, },
			{ .str = "c5", .twain_int = TWSS_C5, },
			{ .str = "c6", .twain_int = TWSS_C6, },
			{ .str = "4a0", .twain_int = TWSS_4A0, },
			{ .str = "2a0", .twain_int = TWSS_2A0, },
			{ .str = "a0", .twain_int = TWSS_A0, },
			{ .str = "a1", .twain_int = TWSS_A1, },
			{ .str = "a2", .twain_int = TWSS_A2, },
			{ .str = "a7", .twain_int = TWSS_A7, },
			{ .str = "a8", .twain_int = TWSS_A8, },
			{ .str = "a9", .twain_int = TWSS_A9, },
			{ .str = "a10", .twain_int = TWSS_A10, },
			{ .str = "iso_b0", .twain_int = TWSS_ISOB0, },
			{ .str = "iso_b1", .twain_int = TWSS_ISOB1, },
			{ .str = "iso_b2", .twain_int = TWSS_ISOB2, },
			{ .str = "iso_b5", .twain_int = TWSS_ISOB5, },
			{ .str = "iso_b7", .twain_int = TWSS_ISOB7, },
			{ .str = "iso_b8", .twain_int = TWSS_ISOB8, },
			{ .str = "iso_b9", .twain_int = TWSS_ISOB9, },
			{ .str = "iso_b10", .twain_int = TWSS_ISOB10, },
			{ .str = "jis_b0", .twain_int = TWSS_JISB0, },
			{ .str = "jis_b1", .twain_int = TWSS_JISB1, },
			{ .str = "jis_b2", .twain_int = TWSS_JISB2, },
			{ .str = "jis_b3", .twain_int = TWSS_JISB3, },
			{ .str = "jis_b4", .twain_int = TWSS_JISB4, },
			{ .str = "jis_b6", .twain_int = TWSS_JISB6, },
			{ .str = "jis_b7", .twain_int = TWSS_JISB7, },
			{ .str = "jis_b8", .twain_int = TWSS_JISB8, },
			{ .str = "jis_b9", .twain_int = TWSS_JISB9, },
			{ .str = "jis_b10", .twain_int = TWSS_JISB10, },
			{ .str = "c0", .twain_int = TWSS_C0, },
			{ .str = "c1", .twain_int = TWSS_C1, },
			{ .str = "c2", .twain_int = TWSS_C2, },
			{ .str = "c3", .twain_int = TWSS_C3, },
			{ .str = "c7", .twain_int = TWSS_C7, },
			{ .str = "c8", .twain_int = TWSS_C8, },
			{ .str = "c9", .twain_int = TWSS_C9, },
			{ .str = "c10", .twain_int = TWSS_C10, },
			{ .str = "us_statement", .twain_int = TWSS_USSTATEMENT, },
			{ .str = "business_card", .twain_int = TWSS_BUSINESSCARD, },
			{ .str = "max_size", .twain_int = TWSS_MAXSIZE, },
			{ .eol = 1 },
		},
	},
	{
		.name = "threshold",
		.id = ICAP_THRESHOLD,
		.readonly = FALSE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "x_scaling",
		.id = ICAP_XSCALING,
		.readonly = FALSE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "y_scaling",
		.id = ICAP_YSCALING,
		.readonly = FALSE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "bit_order_codes",
		.id = ICAP_BITORDERCODES,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = NULL,
	},
	{
		.name = "pixel_flavor_codes",
		.id = ICAP_PIXELFLAVORCODES,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "chocolate", .twain_int = TWPF_CHOCOLATE, },
			{ .str = "vanilla", .twain_int = TWPF_VANILLA, },
			{ .eol = 1 },
		},
	},
	{
		.name = "jpeg_pixel_type",
		.id = ICAP_JPEGPIXELTYPE,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = g_twain_possible_pixel_types,
	},
	{
		.name = "time_fill",
		.id = ICAP_TIMEFILL,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = NULL,
	},
	{
		.name = "bit_depth",
		.id = ICAP_BITDEPTH,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = NULL,
	},
	{
		.name = "bit_depth_reduction",
		.id = ICAP_BITDEPTHREDUCTION,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "threshold", .twain_int = TWBR_THRESHOLD, },
			{ .str = "halftone", .twain_int = TWBR_HALFTONE, },
			{ .str = "custom_halftone", .twain_int = TWBR_CUSTHALFTONE, },
			{ .str = "diffusion", .twain_int = TWBR_DIFFUSION, },
			{ .str = "dynamic_threshold", .twain_int = TWBR_DYNAMICTHRESHOLD, },
			{ .eol = 1 },
		},
	},
	{
		.name = "undefined_image_size",
		.id = ICAP_UNDEFINEDIMAGESIZE,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "image_data_set",
		.id = ICAP_IMAGEDATASET,
		.readonly = FALSE,
		.type = TWTY_UINT32,
		.possibles = NULL,
	},
	{
		.name = "extra_image_info",
		.id = ICAP_EXTIMAGEINFO,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "minimum_height",
		.id = ICAP_MINIMUMHEIGHT,
		.readonly = TRUE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "minimum_width",
		.id = ICAP_MINIMUMWIDTH,
		.readonly = TRUE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "autodiscard_blank_pages",
		.id = ICAP_AUTODISCARDBLANKPAGES,
		.readonly = FALSE,
		.type = TWTY_INT32,
		.possibles = NULL,
	},
	{
		.name = "flip_rotation",
		.id = ICAP_FLIPROTATION,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "book", .twain_int = TWFR_BOOK, },
			{ .str = "fanfold", .twain_int = TWFR_FANFOLD, },
			{ .eol = 1 },
		},
	},
	{
		.name = "barcode_detection_enabled",
		.id = ICAP_BARCODEDETECTIONENABLED,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "supported_barcode_types",
		.id = ICAP_SUPPORTEDBARCODETYPES,
		.readonly = TRUE,
		.type = TWTY_UINT16,
		.possibles = g_twain_possible_barcodes,
	},
	{
		.name = "barcode_max_search_priorities",
		.id = ICAP_BARCODEMAXSEARCHPRIORITIES,
		.readonly = FALSE,
		.type = TWTY_UINT32,
		.possibles = NULL,
	},
	{
		.name = "barcode_search_priorities",
		.id = ICAP_BARCODESEARCHPRIORITIES,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = g_twain_possible_barcodes,
	},
	{
		.name = "barcode_search_mode",
		.id = ICAP_BARCODESEARCHMODE,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = g_twain_possible_orientations,
	},
	{
		.name = "barcode_max_retries",
		.id = ICAP_BARCODEMAXRETRIES,
		.readonly = FALSE,
		.type = TWTY_UINT32,
		.possibles = NULL,
	},
	{
		.name = "barcode_timeout",
		.id = ICAP_BARCODETIMEOUT,
		.readonly = FALSE,
		.type = TWTY_UINT32,
		.possibles = NULL,
	},
	{
		.name = "zoom_factor",
		.id = ICAP_ZOOMFACTOR,
		.readonly = FALSE,
		.type = TWTY_INT16,
		.possibles = NULL,
	},
	{
		.name = "patch_code_detection_enabled",
		.id = ICAP_PATCHCODEDETECTIONENABLED,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "supported_patch_code_types",
		.id = ICAP_SUPPORTEDPATCHCODETYPES,
		.readonly = TRUE,
		.type = TWTY_UINT16,
		.possibles = g_twain_possible_patchcode,
	},
	{
		.name = "patch_code_max_search_priorities",
		.id = ICAP_PATCHCODEMAXSEARCHPRIORITIES,
		.readonly = FALSE,
		.type = TWTY_UINT32,
		.possibles = NULL,
	},
	{
		.name = "patch_code_search_priorities",
		.id = ICAP_PATCHCODESEARCHPRIORITIES,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = g_twain_possible_patchcode,
	},
	{
		.name = "patch_code_search_mode",
		.id = ICAP_PATCHCODESEARCHMODE,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = g_twain_possible_orientations,
	},
	{
		.name = "patch_code_max_retries",
		.id = ICAP_PATCHCODEMAXRETRIES,
		.readonly = FALSE,
		.type = TWTY_UINT32,
		.possibles = NULL,
	},
	{
		.name = "patch_code_timeout",
		.id = ICAP_PATCHCODETIMEOUT,
		.readonly = FALSE,
		.type = TWTY_UINT32,
		.possibles = NULL,
	},
	{
		.name = "flash_used_2",
		.id = ICAP_FLASHUSED2,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "none", .twain_int = TWFL_NONE, },
			{ .str = "off", .twain_int = TWFL_OFF, },
			{ .str = "on", .twain_int = TWFL_ON, },
			{ .str = "auto", .twain_int = TWFL_AUTO, },
			{ .str = "red_eye", .twain_int = TWFL_REDEYE, },
			{ .eol = 1 },
		},
	},
	{
		.name = "image_filter",
		.id = ICAP_IMAGEFILTER,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "none", .twain_int = TWIF_NONE, },
			{ .str = "auto", .twain_int = TWIF_AUTO, },
			{ .str = "lowpass", .twain_int = TWIF_LOWPASS, },
			{ .str = "bandpass", .twain_int = TWIF_BANDPASS, },
			{ .str = "highpass", .twain_int = TWIF_HIGHPASS, },
			{ .str = "text", .twain_int = TWIF_TEXT, },
			{ .str = "fine_line", .twain_int = TWIF_FINELINE, },
			{ .eol = 1 },
		},
	},
	{
		.name = "noise_filter",
		.id = ICAP_NOISEFILTER,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "none", .twain_int = TWNF_NONE, },
			{ .str = "auto", .twain_int = TWNF_AUTO, },
			{ .str = "lone_pixel", .twain_int = TWNF_LONEPIXEL, },
			{ .str = "majority_rule", .twain_int = TWNF_MAJORITYRULE, },
			{ .eol = 1 },
		},
	},
	{
		.name = "overscan",
		.id = ICAP_OVERSCAN,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "none", .twain_int = TWOV_NONE, },
			{ .str = "auto", .twain_int = TWOV_AUTO, },
			{ .str = "top_bottom", .twain_int = TWOV_TOPBOTTOM, },
			{ .str = "left_right", .twain_int = TWOV_LEFTRIGHT, },
			{ .str = "all", .twain_int = TWOV_ALL, },
			{ .eol = 1 },
		},
	},
	{
		.name = "automatic_border_detection",
		.id = ICAP_AUTOMATICBORDERDETECTION,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "automatic_deskew",
		.id = ICAP_AUTOMATICDESKEW,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "automatic_rotate",
		.id = ICAP_AUTOMATICROTATE,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "jpeg_quality",
		.id = ICAP_JPEGQUALITY,
		.readonly = FALSE,
		.type = TWTY_INT16,
		.possibles = NULL,
	},
	{
		.name = "feeder_type",
		.id = ICAP_FEEDERTYPE,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "general", .twain_int = TWFE_GENERAL, },
			{ .str = "photo", .twain_int = TWFE_PHOTO, },
			{ .eol = 1 },
		},
	},
	{
		.name = "icc_profile",
		.id = ICAP_ICCPROFILE,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "none", .twain_int = TWIC_NONE, },
			{ .str = "embed", .twain_int = TWIC_EMBED, },
			{ .str = "link", .twain_int = TWIC_LINK, },
			{ .eol = 1 },
		},
	},
	{
		.name = "autosize",
		.id = ICAP_AUTOSIZE,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "none", .twain_int = TWAS_NONE, },
			{ .str = "auto", .twain_int = TWAS_AUTO, },
			{ .str = "current", .twain_int = TWAS_CURRENT, },
			{ .eol = 1 },
		},
	},
	{
		.name = "automatic_crop_uses_frame",
		.id = ICAP_AUTOMATICCROPUSESFRAME,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "automatic_length_detection",
		.id = ICAP_AUTOMATICLENGTHDETECTION,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "automatic_color_enabled",
		.id = ICAP_AUTOMATICCOLORENABLED,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "automatic_color_noncolor_pixel_type",
		.id = ICAP_AUTOMATICCOLORNONCOLORPIXELTYPE,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "black_white", .twain_int = TWPT_BW, },
			{ .str = "gray", .twain_int = TWPT_GRAY, },
			{ .eol = 1 },
		},
	},
	{
		.name = "color_management_enabled",
		.id = ICAP_COLORMANAGEMENTENABLED,
		.readonly = FALSE,
		.type = TWTY_BOOL,
		.possibles = g_twain_boolean,
	},
	{
		.name = "image_merge",
		.id = ICAP_IMAGEMERGE,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "none", .twain_int = TWIM_NONE, },
			{ .str = "front_on_top", .twain_int = TWIM_FRONTONTOP, },
			{ .str = "front_on_bottom", .twain_int = TWIM_FRONTONBOTTOM, },
			{ .str = "front_on_left", .twain_int = TWIM_FRONTONLEFT, },
			{ .str = "front_on_right", .twain_int = TWIM_FRONTONRIGHT, },
			{ .eol = 1 },
		},
	},
	{
		.name = "image_merge_height_threshold",
		.id = ICAP_IMAGEMERGEHEIGHTTHRESHOLD,
		.readonly = FALSE,
		.type = TWTY_FIX32,
		.possibles = NULL,
	},
	{
		.name = "supported_extra_image_info",
		.id = ICAP_SUPPORTEDEXTIMAGEINFO,
		.readonly = TRUE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "barcode_x", .twain_int = TWEI_BARCODEX, },
			{ .str = "barcode_y", .twain_int = TWEI_BARCODEY, },
			{ .str = "barcode_text", .twain_int = TWEI_BARCODETEXT, },
			{ .str = "barcode_type", .twain_int = TWEI_BARCODETYPE, },
			{ .str = "deshade_top", .twain_int = TWEI_DESHADETOP, },
			{ .str = "deshade_left", .twain_int = TWEI_DESHADELEFT, },
			{ .str = "deshade_height", .twain_int = TWEI_DESHADEHEIGHT, },
			{ .str = "deshade_width", .twain_int = TWEI_DESHADEWIDTH, },
			{ .str = "deshade_size", .twain_int = TWEI_DESHADESIZE, },
			{ .str = "speckles_removed", .twain_int = TWEI_SPECKLESREMOVED, },
			{ .str = "horizontal_line_x_coord", .twain_int = TWEI_HORZLINEXCOORD, },
			{ .str = "horizontal_line_y_coord", .twain_int = TWEI_HORZLINEYCOORD, },
			{ .str = "horizontal_line_length", .twain_int = TWEI_HORZLINELENGTH, },
			{ .str = "horizontal_line_thickness", .twain_int = TWEI_HORZLINETHICKNESS, },
			{ .str = "vertical_line_x_coord", .twain_int = TWEI_VERTLINEXCOORD, },
			{ .str = "vertical_line_y_coord", .twain_int = TWEI_VERTLINEYCOORD, },
			{ .str = "vertical_line_length", .twain_int = TWEI_VERTLINELENGTH, },
			{ .str = "vertical_line_thickness", .twain_int = TWEI_VERTLINETHICKNESS, },
			{ .str = "patch_code", .twain_int = TWEI_PATCHCODE, },
			{ .str = "endorsed_text", .twain_int = TWEI_ENDORSEDTEXT, },
			{ .str = "form_confidence", .twain_int = TWEI_FORMCONFIDENCE, },
			{ .str = "form_template_match", .twain_int = TWEI_FORMTEMPLATEMATCH, },
			{ .str = "form_template_page_match", .twain_int = TWEI_FORMTEMPLATEPAGEMATCH, },
			{ .str = "form_horizontal_doc_offset", .twain_int = TWEI_FORMHORZDOCOFFSET, },
			{ .str = "form_vertical_doc_offset", .twain_int = TWEI_FORMVERTDOCOFFSET, },
			{ .str = "barcode_count", .twain_int = TWEI_BARCODECOUNT, },
			{ .str = "barcode_confidence", .twain_int = TWEI_BARCODECONFIDENCE, },
			{ .str = "barcode_rotation", .twain_int = TWEI_BARCODEROTATION, },
			{ .str = "barcode_text_length", .twain_int = TWEI_BARCODETEXTLENGTH, },
			{ .str = "deshade_count", .twain_int = TWEI_DESHADECOUNT, },
			{ .str = "deshade_black_count_old", .twain_int = TWEI_DESHADEBLACKCOUNTOLD, },
			{ .str = "deshade_black_count_new", .twain_int = TWEI_DESHADEBLACKCOUNTNEW, },
			{ .str = "deshade_black_rl_min", .twain_int = TWEI_DESHADEBLACKRLMIN, },
			{ .str = "deshade_black_rl_max", .twain_int = TWEI_DESHADEBLACKRLMAX, },
			{ .str = "deshade_white_count_old", .twain_int = TWEI_DESHADEWHITECOUNTOLD, },
			{ .str = "deshade_white_count_new", .twain_int = TWEI_DESHADEWHITECOUNTNEW, },
			{ .str = "deshade_white_rl_min", .twain_int = TWEI_DESHADEWHITERLMIN, },
			{ .str = "deshade_white_rl_average", .twain_int = TWEI_DESHADEWHITERLAVE, },
			{ .str = "deshade_white_rl_max", .twain_int = TWEI_DESHADEWHITERLMAX, },
			{ .str = "black_speckles_removed", .twain_int = TWEI_BLACKSPECKLESREMOVED, },
			{ .str = "white_speckles_removed", .twain_int = TWEI_WHITESPECKLESREMOVED, },
			{ .str = "horizontal_line_count", .twain_int = TWEI_HORZLINECOUNT, },
			{ .str = "vertical_line_count", .twain_int = TWEI_VERTLINECOUNT, },
			{ .str = "deskew_status", .twain_int = TWEI_DESKEWSTATUS, },
			{ .str = "skew_original_angle", .twain_int = TWEI_SKEWORIGINALANGLE, },
			{ .str = "skew_final_angle", .twain_int = TWEI_SKEWFINALANGLE, },
			{ .str = "skew_confidence", .twain_int = TWEI_SKEWCONFIDENCE, },
			{ .str = "skew_window_x_1", .twain_int = TWEI_SKEWWINDOWX1, },
			{ .str = "skew_window_y_1", .twain_int = TWEI_SKEWWINDOWY1, },
			{ .str = "skew_window_x_2", .twain_int = TWEI_SKEWWINDOWX2, },
			{ .str = "skew_window_y_2", .twain_int = TWEI_SKEWWINDOWY2, },
			{ .str = "skew_window_x_3", .twain_int = TWEI_SKEWWINDOWX3, },
			{ .str = "skew_window_y_3", .twain_int = TWEI_SKEWWINDOWY3, },
			{ .str = "skew_window_x_4", .twain_int = TWEI_SKEWWINDOWX4, },
			{ .str = "skew_window_y_4", .twain_int = TWEI_SKEWWINDOWX4, },
			{ .str = "book_name", .twain_int = TWEI_BOOKNAME, },
			{ .str = "chapter_number", .twain_int = TWEI_CHAPTERNUMBER, },
			{ .str = "document_number", .twain_int = TWEI_DOCUMENTNUMBER, },
			{ .str = "page_number", .twain_int = TWEI_PAGENUMBER, },
			{ .str = "camera", .twain_int = TWEI_CAMERA, },
			{ .str = "frame_number", .twain_int = TWEI_FRAMENUMBER, },
			{ .str = "frame", .twain_int = TWEI_FRAME, },
			{ .str = "pixel_flavor", .twain_int = TWEI_PIXELFLAVOR, },
			{ .str = "icc_profile", .twain_int = TWEI_ICCPROFILE, },
			{ .str = "last_segment", .twain_int = TWEI_LASTSEGMENT, },
			{ .str = "segment_number", .twain_int = TWEI_SEGMENTNUMBER, },
			{ .str = "mag_data", .twain_int = TWEI_MAGDATA, },
			{ .str = "mag_type", .twain_int = TWEI_MAGTYPE, },
			{ .str = "page_side", .twain_int = TWEI_PAGESIDE, },
			{ .str = "filesystem_source", .twain_int = TWEI_FILESYSTEMSOURCE, },
			{ .str = "image_merged", .twain_int = TWEI_IMAGEMERGED, },
			{ .str = "mag_data_length", .twain_int = TWEI_MAGDATALENGTH, },
			{ .str = "paper_count", .twain_int = TWEI_PAPERCOUNT, },
			{ .str = "printer_text", .twain_int = TWEI_PRINTERTEXT, },
			{ .str = "twain_direct_metadata", .twain_int = TWEI_TWAINDIRECTMETADATA, },
			{ .eol = 1 },
		},
	},
	{
		.name = "film_type",
		.id = ICAP_FILMTYPE,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "positive", .twain_int = TWFM_POSITIVE, },
			{ .str = "negative", .twain_int = TWFM_NEGATIVE, },
			{ .eol = 1 },
		},
	},
	{
		.name = "mirror",
		.id = ICAP_MIRROR,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "none", .twain_int = TWMR_NONE, },
			{ .str = "vertical", .twain_int = TWMR_VERTICAL, },
			{ .str = "horizontal", .twain_int = TWMR_HORIZONTAL, },
			{ .eol = 1 },
		},
	},
	{
		.name = "jpeg_subsampling",
		.id = ICAP_JPEGSUBSAMPLING,
		.readonly = FALSE,
		.type = TWTY_UINT16,
		.possibles = (struct lis_twain_cap_possible[]) {
			{ .str = "444_ycbcr", .twain_int = TWJS_444YCBCR, },
			{ .str = "444_rgb", .twain_int = TWJS_444RGB, },
			{ .str = "422", .twain_int = TWJS_422, },
			{ .str = "421", .twain_int = TWJS_421, },
			{ .str = "411", .twain_int = TWJS_411, },
			{ .str = "420", .twain_int = TWJS_420, },
			{ .str = "410", .twain_int = TWJS_410, },
			{ .str = "311", .twain_int = TWJS_311, },
			{ .eol = 1 },
		},
	},
	/* XXX(JFlesch): undocumented / obsolete ?
	{
		.name = "clear_buffers",
		.id = CAP_CLEARBUFFERS,
		.type = TWTY_UINT16,
		.possibles = NULL,
	},
	{
		.name = "supported_caps_extra",
		.id = CAP_SUPPORTEDCAPSEXT,
		.type = TWTY_UINT16,
		.possibles = NULL,
	},
	{
		.name = "page_multiple_acquire",
		.id = CAP_PAGEMULTIPLEACQUIRE,
		.type = TWTY_UINT16,
		.possibles = NULL,
	},
	{
		.name = "paper_binding",
		.id = CAP_PAPERBINDING,
		.type = TWTY_UINT16,
		.possibles = NULL,
	},
	{
		.name = "passthrough",
		.id = CAP_PASSTHRU,
		.type = TWTY_UINT16,
		.possibles = NULL,
	},
	{
		.name = "power_downtime",
		.id = CAP_POWERDOWNTIME,
		.type = TWTY_UINT16,
		.possibles = NULL,
	},
	*/
};


const struct lis_twain_cap *lis_twain_get_all_caps(int *nb_caps) {
	*nb_caps = LIS_COUNT_OF(g_twain_caps);
	return g_twain_caps;
}
