Hi!

> > The TODO file says:
> > 
> > # > +
> > # > +     skb_queue_tail(&info->txq, fw_skb);
> > # > +     spin_lock_irqsave(&info->lock, flags);
> > # > +     hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) |
> > # > +                     UART_IER_THRI);
> > # > +     spin_unlock_irqrestore(&info->lock, flags);
> > # > +}
> > # 
> > # and as I explained before, this crazy can not continue. Bluetooth drivers 
> > can provide a
> > # +hdev->setup callback for loading firmware and doing other setup details. 
> > You can just
> > # +bring up the HCI transport. We are providing __hci_cmd_sync for easy 
> > loading of the
> > # +firmware. Especially if the firmware just consists of HCI commands. 
> > Which is clearly the
> > # +case with the Nokia firmware files.
> > 
> > ...so I take it you (and thus TODO) were wrong and __hci_cmd_sync is
> > not suitable after all?
> 
> __hci_cmd_sync is to be used in hdev->setup where you load the firmware. 
> However when hdev->setup is run, we expect that the HCI transport is fully up 
> and running and that the driver takes care of the transport. That is done via 
> hdev->send and hci_recv_frame.
>

h4p changes uart speed again after load of the firmware, but I guess
that's ok.

> > But I don't understand what you want me to do at this point. I guess
> > skb_queue_tail+hci_h4p_outb should be moved to a helper function
> > (that's easy), and I already moved initialization to hci_setup().
> > 
> > nokia_core.c uses test_bit(HCI_RUNNING, &info->hdev->flags) to tell
> > between initialization and data traffic, but I guess that's fine?
> 
> I have no idea on how much more I can explain this. There should be code in 
> the driver that handles the HCI transport. That means init of the transport 
> and sending and receiving HCI frames. And then there is the piece to load the 
> firmware etc. These are two independent things.
>

Ok, it looks like __hci_cmd_sync() is indeed good match for the
firmware load.

> 
> What needs to be done is the bring up of the device including the proper UART 
> settings and speed and then just run the firmware downloads. All firmware 
> files on the Nokia devices where just HCI commands with vendor specific 
> details. Some from CSR, some from Broadcom and some from TI. You can actually 
> decode them if you really want to. Shouldn't be that hard.
>

Speed changes at the end of firmware load, but I guess that's detail?
Anyway, patch would look like this.

diff --git a/drivers/staging/nokia_h4p/nokia_core.c 
b/drivers/staging/nokia_h4p/nokia_core.c
index 9ece2c8..5cdb86a 100644
--- a/drivers/staging/nokia_h4p/nokia_core.c
+++ b/drivers/staging/nokia_h4p/nokia_core.c
@@ -475,12 +475,6 @@ static inline void hci_h4p_recv_frame(struct hci_h4p_info 
*info,
                        info->rx_state = WAIT_FOR_PKT_TYPE;
                        return;
                }
-
-               if (!test_bit(HCI_UP, &info->hdev->flags)) {
-                       BT_DBG("fw_event");
-                       hci_h4p_parse_fw_event(info, skb);
-                       return;
-               }
        }
 
        hci_recv_frame(info->hdev, skb);
diff --git a/drivers/staging/nokia_h4p/nokia_fw-bcm.c 
b/drivers/staging/nokia_h4p/nokia_fw-bcm.c
index 8066b21..89718d4 100644
--- a/drivers/staging/nokia_h4p/nokia_fw-bcm.c
+++ b/drivers/staging/nokia_h4p/nokia_fw-bcm.c
@@ -45,84 +45,17 @@ static int hci_h4p_bcm_set_bdaddr(struct hci_h4p_info *info,
        return 0;
 }
 
