static int logi_dj_ll_input_event(struct input_dev *dev, unsigned int type,
				  unsigned int code, int value)
{
	/* Sent by the input layer to handle leds and Force Feedback */
	struct hid_device *dj_hiddev = input_get_drvdata(dev);
	struct dj_device *dj_dev = dj_hiddev->driver_data;

	struct dj_receiver_dev *djrcv_dev =
	    dev_get_drvdata(dj_hiddev->dev.parent);
	struct hid_device *dj_rcv_hiddev = djrcv_dev->hdev;
	struct hid_report_enum *output_report_enum;

	struct hid_field *field;
	struct hid_report *report;
	unsigned char *data;
	int offset;

	dbg_hid("%s: %s, type:%d | code:%d | value:%d\n",
		__func__, dev->phys, type, code, value);

	if (type != EV_LED)
		return -1;

	offset = hidinput_find_field(dj_hiddev, type, code, &field);

	if (offset == -1) {
		dev_warn(&dev->dev, "event field not found\n");
		return -1;
	}
	hid_set_field(field, offset, value);

	data = hid_alloc_report_buf(field->report, GFP_KERNEL);
	if (!data) {
		dev_warn(&dev->dev, "failed to allocate report buf memory\n");
		return -1;
	}

	hid_output_report(field->report, &data[0]);

	output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT];
	report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];
	hid_set_field(report->field[0], 0, dj_dev->device_index);
	hid_set_field(report->field[0], 1, REPORT_TYPE_LEDS);
	hid_set_field(report->field[0], 2, data[1]);

	hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT);

	kfree(data);

	return 0;
}
예제 #2
0
파일: hid-g19.c 프로젝트: guillaumecl/lg4l
static void send_finalize_report(struct gcore_data *gdata)
{
	struct g19_data *g19data = gdata->data;
	struct hid_device *hdev = gdata->hdev;
	unsigned long irq_flags;

	/*
	 * Send the finalize report, then follow with the input report to
	 * trigger report 6 and wait for us to get a response.
	 */
	g19_feature_report_4_send(hdev, G19_REPORT_4_FINALIZE);
	hid_hw_request(hdev, g19data->start_input_report, HID_REQ_GET_REPORT);
	hid_hw_request(hdev, g19data->start_input_report, HID_REQ_GET_REPORT);
	wait_for_completion_timeout(&g19data->ready, HZ);

	/* Protect data->ready_stages */
	spin_lock_irqsave(&gdata->lock, irq_flags);

	if (g19data->ready_stages != G19_READY_STAGE_3) {
		dev_warn(&hdev->dev,
			 "%s hasn't completed stage 3 yet, forging ahead with initialization\n",
			 gdata->name);
		/* Force the stage */
		g19data->ready_stages = G19_READY_STAGE_3;
	} else {
		dbg_hid("%s stage 3 complete\n", gdata->name);
	}

	spin_unlock_irqrestore(&gdata->lock, irq_flags);
}
예제 #3
0
/* Send a given tile to PicoLCD */
static int picolcd_fb_send_tile(struct picolcd_data *data, u8 *vbitmap,
		int chip, int tile)
{
	struct hid_report *report1, *report2;
	unsigned long flags;
	u8 *tdata;
	int i;

	report1 = picolcd_out_report(REPORT_LCD_CMD_DATA, data->hdev);
	if (!report1 || report1->maxfield != 1)
		return -ENODEV;
	report2 = picolcd_out_report(REPORT_LCD_DATA, data->hdev);
	if (!report2 || report2->maxfield != 1)
		return -ENODEV;

	spin_lock_irqsave(&data->lock, flags);
	if ((data->status & PICOLCD_FAILED)) {
		spin_unlock_irqrestore(&data->lock, flags);
		return -ENODEV;
	}
	hid_set_field(report1->field[0],  0, chip << 2);
	hid_set_field(report1->field[0],  1, 0x02);
	hid_set_field(report1->field[0],  2, 0x00);
	hid_set_field(report1->field[0],  3, 0x00);
	hid_set_field(report1->field[0],  4, 0xb8 | tile);
	hid_set_field(report1->field[0],  5, 0x00);
	hid_set_field(report1->field[0],  6, 0x00);
	hid_set_field(report1->field[0],  7, 0x40);
	hid_set_field(report1->field[0],  8, 0x00);
	hid_set_field(report1->field[0],  9, 0x00);
	hid_set_field(report1->field[0], 10,   32);

	hid_set_field(report2->field[0],  0, (chip << 2) | 0x01);
	hid_set_field(report2->field[0],  1, 0x00);
	hid_set_field(report2->field[0],  2, 0x00);
	hid_set_field(report2->field[0],  3,   32);

	tdata = vbitmap + (tile * 4 + chip) * 64;
	for (i = 0; i < 64; i++)
		if (i < 32)
			hid_set_field(report1->field[0], 11 + i, tdata[i]);
		else
			hid_set_field(report2->field[0], 4 + i - 32, tdata[i]);

	hid_hw_request(data->hdev, report1, HID_REQ_SET_REPORT);
	hid_hw_request(data->hdev, report2, HID_REQ_SET_REPORT);
	spin_unlock_irqrestore(&data->lock, flags);
	return 0;
}
예제 #4
0
static void g19_feature_report_4_send(struct hid_device *hdev, int which)
{
	struct g19_data *g19data = hid_get_g19data(hdev);

	if (which == G19_REPORT_4_INIT) {
		g19data->feature_report_4->field[0]->value[0] = 0x02;
		g19data->feature_report_4->field[0]->value[1] = 0x00;
		g19data->feature_report_4->field[0]->value[2] = 0x00;
		g19data->feature_report_4->field[0]->value[3] = 0x00;
	} else if (which == G19_REPORT_4_FINALIZE) {
		g19data->feature_report_4->field[0]->value[0] = 0x02;
		g19data->feature_report_4->field[0]->value[1] = 0x80;
		g19data->feature_report_4->field[0]->value[2] = 0x00;
		g19data->feature_report_4->field[0]->value[3] = 0xFF;
	} else {
		return;
	}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)

	hid_hw_request(hdev, g19data->feature_report_4, HID_REQ_SET_REPORT);

