Userspace driver para Linux de un Diamond ATI TV Wonder (TVW750USB).__
Integrantes:
Descripción:
Un Diamond ATI TV Wonder es un dispositivo USB que permite captar las señales de TV para diferentes fines ya sea grabar videos con mayor calidad que si tuviéramos una cámara frente a nuestro TV o para observar programas de TV desde nuestro computador. Se planeó realizar un controlador (driver) para este dispositivo que trabaje con el sistema operativo llamado Linux. Este driver podrá ser programado en python. El proyecto se desarrollará a lo largo de este semestre y se dividirá en 3 etapas la primera analizar el driver de userspace de easycap usbtv007 y ponerlo en funcionamiento, la segunda es analizar protocolo de comunicación del Diamond ATI TV Wonder y la tercera el desarrollo del driver de userspace del Diamond ATI TV Wonder.
Objetivos:
General:
Específicos:
Instalacion de una maquina virtual
Debido a que el dispositivo solo esta soportado en Windows, es necesaria la instalacion, en Linux, de una maquina virtual en la que se pueda correr el driver del dispositivo.
Pasos a seguir para la instalacion de Virtual Box en Debian Jessie:
1) Añada el componente “contrib” en / etc / apt / sources.list (Al inicio de este curso se agrego en los mirrors)
2) Actualice la lista de paquetes disponibles:
# apt-get update
3) Instalar el paquete linux-headers correspondiente y el paquete virtualbox:
# apt-get install linux-headers-$(uname -r|sed 's,[^-]*-[^-]*-,,') virtualbox
En algunos casos puede presentarse algun problema, asegurese que tenga instalado los linux-headers y linux-images mas recientes para su version de Debian. Recuerde los comandos para saber la version de Debian que tiene y saber cuales son los headers mas recientes que puede encontar:
# uname -a # apt-cache search loquebusco
4) Agregue su usuario al grupo vboxusers:
# adduser nombreusuario vboxusers
5) Una vez teniendo instalado VirtualBox, se puede instalar Windows, para abrirlo utilice:
# virtualbox
6) Para poder habilitar USB 2.0 y otras funciones en VirtualBox es necesario ir a www.virtualbox.org y descargar el “Extension Pack” correspondiente a la version de VirtualBox instalada. Luego se hace click en “Settings”, luego “Preferences” y por ultimo “Extensions” y ahi se agrega el paquete descargado.
7) Luego haga click en “New” y agregue una nueva maquina virtual.
8)Inserte un disco de instalacion de Windows o en su defecto una imagen virtual.
9) Haga click en “Start” y siga los pasos de instalacion.
10) Una vez dentro de la maquina virtual seleccione “Devices” y la opcion “Install Guest Additions” para que la maquina virtual reconzca dispositivos externos y se mejore la comunicación con el Host, entre otras cosas.
Instalando Driver de ATI TV Wonder HD 750
1) Conecte el dispositivo USB en un puerto disponible.
2) Haga click en “Devices” y en “USB” seleccione el dispositivo, que deberia verse como “Cali TV Card”.
3) Inserte el disco de instalcion del Driver (elija dependiendo de la arquitectura de su equipo), comience la instalacion.
4) Elija un programa que soporte observar video, se recomienda Total Media 3.5 de Arcsoft.
5) Por ultimo configure el TotalMedia dependiendo de la senal de TV que se requiera.
Capturando el protocolo de comunicación
1) Descargue, desde la maquina virtual, USBlyzer (puede descargar la version de prueba).
2) Abra USBlyzer, escoja el puerto en el arbol de dispositivos poniendo un check en el puerto donde se encuentra el dispositivo que desea analizar.
3) En caso de ser necesario puede irse a “Options”, luego “Preferences” y despues seleccione “Capture”, en este apartado puede seleccionar el tamaño maximo del archivo que contiene la sesion de captura. Se debe elegir uno que le permita capturar suficientes datos para el analisis.
4) Tambien puede irse a “Capture”, luego a “Capture Settings” y ahi se puede elegir los paquetes que desea filtrar, es decir cuales paquetes desea ver en la captura.
5) Una vez que ha elegido sus preferencias puede iniciar la captura, y activar el dispositivo para observar los paquetes que se producen.
Algunos comandos útiles en Linux
Otra fomra de realizar el “sniffing” del protocolo de comunicación es a través del usbmon de Linux:
Montamos el debugfs:
# mount -t debugfs none_debugs /sys/kernel/debug # modprobe usbmon
Luego podemos ver cuales buses están presentes:
# ls /sys/kernel/debug/usb/usbmon
Y para conocer en cual bus se encuentra el dispositivo buscado además de otros datos importantes que serán útiles después podemos utilizar:
#lsusb -v
Un ejemplo de la salida de este comando:
Bus 002 Device 006: ID 0438:ac14 Advanced Micro Devices, Inc. Couldn't open device, some information will be missing Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x0438 Advanced Micro Devices, Inc. idProduct 0xac14 bcdDevice 1.00 iManufacturer 1 iProduct 2 iSerial 3 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 97 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 0 bmAttributes 0x80 (Bus Powered) MaxPower 500mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 5 bInterfaceClass 255 Vendor Specific Class bInterfaceSubClass 255 Vendor Specific Subclass bInterfaceProtocol 255 Vendor Specific Protocol iInterface 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x82 EP 2 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x03 EP 3 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 3 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x84 EP 4 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x85 EP 5 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 1 bNumEndpoints 5 bInterfaceClass 255 Vendor Specific Class bInterfaceSubClass 255 Vendor Specific Subclass bInterfaceProtocol 255 Vendor Specific Protocol iInterface 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 1 Transfer Type Isochronous Synch Type None Usage Type Data wMaxPacketSize 0x1400 3x 1024 bytes bInterval 1 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x82 EP 2 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x03 EP 3 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 3 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x84 EP 4 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x85 EP 5 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0
Para capturar los datos entre el dispositivo usb y la maquina virtual utilizamos:
Para escuchar un bus específico:
# cat /sys/kernel/debug/usb/usbmon/3u > /tmp/1.mon.out
Para escuchar todos los buses, se utiliza el bus 0:
# cat /sys/kernel/debug/usb/usbmon/0u > /tmp/1.mon.out
La captura se guarda en este caso en el archivo /tmp/1.mon.out y se puede detener con Control-C. Para comprender los que se muestra en la captura puede ir a https://www.kernel.org/doc/Documentation/usb/usbmon.txt
Analizando los datos de la captura
En estas parte se busca encontrar patrones que ayuden a entender el funcionamiento del protocolo.
En el caso del protocolo del ATI TV se pudo notar que al estar conectado únicamente y sin ser utilizado el driver se comunica con el dispositivo con tranferencias bulk de 12 bytes con los mismos datos y el dispositivo responde con transferencias bulk de 4 bytes con lo mismos datos. Se muestran acontinuación:
URB Bulk out 12 bytes = 00 08 00 20 04 00 00 80 FF F7 FF DF
URB Bulk in 4 bytes = 20 00 20 40
Una vez que se activa el software para visualizar los datos de audio y video del ATI TV, en este caso se utilizó Arcsoft TotalMedia 3.5, se envía un IRP Create desde el software hacia el driver del ATI TV que le indica al driver que ya hay actividad, en este momento el driver comienza a enviar continuas transferencias bulk de 12 bytes y 4 bytes y a recibir transferencias bulk de 4 bytes distintas las iniciales.
Un patrón interesante a encontrar es que muchos de las tranferencias bulk de 12 bytes que envía el driver son casi iguales, pero una difrencia de 1 byte indica si la tranferencia bulk que sigue es otro envío esta vez de 4 bytes o sí más bien se espera una respuesta también de 4 bytes. Por ejemplo:
Se envía:
URB Bulk out 12 bytes = 00 14 00 20 04 00 00 **80** FF EB FF DF
Se recibe:
URB Bulk in 4 bytes = 00 00 10 00
Pero si se cambia el 80 por un 00 y se envía:
URB Bulk out 12 bytes = 00 14 00 20 04 00 00 **00** FF EB FF DF
Se vuelve a enviar:
URB Bulk out 4 bytes = 00 00 10 00
Después de enviar muchas tranferencias bulk de este tipo, lo que parece el protocolo de inicialización del dispositivo, el dispositivo envía al driver un URB Sync Reset Pipe and Clear Stall, con lo que se abre el paso para recibir transferencias Isochronous, en donde viaja el video compuesto de entrada, en este caso la señal de un Play Station 2. Durante el envío de las transferencias Isochronous sigue habiendo una comunicación entre el driver y el dispositivo por medio de transferencias Bulk.
Realizando el driver del ATI TV
Los datos visibles al utilizar el comando #lsusb -v, son útiles ya que además de conocer el bus en el que se encuentra el dispositivo podemos conocer su vendor id y su product id que se pueden usar para encontrar y reconocer el dispositivo entre todos los demás. Además, utilizando la información de los endpoints descriptors puedo saber cuales de estos son utilizados en transferencias bulk o isochronous y cual es su numero para poder escribir o leer del endpoint correcto según el tipo de transferencia que se desea realizar.
Conociendo el driver del easycap_utv007 disponible en https://github.com/memeruiz/usbtv007 y con las datos obtenidos anteriormente como el vendor id, product id, endpoint descriptors además de las tranferencias bulk necesarias para inicializar el ATI TV, es posible modificar este driver para obtener uno que funcione para el ATI TV.