V4L/DVB (10237): pvrusb2: Generate a device-unique identifier

Implement a new internal function to create a string device
identifier.  This ID stays with the specific device, making it useful
to user space to identify specific devices.  We use the serial number
if available; otherwise we give up and just spit out a unit/instance ID.

Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
index de7ee72..d96f0f5 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -195,8 +195,20 @@
 	struct mutex big_lock_mutex;
 	int big_lock_held;  /* For debugging */
 
+	/* This is a simple string which identifies the instance of this
+	   driver.  It is unique within the set of existing devices, but
+	   there is no attempt to keep the name consistent with the same
+	   physical device each time. */
 	char name[32];
 
+	/* This is a simple string which identifies the physical device
+	   instance itself - if possible.  (If not possible, then it is
+	   based on the specific driver instance, similar to name above.)
+	   The idea here is that userspace might hopefully be able to use
+	   this recognize specific tuners.  It will encode a serial number,
+	   if available. */
+	char identifier[32];
+
 	/* I2C stuff */
 	struct i2c_adapter i2c_adap;
 	struct i2c_algorithm i2c_algo;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index fa304e5..ac5dad0 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -1283,6 +1283,12 @@
 }
 
 
+const char *pvr2_hdw_get_device_identifier(struct pvr2_hdw *hdw)
+{
+	return hdw->identifier;
+}
+
+
 unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw)
 {
 	return hdw->freqSelector ? hdw->freqValTelevision : hdw->freqValRadio;
@@ -2024,6 +2030,19 @@
 		hdw->std_mask_eeprom = V4L2_STD_ALL;
 	}
 
+	if (hdw->serial_number) {
+		idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1,
+				"sn-%lu", hdw->serial_number);
+	} else if (hdw->unit_number >= 0) {
+		idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1,
+				"unit-%c",
+				hdw->unit_number + 'a');
+	} else {
+		idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1,
+				"unit-??");
+	}
+	hdw->identifier[idx] = 0;
+
 	pvr2_hdw_setup_std(hdw);
 
 	if (!get_default_tuner_type(hdw)) {
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index 1b4fec3..a40f845 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -132,6 +132,9 @@
 /* Retrieve bus location info of device */
 const char *pvr2_hdw_get_bus_info(struct pvr2_hdw *);
 
+/* Retrieve per-instance string identifier for this specific device */
+const char *pvr2_hdw_get_device_identifier(struct pvr2_hdw *);
+
 /* Called when hardware has been unplugged */
 void pvr2_hdw_disconnect(struct pvr2_hdw *);