diff options
author | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2010-01-30 17:02:37 +0000 |
---|---|---|
committer | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2010-01-30 17:02:37 +0000 |
commit | c8d13b6a7dc76e80663ca71338fed4020e2be132 (patch) | |
tree | 01136e99b5b874322f8af6838d2f704dfc4a40e8 /rbutil | |
parent | 25236232c00ed3ead85a6918fa501ba76b4a892a (diff) | |
download | rockbox-c8d13b6a7dc76e80663ca71338fed4020e2be132.tar.gz rockbox-c8d13b6a7dc76e80663ca71338fed4020e2be132.zip |
Implement ipod_scsi_inquiry() on OS X.
This implements the basic functionality for sending inquiries on OS X.
The current implementation has some limitations:
- it will not respect the selected device but pick the first Ipod found.
- it is inefficient due to the way ipodpatcher expects this which doesn't
really match how it works on OS X.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24382 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'rbutil')
-rw-r--r-- | rbutil/ipodpatcher/Makefile | 14 | ||||
-rw-r--r-- | rbutil/ipodpatcher/ipodio-posix.c | 154 | ||||
-rw-r--r-- | rbutil/rbutilqt/rbutilqt.pro | 2 |
3 files changed, 157 insertions, 13 deletions
diff --git a/rbutil/ipodpatcher/Makefile b/rbutil/ipodpatcher/Makefile index 34b4dd6b43..7c203a94aa 100644 --- a/rbutil/ipodpatcher/Makefile +++ b/rbutil/ipodpatcher/Makefile | |||
@@ -39,8 +39,14 @@ OUTPUT=ipodpatcher | |||
39 | CROSS=i586-mingw32msvc- | 39 | CROSS=i586-mingw32msvc- |
40 | endif | 40 | endif |
41 | endif | 41 | endif |
42 | ifeq ($(findstring Darwin,$(shell uname)),Darwin) | ||
43 | # building against SDK 10.4 is not compatible with gcc-4.2 (default on newer Xcode) | ||
44 | # might need adjustment for older Xcode. | ||
45 | NATIVECC ?= gcc-4.0 | ||
46 | CFLAGS+=-framework CoreFoundation -framework IOKit -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 | ||
47 | endif | ||
42 | 48 | ||
43 | NATIVECC = gcc | 49 | NATIVECC ?= gcc |
44 | CC = $(CROSS)gcc | 50 | CC = $(CROSS)gcc |
45 | WINDRES = $(CROSS)windres | 51 | WINDRES = $(CROSS)windres |
46 | 52 | ||
@@ -49,7 +55,7 @@ SRC = main.c ipodpatcher.c fat32format.c arc4.c | |||
49 | all: $(OUTPUT) | 55 | all: $(OUTPUT) |
50 | 56 | ||
51 | ipodpatcher: $(SRC) ipodio-posix.c $(BOOTSRC) | 57 | ipodpatcher: $(SRC) ipodio-posix.c $(BOOTSRC) |
52 | gcc $(CFLAGS) -o ipodpatcher $(SRC) ipodio-posix.c $(BOOTSRC) | 58 | $(NATIVECC) $(CFLAGS) -o ipodpatcher $(SRC) ipodio-posix.c $(BOOTSRC) |
53 | strip ipodpatcher | 59 | strip ipodpatcher |
54 | 60 | ||
55 | ipodpatcher.exe: $(SRC) ipodio-win32.c ipodio-win32-scsi.c ipodpatcher-rc.o $(BOOTSRC) | 61 | ipodpatcher.exe: $(SRC) ipodio-win32.c ipodio-win32-scsi.c ipodpatcher-rc.o $(BOOTSRC) |
@@ -63,11 +69,11 @@ ipodpatcher-mac: ipodpatcher-i386 ipodpatcher-ppc | |||
63 | lipo -create ipodpatcher-ppc ipodpatcher-i386 -output ipodpatcher-mac | 69 | lipo -create ipodpatcher-ppc ipodpatcher-i386 -output ipodpatcher-mac |
64 | 70 | ||
65 | ipodpatcher-i386: $(SRC) ipodio-posix.c $(BOOTSRC) | 71 | ipodpatcher-i386: $(SRC) ipodio-posix.c $(BOOTSRC) |
66 | gcc -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 -arch i386 $(CFLAGS) -o ipodpatcher-i386 $(SRC) ipodio-posix.c $(BOOTSRC) | 72 | $(NATIVECC) -arch i386 $(CFLAGS) -o ipodpatcher-i386 $(SRC) ipodio-posix.c $(BOOTSRC) |
67 | strip ipodpatcher-i386 | 73 | strip ipodpatcher-i386 |
68 | 74 | ||
69 | ipodpatcher-ppc: $(SRC) ipodio-posix.c $(BOOTSRC) | 75 | ipodpatcher-ppc: $(SRC) ipodio-posix.c $(BOOTSRC) |
70 | gcc -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 -arch ppc $(CFLAGS) -o ipodpatcher-ppc $(SRC) ipodio-posix.c $(BOOTSRC) | 76 | $(NATIVECC) -arch ppc $(CFLAGS) -o ipodpatcher-ppc $(SRC) ipodio-posix.c $(BOOTSRC) |
71 | strip ipodpatcher-ppc | 77 | strip ipodpatcher-ppc |
72 | 78 | ||
73 | ipod2c: ipod2c.c | 79 | ipod2c: ipod2c.c |
diff --git a/rbutil/ipodpatcher/ipodio-posix.c b/rbutil/ipodpatcher/ipodio-posix.c index 065aae6303..881c09b54f 100644 --- a/rbutil/ipodpatcher/ipodio-posix.c +++ b/rbutil/ipodpatcher/ipodio-posix.c | |||
@@ -19,6 +19,7 @@ | |||
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | |||
22 | #include <stdio.h> | 23 | #include <stdio.h> |
23 | #include <unistd.h> | 24 | #include <unistd.h> |
24 | #include <fcntl.h> | 25 | #include <fcntl.h> |
@@ -53,7 +54,7 @@ static void get_geometry(struct ipod_t* ipod) | |||
53 | } | 54 | } |
54 | } | 55 | } |
55 | 56 | ||
56 | /* Linux SCSI Inquiry code based on the documentation and example code from | 57 | /* Linux SCSI Inquiry code based on the documentation and example code from |
57 | http://www.ibm.com/developerworks/linux/library/l-scsi-api/index.html | 58 | http://www.ibm.com/developerworks/linux/library/l-scsi-api/index.html |
58 | */ | 59 | */ |
59 | 60 | ||
@@ -84,7 +85,7 @@ int ipod_scsi_inquiry(struct ipod_t* ipod, int page_code, | |||
84 | cdb[3] = 0; | 85 | cdb[3] = 0; |
85 | cdb[4] = 0xff; | 86 | cdb[4] = 0xff; |
86 | cdb[5] = 0; /* For control filed, just use 0 */ | 87 | cdb[5] = 0; /* For control filed, just use 0 */ |
87 | 88 | ||
88 | hdr.dxfer_direction = SG_DXFER_FROM_DEV; | 89 | hdr.dxfer_direction = SG_DXFER_FROM_DEV; |
89 | hdr.cmdp = cdb; | 90 | hdr.cmdp = cdb; |
90 | hdr.cmd_len = 6; | 91 | hdr.cmd_len = 6; |
@@ -123,7 +124,13 @@ int ipod_scsi_inquiry(struct ipod_t* ipod, int page_code, | |||
123 | } | 124 | } |
124 | 125 | ||
125 | #elif defined(__APPLE__) && defined(__MACH__) | 126 | #elif defined(__APPLE__) && defined(__MACH__) |
127 | /* OS X IOKit includes don't like VERSION being defined! */ | ||
128 | #undef VERSION | ||
126 | #include <sys/disk.h> | 129 | #include <sys/disk.h> |
130 | #include <CoreFoundation/CoreFoundation.h> | ||
131 | #include <IOKit/IOKitLib.h> | ||
132 | #include <IOKit/scsi-commands/SCSITaskLib.h> | ||
133 | #include <IOKit/scsi-commands/SCSICommandOperationCodes.h> | ||
127 | #define IPOD_SECTORSIZE_IOCTL DKIOCGETBLOCKSIZE | 134 | #define IPOD_SECTORSIZE_IOCTL DKIOCGETBLOCKSIZE |
128 | 135 | ||
129 | /* TODO: Implement this function for Mac OS X */ | 136 | /* TODO: Implement this function for Mac OS X */ |
@@ -137,12 +144,143 @@ static void get_geometry(struct ipod_t* ipod) | |||
137 | int ipod_scsi_inquiry(struct ipod_t* ipod, int page_code, | 144 | int ipod_scsi_inquiry(struct ipod_t* ipod, int page_code, |
138 | unsigned char* buf, int bufsize) | 145 | unsigned char* buf, int bufsize) |
139 | { | 146 | { |
140 | /* TODO: Implement for OS X */ | 147 | /* OS X doesn't allow to simply send out a SCSI inquiry request but |
148 | * requires registering an interface handler first. | ||
149 | * Currently this is done on each inquiry request which is somewhat | ||
150 | * inefficient but the current ipodpatcher API doesn't really fit here. | ||
151 | * Based on the documentation in Apple's document | ||
152 | * "SCSI Architecture Model Device Interface Guide". | ||
153 | * | ||
154 | * WARNING: this code currently doesn't take the selected device into | ||
155 | * account. It simply looks for an Ipod on the system and uses | ||
156 | * the first match. | ||
157 | */ | ||
141 | (void)ipod; | 158 | (void)ipod; |
142 | (void)page_code; | 159 | int result = 0; |
143 | (void)buf; | 160 | /* first, create a dictionary to match the device. This is needed to get the |
144 | (void)bufsize; | 161 | * service. */ |
145 | return -1; | 162 | CFMutableDictionaryRef match_dict; |
163 | match_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL); | ||
164 | if(match_dict == NULL) | ||
165 | return -1; | ||
166 | |||
167 | /* set value to match. In case of the Ipod this is "iPodUserClientDevice". */ | ||
168 | CFMutableDictionaryRef sub_dict; | ||
169 | sub_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL); | ||
170 | CFDictionarySetValue(sub_dict, CFSTR(kIOPropertySCSITaskDeviceCategory), | ||
171 | CFSTR("iPodUserClientDevice")); | ||
172 | CFDictionarySetValue(match_dict, CFSTR(kIOPropertyMatchKey), sub_dict); | ||
173 | |||
174 | if(sub_dict == NULL) | ||
175 | return -1; | ||
176 | |||
177 | /* get an iterator for searching for the service. */ | ||
178 | kern_return_t kr; | ||
179 | io_iterator_t iterator = IO_OBJECT_NULL; | ||
180 | /* get matching services from IO registry. Consumes one reference to | ||
181 | * the dictionary, so no need to release that. */ | ||
182 | kr = IOServiceGetMatchingServices(kIOMasterPortDefault, match_dict, &iterator); | ||
183 | |||
184 | if(!iterator | (kr != kIOReturnSuccess)) | ||
185 | return -1; | ||
186 | |||
187 | /* get interface and obtain exclusive access */ | ||
188 | SInt32 score; | ||
189 | HRESULT herr; | ||
190 | kern_return_t err; | ||
191 | IOCFPlugInInterface **plugin_interface = NULL; | ||
192 | SCSITaskDeviceInterface **interface = NULL; | ||
193 | io_service_t device = IO_OBJECT_NULL; | ||
194 | device = IOIteratorNext(iterator); | ||
195 | |||
196 | err = IOCreatePlugInInterfaceForService(device, kIOSCSITaskDeviceUserClientTypeID, | ||
197 | kIOCFPlugInInterfaceID, &plugin_interface, | ||
198 | &score); | ||
199 | |||
200 | if(err != noErr) { | ||
201 | return -1; | ||
202 | } | ||
203 | /* query the plugin interface for task interface */ | ||
204 | herr = (*plugin_interface)->QueryInterface(plugin_interface, | ||
205 | CFUUIDGetUUIDBytes(kIOSCSITaskDeviceInterfaceID), (LPVOID*)&interface); | ||
206 | if(herr != S_OK) { | ||
207 | IODestroyPlugInInterface(plugin_interface); | ||
208 | return -1; | ||
209 | } | ||
210 | |||
211 | err = (*interface)->ObtainExclusiveAccess(interface); | ||
212 | if(err != noErr) { | ||
213 | (*interface)->Release(interface); | ||
214 | IODestroyPlugInInterface(plugin_interface); | ||
215 | return -1; | ||
216 | } | ||
217 | |||
218 | /* do the inquiry */ | ||
219 | SCSITaskInterface **task = NULL; | ||
220 | |||
221 | task = (*interface)->CreateSCSITask(interface); | ||
222 | if(task != NULL) { | ||
223 | kern_return_t err; | ||
224 | SCSITaskStatus task_status; | ||
225 | IOVirtualRange* range; | ||
226 | SCSI_Sense_Data sense_data; | ||
227 | SCSICommandDescriptorBlock cdb; | ||
228 | UInt64 transfer_count = 0; | ||
229 | memset(buf, 0, bufsize); | ||
230 | /* allocate virtual range for buffer. */ | ||
231 | range = (IOVirtualRange*) malloc(sizeof(IOVirtualRange)); | ||
232 | memset(&sense_data, 0, sizeof(sense_data)); | ||
233 | memset(cdb, 0, sizeof(cdb)); | ||
234 | /* set up range. address is buffer address, length is request size. */ | ||
235 | range->address = (IOVirtualAddress)buf; | ||
236 | range->length = bufsize; | ||
237 | /* setup CDB */ | ||
238 | cdb[0] = 0x12; /* inquiry */ | ||
239 | cdb[1] = 1; | ||
240 | cdb[2] = page_code; | ||
241 | cdb[4] = bufsize; | ||
242 | |||
243 | /* set cdb in task */ | ||
244 | err = (*task)->SetCommandDescriptorBlock(task, cdb, kSCSICDBSize_6Byte); | ||
245 | if(err != kIOReturnSuccess) { | ||
246 | result = -1; | ||
247 | goto cleanup; | ||
248 | } | ||
249 | err = (*task)->SetScatterGatherEntries(task, range, 1, bufsize, | ||
250 | kSCSIDataTransfer_FromTargetToInitiator); | ||
251 | if(err != kIOReturnSuccess) { | ||
252 | result = -1; | ||
253 | goto cleanup; | ||
254 | } | ||
255 | /* set timeout */ | ||
256 | err = (*task)->SetTimeoutDuration(task, 10000); | ||
257 | if(err != kIOReturnSuccess) { | ||
258 | result = -1; | ||
259 | goto cleanup; | ||
260 | } | ||
261 | |||
262 | /* request data */ | ||
263 | err = (*task)->ExecuteTaskSync(task, &sense_data, &task_status, &transfer_count); | ||
264 | if(err != kIOReturnSuccess) { | ||
265 | result = -1; | ||
266 | goto cleanup; | ||
267 | } | ||
268 | /* cleanup */ | ||
269 | free(range); | ||
270 | |||
271 | /* release task interface */ | ||
272 | (*task)->Release(task); | ||
273 | } | ||
274 | else { | ||
275 | result = -1; | ||
276 | } | ||
277 | cleanup: | ||
278 | /* cleanup interface */ | ||
279 | (*interface)->ReleaseExclusiveAccess(interface); | ||
280 | (*interface)->Release(interface); | ||
281 | IODestroyPlugInInterface(plugin_interface); | ||
282 | |||
283 | return result; | ||
146 | } | 284 | } |
147 | 285 | ||
148 | #else | 286 | #else |
@@ -189,7 +327,7 @@ int ipod_open(struct ipod_t* ipod, int silent) | |||
189 | if (!silent) { | 327 | if (!silent) { |
190 | fprintf(stderr,"[ERR] ioctl() call to get sector size failed, defaulting to %d\n" | 328 | fprintf(stderr,"[ERR] ioctl() call to get sector size failed, defaulting to %d\n" |
191 | ,ipod->sector_size); | 329 | ,ipod->sector_size); |
192 | } | 330 | } |
193 | } | 331 | } |
194 | 332 | ||
195 | get_geometry(ipod); | 333 | get_geometry(ipod); |
diff --git a/rbutil/rbutilqt/rbutilqt.pro b/rbutil/rbutilqt/rbutilqt.pro index a1983719b4..f2f96e70d8 100644 --- a/rbutil/rbutilqt/rbutilqt.pro +++ b/rbutil/rbutilqt/rbutilqt.pro | |||
@@ -276,7 +276,7 @@ macx { | |||
276 | QMAKE_LFLAGS_PPC=-mmacosx-version-min=10.4 -arch ppc | 276 | QMAKE_LFLAGS_PPC=-mmacosx-version-min=10.4 -arch ppc |
277 | QMAKE_LFLAGS_X86=-mmacosx-version-min=10.4 -arch i386 | 277 | QMAKE_LFLAGS_X86=-mmacosx-version-min=10.4 -arch i386 |
278 | CONFIG+=x86 ppc | 278 | CONFIG+=x86 ppc |
279 | LIBS += -L/usr/local/lib -framework IOKit -lz | 279 | LIBS += -L/usr/local/lib -framework IOKit -framework CoreFoundation -lz |
280 | INCLUDEPATH += /usr/local/include | 280 | INCLUDEPATH += /usr/local/include |
281 | QMAKE_INFO_PLIST = Info.plist | 281 | QMAKE_INFO_PLIST = Info.plist |
282 | RC_FILE = icons/rbutilqt.icns | 282 | RC_FILE = icons/rbutilqt.icns |