diff mbox

[v5,5/7] Bluetooth: Extend btuart driver for join more vendor devices

Message ID 85d449cdd34bf47d72935a821915e825c64a2145.1531150733.git.sean.wang@mediatek.com (mailing list archive)
State New, archived
Headers show

Commit Message

Sean Wang July 9, 2018, 3:57 p.m. UTC
From: Sean Wang <sean.wang@mediatek.com>

Adding an independent btuart.h header allows these essential definitions
can be reused in vendor driver. Also, struct btuart_vnd is extended with
additional callbacks such as .init initializing vendor data, .shtudown,
.recv and .send supporting SoC specific framing for that btuart can
simply adapt to various Bluetooth uart-based devices.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 drivers/bluetooth/btuart.c | 73 ++++++++++++++++++++++++----------------------
 drivers/bluetooth/btuart.h | 30 +++++++++++++++++++
 2 files changed, 68 insertions(+), 35 deletions(-)
 create mode 100644 drivers/bluetooth/btuart.h

Comments

Marcel Holtmann July 14, 2018, 4:44 p.m. UTC | #1
Hi Sean,

> Adding an independent btuart.h header allows these essential definitions
> can be reused in vendor driver. Also, struct btuart_vnd is extended with
> additional callbacks such as .init initializing vendor data, .shtudown,
> .recv and .send supporting SoC specific framing for that btuart can
> simply adapt to various Bluetooth uart-based devices.
> 
> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> ---
> drivers/bluetooth/btuart.c | 73 ++++++++++++++++++++++++----------------------
> drivers/bluetooth/btuart.h | 30 +++++++++++++++++++
> 2 files changed, 68 insertions(+), 35 deletions(-)
> create mode 100644 drivers/bluetooth/btuart.h
> 
> diff --git a/drivers/bluetooth/btuart.c b/drivers/bluetooth/btuart.c
> index a900aac..65d0086 100644
> --- a/drivers/bluetooth/btuart.c
> +++ b/drivers/bluetooth/btuart.c
> @@ -33,35 +33,11 @@
> #include <net/bluetooth/hci_core.h>
> 
> #include "h4_recv.h"
> +#include "btuart.h"
> #include "btbcm.h"
> 
> #define VERSION "1.0"
> 
> -struct btuart_vnd {
> -	const struct h4_recv_pkt *recv_pkts;
> -	int recv_pkts_cnt;
> -	unsigned int manufacturer;
> -	int (*open)(struct hci_dev *hdev);
> -	int (*close)(struct hci_dev *hdev);
> -	int (*setup)(struct hci_dev *hdev);
> -};
> -
> -struct btuart_dev {
> -	struct hci_dev *hdev;
> -	struct serdev_device *serdev;
> -
> -	struct work_struct tx_work;
> -	unsigned long tx_state;
> -	struct sk_buff_head txq;
> -
> -	struct sk_buff *rx_skb;
> -
> -	const struct btuart_vnd *vnd;
> -};

I really like to avoid this since it is not clean. Frankly I prefer to keep the btuart.c driver for drivers that really just use H:4 as transport protocol. If the protocol is only H:4 alike and has extra headers, then it should be a separate driver.

The common H:4 handling is abstracted in h4_recv.h already anyway and we can add more pieces if needed. However I also wonder since you have extra framing that the complex H:4 state keeping might be not needed at all. So it could be simplified.

Regards

