PWC - Application Programming Interface

Application Programming Interface for PWC 10+


This is the new API (Application Programming Interface) document for the Philips webcams - pwc version 10.X and on. The API is an extention to the normal Video4Linux API

The V4L API was intended for TV grabber cards and not for webcams. It does not support all the features that webcams have. For example: the framerate of the Philips webcams can be changed. A TV card always uses a fixed rate which is controlled by the video signal.

To write programs for Philips webcams you will also need the Video4Linux (V4L) API document.

You will find that in the Linux sources in the path ---/Documentation/video4linux/API.html

Header Files

In order to write programs the Philips webcam you will need the file pwc-ioctl.h from your pwc sources. Make sure you include an up to date version in your program. This file lists a all the unique private pwc ioctl() calls and #defines.

You must program in a language that supports the ioctl() call, like C, or has a C interface.

Add these includes at the top of your source file(s) that calls the pwc driver module:

#include "pwc-ioctl.h"

Detection of Camera Type

Normally detection of a V4L device is done using the VIDIOCGCAP ioctl(). For better detection of specific pwc compatible camera, detection can be handled using the VIDIOCPWCPROBE ioctl().

After you open() the device, you use the VIDIOCGCAP ioctl() to get a struct video_capability which has a 'name' field. This name field is filled with either the following pattern:

Philips %d webcam

where %d is the model number (645, 646, 675, 730, etc)

or any of the other names (Samsung MPC-C10, Creative Labs Webcam 5, etc.).

To detect a pwc compatible camera use the VIDIOCPWCPROBE call and see if it returns valid data.

Example (pseudo) code:

struct video_capability vcap;
struct pwc_probe probe;
int type;
bool IsPhilips;

