media-ctl: subdev: add Y8 format.
[media-ctl.git] / subdev.c
1 /*
2  * Media controller test application
3  *
4  * Copyright (C) 2010 Ideas on board SPRL <laurent.pinchart@ideasonboard.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  */
19
20 #include <sys/ioctl.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 #include <linux/v4l2-subdev.h>
31
32 #include "media.h"
33 #include "subdev.h"
34 #include "tools.h"
35
36 static struct {
37         const char *name;
38         enum v4l2_mbus_pixelcode code;
39 } mbus_formats[] = {
40         { "Y8", V4L2_MBUS_FMT_Y8_1X8},
41         { "YUYV", V4L2_MBUS_FMT_YUYV8_1X16 },
42         { "UYVY", V4L2_MBUS_FMT_UYVY8_1X16 },
43         { "SGRBG10", V4L2_MBUS_FMT_SGRBG10_1X10 },
44         { "SGRBG10_DPCM8", V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 },
45 };
46
47 const char *pixelcode_to_string(enum v4l2_mbus_pixelcode code)
48 {
49         unsigned int i;
50
51         for (i = 0; i < ARRAY_SIZE(mbus_formats); ++i) {
52                 if (mbus_formats[i].code == code)
53                         return mbus_formats[i].name;
54         }
55
56         return "unknown";
57 }
58
59 enum v4l2_mbus_pixelcode string_to_pixelcode(const char *string,
60                                              unsigned int length)
61 {
62         unsigned int i;
63
64         for (i = 0; i < ARRAY_SIZE(mbus_formats); ++i) {
65                 if (strncmp(mbus_formats[i].name, string, length) == 0)
66                         break;
67         }
68
69         if (i == ARRAY_SIZE(mbus_formats))
70                 return (enum v4l2_mbus_pixelcode)-1;
71
72         return mbus_formats[i].code;
73 }
74
75 static int v4l2_subdev_open(struct media_entity *entity)
76 {
77         if (entity->fd != -1)
78                 return 0;
79
80         entity->fd = open(entity->devname, O_RDWR);
81         if (entity->fd == -1) {
82                 printf("%s: Failed to open subdev device node %s\n", __func__,
83                         entity->devname);
84                 return -errno;
85         }
86
87         return 0;
88 }
89
90 int v4l2_subdev_get_format(struct media_entity *entity,
91         struct v4l2_mbus_framefmt *format, unsigned int pad,
92         enum v4l2_subdev_format_whence which)
93 {
94         struct v4l2_subdev_format fmt;
95         int ret;
96
97         ret = v4l2_subdev_open(entity);
98         if (ret < 0)
99                 return ret;
100
101         memset(&fmt, 0, sizeof(fmt));
102         fmt.pad = pad;
103         fmt.which = which;
104
105         ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_FMT, &fmt);
106         if (ret < 0)
107                 return -errno;
108
109         *format = fmt.format;
110         return 0;
111 }
112
113 int v4l2_subdev_set_format(struct media_entity *entity,
114         struct v4l2_mbus_framefmt *format, unsigned int pad,
115         enum v4l2_subdev_format_whence which)
116 {
117         struct v4l2_subdev_format fmt;
118         int ret;
119
120         ret = v4l2_subdev_open(entity);
121         if (ret < 0)
122                 return ret;
123
124         memset(&fmt, 0, sizeof(fmt));
125         fmt.pad = pad;
126         fmt.which = which;
127         fmt.format = *format;
128
129         ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_FMT, &fmt);
130         if (ret < 0)
131                 return -errno;
132
133         *format = fmt.format;
134         return 0;
135 }
136
137 int v4l2_subdev_get_crop(struct media_entity *entity, struct v4l2_rect *rect,
138                          unsigned int pad, enum v4l2_subdev_format_whence which)
139 {
140         struct v4l2_subdev_crop crop;
141         int ret;
142
143         ret = v4l2_subdev_open(entity);
144         if (ret < 0)
145                 return ret;
146
147         memset(&crop, 0, sizeof(crop));
148         crop.pad = pad;
149         crop.which = which;
150
151         ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_CROP, &crop);
152         if (ret < 0)
153                 return -errno;
154
155         *rect = crop.rect;
156         return 0;
157 }
158
159 int v4l2_subdev_set_crop(struct media_entity *entity, struct v4l2_rect *rect,
160                          unsigned int pad, enum v4l2_subdev_format_whence which)
161 {
162         struct v4l2_subdev_crop crop;
163         int ret;
164
165         ret = v4l2_subdev_open(entity);
166         if (ret < 0)
167                 return ret;
168
169         memset(&crop, 0, sizeof(crop));
170         crop.pad = pad;
171         crop.which = which;
172         crop.rect = *rect;
173
174         ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_CROP, &crop);
175         if (ret < 0)
176                 return -errno;
177
178         *rect = crop.rect;
179         return 0;
180 }
181
182 int v4l2_subdev_set_frame_interval(struct media_entity *entity,
183                                    struct v4l2_fract *interval)
184 {
185         struct v4l2_subdev_frame_interval ival;
186         int ret;
187
188         ret = v4l2_subdev_open(entity);
189         if (ret < 0)
190                 return ret;
191
192         memset(&ival, 0, sizeof(ival));
193         ival.interval = *interval;
194
195         ret = ioctl(entity->fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, &ival);
196         if (ret < 0)
197                 return -errno;
198
199         *interval = ival.interval;
200         return 0;
201 }
202
203 void v4l2_subdev_print_format(struct media_entity *entity,
204         unsigned int pad, enum v4l2_subdev_format_whence which)
205 {
206         struct v4l2_mbus_framefmt format;
207         struct v4l2_rect rect;
208         int ret;
209
210         ret = v4l2_subdev_get_format(entity, &format, pad, which);
211         if (ret != 0)
212                 return;
213
214         printf("[%s %ux%u", pixelcode_to_string(format.code),
215                format.width, format.height);
216
217         ret = v4l2_subdev_get_crop(entity, &rect, pad, which);
218         if (ret == 0)
219                 printf(" (%u,%u)/%ux%u", rect.left, rect.top,
220                        rect.width, rect.height);
221         printf("]");
222 }
223