Marcel
Sean Wang July 15, 2018, 7:52 a.m. UTC | #2
On Sat, 2018-07-14 at 18:44 +0200, Marcel Holtmann wrote:
> Hi Sean,
> 
> > Adding an independent btuart.h header allows these essential definitions
> > can be reused in vendor driver. Also, struct btuart_vnd is extended with
> > additional callbacks such as .init initializing vendor data, .shtudown,
> > .recv and .send supporting SoC specific framing for that btuart can
> > simply adapt to various Bluetooth uart-based devices.
> > 
> > Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> > ---
> > drivers/bluetooth/btuart.c | 73 ++++++++++++++++++++++++----------------------
> > drivers/bluetooth/btuart.h | 30 +++++++++++++++++++
> > 2 files changed, 68 insertions(+), 35 deletions(-)
> > create mode 100644 drivers/bluetooth/btuart.h
> > 
> > diff --git a/drivers/bluetooth/btuart.c b/drivers/bluetooth/btuart.c
> > index a900aac..65d0086 100644
> > --- a/drivers/bluetooth/btuart.c
> > +++ b/drivers/bluetooth/btuart.c
> > @@ -33,35 +33,11 @@
> > #include <net/bluetooth/hci_core.h>
> > 
> > #include "h4_recv.h"
> > +#include "btuart.h"
> > #include "btbcm.h"
> > 
> > #define VERSION "1.0"
> > 
> > -struct btuart_vnd {
> > -	const struct h4_recv_pkt *recv_pkts;
> > -	int recv_pkts_cnt;
> > -	unsigned int manufacturer;
> > -	int (*open)(struct hci_dev *hdev);
> > -	int (*close)(struct hci_dev *hdev);
> > -	int (*setup)(struct hci_dev *hdev);
> > -};
> > -
> > -struct btuart_dev {
> > -	struct hci_dev *hdev;
> > -	struct serdev_device *serdev;
> > -
> > -	struct work_struct tx_work;
> > -	unsigned long tx_state;
> > -	struct sk_buff_head txq;
> > -
> > -	struct sk_buff *rx_skb;
> > -
> > -	const struct btuart_vnd *vnd;
> > -};
> 
> I really like to avoid this since it is not clean. Frankly I prefer to keep the btuart.c driver for drivers that really just use H:4 as transport protocol. If the protocol is only H:4 alike and has extra headers, then it should be a separate driver.
> 

thanks for letting me know your concern. I think I'm a little over in reusing these existing methods and break something generic and its beauty.

I'll make the driver be a separate one based on btuart in the next version.


> The common H:4 handling is abstracted in h4_recv.h already anyway and we can add more pieces if needed. However I also wonder since you have extra framing that the complex H:4 state keeping might be not needed at all. So it could be simplified.
> 

okay, I will get rid of h4_recv.h and consider to use more simplified logic to handle the extra framing and its payload.

> Regards
> 
> Marcel


> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek
Marcel Holtmann July 16, 2018, 12:59 p.m. UTC | #3
Hi Sean,

>>> Adding an independent btuart.h header allows these essential definitions
>>> can be reused in vendor driver. Also, struct btuart_vnd is extended with
>>> additional callbacks such as .init initializing vendor data, .shtudown,
>>> .recv and .send supporting SoC specific framing for that btuart can
>>> simply adapt to various Bluetooth uart-based devices.
>>> 
>>> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
>>> ---
>>> drivers/bluetooth/btuart.c | 73 ++++++++++++++++++++++++----------------------
>>> drivers/bluetooth/btuart.h | 30 +++++++++++++++++++
>>> 2 files changed, 68 insertions(+), 35 deletions(-)
>>> create mode 100644 drivers/bluetooth/btuart.h
>>> 
>>> diff --git a/drivers/bluetooth/btuart.c b/drivers/bluetooth/btuart.c
>>> index a900aac..65d0086 100644
>>> --- a/drivers/bluetooth/btuart.c
>>> +++ b/drivers/bluetooth/btuart.c
>>> @@ -33,35 +33,11 @@
>>> #include <net/bluetooth/hci_core.h>
>>> 
>>> #include "h4_recv.h"
>>> +#include "btuart.h"
>>> #include "btbcm.h"
>>> 
>>> #define VERSION "1.0"
>>> 
>>> -struct btuart_vnd {
>>> -	const struct h4_recv_pkt *recv_pkts;
>>> -	int recv_pkts_cnt;
>>> -	unsigned int manufacturer;
>>> -	int (*open)(struct hci_dev *hdev);
>>> -	int (*close)(struct hci_dev *hdev);
>>> -	int (*setup)(struct hci_dev *hdev);
>>> -};
>>> -
>>> -struct btuart_dev {
>>> -	struct hci_dev *hdev;
>>> -	struct serdev_device *serdev;
>>> -
>>> -	struct work_struct tx_work;
>>> -	unsigned long tx_state;
>>> -	struct sk_buff_head txq;
>>> -
>>> -	struct sk_buff *rx_skb;
>>> -
>>> -	const struct btuart_vnd *vnd;
>>> -};
>> 
>> I really like to avoid this since it is not clean. Frankly I prefer to keep the btuart.c driver for drivers that really just use H:4 as transport protocol. If the protocol is only H:4 alike and has extra headers, then it should be a separate driver.
>> 
> 
> thanks for letting me know your concern. I think I'm a little over in reusing these existing methods and break something generic and its beauty.
> 
> I'll make the driver be a separate one based on btuart in the next version.
> 
> 
>> The common H:4 handling is abstracted in h4_recv.h already anyway and we can add more pieces if needed. However I also wonder since you have extra framing that the complex H:4 state keeping might be not needed at all. So it could be simplified.
>> 
> 
> okay, I will get rid of h4_recv.h and consider to use more simplified logic to handle the extra framing and its payload.

