Mercurial > hg > minimon
comparison minimon.c @ 10:078dc69945ad
working: libjpeg-turbo support, handle fb and monitor with different size
author | Peter Meerwald <pmeerw@pmeerw.net> |
---|---|
date | Sun, 15 May 2011 17:48:57 +0200 |
parents | bac8ed8d6eb9 |
children |
comparison
equal
deleted
inserted
replaced
9:c7af696b6221 | 10:078dc69945ad |
---|---|
1 #include <stdlib.h> | 1 #include <stdlib.h> |
2 #include <stdio.h> | 2 #include <stdio.h> |
3 #include <string.h> | 3 #include <string.h> |
4 #include <fcntl.h> | 4 #include <fcntl.h> |
5 #include <sys/ioctl.h> | |
6 #include <sys/mman.h> | |
5 #include <assert.h> | 7 #include <assert.h> |
6 #include "usb.h" | 8 #include "usb.h" |
9 | |
10 #include "linux/fb.h" | |
11 | |
12 #include "common.h" | |
7 | 13 |
8 static const char *progname = "minimon"; | 14 static const char *progname = "minimon"; |
9 | 15 |
10 static int need_switch = 0; | 16 static int need_switch = 0; |
11 static int have_idx = -1; | 17 static int have_idx = -1; |
110 } | 116 } |
111 | 117 |
112 return udev; | 118 return udev; |
113 } | 119 } |
114 | 120 |
115 static void send_jpeg(FILE *f, usb_dev_handle *udev) { | 121 static int send_jpg(jpg_buf_t *jpg_buf, usb_dev_handle *udev) { |
116 fseek(f, 0, SEEK_END); | |
117 int sz = ftell(f); | |
118 fseek(f, 0, SEEK_SET); | |
119 | |
120 #define URBBUF_MAX 0x20000 | 122 #define URBBUF_MAX 0x20000 |
121 char buf[URBBUF_MAX]; | 123 char buf[URBBUF_MAX]; |
122 | 124 |
123 #define HDR_LEN 12 | 125 #define HDR_LEN 12 |
124 char hdr[HDR_LEN] = {0xa5, 0x5a, 0x18, 0x04, 0xff, 0xff, 0xff, 0xff, 0x48, 0x00, 0x00, 0x00}; | 126 char hdr[HDR_LEN] = {0xa5, 0x5a, 0x18, 0x04, 0xff, 0xff, 0xff, 0xff, 0x48, 0x00, 0x00, 0x00}; |
125 *(int *)(hdr+4) = sz; | 127 *(int *)(hdr+4) = jpg_buf->size; |
126 | 128 |
127 memcpy(buf, hdr, HDR_LEN); | 129 memcpy(buf, hdr, HDR_LEN); |
128 int off = HDR_LEN; | 130 int off = HDR_LEN; |
129 | 131 int jpg_off = 0; |
130 while(!feof(f)) { | 132 int jpg_left = jpg_buf->size; |
131 int nr = fread(buf+off, 1, URBBUF_MAX - off, f); | 133 while (jpg_left > 0) { |
132 if (nr < 0) break; | 134 int nr = MIN(URBBUF_MAX - off, jpg_left); |
135 memcpy(buf+off, &jpg_buf->ptr[jpg_off], nr); | |
133 // pad | 136 // pad |
134 memset(buf + off + nr, 0, URBBUF_MAX - off - nr); | 137 memset(buf + off + nr, 0, URBBUF_MAX - off - nr); |
135 | 138 |
136 // write it out chunk by chunk | 139 // write it out chunk by chunk |
137 int timeout = 1000; | 140 int timeout = 1000; |
138 int endpoint = 0x2; | 141 int endpoint = 0x2; |
139 int res = usb_bulk_write(udev, endpoint, buf, URBBUF_MAX, timeout); | 142 int res = usb_bulk_write(udev, endpoint, buf, URBBUF_MAX, timeout); |
140 | 143 |
141 assert(res >= 0); | 144 if (res < 0) |
145 return 0; | |
142 off = 0; // no header on subsequent chunks | 146 off = 0; // no header on subsequent chunks |
143 } | 147 jpg_off += nr; |
148 jpg_left -= nr; | |
149 } | |
150 | |
151 return 1; | |
144 } | 152 } |
145 | 153 |
146 int main(int argc, char *argv[]) { | 154 int main(int argc, char *argv[]) { |
147 if (argc != 2) { | 155 if (argc != 2) { |
148 fprintf(stderr, "Usage: %s <.jpg file>\n", progname); | 156 fprintf(stderr, "Usage: %s </dev/fbX>\n", progname); |
149 return EXIT_FAILURE; | 157 return EXIT_FAILURE; |
150 } | 158 } |
151 | 159 |
152 struct usb_device *dev = find_dev(index); | 160 int fd = open(argv[1], O_RDONLY); |
153 if (!dev) { | 161 if (fd < 0) { |
154 fprintf(stderr, "%s: no photo frame device found, exit.\n", progname); | 162 perror("minimon framebuffer"); |
155 exit(EXIT_FAILURE); | 163 exit(EXIT_FAILURE); |
156 } | 164 } |
157 | 165 |
158 if (need_switch) { | 166 struct fb_fix_screeninfo sif; |
159 fprintf(stderr, "%s: found %s, trying to switch to custom product mode...\n", | 167 if (ioctl(fd, FBIOGET_FSCREENINFO, &sif) < 0) { |
168 perror("minimon framebuffer info"); | |
169 exit(EXIT_FAILURE); | |
170 } | |
171 | |
172 printf("id %s\n", sif.id); | |
173 printf("type %d, aux %d\n", sif.type, sif.type_aux); | |
174 printf("visual %d\n", sif.visual); | |
175 printf("accel %d\n", sif.accel); | |
176 printf("line length %d\n", sif.line_length); | |
177 printf("mem %d\n", sif.smem_len); | |
178 | |
179 struct fb_var_screeninfo siv; | |
180 if (ioctl(fd, FBIOGET_VSCREENINFO, &siv) < 0) { | |
181 perror("minimon framebuffer info"); | |
182 exit(EXIT_FAILURE); | |
183 } | |
184 | |
185 printf("res x %d y %d\n", siv.xres, siv.yres); | |
186 printf("bpp %d\n", siv.bits_per_pixel); | |
187 | |
188 size_t fb_mem_size = siv.xres * siv.yres * siv.bits_per_pixel / 8; | |
189 void *fb_mem = mmap(NULL, fb_mem_size, PROT_READ, MAP_SHARED, fd, 0); | |
190 if (fb_mem == MAP_FAILED) { | |
191 perror("minimon framebuffer mapping"); | |
192 exit(EXIT_FAILURE); | |
193 } | |
194 | |
195 while (1) { | |
196 struct usb_device *dev = find_dev(index); | |
197 if (!dev) { | |
198 fprintf(stderr, "%s: no photo frame device found, suspending...\n", progname); | |
199 sleep(1); | |
200 continue; | |
201 } | |
202 | |
203 if (need_switch) { | |
204 fprintf(stderr, "%s: found %s, trying to switch to custom product mode...\n", | |
160 ids[have_idx].name, progname); | 205 ids[have_idx].name, progname); |
161 | 206 |
162 usb_dev_handle *udev; | 207 usb_dev_handle *udev; |
163 | 208 udev = usb_open(dev); |
164 udev = usb_open(dev); | 209 if (!udev) { |
165 if (!udev) { | 210 fprintf(stderr, "%s: failed to open device, exit.\n", progname); |
166 fprintf(stderr, "%s: failed to open device, exit.\n", progname); | 211 exit(EXIT_FAILURE); |
167 exit(EXIT_FAILURE); | 212 } |
168 } | 213 |
169 | 214 char buf[254]; |
170 char buf[254]; | 215 memset(buf, 0, 254); |
171 memset(buf, 0, 254); | 216 int res = usb_control_msg(udev, USB_TYPE_STANDARD | USB_ENDPOINT_IN, |
172 | 217 0x06, 0xfe, 0xfe, buf, 0xfe, 1000); |
173 int res = usb_control_msg(udev, USB_TYPE_STANDARD | USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, | 218 fprintf(stderr, "%s: usb_control_msg() = %d\n", progname, res); |
174 0xfe, 0xfe, buf, 0xfe, 1000); | 219 usb_close(udev); |
175 fprintf(stderr, "%s: usb_control_msg() = %d\n", progname, res); | 220 sleep(1); |
221 } | |
222 | |
223 dev = find_dev(index); | |
224 if (!dev || need_switch) { | |
225 fprintf(stderr, "%s: no photo frame device found, suspending...\n", progname); | |
226 sleep(1); | |
227 continue; | |
228 } | |
229 | |
230 int mon_width = ids[have_idx].width; | |
231 int mon_height = ids[have_idx].height; | |
232 fprintf(stderr, "%s: found %s (%d x %d)\n", | |
233 progname, ids[have_idx].name, mon_width, mon_height); | |
234 | |
235 usb_dev_handle *udev = dev_open(dev); | |
236 | |
237 while (1) { | |
238 int transfer = 1; | |
239 | |
240 // poll status to avoid going back to photoframe mode | |
241 char buf[2]; | |
242 int res = usb_control_msg(udev, USB_TYPE_VENDOR | USB_ENDPOINT_IN, | |
243 0x06, 0x0, 0x0, buf, 0x2, 1000); | |
244 if (res != 2) { | |
245 break; | |
246 } | |
247 else if (buf[0] != 0) { | |
248 transfer = 0; | |
249 } | |
250 | |
251 if (transfer) { | |
252 fprintf(stderr, "."); | |
253 jpg_buf_t jpg_buf = build_jpg_from_fb((unsigned char *)fb_mem, siv.xres, siv.yres, siv.bits_per_pixel, mon_width, mon_height); | |
254 | |
255 if (!send_jpg(&jpg_buf, udev)) { | |
256 free(jpg_buf.ptr); | |
257 break; | |
258 } | |
259 free(jpg_buf.ptr); | |
260 } | |
261 else | |
262 fprintf(stderr, "o"); | |
263 | |
264 usleep(500000); | |
265 } | |
176 | 266 |
177 usb_close(udev); | 267 usb_close(udev); |
178 usleep(500000); | 268 } |
179 } | 269 |
180 | 270 munmap(fb_mem, fb_mem_size); |
181 dev = find_dev(index); | 271 close(fd); |
182 if (!dev || need_switch) { | |
183 fprintf(stderr, "%s: no photo frame device found, exit.\n", progname); | |
184 exit(EXIT_FAILURE); | |
185 } | |
186 | |
187 fprintf(stderr, "%s: found %s (%d x %d)\n", | |
188 progname, ids[have_idx].name, ids[have_idx].width, ids[have_idx].height); | |
189 | |
190 usb_dev_handle *udev = dev_open(dev); | |
191 | |
192 FILE *f = fopen(argv[1], "rb"); | |
193 if (f == NULL) { | |
194 fprintf(stderr, "%s: failed to open file '%s', exit.\n", progname, argv[1]); | |
195 exit(EXIT_FAILURE); | |
196 } | |
197 send_jpeg(f, udev); | |
198 fclose(f); | |
199 | |
200 while (1) { | |
201 char buf[2]; | |
202 int res = usb_control_msg(udev, USB_TYPE_VENDOR | USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR, | |
203 0x0, 0x0, buf, 0x2, 1000); | |
204 fprintf(stderr, "%s: usb_control_msg() = %d\n", progname, res); | |
205 | |
206 usleep(500000); | |
207 } | |
208 | |
209 usb_close(udev); | |
210 | 272 |
211 return EXIT_SUCCESS; | 273 return EXIT_SUCCESS; |
212 } | 274 } |