pcmbuf: need ifdef to fix yellow
[kugel-rb.git] / rbutil / ipodpatcher / ipodio-posix.c
blobbe048fc9863f1bf93446961a67749b884ee7f3b5
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006-2007 Dave Chapman
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/ioctl.h>
30 #include <errno.h>
32 #include "ipodio.h"
34 #if defined(linux) || defined (__linux)
35 #include <sys/mount.h>
36 #include <linux/hdreg.h>
37 #include <scsi/scsi_ioctl.h>
38 #include <scsi/sg.h>
40 #define IPOD_SECTORSIZE_IOCTL BLKSSZGET
42 static void get_geometry(struct ipod_t* ipod)
44 struct hd_geometry geometry;
46 if (!ioctl(ipod->dh, HDIO_GETGEO, &geometry)) {
47 /* never use geometry.cylinders - it is truncated */
48 ipod->num_heads = geometry.heads;
49 ipod->sectors_per_track = geometry.sectors;
50 } else {
51 ipod->num_heads = 0;
52 ipod->sectors_per_track = 0;
56 /* 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
60 int ipod_scsi_inquiry(struct ipod_t* ipod, int page_code,
61 unsigned char* buf, int bufsize)
63 unsigned char cdb[6];
64 struct sg_io_hdr hdr;
65 unsigned char sense_buffer[255];
67 memset(&hdr, 0, sizeof(hdr));
69 hdr.interface_id = 'S'; /* this is the only choice we have! */
70 hdr.flags = SG_FLAG_LUN_INHIBIT; /* this would put the LUN to 2nd byte of cdb*/
72 /* Set xfer data */
73 hdr.dxferp = buf;
74 hdr.dxfer_len = bufsize;
76 /* Set sense data */
77 hdr.sbp = sense_buffer;
78 hdr.mx_sb_len = sizeof(sense_buffer);
80 /* Set the cdb format */
81 cdb[0] = 0x12;
82 cdb[1] = 1; /* Enable Vital Product Data (EVPD) */
83 cdb[2] = page_code & 0xff;
84 cdb[3] = 0;
85 cdb[4] = 0xff;
86 cdb[5] = 0; /* For control filed, just use 0 */
88 hdr.dxfer_direction = SG_DXFER_FROM_DEV;
89 hdr.cmdp = cdb;
90 hdr.cmd_len = 6;
92 int ret = ioctl(ipod->dh, SG_IO, &hdr);
94 if (ret < 0) {
95 return -1;
96 } else {
97 return 0;
101 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \
102 || defined(__bsdi__) || defined(__DragonFly__)
103 #include <sys/disk.h>
104 #define IPOD_SECTORSIZE_IOCTL DIOCGSECTORSIZE
106 /* TODO: Implement this function for BSD */
107 static void get_geometry(struct ipod_t* ipod)
109 /* Are these universal for all ipods? */
110 ipod->num_heads = 255;
111 ipod->sectors_per_track = 63;
114 int ipod_scsi_inquiry(struct ipod_t* ipod, int page_code,
115 unsigned char* buf, int bufsize)
117 /* TODO: Implement for BSD */
118 return -1;
121 #elif defined(__APPLE__) && defined(__MACH__)
122 #include <sys/disk.h>
123 #define IPOD_SECTORSIZE_IOCTL DKIOCGETBLOCKSIZE
125 /* TODO: Implement this function for Mac OS X */
126 static void get_geometry(struct ipod_t* ipod)
128 /* Are these universal for all ipods? */
129 ipod->num_heads = 255;
130 ipod->sectors_per_track = 63;
133 int ipod_scsi_inquiry(struct ipod_t* ipod, int page_code,
134 unsigned char* buf, int bufsize)
136 /* TODO: Implement for OS X */
137 return -1;
140 #else
141 #error No sector-size detection implemented for this platform
142 #endif
144 #if defined(__APPLE__) && defined(__MACH__)
145 static int ipod_unmount(struct ipod_t* ipod)
147 char cmd[4096];
148 int res;
150 sprintf(cmd, "/usr/sbin/diskutil unmount \"%ss2\"",ipod->diskname);
151 fprintf(stderr,"[INFO] ");
152 res = system(cmd);
154 if (res==0) {
155 return 0;
156 } else {
157 perror("Unmount failed");
158 return -1;
161 #endif
163 void print_error(char* msg)
165 perror(msg);
168 int ipod_open(struct ipod_t* ipod, int silent)
170 ipod->dh=open(ipod->diskname,O_RDONLY);
171 if (ipod->dh < 0) {
172 if (!silent) perror(ipod->diskname);
173 if(errno == EACCES) return -2;
174 else return -1;
177 /* Read information about the disk */
179 if(ioctl(ipod->dh,IPOD_SECTORSIZE_IOCTL,&ipod->sector_size) < 0) {
180 ipod->sector_size=512;
181 if (!silent) {
182 fprintf(stderr,"[ERR] ioctl() call to get sector size failed, defaulting to %d\n"
183 ,ipod->sector_size);
187 get_geometry(ipod);
189 return 0;
193 int ipod_reopen_rw(struct ipod_t* ipod)
195 #if defined(__APPLE__) && defined(__MACH__)
196 if (ipod_unmount(ipod) < 0)
197 return -1;
198 #endif
200 close(ipod->dh);
201 ipod->dh=open(ipod->diskname,O_RDWR);
202 if (ipod->dh < 0) {
203 perror(ipod->diskname);
204 return -1;
206 return 0;
209 int ipod_close(struct ipod_t* ipod)
211 close(ipod->dh);
212 return 0;
215 int ipod_alloc_buffer(unsigned char** sectorbuf, int bufsize)
217 *sectorbuf=malloc(bufsize);
218 if (*sectorbuf == NULL) {
219 return -1;
221 return 0;
224 int ipod_seek(struct ipod_t* ipod, unsigned long pos)
226 off_t res;
228 res = lseek(ipod->dh, pos, SEEK_SET);
230 if (res == -1) {
231 return -1;
233 return 0;
236 ssize_t ipod_read(struct ipod_t* ipod, unsigned char* buf, int nbytes)
238 return read(ipod->dh, buf, nbytes);
241 ssize_t ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes)
243 return write(ipod->dh, buf, nbytes);