only if it is already framed by your extra header, but I seem to recall that it will frame it. For example the bfusb.c old driver does frame H:4 as well and then no extra state keeping for H:4 is needed. Just pass the frames up into the core via hci_recv_frame (or hci_recv_diag for vendor diagnostic) and move on with it.

You can of course use h4_recv.h if you need to, but only do that if you are true H:4 stream and have no idea where a frame ends and starts.

Regards

Marcel
Sean Wang July 16, 2018, 3:29 p.m. UTC | #4
On Mon, 2018-07-16 at 14:59 +0200, Marcel Holtmann wrote:
> Hi Sean,
> 
> >>> Adding an independent btuart.h header allows these essential definitions
> >>> can be reused in vendor driver. Also, struct btuart_vnd is extended with
> >>> additional callbacks such as .init initializing vendor data, .shtudown,
> >>> .recv and .send supporting SoC specific framing for that btuart can
> >>> simply adapt to various Bluetooth uart-based devices.
> >>> 
> >>> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> >>> ---
> >>> drivers/bluetooth/btuart.c | 73 ++++++++++++++++++++++++----------------------
> >>> drivers/bluetooth/btuart.h | 30 +++++++++++++++++++
> >>> 2 files changed, 68 insertions(+), 35 deletions(-)
> >>> create mode 100644 drivers/bluetooth/btuart.h
> >>> 
> >>> diff --git a/drivers/bluetooth/btuart.c b/drivers/bluetooth/btuart.c
> >>> index a900aac..65d0086 100644
> >>> --- a/drivers/bluetooth/btuart.c
> >>> +++ b/drivers/bluetooth/btuart.c
> >>> @@ -33,35 +33,11 @@
> >>> #include <net/bluetooth/hci_core.h>
> >>> 
> >>> #include "h4_recv.h"
> >>> +#include "btuart.h"
> >>> #include "btbcm.h"
> >>> 
> >>> #define VERSION "1.0"
> >>> 
> >>> -struct btuart_vnd {
> >>> -	const struct h4_recv_pkt *recv_pkts;
> >>> -	int recv_pkts_cnt;
> >>> -	unsigned int manufacturer;
> >>> -	int (*open)(struct hci_dev *hdev);
> >>> -	int (*close)(struct hci_dev *hdev);
> >>> -	int (*setup)(struct hci_dev *hdev);
> >>> -};
> >>> -
> >>> -struct btuart_dev {
> >>> -	struct hci_dev *hdev;
> >>> -	struct serdev_device *serdev;
> >>> -
> >>> -	struct work_struct tx_work;
> >>> -	unsigned long tx_state;
> >>> -	struct sk_buff_head txq;
> >>> -
> >>> -	struct sk_buff *rx_skb;
> >>> -
> >>> -	const struct btuart_vnd *vnd;
> >>> -};
> >> 
> >> I really like to avoid this since it is not clean. Frankly I prefer to keep the btuart.c driver for drivers that really just use H:4 as transport protocol. If the protocol is only H:4 alike and has extra headers, then it should be a separate driver.
> >> 
> > 
> > thanks for letting me know your concern. I think I'm a little over in reusing these existing methods and break something generic and its beauty.
> > 
> > I'll make the driver be a separate one based on btuart in the next version.
> > 
> > 
> >> The common H:4 handling is abstracted in h4_recv.h already anyway and we can add more pieces if needed. However I also wonder since you have extra framing that the complex H:4 state keeping might be not needed at all. So it could be simplified.
> >> 
> > 
> > okay, I will get rid of h4_recv.h and consider to use more simplified logic to handle the extra framing and its payload.
> 
> only if it is already framed by your extra header, but I seem to recall that it will frame it. For example the bfusb.c old driver does frame H:4 as well and then no extra state keeping for H:4 is needed. Just pass the frames up into the core via hci_recv_frame (or hci_recv_diag for vendor diagnostic) and move on with it.
> 
> You can of course use h4_recv.h if you need to, but only do that if you are true H:4 stream and have no idea where a frame ends and starts.
> 
> Regards
> 
> Marcel
> 

