static int samsung_actionmouse_input_mapping(struct hid_device *hdev,
	struct hid_input *hi, struct hid_field *field, struct hid_usage *usage,
	unsigned long **bit, int *max)
{

	dbg_hid("samsung wireless actionmouse input mapping event [0x%x], [0x%x], %ld, %ld, [0x%x]\n",
			usage->hid, usage->hid & HID_USAGE, hi->input->evbit[0], hi->input->absbit[0], usage->hid & HID_USAGE_PAGE);

	if(((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER) && ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON))
		return 0;

	switch (usage->hid & HID_USAGE) {
		case 0x301: samsung_kbd_mouse_map_key_clear(KEY_RECENT); break;
		default:
			return 0;
	}

	return 1;
}
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[8];
	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);
	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]);

	usbhid_submit_report(dj_rcv_hiddev, report, USB_DIR_OUT);

	return 0;

}
Esempio n. 3
0
static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
{
	struct hid_field *field;

	if (report->maxfield == HID_MAX_FIELDS) {
		dbg_hid("too many fields in report\n");
		return NULL;
	}

	if (!(field = kzalloc(sizeof(struct hid_field) + usages * sizeof(struct hid_usage)
		+ values * sizeof(unsigned), GFP_KERNEL))) return NULL;

	field->index = report->maxfield++;
	report->field[field->index] = field;
	field->usage = (struct hid_usage *)(field + 1);
	field->value = (unsigned *)(field->usage + usages);
	field->report = report;

	return field;
}
static int hid_submit_out(struct hid_device *hid)
{
	struct hid_report *report;
	char *raw_report;
	struct usbhid_device *usbhid = hid->driver_data;

	report = usbhid->out[usbhid->outtail].report;
	raw_report = usbhid->out[usbhid->outtail].raw_report;

	if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) {
		usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
		usbhid->urbout->dev = hid_to_usb_dev(hid);
		memcpy(usbhid->outbuf, raw_report, usbhid->urbout->transfer_buffer_length);
		kfree(raw_report);

		dbg_hid("submitting out urb\n");

		if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) {
			err_hid("usb_submit_urb(out) failed");
			return -1;
		}
	} else {
Esempio n. 5
0
static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
					  struct dj_report *dj_report)
{
	/* Called in delayed work context */
	struct hid_device *djrcv_hdev = djrcv_dev->hdev;
	struct usb_interface *intf = to_usb_interface(djrcv_hdev->dev.parent);
	struct usb_device *usbdev = interface_to_usbdev(intf);
	struct hid_device *dj_hiddev;
	struct dj_device *dj_dev;

	/* Device index goes from 1 to 6, we need 3 bytes to store the
	 * semicolon, the index, and a null terminator
	 */
	unsigned char tmpstr[3];

	if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
	    SPFUNCTION_DEVICE_LIST_EMPTY) {
		dbg_hid("%s: device list is empty\n", __func__);
		return;
	}