#else

	usbhid_submit_report(hdev, g19data->feature_report_4, USB_DIR_OUT);

#endif
}
예제 #5
0
파일: hid-zpff.c 프로젝트: 212006949/linux
static int zpff_play(struct input_dev *dev, void *data,
			 struct ff_effect *effect)
{
	struct hid_device *hid = input_get_drvdata(dev);
	struct zpff_device *zpff = data;
	int left, right;

	/*
	 * The following is specified the other way around in the Zeroplus
	 * datasheet but the order below is correct for the XFX Executioner;
	 * however it is possible that the XFX Executioner is an exception
	 */

	left = effect->u.rumble.strong_magnitude;
	right = effect->u.rumble.weak_magnitude;
	dbg_hid("called with 0x%04x 0x%04x\n", left, right);

	left = left * 0x7f / 0xffff;
	right = right * 0x7f / 0xffff;

	zpff->report->field[2]->value[0] = left;
	zpff->report->field[3]->value[0] = right;
	dbg_hid("running with 0x%02x 0x%02x\n", left, right);
	hid_hw_request(hid, zpff->report, HID_REQ_SET_REPORT);

	return 0;
}
예제 #6
0
static ssize_t picolcd_operation_mode_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{
	struct picolcd_data *data = dev_get_drvdata(dev);
	struct hid_report *report = NULL;
	size_t cnt = count;
	int timeout = data->opmode_delay;
	unsigned long flags;

	if (cnt >= 3 && strncmp("lcd", buf, 3) == 0) {
		if (data->status & PICOLCD_BOOTLOADER)
			report = picolcd_out_report(REPORT_EXIT_FLASHER, data->hdev);
		buf += 3;
		cnt -= 3;
	} else if (cnt >= 10 && strncmp("bootloader", buf, 10) == 0) {
		if (!(data->status & PICOLCD_BOOTLOADER))
			report = picolcd_out_report(REPORT_EXIT_KEYBOARD, data->hdev);
		buf += 10;
		cnt -= 10;
	}
	if (!report)
		return -EINVAL;

	while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r'))
		cnt--;
	if (cnt != 0)
		return -EINVAL;

	spin_lock_irqsave(&data->lock, flags);
	hid_set_field(report->field[0], 0, timeout & 0xff);
	hid_set_field(report->field[0], 1, (timeout >> 8) & 0xff);
	hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
	spin_unlock_irqrestore(&data->lock, flags);
	return count;
}
예제 #7
0
/*
 * Reset our device and wait for answer to VERSION request
 */
int picolcd_reset(struct hid_device *hdev)
{
	struct picolcd_data *data = hid_get_drvdata(hdev);
	struct hid_report *report = picolcd_out_report(REPORT_RESET, hdev);
	unsigned long flags;
	int error;

	if (!data || !report || report->maxfield != 1)
		return -ENODEV;

	spin_lock_irqsave(&data->lock, flags);
	if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER)
		data->status |= PICOLCD_BOOTLOADER;

	/* perform the reset */
	hid_set_field(report->field[0], 0, 1);
	if (data->status & PICOLCD_FAILED) {
		spin_unlock_irqrestore(&data->lock, flags);
		return -ENODEV;
	}
	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
	spin_unlock_irqrestore(&data->lock, flags);

	error = picolcd_check_version(hdev);
	if (error)
		return error;

	picolcd_resume_lcd(data);
	picolcd_resume_backlight(data);
	picolcd_fb_refresh(data);
	picolcd_leds_set(data);
	return 0;
}
예제 #8
0
파일: hid-lg2ff.c 프로젝트: 020gzh/linux
static int play_effect(struct input_dev *dev, void *data,
			 struct ff_effect *effect)
{
	struct hid_device *hid = input_get_drvdata(dev);
	struct lg2ff_device *lg2ff = data;
	int weak, strong;

	strong = effect->u.rumble.strong_magnitude;
	weak = effect->u.rumble.weak_magnitude;

	if (weak || strong) {
		weak = weak * 0xff / 0xffff;
		strong = strong * 0xff / 0xffff;

		lg2ff->report->field[0]->value[0] = 0x51;
		lg2ff->report->field[0]->value[2] = weak;
		lg2ff->report->field[0]->value[4] = strong;
	} else {
		lg2ff->report->field[0]->value[0] = 0xf3;
		lg2ff->report->field[0]->value[2] = 0x00;
		lg2ff->report->field[0]->value[4] = 0x00;
	}

	hid_hw_request(hid, lg2ff->report, HID_REQ_SET_REPORT);
	return 0;
}
예제 #9
0
파일: hid-g19.c 프로젝트: guillaumecl/lg4l
static void g19_led_mbtns_send(struct hid_device *hdev)
{
	struct g19_data *g19data = hid_get_g19data(hdev);

	g19data->led_report->field[0]->value[0] = g19data->led_mbtns & 0xFF;

	hid_hw_request(hdev, g19data->led_report, HID_REQ_SET_REPORT);
}
예제 #10
0
파일: hid-g510.c 프로젝트: CMoH/lg4l
static void g510_led_send(struct hid_device *hdev, u8 msg, u8 value1, u8 value2)
{
	struct g510_data *g510data = hid_get_g510data(hdev);

	g510data->led_report->field[0]->value[0] = msg;
	g510data->led_report->field[0]->value[1] = value1;
	g510data->led_report->field[0]->value[2] = value2;

	hid_hw_request(hdev, g510data->led_report, HID_REQ_SET_REPORT);
}
예제 #11
0
static int drff_play(struct input_dev *dev, void *data,
				 struct ff_effect *effect)
{
	struct hid_device *hid = input_get_drvdata(dev);
	struct drff_device *drff = data;
	int strong, weak;

