patch-vid_c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. $OpenBSD: patch-vid_c,v 1.4 2016/04/26 18:06:26 jca Exp $
  2. --- vid.c.orig Mon May 8 06:59:03 2000
  3. +++ vid.c Tue Apr 26 15:50:06 2016
  4. @@ -37,7 +37,7 @@
  5. #include <dev/usb/usb.h>
  6. -#include <pnm.h>
  7. +#include <netpbm/pnm.h>
  8. #include "vid.h"
  9. @@ -48,15 +48,15 @@ ov511_reg_read(int fd, int reg) {
  10. struct usb_ctl_request ur;
  11. unsigned char data[1024];
  12. - ur.request.bmRequestType = UT_READ_VENDOR_INTERFACE;
  13. - ur.request.bRequest = 2;
  14. + ur.ucr_request.bmRequestType = UT_READ_VENDOR_INTERFACE;
  15. + ur.ucr_request.bRequest = 2;
  16. - USETW(ur.request.wValue, 0); /* unused */
  17. - USETW(ur.request.wIndex, reg); /* index */
  18. - USETW(ur.request.wLength, 1); /* payload len in bytes */
  19. - ur.data = data;
  20. - ur.flags = 0;
  21. - ur.actlen = 0;
  22. + USETW(ur.ucr_request.wValue, 0); /* unused */
  23. + USETW(ur.ucr_request.wIndex, reg); /* index */
  24. + USETW(ur.ucr_request.wLength, 1); /* payload len in bytes */
  25. + ur.ucr_data = data;
  26. + ur.ucr_flags = 0;
  27. + ur.ucr_actlen = 0;
  28. if(ioctl(fd, USB_DO_REQUEST, &ur) < 0) {
  29. return -1;
  30. @@ -72,15 +72,15 @@ ov511_reg_write(int fd, int reg, int val) {
  31. data[0] = val;
  32. - ur.request.bmRequestType = UT_WRITE_VENDOR_INTERFACE;
  33. - ur.request.bRequest = 2;
  34. + ur.ucr_request.bmRequestType = UT_WRITE_VENDOR_INTERFACE;
  35. + ur.ucr_request.bRequest = 2;
  36. - USETW(ur.request.wValue, 0); /* unused */
  37. - USETW(ur.request.wIndex, reg); /* index */
  38. - USETW(ur.request.wLength, 1); /* payload len in bytes */
  39. - ur.data = data;
  40. - ur.flags = 0;
  41. - ur.actlen = 0;
  42. + USETW(ur.ucr_request.wValue, 0); /* unused */
  43. + USETW(ur.ucr_request.wIndex, reg); /* index */
  44. + USETW(ur.ucr_request.wLength, 1); /* payload len in bytes */
  45. + ur.ucr_data = data;
  46. + ur.ucr_flags = 0;
  47. + ur.ucr_actlen = 0;
  48. if(ioctl(fd, USB_DO_REQUEST, &ur) < 0) {
  49. return -1;
  50. @@ -213,16 +213,23 @@ main(int argc, char *argv[]) {
  51. char dev[FILENAME_MAX]; /* for constructing device names */
  52. char isocdev[FILENAME_MAX]; /* for constructing endpoint 1 device names */
  53. char *devname = NULL; /* device name */
  54. + char *p = NULL; /* for string ops */
  55. + int slen = -1; /* string length holder */
  56. + int plen = -1; /* string length holder */
  57. int len = -1; /* isochronous input read length */
  58. struct vidstate vs; /* current read state */
  59. int small = 0; /* use 320x240 */
  60. int frmnm = 0; /* cyclic frame number key */
  61. + int isplus; /* bridge is OV511+ if true, else OV511 */
  62. + int is20; /* sensor is OV7620 if true, else OV7610 */
  63. + int bufsize; /* size of packet buffer */
  64. +
  65. /* pnm_init(&argc, argv); */ /* required for PNM programs? */
  66. while(++argv, --argc) {
  67. if(strcmp(*argv, "--version") == 0) {
  68. - fprintf(stderr, "OV511 capture program version " VERSION
  69. + fprintf(stderr, "OV511/OV511+ capture program version " VERSION
  70. "\nCopyright 2000 Peter S. Housel"
  71. "\nThis program is free software; "
  72. "you may redistribute it under the terms of"
  73. @@ -235,7 +242,7 @@ main(int argc, char *argv[]) {
  74. exit(0);
  75. } else if(strcmp(*argv, "--help") == 0) {
  76. fprintf(stderr, "usage: vid [options]\n"
  77. - "Capture an image frame from an OV511-based USB video camera\n"
  78. + "Capture an image frame from an OV511/OV511+ based USB video camera\n"
  79. "and write image data to standard output in PNM format\n\n"
  80. "--version print program version information\n"
  81. "--usage summarize command line options\n"
  82. @@ -243,6 +250,7 @@ main(int argc, char *argv[]) {
  83. "--small capture as 320x240 image (default is 640x480)\n"
  84. "-d device, --device-name=device\n"
  85. " specify OV511 ugen device\n");
  86. + fprintf(stderr, "example: vid | pnmtojpeg > ~/public_html/mywebcam.jpg\n");
  87. exit(0);
  88. } else if(strcmp(*argv, "--small") == 0) {
  89. small = 1;
  90. @@ -287,18 +295,21 @@ main(int argc, char *argv[]) {
  91. exit(1);
  92. }
  93. - if(udi.vendorNo != 0x05A9 || udi.productNo != 0x0511) {
  94. - fprintf(stderr, "device %s is not an OmniVision OV511\n", devname);
  95. + if(udi.udi_vendorNo != 0x05A9 ||
  96. + (udi.udi_productNo != 0x0511 && udi.udi_productNo != 0xa511)) {
  97. + fprintf(stderr, "device %s is not an OmniVision OV511/OV511+\n", devname);
  98. exit(1);
  99. }
  100. } else {
  101. int i = 0;
  102. for(i = 0; i < 15; ++i) {
  103. - sprintf(dev, "/dev/ugen%d", i);
  104. + snprintf(dev, sizeof(dev), "/dev/ugen%d.00", i);
  105. if((fd = open(dev, O_RDWR)) < 0)
  106. continue;
  107. - if(ioctl(fd, USB_GET_DEVICEINFO, &udi) < 0
  108. - || udi.vendorNo != 0x05A9 || udi.productNo != 0x0511) {
  109. + if(ioctl(fd, USB_GET_DEVICEINFO, &udi) < 0 ||
  110. + udi.udi_vendorNo != 0x05A9 ||
  111. + (udi.udi_productNo != 0x0511 &&
  112. + udi.udi_productNo != 0xa511)) {
  113. close(fd);
  114. fd = -1;
  115. continue;
  116. @@ -308,12 +319,15 @@ main(int argc, char *argv[]) {
  117. }
  118. if(fd < 0) {
  119. - fprintf(stderr, "vid: couldn't locate an OV511 device\n");
  120. + fprintf(stderr, "vid: couldn't locate an OV511/OV511+ device\n");
  121. exit(1);
  122. }
  123. devname = dev;
  124. }
  125. +
  126. + isplus = udi.udi_productNo == 0xa511;
  127. + bufsize = (isplus ? 961 : 993);
  128. /* reset the OV511 */
  129. if(ov511_reg_write(fd, OV511_REG_RST, 0x7f) < 0)
  130. @@ -398,24 +412,57 @@ main(int argc, char *argv[]) {
  131. if(ov511_reg_write(fd, OV511_REG_CE_EN, 0x0) < 0)
  132. exit(1);
  133. - ov511_i2c_write(fd, OV7610_REG_RWB, 0x5);
  134. - ov511_i2c_write(fd, OV7610_REG_EC, 0xFF);
  135. - ov511_i2c_write(fd, OV7610_REG_COMB, 0x01);
  136. - ov511_i2c_write(fd, OV7610_REG_FD, 0x06);
  137. - ov511_i2c_write(fd, OV7610_REG_COME, 0x1c);
  138. - ov511_i2c_write(fd, OV7610_REG_COMF, 0x90);
  139. - ov511_i2c_write(fd, OV7610_REG_ECW, 0x2e);
  140. - ov511_i2c_write(fd, OV7610_REG_ECB, 0x7C);
  141. - ov511_i2c_write(fd, OV7610_REG_COMH, 0x24);
  142. - ov511_i2c_write(fd, OV7610_REG_EHSH, 0x04);
  143. - ov511_i2c_write(fd, OV7610_REG_EHSL, 0xAC);
  144. - ov511_i2c_write(fd, OV7610_REG_EXBK, 0xFE);
  145. - ov511_i2c_write(fd, OV7610_REG_COMJ, 0x93);
  146. - ov511_i2c_write(fd, OV7610_REG_BADJ, 0x48);
  147. - ov511_i2c_write(fd, OV7610_REG_COMK, 0x81);
  148. + /* This returns 0 if we have an OV7620 sensor */
  149. + if((is20 = ov511_i2c_read(fd, OV7610_REG_COMI)) < 0)
  150. + exit(1);
  151. + is20 = !is20;
  152. - ov511_i2c_write(fd, OV7610_REG_GAM, 0x04);
  153. + /* set up the OV7610/OV7620 */
  154. + if(is20) {
  155. + ov511_i2c_write(fd, OV7610_REG_EC, 0xff);
  156. + ov511_i2c_write(fd, OV7610_REG_FD, 0x06);
  157. + ov511_i2c_write(fd, OV7610_REG_COMH, 0x24);
  158. + ov511_i2c_write(fd, OV7610_REG_EHSL, 0xac);
  159. + ov511_i2c_write(fd, OV7610_REG_COMA, 0x00);
  160. + ov511_i2c_write(fd, OV7610_REG_COMH, 0x24);
  161. + ov511_i2c_write(fd, OV7610_REG_RWB, 0x85);
  162. + ov511_i2c_write(fd, OV7610_REG_COMD, 0x01);
  163. + ov511_i2c_write(fd, 0x23, 0x00);
  164. + ov511_i2c_write(fd, OV7610_REG_ECW, 0x10);
  165. + ov511_i2c_write(fd, OV7610_REG_ECB, 0x8a);
  166. + ov511_i2c_write(fd, OV7610_REG_COMG, 0xe2);
  167. + ov511_i2c_write(fd, OV7610_REG_EHSH, 0x00);
  168. + ov511_i2c_write(fd, OV7610_REG_EXBK, 0xfe);
  169. + ov511_i2c_write(fd, 0x30, 0x71);
  170. + ov511_i2c_write(fd, 0x31, 0x60);
  171. + ov511_i2c_write(fd, 0x32, 0x26);
  172. + ov511_i2c_write(fd, OV7610_REG_YGAM, 0x20);
  173. + ov511_i2c_write(fd, OV7610_REG_BADJ, 0x48);
  174. + ov511_i2c_write(fd, OV7610_REG_COMA, 0x24);
  175. + ov511_i2c_write(fd, OV7610_REG_SYN_CLK, 0x01);
  176. + ov511_i2c_write(fd, OV7610_REG_BBS, 0x24);
  177. + ov511_i2c_write(fd, OV7610_REG_RBS, 0x24);
  178. + } else {
  179. + ov511_i2c_write(fd, OV7610_REG_RWB, 0x5);
  180. + ov511_i2c_write(fd, OV7610_REG_EC, 0xFF);
  181. + ov511_i2c_write(fd, OV7610_REG_COMB, 0x01);
  182. + ov511_i2c_write(fd, OV7610_REG_FD, 0x06);
  183. + ov511_i2c_write(fd, OV7610_REG_COME, 0x1c);
  184. + ov511_i2c_write(fd, OV7610_REG_COMF, 0x90);
  185. + ov511_i2c_write(fd, OV7610_REG_ECW, 0x2e);
  186. + ov511_i2c_write(fd, OV7610_REG_ECB, 0x7C);
  187. + ov511_i2c_write(fd, OV7610_REG_COMH, 0x24);
  188. + ov511_i2c_write(fd, OV7610_REG_EHSH, 0x04);
  189. + ov511_i2c_write(fd, OV7610_REG_EHSL, 0xAC);
  190. + ov511_i2c_write(fd, OV7610_REG_EXBK, 0xFE);
  191. + ov511_i2c_write(fd, OV7610_REG_COMJ, 0x93);
  192. + ov511_i2c_write(fd, OV7610_REG_BADJ, 0x48);
  193. + ov511_i2c_write(fd, OV7610_REG_COMK, 0x81);
  194. + ov511_i2c_write(fd, OV7610_REG_GAM, 0x04);
  195. + }
  196. +
  197. +
  198. if(small) {
  199. vs.width = 320;
  200. vs.height = 240;
  201. @@ -442,14 +489,14 @@ main(int argc, char *argv[]) {
  202. ov511_reg_write(fd, OV511_REG_LNDV, 0x00);
  203. /* set FIFO format (993-byte packets) */
  204. - if(ov511_reg_write(fd, OV511_REG_PKSZ, 0x1F) < 0)
  205. + if(ov511_reg_write(fd, OV511_REG_PKSZ, bufsize/32) < 0)
  206. exit(1);
  207. if(ov511_reg_write(fd, OV511_REG_PKFMT, 0x03) < 0)
  208. exit(1);
  209. /* select the 993-byte alternative */
  210. - alt.interface_index = 0;
  211. - alt.alt_no = 1;
  212. + alt.uai_interface_index = 0;
  213. + alt.uai_alt_no = (isplus ? 7 : 1);
  214. if(ioctl(fd, USB_SET_ALTINTERFACE, &alt) < 0) {
  215. perror("USB_SET_ALTINTERFACE");
  216. exit(1);
  217. @@ -468,43 +515,62 @@ main(int argc, char *argv[]) {
  218. vs.xels = pnm_allocarray(vs.width, vs.height);
  219. /* open the isochronous endpoint (endpoint 1) */
  220. - sprintf(isocdev, "%s.1", devname);
  221. + /* first we need to construct the endpoint device from */
  222. + /* the given device */
  223. + p = strchr(devname, '.');
  224. + slen = strlen(devname);
  225. + if(p == NULL) {
  226. + /* there is no dot, just append the isoc endpoint */
  227. + /* this is horribly contrived and needs some work, */
  228. + /* at this point OpenBSD doesn't use /dev/ugenX so */
  229. + /* it will get fixed if soon */
  230. + snprintf(isocdev, sizeof(isocdev), "%s.01", devname);
  231. + } else {
  232. + /* there is a dot */
  233. + plen = strlen(p);
  234. + snprintf(isocdev, sizeof(isocdev), "%s", devname);
  235. + isocdev[slen - plen] = NULL;
  236. + snprintf(isocdev, sizeof(isocdev), "%s.01", isocdev);
  237. + }
  238. +
  239. if((isoc = open(isocdev, O_RDONLY)) < 0) {
  240. perror(isocdev);
  241. exit(1);
  242. }
  243. /* read, looking for start and end frames */
  244. - while(vs.state != DONE && (len = read(isoc, &buf, 993)) >= 0) {
  245. + while(vs.state != DONE && (len = read(isoc, &buf, bufsize)) >= 0) {
  246. if(buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0
  247. && buf[4] == 0 && buf[5] == 0 && buf[6] == 0 && buf[7] == 0
  248. - && (buf[8] & 0x80) == 0 && buf[992] == 0 && vs.state == SKIPPING) {
  249. + && (buf[8] & 0x80) == 0 && buf[bufsize-1] == 0 && vs.state == SKIPPING) {
  250. vs.state = READING;
  251. vs.iY = vs.jY = vs.iUV = vs.jUV = 0;
  252. vs.residue = 0;
  253. - procdata(&vs, buf + 9, 993 - 10);
  254. + procdata(&vs, buf + 9, bufsize - 10);
  255. } else if(buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0
  256. && buf[4] == 0 && buf[5] == 0 && buf[6] == 0 && buf[7] == 0
  257. - && (buf[8] & 0x80) == 0x80 && buf[992] == 0
  258. + && (buf[8] & 0x80) == 0x80 && buf[bufsize-1] == 0
  259. && vs.state == READING) {
  260. vs.state = DONE;
  261. } else if(vs.state == READING) {
  262. - procdata(&vs, buf, 993 - 1);
  263. + procdata(&vs, buf, bufsize - 1);
  264. /* abort the capture and start over if packets come in out-of-order */
  265. - if(buf[992] != frmnm && buf[992] != 1) {
  266. + if(buf[bufsize-1] != frmnm && buf[bufsize-1] != 1) {
  267. vs.state = SKIPPING;
  268. }
  269. - frmnm = buf[992] + 1;
  270. + frmnm = buf[bufsize-1] + 1;
  271. if(frmnm == 256)
  272. frmnm = 1;
  273. - } else if(buf[992] != 0) {
  274. - frmnm = buf[992] + 1;
  275. + } else if(buf[bufsize-1] != 0) {
  276. + frmnm = buf[bufsize-1] + 1;
  277. if(frmnm == 256)
  278. frmnm = 1;
  279. }
  280. }
  281. + /* reset and close the OV511 */
  282. + ov511_reg_write(fd, OV511_REG_RST, 0x7f);
  283. close(isoc);
  284. close(fd);