<<<<<<< HEAD
Esempio n. 6
0
static void picolcd_remove(struct hid_device *hdev)
{
	struct picolcd_data *data = hid_get_drvdata(hdev);
	unsigned long flags;

	dbg_hid(PICOLCD_NAME " hardware remove...\n");
	spin_lock_irqsave(&data->lock, flags);
	data->status |= PICOLCD_FAILED;
	spin_unlock_irqrestore(&data->lock, flags);

	picolcd_exit_devfs(data);
	device_remove_file(&hdev->dev, &dev_attr_operation_mode);
	device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
	hid_hw_close(hdev);
	hid_hw_stop(hdev);

	/* Shortcut potential pending reply that will never arrive */
	spin_lock_irqsave(&data->lock, flags);
	if (data->pending)
		complete(&data->pending->ready);
	spin_unlock_irqrestore(&data->lock, flags);

	/* Cleanup LED */
	picolcd_exit_leds(data);
	/* Clean up the framebuffer */
	picolcd_exit_backlight(data);
	picolcd_exit_lcd(data);
	picolcd_exit_framebuffer(data);
	/* Cleanup input */
	picolcd_exit_cir(data);
	picolcd_exit_keys(data);

	hid_set_drvdata(hdev, NULL);
	mutex_destroy(&data->mutex);
	/* Finally, clean up the picolcd data itself */
	kfree(data);
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
struct hid_device *hid_parse_report(__u8 *start, unsigned size)
{
	struct hid_device *device;
	struct hid_parser *parser;
	struct hid_item item;
	__u8 *end;
	unsigned i;
	static int (*dispatch_type[])(struct hid_parser *parser,
				      struct hid_item *item) = {
		hid_parser_main,
		hid_parser_global,
		hid_parser_local,
		hid_parser_reserved
	};

	if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL)))
		return NULL;

	if (!(device->collection = kzalloc(sizeof(struct hid_collection) *
				   HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) {
		kfree(device);
		return NULL;
	}
	device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;

	for (i = 0; i < HID_REPORT_TYPES; i++)
		INIT_LIST_HEAD(&device->report_enum[i].report_list);

	if (!(device->rdesc = kmalloc(size, GFP_KERNEL))) {
		kfree(device->collection);
		kfree(device);
		return NULL;
	}
	memcpy(device->rdesc, start, size);
	device->rsize = size;

	if (!(parser = vmalloc(sizeof(struct hid_parser)))) {
		kfree(device->rdesc);
		kfree(device->collection);
		kfree(device);
		return NULL;
	}
	memset(parser, 0, sizeof(struct hid_parser));
	parser->device = device;

	end = start + size;
	while ((start = fetch_item(start, end, &item)) != NULL) {

		if (item.format != HID_ITEM_FORMAT_SHORT) {
			dbg_hid("unexpected long global item\n");
			hid_free_device(device);
			vfree(parser);
			return NULL;
		}

		if (dispatch_type[item.type](parser, &item)) {
			dbg_hid("item %u %u %u %u parsing failed\n",
				item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
			hid_free_device(device);
			vfree(parser);
			return NULL;
		}

		if (start == end) {
			if (parser->collection_stack_ptr) {
				dbg_hid("unbalanced collection at end of report description\n");
				hid_free_device(device);
				vfree(parser);
				return NULL;
			}
			if (parser->local.delimiter_depth) {
				dbg_hid("unbalanced delimiter at end of report description\n");
				hid_free_device(device);
				vfree(parser);
				return NULL;
			}
			vfree(parser);
			return device;
		}
	}

	dbg_hid("item fetching failed at offset %d\n", (int)(end - start));
	hid_free_device(device);
	vfree(parser);
	return NULL;
}
Esempio n. 9
0
static int hid_parser_reserved(struct hid_parser *parser, struct hid_item *item)
{
	dbg_hid("reserved item type, tag 0x%x\n", item->tag);
	return 0;
}
Esempio n. 10
0
static int hid_parser_local(struct hid_parser *parser, struct hid_item *item)
{
	__u32 data;
	unsigned n;

	if (item->size == 0) {
		dbg_hid("item data expected for local item\n");
		return -1;
	}

	data = item_udata(item);

	switch (item->tag) {

		case HID_LOCAL_ITEM_TAG_DELIMITER:

			if (data) {
				/*
				 * We treat items before the first delimiter
				 * as global to all usage sets (branch 0).
				 * In the moment we process only these global
				 * items and the first delimiter set.
				 */
				if (parser->local.delimiter_depth != 0) {
					dbg_hid("nested delimiters\n");
					return -1;
				}
				parser->local.delimiter_depth++;
				parser->local.delimiter_branch++;
			} else {
				if (parser->local.delimiter_depth < 1) {
					dbg_hid("bogus close delimiter\n");
					return -1;
				}
				parser->local.delimiter_depth--;
			}
			return 1;

		case HID_LOCAL_ITEM_TAG_USAGE:

			if (parser->local.delimiter_branch > 1) {
				dbg_hid("alternative usage ignored\n");
				return 0;
			}

			if (item->size <= 2)
				data = (parser->global.usage_page << 16) + data;

			return hid_add_usage(parser, data);

		case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:

			if (parser->local.delimiter_branch > 1) {
				dbg_hid("alternative usage ignored\n");
				return 0;
			}

			if (item->size <= 2)
				data = (parser->global.usage_page << 16) + data;

			parser->local.usage_minimum = data;
			return 0;

		case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:

			if (parser->local.delimiter_branch > 1) {
				dbg_hid("alternative usage ignored\n");
				return 0;
			}

			if (item->size <= 2)
				data = (parser->global.usage_page << 16) + data;

			for (n = parser->local.usage_minimum; n <= data; n++)
				if (hid_add_usage(parser, n)) {
					dbg_hid("hid_add_usage failed\n");
					return -1;
				}
			return 0;

		default:

			dbg_hid("unknown local item tag 0x%x\n", item->tag);
			return 0;
	}
	return 0;
}
Esempio n. 11
0
static int picolcd_probe(struct hid_device *hdev,
		     const struct hid_device_id *id)
{
	struct picolcd_data *data;
	int error = -ENOMEM;

	dbg_hid(PICOLCD_NAME " hardware probe...\n");

	/*
	 * Let's allocate the picolcd data structure, set some reasonable
	 * defaults, and associate it with the device
	 */
	data = kzalloc(sizeof(struct picolcd_data), GFP_KERNEL);
	if (data == NULL) {
		hid_err(hdev, "can't allocate space for Minibox PicoLCD device data\n");
		error = -ENOMEM;
		goto err_no_cleanup;
	}

	spin_lock_init(&data->lock);
	mutex_init(&data->mutex);
	data->hdev = hdev;
	data->opmode_delay = 5000;
	if (hdev->product == USB_DEVICE_ID_PICOLCD_BOOTLOADER)
		data->status |= PICOLCD_BOOTLOADER;
	hid_set_drvdata(hdev, data);

	/* Parse the device reports and start it up */
	error = hid_parse(hdev);
	if (error) {
		hid_err(hdev, "device report parse failed\n");
		goto err_cleanup_data;
	}

	error = hid_hw_start(hdev, 0);
	if (error) {
		hid_err(hdev, "hardware start failed\n");
		goto err_cleanup_data;
	}

	error = hid_hw_open(hdev);
	if (error) {
		hid_err(hdev, "failed to open input interrupt pipe for key and IR events\n");
		goto err_cleanup_hid_hw;
	}

	error = device_create_file(&hdev->dev, &dev_attr_operation_mode_delay);
	if (error) {
		hid_err(hdev, "failed to create sysfs attributes\n");
		goto err_cleanup_hid_ll;
	}

	error = device_create_file(&hdev->dev, &dev_attr_operation_mode);
	if (error) {
		hid_err(hdev, "failed to create sysfs attributes\n");
		goto err_cleanup_sysfs1;
	}

	if (data->status & PICOLCD_BOOTLOADER)
		error = picolcd_probe_bootloader(hdev, data);
	else
		error = picolcd_probe_lcd(hdev, data);
	if (error)
		goto err_cleanup_sysfs2;

	dbg_hid(PICOLCD_NAME " activated and initialized\n");
	return 0;

err_cleanup_sysfs2:
	device_remove_file(&hdev->dev, &dev_attr_operation_mode);
err_cleanup_sysfs1:
	device_remove_file(&hdev->dev, &dev_attr_operation_mode_delay);
err_cleanup_hid_ll:
	hid_hw_close(hdev);
err_cleanup_hid_hw:
	hid_hw_stop(hdev);
err_cleanup_data:
	kfree(data);
err_no_cleanup:
	hid_set_drvdata(hdev, NULL);

	return error;
}
Esempio n. 12
0
static int logi_dj_raw_event(struct hid_device *hdev,
			     struct hid_report *report, u8 *data,
			     int size)
{
	struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
	struct dj_report *dj_report = (struct dj_report *) data;
	unsigned long flags;

	dbg_hid("%s, size:%d\n", __func__, size);

	/* Here we receive all data coming from iface 2, there are 4 cases:
	 *
	 * 1) Data should continue its normal processing i.e. data does not
	 * come from the DJ collection, in which case we do nothing and
	 * return 0, so hid-core can continue normal processing (will forward
	 * to associated hidraw device)
	 *
	 * 2) Data is from DJ collection, and is intended for this driver i. e.
	 * data contains arrival, departure, etc notifications, in which case
	 * we queue them for delayed processing by the work queue. We return 1
	 * to hid-core as no further processing is required from it.
	 *
	 * 3) Data is from DJ collection, and informs a connection change,
	 * if the change means rf link loss, then we must send a null report
	 * to the upper layer to discard potentially pressed keys that may be
	 * repeated forever by the input layer. Return 1 to hid-core as no
	 * further processing is required.
	 *
	 * 4) Data is from DJ collection and is an actual input event from
	 * a paired DJ device in which case we forward it to the correct hid
	 * device (via hid_input_report() ) and return 1 so hid-core does not do
	 * anything else with it.
	 */

	/* case 1) */
	if (data[0] != REPORT_ID_DJ_SHORT)
		return false;

	if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) ||
	    (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) {
		/*
		 * Device index is wrong, bail out.
		 * This driver can ignore safely the receiver notifications,
		 * so ignore those reports too.
		 */
		if (dj_report->device_index != DJ_RECEIVER_INDEX)
			dev_err(&hdev->dev, "%s: invalid device index:%d\n",
				__func__, dj_report->device_index);
		return false;
	}

	spin_lock_irqsave(&djrcv_dev->lock, flags);
	switch (dj_report->report_type) {
	case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
	case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
		logi_dj_recv_queue_notification(djrcv_dev, dj_report);
		break;
	case REPORT_TYPE_NOTIF_CONNECTION_STATUS:
		if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] ==
		    STATUS_LINKLOSS) {
			logi_dj_recv_forward_null_report(djrcv_dev, dj_report);
		}
		break;
	default:
		logi_dj_recv_forward_report(djrcv_dev, dj_report);
	}
	spin_unlock_irqrestore(&djrcv_dev->lock, flags);

	return true;
}
Esempio n. 13
0
static int logi_dj_ll_start(struct hid_device *hid)
{
	dbg_hid("%s\n", __func__);
	return 0;
}
Esempio n. 14
0
static void logi_dj_ll_close(struct hid_device *hid)
{
	dbg_hid("%s:%s\n", __func__, hid->phys);
}
Esempio n. 15
0
static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
					  struct dj_report *dj_report)
{
	/* Called in delayed work context */
	struct hid_device *djrcv_hdev = djrcv_dev->hdev;
	struct usb_interface *intf = to_usb_interface(djrcv_hdev->dev.parent);
	struct usb_device *usbdev = interface_to_usbdev(intf);
	struct hid_device *dj_hiddev;
	struct dj_device *dj_dev;