	strong = effect->u.rumble.strong_magnitude;
	weak = effect->u.rumble.weak_magnitude;

	dbg_hid("called with 0x%04x 0x%04x", strong, weak);

	if (strong || weak) {
		strong = strong * 0xff / 0xffff;
		weak = weak * 0xff / 0xffff;

		/* While reverse engineering this device, I found that when
		   this value is set, it causes the strong rumble to function
		   at a near maximum speed, so we'll bypass it. */
		if (weak == 0x0a)
			weak = 0x0b;

		drff->report->field[0]->value[0] = 0x51;
		drff->report->field[0]->value[1] = 0x00;
		drff->report->field[0]->value[2] = weak;
		drff->report->field[0]->value[4] = strong;
		hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT);

		drff->report->field[0]->value[0] = 0xfa;
		drff->report->field[0]->value[1] = 0xfe;
	} else {
		drff->report->field[0]->value[0] = 0xf3;
		drff->report->field[0]->value[1] = 0x00;
	}

	drff->report->field[0]->value[2] = 0x00;
	drff->report->field[0]->value[4] = 0x00;
	dbg_hid("running with 0x%02x 0x%02x", strong, weak);
	hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT);

	return 0;
}
예제 #12
0
static int drff_init(struct hid_device *hid)
{
	struct drff_device *drff;
	struct hid_report *report;
	struct hid_input *hidinput = list_first_entry(&hid->inputs,
						struct hid_input, list);
	struct list_head *report_list =
			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
	struct input_dev *dev = hidinput->input;
	int error;

	if (list_empty(report_list)) {
		hid_err(hid, "no output reports found\n");
		return -ENODEV;
	}

	report = list_first_entry(report_list, struct hid_report, list);
	if (report->maxfield < 1) {
		hid_err(hid, "no fields in the report\n");
		return -ENODEV;
	}

	if (report->field[0]->report_count < 7) {
		hid_err(hid, "not enough values in the field\n");
		return -ENODEV;
	}

	drff = kzalloc(sizeof(struct drff_device), GFP_KERNEL);
	if (!drff)
		return -ENOMEM;

	set_bit(FF_RUMBLE, dev->ffbit);

	error = input_ff_create_memless(dev, drff, drff_play);
	if (error) {
		kfree(drff);
		return error;
	}

	drff->report = report;
	drff->report->field[0]->value[0] = 0xf3;
	drff->report->field[0]->value[1] = 0x00;
	drff->report->field[0]->value[2] = 0x00;
	drff->report->field[0]->value[3] = 0x00;
	drff->report->field[0]->value[4] = 0x00;
	drff->report->field[0]->value[5] = 0x00;
	drff->report->field[0]->value[6] = 0x00;
	hid_hw_request(hid, drff->report, HID_REQ_SET_REPORT);

	hid_info(hid, "Force Feedback for DragonRise Inc. "
		 "game controllers by Richard Walmsley <*****@*****.**>\n");

	return 0;
}
예제 #13
0
파일: hid-g19.c 프로젝트: guillaumecl/lg4l
static void g19_led_bl_send(struct hid_device *hdev)
{
	struct g19_data *g19data = hid_get_g19data(hdev);

	struct hid_field *field0 = g19data->backlight_report->field[0];

	field0->value[0] = g19data->backlight_rgb[0];
	field0->value[1] = g19data->backlight_rgb[1];
	field0->value[2] = g19data->backlight_rgb[2];

	hid_hw_request(hdev, g19data->backlight_report, HID_REQ_SET_REPORT);
}
예제 #14
0
파일: hid-emsff.c 프로젝트: ChineseDr/linux
static int emsff_init(struct hid_device *hid)
{
    struct emsff_device *emsff;
    struct hid_report *report;
    struct hid_input *hidinput = list_first_entry(&hid->inputs,
                                 struct hid_input, list);
    struct list_head *report_list =
            &hid->report_enum[HID_OUTPUT_REPORT].report_list;
    struct input_dev *dev = hidinput->input;
    int error;

    if (list_empty(report_list)) {
        hid_err(hid, "no output reports found\n");
        return -ENODEV;
    }

    report = list_first_entry(report_list, struct hid_report, list);
    if (report->maxfield < 1) {
        hid_err(hid, "no fields in the report\n");
        return -ENODEV;
    }

    if (report->field[0]->report_count < 7) {
        hid_err(hid, "not enough values in the field\n");
        return -ENODEV;
    }

    emsff = kzalloc(sizeof(struct emsff_device), GFP_KERNEL);
    if (!emsff)
        return -ENOMEM;

    set_bit(FF_RUMBLE, dev->ffbit);

    error = input_ff_create_memless(dev, emsff, emsff_play);
    if (error) {
        kfree(emsff);
        return error;
    }

    emsff->report = report;
    emsff->report->field[0]->value[0] = 0x01;
    emsff->report->field[0]->value[1] = 0x00;
    emsff->report->field[0]->value[2] = 0x00;
    emsff->report->field[0]->value[3] = 0x00;
    emsff->report->field[0]->value[4] = 0x00;
    emsff->report->field[0]->value[5] = 0x00;
    emsff->report->field[0]->value[6] = 0x00;
    hid_hw_request(hid, emsff->report, HID_REQ_SET_REPORT);

    hid_info(hid, "force feedback for EMS based devices by Ignaz Forster <*****@*****.**>\n");

    return 0;
}
예제 #15
0
파일: hid-tmff.c 프로젝트: 020gzh/linux
static int tmff_play(struct input_dev *dev, void *data,
		struct ff_effect *effect)
{
	struct hid_device *hid = input_get_drvdata(dev);
	struct tmff_device *tmff = data;
	struct hid_field *ff_field = tmff->ff_field;
	int x, y;
	int left, right;	/* Rumbling */