Thanks for the explanation, I didn't show what the extra header is, that causes some misunderstanding.

The mtk extra header doesn't provide any idea where a frame ends and starts in the bluetooth stream. 

It is just totally a legacy stuff used by mtk combo devices sharing a serial transport, such as BT/GPS/FM running via a shared UART, to
let the host know what type of radio the following bytes is for and how long it's. 

The extra header is really useful for a combo device, splitting flow and fitting in a single serial transport, but for a single device such as
mt7622 Bluetooth I made here, it seems to be useless.

Because the extra header doesn't provide any details about this stream and each radio stack still needs to be in charge of their stream
parsing. That is why I still want to use recv_h4.h instead of coding my own parser.

	Sean
Marcel Holtmann July 18, 2018, 12:23 p.m. UTC | #5
Hi Sean,

>>>>> Adding an independent btuart.h header allows these essential definitions
>>>>> can be reused in vendor driver. Also, struct btuart_vnd is extended with
>>>>> additional callbacks such as .init initializing vendor data, .shtudown,
>>>>> .recv and .send supporting SoC specific framing for that btuart can
>>>>> simply adapt to various Bluetooth uart-based devices.
>>>>> 
>>>>> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
>>>>> ---
>>>>> drivers/bluetooth/btuart.c | 73 ++++++++++++++++++++++++----------------------
>>>>> drivers/bluetooth/btuart.h | 30 +++++++++++++++++++
>>>>> 2 files changed, 68 insertions(+), 35 deletions(-)
>>>>> create mode 100644 drivers/bluetooth/btuart.h
>>>>> 
>>>>> diff --git a/drivers/bluetooth/btuart.c b/drivers/bluetooth/btuart.c
>>>>> index a900aac..65d0086 100644
>>>>> --- a/drivers/bluetooth/btuart.c
>>>>> +++ b/drivers/bluetooth/btuart.c
>>>>> @@ -33,35 +33,11 @@
>>>>> #include <net/bluetooth/hci_core.h>
>>>>> 
>>>>> #include "h4_recv.h"
>>>>> +#include "btuart.h"
>>>>> #include "btbcm.h"
>>>>> 
>>>>> #define VERSION "1.0"
>>>>> 
>>>>> -struct btuart_vnd {
>>>>> -	const struct h4_recv_pkt *recv_pkts;
>>>>> -	int recv_pkts_cnt;
>>>>> -	unsigned int manufacturer;
>>>>> -	int (*open)(struct hci_dev *hdev);
>>>>> -	int (*close)(struct hci_dev *hdev);
>>>>> -	int (*setup)(struct hci_dev *hdev);
>>>>> -};
>>>>> -
>>>>> -struct btuart_dev {
>>>>> -	struct hci_dev *hdev;
>>>>> -	struct serdev_device *serdev;
>>>>> -
>>>>> -	struct work_struct tx_work;
>>>>> -	unsigned long tx_state;
>>>>> -	struct sk_buff_head txq;
>>>>> -
>>>>> -	struct sk_buff *rx_skb;
>>>>> -
>>>>> -	const struct btuart_vnd *vnd;
>>>>> -};
>>>> 
>>>> I really like to avoid this since it is not clean. Frankly I prefer to keep the btuart.c driver for drivers that really just use H:4 as transport protocol. If the protocol is only H:4 alike and has extra headers, then it should be a separate driver.
>>>> 
>>> 
>>> thanks for letting me know your concern. I think I'm a little over in reusing these existing methods and break something generic and its beauty.
>>> 
>>> I'll make the driver be a separate one based on btuart in the next version.
>>> 
>>> 
>>>> The common H:4 handling is abstracted in h4_recv.h already anyway and we can add more pieces if needed. However I also wonder since you have extra framing that the complex H:4 state keeping might be not needed at all. So it could be simplified.
>>>> 
>>> 
>>> okay, I will get rid of h4_recv.h and consider to use more simplified logic to handle the extra framing and its payload.
>> 
>> only if it is already framed by your extra header, but I seem to recall that it will frame it. For example the bfusb.c old driver does frame H:4 as well and then no extra state keeping for H:4 is needed. Just pass the frames up into the core via hci_recv_frame (or hci_recv_diag for vendor diagnostic) and move on with it.
>> 
>> You can of course use h4_recv.h if you need to, but only do that if you are true H:4 stream and have no idea where a frame ends and starts.
>> 
>> Regards
>> 
>> Marcel
>> 
> 
> Thanks for the explanation, I didn't show what the extra header is, that causes some misunderstanding.
> 
> The mtk extra header doesn't provide any idea where a frame ends and starts in the bluetooth stream. 
> 
> It is just totally a legacy stuff used by mtk combo devices sharing a serial transport, such as BT/GPS/FM running via a shared UART, to
> let the host know what type of radio the following bytes is for and how long it's. 

