Apple's iPhone has a configuration that sets up an interface for HID.
My goal is to connect to it and set HID reports to the endpoint on that interface.
The device I am using is an iPhone 6S.
My code iterates over all available configurations and their interfaces until it finds that HID interface (which is configuration 1 with interface 2).
Here is some diagnostic information about it:
Configuration #2
--------------------------------------------------------------------------------
Total length: 149 Interface count: 3
Configuration value: 2
Configuration index: 6
Attributes: 0xc0
Max. power: 250
Interface #1
Setting #1
Interface number: 0
Alternate setting: 0
Endpoint count: 0
Interface class: Audio
Interface sub-class: Audio
Interface protocol: 0
Interface index: 0
Interface #2
Setting #1
Interface number: 1
Alternate setting: 0
Endpoint count: 0
Interface class: Audio
Interface sub-class: Communcation
Interface protocol: 0
Interface index: 0
Setting #2
Interface number: 1
Alternate setting: 1
Endpoint count: 1
Interface class: Audio
Interface sub-class: Communcation
Interface protocol: 0
Interface index: 0
Endpoint 00
Endpoint Address: 0x81
Attributes: 0x1
Max. packetsize: 192
Interval: 4
Refresh: 0
Sync. Address: 0
Interface #3
Setting #1
Interface number: 2
Alternate setting: 0
Endpoint count: 1
Interface class: Human Interface Device
Interface sub-class: Interface Specific
Interface protocol: 0
Interface index: 0
Endpoint 00
Endpoint Address: 0x83
Attributes: 0x3
Max. packetsize: 64
Interval: 1
Refresh: 0
Sync. Address: 0
Now when I try to set the interface:
int err = libusb_set_configuration(handle, i);
I get a LIBUSB_ERROR_BUSY.
How can I fix that? What is wrong?
Try detaching kernel driver on the specific interfacing you want to set configuration and then set the configuration. Also check that setAutoDetachKernelDriver(interface_no) is set to false before detaching kernel driver.
Related
I'm running a simple tcp server at port 8080 with Netty that responds with hello when a connection is made.
class MyHandler : ChannelInboundHandlerAdapter() {
override fun channelActive(ctx: ChannelHandlerContext) {
val time = ctx.alloc().buffer(4)
time.writeBytes("hello".toByteArray())
val future = ctx.writeAndFlush(time)
future.addListener(ChannelFutureListener.CLOSE)
}
}
If I run nc localhost 8080, I get hello response. Everything ok. But when I change my code to respond with 1234 (integer) instead, I get an empty response from nc.
class MyHandler : ChannelInboundHandlerAdapter() {
override fun channelActive(ctx: ChannelHandlerContext) {
val time = ctx.alloc().buffer(4)
time.writeInt(1234) // <-- this is the change
val future = ctx.writeAndFlush(time)
future.addListener(ChannelFutureListener.CLOSE)
}
}
The nc program has no idea that you are sending an integer. So when it receives it, it has no idea what would be an appropriate way to display it.
If you were expecting to literally see "1234", then you were expecting magic. How could nc know that the data it received was an encoded integer? If you're going to implement a protocol to send data over TCP, you have to implement it on both ends or you will get garbage on the end that doesn't understand the protocol.
Trying to generate bindings for an Obj-C++ header which is a part of Superpowered crossplatform audio library with rust bindgen.
I am in Catalina 10.15.6,
clang version 10.0.1
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /usr/local/opt/llvm/bin
I got stuck with this error. Searched a lot but it seems rare.
I have tried to use the clang provided in the Xcode App bundle to try but couldn't manage to do it.
The library builds fine in Xcode, I didn't get the same error there.
The header :
#import <AVFoundation/AVFoundation.h>
/// #brief Output channel mapping for iOS audio I/O.
/// This structure maps the channels you provide in the audio processing callback to the appropriate output channels.
/// You can have multi-channel (more than a single stereo channel) output if a HDMI or USB audio device is connected. iOS does not provide multi-channel output for other audio devices, such as wireless audio accessories.
/// #em Example:
/// Let's say you have four output channels, and you'd like the first stereo pair on USB 3+4, and the other stereo pair on the iPad's headphone socket.
/// 1. Set deviceChannels[0] to 2, deviceChannels[1] to 3.
/// 2. Set USBChannels[2] to 0, USBChannels[3] to 1.
/// #em Explanation:
/// - Your four output channels are having the identifiers: 0, 1, 2, 3.
/// - Every iOS device has just one stereo built-in output. This is represented by deviceChannels, and (1.) sets your second stereo pair (2, 3) to these.
/// - You other stereo pair (0, 1) is mapped to USBChannels. USBChannels[2] represents the third USB channel.
/// #since Multi-channel output is available in iOS 6.0 and later.
typedef struct multiOutputChannelMap {
int deviceChannels[2]; ///< The iOS device's built-in output channels. Write only.
int HDMIChannels[8]; ///< HDMI output channels. Write only.
int USBChannels[32]; ///< USB output channels. Write only.
int numberOfHDMIChannelsAvailable; ///< Number of available HDMI output channels. Read only.
int numberOfUSBChannelsAvailable; ///< Number of available USB output channels. Read only.
bool headphoneAvailable; ///< Something is plugged into the iOS device's headphone socket or not. Read only.
} multiOutputChannelMap;
/// #brief Input channel mapping for iOS audio I/O.
/// Similar to the output channels, you can map the input channels to channels in the audio processing callback. This feature works with USB only.
/// Let's say you set the channel count to 4, so RemoteIO provides 4 input channel buffers. Using this struct, you can map which USB input channel appears on the specific buffer positions.
/// #since Available in iOS 6.0 and later.
/// #see #c multiOutputChannelMap
typedef struct multiInputChannelMap {
int USBChannels[32]; ///< Example: set USBChannels[0] to 3, to receive the input of the third USB channel on the first buffer. Write only.
int numberOfUSBChannelsAvailable; ///< Number of USB input channels. Read only.
} multiInputChannelMap;
#protocol SuperpoweredIOSAudioIODelegate;
/// #brief The audio processing callback prototype.
/// #return Return false for no audio output (silence).
/// #param clientData A custom pointer your callback receives.
/// #param inputBuffers Input buffers.
/// #param inputChannels The number of input channels.
/// #param outputBuffers Output buffers.
/// #param outputChannels The number of output channels.
/// #param numberOfFrames The number of frames requested.
/// #param samplerate The current sample rate in Hz.
/// #param hostTime A mach timestamp, indicates when this buffer of audio will be passed to the audio output.
typedef bool (*audioProcessingCallback) (void *clientData, float **inputBuffers, unsigned int inputChannels, float **outputBuffers, unsigned int outputChannels, unsigned int numberOfFrames, unsigned int samplerate, unsigned long long hostTime);
/// #brief Handles all audio session, audio lifecycle (interruptions), output, buffer size, samplerate and routing headaches.
/// #warning All methods and setters should be called on the main thread only!
#interface SuperpoweredIOSAudioIO: NSObject {
int preferredBufferSizeMs;
int preferredSamplerate;
bool saveBatteryInBackground;
bool started;
}
#property (nonatomic, assign) int preferredBufferSizeMs; ///< The preferred buffer size in milliseconds. Recommended: 12.
#property (nonatomic, assign) int preferredSamplerate; ///< The preferred sample rate in Hz.
#property (nonatomic, assign) bool saveBatteryInBackground; ///< Save battery if output is silence and the app runs in background mode. True by default.
#property (nonatomic, assign, readonly) bool started; ///< Indicates if the instance has been started.
/// #brief Constructor.
/// #param delegate The object fully implementing the SuperpoweredIOSAudioIODelegate protocol. Not retained.
/// #param preferredBufferSize The initial value for preferredBufferSizeMs. 12 is good for every iOS device (512 frames).
/// #param preferredSamplerate The preferred sample rate. 44100 or 48000 are recommended for good sound quality.
/// #param audioSessionCategory The audio session category. Audio input is enabled for the appropriate categories only!
/// #param channels The number of output channels in the audio processing callback regardless the actual hardware capabilities. The number of input channels in the audio processing callback will reflect the actual hardware configuration.
/// #param callback The audio processing callback.
/// #param clientdata Custom data passed to the audio processing callback.
- (id)initWithDelegate:(id<SuperpoweredIOSAudioIODelegate>)delegate preferredBufferSize:(unsigned int)preferredBufferSize preferredSamplerate:(unsigned int)preferredSamplerate audioSessionCategory:(NSString *)audioSessionCategory channels:(int)channels audioProcessingCallback:(audioProcessingCallback)callback clientdata:(void *)clientdata;
/// #brief Starts audio I/O.
/// #return True if successful, false if failed.
- (bool)start;
/// #brief Stops audio I/O.
- (void)stop;
/// #brief Call this to re-configure the channel mapping.
- (void)mapChannels;
/// #brief Call this to re-configure the audio session category (such as enabling/disabling recording).
- (void)reconfigureWithAudioSessionCategory:(NSString *)audioSessionCategory;
#end
/// #brief You MUST implement this protocol to use SuperpoweredIOSAudioIO.
#protocol SuperpoweredIOSAudioIODelegate
/// #brief The audio session may be interrupted by a phone call, etc. This method is called on the main thread when the interrupt starts.
#optional
- (void)interruptionStarted;
/// #brief The audio session may be interrupted by a phone call, etc. This method is called on the main thread when audio resumes.
#optional
- (void)interruptionEnded;
/// #brief Called if the user did not grant a recording permission for the app.
#optional
- (void)recordPermissionRefused;
/// #brief This method is called on the main thread when a multi-channel audio device is connected or disconnected.
/// #param outputMap Map the output channels here.
/// #param inputMap Map the input channels here.
/// #param externalAudioDeviceName The name of the attached audio device, such as the model of the sound card.
/// #param outputsAndInputs A human readable description about the available outputs and inputs.
#optional
- (void)mapChannels:(multiOutputChannelMap *)outputMap inputMap:(multiInputChannelMap *)inputMap externalAudioDeviceName:(NSString *)externalAudioDeviceName outputsAndInputs:(NSString *)outputsAndInputs;
#end
build.rs :
use std::env;
use std::path::PathBuf;
fn main() {
let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let out_dir = env::var("OUT_DIR").unwrap();
println!(
"cargo:rustc-flags=-l static=libSuperpoweredAudioIOS -L native={}/Superpowered",
manifest_dir
);
let bindings = bindgen::Builder::default()
.header("Superpowered/OpenSource/SuperpoweredIOSAudioIO.h")
.clang_arg("-ObjC++")
.clang_arg("-v")
.clang_arg("--target=arm64-apple-ios")
.clang_arg("--sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.6.sdk")
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.generate()
.expect("Unable to generate bindings");
let out_path = PathBuf::from(out_dir);
bindings
.write_to_file(out_path.join("SuperpoweredIOSAudioIOBindings.rs"))
.expect("Couldn't write bindings!");
}
Clang errors with :
--- stderr
clang version 5.0.2 (tags/RELEASE_502/final)
Target: arm64-apple-ios
Thread model: posix
InstalledDir:
ignoring nonexistent directory "/usr/include"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.6.sdk/usr/include/c++/v1"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.6.sdk/usr/local/include"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.6.sdk/Library/Frameworks"
ignoring duplicate directory "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.6.sdk/usr/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/Cellar/llvm/10.0.1_1/lib/clang/10.0.1/include
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.6.sdk/usr/include
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.6.sdk/System/Library/Frameworks
/usr/local/opt/llvm#5/include/c++/v1
/usr/local/opt/llvm#5/lib/clang/5.0.2/include
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.6.sdk/System/Library/Frameworks (framework directory)
End of search list.
/usr/local/Cellar/llvm/10.0.1_1/lib/clang/10.0.1/include/arm_neon.h:32395:25: error: incompatible constant for this __builtin_neon function
/usr/local/Cellar/llvm/10.0.1_1/lib/clang/10.0.1/include/arm_neon.h:32416:25: error: incompatible constant for this __builtin_neon function
/usr/local/Cellar/llvm/10.0.1_1/lib/clang/10.0.1/include/arm_neon.h:33990:23: error: use of undeclared identifier '__builtin_neon_vrndns_f32'
/usr/local/Cellar/llvm/10.0.1_1/lib/clang/10.0.1/include/arm_neon.h:32395:25: error: incompatible constant for this __builtin_neon function, err: true
/usr/local/Cellar/llvm/10.0.1_1/lib/clang/10.0.1/include/arm_neon.h:32416:25: error: incompatible constant for this __builtin_neon function, err: true
/usr/local/Cellar/llvm/10.0.1_1/lib/clang/10.0.1/include/arm_neon.h:33990:23: error: use of undeclared identifier '__builtin_neon_vrndns_f32', err: true
Got stuck here, any ideas ?
Found this here:
def err_invalid_neon_type_code : Error<
"incompatible constant for this __builtin_neon function">
Latest news :) :
--target=armv7-apple-ios builds fine.
--target=arm64-apple-ios has the error.
I have updated to Xcode 12.0, will try and report.
Try --target=aarch64-apple-ios. At least rustup target list doesn't have arm64-apple-ios, it has aarch64-apple-ios.
Intro:
I've been trying (and failing for four entire days straight so far) to get my Atmega32u4 device (Arduino Pro Micro) to emulate an Xbox controller.
It doesn't have to pretend it's an Xbox controller, but I need to communicate with the XInput driver, so emulating an official controller seemed like the best way to start.
The problem:
When using the code example XInputPadMicro by Bootsector it gets me exactly halfway. My device can either read OR write from/to the device driver. But not both. Getting both to work is essential to my project.
The code:
Device/Configuration descriptor can be found in XInputPadMicro (I
haven't changed these).
Configuration changed event:
Enabling the "OUT" endpoint will break the "IN" endpoint.
#define JOYSTICK_EPADDR_IN (ENDPOINT_DIR_IN | 1)
#define JOYSTICK_EPADDR_OUT (ENDPOINT_DIR_OUT | 1)
void EVENT_USB_Device_ConfigurationChanged(void)
{
bool ConfigSuccess = true;
ConfigSuccess &= Endpoint_ConfigureEndpoint(JOYSTICK_EPADDR_IN, EP_TYPE_INTERRUPT, 20, 1);
//If I enable this, the "IN" Endpoint will stop sending data.
//ConfigSuccess &= Endpoint_ConfigureEndpoint(JOYSTICK_EPADDR_OUT, EP_TYPE_INTERRUPT, 8, 1);
}
USB control request event:
void EVENT_USB_Device_ControlRequest(void)
{
/* Handle HID Class specific requests */
switch (USB_ControlRequest.bRequest)
{
case HID_REQ_GetReport:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_Write_Control_Stream_LE(&gamepad_state, 20);
Endpoint_ClearIN();
}
break;
case HID_REQ_SetReport:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_Read_Control_Stream_LE(&RXData, 8);
Endpoint_ClearOUT();
}
break;
}
}
HID Task (called every cycle):
void HID_Task(void)
{
/* Device must be connected and configured for the task to run */
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
Endpoint_SelectEndpoint(JOYSTICK_EPADDR_OUT);
if (Endpoint_IsOUTReceived())
{
toggle = !toggle;
SetLED(LED3, toggle);
Endpoint_Read_Stream_LE(&RXData, 8, NULL);
SetLED(LED1, RXData[3] > 0 || RXData[4] > 0);
Endpoint_ClearOUT();
}
/* Select the Joystick Report Endpoint */
Endpoint_SelectEndpoint(JOYSTICK_EPADDR_IN);
/* Check to see if the host is ready for another packet */
if (Endpoint_IsINReady())
{
/* Write Joystick Report Data */
Endpoint_Write_Stream_LE(&gamepad_state, 20, NULL);
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
}
}
Am I missing something crucial? Perhaps about the inner workings of the USB protocol? I am at a loss here.
I'm trying to trigger an interrupt function each time I receive a broadcast message on a given port of an STM32 board (Nucleo f429zi). The communication protocol I use is UDP and the mbed library is UDPSocket which inherits from Socket.
Does anyone have an idea how to achieve it?
Edit:
Thanks to PeterJ's comment I found an interesting (but deprecated) member function of the class Socket which is called attach(). This method registers a callback on state change of the socket (recv/send/accept).
Since I have an incoming broadcast on the socket, there is no state change in my case (only receiving data, never sending). Is there a way I could use this attach() method to detect every message received?
// Open Ethernet connection
EthernetInterface eth;
eth.connect();
// Create an UDP socket for listening to the broadcast
UDPSocket broadcastSocket;
broadcastSocket.open(ð);
broadcastSocket.bind(BROADCAST_PORT);
// Function to call when a broadcast message is received
broadcastSocket.attach(&onUDPSocketEvent);
void onUDPSocketEvent(){
printf("UDP event detected\n");
}
attach has been replaced by sigio, but I don't think it's going to do what you want. A nice way would be to spin up a new thread, and use this thread to handle the socket.
void onUDPSocketEvent(void* buffer, size_t size) {
printf("UDP event detected\n");
}
void udp_main() {
// Open Ethernet connection
EthernetInterface eth;
eth.connect();
// Create an UDP socket for listening to the broadcast
UDPSocket broadcastSocket;
broadcastSocket.open(ð);
broadcastSocket.bind(BROADCAST_PORT);
void* recvBuffer = malloc(1024);
while (1) {
// this blocks until next packet comes in
nsapi_size_or_error_t size = broadcastSocket.recvfrom(NULL, recvBuffer, 1024);
if (size < 0) {
printf("recvfrom failed with error code %d\n", size);
}
onUDPSocketEvent(recvBuffer, size);
}
}
int main() {
Thread t; // can pass in the stack size here if you run out of memory
t.start(&udp_main);
while (1) {
wait(osWaitForever);
}
}
(note that the callback function does not run in an ISR - so not in an interrupt context - but I assume you don't actually want that).
Edit: I have created mbed-udp-ping-pong which shows how to listen for UDP messages on a separate thread.
I have a processing program working on a local machine. It reads data from a local udp port and uses this data to draw circles on my screen. It works, so that great.
But in production the program has to run on an other computer. And I cant get it to work. Processing is presenting me this error message:
opening socket failed!
> address:192.168.1.118, port:6666 [group:null]
> Cannot assign requested address: Cannot bind
Of cource I checked the IP adress and these are OK as it works fine on the local machine. Here is my code for the UDP part:
// import UDP library
import hypermedia.net.*;
String HOST_IP = "192.168.1.118";
UDP udp; // define the UDP object
// get an array ready
int num = 20;
int[] xx = new int[num];
int[] yy = new int[num];
void setup() {
size(1024, 768);
smooth();
//noStroke();
// create a new datagram connection on port 6666
udp = new UDP(this, 6666, HOST_IP);
udp.listen( true );
}
//process events
void draw() {;}
/**
* To perform any action on datagram reception, you need to implement this
* handler in your code. This method will be automatically called by the UDP
* object each time he receive a nonnull message.
* By default, this method have just one argument (the received message as
* byte[] array), but in addition, two arguments (representing in order the
* sender IP address and his port) can be set like below.
*/
// void receive( byte[] data ) { // <-- default handler
void receive( byte[] data ) {
background(255);
// get the "real" message =
// forget the ";\n" at the end <-- !!! only for a communication with Pd !!!
data = subset(data, 0, data.length-2);
String message = new String( data );
// print the result
println(message );
On both machines I use Windows XP And they are connected via a switch and udp cables.
I don't know where to start troubleshooting and how. Any ideas?