	switch (effect->type) {
	case FF_CONSTANT:
		x = tmff_scale_s8(effect->u.ramp.start_level,
					ff_field->logical_minimum,
					ff_field->logical_maximum);
		y = tmff_scale_s8(effect->u.ramp.end_level,
					ff_field->logical_minimum,
					ff_field->logical_maximum);

		dbg_hid("(x, y)=(%04x, %04x)\n", x, y);
		ff_field->value[0] = x;
		ff_field->value[1] = y;
		hid_hw_request(hid, tmff->report, HID_REQ_SET_REPORT);
		break;

	case FF_RUMBLE:
		left = tmff_scale_u16(effect->u.rumble.weak_magnitude,
					ff_field->logical_minimum,
					ff_field->logical_maximum);
		right = tmff_scale_u16(effect->u.rumble.strong_magnitude,
					ff_field->logical_minimum,
					ff_field->logical_maximum);

		dbg_hid("(left,right)=(%08x, %08x)\n", left, right);
		ff_field->value[0] = left;
		ff_field->value[1] = right;
		hid_hw_request(hid, tmff->report, HID_REQ_SET_REPORT);
		break;
	}
	return 0;
}
예제 #16
0
static void g19_led_send(struct hid_device *hdev)
{
	struct g19_data *g19data = hid_get_g19data(hdev);

	g19data->led_report->field[0]->value[0] = g19data->led&0xFF;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)

	hid_hw_request(hdev, g19data->led_report, HID_REQ_SET_REPORT);

#else

	usbhid_submit_report(hdev, g19data->led_report, USB_DIR_OUT);

#endif
}
예제 #17
0
static int picolcd_set_contrast(struct lcd_device *ldev, int contrast)
{
	struct picolcd_data *data = lcd_get_data(ldev);
	struct hid_report *report = picolcd_out_report(REPORT_CONTRAST, data->hdev);
	unsigned long flags;

	if (!report || report->maxfield != 1 || report->field[0]->report_count != 1)
		return -ENODEV;

	data->lcd_contrast = contrast & 0x0ff;
	spin_lock_irqsave(&data->lock, flags);
	hid_set_field(report->field[0], 0, data->lcd_contrast);
	if (!(data->status & PICOLCD_FAILED))
		hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
	spin_unlock_irqrestore(&data->lock, flags);
	return 0;
}
예제 #18
0
파일: hid-zpff.c 프로젝트: 212006949/linux
static int zpff_init(struct hid_device *hid)
{
	struct zpff_device *zpff;
	struct hid_report *report;
	struct hid_input *hidinput = list_entry(hid->inputs.next,
						struct hid_input, list);
	struct list_head *report_list =
			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
	struct input_dev *dev = hidinput->input;
	int error;

	if (list_empty(report_list)) {
		hid_err(hid, "no output report found\n");
		return -ENODEV;
	}

	report = list_entry(report_list->next, struct hid_report, list);

	if (report->maxfield < 4) {
		hid_err(hid, "not enough fields in report\n");
		return -ENODEV;
	}

	zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL);
	if (!zpff)
		return -ENOMEM;

	set_bit(FF_RUMBLE, dev->ffbit);

	error = input_ff_create_memless(dev, zpff, zpff_play);
	if (error) {
		kfree(zpff);
		return error;
	}

	zpff->report = report;
	zpff->report->field[0]->value[0] = 0x00;
	zpff->report->field[1]->value[0] = 0x02;
	zpff->report->field[2]->value[0] = 0x00;
	zpff->report->field[3]->value[0] = 0x00;
	hid_hw_request(hid, zpff->report, HID_REQ_SET_REPORT);

	hid_info(hid, "force feedback for Zeroplus based devices by Anssi Hannula <*****@*****.**>\n");

	return 0;
}
예제 #19
0
static void buzz_set_leds(struct hid_device *hdev, int leds)
{
    struct list_head *report_list =
            &hdev->report_enum[HID_OUTPUT_REPORT].report_list;
    struct hid_report *report = list_entry(report_list->next,
                                           struct hid_report, list);
    __s32 *value = report->field[0]->value;

    value[0] = 0x00;
    value[1] = (leds & 1) ? 0xff : 0x00;
    value[2] = (leds & 2) ? 0xff : 0x00;
    value[3] = (leds & 4) ? 0xff : 0x00;
    value[4] = (leds & 8) ? 0xff : 0x00;
    value[5] = 0x00;
    value[6] = 0x00;
    hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
}
예제 #20
0
파일: hid-g19.c 프로젝트: guillaumecl/lg4l
static void wait_ready(struct gcore_data *gdata)
{
	struct g19_data *g19data = gdata->data;
	struct hid_device *hdev = gdata->hdev;
	unsigned long irq_flags;

	dbg_hid("Waiting for G19 to activate\n");

	/* Wait here for stage 1 (substages 1-3) to complete */
	wait_for_completion_timeout(&g19data->ready, HZ);

	/* Protect data->ready_stages */
	spin_lock_irqsave(&gdata->lock, irq_flags);
	if (g19data->ready_stages != G19_READY_STAGE_1) {
		dev_warn(&hdev->dev,
			 "%s hasn't completed stage 1 yet, forging ahead with initialization\n",
			 gdata->name);
		/* Force the stage */
		g19data->ready_stages = G19_READY_STAGE_1;
	}
	init_completion(&g19data->ready);
	g19data->ready_stages |= G19_READY_SUBSTAGE_4;
	spin_unlock_irqrestore(&gdata->lock, irq_flags);

	/*
	 * Send the init report, then follow with the input report to trigger
	 * report 6 and wait for us to get a response.
	 */
	g19_feature_report_4_send(hdev, G19_REPORT_4_INIT);
	hid_hw_request(hdev, g19data->start_input_report, HID_REQ_GET_REPORT);
	wait_for_completion_timeout(&g19data->ready, HZ);

	/* Protect g19data->ready_stages */
	spin_lock_irqsave(&gdata->lock, irq_flags);
	if (g19data->ready_stages != G19_READY_STAGE_2) {
		dev_warn(&hdev->dev,
			 "%s hasn't completed stage 2 yet, forging ahead with initialization\n",
			 gdata->name);
		/* Force the stage */
		g19data->ready_stages = G19_READY_STAGE_2;
	}
	init_completion(&g19data->ready);
	g19data->ready_stages |= G19_READY_SUBSTAGE_6;
	spin_unlock_irqrestore(&gdata->lock, irq_flags);
}
static int picolcd_set_brightness(struct backlight_device *bdev)
{
	struct picolcd_data *data = bl_get_data(bdev);
	struct hid_report *report = picolcd_out_report(REPORT_BRIGHTNESS, data->hdev);
	unsigned long flags;

	if (!report || report->maxfield != 1 || report->field[0]->report_count != 1)
		return -ENODEV;

	data->lcd_brightness = bdev->props.brightness & 0x0ff;
	data->lcd_power      = bdev->props.power;
	spin_lock_irqsave(&data->lock, flags);
	hid_set_field(report->field[0], 0, data->lcd_power == FB_BLANK_UNBLANK ? data->lcd_brightness : 0);
	if (!(data->status & PICOLCD_FAILED))
		hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
	spin_unlock_irqrestore(&data->lock, flags);
	return 0;
}
예제 #22
0
파일: hid-lenovo.c 프로젝트: 3null/linux
static int lenovo_features_set_tpkbd(struct hid_device *hdev)
{
	struct hid_report *report;
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);

	report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4];

	report->field[0]->value[0]  = data_pointer->press_to_select   ? 0x01 : 0x02;
	report->field[0]->value[0] |= data_pointer->dragging          ? 0x04 : 0x08;
	report->field[0]->value[0] |= data_pointer->release_to_select ? 0x10 : 0x20;
	report->field[0]->value[0] |= data_pointer->select_right      ? 0x80 : 0x40;
	report->field[1]->value[0] = 0x03; // unknown setting, imitate windows driver
	report->field[2]->value[0] = data_pointer->sensitivity;
	report->field[3]->value[0] = data_pointer->press_speed;

	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
	return 0;
}
예제 #23
0
/* Submit a report and wait for a reply from device - if device fades away
 * or does not respond in time, return NULL */
struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev,
		int report_id, const u8 *raw_data, int size)
{
	struct picolcd_data *data = hid_get_drvdata(hdev);
	struct picolcd_pending *work;
	struct hid_report *report = picolcd_out_report(report_id, hdev);
	unsigned long flags;
	int i, j, k;

	if (!report || !data)
		return NULL;
	if (data->status & PICOLCD_FAILED)
		return NULL;
	work = kzalloc(sizeof(*work), GFP_KERNEL);
	if (!work)
		return NULL;

	init_completion(&work->ready);
	work->out_report = report;
	work->in_report  = NULL;
	work->raw_size   = 0;

	mutex_lock(&data->mutex);
	spin_lock_irqsave(&data->lock, flags);
	for (i = k = 0; i < report->maxfield; i++)
		for (j = 0; j < report->field[i]->report_count; j++) {
			hid_set_field(report->field[i], j, k < size ? raw_data[k] : 0);
			k++;
		}
	if (data->status & PICOLCD_FAILED) {
		kfree(work);
		work = NULL;
	} else {
		data->pending = work;
		hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT);
		spin_unlock_irqrestore(&data->lock, flags);
		wait_for_completion_interruptible_timeout(&work->ready, HZ*2);
		spin_lock_irqsave(&data->lock, flags);
		data->pending = NULL;
	}
	spin_unlock_irqrestore(&data->lock, flags);
	mutex_unlock(&data->mutex);
	return work;
}
예제 #24
0
파일: hid-g15v2.c 프로젝트: CMoH/lg4l
static void g15v2_feature_report_4_send(struct hid_device *hdev, int which)
{
	struct g15v2_data *gdata = hid_get_g15data(hdev);

	if (which == G15V2_REPORT_4_INIT) {
		gdata->feature_report_4->field[0]->value[0] = 0x02;
		gdata->feature_report_4->field[0]->value[1] = 0x00;
		gdata->feature_report_4->field[0]->value[2] = 0x00;
		gdata->feature_report_4->field[0]->value[3] = 0x00;
	} else if (which == G15V2_REPORT_4_FINALIZE) {
		gdata->feature_report_4->field[0]->value[0] = 0x02;
		gdata->feature_report_4->field[0]->value[1] = 0x80;
		gdata->feature_report_4->field[0]->value[2] = 0x00;
		gdata->feature_report_4->field[0]->value[3] = 0xFF;
	} else {
		return;
	}

	hid_hw_request(hdev, gdata->feature_report_4, HID_REQ_SET_REPORT);
}
예제 #25
0
파일: hid-lg2ff.c 프로젝트: 020gzh/linux
int lg2ff_init(struct hid_device *hid)
{
	struct lg2ff_device *lg2ff;
	struct hid_report *report;
	struct hid_input *hidinput = list_entry(hid->inputs.next,
						struct hid_input, list);
	struct input_dev *dev = hidinput->input;
	int error;

	/* Check that the report looks ok */
	report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7);
	if (!report)
		return -ENODEV;

	lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL);
	if (!lg2ff)
		return -ENOMEM;

	set_bit(FF_RUMBLE, dev->ffbit);

	error = input_ff_create_memless(dev, lg2ff, play_effect);
	if (error) {
		kfree(lg2ff);
		return error;
	}

	lg2ff->report = report;
	report->field[0]->value[0] = 0xf3;
	report->field[0]->value[1] = 0x00;
	report->field[0]->value[2] = 0x00;
	report->field[0]->value[3] = 0x00;
	report->field[0]->value[4] = 0x00;
	report->field[0]->value[5] = 0x00;
	report->field[0]->value[6] = 0x00;

	hid_hw_request(hid, report, HID_REQ_SET_REPORT);

	hid_info(hid, "Force feedback for Logitech variant 2 rumble devices by Anssi Hannula <*****@*****.**>\n");

	return 0;
}
예제 #26
0
파일: hid-lenovo.c 프로젝트: 3null/linux
static void lenovo_led_brightness_set_tpkbd(struct led_classdev *led_cdev,
			enum led_brightness value)
{
	struct device *dev = led_cdev->dev->parent;
	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
	struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev);
	struct hid_report *report;
	int led_nr = 0;

	if (led_cdev == &data_pointer->led_micmute)
		led_nr = 1;

	if (value == LED_OFF)
		data_pointer->led_state &= ~(1 << led_nr);
	else
		data_pointer->led_state |= 1 << led_nr;

	report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3];
	report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1;
	report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1;
	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);
}
예제 #27
0
파일: hid-emsff.c 프로젝트: ChineseDr/linux
static int emsff_play(struct input_dev *dev, void *data,
                      struct ff_effect *effect)
{
    struct hid_device *hid = input_get_drvdata(dev);
    struct emsff_device *emsff = data;
    int weak, strong;

