Bluetooth: hci_h5: Add support for serdev enumerated devices
Add basic support for serdev enumerated devices, note sine this does not (yet) declare any of / ACPI ids to bind to atm this is a nop. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
1cc194caaf
commit
ce945552fd
1 changed files with 48 additions and 4 deletions
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/serdev.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
|
@ -65,6 +66,9 @@ enum {
|
|||
};
|
||||
|
||||
struct h5 {
|
||||
/* Must be the first member, hci_serdev.c expects this. */
|
||||
struct hci_uart serdev_hu;
|
||||
|
||||
struct sk_buff_head unack; /* Unack'ed packets queue */
|
||||
struct sk_buff_head rel; /* Reliable packets queue */
|
||||
struct sk_buff_head unrel; /* Unreliable packets queue */
|
||||
|
@ -193,9 +197,13 @@ static int h5_open(struct hci_uart *hu)
|
|||
|
||||
BT_DBG("hu %p", hu);
|
||||
|
||||
h5 = kzalloc(sizeof(*h5), GFP_KERNEL);
|
||||
if (!h5)
|
||||
return -ENOMEM;
|
||||
if (hu->serdev) {
|
||||
h5 = serdev_device_get_drvdata(hu->serdev);
|
||||
} else {
|
||||
h5 = kzalloc(sizeof(*h5), GFP_KERNEL);
|
||||
if (!h5)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
hu->priv = h5;
|
||||
h5->hu = hu;
|
||||
|
@ -229,7 +237,8 @@ static int h5_close(struct hci_uart *hu)
|
|||
skb_queue_purge(&h5->rel);
|
||||
skb_queue_purge(&h5->unrel);
|
||||
|
||||
kfree(h5);
|
||||
if (!hu->serdev)
|
||||
kfree(h5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -750,12 +759,47 @@ static const struct hci_uart_proto h5p = {
|
|||
.flush = h5_flush,
|
||||
};
|
||||
|
||||
static int h5_serdev_probe(struct serdev_device *serdev)
|
||||
{
|
||||
struct device *dev = &serdev->dev;
|
||||
struct h5 *h5;
|
||||
|
||||
h5 = devm_kzalloc(dev, sizeof(*h5), GFP_KERNEL);
|
||||
if (!h5)
|
||||
return -ENOMEM;
|
||||
|
||||
set_bit(HCI_UART_RESET_ON_INIT, &h5->serdev_hu.flags);
|
||||
|
||||
h5->hu = &h5->serdev_hu;
|
||||
h5->serdev_hu.serdev = serdev;
|
||||
serdev_device_set_drvdata(serdev, h5);
|
||||
|
||||
return hci_uart_register_device(&h5->serdev_hu, &h5p);
|
||||
}
|
||||
|
||||
static void h5_serdev_remove(struct serdev_device *serdev)
|
||||
{
|
||||
struct h5 *h5 = serdev_device_get_drvdata(serdev);
|
||||
|
||||
hci_uart_unregister_device(&h5->serdev_hu);
|
||||
}
|
||||
|
||||
static struct serdev_device_driver h5_serdev_driver = {
|
||||
.probe = h5_serdev_probe,
|
||||
.remove = h5_serdev_remove,
|
||||
.driver = {
|
||||
.name = "hci_uart_h5",
|
||||
},
|
||||
};
|
||||
|
||||
int __init h5_init(void)
|
||||
{
|
||||
serdev_device_driver_register(&h5_serdev_driver);
|
||||
return hci_uart_register_proto(&h5p);
|
||||
}
|
||||
|
||||
int __exit h5_deinit(void)
|
||||
{
|
||||
serdev_device_driver_unregister(&h5_serdev_driver);
|
||||
return hci_uart_unregister_proto(&h5p);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue