From: "list subscribe" <develnewbie@gmail.com>
To: "BlueZ development" <bluez-devel@lists.sourceforge.net>
Subject: [Bluez-devel] [PATCH]Dynamic Alternate Setting patch (hci_usb.c)
Date: Tue, 24 Apr 2007 16:43:10 +0530 [thread overview]
Message-ID: <fc27e74b0704240413v5b6e2e80h7b2feb40d27de686@mail.gmail.com> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 7395 bytes --]
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,
[-- Attachment #1.2: Type: text/html, Size: 15709 bytes --]
[-- Attachment #2: Type: text/plain, Size: 286 bytes --]
-------------------------------------------------------------------------
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/
[-- Attachment #3: Type: text/plain, Size: 164 bytes --]
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel
next reply other threads:[~2007-04-24 11:13 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-24 11:13 list subscribe [this message]
2007-04-24 13:15 ` [Bluez-devel] [PATCH]Dynamic Alternate Setting patch (hci_usb.c) Jose Vasconcellos
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=fc27e74b0704240413v5b6e2e80h7b2feb40d27de686@mail.gmail.com \
--to=develnewbie@gmail.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