    weak = effect->u.rumble.weak_magnitude;
    strong = effect->u.rumble.strong_magnitude;

    dbg_hid("called with 0x%04x 0x%04x\n", strong, weak);

    weak = weak * 0xff / 0xffff;
    strong = strong * 0xff / 0xffff;

    emsff->report->field[0]->value[1] = weak;
    emsff->report->field[0]->value[2] = strong;

    dbg_hid("running with 0x%02x 0x%02x\n", strong, weak);
    hid_hw_request(hid, emsff->report, HID_REQ_SET_REPORT);

    return 0;
}
static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev,
				    struct dj_report *dj_report)
{
	struct hid_device *hdev = djrcv_dev->hdev;
	struct hid_report *report;
	struct hid_report_enum *output_report_enum;
	u8 *data = (u8 *)(&dj_report->device_index);
	unsigned int i;

	output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT];
	report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT];

	if (!report) {
		dev_err(&hdev->dev, "%s: unable to find dj report\n", __func__);
		return -ENODEV;
	}

	for (i = 0; i < DJREPORT_SHORT_LENGTH - 1; i++)
		report->field[0]->value[i] = data[i];

	hid_hw_request(hdev, report, HID_REQ_SET_REPORT);

	return 0;
}
예제 #29
0
static int g19_probe(struct hid_device *hdev,
                     const struct hid_device_id *id)
{
	unsigned long irq_flags;
	int error;
	struct gcommon_data *gdata;
	struct g19_data *g19data;
	int i;
	int led_num;
	struct usb_interface *intf;
	struct usb_device *usbdev;
	struct list_head *feature_report_list =
			    &hdev->report_enum[HID_FEATURE_REPORT].report_list;
	struct hid_report *report;
	char *led_name;

	dev_dbg(&hdev->dev, "Logitech G19 HID hardware probe...");

	/* Get the usb device to send the start report on */
	intf = to_usb_interface(hdev->dev.parent);
	usbdev = interface_to_usbdev(intf);

	/*
	 * Let's allocate the g19 data structure, set some reasonable
	 * defaults, and associate it with the device
	 */
	gdata = kzalloc(sizeof(struct gcommon_data), GFP_KERNEL);
	if (gdata == NULL) {
		dev_err(&hdev->dev, "can't allocate space for Logitech G19 device attributes\n");
		error = -ENOMEM;
		goto err_no_cleanup;
	}

	g19data = kzalloc(sizeof(struct g19_data), GFP_KERNEL);
	if (g19data == NULL) {
		dev_err(&hdev->dev, "can't allocate space for Logitech G19 device attributes\n");
		error = -ENOMEM;
		goto err_cleanup_gdata;
	}
	gdata->data = g19data;

	spin_lock_init(&gdata->lock);

	init_completion(&g19data->ready);

	gdata->hdev = hdev;

	g19data->ep1_urb = usb_alloc_urb(0, GFP_KERNEL);
	if (g19data->ep1_urb == NULL) {
		dev_err(&hdev->dev, G19_NAME ": ERROR: can't alloc ep1 urb stuff\n");
		error = -ENOMEM;
		goto err_cleanup_g19data;
	}

	hid_set_drvdata(hdev, gdata);

	dbg_hid("Preparing to parse " G19_NAME " hid reports\n");

	/* Parse the device reports and start it up */
	error = hid_parse(hdev);
	if (error) {
		dev_err(&hdev->dev, G19_NAME " device report parse failed\n");
		error = -EINVAL;
		goto err_cleanup_ep1_urb;
	}

	error = hid_hw_start(hdev, HID_CONNECT_DEFAULT | HID_CONNECT_HIDINPUT_FORCE);
	if (error) {
		dev_err(&hdev->dev, G19_NAME " hardware start failed\n");
		error = -EINVAL;
		goto err_cleanup_ep1_urb;
	}

	dbg_hid(G19_NAME " claimed: %d\n", hdev->claimed);

	error = hdev->ll_driver->open(hdev);
	if (error) {
		dev_err(&hdev->dev, G19_NAME " failed to open input interrupt pipe for key and joystick events\n");
		error = -EINVAL;
		goto err_cleanup_hw_start;
	}

	/* Set up the input device for the key I/O */
	gdata->input_dev = input_allocate_device();
	if (gdata->input_dev == NULL) {
		dev_err(&hdev->dev, G19_NAME " error initializing the input device");
		error = -ENOMEM;
		goto err_cleanup_hw_start;
	}

	input_set_drvdata(gdata->input_dev, gdata);

	gdata->input_dev->name = G19_NAME;
	gdata->input_dev->phys = hdev->phys;
	gdata->input_dev->uniq = hdev->uniq;
	gdata->input_dev->id.bustype = hdev->bus;
	gdata->input_dev->id.vendor = hdev->vendor;
	gdata->input_dev->id.product = hdev->product;
	gdata->input_dev->id.version = hdev->version;
	gdata->input_dev->dev.parent = hdev->dev.parent;
	gdata->input_dev->keycode = gdata->input_data.keycode;
	gdata->input_dev->keycodemax = G19_KEYMAP_SIZE;
	gdata->input_dev->keycodesize = sizeof(unsigned int);
	gdata->input_dev->setkeycode = ginput_setkeycode;
	gdata->input_dev->getkeycode = ginput_getkeycode;

	input_set_capability(gdata->input_dev, EV_KEY, KEY_UNKNOWN);
	gdata->input_dev->evbit[0] |= BIT_MASK(EV_REP);

	gdata->input_data.notify_keymap_switched = g19_notify_keymap_switched;

	error = ginput_alloc(gdata, G19_KEYS);
	if (error) {
		dev_err(&hdev->dev, G19_NAME " error allocating memory for the input device");
		goto err_cleanup_input_dev;
	}

	g19_initialize_keymap(gdata);

	error = input_register_device(gdata->input_dev);
	if (error) {
		dev_err(&hdev->dev, G19_NAME " error registering the input device");
		error = -EINVAL;
		goto err_cleanup_input_dev_data;
	}

	if (list_empty(feature_report_list)) {
		dev_err(&hdev->dev, "no feature report found\n");
		error = -ENODEV;
		goto err_cleanup_input_dev_reg;
	}
	dbg_hid(G19_NAME " feature report found\n");

	list_for_each_entry(report, feature_report_list, list) {
		switch (report->id) {
		case 0x04:
			g19data->feature_report_4 = report;
			break;
		case 0x05:
			g19data->led_report = report;
			break;
		case 0x06:
			g19data->start_input_report = report;
			break;
		case 0x07:
			g19data->backlight_report = report;
			break;
		default:
			break;
		}
		dbg_hid(G19_NAME " Feature report: id=%u type=%u size=%u maxfield=%u report_count=%u\n",
		        report->id, report->type, report->size,
		        report->maxfield, report->field[0]->report_count);
	}

	dbg_hid("Found all reports\n");

	/* Create the LED structures */
	for (i = 0; i < LED_COUNT; i++) {
		g19data->led_cdev[i] = kzalloc(sizeof(struct led_classdev), GFP_KERNEL);
		if (g19data->led_cdev[i] == NULL) {
			dev_err(&hdev->dev, G19_NAME " error allocating memory for led %d", i);
			error = -ENOMEM;
			goto err_cleanup_led_structs;
		}
		/* Set the accessor functions by copying from template*/
		*(g19data->led_cdev[i]) = g19_led_cdevs[i];

		/*
		 * Allocate memory for the LED name
		 *
		 * Since led_classdev->name is a const char* we'll use an
		 * intermediate until the name is formatted with sprintf().
		 */
		led_name = kzalloc(sizeof(char)*20, GFP_KERNEL);
		if (led_name == NULL) {
			dev_err(&hdev->dev, G19_NAME " error allocating memory for led %d name", i);
			error = -ENOMEM;
			goto err_cleanup_led_structs;
		}
		switch (i) {
		case G19_LED_M1:
		case G19_LED_M2:
		case G19_LED_M3:
			sprintf(led_name, "g19_%d:orange:m%d", hdev->minor, i+1);
			break;
		case G19_LED_MR:
			sprintf(led_name, "g19_%d:red:mr", hdev->minor);
			break;
		case G19_LED_BL_R:
			sprintf(led_name, "g19_%d:red:bl", hdev->minor);
			break;
		case G19_LED_BL_G:
			sprintf(led_name, "g19_%d:green:bl", hdev->minor);
			break;
		case G19_LED_BL_B:
			sprintf(led_name, "g19_%d:blue:bl", hdev->minor);
			break;
		case G19_LED_BL_SCREEN:
			sprintf(led_name, "g19_%d:white:screen", hdev->minor);
			break;

		}
		g19data->led_cdev[i]->name = led_name;
	}

	for (i = 0; i < LED_COUNT; i++) {
		led_num = i;
		error = led_classdev_register(&hdev->dev, g19data->led_cdev[i]);
		if (error < 0) {
			dev_err(&hdev->dev, G19_NAME " error registering led %d", i);
			error = -EINVAL;
			goto err_cleanup_registered_leds;
		}
	}

	gdata->gfb_data = gfb_probe(hdev, GFB_PANEL_TYPE_320_240_16);
	if (gdata->gfb_data == NULL) {
		dev_err(&hdev->dev, G19_NAME " error registering framebuffer\n");
		goto err_cleanup_registered_leds;
	}

	dbg_hid("Waiting for G19 to activate\n");

	/* Add the sysfs attributes */
	error = sysfs_create_group(&(hdev->dev.kobj), &g19_attr_group);
	if (error) {
		dev_err(&hdev->dev, G19_NAME " failed to create sysfs group attributes\n");
		goto err_cleanup_gfb;
	}

	/*
	 * Wait here for stage 1 (substages 1-3) to complete
	 */
	wait_for_completion_timeout(&g19data->ready, HZ);

	/* Protect data->ready_stages before checking whether we're ready to proceed */
	spin_lock_irqsave(&gdata->lock, irq_flags);
	if (g19data->ready_stages != G19_READY_STAGE_1) {
		dev_warn(&hdev->dev, G19_NAME " hasn't completed stage 1 yet, forging ahead with initialization\n");
		/* Force the stage */
		g19data->ready_stages = G19_READY_STAGE_1;
	}
	init_completion(&g19data->ready);
	g19data->ready_stages |= G19_READY_SUBSTAGE_4;
	spin_unlock_irqrestore(&gdata->lock, irq_flags);

	/*
	 * Send the init report, then follow with the input report to trigger
	 * report 6 and wait for us to get a response.
	 */
	g19_feature_report_4_send(hdev, G19_REPORT_4_INIT);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)

	hid_hw_request(hdev, g19data->start_input_report, HID_REQ_GET_REPORT);

