Commit 20f2ef0b authored by Linus Torvalds's avatar Linus Torvalds

Merge http://linuxusb.bkbits.net/linus-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents c3d7ae3b 90b49267
......@@ -382,6 +382,7 @@ CONFIG_USB_KAWETH
CONFIG_USB_CATC
Say Y if you want to use one of the following 10Mbps USB Ethernet
device based on the EL1210A chip. Supported devices are:
Belkin F5U011
Belkin F5U111
CATC NetMate
CATC NetMate II
......
......@@ -7,6 +7,9 @@
*
* Based on the work of
* Donald Becker
*
* Old chipset support added by Simon Evans <spse@secret.org.uk> 2002
* - adds support for Belkin F5U011
*/
/*
......@@ -70,6 +73,7 @@ MODULE_LICENSE("GPL");
#define RX_MAX_BURST 15 /* Max packets per rx buffer (> 0, < 16) */
#define TX_MAX_BURST 15 /* Max full sized packets per tx buffer (> 0) */
#define CTRL_QUEUE 16 /* Max control requests in flight (power of two) */
#define RX_PKT_SZ 1600 /* Max size of receive packet for F5U011 */
/*
* Control requests.
......@@ -80,6 +84,7 @@ enum control_requests {
GetMac = 0xf2,
Reset = 0xf4,
SetMac = 0xf5,
SetRxMode = 0xf5, /* F5U011 only */
WriteROM = 0xf8,
SetReg = 0xfa,
GetReg = 0xfb,
......@@ -127,6 +132,7 @@ enum rx_filter_bits {
RxForceOK = 0x04,
RxMultiCast = 0x08,
RxPromisc = 0x10,
AltRxPromisc = 0x20, /* F5U011 uses different bit */
};
enum led_values {
......@@ -137,6 +143,12 @@ enum led_values {
LEDLink = 0x08,
};
enum link_status {
LinkNoChange = 0,
LinkGood = 1,
LinkBad = 2
};
/*
* The catc struct.
*/
......@@ -180,6 +192,10 @@ struct catc {
} ctrl_queue[CTRL_QUEUE];
struct urb *tx_urb, *rx_urb, *irq_urb, *ctrl_urb;
u8 is_f5u011; /* Set if device is an F5U011 */
u8 rxmode[2]; /* Used for F5U011 */
atomic_t recq_sz; /* Used for F5U011 - counter of waiting rx packets */
};
/*
......@@ -193,6 +209,10 @@ struct catc {
#define catc_write_mem(catc, addr, buf, size) catc_ctrl_msg(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size)
#define catc_read_mem(catc, addr, buf, size) catc_ctrl_msg(catc, USB_DIR_IN, ReadMem, 0, addr, buf, size)
#define f5u011_rxmode(catc, rxmode) catc_ctrl_msg(catc, USB_DIR_OUT, SetRxMode, 0, 1, rxmode, 2)
#define f5u011_rxmode_async(catc, rxmode) catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 1, &rxmode, 2, NULL)
#define f5u011_mchash_async(catc, hash) catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 2, &hash, 8, NULL)
#define catc_set_reg_async(catc, reg, val) catc_ctrl_async(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0, NULL)
#define catc_get_reg_async(catc, reg, cb) catc_ctrl_async(catc, USB_DIR_IN, GetReg, 0, reg, NULL, 1, cb)
#define catc_write_mem_async(catc, addr, buf, size) catc_ctrl_async(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size, NULL)
......@@ -206,9 +226,12 @@ static void catc_rx_done(struct urb *urb)
struct catc *catc = urb->context;
u8 *pkt_start = urb->transfer_buffer;
struct sk_buff *skb;
int pkt_len;
int pkt_len, pkt_offset = 0;
clear_bit(RX_RUNNING, &catc->flags);
if (!catc->is_f5u011) {
clear_bit(RX_RUNNING, &catc->flags);
pkt_offset = 2;
}
if (urb->status) {
dbg("rx_done, status %d, length %d", urb->status, urb->actual_length);
......@@ -216,19 +239,22 @@ static void catc_rx_done(struct urb *urb)
}
do {
pkt_len = le16_to_cpup((u16*)pkt_start);
if (pkt_len > urb->actual_length) {
catc->stats.rx_length_errors++;
catc->stats.rx_errors++;
break;
if(!catc->is_f5u011) {
pkt_len = le16_to_cpup((u16*)pkt_start);
if (pkt_len > urb->actual_length) {
catc->stats.rx_length_errors++;
catc->stats.rx_errors++;
break;
}
} else {
pkt_len = urb->actual_length;
}
if (!(skb = dev_alloc_skb(pkt_len)))
return;
skb->dev = catc->netdev;
eth_copy_and_sum(skb, pkt_start + 2, pkt_len, 0);
eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0);
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, catc->netdev);
......@@ -237,11 +263,28 @@ static void catc_rx_done(struct urb *urb)
catc->stats.rx_packets++;
catc->stats.rx_bytes += pkt_len;
/* F5U011 only does one packet per RX */
if (catc->is_f5u011)
break;
pkt_start += (((pkt_len + 1) >> 6) + 1) << 6;
} while (pkt_start - (u8 *) urb->transfer_buffer < urb->actual_length);
catc->netdev->last_rx = jiffies;
if (catc->is_f5u011) {
if (atomic_read(&catc->recq_sz)) {
int status;
atomic_dec(&catc->recq_sz);
dbg("getting extra packet");
urb->dev = catc->usbdev;
if ((status = usb_submit_urb(urb, GFP_KERNEL)) < 0) {
dbg("submit(rx_urb) status %d", status);
}
} else {
clear_bit(RX_RUNNING, &catc->flags);
}
}
}
static void catc_irq_done(struct urb *urb)
......@@ -249,29 +292,48 @@ static void catc_irq_done(struct urb *urb)
struct catc *catc = urb->context;
u8 *data = urb->transfer_buffer;
int status;
unsigned int hasdata = 0, linksts = LinkNoChange;
if (!catc->is_f5u011) {
hasdata = data[1] & 0x80;
if (data[1] & 0x40)
linksts = LinkGood;
else if (data[1] & 0x20)
linksts = LinkBad;
} else {
hasdata = (unsigned int)(be16_to_cpup((u16*)data) & 0x0fff);
if (data[0] == 0x90)
linksts = LinkGood;
else if (data[0] == 0xA0)
linksts = LinkBad;
}
if (urb->status) {
dbg("irq_done, status %d, data %02x %02x.", urb->status, data[0], data[1]);
return;
}
if ((data[1] & 0x80) && !test_and_set_bit(RX_RUNNING, &catc->flags)) {
catc->rx_urb->dev = catc->usbdev;
if ((status = usb_submit_urb(catc->rx_urb, GFP_KERNEL)) < 0) {
err("submit(rx_urb) status %d", status);
return;
}
}
if (data[1] & 0x40) {
if (linksts == LinkGood) {
netif_carrier_on(catc->netdev);
dbg("link ok");
}
if (data[1] & 0x20) {
if (linksts == LinkBad) {
netif_carrier_off(catc->netdev);
dbg("link bad");
}
if (hasdata) {
if (test_and_set_bit(RX_RUNNING, &catc->flags)) {
if (catc->is_f5u011)
atomic_inc(&catc->recq_sz);
} else {
catc->rx_urb->dev = catc->usbdev;
if ((status = usb_submit_urb(catc->rx_urb, GFP_KERNEL)) < 0) {
err("submit(rx_urb) status %d", status);
}
}
}
}
/*
......@@ -282,6 +344,9 @@ static void catc_tx_run(struct catc *catc)
{
int status;
if (catc->is_f5u011)
catc->tx_ptr = (catc->tx_ptr + 63) & ~63;
catc->tx_urb->transfer_buffer_length = catc->tx_ptr;
catc->tx_urb->transfer_buffer = catc->tx_buf[catc->tx_idx];
catc->tx_urb->dev = catc->usbdev;
......@@ -338,14 +403,15 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
catc->tx_ptr = (((catc->tx_ptr - 1) >> 6) + 1) << 6;
tx_buf = catc->tx_buf[catc->tx_idx] + catc->tx_ptr;
*((u16*)tx_buf) = cpu_to_le16((u16)skb->len);
*((u16*)tx_buf) = (catc->is_f5u011) ? cpu_to_be16((u16)skb->len) : cpu_to_le16((u16)skb->len);
memcpy(tx_buf + 2, skb->data, skb->len);
catc->tx_ptr += skb->len + 2;
if (!test_and_set_bit(TX_RUNNING, &catc->flags))
catc_tx_run(catc);
if (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2)))
if ((catc->is_f5u011 && catc->tx_ptr)
|| (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2))))
netif_stop_queue(netdev);
spin_unlock_irqrestore(&catc->tx_lock, flags);
......@@ -554,17 +620,32 @@ static void catc_set_multicast_list(struct net_device *netdev)
if (netdev->flags & IFF_PROMISC) {
memset(catc->multicast, 0xff, 64);
rx |= RxPromisc;
rx |= (!catc->is_f5u011) ? RxPromisc : AltRxPromisc;
}
if (netdev->flags & IFF_ALLMULTI)
if (netdev->flags & IFF_ALLMULTI) {
memset(catc->multicast, 0xff, 64);
for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next)
catc_multicast(mc->dmi_addr, catc->multicast);
catc_set_reg_async(catc, RxUnit, rx);
catc_write_mem_async(catc, 0xfa80, catc->multicast, 64);
} else {
for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next) {
u32 crc = ether_crc_le(6, mc->dmi_addr);
if (!catc->is_f5u011) {
catc->multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7);
} else {
catc->multicast[7-(crc >> 29)] |= 1 << ((crc >> 26) & 7);
}
}
}
if (!catc->is_f5u011) {
catc_set_reg_async(catc, RxUnit, rx);
catc_write_mem_async(catc, 0xfa80, catc->multicast, 64);
} else {
f5u011_mchash_async(catc, catc->multicast);
if (catc->rxmode[0] != rx) {
catc->rxmode[0] = rx;
dbg("Setting RX mode to %2.2X %2.2X", catc->rxmode[0], catc->rxmode[1]);
f5u011_rxmode_async(catc, catc->rxmode);
}
}
}
/*
......@@ -591,6 +672,29 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
return -EFAULT;
return 0;
}
/* get settings */
case ETHTOOL_GSET:
if (catc->is_f5u011) {
struct ethtool_cmd ecmd = { ETHTOOL_GSET,
SUPPORTED_10baseT_Half | SUPPORTED_TP,
ADVERTISED_10baseT_Half | ADVERTISED_TP,
SPEED_10,
DUPLEX_HALF,
PORT_TP,
0,
XCVR_INTERNAL,
AUTONEG_DISABLE,
1,
1
};
if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
return -EFAULT;
return 0;
} else {
return -EOPNOTSUPP;
}
/* get link status */
case ETHTOOL_GLINK: {
struct ethtool_value edata = {ETHTOOL_GLINK};
......@@ -632,7 +736,8 @@ static int catc_open(struct net_device *netdev)
netif_start_queue(netdev);
mod_timer(&catc->timer, jiffies + STATS_UPDATE);
if (!catc->is_f5u011)
mod_timer(&catc->timer, jiffies + STATS_UPDATE);
return 0;
}
......@@ -643,7 +748,8 @@ static int catc_stop(struct net_device *netdev)
netif_stop_queue(netdev);
del_timer_sync(&catc->timer);
if (!catc->is_f5u011)
del_timer_sync(&catc->timer);
usb_unlink_urb(catc->rx_urb);
usb_unlink_urb(catc->tx_urb);
......@@ -662,7 +768,7 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
struct net_device *netdev;
struct catc *catc;
u8 broadcast[6];
int i;
int i, pktsz;
if (usb_set_interface(usbdev, ifnum, 1)) {
err("Can't set altsetting 1.");
......@@ -670,9 +776,16 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
}
catc = kmalloc(sizeof(struct catc), GFP_KERNEL);
if (!catc)
return NULL;
memset(catc, 0, sizeof(struct catc));
netdev = init_etherdev(0, 0);
if (!netdev) {
kfree(catc);
return NULL;
}
netdev->open = catc_open;
netdev->hard_start_xmit = catc_hard_start_xmit;
......@@ -701,9 +814,26 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
if ((!catc->ctrl_urb) || (!catc->tx_urb) ||
(!catc->rx_urb) || (!catc->irq_urb)) {
err("No free urbs available.");
if (catc->ctrl_urb) usb_free_urb(catc->ctrl_urb);
if (catc->tx_urb) usb_free_urb(catc->tx_urb);
if (catc->rx_urb) usb_free_urb(catc->rx_urb);
if (catc->irq_urb) usb_free_urb(catc->irq_urb);
kfree(netdev);
kfree(catc);
return NULL;
}
/* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */
if (usbdev->descriptor.idVendor == 0x0423 && usbdev->descriptor.idProduct == 0xa &&
catc->usbdev->descriptor.bcdDevice == 0x0130 ) {
dbg("Testing for f5u011");
catc->is_f5u011 = 1;
atomic_set(&catc->recq_sz, 0);
pktsz = RX_PKT_SZ;
} else {
pktsz = RX_MAX_BURST * (PKT_SZ + 2);
}
FILL_CONTROL_URB(catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0),
NULL, NULL, 0, catc_ctrl_done, catc);
......@@ -711,20 +841,21 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
NULL, 0, catc_tx_done, catc);
FILL_BULK_URB(catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1),
catc->rx_buf, RX_MAX_BURST * (PKT_SZ + 2), catc_rx_done, catc);
catc->rx_buf, pktsz, catc_rx_done, catc);
FILL_INT_URB(catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2),
catc->irq_buf, 2, catc_irq_done, catc, 1);
dbg("Checking memory size\n");
i = 0x12345678;
catc_write_mem(catc, 0x7a80, &i, 4);
i = 0x87654321;
catc_write_mem(catc, 0xfa80, &i, 4);
catc_read_mem(catc, 0x7a80, &i, 4);
if (!catc->is_f5u011) {
dbg("Checking memory size\n");
switch (i) {
i = 0x12345678;
catc_write_mem(catc, 0x7a80, &i, 4);
i = 0x87654321;
catc_write_mem(catc, 0xfa80, &i, 4);
catc_read_mem(catc, 0x7a80, &i, 4);
switch (i) {
case 0x12345678:
catc_set_reg(catc, TxBufCount, 8);
catc_set_reg(catc, RxBufCount, 32);
......@@ -737,44 +868,52 @@ static void *catc_probe(struct usb_device *usbdev, unsigned int ifnum, const str
catc_set_reg(catc, RxBufCount, 16);
dbg("32k Memory\n");
break;
}
dbg("Getting MAC from SEEROM.");
catc_get_mac(catc, netdev->dev_addr);
dbg("Setting MAC into registers.");
for (i = 0; i < 6; i++)
catc_set_reg(catc, StationAddr0 - i, netdev->dev_addr[i]);
dbg("Filling the multicast list.");
memset(broadcast, 0xff, 6);
catc_multicast(broadcast, catc->multicast);
catc_multicast(netdev->dev_addr, catc->multicast);
catc_write_mem(catc, 0xfa80, catc->multicast, 64);
dbg("Clearing error counters.");
for (i = 0; i < 8; i++)
catc_set_reg(catc, EthStats + i, 0);
catc->last_stats = jiffies;
dbg("Enabling.");
catc_set_reg(catc, MaxBurst, RX_MAX_BURST);
catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits);
catc_set_reg(catc, LEDCtrl, LEDLink);
catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast);
} else {
dbg("Performing reset\n");
catc_reset(catc);
catc_get_mac(catc, netdev->dev_addr);
dbg("Setting RX Mode");
catc->rxmode[0] = RxEnable | RxPolarity | RxMultiCast;
catc->rxmode[1] = 0;
f5u011_rxmode(catc, catc->rxmode);
}
dbg("Getting MAC from SEEROM.");
catc_get_mac(catc, netdev->dev_addr);
dbg("Setting MAC into registers.");
for (i = 0; i < 6; i++)
catc_set_reg(catc, StationAddr0 - i, netdev->dev_addr[i]);
dbg("Filling the multicast list.");
memset(broadcast, 0xff, 8);
catc_multicast(broadcast, catc->multicast);
catc_multicast(netdev->dev_addr, catc->multicast);
catc_write_mem(catc, 0xfa80, catc->multicast, 64);
dbg("Clearing error counters.");
for (i = 0; i < 8; i++)
catc_set_reg(catc, EthStats + i, 0);
catc->last_stats = jiffies;
dbg("Enabling.");
catc_set_reg(catc, MaxBurst, RX_MAX_BURST);
catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits);
catc_set_reg(catc, LEDCtrl, LEDLink);
catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast);
dbg("Init done.");
printk(KERN_INFO "%s: CATC EL1210A NetMate USB Ethernet at usb%d:%d.%d, ",
netdev->name, usbdev->bus->busnum, usbdev->devnum, ifnum);
printk(KERN_INFO "%s: %s USB Ethernet at usb%d:%d.%d, ",
netdev->name, (catc->is_f5u011) ? "Belkin F5U011" : "CATC EL1210A NetMate",
usbdev->bus->busnum, usbdev->devnum, ifnum);
for (i = 0; i < 5; i++) printk("%2.2x:", netdev->dev_addr[i]);
printk("%2.2x.\n", netdev->dev_addr[i]);
return catc;
}
......@@ -795,7 +934,7 @@ static void catc_disconnect(struct usb_device *usbdev, void *dev_ptr)
*/
static struct usb_device_id catc_id_table [] = {
{ USB_DEVICE(0x0423, 0xa) }, /* CATC Netmate */
{ USB_DEVICE(0x0423, 0xa) }, /* CATC Netmate, Belkin F5U011 */
{ USB_DEVICE(0x0423, 0xc) }, /* CATC Netmate II, Belkin F5U111 */
{ USB_DEVICE(0x08d1, 0x1) }, /* smartBridges smartNIC */
{ }
......
......@@ -110,10 +110,11 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned
memset(field, 0, sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
+ values * sizeof(unsigned));
report->field[report->maxfield++] = field;
report->field[report->maxfield] = field;
field->usage = (struct hid_usage *)(field + 1);
field->value = (unsigned *)(field->usage + usages);
field->report = report;
field->index = report->maxfield++;
return field;
}
......@@ -741,8 +742,20 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field, s
if (hid->claimed & HID_CLAIMED_INPUT)
hidinput_hid_event(hid, field, usage, value);
#ifdef CONFIG_USB_HIDDEV
if (hid->claimed & HID_CLAIMED_HIDDEV)
hiddev_hid_event(hid, usage->hid, value);
if (hid->claimed & HID_CLAIMED_HIDDEV) {
struct hiddev_usage_ref uref;
unsigned type = field->report_type;
uref.report_type =
(type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
uref.report_id = field->report->id;
uref.field_index = field->index;
uref.usage_index = (usage - field->usage);
uref.usage_code = usage->hid;
uref.value = value;
hiddev_hid_event(hid, &uref);
}
#endif
}
......@@ -839,6 +852,21 @@ static int hid_input_report(int type, struct urb *urb)
return -1;
}
#ifdef CONFIG_USB_HIDDEV
/* Notify listeners that a report has been received */
if (hid->claimed & HID_CLAIMED_HIDDEV) {
struct hiddev_usage_ref uref;
memset(&uref, 0, sizeof(uref));
uref.report_type =
(type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT :
((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT :
((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0));
uref.report_id = report->id;
uref.field_index = HID_FIELD_INDEX_NONE;
hiddev_hid_event(hid, &uref);
}
#endif
size = ((report->size - 1) >> 3) + 1;
if (len < size) {
......@@ -1096,6 +1124,9 @@ void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsign
int head;
unsigned long flags;
if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
return;
if (hid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
spin_lock_irqsave(&hid->outlock, flags);
......@@ -1238,18 +1269,27 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_POWERMATE 0x0410
#define USB_DEVICE_ID_SOUNDKNOB 0x04AA
#define USB_VENDOR_ID_ATEN 0x0557
#define USB_DEVICE_ID_ATEN_UC100KM 0x2004
#define USB_DEVICE_ID_ATEN_CS124U 0x2202
#define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204
struct hid_blacklist {
__u16 idVendor;
__u16 idProduct;
unsigned quirks;
} hid_blacklist[] = {
{ 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},
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE },
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
{ 0, 0 }
};
......@@ -1258,13 +1298,17 @@ static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0;
struct hid_descriptor *hdesc;
struct hid_device *hid;
unsigned rsize = 0;
unsigned quirks = 0, rsize = 0;
char *buf;
int n;
for (n = 0; hid_blacklist[n].idVendor; n++)
if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) &&
(hid_blacklist[n].idProduct == dev->descriptor.idProduct)) return NULL;
(hid_blacklist[n].idProduct == dev->descriptor.idProduct))
quirks = hid_blacklist[n].quirks;
if (quirks & HID_QUIRK_IGNORE)
return NULL;
if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && ((!interface->bNumEndpoints) ||
usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
......@@ -1302,6 +1346,8 @@ static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
}
}
hid->quirks = quirks;
for (n = 0; n < interface->bNumEndpoints; n++) {
struct usb_endpoint_descriptor *endpoint = &interface->endpoint[n];
......
......@@ -203,6 +203,8 @@ struct hid_item {
#define HID_QUIRK_INVERT 0x01
#define HID_QUIRK_NOTOUCH 0x02
#define HID_QUIRK_IGNORE 0x04
#define HID_QUIRK_NOGET 0x08
/*
* This is the global enviroment of the parser. This information is
......@@ -276,6 +278,7 @@ struct hid_field {
__s32 unit_exponent;
unsigned unit;
struct hid_report *report; /* associated report */
unsigned index; /* index into report->field[] */
};
#define HID_MAX_FIELDS 64
......
......@@ -50,9 +50,10 @@ struct hiddev {
};
struct hiddev_list {
struct hiddev_event buffer[HIDDEV_BUFFER_SIZE];
struct hiddev_usage_ref buffer[HIDDEV_BUFFER_SIZE];
int head;
int tail;
unsigned flags;
struct fasync_struct *fasync;
struct hiddev *hiddev;
struct hiddev_list *next;
......@@ -146,17 +147,19 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
* This is where hid.c calls into hiddev to pass an event that occurred over
* the interrupt pipe
*/
void hiddev_hid_event(struct hid_device *hid, unsigned int usage, int value)
void hiddev_hid_event(struct hid_device *hid, struct hiddev_usage_ref *uref)
{
struct hiddev *hiddev = hid->hiddev;
struct hiddev_list *list = hiddev->list;
while (list) {
list->buffer[list->head].hid = usage;
list->buffer[list->head].value = value;
list->head = (list->head + 1) & (HIDDEV_BUFFER_SIZE - 1);
kill_fasync(&list->fasync, SIGIO, POLL_IN);
if (uref->field_index != HID_FIELD_INDEX_NONE ||
(list->flags & HIDDEV_FLAG_REPORT) != 0) {
list->buffer[list->head] = *uref;
list->head = (list->head + 1) &
(HIDDEV_BUFFER_SIZE - 1);
kill_fasync(&list->fasync, SIGIO, POLL_IN);
}
list = list->next;
}
......@@ -257,43 +260,67 @@ static ssize_t hiddev_read(struct file * file, char * buffer, size_t count,
{
DECLARE_WAITQUEUE(wait, current);
struct hiddev_list *list = file->private_data;
int event_size;
int retval = 0;
if (list->head == list->tail) {
add_wait_queue(&list->hiddev->wait, &wait);
set_current_state(TASK_INTERRUPTIBLE);
event_size = ((list->flags & HIDDEV_FLAG_UREF) != 0) ?
sizeof(struct hiddev_usage_ref) : sizeof(struct hiddev_event);
while (list->head == list->tail) {
if (count < event_size) return 0;
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
break;
}
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
if (!list->hiddev->exist) {
retval = -EIO;
break;
while (retval == 0) {
if (list->head == list->tail) {
add_wait_queue(&list->hiddev->wait, &wait);
set_current_state(TASK_INTERRUPTIBLE);
while (list->head == list->tail) {
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
break;
}
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
if (!list->hiddev->exist) {
retval = -EIO;
break;
}
schedule();
}
schedule();
set_current_state(TASK_RUNNING);
remove_wait_queue(&list->hiddev->wait, &wait);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&list->hiddev->wait, &wait);
}
if (retval)
return retval;
if (retval)
return retval;
while (list->head != list->tail &&
retval + event_size <= count) {
if ((list->flags & HIDDEV_FLAG_UREF) == 0) {
if (list->buffer[list->tail].field_index !=
HID_FIELD_INDEX_NONE) {
struct hiddev_event event;
event.hid = list->buffer[list->tail].usage_code;
event.value = list->buffer[list->tail].value;
if (copy_to_user(buffer + retval, &event, sizeof(struct hiddev_event)))
return -EFAULT;
retval += sizeof(struct hiddev_event);
}
} else {
if (list->buffer[list->tail].field_index != HID_FIELD_INDEX_NONE ||
(list->flags & HIDDEV_FLAG_REPORT) != 0) {
if (copy_to_user(buffer + retval, list->buffer + list->tail, sizeof(struct hiddev_usage_ref)))
return -EFAULT;
retval += sizeof(struct hiddev_usage_ref);
}
}
list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1);
}
while (list->head != list->tail && retval + sizeof(struct hiddev_event) <= count) {
if (copy_to_user(buffer + retval, list->buffer + list->tail,
sizeof(struct hiddev_event))) return -EFAULT;
list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1);
retval += sizeof(struct hiddev_event);
}
return retval;
......@@ -358,6 +385,25 @@ static int hiddev_ioctl(struct inode *inode, struct file *file,
return copy_to_user((void *) arg, &dinfo, sizeof(dinfo));
}
case HIDIOCGFLAG:
return put_user(list->flags, (int *) arg);
case HIDIOCSFLAG:
{
int newflags;
if (get_user(newflags, (int *) arg))
return -EFAULT;
if ((newflags & ~HIDDEV_FLAGS) != 0 ||
((newflags & HIDDEV_FLAG_REPORT) != 0 &&
(newflags & HIDDEV_FLAG_UREF) == 0))
return -EINVAL;
list->flags = newflags;
return 0;
}
case HIDIOCGSTRING:
{
int idx, len;
......
/*
* printer.c Version 0.8
* printer.c Version 0.12
*
* Copyright (c) 1999 Michael Gee <michael@linuxspecific.com>
* Copyright (c) 1999 Pavel Machek <pavel@suse.cz>
* Copyright (c) 2000 Randy Dunlap <randy.dunlap@intel.com>
* Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
# Copyright (c) 2001 Pete Zaitcev <zaitcev@redhat.com>
# Copyright (c) 2001 David Paschal <paschal@rcsis.com>
*
* USB Printer Device Class driver for USB printers and printer cables
*
......@@ -17,10 +19,12 @@
* v0.4 - fixes in unidirectional mode
* v0.5 - add DEVICE_ID string support
* v0.6 - never time out
* v0.7 - fixed bulk-IN read and poll (David Paschal, paschal@rcsis.com)
* v0.7 - fixed bulk-IN read and poll (David Paschal)
* v0.8 - add devfs support
* v0.9 - fix unplug-while-open paths
* v0.10- remove sleep_on, fix error on oom (oliver@neukum.org)
* v0.11 - add proto_bias option (Pete Zaitcev)
* v0.12 - add hpoj.sourceforge.net ioctls (David Paschal)
*/
/*
......@@ -55,16 +59,36 @@
/*
* Version Information
*/
#define DRIVER_VERSION "v0.10"
#define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap"
#define DRIVER_VERSION "v0.12"
#define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap, Pete Zaitcev, David Paschal"
#define DRIVER_DESC "USB Printer Device Class driver"
#define USBLP_BUF_SIZE 8192
#define DEVICE_ID_SIZE 1024
#define IOCNR_GET_DEVICE_ID 1
#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len) /* get device_id string */
/* ioctls: */
#define LPGETSTATUS 0x060b /* same as in drivers/char/lp.c */
#define IOCNR_GET_DEVICE_ID 1
#define IOCNR_GET_PROTOCOLS 2
#define IOCNR_SET_PROTOCOL 3
#define IOCNR_HP_SET_CHANNEL 4
#define IOCNR_GET_BUS_ADDRESS 5
#define IOCNR_GET_VID_PID 6
/* Get device_id string: */
#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
/* The following ioctls were added for http://hpoj.sourceforge.net: */
/* Get two-int array:
* [0]=current protocol (1=7/1/1, 2=7/1/2, 3=7/1/3),
* [1]=supported protocol mask (mask&(1<<n)!=0 means 7/1/n supported): */
#define LPIOC_GET_PROTOCOLS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_PROTOCOLS, len)
/* Set protocol (arg: 1=7/1/1, 2=7/1/2, 3=7/1/3): */
#define LPIOC_SET_PROTOCOL _IOC(_IOC_WRITE, 'P', IOCNR_SET_PROTOCOL, 0)
/* Set channel number (HP Vendor-specific command): */
#define LPIOC_HP_SET_CHANNEL _IOC(_IOC_WRITE, 'P', IOCNR_HP_SET_CHANNEL, 0)
/* Get two-int array: [0]=bus number, [1]=device address: */
#define LPIOC_GET_BUS_ADDRESS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_BUS_ADDRESS, len)
/* Get two-int array: [0]=vendor ID, [1]=product ID: */
#define LPIOC_GET_VID_PID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_VID_PID, len)
/*
* A DEVICE_ID string may include the printer's serial number.
......@@ -78,26 +102,40 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H
* USB Printer Requests
*/
#define USBLP_REQ_GET_ID 0x00
#define USBLP_REQ_GET_STATUS 0x01
#define USBLP_REQ_RESET 0x02
#define USBLP_REQ_GET_ID 0x00
#define USBLP_REQ_GET_STATUS 0x01
#define USBLP_REQ_RESET 0x02
#define USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST 0x00 /* HP Vendor-specific */
#define USBLP_MINORS 16
#define USBLP_MINOR_BASE 0
#define USBLP_WRITE_TIMEOUT (5*HZ) /* 5 seconds */
#define USBLP_FIRST_PROTOCOL 1
#define USBLP_LAST_PROTOCOL 3
#define USBLP_MAX_PROTOCOLS (USBLP_LAST_PROTOCOL+1)
struct usblp {
struct usb_device *dev; /* USB device */
devfs_handle_t devfs; /* devfs device */
struct semaphore sem; /* locks this struct, especially "dev" */
char *buf; /* writeurb->transfer_buffer */
struct urb *readurb, *writeurb; /* The urbs */
wait_queue_head_t wait; /* Zzzzz ... */
int readcount; /* Counter for reads */
int ifnum; /* Interface number */
/* Alternate-setting numbers and endpoints for each protocol
* (7/1/{index=1,2,3}) that the device supports: */
struct {
int alt_setting;
struct usb_endpoint_descriptor *epwrite;
struct usb_endpoint_descriptor *epread;
} protocol[USBLP_MAX_PROTOCOLS];
int current_protocol;
int minor; /* minor number of device */
int wcomplete; /* writing is completed */
int rcomplete; /* reading is completed */
int rcomplete; /* reading is completed */
unsigned int quirks; /* quirks flags */
unsigned char used; /* True if open */
unsigned char bidir; /* interface is bidirectional */
......@@ -105,6 +143,35 @@ struct usblp {
/* first 2 bytes are (big-endian) length */
};
#ifdef DEBUG
static void usblp_dump(struct usblp *usblp) {
int p;
dbg("usblp=0x%p", usblp);
dbg("dev=0x%p", usblp->dev);
dbg("devfs=0x%p", usblp->devfs);
dbg("buf=0x%p", usblp->buf);
dbg("readcount=%d", usblp->readcount);
dbg("ifnum=%d", usblp->ifnum);
for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) {
dbg("protocol[%d].alt_setting=%d", p, usblp->protocol[p].alt_setting);
dbg("protocol[%d].epwrite=%p", p, usblp->protocol[p].epwrite);
dbg("protocol[%d].epread=%p", p, usblp->protocol[p].epread);
}
dbg("current_protocol=%d", usblp->current_protocol);
dbg("minor=%d", usblp->minor);
dbg("wcomplete=%d", usblp->wcomplete);
dbg("rcomplete=%d", usblp->rcomplete);
dbg("quirks=%d", usblp->quirks);
dbg("used=%d", usblp->used);
dbg("bidir=%d", usblp->bidir);
dbg("device_id_string=\"%s\"",
usblp->device_id_string ?
usblp->device_id_string + 2 :
(unsigned char *)"(null)");
}
#endif
extern devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */
static struct usblp *usblp_table[USBLP_MINORS];
......@@ -126,29 +193,45 @@ static struct quirk_printer_struct quirk_printers[] = {
{ 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */
{ 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */
{ 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */
{ 0x0409, 0xefbe, USBLP_QUIRK_BIDIR }, /* NEC Picty900 (HP OEM) */
{ 0, 0 }
};
static int usblp_select_alts(struct usblp *usblp);
static int usblp_set_protocol(struct usblp *usblp, int protocol);
static int usblp_cache_device_id_string(struct usblp *usblp);
/*
* Functions for usblp control messages.
*/
static int usblp_ctrl_msg(struct usblp *usblp, int request, int dir, int recip, int value, void *buf, int len)
static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, int recip, int value, void *buf, int len)
{
int retval = usb_control_msg(usblp->dev,
dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0),
request, USB_TYPE_CLASS | dir | recip, value, usblp->ifnum, buf, len, HZ * 5);
request, type | dir | recip, value, usblp->ifnum, buf, len, USBLP_WRITE_TIMEOUT);
dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d len: %#x result: %d",
request, !!dir, recip, value, len, retval);
return retval < 0 ? retval : 0;
}
#define usblp_read_status(usblp, status)\
usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_DIR_IN, USB_RECIP_INTERFACE, 0, status, 1)
usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_TYPE_CLASS, USB_DIR_IN, USB_RECIP_INTERFACE, 0, status, 1)
#define usblp_get_id(usblp, config, id, maxlen)\
usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_DIR_IN, USB_RECIP_INTERFACE, config, id, maxlen)
usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_TYPE_CLASS, USB_DIR_IN, USB_RECIP_INTERFACE, config, id, maxlen)
#define usblp_reset(usblp)\
usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_DIR_OUT, USB_RECIP_OTHER, 0, NULL, 0)
usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_TYPE_CLASS, USB_DIR_OUT, USB_RECIP_OTHER, 0, NULL, 0)
#define usblp_hp_channel_change_request(usblp, channel, buffer) \
usblp_ctrl_msg(usblp, USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST, USB_TYPE_VENDOR, USB_DIR_IN, USB_RECIP_INTERFACE, channel, buffer, 1)
/*
* See the description for usblp_select_alts() below for the usage
* explanation. Look into your /proc/bus/usb/devices and dmesg in
* case of any trouble.
*/
static int proto_bias = -1;
/*
* URB callback.
......@@ -276,7 +359,7 @@ static void usblp_cleanup (struct usblp *usblp)
{
devfs_unregister (usblp->devfs);
usblp_table [usblp->minor] = NULL;
info ("usblp%d: removed", usblp->minor);
info("usblp%d: removed", usblp->minor);
kfree (usblp->writeurb->transfer_buffer);
kfree (usblp->device_id_string);
......@@ -285,6 +368,13 @@ static void usblp_cleanup (struct usblp *usblp)
kfree (usblp);
}
static void usblp_unlink_urbs(struct usblp *usblp)
{
usb_unlink_urb(usblp->writeurb);
if (usblp->bidir)
usb_unlink_urb(usblp->readurb);
}
static int usblp_release(struct inode *inode, struct file *file)
{
struct usblp *usblp = file->private_data;
......@@ -293,9 +383,7 @@ static int usblp_release(struct inode *inode, struct file *file)
lock_kernel();
usblp->used = 0;
if (usblp->dev) {
if (usblp->bidir)
usb_unlink_urb(usblp->readurb);
usb_unlink_urb(usblp->writeurb);
usblp_unlink_urbs(usblp);
up(&usblp->sem);
} else /* finish cleanup from disconnect */
usblp_cleanup (usblp);
......@@ -315,8 +403,9 @@ static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait
static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
struct usblp *usblp = file->private_data;
int length, err;
unsigned char status;
int length, err, i;
unsigned char status, newChannel;
int twoints[2];
int retval = 0;
down (&usblp->sem);
......@@ -335,32 +424,128 @@ static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
goto done;
}
err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
length = usblp_cache_device_id_string(usblp);
if (length < 0) {
retval = length;
goto done;
}
if (length > _IOC_SIZE(cmd))
length = _IOC_SIZE(cmd); /* truncate */
if (copy_to_user((unsigned char *) arg,
usblp->device_id_string,
(unsigned long) length)) {
retval = -EFAULT;
goto done;
}
break;
case IOCNR_GET_PROTOCOLS:
if (_IOC_DIR(cmd) != _IOC_READ ||
_IOC_SIZE(cmd) < sizeof(twoints)) {
retval = -EINVAL;
goto done;
}
twoints[0] = usblp->current_protocol;
twoints[1] = 0;
for (i = USBLP_FIRST_PROTOCOL;
i <= USBLP_LAST_PROTOCOL; i++) {
if (usblp->protocol[i].alt_setting >= 0)
twoints[1] |= (1<<i);
}
if (copy_to_user((unsigned char *)arg,
(unsigned char *)twoints,
sizeof(twoints))) {
retval = -EFAULT;
goto done;
}
break;
case IOCNR_SET_PROTOCOL:
if (_IOC_DIR(cmd) != _IOC_WRITE) {
retval = -EINVAL;
goto done;
}
#ifdef DEBUG
if (arg == -10) {
usblp_dump(usblp);
break;
}
#endif
usblp_unlink_urbs(usblp);
retval = usblp_set_protocol(usblp, arg);
if (retval < 0) {
usblp_set_protocol(usblp,
usblp->current_protocol);
}
break;
case IOCNR_HP_SET_CHANNEL:
if (_IOC_DIR(cmd) != _IOC_WRITE ||
usblp->dev->descriptor.idVendor != 0x03F0 ||
usblp->quirks & USBLP_QUIRK_BIDIR) {
retval = -EINVAL;
goto done;
}
err = usblp_hp_channel_change_request(usblp,
arg, &newChannel);
if (err < 0) {
dbg ("usblp%d: error = %d reading IEEE-1284 Device ID string",
err("usblp%d: error = %d setting "
"HP channel",
usblp->minor, err);
usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
retval = -EIO;
goto done;
}
length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; /* big-endian */
if (length < DEVICE_ID_SIZE)
usblp->device_id_string[length] = '\0';
else
usblp->device_id_string[DEVICE_ID_SIZE - 1] = '\0';
dbg("usblp%d requested/got HP channel %ld/%d",
usblp->minor, arg, newChannel);
break;
dbg ("usblp%d Device ID string [%d/max %d]='%s'",
usblp->minor, length, _IOC_SIZE(cmd), &usblp->device_id_string[2]);
case IOCNR_GET_BUS_ADDRESS:
if (_IOC_DIR(cmd) != _IOC_READ ||
_IOC_SIZE(cmd) < sizeof(twoints)) {
retval = -EINVAL;
goto done;
}
if (length > _IOC_SIZE(cmd)) length = _IOC_SIZE(cmd); /* truncate */
twoints[0] = usblp->dev->bus->busnum;
twoints[1] = usblp->dev->devnum;
if (copy_to_user((unsigned char *)arg,
(unsigned char *)twoints,
sizeof(twoints))) {
retval = -EFAULT;
goto done;
}
if (copy_to_user((unsigned char *) arg,
usblp->device_id_string, (unsigned long) length)) {
dbg("usblp%d is bus=%d, device=%d",
usblp->minor, twoints[0], twoints[1]);
break;
case IOCNR_GET_VID_PID:
if (_IOC_DIR(cmd) != _IOC_READ ||
_IOC_SIZE(cmd) < sizeof(twoints)) {
retval = -EINVAL;
goto done;
}
twoints[0] = usblp->dev->descriptor.idVendor;
twoints[1] = usblp->dev->descriptor.idProduct;
if (copy_to_user((unsigned char *)arg,
(unsigned char *)twoints,
sizeof(twoints))) {
retval = -EFAULT;
goto done;
}
dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X",
usblp->minor, twoints[0], twoints[1]);
break;
default:
......@@ -593,155 +778,268 @@ static struct file_operations usblp_fops = {
static void *usblp_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
{
struct usb_interface_descriptor *interface;
struct usb_endpoint_descriptor *epread, *epwrite;
struct usblp *usblp;
int minor, i, bidir = 0, quirks;
int alts = dev->actconfig->interface[ifnum].act_altsetting;
int length, err;
char *buf;
struct usblp *usblp = 0;
int protocol;
char name[6];
/* If a bidirectional interface exists, use it. */
for (i = 0; i < dev->actconfig->interface[ifnum].num_altsetting; i++) {
interface = &dev->actconfig->interface[ifnum].altsetting[i];
if (interface->bInterfaceClass != 7 || interface->bInterfaceSubClass != 1 ||
interface->bInterfaceProtocol < 1 || interface->bInterfaceProtocol > 3 ||
(interface->bInterfaceProtocol > 1 && interface->bNumEndpoints < 2))
continue;
if (interface->bInterfaceProtocol > 1) {
bidir = 1;
alts = i;
break;
}
}
interface = &dev->actconfig->interface[ifnum].altsetting[alts];
if (usb_set_interface(dev, ifnum, alts))
err("can't set desired altsetting %d on interface %d", alts, ifnum);
epwrite = interface->endpoint + 0;
epread = bidir ? interface->endpoint + 1 : NULL;
if ((epwrite->bEndpointAddress & 0x80) == 0x80) {
if (interface->bNumEndpoints == 1)
return NULL;
epwrite = interface->endpoint + 1;
epread = bidir ? interface->endpoint + 0 : NULL;
}
if ((epwrite->bEndpointAddress & 0x80) == 0x80)
return NULL;
if (bidir && (epread->bEndpointAddress & 0x80) != 0x80)
return NULL;
for (minor = 0; minor < USBLP_MINORS && usblp_table[minor]; minor++);
if (usblp_table[minor]) {
err("no more free usblp devices");
return NULL;
}
/* Malloc and start initializing usblp structure so we can use it
* directly. */
if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) {
err("out of memory");
return NULL;
err("out of memory for usblp");
goto abort;
}
memset(usblp, 0, sizeof(struct usblp));
init_MUTEX (&usblp->sem);
/* lookup quirks for this printer */
quirks = usblp_quirks(dev->descriptor.idVendor, dev->descriptor.idProduct);
if (bidir && (quirks & USBLP_QUIRK_BIDIR)) {
bidir = 0;
epread = NULL;
info ("Disabling reads from problem bidirectional printer on usblp%d",
minor);
}
usblp->dev = dev;
init_MUTEX (&usblp->sem);
init_waitqueue_head(&usblp->wait);
usblp->ifnum = ifnum;
usblp->minor = minor;
usblp->bidir = bidir;
usblp->quirks = quirks;
init_waitqueue_head(&usblp->wait);
/* Look for a free usblp_table entry. */
while (usblp_table[usblp->minor]) {
usblp->minor++;
if (usblp->minor >= USBLP_MINORS) {
err("no more free usblp devices");
goto abort;
}
}
usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL);
if (!usblp->writeurb) {
err("out of memory");
kfree(usblp);
return NULL;
goto abort;
}
usblp->readurb = usb_alloc_urb(0, GFP_KERNEL);
if (!usblp->readurb) {
err("out of memory");
usb_free_urb(usblp->writeurb);
kfree(usblp);
return NULL;
goto abort;
}
if (!(buf = kmalloc(USBLP_BUF_SIZE * (bidir ? 2 : 1), GFP_KERNEL))) {
err("out of memory");
usb_free_urb(usblp->writeurb);
usb_free_urb(usblp->readurb);
kfree(usblp);
return NULL;
/* Malloc device ID string buffer to the largest expected length,
* since we can re-query it on an ioctl and a dynamic string
* could change in length. */
if (!(usblp->device_id_string = kmalloc(DEVICE_ID_SIZE, GFP_KERNEL))) {
err("out of memory for device_id_string");
goto abort;
}
if (!(usblp->device_id_string = kmalloc(DEVICE_ID_SIZE, GFP_KERNEL))) {
err("out of memory");
usb_free_urb(usblp->writeurb);
usb_free_urb(usblp->readurb);
kfree(usblp);
kfree(buf);
return NULL;
/* Malloc write/read buffers in one chunk. We somewhat wastefully
* malloc both regardless of bidirectionality, because the
* alternate setting can be changed later via an ioctl. */
if (!(usblp->buf = kmalloc(2 * USBLP_BUF_SIZE, GFP_KERNEL))) {
err("out of memory for buf");
goto abort;
}
FILL_BULK_URB(usblp->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
buf, 0, usblp_bulk_write, usblp);
/* Lookup quirks for this printer. */
usblp->quirks = usblp_quirks(
dev->descriptor.idVendor,
dev->descriptor.idProduct);
/* Analyze and pick initial alternate settings and endpoints. */
protocol = usblp_select_alts(usblp);
if (protocol < 0) {
dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
dev->descriptor.idVendor,
dev->descriptor.idProduct);
goto abort;
}
if (bidir)
FILL_BULK_URB(usblp->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE, usblp_bulk_read, usblp);
/* Setup the selected alternate setting and endpoints. */
if (usblp_set_protocol(usblp, protocol) < 0)
goto abort;
/* Get the device_id string if possible. FIXME: Could make this kmalloc(length). */
err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
if (err >= 0) {
length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1]; /* big-endian */
if (length < DEVICE_ID_SIZE)
usblp->device_id_string[length] = '\0';
else
usblp->device_id_string[DEVICE_ID_SIZE - 1] = '\0';
dbg ("usblp%d Device ID string [%d]=%s",
minor, length, &usblp->device_id_string[2]);
}
else {
err ("usblp%d: error = %d reading IEEE-1284 Device ID string",
minor, err);
usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
}
/* Retrieve and store the device ID string. */
usblp_cache_device_id_string(usblp);
#ifdef DEBUG
usblp_check_status(usblp, 0);
#endif
sprintf(name, "lp%d", minor);
/* if we have devfs, create with perms=660 */
/* If we have devfs, create with perms=660. */
sprintf(name, "lp%d", usblp->minor);
usblp->devfs = devfs_register(usb_devfs_handle, name,
DEVFS_FL_DEFAULT, USB_MAJOR,
USBLP_MINOR_BASE + minor,
USBLP_MINOR_BASE + usblp->minor,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP |
S_IWGRP, &usblp_fops, NULL);
info("usblp%d: USB %sdirectional printer dev %d if %d alt %d",
minor, bidir ? "Bi" : "Uni", dev->devnum, ifnum, alts);
info("usblp%d: USB %sdirectional printer dev %d "
"if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X",
usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum, ifnum,
usblp->protocol[usblp->current_protocol].alt_setting,
usblp->current_protocol, usblp->dev->descriptor.idVendor,
usblp->dev->descriptor.idProduct);
return usblp_table[minor] = usblp;
return usblp_table[usblp->minor] = usblp;
abort:
if (usblp) {
usb_free_urb(usblp->writeurb);
usb_free_urb(usblp->readurb);
if (usblp->buf) kfree(usblp->buf);
if (usblp->device_id_string) kfree(usblp->device_id_string);
kfree(usblp);
}
return NULL;
}
/*
* We are a "new" style driver with usb_device_id table,
* but our requirements are too intricate for simple match to handle.
*
* The "proto_bias" option may be used to specify the preferred protocol
* for all USB printers (1=7/1/1, 2=7/1/2, 3=7/1/3). If the device
* supports the preferred protocol, then we bind to it.
*
* The best interface for us is 7/1/2, because it is compatible
* with a stream of characters. If we find it, we bind to it.
*
* Note that the people from hpoj.sourceforge.net need to be able to
* bind to 7/1/3 (MLC/1284.4), so we provide them ioctls for this purpose.
*
* Failing 7/1/2, we look for 7/1/3, even though it's probably not
* stream-compatible, because this matches the behaviour of the old code.
*
* If nothing else, we bind to 7/1/1 - the unidirectional interface.
*/
static int usblp_select_alts(struct usblp *usblp)
{
struct usb_interface *if_alt;
struct usb_interface_descriptor *ifd;
struct usb_endpoint_descriptor *epd, *epwrite, *epread;
int p, i, e;
if_alt = &usblp->dev->actconfig->interface[usblp->ifnum];
for (p = 0; p < USBLP_MAX_PROTOCOLS; p++)
usblp->protocol[p].alt_setting = -1;
/* Find out what we have. */
for (i = 0; i < if_alt->num_altsetting; i++) {
ifd = &if_alt->altsetting[i];
if (ifd->bInterfaceClass != 7 || ifd->bInterfaceSubClass != 1)
continue;
if (ifd->bInterfaceProtocol < USBLP_FIRST_PROTOCOL ||
ifd->bInterfaceProtocol > USBLP_LAST_PROTOCOL)
continue;
/* Look for bulk OUT and IN endpoints. */
epwrite = epread = 0;
for (e = 0; e < ifd->bNumEndpoints; e++) {
epd = &ifd->endpoint[e];
if ((epd->bmAttributes&USB_ENDPOINT_XFERTYPE_MASK)!=
USB_ENDPOINT_XFER_BULK)
continue;
if (!(epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)) {
if (!epwrite) epwrite=epd;
} else {
if (!epread) epread=epd;
}
}
/* Ignore buggy hardware without the right endpoints. */
if (!epwrite || (ifd->bInterfaceProtocol > 1 && !epread))
continue;
/* Turn off reads for 7/1/1 (unidirectional) interfaces
* and buggy bidirectional printers. */
if (ifd->bInterfaceProtocol == 1) {
epread = NULL;
} else if (usblp->quirks & USBLP_QUIRK_BIDIR) {
info("Disabling reads from problem bidirectional "
"printer on usblp%d", usblp->minor);
epread = NULL;
}
usblp->protocol[ifd->bInterfaceProtocol].alt_setting = i;
usblp->protocol[ifd->bInterfaceProtocol].epwrite = epwrite;
usblp->protocol[ifd->bInterfaceProtocol].epread = epread;
}
/* If our requested protocol is supported, then use it. */
if (proto_bias >= USBLP_FIRST_PROTOCOL &&
proto_bias <= USBLP_LAST_PROTOCOL &&
usblp->protocol[proto_bias].alt_setting != -1)
return proto_bias;
/* Ordering is important here. */
if (usblp->protocol[2].alt_setting != -1) return 2;
if (usblp->protocol[1].alt_setting != -1) return 1;
if (usblp->protocol[3].alt_setting != -1) return 3;
/* If nothing is available, then don't bind to this device. */
return -1;
}
static int usblp_set_protocol(struct usblp *usblp, int protocol)
{
int r, alts;
if (protocol < USBLP_FIRST_PROTOCOL || protocol > USBLP_LAST_PROTOCOL)
return -EINVAL;
alts = usblp->protocol[protocol].alt_setting;
if (alts < 0) return -EINVAL;
r = usb_set_interface(usblp->dev, usblp->ifnum, alts);
if (r < 0) {
err("can't set desired altsetting %d on interface %d",
alts, usblp->ifnum);
return r;
}
FILL_BULK_URB(usblp->writeurb, usblp->dev,
usb_sndbulkpipe(usblp->dev,
usblp->protocol[protocol].epwrite->bEndpointAddress),
usblp->buf, 0,
usblp_bulk_write, usblp);
usblp->bidir = (usblp->protocol[protocol].epread != 0);
if (usblp->bidir)
FILL_BULK_URB(usblp->readurb, usblp->dev,
usb_rcvbulkpipe(usblp->dev,
usblp->protocol[protocol].epread->bEndpointAddress),
usblp->buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE,
usblp_bulk_read, usblp);
usblp->current_protocol = protocol;
dbg("usblp%d set protocol %d", usblp->minor, protocol);
return 0;
}
/* Retrieves and caches device ID string.
* Returns length, including length bytes but not null terminator.
* On error, returns a negative errno value. */
static int usblp_cache_device_id_string(struct usblp *usblp)
{
int err, length;
err = usblp_get_id(usblp, 0, usblp->device_id_string, DEVICE_ID_SIZE - 1);
if (err < 0) {
dbg("usblp%d: error = %d reading IEEE-1284 Device ID string",
usblp->minor, err);
usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
return -EIO;
}
/* First two bytes are length in big-endian.
* They count themselves, and we copy them into
* the user's buffer. */
length = (usblp->device_id_string[0] << 8) + usblp->device_id_string[1];
if (length < 2)
length = 2;
else if (length >= DEVICE_ID_SIZE)
length = DEVICE_ID_SIZE - 1;
usblp->device_id_string[length] = '\0';
dbg("usblp%d Device ID string [len=%d]=\"%s\"",
usblp->minor, length, &usblp->device_id_string[2]);
return length;
}
static void usblp_disconnect(struct usb_device *dev, void *ptr)
......@@ -757,9 +1055,7 @@ static void usblp_disconnect(struct usb_device *dev, void *ptr)
lock_kernel();
usblp->dev = NULL;
usb_unlink_urb(usblp->writeurb);
if (usblp->bidir)
usb_unlink_urb(usblp->readurb);
usblp_unlink_urbs(usblp);
if (!usblp->used)
usblp_cleanup (usblp);
......@@ -794,7 +1090,7 @@ static int __init usblp_init(void)
{
if (usb_register(&usblp_driver))
return -1;
info(DRIVER_VERSION ":" DRIVER_DESC);
info(DRIVER_VERSION ": " DRIVER_DESC);
return 0;
}
......@@ -808,5 +1104,6 @@ module_exit(usblp_exit);
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_PARM(proto_bias, "i");
MODULE_PARM_DESC(proto_bias, "Favourite protocol number");
MODULE_LICENSE("GPL");
......@@ -262,7 +262,7 @@ static int cyberjack_write (struct usb_serial_port *port, int from_user, const u
port);
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_KERNEL);
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
/* Throw away data. No better idea what to do with it. */
......@@ -331,7 +331,7 @@ static void cyberjack_read_int_callback( struct urb *urb )
if( !old_rdtodo ) {
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if( result )
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
dbg(__FUNCTION__ " - usb_submit_urb(read urb)");
......@@ -387,7 +387,7 @@ static void cyberjack_read_bulk_callback (struct urb *urb)
/* Continue to read if we have still urbs to do. */
if( priv->rdtodo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/ ) {
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
dbg(__FUNCTION__ " - usb_submit_urb(read urb)");
......@@ -440,7 +440,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb)
port);
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_KERNEL);
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
/* Throw away data. No better idea what to do with it. */
......
......@@ -676,7 +676,7 @@ dbg( "digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, co
oob_port->write_urb->transfer_buffer_length = len;
oob_port->write_urb->dev = port->serial->dev;
if( (ret=usb_submit_urb(oob_port->write_urb, GFP_KERNEL)) == 0 ) {
if( (ret=usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0 ) {
oob_priv->dp_write_urb_in_use = 1;
count -= len;
buf += len;
......@@ -764,7 +764,7 @@ count );
}
port->write_urb->dev = port->serial->dev;
if( (ret=usb_submit_urb(port->write_urb, GFP_KERNEL)) == 0 ) {
if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) {
priv->dp_write_urb_in_use = 1;
priv->dp_out_buf_len = 0;
count -= len;
......@@ -841,7 +841,7 @@ port_priv->dp_port_num, modem_signals );
oob_port->write_urb->transfer_buffer_length = 8;
oob_port->write_urb->dev = port->serial->dev;
if( (ret=usb_submit_urb(oob_port->write_urb, GFP_KERNEL)) == 0 ) {
if( (ret=usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0 ) {
oob_priv->dp_write_urb_in_use = 1;
port_priv->dp_modem_signals =
(port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS))
......@@ -962,7 +962,7 @@ dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num );
/* restart read chain */
if( priv->dp_throttle_restart ) {
port->read_urb->dev = port->serial->dev;
ret = usb_submit_urb( port->read_urb, GFP_KERNEL );
ret = usb_submit_urb( port->read_urb, GFP_ATOMIC );
}
/* turn throttle off */
......@@ -1323,7 +1323,7 @@ priv->dp_port_num, count, from_user, in_interrupt() );
/* copy in new data */
memcpy( data, from_user ? user_buf : buf, new_len );
if( (ret=usb_submit_urb(port->write_urb, GFP_KERNEL)) == 0 ) {
if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) {
priv->dp_write_urb_in_use = 1;
ret = new_len;
priv->dp_out_buf_len = 0;
......@@ -1399,7 +1399,7 @@ dbg( "digi_write_bulk_callback: TOP, urb->status=%d", urb->status );
memcpy( port->write_urb->transfer_buffer+2, priv->dp_out_buf,
priv->dp_out_buf_len );
if( (ret=usb_submit_urb(port->write_urb, GFP_KERNEL)) == 0 ) {
if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) {
priv->dp_write_urb_in_use = 1;
priv->dp_out_buf_len = 0;
}
......@@ -1837,7 +1837,7 @@ dbg( "digi_read_bulk_callback: TOP" );
/* continue read */
urb->dev = port->serial->dev;
if( (ret=usb_submit_urb(urb, GFP_KERNEL)) != 0 ) {
if( (ret=usb_submit_urb(urb, GFP_ATOMIC)) != 0 ) {
err( __FUNCTION__ ": failed resubmitting urb, ret=%d, port=%d",
ret, priv->dp_port_num );
}
......
......@@ -256,7 +256,7 @@ static int empeg_write (struct usb_serial_port *port, int from_user, const unsig
}
if (urb->transfer_buffer == NULL) {
urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
if (urb->transfer_buffer == NULL) {
err(__FUNCTION__" no more kernel memory...");
goto exit;
......@@ -288,7 +288,7 @@ static int empeg_write (struct usb_serial_port *port, int from_user, const unsig
urb->transfer_flags |= USB_QUEUE_BULK;
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_KERNEL);
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
bytes_sent = status;
......@@ -441,7 +441,7 @@ static void empeg_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_flags |= USB_QUEUE_BULK;
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
......@@ -466,7 +466,7 @@ static void empeg_unthrottle (struct usb_serial_port *port)
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d", result);
......
......@@ -469,7 +469,7 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user,
port->write_urb->transfer_buffer, count,
ftdi_sio_write_bulk_callback, port);
result = usb_submit_urb(port->write_urb, GFP_KERNEL);
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
return 0;
......@@ -631,7 +631,7 @@ static void ftdi_sio_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
ftdi_sio_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
......
......@@ -790,7 +790,7 @@ static void edge_interrupt_callback (struct urb *urb)
/* we have pending bytes on the bulk in pipe, send a request */
edge_serial->read_urb->dev = edge_serial->serial->dev;
result = usb_submit_urb(edge_serial->read_urb, GFP_KERNEL);
result = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
if (result) {
dbg(__FUNCTION__" - usb_submit_urb(read bulk) failed with result = %d", result);
}
......@@ -867,7 +867,7 @@ static void edge_bulk_in_callback (struct urb *urb)
/* there is, so resubmit our urb */
edge_serial->read_urb->dev = edge_serial->serial->dev;
status = usb_submit_urb(edge_serial->read_urb, GFP_KERNEL);
status = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
if (status) {
err(__FUNCTION__" - usb_submit_urb(read bulk) failed, status = %d", status);
}
......@@ -1435,7 +1435,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
/* build the data header for the buffer and port that we are about to send out */
count = fifo->count;
buffer = kmalloc (count+2, GFP_KERNEL);
buffer = kmalloc (count+2, GFP_ATOMIC);
if (buffer == NULL) {
err(__FUNCTION__" - no more kernel memory...");
edge_port->write_in_progress = FALSE;
......@@ -1474,7 +1474,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
urb->transfer_flags |= USB_QUEUE_BULK;
urb->dev = edge_serial->serial->dev;
status = usb_submit_urb(urb, GFP_KERNEL);
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
/* something went wrong */
dbg(__FUNCTION__" - usb_submit_urb(write bulk) failed");
......@@ -2431,7 +2431,7 @@ static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u
dbg(__FUNCTION__" - %d, %d", command, param);
buffer = kmalloc (10, GFP_KERNEL);
buffer = kmalloc (10, GFP_ATOMIC);
if (!buffer) {
err(__FUNCTION__" - kmalloc(%d) failed.\n", 10);
return -ENOMEM;
......@@ -2467,7 +2467,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
usb_serial_debug_data (__FILE__, __FUNCTION__, length, buffer);
/* Allocate our next urb */
urb = usb_alloc_urb (0, GFP_KERNEL);
urb = usb_alloc_urb (0, GFP_ATOMIC);
if (!urb)
return -ENOMEM;
......@@ -2482,7 +2482,7 @@ static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer
urb->transfer_flags |= USB_QUEUE_BULK;
edge_port->commandPending = TRUE;
status = usb_submit_urb(urb, GFP_KERNEL);
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
/* something went wrong */
......@@ -2532,7 +2532,7 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa
}
// Alloc memory for the string of commands.
cmdBuffer = kmalloc (0x100, GFP_KERNEL);
cmdBuffer = kmalloc (0x100, GFP_ATOMIC);
if (!cmdBuffer) {
err(__FUNCTION__" - kmalloc(%d) failed.\n", 0x100);
return -ENOMEM;
......@@ -2618,7 +2618,7 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
dbg (__FUNCTION__" - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", regValue);
// Alloc memory for the string of commands.
cmdBuffer = kmalloc (0x10, GFP_KERNEL);
cmdBuffer = kmalloc (0x10, GFP_ATOMIC);
if (cmdBuffer == NULL ) {
return -ENOMEM;
}
......
......@@ -297,7 +297,7 @@ static void ipaq_read_bulk_callback(struct urb *urb)
usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
ipaq_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
return;
......@@ -412,7 +412,7 @@ static int ipaq_write_flush(struct usb_serial_port *port)
usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, count, ipaq_write_bulk_callback,
port);
result = usb_submit_urb(urb, GFP_KERNEL);
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
}
......
......@@ -405,7 +405,7 @@ static int ir_write (struct usb_serial_port *port, int from_user, const unsigned
= USB_QUEUE_BULK
| USB_ZERO_PACKET;
result = usb_submit_urb (port->write_urb, GFP_KERNEL);
result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
if (result)
err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
else
......@@ -515,7 +515,7 @@ static void ir_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_flags = USB_QUEUE_BULK;
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err("%s - failed resubmitting read urb, error %d",
......
......@@ -378,7 +378,7 @@ static int keyspan_write(struct usb_serial_port *port, int from_user,
this_urb->transfer_flags &= ~USB_ASYNC_UNLINK;
this_urb->dev = port->serial->dev;
if ((err = usb_submit_urb(this_urb, GFP_KERNEL)) != 0) {
if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
dbg("usb_submit_urb(write bulk) failed (%d)\n", err);
}
p_priv->tx_start_time[flip] = jiffies;
......@@ -436,7 +436,7 @@ static void usa26_indat_callback(struct urb *urb)
/* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
}
return;
......@@ -535,7 +535,7 @@ static void usa26_instat_callback(struct urb *urb)
exit:
/* Resubmit urb so we continue receiving */
urb->dev = serial->dev;
if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
}
}
......@@ -586,7 +586,7 @@ static void usa28_indat_callback(struct urb *urb)
/* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n",
err);
}
......@@ -671,7 +671,7 @@ static void usa28_instat_callback(struct urb *urb)
exit:
/* Resubmit urb so we continue receiving */
urb->dev = serial->dev;
if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
}
}
......@@ -764,7 +764,7 @@ static void usa49_instat_callback(struct urb *urb)
/* Resubmit urb so we continue receiving */
urb->dev = serial->dev;
if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
}
}
......@@ -819,7 +819,7 @@ static void usa49_indat_callback(struct urb *urb)
/* Resubmit urb so we continue receiving */
urb->dev = port->serial->dev;
if ((err = usb_submit_urb(urb, GFP_KERNEL)) != 0) {
if ((err = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
dbg(__FUNCTION__ "resubmit read urb failed. (%d)\n", err);
}
}
......
......@@ -292,7 +292,7 @@ static void keyspan_pda_rx_unthrottle (struct usb_serial_port *port)
/* just restart the receive interrupt URB */
dbg("keyspan_pda_rx_unthrottle port %d", port->number);
port->interrupt_in_urb->dev = port->serial->dev;
if (usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL))
if (usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC))
dbg(" usb_submit_urb(read urb) failed");
return;
}
......@@ -584,7 +584,7 @@ static int keyspan_pda_write(struct usb_serial_port *port, int from_user,
priv->tx_room -= count;
port->write_urb->dev = port->serial->dev;
rc = usb_submit_urb(port->write_urb, GFP_KERNEL);
rc = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (rc) {
dbg(" usb_submit_urb(write bulk) failed");
goto exit;
......
......@@ -519,7 +519,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
}
if (urb->transfer_buffer == NULL) {
urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
if (urb->transfer_buffer == NULL) {
err(__FUNCTION__ " - no more kernel memory...");
goto exit;
......@@ -555,7 +555,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
/* send the data out the bulk port */
result = usb_submit_urb(urb, GFP_KERNEL);
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__
" - failed submitting write urb, error %d", result);
......@@ -721,7 +721,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_buffer_length,
klsi_105_read_bulk_callback,
port);
rc = usb_submit_urb(port->read_urb, GFP_KERNEL);
rc = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (rc)
err(__FUNCTION__
" - failed resubmitting read urb, error %d", rc);
......@@ -1019,7 +1019,7 @@ static void klsi_105_unthrottle (struct usb_serial_port *port)
dbg(__FUNCTION__ " - port %d", port->number);
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d",
result);
......
......@@ -470,7 +470,7 @@ static int mct_u232_write (struct usb_serial_port *port, int from_user,
port);
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_KERNEL);
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result) {
err(__FUNCTION__
" - failed submitting write urb, error %d", result);
......
......@@ -265,7 +265,7 @@ static void omninet_read_bulk_callback (struct urb *urb)
usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
urb->transfer_buffer, urb->transfer_buffer_length,
omninet_read_bulk_callback, port);
result = usb_submit_urb(urb, GFP_KERNEL);
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
......@@ -316,7 +316,7 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns
wport->write_urb->transfer_buffer_length = 64;
wport->write_urb->dev = serial->dev;
result = usb_submit_urb(wport->write_urb, GFP_KERNEL);
result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
else
......
......@@ -195,7 +195,7 @@ static int pl2303_write (struct usb_serial_port *port, int from_user, const uns
port->write_urb->transfer_buffer_length = count;
port->write_urb->dev = port->serial->dev;
result = usb_submit_urb (port->write_urb, GFP_KERNEL);
result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
else
......@@ -643,7 +643,7 @@ static void pl2303_read_bulk_callback (struct urb *urb)
dbg (__FUNCTION__ " - caught -EPROTO, resubmitting the urb");
urb->status = 0;
urb->dev = serial->dev;
result = usb_submit_urb(urb, GFP_KERNEL);
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
return;
......@@ -668,7 +668,7 @@ static void pl2303_read_bulk_callback (struct urb *urb)
/* Schedule the next read _if_ we are still open */
if (port->open_count) {
urb->dev = serial->dev;
result = usb_submit_urb(urb, GFP_KERNEL);
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
}
......@@ -697,7 +697,7 @@ static void pl2303_write_bulk_callback (struct urb *urb)
dbg (__FUNCTION__ " - nonzero write bulk status received: %d", urb->status);
port->write_urb->transfer_buffer_length = 1;
port->write_urb->dev = port->serial->dev;
result = usb_submit_urb (port->write_urb, GFP_KERNEL);
result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting write urb, error %d", result);
......
......@@ -899,7 +899,7 @@ static int generic_write (struct usb_serial_port *port, int from_user, const uns
generic_write_bulk_callback), port);
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_KERNEL);
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting write urb, error %d", result);
else
......@@ -989,7 +989,7 @@ static void generic_read_bulk_callback (struct urb *urb)
((serial->type->read_bulk_callback) ?
serial->type->read_bulk_callback :
generic_read_bulk_callback), port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
}
......
......@@ -344,13 +344,13 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig
dbg(__FUNCTION__ " - port %d", port->number);
buffer = kmalloc (count, GFP_KERNEL);
buffer = kmalloc (count, GFP_ATOMIC);
if (!buffer) {
err ("out of memory");
return -ENOMEM;
}
urb = usb_alloc_urb(0, GFP_KERNEL);
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
err ("no more free urbs");
kfree (buffer);
......@@ -377,7 +377,7 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig
urb->transfer_flags |= USB_QUEUE_BULK;
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_KERNEL);
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
err(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status);
count = status;
......@@ -491,7 +491,7 @@ static void visor_read_bulk_callback (struct urb *urb)
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
visor_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
return;
......@@ -512,7 +512,7 @@ static void visor_unthrottle (struct usb_serial_port *port)
dbg(__FUNCTION__ " - port %d", port->number);
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
err(__FUNCTION__ " - failed submitting read urb, error %d", result);
}
......
......@@ -240,7 +240,7 @@ static void command_port_read_callback (struct urb *urb)
usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
command_port_read_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
dbg(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
}
......
......@@ -119,6 +119,7 @@ struct hiddev_usage_ref {
__s32 value;
};
#define HID_FIELD_INDEX_NONE 0xffffffff
/*
* Protocol version.
......@@ -143,6 +144,15 @@ struct hiddev_usage_ref {
#define HIDIOCGUSAGE _IOWR('H', 0x0B, struct hiddev_usage_ref)
#define HIDIOCSUSAGE _IOW('H', 0x0C, struct hiddev_usage_ref)
#define HIDIOCGUCODE _IOWR('H', 0x0D, struct hiddev_usage_ref)
#define HIDIOCGFLAG _IOR('H', 0x0E, int)
#define HIDIOCSFLAG _IOW('H', 0x0F, int)
/*
* Flags to be used in HIDIOCSFLAG
*/
#define HIDDEV_FLAG_UREF 0x1
#define HIDDEV_FLAG_REPORT 0x2
#define HIDDEV_FLAGS 0x3
/* To traverse the input report descriptor info for a HID device, perform the
* following:
......@@ -179,7 +189,7 @@ struct hiddev_usage_ref {
#ifdef CONFIG_USB_HIDDEV
int hiddev_connect(struct hid_device *);
void hiddev_disconnect(struct hid_device *);
void hiddev_hid_event(struct hid_device *, unsigned int usage, int value);
void hiddev_hid_event(struct hid_device *, struct hiddev_usage_ref *ref);
int __init hiddev_init(void);
void __exit hiddev_exit(void);
#else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment