ultracam.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. /*
  2. * USB NB Camera driver
  3. *
  4. * HISTORY:
  5. * 25-Dec-2002 Dmitri Removed lighting, sharpness parameters, methods.
  6. */
  7. #include <linux/kernel.h>
  8. #include <linux/sched.h>
  9. #include <linux/module.h>
  10. #include <linux/init.h>
  11. #include "usbvideo.h"
  12. #define ULTRACAM_VENDOR_ID 0x0461
  13. #define ULTRACAM_PRODUCT_ID 0x0813
  14. #define MAX_CAMERAS 4 /* How many devices we allow to connect */
  15. /*
  16. * This structure lives in uvd_t->user field.
  17. */
  18. typedef struct {
  19. int initialized; /* Had we already sent init sequence? */
  20. int camera_model; /* What type of IBM camera we got? */
  21. int has_hdr;
  22. } ultracam_t;
  23. #define ULTRACAM_T(uvd) ((ultracam_t *)((uvd)->user_data))
  24. static struct usbvideo *cams = NULL;
  25. static int debug = 0;
  26. static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
  27. static const int min_canvasWidth = 8;
  28. static const int min_canvasHeight = 4;
  29. #define FRAMERATE_MIN 0
  30. #define FRAMERATE_MAX 6
  31. static int framerate = -1;
  32. /*
  33. * Here we define several initialization variables. They may
  34. * be used to automatically set color, hue, brightness and
  35. * contrast to desired values. This is particularly useful in
  36. * case of webcams (which have no controls and no on-screen
  37. * output) and also when a client V4L software is used that
  38. * does not have some of those controls. In any case it's
  39. * good to have startup values as options.
  40. *
  41. * These values are all in [0..255] range. This simplifies
  42. * operation. Note that actual values of V4L variables may
  43. * be scaled up (as much as << 8). User can see that only
  44. * on overlay output, however, or through a V4L client.
  45. */
  46. static int init_brightness = 128;
  47. static int init_contrast = 192;
  48. static int init_color = 128;
  49. static int init_hue = 128;
  50. static int hue_correction = 128;
  51. module_param(debug, int, S_IRUGO | S_IWUSR);
  52. MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
  53. module_param(flags, int, 0);
  54. MODULE_PARM_DESC(flags,
  55. "Bitfield: 0=VIDIOCSYNC, "
  56. "1=B/W, "
  57. "2=show hints, "
  58. "3=show stats, "
  59. "4=test pattern, "
  60. "5=separate frames, "
  61. "6=clean frames");
  62. module_param(framerate, int, 0);
  63. MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
  64. module_param(init_brightness, int, 0);
  65. MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
  66. module_param(init_contrast, int, 0);
  67. MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
  68. module_param(init_color, int, 0);
  69. MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)");
  70. module_param(init_hue, int, 0);
  71. MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");
  72. module_param(hue_correction, int, 0);
  73. MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");
  74. /*
  75. * ultracam_ProcessIsocData()
  76. *
  77. * Generic routine to parse the ring queue data. It employs either
  78. * ultracam_find_header() or ultracam_parse_lines() to do most
  79. * of work.
  80. *
  81. * 02-Nov-2000 First (mostly dummy) version.
  82. * 06-Nov-2000 Rewrote to dump all data into frame.
  83. */
  84. static void ultracam_ProcessIsocData(struct uvd *uvd, struct usbvideo_frame *frame)
  85. {
  86. int n;
  87. assert(uvd != NULL);
  88. assert(frame != NULL);
  89. /* Try to move data from queue into frame buffer */
  90. n = RingQueue_GetLength(&uvd->dp);
  91. if (n > 0) {
  92. int m;
  93. /* See how much spare we have left */
  94. m = uvd->max_frame_size - frame->seqRead_Length;
  95. if (n > m)
  96. n = m;
  97. /* Now move that much data into frame buffer */
  98. RingQueue_Dequeue(
  99. &uvd->dp,
  100. frame->data + frame->seqRead_Length,
  101. m);
  102. frame->seqRead_Length += m;
  103. }
  104. /* See if we filled the frame */
  105. if (frame->seqRead_Length >= uvd->max_frame_size) {
  106. frame->frameState = FrameState_Done;
  107. uvd->curframe = -1;
  108. uvd->stats.frame_num++;
  109. }
  110. }
  111. /*
  112. * ultracam_veio()
  113. *
  114. * History:
  115. * 1/27/00 Added check for dev == NULL; this happens if camera is unplugged.
  116. */
  117. static int ultracam_veio(
  118. struct uvd *uvd,
  119. unsigned char req,
  120. unsigned short value,
  121. unsigned short index,
  122. int is_out)
  123. {
  124. static const char proc[] = "ultracam_veio";
  125. unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */;
  126. int i;
  127. if (!CAMERA_IS_OPERATIONAL(uvd))
  128. return 0;
  129. if (!is_out) {
  130. i = usb_control_msg(
  131. uvd->dev,
  132. usb_rcvctrlpipe(uvd->dev, 0),
  133. req,
  134. USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  135. value,
  136. index,
  137. cp,
  138. sizeof(cp),
  139. 1000);
  140. #if 1
  141. info("USB => %02x%02x%02x%02x%02x%02x%02x%02x "
  142. "(req=$%02x val=$%04x ind=$%04x)",
  143. cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
  144. req, value, index);
  145. #endif
  146. } else {
  147. i = usb_control_msg(
  148. uvd->dev,
  149. usb_sndctrlpipe(uvd->dev, 0),
  150. req,
  151. USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  152. value,
  153. index,
  154. NULL,
  155. 0,
  156. 1000);
  157. }
  158. if (i < 0) {
  159. err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.",
  160. proc, i);
  161. uvd->last_error = i;
  162. }
  163. return i;
  164. }
  165. /*
  166. * ultracam_calculate_fps()
  167. */
  168. static int ultracam_calculate_fps(struct uvd *uvd)
  169. {
  170. return 3 + framerate*4 + framerate/2;
  171. }
  172. /*
  173. * ultracam_adjust_contrast()
  174. */
  175. static void ultracam_adjust_contrast(struct uvd *uvd)
  176. {
  177. }
  178. /*
  179. * ultracam_set_brightness()
  180. *
  181. * This procedure changes brightness of the picture.
  182. */
  183. static void ultracam_set_brightness(struct uvd *uvd)
  184. {
  185. }
  186. static void ultracam_set_hue(struct uvd *uvd)
  187. {
  188. }
  189. /*
  190. * ultracam_adjust_picture()
  191. *
  192. * This procedure gets called from V4L interface to update picture settings.
  193. * Here we change brightness and contrast.
  194. */
  195. static void ultracam_adjust_picture(struct uvd *uvd)
  196. {
  197. ultracam_adjust_contrast(uvd);
  198. ultracam_set_brightness(uvd);
  199. ultracam_set_hue(uvd);
  200. }
  201. /*
  202. * ultracam_video_stop()
  203. *
  204. * This code tells camera to stop streaming. The interface remains
  205. * configured and bandwidth - claimed.
  206. */
  207. static void ultracam_video_stop(struct uvd *uvd)
  208. {
  209. }
  210. /*
  211. * ultracam_reinit_iso()
  212. *
  213. * This procedure sends couple of commands to the camera and then
  214. * resets the video pipe. This sequence was observed to reinit the
  215. * camera or, at least, to initiate ISO data stream.
  216. */
  217. static void ultracam_reinit_iso(struct uvd *uvd, int do_stop)
  218. {
  219. }
  220. static void ultracam_video_start(struct uvd *uvd)
  221. {
  222. ultracam_reinit_iso(uvd, 0);
  223. }
  224. static int ultracam_resetPipe(struct uvd *uvd)
  225. {
  226. usb_clear_halt(uvd->dev, uvd->video_endp);
  227. return 0;
  228. }
  229. static int ultracam_alternateSetting(struct uvd *uvd, int setting)
  230. {
  231. static const char proc[] = "ultracam_alternateSetting";
  232. int i;
  233. i = usb_set_interface(uvd->dev, uvd->iface, setting);
  234. if (i < 0) {
  235. err("%s: usb_set_interface error", proc);
  236. uvd->last_error = i;
  237. return -EBUSY;
  238. }
  239. return 0;
  240. }
  241. /*
  242. * Return negative code on failure, 0 on success.
  243. */
  244. static int ultracam_setup_on_open(struct uvd *uvd)
  245. {
  246. int setup_ok = 0; /* Success by default */
  247. /* Send init sequence only once, it's large! */
  248. if (!ULTRACAM_T(uvd)->initialized) {
  249. ultracam_alternateSetting(uvd, 0x04);
  250. ultracam_alternateSetting(uvd, 0x00);
  251. ultracam_veio(uvd, 0x02, 0x0004, 0x000b, 1);
  252. ultracam_veio(uvd, 0x02, 0x0001, 0x0005, 1);
  253. ultracam_veio(uvd, 0x02, 0x8000, 0x0000, 1);
  254. ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1);
  255. ultracam_veio(uvd, 0x00, 0x00b0, 0x0001, 1);
  256. ultracam_veio(uvd, 0x00, 0x0000, 0x0002, 1);
  257. ultracam_veio(uvd, 0x00, 0x000c, 0x0003, 1);
  258. ultracam_veio(uvd, 0x00, 0x000b, 0x0004, 1);
  259. ultracam_veio(uvd, 0x00, 0x0000, 0x0005, 1);
  260. ultracam_veio(uvd, 0x00, 0x0000, 0x0006, 1);
  261. ultracam_veio(uvd, 0x00, 0x0079, 0x0007, 1);
  262. ultracam_veio(uvd, 0x00, 0x003b, 0x0008, 1);
  263. ultracam_veio(uvd, 0x00, 0x0002, 0x000f, 1);
  264. ultracam_veio(uvd, 0x00, 0x0001, 0x0010, 1);
  265. ultracam_veio(uvd, 0x00, 0x0000, 0x0011, 1);
  266. ultracam_veio(uvd, 0x00, 0x0000, 0x00bf, 1);
  267. ultracam_veio(uvd, 0x00, 0x0001, 0x00c0, 1);
  268. ultracam_veio(uvd, 0x00, 0x0010, 0x00cb, 1);
  269. ultracam_veio(uvd, 0x01, 0x00a4, 0x0001, 1);
  270. ultracam_veio(uvd, 0x01, 0x0010, 0x0002, 1);
  271. ultracam_veio(uvd, 0x01, 0x0066, 0x0007, 1);
  272. ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1);
  273. ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1);
  274. ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1);
  275. ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1);
  276. ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1);
  277. ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1);
  278. ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1);
  279. ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1);
  280. ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1);
  281. ultracam_veio(uvd, 0x01, 0x000b, 0x0011, 1);
  282. ultracam_veio(uvd, 0x01, 0x0001, 0x0012, 1);
  283. ultracam_veio(uvd, 0x01, 0x0000, 0x0013, 1);
  284. ultracam_veio(uvd, 0x01, 0x0000, 0x0014, 1);
  285. ultracam_veio(uvd, 0x01, 0x0087, 0x0051, 1);
  286. ultracam_veio(uvd, 0x01, 0x0040, 0x0052, 1);
  287. ultracam_veio(uvd, 0x01, 0x0058, 0x0053, 1);
  288. ultracam_veio(uvd, 0x01, 0x0040, 0x0054, 1);
  289. ultracam_veio(uvd, 0x01, 0x0000, 0x0040, 1);
  290. ultracam_veio(uvd, 0x01, 0x0010, 0x0041, 1);
  291. ultracam_veio(uvd, 0x01, 0x0020, 0x0042, 1);
  292. ultracam_veio(uvd, 0x01, 0x0030, 0x0043, 1);
  293. ultracam_veio(uvd, 0x01, 0x0040, 0x0044, 1);
  294. ultracam_veio(uvd, 0x01, 0x0050, 0x0045, 1);
  295. ultracam_veio(uvd, 0x01, 0x0060, 0x0046, 1);
  296. ultracam_veio(uvd, 0x01, 0x0070, 0x0047, 1);
  297. ultracam_veio(uvd, 0x01, 0x0080, 0x0048, 1);
  298. ultracam_veio(uvd, 0x01, 0x0090, 0x0049, 1);
  299. ultracam_veio(uvd, 0x01, 0x00a0, 0x004a, 1);
  300. ultracam_veio(uvd, 0x01, 0x00b0, 0x004b, 1);
  301. ultracam_veio(uvd, 0x01, 0x00c0, 0x004c, 1);
  302. ultracam_veio(uvd, 0x01, 0x00d0, 0x004d, 1);
  303. ultracam_veio(uvd, 0x01, 0x00e0, 0x004e, 1);
  304. ultracam_veio(uvd, 0x01, 0x00f0, 0x004f, 1);
  305. ultracam_veio(uvd, 0x01, 0x00ff, 0x0050, 1);
  306. ultracam_veio(uvd, 0x01, 0x0000, 0x0056, 1);
  307. ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1);
  308. ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1);
  309. ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
  310. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  311. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  312. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  313. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  314. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  315. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  316. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  317. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  318. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  319. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  320. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  321. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  322. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  323. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  324. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  325. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  326. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  327. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  328. ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1);
  329. ultracam_veio(uvd, 0x00, 0x0004, 0x00c2, 1);
  330. ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
  331. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  332. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  333. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  334. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  335. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  336. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  337. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  338. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  339. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  340. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  341. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  342. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  343. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  344. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  345. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  346. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  347. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  348. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  349. ultracam_veio(uvd, 0x00, 0x0002, 0x00c1, 1);
  350. ultracam_veio(uvd, 0x00, 0x0020, 0x00c2, 1);
  351. ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
  352. ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
  353. ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
  354. ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
  355. ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
  356. ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
  357. ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
  358. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  359. ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
  360. ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
  361. ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
  362. ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
  363. ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
  364. ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
  365. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  366. ultracam_veio(uvd, 0x00, 0x0040, 0x00c1, 1);
  367. ultracam_veio(uvd, 0x00, 0x0017, 0x00c2, 1);
  368. ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
  369. ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
  370. ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
  371. ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
  372. ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
  373. ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
  374. ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
  375. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  376. ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
  377. ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
  378. ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
  379. ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
  380. ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
  381. ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
  382. ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
  383. ultracam_veio(uvd, 0x00, 0x00c0, 0x00c1, 1);
  384. ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1);
  385. ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
  386. ultracam_veio(uvd, 0x02, 0xc040, 0x0001, 1);
  387. ultracam_veio(uvd, 0x01, 0x0000, 0x0008, 0);
  388. ultracam_veio(uvd, 0x01, 0x0000, 0x0009, 0);
  389. ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 0);
  390. ultracam_veio(uvd, 0x01, 0x0000, 0x000b, 0);
  391. ultracam_veio(uvd, 0x01, 0x0000, 0x000c, 0);
  392. ultracam_veio(uvd, 0x01, 0x0000, 0x000d, 0);
  393. ultracam_veio(uvd, 0x01, 0x0000, 0x000e, 0);
  394. ultracam_veio(uvd, 0x01, 0x0000, 0x000f, 0);
  395. ultracam_veio(uvd, 0x01, 0x0000, 0x0010, 0);
  396. ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1);
  397. ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1);
  398. ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1);
  399. ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1);
  400. ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1);
  401. ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1);
  402. ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1);
  403. ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1);
  404. ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1);
  405. ultracam_veio(uvd, 0x01, 0x0000, 0x0001, 0);
  406. ultracam_veio(uvd, 0x01, 0x0064, 0x0001, 1);
  407. ultracam_veio(uvd, 0x01, 0x0059, 0x0051, 1);
  408. ultracam_veio(uvd, 0x01, 0x003f, 0x0052, 1);
  409. ultracam_veio(uvd, 0x01, 0x0094, 0x0053, 1);
  410. ultracam_veio(uvd, 0x01, 0x00ff, 0x0011, 1);
  411. ultracam_veio(uvd, 0x01, 0x0003, 0x0012, 1);
  412. ultracam_veio(uvd, 0x01, 0x00f7, 0x0013, 1);
  413. ultracam_veio(uvd, 0x00, 0x0009, 0x0011, 1);
  414. ultracam_veio(uvd, 0x00, 0x0000, 0x0001, 1);
  415. ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1);
  416. ultracam_veio(uvd, 0x00, 0x0020, 0x00c1, 1);
  417. ultracam_veio(uvd, 0x00, 0x0010, 0x00c2, 1);
  418. ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
  419. ultracam_alternateSetting(uvd, 0x04);
  420. ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1);
  421. ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1);
  422. ultracam_veio(uvd, 0x02, 0x0000, 0x0006, 1);
  423. ultracam_veio(uvd, 0x02, 0x9000, 0x0007, 1);
  424. ultracam_veio(uvd, 0x02, 0x0042, 0x0001, 1);
  425. ultracam_veio(uvd, 0x02, 0x0000, 0x000b, 0);
  426. ultracam_resetPipe(uvd);
  427. ULTRACAM_T(uvd)->initialized = (setup_ok != 0);
  428. }
  429. return setup_ok;
  430. }
  431. static void ultracam_configure_video(struct uvd *uvd)
  432. {
  433. if (uvd == NULL)
  434. return;
  435. RESTRICT_TO_RANGE(init_brightness, 0, 255);
  436. RESTRICT_TO_RANGE(init_contrast, 0, 255);
  437. RESTRICT_TO_RANGE(init_color, 0, 255);
  438. RESTRICT_TO_RANGE(init_hue, 0, 255);
  439. RESTRICT_TO_RANGE(hue_correction, 0, 255);
  440. memset(&uvd->vpic, 0, sizeof(uvd->vpic));
  441. memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
  442. uvd->vpic.colour = init_color << 8;
  443. uvd->vpic.hue = init_hue << 8;
  444. uvd->vpic.brightness = init_brightness << 8;
  445. uvd->vpic.contrast = init_contrast << 8;
  446. uvd->vpic.whiteness = 105 << 8; /* This one isn't used */
  447. uvd->vpic.depth = 24;
  448. uvd->vpic.palette = VIDEO_PALETTE_RGB24;
  449. memset(&uvd->vcap, 0, sizeof(uvd->vcap));
  450. strcpy(uvd->vcap.name, "IBM Ultra Camera");
  451. uvd->vcap.type = VID_TYPE_CAPTURE;
  452. uvd->vcap.channels = 1;
  453. uvd->vcap.audios = 0;
  454. uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas);
  455. uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas);
  456. uvd->vcap.minwidth = min_canvasWidth;
  457. uvd->vcap.minheight = min_canvasHeight;
  458. memset(&uvd->vchan, 0, sizeof(uvd->vchan));
  459. uvd->vchan.flags = 0;
  460. uvd->vchan.tuners = 0;
  461. uvd->vchan.channel = 0;
  462. uvd->vchan.type = VIDEO_TYPE_CAMERA;
  463. strcpy(uvd->vchan.name, "Camera");
  464. }
  465. /*
  466. * ultracam_probe()
  467. *
  468. * This procedure queries device descriptor and accepts the interface
  469. * if it looks like our camera.
  470. *
  471. * History:
  472. * 12-Nov-2000 Reworked to comply with new probe() signature.
  473. * 23-Jan-2001 Added compatibility with 2.2.x kernels.
  474. */
  475. static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id *devid)
  476. {
  477. struct usb_device *dev = interface_to_usbdev(intf);
  478. struct uvd *uvd = NULL;
  479. int ix, i, nas;
  480. int actInterface=-1, inactInterface=-1, maxPS=0;
  481. unsigned char video_ep = 0;
  482. if (debug >= 1)
  483. info("ultracam_probe(%p)", intf);
  484. /* We don't handle multi-config cameras */
  485. if (dev->descriptor.bNumConfigurations != 1)
  486. return -ENODEV;
  487. info("IBM Ultra camera found (rev. 0x%04x)",
  488. le16_to_cpu(dev->descriptor.bcdDevice));
  489. /* Validate found interface: must have one ISO endpoint */
  490. nas = intf->num_altsetting;
  491. if (debug > 0)
  492. info("Number of alternate settings=%d.", nas);
  493. if (nas < 8) {
  494. err("Too few alternate settings for this camera!");
  495. return -ENODEV;
  496. }
  497. /* Validate all alternate settings */
  498. for (ix=0; ix < nas; ix++) {
  499. const struct usb_host_interface *interface;
  500. const struct usb_endpoint_descriptor *endpoint;
  501. interface = &intf->altsetting[ix];
  502. i = interface->desc.bAlternateSetting;
  503. if (interface->desc.bNumEndpoints != 1) {
  504. err("Interface %d. has %u. endpoints!",
  505. interface->desc.bInterfaceNumber,
  506. (unsigned)(interface->desc.bNumEndpoints));
  507. return -ENODEV;
  508. }
  509. endpoint = &interface->endpoint[0].desc;
  510. if (video_ep == 0)
  511. video_ep = endpoint->bEndpointAddress;
  512. else if (video_ep != endpoint->bEndpointAddress) {
  513. err("Alternate settings have different endpoint addresses!");
  514. return -ENODEV;
  515. }
  516. if ((endpoint->bmAttributes & 0x03) != 0x01) {
  517. err("Interface %d. has non-ISO endpoint!",
  518. interface->desc.bInterfaceNumber);
  519. return -ENODEV;
  520. }
  521. if ((endpoint->bEndpointAddress & 0x80) == 0) {
  522. err("Interface %d. has ISO OUT endpoint!",
  523. interface->desc.bInterfaceNumber);
  524. return -ENODEV;
  525. }
  526. if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) {
  527. if (inactInterface < 0)
  528. inactInterface = i;
  529. else {
  530. err("More than one inactive alt. setting!");
  531. return -ENODEV;
  532. }
  533. } else {
  534. if (actInterface < 0) {
  535. actInterface = i;
  536. maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
  537. if (debug > 0)
  538. info("Active setting=%d. maxPS=%d.", i, maxPS);
  539. } else {
  540. /* Got another active alt. setting */
  541. if (maxPS < le16_to_cpu(endpoint->wMaxPacketSize)) {
  542. /* This one is better! */
  543. actInterface = i;
  544. maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
  545. if (debug > 0) {
  546. info("Even better ctive setting=%d. maxPS=%d.",
  547. i, maxPS);
  548. }
  549. }
  550. }
  551. }
  552. }
  553. if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) {
  554. err("Failed to recognize the camera!");
  555. return -ENODEV;
  556. }
  557. uvd = usbvideo_AllocateDevice(cams);
  558. if (uvd != NULL) {
  559. /* Here uvd is a fully allocated uvd object */
  560. uvd->flags = flags;
  561. uvd->debug = debug;
  562. uvd->dev = dev;
  563. uvd->iface = intf->altsetting->desc.bInterfaceNumber;
  564. uvd->ifaceAltInactive = inactInterface;
  565. uvd->ifaceAltActive = actInterface;
  566. uvd->video_endp = video_ep;
  567. uvd->iso_packet_len = maxPS;
  568. uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24;
  569. uvd->defaultPalette = VIDEO_PALETTE_RGB24;
  570. uvd->canvas = VIDEOSIZE(640, 480); /* FIXME */
  571. uvd->videosize = uvd->canvas; /* ultracam_size_to_videosize(size);*/
  572. /* Initialize ibmcam-specific data */
  573. assert(ULTRACAM_T(uvd) != NULL);
  574. ULTRACAM_T(uvd)->camera_model = 0; /* Not used yet */
  575. ULTRACAM_T(uvd)->initialized = 0;
  576. ultracam_configure_video(uvd);
  577. i = usbvideo_RegisterVideoDevice(uvd);
  578. if (i != 0) {
  579. err("usbvideo_RegisterVideoDevice() failed.");
  580. uvd = NULL;
  581. }
  582. }
  583. if (uvd) {
  584. usb_set_intfdata (intf, uvd);
  585. return 0;
  586. }
  587. return -EIO;
  588. }
  589. static struct usb_device_id id_table[] = {
  590. { USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) },
  591. { } /* Terminating entry */
  592. };
  593. /*
  594. * ultracam_init()
  595. *
  596. * This code is run to initialize the driver.
  597. */
  598. static int __init ultracam_init(void)
  599. {
  600. struct usbvideo_cb cbTbl;
  601. memset(&cbTbl, 0, sizeof(cbTbl));
  602. cbTbl.probe = ultracam_probe;
  603. cbTbl.setupOnOpen = ultracam_setup_on_open;
  604. cbTbl.videoStart = ultracam_video_start;
  605. cbTbl.videoStop = ultracam_video_stop;
  606. cbTbl.processData = ultracam_ProcessIsocData;
  607. cbTbl.postProcess = usbvideo_DeinterlaceFrame;
  608. cbTbl.adjustPicture = ultracam_adjust_picture;
  609. cbTbl.getFPS = ultracam_calculate_fps;
  610. return usbvideo_register(
  611. &cams,
  612. MAX_CAMERAS,
  613. sizeof(ultracam_t),
  614. "ultracam",
  615. &cbTbl,
  616. THIS_MODULE,
  617. id_table);
  618. }
  619. static void __exit ultracam_cleanup(void)
  620. {
  621. usbvideo_Deregister(&cams);
  622. }
  623. MODULE_DEVICE_TABLE(usb, id_table);
  624. MODULE_LICENSE("GPL");
  625. module_init(ultracam_init);
  626. module_exit(ultracam_cleanup);