vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / media / media-add-ons / usb_webcam / addons / NW80xCamDevice.cpp
bloba63b31d62b810dab5f6fecad0f2e528e7648d88a
1 /*
2 * Copyright 2004-2008, François Revol, <revol@free.fr>.
3 * Distributed under the terms of the MIT License.
4 */
6 #include "NW80xCamDevice.h"
7 #include "CamDebug.h"
8 #include "CamSensor.h"
10 // reference drivers:
11 // http://nw802.cvs.sourceforge.net
12 // http://nw802.cvs.sourceforge.net/nw802/nw802-2.4/
13 // http://www.medias.ne.jp/~takam/bsd/NetBSD.html#nw802
14 // https://dev.openwrt.org/attachment/ticket/2319/nw802-patch.txt
15 // win binary driver template, readme has interesting info:
16 // http://www.bulgar-bg.com/Downloads/drivers/PCAMDriver/
17 // http://www.bulgar-bg.com/Downloads/drivers/PCAMDriver/Readme.txt
19 const usb_webcam_support_descriptor kSupportedDevices[] = {
20 {{ 0, 0, 0, 0x046d, 0xd001 }, "Logitech", "QuickCam Pro", "??" }, // Alan's
21 // other IDs according to nw802 linux driver:
22 {{ 0, 0, 0, 0x052b, 0xd001 }, "Ezonics", "EZCam Pro", "??" },
23 {{ 0, 0, 0, 0x055f, 0xd001 }, "Mustek"/*"PCLine"*/, "WCam 300"/*"PCL-W300"*/, "??" },
24 {{ 0, 0, 0, 0x06a5, 0xd001 }, "Divio", "NW802", "??" },
25 {{ 0, 0, 0, 0x06a5, 0x0000 }, "Divio", "NW800", "??" },
26 {{ 0, 0, 0, 0, 0}, NULL, NULL, NULL }
30 #warning TODO!
32 // datasheets: (scarce)
33 // http://www.digchip.com/datasheets/parts/datasheet/132/NW800.php
34 // http://www.digchip.com/datasheets/parts/datasheet/132/NW802.php
35 // http://web.archive.org/web/*/divio.com/*
36 // http://web.archive.org/web/20020217173519/divio.com/NW802.html
38 // supported sensors:
39 // Sensor Model # Data Width Voltage Timing
40 // Conexant CN0352 10 bits 3.3 V Master
41 // Elecvision EVS110K 8 bits 3.3 V Slave
42 // HP (Agilent) HDC1000 10 bits 3.3 V Master
43 // Hyundai HB7121B 8 bits 3.3 V Master
44 // Pixart PAS006AC 9 bits 3.3 V Master
45 // TASC TAS5110A 9 bits 3.8 V Slave
47 // http://www.wifi.com.ar/english/doc/webcam/ov511cameras.html says:
48 // 06a5 (Divio) d800 Etoms ET31X110 (A.K.A Divio NW800)
50 NW80xCamDevice::NW80xCamDevice(CamDeviceAddon &_addon, BUSBDevice* _device)
51 :CamDevice(_addon, _device)
53 status_t err;
55 // linux seems to infer this sets I2C controller to 8 or 16 bit mode...
56 // sensors will set to the mode they want when probing
57 SetIICBitsMode(8);
58 err = ProbeSensor();
59 if (err < B_OK) {
60 // reset I2C mode to 8 bit as linux driver does
61 SetIICBitsMode(8);
62 // not much we can do anyway
65 fInitStatus = B_OK;
69 NW80xCamDevice::~NW80xCamDevice()
75 bool
76 NW80xCamDevice::SupportsBulk()
78 return true;
82 bool
83 NW80xCamDevice::SupportsIsochronous()
85 return true;
89 status_t
90 NW80xCamDevice::StartTransfer()
92 status_t err;
93 uint8 r;
95 SetScale(1);
96 if (Sensor())
97 SetVideoFrame(BRect(0, 0, Sensor()->MaxWidth()-1, Sensor()->MaxHeight()-1));
99 //SetVideoFrame(BRect(0, 0, 320-1, 240-1));
101 DumpRegs();
102 #if 0
103 err = ReadReg(SN9C102_CHIP_CTRL, &r, 1, true);
104 if (err < 0)
105 return err;
106 r |= 0x04;
107 err = WriteReg8(SN9C102_CHIP_CTRL, r);
108 if (err < 0)
109 return err;
110 #endif
111 return CamDevice::StartTransfer();
115 status_t
116 NW80xCamDevice::StopTransfer()
118 status_t err;
119 uint8 r;
121 DumpRegs();
122 err = CamDevice::StopTransfer();
123 #if 0
124 // if (err < 0)
125 // return err;
126 err = ReadReg(SN9C102_CHIP_CTRL, &r, 1, true);
127 if (err < 0)
128 return err;
129 r &= ~0x04;
130 err = WriteReg8(SN9C102_CHIP_CTRL, r);
131 if (err < 0)
132 return err;
133 #endif
134 return err;
138 ssize_t
139 NW80xCamDevice::WriteReg(uint16 address, uint8 *data, size_t count)
141 PRINT((CH "(%u, @%p, %u)" CT, address, data, count));
142 return SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, address, 0, count, data);
146 ssize_t
147 NW80xCamDevice::ReadReg(uint16 address, uint8 *data, size_t count, bool cached)
149 PRINT((CH "(%u, @%p, %u, %d)" CT, address, data, count, cached));
150 memset(data, 0xaa, count); // linux drivers do that without explaining why !?
151 return SendCommand(USB_REQTYPE_DEVICE_IN, 0x04, address, 0, count, data);
155 status_t
156 NW80xCamDevice::GetStatusIIC()
158 status_t err = B_ERROR;
159 uint8 status = 0;
160 #warning WRITEME
161 //dprintf(ID "i2c_status: error 0x%08lx, status = %02x\n", err, status);
162 if (err < 0)
163 return err;
164 return (status&0x08)?EIO:0;
168 status_t
169 NW80xCamDevice::WaitReadyIIC()
171 status_t err;
172 #warning WRITEME
173 return EBUSY;
177 ssize_t
178 NW80xCamDevice::WriteIIC(uint8 address, uint8 *data, size_t count)
180 status_t err;
181 int i;
182 uint8 buffer[0x23];
183 if (count > 16)
184 return EINVAL;
185 memset(buffer, 0, sizeof(buffer));
186 buffer[0x20] = Sensor() ? Sensor()->IICWriteAddress() : 0;
187 buffer[0x21] = count - 1;
188 buffer[0x22] = 0x01;
189 for (i = 0; i < count; i++) {
190 buffer[i] = address + i;
191 buffer[i+16] = data[i];
193 return SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, STV_I2C_WRITE, 0, 0x23, buffer);
197 ssize_t
198 NW80xCamDevice::ReadIIC(uint8 address, uint8 *data)
200 return ReadIIC(address, data);
204 ssize_t
205 NW80xCamDevice::ReadIIC8(uint8 address, uint8 *data)
207 status_t err;
208 int i;
209 uint8 buffer[0x23];
210 memset(buffer, 0, sizeof(buffer));
211 buffer[0x20] = Sensor() ? Sensor()->IICReadAddress() : 0;
212 buffer[0x21] = 1 - 1;
213 buffer[0x22] = 0x03;
214 buffer[0] = address;
215 err = SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, STV_I2C_WRITE, 0, 0x23, buffer);
216 PRINT((CH ": SendCommand: %s" CT, strerror(err)));
217 if (err < B_OK)
218 return err;
220 buffer[0] = 0xaa;
221 err = SendCommand(USB_REQTYPE_DEVICE_IN, 0x04, STV_I2C_READ, 0, 0x1, buffer);
222 PRINT((CH ": SendCommand: %s" CT, strerror(err)));
223 if (err < B_OK)
224 return err;
226 *data = buffer[0];
227 PRINT((CH ": 0x%02x" CT, *data));
228 return 1;
232 ssize_t
233 NW80xCamDevice::ReadIIC16(uint8 address, uint16 *data)
235 status_t err;
236 int i;
237 uint8 buffer[0x23];
238 memset(buffer, 0, sizeof(buffer));
239 buffer[0x20] = Sensor() ? Sensor()->IICReadAddress() : 0;
240 buffer[0x21] = 1 - 1;
241 buffer[0x22] = 0x03;
242 buffer[0] = address;
243 err = SendCommand(USB_REQTYPE_DEVICE_OUT, 0x04, STV_I2C_WRITE, 0, 0x23, buffer);
244 if (err < B_OK)
245 return err;
247 buffer[0] = 0xaa;
248 buffer[1] = 0xaa;
249 err = SendCommand(USB_REQTYPE_DEVICE_IN, 0x04, STV_I2C_READ, 0, 0x2, buffer);
250 PRINT((CH ": SendCommand: %s" CT, strerror(err)));
251 if (err < B_OK)
252 return err;
254 if (fChipIsBigEndian)
255 *data = B_HOST_TO_BENDIAN_INT16(*(uint16 *)(&buffer[0]));
256 else
257 *data = B_HOST_TO_LENDIAN_INT16(*(uint16 *)(&buffer[0]));
258 PRINT((CH ": 0x%04x" CT, *data));
259 return 2;
263 status_t
264 NW80xCamDevice::SetIICBitsMode(size_t bits)
266 switch (bits) {
267 case 8:
268 WriteReg8(STV_REG23, 0);
269 break;
270 case 16:
271 WriteReg8(STV_REG23, 1);
272 break;
273 default:
274 return EINVAL;
276 return B_OK;
280 status_t
281 NW80xCamDevice::SendCommand(uint8 dir, uint8 request, uint16 value,
282 uint16 index, uint16 length, void* data)
284 size_t ret;
285 if (!GetDevice())
286 return ENODEV;
287 if (length > GetDevice()->MaxEndpoint0PacketSize())
288 return EINVAL;
289 ret = GetDevice()->ControlTransfer(
290 USB_REQTYPE_VENDOR | dir,
291 request, value, index, length, data);
292 return ret;
296 NW80xCamDeviceAddon::NW80xCamDeviceAddon(WebCamMediaAddOn* webcam)
297 : CamDeviceAddon(webcam)
299 SetSupportedDevices(kSupportedDevices);
303 NW80xCamDeviceAddon::~NW80xCamDeviceAddon()
308 const char *
309 NW80xCamDeviceAddon::BrandName()
311 return "NW80x-based";
315 NW80xCamDevice *
316 NW80xCamDeviceAddon::Instantiate(CamRoster &roster, BUSBDevice *from)
318 return new NW80xCamDevice(*this, from);
322 extern "C" status_t
323 B_WEBCAM_MKINTFUNC(nw80xcam)
324 (WebCamMediaAddOn* webcam, CamDeviceAddon **addon)
326 *addon = new NW80xCamDeviceAddon(webcam);
327 return B_OK;