jueves, 11 de febrero de 2010

Estudio automático del código fuente: Rats y cppcheck

Rats

rats -i -r -w 3 --html --columns --context /usr/src/linux/drivers/media/video/uvc > ~/rats_results.html && chromium ~/rats_results.html


Entries in perl database: 33
Entries in python database: 62
Entries in c database: 334
Entries in php database: 55
Analyzing /usr/src/linux/drivers/media/video/uvc/uvc_ctrl.c
Analyzing /usr/src/linux/drivers/media/video/uvc/uvc_queue.c
Analyzing /usr/src/linux/drivers/media/video/uvc/uvc_driver.c
Analyzing /usr/src/linux/drivers/media/video/uvc/uvc_v4l2.c
Analyzing /usr/src/linux/drivers/media/video/uvc/uvc_isight.c
Analyzing /usr/src/linux/drivers/media/video/uvc/uvc_status.c
Analyzing /usr/src/linux/drivers/media/video/uvc/uvc_video.c
/usr/src/linux/drivers/media/video/uvc/uvc_status.c:102[9]: High: fixed size local buffer
char *attrs[3] = { "value", "info", "failure" };
Extra care should be taken to ensure that character arrays that are allocated
on the stack are used safely.  They are prime targets for buffer overflow
attacks.


/usr/src/linux/drivers/media/video/uvc/uvc_v4l2.c:1067[10]: Medium: non-function call reference: open
.open = uvc_vm_open,
/usr/src/linux/drivers/media/video/uvc/uvc_v4l2.c:1135[10]: Medium: non-function call reference: open
.open = uvc_v4l2_open,
A function call is not being made here, but a reference is being made to a name
that is normally a vulnerable function.  It could be being assigned as a
pointer to function.


/usr/src/linux/drivers/media/video/uvc/uvc_v4l2.c:1138[10]: Medium: non-function call reference: read
.read = uvc_v4l2_read,
A function call is not being made here, but a reference is being made to a name
that is normally a vulnerable function.  It could be being assigned as a
pointer to function.


