mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
Add fwdv(4) driver for DV video capture from FireWire camcorders using AV/C protocol and isochronous streaming. Supports AV/C tape transport commands (play, stop, ff, rewind, pause, record, eject) with NTSC/PAL auto-detection and read(2) interface for frame capture. Reviewed by: adrian Differential Revision: https://reviews.freebsd.org/D58122
196 lines
4.8 KiB
C
196 lines
4.8 KiB
C
/*
|
|
* Copyright (c) 2026 Abdelkader Boudih <[email protected]>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#ifndef _DEV_FIREWIRE_FWDV_H_
|
|
#define _DEV_FIREWIRE_FWDV_H_
|
|
|
|
/* FCP (Function Control Protocol) register addresses (IEC 61883-1 9.2) */
|
|
#define FCP_COMMAND_ADDR 0xfffff0000b00ULL
|
|
#define FCP_RESPONSE_ADDR 0xfffff0000d00ULL
|
|
#define FCP_MAX_FRAME_LEN 512
|
|
|
|
/* AV/C command/response type codes (ctype / response, 4-bit) */
|
|
#define AVC_CTYPE_CONTROL 0x0
|
|
#define AVC_CTYPE_STATUS 0x1
|
|
#define AVC_CTYPE_NOTIFY 0x3
|
|
|
|
#define AVC_RESP_NOT_IMPL 0x8
|
|
#define AVC_RESP_ACCEPTED 0x9
|
|
#define AVC_RESP_REJECTED 0xa
|
|
#define AVC_RESP_IN_TRANSITION 0xb
|
|
#define AVC_RESP_STABLE 0xc
|
|
#define AVC_RESP_INTERIM 0xf
|
|
|
|
/* AV/C subunit types (5-bit) */
|
|
#define AVC_SUBUNIT_TAPE 0x04
|
|
#define AVC_SUBUNIT_UNIT 0x1f
|
|
|
|
/* AV/C subunit ID (3-bit) */
|
|
#define AVC_SUBUNIT_ID_0 0x00
|
|
#define AVC_SUBUNIT_ID_IGNORE 0x07
|
|
|
|
/* AV/C address byte: subunit_type(5) | subunit_id(3) */
|
|
#define AVC_ADDR(type, id) (((type) << 3) | ((id) & 0x07))
|
|
#define AVC_ADDR_UNIT AVC_ADDR(AVC_SUBUNIT_UNIT, AVC_SUBUNIT_ID_IGNORE)
|
|
#define AVC_ADDR_TAPE0 AVC_ADDR(AVC_SUBUNIT_TAPE, AVC_SUBUNIT_ID_0)
|
|
|
|
/* AV/C unit commands (opcode) */
|
|
#define AVC_OP_UNIT_INFO 0x30
|
|
#define AVC_OP_SUBUNIT_INFO 0x31
|
|
#define AVC_OP_VENDOR_DEP 0x00
|
|
#define AVC_OP_POWER 0xb2
|
|
|
|
/* AV/C tape subunit opcodes */
|
|
#define AVC_OP_PLAY 0xc3
|
|
#define AVC_OP_RECORD 0xc2
|
|
#define AVC_OP_WIND 0xc4
|
|
#define AVC_OP_TRANSPORT_STATE 0xd0
|
|
|
|
/* PLAY operand[0] values */
|
|
#define AVC_PLAY_FWD 0x75
|
|
#define AVC_PLAY_STOP 0x60
|
|
|
|
/* WIND operand[0] values */
|
|
#define AVC_WIND_FFWD 0x75
|
|
#define AVC_WIND_REW 0x65
|
|
#define AVC_WIND_STOP 0x60
|
|
|
|
/* TRANSPORT_STATE operand[0] values */
|
|
#define AVC_XPORT_PLAY 0x01
|
|
#define AVC_XPORT_RECORD 0x02
|
|
#define AVC_XPORT_WIND_FF 0x03
|
|
#define AVC_XPORT_WIND_REW 0x04
|
|
#define AVC_XPORT_NO_INFO 0x7f
|
|
|
|
/* POWER operand[0] */
|
|
#define AVC_POWER_ON 0x70
|
|
#define AVC_POWER_OFF 0x60
|
|
|
|
/* IEEE 1394 CSR register space */
|
|
#define CSR_BASE_HI 0xffff
|
|
#define CSR_BASE_LO 0xf0000000
|
|
|
|
/* ISO channel limits */
|
|
#define ISO_CHANNEL_MASK 0x3f
|
|
#define ISO_CHANNEL_MAX 64
|
|
|
|
/* IEC 61883 plug control registers (CSR offsets) */
|
|
#define PCR_oMPR 0x900
|
|
#define PCR_oPCR(n) (0x904 + (n) * 4)
|
|
#define PCR_iMPR 0x980
|
|
#define PCR_iPCR(n) (0x984 + (n) * 4)
|
|
|
|
/*
|
|
* oPCR register fields (IEC 61883-1 7.5)
|
|
*
|
|
* 31 30 29:24 23:16 15:14 13:10 9:0
|
|
* online bcast n_p2p_conn channel speed overhead_id payload
|
|
*/
|
|
#define OPCR_ONLINE (1U << 31)
|
|
#define OPCR_BCAST (1U << 30)
|
|
#define OPCR_N_P2P_MASK 0x3f000000
|
|
#define OPCR_N_P2P_SHIFT 24
|
|
#define OPCR_CHANNEL_MASK 0x003f0000
|
|
#define OPCR_CHANNEL_SHIFT 16
|
|
#define OPCR_SPEED_MASK 0x0000c000
|
|
#define OPCR_SPEED_SHIFT 14
|
|
#define OPCR_OVERHEAD_MASK 0x00003c00
|
|
#define OPCR_OVERHEAD_SHIFT 10
|
|
#define OPCR_PAYLOAD_MASK 0x000003ff
|
|
|
|
/* DV frame sizes */
|
|
#define DV_SD_NTSC_FRAME (10 * 150 * 80) /* 120,000 bytes */
|
|
#define DV_SD_PAL_FRAME (12 * 150 * 80) /* 144,000 bytes */
|
|
#define DV_DVCPRO_HD_FRAME (10 * 250 * 80) /* 200,000 bytes */
|
|
|
|
/*
|
|
* ioctl interface
|
|
*/
|
|
struct fwdv_info {
|
|
uint8_t state;
|
|
uint8_t iso_channel;
|
|
uint8_t dv_system; /* 0=NTSC, 1=PAL, 0xff=unknown */
|
|
uint8_t _pad;
|
|
uint32_t frame_size;
|
|
uint32_t frame_count;
|
|
uint32_t frame_dropped;
|
|
uint32_t eui_hi; /* device EUI-64 high */
|
|
uint32_t eui_lo; /* device EUI-64 low */
|
|
char vendor[32]; /* from config ROM */
|
|
char model[32]; /* from config ROM */
|
|
};
|
|
|
|
#define FWDV_GINFO _IOR('D', 1, struct fwdv_info)
|
|
#define FWDV_PLAY _IO('D', 2)
|
|
#define FWDV_STOP _IO('D', 3)
|
|
#define FWDV_FFWD _IO('D', 4)
|
|
#define FWDV_REW _IO('D', 5)
|
|
|
|
/* fwdv state values */
|
|
#define FWDV_STATE_IDLE 0 /* no AV/C device found */
|
|
#define FWDV_STATE_PROBED 1 /* device found, not streaming */
|
|
#define FWDV_STATE_STARTING 2 /* iso_start in progress */
|
|
#define FWDV_STATE_STREAMING 3 /* iso receive active */
|
|
#define FWDV_STATE_DETACHING 4
|
|
|
|
#define DV_DIF_BLOCK_SIZE 80
|
|
#define FWDV_MAX_FRAME_SIZE DV_DVCPRO_HD_FRAME
|
|
#define FWDV_ISO_NCHUNK 256
|
|
#define FWDV_ISO_PKTSIZE 2048
|
|
#define FWDV_DEFAULT_ISO_CH 63
|
|
#define FWDV_FCP_XFERS 4
|
|
|
|
#ifdef _KERNEL
|
|
|
|
struct fwdv_softc {
|
|
struct firewire_dev_comm fd;
|
|
struct mtx mtx;
|
|
struct cdev *cdev;
|
|
|
|
struct fw_device *fwdev;
|
|
uint32_t eui_hi;
|
|
uint32_t eui_lo;
|
|
|
|
struct fw_bind fcp_bind;
|
|
uint8_t fcp_resp[FCP_MAX_FRAME_LEN];
|
|
int fcp_resp_len;
|
|
int fcp_resp_ready;
|
|
int avc_busy;
|
|
|
|
int iso_active;
|
|
|
|
char vendor[32];
|
|
char model[32];
|
|
|
|
struct task probe_task;
|
|
|
|
int dma_ch;
|
|
uint8_t iso_channel;
|
|
|
|
uint8_t *frame_buf;
|
|
uint8_t *read_buf;
|
|
uint32_t frame_size;
|
|
uint32_t frame_offset;
|
|
int frame_ready;
|
|
int read_in_progress;
|
|
uint32_t frame_count;
|
|
uint32_t frame_dropped;
|
|
int open_count;
|
|
struct selinfo rsel;
|
|
|
|
uint8_t dv_system;
|
|
int dv_detected;
|
|
|
|
int state;
|
|
};
|
|
|
|
#define FWDV_LOCK(sc) mtx_lock(&(sc)->mtx)
|
|
#define FWDV_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
|
|
|
|
#endif /* _KERNEL */
|
|
|
|
#endif /* _DEV_FIREWIRE_FWDV_H_ */
|