Re: [PATCH 1/4] hid-multitouch: support for PixCir-based panels

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




Le 14 oct. 10 à 11:38, Henrik Rydberg a écrit :

+	bool valid;	/* did we just get valid contact data for this slot? */
+	bool prev_valid;/* was this slot previously valid/active? */


I do think these should be named "touch" or "prox" rather than "valid". The latter term is used in many drivers no represent "not null", and mixing the
semantics with proximity is best avoided.


Actually, the mix of semantics exists because of the mismatch between the (static) HID protocol and the (dynamic) data it transports. Most of the time, TipSwitch=0 occurs when we get placeholder data: there is nothing to report at all, but the message format imposes that something is sent. And sometimes (rarely), we get TipSwitch=0 because a finger has been released. We are lucky that we can handle the two situations in the same way.

See below for a discussion of how we can solve this.


+	bool curvalid; 		/* is the current contact valid? */
+	__u16 curcontactid; 	/* ContactID of the current contact */
+ __u16 curx, cury, curp; /* other attributes of the current contact */


Could be a struct mt_slot instead.

Well, it's not *exactly* the same data. Especially if, as I'm beginning to understand thanks to one of your later comments, there is a difference in the semantics of 'valid' between slots and the current contact as read in the HID message:
 - my above discussion applies to the current contact
- and in slots, this information gets filtered to become actual proximity information.

This would give:
 - curvalid in mt_data
- touch in mt_slot (and not prox, because prox will mean something else in devices that have hover detection)



+};
+
+struct mt_class {
+	int (*compute_slot)(struct mt_device *);
+	__u8 maxcontacts;
+ __s8 inputmode; /* InputMode HID feature number, -1 if non- existent */


It would be nice to have additional information here, like signal- to-noise ratio.

I thought you would say that. My answer was ready: I left it to you to add it afterwards :-)


+/* contact data that only some devices report */
+#define PRESSURE 	(1 << 0)
+#define SIZE		(1 << 1)


The names here are a bit too general, IMO.

I thought so too, but was too lazy to imagine something else and decided that what the heck, these are private names. Any suggestion?


+
+/*
+ * these device-dependent functions determine what slot corresponds
+ * to a valid contact that was just read.
+ */
+
+static int slot_from_contactid(struct mt_device *td)
+{
+	return td->curcontactid;
+}


I suppose this one is meant to loop over available slots for some implementations.

See the following patches for examples. So far, looping was not necessary.


+
+struct mt_class mt_classes[] = {
+	/* DUAL1 */		{ slot_from_contactid, 2, -1 },
+};


Off placement of comment.


Please, please don't force me to add a useless field to the struct so as to make sure that the type is read before the data :-) Oh well...



A helper function that simplifies the repeated usage of input_set_abs_params()
would be nice.

A local variable for hi->input would be nice.

If we want to support fuzz, and do not want to add it to the hid structure (because it is not available in the reports), we should consider setting up the input_dev completely within this driver, as done in the 3M and egalax drivers.

Yes, my idea was that you'd like to take over and introduce the kind of work you are doing for 3M and eGalax. As for the helper function and hi->input, hey, I just copied your code :-)


+		if (slotnum >= 0 && slotnum <= td->mtclass->maxcontacts - 1) {


The returned slotnum should always be valid, so this test is redundant.

Nope. See Cypress devices.


+			slot = td->slots + slotnum;
+
+			slot->valid = true;


Rather that setting valid here, it should simply be the proximity (touch) state.
All slot data in our buffer is actually valid at all times.

+			slot->x = td->curx;
+			slot->y = td->cury;
+			slot->p = td->curp;


Using a temporary slot struct for curx etc would be nice.

+		}
+	}
+	td->curcontact++;

See my previous discussion on curvalid vs valid/prox/touch.


I think it is unnecessary to have both a slot number and a curcontact value. Either the firmware reports the slot itself, or it reports a contact id that needs to be looked up from the list of slots. In neither case does anything but
slot number and contact id enter the equation.

See the following patches for examples of this being wrong.



