mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 22:21:42 +00:00
Merge branches 'upstream', 'raw_report_modifications' and 'apple_magic_mouse' into for-linus
Conflicts: drivers/hid/Kconfig
This commit is contained in:
commit
14ef2b0c02
@ -143,8 +143,8 @@ o provide a way to configure fault attributes
|
||||
failslab, fail_page_alloc, and fail_make_request use this way.
|
||||
Helper functions:
|
||||
|
||||
init_fault_attr_entries(entries, attr, name);
|
||||
void cleanup_fault_attr_entries(entries);
|
||||
init_fault_attr_dentries(entries, attr, name);
|
||||
void cleanup_fault_attr_dentries(entries);
|
||||
|
||||
- module parameters
|
||||
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include <asm/numa.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/init.h>
|
||||
#include <linux/bootmem.h>
|
||||
|
||||
static unsigned long dma_reserve __initdata;
|
||||
|
||||
@ -615,6 +616,21 @@ void __init paging_init(void)
|
||||
* Memory hotplug specific functions
|
||||
*/
|
||||
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||
/*
|
||||
* After memory hotplug the variables max_pfn, max_low_pfn and high_memory need
|
||||
* updating.
|
||||
*/
|
||||
static void update_end_of_memory_vars(u64 start, u64 size)
|
||||
{
|
||||
unsigned long end_pfn = PFN_UP(start + size);
|
||||
|
||||
if (end_pfn > max_pfn) {
|
||||
max_pfn = end_pfn;
|
||||
max_low_pfn = end_pfn;
|
||||
high_memory = (void *)__va(max_pfn * PAGE_SIZE - 1) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Memory is added always to NORMAL zone. This means you will never get
|
||||
* additional DMA/DMA32 memory.
|
||||
@ -634,6 +650,9 @@ int arch_add_memory(int nid, u64 start, u64 size)
|
||||
ret = __add_pages(nid, zone, start_pfn, nr_pages);
|
||||
WARN_ON_ONCE(ret);
|
||||
|
||||
/* update max_pfn, max_low_pfn and high_memory */
|
||||
update_end_of_memory_vars(start, size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(arch_add_memory);
|
||||
|
@ -322,7 +322,7 @@ static void pkt_sysfs_dev_remove(struct pktcdvd_device *pd)
|
||||
pkt_kobj_remove(pd->kobj_stat);
|
||||
pkt_kobj_remove(pd->kobj_wqueue);
|
||||
if (class_pktcdvd)
|
||||
device_destroy(class_pktcdvd, pd->pkt_dev);
|
||||
device_unregister(pd->dev);
|
||||
}
|
||||
|
||||
|
||||
|
@ -195,5 +195,16 @@ config BT_MRVL_SDIO
|
||||
Say Y here to compile support for Marvell BT-over-SDIO driver
|
||||
into the kernel or say M to compile it as module.
|
||||
|
||||
endmenu
|
||||
config BT_ATH3K
|
||||
tristate "Atheros firmware download driver"
|
||||
depends on BT_HCIBTUSB
|
||||
select FW_LOADER
|
||||
help
|
||||
Bluetooth firmware download driver.
|
||||
This driver loads the firmware into the Atheros Bluetooth
|
||||
chipset.
|
||||
|
||||
Say Y here to compile support for "Atheros firmware download driver"
|
||||
into the kernel or say M to compile it as module (ath3k).
|
||||
|
||||
endmenu
|
||||
|
@ -15,6 +15,7 @@ obj-$(CONFIG_BT_HCIBTUART) += btuart_cs.o
|
||||
obj-$(CONFIG_BT_HCIBTUSB) += btusb.o
|
||||
obj-$(CONFIG_BT_HCIBTSDIO) += btsdio.o
|
||||
|
||||
obj-$(CONFIG_BT_ATH3K) += ath3k.o
|
||||
obj-$(CONFIG_BT_MRVL) += btmrvl.o
|
||||
obj-$(CONFIG_BT_MRVL_SDIO) += btmrvl_sdio.o
|
||||
|
||||
|
187
drivers/bluetooth/ath3k.c
Normal file
187
drivers/bluetooth/ath3k.c
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Atheros Communications Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/usb.h>
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
|
||||
#define VERSION "1.0"
|
||||
|
||||
|
||||
static struct usb_device_id ath3k_table[] = {
|
||||
/* Atheros AR3011 */
|
||||
{ USB_DEVICE(0x0CF3, 0x3000) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, ath3k_table);
|
||||
|
||||
#define USB_REQ_DFU_DNLOAD 1
|
||||
#define BULK_SIZE 4096
|
||||
|
||||
struct ath3k_data {
|
||||
struct usb_device *udev;
|
||||
u8 *fw_data;
|
||||
u32 fw_size;
|
||||
u32 fw_sent;
|
||||
};
|
||||
|
||||
static int ath3k_load_firmware(struct ath3k_data *data,
|
||||
unsigned char *firmware,
|
||||
int count)
|
||||
{
|
||||
u8 *send_buf;
|
||||
int err, pipe, len, size, sent = 0;
|
||||
|
||||
BT_DBG("ath3k %p udev %p", data, data->udev);
|
||||
|
||||
pipe = usb_sndctrlpipe(data->udev, 0);
|
||||
|
||||
if ((usb_control_msg(data->udev, pipe,
|
||||
USB_REQ_DFU_DNLOAD,
|
||||
USB_TYPE_VENDOR, 0, 0,
|
||||
firmware, 20, USB_CTRL_SET_TIMEOUT)) < 0) {
|
||||
BT_ERR("Can't change to loading configuration err");
|
||||
return -EBUSY;
|
||||
}
|
||||
sent += 20;
|
||||
count -= 20;
|
||||
|
||||
send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
|
||||
if (!send_buf) {
|
||||
BT_ERR("Can't allocate memory chunk for firmware");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
while (count) {
|
||||
size = min_t(uint, count, BULK_SIZE);
|
||||
pipe = usb_sndbulkpipe(data->udev, 0x02);
|
||||
memcpy(send_buf, firmware + sent, size);
|
||||
|
||||
err = usb_bulk_msg(data->udev, pipe, send_buf, size,
|
||||
&len, 3000);
|
||||
|
||||
if (err || (len != size)) {
|
||||
BT_ERR("Error in firmware loading err = %d,"
|
||||
"len = %d, size = %d", err, len, size);
|
||||
goto error;
|
||||
}
|
||||
|
||||
sent += size;
|
||||
count -= size;
|
||||
}
|
||||
|
||||
kfree(send_buf);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
kfree(send_buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ath3k_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
const struct firmware *firmware;
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
struct ath3k_data *data;
|
||||
int size;
|
||||
|
||||
BT_DBG("intf %p id %p", intf, id);
|
||||
|
||||
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
|
||||
return -ENODEV;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->udev = udev;
|
||||
|
||||
if (request_firmware(&firmware, "ath3k-1.fw", &udev->dev) < 0) {
|
||||
kfree(data);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
size = max_t(uint, firmware->size, 4096);
|
||||
data->fw_data = kmalloc(size, GFP_KERNEL);
|
||||
if (!data->fw_data) {
|
||||
release_firmware(firmware);
|
||||
kfree(data);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(data->fw_data, firmware->data, firmware->size);
|
||||
data->fw_size = firmware->size;
|
||||
data->fw_sent = 0;
|
||||
release_firmware(firmware);
|
||||
|
||||
usb_set_intfdata(intf, data);
|
||||
if (ath3k_load_firmware(data, data->fw_data, data->fw_size)) {
|
||||
usb_set_intfdata(intf, NULL);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath3k_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct ath3k_data *data = usb_get_intfdata(intf);
|
||||
|
||||
BT_DBG("ath3k_disconnect intf %p", intf);
|
||||
|
||||
kfree(data->fw_data);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
static struct usb_driver ath3k_driver = {
|
||||
.name = "ath3k",
|
||||
.probe = ath3k_probe,
|
||||
.disconnect = ath3k_disconnect,
|
||||
.id_table = ath3k_table,
|
||||
};
|
||||
|
||||
static int __init ath3k_init(void)
|
||||
{
|
||||
BT_INFO("Atheros AR30xx firmware driver ver %s", VERSION);
|
||||
return usb_register(&ath3k_driver);
|
||||
}
|
||||
|
||||
static void __exit ath3k_exit(void)
|
||||
{
|
||||
usb_deregister(&ath3k_driver);
|
||||
}
|
||||
|
||||
module_init(ath3k_init);
|
||||
module_exit(ath3k_exit);
|
||||
|
||||
MODULE_AUTHOR("Atheros Communications");
|
||||
MODULE_DESCRIPTION("Atheros AR30xx firmware driver");
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_FIRMWARE("ath3k-1.fw");
|
@ -503,7 +503,9 @@ static irqreturn_t bluecard_interrupt(int irq, void *dev_inst)
|
||||
unsigned int iobase;
|
||||
unsigned char reg;
|
||||
|
||||
BUG_ON(!info->hdev);
|
||||
if (!info || !info->hdev)
|
||||
/* our irq handler is shared */
|
||||
return IRQ_NONE;
|
||||
|
||||
if (!test_bit(CARD_READY, &(info->hw_state)))
|
||||
return IRQ_HANDLED;
|
||||
|
@ -345,7 +345,9 @@ static irqreturn_t bt3c_interrupt(int irq, void *dev_inst)
|
||||
int iir;
|
||||
irqreturn_t r = IRQ_NONE;
|
||||
|
||||
BUG_ON(!info->hdev);
|
||||
if (!info || !info->hdev)
|
||||
/* our irq handler is shared */
|
||||
return IRQ_NONE;
|
||||
|
||||
iobase = info->p_dev->io.BasePort1;
|
||||
|
||||
|
@ -295,7 +295,9 @@ static irqreturn_t btuart_interrupt(int irq, void *dev_inst)
|
||||
int iir, lsr;
|
||||
irqreturn_t r = IRQ_NONE;
|
||||
|
||||
BUG_ON(!info->hdev);
|
||||
if (!info || !info->hdev)
|
||||
/* our irq handler is shared */
|
||||
return IRQ_NONE;
|
||||
|
||||
iobase = info->p_dev->io.BasePort1;
|
||||
|
||||
|
@ -299,7 +299,9 @@ static irqreturn_t dtl1_interrupt(int irq, void *dev_inst)
|
||||
int iir, lsr;
|
||||
irqreturn_t r = IRQ_NONE;
|
||||
|
||||
BUG_ON(!info->hdev);
|
||||
if (!info || !info->hdev)
|
||||
/* our irq handler is shared */
|
||||
return IRQ_NONE;
|
||||
|
||||
iobase = info->p_dev->io.BasePort1;
|
||||
|
||||
|
@ -395,6 +395,7 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
|
||||
unsigned long p = *ppos;
|
||||
ssize_t low_count, read, sz;
|
||||
char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
|
||||
int err = 0;
|
||||
|
||||
read = 0;
|
||||
if (p < (unsigned long) high_memory) {
|
||||
@ -441,12 +442,16 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
|
||||
return -ENOMEM;
|
||||
while (count > 0) {
|
||||
sz = size_inside_page(p, count);
|
||||
if (!is_vmalloc_or_module_addr((void *)p)) {
|
||||
err = -ENXIO;
|
||||
break;
|
||||
}
|
||||
sz = vread(kbuf, (char *)p, sz);
|
||||
if (!sz)
|
||||
break;
|
||||
if (copy_to_user(buf, kbuf, sz)) {
|
||||
free_page((unsigned long)kbuf);
|
||||
return -EFAULT;
|
||||
err = -EFAULT;
|
||||
break;
|
||||
}
|
||||
count -= sz;
|
||||
buf += sz;
|
||||
@ -455,8 +460,8 @@ static ssize_t read_kmem(struct file *file, char __user *buf,
|
||||
}
|
||||
free_page((unsigned long)kbuf);
|
||||
}
|
||||
*ppos = p;
|
||||
return read;
|
||||
*ppos = p;
|
||||
return read ? read : err;
|
||||
}
|
||||
|
||||
|
||||
@ -520,6 +525,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
|
||||
ssize_t wrote = 0;
|
||||
ssize_t virtr = 0;
|
||||
char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
|
||||
int err = 0;
|
||||
|
||||
if (p < (unsigned long) high_memory) {
|
||||
unsigned long to_write = min_t(unsigned long, count,
|
||||
@ -540,14 +546,16 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
|
||||
unsigned long sz = size_inside_page(p, count);
|
||||
unsigned long n;
|
||||
|
||||
if (!is_vmalloc_or_module_addr((void *)p)) {
|
||||
err = -ENXIO;
|
||||
break;
|
||||
}
|
||||
n = copy_from_user(kbuf, buf, sz);
|
||||
if (n) {
|
||||
if (wrote + virtr)
|
||||
break;
|
||||
free_page((unsigned long)kbuf);
|
||||
return -EFAULT;
|
||||
err = -EFAULT;
|
||||
break;
|
||||
}
|
||||
sz = vwrite(kbuf, (char *)p, sz);
|
||||
vwrite(kbuf, (char *)p, sz);
|
||||
count -= sz;
|
||||
buf += sz;
|
||||
virtr += sz;
|
||||
@ -556,8 +564,8 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
|
||||
free_page((unsigned long)kbuf);
|
||||
}
|
||||
|
||||
*ppos = p;
|
||||
return virtr + wrote;
|
||||
*ppos = p;
|
||||
return virtr + wrote ? : err;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -36,17 +36,6 @@ MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
|
||||
MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector.");
|
||||
|
||||
static u32 cn_idx = CN_IDX_CONNECTOR;
|
||||
static u32 cn_val = CN_VAL_CONNECTOR;
|
||||
|
||||
module_param(cn_idx, uint, 0);
|
||||
module_param(cn_val, uint, 0);
|
||||
MODULE_PARM_DESC(cn_idx, "Connector's main device idx.");
|
||||
MODULE_PARM_DESC(cn_val, "Connector's main device val.");
|
||||
|
||||
static DEFINE_MUTEX(notify_lock);
|
||||
static LIST_HEAD(notify_list);
|
||||
|
||||
static struct cn_dev cdev;
|
||||
|
||||
static int cn_already_initialized;
|
||||
@ -209,54 +198,6 @@ static void cn_rx_skb(struct sk_buff *__skb)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Notification routing.
|
||||
*
|
||||
* Gets id and checks if there are notification request for it's idx
|
||||
* and val. If there are such requests notify the listeners with the
|
||||
* given notify event.
|
||||
*
|
||||
*/
|
||||
static void cn_notify(struct cb_id *id, u32 notify_event)
|
||||
{
|
||||
struct cn_ctl_entry *ent;
|
||||
|
||||
mutex_lock(¬ify_lock);
|
||||
list_for_each_entry(ent, ¬ify_list, notify_entry) {
|
||||
int i;
|
||||
struct cn_notify_req *req;
|
||||
struct cn_ctl_msg *ctl = ent->msg;
|
||||
int idx_found, val_found;
|
||||
|
||||
idx_found = val_found = 0;
|
||||
|
||||
req = (struct cn_notify_req *)ctl->data;
|
||||
for (i = 0; i < ctl->idx_notify_num; ++i, ++req) {
|
||||
if (id->idx >= req->first &&
|
||||
id->idx < req->first + req->range) {
|
||||
idx_found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ctl->val_notify_num; ++i, ++req) {
|
||||
if (id->val >= req->first &&
|
||||
id->val < req->first + req->range) {
|
||||
val_found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (idx_found && val_found) {
|
||||
struct cn_msg m = { .ack = notify_event, };
|
||||
|
||||
memcpy(&m.id, id, sizeof(m.id));
|
||||
cn_netlink_send(&m, ctl->group, GFP_KERNEL);
|
||||
}
|
||||
}
|
||||
mutex_unlock(¬ify_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback add routing - adds callback with given ID and name.
|
||||
* If there is registered callback with the same ID it will not be added.
|
||||
@ -276,8 +217,6 @@ int cn_add_callback(struct cb_id *id, char *name,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
cn_notify(id, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cn_add_callback);
|
||||
@ -295,111 +234,9 @@ void cn_del_callback(struct cb_id *id)
|
||||
struct cn_dev *dev = &cdev;
|
||||
|
||||
cn_queue_del_callback(dev->cbdev, id);
|
||||
cn_notify(id, 1);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cn_del_callback);
|
||||
|
||||
/*
|
||||
* Checks two connector's control messages to be the same.
|
||||
* Returns 1 if they are the same or if the first one is corrupted.
|
||||
*/
|
||||
static int cn_ctl_msg_equals(struct cn_ctl_msg *m1, struct cn_ctl_msg *m2)
|
||||
{
|
||||
int i;
|
||||
struct cn_notify_req *req1, *req2;
|
||||
|
||||
if (m1->idx_notify_num != m2->idx_notify_num)
|
||||
return 0;
|
||||
|
||||
if (m1->val_notify_num != m2->val_notify_num)
|
||||
return 0;
|
||||
|
||||
if (m1->len != m2->len)
|
||||
return 0;
|
||||
|
||||
if ((m1->idx_notify_num + m1->val_notify_num) * sizeof(*req1) !=
|
||||
m1->len)
|
||||
return 1;
|
||||
|
||||
req1 = (struct cn_notify_req *)m1->data;
|
||||
req2 = (struct cn_notify_req *)m2->data;
|
||||
|
||||
for (i = 0; i < m1->idx_notify_num; ++i) {
|
||||
if (req1->first != req2->first || req1->range != req2->range)
|
||||
return 0;
|
||||
req1++;
|
||||
req2++;
|
||||
}
|
||||
|
||||
for (i = 0; i < m1->val_notify_num; ++i) {
|
||||
if (req1->first != req2->first || req1->range != req2->range)
|
||||
return 0;
|
||||
req1++;
|
||||
req2++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Main connector device's callback.
|
||||
*
|
||||
* Used for notification of a request's processing.
|
||||
*/
|
||||
static void cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
|
||||
{
|
||||
struct cn_ctl_msg *ctl;
|
||||
struct cn_ctl_entry *ent;
|
||||
u32 size;
|
||||
|
||||
if (msg->len < sizeof(*ctl))
|
||||
return;
|
||||
|
||||
ctl = (struct cn_ctl_msg *)msg->data;
|
||||
|
||||
size = (sizeof(*ctl) + ((ctl->idx_notify_num +
|
||||
ctl->val_notify_num) *
|
||||
sizeof(struct cn_notify_req)));
|
||||
|
||||
if (msg->len != size)
|
||||
return;
|
||||
|
||||
if (ctl->len + sizeof(*ctl) != msg->len)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Remove notification.
|
||||
*/
|
||||
if (ctl->group == 0) {
|
||||
struct cn_ctl_entry *n;
|
||||
|
||||
mutex_lock(¬ify_lock);
|
||||
list_for_each_entry_safe(ent, n, ¬ify_list, notify_entry) {
|
||||
if (cn_ctl_msg_equals(ent->msg, ctl)) {
|
||||
list_del(&ent->notify_entry);
|
||||
kfree(ent);
|
||||
}
|
||||
}
|
||||
mutex_unlock(¬ify_lock);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
size += sizeof(*ent);
|
||||
|
||||
ent = kzalloc(size, GFP_KERNEL);
|
||||
if (!ent)
|
||||
return;
|
||||
|
||||
ent->msg = (struct cn_ctl_msg *)(ent + 1);
|
||||
|
||||
memcpy(ent->msg, ctl, size - sizeof(*ent));
|
||||
|
||||
mutex_lock(¬ify_lock);
|
||||
list_add(&ent->notify_entry, ¬ify_list);
|
||||
mutex_unlock(¬ify_lock);
|
||||
}
|
||||
|
||||
static int cn_proc_show(struct seq_file *m, void *v)
|
||||
{
|
||||
struct cn_queue_dev *dev = cdev.cbdev;
|
||||
@ -437,11 +274,8 @@ static const struct file_operations cn_file_ops = {
|
||||
static int __devinit cn_init(void)
|
||||
{
|
||||
struct cn_dev *dev = &cdev;
|
||||
int err;
|
||||
|
||||
dev->input = cn_rx_skb;
|
||||
dev->id.idx = cn_idx;
|
||||
dev->id.val = cn_val;
|
||||
|
||||
dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR,
|
||||
CN_NETLINK_USERS + 0xf,
|
||||
@ -457,14 +291,6 @@ static int __devinit cn_init(void)
|
||||
|
||||
cn_already_initialized = 1;
|
||||
|
||||
err = cn_add_callback(&dev->id, "connector", &cn_callback);
|
||||
if (err) {
|
||||
cn_already_initialized = 0;
|
||||
cn_queue_free_dev(dev->cbdev);
|
||||
netlink_kernel_release(dev->nls);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
proc_net_fops_create(&init_net, "connector", S_IRUGO, &cn_file_ops);
|
||||
|
||||
return 0;
|
||||
@ -478,7 +304,6 @@ static void __devexit cn_fini(void)
|
||||
|
||||
proc_net_remove(&init_net, "connector");
|
||||
|
||||
cn_del_callback(&dev->id);
|
||||
cn_queue_free_dev(dev->cbdev);
|
||||
netlink_kernel_release(dev->nls);
|
||||
}
|
||||
|
@ -197,6 +197,15 @@ config LOGIG940_FF
|
||||
Say Y here if you want to enable force feedback support for Logitech
|
||||
Flight System G940 devices.
|
||||
|
||||
config HID_MAGICMOUSE
|
||||
tristate "Apple MagicMouse multi-touch support"
|
||||
depends on BT_HIDP
|
||||
---help---
|
||||
Support for the Apple Magic Mouse multi-touch.
|
||||
|
||||
Say Y here if you want support for the multi-touch features of the
|
||||
Apple Wireless "Magic" Mouse.
|
||||
|
||||
config HID_MICROSOFT
|
||||
tristate "Microsoft" if EMBEDDED
|
||||
depends on USB_HID
|
||||
|
@ -35,6 +35,7 @@ obj-$(CONFIG_HID_GYRATION) += hid-gyration.o
|
||||
obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o
|
||||
obj-$(CONFIG_HID_KYE) += hid-kye.o
|
||||
obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
|
||||
obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o
|
||||
obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o
|
||||
obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o
|
||||
obj-$(CONFIG_HID_MOSART) += hid-mosart.o
|
||||
|
@ -51,7 +51,7 @@ EXPORT_SYMBOL_GPL(hid_debug);
|
||||
* Register a new report for a device.
|
||||
*/
|
||||
|
||||
static struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id)
|
||||
struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id)
|
||||
{
|
||||
struct hid_report_enum *report_enum = device->report_enum + type;
|
||||
struct hid_report *report;
|
||||
@ -75,6 +75,7 @@ static struct hid_report *hid_register_report(struct hid_device *device, unsigne
|
||||
|
||||
return report;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(hid_register_report);
|
||||
|
||||
/*
|
||||
* Register a new field for this report.
|
||||
@ -1255,6 +1256,7 @@ static const struct hid_device_id hid_blacklist[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) },
|
||||
@ -1346,6 +1348,7 @@ static const struct hid_device_id hid_blacklist[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
|
||||
|
@ -59,6 +59,7 @@
|
||||
|
||||
#define USB_VENDOR_ID_APPLE 0x05ac
|
||||
#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304
|
||||
#define USB_DEVICE_ID_APPLE_MAGICMOUSE 0x030d
|
||||
#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e
|
||||
#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f
|
||||
#define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214
|
||||
|
449
drivers/hid/hid-magicmouse.c
Normal file
449
drivers/hid/hid-magicmouse.c
Normal file
@ -0,0 +1,449 @@
|
||||
/*
|
||||
* Apple "Magic" Wireless Mouse driver
|
||||
*
|
||||
* Copyright (c) 2010 Michael Poole <mdpoole@troilus.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
static bool emulate_3button = true;
|
||||
module_param(emulate_3button, bool, 0644);
|
||||
MODULE_PARM_DESC(emulate_3button, "Emulate a middle button");
|
||||
|
||||
static int middle_button_start = -350;
|
||||
static int middle_button_stop = +350;
|
||||
|
||||
static bool emulate_scroll_wheel = true;
|
||||
module_param(emulate_scroll_wheel, bool, 0644);
|
||||
MODULE_PARM_DESC(emulate_scroll_wheel, "Emulate a scroll wheel");
|
||||
|
||||
static bool report_touches = true;
|
||||
module_param(report_touches, bool, 0644);
|
||||
MODULE_PARM_DESC(report_touches, "Emit touch records (otherwise, only use them for emulation)");
|
||||
|
||||
static bool report_undeciphered;
|
||||
module_param(report_undeciphered, bool, 0644);
|
||||
MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state field using a MSC_RAW event");
|
||||
|
||||
#define TOUCH_REPORT_ID 0x29
|
||||
/* These definitions are not precise, but they're close enough. (Bits
|
||||
* 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem
|
||||
* to be some kind of bit mask -- 0x20 may be a near-field reading,
|
||||
* and 0x40 is actual contact, and 0x10 may be a start/stop or change
|
||||
* indication.)
|
||||
*/
|
||||
#define TOUCH_STATE_MASK 0xf0
|
||||
#define TOUCH_STATE_NONE 0x00
|
||||
#define TOUCH_STATE_START 0x30
|
||||
#define TOUCH_STATE_DRAG 0x40
|
||||
|
||||
/**
|
||||
* struct magicmouse_sc - Tracks Magic Mouse-specific data.
|
||||
* @input: Input device through which we report events.
|
||||
* @quirks: Currently unused.
|
||||
* @last_timestamp: Timestamp from most recent (18-bit) touch report
|
||||
* (units of milliseconds over short windows, but seems to
|
||||
* increase faster when there are no touches).
|
||||
* @delta_time: 18-bit difference between the two most recent touch
|
||||
* reports from the mouse.
|
||||
* @ntouches: Number of touches in most recent touch report.
|
||||
* @scroll_accel: Number of consecutive scroll motions.
|
||||
* @scroll_jiffies: Time of last scroll motion.
|
||||
* @touches: Most recent data for a touch, indexed by tracking ID.
|
||||
* @tracking_ids: Mapping of current touch input data to @touches.
|
||||
*/
|
||||
struct magicmouse_sc {
|
||||
struct input_dev *input;
|
||||
unsigned long quirks;
|
||||
|
||||
int last_timestamp;
|
||||
int delta_time;
|
||||
int ntouches;
|
||||
int scroll_accel;
|
||||
unsigned long scroll_jiffies;
|
||||
|
||||
struct {
|
||||
short x;
|
||||
short y;
|
||||
short scroll_y;
|
||||
u8 size;
|
||||
} touches[16];
|
||||
int tracking_ids[16];
|
||||
};
|
||||
|
||||
static int magicmouse_firm_touch(struct magicmouse_sc *msc)
|
||||
{
|
||||
int touch = -1;
|
||||
int ii;
|
||||
|
||||
/* If there is only one "firm" touch, set touch to its
|
||||
* tracking ID.
|
||||
*/
|
||||
for (ii = 0; ii < msc->ntouches; ii++) {
|
||||
int idx = msc->tracking_ids[ii];
|
||||
if (msc->touches[idx].size < 8) {
|
||||
/* Ignore this touch. */
|
||||
} else if (touch >= 0) {
|
||||
touch = -1;
|
||||
break;
|
||||
} else {
|
||||
touch = idx;
|
||||
}
|
||||
}
|
||||
|
||||
return touch;
|
||||
}
|
||||
|
||||
static void magicmouse_emit_buttons(struct magicmouse_sc *msc, int state)
|
||||
{
|
||||
int last_state = test_bit(BTN_LEFT, msc->input->key) << 0 |
|
||||
test_bit(BTN_RIGHT, msc->input->key) << 1 |
|
||||
test_bit(BTN_MIDDLE, msc->input->key) << 2;
|
||||
|
||||
if (emulate_3button) {
|
||||
int id;
|
||||
|
||||
/* If some button was pressed before, keep it held
|
||||
* down. Otherwise, if there's exactly one firm
|
||||
* touch, use that to override the mouse's guess.
|
||||
*/
|
||||
if (state == 0) {
|
||||
/* The button was released. */
|
||||
} else if (last_state != 0) {
|
||||
state = last_state;
|
||||
} else if ((id = magicmouse_firm_touch(msc)) >= 0) {
|
||||
int x = msc->touches[id].x;
|
||||
if (x < middle_button_start)
|
||||
state = 1;
|
||||
else if (x > middle_button_stop)
|
||||
state = 2;
|
||||
else
|
||||
state = 4;
|
||||
} /* else: we keep the mouse's guess */
|
||||
|
||||
input_report_key(msc->input, BTN_MIDDLE, state & 4);
|
||||
}
|
||||
|
||||
input_report_key(msc->input, BTN_LEFT, state & 1);
|
||||
input_report_key(msc->input, BTN_RIGHT, state & 2);
|
||||
|
||||
if (state != last_state)
|
||||
msc->scroll_accel = 0;
|
||||
}
|
||||
|
||||
static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata)
|
||||
{
|
||||
struct input_dev *input = msc->input;
|
||||
__s32 x_y = tdata[0] << 8 | tdata[1] << 16 | tdata[2] << 24;
|
||||
int misc = tdata[5] | tdata[6] << 8;
|
||||
int id = (misc >> 6) & 15;
|
||||
int x = x_y << 12 >> 20;
|
||||
int y = -(x_y >> 20);
|
||||
|
||||
/* Store tracking ID and other fields. */
|
||||
msc->tracking_ids[raw_id] = id;
|
||||
msc->touches[id].x = x;
|
||||
msc->touches[id].y = y;
|
||||
msc->touches[id].size = misc & 63;
|
||||
|
||||
/* If requested, emulate a scroll wheel by detecting small
|
||||
* vertical touch motions along the middle of the mouse.
|
||||
*/
|
||||
if (emulate_scroll_wheel &&
|
||||
middle_button_start < x && x < middle_button_stop) {
|
||||
static const int accel_profile[] = {
|
||||
256, 228, 192, 160, 128, 96, 64, 32,
|
||||
};
|
||||
unsigned long now = jiffies;
|
||||
int step = msc->touches[id].scroll_y - y;
|
||||
|
||||
/* Reset acceleration after half a second. */
|
||||
if (time_after(now, msc->scroll_jiffies + HZ / 2))
|
||||
msc->scroll_accel = 0;
|
||||
|
||||
/* Calculate and apply the scroll motion. */
|
||||
switch (tdata[7] & TOUCH_STATE_MASK) {
|
||||
case TOUCH_STATE_START:
|
||||
msc->touches[id].scroll_y = y;
|
||||
msc->scroll_accel = min_t(int, msc->scroll_accel + 1,
|
||||
ARRAY_SIZE(accel_profile) - 1);
|
||||
break;
|
||||
case TOUCH_STATE_DRAG:
|
||||
step = step / accel_profile[msc->scroll_accel];
|
||||
if (step != 0) {
|
||||
msc->touches[id].scroll_y = y;
|
||||
msc->scroll_jiffies = now;
|
||||
input_report_rel(input, REL_WHEEL, step);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate the input events for this touch. */
|
||||
if (report_touches) {
|
||||
int orientation = (misc >> 10) - 32;
|
||||
|
||||
input_report_abs(input, ABS_MT_TRACKING_ID, id);
|
||||
input_report_abs(input, ABS_MT_TOUCH_MAJOR, tdata[3]);
|
||||
input_report_abs(input, ABS_MT_TOUCH_MINOR, tdata[4]);
|
||||
input_report_abs(input, ABS_MT_ORIENTATION, orientation);
|
||||
input_report_abs(input, ABS_MT_POSITION_X, x);
|
||||
input_report_abs(input, ABS_MT_POSITION_Y, y);
|
||||
|
||||
if (report_undeciphered)
|
||||
input_event(input, EV_MSC, MSC_RAW, tdata[7]);
|
||||
|
||||
input_mt_sync(input);
|
||||
}
|
||||
}
|
||||
|
||||
static int magicmouse_raw_event(struct hid_device *hdev,
|
||||
struct hid_report *report, u8 *data, int size)
|
||||
{
|
||||
struct magicmouse_sc *msc = hid_get_drvdata(hdev);
|
||||
struct input_dev *input = msc->input;
|
||||
int x, y, ts, ii, clicks;
|
||||
|
||||
switch (data[0]) {
|
||||
case 0x10:
|
||||
if (size != 6)
|
||||
return 0;
|
||||
x = (__s16)(data[2] | data[3] << 8);
|
||||
y = (__s16)(data[4] | data[5] << 8);
|
||||
clicks = data[1];
|
||||
break;
|
||||
case TOUCH_REPORT_ID:
|
||||
/* Expect six bytes of prefix, and N*8 bytes of touch data. */
|
||||
if (size < 6 || ((size - 6) % 8) != 0)
|
||||
return 0;
|
||||
ts = data[3] >> 6 | data[4] << 2 | data[5] << 10;
|
||||
msc->delta_time = (ts - msc->last_timestamp) & 0x3ffff;
|
||||
msc->last_timestamp = ts;
|
||||
msc->ntouches = (size - 6) / 8;
|
||||
for (ii = 0; ii < msc->ntouches; ii++)
|
||||
magicmouse_emit_touch(msc, ii, data + ii * 8 + 6);
|
||||
/* When emulating three-button mode, it is important
|
||||
* to have the current touch information before
|
||||
* generating a click event.
|
||||
*/
|
||||
x = (signed char)data[1];
|
||||
y = (signed char)data[2];
|
||||
clicks = data[3];
|
||||
break;
|
||||
case 0x20: /* Theoretically battery status (0-100), but I have
|
||||
* never seen it -- maybe it is only upon request.
|
||||
*/
|
||||
case 0x60: /* Unknown, maybe laser on/off. */
|
||||
case 0x61: /* Laser reflection status change.
|
||||
* data[1]: 0 = spotted, 1 = lost
|
||||
*/
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
magicmouse_emit_buttons(msc, clicks & 3);
|
||||
input_report_rel(input, REL_X, x);
|
||||
input_report_rel(input, REL_Y, y);
|
||||
input_sync(input);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int magicmouse_input_open(struct input_dev *dev)
|
||||
{
|
||||
struct hid_device *hid = input_get_drvdata(dev);
|
||||
|
||||
return hid->ll_driver->open(hid);
|
||||
}
|
||||
|
||||
static void magicmouse_input_close(struct input_dev *dev)
|
||||
{
|
||||
struct hid_device *hid = input_get_drvdata(dev);
|
||||
|
||||
hid->ll_driver->close(hid);
|
||||
}
|
||||
|
||||
static void magicmouse_setup_input(struct input_dev *input, struct hid_device *hdev)
|
||||
{
|
||||
input_set_drvdata(input, hdev);
|
||||
input->event = hdev->ll_driver->hidinput_input_event;
|
||||
input->open = magicmouse_input_open;
|
||||
input->close = magicmouse_input_close;
|
||||
|
||||
input->name = hdev->name;
|
||||
input->phys = hdev->phys;
|
||||
input->uniq = hdev->uniq;
|
||||
input->id.bustype = hdev->bus;
|
||||
input->id.vendor = hdev->vendor;
|
||||
input->id.product = hdev->product;
|
||||
input->id.version = hdev->version;
|
||||
input->dev.parent = hdev->dev.parent;
|
||||
|
||||
__set_bit(EV_KEY, input->evbit);
|
||||
__set_bit(BTN_LEFT, input->keybit);
|
||||
__set_bit(BTN_RIGHT, input->keybit);
|
||||
if (emulate_3button)
|
||||
__set_bit(BTN_MIDDLE, input->keybit);
|
||||
__set_bit(BTN_TOOL_FINGER, input->keybit);
|
||||
|
||||
__set_bit(EV_REL, input->evbit);
|
||||
__set_bit(REL_X, input->relbit);
|
||||
__set_bit(REL_Y, input->relbit);
|
||||
if (emulate_scroll_wheel)
|
||||
__set_bit(REL_WHEEL, input->relbit);
|
||||
|
||||
if (report_touches) {
|
||||
__set_bit(EV_ABS, input->evbit);
|
||||
|
||||
input_set_abs_params(input, ABS_MT_TRACKING_ID, 0, 15, 0, 0);
|
||||
input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 4, 0);
|
||||
input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 255, 4, 0);
|
||||
input_set_abs_params(input, ABS_MT_ORIENTATION, -32, 31, 1, 0);
|
||||
input_set_abs_params(input, ABS_MT_POSITION_X, -1100, 1358,
|
||||
4, 0);
|
||||
/* Note: Touch Y position from the device is inverted relative
|
||||
* to how pointer motion is reported (and relative to how USB
|
||||
* HID recommends the coordinates work). This driver keeps
|
||||
* the origin at the same position, and just uses the additive
|
||||
* inverse of the reported Y.
|
||||
*/
|
||||
input_set_abs_params(input, ABS_MT_POSITION_Y, -1589, 2047,
|
||||
4, 0);
|
||||
}
|
||||
|
||||
if (report_undeciphered) {
|
||||
__set_bit(EV_MSC, input->evbit);
|
||||
__set_bit(MSC_RAW, input->mscbit);
|
||||
}
|
||||
}
|
||||
|
||||
static int magicmouse_probe(struct hid_device *hdev,
|
||||
const struct hid_device_id *id)
|
||||
{
|
||||
__u8 feature_1[] = { 0xd7, 0x01 };
|
||||
__u8 feature_2[] = { 0xf8, 0x01, 0x32 };
|
||||
struct input_dev *input;
|
||||
struct magicmouse_sc *msc;
|
||||
struct hid_report *report;
|
||||
int ret;
|
||||
|
||||
msc = kzalloc(sizeof(*msc), GFP_KERNEL);
|
||||
if (msc == NULL) {
|
||||
dev_err(&hdev->dev, "can't alloc magicmouse descriptor\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
msc->quirks = id->driver_data;
|
||||
hid_set_drvdata(hdev, msc);
|
||||
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "magicmouse hid parse failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "magicmouse hw start failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
report = hid_register_report(hdev, HID_INPUT_REPORT, TOUCH_REPORT_ID);
|
||||
if (!report) {
|
||||
dev_err(&hdev->dev, "unable to register touch report\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_stop_hw;
|
||||
}
|
||||
report->size = 6;
|
||||
|
||||
ret = hdev->hid_output_raw_report(hdev, feature_1, sizeof(feature_1),
|
||||
HID_FEATURE_REPORT);
|
||||
if (ret != sizeof(feature_1)) {
|
||||
dev_err(&hdev->dev, "unable to request touch data (1:%d)\n",
|
||||
ret);
|
||||
goto err_stop_hw;
|
||||
}
|
||||
ret = hdev->hid_output_raw_report(hdev, feature_2,
|
||||
sizeof(feature_2), HID_FEATURE_REPORT);
|
||||
if (ret != sizeof(feature_2)) {
|
||||
dev_err(&hdev->dev, "unable to request touch data (2:%d)\n",
|
||||
ret);
|
||||
goto err_stop_hw;
|
||||
}
|
||||
|
||||
input = input_allocate_device();
|
||||
if (!input) {
|
||||
dev_err(&hdev->dev, "can't alloc input device\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_stop_hw;
|
||||
}
|
||||
magicmouse_setup_input(input, hdev);
|
||||
|
||||
ret = input_register_device(input);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "input device registration failed\n");
|
||||
goto err_input;
|
||||
}
|
||||
msc->input = input;
|
||||
|
||||
return 0;
|
||||
err_input:
|
||||
input_free_device(input);
|
||||
err_stop_hw:
|
||||
hid_hw_stop(hdev);
|
||||
err_free:
|
||||
kfree(msc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void magicmouse_remove(struct hid_device *hdev)
|
||||
{
|
||||
hid_hw_stop(hdev);
|
||||
kfree(hid_get_drvdata(hdev));
|
||||
}
|
||||
|
||||
static const struct hid_device_id magic_mice[] = {
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE),
|
||||
.driver_data = 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, magic_mice);
|
||||
|
||||
static struct hid_driver magicmouse_driver = {
|
||||
.name = "magicmouse",
|
||||
.id_table = magic_mice,
|
||||
.probe = magicmouse_probe,
|
||||
.remove = magicmouse_remove,
|
||||
.raw_event = magicmouse_raw_event,
|
||||
};
|
||||
|
||||
static int __init magicmouse_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = hid_register_driver(&magicmouse_driver);
|
||||
if (ret)
|
||||
printk(KERN_ERR "can't register magicmouse driver\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit magicmouse_exit(void)
|
||||
{
|
||||
hid_unregister_driver(&magicmouse_driver);
|
||||
}
|
||||
|
||||
module_init(magicmouse_init);
|
||||
module_exit(magicmouse_exit);
|
||||
MODULE_LICENSE("GPL");
|
@ -48,7 +48,7 @@ static void sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||
* to "operational". Without this, the ps3 controller will not report any
|
||||
* events.
|
||||
*/
|
||||
static int sony_set_operational(struct hid_device *hdev)
|
||||
static int sony_set_operational_usb(struct hid_device *hdev)
|
||||
{
|
||||
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
|
||||
struct usb_device *dev = interface_to_usbdev(intf);
|
||||
@ -73,6 +73,12 @@ static int sony_set_operational(struct hid_device *hdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sony_set_operational_bt(struct hid_device *hdev)
|
||||
{
|
||||
unsigned char buf[] = { 0x53, 0xf4, 0x42, 0x03, 0x00, 0x00 };
|
||||
return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
|
||||
}
|
||||
|
||||
static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
{
|
||||
int ret;
|
||||
@ -101,7 +107,17 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = sony_set_operational(hdev);
|
||||
switch (hdev->bus) {
|
||||
case BUS_USB:
|
||||
ret = sony_set_operational_usb(hdev);
|
||||
break;
|
||||
case BUS_BLUETOOTH:
|
||||
ret = sony_set_operational_bt(hdev);
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
goto err_stop;
|
||||
|
||||
@ -121,6 +137,7 @@ static void sony_remove(struct hid_device *hdev)
|
||||
|
||||
static const struct hid_device_id sony_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
|
||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE),
|
||||
.driver_data = VAIO_RDESC_CONSTANT },
|
||||
{ }
|
||||
|
@ -156,7 +156,9 @@ static int wacom_probe(struct hid_device *hdev,
|
||||
struct hid_input *hidinput;
|
||||
struct input_dev *input;
|
||||
struct wacom_data *wdata;
|
||||
char rep_data[2];
|
||||
int ret;
|
||||
int limit;
|
||||
|
||||
wdata = kzalloc(sizeof(*wdata), GFP_KERNEL);
|
||||
if (wdata == NULL) {
|
||||
@ -166,6 +168,7 @@ static int wacom_probe(struct hid_device *hdev,
|
||||
|
||||
hid_set_drvdata(hdev, wdata);
|
||||
|
||||
/* Parse the HID report now */
|
||||
ret = hid_parse(hdev);
|
||||
if (ret) {
|
||||
dev_err(&hdev->dev, "parse failed\n");
|
||||
@ -178,6 +181,31 @@ static int wacom_probe(struct hid_device *hdev,
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that if the raw queries fail, it's not a hard failure and it
|
||||
* is safe to continue
|
||||
*/
|
||||
|
||||
/* Set Wacom mode2 */
|
||||
rep_data[0] = 0x03; rep_data[1] = 0x00;
|
||||
limit = 3;
|
||||
do {
|
||||
ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
|
||||
HID_FEATURE_REPORT);
|
||||
} while (ret < 0 && limit-- > 0);
|
||||
if (ret < 0)
|
||||
dev_warn(&hdev->dev, "failed to poke device #1, %d\n", ret);
|
||||
|
||||
/* 0x06 - high reporting speed, 0x05 - low speed */
|
||||
rep_data[0] = 0x06; rep_data[1] = 0x00;
|
||||
limit = 3;
|
||||
do {
|
||||
ret = hdev->hid_output_raw_report(hdev, rep_data, 2,
|
||||
HID_FEATURE_REPORT);
|
||||
} while (ret < 0 && limit-- > 0);
|
||||
if (ret < 0)
|
||||
dev_warn(&hdev->dev, "failed to poke device #2, %d\n", ret);
|
||||
|
||||
hidinput = list_entry(hdev->inputs.next, struct hid_input, list);
|
||||
input = hidinput->input;
|
||||
|
||||
|
@ -134,7 +134,7 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = dev->hid_output_raw_report(dev, buf, count);
|
||||
ret = dev->hid_output_raw_report(dev, buf, count, HID_OUTPUT_REPORT);
|
||||
out:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
|
@ -798,7 +798,8 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count)
|
||||
static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count,
|
||||
unsigned char report_type)
|
||||
{
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
struct usb_device *dev = hid_to_usb_dev(hid);
|
||||
@ -809,7 +810,7 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co
|
||||
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
|
||||
HID_REQ_SET_REPORT,
|
||||
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
((HID_OUTPUT_REPORT + 1) << 8) | *buf,
|
||||
((report_type + 1) << 8) | *buf,
|
||||
interface->desc.bInterfaceNumber, buf + 1, count - 1,
|
||||
USB_CTRL_SET_TIMEOUT);
|
||||
|
||||
|
@ -276,8 +276,13 @@ struct be_adapter {
|
||||
int link_speed;
|
||||
u8 port_type;
|
||||
u8 transceiver;
|
||||
u8 generation; /* BladeEngine ASIC generation */
|
||||
};
|
||||
|
||||
/* BladeEngine Generation numbers */
|
||||
#define BE_GEN2 2
|
||||
#define BE_GEN3 3
|
||||
|
||||
extern const struct ethtool_ops be_ethtool_ops;
|
||||
|
||||
#define drvr_stats(adapter) (&adapter->stats.drvr_stats)
|
||||
|
@ -164,7 +164,8 @@ struct be_cmd_req_hdr {
|
||||
u8 domain; /* dword 0 */
|
||||
u32 timeout; /* dword 1 */
|
||||
u32 request_length; /* dword 2 */
|
||||
u32 rsvd; /* dword 3 */
|
||||
u8 version; /* dword 3 */
|
||||
u8 rsvd[3]; /* dword 3 */
|
||||
};
|
||||
|
||||
#define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */
|
||||
|
@ -1350,7 +1350,7 @@ static irqreturn_t be_intx(int irq, void *dev)
|
||||
int isr;
|
||||
|
||||
isr = ioread32(adapter->csr + CEV_ISR0_OFFSET +
|
||||
be_pci_func(adapter) * CEV_ISR_SIZE);
|
||||
(adapter->tx_eq.q.id/ 8) * CEV_ISR_SIZE);
|
||||
if (!isr)
|
||||
return IRQ_NONE;
|
||||
|
||||
@ -2051,6 +2051,7 @@ static void be_unmap_pci_bars(struct be_adapter *adapter)
|
||||
static int be_map_pci_bars(struct be_adapter *adapter)
|
||||
{
|
||||
u8 __iomem *addr;
|
||||
int pcicfg_reg;
|
||||
|
||||
addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2),
|
||||
pci_resource_len(adapter->pdev, 2));
|
||||
@ -2064,8 +2065,13 @@ static int be_map_pci_bars(struct be_adapter *adapter)
|
||||
goto pci_map_err;
|
||||
adapter->db = addr;
|
||||
|
||||
addr = ioremap_nocache(pci_resource_start(adapter->pdev, 1),
|
||||
pci_resource_len(adapter->pdev, 1));
|
||||
if (adapter->generation == BE_GEN2)
|
||||
pcicfg_reg = 1;
|
||||
else
|
||||
pcicfg_reg = 0;
|
||||
|
||||
addr = ioremap_nocache(pci_resource_start(adapter->pdev, pcicfg_reg),
|
||||
pci_resource_len(adapter->pdev, pcicfg_reg));
|
||||
if (addr == NULL)
|
||||
goto pci_map_err;
|
||||
adapter->pcicfg = addr;
|
||||
@ -2162,6 +2168,7 @@ static int be_stats_init(struct be_adapter *adapter)
|
||||
cmd->va = pci_alloc_consistent(adapter->pdev, cmd->size, &cmd->dma);
|
||||
if (cmd->va == NULL)
|
||||
return -1;
|
||||
memset(cmd->va, 0, cmd->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2240,6 +2247,20 @@ static int __devinit be_probe(struct pci_dev *pdev,
|
||||
goto rel_reg;
|
||||
}
|
||||
adapter = netdev_priv(netdev);
|
||||
|
||||
switch (pdev->device) {
|
||||
case BE_DEVICE_ID1:
|
||||
case OC_DEVICE_ID1:
|
||||
adapter->generation = BE_GEN2;
|
||||
break;
|
||||
case BE_DEVICE_ID2:
|
||||
case OC_DEVICE_ID2:
|
||||
adapter->generation = BE_GEN3;
|
||||
break;
|
||||
default:
|
||||
adapter->generation = 0;
|
||||
}
|
||||
|
||||
adapter->pdev = pdev;
|
||||
pci_set_drvdata(pdev, adapter);
|
||||
adapter->netdev = netdev;
|
||||
|
@ -3639,7 +3639,7 @@ static int bond_open(struct net_device *bond_dev)
|
||||
*/
|
||||
if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB))) {
|
||||
/* something went wrong - fail the open operation */
|
||||
return -1;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor);
|
||||
|
@ -2117,6 +2117,7 @@ static inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter,
|
||||
/* set time_stamp *before* dma to help avoid a possible race */
|
||||
buffer_info->time_stamp = jiffies;
|
||||
buffer_info->next_to_watch = i;
|
||||
buffer_info->mapped_as_page = false;
|
||||
buffer_info->dma = pci_map_single(pdev, skb->data, len,
|
||||
PCI_DMA_TODEVICE);
|
||||
if (pci_dma_mapping_error(pdev, buffer_info->dma))
|
||||
|
@ -223,7 +223,7 @@ static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
|
||||
|
||||
if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] !=
|
||||
adapter->dcb_cfg.bw_percentage[0][bwg_id]) {
|
||||
adapter->dcb_set_bitmap |= BIT_PG_RX;
|
||||
adapter->dcb_set_bitmap |= BIT_PG_TX;
|
||||
adapter->dcb_set_bitmap |= BIT_RESETLINK;
|
||||
}
|
||||
}
|
||||
@ -341,6 +341,12 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
|
||||
if (!adapter->dcb_set_bitmap)
|
||||
return DCB_NO_HW_CHG;
|
||||
|
||||
ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
|
||||
adapter->ring_feature[RING_F_DCB].indices);
|
||||
|
||||
if (ret)
|
||||
return DCB_NO_HW_CHG;
|
||||
|
||||
/*
|
||||
* Only take down the adapter if the configuration change
|
||||
* requires a reset.
|
||||
@ -359,14 +365,6 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
|
||||
}
|
||||
}
|
||||
|
||||
ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
|
||||
adapter->ring_feature[RING_F_DCB].indices);
|
||||
if (ret) {
|
||||
if (adapter->dcb_set_bitmap & BIT_RESETLINK)
|
||||
clear_bit(__IXGBE_RESETTING, &adapter->state);
|
||||
return DCB_NO_HW_CHG;
|
||||
}
|
||||
|
||||
if (adapter->dcb_cfg.pfc_mode_enable) {
|
||||
if ((adapter->hw.mac.type != ixgbe_mac_82598EB) &&
|
||||
(adapter->hw.fc.current_mode != ixgbe_fc_pfc))
|
||||
|
@ -854,8 +854,8 @@ static void ks_update_link_status(struct net_device *netdev, struct ks_net *ks)
|
||||
|
||||
static irqreturn_t ks_irq(int irq, void *pw)
|
||||
{
|
||||
struct ks_net *ks = pw;
|
||||
struct net_device *netdev = ks->netdev;
|
||||
struct net_device *netdev = pw;
|
||||
struct ks_net *ks = netdev_priv(netdev);
|
||||
u16 status;
|
||||
|
||||
/*this should be the first in IRQ handler */
|
||||
|
@ -1063,7 +1063,7 @@ static int netdev_open(struct net_device *dev)
|
||||
if (retval) {
|
||||
printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n",
|
||||
FIRMWARE_RX);
|
||||
return retval;
|
||||
goto out_init;
|
||||
}
|
||||
if (fw_rx->size % 4) {
|
||||
printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n",
|
||||
@ -1108,6 +1108,9 @@ out_tx:
|
||||
release_firmware(fw_tx);
|
||||
out_rx:
|
||||
release_firmware(fw_rx);
|
||||
out_init:
|
||||
if (retval)
|
||||
netdev_close(dev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -419,7 +419,7 @@ static int cdc_manage_power(struct usbnet *dev, int on)
|
||||
|
||||
static const struct driver_info cdc_info = {
|
||||
.description = "CDC Ethernet Device",
|
||||
.flags = FLAG_ETHER | FLAG_LINK_INTR,
|
||||
.flags = FLAG_ETHER,
|
||||
// .check_connect = cdc_check_connect,
|
||||
.bind = cdc_bind,
|
||||
.unbind = usbnet_cdc_unbind,
|
||||
|
@ -855,12 +855,11 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah)
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_hw_init_11a_eeprom_fix(struct ath_hw *ah)
|
||||
static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah)
|
||||
{
|
||||
u32 i, j;
|
||||
|
||||
if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
|
||||
test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) {
|
||||
if (ah->hw_version.devid == AR9280_DEVID_PCI) {
|
||||
|
||||
/* EEPROM Fixup */
|
||||
for (i = 0; i < ah->iniModes.ia_rows; i++) {
|
||||
@ -980,7 +979,7 @@ int ath9k_hw_init(struct ath_hw *ah)
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ath9k_hw_init_11a_eeprom_fix(ah);
|
||||
ath9k_hw_init_eeprom_fix(ah);
|
||||
|
||||
r = ath9k_hw_init_macaddr(ah);
|
||||
if (r) {
|
||||
|
@ -2655,10 +2655,10 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
|
||||
(sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
|
||||
ath_beacon_return(sc, avp);
|
||||
ath9k_ps_restore(sc);
|
||||
}
|
||||
|
||||
ath_beacon_return(sc, avp);
|
||||
sc->sc_flags &= ~SC_OP_BEACONS;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
|
||||
|
@ -297,7 +297,7 @@ u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags,
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_add_station);
|
||||
|
||||
static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
|
||||
static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const u8 *addr)
|
||||
{
|
||||
unsigned long flags;
|
||||
u8 sta_id = iwl_find_station(priv, addr);
|
||||
@ -324,7 +324,7 @@ static void iwl_remove_sta_callback(struct iwl_priv *priv,
|
||||
{
|
||||
struct iwl_rem_sta_cmd *rm_sta =
|
||||
(struct iwl_rem_sta_cmd *)cmd->cmd.payload;
|
||||
const char *addr = rm_sta->addr;
|
||||
const u8 *addr = rm_sta->addr;
|
||||
|
||||
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
|
||||
|
@ -376,20 +376,22 @@ static int __devinit fm3130_probe(struct i2c_client *client,
|
||||
}
|
||||
|
||||
/* Disabling calibration mode */
|
||||
if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL)
|
||||
if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) {
|
||||
i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
|
||||
fm3130->regs[FM3130_RTC_CONTROL] &
|
||||
~(FM3130_RTC_CONTROL_BIT_CAL));
|
||||
dev_warn(&client->dev, "Disabling calibration mode!\n");
|
||||
}
|
||||
|
||||
/* Disabling read and write modes */
|
||||
if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE ||
|
||||
fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ)
|
||||
fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) {
|
||||
i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
|
||||
fm3130->regs[FM3130_RTC_CONTROL] &
|
||||
~(FM3130_RTC_CONTROL_BIT_READ |
|
||||
FM3130_RTC_CONTROL_BIT_WRITE));
|
||||
dev_warn(&client->dev, "Disabling READ or WRITE mode!\n");
|
||||
}
|
||||
|
||||
/* oscillator off? turn it on, so clock can tick. */
|
||||
if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN)
|
||||
|
@ -394,7 +394,7 @@ static void ulite_console_write(struct console *co, const char *s,
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
static int __init ulite_console_setup(struct console *co, char *options)
|
||||
static int __devinit ulite_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_port *port;
|
||||
int baud = 9600;
|
||||
|
@ -593,7 +593,8 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
|
||||
*/
|
||||
static int imxfb_suspend(struct platform_device *dev, pm_message_t state)
|
||||
{
|
||||
struct imxfb_info *fbi = platform_get_drvdata(dev);
|
||||
struct fb_info *info = platform_get_drvdata(dev);
|
||||
struct imxfb_info *fbi = info->par;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
@ -603,7 +604,8 @@ static int imxfb_suspend(struct platform_device *dev, pm_message_t state)
|
||||
|
||||
static int imxfb_resume(struct platform_device *dev)
|
||||
{
|
||||
struct imxfb_info *fbi = platform_get_drvdata(dev);
|
||||
struct fb_info *info = platform_get_drvdata(dev);
|
||||
struct imxfb_info *fbi = info->par;
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
|
@ -324,8 +324,11 @@ static void sdc_enable_channel(struct mx3fb_info *mx3_fbi)
|
||||
unsigned long flags;
|
||||
dma_cookie_t cookie;
|
||||
|
||||
dev_dbg(mx3fb->dev, "mx3fbi %p, desc %p, sg %p\n", mx3_fbi,
|
||||
to_tx_desc(mx3_fbi->txd), to_tx_desc(mx3_fbi->txd)->sg);
|
||||
if (mx3_fbi->txd)
|
||||
dev_dbg(mx3fb->dev, "mx3fbi %p, desc %p, sg %p\n", mx3_fbi,
|
||||
to_tx_desc(mx3_fbi->txd), to_tx_desc(mx3_fbi->txd)->sg);
|
||||
else
|
||||
dev_dbg(mx3fb->dev, "mx3fbi %p, txd = NULL\n", mx3_fbi);
|
||||
|
||||
/* This enables the channel */
|
||||
if (mx3_fbi->cookie < 0) {
|
||||
@ -646,6 +649,7 @@ static int sdc_set_global_alpha(struct mx3fb_data *mx3fb, bool enable, uint8_t a
|
||||
|
||||
static void sdc_set_brightness(struct mx3fb_data *mx3fb, uint8_t value)
|
||||
{
|
||||
dev_dbg(mx3fb->dev, "%s: value = %d\n", __func__, value);
|
||||
/* This might be board-specific */
|
||||
mx3fb_write_reg(mx3fb, 0x03000000UL | value << 16, SDC_PWM_CTRL);
|
||||
return;
|
||||
@ -1486,12 +1490,12 @@ static int mx3fb_probe(struct platform_device *pdev)
|
||||
goto ersdc0;
|
||||
}
|
||||
|
||||
mx3fb->backlight_level = 255;
|
||||
|
||||
ret = init_fb_chan(mx3fb, to_idmac_chan(chan));
|
||||
if (ret < 0)
|
||||
goto eisdc0;
|
||||
|
||||
mx3fb->backlight_level = 255;
|
||||
|
||||
return 0;
|
||||
|
||||
eisdc0:
|
||||
|
@ -828,6 +828,9 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,
|
||||
if (!page)
|
||||
break;
|
||||
|
||||
if (mapping_writably_mapped(mapping))
|
||||
flush_dcache_page(page);
|
||||
|
||||
pagefault_disable();
|
||||
tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes);
|
||||
pagefault_enable();
|
||||
|
@ -24,9 +24,6 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define CN_IDX_CONNECTOR 0xffffffff
|
||||
#define CN_VAL_CONNECTOR 0xffffffff
|
||||
|
||||
/*
|
||||
* Process Events connector unique ids -- used for message routing
|
||||
*/
|
||||
@ -75,30 +72,6 @@ struct cn_msg {
|
||||
__u8 data[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* Notify structure - requests notification about
|
||||
* registering/unregistering idx/val in range [first, first+range].
|
||||
*/
|
||||
struct cn_notify_req {
|
||||
__u32 first;
|
||||
__u32 range;
|
||||
};
|
||||
|
||||
/*
|
||||
* Main notification control message
|
||||
* *_notify_num - number of appropriate cn_notify_req structures after
|
||||
* this struct.
|
||||
* group - notification receiver's idx.
|
||||
* len - total length of the attached data.
|
||||
*/
|
||||
struct cn_ctl_msg {
|
||||
__u32 idx_notify_num;
|
||||
__u32 val_notify_num;
|
||||
__u32 group;
|
||||
__u32 len;
|
||||
__u8 data[0];
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <asm/atomic.h>
|
||||
@ -151,11 +124,6 @@ struct cn_callback_entry {
|
||||
u32 seq, group;
|
||||
};
|
||||
|
||||
struct cn_ctl_entry {
|
||||
struct list_head notify_entry;
|
||||
struct cn_ctl_msg *msg;
|
||||
};
|
||||
|
||||
struct cn_dev {
|
||||
struct cb_id id;
|
||||
|
||||
|
@ -501,7 +501,7 @@ struct hid_device { /* device report descriptor */
|
||||
void (*hiddev_report_event) (struct hid_device *, struct hid_report *);
|
||||
|
||||
/* handler for raw output data, used by hidraw */
|
||||
int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t);
|
||||
int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t, unsigned char);
|
||||
|
||||
/* debugging support via debugfs */
|
||||
unsigned short debug;
|
||||
@ -690,6 +690,7 @@ int hid_input_report(struct hid_device *, int type, u8 *, int, int);
|
||||
int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field);
|
||||
void hid_output_report(struct hid_report *report, __u8 *data);
|
||||
struct hid_device *hid_allocate_device(void);
|
||||
struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id);
|
||||
int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
|
||||
int hid_check_keys_pressed(struct hid_device *hid);
|
||||
int hid_connect(struct hid_device *hid, unsigned int connect_mask);
|
||||
|
@ -2936,14 +2936,17 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
|
||||
|
||||
for_each_subsys(root, ss) {
|
||||
struct cgroup_subsys_state *css = ss->create(ss, cgrp);
|
||||
|
||||
if (IS_ERR(css)) {
|
||||
err = PTR_ERR(css);
|
||||
goto err_destroy;
|
||||
}
|
||||
init_cgroup_css(css, ss, cgrp);
|
||||
if (ss->use_id)
|
||||
if (alloc_css_id(ss, parent, cgrp))
|
||||
if (ss->use_id) {
|
||||
err = alloc_css_id(ss, parent, cgrp);
|
||||
if (err)
|
||||
goto err_destroy;
|
||||
}
|
||||
/* At error, ->destroy() callback has to free assigned ID. */
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,7 @@ struct cred *cred_alloc_blank(void)
|
||||
#ifdef CONFIG_KEYS
|
||||
new->tgcred = kzalloc(sizeof(*new->tgcred), GFP_KERNEL);
|
||||
if (!new->tgcred) {
|
||||
kfree(new);
|
||||
kmem_cache_free(cred_jar, new);
|
||||
return NULL;
|
||||
}
|
||||
atomic_set(&new->tgcred->usage, 1);
|
||||
|
@ -349,6 +349,7 @@ EXPORT_SYMBOL(__kfifo_from_user_n);
|
||||
* @fifo: the fifo to be used.
|
||||
* @from: pointer to the data to be added.
|
||||
* @len: the length of the data to be added.
|
||||
* @total: the actual returned data length.
|
||||
*
|
||||
* This function copies at most @len bytes from the @from into the
|
||||
* FIFO depending and returns -EFAULT/0.
|
||||
@ -399,7 +400,7 @@ EXPORT_SYMBOL(__kfifo_to_user_n);
|
||||
* @fifo: the fifo to be used.
|
||||
* @to: where the data must be copied.
|
||||
* @len: the size of the destination buffer.
|
||||
@ @lenout: pointer to output variable with copied data
|
||||
* @lenout: pointer to output variable with copied data
|
||||
*
|
||||
* This function copies at most @len bytes from the FIFO into the
|
||||
* @to buffer and 0 or -EFAULT.
|
||||
|
@ -140,8 +140,7 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
|
||||
id = *starting_id;
|
||||
restart:
|
||||
p = idp->top;
|
||||
l = idp->layers;
|
||||
pa[l--] = NULL;
|
||||
l = p->layer;
|
||||
while (1) {
|
||||
/*
|
||||
* We run around this while until we reach the leaf node...
|
||||
@ -155,8 +154,8 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
|
||||
oid = id;
|
||||
id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1;
|
||||
|
||||
/* if already at the top layer, we need to grow */
|
||||
if (!(p = pa[l])) {
|
||||
/* did id go over the limit? */
|
||||
if (id >= (1 << (idp->layers * IDR_BITS))) {
|
||||
*starting_id = id;
|
||||
return IDR_NEED_TO_GROW;
|
||||
}
|
||||
|
@ -2232,6 +2232,9 @@ again:
|
||||
if (unlikely(status))
|
||||
break;
|
||||
|
||||
if (mapping_writably_mapped(mapping))
|
||||
flush_dcache_page(page);
|
||||
|
||||
pagefault_disable();
|
||||
copied = iov_iter_copy_from_user_atomic(page, i, offset, bytes);
|
||||
pagefault_enable();
|
||||
|
@ -1515,10 +1515,9 @@ static struct attribute_group hstate_attr_group = {
|
||||
.attrs = hstate_attrs,
|
||||
};
|
||||
|
||||
static int __init hugetlb_sysfs_add_hstate(struct hstate *h,
|
||||
struct kobject *parent,
|
||||
struct kobject **hstate_kobjs,
|
||||
struct attribute_group *hstate_attr_group)
|
||||
static int hugetlb_sysfs_add_hstate(struct hstate *h, struct kobject *parent,
|
||||
struct kobject **hstate_kobjs,
|
||||
struct attribute_group *hstate_attr_group)
|
||||
{
|
||||
int retval;
|
||||
int hi = h - hstates;
|
||||
|
@ -243,6 +243,39 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
|
||||
input_sync(dev);
|
||||
}
|
||||
|
||||
static int __hidp_send_ctrl_message(struct hidp_session *session,
|
||||
unsigned char hdr, unsigned char *data, int size)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
BT_DBG("session %p data %p size %d", session, data, size);
|
||||
|
||||
if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
|
||||
BT_ERR("Can't allocate memory for new frame");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*skb_put(skb, 1) = hdr;
|
||||
if (data && size > 0)
|
||||
memcpy(skb_put(skb, size), data, size);
|
||||
|
||||
skb_queue_tail(&session->ctrl_transmit, skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int hidp_send_ctrl_message(struct hidp_session *session,
|
||||
unsigned char hdr, unsigned char *data, int size)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = __hidp_send_ctrl_message(session, hdr, data, size);
|
||||
|
||||
hidp_schedule(session);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int hidp_queue_report(struct hidp_session *session,
|
||||
unsigned char *data, int size)
|
||||
{
|
||||
@ -280,9 +313,22 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep
|
||||
return hidp_queue_report(session, buf, rsize);
|
||||
}
|
||||
|
||||
static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count)
|
||||
static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
|
||||
unsigned char report_type)
|
||||
{
|
||||
if (hidp_queue_report(hid->driver_data, data, count))
|
||||
switch (report_type) {
|
||||
case HID_FEATURE_REPORT:
|
||||
report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
|
||||
break;
|
||||
case HID_OUTPUT_REPORT:
|
||||
report_type = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (hidp_send_ctrl_message(hid->driver_data, report_type,
|
||||
data, count))
|
||||
return -ENOMEM;
|
||||
return count;
|
||||
}
|
||||
@ -307,39 +353,6 @@ static inline void hidp_del_timer(struct hidp_session *session)
|
||||
del_timer(&session->timer);
|
||||
}
|
||||
|
||||
static int __hidp_send_ctrl_message(struct hidp_session *session,
|
||||
unsigned char hdr, unsigned char *data, int size)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
BT_DBG("session %p data %p size %d", session, data, size);
|
||||
|
||||
if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
|
||||
BT_ERR("Can't allocate memory for new frame");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*skb_put(skb, 1) = hdr;
|
||||
if (data && size > 0)
|
||||
memcpy(skb_put(skb, size), data, size);
|
||||
|
||||
skb_queue_tail(&session->ctrl_transmit, skb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int hidp_send_ctrl_message(struct hidp_session *session,
|
||||
unsigned char hdr, unsigned char *data, int size)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = __hidp_send_ctrl_message(session, hdr, data, size);
|
||||
|
||||
hidp_schedule(session);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void hidp_process_handshake(struct hidp_session *session,
|
||||
unsigned char param)
|
||||
{
|
||||
|
@ -1368,7 +1368,6 @@ static int l2cap_ertm_send(struct sock *sk)
|
||||
|
||||
while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk)) &&
|
||||
!(pi->conn_state & L2CAP_CONN_REMOTE_BUSY)) {
|
||||
tx_skb = skb_clone(skb, GFP_ATOMIC);
|
||||
|
||||
if (pi->remote_max_tx &&
|
||||
bt_cb(skb)->retries == pi->remote_max_tx) {
|
||||
@ -1376,6 +1375,8 @@ static int l2cap_ertm_send(struct sock *sk)
|
||||
break;
|
||||
}
|
||||
|
||||
tx_skb = skb_clone(skb, GFP_ATOMIC);
|
||||
|
||||
bt_cb(skb)->retries++;
|
||||
|
||||
control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
|
||||
@ -3518,7 +3519,6 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
|
||||
struct l2cap_pinfo *pi;
|
||||
u16 control, len;
|
||||
u8 tx_seq;
|
||||
int err;
|
||||
|
||||
sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
|
||||
if (!sk) {
|
||||
@ -3570,13 +3570,11 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
|
||||
goto drop;
|
||||
|
||||
if (__is_iframe(control))
|
||||
err = l2cap_data_channel_iframe(sk, control, skb);
|
||||
l2cap_data_channel_iframe(sk, control, skb);
|
||||
else
|
||||
err = l2cap_data_channel_sframe(sk, control, skb);
|
||||
l2cap_data_channel_sframe(sk, control, skb);
|
||||
|
||||
if (!err)
|
||||
goto done;
|
||||
break;
|
||||
goto done;
|
||||
|
||||
case L2CAP_MODE_STREAMING:
|
||||
control = get_unaligned_le16(skb->data);
|
||||
@ -3602,7 +3600,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
|
||||
else
|
||||
pi->expected_tx_seq = tx_seq + 1;
|
||||
|
||||
err = l2cap_sar_reassembly_sdu(sk, skb, control);
|
||||
l2cap_sar_reassembly_sdu(sk, skb, control);
|
||||
|
||||
goto done;
|
||||
|
||||
|
@ -63,6 +63,7 @@ struct nf_ct_frag6_queue
|
||||
struct inet_frag_queue q;
|
||||
|
||||
__be32 id; /* fragment id */
|
||||
u32 user;
|
||||
struct in6_addr saddr;
|
||||
struct in6_addr daddr;
|
||||
|
||||
|
@ -680,7 +680,7 @@ TRACE_EVENT(drv_ampdu_action,
|
||||
__entry->ret = ret;
|
||||
__entry->action = action;
|
||||
__entry->tid = tid;
|
||||
__entry->ssn = *ssn;
|
||||
__entry->ssn = ssn ? *ssn : 0;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
|
@ -1437,8 +1437,9 @@ ctnetlink_exp_dump_mask(struct sk_buff *skb,
|
||||
struct nlattr *nest_parms;
|
||||
|
||||
memset(&m, 0xFF, sizeof(m));
|
||||
m.src.u.all = mask->src.u.all;
|
||||
memcpy(&m.src.u3, &mask->src.u3, sizeof(m.src.u3));
|
||||
m.src.u.all = mask->src.u.all;
|
||||
m.dst.protonum = tuple->dst.protonum;
|
||||
|
||||
nest_parms = nla_nest_start(skb, CTA_EXPECT_MASK | NLA_F_NESTED);
|
||||
if (!nest_parms)
|
||||
|
@ -376,7 +376,7 @@ int ct_sip_get_header(const struct nf_conn *ct, const char *dptr,
|
||||
dptr += hdr->len;
|
||||
else if (hdr->cname && limit - dptr >= hdr->clen + 1 &&
|
||||
strnicmp(dptr, hdr->cname, hdr->clen) == 0 &&
|
||||
!isalpha(*(dptr + hdr->clen + 1)))
|
||||
!isalpha(*(dptr + hdr->clen)))
|
||||
dptr += hdr->clen;
|
||||
else
|
||||
continue;
|
||||
|
@ -74,8 +74,8 @@ my %VCS_cmds;
|
||||
my %VCS_cmds_git = (
|
||||
"execute_cmd" => \&git_execute_cmd,
|
||||
"available" => '(which("git") ne "") && (-d ".git")',
|
||||
"find_signers_cmd" => "git log --since=\$email_git_since -- \$file",
|
||||
"find_commit_signers_cmd" => "git log -1 \$commit",
|
||||
"find_signers_cmd" => "git log --no-color --since=\$email_git_since -- \$file",
|
||||
"find_commit_signers_cmd" => "git log --no-color -1 \$commit",
|
||||
"blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file",
|
||||
"blame_file_cmd" => "git blame -l \$file",
|
||||
"commit_pattern" => "^commit [0-9a-f]{40,40}",
|
||||
|
@ -158,7 +158,7 @@ while (<STDIN>) {
|
||||
$function = $1;
|
||||
$func_offset = $2;
|
||||
}
|
||||
if ($line =~ /RIP: 0010:\[\<[0-9a-f]+\>\] \[\<[0-9a-f]+\>\] ([a-zA-Z0-9\_]+)\+(0x[0-9a-f]+)\/0x[a-f0-9]/) {
|
||||
if ($line =~ /RIP: 0010:\[\<[0-9a-f]+\>\] \[\<[0-9a-f]+\>\] ([a-zA-Z0-9\_]+)\+0x([0-9a-f]+)\/0x[a-f0-9]/) {
|
||||
$function = $1;
|
||||
$func_offset = $2;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user