diff options
Diffstat (limited to 'libs/usb/tests')
8 files changed, 474 insertions, 0 deletions
diff --git a/libs/usb/tests/AccessoryChat/Android.mk b/libs/usb/tests/AccessoryChat/Android.mk new file mode 100644 index 0000000..b854569 --- /dev/null +++ b/libs/usb/tests/AccessoryChat/Android.mk @@ -0,0 +1,15 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_PACKAGE_NAME := AccessoryChatGB + +LOCAL_JAVA_LIBRARIES := com.google.android.usb + +# Force an old SDK version to make sure we aren't using newer UsbManager APIs +LOCAL_SDK_VERSION := 8 + +include $(BUILD_PACKAGE) diff --git a/libs/usb/tests/AccessoryChat/AndroidManifest.xml b/libs/usb/tests/AccessoryChat/AndroidManifest.xml new file mode 100644 index 0000000..b63999c --- /dev/null +++ b/libs/usb/tests/AccessoryChat/AndroidManifest.xml @@ -0,0 +1,23 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.google.android.accessorychat"> + + <application> + <uses-library android:name="com.google.android.usb" /> + + <activity android:name="AccessoryChat" android:label="Accessory Chat GB"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + + <intent-filter> + <action android:name="android.hardware.action.USB_ACCESSORY_ATTACHED" /> + </intent-filter> + + <meta-data android:name="android.hardware.action.USB_ACCESSORY_ATTACHED" + android:resource="@xml/accessory_filter" /> + </activity> + </application> + <uses-sdk android:minSdkVersion="8" /> +</manifest> diff --git a/libs/usb/tests/AccessoryChat/README.txt b/libs/usb/tests/AccessoryChat/README.txt new file mode 100644 index 0000000..d2ce11e --- /dev/null +++ b/libs/usb/tests/AccessoryChat/README.txt @@ -0,0 +1,10 @@ +This is a test app for the USB accessory APIs. It consists of two parts: + +AccessoryChat - A Java app with a chat-like UI that sends and receives strings + via the UsbAccessory class. + +accessorychat - A C command-line program that communicates with AccessoryChat. + This program behaves as if it were a USB accessory. + It builds both for the host (Linux PC) and as an android + command line program, which will work if run as root on an + android device with USB host support diff --git a/libs/usb/tests/AccessoryChat/accessorychat/Android.mk b/libs/usb/tests/AccessoryChat/accessorychat/Android.mk new file mode 100644 index 0000000..300224a --- /dev/null +++ b/libs/usb/tests/AccessoryChat/accessorychat/Android.mk @@ -0,0 +1,34 @@ +LOCAL_PATH:= $(call my-dir) + +# Build for Linux (desktop) host +ifeq ($(HOST_OS),linux) + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := accessorychat.c + +LOCAL_MODULE := accessorychat + +LOCAL_C_INCLUDES += bionic/libc/kernel/common +LOCAL_STATIC_LIBRARIES := libusbhost libcutils +LOCAL_LDLIBS += -lpthread +LOCAL_CFLAGS := -g -O0 + +include $(BUILD_HOST_EXECUTABLE) + +endif + +# Build for device +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := accessorychat.c + +LOCAL_MODULE := accessorychat + +LOCAL_SHARED_LIBRARIES := libusbhost libcutils + +include $(BUILD_EXECUTABLE) diff --git a/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c new file mode 100644 index 0000000..94cc0ce --- /dev/null +++ b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <pthread.h> + +#include <usbhost/usbhost.h> +#include <linux/usb/f_accessory.h> + +struct usb_device *sDevice = NULL; + +static void* read_thread(void* arg) { + int endpoint = (int)arg; + int ret = 0; + + while (sDevice && ret >= 0) { + char buffer[16384]; + + ret = usb_device_bulk_transfer(sDevice, endpoint, buffer, sizeof(buffer), 1000); + if (ret < 0 && errno == ETIMEDOUT) + ret = 0; + if (ret > 0) { + fwrite(buffer, 1, ret, stdout); + printf("\n"); + fflush(stdout); + } + } + + return NULL; +} + +static void* write_thread(void* arg) { + int endpoint = (int)arg; + int ret = 0; + + while (ret >= 0) { + char buffer[16384]; + char *line = fgets(buffer, sizeof(buffer), stdin); + if (!line || !sDevice) + break; + ret = usb_device_bulk_transfer(sDevice, endpoint, line, strlen(line), 1000); + } + + return NULL; +} + +static void send_string(struct usb_device *device, int index, const char* string) { + int ret = usb_device_control_transfer(device, USB_DIR_OUT | USB_TYPE_VENDOR, + ACCESSORY_SEND_STRING, 0, index, (void *)string, strlen(string) + 1, 0); +} + +static int usb_device_added(const char *devname, void* client_data) { + struct usb_descriptor_header* desc; + struct usb_descriptor_iter iter; + uint16_t vendorId, productId; + int ret; + pthread_t th; + + struct usb_device *device = usb_device_open(devname); + if (!device) { + fprintf(stderr, "usb_device_open failed\n"); + return 0; + } + + vendorId = usb_device_get_vendor_id(device); + productId = usb_device_get_product_id(device); + + if (vendorId == 0x18D1 || vendorId == 0x22B8) { + if (!sDevice && (productId == 0x2D00 || productId == 0x2D01)) { + struct usb_descriptor_header* desc; + struct usb_descriptor_iter iter; + struct usb_interface_descriptor *intf = NULL; + struct usb_endpoint_descriptor *ep1 = NULL; + struct usb_endpoint_descriptor *ep2 = NULL; + + printf("Found android device in accessory mode\n"); + sDevice = device; + + usb_descriptor_iter_init(device, &iter); + while ((desc = usb_descriptor_iter_next(&iter)) != NULL && (!intf || !ep1 || !ep2)) { + if (desc->bDescriptorType == USB_DT_INTERFACE) { + intf = (struct usb_interface_descriptor *)desc; + } else if (desc->bDescriptorType == USB_DT_ENDPOINT) { + if (ep1) + ep2 = (struct usb_endpoint_descriptor *)desc; + else + ep1 = (struct usb_endpoint_descriptor *)desc; + } + } + + if (!intf) { + fprintf(stderr, "interface not found\n"); + exit(1); + } + if (!ep1 || !ep2) { + fprintf(stderr, "endpoints not found\n"); + exit(1); + } + + if (usb_device_claim_interface(device, intf->bInterfaceNumber)) { + fprintf(stderr, "usb_device_claim_interface failed errno: %d\n", errno); + exit(1); + } + + if ((ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) { + pthread_create(&th, NULL, read_thread, (void *)ep1->bEndpointAddress); + pthread_create(&th, NULL, write_thread, (void *)ep2->bEndpointAddress); + } else { + pthread_create(&th, NULL, read_thread, (void *)ep2->bEndpointAddress); + pthread_create(&th, NULL, write_thread, (void *)ep1->bEndpointAddress); + } + } else { + printf("Found possible android device - attempting to switch to accessory mode\n"); + + send_string(device, ACCESSORY_STRING_MANUFACTURER, "Google, Inc."); + send_string(device, ACCESSORY_STRING_MODEL, "AccessoryChat"); + send_string(device, ACCESSORY_STRING_TYPE, "Sample Program"); + send_string(device, ACCESSORY_STRING_VERSION, "1.0"); + + ret = usb_device_control_transfer(device, USB_DIR_OUT | USB_TYPE_VENDOR, + ACCESSORY_START, 0, 0, 0, 0, 0); + return 0; + } + } + + if (device != sDevice) + usb_device_close(device); + + return 0; +} + +static int usb_device_removed(const char *devname, void* client_data) { + if (sDevice && !strcmp(usb_device_get_name(sDevice), devname)) { + usb_device_close(sDevice); + sDevice = NULL; + // exit when we are disconnected + return 1; + } + return 0; +} + + +int main(int argc, char* argv[]) { + struct usb_host_context* context = usb_host_init(); + if (!context) { + fprintf(stderr, "usb_host_init failed"); + return 1; + } + + // this will never return so it is safe to pass thiz directly + usb_host_run(context, usb_device_added, usb_device_removed, NULL, NULL); + return 0; +} diff --git a/libs/usb/tests/AccessoryChat/res/layout/accessory_chat.xml b/libs/usb/tests/AccessoryChat/res/layout/accessory_chat.xml new file mode 100644 index 0000000..596ecbf --- /dev/null +++ b/libs/usb/tests/AccessoryChat/res/layout/accessory_chat.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + > + + <ScrollView android:id="@+id/scroll" + android:layout_width="match_parent" + android:layout_height="0px" + android:layout_weight="1" + > + <TextView android:id="@+id/log" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="25dp" + android:textSize="12sp" + android:textColor="#ffffffff" + /> + </ScrollView> + + <EditText android:id="@+id/message" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:capitalize="sentences" + android:autoText="true" + android:singleLine="true" + /> + +</LinearLayout> + + diff --git a/libs/usb/tests/AccessoryChat/res/xml/accessory_filter.xml b/libs/usb/tests/AccessoryChat/res/xml/accessory_filter.xml new file mode 100644 index 0000000..588946f --- /dev/null +++ b/libs/usb/tests/AccessoryChat/res/xml/accessory_filter.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<resources> + <usb-accessory manufacturer="Google, Inc." model="AccessoryChat" type="Sample Program" version="1.0" /> +</resources> diff --git a/libs/usb/tests/AccessoryChat/src/com/google/android/accessorychat/AccessoryChat.java b/libs/usb/tests/AccessoryChat/src/com/google/android/accessorychat/AccessoryChat.java new file mode 100644 index 0000000..0a5701c --- /dev/null +++ b/libs/usb/tests/AccessoryChat/src/com/google/android/accessorychat/AccessoryChat.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.accessorychat; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.os.ParcelFileDescriptor; +import android.view.KeyEvent; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.util.Log; +import android.widget.EditText; +import android.widget.TextView; + +import com.google.android.usb.UsbAccessory; +import com.google.android.usb.UsbManager; + +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +public class AccessoryChat extends Activity implements Runnable, TextView.OnEditorActionListener { + + private static final String TAG = "AccessoryChat"; + TextView mLog; + EditText mEditText; + ParcelFileDescriptor mFileDescriptor; + FileInputStream mInputStream; + FileOutputStream mOutputStream; + + private static final int MESSAGE_LOG = 1; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.accessory_chat); + mLog = (TextView)findViewById(R.id.log); + mEditText = (EditText)findViewById(R.id.message); + mEditText.setOnEditorActionListener(this); + } + + @Override + public void onResume() { + super.onResume(); + + Intent intent = getIntent(); + Log.d(TAG, "intent: " + intent); + UsbManager manager = UsbManager.getInstance(); + UsbAccessory[] accessories = manager.getAccessoryList(); + UsbAccessory accessory = (accessories == null ? null : accessories[0]); + if (accessory != null) { + mFileDescriptor = manager.openAccessory(accessory); + if (mFileDescriptor != null) { + FileDescriptor fd = mFileDescriptor.getFileDescriptor(); + mInputStream = new FileInputStream(fd); + mOutputStream = new FileOutputStream(fd); + Thread thread = new Thread(null, this, "AccessoryChat"); + thread.start(); + } else { + Log.d(TAG, "openAccessory fail"); + } + } else { + Log.d(TAG, "mAccessory is null"); + } + } + + @Override + public void onPause() { + super.onPause(); + if (mFileDescriptor != null) { + try { + mFileDescriptor.close(); + } catch (IOException e) { + } finally { + mFileDescriptor = null; + } + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE && mOutputStream != null) { + try { + mOutputStream.write(v.getText().toString().getBytes()); + } catch (IOException e) { + Log.e(TAG, "write failed", e); + } + v.setText(""); + return true; + } + Log.d(TAG, "onEditorAction " + actionId + " event: " + event); + return false; + } + + public void run() { + int ret = 0; + byte[] buffer = new byte[16384]; + while (ret >= 0) { + try { + ret = mInputStream.read(buffer); + } catch (IOException e) { + break; + } + + if (ret > 0) { + Message m = Message.obtain(mHandler, MESSAGE_LOG); + String text = new String(buffer, 0, ret); + Log.d(TAG, "chat: " + text); + m.obj = text; + mHandler.sendMessage(m); + } + } + Log.d(TAG, "thread out"); + } + + Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MESSAGE_LOG: + mLog.setText(mLog.getText() + "\n" + (String)msg.obj); + break; + } + } + }; +} + + |