	/* Device index goes from 1 to 6, we need 3 bytes to store the
	 * semicolon, the index, and a null terminator
	 */
	unsigned char tmpstr[3];

	if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
	    SPFUNCTION_DEVICE_LIST_EMPTY) {
		dbg_hid("%s: device list is empty\n", __func__);
		return;
	}

	if (djrcv_dev->paired_dj_devices[dj_report->device_index]) {
		/* The device is already known. No need to reallocate it. */
		dbg_hid("%s: device is already known\n", __func__);
		return;
	}

	dj_hiddev = hid_allocate_device();
	if (IS_ERR(dj_hiddev)) {
		dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n",
			__func__);
		return;
	}

	dj_hiddev->ll_driver = &logi_dj_ll_driver;
	dj_hiddev->hid_output_raw_report = logi_dj_output_hidraw_report;

	dj_hiddev->dev.parent = &djrcv_hdev->dev;
	dj_hiddev->bus = BUS_USB;
	dj_hiddev->vendor = le16_to_cpu(usbdev->descriptor.idVendor);
	dj_hiddev->product = le16_to_cpu(usbdev->descriptor.idProduct);
	snprintf(dj_hiddev->name, sizeof(dj_hiddev->name),
		"Logitech Unifying Device. Wireless PID:%02x%02x",
		dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB],
		dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_LSB]);

	usb_make_path(usbdev, dj_hiddev->phys, sizeof(dj_hiddev->phys));
	snprintf(tmpstr, sizeof(tmpstr), ":%d", dj_report->device_index);
	strlcat(dj_hiddev->phys, tmpstr, sizeof(dj_hiddev->phys));

	dj_dev = kzalloc(sizeof(struct dj_device), GFP_KERNEL);

	if (!dj_dev) {
		dev_err(&djrcv_hdev->dev, "%s: failed allocating dj_device\n",
			__func__);
		goto dj_device_allocate_fail;
	}

	dj_dev->reports_supported = le32_to_cpu(
		dj_report->report_params[DEVICE_PAIRED_RF_REPORT_TYPE]);
	dj_dev->hdev = dj_hiddev;
	dj_dev->dj_receiver_dev = djrcv_dev;
	dj_dev->device_index = dj_report->device_index;
	dj_hiddev->driver_data = dj_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);
}
Esempio n. 16
0
static int samsung_kbd_input_mapping(struct hid_device *hdev,
	struct hid_input *hi, struct hid_field *field, struct hid_usage *usage,
	unsigned long **bit, int *max)
{
	if (!(HID_UP_CONSUMER == (usage->hid & HID_USAGE_PAGE) ||
			HID_UP_KEYBOARD == (usage->hid & HID_USAGE_PAGE)))
		return 0;

	dbg_hid("samsung wireless keyboard input mapping event [0x%x]\n",
		usage->hid & HID_USAGE);

	if (HID_UP_KEYBOARD == (usage->hid & HID_USAGE_PAGE)) {
		switch (usage->hid & HID_USAGE) {
		/*set_bit(EV_REP, hi->input->evbit);*/
				/* SS_BLUETOOTH(js80.hong) 2012.03.17 */
		/* Only for UK keyboard */
		/* key found */
		case 0x32:
			samsung_kbd_mouse_map_key_clear(KEY_KBDILLUMTOGGLE);
			break;
		case 0x64:
			samsung_kbd_mouse_map_key_clear(KEY_BACKSLASH);
			break;
		default:
			return 0;
		}
	}

	if (HID_UP_CONSUMER == (usage->hid & HID_USAGE_PAGE)) {
		switch (usage->hid & HID_USAGE) {
		/* report 2 */
		/* MENU */
		case 0x040:
			samsung_kbd_mouse_map_key_clear(KEY_MENU);
			break;
		case 0x18a:
			samsung_kbd_mouse_map_key_clear(KEY_MAIL);
			break;
		case 0x196:
			samsung_kbd_mouse_map_key_clear(KEY_WWW);
			break;
		case 0x19e:
			samsung_kbd_mouse_map_key_clear(KEY_SCREENLOCK);
			break;
		case 0x221:
			samsung_kbd_mouse_map_key_clear(KEY_SEARCH);
			break;
		case 0x223:
			samsung_kbd_mouse_map_key_clear(KEY_HOMEPAGE);
			break;
		/* RECENTAPPS */
		case 0x301:
			samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY1);
			break;
		/* APPLICATION */
		case 0x302:
			samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY2);
			break;
		/* Voice search */
		case 0x305:
			samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY4);
			break;
		/* QPANEL on/off */
		case 0x306:
			samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY5);
			break;
		/* SIP on/off */
		case 0x307:
			samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY3);
			break;
		/* LANG */
		case 0x308:
			samsung_kbd_mouse_map_key_clear(KEY_LANGUAGE);
			break;
		case 0x30a:
			samsung_kbd_mouse_map_key_clear(KEY_BRIGHTNESSDOWN);
			break;
		case 0x30b:
			samsung_kbd_mouse_map_key_clear(KEY_BRIGHTNESSUP);
			break;
		default:
			return 0;
		}
	}

	return 1;
}
Esempio n. 17
0
static int g15_probe(struct hid_device *hdev,
		     const struct hid_device_id *id)
{
	unsigned long irq_flags;
	int error;
	struct gcommon_data *gdata;
	struct g15_data *g15data;
	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 list_head *output_report_list =
			&hdev->report_enum[HID_OUTPUT_REPORT].report_list;
	struct hid_report *report;
	char *led_name;

	dev_dbg(&hdev->dev, "Logitech G15 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 g15 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 G15 device attributes\n");
		error = -ENOMEM;
		goto err_no_cleanup;
	}

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

	spin_lock_init(&gdata->lock);

	init_completion(&g15data->ready);

	gdata->hdev = hdev;

	hid_set_drvdata(hdev, gdata);

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

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

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

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

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

	/* 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, G15_NAME " error initializing the input device");
		error = -ENOMEM;
		goto err_cleanup_g15data;
	}

	input_set_drvdata(gdata->input_dev, gdata);

	gdata->input_dev->name = G15_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 = G15_KEYMAP_SIZE;
	gdata->input_dev->keycodesize = sizeof(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 = g15_notify_keymap_switched;

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

	g15_initialize_keymap(gdata);

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

	dbg_hid(KERN_INFO G15_NAME " allocated framebuffer\n");

	dbg_hid(KERN_INFO G15_NAME " allocated deferred IO structure\n");

	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(G15_NAME " feature report found\n");

	list_for_each_entry(report, feature_report_list, list) {
		switch (report->id) {
		case 0x02: /* G15 has only one feature report 0x02 */
			g15data->feature_report_4
                          = g15data->led_report
                          = g15data->start_input_report
                          = g15data->backlight_report
                          = report;
			break;
		default:
			break;
		}
		dbg_hid(G15_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);
	}

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

	list_for_each_entry(report, output_report_list, list) {
		dbg_hid(G15_NAME " output report %d found size=%u maxfield=%u\n", report->id, report->size, report->maxfield);
		if (report->maxfield > 0) {
			dbg_hid(G15_NAME " offset=%u size=%u count=%u type=%u\n",
			       report->field[0]->report_offset,
			       report->field[0]->report_size,
			       report->field[0]->report_count,
			       report->field[0]->report_type);
		}
		switch (report->id) {
		case 0x03:
			g15data->output_report_3 = report;
			break;
		}
	}
