blob: 0282086458aa87949dff302065013dfd15c24a2f [file] [log] [blame]
Mike Lockwood5ed68d22010-05-25 19:08:48 -04001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <sys/types.h>
20#include <sys/ioctl.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <errno.h>
24
25#include <usbhost/usbhost.h>
26
27#include "MtpDevice.h"
28#include "MtpDebug.h"
29#include "MtpDeviceInfo.h"
30#include "MtpObjectInfo.h"
31#include "MtpStorageInfo.h"
32#include "MtpStringBuffer.h"
33
34namespace android {
35
36MtpDevice::MtpDevice(struct usb_device* device, int interface,
37 struct usb_endpoint *ep_in, struct usb_endpoint *ep_out,
38 struct usb_endpoint *ep_intr)
39 : mDevice(device),
40 mInterface(interface),
41 mEndpointIn(ep_in),
42 mEndpointOut(ep_out),
43 mEndpointIntr(ep_intr),
44 mDeviceInfo(NULL),
45 mID(usb_device_get_unique_id(device)),
46 mSessionID(0),
47 mTransactionID(0)
48{
49}
50
51MtpDevice::~MtpDevice() {
52 close();
53}
54
55void MtpDevice::initialize() {
56 openSession();
57 mDeviceInfo = getDeviceInfo();
58 if (mDeviceInfo) {
59 mDeviceInfo->print();
60 }
61}
62
63void MtpDevice::close() {
64 if (mDevice) {
65 usb_device_release_interface(mDevice, mInterface);
66 usb_device_close(mDevice);
67 mDevice = NULL;
68 }
69}
70
71const char* MtpDevice::getDeviceName() {
72 if (mDevice)
73 return usb_device_get_name(mDevice);
74 else
75 return "???";
76}
77
78bool MtpDevice::openSession() {
79printf("openSession\n");
80 mSessionID = 0;
81 mTransactionID = 0;
82 MtpSessionID newSession = 1;
83 mRequest.reset();
84 mRequest.setParameter(1, newSession);
85 if (!sendRequest(MTP_OPERATION_OPEN_SESSION))
86 return false;
87 MtpResponseCode ret = readResponse();
88 if (ret == MTP_RESPONSE_SESSION_ALREADY_OPEN)
89 newSession = mResponse.getParameter(1);
90 else if (ret != MTP_RESPONSE_OK)
91 return false;
92
93 mSessionID = newSession;
94 mTransactionID = 1;
95 return true;
96}
97
98bool MtpDevice::closeSession() {
99 // FIXME
100 return true;
101}
102
103MtpDeviceInfo* MtpDevice::getDeviceInfo() {
104 mRequest.reset();
105 if (!sendRequest(MTP_OPERATION_GET_DEVICE_INFO))
106 return NULL;
107 if (!readData())
108 return NULL;
109 MtpResponseCode ret = readResponse();
110printf("getDeviceInfo returned %04X\n", ret);
111 if (ret == MTP_RESPONSE_OK) {
112 MtpDeviceInfo* info = new MtpDeviceInfo;
113 info->read(mData);
114 return info;
115 }
116 return NULL;
117}
118
119MtpStorageIDList* MtpDevice::getStorageIDs() {
120 mRequest.reset();
121 if (!sendRequest(MTP_OPERATION_GET_STORAGE_IDS))
122 return NULL;
123 if (!readData())
124 return NULL;
125 MtpResponseCode ret = readResponse();
126 if (ret == MTP_RESPONSE_OK) {
127 return mData.getAUInt32();
128 }
129 return NULL;
130}
131
132MtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) {
133 mRequest.reset();
134 mRequest.setParameter(1, storageID);
135 if (!sendRequest(MTP_OPERATION_GET_STORAGE_INFO))
136 return NULL;
137 if (!readData())
138 return NULL;
139 MtpResponseCode ret = readResponse();
140printf("getStorageInfo returned %04X\n", ret);
141 if (ret == MTP_RESPONSE_OK) {
142 MtpStorageInfo* info = new MtpStorageInfo(storageID);
143 info->read(mData);
144 return info;
145 }
146 return NULL;
147}
148
149MtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID,
150 MtpObjectFormat format, MtpObjectHandle parent) {
151 mRequest.reset();
152 mRequest.setParameter(1, storageID);
153 mRequest.setParameter(2, format);
154 mRequest.setParameter(3, parent);
155 if (!sendRequest(MTP_OPERATION_GET_OBJECT_HANDLES))
156 return NULL;
157 if (!readData())
158 return NULL;
159 MtpResponseCode ret = readResponse();
160printf("getObjectHandles returned %04X\n", ret);
161 if (ret == MTP_RESPONSE_OK) {
162 return mData.getAUInt32();
163 }
164 return NULL;
165}
166
167MtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) {
168 mRequest.reset();
169 mRequest.setParameter(1, handle);
170 if (!sendRequest(MTP_OPERATION_GET_OBJECT_INFO))
171 return NULL;
172 if (!readData())
173 return NULL;
174 MtpResponseCode ret = readResponse();
175printf("getObjectInfo returned %04X\n", ret);
176 if (ret == MTP_RESPONSE_OK) {
177 MtpObjectInfo* info = new MtpObjectInfo(handle);
178 info->read(mData);
179 return info;
180 }
181 return NULL;
182}
183
184bool MtpDevice::sendRequest(MtpOperationCode operation) {
185 printf("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation));
186 mRequest.setOperationCode(operation);
187 if (mTransactionID > 0)
188 mRequest.setTransactionID(mTransactionID++);
189 int ret = mRequest.write(mEndpointOut);
190 mRequest.dump();
191 return (ret > 0);
192}
193
194bool MtpDevice::sendData(MtpOperationCode operation) {
195 printf("sendData\n");
196 mData.setOperationCode(mRequest.getOperationCode());
197 mData.setTransactionID(mRequest.getTransactionID());
198 int ret = mData.write(mEndpointOut);
199 mData.dump();
200 return (ret > 0);
201}
202
203bool MtpDevice::readData() {
204 mData.reset();
205 int ret = mData.read(mEndpointIn);
206 printf("readData returned %d\n", ret);
207 if (ret >= MTP_CONTAINER_HEADER_SIZE) {
208 mData.dump();
209 return true;
210 }
211 else {
212 printf("readResponse failed\n");
213 return false;
214 }
215}
216
217MtpResponseCode MtpDevice::readResponse() {
218 printf("readResponse\n");
219 int ret = mResponse.read(mEndpointIn);
220 if (ret >= MTP_CONTAINER_HEADER_SIZE) {
221 mResponse.dump();
222 return mResponse.getResponseCode();
223 }
224 else {
225 printf("readResponse failed\n");
226 return -1;
227 }
228}
229
230} // namespace android