1、Linux要与苹果手机通讯需要两个组件
1、usbmuxd 是苹果的一个服务,这个服务主要用于在USB协议上实现多路TCP连接,将USB通信抽象为TCP通信。苹果的iTunes、Xcode,都直接或间接地用到了这个服务。
参考链接:https://www.theiphonewiki.com/wiki/Usbmux
2、libimobiledevice是一个跨平台的软件库,用于与iOS设备进行交互。
参考链接:https://www.theiphonewiki.com/wiki/MobileDevice_Library
编译安装上面2个库就直接可以使用socket套接字进行通讯
上代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <errno.h>
#include <stddef.h>
#include <unistd.h>
#include <pthread.h>
#define MAX_CONNECT_NUM 2
#define BUFFER_SIZE 1024
const char *filename = "/var/run/usbmuxd";
static pthread_t th;
static pthread_t th1;
//sudo mv /var/run/usbmuxd /var/run/usbmuxx
// sudo socat -t100 -x -v UNIX-LISTEN:/var/run/usbmuxd,mode=777,reuseaddr,fork UNIX-CONNECT:/var/run/usbmuxx
void *thread_recv(void *ptr)
{
int fd = *(int *)ptr;
char buffer[BUFFER_SIZE];
bzero(buffer, BUFFER_SIZE);
while (1)
{
printf("waiting recv...\n");
int ret = recv(fd, buffer, BUFFER_SIZE, 0);
if (ret <= 0)
{
printf("recv failed\n");
close(fd);
pthread_cancel(th1);
return NULL;
}
printf("%s\n", buffer);
if (strncmp("end", buffer, 3) == 0)
{
close(fd);
exit(0);
}
}
}
void *thread_send(void *ptr)
{
int fd = *(int *)ptr;
while(1)
{
char buff[128] = {0};
fgets(buff, 128, stdin);
int ret = send(fd, buff, 128, 0);
if (ret <= 0)
{
close(fd);
pthread_cancel(th);
return NULL;
}
}
}
int main()
{
int fd, new_fd, len, i;
//struct sockaddr_un结构有两个参数:sun_family、sun_path
//sun_family只能是AF_LOCAL或AF_UNIX,而sun_path是本地文件的路径。
struct sockaddr_un un;
fd = socket(AF_UNIX, SOCK_STREAM, 0);//SOCK_DGRAM是基于UDP的
//本地套接字的通讯类型应该是SOCK_STREAM或SOCK_DGRAM,协议为默认协议。
if (fd < 0)
{
printf("Request socket failed!\n");
return -1;
}
un.sun_family = AF_UNIX;
strcpy(un.sun_path, filename);
if (bind(fd, (struct sockaddr *)&un, sizeof(un)) < 0)
{
printf("bind failed!\n");
return -1;
}
if (listen(fd, MAX_CONNECT_NUM) < 0)
{
printf("listen failed!\n");
return -1;
}
while (1)
{
printf("wait to accept...\n");
new_fd = accept(fd, NULL, NULL);
printf("new accept.\n");
if (new_fd < 0)
{
printf("accept failed\n");
return -1;
}
pthread_create(&th, NULL, thread_recv, (void *)(&new_fd));
pthread_create(&th1, NULL, thread_send, (void *)(&new_fd));
}
close(fd);
}
2、Linux要与Android手机通讯只需要一个库
libusb是一个开源的用C实现的,应用程序与用户的USB设备进行通信的库。 链接地址:https://github.com/libusb/libusb
编译安装好上面的库后直接可以使用AOA进行通讯了
AOA说明:手机通过USB连接到设备时,触发一次插入事件,设备通过VID和PID来判断USB是否为AOA模式
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include "libusb.h"
/*手机通过USB连接到设备时,触发一次插入事件,设备通过VID和PID来判断USB是否为AOA模式
不是AOA模式:则进入切换到AOA模式流程
1.打开usb设备
2.发送AOA协议报文交互
3.关闭usb设备
USB会出现一次逻辑拔插过程:触发一次拔出事件和一次插入事件,手机切换VID和PID为AOA模式
4.USB已切换为AOA模式
5.获取USB接口信息
6.打开USB设备并声明读写接口,建立AOA数据通道
是AOA模式:
1.获取USB接口信息
2.打开USB设备并声明读写接口,建立AOA数据通道*/
#define BULK_RECV_EP 0x83
#define BULK_SEND_EP 0x02
#define INT_RECV_EP 0x81
#define INT_SEND_EP 0x01
#define VID_GOOGLE 0x18D1
#define PID_AOA_ACC 0x2D00
#define PID_AOA_ACC_ADB 0x2D01
#define PID_AOA_AU 0x2D02
#define PID_AOA_AU_ADB 0x2D03
#define PID_AOA_ACC_AU 0x2D04
#define PID_AOA_ACC_AU_ADB 0x2D05
//PID 模式
//0x2D00 accessory
//0x2D01 accessory + adb
//0x2D02 audio
//0x2D03 audio + adb
//0x2D04 accessory + audio
//0x2D05 accessory + audio + adb
static char manufacturer[] = "Lutixia";
static char modelName[] = "Demo";
static char description[] = "Android Aoa Interface";
static char version[] = "1.0";
static char uri[] = "https://www.baidu.com/";
static char serialNumber[] = "1234567890";
typedef struct
{
unsigned int pid;
unsigned int vid;
unsigned char bInEndpointAddress;
unsigned char bOutEndpointAddress;
unsigned char bInterfaceNumber;
libusb_device *dev;
pthread_mutex_t stLock;
libusb_device_handle *handle;
libusb_hotplug_callback_handle hotplugCbh;
int event;
int bNumConfigurations;
//libusb_device **devs;
} usb_dev_mngr_s;
static usb_dev_mngr_s gstUsbMngr;
void usb_error(int code, int line)
{
fprintf(stdout,"line %d:", line);
switch (code)
{
case LIBUSB_ERROR_IO:
fprintf(stderr, "LIBUSB_ERROR_IO\n");
break;
case LIBUSB_ERROR_INVALID_PARAM:
fprintf(stderr, "LIBUSB_ERROR_INVALID_PARAM\n");
break;
case LIBUSB_ERROR_ACCESS:
fprintf(stderr, "Error: LIBUSB_ERROR_ACCESS\n");
break;
case LIBUSB_ERROR_NO_DEVICE:
fprintf(stderr, "LIBUSB_ERROR_NO_DEVICE\n");
break;
case LIBUSB_ERROR_NOT_FOUND:
fprintf(stderr, "LIBUSB_ERROR_NOT_FOUND\n");
break;
case LIBUSB_ERROR_BUSY:
fprintf(stderr, "LIBUSB_ERROR_BUSY\n");
break;
case LIBUSB_ERROR_TIMEOUT:
fprintf(stderr, "LIBUSB_ERROR_TIMEOUT\n");
break;
case LIBUSB_ERROR_OVERFLOW:
fprintf(stderr, "LIBUSB_ERROR_OVERFLOW\n");
break;
case LIBUSB_ERROR_PIPE:
fprintf(stderr, "LIBUSB_ERROR_PIPE\n");
break;
case LIBUSB_ERROR_INTERRUPTED:
fprintf(stderr, "LIBUSB_ERROR_INTERRUPTED\n");
break;
case LIBUSB_ERROR_NO_MEM:
fprintf(stderr, "LIBUSB_ERROR_NO_MEM\n");
break;
case LIBUSB_ERROR_NOT_SUPPORTED:
fprintf(stderr, "LIBUSB_ERROR_NOT_SUPPORTED\n");
break;
case LIBUSB_ERROR_OTHER:
fprintf(stderr, "LIBUSB_ERROR_OTHER\n");
break;
default:
fprintf(stderr,"unkown error\n");
break;
}
}
static int usb_getEndpoint(const struct libusb_interface_descriptor * interface, usb_dev_mngr_s* user_device)
{
int i;
int ret = 0;
const struct libusb_endpoint_descriptor *epdesc;
for(i=0; i<interface->bNumEndpoints; i++)
{
epdesc = &interface->endpoint[i];
if(epdesc->bmAttributes == LIBUSB_TRANSFER_TYPE_BULK) //transfer type :bulk
{
if(epdesc->bEndpointAddress & LIBUSB_ENDPOINT_IN) // in endpoint
{
printf("EP IN: %02x \n", epdesc->bEndpointAddress);
user_device->bInEndpointAddress = epdesc->bEndpointAddress;
}
//else if (epdesc->bEndpointAddress & LIBUSB_ENDPOINT_OUT)// out endpoint
else if (!(epdesc->bEndpointAddress & LIBUSB_ENDPOINT_IN))
{
printf("EP OUT: %02x \n", epdesc->bEndpointAddress);
user_device->bOutEndpointAddress = epdesc->bEndpointAddress;
}
}
if (user_device->bInEndpointAddress && user_device->bOutEndpointAddress)
{
ret = 1;
break;
}
}
return ret;
}
//获取USB的信息
static int usb_getUSBInfo(usb_dev_mngr_s* user_device)
{
int rv = -1;
int i,j,k;
struct libusb_config_descriptor *conf_desc = NULL;
const struct libusb_interface *inter;
const struct libusb_interface_descriptor *interdesc;
for (i = 0; i < user_device->bNumConfigurations; i++)
{
if(user_device->dev != NULL)
{
if (LIBUSB_SUCCESS != libusb_get_config_descriptor(user_device->dev, i, &conf_desc))
{
continue;
}
}
for (j = 0; j < conf_desc->bNumInterfaces; j++)
{
inter = &conf_desc->interface[j];
for (k=0; k < inter->num_altsetting; k++)
{
interdesc = &inter->altsetting[k];
if(interdesc->bInterfaceClass == LIBUSB_CLASS_VENDOR_SPEC && interdesc->bInterfaceSubClass == LIBUSB_CLASS_VENDOR_SPEC)
{
if (user_device->bInEndpointAddress <= 0 || user_device->bOutEndpointAddress <= 0)
{
if(usb_getEndpoint(interdesc, user_device))
{
user_device->bInterfaceNumber = interdesc->bInterfaceNumber;
rv = 0;
break;
}
}
}
else
{
printf("bInterfaceClass:%02x, bInterfaceSubClass:%02x\n", interdesc->bInterfaceClass, interdesc->bInterfaceSubClass);
}
}
}
libusb_free_config_descriptor(conf_desc);
conf_desc = NULL;
if (0 == rv)
{
break;
}
}
return rv;
}
//检查安卓设备是否处于Accessory模式
static int usb_checkAccessory(uint16_t idVendor, uint16_t idProduct)
{
if (idVendor == VID_GOOGLE)
{
switch (idProduct)
{
case PID_AOA_ACC:
case PID_AOA_ACC_ADB:
case PID_AOA_ACC_AU:
case PID_AOA_ACC_AU_ADB:
return 1;
//音频
case PID_AOA_AU:
case PID_AOA_AU_ADB:
break;
default:
break;
}
}
return 0;
}
static int usb_sendCtrl(libusb_device_handle *handle, char *buff, int req, int index)
{
int ret = 0;
if (NULL != buff)
{
ret = libusb_control_transfer(handle, 0x40, req, 0, index, buff, strlen(buff) + 1, 0);
}
else
{
ret = libusb_control_transfer(handle, 0x40, req, 0, index, NULL, 0, 0);
}
if (ret < 0) {
usb_error(ret, __LINE__);
}
return ret;
}
static int usb_setupAccessory(libusb_device *dev)
{
unsigned char ioBuffer[2] = {0};
int aoaVersion;
int ret = 0;
libusb_device_handle *handle = NULL;
ret = libusb_open (dev, &handle);
if (LIBUSB_SUCCESS != ret)
{
printf("libusb_open failed, ret:%d\n", ret);
usb_error(ret, __LINE__);
return -1;
}
//如果USB连接到内核驱动则进行 detach
//libusb_set_auto_detach_kernel_driver(gstUsbMngr.handle, 1);
if(libusb_kernel_driver_active(handle, 0) > 0)
{
printf("kernel driver active, ignoring device");
if(libusb_detach_kernel_driver(handle, 0) != LIBUSB_SUCCESS)
{
printf("failed to detach kernel driver, ignoring device");
goto EXIT;;
}
}
//发送序号为51的USB报文,获取手机的AOA协议版本,目前为1或2
ret = libusb_control_transfer(handle, 0xC0, 51, 0, 0, ioBuffer, 2, 1000);
if (ret < 0)
{
usb_error(ret, __LINE__);
goto EXIT;
}
aoaVersion = ioBuffer[1] << 8 | ioBuffer[0];
printf("AOA Verion: %d \n", aoaVersion);
if (aoaVersion != 1 && aoaVersion != 2)
{
goto EXIT;
}
ret = -1;
usleep(1000);
//发送序号为52的USB报文,涉及制造商、型号、版本、设备描述、序列号、uri
if (usb_sendCtrl(handle, manufacturer, 52, 0) < 0) {
goto EXIT;
}
if (usb_sendCtrl(handle, modelName, 52, 1) < 0) {
goto EXIT;
}
if (usb_sendCtrl(handle, description, 52, 2) < 0) {
goto EXIT;
}
if (usb_sendCtrl(handle, version, 52, 3) < 0) {
goto EXIT;
}
if (usb_sendCtrl(handle, uri, 52, 4) < 0) {
goto EXIT;
}
if (usb_sendCtrl(handle, serialNumber, 52, 5) < 0) {
goto EXIT;
}
printf("Accessory Identification sent\n");
//发送序号为53的USB报文,切换USB模式
if (usb_sendCtrl(handle, NULL, 53, 0) < 0) {
goto EXIT;
}
ret = 0;
EXIT:
libusb_close(handle);
handle = NULL;
return ret;
}
static int usb_openUSB(void)
{
int rc = 0;
rc = libusb_open(gstUsbMngr.dev, &gstUsbMngr.handle);
if (LIBUSB_SUCCESS != rc)
{
return -1;
}
//声明读写接口
rc = libusb_claim_interface(gstUsbMngr.handle, gstUsbMngr.bInterfaceNumber);
if (LIBUSB_SUCCESS != rc)
{
libusb_close(gstUsbMngr.handle);
gstUsbMngr.handle = NULL;
return -1;
}
return 0;
}
/*
不能在usb_hotplugCallback调用usb_handleHotplugArrived和usb_handleHotplugLeft
否则会出现LIBUSB_ERROR_BUSY
*/
int usb_handleHotplugArrived(void)
{
int rc = 0;
printf("===>> usb_handleHotplugArrived \n");
pthread_mutex_lock(&gstUsbMngr.stLock);
if (!usb_checkAccessory(gstUsbMngr.vid, gstUsbMngr.pid))//不是AOA模式
{
rc = usb_setupAccessory(gstUsbMngr.dev);
if (rc)
{
fprintf (stderr, "usb_setupAccessory Error, rc:%d\n", rc);
pthread_mutex_unlock(&gstUsbMngr.stLock);
return -1;
}
}
else //是AOA模式
{
rc = usb_getUSBInfo(&gstUsbMngr);
if (rc)
{
fprintf (stderr, "usb_getUSBInfo Error, rc:%d\n", rc);
pthread_mutex_unlock(&gstUsbMngr.stLock);
return -1;
}
rc = usb_openUSB();
if (rc)
{
fprintf (stderr, "usb_openUSB Error, rc:%d\n", rc);
pthread_mutex_unlock(&gstUsbMngr.stLock);
return -1;
}
}
pthread_mutex_unlock(&gstUsbMngr.stLock);
return 0;
}
//LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT 设备拔出事件
int usb_handleHotplugLeft(void)
{
if (gstUsbMngr.handle)
{
libusb_release_interface (gstUsbMngr.handle, gstUsbMngr.bInterfaceNumber);
libusb_close (gstUsbMngr.handle);
gstUsbMngr.handle = NULL;
}
return 0;
}
//USB 插入回调函数
static int LIBUSB_CALL usb_hotplugCallback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
int rc;
struct libusb_device_descriptor desc;
pthread_mutex_lock(&gstUsbMngr.stLock);
rc = libusb_get_device_descriptor(dev, &desc);
if (LIBUSB_SUCCESS != rc) {
fprintf (stderr, "Error getting device descriptor\n");
pthread_mutex_unlock(&gstUsbMngr.stLock);
return -1;
}
if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)//插入
{
if (0x1d6b == desc.idVendor && 0x0002 == desc.idProduct) //过滤设备本身存在的usb设备
{
pthread_mutex_unlock(&gstUsbMngr.stLock);
return 0;
}
printf ("Device attached: %04x:%04x\n", desc.idVendor, desc.idProduct);
gstUsbMngr.vid = desc.idVendor;
gstUsbMngr.pid = desc.idProduct;
gstUsbMngr.bInEndpointAddress = 0;
gstUsbMngr.bOutEndpointAddress = 0;
gstUsbMngr.bNumConfigurations = desc.bNumConfigurations;
gstUsbMngr.dev = dev;
gstUsbMngr.event = event;
}
else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT)//拔出
{
printf ("Device detached: %04x:%04x\n", desc.idVendor, desc.idProduct);
gstUsbMngr.event = event;
}
else
{
printf("event wrong, event: %d \n", event);
gstUsbMngr.event = 0;
}
pthread_mutex_unlock(&gstUsbMngr.stLock);
return 0;
}
//监听事件
void *usb_eventMonitorProcess(void *args)
{
int rc = 0;
while(1)
{
//处理事件
//IBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED设备插入事件
//LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT 设备拔出事件
if (gstUsbMngr.event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED)
{
usb_handleHotplugArrived();
gstUsbMngr.event = 0;
}
else if (gstUsbMngr.event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT)
{
usb_handleHotplugLeft();
gstUsbMngr.event = 0;
}
//事件循环(阻塞),读写USB会触发
rc = libusb_handle_events(NULL);
if (rc < 0)
{
printf("libusb_handle_events() failed: %s\n", libusb_error_name(rc));
}
}
return NULL;
}
int usb_write(char *buf, int bufLen)
{
int rc = 0;
int nActualBytes = 0;
pthread_mutex_lock(&gstUsbMngr.stLock);
if (NULL == gstUsbMngr.handle || 0 != gstUsbMngr.event)
{
pthread_mutex_unlock(&gstUsbMngr.stLock);
return -1;
}
rc = libusb_bulk_transfer(gstUsbMngr.handle, gstUsbMngr.bOutEndpointAddress, (unsigned char *)buf, bufLen, &nActualBytes, 1000);
if (rc < 0)
{
printf("libusb_bulk_transfer(0x01) write failed:[%s] \n", libusb_strerror(rc));
pthread_mutex_unlock(&gstUsbMngr.stLock);
return rc;
}
pthread_mutex_unlock(&gstUsbMngr.stLock);
return nActualBytes;
}
int usb_read(char *buf, int bufLen)
{
int rc = 0;
int nActualBytes = 0;
pthread_mutex_lock(&gstUsbMngr.stLock);
if (NULL == gstUsbMngr.handle || 0 != gstUsbMngr.event)
{
pthread_mutex_unlock(&gstUsbMngr.stLock);
return -1;
}
rc = libusb_bulk_transfer(gstUsbMngr.handle, gstUsbMngr.bInEndpointAddress, (unsigned char *)buf, bufLen, &nActualBytes, 1000);
if (rc < 0)
{
//printf("libusb_bulk_transfer(0x81) read failed:[%s] \n", libusb_strerror(rc));
pthread_mutex_unlock(&gstUsbMngr.stLock);
return rc;
}
pthread_mutex_unlock(&gstUsbMngr.stLock);
return nActualBytes;
}
//测试读写
void *usb_readProcess(void *args)
{
int rc = 0;
char readBuf[4*1024] = {0};
int nActualBytes = 0;
while (1)
{
if (NULL == gstUsbMngr.handle)
{
usleep(100*1000);
continue;
}
rc = usb_read(readBuf, sizeof(readBuf));
if (rc > 0)
{
usb_write(readBuf, rc);
}
}
}
int usb_init(void)
{
int product_id, vendor_id, class_id;
int rc;
pthread_t tid;
vendor_id = LIBUSB_HOTPLUG_MATCH_ANY;//设置为 LIBUSB_HOTPLUG_MATCH_ANY 来匹配所有
product_id = LIBUSB_HOTPLUG_MATCH_ANY;//设置为 LIBUSB_HOTPLUG_MATCH_ANY 来匹配所有
class_id = LIBUSB_HOTPLUG_MATCH_ANY;//设置为 LIBUSB_HOTPLUG_MATCH_ANY 来匹配所有
memset(&gstUsbMngr, 0x0, sizeof(usb_dev_mngr_s));
rc = pthread_mutex_init(&gstUsbMngr.stLock, NULL);
if (rc)
{
printf("pthread_mutex_init failed \n");
return EXIT_FAILURE;
}
rc = libusb_init (NULL);
if (rc < 0)
{
printf("failed to initialise libusb: %s\n", libusb_error_name(rc));
return EXIT_FAILURE;
}
//获取当前库是否支持热插拔
if (!libusb_has_capability (LIBUSB_CAP_HAS_HOTPLUG)) {
printf("Hotplug capabilities are not supported on this platform\n");
libusb_exit (NULL);
return EXIT_FAILURE;
}
//注册热插拔事件回调
//配件向 endpoint 0 端口中写入 51 号指令,
//如果返回值为1 或者 2,则说明Android 设备支持 AOA1.0 或者 AOA2.0,
//如果小于 1 或者大于 2,则说明连接设备不支持AOA协议或者支持的 AOA 协议版本号不正确。
rc = libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_ENUMERATE, vendor_id,
product_id, class_id, usb_hotplugCallback, NULL, &gstUsbMngr.hotplugCbh);
if (LIBUSB_SUCCESS != rc) {
printf("libusb_hotplug_register_callback failed \n");
libusb_exit (NULL);
return EXIT_FAILURE;
}
//开启事件处理线程
pthread_create(&tid, NULL, usb_eventMonitorProcess, NULL);
return LIBUSB_SUCCESS;
}
int usb_deinit(void)
{
if (gstUsbMngr.handle) {
libusb_release_interface(gstUsbMngr.handle, gstUsbMngr.bInterfaceNumber);
libusb_close (gstUsbMngr.handle);
gstUsbMngr.handle = NULL;
}
if (0 < gstUsbMngr.hotplugCbh) {
libusb_hotplug_deregister_callback(NULL, gstUsbMngr.hotplugCbh);
}
pthread_mutex_destroy(&gstUsbMngr.stLock);
libusb_exit (NULL);
return LIBUSB_SUCCESS;
}
int main(int argc, char *argv[])
{
int rc;
pthread_t tid;
rc = usb_init();
if (LIBUSB_SUCCESS != rc)
{
return -1;
}
pthread_create(&tid, NULL, usb_readProcess, NULL);
while (1)
{
sleep(1);
}
usb_deinit();
return EXIT_SUCCESS;
}
如果对你有帮助,请给予作者一丝丝奖励