У меня есть следующий код для чтения и записи в последовательные порты на iOS 10.3.3 Jailbroken iPhone 6S (я использовал h3lix для джейлбрейка):
serial.h:
//
// Serial.h
// iOUSB
//
// Created by Brandon on 2018-05-21.
// Copyright © 2018 XIO. All rights reserved.
//
#if !defined(__cplusplus) //-fmodules -fcxx-modules
@import Foundation;
#else
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wauto-import"
#import <Foundation/Foundation.h>
#pragma clang diagnostic pop
#endif
#define BAUD_RATE 9600
@interface Serial : NSObject
+ (instancetype)shared;
- (bool)setup:(NSString *)filePath;
- (bool)disconnect;
- (size_t)available;
- (size_t)read:(uint8_t *)bytes length:(int32_t)length;
- (size_t)write:(uint8_t *)bytes length:(int32_t)length;
- (void)flushInputStream;
- (void)flushOutputStream;
- (void)flush;
- (NSString *)lastError;
- (void)eraseLastError;
@end
Serial.mm:
//
// Serial.mm
// iOUSB
//
// Created by Brandon on 2018-05-21.
// Copyright © 2018 XIO. All rights reserved.
//
#import "Serial.h"
#include <fstream>
#include <iostream>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
#define DEFAULT_BAUD_RATE 9600
@interface Serial()
@property (nonatomic, assign) int file_descriptor;
@property (nonatomic, strong) NSString *lastError;
@end
@implementation Serial
+ (instancetype)shared {
static Serial *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[Serial alloc] init];
});
return instance;
}
- (instancetype)init {
if ((self = [super init])) {
self.file_descriptor = -1;
self.lastError = nil;
}
return self;
}
- (void)dealloc {
[self disconnect];
}
- (bool)setup:(NSString *)filePath {
if (self.file_descriptor != -1)
{
return true;
}
self.file_descriptor = open(filePath.UTF8String, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
if (self.file_descriptor == -1)
{
const char* error = strerror(errno);
self.lastError = [[NSString alloc] initWithUTF8String:error];
perror(error);
return false;
}
struct termios options;
struct termios oldoptions;
tcgetattr(self.file_descriptor, &oldoptions);
options = oldoptions;
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
int baud_rates[] = {B0, B50, B75, B110, B134, B150, B200, B300, B1200, B1800, B2400, B4800, B9600, B19200, B38400, B7200, B14400, B28800, B57600, B76800, B115200, B230400
};
#else
int baud_rates[] = {B0, B50, B75, B110, B134, B150, B200, B300, B1200, B1800, B2400, B4800, B9600, B19200, B38400};
#endif
auto it = std::find(std::begin(baud_rates), std::end(baud_rates), BAUD_RATE);
if (it != std::end(baud_rates))
{
cfsetispeed(&options, *it);
cfsetospeed(&options, *it);
std::cout<<"BAUD_RATE Set Successfully!\n";
}
else
{
cfsetispeed(&options, DEFAULT_BAUD_RATE);
cfsetospeed(&options, DEFAULT_BAUD_RATE);
std::cerr<<"Invalid BAUD_RATE.. Setting to default: "<<DEFAULT_BAUD_RATE<<"\n";
}
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag |= CS8;
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
tcsetattr(self.file_descriptor, TCSANOW, &options);
return true;
}
- (bool)disconnect {
if (self.file_descriptor != -1)
{
close(self.file_descriptor);
self.file_descriptor = -1;
self.lastError = nil;
}
return self.file_descriptor == -1;
}
- (size_t)available {
if (self.file_descriptor == -1)
{
return -1;
}
int available = -1;
ioctl(self.file_descriptor, FIONREAD, &available);
return available;
}
- (size_t)read:(uint8_t *)bytes length:(int32_t)length {
if (self.file_descriptor == -1)
{
return -1;
}
ssize_t bytesRead = read(self.file_descriptor, bytes, length);
if (bytesRead < 0)
{
const char* error = strerror(errno);
self.lastError = [[NSString alloc] initWithUTF8String:error];
perror(error);
}
return bytesRead;
}
- (size_t)write:(uint8_t *)bytes length:(int32_t)length {
if (self.file_descriptor == -1)
{
return -1;
}
ssize_t bytesWritten = write(self.file_descriptor, bytes, length);
if (bytesWritten <= 0)
{
const char* error = strerror(errno);
self.lastError = [[NSString alloc] initWithUTF8String:error];
perror(error);
}
return bytesWritten;
}
- (void)flushInputStream {
if (self.file_descriptor == -1)
{
return;
}
tcflush(self.file_descriptor, TCIFLUSH);
}
- (void)flushOutputStream {
if (self.file_descriptor == -1)
{
return;
}
tcflush(self.file_descriptor, TCOFLUSH);
}
- (void)flush {
if (self.file_descriptor == -1)
{
return;
}
tcflush(self.file_descriptor, TCIOFLUSH);
}
- (NSString *)lastError {
return _lastError ?: @"";
}
- (void)eraseLastError {
_lastError = nil;
}
@end
Я приобрел адаптер OTG: "Lightning to USB 3 Camera Adapter", показанный здесь: https://www.apple.com/ca/shop/product/MK0W2AM/A/lightning-to-usb-3-camera-adapter
Я подключил устройство, и оно отображается как неподдерживаемое устройство, которое прекрасно, поскольку оно не сертифицировано MFI.
Однако, когда я пытаюсь открыть /dev/tty.iap
, я продолжаю получать Error: Resource Busy
.
Например, я могу открыть /dev/tty.wlan
. Только некоторые порты дают мне проблемы, такие как iap
.
Что я делаю неправильно, что не могу прочитать tty.iap
? Я попытался запустить приложение как root, переместив его в /Applications
из /var/containers/Bundle/Applications
. Я попытался выполнить chown root:wheel
запустите приложение и приложение chmod 0777
. Тем не менее я получаю resource busy
.
Я читал в Интернете, что вы получаете эту ошибку, когда вы НЕ root.
Как запустить приложение под учетной записью root? Как я могу исправить это, чтобы я мог прочитать порт молнии?
Я пробовал qaru.site/info/150995/... но он не работает. Приложение запустится, а затем немедленно закроется независимо от того, сколько раз я пытаюсь.