Esempio n. 18
0
static int g19_probe(struct hid_device *hdev,
		     const struct hid_device_id *id)
{
        unsigned long irq_flags;
	int error;
	struct g19_data *data;
	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
	 */
	data = kzalloc(sizeof(struct g19_data), GFP_KERNEL);
	if (data == NULL) {
		dev_err(&hdev->dev, "can't allocate space for Logitech G19 device attributes\n");
		error = -ENOMEM;
		goto err_no_cleanup;
	}

	spin_lock_init(&data->lock);

	init_completion(&data->ready);

	data->hdev = hdev;

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

	hid_set_drvdata(hdev, data);

	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_ep1_urb;
	}

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

	input_set_drvdata(data->input_dev, hdev);

	data->input_dev->name = G19_NAME;
	data->input_dev->phys = hdev->phys;
	data->input_dev->uniq = hdev->uniq;
	data->input_dev->id.bustype = hdev->bus;
	data->input_dev->id.vendor = hdev->vendor;
	data->input_dev->id.product = hdev->product;
	data->input_dev->id.version = hdev->version;
	data->input_dev->dev.parent = hdev->dev.parent;
	data->input_dev->keycode = data->keycode;
	data->input_dev->keycodemax = G19_KEYMAP_SIZE;
	data->input_dev->keycodesize = sizeof(int);
	data->input_dev->setkeycode = g19_input_setkeycode;
	data->input_dev->getkeycode = g19_input_getkeycode;

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

	g19_initialize_keymap(data);

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

	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:
			data->feature_report_4 = report;
			break;
		case 0x05:
			data->led_report = report;
			break;
		case 0x06:
			data->start_input_report = report;
			break;
		case 0x07:
			data->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++) {
		data->led_cdev[i] = kzalloc(sizeof(struct led_classdev), GFP_KERNEL);
		if (data->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*/
		*(data->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;

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

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

	data->gfb_data = gfb_probe(hdev, GFB_PANEL_TYPE_320_240_16);
	if (data->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_registered_leds;
	}

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

	/* Protect data->ready_stages before checking whether we're ready to proceed */
	spin_lock_irqsave(&data->lock, irq_flags);
	if (data->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 */
		data->ready_stages = G19_READY_STAGE_1;
	}
	init_completion(&data->ready);
	data->ready_stages |= G19_READY_SUBSTAGE_4;
	spin_unlock_irqrestore(&data->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);
	usbhid_submit_report(hdev, data->start_input_report, USB_DIR_IN);
	wait_for_completion_timeout(&data->ready, HZ);

	/* Protect data->ready_stages before checking whether we're ready to proceed */
	spin_lock_irqsave(&data->lock, irq_flags);
	if (data->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 */
		data->ready_stages = G19_READY_STAGE_2;
	}
	init_completion(&data->ready);
	data->ready_stages |= G19_READY_SUBSTAGE_6;
	spin_unlock_irqrestore(&data->lock, irq_flags);

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

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

	data->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);
	usbhid_submit_report(hdev, data->start_input_report, USB_DIR_IN);
	usbhid_submit_report(hdev, data->start_input_report, USB_DIR_IN);
	wait_for_completion_timeout(&data->ready, HZ);

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

	if (data->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 */
		data->ready_stages = G19_READY_STAGE_3;
	} else {
		dbg_hid(G19_NAME " stage 3 complete\n");
	}

	spin_unlock_irqrestore(&data->lock, irq_flags);

	g19_set_keymap_switching(hdev, 1);

	g19_ep1_read(hdev);

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

	/* Everything went well */
	return 0;

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

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

err_cleanup_input_dev_reg:
	input_unregister_device(data->input_dev);

err_cleanup_input_dev:
	input_free_device(data->input_dev);

err_cleanup_ep1_urb:
	usb_free_urb(data->ep1_urb);



err_cleanup_data:
	/* Make sure we clean up the allocated data structure */
	kfree(data);

err_no_cleanup:

	hid_set_drvdata(hdev, NULL);

	return error;
}
Esempio n. 19
0
File: hid-g510.c Progetto: CMoH/lg4l
static int read_feature_reports(struct gcore_data *gdata)
{
	struct hid_device *hdev = gdata->hdev;
	struct g510_data *g510data = gdata->data;

	struct list_head *feature_report_list =
			    &hdev->report_enum[HID_FEATURE_REPORT].report_list;
	struct list_head *output_report_list =
			    &hdev->report_enum[HID_OUTPUT_REPORT].report_list;
	struct hid_report *report;

	if (list_empty(feature_report_list)) {
		dev_err(&hdev->dev, "no feature report found\n");
		return -ENODEV;
	}
	dbg_hid(G510_NAME " feature report found\n");

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

	if (list_empty(output_report_list)) {
		dev_err(&hdev->dev, "no output report found\n");
		return -ENODEV;
	}
	dbg_hid("%s output report found\n", gdata->name);

	list_for_each_entry(report, output_report_list, list) {
		dbg_hid("%s output report %d found size=%u maxfield=%u\n",
			gdata->name,
			report->id, report->size, report->maxfield);
		if (report->maxfield > 0) {
			dbg_hid("%s offset=%u size=%u count=%u type=%u\n",
				gdata->name,
				report->field[0]->report_offset,
				report->field[0]->report_size,
				report->field[0]->report_count,
				report->field[0]->report_type);
		}
		switch (report->id) {
		case 0x03:
			g510data->output_report_3 = report;
			break;
		}
	}
Esempio n. 20
0
static int g19_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
	int error;
	struct gcore_data *gdata;
	struct g19_data *g19data;

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

	gdata = gcore_alloc_data(G19_NAME, hdev);
	if (gdata == NULL) {
		dev_err(&hdev->dev,
			G19_NAME
			" can't allocate space for device attributes\n");
		error = -ENOMEM;
		goto err_no_cleanup;
	}

	g19data = kzalloc(sizeof(struct g19_data), GFP_KERNEL);
	if (g19data == NULL) {
		error = -ENOMEM;
		goto err_cleanup_gdata;
	}
	gdata->data = g19data;
	init_completion(&g19data->ready);

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

	error = gcore_hid_open(gdata);
	if (error) {
		dev_err(&hdev->dev,
			"%s error opening hid device\n",
			gdata->name);
		goto err_cleanup_ep1_urb;
	}

	error = gcore_input_probe(gdata, g19_default_keymap,
				  ARRAY_SIZE(g19_default_keymap));
	if (error) {
		dev_err(&hdev->dev,
			"%s error registering input device\n",
			gdata->name);
		goto err_cleanup_hid;
	}

	error = read_feature_reports(gdata);
	if (error) {
		dev_err(&hdev->dev,
			"%s error reading feature reports\n",
			gdata->name);
		goto err_cleanup_input;
	}

	error = gcore_leds_probe(gdata, g19_led_cdevs,
				 ARRAY_SIZE(g19_led_cdevs));
	if (error) {
		dev_err(&hdev->dev, "%s error registering leds\n", gdata->name);
		goto err_cleanup_input;
	}

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

	error = sysfs_create_group(&(hdev->dev.kobj), &g19_attr_group);
	if (error) {
		dev_err(&hdev->dev,
			"%s failed to create sysfs group attributes\n",
			gdata->name);
		goto err_cleanup_gfb;
	}

	wait_ready(gdata);

	/*
	 * Clear the LEDs
	 */
	g19data->backlight_rgb[0] = G19_DEFAULT_RED;
	g19data->backlight_rgb[1] = G19_DEFAULT_GREEN;
	g19data->backlight_rgb[2] = G19_DEFAULT_BLUE;
	g19data->screen_bl = G19_DEFAULT_BRIGHTNESS;

	g19_led_bl_send(hdev);
	g19_led_mbtns_send(hdev);
	g19_led_screen_bl_send(hdev);

	send_finalize_report(gdata);

	error = g19_ep1_read(hdev);
	if (error) {
		dev_err(&hdev->dev, "%s failed to read ep1\n", gdata->name);
		goto err_cleanup_sysfs;
	}

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

	/* Everything went well */
	return 0;

err_cleanup_sysfs:
	sysfs_remove_group(&(hdev->dev.kobj), &g19_attr_group);

err_cleanup_gfb:
	gfb_remove(gdata->gfb_data);

err_cleanup_leds:
	gcore_leds_remove(gdata);

err_cleanup_input:
	gcore_input_remove(gdata);

err_cleanup_hid:
	gcore_hid_close(gdata);

err_cleanup_ep1_urb:
	usb_free_urb(g19data->ep1_urb);

err_cleanup_g19data:
	kfree(g19data);

err_cleanup_gdata:
	gcore_free_data(gdata);

err_no_cleanup:
	hid_set_drvdata(hdev, NULL);
	return error;
}
Esempio n. 21
0
static int zc_input_mapping(struct hid_device *hdev, struct hid_input *hi,
	struct hid_field *field, struct hid_usage *usage,
	unsigned long **bit, int *max)
{
	int i;
	struct zc_device *zc = hid_get_drvdata(hdev);
	zc->input_ep81 = hi->input;

	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
		return 0;

	dbg_hid("zynacron input mapping event [0x%x]\n",
		usage->hid & HID_USAGE);

	switch (usage->hid & HID_USAGE) {
	/* report 2 */
	case 0x10:
		zc_map_key_clear(KEY_MODE);
		break;
	case 0x30:
		zc_map_key_clear(KEY_SCREEN);
		break;
	case 0x70:
		zc_map_key_clear(KEY_INFO);
		break;
	/* report 3 */
	case 0x04:
		zc_map_key_clear(KEY_RADIO);
		break;
	/* report 4 */
	case 0x0d:
		zc_map_key_clear(KEY_PVR);
		break;
	case 0x25:
		zc_map_key_clear(KEY_TV);
		break;
	case 0x47:
		zc_map_key_clear(KEY_AUDIO);
		break;
	case 0x49:
		zc_map_key_clear(KEY_AUX);
		break;
	case 0x4a:
		zc_map_key_clear(KEY_VIDEO);
		break;
	case 0x48:
		zc_map_key_clear(KEY_DVD);
		break;
	case 0x24:
		zc_map_key_clear(KEY_MENU);
		break;
	case 0x32:
		zc_map_key_clear(KEY_TEXT);
		break;
	default:
		return 0;
	}

	for (i = 0; i < 4; i++)
		zc->last_key[i] = 0;

	return 1;
}
static int nvidia_raw_event(struct hid_device *hdev,
		struct hid_report *report, u8 *data, int size) {

	unsigned id;
	struct nvidia_tp_loc *loc =
		(struct nvidia_tp_loc *)hid_get_drvdata(hdev);
	u8 action;
	u16 x, y;
	int press = 0;
	int release = 0;
	signed short relx, rely;
	signed short relx_raw, rely_raw;

	if (!report)
		return 1;
	id = report->id;

	if (!loc)
		return 1;

	/* If not valid touch events, let generic driver to handle this */
	if (id != TOUCH_REPORT_ID)
		return 0;

	/* If driver is in disabled mode,
	 * don't report anything to generic
	 * driver
	 */
	if (loc->mode == DISABLED_MODE)
		return 1;

	action = (data[1] & TOUCH_ACTION_MASK) >> TOUCH_ACTION_SHFT;
	x = data[2];
	y = data[4];



	if (!loc->action && action)
		press = 1;
	else if (loc->action && !action)
		release = 1;
	else if (!loc->action && !action)
		return 1;/* Double release, don't do anything */

	relx_raw = x - loc->x;
	rely_raw = y - loc->y;

	relx = scale_rel(relx_raw, loc->speed, XSCALE);
	rely = scale_rel(rely_raw, (loc->speed), YSCALE);

	loc->action = action;

	dbg_hid("%u %u %u rel %d %d\n", action, x, y, (s8)relx, (s8)rely);

	loc->x = x;
	loc->y = y;
	if (!press) {
		/*
		 * Not a press event, we
		 * need to report it to input subsystem
		 *
		 * If driver is in absolute mode, report
		 * raw absolute data to generic driver
		 *
		 * If driver is in gesture mode, report
		 * raw relative data to generic driver
		 */
		if (loc->mode == ABSOLUTE_MODE) {
			if (loc->tp_size == 8) {
				data[2] = x & 0xff;
				data[3] = y & 0xff;
			}
			/* otherwise we don't need to do anything */
			return 0;
		} else if (loc->mode == GESTURE_MODE) {
			if (loc->tp_size == 8) {
				data[2] = relx_raw & 0xff;
				data[3] = rely_raw & 0xff;
			} else {
				data[2] = relx_raw & 0xff;
				data[3] = relx_raw >> 8;
				data[4] = rely_raw & 0xff;
				data[5] = rely_raw >> 8;
			}
			if (release)
				loc->release = 1;
			else
				loc->release = 0;
			return 0;
		} else {
			if (loc->tp_size == 8) {
				data[2] = relx & 0xff;
				data[3] = rely & 0xff;
			} else {
				data[2] = relx & 0xff;
				data[3] = relx >> 8;
				data[4] = rely & 0xff;
				data[5] = rely >> 8;
			}
			return 0;
		}
	} else {
Esempio n. 23
0
static int logi_dj_ll_open(struct hid_device *hid)
{
	dbg_hid("%s:%s\n", __func__, hid->phys);
	return 0;

}
static void delayedwork_callback(struct work_struct *work)
{
	struct dj_receiver_dev *djrcv_dev =
		container_of(work, struct dj_receiver_dev, work);

	struct dj_report dj_report;
	unsigned long flags;
	int count;
	int retval;

	dbg_hid("%s\n", __func__);

	spin_lock_irqsave(&djrcv_dev->lock, flags);

	count = kfifo_out(&djrcv_dev->notif_fifo, &dj_report,
				sizeof(struct dj_report));

	if (count != sizeof(struct dj_report)) {
		dev_err(&djrcv_dev->hdev->dev, "%s: workitem triggered without "
			"notifications available\n", __func__);
		spin_unlock_irqrestore(&djrcv_dev->lock, flags);
		return;
	}

	if (!kfifo_is_empty(&djrcv_dev->notif_fifo)) {
		if (schedule_work(&djrcv_dev->work) == 0) {
			dbg_hid("%s: did not schedule the work item, was "
				"already queued\n", __func__);
		}
	}

	spin_unlock_irqrestore(&djrcv_dev->lock, flags);

	switch (dj_report.report_type) {
	case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
		logi_dj_recv_add_djhid_device(djrcv_dev, &dj_report);
		break;
	case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
		logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report);
		break;
	default:
	/* A normal report (i. e. not belonging to a pair/unpair notification)
	 * arriving here, means that the report arrived but we did not have a
	 * paired dj_device associated to the report's device_index, this
	 * means that the original "device paired" notification corresponding
	 * to this dj_device never arrived to this driver. The reason is that
	 * hid-core discards all packets coming from a device while probe() is
	 * executing. */
	if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) {
		/* ok, we don't know the device, just re-ask the
		 * receiver for the list of connected devices. */
		retval = logi_dj_recv_query_paired_devices(djrcv_dev);
		if (!retval) {
			/* everything went fine, so just leave */
			break;
		}
		dev_err(&djrcv_dev->hdev->dev,
			"%s:logi_dj_recv_query_paired_devices "
			"error:%d\n", __func__, retval);
		}
		dbg_hid("%s: unexpected report type\n", __func__);
	}
}
Esempio n. 25
0
static int logi_dj_ll_parse(struct hid_device *hid)
{
	struct dj_device *djdev = hid->driver_data;
	int retval;

	dbg_hid("%s\n", __func__);

	djdev->hdev->version = 0x0111;
	djdev->hdev->country = 0x00;

	if (djdev->reports_supported & STD_KEYBOARD) {
		dbg_hid("%s: sending a kbd descriptor, reports_supported: %x\n",
			__func__, djdev->reports_supported);
		retval = hid_parse_report(hid,
					  (u8 *) kbd_descriptor,
					  sizeof(kbd_descriptor));
		if (retval) {
			dbg_hid("%s: sending a kbd descriptor, hid_parse failed"
				" error: %d\n", __func__, retval);
			return retval;
		}
	}

	if (djdev->reports_supported & STD_MOUSE) {
		dbg_hid("%s: sending a mouse descriptor, reports_supported: "
			"%x\n", __func__, djdev->reports_supported);
		retval = hid_parse_report(hid,
					  (u8 *) mse_descriptor,
					  sizeof(mse_descriptor));
		if (retval) {
			dbg_hid("%s: sending a mouse descriptor, hid_parse "
				"failed error: %d\n", __func__, retval);
			return retval;
		}
	}

	if (djdev->reports_supported & MULTIMEDIA) {
		dbg_hid("%s: sending a multimedia report descriptor: %x\n",
			__func__, djdev->reports_supported);
		retval = hid_parse_report(hid,
					  (u8 *) consumer_descriptor,
					  sizeof(consumer_descriptor));
		if (retval) {
			dbg_hid("%s: sending a consumer_descriptor, hid_parse "
				"failed error: %d\n", __func__, retval);
			return retval;
		}
	}

	if (djdev->reports_supported & POWER_KEYS) {
		dbg_hid("%s: sending a power keys report descriptor: %x\n",
			__func__, djdev->reports_supported);
		retval = hid_parse_report(hid,
					  (u8 *) syscontrol_descriptor,
					  sizeof(syscontrol_descriptor));
		if (retval) {
			dbg_hid("%s: sending a syscontrol_descriptor, "
				"hid_parse failed error: %d\n",
				__func__, retval);
			return retval;
		}
	}

	if (djdev->reports_supported & MEDIA_CENTER) {
		dbg_hid("%s: sending a media center report descriptor: %x\n",
			__func__, djdev->reports_supported);
		retval = hid_parse_report(hid,
					  (u8 *) media_descriptor,
					  sizeof(media_descriptor));
		if (retval) {
			dbg_hid("%s: sending a media_descriptor, hid_parse "
				"failed error: %d\n", __func__, retval);
			return retval;
		}
	}

	if (djdev->reports_supported & KBD_LEDS) {
		dbg_hid("%s: need to send kbd leds report descriptor: %x\n",
			__func__, djdev->reports_supported);
	}

	return 0;
}
static int logi_dj_probe(struct hid_device *hdev,
			 const struct hid_device_id *id)
{
	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
	struct dj_receiver_dev *djrcv_dev;
	int retval;

	if (is_dj_device((struct dj_device *)hdev->driver_data))
		return -ENODEV;

	dbg_hid("%s called for ifnum %d\n", __func__,
		intf->cur_altsetting->desc.bInterfaceNumber);

	if (intf->cur_altsetting->desc.bInterfaceNumber !=
	    LOGITECH_DJ_INTERFACE_NUMBER) {
		dbg_hid("%s: ignoring ifnum %d\n", __func__,
			intf->cur_altsetting->desc.bInterfaceNumber);
		return -ENODEV;
	}

	

	djrcv_dev = kzalloc(sizeof(struct dj_receiver_dev), GFP_KERNEL);
	if (!djrcv_dev) {
		dev_err(&hdev->dev,
			"%s:failed allocating dj_receiver_dev\n", __func__);
		return -ENOMEM;
	}
	djrcv_dev->hdev = hdev;
	INIT_WORK(&djrcv_dev->work, delayedwork_callback);
	spin_lock_init(&djrcv_dev->lock);
	if (kfifo_alloc(&djrcv_dev->notif_fifo,
			DJ_MAX_NUMBER_NOTIFICATIONS * sizeof(struct dj_report),
			GFP_KERNEL)) {
		dev_err(&hdev->dev,
			"%s:failed allocating notif_fifo\n", __func__);
		kfree(djrcv_dev);
		return -ENOMEM;
	}
	hid_set_drvdata(hdev, djrcv_dev);

	retval = hid_parse(hdev);
	if (retval) {
		dev_err(&hdev->dev,
			"%s:parse of interface 2 failed\n", __func__);
		goto hid_parse_fail;
	}

	retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
	if (retval) {
		dev_err(&hdev->dev,
			"%s:hid_hw_start returned error\n", __func__);
		goto hid_hw_start_fail;
	}

	retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
	if (retval < 0) {
		dev_err(&hdev->dev,
			"%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n",
			__func__, retval);
		goto switch_to_dj_mode_fail;
	}

	
	retval = hdev->ll_driver->open(hdev);
	if (retval < 0) {
		dev_err(&hdev->dev, "%s:hdev->ll_driver->open returned "
			"error:%d\n", __func__, retval);
		goto llopen_failed;
	}

	retval = logi_dj_recv_query_paired_devices(djrcv_dev);
	if (retval < 0) {
		dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices "
			"error:%d\n", __func__, retval);
		goto logi_dj_recv_query_paired_devices_failed;
	}

	return retval;

logi_dj_recv_query_paired_devices_failed:
	hdev->ll_driver->close(hdev);

llopen_failed:
switch_to_dj_mode_fail:
	hid_hw_stop(hdev);

hid_hw_start_fail:
hid_parse_fail:
	kfifo_free(&djrcv_dev->notif_fifo);
	kfree(djrcv_dev);
	hid_set_drvdata(hdev, NULL);
	return retval;

}
Esempio n. 27
0
static void logi_dj_ll_stop(struct hid_device *hid)
{
	dbg_hid("%s\n", __func__);
}
static int samsung_universal_kbd_input_mapping(struct hid_device *hdev,
	struct hid_input *hi, struct hid_field *field, struct hid_usage *usage,
	unsigned long **bit, int *max)
{
	if (!(HID_UP_CONSUMER == (usage->hid & HID_USAGE_PAGE) ||
			HID_UP_KEYBOARD == (usage->hid & HID_USAGE_PAGE)))
		return 0;

	dbg_hid("samsung wireless keyboard input mapping event [0x%x]\n",
		usage->hid & HID_USAGE);

	if (HID_UP_KEYBOARD == (usage->hid & HID_USAGE_PAGE)) {
		switch (usage->hid & HID_USAGE) {
		set_bit(EV_REP, hi->input->evbit);
		/* Only for UK keyboard */
		/* key found */
		case 0x32: samsung_kbd_mouse_map_key_clear(KEY_BACKSLASH); break;
		case 0x64: samsung_kbd_mouse_map_key_clear(KEY_102ND); break;
		/* Only for BR keyboard */
		case 0x87: samsung_kbd_mouse_map_key_clear(KEY_RO); break;
		default:
			return 0;
		}
	}

	if (HID_UP_CONSUMER == (usage->hid & HID_USAGE_PAGE)) {
		switch (usage->hid & HID_USAGE) {
		/* report 2 */
		/* MENU */
		case 0x040: samsung_kbd_mouse_map_key_clear(KEY_MENU); break;
		case 0x18a: samsung_kbd_mouse_map_key_clear(KEY_MAIL); break;
		case 0x196: samsung_kbd_mouse_map_key_clear(KEY_WWW); break;
		case 0x19e: samsung_kbd_mouse_map_key_clear(KEY_SCREENLOCK); break;
		case 0x221: samsung_kbd_mouse_map_key_clear(KEY_SEARCH); break;
		case 0x223: samsung_kbd_mouse_map_key_clear(KEY_HOMEPAGE); break;
		/* RECENTAPPS */
		case 0x301: samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY1); break;
		/* APPLICATION */
		case 0x302: samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY2); break;
		/* Voice search */
		case 0x305: samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY4); break;
		/* QPANEL on/off */
		case 0x306: samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY5); break;
		/* SIP on/off */
		case 0x307: samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY3); break;
		/* LANG */
		case 0x308: samsung_kbd_mouse_map_key_clear(KEY_LANGUAGE); break;
		case 0x30a: samsung_kbd_mouse_map_key_clear(KEY_BRIGHTNESSDOWN); break;
		case 0x070: samsung_kbd_mouse_map_key_clear(KEY_BRIGHTNESSDOWN); break;
		case 0x30b: samsung_kbd_mouse_map_key_clear(KEY_BRIGHTNESSUP); break;
		case 0x06f: samsung_kbd_mouse_map_key_clear(KEY_BRIGHTNESSUP); break;
		/* S-Finder */
		case 0x304: samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY7); break;
		/* Screen Capture */
		case 0x303: samsung_kbd_mouse_map_key_clear(KEY_SYSRQ); break;
		/* Multi Window */
		case 0x309: samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY9); break;
		/* TouchPad ON for TabS2*/
		case 0x310: samsung_kbd_mouse_map_key_clear(KEY_TOUCHPAD_ON); break;
		/* TouchPad OFF for TabS2*/
		case 0x311: samsung_kbd_mouse_map_key_clear(KEY_TOUCHPAD_OFF); break;
		default:
			return 0;
		}
	}

	return 1;
}
Esempio n. 29
0
static int logi_dj_probe(struct hid_device *hdev,
			 const struct hid_device_id *id)
{
	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
	struct dj_receiver_dev *djrcv_dev;
	int retval;

	if (is_dj_device((struct dj_device *)hdev->driver_data))
		return -ENODEV;

	dbg_hid("%s called for ifnum %d\n", __func__,
		intf->cur_altsetting->desc.bInterfaceNumber);

	/* Ignore interfaces 0 and 1, they will not carry any data, dont create
	 * any hid_device for them */
	if (intf->cur_altsetting->desc.bInterfaceNumber !=
	    LOGITECH_DJ_INTERFACE_NUMBER) {
		dbg_hid("%s: ignoring ifnum %d\n", __func__,
			intf->cur_altsetting->desc.bInterfaceNumber);
		return -ENODEV;
	}

	/* Treat interface 2 */

	djrcv_dev = kzalloc(sizeof(struct dj_receiver_dev), GFP_KERNEL);
	if (!djrcv_dev) {
		dev_err(&hdev->dev,
			"%s:failed allocating dj_receiver_dev\n", __func__);
		return -ENOMEM;
	}
	djrcv_dev->hdev = hdev;
	INIT_WORK(&djrcv_dev->work, delayedwork_callback);
	spin_lock_init(&djrcv_dev->lock);
	if (kfifo_alloc(&djrcv_dev->notif_fifo,
			DJ_MAX_NUMBER_NOTIFICATIONS * sizeof(struct dj_report),
			GFP_KERNEL)) {
		dev_err(&hdev->dev,
			"%s:failed allocating notif_fifo\n", __func__);
		kfree(djrcv_dev);
		return -ENOMEM;
	}
	hid_set_drvdata(hdev, djrcv_dev);

	/* Call  to usbhid to fetch the HID descriptors of interface 2 and
	 * subsequently call to the hid/hid-core to parse the fetched
	 * descriptors, this will in turn create the hidraw and hiddev nodes
	 * for interface 2 of the receiver */
	retval = hid_parse(hdev);
	if (retval) {
		dev_err(&hdev->dev,
			"%s:parse of interface 2 failed\n", __func__);
		goto hid_parse_fail;
	}

	/* Starts the usb device and connects to upper interfaces hiddev and
	 * hidraw */
	retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
	if (retval) {
		dev_err(&hdev->dev,
			"%s:hid_hw_start returned error\n", __func__);
		goto hid_hw_start_fail;
	}

	retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
	if (retval < 0) {
		dev_err(&hdev->dev,
			"%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n",
			__func__, retval);
		goto switch_to_dj_mode_fail;
	}

	/* This is enabling the polling urb on the IN endpoint */
	retval = hdev->ll_driver->open(hdev);
	if (retval < 0) {
		dev_err(&hdev->dev, "%s:hdev->ll_driver->open returned "
			"error:%d\n", __func__, retval);
		goto llopen_failed;
	}

	retval = logi_dj_recv_query_paired_devices(djrcv_dev);
	if (retval < 0) {
		dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices "
			"error:%d\n", __func__, retval);
		goto logi_dj_recv_query_paired_devices_failed;
	}

	return retval;

