/* Same as idma_pci9_read, but 16-bit little-endian byte swapping is performed * if the unit_size is 2, and 32-bit little-endian byte swapping is performed if * the unit_size is 4. */ static void idma_pci9_read_le(u8 *dst, u8 *src, int bytes, int unit_size, int sinc) { int i; u8 *p; idma_pci9_read(dst, src, bytes, unit_size, sinc); switch(unit_size) { case 2: for (i = 0, p = dst; i < bytes; i += 2, p += 2) swab16s((u16 *) p); break; case 4: for (i = 0, p = dst; i < bytes; i += 4, p += 4) swab32s((u32 *) p); break; default: break; } }
/* this function reads a full JPEG picture synchronously * TODO: do it asynchronously... */ static int read_frame(struct zr364xx_camera *cam, int framenum) { int i, n, temp, head, size, actual_length; unsigned char *ptr = NULL, *jpeg; redo: /* hardware brightness */ n = send_control_msg(cam->udev, 1, 0x2001, 0, NULL, 0); temp = (0x60 << 8) + 127 - cam->brightness; n = send_control_msg(cam->udev, 1, temp, 0, NULL, 0); /* during the first loop we are going to insert JPEG header */ head = 0; /* this is the place in memory where we are going to build * the JPEG image */ jpeg = cam->framebuf + framenum * MAX_FRAME_SIZE; /* read data... */ do { n = usb_bulk_msg(cam->udev, usb_rcvbulkpipe(cam->udev, 0x81), cam->buffer, BUFFER_SIZE, &actual_length, CTRL_TIMEOUT); DBG("buffer : %d %d", cam->buffer[0], cam->buffer[1]); DBG("bulk : n=%d size=%d", n, actual_length); if (n < 0) { dev_err(&cam->udev->dev, "error reading bulk msg\n"); return 0; } if (actual_length < 0 || actual_length > BUFFER_SIZE) { dev_err(&cam->udev->dev, "wrong number of bytes\n"); return 0; } /* swap bytes if camera needs it */ if (cam->method == METHOD0) { u16 *buf = (u16*)cam->buffer; for (i = 0; i < BUFFER_SIZE/2; i++) swab16s(buf + i); } /* write the JPEG header */ if (!head) { DBG("jpeg header"); ptr = jpeg; memcpy(ptr, header1, sizeof(header1)); ptr += sizeof(header1); header3 = 0; memcpy(ptr, &header3, 1); ptr++; memcpy(ptr, cam->buffer, 64); ptr += 64; header3 = 1; memcpy(ptr, &header3, 1); ptr++; memcpy(ptr, cam->buffer + 64, 64); ptr += 64; memcpy(ptr, header2, sizeof(header2)); ptr += sizeof(header2); memcpy(ptr, cam->buffer + 128, actual_length - 128); ptr += actual_length - 128; head = 1; DBG("header : %d %d %d %d %d %d %d %d %d", cam->buffer[0], cam->buffer[1], cam->buffer[2], cam->buffer[3], cam->buffer[4], cam->buffer[5], cam->buffer[6], cam->buffer[7], cam->buffer[8]); } else { memcpy(ptr, cam->buffer, actual_length); ptr += actual_length; } } /* ... until there is no more */ while (actual_length == BUFFER_SIZE); /* we skip the 2 first frames which are usually buggy */ if (cam->skip) { cam->skip--; goto redo; } /* go back to find the JPEG EOI marker */ size = ptr - jpeg; ptr -= 2; while (ptr > jpeg) { if (*ptr == 0xFF && *(ptr + 1) == 0xD9 && *(ptr + 2) == 0xFF) break; ptr--; } if (ptr == jpeg) DBG("No EOI marker"); /* Sometimes there is junk data in the middle of the picture, * we want to skip this bogus frames */ while (ptr > jpeg) { if (*ptr == 0xFF && *(ptr + 1) == 0xFF && *(ptr + 2) == 0xFF) break; ptr--; } if (ptr != jpeg) { DBG("Bogus frame ? %d", cam->nb); goto redo; } DBG("jpeg : %d %d %d %d %d %d %d %d", jpeg[0], jpeg[1], jpeg[2], jpeg[3], jpeg[4], jpeg[5], jpeg[6], jpeg[7]); return size; }