but that means it is framed. You know ahead of time how long the H:4 packet will be. That is the important part. Unless you tell me that it can fragment a H:4 frame over multiple MTK specific frames.

> The extra header is really useful for a combo device, splitting flow and fitting in a single serial transport, but for a single device such as
> mt7622 Bluetooth I made here, it seems to be useless.

Useless or not depends on what you are going to do with the device. In theory you could write a serdev driver that just handles the multiplexing (since that is what you have) and then hands down the frames to individual drivers. Frankly something like btqcomsmd.c seems to be what you really want here. However first you would needed this multiplex driver that takes the serial stream and breaks it up.

> Because the extra header doesn't provide any details about this stream and each radio stack still needs to be in charge of their stream
> parsing. That is why I still want to use recv_h4.h instead of coding my own parser.

As I said above, if the header + length always indicates a full H:4 frame, then you do not need h4_recv.h since you know the packet size. If it doesn't (and it means things can fragment), then you do.

However I have to note that a serial stream from your multiplexer protocol also needs some state handling since it can be interrupted at any point. If you want this clean, then you actually do that anyway. Essentially you have two protocols layered and want to process the independently.

If you post details about the multiplexing protocol for your serial stream, then I can help you design a driver for it. With serdev that is actually simple. And then you could hook up GPS etc. at some point once you want to run this on hardware that has the combo chip.

Having a Linux Bluetooth driver is useful for Android as well btw. We have HCI_CHANNEL_USER and a generic Android driver for using it. So enabling the chip in Linux upstream will enable it for Android as well.

Regards