IsPhilips = FALSE;
if (ioctl(cam_fd, VIDIOCGCAP, &vcap) < 0)
if (sscanf(, "Philips %d webcam", &type) == 1)
    IsPhilips = TRUE;
    /* No match yet; try the PROBE */
    if (ioctl(cam_fd, VIDIOCPWCPROBE, &probe) == 0)
        if (strcmp(,
            IsPhilips = TRUE;
            type = probe.type;

Supported libc functions

The driver supports the following libc functions:

  • select() ( and poll() )
  • read()
  • mmap()

Even if it is possible to open the /dev/video# device as read-write, trying to write() to the device will result in an error. Only one process at a time can open the device.

You can read the entire image in one go. You can also do partial reads. When you reach the end of the image buffer you will not read across the images border between current and next image. Only the remaining bytes in the buffer will be returned.

read() will normally block until an image is available. If you open the device with O_NONBLOCK read() will return -EAGAIN when no image is available. You are advised to use the select() call with only the bit in the 'readfds' set.

In case you are using mmap() the select() call will return when an image is available.

Additions to the standard Video4Linux API

The Video4Linux 1 API (Linux sources in the path ---/Documentation/video4linux/API.html) was originally made for video capture cards. Please note that:

  • Some of the V4L functions defined are not valid for a webcam.
  • The V4L standard misses som important important ioctl() calls, like querying the current input setting (most TV cards have multiple inputs, one for tuner, one for S-VHS, etc). But there is no way to ask which input has currently been selected. The same applies to the tuner.
  • The API makes a distinction between input and tuners. You can query which inputs and tuners there are but not which tuner is connected to which input. This is usally not a problem, since most cards will only have one tuner attached to one input.


This ioctl call takes a struct video_channel as argument, just like its counterpart VIDIOCGCHAN.

The V4L API document says something else but this seems to be an error in the document.


The 'whiteness' field in struct video_picture is used for the gamma setting of the cameras in the pwc driver. The other three settings: brightness, contrast and colour (saturation) work as normal. Some older models do not have colour saturation in which case this setting is ignored.

When a setting is not supported, the VIDIOGPICT call returns the value 0xFFFF in the unsupported fields. This value is not returned during normal operation.

The struct video_picture also has a palette field, which is described in a separate chapter below. A value of 0 leaves the current palette intact.


Set/get size and framerate.

The pwc driver supports any image size between the minimum and maximum size. For image sizes that are not directly supported by the camera, the image is padded with a gray border. It selects a format that is smaller or equal to the requested size and adds the gray border around it.

If you do a VIDIOCGWIN call right after VIDIOCSWIN you know exactly what resolution will be used.

If a cell is blank it means the combination of resolution and framerate is not supported. A DONE means the combination is supported uncompressed and PICK indicates that combination is only available in compressed mode.

Size PCA 645/646 & VC010
3.75 5 7.5 10 12 15 20 24
QSIF 160x120                
SIF 320x240                
VGA 640x480                

Size PCVC 675/680/690
5 10 15 20 25 30
VGA 640x480 PICK PICK PICK      

Size PCVC 730/740/750
5 10 15 20 25 30
sQCIF 128x96            
QCIF 176x144            
CIF 352x288            
VGA 640x480 PICK PICK PICK      

The VIDIOCSWIN call is also used to set the frame rate. A TV grabber card doesn't have this, since its 'framerate' is given by the video signal (50 Hz for PAL/SECAM, and 59.94 Hz for NTSC 1). The framerate setting was added to the VIDIOCSWIN call for a good reason. Some combinations of size and framerate are not allowed, and if size and framerate were set in 2 separate calls, this would make it difficult to 'reach' some of these combinations. Now, you immediately know the setting was not valid because ioctl() returned -EINVAL.

The frame rate is defined in the higher 16 bits of the 'flags' field, since some of the lower 16 bits are already used by Video4Linux.

Bits 31..23 21..16 15.. 0
Function None, set to 0 Framerate Reserved for V4L

Note that the framerate is given by 6 bits. The higher 10 bits are undefined and should be 0.

Normally the framerate should be number between 4 and 30. If you set the framerate bits to 0, the current framerate is unchanged. This way the VIDIOCSWIN call is backwards compatible with current applications who normally set this field to 0, or use the previous value from a VIDIOCGWIN call. To set a framerate of 3.75 or 7.5 Hz, use a framerate of 4 or 8. You can use any value between 4 and 30, The driver will choose the nearest framerate. If you set a framerate which is not supported by the device the driver will return errors. For critical applications, use a VIDIOCGWIN call to query the actual framerate.

Use these defines from pwc-ioctl.h to filter out or set the framerate settings:

Bit shift for the framerate bits.
Bit mask for both the framerate and snapshot setting. If flags & PWC_FPS_FRMASK = 0, and you detected a Philips cam, then you can safely use the framerate setting.
Bit mask for for the framerate setting.

Example code for reading and setting framerate:

struct video_window vwin;

ioctl(cam_fd, VIDIOCGWIN, &vwin);
if (vwin.flags & PWC_FPS_FRMASK)
    printf("Camera has framerate setting; current framerate: %d fps\n", (vwin.flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT);

/* Set new framerate */
vwin.flags &= ~PWC_FPS_FRMASK;
vwin.flags |= (new_frame_rate << PWC_FPS_SHIFT);

ioctl(cam_fd, VIDIOCSWIN, &amp;vwin);


The Philips webcam driver supports only the YUV420P palette (VIDEO_PALETTE_YUV420P), also known as YUV 4:2:0 planar.

All the Y components are given first, then the U components (1 sample per 2x2 pixels), then the V components (1 sample per 2x2 pixels).

The U and V values are decimated by 2 in both horizontal and vertical direction. In other words: for every 4 Y values there is one U and one V value. Conversely, each U and V value apply to a block of 2x2 Y values.

Thus, the layout for a 4x4 image is:

Y01 Y02 Y03 Y04 Y05 Y06 Y07 Y08 Y09 Y10 Y11 Y12 Y13 Y14 Y15 Y16 U1 U2 U3 U4 V1 V2 V3 V4

The components map onto the image as follows:

[Y01 U1 V1] [Y02 U1 V1] [Y03 U2 V2] [Y04 U2 V2]

[Y05 U1 V1] [Y06 U1 V1] [Y07 U2 V2] [Y08 U2 V2]

[Y09 U3 V3] [Y10 U3 V3] [Y11 U4 V4] [Y12 U4 V4]

[Y13 U3 V3] [Y13 U3 V3] [Y12 U4 V4] [Y16 U4 V4]

Note that in the image data,

  • The Y component takes up Width × Height bytes. This group of bytes forms the Y plane.
  • The U component plane takes only Width × Height / 4 bytes.
  • The V component plane is the same size as the U plane.

Private calls

Apart from the backwards compatible calls defined in the Video4Linux API, the pwc driver has a number of extra ioctl() calls for Philips specific features. They are called 'private' because they use the number range marked 'private' in videodev.h. You should be careful to check that you are really talking to a Philips webcam, because other drivers have their own set of private calls which could cause trouble. These ioctl() calls are defined in the pwc-ioctl.h file.

All ioctl() calls below describe the argument(s) they take.

Some take no argument at all. Others take an integer or a structure. Note that the 3rd argument to an ioctl() call is virtually always the address of a variable, so use the & operator. This also means you cannot pass constants to ioctl() directly. You must place them in a variable first.

If a private function is not implemented, the ioctl() call will return -ENOIOCTLCMD. Any other value is an indication the function is available but failed like not supported by the specific cameramodel. The error -EFAULT probably means you forgot the & with your argument.


Description: Prove existence of Philips compatible camera.


struct pwc_probe
    char name[32];
    int type;

This function can be used to prove the presence of a Philips OEM compatible camera. The OEM models carry their own name in the video_capability field, thus making it a bit harder to determine if a camera has all the extra features. When this ioctl() call returns 0, compare the name field from pwc_probe to the name field of video_capability. If they match, the probe was succesful.

The type parameters returns the closest Philips compatible type (645, 680, 730, etc). It's purely informational.


Description: Saves user settings.

Argument: none.

This function will write the current brightness, contrast, colour and whiteness (gamma) settings into the camera's internal EEPROM, where they can be restored by the following call.

Do not over-use this call. EEPROMs can only be written a limited number of times (usually around 10000 times). After that, the EEPROM gets damaged and may not work at all.


Description: Restore user settings.

Argument: none.

With this function, the values a user previously stored in the internal EEPROM will be recalled. This function only reads from the EEPROM and is will not damage the EEPROM.


Description: Restore factory defaults.

Argument: none.

This function will restore all internal settings to a reasonable factory default, including the values set by the user with VIDIOCPWCSUSER. This function will write to the camera's internal EEPROM, so don't overdo it. EEPROMs can only be written a limited number of times (usually around 10000 times). After that, the EEPROM gets damaged and may not work at all.


Description: Set compression preference.

Argument: integer.

The Philips webcams use compression techniques to get the images across the bandwidth limited USB bus. With this ioctl() call you can specify if you like no compression, low, medium or high compression. Higher compression means less bandwidth is used, but could introduce artefacts into the image.

The function takes an integer in the range 0 - 3. 0 Means that you prefer no compression, 3 = high compression. This setting is retained between close() and open() but not between plug/unplug.

This setting does take effect immediately.


Description: Get compression preference.

Argument: integer.



Description: Set AGC (Automatic Gain Control)

Argument: integer.

The webcams have features like auto-exposure and some additional circuitry to accomodate for changing light conditions. One of these features is an AGC circuit that amplifies or attenuates the signal that comes from the CCD/CMOS sensor.

Normally this circuit is in auto mode, but you can set it to a fixed value if you like. The VIDIOCPWCSAGC call takes an integer argument, in the range 0..65535 (0x0..0xFFFF). 0 is low gain, and 65535 sets it to highest gain possible. If you supply a negative number, the AGC is set to automatic mode.

Example code:

int agc;

/* Select a high gain. Note the use of the &amp; with the 3rd parameter */
agc = 40000;
ioctl(fd, VIDIOCPWCSAGC, &agc);


Description: Get AGC (Automatic Gain Control) value.

Argument: integer.

This function has a double meaning. If the returned value is negative, it means the camera is in auto-AGC mode and the absolute value is the current gain (range: -65535..-1). A positive value indicates the camera has been set to fixed AGC mode and the selected gain is returned.


Description: Set shutter speed

Argument: integer.

With this call you can set the shutter speed of the camera, or the rate at which it takes images from the CCD/CMOS sensor. The higher the value, the longer it will take. Together with the AGC settings you can change the light-sensitivity of the camera quite a lot.

A negative value sets the shutter speed to automatic (controlled by the camera's firmware). A value of 0..65535 will set manual mode, where the values have been calibrated such that 65535 is the longest possible exposure time. It is not a linear scale, where a value of '1' is 1/65536th of a second, etc.

The longest exposure time is limited by the framerate (at least 5 frames per second, so 1/5th of a second).


Description: Set Automatic White Balance


struct pwc_whitebalance
   int mode;
   int manual_red, manual_blue;    /* read/write */
   int read_red, read_blue;        /* read/only */

The camera has built-in White Balance compensation. I.e. it has the ability to correct for different lighting conditions (outdoor, indoor, artificial lighting, etc) by adjusting the gains for the red and blue pixels (green is never affected). Normally you leave it in automatic mode, but it can be changed to a fixed setting. You can also query the current values. This is what VIDIOCPWCSAWB and VIDIOCPWCGAWB are for.

mode can be one of these defined values:

  • PWC_WB_AUTO - Automatic
  • PWC_WB_MANUAL - Manually set by manual_red and manual_blue
  • PWC_WB_INDOOR - Indoor lightbulb type lighting
  • PWC_WB_OUTDOOR - Outdoor lighting
  • PWC_WB_FL - Flourescent lighting (FL tubes)

It is only when mode = PWC_WB_MANUAL that the manual_red and manual_blue parameters are valid.

They are used to program the camera with your own red and blue gain values. The range is 0..65535 (0x0..0xffff). In all other modes these parameters are ignored. The read_red and read_blue parameters are never used with VIDIOCPWCSAWB.


Description: Get Automatic White Balance

Argument: See VIDIOCPWCSAWB See Set Automatic White Balance

This function is used to query the current Auto White Balance mode and optionally the red and blue gain values of the camera. It takes a pwc_whitebalance struct, which is filled with the mode (see above). If mode = PWC_WB_MANUAL, the manual_red and manual_blue parameters are set; if mode = PWC_WB_AUTO the read_red and read_blue parameters are set. In any other mode the read_red and read_blue parameters are undefined.


Description: Control speed of Automatic White Balance


struct pwc_wb_speed
   int control_speed;
   int control_delay;

These two functions are also part of the Auto White Balance mode of the cameras, but are separated from the VIDIOCPWCGAWB/VIDIOCPWCSAWB calls since they are probably not used much and this way you don't break the pwc_whitebalance struct.

The parameters control_speed and control_delay determine how fast the camera reacts to changes in lighting when it is in automatic mode, and how long it waits before it starts adjusting the red/blue gains. These are not absolute times (seems to be related to the number of frames processed). The range of both numbers is 1..65535 (0x1..0xffff). A setting of 0 leaves the settings untouched.

Note: the term 'speed' is a bit misleading; in fact, the higher the number, the slower it reacts.


Description: Control and query the LED on the camera.


struct pwc_leds
   int led_on;         /* Led on-time; range = 0..25000 */
   int led_off;        /* Led off-time; idem. */

Only supported by ToUCam series (730 to 750). Not every OEM cam based on this chipset supports this feature!

With the VIDIOCPWCSLED function you can control if the LED on the camera should be on while it is in use (the default), off (handy for survaillance cams), or blink (draws extra attention). VIDIOCPWCGLED returns the current settings.

The time is specified in milliseconds, with a resolution of 100 ms. The maximum is 25500 (about 25 seconds). If you want a LED that is always on, specify a led_on time >= 100, and a led_off time of 0. To get a dark LED, specify a led_on time of 0, and time_off >= 100. For a blinking LED, set both led_on and led_off to a value larger than 100.

Example code:

#include "pwc-ioctl.h"
struct pwc_leds LED;

/* Turn LED off */
LED.led_on = 0;
LED.led_off = 0;

/* Turn LED on solid */
LED.led_on = 100;
LED.led_off = 0;

/* Blinking LED, 1 second interval, 20% duty cycle */
LED.led_on = 200;
LED.led_off = 800;

There is a parameter that can be specified when loading the pwc module that also controls the LED time. It sets the default timing.

When the video device is closed, the LED is always turned off. This is done by the driver.


Description: Control and query electronic sharpness

Argument: integer

This feature can blur or sharpen the image from the cam. This is done electronically, not by actually focussing the camera (you have to do this manually by rotating the canule, thus screwing the lens in or out). But it produces some interesting results. You can blur the image a bit to get a soft-focus effect, or sharpen it to enhance the edges in the image.

Don't overdo it, though. Sharpening the image also introduces more noise, making it harder to compress the image for videoconferencing and makes the image look unnatural. And of course it can't correct for a camera that is out of focus.

A negative argument indicates the webcam determines the contour value automatically (this value cannot be queried). A positive value in the range 0..65535 will set the contour value manually. Low values will give a blurred image, a high value sharpens it.


Description: Backlight compensation mode

Argument: integer

In case the object you are viewing with the camera is in front of a bright background (for example, a window or some bright lights), the automatic exposure unit may make the image too dark. You can turn the backlight compensation mode off by setting this value to 0. Any other value means the backlight compensation mode is on.


Description: Anti-flicker mode

Argument: integer

Due to the different frequencies of the webcam, monitor refresh rate and the electrical power supply, the intensity of the image may 'pulsate' which is quite annoying to watch. The Philips cams have a way to suppress this (don't ask me how...) This function turns that feature on or off. A value of 0 turns if off, any other value means its on; simple as that.


Brief: Control the dynamic noise reduction mode

Argument: integer

One of the more advanced features of the camera. It has an internal noise reduction algorithm (probably some temporal filtering), and works quite well to smooth out noise in the images. It can be set from None (value = 0) to High (value = 3).


Description: Get the image size as produced by the camera


struct pwc_imagesize
   int width;
   int height;

Sometimes it's handy to know the real size of the image that is delivered by the camera (see this chart), because PWC pads any image size that is not directly supported with a gray border (doing interpolation in the kernel is a no-no). This function will tell what the 'real' current image size is, in pixels.


The MPT (Motorized Pan Tilt) functions current only support the Logitech QuickCam Orbit or Sphere (they are the same cam, just named differently).

The Orbit/Sphere can pan about 70 degrees left and right from its home position, and tilt 30 degrees up and down, giving you a total view of about 180 degrees horizontally and 120 degrees vertically.

Below, the ioctl() commands are described which allow you to rotate the camera. When the camera does not have motorized pan & tilt, the ioctl() will return an errno of -ENXIO (no such device or address). The safest way to probe for this feature is by using VIDIOCPWCMPTGRANGE (get range), as this does not affect the cams position or operation, plus you get some useful information in case the cam does have the feature.

All angles described below are in degrees * 100, even though the cam cannot be set this accurate. Also after a while the camera looses its absolute position. Then you need to take it to an extreme position to get it re-calibrated.

For panning, positive angles are clockwise from the home position, and for tilting positive angles are up.

The zoom feature does not have any function. There are no pwc compatible cameras available supporting this yet.


Description: Reset motorized pan/tilt position

Argument: integer

This will reset the webcam to it's home position, which is horizontally halfway between its outermost left and right position and looking ahead level. The cam will perform a reset by first going to its topleft position, and then moving forward to its home position.

The camera must finish this before it accepts more commands.

Bits 31..2 1 0
Function Unused - set to 0 reset tilt position reset pan position

After this call, the driver will set its internal angle position to 0,0.


Description: Get pan/tilt range


struct pwc_mpt_range
    int pan_min, pan_max;
    int tilt_min, tilt_max;
    int zoom_min, zoom_max;

This function will query the driver for the minimum and maximum angles by which the cam can be rotated. All angles are expressed in degrees * 100.

Trying to set an angle beyond these bounds will return in an -ERANGE error code.

The hardware zoom function is currently not available on any camera, so -1,-1 is returned in the zoom_min and zoom_max fields.


Description: Set pan/tilt position


struct pwc_mpt_angles
    int absolute;   /* write-only */
    int pan;        /* degrees * 100 */
    int tilt        /* degrees * 100 */

With this command you tell the Orbit/Sphere to rotate. You can rotate to an absolute position or relative to the current one. In all cases, trying to rotate beyond the allowed angles will return an -ERANGE error.

Do not send another VIDIOCPWCMPGSANGLE command until the last one has finished (either succesfully or with an error). Use the VIDIOCPWCMPTGSTATUS call to determine when the camera is ready (see below).

After several movements the camera will loose its accuracy. You can re-calibrate the position by doing a VIDIOCPWCMPTRESET or by taking the camera to its extreme positions.


Description: Get pan/tilt position

Argument: struct pwc_mpt_angles. See VIDIOCPWCMPTSANGLE

Query the current angle of the camera. The angle is not really queried from the camera, as it does not have position sensors. Rather, the last position set with VIDIOCPWCMPTSANGLE or VIDIOCPWCMPTRESET is remembered. After several movements the camera will loose its accuracy. You can re-calibrate the position by doing a VIDIOCPWCMPTRESET or by taking the camera to its extreme positions.


Description: Query pan/tilt status


struct pwc_mpt_status
    int status;
    int time_pan;
    int time_tilt;

With this function you request the MPT status of the camera. These bits change when the camera is rotating.

Bits of 'status' 31...3 2 1 0
Function Unused General status bit Tilt status Pan status

The General status bit is 1 when the command was processed successfully internally. A 0 signals a time out. For the Pan and Tilt status a 1 means the command completed succesfully, and a 0 means busy, or hard stop error (i.e. hitting one of the limits).

When setting the angle or doing a reset, you have to poll the status regularly until the command completes or returns an error. The following table clarifies the various bit combinations.

0x00 Command running
0x01 Timeout
0x02 Timeout
0x03 Timeout
0x04 Both axis hit hard stop
0x05 Tilt hit hard stop
0x06 Pan hit hard stop
0x07 Command completed succesfully

The polling should not be done too often. An interval of 250 to 500 ms should be fine. The camera usually completes rotating within 2 seconds.

It has not been identified what the time_pan and time_tilt parameters contain. A guess is they hold the time in milliseconds that the motor for that particular axis is running/has been running.

Note: This document is a re-write of the original Nemosoft PWC API document - (C) 2001-2004 Nemosoft Unv. The original API document was released as part of pwc version 9.0.2 package. This entire package was released under the GNU GENERAL PUBLIC LICENSE (GPL) version 2 or later. This Wikipage is therefore also under the same license.

-- KennethLavrsen - 15 Nov 2004
Topic revision: r10 - 25 Nov 2006, KennethLavrsen
Copyright © 1999-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Please do not email Kenneth for support questions. Kenneth only maintains the wiki.
Luc Saillard is the author of the PWC driver and he does not like direct emails either. Please join the Mailing List and ask your questions there.