-void hci_h4p_bcm_parse_fw_event(struct hci_h4p_info *info, struct sk_buff *skb)
-{
-       struct sk_buff *fw_skb;
-       int err;
-       unsigned long flags;
-
-       if (skb->data[5] != 0x00) {
-               dev_err(info->dev, "Firmware sending command failed 0x%.2x\n",
-                       skb->data[5]);
-               info->fw_error = -EPROTO;
-       }
-
-       kfree_skb(skb);
-
-       fw_skb = skb_dequeue(info->fw_q);
-       if (fw_skb == NULL || info->fw_error) {
-               complete(&info->fw_completion);
-               return;
-       }
-
-       if (fw_skb->data[1] == 0x01 && fw_skb->data[2] == 0xfc &&
-                       fw_skb->len >= 10) {
-               BT_DBG("Setting bluetooth address");
-               err = hci_h4p_bcm_set_bdaddr(info, fw_skb);
-               if (err < 0) {
-                       kfree_skb(fw_skb);
-                       info->fw_error = err;
-                       complete(&info->fw_completion);
-                       return;
-               }
-       }
-
-       hci_h4p_simple_send_frame(info, fw_skb);
-}
-
-
 int hci_h4p_bcm_send_fw(struct hci_h4p_info *info,
                        struct sk_buff_head *fw_queue)
 {
-       struct sk_buff *skb;
-       unsigned long flags, time;
+       unsigned long time;
 
        info->fw_error = 0;
 
-       BT_DBG("Sending firmware");
+       printk("Sending firmware (not really)\n");
 
        time = jiffies;
-
-       info->fw_q = fw_queue;
-       skb = skb_dequeue(fw_queue);
-       if (!skb)
-               return -ENODATA;
-
-       BT_DBG("Sending commands");
-
-       /*
-        * Disable smart-idle as UART TX interrupts
-        * are not wake-up capable
-        */
-       hci_h4p_smart_idle(info, 0);
-
-       /* Check if this is bd_address packet */
-       init_completion(&info->fw_completion);
-
-       hci_h4p_simple_send_frame(info, skb);
-
-       if (!wait_for_completion_timeout(&info->fw_completion,
-                               msecs_to_jiffies(2000))) {
-               dev_err(info->dev, "No reply to fw command\n");
-               return -ETIMEDOUT;
-       }
-
-       if (info->fw_error) {
-               dev_err(info->dev, "FW error\n");
-               return -EPROTO;
-       }
-
-       BT_DBG("Firmware sent in %d msecs",
+       printk("Firmware sent in %d msec\n",
                   jiffies_to_msecs(jiffies-time));
 
        hci_h4p_set_auto_ctsrts(info, 0, UART_EFR_RTS);
diff --git a/drivers/staging/nokia_h4p/nokia_fw.c 
b/drivers/staging/nokia_h4p/nokia_fw.c
index b5748c8..be5f619 100644
--- a/drivers/staging/nokia_h4p/nokia_fw.c
+++ b/drivers/staging/nokia_h4p/nokia_fw.c
@@ -76,6 +72,7 @@ static int hci_h4p_read_fw_cmd(struct hci_h4p_info *info, 
struct sk_buff **skb,
                               const struct firmware *fw_entry, gfp_t how)
 {
        unsigned int cmd_len;
+       static int num = 0;
 
        if (fw_pos >= fw_entry->size)
                return 0;
@@ -95,16 +92,24 @@ static int hci_h4p_read_fw_cmd(struct hci_h4p_info *info, 
struct sk_buff **skb,
                return -EMSGSIZE;
        }
 
-       *skb = bt_skb_alloc(cmd_len, how);
-       if (!*skb) {
-               dev_err(info->dev, "Cannot reserve memory for buffer\n");
-               return -ENOMEM;
+       /* Note that this is timing-critical. If sending packets takes too
+          long, initialization will fail. */
+       printk("Packet %d...", num);
+       if (num > 1) {
+               int cmd = fw_entry->data[fw_pos+1] + (fw_entry->data[fw_pos+2] 
<< 8);
+               int len = fw_entry->data[fw_pos+3];
+               printk("cmd %x, len %d.", cmd, len);
+               *skb = __hci_cmd_sync(info->hdev, cmd, len, 
fw_entry->data+fw_pos+4, 500);
+               if (IS_ERR(*skb)) {
+                       printk("...sending cmd failed %d\n", PTR_ERR(*skb));
+                       return -EIO;
+               }
        }
-       memcpy(skb_put(*skb, cmd_len), &fw_entry->data[fw_pos], cmd_len);
+       num++;
 
        fw_pos += cmd_len;
 
-       return (*skb)->len;
+       return 1;
 }
 
 int hci_h4p_read_fw(struct hci_h4p_info *info, struct sk_buff_head *fw_queue)
@@ -113,31 +118,22 @@ int hci_h4p_read_fw(struct hci_h4p_info *info, struct 
sk_buff_head *fw_queue)
        struct sk_buff *skb = NULL;
        int err;
 
+       /*
+        * Disable smart-idle as UART TX interrupts
+        * are not wake-up capable
+        */
+       hci_h4p_smart_idle(info, 0);
+       
        err = hci_h4p_open_firmware(info, &fw_entry);
        if (err < 0 || !fw_entry)
                goto err_clean;
 
+       printk("read firmware\n");
+       /* FIXME: remove skb... */
        while ((err = hci_h4p_read_fw_cmd(info, &skb, fw_entry, GFP_KERNEL))) {
-               if (err < 0 || !skb)
-                       goto err_clean;
-
-               skb_queue_tail(fw_queue, skb);
        }
 
-       /* Chip detection code does neg and alive stuff
-        * discard two first skbs */
-       skb = skb_dequeue(fw_queue);
-       if (!skb) {
-               err = -EMSGSIZE;
-               goto err_clean;
-       }
-       kfree_skb(skb);
-       skb = skb_dequeue(fw_queue);
-       if (!skb) {
-               err = -EMSGSIZE;
-               goto err_clean;
-       }
-       kfree_skb(skb);
+       printk("done read firmware\n");
 
 err_clean:
        hci_h4p_close_firmware(fw_entry);
@@ -160,20 +156,4 @@ int hci_h4p_send_fw(struct hci_h4p_info *info, struct 
sk_buff_head *fw_queue)
        return err;
 }
 
-void hci_h4p_parse_fw_event(struct hci_h4p_info *info, struct sk_buff *skb)
-{
-       switch (info->man_id) {
-       case H4P_ID_BCM2048:
-               hci_h4p_bcm_parse_fw_event(info, skb);
-               break;
-       default:
-               dev_err(info->dev, "Don't know how to parse fw event\n");
-               info->fw_error = -EINVAL;
-       }
-}
-
-MODULE_FIRMWARE(FW_NAME_TI1271_PRELE);
-MODULE_FIRMWARE(FW_NAME_TI1271_LE);
-MODULE_FIRMWARE(FW_NAME_TI1271);
 MODULE_FIRMWARE(FW_NAME_BCM2048);
-MODULE_FIRMWARE(FW_NAME_CSR);


-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to