Commit 85cdaf52 authored by Jiri Slaby's avatar Jiri Slaby Committed by Jiri Kosina

HID: make a bus from hid code

Make a bus from hid core. This is the first step for converting all the
quirks and separate almost-drivers into real drivers attached to this bus.

It's implemented to change behaviour in very tiny manner, so that no driver
needs to be changed this time.

Also add generic drivers for both usb and bt into usbhid or hidp
respectively which will bind all non-blacklisted device. Those blacklisted
will be either grabbed by special drivers or by nobody if they are broken at
the very rude base.
Signed-off-by: default avatarJiri Slaby <jslaby@suse.cz>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent e8c84f9a
This diff is collapsed.
......@@ -1032,7 +1032,7 @@ int hidinput_connect(struct hid_device *hid)
input_dev->id.vendor = hid->vendor;
input_dev->id.product = hid->product;
input_dev->id.version = hid->version;
input_dev->dev.parent = hid->dev;
input_dev->dev.parent = hid->dev.parent;
hidinput->input = input_dev;
list_add_tail(&hidinput->list, &hid->inputs);
}
......
......@@ -770,8 +770,15 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
dbg_hid_line(" %02x", (unsigned char) rdesc[n]);
dbg_hid_line("\n");
if (!(hid = hid_parse_report(rdesc, n))) {
hid = hid_allocate_device();
if (IS_ERR(hid)) {
kfree(rdesc);
return NULL;
}
if (hid_parse_report(hid, rdesc, n)) {
dbg_hid("parsing report descriptor failed\n");
hid_destroy_device(hid);
kfree(rdesc);
return NULL;
}
......@@ -798,10 +805,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (insize > HID_MAX_BUFFER_SIZE)
insize = HID_MAX_BUFFER_SIZE;
if (hid_alloc_buffers(dev, hid)) {
hid_free_buffers(dev, hid);
if (hid_alloc_buffers(dev, hid))
goto fail;
}
hid->name[0] = 0;
......@@ -881,7 +886,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
hid->version = le16_to_cpu(hdesc->bcdHID);
hid->country = hdesc->bCountryCode;
hid->dev = &intf->dev;
hid->dev.parent = &intf->dev;
usbhid->intf = intf;
usbhid->ifnum = interface->desc.bInterfaceNumber;
......@@ -925,7 +930,7 @@ fail:
hid_free_buffers(dev, hid);
kfree(usbhid);
fail_no_usbhid:
hid_free_device(hid);
hid_destroy_device(hid);
return NULL;
}
......@@ -964,14 +969,14 @@ static void hid_disconnect(struct usb_interface *intf)
hid_free_buffers(hid_to_usb_dev(hid), hid);
kfree(usbhid);
hid_free_device(hid);
hid_destroy_device(hid);
}
static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct hid_device *hid;
char path[64];
int i;
int i, ret;
char *c;
dbg_hid("HID probe called for ifnum %d\n",
......@@ -1037,7 +1042,12 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
printk(": USB HID v%x.%02x %s [%s] on %s\n",
hid->version >> 8, hid->version & 0xff, c, hid->name, path);
return 0;
ret = hid_add_device(hid);
if (ret) {
dev_err(&intf->dev, "can't add hid device: %d\n", ret);
hid_disconnect(intf);
}
return ret;
}
static int hid_suspend(struct usb_interface *intf, pm_message_t message)
......@@ -1107,9 +1117,22 @@ static struct usb_driver hid_driver = {
.supports_autosuspend = 1,
};
static const struct hid_device_id hid_usb_table[] = {
{ HID_USB_DEVICE(HID_ANY_ID, HID_ANY_ID) },
{ }
};
static struct hid_driver hid_usb_driver = {
.name = "generic-usb",
.id_table = hid_usb_table,
};
static int __init hid_init(void)
{
int retval;
retval = hid_register_driver(&hid_usb_driver);
if (retval)
goto hid_register_fail;
retval = usbhid_quirks_init(quirks_param);
if (retval)
goto usbhid_quirks_init_fail;
......@@ -1127,6 +1150,8 @@ usb_register_fail:
hiddev_init_fail:
usbhid_quirks_exit();
usbhid_quirks_init_fail:
hid_unregister_driver(&hid_usb_driver);
hid_register_fail:
return retval;
}
......@@ -1135,6 +1160,7 @@ static void __exit hid_exit(void)
usb_deregister(&hid_driver);
hiddev_exit();
usbhid_quirks_exit();
hid_unregister_driver(&hid_usb_driver);
}
module_init(hid_init);
......
......@@ -82,7 +82,7 @@ struct usbhid_device {
};
#define hid_to_usb_dev(hid_dev) \
container_of(hid_dev->dev->parent, struct usb_device, dev)
container_of(hid_dev->dev.parent->parent, struct usb_device, dev)
#endif
......@@ -418,6 +418,8 @@ struct hid_control_fifo {
#define HID_CLAIMED_HIDDEV 2
#define HID_CLAIMED_HIDRAW 4
#define HID_STAT_ADDED 1
#define HID_CTRL_RUNNING 1
#define HID_OUT_RUNNING 2
#define HID_IN_RUNNING 3
......@@ -432,22 +434,26 @@ struct hid_input {
struct input_dev *input;
};
struct hid_driver;
struct hid_device { /* device report descriptor */
__u8 *rdesc;
__u8 *rdesc;
unsigned rsize;
struct hid_collection *collection; /* List of HID collections */
unsigned collection_size; /* Number of allocated hid_collections */
unsigned maxcollection; /* Number of parsed collections */
unsigned maxapplication; /* Number of applications */
unsigned short bus; /* BUS ID */
unsigned short vendor; /* Vendor ID */
unsigned short product; /* Product ID */
unsigned version; /* HID version */
__u16 bus; /* BUS ID */
__u32 vendor; /* Vendor ID */
__u32 product; /* Product ID */
__u32 version; /* HID version */
unsigned country; /* HID country */
struct hid_report_enum report_enum[HID_REPORT_TYPES];
struct device *dev; /* device */
struct device dev; /* device */
struct hid_driver *driver;
unsigned int status; /* see STAT flags above */
unsigned claimed; /* Claimed by hidinput, hiddev? */
unsigned quirks; /* Various quirks the device can pull on us */
......@@ -483,6 +489,16 @@ struct hid_device { /* device report descriptor */
#endif
};
static inline void *hid_get_drvdata(struct hid_device *hdev)
{
return dev_get_drvdata(&hdev->dev);
}
static inline void hid_set_drvdata(struct hid_device *hdev, void *data)
{
dev_set_drvdata(&hdev->dev, data);
}
#define HID_GLOBAL_STACK_SIZE 4
#define HID_COLLECTION_STACK_SIZE 4
......@@ -511,6 +527,61 @@ struct hid_descriptor {
struct hid_class_descriptor desc[1];
} __attribute__ ((packed));
#define HID_DEVICE(b, ven, prod) \
.bus = (b), \
.vendor = (ven), .product = (prod)
#define HID_USB_DEVICE(ven, prod) HID_DEVICE(BUS_USB, ven, prod)
#define HID_BLUETOOTH_DEVICE(ven, prod) HID_DEVICE(BUS_BLUETOOTH, ven, prod)
#define HID_REPORT_ID(rep) \
.report_type = (rep)
#define HID_USAGE_ID(uhid, utype, ucode) \
.usage_hid = (uhid), .usage_type = (utype), .usage_code = (ucode)
/* we don't want to catch types and codes equal to 0 */
#define HID_TERMINATOR (HID_ANY_ID - 1)
struct hid_report_id {
__u32 report_type;
};
struct hid_usage_id {
__u32 usage_hid;
__u32 usage_type;
__u32 usage_code;
};
/**
* struct hid_driver
* @name: driver name (e.g. "Footech_bar-wheel")
* @id_table: which devices is this driver for (must be non-NULL for probe
* to be called)
* @probe: new device inserted
* @remove: device removed (NULL if not a hot-plug capable driver)
* @report_table: on which reports to call raw_event (NULL means all)
* @raw_event: if report in report_table, this hook is called (NULL means nop)
* @usage_table: on which events to call event (NULL means all)
* @event: if usage in usage_table, this hook is called (NULL means nop)
*
* raw_event and event should return 0 on no action performed, 1 when no
* further processing should be done and negative on error
*/
struct hid_driver {
char *name;
const struct hid_device_id *id_table;
int (*probe)(struct hid_device *dev, const struct hid_device_id *id);
void (*remove)(struct hid_device *dev);
const struct hid_report_id *report_table;
int (*raw_event)(struct hid_device *hdev, struct hid_report *report,
u8 *data, int size);
const struct hid_usage_id *usage_table;
int (*event)(struct hid_device *hdev, struct hid_field *field,
struct hid_usage *usage, __s32 value);
/* private: */
struct device_driver driver;
};
/* Applications from HID Usage Tables 4/8/99 Version 1.1 */
/* We ignore a few input applications that are not widely used */
#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001) || (a == 0x000d0002))
......@@ -521,6 +592,17 @@ struct hid_descriptor {
extern int hid_debug;
#endif
extern int hid_add_device(struct hid_device *);
extern void hid_destroy_device(struct hid_device *);
extern int __must_check __hid_register_driver(struct hid_driver *,
struct module *, const char *mod_name);
static inline int __must_check hid_register_driver(struct hid_driver *driver)
{
return __hid_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);
}
extern void hid_unregister_driver(struct hid_driver *);
extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report);
extern int hidinput_connect(struct hid_device *);
......@@ -533,8 +615,14 @@ int hidinput_mapping_quirks(struct hid_usage *, struct input_dev *, unsigned lon
int hidinput_event_quirks(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
int hidinput_apple_event(struct hid_device *, struct input_dev *, struct hid_usage *, __s32);
void hid_output_report(struct hid_report *report, __u8 *data);
void hid_free_device(struct hid_device *device);
struct hid_device *hid_parse_report(__u8 *start, unsigned size);
struct hid_device *hid_allocate_device(void);
int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
int interrupt);
extern int hid_generic_init(void);
extern void hid_generic_exit(void);
/* HID quirks API */
u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct);
......
......@@ -578,7 +578,7 @@ static int hidp_session(void *arg)
if (session->hid) {
if (session->hid->claimed & HID_CLAIMED_INPUT)
hidinput_disconnect(session->hid);
hid_free_device(session->hid);
hid_destroy_device(session->hid);
}
/* Wakeup user-space polling for socket errors */
......@@ -698,12 +698,13 @@ static void hidp_setup_quirks(struct hid_device *hid)
hid->quirks = hidp_blacklist[n].quirks;
}
static void hidp_setup_hid(struct hidp_session *session,
static int hidp_setup_hid(struct hidp_session *session,
struct hidp_connadd_req *req)
{
struct hid_device *hid = session->hid;
struct hid_report *report;
bdaddr_t src, dst;
int ret;
baswap(&src, &bt_sk(session->ctrl_sock->sk)->src);
baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst);
......@@ -721,7 +722,7 @@ static void hidp_setup_hid(struct hidp_session *session,
strncpy(hid->phys, batostr(&src), 64);
strncpy(hid->uniq, batostr(&dst), 64);
hid->dev = hidp_get_device(session);
hid->dev.parent = hidp_get_device(session);
hid->hid_open = hidp_open;
hid->hid_close = hidp_close;
......@@ -738,6 +739,15 @@ static void hidp_setup_hid(struct hidp_session *session,
if (hidinput_connect(hid) == 0)
hid->claimed |= HID_CLAIMED_INPUT;
ret = hid_add_device(hid);
if (ret) {
if (hid->claimed & HID_CLAIMED_INPUT)
hidinput_disconnect(hid);
skb_queue_purge(&session->intr_transmit);
}
return ret;
}
int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
......@@ -771,11 +781,19 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
return -EFAULT;
}
session->hid = hid_parse_report(buf, req->rd_size);
session->hid = hid_allocate_device();
if (IS_ERR(session->hid)) {
kfree(buf);
kfree(session);
return PTR_ERR(session->hid);
}
err = hid_parse_report(session->hid, buf, req->rd_size);
kfree(buf);
if (!session->hid) {
if (err) {
hid_destroy_device(session->hid);
kfree(session);
return -EINVAL;
}
......@@ -822,8 +840,11 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
goto failed;
}
if (session->hid)
hidp_setup_hid(session, req);
if (session->hid) {
err = hidp_setup_hid(session, req);
if (err)
goto failed;
}
__hidp_link_session(session);
......@@ -859,7 +880,7 @@ failed:
up_write(&hidp_session_sem);
if (session->hid)
hid_free_device(session->hid);
hid_destroy_device(session->hid);
input_free_device(session->input);
kfree(session);
......@@ -950,18 +971,43 @@ int hidp_get_conninfo(struct hidp_conninfo *ci)
return err;
}
static const struct hid_device_id hidp_table[] = {
{ HID_BLUETOOTH_DEVICE(HID_ANY_ID, HID_ANY_ID) },
{ }
};
static struct hid_driver hidp_driver = {
.name = "generic-bluetooth",
.id_table = hidp_table,
};
static int __init hidp_init(void)
{
int ret;
l2cap_load();
BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
return hidp_init_sockets();
ret = hid_register_driver(&hidp_driver);
if (ret)
goto err;
ret = hidp_init_sockets();
if (ret)
goto err_drv;
return 0;
err_drv:
hid_unregister_driver(&hidp_driver);
err:
return ret;
}
static void __exit hidp_exit(void)
{
hidp_cleanup_sockets();
hid_unregister_driver(&hidp_driver);
}
module_init(hidp_init);
......
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