#else

	usbhid_submit_report(hdev, g19data->start_input_report, USB_DIR_IN);

#endif

	wait_for_completion_timeout(&g19data->ready, HZ);

	/* Protect g19data->ready_stages before checking whether we're ready to proceed */
	spin_lock_irqsave(&gdata->lock, irq_flags);
	if (g19data->ready_stages != G19_READY_STAGE_2) {
		dev_warn(&hdev->dev, G19_NAME " hasn't completed stage 2 yet, forging ahead with initialization\n");
		/* Force the stage */
		g19data->ready_stages = G19_READY_STAGE_2;
	}
	init_completion(&g19data->ready);
	g19data->ready_stages |= G19_READY_SUBSTAGE_6;
	spin_unlock_irqrestore(&gdata->lock, irq_flags);

	/*
	 * Clear the LEDs
	 */
	g19_led_send(hdev);

	g19data->rgb[0] = G19_DEFAULT_RED;
	g19data->rgb[1] = G19_DEFAULT_GREEN;
	g19data->rgb[2] = G19_DEFAULT_BLUE;
	g19_rgb_send(hdev);

	g19data->screen_bl = G19_DEFAULT_BRIGHTNESS;
	g19_screen_bl_send(hdev);

	/*
	 * Send the finalize report, then follow with the input report to trigger
	 * report 6 and wait for us to get a response.
	 */
	g19_feature_report_4_send(hdev, G19_REPORT_4_FINALIZE);

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)

	hid_hw_request(hdev, g19data->start_input_report, HID_REQ_GET_REPORT);
	hid_hw_request(hdev, g19data->start_input_report, HID_REQ_GET_REPORT);