logi_dj_recv_query_paired_devices_failed:
	hdev->ll_driver->close(hdev);

llopen_failed:
switch_to_dj_mode_fail:
	hid_hw_stop(hdev);

hid_hw_start_fail:
hid_parse_fail:
	kfifo_free(&djrcv_dev->notif_fifo);
	kfree(djrcv_dev);
	hid_set_drvdata(hdev, NULL);
	return retval;

}
Esempio n. 30
0
static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
{
	switch (item->tag) {

		case HID_GLOBAL_ITEM_TAG_PUSH:

			if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
				dbg_hid("global enviroment stack overflow\n");
				return -1;
			}

			memcpy(parser->global_stack + parser->global_stack_ptr++,
				&parser->global, sizeof(struct hid_global));
			return 0;

		case HID_GLOBAL_ITEM_TAG_POP:

			if (!parser->global_stack_ptr) {
				dbg_hid("global enviroment stack underflow\n");
				return -1;
			}

			memcpy(&parser->global, parser->global_stack + --parser->global_stack_ptr,
				sizeof(struct hid_global));
			return 0;

		case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
			parser->global.usage_page = item_udata(item);
			return 0;

		case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:
			parser->global.logical_minimum = item_sdata(item);
			return 0;

		case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
			if (parser->global.logical_minimum < 0)
				parser->global.logical_maximum = item_sdata(item);
			else
				parser->global.logical_maximum = item_udata(item);
			return 0;

		case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
			parser->global.physical_minimum = item_sdata(item);
			return 0;

		case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
			if (parser->global.physical_minimum < 0)
				parser->global.physical_maximum = item_sdata(item);
			else
				parser->global.physical_maximum = item_udata(item);
			return 0;

		case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
			parser->global.unit_exponent = item_sdata(item);
			return 0;

		case HID_GLOBAL_ITEM_TAG_UNIT:
			parser->global.unit = item_udata(item);
			return 0;

		case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
			if ((parser->global.report_size = item_udata(item)) > 32) {
				dbg_hid("invalid report_size %d\n", parser->global.report_size);
				return -1;
			}
			return 0;

		case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
			if ((parser->global.report_count = item_udata(item)) > HID_MAX_USAGES) {
				dbg_hid("invalid report_count %d\n", parser->global.report_count);
				return -1;
			}
			return 0;

		case HID_GLOBAL_ITEM_TAG_REPORT_ID:
			if ((parser->global.report_id = item_udata(item)) == 0) {
				dbg_hid("report_id 0 is invalid\n");
				return -1;
			}
			return 0;

		default:
			dbg_hid("unknown global tag 0x%x\n", item->tag);
			return -1;
	}
}