1c77a61a7Syz /* 2c77a61a7Syz * CDDL HEADER START 3c77a61a7Syz * 4c77a61a7Syz * The contents of this file are subject to the terms of the 5c77a61a7Syz * Common Development and Distribution License (the "License"). 6c77a61a7Syz * You may not use this file except in compliance with the License. 7c77a61a7Syz * 8c77a61a7Syz * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9c77a61a7Syz * or http://www.opensolaris.org/os/licensing. 10c77a61a7Syz * See the License for the specific language governing permissions 11c77a61a7Syz * and limitations under the License. 12c77a61a7Syz * 13c77a61a7Syz * When distributing Covered Code, include this CDDL HEADER in each 14c77a61a7Syz * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15c77a61a7Syz * If applicable, add the following below this CDDL HEADER, with the 16c77a61a7Syz * fields enclosed by brackets "[]" replaced with your own identifying 17c77a61a7Syz * information: Portions Copyright [yyyy] [name of copyright owner] 18c77a61a7Syz * 19c77a61a7Syz * CDDL HEADER END 20c77a61a7Syz */ 21c77a61a7Syz /* 229e37f2b5SRaymond Chen * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23c77a61a7Syz * Use is subject to license terms. 24c77a61a7Syz */ 25c77a61a7Syz 26c77a61a7Syz #ifndef _SYS_USB_USBVC_VAR_H 27c77a61a7Syz #define _SYS_USB_USBVC_VAR_H 28c77a61a7Syz 29c77a61a7Syz 30c77a61a7Syz #ifdef __cplusplus 31c77a61a7Syz extern "C" { 32c77a61a7Syz #endif 33c77a61a7Syz 34c77a61a7Syz #include <sys/list.h> 35*5c5f1371SRichard Lowe #include <sys/sysmacros.h> 36c77a61a7Syz #include <sys/usb/usba/usbai_private.h> 37c77a61a7Syz #include <sys/videodev2.h> 38c77a61a7Syz #include <sys/usb/clients/video/usbvc/usbvc.h> 39c77a61a7Syz 40c77a61a7Syz typedef struct usbvc_state usbvc_state_t; 41c77a61a7Syz 42c77a61a7Syz /* 43c77a61a7Syz * Power Management support 44c77a61a7Syz */ 45c77a61a7Syz typedef struct usbvc_power { 46c77a61a7Syz 47c77a61a7Syz void *usbvc_state; /* points back to usbvc_state */ 48c77a61a7Syz uint8_t usbvc_pwr_states; /* bit mask of device pwr states */ 49c77a61a7Syz int usbvc_pm_busy; 50c77a61a7Syz 51c77a61a7Syz /* Wakeup and power transistion capabilites of an interface */ 52c77a61a7Syz uint8_t usbvc_pm_capabilities; 53c77a61a7Syz 54c77a61a7Syz /* flag to indicate if driver is about to raise power level */ 55c77a61a7Syz boolean_t usbvc_raise_power; 56c77a61a7Syz 57c77a61a7Syz uint8_t usbvc_current_power; 58c77a61a7Syz uint8_t usbvc_wakeup_enabled; 59c77a61a7Syz } usbvc_power_t; 60c77a61a7Syz 61c77a61a7Syz /* Raw data buf from the USB cam */ 62c77a61a7Syz typedef struct usbvc_buf 63c77a61a7Syz { 64c77a61a7Syz uchar_t *data; 65c77a61a7Syz uint_t len; /* the length of the allocated memory of data */ 66c77a61a7Syz uint_t filled; /* number of bytes filled */ 679e37f2b5SRaymond Chen uint_t len_read; /* bytes read */ 68c77a61a7Syz uchar_t status; /* empty, filling done, read done */ 69c77a61a7Syz 70c77a61a7Syz /* cookie used for memory mapping */ 71c77a61a7Syz ddi_umem_cookie_t umem_cookie; 72c77a61a7Syz struct v4l2_buffer v4l2_buf; 73c77a61a7Syz list_node_t buf_node; /* list */ 74c77a61a7Syz } usbvc_buf_t; 75c77a61a7Syz 76c77a61a7Syz /* Group data buf related lists and other elements */ 77c77a61a7Syz typedef struct usbvc_buf_grp 78c77a61a7Syz { 7961b2e298Slc list_t uv_buf_free; 80c77a61a7Syz list_t uv_buf_done; 81c77a61a7Syz usbvc_buf_t *buf_filling; 82c77a61a7Syz uint_t buf_cnt; 83c77a61a7Syz usbvc_buf_t *buf_head; 84c77a61a7Syz } usbvc_buf_grp_t; 85c77a61a7Syz 86c77a61a7Syz /* 87c77a61a7Syz * UVC Spec: one format descriptor may be followed by sererval frame 88c77a61a7Syz * descriptors, one still image descriptor and one color matching descriptor. 89c77a61a7Syz * It is called a format group. There might be several format groups follow 90c77a61a7Syz * one input/output header. 91c77a61a7Syz */ 92c77a61a7Syz typedef struct usbvc_format_group { 93c77a61a7Syz usbvc_format_descr_t *format; 94c77a61a7Syz usbvc_frames_t *frames; 95c77a61a7Syz uint8_t frame_cnt; 96c77a61a7Syz 97c77a61a7Syz /* bytes per pix, used to calculate bytesperline */ 98c77a61a7Syz uint8_t v4l2_bpp; 99c77a61a7Syz 100c77a61a7Syz uint8_t v4l2_color; 101c77a61a7Syz uint32_t v4l2_pixelformat; /* fcc, pixelformat */ 102c77a61a7Syz usbvc_still_image_frame_t *still; 103c77a61a7Syz usbvc_color_matching_descr_t *color; 104c77a61a7Syz usbvc_frames_t *cur_frame; 105c77a61a7Syz } usbvc_format_group_t; 106c77a61a7Syz 107c77a61a7Syz /* A stream interface may have several format groups */ 108c77a61a7Syz typedef struct usbvc_stream_if { 109c77a61a7Syz 110c77a61a7Syz /* The actual format groups we parsed for the stream interface */ 111c77a61a7Syz uint8_t fmtgrp_cnt; 112c77a61a7Syz 113c77a61a7Syz usb_if_data_t *if_descr; 114c77a61a7Syz usbvc_input_header_t *input_header; 115c77a61a7Syz usbvc_output_header_t *output_header; 116c77a61a7Syz usbvc_format_group_t *format_group; 117c77a61a7Syz usbvc_format_group_t *cur_format_group; 118c77a61a7Syz usbvc_vs_probe_commit_t ctrl_pc; 119c77a61a7Syz usb_ep_descr_t *curr_ep; /* current isoc ep descr */ 120c77a61a7Syz usb_pipe_handle_t datain_ph; /* current isoc pipe handle */ 121c77a61a7Syz uint_t curr_alt; /* current alternate */ 122c77a61a7Syz 123c77a61a7Syz /* The max payload that the isoc data EPs can support */ 124c77a61a7Syz uint32_t max_isoc_payload; 125c77a61a7Syz 126c77a61a7Syz uchar_t start_polling; /* indicate if isoc polling started */ 12709dd0d6cSRaymond Chen 12809dd0d6cSRaymond Chen /* 12909dd0d6cSRaymond Chen * To flag if VIDIOC_STREAMON is executed, only used by STREAM mode 13009dd0d6cSRaymond Chen * for suspend/resume. If it's non-zero, we'll have to resume the 13109dd0d6cSRaymond Chen * device's isoc polling operation after resume. 13209dd0d6cSRaymond Chen */ 13309dd0d6cSRaymond Chen uint8_t stream_on; 13409dd0d6cSRaymond Chen 135c77a61a7Syz uchar_t fid; /* the MJPEG FID bit */ 136c77a61a7Syz usbvc_buf_grp_t buf_read; /* buf used for read I/O */ 13761b2e298Slc uint8_t buf_read_num; /* desired buf num for read I/O */ 138c77a61a7Syz usbvc_buf_grp_t buf_map; /* buf used for mmap I/O */ 139c77a61a7Syz list_node_t stream_if_node; 140c77a61a7Syz } usbvc_stream_if_t; 141c77a61a7Syz 142c77a61a7Syz /* video interface collection */ 143c77a61a7Syz typedef struct usbvc_vic { 144c77a61a7Syz 145c77a61a7Syz /* bFirstInterface, the video control infterface num of this VIC */ 146c77a61a7Syz uint8_t vctrl_if_num; 147c77a61a7Syz 148c77a61a7Syz /* 149c77a61a7Syz * bInterfaceCount -1, the total number of stream interfaces 150c77a61a7Syz * belong to this VIC 151c77a61a7Syz */ 152c77a61a7Syz uint8_t vstrm_if_cnt; 153c77a61a7Syz } usbvc_vic_t; 154c77a61a7Syz 155c77a61a7Syz /* Macros */ 156c77a61a7Syz #define USBVC_OPEN 0x00000001 157c77a61a7Syz 158c77a61a7Syz /* For serialization. */ 159c77a61a7Syz #define USBVC_SER_NOSIG B_FALSE 160c77a61a7Syz #define USBVC_SER_SIG B_TRUE 161c77a61a7Syz 162c77a61a7Syz /* 163c77a61a7Syz * Masks for debug printing 164c77a61a7Syz */ 165c77a61a7Syz #define PRINT_MASK_ATTA 0x00000001 166c77a61a7Syz #define PRINT_MASK_OPEN 0x00000002 167c77a61a7Syz #define PRINT_MASK_CLOSE 0x00000004 168c77a61a7Syz #define PRINT_MASK_READ 0x00000008 169c77a61a7Syz #define PRINT_MASK_IOCTL 0x00000010 170c77a61a7Syz #define PRINT_MASK_PM 0x00000020 171c77a61a7Syz #define PRINT_MASK_CB 0x00000040 172c77a61a7Syz #define PRINT_MASK_HOTPLUG 0x00000080 173c77a61a7Syz #define PRINT_MASK_DEVCTRL 0x00000100 174c77a61a7Syz #define PRINT_MASK_DEVMAP 0x00000200 175c77a61a7Syz #define PRINT_MASK_ALL 0xFFFFFFFF 176c77a61a7Syz 177c77a61a7Syz #define USBVC_MAX_PKTS 40 178c77a61a7Syz 17961b2e298Slc #define USBVC_DEFAULT_READ_BUF_NUM 3 18061b2e298Slc #define USBVC_MAX_READ_BUF_NUM 40 181c77a61a7Syz #define USBVC_MAX_MAP_BUF_NUM 40 182c77a61a7Syz 18361b2e298Slc /* According to UVC specs, the frame interval is in 100ns unit */ 18461b2e298Slc #define USBVC_FRAME_INTERVAL_DENOMINATOR 10000000 18561b2e298Slc 186c77a61a7Syz /* Only D3...D0 are writable, Table 4-6, UVC Spec */ 187c77a61a7Syz #define USBVC_POWER_MODE_MASK 0xf0; 188c77a61a7Syz 189c77a61a7Syz enum usbvc_buf_status { 190c77a61a7Syz USBVC_BUF_INIT = 0, /* Allocated, to be queued */ 19161b2e298Slc USBVC_BUF_MAPPED = 1, /* For map I/O only. Memory is mapped. */ 19261b2e298Slc USBVC_BUF_EMPTY = 2, /* not initialized, to be filled */ 193c77a61a7Syz 194c77a61a7Syz /* 195c77a61a7Syz * buf is filled with a full frame without any errors, 196c77a61a7Syz * it will be moved to full list. 197c77a61a7Syz */ 19861b2e298Slc USBVC_BUF_DONE = 4, 199c77a61a7Syz 200c77a61a7Syz /* 201c77a61a7Syz * buf is filled to full but no EOF bit is found at the end 202c77a61a7Syz * of video data 203c77a61a7Syz */ 20461b2e298Slc USBVC_BUF_ERR = 8 205c77a61a7Syz }; 206c77a61a7Syz 207c77a61a7Syz /* 208c77a61a7Syz * This structure is used to map v4l2 controls to uvc controls. The structure 209c77a61a7Syz * array is addressed by (V4L2_CID_BASE - V4L2_CID_*) 210c77a61a7Syz */ 211c77a61a7Syz typedef struct usbvc_v4l2_ctrl_map { 212c77a61a7Syz char name[32]; 213c77a61a7Syz uint8_t selector; /* Control Selector */ 214c77a61a7Syz uint8_t len; /* wLength, defined in uvc spec chp 4 for each ctrl */ 215c77a61a7Syz 216c77a61a7Syz /* The xth bit in bmControls bitmap of processing unit descriptor */ 217c77a61a7Syz uint8_t bit; 218c77a61a7Syz 219c77a61a7Syz enum v4l2_ctrl_type type; 220c77a61a7Syz } usbvc_v4l2_ctrl_map_t; 221c77a61a7Syz 222c77a61a7Syz typedef struct usbvc_v4l2_ctrl { 223c77a61a7Syz uint8_t entity_id; 224c77a61a7Syz usbvc_v4l2_ctrl_map_t *ctrl_map; 225c77a61a7Syz } usbvc_v4l2_ctrl_t; 226c77a61a7Syz 227c77a61a7Syz 228c77a61a7Syz /* 229c77a61a7Syz * State structure 230c77a61a7Syz */ 231c77a61a7Syz struct usbvc_state { 232c77a61a7Syz dev_info_t *usbvc_dip; /* per-device info handle */ 233c77a61a7Syz usb_client_dev_data_t *usbvc_reg; /* registration data */ 234c77a61a7Syz int usbvc_dev_state; /* USB device states. */ 235c77a61a7Syz int usbvc_drv_state; /* driver states. */ 236c77a61a7Syz kmutex_t usbvc_mutex; 237c77a61a7Syz kcondvar_t usbvc_serial_cv; 238c77a61a7Syz boolean_t usbvc_serial_inuse; 239c77a61a7Syz boolean_t usbvc_locks_initialized; 240c77a61a7Syz 241c77a61a7Syz usbvc_power_t *usbvc_pm; 242c77a61a7Syz 243c77a61a7Syz usb_log_handle_t usbvc_log_handle; /* log handle */ 244c77a61a7Syz usb_pipe_handle_t usbvc_default_ph; /* default pipe */ 245c77a61a7Syz 246c77a61a7Syz /* Video ctrl interface header descriptor */ 247c77a61a7Syz usbvc_vc_header_t *usbvc_vc_header; 248c77a61a7Syz list_t usbvc_term_list; 249c77a61a7Syz list_t usbvc_unit_list; 250c77a61a7Syz 251c77a61a7Syz list_t usbvc_stream_list; 252c77a61a7Syz usbvc_stream_if_t *usbvc_curr_strm; 253c77a61a7Syz kcondvar_t usbvc_read_cv; /* wait for read buf done */ 254c77a61a7Syz kcondvar_t usbvc_mapio_cv; /* wait for mmap I/O buf done */ 255c77a61a7Syz 256c77a61a7Syz /* current I/O type: read or mmap. */ 257c77a61a7Syz uchar_t usbvc_io_type; 258c77a61a7Syz }; 259c77a61a7Syz 260c77a61a7Syz 261c77a61a7Syz /* 262c77a61a7Syz * Used in ioctl entry to copy an argument from kernel space (arg_name) 263c77a61a7Syz * to USER space (arg) 264c77a61a7Syz */ 265c77a61a7Syz #define USBVC_COPYOUT(arg_name) \ 266c77a61a7Syz if (ddi_copyout(&arg_name, (caddr_t)arg, sizeof (arg_name), mode)) { \ 26761b2e298Slc rv = EFAULT; \ 26861b2e298Slc break; \ 269c77a61a7Syz } 270c77a61a7Syz 271c77a61a7Syz /* 272c77a61a7Syz * Used in ioctl entry to copy an argument from USER space (arg) to 273c77a61a7Syz * KERNEL space (arg_name) 274c77a61a7Syz */ 275c77a61a7Syz #define USBVC_COPYIN(arg_name) \ 276c77a61a7Syz if (ddi_copyin((caddr_t)arg, &arg_name, sizeof (arg_name), mode)) { \ 277c77a61a7Syz rv = EFAULT; \ 278c77a61a7Syz break; \ 279c77a61a7Syz } 280c77a61a7Syz 281c77a61a7Syz /* Turn a little endian byte array to a uint32_t */ 282c77a61a7Syz #define LE_TO_UINT32(src, off, des) { \ 283c77a61a7Syz uint32_t tmp; \ 284c77a61a7Syz des = src[off + 3]; \ 285c77a61a7Syz des = des << 24; \ 286c77a61a7Syz tmp = src[off + 2]; \ 287c77a61a7Syz des |= tmp << 16; \ 288c77a61a7Syz tmp = src[off + 1]; \ 289c77a61a7Syz des |= tmp << 8; \ 290c77a61a7Syz des |= src[off]; \ 291c77a61a7Syz } 292c77a61a7Syz 293c77a61a7Syz /* Turn a uint32_t to a little endian byte array */ 294c77a61a7Syz #define UINT32_TO_LE(src, off, des) { \ 295c77a61a7Syz des[off + 0] = 0xff & src; \ 296c77a61a7Syz des[off + 1] = 0xff & (src >> 8); \ 297c77a61a7Syz des[off + 2] = 0xff & (src >> 16); \ 298c77a61a7Syz des[off + 3] = 0xff & (src >> 24); \ 299c77a61a7Syz } 300c77a61a7Syz 301c77a61a7Syz /* Turn a little endian byte array to a uint16_t */ 302c77a61a7Syz #define LE_TO_UINT16(src, off, des) \ 303c77a61a7Syz des = src[off + 1]; \ 304c77a61a7Syz des = des << 8; \ 305c77a61a7Syz des |= src[off]; 306c77a61a7Syz 307c77a61a7Syz /* Turn a uint16_t to alittle endian byte array */ 308c77a61a7Syz #define UINT16_TO_LE(src, off, des) { \ 309c77a61a7Syz des[off + 0] = 0xff & src; \ 310c77a61a7Syz des[off + 1] = 0xff & (src >> 8); \ 311c77a61a7Syz } 312c77a61a7Syz 313c77a61a7Syz #define NELEM(a) (sizeof (a) / sizeof (*(a))) 314c77a61a7Syz 315c77a61a7Syz /* Minimum length of class specific descriptors */ 316c77a61a7Syz #define USBVC_C_HEAD_LEN_MIN 12 /* ctrl header */ 317c77a61a7Syz #define USBVC_I_TERM_LEN_MIN 8 /* input term */ 318c77a61a7Syz #define USBVC_O_TERM_LEN_MIN 9 /* output term */ 319c77a61a7Syz #define USBVC_P_UNIT_LEN_MIN 8 /* processing unit */ 320c77a61a7Syz #define USBVC_S_UNIT_LEN_MIN 5 /* selector unit */ 321c77a61a7Syz #define USBVC_E_UNIT_LEN_MIN 22 /* extension unit */ 322c77a61a7Syz #define USBVC_FRAME_LEN_MIN 26 /* Frame descriptor */ 323c77a61a7Syz 324c77a61a7Syz /* Length of the Frame descriptor which has continuous frame intervals */ 325c77a61a7Syz #define USBVC_FRAME_LEN_CON 38 326c77a61a7Syz 327c77a61a7Syz 328c77a61a7Syz /* 329c77a61a7Syz * According to usb2.0 spec (table 9-13), for all ep, bits 10..0 specify the 330c77a61a7Syz * max pkt size; for high speed ep, bits 12..11 specify the number of 331c77a61a7Syz * additional transaction opportunities per microframe. 332c77a61a7Syz */ 333c77a61a7Syz #define HS_PKT_SIZE(pktsize) (pktsize & 0x07ff) * (1 + ((pktsize >> 11) & 3)) 334c77a61a7Syz 335c77a61a7Syz /* 336c77a61a7Syz * warlock directives 337c77a61a7Syz * _NOTE is an advice for locklint. Locklint checks lock use for deadlocks. 338c77a61a7Syz */ 339c77a61a7Syz _NOTE(MUTEX_PROTECTS_DATA(usbvc_state_t::usbvc_mutex, usbvc_state_t)) 340c77a61a7Syz _NOTE(DATA_READABLE_WITHOUT_LOCK(usbvc_state_t::{ 341c77a61a7Syz usbvc_dip 342c77a61a7Syz usbvc_pm 343c77a61a7Syz usbvc_log_handle 344c77a61a7Syz usbvc_reg 345c77a61a7Syz usbvc_default_ph 346c77a61a7Syz usbvc_vc_header 347c77a61a7Syz usbvc_term_list 348c77a61a7Syz usbvc_unit_list 349c77a61a7Syz usbvc_stream_list 350c77a61a7Syz })) 351c77a61a7Syz 352c77a61a7Syz _NOTE(SCHEME_PROTECTS_DATA("stable data", usb_pipe_policy)) 353c77a61a7Syz _NOTE(SCHEME_PROTECTS_DATA("USBA", usbvc_stream_if::datain_ph)) 354c77a61a7Syz _NOTE(SCHEME_PROTECTS_DATA("USBA", usbvc_stream_if::curr_alt)) 355c77a61a7Syz _NOTE(SCHEME_PROTECTS_DATA("USBA", usbvc_stream_if::curr_ep)) 356c77a61a7Syz _NOTE(SCHEME_PROTECTS_DATA("unshared data", usbvc_buf::umem_cookie)) 357c77a61a7Syz _NOTE(SCHEME_PROTECTS_DATA("unshared data", usbvc_buf::data)) 358c77a61a7Syz _NOTE(SCHEME_PROTECTS_DATA("unshared data", usbvc_v4l2_ctrl)) 359c77a61a7Syz _NOTE(SCHEME_PROTECTS_DATA("unshared data", usbvc_v4l2_ctrl_map)) 360c77a61a7Syz _NOTE(SCHEME_PROTECTS_DATA("unshared data", mblk_t)) 361c77a61a7Syz _NOTE(SCHEME_PROTECTS_DATA("unshared data", buf)) 362c77a61a7Syz _NOTE(SCHEME_PROTECTS_DATA("unshared data", usb_isoc_req)) 363c77a61a7Syz _NOTE(SCHEME_PROTECTS_DATA("unshared data", v4l2_queryctrl)) 364c77a61a7Syz _NOTE(SCHEME_PROTECTS_DATA("unshared data", v4l2_format)) 365c77a61a7Syz _NOTE(SCHEME_PROTECTS_DATA("unshared data", v4l2_control)) 36661b2e298Slc _NOTE(SCHEME_PROTECTS_DATA("unshared data", v4l2_streamparm)) 367c77a61a7Syz 368c77a61a7Syz int usbvc_open_isoc_pipe(usbvc_state_t *, usbvc_stream_if_t *); 369c77a61a7Syz int usbvc_start_isoc_polling(usbvc_state_t *, usbvc_stream_if_t *, uchar_t); 370c77a61a7Syz int usbvc_vc_set_ctrl(usbvc_state_t *, uint8_t, uint8_t, 371c77a61a7Syz uint16_t, uint16_t, mblk_t *); 372c77a61a7Syz int usbvc_vc_get_ctrl(usbvc_state_t *, uint8_t, uint8_t, 373c77a61a7Syz uint16_t, uint16_t, mblk_t *); 374c77a61a7Syz int usbvc_vs_set_probe_commit(usbvc_state_t *, usbvc_stream_if_t *, 375c77a61a7Syz usbvc_vs_probe_commit_t *, uchar_t); 376c77a61a7Syz void usbvc_free_map_bufs(usbvc_state_t *, usbvc_stream_if_t *); 377c77a61a7Syz int usbvc_alloc_map_bufs(usbvc_state_t *, usbvc_stream_if_t *, int, int); 378c77a61a7Syz int usbvc_vs_get_probe(usbvc_state_t *, usbvc_stream_if_t *, 379c77a61a7Syz usbvc_vs_probe_commit_t *, uchar_t); 380c77a61a7Syz 381c77a61a7Syz /* Functions specific for V4L2 API */ 382c77a61a7Syz uint8_t usbvc_v4l2_colorspace(uint8_t); 383c77a61a7Syz uint32_t usbvc_v4l2_guid2fcc(uint8_t *); 384c77a61a7Syz int usbvc_v4l2_ioctl(usbvc_state_t *, int, intptr_t, int); 385c77a61a7Syz 386c77a61a7Syz 387c77a61a7Syz #ifdef __cplusplus 388c77a61a7Syz } 389c77a61a7Syz #endif 390c77a61a7Syz 391c77a61a7Syz #endif /* _SYS_USB_USBVC_VAR_H */ 392