Marcel
Sean Wang July 18, 2018, 2:26 p.m. UTC | #6
On Wed, 2018-07-18 at 14:23 +0200, Marcel Holtmann wrote:
> Hi Sean,
> 
> >>>>> Adding an independent btuart.h header allows these essential definitions
> >>>>> can be reused in vendor driver. Also, struct btuart_vnd is extended with
> >>>>> additional callbacks such as .init initializing vendor data, .shtudown,
> >>>>> .recv and .send supporting SoC specific framing for that btuart can
> >>>>> simply adapt to various Bluetooth uart-based devices.
> >>>>> 
> >>>>> Signed-off-by: Sean Wang <sean.wang@mediatek.com>
> >>>>> ---
> >>>>> drivers/bluetooth/btuart.c | 73 ++++++++++++++++++++++++----------------------
> >>>>> drivers/bluetooth/btuart.h | 30 +++++++++++++++++++
> >>>>> 2 files changed, 68 insertions(+), 35 deletions(-)
> >>>>> create mode 100644 drivers/bluetooth/btuart.h
> >>>>> 
> >>>>> diff --git a/drivers/bluetooth/btuart.c b/drivers/bluetooth/btuart.c
> >>>>> index a900aac..65d0086 100644
> >>>>> --- a/drivers/bluetooth/btuart.c
> >>>>> +++ b/drivers/bluetooth/btuart.c
> >>>>> @@ -33,35 +33,11 @@
> >>>>> #include <net/bluetooth/hci_core.h>
> >>>>> 
> >>>>> #include "h4_recv.h"
> >>>>> +#include "btuart.h"
> >>>>> #include "btbcm.h"
> >>>>> 
> >>>>> #define VERSION "1.0"
> >>>>> 
> >>>>> -struct btuart_vnd {
> >>>>> -	const struct h4_recv_pkt *recv_pkts;
> >>>>> -	int recv_pkts_cnt;
> >>>>> -	unsigned int manufacturer;
> >>>>> -	int (*open)(struct hci_dev *hdev);
> >>>>> -	int (*close)(struct hci_dev *hdev);
> >>>>> -	int (*setup)(struct hci_dev *hdev);
> >>>>> -};
> >>>>> -
> >>>>> -struct btuart_dev {
> >>>>> -	struct hci_dev *hdev;
> >>>>> -	struct serdev_device *serdev;
> >>>>> -
> >>>>> -	struct work_struct tx_work;
> >>>>> -	unsigned long tx_state;
> >>>>> -	struct sk_buff_head txq;
> >>>>> -
> >>>>> -	struct sk_buff *rx_skb;
> >>>>> -
> >>>>> -	const struct btuart_vnd *vnd;
> >>>>> -};
> >>>> 
> >>>> I really like to avoid this since it is not clean. Frankly I prefer to keep the btuart.c driver for drivers that really just use H:4 as transport protocol. If the protocol is only H:4 alike and has extra headers, then it should be a separate driver.
> >>>> 
> >>> 
> >>> thanks for letting me know your concern. I think I'm a little over in reusing these existing methods and break something generic and its beauty.
> >>> 
> >>> I'll make the driver be a separate one based on btuart in the next version.
> >>> 
> >>> 
> >>>> The common H:4 handling is abstracted in h4_recv.h already anyway and we can add more pieces if needed. However I also wonder since you have extra framing that the complex H:4 state keeping might be not needed at all. So it could be simplified.
> >>>> 
> >>> 
> >>> okay, I will get rid of h4_recv.h and consider to use more simplified logic to handle the extra framing and its payload.
> >> 
> >> only if it is already framed by your extra header, but I seem to recall that it will frame it. For example the bfusb.c old driver does frame H:4 as well and then no extra state keeping for H:4 is needed. Just pass the frames up into the core via hci_recv_frame (or hci_recv_diag for vendor diagnostic) and move on with it.
> >> 
> >> You can of course use h4_recv.h if you need to, but only do that if you are true H:4 stream and have no idea where a frame ends and starts.
> >> 
> >> Regards
> >> 
> >> Marcel
> >> 
> > 
> > Thanks for the explanation, I didn't show what the extra header is, that causes some misunderstanding.
> > 
> > The mtk extra header doesn't provide any idea where a frame ends and starts in the bluetooth stream. 
> > 
> > It is just totally a legacy stuff used by mtk combo devices sharing a serial transport, such as BT/GPS/FM running via a shared UART, to
> > let the host know what type of radio the following bytes is for and how long it's. 
> 
> but that means it is framed. You know ahead of time how long the H:4 packet will be. That is the important part. Unless you tell me that it can fragment a H:4 frame over multiple MTK specific frames.
> 
> > The extra header is really useful for a combo device, splitting flow and fitting in a single serial transport, but for a single device such as
> > mt7622 Bluetooth I made here, it seems to be useless.
> 
> Useless or not depends on what you are going to do with the device. In theory you could write a serdev driver that just handles the multiplexing (since that is what you have) and then hands down the frames to individual drivers. Frankly something like btqcomsmd.c seems to be what you really want here. However first you would needed this multiplex driver that takes the serial stream and breaks it up.
> 
> > Because the extra header doesn't provide any details about this stream and each radio stack still needs to be in charge of their stream
> > parsing. That is why I still want to use recv_h4.h instead of coding my own parser.
> 
> As I said above, if the header + length always indicates a full H:4 frame, then you do not need h4_recv.h since you know the packet size. If it doesn't (and it means things can fragment), then you do.
> 

My case is the extra header + length doesn't indicate a full H:4 frame,
things can fragment

> However I have to note that a serial stream from your multiplexer protocol also needs some state handling since it can be interrupted at any point. If you want this clean, then you actually do that anyway. Essentially you have two protocols layered and want to process the independently.

Yes, I also agree that it makes better and cleaner if there is another
driver in charge of the multiplexer protocol and the framing.

But, could you accept that I postpone the target into the next stage,
I just like to consider BT single device, not for multiplexer protocol
case, in the current stage.

To be honest, my next step is to add mt7688 btusb and then want to have
an integration with btmtkuart. mt7688 btusb doesn't have extra framing
for multiplexer protocol, so it can allow me to make the concentration
more on pure bt protocol and pushing the latest mtk bluetooth devices
being supported on the bluez driver.

> If you post details about the multiplexing protocol for your serial stream, then I can help you design a driver for it. With serdev that is actually simple. And then you could hook up GPS etc. at some point once you want to run this on hardware that has the combo chip.
> 

okay, really thanks for your help. I also have an interest on this part.
now how does bluez receive and sent packet from/to a virtual device ( a
serdev handling multiplexer protocol)? It seems current bluez device all
handling packet from/to physical bus device. or I was missing something?

> Having a Linux Bluetooth driver is useful for Android as well btw. We have HCI_CHANNEL_USER and a generic Android driver for using it. So enabling the chip in Linux upstream will enable it for Android as well.
> 
it really save more time as I knew many vendors do two driver separately
for bluez and bluedroid. where could I find the resource for
HCI_CHANNEL_USER and generic android driver ? Is it still the part of
bluez or run by another project ?

> Regards
> 
> Marcel
>
Sean Wang July 18, 2018, 4:56 p.m. UTC | #7
On Wed, 2018-07-18 at 22:26 +0800, Sean Wang wrote:
> On Wed, 2018-07-18 at 14:23 +0200, Marcel Holtmann wrote:
> > Hi Sean,
> > 

[ ... ]

> > > Because the extra header doesn't provide any details about this stream and each radio stack still needs to be in charge of their stream
> > > parsing. That is why I still want to use recv_h4.h instead of coding my own parser.
> > 
> > As I said above, if the header + length always indicates a full H:4 frame, then you do not need h4_recv.h since you know the packet size. If it doesn't (and it means things can fragment), then you do.
> > 
> 
> My case is the extra header + length doesn't indicate a full H:4 frame,
> things can fragment
> 
> > However I have to note that a serial stream from your multiplexer protocol also needs some state handling since it can be interrupted at any point. If you want this clean, then you actually do that anyway. Essentially you have two protocols layered and want to process the independently.
> 
> Yes, I also agree that it makes better and cleaner if there is another
> driver in charge of the multiplexer protocol and the framing.
> 
> But, could you accept that I postpone the target into the next stage,
> I just like to consider BT single device, not for multiplexer protocol
> case, in the current stage.
> 
> To be honest, my next step is to add mt7688 btusb and then want to have
> an integration with btmtkuart. mt7688 btusb doesn't have extra framing

something needs to be fixed, I mean mt7668 instead of mt7688

> for multiplexer protocol, so it can allow me to make the concentration
> more on pure bt protocol and pushing the latest mtk bluetooth devices
> being supported on the bluez driver.
> 
> > If you post details about the multiplexing protocol for your serial stream, then I can help you design a driver for it. With serdev that is actually simple. And then you could hook up GPS etc. at some point once you want to run this on hardware that has the combo chip.
> > 
> 
> okay, really thanks for your help. I also have an interest on this part.
> now how does bluez receive and sent packet from/to a virtual device ( a
> serdev handling multiplexer protocol)? It seems current bluez device all
> handling packet from/to physical bus device. or I was missing something?
> 
> > Having a Linux Bluetooth driver is useful for Android as well btw. We have HCI_CHANNEL_USER and a generic Android driver for using it. So enabling the chip in Linux upstream will enable it for Android as well.
> > 
> it really save more time as I knew many vendors do two driver separately
> for bluez and bluedroid. where could I find the resource for
> HCI_CHANNEL_USER and generic android driver ? Is it still the part of
> bluez or run by another project ?
> 
> > Regards
> > 
> > Marcel
> > 
> 
> 
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek
diff mbox

Patch

diff --git a/drivers/bluetooth/btuart.c b/drivers/bluetooth/btuart.c
index a900aac..65d0086 100644
--- a/drivers/bluetooth/btuart.c
+++ b/drivers/bluetooth/btuart.c
@@ -33,35 +33,11 @@ 
 #include <net/bluetooth/hci_core.h>
 
 #include "h4_recv.h"
+#include "btuart.h"
 #include "btbcm.h"
 
 #define VERSION "1.0"
 
