Fixup fromcvs/togit conversion
[minix-pkgsrc.git] / sysutils / hal / files / hald-netbsd / devinfo_optical.c
blobe435f3223183ccf221f5c9245a49232e446ae3e1
1 /*
2 * Copyright (c) 2008 Reinoud Zandijk
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #ifdef HAVE_CONFIG_H
28 # include <config.h>
29 #endif
31 #include <stdio.h>
32 #include <sys/types.h>
33 #include <sys/scsiio.h>
34 #include <sys/disklabel.h>
35 #include <dev/scsipi/scsi_spc.h>
36 #include <dev/scsipi/scsipi_all.h>
37 #include <dev/scsipi/scsipi_cd.h>
38 #include <string.h>
39 #include <machine/disklabel.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <ctype.h>
43 #include <fcntl.h>
45 #include "../osspec.h"
46 #include "../logger.h"
47 #include "../hald.h"
48 #include "../hald_dbus.h"
49 #include "../device_info.h"
50 #include "../util.h"
51 #include "devinfo_optical.h"
53 #include "devinfo.h"
56 #define DEVINFO_PROBE_STORAGE_TIMEOUT 60000
57 static HalDevice *devinfo_optical_add(HalDevice *, const char *, char *,char *);
58 static HalDevice *devinfo_optical_volume_add(HalDevice *, const char *, char *, char *);
61 static const gchar *
62 devinfo_storage_get_prober (HalDevice *d, int *timeout)
64 *timeout = DEVINFO_PROBE_STORAGE_TIMEOUT;
65 return "hald-probe-storage";
68 #if notyet
69 const gchar *
70 devinfo_volume_get_prober (HalDevice *d, int *timeout)
72 *timeout = DEVINFO_PROBE_VOLUME_TIMEOUT;
73 return "hald-probe-volume";
75 #endif
77 DevinfoDevHandler devinfo_optical_handler = {
78 devinfo_optical_add,
79 NULL, /* remove */
80 NULL, /* hotplug_begin_add */
81 NULL, /* hotplug_begin_remove */
82 NULL, /* probing_done */
83 NULL /* devinfo_storage_get_prober */ /* get_prober */
87 DevinfoDevHandler devinfo_optical_volume_handler = {
88 devinfo_optical_volume_add,
89 NULL, /* remove */
90 NULL, /* hotplug_begin_add */
91 NULL, /* hotplug_begin_remove */
92 NULL, /* probing_done */
93 NULL /* devinfo_storage_get_prober */ /* get_prober */
97 /* XXX i dont know how to link cdutils here XXX ! */
98 bool
99 scsi_command (int fd, void *cmd, size_t cmdlen, void *data, size_t datalen,
100 int timeout, int flags)
102 scsireq_t req;
104 memset(&req, 0, sizeof(req));
105 memcpy(req.cmd, cmd, cmdlen);
106 req.cmdlen = cmdlen;
107 req.databuf = data;
108 req.datalen = datalen;
109 req.timeout = timeout;
110 req.flags = flags;
111 req.senselen = SENSEBUFLEN;
113 if (ioctl(fd, SCIOCCOMMAND, &req) == -1)
114 return false;
115 if (req.retsts == SCCMD_OK)
116 return true;
117 return false;
121 static void
122 optical_get_str(char *str, unsigned char *buf, int len)
124 char *pos;
125 int i;
127 pos = str;
128 for (i = 0; i < len; i++) {
129 if (isprint(buf[i]))
130 *pos++ = buf[i];
132 *pos = (char) 0;
133 pos--;
134 while (*pos == ' ')
135 *pos-- = (char) 0;
139 static void
140 devinfo_optical_identify_drive(HalDevice *d, char *devstr)
142 uint8_t cmd[12], buf[100];
143 char str[100];
144 int fd, ok;
146 fd = open(devstr, O_RDONLY, 0);
147 if(!fd)
148 return;
150 HAL_INFO(("devinfo_optical_identify_drive: SCSI call"));
151 cmd[0] = 0x12; /* INQUIRY */
152 cmd[1] = 0; /* basic inquiry */
153 cmd[2] = 0; /* no page or operation code */
154 cmd[3] = 0; /* reserved/MSB result */
155 cmd[4] = 96; /* all but vendor specific */
156 cmd[5] = 0; /* control */
157 ok = scsi_command(fd, cmd, 6, buf, 96, 30000, SCCMD_READ);
158 close(fd);
160 if (!ok)
161 return;
163 optical_get_str(str, buf+8, 8);
164 hal_device_property_set_string (d, "storage.vendor", str);
165 optical_get_str(str, buf+16, 16);
166 hal_device_property_set_string (d, "storage.model", str);
167 optical_get_str(str, buf+32, 4);
168 hal_device_property_set_string (d, "storage.firmware_version", str);
172 static char const *
173 get_profile_name(HalDevice *d, int profile)
175 switch (profile) {
176 case 0x00 : return NULL; // "Unknown[0] profile";
177 case 0x01 : return NULL; // "Non removeable disc";
178 case 0x02 : return NULL; // "Removable disc";
179 case 0x03 : return "mo"; // Magneto Optical with sector erase";
180 case 0x04 : return "mo"; // "Magneto Optical write once";
181 case 0x05 : return "mo"; // "Advance Storage Magneto Optical";
182 case 0x08 : return "cd"; // "CD-ROM"; no writing
183 case 0x09 : return "cdr"; // "CD-R recordable";
184 case 0x0a : return "cdrw"; // "CD-RW rewritable";
185 case 0x10 : return "dvd"; // "DVD-ROM"; no writing
186 case 0x11 : return "dvdr"; // "DVD-R sequential";
187 case 0x12 : return "dvdram"; // "DVD-RAM rewritable";
188 case 0x13 : return "dvdrw"; // "DVD-RW restricted overwrite";
189 case 0x14 : return "dvdrw"; // "DVD-RW sequential";
190 case 0x15 : return "dvdr"; // "DVD-R dual layer sequential";
191 case 0x16 : return "dvdr"; // "DVD-R dual layer jump";
192 case 0x17 : return "dvdrw"; // "DVD-RW dual layer";
193 case 0x18 : return NULL; // "DVD-Download disc"; UNKNOWN
194 case 0x1a : return "dvdplusrw"; // "DVD+RW rewritable";
195 case 0x1b : return "dvdplusr"; // "DVD+R recordable";
196 case 0x20 : return "ddcd"; // "DDCD readonly (retracted)"; no writing
197 case 0x21 : return "ddcdr"; // "DDCD-R recordable (retracted)"; OK?
198 case 0x22 : return "ddcdrw"; // "DDCD-RW rewritable (retracted)"; OK?
199 case 0x2a : return "dvdplusrwdl";//"DVD+RW double layer";
200 case 0x2b : return "dvdplusrdl";// "DVD+R double layer";
201 case 0x40 : return "bd"; // "BD-ROM";
202 case 0x41 : return "bdr"; // "BD-R Sequential Recording (SRM)";
203 case 0x42 : return "bdr"; // "BD-R Random Recording (RRM)";
204 case 0x43 : return "bdre"; // "BD-RE rewritable";
205 case 0x50 : return "hddvd"; // "HD DVD-ROM (retracted)";
206 case 0x51 : return "hddvdr"; // "HD DVD-R (retracted)";
207 case 0x52 : return "hddvdram"; // "HD DVD-RAM (retracted)";
208 case 0x53 : return "hddvdrw"; // "HD DVD-RW (retracted)";
209 case 0x58 : return "hddvdrdl"; // "HD DVD-R dual layer (retracted)";
210 case 0x5a : return "hddvdrwdl"; // "HD DVD-RW dual layer (retracted)";
212 /* reserved */
213 return NULL;
217 #define feat_tbl_len 300
218 #define max_profile 255
219 static void
220 devinfo_optical_disc_caps(int fd, HalDevice *d)
222 uint8_t cmd[12], buf[feat_tbl_len], *fpos, *pos;
223 char str[100];
224 uint8_t present[max_profile+1];
225 char const *name;
226 int feature, feature_cur, feature_len, req_feature;
227 int cnt, profile;
228 int mrw, mrw_w, ok;
230 /* set defaults */
231 for (profile = 0; profile <= max_profile; profile++) {
232 present[profile] = FALSE;
235 HAL_INFO(("devinfo_optical_disc_caps: get feature 0 SCSI call"));
236 req_feature = 0;
237 cmd[0] = 0x46; /* Get configuration */
238 cmd[1] = 0; /* RT=0 -> all independent of current setting */
239 cmd[2] = (req_feature) >> 8; /* MSB feature number */
240 cmd[3] = (req_feature) & 0xff; /* LSB feature number */
241 cmd[7] = (feat_tbl_len) >> 8; /* MSB buffersize */
242 cmd[8] = (feat_tbl_len) & 0xff; /* LSB buffersize */
243 cmd[9] = 0; /* control */
244 ok = scsi_command(fd, cmd, 10, buf, feat_tbl_len, 30000, SCCMD_READ);
246 if (!ok)
247 return;
249 HAL_INFO(("devinfo_optical_disc_caps: processing profiles\n"));
250 fpos = buf + 8;
252 feature = fpos[1] | (fpos[0] << 8);
253 feature_cur = (fpos[2] & 1);
254 feature_len = fpos[3];
255 if (feature != 0) {
256 HAL_INFO(("cdrom drive on crack, its not returning feature 0\n"));
257 return;
260 if ((feature_len & 3) != 0)
261 HAL_INFO(("*** drive returned bad feature length ***"));
263 /* process feature */
264 pos = &fpos[4];
265 for (cnt=0; cnt < feature_len; cnt += 4) {
266 profile = pos[1] | (pos[0] << 8);
267 if (profile <= max_profile) {
268 present[profile] = TRUE;
269 } else {
270 if (profile != 0xffff)
271 HAL_INFO(("devinfo_optical_disc_caps: bump max_profile!, "
272 "found profile %d", profile));
274 pos += 4;
277 /* set hal properties */
278 for (profile = 0; profile <= max_profile; profile++) {
279 /* process profile */
280 name = get_profile_name(d, profile);
281 if (name) {
282 strcpy(str, "storage.cdrom.");
283 strcat(str, name);
284 HAL_INFO(("Profile %d : %s : %s", profile, str,
285 present[profile] ? "true":"false"));
286 hal_device_property_set_bool(d, str, present[profile]);
290 /* set MRW support; feature 0x28, version 0/1 */
291 HAL_INFO(("devinfo_optical_disc_caps: get feature 0x28 SCSI call"));
292 req_feature = 0x28;
293 cmd[0] = 0x46; /* Get configuration */
294 cmd[1] = 0; /* RT=0 -> all independent of current setting */
295 cmd[2] = (req_feature) >> 8; /* MSB feature number */
296 cmd[3] = (req_feature) & 0xff; /* LSB feature number */
297 cmd[7] = (feat_tbl_len) >> 8; /* MSB buffersize */
298 cmd[8] = (feat_tbl_len) & 0xff; /* LSB buffersize */
299 cmd[9] = 0; /* control */
300 ok = scsi_command(fd, cmd, 10, buf, feat_tbl_len, 30000, SCCMD_READ);
302 if (!ok)
303 return;
305 feature = fpos[1] | (fpos[0] << 8);
306 feature_cur = (fpos[2] & 1);
307 feature_len = fpos[3];
309 if ((feature_len & 3) != 0)
310 HAL_INFO(("*** drive returned bad feature length ***"));
312 HAL_INFO(("devinfo_optical_disc_caps: processing MRW\n"));
313 /* process feature */
314 pos = &fpos[4];
315 mrw = FALSE;
316 mrw_w = FALSE;
317 if (feature == 0x28) {
318 mrw = TRUE;
319 if (pos[0] & 1)
320 mrw_w = TRUE;
322 hal_device_property_set_bool(d, "storage.cdrom.mrw", mrw);
323 hal_device_property_set_bool(d, "storage.cdrom.mrw_w", mrw_w);
326 * XXX very rare to now have multi-session support; could be detected
327 * in the change bits of page 5, but set to true for now
329 hal_device_property_set_bool(d, "storage.cdrom.support_multisession", TRUE);
331 /* XXX realy? */
332 hal_device_property_set_bool(d, "storage.cdrom.support_media_changed", TRUE);
334 /* media dependent; addon-storage will handle these */
335 //hal_device_property_set_int(d,"storage.cdrom.read_speed", 0);
336 //hal_device_property_set_int(d,"storage.cdrom.write_speed", 0);
337 //hal_device_property_set_string(d, "storage.cdrom.write_speeds", FALSE);
340 #undef max_profile
341 #undef feat_tbl_len
344 static HalDevice *
345 devinfo_optical_volume_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type)
347 HalDevice *d;
348 struct stat devstat;
349 char *devstr;
350 int error;
352 HAL_INFO (("devinfo_optical_volume_add: parent=%p devnode=%s devfs_path=%s device_type=%s",
353 parent, devnode, devfs_path, device_type));
355 d = hal_device_new ();
357 devstr = malloc(strlen(devnode) + 10);
359 /* info */
360 devinfo_set_default_properties (d, parent, devnode, devnode);
361 hal_device_add_capability (d, "block");
362 hal_device_add_capability (d, "volume");
363 hal_device_add_capability (d, "volume.disc");
364 hal_device_property_set_string (d, "info.category", "volume");
366 /* block */
367 sprintf(devstr, "/dev/%s", devnode);
368 hal_device_property_set_string (d, "block.device", devstr);
369 error = stat(devstr, &devstat);
370 if (!error) {
371 hal_device_property_set_int (d, "block.major", major(devstat.st_rdev));
372 hal_device_property_set_int (d, "block.minor", minor(devstat.st_rdev));
374 sprintf(devstr, "/dev/r%s", devnode);
375 hal_device_property_set_string (d, "block.netbsd.raw_device", devstr);
377 hal_device_property_set_bool (d, "block.is_volume", TRUE);
378 hal_device_property_set_bool (d, "block.no_partitions", TRUE);
379 hal_device_property_set_bool (d, "block.have_scanned", TRUE);
380 hal_device_property_set_string (d, "block.storage_device",
381 hal_device_property_get_string (parent, "info.udi"));
383 /* volume */
384 hal_device_property_set_bool (d, "volume.ignore", FALSE);
385 hal_device_property_set_string(d, "volume.fsusage", "filesytem");
386 hal_device_property_set_string(d, "volume.fstype", "");
387 hal_device_property_set_string(d, "volume.label", "");
388 hal_device_property_set_bool (d, "volume.is_disc", TRUE);
389 hal_device_property_set_bool (d, "volume.is_partition", FALSE);
390 /* rest by addon */
392 /* volume.disc */
393 /* by addon */
395 devinfo_add_enqueue (d, devnode, &devinfo_optical_volume_handler);
397 return d;
401 static HalDevice *
402 devinfo_optical_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type)
404 HalDevice *d;
405 struct stat devstat;
406 char *devstr;
407 char *parent_devnode;
408 int fd, error;
410 if (strncmp(devnode, "cd", 2) != 0) {
411 return (NULL);
414 HAL_INFO (("devinfo_optical_add: parent=%p devnode=%s devfs_path=%s device_type=%s",
415 parent, devnode, devfs_path, device_type));
417 d = hal_device_new ();
419 devstr = malloc(strlen(devnode) + 10);
421 /* info */
422 devinfo_set_default_properties (d, parent, devnode, devnode);
423 // hal_device_property_set_string (d, "netbsd.device", devfs_path);
425 hal_device_property_set_string (d, "info.subsystem", "block");
426 hal_device_add_capability (d, "block");
427 hal_device_add_capability (d, "storage");
428 hal_device_add_capability (d, "storage.cdrom");
430 /* block */
431 sprintf(devstr, "/dev/%s%c", devnode, 'a' + RAW_PART);
432 hal_device_property_set_string (d, "block.device", devstr);
433 error = stat(devstr, &devstat);
434 if (!error) {
435 hal_device_property_set_int (d, "block.major", major(devstat.st_rdev));
436 hal_device_property_set_int (d, "block.minor", minor(devstat.st_rdev));
438 sprintf(devstr, "/dev/r%s%c", devnode, 'a' + RAW_PART);
439 hal_device_property_set_string (d, "block.netbsd.raw_device", devstr);
441 hal_device_property_set_bool (d, "block.is_volume", FALSE);
442 hal_device_property_set_bool (d, "block.no_partitions", TRUE);
443 hal_device_property_set_bool (d, "block.have_scanned", TRUE);
445 /* storage */
446 parent_devnode = hal_device_property_get_string (parent, "netbsd.device");
447 if (strstr (parent_devnode, "umass") == parent_devnode)
448 hal_device_property_set_string (d, "storage.bus", "usb");
449 else if (strstr (parent_devnode, "atapi") == parent_devnode)
450 hal_device_property_set_string (d, "storage.bus", "ide");
451 else
452 hal_device_property_set_string (d, "storage.bus", "scsi");
454 hal_device_property_set_string (d, "storage.drive_type", "cdrom");
455 hal_device_property_set_bool (d, "storage.removable", TRUE);
456 /* "storage.removable.media_available" set by addon-storage */
457 /* "storage.removable.media_size" set by addon-storage */
458 hal_device_property_set_bool (d, "storage.removable.support_async_notification", FALSE);
459 hal_device_property_set_bool (d, "storage.requires_eject", TRUE);
460 hal_device_property_set_bool (d, "storage.hotpluggable", TRUE);
461 hal_device_property_set_bool (d, "storage.media_check_enabled", TRUE); /* XXX */
462 hal_device_property_set_bool (d, "storage.automount_enabled_hint", FALSE); /* multiple choice */
463 hal_device_property_set_bool (d, "storage.no_partitions_hint", TRUE);
464 hal_device_property_set_string (d, "storage.originating_device", ""); /* XXX */
466 fd = open(devstr, O_RDONLY, 0);
467 if (fd) {
468 /* get drive's vendor and model name */
469 devinfo_optical_identify_drive(d, devstr);
471 /* get CD specific `storage.cdrom' values */
472 devinfo_optical_disc_caps(fd, d);
475 devinfo_add_enqueue (d, devnode, &devinfo_optical_handler);
476 if (fd) {
477 /* create CD volume node */
478 sprintf(devstr, "%s%c", devnode, 'a' + RAW_PART);
479 devinfo_optical_volume_add(d, devstr, devfs_path, "volume");
481 close(fd);
483 return (d);