Linux bluetooth development
 help / color / mirror / Atom feed
* [Bluez-devel] Modified patch (Dynamic Alternate Setting)
@ 2007-04-25 21:24 list subscribe
  2007-04-25 22:04 ` Marcel Holtmann
  0 siblings, 1 reply; 5+ messages in thread
From: list subscribe @ 2007-04-25 21:24 UTC (permalink / raw)
  To: BlueZ development

[-- Attachment #1: Type: text/plain, Size: 90 bytes --]

Marcel,

I have made the changes u suggested.
Take a look and let me know.

Thanks,
Alok.

[-- Attachment #2: alternate-setting-patch --]
[-- Type: application/octet-stream, Size: 5700 bytes --]

diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index 406af57..3742ab7 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -56,6 +56,8 @@
 #undef  BT_DBG
 #define BT_DBG(D...)
 #endif
+/* The Workque Function */
+static void set_alternate_config(struct work_struct *work);
 
 #ifndef CONFIG_BT_HCIUSB_ZERO_PACKET
 #undef  URB_ZERO_PACKET
@@ -840,6 +842,7 @@ static void hci_usb_destruct(struct hci_dev *hdev)
 static void hci_usb_notify(struct hci_dev *hdev, unsigned int evt)
 {
 	BT_DBG("%s evt %d", hdev->name, evt);
+	schedule_work(&hdev->setting_work);
 }
 
 static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -1007,6 +1010,7 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id
 
 	hdev->owner = THIS_MODULE;
 
+    INIT_WORK(&hdev->setting_work,set_alternate_config);
 	if (reset || id->driver_info & HCI_RESET)
 		set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks);
 
@@ -1142,6 +1146,128 @@ static int hci_usb_resume(struct usb_interface *intf)
 	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)
+{
+
+  struct hci_dev *hdev = container_of(work, struct hci_dev, setting_work);
+  struct hci_usb *hUSB = (struct hci_usb *) hdev->driver_data;
+  
+/* if bit=0,its 8bit encoding else its 16bit */
+__u16 bit = 0x20;
+struct usb_interface *isocIface;
+  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(hdev->conn_hash.sco_num > 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(hdev->conn_hash.sco_num)
+		{
+		case 1:
+			if(hdev->voice_setting && bit)
+				isocAlt=2;
+			else
+				isocAlt=1;
+			break;
+		case 2:
+			if(hdev->voice_setting && bit)
+				isocAlt=4;
+			else
+				isocAlt=2;
+			break;
+		case 3:
+			if(hdev->voice_setting && 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);
+		isocIface = usb_ifnum_to_if(hUSB->udev, isocIfnum);
+		/* 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(hUSB->udev,isocIfnum, isocAlt)) {
+					BT_ERR("Can't set isoc interface settings");
+					hUSB->isoc_iface = isocIface;
+					usb_driver_release_interface(&hci_usb_driver, hUSB->isoc_iface);
+					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,
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 8a57b7d..f060288 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -110,6 +110,7 @@ struct hci_dev {
 	struct sk_buff_head	raw_q;
 	struct sk_buff_head	cmd_q;
 
+        struct work_struct      setting_work;
 	struct sk_buff		*sent_cmd;
 
 	struct semaphore	req_lock;

[-- Attachment #3: 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 #4: Type: text/plain, Size: 164 bytes --]

_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2007-05-03 21:17 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-04-25 21:24 [Bluez-devel] Modified patch (Dynamic Alternate Setting) list subscribe
2007-04-25 22:04 ` Marcel Holtmann
2007-04-27 19:40   ` Marcel Holtmann
2007-04-27 20:10     ` Marcel Holtmann
2007-05-03 21:17       ` list subscribe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox