Adding media_device support including the serial number. Signed-off-by: Dean Anderson <dean@xxxxxxxxxxxx> --- drivers/media/usb/s2255/s2255drv.c | 45 ++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) 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: -- 2.30.2