public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
From: Jose Vasconcellos <jose@vasmac.com>
To: BlueZ development <bluez-devel@lists.sourceforge.net>
Subject: Re: [Bluez-devel] [PATCH]Dynamic Alternate Setting patch (hci_usb.c)
Date: Tue, 24 Apr 2007 07:15:39 -0600	[thread overview]
Message-ID: <462E02FB.8000600@vasmac.com> (raw)
In-Reply-To: <fc27e74b0704240413v5b6e2e80h7b2feb40d27de686@mail.gmail.com>

Hi Alok,

This is a good start. There are a few other things to consider:

* Are there error conditions in hci_usb_tx_complete that need to be handled?
* How do you make sure data for different channels is interleaved?

Jose

list subscribe wrote:
> Hi,
>
> As per the discussion on #bluez channel , I am attaching a patch which 
> dynamically manages the the alternate settings for SCO channels.
> The patch includes the following :
>
> 1. It declares a work queue(config_work), which is scheduled when
>              1. There is a change in number of SCO channels OR
>              2. There is a change in the Voice setting.
>
> 2. On invocation it determines the alternate setting based on the 
> table given in HCI - usb spec docs. The  table is also mentioned  in 
> the patch.
>
> 3. It then empties all the queued isochronous URBs , except those 
> which are already submitted.
>
> 4. It then sets the alternate setting by calling   usb_set_interface().
>
> I have tested this patch using "scotest".
> I am using 2.6.21-rc7 with sco-flowcontrol-v4.2.diff patch.
>
> Let me know if  any changes are necessary.
> Any suggestions are welcome.
>
>
>
> Alok. 
>
>
> --- hci_usb.c.orig    2007-04-16 19:37:41.000000000 +0530
> +++ hci_usb.c    2007-04-24 01:41:31.000000000 +0530
> @@ -47,6 +47,8 @@
>  
>  #include <linux/usb.h>
>  
> +#include <linux/workqueue.h>
> +
>  #include <net/bluetooth/bluetooth.h>
>  #include <net/bluetooth/hci_core.h>
>  
> @@ -57,6 +59,21 @@
>  #define BT_DBG(D...)
>  #endif
>  
> +/* The number of SCO channels  */
> +int NoSco=0;
> +/* The  Voice setting  */
> +__u16 VocSetting=0;
> +/* if bit=0,its 8bit encoding else its 16bit */
> +__u16 bit = 0x20;
> +
> +struct hci_usb *hUSB;
> +struct usb_device *usbdevice;
> +struct usb_interface *isocIface;
> +/* The Workque Function */
> +static void set_alternate_config(struct work_struct *work);
> +static DECLARE_WORK(config_work, set_alternate_config);
> +
> +
>  #ifndef CONFIG_BT_HCIUSB_ZERO_PACKET
>  #undef  URB_ZERO_PACKET
>  #define URB_ZERO_PACKET 0
> @@ -840,6 +857,10 @@
>  static void hci_usb_notify(struct hci_dev *hdev, unsigned int evt)
>  {
>      BT_DBG("%s evt %d", hdev->name, evt);
> +    NoSco = hdev->conn_hash.sco_num;
> +    VocSetting = hdev->voice_setting;
> +    hUSB = (struct hci_usb *) hdev->driver_data;
> +    schedule_work(&config_work);
>  }
>  
>  static int hci_usb_probe(struct usb_interface *intf, const struct 
> usb_device_id *id)
> @@ -854,7 +875,7 @@
>      struct hci_usb *husb;
>      struct hci_dev *hdev;
>      int i, e, size, isoc_ifnum, isoc_alts;
> -
> +    usbdevice = interface_to_usbdev(intf);
>      BT_DBG("udev %p intf %p", udev, intf);
>  
>      if (!id->driver_info) {
> @@ -926,9 +947,11 @@
>      isoc_ifnum = 1;
>  
>  #ifdef CONFIG_BT_HCIUSB_SCO
> -    if (isoc && !(id->driver_info & (HCI_BROKEN_ISOC | HCI_SNIFFER)))
> +    if (isoc && !(id->driver_info & (HCI_BROKEN_ISOC | HCI_SNIFFER))){
>          isoc_iface = usb_ifnum_to_if(udev, isoc_ifnum);
> -
> +            isocIface = usb_ifnum_to_if(udev, isoc_ifnum);
> +    }
> +   
>      if (isoc_iface) {
>          int a;
>          struct usb_host_endpoint *isoc_out_ep = NULL;
> @@ -1142,6 +1165,121 @@
>      return 0;
>  }
>  
> +
> +/*Set the alternate setting based on the number of SCO channels and the
> +  voice setting.This function is invoked when there is a change in 
> Number of
> +  SCO channels or when the voice encoding changes.*/
> +static void set_alternate_config(struct work_struct *work)
> +{
> +    int isocIfnum=1, isocAlt=0;
> +    struct usb_host_endpoint  *ep;
> +    struct usb_host_interface *uif;
> +    struct _urb *_urb,*_tmp;
> +    struct _urb_queue *q = &hUSB->pending_q[isoc];
> +    unsigned long flags;
> +    atomic_t temp;/*Holds the number of URBs we need to skip(which 
> are submitted)*/
> +    struct list_head inprocess;/*This list holds the already 
> submitted URBs */
> +   
> +    /*Change the alternate setting only if the number of SCO channels 
> are more than 1 */
> +    if(NoSco > 0){
> +        /* The alternate setting selection is based on the following 
> table */
> +        /*   No. of SCO channels    Bit-Encoding    Alternate 
> Setting   Max. Packet Size */
> +        /*           1                 8bit                 
> 1                  9 */
> +        /*           1                16bit                 
> 2                 17 */
> +        /*           2                 8bit                 
> 2                 17 */
> +        /*           2                16bit                 
> 4                 33 */
> +        /*           3                 8bit                 
> 3                 25 */
> +        /*           3                16bit                 
> 5                 49 */
> +        switch(NoSco)
> +        {
> +        case 1:
> +            if(VocSetting && bit)
> +                isocAlt=2;
> +            else
> +                isocAlt=1;
> +            break;
> +        case 2:
> +            if(VocSetting && bit)
> +                isocAlt=4;
> +            else
> +                isocAlt=2;
> +            break;
> +        case 3:
> +            if(VocSetting && bit)
> +                isocAlt=5;
> +            else
> +                isocAlt=3;
> +            break;
> +        }
> +
> +        /*Stop Current TX */
> +        clear_bit(HCI_USB_TX_WAKEUP, &hUSB->state);
> +        INIT_LIST_HEAD(&inprocess);
> +        temp = hUSB->pending_tx[isoc];
> +        /*  We cannot purge URBs which have been submitted. inprocess 
> is a */
> +        /*  temporary list which holds the currently submitted URBs. */
> +        /*  This list is later merged with the emptyed pending queue.  */
> +  
> +        while ((_urb = _urb_dequeue(q))) {
> +            /*Dequeue all the submitted URBs and put them in the 
> temporary list*/ 
> +            if(!atomic_dec_and_test(&temp)){
> +                _urb->queue = q;
> +                list_add(&_urb->list, &inprocess);
> +            }
> +            else{
> +                /*Unlink all the rest of URBs and put them into the 
> completed queue.*/
> +                _urb_unlink(_urb);
> +                _urb_queue_tail(__completed_q(hUSB,HCI_SCODATA_PKT), 
> _urb);
> +            }
> +        }
> +        /*merge the inprocess queue with the pending queue*/
> +        spin_lock_irqsave(&q->lock, flags);
> +        list_for_each_entry_safe(_urb, _tmp, &inprocess, list) {
> +            list_move_tail(&_urb->list, &q->head);
> +        }
> +        spin_unlock_irqrestore(&q->lock, flags);
> +   
> +        /* Set the setting and the in/out endpoints */
> +        if (isocIface) {
> +            int e;
> +            struct usb_host_endpoint *out = NULL;
> +            struct usb_host_endpoint *in = NULL;
> +            uif = &isocIface->altsetting[isocAlt];
> +            for (e = 0; e < uif->desc.bNumEndpoints; e++) {
> +                ep = &uif->endpoint[e];
> +                switch (ep->desc.bmAttributes & 
> USB_ENDPOINT_XFERTYPE_MASK) {
> +                case USB_ENDPOINT_XFER_ISOC:
> +                    if (ep->desc.bEndpointAddress & USB_DIR_IN)
> +                        in  = ep;
> +                    else
> +                        out = ep;
> +                    break;
> +                }
> +            }
> +       
> +            if (!in || !out)
> +                BT_DBG("Isoc endpoints not found");
> +            else {
> +                BT_DBG("isoc ifnum %d alts %d", isocIfnum, isocAlt);
> +                if (usb_set_interface(usbdevice, isocIfnum, isocAlt)) {
> +                    BT_ERR("Can't set isoc interface settings");
> +                    hUSB->isoc_iface = isocIface;
> +                    usb_driver_release_interface(&hci_usb_driver, 
> isocIface);
> +                    hUSB->isoc_iface = NULL;
> +                } else {
> +                    hUSB->isoc_iface  = isocIface;
> +                    hUSB->isoc_in_ep  = in;
> +                    hUSB->isoc_out_ep  = out;
> +                }
> +            }
> +        }
> +        set_bit(HCI_USB_TX_WAKEUP, &hUSB->state);
> +    }
> +
> +}
> + 
> +
> +
>  static struct usb_driver hci_usb_driver = {
>      .name        = "hci_usb",
>      .probe        = hci_usb_probe,
> ------------------------------------------------------------------------

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

  reply	other threads:[~2007-04-24 13:15 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-04-24 11:13 [Bluez-devel] [PATCH]Dynamic Alternate Setting patch (hci_usb.c) list subscribe
2007-04-24 13:15 ` Jose Vasconcellos [this message]
2007-04-24 15:08   ` list subscribe
2007-04-24 15:27     ` Jose Vasconcellos
2007-04-24 16:06       ` Marcel Holtmann
2007-04-24 16:13       ` alok
2007-04-24 17:08         ` Jose Vasconcellos
2007-04-24 18:38 ` Marcel Holtmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=462E02FB.8000600@vasmac.com \
    --to=jose@vasmac.com \
    --cc=bluez-devel@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox