Please help me find errors wich causes that I get incorrect datas from my
device ( from FX2 CY7C68013-128AC )
Below is my device driver ...
/* Linux przypisuje zmiennej HZ wartosc 100. Gdy przerwanie zegarowe
zostanie wyzwolone, wartosc zmiennej
jiffies jest zwiekszana. W ten sposob zmienna jiffies zawiera liczbe taktow
zegara od wlaczenia komputera.*/
#define __KERNEL__
#define MODULE
#define _LOOSE_KERNEL_NAMES
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h> //tu znajduje sie zmienna unsigned long volataile
jiffies - przepelnia sie po 16 miesiacach
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/smp_lock.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/version.h>
#include <linux/usb.h>
#include <asm/uaccess.h>
//Jesli kompilacja zostanie przeprowadzona z opcja -DDEBUG sterownik zacznie
pluc po konsoli tym co sie w nim dzieje.
#ifdef DEBUG
#define __PRINT_DEBUG(a) err(a)
#else
#define __PRINT_DEBUG(a)
#endif
/* Informacje na temat drivera */
#define DRIVER_NAME "Sterownik FX2"
#define DRIVER_VERSION "alpha 0.1"
#define DRIVER_AUTHOR "Norbert Lipinski"
#define DRIVER_DESC "Cypress FX2 CY7C68013-128AC"
//narazie skaner
#define VENDOR 0x04b4
#define PRODUCT 0x8613
/* minor rowny 192 */
#define USB_FX2_MINOR 192
//Ustawienia stałe
int frame_size; //dlugosc pakietu w BULK, ilosc ramek stala = 1
int endpoint_r; //endpoint do odczytu z urzadzenia IN
int endpoint_w; //endpoint do zapisu do urzadzenia OUT
//definicje startowe uzyte w sterowniku
#define LOADED 0
#define PROBED 1 //urzadzenie podlaczone i zenumerowane
#define DISCONNECTED 0 //urzadzenie rozlaczone
#define OPEN 1 // stan otwarcia urzadzenia ( 1 oznacza otwarte)
#define CLOSED 0
#define FALSE 0
#define TRUE 1
//funkcje ioctl
#define IOCTL_SET_TOTAL_TIMEOUT 1 //czas ustalenia odpowiedzi urzadzenia po
odbytej transmisji
#define IOCTL_SET_POLL_INTERVAL 2 //ustawienie odstepu pomiedzy pytaniami o
dostepnosc danych
#define IOCTL_GET_VENDORID 3 //wypisanie vendor urzadzenia
#define IOCTL_GET_PRODUCTID 4 //wypisanie productid urzadzenia
#define IOCTL_IN 5 //proba
#define IOCTL_OUT 6 //proba
//zmienna volatile sa odczytywane za kazdym razem, gdy jakis kod sie do niej
odwoluje
//static nie zasmieca pamieci
volatile static int opened;
volatile static int probed;
static int timeout; //licznik czasu oczekiwania na dane (<0 oznacza ze
zakladany w timeout_total zostal przekroczony)
volatile static int buffersNotAllocated;
static int timeout_total; //zmienna przechowujaca calkowity timeout -
ustawiana moze byc w ioctl
static int poll_interval; //odstep pomiedzy pytaniami o dostepnosc danych
//stale przyjete odgornie zaczerpniete z dokumentacji USB
#define FILE_ERR -86
#define FILE_TO -1
//Struktura do przechowywania wskaznikow na zlecenie URB
struct Request {
purb_t pUrb; //wskaznik na URB, obszar pamieci tworzony przez
usb_alloc_urb()
char *pBuff; //wskaznik na bufor pamieci do ktorego zostana przeslane dane
w wyniku realizacji zlecenia URB
unsigned long nLeft; //informacje o pozostalych danych w buforze
koniecznych do odczytania przez procedure READ
unsigned long nOffset; // wskazanie na poczatek danych w buforze ktore
zostana przedstawione procedurze odczytujacej dane
int nFirstTime; //zmienna kontrolujaca pojedyncze wywolanie czesci kodu
wewnatrz procedury odczytujacej dane
};
/* zdefiniowanie semafora -- blokowanie i odblokowywanie funkcji dla innych
procesow*/
static struct semaphore mutex;
static struct Request sRead; //odczyt danych
static struct Request sWrite; //zapis danych do urzadzenia
/*wskaznik na nasze urzadzenie USB .. struktura usb_device jest zdefiniowana
w pliku usb.h */
static struct usb_device *my_dev;
/* prototypy lokalnych funkcji */
static ssize_t fx2_read(struct file *file, char *buf, size_t count, loff_t
*ppos);
static ssize_t fx2_write(struct file *file, const char *buf, size_t count,
loff_t *ppos);
static int fx2_ioctl(struct inode *inode, struct file *file, unsigned int
cmd, unsigned long arg);
/* sterowanie urządzeniem */
static int fx2_open(struct inode *inode, struct file *file);
/* funkcja wywolywana po otwarciu pliku skojarzonego z urzadzeniem USB
Otwarcie urzadzenia do odczytu lub zapisu powoduje sprawdzenie czy minor
przypisanego urzadzenia sie
zgadza oraz wyzerowanie zmiennych wewnetrznych. Jest to funkcja
rejestrowana w wewnetrznej nieusuwalnej
z jadra strukturze przechowujacej wskazania do wszystkich dozwolonych
operacji na urzadzeniu ...
ZWIEKSZENIE LICZNIKA WYKORZYSTANIA*/
static int fx2_release(struct inode *inode, struct file *file);
/* Po wywolaniu fclose na pliku skojarzonym z urzadzeniem nastepuje
wywolanie poprzez stos USB tej funkcji
Jest to funkcja rejestrowana w wewnetrznej nieusuwalnej z jadra
strukturze przechowujacej wskazania do
wszystkich dozwolonych operacji na urzadzeniu. */
static void * fx2_probe (struct usb_device *dev, unsigned int ifnum, const
struct usb_device_id *id);
/* funkcja działająca tuż po podłączeniu urządzenia .. sprawdzenie vendor i
product id*/
static void fx2_disconnect(struct usb_device *dev, void *ptr);
/* Wewnatrz funkcji zwalniane sa bufory sluzace do transmisji danych.
Zwolnienie nastepuje po odebraniu
ostatniego zlecenia. Zmniejszany jest licznik uzycia modulu */
static void wait_for_urb( purb_t pUrbLoc );
/* Odczekanie az URB sie wypelni danymi lub Timeout */
static void show_error(int errno);
/*wyswietla bledy*/
static int AllocateBuffers();
/*przydziela bufory w kernelu*/
static int FreeBuffers();
/*zwalnia bufory */
/*Ta struktura przechowuje wskazniki do wywolan funckji
open,close,seek itp.*/
static struct file_operations fx2_fops = {
// owner: THIS_MODULE,
read: fx2_read,
write: fx2_write,
ioctl: fx2_ioctl,
open: fx2_open,
release: fx2_release,
};
/* Struktura sluzaca rejestracji sterownika usb w jadrze. Wewnatrz znajduja
sie wskazniki do funkcji
uruchamianych przez podsystem usb po podlaczeniu urzadzenia ( funkcja probe)
oraz po wylaczeniu urzadzenia
(funkcja disconnect)*/
static struct usb_driver fx2_driver = {
name: "Cypress FX2", //nazwa sterownika
probe: fx2_probe, //(wsk) funkcja wywolywana po podlaczeniu urzadzenia
disconnect: fx2_disconnect, //(wsk) funkcja wywolywana po odlaczeniu
urzadzenia
driver_list: {NULL,NULL}, //struktura wewnetrzna podsystemu USB
fops: &fx2_fops, //wskaznik na strukture z dozwolonymi operacjami
minor: USB_FX2_MINOR, //pod tym numerem zostanie utworzony wpis w /dev
};
static void show_error(int errno)
{
//Dolaczona obsluga bledow - zgodnie z dokumentem Programming Guide for
Linux USB Device Drviers
//err wyswietla tekst w nawiasach zgodnie z deklaracja powyzej
__PRINT_DEBUG
switch (errno)
{
case 0:
break; //cool, no error .... yet!
case -ENOENT:
err ("URB was canceled by unlink_urb");
printk("<1>URB was canceled by unlink_urb");
break;
case -EINPROGRESS:
err ("URB Still Pending ...");
printk("<1>URB Still Pending ...");
break;
case -EPROTO:
err ("Bitstuff error or Unknown USB error");
printk("<1>Bitstuff error or Unknown USB error");
break;
case -EILSEQ:
err ("CRC Mismatch");
printk("<1>CRC Mismatch");
break;
case -EPIPE:
err ("Babble detect or Endpoint stalled");
printk("<1>Babble detect or Endpoint stalled");
break;
case -ETIMEDOUT:
err ("Transfer timed out,NAK");
printk("<1>Transfer timed out,NAK");
break;
case -ENODEV:
err ("Device was removed");
printk("<1>Device was removed");
break;
case -EREMOTEIO:
err ("Short packet detected");
printk("<1>Short packet detected");
break;
case -EXDEV:
err ("ISO only partially completed, look at indywidual frame");
printk("<1>ISO only partially completed, look at indywidual frame");
break;
case -EINVAL:
err ("ISO madness; log off an go home");
printk("<1>ISO madness; log off an go home");
break;
default:
err ("Other:%d", errno );
printk("<1>Other:%d", errno );
break;
}
}
static int fx2_open (struct inode *inode, struct file *file)
{
int retval = 0;
timeout_total = 1000; // w [ms] odczekanie 1000 ms na zakonczenie
transmisji
poll_interval = 1000; // czas interwalow = odstepow sprawdzania
transmisji w [ms]
sRead.nLeft = 0; //ustawienie pozostalych danych jako 0
sRead.nOffset = 0; //czytanie od poczatku pliku
sRead.nFirstTime = 1; //pierwsze wywolanie
down(&mutex); //zablokowanie funkcji open dla innych procesow
err("fx2_open");
if (opened) //jesli jest 1 a powinno byc 0
{
printk("<1>Blad w open");
err("fx2_open: plik jest juz otwarty przez aplikacje");
up(&mutex); //zwolnienie semafora
return FILE_ERR; //numer bledu -86
}
//w funkcjo probe jest ustawienie zmiennej probed na 1 ...... PROBED
oznacza 1
if (probed !=PROBED) //jesli jest rozne od 1 to znaczy ze nie bylo PROBED
{
printk("<1>Blad w open");
err("fx2_open: urzadzenie zostalo odlaczone");
up(&mutex); //zwolnienie semafora
return FILE_ERR; //zwrocenie bledu o numerze -86
}
//jesli wszystko pomyslnie to :
opened = 1 ; //ustawienie licznika otwarcia !
MOD_INC_USE_COUNT; //zwiekszenie licznika otwarcia
up(&mutex); //zwolnienie funkcji
printk("<1>Otwarcie powiodlo sie");
err("open ok" );
buffersNotAllocated=1;
return retval; //zwrocenie 0 oznacza OK
}
//zamkniecie pliku urzadzenia
static int fx2_release (struct inode *inode, struct file *file)
{
int retval = 0; /*ustawienie wartosci zwracanej przez funkcje */
err("fx2_release");
down (&mutex); /* zamrozenie naszej funkcji dla innych funkcji */
if (!opened) //powinno byc 1 a jest 0
{
err("Urzadzenie nie zostalo otwarte");
up(&mutex);
retval = -ENODEV; //no device
}//w funkcji probe jest ustawienie zmiennej probed na 1 ...... PROBED
oznacza 1
if (probed != PROBED)
{
printk("<1>Urzadzenie zostalo odlaczone przed wywolaniem release");
err("Ostrzezenie:Urzadzenie zostalo niewlasciwie odlaczone");
FreeBuffers(); //zwolnienie pamieci
return retval; //zwrocenie wartosci 0 - mimo ze bylo odlaczenie
urzadzenia wczesniejsza nie sprawia to problemu
up(&mutex);
}
opened=0; //wyzerowanie otwarcia urzadzenia
up(&mutex);
MOD_DEC_USE_COUNT; /* zmniejszenie licznika wykorzystania */
return retval; //zwrocenie 0 oznacza OK
}
static int AllocateBuffers()
{
int status = 0 ; //status funkcji AllocateBuffers
//wedlug dokumentacji z Linuxa /usr/src/linux/Documentation/usb
//dla transferu bulk,int oraz ctrl nalezy wpisac 0, gdyz jest to ilosc
isochronicznych transmisji ramek
//jesli nie powiedzie sie jedna z operacji to status przyjmuje wartosc 1
if ( ! ( sRead.pUrb = usb_alloc_urb (0)) ) status = 1 ;
if ( ! ( sWrite.pUrb = usb_alloc_urb (0)) ) status = 1 ;
if ( ! (sRead.pBuff = kmalloc ( frame_size , GFP_KERNEL)) ) status = 1 ;
if ( ! (sWrite.pBuff = kmalloc ( frame_size , GFP_KERNEL)) ) status = 1 ;
if ( status != 0 ) {
printk("<1>Nie powiodlo sie przydzielanie pamieci w trakcie ladowania
modulu");
err( "Nie powiodlo sie przydzielanie pamieci w trakcie ladowania modulu")
;
}
//status 0 oznacza wszystko w porzadku .. jesli sie nie uda to nad
buffersnotallocated = 1
printk("<1>Pamiec zaalokowana");
buffersNotAllocated = status ;
return status ;
}
//zwolnienie buforow pamieci
static int FreeBuffers()
{
if ( buffersNotAllocated == 0 )
{
printk("<1>Bufory nie sa zaalokowane i nie ma co zwalniac");
return 0 ;
}
down (&mutex); //zablokowanie funkcji dla innych procesow
usb_unlink_urb( sRead.pUrb ); //shut down any possible pending reads that
might be currently occurring
usb_unlink_urb( sWrite.pUrb ); //shut down any possible pending writes
that might be currently occurring
kfree (sRead.pBuff); //zwolnienie pamieci zaalokowanej w buforze odczytu
z urzadzenia
kfree (sWrite.pBuff); //zwolnienie pamieci zaalokowanej w buforze zapisu
do urzadzenia
//zwolnienie URB
usb_free_urb(sRead.pUrb);
usb_free_urb(sWrite.pUrb);
buffersNotAllocated = 0; //pamiec = bufory sa zwolnione juz
up(&mutex); //odmrozenie funkcji
return 0 ;
}
//HZ to przerwanie zegarowe ustawione na domyslna czestotliwosc 100
//z taka czestotliwoscia zwieksza sie wartosc zmiennej jiffies
//funkcja uzywana do odczekania pewnego okreslonego czasu ustalenia
odpowiedzi z urzadzenia po transmisji
#define TIMEOUT_JIFFIES(x) (1+(x*HZ)/1000)
static void wait_for_urb (purb_t pUrbLoc)
{
//poll_interval ma wartosc domyslna 0 !
int pollInterval=TIMEOUT_JIFFIES(poll_interval); //w tym momencie
pollInterval rowny jest 1
//wartosc probed ustawiana jest w funkcji probe .. DISCONNECTED ma wartosc 0
if ( probed == DISCONNECTED )
{
err("wait_for_urb, Urzadzenie odlaczone");
return ; //wyjscie z funkcji
}
timeout = TIMEOUT_JIFFIES(timeout_total) ; //Zmienna timeout_total
ustawiona w funkcji open = 1000 , timeout 101
//odczekanie procesu tworzenia polaczenia .. EINPROGRESS oznacza tworzenie
polaczenia bez bledow !!!
//czas oczekiwania jest rowny timeout*shedule_timeout=timeout*1[ms]=101[ms]
czyli status=-EINPROGRESS moze byc przez 101[ms]
while (timeout>=0 && pUrbLoc->status == -EINPROGRESS && probed !=
DISCONNECTED )
{
int sleep;
set_current_state(TASK_INTERRUPTIBLE); //procesor moze wykonywac inne
procesy podczas czekania na URB
sleep=schedule_timeout (pollInterval); //causes the process to sleep
until the given time has passed
//gdy czas sleep minie i bedzie rowny 0 to lub wynik dzialania procedury
pozytywny i rowny 0
if (!sleep)
{
// printk("<1>Caly pollinterval uplynal");
timeout -= pollInterval; // caly pollInterval uplynal i zmniejszanie
wartosci timeout az do < od 0 zgodnie z while
}
else
{
printk("<1>Powrot przez sygnal sleep");
timeout -= sleep; // powrot przez sygnal
}
}
if ( timeout < 0 || probed == DISCONNECTED )
{
if ( probed == DISCONNECTED )
err("Odlaczone urzadzenie!!") ;
else
err("Wystapil TimeOut - odlaczam zlecenie URB");
if ( pUrbLoc == sRead.pUrb ) //jesli mamy do czynienia z odczytem z
urzadzenia
sRead.nFirstTime = 1; //pierwsze wywolanie
usb_unlink_urb( pUrbLoc ); //odlaczenie zlecenie URB czyli ok
}
show_error( pUrbLoc->status );
}
static ssize_t fx2_read (struct file *file, char *buf, size_t count, loff_t
*ppos)
{
ssize_t retval = 0 ; //do zwracania wyniku funkcji fx2_read
err("fx2_read" );
down (&mutex); /* zamrozenie funkcji */
if ( probed == DISCONNECTED ) //status probed ustawiony w funkcji
disconnect po odlaczeniu urzadzenia
{
printk("<1>Urzadzenie odlaczone");
err("fx2_read: Urzadzenie zostalo odlaczone");
up(&mutex);
return -EFAULT ;
}
// PRZYDZIELENIE PAMIECI W FUNKCJI PROBE oraz tu//
//jesli prawda czyli jesli buffersNotAllocated =1
if ( buffersNotAllocated ) AllocateBuffers();
//jesli nadal bufory nie sa zaalokowane to blad
if ( buffersNotAllocated )
{
printk("<1>Buffers not allocated");
err("fx2_read:BuffersNotAllocated");
up(&mutex);
return -EFAULT ;
}
//sprawdzenie czy pamiec zostala przydzielona
if(!buffersNotAllocated)
printk("<1>Pamiec jest przydzielona.. Jest OK\n");
if ( opened == 0 ) //jesli opened ustawiony w funkcji open
{
printk("<1>Czytamy z zamknietego pliku?");
err("fx2_read:czytamy z zamkniego pliku ?");
up(&mutex);
return -EFAULT ;
}
//ustawienie momentu czytania na sam poczatek strony pamieci
sRead.nOffset = 0;
switch(my_dev->descriptor.idProduct)
{
case PRODUCT:
/* do an immediate bulk read to get data from the device
usb_bulk_msg(dev->udev,usb_rcvbulkpipe(dev->udev,dev->bulk_in_endpointAddr),
dev->bulk_in_buffer,
dev->bulk_in_size,&count,HZ*10); --- prototyp funkcji z usb-skeleton.c*/
//The number of actual bytes transferred will be placed in the count
paramater.
//retval=usb_submit_urb(sRead.pUrb);
//wait_for_urb(sRead.pUrb);
retval=usb_bulk_msg (my_dev, usb_rcvbulkpipe
(my_dev,endpoint_r),sRead.pBuff, frame_size, &count, HZ*5);
wait_for_urb (sRead.pUrb); //ustalenie czasu odpowiedzi
if (timeout<0){
printk("<1>Timeout w funkcji read"); //status -EINPROGRESS byl dluzej niz
przez 101[ms]
return sRead.pUrb->status ;/* FILE_TO ; */
}
sRead.nLeft = sRead.pUrb->actual_length; //aktualny rozmiar pozostalych
danych w buforze transferu
if ( sRead.pUrb->status != 0 /** Transmisja niepoprawna - zwracany -1*/)
{
printk("<1>Transmisja niepoprawna w read");
show_error( sRead.pUrb->status );
return sRead.pUrb->status ;
}
/* if the read was successful =0 , copy the data to userspace */
if (!retval) {
printk("<1>Kopiowanie danych do przestrzeni uzytkownika");
if (copy_to_user (buf, sRead.pBuff, sRead.nLeft))
retval = -EFAULT; //gdy copy_to_user zwroci 0
else{
printk("<1> Kopiowanie danych do przestrzeni uzytkownika powiodlo sie");
retval = count; //ile danych zostalo skopiowanych
}
}
else{
/*When the host sends an IN token to any IN endpoint which does not have
data to send, the FX2
automatically NAKs the IN token and asserts this interrupt. ale nie wiem czy
podobnie jest z procesorem w skanerze*/
if(retval==-110){
printk("<1> Brak danych do odczytu lub sprobuj pozniej %d\n",retval);
//NAK -- not ready try later
show_error(retval);
}
}
break;
default:
{
printk("<1>Nieznane urzadzenie");
err("Nieznane urzadzenie");
}
}
//teoretycznie wartosc sRead.nLeft powinna byc rowna count choc nazwy
wskazuja na cos innego.. sprawdzmy to
printk("<1>sRead.nleft: %d , count %d",sRead.nLeft,count);
up(&mutex);
printk("<1>Wszystko ok");
err ( "fx2_read ok" );
return retval; //zwraca wartosc funkcji
}
//zapis do pamieci urzadzenia --- transfer OUT
static ssize_t fx2_write (struct file *file, const char *buf, size_t count,
loff_t *ppos)
{
ssize_t bytes_written =0;
ssize_t retval = 0 ; //do zwracania wyniku funkcji fx2_write
err("fx2_write");
// PRZYDZIELENIE PAMIECI W FUNKCJI PROBE oraz tu//
//jesli prawda czyli jesli buffersNotAllocated =1
if ( buffersNotAllocated ) AllocateBuffers();
//jesli nadal bufory nie sa zaalokowane to blad
if ( buffersNotAllocated )
{
printk("<1>Buffers not allocated");
err("fx2_read:BuffersNotAllocated");
up(&mutex);
return -EFAULT ;
}
//sprawdzenie czy pamiec zostala przydzielona
if(!buffersNotAllocated)
printk("<1>Pamiec jest przydzielona\n");
switch(my_dev->descriptor.idProduct)
{
case PRODUCT:
down (&mutex);
if ( probed == DISCONNECTED )
{
err("fx2_write: Urzadzenie zostalo odlaczone");
up(&mutex);
return -EFAULT ;
}
if ( opened == 0 )
{
err("fx2_write:Piszemy do zamknietego pliku ?!");
up(&mutex);
return -EFAULT ;
}
err("mutex ok");
/* mozemy zapisac tyle ile pociagnie 1 URB*/
bytes_written = ( count >frame_size) ? frame_size : count;
//skopiowanie z bufora buf do bufora sWrite.pBuff danych o liczbie count
//jesli wynik kopiowania rowny 0 to :
if (copy_from_user (sWrite.pBuff, buf, bytes_written)){
printk("<1>Skopiowalem z przestrzeni uzytkownika do jadra");
retval = -EFAULT;
goto exit;
}
FILL_BULK_URB(sWrite.pUrb, my_dev, usb_sndbulkpipe(my_dev, endpoint_w),
sWrite.pBuff, bytes_written,
NULL, my_dev);
//usb_submit_urb -- przeslanie danych !
retval = usb_submit_urb (sWrite.pUrb); //tlo --(dane)--urzadzenie
if (retval) //jesli rozne od 0
{
err("SUBMIT BULK ");
printk("<1>WRITE_Blad w usb_submit_urb w funkcji write");
retval = FILE_ERR;
}
else {
// jesli wszystko jest w porzadku czyli usb_submit_urb zadzialalo ==0 to
odlaczenie URB przez usb_unlink_urb
//ktore znajduje sie w procedurze wait_for_urb
printk("<1>Transfer powiodl sie");
wait_for_urb(sWrite.pUrb);
retval = bytes_written; //retval przyjmuje wartosc ilosci danych
zapisanych do urzadzenia
}
up(&mutex);
break;
}
err ("fx2_write ok" );
return retval;
exit:
/* unlock the device*/
printk("<1>Nie udalo sie skopiowac danych z przestrzeni uzytkownika");
up(&mutex);
return retval;
}
static int fx2_ioctl (struct inode *inode, struct file *file, unsigned int
cmd, unsigned long arg)
{
int result;
int ret=0;
err("fx2_ioctl");
if ( probed == DISCONNECTED )
{
err("Urzadzenie zostalo odlaczone");
return -EFAULT ;
}
switch (cmd)
{
case IOCTL_SET_TOTAL_TIMEOUT:
timeout_total = arg ;
err("timeout_total=%d",timeout_total);
break;
case IOCTL_SET_POLL_INTERVAL:
poll_interval = arg ;
err("poll_interval=%d",poll_interval);
break;
case IOCTL_GET_VENDORID:
err("Vendor id %s\n",my_dev->descriptor.idVendor);
printk("<1>VendorID %s\n",my_dev->descriptor.idVendor);
break;
case IOCTL_GET_PRODUCTID:
printk("<1>Product id %s\n",my_dev->descriptor.idProduct);
break;
case IOCTL_IN:
{
/* result = usb_control_msg(my_dev, usb_rcvctrlpipe(my_dev, 0),
args.request, USB_TYPE_VENDOR|
USB_RECIP_DEVICE|USB_DIR_IN,
args.value, args.index, &args.data,
1, HZ*5);
*/
printk("<1> rezultat %d",result); //-32
return result;
break;
}
case IOCTL_OUT:
{
result = usb_control_msg(my_dev, usb_sndctrlpipe(my_dev, 0),
0x40, 0x00,
0x01, 0x8114, NULL,
0, HZ*5);
printk("<1>Result: %d\n",result);
show_error(result);
return result;
break;
}
default:
err ("Not supported method in IOCTL"); //OK ...
break;
}
return ret;
}
static void * fx2_probe(struct usb_device *dev, unsigned int ifnum, const
struct usb_device_id *id)
{
printk("<1>fx2_probe for %x %x : a znalazl %x %x \n ", VENDOR, PRODUCT,
dev->descriptor.idVendor,dev->descriptor.idProduct);
if (dev->descriptor.idVendor == VENDOR && dev->descriptor.idProduct ==
PRODUCT )
{
my_dev = dev; //przypisanie znalezionego urzadzenia do urzadzenia
usb_device
down(&mutex); //zamrozenie funkcji probe
if ( probed == PROBED ) //PROBED ma wartosc 1
{
printk("<1>Blad\n");
err( "Warnning - Urzadzenie juz raz otrzymalo PROBE !(lub nie
otrzymalo DISCONNECT)");
}
if ( opened )
{
printk("<1>Blad\n");
err("Warnning - ktos otwiera driver przed probe\n");
}
probed = PROBED ;
//jesli prawda czyli jesli buffersNotAllocated =1 trzeba zrobic
buffersnotallocated = 0
if ( buffersNotAllocated ) AllocateBuffers();
//jesli nadal bufory nie sa zaalokowane to blad
if ( buffersNotAllocated )
{
printk("<1>Buffers not allocated");
err("fx2_read:BuffersNotAllocated");
up(&mutex);
//return -EFAULT ;
}
else
printk("<1> Pamiec zostala przydzielona\n");
//adresy endpoints sa na stale
up(&mutex);
printk("<1>Znalazlem swoje urzadzenie\n");
err( "Probe ok connected:");
err( DRIVER_NAME );
return my_dev; //zwrocenie urzadzenia po dokonaniu funkcji probe
}
printk("<1>Cos jest nie tak w probe\n");
return NULL ; //wystapil blad ....
}
/*
Wzywane przez usb core jesli urzadzenie zostaje odlaczone z portu USB
*/
static void fx2_disconnect(struct usb_device *dev, void *ptr)
{
printk("<1>Urzadzenie zostaje odlaczane\n");
err("fx2_disconnect");
if ( probed != PROBED ) //jest rozne od 1
err("Warnning! - Urzadzenie otrzymalo juz DISCONNECT (Lub nie otrzymalo
PROBE)" );
if (dev->descriptor.idVendor == VENDOR && dev->descriptor.idProduct ==
PRODUCT )
{
down(&mutex);
probed = DISCONNECTED ; //PROBED otrzymuje wartosc 0
if(opened){
opened=0;
printk("<1> Zmniejszam licznik wykorzystania w funkcji disconnect\n");
MOD_DEC_USE_COUNT;
}
up(&mutex);
}
}
/*
* Po zaladowaniu modulu do przestrzeni jadra
*/
static int __init usb_fx2_init(void)
{
int result = 0;
printk("<1> Witaj w FX2 driver\n");
err("fx2_init");
init_MUTEX (&mutex);
opened=0; //wyzerowanie liczby otwarc urzadzenia
buffersNotAllocated=1 ; //bufory nie sa zaalokowane
probed=LOADED ; //LOADED ma wartosc 0
// if (frame_size == 0)
frame_size = 64 ; //64 bajty
if (endpoint_r == 0)
endpoint_r = 0x82;
if (endpoint_w == 0)
endpoint_w = 0x06;
if(usb_register (&fx2_driver)){
printk("<1>Blad podczas rejestracji drivera");
return -1;
}
printk("<1> %s 11-02-2003 (timeout przez ioctl) frame_size=%d - max
request.\nendpoint_r=$%x\nendpoint_w=$%x\n",
__FILE__,frame_size, endpoint_r, endpoint_w);
info("CZESC --- rezultat rejestracji wynosi %d",result);
info(DRIVER_DESC " " DRIVER_VERSION);
return result;
}
static void __exit usb_fx2_exit(void)
{
err("fx2_unload");
FreeBuffers();
/* deregister this driver with the USB subsystem */
usb_deregister(&fx2_driver);
}
module_init(usb_fx2_init);
module_exit(usb_fx2_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel