Skip to content

Linux drivers for sunscreen UV camera with proprietary protocol

License

Notifications You must be signed in to change notification settings

MAkcanca/useeplus-linux-driver

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SuperCamera Linux Driver Documentation

Project Overview

This document describes the development of a Linux kernel driver for a proprietary USB camera device (Geek szitman supercamera, ID 2ce3:3828). The camera doesn't use standard UVC descriptors but follows a proprietary protocol with a custom packet format that carries JPEG image data.

Device Specifications

  • Vendor ID: 0x2ce3 (Geek szitman)
  • Product ID: 0x3828 (supercamera)
  • USB Version: 2.0
  • Interfaces: 2 interfaces, with interface 1 having multiple alternate settings
  • Endpoint: Bulk transfer endpoint (0x81 IN, 0x01 OUT)
  • Protocol: Proprietary (not standard UVC), but transmits JPEG images

Driver Architecture

The driver is implemented as a character device that:

  1. Initializes the camera with a specific command sequence
  2. Sets the alternate interface setting to 1
  3. Captures data from the bulk endpoint
  4. Processes the proprietary packet format to extract JPEG images
  5. Makes the image data available to userspace via a /dev/supercamera device

Key Data Structures

struct camera_frame {
    unsigned char *data;
    size_t size;
    bool ready;
};

struct camera_dev {
    struct usb_device *udev;
    struct usb_interface *interface;
    struct urb *urb;
    unsigned char *urb_buffer;
    
    // Connection command
    unsigned char connect_cmd[CONNECT_CMD_SIZE];
    
    // Frame ring buffer
    struct camera_frame frames[MAX_FRAMES];
    int current_frame;
    int read_frame;
    
    // Character device
    struct cdev cdev;
    dev_t dev_num;
    struct class *class;
    struct device *device;
    struct mutex io_mutex;
    bool device_open;
    
    // Read position
    size_t read_pos;
    
    // State
    bool streaming;
    
    // Wait queue for blocking reads
    wait_queue_head_t read_wait;
};

Initialization Sequence

A critical part of the driver is the initialization sequence. The camera needs:

  1. Setting interface 1 to alternate setting 1
  2. Sending a specific command sequence: 0xBB 0xAA 0x05 0x00 0x00
// Start streaming
static int start_streaming(struct camera_dev *dev)
{
    int result;
    
    // Set alt setting to 1
    result = usb_set_interface(dev->udev, INTERFACE_NUM, 1);
    if (result) {
        printk(KERN_ERR "Camera: Failed to set alt setting: %d", result);
        return result;
    }
    
    // Send connect command
    result = send_command(dev, dev->connect_cmd, CONNECT_CMD_SIZE);
    if (result) {
        return result;
    }
    
    // [URB setup code...]
}

Packet Format

The camera uses a proprietary packet format with the following characteristics:

  1. Each packet begins with a header
  2. The header starts with the sequence 0xAA 0xBB 0x07
  3. The header appears to be 12 bytes long
  4. The payload data follows the header
  5. The payload contains JPEG image data, which can span multiple packets

Example packet header:

AA BB 07 AB 03 00 00 00 57 43 00 73

Data Processing Algorithm

The most challenging part was correctly parsing the proprietary packet format:

static void process_data(struct camera_dev *dev, unsigned char *data, int length)
{
    struct camera_frame *frame = &dev->frames[dev->current_frame];
    static int packet_count = 0;
    
    // Custom header appears to be 12 bytes
    const int HEADER_SIZE = 12;
    
    // Debug first few packets
    if (packet_count < 10) {
        printk(KERN_INFO "Camera: Packet %d (%d bytes): ", packet_count, length);
        for (int i = 0; i < min(16, length); i++) {
            printk(KERN_CONT "%02x ", data[i]);
        }
        printk(KERN_CONT "\n");
        packet_count++;
    }
    
    // Relaxed header check - only check first 3 bytes
    if (length >= 3 && data[0] == 0xaa && data[1] == 0xbb && data[2] == 0x07) {
        // Valid packet header processing
        // [detailed packet processing code...]
    } else {
        // Invalid header handling
        // [invalid packet handling code...]
    }
}

Challenges and Solutions

1. Non-Standard Protocol

Challenge: The camera doesn't use standard UVC protocol.

Solution: Reverse-engineered the protocol by examining packet data and identified a consistent pattern.

2. Header Format Variations

Challenge: Initially, we expected a consistent header pattern (AA BB 07 AB 03), but later packets showed variations.

Solution: Relaxed the header check to only verify the first 3 bytes (AA BB 07).

3. Frame Boundary Detection

Challenge: Determining where one image ends and another begins.

Solution: Used JPEG markers (SOI: FF D8, EOI: FF D9) to identify image boundaries within the data stream.

4. Incomplete Images

Challenge: Some extracted images were incomplete or truncated.

Solution: Implemented a JPEG validation mechanism that ensures only complete, valid JPEG images are processed.

Userspace Image Extraction

A companion userspace tool extracts individual JPEG images from the camera's data stream:

// extract_images.c
// [detailed implementation...]

Key features:

  1. Opens the /dev/supercamera device
  2. Reads frames from the driver
  3. Scans for JPEG SOI/EOI markers
  4. Extracts and validates individual JPEG images
  5. Saves valid images to disk

Common Pitfalls to Avoid

  1. Assuming Standard UVC: The device is NOT a standard UVC device despite similarities.

  2. Strict Header Parsing: The header format varies slightly between packets. A relaxed approach is needed.

  3. Missing Frame Boundaries: Without proper detection of JPEG markers, you'll get incomplete or mixed images.

  4. System Freezes: Overly aggressive assumptions about the protocol can lead to kernel crashes.

  5. Insufficient Buffer Size: JPEG frames can be large; ensure buffers are big enough.

Performance Considerations

  1. The driver uses a ring buffer of frames to help with throughput.

  2. Blocking read operations allow userspace applications to efficiently wait for new frames.

  3. Frame size thresholds prevent buffer overflows while ensuring complete images.

Further Improvements

  1. V4L2 Integration: Implementing the Video4Linux2 API would provide better compatibility with existing applications.

  2. Direct JPEG Extraction: The driver could extract individual JPEG images directly rather than passing raw data to userspace.

  3. Camera Control: Adding ioctls to control camera parameters like resolution, frame rate, etc.

  4. Multiple Opening: Currently only one process can open the device at a time.

This driver provides basic functionality for the proprietary SuperCamera device, enabling Linux applications to capture images from it. While not a standard UVC driver, it successfully handles the device's custom protocol to extract JPEG image data. Do not ask how I developed it, it was full of tears.

About

Linux drivers for sunscreen UV camera with proprietary protocol

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published