diff mbox series

[PATCHv4] media: usb: s2255: media_device and serial number added

Message ID 20240123201212.23896-1-dean@sensoray.com (mailing list archive)
State New
Headers show
Series [PATCHv4] media: usb: s2255: media_device and serial number added | expand

Commit Message

Dean Anderson Jan. 23, 2024, 8:12 p.m. UTC
Adding media_device support including the serial number.

Signed-off-by: Dean Anderson <dean@sensoray.com>

---
 drivers/media/usb/s2255/s2255drv.c | 45 ++++++++++++++++++++++++++++--
 1 file changed, 43 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index 3c2627712fe9..2319cf93e726 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -60,6 +60,7 @@ 
 #define S2255_MIN_BUFS          2
 #define S2255_SETMODE_TIMEOUT   500
 #define S2255_VIDSTATUS_TIMEOUT 350
+#define S2255_MARKER_SERIALNUM	cpu_to_le32(0xDDCCBBAAL)
 #define S2255_MARKER_FRAME	cpu_to_le32(0x2255DA4AL)
 #define S2255_MARKER_RESPONSE	cpu_to_le32(0x2255ACACL)
 #define S2255_RESPONSE_SETMODE  cpu_to_le32(0x01)
@@ -245,6 +246,7 @@  struct s2255_vc {
 
 
 struct s2255_dev {
+	struct media_device     mdev;
 	struct s2255_vc         vc[MAX_CHANNELS];
 	struct v4l2_device      v4l2_dev;
 	atomic_t                num_channels;
@@ -323,6 +325,7 @@  struct s2255_buffer {
 #define S2255_V4L2_YC_ON  1
 #define S2255_V4L2_YC_OFF 0
 #define V4L2_CID_S2255_COLORFILTER (V4L2_CID_USER_S2255_BASE + 0)
+#define V4L2_CID_S2255_SERIALNUM (V4L2_CID_USER_S2255_BASE + 1)
 
 /* frame prefix size (sent once every frame) */
 #define PREFIX_SIZE		512
@@ -1232,6 +1235,29 @@  static int s2255_s_ctrl(struct v4l2_ctrl *ctrl)
 	return 0;
 }
 
+/*
+ * serial number is not used in usb device descriptors.
+ * returns serial number from device, 0 if none found.
+ */
+
+static int s2255_g_serialnum(struct s2255_dev *dev, u32 *serial)
+{
+#define S2255_I2C_SIZE     16
+#define S2255_I2C_SERIALNUM 0xa2
+#define S2255_I2C_SERIALNUM_OFFSET 0x1ff0
+#define S2255_VENDOR_READREG 0x22
+	u8 buf[16];
+	int rc;
+
+	rc = s2255_vendor_req(dev, S2255_VENDOR_READREG, S2255_I2C_SERIALNUM_OFFSET,
+			      S2255_I2C_SERIALNUM >> 1, buf, S2255_I2C_SIZE, 0);
+	if (rc != S2255_I2C_SIZE || *(__le32 *)buf != S2255_MARKER_SERIALNUM)
+		return -EINVAL;
+	/* Unlike the other parameters, the serial number is sent as big endian */
+	*serial = be32_to_cpu(*((__be32 *)buf + 3));
+	return 0;
+}
+
 static int vidioc_g_jpegcomp(struct file *file, void *priv,
 			 struct v4l2_jpegcompression *jc)
 {
@@ -1500,6 +1526,9 @@  static void s2255_destroy(struct s2255_dev *dev)
 	s2255_reset_dsppower(dev);
 	mutex_destroy(&dev->lock);
 	usb_put_dev(dev->udev);
+	if (media_devnode_is_registered(dev->mdev.devnode))
+		media_device_unregister(&dev->mdev);
+	media_device_cleanup(&dev->mdev);
 	v4l2_device_unregister(&dev->v4l2_dev);
 	kfree(dev->cmdbuf);
 	kfree(dev);
@@ -2206,14 +2235,13 @@  static int s2255_probe(struct usb_interface *interface,
 	int retval = -ENOMEM;
 	__le32 *pdata;
 	int fw_size;
-
+	u32 serialno;
 	/* allocate memory for our device state and initialize it to zero */
 	dev = kzalloc(sizeof(struct s2255_dev), GFP_KERNEL);
 	if (dev == NULL) {
 		s2255_dev_err(&interface->dev, "out of memory\n");
 		return -ENOMEM;
 	}
-
 	dev->cmdbuf = kzalloc(S2255_CMDBUF_SIZE, GFP_KERNEL);
 	if (dev->cmdbuf == NULL) {
 		s2255_dev_err(&interface->dev, "out of memory\n");
@@ -2237,6 +2265,15 @@  static int s2255_probe(struct usb_interface *interface,
 	dev_dbg(&interface->dev, "dev: %p, udev %p interface %p\n",
 		dev, dev->udev, interface);
 	dev->interface = interface;
+
+	dev->mdev.dev = &interface->dev;
+	strscpy(dev->mdev.model, "Sensoray Model 2255", sizeof(dev->mdev.model));
+	usb_make_path(dev->udev, dev->mdev.bus_info, sizeof(dev->mdev.bus_info));
+	dev->mdev.hw_revision = le16_to_cpu(dev->udev->descriptor.bcdDevice);
+	if (s2255_g_serialnum(dev, &serialno) == 0)
+		snprintf(dev->mdev.serial, sizeof(dev->mdev.serial), "%d", serialno);
+	media_device_init(&dev->mdev);
+	dev->v4l2_dev.mdev = &dev->mdev;
 	/* set up the endpoint information  */
 	iface_desc = interface->cur_altsetting;
 	dev_dbg(&interface->dev, "num EP: %d\n",
@@ -2311,6 +2348,10 @@  static int s2255_probe(struct usb_interface *interface,
 	retval = s2255_probe_v4l(dev);
 	if (retval)
 		goto errorBOARDINIT;
+
+	if (media_device_register(&dev->mdev) < 0)
+		goto errorBOARDINIT;
+
 	dev_info(&interface->dev, "Sensoray 2255 detected\n");
 	return 0;
 errorBOARDINIT: