static int valve_sc_send_request(struct valve_sc_device *sc, u8 report_id, const u8 *params, int params_size, u8 *answer, int *answer_size) { int ret; struct hid_device *hdev = sc->hdev; u8 report[65]; if (params_size > 62) return -EINVAL; report[0] = 0; report[1] = report_id; report[2] = params_size; memcpy(&report[3], params, params_size); ret = hid_hw_raw_request(hdev, 0, report, sizeof(report), HID_FEATURE_REPORT, HID_REQ_SET_REPORT); if (ret < 0) { hid_warn(hdev, "Error sending feature: %d\n", -ret); return ret; } if (ret != sizeof (report)) { hid_warn(hdev, "Sent incomplete feature.\n"); return -EIO; } if (!answer) return 0; msleep(50); ret = hid_hw_raw_request(hdev, 0, report, sizeof(report), HID_FEATURE_REPORT, HID_REQ_GET_REPORT); if (ret < 0) { hid_warn(hdev, "Error receiving feature: %d\n", -ret); return ret; } if (ret != sizeof (report)) { hid_warn(hdev, "Received incomplete feature.\n"); return -EIO; } if (report[1] != report_id) { hid_warn(hdev, "Invalid feature id.\n"); return -EIO; } *answer_size = report[2]; memcpy(answer, &report[3], *answer_size); return 0; }
static void mt_get_feature(struct hid_device *hdev, struct hid_report *report) { struct mt_device *td = hid_get_drvdata(hdev); int ret, size = hid_report_len(report); u8 *buf; /* * Do not fetch the feature report if the device has been explicitly * marked as non-capable. */ if (td->initial_quirks & HID_QUIRK_NO_INIT_REPORTS) return; buf = hid_alloc_report_buf(report, GFP_KERNEL); if (!buf) return; ret = hid_hw_raw_request(hdev, report->id, buf, size, HID_FEATURE_REPORT, HID_REQ_GET_REPORT); if (ret < 0) { dev_warn(&hdev->dev, "failed to fetch feature %d\n", report->id); } else { ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf, size, 0); if (ret) dev_warn(&hdev->dev, "failed to report feature\n"); } kfree(buf); }
static int logi_dj_ll_raw_request(struct hid_device *hid, unsigned char reportnum, __u8 *buf, size_t count, unsigned char report_type, int reqtype) { struct dj_device *djdev = hid->driver_data; struct dj_receiver_dev *djrcv_dev = djdev->dj_receiver_dev; u8 *out_buf; int ret; if (buf[0] != REPORT_TYPE_LEDS) return -EINVAL; out_buf = kzalloc(DJREPORT_SHORT_LENGTH, GFP_ATOMIC); if (!out_buf) return -ENOMEM; if (count > DJREPORT_SHORT_LENGTH - 2) count = DJREPORT_SHORT_LENGTH - 2; out_buf[0] = REPORT_ID_DJ_SHORT; out_buf[1] = djdev->device_index; memcpy(out_buf + 2, buf, count); ret = hid_hw_raw_request(djrcv_dev->hdev, out_buf[0], out_buf, DJREPORT_SHORT_LENGTH, report_type, reqtype); kfree(out_buf); return ret; }
/* Send a config command to the keyboard */ static int lenovo_send_cmd_cptkbd(struct hid_device *hdev, unsigned char byte2, unsigned char byte3) { int ret; unsigned char *buf; buf = kzalloc(3, GFP_KERNEL); if (!buf) return -ENOMEM; buf[0] = 0x18; buf[1] = byte2; buf[2] = byte3; switch (hdev->product) { case USB_DEVICE_ID_LENOVO_CUSBKBD: ret = hid_hw_raw_request(hdev, 0x13, buf, 3, HID_FEATURE_REPORT, HID_REQ_SET_REPORT); break; case USB_DEVICE_ID_LENOVO_CBTKBD: ret = hid_hw_output_report(hdev, buf, 3); break; default: ret = -EINVAL; break; } kfree(buf); return ret < 0 ? ret : 0; /* BT returns 0, USB returns sizeof(buf) */ }
static void mt_get_feature(struct hid_device *hdev, struct hid_report *report) { struct mt_device *td = hid_get_drvdata(hdev); int ret, size = hid_report_len(report); u8 *buf; /* * Only fetch the feature report if initial reports are not already * been retrieved. Currently this is only done for Windows 8 touch * devices. */ if (!(hdev->quirks & HID_QUIRK_NO_INIT_REPORTS)) return; if (td->mtclass.name != MT_CLS_WIN_8) return; buf = hid_alloc_report_buf(report, GFP_KERNEL); if (!buf) return; ret = hid_hw_raw_request(hdev, report->id, buf, size, HID_FEATURE_REPORT, HID_REQ_GET_REPORT); if (ret < 0) { dev_warn(&hdev->dev, "failed to fetch feature %d\n", report->id); } else { ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf, size, 0); if (ret) dev_warn(&hdev->dev, "failed to report feature\n"); } kfree(buf); }
/* Send a config command to the keyboard */ static int lenovo_send_cmd_cptkbd(struct hid_device *hdev, unsigned char byte2, unsigned char byte3) { int ret; unsigned char buf[] = {0x18, byte2, byte3}; switch (hdev->product) { case USB_DEVICE_ID_LENOVO_CUSBKBD: ret = hid_hw_raw_request(hdev, 0x13, buf, sizeof(buf), HID_FEATURE_REPORT, HID_REQ_SET_REPORT); break; case USB_DEVICE_ID_LENOVO_CBTKBD: ret = hid_hw_output_report(hdev, buf, sizeof(buf)); break; default: ret = -EINVAL; break; } return ret < 0 ? ret : 0; /* BT returns 0, USB returns sizeof(buf) */ }
static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) { struct usb_interface *iface = to_usb_interface(hdev->dev.parent); __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber; unsigned int connect_mask = HID_CONNECT_DEFAULT; struct lg_drv_data *drv_data; int ret; /* G29 only work with the 1st interface */ if ((hdev->product == USB_DEVICE_ID_LOGITECH_G29_WHEEL) && (iface_num != 0)) { dbg_hid("%s: ignoring ifnum %d\n", __func__, iface_num); return -ENODEV; } drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL); if (!drv_data) { hid_err(hdev, "Insufficient memory, cannot allocate driver data\n"); return -ENOMEM; } drv_data->quirks = id->driver_data; hid_set_drvdata(hdev, (void *)drv_data); if (drv_data->quirks & LG_NOGET) hdev->quirks |= HID_QUIRK_NOGET; ret = hid_parse(hdev); if (ret) { hid_err(hdev, "parse failed\n"); goto err_free; } if (drv_data->quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4)) connect_mask &= ~HID_CONNECT_FF; ret = hid_hw_start(hdev, connect_mask); if (ret) { hid_err(hdev, "hw start failed\n"); goto err_free; } /* Setup wireless link with Logitech Wii wheel */ if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) { unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf), HID_FEATURE_REPORT, HID_REQ_SET_REPORT); if (ret >= 0) { /* insert a little delay of 10 jiffies ~ 40ms */ wait_queue_head_t wait; init_waitqueue_head (&wait); wait_event_interruptible_timeout(wait, 0, msecs_to_jiffies(40)); /* Select random Address */ buf[1] = 0xB2; get_random_bytes(&buf[2], 2); ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf), HID_FEATURE_REPORT, HID_REQ_SET_REPORT); } } if (drv_data->quirks & LG_FF) ret = lgff_init(hdev); else if (drv_data->quirks & LG_FF2) ret = lg2ff_init(hdev); else if (drv_data->quirks & LG_FF3) ret = lg3ff_init(hdev); else if (drv_data->quirks & LG_FF4) ret = lg4ff_init(hdev); if (ret) goto err_free; return 0; err_free: kfree(drv_data); return ret; }
static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) { unsigned int connect_mask = HID_CONNECT_DEFAULT; struct lg_drv_data *drv_data; int ret; drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL); if (!drv_data) { hid_err(hdev, "Insufficient memory, cannot allocate driver data\n"); return -ENOMEM; } drv_data->quirks = id->driver_data; hid_set_drvdata(hdev, (void *)drv_data); if (drv_data->quirks & LG_NOGET) hdev->quirks |= HID_QUIRK_NOGET; ret = hid_parse(hdev); if (ret) { hid_err(hdev, "parse failed\n"); goto err_free; } if (drv_data->quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4)) connect_mask &= ~HID_CONNECT_FF; ret = hid_hw_start(hdev, connect_mask); if (ret) { hid_err(hdev, "hw start failed\n"); goto err_free; } /* Setup wireless link with Logitech Wii wheel */ if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) { unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf), HID_FEATURE_REPORT, HID_REQ_SET_REPORT); if (ret >= 0) { /* insert a little delay of 10 jiffies ~ 40ms */ wait_queue_head_t wait; init_waitqueue_head (&wait); wait_event_interruptible_timeout(wait, 0, 10); /* Select random Address */ buf[1] = 0xB2; get_random_bytes(&buf[2], 2); ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf), HID_FEATURE_REPORT, HID_REQ_SET_REPORT); } } if (drv_data->quirks & LG_FF) lgff_init(hdev); if (drv_data->quirks & LG_FF2) lg2ff_init(hdev); if (drv_data->quirks & LG_FF3) lg3ff_init(hdev); if (drv_data->quirks & LG_FF4) lg4ff_init(hdev); return 0; err_free: kfree(drv_data); return ret; }