#else

	usbhid_submit_report(hdev, g19data->start_input_report, USB_DIR_IN);
	usbhid_submit_report(hdev, g19data->start_input_report, USB_DIR_IN);

#endif

	wait_for_completion_timeout(&g19data->ready, HZ);

	/* Protect data->ready_stages before checking whether we're ready to proceed */
	spin_lock_irqsave(&gdata->lock, irq_flags);

	if (g19data->ready_stages != G19_READY_STAGE_3) {
		dev_warn(&hdev->dev, G19_NAME " hasn't completed stage 3 yet, forging ahead with initialization\n");
		/* Force the stage */
		g19data->ready_stages = G19_READY_STAGE_3;
	} else {
		dbg_hid(G19_NAME " stage 3 complete\n");
	}

	spin_unlock_irqrestore(&gdata->lock, irq_flags);

	ginput_set_keymap_switching(gdata, 1);

	g19_ep1_read(hdev);

	dbg_hid("G19 activated and initialized\n");

	/* Everything went well */
	return 0;

err_cleanup_gfb:
	gfb_remove(gdata->gfb_data);

err_cleanup_registered_leds:
	for (i = 0; i < led_num; i++)
		led_classdev_unregister(g19data->led_cdev[i]);

err_cleanup_led_structs:
	for (i = 0; i < LED_COUNT; i++) {
		if (g19data->led_cdev[i] != NULL) {
			if (g19data->led_cdev[i]->name != NULL)
				kfree(g19data->led_cdev[i]->name);
			kfree(g19data->led_cdev[i]);
		}
	}

err_cleanup_input_dev_reg:
	input_unregister_device(gdata->input_dev);

err_cleanup_input_dev_data:
	ginput_free(gdata);

err_cleanup_input_dev:
	input_free_device(gdata->input_dev);

err_cleanup_hw_start:
	hid_hw_stop(hdev);

err_cleanup_ep1_urb:
	usb_free_urb(g19data->ep1_urb);

err_cleanup_g19data:
	kfree(g19data);

err_cleanup_gdata:
	kfree(gdata);

err_no_cleanup:
	hid_set_drvdata(hdev, NULL);
	return error;
}