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 } |
