| // Copyright 2017 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #![allow(non_camel_case_types,non_snake_case)] |
| #![deny(warnings)] |
| |
| extern crate fuchsia_zircon as zircon; |
| |
| use zircon::sys as sys; |
| use std::os::raw::c_char; |
| |
| // References to Zircon DDK's driver.h |
| |
| // Copied from fuchsia-zircon-sys. |
| macro_rules! multiconst { |
| ($typename:ident, [$($rawname:ident = $value:expr;)*]) => { |
| $( |
| pub const $rawname: $typename = $value; |
| )* |
| } |
| } |
| |
| // Opaque structs |
| #[repr(u8)] |
| pub enum zx_device_t { |
| variant1, |
| } |
| |
| #[repr(u8)] |
| pub enum zx_device_prop_t { |
| variant1, |
| } |
| |
| #[repr(u8)] |
| pub enum zx_driver_t { |
| variant1, |
| } |
| |
| #[repr(C)] |
| pub struct zx_driver_rec_t { |
| pub ops: *const zx_driver_ops_t, |
| pub driver: *mut zx_driver_t, |
| pub log_flags: u32, |
| } |
| |
| pub const ZX_DEVICE_NAME_MAX: usize = 31; |
| |
| #[repr(C)] |
| pub struct list_node_t { |
| pub prev: *mut list_node_t, |
| pub next: *mut list_node_t, |
| } |
| |
| impl Default for list_node_t { |
| fn default() -> Self { |
| list_node_t { |
| prev: std::ptr::null_mut(), |
| next: std::ptr::null_mut(), |
| } |
| } |
| } |
| |
| const DRIVER_OPS_VERSION: u64 = 0x2b3490fa40d9f452; |
| |
| #[repr(C)] |
| pub struct zx_driver_ops_t { |
| pub __version: u64, |
| |
| pub init: Option<unsafe extern "C" fn (out_ctx: *mut *mut u8) -> sys::zx_status_t>, |
| pub bind: Option<unsafe extern "C" fn (ctx: *mut u8, device: *mut zx_device_t) -> sys::zx_status_t>, |
| pub create: Option<unsafe extern "C" fn (ctx: *mut u8, parent: *mut zx_device_t, name: *const c_char, args: *const c_char, rpc_channel: sys::zx_handle_t) -> sys::zx_status_t>, |
| pub release: Option<unsafe extern "C" fn (ctx: *mut u8)>, |
| } |
| |
| // This is needed instead of Default::default() because the latter can't be called in a static |
| // context. |
| pub const DEFAULT_DRIVER_OPS: zx_driver_ops_t = zx_driver_ops_t { |
| __version: DRIVER_OPS_VERSION, |
| init: None, |
| bind: None, |
| create: None, |
| release: None, |
| }; |
| |
| impl Default for zx_driver_ops_t { |
| fn default() -> Self { |
| DEFAULT_DRIVER_OPS |
| } |
| } |
| |
| const DEVICE_OPS_VERSION: u64 = 0xc9410d2a24f57424; |
| |
| #[repr(C)] |
| pub struct zx_protocol_device_t { |
| pub __version: u64, |
| |
| pub get_protocol: Option<unsafe extern "C" fn (ctx: *mut u8, proto_id: u32, protocol: *mut u8) -> sys::zx_status_t>, |
| pub open: Option<unsafe extern "C" fn (ctx: *mut u8, dev_out: *mut *mut zx_device_t, flags: u32) -> sys::zx_status_t>, |
| pub open_at: Option<unsafe extern "C" fn (ctx: *mut u8, dev_out: *mut *mut zx_device_t, path: *const c_char, flags: u32) -> sys::zx_status_t>, |
| pub close: Option<unsafe extern "C" fn (ctx: *mut u8, flags: u32) -> sys::zx_status_t>, |
| pub unbind: Option<unsafe extern "C" fn (ctx: *mut u8)>, |
| pub release: Option<unsafe extern "C" fn (ctx: *mut u8)>, |
| pub read: Option<unsafe extern "C" fn (ctx: *mut u8, buf: *mut u8, count: usize, off: sys::zx_off_t, actual: *mut usize) -> sys::zx_status_t>, |
| pub write: Option<unsafe extern "C" fn (ctx: *mut u8, buf: *const u8, count: usize, off: sys::zx_off_t, actual: *mut usize) -> sys::zx_status_t>, |
| pub get_size: Option<unsafe extern "C" fn (ctx: *mut u8) -> sys::zx_off_t>, |
| pub ioctl: Option<unsafe extern "C" fn (ctx: *mut u8, op: u32, in_buf: *const u8, in_len: usize, out_buf: *mut u8, out_len: usize, out_actual: *mut usize) -> sys::zx_status_t>, |
| pub suspend: Option<unsafe extern "C" fn (ctx: *mut u8, flags: u32) -> sys::zx_status_t>, |
| pub resume: Option<unsafe extern "C" fn (ctx: *mut u8, flags: u32) -> sys::zx_status_t>, |
| pub rxrpc: Option<unsafe extern "C" fn (ctx: *mut u8, channel: sys::zx_handle_t) -> sys::zx_status_t>, |
| } |
| |
| // This is needed instead of Default::default() because the latter can't be called in a static |
| // context. |
| pub const DEFAULT_PROTOCOL_DEVICE: zx_protocol_device_t = zx_protocol_device_t { |
| __version: DEVICE_OPS_VERSION, |
| get_protocol: None, |
| open: None, |
| open_at: None, |
| close: None, |
| unbind: None, |
| release: None, |
| read: None, |
| write: None, |
| get_size: None, |
| ioctl: None, |
| suspend: None, |
| resume: None, |
| rxrpc: None, |
| }; |
| |
| impl Default for zx_protocol_device_t { |
| fn default() -> Self { |
| DEFAULT_PROTOCOL_DEVICE |
| } |
| } |
| |
| pub type device_add_flags_t = u32; |
| |
| multiconst!(device_add_flags_t, [ |
| DEVICE_ADD_NONE = 0; |
| DEVICE_ADD_NON_BINDABLE = 1 << 0; |
| DEVICE_ADD_INSTANCE = 1 << 1; |
| DEVICE_ADD_MUST_ISOLATE = 1 << 2; |
| DEVICE_ADD_INVISIBLE = 1 << 3; |
| ]); |
| |
| // Device Manager API |
| const DEVICE_ADD_ARGS_VERSION: u64 = 0x96a64134d56e88e3; |
| |
| #[repr(C)] |
| pub struct device_add_args_t { |
| pub version: u64, |
| pub name: *const c_char, |
| pub ctx: *mut u8, |
| pub ops: *mut zx_protocol_device_t, |
| pub props: *mut zx_device_prop_t, |
| pub prop_count: u32, |
| pub proto_id: u32, |
| pub proto_ops: *mut u8, |
| pub proxy_args: *const c_char, |
| pub flags: device_add_flags_t, |
| } |
| |
| impl Default for device_add_args_t { |
| fn default() -> Self { |
| device_add_args_t { |
| version: DEVICE_ADD_ARGS_VERSION, |
| name: std::ptr::null_mut(), |
| ctx: std::ptr::null_mut(), |
| ops: std::ptr::null_mut(), |
| props: std::ptr::null_mut(), |
| prop_count: 0, |
| proto_id: 0, |
| proto_ops: std::ptr::null_mut(), |
| proxy_args: std::ptr::null_mut(), |
| flags: DEVICE_ADD_NON_BINDABLE, |
| } |
| } |
| } |
| |
| // USB request types |
| pub type usb_request_type_t = u8; |
| |
| multiconst!(usb_request_type_t, [ |
| USB_DIR_OUT = 0 << 7; |
| USB_DIR_IN = 1 << 7; |
| USB_DIR_MASK = 1 << 7; |
| USB_TYPE_STANDARD = 0 << 5; |
| USB_TYPE_CLASS = 1 << 5; |
| USB_TYPE_VENDOR = 2 << 5; |
| USB_TYPE_MASK = 3 << 5; |
| USB_RECIP_DEVICE = 0 << 0; |
| USB_RECIP_INTERFACE = 1 << 0; |
| USB_RECIP_ENDPOINT = 2 << 0; |
| USB_RECIP_OTHER = 3 << 0; |
| USB_RECIP_MASK = 0x1f << 0; |
| ]); |
| |
| // USB standard request values |
| multiconst!(u8, [ |
| USB_REQ_GET_STATUS = 0x00; |
| USB_REQ_CLEAR_FEATURE = 0x01; |
| USB_REQ_SET_FEATURE = 0x03; |
| USB_REQ_SET_ADDRESS = 0x05; |
| USB_REQ_GET_DESCRIPTOR = 0x06; |
| USB_REQ_SET_DESCRIPTOR = 0x07; |
| USB_REQ_GET_CONFIGURATION = 0x08; |
| USB_REQ_SET_CONFIGURATION = 0x09; |
| USB_REQ_GET_INTERFACE = 0x0a; |
| USB_REQ_SET_INTERFACE = 0x0b; |
| USB_REQ_SYNCH_FRAME = 0x0c; |
| ]); |
| |
| // USB device/interface classes |
| #[repr(u8)] |
| #[derive(Debug, Copy, Clone, Eq, PartialEq)] |
| pub enum usb_class_t { |
| USB_CLASS_AUDIO = 0x01, |
| USB_CLASS_COMM = 0x02, |
| USB_CLASS_HID = 0x03, |
| USB_CLASS_PHYSICAL = 0x05, |
| USB_CLASS_IMAGING = 0x06, |
| USB_CLASS_PRINTER = 0x07, |
| USB_CLASS_MSC = 0x08, |
| USB_CLASS_HUB = 0x09, |
| USB_CLASS_CDC = 0x0a, |
| USB_CLASS_CCID = 0x0b, |
| USB_CLASS_SECURITY = 0x0d, |
| USB_CLASS_VIDEO = 0x0e, |
| USB_CLASS_HEALTHCARE = 0x0f, |
| USB_CLASS_DIAGNOSTIC = 0xdc, |
| USB_CLASS_WIRELESS = 0xe0, |
| USB_CLASS_MISC = 0xef, |
| USB_CLASS_VENDOR = 0xff, |
| } |
| |
| pub const USB_SUBCLASS_MSC_SCSI: u8 = 0x06; |
| pub const USB_PROTOCOL_MSC_BULK_ONLY: u8 = 0x50; |
| |
| // USB descriptor types |
| multiconst!(u8, [ |
| USB_DT_DEVICE = 0x01; |
| USB_DT_CONFIG = 0x02; |
| USB_DT_STRING = 0x03; |
| USB_DT_INTERFACE = 0x04; |
| USB_DT_ENDPOINT = 0x05; |
| USB_DT_DEVICE_QUALIFIER = 0x06; |
| USB_DT_OTHER_SPEED_CONFIG = 0x07; |
| USB_DT_INTERFACE_POWER = 0x08; |
| USB_DT_INTERFACE_ASSOCIATION = 0x0b; |
| USB_DT_HID = 0x21; |
| USB_DT_HIDREPORT = 0x22; |
| USB_DT_HIDPHYSICAL = 0x23; |
| USB_DT_CS_INTERFACE = 0x24; |
| USB_DT_CS_ENDPOINT = 0x25; |
| USB_DT_SS_EP_COMPANION = 0x30; |
| USB_DT_SS_ISOCH_EP_COMPANION = 0x31; |
| ]); |
| |
| pub const ZX_PROTOCOL_USB: u32 = 0x70555342; // 'pUSB' |
| |
| #[repr(C)] |
| #[derive(Debug, Copy, Clone, Eq, PartialEq)] |
| pub enum usb_speed_t { |
| USB_SPEED_UNDEFINED = 0, |
| USB_SPEED_FULL = 1, |
| USB_SPEED_LOW = 2, |
| USB_SPEED_HIGH = 3, |
| USB_SPEED_SUPER = 4, |
| } |
| |
| // Opaque struct |
| #[repr(u8)] |
| pub enum usb_request_t { |
| variant1, |
| } |
| |
| #[repr(C, packed)] |
| pub struct usb_device_descriptor_t { |
| pub bLength: u8, |
| pub bDescriptorType: u8, |
| pub bcdUSB: u16, |
| pub bDeviceClass: u8, |
| pub bDeviceSubClass: u8, |
| pub bDeviceProtocol: u8, |
| pub bMaxPacketSize0: u8, |
| pub idVendor: u16, |
| pub idProduct: u16, |
| pub bcdDevice: u16, |
| pub iManufacturer: u8, |
| pub iProduct: u8, |
| pub iSerialNumber: u8, |
| pub bNumConfigurations: u8, |
| } |
| |
| impl Default for usb_device_descriptor_t { |
| fn default() -> Self { |
| usb_device_descriptor_t { |
| bLength: 0, |
| bDescriptorType: 0, |
| bcdUSB: 0, |
| bDeviceClass: 0, |
| bDeviceSubClass: 0, |
| bDeviceProtocol: 0, |
| bMaxPacketSize0: 0, |
| idVendor: 0, |
| idProduct: 0, |
| bcdDevice: 0, |
| iManufacturer: 0, |
| iProduct: 0, |
| iSerialNumber: 0, |
| bNumConfigurations: 0, |
| } |
| } |
| } |
| |
| #[repr(C, packed)] |
| pub struct usb_configuration_descriptor_t { |
| pub bLength: u8, |
| pub bDescriptorType: u8, |
| pub wTotalLength: u16, |
| pub bNumInterfaces: u8, |
| pub bConfigurationValue: u8, |
| pub iConfiguration: u8, |
| pub bmAttributes: u8, |
| pub bMaxPower: u8, |
| } |
| |
| #[repr(C, packed)] |
| pub struct usb_interface_descriptor_t { |
| pub bLength: u8, |
| pub bDescriptorType: u8, |
| pub bInterfaceNumber: u8, |
| pub bAlternateSetting: u8, |
| pub bNumEndpoints: u8, |
| pub bInterfaceClass: u8, |
| pub bInterfaceSubClass: u8, |
| pub bInterfaceProtocol: u8, |
| pub iInterface: u8, |
| } |
| |
| #[repr(C, packed)] |
| pub struct usb_endpoint_descriptor_t { |
| pub bLength: u8, |
| pub bDescriptorType: u8, |
| pub bEndpointAddress: u8, |
| pub bmAttributes: u8, |
| pub wMaxPacketSize: u16, |
| pub bInterval: u8, |
| } |
| |
| #[repr(C)] |
| pub struct usb_protocol_ops_t { |
| pub control: unsafe extern "C" fn (ctx: *mut u8, request_type: usb_request_type_t, request: u8, |
| value: u16, index: u16, data: *mut u8, length: usize, timeout: sys::zx_time_t, |
| out_length: *mut usize) -> sys::zx_status_t, |
| pub request_queue: unsafe extern "C" fn (ctx: *mut u8, usb_request: *mut usb_request_t), |
| pub get_speed: unsafe extern "C" fn (ctx: *mut u8) -> usb_speed_t, |
| pub set_interface: unsafe extern "C" fn (ctx: *mut u8, interface_number: i32, alt_setting: i32) |
| -> sys::zx_status_t, |
| pub set_configuration: unsafe extern "C" fn (ctx: *mut u8, configuration: i32) -> sys::zx_status_t, |
| pub reset_endpoint: unsafe extern "C" fn (ctx: *mut u8, ep_address: u8) -> sys::zx_status_t, |
| pub get_max_transfer_size: unsafe extern "C" fn (ctx: *mut u8, ep_address: u8) -> usize, |
| pub get_device_id: unsafe extern "C" fn (ctx: *mut u8) -> u32, |
| pub get_descriptor_list: unsafe extern "C" fn (ctx: *mut u8, out_descriptors: *mut *mut u8, |
| out_length: *mut usize) -> sys::zx_status_t, |
| pub get_additional_descriptor_list: unsafe extern "C" fn (ctx: *mut u8, out_descriptors: *mut *mut u8, |
| out_length: *mut usize) -> sys::zx_status_t, |
| pub claim_interface: unsafe extern "C" fn (ctx: *mut u8, intf: *mut usb_interface_descriptor_t, |
| length: usize) -> sys::zx_status_t, |
| pub cancel_all: unsafe extern "C" fn (ctx: *mut u8, ep_address: u8) -> sys::zx_status_t, |
| } |
| |
| #[repr(C)] |
| pub struct usb_protocol_t { |
| pub ops: *mut usb_protocol_ops_t, |
| pub ctx: *mut u8, |
| } |
| |
| impl Default for usb_protocol_t { |
| fn default() -> Self { |
| usb_protocol_t { |
| ops: std::ptr::null_mut(), |
| ctx: std::ptr::null_mut(), |
| } |
| } |
| } |
| |
| #[link(name = "ddk")] |
| extern "C" { |
| pub static __zircon_driver_rec__: zx_driver_rec_t; |
| |
| pub fn device_add_from_driver(driver: *mut zx_driver_t, parent: *mut zx_device_t, args: *mut device_add_args_t, out: *mut *mut zx_device_t) -> sys::zx_status_t; |
| pub fn device_remove(device: *mut zx_device_t) -> sys::zx_status_t; |
| pub fn device_rebind(device: *mut zx_device_t) -> sys::zx_status_t; |
| pub fn load_firmware(device: *mut zx_device_t, path: *const c_char, fw: *mut sys::zx_handle_t, size: *mut usize) -> sys::zx_status_t; |
| pub fn device_get_name(dev: *mut zx_device_t) -> *const c_char; |
| pub fn device_get_parent(dev: *mut zx_device_t) -> *mut zx_device_t; |
| pub fn device_get_protocol(dev: *mut zx_device_t, proto_id: u32, protocol: *mut u8) -> sys::zx_status_t; |
| pub fn device_read(dev: *mut zx_device_t, buf: *mut u8, count: usize, off: sys::zx_off_t, actual: *mut usize) -> sys::zx_status_t; |
| pub fn device_write(dev: *mut zx_device_t, buf: *const u8, count: usize, off: sys::zx_off_t, actual: *mut usize) -> sys::zx_status_t; |
| pub fn device_get_size(dev: *mut zx_device_t) -> sys::zx_off_t; |
| pub fn device_ioctl(dev: *mut zx_device_t, op: u32, in_buf: *const u8, in_len: usize, out_buf: *mut u8, out_len: usize, out_actual: *mut usize) -> sys::zx_status_t; |
| pub fn device_state_clr_set(dev: *mut zx_device_t, clearflag: sys::zx_signals_t, setflag: sys::zx_signals_t); |
| } |