CHROMEOS: HID: logitech-dj: Delay creation of enumerated devices until connected.
authorAndrew de los Reyes <adlr@chromium.org>
Sat, 5 Jan 2013 22:06:32 +0000 (14:06 -0800)
committerChromeBot <chrome-bot@google.com>
Fri, 22 Mar 2013 02:09:12 +0000 (19:09 -0700)
This is necessary because it's impossible to communicate with devices
that aren't connected and future patches will need to communicate with
devices during probe().

By waiting until the device is connected, we ensure that we only
register the device when it's active and ready for use.

BUG=chromium-os:39354
TEST=manually tested on Link

Signed-off-by: Andrew de los Reyes <adlr@chromium.org>
Change-Id: Id5f2ae88839d1c39362cf0f9246a39d1f6e6238a
Reviewed-on: https://gerrit.chromium.org/gerrit/46007
Reviewed-by: Yufeng Shen <miletus@chromium.org>
drivers/hid/hid-logitech-dj.c
drivers/hid/hid-logitech-dj.h

index 199b78c..b5f43b0 100644 (file)
@@ -283,17 +283,8 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
 
        djrcv_dev->paired_dj_devices[dj_report->device_index] = dj_dev;
 
-       if (hid_add_device(dj_hiddev)) {
-               dev_err(&djrcv_hdev->dev, "%s: failed adding dj_device\n",
-                       __func__);
-               goto hid_add_device_fail;
-       }
-
        return;
 
-hid_add_device_fail:
-       djrcv_dev->paired_dj_devices[dj_report->device_index] = NULL;
-       kfree(dj_dev);
 dj_device_allocate_fail:
        hid_destroy_device(dj_hiddev);
 }
@@ -302,10 +293,14 @@ static void delayedwork_callback(struct work_struct *work)
 {
        struct dj_receiver_dev *djrcv_dev =
                container_of(work, struct dj_receiver_dev, work);
+       struct hid_device *djrcv_hdev = djrcv_dev->hdev;
 
+       struct dj_device *djdev;
        struct dj_report dj_report;
        unsigned long flags;
        int count;
+       u8 param_status;
+       bool connected;
 
        dbg_hid("%s\n", __func__);
 
@@ -337,6 +332,27 @@ static void delayedwork_callback(struct work_struct *work)
        case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
                logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report);
                break;
+       case REPORT_TYPE_NOTIF_CONNECTION_STATUS:
+               param_status = dj_report.report_params[
+                                       CONNECTION_STATUS_PARAM_STATUS];
+               connected = param_status != STATUS_LINKLOSS;
+               djdev = djrcv_dev->paired_dj_devices[dj_report.device_index];
+               dbg_hid("%s: got REPORT_TYPE_NOTIF_CONNECTION_STATUS %d %d\n", __func__, djdev ? djdev->hid_device_started : -1, connected);
+               if (!djdev) {
+                       dev_err(&djrcv_dev->hdev->dev, "%s:"
+                               "dj_dev null, unexpected device index\n",
+                               __func__);
+                       return;
+               }
+               if (!djdev->hid_device_started && connected) {
+                       if (hid_add_device(djdev->hdev)) {
+                               dev_err(&djrcv_hdev->dev,
+                                       "%s: failed adding dj_device\n",
+                                       __func__);
+                       } else {
+                               djdev->hid_device_started = 1;
+                       }
+               }
        default:
                dbg_hid("%s: unexpected report type\n", __func__);
        }
@@ -668,6 +684,7 @@ static int logi_dj_raw_event(struct hid_device *hdev,
                            STATUS_LINKLOSS) {
                                logi_dj_recv_forward_null_report(djrcv_dev, dj_report);
                        }
+                       logi_dj_recv_queue_notification(djrcv_dev, dj_report);
                        break;
                default:
                        logi_dj_recv_forward_report(djrcv_dev, dj_report);
index fd28a5e..3eb4528 100644 (file)
@@ -108,6 +108,7 @@ struct dj_device {
        struct dj_receiver_dev *dj_receiver_dev;
        u32 reports_supported;
        u8 device_index;
+       unsigned hid_device_started:1;
 };
 
 /**