-struct btuart_vnd {
-	const struct h4_recv_pkt *recv_pkts;
-	int recv_pkts_cnt;
-	unsigned int manufacturer;
-	int (*open)(struct hci_dev *hdev);
-	int (*close)(struct hci_dev *hdev);
-	int (*setup)(struct hci_dev *hdev);
-};
-
-struct btuart_dev {
-	struct hci_dev *hdev;
-	struct serdev_device *serdev;
-
-	struct work_struct tx_work;
-	unsigned long tx_state;
-	struct sk_buff_head txq;
-
-	struct sk_buff *rx_skb;
-
-	const struct btuart_vnd *vnd;
-};
-
-#define BTUART_TX_STATE_ACTIVE	1
-#define BTUART_TX_STATE_WAKEUP	2
-
 static void btuart_tx_work(struct work_struct *work)
 {
 	struct btuart_dev *bdev = container_of(work, struct btuart_dev,
@@ -187,13 +163,27 @@  static int btuart_setup(struct hci_dev *hdev)
 	return 0;
 }
 
+static int btuart_shutdown(struct hci_dev *hdev)
+{
+	struct btuart_dev *bdev = hci_get_drvdata(hdev);
+
+	if (bdev->vnd->shutdown)
+		return bdev->vnd->shutdown(hdev);
+
+	return 0;
+}
+
 static int btuart_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct btuart_dev *bdev = hci_get_drvdata(hdev);
 
-	/* Prepend skb with frame type */
-	memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
-	skb_queue_tail(&bdev->txq, skb);
+	if (bdev->vnd->send) {
+		bdev->vnd->send(hdev, skb);
+	} else {
+		/* Prepend skb with frame type */
+		memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
+		skb_queue_tail(&bdev->txq, skb);
+	}
 
 	btuart_tx_wakeup(bdev);
 	return 0;
@@ -204,14 +194,23 @@  static int btuart_receive_buf(struct serdev_device *serdev, const u8 *data,
 {
 	struct btuart_dev *bdev = serdev_device_get_drvdata(serdev);
 	const struct btuart_vnd *vnd = bdev->vnd;
+	int err;
 
-	bdev->rx_skb = h4_recv_buf(bdev->hdev, bdev->rx_skb, data, count,
-				   vnd->recv_pkts, vnd->recv_pkts_cnt);
-	if (IS_ERR(bdev->rx_skb)) {
-		int err = PTR_ERR(bdev->rx_skb);
-		bt_dev_err(bdev->hdev, "Frame reassembly failed (%d)", err);
-		bdev->rx_skb = NULL;
-		return err;
+	if (bdev->vnd->recv) {
+		err = bdev->vnd->recv(bdev->hdev, data, count);
+		if (err < 0)
+			return err;
+	} else {
+		bdev->rx_skb = h4_recv_buf(bdev->hdev, bdev->rx_skb,
+					   data, count, vnd->recv_pkts,
+					   vnd->recv_pkts_cnt);
+		if (IS_ERR(bdev->rx_skb)) {
+			err = PTR_ERR(bdev->rx_skb);
+			bt_dev_err(bdev->hdev,
+				   "Frame reassembly failed (%d)", err);
+			bdev->rx_skb = NULL;
+			return err;
+		}
 	}
 
 	bdev->hdev->stat.byte_rx += count;
@@ -429,6 +428,9 @@  static int btuart_probe(struct serdev_device *serdev)
 	if (!bdev->vnd)
 		bdev->vnd = &default_vnd;
 
+	if (bdev->vnd->init)
+		bdev->data = bdev->vnd->init(&serdev->dev);
+
 	bdev->serdev = serdev;
 	serdev_device_set_drvdata(serdev, bdev);
 
@@ -460,6 +462,7 @@  static int btuart_probe(struct serdev_device *serdev)
 	hdev->close = btuart_close;
 	hdev->flush = btuart_flush;
 	hdev->setup = btuart_setup;
+	hdev->shutdown = btuart_shutdown;
 	hdev->send  = btuart_send_frame;
 	SET_HCIDEV_DEV(hdev, &serdev->dev);
 
diff --git a/drivers/bluetooth/btuart.h b/drivers/bluetooth/btuart.h
new file mode 100644
index 0000000..6c1fe31
--- /dev/null
+++ b/drivers/bluetooth/btuart.h
@@ -0,0 +1,30 @@ 
+struct btuart_vnd {
+	const struct h4_recv_pkt *recv_pkts;
+	int recv_pkts_cnt;
+	unsigned int manufacturer;
+	void *(*init)(struct device *dev);
+
+	int (*open)(struct hci_dev *hdev);
+	int (*close)(struct hci_dev *hdev);
+	int (*setup)(struct hci_dev *hdev);
+	int (*shutdown)(struct hci_dev *hdev);
+	int (*send)(struct hci_dev *hdev, struct sk_buff *skb);
+	int (*recv)(struct hci_dev *hdev, const u8 *data, size_t count);
+};
+
+struct btuart_dev {
+	struct hci_dev *hdev;
+	struct serdev_device *serdev;
+
+	struct work_struct tx_work;
+	unsigned long tx_state;
+	struct sk_buff_head txq;
+
+	struct sk_buff *rx_skb;
+
+	const struct btuart_vnd *vnd;
+	void *data;
+};
+
+#define BTUART_TX_STATE_ACTIVE	1
+#define BTUART_TX_STATE_WAKEUP	2