diff --git a/ChangeLog b/ChangeLog index e58f05f76..5aefb51e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2002-08-08 Lutz Müller + + * configure.in + * camlibs/gsmart: New driver by Till Adam . + 2002-08-01 Hubert Figuiere * libgphoto2/gphoto2-list.c (exchange): changed strcpy with memcpy diff --git a/camlibs/gsmart/ChangeLog b/camlibs/gsmart/ChangeLog new file mode 100644 index 000000000..1498542f3 --- /dev/null +++ b/camlibs/gsmart/ChangeLog @@ -0,0 +1,3 @@ +Mon Aug 05 00:01:06 2002 Till Adam + + * initial release of the module diff --git a/camlibs/gsmart/Makefile.am b/camlibs/gsmart/Makefile.am new file mode 100644 index 000000000..bd96aec59 --- /dev/null +++ b/camlibs/gsmart/Makefile.am @@ -0,0 +1,11 @@ +camlibdir = $(libdir)/gphoto2/$(VERSION) +camlib_LTLIBRARIES = libgphoto2_gsmart.la + +INCLUDES = \ + -I$(top_srcdir)/libgphoto2_port/libgphoto2_port \ + -I$(top_srcdir)/libgphoto2 + +libgphoto2_gsmart_la_SOURCES = gsmart.c gsmart.h library.c \ + gsmart-jpeg-header.h gsmart-registers.h +libgphoto2_gsmart_la_LDFLAGS = -module -avoid-version +libgphoto2_gsmart_la_LIBADD = $(top_builddir)/libgphoto2/libgphoto2.la diff --git a/camlibs/gsmart/README b/camlibs/gsmart/README new file mode 100644 index 000000000..09918e086 --- /dev/null +++ b/camlibs/gsmart/README @@ -0,0 +1,32 @@ +Mustek gSmart mini 2 + +This driver is based on the windows driver source kindly provided by +Mustek. It is known to work with the mini 2 but might very well also work with +other members of the gsmart mini family. I dont have these cameras, so if you +have one and want support for it, you'll have to do it yourself or send +me your camera ;). + +If you want to hack on this module, or have questions or suggestions, +don't hesitate to email me: + + Till Adam + +---------------------------------------------------------------- + +TODO List +--------- + - implement thumbnails for avi files + - implement downloading of avi files + - implement streaming "webcam" mode + +----------------------------------------------------------------- +Thanks +------- +Special thanks go to Bjorn Borud who extorted the above +mentioned sources for the windows driver from Mustek. + +Also thanks to the following people for testing and feedback: + +Torfinn Ingolfsen +Mikael Nilsson + diff --git a/camlibs/gsmart/gsmart-jpeg-header.h b/camlibs/gsmart/gsmart-jpeg-header.h new file mode 100644 index 000000000..a62464c7c --- /dev/null +++ b/camlibs/gsmart/gsmart-jpeg-header.h @@ -0,0 +1,263 @@ +#ifndef __GSMART_JPEG_HEADER_H +#define __GSMART_JPEG_HEADER_H + +/* + * Start from 0 -> 588 + * 7 - 70 : Quantization Table[0] + * 72 - 135 : Quantization Table[1] + * 561 - 562 : Image Height(H Byte,L Byte) + * 563 - 564 : Image Width(H Byte,L Byte) + */ +#define GSMART_JPG_DEFAULT_HEADER_LENGTH 589 +u_int8_t GsmartJPGDefaultHeader[GSMART_JPG_DEFAULT_HEADER_LENGTH] = { + //SOI(Start of Image) + 0xFF,0xD8, + //DQT(Define Quantization Table) + 0xFF,0xDB, + 0x00,0x84, + 0x00, + 0x05,0x03,0x04,0x04,0x04,0x03,0x05,0x04,0x04,0x04,0x06,0x05,0x05,0x06,0x08,0x0D, + 0x08,0x08,0x07,0x07,0x08,0x10,0x0C,0x0C,0x0A,0x0D,0x14,0x11,0x15,0x14,0x13,0x11, + 0x13,0x13,0x16,0x18,0x1F,0x1A,0x16,0x17,0x1E,0x17,0x13,0x13,0x1B,0x25,0x1C,0x1E, + 0x20,0x21,0x23,0x23,0x23,0x15,0x1A,0x27,0x29,0x26,0x22,0x29,0x1F,0x22,0x23,0X22, + 0X01, + 0x05,0x06,0x06,0x08,0x07,0x08,0x10,0x08,0x08,0x10,0x22,0x16,0x13,0x16,0x22,0x22, + 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, + 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, + 0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, + //DHT(Define Huffman Table) + 0xFF,0xC4, + 0x01,0xA2, + 0x00,0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x01,0x00,0x03, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x10,0x00,0x02,0x01,0x03,0x03, + 0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,0x00,0x01,0x7D,0x01,0x02,0x03,0x00,0x04, + 0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81, + 0x91,0xA1,0x08,0x23,0x42,0xB1,0xC1,0x15,0x52,0xD1,0xF0,0x24,0x33,0x62,0x72,0x82, + 0x09,0x0A,0x16,0x17,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,0x29,0x2A,0x34,0x35,0x36, + 0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x53,0x54,0x55,0x56, + 0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x73,0x74,0x75,0x76, + 0x77,0x78,0x79,0x7A,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x92,0x93,0x94,0x95, + 0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xB2,0xB3, + 0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA, + 0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7, + 0xE8,0xE9,0xEA,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0x11,0x00,0x02, + 0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,0x02,0x77,0x00,0x01, + 0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22, + 0x32,0x81,0x08,0x14,0x42,0x91,0xA1,0xB1,0xC1,0x09,0x23,0x33,0x52,0xF0,0x15,0x62, + 0x72,0xD1,0x0A,0x16,0x24,0x34,0xE1,0x25,0xF1,0x17,0x18,0x19,0x1A,0x26,0x27,0x28, + 0x29,0x2A,0x35,0x36,0x37,0x38,0x39,0x3A,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A, + 0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A, + 0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8A,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7, + 0xA8,0xA9,0xAA,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xC2,0xC3,0xC4,0xC5, + 0xC6,0xC7,0xC8,0xC9,0xCA,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xE2,0xE3, + 0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA, + //SOFn(Start of Frame) + 0xFF,0xC0, + 0x00,0x11, + 0x08,0x00,0x78,0x00,0xA0,0x03,0x01,0x21,0x00,0x02,0x11,0x01,0x03,0x11,0x01, + //SOS(Srart of Scan) + 0xFF,0xDA, + 0x00,0x0C, + 0x03,0x01,0x00,0x02,0x11,0x03,0x11,0x00,0x3F,0x00 +}; + +u_int8_t GsmartQTable[20][64]= +{ + // index 0, Q50 + { 16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, 40, + 26, 24, 22, 22, 24, 49, 35, 37, 29, 40, 58, 51, 61, 60, 57, 51, + 56, 55, 64, 72, 92, 78, 64, 68, 87, 69, 55, 56, 80,109, 81, 87, + 95, 98,103,104,103, 62, 77,113,121,112,100,120, 92,101,103, 99 }, + { 17, 18, 18, 24, 21, 24, 47, 26, 26, 47, 99, 66, 56, 66, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 }, + + // index 1, Q70 + { 10, 7, 7, 8, 7, 6, 10, 8, 8, 8, 11, 10, 10, 11, 14, 24, + 16, 14, 13, 13, 14, 29, 21, 22, 17, 24, 35, 31, 37, 36, 34, 31, + 34, 33, 38, 43, 55, 47, 38, 41, 52, 41, 33, 34, 48, 65, 49, 52, + 57, 59, 62, 62, 62, 37, 46, 68, 73, 67, 60, 72, 55, 61, 62, 59 }, + { 10, 11, 11, 14, 13, 14, 28, 16, 16, 28, 59, 40, 34, 40, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59 }, + + // index 2, Q80 + { 6, 4, 5, 6, 5, 4, 6, 6, 5, 6, 7, 7, 6, 8, 10, 16, + 10, 10, 9, 9, 10, 20, 14, 15, 12, 16, 23, 20, 24, 24, 23, 20, + 22, 22, 26, 29, 37, 31, 26, 27, 35, 28, 22, 22, 32, 44, 32, 35, + 38, 39, 41, 42, 41, 25, 31, 45, 48, 45, 40, 48, 37, 40, 41, 40 }, + { 7, 7, 7, 10, 8, 10, 19, 10, 10, 19, 40, 26, 22, 26, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40 }, + + // index 3, Q85 + { 5, 3, 4, 4, 4, 3, 5, 4, 4, 4, 5, 5, 5, 6, 7, 12, + 8, 7, 7, 7, 7, 15, 11, 11, 9, 12, 17, 15, 18, 18, 17, 15, + 17, 17, 19, 22, 28, 23, 19, 20, 26, 21, 17, 17, 24, 33, 24, 26, + 29, 29, 31, 31, 31, 19, 23, 34, 36, 34, 30, 36, 28, 30, 31, 30 }, + { 5, 5, 5, 7, 6, 7, 14, 8, 8, 14, 30, 20, 17, 20, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }, + + // index 4, Q90 + { 3, 2, 2, 3, 2, 2, 3, 3, 3, 3, 4, 3, 3, 4, 5, 8, + 5, 5, 4, 4, 5, 10, 7, 7, 6, 8, 12, 10, 12, 12, 11, 10, + 11, 11, 13, 14, 18, 16, 13, 14, 17, 14, 11, 11, 16, 22, 16, 17, + 19, 20, 21, 21, 21, 12, 15, 23, 24, 22, 20, 24, 18, 20, 21, 20 }, + { 3, 4, 4, 5, 4, 5, 9, 5, 5, 9, 20, 13, 11, 13, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 }, + + // index 5, Q60 + { 13, 9, 10, 11, 10, 8, 13, 11, 10, 11, 14, 14, 13, 15, 19, 32, + 21, 19, 18, 18, 19, 39, 28, 30, 23, 32, 46, 41, 49, 48, 46, 41, + 45, 44, 51, 58, 74, 62, 51, 54, 70, 55, 44, 45, 64, 87, 65, 70, + 76, 78, 82, 83, 82, 50, 62, 90, 97, 90, 80, 96, 74, 81, 82, 79 }, + { 14, 14, 14, 19, 17, 19, 38, 21, 21, 38, 79, 53, 45, 53, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79 }, + + // index 6, Q25 + { 32, 22, 24, 28, 24, 20, 32, 28, 26, 28, 36, 34, 32, 38, 48, 80, + 52, 48, 44, 44, 48, 98, 70, 74, 58, 80,116,102,122,120,114,102, + 112,110,128,144,184,156,128,136,174,138,110,112,160,218,162,174, + 190,196,206,208,206,124,154,226,242,224,200,240,184,202,206,198 }, + { 34, 36, 36, 48, 42, 48, 94, 52, 52, 94,198,132,112,132,198,198, + 198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, + 198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, + 198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198 }, + + // index 7, Q95 + { 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 4, + 3, 2, 2, 2, 2, 5, 4, 4, 3, 4, 6, 5, 6, 6, 6, 5, + 6, 6, 6, 7, 9, 8, 6, 7, 9, 7, 6, 6, 8, 11, 8, 9, + 10, 10, 10, 10, 10, 6, 8, 11, 12, 11, 10, 12, 9, 10, 10, 10 }, + { 2, 2, 2, 2, 2, 2, 5, 3, 3, 5, 10, 7, 6, 7, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 }, + + // index 8, Q93 + { 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 3, 2, 2, 3, 3, 6, + 4, 3, 3, 3, 3, 7, 5, 5, 4, 6, 8, 7, 9, 8, 8, 7, + 8, 8, 9, 10, 13, 11, 9, 10, 12, 10, 8, 8, 11, 15, 11, 12, + 13, 14, 14, 15, 14, 9, 11, 16, 17, 16, 14, 17, 13, 14, 14, 14 }, + { 2, 3, 3, 3, 3, 3, 7, 4, 4, 7, 14, 9, 8, 9, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14 }, + + // index 9, Q40 + { 20, 14, 15, 18, 15, 13, 20, 18, 16, 18, 23, 21, 20, 24, 30, 50, + 33, 30, 28, 28, 30, 61, 44, 46, 36, 50, 73, 64, 76, 75, 71, 64, + 70, 69, 80, 90,115, 98, 80, 85,109, 86, 69, 70,100,136,101,109, + 119,123,129,130,129, 78, 96,141,151,140,125,150,115,126,129,124 }, + { 21, 23, 23, 30, 26, 30, 59, 33, 33, 59,124, 83, 70, 83,124,124, + 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, + 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, + 124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124 } +}; + +u_int8_t GsmartOriginal_QTable_4NF_M[18][64]= //not Z-Z +{ + // index 0, Q50 + { 16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68,109,103, 77, 24, 35, 55, 64, 81,104,113, 92, + 49, 64, 78, 87,103,121,120,101, 72, 92, 95, 98,112,100,103, 99 }, + { 17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 }, + + // index 1, Q70 + { 10, 7, 6, 10, 14, 24, 31, 37, 7, 7, 8, 11, 16, 35, 36, 33, + 8, 8, 10, 14, 24, 34, 41, 34, 8, 10, 13, 17, 31, 52, 48, 37, + 11, 13, 22, 34, 41, 65, 62, 46, 14, 21, 33, 38, 49, 62, 68, 55, + 29, 38, 47, 52, 62, 73, 72, 61, 43, 55, 57, 59, 67, 60, 62, 59 }, + { 10, 11, 14, 28, 59, 59, 59, 59, 11, 13, 16, 40, 59, 59, 59, 59, + 14, 16, 34, 59, 59, 59, 59, 59, 28, 40, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59 }, + + // index 2, Q80 + { 6, 4, 4, 6, 10, 16, 20, 24, 5, 5, 6, 8, 10, 23, 24, 22, + 6, 5, 6, 10, 16, 23, 28, 22, 6, 7, 9, 12, 20, 35, 32, 25, + 7, 9, 15, 22, 27, 44, 41, 31, 10, 14, 22, 26, 32, 42, 45, 37, + 20, 26, 31, 35, 41, 48, 48, 40, 29, 37, 38, 39, 45, 40, 41, 40 }, + { 7, 7, 10, 19, 40, 40, 40, 40, 7, 8, 10, 26, 40, 40, 40, 40, + 10, 10, 22, 40, 40, 40, 40, 40, 19, 26, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40 }, + + // index 3, Q85 + { 5, 3, 3, 5, 7, 12, 15, 18, 4, 4, 4, 6, 8, 17, 18, 17, + 4, 4, 5, 7, 12, 17, 21, 17, 4, 5, 7, 9, 15, 26, 24, 19, + 5, 7, 11, 17, 20, 33, 31, 23, 7, 11, 17, 19, 24, 31, 34, 28, + 15, 19, 23, 26, 31, 36, 36, 30, 22, 28, 29, 29, 34, 30, 31, 30 }, + { 5, 5, 7, 14, 30, 30, 30, 30, 5, 6, 8, 20, 30, 30, 30, 30, + 7, 8, 17, 30, 30, 30, 30, 30, 14, 20, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 }, + + // index 4, Q90 + { 3, 2, 2, 3, 5, 8, 10, 12, 2, 2, 3, 4, 5, 12, 12, 11, + 3, 3, 3, 5, 8, 11, 14, 11, 3, 3, 4, 6, 10, 17, 16, 12, + 4, 4, 7, 11, 14, 22, 21, 15, 5, 7, 11, 13, 16, 21, 23, 18, + 10, 13, 16, 17, 21, 24, 24, 20, 14, 18, 19, 20, 22, 20, 21, 20 }, + { 3, 4, 5, 9, 20, 20, 20, 20, 4, 4, 5, 13, 20, 20, 20, 20, + 5, 5, 11, 20, 20, 20, 20, 20, 9, 13, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 }, + + // index 5, Q60 + { 13, 9, 8, 13, 19, 32, 41, 49, 10, 10, 11, 15, 21, 46, 48, 44, + 11, 10, 13, 19, 32, 46, 55, 45, 11, 14, 18, 23, 41, 70, 64, 50, + 14, 18, 30, 45, 54, 87, 82, 62, 19, 28, 44, 51, 65, 83, 90, 74, + 39, 51, 62, 70, 82, 97, 96, 81, 58, 74, 76, 78, 90, 80, 82, 79 }, + { 14, 14, 19, 38, 79, 79, 79, 79, 14, 17, 21, 53, 79, 79, 79, 79, + 19, 21, 45, 79, 79, 79, 79, 79, 38, 53, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79 }, + + // index 6, Q25 + { 32, 22, 20, 32, 48, 80,102,122, 24, 24, 28, 38, 52,116,120,110, + 28, 26, 32, 48, 80,114,138,112, 28, 34, 44, 58,102,174,160,124, + 36, 44, 74,112,136,218,206,154, 48, 70,110,128,162,208,226,184, + 98,128,156,174,206,242,240,202,144,184,190,196,224,200,206,198 }, + { 34, 36, 48, 94,198,198,198,198, 36, 42, 52,132,198,198,198,198, + 48, 52,112,198,198,198,198,198, 94,132,198,198,198,198,198,198, + 198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198, + 198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198 }, + + // index 7, Q95 + { 2, 1, 1, 2, 2, 4, 5, 6, 1, 1, 1, 2, 3, 6, 6, 6, + 1, 1, 2, 2, 4, 6, 7, 6, 1, 2, 2, 3, 5, 9, 8, 6, + 2, 2, 4, 6, 7, 11, 10, 8, 2, 4, 6, 6, 8, 10, 11, 9, + 5, 6, 8, 9, 10, 12, 12, 10, 7, 9, 10, 10, 11, 10, 10, 10 }, + { 2, 2, 2, 5, 10, 10, 10, 10, 2, 2, 3, 7, 10, 10, 10, 10, + 2, 3, 6, 10, 10, 10, 10, 10, 5, 7, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 }, + + // index 8, Q93 + { 2, 2, 1, 2, 3, 6, 7, 9, 2, 2, 2, 3, 4, 8, 8, 8, + 2, 2, 2, 3, 6, 8, 10, 8, 2, 2, 3, 4, 7, 12, 11, 9, + 3, 3, 5, 8, 10, 15, 14, 11, 3, 5, 8, 9, 11, 15, 16, 13, + 7, 9, 11, 12, 14, 17, 17, 14, 10, 13, 13, 14, 16, 14, 14, 14 }, + { 2, 3, 3, 7, 14, 14, 14, 14, 3, 3, 4, 9, 14, 14, 14, 14, + 3, 4, 8, 14, 14, 14, 14, 14, 7, 9, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14 } +}; + +#endif /* __GSMART_JPEG_HEADER_H */ diff --git a/camlibs/gsmart/gsmart-registers.h b/camlibs/gsmart/gsmart-registers.h new file mode 100644 index 000000000..1463e752c --- /dev/null +++ b/camlibs/gsmart/gsmart-registers.h @@ -0,0 +1,84 @@ +/****************************************************************/ +/* gsmart-registers.h - Gphoto2 library for the Mustek gSmart */ +/* mini 2 */ +/* */ +/* Copyright (C) 2002 Till Adam */ +/* */ +/* Author: Till Adam */ +/* */ +/* This library is free software; you can redistribute it */ +/* and/or modify it under the terms of the GNU Library General */ +/* Public License as published by the Free Software Foundation; */ +/* either version 2 of the License, or (at your option) any */ +/* later version. */ +/* */ +/* This library is distributed in the hope that it will be */ +/* useful, but WITHOUT ANY WARRANTY; without even the implied */ +/* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */ +/* PURPOSE. See the GNU Library General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU Library General */ +/* Public License along with this library; if not, write to the */ +/* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */ +/* Boston, MA 02111-1307, USA. */ +/****************************************************************/ + +#ifndef __GSMART_REGISTERS_H__ +#define __GSMART_REGISTERS_H__ + + +/* ---- Register ---- */ +#define GSMART_REG_CamMode 0x2000 +/* ---- CamMode Value ---- */ +typedef enum +{ + GSMART_CamMode_Idle = 0, + GSMART_CamMode_DSC = 1, + GSMART_CamMode_VideoClip = 2, + GSMART_CamMode_PcCamera = 3, + GSMART_CamMode_Upload = 4 +} +GsmartCamMode; + +#define GSMART_REG_PbSrc 0x2301 +/* ---- PbSrc Value ---- */ +#define GSMART_DramUsb 0x13 + +#define GSMART_REG_AutoPbSize 0x2306 + +#define GSMART_REG_DramType 0x2705 + +#define GSMART_REG_ImageType 0x270c + +#define GSMART_REG_SdramSizeL 0x2710 /* Size [7:0] */ +#define GSMART_REG_SdramSizeM 0x2711 /* Size [15:8] */ +#define GSMART_REG_SdramSizeH 0x2712 /* Size [21:16] */ + +#define GSMART_REG_VlcAddressL 0x2713 +#define GSMART_REG_VlcAddressM 0x2714 +#define GSMART_REG_VlcAddressH 0x2715 + +#define GSMART_REG_MemWidthL 0x2720 +#define GSMART_REG_MemWidthH 0x2721 + +#define GSMART_REG_MemHeightL 0x2722 +#define GSMART_REG_MemHeightH 0x2723 + +#define GSMART_REG_Trigger 0x27a1 +/* ---- Trigger bit Value ---- */ +#define GSMART_TrigDramFifo 2 + +#define GSMART_REG_JFIF 0x2884 + +#define GSMART_REG_CompSizeL 0x2887 +#define GSMART_REG_CompSizeM 0x2888 +#define GSMART_REG_CompSizeH 0x2889 + +#define GSMART_REG_I2C_wIndex 0x2a08 +#define GSMART_REG_I2C_wValue 0x2a10 +#define GSMART_REG_I2C_rValue 0x2a30 +#define GSMART_REG_I2C_rStatus 0x2a06 + + +#endif /* __GSMART_REGISTERS_H__ */ diff --git a/camlibs/gsmart/gsmart.c b/camlibs/gsmart/gsmart.c new file mode 100644 index 000000000..707e7cb33 --- /dev/null +++ b/camlibs/gsmart/gsmart.c @@ -0,0 +1,547 @@ +/****************************************************************/ +/* library.c - Gphoto2 library for the Mustek gSmart mini 2 */ +/* */ +/* Copyright (C) 2002 Till Adam */ +/* */ +/* Author: Till Adam */ +/* */ +/* This library is free software; you can redistribute it */ +/* and/or modify it under the terms of the GNU Library General */ +/* Public License as published by the Free Software Foundation; */ +/* either version 2 of the License, or (at your option) any */ +/* later version. */ +/* */ +/* This library is distributed in the hope that it will be */ +/* useful, but WITHOUT ANY WARRANTY; without even the implied */ +/* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */ +/* PURPOSE. See the GNU Library General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU Library General */ +/* Public License along with this library; if not, write to the */ +/* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */ +/* Boston, MA 02111-1307, USA. */ +/****************************************************************/ +#include + +#include +#include +#include +#include +#include + +#include "gsmart.h" +#include "gsmart-registers.h" +#include "gsmart-jpeg-header.h" + +#ifdef ENABLE_NLS +# include +# undef _ +# define _(String) dgettext (PACKAGE, String) +# ifdef gettext_noop +# define N_(String) gettext_noop (String) +# else +# define N_(String) (String) +# endif +#else +# define textdomain(String) (String) +# define gettext(String) (String) +# define dgettext(Domain,Message) (Message) +# define dcgettext(Domain,Message,Type) (Message) +# define bindtextdomain(Domain,Directory) (Domain) +# define _(String) (String) +# define N_(String) (String) +#endif + +#define GP_MODULE + +static int yuv2rgb (int y, int u, int v, int *r, int *g, int *b); + +int +gsmart_get_file_count (CameraPrivateLibrary * lib) +{ + GP_DEBUG ("* gsmart_get_file_count"); + CHECK (gp_port_usb_msg_write (lib->gpdev, 0x5, 0, 0, NULL, 0)); + sleep (1); + CHECK (gp_port_usb_msg_read + (lib->gpdev, 0, 0, 0xe15, (u_int8_t *) & lib->num_files, 1)); + + GP_DEBUG ("gSmart file count: %d\n", lib->num_files); + + return (GP_OK); +} + +int +gsmart_delete_file (CameraPrivateLibrary * lib, unsigned int index) +{ + struct GsmartFile *g_file; + u_int16_t fat_index; + + GP_DEBUG ("* gsmart_delete_file"); + + CHECK (gsmart_get_file_info (lib, index, &g_file)); + + fat_index = 0xD8000 - g_file->fat_start - 1; + + CHECK (gp_port_usb_msg_write (lib->gpdev, 0x06, fat_index, 0x0007, NULL, 0)); + + /* Reread fats the next time it is accessed */ + lib->dirty = 1; + + return GP_OK; +} + +int +gsmart_delete_all (CameraPrivateLibrary * lib) +{ + GP_DEBUG ("* gsmart_delete_all"); + + CHECK (gp_port_usb_msg_write (lib->gpdev, 0x02, 0x0000, 0x0005, NULL, 0)); + sleep (3); + + /* Reread fats the next time it is accessed */ + lib->dirty = 1; + return GP_OK; +} + +int +gsmart_request_file (CameraPrivateLibrary * lib, u_int8_t ** buf, unsigned int *len, + unsigned int number) +{ + struct GsmartFile *g_file; + u_int8_t *p, *lp_jpg, *start_of_file; + u_int8_t qIndex, quality, value; + u_int32_t start; + u_int8_t *mybuf; + int size, o_size, i, file_size; + int f_counter = 0; + + GP_DEBUG ("* gsmart_request_file"); + + CHECK (gsmart_get_file_info (lib, number, &g_file)); + /* FIXME implement avi downloading */ + if (g_file->mime_type == FILE_TYPE_AVI) + return GP_ERROR_NOT_SUPPORTED; + + + p = g_file->fat; + + /* get the position in memory where the image is */ + start = (p[1] & 0xff) + (p[2] & 0xff) * 0x100; + start *= 128; + + /* decode the image size */ + o_size = size = (p[13] & 0xff) * 0x10000 + (p[12] & 0xff) * 0x100 + (p[11] & 0xff); + qIndex = p[7] & 0x07; + quality = p[40] & 0xff; + + printf("size: %d or: %d\n", size, g_file->width * g_file->height / 2 * 4); + + /* align */ + if (size % 64 != 0) + size = ((size / 64) + 1) * 64; + + file_size = size + GSMART_JPG_DEFAULT_HEADER_LENGTH + 1024 * 10; + + /* slurp in the image */ + mybuf = malloc (size); + if (!mybuf) + return GP_ERROR_NO_MEMORY; + + CHECK (gsmart_download_data (lib, start, size, mybuf)); + + /* now build a jpeg */ + lp_jpg = malloc (file_size); + if (!lp_jpg) + return GP_ERROR_NO_MEMORY; + start_of_file = lp_jpg; + + /* copy the header from the template */ + memcpy (lp_jpg, GsmartJPGDefaultHeader, GSMART_JPG_DEFAULT_HEADER_LENGTH); + + /* modify quantization table */ + memcpy (lp_jpg + 7, GsmartQTable[qIndex * 2], 64); + memcpy (lp_jpg + 72, GsmartQTable[qIndex * 2 + 1], 64); + + /* modify the image width, height */ + *(lp_jpg + 564) = (g_file->width) & 0xFF; //Image width low byte + *(lp_jpg + 563) = (g_file->width >> 8) & 0xFF; //Image width high byte + *(lp_jpg + 562) = (g_file->height) & 0xFF; //Image height low byte + *(lp_jpg + 561) = (g_file->height >> 8) & 0xFF; //Image height high byte + + /* point to real JPG compress data start position and copy */ + lp_jpg += GSMART_JPG_DEFAULT_HEADER_LENGTH; + + for (i = 0; i < o_size; i++) { + value = *(mybuf + i) & 0xFF; + *(lp_jpg) = value; + lp_jpg++; + if (value == 0xFF) { + *(lp_jpg) = 0x00; + lp_jpg++; + f_counter++; + } + } + /* Add end of image marker */ + *(lp_jpg++) = 0xFF; + *(lp_jpg++) = 0xD9; + free (mybuf); + file_size = lp_jpg - start_of_file; + start_of_file = realloc(start_of_file, file_size); + *buf = start_of_file; + *len = file_size; + + return (GP_OK); +} + +int +gsmart_request_thumbnail (CameraPrivateLibrary * lib, u_int8_t ** buf, unsigned int *len, + unsigned int number) +{ + struct GsmartFile *g_file; + unsigned int size; + u_int8_t *p; + u_int8_t quality; + u_int32_t start; + u_int8_t *mybuf = NULL; + u_int8_t *tmp; + unsigned int t_width, t_height; + u_int8_t *yuv_p; + u_int8_t *rgb_p; + unsigned char pbm_header[16]; + + GP_DEBUG ("* gsmart_request_thumbnail number: %d", number); + + CHECK (gsmart_get_file_info (lib, number, &g_file)); + + /* FIXME implement avi downloading */ + if (g_file->mime_type == FILE_TYPE_AVI) + return GP_ERROR_NOT_SUPPORTED; + + p = g_file->fat; + quality = p[40] & 0xFF; + + start = (p[3] & 0xff) + (p[4] & 0xff) * 0x100; + start *= 128; + + size = g_file->width * g_file->height * 2 / 64; + t_width = g_file->width / 8; + t_height = g_file->height / 8; + sprintf (pbm_header, "P6 %d %d 255\n", t_width, t_height); + + /* align */ + if (size % 64 != 0) + size = ((size / 64) + 1) * 64; + + mybuf = malloc (size); + CHECK (gsmart_download_data (lib, start, size, mybuf)); + *len = t_width * t_height * 3 + sizeof (pbm_header); + *buf = malloc (*len); + if (!*buf) + return (GP_ERROR_NO_MEMORY); + + tmp = *buf; + snprintf (tmp, sizeof (pbm_header), pbm_header); + tmp += sizeof (pbm_header) - 1; + + yuv_p = mybuf; + rgb_p = tmp; + while (yuv_p < mybuf + size) { + unsigned int u, v, y, y2; + unsigned int r, g, b; + + y = yuv_p[0]; + y2 = yuv_p[1]; + u = yuv_p[2]; + v = yuv_p[3]; + + CHECK (yuv2rgb (y, u, v, &r, &g, &b)); + *rgb_p++ = r; + *rgb_p++ = g; + *rgb_p++ = b; + + CHECK (yuv2rgb (y2, u, v, &r, &g, &b)); + *rgb_p++ = r; + *rgb_p++ = g; + *rgb_p++ = b; + + yuv_p += 4; + } + + free (mybuf); + return (GP_OK); +} + + +int +gsmart_get_FATs (CameraPrivateLibrary * lib) +{ + u_int8_t dramtype, type; + u_int8_t lower, upper; + u_int32_t fatscount; + unsigned int index = 0; + unsigned int file_index = 0; + u_int8_t *p = NULL; + u_int8_t buf[14]; + + if (!lib->num_files) + return GP_OK; + + /* Reset image and movie counter */ + lib->num_images = lib->num_movies = 0; + + CHECK (gp_port_usb_msg_write (lib->gpdev, 0x05, 0x0000, 0x0008, NULL, 0)); + sleep (0.1); + + CHECK (gp_port_usb_msg_read (lib->gpdev, 0, 0, 0x0e19, (u_int8_t *) & lower, 1)); + CHECK (gp_port_usb_msg_read (lib->gpdev, 0, 0, 0x0e20, (u_int8_t *) & upper, 1)); + + fatscount = ((upper & 0xFF << 8) | (lower & 0xFF)); + GP_DEBUG ("fatscount: %d\n", fatscount); + + if (lib->fats) + free (lib->fats); + lib->fats = malloc (fatscount * FLASH_PAGE_SIZE); + + if (!gsmart_is_idle (lib)) + gsmart_mode_set_idle (lib); + + gsmart_mode_set_download (lib); + + CHECK (gp_port_usb_msg_write + (lib->gpdev, 0x00, 0x0001, GSMART_REG_AutoPbSize, NULL, 0)); + CHECK (gp_port_usb_msg_read + (lib->gpdev, 0, 0, GSMART_REG_DramType, (u_int8_t *) & dramtype, 1)); + + dramtype &= 0xFF; + p = lib->fats; + + while (index < fatscount) { + switch (dramtype) { + case 4: /* 128 Mbit */ + CHECK (gsmart_download_data + (lib, 0x7fff80 - index * 0x80, FLASH_PAGE_SIZE, p)); + break; + default: /* FALLTHROUGH */ + case 3: /* 64 Mbit */ + CHECK (gsmart_download_data + (lib, 0x3fff80 - index * 0x80, FLASH_PAGE_SIZE, p)); + break; + } + if (p[0] == 0xFF) + break; + type = p[0]; + if (type == 0x00) { /* its an image */ + sprintf (buf, "Image%03d.jpg", ++lib->num_images); + lib->files[file_index].name = strdup (buf); + lib->files[file_index].fat_start = index; + lib->files[file_index].fat_end = index; + lib->files[file_index].fat = p; + lib->files[file_index].mime_type = FILE_TYPE_IMAGE; + file_index++; + } else if (type == 0x08) { /* its the start of an avi */ + sprintf (buf, "Movie%03d.avi", ++lib->num_movies); + lib->files[file_index].name = strdup (buf); + lib->files[file_index].mime_type = FILE_TYPE_AVI; + lib->files[file_index].fat_start = index; + lib->files[file_index].fat = p; + file_index++; + } else if (type == 0x80) { /* continuation of an avi */ + lib->files[file_index - 1].fat_end = index; + } + p += FLASH_PAGE_SIZE; + index++; + } + + return GP_OK; +} + +int +gsmart_get_info (CameraPrivateLibrary * lib) +{ + unsigned int index; + u_int8_t *p; + u_int32_t start_page, end_page; + u_int8_t file_type; + + GP_DEBUG ("* gsmart_get_info"); + CHECK (gsmart_get_file_count (lib)); + if (lib->num_files > 0) { + CHECK (gsmart_get_FATs (lib)); + + index = lib->files[lib->num_files - 1].fat_end; + p = lib->fats + FLASH_PAGE_SIZE * index; + /* p now points to the fat of the last image of the last file */ + + file_type = p[0]; + start_page = ((p[2] & 0xFF) << 8) | (p[1] & 0xFF); + end_page = start_page + (((p[6] & 0xFF) << 8) | (p[5] & 0xFF)); + if (file_type == FILE_TYPE_IMAGE) + end_page = end_page + 0xA0; + + lib->size_used = (end_page - 0x2800) * FLASH_PAGE_SIZE; + } else + lib->size_used = 0; + + lib->size_free = 16 * 1024 * 1024 - 0x2800 * FLASH_PAGE_SIZE - lib->size_used; + lib->dirty = 0; + + return GP_OK; +} + +int +gsmart_get_file_info (CameraPrivateLibrary * lib, unsigned int index, + struct GsmartFile **g_file) +{ + struct GsmartFile *file; + u_int8_t *p; + + GP_DEBUG ("* gsmart_get_file_info"); + + if (lib->dirty) + CHECK (gsmart_get_info (lib)); + + file = &(lib->files[index]); + p = file->fat; + + file->width = (p[8] & 0xFF) * 16; + file->height = (p[9] & 0xFF) * 16; + *g_file = file; + + return GP_OK; +} + +int +gsmart_reset (CameraPrivateLibrary * lib) +{ + GP_DEBUG ("* gsmart_reset"); + CHECK (gp_port_usb_msg_write (lib->gpdev, 0x02, 0x0000, 0x0003, NULL, 0)); + sleep (1); + return GP_OK; +} + +int +gsmart_capture (CameraPrivateLibrary * lib) +{ + GP_DEBUG ("* gsmart_capture"); + sleep (2); + CHECK (gp_port_usb_msg_write (lib->gpdev, 0x06, 0x0000, 0x0003, NULL, 0)); + sleep (3); + return GP_OK; +} + +int +gsmart_mode_set_idle (CameraPrivateLibrary * lib) +{ + GP_DEBUG ("* gsmart_mode_set_idle"); + CHECK (gp_port_usb_msg_write + (lib->gpdev, 0, GSMART_CamMode_Idle, GSMART_REG_CamMode, NULL, 0)); + return GP_OK; +} + +int +gsmart_is_idle (CameraPrivateLibrary * lib) +{ + int mode; + + GP_DEBUG ("* gsmart_is_idle"); + + CHECK (gp_port_usb_msg_read + (lib->gpdev, 0, 0, GSMART_REG_CamMode, (u_int8_t *) & mode, 1)); + + return mode == GSMART_CamMode_Idle ? 1 : 0; +} + +int +gsmart_mode_set_download (CameraPrivateLibrary * lib) +{ + GP_DEBUG ("* gsmart_mode_set_download"); + CHECK (gp_port_usb_msg_write + (lib->gpdev, 0, GSMART_CamMode_Upload, GSMART_REG_CamMode, NULL, 0)); + return GP_OK; +} + +int +gsmart_download_data (CameraPrivateLibrary * lib, u_int32_t start, unsigned int size, + u_int8_t * buf) +{ + + u_int8_t foo; + u_int8_t vlcAddressL, vlcAddressM, vlcAddressH; + + GP_DEBUG ("* gsmart_download_data"); + + if (!gsmart_is_idle (lib)) + gsmart_mode_set_idle (lib); + + gsmart_mode_set_download (lib); + + foo = size & 0xFF; + CHECK (gp_port_usb_msg_write (lib->gpdev, 0, foo, GSMART_REG_SdramSizeL, NULL, 0)); + foo = (size >> 8) & 0xFF; + CHECK (gp_port_usb_msg_write (lib->gpdev, 0, foo, GSMART_REG_SdramSizeM, NULL, 0)); + foo = (size >> 16) & 0xFF; + CHECK (gp_port_usb_msg_write (lib->gpdev, 0, foo, GSMART_REG_SdramSizeH, NULL, 0)); + + CHECK (gp_port_usb_msg_read + (lib->gpdev, 0, 0, GSMART_REG_VlcAddressL, (u_int8_t *) & vlcAddressL, 1)); + CHECK (gp_port_usb_msg_read + (lib->gpdev, 0, 0, GSMART_REG_VlcAddressM, (u_int8_t *) & vlcAddressM, 1)); + CHECK (gp_port_usb_msg_read + (lib->gpdev, 0, 0, GSMART_REG_VlcAddressH, (u_int8_t *) & vlcAddressH, 1)); + + foo = start & 0xFF; + CHECK (gp_port_usb_msg_write (lib->gpdev, 0, foo, GSMART_REG_VlcAddressL, NULL, 0)); + foo = (start >> 8) & 0xFF; + CHECK (gp_port_usb_msg_write (lib->gpdev, 0, foo, GSMART_REG_VlcAddressM, NULL, 0)); + foo = (start >> 16) & 0xFF; + CHECK (gp_port_usb_msg_write (lib->gpdev, 0, foo, GSMART_REG_VlcAddressH, NULL, 0)); + + /* Set mode to ram -> usb */ + CHECK (gp_port_usb_msg_write + (lib->gpdev, 0, GSMART_DramUsb, GSMART_REG_PbSrc, NULL, 0)); + /* and pull the trigger */ + CHECK (gp_port_usb_msg_write + (lib->gpdev, 0, GSMART_TrigDramFifo, GSMART_REG_Trigger, NULL, 0)); + + CHECK (gp_port_read (lib->gpdev, buf, size)); + + CHECK (gp_port_usb_msg_write + (lib->gpdev, 0, vlcAddressL, GSMART_REG_VlcAddressL, NULL, 0)); + CHECK (gp_port_usb_msg_write + (lib->gpdev, 0, vlcAddressM, GSMART_REG_VlcAddressM, NULL, 0)); + CHECK (gp_port_usb_msg_write + (lib->gpdev, 0, vlcAddressH, GSMART_REG_VlcAddressH, NULL, 0)); + + gsmart_mode_set_idle (lib); + return GP_OK; +} + +static int +yuv2rgb (int y, int u, int v, int *_r, int *_g, int *_b) +{ + double r, g, b; + + r = (char) y + 128 + 1.402 * (char) v; + g = (char) y + 128 - 0.34414 * (char) u - 0.71414 * (char) v; + b = (char) y + 128 + 1.772 * (char) u; + + if (r > 255) + r = 255; + if (g > 255) + g = 255; + if (b > 255) + b = 255; + if (r < 0) + r = 0; + if (g < 0) + g = 0; + if (b < 0) + b = 0; + + *_r = r; + *_g = g; + *_b = b; + + return GP_OK; +} diff --git a/camlibs/gsmart/gsmart.h b/camlibs/gsmart/gsmart.h new file mode 100644 index 000000000..45f58acb4 --- /dev/null +++ b/camlibs/gsmart/gsmart.h @@ -0,0 +1,83 @@ +/****************************************************************/ +/* gsmart.h - Gphoto2 library for the Mustek gSmart mini 2 */ +/* */ +/* Copyright (C) 2002 Till Adam */ +/* */ +/* Author: Till Adam */ +/* */ +/* This library is free software; you can redistribute it */ +/* and/or modify it under the terms of the GNU Library General */ +/* Public License as published by the Free Software Foundation; */ +/* either version 2 of the License, or (at your option) any */ +/* later version. */ +/* */ +/* This library is distributed in the hope that it will be */ +/* useful, but WITHOUT ANY WARRANTY; without even the implied */ +/* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */ +/* PURPOSE. See the GNU Library General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU Library General */ +/* Public License along with this library; if not, write to the */ +/* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */ +/* Boston, MA 02111-1307, USA. */ +/****************************************************************/ + +#ifndef __GSMART_H__ +#define __GSMART_H__ +#include + +#define FLASH_PAGE_SIZE 0x100 +#define FILE_TYPE_IMAGE 0x00 +#define FILE_TYPE_AVI 0x01 + +#define CHECK(result) {int res; res = result; if (res < 0) return (res);} + +struct GsmartFile +{ + char *name; + int width; + int height; + int fat_start; + int fat_end; + u_int8_t *fat; + int mime_type; +}; + +struct _CameraPrivateLibrary +{ + GPPort *gpdev; + int dirty; + int num_files; + int num_images; + int num_movies; + int size_used; + int size_free; + u_int8_t *fats; + struct GsmartFile files[250]; +}; + +int gsmart_reset (CameraPrivateLibrary * lib); +int gsmart_capture (CameraPrivateLibrary * lib); +int gsmart_mode_set_idle (CameraPrivateLibrary * lib); +int gsmart_is_idle (CameraPrivateLibrary * lib); +int gsmart_mode_set_download (CameraPrivateLibrary * lib); + +int gsmart_download_data (CameraPrivateLibrary * lib, u_int32_t start, unsigned int size, + u_int8_t * buf); + +int gsmart_get_FATs (CameraPrivateLibrary * lib); +int gsmart_get_file_count (CameraPrivateLibrary * lib); +int gsmart_get_info (CameraPrivateLibrary * lib); +int gsmart_delete_file (CameraPrivateLibrary * lib, unsigned int index); +int gsmart_delete_all (CameraPrivateLibrary * lib); +int gsmart_get_file_info (CameraPrivateLibrary * lib, unsigned int index, + struct GsmartFile **file); + +int gsmart_request_file (CameraPrivateLibrary * lib, u_int8_t ** buf, unsigned int *len, + unsigned int number); +int gsmart_request_thumbnail (CameraPrivateLibrary * lib, u_int8_t ** buf, unsigned int *len, + unsigned int number); + + +#endif /* __GSMART_H__ */ diff --git a/camlibs/gsmart/library.c b/camlibs/gsmart/library.c new file mode 100644 index 000000000..5c04e78d1 --- /dev/null +++ b/camlibs/gsmart/library.c @@ -0,0 +1,389 @@ +/****************************************************************/ +/* library.c - Gphoto2 library for the Mustek gSmart mini 2 */ +/* */ +/* Copyright (C) 2002 Till Adam */ +/* */ +/* Author: Till Adam */ +/* */ +/* This library is free software; you can redistribute it */ +/* and/or modify it under the terms of the GNU Library General */ +/* Public License as published by the Free Software Foundation; */ +/* either version 2 of the License, or (at your option) any */ +/* later version. */ +/* */ +/* This library is distributed in the hope that it will be */ +/* useful, but WITHOUT ANY WARRANTY; without even the implied */ +/* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */ +/* PURPOSE. See the GNU Library General Public License for */ +/* more details. */ +/* */ +/* You should have received a copy of the GNU Library General */ +/* Public License along with this library; if not, write to the */ +/* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */ +/* Boston, MA 02111-1307, USA. */ +/****************************************************************/ + +#include + +#include +#include +#include + +#include + +#ifdef ENABLE_NLS +# include +# undef _ +# define _(String) dgettext (PACKAGE, String) +# ifdef gettext_noop +# define N_(String) gettext_noop (String) +# else +# define N_(String) (String) +# endif +#else +# define _(String) (String) +# define N_(String) (String) +#endif + +#include "gsmart.h" + +#define GP_MODULE "gsmartmini2" +#define TIMEOUT 5000 + +#define GSMART_VERSION "0.1" +#define GSMART_LAST_MOD "08/07/02 - 17:21:11" + +/* forward declarations */ +static int file_list_func (CameraFilesystem *fs, const char *folder, + CameraList *list, void *data, GPContext *context); +static int get_file_func (CameraFilesystem *fs, const char *folder, + const char *filename, CameraFileType type, + CameraFile *file, void *user_data, GPContext *context); + +static int delete_file_func (CameraFilesystem *fs, const char *folder, + const char *filename, void *data, GPContext *context); +static int delete_all_func (CameraFilesystem *fs, const char *folder, + void *data, GPContext *context); +static int get_info_func (CameraFilesystem *fs, const char *folder, + const char *filename, CameraFileInfo *info, + void *data, GPContext *context); + +/* define what cameras we support */ +static struct +{ + char *model; + int usb_vendor; + int usb_product; +} +models[] = +{ + { + "Mustek gSmart mini 2", 0x055f, 0xc420} + , { + NULL, 0, 0} +}; + +int +camera_id (CameraText *id) +{ + GP_DEBUG ("* camera_id"); + + strcpy (id->text, "gsmartmini2"); + + return (GP_OK); +} + +int +camera_abilities (CameraAbilitiesList *list) +{ + int x = 0; + char *ptr; + CameraAbilities a; + + GP_DEBUG ("* camera_abilities"); + + ptr = models[x].model; + while (ptr) { + memset (&a, 0, sizeof (a)); + strcpy (a.model, ptr); + a.status = GP_DRIVER_STATUS_EXPERIMENTAL; + a.port = GP_PORT_USB; + a.speed[0] = 0; + + a.operations = GP_OPERATION_CAPTURE_IMAGE; + a.file_operations = GP_FILE_OPERATION_PREVIEW | GP_FILE_OPERATION_DELETE; + + a.folder_operations = GP_FOLDER_OPERATION_DELETE_ALL; + + a.usb_vendor = models[x].usb_vendor; + a.usb_product = models[x].usb_product; + + gp_abilities_list_append (list, a); + + ptr = models[++x].model; + } + + return (GP_OK); +} + +static int +camera_capture (Camera *camera, CameraCaptureType type, + CameraFilePath * path, GPContext *context) +{ + struct GsmartFile *file; + + GP_DEBUG ("* camera_capture"); + + CHECK (gsmart_capture (camera->pl)); + CHECK (gsmart_get_info (camera->pl)); + + CHECK (gsmart_get_file_info (camera->pl, camera->pl->num_files - 1, &file)); + + /* Now tell the frontend where to look for the image */ + strncpy (path->folder, "/", sizeof (path->folder)); + strncpy (path->name, file->name, sizeof (path->name)); + + CHECK (gp_filesystem_append (camera->fs, path->folder, path->name, context)); + + return GP_OK; +} + + +static int +camera_exit (Camera *camera, GPContext *context) +{ + GP_DEBUG ("* camera_exit"); + + if (camera->pl) { + if (camera->pl->fats) { + free (camera->pl->fats); + camera->pl->fats = NULL; + } + free (camera->pl); + camera->pl = NULL; + } + return (GP_OK); +} + +static int +camera_summary (Camera *camera, CameraText *summary, GPContext *context) +{ + char tmp[1024]; + + GP_DEBUG ("* camera_summary"); + + /* possibly get # pics, mem free, etc. if needed */ + if (camera->pl->dirty) + CHECK (gsmart_get_info (camera->pl)); + + sprintf (tmp, + "Files: %d\n Images: %4d\n Movies: %4d\nSpace used: %8d\nSpace free: %8d\n", + camera->pl->num_files, camera->pl->num_images, + camera->pl->num_movies, camera->pl->size_used, camera->pl->size_free); + strcat (summary->text, tmp); + + return (GP_OK); +} + +static int +camera_about (Camera *camera, CameraText *about, GPContext *context) +{ + GP_DEBUG ("* camera_about"); + + strcpy (about->text, + _("gsmart library v" GSMART_VERSION + " " GSMART_LAST_MOD "\n" + "Till Adam \n" + "Support for Mustek gSmart mini 2 digital cameras\n" + "based on several other gphoto2 camlib modules and " + "the windows driver source kindly provided by Mustek.\n" "\n")); + + return (GP_OK); +} + +int +camera_init (Camera *camera, GPContext *context) +{ + int ret; + GPPortSettings settings; + + GP_DEBUG ("* camera_init"); + GP_DEBUG (" * gsmart library for Gphoto2 by Till Adam "); + GP_DEBUG (" * gsmart library v%s, %s", GSMART_VERSION, GSMART_LAST_MOD); + + /* First, set up all the function pointers */ + camera->functions->exit = camera_exit; + camera->functions->summary = camera_summary; + camera->functions->about = camera_about; + camera->functions->capture = camera_capture; + + CHECK (gp_port_get_settings (camera->port, &settings)); + switch (camera->port->type) { + case GP_PORT_USB: + settings.usb.inep = 0x82; + settings.usb.outep = 0x03; + settings.usb.config = 1; + settings.usb.interface = 0; + settings.usb.altsetting = 0; + + CHECK (gp_port_set_settings (camera->port, settings)); + CHECK (gp_port_set_timeout (camera->port, TIMEOUT)); + + break; + default: + fprintf (stderr, "Unsuported port type: %d\n", camera->port->type); + return (GP_ERROR); + break; + } + + camera->pl = malloc (sizeof (CameraPrivateLibrary)); + if (!camera->pl) + return (GP_ERROR_NO_MEMORY); + memset (camera->pl, 0, sizeof (CameraPrivateLibrary)); + camera->pl->gpdev = camera->port; + camera->pl->dirty = 1; + + ret = gsmart_reset (camera->pl); + + if (ret < 0) { + fprintf (stderr, "* gsmart: Couldn't reset camera.\n"); + free (camera->pl); + camera->pl = NULL; + + return (ret); + } + + /* Set up the CameraFilesystem */ + CHECK (gp_filesystem_set_list_funcs (camera->fs, file_list_func, NULL, camera)); + CHECK (gp_filesystem_set_file_funcs (camera->fs, get_file_func, + delete_file_func, camera)); + CHECK (gp_filesystem_set_info_funcs (camera->fs, get_info_func, NULL, camera)); + CHECK (gp_filesystem_set_folder_funcs (camera->fs, + NULL, delete_all_func, NULL, NULL, camera)); + + CHECK (gsmart_mode_set_idle (camera->pl)); + + return (GP_OK); +} + + +static int +file_list_func (CameraFilesystem *fs, const char *folder, + CameraList *list, void *data, GPContext *context) +{ + + Camera *camera = data; + int i; + char temp_file[14]; + + GP_DEBUG ("camera_file_list %s\n", folder); + + if (camera->pl->dirty) + CHECK (gsmart_get_info (camera->pl)); + + for (i = 0; i < camera->pl->num_files; i++) { + strncpy (temp_file, camera->pl->files[i].name, 12); + temp_file[12] = 0; + gp_list_append (list, temp_file, NULL); + } + + return GP_OK; +} + + +static int +get_file_func (CameraFilesystem *fs, const char *folder, + const char *filename, CameraFileType type, + CameraFile *file, void *user_data, GPContext *context) +{ + + Camera *camera = user_data; + unsigned char *data = NULL; + int size, number; + + GP_DEBUG ("* get_file_func"); + GP_DEBUG ("*** folder: %s", folder); + GP_DEBUG ("*** filename: %s", filename); + + CHECK (number = gp_filesystem_number (camera->fs, folder, filename, context)); + + switch (type) { + case GP_FILE_TYPE_NORMAL: + CHECK (gsmart_request_file (camera->pl, &data, &size, number)); + break; + case GP_FILE_TYPE_PREVIEW: + CHECK (gsmart_request_thumbnail (camera->pl, &data, &size, number)); + CHECK (gp_file_set_mime_type (file, GP_MIME_BMP)); + break; + default: + return GP_ERROR_NOT_SUPPORTED; + } + + if (!data) + return GP_ERROR; + + CHECK (gp_file_set_data_and_size (file, data, size)); + CHECK (gp_file_set_name (file, filename)); + + return GP_OK; +} + +static int +get_info_func (CameraFilesystem *fs, const char *folder, + const char *filename, CameraFileInfo *info, void *data, GPContext *context) +{ + Camera *camera = data; + int n; + struct GsmartFile *file; + + GP_DEBUG ("* get_info_func"); + GP_DEBUG ("*** folder: %s", folder); + GP_DEBUG ("*** filename: %s", filename); + + /* Get the file number from the CameraFileSystem */ + CHECK (n = gp_filesystem_number (camera->fs, folder, filename, context)); + + CHECK (gsmart_get_file_info (camera->pl, n, &file)); + + info->file.fields = GP_FILE_INFO_TYPE | GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT; + if (file->mime_type == FILE_TYPE_IMAGE) + strcpy (info->file.type, GP_MIME_JPEG); + else if (file->mime_type == FILE_TYPE_AVI) + strcpy (info->file.type, GP_MIME_AVI); + info->file.width = file->width; + info->file.height = file->height; + + info->preview.fields = GP_FILE_INFO_TYPE | GP_FILE_INFO_WIDTH | GP_FILE_INFO_HEIGHT; + strcpy (info->preview.type, GP_MIME_BMP); + info->preview.width = 160; + info->preview.height = 120; + + return (GP_OK); +} + +static int +delete_file_func (CameraFilesystem *fs, const char *folder, + const char *filename, void *data, GPContext *context) +{ + Camera *camera = data; + int index; + + GP_DEBUG ("Deleting '%s' in '%s'...", filename, folder); + + /* Get the file number from the CameraFileSystem */ + CHECK (index = gp_filesystem_number (camera->fs, folder, filename, context)); + CHECK (gsmart_delete_file (camera->pl, index)); + + return GP_OK; +} + +static int +delete_all_func (CameraFilesystem *fs, const char *folder, void *data, GPContext *context) +{ + Camera *camera = data; + + GP_DEBUG ("Deleting all in '%s'...", folder); + + CHECK (gsmart_delete_all (camera->pl)); + return GP_OK; +} diff --git a/configure.in b/configure.in index 38c7a79fe..d69350a37 100644 --- a/configure.in +++ b/configure.in @@ -145,7 +145,7 @@ fi dnl --------------------------------------------------------------------------- dnl Camera drivers dnl --------------------------------------------------------------------------- -camlibs='agfa barbie canon casio digita dimera directory fuji jamcam jd11 kodak konica minolta mustek panasonic polaroid ptp ricoh samsung sierra sipix sonydscf1 sonydscf55 stv0680 sx330z' +camlibs='agfa barbie canon casio digita dimera directory fuji gsmart jamcam jd11 kodak konica minolta mustek panasonic polaroid ptp ricoh samsung sierra sipix sonydscf1 sonydscf55 stv0680 sx330z' AC_SUBST(SUBDIRS_CAMLIBS) for i in $camlibs; do d=`echo $i | $TR a-z A-Z` @@ -158,7 +158,7 @@ AC_ARG_WITH(drivers, [ 'all' compiles all drivers; ] [ possible drivers are: ] [ agfa, barbie, canon, casio, digita, dimera,] - [ directory, fuji, jamcam, jd11, kodak,] + [ directory, fuji, gsmart, jamcam, jd11, kodak,] [ konica, mustek,] [ minolta, panasonic, polaroid, ptp, ricoh,] [ samsung, sierra, sx330z, sonydscf1, sonydscf55,]