USB 2.0 Datum: 2003-10-13 Handledare/Lärare: Ulf Brydsten Björne Lindberg Lars Karlsson Johannes Karlsson Av: Mikael Backlund USB 2.0 Mikael Backlund Wearable Computer HT 2003 2 Sammanfattning USB 2.0 är en standard för seriell dataöverföring som utvecklades för att tillgodose marknadens nya krav på högre bandbredd. I denna rapport går jag igenom vilka hastigheter USB 2.0 stödjer, hur en USB buss är uppbyggd (dess topologi), vilka hårdvarukomponenter en USB buss innehåller och hur de fungerar. Går även in lite närmare på själva överföringen och dataflöde. Några mer allmänna saker som kompatibilitet, användningsområde och USB On The Go tas även det upp. 2 USB 2.0 Mikael Backlund Wearable Computer HT 2003 3 Innehållsförteckning INLEDNING .......................................................................................................................................... 4 ARKITEKTUR ...................................................................................................................................... 5 TOPOLOGI ............................................................................................................................................ 5 TYPER AV USB .................................................................................................................................... 6 HOT PLUG ............................................................................................................................................ 6 HÅRDVARA .......................................................................................................................................... 7 KOMPONENTER .................................................................................................................................... 7 USB Host ........................................................................................................................................ 7 Hub ................................................................................................................................................. 8 USB Enhet ...................................................................................................................................... 8 Kablage .......................................................................................................................................... 8 STRÖMFÖRSÖRJNING.......................................................................................................................... 10 ÖVERFÖRING .................................................................................................................................... 10 PROTOKOLLAGRET............................................................................................................................. 10 Tokenpaket ................................................................................................................................... 10 Datapaket ..................................................................................................................................... 11 Handskakningspaket ..................................................................................................................... 11 CRC .............................................................................................................................................. 12 Data toggle synchronisation......................................................................................................... 12 Bus Turn-around Timing .............................................................................................................. 13 DATAFLÖDE ....................................................................................................................................... 14 Typer av dataöverföring ............................................................................................................... 14 NRZI-KODNING OCH BITSTUFFING..................................................................................................... 15 ALLMÄNT ........................................................................................................................................... 16 MÅL MED STANDARDEN..................................................................................................................... 16 USB ON THE GO ................................................................................................................................. 16 KOMPATIBILITET ............................................................................................................................... 17 ANVÄNDNINGS OMRÅDE .................................................................................................................... 17 IMPLEMENTATION ......................................................................................................................... 18 PRAKTISK TILLÄMPNING ............................................................................................................. 19 USB DRIVRUTIN FÖR PHILIPS WEBKAMERA ....................................................................................... 19 BILAGA 1: KÄLLKOD ...................................................................................................................... 21 3 USB 2.0 Mikael Backlund Wearable Computer HT 2003 4 Inledning Under mitten av 90-talet påbörjade 7 företag utvecklingen av en ny standard för seriell överföring. Standarden fick namnet USB(Universal Serial Bus) och företagen var Compaq, Hewlett-Packard, Intel, Lucent, Microsoft, NEC och Philips. Den nya standarden skulle uppfylla tre krav som företagen ansåg vara kritiska, lätt att använda med stöd för plug and play, billig men ändå stor bandbredd och att med hjälp av USB kunna koppla ihop datorn med kommunikations apparater t. ex telefon. Dagens USB version som släpptes i april år 2000 går under namnet 2.0. USB 2.0 stödjer tre hastigheter: 1.5Mbit/s, 12Mbit/s och 480Mbit/s. Den senaste går under namnet High-speed USB och utvecklades speciellt för videoöverföring, lagring, bildmanipulering och bredband. USB är med sin billiga produktionskostnad och enkelhet idag ledande inom sin marknad för periferienheter (tangentbord, mus, spelkontroll, skrivare, bärbar lagringsmedia m. m). Samt att många andra applikationer för USB har tagits fram så som laddare till mobiltelefoner, lampor m. m. 4 USB 2.0 Mikael Backlund Wearable Computer HT 2003 5 Arkitektur Topologi Nätverket för en USB buss är uppbyggt som ett stjärnnätverk med distinkta nivåer. För varje steg som nätet tar ifrån sin host bildas en ny nivå med en eller flera stjärnor och i centrum av dess stjärnor återfinns alltid en hub. Det maximala antalet nivåer en USB buss kan ha är sju, detta beror på att responstiden försämras i kablar och hubbar. En sammansatt enhet (compound device) består av både en hub och en enhet och tar således upp två nivåer och kan därför ej kopplas in som sjunde led i nätet. Bilden nedan visar en typiskt USB buss uppkoppling som illustrerar tre nivåer och en sammansatt enhet. 5 USB 2.0 Mikael Backlund Wearable Computer HT 2003 6 Typer av USB Det finns tre versioner av USB specificerade i 2.0 standarden. Version Low speed Full speed Bandbredd 1.5Mbit/s 12Mbit/s High speed 480Mbit/s High-speed versionen utvecklades fram till USB 2.0 speciellt för enheter som kräver stor bandbredd så som videoöverföring, lagring m.m. De två andra versionerna används på mer normala enheter så som möss, tangentbord, skrivare m.m. Men oftast på dagens USB bussar används hög hastighetsversionen mellan nätets host och hubbar samt mellan hubbar och hubbar, låg och full hastigheterna används oftast endast mellan hubbar och enheter. Detta minskar chanserna att en långsammare enhet fördröjer en snabbare enhet. Hot plug USB utnyttjar hot-plug teknologi som gör det möjligt att koppla till eller ifrån enheter medan system är igång. När en enhet kopplas in eller ifrån noterar hubben det och lagrar förändringen i sin status. Hubbens host frågar regelbundet om några förändringar skett och förändringar skett utför lämpliga åtgärder. Portar på hubben öppnas eller stängs, adresser tilldelas eller tas bort o.s.v. Om enheten som togs bort eller las till är en hub så upprepas detta för alla enheter som den hade uppkopplat till sig. När en enhet läggs till får dess inbyggda mjukvara ta hand om sin initieringen. 6 USB 2.0 Mikael Backlund Wearable Computer HT 2003 7 Hårdvara Komponenter En USB-buss byggs upp av en del olika fysiska delar, dessa är: USB Host Hub USB enhet Kablage De flesta moderna datorsystem har en Host och en hub inbyggd, så allt som behövs för att få en fungerande USB enhet är den aktuella enheten och kabeln mellan enheten och hubben. Men de existerande USB systemen kan enkelt byggas ut om behovet finns. Utbyggnad sker enklast genom att hubbar kopplas ihop med andra hubbar och på så sätt görs en port om till flera. Enheten i sig kan också ha en inbyggd hub och därigenom bidra till utbyggnad av systemet. USB Host Består logiskt av tre separata delar. USB Host kontroller Systemets mjukvara (drivrutiner m. m) Klientens mjukvara Host:en är den fysiska del som koordinerar dataflödet till enheterna på sitt USB nät. Om en enhet vill använda bussen för t. ex en överföring måste den först få tillstånd av sin host. Om flera enheter samtidigt vill ha tillgång så har nätets host specifika ansvarsförhållanden med varje enskild enhet och kan därigenom särställa vilken enhet som får gå först. Varje host har också i uppgift att övervaka topologin för sin buss, alltså måste den hålla reda på hur nätet runt den ser ut. Inne i varje host finns en inbyggd hub kallad root hub. 7 USB 2.0 Mikael Backlund Wearable Computer HT 2003 8 Hub Abstrakt är en hub som ett nav i ett hjul, den tillåter flera enheter/hubbar att få kontakt med en host. Men under ytan utför huben en mängd viktiga funktioner åt sitt nät. Det är här som hastigheten på enheterna avgörs, om en enhet kopplas till eller från är det här som det upptäcks, strömförsörjning till enheterna sköts också här. En USB hub byggs upp av tre komponenter, hub repeater, hub controller och en hub translator. Hub repeatern hanterar händelser där en enhet läggs till eller tas bort samt att den hanterar vissa undantagstillstånd. Hub controllern sköter kommunikation mellan host och hub. Hub translatorn konverterar high-speed överföringar ämnade för enheter som ej klarar den hastigheten till full-/low-speed. USB Enhet Logisk utseende för en USB enhet: Buss interface Logisk enhet Funktion En fysisk USB enhet tillför funktionalitet till sin host, en funktionalitet som kan variera stort mellan olika enheter. Men även om funktionaliteten är väldigt olika mellan två enheter används samma interface emot bussen för båda. Detta medför att en host på ett nät med mängder av olika enheter endast behöver kommunicera med dem på ett sätt. Ungefär som att säga att alla enheter pratar samma språk men ändå är totalt olika. Varje enskild enhet innehåller och rapporterar sin egen konfigurationsinformation till sin host vid kontakt för att nätets host skall kunna identifiera enheten. Konfigurationsinformationen innehåller även specifik information rörande enhetens funktion. Kablage En USB kabel består av 4 ledare, 2 dataledare (D- och D+) och två matningsledare (Vbuss och GND). Kablarna kan vara uppbyggda olika för låg hastighet mot full och hög hastighet. Kablar för låg hastighets USB rekommenderar men kräver inte tvinnade dataledare eller ett flätat yttre skyddslager medan de högre hastigheterna kräver det. 8 USB 2.0 Mikael Backlund Wearable Computer HT 2003 9 Bilden nedan visar en genomskärning av en USB kabel: USB kablar kan ha tre olika kontakter: Modell A Riktning (dataflöde) Upstream Kopplas mot Host/hub B Downstream Enhet Mini-B Downstream Enhet Bilden nedan visar modell A och modell B kontakter: Så en USB kabel har alltid en A kontakt och antingen en B eller mini-B kontakt. Mini-B kontakten togs speciellt fram för att användas på små enheter som t. ex digitalkameror. 9 USB 2.0 Mikael Backlund Wearable Computer HT 2003 10 Strömförsörjning En USB enhet kan antingen ha en egen strömkälla eller använda bussen som strömkälla. Men blanda med försiktighet, använda mer än en strömkälla kan medföra problem. USB bussen levererar en spänning på mellan 4.4V och 5.25V och en maximal ström på 500mA, vilket räcker och blir över till små enheter som möss, tangentbord etc. Överföring Protokollagret Protokollet för USB talar om hur bitarna i paketen som skickas på USB bussen är uppbyggda. All överföring sker med att LSB (least significant bit) skickas först och MSB (most significant bit) sist. Det finns fyra olika typer av paket inom USB protokollet. Token Data Handskakning Special Gemensamt för alla typer av paket är synkroniseringsfältet (SYNC) som används för att få inkommande data synkroniserat med systemklockan samt paketidentifieringsfältet (PID) som kommer efter SYNC fältet, PID fältet anger vilket typ av paket, vilket format samt vilken typ av felkontroll som paketet utnyttjar. På slutet av alla paket utom handskakningspaketen återfinns CRC fältet för felkontroller. Tokenpaket PID-fältet talar om vad för typ av paket det är. IN, OUT eller SETUP är de tre olika typer av paket ett tokenpaket kan vara. För OUT och SETUP paket talar ADDR-fältet och ENDP-fältet om vilken ändpunkt som skall ta emot det följande datapaketet. För IN paket talar de om vilken ändpunkt som skickar det kommande paketet. CRCfältet har till uppgift att skydda ADDR och ENDP fälten. Det finns ett till speciellt definierat tokenpaket kallat SPLIT och som används vid delade överföringar t. ex när en host kommunicerar med en hub med hög hastighet 10 USB 2.0 Mikael Backlund Wearable Computer HT 2003 11 och med en på full eller låg hastighet. Denna token är 1 byte längre än den normala tokenstandarden och de ytterligare 4 bitarna möjliggör ytterligare typer och mer specifik överföringsinformation. Det finns två definierade SPLIT överföringsmetoder: SSPLIT – start-split transaction CSPLIT – complete-split transaction Ovan: Denna bild illustrerar ett token paket och dess fält. Datapaket PID fältet följs av ett 0-8192 bitar långt data fält samt en 16 bitars CRC fält. Fyra olika sorters datapaket finns: DATA0, DATA1, DATA2 och MDATA. Två av dessa (DATA0, DATA1) är designade att stödja data toggle synchronisation. Alla fyra kan användas av ändpunkter som använder högfart och kräver mycket bandbredd. MDATA, DATA0 och DATA1 används även inom delade överföringar. Storleken på datafältet får ej överstiga 8 bytes vid låghastighetsöverföring, 1023 bytes vid fullfarts och 1024 bytes vid höghastighetsöverföring. Paketet ovan är ett datapaket. Handskakningspaket Det består av ett PID fält och inget mer. Handskakningspaket används för att hålla koll på statusen av en överföring. En handskakning kan returnera om det gått bra, om det blev fel, om kommandot mottagits eller förkastats, flödeskontroll och om en situation uppstår där nåt vill stoppa överföringenn. Det finns 5 typer av handskakningsmeddelanden. ACK som säger att allt är ok. NAK skickas när det inte finns någon data att skicka eller när data från nätets host inte kunde tas emot. STALL används när en enhet är upptagen och ej kan ta emot eller skicka data. 11 USB 2.0 Mikael Backlund Wearable Computer HT 2003 12 NYET är en hög hastighets handskakning som endast används i två fall, som en del av ett PING protokoll eller som ett svar på en överföring mellan två delar i nätet som kör på olika hastigheter och där låg eller full farts överföringen inte hunnit klart ännu. ERR är ett felmeddelande som används som svar när en höghastighets hub vill anmäla ett fel på en låg eller full fart hub. Handskakningspaketet som bilden ovan visar är det enklaste paketet inom USB protokollet. CRC Cyclic Redundancy Checks används för att skydda alla fält utom PID fältet i tokenoch datapaket. CRC kodning genereras hos sändaren och avkodas hos mottagaren. Om CRC kollen inte godkänns tas åtminstone det fält som är korrupt bort men oftast kastas hela paketet. Kodningssystemet som används är att för varje bit som skickas eller tas emot körs en bitvis XOR mot den nuvarande summans högsta del, efteråt skiftas summans ett steg vänster och summans låga del nollställs. När proceduren gjorts för hela paketet och summan är ett så XOR:as summan med kodgeneratorns polynom. När sista tecknet som kollats skickats inverteras generatorns CRC och skickas till kontrollanten MSb först. När sista tecknet mottagits av kontrollanten och inga fel upptäckts så ska summan vara lika med den överblivna polynomet. Eftersom USB utnyttjar bitstuffing (förklaras längre fram i kapitlet) så måste givitvis dessa krav uppfyllas i CRC generering/kontroll. Alltså om CRC koden innehåller sex raka logiska ettor måste det sättas in en logisk nolla. Tokenpaket använder ett 5-bitars fält för CRC. Detta fält skyddar adress- och ändpunktsfälten. Detta pakets polynom är på binär form: 00101B. Om alla bitars tas emot korrekt så blir det överblivna polynomet hos mottagaren: 01100B. Datapaket har ett 16-bitar långt CRC fält som har till uppgift att skydda datafältet. Polynomets binära mönster: 1000000000000101B. Överblivna polynomet: 1000000000001101B. Data toggle synchronisation USB har en inbyggd mekanism för att garantera att data sekvenserna mellan sändare och mottagare är synkroniserade. Med denna funktion kan man vara säker på att 12 USB 2.0 Mikael Backlund Wearable Computer HT 2003 13 handskakningar mellan sändare och mottagare är korrekta. Synkronisering uppnås med hjälp av PID fältet som anger DATA0 och DATA1 som typ av datapaket. Dessa paket har separata sekvensbitar för sändare respektive mottagare. Sekvensbitarna hos mottagaren togglas när den är redo att motta ett nytt paket och får ett korrekt datapaket med rätt information i paketets PID-fält. Sändaren togglar bitarna när den får en korrekt ACK handskakning. För att en överföring skall bli korrekt måste båda sidor vara synkroniserade i början av den överföringen. Denna mekanism fungerar endast vid synkrona överföringar. Bilderna nedan illustrerar hur sekvensbitarna (siffran i parentesen) togglar i två olika fall. Först två raka korrekta överföringar sen under den en felaktig sen en korrekt. ---------------------------------------------------------- Bus Turn-around Timing Eftersom varken en host eller en enhet skickar nån form av meddelande om nåt går fel så måste ett brist på svar att det gått bra ses som att det fel. För att få det att fungera måste därför både enheten och dess host hålla reda på hur mycket tid som gått sedan sändaren skickade ett paket. Tiden mellan när sändaren skcikat och när den börjar ta emot svarspaketet kallas bus turn-around time. En enhet sätter sin bus turn-around time till den värsta tur-retur fördröjningen plus enhetens maximala svarsdelay. 13 USB 2.0 Mikael Backlund Wearable Computer HT 2003 14 Dataflöde USB erbjuder kommunikation mellan enheten och mjukvaran hos dess host. Olika enheter kan ha olika krav på kommunikationen och dess dataflöde. USB separerar därför på sina olika kommunikationer för att bättre utnyttja bussen. Varje kommunikation får ett rör (pipe) att kommunicera igenom. På den sidan dit datat skall skickas skapas en ändpunkt (endpoint) som har hand om diverse information om kommunikationen, hastighet, överföringstyp och riktning bland annat. Ändpunkten är en del av enheten och bussen och varje enhet måste minst ha en ändpunkt (ändpunkt 0) men kan ha flera. Ändpunkt 0 består av två separata ändpunkter, en för indata och en för utdata och används mestadels för konfiguration och initiering. Varje enskild ändpunkt kan bli adresserad med hjälp av sitt ändpunktsnummer, riktning på överföring samt enhetens adress. Ett rör är en association mellan ändpunkten på en enhet och mjukvaran på en host. Rören använder en minnesbuffer vid dessa överföringar. Bilden nedan demonstrerar logiskt hur rör och ändpunkter fungerar. Typer av dataöverföring I USB standarden finns fyra olika typer av dataöverföring specificerade. Kontroll: snabba, ej periodiska, begäran och svars kommunikation som oftast används vid kommando och status operationer. Isokronisk: Periodisk fortlöpande kommunikation mellan host och enhet, används för det mesta till tidsrelaterade operationer. Avbrott: Överföringar som inte händer så ofta och är bundna till något speciellt. Volym: Denna typ är avsedd för dataöverföringar, ej periodisk, stora paket, klarar alla hastigheter och kan vänta tills rätt bandbredd finns tillgänglig. För att få dessa överföringar att bli korrekta krävs att de körs i rätt sekvens vilket man löst med tillståndsmaskiner i båda ändarna. 14 USB 2.0 Mikael Backlund Wearable Computer HT 2003 15 NRZI-kodning och bitstuffing USB utnyttjar NRZI kodning vid överföring. Det innebär att en logisk ”1” är när det inte är någon spänningsändring och logisk ”0” är vid spänningsändring. Bilden nedan demonstrerar NRZI kodning. För att försäkra godtagbara signalöverföringar har man även implementerat bitstuffing, vilket innebär att efter 6 stycken raka ”1” sätter man in en ”0”. Alltså ligger spänningen oförändrad sex bitar på raken ändrar man spänningen. Detta gör att en ändring i spänningen sker minst var sjunde bit vilket försäkrar att synkning och klockning stämmer. 15 USB 2.0 Mikael Backlund Wearable Computer HT 2003 16 Allmänt Mål med standarden I början hade man tre stora anledningar till att man ville utveckla en ny seriell standard. Telefoni marknaden hade oanade framtida behov och en standard som medförde PC till telekommunikation sågs som ett stort steg i rätt riktning. Datorn var fortfarande inte så användarvänlig som den kunde vara, speciellt parallell portarna och serieportarna eftersom de inte stödde plug and play. Så en standard för att ersätta dessa portar samtidigt som den stödde plug and play vore väldigt bra. Expansionssvårigheter med dåvarande portar, en port som var enkel att utvidga och samtidigt kunna klara av nog höga hastigheter för avancerad utrustning skulle medföra ytterligare möjligheter för datorn och föra utvecklingen åt rätt håll. USB 2.0 standarden har en stor skillnad från tidigare versioner av USB, den klarar 480 Mbit/s överföring. Detta var det stora målet för den nya USB standarden när utvecklingen av 2.0 påbörjades 1998-99. Marknaden krävde högre hastigheter med alla digitala utrustningar som utvecklades till datorn. Speciellt inom video, bild och lagringsmedia. USB on the go On The Go är namnet på ett tillägg i USB 2.0 standarden som möjliggör att två eller flera USB enheter skall kunna kommunicera direkt med varandra utan att en dator/kontroller behövs. En del saker i USB standarden gör detta mycket svårt för kommunikation kan endast ske mellan en host och en enhet med en hub som mellanhand, och även om vissa enheter har inbyggda hubbar så finns det inte någon host i någon enskild enhet. Enheten måste även kunna lagra data i form av drivrutiner och få ström på något sätt. För att få detta att fungera utvecklades ett tillägg till USB 2.0 som kallas USB OnThe-Go. Det möjliggör att en enhet skall kunna fungera i en roll som en begränsad host. 16 USB 2.0 Mikael Backlund Wearable Computer HT 2003 17 Kompatibilitet Eftersom USB standarden har utvecklas genom åren krävs det någon form av kompatibilitet. I USB 2.0 är det full kompatibilitet bakåt. Utrustning som utvecklades och använder USB 1.1 kan köras utan bekymmer på en dator som har USB 2.0. Användnings område USB är ett seriellt dataöverföringsmedium som är lätt att använda och passar därför perfekt som medium för utrustning anpassad för privatpersonen t. ex digitalkameror, spelkontroller och videkameror. Eftersom USB stödjer plug and play och smidig att använda är den även utmärkt för standardutrustning så som möss, skrivare, tangentbord. Enkelheten att implementera USB i inbyggda lösningar öppnar även marknaden för såväl proffsutvecklare som amatörerna. 17 USB 2.0 Mikael Backlund Wearable Computer HT 2003 18 Implementation USB går förmodligen att implementera på alla dagens mikrokontrollers/processorer och datasystem men undersök alltid om den aktuella processorn/kontroller klarar det. I vårt projekt använder vi ett utvecklingskort från Axis. På det kortet sitter en Etrax 100LX processor och på deras hemsida finns instruktioner om hur parallellporten på utvecklingskortet enkelt kan konstrueras om till en USB port. Det finns färdiga USB-interface kretsar att köpa som möjliggör USB kommunikation mellan mikroprocessorer eller enchipsdatorer och vanliga PC system. Dessa kretsar använder antingen parallellt interface eller seriellt interface men resultatet blir detsamma. Efter att konstruktionen/ombyggnaden är klar behövs mjukvara i form av drivrutiner och program för att hantera all data. 18 USB 2.0 Mikael Backlund Wearable Computer HT 2003 19 Praktisk tillämpning USB drivrutin för Philips webkamera Detta är en drivrutin utvecklad för Philips webkameror som utnyttjar V4L (video for linux). Den består av två enheter, en videoenhet och en USB enhet. När modulen laddas körs initieringen för USB enheten och ger videoenheten en device node samt registrerar USB enheten till USB kärnan. Sedan när en enhet pluggas in i USB porten eller när USB kärnan ladas körs probe kommandot till USB-enheten. Probe kommandot kollar vad för sorts kamera som sitter på porten, sen initieras enhetsstrukturen, diverse pekare och videoenheten länkas till USB-enheten. Mer inställningar utföres, spinlock låses upp, initierar en kö och sätter ägaren till modulen är några. Efter det sökes en lista med nodnummer igenom efter en ledig plats och när den hittas försöker drivrutinen registrera en videoenhet. Drivrutinen har även en disconnect drivrutin som exekveras vid händelse att enheten kopplas ur. Det första den funktionen utför är en funktion som låser kärnan. Efter det kollas om nåt fel uppstod i.s.f lås upp kärnan och hoppa ur funktionen. Om det inte var nåt fel utan enheten blev urkopplad kolla först om den användes vid urkoppling. Efter det stäng videoenheten och avregistrera den samt frigör resurser som allokerats. På slutet av denna funktion låses kärnan upp. Källkod medföljer som bilaga. 19 USB 2.0 Mikael Backlund Wearable Computer HT 2003 20 Källförteckning USB 2.0 specifikation http://www.usb.org/developers/docs/usb_20.zip Axis utvecklingskort byggs om för USB http://developer.axis.com/doc/hardware/devboard_lx/USB_Devboard_LX.pdf USB drivrutin http://www.smcc.demon.nl/webcam/pwc-8.12.tar.gz 20 USB 2.0 Mikael Backlund Wearable Computer HT 2003 21 Bilaga 1: Källkod /* Linux driver for Philips webcam USB and Video4Linux interface part. (C) 1999-2003 Nemosoft Unv. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* This code forms the interface between the USB layers and the Philips specific stuff. Some adanved stuff of the driver falls under an NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and is thus not distributed in source form. The binary pwcx.o module contains the code that falls under the NDA. In case you're wondering: 'pwc' stands for "Philips WebCam", but I really didn't want to type 'philips_web_cam' every time (I'm lazy as any Linux kernel hacker, but I don't like uncomprehensible abbreviations without explanation). Oh yes, convention: to disctinguish between all the various pointers to device-structures, I use these names for the pointer variables: udev: struct usb_device * vdev: struct video_device * pdev: struct pwc_devive * */ /* Contributors: - Alvarado: adding whitebalance code - Alistar Moire: QuickCam 3000 Pro device/product ID - Tony Hoyle: Creative Labs Webcam 5 device/product ID - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged - Jk Fang: Sotec Afina Eye ID - Xavier Roche: QuickCam Pro 4000 ID - Jens Knudsen: QuickCam Zoom ID - J. Debert: QuickCam for Notebooks ID */ #include #include #include #include #include #include #include #include #include <linux/errno.h> <linux/init.h> <linux/mm.h> <linux/module.h> <linux/poll.h> <linux/slab.h> <linux/vmalloc.h> <linux/wrapper.h> <asm/io.h> #include "pwc.h" #include "pwc-ioctl.h" #include "pwc-uncompress.h" /* Function prototypes and driver templates */ 21 USB 2.0 Mikael Backlund Wearable Computer HT 2003 22 /* hotplug device table support */ static struct usb_device_id pwc_device_table [] = { { USB_DEVICE(0x0471, 0x0302) }, /* Philips models */ { USB_DEVICE(0x0471, 0x0303) }, { USB_DEVICE(0x0471, 0x0304) }, { USB_DEVICE(0x0471, 0x0307) }, { USB_DEVICE(0x0471, 0x0308) }, { USB_DEVICE(0x0471, 0x030C) }, { USB_DEVICE(0x0471, 0x0310) }, { USB_DEVICE(0x0471, 0x0311) }, { USB_DEVICE(0x0471, 0x0312) }, { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */ { USB_DEVICE(0x069A, 0x0001) }, /* Askey */ { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */ { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */ { USB_DEVICE(0x046D, 0x08B2) }, /* Logitech QuickCam Pro 4000 */ { USB_DEVICE(0x046D, 0x08B3) }, /* Logitech QuickCam Zoom (old model) */ { USB_DEVICE(0x046D, 0x08B4) }, /* Logitech QuickCam Zoom (new model) */ { USB_DEVICE(0x046D, 0x08B5) }, /* Logitech QuickCam Orbit/Sphere */ { USB_DEVICE(0x046D, 0x08B6) }, /* Logitech (reserved) */ { USB_DEVICE(0x046D, 0x08B7) }, /* Logitech (reserved) */ { USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */ { USB_DEVICE(0x055D, 0x9000) }, /* Samsung */ { USB_DEVICE(0x055D, 0x9001) }, { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */ { USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */ { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */ { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */ { USB_DEVICE(0x0d81, 0x1900) }, { } }; MODULE_DEVICE_TABLE(usb, pwc_device_table); static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id); static void usb_pwc_disconnect(struct usb_device *udev, void *ptr); static struct usb_driver pwc_driver = { name: "Philips webcam", id_table: pwc_device_table, probe: usb_pwc_probe, disconnect: usb_pwc_disconnect, }; #define MAX_DEV_HINTS 20 #define MAX_ISOC_ERRORS /* name */ /* probe() */ /* disconnect() */ 20 static static static static int default_size = PSZ_QCIF; int default_fps = 10; int default_fbufs = 3; /* Default number of frame buffers */ int default_mbufs = 2; /* Default number of mmap() buffers */ int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX; static int power_save = 0; static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */ int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */ static struct { int type; char serial_number[30]; int device_node; struct pwc_device *pdev; } device_hint[MAX_DEV_HINTS]; /***/ static int pwc_video_open(struct video_device *vdev, int mode); static void pwc_video_close(struct video_device *vdev); static long pwc_video_read(struct video_device *vdev, char *buf, unsigned long count, int noblock); static long pwc_video_write(struct video_device *vdev, const char *buf, unsigned long count, int noblock); 22 USB 2.0 Mikael Backlund Wearable Computer HT 2003 23 static unsigned int pwc_video_poll(struct video_device *vdev, struct file *file, poll_table *wait); static int pwc_video_ioctl(struct video_device *vdev, unsigned int cmd, void *arg); static int pwc_video_mmap(struct video_device *vdev, const char *adr, unsigned long size); static struct video_device pwc_template = { owner: THIS_MODULE, name: "Philips Webcam", type: VID_TYPE_CAPTURE, hardware: VID_HARDWARE_PWC, open: pwc_video_open, close: pwc_video_close, read: pwc_video_read, write: pwc_video_write, poll: pwc_video_poll, ioctl: pwc_video_ioctl, mmap: pwc_video_mmap, initialize: NULL, minor: 0 }; /* Filled in later */ /* initialize */ /* minor */ /***************************************************************************/ /* Okay, this is some magic that I worked out and the reasoning behind it... The biggest problem with any USB device is of course: "what to do when the user unplugs the device while it is in use by an application?" We have several options: 1) Curse them with the 7 plagues when they do (requires divine intervention) 2) Tell them not to (won't work: they'll do it anyway) 3) Oops the kernel (this will have a negative effect on a user's uptime) 4) Do something sensible. Of course, we go for option 4. It happens that this device will be linked to two times, once from usb_device and once from the video_device in their respective 'private' pointers. This is done when the device is probed() and all initialization succeeded. The pwc_device struct links back to both structures. When a device is unplugged while in use it will be removed from the list of known USB devices; I also de-register it as a V4L device, but unfortunately I can't free the memory since the struct is still in use by the file descriptor. This free-ing is then deferend until the first opportunity. Crude, but it works. A small 'advantage' is that if a user unplugs the cam and plugs it back in, it should get assigned the same video device minor, but unfortunately it's non-trivial to re-link the cam back to the video device... (that would surely be magic! :)) */ /***************************************************************************/ /* Private functions */ /* Here we want the physical address of the memory. * This is used when initializing the contents of the area. */ static inline unsigned long kvirt_to_pa(unsigned long adr) { unsigned long kva, ret; kva = (unsigned long) page_address(vmalloc_to_page((void *)adr)); kva |= adr & (PAGE_SIZE-1); /* restore the offset */ ret = __pa(kva); return ret; } static void * rvmalloc(unsigned long size) { 23 USB 2.0 Mikael Backlund Wearable Computer HT 2003 24 void * mem; unsigned long adr; size=PAGE_ALIGN(size); mem=vmalloc_32(size); if (mem) { memset(mem, 0, size); /* Clear the ram out, no junk to the user */ adr=(unsigned long) mem; while (size > 0) { mem_map_reserve(vmalloc_to_page((void *)adr)); adr+=PAGE_SIZE; size-=PAGE_SIZE; } } return mem; } static void rvfree(void * mem, unsigned long size) { unsigned long adr; if (mem) { adr=(unsigned long) mem; while ((long) size > 0) { mem_map_unreserve(vmalloc_to_page((void *)adr)); adr+=PAGE_SIZE; size-=PAGE_SIZE; } vfree(mem); } } static int pwc_allocate_buffers(struct pwc_device *pdev) { int i; void *kbuf; Trace(TRACE_MEMORY, ">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev); if (pdev == NULL) return -ENXIO; #ifdef PWC_MAGIC if (pdev->magic != PWC_MAGIC) { Err("allocate_buffers(): magic failed.\n"); return -ENXIO; } #endif /* Allocate Isochronuous pipe buffers */ for (i = 0; i < MAX_ISO_BUFS; i++) { if (pdev->sbuf[i].data == NULL) { kbuf = kmalloc(ISO_BUFFER_SIZE, GFP_KERNEL); if (kbuf == NULL) { Err("Failed to allocate iso buffer %d.\n", i); return -ENOMEM; } Trace(TRACE_MEMORY, "Allocated iso buffer at %p.\n", kbuf); pdev->sbuf[i].data = kbuf; memset(kbuf, 0, ISO_BUFFER_SIZE); } } /* Allocate frame buffer structure */ if (pdev->fbuf == NULL) { 24 USB 2.0 Mikael Backlund Wearable Computer HT 2003 25 kbuf = kmalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL); if (kbuf == NULL) { Err("Failed to allocate frame buffer structure.\n"); return -ENOMEM; } Trace(TRACE_MEMORY, "Allocated frame buffer structure at %p.\n", kbuf); pdev->fbuf = kbuf; memset(kbuf, 0, default_fbufs * sizeof(struct pwc_frame_buf)); } /* create frame buffers, and make circular ring */ for (i = 0; i < default_fbufs; i++) { if (pdev->fbuf[i].data == NULL) { kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */ if (kbuf == NULL) { Err("Failed to allocate frame buffer %d.\n", i); return -ENOMEM; } Trace(TRACE_MEMORY, "Allocated frame buffer %d at %p.\n", i, kbuf); pdev->fbuf[i].data = kbuf; memset(kbuf, 128, PWC_FRAME_SIZE); } } /* Allocate decompressor table space */ kbuf = NULL; if (pdev->decompressor != NULL) { kbuf = kmalloc(pdev->decompressor->table_size, GFP_KERNEL); if (kbuf == NULL) { Err("Failed to allocate decompress table.\n"); return -ENOMEM; } Trace(TRACE_MEMORY, "Allocated decompress table %p.\n", kbuf); } pdev->decompress_data = kbuf; /* Allocate image buffer; double buffer for mmap() */ kbuf = rvmalloc(default_mbufs * pdev->len_per_image); if (kbuf == NULL) { Err("Failed to allocate image buffer(s).\n"); return -ENOMEM; } Trace(TRACE_MEMORY, "Allocated image buffer at %p.\n", kbuf); pdev->image_data = kbuf; for (i = 0; i < default_mbufs; i++) pdev->image_ptr[i] = kbuf + i * pdev->len_per_image; for (; i < MAX_IMAGES; i++) pdev->image_ptr[i] = NULL; kbuf = NULL; Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n"); return 0; } static void pwc_free_buffers(struct pwc_device *pdev) { int i; Trace(TRACE_MEMORY, "Entering free_buffers(%p).\n", pdev); if (pdev == NULL) return; #ifdef PWC_MAGIC if (pdev->magic != PWC_MAGIC) { Err("free_buffers(): magic failed.\n"); return; } #endif 25 USB 2.0 Mikael Backlund Wearable Computer HT 2003 26 /* Release Iso-pipe buffers */ for (i = 0; i < MAX_ISO_BUFS; i++) if (pdev->sbuf[i].data != NULL) { Trace(TRACE_MEMORY, "Freeing ISO buffer at %p.\n", pdev>sbuf[i].data); kfree(pdev->sbuf[i].data); pdev->sbuf[i].data = NULL; } /* The same for frame buffers */ if (pdev->fbuf != NULL) { for (i = 0; i < default_fbufs; i++) { if (pdev->fbuf[i].data != NULL) { Trace(TRACE_MEMORY, "Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data); vfree(pdev->fbuf[i].data); pdev->fbuf[i].data = NULL; } } kfree(pdev->fbuf); pdev->fbuf = NULL; } /* Intermediate decompression buffer & tables */ if (pdev->decompress_data != NULL) { Trace(TRACE_MEMORY, "Freeing decompression buffer at %p.\n", pdev>decompress_data); kfree(pdev->decompress_data); pdev->decompress_data = NULL; } pdev->decompressor = NULL; /* Release image buffers */ if (pdev->image_data != NULL) { Trace(TRACE_MEMORY, "Freeing image buffer at %p.\n", pdev->image_data); rvfree(pdev->image_data, default_mbufs * pdev->len_per_image); } pdev->image_data = NULL; Trace(TRACE_MEMORY, "Leaving free_buffers().\n"); } /* The frame & image buffer mess. Yes, this is a mess. Well, it used to be simple, but alas... In this module, 3 buffers schemes are used to get the data from the USB bus to the user program. The first scheme involves the ISO buffers (called thus since they transport ISO data from the USB controller), and not really interesting. Suffices to say the data from this buffer is quickly gathered in an interrupt handler (pwc_isoc_handler) and placed into the frame buffer. The frame buffer is the second scheme, and is the central element here. It collects the data from a single frame from the camera (hence, the name). Frames are delimited by the USB camera with a short USB packet, so that's easy to detect. The frame buffers form a list that is filled by the camera+USB controller and drained by the user process through either read() or mmap(). The image buffer is the third scheme, in which frames are decompressed and converted into planar format. For mmap() there is more than one image buffer available. The frame buffers provide the image buffering. In case the user process is a bit slow, this introduces lag and some undesired side-effects. The problem arises when the frame buffer is full. I used to drop the last frame, which makes the data in the queue stale very quickly. But dropping the frame at the head of the queue proved to be a litte bit more difficult. I tried a circular linked scheme, but this introduced more problems than it solved. 26 USB 2.0 Mikael Backlund Wearable Computer HT 2003 27 Because filling and draining are completely asynchronous processes, this requires some fiddling with pointers and mutexes. Eventually, I came up with a system with 2 lists: an 'empty' frame list and a 'full' frame list: * Initially, all frame buffers but one are on the 'empty' list; the one remaining buffer is our initial fill frame. * If a frame is needed for filling, we try to take it from the 'empty' list, unless that list is empty, in which case we take the buffer at the head of the 'full' list. * When our fill buffer has been filled, it is appended to the 'full' list. * If a frame is needed by read() or mmap(), it is taken from the head of the 'full' list, handled, and then appended to the 'empty' list. If no buffer is present on the 'full' list, we wait. The advantage is that the buffer that is currently being decompressed/ converted, is on neither list, and thus not in our way (any other scheme I tried had the problem of old data lingering in the queue). Whatever strategy you choose, it always remains a tradeoff: with more frame buffers the chances of a missed frame are reduced. On the other hand, on slower machines it introduces lag because the queue will always be full. */ /** \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first. */ static inline int pwc_next_fill_frame(struct pwc_device *pdev) { int ret; unsigned long flags; ret = 0; spin_lock_irqsave(&pdev->ptrlock, flags); if (pdev->fill_frame != NULL) { /* append to 'full' list */ if (pdev->full_frames == NULL) { pdev->full_frames = pdev->fill_frame; pdev->full_frames_tail = pdev->full_frames; } else { pdev->full_frames_tail->next = pdev->fill_frame; pdev->full_frames_tail = pdev->fill_frame; } } if (pdev->empty_frames != NULL) { /* We have empty frames available. That's easy */ pdev->fill_frame = pdev->empty_frames; pdev->empty_frames = pdev->empty_frames->next; } else { /* Hmm. Take it from the full list */ #if PWC_DEBUG /* sanity check */ if (pdev->full_frames == NULL) { Err("Neither empty or full frames available!\n"); spin_unlock_irqrestore(&pdev->ptrlock, flags); return -EINVAL; } #endif pdev->fill_frame = pdev->full_frames; pdev->full_frames = pdev->full_frames->next; ret = 1; } pdev->fill_frame->next = NULL; #if PWC_DEBUG Trace(TRACE_SEQUENCE, "Assigning sequence number %d.\n", pdev->sequence); pdev->fill_frame->sequence = pdev->sequence++; 27 USB 2.0 Mikael Backlund Wearable Computer HT 2003 28 #endif spin_unlock_irqrestore(&pdev->ptrlock, flags); return ret; } /** \brief Reset all buffers, pointers and lists, except for the image_used[] buffer. If the image_used[] buffer is cleared too, mmap()/VIDIOCSYNC will run into trouble. */ static void pwc_reset_buffers(struct pwc_device *pdev) { int i; unsigned long flags; spin_lock_irqsave(&pdev->ptrlock, flags); pdev->full_frames = NULL; pdev->full_frames_tail = NULL; for (i = 0; i < default_fbufs; i++) { pdev->fbuf[i].filled = 0; if (i > 0) pdev->fbuf[i].next = &pdev->fbuf[i - 1]; else pdev->fbuf->next = NULL; } pdev->empty_frames = &pdev->fbuf[default_fbufs - 1]; pdev->empty_frames_tail = pdev->fbuf; pdev->read_frame = NULL; pdev->fill_frame = pdev->empty_frames; pdev->empty_frames = pdev->empty_frames->next; pdev->image_read_pos = 0; pdev->fill_image = 0; spin_unlock_irqrestore(&pdev->ptrlock, flags); } /** \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers. */ static int pwc_handle_frame(struct pwc_device *pdev) { int ret = 0; unsigned long flags; spin_lock_irqsave(&pdev->ptrlock, flags); /* First grab our read_frame; this is removed from all lists, so we can release the lock after this without problems */ if (pdev->read_frame != NULL) { /* This can't theoretically happen */ Err("Huh? Read frame still in use?\n"); } else { if (pdev->full_frames == NULL) { Err("Woops. No frames ready.\n"); } else { pdev->read_frame = pdev->full_frames; pdev->full_frames = pdev->full_frames->next; pdev->read_frame->next = NULL; } if (pdev->read_frame != NULL) { #if PWC_DEBUG Trace(TRACE_SEQUENCE, "Decompressing frame %d\n", pdev>read_frame->sequence); #endif /* Decompression is a lenghty process, so it's outside of the lock. 28 USB 2.0 Mikael Backlund Wearable Computer HT 2003 29 This gives the isoc_handler the opportunity to fill more frames in the mean time. */ spin_unlock_irqrestore(&pdev->ptrlock, flags); ret = pwc_decompress(pdev); spin_lock_irqsave(&pdev->ptrlock, flags); /* We're done with read_buffer, tack it to the end of the empty buffer list */ if (pdev->empty_frames == NULL) { pdev->empty_frames = pdev->read_frame; pdev->empty_frames_tail = pdev->empty_frames; } else { pdev->empty_frames_tail->next = pdev->read_frame; pdev->empty_frames_tail = pdev->read_frame; } pdev->read_frame = NULL; } } spin_unlock_irqrestore(&pdev->ptrlock, flags); return ret; } /** \brief Advance pointers of image buffer (after each user request) */ static inline void pwc_next_image(struct pwc_device *pdev) { pdev->image_used[pdev->fill_image] = 0; pdev->fill_image = (pdev->fill_image + 1) % default_mbufs; } /* This gets called for the Isochronous pipe (video). This is done in * interrupt time, so it has to be fast, not crash, and not stall. Neat. */ static void pwc_isoc_handler(struct urb *urb) { struct pwc_device *pdev; int i, fst, flen; int awake; struct pwc_frame_buf *fbuf; unsigned char *fillptr = 0, *iso_buf = 0; awake = 0; pdev = (struct pwc_device *)urb->context; if (pdev == NULL) { Err("isoc_handler() called with NULL device?!\n"); return; } #ifdef PWC_MAGIC if (pdev->magic != PWC_MAGIC) { Err("isoc_handler() called with bad magic!\n"); return; } #endif if (urb->status == -ENOENT || urb->status == -ECONNRESET) { Trace(TRACE_OPEN, "pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a"); return; } if (urb->status != -EINPROGRESS && urb->status != 0) { const char *errmsg; errmsg = "Unknown"; switch(urb->status) { case -ENOSR: errmsg = "Buffer error (overrun)"; break; 29 USB 2.0 Mikael Backlund Wearable Computer HT 2003 30 case -EPIPE: errmsg = "Stalled (device not case -EOVERFLOW: case -EPROTO: errmsg = "Babble (bad cable?)"; break; errmsg = "Bit-stuff error (bad cable?)"; case -EILSEQ: errmsg = "CRC/Timeout (could be case -ETIMEDOUT: errmsg = "NAK (device does not respond)"; responding)"; break; break; anything)"; break; break; } Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg); /* Give up after a number of contiguous errors on the USB bus. Appearantly something is wrong so we simulate an unplug event. */ if (++pdev->visoc_errors > MAX_ISOC_ERRORS) { Info("Too many ISOC errors, bailing out.\n"); pdev->error_status = EIO; awake = 1; } else return; // better luck next time } fbuf = pdev->fill_frame; if (fbuf == NULL) { Err("pwc_isoc_handler without valid fill frame.\n"); awake = 1; } else { fillptr = fbuf->data + fbuf->filled; } /* Premature wakeup */ if (awake) { wake_up_interruptible(&pdev->frameq); return; } /* Reset ISOC error counter. We did get here, after all. */ pdev->visoc_errors = 0; /* vsync: 0 = don't copy data 1 = sync-hunt 2 = synched */ /* Compact data */ for (i = 0; i < urb->number_of_packets; i++) { fst = urb->iso_frame_desc[i].status; flen = urb->iso_frame_desc[i].actual_length; iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset; if (fst == 0) { if (flen > 0) { /* if valid data... */ if (pdev->vsync > 0) { /* ...and we are not synchunting... */ pdev->vsync = 2; /* ...copy data to frame buffer, if possible */ if (flen + fbuf->filled > pdev->frame_size) { Trace(TRACE_FLOW, "Frame buffer overflow (flen = %d, frame_size = %d).\n", flen, pdev->frame_size); pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */ pdev->vframes_error++; } else { memmove(fillptr, iso_buf, flen); fillptr += flen; } } fbuf->filled += flen; 30 USB 2.0 Mikael Backlund Wearable Computer HT 2003 31 } /* ..flen > 0 */ if (flen < pdev->vlast_packet_size) { /* Shorter packet... We probably have the end of an image-frame; wake up read() process and let select()/poll() do something. Decompression is done in user time over there. */ if (pdev->vsync == 2) { /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus frames on the USB wire after an exposure change. This conditition is however detected in the cam and a bit is set in the header. */ if (pdev->type == 730) { unsigned char *ptr = (unsigned char *)fbuf->data; if (ptr[1] == 1 && ptr[0] & 0x10) { #if PWC_DEBUG Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence); #endif pdev->drop_frames += 2; pdev->vframes_error++; } if ((ptr[0] ^ pdev->vmirror) & 0x01) { if (ptr[0] & 0x01) Info("Snapshot button pressed.\n"); else Info("Snapshot button released.\n"); } if ((ptr[0] ^ pdev->vmirror) & 0x02) { if (ptr[0] & 0x02) Info("Image is mirrored.\n"); else Info("Image is normal.\n"); } pdev->vmirror = ptr[0] & 0x03; /* Sometimes the trailer of the 730 is still sent as a 4 byte packet after a short frame; this condition is filtered out specifically. A 4 byte frame doesn't make sense anyway. So we get either this sequence: drop_bit set -> 4 byte frame -> short frame -> good frame Or this one: drop_bit set -> short frame -> good frame So we drop either 3 or 2 frames in all! */ if (fbuf->filled == 4) pdev->drop_frames++; } /* In case we were instructed to drop the frame, do so silently. The buffer pointers are not updated either (but the counters are reset below). */ if (pdev->drop_frames > 0) pdev->drop_frames--; 31 USB 2.0 Mikael Backlund Wearable Computer HT 2003 32 else { /* Check for underflow first */ if (fbuf->filled < pdev->frame_size) { Trace(TRACE_FLOW, "Frame buffer underflow (%d bytes); discarded.\n", fbuf->filled); pdev->vframes_error++; } else { /* Send only once per EOF */ awake = 1; /* delay wake_ups */ /* Find our next frame to fill. This will always succeed, since we * nick a frame from either empty or full list, but if we had to * take it from the full list, it means a frame got dropped. */ if (pwc_next_fill_frame(pdev)) { pdev->vframes_dumped++; if ((pdev->vframe_count > FRAME_LOWMARK) && (pwc_trace & TRACE_FLOW)) { if (pdev>vframes_dumped < 20) Trace(TRACE_FLOW, "Dumping frame %d.\n", pdev->vframe_count); if (pdev>vframes_dumped == 20) Trace(TRACE_FLOW, "Dumping frame %d (last message).\n", pdev->vframe_count); } } fbuf = pdev->fill_frame; } } /* !drop_frames */ pdev->vframe_count++; } fbuf->filled = 0; fillptr = fbuf->data; pdev->vsync = 1; } /* .. flen < last_packet_size */ pdev->vlast_packet_size = flen; } /* ..status == 0 */ #if PWC_DEBUG /* This is normally not interesting to the user, unless you are really debugging something */ else { static int iso_error = 0; iso_error++; if (iso_error < 20) Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst); } #endif } if (awake) wake_up_interruptible(&pdev->frameq); } static int pwc_isoc_init(struct pwc_device *pdev) { struct usb_device *udev; struct urb *urb; int i, j, ret; struct usb_interface_descriptor *idesc; if (pdev == NULL) return -EFAULT; if (pdev->iso_init) 32 USB 2.0 Mikael Backlund Wearable Computer HT 2003 33 return 0; pdev->vsync = 0; udev = pdev->udev; /* Get the current alternate interface, adjust packet size */ if (!udev->actconfig) return -EFAULT; idesc = &udev->actconfig->interface[0].altsetting[pdev->valternate]; if (!idesc) return -EFAULT; /* Search video endpoint */ pdev->vmax_packet_size = -1; for (i = 0; i < idesc->bNumEndpoints; i++) if ((idesc->endpoint[i].bEndpointAddress & 0xF) == pdev->vendpoint) { pdev->vmax_packet_size = idesc->endpoint[i].wMaxPacketSize; break; } if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) { Err("Failed to find packet size for video endpoint in current alternate setting.\n"); return -ENFILE; /* Odd error, that should be noticable */ } /* Set alternate interface */ ret = 0; Trace(TRACE_OPEN, "Setting alternate interface %d\n", pdev->valternate); ret = usb_set_interface(pdev->udev, 0, pdev->valternate); if (ret < 0) return ret; for (i = 0; i < MAX_ISO_BUFS; i++) { urb = usb_alloc_urb(ISO_FRAMES_PER_DESC); if (urb == NULL) { Err("Failed to allocate urb %d\n", i); ret = -ENOMEM; break; } pdev->sbuf[i].urb = urb; Trace(TRACE_MEMORY, "Allocated URB at 0x%p\n", urb); } if (ret) { /* De-allocate in reverse order */ while (i >= 0) { if (pdev->sbuf[i].urb != NULL) usb_free_urb(pdev->sbuf[i].urb); pdev->sbuf[i].urb = NULL; i--; } return ret; } /* init URB structure */ for (i = 0; i < MAX_ISO_BUFS; i++) { urb = pdev->sbuf[i].urb; urb->next = pdev->sbuf[(i + 1) % MAX_ISO_BUFS].urb; urb->dev = udev; urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint); urb->transfer_flags = USB_ISO_ASAP; urb->transfer_buffer = pdev->sbuf[i].data; urb->transfer_buffer_length = ISO_BUFFER_SIZE; urb->complete = pwc_isoc_handler; urb->context = pdev; urb->start_frame = 0; urb->number_of_packets = ISO_FRAMES_PER_DESC; for (j = 0; j < ISO_FRAMES_PER_DESC; j++) { urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE; urb->iso_frame_desc[j].length = pdev->vmax_packet_size; 33 USB 2.0 Mikael Backlund Wearable Computer HT 2003 34 } } /* link */ for (i = 0; i < MAX_ISO_BUFS; i++) { ret = usb_submit_urb(pdev->sbuf[i].urb); if (ret) Err("isoc_init() submit_urb %d failed with error %d\n", i, ret); else Trace(TRACE_OPEN, "URB 0x%p submitted.\n", pdev->sbuf[i].urb); } /* All is done... */ pdev->iso_init = 1; Trace(TRACE_OPEN, "<< pwc_isoc_init()\n"); return 0; } static void pwc_isoc_cleanup(struct pwc_device *pdev) { int i; Trace(TRACE_OPEN, ">> pwc_isoc_cleanup()\n"); if (pdev == NULL) return; /* Unlinking ISOC buffers one by one */ for (i = 0; i < MAX_ISO_BUFS; i++) { struct urb *urb; urb = pdev->sbuf[i].urb; if (urb != 0) { if (pdev->iso_init) { Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb); usb_unlink_urb(urb); } Trace(TRACE_MEMORY, "Freeing URB\n"); usb_free_urb(urb); pdev->sbuf[i].urb = NULL; } } /* Stop camera, but only if we are sure the camera is still there (unplug is signalled by EPIPE) */ if (pdev->error_status && pdev->error_status != EPIPE) { Trace(TRACE_OPEN, "Setting alternate interface 0.\n"); usb_set_interface(pdev->udev, 0, 0); } pdev->iso_init = 0; Trace(TRACE_OPEN, "<< pwc_isoc_cleanup()\n"); } int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot) { int ret, start; /* Stop isoc stuff */ pwc_isoc_cleanup(pdev); /* Reset parameters */ pwc_reset_buffers(pdev); /* Try to set video mode... */ start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot); if (ret) { Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n"); /* That failed... restore old mode (we know that worked) */ 34 USB 2.0 Mikael Backlund Wearable Computer HT 2003 35 start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev>vframes, pdev->vcompression, pdev->vsnapshot); if (start) { Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n"); } } if (start == 0) { if (pwc_isoc_init(pdev) < 0) { Info("Failed to restart ISOC transfers in pwc_try_video_mode.\n"); ret = -EAGAIN; /* let's try again, who knows if it works a second time */ } } pdev->drop_frames++; /* try to avoid garbage during switch */ return ret; /* Return original error code */ } /***************************************************************************/ /* Video4Linux functions */ static int pwc_video_open(struct video_device *vdev, int mode) { int i; struct pwc_device *pdev; Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev); if (vdev == NULL) BUG(); pdev = (struct pwc_device *)vdev->priv; if (pdev == NULL) BUG(); if (pdev->vopen) return -EBUSY; down(&pdev->modlock); if (!pdev->usb_init) { Trace(TRACE_OPEN, "Doing first time initialization.\n"); pdev->usb_init = 1; { /* Query sensor type */ const char *sensor_type = NULL; i = pwc_get_cmos_sensor(pdev); switch(i) { case -1: /* Unknown, show nothing */; break; case 0x00: sensor_type = "Hyundai CMOS sensor"; break; case 0x20: sensor_type = "Sony CCD sensor + TDA8787"; break; case 0x2E: sensor_type = "Sony CCD sensor + Exas 98L59"; break; case 0x2F: case 0x30: case 0x3E: sensor_type = "Sony CCD sensor + ADI 9804"; break; sensor_type = "Sharp CCD sensor + TDA8787"; break; sensor_type = "Sharp CCD sensor + Exas 98L59"; break; case 0x3F: sensor_type = "Sharp CCD sensor + ADI 9804"; break; case 0x40: sensor_type = "UPA 1021 sensor"; break; case 0x100: sensor_type = "VGA sensor"; break; case 0x101: sensor_type = "PAL MR sensor"; break; default: sensor_type = "unknown type of sensor"; break; } if (sensor_type != NULL) Info("This %s camera is equipped with a %s (%d).\n", pdev->vdev.name, sensor_type, i); } } 35 USB 2.0 Mikael Backlund Wearable Computer HT 2003 36 /* Turn on camera */ if (power_save) { i = pwc_camera_power(pdev, 1); if (i < 0) Info("Failed to restore power to the camera! (%d)\n", i); } /* Set LED on/off time */ if (pwc_set_leds(pdev, led_on, led_off) < 0) Info("Failed to set LED on/off time.\n"); /* Find our decompressor, if any */ pdev->decompressor = pwc_find_decompressor(pdev->type); #if PWC_DEBUG Debug("Found decompressor for %d at 0x%p\n", pdev->type, pdev->decompressor); #endif pwc_construct(pdev); /* set min/max sizes correct */ /* So far, so good. Allocate memory. */ i = pwc_allocate_buffers(pdev); if (i < 0) { Trace(TRACE_OPEN, "Failed to allocate buffer memory.\n"); up(&pdev->modlock); return i; } /* Reset buffers & parameters */ pwc_reset_buffers(pdev); for (i = 0; i < default_mbufs; i++) pdev->image_used[i] = 0; pdev->vframe_count = 0; pdev->vframes_dumped = 0; pdev->vframes_error = 0; pdev->visoc_errors = 0; pdev->error_status = 0; #if PWC_DEBUG pdev->sequence = 0; #endif /* Set some defaults */ pdev->vsnapshot = 0; /* Start iso pipe for video; first try the last used video size (or the default one); if that fails try QCIF/10 or QSIF/10; it that fails too, give up. */ i = pwc_set_video_mode(pdev, pwc_image_sizes[pdev->vsize].x, pwc_image_sizes[pdev->vsize].y, pdev->vframes, pdev->vcompression, 0); if (i) { Trace(TRACE_OPEN, "First attempt at set_video_mode failed.\n"); if (pdev->type == 730 || pdev->type == 740 || pdev->type == 750) i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QSIF].x, pwc_image_sizes[PSZ_QSIF].y, 10, pdev->vcompression, 0); else i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QCIF].x, pwc_image_sizes[PSZ_QCIF].y, 10, pdev->vcompression, 0); } if (i) { Trace(TRACE_OPEN, "Second attempt at set_video_mode failed.\n"); up(&pdev->modlock); return i; } i = pwc_isoc_init(pdev); if (i) { Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i); up(&pdev->modlock); return i; } pdev->vopen++; /* lock decompressor; this has a small race condition, since we 36 USB 2.0 Mikael Backlund Wearable Computer HT 2003 37 could in theory unload pwcx.o between pwc_find_decompressor() above and this call. I doubt it's ever going to be a problem. */ if (pdev->decompressor != NULL) pdev->decompressor->lock(); up(&pdev->modlock); Trace(TRACE_OPEN, "<< video_open() returns 0.\n"); return 0; } /* Note that all cleanup is done in the reverse order as in _open */ static void pwc_video_close(struct video_device *vdev) { struct pwc_device *pdev; int i; Trace(TRACE_OPEN, ">> video_close called(vdev = 0x%p).\n", vdev); pdev = (struct pwc_device *)vdev->priv; if (pdev->vopen == 0) Info("video_close() called on closed device?\n"); /* Dump statistics, but only if a reasonable amount of frames were processed (to prevent endless log-entries in case of snap-shot programs) */ if (pdev->vframe_count > 20) Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev>vframes_error); if (pdev->decompressor != NULL) { pdev->decompressor->exit(); pdev->decompressor->unlock(); pdev->decompressor = NULL; } pwc_isoc_cleanup(pdev); pwc_free_buffers(pdev); /* Turn off LEDS and power down camera, but only when not unplugged */ if (pdev->error_status != EPIPE) { if (pwc_set_leds(pdev, 0, 0) < 0) Info("Failed to set LED on/off time.\n"); if (power_save) { i = pwc_camera_power(pdev, 0); if (i < 0) Err("Failed to power down camera (%d)\n", i); } } pdev->vopen = 0; Trace(TRACE_OPEN, "<< video_close()\n"); } /* * * FIXME: what about two parallel reads ???? ANSWER: Not supported. You can't open the device more than once, despite what the V4L1 interface says. First, I don't see the need, second there's no mechanism of alerting the 2nd/3rd/... process of events like changing image size. And I don't see the point of blocking that for the 2nd/3rd/... process. In multi-threaded environments reading parallel from any device is tricky anyhow. */ static long pwc_video_read(struct video_device *vdev, char *buf, unsigned long count, int noblock) { struct pwc_device *pdev; DECLARE_WAITQUEUE(wait, current); 37 USB 2.0 Mikael Backlund Wearable Computer HT 2003 38 Trace(TRACE_READ, "video_read(0x%p, %p, %ld, %d) called.\n", vdev, buf, count, noblock); if (vdev == NULL) return -EFAULT; pdev = vdev->priv; if (pdev == NULL) return -EFAULT; if (pdev->error_status) return -pdev->error_status; /* Something happened, report what. */ /* In case we're doing partial reads, we don't have to wait for a frame */ if (pdev->image_read_pos == 0) { /* Do wait queueing according to the (doc)book */ add_wait_queue(&pdev->frameq, &wait); while (pdev->full_frames == NULL) { /* Check for unplugged/etc. here */ if (pdev->error_status) { remove_wait_queue(&pdev->frameq, &wait); set_current_state(TASK_RUNNING); return -pdev->error_status ; } if (noblock) { remove_wait_queue(&pdev->frameq, &wait); set_current_state(TASK_RUNNING); return -EWOULDBLOCK; } if (signal_pending(current)) { remove_wait_queue(&pdev->frameq, &wait); set_current_state(TASK_RUNNING); return -ERESTARTSYS; } schedule(); set_current_state(TASK_INTERRUPTIBLE); } remove_wait_queue(&pdev->frameq, &wait); set_current_state(TASK_RUNNING); /* Decompress and release frame */ if (pwc_handle_frame(pdev)) return -EFAULT; } Trace(TRACE_READ, "Copying data to user space.\n"); /* copy bytes to user space; we allow for partial reads */ if (count + pdev->image_read_pos > pdev->view.size) count = pdev->view.size - pdev->image_read_pos; if (copy_to_user(buf, pdev->image_ptr[pdev->fill_image] + pdev>image_read_pos, count)) return -EFAULT; pdev->image_read_pos += count; if (pdev->image_read_pos >= pdev->view.size) { /* All data has been read */ pdev->image_read_pos = 0; pwc_next_image(pdev); } return count; } static long pwc_video_write(struct video_device *vdev, const char *buf, unsigned long count, int noblock) { return -EINVAL; } static unsigned int pwc_video_poll(struct video_device *vdev, struct file *file, poll_table *wait) { struct pwc_device *pdev; if (vdev == NULL) 38 USB 2.0 Mikael Backlund Wearable Computer HT 2003 39 return -EFAULT; pdev = vdev->priv; if (pdev == NULL) return -EFAULT; poll_wait(file, &pdev->frameq, wait); if (pdev->error_status) return POLLERR; if (pdev->full_frames != NULL) /* we have frames waiting */ return (POLLIN | POLLRDNORM); return 0; } static int pwc_video_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) { struct pwc_device *pdev; DECLARE_WAITQUEUE(wait, current); if (vdev == NULL) return -EFAULT; pdev = vdev->priv; if (pdev == NULL) return -EFAULT; switch (cmd) { /* Query cabapilities */ case VIDIOCGCAP: { struct video_capability caps; strcpy(caps.name, vdev->name); caps.type = VID_TYPE_CAPTURE; caps.channels = 1; caps.audios = 1; caps.minwidth = pdev->view_min.x; caps.minheight = pdev->view_min.y; caps.maxwidth = pdev->view_max.x; caps.maxheight = pdev->view_max.y; if (copy_to_user(arg, &caps, sizeof(caps))) return -EFAULT; break; } /* Channel functions (simulate 1 channel) */ case VIDIOCGCHAN: { struct video_channel v; if (copy_from_user(&v, arg, sizeof(v))) return -EFAULT; if (v.channel != 0) return -EINVAL; v.flags = 0; v.tuners = 0; v.type = VIDEO_TYPE_CAMERA; strcpy(v.name, "Webcam"); if (copy_to_user(arg, &v, sizeof(v))) return -EFAULT; return 0; } case VIDIOCSCHAN: { /* The spec says the argument is an integer, but the bttv driver uses a video_channel arg, which makes sense becasue it also has the norm flag. */ 39 USB 2.0 Mikael Backlund Wearable Computer HT 2003 40 struct video_channel v; if (copy_from_user(&v, arg, sizeof(v))) return -EFAULT; if (v.channel != 0) return -EINVAL; return 0; } /* Picture functions; contrast etc. */ case VIDIOCGPICT: { struct video_picture p; int val; p.colour = 0x8000; p.hue = 0x8000; val = pwc_get_brightness(pdev); if (val >= 0) p.brightness = val; else p.brightness = 0xffff; val = pwc_get_contrast(pdev); if (val >= 0) p.contrast = val; else p.contrast = 0xffff; /* Gamma, Whiteness, what's the difference? :) */ val = pwc_get_gamma(pdev); if (val >= 0) p.whiteness = val; else p.whiteness = 0xffff; val = pwc_get_saturation(pdev); if (val >= 0) p.colour = val; else p.colour = 0xffff; p.depth = 24; p.palette = VIDEO_PALETTE_YUV420P; p.hue = 0xFFFF; /* N/A */ if (copy_to_user(arg, &p, sizeof(p))) return -EFAULT; break; } case VIDIOCSPICT: { struct video_picture p; if (copy_from_user(&p, arg, sizeof(p))) return -EFAULT; /* * FIXME: Suppose we are mid read ANSWER: No problem: the firmware of the camera can handle brightness/contrast/etc changes at _any_ time, and the palette is used exactly once in the uncompress routine. */ pwc_set_brightness(pdev, p.brightness); pwc_set_contrast(pdev, p.contrast); pwc_set_gamma(pdev, p.whiteness); pwc_set_saturation(pdev, p.colour); if (p.palette && p.palette != VIDEO_PALETTE_YUV420P) { return -EINVAL; 40 USB 2.0 Mikael Backlund Wearable Computer HT 2003 41 } break; } /* Window/size parameters */ case VIDIOCGWIN: { struct video_window vw; vw.x = 0; vw.y = 0; vw.width = pdev->view.x; vw.height = pdev->view.y; vw.chromakey = 0; vw.flags = (pdev->vframes << PWC_FPS_SHIFT) | (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0); if (copy_to_user(arg, &vw, sizeof(vw))) return -EFAULT; break; } case VIDIOCSWIN: { struct video_window vw; int fps, snapshot, ret; if (copy_from_user(&vw, arg, sizeof(vw))) return -EFAULT; fps = (vw.flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT; snapshot = vw.flags & PWC_FPS_SNAPSHOT; if (fps == 0) fps = pdev->vframes; if (pdev->view.x == vw.width && pdev->view.y && fps == pdev>vframes && snapshot == pdev->vsnapshot) return 0; ret = pwc_try_video_mode(pdev, vw.width, vw.height, fps, pdev>vcompression, snapshot); if (ret) return ret; break; } /* We don't have overlay support (yet) */ case VIDIOCGFBUF: { struct video_buffer vb; vb.base = NULL; vb.height = 0; vb.width = 0; vb.depth = 0; vb.bytesperline = 0; if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb))) return -EFAULT; break; } /* mmap() functions */ case VIDIOCGMBUF: { /* Tell the user program how much memory is needed for a mmap() */ struct video_mbuf vm; int i; memset(&vm, 0, sizeof(vm)); vm.size = default_mbufs * pdev->len_per_image; 41 USB 2.0 Mikael Backlund Wearable Computer HT 2003 42 vm.frames = default_mbufs; /* double buffering should be enough for most applications */ for (i = 0; i < default_mbufs; i++) vm.offsets[i] = i * pdev->len_per_image; if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm))) return -EFAULT; break; } case VIDIOCMCAPTURE: { /* Start capture into a given image buffer (called 'frame' in video_mmap structure) */ struct video_mmap vm; if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm))) return -EFAULT; Trace(TRACE_READ, "VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm.width, vm.height, vm.frame, vm.format); if (vm.frame < 0 || vm.frame >= default_mbufs) return -EINVAL; /* xawtv is nasty. It probes the available palettes by setting a very small image size and trying various palettes... The driver doesn't support such small images, so I'm working around it. */ if (vm.format && vm.format != VIDEO_PALETTE_YUV420P) return -EINVAL; if ((vm.width != pdev->view.x || vm.height != pdev->view.y) && (vm.width >= pdev->view_min.x && vm.height >= pdev>view_min.y)) { int ret; Trace(TRACE_OPEN, "VIDIOCMCAPTURE: changing size to please xawtv :-(.\n"); ret = pwc_try_video_mode(pdev, vm.width, vm.height, pdev->vframes, pdev->vcompression, pdev->vsnapshot); if (ret) return ret; } /* ... size mismatch */ /* FIXME: should we lock here? */ if (pdev->image_used[vm.frame]) return -EBUSY; /* buffer wasn't available. Bummer */ pdev->image_used[vm.frame] = 1; /* Okay, we're done here. In the SYNC call we wait until a frame comes available, then expand image into the given buffer. In contrast to the CPiA cam the Philips cams deliver a constant stream, almost like a grabber card. Also, we have separate buffers for the rawdata and the image, meaning we can nearly always expand into the requested buffer. */ Trace(TRACE_READ, "VIDIOCMCAPTURE done.\n"); break; } case VIDIOCSYNC: { /* The doc says: "Whenever a buffer is used it should call VIDIOCSYNC to free this frame up and continue." The only odd thing about this whole procedure is that MCAPTURE flags the buffer as "in use", and SYNC immediately unmarks it, while it isn't after SYNC that you know that the buffer actually 42 USB 2.0 Mikael Backlund Wearable Computer HT 2003 43 got filled! So you better not start a CAPTURE in the same frame immediately (use double buffering). This is not a problem for this cam, since it has extra intermediate buffers, but a hardware grabber card will then overwrite the buffer you're working on. */ int mbuf, ret; if (copy_from_user((void *)&mbuf, arg, sizeof(int))) return -EFAULT; Trace(TRACE_READ, "VIDIOCSYNC called (%d).\n", mbuf); /* bounds check */ if (mbuf < 0 || mbuf >= default_mbufs) return -EINVAL; /* check if this buffer was requested anyway */ if (pdev->image_used[mbuf] == 0) return -EINVAL; /* Add ourselves to the frame wait-queue. In the loop, check for error conditions and signals. FIXME: needs auditing for safety. QUESTION: In what respect? I think that using the frameq is safe now. */ add_wait_queue(&pdev->frameq, &wait); while (pdev->full_frames == NULL) { if (pdev->error_status) { remove_wait_queue(&pdev->frameq, &wait); set_current_state(TASK_RUNNING); return -pdev->error_status; } if (signal_pending(current)) { remove_wait_queue(&pdev->frameq, &wait); set_current_state(TASK_RUNNING); return -ERESTARTSYS; } schedule(); set_current_state(TASK_INTERRUPTIBLE); } remove_wait_queue(&pdev->frameq, &wait); set_current_state(TASK_RUNNING); /* The frame is ready. Expand in the image buffer requested by the user. I don't care if you mmap() 5 buffers and request data in this order: buffer 4 2 3 0 1 2 3 0 4 3 1 . . . Grabber hardware may not be so forgiving. */ Trace(TRACE_READ, "VIDIOCSYNC: frame ready.\n"); pdev->fill_image = mbuf; /* tell in which buffer we want the image to be expanded */ /* Decompress, etc */ ret = pwc_handle_frame(pdev); pdev->image_used[mbuf] = 0; if (ret) return -EFAULT; break; } case VIDIOCGAUDIO: { struct video_audio v; strcpy(v.name, "Microphone"); v.audio = -1; /* unknown audio minor */ v.flags = 0; v.mode = VIDEO_SOUND_MONO; 43 USB 2.0 Mikael Backlund Wearable Computer HT 2003 44 v.volume = 0; v.bass = 0; v.treble = 0; v.balance = 0x8000; v.step = 1; if (copy_to_user(arg, &v, sizeof(v))) return -EFAULT; break; } case VIDIOCSAUDIO: { struct video_audio v; if (copy_from_user(&v, arg, sizeof(v))) return -EFAULT; /* Dummy: nothing can be set */ break; } case VIDIOCGUNIT: { struct video_unit vu; vu.video = pdev->vdev.minor & 0x3F; vu.audio = -1; /* not known yet */ vu.vbi = -1; vu.radio = -1; vu.teletext = -1; if (copy_to_user(arg, &vu, sizeof(vu))) return -EFAULT; break; } default: return pwc_ioctl(pdev, cmd, arg); } /* ..switch */ return 0; } static int pwc_video_mmap(struct video_device *vdev, const char *adr, unsigned long size) { struct pwc_device *pdev; unsigned long start = (unsigned long)adr; unsigned long page, pos; Trace(TRACE_MEMORY, "mmap(0x%p, 0x%p, %lu) called.\n", vdev, adr, size); pdev = vdev->priv; pos = (unsigned long)pdev->image_data; while (size > 0) { page = kvirt_to_pa(pos); if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) return -EAGAIN; start += PAGE_SIZE; pos += PAGE_SIZE; if (size > PAGE_SIZE) size -= PAGE_SIZE; else size = 0; } return 0; } /***************************************************************************/ /* USB functions */ /* This function gets called when a new device is plugged in or the usb core 44 USB 2.0 Mikael Backlund Wearable Computer HT 2003 45 * is loaded. */ static void *usb_pwc_probe(struct usb_device *udev, unsigned int ifnum, const struct usb_device_id *id) { struct pwc_device *pdev = NULL; int vendor_id, product_id, type_id; int i, hint; int features = 0; int video_nr = -1; /* default: use next available device */ char serial_number[30], *name; /* Check if we can handle this device */ Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", udev>descriptor.idVendor, udev->descriptor.idProduct, ifnum); /* the interfaces are probed one by one. We are only interested in the video interface (0) now. Interface 1 is the Audio Control, and interface 2 Audio itself. */ if (ifnum > 0) return NULL; vendor_id = udev->descriptor.idVendor; product_id = udev->descriptor.idProduct; if (vendor_id == 0x0471) { switch (product_id) { case 0x0302: Info("Philips PCA645VC USB webcam detected.\n"); name = "Philips 645 webcam"; type_id = 645; break; case 0x0303: Info("Philips PCA646VC USB webcam detected.\n"); name = "Philips 646 webcam"; type_id = 646; break; case 0x0304: Info("Askey VC010 type 2 USB webcam detected.\n"); name = "Askey VC010 webcam"; type_id = 646; break; case 0x0307: Info("Philips PCVC675K (Vesta) USB webcam detected.\n"); name = "Philips 675 webcam"; type_id = 675; break; case 0x0308: Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n"); name = "Philips 680 webcam"; type_id = 680; break; case 0x030C: Info("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n"); name = "Philips 690 webcam"; type_id = 690; break; case 0x0310: Info("Philips PCVC730K (ToUCam Fun) USB webcam detected.\n"); name = "Philips 730 webcam"; type_id = 730; break; case 0x0311: Info("Philips PCVC740K (ToUCam Pro) USB webcam detected.\n"); name = "Philips 740 webcam"; type_id = 740; break; case 0x0312: 45 USB 2.0 Mikael Backlund Wearable Computer HT 2003 46 Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n"); name = "Philips 750 webcam"; type_id = 750; break; case 0x0313: Info("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n"); name = "Philips 720 webcam"; type_id = 720; break; default: return NULL; break; } } else if (vendor_id == 0x069A) { switch(product_id) { case 0x0001: Info("Askey VC010 type 1 USB webcam detected.\n"); name = "Askey VC010 webcam"; type_id = 645; break; default: return NULL; break; } } else if (vendor_id == 0x046d) { switch(product_id) { case 0x08b0: Info("Logitech QuickCam Pro 3000 USB webcam detected.\n"); name = "Logitech QuickCam Pro 3000"; type_id = 740; /* CCD sensor */ break; case 0x08b1: Info("Logitech QuickCam for Notebook Pro USB webcam detected.\n"); name = "Logitech QuickCam Notebook Pro"; type_id = 740; /* CCD sensor */ break; case 0x08b2: Info("Logitech QuickCam 4000 Pro USB webcam detected.\n"); name = "Logitech QuickCam Pro 4000"; type_id = 740; /* CCD sensor */ break; case 0x08b3: Info("Logitech QuickCam Zoom USB webcam detected.\n"); name = "Logitech QuickCam Zoom"; type_id = 740; /* CCD sensor */ break; case 0x08B4: Info("Logitech QuickCam Zoom (new model) USB webcam detected.\n"); name = "Logitech QuickCam Zoom"; type_id = 740; /* CCD sensor */ break; case 0x08b5: Info("Logitech QuickCam Orbit/Sphere USB webcam detected.\n"); name = "Logitech QuickCam Orbit"; type_id = 740; /* CCD sensor */ features |= FEATURE_MOTOR_PANTILT; break; case 0x08b6: case 0x08b7: case 0x08b8: Info("Logitech QuickCam detected (reserved ID).\n"); name = "Logitech QuickCam (res.)"; type_id = 730; /* Assuming CMOS */ break; default: return NULL; 46 USB 2.0 Mikael Backlund Wearable Computer HT 2003 47 break; } } else if (vendor_id == 0x055d) { /* I don't know the difference between the C10 and the C30; I suppose the difference is the sensor, but both cameras work equally well with a type_id of 675 */ switch(product_id) { case 0x9000: Info("Samsung MPC-C10 USB webcam detected.\n"); name = "Samsung MPC-C10"; type_id = 730; break; case 0x9001: Info("Samsung MPC-C30 USB webcam detected.\n"); name = "Samsung MPC-C30"; type_id = 740; break; default: return NULL; break; } } else if (vendor_id == 0x041e) { switch(product_id) { case 0x400c: Info("Creative Labs Webcam 5 detected.\n"); name = "Creative Labs Webcam 5"; type_id = 730; break; case 0x4011: Info("Creative Labs Webcam Pro Ex detected.\n"); name = "Creative Labs Webcam Pro Ex"; type_id = 740; break; default: return NULL; break; } } else if (vendor_id == 0x04cc) { switch(product_id) { case 0x8116: Info("Sotec Afina Eye USB webcam detected.\n"); name = "Sotec Afina Eye"; type_id = 730; break; default: return NULL; break; } } else if (vendor_id == 0x0d81) { switch(product_id) { case 0x1900: Info("Visionite VCS-UC300 USB webcam detected.\n"); name = "Visionite VCS-UC300"; type_id = 740; /* CCD sensor */ break; case 0x1910: Info("Visionite VCS-UM100 USB webcam detected.\n"); name = "Visionite VCS-UM100"; type_id = 730; /* CMOS sensor */ break; default: return NULL; break; } } else 47 USB 2.0 Mikael Backlund Wearable Computer HT 2003 48 return NULL; /* Not any of the know types; but the list keeps growing. */ memset(serial_number, 0, 30); usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29); Trace(TRACE_PROBE, "Device serial number is %s\n", serial_number); if (udev->descriptor.bNumConfigurations > 1) Info("Warning: more than 1 configuration available.\n"); /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */ pdev = kmalloc(sizeof(struct pwc_device), GFP_KERNEL); if (pdev == NULL) { Err("Oops, could not allocate memory for pwc_device.\n"); return NULL; } memset(pdev, 0, sizeof(struct pwc_device)); pdev->type = type_id; pdev->vsize = default_size; pdev->vframes = default_fps; pdev->features = features; if (vendor_id == 0x046D && product_id == 0x08B5) { /* Logitech QuickCam Orbit The ranges have been determined experimentally; they may differ from cam to cam. Also, the exact ranges left-right and up-down are different for my cam */ pdev->angle_range.pan_min = -7000; pdev->angle_range.pan_max = 7000; pdev->angle_range.tilt_min = -3000; pdev->angle_range.tilt_max = 2500; pdev->angle_range.zoom_min = -1; pdev->angle_range.zoom_max = -1; } init_MUTEX(&pdev->modlock); pdev->ptrlock = SPIN_LOCK_UNLOCKED; pdev->udev = udev; init_waitqueue_head(&pdev->frameq); pdev->vcompression = pwc_preferred_compression; memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template)); strcpy(pdev->vdev.name, name); SET_MODULE_OWNER(&pdev->vdev); pdev->vdev.priv = pdev; pdev->release = udev->descriptor.bcdDevice; Trace(TRACE_PROBE, "Release: %04x\n", pdev->release); /* Now search device_hint[] table for a match, so we can hint a node number. */ for (hint = 0; hint < MAX_DEV_HINTS; hint++) { if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev>type)) && (device_hint[hint].pdev == NULL)) { /* so far, so good... try serial number */ if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) { /* match! */ video_nr = device_hint[hint].device_node; Trace(TRACE_PROBE, "Found hint, will try to register as /dev/video%d\n", video_nr); break; } } } 48 USB 2.0 Mikael Backlund Wearable Computer HT 2003 49 i = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr); if (i < 0) { Err("Failed to register as video device (%d).\n", i); kfree(pdev); /* Oops, no memory leaks please */ return NULL; } else { Info("Registered as /dev/video%d.\n", pdev->vdev.minor & 0x3F); } /* occupy slot */ if (hint < MAX_DEV_HINTS) device_hint[hint].pdev = pdev; Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev); return pdev; } /* The user janked out the cable... */ static void usb_pwc_disconnect(struct usb_device *udev, void *ptr) { struct pwc_device *pdev; int hint; lock_kernel(); pdev = (struct pwc_device *)ptr; if (pdev == NULL) { Err("pwc_disconnect() Called without private pointer.\n"); unlock_kernel(); return; } if (pdev->udev == NULL) { Err("pwc_disconnect() already called for %p\n", pdev); unlock_kernel(); return; } if (pdev->udev != udev) { Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n"); unlock_kernel(); return; } #ifdef PWC_MAGIC if (pdev->magic != PWC_MAGIC) { Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n"); unlock_kernel(); return; } #endif /* We got unplugged; this is signalled by an EPIPE error code */ if (pdev->vopen) { Info("Disconnected while webcam is in use!\n"); pdev->error_status = EPIPE; } /* Alert waiting processes */ wake_up_interruptible(&pdev->frameq); /* Wait until device is closed */ while (pdev->vopen) schedule(); /* Device is now closed, so we can safely unregister it */ Trace(TRACE_PROBE, "Unregistering video device in disconnect().\n"); video_unregister_device(&pdev->vdev); /* Free memory (don't set pdev to 0 just yet) */ kfree(pdev); /* search device_hint[] table if we occupy a slot, by any chance */ for (hint = 0; hint < MAX_DEV_HINTS; hint++) if (device_hint[hint].pdev == pdev) device_hint[hint].pdev = NULL; 49 USB 2.0 Mikael Backlund Wearable Computer HT 2003 50 unlock_kernel(); } /* *grunt* We have to do atoi ourselves :-( */ static int pwc_atoi(const char *s) { int k = 0; k = 0; while (*s != '\0' && *s >= '0' && *s <= '9') { k = 10 * k + (*s - '0'); s++; } return k; } /* * Initialization code & module stuff */ static static static static static static static static char *size = NULL; int fps = 0; int fbufs = 0; int mbufs = 0; int trace = -1; int compression = -1; int leds[2] = { -1, -1 }; char *dev_hint[MAX_DEV_HINTS] = { }; MODULE_PARM(size, "s"); MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga"); MODULE_PARM(fps, "i"); MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 530"); MODULE_PARM(fbufs, "i"); MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve"); MODULE_PARM(mbufs, "i"); MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers"); MODULE_PARM(trace, "i"); MODULE_PARM_DESC(trace, "For debugging purposes"); MODULE_PARM(power_save, "i"); MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off"); MODULE_PARM(compression, "i"); MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)"); MODULE_PARM(leds, "2i"); MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); MODULE_PARM(dev_hint, "0-20s"); MODULE_PARM_DESC(dev_hint, "Device node hints"); MODULE_DESCRIPTION("Philips USB & OEM webcam driver"); MODULE_AUTHOR("Nemosoft Unv. <nemosoft@smcc.demon.nl>"); MODULE_LICENSE("GPL"); static int __init usb_pwc_init(void) { int i, sz; char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" }; Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740/750 webcam module version " PWC_VERSION " loaded.\n"); Info("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPCC10 and MPC-C30,\n"); Info("the Creative WebCam 5, SOTEC Afina Eye and Visionite VCS-UC300 and VCSUM100.\n"); if (fps) { if (fps < 4 || fps > 30) { 50 USB 2.0 Mikael Backlund Wearable Computer HT 2003 51 Err("Framerate out of bounds (4-30).\n"); return -EINVAL; } default_fps = fps; Info("Default framerate set to %d.\n", default_fps); } if (size) { /* string; try matching with array */ for (sz = 0; sz < PSZ_MAX; sz++) { if (!strcmp(sizenames[sz], size)) { /* Found! */ default_size = sz; break; } } if (sz == PSZ_MAX) { Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n"); return -EINVAL; } Info("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y); } if (mbufs) { if (mbufs < 1 || mbufs > MAX_IMAGES) { Err("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES); return -EINVAL; } default_mbufs = mbufs; Info("Number of image buffers set to %d.\n", default_mbufs); } if (fbufs) { if (fbufs < 2 || fbufs > MAX_FRAMES) { Err("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES); return -EINVAL; } default_fbufs = fbufs; Info("Number of frame buffers set to %d.\n", default_fbufs); } if (trace >= 0) { Info("Trace options: 0x%04x\n", trace); pwc_trace = trace; } if (compression >= 0) { if (compression > 3) { Err("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n"); return -EINVAL; } pwc_preferred_compression = compression; Info("Preferred compression set to %d.\n", pwc_preferred_compression); } if (power_save) Info("Enabling power save on open/close.\n"); if (leds[0] >= 0) led_on = leds[0]; if (leds[1] >= 0) led_off = leds[1]; /* Big device node whoopla. Basicly, it allows you to assign a device node (/dev/videoX) to a camera, based on its type & serial number. The format is [type[.serialnumber]:]node. Any camera that isn't matched by these rules gets the next available free device node. */ for (i = 0; i < MAX_DEV_HINTS; i++) { char *s, *colon, *dot; 51 USB 2.0 Mikael Backlund Wearable Computer HT 2003 52 /* This loop also initializes the array */ device_hint[i].pdev = NULL; s = dev_hint[i]; if (s != NULL && *s != '\0') { device_hint[i].type = -1; /* wildcard */ strcpy(device_hint[i].serial_number, "*"); /* parse string: chop at ':' & '/' */ colon = dot = s; while (*colon != '\0' && *colon != ':') colon++; while (*dot != '\0' && *dot != '.') dot++; /* Few sanity checks */ if (*dot != '\0' && dot > colon) { Err("Malformed camera hint: the colon must be after the dot.\n"); return -EINVAL; } if (*colon == '\0') { /* No colon */ if (*dot != '\0') { Err("Malformed camera hint: no colon + device node given.\n"); return -EINVAL; } else { /* No type or serial number specified, just a number. */ device_hint[i].device_node = pwc_atoi(s); } } else { /* There's a colon, so we have at least a type and a device node */ device_hint[i].type = pwc_atoi(s); device_hint[i].device_node = pwc_atoi(colon + 1); if (*dot != '\0') { /* There's a serial number as well */ int k; dot++; k = 0; while (*dot != ':' && k < 29) { device_hint[i].serial_number[k++] = *dot; dot++; } device_hint[i].serial_number[k] = '\0'; } } #if PWC_DEBUG Debug("device_hint[%d]:\n", i); Debug(" type : %d\n", device_hint[i].type); Debug(" serial# : %s\n", device_hint[i].serial_number); Debug(" node : %d\n", device_hint[i].device_node); #endif } else device_hint[i].type = 0; /* not filled */ } /* ..for MAX_DEV_HINTS */ Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver); return usb_register(&pwc_driver); } static void __exit usb_pwc_exit(void) { Trace(TRACE_MODULE, "Deregistering driver.\n"); usb_deregister(&pwc_driver); 52 USB 2.0 Mikael Backlund Wearable Computer HT 2003 53 Info("Philips webcam module removed.\n"); } module_init(usb_pwc_init); module_exit(usb_pwc_exit); 53