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 }

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.