/usr/src/linux/drivers/media/video/uvc/uvc_ctrl.c:789[9]: Low: strlcpy: read
strlcpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:315[25]: Low: strlcpy: read
strlcpy(format->name, fmtdesc->name,
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:346[17]: Low: strlcpy: read
strlcpy(format->name, "MJPEG", sizeof format->name);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:364[25]: Low: strlcpy: read
strlcpy(format->name, "SD-DV", sizeof format->name);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:367[25]: Low: strlcpy: read
strlcpy(format->name, "SDL-DV", sizeof format->name);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:370[25]: Low: strlcpy: read
strlcpy(format->name, "HD-DV", sizeof format->name);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:1509[9]: Low: strlcpy: read
strlcpy(vdev->name, dev->name, sizeof vdev->name);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:1605[17]: Low: strlcpy: read
strlcpy(dev->name, udev->product, sizeof dev->name);
/usr/src/linux/drivers/media/video/uvc/uvc_v4l2.c:64[9]: Low: strlcpy: read
strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name);
/usr/src/linux/drivers/media/video/uvc/uvc_v4l2.c:507[17]: Low: strlcpy: read
strlcpy(cap->driver, "uvcvideo", sizeof cap->driver);
/usr/src/linux/drivers/media/video/uvc/uvc_v4l2.c:508[17]: Low: strlcpy: read
strlcpy(cap->card, vdev->name, sizeof cap->card);
/usr/src/linux/drivers/media/video/uvc/uvc_v4l2.c:650[17]: Low: strlcpy: read
strlcpy(input->name, iterm->name, sizeof input->name);
/usr/src/linux/drivers/media/video/uvc/uvc_v4l2.c:718[17]: Low: strlcpy: read
strlcpy(fmt->description, format->name,
Double check that your buffer is as big as you specify


/usr/src/linux/drivers/media/video/uvc/uvc_ctrl.c:923[25]: Low: memcpy: read
memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
/usr/src/linux/drivers/media/video/uvc/uvc_ctrl.c:1039[17]: Low: memcpy: read
memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
/usr/src/linux/drivers/media/video/uvc/uvc_ctrl.c:1108[9]: Low: memcpy: read
memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
/usr/src/linux/drivers/media/video/uvc/uvc_ctrl.c:1131[17]: Low: memcpy: read
memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
/usr/src/linux/drivers/media/video/uvc/uvc_queue.c:192[9]: Low: memcpy: read
memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:638[9]: Low: memcpy: read
memcpy(streaming->header.bmaControls, &buffer[size], p*n);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:823[17]: Low: memcpy: read
memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:827[17]: Low: memcpy: read
memcpy(unit->extension.baSourceID, &buffer[22], p);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:832[17]: Low: memcpy: read
memcpy(unit->extension.bmControls, &buffer[23+p], 2*n);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:944[25]: Low: memcpy: read
memcpy(term->camera.bmControls, &buffer[15], n);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:951[25]: Low: memcpy: read
memcpy(term->media.bmControls, &buffer[9], n);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:952[25]: Low: memcpy: read
memcpy(term->media.bmTransportModes, &buffer[10+n], p);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:1023[17]: Low: memcpy: read
memcpy(unit->selector.baSourceID, &buffer[5], p);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:1056[17]: Low: memcpy: read
memcpy(unit->processing.bmControls, &buffer[8], n);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:1086[17]: Low: memcpy: read
memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:1090[17]: Low: memcpy: read
memcpy(unit->extension.baSourceID, &buffer[22], p);
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:1093[17]: Low: memcpy: read
memcpy(unit->extension.bmControls, &buffer[23+p], n);
/usr/src/linux/drivers/media/video/uvc/uvc_v4l2.c:261[9]: Low: memcpy: read
memcpy(&video->streaming->ctrl, &probe, sizeof probe);
/usr/src/linux/drivers/media/video/uvc/uvc_v4l2.c:320[9]: Low: memcpy: read
memcpy(&probe, &video->streaming->ctrl, sizeof probe);
/usr/src/linux/drivers/media/video/uvc/uvc_v4l2.c:332[9]: Low: memcpy: read
memcpy(&video->streaming->ctrl, &probe, sizeof probe);
/usr/src/linux/drivers/media/video/uvc/uvc_v4l2.c:973[17]: Low: memcpy: read
memcpy(info->entity, xinfo->entity, sizeof info->entity);
/usr/src/linux/drivers/media/video/uvc/uvc_v4l2.c:1001[17]: Low: memcpy: read
memcpy(map->name, xmap->name, sizeof map->name);
/usr/src/linux/drivers/media/video/uvc/uvc_v4l2.c:1002[17]: Low: memcpy: read
memcpy(map->entity, xmap->entity, sizeof map->entity);
/usr/src/linux/drivers/media/video/uvc/uvc_isight.c:89[17]: Low: memcpy: read
memcpy(mem, data, nbytes);
/usr/src/linux/drivers/media/video/uvc/uvc_video.c:459[9]: Low: memcpy: read
memcpy(mem, data, nbytes);
/usr/src/linux/drivers/media/video/uvc/uvc_video.c:515[9]: Low: memcpy: read
memcpy(data, mem, nbytes);
/usr/src/linux/drivers/media/video/uvc/uvc_video.c:595[25]: Low: memcpy: read
memcpy(video->bulk.header, mem, ret);
Double check that your buffer is as big as you specify.
When using functions that accept a number n of bytes to copy, such as strncpy, be aware that if the dest buffer size = n it may not NULL-terminate the string.


/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:322[25]: Low: snprintf: read
snprintf(format->name, sizeof format->name,
/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:1607[17]: Low: snprintf: read
snprintf(dev->name, sizeof dev->name,
Double check that your buffer is as big as you specify.
When using functions that accept a number n of bytes to copy, such as strncpy, be aware that if the dest buffer size = n it may not NULL-terminate the string.


/usr/src/linux/drivers/media/video/uvc/uvc_driver.c:380[17]: Low: strlcat: read
strlcat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz",
/usr/src/linux/drivers/media/video/uvc/uvc_status.c:35[9]: Low: strlcat: read
strlcat(dev->input_phys, "/button", sizeof(dev->input_phys));
Double check that your buffer is as big as you specify


Total lines analyzed: 6748
Total time 0.010565 seconds
638712 lines per second



Cppcheck

cppcheck --enable=all /usr/src/linux/drivers/media/video/uvc/ 2> ~/err.txt && kwrite ~/err.txt


[/usr/src/linux/drivers/media/video/uvc/uvc_ctrl.c:970]: (style) The scope of the variable ret can be limited
[/usr/src/linux/drivers/media/video/uvc/uvc_ctrl.c:1009]: (style) The scope of the variable ret can be limited
[/usr/src/linux/drivers/media/video/uvc/uvc_video.c:572]: (style) The scope of the variable ret can be limited
[/usr/src/linux/drivers/media/video/uvc/uvc_ctrl.c:1]: (style) The function '__uvc_ctrl_commit' is never used

jueves, 4 de febrero de 2010

Características de los campos de control de una Webcam

Tabla de la estructura uvc_streaming control

struct
uvc_streaming_control
0-7 bits 8-15 bits
bmHint
bFormatIndex
bFrameIndex

dwFrameInterval

wKeyFrameRate
wPFrameRate
wCompQuality
wCompWindowSize
wDelay

dwMaxVideoFrameSize


dwMaxPayloadTransferSize


dwClockFrequency

bmFramingInfo
bPreferedVersion
bMinVersion
bMaxVersion


Detalles de los campos de control


bmHint

Es una máscara de bits.
Cada campo de control indica a la función que campos deberían permanecer ajustados (sólo son una mera indicación):
D0: dwFrameInterval
D1: wKeyFrameRate
D2: wPFrameRate
D3: wCompQuality
D4: wCompWindowSize
D15..5: Reserved (0)
El uno en la máscara de bits indica al flujo de vídeo que campos deberían permanecer constantes durante la negociación de los parámetros del flujo. Por ejemplo, si la selección quiere favorecer el número de cuadros por encima de la calidad, el bit dwFrameInterval debería ser fijado a 1.
Este campo estará fijado por el anfitrión y es de sólo lectura para el interfaz del flujo de vídeo.


bFormatIndex

El índice del formato de vídeo de un descriptor de formato.
Se selecciona un formato de flujo de vídeo específico estableciendo este campo a uno de los descritos en el índice del descriptor del formato asociado. Para seleccionar el primer formato definido por el dispositivo, un valor 1 se pondrá en este campo.
Este campo debe ser soportado incluso si sólo un único formato de vídeo está soportado por el dispositivo.
Este campo será fijado por el anfitrión.


bFrameIndex

Este campo lo indica el anfitrión.
Es el índice de fotograma del vídeo de un descriptor de fotograma.
Este campo seleccionará la resolución del fotograma de vídeo desde una cadena de resoluciones soportadas por el flujo seleccionado. El rango de valores del índice irán desde 1 hasta el número de descriptores de fotograma siguiendo un descriptor de formato particular. Este campo debe ser soportado incluso si sólo un único índice de fotograma está soportado por el dispositivo.
Para carga de vídeo que no tienen definidos un descriptor de fotograma, este campo debería estar puesto a 0.
Este campo será fijado por el anfitrión.


dwFrameInterval

Este campo debería ser puesto por el anfitrión.
El intervalo de fotogramas se mide en unidades de 100 ns.
Este campo se fijará con el intervalo de fotogramas de vídeo deseado para el flujo de vídeo seleccionado y el índice de fotograma. El valor del intervalo de fotogramas se especificará en unidades de 100ns. El dispositivo debería soportar la configuración de todo los intervalos de fotogramas descritos en el descriptor de fotograma correspondiente al índice de fotograma de vídeo. Este campo debe ser implementado incluso si sólo un único intervalo de fotogramas de vídeo está soportado por el dispositivo.
Cuando se usa en un endpoint de entrada, el anfitrión deberá indicar sus preferencias durante la etapa de sondeo. El valor debe estar dentro del rango de valores soportado por el dispositivo.
Cuando se usa en un endpoint de salida, el anfitrión deberá aceptar el valor indicado por el dispositivo.


bFormatIndex

El ratio de fotogramas clave en unidades de fotogramas clave por fotogramas de vídeo.
Este campo es únicamente aplicable a fuentes (y formatos) que permitan un flujo de vídeo con parámetros de compresión ajustables. La utilización de este control es a discreción del dispositivo y estará indicado en el descriptor de cabeceras de entrada o salida VS.
El ratio de fotogramas clave se usa para especificar el ratio de fotogramas clave del compresor. Por ejemplo, si uno de cada diez cuadros codificados es un fotograma clave, este control debiera tomar el valor de 10. Un valor de 0 indica que sólo el primer cuadro es un cuadro clave.
Cuando se usa en un endpoint de entrada, el anfitrión indicará su preferencias en la fase de sondeo. El valor deberá estar dentro del rango de valores soportado por el dispositivo.
Cuando se usa en un endpoint de salida, el anfitrión deberá aceptar el valor que le sea indicado por el dispositivo.

wPFrameRate

El ratio Pframe se mide en unidades Pframe / fotogramas clave.
Este campo es únicamente aplicable a fuentes (y formatos) que permitan un flujo de vídeo con parámetros de compresión ajustables. La utilización de este control es a a discreción del dispositivo y estará indicado en el descriptor de cabeceras de entrada o salida VS.
El control del ratio de fotogramas P es utilizado para especificar el número de fotogramas P por cada fotograma clave. Como ejemplo de la relación entre los tipos de codificación de fotogramas, supóngase que un fotograma clave se da cada 10 fotogramas, y luego hay 3 fotogramas P por cada fotograma clave. Los fotogramas P serán los comprendidos entre los fotogramas clave. Los otros 6 fotogramas, los cuales se dan entre los fotogramas clave y los fotogramas P, serán fotogramas bidireccionales (B).
Cuando se usa en un endpoint de entrada, el anfitrión indicará su preferencias en la fase de sondeo. El valor deberá estar dentro del rango de valores soportado por el dispositivo.
Cuando se usa en un endpoint de salida, el anfitrión deberá aceptar el valor que le sea indicado por el dispositivo.


wCompQuality

El control de la calidad de compresión se mide en unidades abstractas desde 0 (el más bajo) hasta 10000 (el más alto).
Este campo es únicamente aplicable a fuentes (y formatos) que permitan un flujo de vídeo con parámetros de compresión ajustables. La utilización de este control es a a discreción del dispositivo y estará indicado en el descriptor de cabeceras de entrada o salida VS.
Este campo sirve para especificar la calidad de la compresión del vídeo. Los valores para este propósito comprenden el rango desde 0 a 10000 ( 0 indica la más baja calidad, 10000 la máxima). La resolución indicada en este control determinará el número de configuraciones distintas de calidad que puede mantener.
Cuando se usa en un endpoint de entrada, el anfitrión indicará su preferencias en la fase de sondeo. El valor deberá estar dentro del rango de valores soportado por el dispositivo.
Cuando se usa en un endpoint de salida, el anfitrión deberá aceptar el valor que le sea indicado por el dispositivo.

wCompWindowSize

Es el tamaño de la ventana por la media de la tasa de bits de control.
Este campo es únicamente aplicable a fuentes (y formatos) que permitan un flujo de vídeo con parámetros de compresión ajustables. La utilización de este control es a a discreción del dispositivo y estará indicado en el descriptor de cabeceras de entrada o salida VS.
El tamaño de la ventana de compresión de control se utiliza para especificar el número de fotogramas de vídeo codificados sobre el que el tamaño promedio no puede exceder la velocidad de datos especificada. Para una ventana de tamaño n, el promedio del tamaño de los fotogramas no excederá el ratio de datos especificados en el flujo.
Algunos fotogramas pueden ser mayores o menores.
Por ejemplo, si el ratio de datos ha sido fijado a 100 kilobytes por segundo (Kbps) en una película de 10 fotogramas por segundo (fps) con un tamaño de compresión de 10, algunos fotogramas pueden ser de cualquier de cualquier tamaño siempre y cuando el tamaño medio de un fotograma en cualquier secuencia de 10 fotogramas sea menor o igual que 10 kilobytes.
Cuando se usa en un endpoint de entrada, el anfitrión indicará su preferencias en la fase de sondeo. El valor deberá estar dentro del rango de valores soportado por el dispositivo.
Cuando se usa en un endpoint de salida, el anfitrión deberá aceptar el valor que le sea indicado por el dispositivo.

wDelay

Es la latencia del interfaz del flujo de vídeo interno medido en ms desde la captura de datos de vídeo hasta la presentación en el USB.
Cuando se usa en un endpoint de entrada, este campo será fijado por el dispositivo y será de sólo lectura para el anfitrión.
Cuando se usa en un endpoint de salida, este campo será fijado por el anfitrión y será de sólo lectura para el dispositivo.


dwMaxVideoFrameSize

Es el tamaño máximo de la fotograma de vídeo o de los segmentos específicos para la codificación, se mide en bytes.
Para los formatos basados en fotogramas, este campo indica el tamaño máximo de un único fotograma de vídeo.
Para los formatos basados en flujo, y cuando este comportamiento se habilita mediante el campo bmFramingInfo (véase más abajo), este campo indica el tamaño máximo de un único segmento especificado en el codec. Se requerirá al que envía que indique un límite de segmento mediante el bit FID en la cabecera del envío de carga útil.
Este campo será ignorado (para los formatos basados en flujo si ellos bits bmFramingInfo no están habilitados.
Cuando se usa en un endpoint de entrada, este campo será fijado por el dispositivo y será de sólo lectura para el anfitrión.
Cuando se usa en un endpoint de salida, este campo será fijado por el anfitrión y será de sólo lectura para el dispositivo.


dwMaxPayloadTransferSize

Especifica el número máximo de bytes que el dispositivo puede transmitir o recibir en un único de envío de carga útil. Este campo será fijado por el dispositivo y sólo lectura por el anfitrión. Algunas implementaciones de anfitriones restringe el máximo valor permitido para este campo.


dwClockFrequency

Es la frecuencia de reloj del dispositivo para un formato específico, se mide en Hz. Esto se especificará las unidades usadas para los campos de información de tiempo en las cabeceras de envío de carga útil de vídeo en los flujos de datos.
Este parámetro está fijado por un dispositivo y es de sólo lectura para el anfitrión.


bmFramingInfo

Es una máscara de bits de control que permite los siguientes valores:
D0: Si está fijado a 1, el campo de identificación de fotograma (FID) será requerido en la cabecera de envío de carga útil (ver la descripción de D0 en la sección
2.4.3.3: “Video and Still Image Payload Headers”). Se requiere que el que envía cambie el identificador del fotograma al menos cada dwMaxVideoFrameSize bytes (véase más arriba).
D1: Si está fijado a 1, indica que el campo del final de fotograma (EOF) puede estar presente en la cabecera del envío de carga útil (ver la descripción de D1 en la sección 2.4.3.3: “Video and Still Image Payload Headers”). Es un error especificar este bit sin especificar D0.
D7..2: D7..2: Reservado (0).
Este control indica a la función si las transferencias de carga útil contendrán información fuera de los límites del marco en la cabecera de envío de carga útil de vídeo (ver sección 2.4.3.3: “Video and Still Image Payload Headers”).
Para los formato conocidos basado en fotogramas (por ejemplo MJPEG, sin comprimir, DV), este control será ignorado. Para los formatos conocidos basados en flujos, este control permite al que envío indicar que serán identificados los límites de los segmentos en el flujo, lo que permite la gestión de buffers de baja latencia por el receptor sin el sobrecoste de analizar el flujo por sí mismo.
Cuando se usa en un endpoint de entrada, este campo será fijado por el dispositivo y será de sólo lectura para el anfitrión.
Cuando se usa en un endpoint de salida, este campo será fijado por el anfitrión y será de sólo lectura para el dispositivo.


bPreferedVersion

Es la versión de formato de envío de carga favorita soportada por el anfitrión o el dispositivo para el valor de bFormatIndex especificado.
Este parámetro permite al anfitrión y el dispositivo negociar de mutuo acuerdo una versión del formato de envío de carga útil asociado con el campo bFormatIndex. El anfitrión inicializa este y los siguientes campos bMinVersion y bMaxVersion a cero en el primer poner del sondeo. En la etapa de obtener del sondeo, el dispositivo deberá devolver su versión favorita, además de las versiones mínimas y máximas soportadas por el dispositivo (véase bMinVersion y bMaxVersion más abajo). El anfitrión puede enviar una subsecuencia de conjuntos de sondeos de poner y obtener para especificar su versión favorita (dentro del rango que fue devuelto, entre bMinVersion y bMaxVersion desde la secuencia inicial de poner y obtener). Al anfitrión no se le permite alterar los valores bMinVersion y bMaxVersion.
Este campo permite hasta 256 versiones (0-255) de un formato de envío de carga útil único. El número de versión se extrae de la menor versión de la especificación de formatos de carga útil. Por ejemplo, la versión 1.2 de una especificación de formato de envío de carga útil se representaría con un valor de 2 en este parámetro.


bMinVersion

La versión mínima del formato de envío de carga útil soportado por el dispositivo para el valor especificado de bFormatIndex.
Este valor se inicializa a cero por el huésped y se restablece por un valor en el rango de 0 a 255 por el dispositivo. El huésped no puede modificar este valor (excepto para reiniciar la negociación estableciendo a cero bPreferredVersion, bMinVersion y bMaxVersion).


bMaxVersion

La versión máxima del formato de envío de carga útil soportado por el dispositivo para el valor especificado de bFormatIndex.
Este valor se inicializa a cero por el huésped y se restablece por un valor en el rango de 0 a 255 por el dispositivo. El huésped no puede modificar este valor (excepto para reiniciar la negociación estableciendo a cero bPreferredVersion, bMinVersion y bMaxVersion).

miércoles, 3 de febrero de 2010

VS_PROBE_CONTROL



Ahora lo siguiente que hay que realizar es consultar que tamaños de imágenes puede capturar la cámara web.

Para ello hay que utilizar la llamada VS_PROBE_CONTROL que podéis consultarla en la tabla 4-47 "Video Probe and Commit Controls" que se encuentra en la página 116 de las 143 de la documentación de la clase.

La idea sería conseguir una foto con la mayor resolución posible de las que se pudieran capturar.

miércoles, 30 de diciembre de 2009

uvc_video_resume = resumir el vídeo


Continuemos estudiando como resumir o continuar el flujo de vídeo descrito en la función uvc_video_resume:


/*
 * Reconfigure the video interface and restart streaming if it was enabled
 * before suspend.
 *
 * If an error occurs, disable the video queue. This will wake all pending
 * buffers, making sure userspace applications are notified of the problem
 * instead of waiting forever.
 */
int uvc_video_resume(struct uvc_streaming *stream)
{
int ret;

stream->frozen = 0;

ret = uvc_commit_video(stream, &stream->ctrl);
if (ret < 0) {
uvc_queue_enable(&stream->queue, 0);
return ret;
}

if (!uvc_queue_streaming(&stream->queue))
return 0;

ret = uvc_init_video(stream, GFP_NOIO);
if (ret < 0)
uvc_queue_enable(&stream->queue, 0);

return ret;
}


Y ahora voy a comentar el código para hacerlo más legible:

/**
 * uvc_video_resume - Reconfigure the video interface and restart streaming if
 * it was enabled before suspend.
 * @stream: the stream that will be resumed
 *
 * If an error occurs, disable the video queue. This will wake all pending
 * buffers, making sure userspace applications are notified of the problem
 * instead of waiting forever.
 */
int uvc_video_resume(struct uvc_streaming *stream)
{
int ret;

        //  It could be interesting to compare if it was frozen before with a
        //  if (stream->frozen == 1)
        //    return "?";
stream->frozen = 0;  // stream knows if it's frozen

        //  uvc_commit_video will overwrite controls of our stream
ret = uvc_commit_video(stream, &stream->ctrl);
if (ret < 0) {
                //  It will cancel the queue, put it in a IDLE state and delete
                //  the streaming label from queue flag
uvc_queue_enable(&stream->queue, 0);
return ret;
}

        //  if queue is not streaming
if (!uvc_queue_streaming(&stream->queue))
return 0;

        //  if queue is streaming we have to init video
        //  payload can be put in a packet?
ret = uvc_init_video(stream, GFP_NOIO);
if (ret < 0)
                //  We need to enable the queue of @stream
uvc_queue_enable(&stream->queue, 0);

return ret;
}


Además para comprender bien la continuación de la captura de vídeo hay que estudiar cómo funciona las colas (que he tenido que comentar parte de su código para entenderlo completamente), pero eso ya es un poco más difícil de entender. En otro artículo lo comentaré.

lunes, 28 de diciembre de 2009

Los vectores


En algunos momentos tenemos que manejar una lista de cosas, eso implica un orden y luego hay que seguirlo. Lo más natural sería lo ilustrado arriba, primero viene el elemento 1, luego el 2, ... y para terminar el último.



Pero los ordenadores "prefieren" empezar en 0 y además que sean nombres cortos por ejemplo d, por lo que el d0 sería el elemento 1.



Además también es muy común que el orden vaya al revés, es decir que los dígitos más importantes vayan antes. Esto sucede como en las matemáticas: centenas, decenas y unidades, las centenas van delante porque las centenas son más importantes que las decenas y estas a su vez preceden a las unidades porque son más importantes que ellas.


Algo similar me sucede a mi con le código de linux-uvc, que hay veces que toca trabajar con máscaras de bits y hay que tener mucho cuidado con el orden y que significa cada elemento o dígito de la máscara.

lunes, 14 de diciembre de 2009

Calculando mi primer parche


Como visteis he comentado un poco el código de linux-uvc y es que Laurent Pinchart no suele ser comentar mucho (el mantenedor de linux-uvc).

Así que me decido a calcular mi primer parche con esos comentarios, pero antes cabe exponer que es un parche.

Un parche es un fichero de texto que contiene la diferencia al estilo del juego de las diferencias. Las diferencias van precedidas con signos negativos y positivos para saber que se quita y que se pone de una versión a otra.

En el ejemplo que os he puesto encima, el parche entre los dos dibujos sería del estilo de: redondea un poco el borde del cuadrado más exterior y convierte en círculo el cuadrado más interior.

En el ejemplo de uvc_video_suspend sería:
--- /home/palmax/palmax-uvc/uvc/uvc_video.c     2009-12-14 17:35:53.000000000 +0100
+++ /home/palmax/palmax-uvc/palmax/palmax-mod/uvc_video.c       2009-12-14 17:41:10.000000000 +0100
@@ -1031,8 +1031,9 @@ static int uvc_init_video(struct uvc_str
  * Suspend/resume
  */

-/*
- * Stop streaming without disabling the video queue.
+/**
+ * uvc_video_suspend - Stop streaming without disabling the video queue.
+ * @stream: the stream that will be suspended
  *
  * To let userspace applications resume without trouble, we must not touch the
  * video buffers in any way. We mark the device as frozen to make sure the URB
@@ -1040,11 +1041,12 @@ static int uvc_init_video(struct uvc_str
  */
 int uvc_video_suspend(struct uvc_streaming *stream)
 {
-       if (!uvc_queue_streaming(&stream->queue))
+       if (!uvc_queue_streaming(&stream->queue))  // if queue is STREAMING
                return 0;

-       stream->frozen = 1;
-       uvc_uninit_video(stream, 0);
+       stream->frozen = 1;  //  uvc_video_device knowns if it's frozen or not
+       uvc_uninit_video(stream, 0);  //  it will kill all URBs and free them
+        //  it will alternate to the 0 alternative setting
        usb_set_interface(stream->dev->udev, stream->intfnum, 0);
        return 0;
 }

Arriba indica de que dos ficheros es la diferencia y desde que línea, para que así luego se pueda obtener el segundo desde el primero y el parche.


Lo he generado como se explica en el libro "Understanding the Linux Virtual Memory Manager". En este caso ha bastado con:
diff -up ~/palmax-uvc/uvc/uvc_video.c ~/palmax-uvc/palmax/palmax-mod/uvc_video.c > patches/uvc_video.c.patch

uvc_video_suspend



Ahora vamos a estudiar uvc_video_suspend:
/* --------------------------------------------------------------------------
 * Suspend/resume
 */

/*
 * Stop streaming without disabling the video queue.
 *
 * To let userspace applications resume without trouble, we must not touch the
 * video buffers in any way. We mark the device as frozen to make sure the URB
 * completion handler won't try to cancel the queue when we kill the URBs.
 */
int uvc_video_suspend(struct uvc_streaming *stream)
{
    if (!uvc_queue_streaming(&stream->queue))
        return 0;

    stream->frozen = 1;
    uvc_uninit_video(stream, 0);
    usb_set_interface(stream->dev->udev, stream->intfnum, 0);
    return 0;
}


Ahora voy a ir comentándolo para hacerlo más legible:
/* --------------------------------------------------------------------------
 * Suspend/resume
 */

/**
 * uvc_video_suspend - Stop streaming without disabling the video queue.
 * @stream: the stream that will be suspended
 *
 * To let userspace applications resume without trouble, we must not touch the
 * video buffers in any way. We mark the device as frozen to make sure the URB
 * completion handler won't try to cancel the queue when we kill the URBs.
 */
int uvc_video_suspend(struct uvc_streaming *stream)
{
    if (!uvc_queue_streaming(&stream->queue))  // if queue is STREAMING
        return 0;

    stream->frozen = 1;  //  uvc_video_device knowns if it's frozen or not
    uvc_uninit_video(stream, 0);  //  it will kill all URBs and free them
        //  it will alternate to the 0 alternative setting
    usb_set_interface(stream->dev->udev, stream->intfnum, 0);
    return 0;
}


No es muy complejo, pero es curioso que exista una alternativa de configuración número 0 que se use en este caso.