t613.c 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036
  1. /*
  2. * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. *
  18. *Notes: * t613 + tas5130A
  19. * * Focus to light do not balance well as in win.
  20. * Quality in win is not good, but its kinda better.
  21. * * Fix some "extraneous bytes", most of apps will show the image anyway
  22. * * Gamma table, is there, but its really doing something?
  23. * * 7~8 Fps, its ok, max on win its 10.
  24. * Costantino Leandro
  25. */
  26. #define MODULE_NAME "t613"
  27. #include "gspca.h"
  28. #define MAX_GAMMA 0x10 /* 0 to 15 */
  29. #define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 3)
  30. MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
  31. MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
  32. MODULE_LICENSE("GPL");
  33. struct sd {
  34. struct gspca_dev gspca_dev; /* !! must be the first item */
  35. unsigned char brightness;
  36. unsigned char contrast;
  37. unsigned char colors;
  38. unsigned char autogain;
  39. unsigned char gamma;
  40. unsigned char sharpness;
  41. unsigned char freq;
  42. unsigned char whitebalance;
  43. unsigned char mirror;
  44. unsigned char effect;
  45. };
  46. /* V4L2 controls supported by the driver */
  47. static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
  48. static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
  49. static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
  50. static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
  51. static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
  52. static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
  53. static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val);
  54. static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val);
  55. static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val);
  56. static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val);
  57. static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
  58. static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
  59. static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val);
  60. static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val);
  61. static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val);
  62. static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val);
  63. static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val);
  64. static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val);
  65. static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val);
  66. static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val);
  67. static int sd_querymenu(struct gspca_dev *gspca_dev,
  68. struct v4l2_querymenu *menu);
  69. static struct ctrl sd_ctrls[] = {
  70. #define SD_BRIGHTNESS 0
  71. {
  72. {
  73. .id = V4L2_CID_BRIGHTNESS,
  74. .type = V4L2_CTRL_TYPE_INTEGER,
  75. .name = "Brightness",
  76. .minimum = 0,
  77. .maximum = 0x0f,
  78. .step = 1,
  79. .default_value = 0x09,
  80. },
  81. .set = sd_setbrightness,
  82. .get = sd_getbrightness,
  83. },
  84. #define SD_CONTRAST 1
  85. {
  86. {
  87. .id = V4L2_CID_CONTRAST,
  88. .type = V4L2_CTRL_TYPE_INTEGER,
  89. .name = "Contrast",
  90. .minimum = 0,
  91. .maximum = 0x0d,
  92. .step = 1,
  93. .default_value = 0x07,
  94. },
  95. .set = sd_setcontrast,
  96. .get = sd_getcontrast,
  97. },
  98. #define SD_COLOR 2
  99. {
  100. {
  101. .id = V4L2_CID_SATURATION,
  102. .type = V4L2_CTRL_TYPE_INTEGER,
  103. .name = "Color",
  104. .minimum = 0,
  105. .maximum = 0x0f,
  106. .step = 1,
  107. .default_value = 0x05,
  108. },
  109. .set = sd_setcolors,
  110. .get = sd_getcolors,
  111. },
  112. #define SD_GAMMA 3
  113. {
  114. {
  115. .id = V4L2_CID_GAMMA, /* (gamma on win) */
  116. .type = V4L2_CTRL_TYPE_INTEGER,
  117. .name = "Gamma (Untested)",
  118. .minimum = 0,
  119. .maximum = MAX_GAMMA,
  120. .step = 1,
  121. .default_value = 0x09,
  122. },
  123. .set = sd_setgamma,
  124. .get = sd_getgamma,
  125. },
  126. #define SD_AUTOGAIN 4
  127. {
  128. {
  129. .id = V4L2_CID_GAIN, /* here, i activate only the lowlight,
  130. * some apps dont bring up the
  131. * backligth_compensation control) */
  132. .type = V4L2_CTRL_TYPE_INTEGER,
  133. .name = "Low Light",
  134. .minimum = 0,
  135. .maximum = 1,
  136. .step = 1,
  137. .default_value = 0x01,
  138. },
  139. .set = sd_setlowlight,
  140. .get = sd_getlowlight,
  141. },
  142. #define SD_MIRROR 5
  143. {
  144. {
  145. .id = V4L2_CID_HFLIP,
  146. .type = V4L2_CTRL_TYPE_BOOLEAN,
  147. .name = "Mirror Image",
  148. .minimum = 0,
  149. .maximum = 1,
  150. .step = 1,
  151. .default_value = 0,
  152. },
  153. .set = sd_setflip,
  154. .get = sd_getflip
  155. },
  156. #define SD_LIGHTFREQ 6
  157. {
  158. {
  159. .id = V4L2_CID_POWER_LINE_FREQUENCY,
  160. .type = V4L2_CTRL_TYPE_MENU,
  161. .name = "Light Frequency Filter",
  162. .minimum = 1, /* 1 -> 0x50, 2->0x60 */
  163. .maximum = 2,
  164. .step = 1,
  165. .default_value = 1,
  166. },
  167. .set = sd_setfreq,
  168. .get = sd_getfreq},
  169. #define SD_WHITE_BALANCE 7
  170. {
  171. {
  172. .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
  173. .type = V4L2_CTRL_TYPE_INTEGER,
  174. .name = "White Balance",
  175. .minimum = 0,
  176. .maximum = 1,
  177. .step = 1,
  178. .default_value = 1,
  179. },
  180. .set = sd_setwhitebalance,
  181. .get = sd_getwhitebalance
  182. },
  183. #define SD_SHARPNESS 8 /* (aka definition on win) */
  184. {
  185. {
  186. .id = V4L2_CID_SHARPNESS,
  187. .type = V4L2_CTRL_TYPE_INTEGER,
  188. .name = "Sharpness",
  189. .minimum = 0,
  190. .maximum = MAX_GAMMA, /* 0 to 16 */
  191. .step = 1,
  192. .default_value = 0x06,
  193. },
  194. .set = sd_setsharpness,
  195. .get = sd_getsharpness,
  196. },
  197. #define SD_EFFECTS 9
  198. {
  199. {
  200. .id = V4L2_CID_EFFECTS,
  201. .type = V4L2_CTRL_TYPE_MENU,
  202. .name = "Webcam Effects",
  203. .minimum = 0,
  204. .maximum = 4,
  205. .step = 1,
  206. .default_value = 0,
  207. },
  208. .set = sd_seteffect,
  209. .get = sd_geteffect
  210. },
  211. };
  212. static char *effects_control[] = {
  213. "Normal",
  214. "Emboss", /* disabled */
  215. "Monochrome",
  216. "Sepia",
  217. "Sketch",
  218. "Sun Effect", /* disabled */
  219. "Negative",
  220. };
  221. static struct v4l2_pix_format vga_mode_t16[] = {
  222. {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  223. .bytesperline = 160,
  224. .sizeimage = 160 * 120 * 3 / 8 + 590,
  225. .colorspace = V4L2_COLORSPACE_JPEG,
  226. .priv = 4},
  227. {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  228. .bytesperline = 176,
  229. .sizeimage = 176 * 144 * 3 / 8 + 590,
  230. .colorspace = V4L2_COLORSPACE_JPEG,
  231. .priv = 3},
  232. {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  233. .bytesperline = 320,
  234. .sizeimage = 320 * 240 * 3 / 8 + 590,
  235. .colorspace = V4L2_COLORSPACE_JPEG,
  236. .priv = 2},
  237. {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  238. .bytesperline = 352,
  239. .sizeimage = 352 * 288 * 3 / 8 + 590,
  240. .colorspace = V4L2_COLORSPACE_JPEG,
  241. .priv = 1},
  242. {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
  243. .bytesperline = 640,
  244. .sizeimage = 640 * 480 * 3 / 8 + 590,
  245. .colorspace = V4L2_COLORSPACE_JPEG,
  246. .priv = 0},
  247. };
  248. #define T16_OFFSET_DATA 631
  249. #define MAX_EFFECTS 7
  250. /* easily done by soft, this table could be removed,
  251. * i keep it here just in case */
  252. static const __u8 effects_table[MAX_EFFECTS][6] = {
  253. {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00}, /* Normal */
  254. {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04}, /* Repujar */
  255. {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20}, /* Monochrome */
  256. {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80}, /* Sepia */
  257. {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02}, /* Croquis */
  258. {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10}, /* Sun Effect */
  259. {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40}, /* Negative */
  260. };
  261. static const __u8 gamma_table[MAX_GAMMA][34] = {
  262. {0x90, 0x00, 0x91, 0x3e, 0x92, 0x69, 0x93, 0x85,
  263. 0x94, 0x95, 0x95, 0xa1, 0x96, 0xae, 0x97, 0xb9,
  264. 0x98, 0xc2, 0x99, 0xcb, 0x9a, 0xd4, 0x9b, 0xdb,
  265. 0x9c, 0xe3, 0x9d, 0xea, 0x9e, 0xf1, 0x9f, 0xf8,
  266. 0xa0, 0xff},
  267. {0x90, 0x00, 0x91, 0x33, 0x92, 0x5A, 0x93, 0x75,
  268. 0x94, 0x85, 0x95, 0x93, 0x96, 0xA1, 0x97, 0xAD,
  269. 0x98, 0xB7, 0x99, 0xC2, 0x9A, 0xCB, 0x9B, 0xD4,
  270. 0x9C, 0xDE, 0x9D, 0xE7, 0x9E, 0xF0, 0x9F, 0xF7,
  271. 0xa0, 0xff},
  272. {0x90, 0x00, 0x91, 0x2F, 0x92, 0x51, 0x93, 0x6B,
  273. 0x94, 0x7C, 0x95, 0x8A, 0x96, 0x99, 0x97, 0xA6,
  274. 0x98, 0xB1, 0x99, 0xBC, 0x9A, 0xC6, 0x9B, 0xD0,
  275. 0x9C, 0xDB, 0x9D, 0xE4, 0x9E, 0xED, 0x9F, 0xF6,
  276. 0xa0, 0xff},
  277. {0x90, 0x00, 0x91, 0x29, 0x92, 0x48, 0x93, 0x60,
  278. 0x94, 0x72, 0x95, 0x81, 0x96, 0x90, 0x97, 0x9E,
  279. 0x98, 0xAA, 0x99, 0xB5, 0x9A, 0xBF, 0x9B, 0xCB,
  280. 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
  281. 0xa0, 0xff},
  282. {0x90, 0x00, 0x91, 0x23, 0x92, 0x3F, 0x93, 0x55,
  283. 0x94, 0x68, 0x95, 0x77, 0x96, 0x86, 0x97, 0x95,
  284. 0x98, 0xA2, 0x99, 0xAD, 0x9A, 0xB9, 0x9B, 0xC6,
  285. 0x9C, 0xD2, 0x9D, 0xDE, 0x9E, 0xE9, 0x9F, 0xF4,
  286. 0xa0, 0xff},
  287. {0x90, 0x00, 0x91, 0x1B, 0x92, 0x33, 0x93, 0x48,
  288. 0x94, 0x59, 0x95, 0x69, 0x96, 0x79, 0x97, 0x87,
  289. 0x98, 0x96, 0x99, 0xA3, 0x9A, 0xB1, 0x9B, 0xBE,
  290. 0x9C, 0xCC, 0x9D, 0xDA, 0x9E, 0xE7, 0x9F, 0xF3,
  291. 0xa0, 0xff},
  292. {0x90, 0x00, 0x91, 0x02, 0x92, 0x10, 0x93, 0x20,
  293. 0x94, 0x32, 0x95, 0x40, 0x96, 0x57, 0x97, 0x67,
  294. 0x98, 0x77, 0x99, 0x88, 0x9a, 0x99, 0x9b, 0xaa,
  295. 0x9c, 0xbb, 0x9d, 0xcc, 0x9e, 0xdd, 0x9f, 0xee,
  296. 0xa0, 0xff},
  297. {0x90, 0x00, 0x91, 0x02, 0x92, 0x14, 0x93, 0x26,
  298. 0x94, 0x38, 0x95, 0x4A, 0x96, 0x60, 0x97, 0x70,
  299. 0x98, 0x80, 0x99, 0x90, 0x9A, 0xA0, 0x9B, 0xB0,
  300. 0x9C, 0xC0, 0x9D, 0xD0, 0x9E, 0xE0, 0x9F, 0xF0,
  301. 0xa0, 0xff},
  302. {0x90, 0x00, 0x91, 0x10, 0x92, 0x22, 0x93, 0x35,
  303. 0x94, 0x47, 0x95, 0x5A, 0x96, 0x69, 0x97, 0x79,
  304. 0x98, 0x88, 0x99, 0x97, 0x9A, 0xA7, 0x9B, 0xB6,
  305. 0x9C, 0xC4, 0x9D, 0xD3, 0x9E, 0xE0, 0x9F, 0xF0,
  306. 0xa0, 0xff},
  307. {0x90, 0x00, 0x91, 0x10, 0x92, 0x26, 0x93, 0x40,
  308. 0x94, 0x54, 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
  309. 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd,
  310. 0x9c, 0xca, 0x9d, 0xd6, 0x9e, 0xe0, 0x9f, 0xf0,
  311. 0xa0, 0xff},
  312. {0x90, 0x00, 0x91, 0x18, 0x92, 0x2B, 0x93, 0x44,
  313. 0x94, 0x60, 0x95, 0x70, 0x96, 0x80, 0x97, 0x8E,
  314. 0x98, 0x9C, 0x99, 0xAA, 0x9A, 0xB7, 0x9B, 0xC4,
  315. 0x9C, 0xD0, 0x9D, 0xD8, 0x9E, 0xE2, 0x9F, 0xF0,
  316. 0xa0, 0xff},
  317. {0x90, 0x00, 0x91, 0x1A, 0x92, 0x34, 0x93, 0x52,
  318. 0x94, 0x66, 0x95, 0x7E, 0x96, 0x8D, 0x97, 0x9B,
  319. 0x98, 0xA8, 0x99, 0xB4, 0x9A, 0xC0, 0x9B, 0xCB,
  320. 0x9C, 0xD6, 0x9D, 0xE1, 0x9E, 0xEB, 0x9F, 0xF5,
  321. 0xa0, 0xff},
  322. {0x90, 0x00, 0x91, 0x3F, 0x92, 0x5A, 0x93, 0x6E,
  323. 0x94, 0x7F, 0x95, 0x8E, 0x96, 0x9C, 0x97, 0xA8,
  324. 0x98, 0xB4, 0x99, 0xBF, 0x9A, 0xC9, 0x9B, 0xD3,
  325. 0x9C, 0xDC, 0x9D, 0xE5, 0x9E, 0xEE, 0x9F, 0xF6,
  326. 0xA0, 0xFF},
  327. {0x90, 0x00, 0x91, 0x54, 0x92, 0x6F, 0x93, 0x83,
  328. 0x94, 0x93, 0x95, 0xA0, 0x96, 0xAD, 0x97, 0xB7,
  329. 0x98, 0xC2, 0x99, 0xCB, 0x9A, 0xD4, 0x9B, 0xDC,
  330. 0x9C, 0xE4, 0x9D, 0xEB, 0x9E, 0xF2, 0x9F, 0xF9,
  331. 0xa0, 0xff},
  332. {0x90, 0x00, 0x91, 0x6E, 0x92, 0x88, 0x93, 0x9A,
  333. 0x94, 0xA8, 0x95, 0xB3, 0x96, 0xBD, 0x97, 0xC6,
  334. 0x98, 0xCF, 0x99, 0xD6, 0x9A, 0xDD, 0x9B, 0xE3,
  335. 0x9C, 0xE9, 0x9D, 0xEF, 0x9E, 0xF4, 0x9F, 0xFA,
  336. 0xa0, 0xff},
  337. {0x90, 0x00, 0x91, 0x93, 0x92, 0xA8, 0x93, 0xB7,
  338. 0x94, 0xC1, 0x95, 0xCA, 0x96, 0xD2, 0x97, 0xD8,
  339. 0x98, 0xDE, 0x99, 0xE3, 0x9A, 0xE8, 0x9B, 0xED,
  340. 0x9C, 0xF1, 0x9D, 0xF5, 0x9E, 0xF8, 0x9F, 0xFC,
  341. 0xA0, 0xFF}
  342. };
  343. static const __u8 tas5130a_sensor_init[][8] = {
  344. {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
  345. {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
  346. {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
  347. {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
  348. {},
  349. };
  350. /* read 1 byte */
  351. static int reg_r_1(struct gspca_dev *gspca_dev,
  352. __u16 index)
  353. {
  354. usb_control_msg(gspca_dev->dev,
  355. usb_rcvctrlpipe(gspca_dev->dev, 0),
  356. 0, /* request */
  357. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  358. 0, /* value */
  359. index,
  360. gspca_dev->usb_buf, 1, 500);
  361. return gspca_dev->usb_buf[0];
  362. }
  363. static void reg_w(struct gspca_dev *gspca_dev,
  364. __u16 value,
  365. __u16 index,
  366. const __u8 *buffer, __u16 len)
  367. {
  368. if (buffer == NULL) {
  369. usb_control_msg(gspca_dev->dev,
  370. usb_sndctrlpipe(gspca_dev->dev, 0),
  371. 0,
  372. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
  373. value, index,
  374. NULL, 0, 500);
  375. return;
  376. }
  377. if (len <= sizeof gspca_dev->usb_buf) {
  378. memcpy(gspca_dev->usb_buf, buffer, len);
  379. usb_control_msg(gspca_dev->dev,
  380. usb_sndctrlpipe(gspca_dev->dev, 0),
  381. 0,
  382. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
  383. value, index,
  384. gspca_dev->usb_buf, len, 500);
  385. } else {
  386. __u8 *tmpbuf;
  387. tmpbuf = kmalloc(len, GFP_KERNEL);
  388. memcpy(tmpbuf, buffer, len);
  389. usb_control_msg(gspca_dev->dev,
  390. usb_sndctrlpipe(gspca_dev->dev, 0),
  391. 0,
  392. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
  393. value, index,
  394. tmpbuf, len, 500);
  395. kfree(tmpbuf);
  396. }
  397. }
  398. /* this function is called at probe time */
  399. static int sd_config(struct gspca_dev *gspca_dev,
  400. const struct usb_device_id *id)
  401. {
  402. struct sd *sd = (struct sd *) gspca_dev;
  403. struct cam *cam;
  404. cam = &gspca_dev->cam;
  405. cam->dev_name = (char *) id->driver_info;
  406. cam->epaddr = 0x01;
  407. cam->cam_mode = vga_mode_t16;
  408. cam->nmodes = ARRAY_SIZE(vga_mode_t16);
  409. sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
  410. sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
  411. sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
  412. sd->gamma = sd_ctrls[SD_GAMMA].qctrl.default_value;
  413. sd->mirror = sd_ctrls[SD_MIRROR].qctrl.default_value;
  414. sd->freq = sd_ctrls[SD_LIGHTFREQ].qctrl.default_value;
  415. sd->whitebalance = sd_ctrls[SD_WHITE_BALANCE].qctrl.default_value;
  416. sd->sharpness = sd_ctrls[SD_SHARPNESS].qctrl.default_value;
  417. sd->effect = sd_ctrls[SD_EFFECTS].qctrl.default_value;
  418. return 0;
  419. }
  420. static int init_default_parameters(struct gspca_dev *gspca_dev)
  421. {
  422. /* some of this registers are not really neded, because
  423. * they are overriden by setbrigthness, setcontrast, etc,
  424. * but wont hurt anyway, and can help someone with similar webcam
  425. * to see the initial parameters.*/
  426. int i = 0;
  427. __u8 test_byte;
  428. static const __u8 read_indexs[] =
  429. { 0x06, 0x07, 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
  430. 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00, 0x00 };
  431. static const __u8 n1[6] =
  432. {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
  433. static const __u8 n2[2] =
  434. {0x08, 0x00};
  435. static const __u8 nset[6] =
  436. { 0x61, 0x68, 0x62, 0xff, 0x60, 0x07 };
  437. static const __u8 n3[6] =
  438. {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04};
  439. static const __u8 n4[0x46] =
  440. {0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
  441. 0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
  442. 0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
  443. 0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
  444. 0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
  445. 0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
  446. 0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
  447. 0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
  448. 0xac, 0x84, 0xad, 0x86, 0xaf, 0x46};
  449. static const __u8 nset4[18] = {
  450. 0xe0, 0x60, 0xe1, 0xa8, 0xe2, 0xe0, 0xe3, 0x60, 0xe4, 0xa8,
  451. 0xe5, 0xe0, 0xe6, 0x60, 0xe7, 0xa8,
  452. 0xe8, 0xe0
  453. };
  454. /* ojo puede ser 0xe6 en vez de 0xe9 */
  455. static const __u8 nset2[20] = {
  456. 0xd0, 0xbb, 0xd1, 0x28, 0xd2, 0x10, 0xd3, 0x10, 0xd4, 0xbb,
  457. 0xd5, 0x28, 0xd6, 0x1e, 0xd7, 0x27,
  458. 0xd8, 0xc8, 0xd9, 0xfc
  459. };
  460. static const __u8 missing[8] =
  461. { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
  462. static const __u8 nset3[18] = {
  463. 0xc7, 0x60, 0xc8, 0xa8, 0xc9, 0xe0, 0xca, 0x60, 0xcb, 0xa8,
  464. 0xcc, 0xe0, 0xcd, 0x60, 0xce, 0xa8,
  465. 0xcf, 0xe0
  466. };
  467. static const __u8 nset5[4] =
  468. { 0x8f, 0x24, 0xc3, 0x00 }; /* bright */
  469. static const __u8 nset6[34] = {
  470. 0x90, 0x00, 0x91, 0x1c, 0x92, 0x30, 0x93, 0x43, 0x94, 0x54,
  471. 0x95, 0x65, 0x96, 0x75, 0x97, 0x84,
  472. 0x98, 0x93, 0x99, 0xa1, 0x9a, 0xb0, 0x9b, 0xbd, 0x9c, 0xca,
  473. 0x9d, 0xd8, 0x9e, 0xe5, 0x9f, 0xf2,
  474. 0xa0, 0xff
  475. }; /* Gamma */
  476. static const __u8 nset7[4] =
  477. { 0x66, 0xca, 0xa8, 0xf8 }; /* 50/60 Hz */
  478. static const __u8 nset9[4] =
  479. { 0x0b, 0x04, 0x0a, 0x78 };
  480. static const __u8 nset8[6] =
  481. { 0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00 };
  482. static const __u8 nset10[6] =
  483. { 0x0c, 0x03, 0xab, 0x10, 0x81, 0x20 };
  484. reg_w(gspca_dev, 0x01, 0x0000, n1, 0x06);
  485. reg_w(gspca_dev, 0x01, 0x0000, nset, 0x06);
  486. reg_r_1(gspca_dev, 0x0063);
  487. reg_w(gspca_dev, 0x01, 0x0000, n2, 0x02);
  488. while (read_indexs[i] != 0x00) {
  489. test_byte = reg_r_1(gspca_dev, read_indexs[i]);
  490. PDEBUG(D_CONF, "Reg 0x%02x => 0x%02x", read_indexs[i],
  491. test_byte);
  492. i++;
  493. }
  494. reg_w(gspca_dev, 0x01, 0x0000, n3, 0x06);
  495. reg_w(gspca_dev, 0x01, 0x0000, n4, 0x46);
  496. reg_r_1(gspca_dev, 0x0080);
  497. reg_w(gspca_dev, 0x00, 0x2c80, NULL, 0);
  498. reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
  499. reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
  500. reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
  501. reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
  502. reg_w(gspca_dev, 0x00, 0x3880, NULL, 0);
  503. reg_w(gspca_dev, 0x00, 0x338e, NULL, 0);
  504. reg_w(gspca_dev, 0x01, 0x0000, nset5, 0x04);
  505. reg_w(gspca_dev, 0x00, 0x00a9, NULL, 0);
  506. reg_w(gspca_dev, 0x01, 0x0000, nset6, 0x22);
  507. reg_w(gspca_dev, 0x00, 0x86bb, NULL, 0);
  508. reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
  509. reg_w(gspca_dev, 0x01, 0x0000, missing, 0x08);
  510. reg_w(gspca_dev, 0x00, 0x2087, NULL, 0);
  511. reg_w(gspca_dev, 0x00, 0x2088, NULL, 0);
  512. reg_w(gspca_dev, 0x00, 0x2089, NULL, 0);
  513. reg_w(gspca_dev, 0x01, 0x0000, nset7, 0x04);
  514. reg_w(gspca_dev, 0x01, 0x0000, nset10, 0x06);
  515. reg_w(gspca_dev, 0x01, 0x0000, nset8, 0x06);
  516. reg_w(gspca_dev, 0x01, 0x0000, nset9, 0x04);
  517. reg_w(gspca_dev, 0x00, 0x2880, NULL, 0);
  518. reg_w(gspca_dev, 0x01, 0x0000, nset2, 0x14);
  519. reg_w(gspca_dev, 0x01, 0x0000, nset3, 0x12);
  520. reg_w(gspca_dev, 0x01, 0x0000, nset4, 0x12);
  521. return 0;
  522. }
  523. static void setbrightness(struct gspca_dev *gspca_dev)
  524. {
  525. struct sd *sd = (struct sd *) gspca_dev;
  526. unsigned int brightness;
  527. __u8 set6[4] = { 0x8f, 0x26, 0xc3, 0x80 };
  528. brightness = sd->brightness;
  529. if (brightness < 7) {
  530. set6[3] = 0x70 - (brightness * 0xa);
  531. } else {
  532. set6[1] = 0x24;
  533. set6[3] = 0x00 + ((brightness - 7) * 0xa);
  534. }
  535. reg_w(gspca_dev, 0x01, 0x0000, set6, 4);
  536. }
  537. static void setflip(struct gspca_dev *gspca_dev)
  538. {
  539. struct sd *sd = (struct sd *) gspca_dev;
  540. __u8 flipcmd[8] =
  541. { 0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09 };
  542. if (sd->mirror == 1)
  543. flipcmd[3] = 0x01;
  544. reg_w(gspca_dev, 0x01, 0x0000, flipcmd, 8);
  545. }
  546. static void seteffect(struct gspca_dev *gspca_dev)
  547. {
  548. struct sd *sd = (struct sd *) gspca_dev;
  549. reg_w(gspca_dev, 0x01, 0x0000, effects_table[sd->effect], 0x06);
  550. if (sd->effect == 1 || sd->effect == 5) {
  551. PDEBUG(D_CONF,
  552. "This effect have been disabled for webcam \"safety\"");
  553. return;
  554. }
  555. if (sd->effect == 1 || sd->effect == 4)
  556. reg_w(gspca_dev, 0x00, 0x4aa6, NULL, 0);
  557. else
  558. reg_w(gspca_dev, 0x00, 0xfaa6, NULL, 0);
  559. }
  560. static void setwhitebalance(struct gspca_dev *gspca_dev)
  561. {
  562. struct sd *sd = (struct sd *) gspca_dev;
  563. __u8 white_balance[8] =
  564. { 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x80, 0x38 };
  565. if (sd->whitebalance == 1)
  566. white_balance[7] = 0x3c;
  567. reg_w(gspca_dev, 0x01, 0x0000, white_balance, 8);
  568. }
  569. static void setlightfreq(struct gspca_dev *gspca_dev)
  570. {
  571. struct sd *sd = (struct sd *) gspca_dev;
  572. __u8 freq[4] = { 0x66, 0x40, 0xa8, 0xe8 };
  573. if (sd->freq == 2) /* 60hz */
  574. freq[1] = 0x00;
  575. reg_w(gspca_dev, 0x1, 0x0000, freq, 0x4);
  576. }
  577. static void setcontrast(struct gspca_dev *gspca_dev)
  578. {
  579. struct sd *sd = (struct sd *) gspca_dev;
  580. unsigned int contrast = sd->contrast;
  581. __u16 reg_to_write = 0x00;
  582. if (contrast < 7)
  583. reg_to_write = 0x8ea9 - (0x200 * contrast);
  584. else
  585. reg_to_write = (0x00a9 + ((contrast - 7) * 0x200));
  586. reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
  587. }
  588. static void setcolors(struct gspca_dev *gspca_dev)
  589. {
  590. struct sd *sd = (struct sd *) gspca_dev;
  591. __u16 reg_to_write;
  592. reg_to_write = 0xc0bb + sd->colors * 0x100;
  593. reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
  594. }
  595. static void setgamma(struct gspca_dev *gspca_dev)
  596. {
  597. }
  598. static void setsharpness(struct gspca_dev *gspca_dev)
  599. {
  600. struct sd *sd = (struct sd *) gspca_dev;
  601. __u16 reg_to_write;
  602. reg_to_write = 0x0aa6 + 0x1000 * sd->sharpness;
  603. reg_w(gspca_dev, 0x00, reg_to_write, NULL, 0);
  604. }
  605. static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
  606. {
  607. struct sd *sd = (struct sd *) gspca_dev;
  608. sd->brightness = val;
  609. if (gspca_dev->streaming)
  610. setbrightness(gspca_dev);
  611. return 0;
  612. }
  613. static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
  614. {
  615. struct sd *sd = (struct sd *) gspca_dev;
  616. *val = sd->brightness;
  617. return *val;
  618. }
  619. static int sd_setwhitebalance(struct gspca_dev *gspca_dev, __s32 val)
  620. {
  621. struct sd *sd = (struct sd *) gspca_dev;
  622. sd->whitebalance = val;
  623. if (gspca_dev->streaming)
  624. setwhitebalance(gspca_dev);
  625. return 0;
  626. }
  627. static int sd_getwhitebalance(struct gspca_dev *gspca_dev, __s32 *val)
  628. {
  629. struct sd *sd = (struct sd *) gspca_dev;
  630. *val = sd->whitebalance;
  631. return *val;
  632. }
  633. static int sd_setflip(struct gspca_dev *gspca_dev, __s32 val)
  634. {
  635. struct sd *sd = (struct sd *) gspca_dev;
  636. sd->mirror = val;
  637. if (gspca_dev->streaming)
  638. setflip(gspca_dev);
  639. return 0;
  640. }
  641. static int sd_getflip(struct gspca_dev *gspca_dev, __s32 *val)
  642. {
  643. struct sd *sd = (struct sd *) gspca_dev;
  644. *val = sd->mirror;
  645. return *val;
  646. }
  647. static int sd_seteffect(struct gspca_dev *gspca_dev, __s32 val)
  648. {
  649. struct sd *sd = (struct sd *) gspca_dev;
  650. sd->effect = val;
  651. if (gspca_dev->streaming)
  652. seteffect(gspca_dev);
  653. return 0;
  654. }
  655. static int sd_geteffect(struct gspca_dev *gspca_dev, __s32 *val)
  656. {
  657. struct sd *sd = (struct sd *) gspca_dev;
  658. *val = sd->effect;
  659. return *val;
  660. }
  661. static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
  662. {
  663. struct sd *sd = (struct sd *) gspca_dev;
  664. sd->contrast = val;
  665. if (gspca_dev->streaming)
  666. setcontrast(gspca_dev);
  667. return 0;
  668. }
  669. static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val)
  670. {
  671. struct sd *sd = (struct sd *) gspca_dev;
  672. *val = sd->contrast;
  673. return *val;
  674. }
  675. static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val)
  676. {
  677. struct sd *sd = (struct sd *) gspca_dev;
  678. sd->colors = val;
  679. if (gspca_dev->streaming)
  680. setcolors(gspca_dev);
  681. return 0;
  682. }
  683. static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
  684. {
  685. struct sd *sd = (struct sd *) gspca_dev;
  686. *val = sd->colors;
  687. return 0;
  688. }
  689. static int sd_setgamma(struct gspca_dev *gspca_dev, __s32 val)
  690. {
  691. struct sd *sd = (struct sd *) gspca_dev;
  692. sd->gamma = val;
  693. if (gspca_dev->streaming)
  694. setgamma(gspca_dev);
  695. return 0;
  696. }
  697. static int sd_getgamma(struct gspca_dev *gspca_dev, __s32 *val)
  698. {
  699. struct sd *sd = (struct sd *) gspca_dev;
  700. *val = sd->gamma;
  701. return 0;
  702. }
  703. static int sd_setfreq(struct gspca_dev *gspca_dev, __s32 val)
  704. {
  705. struct sd *sd = (struct sd *) gspca_dev;
  706. sd->freq = val;
  707. if (gspca_dev->streaming)
  708. setlightfreq(gspca_dev);
  709. return 0;
  710. }
  711. static int sd_getfreq(struct gspca_dev *gspca_dev, __s32 *val)
  712. {
  713. struct sd *sd = (struct sd *) gspca_dev;
  714. *val = sd->freq;
  715. return 0;
  716. }
  717. static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
  718. {
  719. struct sd *sd = (struct sd *) gspca_dev;
  720. sd->sharpness = val;
  721. if (gspca_dev->streaming)
  722. setsharpness(gspca_dev);
  723. return 0;
  724. }
  725. static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
  726. {
  727. struct sd *sd = (struct sd *) gspca_dev;
  728. *val = sd->sharpness;
  729. return 0;
  730. }
  731. /* Low Light set here......*/
  732. static int sd_setlowlight(struct gspca_dev *gspca_dev, __s32 val)
  733. {
  734. struct sd *sd = (struct sd *) gspca_dev;
  735. sd->autogain = val;
  736. if (val != 0)
  737. reg_w(gspca_dev, 0x00, 0xf48e, NULL, 0);
  738. else
  739. reg_w(gspca_dev, 0x00, 0xb48e, NULL, 0);
  740. return 0;
  741. }
  742. static int sd_getlowlight(struct gspca_dev *gspca_dev, __s32 *val)
  743. {
  744. struct sd *sd = (struct sd *) gspca_dev;
  745. *val = sd->autogain;
  746. return 0;
  747. }
  748. static void sd_start(struct gspca_dev *gspca_dev)
  749. {
  750. int mode;
  751. static const __u8 t1[] = { 0x66, 0x00, 0xa8, 0xe8 };
  752. __u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
  753. static const __u8 t3[] =
  754. { 0xb3, 0x07, 0xb4, 0x00, 0xb5, 0x88, 0xb6, 0x02, 0xb7, 0x06,
  755. 0xb8, 0x00, 0xb9, 0xe7, 0xba, 0x01 };
  756. static const __u8 t4[] = { 0x0b, 0x04, 0x0a, 0x40 };
  757. mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode]. priv;
  758. switch (mode) {
  759. case 1: /* 352x288 */
  760. t2[1] = 0x40;
  761. break;
  762. case 2: /* 320x240 */
  763. t2[1] = 0x10;
  764. break;
  765. case 3: /* 176x144 */
  766. t2[1] = 0x50;
  767. break;
  768. case 4: /* 160x120 */
  769. t2[1] = 0x20;
  770. break;
  771. default: /* 640x480 (0x00) */
  772. break;
  773. }
  774. reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[0], 0x8);
  775. reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[1], 0x8);
  776. reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[2], 0x8);
  777. reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
  778. reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
  779. /* just in case and to keep sync with logs (for mine) */
  780. reg_w(gspca_dev, 0x01, 0x0000, tas5130a_sensor_init[3], 0x8);
  781. reg_w(gspca_dev, 0x00, 0x3c80, NULL, 0);
  782. /* just in case and to keep sync with logs (for mine) */
  783. reg_w(gspca_dev, 0x01, 0x0000, t1, 4);
  784. reg_w(gspca_dev, 0x01, 0x0000, t2, 6);
  785. reg_r_1(gspca_dev, 0x0012);
  786. reg_w(gspca_dev, 0x01, 0x0000, t3, 0x10);
  787. reg_w(gspca_dev, 0x00, 0x0013, NULL, 0);
  788. reg_w(gspca_dev, 0x01, 0x0000, t4, 0x4);
  789. /* restart on each start, just in case, sometimes regs goes wrong
  790. * when using controls from app */
  791. setbrightness(gspca_dev);
  792. setcontrast(gspca_dev);
  793. setcolors(gspca_dev);
  794. }
  795. static void sd_stopN(struct gspca_dev *gspca_dev)
  796. {
  797. }
  798. static void sd_stop0(struct gspca_dev *gspca_dev)
  799. {
  800. }
  801. static void sd_close(struct gspca_dev *gspca_dev)
  802. {
  803. }
  804. static void sd_pkt_scan(struct gspca_dev *gspca_dev,
  805. struct gspca_frame *frame, /* target */
  806. __u8 *data, /* isoc packet */
  807. int len) /* iso packet length */
  808. {
  809. int sof = 0;
  810. static __u8 ffd9[] = { 0xff, 0xd9 };
  811. if (data[0] == 0x5a) {
  812. /* Control Packet, after this came the header again,
  813. * but extra bytes came in the packet before this,
  814. * sometimes an EOF arrives, sometimes not... */
  815. return;
  816. }
  817. if (data[len - 1] == 0xff && data[len] == 0xd9) {
  818. /* Just in case, i have seen packets with the marker,
  819. * other's do not include it... */
  820. data += 2;
  821. len -= 4;
  822. } else if (data[2] == 0xff && data[3] == 0xd8) {
  823. sof = 1;
  824. data += 2;
  825. len -= 2;
  826. } else {
  827. data += 2;
  828. len -= 2;
  829. }
  830. if (sof) {
  831. /* extra bytes....., could be processed too but would be
  832. * a waste of time, right now leave the application and
  833. * libjpeg do it for ourserlves.. */
  834. frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
  835. ffd9, 2);
  836. gspca_frame_add(gspca_dev, FIRST_PACKET, frame, data, len);
  837. return;
  838. }
  839. gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
  840. }
  841. static int sd_querymenu(struct gspca_dev *gspca_dev,
  842. struct v4l2_querymenu *menu)
  843. {
  844. switch (menu->id) {
  845. case V4L2_CID_POWER_LINE_FREQUENCY:
  846. switch (menu->index) {
  847. case 1: /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
  848. strcpy((char *) menu->name, "50 Hz");
  849. return 0;
  850. case 2: /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
  851. strcpy((char *) menu->name, "60 Hz");
  852. return 0;
  853. }
  854. break;
  855. case V4L2_CID_EFFECTS:
  856. if ((unsigned) menu->index < ARRAY_SIZE(effects_control)) {
  857. strncpy((char *) menu->name,
  858. effects_control[menu->index], 32);
  859. return 0;
  860. }
  861. break;
  862. }
  863. return -EINVAL;
  864. }
  865. /* this function is called at open time */
  866. static int sd_open(struct gspca_dev *gspca_dev)
  867. {
  868. init_default_parameters(gspca_dev);
  869. return 0;
  870. }
  871. /* sub-driver description */
  872. static const struct sd_desc sd_desc = {
  873. .name = MODULE_NAME,
  874. .ctrls = sd_ctrls,
  875. .nctrls = ARRAY_SIZE(sd_ctrls),
  876. .config = sd_config,
  877. .open = sd_open,
  878. .start = sd_start,
  879. .stopN = sd_stopN,
  880. .stop0 = sd_stop0,
  881. .close = sd_close,
  882. .pkt_scan = sd_pkt_scan,
  883. .querymenu = sd_querymenu,
  884. };
  885. /* -- module initialisation -- */
  886. #define DVNM(name) .driver_info = (kernel_ulong_t) name
  887. static const __devinitdata struct usb_device_id device_table[] = {
  888. {USB_DEVICE(0x17a1, 0x0128), DVNM("XPX Webcam")},
  889. {}
  890. };
  891. MODULE_DEVICE_TABLE(usb, device_table);
  892. /* -- device connect -- */
  893. static int sd_probe(struct usb_interface *intf,
  894. const struct usb_device_id *id)
  895. {
  896. return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
  897. THIS_MODULE);
  898. }
  899. static struct usb_driver sd_driver = {
  900. .name = MODULE_NAME,
  901. .id_table = device_table,
  902. .probe = sd_probe,
  903. .disconnect = gspca_disconnect,
  904. };
  905. /* -- module insert / remove -- */
  906. static int __init sd_mod_init(void)
  907. {
  908. if (usb_register(&sd_driver) < 0)
  909. return -1;
  910. PDEBUG(D_PROBE, "registered");
  911. return 0;
  912. }
  913. static void __exit sd_mod_exit(void)
  914. {
  915. usb_deregister(&sd_driver);
  916. PDEBUG(D_PROBE, "deregistered");
  917. }
  918. module_init(sd_mod_init);
  919. module_exit(sd_mod_exit);