E: akrebs@altavista.net
D: CYPRESS CY82C693 chipset IDE, Digital's PC-Alpha 164SX boards
+N: Greg Kroah-Hartman
+E: greg@kroah.com
+W: http://www.kroah.com/linux-usb/
+D: USB Serial Converter driver framework, USB Handspring Visor driver
+D: ConnectTech WHITEHeat USB driver, Generic USB Serial driver
+D: bits and pieces of USB core code.
+
N: Russell Kroll
E: rkroll@exploits.org
W: http://www.exploits.org/
S: Germany
N: Jaroslav Kysela
-E: perex@jcu.cz
-W: http://www.pf.jcu.cz/~perex
+E: perex@suse.cz
+W: http://www.perex.cz
D: Original Author and Maintainer for HP 10/100 Mbit Network Adapters
-S: Unix Centre of Pedagogical Faculty, University of South Bohemia
+D: ISA PnP
+S: Sindlovy Dvory 117
+S: 370 01 Ceske Budejovice
+S: Czech Republic
N: Bas Laarhoven
E: bas@vimec.nl
unsigned short device,
struct pci_bus *from);
-The above function finds a ISA PnP card. For the vendor device should
+This function finds a ISA PnP card. For the vendor device should
be used ISAPNP_VENDOR(a,b,c) where a,b,c are characters or integers.
For the device number should be used ISAPNP_DEVICE(x) macro where x is
-integer value. Both vendor and device numbers can be get from contents
+integer value. Both vendor and device numbers can be taken from contents
of the /proc/isapnp file.
extern struct pci_dev *isapnp_find_dev(struct pci_bus *card,
unsigned short function,
struct pci_dev *from);
-The above function finds the ISA PnP device. If card is NULL, then
+This function finds the ISA PnP device. If card is NULL, then
the global search mode is used (all devices are used for the searching).
Otherwise only devices which belongs to the specified card are verified.
For the function number can be used ISAPNP_FUNCTION(x) macro which works
similarly as the ISAPNP_DEVICE(x) macro.
+extern int isapnp_probe_cards(const struct isapnp_card_id *ids,
+ int (*probe)(struct pci_bus *card,
+ const struct isapnp_card_id *id));
+
+
+This function is a helper for drivers which requires to use more than
+one device from an ISA PnP card. For each cards is called the probe
+callback with appropriate information.
+
+Example for ids parameter initialization:
+
+static struct isapnp_card_id ids[] __devinitdata = {
+ {
+ ISAPNP_CARD_ID('A','D','V', 0x550a),
+ devs: {
+ ISAPNP_DEVICE_ID('A', 'D', 'V', 0x0010),
+ ISAPNP_DEVICE_ID('A', 'D', 'V', 0x0011)
+ },
+ driver_data: 0x1234,
+ },
+ {
+ ISAPNP_CARD_END,
+ }
+};
+
ISA PnP configuration
=====================
Second way is auto-configuration
--------------------------------
-These two functions gives to the driver the real power of the ISA PnP
-feature. First function dev->prepare() only initialize the resource
-members in the device structure. This structure contains all resources
-set to auto configuration values after the initialization. The driver for
-ISA PnP device may modify (or not) some resources to skip auto configuration
-for the given resource.
+This feature gives to the driver the real power of the ISA PnP code.
+Function dev->prepare() initializes the resource members in the device
+structure. This structure contains all resources set to auto configuration
+values after the initialization. The device driver may modify some resources
+to skip the auto configuration for a given resource.
-The function isapnp_configure does:
- - resources which have the auto configuration value are configured
+Once the device structure contains all requested resource values, the function
+dev->activate() must be called to assign free resources to resource members
+with the auto configuration value.
+
+Function dev->activate() does:
+ - resources with the auto configuration value are configured
- the auto configuration is created using ISA PnP resource map
- the function writes configuration to ISA PnP configuration registers
- the function returns to the caller actual used resources
+When the device driver is removing, function dev->deactivate() has to be
+called to free all assigned resources.
+
Example (game port initialization)
==================================
mailing me directly. The chance that someone with the same card
listens there is much higher...
+For problems with sound: There are alot of different systems used
+for TV sound all over the world. And there are also different chips
+which decode the audio signal. Reports about sound problems ("stereo
+does'nt work") are pretty useless unless you include some details
+about your hardware and the TV sound scheme used in your country (or
+at least the country you are living in).
+
Finally: If you mail some patches for bttv around the world (to
linux-kernel/Alan/Linus/...), please Cc: me.
VERSION = 2
PATCHLEVEL = 3
SUBLEVEL = 99
-EXTRAVERSION = -pre2
+EXTRAVERSION = -pre3
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
include arch/$(ARCH)/Makefile
-export CORE_FILES NETWORKS DRIVERS LIBS HEAD LDFLAGS LIBS LINKFLAGS \
- MAKEBOOT ASFLAGS
+export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS
# use '-fno-strict-aliasing', but only if the compiler can take it
CFLAGS += $(shell if $(CC) -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-strict-aliasing"; fi)
#define I2C_GET() (btread(BT848_I2C)&1)
#define BURSTOFFSET 76
+#define BTTV_ERRORS 5
/* ----------------------------------------------------------------------- */
if (card >= bttv_num) {
return -1;
}
-
return bttvs[card].type;
}
}
btv = &bttvs[card];
- down(&btv->lock);
btaor(data, ~mask, BT848_GPIO_OUT_EN);
- up(&btv->lock);
-
return 0;
}
return -ENODEV;
}
- down(&btv->lock);
-
/* prior setting BT848_GPIO_REG_INP is (probably) not needed
because we set direct input on init */
-
*data = btread(BT848_GPIO_DATA);
-
- up(&btv->lock);
-
return 0;
}
btv = &bttvs[card];
- down(&btv->lock);
-
/* prior setting BT848_GPIO_REG_INP is (probably) not needed
because direct input is set on init */
-
btaor(data & mask, ~mask, BT848_GPIO_DATA);
-
- up(&btv->lock);
-
return 0;
}
}
btv = &bttvs[card];
-
if (bttvs[card].shutdown) {
return NULL;
}
-
return &btv->gpioq;
}
4, 1, 0, 2,15, { 2, 3, 1, 1}, { 2, 0, 0, 0,10},0,
1,1,1,1,0 },
{ "Hauppauge old",
- 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0,
+ 4, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0,
1,1,0,1,0 },
{ "STB",
3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1},0,
3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0},0,
1,1,1,1,0 },
{ "Hauppauge new (bt878)",
- 3, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4},0,
+ 4, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4},0,
1,1,0,1,0 },
{ "MIRO PCTV pro",
3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10},0,
unsigned int *pe=(unsigned int *) btv->vbi_even;
if (debug)
- printk("bttv%d: vbi: po=%08lx pe=%08lx\n",
+ printk("bttv%d: vbi1: po=%08lx pe=%08lx\n",
btv->nr,virt_to_bus(po), virt_to_bus(pe));
*(po++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(po++)=0;
}
*(pe++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(0x01<<16));
*(pe++)=cpu_to_le32(virt_to_bus(btv->risc_jmp+10));
- DEBUG(printk(KERN_DEBUG "po: 0x%lx\n",(long)po));
- DEBUG(printk(KERN_DEBUG "pe: 0x%lx\n",(long)pe));
+
+ if (debug)
+ printk("bttv%d: vbi2: po=%08lx pe=%08lx\n",
+ btv->nr,virt_to_bus(po), virt_to_bus(pe));
}
static int fmtbppx2[16] = {
int shift, csize;
if (debug)
- printk("bttv%d: prisc: ro=%08lx re=%08lx\n",
+ printk("bttv%d: prisc1: ro=%08lx re=%08lx\n",
btv->nr,virt_to_bus(ro), virt_to_bus(re));
switch(fmt)
*(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16));
*(re++)=cpu_to_le32(btv->bus_vbi_odd);
+ if (debug)
+ printk("bttv%d: prisc2: ro=%08lx re=%08lx\n",
+ btv->nr,virt_to_bus(ro), virt_to_bus(re));
+
return 0;
}
return make_prisctab(btv, ro, re, vbuf, width, height, palette);
if (debug)
- printk("bttv%d: vrisc: ro=%08lx re=%08lx\n",
+ printk("bttv%d: vrisc1: ro=%08lx re=%08lx\n",
btv->nr,virt_to_bus(ro), virt_to_bus(re));
inter = (height>tvnorms[btv->win.norm].sheight/2) ? 1 : 0;
*(ro++)=cpu_to_le32(btv->bus_vbi_even);
*(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16));
*(re++)=cpu_to_le32(btv->bus_vbi_odd);
+
+ if (debug)
+ printk("bttv%d: vrisc2: ro=%08lx re=%08lx\n",
+ btv->nr,virt_to_bus(ro), virt_to_bus(re));
return 0;
}
width=btv->win.width;
height=btv->win.height;
if (debug)
- printk("bttv%d: make_clip: pal=%d size=%dx%d, bpl=%d bpp=%d\n",
+ printk("bttv%d: clip1: pal=%d size=%dx%d, bpl=%d bpp=%d\n",
btv->nr,btv->picture.palette,width,height,bpl,bpp);
if(width > 1023)
width = 1023; /* sanity check */
*(ro++)=cpu_to_le32(btv->bus_vbi_even);
*(re++)=cpu_to_le32(BT848_RISC_JUMP);
*(re++)=cpu_to_le32(btv->bus_vbi_odd);
+
+ if (debug)
+ printk("bttv%d: clip2: pal=%d size=%dx%d, bpl=%d bpp=%d\n",
+ btv->nr,btv->picture.palette,width,height,bpl,bpp);
}
/*
if(btv->gbuf[mp->frame].stat != GBUFFER_UNUSED)
return -EBUSY;
- if(mp->height <0 || mp->width <0)
+ if(mp->height < 32 || mp->width < 32)
return -EINVAL;
if (mp->format >= PALETTEFMT_MAX)
return -EINVAL;
if(-1 == palette2fmt[mp->format])
return -EINVAL;
- /*
- * FIXME: Check the format of the grab here. This is probably
- * also less restrictive than the normal overlay grabs. Stuff
- * like QCIF has meaning as a capture.
- */
-
/*
* Ok load up the BT848
*/
make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, mp->format);
if (debug)
- printk("bttv%d: cap vgrab: queue %d\n",btv->nr,mp->frame);
+ printk("bttv%d: cap vgrab: queue %d (%dx%d)\n",
+ btv->nr,mp->frame,mp->width,mp->height);
cli();
btv->gbuf[mp->frame].stat = GBUFFER_GRABBING;
btv->gbuf[mp->frame].fmt = palette2fmt[mp->format];
tvnorms[2].hdelayx1 = 186 - (on?BURSTOFFSET :0);
}
+static void bt848_restart(struct bttv *btv)
+{
+ if (verbose)
+ printk("bttv%d: resetting chip\n",btv->nr);
+ btwrite(0xfffffUL, BT848_INT_STAT);
+ btand(~15, BT848_GPIO_DMA_CTL);
+ btwrite(0, BT848_SRESET);
+ btwrite(virt_to_bus(btv->risc_jmp+2),
+ BT848_RISC_STRT_ADD);
+
+ /* enforce pll reprogramming */
+ btv->pll.pll_current = 0;
+ set_pll(btv);
+
+ btv->errors = 0;
+ btv->needs_restart = 0;
+ bt848_set_geo(btv,0);
+ bt848_set_risc_jmps(btv,-1);
+}
+
/*
* Open a bttv card. Right now the flags stuff is just playing
*/
for (i = 0; i < gbuffers; i++)
btv->gbuf[i].stat = GBUFFER_UNUSED;
+ if (btv->needs_restart)
+ bt848_restart(btv);
burst(0);
set_pll(btv);
btv->user++;
btaor(datahi, ~1, BT848_O_CONTROL);
}
-
/*
* ioctl routine
*/
static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
{
struct bttv *btv=(struct bttv *)dev;
- int i,ret;
+ int i,ret = 0;
if (debug) printk("bttv%d: ioctl 0x%x\n",btv->nr,cmd);
if(copy_from_user(&vw,arg,sizeof(vw)))
return -EFAULT;
-
+
if(vw.flags || vw.width < 16 || vw.height < 16)
{
down(&btv->lock);
vw.width &= ~3;
}
down(&btv->lock);
+ if (btv->needs_restart)
+ bt848_restart(btv);
btv->win.x=vw.x;
btv->win.y=vw.y;
btv->win.width=vw.width;
return -EINVAL;
switch (btv->gbuf[i].stat) {
case GBUFFER_UNUSED:
- return -EINVAL;
+ ret = -EINVAL;
+ break;
case GBUFFER_GRABBING:
while(btv->gbuf[i].stat==GBUFFER_GRABBING) {
if (debug)
printk("bttv%d: cap sync: sleep on %d\n",btv->nr,i);
interruptible_sleep_on(&btv->capq);
- if(signal_pending(current))
- return -EINTR;
+ if(signal_pending(current)) {
+ ret = -EINTR;
+ break;
+ }
}
/* fall throuth */
case GBUFFER_DONE:
if (debug)
printk("bttv%d: cap sync: buffer %d, retval %d\n",btv->nr,i,ret);
btv->gbuf[i].stat = GBUFFER_UNUSED;
- return ret;
}
- return 0;
+ if (btv->needs_restart) {
+ down(&btv->lock);
+ bt848_restart(btv);
+ up(&btv->lock);
+ }
+ return ret;
case BTTV_FIELDNR:
if(copy_to_user((void *) arg, (void *) &btv->last_field,
todo=count;
while (todo && todo>(q=VBIBUF_SIZE-btv->vbip))
{
+ if (btv->needs_restart) {
+ down(&btv->lock);
+ bt848_restart(btv);
+ up(&btv->lock);
+ }
if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, q))
return -EFAULT;
todo-=q;
struct bttv *btv=(struct bttv *)(dev-2);
down(&btv->lock);
+ if (btv->needs_restart)
+ bt848_restart(btv);
btv->vbip=VBIBUF_SIZE;
btv->vbi_on = 1;
bt848_set_risc_jmps(btv,-1);
if(v.tuner||btv->channel) /* Only tuner 0 */
return -EINVAL;
strcpy(v.name, "Radio");
- v.rangelow=(int)(87.5*16);
- v.rangehigh=(int)(108*16);
+ v.rangelow=(int)(76*16); /* jp: 76.0MHz - 89.9MHz */
+ v.rangehigh=(int)(108*16); /* eu: 87.5MHz - 108.0MHz */
v.flags= 0; /* XXX */
v.mode = 0; /* XXX */
if(copy_to_user(arg,&v,sizeof(v)))
/* print which board we have found */
printk(KERN_INFO "bttv%d: model: ",btv->nr);
- sprintf(btv->video_dev.name,"BT%d",btv->id);
- if (btv->id==848 && btv->revision==0x12)
- strcat(btv->video_dev.name,"A");
- strcat(btv->video_dev.name,"(");
- strcat(btv->video_dev.name, tvcards[btv->type].name);
- strcat(btv->video_dev.name,")");
+ sprintf(btv->video_dev.name,"BT%d%s(%.22s)",
+ btv->id,
+ (btv->id==848 && btv->revision==0x12) ? "A" : "",
+ tvcards[btv->type].name);
printk("%s\n",btv->video_dev.name);
/* board specific initialisations */
btv->vbibuf=0;
btv->field=btv->last_field=0;
+ btv->errors=0;
+ btv->needs_restart=0;
+
/* i2c */
btv->tuner_type=-1;
init_bttv_i2c(btv);
{
u32 stat,astat;
u32 dstat;
- int count;
+ int count,i;
struct bttv *btv;
btv=(struct bttv *)dev_id;
btv->field++;
}
if (astat&(BT848_INT_SCERR|BT848_INT_OCERR)) {
- printk("bttv%d: irq:%s%s risc_count=%08x\n",btv->nr,
- (astat&BT848_INT_SCERR) ? " SCERR" : "",
- (astat&BT848_INT_OCERR) ? " OCERR" : "",
- btread(BT848_RISC_COUNT));
- bt848_set_risc_jmps(btv,0);
- btwrite(0, BT848_SRESET);
- btwrite(virt_to_bus(btv->risc_jmp),
- BT848_RISC_STRT_ADD);
- bt848_set_geo(btv,0);
- bt848_set_risc_jmps(btv,-1);
-#if 0
- wake_up_interruptible(&btv->vbiq);
- wake_up_interruptible(&btv->capq);
-#endif
+ if (verbose)
+ printk("bttv%d: irq:%s%s risc_count=%08x\n",
+ btv->nr,
+ (astat&BT848_INT_SCERR) ? " SCERR" : "",
+ (astat&BT848_INT_OCERR) ? " OCERR" : "",
+ btread(BT848_RISC_COUNT));
+ btv->errors++;
+ if (btv->errors < BTTV_ERRORS) {
+ btand(~15, BT848_GPIO_DMA_CTL);
+ btwrite(virt_to_bus(btv->risc_jmp+2),
+ BT848_RISC_STRT_ADD);
+ bt848_set_geo(btv,0);
+ bt848_set_risc_jmps(btv,-1);
+ } else {
+ if (verbose)
+ printk("bttv%d: aiee: error loops\n",btv->nr);
+ /* cancel all outstanding grab requests */
+ btv->gq_in = 0;
+ btv->gq_out = 0;
+ btv->gq_grab = -1;
+ for (i = 0; i < gbuffers; i++)
+ if (btv->gbuf[i].stat == GBUFFER_GRABBING)
+ btv->gbuf[i].stat = GBUFFER_ERROR;
+ /* disable DMA */
+ btv->risc_cap_odd = 0;
+ btv->risc_cap_even = 0;
+ bt848_set_risc_jmps(btv,0);
+
+ btv->needs_restart = 1;
+ wake_up_interruptible(&btv->vbiq);
+ wake_up_interruptible(&btv->capq);
+ }
}
if (astat&BT848_INT_RISCI)
{
- IDEBUG(printk ("bttv%d: IRQ_RISCI\n", btv->nr));
+ if (debug > 1)
+ printk("bttv%d: IRQ_RISCI\n",btv->nr);
/* captured VBI frame */
if (stat&(1<<28))
}
/* captured full frame */
- if (stat&(2<<28))
+ if (stat&(2<<28) && btv->gq_grab != -1)
{
btv->last_field=btv->field;
if (debug)
printk("bttv%d: cap irq: done %d\n",btv->nr,btv->gq_grab);
+ do_gettimeofday(&btv->gbuf[btv->gq_grab].tv);
btv->gbuf[btv->gq_grab].stat = GBUFFER_DONE;
btv->gq_grab = -1;
if (btv->gq_in != btv->gq_out)
btv->id=dev->device;
btv->irq=dev->irq;
btv->bt848_adr=dev->resource[0].start;
+ if (!request_mem_region(pci_resource_start(dev,0),
+ pci_resource_len(dev,0),
+ "bttv")) {
+ return -EBUSY;
+ }
if (btv->id >= 878)
btv->i2c_command = 0x83;
else
{
printk(KERN_ERR "bttv%d: Bad irq number or handler\n",
bttv_num);
- return -EINVAL;
+ goto fail;
}
if (result==-EBUSY)
{
printk(KERN_ERR "bttv%d: IRQ %d busy, change your PnP config in BIOS\n",bttv_num,btv->irq);
- return result;
+ goto fail;
}
if (result < 0)
- return result;
+ goto fail;
pci_set_master(dev);
if (!(command&BT878_EN_TBFX))
{
printk("bttv: 430FX compatibility could not be enabled\n");
- return -1;
+ result = -1;
+ goto fail;
}
}
-
return 0;
+
+ fail:
+ release_mem_region(pci_resource_start(btv->dev,0),
+ pci_resource_len(btv->dev,0));
+ return result;
}
static int find_bt848(void)
if (radio[btv->nr] && btv->radio_dev.minor != -1)
video_unregister_device(&btv->radio_dev);
+ release_mem_region(pci_resource_start(btv->dev,0),
+ pci_resource_len(btv->dev,0));
/* wake up any waiting processes
because shutdown flag is set, no new processes (in this queue)
are expected
#ifndef _BTTV_H_
#define _BTTV_H_
-#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,22)
+#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,24)
#include <linux/types.h>
#include <linux/wait.h>
#define GBUFFER_GRABBING 1
#define GBUFFER_DONE 2
#define GBUFFER_ERROR 3
-
+ struct timeval tv;
+
u16 width;
u16 height;
u16 fmt;
unsigned long re;
};
-struct bttv
-{
+struct bttv {
struct video_device video_dev;
struct video_device radio_dev;
struct video_device vbi_dev;
int i2c_command;
int triton1;
+ int errors;
+ int needs_restart;
+
WAIT_QUEUE gpioq;
int shutdown;
};
#ifdef ENABLE_SERIAL_PNP
static struct pci_board pnp_devices[] __initdata = {
+ /* Motorola VoiceSURFR 56K Modem */
+ { ISAPNP_VENDOR('M', 'O', 'T'), ISAPNP_DEVICE(0x15F0), 0, 0,
+ SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 },
/* Rockwell 56K ACF II Fax+Data+Voice Modem */
{ ISAPNP_VENDOR('A', 'K', 'Y'), ISAPNP_DEVICE(0x1021), 0, 0,
SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 },
return NULL;
}
+static const struct isapnp_card_id *
+isapnp_match_card(const struct isapnp_card_id *ids, struct pci_bus *card)
+{
+ int idx;
+
+ while (ids->vendor || ids->device) {
+ if ((ids->vendor == ISAPNP_ANY_ID || ids->vendor == card->vendor) &&
+ (ids->device == ISAPNP_ANY_ID || ids->device == card->device)) {
+ for (idx = 0; idx < ISAPNP_CARD_DEVS; idx++) {
+ if (ids->devs[idx].vendor == 0 &&
+ ids->devs[idx].function == 0)
+ return ids;
+ if (isapnp_find_dev(card,
+ ids->devs[idx].vendor,
+ ids->devs[idx].function,
+ NULL) == NULL)
+ goto __next;
+ }
+ return ids;
+ }
+ __next:
+ ids++;
+ }
+ return NULL;
+}
+
+int isapnp_probe_cards(const struct isapnp_card_id *ids,
+ int (*probe)(struct pci_bus *_card,
+ const struct isapnp_card_id *_id))
+{
+ struct pci_bus *card;
+ const struct isapnp_card_id *id;
+ int count = 0;
+
+ if (ids == NULL || probe == NULL)
+ return -EINVAL;
+ isapnp_for_each_card(card) {
+ id = isapnp_match_card(ids, card);
+ if (id != NULL && probe(card, id) >= 0)
+ count++;
+ }
+ return count;
+}
+
static unsigned int isapnp_dma_resource_flags(struct isapnp_dma *dma)
{
return dma->flags | IORESOURCE_DMA | IORESOURCE_AUTO;
#endif /* CONFIG_PCI */
+EXPORT_SYMBOL(isapnp_cards);
+EXPORT_SYMBOL(isapnp_devices);
EXPORT_SYMBOL(isapnp_present);
EXPORT_SYMBOL(isapnp_cfg_begin);
EXPORT_SYMBOL(isapnp_cfg_end);
EXPORT_SYMBOL(isapnp_deactivate);
EXPORT_SYMBOL(isapnp_find_card);
EXPORT_SYMBOL(isapnp_find_dev);
+EXPORT_SYMBOL(isapnp_probe_cards);
EXPORT_SYMBOL(isapnp_resource_change);
int __init isapnp_init(void)
#endif /* ADVANSYS_DEBUG */
#ifdef ADVANSYS_ASSERT
-STATIC int interrupts_enabled(void);
+STATIC int advansys_interrupts_enabled(void);
#endif /* ADVANSYS_ASSERT */
Scsi_Device *device;
int ret;
- ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+ ASC_ASSERT(advansys_interrupts_enabled() == ASC_FALSE);
ASC_DBG2(1, "asc_execute_scsi_cmnd: scp %lx, done %lx\n",
(ulong) scp, (ulong) scp->scsi_done);
}
ASC_DBG(1, "asc_execute_scsi_cmnd: end\n");
- ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+ ASC_ASSERT(advansys_interrupts_enabled() == ASC_FALSE);
return ret;
}
struct Scsi_Host *shp;
int i;
- ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+ ASC_ASSERT(advansys_interrupts_enabled() == ASC_FALSE);
ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp %lx, qdonep %lx\n",
(ulong) asc_dvc_varp, (ulong) qdonep);
ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep);
struct Scsi_Host *shp;
int i;
- ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+ ASC_ASSERT(advansys_interrupts_enabled() == ASC_FALSE);
ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp %lx, scsiqp %lx\n",
(ulong) adv_dvc_varp, (ulong) scsiqp);
ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp);
ASC_DBG3(3, "asc_enqueue: ascq %lx, reqp %lx, flag %d\n",
(ulong) ascq, (ulong) reqp, flag);
- ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+ ASC_ASSERT(advansys_interrupts_enabled() == ASC_FALSE);
ASC_ASSERT(reqp != NULL);
ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK);
tid = REQPTID(reqp);
REQP reqp;
ASC_DBG2(3, "asc_dequeue: ascq %lx, tid %d\n", (ulong) ascq, tid);
- ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+ ASC_ASSERT(advansys_interrupts_enabled() == ASC_FALSE);
ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID);
if ((reqp = ascq->q_first[tid]) != NULL) {
ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid));
int i;
ASC_DBG2(3, "asc_dequeue_list: ascq %lx, tid %d\n", (ulong) ascq, tid);
- ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+ ASC_ASSERT(advansys_interrupts_enabled() == ASC_FALSE);
ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID));
/*
ASC_DBG2(3, "asc_rmqueue: ascq %lx, reqp %lx\n",
(ulong) ascq, (ulong) reqp);
- ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+ ASC_ASSERT(advansys_interrupts_enabled() == ASC_FALSE);
ASC_ASSERT(reqp != NULL);
tid = REQPTID(reqp);
ASC_DBG2(3, "asc_isqueued: ascq %lx, reqp %lx\n",
(ulong) ascq, (ulong) reqp);
- ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+ ASC_ASSERT(advansys_interrupts_enabled() == ASC_FALSE);
ASC_ASSERT(reqp != NULL);
tid = REQPTID(reqp);
int i;
ASC_DBG1(1, "asc_execute_queue: ascq %lx\n", (ulong) ascq);
- ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
+ ASC_ASSERT(advansys_interrupts_enabled() == ASC_FALSE);
/*
* Execute queued commands for devices attached to
* the current board in round-robin fashion.
#ifdef ADVANSYS_ASSERT
/*
- * interrupts_enabled()
+ * advansys_interrupts_enabled()
*
* Return 1 if interrupts are enabled, otherwise return 0.
*/
STATIC int
-interrupts_enabled(void)
+advansys_interrupts_enabled(void)
{
int flags;
{0, 0x35, "Tap"},
{0, 0x39, "TabletFunctionKey"},
{0, 0x3a, "ProgramChangeKey"},
+ {0, 0x3c, "Invert"},
{0, 0x42, "TipSwitch"},
{0, 0x43, "SecondaryTipSwitch"},
{0, 0x44, "BarrelSwitch"},
case 0x30: /* TipPressure */
+ if (!test_bit(BTN_TOUCH, input->keybit)) {
+ device->quirks |= HID_QUIRK_NOTOUCH;
+ set_bit(EV_KEY, input->evbit);
+ set_bit(BTN_TOUCH, input->keybit);
+ }
usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
usage->code = ABS_PRESSURE;
clear_bit(usage->code, bit);
}
break;
+ case 0x3c: /* Invert */
+
+ usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
+ usage->code = BTN_TOOL_RUBBER;
+ clear_bit(usage->code, bit);
+ break;
+
case 0x33: /* Touch */
case 0x42: /* TipSwitch */
case 0x43: /* TipSwitch2 */
+ device->quirks &= ~HID_QUIRK_NOTOUCH;
usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
usage->code = BTN_TOUCH;
clear_bit(usage->code, bit);
}
}
-static void hid_process_event(struct input_dev *input, int flags, struct hid_usage *usage, __s32 value)
+static void hid_process_event(struct input_dev *input, int *quirks, struct hid_field *field, struct hid_usage *usage, __s32 value)
{
hid_dump_input(usage, value);
return;
}
+ if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */
+ *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT);
+ return;
+ }
+
+ if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */
+ if (value) {
+ input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1);
+ return;
+ }
+ input_event(input, usage->type, usage->code, 0);
+ input_event(input, usage->type, BTN_TOOL_RUBBER, 0);
+ return;
+ }
+
+ if (usage->hid == (HID_UP_DIGITIZER | 0x0030) && (*quirks & HID_QUIRK_NOTOUCH)) { /* Pressure */
+ int a = field->logical_minimum;
+ int b = field->logical_maximum;
+ input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3));
+ }
+
input_event(input, usage->type, usage->code, value);
- if ((flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
+ if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
input_event(input, usage->type, usage->code, 0);
}
} else {
if (value[n] == field->value[n]) continue;
}
- hid_process_event(&dev->input, field->flags, &field->usage[n], value[n]);
+ hid_process_event(&dev->input, &dev->quirks, field, &field->usage[n], value[n]);
} else {
if (field->value[n] >= min && field->value[n] <= max /* non-NULL value */
&& field->usage[field->value[n] - min].hid /* nonzero usage */
&& search(value, field->value[n], count))
- hid_process_event(&dev->input, field->flags, &field->usage[field->value[n] - min], 0);
+ hid_process_event(&dev->input, &dev->quirks, field,
+ &field->usage[field->value[n] - min], 0);
if (value[n] >= min && value[n] <= max /* non-NULL value */
&& field->usage[value[n] - min].hid /* nonzero usage */
&& search(field->value, value[n], count))
- hid_process_event(&dev->input, field->flags, &field->usage[value[n] - min], 1);
+ hid_process_event(&dev->input, &dev->quirks,
+ field, &field->usage[value[n] - min], 1);
}
}
#define USB_VENDOR_ID_WACOM 0x056a
#define USB_DEVICE_ID_WACOM_GRAPHIRE 0x0010
-#define USB_DEVICE_ID_WACOM_INTUOS 0x0021
+#define USB_DEVICE_ID_WACOM_INTUOS 0x0020
struct hid_blacklist {
__u16 idVendor;
__u16 idProduct;
} hid_blacklist[] = {
- { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS },
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1},
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2},
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3},
+ { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4},
{ 0, 0 }
};
#define HID_OUTPUT_REPORT 1
#define HID_FEATURE_REPORT 2
+/*
+ * HID device quirks.
+ */
+
+#define HID_QUIRK_INVERT 0x01
+#define HID_QUIRK_NOTOUCH 0x02
+
/*
* This is the global enviroment of the parser. This information is
* persistent for main-items. The global enviroment can be saved and
struct urb urb; /* USB URB structure */
struct urb urbout; /* Output URB */
struct input_dev input; /* input device structure */
+ int quirks; /* Various nasty tricks the device can pull on us */
};
#define HID_GLOBAL_STACK_SIZE 4
#endif
-struct input_handler keybdev_handler;
+static struct input_handler keybdev_handler;
+static int keybdev_alt = 0;
void keybdev_ledfunc(unsigned int led)
{
handle_scancode(0x1d, down);
handle_scancode(0x45, down);
} else if (code >= 96) {
- handle_scancode(0xe0, 1);
- handle_scancode(keybdev_x86_e0s[code - 96], down);
- if (code == 99) {
+ if (code == 99 && keybdev_alt) {
+ handle_scancode(84, down);
+ } else {
handle_scancode(0xe0, 1);
- handle_scancode(0x37, down);
+ handle_scancode(keybdev_x86_e0s[code - 96], down);
+ if (code == 99) {
+ handle_scancode(0xe0, 1);
+ handle_scancode(0x37, down);
+ }
}
+ } else if (code == 84) {
+ handle_scancode(43, down);
} else handle_scancode(code, down);
+ if (code == 56 || code == 100) keybdev_alt = down;
+
#elif CONFIG_ADB_KEYBOARD
if (code < 128 && keybdev_mac_codes[code])
kfree(handle);
}
-struct input_handler keybdev_handler = {
+static struct input_handler keybdev_handler = {
event: keybdev_event,
connect: keybdev_connect,
disconnect: keybdev_disconnect,
break;
case ABS_Y:
size = handle->dev->absmax[ABS_Y] - handle->dev->absmin[ABS_Y];
- list->dy += (value * CONFIG_MOUSEDEV_SCREEN_Y - list->oldy) / size;
- list->oldy += list->dy * size;
+ list->dy -= (value * CONFIG_MOUSEDEV_SCREEN_Y - list->oldy) / size;
+ list->oldy -= list->dy * size;
break;
}
break;
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
+ * (03/19/2000) gkh
+ * Fixed oops that could happen when device was removed while a program
+ * was talking to the device.
+ * Removed the static urbs and now all urbs are created and destroyed
+ * dynamically.
+ * Reworked the internal interface. Now everything is based on the
+ * usb_serial_port structure instead of the larger usb_serial structure.
+ * This fixes the bug that a multiport device could not have more than
+ * one port open at one time.
+ *
* (03/17/2000) gkh
* Added config option for debugging messages.
* Added patch for keyspan pda from Brian Warner.
static void usb_serial_disconnect(struct usb_device *dev, void *ptr);
static struct usb_driver usb_serial_driver = {
- "serial",
- usb_serial_probe,
- usb_serial_disconnect,
- { NULL, NULL }
+ name: "serial",
+ probe: usb_serial_probe,
+ disconnect: usb_serial_disconnect,
};
static int serial_refcount;
static struct usb_serial *serial_table[SERIAL_TTY_MINORS] = {NULL, };
+static inline int serial_paranoia_check (struct usb_serial *serial, const char *function)
+{
+ if (!serial) {
+ dbg("%s - serial == NULL", function);
+ return -1;
+ }
+ if (serial->magic != USB_SERIAL_MAGIC) {
+ dbg("%s - bad magic number for serial", function);
+ return -1;
+ }
+ if (!serial->type) {
+ dbg("%s - serial->type == NULL!", function);
+ return -1;
+ }
+
+ return 0;
+}
-static struct usb_serial *get_serial_by_minor (int minor)
+
+static inline int port_paranoia_check (struct usb_serial_port *port, const char *function)
{
- dbg("get_serial_by_minor %d", minor);
+ if (!port) {
+ dbg("%s - port == NULL", function);
+ return -1;
+ }
+ if (port->magic != USB_SERIAL_PORT_MAGIC) {
+ dbg("%s - bad magic number for port", function);
+ return -1;
+ }
+ if (!port->serial) {
+ dbg("%s - port->serial == NULL", function);
+ return -1;
+ }
+ if (!port->tty) {
+ dbg("%s - port->tty == NULL", function);
+ return -1;
+ }
+ return 0;
+}
+
+
+static struct usb_serial *get_serial_by_minor (int minor)
+{
return serial_table[minor];
}
return NULL;
}
memset(serial, 0, sizeof(struct usb_serial));
+ serial->magic = USB_SERIAL_MAGIC;
serial_table[i] = serial;
*minor = i;
dbg("minor base = %d", *minor);
static int serial_open (struct tty_struct *tty, struct file * filp)
{
struct usb_serial *serial;
+ struct usb_serial_port *port;
+ int portNumber;
dbg("serial_open");
/* get the serial object associated with this tty pointer */
serial = get_serial_by_minor (MINOR(tty->device));
- /* do some sanity checking that we really have a device present */
- if (!serial) {
- dbg("serial == NULL!");
- return (-ENODEV);
- }
- if (!serial->type) {
- dbg("serial->type == NULL!");
- return (-ENODEV);
+ if (serial_paranoia_check (serial, "serial_open")) {
+ return -ENODEV;
}
- /* make the tty driver remember our serial object, and us it */
- tty->driver_data = serial;
- serial->tty = tty;
+ /* set up our port structure */
+ portNumber = MINOR(tty->device) - serial->minor;
+ port = &serial->port[portNumber];
+ port->number = portNumber;
+ port->serial = serial;
+ port->magic = USB_SERIAL_PORT_MAGIC;
+
+ /* make the tty driver remember our port object, and us it */
+ tty->driver_data = port;
+ port->tty = tty;
/* pass on to the driver specific version of this function if it is available */
if (serial->type->open) {
- return (serial->type->open(tty, filp));
+ return (serial->type->open(port, filp));
} else {
- return (generic_serial_open(tty, filp));
+ return (generic_open(port, filp));
}
}
static void serial_close(struct tty_struct *tty, struct file * filp)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int port;
+ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial *serial;
dbg("serial_close");
- if (!serial) {
- dbg("serial == NULL!");
+ if (port_paranoia_check (port, "serial_close")) {
return;
}
- port = MINOR(tty->device) - serial->minor;
-
- dbg("serial_close port %d", port);
-
- /* do some sanity checking that we really have a device present */
- if (!serial->type) {
- dbg("serial->type == NULL!");
+ serial = port->serial;
+ if (serial_paranoia_check (serial, "serial_close")) {
return;
}
- if (!serial->port[port].active) {
- dbg ("device not opened");
+
+ dbg("serial_close port %d", port->number);
+
+ if (!port->active) {
+ dbg ("port not opened");
return;
}
/* pass on to the driver specific version of this function if it is available */
if (serial->type->close) {
- serial->type->close(tty, filp);
+ serial->type->close(port, filp);
} else {
- generic_serial_close(tty, filp);
+ generic_close(port, filp);
}
}
static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int port = MINOR(tty->device) - serial->minor;
+ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial *serial;
- dbg("serial_write port %d, %d byte(s)", port, count);
-
- /* do some sanity checking that we really have a device present */
- if (!serial) {
- dbg("serial == NULL!");
- return (-ENODEV);
+ dbg("serial_write");
+
+ if (port_paranoia_check (port, "serial_write")) {
+ return -ENODEV;
}
- if (!serial->type) {
- dbg("serial->type == NULL!");
- return (-ENODEV);
+
+ serial = port->serial;
+ if (serial_paranoia_check (serial, "serial_write")) {
+ return -ENODEV;
}
- if (!serial->port[port].active) {
- dbg ("device not opened");
- return (-EINVAL);
+
+ dbg("serial_write port %d, %d byte(s)", port->number, count);
+
+ if (!port->active) {
+ dbg ("port not opened");
+ return -EINVAL;
}
/* pass on to the driver specific version of this function if it is available */
if (serial->type->write) {
- return (serial->type->write(tty, from_user, buf, count));
+ return (serial->type->write(port, from_user, buf, count));
} else {
- return (generic_serial_write(tty, from_user, buf, count));
+ return (generic_write(port, from_user, buf, count));
}
}
static int serial_write_room (struct tty_struct *tty)
{
- struct usb_serial *serial = (struct usb_serial *)tty->driver_data;
- int port = MINOR(tty->device) - serial->minor;
-
- dbg("serial_write_room port %d", port);
+ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial *serial;
- /* do some sanity checking that we really have a device present */
- if (!serial) {
- dbg("serial == NULL!");
- return (-ENODEV);
+ dbg("serial_write_room");
+
+ if (port_paranoia_check (port, "serial_write")) {
+ return -ENODEV;
}
- if (!serial->type) {
- dbg("serial->type == NULL!");
- return (-ENODEV);
+
+ serial = port->serial;
+ if (serial_paranoia_check (serial, "serial_write")) {
+ return -ENODEV;
}
- if (!serial->port[port].active) {
- dbg ("device not open");
- return (-EINVAL);
+
+ dbg("serial_write_room port %d", port->number);
+
+ if (!port->active) {
+ dbg ("port not open");
+ return -EINVAL;
}
/* pass on to the driver specific version of this function if it is available */
if (serial->type->write_room) {
- return (serial->type->write_room(tty));
+ return (serial->type->write_room(port));
} else {
- return (generic_write_room(tty));
+ return (generic_write_room(port));
}
}
static int serial_chars_in_buffer (struct tty_struct *tty)
{
- struct usb_serial *serial = (struct usb_serial *)tty->driver_data;
- int port = MINOR(tty->device) - serial->minor;
-
- dbg("serial_chars_in_buffer port %d", port);
+ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial *serial;
- /* do some sanity checking that we really have a device present */
- if (!serial) {
- dbg("serial == NULL!");
- return (-ENODEV);
+ dbg("serial_chars_in_buffer");
+
+ if (port_paranoia_check (port, "serial_chars_in_buffer")) {
+ return -ENODEV;
}
- if (!serial->type) {
- dbg("serial->type == NULL!");
- return (-ENODEV);
+
+ serial = port->serial;
+ if (serial_paranoia_check (serial, "serial_chars_in_buffer")) {
+ return -ENODEV;
}
- if (!serial->port[port].active) {
- dbg ("device not open");
- return (-EINVAL);
+
+ if (!port->active) {
+ dbg ("port not open");
+ return -EINVAL;
}
/* pass on to the driver specific version of this function if it is available */
if (serial->type->chars_in_buffer) {
- return (serial->type->chars_in_buffer(tty));
+ return (serial->type->chars_in_buffer(port));
} else {
- return (generic_chars_in_buffer(tty));
+ return (generic_chars_in_buffer(port));
}
}
static void serial_throttle (struct tty_struct * tty)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int port = MINOR(tty->device) - serial->minor;
-
- dbg("serial_throttle port %d", port);
+ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial *serial;
- /* do some sanity checking that we really have a device present */
- if (!serial) {
- dbg("serial == NULL!");
+ dbg("serial_throttle");
+
+ if (port_paranoia_check (port, "serial_throttle")) {
return;
}
- if (!serial->type) {
- dbg("serial->type == NULL!");
+
+ serial = port->serial;
+ if (serial_paranoia_check (serial, "serial_throttle")) {
return;
}
- if (!serial->port[port].active) {
- dbg ("device not open");
+
+ dbg("serial_throttle port %d", port->number);
+
+ if (!port->active) {
+ dbg ("port not open");
return;
}
/* pass on to the driver specific version of this function */
if (serial->type->throttle) {
- serial->type->throttle(tty);
- } else {
- generic_throttle(tty);
+ serial->type->throttle(port);
}
return;
static void serial_unthrottle (struct tty_struct * tty)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int port = MINOR(tty->device) - serial->minor;
-
- dbg("serial_unthrottle port %d", port);
+ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial *serial;
- /* do some sanity checking that we really have a device present */
- if (!serial) {
- dbg("serial == NULL!");
+ dbg("serial_unthrottle");
+
+ if (port_paranoia_check (port, "serial_unthrottle")) {
return;
}
- if (!serial->type) {
- dbg("serial->type == NULL!");
+
+ serial = port->serial;
+ if (serial_paranoia_check (serial, "serial_unthrottle")) {
return;
}
- if (!serial->port[port].active) {
- dbg ("device not open");
+
+ dbg("serial_unthrottle port %d", port->number);
+
+ if (!port->active) {
+ dbg ("port not open");
return;
}
/* pass on to the driver specific version of this function */
if (serial->type->unthrottle) {
- serial->type->unthrottle(tty);
- } else {
- generic_unthrottle(tty);
+ serial->type->unthrottle(port);
}
return;
static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int port;
-
+ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial *serial;
+
dbg("serial_ioctl");
-
- if (!serial) {
- dbg("serial == NULL!");
+
+ if (port_paranoia_check (port, "serial_ioctl")) {
return -ENODEV;
}
- port = MINOR(tty->device) - serial->minor;
-
- dbg("serial_ioctl port %d", port);
-
- /* do some sanity checking that we really have a device present */
- if (!serial->type) {
- dbg("serial->type == NULL!");
+ serial = port->serial;
+ if (serial_paranoia_check (serial, "serial_ioctl")) {
return -ENODEV;
}
- if (!serial->port[port].active) {
- dbg ("device not open");
+
+ dbg("serial_ioctl port %d", port->number);
+
+ if (!port->active) {
+ dbg ("port not open");
return -ENODEV;
}
/* pass on to the driver specific version of this function if it is available */
if (serial->type->ioctl) {
- return (serial->type->ioctl(tty, file, cmd, arg));
+ return (serial->type->ioctl(port, file, cmd, arg));
} else {
- return (generic_ioctl (tty, file, cmd, arg));
+ return -ENOIOCTLCMD;
}
}
static void serial_set_termios (struct tty_struct *tty, struct termios * old)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int port;
-
+ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial *serial;
+
dbg("serial_set_termios");
-
- if (!serial) {
- dbg("serial == NULL!");
+
+ if (port_paranoia_check (port, "serial_set_termios")) {
return;
}
- port = MINOR(tty->device) - serial->minor;
-
- dbg("serial_set_termios port %d", port);
-
- /* do some sanity checking that we really have a device present */
- if (!serial->type) {
- dbg("serial->type == NULL!");
+ serial = port->serial;
+ if (serial_paranoia_check (serial, "serial_set_termios")) {
return;
}
- if (!serial->port[port].active) {
- dbg ("device not open");
+
+ dbg("serial_set_termios port %d", port->number);
+
+ if (!port->active) {
+ dbg ("port not open");
return;
}
/* pass on to the driver specific version of this function if it is available */
if (serial->type->set_termios) {
- serial->type->set_termios(tty, old);
- } else {
- generic_set_termios (tty, old);
+ serial->type->set_termios(port, old);
}
return;
static void serial_break (struct tty_struct *tty, int break_state)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int port;
-
- if (!serial) {
- dbg("serial == NULL!");
+ struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data;
+ struct usb_serial *serial;
+
+ dbg("serial_break");
+
+ if (port_paranoia_check (port, "serial_break")) {
return;
}
- port = MINOR(tty->device) - serial->minor;
-
- dbg("serial_break port %d", port);
-
- /* do some sanity checking that we really have a device present */
- if (!serial->type) {
- dbg("serial->type == NULL!");
+ serial = port->serial;
+ if (serial_paranoia_check (serial, "serial_break")) {
return;
}
- if (!serial->port[port].active) {
- dbg ("device not open");
+
+ dbg("serial_break port %d", port->number);
+
+ if (!port->active) {
+ dbg ("port not open");
return;
}
/* pass on to the driver specific version of this function if it is
available */
if (serial->type->break_ctl) {
- serial->type->break_ctl(tty, break_state);
+ serial->type->break_ctl(port, break_state);
}
}
/*****************************************************************************
* Connect Tech's White Heat specific driver functions
*****************************************************************************/
-static int whiteheat_serial_open (struct tty_struct *tty, struct file *filp)
+static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int portNumber = MINOR(tty->device) - serial->minor;
- struct usb_serial_port *port = &serial->port[portNumber];
-
- dbg("whiteheat_serial_open port %d", portNumber);
+ dbg("whiteheat_open port %d", port->number);
if (port->active) {
dbg ("device already open");
port->active = 1;
/*Start reading from the device*/
- if (usb_submit_urb(&port->read_urb))
+ if (usb_submit_urb(port->read_urb))
dbg("usb_submit_urb(read bulk) failed");
/* Need to do device specific setup here (control lines, baud rate, etc.) */
}
-static void whiteheat_serial_close(struct tty_struct *tty, struct file * filp)
+static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int portNumber = MINOR(tty->device) - serial->minor;
- struct usb_serial_port *port = &serial->port[portNumber];
-
- dbg("whiteheat_serial_close port %d", portNumber);
+ dbg("whiteheat_close port %d", port->number);
/* Need to change the control lines here */
/* FIXME */
/* shutdown our bulk reads and writes */
- usb_unlink_urb (&port->write_urb);
- usb_unlink_urb (&port->read_urb);
+ usb_unlink_urb (port->write_urb);
+ usb_unlink_urb (port->read_urb);
port->active = 0;
}
-static void whiteheat_set_termios (struct tty_struct *tty, struct termios *old_termios)
+static void whiteheat_set_termios (struct usb_serial_port *port, struct termios *old_termios)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int port = MINOR(tty->device) - serial->minor;
- unsigned int cflag = tty->termios->c_cflag;
+ unsigned int cflag = port->tty->termios->c_cflag;
- dbg("whiteheat_set_termios port %d", port);
+ dbg("whiteheat_set_termios port %d", port->number);
/* check that they really want us to change something */
if (old_termios) {
if ((cflag == old_termios->c_cflag) &&
- (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
+ (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
dbg("nothing to change...");
return;
}
return;
}
-static void whiteheat_throttle (struct tty_struct * tty)
+static void whiteheat_throttle (struct usb_serial_port *port)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int port = MINOR(tty->device) - serial->minor;
-
- dbg("whiteheat_throttle port %d", port);
+ dbg("whiteheat_throttle port %d", port->number);
/* Change the control signals */
/* FIXME!!! */
}
-static void whiteheat_unthrottle (struct tty_struct * tty)
+static void whiteheat_unthrottle (struct usb_serial_port *port)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int port = MINOR(tty->device) - serial->minor;
-
- dbg("whiteheat_unthrottle port %d", port);
+ dbg("whiteheat_unthrottle port %d", port->number);
/* Change the control signals */
/* FIXME!!! */
/******************************************************************************
* Handspring Visor specific driver functions
******************************************************************************/
-static int visor_serial_open (struct tty_struct *tty, struct file *filp)
+static int visor_open (struct usb_serial_port *port, struct file *filp)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int portNumber = MINOR(tty->device) - serial->minor;
- struct usb_serial_port *port = &serial->port[portNumber];
-
- dbg("visor_serial_open port %d", portNumber);
+ dbg("visor_open port %d", port->number);
if (port->active) {
dbg ("device already open");
port->active = 1;
/*Start reading from the device*/
- if (usb_submit_urb(&port->read_urb))
+ if (usb_submit_urb(port->read_urb))
dbg("usb_submit_urb(read bulk) failed");
return (0);
}
-static void visor_serial_close(struct tty_struct *tty, struct file * filp)
+
+static void visor_close (struct usb_serial_port *port, struct file * filp)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int portNumber = MINOR(tty->device) - serial->minor;
- struct usb_serial_port *port = &serial->port[portNumber];
+ struct usb_serial *serial = port->serial;
unsigned char *transfer_buffer = kmalloc (0x12, GFP_KERNEL);
- dbg("visor_serial_close port %d", portNumber);
+ dbg("visor_close port %d", port->number);
if (!transfer_buffer) {
- err("visor_serial_close: kmalloc(%d) failed.", 0x12);
+ err("visor_close: kmalloc(%d) failed.", 0x12);
} else {
/* send a shutdown message to the device */
usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_CLOSE_NOTIFICATION,
}
/* shutdown our bulk reads and writes */
- usb_unlink_urb (&port->write_urb);
- usb_unlink_urb (&port->read_urb);
+ usb_unlink_urb (port->write_urb);
+ usb_unlink_urb (port->read_urb);
port->active = 0;
}
-static void visor_throttle (struct tty_struct * tty)
+static void visor_throttle (struct usb_serial_port *port)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int port = MINOR(tty->device) - serial->minor;
-
- dbg("visor_throttle port %d", port);
+ dbg("visor_throttle port %d", port->number);
- usb_unlink_urb (&serial->port[port].read_urb);
+ usb_unlink_urb (port->read_urb);
return;
}
-static void visor_unthrottle (struct tty_struct * tty)
+static void visor_unthrottle (struct usb_serial_port *port)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int port = MINOR(tty->device) - serial->minor;
+ dbg("visor_unthrottle port %d", port->number);
- dbg("visor_unthrottle port %d", port);
-
- if (usb_unlink_urb (&serial->port[port].read_urb))
+ if (usb_unlink_urb (port->read_urb))
dbg("usb_submit_urb(read bulk) failed");
return;
#include "ftdi_sio.h"
-static int ftdi_sio_serial_open (struct tty_struct *tty, struct file *filp)
+static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int portNumber = MINOR(tty->device) - serial->minor;
- struct usb_serial_port *port = &serial->port[portNumber];
+ struct usb_serial *serial = port->serial;
char buf[1]; /* Needed for the usb_control_msg I think */
- dbg("ftdi_sio_serial_open port %d", portNumber);
+ dbg("ftdi_sio_open port %d", port->number);
if (port->active) {
- dbg ("device already open");
+ dbg ("port already open");
return -EINVAL;
}
port->active = 1;
}
/*Start reading from the device*/
- if (usb_submit_urb(&port->read_urb))
+ if (usb_submit_urb(port->read_urb))
dbg("usb_submit_urb(read bulk) failed");
return (0);
}
-static void ftdi_sio_serial_close (struct tty_struct *tty, struct file *filp)
+static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int portNumber = MINOR(tty->device) - serial->minor;
- struct usb_serial_port *port = &serial->port[portNumber];
+ struct usb_serial *serial = port->serial;
char buf[1];
- dbg("ftdi_sio_serial_close port %d", portNumber);
+ dbg("ftdi_sio_close port %d", port->number);
/* FIXME - might be able to do both simultaneously */
if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
/* FIXME Should I flush the device here? - not doing it for now */
/* shutdown our bulk reads and writes */
- usb_unlink_urb (&port->write_urb);
- usb_unlink_urb (&port->read_urb);
+ usb_unlink_urb (port->write_urb);
+ usb_unlink_urb (port->read_urb);
port->active = 0;
}
B1 0
B2..7 length of message excluding byte 0
*/
-static int ftdi_sio_serial_write (struct tty_struct * tty, int from_user,
- const unsigned char *buf, int count)
+static int ftdi_sio_write (struct usb_serial_port *port, int from_user,
+ const unsigned char *buf, int count)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int portNumber = MINOR(tty->device) - serial->minor;
- struct usb_serial_port *port = &serial->port[portNumber];
+ struct usb_serial *serial = port->serial;
const int data_offset = 1;
- dbg("ftdi_sio_serial_write port %d, %d bytes", portNumber, count);
+ dbg("ftdi_sio_serial_write port %d, %d bytes", port->number, count);
if (count == 0) {
dbg("write request of 0 bytes");
/* only do something if we have a bulk out endpoint */
if (serial->num_bulk_out) {
- unsigned char *first_byte = port->write_urb.transfer_buffer;
+ unsigned char *first_byte = port->write_urb->transfer_buffer;
- if (port->write_urb.status == -EINPROGRESS) {
+ if (port->write_urb->status == -EINPROGRESS) {
dbg ("already writing");
return 0;
}
/* Copy in the data to send */
if (from_user) {
- copy_from_user(port->write_urb.transfer_buffer + data_offset ,
+ copy_from_user(port->write_urb->transfer_buffer + data_offset ,
buf, count - data_offset );
}
else {
- memcpy(port->write_urb.transfer_buffer + data_offset,
+ memcpy(port->write_urb->transfer_buffer + data_offset,
buf, count - data_offset );
}
/* Write the control byte at the front of the packet*/
- first_byte = port->write_urb.transfer_buffer;
+ first_byte = port->write_urb->transfer_buffer;
*first_byte = 1 | ((count-data_offset) << 2) ;
#ifdef DEBUG
#endif
/* send the data out the bulk port */
- port->write_urb.transfer_buffer_length = count;
+ port->write_urb->transfer_buffer_length = count;
- if (usb_submit_urb(&port->write_urb))
+ if (usb_submit_urb(port->write_urb))
dbg("usb_submit_urb(write bulk) failed");
dbg("write returning: %d", count - data_offset);
static void ftdi_sio_read_bulk_callback (struct urb *urb)
{ /* ftdi_sio_serial_buld_callback */
- struct usb_serial *serial = (struct usb_serial *)urb->context;
- struct tty_struct *tty = serial->tty;
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct usb_serial *serial;
+ struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
const int data_offset = 2;
int i;
dbg("ftdi_sio_read_bulk_callback");
+ if (port_paranoia_check (port, "ftdi_sio_read_bulk_callback")) {
+ return;
+ }
+
+ serial = port->serial;
+ if (serial_paranoia_check (serial, "ftdi_sio_read_bulk_callback")) {
+ return;
+ }
+
if (urb->status) {
dbg("nonzero read bulk status received: %d", urb->status);
return;
if (urb->actual_length > data_offset) {
+ tty = port->tty;
for (i = data_offset ; i < urb->actual_length ; ++i) {
tty_insert_flip_char(tty, data[i], 0);
}
} /* ftdi_sio_serial_read_bulk_callback */
-static void ftdi_sio_set_termios (struct tty_struct *tty, struct termios *old_termios)
+static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *old_termios)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int port = MINOR(tty->device) - serial->minor;
- unsigned int cflag = tty->termios->c_cflag;
+ struct usb_serial *serial = port->serial;
+ unsigned int cflag = port->tty->termios->c_cflag;
__u16 urb_value; /* Will hold the new flags */
char buf[1]; /* Perhaps I should dynamically alloc this? */
- dbg("ftdi_sio_set_termios port %d", port);
+
+ dbg("ftdi_sio_set_termios port %d", port->number);
/* FIXME - we should keep the old termios really */
/* FIXME -For this cut I don't care if the line is really changing or
/*FIXME - the beginnings of this implementation - not even hooked into the driver yet */
-static int ftdi_sio_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
+static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int port = MINOR(tty->device) - serial->minor;
+ struct usb_serial *serial = port->serial;
__u16 urb_value=0; /* Will hold the new flags */
char buf[1];
int ret, mask;
- dbg("ftdi_sio_ioctl port %d", port);
+
+ dbg("ftdi_sio_ioctl port %d", port->number);
/* Based on code from acm.c */
switch (cmd) {
static void keyspan_pda_rx_interrupt (struct urb *urb)
{
- struct usb_serial *serial = (struct usb_serial *) urb->context;
- struct tty_struct *tty = serial->tty;
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct usb_serial *serial;
+ struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int i;
if (urb->status)
return;
- /* see if the message is data or a status interrupt */
+ if (port_paranoia_check (port, "keyspan_pda_rx_interrupt")) {
+ return;
+ }
+
+ serial = port->serial;
+ if (serial_paranoia_check (serial, "keyspan_pda_rx_interrupt")) {
+ return;
+ }
+
+ /* see if the message is data or a status interrupt */
switch (data[0]) {
case 0:
/* rest of message is rx data */
if (urb->actual_length) {
+ tty = serial->port[0].tty;
for (i = 1; i < urb->actual_length ; ++i) {
tty_insert_flip_char(tty, data[i], 0);
}
case 1: /* modemline change */
break;
case 2: /* tx unthrottle interrupt */
+ tty = serial->port[0].tty;
serial->tx_throttled = 0;
wake_up(&serial->write_wait); /* wake up writer */
wake_up(&tty->write_wait); /* them too */
}
-static void keyspan_pda_rx_throttle (struct tty_struct *tty)
+static void keyspan_pda_rx_throttle (struct usb_serial_port *port)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int port = MINOR(tty->device) - serial->minor;
-
/* stop receiving characters. We just turn off the URB request, and
let chars pile up in the device. If we're doing hardware
flowcontrol, the device will signal the other end when its buffer
send an XOFF, although it might make sense to foist that off
upon the device too. */
- dbg("keyspan_pda_rx_throttle port %d", port);
- usb_unlink_urb(&serial->port[port].read_urb);
+ dbg("keyspan_pda_rx_throttle port %d", port->number);
+ usb_unlink_urb(port->read_urb);
}
-static void keyspan_pda_rx_unthrottle (struct tty_struct *tty)
+static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int port = MINOR(tty->device) - serial->minor;
-
/* just restart the receive interrupt URB */
- dbg("keyspan_pda_rx_unthrottle port %d", port);
- if (usb_submit_urb(&serial->port[port].read_urb))
+ dbg("keyspan_pda_rx_unthrottle port %d", port->number);
+ if (usb_submit_urb(port->read_urb))
dbg(" usb_submit_urb(read urb) failed");
return;
}
}
-static void keyspan_pda_break_ctl (struct tty_struct *tty, int break_state)
+static void keyspan_pda_break_ctl (struct usb_serial_port *port, int break_state)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ struct usb_serial *serial = port->serial;
int value;
if (break_state == -1)
value = 1; /* start break */
}
-static void keyspan_pda_set_termios (struct tty_struct *tty,
+static void keyspan_pda_set_termios (struct usb_serial_port *port,
struct termios *old_termios)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- unsigned int cflag = tty->termios->c_cflag;
+ struct usb_serial *serial = port->serial;
+ unsigned int cflag = port->tty->termios->c_cflag;
/* cflag specifies lots of stuff: number of stop bits, parity, number
of data bits, baud. What can the device actually handle?:
}
-static int keyspan_pda_ioctl(struct tty_struct *tty, struct file *file,
+static int keyspan_pda_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+ struct usb_serial *serial = port->serial;
int rc;
unsigned int value;
unsigned char status, mask;
return -ENOIOCTLCMD;
}
-static int keyspan_pda_write(struct tty_struct * tty, int from_user,
+static int keyspan_pda_write(struct usb_serial_port *port, int from_user,
const unsigned char *buf, int count)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int port = MINOR(tty->device) - serial->minor;
+ struct usb_serial *serial = port->serial;
int request_unthrottle = 0;
int rc = 0;
DECLARE_WAITQUEUE(wait, current);
the TX urb is in-flight (wait until it completes)
the device is full (wait until it says there is room)
*/
- while (serial->port[port].write_urb.status == -EINPROGRESS) {
+ while (port->write_urb->status == -EINPROGRESS) {
if (0 /* file->f_flags & O_NONBLOCK */) {
rc = -EAGAIN;
goto err;
remove_wait_queue(&serial->write_wait, &wait);
set_current_state(TASK_RUNNING);
- count = (count > serial->port[port].bulk_out_size) ?
- serial->port[port].bulk_out_size : count;
+ count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
if (count > serial->tx_room) {
unsigned char room;
/* Looks like we might overrun the Tx buffer. Ask the device
if (count) {
/* now transfer data */
if (from_user) {
- copy_from_user(serial->port[port].write_urb.transfer_buffer,
- buf, count);
+ copy_from_user(port->write_urb->transfer_buffer, buf, count);
}
else {
- memcpy (serial->port[port].write_urb.transfer_buffer,
- buf, count);
+ memcpy (port->write_urb->transfer_buffer, buf, count);
}
/* send the data out the bulk port */
- serial->port[port].write_urb.transfer_buffer_length = count;
+ port->write_urb->transfer_buffer_length = count;
- if (usb_submit_urb(&serial->port[port].write_urb))
+ if (usb_submit_urb(port->write_urb))
dbg(" usb_submit_urb(write bulk) failed");
}
else {
static void keyspan_pda_write_bulk_callback (struct urb *urb)
{
- struct usb_serial *serial = (struct usb_serial *) urb->context;
- struct tty_struct *tty = serial->tty;
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct usb_serial *serial;
+ struct tty_struct *tty;
+ if (port_paranoia_check (port, "keyspan_pda_rx_interrupt")) {
+ return;
+ }
+
+ serial = port->serial;
+ if (serial_paranoia_check (serial, "keyspan_pda_rx_interrupt")) {
+ return;
+ }
+
wake_up_interruptible(&serial->write_wait);
+ tty = port->tty;
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
tty->ldisc.write_wakeup)
(tty->ldisc.write_wakeup)(tty);
}
-static int keyspan_pda_write_room (struct tty_struct *tty)
+static int keyspan_pda_write_room (struct usb_serial_port *port)
{
- struct usb_serial *serial = (struct usb_serial *)tty->driver_data;
+ struct usb_serial *serial = port->serial;
/* used by n_tty.c for processing of tabs and such. Giving it our
conservative guess is probably good enough, but needs testing by
}
-static int keyspan_pda_chars_in_buffer (struct tty_struct *tty)
+static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port)
{
- struct usb_serial *serial = (struct usb_serial *)tty->driver_data;
+ struct usb_serial *serial = port->serial;
/* when throttled, return at least WAKEUP_CHARS to tell select() (via
n_tty.c:normal_poll() ) that we're not writeable. */
}
-static int keyspan_pda_serial_open (struct tty_struct *tty, struct file *filp)
+static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int portNumber = MINOR(tty->device) - serial->minor;
- struct usb_serial_port *port = &serial->port[portNumber];
+ struct usb_serial *serial = port->serial;
unsigned char room;
int rc;
/* the normal serial device seems to always turn on DTR and RTS here,
so do the same */
- if (tty->termios->c_cflag & CBAUD)
+ if (port->tty->termios->c_cflag & CBAUD)
keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2) );
else
keyspan_pda_set_modem_info(serial, 0);
/*Start reading from the device*/
- if (usb_submit_urb(&port->read_urb))
+ if (usb_submit_urb(port->read_urb))
dbg(" usb_submit_urb(read int) failed");
return (0);
}
-static void keyspan_pda_serial_close(struct tty_struct *tty,
- struct file *filp)
+static void keyspan_pda_close(struct usb_serial_port *port, struct file *filp)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int portNumber = MINOR(tty->device) - serial->minor;
- struct usb_serial_port *port = &serial->port[portNumber];
+ struct usb_serial *serial = port->serial;
/* the normal serial device seems to always shut off DTR and RTS now */
- if (tty->termios->c_cflag & HUPCL)
+ if (port->tty->termios->c_cflag & HUPCL)
keyspan_pda_set_modem_info(serial, 0);
/* shutdown our bulk reads and writes */
- usb_unlink_urb (&port->write_urb);
- usb_unlink_urb (&port->read_urb);
+ usb_unlink_urb (port->write_urb);
+ usb_unlink_urb (port->read_urb);
port->active = 0;
}
intin = serial->port[0].interrupt_in_endpoint;
/* set up the receive interrupt urb */
- FILL_INT_URB(&serial->port[0].read_urb, serial->dev,
+ FILL_INT_URB(serial->port[0].read_urb, serial->dev,
usb_rcvintpipe(serial->dev, intin->bEndpointAddress),
serial->port[0].interrupt_in_buffer,
intin->wMaxPacketSize,
/*****************************************************************************
* generic devices specific driver functions
*****************************************************************************/
-static int generic_serial_open (struct tty_struct *tty, struct file *filp)
+static int generic_open (struct usb_serial_port *port, struct file *filp)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int portNumber = MINOR(tty->device) - serial->minor;
- struct usb_serial_port *port = &serial->port[portNumber];
+ struct usb_serial *serial = port->serial;
- dbg("generic_serial_open port %d", portNumber);
+ dbg("generic_open port %d", port->number);
if (port->active) {
dbg ("device already open");
/* if we have a bulk interrupt, start reading from it */
if (serial->num_bulk_in) {
/*Start reading from the device*/
- if (usb_submit_urb(&port->read_urb))
+ if (usb_submit_urb(port->read_urb))
dbg("usb_submit_urb(read bulk) failed");
}
}
-static void generic_serial_close(struct tty_struct *tty, struct file * filp)
+static void generic_close (struct usb_serial_port *port, struct file * filp)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int portNumber = MINOR(tty->device) - serial->minor;
- struct usb_serial_port *port = &serial->port[portNumber];
+ struct usb_serial *serial = port->serial;
- dbg("generic_serial_close port %d", portNumber);
+ dbg("generic_close port %d", port->number);
/* shutdown any bulk reads that might be going on */
if (serial->num_bulk_out) {
- usb_unlink_urb (&port->write_urb);
+ usb_unlink_urb (port->write_urb);
}
if (serial->num_bulk_in) {
- usb_unlink_urb (&port->read_urb);
+ usb_unlink_urb (port->read_urb);
}
port->active = 0;
}
-static int generic_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
+static int generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
{
- struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
- int portNumber = MINOR(tty->device) - serial->minor;
- struct usb_serial_port *port = &serial->port[portNumber];
+ struct usb_serial *serial = port->serial;
- dbg("generic_serial_write port %d", portNumber);
+ dbg("generic_serial_write port %d", port->number);
if (count == 0) {
dbg("write request of 0 bytes");
/* only do something if we have a bulk out endpoint */
if (serial->num_bulk_out) {
- if (port->write_urb.status == -EINPROGRESS) {
+ if (port->write_urb->status == -EINPROGRESS) {
dbg ("already writing");
return (0);
}
count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
if (from_user) {
- copy_from_user(port->write_urb.transfer_buffer, buf, count);
+ copy_from_user(port->write_urb->transfer_buffer, buf, count);
}
else {
- memcpy (port->write_urb.transfer_buffer, buf, count);
+ memcpy (port->write_urb->transfer_buffer, buf, count);
}
/* send the data out the bulk port */
- port->write_urb.transfer_buffer_length = count;
+ port->write_urb->transfer_buffer_length = count;
- if (usb_submit_urb(&port->write_urb))
+ if (usb_submit_urb(port->write_urb))
dbg("usb_submit_urb(write bulk) failed");
return (count);
}
-static int generic_write_room (struct tty_struct *tty)
+static int generic_write_room (struct usb_serial_port *port)
{
- struct usb_serial *serial = (struct usb_serial *)tty->driver_data;
- int portNumber = MINOR(tty->device) - serial->minor;
- struct usb_serial_port *port = &serial->port[portNumber];
+ struct usb_serial *serial = port->serial;
int room;
- dbg("generic_write_room port %d", portNumber);
+ dbg("generic_write_room port %d", port->number);
if (serial->num_bulk_out) {
- if (port->write_urb.status == -EINPROGRESS)
+ if (port->write_urb->status == -EINPROGRESS)
room = 0;
else
room = port->bulk_out_size;
}
-static int generic_chars_in_buffer (struct tty_struct *tty)
+static int generic_chars_in_buffer (struct usb_serial_port *port)
{
- struct usb_serial *serial = (struct usb_serial *)tty->driver_data;
- int portNumber = MINOR(tty->device) - serial->minor;
- struct usb_serial_port *port = &serial->port[portNumber];
+ struct usb_serial *serial = port->serial;
- dbg("generic_chars_in_buffer port %d", portNumber);
+ dbg("generic_chars_in_buffer port %d", port->number);
if (serial->num_bulk_out) {
- if (port->write_urb.status == -EINPROGRESS) {
+ if (port->write_urb->status == -EINPROGRESS) {
return (port->bulk_out_size);
}
}
}
-static void generic_throttle (struct tty_struct *tty)
-{
- /* do nothing for the generic device */
- return;
-}
-
-
-static void generic_unthrottle (struct tty_struct *tty)
-{
- /* do nothing for the generic device */
- return;
-}
-
-
-static int generic_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
-{
- /* generic driver doesn't support any ioctls yet */
- return -ENOIOCTLCMD;
-}
-
-
-static void generic_set_termios (struct tty_struct *tty, struct termios * old)
-{
- /* generic driver doesn't really care about setting any line settings */
- return;
-}
-
-
static void generic_read_bulk_callback (struct urb *urb)
{
- struct usb_serial *serial = (struct usb_serial *)urb->context;
- struct tty_struct *tty = serial->tty;
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct usb_serial *serial;
+ struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int i;
dbg("generic_read_bulk_callback");
+ if (port_paranoia_check (port, "generic_read_bulk_callback")) {
+ return;
+ }
+
+ serial = port->serial;
+ if (serial_paranoia_check (serial, "generic_read_bulk_callback")) {
+ return;
+ }
+
if (urb->status) {
dbg("nonzero read bulk status received: %d", urb->status);
return;
printk ("\n");
}
#endif
-
+
+ tty = port->tty;
if (urb->actual_length) {
for (i = 0; i < urb->actual_length ; ++i) {
tty_insert_flip_char(tty, data[i], 0);
static void generic_write_bulk_callback (struct urb *urb)
{
- struct usb_serial *serial = (struct usb_serial *) urb->context;
- struct tty_struct *tty = serial->tty;
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct usb_serial *serial;
+ struct tty_struct *tty;
dbg("generic_write_bulk_callback");
+ if (port_paranoia_check (port, "generic_write_bulk_callback")) {
+ return;
+ }
+
+ serial = port->serial;
+ if (serial_paranoia_check (serial, "generic_write_bulk_callback")) {
+ return;
+ }
+
if (urb->status) {
dbg("nonzero write bulk status received: %d", urb->status);
return;
}
+ tty = port->tty;
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
(tty->ldisc.write_wakeup)(tty);
}
-
static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
{
struct usb_serial *serial = NULL;
/* set up the endpoint information */
for (i = 0; i < num_bulk_in; ++i) {
port = &serial->port[i];
+ port->read_urb = usb_alloc_urb (0);
+ if (!port->read_urb) {
+ err("No free urbs available");
+ goto probe_error;
+ }
buffer_size = bulk_in_endpoint[i]->wMaxPacketSize;
port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
if (!port->bulk_in_buffer) {
goto probe_error;
}
if (serial->type->read_bulk_callback) {
- FILL_BULK_URB(&port->read_urb, dev, usb_rcvbulkpipe (dev, bulk_in_endpoint[i]->bEndpointAddress),
- port->bulk_in_buffer, buffer_size, serial->type->read_bulk_callback, serial);
+ FILL_BULK_URB(port->read_urb, dev, usb_rcvbulkpipe (dev, bulk_in_endpoint[i]->bEndpointAddress),
+ port->bulk_in_buffer, buffer_size, serial->type->read_bulk_callback, port);
} else {
- FILL_BULK_URB(&port->read_urb, dev, usb_rcvbulkpipe (dev, bulk_in_endpoint[i]->bEndpointAddress),
- port->bulk_in_buffer, buffer_size, generic_read_bulk_callback, serial);
+ FILL_BULK_URB(port->read_urb, dev, usb_rcvbulkpipe (dev, bulk_in_endpoint[i]->bEndpointAddress),
+ port->bulk_in_buffer, buffer_size, generic_read_bulk_callback, port);
}
}
for (i = 0; i < num_bulk_out; ++i) {
port = &serial->port[i];
+ port->write_urb = usb_alloc_urb(0);
+ if (!port->write_urb) {
+ err("No free urbs available");
+ goto probe_error;
+ }
port->bulk_out_size = bulk_out_endpoint[i]->wMaxPacketSize;
port->bulk_out_buffer = kmalloc (port->bulk_out_size, GFP_KERNEL);
if (!port->bulk_out_buffer) {
goto probe_error;
}
if (serial->type->write_bulk_callback) {
- FILL_BULK_URB(&port->write_urb, dev, usb_sndbulkpipe (dev, bulk_out_endpoint[i]->bEndpointAddress),
- port->bulk_out_buffer, port->bulk_out_size, serial->type->write_bulk_callback, serial);
+ FILL_BULK_URB(port->write_urb, dev, usb_sndbulkpipe (dev, bulk_out_endpoint[i]->bEndpointAddress),
+ port->bulk_out_buffer, port->bulk_out_size, serial->type->write_bulk_callback, port);
} else {
- FILL_BULK_URB(&port->write_urb, dev, usb_sndbulkpipe (dev, bulk_out_endpoint[i]->bEndpointAddress),
- port->bulk_out_buffer, port->bulk_out_size, generic_write_bulk_callback, serial);
+ FILL_BULK_URB(port->write_urb, dev, usb_sndbulkpipe (dev, bulk_out_endpoint[i]->bEndpointAddress),
+ port->bulk_out_buffer, port->bulk_out_size, generic_write_bulk_callback, port);
}
}
#if 0 /* use this code when WhiteHEAT is up and running */
for (i = 0; i < num_interrupt_in; ++i) {
+ port = &serial->port[i];
+ port->control_urb = usb_alloc_urb(0);
+ if (!port->control_urb) {
+ err("No free urbs available");
+ goto probe_error;
+ }
buffer_size = interrupt_in_endpoint[i]->wMaxPacketSize;
- serial->interrupt_in_buffer[i] = kmalloc (buffer_size, GFP_KERNEL);
- if (!serial->interrupt_in_buffer[i]) {
+ port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+ if (!port->interrupt_in_buffer) {
err("Couldn't allocate interrupt_in_buffer");
goto probe_error;
}
- FILL_INT_URB(&serial->control_urb[i], dev, usb_rcvintpipe (dev, interrupt_in_endpoint[i]->bEndpointAddress),
- serial->interrupt_in_buffer[i], buffer_size, serial_control_irq,
- serial, interrupt_in_endpoint[i]->bInterval);
+ FILL_INT_URB(port->control_urb, dev, usb_rcvintpipe (dev, interrupt_in_endpoint[i]->bEndpointAddress),
+ port->interrupt_in_buffer, buffer_size, serial_control_irq,
+ port, interrupt_in_endpoint[i]->bInterval);
}
#endif
probe_error:
if (serial) {
- for (i = 0; i < num_bulk_in; ++i)
+ for (i = 0; i < num_bulk_in; ++i) {
+ port = &serial->port[i];
+ if (port->read_urb)
+ usb_free_urb (port->read_urb);
if (serial->port[i].bulk_in_buffer[i])
kfree (serial->port[i].bulk_in_buffer);
- for (i = 0; i < num_bulk_out; ++i)
+ }
+ for (i = 0; i < num_bulk_out; ++i) {
+ port = &serial->port[i];
+ if (port->write_urb)
+ usb_free_urb (port->write_urb);
if (serial->port[i].bulk_out_buffer)
kfree (serial->port[i].bulk_out_buffer);
- for (i = 0; i < num_interrupt_in; ++i)
+ }
+ for (i = 0; i < num_interrupt_in; ++i) {
+ port = &serial->port[i];
+ if (port->control_urb)
+ usb_free_urb (port->control_urb);
if (serial->port[i].interrupt_in_buffer)
kfree (serial->port[i].interrupt_in_buffer);
+ }
/* return the minor range that this device had */
return_serial (serial);
int i;
if (serial) {
- /* need to stop any transfers...*/
- for (i = 0; i < serial->num_ports; ++i) {
- port = &serial->port[i];
- usb_unlink_urb (&port->write_urb);
- usb_unlink_urb (&port->read_urb);
- port->active = 0;
- }
+ for (i = 0; i < serial->num_ports; ++i)
+ serial->port[i].active = 0;
- /* free up any memory that we allocated */
for (i = 0; i < serial->num_bulk_in; ++i) {
port = &serial->port[i];
+ if (port->read_urb) {
+ usb_unlink_urb (port->read_urb);
+ usb_free_urb (port->read_urb);
+ }
if (port->bulk_in_buffer)
kfree (port->bulk_in_buffer);
}
for (i = 0; i < serial->num_bulk_out; ++i) {
port = &serial->port[i];
+ if (port->write_urb) {
+ usb_unlink_urb (port->write_urb);
+ usb_free_urb (port->write_urb);
+ }
if (port->bulk_out_buffer)
kfree (port->bulk_out_buffer);
}
for (i = 0; i < serial->num_interrupt_in; ++i) {
port = &serial->port[i];
+ if (port->control_urb) {
+ usb_unlink_urb (port->control_urb);
+ usb_free_urb (port->control_urb);
+ }
if (port->interrupt_in_buffer)
kfree (port->interrupt_in_buffer);
}
static struct tty_driver serial_tty_driver = {
magic: TTY_DRIVER_MAGIC,
driver_name: "usb",
- name: "ttyUSB",
+ name: "ttyUSB%d",
major: SERIAL_TTY_MAJOR,
minor_start: 0,
num: SERIAL_TTY_MINORS,
#define MAX_NUM_PORTS 8 /* The maximum number of ports one device can grab at once */
+#define USB_SERIAL_MAGIC 0x6702 /* magic number for usb_serial struct */
+#define USB_SERIAL_PORT_MAGIC 0x7301 /* magic number for usb_serial_port struct */
+
struct usb_serial_port {
+ int magic;
struct usb_serial *serial; /* pointer back to the owner of this port */
struct tty_struct * tty; /* the coresponding tty for this device */
unsigned char minor;
struct usb_endpoint_descriptor * interrupt_in_endpoint;
__u8 interrupt_in_interval;
unsigned char * interrupt_in_buffer;
- struct urb control_urb;
+ struct urb * control_urb;
unsigned char * bulk_in_buffer;
- struct urb read_urb;
+ struct urb * read_urb;
unsigned char * bulk_out_buffer;
int bulk_out_size;
- struct urb write_urb;
+ struct urb * write_urb;
void * private; /* data private to the specific driver */
};
struct usb_serial {
+ int magic;
struct usb_device * dev;
struct usb_serial_device_type * type;
- struct tty_struct * tty; /* the coresponding tty for this device */
unsigned char minor;
unsigned char num_ports; /* the number of ports this device has */
char num_interrupt_in; /* number of interrupt in endpoints we have */
int (*startup) (struct usb_serial *serial); /* return 0 to continue initialization, anything else to abort */
/* serial function calls */
- int (*open)(struct tty_struct * tty, struct file * filp);
- void (*close)(struct tty_struct * tty, struct file * filp);
- int (*write)(struct tty_struct * tty, int from_user,const unsigned char *buf, int count);
- int (*write_room)(struct tty_struct *tty);
- int (*ioctl)(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg);
- void (*set_termios)(struct tty_struct *tty, struct termios * old);
- void (*break_ctl)(struct tty_struct *tty, int break_state);
- int (*chars_in_buffer)(struct tty_struct *tty);
- void (*throttle)(struct tty_struct * tty);
- void (*unthrottle)(struct tty_struct * tty);
+ int (*open) (struct usb_serial_port *port, struct file * filp);
+ void (*close) (struct usb_serial_port *port, struct file * filp);
+ int (*write) (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
+ int (*write_room) (struct usb_serial_port *port);
+ int (*ioctl) (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
+ void (*set_termios) (struct usb_serial_port *port, struct termios * old);
+ void (*break_ctl) (struct usb_serial_port *port, int break_state);
+ int (*chars_in_buffer) (struct usb_serial_port *port);
+ void (*throttle) (struct usb_serial_port *port);
+ void (*unthrottle) (struct usb_serial_port *port);
void (*read_bulk_callback)(struct urb *urb);
void (*write_bulk_callback)(struct urb *urb);
/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */
/* need to always compile these in, as some of the other devices use these functions as their own. */
/* if a driver does not provide a function pointer, the generic function will be called. */
-static int generic_serial_open (struct tty_struct *tty, struct file *filp);
-static void generic_serial_close (struct tty_struct *tty, struct file *filp);
-static int generic_serial_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
-static int generic_write_room (struct tty_struct *tty);
-static int generic_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg);
-static void generic_set_termios (struct tty_struct *tty, struct termios * old);
-static int generic_chars_in_buffer (struct tty_struct *tty);
-static void generic_throttle (struct tty_struct *tty);
-static void generic_unthrottle (struct tty_struct *tty);
+static int generic_open (struct usb_serial_port *port, struct file *filp);
+static void generic_close (struct usb_serial_port *port, struct file *filp);
+static int generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
+static int generic_write_room (struct usb_serial_port *port);
+static int generic_chars_in_buffer (struct usb_serial_port *port);
static void generic_read_bulk_callback (struct urb *urb);
static void generic_write_bulk_callback (struct urb *urb);
#ifdef CONFIG_USB_SERIAL_WHITEHEAT
/* function prototypes for the Connect Tech WhiteHEAT serial converter */
-static int whiteheat_serial_open (struct tty_struct *tty, struct file *filp);
-static void whiteheat_serial_close (struct tty_struct *tty, struct file *filp);
-static void whiteheat_set_termios (struct tty_struct *tty, struct termios * old);
-static void whiteheat_throttle (struct tty_struct *tty);
-static void whiteheat_unthrottle (struct tty_struct *tty);
+static int whiteheat_open (struct usb_serial_port *port, struct file *filp);
+static void whiteheat_close (struct usb_serial_port *port, struct file *filp);
+static void whiteheat_set_termios (struct usb_serial_port *port, struct termios * old);
+static void whiteheat_throttle (struct usb_serial_port *port);
+static void whiteheat_unthrottle (struct usb_serial_port *port);
static int whiteheat_startup (struct usb_serial *serial);
/* All of the device info needed for the Connect Tech WhiteHEAT */
num_interrupt_in: NUM_DONT_CARE,
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
+ num_ports: 1,
startup: whiteheat_startup
};
static struct usb_serial_device_type whiteheat_device = {
num_bulk_in: NUM_DONT_CARE,
num_bulk_out: NUM_DONT_CARE,
num_ports: 4,
- open: whiteheat_serial_open,
- close: whiteheat_serial_close,
+ open: whiteheat_open,
+ close: whiteheat_close,
throttle: whiteheat_throttle,
unthrottle: whiteheat_unthrottle,
set_termios: whiteheat_set_termios,
/* function prototypes for a handspring visor */
-static int visor_serial_open (struct tty_struct *tty, struct file *filp);
-static void visor_serial_close (struct tty_struct *tty, struct file *filp);
-static void visor_throttle (struct tty_struct *tty);
-static void visor_unthrottle (struct tty_struct *tty);
-static int visor_startup (struct usb_serial *serial);
+static int visor_open (struct usb_serial_port *port, struct file *filp);
+static void visor_close (struct usb_serial_port *port, struct file *filp);
+static void visor_throttle (struct usb_serial_port *port);
+static void visor_unthrottle (struct usb_serial_port *port);
+static int visor_startup (struct usb_serial *serial);
/* All of the device info needed for the Handspring Visor */
static __u16 handspring_vendor_id = HANDSPRING_VENDOR_ID;
num_bulk_in: 2,
num_bulk_out: 2,
num_ports: 2,
- open: visor_serial_open,
- close: visor_serial_close,
+ open: visor_open,
+ close: visor_close,
throttle: visor_throttle,
unthrottle: visor_unthrottle,
startup: visor_startup,
#ifdef CONFIG_USB_SERIAL_FTDI_SIO
/* function prototypes for a FTDI serial converter */
-static int ftdi_sio_serial_open (struct tty_struct *tty, struct file *filp);
-static void ftdi_sio_serial_close (struct tty_struct *tty, struct file *filp);
-static int ftdi_sio_serial_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
+static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp);
+static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp);
+static int ftdi_sio_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
static void ftdi_sio_read_bulk_callback (struct urb *urb);
-static void ftdi_sio_set_termios (struct tty_struct *tty, struct termios * old);
-static int ftdi_sio_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg);
+static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * old);
+static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
/* All of the device info needed for the FTDI SIO serial converter */
static __u16 ftdi_vendor_id = FTDI_VENDOR_ID;
num_bulk_in: 1,
num_bulk_out: 1,
num_ports: 1,
- open: ftdi_sio_serial_open,
- close: ftdi_sio_serial_close,
- write: ftdi_sio_serial_write,
+ open: ftdi_sio_open,
+ close: ftdi_sio_close,
+ write: ftdi_sio_write,
+ ioctl: ftdi_sio_ioctl,
read_bulk_callback: ftdi_sio_read_bulk_callback,
set_termios: ftdi_sio_set_termios
};
#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA
/* function prototypes for a Keyspan PDA serial converter */
-static int keyspan_pda_serial_open (struct tty_struct *tty,
+static int keyspan_pda_open (struct usb_serial_port *port,
struct file *filp);
-static void keyspan_pda_serial_close (struct tty_struct *tty,
+static void keyspan_pda_close (struct usb_serial_port *port,
struct file *filp);
static int keyspan_pda_startup (struct usb_serial *serial);
-static void keyspan_pda_rx_throttle (struct tty_struct *tty);
-static void keyspan_pda_rx_unthrottle (struct tty_struct *tty);
+static void keyspan_pda_rx_throttle (struct usb_serial_port *port);
+static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port);
static int keyspan_pda_setbaud (struct usb_serial *serial, int baud);
-static int keyspan_pda_write_room (struct tty_struct *tty);
-static int keyspan_pda_write (struct tty_struct *tty,
+static int keyspan_pda_write_room (struct usb_serial_port *port);
+static int keyspan_pda_write (struct usb_serial_port *port,
int from_user,
const unsigned char *buf,
int count);
static void keyspan_pda_write_bulk_callback (struct urb *urb);
-static int keyspan_pda_chars_in_buffer (struct tty_struct *tty);
-static int keyspan_pda_ioctl (struct tty_struct *tty,
+static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port);
+static int keyspan_pda_ioctl (struct usb_serial_port *port,
struct file *file,
unsigned int cmd,
unsigned long arg);
-static void keyspan_pda_set_termios (struct tty_struct *tty,
+static void keyspan_pda_set_termios (struct usb_serial_port *port,
struct termios *old);
-static void keyspan_pda_break_ctl (struct tty_struct *tty,
+static void keyspan_pda_break_ctl (struct usb_serial_port *port,
int break_state);
static int keyspan_pda_fake_startup (struct usb_serial *serial);
num_bulk_in: 0,
num_bulk_out: 1,
num_ports: 1,
- open: keyspan_pda_serial_open,
- close: keyspan_pda_serial_close,
+ open: keyspan_pda_open,
+ close: keyspan_pda_close,
write: keyspan_pda_write,
write_room: keyspan_pda_write_room,
write_bulk_callback: keyspan_pda_write_bulk_callback,
{
int retval;
struct uhci *uhci;
+ char buf[8], *bufp = buf;
+
+#ifndef __sparc__
+ sprintf(buf, "%d", irq);
+#else
+ bufp = __irq_itoa(irq);
+#endif
+ printk(KERN_INFO __FILE__ ": USB UHCI at I/O 0x%x, IRQ %s\n",
+ io_addr, bufp);
uhci = alloc_uhci(io_addr, io_size);
if (!uhci)
static int hc_found_ohci (struct pci_dev *dev, int irq, void * mem_base)
{
ohci_t * ohci;
- dbg("USB HC found: irq= %d membase= %lx", irq, (unsigned long) mem_base);
+ char buf[8], *bufp = buf;
+
+#ifndef __sparc__
+ sprintf(buf, "%d", irq);
+#else
+ bufp = __irq_itoa(irq);
+#endif
+ printk(KERN_INFO __FILE__ ": USB OHCI at membase 0x%lx, IRQ %s\n",
+ (unsigned long) mem_base, bufp);
ohci = hc_alloc_ohci (mem_base);
if (!ohci) {
return -ENOMEM;
}
-
+
INIT_LIST_HEAD (&ohci->ohci_hcd_list);
list_add (&ohci->ohci_hcd_list, &ohci_hcd_list);
-
+
hc_reset (ohci);
writel (ohci->hc_control = OHCI_USB_RESET, &ohci->regs->control);
wait_ms (10);
uhci_t *s;
struct usb_bus *bus;
struct pm_dev *pmdev;
+ char buf[8], *bufp = buf;
+
+#ifndef __sparc__
+ sprintf(buf, "%d", irq);
+#else
+ bufp = __irq_itoa(irq);
+#endif
+ printk(KERN_INFO __FILE__ ": USB UHCI at I/O 0x%x, IRQ %s\n",
+ io_addr, bufp);
s = kmalloc (sizeof (uhci_t), GFP_KERNEL);
if (!s)
/*
- * wacom.c Version 0.4
+ * wacom.c Version 0.5
*
* Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2000 Andreas Bach Aaen <abach@stofanet.dk>
* v0.1 (vp) - Initial release
* v0.2 (aba) - Support for all buttons / combinations
* v0.3 (vp) - Support for Intuos added
- * v0.4 (sm) - Support for more Intuos models, menustrip,
- * relative mode, proximity.
+ * v0.4 (sm) - Support for more Intuos models, menustrip
+ * relative mode, proximity.
+ * v0.5 (vp) - Big cleanup, nifty features removed,
+ * they belong in userspace
*/
/*
/*
* Wacom Graphire packet:
*
- * The input report:
- *
* byte 0: report ID (2)
- * byte 1: bit7 mouse/pen/rubber near
- * bit5-6 0 - pen, 1 - rubber, 2 - mouse
- * bit4 1 ?
- * bit3 0 ?
- * bit2 mouse middle button / pen button2
- * bit1 mouse right button / pen button1
- * bit0 mouse left button / pen tip / rubber
+ * byte 1: bit7 pointer in range
+ * bit5-6 pointer type 0 - pen, 1 - rubber, 2 - mouse
+ * bit4 1 ?
+ * bit3 0 ?
+ * bit2 mouse middle button / pen button2
+ * bit1 mouse right button / pen button1
+ * bit0 mouse left button / touch
* byte 2: X low bits
* byte 3: X high bits
* byte 4: Y low bits
*
* There are also two single-byte feature reports (2 and 3).
*
- * Resolution:
- * X: 0 - 10206
- * Y: 0 - 7422
- *
- * (0,0) is upper left corner
- *
- * Wacom Intuos Status packet:
+ * Wacom Intuos status packet:
*
- * byte 0: report ID (2)
- * byte 1: bit7 1 (Sync Byte)
- * bit6 Pointer Near
- * bit5 0 - first proximity report
- * bit4 0 ?
- * bit3 0 ?
- * bit2 pen button2
- * bit1 pen button1
- * bit0 0 ?
- * byte 2: X high bits
- * byte 3: X low bits
- * byte 4: Y high bits
- * byte 5: Y low bits
- * byte 6: bits 0-7: pressure (bits 2-9)
- * byte 7: bits 6-7: pressure (bits 0-1)
- * byte 7: bits 0-5: X tilt (bits 1-6)
- * byte 8: bit 7: X tilt (bit 0)
- * byte 8: bits 0-6: Y tilt (bits 0-6)
- * byte 9: bits 4-7: Proximity
+ * byte 0: report ID (2)
+ * byte 1: bit7 1 - sync bit
+ * bit6 pointer in range
+ * bit5 pointer type report
+ * bit4 0 ?
+ * bit3 0 ?
+ * bit2 pen button2
+ * bit1 pen button1
+ * bit0 0 ?
+ * byte 2: X high bits
+ * byte 3: X low bits
+ * byte 4: Y high bits
+ * byte 5: Y low bits
+ * byte 6: bits 0-7: pressure (bits 2-9)
+ * byte 7: bits 6-7: pressure (bits 0-1)
+ * byte 7: bits 0-5: X tilt (bits 1-6)
+ * byte 8: bit 7: X tilt (bit 0)
+ * byte 8: bits 0-6: Y tilt (bits 0-6)
+ * byte 9: bits 4-7: distance
*/
-#define USB_VENDOR_ID_WACOM 0x056a
-#define USB_DEVICE_ID_WACOM_GRAPHIRE 0x0010
-#define USB_DEVICE_ID_WACOM_INTUOS45 0x0020 /* Guess */
-#define USB_DEVICE_ID_WACOM_INTUOS68 0x0021
-#define USB_DEVICE_ID_WACOM_INTUOS912 0x0022 /* Guess */
-#define USB_DEVICE_ID_WACOM_INTUOS1212 0x0023
-#define USB_DEVICE_ID_WACOM_INTUOS1218 0x0024 /* Guess */
-
-#define USB_TOOL_ID_WACOM_PEN 0x0022
-#define USB_TOOL_ID_WACOM_ERASER 0x00fa
-#define USB_TOOL_ID_WACOM_STROKE_PEN 0x0032
-#define USB_TOOL_ID_WACOM_INKING_PEN 0x0012
-#define USB_TOOL_ID_WACOM_AIRBRUSH 0x0112
-#define USB_TOOL_ID_WACOM_MOUSE4D 0x0094
-#define USB_TOOL_ID_WACOM_LENS_CURSOR 0x0096
-
-#define INTUOS_PEN_MODE_ABS 0x00
-#define INTUOS_PEN_MODE_REL 0x01
-#define INTUOS_PEN_MODE_QUICKPOINT 0x02
-
-#define INTUOS_PRESSURE_MODE_SOFT 0x00
-#define INTUOS_PRESSURE_MODE_MED 0x01
-#define INTUOS_PRESSURE_MODE_FIRM 0x02
-
-#define INTUOS_MENUSTRIP_Y_ZONE 1400
-#define INTUOS_MENUSTRIP_BTN_YMIN 270
-#define INTUOS_MENUSTRIP_BTN_YMAX 1070
-#define INTUOS_MENUSTRIP_F1_XMIN 40
-#define INTUOS_MENUSTRIP_F7_XMIN 8340
-#define INTUOS_MENUSTRIP_F12_XMIN 15300
-
-#define INTUOS_MENUSTRIP_BTN_WIDTH 1300
-
-#define INTUOS_MENUSTRIP_F7_IX_OFFSET 6 /* offset into wacom_fkeys */
-#define INTUOS_MENUSTRIP_F12_IX_OFFSET 11
+#define USB_VENDOR_ID_WACOM 0x056a
+
+struct wacom_features {
+ char *name;
+ int idProduct;
+ int pktlen;
+ int x_max;
+ int y_max;
+ int pressure_max;
+ int distance_max;
+ void (*irq)(struct urb *urb);
+ unsigned long evbit;
+ unsigned long relbit;
+ unsigned long absbit;
+ unsigned long btnbit;
+ unsigned long digibit;
+};
struct wacom {
- signed char data[10];
+ signed char data[10];
struct input_dev dev;
struct urb irq;
-
- int last_x, last_y;
- unsigned int tool, device;
- unsigned int ymax, menustrip_touch;
- unsigned int pen_mode;
- unsigned int pressure_mode;
+ struct wacom_features *features;
+ int tool;
};
-static int wacom_fkeys[16] = { KEY_F1, KEY_F2, KEY_F3, KEY_F4,
- KEY_F5, KEY_F6, KEY_F7, KEY_F8,
- KEY_F9, KEY_F10, KEY_F11, KEY_F12,
- KEY_F13, KEY_F14, KEY_F15, KEY_F16};
-
-#define INTUOS_EXTENTS_MAX_X 0x00
-#define INTUOS_EXTENTS_MAX_Y 0x01
-#define INTUOS_EXTENTS_HAS_F7 0x02
-#define INTUOS_EXTENTS_HAS_F12 0x03
-#define INTUOS_EXTENTS_PEN_MODE 0x04
-#define INTUOS_EXTENTS_HAS_QUICKPOINT 0x05
-#define INTUOS_EXTENTS_HAS_PRESSURE_MODE 0x06
-#define INTUOS_EXTENTS_PRESSURE_MODE 0x07
-
-#define WACOM_TRUE 1
-#define WACOM_FALSE 0
-
-static int intuos_extents[5][8] = {
- { 12700, 10360, WACOM_FALSE, WACOM_FALSE, 8340, WACOM_FALSE, WACOM_FALSE, 0}, /* Intuos 4x5 */
- { 20320, 15040, WACOM_TRUE, WACOM_FALSE, 15300, WACOM_FALSE, WACOM_TRUE, 18360}, /* Intuos 6x8 */
- { 30480, 23060, WACOM_TRUE, WACOM_TRUE, 22280, WACOM_TRUE, WACOM_TRUE, 26640}, /* Intuos 9x12 */
- { 30480, 30480, WACOM_TRUE, WACOM_TRUE, 22280, WACOM_TRUE, WACOM_TRUE, 26640}, /* Intuos 12x12 */
- { 47720, 30480, WACOM_TRUE, WACOM_TRUE, 29260, WACOM_TRUE, WACOM_TRUE, 33620}}; /* Intuos 12x18 */
-
-static char intuos_names[5][12] = {
- {"Intuos 4x5 "}, {"Intuos 6x8 "},
- {"Intuos 9x12 "}, {"Intuos 12x12"},
- {"Intuos 12x18"}};
-
static void wacom_graphire_irq(struct urb *urb)
{
- struct wacom *wacom = urb->context;
+ struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
struct input_dev *dev = &wacom->dev;
if (data[0] != 2)
dbg("received unknown report #%d", data[0]);
- if ( data[1] & 0x80 ) {
- input_report_abs(dev, ABS_X, data[2] | ((__u32)data[3] << 8));
- input_report_abs(dev, ABS_Y, 7422 - (data[4] | ((__u32)data[5] << 8)));
+ if ( data[1] & 0x80 ) {
+ input_report_abs(dev, ABS_X, data[2] | ((__u32)data[3] << 8));
+ input_report_abs(dev, ABS_Y, data[4] | ((__u32)data[5] << 8));
}
switch ((data[1] >> 5) & 3) {
- case 0: /* Pen */
- input_report_btn(dev, BTN_TOOL_PEN, data[1] & 0x80);
- input_report_btn(dev, BTN_TOUCH, data[1] & 0x01);
- input_report_btn(dev, BTN_STYLUS, data[1] & 0x02);
- input_report_btn(dev, BTN_STYLUS2, data[1] & 0x04);
- input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8));
- break;
-
- case 1: /* Rubber */
- input_report_btn(dev, BTN_TOOL_RUBBER, data[1] & 0x80);
- input_report_btn(dev, BTN_TOUCH, data[1] & 0x01);
- input_report_btn(dev, BTN_STYLUS, data[1] & 0x02);
- input_report_btn(dev, BTN_STYLUS2, data[1] & 0x04);
- input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8));
- break;
-
- case 2: /* Mouse */
- input_report_btn(dev, BTN_TOOL_MOUSE, data[7] > 24);
- input_report_btn(dev, BTN_LEFT, data[1] & 0x01);
- input_report_btn(dev, BTN_RIGHT, data[1] & 0x02);
- input_report_btn(dev, BTN_MIDDLE, data[1] & 0x04);
- input_report_abs(dev, ABS_DISTANCE, data[7]);
- input_report_rel(dev, REL_WHEEL, (signed char) data[6]);
- break;
- }
-}
+ case 0: /* Pen */
+ input_report_btn(dev, BTN_TOOL_PEN, data[1] & 0x80);
+ break;
-static void intuos_menustrip( unsigned int x, unsigned int y, struct wacom *wacom )
-{
- struct input_dev *dev = &wacom->dev;
- unsigned int local_x = x;
- unsigned int local_y = y - ( wacom->ymax - INTUOS_MENUSTRIP_Y_ZONE );
- unsigned int fkey_index ;
-
- /* Ensure we are in the vertical strip for the buttons */
- if ( (local_y > INTUOS_MENUSTRIP_BTN_YMIN) && (local_y < INTUOS_MENUSTRIP_BTN_YMAX) ) {
-
- /* Handle Pressure Mode */
- if ( intuos_extents[wacom->device][INTUOS_EXTENTS_HAS_PRESSURE_MODE] ) {
- int pressure_mode = ( (local_x - intuos_extents[wacom->device][INTUOS_EXTENTS_PRESSURE_MODE])
- / INTUOS_MENUSTRIP_BTN_WIDTH );
- if ( ( pressure_mode >= INTUOS_PRESSURE_MODE_SOFT ) &&
- ( pressure_mode <= INTUOS_PRESSURE_MODE_FIRM ) ) {
- wacom->pressure_mode = pressure_mode;
- return;
- }
- }
-
- /* Handle Pen Mode */
- {
- int pen_mode = ( (local_x - intuos_extents[wacom->device][INTUOS_EXTENTS_PEN_MODE])
- / INTUOS_MENUSTRIP_BTN_WIDTH );
- if ( ( pen_mode == INTUOS_PEN_MODE_ABS ) ||
- ( pen_mode == INTUOS_PEN_MODE_REL ) ||
- ( ( pen_mode == INTUOS_PEN_MODE_QUICKPOINT ) &&
- ( intuos_extents[wacom->device][INTUOS_EXTENTS_HAS_QUICKPOINT] ) ) ) {
- wacom->pen_mode = pen_mode;
- return;
- }
- }
-
- /* Handle Function Keys */
- if ( local_x > INTUOS_MENUSTRIP_F12_XMIN ) {
- fkey_index = INTUOS_MENUSTRIP_F12_IX_OFFSET
- + ( (local_x - INTUOS_MENUSTRIP_F12_XMIN) / INTUOS_MENUSTRIP_BTN_WIDTH );
- fkey_index = ( fkey_index > 16 ) ? 16 : fkey_index; /* Ensure in range */
- }
- else if ( local_x > INTUOS_MENUSTRIP_F7_XMIN ) {
- fkey_index = INTUOS_MENUSTRIP_F7_IX_OFFSET
- + ( (local_x - INTUOS_MENUSTRIP_F7_XMIN) / INTUOS_MENUSTRIP_BTN_WIDTH );
- fkey_index = ( fkey_index > 11 ) ? 11 : fkey_index;
- }
- else {
- fkey_index = ( (local_x - INTUOS_MENUSTRIP_F1_XMIN) / INTUOS_MENUSTRIP_BTN_WIDTH );
- fkey_index = ( fkey_index > 6 ) ? 6 : fkey_index;
- }
- input_report_key(dev, wacom_fkeys[fkey_index], 1);
- input_report_key(dev, wacom_fkeys[fkey_index], 0);
+ case 1: /* Rubber */
+ input_report_btn(dev, BTN_TOOL_RUBBER, data[1] & 0x80);
+ break;
- return;
+ case 2: /* Mouse */
+ input_report_btn(dev, BTN_TOOL_MOUSE, data[7] > 24);
+ input_report_btn(dev, BTN_LEFT, data[1] & 0x01);
+ input_report_btn(dev, BTN_RIGHT, data[1] & 0x02);
+ input_report_btn(dev, BTN_MIDDLE, data[1] & 0x04);
+ input_report_abs(dev, ABS_DISTANCE, data[7]);
+ input_report_rel(dev, REL_WHEEL, (signed char) data[6]);
+ return;
}
+
+ input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8));
+
+ input_report_btn(dev, BTN_TOUCH, data[1] & 0x01);
+ input_report_btn(dev, BTN_STYLUS, data[1] & 0x02);
+ input_report_btn(dev, BTN_STYLUS2, data[1] & 0x04);
}
-
+
static void wacom_intuos_irq(struct urb *urb)
{
- struct wacom *wacom = urb->context;
+ struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
struct input_dev *dev = &wacom->dev;
unsigned int t;
- int x, y;
if (urb->status) return;
if (data[0] != 2)
dbg("received unknown report #%d", data[0]);
- if ( ((data[1] >> 5) & 0x3) == 0x2 ) /* First record, feature report */
- {
- wacom->tool = (((char)data[2] << 4) | (char)data[3] >> 4) & 0xff ;
- /* Report tool type */
- switch ( wacom->tool ) {
- case USB_TOOL_ID_WACOM_PEN:
- input_report_btn(dev, BTN_TOOL_PEN, 1);
- break;
- case USB_TOOL_ID_WACOM_ERASER:
- input_report_btn(dev, BTN_TOOL_RUBBER, 1);
- break;
- case USB_TOOL_ID_WACOM_STROKE_PEN:
- input_report_btn(dev, BTN_TOOL_BRUSH, 1);
- break;
- case USB_TOOL_ID_WACOM_INKING_PEN:
- input_report_btn(dev, BTN_TOOL_PENCIL, 1);
- break;
- case USB_TOOL_ID_WACOM_AIRBRUSH:
- input_report_btn(dev, BTN_TOOL_AIRBRUSH, 1);
- break;
- case USB_TOOL_ID_WACOM_MOUSE4D:
- case USB_TOOL_ID_WACOM_LENS_CURSOR:
- input_report_btn(dev, BTN_TOOL_MOUSE, 1);
- break;
- default:
- break;
- }
- return;
- }
-
- if ( ( data[1] | data[2] | data[3] | data[4] | data[5] | data[6]
- | data[7] | data[8] | data[9] ) == 0x80 ) { /* exit report */
- switch ( wacom->tool ) {
- case USB_TOOL_ID_WACOM_PEN:
- input_report_btn(dev, BTN_TOOL_PEN, 0);
- break;
- case USB_TOOL_ID_WACOM_ERASER:
- input_report_btn(dev, BTN_TOOL_RUBBER, 0);
- break;
- case USB_TOOL_ID_WACOM_STROKE_PEN:
- input_report_btn(dev, BTN_TOOL_BRUSH, 0);
- break;
- case USB_TOOL_ID_WACOM_INKING_PEN:
- input_report_btn(dev, BTN_TOOL_PENCIL, 0);
- break;
- case USB_TOOL_ID_WACOM_AIRBRUSH:
- input_report_btn(dev, BTN_TOOL_AIRBRUSH, 0);
- break;
- case USB_TOOL_ID_WACOM_MOUSE4D:
- case USB_TOOL_ID_WACOM_LENS_CURSOR:
- input_report_btn(dev, BTN_TOOL_MOUSE, 0);
- break;
- default:
- break;
+ if (((data[1] >> 5) & 0x3) == 0x2) { /* Enter report */
+
+ switch (((__u32)data[2] << 4) | (data[3] >> 4)) {
+ case 0x012: wacom->tool = BTN_TOOL_PENCIL; break; /* Inking pen */
+ case 0x022: wacom->tool = BTN_TOOL_PEN; break; /* Pen */
+ case 0x032: wacom->tool = BTN_TOOL_BRUSH; break; /* Stroke pen */
+ case 0x094: wacom->tool = BTN_TOOL_MOUSE; break; /* Mouse 4D */
+ case 0x096: wacom->tool = BTN_TOOL_LENS; break; /* Lens cursor */
+ case 0x0fa: wacom->tool = BTN_TOOL_RUBBER; break; /* Eraser */
+ case 0x112: wacom->tool = BTN_TOOL_AIRBRUSH; break; /* Airbrush */
+ default: wacom->tool = BTN_TOOL_PEN; break; /* Unknown tool */
}
+ input_report_btn(dev, wacom->tool, 1);
return;
}
- x = (((unsigned int) data[2]) << 8) | data[3] ;
- y = wacom->dev.absmax[ABS_Y] - ((((unsigned int) data[4]) << 8) | data[5]);
-
- t = (((unsigned int) data[6]) << 2) | ((data[7] & 0xC0) >> 6);
-
- /* Handle touch near menustrip */
- if ( y > ( wacom->dev.absmax[ABS_Y] - INTUOS_MENUSTRIP_Y_ZONE ) ) {
- if ( t > 10 ) /* Touch */
- wacom->menustrip_touch = 1;
- if ( (wacom->menustrip_touch) && (t <= 10) ) { /* Pen Up */
- intuos_menustrip( x, y, wacom );
- wacom->menustrip_touch = 0;
- }
+ if ((data[1] | data[2] | data[3] | data[4] | data[5] |
+ data[6] | data[7] | data[8] | data[9]) == 0x80) { /* Exit report */
+ input_report_btn(dev, wacom->tool, 0);
return;
}
- else
- wacom->menustrip_touch = 0;
-
- switch ( wacom->pen_mode ) {
- case INTUOS_PEN_MODE_ABS:
- input_report_abs(dev, ABS_X, x);
- input_report_abs(dev, ABS_Y, y);
- break;
- case INTUOS_PEN_MODE_REL:
- input_report_rel(dev, REL_X, ( x - wacom->last_x) / 8 );
- input_report_rel(dev, REL_Y, - ( y - wacom->last_y) / 8 );
- break;
- default: break;
- }
-
- wacom->last_x = x;
- wacom->last_y = y;
- input_report_btn(dev, BTN_STYLUS, data[1] & 0x02);
- input_report_btn(dev, BTN_STYLUS2, data[1] & 0x04);
-
- input_report_btn(dev, BTN_TOUCH, t > 10);
- input_report_abs(dev, ABS_PRESSURE, t);
-
- input_report_abs(dev, ABS_DISTANCE, ( data[9] & 0xf0 ) >> 4 );
-
- input_report_abs(dev, ABS_TILT_X, ((((unsigned int) data[7]) & 0x3f) << 1) | ((data[8] & 0x80) >> 7));
+ input_report_abs(dev, ABS_X, ((__u32)data[2] << 8) | data[3]);
+ input_report_abs(dev, ABS_Y, ((__u32)data[4] << 8) | data[5]);
+ input_report_abs(dev, ABS_PRESSURE, t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
+ input_report_abs(dev, ABS_DISTANCE, data[9] >> 4);
+ input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7));
input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
+ input_report_btn(dev, BTN_STYLUS, data[1] & 2);
+ input_report_btn(dev, BTN_STYLUS2, data[1] & 4);
+ input_report_btn(dev, BTN_TOUCH, t > 10);
}
+#define WACOM_INTUOS_TOOLS (BIT(BTN_TOOL_BRUSH) | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS))
+
+struct wacom_features wacom_features[] = {
+ { "Graphire", 0x10, 8, 10206, 7422, 511, 32, wacom_graphire_irq,
+ BIT(EV_REL), 0, BIT(REL_WHEEL), BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE), 0 },
+ { "Intuos 4x5", 0x20, 10, 12700, 10360, 1023, 15, wacom_intuos_irq,
+ 0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS },
+ { "Intuos 6x8", 0x21, 10, 20320, 15040, 1023, 15, wacom_intuos_irq,
+ 0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS },
+ { "Intuos 9x12", 0x22, 10, 30480, 23060, 1023, 15, wacom_intuos_irq,
+ 0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS },
+ { "Intuos 12x12", 0x23, 10, 30480, 30480, 1023, 15, wacom_intuos_irq,
+ 0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS },
+ { "Intuos 12x18", 0x24, 10, 47720, 30480, 1023, 15, wacom_intuos_irq,
+ 0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS },
+ { NULL , 0 }
+};
+
static void *wacom_probe(struct usb_device *dev, unsigned int ifnum)
{
struct usb_endpoint_descriptor *endpoint;
struct wacom *wacom;
- char *name;
+ int i;
- if (dev->descriptor.idVendor != USB_VENDOR_ID_WACOM ||
- (dev->descriptor.idProduct != USB_DEVICE_ID_WACOM_GRAPHIRE &&
- dev->descriptor.idProduct != USB_DEVICE_ID_WACOM_INTUOS45 &&
- dev->descriptor.idProduct != USB_DEVICE_ID_WACOM_INTUOS68 &&
- dev->descriptor.idProduct != USB_DEVICE_ID_WACOM_INTUOS912 &&
- dev->descriptor.idProduct != USB_DEVICE_ID_WACOM_INTUOS1212 &&
- dev->descriptor.idProduct != USB_DEVICE_ID_WACOM_INTUOS1218))
- return NULL;
+ if (dev->descriptor.idVendor != USB_VENDOR_ID_WACOM) return NULL;
+ for (i = 0; wacom_features[i].idProduct && wacom_features[i].idProduct != dev->descriptor.idProduct; i++);
+ if (!wacom_features[i].idProduct) return NULL;
endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;
if (!(wacom = kmalloc(sizeof(struct wacom), GFP_KERNEL))) return NULL;
memset(wacom, 0, sizeof(struct wacom));
- if ( dev->descriptor.idProduct == USB_DEVICE_ID_WACOM_GRAPHIRE ) {
- wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
- wacom->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
- wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE);
- wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2);
- wacom->dev.relbit[0] |= BIT(REL_WHEEL);
- wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE);
-
- wacom->dev.absmax[ABS_X] = 10206;
- wacom->dev.absmax[ABS_Y] = 7422;
- wacom->dev.absmax[ABS_PRESSURE] = 511;
- wacom->dev.absmax[ABS_DISTANCE] = 32;
-
- FILL_INT_URB(&wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
- wacom->data, 8, wacom_graphire_irq, wacom, endpoint->bInterval);
-
- name = "Graphire";
- }
- else { /* Intuos */
-
- wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
- wacom->dev.keybit[LONG(KEY_F1)] |= BIT(KEY_F1) | BIT(KEY_F2) | BIT(KEY_F3) | BIT(KEY_F4) | BIT(KEY_F5);
- wacom->dev.keybit[LONG(KEY_F6)] |= BIT(KEY_F6) | BIT(KEY_F7) | BIT(KEY_F8);
- wacom->dev.keybit[LONG(KEY_F9)] |= BIT(KEY_F9) | BIT(KEY_F10) | BIT(KEY_F11) | BIT(KEY_F12);
- wacom->dev.keybit[LONG(KEY_F13)] |= BIT(KEY_F13) | BIT(KEY_F14) | BIT(KEY_F15) | BIT(KEY_F16);
- wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2);
- wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_BRUSH);
- wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_MOUSE);
- wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE);
- wacom->dev.absbit[0] |= BIT(ABS_TILT_X) | BIT(ABS_TILT_Y);
- wacom->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
-
- wacom->dev.absmax[ABS_PRESSURE] = 1023;
- wacom->dev.absmax[ABS_DISTANCE] = 15;
- wacom->dev.absmax[ABS_TILT_X] = 127;
- wacom->dev.absmax[ABS_TILT_Y] = 127;
-
- wacom->device = dev->descriptor.idProduct - USB_DEVICE_ID_WACOM_INTUOS45;
+ wacom->features = wacom_features + i;
- wacom->dev.absmax[ABS_X] = intuos_extents[wacom->device][INTUOS_EXTENTS_MAX_X];
- wacom->dev.absmax[ABS_Y] = intuos_extents[wacom->device][INTUOS_EXTENTS_MAX_Y];
+ wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | wacom->features->evbit;
+ wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE) | wacom->features->absbit;
+ wacom->dev.relbit[0] |= wacom->features->relbit;
+ wacom->dev.keybit[LONG(BTN_LEFT)] |= wacom->features->btnbit;
+ wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) |
+ BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2) | wacom->features->digibit;
- wacom->ymax = intuos_extents[wacom->device][INTUOS_EXTENTS_MAX_Y];
- wacom->pen_mode = INTUOS_PEN_MODE_ABS;
- wacom->pressure_mode = INTUOS_PRESSURE_MODE_SOFT;
+ wacom->dev.absmax[ABS_X] = wacom->features->x_max;
+ wacom->dev.absmax[ABS_Y] = wacom->features->y_max;
+ wacom->dev.absmax[ABS_PRESSURE] = wacom->features->pressure_max;
+ wacom->dev.absmax[ABS_DISTANCE] = wacom->features->distance_max;
+ wacom->dev.absmax[ABS_TILT_X] = 127;
+ wacom->dev.absmax[ABS_TILT_Y] = 127;
- name = intuos_names[wacom->device];
-
- FILL_INT_URB(&wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
- wacom->data, 10, wacom_intuos_irq, wacom, endpoint->bInterval);
-
- }
+ FILL_INT_URB(&wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
+ wacom->data, wacom->features->pktlen, wacom->features->irq, wacom, endpoint->bInterval);
if (usb_submit_urb(&wacom->irq)) {
kfree(wacom);
input_register_device(&wacom->dev);
- printk(KERN_INFO "input%d: Wacom %s\n", wacom->dev.number, name);
+ printk(KERN_INFO "input%d: Wacom %s on usb%d\n", wacom->dev.number, wacom->features->name, dev->devnum);
return wacom;
}
if( !buf )
return;
delta=0;
- for(offset=0;datasize;datasize-=len)
+ for(offset=0;datasize;datasize-=len,offset+=len)
{
ntfs_io io;
io.fn_put=ntfs_put;
if(ntfs_read_attr(ino,vol->at_attribute_list,0,offset,&io)){
ntfs_error("error in load_attributes\n");
}
- delta=len;
+ delta+=len;
parse_attributes(ino,buf,&delta);
if(delta)
/* move remaining bytes to buffer start */
#define BTN_TOOL_AIRBRUSH 0x144
#define BTN_TOOL_FINGER 0x145
#define BTN_TOOL_MOUSE 0x146
-#define BTN_TOUCH 0x147
-#define BTN_STYLUS 0x148
-#define BTN_STYLUS2 0x149
+#define BTN_TOOL_LENS 0x147
+#define BTN_TOUCH 0x14a
+#define BTN_STYLUS 0x14b
+#define BTN_STYLUS2 0x14c
#define KEY_MAX 0x1ff
struct isapnp_resources *next; /* next resource */
};
+#define ISAPNP_ANY_ID 0xffff
+#define ISAPNP_CARD_DEVS 8
+
+#define ISAPNP_CARD_ID(_va, _vb, _vc, _device) \
+ vendor: ISAPNP_VENDOR(_va, _vb, _vc), device: ISAPNP_DEVICE(_device)
+#define ISAPNP_CARD_END \
+ vendor: 0, device: 0
+#define ISAPNP_DEVICE_ID(_va, _vb, _vc, _function) \
+ { vendor: ISAPNP_VENDOR(_va, _vb, _vc), function: ISAPNP_FUNCTION(_function) }
+
+struct isapnp_card_id {
+ unsigned short vendor, device;
+ struct {
+ unsigned short vendor, function;
+ } devs[ISAPNP_CARD_DEVS]; /* logical devices */
+ unsigned long driver_data; /* data private to the driver */
+};
+
#if defined(CONFIG_ISAPNP) || (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE))
#define __ISAPNP__
unsigned short vendor,
unsigned short function,
struct pci_dev *from);
+int isapnp_probe_cards(const struct isapnp_card_id *ids,
+ int (*probe)(struct pci_bus *card,
+ const struct isapnp_card_id *id));
/* misc */
void isapnp_resource_change(struct resource *resource,
unsigned long start,
extern inline struct pci_dev *isapnp_find_dev(struct pci_bus *card,
unsigned short vendor,
unsigned short function,
- struct pci_dev *from) { return NULL; }
+ struct pci_dev *from) { return NULL; }
+extern inline int isapnp_probe_cards(const struct isapnp_card_id *ids,
+ int (*probe)(struct pci_bus *card,
+ const struct isapnp_card_id *id)) { return -ENODEV; }
extern inline void isapnp_resource_change(struct resource *resource,
unsigned long start,
unsigned long size) { ; }
*/
#include <linux/config.h>
+#include <linux/module.h>
#include <linux/malloc.h>
#include <linux/shm.h>
#include <linux/swap.h>
O_OBJS += $(IP_NF_CONNTRACK_OBJ)
else
ifeq ($(CONFIG_IP_NF_CONNTRACK),m)
+ MI_OBJS += $(IP_NF_CONNTRACK_OBJ)
+ MIX_OBJS += ip_conntrack_standalone.o
M_OBJS += ip_conntrack.o
endif
endif
OX_OBJS += ip_conntrack_ftp.o
else
ifeq ($(CONFIG_IP_NF_FTP),m)
- M_OBJS += ip_conntrack_ftp.o
+ MX_OBJS += ip_conntrack_ftp.o
endif
endif
endif
else
ifeq ($(CONFIG_IP_NF_NAT),m)
+ MI_OBJS += ip_nat_rule.o $(IP_NF_NAT_OBJ)
+ MIX_OBJS += ip_nat_standalone.o
M_OBJS += iptable_nat.o
ifeq ($(CONFIG_IP_NF_FTP),m)
M_OBJS += ip_nat_ftp.o
/* FTP extension for IP connection tracking. */
-#ifdef MODULE
-#define EXPORT_SYMTAB
-#endif
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/ip.h>
/* (c) 1999 Paul `Rusty' Russell. Licenced under the GNU General
Public Licence. */
-#ifdef MODULE
-#define EXPORT_SYMTAB
-#endif
#include <linux/types.h>
#include <linux/ip.h>
#include <linux/netfilter.h>
/* (c) 1999 Paul `Rusty' Russell. Licenced under the GNU General
Public Licence. */
-#ifdef MODULE
-#define EXPORT_SYMTAB
-#endif
#include <linux/types.h>
#include <linux/ip.h>
#include <linux/netfilter.h>