+			if (s->prev_valid) {
+				input_mt_slot(input, i);	


The logic is a bit easier if input_mt_slot() appears once before all the branching. If nothing else is emitted, the input core does not emit the slot event.

I'm not a big fan of this kind of 'blind pass'. Jiri?




How about touch_major, touch_minor and orientation here?

I have no device available to test this at the moment. What I had in mind was to add them when we add support for a device that has them.


+		s->prev_valid = true;
+		s->valid = false;


Changing the touch state to false here seems wrong.

But it's necessary, believe me. There are devices for which we don't get a chance to change it to false when the finger is released. Setting it to false every time and resetting it to true when we get confirmation that the contact is still alive is the failsafe way of doing things.


+		input_event(input, EV_KEY, BTN_TOUCH, 1);
+		input_event(input, EV_ABS, ABS_X, oldest->x);
+		input_event(input, EV_ABS, ABS_Y, oldest->y);


Pressure here as well.

Oops.


+	} else {
+		input_event(input, EV_KEY, BTN_TOUCH, 0);
+	}
+
+	input_sync(input);
+	td->curcontact = 0;


The curcontact semantics could be clearer, as noted elsewhere.

Another name, perhaps? The bottom line is that we need to keep trace of the rank of the contact in the current message.


+}
+
+
+
+static int mt_event(struct hid_device *hid, struct hid_field *field,
+				struct hid_usage *usage, __s32 value)
+{
+	struct mt_device *td = hid_get_drvdata(hid);
+
+	if (hid->claimed & HID_CLAIMED_INPUT) {
+		struct input_dev *input = field->hidinput->input;
+		switch (usage->hid) {
+		case HID_DG_INRANGE:


This one is used to report the validity of the current reported contact on many
devices. Maybe all, even?

Actually, only on a minority of device last time I checked.


+		case HID_DG_TIPSWITCH:
+			td->curvalid = value;


This is really the touch state, the proximity.

I wish.


+			break;
+		case HID_DG_CONFIDENCE:
+			break;
+		case HID_DG_CONTACTID:
+			td->curcontactid = value;


Here is where I would but the conversion to slot id. And it should definitely be
guarded so that it is always a valid index.

I'll pay you a beer if you find how to make this work for all devices :-)


+		case HID_GD_Y:
+			td->cury = value;
+			/* works for devices where Y is last in a contact */
+			mt_complete_slot(td);


Relying on a particular field to come last seems non-generic. Since there is already a bit field started for various features of the device, why not complete that list with all data reported per contact, and use it know when a contact is
complete? Something like "recorded_mask == expected_mask".

What I had in mind was that the information is available in lower level code, and that we could handle this when switching to a raw hid device. Otherwise, we'd just be reinventing the wheel, that is rebuilding information that's already there. Same for HID_CONTACTCOUNT below: I use it because it marks the end of messages on most devices, but there should be a better way of knowing that we are at the end of a message.



+			break;
+		case HID_DG_CONTACTCOUNT:
+			/*
+			 * works for devices where contact count is
+			 * the last field in a message
+			 */
+			if (value)
+				td->maxcontact = value - 1;


The usage of maxcontact is a bit odd. Perhaps there should be a "maxslot" which
never changes, and a "contactcount" which starts at zero.

maxcontact works with curcontact. I found the name 'contactcount' confusing, because in HID it means something else. Still looking for a better name for 'curcontact'.


+			if (td->curcontact > td->maxcontact)
+				mt_emit_event(td, input);


So curcontact is here a counter, which implements the logic found in the 3M, with partial reports combining into a single one. Maybe we need a counter, or
maybe we can get by using the CONTACTID field.



Yes, curcontact is a counter. And we also need it for computing the slot id sometimes.


+
+#if 0
+	/*
+ * todo: activate this as soon as the patch where the quirk below + * is defined is commited. This will allow the driver to correctly + * support devices that emit events over several HID messages.
+         */
+	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
+#endif


This code should be active.

Then it won't compile in 2.6.36-rc7.


+
+	td = kzalloc(sizeof(struct mt_device), GFP_KERNEL);
+	if (!td) {
+		dev_err(&hdev->dev, "cannot allocate multitouch data\n");
+		return -ENOMEM;
+	}
+	td->mtclass = mt_classes + id->driver_data;
+ td->slots = kzalloc(td->mtclass->maxcontacts * sizeof(struct mt_slot),
+				GFP_KERNEL);


Allocating slots in the same range as mt_device would be nice.

Agreed.


+		struct hid_report_enum *re = hdev->report_enum
+						+ HID_FEATURE_REPORT;


&hdev->report_enum[HID_FEATURE_REPORT]

Won't fit on one line, then. Visually, it gets worse. Someone else, an opinion?



That's it for now :-)


Then, on to patches 2, 3 and 4 :-)

St.

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux