Merge branch 'for-3.15/ll-driver-new-callbacks' into for-linus
authorJiri Kosina <jkosina@suse.cz>
Tue, 1 Apr 2014 16:56:24 +0000 (18:56 +0200)
committerJiri Kosina <jkosina@suse.cz>
Tue, 1 Apr 2014 16:56:24 +0000 (18:56 +0200)
1  2 
net/bluetooth/hidp/core.c

index d9fb9345144238f61372fdb21ca57c08b9471efd,b062cee3f319728ef3422e9eedcce22e1cbe3615..450a0b999614f980f3440f607b4f0af018c3e0a1
@@@ -353,6 -353,71 +353,71 @@@ err
        return ret;
  }
  
+ static int hidp_set_raw_report(struct hid_device *hid, unsigned char reportnum,
+                              unsigned char *data, size_t count,
+                              unsigned char report_type)
+ {
+       struct hidp_session *session = hid->driver_data;
+       int ret;
+       switch (report_type) {
+       case HID_FEATURE_REPORT:
+               report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
+               break;
+       case HID_INPUT_REPORT:
+               report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_INPUT;
+               break;
+       case HID_OUTPUT_REPORT:
+               report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT;
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (mutex_lock_interruptible(&session->report_mutex))
+               return -ERESTARTSYS;
+       /* Set up our wait, and send the report request to the device. */
+       data[0] = reportnum;
+       set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
+       ret = hidp_send_ctrl_message(session, report_type, data, count);
+       if (ret)
+               goto err;
+       /* Wait for the ACK from the device. */
+       while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags) &&
+              !atomic_read(&session->terminate)) {
+               int res;
+               res = wait_event_interruptible_timeout(session->report_queue,
+                       !test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)
+                               || atomic_read(&session->terminate),
+                       10*HZ);
+               if (res == 0) {
+                       /* timeout */
+                       ret = -EIO;
+                       goto err;
+               }
+               if (res < 0) {
+                       /* signal */
+                       ret = -ERESTARTSYS;
+                       goto err;
+               }
+       }
+       if (!session->output_report_success) {
+               ret = -EIO;
+               goto err;
+       }
+       ret = count;
+ err:
+       clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
+       mutex_unlock(&session->report_mutex);
+       return ret;
+ }
  static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
                unsigned char report_type)
  {
@@@ -411,6 -476,29 +476,29 @@@ err
        return ret;
  }
  
+ static int hidp_raw_request(struct hid_device *hid, unsigned char reportnum,
+                           __u8 *buf, size_t len, unsigned char rtype,
+                           int reqtype)
+ {
+       switch (reqtype) {
+       case HID_REQ_GET_REPORT:
+               return hidp_get_raw_report(hid, reportnum, buf, len, rtype);
+       case HID_REQ_SET_REPORT:
+               return hidp_set_raw_report(hid, reportnum, buf, len, rtype);
+       default:
+               return -EIO;
+       }
+ }
+ static int hidp_output_report(struct hid_device *hid, __u8 *data, size_t count)
+ {
+       struct hidp_session *session = hid->driver_data;
+       return hidp_send_intr_message(session,
+                                     HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT,
+                                     data, count);
+ }
  static void hidp_idle_timeout(unsigned long arg)
  {
        struct hidp_session *session = (struct hidp_session *) arg;
@@@ -430,16 -518,6 +518,16 @@@ static void hidp_del_timer(struct hidp_
                del_timer(&session->timer);
  }
  
 +static void hidp_process_report(struct hidp_session *session,
 +                              int type, const u8 *data, int len, int intr)
 +{
 +      if (len > HID_MAX_BUFFER_SIZE)
 +              len = HID_MAX_BUFFER_SIZE;
 +
 +      memcpy(session->input_buf, data, len);
 +      hid_input_report(session->hid, type, session->input_buf, len, intr);
 +}
 +
  static void hidp_process_handshake(struct hidp_session *session,
                                        unsigned char param)
  {
@@@ -512,8 -590,7 +600,8 @@@ static int hidp_process_data(struct hid
                        hidp_input_report(session, skb);
  
                if (session->hid)
 -                      hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
 +                      hidp_process_report(session, HID_INPUT_REPORT,
 +                                          skb->data, skb->len, 0);
                break;
  
        case HIDP_DATA_RTYPE_OTHER:
@@@ -595,8 -672,7 +683,8 @@@ static void hidp_recv_intr_frame(struc
                        hidp_input_report(session, skb);
  
                if (session->hid) {
 -                      hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
 +                      hidp_process_report(session, HID_INPUT_REPORT,
 +                                          skb->data, skb->len, 1);
                        BT_DBG("report len %d", skb->len);
                }
        } else {
@@@ -739,6 -815,8 +827,8 @@@ static struct hid_ll_driver hidp_hid_dr
        .stop = hidp_stop,
        .open  = hidp_open,
        .close = hidp_close,
+       .raw_request = hidp_raw_request,
+       .output_report = hidp_output_report,
        .hidinput_input_event = hidp_hidinput_event,
  };