From b3d94504c208adafebbf2ba62ae7fc4e0b7d68f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Mon, 29 May 2006 09:54:03 +0000 Subject: [PATCH] * added a bunch of drivers by Siarzhuk Zharski -> a USB Mass Storgage module (SCSI bus manager add-on) -> a SiS 7018 AC97 driver (uses "old" audio driver interface) -> a USB Serial driver -> a USB Vision driver and media add-on (Haupauge WinTV USB) * moved R3MediaDefs.h from usb_audio driver to common place headers/private/audio (also used by SiS 7018 driver) * added TV tuner frequency defines to data/settings/media/usb_vision Some of these drivers are in unfinished state, particularily the USB Vision driver, the VideoProducer doesn't seem to use it yet, the USB Mass Storage module is known to work though, it also includes add-ons for itself that add support for some "special" hardware, these are not integrated with the Jamfile build system though. Also I didn't much much time with the "CVS package" targets, the ReadMes are not added, someone with more knowledge about this could add them... None of this stuff is added to the Haiku image, it is simply included to be maintained in the Haiku tree from now on. * fixed a bug in Video Producer sample inherited from Be Sample code - the timing from the time source was not really used, on some systems this could cause in the producer not waking up at the correct time if the system time and audio card time are drifting apart git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17625 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../media/usb_vision/Locales/Australia Air | 81 ++ .../media/usb_vision/Locales/FM Radio | 228 ++++ .../media/usb_vision/Locales/Ireland Air | 88 ++ .../media/usb_vision/Locales/Japan Air | 91 ++ .../media/usb_vision/Locales/Japan Cable | 92 ++ data/settings/media/usb_vision/Locales/UK Air | 104 ++ .../media/usb_vision/Locales/UKW Radio | 113 ++ data/settings/media/usb_vision/Locales/US Air | 97 ++ .../media/usb_vision/Locales/US Cable | 154 +++ .../media/usb_vision/Locales/US Cable HRC | 153 +++ .../media/usb_vision/Locales/xUSSR Air | 90 ++ .../media/usb_vision/Locales/xUSSR Cable | 67 + headers/private/audio/R3MediaDefs.h | 86 ++ headers/private/usb_vision/nt100x.h | 115 ++ src/add-ons/kernel/busses/Jamfile | 1 + src/add-ons/kernel/busses/scsi/Jamfile | 3 + src/add-ons/kernel/busses/scsi/usb/Jamfile | 30 + .../kernel/busses/scsi/usb/ReadMe.html | 745 +++++++++++ src/add-ons/kernel/busses/scsi/usb/TODO | 68 + src/add-ons/kernel/busses/scsi/usb/USB_v3.h | 194 +++ .../kernel/busses/scsi/usb/datafab/COPYING | 340 +++++ .../kernel/busses/scsi/usb/datafab/datafab.c | 850 ++++++++++++ .../kernel/busses/scsi/usb/datafab/makefile | 146 ++ .../kernel/busses/scsi/usb/device_info.h | 57 + .../kernel/busses/scsi/usb/fake_device.c | 88 ++ .../kernel/busses/scsi/usb/fake_device.h | 13 + .../kernel/busses/scsi/usb/freecom/COPYING | 340 +++++ .../scsi/usb/freecom/ReadMe.freecom.html | 176 +++ .../scsi/usb/freecom/device_info.sample | 21 + .../kernel/busses/scsi/usb/freecom/freecom.c | 590 +++++++++ .../kernel/busses/scsi/usb/freecom/install.sh | 41 + .../kernel/busses/scsi/usb/freecom/makefile | 151 +++ .../busses/scsi/usb/freecom/uninstall.sh | 33 + src/add-ons/kernel/busses/scsi/usb/install.sh | 45 + .../kernel/busses/scsi/usb/proto_bulk.c | 383 ++++++ .../kernel/busses/scsi/usb/proto_bulk.h | 19 + .../kernel/busses/scsi/usb/proto_cbi.c | 257 ++++ .../kernel/busses/scsi/usb/proto_cbi.h | 16 + .../kernel/busses/scsi/usb/proto_common.c | 164 +++ .../kernel/busses/scsi/usb/proto_common.h | 28 + .../kernel/busses/scsi/usb/proto_module.h | 81 ++ .../kernel/busses/scsi/usb/scsi_commands.h | 318 +++++ src/add-ons/kernel/busses/scsi/usb/settings.c | 340 +++++ src/add-ons/kernel/busses/scsi/usb/settings.h | 31 + .../kernel/busses/scsi/usb/sg_buffer.c | 173 +++ .../kernel/busses/scsi/usb/sg_buffer.h | 37 + src/add-ons/kernel/busses/scsi/usb/tracing.c | 377 ++++++ src/add-ons/kernel/busses/scsi/usb/tracing.h | 96 ++ .../kernel/busses/scsi/usb/transform_procs.c | 476 +++++++ .../kernel/busses/scsi/usb/transform_procs.h | 25 + .../kernel/busses/scsi/usb/uninstall.sh | 32 + src/add-ons/kernel/busses/scsi/usb/usb_defs.h | 37 + src/add-ons/kernel/busses/scsi/usb/usb_scsi.c | 964 ++++++++++++++ .../kernel/busses/scsi/usb/usb_scsi.devices | 76 ++ src/add-ons/kernel/busses/scsi/usb/usb_scsi.h | 72 + .../busses/scsi/usb/usb_scsi.settings.sample | 30 + src/add-ons/kernel/drivers/Jamfile | 2 + src/add-ons/kernel/drivers/audio/Jamfile | 3 +- .../kernel/drivers/audio/sis7018/Jamfile | 25 + .../kernel/drivers/audio/sis7018/ReadMe | 84 ++ .../kernel/drivers/audio/sis7018/ac97.c | 605 +++++++++ .../kernel/drivers/audio/sis7018/ac97.h | 112 ++ .../kernel/drivers/audio/sis7018/install.sh | 21 + .../kernel/drivers/audio/sis7018/midi.c | 176 +++ .../kernel/drivers/audio/sis7018/midi.h | 19 + .../drivers/audio/sis7018/midi_driver.h | 117 ++ .../kernel/drivers/audio/sis7018/pcm.c | 479 +++++++ .../kernel/drivers/audio/sis7018/pcm.h | 43 + .../kernel/drivers/audio/sis7018/sis7018.c | 441 +++++++ .../kernel/drivers/audio/sis7018/sis7018.h | 166 +++ .../kernel/drivers/audio/sis7018/sis7018.rdef | 54 + .../audio/sis7018/sis7018.settings.sample | 37 + .../kernel/drivers/audio/sis7018/sis7018hw.c | 563 ++++++++ .../kernel/drivers/audio/sis7018/sis7018hw.h | 35 + .../kernel/drivers/audio/sis7018/sound.h | 94 ++ .../kernel/drivers/audio/sis7018/t4dwave.h | 114 ++ .../kernel/drivers/audio/sis7018/uninstall.sh | 14 + .../kernel/drivers/audio/usb_audio/Jamfile | 4 + .../drivers/audio/usb_audio/R3MediaDefs.h | 88 -- src/add-ons/kernel/drivers/bus/Jamfile | 2 +- .../graphics/intel_extreme/intel_extreme.cpp | 7 +- src/add-ons/kernel/drivers/ports/Jamfile | 3 + .../kernel/drivers/ports/usb_serial/Jamfile | 27 + .../drivers/ports/usb_serial/ReadMe.html | 262 ++++ .../kernel/drivers/ports/usb_serial/acm.c | 108 ++ .../kernel/drivers/ports/usb_serial/acm.h | 20 + .../kernel/drivers/ports/usb_serial/driver.c | 867 ++++++++++++ .../kernel/drivers/ports/usb_serial/driver.h | 154 +++ .../kernel/drivers/ports/usb_serial/ftdi.c | 225 ++++ .../kernel/drivers/ports/usb_serial/ftdi.h | 27 + .../drivers/ports/usb_serial/install.sh | 24 + .../drivers/ports/usb_serial/prolific.c | 75 ++ .../drivers/ports/usb_serial/prolific.h | 42 + .../kernel/drivers/ports/usb_serial/tracing.c | 169 +++ .../kernel/drivers/ports/usb_serial/tracing.h | 37 + .../drivers/ports/usb_serial/uftdireg.h | 358 +++++ .../drivers/ports/usb_serial/uninstall.sh | 17 + .../drivers/ports/usb_serial/usb_serial.rdef | 54 + .../usb_serial/usb_serial.settings.sample | 37 + src/add-ons/kernel/drivers/video/Jamfile | 3 + .../kernel/drivers/video/usb_vision/Jamfile | 24 + .../drivers/video/usb_vision/ReadMe.html | 240 ++++ .../drivers/video/usb_vision/install.sh | 24 + .../kernel/drivers/video/usb_vision/tracing.c | 107 ++ .../kernel/drivers/video/usb_vision/tracing.h | 31 + .../drivers/video/usb_vision/uninstall.sh | 17 + .../drivers/video/usb_vision/usb_vision.c | 401 ++++++ .../drivers/video/usb_vision/usb_vision.h | 36 + .../usb_vision/usb_vision.settings.sample | 31 + src/add-ons/media/media-add-ons/Jamfile | 1 + .../media/media-add-ons/usb_vision/AddOn.cpp | 165 +++ .../media/media-add-ons/usb_vision/AddOn.h | 59 + .../media-add-ons/usb_vision/Channels.cpp | 582 ++++++++ .../media/media-add-ons/usb_vision/Jamfile | 13 + .../media-add-ons/usb_vision/Producer.cpp | 1173 +++++++++++++++++ .../media/media-add-ons/usb_vision/Producer.h | 208 +++ .../media-add-ons/usb_vision/TunerLocale.cpp | 135 ++ .../media-add-ons/usb_vision/TunerLocale.h | 51 + .../video_producer_demo/Producer.cpp | 4 +- 119 files changed, 18546 insertions(+), 93 deletions(-) create mode 100644 data/settings/media/usb_vision/Locales/Australia Air create mode 100644 data/settings/media/usb_vision/Locales/FM Radio create mode 100644 data/settings/media/usb_vision/Locales/Ireland Air create mode 100644 data/settings/media/usb_vision/Locales/Japan Air create mode 100644 data/settings/media/usb_vision/Locales/Japan Cable create mode 100644 data/settings/media/usb_vision/Locales/UK Air create mode 100644 data/settings/media/usb_vision/Locales/UKW Radio create mode 100644 data/settings/media/usb_vision/Locales/US Air create mode 100644 data/settings/media/usb_vision/Locales/US Cable create mode 100644 data/settings/media/usb_vision/Locales/US Cable HRC create mode 100644 data/settings/media/usb_vision/Locales/xUSSR Air create mode 100644 data/settings/media/usb_vision/Locales/xUSSR Cable create mode 100644 headers/private/audio/R3MediaDefs.h create mode 100644 headers/private/usb_vision/nt100x.h create mode 100644 src/add-ons/kernel/busses/scsi/Jamfile create mode 100644 src/add-ons/kernel/busses/scsi/usb/Jamfile create mode 100644 src/add-ons/kernel/busses/scsi/usb/ReadMe.html create mode 100644 src/add-ons/kernel/busses/scsi/usb/TODO create mode 100644 src/add-ons/kernel/busses/scsi/usb/USB_v3.h create mode 100644 src/add-ons/kernel/busses/scsi/usb/datafab/COPYING create mode 100644 src/add-ons/kernel/busses/scsi/usb/datafab/datafab.c create mode 100644 src/add-ons/kernel/busses/scsi/usb/datafab/makefile create mode 100644 src/add-ons/kernel/busses/scsi/usb/device_info.h create mode 100644 src/add-ons/kernel/busses/scsi/usb/fake_device.c create mode 100644 src/add-ons/kernel/busses/scsi/usb/fake_device.h create mode 100644 src/add-ons/kernel/busses/scsi/usb/freecom/COPYING create mode 100644 src/add-ons/kernel/busses/scsi/usb/freecom/ReadMe.freecom.html create mode 100644 src/add-ons/kernel/busses/scsi/usb/freecom/device_info.sample create mode 100644 src/add-ons/kernel/busses/scsi/usb/freecom/freecom.c create mode 100755 src/add-ons/kernel/busses/scsi/usb/freecom/install.sh create mode 100644 src/add-ons/kernel/busses/scsi/usb/freecom/makefile create mode 100755 src/add-ons/kernel/busses/scsi/usb/freecom/uninstall.sh create mode 100755 src/add-ons/kernel/busses/scsi/usb/install.sh create mode 100644 src/add-ons/kernel/busses/scsi/usb/proto_bulk.c create mode 100644 src/add-ons/kernel/busses/scsi/usb/proto_bulk.h create mode 100644 src/add-ons/kernel/busses/scsi/usb/proto_cbi.c create mode 100644 src/add-ons/kernel/busses/scsi/usb/proto_cbi.h create mode 100644 src/add-ons/kernel/busses/scsi/usb/proto_common.c create mode 100644 src/add-ons/kernel/busses/scsi/usb/proto_common.h create mode 100644 src/add-ons/kernel/busses/scsi/usb/proto_module.h create mode 100644 src/add-ons/kernel/busses/scsi/usb/scsi_commands.h create mode 100644 src/add-ons/kernel/busses/scsi/usb/settings.c create mode 100644 src/add-ons/kernel/busses/scsi/usb/settings.h create mode 100644 src/add-ons/kernel/busses/scsi/usb/sg_buffer.c create mode 100644 src/add-ons/kernel/busses/scsi/usb/sg_buffer.h create mode 100644 src/add-ons/kernel/busses/scsi/usb/tracing.c create mode 100644 src/add-ons/kernel/busses/scsi/usb/tracing.h create mode 100644 src/add-ons/kernel/busses/scsi/usb/transform_procs.c create mode 100644 src/add-ons/kernel/busses/scsi/usb/transform_procs.h create mode 100755 src/add-ons/kernel/busses/scsi/usb/uninstall.sh create mode 100644 src/add-ons/kernel/busses/scsi/usb/usb_defs.h create mode 100644 src/add-ons/kernel/busses/scsi/usb/usb_scsi.c create mode 100644 src/add-ons/kernel/busses/scsi/usb/usb_scsi.devices create mode 100644 src/add-ons/kernel/busses/scsi/usb/usb_scsi.h create mode 100644 src/add-ons/kernel/busses/scsi/usb/usb_scsi.settings.sample create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/Jamfile create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/ReadMe create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/ac97.c create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/ac97.h create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/install.sh create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/midi.c create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/midi.h create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/midi_driver.h create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/pcm.c create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/pcm.h create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/sis7018.c create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/sis7018.h create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/sis7018.rdef create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/sis7018.settings.sample create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/sis7018hw.c create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/sis7018hw.h create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/sound.h create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/t4dwave.h create mode 100644 src/add-ons/kernel/drivers/audio/sis7018/uninstall.sh delete mode 100644 src/add-ons/kernel/drivers/audio/usb_audio/R3MediaDefs.h create mode 100644 src/add-ons/kernel/drivers/ports/Jamfile create mode 100644 src/add-ons/kernel/drivers/ports/usb_serial/Jamfile create mode 100644 src/add-ons/kernel/drivers/ports/usb_serial/ReadMe.html create mode 100644 src/add-ons/kernel/drivers/ports/usb_serial/acm.c create mode 100644 src/add-ons/kernel/drivers/ports/usb_serial/acm.h create mode 100644 src/add-ons/kernel/drivers/ports/usb_serial/driver.c create mode 100644 src/add-ons/kernel/drivers/ports/usb_serial/driver.h create mode 100644 src/add-ons/kernel/drivers/ports/usb_serial/ftdi.c create mode 100644 src/add-ons/kernel/drivers/ports/usb_serial/ftdi.h create mode 100755 src/add-ons/kernel/drivers/ports/usb_serial/install.sh create mode 100644 src/add-ons/kernel/drivers/ports/usb_serial/prolific.c create mode 100644 src/add-ons/kernel/drivers/ports/usb_serial/prolific.h create mode 100644 src/add-ons/kernel/drivers/ports/usb_serial/tracing.c create mode 100644 src/add-ons/kernel/drivers/ports/usb_serial/tracing.h create mode 100644 src/add-ons/kernel/drivers/ports/usb_serial/uftdireg.h create mode 100755 src/add-ons/kernel/drivers/ports/usb_serial/uninstall.sh create mode 100644 src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.rdef create mode 100644 src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.settings.sample create mode 100644 src/add-ons/kernel/drivers/video/Jamfile create mode 100644 src/add-ons/kernel/drivers/video/usb_vision/Jamfile create mode 100644 src/add-ons/kernel/drivers/video/usb_vision/ReadMe.html create mode 100644 src/add-ons/kernel/drivers/video/usb_vision/install.sh create mode 100644 src/add-ons/kernel/drivers/video/usb_vision/tracing.c create mode 100644 src/add-ons/kernel/drivers/video/usb_vision/tracing.h create mode 100644 src/add-ons/kernel/drivers/video/usb_vision/uninstall.sh create mode 100644 src/add-ons/kernel/drivers/video/usb_vision/usb_vision.c create mode 100644 src/add-ons/kernel/drivers/video/usb_vision/usb_vision.h create mode 100644 src/add-ons/kernel/drivers/video/usb_vision/usb_vision.settings.sample create mode 100644 src/add-ons/media/media-add-ons/usb_vision/AddOn.cpp create mode 100644 src/add-ons/media/media-add-ons/usb_vision/AddOn.h create mode 100644 src/add-ons/media/media-add-ons/usb_vision/Channels.cpp create mode 100644 src/add-ons/media/media-add-ons/usb_vision/Jamfile create mode 100644 src/add-ons/media/media-add-ons/usb_vision/Producer.cpp create mode 100644 src/add-ons/media/media-add-ons/usb_vision/Producer.h create mode 100644 src/add-ons/media/media-add-ons/usb_vision/TunerLocale.cpp create mode 100644 src/add-ons/media/media-add-ons/usb_vision/TunerLocale.h diff --git a/data/settings/media/usb_vision/Locales/Australia Air b/data/settings/media/usb_vision/Locales/Australia Air new file mode 100644 index 0000000000..7923fe3029 --- /dev/null +++ b/data/settings/media/usb_vision/Locales/Australia Air @@ -0,0 +1,81 @@ +; +; Tuner locale file for BeOS USBVision driver +; +; "Australia Broadcast channels" +; +;=========================================================== +; This file is a part of BeOS USBVision driver project. +; Copyright (c) 2003 by Siarzuk Zharski +; +; This file may be used under the terms of the BSD License +; Look into the file "License" for details. +; +; $Source: /cvsroot/sis4be/usbvision/Locales/Australia\040Air,v $ +; $Author: zharik $ +; $Revision: 1.2 $ +; $Date: 2003/07/09 04:58:08 $ +;=========================================================== +; +; Format of this file: +; +; The file begins with the name of locale preceded with "@"-sign. This name will be +; visible for user in Tuner Locale settings. +; Channels are presented as frequency <-> name pairs. +; The Frequency is in Hz and name begins just after the first space character +; after frequency number. The name ends at the end of line. +; +; All lines beginning with ";"-sign are comments and will be ignored. +; +@Australia Air + 46250000 0 + 57250000 1 + 64250000 2 + 86250000 3 + 95250000 4 +102250000 5 +138250000 5A +175250000 6 +182250000 7 +189250000 8 +196250000 9 +209250000 10 +216250000 11 +527250000 28 +534250000 29 +541250000 30 +548250000 31 +555250000 32 +562250000 33 +569250000 34 +576250000 35 +604250000 39 +611250000 40 +618250000 41 +625250000 42 +632250000 43 +639250000 44 +646250000 45 +653250000 46 +660250000 47 +667250000 48 +674250000 49 +681250000 50 +688250000 51 +695250000 52 +702250000 53 +709250000 54 +716250000 55 +723250000 56 +730250000 57 +737250000 58 +744250000 59 +751250000 60 +758250000 61 +765250000 62 +772250000 63 +779250000 64 +786250000 65 +793250000 66 +800250000 67 +807250000 68 +814250000 69 diff --git a/data/settings/media/usb_vision/Locales/FM Radio b/data/settings/media/usb_vision/Locales/FM Radio new file mode 100644 index 0000000000..cb880bffc4 --- /dev/null +++ b/data/settings/media/usb_vision/Locales/FM Radio @@ -0,0 +1,228 @@ +; +; Tuner locale file for BeOS USBVision driver +; +; "FM Radio channels" +; +;=========================================================== +; This file is a part of BeOS USBVision driver project. +; Copyright (c) 2003 by Siarzuk Zharski +; +; This file may be used under the terms of the BSD License +; Look into the file "License" for details. +; +; $Source: /cvsroot/sis4be/usbvision/Locales/FM\040Radio,v $ +; $Author: zharik $ +; $Revision: 1.2 $ +; $Date: 2003/07/09 04:58:08 $ +;=========================================================== +; +; Format of this file: +; +; The file begins with the name of locale preceded with "@"-sign. This name will be +; visible for user in Tuner Locale settings. +; Channels are presented as frequency <-> name pairs. +; The Frequency is in Hz and name begins just after the first space character +; after frequency number. The name ends at the end of line. +; +; All lines beginning with ";"-sign are comments and will be ignored. +; +; The word "Radio" in angle brakets means that channels are radio channels. +; +@FM Radio +; + 87500000 87,5 + 87600000 87,6 + 87700000 87,7 + 87800000 87,8 + 87900000 87,9 + 88000000 88,0 + 88100000 88,1 + 88200000 88,2 + 88300000 88,3 + 88400000 88,4 + 88500000 88,5 + 88600000 88,6 + 88700000 88,7 + 88800000 88,8 + 88900000 88,9 + 89000000 89,0 + 89100000 89,1 + 89200000 89,2 + 89300000 89,3 + 89400000 89,4 + 89500000 89,5 + 89600000 89,6 + 89700000 89,7 + 89800000 89,8 + 89900000 89,9 + 90000000 90,0 + 90100000 90,1 + 90200000 90,2 + 90300000 90,3 + 90400000 90,4 + 90500000 90,5 + 90600000 90,6 + 90700000 90,7 + 90800000 90,8 + 90900000 90,9 + 91000000 91,0 + 91100000 91,1 + 91200000 91,2 + 91300000 91,3 + 91400000 91,4 + 91500000 91,5 + 91600000 91,6 + 91700000 91,7 + 91800000 91,8 + 91900000 91,9 + 92000000 92,0 + 92100000 92,1 + 92200000 92,2 + 92300000 92,3 + 92400000 92,4 + 92500000 92,5 + 92600000 92,6 + 92700000 92,7 + 92800000 92,8 + 92900000 92,9 + 93000000 93,0 + 93100000 93,1 + 93200000 93,2 + 93300000 93,3 + 93400000 93,4 + 93500000 93,5 + 93600000 93,6 + 93700000 93,7 + 93800000 93,8 + 93900000 93,9 + 94000000 94,0 + 94100000 94,1 + 94200000 94,2 + 94300000 94,3 + 94400000 94,4 + 94500000 94,5 + 94600000 94,6 + 94700000 94,7 + 94800000 94,8 + 94900000 94,9 + 95000000 95,0 + 95100000 95,1 + 95200000 95,2 + 95300000 95,3 + 95400000 95,4 + 95500000 95,5 + 95600000 95,6 + 95700000 95,7 + 95800000 95,8 + 95900000 95,9 + 96000000 96,0 + 97100000 97,1 + 97200000 97,2 + 97300000 97,3 + 97400000 97,4 + 97500000 97,5 + 97600000 97,6 + 97700000 97,7 + 97800000 97,8 + 97900000 97,9 + 98000000 98,0 + 98100000 98,1 + 98200000 98,2 + 98300000 98,3 + 98400000 98,4 + 98500000 98,5 + 98600000 98,6 + 98700000 98,7 + 98800000 98,8 + 98900000 98,9 + 99000000 99,0 + 99100000 99,1 + 99200000 99,2 + 99300000 99,3 + 99400000 99,4 + 99500000 99,5 + 99600000 99,6 + 99700000 99,7 + 99800000 99,8 + 99900000 99,9 +100000000 100,0 +100100000 100,1 +100200000 100,2 +100300000 100,3 +100400000 100,4 +100500000 100,5 +100600000 100,6 +100700000 100,7 +100800000 100,8 +100900000 100,9 +101000000 101,0 +101100000 101,1 +101200000 101,2 +101300000 101,3 +101400000 101,4 +101500000 101,5 +101600000 101,6 +101700000 101,7 +101800000 101,8 +101900000 101,9 +102000000 102,0 +102100000 102,1 +102200000 102,2 +102300000 102,3 +102400000 102,4 +102500000 102,5 +102600000 102,6 +102700000 102,7 +102800000 102,8 +102900000 102,9 +103000000 103,0 +103100000 103,1 +103200000 103,2 +103300000 103,3 +103400000 103,4 +103500000 103,5 +103600000 103,6 +103700000 103,7 +103800000 103,8 +103900000 103,9 +104000000 104,0 +104100000 104,1 +104200000 104,2 +104300000 104,3 +104400000 104,4 +104500000 104,5 +104600000 104,6 +104700000 104,7 +104800000 104,8 +104900000 104,9 +105000000 105,0 +105100000 105,1 +105200000 105,2 +105300000 105,3 +105400000 105,4 +105500000 105,5 +105600000 105,6 +105700000 105,7 +105800000 105,8 +105900000 105,9 +106000000 106,0 +106100000 106,1 +106200000 106,2 +106300000 106,3 +106400000 106,4 +106500000 106,5 +106600000 106,6 +106700000 106,7 +106800000 106,8 +106900000 106,9 +107000000 107,0 +107100000 107,1 +107200000 107,2 +107300000 107,3 +107400000 107,4 +107500000 107,5 +107600000 107,6 +107700000 107,7 +107800000 107,8 +107900000 107,9 +108000000 108,0 diff --git a/data/settings/media/usb_vision/Locales/Ireland Air b/data/settings/media/usb_vision/Locales/Ireland Air new file mode 100644 index 0000000000..c945379d16 --- /dev/null +++ b/data/settings/media/usb_vision/Locales/Ireland Air @@ -0,0 +1,88 @@ +; +; Tuner locale file for BeOS USBVision driver +; +; "Ireland Broadcast channels" +; +;=========================================================== +; This file is a part of BeOS USBVision driver project. +; Copyright (c) 2003 by Siarzuk Zharski +; +; This file may be used under the terms of the BSD License +; Look into the file "License" for details. +; +; $Source: /cvsroot/sis4be/usbvision/Locales/Ireland\040Air,v $ +; $Author: zharik $ +; $Revision: 1.2 $ +; $Date: 2003/07/09 04:58:08 $ +;=========================================================== +; +; Format of this file: +; +; The file begins with the name of locale preceded with "@"-sign. This name will be +; visible for user in Tuner Locale settings. +; Channels are presented as frequency <-> name pairs. +; The Frequency is in Hz and name begins just after the first space character +; after frequency number. The name ends at the end of line. +; +; All lines beginning with ";"-sign are comments and will be ignored. +; +@Ireland Air + 45750000 A(2) + 53750000 B(3) + 61750000 C(4) +175250000 D(5) +183250000 E(6) +191250000 F(7) +199250000 G(8) +207250000 H(9) +215250000 I(10) +223250000 J(11) +471250000 21 +479250000 22 +487250000 23 +495250000 24 +503250000 25 +511250000 26 +519250000 27 +527250000 28 +535250000 29 +543250000 30 +551250000 31 +559250000 32 +567250000 33 +575250000 34 +583250000 35 +591250000 36 +599250000 37 +607250000 38 +615250000 39 +623250000 40 +631250000 41 +639250000 42 +647250000 43 +655250000 44 +663250000 45 +671250000 46 +679250000 47 +687250000 48 +695250000 49 +703250000 50 +711250000 51 +719250000 52 +727250000 53 +735250000 54 +743250000 55 +751250000 56 +759250000 57 +767250000 58 +775250000 59 +783250000 60 +791250000 61 +799250000 62 +807250000 63 +815250000 64 +823250000 65 +831250000 66 +839250000 67 +847250000 68 +855250000 69 diff --git a/data/settings/media/usb_vision/Locales/Japan Air b/data/settings/media/usb_vision/Locales/Japan Air new file mode 100644 index 0000000000..2e6484d7f7 --- /dev/null +++ b/data/settings/media/usb_vision/Locales/Japan Air @@ -0,0 +1,91 @@ +; +; Tuner locale file for BeOS USBVision driver +; +; "Japan Broadcast channels" +; +;=========================================================== +; This file is a part of BeOS USBVision driver project. +; Copyright (c) 2003 by Siarzuk Zharski +; +; This file may be used under the terms of the BSD License +; Look into the file "License" for details. +; +; $Source: /cvsroot/sis4be/usbvision/Locales/Japan\040Air,v $ +; $Author: zharik $ +; $Revision: 1.2 $ +; $Date: 2003/07/09 04:58:08 $ +;=========================================================== +; +; Format of this file: +; +; The file begins with the name of locale preceded with "@"-sign. This name will be +; visible for user in Tuner Locale settings. +; Channels are presented as frequency <-> name pairs. +; The Frequency is in Hz and name begins just after the first space character +; after frequency number. The name ends at the end of line. +; +; All lines beginning with ";"-sign are comments and will be ignored. +; +@Japan Air + 91250000 1 + 97250000 2 +103250000 3 +171250000 4 +177250000 5 +183250000 6 +189250000 7 +193250000 8 +199250000 9 +205250000 10 +211250000 11 +217250000 12 +471250000 13 +477250000 14 +483250000 15 +489250000 16 +495250000 17 +501250000 18 +507250000 19 +513250000 20 +519250000 21 +525250000 22 +531250000 23 +537250000 24 +543250000 25 +549250000 26 +555250000 27 +561250000 28 +567250000 29 +573250000 30 +579250000 31 +585250000 32 +591250000 33 +597250000 34 +603250000 35 +609250000 36 +615250000 37 +621250000 38 +627250000 39 +633250000 40 +639250000 41 +645250000 42 +651250000 43 +657250000 44 +663250000 45 +669250000 46 +675250000 47 +681250000 48 +687250000 49 +693250000 50 +699250000 51 +705250000 52 +711250000 53 +717250000 54 +723250000 55 +729250000 56 +735250000 57 +741250000 58 +747250000 59 +753250000 60 +759250000 61 +765250000 62 diff --git a/data/settings/media/usb_vision/Locales/Japan Cable b/data/settings/media/usb_vision/Locales/Japan Cable new file mode 100644 index 0000000000..d2140d32a6 --- /dev/null +++ b/data/settings/media/usb_vision/Locales/Japan Cable @@ -0,0 +1,92 @@ +; +; Tuner locale file for BeOS USBVision driver +; +; "Japan Cable channels" +; +;=========================================================== +; This file is a part of BeOS USBVision driver project. +; Copyright (c) 2003 by Siarzuk Zharski +; +; This file may be used under the terms of the BSD License +; Look into the file "License" for details. +; +; $Source: /cvsroot/sis4be/usbvision/Locales/Japan\040Cable,v $ +; $Author: zharik $ +; $Revision: 1.2 $ +; $Date: 2003/07/09 04:58:08 $ +;=========================================================== +; +; Format of this file: +; +; The file begins with the name of locale preceded with "@"-sign. This name will be +; visible for user in Tuner Locale settings. +; Channels are presented as frequency <-> name pairs. +; The Frequency is in Hz and name begins just after the first space character +; after frequency number. The name ends at the end of line. +; +; All lines beginning with ";"-sign are comments and will be ignored. +; +@Japan Cable + 91250000 1 + 97250000 2 +103250000 3 +171250000 4 +177250000 5 +183250000 6 +189250000 7 +193250000 8 +199250000 9 +205250000 10 +211250000 11 +217250000 12 +109250000 C13 +115250000 C14 +121250000 C15 +127250000 C16 +133250000 C17 +139250000 C18 +145250000 C19 +151250000 C20 +157250000 C21 +165250000 C22 +223250000 C23 +229250000 C24 +235250000 C25 +241250000 C26 +247250000 C27 +253250000 C28 +259250000 C29 +265250000 C30 +271250000 C31 +277250000 C32 +293250000 C33 +289250000 C34 +295250000 C35 +301250000 C36 +307250000 C37 +313250000 C38 +319250000 C39 +325250000 C40 +331250000 C41 +337250000 C42 +343250000 C43 +349250000 C44 +355250000 C45 +361250000 C46 +367250000 C47 +373250000 C48 +379250000 C49 +385250000 C50 +391250000 C51 +397250000 C52 +403250000 C53 +409250000 C54 +415250000 C55 +421250000 C56 +427250000 C57 +433250000 C58 +439250000 C59 +445250000 C60 +451250000 C61 +457250000 C62 +463250000 C63 diff --git a/data/settings/media/usb_vision/Locales/UK Air b/data/settings/media/usb_vision/Locales/UK Air new file mode 100644 index 0000000000..cce3ff4f51 --- /dev/null +++ b/data/settings/media/usb_vision/Locales/UK Air @@ -0,0 +1,104 @@ +; +; Tuner locale file for BeOS USBVision driver +; +; "Great Britain Broadcast channels" +; +;=========================================================== +; This file is a part of BeOS USBVision driver project. +; Copyright (c) 2003 by Siarzuk Zharski +; +; This file may be used under the terms of the BSD License +; Look into the file "License" for details. +; +; $Source: /cvsroot/sis4be/usbvision/Locales/UK\040Air,v $ +; $Author: zharik $ +; $Revision: 1.2 $ +; $Date: 2003/07/09 04:58:08 $ +;=========================================================== +; +; Format of this file: +; +; The file begins with the name of locale preceded with "@"-sign. This name will be +; visible for user in Tuner Locale settings. +; Channels are presented as frequency <-> name pairs. +; The Frequency is in Hz and name begins just after the first space character +; after frequency number. The name ends at the end of line. +; +; All lines beginning with ";"-sign are comments and will be ignored. +; +@UK Air + 45750000 A + 53750000 B + 61750000 C +175250000 D +183250000 E +191250000 F +199250000 G +207250000 H +215250000 J +223250000 C10 +231250000 C11 +247250000 C13 +471250000 B21 +479250000 B22 +487250000 B23 +495250000 B24 +503250000 B25 +511250000 B26 +519250000 B27 +527250000 B28 +535250000 B29 +543250000 B30 +551250000 B31 +559250000 B32 +567250000 B33 +575250000 B34 +583250000 B35 +591250000 B36 +599250000 B37 +607250000 B38 +615250000 B39 +623250000 B40 +631250000 B41 +639250000 B42 +647250000 B43 +655250000 B44 +663250000 B45 +671250000 B46 +679250000 B47 +687250000 B48 +695250000 B49 +703250000 B50 +711250000 B51 +719250000 B52 +727250000 B53 +735250000 B54 +743250000 B55 +751250000 B56 +759250000 B57 +767250000 B58 +775250000 B59 +783250000 B60 +791250000 B61 +799250000 B62 +807250000 B63 +815250000 B64 +823250000 B65 +831250000 B66 +839250000 B67 +847250000 B68 +855250000 B69 + 45000000 B1 + 51750000 B2 + 56750000 B3 + 61750000 B4 + 66750000 B5 +179750000 B6 +184750000 B7 +189750000 B8 +194750000 B9 +199750000 B10 +204750000 B11 +209750000 B12 +214750000 B13 +219750000 B14 diff --git a/data/settings/media/usb_vision/Locales/UKW Radio b/data/settings/media/usb_vision/Locales/UKW Radio new file mode 100644 index 0000000000..4f944e0258 --- /dev/null +++ b/data/settings/media/usb_vision/Locales/UKW Radio @@ -0,0 +1,113 @@ +; +; Tuner locale file for BeOS USBVision driver +; +; "Ex USSR UKW Radio channels" +; +;=========================================================== +; This file is a part of BeOS USBVision driver project. +; Copyright (c) 2003 by Siarzuk Zharski +; +; This file may be used under the terms of the BSD License +; Look into the file "License" for details. +; +; $Source: /cvsroot/sis4be/usbvision/Locales/UKW\040Radio,v $ +; $Author: zharik $ +; $Revision: 1.2 $ +; $Date: 2003/07/09 04:58:08 $ +;=========================================================== +; +; Format of this file: +; +; The file begins with the name of locale preceded with "@"-sign. This name will be +; visible for user in Tuner Locale settings. +; Channels are presented as frequency <-> name pairs. +; The Frequency is in Hz and name begins just after the first space character +; after frequency number. The name ends at the end of line. +; +; All lines beginning with ";"-sign are comments and will be ignored. +; +; The word "Radio" in angle brakets means that this channels is radio channels. +; +@UKW Radio +; +66000000 66,0 +66100000 66,1 +66200000 66,2 +66300000 66,3 +66400000 66,4 +66500000 66,5 +66600000 66,6 +66700000 66,7 +66800000 66,8 +66900000 66,9 +67000000 67,0 +67100000 67,1 +67200000 67,2 +67300000 67,3 +67400000 67,4 +67500000 67,5 +67600000 67,6 +67700000 67,7 +67800000 67,8 +67900000 67,9 +68000000 68,0 +68100000 68,1 +68200000 68,2 +68300000 68,3 +68400000 68,4 +68500000 68,5 +68600000 68,6 +68700000 68,7 +68800000 68,8 +68900000 68,9 +69000000 69,0 +69100000 69,1 +69200000 69,2 +69300000 69,3 +69400000 69,4 +69500000 69,5 +69600000 69,6 +69700000 69,7 +69800000 69,8 +69900000 69,9 +70000000 70,0 +70100000 70,1 +70200000 70,2 +70300000 70,3 +70400000 70,4 +70500000 70,5 +70600000 70,6 +70700000 70,7 +70800000 70,8 +70900000 70,9 +71000000 71,0 +71100000 71,1 +71200000 71,2 +71300000 71,3 +71400000 71,4 +71500000 71,5 +71600000 71,6 +71700000 71,7 +71800000 71,8 +71900000 71,9 +72000000 72,0 +72100000 72,1 +72200000 72,2 +72300000 72,3 +72400000 72,4 +72500000 72,5 +72600000 72,6 +72700000 72,7 +72800000 72,8 +72900000 72,9 +73000000 73,0 +73100000 73,1 +73200000 73,2 +73300000 73,3 +73400000 73,4 +73500000 73,5 +73600000 73,6 +73700000 73,7 +73800000 73,8 +73900000 73,9 +74000000 74,0 diff --git a/data/settings/media/usb_vision/Locales/US Air b/data/settings/media/usb_vision/Locales/US Air new file mode 100644 index 0000000000..01ff680896 --- /dev/null +++ b/data/settings/media/usb_vision/Locales/US Air @@ -0,0 +1,97 @@ +; +; Tuner locale file for BeOS USBVision driver +; +; "US Broadcast channels" +; +;=========================================================== +; This file is a part of BeOS USBVision driver project. +; Copyright (c) 2003 by Siarzuk Zharski +; +; This file may be used under the terms of the BSD License +; Look into the file "License" for details. +; +; $Source: /cvsroot/sis4be/usbvision/Locales/US\040Air,v $ +; $Author: zharik $ +; $Revision: 1.2 $ +; $Date: 2003/07/09 04:58:08 $ +;=========================================================== +; +; Format of this file: +; +; The file begins with the name of locale preceded with "@"-sign. This name will be +; visible for user in Tuner Locale settings. +; Channels are presented as frequency <-> name pairs. +; The Frequency is in Hz and name begins just after the first space character +; after frequency number. The name ends at the end of line. +; +; All lines beginning with ";"-sign are comments and will be ignored. +; +@US Air + 55250000 2 + 61250000 3 + 67250000 4 + 77250000 5 + 83250000 6 +175250000 7 +181250000 8 +187250000 9 +193250000 10 +199250000 11 +205250000 12 +211250000 13 +471250000 14 +477250000 15 +483250000 16 +489250000 17 +495250000 18 +501250000 19 +507250000 20 +513250000 21 +519250000 22 +525250000 23 +531250000 24 +537250000 25 +543250000 26 +549250000 27 +555250000 28 +561250000 29 +567250000 30 +573250000 31 +579250000 32 +585250000 33 +591250000 34 +597250000 35 +603250000 36 +609250000 37 +615250000 38 +621250000 39 +627250000 40 +633250000 41 +639250000 42 +645250000 43 +651250000 44 +657250000 45 +663250000 46 +669250000 47 +675250000 48 +681250000 49 +687250000 50 +693250000 51 +699250000 52 +705250000 53 +711250000 54 +717250000 55 +723250000 56 +729250000 57 +735250000 58 +741250000 59 +747250000 60 +753250000 61 +759250000 62 +765250000 63 +771250000 64 +777250000 65 +783250000 66 +789250000 67 +795250000 68 +801250000 69 diff --git a/data/settings/media/usb_vision/Locales/US Cable b/data/settings/media/usb_vision/Locales/US Cable new file mode 100644 index 0000000000..7d17246b8c --- /dev/null +++ b/data/settings/media/usb_vision/Locales/US Cable @@ -0,0 +1,154 @@ +; +; Tuner locale file for BeOS USBVision driver +; +; "US Cable channels" +; +;=========================================================== +; This file is a part of BeOS USBVision driver project. +; Copyright (c) 2003 by Siarzuk Zharski +; +; This file may be used under the terms of the BSD License +; Look into the file "License" for details. +; +; $Source: /cvsroot/sis4be/usbvision/Locales/US\040Cable,v $ +; $Author: zharik $ +; $Revision: 1.2 $ +; $Date: 2003/07/09 04:58:08 $ +;=========================================================== +; +; Format of this file: +; +; The file begins with the name of locale preceded with "@"-sign. This name will be +; visible for user in Tuner Locale settings. +; Channels are presented as frequency <-> name pairs. +; The Frequency is in Hz and name begins just after the first space character +; after frequency number. The name ends at the end of line. +; +; All lines beginning with ";"-sign are comments and will be ignored. +; +@US Cable + 73250000 4A + 55250000 2 + 61250000 3 + 67250000 4 + 77250000 5 + 83250000 6 +175250000 7 +181250000 8 +187250000 9 +193250000 10 +199250000 11 +205250000 12 +211250000 13 +121250000 A +127250000 B +133250000 C +139250000 D +145250000 E +151250000 F +157250000 G +163250000 H +169250000 I +217250000 J +223250000 K +229250000 L +235250000 M +241250000 N +247250000 O +253250000 P +259250000 Q +265250000 R +271250000 S +277250000 T +283250000 U +289250000 V +295250000 W +301250000 W+1 +307250000 W+2 +313250000 W+3 +319250000 W+4 +325250000 W+5 +331250000 W+6 +337250000 W+7 +343250000 W+8 +349250000 W+9 +355250000 W+10 +361250000 W+11 +367250000 W+12 +373250000 W+13 +379250000 W+14 +385250000 W+15 +391250000 W+16 +397250000 W+17 +403250000 W+18 +409250000 W+19 +415250000 W+20 +421250000 W+21 +427250000 W+22 +433250000 W+23 +439250000 W+24 +445250000 W+25 +451250000 W+26 +457250000 W+27 +463250000 W+28 +469250000 65 +475250000 66 +481250000 67 +487250000 68 +493250000 69 +499250000 70 +505250000 71 +511250000 72 +517250000 73 +523250000 74 +529250000 75 +535250000 76 +541250000 77 +547250000 78 +553250000 79 +559250000 80 +565250000 81 +571250000 82 +577250000 83 +583250000 84 +589250000 85 +595250000 86 +601250000 87 +607250000 88 +613250000 89 +619250000 90 +625250000 91 +631250000 92 +637250000 93 +643250000 94 + 91250000 A­5 + 97250000 A­4 +103250000 A­3 +109250000 A­2 +115250000 A-1 +649250000 100 +655250000 101 +661250000 102 +667250000 103 +673250000 104 +679250000 105 +685250000 106 +691250000 107 +697250000 108 +703250000 109 +709250000 110 +715250000 111 +721250000 112 +727250000 113 +733250000 114 +739250000 115 +745250000 116 +751250000 117 +757250000 118 +763250000 119 +769250000 120 +775250000 121 +781250000 122 +787250000 123 +793250000 124 +799250000 125 diff --git a/data/settings/media/usb_vision/Locales/US Cable HRC b/data/settings/media/usb_vision/Locales/US Cable HRC new file mode 100644 index 0000000000..3493a381ab --- /dev/null +++ b/data/settings/media/usb_vision/Locales/US Cable HRC @@ -0,0 +1,153 @@ +; +; Tuner locale file for BeOS USBVision driver +; +; "US Cable HRC channels" +; +;=========================================================== +; This file is a part of BeOS USBVision driver project. +; Copyright (c) 2003 by Siarzuk Zharski +; +; This file may be used under the terms of the BSD License +; Look into the file "License" for details. +; +; $Source: /cvsroot/sis4be/usbvision/Locales/US\040Cable\040HRC,v $ +; $Author: zharik $ +; $Revision: 1.2 $ +; $Date: 2003/07/09 04:58:08 $ +;=========================================================== +; +; Format of this file: +; +; The file begins with the name of locale preceded with "@"-sign. This name will be +; visible for user in Tuner Locale settings. +; Channels are presented as frequency <-> name pairs. +; The Frequency is in Hz and name begins just after the first space character +; after frequency number. The name ends at the end of line. +; +; All lines beginning with ";"-sign are comments and will be ignored. +; +@US Cable HRC + 54000000 2 + 60000000 3 + 66000000 4 + 76000000 5 + 82000000 6 +174000000 7 +180000000 8 +186000000 9 +192000000 10 +198000000 11 +204000000 12 +210000000 13 +120000000 A +126000000 B +132000000 C +138000000 D +144000000 E +150000000 F +156000000 G +162000000 H +168000000 I +216000000 J +222000000 K +228000000 L +234000000 M +240000000 N +246000000 O +252000000 P +258000000 Q +264000000 R +270000000 S +276000000 T +282000000 U +288000000 V +294000000 W +300000000 W+1 +306000000 W+2 +312000000 W+3 +318000000 W+4 +324000000 W+5 +330000000 W+6 +336000000 W+7 +342000000 W+8 +348000000 W+9 +354000000 W+10 +360000000 W+11 +366000000 W+12 +372000000 W+13 +378000000 W+14 +384000000 W+15 +390000000 W+16 +396000000 W+17 +402000000 W+18 +408000000 W+19 +414000000 W+20 +420000000 W+21 +426000000 W+22 +432000000 W+23 +438000000 W+24 +444000000 W+25 +450000000 W+26 +456000000 W+27 +462000000 W+28 +468000000 65 +474000000 66 +480000000 67 +486000000 68 +492000000 69 +498000000 70 +504000000 71 +510000000 72 +516000000 73 +522000000 74 +528000000 75 +534000000 76 +540000000 77 +546000000 78 +552000000 79 +558000000 80 +564000000 81 +570000000 82 +576000000 83 +582000000 84 +588000000 85 +594000000 86 +600000000 87 +606000000 88 +612000000 89 +618000000 90 +624000000 91 +630000000 92 +636000000 93 +642000000 94 + 90000000 A­5 + 96000000 A­4 +102000000 A­3 +108000000 A­2 +114000000 A-1 +648000000 100 +654000000 101 +660000000 102 +666000000 103 +672000000 104 +678000000 105 +684000000 106 +690000000 107 +696000000 108 +702000000 109 +708000000 110 +714000000 111 +720000000 112 +726000000 113 +732000000 114 +738000000 115 +744000000 116 +750000000 117 +756000000 118 +762000000 119 +768000000 120 +774000000 121 +780000000 122 +786000000 123 +792000000 124 +798000000 125 diff --git a/data/settings/media/usb_vision/Locales/xUSSR Air b/data/settings/media/usb_vision/Locales/xUSSR Air new file mode 100644 index 0000000000..8fd4b95f5c --- /dev/null +++ b/data/settings/media/usb_vision/Locales/xUSSR Air @@ -0,0 +1,90 @@ +; +; Tuner locale file for BeOS USBVision driver +; +; "Ex USSR Broadcast channels" +; +;=========================================================== +; This file is a part of BeOS USBVision driver project. +; Copyright (c) 2003 by Siarzuk Zharski +; +; This file may be used under the terms of the BSD License +; Look into the file "License" for details. +; +; $Source: /cvsroot/sis4be/usbvision/Locales/xUSSR\040Air,v $ +; $Author: zharik $ +; $Revision: 1.2 $ +; $Date: 2003/07/09 04:58:08 $ +;=========================================================== +; +; Format of this file: +; +; The file begins with the name of locale preceded with "@"-sign. This name will be +; visible for user in Tuner Locale settings. +; Channels are presented as frequency <-> name pairs. +; The Frequency is in Hz and name begins just after the first space character +; after frequency number. The name ends at the end of line. +; +; All lines beginning with ";"-sign are comments and will be ignored. +; +@xUSSR Air + 49750000 1 + 59250000 2 + 77250000 3 + 85250000 4 + 93250000 5 +175250000 6 +183250000 7 +191250000 8 +199250000 9 +207250000 10 +215250000 11 +223250000 12 +471250000 21 +479250000 22 +487250000 23 +495250000 24 +503250000 25 +511250000 26 +519250000 27 +527250000 28 +535250000 29 +543250000 30 +551250000 31 +559250000 32 +567250000 33 +575250000 34 +583250000 35 +591250000 36 +599250000 37 +607250000 38 +615250000 39 +623250000 40 +631250000 41 +639250000 42 +647250000 43 +655250000 44 +663250000 45 +671250000 46 +679250000 47 +687250000 48 +695250000 49 +703250000 50 +711250000 51 +719250000 52 +727250000 53 +735250000 54 +743250000 55 +751250000 56 +759250000 57 +767250000 58 +775250000 59 +783250000 60 +791250000 61 +799250000 62 +807250000 63 +815250000 64 +823250000 65 +831250000 66 +839250000 67 +847250000 68 +855250000 69 diff --git a/data/settings/media/usb_vision/Locales/xUSSR Cable b/data/settings/media/usb_vision/Locales/xUSSR Cable new file mode 100644 index 0000000000..d5f70662c7 --- /dev/null +++ b/data/settings/media/usb_vision/Locales/xUSSR Cable @@ -0,0 +1,67 @@ +; +; Tuner locale file for BeOS USBVision driver +; +; "Ex USSR Cable channels" +; +;=========================================================== +; This file is a part of BeOS USBVision driver project. +; Copyright (c) 2003 by Siarzuk Zharski +; +; This file may be used under the terms of the BSD License +; Look into the file "License" for details. +; +; $Source: /cvsroot/sis4be/usbvision/Locales/xUSSR\040Cable,v $ +; $Author: zharik $ +; $Revision: 1.2 $ +; $Date: 2003/07/09 04:58:08 $ +;=========================================================== +; +; Format of this file: +; +; The file begins with the name of locale preceded with "@"-sign. This name will be +; visible for user in Tuner Locale settings. +; Channels are presented as frequency <-> name pairs. +; The Frequency is in Hz and name begins just after the first space character +; after frequency number. The name ends at the end of line. +; +; All lines beginning with ";"-sign are comments and will be ignored. +; +@xUSSR Cable +111250000 70 +119250000 71 +127250000 72 +135250000 73 +143250000 74 +141250000 75 +159250000 76 +167250000 77 +231250000 78 +239250000 79 +247250000 80 +255250000 81 +263250000 82 +271250000 83 +279250000 84 +287250000 85 +295250000 86 +303250000 87 +311250000 88 +319250000 89 +327250000 90 +335250000 91 +343250000 92 +351250000 93 +359250000 94 +367250000 95 +375250000 96 +383250000 97 +391250000 98 +399250000 99 +407250000 100 +415250000 101 +423250000 102 +431250000 103 +439250000 104 +447250000 105 +455250000 106 +463250000 107 diff --git a/headers/private/audio/R3MediaDefs.h b/headers/private/audio/R3MediaDefs.h new file mode 100644 index 0000000000..b290db6649 --- /dev/null +++ b/headers/private/audio/R3MediaDefs.h @@ -0,0 +1,86 @@ +/****************************************************************************** + + File: MediaDefs.h + + Copyright 1995-1999, Be Incorporated + This file may be used under the terms of the Be Sample Code License. + +******************************************************************************/ +#ifndef _R3_MEDIA_DEFS_H +#define _R3_MEDIA_DEFS_H + +#include +#include +#if defined(__cplusplus) +# include +#else + /* values for byte_ordering */ + enum { B_BIG_ENDIAN, B_LITTLE_ENDIAN }; + + /* values for sample_format */ + enum { + B_UNDEFINED_SAMPLES, + B_LINEAR_SAMPLES, + B_FLOAT_SAMPLES, + B_MULAW_SAMPLES + }; +#endif + +/* Buffer header for audio server */ + +typedef struct audio_buffer_header { + int32 buffer_number; + int32 subscriber_count; + bigtime_t time; + int32 reserved_1; + int32 reserved_2; + bigtime_t sample_clock; +} audio_buffer_header; + + +#define B_MEDIA_LEVEL B_REAL_TIME_PRIORITY + +#define B_NO_CHANGE (-1) + +/* ================ + Subscriber IDs and special values + ================ */ + +#define B_NO_SUBSCRIBER_ID ((subscriber_id)-1) +#define B_NO_SUBSCRIBER_NAME "not subscribed" + +#define B_SHARED_SUBSCRIBER_ID ((subscriber_id)-2) +#define B_SHARED_SUBSCRIBER_NAME "shared subscriber" + +/* ================ + Values for sound files and audio streams + ================ */ + + +/* Audio device codes for BAudioSubscriber's + * Get/SetVolume() and EnableDevice() calls + */ +enum { + B_CD_THROUGH = 0, + B_LINE_IN_THROUGH, + B_ADC_IN, + B_LOOPBACK, + B_DAC_OUT, + B_MASTER_OUT, + B_SPEAKER_OUT, + B_SOUND_DEVICE_END +}; + +/* ADC input codes */ +enum { + B_CD_IN, + B_LINE_IN, + B_MIC_IN +}; + +enum { + B_DAC_STREAM = 2354, + B_ADC_STREAM +}; + +#endif /* #ifndef _R3_MEDIA_DEFS_H */ diff --git a/headers/private/usb_vision/nt100x.h b/headers/private/usb_vision/nt100x.h new file mode 100644 index 0000000000..be75c7f905 --- /dev/null +++ b/headers/private/usb_vision/nt100x.h @@ -0,0 +1,115 @@ +/* + * This file is a part of BeOS USBVision driver project. + * Copyright (c) 2003 by Siarzuk Zharski + * + * This file may be used under the terms of the BSD License + * Look into the file "License" for details. + * + * Skeletal part of this code was inherired from original BeOS sample code, + * that is distributed under the terms of the Be Sample Code License. + * Look into the file "Be License" for details. + * + * $Source: /cvsroot/sis4be/usbvision/include/nt100x.h,v $ + * $Author: zharik $ + * $Revision: 1.1 $ + * $Date: 2003/07/15 18:58:05 $ + * + */ + +#ifndef _NT100X_H_ + #define _NT100X_H_ + +#define READ_CMD_PREFIX 0x33C2 +#define WRITE_CMD_PREFIX 0x3342 + +#define COMMAND_DATA_LENGTH 0x08 +typedef struct{ + uint8 reg; + uint8 data_length; + uint8 data[COMMAND_DATA_LENGTH]; +}xet_nt100x_reg; + +#define NT_IOCTL_READ_REGISTER B_DEVICE_OP_CODES_END + 1 +#define NT_IOCTL_WRITE_REGISTER B_DEVICE_OP_CODES_END + 2 + +/*General Control Registers (Power, Restart EP, USB, IO­pins, Camera Control)*/ +#define PWR_REG 0x00 /*0*/ +#define CONFIG_REG 0x01 /*1*/ +#define ADRS_REG 0x02 /*2*/ +#define ALTER_REG 0x03 /*3*/ +#define FORCE_ALTER_REG 0x04 /*4*/ +#define STATUS_REG 0x05 /*5*/ +#define IOPIN_REG 0x06 /*6*/ +#define SER_MODE 0x07 /*7*/ +#define SER_ADRS 0x08 /*8*/ +#define SER_CONT 0x09 /*9*/ +#define SER_DAT1 0x0a /*10*/ +#define SER_DAT2 0x0b /*11*/ +#define SER_DAT3 0x0c /*12*/ +#define SER_DAT4 0x0d /*13*/ + +/*EEPROM Read/Write Registers*/ +#define EE_DATA 0x0e /*14*/ +#define EE_LSBAD 0x0f /*15*/ +#define EE_CONT 0x10 /*16*/ + +/*17: 0x11*/ + +/*DRAM and Memory Buffers Setup Registers*/ +#define DRM_CONT 0x12 /*18*/ +#define DRM_PRM1 0x13 /*19*/ +#define DRM_PRM2 0x14 /*20*/ +#define DRM_PRM3 0x15 /*21*/ +#define DRM_PRM4 0x16 /*22*/ +#define DRM_PRM5 0x17 /*23*/ +#define DRM_PRM6 0x18 /*24*/ +#define DRM_PRM7 0x19 /*25*/ +#define DRM_PRM8 0x1a /*26*/ + +/*Video Setup and Control Registers*/ +#define VIN_REG1 0x1b /*27*/ +#define VIN_REG2 0x1c /*28*/ +#define LXSIZE_IN 0x1d /*29*/ +#define MXSIZE_IN 0x1e /*30*/ +#define LYSIZE_IN 0x1f /*31*/ +#define MYSIZE_IN 0x20 /*32*/ +#define LX_OFFST 0x21 /*33*/ +#define MX_OFFST 0x22 /*34*/ +#define LY_OFFST 0x23 /*35*/ +#define MY_OFFST 0x24 /*36*/ +#define FRM_RATE 0x25 /*37*/ +#define LXSIZE_O 0x26 /*38*/ +#define MXSIZE_O 0x27 /*39*/ +#define LYSIZE_O 0x28 /*40*/ +#define MYSIZE_O 0x29 /*41*/ +#define FILT_CONT 0x2a /*42*/ +#define VO_MODE 0x2b /*43*/ +#define INTRA_CYC 0x2c /*44*/ +#define STRIP_SZ 0x2d /*45*/ +#define FORCE_INTRA 0x2e /*46*/ +#define FORCE_UP 0x2f /*47*/ +#define BUF_THR 0x30 /*48*/ +#define DVI_YUV 0x31 /*49*/ +#define AUDIO_CONT 0x32 /*50*/ +#define AUD_PK_LEN 0x33 /*51*/ +#define BLK_PK_LEN 0x34 /*52*/ + +/*USB Watch­Dog Register*/ +#define WD_COUNT 0x35 /*53*/ + +/*54 0x36*/ +/*55 0x37*/ + +/*Compression Ratio Management Registers*/ +#define PCM_THR1 0x38 /*56*/ +#define PCM_THR2 0x39 /*57*/ +#define DIST_THR_I 0x3a /*58*/ +#define DIST_THR_A 0x3b /*59*/ +#define MAX_DIST_I 0x3c /*60*/ +#define MAX_DIST_A 0x3d /*61*/ +#define VID_BUF_ 0x3e /*62*/ +#define LFP_LSB 0x3f /*63*/ +#define LFP_MSB 0x40 /*64*/ +#define VID_LPF 0x41 /*65*/ + +#endif //_NT100X_H_ \ No newline at end of file diff --git a/src/add-ons/kernel/busses/Jamfile b/src/add-ons/kernel/busses/Jamfile index d5ab964aab..84f7392775 100644 --- a/src/add-ons/kernel/busses/Jamfile +++ b/src/add-ons/kernel/busses/Jamfile @@ -1,4 +1,5 @@ SubDir HAIKU_TOP src add-ons kernel busses ; SubInclude HAIKU_TOP src add-ons kernel busses ide ; +SubInclude HAIKU_TOP src add-ons kernel busses scsi ; SubInclude HAIKU_TOP src add-ons kernel busses usb ; diff --git a/src/add-ons/kernel/busses/scsi/Jamfile b/src/add-ons/kernel/busses/scsi/Jamfile new file mode 100644 index 0000000000..f9cf48f6c7 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/Jamfile @@ -0,0 +1,3 @@ +SubDir HAIKU_TOP src add-ons kernel busses scsi ; + +SubInclude HAIKU_TOP src add-ons kernel busses scsi usb ; diff --git a/src/add-ons/kernel/busses/scsi/usb/Jamfile b/src/add-ons/kernel/busses/scsi/usb/Jamfile new file mode 100644 index 0000000000..e3d6922fef --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/Jamfile @@ -0,0 +1,30 @@ +SubDir HAIKU_TOP src add-ons kernel busses scsi usb ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +KernelAddon usb : kernel busses scsi : + usb_scsi.c + tracing.c + transform_procs.c + proto_common.c + proto_bulk.c + proto_cbi.c + settings.c + fake_device.c + sg_buffer.c +; + +# BUILD_LOG_DAEMON +#App usb_scsi_logging : kernel drivers busses scsi : +# tracing.c +# tracing_daemon.c +#; + +Package haiku-usb_scsi-cvs + : + usb + : + boot home config add-ons kernel busses scsi ; + +Package haiku-usb_scsi-cvs : usb_scsi.settings.sample + : boot home config settings kernel drivers sample ; diff --git a/src/add-ons/kernel/busses/scsi/usb/ReadMe.html b/src/add-ons/kernel/busses/scsi/usb/ReadMe.html new file mode 100644 index 0000000000..9f3c3db9b8 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/ReadMe.html @@ -0,0 +1,745 @@ + + + + + USB mass storage support for BeOS + + +

USB mass storage support for + BeOS

+ +This is yet another piece of hardware support for BeOS/Dano/Zeta operating systems. +This USB Storage Module (The Module) is designed to support a wide variety +of standard USB mass storage devices. Those devices are: +
    +
  • memory (flash) keys,
  • +
  • external HDD/CD/DVD/ZIP/Floppy drives with USB connection,
  • +
  • digital cameras/camcorders with USBMS protocol,
  • +
  • MP3 players,
  • +
  • card readers,
  • +
  • Jukeboxes
  • +
  • etc.
  • +
+

In other (more special and technical) words this Module +works with standard USB class 8 devices, both Bulk-Only and CB[I] ones, +with all standard command sets used in such devices. +

+

Table of Contents

+ + +

1. Installation and using

+

(!!!) FIRST EMERGENCY TIP: If your system +crashes with this Module - reboot and press "Space" +during load. In boot menu select "Disable user add-ons" and continue +booting. Uninstall and reboot again into normal mode. Please, inform the developer about this problem. +

+
    +
  1. Please check, that you have supported version of BeOS. Minimal system +requirement is R5 + BeOS.USB-patches. No support for "plain" R5! More +information about USB-patches you can find in +corresponding clause of this document. +Note that Dan0, all it's successors and Zeta already have compatible USB stack - no patches +are required.
  2. +
  3. Contents of distribution archive: +
        ReadMe.html      <--- file you are reading now
    +    install.sh       <--- installation script
    +    uninstall.sh     <--- uninstallation script
    +    usb              <--- The Module binary
    +    usb_scsi.sample  <--- settings file sample
    +    usb_scsi_logging <--- logging daemon
    +    usb_scsi.devices <--- definitions for "non-standard" devices
    +    usb_dev_info     <--- the tool to obtain device inforamtion
    +
  4. +
  5. Run ./install.sh to install The Module on your system. +This script do the following:
  6. +
      +
    • copies The Module binary to + /boot/home/config/add-ons/kernel/busses/scsi/usb + directory
    • +
    +
      +
    • copies settings file to + /boot/home/config/settings/kernel/drivers/usb_scsi + file
    • +
    • ask you to reboot your system or edit settings file. More +information on settings file is here. +If you doesn't reboot from script - you +have to do it manually to let The Module work with updated settings. +
    • +
    +
  7. After system rebooted, plug in your USB device into USB slot and +try to open Tracker's "Mount" menu some times. In case if all goes OK - +you'll see some additional volumes available for mounting. Mount that +one you +think is your USB mass storage and use it as usual "real" drives.
  8. +
  9. It is highly recommended to unmount your USB volume before +unplugging device from USB slot. Some pending read/write operations can +be still active in background. If you break this process - +YOU CAN LOOSE YOUR DATA. Unmount +it and wait until your USB volume icon is +disappeared from desktop and led on your device ( in case this led +exists, of course ) turns off. To be sure you can run "sync" command from the Terminal.
  10. +
  11. [optional] To uninstall The Module from your system - run uninstall.sh +from distribution archive or delete files mentioned in +clause 3 of this section manually.
  12. +
+Table +of Contents +

2. Troubleshooting

+
    +
  1. Is my USB device supported? +
      +
    • May be. Install this software, plug your device in and +try to mount it. Or look for class / subclass / protocol values +in usb device description and check against the following lists. +
        +
      • Supported class : 8
      • +
      • Supported subclasses ( command sets ) : 1, 2, 3, 4, 5, 6
      • +
      • Supported protocols: 0, 1, 80
      • +
      +Any combination of mentioned above class / subclass / protocol is supported. +
    • +
    +
  2. +
  3. I have installed this software on R5 + USB.patches but my system +goes to Kernel Debugger on very early booting stage. Help! +
      +
    • Edit settings +file and activate the following key: +
        +
      • ignore_sysinit2 true
      • +
      +
    • +
    +
  4. +
  5. I have installed this software and there are still no additional +volumes in Tracker's "Mount" menu. +
      +
    • Sometimes it is required to open "Mount" menu more than +one time to see volumes. +
    • +
    • You can try open "Mount" menu with "Shift" button pressed and +select "Rescan All Devices" menu item to help the system recognize your device. +
    • +
    • Try to Rescan SCSI in DriveSetup. +
    • +
    +
  6. +
  7. I still have no volumes to mount!!! +
      +
    • Please check the following: +
        +
      • [for R5 only. Not required for Dano/Zeta etc. ] your system +has USB patches installed;
      • +
      • the binary file /boot/home/config/add-ons/kernel/busses/scsi/usb +exists on your system; +
      • +
      • the settings file /boot/home/config/settings/kernel/drivers/usb_scsi +exists on your system;
      • +
      • check that your device uses standard protocols and should be supported by +this module ( see clause 1 of this section ) +
      • +
      • Despite of fact that latest versions of Zeta OS use this module, some of +pre-releases of this OS have completely different stuff to support USB storage devices. +In some circumstances those Zeta's modules can prevent this USB Support Module from correct working. +In this situation you have to disable Zeta's USB Storage support. To do this go to +/boot/beos/system/add-ons/kernel/busses/scsi/ diectory and rename or remove the +usb and usb_scsi files. After rebooting your system +you should have updated USB Storage support. +
      • +
      +
    • +
    +
  8. +
  9. STILL NOTHING TO MOUNT ! ! ! + +
  10. +
  11. I see a lot of empty SCSI devices in DriveSetup and SCSIProbe. +What is it? +
      +
    • Those "disks" are just reserved device entries - some kind of +placeholders for real devices you'll attach to your computer. Read +about this technique here. +
    • +
    +
  12. +
  13. DriveSetup hangs on exit!?! +
      +
    • It is known bug. I don't know who is wrong with it. No +solution at this time. Just kill this zombie. +
    • +
    +
  14. +
  15. I have found a bug! I have unmounted my USB floppy, unplug it +than plug in another device but still see the "floppy" volume in the mount +list. +
      +
    • The mounting in BeOS is broken. Just press "Shift" key before +opening Tracker's "Mount" menu than select "Rescan Devices" +After some seconds try to mount your device again. Should work now. +
    • +
    +
  16. +
  17. I have set reserve_devices to maximal value but still no reserved device +entries in DriveSetup. +
      +
    • Known bug. In some situations reservation doesn't work. +It's reproducible with Adaptec SCSI controllers installed on your +system. You have to use DriveSetup for first mounting of device in this +situation. Nothing is perfect in this World. +
    • +
    +
  18. +
  19. Does my Canon PowerShot A70 digital camera supported by this software? +
      +
    • No. It uses Picture Transfer Protocol (PTP) instead of USB Mass Storage (USBMS) +one. You can check your camera information for Interface class. For USBMS it should +be 8, for PTP - 6. +
    • +
    +
  20. +
  21. Help me! No more than 2 devices visible by module at the same time. + +
  22. +
  23. My 9-in-1 card reader works only with media in first 4 slots! No +reaction on media in 5th - 9th slots! Is it a trial version of a driver? Where can I buy full version? + +
  24. +
  25. "Mount" menu hangs for a time +
      +
    • System requires some time to ask all available volumes for media +availability, filesystem data format etc. This check is performed any time you opening "Mount" +menu. In case you have many devices reserved in your configuration - you can be in such +trouble. Read about device entries +reservation and optimize your settings to more reasonable values. +
    • +
    +
  26. +
  27. I see the Generic OS Error message any time I want to mount my device. +

    In most of such situations your hardware is OK. The problem is that standard filesystem + addon doesn't recognize the filesystem on volume as correct. Unfortunatley BeOS is + "to close to standard" to be compatible with all bugs of Windows. Do not + forget to backup your data before trying to solve this problem!

    +

    First of all try to reformat your media.

    +

    If formatting doesn't help or doesn't work with your hardware - open DriveSetup + and [re]create partition on your device. Rescan SCSI bus if required. + Note that you have to make your partition a bit smaller as physical + size of your device. Try to initialize and reformat your media with new size.

    +
  28. +
  29. Your software sucks!!! + +
  30. +
+Table of Contents +

3. Writing a problem report

+Either something goes wrong with this software or nothing goes right +you have to write a bug report about it. +
    +
  1. Obtain your USB device information and +save it in safe place
  2. +
  3. now investigate device information for interface class. If it is +not equal to 8 go to step 12
  4. +
  5. open your settings file +( /boot/home/config/settings/kernel/drivers/usb_scsi +) in editor you prefer to use
  6. +
  7. activate following keys if they are still not activated
  8. +
        debug_output true
    +    debug_output_in_file true
    +    debug_output_file_rewrite true
    +    debug_trace_protocol true
    +    debug_trace_sense_data true
    +
  9. save your changes and close your editor
  10. +
  11. reboot your system keeping your devices switched off from your computer
  12. +
  13. after reboot run usb_scsi_logging application from distribution pack
  14. +
  15. plug your device in free USB slot
  16. +
  17. try to mount it again.
  18. +
  19. unplug your device from computer
  20. +
  21. copy the /var/log/usb_scsi.log file into same place as in step 1.
  22. +
  23. Get the information, obtained on step 1 and step 12 and let +developer know about your problem
  24. +
+Table of Contents +

4. Technical notes

+

4.1. BeOS USB patches

+To work with this software on +original BeOS R5 Pro/PE versions and it's successors your system need +to be improved to newer version of USB. This version is available +on well-known BeOS file-sharing network as BeOS.USB-patches.zip. Get it, unpack and +install it as required in corresponding readme. Note that, there +are 3 patches in this archive: +
    +
  1. beos-usb-patch
  2. +
  3. beos-usb.modem-patch
  4. +
  5. beos-usb.modem-patch.sm
  6. +
+

At least first one should be installed on your system to make using of +The USB Support Module possible. Note that Dan0, all it's successors and Zeta don't +require this patches.

+Table of Contents +

4.2. USB Device information

+

4.2.1. How to obtain +USB device information for your hardware

+There is an usb_dev_info tool inside of distribution +archive. It can +be used to obtain this information. Someone prefers USBCommander. +
    +
  1. Unplug all USB devices and hubs from your PC.
  2. +
  3. Go into Terminal and run the following command: ls -alR /dev/bus/usb + You should see something like this: +
        $ ls -alR /dev/bus/usb/
    +    /dev/bus/usb:
    +    total 0
    +    drw-r--r--   1 walther  users           0 May 31 23:16 .
    +    drw-r--r--   1 walther  users           0 Jun  1  2003 ..
    +    drw-r--r--   1 walther  users           0 May 31 23:16 0
    +    drw-r--r--   1 walther  users           0 May 31 23:16 1
    +    crw-r--r--   1 walther  users      0,   0 May 31 23:16 unload
    +    
    +    /dev/bus/usb/0:
    +    total 0
    +    drw-r--r--   1 walther  users           0 May 31 23:16 .
    +    drw-r--r--   1 walther  users           0 May 31 23:16 ..
    +    crw-r--r--   1 walther  users      0,   0 May 31 23:16 hub
    +    
    +    /dev/bus/usb/1:
    +    total 0
    +    drw-r--r--   1 walther  users           0 May 31 23:16 .
    +    drw-r--r--   1 walther  users           0 May 31 23:16 ..
    +    crw-r--r--   1 walther  users      0,   0 May 31 23:16 hub
    +
  4. +
  5. Note this information.
  6. +
  7. Now plug your USB device into PC and run ls -alR /dev/bus/usb/ again. +You'll get something slightly different: +
        $ ls -alR /dev/bus/usb/
    +    /dev/bus/usb:
    +    total 0
    +    drw-r--r--   1 walther  users           0 May 31 23:16 .
    +    drw-r--r--   1 walther  users           0 Jun  1  2003 ..
    +    drw-r--r--   1 walther  users           0 May 31 23:16 0
    +    drw-r--r--   1 walther  users           0 May 31 23:16 1
    +    crw-r--r--   1 walther  users      0,   0 May 31 23:16 unload
    +    
    +    /dev/bus/usb/0:
    +    total 0
    +    drw-r--r--   1 walther  users           0 May 31 23:16 .
    +    drw-r--r--   1 walther  users           0 May 31 23:16 ..
    +    crw-r--r--   1 walther  users      0,   0 May 31 23:17 1
    +    crw-r--r--   1 walther  users      0,   0 May 31 23:16 hub
    +    
    +    /dev/bus/usb/1:
    +    total 0
    +    drw-r--r--   1 walther  users           0 May 31 23:16 .
    +    drw-r--r--   1 walther  users           0 May 31 23:16 ..
    +    crw-r--r--   1 walther  users      0,   0 May 31 23:16 hub
    +
  8. +
  9. Compare this results with previous one and look for file, +that appeared (is selected for our sample case). This file is your +"unknown" USB device (in our sample it is /dev/bus/usb/0/1).
  10. +
  11. Now you can run usb_dev_info tool to obtain device information: +
    $ usb_dev_info /dev/bus/usb/0/1
    +
  12. +
+Table of Contents +

4.2.2. How USB device information +looks like and what does it mean

+

After performing tasks, described in previous clause you'll +receive something like the following. Note that some details can be +different for your hardware +

    $ usb_dev_info /dev/bus/usb/0/1
+    [Device]
+    Class .................. 0
+    Subclass ............... 0
+    Protocol ............... 0
+    Vendor ID .............. 0x08ec   <---------- Vendor ID of your hardware manufacturer
+    Product ID ............. 0x0011   <---------- unique Product ID of your hardware
+    Version ................ 0x0200
+    Manufacturer String .... "      "
+    Product String ......... "      "
+    Serial Number .......... "      "
+      [Configuration 0]               <---------- begin of configuration description 
+        [Interface 0]                 <---------- begin of interface description
+        Class .............. 8        <---------- this interface class. 
+        Subclass ........... 6        <---------- this interface subclass
+        Protocol ........... 80       <---------- protocol used by this interface
+          [Endpoint 0]
+          MaxPacketSize .... 64
+          Interval ......... 0
+          Type ............. Bulk
+          Direction ........ Input
+          [Endpoint 1]
+          MaxPacketSize .... 64
+          Interval ......... 0
+          Type ............. Bulk
+          Direction ........ Output
+ + +Table of Contents +

4.3. Device entries +reservation technique

+

Some tricks are required to implement simple and natural ( "one-click" +) volumes mounting in Tracker. Current versions of BeOS don't fully conform to +SCSI Common Access Model specifications. Particularly that is mean, +that there are no possibility to tell system about mass storage devices, +attached after system boot. If you already used usb mass storage driver +from Dano you should know this problem - you have to go to DriveSetup +than Rescan SCSI bus and only after this mount your volume from DriveSetup.

+

This Module introduces a workaround for such problem - it just let system to +know, that "device is here, but not ready at the moment, keep trying". This allows +to simulate some kind of plug and play in mounting from Tracker. You +can see those reserved device entries in DriveSetup -a lot of SCSI +"drives" without media and with ZIP cartridge icon left of it. This +reservation can be +configured in settings file.

+Table of Contents +

4.4. A couple +of words about usb_scsi settings file

+

You can configure some aspects of this software behavior through +editing it's settings file. This file is placed by installation script into +/boot/home/config/settings/kernel/drivers/ directory +and has the name +usb_scsi. It is usual text file and can be edited by +any text editor you like. Note that improper using of this settings +file can crash your system - please be accurate.

+

Typically the parameters in settings file +can be inactive (commented ) or active. For example the following +quote from settings file contains two parameters: first one +( reserve_devices ) is inactive ( commented by '#'-sign at the begin of +line ) and second one ( reserve_luns ) is active and set to 4: +

#reserve_devices 2 <----------------- inactive
+reserve_luns    4 <----------------- active
+Please use this notation during editing of settings file.

+

4.4.1 The Module configuration parameters

+This set of parameters is loaded by Module during +system boot and is used on permanent basis. To apply changes, made by you in any of +this parameter you have to restart your system +
    +
  • reserve_devices +
      +
    • Amount of device entries to be reserved by The Module. +If you plan to use more than 2 devices simultaneously than increase this +parameter. Note that if you set this parameter to 0 - device entry +reservation will be "switched off" and you have to use DriveSetup for +first mounting.
    • +
    • default value: 2
    • +
    • maximal value: 7
    • +
    +
  • +
  • reserve_luns +
      +
    • Amount of logical unit numbers (LUN) to be reserved by The Module for every + device entry defined in reserve_devices parameter. If you plan to use devices + with more than 4 LUNs than increase this parameter.
    • +
    • default value: 4
    • +
    • maximal value: 8
    • +
    +
  • +
  • ignore_sysinit2
  • +
      +
    • If you have R5 with USB patches and your system goes in kernel debugger on +booting with this software - this parameter is for you. Set it to true +and reboot to avoid such crashing behavior.
    • +
    • default value: false
    • +
    +
+Table of Contents +

4.4.2. Parameters for debugging mode

+
    +
  • debug_output +
  • +
      +
    • This parameter activates / deactivates debug output.
    • +
    • default value: false
    • +
    +
  • debug_output_in_file
  • +
      +
    • This parameter handles redirection of tracing information to +private log file (/var/log/usb_scsi.log). If this +parameter is false - all debuging information goes to system log. +
    • +
    • default value: false
    • +
    +
  • debug_output_file_rewrite
  • +
      +
    • Forces private log file to be truncated on every system restart
    • +
    • default value: false
    • +
    +
  • debug_trace_commands
  • +
      +
    • Activate this to dump SCSI commands to debug output
    • +
    • default value: false
    • +
    +
  • debug_trace_protocol
  • +
      +
    • Activate this to see mass storage protocols work information in debug output
    • +
    • default value: false
    • +
    +
  • debug_trace_data_io
  • +
  • debug_trace_sense_data
  • +
  • debug_trace_bulk_callback
  • +
  • debug_trace_time
  • +
  • debug_trace_threadid
  • +
  • debug_trace_thread_name
  • +
  • debug_trace_capacity
  • +
      +
    • Mean this stuff as undocumented because it is rarely used.
    • +
    • default values: false
    • +
    +
+Table of Contents +

4.4.3 Configuring device definitions

+

Device definition allows to override your hardware parameters and tweak +it's functionality. This parameters are device-specific and reloaded on +physical device attach. You not need to reboot your system to apply +your changes in device descriptions. All you need to use changed device +definitions - unplug your USB hardware from computer and plug it in +again.

+

Typical "non-standard" devices definition looks like this: +

vendor <<vendor id>> {
+  device <<product id 1>> {
+    <<parameter 1>> 
+    <<parameter 2>>
+         ...
+    <<parameter N>>
+  }
+    ....
+  device <<product id N>> {
+    <<parameter 1>> 
+    <<parameter 2>>
+         ...
+    <<parameter N>>
+  }
+}
+

+

The real vendor ID and product ID for your hardware you can obtain from +USB Device information. Note that you can define many devices inside of +single vendor definition. More real samples of device overrides you can +find in usb_scsi.devices file inside of +distribution archive. Just copy the content of corresponding device +description into settings file and re-plug your hardware.

+Table of Contents +

4.4.3.1.Tweaking device definition

+Every parameter of device definition is like switch. It affects on Module behavior +only if exists in device definition and is not commented out. +
    +
  • fake_inquiry
  • +
      +
    • do not send INQUIRY SCSI command to USB device but handle it in Module.
    • +
    +
  • use_6byte_cmd
  • +
      +
    • use 6 byte length SCSI READ/WRITE/MODE SENSE/SELECT SENSE +commands instead of 10 byte ones. Typically BeOS uses 6-byte commands +but many USB mass storage devices doesn't like this. To avoid massive +device +redefinitions this Module automatically translates such commands to +10-byte counterparts. If this default translation doesn't work for you +- set use_6byte_cmd to avoid it.
    • +
    +
  • trans_test_unit
  • +
      +
    • translate TEST UNIT SCSI command to START STOP one.
    • +
    +
  • no_test_unit
  • +
      +
    • do not send TEST UNIT SCSI command to device. At all.
    • +
    +
  • no_get_max_lun
  • +
      +
    • do not ask for maximal number of supported Logical Unit Numbers
    • +
    +
  • no_prevent_media
  • +
      +
    • do not send to device PREVENT ALLOW MEDIA REMOVAL SCSI command.
    • +
    +
  • use_mode_sense_10
  • +
      +
    • force module to use 10-byte MODE SENSE command. Typically this +Module detects automatically the supported MODE SENSE command and you +don't need to set it manually.
    • +
    +
  • force_read_only
  • +
      +
    • force drive to be read-only. It is not 100% guaranteed - but in +many cases works. If you need "true" read-only volumes - than mount it +with corresponding flags from command line.
    • +
    +
+

4.4.3.2. +Overriding device protocol

+There are two special parameters allow to override protocol and +command set used to communicate with device +
    +
  • commandset
  • +
      +
    • forces The Module to use specific command set when +communicating with device. The following command sets are supported
    • +
    +
      +
        +
      • SCSI - transparent SCSI command set. USB subclass 6
      • +
      • UFI - USB subclass 4
      • +
      • ATAPI - USB subclasses 5,2
      • +
      • RBC - USB subclass 1
      • +
      • QIC157 - USB subclass 3. Used for tape drives so, probably is +not be anytime usable... but supported. =-)
      • +
      • <Vendor> - any vendor-specific, non-standard commands +set. Note that to work with it a corresponding protocol extension module is +required.
      • +
      +
    +
  • protocol
  • +
      +
    • forces The Module to use specific protocol when +communicating with device. The following protocols are supported
    • +
        +
      • BULK - bulk-only. USB protocol 80
      • +
      • CB - Control/Bulk/Interrupt protocol (with command +completion interrupt). USB protocol 1
      • +
      • CBI - Control/Bulk/Interrupt protocol (with no command +completion interrupt) USB protocol 0
      • +
      • <Vendor> - any vendor-specific, non-standard protocol. +Note that to work with it a corresponding protocol extension module is +required.
      • +
      +
    +
+Table of Contents +

4.5. Protocol extension modules

+

The BeOS USB Support Module was designed with extensibility in mind. It means, that you +can add support of vendor-specific, non-standard protocols/commandsets without +changing the main Module. All you need is protocol extention module, that implements all +specifics of the data and commands flow.

+

Currently available modules:

+
    +
  • freecom - FREECOM USB-IDE Bridge (ATAPI devices only).
  • +
+

To install protocol extention module obtain it's distribution archive +and read instructions inside of it.

+

For development questions refer to of already existing protocol extention modules +or the Author of UBS Support Module.

+ +Table of Contents +

4.Contact and support information

+The BeOS USB Support Module project is hosted on SourceForge +and uses some it's powerful development services. There are some ways to inform +developer about problems or put feature requests for next version +
    +
  1. Use Bug +Tracker to put problem reports.
  2. +
  3. Use Forum +to ask simple support question, discuss any problems. +Do not put your problem reports here - use Bug +Tracker!
  4. +
  5. Use Mailing-list +to be informed with latest news, ask questions +etc. This is also not right place for your problem reports - use Bug +Tracker instead.
  6. +
  7. If you want to share any ideas, that can be good to implement in +future versions - use Feature +Request Submit form.
  8. +
  9. If you doesn't like any way, mentioned above you can +contact me personally by e-mail but +remember, that I don't like this +way!(Joke!) =-) In my opinion such Community Knowledges like +Forums and mail-lists must be public and available for everyone.
  10. +
+Table of Contents +

5.Credits

+

I want to say my "Thanks" to:

+

... Sergei Dolgov ("fyysik") for pushing me to develop this software +and help in testing,

+

... Valery Rybin for testing a really lot of those USB +gadgets he has at his hands,

+

... them who have spend some time to trying all those "-dev-" +versions in work.

+Table of Contents +

6. The History

+

+ + + + + + + + + + + + +
Date: Version: What's new:
06 June 20040.1.0-alpha-1 first public release.
+

+Table +of Contents +
< End of document >
+ + diff --git a/src/add-ons/kernel/busses/scsi/usb/TODO b/src/add-ons/kernel/busses/scsi/usb/TODO new file mode 100644 index 0000000000..0e935a350a --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/TODO @@ -0,0 +1,68 @@ +# +# This file is a part of BeOS USB SCSI interface module project. +# Copyright (c) 2003-2004 by Siarzhuk Zharski +# +# This file may be used under the terms of the BSD License +# See the file "License" for details. +# +#1) Correct handling of FORMAT_UNIT command +#2) Correct handling of SCSI return codes +#3) Locking of trace file should be not so "hard" +4)(????)Correct locking of driver entry in xpt_scsi_io +#5) Use USB stack 2.0 ? +6)(???) Hang problem with DriveSetup #reproduced on clean system without SCSI... +#7) Support of CBI protocol +#8) Support of FREECOM protocol +#9) Support of read-only forcing (fyysik asks) +#10) Make reservation of devices more flexible (can switch it off). +#11) Transfer should be build on callback ideology +#12) Timeouts should be more adequate +13) Review RBC transform against specs +14) Review QIC-157 transform against specs +#15) Make HBA SCSI ID configurable +#16) Think on possibility to use "one.dev <-> one.path" scheme +#17) Set cam_scsi_status correctly on return! +#18) Support of autosense on fake devices +#-INVALID-19)Locking for fake devices too +#20) What with write-protected devices? +#21) Some kind of investigation - try to return CHECK_CONDITION in case of zero autosense_len - will system resend this command with non-zero autosense len? +#22) mode sense data for 10-byte translated command. Wait for test results. Probably will be not required at all. +#23) implement protocols as modules +#24) Some kind of automatic detection if 6-byte READ/WRITE and MODE SELECT/SENSE commands supported. +#25) Do not let MODE_SENSE go to NOT READY LUNs. It can "kill" the hardware +#26) Replace the write/read to fwrite/fread in tracing daemon (fyysik's request) +27)(???) Looks like system ignores our CHECK_CONDITION (for example on handling 1e, 1b, 2a). Is it our problem? +#-INVALID-28) Clean-up the data buffer before MODE_SENSE request .... +#29) Problem with synchronize cache command (see BePage's log) +#30) Try to workaround R5+patches=KDL problem. Ignore calls from 'sysinit2'? +31) Work with NewFS Tracker and it's derivatives. There are lot of problems with that mad software. +#32) deactivate automatic READ(10)->READ(6) switching. Looks like it's makes more problems than solves. +#33) Are we really need private protocol buffer ? Try to remove this and use stack allocated objects. +#34) Tracing in protocols implementations should be more generic ... +#35) overwrite tracing ... +36) Handle FORMAT_UNIT for UFI devices. +#37) Locking of global devices table +#38) Locking of device_removed - avoid removing during handling xpt_scsi_io +39) Device mounted than unplugged.It stay mounted but doesn't work and get the garbage in "opened" files. Are there solutions? +#40) open log file in /var/log/ instead of home directory +#41) More correct work with MODE_SENSE/MODE_SELECT convertions ... +#42) debug output settings should be used in protocol extensions too ... +#-INVALID!-43) What with sense data? should it be reorganized as MODE_SENSE/MODE_SELECT one? +44) Fix possible problem with READ_CAPACITY command. Some cameras produce "Generic OS Error" during mounting. +#45) Some Minolta cameras have nulified semaphore after creation. :-( ) +#46) Add "invalid" devices entries. Check your mailing for information. +#-DUPLICATE-47) A word about disabling Zeta's modules in manual. +#48) Handle all TODOs in ReadMe.html before releasing RC-1. +#49) Handling 0xA1 (Blank) command for C/DVD-RW devices. Should be like FORMAT UNIT? +#-CDBurner's problem-50) Problems with 35h SYNCHRONIZE_CACHE command with CDBurner on FREECOM module. +#-Problems in current BeOS USB stack- 51) Support for DATAFAB extention +#-INVALID-52)Some kind of reset required for FREECOM. Test it until this MODE_SELECT is not working! +#51) problem with SCSIProbe +#52) Support for Siemens MP3 Player +#53) Stess tests for floppy +54) Handling of transfer timeout should be refactored. +55) Tracing Mode_sense/mode_select data for all case if configured - not only for converting! +#56) Are there problems with simultaneous tracing to log file and system log? Check! +57) Write a ReadMe.html for FREECOM module and make distribution support for it. +#58) Add tracing for READ_CAPACITY results +59) Check again MODE_SENSE/MODE_SELECT pages translations... MYOB has some problems... diff --git a/src/add-ons/kernel/busses/scsi/usb/USB_v3.h b/src/add-ons/kernel/busses/scsi/usb/USB_v3.h new file mode 100644 index 0000000000..79c791d6d9 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/USB_v3.h @@ -0,0 +1,194 @@ +/* +** USB.h - Version 3 USB Device Driver API +** +** Copyright 1999, Be Incorporated. All Rights Reserved. +** +*/ + +#ifndef _USB_V3_H +#define _USB_V3_H + +#include +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct usb_module_info usb_module_info; + +/* these are opaque handles to internal stack objects */ +typedef uint32 usb_id; +typedef usb_id usb_device; +typedef usb_id usb_interface; +typedef usb_id usb_pipe; + +typedef struct usb_endpoint_info usb_endpoint_info; +typedef struct usb_interface_info usb_interface_info; +typedef struct usb_interface_list usb_interface_list; +typedef struct usb_configuration_info usb_configuration_info; + +typedef struct usb_notify_hooks { + status_t (*device_added)(usb_device device, void **cookie); + status_t (*device_removed)(void *cookie); +} usb_notify_hooks; + +typedef struct usb_support_descriptor { + uint8 dev_class; + uint8 dev_subclass; + uint8 dev_protocol; + uint16 vendor; + uint16 product; +} usb_support_descriptor; + +/* ie, I support any hub device: +** usb_support_descriptor hub_devs = { 9, 0, 0, 0, 0 }; +*/ + +struct usb_endpoint_info { + usb_endpoint_descriptor *descr; /* descriptor and handle */ + usb_pipe handle; /* of this endpoint/pipe */ +}; + +struct usb_interface_info { + usb_interface_descriptor *descr; /* descriptor and handle */ + usb_interface handle; /* of this interface */ + + size_t endpoint_count; /* count and list of endpoints */ + usb_endpoint_info *endpoint; /* in this interface */ + + size_t generic_count; /* unparsed descriptors in this */ + usb_descriptor **generic; /* interface */ +}; + +struct usb_interface_list { + size_t alt_count; /* count and list of alternate */ + usb_interface_info *alt; /* interfaces available */ + + usb_interface_info *active; /* currently active alternate */ +}; + +struct usb_configuration_info { + usb_configuration_descriptor *descr; /* descriptor of this config */ + + size_t interface_count; /* interfaces in this config */ + usb_interface_list *interface; +}; + + +typedef void (*usb_callback_func)(void *cookie, uint32 status, + void *data, uint32 actual_len); + +struct usb_module_info { + bus_manager_info binfo; + + /* inform the bus manager of our intent to support a set of devices */ + status_t (*register_driver)(const char *driver_name, + const usb_support_descriptor *descriptors, + size_t count, + const char *optional_republish_driver_name); + + /* request notification from the bus manager for add/remove of devices we + support */ + status_t (*install_notify)(const char *driver_name, + const usb_notify_hooks *hooks); + status_t (*uninstall_notify)(const char *driver_name); + + /* get the device descriptor */ + const usb_device_descriptor *(*get_device_descriptor)(usb_device device); + + /* get the nth supported configuration */ + const usb_configuration_info *(*get_nth_configuration)(usb_device device, uint index); + + /* get the active configuration */ + const usb_configuration_info *(*get_configuration)(usb_device device); + + /* set the active configuration */ + status_t (*set_configuration)(usb_device device, + const usb_configuration_info *configuration); + + status_t (*set_alt_interface)(usb_device device, + const usb_interface_info *ifc); + + /* standard device requests -- convenience functions */ + /* handle may be a usb_device, usb_pipe, or usb_interface */ + status_t (*set_feature)(usb_id handle, uint16 selector); + status_t (*clear_feature)(usb_id handle, uint16 selector); + status_t (*get_status)(usb_id handle, uint16 *status); + + status_t (*get_descriptor)(usb_device device, + uint8 type, uint8 index, uint16 lang, + void *data, size_t len, size_t *actual_len); + + /* generic device request function */ + status_t (*send_request)(usb_device device, + uint8 request_type, uint8 request, + uint16 value, uint16 index, uint16 length, + void *data, size_t *actual_len); + + /* async request queueing */ + status_t (*queue_interrupt)(usb_pipe pipe, + void *data, size_t len, + usb_callback_func notify, void *cookie); + + status_t (*queue_bulk)(usb_pipe pipe, + void *data, size_t len, + usb_callback_func notify, void *cookie); + + status_t (*queue_bulk_v)(usb_pipe pipe, + iovec *vec, size_t count, + usb_callback_func notify, void *cookie); + + status_t (*queue_isochronous)(usb_pipe pipe, + void *data, size_t len, + rlea* rle_array, uint16 buffer_duration_ms, + usb_callback_func notify, void *cookie); + + status_t (*queue_request)(usb_device device, + uint8 request_type, uint8 request, + uint16 value, uint16 index, uint16 length, + void *data, usb_callback_func notify, void *cookie); + + status_t (*set_pipe_policy)(usb_pipe pipe, uint8 max_num_queued_packets, + uint16 max_buffer_duration_ms, uint16 sample_size); + + /* cancel pending async requests to an endpoint */ + status_t (*cancel_queued_transfers)(usb_pipe pipe); + + /* tuning, timeouts, etc */ + status_t (*usb_ioctl)(uint32 opcode, void* buf, size_t buf_size); +}; + +/* status code for usb callback functions */ +/*#define B_USB_STATUS_SUCCESS 0x0000 +#define B_USB_STATUS_DEVICE_CRC_ERROR 0x0002 +#define B_USB_STATUS_DEVICE_TIMEOUT 0x0004 +#define B_USB_STATUS_DEVICE_STALLED 0x0008 +#define B_USB_STATUS_IRP_CANCELLED_BY_REQUEST 0x0010 +#define B_USB_STATUS_DRIVER_INTERNAL_ERROR 0x0020 +#define B_USB_STATUS_ADAPTER_HARDWARE_ERROR 0x0040 +#define B_USB_STATUS_ISOCH_IRP_ABORTED 0x0080 +*/ +/* result codes for usb bus manager functions */ +/*#define B_USBD_SUCCESS 0 +#define B_USBD_BAD_HANDLE 1 +#define B_USBD_BAD_ARGS 2 +#define B_USBD_NO_DATA 3 +#define B_USBD_DEVICE_FAILURE 4 +#define B_USBD_COMMAND_FAILED 5 +#define B_USBD_PIPE_NOT_CONFIGURED 6 +#define B_USBD_DEVICE_ERROR 7 +#define B_USBD_PIPE_ERROR 8 +#define B_USBD_NO_MEMORY 9 +*/ +#define B_USB_MODULE_NAME "bus_managers/usb/v3" + +#ifdef __cplusplus +} +#endif + +#endif // _USB_V3_H diff --git a/src/add-ons/kernel/busses/scsi/usb/datafab/COPYING b/src/add-ons/kernel/busses/scsi/usb/datafab/COPYING new file mode 100644 index 0000000000..60549be514 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/datafab/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/src/add-ons/kernel/busses/scsi/usb/datafab/datafab.c b/src/add-ons/kernel/busses/scsi/usb/datafab/datafab.c new file mode 100644 index 0000000000..197b591a3f --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/datafab/datafab.c @@ -0,0 +1,850 @@ +/* + * \file: datafab.c + * \brief: USB SCSI module extention for Datafab USB readers + * + * This file is a part of BeOS USB SCSI interface module project. + * Copyright (c) 2005 by Siarzhuk Zharski + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * This protocol extension module was developed using information from + * "Driver for Datafab USB Compact Flash reader" in Linux usb storage driver. + * + * $Source: /cvsroot/sis4be/usb_scsi/datafab/datafab.c,v $ + * $Author: zharik $ + * $Revision: 1.3 $ + * $Date: 2005/03/12 21:18:48 $ + * + */ +#include "usb_scsi.h" + +#include +#include "device_info.h" +#include "proto_module.h" + +#define DATAFAB_MODULE_NAME "datafab" +#define DATAFAB_PROTOCOL_MODULE_NAME \ + MODULE_PREFIX DATAFAB_MODULE_NAME PROTOCOL_SUFFIX + +typedef struct { + usb_device_info *udi; + uint8 *cmd; + uint8 cmdlen; + iovec*sg_data; + int32 sg_count; + int32 transfer_len; + EDirection dir; + CCB_SCSIIO *ccbio; + int32 residue; +} usb_scsi_transport_info; + +typedef struct{ +/* +0 M General configuration bit-significant information: + F 15 0 = ATA device + X 14-8 Retired + F 7 1 = removable media device + X 6 Obsolete + X 5-3 Retired + V 2 Response incomplete + X 1 Retired + F 0 Reserved +*/ + uint16 info; +#define NON_ATA_DEVICE 0x +#define REMOVABLE_DEVICE 0x +/* +1 X Obsolete +2 O V Specific configuration +3 X Obsolete +4-5 X Retired +6 X Obsolete +7-8 O V Reserved for assignment by the CompactFlashä Association +9 X Retired +*/ + uint16 pad1[9]; + /* +10-19 M F Serial number (20 ASCII characters) +*/ + uint16 serial[10]; +/* +20-21 X Retired +22 X Obsolete +*/ + uint16 pad2[3]; + /* +23-26 M F Firmware revision (8 ASCII characters) +*/ + uint16 firmware_rev[4]; + /* +27-46 M F Model number (40 ASCII characters) +*/ + uint16 model_num[20]; +/* +47 M F 15-8 80h + F 7-0 00h = Reserved + F 01h-FFh = Maximum number of sectors that shall be transferred per interrupt on + READ/WRITE MULTIPLE commands +*//* +48 F Reserved +*//* +49 M Capabilities + F 15-14 Reserved for the IDENTIFY PACKET DEVICE command. + F 13 1 = Standby timer values as specified in this standard are supported + 0 = Standby timer values shall be managed by the device + F 12 Reserved for the IDENTIFY PACKET DEVICE command. + F 11 1 = IORDY supported + 0 = IORDY may be supported + F 10 1 = IORDY may be disabled + F 9 1 = LBA supported + F 8 1 = DMA supported. + X 7-0 Retired +*//* +50 M Capabilities + F 15 Shall be cleared to zero. + F 14 Shall be set to one. + F 13-2 Reserved. + X 1 Obsolete + F 0 Shall be set to one to indicate a device specific Standby timer value minimum. +*//* +51-52 X Obsolete +*//* +53 M F 15-3 Reserved + F 2 1 = the fields reported in word 88 are valid + 0 = the fields reported in word 88 are not valid + F 1 1 = the fields reported in words (70:64) are valid + 0 = the fields reported in words (70:64) are not valid + X 0 Obsolete +*//* +54-58 X Obsolete +*//* +59 M F 15-9 Reserved + V 8 1 = Multiple sector setting is valid + V 7-0 xxh = Current setting for number of sectors that shall be transferred per interrupt on + R/W Multiple command +*/ + uint16 pad3[13]; +/* +60-61 M F Total number of user addressable sectors +*/ + uint32 total_secs; +/* +62 X Obsolete +*//* +63 M F 15-11 Reserved + V 10 1 = Multiword DMA mode 2 is selected + 0 = Multiword DMA mode 2 is not selected + V 9 1 = Multiword DMA mode 1 is selected + 0 = Multiword DMA mode 1 is not selected + V 8 1 = Multiword DMA mode 0 is selected + 0 = Multiword DMA mode 0 is not selected + F 7-3 Reserved + F 2 1 = Multiword DMA mode 2 and below are supported + F 1 1 = Multiword DMA mode 1 and below are supported + F 0 1 = Multiword DMA mode 0 is supported +64 M F 15-8 Reserved + F 7-0 PIO modes supported +65 M Minimum Multiword DMA transfer cycle time per word + F 15-0 Cycle time in nanoseconds +66 M Manufacturer’s recommended Multiword DMA transfer cycle time + F 15-0 Cycle time in nanoseconds +67 M Minimum PIO transfer cycle time without flow control + F 15-0 Cycle time in nanoseconds +68 M Minimum PIO transfer cycle time with IORDY flow control + F 15-0 Cycle time in nanoseconds +69-70 F Reserved (for future command overlap and queuing) +71-74 F Reserved for IDENTIFY PACKET DEVICE command. +75 O Queue depth + F 15-5 Reserved + F 4-0 Maximum queue depth – 1 +76-79 F Reserved +80 M Major version number + 0000h or FFFFh = device does not report version + F 15 Reserved + F 14 Reserved for ATA/ATAPI-14 + F 13 Reserved for ATA/ATAPI-13 + F 12 Reserved for ATA/ATAPI-12 + F 11 Reserved for ATA/ATAPI-11 + F 10 Reserved for ATA/ATAPI-10 + F 9 Reserved for ATA/ATAPI-9 + F 8 Reserved for ATA/ATAPI-8 + F 7 Reserved for ATA/ATAPI-7 + F 6 1 = supports ATA/ATAPI-6 + F 5 1 = supports ATA/ATAPI-5 + F 4 1 = supports ATA/ATAPI-4 + F 3 1 = supports ATA-3 + X 2 Obsolete + X 1 Obsolete + F 0 Reserved +81 M F Minor version number + 0000h or FFFFh = device does not report version + 0001h-FFFEh = see 8.15.41 +82 M Command set supported. + X 15 Obsolete + F 14 1 = NOP command supported + F 13 1 = READ BUFFER command supported + F 12 1 = WRITE BUFFER command supported + X 11 Obsolete + F 10 1 = Host Protected Area feature set supported + F 9 1 = DEVICE RESET command supported + F 8 1 = SERVICE interrupt supported + F 7 1 = release interrupt supported + F 6 1 = look-ahead supported + F 5 1 = write cache supported + F 4 Shall be cleared to zero to indicate that the PACKET Command feature set is not + supported. + F 3 1 = mandatory Power Management feature set supported + F 2 1 = Removable Media feature set supported + F 1 1 = Security Mode feature set supported + F 0 1 = SMART feature set supported +83 M Command sets supported. + F 15 Shall be cleared to zero + F 14 Shall be set to one + F 13 1 = FLUSH CACHE EXT command supported + F 12 1 = mandatory FLUSH CACHE command supported + F 11 1 = Device Configuration Overlay feature set supported + F 10 1 = 48-bit Address feature set supported + F 9 1 = Automatic Acoustic Management feature set supported + F 8 1 = SET MAX security extension supported + F 7 See Address Offset Reserved Area Boot, NCITS TR27:2001 + F 6 1 = SET FEATURES subcommand required to spinup after power-up + F 5 1 = Power-Up In Standby feature set supported + F 4 1 = Removable Media Status Notification feature set supported + F 3 1 = Advanced Power Management feature set supported + F 2 1 = CFA feature set supported + F 1 1 = READ/WRITE DMA QUEUED supported + F 0 1 = DOWNLOAD MICROCODE command supported +84 M Command set/feature supported extension. + F 15 Shall be cleared to zero + F 14 Shall be set to one + F 13-6 Reserved + F 5 1 = General Purpose Logging feature set supported + F 4 Reserved + F 3 1 = Media Card Pass Through Command feature set supported + F 2 1 = Media serial number supported + F 1 1 = SMART self-test supported + F 0 1 = SMART error logging supported +85 M Command set/feature enabled. + X 15 Obsolete + F 14 1 = NOP command enabled + F 13 1 = READ BUFFER command enabled + F 12 1 = WRITE BUFFER command enabled + X 11 Obsolete + V 10 1 = Host Protected Area feature set enabled + F 9 1 = DEVICE RESET command enabled + V 8 1 = SERVICE interrupt enabled + V 7 1 = release interrupt enabled + V 6 1 = look-ahead enabled + V 5 1 = write cache enabled + F 4 Shall be cleared to zero to indicate that the PACKET Command feature set is not + supported. + F 3 1 = Power Management feature set enabled + F 2 1 = Removable Media feature set enabled + V 1 1 = Security Mode feature set enabled + V 0 1 = SMART feature set enabled +86 M Command set/feature enabled. + F 15-14 Reserved + F 13 1 = FLUSH CACHE EXT command supported + F 12 1 = FLUSH CACHE command supported + F 11 1 = Device Configuration Overlay supported + F 10 1 = 48-bit Address features set supported + V 9 1 = Automatic Acoustic Management feature set enabled + F 8 1 = SET MAX security extension enabled by SET MAX SET PASSWORD + F 7 See Address Offset Reserved Area Boot, NCITS TR27:2001 + F 6 1 = SET FEATURES subcommand required to spin-up after power-up + V 5 1 = Power-Up In Standby feature set enabled + V 4 1 = Removable Media Status Notification feature set enabled + V 3 1 = Advanced Power Management feature set enabled + F 2 1 = CFA feature set enabled + F 1 1 = READ/WRITE DMA QUEUED command supported + F 0 1 = DOWNLOAD MICROCODE command supported +87 M Command set/feature default. + F 15 Shall be cleared to zero + F 14 Shall be set to one + F 13-6 Reserved + F 5 General Purpose Logging feature set supported + V 4 Reserved + V 3 1 = Media Card Pass Through Command feature set enabled + V 2 1 = Media serial number is valid + F 1 1 = SMART self-test supported + F 0 1 = SMART error logging supported +88 O F 15-14 Reserved + V 13 1 = Ultra DMA mode 5 is selected + 0 = Ultra DMA mode 5 is not selected + V 12 1 = Ultra DMA mode 4 is selected + 0 = Ultra DMA mode 4 is not selected + V 11 1 = Ultra DMA mode 3 is selected + 0 = Ultra DMA mode 3 is not selected + V 10 1 = Ultra DMA mode 2 is selected + 0 = Ultra DMA mode 2 is not selected + V 9 1 = Ultra DMA mode 1 is selected + 0 = Ultra DMA mode 1 is not selected + V 8 1 = Ultra DMA mode 0 is selected + 0 = Ultra DMA mode 0 is not selected + F 7-6 Reserved + F 5 1 = Ultra DMA mode 5 and below are supported + F 4 1 = Ultra DMA mode 4 and below are supported + F 3 1 = Ultra DMA mode 3 and below are supported + F 2 1 = Ultra DMA mode 2 and below are supported + F 1 1 = Ultra DMA mode 1 and below are supported + F 0 1 = Ultra DMA mode 0 is supported +89 O F Time required for security erase unit completion +90 O F Time required for Enhanced security erase completion +91 O V Current advanced power management value +92 O V Master Password Revision Code +93 * Hardware reset result. The contents of bits (12:0) of this word shall change only during the + execution of a hardware reset. + F 15 Shall be cleared to zero. + F 14 Shall be set to one. + V 13 1 = device detected CBLID- above ViH + 0 = device detected CBLID- below ViL + 12-8 Device 1 hardware reset result. Device 0 shall clear these bits to zero. Device 1 + shall set these bits as follows: + F 12 Reserved. + V 11 0 = Device 1 did not assert PDIAG-. + 1 = Device 1 asserted PDIAG-. + V 10-9 These bits indicate how Device 1 determined the device number: + 00 = Reserved. + 01 = a jumper was used. + 10 = the CSEL signal was used. + 11 = some other method was used or the method is unknown. + 8 Shall be set to one. + 7-0 Device 0 hardware reset result. Device 1 shall clear these bits to zero. Device 0 + shall set these bits as follows: + F 7 Reserved. + F 6 0 = Device 0 does not respond when Device 1 is selected. + 1 = Device 0 responds when Device 1 is selected. + V 5 0 = Device 0 did not detect the assertion of DASP-. + 1 = Device 0 detected the assertion of DASP-. + V 4 0 = Device 0 did not detect the assertion of PDIAG-. + 1 = Device 0 detected the assertion of PDIAG-. + V 3 0 = Device 0 failed diagnostics. + 1 = Device 0 passed diagnostics. + V 2-1 These bits indicate how Device 0 determined the device number: + 00 = Reserved. + 01 = a jumper was used. + 10 = the CSEL signal was used. + 11 = some other method was used or the method is unknown. + F 0 Shall be set to one. +94 O V 15-8 Vendor’s recommended acoustic management value. + V 7-0 Current automatic acoustic management value. +95-99 F Reserved +100-103 O V Maximum user LBA for 48-bit Address feature set. +104-126 F Reserved +127 O Removable Media Status Notification feature set support + F 15-2 Reserved + F 1-0 00 = Removable Media Status Notification feature set not supported + 01 = Removable Media Status Notification feature supported + 10 = Reserved + 11 = Reserved +128 O Security status + F 15-9 Reserved + V 8 Security level 0 = High, 1 = Maximum + F 7-6 Reserved + F 5 1 = Enhanced security erase supported + V 4 1 = Security count expired + V 3 1 = Security frozen + V 2 1 = Security locked + V 1 1 = Security enabled + F 0 1 = Security supported +129-159 X Vendor specific +160 O CFA power mode 1 + F 15 Word 160 supported + F 14 Reserved + F 13 CFA power mode 1 is required for one or more commands implemented by the + device + V 12 CFA power mode 1 disabled + F 11-0 Maximum current in ma +161-175 X Reserved for assignment by the CompactFlashä Association +176-205 O V Current media serial number +206-254 F Reserved +255 M X Integrity word + 15-8 Checksum + 7-0 Signature +*/ + uint16 pad4[24]; + uint16 pad5[25]; + uint16 pad6[25]; + uint16 pad7[20]; + uint16 pad8[25]; + uint16 pad9[25]; + uint16 padA[25]; + uint16 padB[25]; +}ATA_DEVICE_INFO; + +#define DEVICE_INFO_SIZE 512 + +typedef struct { + uint8 feature; /* R: error, W:feature */ + uint8 sector_count; /* R: IReason W: Sectors Count*/ + uint8 address[3]; /* part of address */ + uint8 addr_dev; /* part of address and device info*/ +#define ADDR_MASK 0x0F +#define DEV_MASK 0xF0 +#define DEV_ON 0xA0 +#define DEV_LBA 0x40 +#define DEV_MASTER 0x00 +#define DEV_SLAVE 0x10 + uint8 command; /* R: status W:command */ + uint8 intr_reset; /* interrupt/reset register */ +#define IR_IRQ_ENABLE 0x01 +#define IR_RESET 0x02 +}command_registers; + +typedef struct { + uint8 reg1; + uint8 reg2; +}status_registers; + +#define IDE_CMD_IDENTIFY_DEVICE 0xEC +#define IDE_CMD_READ 0x20 +#define IDE_CMD_WRITE 0x30 + +/* duplication! */ +#define INQ_VENDOR_LEN 0x08 +#define INQ_PRODUCT_LEN 0x10 +#define INQ_REVISION_LEN 0x04 + + +/* + B_DEV_INVALID_IOCTL = B_DEVICE_ERROR_BASE, + B_DEV_NO_MEMORY, + B_DEV_BAD_DRIVE_NUM, + B_DEV_NO_MEDIA, + B_DEV_UNREADABLE, + B_DEV_FORMAT_ERROR, + B_DEV_TIMEOUT, + B_DEV_RECALIBRATE_ERROR, + B_DEV_SEEK_ERROR, + B_DEV_ID_ERROR, + B_DEV_READ_ERROR, a + B_DEV_WRITE_ERROR, + B_DEV_NOT_READY, + B_DEV_MEDIA_CHANGED, + B_DEV_MEDIA_CHANGE_REQUESTED, + B_DEV_RESOURCE_CONFLICT, + B_DEV_CONFIGURATION_ERROR, 10 + B_DEV_DISABLED_BY_USER, + B_DEV_DOOR_OPEN, + + B_DEV_INVALID_PIPE, 13 + B_DEV_CRC_ERROR, + B_DEV_STALLED, 15 + B_DEV_BAD_PID, + B_DEV_UNEXPECTED_PID, + B_DEV_DATA_OVERRUN, 18 + B_DEV_DATA_UNDERRUN, + B_DEV_FIFO_OVERRUN, 1a + B_DEV_FIFO_UNDERRUN, + B_DEV_PENDING, + B_DEV_MULTIPLE_ERRORS, 1d + B_DEV_TOO_LATE +*/ + +/** + \fn:datafab_initialize + \param udi: device on wich we should perform initialization + \return:error code if initialization failed or B_OK if it passed + + initialize procedure for bulk only protocol devices. +*/ +status_t +datafab_initialize(usb_device_info *udi) +{ + status_t status = B_OK; +/*TODO*/ + return status; +} +/** + \fn:datafab_reset + \param udi: device on wich we should perform reset + \return:error code if reset failed or B_OK if it passed + + reset procedure for bulk only protocol devices. Tries to send + BulkOnlyReset USB request and clear USB_FEATURE_ENDPOINT_HALT features on + input and output pipes. ([2] 3.1) +*/ +status_t +datafab_reset(usb_device_info *udi) +{ + status_t status = B_OK; + /* not required ? */ + return status; +} + +/** + \fn:usb_callback + \param cookie:??? + \param status:??? + \param data:??? + \param actual_len:??? + \return:??? + + ??? +*/ +static void usb_callback(void *cookie, + uint32 status, + void *data, + uint32 actual_len) +{ + if(cookie){ + usb_device_info *udi = (usb_device_info *)cookie; + udi->status = status; + udi->data = data; + udi->actual_len = actual_len; + if(udi->status != B_CANCELED) + release_sem(udi->trans_sem); + } +} + +/** + \fn:queue_bulk + \param udi: device for which que_bulk request is performed + \param buffer: data buffer, used in bulk i/o operation + \param len: length of data buffer + \param b_in: is "true" if input (device->host) data transfer, "false" otherwise + \return: status of operation. + + performs queue_bulk USB request for corresponding pipe and handle timeout of this + operation. +*/ +static status_t +queue_bulk(usb_device_info *udi, + void *buffer, + size_t len, + bool b_in) +{ + status_t status = B_OK; + usb_pipe pipe = b_in ? udi->pipe_in : udi->pipe_out; + status = (*udi->usb_m->queue_bulk)(pipe, buffer, len, usb_callback, udi); + if(status != B_OK){ + PTRACE_ALWAYS(udi, "datafab_queue_bulk:failed:%08x\n", status); + } else { + status = acquire_sem_etc(udi->trans_sem, 1, B_RELATIVE_TIMEOUT, + /*DATAFAB_USB_TIMEOUT*/ udi->trans_timeout); + if(status != B_OK){ + PTRACE_ALWAYS(udi, "datafab_queue_bulk:acquire_sem_etc failed:%08x\n", status); + (*udi->usb_m->cancel_queued_transfers)(pipe); + } + } + return status; +} + +/** + \fn:handle_INQUIRY + \param usti: pointer to usb_scsi_transport_info sutruct containing request + information + \return: command execution status + + handles INQUIRY SCSI command +*/ +static status_t +handle_INQUIRY(usb_scsi_transport_info *usti) +{ + status_t status = B_CMD_FAILED; + uint8 *data = usti->ccbio->cam_data_ptr; + if(usti->ccbio->cam_ch.cam_flags & CAM_SCATTER_VALID){ + PTRACE(usti->udi,"handle_INQUIRY: problems!!! scatter gatter ....=-(\n"); + } else { + command_registers cr = { + .feature = 0, + .sector_count = 1, + .address = {0}, + .addr_dev = 0xa0, + .command = 0xec, + .intr_reset = 0x01 + }; + + ATA_DEVICE_INFO adi = {0}; + + PTRACE(usti->udi, "ATA_DEVICE_INFO sizeof:%d pipe_in:%x, pipe_out:%x\n", sizeof(adi), + usti->udi->pipe_in, usti->udi->pipe_out); + + PTRACE(usti->udi, "command_registers sizeof:%d\n", sizeof(cr)); + + memset(data, 0, usti->ccbio->cam_dxfer_len); +//TODO!!! + /* data[0] = 0x1F;*/ /* we can play here with type of device */ + /* data[1] = 0x80; + data[2] = 0x02; + data[3] = 0x02; + data[4] = (0 != usti->udi) ? 5 : 31; / * udi != 0 - mean FIX_NO_INQUIRY * / + if(usti->ccbio->cam_dxfer_len >= 0x24){ + strncpy(&data[8], "USB SCSI", INQ_VENDOR_LEN); + strncpy(&data[16], "Reserved", INQ_PRODUCT_LEN); + strncpy(&data[32], "N/A", INQ_REVISION_LEN); + } */ + status = queue_bulk(usti->udi, &cr, sizeof(cr), false); + if(B_OK != status){ + PTRACE(usti->udi, "write command 1 status:%08x\n", status); + //goto finalize; + } + + status = queue_bulk(usti->udi, &adi, sizeof(adi), true); + if(B_OK != status){ + PTRACE(usti->udi, "write command 2 status:%08x\n", status); + goto finalize; + } + + PTRACE(usti->udi, "ADI::info:%08x\n", adi.info); + usti->udi->trace_bytes("ADI::pad1:", (char*)adi.pad1, sizeof(adi.pad1)); + usti->udi->trace_bytes("ADI::serial:", (char*)adi.serial, sizeof(adi.serial)); + usti->udi->trace_bytes("ADI::pad2:", (char*)adi.pad2, sizeof(adi.pad2)); + usti->udi->trace_bytes("ADI::firmware_rev:", (char*)adi.firmware_rev, sizeof(adi.firmware_rev)); + usti->udi->trace_bytes("ADI::model_num:", (char*)adi.model_num, sizeof(adi.model_num)); + usti->udi->trace_bytes("ADI::pad3:", (char*)adi.pad3, sizeof(adi.pad3)); + usti->udi->trace_bytes("ADI::total_secs:", (char*)&adi.total_secs, sizeof(adi.total_secs)); + usti->udi->trace_bytes("ADI::pad4:", (char*)adi.pad4, sizeof(adi.pad4)); + usti->udi->trace_bytes("ADI::pad5:", (char*)adi.pad5, sizeof(adi.pad5)); + usti->udi->trace_bytes("ADI::pad6:", (char*)adi.pad6, sizeof(adi.pad6)); + usti->udi->trace_bytes("ADI::pad7:", (char*)adi.pad7, sizeof(adi.pad7)); + usti->udi->trace_bytes("ADI::pad8:", (char*)adi.pad8, sizeof(adi.pad8)); + usti->udi->trace_bytes("ADI::pad9:", (char*)adi.pad9, sizeof(adi.pad9)); + usti->udi->trace_bytes("ADI::padA:", (char*)adi.padA, sizeof(adi.padA)); + usti->udi->trace_bytes("ADI::padB:", (char*)adi.padB, sizeof(adi.padB)); + +finalize: + status = B_CMD_WIRE_FAILED; + } + return status; +} + +/** + \fn:handle_TEST_UNIT_READY + \param usti: pointer to usb_scsi_transport_info sutruct containing request + information + \return: command execution status + + handles TEST_UNIT_READY SCSI command +*/ +static status_t +handle_TEST_UNIT_READY(usb_scsi_transport_info *usti) +{ + status_t status = B_CMD_FAILED; + return status; +} + +/** + \fn:handle_READ_CAPACITY + \param usti: pointer to usb_scsi_transport_info sutruct containing request + information + \return: command execution status + + handles READ_CAPACITY SCSI command +*/ +static status_t +handle_READ_CAPACITY(usb_scsi_transport_info *usti) +{ + status_t status = B_CMD_FAILED; + return status; +} + +/** + \fn:handle_REQUEST_SENSE + \param usti: pointer to usb_scsi_transport_info sutruct containing request + information + \return: command execution status + + handles REQUEST_SENSE SCSI command +*/ +static status_t +handle_REQUEST_SENSE(usb_scsi_transport_info *usti) +{ + status_t status = B_CMD_FAILED; + return status; +} + +/** + \fn:handle_MODE_SENSE + \param usti: pointer to usb_scsi_transport_info sutruct containing request + information + \return: command execution status + + handles MODE_SENSE SCSI command +*/ +static status_t +handle_MODE_SENSE(usb_scsi_transport_info *usti) +{ + status_t status = B_CMD_FAILED; + return status; +} + +/** + \fn:handle_MODE_SELECT + \param usti: pointer to usb_scsi_transport_info sutruct containing request + information + \return: command execution status + + handles MODE_SELECT SCSI command +*/ +static status_t +handle_MODE_SELECT(usb_scsi_transport_info *usti) +{ + status_t status = B_CMD_FAILED; + return status; +} + +/** + \fn:handle_READ + \param usti: pointer to usb_scsi_transport_info sutruct containing request + information + \return: command execution status + + handles READ SCSI command +*/ +static status_t +handle_READ(usb_scsi_transport_info *usti) +{ + status_t status = B_CMD_FAILED; + return status; +} + +/** + \fn:handle_WRITE + \param usti: pointer to usb_scsi_transport_info sutruct containing request + information + \return: command execution status + + handles WRITE SCSI command +*/ +static status_t +handle_WRITE(usb_scsi_transport_info *usti) +{ + status_t status = B_CMD_FAILED; + return status; +} + +/** + \fn:handle_UnknownCommand + \param usti: pointer to usb_scsi_transport_info sutruct containing request + information + \return: command execution status + + handles "Unknown" SCSI command that were not handled +*/ +static status_t +handle_UnknownCommand(usb_scsi_transport_info *usti) +{ + status_t status = B_CMD_FAILED; + return status; +} + +/** + \fn:datafab_transfer + \param udi: corresponding device + \param cmd: SCSI command to be performed on USB device + \param cmdlen: length of SCSI command + \param data_sg: io vectors array with data to transfer + \param sglist_count: count of entries in io vector array + \param transfer_len: overall length of data to be transferred + \param dir: direction of data transfer + \param ccbio: CCB_SCSIIO struct for original SCSI command + \param cb: callback to handle of final stage of command performing (autosense \ + request etc.) + + transfer procedure for bulk-only protocol. Performs SCSI command on USB device + [2] +*/ +void +datafab_transfer(usb_device_info *udi, + uint8 *cmd, + uint8 cmdlen, + iovec*sg_data, + int32 sg_count, + int32 transfer_len, + EDirection dir, + CCB_SCSIIO *ccbio, + ud_transfer_callback cb) +{ + status_t command_status = B_CMD_WIRE_FAILED;//B_OK; + int32 residue = transfer_len; + usb_scsi_transport_info usti = { + .udi = udi, + .cmd = cmd, + .cmdlen = cmdlen, + .sg_data = sg_data, + .sg_count = sg_count, + .transfer_len = transfer_len, + .dir = dir, + .ccbio = ccbio, + .residue = transfer_len + }; + + switch(cmd[0]){ + case TEST_UNIT_READY: + command_status = handle_TEST_UNIT_READY(&usti); + break; + case INQUIRY: + command_status = handle_INQUIRY(&usti); + break; + case READ_CAPACITY: + command_status = handle_READ_CAPACITY(&usti); + break; + case REQUEST_SENSE: + command_status = handle_REQUEST_SENSE(&usti); + break; + case MODE_SENSE_6: + case MODE_SENSE_10: + command_status = handle_MODE_SENSE(&usti); + break; + case MODE_SELECT_6: + case MODE_SELECT_10: + command_status = handle_MODE_SELECT(&usti); + break; +/* case ALLOW_MEDIUM_REMOVAL: + command_status = handle_ALLOW_MEDIUM_REMOVAL(); + break;*/ + case READ_6: + case READ_10: + case READ_12: + command_status = handle_READ(&usti); + break; + case WRITE_6: + case WRITE_10: + case WRITE_12: + command_status = handle_WRITE(&usti); + break; + default: + command_status = handle_UnknownCommand(&usti); + break; + } + /* finalize transfer */ + cb(udi, ccbio, residue, command_status); +} + +static status_t +std_ops(int32 op, ...) +{ + switch(op) { + case B_MODULE_INIT: + return B_OK; + case B_MODULE_UNINIT: + return B_OK; + default: + return B_ERROR; + } +} + +static protocol_module_info datafab_protocol_module = { + { DATAFAB_PROTOCOL_MODULE_NAME, 0, std_ops }, + datafab_initialize, + datafab_reset, + datafab_transfer, +}; + +_EXPORT protocol_module_info *modules[] = { + &datafab_protocol_module, + NULL +}; diff --git a/src/add-ons/kernel/busses/scsi/usb/datafab/makefile b/src/add-ons/kernel/busses/scsi/usb/datafab/makefile new file mode 100644 index 0000000000..66098b3207 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/datafab/makefile @@ -0,0 +1,146 @@ +## +## This file is a part of BeOS USB Serial driver project. +## Copyright (c) 2005 by Siarzhuk Zharski +## All rights reserved. +## +## Based on BeOS Generic Makefile v2.2 ## + +## Fill in this file to specify the project being created, and the referenced +## makefile-engine will do all of the hard work for you. This handles both +## Intel and PowerPC builds of the BeOS. + +## Application Specific Settings --------------------------------------------- +#SETVERSION=setversion +#GETVERSION=version +#ZIP=zip +#ZIPOPT=-j + +# specify the name of the binary +NAME=datafab + +# specify the type of binary +# APP: Application +# SHARED: Shared library or add-on +# STATIC: Static library archive +# DRIVER: Kernel Driver +TYPE=DRIVER + +# some version definitions +#VER_MAJ = 0 +#VER_MID = 1 +#VER_MIN = 0 +#VER_TYP = d #d-development a-alpha b-beta g-RC f-release +#VER_BLD = 18 +#VER_SHORT = $(NAME) +#VER_LONG = "The module for SCSI interface to USB mass storage devices. Copyright "`echo -n -e '\302\251'`" 2003-2004 by Siarzhuk Zharski" + +# add support for new Pe and Eddie features +# to fill in generic makefile + +#%{ +# @src->@ + +# specify the source files to use +# full paths or paths relative to the makefile can be included +# all files, regardless of directory, will have their object +# files created in the common object directory. +# Note that this means this makefile will not work correctly +# if two source files with the same name (source.c or source.cpp) +# are included from different directories. Also note that spaces +# in folder names do not work well with this makefile. +SRCS=datafab.c + +# specify the resource files to use +# full path or a relative path to the resource file can be used. +RSRCS= + +# @<-src@ +#%} + +# end support for Pe and Eddie + +# specify additional libraries to link against +# there are two acceptable forms of library specifications +# - if your library follows the naming pattern of: +# libXXX.so or libXXX.a you can simply specify XXX +# library: libbe.so entry: be +# +# - if your library does not follow the standard library +# naming scheme you need to specify the path to the library +# and it's name +# library: my_lib.a entry: my_lib.a or path/my_lib.a +LIBS= + +# specify additional paths to directories following the standard +# libXXX.so or libXXX.a naming scheme. You can specify full paths +# or paths relative to the makefile. The paths included may not +# be recursive, so include all of the paths where libraries can +# be found. Directories where source files are found are +# automatically included. +LIBPATHS= + +# additional paths to look for system headers +# thes use the form: #include
+# source file directories are NOT auto-included here +SYSTEM_INCLUDE_PATHS = + +# additional paths to look for local headers +# thes use the form: #include "header" +# source file directories are automatically included +LOCAL_INCLUDE_PATHS = ../ + +# specify the level of optimization that you desire +# NONE, SOME, FULL +OPTIMIZE= + +# specify any preprocessor symbols to be defined. The symbols will not +# have their values set automatically; you must supply the value (if any) +# to use. For example, setting DEFINES to "DEBUG=1" will cause the +# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" +# would pass "-DDEBUG" on the compiler's command line. +#DEFINES=DEBUG=1 + +# specify special warning levels +# if unspecified default warnings will be used +# NONE = supress all warnings +# ALL = enable all warnings +WARNINGS= + +# specify whether image symbols will be created +# so that stack crawls in the debugger are meaningful +# if TRUE symbols will be created +SYMBOLS=TRUE + +# specify debug settings +# if TRUE will allow application to be run from a source-level +# debugger. Note that this will disable all optimzation. +DEBUGGER=TRUE + +# specify additional compiler flags for all files +COMPILER_FLAGS = + +# specify additional linker flags +LINKER_FLAGS = + +# specify the version of this particular item +# (for example, -app 3 4 0 d 0 -short 340 -long "340 "`echo -n -e '\302\251'`"1999 GNU GPL") +# This may also be specified in a resource. +#APP_VERSION = +#VERSION = $(VER_MAJ) $(VER_MID) $(VER_MIN) $(VER_TYP) $(VER_BLD) -short $(VER_SHORT) -long $(VER_LONG) +#APP_VERSION = -app $(VERSION) +#SYS_VERSION = -system $(VERSION) + +# (for TYPE == DRIVER only) Specify desired location of driver in the /dev +# hierarchy. Used by the driverinstall rule. E.g., DRIVER_PATH = video/usb will +# instruct the driverinstall rule to place a symlink to your driver's binary in +# ~/add-ons/kernel/drivers/dev/video/usb, so that your driver will appear at +# /dev/video/usb when loaded. Default is "misc". +DRIVER_PATH= + +CFLAGS += -Wall + +## include the makefile-engine +include $(BUILDHOME)/etc/makefile-engine + +install: default + copyattr --data $(TARGET) /boot/home/config/add-ons/kernel/generic/usb_scsi_extensions/$(NAME) diff --git a/src/add-ons/kernel/busses/scsi/usb/device_info.h b/src/add-ons/kernel/busses/scsi/usb/device_info.h new file mode 100644 index 0000000000..cdbac7577e --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/device_info.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ +#ifndef _DEVICE_INFO_H_ + #define _DEVICE_INFO_H_ + +#ifndef _SCSI_COMMANDS_H_ + #include "scsi_commands.h" +#endif /*_SCSI_COMMANDS_H_*/ + +#ifndef _PROTO_MODULE_H_ + #include "proto_module.h" +#endif /* _PROTO_MODULE_H_ */ + +typedef struct _usb_device_info{ + uint8 dev_num; /**/ + const usb_device device; /**/ + uint16 interface; /**/ + uint8 max_lun; /**/ + + uint32 properties; + + usb_pipe pipe_in; /**/ + usb_pipe pipe_out; /**/ + usb_pipe pipe_intr; /**/ + + sem_id lock_sem; /**/ + sem_id trans_sem; /**/ + uint32 tag; /**/ + status_t status; /**/ + + bigtime_t trans_timeout; + usb_module_info *usb_m; + + void *data; /**/ + int actual_len; /**/ + + protocol_module_info *protocol_m; + char *protocol_m_path; + + transform_module_info *transform_m; + char *transform_m_path; + + bool b_trace; + void (*trace)(bool b_force, const char *fmt, ...); + void (*trace_bytes)(const char *prefix, const uint8 *bytes, size_t bytes_len); + + uint8 scsi_command_buf[IOCDBLEN]; + /* auto sense buffer. Some commands doesn't have it. emulate */ + scsi_sense_data autosense_data; + /* iovec autosense_sg; DO NOT RESTORE IT !!!*/ + uint8 not_ready_luns; +} usb_device_info; + +#endif /* _DEVICE_INFO_H_ */ diff --git a/src/add-ons/kernel/busses/scsi/usb/fake_device.c b/src/add-ons/kernel/busses/scsi/usb/fake_device.c new file mode 100644 index 0000000000..7b74a8eda6 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/fake_device.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ +#include "usb_scsi.h" + +#include +#include "device_info.h" +#include "tracing.h" + +#include "fake_device.h" + +/* duplication! Hope this fake file will be not required in Haiku version*/ +#define INQ_VENDOR_LEN 0x08 +#define INQ_PRODUCT_LEN 0x10 +#define INQ_REVISION_LEN 0x04 + + +void fake_inquiry_request(usb_device_info *udi, CCB_SCSIIO *ccbio) +{ + uint8 *data = ccbio->cam_data_ptr; + if(ccbio->cam_ch.cam_flags & CAM_SCATTER_VALID){ + TRACE_ALWAYS("fake_inquiry: problems!!! scatter gatter ....=-(\n"); + } else { + memset(data, 0, ccbio->cam_dxfer_len); + /* data[0] = 0x1F;*/ /* we can play here with type of device */ + data[1] = 0x80; + data[2] = 0x02; + data[3] = 0x02; + data[4] = (0 != udi) ? 5 : 31; /* udi != 0 - mean FIX_NO_INQUIRY */ + if(ccbio->cam_dxfer_len >= 0x24){ + strncpy(&data[8], "USB SCSI", INQ_VENDOR_LEN); + strncpy(&data[16], "Reserved", INQ_PRODUCT_LEN); + strncpy(&data[32], "N/A", INQ_REVISION_LEN); + } + } +} + +void fake_test_unit_ready_request(CCB_SCSIIO *ccbio) +{ + if(ccbio->cam_sense_ptr != NULL){ + scsi_sense_data *sense_data = (scsi_sense_data *)ccbio->cam_sense_ptr; + memset(sense_data, 0, ccbio->cam_sense_len); + sense_data->error_code = SSD_CURRENT_ERROR; + sense_data->flags = SSD_KEY_NOT_READY; + ccbio->cam_ch.cam_status = CAM_REQ_CMP_ERR | CAM_AUTOSNS_VALID; + ccbio->cam_scsi_status = SCSI_STATUS_CHECK_CONDITION; + } else { + ccbio->cam_ch.cam_status = CAM_REQ_CMP_ERR; + ccbio->cam_scsi_status = SCSI_STATUS_OK; + } +} + +/** + \fn:fake_scsi_io + \param ccbio: ???? + \return: ??? + + xpt_scsi_io - handle XPT_SCSI_IO sim action +*/ +status_t fake_scsi_io(CCB_SCSIIO *ccbio) +{ + status_t status = B_BAD_VALUE; + uint8 *cmd; + scsi_cmd_generic *command; + if(ccbio->cam_ch.cam_flags & CAM_CDB_POINTER){ + cmd = ccbio->cam_cdb_io.cam_cdb_ptr; + }else{ + cmd = ccbio->cam_cdb_io.cam_cdb_bytes; + } + command = (scsi_cmd_generic *)cmd; + switch(command->opcode){ + case TEST_UNIT_READY:{ + fake_test_unit_ready_request(ccbio); + status = B_OK; + }break; + case INQUIRY:{ + fake_inquiry_request(NULL, ccbio); + ccbio->cam_ch.cam_status = CAM_REQ_CMP; + status = B_OK; + }break; + default: + ccbio->cam_ch.cam_status = CAM_REQ_INVALID; + break; + } + return status; +} diff --git a/src/add-ons/kernel/busses/scsi/usb/fake_device.h b/src/add-ons/kernel/busses/scsi/usb/fake_device.h new file mode 100644 index 0000000000..f7e0b6cc4f --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/fake_device.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ +#ifndef _FAKE_DEVICE_H_ + #define _FAKE_DEVICE_H_ + +void fake_inquiry_request(usb_device_info *udi, CCB_SCSIIO *ccbio); +void fake_test_unit_ready_request(CCB_SCSIIO *ccbio); +status_t fake_scsi_io(CCB_SCSIIO *ccbio); + +#endif /* _FAKE_DEVICE_H_ */ diff --git a/src/add-ons/kernel/busses/scsi/usb/freecom/COPYING b/src/add-ons/kernel/busses/scsi/usb/freecom/COPYING new file mode 100644 index 0000000000..60549be514 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/freecom/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/src/add-ons/kernel/busses/scsi/usb/freecom/ReadMe.freecom.html b/src/add-ons/kernel/busses/scsi/usb/freecom/ReadMe.freecom.html new file mode 100644 index 0000000000..f7782023ea --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/freecom/ReadMe.freecom.html @@ -0,0 +1,176 @@ + + + + + FREECOM extension module for BeOS USB mass storage support + + +

FREECOM extension module for + BeOS + USB mass storage support

+ +

This FREECOM extension module (The Extension) is kind of the helper for +BeOS USB Storage Module (The Module) that is designed to support +external CD/DVD drives connected with FREECOM USB 1.1 Cable. +This software is for BeOS/Dano/Zeta operating systems. +

+

Note that this manual contains only FREECOM extension specific information. For general USB +Storage Module questions look into the corresponding manual. +

+ +

Table of Contents

+ + +

1. Installation and using

+
    +
  1. Contents of distribution archive: +
        ReadMe.freecom.html      <--- file you are reading now
    +    install.sh       <--- installation script
    +    uninstall.sh     <--- uninstallation script
    +    freecom              <--- The Extension binary
    +    device_info.sample  <--- device description sample
    +
    +
  2. +
  3. Run ./install.sh to install The Extension on your system. +This script do the following:
  4. +
      +
    • copies The Extension binary to + /boot/home/config/add-ons/kernel/generic/usb_scsi_extensions/ + directory
    • +
    +
      +
    • add device definition into + /boot/home/config/settings/kernel/drivers/usb_scsi + file
    • +
    • ask you to edit settings file. Note that you have to check vendor and product ids for + your FREECOM device and edit device settings correspondently! It is not required to reboot your PC after installing +The Extension and changing it's definitions.
    • +
    +
  5. Plug in your FREECOM CD/DVD drive into USB slot, load a media into it and +try to open Tracker's "Mount" menu some times. In case if all goes OK - +you'll see your CD/DVD volume available for mounting. You can of course use your CD/DVD burning +software with this drive.
  6. +
  7. [optional] To uninstall The Module from your system - run uninstall.sh +from distribution archive or delete files mentioned in +clause 3 of this section manually.
  8. +
+Table +of Contents +

2. Troubleshooting

+
    +
  1. Is my external USB CD/DVD device supported? +
      +
    • Only "old" FREECOM USB 1.1 cable connected drives are supported. Obtain your device + vendor and product ids as described in ReadMe.html for + BeOS USB storage Module, edit the device description in settings file correspondently and try + to work with it. Be sure that your FREECOM device is really non-standard and has 255 as class in + usb device description. Vendor id for FREECOM is 0x07ab. +
    • +
    +
  2. +
  3. Cannot mount my CD/DVDs. +
      +
    • Please check the following: +
        +
      • the binary file /boot/home/config/add-ons/kernel/generic/usb_scsi_extensions/freecom +exists on your system; +
      • +
      • the settings file /boot/home/config/settings/kernel/drivers/usb_scsi +exists on your system and contains description for your FREECOM device;
      • +
      • check that device description correspond to your real device information; +
      • +
      +
    • +
    +
  4. +
  5. My external USB HDD in FREECOM case doesn't work +
      +
    • Only ATAPI devices are supported. ATA protocol doesn't uses SCSI-like commands.
    • +
    +
  6. +
  7. Mmmm... another question... +
      +
    • Please refer to Troubleshooting section of ReadMe.html for BeOS USB Storage Support Module and + contact the developer if you still have a problem. +
    • +
    +
  8. +
+Table of Contents +

3. Writing a problem report

+Refer to corresponding section of ReadMe.html file for BeOS USB Storage Support Module. +Table of Contents +

4.Contact and support information

+The Extension is a part of BeOS USB Support Module project that is hosted on SourceForge +and uses some it's powerful development services. There are some ways to inform +developer about problems or put feature requests for next version +
    +
  1. Use Bug +Tracker to put problem reports.
  2. +
  3. Use Forum +to ask simple support question, discuss any problems. +
  4. Use Mailing-list +to be informed with latest news, ask questions +etc.
  5. +
  6. Also you can contact me personally by e-mail.
  7. +
+Table of Contents +

5.Credits

+

I want to say my "Thanks" to:

+

brave testers...

+Table of Contents +

6. The History

+

+ + + + + + + + + + + + +
Date: Version: What's new:
?? ??April 20050.1.0-alpha-1 first public release.
+

+Table +of Contents +
< End of document >
+ + diff --git a/src/add-ons/kernel/busses/scsi/usb/freecom/device_info.sample b/src/add-ons/kernel/busses/scsi/usb/freecom/device_info.sample new file mode 100644 index 0000000000..9f5aebbe2f --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/freecom/device_info.sample @@ -0,0 +1,21 @@ +########################################################## +## +## USB Storage Module non-standard devices definitions +## +## This file is a part of BeOS USB SCSI interface module project. +## Copyright (c) 2003-2005 by Siarzhuk Zharski +## All rights reserved. +## +########################################################## +# +# FREECOM USB-ATAPI bridge. +# +# Supports FREECOM USB Cable connected CD/DVD drives/burners +# +# +vendor 0x07ab { + device 0xfc01 { + protocol freecom + commandset ATAPI + } +} diff --git a/src/add-ons/kernel/busses/scsi/usb/freecom/freecom.c b/src/add-ons/kernel/busses/scsi/usb/freecom/freecom.c new file mode 100644 index 0000000000..351a679006 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/freecom/freecom.c @@ -0,0 +1,590 @@ +/* + * \file: freecom.c + * \brief: USB SCSI module extention for Freecom USB/IDE adaptor + * + * This file is a part of BeOS USB SCSI interface module project. + * Copyright (c) 2003-2004 by Siarzhuk Zharski + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + * This protocol extension module was developed using information from + * "Driver for Freecom USB/IDE adaptor" in Linux usb storage driver and + * "Mac OS X driver for the Freecom Traveller CD writer". + * + * $Source: /cvsroot/sis4be/usb_scsi/freecom/freecom.c,v $ + * $Author: zharik $ + * $Revision: 1.11 $ + * $Date: 2005/04/01 22:39:23 $ + * + */ +#include "usb_scsi.h" + +#include +#include "device_info.h" +#include "proto_module.h" + +#define FREECOM_MODULE_NAME "freecom" +#define FREECOM_PROTOCOL_MODULE_NAME \ + MODULE_PREFIX FREECOM_MODULE_NAME PROTOCOL_SUFFIX + +/** + \struct:fcm_command +*/ +typedef struct { + uint8 type; /* block type. */ +#define FCMT_ATAPI 0x21 /* send command. low bit indicates waiting for interrupt */ +#define FCMT_STATUS 0x20 /* request for status */ +#define FCMT_IN 0x81 /* request read data transfer. */ +#define FCMT_OUT 0x01 /* request write data transfer */ +#define FCMT_REG_IN 0xC0 /* read value from IDE regsiter */ +#define FCMT_REG_OUT 0x40 /* write value to IDE register */ + /* to use FCMT_REG_ combine it with register */ +#define FCMR_DATA 0x10 /* data register */ + /* ... */ +#define FCMR_CMD 0x16 /* status-command register */ +#define FCMR_INT 0x17 /* interrupt-error register */ + uint8 timeout; /* timeout (seconds?) */ +#define FCMTO_DEF 0xfe /* default timeout */ +#define FCMTO_TU 0x14 /* timeout for TEST UNIT READY command */ + union{ + uint8 cmd[12]; /* An ATAPI command. */ + uint32 count; /* number of bytes to transfer. */ + uint16 reg_val; /* Value to write to IDE register. */ + uint8 pad[62]; /* Padding Data. All FREECOM commands are 64 bytes long */ + }_PACKED data; +}_PACKED fcm_command; + +/** + \struct:fcm_status +*/ +typedef struct { + uint8 status; +#define FCMS_BSY 0x80 /* device is busy */ +#define FCMS_DRDY 0x40 /* */ +#define FCMS_DMA 0x20 /* */ +#define FCMS_SEEK 0x10 /* */ +#define FCMS_DRQ 0x08 /* */ +#define FCMS_CORR 0x04 /* */ +#define FCMS_INTR 0x02 /*FREECOM specific: use obsolete bit*/ +#define FCMS_CHECK 0x01 /* device is in error condition */ + uint8 reason; +#define FCMR_REL 0x04 /* */ +#define FCMR_IO 0x02 /* */ +#define FCMR_COD 0x01 /* */ + uint16 count; +}_PACKED fcm_status; + +// Timeout value (in us) for the freecom packet USB BulkRead and BulkWrite functions +#define FREECOM_USB_TIMEOUT 30000000 + +/** + \fn: + \param udi: + \param st: + \return: + +*/ +void trace_status(usb_device_info *udi, const fcm_status *st) +{ + char ch_status[] = "BDFSRCIE"; + char ch_reason[] = ".....RIC"; + int i = 0; + for(; i < 8; i++){ + if(!(st->status & (1 << i))) + ch_status[7 - i] = '.'; + if(!(st->reason & (1 << i))) + ch_reason[7 - i] = '.'; + } + PTRACE(udi, "FCM:Status:{%s; Reason:%s; Count:%d}\n", + ch_status, ch_reason, st->count); +} + +/** + \fn:freecom_initialize + \param udi: device on wich we should perform initialization + \return:error code if initialization failed or B_OK if it passed + + initialize procedure. +*/ +status_t +freecom_initialize(usb_device_info *udi) +{ + status_t status = B_OK; +#define INIT_BUFFER_SIZE 0x20 + char buffer[INIT_BUFFER_SIZE + 1]; + size_t len = 0; + + if(B_OK != (status = (*udi->usb_m->send_request)(udi->device, + USB_REQTYPE_DEVICE_IN | USB_REQTYPE_VENDOR, + 0x4c, 0x4346, 0x0, INIT_BUFFER_SIZE, + buffer, &len))) + { + PTRACE_ALWAYS(udi, "FCM:init[%d]: init failed: %08x\n", udi->dev_num, status); + } else { + buffer[len] = 0; + PTRACE(udi, "FCM:init[%d]: init '%s' OK\n", udi->dev_num, buffer); + } + + if(B_OK != (status = (*udi->usb_m->send_request)(udi->device, + USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_VENDOR, + 0x4d, 0x24d8, 0x0, 0, 0, &len))) + { + PTRACE_ALWAYS(udi, "FCM:init[%d]: reset on failed:%08x\n", udi->dev_num, status); + } + + snooze(250000); + + if(B_OK != (status = (*udi->usb_m->send_request)(udi->device, + USB_REQTYPE_DEVICE_OUT | USB_REQTYPE_VENDOR, + 0x4d, 0x24f8, 0x0, 0, 0, &len))) + { + PTRACE_ALWAYS(udi, "FCM:init[%d]: reset off failed:%08x\n", udi->dev_num, status); + } + + snooze(3 * 1000000); + + return status; +} +/** + \fn:freecom_reset + \param udi: device on wich we should perform reset + \return:error code if reset failed or B_OK if it passed + + reset procedure. +*/ +status_t +freecom_reset(usb_device_info *udi) +{ + status_t status = B_OK; + /* not required ? */ + return status; +} + +/** + \fn:usb_callback + \param cookie:??? + \param status:??? + \param data:??? + \param actual_len:??? + \return:??? + + ??? +*/ +static void usb_callback(void *cookie, + uint32 status, + void *data, + uint32 actual_len) +{ + if(cookie){ + usb_device_info *udi = (usb_device_info *)cookie; +// PTRACE(udi, "FCM:usb_callback:status:0x%08x,len:%d\n", status, actual_len); + udi->status = status; + udi->data = data; + udi->actual_len = actual_len; + if(udi->status != B_CANCELED) + release_sem(udi->trans_sem); + } +} + +/** + \fn:queue_bulk + \param udi: device for which que_bulk request is performed + \param buffer: data buffer, used in bulk i/o operation + \param len: length of data buffer + \param b_in: is "true" if input (device->host) data transfer, "false" otherwise + \return: status of operation. + + performs queue_bulk USB request for corresponding pipe and handle timeout of this + operation. +*/ +static status_t +queue_bulk(usb_device_info *udi, + void *buffer, + size_t len, + bool b_in) +{ + status_t status = B_OK; + usb_pipe pipe = b_in ? udi->pipe_in : udi->pipe_out; + status = (*udi->usb_m->queue_bulk)(pipe, buffer, len, usb_callback, udi); + if(status != B_OK){ + PTRACE_ALWAYS(udi, "FCM:queue_bulk:failed:%08x\n", status); + } else { + status = acquire_sem_etc(udi->trans_sem, 1, B_RELATIVE_TIMEOUT, FREECOM_USB_TIMEOUT/*udi->trans_timeout*/); + if(status != B_OK){ + PTRACE_ALWAYS(udi, "FCM:queue_bulk:acquire_sem_etc failed:%08x\n", status); + (*udi->usb_m->cancel_queued_transfers)(pipe); + } + } + return status; +} + +/** + \fn:write_command +*/ +static status_t +write_command(usb_device_info *udi, uint8 type, uint8 *cmd, uint8 timeout) +{ + status_t status = B_OK; + /* initialize and fill in command block*/ + fcm_command fc = { + .type = type, + .timeout = FCMTO_DEF, + }; + if(0 != cmd){ + memcpy(fc.data.cmd, cmd, sizeof(fc.data.cmd)); + if(cmd[0] == 0x00){ + fc.timeout = FCMTO_TU; + } + } + PTRACE(udi, "FCM:FC:{Type:0x%02x; TO:%d;}\n", fc.type, fc.timeout); + udi->trace_bytes("FCM:FC::Cmd:\n", fc.data.cmd, sizeof(fc.data.cmd)); + udi->trace_bytes("FCM:FC::Pad:\n", fc.data.pad, sizeof(fc.data.pad)); +PTRACE(udi,"sizeof:%d\n",sizeof(fc)); + /* send command block to device */ + status = queue_bulk(udi, &fc, sizeof(fc), false); + if(status != B_OK || udi->status != B_OK){ + PTRACE_ALWAYS(udi, "FCM:write_command failed:status:%08x usb status:%08x\n", + status, udi->status); + //(*udi->protocol_m->reset)(udi); + status = B_CMD_WIRE_FAILED; + } + return status; +} + +/** + \fn:read_status +*/ +static status_t +read_status(usb_device_info *udi, fcm_status *fst) +{ + status_t status = B_OK; + do{ + /* cleanup structure */ + memset(fst, 0, sizeof(fcm_status)); + /* read status */ + status = queue_bulk(udi, fst, sizeof(fcm_status), true); + if(status != B_OK || udi->status != B_OK){ + PTRACE_ALWAYS(udi, "FCM:read_status failed:" + "status:%08x usb status:%08x\n", status, udi->status); + //(*udi->protocol_m->reset)(udi); + status = B_CMD_WIRE_FAILED; + break; + } + if(udi->actual_len != sizeof(fcm_status)){ + PTRACE_ALWAYS(udi, "FCM:read_status failed:requested:%d, readed %d bytes\n", + sizeof(fcm_status), udi->actual_len); + status = B_CMD_WIRE_FAILED; + break; + } + /* trace readed status info. if required. */ + trace_status(udi, fst); + if(fst->status & FCMS_BSY){ + PTRACE(udi, "FCM:read_status:Timeout. Poll device with another status request.\n"); + if(B_OK != (status = write_command(udi, FCMT_STATUS, 0, 0))){ + PTRACE_ALWAYS(udi, "FCM:read_status failed:write_command_block failed %08x\n", status); + break; + } + } + }while(fst->status & FCMS_BSY); /* repeat until device is busy */ + return status; +} + +/** + \fn:request_transfer +*/ +static status_t +request_transfer(usb_device_info *udi, uint8 type, uint32 length, uint8 timeout) +{ + status_t status = B_OK; + /* initialize and fill in Command Block */ + fcm_command fc = { + .type = type, + .timeout = timeout, + }; + fc.data.count = length; + + PTRACE(udi, "FCM:FC:{Type:0x%02x; TO:%d; Count:%d}\n", fc.type, fc.timeout, fc.data.count); + udi->trace_bytes("FCM:FC::Pad:\n", fc.data.pad, sizeof(fc.data.pad)); +PTRACE(udi,"sizeof:%d\n",sizeof(fc)); + /* send command block to device */ + status = queue_bulk(udi, &fc, sizeof(fc), false); + if(status != B_OK || udi->status != B_OK){ + PTRACE_ALWAYS(udi, "FCM:request_transfer:fc send failed:" + "status:%08x usb status:%08x\n", status, udi->status); + status = B_CMD_WIRE_FAILED; + } + return status; +} + + +/** + \fn:transfer_sg + \param udi: corresponding device + \param data_sg: io vectors array with data to transfer + \param sglist_count: count of entries in io vector array + \param offset: + \param block_len: + \param b_in: direction of data transfer) + + +*/ +static status_t +transfer_sg(usb_device_info *udi, + iovec *data_sg, + int32 sglist_count, + int32 offset, + int32 *block_len, + bool b_in) +{ + status_t status = B_OK; + usb_pipe pipe = (b_in) ? udi->pipe_in : udi->pipe_out; + int32 off = offset; + int32 to_xfer = *block_len; + /* iterate through SG list */ + int i = 0; + for(; i < sglist_count && to_xfer > 0; i++) { + if(off < data_sg[i].iov_len) { + int len = min(to_xfer, (data_sg[i].iov_len - off)); + char *buf = ((char *)data_sg[i].iov_base) + off; + /* transfer linear block of data to/from device */ + if(B_OK == (status = (*udi->usb_m->queue_bulk)(pipe, buf, len, usb_callback, udi))) { + status = acquire_sem_etc(udi->trans_sem, 1, B_RELATIVE_TIMEOUT, FREECOM_USB_TIMEOUT); + if(status == B_OK){ + status = udi->status; + if(B_OK != status){ + PTRACE_ALWAYS(udi, "FCM:transfer_sg:usb transfer status is not OK:%08x\n", status); + } + } else { + PTRACE_ALWAYS(udi, "FCM:transfer_sg:acquire_sem_etc failed:%08x\n", status); + goto finalize; + } + } else { + PTRACE_ALWAYS(udi, "FCM:transfer_sg:queue_bulk failed:%08x\n", status); + goto finalize; + } + /*check amount of transferred data*/ + if(len != udi->actual_len){ + PTRACE_ALWAYS(udi, "FCM:transfer_sg:WARNING!!!Length reported:%d required:%d\n", + udi->actual_len, len); + } + /* handle offset logic */ + to_xfer -= len; + off = 0; + } else { + off -= data_sg[i].iov_len; + } + } +finalize: + *block_len -= to_xfer; + return (B_OK != status) ? B_CMD_WIRE_FAILED : status; +} + +static status_t +transfer_data(usb_device_info *udi, + iovec *data_sg, + int32 sglist_count, + int32 transfer_length, + int32 *residue, + fcm_status *fst, + bool b_in) +{ + status_t status = B_OK; + int32 readed_len = 0; + uint8 xfer_type = b_in ? FCMT_IN : FCMT_OUT; + int32 block_len = (FCMR_COD == (fst->reason & FCMR_COD)) ? + transfer_length : fst->count; + /* Strange situation with SCSIProbe - device say about 6 bytes available for 5-bytes + request. Read 5 and all is ok. Hmm... */ + if(block_len > transfer_length){ + PTRACE_ALWAYS(udi, "FCM:transfer_data:TRUNCATED! " + "requested:%d available:%d.\n", transfer_length, block_len); + block_len = transfer_length; + } + /* iterate until data will be transferred */ + while(readed_len < transfer_length && block_len > 0){ + /* send transfer block */ + if(B_OK != (status = request_transfer(udi, xfer_type, block_len, 0))){ + goto finalize; + } + /* check if data available/awaited */ + if(FCMS_DRQ != (fst->status & FCMS_DRQ)){ + PTRACE_ALWAYS(udi, "FCM:transfer_data:device doesn't want to transfer anything!!!\n"); + status = B_CMD_FAILED; + goto finalize; + } + /* check the device state */ + if(!((fst->reason & FCMR_REL) == 0 && + (fst->reason & FCMR_IO) == ((b_in) ? FCMR_IO : 0) && + (fst->reason & FCMR_COD) == 0)) + { + PTRACE_ALWAYS(udi, "FCM:transfer_data:device doesn't ready to transfer?\n"); + status = B_CMD_FAILED; + goto finalize; + } + /* transfer scatter/gather safely only for length bytes at specified offset */ + if(B_OK != (status = transfer_sg(udi, data_sg, + sglist_count, readed_len, &block_len, b_in))) + { + goto finalize; + } + /* read status */ + if(B_OK != (status = read_status(udi, fst))){ + goto finalize; + } + /* check device error state */ + if(fst->status & FCMS_CHECK){ + PTRACE(udi, "FCM:transfer_data:data transfer failed?\n", fst->status); + status = B_CMD_FAILED; + goto finalize; + } + /* we have read block successfully */ + readed_len += block_len; + /* check device state and amount of data */ + if((fst->reason & FCMR_COD) == FCMR_COD){ +#if 0 /* too frequently reported - disabled to prevent log trashing */ + if(readed_len < transfer_length){ + PTRACE_ALWAYS(udi, "FCM:transfer_data:Device had LESS data that we wanted.\n"); + } +#endif + break; /* exit iterations - device has finished the talking */ + } else { + if(readed_len >= transfer_length){ + PTRACE_ALWAYS(udi, "FCM:transfer_data:Device had MORE data that we wanted.\n"); + break; + } + block_len = fst->count; /* still have something to read */ + } + } + /* calculate residue */ + *residue -= readed_len; + if(*residue < 0) + *residue = 0; /* TODO: consistency between SG length and transfer length - + in MODE_SENSE_10 converted commands f.example ... */ + PTRACE(udi,"FCM:transfer_data:was requested:%d, residue:%d\n", transfer_length, *residue); +finalize: + return status; /* TODO: MUST return B_CMD_*** error codes !!!!! */ +} + +/** + \fn:freecom_transfer + \param udi: corresponding device + \param cmd: SCSI command to be performed on USB device + \param cmdlen: length of SCSI command + \param data_sg: io vectors array with data to transfer + \param sglist_count: count of entries in io vector array + \param transfer_len: overall length of data to be transferred + \param dir: direction of data transfer + \param ccbio: CCB_SCSIIO struct for original SCSI command + \param cb: callback to handle of final stage of command performing (autosense \ + request etc.) + + transfer procedure for bulk-only protocol. Performs SCSI command on USB device + [2] +*/ +void +freecom_transfer(usb_device_info *udi, + uint8 *cmd, + uint8 cmdlen, + iovec*sg_data, + int32 sg_count, + int32 transfer_len, + EDirection dir, + CCB_SCSIIO *ccbio, + ud_transfer_callback cb) +{ + status_t command_status = B_CMD_WIRE_FAILED; + int32 residue = transfer_len; + fcm_status fst = {0}; + + /* Current BeOS scsi_cd driver bombs us with lot of + MODE_SENSE/MODE_SELECT commands. Unfortunately some of them + hangs the Freecom firmware. Try to ignore translated ones */ +#if 1 + if((MODE_SENSE_10 == cmd[0] && 0x0e == cmd[2]) || + (MODE_SELECT_10 == cmd[0] && 0x10 == cmd[1])) + { + uint8 *cmd_org = 0; + /* set the command data pointer */ + if(ccbio->cam_ch.cam_flags & CAM_CDB_POINTER){ + cmd_org = ccbio->cam_cdb_io.cam_cdb_ptr; + }else{ + cmd_org = ccbio->cam_cdb_io.cam_cdb_bytes; + } + if(cmd_org[0] != cmd[0]){ + if(MODE_SENSE_10 == cmd[0]){ /* emulate answer - return empty pages */ + scsi_mode_param_header_10 *hdr = (scsi_mode_param_header_10*)sg_data[0].iov_base; + memset(hdr, 0, sizeof(scsi_mode_param_header_10)); + hdr->mode_data_len[1] = 6; + PTRACE(udi, "FCM:freecom_transfer:MODE_SENSE_10 ignored %02x->02x\n", cmd_org[0], cmd[0]); + } else { + PTRACE(udi, "FCM:freecom_transfer:MODE_SELECT_10 ignored %02x->%02x\n", cmd_org[0], cmd[0]); + } + command_status = B_OK; /* just say that command processed OK */ + goto finalize; + } + } +#endif + /* write command to device */ + if(B_OK != (command_status = write_command(udi, FCMT_ATAPI, cmd, 0))){ + PTRACE_ALWAYS(udi, "FCM:freecom_transfer:" + "send command failed. Status:%08x\n", command_status); + goto finalize; + } + /* obtain status */ + if(B_OK != (command_status = read_status(udi, &fst))){ + PTRACE_ALWAYS(udi, "FCM:freecom_transfer:" + "read status failed. Status:%08x\n", command_status); + goto finalize; + } + /* check device error state */ + if(fst.status & FCMS_CHECK){ + PTRACE_ALWAYS(udi, "FCM:freecom_transfer:FST.Status is not OK\n"); + command_status = B_CMD_FAILED; + goto finalize; + } + /* transfer data */ + if(transfer_len != 0x0 && dir != eDirNone){ + command_status = transfer_data(udi, sg_data, sg_count, transfer_len, + &residue, &fst, (eDirIn == dir)); + } +finalize: + /* finalize transfer */ + cb(udi, ccbio, residue, command_status); +} + +static status_t +std_ops(int32 op, ...) +{ + switch(op) { + case B_MODULE_INIT: + return B_OK; + case B_MODULE_UNINIT: + return B_OK; + default: + return B_ERROR; + } +} + +static protocol_module_info freecom_protocol_module = { + { FREECOM_PROTOCOL_MODULE_NAME, 0, std_ops }, + freecom_initialize, + freecom_reset, + freecom_transfer, +}; + +_EXPORT protocol_module_info *modules[] = { + &freecom_protocol_module, + NULL +}; diff --git a/src/add-ons/kernel/busses/scsi/usb/freecom/install.sh b/src/add-ons/kernel/busses/scsi/usb/freecom/install.sh new file mode 100755 index 0000000000..2236a511cd --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/freecom/install.sh @@ -0,0 +1,41 @@ +#!/bin/sh +########################################################## +## +## USB Storage Module installation script +## +## This file is a part of BeOS USB SCSI interface module project. +## Copyright (c) 2003-2004 by Siarzhuk Zharski +## All rights reserved. +## +## $Source: /cvsroot/sis4be/usb_scsi/freecom/install.sh,v $ +## $Author: zharik $ +## $Revision: 1.1 $ +## $Date: 2005/04/09 22:16:17 $ +## +########################################################## + +MODULE_TITLE="FREECOM extension for USB Storage Module" +MODULE_NAME=freecom +SETTINGS_NAME=usb_scsi + +answer=`alert "Do you really want to install the $MODULE_TITLE ?" "No" "Yes"` +if [ $answer == "No" ]; then + exit +fi + +/boot/beos/bin/install -d ~/config/add-ons/kernel/generic/usb_scsi_extension/ +/boot/beos/bin/install `dirname $0`/$MODULE_NAME ~/config/add-ons/kernel/generic/usb_scsi_extension/$MODULE_NAME + +# TODO!!! +#if [ -e ~/config/settings/kernel/drivers/$SETTINGS_NAME ]; then +#/boot/beos/bin/cp `dirname $0`/$SETTINGS_NAME.sample ~/config/settings/kernel/drivers/ +#else +#/boot/beos/bin/cp `dirname $0`/$SETTINGS_NAME.sample ~/config/settings/kernel/drivers/$SETTINGS_NAME +#fi + +mimeset ~/config/add-ons/kernel/generic/usb_scsi_extension/$MODULE_NAME + +INSTALLED_MESSAGE="The $MODULE_TITLE has been installed on your system. You have to review/edit settings for your FREECOM device." +alert "$INSTALLED_MESSAGE" "Edit settings" + +StyledEdit /boot/home/config/settings/kernel/drivers/$SETTINGS_NAME diff --git a/src/add-ons/kernel/busses/scsi/usb/freecom/makefile b/src/add-ons/kernel/busses/scsi/usb/freecom/makefile new file mode 100644 index 0000000000..82714117d7 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/freecom/makefile @@ -0,0 +1,151 @@ +## +## This file is a part of BeOS USB Serial driver project. +## Copyright (c) 2003-2004 by Siarzhuk Zharski +## All rights reserved. +## +## $Source: /cvsroot/sis4be/usb_scsi/freecom/makefile,v $ +## $Author: zharik $ +## $Revision: 1.5 $ +## $Date: 2005/04/09 22:23:20 $ +## +## Based on BeOS Generic Makefile v2.2 ## + +## Fill in this file to specify the project being created, and the referenced +## makefile-engine will do all of the hard work for you. This handles both +## Intel and PowerPC builds of the BeOS. + +## Application Specific Settings --------------------------------------------- +#SETVERSION=setversion +#GETVERSION=version +#ZIP=zip +#ZIPOPT=-j + +# specify the name of the binary +NAME=freecom + +# specify the type of binary +# APP: Application +# SHARED: Shared library or add-on +# STATIC: Static library archive +# DRIVER: Kernel Driver +TYPE=DRIVER + +# some version definitions +#VER_MAJ = 0 +#VER_MID = 1 +#VER_MIN = 0 +#VER_TYP = d #d-development a-alpha b-beta g-RC f-release +#VER_BLD = 18 +#VER_SHORT = $(NAME) +#VER_LONG = "The module for SCSI interface to USB mass storage devices. Copyright "`echo -n -e '\302\251'`" 2003-2004 by Siarzhuk Zharski" + +# add support for new Pe and Eddie features +# to fill in generic makefile + +#%{ +# @src->@ + +# specify the source files to use +# full paths or paths relative to the makefile can be included +# all files, regardless of directory, will have their object +# files created in the common object directory. +# Note that this means this makefile will not work correctly +# if two source files with the same name (source.c or source.cpp) +# are included from different directories. Also note that spaces +# in folder names do not work well with this makefile. +SRCS=freecom.c + +# specify the resource files to use +# full path or a relative path to the resource file can be used. +RSRCS= + +# @<-src@ +#%} + +# end support for Pe and Eddie + +# specify additional libraries to link against +# there are two acceptable forms of library specifications +# - if your library follows the naming pattern of: +# libXXX.so or libXXX.a you can simply specify XXX +# library: libbe.so entry: be +# +# - if your library does not follow the standard library +# naming scheme you need to specify the path to the library +# and it's name +# library: my_lib.a entry: my_lib.a or path/my_lib.a +LIBS= + +# specify additional paths to directories following the standard +# libXXX.so or libXXX.a naming scheme. You can specify full paths +# or paths relative to the makefile. The paths included may not +# be recursive, so include all of the paths where libraries can +# be found. Directories where source files are found are +# automatically included. +LIBPATHS= + +# additional paths to look for system headers +# thes use the form: #include
+# source file directories are NOT auto-included here +SYSTEM_INCLUDE_PATHS = + +# additional paths to look for local headers +# thes use the form: #include "header" +# source file directories are automatically included +LOCAL_INCLUDE_PATHS = ../ + +# specify the level of optimization that you desire +# NONE, SOME, FULL +OPTIMIZE= + +# specify any preprocessor symbols to be defined. The symbols will not +# have their values set automatically; you must supply the value (if any) +# to use. For example, setting DEFINES to "DEBUG=1" will cause the +# compiler option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" +# would pass "-DDEBUG" on the compiler's command line. +#DEFINES=DEBUG=1 + +# specify special warning levels +# if unspecified default warnings will be used +# NONE = supress all warnings +# ALL = enable all warnings +WARNINGS= + +# specify whether image symbols will be created +# so that stack crawls in the debugger are meaningful +# if TRUE symbols will be created +SYMBOLS=TRUE + +# specify debug settings +# if TRUE will allow application to be run from a source-level +# debugger. Note that this will disable all optimzation. +DEBUGGER=TRUE + +# specify additional compiler flags for all files +COMPILER_FLAGS = + +# specify additional linker flags +LINKER_FLAGS = + +# specify the version of this particular item +# (for example, -app 3 4 0 d 0 -short 340 -long "340 "`echo -n -e '\302\251'`"1999 GNU GPL") +# This may also be specified in a resource. +#APP_VERSION = +#VERSION = $(VER_MAJ) $(VER_MID) $(VER_MIN) $(VER_TYP) $(VER_BLD) -short $(VER_SHORT) -long $(VER_LONG) +#APP_VERSION = -app $(VERSION) +#SYS_VERSION = -system $(VERSION) + +# (for TYPE == DRIVER only) Specify desired location of driver in the /dev +# hierarchy. Used by the driverinstall rule. E.g., DRIVER_PATH = video/usb will +# instruct the driverinstall rule to place a symlink to your driver's binary in +# ~/add-ons/kernel/drivers/dev/video/usb, so that your driver will appear at +# /dev/video/usb when loaded. Default is "misc". +DRIVER_PATH= + +CFLAGS += -Wall + +## include the makefile-engine +include $(BUILDHOME)/etc/makefile-engine + +install: default + copyattr --data $(TARGET) /boot/home/config/add-ons/kernel/generic/usb_scsi_extensions/$(NAME) diff --git a/src/add-ons/kernel/busses/scsi/usb/freecom/uninstall.sh b/src/add-ons/kernel/busses/scsi/usb/freecom/uninstall.sh new file mode 100755 index 0000000000..98d8e15621 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/freecom/uninstall.sh @@ -0,0 +1,33 @@ +#!/bin/sh +########################################################## +## +## USB Storage Module uninstallation script +## +## This file is a part of BeOS USB SCSI interface module project. +## Copyright (c) 2003-2004 by Siarzhuk Zharski +## All rights reserved. +## +## $Source: /cvsroot/sis4be/usb_scsi/freecom/uninstall.sh,v $ +## $Author: zharik $ +## $Revision: 1.1 $ +## $Date: 2005/04/09 22:16:17 $ +## +########################################################## + +DRIVER_TITLE="FREECOM extension for USB Storage Module" +SETTINGS_NAME=usb_scsi +DRIVER_TARGET_NAME=freecom + +answer=`alert "Do you really want to uninstall the $DRIVER_TITLE ?" "No" "Yes"` +if [ $answer == "No" ]; then + exit +fi + +rm ~/config/add-ons/kernel/generic/usb_scsi_extension/$DRIVER_TARGET_NAME + +answer=`alert "The $DRIVER_TITLE has been removed from your system. You can now remove FREECOM device description for settings file." "OK" "Edit settings"` +if [ $answer == "OK" ]; then + exit +fi + +StyledEdit /boot/home/config/settings/kernel/drivers/$SETTINGS_NAME diff --git a/src/add-ons/kernel/busses/scsi/usb/install.sh b/src/add-ons/kernel/busses/scsi/usb/install.sh new file mode 100755 index 0000000000..5390c2a03f --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/install.sh @@ -0,0 +1,45 @@ +#!/bin/sh +########################################################## +## +## USB Storage Module installation script +## +## This file is a part of BeOS USB SCSI interface module project. +## Copyright (c) 2003-2004 by Siarzhuk Zharski +## All rights reserved. +## +## $Source: /cvsroot/sis4be/usb_scsi/install.sh,v $ +## $Author: zharik $ +## $Revision: 1.5 $ +## $Date: 2004/06/06 09:19:47 $ +## +########################################################## + +MODULE_TITLE="USB Storage Module" +MODULE_NAME=usb +SETTINGS_NAME=usb_scsi + +answer=`alert "Do you really want to install the $MODULE_TITLE ?" "No" "Yes"` +if [ $answer == "No" ]; then + exit +fi + +/boot/beos/bin/install -d ~/config/add-ons/kernel/busses/scsi/ +/boot/beos/bin/install `dirname $0`/$MODULE_NAME ~/config/add-ons/kernel/busses/scsi/$MODULE_NAME +if [ -e ~/config/settings/kernel/drivers/$SETTINGS_NAME ]; then +/boot/beos/bin/cp `dirname $0`/$SETTINGS_NAME.sample ~/config/settings/kernel/drivers/ +else +/boot/beos/bin/cp `dirname $0`/$SETTINGS_NAME.sample ~/config/settings/kernel/drivers/$SETTINGS_NAME +fi + +mimeset ~/config/add-ons/kernel/busses/scsi/$MODULE_NAME +mimeset ~/config/settings/kernel/drivers/$SETTINGS_NAME + +INSTALLED_MESSAGE="The $MODULE_TITLE has been installed on your system.You have to reboot your system before using it." +answer=`alert "$INSTALLED_MESSAGE" "Edit settings" "Reboot" "OK"` +if [ $answer == "OK" ]; then + exit +elif [ $answer == "Reboot" ]; then + shutdown -r +fi + +StyledEdit /boot/home/config/settings/kernel/drivers/$SETTINGS_NAME diff --git a/src/add-ons/kernel/busses/scsi/usb/proto_bulk.c b/src/add-ons/kernel/busses/scsi/usb/proto_bulk.c new file mode 100644 index 0000000000..dc89975c25 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/proto_bulk.c @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ + +/** bulk-only protocol specific implementation */ + +/* References: + * USB Mass Storage Class specifications: + * http://www.usb.org/developers/data/devclass/usbmassover_11.pdf [1] + * http://www.usb.org/developers/data/devclass/usbmassbulk_10.pdf [2] + */ +#include "usb_scsi.h" + +#include "device_info.h" + +#include "proto_module.h" +#include "proto_common.h" +#include "proto_bulk.h" + +#include "usb_defs.h" + +#include /* strncpy */ + +/*Bulk-Only protocol specifics*/ +#define USB_REQ_MS_RESET 0xff /* Bulk-Only reset */ +#define USB_REQ_MS_GET_MAX_LUN 0xfe /* Get maximum lun */ + +/* Command Block Wrapper */ +typedef struct _usb_mass_CBW{ + uint32 signature; + uint32 tag; + uint32 data_transfer_len; + uint8 flags; + uint8 lun; + uint8 cdb_len; +#define CBW_CDB_LENGTH 16 + uint8 CDB[CBW_CDB_LENGTH]; +} usb_mass_CBW; /*sizeof(usb_mass_CBW) must be 31*/ +#define CBW_LENGTH 0x1f + +/* Command Status Wrapper */ +typedef struct _usb_mass_CSW{ + uint32 signature; + uint32 tag; + uint32 data_residue; + uint8 status; +} usb_mass_CSW; /*sizeof(usb_mass_CSW) must be 13*/ +#define CSW_LENGTH 0x0d + +#define CSW_STATUS_GOOD 0x0 +#define CSW_STATUS_FAILED 0x1 +#define CSW_STATUS_PHASE 0x2 + +#define CBW_SIGNATURE 0x43425355 +#define CSW_SIGNATURE 0x53425355 + +#define CBW_FLAGS_OUT 0x00 +#define CBW_FLAGS_IN 0x80 + +/*=========================== tracing helpers ==================================*/ +void trace_CBW(usb_device_info *udi, const usb_mass_CBW *cbw) +{ + char buf[sizeof(uint32) + 1] = {0}; + strncpy(buf, (char *)&cbw->signature, sizeof(uint32)); + PTRACE(udi, "\nCBW:{'%s'; tag:%d; data_len:%d; flags:0x%02x; lun:%d; cdb_len:%d;}\n", + buf, + cbw->tag, + cbw->data_transfer_len, + cbw->flags, + cbw->lun, + cbw->cdb_len); + udi->trace_bytes("CDB:\n", cbw->CDB, CBW_CDB_LENGTH); +} + +void trace_CSW(usb_device_info *udi, const usb_mass_CSW *csw) +{ + char buf[sizeof(uint32) + 1] = {0}; + strncpy(buf, (char *)&csw->signature, sizeof(uint32)); + PTRACE(udi, "CSW:{'%s'; tag:%d; residue:%d; status:0x%02x}\n", + buf, + csw->tag, + csw->data_residue, + csw->status); +} + +/** + \fn:get_max_luns + \param udi: device for wich max LUN info is requested + \return:always B_OK - if info was not retrieved max LUN is defaulted to 0 + + tries to retrieve the maximal Logical Unit Number supported by + this device. If device doesn't support GET_MAX_LUN request - single LUN is + assumed. ([2] 3.2) +*/ +static status_t +get_max_luns(usb_device_info *udi) +{ + status_t status = B_OK; + udi->max_lun = 0; + if(!HAS_FIXES(udi->properties, FIX_NO_GETMAXLUN)){ + size_t len = 0; + if(B_OK != (status = (*udi->usb_m->send_request)(udi->device, + USB_REQTYPE_INTERFACE_IN | USB_REQTYPE_CLASS, + USB_REQ_MS_GET_MAX_LUN, 0x0, udi->interface, + 0x1, &udi->max_lun, &len))) + { + if(status == B_DEV_STALLED){ + PTRACE_ALWAYS(udi, "get_max_luns[%d]:not supported. " + "Assuming single LUN available.\n", udi->dev_num); + } else { + PTRACE(udi, "get_max_luns[%d]:failed(%08x)." + "Assuming single LUN available.\n", udi->dev_num, status); + } + udi->max_lun = 0; + status = B_OK; + } /* else - all is OK - max luns info readed */ + } + return status; +} +/** + \fn:queue_bulk + \param udi: device for which que_bulk request is performed + \param buffer: data buffer, used in bulk i/o operation + \param len: length of data buffer + \param b_in: is "true" if input (device->host) data transfer, "false" otherwise + \return: status of operation. + + performs queue_bulk USB request for corresponding pipe and handle timeout of this + operation. +*/ +static status_t +queue_bulk(usb_device_info *udi, + void *buffer, + size_t len, + bool b_in) +{ + status_t status = B_OK; + usb_pipe pipe = b_in ? udi->pipe_in : udi->pipe_out; + status = (*udi->usb_m->queue_bulk)(pipe, buffer, len, bulk_callback, udi); + if(status != B_OK){ + PTRACE_ALWAYS(udi, "queue_bulk:failed:%08x\n", status); + } else { + status = acquire_sem_etc(udi->trans_sem, 1, B_RELATIVE_TIMEOUT, udi->trans_timeout/*LOCK_TIMEOUT*/); + if(status != B_OK){ + PTRACE_ALWAYS(udi, "queue_bulk:acquire_sem_etc failed:%08x\n", status); + (*udi->usb_m->cancel_queued_transfers)(pipe); + } + } + return status; +} +/** + \fn:check_CSW + \param udi:corresponding device info + \param csw: CSW to be checked for validity and meaningfullness + \param transfer_len: data transferred during operation, which is checked for status + \return: "true" if CSW valid and meanigfull, "false" otherwise + + checks CSW for validity and meaningfullness as required by USB mass strorge + BulkOnly specification ([2] 6.3) +*/ +static bool +check_CSW(usb_device_info *udi, + usb_mass_CSW *csw, + int transfer_len) +{ + bool is_valid = false; + do{ + /* check for CSW validity */ + if(udi->actual_len != CSW_LENGTH){ + PTRACE_ALWAYS(udi, "check_CSW:wrong length %d instead of %d\n", + udi->actual_len, CSW_LENGTH); + break;/* failed */ + } + if(csw->signature != CSW_SIGNATURE){ + PTRACE_ALWAYS(udi, "check_CSW:wrong signature %08x instead of %08x\n", + csw->signature, CSW_SIGNATURE); + break;/* failed */ + } + if(csw->tag != udi->tag - 1){ + PTRACE_ALWAYS(udi, "check_CSW:tag mismatch received:%d, awaited:%d\n", + csw->tag, udi->tag-1); + break;/* failed */ + } + /* check for CSW meaningfullness */ + if(CSW_STATUS_PHASE == csw->status){ + PTRACE_ALWAYS(udi, "check_CSW:not meaningfull: phase error\n"); + break;/* failed */ + } + if(transfer_len < csw->data_residue){ + PTRACE_ALWAYS(udi, "check_CSW:not meaningfull: " + "residue:%d is greater than transfer length:%d\n", + csw->data_residue, transfer_len); + break;/* failed */ + } + is_valid = true; + }while(false); + return is_valid; +} +/** + \fn:read_status + \param udi: corresponding device + \param csw: buffer for CSW data + \param transfer_len: data transferred during operation, which is checked for status + \return: success status code + + reads CSW from device as proposed in ([2] 5.3.3; Figure 2.). +*/ +static status_t +read_status(usb_device_info *udi, + usb_mass_CSW *csw, + int transfer_len) +{ + status_t status = B_ERROR; + int try = 0; + do{ + status = queue_bulk(udi, csw, CSW_LENGTH, true); + if(0 == try){ + if(B_OK != status || B_OK != udi->status){ + status = (*udi->usb_m->clear_feature)(udi->pipe_in, USB_FEATURE_ENDPOINT_HALT); + if(status != 0){ + PTRACE_ALWAYS(udi, "read_status:failed 1st try, " + "status:%08x; usb_status:%08x\n", status, udi->status); + (*udi->protocol_m->reset)(udi); + break; + } + continue; /* go to second try*/ + } + /* CSW was readed without errors */ + } else { /* second try */ + if(B_OK != status || B_OK != udi->status){ + PTRACE_ALWAYS(udi, "read_status:failed 2nd try status:%08x; usb_status:%08x\n", + status, udi->status); + (*udi->protocol_m->reset)(udi); + status = (B_OK == status) ? udi->status : status; + break; + } + } + if(!check_CSW(udi, csw, transfer_len)){ + (*udi->protocol_m->reset)(udi); + status = B_ERROR; + break; + } + trace_CSW(udi, csw); + break; /* CSW was read successfully */ + }while(try++ < 2); + return status; +} + +/*================= "standard" protocol procedures ==============================*/ + +/** + \fn:bulk_only_initialize + \param udi: device on wich we should perform initialization + \return:error code if initialization failed or B_OK if it passed + + initialize procedure for bulk only protocol devices. +*/ +status_t +bulk_only_initialize(usb_device_info *udi) +{ + status_t status = B_OK; + status = get_max_luns(udi); + return status; +} +/** + \fn:bulk_only_reset + \param udi: device on wich we should perform reset + \return:error code if reset failed or B_OK if it passed + + reset procedure for bulk only protocol devices. Tries to send + BulkOnlyReset USB request and clear USB_FEATURE_ENDPOINT_HALT features on + input and output pipes. ([2] 3.1) +*/ +status_t +bulk_only_reset(usb_device_info *udi) +{ + status_t status = B_ERROR; + status = (*udi->usb_m->send_request)(udi->device, + USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, + USB_REQ_MS_RESET, 0, + udi->interface, 0, 0, 0); + if(status != B_OK){ + PTRACE_ALWAYS(udi, "bulk_only_reset: reset request failed: %08x\n", status); + } + if(B_OK != (status = (*udi->usb_m->clear_feature)(udi->pipe_in, + USB_FEATURE_ENDPOINT_HALT))) + { + PTRACE_ALWAYS(udi, "bulk_only_reset: clear_feature on pipe_in failed: %08x\n", status); + } + if(B_OK != (status = (*udi->usb_m->clear_feature)(udi->pipe_out, + USB_FEATURE_ENDPOINT_HALT))) + { + PTRACE_ALWAYS(udi, "bulk_only_reset: clear_feature on pipe_out failed: %08x\n", status); + } + PTRACE(udi, "bulk_only_reset:%08x\n", status); + return status; +} +/** + \fn:bulk_only_transfer + \param udi: corresponding device + \param cmd: SCSI command to be performed on USB device + \param cmdlen: length of SCSI command + \param data_sg: io vectors array with data to transfer + \param sglist_count: count of entries in io vector array + \param transfer_len: overall length of data to be transferred + \param dir: direction of data transfer + \param ccbio: CCB_SCSIIO struct for original SCSI command + \param cb: callback to handle of final stage of command performing (autosense \ + request etc.) + + transfer procedure for bulk-only protocol. Performs SCSI command on USB device + [2] +*/ +void +bulk_only_transfer(usb_device_info *udi, + uint8 *cmd, + uint8 cmdlen, + //sg_buffer *sgb, + iovec *sg_data, + int32 sg_count, + int32 transfer_len, + EDirection dir, + CCB_SCSIIO *ccbio, + ud_transfer_callback cb) +{ + status_t status = B_OK; + status_t command_status = B_OK; + int32 residue = transfer_len; + usb_mass_CSW csw = {0}; + /* initialize and fill in Command Block Wrapper */ + usb_mass_CBW cbw = { + .signature = CBW_SIGNATURE, + .tag = atomic_add(&udi->tag, 1), + .data_transfer_len = transfer_len, + .flags = (dir == eDirIn) ? CBW_FLAGS_IN : CBW_FLAGS_OUT, + .lun = ccbio->cam_ch.cam_target_lun & 0xf, + .cdb_len = cmdlen, + }; + memcpy(cbw.CDB, cmd, cbw.cdb_len); + do{ + trace_CBW(udi, &cbw); + /* send CBW to device */ + status = queue_bulk(udi, &cbw, CBW_LENGTH, false); + if(status != B_OK || udi->status != B_OK){ + PTRACE_ALWAYS(udi, "bulk_only_transfer: queue_bulk failed:" + "status:%08x usb status:%08x\n", status, udi->status); + (*udi->protocol_m->reset)(udi); + command_status = B_CMD_WIRE_FAILED; + break; + } + /* perform data transfer if required */ + if(transfer_len != 0x0){ + status = process_data_io(udi, sg_data, sg_count, dir); + if(status != B_OK && status != B_DEV_STALLED){ + command_status = B_CMD_WIRE_FAILED; + break; + } + } + /* get status of command */ + status = read_status(udi, &csw, transfer_len); + if(B_OK != status){ + command_status = B_CMD_WIRE_FAILED; + break; + } + residue = csw.data_residue; + if(csw.status == CSW_STATUS_FAILED){ + command_status = B_CMD_FAILED; + }else{ + command_status = B_OK; + } + }while(false); + /* finalize transfer */ + cb(udi, ccbio, residue, command_status); +} + +protocol_module_info bulk_only_protocol_m = { + {0, 0, 0}, /* this is not a real kernel module - just interface */ + bulk_only_initialize, + bulk_only_reset, + bulk_only_transfer, +}; diff --git a/src/add-ons/kernel/busses/scsi/usb/proto_bulk.h b/src/add-ons/kernel/busses/scsi/usb/proto_bulk.h new file mode 100644 index 0000000000..9d2588462f --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/proto_bulk.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ + +/** bulk-only protocol "standard" procedures */ + + +#ifndef _PROTO_BULK_H_ + #define _PROTO_BULK_H_ + +#ifndef _PROTO_MODULE_H_ +#include "proto_module.h" +#endif /* _PROTO_MODULE_H_ */ + +extern protocol_module_info bulk_only_protocol_m; + +#endif /*_PROTO_BULK_H_*/ diff --git a/src/add-ons/kernel/busses/scsi/usb/proto_cbi.c b/src/add-ons/kernel/busses/scsi/usb/proto_cbi.c new file mode 100644 index 0000000000..6ffaa6de57 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/proto_cbi.c @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ + +/* References: + * USB Mass Storage Class specifications: + * http://www.usb.org/developers/data/devclass/usbmassover_11.pdf + * http://www.usb.org/developers/data/devclass/usbmass-ufi10.pdf + * http://www.usb.org/developers/data/devclass/usbmass-cbi10.pdf + */ + +#include + +#include "usb_scsi.h" + +#include "device_info.h" + +#include "proto_module.h" +#include "proto_common.h" +#include "proto_cbi.h" + +#include "usb_defs.h" + +#define USB_REQ_CBI_ADSC 0x00 + + +typedef struct _usb_mass_CBI_CB{ + uint8 op; + uint8 op2; + uint8 padding[14]; +} usb_mass_CBI_CB; + +#define CDB_LEN 16 +#define CDB_RESET_LEN 12 + +//typedef uint8 usb_mass_CDB[CDB_LEN]; + +typedef union _usb_mass_CBI_IDB{ + struct { + uint8 type; + uint8 value; + } common; + struct { + uint8 asc; + uint8 ascq; + } ufi; +} usb_mass_CBI_IDB; + +#define CBI_IDB_TYPE_CCI 0x00 +#define CBI_IDB_VALUE_PASS 0x00 +#define CBI_IDB_VALUE_FAIL 0x01 +#define CBI_IDB_VALUE_PHASE 0x02 +#define CBI_IDB_VALUE_PERSISTENT 0x03 +#define CBI_IDB_VALUE_STATUS_MASK 0x03 + +/** returns size of private protocol buffer */ +//int cbi_buffer_length(){ return sizeof(usb_mass_CBI_CB) + sizeof(usb_mass_CBI_IDB); } +/** casts private protocol buffer to CBI_IDB */ +/*#define IDB_BUFFER(__buff)\ + ((usb_mass_CBI_IDB*)(((uint8*)__buff) + sizeof(usb_mass_CBI_CB))) +*/ +/** casts private protocol buffer to CBI_CB */ +/*#define CB_BUFFER(__buff)\ + ((usb_mass_CBI_CB*)(__buff)) +*/ +void trace_CDB(usb_device_info *udi, const usb_mass_CBI_CB *cb, int len) +{ + PTRACE(udi, "CB:{op:0x%02x; op2:0x%02x;}\n", cb->op, cb->op2); + udi->trace_bytes(" padding:", cb->padding, len - 2); +} + +static status_t +send_request_adsc(usb_device_info *udi, + void *cb, + int length) +{ + status_t status = B_ERROR; + size_t len = 0; + trace_CDB(udi, cb, length); + status = (*udi->usb_m->send_request)(udi->device, + USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, + USB_REQ_CBI_ADSC, 0, + udi->interface, length, + cb, &len); + return status; +} + +static status_t +request_interrupt(usb_device_info *udi, + usb_mass_CBI_IDB *idb) +{ + status_t status = B_ERROR; + status = (*udi->usb_m->queue_interrupt)(udi->pipe_intr, idb, + sizeof(usb_mass_CBI_IDB), bulk_callback, udi); + if(status != B_OK){ + PTRACE(udi, "request_interrupt:failed:%08x\n", status); + } else { + status = acquire_sem_etc(udi->trans_sem, 1, B_RELATIVE_TIMEOUT, udi->trans_timeout/*LOCK_TIMEOUT*/); + if(status != B_OK){ + PTRACE(udi, "request_interrupt:acquire_sem_etc failed:%08x\n", status); + (*udi->usb_m->cancel_queued_transfers)(udi->pipe_intr); + } + } + udi->trace_bytes("Intr status:", (uint8*)idb, sizeof(usb_mass_CBI_IDB)); + return status; +} + +static status_t +parse_status(usb_device_info *udi, + usb_mass_CBI_IDB *idb) +{ + status_t command_status = B_OK; + if(CMDSET(udi->properties) == CMDSET_UFI){ + if(idb->ufi.asc == 0 && idb->ufi.ascq == 0){ + command_status = B_OK; + }else{ + command_status = B_CMD_FAILED; + } + } else { + if(idb->common.type == CBI_IDB_TYPE_CCI){ + switch(idb->common.value & CBI_IDB_VALUE_STATUS_MASK){ + case CBI_IDB_VALUE_PASS: + command_status = B_OK; + break; + case CBI_IDB_VALUE_FAIL: + case CBI_IDB_VALUE_PERSISTENT: + command_status = B_CMD_FAILED; + break; + case CBI_IDB_VALUE_PHASE: + default: + command_status = B_CMD_WIRE_FAILED; + break; + } + } /* else ?? */ + } + return command_status; +} + +/*================= "standard" protocol procedures ==============================*/ + +/** + \fn: + \param udi: ??? + \return:?? + + ?? +*/ +status_t +cbi_reset(usb_device_info *udi) +{ + status_t status = B_ERROR; + //usb_mass_CBI_CB *cb = CB_BUFFER(udi->proto_buf); + //usb_mass_CDB cdb = {0x1d, 0x04, 0x00}; + //memset(cdb + 2, 0xff, CDB_RESET_LEN - 2); + usb_mass_CBI_CB cb = { + .op = 0x1D, + .op2 = 0x04, + }; + memset(cb.padding , 0xff, sizeof(cb.padding)); + status = send_request_adsc(udi, &cb, CDB_RESET_LEN); + if(status != B_OK) + PTRACE_ALWAYS(udi, "command_block_reset: reset request failed: %08x\n", status); + + if(B_OK != (status = (*udi->usb_m->clear_feature)(udi->pipe_in, + USB_FEATURE_ENDPOINT_HALT))) + PTRACE_ALWAYS(udi, "command_block_reset: clear_feature on pipe_in failed: %08x\n", status); + + if(B_OK != (status = (*udi->usb_m->clear_feature)(udi->pipe_out, + USB_FEATURE_ENDPOINT_HALT))) + PTRACE_ALWAYS(udi, "command_block_reset: clear_feature on pipe_out failed: %08x\n", status); + PTRACE(udi, "command_block_reset:%08x\n", status); + + return status; +} + +/** + \fn: +*/ +status_t +cbi_initialize(usb_device_info *udi) +{ + status_t status = B_OK; + udi->max_lun = 0; + return status; +} + +/** + \fn:bulk_only_transfer + \param udi: ??? + \param cmd: ??? + \param cmdlen: ??? + \return:??? + + ??? +*/ +void +cbi_transfer(usb_device_info *udi, + uint8 *cmd, + uint8 cmdlen, + //sg_buffer *sgb, + iovec *sg_data, + int32 sg_count, + int32 transfer_len, + EDirection dir, + CCB_SCSIIO *ccbio, + ud_transfer_callback cb) +{ + status_t status = B_OK; + status_t command_status = B_OK; + int32 residue = transfer_len; + usb_mass_CBI_IDB idb = {{0}}; + do{ + status = send_request_adsc(udi, cmd, cmdlen); + if(status != B_OK){ + PTRACE(udi, "cbi_transfer:send command block failed: %08x\n", status); + if(status == B_DEV_STALLED){ + command_status = B_CMD_FAILED; + } else { + command_status = B_CMD_WIRE_FAILED; + (*udi->protocol_m->reset)(udi); + } + break; + } + if(transfer_len != 0){ + status = process_data_io(udi, sg_data, sg_count, dir); + if(status != B_OK){ + command_status = B_CMD_WIRE_FAILED; + break; + } + } + + if(PROTO(udi->properties) == PROTO_CBI){ + status = request_interrupt(udi, &idb); + PTRACE(udi, "cbi_transfer:request interrupt: %08x(%08x)\n", status, udi->status); + if(status != B_OK){ + command_status = B_CMD_WIRE_FAILED; + break; + } + if(udi->status == B_DEV_STALLED){ + } + command_status = parse_status(udi, &idb); + } else { /* PROP_CB ???*/ + command_status = B_CMD_UNKNOWN; + } + residue = 0; /* DEBUG!!!!!!!!!*/ + }while(false); + cb(udi, ccbio, residue, command_status); +} + +protocol_module_info cbi_protocol_m = { + {0, 0, 0}, /* this is not a real kernel module - just interface */ + cbi_initialize, + cbi_reset, + cbi_transfer, +}; diff --git a/src/add-ons/kernel/busses/scsi/usb/proto_cbi.h b/src/add-ons/kernel/busses/scsi/usb/proto_cbi.h new file mode 100644 index 0000000000..3121f923c1 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/proto_cbi.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ + +#ifndef _PROTO_CBI_H_ + #define _PROTO_CBI_H_ + +#ifndef _PROTO_MODULE_H_ +#include "proto_module.h" +#endif /* _PROTO_MODULE_H_ */ + +extern protocol_module_info cbi_protocol_m; + +#endif /*_PROTO_CBI_H_*/ diff --git a/src/add-ons/kernel/busses/scsi/usb/proto_common.c b/src/add-ons/kernel/busses/scsi/usb/proto_common.c new file mode 100644 index 0000000000..9c4e98836a --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/proto_common.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ + +#include + +#include "usb_scsi.h" + +#include "device_info.h" +#include "proto_common.h" +#include "tracing.h" +#include "usb_defs.h" +#include "scsi_commands.h" + +/** + \fn:bulk_callback + \param cookie:??? + \param status:??? + \param data:??? + \param actual_len:??? + \return:??? + + ??? +*/ +void bulk_callback(void *cookie, + uint32 status, + void *data, + uint32 actual_len) +{ + TRACE_BULK_CALLBACK(status, actual_len); + if(cookie){ + usb_device_info *udi = (usb_device_info *)cookie; + udi->status = status; + udi->data = data; + udi->actual_len = actual_len; + if(udi->status != B_CANCELED) + release_sem(udi->trans_sem); + } +} + +/** + \fn:exec_io + \param udi: ??? + \return:??? + + ??? +*/ +status_t process_data_io(usb_device_info *udi, + //sg_buffer *sgb, + iovec *sg_data, int32 sg_count, + EDirection dir) +{ + status_t status = B_OK; + usb_pipe pipe = (dir == eDirIn) ? udi->pipe_in : udi->pipe_out; +// TRACE_DATA_IO_SG(data_sg, sglist_count); + status = (*udi->usb_m->queue_bulk_v)(pipe, sg_data, sg_count, bulk_callback, udi); + if(status == B_OK){ + status = acquire_sem_etc(udi->trans_sem, 1, B_RELATIVE_TIMEOUT, udi->trans_timeout/*LOCK_TIMEOUT*/); + if(status == B_OK){ + status = udi->status; + if(udi->status == B_DEV_STALLED){ + status_t st=(*udi->usb_m->clear_feature)(pipe, USB_FEATURE_ENDPOINT_HALT); + TRACE_ALWAYS("clear_on_STALL:%08x\n",st); + } + }else{ + TRACE_ALWAYS("process_data_io:acquire_sem failed:%08x\n", status); + (*udi->usb_m->cancel_queued_transfers)(pipe); + } + } else { + TRACE_ALWAYS("process_data_io:queue_bulk_v failed:%08x\n", status); + } + TRACE_DATA_IO("process_data_io:processed:%d;status:%08x\n", udi->actual_len, status); + return status; +} + +void transfer_callback(struct _usb_device_info *udi, + CCB_SCSIIO *ccbio, + int32 residue, + status_t status) +{ + ccbio->cam_resid = residue; + switch(status){ + case B_OK: + ccbio->cam_ch.cam_status = CAM_REQ_CMP; + break; + case B_CMD_FAILED: + case B_CMD_UNKNOWN:{ + size_t sense_data_len = (0 != ccbio->cam_sense_len) ? + ccbio->cam_sense_len : SSD_MIN_SIZE; + uchar *sense_data_ptr = (NULL != ccbio->cam_sense_ptr) ? + ccbio->cam_sense_ptr : (uchar*)&udi->autosense_data; + uint8 lun = ((ccbio->cam_ch.cam_target_lun) << CMD_LUN_SHIFT) & CMD_LUN; + scsi_cmd_generic_6 cmd = { REQUEST_SENSE, {lun, 0}, sense_data_len, 0}; + /* transform command as required by protocol */ + uint8 *rcmd = udi->scsi_command_buf; + uint8 rcmdlen = sizeof(udi->scsi_command_buf); + iovec sense_sg = { sense_data_ptr, sense_data_len }; + TRACE("transfer_callback:requesting sense information " + "due status:%08x\n", status); + memset(&udi->autosense_data, 0, SSD_FULL_SIZE); /* just to be sure */ + if(B_OK != (*udi->transform_m->transform)(udi, (uint8 *)&cmd, sizeof(cmd), &rcmd, &rcmdlen)){ + TRACE_ALWAYS("transfer_callback: REQUEST SENSE command transform failed\n"); + ccbio->cam_ch.cam_status = CAM_IDE; //????????? + break; + } + /* transfer command to device. SCSI status will be handled in callback */ + (*udi->protocol_m->transfer)(udi, rcmd, rcmdlen, &sense_sg, 1, sense_data_len, + eDirIn, ccbio, sense_callback); + } + break; + case B_CMD_WIRE_FAILED: + ccbio->cam_ch.cam_status = CAM_REQ_CMP_ERR; + break; + default: + TRACE_ALWAYS("transfer_callback:unknown status:%08x\n", status); + ccbio->cam_ch.cam_status = CAM_IDE; + break; + } +} + +void sense_callback(struct _usb_device_info *udi, + CCB_SCSIIO *ccbio, + int32 residue, + status_t status) +{ + ccbio->cam_sense_resid = residue; + switch(status){ + case B_CMD_UNKNOWN: + case B_CMD_FAILED: + case B_OK:{ + bool b_own_data = (ccbio->cam_sense_ptr == NULL); + scsi_sense_data *sense_data = b_own_data ? + &udi->autosense_data : (scsi_sense_data *)ccbio->cam_sense_ptr; + int data_len = (ccbio->cam_sense_len != 0) ? ccbio->cam_sense_len : SSD_MIN_SIZE; + TRACE_SENSE_DATA((uint8*)sense_data, data_len); + if((sense_data->flags & SSD_KEY) == SSD_KEY_NO_SENSE){ + /* no problems. normal case for CB handling */ + TRACE("sense_callback: key OK\n"); + ccbio->cam_ch.cam_status = CAM_REQ_CMP; + } else { + if(!b_own_data){ /* we have used CCBIO provided buffer for sense data */ + TRACE("sense_callback:sense info OK????:%08x \n", sense_data); + ccbio->cam_ch.cam_status = CAM_REQ_CMP_ERR | CAM_AUTOSNS_VALID; + ccbio->cam_scsi_status = SCSI_STATUS_CHECK_CONDITION; + } else { + /*TODO: ?????????????????????????????????????? */ + ccbio->cam_ch.cam_status = CAM_REQ_CMP; + // ccbio->cam_ch.cam_status = CAM_REQ_CMP_ERR /*| CAM_AUTOSNS_VALID*/; + // ccbio->cam_scsi_status = SCSI_STATUS_CHECK_CONDITION; + TRACE("sense_callback: sense still not handled...\n"); + } + } + } + break; + default: + TRACE_ALWAYS("sense_callback:unknown status:%08x\n", status); + case B_CMD_WIRE_FAILED: + ccbio->cam_ch.cam_status = CAM_AUTOSENSE_FAIL; + break; + } +} + diff --git a/src/add-ons/kernel/busses/scsi/usb/proto_common.h b/src/add-ons/kernel/busses/scsi/usb/proto_common.h new file mode 100644 index 0000000000..f1ea0f2d2e --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/proto_common.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ +#ifndef _PROTO_COMMON_H_ + #define _PROTO_COMMON_H_ + +#ifndef _DEVICE_INFO_H_ + #include "device_info.h" +#endif /* _DEVICE_INFO_H_ */ + +void bulk_callback(void *cookie, + uint32 status, + void *data, + uint32 actual_len); + +status_t process_data_io(usb_device_info *udi, iovec *sg_data, int32 sg_count/*sg_buffer *sgb*/, EDirection dir); + +void transfer_callback(usb_device_info *udi, + CCB_SCSIIO *ccbio, + int32 residue, + status_t status); +void sense_callback(usb_device_info *udi, + CCB_SCSIIO *ccbio, + int32 residue, + status_t status); +#endif /*_PROTO_COMMON_H_*/ diff --git a/src/add-ons/kernel/busses/scsi/usb/proto_module.h b/src/add-ons/kernel/busses/scsi/usb/proto_module.h new file mode 100644 index 0000000000..6cc87d2981 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/proto_module.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ +#ifndef _PROTO_MODULE_H_ + #define _PROTO_MODULE_H_ + +#ifndef _MODULE_H + #include +#endif /*_MODULE_H*/ + +/*#ifndef _SG_BUFFER_H_ + #include "sg_buffer.h" +#endif / *_SG_BUFFER_H_*/ + +enum { + /* B_OK */ /* JFYI:command is OK */ + B_CMD_FAILED = B_ERRORS_END + 1, /* command failed */ + B_CMD_WIRE_FAILED, /* device problems */ + B_CMD_UNKNOWN, /* command state unknown */ +}; + +typedef enum{ + eDirNone = 0, + eDirIn, + eDirOut, +} EDirection; + +struct _usb_device_info; /* forward, we can be included from device_info.h */ + +typedef void (*ud_transfer_callback)(struct _usb_device_info *udi, + CCB_SCSIIO *ccbio, + int32 residue, + status_t status); + +typedef struct { + module_info module; + + status_t (*init)(struct _usb_device_info *udi); + status_t (*reset)(struct _usb_device_info *udi); + void (*transfer)(struct _usb_device_info *udi, + uint8 *cmd, uint8 cmdlen, + //sg_buffer *sgb, + iovec *sg_data, + int32 sg_count, + int32 transfer_len, + EDirection dir, + CCB_SCSIIO *ccbio, + ud_transfer_callback cb); +} protocol_module_info; + + +typedef struct { + module_info module; + + status_t (*transform)(struct _usb_device_info *udi, + uint8 *cmd, uint8 len, + uint8 **rcmd, uint8 *rlen); +} transform_module_info; + +#define MODULE_PREFIX "generic/usb_scsi_extensions/" +#define PROTOCOL_SUFFIX "/protocol/v1" +#define TRANSFORM_SUFFIX "/transform/v1" +#define PROTOCOL_MODULE_MASK MODULE_PREFIX"%s"PROTOCOL_SUFFIX +#define TRANSFORM_MODULE_MASK MODULE_PREFIX"%s"TRANSFORM_SUFFIX + +/** + \define:_TRACE_ALWAYS + trace always - used mainly for error messages +*/ +#define PTRACE_ALWAYS(__udi, __x...) \ + { /*if(__udi->b_trace)*/ __udi->trace(true, __x); } +/** + \define:TRACE + trace only if logging is activated +*/ +#define PTRACE(__udi, __x...) \ + { if(__udi->b_trace) __udi->trace(false, __x); } + +#endif /* _PROTO_MODULE_H_ */ diff --git a/src/add-ons/kernel/busses/scsi/usb/scsi_commands.h b/src/add-ons/kernel/busses/scsi/usb/scsi_commands.h new file mode 100644 index 0000000000..ecc3e2528d --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/scsi_commands.h @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ + +/** definitions for SCSI commands, structures etc. */ + +#ifndef _SCSI_COMMANDS_H_ + #define _SCSI_COMMANDS_H_ + +/* References: + * http://www.t10.org/ftp/t10/drafts/rbc/rbc-r10a.pdf + * http://www.t10.org/ftp/t10/drafts/rbc/rbc-a101.pdf + * http://www.t10.org/ftp/t10/drafts/s2/s2-r10l.pdf + * http://www.t10.org/ftp/t10/drafts/cam/cam-r12b.pdf + * http://www.qic.org/html/standards/15x.x/qic157d.pdf + * + * http://www.usb.org/developers/data/devclass/usbmass-ufi10.pdf + */ + +#define CAM_DIR_MASK (CAM_DIR_IN | CAM_DIR_OUT | CAM_DIR_NONE ) + +/* SCSI status defines */ +#define SCSI_STATUS_OK 0x00 +#define SCSI_STATUS_CHECK_CONDITION 0x02 + +/* SCSI command opcodes */ +#define READ_6 0x08 +#define WRITE_6 0x0a +#define READ_10 0x28 +#define WRITE_10 0x2a +#define MODE_SELECT_6 0x15 +#define MODE_SENSE_6 0x1a +#define MODE_SELECT_10 0x55 +#define MODE_SENSE_10 0x5a +#define READ_CAPACITY 0x25 +#define TEST_UNIT_READY 0x00 +#define START_STOP_UNIT 0x1b + +/* come from UFI specs */ +#define FORMAT_UNIT 0x04 +#define INQUIRY 0x12 +/*#define START_STOP_UNIT 0x1b +#define MODE_SELECT 0x55 +#define MODE_SENSE 0x5a */ +#define PREVENT_ALLOW_MEDIA_REMOVAL 0x1e +#define READ_10 0x28 +#define READ_12 0xa8 +/*#define READ_CAPACITY 0x25*/ +#define READ_FORMAT_CAPACITY 0x23 +#define REQUEST_SENSE 0x03 +#define REZERO_UNIT 0x01 +#define SEEK_10 0x2b +#define SEND_DIAGNOSTICS 0x1d +/*#define TEST_UNIT_READY 0x00*/ +#define VERIFY 0x2f +#define WRITE_10 0x2a +#define WRITE_12 0xaa +#define WRITE_AND_VERIFY 0x2e +/* end of UFI commands*/ + +/* come from ATAPI specs*/ +/*#define FORMAT_UNIT 0x04 +#define INQUIRY 0x12 +#define MODE_SELECT 0x55 +#define MODE_SENSE 0x5a +#define PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e +#define READ_10 0x28 +#define READ_12 0xa8 +#define READ_CAPACITY 0x25 +#define READ_FORMAT_CAPACITIES 0x23 +#define REQUEST_SENSE 0x03 +#define SEEK 0x2b +#define START_STOP_UNIT 0x1b +#define TEST_UNIT_READY 0x00 +#define VERIFY 0x2f +#define WRITE_10 0x2a +#define WRITE_12 0xaa +#define WRITE_AND_VEIRIFY 0x2e */ +#define PAUSE_RESUME 0x4b +#define PLAY_AUDIO 0x45 +#define PLAY_AUDIO_MSF 0x47 +#define REWIND 0x01 +#define PLAY_AUDIO_TRACK 0x48 + +/* end of ATAPI commands*/ + +/* come from MMC2 specs */ +#define READ_BUFFER 0x3c +#define READ_SUBCHANNEL 0x42 +#define READ_TOC 0x43 +#define READ_HEADER 0x44 +#define READ_DISK_INFO 0x51 +#define READ_TRACK_INFO 0x52 +#define SEND_OPC 0x54 +#define READ_MASTER_CUE 0x59 +#define CLOSE_TR_SESSION 0x5b +#define READ_BUFFER_CAP 0x5c +#define SEND_CUE_SHEET 0x5d +#define BLANK 0xa1 +#define EXCHANGE_MEDIUM 0xa6 +#define READ_DVD_STRUCTURE 0xad +#define DVD_REPORT_KEY 0xa4 +#define DVD_SEND_KEY 0xa3 +#define SET_CD_SPEED 0xbb +#define GET_CONFIGURATION 0x46 +/* end of MMC2 specs */ + +/* come from RBC specs */ +/*#define FORMAT_UNIT 0x04 +#define INQUIRY 0x12 +#define MODE_SELECT_6 0x15 +#define MODE_SENSE_6 0x1a*/ +#define PERSISTENT_RESERVE_IN 0x5e +#define PERSISTENT_RESERVE_OUT 0x5f +/*#define PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e +#define READ_10 0x28 +#define READ_CAPACITY 0x25*/ +#define RELEASE_6 0x17 +/*#define REQUEST_SENSE 0x03*/ +#define RESERVE_6 0x16 +/*#define START_STOP_UNIT 0x1b*/ +#define SYNCHRONIZE_CACHE 0x35 +/*#define TEST_UNIT_READY 0x00 +#define VERIFY_10 0x2f +#define WRITE_10 0x2a*/ +#define WRITE_BUFFER 0x3b +/* end of RBC commands */ + +/* come from QIC-157 specvs */ +#define ERASE 0x19 +/*#define INQUIRY 0x12*/ +#define LOAD_UNLOAD 0x1b +#define LOCATE 0x2b +#define LOG_SELECT 0x4c +#define LOG_SENSE 0x4d +/*#define MODE_SELECT 0x15 +#define MODE_SENSE 0x1a +#define READ 0x08*/ +#define READ_POSITION 0x34 +/*#define REQUEST_SENSE 0x03*/ +#define REWIND 0x01 +#define SPACE 0x11 +/*#define TEST_UNIT_READY 0x00 +#define WRITE 0x0a*/ +#define WRITE_FILEMARK 0x10 +/* end of QIC-157 */ + +/* SCSI commands layout*/ +/* generic commands layout*/ +typedef struct{ + uint8 opcode; + uint8 bytes[11]; +}scsi_cmd_generic; +/* six-bytes command*/ +typedef struct{ + uint8 opcode; + uint8 addr[3]; +#define CMD_GEN_6_ADDR 0x1f /* mask used for addr field*/ +#define CMD_LUN 0xE0 /* mask used for LUN */ +#define CMD_LUN_SHIFT 0x05 /* shift for LUN */ + uint8 len; + uint8 ctrl; +}scsi_cmd_generic_6; +/* ten-bytes command*/ +typedef struct{ + uint8 opcode; + uint8 byte2; + uint8 addr[4]; + uint8 reserved; + uint8 len[2]; + uint8 ctrl; +}scsi_cmd_generic_10; +/* twelve-bytes command*/ +typedef struct{ + uint8 opcode; + uint8 byte2; + uint8 addr[4]; + uint8 len[4]; + uint8 reserved; + uint8 ctrl; +}scsi_cmd_generic_12; +/* READ_6 / WRITE_6 */ +typedef scsi_cmd_generic_6 scsi_cmd_rw_6; +/* READ_10 / WRITE_10 */ +typedef struct{ + uint8 opcode; + uint8 byte2; +#define CMD_RW_10_RELADDR 0x01 +#define CMD_RW_10_FUA 0x08 +#define CMD_RW_10_DPO 0x10 + uint8 addr[4]; + uint8 reserved; + uint8 len[2]; + uint8 ctrl; +}scsi_cmd_rw_10; +/* MODE_SELECT_6 */ +typedef struct{ + uint8 opcode; + uint8 byte2; +#define CMD_MSEL_6_SP 0x01 +#define CMD_MSEL_6_PF 0x10 + uint8 reserved[2]; + uint8 len; + uint8 ctrl; +}scsi_cmd_mode_select_6; +/* MODE_SELECT_10 */ +typedef struct{ + uint8 opcode; + uint8 byte2; +#define CMD_MSEL_10_SP 0x01 +#define CMD_MSEL_10_PF 0x10 + uint8 reserved[5]; + uint8 len[2]; + uint8 ctrl; +}scsi_cmd_mode_select_10; +/* MODE_SENSE_6 */ +typedef struct{ + uint8 opcode; + uint8 byte2; +#define CMD_MSENSE_6_DBD 0x08 + uint8 byte3; +#define CMD_MSENSE_6_PC 0x0c + uint8 reserved; + uint8 len; + uint8 ctrl; +}scsi_cmd_mode_sense_6; +typedef struct{ + uint8 mode_data_len; + uint8 medium_type; + uint8 device_spec_params; + uint8 block_descr_len; +}scsi_mode_param_header_6; +/* MODE_SENSE_10 */ +typedef struct{ + uint8 opcode; + uint8 byte2; +#define CMD_MSENSE_10_DBD 0x08 + uint8 byte3; +#define CMD_MSENSE_10_PC 0x0c + uint8 reserved[4]; + uint8 len[2]; + uint8 ctrl; +}scsi_cmd_mode_sense_10; +typedef struct{ + uint8 mode_data_len[2]; + uint8 medium_type; + uint8 device_spec_params; + uint8 reserved1; + uint8 reserved2; + uint8 block_descr_len[2]; +}scsi_mode_param_header_10; +/* TEST_UNIT_READY */ +typedef struct{ + uint8 opcode; + uint8 byte2; + uint8 reserved[3]; + uint8 ctrl; +}scsi_cmd_test_unit_ready; +/* START_STOP_UNIT */ +typedef struct{ + uint8 opcode; + uint8 byte2; +#define CMD_SSU_IMMED 0x01 + uint8 reserved[2]; + uint8 start_loej; +#define CMD_SSU_LOEJ 0x02 +#define CMD_SSU_START 0x01 + uint8 ctrl; +}scsi_cmd_start_stop_unit; + +/* SCSI REQUEST SENSE data. See 8.2.14*/ +typedef struct _scsi_sense_data{ + uint8 error_code; +#define SSD_ERRCODE 0x7F +#define SSD_CURRENT_ERROR 0x70 +#define SSD_DEFERRED_ERROR 0x71 +#define SSD_ERRCODE_VALID 0x80 + uint8 segment; + uint8 flags; +#define SSD_KEY 0x0F +#define SSD_KEY_NO_SENSE 0x00 +#define SSD_KEY_RECOVERED_ERROR 0x01 +#define SSD_KEY_NOT_READY 0x02 +#define SSD_KEY_MEDIUM_ERROR 0x03 +#define SSD_KEY_HARDWARE_ERROR 0x04 +#define SSD_KEY_ILLEGAL_REQUEST 0x05 +#define SSD_KEY_UNIT_ATTENTION 0x06 +#define SSD_KEY_DATA_PROTECT 0x07 +#define SSD_KEY_BLANK_CHECK 0x08 +#define SSD_KEY_Vendor_Specific 0x09 +#define SSD_KEY_COPY_ABORTED 0x0a +#define SSD_KEY_ABORTED_COMMAND 0x0b +#define SSD_KEY_EQUAL 0x0c +#define SSD_KEY_VOLUME_OVERFLOW 0x0d +#define SSD_KEY_MISCOMPARE 0x0e +#define SSD_KEY_RESERVED 0x0f +#define SSD_ILI 0x20 +#define SSD_EOM 0x40 +#define SSD_FILEMARK 0x80 + uint8 info[4]; + uint8 extra_len; + uint8 cmd_spec_info[4]; + uint8 add_sense_code; + uint8 add_sense_code_qual; + uint8 fru; + uint8 sense_key_spec[3]; +#define SSD_SCS_VALID 0x80 +#define SSD_FIELDPTR_CMD 0x40 +#define SSD_BITPTR_VALID 0x08 +#define SSD_BITPTR_VALUE 0x07 +#define SSD_MIN_SIZE 18 + uint8 extra_bytes[14]; +#define SSD_FULL_SIZE sizeof(struct _scsi_sense_data) +}scsi_sense_data; + +#endif /*_SCSI_COMMANDS_H_*/ diff --git a/src/add-ons/kernel/busses/scsi/usb/settings.c b/src/add-ons/kernel/busses/scsi/usb/settings.c new file mode 100644 index 0000000000..cc013fb485 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/settings.c @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ + +/** driver settings support implementation */ + +#include "usb_scsi.h" +#include "settings.h" +//#include "proto_common.h" + +#include /* strtoul */ +#include /* strncpy */ +#include +#include "tracing.h" + +#define DEF_DEVS 2 /**< default amount of reserved devices */ +#define S_DEF_DEVS "2" /**< default amount of reserved devices */ +#define DEF_LUNS 4 /**< default amount of reserved LUNs */ +#define S_DEF_LUNS "4" /**< default amount of reserved LUNs */ +/** count of device entries, to be reserved for fake devices */ +int reserved_devices = DEF_DEVS; +/** count of Logical Unit Numbers, to be reserved for fake devices */ +int reserved_luns = DEF_LUNS; + +bool b_reservation_on = true; +bool b_ignore_sysinit2 = false; +/** + support of some kind rudimentary "quick" search. Indexes in + settings_keys array. +*/ +enum SKKeys{ + skkVendor = 0, + skkDevice, +// skkName, +// skkTransport, + skkProtocol, + skkCommandSet, + skkFakeInq, + skk6ByteCmd, + skkTransTU, + skkNoTU, + skkNoGetMaxLUN, + skkNoPreventMedia, + skkUseModeSense10, + skkForceReadOnly, + skkProtoBulk, + skkProtoCB, + skkProtoCBI, +// skkProtoFreecom, + skkCmdSetSCSI, + skkCmdSetUFI, + skkCmdSetATAPI, + skkCmdSetRBC, + skkCmdSetQIC157, + + skkKeysCount, +// skkTransportBase = skkSubClassSCSI, + skkProtoBegin = skkProtoBulk, + skkProtoEnd = skkProtoCBI, + skkCmdSetBegin = skkCmdSetSCSI, + skkCmdSetEnd = skkCmdSetQIC157, +}; +/** + helper struct, used in our "quick" search algorithm +*/ +struct _settings_key{ + union _hash{ + char name[32]; + uint16 key; + }hash; + uint32 property; +}settings_keys[] = { /**< array of keys, used in our settings files */ + {{"vendor" }, 0}, /* MUST BE SYNCHRONISED WITH skk*** indexes!!! */ + {{"device" }, 0}, +// {{"name" }, 0}, +// {{"transport"}, 0}, + {{"protocol"}, 0}, + {{"commandset"}, 0}, + {{"fake_inquiry" }, 0}, + {{"use_rw6_byte_cmd" }, 0}, + {{"trans_test_unit" }, 0}, + {{"no_test_unit" }, 0}, + {{"no_get_max_lun"}, 0}, + {{"no_prevent_media"}, 0}, + {{"use_mode_sense_10"}, 0}, + {{"force_read_only"}, 0}, + {{"BULK" }, PROTO_BULK_ONLY}, + {{"CB" }, PROTO_CB}, + {{"CBI" }, PROTO_CBI}, +// {{"Freecom"}, PROTO_FREECOM}, + {{"SCSI" }, CMDSET_SCSI}, + {{"UFI" }, CMDSET_UFI}, + {{"ATAPI" }, CMDSET_ATAPI}, + {{"RBC" }, CMDSET_RBC}, + {{"QIC157" }, CMDSET_QIC157}, +}; +/** + \define:SK_EQUAL + checks is the __name parameter correspond to value, pointed by __id index + in settings_keys array. The magic of our "quick" search algorithm =-)) +*/ +#define CAST_SK(__name) (*(uint16 *)(__name)) +#define SK_EQUAL(__name, __id) ((CAST_SK(__name) == (settings_keys[__id].hash.key)) && \ + (0 == strcmp(__name, settings_keys[__id].hash.name))) +/** + \fn:load_module_settings + loads driver settings from extarnal settings file through BeOS driver + settings API. Called on initialization of the module +*/ +void load_module_settings() +{ + void *sh = load_driver_settings(MODULE_NAME); + if(sh){ + load_log_settings(sh); + /* devices "reservation". Workaround for plug-n-play device attaching*/ + reserved_devices = strtoul(get_driver_parameter(sh, "reserve_devices", + S_DEF_DEVS, S_DEF_DEVS), NULL, 0); + reserved_luns = strtoul(get_driver_parameter(sh, "reserve_luns", + S_DEF_LUNS, S_DEF_LUNS), NULL, 0); + b_ignore_sysinit2 = get_driver_boolean_parameter(sh, "ignore_sysinit2", + b_ignore_sysinit2, false); + if(reserved_devices > MAX_DEVICES_COUNT) + reserved_devices = MAX_DEVICES_COUNT; + if(reserved_luns > MAX_LUNS_COUNT) + reserved_luns = MAX_LUNS_COUNT; + b_reservation_on = (reserved_devices != 0); + + unload_driver_settings(sh); + } else { + TRACE("settings:load:file '%s' was not found. Using default setting...\n", + MODULE_NAME); + } +} +/** + \fn:strncpy_value + \param to: buffer for copied string + \param dp: driver_parameter, from wich copied string come + \param size: maximal size of copied string + copies a string, containing value[0] of this parameter, from driver_parameter, + pointed by dp, to buffer pointed by to. Semantic of this function is similar + to standard strncpy() one. +*/ +/*static void +strncpy_value(char *to, driver_parameter *dp, size_t size) +{ + to[0] = 0; + if(dp->value_count > 0){ + strncpy(to, dp->values[0], size); + } +}*/ +/** + \fn:parse_transport + \param dp: driver_parameter, containing device transport information + \return: a bitmasked value from PROP_-defined flags for USB subclass and \ + protocol + parse the transport driver_parameter for known USB subclasses, protocols and + compose a bitmasked value from those settings +*/ +static uint32 +parse_transport(driver_parameter *dp, + int skkBase, int skkEnd, + uint32 vendor_prop, char *vendor_prop_name) +{ + uint32 ret = 0; + if(dp->value_count > 0){ + char *value = dp->values[0]; + int skkIdx = skkBase; + for(; skkIdx <= skkEnd; skkIdx++){ + if(SK_EQUAL(value, skkIdx)){ + ret |= settings_keys[skkIdx].property; + break; + } + } /* for(...) enumerate protocol and commandset keys */ + if(skkIdx > skkEnd){ /* not found - assume vendor prop */ + ret |= vendor_prop; + strncpy(vendor_prop_name, value, VENDOR_PROP_NAME_LEN); + } + if(dp->value_count > 1){ + TRACE("settings:parse_transport:accept '%s', ignore extra...\n", value); + } + } + return ret; +} +/** + \fn:lookup_device_info + \param product_id: product id of device to be checked for private settings + \param dp: driver_parameter, containing device information + \param udd: on return contains name,protocol etc. information about device + \return: "true" if private settings for device found - "false" otherwise + looks through device parameter, pointed by dp, obtains the name and other + parameters of private device settings if available +*/ +static bool +lookup_device_info(uint16 product_id, + driver_parameter *dp, + usb_device_settings *uds) +{ + bool b_found = false; + if(dp){ + int i = 0; + for(; i < dp->value_count; i++){ + uint16 id = strtoul(dp->values[0], NULL, 0) & 0xffff; + if(product_id == id){ + int prm = 0; + uds->product_id = product_id; + for(; prm < dp->parameter_count; prm++){ +/* if(SK_EQUAL(dp->parameters[prm].name, skkName)){ + strncpy_value(udd->product_name, &dp->parameters[prm], INQ_PRODUCT_LEN); + } else*/ +/* if(SK_EQUAL(dp->parameters[prm].name, skkTransport)){ + udd->properties |= parse_transport(&dp->parameters[prm]); + } else*/ + if(SK_EQUAL(dp->parameters[prm].name, skkProtocol)){ + uds->properties |= parse_transport(&dp->parameters[prm], + skkProtoBegin, skkProtoEnd, + PROTO_VENDOR, + uds->vendor_protocol); + } else + if(SK_EQUAL(dp->parameters[prm].name, skkCommandSet)){ + uds->properties |= parse_transport(&dp->parameters[prm], + skkCmdSetBegin, skkCmdSetEnd, + CMDSET_VENDOR, + uds->vendor_commandset); + } else + if(SK_EQUAL(dp->parameters[prm].name, skkFakeInq)){ + uds->properties |= FIX_NO_INQUIRY; + } else + if(SK_EQUAL(dp->parameters[prm].name, skk6ByteCmd)){ + uds->properties |= FIX_FORCE_RW_TO_6; + } else + if(SK_EQUAL(dp->parameters[prm].name, skkTransTU)){ + uds->properties |= FIX_TRANS_TEST_UNIT; + } else + if(SK_EQUAL(dp->parameters[prm].name, skkNoTU)){ + uds->properties |= FIX_NO_TEST_UNIT; + } else + if(SK_EQUAL(dp->parameters[prm].name, skkNoPreventMedia)){ + uds->properties |= FIX_NO_PREVENT_MEDIA; + } else + if(SK_EQUAL(dp->parameters[prm].name, skkUseModeSense10)){ + uds->properties |= FIX_FORCE_MS_TO_10; + } else + if(SK_EQUAL(dp->parameters[prm].name, skkForceReadOnly)){ + uds->properties |= FIX_FORCE_READ_ONLY; + } else + if(SK_EQUAL(dp->parameters[prm].name, skkNoGetMaxLUN)){ + uds->properties |= FIX_NO_GETMAXLUN; + } else { + TRACE("settings:device:ignore unknown parameter:%s\n", + dp->parameters[prm].name); + } + } /* for(...) enumerate device parameters */ + b_found = true; + break; + } /* if(product_id == id){ */ + } /*enumerate parameter values (product ids) */ + } /* if(dp) */ + return b_found; +} +/** + \fn:lookup_vendor_info + \param vendor_id: vendor id of device to be checked for private settings + \param product_id: product id of device to be checked for private settings + \param dp: driver_parameter, containing vendor information + \param udd: on return contains name, protocol etc. information about device + \return: "true" if private settings for device found - "false" otherwise + looks through vendor parameter, pointed by dp, obtains the name of vendor and + device information if available +*/ +static bool +lookup_vendor_info(uint16 vendor_id, + uint16 product_id, + driver_parameter *dp, + usb_device_settings *uds) +{ + bool b_found = false; + if(dp && dp->value_count > 0 && dp->values[0]){ + uint16 id = strtoul(dp->values[0], NULL, 0) & 0xffff; + if(vendor_id == id){ + int i = 0; + for( i = 0; i < dp->parameter_count; i++){ + if(!b_found && SK_EQUAL(dp->parameters[i].name, skkDevice)){ + b_found = lookup_device_info(product_id, &dp->parameters[i], uds); + } /*else + if(SK_EQUAL(dp->parameters[i].name, skkName)){ + strncpy_value(udd->vendor_name, &dp->parameters[i], INQ_VENDOR_LEN); + } */else { + TRACE("settings:vendor:ignore unknown parameter:%s\n", + dp->parameters[i].name); + } + } /*for(...) enumerate "vendor" parameters*/ + } /*if(vendor_id == id){*/ + } /* if(dp && ... etc */ + return b_found; +} +/** + \fn:lookup_device_settings + \param vendor_id: vendor id of device to be checked for private settings + \param product_id: product id of device to be checked for private settings + \param udd: on return contains name,protocol etc. information about device + \return: "true" if private settings for device found - "false" otherwise + looks through driver settings file for private device description and load it + if available into struct pointed by udd +*/ +bool lookup_device_settings(const usb_device_descriptor *udd, + usb_device_settings *uds) +{ + bool b_found = false; + if(uds){ + void *sh = load_driver_settings(MODULE_NAME); + if(sh){ + const driver_settings *ds = get_driver_settings(sh); + if(ds){ + int i = 0; + for(i = 0; i < ds->parameter_count; i++){ + if(SK_EQUAL(ds->parameters[i].name, skkVendor)){ + b_found = lookup_vendor_info(udd->vendor_id, + udd->product_id, + &ds->parameters[i], uds); + if(b_found){ + uds->vendor_id = udd->vendor_id; + break; //we've got it - stop enumeration. + } + } + } /*for(...) - enumerate "root" parameters*/ + } /* if(ds) */ + unload_driver_settings(sh); + } /* if(sh) */ + if(b_found){ + //TRACE("settings:loaded settings:'%s(%04x)/%s(%04x)/%08x'\n", + TRACE("settings:loaded settings:'%04x/%04x/%08x'\n", + /*descr->vendor_name,*/ uds->vendor_id, + /*descr->product_name,*/ + uds->product_id, uds->properties); + } + } /* if(descr)*/ + return b_found; +} diff --git a/src/add-ons/kernel/busses/scsi/usb/settings.h b/src/add-ons/kernel/busses/scsi/usb/settings.h new file mode 100644 index 0000000000..10cb13c551 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/settings.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ + +/** driver settings support definitions */ + +#ifndef _USB_SCSI_SETTINGS_H_ + #define _USB_SCSI_SETTINGS_H_ + +void load_module_settings(); + +typedef struct{ + uint16 vendor_id; + uint16 product_id; + uint32 properties; +#define VENDOR_PROP_NAME_LEN 0x08 + char vendor_protocol[VENDOR_PROP_NAME_LEN + 1]; + char vendor_commandset[VENDOR_PROP_NAME_LEN + 1]; +}usb_device_settings; + +bool lookup_device_settings(const usb_device_descriptor *udd, + usb_device_settings *uds); + +extern int reserved_devices; +extern int reserved_luns; +extern bool b_reservation_on; +extern bool b_ignore_sysinit2; + +#endif /*_USB_SCSI_SETTINGS_H_*/ diff --git a/src/add-ons/kernel/busses/scsi/usb/sg_buffer.c b/src/add-ons/kernel/busses/scsi/usb/sg_buffer.c new file mode 100644 index 0000000000..0952192e73 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/sg_buffer.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ + +/** handling SCSI data-buffer (both usual "plain" and scatter/gather ones) */ + +#include + +#include "usb_scsi.h" + +#include +#include "tracing.h" +#include "sg_buffer.h" + +/** + \fn:init_sg_buffer + TODO!!! +*/ +status_t +init_sg_buffer(sg_buffer *sgb, CCB_SCSIIO *ccbio) +{ + status_t status = B_NO_INIT; + if(0 != sgb){ + memset(sgb, 0, sizeof(sg_buffer)); + /* setup scatter/gather if exists in CCBIO*/ + if(ccbio->cam_ch.cam_flags & CAM_SCATTER_VALID) { + sgb->piov = (iovec *) ccbio->cam_data_ptr; + sgb->count = ccbio->cam_sglist_cnt; + } else { + sgb->iov.iov_base = (iovec *) ccbio->cam_data_ptr; + sgb->iov.iov_len = ccbio->cam_dxfer_len; + sgb->piov = &sgb->iov; + sgb->count = 1; + } + status = B_OK; + } else { + TRACE_ALWAYS("init_sg_buffer fatal: not initialized!\n"); + } + return status; +} + +/** + \fn:alloc_sg_buffer + TODO!!! +*/ +status_t +realloc_sg_buffer(sg_buffer *sgb, size_t size) +{ + status_t status = B_NO_INIT; + if(0 != sgb){ + /* NOTE: no check for previously allocations! May be dangerous!*/ + void *ptr = malloc(size); + status = (0 != ptr) ? B_OK : B_NO_MEMORY; + if(B_OK == status) { + memset(ptr, 0, size); + sgb->iov.iov_base = (iovec *)ptr; + sgb->iov.iov_len = size; + sgb->piov = &sgb->iov; + sgb->count = 1; + sgb->b_own = true; + status = B_OK; + } + } else { + TRACE_ALWAYS("realloc_sg_buffer fatal: not initialized!\n"); + } + return status; +} + +status_t +sg_access_byte(sg_buffer *sgb, off_t offset, uchar *byte, bool b_set) +{ + status_t status = B_ERROR; + int i = 0; + for(; i < sgb->count; i++){ + if(offset >= sgb->piov[i].iov_len){ + offset -= sgb->piov[i].iov_len; + } else { + uchar *ptr = (uchar *)sgb->piov[i].iov_base; + if(b_set){ + ptr[offset] = *byte; + }else{ + *byte = ptr[offset]; + } + status = B_OK; + break; + } + } + return status; +} + +status_t +sg_memcpy(sg_buffer *d_sgb, off_t d_offset, + sg_buffer *s_sgb, off_t s_offset, size_t size) +{ + status_t status = B_NO_INIT; + while(0 != d_sgb && 0 != s_sgb){ + uchar *d_ptr = 0; + uchar *s_ptr = 0; + status = B_ERROR; + if(1 == d_sgb->count){ + d_ptr = d_sgb->piov->iov_base + d_offset; + if((d_offset + size) > d_sgb->piov->iov_len){ + TRACE_ALWAYS("sg_memcpy fatal: dest buffer overflow: has:%d req:%d\n", + d_sgb->piov->iov_len, d_offset + size); + break; + } + } + if(1 == s_sgb->count){ + s_ptr = s_sgb->piov->iov_base + s_offset; + if((s_offset + size) > s_sgb->piov->iov_len){ + TRACE_ALWAYS("sg_memcpy fatal: src buffer overflow: has:%d req:%d\n", + s_sgb->piov->iov_len, s_offset + size); + break; + } + } + if(0 != d_ptr && 0 != s_ptr){ + memcpy(d_ptr, s_ptr, size); + } else { + uchar byte = 0; + int i = 0; + for(; i < size; i++){ + status = sg_access_byte(s_sgb, s_offset + i, &byte, false); + if(B_OK == status) + status = sg_access_byte(d_sgb, d_offset + i, &byte, true); + if(B_OK != status){ + TRACE_ALWAYS("sg_memcpy fatal: dest:%d src:%d size:%d/%d\n", + d_offset, s_offset, i, size); + break; + } + } + } + status = B_OK; + break; + } + if(B_NO_INIT == status) + TRACE_ALWAYS("sg_memcpy fatal: not initialized"); + return status; +} + +/** + \fn:free_sg_buffer + TODO!!! +*/ +void +free_sg_buffer(sg_buffer *sgb) +{ + if(0 != sgb && sgb->b_own){ + int i = 0; + for(; i < sgb->count; i++){ + free(sgb->piov[i].iov_base); + } + memset(sgb, 0, sizeof(sg_buffer)); + } +} + +status_t +sg_buffer_len(sg_buffer *sgb, size_t *size) +{ + status_t status = B_NO_INIT; + if(0!=sgb && 0!=size){ + int i = 0; + *size = 0; + for(; i < sgb->count; i++){ + *size += sgb->piov[i].iov_len; + } + status = B_OK; + } else { + TRACE_ALWAYS("sg_buffer_len fatal: not initialized (sgb:%x/size:%x)", sgb, size); + } + return status; +} diff --git a/src/add-ons/kernel/busses/scsi/usb/sg_buffer.h b/src/add-ons/kernel/busses/scsi/usb/sg_buffer.h new file mode 100644 index 0000000000..50c685e8e7 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/sg_buffer.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ + +/** handling SCSI data-buffer (both usual "plain" and scatter/gather ones) */ + +#ifndef _SG_BUFFER_H_ + #define _SG_BUFFER_H_ + +#ifndef _IOVEC_H + #include +#endif/*_IOVEC_H*/ + +/** + \struct:_sg_buffer +*/ +typedef struct _sg_buffer{ + iovec iov; /**< to avoid extra memory allocations */ + iovec *piov; /**< ptr to scatter/gather list, default is equal to &iov */ + int count; /**< count of scatter/gather vector entries */ + bool b_own; /**< was allocated - must be freed */ +} sg_buffer; + +#define member_offset(__type, __member) ((size_t)&(((__type *)0)->__member)) +#define member_size(__type, __member) sizeof(((__type *)0)->__member) + +status_t init_sg_buffer(sg_buffer *sgb, CCB_SCSIIO *ccbio); +status_t realloc_sg_buffer(sg_buffer *sgb, size_t size); +status_t sg_buffer_len(sg_buffer *sgb, size_t *size); +status_t sg_access_byte(sg_buffer *sgb, off_t offset, uchar *byte, bool b_set); +status_t sg_memcpy(sg_buffer *dest_sgb, off_t dest_offset, + sg_buffer *src_sgb, off_t src_offset, size_t size); +void free_sg_buffer(sg_buffer *sgb); + +#endif /*_SG_BUFFER_H_*/ diff --git a/src/add-ons/kernel/busses/scsi/usb/tracing.c b/src/add-ons/kernel/busses/scsi/usb/tracing.c new file mode 100644 index 0000000000..c530dbe412 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/tracing.c @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ + +/** tracing support implementation */ + +#include "usb_scsi.h" +#include "tracing.h" + +#include +#include /* posix file i/o - create, write, close */ +#include +#include +#include + +/** private log path name */ +static const char *private_log_path = "/var/log/"MODULE_NAME".log"; + +static const char *log_port_name = MODULE_NAME"-logging"; + +#ifdef BUILD_LOG_DAEMON + +int main(int argc, char**argv) +{ + if(B_NAME_NOT_FOUND == find_port(log_port_name)){ + bool b_screen = (argc > 1); + port_id pid = create_port(1000, log_port_name); + while(true){ + int32 code; + char buffer[1024 + 1]; + size_t sz = read_port_etc(pid, &code, buffer, 1024, B_TIMEOUT, 1000 * 1000); + if(sz != B_TIMED_OUT){ + if(b_screen){ + buffer[sz] = 0; + printf(buffer); + } else { + FILE *f = fopen(private_log_path, "a"); + fwrite(buffer, sz, 1, f); + fclose(f); + } + } + } + } + return 0; +} + +#else /* BUILD_LOG_DAEMON */ + +/** is activity logging on or off? */ +#if DEBUG +bool b_log = true; +#else +bool b_log = false; +#endif +/** logging in private file */ +bool b_log_file = false; +/** appending logs to previous log sessions */ +bool b_log_append = false; +/** log SCSI commands */ +bool b_log_scsi_cmd = false; +/** log USB bulk callback function activity */ +bool b_log_bulk_cb = false; + +bool b_log_protocol = false; +//bool b_log_CSW = false; +//bool b_log_CDB = false; +bool b_log_data_processing = false; +bool b_log_sense_data = false; +/** log time at wich logging event occured */ +static bool b_log_time = false; +/** log thread id from wich logging performed */ +static bool b_log_thid = false; +/** log thread name from wich logging performed */ +static bool b_log_thname = false; +/** semaphore id used to synchronizing logging requests */ +//static sem_id loglock; +/** log result of READ_CAPACITY command */ +bool b_log_capacity = false; + +/** + \fn: load_log_settings + \param sh: driver_settings handle + called from main driver settings loading procedure to load log-related + parameters +*/ +void +load_log_settings(void *sh) +{ + if(sh){ +#if !DEBUG + b_log = get_driver_boolean_parameter(sh, "debug_output", b_log, true); +#endif + b_log_file = get_driver_boolean_parameter(sh, "debug_output_in_file", + b_log_file, true); + b_log_append = ! get_driver_boolean_parameter(sh, "debug_output_file_rewrite", + !b_log_append, true); + b_log_time = get_driver_boolean_parameter(sh, "debug_trace_time", + b_log_time, false); + b_log_thid = get_driver_boolean_parameter(sh, "debug_trace_threadid", + b_log_thid, false); + b_log_thname = get_driver_boolean_parameter(sh, "debug_trace_thread_name", + b_log_thname, false); + b_log_scsi_cmd = get_driver_boolean_parameter(sh, "debug_trace_commands", + b_log_scsi_cmd, false); + b_log_bulk_cb = get_driver_boolean_parameter(sh, "debug_trace_bulk_callback", + b_log_bulk_cb, false); + b_log_protocol = get_driver_boolean_parameter(sh, "debug_trace_protocol", + b_log_protocol, false); + b_log_data_processing = + get_driver_boolean_parameter(sh, "debug_trace_data_io", + b_log_data_processing, false); + b_log_sense_data = + get_driver_boolean_parameter(sh, "debug_trace_sense_data", + b_log_sense_data, false); + b_log_capacity = get_driver_boolean_parameter(sh, "debug_trace_capacity", + b_log_capacity, false); + if(!b_log_file){ /* some information is already in system log entries */ + b_log_thid = false; + b_log_thname = false; + } + } +} +/** + \fn: create_log + called to [re]create private log file +*/ +void +create_log() +{ + int flags = O_WRONLY | O_CREAT | ((!b_log_append) ? O_TRUNC : 0); + if(b_log_file){ + close(open(private_log_path, flags, 0666)); + } +} + +/** + \fn: usb_scsi_trace + \param b_force: if true - output message ignoring current logging state + \param fmt: format string used in message formatting + \param ...: variable argument used in message formatting + formats and traces messages to current debug output target. +*/ +void +usb_scsi_trace(bool b_force, const char *fmt, ...) +{ + if(b_force || b_log){ + va_list arg_list; + static char *prefix = "\33[35m"MODULE_NAME":\33[0m"; + static char buf[1024]; + char *buf_ptr = buf; + port_id pid = find_port(log_port_name); + bool b_no_port = (pid == B_NAME_NOT_FOUND); + if(!b_log_file || b_no_port){ /* it's not a good idea to add prefix in private file */ + strcpy(buf, prefix); + buf_ptr += strlen(prefix); + } + if(b_log_time){ /* add time of logging this string */ + bigtime_t time = system_time(); + uint32 msec = time / 1000; + uint32 sec = msec / 1000; + sprintf(buf_ptr, "%02ld.%02ld.%03ld:", sec / 60, sec % 60, msec % 1000); + buf_ptr += strlen(buf_ptr); + } + if(b_log_thid){ /* add id of the calling thread */ + thread_id tid = find_thread(0); + thread_info tinfo = {0}; + if(b_log_thname){ /* add name of the calling thread */ + get_thread_info(tid, &tinfo); + } + sprintf(buf_ptr, "['%s':%lx]:", tinfo.name, tid); + buf_ptr += strlen(buf_ptr); + } + va_start(arg_list, fmt); + vsprintf(buf_ptr, fmt, arg_list); + va_end(arg_list); + if(b_log_file && !b_no_port){ /* write in private log file */ + if(B_OK != write_port_etc(pid, 0, buf, strlen(buf), B_TIMEOUT, 0)) + dprintf(buf); + } else /* write in system log*/ + dprintf(buf); + } +} +/** + \fn: trace_CCB_HEADER + \param ccbh: struct to be traced + traces CCB_HEADER struct to current debug output target +*/ +void +usb_scsi_trace_CCB_HEADER(const CCB_HEADER *ccbh) +{ + TRACE("CCB_HEADER:%08x\n" + " phys_addr:%ld\n" + " cam_ccb_len:%d\n" + " cam_func_code:%02x\n" + " cam_status:%02x\n" + " cam_hrsvd0:%02x\n" + " cam_path_id:%02x\n" + " cam_target_id:%02x\n" + " cam_target_lun:%02x\n" + " cam_flags:%08x\n", + ccbh, + ccbh->phys_addr, + ccbh->cam_ccb_len, + ccbh->cam_func_code, + ccbh->cam_status, + ccbh->cam_hrsvd0, + ccbh->cam_path_id, + ccbh->cam_target_id, + ccbh->cam_target_lun, + ccbh->cam_flags); +} +/** + \fn: trace_CCB_SCSIIO + \param ccbio: struct to be traced + traces CCB_SCSIIO struct to current debug output target +*/ +void +usb_scsi_trace_CCB_SCSIIO(const CCB_SCSIIO *ccbio) +{ + TRACE("CCB_SCSIIO:%08x\n", ccbio); + usb_scsi_trace_CCB_HEADER(&ccbio->cam_ch); + TRACE(" cam_pdrv_ptr:%08x\n" + " cam_next_ccb:%08x\n" + " cam_req_map:%08x\n" + " (*cam_cbfcnp):%08x\n" + " cam_data_ptr:%08x\n" + " cam_dxfer_len:%ld\n" + " cam_sense_ptr:%08x\n" + " cam_sense_len:%d\n" + " cam_cdb_len:%d\n" + " cam_sglist_cnt:%d\n" + " cam_sort:%d\n" + " cam_scsi_status:%02x\n" + " cam_sense_resid:%d\n" + " cam_resid:%d\n" + " cam_timeout:%d\n" + " cam_msg_ptr:%08x\n" + " cam_msgb_len:%d\n" + " cam_vu_flags:%04x\n" + " cam_tag_action:%d\n", + ccbio->cam_pdrv_ptr, + ccbio->cam_next_ccb, + ccbio->cam_req_map, + ccbio->cam_cbfcnp, + ccbio->cam_data_ptr, + ccbio->cam_dxfer_len, + ccbio->cam_sense_ptr, + ccbio->cam_sense_len, + ccbio->cam_cdb_len, + ccbio->cam_sglist_cnt, + ccbio->cam_sort, + ccbio->cam_scsi_status, + ccbio->cam_sense_resid, + ccbio->cam_resid, + ccbio->cam_timeout, + ccbio->cam_msg_ptr, + ccbio->cam_msgb_len, + ccbio->cam_vu_flags, + ccbio->cam_tag_action); + + usb_scsi_trace_bytes("CDB_UN:\n", ccbio->cam_cdb_io.cam_cdb_bytes, IOCDBLEN); +} +/** + \fn: usb_scsi_command_trace + \param b_hlight: highlight command and prefix it with spec. charachter + \param cmd: array of bytes to be traced. typically pointer SCSI command buffer + \param cmdlen: size of buffer in cmd parameter + traces SCSI commands into debug output target.can highlight and prefix the + text with special charachter and color for two different types + of commands. +*/ +void +usb_scsi_trace_command(bool b_hlight, const uint8 *cmd, size_t cmdlen) +{ + size_t len = min(cmdlen, 12); /* command length watchdog */ + char hl_mask[] = "\33[%sCMD:\33[0m"; + char prefix[sizeof(hl_mask) + 6]; + if(b_log_file){ /* compose CMD prefix */ + sprintf(prefix, "%sCMD:", b_hlight ? "=>":""); + } else { + sprintf(prefix, hl_mask, b_hlight ? "33m=>":"32m"); + } + usb_scsi_trace_bytes(prefix, cmd, len); /* append command bytes to log */ +} +/** + \fn:usb_scsi_bytes_trace + \param bytes:array of bytes to be traced. + \param bytes_len: size of buffer in bytes parameter + traces buffer bytes one by one into debug output target. +*/ +void +usb_scsi_trace_bytes(const char *prefix, const uint8 *bytes, size_t bytes_len) +{ + size_t len = min(bytes_len, 0x100); /* length watchdog */ + char truncTail[] = "\n"; + char *pbuf = (char *)malloc(len * 3 + sizeof(truncTail) + strlen(prefix) + 1); + if(pbuf){ + size_t i = 0; + char *p = pbuf; + strcpy(p, prefix); + p += strlen(prefix); + for(;i < len; i++){ + sprintf(p, " %02x", bytes[i]); + p += strlen(p); + } + /* user should be informed about truncation too*/ + strcpy(p, (len < bytes_len) ? truncTail : "\n"); + TRACE(pbuf); + free(pbuf); + } else { + TRACE_ALWAYS("usb_scsi_trace_bytes:error allocate " + "memory for tracing %d bytes\n", len); + } +} + +void usb_scsi_trace_sgb(const char *prefix, sg_buffer *sgb) +{ + char sgbHead[] = "SGB:"; + size_t i = 0; + size_t len = strlen(prefix) + strlen(sgbHead) + sgb->count * 9; + char *sgbPrefix = (char*)malloc(len); + if(0 != sgbPrefix){ + sg_buffer sgb_own; + size_t sgb_len = 0; + char *p = sgbPrefix; + strcpy(p, prefix); + p += strlen(p); + strcpy(p, sgbHead); + p += strlen(p); + i = 0; + for(; i < sgb->count; i++){ + sprintf(p, "%lX,", sgb->piov[i].iov_len); + sgb_len += sgb->piov[i].iov_len; + p += strlen(p); + } + if(B_OK == realloc_sg_buffer(&sgb_own, sgb_len)){ + sg_memcpy(&sgb_own, 0, sgb, 0, sgb_len); + /* assume non-fragmented memory */ + usb_scsi_trace_bytes(sgbPrefix, sgb_own.piov->iov_base, sgb_own.piov->iov_len); + free_sg_buffer(&sgb_own); + } else { + TRACE_ALWAYS("usb_scsi_trace_sgb:error allocate sgb for %d bytes\n", sgb_len); + } + } else { + TRACE_ALWAYS("usb_scsi_trace_sgb:error allocate memory for %d bytes\n", len); + } +} + +void usb_scsi_trace_SG(iovec *sg, int count) +{ + char sg_mask[] = "SG:{%s}\n"; + char truncTail[] = ""; + size_t trunc_count = min(count, 0x20); /* length watchdog */ + size_t len = sizeof(sg_mask) + sizeof(truncTail) + trunc_count * 16; + char *pbuf = (char *)malloc(len + 1); + if(pbuf){ + int i = 0; + char *p = pbuf; + for(; i < trunc_count; i++){ + sprintf(p, (!i) ? "%d" : ", %d", sg[i].iov_len); + p += strlen(p); + } + /* user should be informed about truncation too*/ + if(trunc_count < count) + strcpy(p, truncTail); + + TRACE(sg_mask, pbuf); + free(pbuf); + } else { + TRACE_ALWAYS("usb_scsi_trace_SG:error allocate " + "memory for tracing %d SG entries\n", trunc_count); + } +} + +#endif /* BUILD_LOG_DAEMON */ diff --git a/src/add-ons/kernel/busses/scsi/usb/tracing.h b/src/add-ons/kernel/busses/scsi/usb/tracing.h new file mode 100644 index 0000000000..5a1ab6c17d --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/tracing.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ + +/** tracing support definitions */ + +#ifndef _USB_SCSI_TRACING_H_ + #define _USB_SCSI_TRACING_H_ + +#ifndef _SG_BUFFER_H_ + #include "sg_buffer.h" +#endif /*_SG_BUFFER_H_*/ + +void load_log_settings(void *sh); +void create_log(); +void usb_scsi_trace(bool b_force, const char *fmt, ...); + +/* non-switchable tracng functions */ +void usb_scsi_trace_bytes(const char *prefix, const uint8 *bytes, size_t bytes_len); +void usb_scsi_trace_sgb(const char *prefix, sg_buffer *sgb); +void usb_scsi_trace_CCB_HEADER(const CCB_HEADER *ccb); +void usb_scsi_trace_CCB_SCSIIO(const CCB_SCSIIO *ccbio); + +/* ---------------------- Generic tracing --------------------------------------- */ +/** + \define:TRACE_ALWAYS + trace always - used mainly for error messages +*/ +#define TRACE_ALWAYS(x...) \ + usb_scsi_trace(true, x) +/** + \define:TRACE + trace only if logging is activated +*/ +#define TRACE(x...) \ + usb_scsi_trace(false, x) + +/* ---------------------- SCSI commands tracing -------------------------------- */ +extern bool b_log_scsi_cmd; +void usb_scsi_trace_command(bool b_hlight, const uint8 *cmd, size_t cmdlen); +/** + \define:TRACE_SCSI_COMMAND + trace SCSI command +*/ +#define TRACE_SCSI_COMMAND(cmd, cmdlen)\ + { if(b_log_scsi_cmd) usb_scsi_trace_command(false, cmd, cmdlen); } +/** + \define:TRACE_SCSI_COMMAND_HLIGHT + trace SCSI command and prefixes it with special sign. Used for tracing + commands internally converted by this module. +*/ +#define TRACE_SCSI_COMMAND_HLIGHT(cmd, cmdlen)\ + { if(b_log_scsi_cmd) usb_scsi_trace_command(true, cmd, cmdlen); } + +/* ---------------------- USB callback tracing -------------------------------- */ +/** + \define:TRACE_BULK_CALLBACK + trace the bulk_callback procedures data and status flow. +*/ +extern bool b_log_bulk_cb; +#define TRACE_BULK_CALLBACK(stat, len)\ + { if(b_log_bulk_cb) TRACE("B_CB:status:%08x;length:%d\n", stat, len); } + +/* --------------- USB mass storage commands tracing --------------------------- */ +extern bool b_log_protocol; +/* --------------------------- data i/o tracing -------------------------------- */ +extern bool b_log_data_processing; +void usb_scsi_trace_SG(iovec *sg, int count); +/** + \define:TRACE_DATA_IO + trace the information about amount processed data and status of process. +*/ +#define TRACE_DATA_IO(x...)\ + { if(b_log_data_processing) usb_scsi_trace(false, x); } +#define TRACE_DATA_IO_SG(sg, cnt)\ + { if(b_log_data_processing) usb_scsi_trace_SG(sg, cnt); } + +extern bool b_log_sense_data; +/** + \define:TRACE_SENSE_DATA + trace the information REQUEST SENSE data. +*/ +#define TRACE_SENSE_DATA(data, len)\ + { if(b_log_sense_data) usb_scsi_trace_bytes("SENSE:", data, len); } +#define TRACE_MODE_SENSE_DATA(prefix, data, len)\ + { if(b_log_sense_data) usb_scsi_trace_bytes(prefix, data, len); } +#define TRACE_MODE_SENSE_SGB(prefix, data)\ + { if(b_log_sense_data) usb_scsi_trace_sgb(prefix, data); } + +extern bool b_log_capacity; +#define TRACE_CAPACITY(prefix, data)\ + { if(b_log_capacity) usb_scsi_trace_sgb(prefix, data); } + +#endif /*_USB_SCSI_TRACING_H_*/ diff --git a/src/add-ons/kernel/busses/scsi/usb/transform_procs.c b/src/add-ons/kernel/busses/scsi/usb/transform_procs.c new file mode 100644 index 0000000000..f0b8721469 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/transform_procs.c @@ -0,0 +1,476 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ + +/** SCSI commands transformations support */ + +#include "usb_scsi.h" + +#include "device_info.h" +#include "transform_procs.h" +#include "tracing.h" +#include "scsi_commands.h" +//#include "proto_common.h" +#include "settings.h" + +#define UFI_COMMAND_LEN 12 +#define ATAPI_COMMAND_LEN 12 + +/** + \fn:transform_6_to_10 + \param cmd: SCSI command buffer to be transformed + \param len: length of buffer, pointed by cmd parameter + \param rcmd: a place for buffer pointer with transformed command + \param rlen: a place for length of transformed command + \return: true if transformation was performed + transforms a 6-byte command to 10-byte one if required.Transformed command is + returned in rcmd parameter. In case if no transformation was performed the return + buffer is untouched. +*/ +static bool transform_6_to_10(uint8 *cmd, + uint8 len, + uint8 **rcmd, + uint8 *rlen) +{ + bool transformed = true; + scsi_cmd_generic_6 *from = (scsi_cmd_generic_6 *)cmd; + memset(*rcmd, 0, *rlen); + switch (from->opcode){ + case READ_6: + case WRITE_6:{ + scsi_cmd_rw_10 *to = (scsi_cmd_rw_10 *)(*rcmd); + to->opcode = (from->opcode == READ_6) ? READ_10 : WRITE_10; + memcpy(to->addr + 1, from->addr, 3); + to->byte2 = from->addr[0]; + to->byte2 &= ~CMD_GEN_6_ADDR; + to->addr[1] &= CMD_GEN_6_ADDR; + to->len[1] = from->len; + to->ctrl = from->ctrl; + if(0 == from->len){ /* special case! in 6-byte R/W commands */ + to->len[0] = 1; /* the length 0x00 assume transfering 0x100 blocks! */ + } + }break; + case MODE_SENSE_6: + case MODE_SELECT_6:{ + scsi_cmd_generic_10 *to = (scsi_cmd_generic_10 *)(*rcmd); + if(from->opcode == MODE_SENSE_6){ + to->opcode = MODE_SENSE_10; + ((scsi_cmd_mode_sense_10 *)to)->byte3 = + ((scsi_cmd_mode_sense_6 *)from)->byte3; + }else + to->opcode = MODE_SELECT_10; + to->byte2 = from->addr[0]; + to->len[1] = from->len + 4; /*TODO: hardcoded length*/ + to->ctrl = from->ctrl; + }break; + default:{ /* no transformation needed */ + transformed = false; + }break; + } + return transformed; +} +/** + \fn:transform_cmd_6_to_10 + \param udi: usb_device_info object for wich transformation is requested + \param cmd: SCSI command buffer to be transformed + \param len: length of buffer, pointed by cmd parameter + \param rcmd: a place for buffer pointer with transformed command + \param rlen: a place for length of transformed command + \return: true if transformation was performed + transforms a 6-byte command to 10-byte depending on information provided with + udi object. +*/ +static bool transform_cmd_6_to_10(usb_device_info *udi, + uint8 *cmd, + uint8 len, + uint8 **rcmd, + uint8 *rlen) +{ + bool transformed = true; + scsi_cmd_generic_6 *from = (scsi_cmd_generic_6 *)cmd; + switch (from->opcode){ + case READ_6: + case WRITE_6:{ +// if(!(HAS_FEATURES(udi->descr.properties, PROP_FORCE_TO_6))){ + if(!HAS_FIXES(udi->properties, FIX_FORCE_RW_TO_6)){ + if((transformed = transform_6_to_10(cmd, len, rcmd, rlen)) == true) + *rlen = 10; + }else + transformed = false; + }break; + case MODE_SENSE_6: + case MODE_SELECT_6:{ +// if(HAS_FEATURES(udi->descr.properties, PROP_USE_MODESENSE_10)){ + if(HAS_FIXES(udi->properties, FIX_FORCE_MS_TO_10)){ + if((transformed = transform_6_to_10(cmd, len, rcmd, rlen)) == true) + *rlen = 10; + }else + transformed = false; + } + } + return transformed; +} +/** + \fn:transform_cmd_test_unit_ready + \param udi: usb_device_info object for wich transformation is requested + \param cmd: SCSI command buffer to be transformed + \param len: length of buffer, pointed by cmd parameter + \param rcmd: a place for buffer pointer with transformed command + \param rlen: a place for length of transformed command + \return: true if transformation was performed + transforms a TEST_UNIT_COMAND SCSI command to START_STOP_UNIT one depending + on properties provided with udi object. +*/ +static bool transform_cmd_test_unit_ready(usb_device_info *udi, + uint8 *cmd, + uint8 len, + uint8 **rcmd, + uint8 *rlen) +{ + bool transformed = false; + if(HAS_FIXES(udi->properties, FIX_TRANS_TEST_UNIT)){ + scsi_cmd_start_stop_unit *command = (scsi_cmd_start_stop_unit *)(*rcmd); + memset(*rcmd, 0, *rlen); + command->opcode = START_STOP_UNIT; + command->start_loej = CMD_SSU_START; + *rlen = 6; + transformed = true; + } + return transformed; +} +/** + \fn:scsi_transform + \param udi: usb_device_info object for wich transformation is requested + \param cmd: SCSI command buffer to be transformed + \param len: length of buffer, pointed by cmd parameter + \param rcmd: a place for buffer pointer with transformed command + \param rlen: a place for length of transformed command + \return: B_OK if transformation was successfull, B_ERROR otherwise + this is the "transformation procedure" for transparent SCSI (0x06) USB subclass.It + performs all SCSI commands transformations required by this protocol. Additionally + it tries to make some workarounds for "brocken" USB devices. If no transformation + was performed resulting command buffer points to original one. +*/ +status_t +scsi_transform(usb_device_info *udi, + uint8 *cmd, + uint8 len, + uint8 **rcmd, + uint8 *rlen) +{ + status_t status = B_OK; + bool transformed = false; + scsi_cmd_generic *command = (scsi_cmd_generic *)cmd; + TRACE_SCSI_COMMAND(cmd, len); + switch(command->opcode){ + case READ_6: + case WRITE_6: + case MODE_SENSE_6: + case MODE_SELECT_6: + transformed = transform_cmd_6_to_10(udi, cmd, len, rcmd, rlen); + break; + case TEST_UNIT_READY: + transformed = transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen); + break; + default: break; + } + if(!transformed){ /* transformation was not required */ + *rcmd = cmd; + *rlen = len; + }else + TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen); + return status; +} +/** + \fn:rbc_transform + \param udi: usb_device_info object for wich transformation is requested + \param cmd: SCSI command buffer to be transformed + \param len: length of buffer, pointed by cmd parameter + \param rcmd: a place for buffer pointer with transformed command + \param rlen: a place for length of transformed command + \return: B_OK if transformation was successfull, B_ERROR otherwise + this is the "transformation procedure" for RBC USB subclass (0x01).It + performs all SCSI commands transformations required by this protocol. Additionally + it tries to make some workarounds for "brocken" USB devices. If no transformation + was performed resulting command buffer points to original one. +*/ +status_t rbc_transform(usb_device_info *udi, + uint8 *cmd, + uint8 len, + uint8 **rcmd, + uint8 *rlen) +{ + status_t status = B_OK; + bool transformed = false; + scsi_cmd_generic *command = (scsi_cmd_generic *)cmd; + TRACE_SCSI_COMMAND(cmd, len); + switch(command->opcode){ + case TEST_UNIT_READY: + transformed = transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen); + break; + case READ_6: + case WRITE_6: /* there are no such command in list of allowed - transform*/ + transformed = transform_cmd_6_to_10(udi, cmd, len, rcmd, rlen); + break; + case FORMAT_UNIT: /* TODO: all following ones are not checked against specs !!!*/ + case INQUIRY: /*TODO: check !!! */ + case MODE_SELECT_6: /*TODO: check !!! */ + case MODE_SENSE_6: /*TODO: check !!! */ + case PERSISTENT_RESERVE_IN: /*TODO: check !!! */ + case PERSISTENT_RESERVE_OUT: /*TODO: check !!! */ + case PREVENT_ALLOW_MEDIA_REMOVAL: /*TODO: check !!! */ + case READ_10: /*TODO: check !!! */ + case READ_CAPACITY: /*TODO: check !!! */ + case RELEASE_6: /*TODO: check !!! */ + case REQUEST_SENSE: /*TODO: check !!! */ + case RESERVE_6: /*TODO: check !!! */ + case START_STOP_UNIT: /*TODO: check !!! */ + case SYNCHRONIZE_CACHE: /*TODO: check !!! */ + case VERIFY: /*TODO: check !!! */ + case WRITE_10: /*TODO: check !!! */ + case WRITE_BUFFER:/*TODO Check correctnes of such translation!*/ + *rcmd = cmd; /* No need to copy */ + *rlen = len; /*TODO: check !!! */ + default: + TRACE_ALWAYS("An unsupported RBC command: %08x\n", command->opcode); + status = B_ERROR; + break; + } + if(transformed) + TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen); + return status; +} +/** + \fn:ufi_transform + \param udi: usb_device_info object for wich transformation is requested + \param cmd: SCSI command buffer to be transformed + \param len: length of buffer, pointed by cmd parameter + \param rcmd: a place for buffer pointer with transformed command + \param rlen: a place for length of transformed command + \return: B_OK if transformation was successfull, B_ERROR otherwise + this is the "transformation procedure" for UFI USB subclass (0x04).It + performs all SCSI commands transformations required by this protocol. Additionally + it tries to make some workarounds for "brocken" USB devices. If no transformation + was performed resulting command buffer points to original one. +*/ +status_t ufi_transform(usb_device_info *udi, + uint8 *cmd, + uint8 len, + uint8 **rcmd, + uint8 *rlen) +{ + status_t status = B_OK; + TRACE_SCSI_COMMAND(cmd, len); + memset(*rcmd, 0, UFI_COMMAND_LEN); + if(!transform_6_to_10(cmd, len, rcmd, rlen)){ /* was not transformed ?*/ + scsi_cmd_generic *command = (scsi_cmd_generic *)cmd; + switch(command->opcode){ + case TEST_UNIT_READY: + if(transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen)){ + break; /* if TEST UNIT READY was transformed*/ + } + case FORMAT_UNIT: /* TODO: mismatch */ + case INQUIRY: + case START_STOP_UNIT: + case MODE_SELECT_10: + case MODE_SENSE_10: + case PREVENT_ALLOW_MEDIA_REMOVAL: + case READ_10: + case READ_12: + case READ_CAPACITY: + case READ_FORMAT_CAPACITY: /* TODO: not in the SCSI-2 specs */ + case REQUEST_SENSE: + case REZERO_UNIT: + case SEEK_10: + case SEND_DIAGNOSTICS: /* TODO: parameter list len mismatch */ + case VERIFY: + case WRITE_10: + case WRITE_12: /* TODO: EBP. mismatch */ + case WRITE_AND_VERIFY: + memcpy(*rcmd, cmd, len); /*TODO what about control? ignored in UFI?*/ + break; + default: + TRACE_ALWAYS("An unsupported UFI command: %08x\n", command->opcode); + status = B_ERROR; + break; + } + } + *rlen = UFI_COMMAND_LEN; /* override any value set in transform funcs !!!*/ + if(status == B_OK) + TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen); + return status; +} +/** + \fn:atapi_transform + \param udi: usb_device_info object for wich transformation is requested + \param cmd: SCSI command buffer to be transformed + \param len: length of buffer, pointed by cmd parameter + \param rcmd: a place for buffer pointer with transformed command + \param rlen: a place for length of transformed command + \return: B_OK if transformation was successfull, B_ERROR otherwise + this is the "transformation procedure" for SFF8020I and SFF8070I + USB subclassses (0x02 and 0x05). It performs all SCSI commands transformations + required by this protocol. Additionally it tries to make some workarounds for + "broken" USB devices. If no transformation was performed resulting command + buffer points to original one. +*/ +status_t atapi_transform(usb_device_info *udi, + uint8 *cmd, + uint8 len, + uint8 **rcmd, + uint8 *rlen) +{ + status_t status = B_OK; + TRACE_SCSI_COMMAND(cmd, len); + memset(*rcmd, 0, ATAPI_COMMAND_LEN); + if(!transform_6_to_10(cmd, len, rcmd, rlen)){ /* was not transformed ?*/ + scsi_cmd_generic *command = (scsi_cmd_generic *)cmd; + switch(command->opcode){ + case TEST_UNIT_READY: + if(transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen)){ + break; /* if TEST UNIT READY was transformed*/ + } + case FORMAT_UNIT: + case INQUIRY: + case MODE_SELECT_10: + case MODE_SENSE_10: + case PREVENT_ALLOW_MEDIA_REMOVAL: + case READ_10: + case READ_12: /* mismatch in byte 1 */ + case READ_CAPACITY: /* mismatch. no transf len defined... */ + case READ_FORMAT_CAPACITY: /* TODO: check!!! */ + case REQUEST_SENSE: + case SEEK_10: + case START_STOP_UNIT: + case VERIFY: /* mismatch DPO */ + case WRITE_10: /* mismatch in byte 1 */ + case WRITE_12: /* mismatch in byte 1 */ + case WRITE_AND_VERIFY: /* mismatch byte 1 */ + case PAUSE_RESUME: + case PLAY_AUDIO: + case PLAY_AUDIO_MSF: + case REWIND: + case PLAY_AUDIO_TRACK: + /* are in FreeBSD driver but no in 8070/8020 specs ... + //case REZERO_UNIT: + //case SEND_DIAGNOSTIC: + //case POSITION_TO_ELEMENT: */ + case GET_CONFIGURATION: + case SYNCHRONIZE_CACHE: + case READ_BUFFER: + case READ_SUBCHANNEL: + case READ_TOC: /* some mismatch */ + case READ_HEADER: + case READ_DISK_INFO: + case READ_TRACK_INFO: + case SEND_OPC: + case READ_MASTER_CUE: + case CLOSE_TR_SESSION: + case READ_BUFFER_CAP: + case SEND_CUE_SHEET: + case BLANK: + case EXCHANGE_MEDIUM: + case READ_DVD_STRUCTURE: + case SET_CD_SPEED: + case DVD_REPORT_KEY: + case DVD_SEND_KEY: +// case 0xe5: /* READ_TRACK_INFO_PHILIPS *//* TODO: check!!! */ + memcpy(*rcmd, cmd, len); /* TODO: check!!! */ + break; + default: + TRACE_ALWAYS("An unsupported (?) ATAPI command: %08x\n", command->opcode); + status = B_ERROR; + break; + } + } + *rlen = ATAPI_COMMAND_LEN; + if(status == B_OK) + TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen); + return status; +} +/** + \fn:qic157_transform + \param udi: usb_device_info object for wich transformation is requested + \param cmd: SCSI command buffer to be transformed + \param len: length of buffer, pointed by cmd parameter + \param rcmd: a place for buffer pointer with transformed command + \param rlen: a place for length of transformed command + \return: B_OK if transformation was successfull, B_ERROR otherwise + this is the "transformation procedure" for QIC157 USB subclass (0x03).It + performs all SCSI commands transformations required by this protocol. Additionally + it tries to make some workarounds for "brocken" USB devices. If no transformation + was performed resulting command buffer points to original one. +*/ +status_t qic157_transform(usb_device_info *udi, + uint8 *cmd, + uint8 len, + uint8 **rcmd, + uint8 *rlen) +{ + status_t status = B_OK; + TRACE_SCSI_COMMAND(cmd, len); + *rlen = ATAPI_COMMAND_LEN; + memset(*rcmd, 0, *rlen); + if(!transform_6_to_10(cmd, len, rcmd, rlen)){ // was not transformed ? + scsi_cmd_generic *command = (scsi_cmd_generic *)cmd; + switch(command->opcode){ + case TEST_UNIT_READY: + if(transform_cmd_test_unit_ready(udi, cmd, len, rcmd, rlen)){ + break; // if TEST UNIT READY was transformed + } + case ERASE: /*TODO: check !!! */ + case INQUIRY: /*TODO: check !!! */ + case LOAD_UNLOAD: /*TODO: check !!! */ + case LOCATE: /*TODO: check !!! */ + case LOG_SELECT: /*TODO: check !!! */ + case LOG_SENSE: /*TODO: check !!! */ + case MODE_SELECT_6: /*TODO: check !!! */ + case MODE_SENSE_6: /*TODO: check !!! */ + case READ_6: /*TODO: check !!! */ + case READ_POSITION: /*TODO: check !!! */ + case REQUEST_SENSE: /*TODO: check !!! */ + case REWIND: /*TODO: check !!! */ + case SPACE: /*TODO: check !!! */ + case WRITE_6: /*TODO: check !!! */ + case WRITE_FILEMARK: /*TODO: check !!! */ + *rcmd = cmd; /*TODO: check !!! */ + *rlen = len; + break; + default: + TRACE_ALWAYS("An unsupported QIC-157 command: %08x\n", command->opcode); + status = B_ERROR; + break; + } + } + if(status == B_OK) + TRACE_SCSI_COMMAND_HLIGHT(*rcmd, *rlen); + return status; +} + + +transform_module_info scsi_transform_m = { + {0, 0, 0}, /* this is not a real kernel module - just interface */ + scsi_transform, +}; + +transform_module_info rbc_transform_m = { + {0, 0, 0}, /* this is not a real kernel module - just interface */ + rbc_transform, +}; + +transform_module_info ufi_transform_m = { + {0, 0, 0}, /* this is not a real kernel module - just interface */ + ufi_transform, +}; + +transform_module_info atapi_transform_m = { + {0, 0, 0}, /* this is not a real kernel module - just interface */ + atapi_transform, +}; + +transform_module_info qic157_transform_m = { + {0, 0, 0}, /* this is not a real kernel module - just interface */ + qic157_transform, +}; diff --git a/src/add-ons/kernel/busses/scsi/usb/transform_procs.h b/src/add-ons/kernel/busses/scsi/usb/transform_procs.h new file mode 100644 index 0000000000..2d62bfe824 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/transform_procs.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ + +/** decalration of SCSI commands transformation procedures */ + +#ifndef _TRANSFORM_PROCS_H_ + #define _TRANSFORM_PROCS_H_ + +#ifndef _PROTO_MODULE_H_ +#include "proto_module.h" +#endif /* _PROTO_MODULE_H_ */ +/* transforms SCSI commands */ +extern transform_module_info scsi_transform_m; +/* transforms RBC commands */ +extern transform_module_info rbc_transform_m; +/* transforms UFI commands */ +extern transform_module_info ufi_transform_m; +/* transforms ATAPI commands */ +extern transform_module_info atapi_transform_m; +/* transforms QIC-157 commands */ +extern transform_module_info qic157_transform_m; +#endif /*_TRANSFORM_PROCS_H_*/ diff --git a/src/add-ons/kernel/busses/scsi/usb/uninstall.sh b/src/add-ons/kernel/busses/scsi/usb/uninstall.sh new file mode 100755 index 0000000000..e1c15c0e86 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/uninstall.sh @@ -0,0 +1,32 @@ +#!/bin/sh +########################################################## +## +## USB Storage Module uninstallation script +## +## This file is a part of BeOS USB SCSI interface module project. +## Copyright (c) 2003-2004 by Siarzhuk Zharski +## All rights reserved. +## +## $Source: /cvsroot/sis4be/usb_scsi/uninstall.sh,v $ +## $Author: zharik $ +## $Revision: 1.3 $ +## $Date: 2004/06/06 09:19:47 $ +## +########################################################## + +DRIVER_TITLE="USB Storage Module" +DRIVER_NAME=usb_scsi +DRIVER_TARGET_NAME=usb + +answer=`alert "Do you really want to uninstall the $DRIVER_TITLE ?" "No" "Yes"` +if [ $answer == "No" ]; then + exit +fi + +rm ~/config/add-ons/kernel/busses/scsi/$DRIVER_TARGET_NAME +#rm ~/config/settings/kernel/drivers/$DRIVER_NAME + +answer=`alert "The $DRIVER_TITLE has been removed from your system.You need to reboot your system to finish uninstalletion" "Reboot" "OK"` +if [ $answer == "Reboot" ]; then + shutdown -r +fi diff --git a/src/add-ons/kernel/busses/scsi/usb/usb_defs.h b/src/add-ons/kernel/busses/scsi/usb/usb_defs.h new file mode 100644 index 0000000000..54db903b11 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/usb_defs.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ + +/** definitions that should be in system headers but ... */ + +#ifndef _USB_DEFS_H_ + #define _USB_DEFS_H_ + +#define USB_EP_ATTR_CONTROL 0x00 +#define USB_EP_ATTR_ISOCHRONOUS 0x01 +#define USB_EP_ATTR_BULK 0x02 +#define USB_EP_ATTR_INTERRUPT 0x03 +#define USB_EP_ATTR_MASK 0x03 + +#define USB_EP_ADDR_DIR_IN 0x80 +#define USB_EP_ADDR_DIR_OUT 0x00 + +/*USB device class/subclass/protocl definitions*/ +#define USB_DEV_CLASS_MASS 0x08 + +#define USB_DEV_SUBCLASS_RBC 0x01 +#define USB_DEV_SUBCLASS_SFF8020I 0x02 +#define USB_DEV_SUBCLASS_QIC157 0x03 +#define USB_DEV_SUBCLASS_UFI 0x04 +#define USB_DEV_SUBCLASS_SFF8070I 0x05 +#define USB_DEV_SUBCLASS_SCSI 0x06 + +#define USB_DEV_PROTOCOL_CBI 0x00 +#define USB_DEV_PROTOCOL_CB 0x01 +#define USB_DEV_PROTOCOL_BULK 0x50 + +#define B_DEV_STALLED 0x8000a015 /* some "forgotten" error */ + +#endif /*_USB_DEFS_H_*/ diff --git a/src/add-ons/kernel/busses/scsi/usb/usb_scsi.c b/src/add-ons/kernel/busses/scsi/usb/usb_scsi.c new file mode 100644 index 0000000000..2115731106 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/usb_scsi.c @@ -0,0 +1,964 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ + +/** Main part of USB SIM implementation */ + +#include "usb_scsi.h" + +#include +#include +#include +#include +#include +#include "device_info.h" +#include "settings.h" +#include "transform_procs.h" +#include "tracing.h" +#include "scsi_commands.h" +#include "proto_common.h" +#include "proto_bulk.h" +#include "proto_cbi.h" +#include "usb_defs.h" +#include "fake_device.h" +#include "sg_buffer.h" + +status_t device_added(const usb_device device, + void **cookie); + +status_t device_removed(void *cookie); + +static long sim_action(CCB_HEADER *ccbh); +static long sim_init(); + +#define SIM_VERSION 1 +#define HBA_VERSION 1 + +//#define ROUNDUP(size, seg) (((size) + (seg) - 1) & ~((seg) - 1)) + +#define INQ_VENDOR_LEN 0x08 +#define INQ_PRODUCT_LEN 0x10 +#define INQ_REVISION_LEN 0x04 + +#define TRANS_TIMEOUT 7500000 + +static long path_id = -1; +static int32 load_count = 0; + +static char sim_vendor_name[] = "S.Zharski"; /* who wrote this driver */ +static char hba_vendor_name[] = "USB"; /* who made the hardware */ +static char controller_family[] = "USB SCSI"; /* what family of products */ + +struct usb_support_descriptor supported_devices[] = { + {0, 0, 0, 0, 0} +}; + +#define SIZEOF(array) (sizeof(array)/sizeof(array[0])) //????? + +usb_device_info *usb_devices[MAX_DEVICES_COUNT]; +/* main devices table locking semaphore */ +sem_id usb_serial_lock = -1; + +usb_module_info *usb; +static cam_for_sim_module_info *cam; + +struct usb_notify_hooks notify_hooks = { + device_added, + device_removed +}; +/** + \fn:match_device + \param device:??? + \param uii:??? + \param pproperties:??? + \return:B_BAD_TYPE , B_ENTRY_NOT_FOUND, B_OK + + ?? +*/ +status_t get_interface_properties(usb_interface_info *uii, + uint32 *pproperties) +{ + status_t status = B_BAD_TYPE; + if(uii->descr->interface_class == USB_DEV_CLASS_MASS){ + status = B_OK; + switch(uii->descr->interface_subclass){ + case USB_DEV_SUBCLASS_RBC: *pproperties |= CMDSET_RBC; break; + case USB_DEV_SUBCLASS_UFI: *pproperties |= CMDSET_UFI; break; + case USB_DEV_SUBCLASS_SFF8020I: + case USB_DEV_SUBCLASS_SFF8070I: *pproperties |= CMDSET_ATAPI; break; + case USB_DEV_SUBCLASS_SCSI: *pproperties |= CMDSET_SCSI; break; + case USB_DEV_SUBCLASS_QIC157: *pproperties |= CMDSET_QIC157; break; + default: + TRACE_ALWAYS("get_interface_properties:unknown USB subclass:%02x\n", + uii->descr->interface_subclass); + /*status = B_ENTRY_NOT_FOUND;*/ /*B_BAD_TYPE assumed*/ + break; + } + switch(uii->descr->interface_protocol){ + case USB_DEV_PROTOCOL_CBI: *pproperties |= PROTO_CBI; break; + case USB_DEV_PROTOCOL_CB: *pproperties |= PROTO_CB; break; + case USB_DEV_PROTOCOL_BULK: *pproperties |= PROTO_BULK_ONLY; break; + default: + TRACE_ALWAYS("get_interface_properties:unknown USB protocol:%02x\n", + uii->descr->interface_protocol); + /*status = B_ENTRY_NOT_FOUND;*/ /*B_BAD_TYPE assumed*/ + break; + } + if(status == B_OK){ + TRACE("get_interface_properties: standard properties:%08x\n", *pproperties); + } + } + return status; +} +/** + \fn: + +*/ +status_t load_vendor_module(char **path, const char *path_mask, + const char *prop, module_info **mi) +{ + status_t status = B_NO_MEMORY; + int path_len = strlen(path_mask) + strlen(prop); + *path = malloc(path_len); + if(*path){ + sprintf(*path, path_mask, prop); + status = get_module(*path, mi); + if(status != B_OK) + TRACE_ALWAYS("load_vendor_module:get_module(%s) failed:%08x\n", *path, status); + } else { + TRACE_ALWAYS("load_vendor_module:couldn't allocate %d bytes\n", path_len); + } + return status; +} +/** + \fn: + +*/ +status_t setup_transport_modules(usb_device_info *udi, + usb_device_settings *uds) +{ + status_t status = B_OK; + switch(PROTO(udi->properties)){ + case PROTO_BULK_ONLY: + udi->protocol_m = &bulk_only_protocol_m; + break; + case PROTO_CB: + case PROTO_CBI: + udi->protocol_m = &cbi_protocol_m; + break; + case PROTO_VENDOR:{ + status = load_vendor_module(&udi->protocol_m_path, + PROTOCOL_MODULE_MASK, + uds->vendor_protocol, + (module_info**)&udi->protocol_m); + }break; + default: + TRACE_ALWAYS("setup_transport_modules: " + "transport %02x is not supported\n", PROTO(udi->properties)); + status = B_ENTRY_NOT_FOUND; + } + if(status == B_OK){ + switch(CMDSET(udi->properties)){ + case CMDSET_SCSI: + udi->transform_m = &scsi_transform_m; + break; + case CMDSET_UFI: + udi->transform_m = &ufi_transform_m; + udi->properties |= FIX_FORCE_MS_TO_10; /* always use 10-byte request */ + break; + case CMDSET_ATAPI: + udi->transform_m = &atapi_transform_m; + udi->properties |= FIX_FORCE_MS_TO_10; /* always use 10-byte request */ + break; + case CMDSET_RBC: + udi->transform_m = &rbc_transform_m; + break; + case CMDSET_QIC157: + udi->transform_m = &qic157_transform_m; + udi->properties |= FIX_FORCE_MS_TO_10; /* always use 10-byte request */ + break; + case CMDSET_VENDOR:{ + status = load_vendor_module(&udi->transform_m_path, + TRANSFORM_MODULE_MASK, + uds->vendor_commandset, + (module_info**)&udi->transform_m); + }break; + default: + TRACE_ALWAYS("setup_transport_modules: " + "protocol %02x is not supported\n", CMDSET(udi->properties)); + status = B_ENTRY_NOT_FOUND; + } + } + return status; +} + +static void +release_transport_modules(usb_device_info *udi) +{ + if(PROTO(udi->properties) == PROTO_VENDOR && 0 != udi->protocol_m_path){ + put_module(udi->protocol_m_path); + udi->protocol_m = 0; + free(udi->protocol_m_path); + } + if(CMDSET(udi->properties) == CMDSET_VENDOR && 0 != udi->transform_m_path){ + put_module(udi->transform_m_path); + udi->transform_m = 0; + free(udi->transform_m_path); + } +} + +/** + \fn: +*/ +status_t setup_endpoints(usb_interface_info *uii, + usb_device_info *udi) +{ + status_t status = B_OK; + int16 idx = 0; + enum{ epIn = 0, epOut, epIntr, epCount }; + size_t epts[epCount] = { -1, -1, -1 }; + char *epnames[epCount] = {"input", "output", "interrupt"}; + size_t ep = 0; + for(; ep < uii->endpoint_count; ep++){ + usb_endpoint_descriptor *ed = uii->endpoint[ep].descr; + TRACE("try endpoint:%d %x %x %x\n", ep, (int32)ed->attributes, (int32)ed->endpoint_address, uii->endpoint[ep].handle); + if((ed->attributes & USB_EP_ATTR_MASK) == USB_EP_ATTR_BULK){ + if((ed->endpoint_address & USB_EP_ADDR_DIR_IN) == USB_EP_ADDR_DIR_IN){ + epts[epIn] = ep; + }else{ + epts[epOut] = ep; + } + }else{ + if((ed->attributes & USB_EP_ATTR_MASK) == USB_EP_ATTR_INTERRUPT) + epts[epIntr] = ep; + } + } + switch(PROTO(udi->properties)){ + case PROTO_CB: + case PROTO_BULK_ONLY: + if(epts[epIntr] == -1) + epts[epIntr] = 0; /* not required for this transports - set it to default*/ + break; + case PROTO_CBI: + default: + } + for(idx = 0; idx < epCount; idx++){ + if(epts[idx] == -1 && PROTO(udi->properties) != PROTO_VENDOR){ + TRACE_ALWAYS("setup_endpoints: required %s endpoint not found. " + "ignore this interface\n", epnames[idx]); + // DEBUG!!!!!!!!!! + status = B_ERROR; + } + } + if(status == B_OK){ + udi->pipe_in = uii->endpoint[epts[epIn]].handle; + udi->pipe_out = uii->endpoint[epts[epOut]].handle; + udi->pipe_intr = uii->endpoint[epts[epIntr]].handle; + //TRACE("setup_endpoints: input:%d output:%d " + // "interrupt:%d\n", epts[epIn], epts[epOut], epts[epIntr]); + TRACE("endpoint:%x %x %x\n", udi->pipe_in, udi->pipe_out, udi->pipe_intr); + } + return status; +} +/** + \fn:create_device_info + \param device:??? + \param ppudi:??? + \return:??? + + ??? +*/ +status_t allocate_resources(usb_device_info *udi) +{ + char name[32]; + status_t status = B_NO_MEMORY; + uint16 dev = 0; + acquire_sem(usb_serial_lock); + for(; dev < MAX_DEVICES_COUNT; dev++){ + if(!usb_devices[dev]) + break; + } + if(dev < MAX_DEVICES_COUNT){ + usb_devices[dev] = udi; + udi->lock_sem = + udi->trans_sem = -1; + sprintf(name, "usb_scsi lock_sem:%d", dev); + if((udi->lock_sem = create_sem(0, name)) >= 0){ + sprintf(name, "usb_scsi trans_sem:%d", dev); + if((udi->trans_sem = create_sem(0, name))>=0){ + udi->dev_num = dev; + release_sem(udi->lock_sem); + status = B_OK; + }else + status = udi->trans_sem; + } else + status = udi->lock_sem; + + if(status != B_OK){ + TRACE_ALWAYS("allocate_resources:error:%s", strerror(status)); + if(udi->lock_sem >= 0) + delete_sem(udi->lock_sem); + if(udi->trans_sem >= 0) + delete_sem(udi->trans_sem); + usb_devices[dev] = NULL; + free(udi); + } + }else{ + TRACE_ALWAYS("allocate_resources:reserved devices space exhausted." + "Unplug unnesesary devices or reconfigure this driver.\n"); + } + release_sem(usb_serial_lock); + return status; +} +/** + \fn: + +*/ +void release_resources(usb_device_info *udi) +{ + release_transport_modules(udi); + udi->usb_m = 0; + (*usb->cancel_queued_transfers)(udi->pipe_in); + (*usb->cancel_queued_transfers)(udi->pipe_out); + delete_sem(udi->lock_sem); + delete_sem(udi->trans_sem); + acquire_sem(usb_serial_lock); + usb_devices[udi->dev_num] = NULL; + release_sem(usb_serial_lock); +} +/** + \fn:device_added + \param device:?? + \param cookie:?? + \return:?? + + ?? +*/ +status_t device_added(const usb_device device, + void **cookie){ + status_t status = B_NO_MEMORY; + const usb_configuration_info *uci = NULL; + uint16 cfg = 0; + bool b_found = false; + bool b_has_extra_settings = false; + const usb_device_descriptor *udd = (*usb->get_device_descriptor)(device); + usb_device_info *udi = (usb_device_info *)malloc(sizeof(usb_device_info)); + TRACE("device_added: probing canidate: " + "%04x/%04x %02d/%02d/%02d\n", udd->vendor_id, udd->product_id, + udd->device_class, udd->device_subclass, udd->device_protocol); + if(udi){ + status = B_NO_INIT; + while(!b_found && (uci = (*usb->get_nth_configuration)(device, cfg++))){ + uint16 itf = 0; + for(; itf < uci->interface_count && !b_found; itf++){ + usb_interface_list *ifl = &uci->interface[itf]; + uint16 alt = 0; + for(; alt < ifl->alt_count; alt++){ + usb_interface_info *uii = &ifl->alt[alt]; + usb_device_settings ud_settings; + memset(udi, 0, sizeof(usb_device_info)); + memset(&ud_settings, 0, sizeof(usb_device_settings)); + udi->device = device; + udi->interface = itf; + b_has_extra_settings = lookup_device_settings(udd, &ud_settings); + switch(get_interface_properties(uii, &udi->properties)){ + case B_BAD_TYPE: /* non-standard USB class*/ + if(!b_has_extra_settings){ + continue; /* skip to next interface */ + } /* no break - fall through */ + case B_OK: + if(b_has_extra_settings){ + if(PROTO(ud_settings.properties) != PROTO_NONE){ + udi->properties &= ~PROTO_MASK; + udi->properties |= PROTO(ud_settings.properties); + } + if(CMDSET(ud_settings.properties) != CMDSET_NONE){ + udi->properties &= ~CMDSET_MASK; + udi->properties |= CMDSET(ud_settings.properties); + } + udi->properties |= ud_settings.properties & FIX_MASK; + TRACE("device_added: properties merged:%08x\n", udi->properties); + } + if( B_OK == setup_transport_modules(udi, &ud_settings)){ + break; + } /* else - no break - fall through */ + default: + continue; /* skip to next interface */ + } + if(alt != 0){ /*TODO: are we need this ???*/ + if((status = (*usb->set_alt_interface)(device, uii)) != B_OK){ + TRACE_ALWAYS("device_added:setting alt interface failed:%s", + strerror(status)); + goto Failed;/* Break - is it right?*/ + } + } + if((*usb->get_configuration)(device) != uci){ + if((status = (*usb->set_configuration)(device, uci)) != B_OK){ + TRACE_ALWAYS("device_added:setting configuration failed:%08x uci: %08x\n", + (*usb->get_configuration)(device), uci); + TRACE_ALWAYS("device_added:setting configuration failed:%s\n", + strerror(status)); + + goto Failed;/* Break - is it right?*/ + } + } + if(B_OK != setup_endpoints(uii, udi)){ + continue; /* skip to next interface */ + } + if((status = allocate_resources(udi)) == B_OK){ + udi->b_trace = b_log_protocol; + udi->trace = usb_scsi_trace; + udi->trace_bytes = usb_scsi_trace_bytes; + udi->trans_timeout = TRANS_TIMEOUT; + udi->usb_m = usb; + udi->not_ready_luns = 0xff; /*assume all LUNs initially not ready */ + if((status = (*udi->protocol_m->init)(udi)) == B_OK){ + TRACE("device_added[%d]: SUCCESS! Enjoy using!\n", udi->dev_num); + *cookie = udi; + b_found = true; /* we have found something useful - time to go out! */ + break; /* ... now break alternatives iteration.*/ + } else { + release_resources(udi); + } + } + /* go to next iteration - check all configurations for possible devices */ + }/* for(...) iterate interface alternates*/ + }/* for(...) iterate interfaces*/ + }/* while(...) iterate configurations */ + if(status == B_OK){ + (*cam->minfo.rescan)(); + } else { + free(udi); + } + } /* if(udi){ */ + if(status != B_OK){ + TRACE("device_added: probing failed (%s) for: %04x/%04x\n", + strerror(status), udd->vendor_id, udd->product_id); + } +Failed: + return status; +} +/** + \fn:device_removed + \param cookie:??? + \return:??? + + ??? +*/ +status_t device_removed(void *cookie) +{ + status_t status = B_OK; + usb_device_info *udi = (usb_device_info *)cookie; + acquire_sem(udi->lock_sem); /* wait for possible I/O operation complete */ + release_resources(udi); + /* no corresponding call of release_sem(udi->lock_sem); + - semaphore was deleted in release_resources, any waiting thread + was failed with BAD_SEM_ID. + */ + TRACE_ALWAYS("device_removed[%d]:All The Best !!!\n", udi->dev_num); + free(udi); + (*cam->minfo.rescan)(); + return status; +} +/** + \fn:sim_init + \return: ??? + + called on SIM init +*/ +static long sim_init(void) +{ + status_t status = B_OK; + TRACE("sim_init\n"); + return status; +} + +/** +*/ +static bool +pre_check_scsi_io_request(usb_device_info *udi, + CCB_SCSIIO *ccbio, + status_t *ret_status) +{ + int target_id = ccbio->cam_ch.cam_target_id; + uint8 target_lun = ccbio->cam_ch.cam_target_lun; + *ret_status = B_OK; + /* handle reserved device and luns entries */ + if(b_reservation_on && udi == NULL && + target_id < reserved_devices && + target_lun < reserved_luns) + { + *ret_status = fake_scsi_io(ccbio); + return false; + } + /* no device for this target | LUN */ + if(udi == NULL || target_lun > udi->max_lun){ + ccbio->cam_ch.cam_status = CAM_DEV_NOT_THERE; + *ret_status = B_DEV_BAD_DRIVE_NUM; + return false; + } + /* check command length */ + if(ccbio->cam_cdb_len != 6 && + ccbio->cam_cdb_len != 10 && + ccbio->cam_cdb_len != 12) + { + TRACE("Bad SCSI command length:%d.Ignore\n", ccbio->cam_cdb_len); + ccbio->cam_ch.cam_status = CAM_REQ_INVALID; + *ret_status = B_BAD_VALUE; + return false; + } + /* Clean up auto sense buffer. + To avoid misunderstanding in not ready luns logic detection.*/ + if(NULL == ccbio->cam_sense_ptr){ + memset(&udi->autosense_data, 0, sizeof(udi->autosense_data)); + } else { + memset(ccbio->cam_sense_ptr, 0, ccbio->cam_sense_len); + } + return true; +} +/** +*/ +static bool +pre_handle_features(usb_device_info *udi, + CCB_SCSIIO *ccbio, + scsi_cmd_generic *command, + sg_buffer *sgb, + status_t *ret_status) +{ + uint8 target_lun = ccbio->cam_ch.cam_target_lun; + *ret_status = B_OK; + udi->trans_timeout = TRANS_TIMEOUT; + switch(command->opcode){ + case MODE_SELECT_6: + case MODE_SENSE_6:{ + bool b_select = (MODE_SELECT_6 == command->opcode); + const char*cmd_name = b_select ? "MODE_SELECT" : "MODE_SENSE"; + if(udi->not_ready_luns & (1 << target_lun)){ + TRACE("pre_handle_features:%s_6 bypassed for LUN:%d\n", cmd_name, target_lun); + goto set_REQ_INVALID_and_return; + } + if(HAS_FIXES(udi->properties, FIX_FORCE_MS_TO_10)){ + if( B_OK != realloc_sg_buffer(sgb, ccbio->cam_dxfer_len + 4)){ /* TODO: 4 - hardcoded? */ + TRACE_ALWAYS("pre_handle_features:error allocating %d bytes for %s_10\n", + ccbio->cam_dxfer_len + 4, cmd_name); + goto set_REQ_INVALID_and_return; + } + if(b_select){ + sg_buffer sgb_sense_6; + /*TODO: implemenet and try refragment_sg_buffer - to check handling of real scatter/gather!!*/ + if(B_OK != init_sg_buffer(&sgb_sense_6, ccbio)){ + /* In case of error TRACE-ing was already performed in sg_ functions */ + goto set_REQ_INVALID_and_return; + } + TRACE_MODE_SENSE_SGB("MODE SELECT 6:", &sgb_sense_6); + if(B_OK != sg_memcpy(sgb, 1, &sgb_sense_6, 0, 3) || + B_OK != sg_memcpy(sgb, 7, &sgb_sense_6, 3, 1) || + B_OK != sg_memcpy(sgb, 8, &sgb_sense_6, 4, ccbio->cam_dxfer_len - sizeof(scsi_mode_param_header_6))) + { + /* In case of error TRACE-ing was already performed in sg_ functions */ + goto set_REQ_INVALID_and_return; + } + TRACE_MODE_SENSE_SGB("MODE SELECT 10:", sgb); + } + } /*else { + if(b_select){ / * trace data if configured in settings * / + TRACE_MODE_SENSE_DATA("MODE_SELECT:", ccbio->cam_data_ptr, ccbio->cam_dxfer_len); + } + }*/ + }break; + case INQUIRY: /* fake INQUIRY request */ + if(HAS_FIXES(udi->properties, FIX_NO_INQUIRY)){ + fake_inquiry_request(udi, ccbio); + goto set_REQ_CMP_and_return; + } break; + case TEST_UNIT_READY: /* fake INQUIRY request */ + if(HAS_FIXES(udi->properties, FIX_NO_TEST_UNIT)){ + goto set_REQ_CMP_and_return; + } break; + case PREVENT_ALLOW_MEDIA_REMOVAL: /* fake PREVENT_ALLOW_MEDIA_REMOVAL request */ + if(HAS_FIXES(udi->properties, FIX_NO_PREVENT_MEDIA)){ + goto set_REQ_CMP_and_return; + } break; + case FORMAT_UNIT: + udi->trans_timeout = B_INFINITE_TIMEOUT; + break; + default: break; + } + return true; + +set_REQ_CMP_and_return: + ccbio->cam_ch.cam_status = CAM_REQ_CMP; + return false;//*ret_status = B_OK; + +set_REQ_INVALID_and_return: + ccbio->cam_ch.cam_status = CAM_REQ_INVALID; + *ret_status = B_BAD_VALUE; + return false; +} +/** +*/ +static bool +post_handle_features(usb_device_info *udi, + CCB_SCSIIO *ccbio, + scsi_cmd_generic *command, + sg_buffer *sgb, + status_t *ret_status) +{ + bool b_cmd_ok = (ccbio->cam_ch.cam_status == CAM_REQ_CMP); + uint8 target_lun = ccbio->cam_ch.cam_target_lun; + switch(command->opcode){ + case READ_6: + case WRITE_6: +#if 0 +/* Disabled - single problem can switch to 6-bytes mode. If device doesn't + support 6-bytes command all goes totally wrong. That's bad. */ + if(!b_cmd_ok && !HAS_FEATURES(udi->descr.properties, PROP_FORCE_RW_TO_6)){ + TRACE("post_handle_features:READ(10)/WRITE(10) failed - retry 6-byte one\n"); + udi->descr.properties |= PROP_FORCE_RW_TO_6; + ccbio->cam_scsi_status = SCSI_STATUS_OK; /* clear the scsi_status. */ + ccbio->cam_ch.cam_status = CAM_REQ_INPROG; /* set status in progress again. */ + b_retry = true; /* inform caller about retry */ + } +#endif + break; + case MODE_SENSE_6: + if(!b_cmd_ok && !HAS_FIXES(udi->properties, FIX_FORCE_MS_TO_10)){ + TRACE("post_handle_features:MODE SENSE(6) failed - retry 10-byte one\n"); + udi->properties |= FIX_FORCE_MS_TO_10; + ccbio->cam_scsi_status = SCSI_STATUS_OK; /* clear the scsi_status. */ + ccbio->cam_ch.cam_status = CAM_REQ_INPROG; /* set status in progress again. */ + return true; /* inform caller about retry */ + } /* no break, - fallthrough! */ + case MODE_SELECT_6:{ + if(MODE_SENSE_6 == command->opcode){ + sg_buffer sgb_sense_6; + if(B_OK != init_sg_buffer(&sgb_sense_6, ccbio)){ + TRACE_ALWAYS("post_hanlde_features: initialize sgb failed\n"); + goto set_REQ_INVALID_and_return; + } + /* convert sense information from 10-byte request result to 6-byte one */ + if(HAS_FIXES(udi->properties, FIX_FORCE_MS_TO_10)){ + uchar mode_data_len_msb = 0, block_descr_len_msb = 0; + if( B_OK != sg_access_byte(sgb, 0, &mode_data_len_msb, false) || + B_OK != sg_access_byte(sgb, 6, &block_descr_len_msb, false) || + 0 != mode_data_len_msb || 0 != block_descr_len_msb) + { + /* In case of error TRACE-ing was already performed in sg_ functions */ + TRACE_ALWAYS("MODE_SENSE 10->6 conversion overflow: %d, %d\n", + mode_data_len_msb, block_descr_len_msb); + goto set_REQ_INVALID_and_return; + } + TRACE_MODE_SENSE_SGB("MODE SENSE 10:", sgb); + if( B_OK != sg_memcpy(&sgb_sense_6, 0, sgb, 1, 3) || + B_OK != sg_memcpy(&sgb_sense_6, 3, sgb, 7, 1) || + B_OK != sg_memcpy(&sgb_sense_6, 4, sgb, 8, ccbio->cam_dxfer_len - sizeof(scsi_mode_param_header_6))) + { + /* In case of error TRACE-ing was already performed in sg_ functions */ + TRACE_ALWAYS("MODE_SENSE 10->6 conversion failed\n"); + goto set_REQ_INVALID_and_return; + } + } + /* set write-protected flag if required by user */ + if(HAS_FIXES(udi->properties, FIX_FORCE_READ_ONLY)){ + status_t status = B_OK; + uchar device_spec_params = 0; + if(B_OK == (status = sg_access_byte(sgb, 2, &device_spec_params, false))){ + device_spec_params |= 0x80; + status = sg_access_byte(sgb, 2, &device_spec_params, true); + } + if(B_OK != status){ + TRACE_ALWAYS("MODE_SENSE set READ-ONLY mode failed. Writing ALLOWED!\n"); + /*goto set_req_invalid_and_return;*/ /* not urgent. do not fail processing... */ + } + } + TRACE_MODE_SENSE_SGB("MODE SENSE 6:", &sgb_sense_6); + } + if(HAS_FIXES(udi->properties, FIX_FORCE_MS_TO_10)){ + free_sg_buffer(sgb); + } + } break; + case TEST_UNIT_READY: { /* set the not ready luns flag */ + scsi_sense_data *sense_data = (ccbio->cam_sense_ptr == NULL) ? + &udi->autosense_data : (scsi_sense_data *)ccbio->cam_sense_ptr; + if((sense_data->flags & SSD_KEY) == SSD_KEY_NOT_READY){ + udi->not_ready_luns |= (1 << target_lun); + } else { + udi->not_ready_luns &= ~(1 << target_lun); + } + usb_scsi_trace_bytes("NOT_READY_LUNS:", &udi->not_ready_luns, 1); + } break; + case READ_CAPACITY:{ + /*uint8 *bts = sgb->piov->iov_base; + uint32 capacity = (bts[0]<<24) + (bts[1]<<16) + (bts[2]<<8) + (bts[3]); + TRACE_ALWAYS("CAPAC:%d\n", capacity); + //bts[3] -= 3;*/ + TRACE_CAPACITY("READ_CAPACITY:", sgb); + } break; + default: break; + } + return false; /* do not retry - all is OK */ //b_retry; + +set_REQ_INVALID_and_return: + ccbio->cam_ch.cam_status = CAM_REQ_INVALID; + *ret_status = B_BAD_VALUE; + return false; /* do not retry - fatal error */ +} +/** + \fn:xpt_scsi_io + \param ccbio: ???? + \return: ??? + + xpt_scsi_io - handle XPT_SCSI_IO sim action +*/ +status_t xpt_scsi_io(CCB_SCSIIO *ccbio) +{ + status_t status = B_OK; + usb_device_info *udi = usb_devices[ccbio->cam_ch.cam_target_id/*target_id*/]; + uint8 *cmd; + sg_buffer sgb; + + /* clear the scsi_status. It can come from system with some garbage value ...*/ + ccbio->cam_scsi_status = SCSI_STATUS_OK; + /* check the request for correct parameters, valid targets, luns etc ... */ + if(false == pre_check_scsi_io_request(udi, ccbio, &status)){ + return status; + } + +#if 0 /* activate if you need detailed logging of CCB_SCSI request*/ + usb_scsi_trace_CCB_SCSIIO(ccbio); +#endif + + + /* acquire semaphore - avoid re-enters */ +/* if((status = acquire_sem_etc(udi->lock_sem, 1, + B_RELATIVE_TIMEOUT, + udi->trans_timeout)) != B_OK) */ +// TRACE_ALWAYS("sem before acq:%08x\n",udi->lock_sem); + if((status = acquire_sem(udi->lock_sem)) != B_OK){ + /* disabled - CAM_BUSY flag is not recognized by BeOS ... :-( + if(status == B_WOULD_BLOCK){ + TRACE("locked sema bypass OK\n"); + ccbio->cam_ch.cam_status = CAM_BUSY; + return B_OK; + }*/ + TRACE("xpt_scsi_io:acquire_sem_etc() failed:%08x\n", status); + ccbio->cam_ch.cam_status = CAM_DEV_NOT_THERE; + return B_DEV_BAD_DRIVE_NUM; + } + /* set the command data pointer */ + if(ccbio->cam_ch.cam_flags & CAM_CDB_POINTER){ + cmd = ccbio->cam_cdb_io.cam_cdb_ptr; + }else{ + cmd = ccbio->cam_cdb_io.cam_cdb_bytes; + } + /* NOTE: using stack copy of sg_buffer sgb. It can be modified/freed in + *_handle_features() functions! Twice reallocation is also not awaited! + Note this on refactoring!!! */ + /*TODO returns!*/ + init_sg_buffer(&sgb, ccbio); + do{ /* <-- will be repeated if 6-byte RW/MS commands failed */ + uint8 *rcmd; + uint8 rcmdlen; + uint32 transfer_len = 0; + EDirection dir = eDirNone; + /* handle various features for this device */ + if(!pre_handle_features(udi, ccbio, (scsi_cmd_generic *)cmd, &sgb, &status)){ + release_sem(udi->lock_sem); + return status; + } + /* transform command as required by protocol */ + rcmd = udi->scsi_command_buf; + rcmdlen = sizeof(udi->scsi_command_buf); + if((status = (*udi->transform_m->transform)(udi, cmd, ccbio->cam_cdb_len & 0x1f, + &rcmd, &rcmdlen)) != B_OK) + { + TRACE_ALWAYS("xpt_scsi_io: transform failed: %08x\n", status); + ccbio->cam_ch.cam_status = CAM_REQ_INVALID; + release_sem(udi->lock_sem); + return B_BAD_VALUE; + } + /* set correct direction flag */ + switch(CAM_DIR_MASK & ccbio->cam_ch.cam_flags){ + case CAM_DIR_IN: dir = eDirIn; break; + case CAM_DIR_OUT: dir = eDirOut; break; + default: dir = eDirNone; break; + } + + TRACE_DATA_IO_SG(sgb.piov, sgb.count); + + /*TODO: return!*/ + sg_buffer_len(&sgb, &transfer_len); + /* transfer command to device. SCSI status will be handled in callback */ + (*udi->protocol_m->transfer)(udi, rcmd, rcmdlen, sgb.piov, sgb.count, + transfer_len/*ccbio->cam_dxfer_len*/, + dir, ccbio, transfer_callback); + /* perform some post-tranfer features handling + and automatic 6-10 bytes command support detection */ + } while(post_handle_features(udi, ccbio, (scsi_cmd_generic *)cmd, &sgb, &status)); + release_sem(udi->lock_sem); + return status; +} +/** + \fn:xpt_path_inquiry + \param ccbp: + \return: + + xpt_path_inquiry - handle XPT_PATH_INQ sim action +*/ +status_t xpt_path_inquiry(CCB_PATHINQ *ccbp) +{ + status_t status = B_OK; + ccbp->cam_version_num = SIM_VERSION; + ccbp->cam_target_sprt = 0; + ccbp->cam_hba_eng_cnt = 0; + memset (ccbp->cam_vuhba_flags, 0, VUHBA); + ccbp->cam_sim_priv = SIM_PRIV; + ccbp->cam_async_flags = 0; + ccbp->cam_initiator_id = CONTROLLER_SCSI_ID; + ccbp->cam_hba_inquiry = CONTROLLER_SCSI_BUS; /* Narrow SCSI bus */ + ccbp->cam_hba_misc = PIM_NOINQUIRY; + ccbp->cam_osd_usage = 0; + /* There should be special handling of path_id == 0xff + but looks like it's not used by BeOS now */ + /*ccbp->cam_hpath_id = path_id;*/ + strncpy(ccbp->cam_sim_vid, sim_vendor_name, SIM_ID); + strncpy(ccbp->cam_hba_vid, hba_vendor_name, HBA_ID); + ccbp->cam_ch.cam_status = CAM_REQ_CMP; + return status; +} +/** + \fn:xpt_extended_path_inquiry + \param ccbep: ??? + \return:??? + + xpt_extended_path_inquiry - handle XPT_EXTENDED_PATH_INQ sim action +*/ +status_t xpt_extended_path_inquiry(CCB_EXTENDED_PATHINQ *ccbep) +{ + status_t status = B_OK; + xpt_path_inquiry((CCB_PATHINQ *)ccbep); + sprintf(ccbep->cam_sim_version, "%d.0", SIM_VERSION); + sprintf(ccbep->cam_hba_version, "%d.0", HBA_VERSION); + strncpy(ccbep->cam_controller_family, controller_family, FAM_ID); + strncpy(ccbep->cam_controller_type, "USB-SCSI", TYPE_ID); + return status; +} +/** + \fn:sim_action + \param ccbh: ???? + \return: ???? + + This fucntion performs SCSI interface module actions - + calls corresponding xpt_* - functions. +*/ +static long sim_action(CCB_HEADER *ccbh) +{ + status_t status = B_ERROR; + if(path_id != ccbh->cam_path_id){ + TRACE_ALWAYS("sim_action:path_id mismatch of func:%d:our:%d,requested:%d\n", + ccbh->cam_func_code, path_id, ccbh->cam_path_id); + ccbh->cam_status = CAM_PATH_INVALID; + } else { + ccbh->cam_status = CAM_REQ_INPROG; + switch(ccbh->cam_func_code){ + case XPT_SCSI_IO: + status = xpt_scsi_io((CCB_SCSIIO *)ccbh); + break; + case XPT_PATH_INQ: + status = xpt_path_inquiry((CCB_PATHINQ *)ccbh); + break; + case XPT_EXTENDED_PATH_INQ: + status = xpt_extended_path_inquiry((CCB_EXTENDED_PATHINQ *)ccbh); + break; + default: + TRACE_ALWAYS("sim_action: unsupported function: %x\n", ccbh->cam_func_code); + ccbh->cam_status = CAM_REQ_INVALID; + break; + } + } + return status; +} +/** + \fn:std_ops + \param op: operation to be performed on this module + \param ...: possible additional arguments + \return: B_OK on success, error status on failure + + This function deals with standard module operations. Currently, the only + two things that entails are initialization and uninitialization. + - get the SCSI Bus Manager Module and USB Manager Module + - put them when we're finished +*/ +static status_t std_ops(int32 op, ...) +{ + int i; + status_t status = B_ERROR; + CAM_SIM_ENTRY entry; + switch(op) { + case B_MODULE_INIT: + if(0 == atomic_add(&load_count, 1)){ + thread_info tinfo = {0}; + load_module_settings(); + get_thread_info(find_thread(0), &tinfo); + if(!b_ignore_sysinit2 || (0 != strcmp(tinfo.name, "sysinit2"))){ + create_log(); + if(get_module(B_USB_MODULE_NAME, (module_info **)&usb) == B_OK){ + if(get_module(B_CAM_FOR_SIM_MODULE_NAME, (module_info **)&cam) == B_OK){ + for(i = 0; i < MAX_DEVICES_COUNT; i++) + usb_devices[i] = NULL; + + if((*usb->register_driver)(MODULE_NAME, supported_devices, SIZEOF(supported_devices), "usb_dsk") == B_OK){ + if((*usb->install_notify)(MODULE_NAME, ¬ify_hooks) == B_OK){ + entry.sim_init = sim_init; + entry.sim_action = sim_action; + path_id =(*cam->xpt_bus_register)(&entry); + usb_serial_lock = create_sem(1, MODULE_NAME"_devices_table_lock"); + status = B_OK; + break; + } + } + put_module(B_CAM_FOR_SIM_MODULE_NAME); + } + put_module(B_USB_MODULE_NAME); + } + } else { + TRACE_ALWAYS("std_ops INIT call was ignored for thread:%s\n", tinfo.name); + } + } else { + atomic_add(&load_count, -1); + } + break; + case B_MODULE_UNINIT: + if(1 == atomic_add(&load_count, -1)){ + (*usb->uninstall_notify)(MODULE_NAME); + status = B_OK; + if(path_id != -1){ + (*cam->xpt_bus_deregister)(path_id); + path_id = -1; + } + delete_sem(usb_serial_lock); + put_module(B_USB_MODULE_NAME); + put_module(B_CAM_FOR_SIM_MODULE_NAME); + } else { + atomic_add(&load_count, 1); + } + break; + } + return status; +} + +/** + Declare our module_info so we can be loaded as a kernel module +*/ +static sim_module_info sim_usb_module = { + { "busses/scsi/usb/v1", 0, &std_ops } +}; +/** + Export module_info-s list +*/ +_EXPORT module_info *modules[] = { + (module_info *) &sim_usb_module, + NULL +}; diff --git a/src/add-ons/kernel/busses/scsi/usb/usb_scsi.devices b/src/add-ons/kernel/busses/scsi/usb/usb_scsi.devices new file mode 100644 index 0000000000..fbc4e19da7 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/usb_scsi.devices @@ -0,0 +1,76 @@ +########################################################## +## +## USB Storage Module non-standard devices definitions +## +## This file is a part of BeOS USB SCSI interface module project. +## Copyright (c) 2003-2005 by Siarzhuk Zharski +## All rights reserved. +## +########################################################## +## +## To use the those devices definitions, listed below copy +## it to your settings file. For more details look in ReadMe.html +## + +########################################################## +# +# Sony DSC series of digital cameras. +# +# ( reported by CKJ ) +# +# Those devices report subclass (command set) as 0xff +# but work with transparent SCSI command set +# +vendor 0x054c { + device 0x0010 { + commandset SCSI + protocol CB + } +} +########################################################## +# +# Sony cameras. +# +# (reported by RudolfC) +# +# Sony DV handycam DCR-TRV22E USB mass storage interface +# Those devices report subclass (command set) as 0xff +# but work with transparent SCSI command set +# +vendor 0x054c { + device 0x002e { + commandset SCSI + protocol CB + } +} + + +########################################################## +# +# Siemens mp3 Player. +# +# Supports standard protocol but doesn't like 6-byte mode_sense/mode_select +# requests. Doesn't perform standard reset procedures - if device hang - switch +# it off and plug it again. +# +vendor 0x0483 { + device 0x1307 { + protocol BULK + commandset SCSI + use_mode_sense_10 + } +} + +########################################################## +# +# FREECOM USB-ATAPI bridge. +# +# Supports FREECOM USB Cable connected CD/DVD drives/burners +# +# +vendor 0x07ab { + device 0xfc01 { + protocol freecom + commandset ATAPI + } +} diff --git a/src/add-ons/kernel/busses/scsi/usb/usb_scsi.h b/src/add-ons/kernel/busses/scsi/usb/usb_scsi.h new file mode 100644 index 0000000000..67925e9722 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/usb_scsi.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2003-2005 by Siarzhuk Zharski + * Distributed under the terms of the BSD License. + * + */ + +#ifndef _USB_SCSI_H_ + #define _USB_SCSI_H_ + +#ifndef _OS_H + #include +#endif //_OS_H + +#ifndef _USB_V3_H + #include "USB_v3.h" +#endif /* _USB_V3_H */ + +#ifndef _CAM_H + #include +#endif /*_CAM_H*/ + +#define MODULE_NAME "usb_scsi" + +#define CONTROLLER_SCSI_BUS 0x00 /* Narrow SCSI bus. Use PI_* to alter this*/ +#define MAX_DEVICES_COUNT 0x07 /* simulate Narrow SCSI bus - 8 devices*/ +#define CONTROLLER_SCSI_ID 0x07 /* "controller" SCSI ID */ +#define MAX_LUNS_COUNT 0x08 + +/* transport protocol definitions - are not bitmasks */ +#define PROTO_NONE 0x00000000 +#define PROTO_BULK_ONLY 0x00000001 +#define PROTO_CB 0x00000002 +#define PROTO_CBI 0x00000003 + +#define PROTO_VENDOR 0x0000000e +#define PROTO_MASK 0x0000000f + +#define PROTO(__value) ((__value) & PROTO_MASK) + +/* command set definitions - are not bitmasks */ +#define CMDSET_NONE 0x00000000 +#define CMDSET_SCSI 0x00000010 +#define CMDSET_UFI 0x00000020 +#define CMDSET_ATAPI 0x00000030 +#define CMDSET_RBC 0x00000040 +#define CMDSET_QIC157 0x00000050 + +#define CMDSET_VENDOR 0x000000e0 +#define CMDSET_MASK 0x000000f0 + +#define CMDSET(__value)((__value) & CMDSET_MASK) + +#define HAS_SET(__mask, __flag) \ + (((__mask) & __flag) == (__flag)) + +/* fixes - bitmasked */ +#define FIX_NO_GETMAXLUN 0x00000100 +#define FIX_FORCE_RW_TO_6 0x00000200 +#define FIX_NO_TEST_UNIT 0x00000400 +#define FIX_NO_INQUIRY 0x00000800 +#define FIX_TRANS_TEST_UNIT 0x00001000 +#define FIX_NO_PREVENT_MEDIA 0x00002000 +#define FIX_FORCE_MS_TO_10 0x00004000 +#define FIX_FORCE_READ_ONLY 0x00008000 + +#define FIX_NONE 0x00000000 +#define FIX_MASK 0x000fff00 + +#define HAS_FIXES(__value, __fix) \ + HAS_SET((__value), (__fix)) + +#endif /*_USB_SCSI_H_*/ diff --git a/src/add-ons/kernel/busses/scsi/usb/usb_scsi.settings.sample b/src/add-ons/kernel/busses/scsi/usb/usb_scsi.settings.sample new file mode 100644 index 0000000000..51c00f91c2 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/usb/usb_scsi.settings.sample @@ -0,0 +1,30 @@ +########################################################## +## +## USB Storage Module settings file +## +## This file is a part of BeOS USB SCSI interface module project. +## Copyright (c) 2003-2005 by Siarzhuk Zharski +## All rights reserved. +## +########################################################## +## This file typically placed in following directory: +## /boot/home/config/settings/kernel/drivers/ +########################################################## +## +## More details on using this settings file and +## detailed parameters reference are in the ReadMe.html +## + +#reserve_devices 2 # count of device entries reserved by this SIM. default is 2 +#reserve_luns 4 # count of LUNs available for every reserved device entry. default is 4 + +#ignore_sysinit2 true # workaround for some R5 + USB patches boot problem + +#debug_output true # activates debug output +#debug_output_in_file true # use /var/log/usb_scsi.log instead of syslog +#debug_output_file_rewrite true # truncate log file on system reboot + +#debug_trace_protocol true # dump USB MS protocol information +#debug_trace_sense_data true # dump additional USB MS protocol information +#debug_trace_capacity true # dump READ CAPACITY SCSI command results + diff --git a/src/add-ons/kernel/drivers/Jamfile b/src/add-ons/kernel/drivers/Jamfile index bc1706673d..a0fbf56faf 100644 --- a/src/add-ons/kernel/drivers/Jamfile +++ b/src/add-ons/kernel/drivers/Jamfile @@ -10,6 +10,8 @@ SubInclude HAIKU_TOP src add-ons kernel drivers graphics ; SubInclude HAIKU_TOP src add-ons kernel drivers midi ; SubInclude HAIKU_TOP src add-ons kernel drivers misc ; SubInclude HAIKU_TOP src add-ons kernel drivers network ; +SubInclude HAIKU_TOP src add-ons kernel drivers ports ; SubInclude HAIKU_TOP src add-ons kernel drivers power ; SubInclude HAIKU_TOP src add-ons kernel drivers random ; SubInclude HAIKU_TOP src add-ons kernel drivers tty ; +SubInclude HAIKU_TOP src add-ons kernel drivers video ; diff --git a/src/add-ons/kernel/drivers/audio/Jamfile b/src/add-ons/kernel/drivers/audio/Jamfile index cf2c7658b8..1f4ac62a2e 100644 --- a/src/add-ons/kernel/drivers/audio/Jamfile +++ b/src/add-ons/kernel/drivers/audio/Jamfile @@ -3,5 +3,6 @@ SubDir HAIKU_TOP src add-ons kernel drivers audio ; SubInclude HAIKU_TOP src add-ons kernel drivers audio ac97 ; SubInclude HAIKU_TOP src add-ons kernel drivers audio echo ; SubInclude HAIKU_TOP src add-ons kernel drivers audio emuxki ; -SubInclude HAIKU_TOP src add-ons kernel drivers audio usb_audio ; SubInclude HAIKU_TOP src add-ons kernel drivers audio module_driver ; +SubInclude HAIKU_TOP src add-ons kernel drivers audio sis7018 ; +SubInclude HAIKU_TOP src add-ons kernel drivers audio usb_audio ; diff --git a/src/add-ons/kernel/drivers/audio/sis7018/Jamfile b/src/add-ons/kernel/drivers/audio/sis7018/Jamfile new file mode 100644 index 0000000000..837caf6bfc --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/Jamfile @@ -0,0 +1,25 @@ +SubDir HAIKU_TOP src add-ons kernel drivers audio sis7018 ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +UsePrivateHeaders audio ; + +KernelAddon sis7018 : kernel drivers bin : + ac97.c + midi.c + pcm.c + sis7018.c + sis7018hw.c +; + +AddResources sis7018 : vsis7018.rdef ; + +Package haiku-sis7018-cvs + : + sis7018 + : + boot home config add-ons kernel drivers bin ; + +PackageDriverSymLink haiku-sis7018-cvs : audio sis7018 ; +Package haiku-sis7018-cvs : sis7018.settings.sample + : boot home config settings kernel drivers sample ; diff --git a/src/add-ons/kernel/drivers/audio/sis7018/ReadMe b/src/add-ons/kernel/drivers/audio/sis7018/ReadMe new file mode 100644 index 0000000000..a0a5b5bdbe --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/ReadMe @@ -0,0 +1,84 @@ +BeOS sound driver for SiS 7018 PCI Audio Accelerator + +This driver is designed to supports following chipsets: +SiS 7018 (vendor:1039 card:7018) +Trident 4D Wave DX (vendor:1023 card:2000) +Trident 4D Wave NX (vendor:1023 card:2001) - not tested +Acer Lab's M5451 (vendor:10b9 card:5451) + +What's new: +----------------------------------------------------------------------------------------------- +version 0.1.0-dev-8 +* The AC'97 codec id checking restored. +- to be continued! + +version 0.1.0-dev-7 + * Added use_io_registers to settings file. Just for testers. + * The AC'97 codec id checking bypassed - for testing purposes only + +version 0.1.0-dev-6 + * Fixed problem with "Real-time Audio". Currently works in this mode too. + +version 0.1.0-dev-5 + * Fixed AC'97 codec handling - 6bit master gain codecs schould be supported correctly + + For testing purposes added Trident DX with vendorID : 0x03 - such card found + by one tester. + +version 0.1.0-dev-4 ++ Finished some codec manipulations - mio volumes, mio mutes etc. + +version 0.1.0-dev-3 +* Fixed "last thrashed" sample problem ++ makefile and install script are fixed. + +version 0.1.0-dev-2 +* changed AC'97 initialization ++ Added settings file ++ Added possibility to write into private log file ++ More complicated AC'97 tracing possible ... + +version 0.1.0-dev-1 +* changed AC'97 initialization + +version 0.1.0-dev-0 + initial build. +----------------------------------------------------------------------------------------------- + +!!! WANTED !!! +Wanted testers with Trident NX sound hardware. Current driver is not tested on such hardware. It'll be good to asure that it work with that cards too! + +Installation +Run install.sh + +Uninstallation +Run uninstall.sh + +Problems solving +If this driver crash your system - reboot and press "Space" during load. In boot menu select "Disable user add-ons" and continue boot. Uninstall driver and reboot again into normal mode. Write me a e-mail about this problem. + +Professional testing: +If you found a problem with this driver and want to help me in development of this software make the following things (Assume that driver is already installed): + +1) Open the file /boot/home/config/settings/kernel/drivers/sis7018 and set following parameters: + +debug_output true +debug_output_in_file true + +if you have a problems with mixer - it's not work, or settings is not saved on reboot - activate this one too: + +debug_trace_ac97 true + +2) Reboot your system and try to play something. + +3) After that get the file /boot/home/sis7018.log and send it to me. + +4) It'll be good on your first bug report to me send also hardware configuration of your system. To get it go into Terminal and run following commands + +listdev + +Get all that it say to you and send me too, please ... + +Thank you !!! + +Siarzuk Zharski +http://www.zharik.host.sk/ diff --git a/src/add-ons/kernel/drivers/audio/sis7018/ac97.c b/src/add-ons/kernel/drivers/audio/sis7018/ac97.c new file mode 100644 index 0000000000..8d806b870c --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/ac97.c @@ -0,0 +1,605 @@ +/* + * This file is a part of SiS 7018 BeOS driver project. + * Copyright (c) 2002-2003 by Siarzuk Zharski + * Portional Copyright (c) 1999 Cameron Grant + * + * This file may be used under the terms of the BSD License + * See the file "License" for details. + */ +#include "sis7018.h" +#include "sis7018hw.h" +#include "t4dwave.h" +#include "ac97.h" +//#include "pcm.h" + +#define TR_TIMEOUT_CDC 0xffff + +//typedef bool (*ac97init_proc)(sis7018_dev *dev, bool bOn); +/* init functions*/ +status_t ac97init_CS4299(sis7018_dev *dev, bool bOn); +status_t ac97init_default(sis7018_dev *dev, bool bOn); + +static struct ac97_codecid +{ + uint32 id; + int noext; + char *name; + status_t (*ac97init)(sis7018_dev *dev, bool bOn); +} ac97codecid[] = { + { 0x41445303, 0, "Analog Devices AD1819", NULL }, + { 0x41445340, 0, "Analog Devices AD1881", NULL }, + { 0x41445348, 0, "Analog Devices AD1881A", NULL }, + { 0x41445360, 0, "Analog Devices AD1885", NULL }, + { 0x414b4d00, 1, "Asahi Kasei AK4540", NULL }, + { 0x414b4d01, 1, "Asahi Kasei AK4542", NULL }, + { 0x414b4d02, 1, "Asahi Kasei AK4543", NULL }, + { 0x414c4710, 0, "Avance Logic ALC200/200P", NULL }, + { 0x43525900, 0, "Cirrus Logic CS4297", NULL }, + { 0x43525903, 0, "Cirrus Logic CS4297", NULL }, + { 0x43525913, 0, "Cirrus Logic CS4297A", NULL }, + { 0x43525914, 0, "Cirrus Logic CS4297B", NULL }, + { 0x43525923, 0, "Cirrus Logic CS4294C", NULL }, + { 0x4352592b, 0, "Cirrus Logic CS4298C", NULL }, + { 0x43525931, 0, "Cirrus Logic CS4299A", ac97init_CS4299 }, + { 0x43525933, 0, "Cirrus Logic CS4299C", ac97init_CS4299 }, + { 0x43525934, 0, "Cirrus Logic CS4299D", ac97init_CS4299 }, + { 0x43525941, 0, "Cirrus Logic CS4201A", NULL }, + { 0x43525951, 0, "Cirrus Logic CS4205A", NULL }, + { 0x43525961, 0, "Cirrus Logic CS4291A", NULL }, + { 0x45838308, 0, "ESS Technology ES1921", NULL }, + { 0x49434511, 0, "ICEnsemble ICE1232", NULL }, + { 0x4e534331, 0, "National Semiconductor LM4549", NULL }, + { 0x83847600, 0, "SigmaTel STAC9700/9783/9784", NULL }, + { 0x83847604, 0, "SigmaTel STAC9701/9703/9704/9705", NULL }, + { 0x83847605, 0, "SigmaTel STAC9704", NULL }, + { 0x83847608, 0, "SigmaTel STAC9708/9711", NULL }, + { 0x83847609, 0, "SigmaTel STAC9721/9723", NULL }, + { 0x83847644, 0, "SigmaTel STAC9744", NULL }, + { 0x83847656, 0, "SigmaTel STAC9756/9757", NULL }, + { 0x53494c22, 0, "Silicon Laboratory Si3036", NULL }, + { 0x53494c23, 0, "Silicon Laboratory Si3038", NULL }, + { 0x54524103, 0, "TriTech TR?????", NULL }, + { 0x54524106, 0, "TriTech TR28026", NULL }, + { 0x54524108, 0, "TriTech TR28028", NULL }, + { 0x54524123, 0, "TriTech TR28602", NULL }, + { 0x574d4c00, 0, "Wolfson WM9701A", NULL }, + { 0x574d4c03, 0, "Wolfson WM9703/9704", NULL }, + { 0x574d4c04, 0, "Wolfson WM9704 (quad)", NULL }, + { 0, 0, NULL } +}; + +static char *ac97enhancement[] = { + "no 3D Stereo Enhancement", + "Analog Devices Phat Stereo", + "Creative Stereo Enhancement", + "National Semi 3D Stereo Enhancement", + "Yamaha Ymersion", + "BBE 3D Stereo Enhancement", + "Crystal Semi 3D Stereo Enhancement", + "Qsound QXpander", + "Spatializer 3D Stereo Enhancement", + "SRS 3D Stereo Enhancement", + "Platform Tech 3D Stereo Enhancement", + "AKM 3D Audio", + "Aureal Stereo Enhancement", + "Aztech 3D Enhancement", + "Binaura 3D Audio Enhancement", + "ESS Technology Stereo Enhancement", + "Harman International VMAx", + "Nvidea 3D Stereo Enhancement", + "Philips Incredible Sound", + "Texas Instruments 3D Stereo Enhancement", + "VLSI Technology 3D Stereo Enhancement", + "TriTech 3D Stereo Enhancement", + "Realtek 3D Stereo Enhancement", + "Samsung 3D Stereo Enhancement", + "Wolfson Microelectronics 3D Enhancement", + "Delta Integration 3D Enhancement", + "SigmaTel 3D Enhancement", + "KS Waves", + "Rockwell 3D Stereo Enhancement", + "Reserved 29", + "Reserved 30", + "Reserved 31" +}; + +static char *ac97feature[] = { + "mic channel", + "reserved", + "tone", + "simulated stereo", + "headphone", + "bass boost", + "18 bit DAC", + "20 bit DAC", + "18 bit ADC", + "20 bit ADC" +}; + +static char *ac97extfeature[] = { + "variable rate PCM", + "double rate PCM", + "reserved 1", + "variable rate mic", + "reserved 2", + "reserved 3", + "center DAC", + "surround DAC", + "LFE DAC", + "AMAP", + "reserved 4", + "reserved 5", + "reserved 6", + "reserved 7", +}; + +int ac97read(sis7018_dev *dev, int regno) +{ + cpu_status cp; + int i, j, reg, rw; + if(b_trace_ac97) + TRACE(" ac97read: regno=%x\n", regno); + + switch (dev->type->ids.chip_id){ + case SPA_PCI_ID: + reg=SPA_REG_CODECRD; + rw=SPA_CDC_RWSTAT; + break; + case ALI_PCI_ID: + if(dev->info.revision > 0x01) + reg=TDX_REG_CODECWR; + else + reg=TDX_REG_CODECRD; + rw=TDX_CDC_RWSTAT; + break; + case TDX_PCI_ID: + case xDX_PCI_ID: + reg=TDX_REG_CODECRD; + rw=TDX_CDC_RWSTAT; + break; + case TNX_PCI_ID: + reg=(regno & 0x100)? TNX_REG_CODEC2RD : TNX_REG_CODEC1RD; + rw=TNX_CDC_RWSTAT; + break; + default: + TRACE("ac97read defaulted !!!\n"); + return ENODEV; + } + + cp = disable_interrupts(); + acquire_spinlock(&dev->hardware); + + regno &= 0x7f; + + if(dev->type->ids.chip_id == ALI_PCI_ID){ + j = rw; + for (i=TR_TIMEOUT_CDC; (i > 0) && (j & rw); i--){ + j = hw_read(dev, reg, 4); + } + if(i > 0){ + uint32 c1 = hw_read(dev, 0xc8, 4); + uint32 c2 = hw_read(dev, 0xc8, 4); + for(i=TR_TIMEOUT_CDC; (i > 0) && (c1 == c2); i--){ + c2 = hw_read(dev, 0xc8, 4); + } + } + } + if(dev->type->ids.chip_id != ALI_PCI_ID || i > 0){ + hw_write(dev, reg, regno | rw, 4); + j=rw; + for (i=TR_TIMEOUT_CDC; (i > 0) && (j & rw); i--){ + j=hw_read(dev, reg, 4); + } + } + + release_spinlock(&dev->hardware); + restore_interrupts(cp); + + if (i == 0) + TRACE_ALWAYS("ac97 codec timeout during read of register %x\n", regno); + if(b_trace_ac97) + TRACE(" ac97read: regno=%x ret = %x\n", regno, j); + return (j >> TR_CDC_DATA) & 0xffff; +} + +status_t ac97write(sis7018_dev *dev, int regno, uint32 data) +{ + cpu_status cp; + int i, j, reg, rw; + + if(b_trace_ac97) + TRACE("\nac97write: regno=%x, data=%lx\n", regno, data); + + switch (dev->type->ids.chip_id){ + case SPA_PCI_ID: + reg=SPA_REG_CODECWR; + rw=SPA_CDC_RWSTAT; + break; + case ALI_PCI_ID: + case TDX_PCI_ID: + case xDX_PCI_ID: + reg=TDX_REG_CODECWR; + rw=TDX_CDC_RWSTAT; + break; + case TNX_PCI_ID: + reg=TNX_REG_CODECWR; + rw=TNX_CDC_RWSTAT | ((regno & 0x100)? TNX_CDC_SEC : 0); + break; + default: + TRACE("ac97write defaulted !!!"); + return ENODEV; + } + + regno &= 0x7f; + if(b_trace_ac97) + TRACE("ac97write: reg %x was %x\n", regno, ac97read(dev, regno)); + + cp = disable_interrupts(); + acquire_spinlock(&dev->hardware); + j=rw; + + if(dev->type->ids.chip_id == ALI_PCI_ID){ + for(i = TR_TIMEOUT_CDC; (i > 0) && (j & rw); i--){ + j = hw_read(dev, reg, 4); + } + if(i > 0) { + uint32 c1 = hw_read(dev, 0xc8, 4); + uint32 c2 = hw_read(dev, 0xc8, 4); + for (i = TR_TIMEOUT_CDC; (i > 0) && (c1 == c2); i--) + c2 = hw_read(dev, 0xc8, 4); + } + } + if(dev->type->ids.chip_id != ALI_PCI_ID || i > 0){ + for(i=TR_TIMEOUT_CDC; (i>0) && (j & rw); i--){ + j=hw_read(dev, reg, 4); + } + if(dev->type->ids.chip_id == ALI_PCI_ID && dev->info.revision > 0x01) + rw |= 0x0100; + hw_write(dev, reg, (data << TR_CDC_DATA) | regno | rw, 4); + } + + release_spinlock(&dev->hardware); + restore_interrupts(cp); + + if(b_trace_ac97) + TRACE("ac97write: wrote %x, now %x\n", data, ac97read(dev, regno)); + if (i==0) + TRACE_ALWAYS("ac97 codec timeout writing %x, data %lx\n", regno, data); + if(b_trace_ac97) + TRACE("ac97write: ret = %x\n\n", i); + return (i > 0)? B_OK : B_TIMED_OUT; +} + +status_t ac97init(sis7018_dev *card) +{ +// cpu_status cp; + status_t err=B_OK; + int i, /*j,*/ caps, se, noext, extcaps, extid, extstat, reg=0; + int32 id; +/* old manner + err |= ac97write(card, AC97_REG_POWER, 0); + err |= ac97write(card, AC97_REG_RESET, 0); + + err |= ac97write(card, AC97_MIX_PCM, 0x707); + err |= ac97write(card, AC97_MIX_BEEP, 0x06); + err |= ac97write(card, AC97_MIX_MIC, 0x8000); + err |= ac97write(card, AC97_MIX_PHONE, 0x707); + err |= ac97write(card, AC97_MIX_PHONES, 0x707); +*/ + + //BSD init manner + err |= ac97write(card, AC97_REG_POWER, 0x0000); + err |= ac97write(card, AC97_REG_RESET, 0); + snooze(100000); + //snooze(50000); + err |= ac97write(card, AC97_REG_POWER, 0x0000); + err |= ac97write(card, AC97_REG_GEN, 0x0000); + +/* Marcus's init manner*/ +// err |= ac97write(card, AC97_REG_RESET, 0); +// snooze(50000); // 50 ms + + if (err != B_OK){ + TRACE("ac97 codec resetting failed: %lx\n", err); + return ENODEV; + } + +// cp = disable_interrupts(); +// acquire_spinlock(&card->hardware); + + i = ac97read(card, AC97_REG_RESET); + caps = i & 0x03ff; + se = (i & 0x7c00) >> 10; + + id = (ac97read(card, AC97_REG_ID1) << 16) | ac97read(card, AC97_REG_ID2); +// codec->rev = id & 0x000000ff; + +// release_spinlock(&card->hardware); +// restore_interrupts(cp); +#if 1 + if (id == 0 || id == 0xffffffff){ + TRACE("ac97 codec invalid or not present (id == %lx)\n", id); + return ENODEV; + } +#endif + noext = 0; + for (i = 0; ac97codecid[i].id; i++){ + if (ac97codecid[i].id == id){ + status_t err = B_OK; + noext = ac97codecid[i].noext; + if (ac97codecid[i].name) + TRACE("\nac97 codec id 0x%08lx (%s)\n", id, ac97codecid[i].name); + if(ac97codecid[i].ac97init) + err |= (*ac97codecid[i].ac97init)(card, true); + else + err |= ac97init_default(card, true); + if(err != B_OK) + TRACE("ac97 codec initializatin error\n"); + } + } + + TRACE("ac97 codec features:\n"); + + for (i = 0; i < 10; i++) + if (caps & (1 << i)) + TRACE("> %s\n", ac97feature[i]); + TRACE("> %s\n", ac97enhancement[se]); + TRACE("\n"); + + extcaps = 0; + extid = 0; + extstat = 0; + if (!noext){ + i = ac97read(card, AC97_REGEXT_ID); + if (i != 0xffff){ + extcaps = i & 0x3fff; + extid = (i & 0xc000) >> 14; + extstat = ac97read(card, AC97_REGEXT_STAT) & AC97_EXTCAPS; + } + } + + if (extcaps != 0 || extid){ + TRACE("\nac97 %s codec %s:\n", extid? "secondary" : "primary", + extcaps? "extended features":""); + for (i = 0; i < 14; i++) + if (extcaps & (1 << i)) + TRACE("> %s\n", ac97extfeature[i]); + TRACE("\n"); + } + + if ((ac97read(card, AC97_REG_POWER) & 2) == 0) + TRACE("ac97 codec reports dac not ready\n"); + +// some addition + + reg = ac97read(card, AC97_MIX_MASTER); + err |= ac97write(card, AC97_MIX_MASTER, 0x3f3f); + if(0x3f3f == ac97read(card, AC97_MIX_MASTER)){ + TRACE("AC97 master gain is wide!\n"); + card->ac97.wide_main_gain = true; + } + err |= ac97write(card, AC97_MIX_MASTER, reg); + +// BSD manner + err |= ac97write(card, AC97_MIX_PCM, 0x707); +// err |= ac97write(card, AC97_MIX_BEEP, 0x06); +// err |= ac97write(card, AC97_MIX_MIC, 0x8000); +// err |= ac97write(card, AC97_MIX_PHONE, 0x707); +// err |= ac97write(card, AC97_MIX_PHONES, 0x707); + +/*Marcus's manner*/ + // err |= ac97write(card, AC97_MIX_MASTER, 0x00); + // err |= ac97write(card, AC97_MIX_PCM, 0x404); + + return err; +} + +status_t ac97get_params(sis7018_dev *dev, sound_setup *sound) +{ + uint16 reg = 0; + int main_gain_multiplier = dev->ac97.wide_main_gain ? 1 : 2; + + sound->sample_rate = kHz_48_0; + sound->dither_enable = false; + sound->output_boost = 0; + sound->highpass_enable = 0; + + reg=ac97read(dev, AC97_MIX_MONO); + sound->mono_gain = (char)reg; + sound->mono_mute = (char)(reg & AC97_MUTE) ? 1 : 0; + + reg=ac97read(dev, AC97_REG_RECSEL); + switch (reg&0x07){ + case 4: sound->right.adc_source = line; break; + case 3: sound->right.adc_source = aux1; break; + case 0: sound->right.adc_source = mic; break; + default: sound->right.adc_source = loopback; break; + } + + switch ((reg >> 8) & 0x07){ + case 4: sound->left.adc_source = line; break; + case 3: sound->left.adc_source = aux1; break; + case 0: sound->left.adc_source = mic; break; + default: sound->left.adc_source = loopback; break; + } + + reg = ac97read(dev, AC97_MIX_MIC); + sound->loop_attn = (reg & 0x1f)*2; + sound->loop_enable = (reg & AC97_MUTE) ? 0 : 1; + sound->left.mic_gain_enable = + sound->right.mic_gain_enable = (reg >> 6) & 0x01; + + reg = ac97read(dev, AC97_MIX_RGAIN); + sound->left.adc_gain = (reg >> 0x8) & 0xf; + sound->right.adc_gain = reg & 0xf; + + reg = ac97read(dev, AC97_MIX_CD); + sound->left.aux1_mix_gain = ((reg >> 8) & 0x1f); + sound->right.aux1_mix_gain = (reg & 0x1f); + sound->left.aux1_mix_mute = + sound->right.aux1_mix_mute = (reg & AC97_MUTE) ? 1 : 0; + + reg = ac97read(dev, AC97_MIX_AUX); + sound->left.aux2_mix_gain = ((reg >> 8) & 0x1f); + sound->right.aux2_mix_gain = (reg & 0x1f); + sound->left.aux2_mix_mute = + sound->right.aux2_mix_mute = (reg & AC97_MUTE) ? 1 : 0; + + + reg = ac97read(dev, AC97_MIX_LINE); + sound->left.line_mix_gain = ((reg >> 8) & 0x1f); + sound->right.line_mix_gain = (reg & 0x1f); + sound->left.line_mix_mute = + sound->right.line_mix_mute = (reg & AC97_MUTE) ? 1 : 0; + + reg = ac97read(dev, AC97_MIX_MASTER); + sound->left.dac_attn = ((reg >> 8) & 0x1f) * main_gain_multiplier; + sound->right.dac_attn = (reg & 0x1f) * main_gain_multiplier; + sound->left.dac_mute = + sound->right.dac_mute = (reg & AC97_MUTE) ? 1 : 0; + + return B_OK; +} + +status_t ac97set_params(sis7018_dev *dev, sound_setup * sound) +{ + status_t err = B_OK; + uint16 reg = 0; + int main_gain_divider = dev->ac97.wide_main_gain ? 1 : 2; + +#if 0 //DEBUG + TRACE("\nsound setup (left/right)\n"); + TRACE("adc_source %x/%x\n", sound->left.adc_source, sound->right.adc_source); + TRACE("adc_gain %x/%x\n", sound->left.adc_gain, sound->right.adc_gain); + TRACE("mic_gain_enable %x/%x\n", sound->left.mic_gain_enable, sound->right.mic_gain_enable); + TRACE("aux1_mix_gain %x/%x\n", sound->left.aux1_mix_gain, sound->right.aux1_mix_gain); + TRACE("aux1_mix_mute %x/%x\n", sound->left.aux1_mix_mute, sound->right.aux1_mix_mute); + TRACE("aux2_mix_gain %x/%x\n", sound->left.aux2_mix_gain, sound->right.aux2_mix_gain); + TRACE("aux2_mix_mute %x/%x\n", sound->left.aux2_mix_mute, sound->right.aux2_mix_mute); + TRACE("line_mix_gain %x/%x\n", sound->left.line_mix_gain, sound->right.line_mix_gain); + TRACE("line_mix_mute %x/%x\n", sound->left.line_mix_mute, sound->right.line_mix_mute); + TRACE("dac_attn %x/%x\n", sound->left.dac_attn, sound->right.dac_attn); + TRACE("dac_mute %x/%x\n", sound->left.dac_mute, sound->right.dac_mute); + TRACE("sound setup\n"); + TRACE("sample_rate %x\n", sound->sample_rate); + TRACE("playback_format %x\n", sound->playback_format); + TRACE("capture_format %x\n", sound->capture_format); + TRACE("dither_enable %x\n", sound->dither_enable); + TRACE("loop_attn %x\n", sound->loop_attn); + TRACE("loop_enable %x\n", sound->loop_enable); + TRACE("output_boost %x\n", sound->output_boost); + TRACE("highpass_enable %x\n", sound->highpass_enable); + TRACE("mono_gain %x\n", sound->mono_gain); + TRACE("mono_mute %x\n", sound->mono_mute); +#endif +//TRACE("sample-rate:%d\n", sound->sample_rate); + sound->sample_rate = kHz_48_0; + sound->dither_enable = false; + sound->output_boost = 0; + sound->highpass_enable = 0; + + reg = sound->mono_gain | ((sound->mono_mute) ? AC97_MUTE : 0); + err |= ac97write(dev, AC97_MIX_MONO, reg); + + reg = sound->loop_attn / 2; + reg |= ((sound->left.mic_gain_enable || sound->right.mic_gain_enable) ? 0x01 : 0x00) << 6; + reg |= (sound->loop_enable) ? 0 : AC97_MUTE; + err |= ac97write(dev, AC97_MIX_MIC, reg); + + reg = 0; + switch(sound->left.adc_source){ + case line: reg = 4; break; + case aux1: reg = 3; break; + case mic: reg = 0; break; + default: reg = 0; break; + } + + reg <<= 8; + switch(sound->right.adc_source){ + case line: reg |= 4; break; + case aux1: reg |= 3; break; + case mic: reg |= 0; break; + default: reg |= 0; break; + } + + err |= ac97write(dev, AC97_REG_RECSEL, reg); + + reg = (sound->left.adc_gain) << 8; + reg |= sound->right.adc_gain; + err |= ac97write(dev, AC97_MIX_RGAIN, reg); + + reg = (sound->left.aux1_mix_gain) << 0x08; + reg |= sound->right.aux1_mix_gain; + reg |= (sound->left.aux1_mix_mute || sound->right.aux1_mix_mute) ? AC97_MUTE : 0 ; + err |= ac97write(dev, AC97_MIX_CD, reg); + + reg = (sound->left.aux2_mix_gain) << 0x08; + reg |= sound->right.aux2_mix_gain; + reg |= (sound->left.aux2_mix_mute || sound->right.aux2_mix_mute) ? AC97_MUTE : 0 ; + err |= ac97write(dev, AC97_MIX_AUX, reg); + + reg = (sound->left.line_mix_gain) << 0x08; + reg |= sound->right.line_mix_gain; + reg |= (sound->left.line_mix_mute || sound->right.line_mix_mute) ? AC97_MUTE : 0 ; + err |= ac97write(dev, AC97_MIX_LINE, reg); + + reg = ((sound->left.dac_attn) / main_gain_divider) << 0x08; + reg |= (sound->right.dac_attn) / main_gain_divider; + reg |= (sound->left.dac_mute || sound->right.dac_mute) ? AC97_MUTE : 0 ; + err |= ac97write(dev, AC97_MIX_MASTER, reg); + + return err; +} + +status_t ac97init_default(sis7018_dev *dev, bool bOn) +{ + status_t err = B_OK; + //TRACE("powerdown register was = %#04x\n",ich_codec_read(AC97_POWERDOWN))); +// if (bOn) +// ac97write(dev, AC97_REG_POWER, ac97read(dev, AC97_REG_POWER) & ~0x8000); /* switch on (low active) */ +// else +// ac97write(dev, AC97_REG_POWER, ac97read(dev, AC97_REG_POWER) | 0x8000); /* switch off */ + //LOG(("powerdown register is = %#04x\n",ich_codec_read(AC97_POWERDOWN))); + return err; +} + +status_t ac97init_CS4299(sis7018_dev *dev, bool bOn) +{ + status_t err = B_OK; + TRACE("Use CS4299 init\n"); + // if (bOn) +// err |= ac97write(dev, 0x68, 0x8004); +// else +// err |= ac97write(dev, 0x68, 0); + return err; +} + +#if DEBUG +static struct +{ + int16 reg; + char name[DEVNAME]; +} ac97_regs[]= +{ + {AC97_REG_RESET, "Reset"}, {AC97_MIX_MASTER, "Master Volume"}, + {AC97_MIX_PHONES, "AUX Out volume"}, {AC97_MIX_MONO, "Mono Volume"}, + {AC97_MIX_TONE, "Master Tone"}, {AC97_MIX_BEEP, "PC Beep"}, + {AC97_MIX_PHONE, "Phone volume"}, {AC97_MIX_MIC, "Mio Volume"}, + {AC97_MIX_LINE, "Line In Volume"}, {AC97_MIX_CD, "CD Volume"}, + {AC97_MIX_VIDEO, "Video Volume"}, {AC97_MIX_AUX, "AUX In Volume"}, + {AC97_MIX_PCM, "PCM Out Volume"}, {AC97_REG_RECSEL, "Record Select"}, + {AC97_MIX_RGAIN, "Record Gain"}, {AC97_MIX_MGAIN, "Record Gain Mio"}, + {AC97_REG_GEN, "General Purpose"}, {AC97_REG_3D, "3D Control"}, + {0x24, "Audio Int & Paging"}, {AC97_REG_POWER, "Powerdown Ctrl/Stat"}, + {AC97_REG_ID1, "Vendor ID1"}, {AC97_REG_ID2, "VendorID 2"}, +}; + +void ac97dump(int card_id) +{ + int i; + for(i=0; i < sizeof(ac97_regs)/sizeof(ac97_regs[0]); i++) + kprintf("%s : %x\n", ac97_regs[i].name, ac97read(&cards[card_id], ac97_regs[i].reg)); +} + +#endif //DEBUG + diff --git a/src/add-ons/kernel/drivers/audio/sis7018/ac97.h b/src/add-ons/kernel/drivers/audio/sis7018/ac97.h new file mode 100644 index 0000000000..efad1729a2 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/ac97.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1999 Cameron Grant + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/dev/sound/pcm/ac97.h,v 1.3.2.5 2001/08/01 03:41:03 cg Exp $ + */ + +/* + * This file is a part of SiS 7018 BeOS driver project. + * Copyright permissions see above. + * + * Portion copyright (c) 2002-2003 by Siarzuk Zharski + * + * $Source: /cvsroot/sis4be/sis7018/ac97.h,v $ + * $Author: zharik $ + * $Revision: 1.4 $ + * $Date: 2003/04/08 19:18:37 $ + */ + +#define AC97_MUTE 0x8000 + +#define AC97_REG_RESET 0x00 +#define AC97_MIX_MASTER 0x02 +#define AC97_MIX_PHONES 0x04 +#define AC97_MIX_MONO 0x06 +#define AC97_MIX_TONE 0x08 +#define AC97_MIX_BEEP 0x0a +#define AC97_MIX_PHONE 0x0c +#define AC97_MIX_MIC 0x0e +#define AC97_MIX_LINE 0x10 +#define AC97_MIX_CD 0x12 +#define AC97_MIX_VIDEO 0x14 +#define AC97_MIX_AUX 0x16 +#define AC97_MIX_PCM 0x18 +#define AC97_REG_RECSEL 0x1a +#define AC97_MIX_RGAIN 0x1c +#define AC97_MIX_MGAIN 0x1e +#define AC97_REG_GEN 0x20 +#define AC97_REG_3D 0x22 +#define AC97_REG_POWER 0x26 +#define AC97_REGEXT_ID 0x28 +#define AC97_EXTCAP_VRA (1 << 0) +#define AC97_EXTCAP_DRA (1 << 1) +#define AC97_EXTCAP_VRM (1 << 3) +#define AC97_EXTCAPS (AC97_EXTCAP_VRA | AC97_EXTCAP_DRA | AC97_EXTCAP_VRM) +#define AC97_REGEXT_STAT 0x2a +#define AC97_REGEXT_FDACRATE 0x2c +#define AC97_REGEXT_SDACRATE 0x2e +#define AC97_REGEXT_LDACRATE 0x30 +#define AC97_REGEXT_LADCRATE 0x32 +#define AC97_REGEXT_MADCRATE 0x34 +#define AC97_MIXEXT_CLFE 0x36 +#define AC97_MIXEXT_SURROUND 0x38 +#define AC97_REG_ID1 0x7c +#define AC97_REG_ID2 0x7e + +/* Added by S.Zharski*/ + +status_t ac97init(sis7018_dev *dev); + +int ac97read(sis7018_dev *dev, int regno); +status_t ac97write(sis7018_dev *dev, int regno, uint32 data); + +status_t ac97get_params(sis7018_dev *dev, sound_setup *sound); +status_t ac97set_params(sis7018_dev *dev, sound_setup *sound); + +void ac97dump(int card_id); + +/* +Siarzhuk Zharski: Following not needed in BeOS build. =-) +*/ +/*#define AC97_F_EAPD_INV 0x00000001 + +#define AC97_DECLARE(name) static DEFINE_CLASS(name, name ## _methods, sizeof(struct kobj)) +#define AC97_CREATE(dev, devinfo, cls) ac97_create(dev, devinfo, &cls ## _class) + +struct ac97_info; + +#include "ac97_if.h" + +extern kobj_class_t ac97_getmixerclass(void); + +struct ac97_info *ac97_create(device_t dev, void *devinfo, kobj_class_t cls); +void ac97_destroy(struct ac97_info *codec); +void ac97_setflags(struct ac97_info *codec, u_int32_t val); +u_int32_t ac97_getflags(struct ac97_info *codec); +int ac97_setrate(struct ac97_info *codec, int which, int rate); +int ac97_setextmode(struct ac97_info *codec, u_int16_t mode); +u_int16_t ac97_getextmode(struct ac97_info *codec); +u_int16_t ac97_getextcaps(struct ac97_info *codec); +*/ diff --git a/src/add-ons/kernel/drivers/audio/sis7018/install.sh b/src/add-ons/kernel/drivers/audio/sis7018/install.sh new file mode 100644 index 0000000000..901616bdb7 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/install.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +answer=`alert "Do you really want to install the SiS 7018 driver?" "No" "Yes"` +if [ $answer == "No" ]; then + exit +fi + +/boot/beos/bin/install -d ~/config/add-ons/kernel/drivers/bin/ +/boot/beos/bin/install -d ~/config/settings/kernel/drivers/ +/boot/beos/bin/install -d ~/config/add-ons/kernel/drivers/dev/audio/old/ +/boot/beos/bin/install `dirname $0`/sis7018 ~/config/add-ons/kernel/drivers/bin/ +/boot/beos/bin/cp `dirname $0`/sis7018.settings.sample ~/config/settings/kernel/drivers/sis7018 + +mimeset ~/config/add-ons/kernel/drivers/bin/sis7018 +mimeset ~/config/settings/kernel/drivers/sis7018 + +ln -sf ../../../bin/sis7018 ~/config/add-ons/kernel/drivers/dev/audio/old/sis7018 + +alert "The SiS 7018 driver is installed in your system. + +Go to Preferences->Media and restart media services to activate driver." diff --git a/src/add-ons/kernel/drivers/audio/sis7018/midi.c b/src/add-ons/kernel/drivers/audio/sis7018/midi.c new file mode 100644 index 0000000000..1e3a79d042 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/midi.c @@ -0,0 +1,176 @@ +/* + Copyright 1999, Be Incorporated. All Rights Reserved. + This file may be used under the terms of the Be Sample Code License. +*/ + +/* + * This file is a part of SiS 7018 BeOS driver project. + * Copyright permissions see above. + * + * Portion copyright (c) 2002-2003 by Siarzuk Zharski + */ + +//#include +//#include +//#include + +#include "sis7018.h" +#include "sis7018hw.h" +#include "midi_driver.h" +#include "midi.h" + +generic_mpu401_module *mpu401; + +//extern void dump_card(sonic_vibes_dev * card); + +#if !defined(_KERNEL_EXPORT_H) +#include +#endif /* _KERNEL_EXPORT_H */ + +//#define MIDI_ACTIVE_SENSE 0xfe +//#define SNOOZE_GRANULARITY 500 + +//extern generic_mpu401_module * mpu401; + +void midi_interrupt_op(int32 op, void * data) +{ + midi_dev * port = (midi_dev *)data; + TRACE("port = %p\n", port); + if (op == B_MPU_401_ENABLE_CARD_INT) + { + cpu_status cp; + TRACE("B_MPU_401_ENABLE_CARD_INT\n"); + cp = disable_interrupts(); + acquire_spinlock(&port->card->hardware); + hw_increment_interrupt_handler(port->card); + //set_direct(port->card, 0x01, 0x00, 0x80); + //set_indirect(port->card, 0x2A, 0x04, 0xff); + release_spinlock(&port->card->hardware); + restore_interrupts(cp); + } + else if (op == B_MPU_401_DISABLE_CARD_INT) + { + /* turn off MPU interrupts */ + cpu_status cp; + TRACE("B_MPU_401_DISABLE_CARD_INT\n"); + cp = disable_interrupts(); + acquire_spinlock(&port->card->hardware); + //set_direct(port->card, 0x01, 0x80, 0x80); + /* remove interrupt handler if necessary */ + hw_decrement_interrupt_handler(port->card); + release_spinlock(&port->card->hardware); + restore_interrupts(cp); + } + TRACE("midi_interrupt_op() done\n"); +} + +static status_t midi_open(const char *name, uint32 flags, void **cookie); +static status_t midi_close(void *cookie); +static status_t midi_free(void *cookie); +static status_t midi_control(void *cookie, uint32 op, void *data, size_t len); +static status_t midi_read(void *cookie, off_t pos, void *data, size_t *len); +static status_t midi_write(void *cookie, off_t pos, const void *data, size_t *len); + + +device_hooks midi_hooks = { + &midi_open, + &midi_close, + &midi_free, + &midi_control, + &midi_read, + &midi_write, + NULL, /* select */ + NULL, /* deselect */ + NULL, /* readv */ + NULL /* writev */ +}; + +static status_t midi_open(const char * name, uint32 flags, void ** cookie) +{ + int ix; + int ret; + + TRACE("midi_open()\n"); + + *cookie = NULL; + for (ix=0; ix= num_cards) + { + TRACE("bad device\n"); + return ENODEV; + } + + TRACE("mpu401: %p open(): %p driver: %p\n", mpu401, mpu401->open_hook, cards[ix].midi.driver); + ret = (*mpu401->open_hook)(cards[ix].midi.driver, flags, cookie); + if (ret >= B_OK) + { + cards[ix].midi.cookie = *cookie; + atomic_add(&cards[ix].midi.count, 1); + } + TRACE("mpu401: open returns %x / %p\n", ret, *cookie); + return ret; +} + +static status_t midi_close(void * cookie) +{ + TRACE("midi_close()\n"); + return (*mpu401->close_hook)(cookie); +} + +static status_t midi_free(void * cookie) +{ + int ix; + status_t f; + TRACE("midi_free()\n"); + f = (*mpu401->free_hook)(cookie); + for (ix=0; ixcontrol_hook)(cookie, iop, data, len); +} + +static status_t midi_read( void * cookie, off_t pos, void * ptr, size_t * nread) +{ + TRACE("midi_read\n"); + return (*mpu401->read_hook)(cookie, pos, ptr, nread); +} + +static status_t midi_write(void * cookie, off_t pos, const void * ptr, size_t * nwritten) +{ + TRACE("midi_write\n"); + return (*mpu401->write_hook)(cookie, pos, ptr, nwritten); +} + +bool midi_interrupt( sis7018_dev * dev) +{ + if (!dev->midi.driver) + { +// kprintf("aiigh\n"); + return false; + } + kprintf("midi_interrupt\n"); + return (*mpu401->interrupt_hook)(dev->midi.driver); +} + diff --git a/src/add-ons/kernel/drivers/audio/sis7018/midi.h b/src/add-ons/kernel/drivers/audio/sis7018/midi.h new file mode 100644 index 0000000000..6ee6616bdd --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/midi.h @@ -0,0 +1,19 @@ +/* + * This file is a part of SiS 7018 BeOS driver project. + * Copyright (c) 2002-2003 by Siarzuk Zharski + * + * This file may be used under the terms of the BSD License + * See the file "License" for details. + */ + +#ifndef _MIDI_H_ + #define _MIDI_H_ + +#ifndef _DRIVERS_H + #include +#endif //_DRIVERS_H + +extern device_hooks midi_hooks; +void midi_interrupt_op(int32 op, void * data); +extern generic_mpu401_module *mpu401; +#endif //_MIDI_H_ diff --git a/src/add-ons/kernel/drivers/audio/sis7018/midi_driver.h b/src/add-ons/kernel/drivers/audio/sis7018/midi_driver.h new file mode 100644 index 0000000000..2d0eff4355 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/midi_driver.h @@ -0,0 +1,117 @@ +/* + Copyright 1999, Be Incorporated. All Rights Reserved. + This file may be used under the terms of the Be Sample Code License. +*/ + +/* + * This file is a part of SiS 7018 BeOS driver project. + * Copyright permissions see above. + * + * Portion copyright (c) 2002-2003 by Siarzuk Zharski + */ + +#ifndef _MIDI_DRIVER_H +#define _MIDI_DRIVER_H + +#include +#include + +/* ----- + ioctl codes +----- */ + +/* the old opcodes are deprecated, and may or may not work + in newer drivers */ +enum { + B_MIDI_GET_READ_TIMEOUT = B_MIDI_DRIVER_BASE, + B_MIDI_SET_READ_TIMEOUT, + B_MIDI_TIMED_READ, + B_MIDI_TIMED_WRITE, + B_MIDI_WRITE_SYNC, + B_MIDI_WRITE_CLEAR, + B_MIDI_GET_READ_TIMEOUT_OLD = B_DEVICE_OP_CODES_END + 1, + B_MIDI_SET_READ_TIMEOUT_OLD +}; + +/* the default timeout when you open a midi driver */ +#define B_MIDI_DEFAULT_TIMEOUT 1000000000000000LL + +/* Usage: + To read, set "data" to a pointer to your buffer, and "size" to the + maximum size of this buffer. On return, "when" will contain the time + at which the data was received (first byte) and "size" will contain + the actual amount of data read. + Call ioctl(fd, B_MIDI_TIMED_READ, &midi_timed_data, sizeof(midi_timed_data)); + To write, set "when" to when you want the first byte to go out the + wire, set "data" to point to your data, and set "size" to the size + of your data. + Call ioctl(fd, B_MIDI_TIMED_WRITE, &midi_timed_data, sizeof(midi_timed_data)); +*/ +typedef struct { + bigtime_t when; + size_t size; + unsigned char * data; +} midi_timed_data; + + +/* The MIDI parser returns the number of bytes that a message contains, given the */ +/* initial byte. For some messages, this is not known until the second byte is seen. */ +/* For such messages, a state > 0 is returned as well as some count > 0. When state */ +/* is > 0, you should call (*parse) for the next byte as well, which might modify */ +/* the returned message size. Message size will always be returned with the current */ +/* byte being counted as byte 1. A return of 0 means that the byte initiates a new */ +/* message. SysX is handled by returning max_size until the end or next initial message */ +/* is seen. So your loop looks something like: */ +/* + uint32 state = 0; // Only set this to 0 the first time you call the parser. + // preserve the 'state' between invocations of your read() hook. + int todo = 0; + unsigned char * end = in_buf+buf_size + unsigned char * out_buf = in_buf; + while (true) { + uchar byte = read_midi(); + if (!todo || state) { + todo = (*parser->parse)(&state, byte, end-out_buf); + } + if (todo < 1) { + unput_midi(byte); + } else { + *(out_buf++) = byte; + todo--; + } + if (todo < 1 || out_buf >= end) { + received_midi_message(in_buf, out_buf-in_buf); + todo = 0; + } + } + */ + +#define B_MIDI_PARSER_MODULE_NAME "media/midiparser/v1" + +typedef struct _midi_parser_module_info { + module_info minfo; + int (*parse)(uint32 * state, uchar byte, size_t max_size); + int _reserved_; +} midi_parser_module_info; + +#define B_MPU_401_MODULE_NAME "generic/mpu401/v1" + +enum { + B_MPU_401_ENABLE_CARD_INT = 1, + B_MPU_401_DISABLE_CARD_INT +}; +typedef struct _generic_mpu401_module { + module_info minfo; + status_t (*create_device)(int port, void ** out_storage, uint32 workarounds, void (*interrupt_op)(int32 op, void * card), void * card); + status_t (*delete_device)(void * storage); + status_t (*open_hook)(void * storage, uint32 flags, void ** out_cookie); + status_t (*close_hook)(void * cookie); + status_t (*free_hook)(void * cookie); + status_t (*control_hook)(void * cookie, uint32 op, void * data, size_t len); + status_t (*read_hook)(void * cookie, off_t pos, void * data, size_t * len); + status_t (*write_hook)(void * cookie, off_t pos, const void * data, size_t * len); + bool (*interrupt_hook)(void * cookie); + int _reserved_; +} generic_mpu401_module; + +#endif diff --git a/src/add-ons/kernel/drivers/audio/sis7018/pcm.c b/src/add-ons/kernel/drivers/audio/sis7018/pcm.c new file mode 100644 index 0000000000..b9378b87e2 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/pcm.c @@ -0,0 +1,479 @@ +/* + * This file is a part of SiS 7018 BeOS driver project. + * Copyright (c) 2002-2003 by Siarzuk Zharski + * + * This file may be used under the terms of the BSD License + * See the file "License" for details. + */ +#include "pcm.h" +#include "sis7018.h" +#include "sis7018hw.h" // ioctl definitions +#include "sound.h" +#include "ac97.h" +#include "R3MediaDefs.h" // sound_buffer definition +#include "t4dwave.h" + +#if DEBUG +int32 int_cnt; +int32 put_cnt; +bigtime_t the_time; +#endif + +/* pcm_open - handle open() calls */ +static status_t pcm_open (const char *name, uint32 flags, void** cookie) +{ + int ix; + pcm_dev *port = NULL; + + TRACE("pcm_open(%s, %lx)\n", name, flags); + + *cookie = NULL; + for (ix=0; ixinit_sem); + + if (atomic_add(&port->open_count, 1) == 0) + { + TRACE("pcm_open: first open\n"); + port->card = &cards[ix]; + + port->open_mode = (flags & O_RWMASK); + if (port->open_mode != O_RDONLY) + ;// TODO start playback "dma" + + if (port->open_mode != O_WRONLY) + ;//TODO start record "dma" + + port->old_cap_sem = -1; + port->old_play_sem = -1; + + hw_pchannel_init(port); + hw_increment_interrupt_handler(port->card); + } + else + { + if ((flags & O_RWMASK) == O_RDWR) + { + if (port->open_mode == O_RDONLY) + ; //TODO start playback "dma" + else + if (port->open_mode == O_WRONLY) + ; //TODO start record "dma" + port->open_mode = O_RDWR; + } + TRACE("pcm_open: next opens\n"); + } + + hw_start(port); + + release_sem(port->init_sem); + + return B_OK; +} + +/* pcm_read - handle read() calls */ +static status_t pcm_read (void* cookie, off_t position, void *buf, size_t* num_bytes) +{ + pcm_dev * port = (pcm_dev *)cookie; + + if (port->open_mode == O_WRONLY) + return EPERM; + +// TRACE("pcm_read(%p, %d, %p, %d)\n", cookie, position, buf, *num_bytes); + *num_bytes = 0; /* tell caller nothing was read */ + return B_IO_ERROR; +} + +extern int intrs; + +static status_t pcm_write(void * cookie, off_t pos, const void * data, size_t * nwritten) +{ + pcm_dev * port = (pcm_dev *)cookie; + sis7018_ch *ch = &((pcm_dev *)cookie)->play_channel; + status_t err; + cpu_status cp; + int written = 0; + int to_write = *nwritten; /* in play bytes, not input bytes! */ + int block; + int bytes_xferred; + + if (port->open_mode == O_RDONLY) + return EPERM; + + *nwritten = 0; + + if ((err = acquire_sem_etc(ch->wr_entry, 1, B_CAN_INTERRUPT, 0)) < B_OK) + { + TRACE("wr_entry acquisition failed\n"); + return err; + } + atomic_add(&ch->write_waiting, 1); + + while (to_write > 0) + { + /* wait to write */ + if ((err = acquire_sem_etc(ch->write_sem, 1, B_CAN_INTERRUPT, 0)) < B_OK) + { + TRACE("write_sem acquisition failed\n"); + release_sem(ch->wr_entry); + return err; + } + +#if DEBUG + put_cnt++; + { + bigtime_t delta = system_time() - the_time; + if (delta < 1) { + TRACE("delta %Ld (low!) #%ld\n", delta, put_cnt); + } + else if (delta > 2000) { + TRACE("delta %Ld (high!) #%ld\n", delta, put_cnt); + } + } + if (put_cnt != int_cnt) { + static int last; + if (last != int_cnt-put_cnt) + TRACE("%ld mismatch\n", int_cnt-put_cnt); + last = int_cnt-put_cnt; + } +#endif /* DEBUG */ + + // KTRACE(); + cp = disable_interrupts(); + acquire_spinlock(&ch->wr_lock); + + block = ch->wr_size-ch->was_written; + if (block > to_write) + { + /* must let next guy in */ + if (atomic_add(&ch->write_waiting, -1) > 0) + release_sem_etc(ch->write_sem, 1, B_DO_NOT_RESCHEDULE); + else + atomic_add(&ch->write_waiting, 1); /* undo damage */ + + block = to_write; + } + else + if (block < to_write) + atomic_add(&ch->write_waiting, 1); /* we will loop back */ + + /* switch (port->config.format) + {*/ + // case 0x24: /* floats */ + /* copy_float_to_short((short *)(port->wr_cur+port->was_written), (const float *)data, + block, !B_HOST_IS_LENDIAN == !port->config.big_endian); + bytes_xferred = block * 2; + break; */ + // case 0x02: /* shorts */ + // if (!B_HOST_IS_LENDIAN == !port->config.big_endian) { + /* we need to swap */ + /* swap_copy((short *)(port->wr_cur+port->was_written), (const short *)data, block); + bytes_xferred = block; + break; + } + */ /* else fall through to default case */ + // case 0x11: /* bytes */ + // default: +// my_copy((short *)(ch->wr_cur+ch->was_written), (const short *)data, block); + memcpy((void *)(ch->wr_cur+ch->was_written), data, block); + bytes_xferred = block; + /* break; + }*/ + ch->was_written += block; + ch->wr_silence = 0; + + release_spinlock(&ch->wr_lock); + restore_interrupts(cp); + +#if DEBUG + if(ch->wr_cur == ch->wr_cur_prv) + { + int tt = (system_time() - ch->time_prv)/1000; + TRACE("%d ms block - %x, to_write: %x ,size: %x,was_written: %x\n", tt, block, to_write, ch->wr_size, ch->was_written); + ch->time_prv = system_time(); + } + + ch->wr_cur_prv = ch->wr_cur; +#endif + + data = ((char *)data)+bytes_xferred; + written += bytes_xferred; + to_write -= block; + } + + *nwritten = written; + release_sem(ch->wr_entry); + + return B_OK; +} + +bool playback_interrupt(sis7018_ch * ch, bool bHalf) +{ + bool ret = false; +// pcm_dev * port = &dev->pcm; +// sis7018_ch *ch = &dev->pcm.play_channel; + volatile uchar * ptr; +// uint32 addr; + uint32 offs; + bigtime_t st = system_time(); +// int32 ww; +// sis7018_ch ch2 = *ch; + +#if 0 +ddprintf(("sonic_vibes: dma_a 0x%x+0x%x\n", PCI_IO_RD_32((int)port->dma_c), PCI_IO_RD_32((int)port->dma_c+4))); +#endif +// KTRACE(); /* */ + acquire_spinlock(&ch->wr_lock); + + if (ch->write_sem < 0) + { + dprintf("spurious play interrupt!\n"); + release_spinlock(&ch->wr_lock); + return false; + } + /* copy possible silence into playback buffer */ + + if (ch->was_written > 0 && ch->was_written < ch->wr_size) + // { +/* if (port->config.format == 0x11) + { + memset((void *)(port->wr_cur+port->was_written), 0x80, port->wr_size-port->was_written); + } + else {*/ + memset((void *)(ch->wr_cur+ch->was_written), 0, ch->wr_size-ch->was_written); + // } +// } + + /* because the system may be lacking and not hand us the */ + /* interrupt in time, we check which half is currently being */ + /* played, and set the pointer to the other half */ + +// addr = PCI_IO_RD_32((uint32)port->dma_a); +// if ((offs = addr-(uint32)port->card->low_phys) < port->wr_size) +// hw_rdch(&ch2); + + // select channel ... + offs = hw_read(ch->card, TR_REG_CIR, 4); + offs &= ~TR_CIR_MASK; + offs |= ch->index & 0x3f; + hw_write(ch->card, TR_REG_CIR, offs, 4); + + // read current cso + switch(ch->card->type->ids.chip_id) + { + case SPA_PCI_ID: + case ALI_PCI_ID: + case TDX_PCI_ID: + case xDX_PCI_ID: + offs=((hw_read(ch->card, TR_REG_CHNBASE, 4) & 0xffff0000) >> 16) * 4; + break; + case TNX_PCI_ID: + offs=(hw_read(ch->card, TR_REG_CHNBASE, 4) & 0x00ffffff) * 4; + break; + } + + if (offs < ch->wr_size) + ptr = ch->wr_2; + else + ptr = ch->wr_1; + + ch->wr_total += ch->mem_size/2; + /* compensate for interrupt latency */ + /* assuming 4 byte frames */ + ch->wr_time = st-(offs&(ch->mem_size/2-1))*250000LL/(int64)48000; + +/* if ((ww = atomic_add(&ch->wr_time_wait, -1)) > 0) + { + release_sem_etc(ch->wr_time_sem, 1, B_DO_NOT_RESCHEDULE); + ret = true; + } + else + { +*/// atomic_add(&ch->wr_time_wait, 1); /* re-set to 0 */ +// } + + if (ch->wr_cur == ptr) + { + ch->wr_skipped++; + dprintf("write skipped %ld\n", ch->wr_skipped); + } + + ch->wr_cur = ptr; + ch->was_written = 0; + + /* check for client there to write into buffer */ + + if (atomic_add(&ch->write_waiting, -1) > 0) + { +#if DEBUG + int_cnt++; + the_time = st; +#endif + release_sem_etc(ch->write_sem, 1, B_DO_NOT_RESCHEDULE); + ret = true; + } + else + { + atomic_add(&ch->write_waiting, 1); + /* if none there, fill with silence */ + if (ch->wr_silence < ch->mem_size) + { + /* if (port->config.format == 0x11) { + memset((void *)ptr, 0x80, port->wr_size); + } + else {*/ + memset((void *)ptr, 0, ch->wr_size); + //} + ch->wr_silence += ch->wr_size; + } + } + /* copying will be done in user thread */ + + release_spinlock(&ch->wr_lock); + return ret; +} + +/* pcm_control - handle ioctl calls */ +static status_t pcm_control (void* cookie, uint32 op, void* arg, size_t len) +{ + status_t err = B_BAD_VALUE; + pcm_dev * port = (pcm_dev *)cookie; +// TRACE("pcm_control(%p, %lx)\n", cookie, op); + switch (op) + { + case SOUND_GET_PARAMS: + // TRACE("SOUND_GET_PARAMS\n"); + err = ac97get_params(port->card, (sound_setup *)arg); + break; + case SOUND_SET_PARAMS: + // TRACE("SOUND_SET_PARAMS\n"); + err = ac97set_params(port->card, (sound_setup *)arg); + break; + case SOUND_SET_PLAYBACK_COMPLETION_SEM: + // TRACE("SOUND_SET_PLAYBACK_COMPLETION_SEM\n"); + port->old_play_sem = *(sem_id *)arg; + err = B_OK; + break; + case SOUND_SET_CAPTURE_COMPLETION_SEM: + // TRACE("SOUND_SET_CAPTURE_COMPLETION_SEM\n"); + port->old_cap_sem = *(sem_id *)arg; + err = B_OK; + break; + case SOUND_UNSAFE_WRITE: + { + sis7018_ch *ch = &((sis7018_dev *)cookie)->pcm.play_channel; + audio_buffer_header * buf = (audio_buffer_header *)arg; + size_t n = buf->reserved_1-sizeof(*buf); + //TRACE("%ld %ld %ld %ld\n", buf->reserved_1, buf->reserved_2, buf->sample_clock, buf->time ); + //TRACE("SOUND_UNSAFE_WRITE %d\n", n); + err = pcm_write(cookie, 0, buf+1, &n); + buf->time = ch->wr_time; + buf->sample_clock = ch->wr_total/4 * 1000 / 48; + err |= release_sem(port->old_play_sem); + // err = B_OK; + } + break; + case SOUND_UNSAFE_READ: + TRACE("SOUND_UNSAFE_READ\n"); + // ASSERT(0); + err = release_sem(port->old_cap_sem); + err = B_IO_ERROR; + break; + case SOUND_LOCK_FOR_DMA: + TRACE("SOUND_LOCK_FOR_DMA\n"); + err = B_OK; + break; + case SOUND_SET_PLAYBACK_PREFERRED_BUF_SIZE: + { + int32 new_size = (int32)arg; + TRACE("SOUND_SET_PLAYBACK_PREFERRED_BUF_SIZE: 0x%x\n", new_size); + hw_pchannel_setblocksize(port, new_size); + err = B_OK; + } + break; + case SOUND_SET_CAPTURE_PREFERRED_BUF_SIZE: + // TRACE("SOUND_SET_CAPTURE_PREFERRED_BUF_SIZE\n"); + // config.rec_buf_size = (int32)data; + // configure = true; + err = B_OK; + break; + case SOUND_GET_PLAYBACK_PREFERRED_BUF_SIZE: + TRACE("SOUND_GET_PLAYBACK_PREFERRED_BUF_SIZE\n"); + *(int32*)arg = port->play_channel.mem_size/2; + err = B_OK; + break; + case SOUND_GET_CAPTURE_PREFERRED_BUF_SIZE: + // TRACE("SOUND_GET_CAPTURE_PREFERRED_BUF_SIZE\n"); + // *(int32*)data = config.rec_buf_size; + err = B_OK; + break; + default: + TRACE("pcm_control : unknown code %ld\n", op); + err = B_BAD_VALUE; + break; + } + return err; +} + +/* pcm_close - handle close() calls */ +static status_t pcm_close (void* cookie) +{ + pcm_dev * port = (pcm_dev *)cookie; + TRACE("pcm_close(%p)\n", cookie); + + acquire_sem(port->init_sem); + + if (atomic_add(&port->open_count, -1) == 1) + { + TRACE("pcm_close: last close\n"); + hw_stop(port); + hw_pchannel_free(port); + } + else + { + TRACE("pcm_close: previous closes\n"); + } + + release_sem(port->init_sem); + return B_OK; +} + + +/* pcm_free - called after the last device is closed, and after all i/o is complete. */ +static status_t pcm_free (void* cookie) +{ + pcm_dev *port = (pcm_dev *)cookie; + TRACE("pcm_free(%p)\n", cookie); + + acquire_sem(port->init_sem); + + if (port->open_count == 0) + { + hw_decrement_interrupt_handler(port->card); + } + + release_sem(port->init_sem); + return B_OK; +} + +/* function pointers for the device hooks entry points */ +device_hooks pcm_hooks = +{ + pcm_open, /* -> open entry point */ + pcm_close, /* -> close entry point */ + pcm_free, /* -> free cookie */ + pcm_control, /* -> control entry point */ + pcm_read, /* -> read entry point */ + pcm_write /* -> write entry point */ +}; diff --git a/src/add-ons/kernel/drivers/audio/sis7018/pcm.h b/src/add-ons/kernel/drivers/audio/sis7018/pcm.h new file mode 100644 index 0000000000..6e034e71e8 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/pcm.h @@ -0,0 +1,43 @@ +/* + * This file is a part of SiS 7018 BeOS driver project. + * Copyright (c) 2002-2003 by Siarzuk Zharski + * + * This file may be used under the terms of the BSD License + * See the file "License" for details. + */ +#ifndef _PCM_H_ + #define _PCM_H_ + +#ifndef _DRIVERS_H + #include +#endif //_DRIVERS_H + +#ifndef _SIS7018_H_ + #include "sis7018.h" +#endif //_SIS7018_H_ + +extern device_hooks pcm_hooks; + +bool playback_interrupt(sis7018_ch *ch, bool bHalf); + +/* secret handshake ioctl()s */ +/*#define SV_SECRET_HANDSHAKE 10100 +typedef struct { + bigtime_t wr_time; + bigtime_t rd_time; + uint32 wr_skipped; + uint32 rd_skipped; + uint64 wr_total; + uint64 rd_total; + uint32 _reserved_[6]; +} sv_handshake; +#define SV_RD_TIME_WAIT 10101 +#define SV_WR_TIME_WAIT 10102 +typedef struct { + bigtime_t time; + bigtime_t bytes; + uint32 skipped; + uint32 _reserved_[3]; +} sv_timing; +*/ +#endif //_PCM_H_ diff --git a/src/add-ons/kernel/drivers/audio/sis7018/sis7018.c b/src/add-ons/kernel/drivers/audio/sis7018/sis7018.c new file mode 100644 index 0000000000..d0b80d32b2 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/sis7018.c @@ -0,0 +1,441 @@ +/* + * This file is a part of SiS 7018 BeOS driver project. + * Copyright (c) 2002-2003 by Siarzuk Zharski + * + * This file may be used under the terms of the BSD License + * See the file "License" for details. + */ +#include //sprintf +#include +#include //posix file i/o - create, write, close +#include +#include "sis7018.h" +#include "sis7018hw.h" +#include "ac97.h" + +#if DO_PCM +#include "pcm.h" +#endif + +#if DO_MIDI +#include "midi_driver.h" +#include "midi.h" +#endif + +#define NUM_CARDS 3 + +int32 num_cards; +sis7018_dev cards[NUM_CARDS]; +int num_names; +char * names[NUM_CARDS*7+1]; + +#if DEBUG +bool b_log = true; +#else +bool b_log = false; +#endif +bool b_log_file = false; +bool b_log_append = false; +bool b_trace_ac97 = false; +bool use_io_regs = false; + +static const char *private_log_path="/boot/home/sis7018.log"; +static sem_id loglock; + +static void reload_sis7018_setting() +{ + void *settingshandle; + settingshandle = load_driver_settings(CHIPNAME); +#if !DEBUG + b_log = get_driver_boolean_parameter(settingshandle, "debug_output", b_log, true); +#endif + b_log_file = get_driver_boolean_parameter(settingshandle, "debug_output_in_file", b_log_file, true); + b_log_append = ! get_driver_boolean_parameter(settingshandle, "debug_output_file_rewrite", !b_log_append, true); + b_trace_ac97 = get_driver_boolean_parameter(settingshandle, "debug_trace_ac97", b_trace_ac97, true); + use_io_regs = get_driver_boolean_parameter(settingshandle, "use_io_registers", use_io_regs, true); + unload_driver_settings(settingshandle); +} + +void create_log() +{ + int flags = O_WRONLY | O_CREAT | ((!b_log_append) ? O_TRUNC : 0); + if(!b_log_file) + return; + close(open(private_log_path, flags, 0666)); + loglock = create_sem(1,"sis7018 logfile"); +} + +void sis7018_trace(bool b_force, char *fmt, ...) +{ + if(!(b_force || b_log)) + return; + { + va_list arg_list; + static char *prefix = "\33[32m"CHIPNAME":\33[0m"; + static char buf[1024]; + char *buf_ptr = buf; + if(!b_log_file) + { + strcpy(buf, prefix); + buf_ptr += strlen(prefix); + } + + va_start(arg_list, fmt); + vsprintf(buf_ptr, fmt, arg_list); + va_end(arg_list); + + if(b_log_file) + { + int fd; + if(!b_trace_ac97) + acquire_sem(loglock); + fd = open(private_log_path, O_WRONLY | O_APPEND); + write(fd, buf, strlen(buf)); + close(fd); + if(!b_trace_ac97) + release_sem(loglock); + } + else + dprintf(buf); + } +} + +card_type card_types[]= +{ + {{TDX_PCI_ID}, "Trident DX"}, + {{xDX_PCI_ID}, "Trident XX"}, + {{TNX_PCI_ID}, "Trident NX"}, + {{ALI_PCI_ID}, "ALi 5451"}, + {{SPA_PCI_ID}, "SiS 7018"}, +}; + +#ifdef DEBUG +int _assert_(char *a, int b, char *c) +{ + char sz[1024]; + sprintf(sz, CHIPNAME":tripped assertion in %s/%d (%s)", a, b, c); + TRACE("tripped assertion in %s/%d (%s)\n", a, b, c); + kernel_debugger(sz); + return 0; +} +#endif + +static void make_device_names(sis7018_dev * card) +{ + char * name = card->name; + sprintf(name, "%s/%ld", card->type->chip_name, card-cards+1); + +#if DO_MIDI + sprintf(card->midi.name, "midi/%s", name); + names[num_names++] = card->midi.name; +#endif //DO_MIDI + +#if DO_PCM +// sprintf(card->pcm.name, "audio/raw/%s", name); +// names[num_names++] = card->pcm.name; + sprintf(card->pcm.oldname, "audio/old/%s", name); + names[num_names++] = card->pcm.oldname; +#endif //DO_PCM + + names[num_names] = NULL; +} + +static status_t setup_hardware( sis7018_dev * card) +{ + status_t err = B_OK; + int32 command_reg; + + TRACE("setup_hardware(%p)\n", card); + + if ((card->pcm.init_sem = create_sem(1, "sis7018 pcm init")) < B_OK) + goto bail; + +#if DO_MIDI //TODO: below? + if ((*mpu401->create_device)(card->info.u.h0.base_registers[3], &card->midi.driver, + 0, midi_interrupt_op, &card->midi) < B_OK) + goto bail3; + TRACE("midi %p\n", card->midi.driver); + card->midi.card = card; +#endif //DO_MIDI + + make_device_names(card); + + command_reg = (*pci->read_pci_config)(card->info.bus, card->info.device, card->info.function, + PCI_command, 2); +// TRACE("PCI command config was: %lx\n", command_reg); + command_reg |= PCI_command_io | PCI_command_memory | PCI_command_master; + (*pci->write_pci_config)(card->info.bus, card->info.device, card->info.function, + PCI_command, 2, command_reg); +// TRACE("PCI command config set to: %lx\n", command_reg); + + if(use_io_regs) + { + card->io_base = card->info.u.h0.base_registers[0]; + TRACE("%s base at %x\n", card->name, card->io_base); + } + else // USE_IO_RANGE + { + TRACE("%s memory %lx length %lx\n", card->name, card->info.u.h0.base_registers[1], card->info.u.h0.base_register_sizes[1]); + card->regs_area = map_physical_memory("Regs sis7018", + (void *)card->info.u.h0.base_registers[1], + card->info.u.h0.base_register_sizes[1], + B_ANY_KERNEL_ADDRESS, + B_READ_AREA + B_WRITE_AREA, + &card->regs_mem_base); + + TRACE("%s registers memory base at 0x%p\n", card->name, card->regs_mem_base); + }// USE_IO_RANGE + + err = hw_initialize(card); + return err; + +#if DO_MIDI +bail3: +#endif //DO_MIDI + delete_sem(card->pcm.init_sem); +bail: + return err < B_OK ? err : B_ERROR; +} + +#if DEBUG +static int debug_sis7018(int argc, char * argv[]) +{ + int err = (argc < 2 || argc > 3); + int card_id = 0; + + if(!err) + { + if(argc == 3) + card_id = parse_expression(argv[2]); + + if(card_id < 0 || card_id > num_cards-1) + { + kprintf("ERROR: Wrong card_id: %d\n", card_id); + kprintf("\n"); + err = 1; + } + else + { + switch((char)*(argv[1])) + { + case 'd': hw_dump_device(card_id); break; + case 'i': hw_dump_pci_info(card_id); break; + case 'p': hw_dump_pcm_device(card_id); break; + case 'm': hw_dump_midi_device(card_id); break; + case 'c': hw_dump_play_channel(card_id); break; + case 'a': ac97dump(card_id); break; + default: + kprintf("ERROR: Wrong command: %s\n",argv[1]); + kprintf("\n"); + err=1; + break; + } + } + } + + if (err) + { + kprintf("Syntax: "CHIPNAME" < command > [card id]\n"); + kprintf(" - where commands is:\n"); + kprintf(" d - dump device info\n"); + kprintf(" i - dump pci_info\n"); + kprintf(" p - dump pcm info\n"); + kprintf(" m - dump midi info\n"); + kprintf(" c - dump playback channel info\n"); + kprintf(" a - dump AC'97 registers info\n"); + kprintf(" - and card id is zero-based id of card to be investigated\n"); + kprintf(" default card id is 0\n"); + kprintf(" current cards count is %ld\n", num_cards); + kprintf("\n"); + } + + return 0; +} +#endif /* DEBUG */ + +/************** SYSTEM CALLBACKS ************************************/ + +int32 api_version = B_CUR_DRIVER_API_VERSION; + +/* init_hardware - called once the first time the driver is loaded */ +status_t init_hardware (void) +{ + int ix = 0, jx = 0; + pci_info info; + status_t err = ENODEV; + + TRACE("init_hardware()\n"); + + if (get_module(B_PCI_MODULE_NAME, (module_info **)&pci)) + return ENOSYS; + + while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) + { + for(jx = 0; jx < sizeof(card_types)/sizeof(card_types[0]); jx++) + if (info.vendor_id == card_types[jx].ids.ids.vendor_id + && info.device_id == card_types[jx].ids.ids.card_id) + { + err = B_OK; + } + ix++; + } + + put_module(B_PCI_MODULE_NAME); + return err; +} + +/* init_driver - optional function - called every time the drive is loaded. */ +status_t init_driver (void) +{ + int ix=0, jx=0; + pci_info info; + num_cards = 0; + + reload_sis7018_setting(); + create_log(); + + TRACE("\n>>> init_driver()\n"); + load_driver_symbols(CHIPNAME); + + if (get_module(B_PCI_MODULE_NAME, (module_info **) &pci)) + return ENOSYS; + +#if DO_MIDI + TRACE("MPU\n"); + if (get_module(B_MPU_401_MODULE_NAME, (module_info **) &mpu401)) + { + put_module(B_PCI_MODULE_NAME); + return ENOSYS; + } + TRACE("MPU: %p\n", mpu401); +#endif //DO_MIDI + + while ((*pci->get_nth_pci_info)(ix, &info) == B_OK) + { + for(jx = 0; jx < sizeof(card_types)/sizeof(card_types[0]); jx++) + if (info.vendor_id == card_types[jx].ids.ids.vendor_id + && info.device_id == card_types[jx].ids.ids.card_id) + { + if (num_cards == NUM_CARDS) + { + TRACE_ALWAYS("Too many cards installed! Only %d will be used.\n", NUM_CARDS); + break; + } + + memset(&cards[num_cards], 0, sizeof(sis7018_dev)); + cards[num_cards].info = info; + cards[num_cards].type = &card_types[jx]; + if (setup_hardware(&cards[num_cards])) + { + TRACE_ALWAYS("Setup of %s driver for %ld-th card failed\n", CHIPNAME, num_cards+1); + } + else + num_cards++; + + TRACE_ALWAYS("%s found.\n", + card_types[jx].chip_name, + card_types[jx].ids.ids.vendor_id, + card_types[jx].ids.ids.card_id); + } + ix++; + } + + if (!num_cards) + { +#if DO_MIDI + put_module(B_MPU_401_MODULE_NAME); +#endif //DO_MIDI + put_module(B_PCI_MODULE_NAME); + TRACE("No suitable cards found\n"); + return ENODEV; + } + +#if DEBUG + add_debugger_command(CHIPNAME, debug_sis7018, CHIPNAME" driver info."); +#endif + return B_OK; +} + +static void teardown_card(sis7018_dev *card) +{ + /* remove created devices */ +#if DO_MIDI + (*mpu401->delete_device)(card->midi.driver); +#endif //DO_MIDI + + if(!use_io_regs) + delete_area(card->regs_area); + + delete_sem(card->pcm.init_sem); +} + +/* uninit_driver - optional function - called every time the driver is unloaded */ +void uninit_driver (void) +{ + int ix, cnt = num_cards; + num_cards = 0; + + TRACE("<<< uninit_driver()\n\n"); + +#if DEBUG + remove_debugger_command(CHIPNAME, debug_sis7018); +#endif + + for (ix=0; ix + * + * This file may be used under the terms of the BSD License + * See the file "License" for details. + */ +#ifndef _SIS7018_H_ + #define _SIS7018_H_ + +#include +#include +#include +#include + +#define CHIPNAME "sis7018" + +void sis7018_trace(bool b_force, char *fmt, ...); + +//#define TRACE_ALWAYS(x...) dprintf("\33[32m"CHIPNAME":\33[0m"x); +#define TRACE_ALWAYS(x...) sis7018_trace(true, x); +#define TRACE(x...) sis7018_trace(false, x); + +extern bool b_trace_ac97; + +#if DEBUG +//#define TRACE(x...) TRACE_ALWAYS(x) +int _assert_(char *,int,char *); +#define ASSERT(c) (!(c) ? _assert_(__FILE__, __LINE__, #c) : 0) +#else +//#define TRACE(x...) +#define ASSERT(c) +#endif + +#define DEVNAME 32 + +#define TDX_PCI_ID 0x20001023 // Trident 4D Wave/DX +#define xDX_PCI_ID 0x20000003 // Hypotese? +#define TNX_PCI_ID 0x20011023 // Trident 4D Wave/NX +#define ALI_PCI_ID 0x545110b9 // Acer Labs 5451 Audio +#define SPA_PCI_ID 0x70181039 // SiS PCI Audio + +typedef struct _card_type +{ + union _ids + { + uint32 chip_id; + struct { + uint16 vendor_id; + uint16 card_id; + } ids; + } ids; + char chip_name[DEVNAME]; +} card_type; + +#define DO_PCM 1 +#define DO_MIDI 0 + +//#define USE_IO_REGS 0 +extern bool use_io_regs; + +typedef struct _midi_dev { + struct _sis7018_dev *card; + void * driver; + void * cookie; + int32 count; + char name[64]; +} midi_dev; + +/* channel registers */ +typedef struct _sis7018_ch { + int32 cso, alpha, fms, fmc, ec; + int32 lba; + int32 eso, delta; + int32 rvol, cvol; + int32 gvsel, pan, vol, ctrl; + int32 active/*:1, was_active:1*/; + int index/*, bufhalf*/; + struct _sis7018_dev *card; + size_t mem_size; /* size of low memory */ + vuchar * mem_ptr; + vuchar * mem_phys; /* physical address */ + area_id areaid; /* area pointing to low memory */ + + vuchar * wr_1; + vuchar * wr_2; + vuchar * wr_cur; +#if DEBUG + vuchar * wr_cur_prv; + bigtime_t time_prv; + bool prevInt; +#endif + size_t wr_size; + + int32 wr_lock; + int wr_silence; + int32 write_waiting; + sem_id write_sem; + size_t was_written; + uint32 wr_skipped; + sem_id wr_entry; + bigtime_t wr_time; + uint64 wr_total; +// sem_id wr_time_sem; +// int32 wr_time_wait; +} sis7018_ch; + +typedef struct { + struct _sis7018_dev * card; + char name[DEVNAME]; + int32 open_count; + int32 open_mode; + sem_id init_sem; + + sem_id old_cap_sem; + sem_id old_play_sem; + + char oldname[DEVNAME]; + struct _sis7018_ch play_channel; +} pcm_dev; + +typedef struct _ac97_codec +{ + bool wide_main_gain; +} ac97_codec; + +typedef struct _sis7018_dev +{ + char name[DEVNAME]; /* used for resources */ + int32 hardware; /* spinlock */ +//#if(USE_IO_REGS) + int io_base; /* offset to port */ +//#else + void *regs_mem_base; +//#endif + int32 inth_count; +/* int dma_base; + size_t low_size;*/ /* size of low memory */ +/* vuchar * low_mem; + vuchar * low_phys;*/ /* physical address */ +// area_id map_low; /* area pointing to low memory */ +//#if(!USE_IO_REGS) + area_id regs_area; +//#endif + pci_info info; + midi_dev midi; +/* joy_dev joy;*/ + pcm_dev pcm; +/* mux_dev mux; + mixer_dev mixer;*/ + card_type *type; + ac97_codec ac97; +} sis7018_dev; + +extern int32 num_cards; +extern sis7018_dev cards[]; + +/*uint32 io_rd(sis7018_dev *dev, int offset, int size); +void io_wr(sis7018_dev *dev, int offset, uint32 value, int size); +int rd_cd(sis7018_dev *dev, int regno); +int wr_cd(sis7018_dev *dev, int regno, uint32 data); + +void increment_interrupt_handler(sis7018_dev * card); +void decrement_interrupt_handler(sis7018_dev * card); +*/ +#endif //_SIS7018_H_ diff --git a/src/add-ons/kernel/drivers/audio/sis7018/sis7018.rdef b/src/add-ons/kernel/drivers/audio/sis7018/sis7018.rdef new file mode 100644 index 0000000000..dda3560e09 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/sis7018.rdef @@ -0,0 +1,54 @@ + +resource(101, "BEOS:L:STD_ICON") #'ICON' array { + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFF3F7E3DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFF3F3F7E3E28FFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF3F3F7E3E5F3E28FFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFF3F3F7E3E5F3E5F3E27FFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFF3F3F7E3E5F3E5F3E937E3DFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFF3F3F7E3E5F3E5F3E937E3E5FDFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFF3F3F7E3E5F3E5F3E937E3E5F3E9301FFFFFFFFFFFFFFFFFF" + $"FFFFFF3F3F3F3F3F3F7E3E5F3E5F3F3F3F3E937E3E5F403F3F3F3F3FFFFFFFFF" + $"FFFF3FFAFAFAFAFAFA3F7E3E5F1FFAFAFA3F3E5F3E3FFCFAFAFAFAFA1FFFFFFF" + $"FF3FFAFAFAFAFAFAFAFA3F7E3E3FFBFAFA3F257E3FFAFAFAFAFAFAFAFA3FFFFF" + $"3FFAFAFA3F3F3F3FFAFAFA3F7E1FFAFAFA1FDD3FFAFAFA3F3F3F3FFAFAFA3FFF" + $"3FFAFA3F252525253F3F3F3F24253F3F3F25253FFAFA3F252525253F3F3F3F25" + $"3FFAFA3F257E3E5FDD242525257E252525253E3FFCFA1F257F3E5EDD25242525" + $"3FFAFAFA3F3F7E3E5F3E5F3E93403F3F3F3F7E1FFAFAFA3F3F3E937E3E28FFFF" + $"253FFAFAFAFA3F3F7E3E5F3E5F3FFAFAFA3FDC263FFAFAFAFA3F3F7E3E5F3DFF" + $"FF253F3FFAFAFAFA3F3F7E3E5F3FFAFAFA3FDD7E253F3FFAFAFAFA3F3F3E5F3D" + $"FFFF25253F3FFAFAFAFA3F7E3E3FFBFAFA3F247F3E21253F3FFAFAFAFA3F01FF" + $"FFFFFF3F25253F3FFAFAFA3F7E1FFAFAFA3FDD7E3E5F3E21253F3FFAFAFA3FFF" + $"FFFFFFFF3F7E26253FFAFA3F253FFAFAFA3F243E5F3E5F3E93242540FAFA3F25" + $"3F3F3F3FFF3F7E3E3FFBFA3F253FFAFAFA3F241F3F3F3F3E5F3E5F3FFAFA3FDC" + $"3FFAFAFA3F3F3F3FFAFAFA3F253FFAFAFA3F253FFAFAFA3F3F3F3FFAFAFA3F25" + $"253FFAFAFAFAFAFAFAFA3F25253FFAFAFA3F25241FFAFAFAFAFAFAFAFA3F2525" + $"FF253FFAFAFAFAFA3F3F25257E1FFAFAFA3FDC7F253FFAFAFAFAFA3F3F2524FF" + $"FFFF253F3F3F3F3F2525257E3E3F3F3F3F3F227E3E221F3F3F3F3F252525FFFF" + $"FFFFFF252525252425FF3F3F7F2425252525243E5F3E222524252525FFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFF3F3F7E3E5F3E5F3E937E3DE0FFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF3F3F7E3E5F3E5F3E27FFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFF3F3F7E3E5F3E28FFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFF3F3F7E3E28FFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F7E3DFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +}; + +resource(101, "BEOS:M:STD_ICON") #'MICN' array { + $"FFFFFFFFFFFFFFB500FFFFFFFFFFFFFF" + $"FFFFFFFFFFFF19947F01FFFFFFFFFFFF" + $"FFFFFFFFFF19943E5F7F01FFFFFFFFFF" + $"FFFFFFFF18947E3E5F3E7E3DFFFFFFFF" + $"FF63FCFD687E6EFC687E74FCFDFC07FF" + $"63FAFDFCFA6867FAFCB4E5FBFDFBFB07" + $"FCFDDDDCAD12248DD487FA10DCB310D3" + $"17FAFC687E3E6CFDFED4FBFB42947F00" + $"29ADFCFAFD9468FAFDDDB418FBFB4229" + $"B807B410E5FD8DFAFC7E7F7EAE15FA10" + $"FEFC186DFBFCA7FAFD8EFD626E19FA11" + $"D4FBFAFAFCB487FAFC2468FAFAFB6226" + $"FFB5A78D278DB4A78EDC7E11ADCE27FF" + $"FFFFFFFFFF07417E7F3EDCFFFFFFFFFF" + $"FFFFFFFFFFFF07617E3BFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFD6DEFFFFFFFFFFFFFF" +}; diff --git a/src/add-ons/kernel/drivers/audio/sis7018/sis7018.settings.sample b/src/add-ons/kernel/drivers/audio/sis7018/sis7018.settings.sample new file mode 100644 index 0000000000..5e2c792449 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/sis7018.settings.sample @@ -0,0 +1,37 @@ +# +# The sample sis7018 driver settings file +# +# Rename it to sis7018 and put into +# /boot/home/config/settings/kernel/drivers/ +# After restarting Media Services the new settings will works. + +# Debug output - this is a possibility to view some kind of development related +# information - error and warning messages etc. + +# debug_output - activates debug output. The debug builds has debug output +# activated by default and this key has no effect on it. The release builds requires +# to activate this if you want to see debug messages in syslog or in private log file. +# +# debug_output true + +# debug_output_in_file - activates writing of debug messages into private log file. +# The name of this file is /boot/home/sis7018.log. If this key is set to true - no messages +# will be written into syslog. +# +# debug_output_in_file true + +# debug_output_file_rewrite - activates rewriting of private log file on +# calling driver_init() syscall. By default this set in false. +# +# debug_output_file_rewrite false + +# debug_trace_ac97 - activates more detailed logging of AC'97 operations. +# Do not use it with syslog output - you'll get only messages +# because BeOS's syslog daemon don't like a lot of messages in short time +# +# debug_trace_ac97 true + +# use_io_registers - switches driver from "memory" scheme to "io registers" +# scheme. This key is usefull for testers. Don't use it if you don't need it. +# +# use_io_registers true diff --git a/src/add-ons/kernel/drivers/audio/sis7018/sis7018hw.c b/src/add-ons/kernel/drivers/audio/sis7018/sis7018hw.c new file mode 100644 index 0000000000..220e96e00d --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/sis7018hw.c @@ -0,0 +1,563 @@ +/* + * This file is a part of SiS 7018 BeOS driver project. + * Copyright (c) 2002-2003 by Siarzuk Zharski + * + * This file may be used under the terms of the BSD License + * See the file "License" for details. + */ +#include //sprintf +#include + +#include "sis7018.h" +#include "sis7018hw.h" +#include "t4dwave.h" +#include "ac97.h" +#include "pcm.h" + +pci_module_info* pci; + +#define MIN_MEMORY_SIZE 0x2000 +#define PCHANNEL_ID 0x00 + +int intrs; + +uint32 hw_read(sis7018_dev *dev, int offset, int size) +{ + uint32 ret = 0xffffffff; + if(use_io_regs){ + switch(size){ + case 1: ret = (*pci->read_io_8)(dev->io_base + offset); break; + case 2: ret = (*pci->read_io_16)(dev->io_base + offset); break; + case 4: ret = (*pci->read_io_32)(dev->io_base + offset); break; + default: break; + } + } + else{ + switch(size){ + case 1: ret = *(int8 *)((char *)dev->regs_mem_base + offset); break; + case 2: ret = *(int16 *)((char *)dev->regs_mem_base + offset); break; + case 4: ret = *(int32 *)((char *)dev->regs_mem_base + offset); break; + default: break; + } + } + // TRACE("tr_rd off=%x ret=%lx\n", offset, ret); + return ret; +} + +void hw_write(sis7018_dev *dev, int offset, uint32 value, int size) +{ + //TRACE("tr_wr off=%x value = %lx\n", offset, value); + if(use_io_regs){ + switch(size){ + case 1: (*pci->write_io_8)(dev->io_base + offset, (uint8) value); break; + case 2: (*pci->write_io_16)(dev->io_base + offset, (uint16) value); break; + case 4: (*pci->write_io_32)(dev->io_base + offset, value); break; + default: break; + } + } + else{ + switch(size){ + case 1: *(int8 *)((char *)dev->regs_mem_base + offset) = (int8)value; break; + case 2: *(int16 *)((char *)dev->regs_mem_base + offset) = (int16)value; break; + case 4: *(int32 *)((char *)dev->regs_mem_base + offset) = (int32)value; break; + default: break; + } + } +} + +static void hw_clrint(sis7018_ch *ch) +{ + sis7018_dev *dev = ch->card; + int bank, chan; + + bank = (ch->index & 0x20) ? 1 : 0; + chan = ch->index & 0x1f; + hw_write(dev, bank? TR_REG_ADDRINTB : TR_REG_ADDRINTA, 1 << chan, 4); +} + +static void hw_enaint(sis7018_ch *ch, int enable) +{ + sis7018_dev *dev = ch->card; + int32 i, reg; + int bank, chan; + cpu_status cp; + + cp = disable_interrupts(); + acquire_spinlock(&dev->hardware); + + bank = (ch->index & 0x20) ? 1 : 0; + chan = ch->index & 0x1f; + reg = bank? TR_REG_INTENB : TR_REG_INTENA; + + i = hw_read(dev, reg, 4); + i &= ~(1 << chan); + i |= (enable? 1 : 0) << chan; + + hw_clrint(ch); + hw_write(dev, reg, i, 4); + + release_spinlock(&dev->hardware); + restore_interrupts(cp); +} + +static void hw_selch(sis7018_ch *ch) +{ + sis7018_dev *dev = ch->card; + int32 i; + + i = hw_read(dev, TR_REG_CIR, 4); + i &= ~TR_CIR_MASK; + i |= ch->index & 0x3f; + hw_write(dev, TR_REG_CIR, i, 4); +} + +static void hw_startch(sis7018_ch *ch) +{ + sis7018_dev *dev = ch->card; + int bank, chan; + + bank = (ch->index & 0x20) ? 1 : 0; + chan = ch->index & 0x1f; + hw_write(dev, bank? TR_REG_STARTB : TR_REG_STARTA, 1 << chan, 4); +} + +static void hw_stopch(sis7018_ch *ch) +{ + sis7018_dev *dev = ch->card; + int bank, chan; + + bank = (ch->index & 0x20) ? 1 : 0; + chan = ch->index & 0x1f; + hw_write(dev, bank? TR_REG_STOPB : TR_REG_STOPA, 1 << chan, 4); +} + +static void hw_wrch(sis7018_ch *ch) +{ + sis7018_dev *dev = ch->card; + int32 cr[TR_CHN_REGS], i; + cpu_status cp; + + ch->gvsel &= 0x00000001; + ch->fmc &= 0x00000003; + ch->fms &= 0x0000000f; + ch->ctrl &= 0x0000000f; + ch->pan &= 0x0000007f; + ch->rvol &= 0x0000007f; + ch->cvol &= 0x0000007f; + ch->vol &= 0x000000ff; + ch->ec &= 0x00000fff; + ch->alpha &= 0x00000fff; + ch->delta &= 0x0000ffff; + ch->lba &= 0x3fffffff; + + cr[1]=ch->lba; + cr[3]=(ch->fmc<<14) | (ch->rvol<<7) | (ch->cvol); + cr[4]=(ch->gvsel<<31) | (ch->pan<<24) | (ch->vol<<16) | (ch->ctrl<<12) | (ch->ec); + + switch (ch->card->type->ids.chip_id) + { + case SPA_PCI_ID: + case ALI_PCI_ID: + case TDX_PCI_ID: + case xDX_PCI_ID: + ch->cso &= 0x0000ffff; + ch->eso &= 0x0000ffff; + cr[0]=(ch->cso<<16) | (ch->alpha<<4) | (ch->fms); + cr[2]=(ch->eso<<16) | (ch->delta); + break; + case TNX_PCI_ID: + ch->cso &= 0x00ffffff; + ch->eso &= 0x00ffffff; + cr[0]=((ch->delta & 0xff)<<24) | (ch->cso); + cr[2]=((ch->delta>>8)<<24) | (ch->eso); + cr[3]|=(ch->alpha<<20) | (ch->fms<<16) | (ch->fmc<<14); + break; + } + cp = disable_interrupts(); + acquire_spinlock(&dev->hardware); + + hw_selch(ch); + for (i=0; ihardware); + restore_interrupts(cp); +} + +void hw_rdch(sis7018_ch *ch) +{ + sis7018_dev *dev = ch->card; + int32 cr[5], i; + cpu_status cp; + + cp = disable_interrupts(); + acquire_spinlock(&dev->hardware); + + hw_selch(ch); + for (i=0; i<5; i++) + cr[i]=hw_read(dev, TR_REG_CHNBASE+(i<<2), 4); + + release_spinlock(&dev->hardware); + restore_interrupts(cp); + + ch->lba= (cr[1] & 0x3fffffff); + ch->fmc= (cr[3] & 0x0000c000) >> 14; + ch->rvol= (cr[3] & 0x00003f80) >> 7; + ch->cvol= (cr[3] & 0x0000007f); + ch->gvsel= (cr[4] & 0x80000000) >> 31; + ch->pan= (cr[4] & 0x7f000000) >> 24; + ch->vol= (cr[4] & 0x00ff0000) >> 16; + ch->ctrl= (cr[4] & 0x0000f000) >> 12; + ch->ec= (cr[4] & 0x00000fff); + + switch(ch->card->type->ids.chip_id) + { + case SPA_PCI_ID: + case ALI_PCI_ID: + case TDX_PCI_ID: + case xDX_PCI_ID: + ch->cso= (cr[0] & 0xffff0000) >> 16; + ch->alpha= (cr[0] & 0x0000fff0) >> 4; + ch->fms= (cr[0] & 0x0000000f); + ch->eso= (cr[2] & 0xffff0000) >> 16; + ch->delta= (cr[2] & 0x0000ffff); + break; + case TNX_PCI_ID: + ch->cso= (cr[0] & 0x00ffffff); + ch->eso= (cr[2] & 0x00ffffff); + ch->delta= ((cr[2] & 0xff000000) >> 16) | ((cr[0] & 0xff000000) >> 24); + ch->alpha= (cr[3] & 0xfff00000) >> 20; + ch->fms= (cr[3] & 0x000f0000) >> 16; + break; + } +} + +status_t hw_pchannel_init(pcm_dev *dev) +{ + char name_buf[256]; + sis7018_ch *ch = &dev->play_channel; + ch->index = PCHANNEL_ID; + hw_pchannel_setblocksize(dev, 8192); + ch->ctrl = 0x0f; // 16-bit stereo signed + loop mode enabled + ch->delta = (48000 << 12 ) / 48000; + ch->card = dev->card; + ch->areaid=-1; + + ch->wr_lock = 0; + ch->write_waiting = 0; + sprintf(name_buf, "WS:%s", dev->name); + name_buf[B_OS_NAME_LENGTH-1] = 0; + ch->write_sem = create_sem(0, name_buf); + if (ch->write_sem < B_OK) + return ch->write_sem; + + set_sem_owner(ch->write_sem, B_SYSTEM_TEAM); + name_buf[0] = 'W'; name_buf[1] = 'E'; + ch->wr_entry = create_sem(1, name_buf); + if (ch->wr_entry < B_OK){ + delete_sem(ch->write_sem); + return ch->wr_entry; + } + set_sem_owner(ch->wr_entry, B_SYSTEM_TEAM); + ch->wr_time = 0; + return B_OK; +} + +void hw_pchannel_free(pcm_dev *dev) +{ + sis7018_ch *ch = &dev->play_channel; + if(ch->areaid >= 0){ + delete_area(ch->areaid); + ch->areaid = -1; + + delete_sem(ch->write_sem); + delete_sem(ch->wr_entry); + ch->write_sem = -1; + ch->wr_entry = -1; + } +} + +void hw_start(pcm_dev *dev) +{ + sis7018_ch *ch = &dev->play_channel; + + if(ch->active) + return; + + /* start out with a clean slate */ + TRACE("hw_start()\n"); +/* if (port->config.format == 0x11) + { + memset((void*)port->card->low_mem, 0x80, port->config.play_buf_size + + port->config.rec_buf_size); + } + else {*/ + + // TODO? + // memset((void *)port->card->low_mem, 0, port->config.play_buf_size + + // port->config.rec_buf_size); + //} + + ch->wr_cur = ch->wr_2; + ch->wr_silence = ch->mem_size; + ch->was_written = 0; + ch->wr_total = 0; + + ch->fmc = 3; + ch->fms = 0; + ch->ec = 0; + ch->alpha = 0; + ch->lba = (int32)ch->mem_phys; + ch->cso = 0; + ch->eso = ch->mem_size/(sizeof(int16)*2)-1; + ch->rvol = ch->cvol = 0x7f; + ch->gvsel = 0; + ch->pan = 0; + ch->vol = 0; + + hw_wrch(ch); + hw_enaint(ch, 1); + hw_startch(ch); + + ch->active = 1; +} + +void hw_stop(pcm_dev *dev) +{ + sis7018_ch *ch = &dev->play_channel; + if(!ch->active) + return; + + hw_stopch(ch); + ch->active = 0; +} + +static int32 hw_interrupt_handler(void * data) +{ + int32 active, mask, bufhalf, chnum, intsrc; + sis7018_dev *card = (sis7018_dev *)data; + sis7018_ch *ch; + int32 handled = B_UNHANDLED_INTERRUPT; + intrs++; + + acquire_spinlock(&card->hardware); + intsrc = hw_read(card, TR_REG_MISCINT, 4); + +#if DO_PCM + if (intsrc & TR_INT_ADDR){ + chnum = PCHANNEL_ID; + mask = 0x00000001 << PCHANNEL_ID; + active = hw_read(card, (chnum < 32)? TR_REG_ADDRINTA : TR_REG_ADDRINTB, 4); + bufhalf = hw_read(card, (chnum < 32)? TR_REG_CSPF_A : TR_REG_CSPF_B, 4); + if (active & mask){ + ch = &card->pcm.play_channel; + if(playback_interrupt(ch, (bufhalf & mask))) + handled = B_INVOKE_SCHEDULER; + else + handled = B_HANDLED_INTERRUPT; + } + hw_write(card, (chnum <= 32)? TR_REG_ADDRINTA : TR_REG_ADDRINTB, active, 4); + } +#endif +#if DO_MIDI + ssssssss + /*if (status & 0x80) { + if (midi_interrupt(card)) { + handled = B_INVOKE_SCHEDULER; + } else { + handled = B_HANDLED_INTERRUPT; + } + }*/ + handled = B_HANDLED_INTERRUPT; +#endif + + release_spinlock(&card->hardware); + return handled; +} + +void hw_increment_interrupt_handler(sis7018_dev * card) +{ + TRACE("hw_increment_interrupt_handler()\n"); + if (atomic_add(&card->inth_count, 1) == 0){ + TRACE("intline %d int %p\n", card->info.u.h0.interrupt_line, hw_interrupt_handler); + install_io_interrupt_handler(card->info.u.h0.interrupt_line, hw_interrupt_handler, card, 0); + } +} + +void hw_decrement_interrupt_handler(sis7018_dev * card) +{ + TRACE("hw_decrement_interrupt_handler()\n"); + if (atomic_add(&card->inth_count, -1) == 1){ + TRACE("remove_io_interrupt_handler()\n"); + remove_io_interrupt_handler(card->info.u.h0.interrupt_line, hw_interrupt_handler, card); + } +} + +status_t hw_initialize(sis7018_dev *card) +{ + status_t err = B_OK; + + cpu_status cp = disable_interrupts(); + acquire_spinlock(&card->hardware); + + switch (card->type->ids.chip_id){ + case SPA_PCI_ID: + hw_write(card, SPA_REG_GPIO, 0, 4); + hw_write(card, SPA_REG_CODECST, SPA_RST_OFF, 4); + break; + case TDX_PCI_ID: + case xDX_PCI_ID: + hw_write(card, TDX_REG_CODECST, TDX_CDC_ON, 4); + break; + case TNX_PCI_ID: + hw_write(card, TNX_REG_CODECST, TNX_CDC_ON, 4); + break; + } + + hw_write(card, TR_REG_CIR, TR_CIR_MIDENA | TR_CIR_ADDRENA, 4); + + release_spinlock(&card->hardware); + restore_interrupts(cp); + + err |= ac97init(card); + + return err; +} + +void hw_dump_device(int card_id) +{ + kprintf("interrupt handler called: %d\n", intrs); +} + +void hw_dump_pci_info(int card_id) +{ + kprintf("dump_pci_info is not yet implemented.\n"); +} + +void hw_dump_pcm_device(int card_id) +{ + kprintf("dump_pcm_device is not yet implemented.\n"); +} + +void hw_dump_midi_device(int card_id) +{ + kprintf("dump_midi_device is not yet implemented.\n"); +} + +static void hw_dump_channel(sis7018_ch *ch) +{ + kprintf("Pointer : %p\n", ch); + kprintf(" cso:%8lx, alpha:%8lx, fms:%8lx, fmc:%8lx, ec:%lx\n", + ch->cso, ch->alpha, ch->fms, ch->fmc, ch->ec); + kprintf(" lba:%8lx, eso:%8lx, delta:%8lx, rvol:%8lx, cvol:%lx\n", + ch->lba, ch->eso, ch->delta, ch->rvol, ch->cvol); + kprintf("gvsel:%8lx, pan:%8lx, vol:%8lx, ctrl:%8lx, active:%x\n", + ch->gvsel, ch->pan, ch->vol, ch->ctrl, (int)ch->active); + kprintf("index:%8x, card:0x%8p, mem_ptr:0x%8p, mem_size:%8lx, mem_phys:0x%8p\n", + ch->index, ch->card, ch->mem_ptr, ch->mem_size, ch->mem_phys); + kprintf("\n"); +} + +void hw_dump_play_channel(int card_id) +{ + sis7018_ch ch; + memcpy(&ch, &cards[card_id].pcm.play_channel, sizeof(sis7018_ch)); + kprintf("Dumping play channel information:\n"); + kprintf(" - cached:\n"); + hw_dump_channel(&ch); + kprintf(" - readed from hardware:\n"); + hw_rdch(&ch); + hw_dump_channel(&ch); +} + +static status_t hw_find_memory(sis7018_ch *ch, size_t blocksize) +{ + size_t low_size = (blocksize * 2+(B_PAGE_SIZE-1))&~(B_PAGE_SIZE-1); + physical_entry where; + size_t trysize; + area_id curarea; + void * addr; + char name[DEVNAME]; + + sprintf(name, "%s_area", ch->card->name); + if (low_size < MIN_MEMORY_SIZE) + low_size = MIN_MEMORY_SIZE; + trysize = low_size; + + curarea = find_area(name); + if (curarea != B_NAME_NOT_FOUND){ + TRACE("delete previously allocated area\n"); + delete_area(curarea); + curarea = -1; + } + + TRACE("allocating new area\n"); + + curarea = create_area(name, &addr, B_ANY_KERNEL_ADDRESS, + trysize, B_LOMEM, B_READ_AREA | B_WRITE_AREA); + TRACE("create_area(%lx) returned %lx logical %p\n", trysize, curarea, addr); + + if (curarea < 0) + goto oops; + + if (get_memory_map(addr, low_size, &where, 1) < 0){ + delete_area(curarea); + curarea = B_ERROR; + goto oops; + } + TRACE("physical %p\n", where.address); + if ((uint32)where.address & 0xff000000){ + delete_area(curarea); + curarea = B_ERROR; + goto oops; + } + if ((((uint32)where.address)+low_size) & 0xff000000){ + delete_area(curarea); + curarea = B_ERROR; + goto oops; + } + /* hey, it worked! */ + if (trysize > low_size) /* don't waste */ + resize_area(curarea, low_size); + +oops: + if (curarea < 0){ + TRACE("failed to create area\n"); + return curarea; + } +//a_o_k: + TRACE("successfully created area!\n"); + + ch->mem_size = low_size; + ch->mem_ptr = addr; + ch->mem_phys = (vuchar *)where.address; + + ch->wr_1 = ch->mem_ptr; + ch->wr_2 = ch->wr_1+ch->mem_size/2; + ch->wr_size = ch->mem_size/2; + + ch->areaid = curarea; + + if(ch->active){ + hw_stop(&ch->card->pcm); + hw_start(&ch->card->pcm); + } + + return B_OK; +} + +size_t hw_pchannel_setblocksize(pcm_dev *dev, size_t blocksize) +{ + sis7018_ch *ch = &dev->play_channel; + + if(ch->mem_size/2 != blocksize){ + if(ch->areaid >= 0){ + TRACE("delete area on resize\n"); + delete_area(ch->areaid); + ch->areaid = -1; + } + //TODO : error cheking. + hw_find_memory(ch, blocksize); + } + return blocksize; +} diff --git a/src/add-ons/kernel/drivers/audio/sis7018/sis7018hw.h b/src/add-ons/kernel/drivers/audio/sis7018/sis7018hw.h new file mode 100644 index 0000000000..a192488396 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/sis7018hw.h @@ -0,0 +1,35 @@ +/* + * This file is a part of SiS 7018 BeOS driver project. + * Copyright (c) 2002-2003 by Siarzuk Zharski + * + * This file may be used under the terms of the BSD License + * See the file "License" for details. + */ +#ifndef _SIS7018HW_H_ +#define _SIS7018HW_H_ + +#ifndef _SOUND_H +#include "sound.h" +#endif + +extern pci_module_info* pci; + +uint32 hw_read(sis7018_dev *dev, int offset, int size); +void hw_write(sis7018_dev *dev, int offset, uint32 value, int size); +status_t hw_pchannel_init(pcm_dev *dev); +void hw_pchannel_free(pcm_dev *dev); +size_t hw_pchannel_setblocksize(pcm_dev *dev, size_t blocksize); +void hw_start(pcm_dev *dev); +void hw_stop(pcm_dev *dev); +void hw_increment_interrupt_handler(sis7018_dev * card); +void hw_decrement_interrupt_handler(sis7018_dev * card); +status_t hw_initialize(sis7018_dev *card); +void hw_rdch(sis7018_ch *ch); + +void hw_dump_device(int card_id); +void hw_dump_pci_info(int card_id); +void hw_dump_pcm_device(int card_id); +void hw_dump_midi_device(int card_id); +void hw_dump_play_channel(int card_id); + +#endif //_SIS7018HW_H_ diff --git a/src/add-ons/kernel/drivers/audio/sis7018/sound.h b/src/add-ons/kernel/drivers/audio/sis7018/sound.h new file mode 100644 index 0000000000..4f6b192f8b --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/sound.h @@ -0,0 +1,94 @@ +/* ++++++++++ + Data structures and control calls for using the sound driver ++++++ */ +/* + Copyright 1999, Be Incorporated. All Rights Reserved. + This file may be used under the terms of the Be Sample Code License. +*/ +/* + * This file is a part of SiS 7018 BeOS driver project. + * Copyright permissions see above. + * + * Portion copyright (c) 2002-2003 by Siarzuk Zharski + */ +#ifndef _SOUND_H +#define _SOUND_H + +#ifndef _DRIVERS_H +#include +#endif + +enum adc_source { + line=0, aux1, mic, loopback +}; + +enum sample_rate { + kHz_8_0 = 0, kHz_5_51, kHz_16_0, kHz_11_025, kHz_27_42, kHz_18_9, + kHz_32_0, kHz_22_05, kHz_37_8 = 9, kHz_44_1 = 11, kHz_48_0, kHz_33_075, + kHz_9_6, kHz_6_62 +}; + +enum sample_format { + linear_8bit_unsigned_mono = 0, linear_8bit_unsigned_stereo, + ulaw_8bit_companded_mono, ulaw_8bit_companded_stereo, + linear_16bit_little_endian_mono, linear_16bit_little_endian_stereo, + alaw_8bit_companded_mono, alaw_8bit_companded_stereo, + sample_format_reserved_1, sample_format_reserved_2, + adpcm_4bit_mono, adpcm_4bit_stereo, + linear_16bit_big_endian_mono, linear_16bit_big_endian_stereo, + sample_format_reserved_3, sample_format_reserved_4 +}; + +struct channel { + enum adc_source adc_source; /* adc input source */ + char adc_gain; /* 0..15 adc gain, in 1.5 dB steps */ + char mic_gain_enable; /* non-zero enables 20 dB MIC input gain */ + char aux1_mix_gain; /* 0..31 aux1 mix to output gain. 12.0 to -34.5 dB in 1.5dB steps */ + char aux1_mix_mute; /* non-zero mutes aux1 mix */ + char aux2_mix_gain; /* 0..31 aux2 mix to output gain. 12.0 to -34.5 dB in 1.5dB steps */ + char aux2_mix_mute; /* non-zero mutes aux2 mix */ + char line_mix_gain; /* 0..31 line mix to output gain. 12.0 to -34.5 dB in 1.5dB steps */ + char line_mix_mute; /* non-zero mutes line mix */ + char dac_attn; /* 0..61 dac attenuation, in -1.5 dB steps */ + char dac_mute; /* non-zero mutes dac output */ +}; + +typedef struct sound_setup { + struct channel left; /* left channel setup */ + struct channel right; /* right channel setup */ + enum sample_rate sample_rate; /* sample rate */ + enum sample_format playback_format; /* sample format for playback */ + enum sample_format capture_format; /* sample format for capture */ + char dither_enable; /* non-zero enables dither on 16 => 8 bit */ + char loop_attn; /* 0..64 adc to dac loopback attenuation, in -1.5 dB steps */ + char loop_enable; /* non-zero enables loopback */ + char output_boost; /* zero (2.0 Vpp) non-zero (2.8 Vpp) output level boost */ + char highpass_enable;/* non-zero enables highpass filter in adc */ + char mono_gain; /* 0..64 mono speaker gain */ + char mono_mute; /* non-zero mutes speaker */ +} sound_setup; + + +/* ----- + control opcodes for sound driver +----- */ + +enum { + SOUND_GET_PARAMS = B_DEVICE_OP_CODES_END, + SOUND_SET_PARAMS, /* 10000 */ + SOUND_SET_PLAYBACK_COMPLETION_SEM, + SOUND_SET_CAPTURE_COMPLETION_SEM, + SOUND_GET_PLAYBACK_TIMESTAMP, /* 10003 */ + SOUND_GET_CAPTURE_TIMESTAMP, + SOUND_DEBUG_ON, + SOUND_DEBUG_OFF, /* 10006 */ + SOUND_UNSAFE_WRITE, + SOUND_UNSAFE_READ, + SOUND_LOCK_FOR_DMA, /* 10009 */ + SOUND_SET_CAPTURE_PREFERRED_BUF_SIZE, + SOUND_SET_PLAYBACK_PREFERRED_BUF_SIZE, + SOUND_GET_CAPTURE_PREFERRED_BUF_SIZE, /* 10012 */ + SOUND_GET_PLAYBACK_PREFERRED_BUF_SIZE +}; + +#endif diff --git a/src/add-ons/kernel/drivers/audio/sis7018/t4dwave.h b/src/add-ons/kernel/drivers/audio/sis7018/t4dwave.h new file mode 100644 index 0000000000..4dc4e78064 --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/t4dwave.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1999 Cameron Grant + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/dev/sound/pci/t4dwave.h,v 1.3.2.3 2001/08/30 23:10:50 greid Exp $ + */ +/* + * This file is a part of SiS 7018 BeOS driver project. + * Copyright permissions see above. + * + * Portion copyright (c) 2002 by Siarzuk Zharski + * + * $Source: /cvsroot/sis4be/sis7018/t4dwave.h,v $ + * $Author: zharik $ + * $Revision: 1.4 $ + * $Date: 2004/06/24 15:47:40 $ + */ +#ifndef _T4DWAVE_REG_H +#define _T4DWAVE_REG_H + +#define TR_REG_CIR 0xa0 +#define TR_CIR_MASK 0x0000003f +#define TR_CIR_ADDRENA 0x00001000 +#define TR_CIR_MIDENA 0x00002000 +#define TR_REG_MISCINT 0xb0 +#define TR_INT_ADDR 0x00000020 +#define TR_INT_SB 0x00000004 + +#define TR_REG_DMAR0 0x00 +#define TR_REG_DMAR4 0x04 +#define TR_REG_DMAR11 0x0b +#define TR_REG_DMAR15 0x0f +#define TR_REG_SBR4 0x14 +#define TR_REG_SBR5 0x15 +#define TR_SB_INTSTATUS 0x82 +#define TR_REG_SBR9 0x1e +#define TR_REG_SBR10 0x1f +#define TR_REG_SBBL 0xc0 +#define TR_REG_SBCTRL 0xc4 +#define TR_REG_SBDELTA 0xac + +#define TR_CDC_DATA 16 +#define TDX_REG_CODECWR 0x40 +#define TDX_REG_CODECRD 0x44 +#define TDX_CDC_RWSTAT 0x00008000 +#define TDX_REG_CODECST 0x48 +#define TDX_CDC_SBCTRL 0x40 +#define TDX_CDC_ACTIVE 0x20 +#define TDX_CDC_READY 0x10 +#define TDX_CDC_ADCON 0x08 +#define TDX_CDC_DACON 0x02 +#define TDX_CDC_RESET 0x01 +#define TDX_CDC_ON (TDX_CDC_ADCON|TDX_CDC_DACON) + +#define SPA_REG_CODECRD 0x44 +#define SPA_REG_CODECWR 0x40 +#define SPA_REG_CODECST 0x48 +#define SPA_RST_OFF 0x0f0000 +#define SPA_REG_GPIO 0x48 +#define SPA_CDC_RWSTAT 0x00008000 + +#define TNX_REG_CODECWR 0x44 +#define TNX_REG_CODEC1RD 0x48 +#define TNX_REG_CODEC2RD 0x4c +#define TNX_CDC_RWSTAT 0x00000c00 +#define TNX_CDC_SEC 0x00000100 +#define TNX_REG_CODECST 0x40 +#define TNX_CDC_READY2 0x40 +#define TNX_CDC_ADC2ON 0x20 +#define TNX_CDC_DAC2ON 0x10 +#define TNX_CDC_READY1 0x08 +#define TNX_CDC_ADC1ON 0x04 +#define TNX_CDC_DAC1ON 0x02 +#define TNX_CDC_RESET 0x01 +#define TNX_CDC_ON (TNX_CDC_ADC1ON|TNX_CDC_DAC1ON) + + +#define TR_REG_STARTA 0x80 +#define TR_REG_STOPA 0x84 +#define TR_REG_CSPF_A 0x90 +#define TR_REG_ADDRINTA 0x98 +#define TR_REG_INTENA 0xa4 + +#define TR_REG_STARTB 0xb4 +#define TR_REG_STOPB 0xb8 +#define TR_REG_CSPF_B 0xbc +#define TR_REG_ADDRINTB 0xd8 +#define TR_REG_INTENB 0xdc + +#define TR_REG_CHNBASE 0xe0 +#define TR_CHN_REGS 5 + +#endif diff --git a/src/add-ons/kernel/drivers/audio/sis7018/uninstall.sh b/src/add-ons/kernel/drivers/audio/sis7018/uninstall.sh new file mode 100644 index 0000000000..fe6aeee54f --- /dev/null +++ b/src/add-ons/kernel/drivers/audio/sis7018/uninstall.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +answer=`alert "Do you really want to uninstall the Sis 7018 driver?" "No" "Yes"` +if [ $answer == "No" ]; then + exit +fi + +rm ~/config/add-ons/kernel/drivers/bin/sis7018 +rm ~/config/settings/kernel/drivers/sis7018 +rm ~/config/add-ons/kernel/drivers/dev/audio/old/sis7018 + +alert "The SiS7018 driver has been removed. + +Restart your system now." diff --git a/src/add-ons/kernel/drivers/audio/usb_audio/Jamfile b/src/add-ons/kernel/drivers/audio/usb_audio/Jamfile index 2bcf54179b..b6620afeec 100644 --- a/src/add-ons/kernel/drivers/audio/usb_audio/Jamfile +++ b/src/add-ons/kernel/drivers/audio/usb_audio/Jamfile @@ -1,5 +1,9 @@ SubDir HAIKU_TOP src add-ons kernel drivers audio usb_audio ; +SetSubDirSupportedPlatformsBeOSCompatible ; + +UsePrivateHeaders audio ; + KernelAddon usb_audio : kernel drivers bin : usb_audio.c USB_audio_utils.c diff --git a/src/add-ons/kernel/drivers/audio/usb_audio/R3MediaDefs.h b/src/add-ons/kernel/drivers/audio/usb_audio/R3MediaDefs.h deleted file mode 100644 index 814a5c8c03..0000000000 --- a/src/add-ons/kernel/drivers/audio/usb_audio/R3MediaDefs.h +++ /dev/null @@ -1,88 +0,0 @@ -/****************************************************************************** - - File: MediaDefs.h - - Copyright 1995-1999, Be Incorporated - This file may be used under the terms of the Be Sample Code License. - -******************************************************************************/ -#ifndef _R3_MEDIA_DEFS_H -#define _R3_MEDIA_DEFS_H - -#include -#include -#if defined(__cplusplus) - #include -#else -/* values for byte_ordering */ -enum { B_BIG_ENDIAN, B_LITTLE_ENDIAN }; - -/* values for sample_format */ -enum { - B_UNDEFINED_SAMPLES, - B_LINEAR_SAMPLES, - B_FLOAT_SAMPLES, - B_MULAW_SAMPLES - }; -#endif - -/* Buffer header for audio server */ - -typedef struct audio_buffer_header { - int32 buffer_number; - int32 subscriber_count; - bigtime_t time; - int32 reserved_1; - int32 reserved_2; - bigtime_t sample_clock; -} audio_buffer_header; - - -#define B_MEDIA_LEVEL B_REAL_TIME_PRIORITY - -#define B_NO_CHANGE (-1) - -/* ================ - Subscriber IDs and special values - ================ */ - -#define B_NO_SUBSCRIBER_ID ((subscriber_id)-1) -#define B_NO_SUBSCRIBER_NAME "not subscribed" - -#define B_SHARED_SUBSCRIBER_ID ((subscriber_id)-2) -#define B_SHARED_SUBSCRIBER_NAME "shared subscriber" - -/* ================ - Values for sound files and audio streams - ================ */ - - -/* Audio device codes for BAudioSubscriber's - * Get/SetVolume() and EnableDevice() calls - */ -enum { - B_CD_THROUGH=0, - B_LINE_IN_THROUGH, - B_ADC_IN, - B_LOOPBACK, - B_DAC_OUT, - B_MASTER_OUT, - B_SPEAKER_OUT, - B_SOUND_DEVICE_END - }; - -/* ADC input codes */ -enum { - B_CD_IN, - B_LINE_IN, - B_MIC_IN - }; - - -enum { - B_DAC_STREAM = 2354, - B_ADC_STREAM - }; - -#endif -/* #ifndef _R3_MEDIA_DEFS_H*/ diff --git a/src/add-ons/kernel/drivers/bus/Jamfile b/src/add-ons/kernel/drivers/bus/Jamfile index dae876c50f..817b78c74d 100644 --- a/src/add-ons/kernel/drivers/bus/Jamfile +++ b/src/add-ons/kernel/drivers/bus/Jamfile @@ -1,4 +1,4 @@ SubDir HAIKU_TOP src add-ons kernel drivers bus ; -SubInclude HAIKU_TOP src add-ons kernel drivers bus scsi ; SubInclude HAIKU_TOP src add-ons kernel drivers bus pcmcia ; +SubInclude HAIKU_TOP src add-ons kernel drivers bus scsi ; diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp index 3640da720e..0b454a9b90 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp @@ -129,6 +129,7 @@ read_settings(size_t &memorySize, bool &hardwareCursor) static size_t determine_stolen_memory_size(intel_info &info) { +#if 0 // read stolen memory from the PCI configuration of the PCI bridge uint16 memoryConfig = gPCI->read_pci_config(0, 0, 0, INTEL_GRAPHICS_MEMORY_CONTROL, 2); size_t memorySize = 1 << 20; // 1 MB @@ -171,6 +172,10 @@ determine_stolen_memory_size(intel_info &info) } return memorySize; +#endif +// stippi: das sorgt dafür, daß er den Speicher vom BIOS komplett +// wegwirft + return 0; } @@ -315,7 +320,7 @@ intel_extreme_init(intel_info &info) // on demand only, but we're lazy here... info.additional_memory_area = additionalMemoryCreator.Create("intel additional memory", (void **)&additionalMemory, B_ANY_KERNEL_ADDRESS, - totalSize - stolenSize, B_FULL_LOCK, 0); + totalSize - stolenSize, B_FULL_LOCK | B_CONTIGUOUS, 0); if (info.additional_memory_area < B_OK) return info.additional_memory_area; } else diff --git a/src/add-ons/kernel/drivers/ports/Jamfile b/src/add-ons/kernel/drivers/ports/Jamfile new file mode 100644 index 0000000000..05ec19bdd2 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/Jamfile @@ -0,0 +1,3 @@ +SubDir HAIKU_TOP src add-ons kernel drivers ports ; + +SubInclude HAIKU_TOP src add-ons kernel drivers ports usb_serial ; diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/Jamfile b/src/add-ons/kernel/drivers/ports/usb_serial/Jamfile new file mode 100644 index 0000000000..80d0e38b82 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/Jamfile @@ -0,0 +1,27 @@ +SubDir HAIKU_TOP src add-ons kernel drivers ports usb_serial ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +local defines = [ FDefines DB_USB_USE_V2_MODULE ] ; + +SubDirCcFlags $(defines) ; + +KernelAddon usb_serial : kernel drivers bin : + driver.c + tracing.c + acm.c + prolific.c + ftdi.c +; + +AddResources usb_serial : usb_serial.rdef ; + + +Package haiku-usb_serial-cvs + : + usb_serial + : + boot home config add-ons kernel drivers bin ; + +Package haiku-usb_serial-cvs : usb_serial.settings.sample + : boot home config settings kernel drivers sample ; diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/ReadMe.html b/src/add-ons/kernel/drivers/ports/usb_serial/ReadMe.html new file mode 100644 index 0000000000..60152ba583 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/ReadMe.html @@ -0,0 +1,262 @@ + +BeOS driver for USB serial adapters and CDC ACM compatible USB modems + +

BeOS driver for USB serial adapters and CDC ACM compatible USB modems

+ +

Introduction

+

This driver is designed to support following USB serial adapters and modems:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameVendor IDProduct ID
USB CDC ACM-compatible modems:anyany
Prolific PL2303-based adapters:
PL2303 Serial adapter (IODATA USB-RSAQ2)0x067b0x04bb
I/O Data USB serial adapter USB-RSAQ10x04bb0x0a03
Aten Serial adapter"0x05570x2008
TDK USB-PHS Adapter UHA64000x04bf0x0117
Ratoc USB serial adapter REX-USB600x05840xb000 +
PL2303 Serial adapter (ATEN/IOGEAR UC232A)0x067b0x2303
Elecom UC-SGT0x056e0x5003
FTDI-based:
FTDI 8U100AX serial converter0x04030x8372
FTDI 8U232AM serial converter0x04030x6001
+ +
+NOTE that + +There are a lot of USB modems in this world. Not every one can be supported by this driver. +Only CDC ACM-compatible modems will works with it. How you can guess it? Just try to install +this driver and plug your modem in. If you get the usb0 in ports list - it probably works. +If not - obtain the information about your device and +send it to me. +
+NOTE that + +If your computer has the OHCI-compatible USB hardware you are out of luck. This hardware is not +supported by non-Dan0-like versions. See the BeOS.USB.patches vor details and +solutions. +
+NOTE that + +For Dan0 you have to build a special version of binaries. +Read here for details. +
+WARNING!!! + +If your system was patched with BeOS.USB.patches - your system is candidate to crash +trying this driver!! You must very accurate read this. +
+ +What's new: +
+Version: + +History: +
+0.1.0-dev-0 + +very first "development" release. +
+1.0.0-RC-1 + +Release Candidate 1. +
    +
  • Code re-designed +
  • Code is chaged to be compatible with Dan0. +
+
+ + +

1. Installation

+
    +
  • Run install.sh +
  • If all is OK run SerialConnect application and press Alt-D. If you can select the port, that + looks like "usb0" - your device was identified as supported. You can use this "usb" - port as + you do with usual "serial" ones. Good luck! +
  • If something goes wrong - open the Terminal and run the following command: +

    ls /dev/ports/ +

    It lists all ports that present on your system. If you have no "usb0" here but sure, that you + have USB to Serial adapter plugged in your USB port - write an e-mail about your problem. I'll + try to help you. +

+

2. Uninstallation

+
    +
  • Run uninstall.sh +
+ +

3. Problems solving

+
    +
  • If this driver crash your system - reboot and press "Space" during load. In boot menu select + "Disable user add-ons" and continue boot. Uninstall driver and reboot again into normal mode. + Write me a e-mail about this problem. +
+

4. "Unknown" devices

+ + If you have something, that looks like USB->RS232(serial) adapter or USB modem and tried it with + this driver but have no success - download + usb device info tool and use it to get required information. +
    +
  • Unplug all USB devices and hubs from your PC. +
  • Go into Terminal and run the following command: + ls -alR /dev/bus/usb + You should see something like this: +
    +$ ls -alR /dev/bus/usb/
    +/dev/bus/usb:
    +total 0
    +drw-r--r--   1 walther  users           0 May 31 23:16 .
    +drw-r--r--   1 walther  users           0 Jun  1  2003 ..
    +drw-r--r--   1 walther  users           0 May 31 23:16 0
    +drw-r--r--   1 walther  users           0 May 31 23:16 1
    +crw-r--r--   1 walther  users      0,   0 May 31 23:16 unload
    +
    +/dev/bus/usb/0:
    +total 0
    +drw-r--r--   1 walther  users           0 May 31 23:16 .
    +drw-r--r--   1 walther  users           0 May 31 23:16 ..
    +crw-r--r--   1 walther  users      0,   0 May 31 23:16 hub
    +
    +/dev/bus/usb/1:
    +total 0
    +drw-r--r--   1 walther  users           0 May 31 23:16 .
    +drw-r--r--   1 walther  users           0 May 31 23:16 ..
    +crw-r--r--   1 walther  users      0,   0 May 31 23:16 hub
    +
    + +
  • Note this information. +
  • Now plug your USB serial adapter into PC and run ls -alR /dev/bus/usb/ again. +You'll get something slightly different: +
    +$ ls -alR /dev/bus/usb/
    +/dev/bus/usb:
    +total 0
    +drw-r--r--   1 walther  users           0 May 31 23:16 .
    +drw-r--r--   1 walther  users           0 Jun  1  2003 ..
    +drw-r--r--   1 walther  users           0 May 31 23:16 0
    +drw-r--r--   1 walther  users           0 May 31 23:16 1
    +crw-r--r--   1 walther  users      0,   0 May 31 23:16 unload
    +
    +/dev/bus/usb/0:
    +total 0
    +drw-r--r--   1 walther  users           0 May 31 23:16 .
    +drw-r--r--   1 walther  users           0 May 31 23:16 ..
    +crw-r--r--   1 walther  users      0,   0 May 31 23:17 1
    +crw-r--r--   1 walther  users      0,   0 May 31 23:16 hub
    +
    +/dev/bus/usb/1:
    +total 0
    +drw-r--r--   1 walther  users           0 May 31 23:16 .
    +drw-r--r--   1 walther  users           0 May 31 23:16 ..
    +crw-r--r--   1 walther  users      0,   0 May 31 23:16 hub
    +
    + +$ +
  • Compare this results with previous one and look for file, +that appeared. This file is your USB serial adapter. +
  • Unpack downloaded usb_dev_info command and run it with full path to file appeared in +the second listing. For my sample I should run: +usb_dev_info /dev/bus/usb/0/1 +I'll get the following: +
    +$ usb_dev_info /dev/bus/usb/0/1
    +[Device]
    +Class .................. 0
    +Subclass ............... 0
    +Protocol ............... 0
    +Vendor ID .............. 0x067b
    +Product ID ............. 0x2303
    +Version ................ 0x0202
    +Manufacturer String .... ""
    +Product String ......... ""
    +Serial Number .......... ""
    +  [Configuration 0]
    +    [Interface 0]
    +    Class .............. 255
    +    Subclass ........... 0
    +    Protocol ........... 0
    +      [Endpoint 0]
    +      MaxPacketSize .... 10
    +      Interval ......... 1
    +      Type ............. Interrupt
    +      Direction ........ Input
    +      [Endpoint 1]
    +      MaxPacketSize .... 64
    +      Interval ......... 0
    +      Type ............. Bulk
    +      Direction ........ Output
    +      [Endpoint 2]
    +      MaxPacketSize .... 64
    +      Interval ......... 0
    +      Type ............. Bulk
    +      Direction ........ Input
    +
    +
  • Send this information to me with some additional words about your device. +
+ +

What is wrong with BeOS.USB.patches?

+ +All know that "classical" BeOS R5 don't works on OHCI USB hardware. But some time ago on one well-known +BeOS file-sharing network appeared patches for plain R5. Those patches allows to work with OHCI +hardware under this system version. Looks like it is some part of Dan0 or other "leaked" versions. +There are 3 patches in BeOS.USB.patches.zip: +

1. beos-usb-patch, +

2. beos-usb.modem-patch, +

3. beos-usb.modem-patch.sm. +

The Evil is in two last patches. The source of problem - changed functions in tty module. The +Dan0 contains two additional functions in the middle of tty module description table. But the module version +was not changed - it is still v1. So if driver, that was compiled with old tty module layout, will try to use it - system +crashes. Looks like those patches contains the same "enchanced" tty module like in Dan0. So - you should roll back +those modem-patches - restore the previous configuration as described in patches readme. The first one +- "beos-usb-patch" is OK. + +

Information for Dan0 users

+ +The driver is still not working under Dan0 out of box. At first you have no need to use it for ACM-compatible devices, +because Dan0 has it's own implementation of usb_acm driver. There is also one problem with Dan0 - the +"tty" module was chaged in very dangerous way - there is no possibility to create backward compatible +implementation of serial port driver with the new tty interfaces. If you really have one of those USB Serial +Adapters and want to use it under Dan0 - you have to make some hand work. Sorry for this, but I have not +using Dan0 as my main working system. So you must to build Dan0 version by yourself. Thank you for your patience. Below +is an operations you need to install USB serial driver for Dan0: +
    +
  • Obtain the zip archive with the USB Serial driver for R5. +
  • Obtain the zip archive with sources of the driver. +
  • ATTENTION!!! Unplug all USB devices from your PC. You must to do this - in opposite case you +system can crash! +
  • Install the USB Serial driver as was described in this document. +
  • Unpack the sources of the driver, go to Terminal, change dir to unpacked sources and run the +"make" command. You should see many warnings but no errors. +
  • Stay in Terminal and change the current directory to "obj.x86". You should see the "usb_serial" +driver binary if everything went OK. +
  • Now copy the usb_serial to right place: +
    +cp ./usb_serial ~/config/add-ons/kernel/drivers/bin/usb_serial
    +
    +and let the system to know about changes: +
    +rescan usb_serial
    +
    +
  • The last thing you have to do - disable ACM support in this driver: +Open the file /boot/home/config/settings/kernel/drivers/usb_serial in your text editor and add or +uncomment the following string: +
    +support_acm_devices false
    +
    +
  • Now you should have working version of USB Serial driver under Dan0. +
+

Siarzuk Zharski +

http://www.zharik.host.sk/ + \ No newline at end of file diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/acm.c b/src/add-ons/kernel/drivers/ports/usb_serial/acm.c new file mode 100644 index 0000000000..0b2ed7432e --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/acm.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + * + */ + +#include +#include +#include +#include + +#include "driver.h" +#include "acm.h" + +status_t add_acm_device(usb_serial_device *usd, + const usb_configuration_info *uci) +{ + struct usb_endpoint_info *comm_epi = NULL; + struct usb_endpoint_info *data_out_epi = NULL; + struct usb_endpoint_info *data_in_epi = NULL; + status_t status = ENODEV; + int i = 0; + + TRACE_FUNCALLS("> add_acm_device(%08x, %08x)\n", usd, uci); + + for(i=0; i < uci->interface_count; i++){ + usb_interface_descriptor *uid = + uci->interface[i].active->descr; + if(uid->interface_class == USB_INT_CLASS_CDC && + uid->interface_subclass == USB_INT_SUBCLASS_ABSTRACT_CONTROL_MODEL && + uid->num_endpoints == 1){ + comm_epi = uci->interface[i].active->endpoint; + } + + if(uid->interface_class == USB_INT_CLASS_CDC_DATA && + (uid->interface_subclass == 2 || // ????????????? + uid->interface_subclass == USB_INT_SUBCLASS_DATA)){ + if(uid->num_endpoints == 2){ + data_out_epi = &uci->interface[i].active->endpoint[0]; + data_in_epi = &uci->interface[i].active->endpoint[1]; + } + } + if(comm_epi && data_out_epi && data_in_epi) + break; + } + + if(comm_epi && data_out_epi && data_in_epi){ + status = add_device(usd, uci, comm_epi, data_out_epi, data_in_epi); + } + + TRACE_FUNCRET("< add_acm_device returns:%08x\n", status); + return status; +} + +status_t reset_acm_device(usb_serial_device *usd){ + status_t status = B_OK; + TRACE_FUNCALLS("> reset_acm_device(%08x)\n", usd); + TRACE_FUNCRET("< reset_acm_device returns:%08x\n", status); + return status; +} + +status_t set_line_coding_acm(usb_serial_device *usd, + usb_serial_line_coding *line_coding){ + size_t len = 0; + status_t status = B_OK; + TRACE_FUNCALLS("> set_line_coding_acm(%08x, {%d, %02x, %02x, %02x})\n", + usd, line_coding->speed, + line_coding->stopbits, + line_coding->parity, + line_coding->databits); + status = (*usb_m->send_request)(usd->dev, + USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, + SET_LINE_CODING, 0x0, 0x0, + sizeof(usb_serial_line_coding), + line_coding, + sizeof(usb_serial_line_coding), &len); + TRACE_FUNCRET("< set_line_coding_acm returns:%08x\n", status); + return status; +} + +status_t set_control_line_state_acm(usb_serial_device *usd, uint16 state){ + size_t len = 0; + status_t status = B_OK; + TRACE_FUNCALLS("> set_control_line_state_acm(%08x, %04x)\n", usd, state); + status = (*usb_m->send_request)(usd->dev, + USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, + SET_CONTROL_LINE_STATE, state, 0, 0, 0, 0, + &len); + TRACE_FUNCRET("< set_control_line_state_acm returns:%08x\n", status); + return status; +} + +void on_read_acm(usb_serial_device *usd, char **buf, size_t *num_bytes){ +} + +void on_write_acm(usb_serial_device *usd, const char *buf, size_t *num_bytes){ + if(*num_bytes > usd->write_buffer_size) + *num_bytes = usd->write_buffer_size; + memcpy(usd->write_buffer, buf, *num_bytes); +} + +void on_close_acm(usb_serial_device *usd){ + TRACE_FUNCALLS("> add_acm_device(%08x)\n", usd); + (*usb_m->cancel_queued_transfers)(usd->pipe_read); + (*usb_m->cancel_queued_transfers)(usd->pipe_write); + (*usb_m->cancel_queued_transfers)(usd->pipe_control); +} + diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/acm.h b/src/add-ons/kernel/drivers/ports/usb_serial/acm.h new file mode 100644 index 0000000000..e1043cdd6c --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/acm.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + * + */ + +#ifndef _USB_ACM_H_ + #define _USB_ACM_H_ + +status_t add_acm_device(usb_serial_device *usd, + const usb_configuration_info *uci); +status_t reset_acm_device(usb_serial_device *usd); +status_t set_line_coding_acm(usb_serial_device *usd, + usb_serial_line_coding *line_coding); +status_t set_control_line_state_acm(usb_serial_device *usd, uint16 state); +void on_read_acm(usb_serial_device *usd, char **buf, size_t *num_bytes); +void on_write_acm(usb_serial_device *usd, const char *buf, size_t *num_bytes); +void on_close_acm(usb_serial_device *usd); + +#endif //_USB_ACM_H_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/driver.c b/src/add-ons/kernel/drivers/ports/usb_serial/driver.c new file mode 100644 index 0000000000..80ae4698c1 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/driver.c @@ -0,0 +1,867 @@ +/* + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + * + */ + +#include +#include +#include +#include +#include +#include /* strerror */ +#include /* strtol */ +#include /* sprintf */ + +#include "driver.h" +#include "acm.h" +#include "prolific.h" +#include "ftdi.h" + +/* driver callbacks forward declarations */ +static status_t usb_serial_open (const char *name, uint32 flags, void** cookie); +static status_t usb_serial_read (void* cookie, + off_t position, void *buf, size_t* num_bytes); +static status_t usb_serial_write (void* cookie, off_t position, + const void* buffer, size_t* num_bytes); +static status_t usb_serial_control (void* cookie, uint32 op, void* arg, size_t len); +static status_t usb_serial_close (void* cookie); +static status_t usb_serial_free (void* cookie); +/* USB notify callbacks forward declarations */ +status_t usb_serial_device_added(const usb_device *dev, void **cookie); +status_t usb_serial_device_removed(void *cookie); + +/* The base name of drivers created in /dev/ports/ directory */ +#define BASENAME_LEN 0x09 /*must be synchronized with below !!!*/ +static const char *basename = "ports/usb%u"; + +/* function pointers for the device hooks entry points */ +device_hooks usb_serial_hooks = { + usb_serial_open, /* -> open entry point */ + usb_serial_close, /* -> close entry point */ + usb_serial_free, /* -> free cookie */ + usb_serial_control, /* -> control entry point */ + usb_serial_read, /* -> read entry point */ + usb_serial_write /* -> write entry point */ +}; +/* USB notify hooks */ +static usb_notify_hooks notify_hooks = { + &usb_serial_device_added, + &usb_serial_device_removed +}; +/* kernel modules */ +usb_module_info *usb_m; /* usb layer */ +tty_module_info *tty_m; /* tty layer */ + +struct tty usb_serial_tty[DEVICES_COUNT]; +struct ddomain usb_serial_dd; +/* hardware devices, supported by this driver. + See description field for human readable names */ +usb_serial_hw usb_serial_hw_devices[] = { + {0, 0, add_acm_device, reset_acm_device, + set_line_coding_acm, set_control_line_state_acm, + on_read_acm, on_write_acm, on_close_acm, + "CDC ACM compatible device"}, + + {VND_PROLIFIC, PROD_PROLIFIC_RSAQ2, + add_prolific_device, reset_prolific_device, + set_line_coding_acm, set_control_line_state_acm, + on_read_acm, on_write_acm, on_close_acm, + "PL2303 Serial adapter (IODATA USB-RSAQ2)"}, + {VND_IODATA, PROD_IODATA_USBRSAQ, + add_prolific_device, reset_prolific_device, + set_line_coding_acm, set_control_line_state_acm, + on_read_acm, on_write_acm, on_close_acm, + "I/O Data USB serial adapter USB-RSAQ1"}, + {VND_ATEN, PROD_ATEN_UC232A, + add_prolific_device, reset_prolific_device, + set_line_coding_acm, set_control_line_state_acm, + on_read_acm, on_write_acm, on_close_acm, + "Aten Serial adapter"}, + {VND_TDK, PROD_TDK_UHA6400, + add_prolific_device, reset_prolific_device, + set_line_coding_acm, set_control_line_state_acm, + on_read_acm, on_write_acm, on_close_acm, + "TDK USB-PHS Adapter UHA6400"}, + {VND_RATOC, PROD_RATOC_REXUSB60, + add_prolific_device, reset_prolific_device, + set_line_coding_acm, set_control_line_state_acm, + on_read_acm, on_write_acm, on_close_acm, + "Ratoc USB serial adapter REX-USB60"}, + {VND_PROLIFIC, PROD_PROLIFIC_PL2303, + add_prolific_device, reset_prolific_device, + set_line_coding_acm, set_control_line_state_acm, + on_read_acm, on_write_acm, on_close_acm, + "PL2303 Serial adapter (ATEN/IOGEAR UC232A)"}, + {VND_ELECOM, PROD_ELECOM_UCSGT, + add_prolific_device, reset_prolific_device, + set_line_coding_acm, set_control_line_state_acm, + on_read_acm, on_write_acm, on_close_acm, + "Elecom UC-SGT"}, + {VND_SOURCENEXT, PROD_SOURCENEXT_KEIKAI8, + add_prolific_device, reset_prolific_device, + set_line_coding_acm, set_control_line_state_acm, + on_read_acm, on_write_acm, on_close_acm, + "SOURCENEXT KeikaiDenwa 8"}, + {VND_SOURCENEXT, PROD_SOURCENEXT_KEIKAI8_CHG, + add_prolific_device, reset_prolific_device, + set_line_coding_acm, set_control_line_state_acm, + on_read_acm, on_write_acm, on_close_acm, + "SOURCENEXT KeikaiDenwa 8 with charger"}, + {VND_HAL, PROD_HAL_IMR001, + add_prolific_device, reset_prolific_device, + set_line_coding_acm, set_control_line_state_acm, + on_read_acm, on_write_acm, on_close_acm, + "HAL Corporation Crossam2+USB"}, + + {VND_FTDI, PROD_8U100AX, + add_ftdi_device, reset_ftdi_device, + set_line_coding_ftdi, set_control_line_state_ftdi, + on_read_ftdi, on_write_ftdi, on_close_ftdi, + "FTDI 8U100AX serial converter"}, + {VND_FTDI, PROD_8U232AM, + add_ftdi_device, reset_ftdi_device, + set_line_coding_ftdi, set_control_line_state_ftdi, + on_read_ftdi, on_write_ftdi, on_close_ftdi, + "FTDI 8U232AM serial converter"}, +}; +/* supported devices*/ +usb_support_descriptor supported_devices[] = { + {USB_DEV_CLASS_COMM, 0, 0, 0, 0}, + {0, 0, 0, VND_PROLIFIC, PROD_PROLIFIC_RSAQ2 }, + {0, 0, 0, VND_IODATA, PROD_IODATA_USBRSAQ }, + {0, 0, 0, VND_ATEN, PROD_ATEN_UC232A }, + {0, 0, 0, VND_TDK, PROD_TDK_UHA6400 }, + {0, 0, 0, VND_RATOC, PROD_RATOC_REXUSB60 }, + {0, 0, 0, VND_PROLIFIC, PROD_PROLIFIC_PL2303 }, + {0, 0, 0, VND_ELECOM, PROD_ELECOM_UCSGT }, + + {0, 0, 0, VND_FTDI, PROD_8U100AX }, + {0, 0, 0, VND_FTDI, PROD_8U232AM }, +}; +/* main devices table locking semaphore */ +sem_id usb_serial_lock = -1; +/* array of pointers to device objects */ +usb_serial_device *usb_serial_devices[DEVICES_COUNT]; +/* the names of "ports" */ +char * usb_serial_names[DEVICES_COUNT + 1]; +/* speed constants, supported by this driver. */ +const uint32 serial_tty_speed[] = { + 0x00000000, //B0 + 0x00000032, //B50 + 0x0000004B, //B75 + 0x0000006E, //B110 + 0x00000086, //B134 + 0x00000096, //B150 + 0x000000C8, //B200 + 0x0000012C, //B300 + 0x00000258, //B600 + 0x000004B0, //B1200 + 0x00000708, //B1800 + 0x00000960, //B2400 + 0x000012C0, //B4800 + 0x00002580, //B9600 + 0x00004B00, //B19200 + 0x00009600, //B38400 + 0x0000E100, //B57600 + 0x0001C200, //B115200 + 0x00038400, //B230400 + 0x00070800, //460800 + 0x000E1000, //921600 +}; + +/* init_hardware - called once the first time the driver is loaded */ +status_t init_hardware (void){ + TRACE("init_hardware\n"); /*special case - no file-logging activated now*/ + return B_OK; +} + +/* init_driver - optional function - called every time the driver + is loaded. */ +status_t init_driver (void){ + int i; + status_t status = B_OK; + load_setting(); + create_log(); + + TRACE_FUNCALLS("init_driver\n"); + + if((status = get_module(B_TTY_MODULE_NAME, (module_info **)&tty_m)) == B_OK){ + if((status = get_module(B_USB_MODULE_NAME, (module_info **)&usb_m)) == B_OK){ + if(tty_m && usb_m){ + for(i = 0; i < DEVICES_COUNT; i++) + usb_serial_devices[i] = 0; + + usb_serial_names[0] = NULL; + load_driver_symbols(DRIVER_NAME); + + (*usb_m->register_driver)(DRIVER_NAME, supported_devices, + SIZEOF(supported_devices), DRIVER_NAME); + (*usb_m->install_notify)(DRIVER_NAME, ¬ify_hooks); + + usb_serial_lock = create_sem(1, DRIVER_NAME"_devices_table_lock"); + }else{ + status = B_ERROR; + TRACE_ALWAYS("init_driver failed: tty_m:%08x usb_m:%08x", tty_m, usb_m); + } + }else + TRACE_ALWAYS("init_driver failed:%lx cannot get a module %s", status, + B_USB_MODULE_NAME); + }else + TRACE_ALWAYS("init_driver failed:%lx cannot get a module %s", status, + B_TTY_MODULE_NAME); + + TRACE_FUNCRET("init_driver returns:%08x\n", status); + return status; +} + +/* uninit_driver - optional function - called every time the driver + is unloaded */ +void uninit_driver (void){ + int i; + TRACE_FUNCALLS("uninit_driver\n"); + + (*usb_m->uninstall_notify)(DRIVER_NAME); + acquire_sem(usb_serial_lock); + + for(i = 0; i < DEVICES_COUNT; i++) + if(usb_serial_devices[i]){ + delete_area(usb_serial_devices[i]->buffers_area); + delete_sem(usb_serial_devices[i]->done_read); + delete_sem(usb_serial_devices[i]->done_write); + free(usb_serial_devices[i]); + usb_serial_devices[i] = 0; + } + + release_sem_etc(usb_serial_lock, 1, B_DO_NOT_RESCHEDULE); + delete_sem(usb_serial_lock); + + for(i = 0; usb_serial_names[i]; i++) + free(usb_serial_names[i]); + + put_module(B_USB_MODULE_NAME); + put_module(B_TTY_MODULE_NAME); +} + +void usb_serial_device_notify_in(void *cookie, + uint32 status, void *data, uint32 actual_len){ + TRACE_FUNCALLS("usb_serial_device_notify_in:cookie:%08x status:%08x data:%08x len:%d\n", cookie, status, data, actual_len); + if(cookie){ + usb_serial_device *usd = ((usb_serial_device_info *)cookie)->device; + usd->actual_len_read = actual_len; + usd->dev_status_read = status; + release_sem(usd->done_read); + } +} + +void usb_serial_device_notify_out(void *cookie, uint32 status, + void *data, uint32 actual_len){ + TRACE_FUNCALLS("usb_serial_device_notify_out:cookie:%08x status:%08x " + "data:%08x len:%d\n", cookie, status, data, actual_len); + if(cookie){ + usb_serial_device *usd = ((usb_serial_device_info *)cookie)->device; + usd->actual_len_write = actual_len; + usd->dev_status_write = status; + release_sem(usd->done_write); + } +} + +status_t usb_serial_device_thread(void *param){ + status_t status = B_ERROR; + usb_serial_device_info *usdi = (usb_serial_device_info *)param; + usb_serial_device *usd = usdi->device; + TRACE_FUNCALLS("usb_serial_device_thread:%08x\n", param); + + while(true){ + size_t i, to_read; + char *buf; + struct ddrover *ddr; + usd->actual_len_read = 0; + usd->dev_status_read = 0; + status = (*usb_m->queue_bulk)(usd->pipe_read, usd->read_buffer, + usd->read_buffer_size, usb_serial_device_notify_in, usdi); + if(status != B_OK){ + TRACE_ALWAYS("usb_serial_device_thread : queue_bulk error : %lx\n", status); + break; + } + + status = acquire_sem_etc(usd->done_read, 1, B_CAN_INTERRUPT, 0); + if(status != B_OK){ + TRACE_ALWAYS("usb_serial_device_thread : acquire_sem_etc : " + "error %08lx (%s)\n", status, strerror(status)); + break; + } + + if(usd->dev_status_read){ + TRACE_ALWAYS("usb_serial_device_thread : dev_status error !!!\n"); + break; + } + + buf = usd->read_buffer; + to_read = usd->actual_len_read; + (*usd->hw->on_read)(usd, &buf, &to_read); + + if(!to_read) + continue; + + ddr = (*tty_m->ddrstart)(NULL); + if(!ddr){ + TRACE_ALWAYS("usb_serial_device_thread : ddrstart problem !!!\n"); + status = B_NO_MEMORY; + break; + } + + (*tty_m->ttyilock)(usd->tty, ddr, true); + for(i = 0; i < to_read; i++){ + (*tty_m->ttyin)(usd->tty, ddr, buf[i]); + } + (*tty_m->ttyilock)(usd->tty, ddr, false); + (*tty_m->ddrdone)(ddr); + } + + TRACE_FUNCRET("usb_serial_device_thread returns %08x\n", status); + return status; +} + +void usb_serial_setmodes(usb_serial_device *usd){ + usb_serial_line_coding line_coding; + struct termios tios; + + int newctrl, baud_index; + TRACE_FUNCALLS("usb_serial_setmodes:%08x\n", usd); + + memcpy(&tios, &usd->tty->t, sizeof(struct termios)); + newctrl = usd->ctrlout; + + TRACE_FUNCRES(trace_termios, &tios); + TRACE("newctrl:%08x\n", newctrl); + + baud_index = tios.c_cflag & CBAUD; + if(baud_index > SIZEOF(serial_tty_speed)) + baud_index = SIZEOF(serial_tty_speed) - 1; + + line_coding.speed = serial_tty_speed[baud_index]; + line_coding.stopbits = ( tios.c_cflag & CSTOPB ) ? LC_STOP_BIT_2 : LC_STOP_BIT_1; + + if(PARENB & tios.c_cflag){ + line_coding.parity = LC_PARITY_EVEN; + + if(PARODD & tios.c_cflag){ + line_coding.parity = LC_PARITY_ODD; + } + }else + line_coding.parity = LC_PARITY_NONE; + + line_coding.databits = (tios.c_cflag & CS8) ? 8 : 7; + + if(line_coding.speed == 0){ + newctrl &= 0xfffffffe; + line_coding.speed = usd->line_coding.speed; + }else + newctrl = CLS_LINE_DTR; + + if(usd->ctrlout != newctrl ){ + usd->ctrlout = newctrl; + TRACE("newctrl send to modem:%08x\n", newctrl); + (*usd->hw->set_control_line_state)(usd, newctrl); + } + + if(memcmp (&line_coding, &usd->line_coding, sizeof(usb_serial_line_coding))){ + usd->line_coding.speed = line_coding.speed; + usd->line_coding.stopbits = line_coding.stopbits; + usd->line_coding.databits = line_coding.databits; + usd->line_coding.parity = line_coding.parity; + TRACE("send to modem:speed %d sb:%08x db:%08x parity:%08x\n", + usd->line_coding.speed, usd->line_coding.stopbits, + usd->line_coding.databits, usd->line_coding.parity); + (*usd->hw->set_line_coding)(usd, &usd->line_coding); + } +} + +bool usb_serial_service(struct tty *ptty, struct ddrover *ddr, uint flags){ + int i; + bool bret = false; + usb_serial_device *usd; + TRACE_FUNCALLS("usb_serial_service:%08x ddr:%08x flags:%08x\n", ptty, ddr, flags); + + for(i = 0; i < DEVICES_COUNT; i++){ + if(usb_serial_devices[i]){ + if(ptty == usb_serial_devices[i]->tty){ + usd = usb_serial_devices[i]; + break; + } + } + } + + if(usd){ + if(flags <= TTYGETSIGNALS){ + switch(flags){ + case TTYENABLE: + (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWDCD, false); + (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWCTS, true); + + usd->ctrlout = CLS_LINE_DTR | CLS_LINE_RTS; + (*usd->hw->set_control_line_state)(usd, usd->ctrlout); + break; + + case TTYDISABLE: + + (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWDCD, false); + + usd->ctrlout = 0x0; + (*usd->hw->set_control_line_state)(usd, usd->ctrlout); + break; + + case TTYISTOP: + (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWCTS, false); + break; + + case TTYIRESUME: + (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWCTS, true); + break; + + case TTYGETSIGNALS: + (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWDCD, true); + (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWCTS, true); + (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWDSR, false); + (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWRI, false); + break; + + case TTYSETMODES: + usb_serial_setmodes(usd); + break; + + case TTYOSTART: + case TTYOSYNC: + case TTYSETBREAK: + case TTYCLRBREAK: + case TTYSETDTR: + case TTYCLRDTR: + break; + } + } + bret = true; + } + + TRACE_FUNCRET("usb_serial_service returns %d\n", bret); + return bret; +} + +void usb_serial_notify_interrupt(void *cookie, uint32 status, + void *data, uint32 actual_len){ + TRACE_FUNCALLS("usb_serial_notify_interrupt : %p %lx %p %ld\n", + cookie, status, data, actual_len); + if(cookie){ + usb_serial_device *usd = ((usb_serial_device_info *)cookie)->device; + usd->actual_len_interrupt = actual_len; + usd->dev_status_interrupt = status; + } +} + +/* usb_serial_open - handle open() calls */ +static status_t usb_serial_open (const char *name, uint32 flags, void** cookie){ + int i; + status_t status = ENODEV; + TRACE_FUNCALLS("usb_serial_open:%s flags:%d cookie:%08x\n", + name, flags, cookie); + + for(i=0;i= 0 && i < DEVICES_COUNT){ + acquire_sem(usb_serial_lock); + if(usb_serial_devices[i]){ + usb_serial_device_info *usdi = malloc(sizeof(usb_serial_device_info)); + if(usdi){ + struct ddrover *ddr; + memset(usdi, 0, sizeof(usb_serial_device_info)); + *cookie = usdi; + + TRACE("cookie in open:%08x\n", *cookie); + + usdi->device = usb_serial_devices[i]; + + (*tty_m->ttyinit)(&usb_serial_tty[i], true); + + usdi->ttyfile.tty = &usb_serial_tty[i]; + usdi->ttyfile.flags = flags; + usb_serial_devices[i]->tty = &usb_serial_tty[i]; + + (*usdi->device->hw->reset_device)(usdi->device); + + TRACE("Opened:%s %08x\n", usdi->device->hw->descr, usdi->device->dev); + + ddr = (*tty_m->ddrstart)(NULL); + if(ddr){ + (*tty_m->ddacquire)(ddr, &usb_serial_dd); + status = (*tty_m->ttyopen)(&usdi->ttyfile, ddr, usb_serial_service); + (*tty_m->ddrdone)(ddr); + + if(status == B_OK){ + sem_id sem = spawn_kernel_thread(usb_serial_device_thread, + "usb_serial_device_thread", 0xa, usdi); + if(sem != -1) + resume_thread(sem); + else + TRACE_ALWAYS("usb_serial_open: cannot spawn kernel thread!!!\n"); + + usdi->device->ctrlout = CLS_LINE_DTR | CLS_LINE_RTS; + (*usdi->device->hw->set_control_line_state)(usdi->device, + usdi->device->ctrlout); + + status = (*usb_m->queue_interrupt)(usdi->device->pipe_control, + usdi->device->interrupt_buffer, + usdi->device->interrupt_buffer_size, + usb_serial_notify_interrupt, usdi); + } + }else + status = B_NO_MEMORY; + + if(status != B_OK) + free(usdi); + }else + status = B_NO_MEMORY; + } + release_sem(usb_serial_lock); + } + + TRACE_FUNCRET("usb_serial_open returns:%08x\n", status); + return status; +} + +/* usb_serial_read - handle read() calls */ +static status_t usb_serial_read (void* cookie, off_t position, + void *buf, size_t* num_bytes){ + status_t status = B_OK; + struct ddrover *ddr; + TRACE_FUNCALLS("usb_serial_read:%08x position:%Ld buf:%08x len:%d\n", + cookie, position, buf, *num_bytes); + + ddr = (*tty_m->ddrstart)(NULL); + if(ddr){ + if(cookie) + status = (*tty_m->ttyread)(cookie, ddr, buf, num_bytes); + else + (*tty_m->ddacquire)(ddr, &usb_serial_dd); + (*tty_m->ddrdone)(ddr); + }else{ + TRACE_ALWAYS("usb_serial_read : ddrstart problem !!!\n"); + status = B_NO_MEMORY; + } + + TRACE_FUNCRET("usb_serial_read returns:%08x readed:%d\n", status, *num_bytes); + return status; +} + +/* usb_serial_write - handle write() calls */ + +static status_t usb_serial_write (void* cookie, off_t position, + const void* buffer, size_t* num_bytes){ + status_t status = B_OK; + usb_serial_device_info *usdi = (usb_serial_device_info *)cookie; + usb_serial_device *usd = usdi->device; + size_t to_write = *num_bytes; + TRACE_FUNCALLS("usb_serial_write:%08x position:%Ld buf:%08x len:%d\n", + cookie, position, buffer, *num_bytes); + *num_bytes = 0; /* tell caller nothing was written */ + + while(to_write > 0){ + size_t len = to_write; + + (*usd->hw->on_write)(usd, buffer, &len); + + usd->actual_len_write = 0; + usd->dev_status_write = 0; + + status = (*usb_m->queue_bulk)(usd->pipe_write, usd->write_buffer, + len, usb_serial_device_notify_out, cookie); + if(status != B_OK){ + TRACE_ALWAYS("usb_serial_write : dev %p status %lx", cookie, status); + break; + } + + status = acquire_sem_etc(usd->done_write, 1, B_CAN_INTERRUPT, 0); + if(status != B_OK){ + TRACE_ALWAYS("usb_serial_write : acquire_sem_etc() %lx (%s)", + status, strerror(status)); + break; + } + + ((const char*)buffer) += usd->actual_len_write; + *num_bytes += usd->actual_len_write; + to_write -= usd->actual_len_write; + } + + TRACE_FUNCRET("usb_serial_write returns:%08x written:%d\n", status, *num_bytes); + return status; +} + +/* usb_serial_control - handle ioctl calls */ +static status_t usb_serial_control (void* cookie, uint32 op, void* arg, size_t len){ + status_t status = B_BAD_VALUE; + TRACE_FUNCALLS("usb_serial_control cookie:%08x op:%08x arg:%08x len:%d\n", + cookie, op, arg, len); + + if(cookie){ + struct ddrover *ddr = (*tty_m->ddrstart)(NULL); + if(ddr){ + status = (*tty_m->ttycontrol)(cookie, ddr, op, arg, len); + (*tty_m->ddrdone)(ddr); + }else + status = B_NO_MEMORY; + }else + status = ENODEV; + + TRACE_FUNCRET("usb_serial_control returns:%08x\n", status); + return status; +} + +/* usb_serial_close - handle close() calls */ +static status_t usb_serial_close (void* cookie){ + status_t status = ENODEV; + TRACE_FUNCALLS("usb_serial_close:%08x\n", cookie); + + if(cookie){ + usb_serial_device_info *usdi = (usb_serial_device_info *)cookie; + usb_serial_device *usd = usdi->device; + struct ddrover *ddr; + + (*usd->hw->on_close)(usd); + + ddr = (*tty_m->ddrstart)(NULL); + if(ddr){ + status = (*tty_m->ttyclose)(cookie, ddr); + (*tty_m->ddrdone)(ddr); + }else + status = B_NO_MEMORY; + } + + TRACE_FUNCRET("usb_serial_close returns:%08x\n", status); + return status; +} + +/* usb_serial_free - called after the last device is closed, and after + all i/o is complete.*/ +static status_t usb_serial_free (void* cookie){ + status_t status = B_OK; + TRACE_FUNCALLS("usb_serial_free:%08x\n", cookie); + + if(cookie){ + struct ddrover *ddr = (*tty_m->ddrstart)(NULL); + if(ddr){ + status = (*tty_m->ttyfree)(cookie, ddr); + (*tty_m->ddrdone)(ddr); + }else + status = B_NO_MEMORY; + free(cookie); + } + + TRACE_FUNCRET("usb_serial_free returns:%08x\n", status); + return status; +} + +/* publish_devices - return a null-terminated array of devices + supported by this driver. */ +const char** publish_devices(){ + int i, j; + TRACE_FUNCALLS("publish_devices\n"); + + for(i=0; usb_serial_names[i]; i++) + free(usb_serial_names[i]); + + acquire_sem(usb_serial_lock); + for(i=0, j=0; i < DEVICES_COUNT; i++){ + if(usb_serial_devices[i]){ + usb_serial_names[j] = malloc(strlen(basename + 2)); + if(usb_serial_names[j]){ + sprintf(usb_serial_names[j], basename, i); + j++; + } + else + TRACE_ALWAYS("publish_devices - NO MEMORY\n"); + } + } + usb_serial_names[j] = NULL; + release_sem(usb_serial_lock); + + return (const char **)&usb_serial_names[0]; +} + +/* find_device - return ptr to device hooks structure for a + given device name */ +device_hooks* find_device(const char* name){ + TRACE_FUNCALLS("find_device(%s)\n", name); + return &usb_serial_hooks; +} + +status_t add_device(usb_serial_device *usd, const usb_configuration_info *uci, + usb_endpoint_info *comm_epi, + usb_endpoint_info *data_out_epi, + usb_endpoint_info *data_in_epi){ + char name[32]; + status_t status = ENODEV; + size_t buf_len; + int i = 0; + + TRACE_FUNCALLS("add_device(%08x, %08x, %08x, %08x, %08x)\n", + usd, uci, comm_epi, data_in_epi, data_out_epi); + + acquire_sem(usb_serial_lock); + + for(i = 0; i < DEVICES_COUNT; i++){ + if(usb_serial_devices[i] != NULL) + continue; + + usb_serial_devices[i] = usd; + + usd->active = 1; + usd->open = 0; + + sprintf(name, "usb_serial:%d:done_read", i ); + usd->done_read = create_sem(0, name); + + sprintf(name, "usb_serial:%d:done_write", i); + usd->done_write = create_sem(0, name); + + usd->tty = NULL; + + buf_len = usd->read_buffer_size + usd->write_buffer_size + + usd->interrupt_buffer_size; + + usd->buffers_area = create_area("usb_serial:buffers_area", + (void *)&usd->read_buffer, + B_ANY_KERNEL_ADDRESS, + ROUNDUP(buf_len, B_PAGE_SIZE), + B_CONTIGUOUS, B_READ_AREA|B_WRITE_AREA); + + usd->write_buffer = usd->read_buffer + usd->read_buffer_size; + usd->interrupt_buffer = usd->write_buffer + usd->write_buffer_size; + + (*usb_m->set_configuration)(usd->dev, uci); + + usd->pipe_control = (comm_epi) ? comm_epi->handle : 0; + usd->pipe_write = data_out_epi->handle; + usd->pipe_read = data_in_epi->handle; + + status = B_OK; + break; + } + + release_sem(usb_serial_lock); + + TRACE_FUNCRET("add_device returns:%08x\n", status); + return status; +} + + +status_t usb_serial_device_added(const usb_device *dev, void **cookie){ + int i; + status_t status = B_OK; + const usb_device_descriptor *udd; + usb_serial_device *usd = 0; + TRACE_FUNCALLS("usb_serial_device_added:%08x cookie:%08x\n", dev, cookie); + + udd = (*usb_m->get_device_descriptor)(dev); + + TRACE_ALWAYS("Probing device: %08x/%08x\n", udd->vendor_id, udd->product_id); + + *cookie = 0; + for(i=1; i < sizeof(usb_serial_hw_devices)/sizeof(usb_serial_hw_devices[0]); i++) + if(usb_serial_hw_devices[i].vendor_id == udd->vendor_id + && usb_serial_hw_devices[i].product_id == udd->product_id){ + const usb_configuration_info *uci; + uci = (*usb_m->get_nth_configuration)(dev, 0); + if(uci){ + usd = malloc(sizeof(usb_serial_device)); + if(usd){ + usd->dev = dev; + usd->hw = &usb_serial_hw_devices[i]; + usd->read_buffer_size = + usd->write_buffer_size = + usd->interrupt_buffer_size = ROUNDUP(DEF_BUFFER_SIZE, 16); + if((status = (*usb_serial_hw_devices[i].add_device)(usd, uci)) == B_OK){ + *cookie = dev; + TRACE_ALWAYS("%s (%04x/%04x) added \n", + usb_serial_hw_devices[i].descr, + usb_serial_hw_devices[i].vendor_id, + usb_serial_hw_devices[i].product_id); + }else + free(usd); + }else + status = B_NO_MEMORY; + } + break; + } + + if(!*cookie){ + if(b_acm_support && + udd->device_class == USB_DEV_CLASS_COMM && + udd->device_subclass == 0 && + udd->device_protocol == 0 ){ + const usb_configuration_info *uci; + uint16 idx = 0; + do{ + uci = (*usb_m->get_nth_configuration)(dev, idx++); + if(uci){ + if(uci->interface_count != 2) + continue; + usd = malloc(sizeof(usb_serial_device)); + if(usd){ + usd->dev = dev; + usd->hw = &usb_serial_hw_devices[0]; + usd->read_buffer_size = + usd->write_buffer_size = + usd->interrupt_buffer_size = ROUNDUP(DEF_BUFFER_SIZE, 16); + if((status = (*usb_serial_hw_devices[0].add_device)(usd, uci)) == B_OK){ + *cookie = dev; + TRACE_ALWAYS("%s (%04x/%04x) added \n", + usb_serial_hw_devices[0].descr, + udd->vendor_id, udd->product_id); + }else + free(usd); + }else + status = B_NO_MEMORY; + } + }while(uci); + }else{ + TRACE_ALWAYS("device has wrong class, subclass and protocol\n"); + status = B_ERROR; + } + } + TRACE_FUNCRET("usb_serial_device_added returns:%08x\n", status); + return status; +} + +status_t usb_serial_device_removed(void *cookie){ + int i; + status_t status = B_OK; + usb_device *ud = (usb_device *) cookie; + TRACE_FUNCALLS("usb_serial_device_removed:%08x\n", cookie); + + acquire_sem(usb_serial_lock); + + for(i = 0; i < DEVICES_COUNT; i++ ){ + usb_serial_device *usd = usb_serial_devices[i]; + if(usd){ + if(ud == usd->dev){ + usd->active = 0; + if(!usd->open) + break; + + delete_area(usd->buffers_area); + delete_sem(usd->done_read); + delete_sem(usd->done_write); + free(usd); + usb_serial_devices[i] = 0; + } + } + } + + release_sem(usb_serial_lock); + + TRACE_FUNCRET("usb_serial_device_removed returns:%08x\n", status); + return status; +} + diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/driver.h b/src/add-ons/kernel/drivers/ports/usb_serial/driver.h new file mode 100644 index 0000000000..885fd642cf --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/driver.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + * + */ + +#ifndef _USB_SERIAL_DRIVER_H_ + #define _USB_SERIAL_DRIVER_H_ + +/* The name of this driver ... */ +#define DRIVER_NAME "usb_serial" +/* Maximal count of devices supported by this driver at the same time. */ +#define DEVICES_COUNT 20 + +#include "tracing.h" + +/* Some usefull helper defines ... */ +#define SIZEOF(array) (sizeof(array)/sizeof(array[0])) /* size of array */ +/* This one rounds the size to integral count of segs (segments) */ +#define ROUNDUP(size, seg) (((size) + (seg) - 1) & ~((seg) - 1)) +/* buffer size */ +#define DEF_BUFFER_SIZE 0x100 + +/* line coding defines ... Come from CDC USB specs? */ +#define LC_STOP_BIT_1 0 +#define LC_STOP_BIT_2 2 + +#define LC_PARITY_NONE 0 +#define LC_PARITY_ODD 1 +#define LC_PARITY_EVEN 2 +/* struct that represents line coding */ +typedef struct _s_usb_serial_line_coding{ + uint32 speed; + uint8 stopbits; + uint8 parity; + uint8 databits; +} usb_serial_line_coding; + +/* "forgotten" requests for CDC ACM devices */ +#define SET_LINE_CODING 0x20 +#define SET_CONTROL_LINE_STATE 0x22 + +/* control line states */ +#define CLS_LINE_DTR 0x0001 +#define CLS_LINE_RTS 0x0002 + +/* "forgotten" attributes etc ...*/ +#define USB_EP_ADDR_DIR_IN 0x80 +#define USB_EP_ADDR_DIR_OUT 0x00 + +#define USB_EP_ATTR_CONTROL 0x00 +#define USB_EP_ATTR_ISOCHRONOUS 0x01 +#define USB_EP_ATTR_BULK 0x02 +#define USB_EP_ATTR_INTERRUPT 0x03 +/* USB class - communication devices */ +#define USB_DEV_CLASS_COMM 0x02 + +#define USB_INT_CLASS_CDC 0x02 +#define USB_INT_SUBCLASS_ABSTRACT_CONTROL_MODEL 0x02 + +#define USB_INT_CLASS_CDC_DATA 0x0a +#define USB_INT_SUBCLASS_DATA 0x00 + +/* a kind of forward declaration */ +typedef struct _s_usb_serial_device usb_serial_device; + +/* usb_serial_hw - represents the different hardware devices */ +typedef struct _s_usb_serial_hw{ + uint16 vendor_id; /* vendor id and card id of device */ + uint16 product_id; + /* callbacks used in "customization" of the driver behaviour */ + status_t (*add_device)(usb_serial_device *usd, + const usb_configuration_info *uci); + status_t (*reset_device)(usb_serial_device *usd); + status_t (*set_line_coding)(usb_serial_device *usd, + usb_serial_line_coding *line_coding); + status_t (*set_control_line_state)(usb_serial_device *usd, uint16 state); + void (*on_read)(usb_serial_device *usd, char **buf, size_t *num_bytes); + void (*on_write)(usb_serial_device *usd, const char *buf, + size_t *num_bytes); + void (*on_close)(usb_serial_device *usd); + const char *descr; /* informational description */ +}usb_serial_hw; + +status_t add_device(usb_serial_device *usd, const usb_configuration_info *uci, + usb_endpoint_info *comm_epi, + usb_endpoint_info *data_out_epi, + usb_endpoint_info *data_in_epi); + +/* this one was typedefed into usb_serial_device - see above for details + this struct represents the main device object */ +struct _s_usb_serial_device{ + int active; /* is device active - performing some tasks */ + int32 open; /* is device opened */ + const usb_device *dev; /* points to usb device handle */ + /* communication pipes */ + usb_pipe *pipe_control; + usb_pipe *pipe_read; + usb_pipe *pipe_write; + /* line coding */ + usb_serial_line_coding line_coding; + + /* data buffers */ + area_id buffers_area; + /* read buffer */ + char *read_buffer; + size_t read_buffer_size; + /* write buffer */ + char *write_buffer; + size_t write_buffer_size; + /* interrupt buffer */ + char *interrupt_buffer; + size_t interrupt_buffer_size; + + /* variables used in callback functionality */ + size_t actual_len_read; + uint32 dev_status_read; + size_t actual_len_write; + uint32 dev_status_write; + size_t actual_len_interrupt; + uint32 dev_status_interrupt; + /* semaphores used in callbacks */ + sem_id done_read; + sem_id done_write; + + uint16 ctrlout; + + struct tty *tty; + + usb_serial_hw *hw; /* points to corresponding hardware description */ + /* place for device specific data */ + union{ + struct _spec_acm{ /* ACM-compatible devices */ + }acm; + struct _spec_prolific{ /* Prolific devices*/ + }prolific; + struct _spec_ftdi{ /* FTDI devices*/ + uint8 hdrlen; + uint8 status_msr; + uint8 status_lsr; + }ftdi; + }spec; +}; /*already typedef-ed - see comment above! */ +/* high-level of abstraction of the device*/ +typedef struct _s_usb_serial_device_info{ + struct ttyfile ttyfile; /* */ + usb_serial_device *device; /* */ +}usb_serial_device_info; + +extern usb_serial_device *usb_serial_devices[]; +extern char * usb_serial_names[]; +extern usb_module_info *usb_m; + +#endif//_USB_SERIAL_DRIVER_H_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.c b/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.c new file mode 100644 index 0000000000..7bcfc3deee --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + * + */ + +#include +#include +#include +#include +#include + +#include "driver.h" +#include "ftdi.h" +#include "uftdireg.h" + + +status_t add_ftdi_device(usb_serial_device *usd, + const usb_configuration_info *uci) +{ + struct usb_endpoint_info *comm_epi = NULL; + struct usb_endpoint_info *data_out_epi = NULL; + struct usb_endpoint_info *data_in_epi = NULL; + status_t status = ENODEV; + int i = 0; + + TRACE_FUNCALLS("> add_ftdi_device(%08x, %08x)\n", usd, uci); + + if(uci->interface_count){ + struct usb_interface_info *uii = uci->interface[0].active; + for(i = 0; i < uii->endpoint_count; i++){ + if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_BULK){ + if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN) + == USB_EP_ADDR_DIR_IN){ + data_in_epi = &uii->endpoint[i]; + }else{ + if(uii->endpoint[i].descr->endpoint_address + /*USB_EP_ADDR_DIR_OUT = 0x0*/){ + comm_epi = data_out_epi = &uii->endpoint[i]; + } + } + } + } + + if(comm_epi && data_in_epi && data_out_epi){ + if(usd->hw->product_id == PROD_8U100AX) + usd->spec.ftdi.hdrlen = 1; + else + usd->spec.ftdi.hdrlen = 0; + + usd->read_buffer_size = + usd->write_buffer_size = + usd->interrupt_buffer_size = ROUNDUP(FTDI_BUF_SIZE, 16); + status = add_device(usd, uci, comm_epi, data_out_epi, data_in_epi); + } + } + + TRACE_FUNCRET("< add_ftdi_device returns:%08x\n", status); + return status; +} + +status_t reset_ftdi_device(usb_serial_device *usd){ + status_t status = B_OK; + size_t len = 0; + TRACE_FUNCALLS("> reset_ftdi_device(%08x)\n", usd); + status = (*usb_m->send_request)(usd->dev, + USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, + FTDI_SIO_RESET, FTDI_SIO_RESET_SIO, + FTDI_PIT_DEFAULT, 0, 0, 0, &len); + TRACE_FUNCRET("< reset_ftdi_device returns:%08x\n", status); + return status; +} + +status_t set_line_coding_ftdi(usb_serial_device *usd, + usb_serial_line_coding *line_coding){ + status_t status = B_OK; + int32 rate, data = 0; + size_t len1 = 0, len2 = 0; + TRACE_FUNCALLS("> set_line_coding_ftdi(%08x, {%d, %02x, %02x, %02x})\n", + usd, line_coding->speed, + line_coding->stopbits, + line_coding->parity, + line_coding->databits); + + if(usd->hw->product_id == PROD_8U100AX){ + switch (line_coding->speed){ + case 300: rate = ftdi_sio_b300; break; + case 600: rate = ftdi_sio_b600; break; + case 1200: rate = ftdi_sio_b1200; break; + case 2400: rate = ftdi_sio_b2400; break; + case 4800: rate = ftdi_sio_b4800; break; + case 9600: rate = ftdi_sio_b9600; break; + case 19200: rate = ftdi_sio_b19200; break; + case 38400: rate = ftdi_sio_b38400; break; + case 57600: rate = ftdi_sio_b57600; break; + case 115200: rate = ftdi_sio_b115200; break; + default: + rate = ftdi_sio_b19200; + TRACE_ALWAYS("= set_line_coding_ftdi: Datarate:%d is not supported " + "by this hardware. Defaulted to %d\n", + line_coding->speed, rate); + break; + } + }else{ + switch(line_coding->speed){ + case 300: rate = ftdi_8u232am_b300; break; + case 600: rate = ftdi_8u232am_b600; break; + case 1200: rate = ftdi_8u232am_b1200; break; + case 2400: rate = ftdi_8u232am_b2400; break; + case 4800: rate = ftdi_8u232am_b4800; break; + case 9600: rate = ftdi_8u232am_b9600; break; + case 19200: rate = ftdi_8u232am_b19200; break; + case 38400: rate = ftdi_8u232am_b38400; break; + case 57600: rate = ftdi_8u232am_b57600; break; + case 115200: rate = ftdi_8u232am_b115200; break; + case 230400: rate = ftdi_8u232am_b230400; break; + case 460800: rate = ftdi_8u232am_b460800; break; + case 921600: rate = ftdi_8u232am_b921600; break; + default: + rate = ftdi_sio_b19200; + TRACE_ALWAYS("= set_line_coding_ftdi: Datarate:%d is not supported " + "by this hardware. Defaulted to %d\n", + line_coding->speed, rate); + break; + } + } + + status = (*usb_m->send_request)(usd->dev, + USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, + FTDI_SIO_SET_BAUD_RATE, rate, + FTDI_PIT_DEFAULT, 0, 0, 0, &len1); + if(status != B_OK) + TRACE_ALWAYS("= set_line_coding_ftdi: datarate set request failed:%08x", + status); + + switch(line_coding->stopbits){ + case LC_STOP_BIT_2: data = FTDI_SIO_SET_DATA_STOP_BITS_2; break; + case LC_STOP_BIT_1: data = FTDI_SIO_SET_DATA_STOP_BITS_1; break; + default: + TRACE_ALWAYS("= set_line_coding_ftdi: Wrong stopbits param:%d", + line_coding->stopbits); + break; + } + + switch(line_coding->parity){ + case LC_PARITY_NONE: data |= FTDI_SIO_SET_DATA_PARITY_NONE; break; + case LC_PARITY_EVEN: data |= FTDI_SIO_SET_DATA_PARITY_EVEN; break; + case LC_PARITY_ODD: data |= FTDI_SIO_SET_DATA_PARITY_ODD; break; + default: + TRACE_ALWAYS("= set_line_coding_ftdi: Wrong parity param:%d", + line_coding->parity); + break; + } + + switch(line_coding->databits){ + case 8: data |= FTDI_SIO_SET_DATA_BITS(8); break; + case 7: data |= FTDI_SIO_SET_DATA_BITS(7); break; + default: + TRACE_ALWAYS("= set_line_coding_ftdi: Wrong databits param:%d", + line_coding->databits); + break; + } + + status = (*usb_m->send_request)(usd->dev, + USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, + FTDI_SIO_SET_DATA, data, + FTDI_PIT_DEFAULT, 0, 0, 0, &len2); + if(status != B_OK) + TRACE_ALWAYS("= set_line_coding_ftdi: data set request failed:%08x", + status); + + TRACE_FUNCRET("< set_line_coding_ftdi returns:%08x\n", status); + return status; +} + +status_t set_control_line_state_ftdi(usb_serial_device *usd, uint16 state){ + status_t status = B_OK; + int32 ctrl; + size_t len = 0; + TRACE_FUNCALLS("> set_control_line_state_ftdi(%08x, %04x)\n", usd, state); + + ctrl = (state & CLS_LINE_RTS) ? + FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW; + ctrl |= (state & CLS_LINE_DTR) ? + FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW; + status = (*usb_m->send_request)(usd->dev, + USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, + FTDI_SIO_MODEM_CTRL, ctrl, + FTDI_PIT_DEFAULT, 0, 0, 0, &len); + if(status != B_OK) + TRACE_ALWAYS("= set_control_line_state_ftdi: control set request " + "failed:%08x", status); + + TRACE_FUNCRET("< set_control_line_state_ftdi returns:%08x\n", status); + return status; +} + +void on_read_ftdi(usb_serial_device *usd, char **buf, size_t *num_bytes){ + usd->spec.ftdi.status_msr = FTDI_GET_MSR(*buf); + usd->spec.ftdi.status_lsr = FTDI_GET_LSR(*buf); + TRACE("MSR:%02x LSR:%02x\n", usd->spec.ftdi.status_msr, + usd->spec.ftdi.status_lsr); + *buf += 2; + *num_bytes -= 2; +} + +void on_write_ftdi(usb_serial_device *usd, const char *buf, + size_t *num_bytes){ + char *buf_to = usd->write_buffer; + int hdrlen = usd->spec.ftdi.hdrlen; + TRACE("hdrlen:%d\n", hdrlen); + if(*num_bytes > usd->write_buffer_size - hdrlen) + *num_bytes = usd->write_buffer_size - hdrlen; + if(hdrlen > 0) + *buf_to = FTDI_OUT_TAG(*num_bytes, FTDI_PIT_DEFAULT); + memcpy(buf_to + hdrlen, buf, *num_bytes); + *num_bytes += hdrlen; +} + +void on_close_ftdi(usb_serial_device *usd){ + TRACE_FUNCALLS("> on_close_ftdi(%08x)\n", usd); + (*usb_m->cancel_queued_transfers)(usd->pipe_read); + (*usb_m->cancel_queued_transfers)(usd->pipe_write); +} + diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.h b/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.h new file mode 100644 index 0000000000..5f80bb1c48 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + * + */ + +#ifndef _USB_FTDI_H_ + #define _USB_FTDI_H_ + +#define VND_FTDI 0x0403 + +#define PROD_8U100AX 0x8372 +#define PROD_8U232AM 0x6001 + +#define FTDI_BUF_SIZE 0x40 + +status_t add_ftdi_device(usb_serial_device *usd, + const usb_configuration_info *uci); +status_t reset_ftdi_device(usb_serial_device *usd); +status_t set_line_coding_ftdi(usb_serial_device *usd, + usb_serial_line_coding *line_coding); +status_t set_control_line_state_ftdi(usb_serial_device *usd, uint16 state); +void on_read_ftdi(usb_serial_device *usd, char **buf, size_t *num_bytes); +void on_write_ftdi(usb_serial_device *usd, const char *buf, size_t *num_bytes); +void on_close_ftdi(usb_serial_device *usd); + +#endif //_USB_FTDI_H_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/install.sh b/src/add-ons/kernel/drivers/ports/usb_serial/install.sh new file mode 100755 index 0000000000..b373eba71c --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/install.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +DRIVER_TITLE="USB Serial" +DRIVER_NAME=usb_serial + +answer=`alert "Do you really want to install the $DRIVER_TITLE driver?" "No" "Yes"` +if [ $answer == "No" ]; then + exit +fi + +/boot/beos/bin/install -d ~/config/add-ons/kernel/drivers/bin/ +/boot/beos/bin/install -d ~/config/settings/kernel/drivers/ +/boot/beos/bin/install -d ~/config/add-ons/kernel/drivers/dev/ports/ +/boot/beos/bin/install `dirname $0`/$DRIVER_NAME ~/config/add-ons/kernel/drivers/bin/ +/boot/beos/bin/cp `dirname $0`/$DRIVER_NAME.settings.sample ~/config/settings/kernel/drivers/$DRIVER_NAME + +mimeset ~/config/add-ons/kernel/drivers/bin/$DRIVER_NAME +mimeset ~/config/settings/kernel/drivers/$DRIVER_NAME + +ln -sf ../../bin/$DRIVER_NAME ~/config/add-ons/kernel/drivers/dev/ports/$DRIVER_NAME + +rescan $DRIVER_NAME + +alert "The $DRIVER_TITLE driver has been installed in your system." diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/prolific.c b/src/add-ons/kernel/drivers/ports/usb_serial/prolific.c new file mode 100644 index 0000000000..823963d164 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/prolific.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + * + */ + +#include +#include +#include +#include + +#include "driver.h" +#include "prolific.h" + +status_t add_prolific_device(usb_serial_device *usd, + const usb_configuration_info *uci) +{ + struct usb_endpoint_info *comm_epi = NULL; + struct usb_endpoint_info *data_out_epi = NULL; + struct usb_endpoint_info *data_in_epi = NULL; + status_t status = ENODEV; + int i = 0; + + TRACE_FUNCALLS("> add_prolific_device(%08x, %08x)\n", usd, uci); + + if(uci->interface_count){ + struct usb_interface_info *uii = uci->interface[0].active; + for(i = 0; i < uii->endpoint_count; i++){ + if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_INTERRUPT){ + if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN) + == USB_EP_ADDR_DIR_IN) /*USB_EP_ADDR_DIR_OUT = 0x0*/ + comm_epi = &uii->endpoint[i]; + } + } + /*They say that USB-RSAQ1 has 2 interfaces */ + if(uci->interface_count == 2){ + uii = uci->interface[1].active; + } + + for(i = 0; i < uii->endpoint_count; i++){ + if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_BULK){ + if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN) + == USB_EP_ADDR_DIR_IN){ + data_in_epi = &uii->endpoint[i]; + }else{ + if(uii->endpoint[i].descr->endpoint_address + /*USB_EP_ADDR_DIR_OUT = 0x0*/){ + data_out_epi = &uii->endpoint[i]; + } + } + } + } + + if(comm_epi && data_in_epi && data_out_epi){ + usd->read_buffer_size = + usd->write_buffer_size = + usd->interrupt_buffer_size = ROUNDUP(PROLIFIC_BUF_SIZE, 16); + status = add_device(usd, uci, comm_epi, data_out_epi, data_in_epi); + } + } + + TRACE_FUNCRET("< add_prolific_device returns:%08x\n", status); + return status; +} + +status_t reset_prolific_device(usb_serial_device *usd){ + status_t status; + size_t len = 0; + TRACE_FUNCALLS("> reset_prolific_device(%08x)\n", usd); + status = (*usb_m->send_request)(usd->dev, + USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, + PROLIFIC_SET_REQUEST, 0, 0, 0, 0, 0, &len); + TRACE_FUNCRET("< reset_prolific_device returns:%08x\n", status); + return status; +} diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/prolific.h b/src/add-ons/kernel/drivers/ports/usb_serial/prolific.h new file mode 100644 index 0000000000..10e86ab193 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/prolific.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2003-2004 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + * + */ + +#ifndef _USB_PROLIFIC_H_ + #define _USB_PROLIFIC_H_ + +#define VND_PROLIFIC 0x067b +#define VND_IODATA 0x04bb +#define VND_ATEN 0x0557 +#define VND_TDK 0x04bf +#define VND_RATOC 0x0584 +#define VND_ELECOM 0x056e +#define VND_SOURCENEXT 0x0833 +#define VND_HAL 0x0b41 + +#define PROD_IODATA_USBRSAQ 0x0a03 +#define PROD_PROLIFIC_RSAQ2 0x04bb +#define PROD_ATEN_UC232A 0x2008 +#define PROD_PROLIFIC_PL2303 0x2303 +#define PROD_TDK_UHA6400 0x0117 +#define PROD_RATOC_REXUSB60 0xb000 +#define PROD_ELECOM_UCSGT 0x5003 +#define PROD_SOURCENEXT_KEIKAI8 0x039f +#define PROD_SOURCENEXT_KEIKAI8_CHG 0x012e +#define PROD_HAL_IMR001 0x0011 + +// dobavit?!!!!!!!!!!!!! +// { 0, 0, 0, 0x0eba, 0x1080 }, // ITEGNO +// { 0, 0, 0, 0x0df7, 0x2620 } // MA620 + +#define PROLIFIC_SET_REQUEST 0x01 + +#define PROLIFIC_BUF_SIZE 0x100 + +status_t add_prolific_device(usb_serial_device *usd, + const usb_configuration_info *uci); +status_t reset_prolific_device(usb_serial_device *usd); + +#endif //_USB_PROLIFIC_H_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/tracing.c b/src/add-ons/kernel/drivers/ports/usb_serial/tracing.c new file mode 100644 index 0000000000..33075b1a3c --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/tracing.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + * + */ + +#include +#include +#include + +#include //sprintf +#include //posix file i/o - create, write, close +#include + + +#include "driver.h" +//#include "dano_hack.h" + +#if DEBUG +bool b_log = true; +#else +bool b_log = false; +#endif +bool b_log_file = false; +bool b_log_append = false; +bool b_log_funcalls = false; +bool b_log_funcret = false; +bool b_log_funcres = false; +bool b_acm_support = true; + +static const char *private_log_path="/boot/home/"DRIVER_NAME".log"; +static sem_id loglock; + +void load_setting(){ + void *settingshandle; + settingshandle = load_driver_settings(DRIVER_NAME); +#if !DEBUG + b_log = get_driver_boolean_parameter( + settingshandle, "debug_output", b_log, true); +#endif + b_log_file = get_driver_boolean_parameter( + settingshandle, "debug_output_in_file", b_log_file, true); + b_log_append = ! get_driver_boolean_parameter( + settingshandle, "debug_output_file_rewrite", !b_log_append, true); + b_log_funcalls = get_driver_boolean_parameter( + settingshandle, "debug_trace_func_calls", b_log_funcalls, false); + b_log_funcret = get_driver_boolean_parameter( + settingshandle, "debug_trace_func_returns", b_log_funcret, false); + b_log_funcres = get_driver_boolean_parameter( + settingshandle, "debug_trace_func_results", b_log_funcres, false); + b_acm_support = get_driver_boolean_parameter( + settingshandle, "support_acm_devices", b_acm_support, true); + + unload_driver_settings(settingshandle); +} + +void create_log(){ + int flags = O_WRONLY | O_CREAT | ((!b_log_append) ? O_TRUNC : 0); + if(!b_log_file) + return; + close(open(private_log_path, flags, 0666)); + loglock = create_sem(1, DRIVER_NAME"-logging"); +} + +void usb_serial_trace(bool b_force, char *fmt, ...){ + if(!(b_force || b_log)) + return; + { + va_list arg_list; + static char *prefix = "\33[32m"DRIVER_NAME":\33[0m"; + static char buf[1024]; + char *buf_ptr = buf; + if(!b_log_file){ + strcpy(buf, prefix); + buf_ptr += strlen(prefix); + } + + va_start(arg_list, fmt); + vsprintf(buf_ptr, fmt, arg_list); + va_end(arg_list); + + if(b_log_file){ + int fd; + acquire_sem(loglock); + fd = open(private_log_path, O_WRONLY | O_APPEND); + write(fd, buf, strlen(buf)); + close(fd); + release_sem(loglock); + } + else + dprintf(buf); + } +} + +void trace_ddomain(struct ddomain *dd){ + TRACE("struct ddomain\n" + " ddrover: %08x\n" + " bg:%d, locked:%d\n", dd->r, dd->bg, dd->locked); +} + +void trace_termios(struct termios *tios){ + TRACE("struct termios\n" + " c_iflag:%08x\n" + " c_oflag:%08x\n" + " c_cflag:%08x\n" + " c_lflag:%08x\n" + " c_line: %08x\n" + " c_ixxxxx:%08x\n" + " c_oxxxxx:%08x\n" + " c_cc [%02x, %02x, %02x, %02x, %02x, %02x, " + "%02x, %02x, %02x, %02x, %02x]\n", + tios->c_iflag, tios->c_oflag, tios->c_cflag, tios->c_lflag, + tios->c_line, tios->c_ixxxxx, tios->c_oxxxxx, + tios->c_cc[0], tios->c_cc[1], tios->c_cc[2], tios->c_cc[3], + tios->c_cc[4], tios->c_cc[5], tios->c_cc[6], tios->c_cc[7], + tios->c_cc[8], tios->c_cc[9], tios->c_cc[10]); +} + +void trace_str(struct str *str){ + TRACE("struct str\n" + " buffer:%08x\n" + " bufsize:%d\n" + " count:%d\n" + " tail:%d\n" + " allocated: %d\n", + str->buffer, + str->bufsize, str->count, str->tail, + str->allocated); +} + +void trace_winsize(struct winsize *ws){ + TRACE("struct winsize\n" + " ws_row:%d\n" + " ws_col:%d\n" + " ws_xpixel:%d\n" + " ws_ypixel:%d\n", + ws->ws_row, ws->ws_col, ws->ws_xpixel, ws->ws_ypixel); +} + +void trace_tty(struct tty *tty){ + TRACE("\n>> STRUCT tty\n" + " nopen:%d, flags:%08x,\n", + tty->nopen, tty->flags); + + TRACE("\n ddomain dd:\n"); + trace_ddomain(&tty->dd); + TRACE("\n ddomain ddi:\n"); + trace_ddomain(&tty->ddi); + + TRACE(" pgid: %08x\n", tty->pgid); + + TRACE("\n termios t:"); + trace_termios(&tty->t); + + TRACE(" iactivity: %d, ibusy:%d\n", tty->iactivity, tty->ibusy); + + TRACE("\n str istr:\n"); + trace_str(&tty->istr); + TRACE("\n str rstr:\n"); + trace_str(&tty->rstr); + TRACE("\n str ostr:\n"); + trace_str(&tty->ostr); + + TRACE("\n winsize wsize:\n"); + trace_winsize(&tty->wsize); + + TRACE(" service: %08x\n", tty->service); + TRACE("\n<< STRUCT tty\n"); +} diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/tracing.h b/src/add-ons/kernel/drivers/ports/usb_serial/tracing.h new file mode 100644 index 0000000000..e15ab9ee67 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/tracing.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + * + */ + +#ifndef _USB_SERIAL_TRACING_H_ + #define _USB_SERIAL_TRACING_H_ + +void load_setting(); +void create_log(); +void usb_serial_trace(bool b_force, char *fmt, ...); + +#define TRACE_ALWAYS(x...) usb_serial_trace(true, x); +#define TRACE(x...) usb_serial_trace(false, x); + +extern bool b_log_funcalls; +#define TRACE_FUNCALLS(x...)\ + { if(b_log_funcalls) usb_serial_trace(false, x);} + +extern bool b_log_funcret; +#define TRACE_FUNCRET(x...)\ + { if(b_log_funcret) usb_serial_trace(false, x);} + +extern bool b_log_funcres; +#define TRACE_FUNCRES(func, param)\ + { if(b_log_funcres) func(param);} + +void trace_ddomain(struct ddomain *dd); +void trace_termios(struct termios *tios); +void trace_str(struct str *str); +void trace_winsize(struct winsize *ws); +void trace_tty(struct tty *tty); + +extern bool b_acm_support; + +#endif//_USB_SERIAL_TRACING_H_ diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/uftdireg.h b/src/add-ons/kernel/drivers/ports/usb_serial/uftdireg.h new file mode 100644 index 0000000000..04586e8030 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/uftdireg.h @@ -0,0 +1,358 @@ +/* $NetBSD: uftdireg.h,v 1.6 2002/07/11 21:14:28 augustss Exp $ */ +/* $FreeBSD: src/sys/dev/usb/uftdireg.h,v 1.1 2002/08/11 23:32:33 joe Exp $ */ + +/* + * Definitions for the FTDI USB Single Port Serial Converter - + * known as FTDI_SIO (Serial Input/Output application of the chipset) + * + * The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side, + * USB on the other. + * + * Thanx to FTDI (http://www.ftdi.co.uk) for so kindly providing details + * of the protocol required to talk to the device and ongoing assistence + * during development. + * + * Bill Ryder - bryder@sgi.com of Silicon Graphics, Inc. is the original + * author of this file. + */ +/* Modified by Lennart Augustsson */ + +/* + * Added to BeOS USB Serial Driver project by Siarzhuk Zharski + * + * $Source: /cvsroot/sis4be/usb_serial/uftdireg.h,v $ + * $Author: zharik $ + * $Revision: 1.1 $ + * $Date: 2003/05/29 18:55:43 $ + * + */ + +/* Vendor Request Interface */ +#define FTDI_SIO_RESET 0 /* Reset the port */ +#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ +#define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */ +#define FTDI_SIO_SET_BAUD_RATE 3 /* Set baud rate */ +#define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of the port */ +#define FTDI_SIO_GET_STATUS 5 /* Retrieve current value of status reg */ +#define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */ +#define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */ + +/* Port Identifier Table */ +#define FTDI_PIT_DEFAULT 0 /* SIOA */ +#define FTDI_PIT_SIOA 1 /* SIOA */ +#define FTDI_PIT_SIOB 2 /* SIOB */ +#define FTDI_PIT_PARALLEL 3 /* Parallel */ + +enum uftdi_type { + UFTDI_TYPE_SIO, + UFTDI_TYPE_8U232AM +}; + +/* + * BmRequestType: 0100 0000B + * bRequest: FTDI_SIO_RESET + * wValue: Control Value + * 0 = Reset SIO + * 1 = Purge RX buffer + * 2 = Purge TX buffer + * wIndex: Port + * wLength: 0 + * Data: None + * + * The Reset SIO command has this effect: + * + * Sets flow control set to 'none' + * Event char = 0x0d + * Event trigger = disabled + * Purge RX buffer + * Purge TX buffer + * Clear DTR + * Clear RTS + * baud and data format not reset + * + * The Purge RX and TX buffer commands affect nothing except the buffers + * + */ +/* FTDI_SIO_RESET */ +#define FTDI_SIO_RESET_SIO 0 +#define FTDI_SIO_RESET_PURGE_RX 1 +#define FTDI_SIO_RESET_PURGE_TX 2 + + +/* + * BmRequestType: 0100 0000B + * bRequest: FTDI_SIO_SET_BAUDRATE + * wValue: BaudRate value - see below + * wIndex: Port + * wLength: 0 + * Data: None + */ +/* FTDI_SIO_SET_BAUDRATE */ +enum { + ftdi_sio_b300 = 0, + ftdi_sio_b600 = 1, + ftdi_sio_b1200 = 2, + ftdi_sio_b2400 = 3, + ftdi_sio_b4800 = 4, + ftdi_sio_b9600 = 5, + ftdi_sio_b19200 = 6, + ftdi_sio_b38400 = 7, + ftdi_sio_b57600 = 8, + ftdi_sio_b115200 = 9 +}; + +enum { + ftdi_8u232am_b300 = 0x2710, + ftdi_8u232am_b600 = 0x1388, + ftdi_8u232am_b1200 = 0x09c4, + ftdi_8u232am_b2400 = 0x04e2, + ftdi_8u232am_b4800 = 0x0271, + ftdi_8u232am_b9600 = 0x4138, + ftdi_8u232am_b19200 = 0x809c, + ftdi_8u232am_b38400 = 0xc04e, + ftdi_8u232am_b57600 = 0x0034, + ftdi_8u232am_b115200 = 0x001a, + ftdi_8u232am_b230400 = 0x000d, + ftdi_8u232am_b460800 = 0x4006, + ftdi_8u232am_b921600 = 0x8003 +}; + +/* + * BmRequestType: 0100 0000B + * bRequest: FTDI_SIO_SET_DATA + * wValue: Data characteristics (see below) + * wIndex: Port + * wLength: 0 + * Data: No + * + * Data characteristics + * + * B0..7 Number of data bits + * B8..10 Parity + * 0 = None + * 1 = Odd + * 2 = Even + * 3 = Mark + * 4 = Space + * B11..13 Stop Bits + * 0 = 1 + * 1 = 1.5 + * 2 = 2 + * B14..15 Reserved + * + */ +/* FTDI_SIO_SET_DATA */ +#define FTDI_SIO_SET_DATA_BITS(n) (n) +#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8) +#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8) +#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8) +#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8) +#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8) +#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11) +#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11) +#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11) +#define FTDI_SIO_SET_BREAK (0x1 << 14) + + +/* + * BmRequestType: 0100 0000B + * bRequest: FTDI_SIO_MODEM_CTRL + * wValue: ControlValue (see below) + * wIndex: Port + * wLength: 0 + * Data: None + * + * NOTE: If the device is in RTS/CTS flow control, the RTS set by this + * command will be IGNORED without an error being returned + * Also - you can not set DTR and RTS with one control message + * + * ControlValue + * B0 DTR state + * 0 = reset + * 1 = set + * B1 RTS state + * 0 = reset + * 1 = set + * B2..7 Reserved + * B8 DTR state enable + * 0 = ignore + * 1 = use DTR state + * B9 RTS state enable + * 0 = ignore + * 1 = use RTS state + * B10..15 Reserved + */ +/* FTDI_SIO_MODEM_CTRL */ +#define FTDI_SIO_SET_DTR_MASK 0x1 +#define FTDI_SIO_SET_DTR_HIGH (1 | ( FTDI_SIO_SET_DTR_MASK << 8)) +#define FTDI_SIO_SET_DTR_LOW (0 | ( FTDI_SIO_SET_DTR_MASK << 8)) +#define FTDI_SIO_SET_RTS_MASK 0x2 +#define FTDI_SIO_SET_RTS_HIGH (2 | ( FTDI_SIO_SET_RTS_MASK << 8)) +#define FTDI_SIO_SET_RTS_LOW (0 | ( FTDI_SIO_SET_RTS_MASK << 8)) + + +/* + * BmRequestType: 0100 0000b + * bRequest: FTDI_SIO_SET_FLOW_CTRL + * wValue: Xoff/Xon + * wIndex: Protocol/Port - hIndex is protocl / lIndex is port + * wLength: 0 + * Data: None + * + * hIndex protocol is: + * B0 Output handshaking using RTS/CTS + * 0 = disabled + * 1 = enabled + * B1 Output handshaking using DTR/DSR + * 0 = disabled + * 1 = enabled + * B2 Xon/Xoff handshaking + * 0 = disabled + * 1 = enabled + * + * A value of zero in the hIndex field disables handshaking + * + * If Xon/Xoff handshaking is specified, the hValue field should contain the + * XOFF character and the lValue field contains the XON character. + */ +/* FTDI_SIO_SET_FLOW_CTRL */ +#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 +#define FTDI_SIO_RTS_CTS_HS 0x1 +#define FTDI_SIO_DTR_DSR_HS 0x2 +#define FTDI_SIO_XON_XOFF_HS 0x4 + + +/* + * BmRequestType: 0100 0000b + * bRequest: FTDI_SIO_SET_EVENT_CHAR + * wValue: Event Char + * wIndex: Port + * wLength: 0 + * Data: None + * + * wValue: + * B0..7 Event Character + * B8 Event Character Processing + * 0 = disabled + * 1 = enabled + * B9..15 Reserved + * + * FTDI_SIO_SET_EVENT_CHAR + * + * Set the special event character for the specified communications port. + * If the device sees this character it will immediately return the + * data read so far - rather than wait 40ms or until 62 bytes are read + * which is what normally happens. + */ + + + +/* + * BmRequestType: 0100 0000b + * bRequest: FTDI_SIO_SET_ERROR_CHAR + * wValue: Error Char + * wIndex: Port + * wLength: 0 + * Data: None + * + * Error Char + * B0..7 Error Character + * B8 Error Character Processing + * 0 = disabled + * 1 = enabled + * B9..15 Reserved + * + * + * FTDI_SIO_SET_ERROR_CHAR + * Set the parity error replacement character for the specified communications + * port. + */ + + +/* + * BmRequestType: 1100 0000b + * bRequest: FTDI_SIO_GET_MODEM_STATUS + * wValue: zero + * wIndex: Port + * wLength: 1 + * Data: Status + * + * One byte of data is returned + * B0..3 0 + * B4 CTS + * 0 = inactive + * 1 = active + * B5 DSR + * 0 = inactive + * 1 = active + * B6 Ring Indicator (RI) + * 0 = inactive + * 1 = active + * B7 Receive Line Signal Detect (RLSD) + * 0 = inactive + * 1 = active + * + * FTDI_SIO_GET_MODEM_STATUS + * Retrieve the current value of the modem status register. + */ +#define FTDI_SIO_CTS_MASK 0x10 +#define FTDI_SIO_DSR_MASK 0x20 +#define FTDI_SIO_RI_MASK 0x40 +#define FTDI_SIO_RLSD_MASK 0x80 + + + +/* + * + * DATA FORMAT + * + * IN Endpoint + * + * The device reserves the first two bytes of data on this endpoint to contain + * the current values of the modem and line status registers. In the absence of + * data, the device generates a message consisting of these two status bytes + * every 40 ms. + * + * Byte 0: Modem Status + * NOTE: 4 upper bits have same layout as the MSR register in a 16550 + * + * Offset Description + * B0..3 Port + * B4 Clear to Send (CTS) + * B5 Data Set Ready (DSR) + * B6 Ring Indicator (RI) + * B7 Receive Line Signal Detect (RLSD) + * + * Byte 1: Line Status + * NOTE: same layout as the LSR register in a 16550 + * + * Offset Description + * B0 Data Ready (DR) + * B1 Overrun Error (OE) + * B2 Parity Error (PE) + * B3 Framing Error (FE) + * B4 Break Interrupt (BI) + * B5 Transmitter Holding Register (THRE) + * B6 Transmitter Empty (TEMT) + * B7 Error in RCVR FIFO + * + * + * OUT Endpoint + * + * This device reserves the first bytes of data on this endpoint contain the + * length and port identifier of the message. For the FTDI USB Serial converter + * the port identifier is always 1. + * + * Byte 0: Port & length + * + * Offset Description + * B0..1 Port + * B2..7 Length of message - (not including Byte 0) + * + */ +#define FTDI_PORT_MASK 0x0f +#define FTDI_MSR_MASK 0xf0 +#define FTDI_GET_MSR(p) (((p)[0]) & FTDI_MSR_MASK) +#define FTDI_GET_LSR(p) ((p)[1]) +#define FTDI_LSR_MASK (~0x60) /* interesting bits */ +#define FTDI_OUT_TAG(len, port) (((len) << 2) | (port)) diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/uninstall.sh b/src/add-ons/kernel/drivers/ports/usb_serial/uninstall.sh new file mode 100755 index 0000000000..351b914a64 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/uninstall.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +DRIVER_TITLE="USB Serial" +DRIVER_NAME=usb_serial + +answer=`alert "Do you really want to uninstall the $DRIVER_TITLE driver?" "No" "Yes"` +if [ $answer == "No" ]; then + exit +fi + +rm ~/config/add-ons/kernel/drivers/bin/$DRIVER_NAME +rm ~/config/settings/kernel/drivers/$DRIVER_NAME +rm ~/config/add-ons/kernel/drivers/dev/ports/$DRIVER_NAME + +rescan $DRIVER_NAME + +alert "The $DRIVER_TITLE driver has been removed from your system." diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.rdef b/src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.rdef new file mode 100644 index 0000000000..5e16be8d69 --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.rdef @@ -0,0 +1,54 @@ +resource(1, "BEOS:L:STD_ICON") #'ICON' array { + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF0000FFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF0000FFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF00FFFFFF0000FFFFFFFF0000FFFFFFFFFFFFFF00" + $"FFFFFFFFFFFFFFFFFFFFFF001C00000000FFFFFFFF0000FFFFFFFFFFFFFF0000" + $"FFFFFFFFFFFFFFFFFFFF001B1818180000FFFFFF0000FFFFFFFF000000000000" + $"FFFFFFFFFFFFFFFFFF001B183F3F3F181800000000FFFFFFFF001C1C1C000000" + $"FFFFFFFFFFFFFFFF001B180F0F0F0F0F1818180000FFFFFF001C1818181800FF" + $"FFFFFFFFFFFFFF001C1818181818181818181818180000001C181818183F00FF" + $"FFFFFFFFFFFF001C18181818181818181818181818181800001818183F0F00FF" + $"FFFFFFFFFF001B18181818181818181818181818181818181800003F0F0F00FF" + $"FFFFFFFF001C181818181818181818181818181818181818181818000000FFFF" + $"FFFFFF001C181818181818181818181818181818181818181818183F0E00FFFF" + $"FFFF001B181818181818181818181818181818181818181818183F0F0F00FFFF" + $"FF001C181818181818181818181818181818181818181818183F0F0F0F00FFFF" + $"000E181818181818181818181818181818181818181818183F0F0F0F0F00FFFF" + $"003F3F1818183F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F183F0F0F0F0F0F00FFFF" + $"0017173F3F18180F0F0F0F0F0F0F0F0F0F0F0F0F0F183F0F0F0F0F0F0F000FFF" + $"00202018173F3F1818183F3F3F3F3F3F3F3F3F3F183F0F0F0F0F0F0F000E0EFF" + $"001717202017183F3F18180F0F0F0F0F0F0F0F183F0F0F0F0F0F0F000F0F0FFF" + $"00182A1817202017183F3F1818183F3F3F18183F0F0F0F0F0F0F000F0F0FFFFF" + $"002A2A182E1817171718173F3F18180F0F183F0F0F0F0F0F0F000F0F0FFFFFFF" + $"0017182E2E182E1818171718173F3F18183F0F0F0F0F0F0F000F0F0FFFFFFFFF" + $"FF000017182E2E182A1718171718173F3F0F0F0F0F0F0F000F0F0FFFFFFFFFFF" + $"FFFFFF000017172A2A182E171817171C170F0F0F0F0F000F0F0FFFFFFFFFFFFF" + $"FFFFFFFFFF000017172E2E182A17181B180E0F0F0F000F0F0FFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFF000017172A2A18341B180F0F0E000F0F0FFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFF0000171734341C170F0F000F0F0EFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFF000017171C170F000F0F0FFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFF00001B18000E0F0FFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000E0F0FFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +}; + +resource(1, "BEOS:M:STD_ICON") #'MICN' array { + $"FFFFFFFFFFFFFFFFFF00FFFF00FFFFFF" + $"FFFFFFFFFFFF09FF00FFFF00FFFFFF00" + $"FFFFFFFFFF131B1308FF00FFFF0E0700" + $"FFFFFFFF13151313181208FF141819FF" + $"FFFFFF1318181818181818120C1313FF" + $"FFFF14181818181818181818181303FF" + $"FF1318181818181818181818191307FF" + $"0B19181B1B1B1B1B1B1B1B19130F07FF" + $"D5871B1713171717171717130F0F07FF" + $"0BA8AD871B1713171517130F0F070FFF" + $"D0A3A91317191B1717130F0F070FFFFF" + $"FF07A9A3A313171A150F0F070FFFFFFF" + $"FFFFFF07A9A3A368130E070FFFFFFFFF" + $"FFFFFFFFFF078F6813070FFFFFFFFFFF" + $"FFFFFFFFFFFFFF09090EFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +}; + diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.settings.sample b/src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.settings.sample new file mode 100644 index 0000000000..2e008c263d --- /dev/null +++ b/src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.settings.sample @@ -0,0 +1,37 @@ +# +# The sample USB serial driver settings file +# +# Rename it to usb_serial and put into +# /boot/home/config/settings/kernel/drivers/ +# After restarting your system the new settings will works. + +#support_acm_devices - if you have other ACM driver in your system you can disable +# ACM support by setting this key to "false". The default value is "true" - the ACM +# support is activated. +#support_acm_devices true + +# Following settings are for debugging purposes. +# Debug output - this is a possibility to view some kind of development related +# information - error and warning messages etc. + +# debug_output - activates debug output. The debug builds has debug output +# activated by default and this key has no effect on it. The release builds requires +# to activate this if you want to see debug messages in syslog or in private log file. +# +# debug_output true + +# debug_output_in_file - activates writing of debug messages into private log file. +# The name of this file is /boot/home/usb_serial.log. If this key is set to true - no messages +# will be written into syslog. +# +# debug_output_in_file true + +# debug_output_file_rewrite - activates rewriting of private log file on +# calling driver_init() syscall. By default this set in false. +# +# debug_output_file_rewrite false + +# debug_trace_func_calls - the information about driver functions calls +# will be traced. Would you like to see internals? Then activate this. +# +# debug_trace_func_calls true diff --git a/src/add-ons/kernel/drivers/video/Jamfile b/src/add-ons/kernel/drivers/video/Jamfile new file mode 100644 index 0000000000..9c40f09ee8 --- /dev/null +++ b/src/add-ons/kernel/drivers/video/Jamfile @@ -0,0 +1,3 @@ +SubDir HAIKU_TOP src add-ons kernel drivers video ; + +SubInclude HAIKU_TOP src add-ons kernel drivers video usb_vision ; diff --git a/src/add-ons/kernel/drivers/video/usb_vision/Jamfile b/src/add-ons/kernel/drivers/video/usb_vision/Jamfile new file mode 100644 index 0000000000..81e259797c --- /dev/null +++ b/src/add-ons/kernel/drivers/video/usb_vision/Jamfile @@ -0,0 +1,24 @@ +SubDir HAIKU_TOP src add-ons kernel drivers video ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +UsePrivateHeaders usb_vision ; + +#local defines = [ FDefines DB_USB_USE_V2_MODULE ] ; +#SubDirCcFlags $(defines) ; + +KernelAddon usb_vision : kernel drivers bin : + usb_vision.c + tracing.c +; + +# driver goes in dev/video + +Package haiku-usb_vision-cvs + : + usb_vision + : + boot home config add-ons kernel drivers bin ; + +Package haiku-usb_vision-cvs : usb_vision.settings.sample + : boot home config settings kernel drivers sample ; diff --git a/src/add-ons/kernel/drivers/video/usb_vision/ReadMe.html b/src/add-ons/kernel/drivers/video/usb_vision/ReadMe.html new file mode 100644 index 0000000000..40716c245b --- /dev/null +++ b/src/add-ons/kernel/drivers/video/usb_vision/ReadMe.html @@ -0,0 +1,240 @@ + +BeOS driver for USBVision (Nogatech) TV tuners + +

BeOS driver for USBVision (Nogatech) TV tuners

+ +

Introduction

+

This driver is designed to support USBVision (Nogatech) TV Tuners. Tested with:

+ +
+ + + +
NameVendor IDProduct ID
Hauppauge WinTV FM0x05730x4d31
+ +
+NOTE that + +I have one small request for you - if you tried this driver and it works - +PLEASE e-mail me the information about your USB TV Tuner and results of your +experiments. This information is very interesting for me and helps in improvement +this driver! Thank you for co-operation! +
+NOTE that + +If you definetily have the some kind of USB TV Tuner but this driver didn't +help you - see section "Unknown devices" below for instructions. +
+ +
+NOTE that + +If your computer has the OHCI-compatible USB hardware you are out of luck. This hardware is not +supported by non-Dan0-like versions. See the BeOS.USB.patches vor details and +solutions. +
+ +What's new: +
+Version: + +History: +
+0.1.0-dev-0 + +very first "development" release. +
+ + +

1. Installation

+
    +
  • Run install.sh +
  • If all is OK ... //TODO: +
  • If something goes wrong ... //TODO: +
+

2. Uninstallation

+
    +
  • Run uninstall.sh +
+ +

3. Problems solving

+
    +
  • If this driver crash your system - reboot and press "Space" during load. In boot menu select + "Disable user add-ons" and continue boot. Uninstall driver and reboot again into normal mode. + Write me a e-mail about this problem. +
+

4. "Unknown" devices

+ + If you have something, that looks like USB TV tuner and tried it with + this driver but have no success - download + usb device info tool and use it to get required information. +
    +
  • Unplug all USB devices and hubs from your PC. +
  • Go into Terminal and run the following command: + ls -alR /dev/bus/usb + You should see something like this: +
    +$ ls -alR /dev/bus/usb/
    +/dev/bus/usb:
    +total 0
    +drw-r--r--   1 walther  users           0 May 31 23:16 .
    +drw-r--r--   1 walther  users           0 Jun  1  2003 ..
    +drw-r--r--   1 walther  users           0 May 31 23:16 0
    +drw-r--r--   1 walther  users           0 May 31 23:16 1
    +crw-r--r--   1 walther  users      0,   0 May 31 23:16 unload
    +
    +/dev/bus/usb/0:
    +total 0
    +drw-r--r--   1 walther  users           0 May 31 23:16 .
    +drw-r--r--   1 walther  users           0 May 31 23:16 ..
    +crw-r--r--   1 walther  users      0,   0 May 31 23:16 hub
    +
    +/dev/bus/usb/1:
    +total 0
    +drw-r--r--   1 walther  users           0 May 31 23:16 .
    +drw-r--r--   1 walther  users           0 May 31 23:16 ..
    +crw-r--r--   1 walther  users      0,   0 May 31 23:16 hub
    +
    + +
  • Note this information. +
  • Now plug your USB TV tuner into PC and run ls -alR /dev/bus/usb/ again. +You'll get something slightly different: +
    +$ ls -alR /dev/bus/usb/
    +/dev/bus/usb:
    +total 0
    +drw-r--r--   1 walther  users           0 May 31 23:16 .
    +drw-r--r--   1 walther  users           0 Jun  1  2003 ..
    +drw-r--r--   1 walther  users           0 May 31 23:16 0
    +drw-r--r--   1 walther  users           0 May 31 23:16 1
    +crw-r--r--   1 walther  users      0,   0 May 31 23:16 unload
    +
    +/dev/bus/usb/0:
    +total 0
    +drw-r--r--   1 walther  users           0 May 31 23:16 .
    +drw-r--r--   1 walther  users           0 May 31 23:16 ..
    +crw-r--r--   1 walther  users      0,   0 May 31 23:17 1
    +crw-r--r--   1 walther  users      0,   0 May 31 23:16 hub
    +
    +/dev/bus/usb/1:
    +total 0
    +drw-r--r--   1 walther  users           0 May 31 23:16 .
    +drw-r--r--   1 walther  users           0 May 31 23:16 ..
    +crw-r--r--   1 walther  users      0,   0 May 31 23:16 hub
    +
    + +$ +
  • Compare this results with previous one and look for file, +that appeared. This file is your USB TV tuner. +
  • Unpack downloaded usb_dev_info command and run it with full path to file appeared in +the second listing. For my sample I should run: +usb_dev_info /dev/bus/usb/0/1 +I'll get the following: +
    +$ usb_dev_info /dev/bus/usb/0/1
    +[Device]
    +Class .................. 0
    +Subclass ............... 0
    +Protocol ............... 0
    +Vendor ID .............. 0x0573
    +Product ID ............. 0x4d31
    +Version ................ 0x0100
    +Manufacturer String .... "NT"
    +Product String ......... ""
    +Serial Number .......... ""
    +  [Configuration 0]
    +    [Interface 0]
    +    Class .............. 0
    +    Subclass ........... 0
    +    Protocol ........... 0
    +      [Endpoint 0]
    +      MaxPacketSize .... 8
    +      Interval ......... 1
    +      Direction ........ Input
    +      [Endpoint 1]
    +      MaxPacketSize .... 0
    +      Interval ......... 1
    +      Type ............. Isochronous
    +      Direction ........ Output
    +  [Configuration 1]
    +    [Interface 0]
    +    Class .............. 0
    +    Subclass ........... 0
    +    Protocol ........... 0
    +      [Endpoint 0]
    +      MaxPacketSize .... 8
    +      Interval ......... 1
    +      Direction ........ Input
    +      [Endpoint 1]
    +      MaxPacketSize .... 0
    +      Interval ......... 1
    +      Type ............. Isochronous
    +      Direction ........ Output
    +      [Endpoint 2]
    +      MaxPacketSize .... 0
    +      Interval ......... 1
    +      Type ............. Isochronous
    +      Direction ........ Input
    +  [Configuration 2]
    +    [Interface 0]
    +    Class .............. 0
    +    Subclass ........... 0
    +    Protocol ........... 0
    +      [Endpoint 0]
    +      MaxPacketSize .... 8
    +      Interval ......... 1
    +      Direction ........ Input
    +      [Endpoint 1]
    +      MaxPacketSize .... 0
    +      Interval ......... 1
    +      Type ............. Isochronous
    +      Direction ........ Output
    +      [Endpoint 2]
    +      MaxPacketSize .... 64
    +      Interval ......... 1
    +      Type ............. Bulk
    +      Direction ........ Output
    +  [Configuration 3]
    +    [Interface 0]
    +    Class .............. 0
    +    Subclass ........... 0
    +    Protocol ........... 0
    +      [Endpoint 0]
    +      MaxPacketSize .... 8
    +      Interval ......... 1
    +      Direction ........ Input
    +      [Endpoint 1]
    +      MaxPacketSize .... 0
    +      Interval ......... 1
    +      Type ............. Isochronous
    +      Direction ........ Output
    +      [Endpoint 2]
    +      MaxPacketSize .... 0
    +      Interval ......... 1
    +      Type ............. Isochronous
    +      Direction ........ Input
    +      [Endpoint 3]
    +      MaxPacketSize .... 64
    +      Interval ......... 1
    +      Type ............. Bulk
    +      Direction ........ Output
    +
    +
  • Send this information to me with some additional words about your device. +
+ +

What is "BeOS.USB.patches"?

+ +All know that "classical" BeOS R5 don't works on OHCI USB hardware. But some time ago on one well-known +BeOS file-sharing network appeared patches for plain R5. Those patches allows to work with OHCI +hardware under this system version. Looks like it is some part of Dan0 or other "leaked" versions. +There are 3 patches in BeOS.USB.patches.zip: +

1. beos-usb-patch, +

2. beos-usb.modem-patch, +

3. beos-usb.modem-patch.sm. +

You need the first one to make your OHCI hardware working under R5. Install it and proceed with this +driver. Good luck! + + +

Siarzuk Zharski +

http://www.zharik.host.sk/ + \ No newline at end of file diff --git a/src/add-ons/kernel/drivers/video/usb_vision/install.sh b/src/add-ons/kernel/drivers/video/usb_vision/install.sh new file mode 100644 index 0000000000..6bb874e9c0 --- /dev/null +++ b/src/add-ons/kernel/drivers/video/usb_vision/install.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +DRIVER_TITLE="USBVision" +DRIVER_NAME=usbvision + +answer=`alert "Do you really want to install the $DRIVER_TITLE driver?" "No" "Yes"` +if [ $answer == "No" ]; then + exit +fi + +/boot/beos/bin/install -d ~/config/add-ons/kernel/drivers/bin/ +/boot/beos/bin/install -d ~/config/settings/kernel/drivers/ +/boot/beos/bin/install -d ~/config/add-ons/kernel/drivers/dev/video/ +/boot/beos/bin/install `dirname $0`/$DRIVER_NAME ~/config/add-ons/kernel/drivers/bin/ +/boot/beos/bin/cp `dirname $0`/$DRIVER_NAME.settings.sample ~/config/settings/kernel/drivers/$DRIVER_NAME + +mimeset ~/config/add-ons/kernel/drivers/bin/$DRIVER_NAME +mimeset ~/config/settings/kernel/drivers/$DRIVER_NAME + +ln -sf ../../bin/$DRIVER_NAME ~/config/add-ons/kernel/drivers/dev/video/$DRIVER_NAME + +rescan $DRIVER_NAME + +alert "The $DRIVER_TITLE driver has been installed in your system." diff --git a/src/add-ons/kernel/drivers/video/usb_vision/tracing.c b/src/add-ons/kernel/drivers/video/usb_vision/tracing.c new file mode 100644 index 0000000000..e9cbd19d4f --- /dev/null +++ b/src/add-ons/kernel/drivers/video/usb_vision/tracing.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + * + */ + +#include +#include + +#include +//#include +#include //sprintf +#include //posix file i/o - create, write, close +#include + +#include "usbvision.h" + +#if DEBUG +bool b_log = true; +#else +bool b_log = false; +#endif +bool b_log_file = false; +bool b_log_append = false; +bool b_log_funcalls = false; +bool b_log_funcret = false; +bool b_log_funcres = false; + +bool b_log_settings_loaded = false; + +static const char *private_log_path="/boot/home/"DRIVER_NAME".log"; +static sem_id loglock; + +void load_setting(){ + if(!b_log_settings_loaded){ + void *settingshandle; + settingshandle = load_driver_settings(DRIVER_NAME); +#if !DEBUG + b_log = get_driver_boolean_parameter(settingshandle, "debug_output", b_log, true); +#endif + b_log_file = get_driver_boolean_parameter(settingshandle, "debug_output_in_file", b_log_file, true); + b_log_append = ! get_driver_boolean_parameter(settingshandle, "debug_output_file_rewrite", !b_log_append, true); + b_log_funcalls = get_driver_boolean_parameter(settingshandle, "debug_trace_func_calls", b_log_funcalls, false); + b_log_funcret = get_driver_boolean_parameter(settingshandle, "debug_trace_func_returns", b_log_funcret, false); + b_log_funcres = get_driver_boolean_parameter(settingshandle, "debug_trace_func_results", b_log_funcres, false); + unload_driver_settings(settingshandle); + b_log_settings_loaded = true; + } +} + +void create_log(){ + int flags = O_WRONLY | O_CREAT | ((!b_log_append) ? O_TRUNC : 0); + if(!b_log_file) + return; + close(open(private_log_path, flags, 0666)); + loglock = create_sem(1, DRIVER_NAME"-logging"); +} + +void usbvision_trace(bool b_force, char *fmt, ...){ + if(!(b_force || b_log)) + return; + { + va_list arg_list; + static char *prefix = "\33[32m"DRIVER_NAME":\33[0m"; + static char buf[1024]; + char *buf_ptr = buf; + if(!b_log_file){ + strcpy(buf, prefix); + buf_ptr += strlen(prefix); + } + +/* { + bigtime_t time = system_time(); + uint32 msec = time / 1000; + uint32 sec = msec / 1000; + sprintf(buf_ptr, "%02d.%02d.%03d:", sec / 60, sec % 60, msec % 1000); + buf_ptr += strlen(buf_ptr); + } +*/ + va_start(arg_list, fmt); + vsprintf(buf_ptr, fmt, arg_list); + va_end(arg_list); + + if(b_log_file){ + int fd; + acquire_sem(loglock); + fd = open(private_log_path, O_WRONLY | O_APPEND); + write(fd, buf, strlen(buf)); + close(fd); + release_sem(loglock); + } + else + dprintf(buf); + } +} + +void trace_reginfo(xet_nt100x_reg *ri) +{ + int i; + TRACE("struct set_nt100x_reg\n" + " reg:%02x\n" + " data_length:%d\n", + ri->reg, ri->data_length); + for(i = 0; i < ri->data_length; i++) + TRACE("%02x ", ri->data[i]); + TRACE("\n"); +} diff --git a/src/add-ons/kernel/drivers/video/usb_vision/tracing.h b/src/add-ons/kernel/drivers/video/usb_vision/tracing.h new file mode 100644 index 0000000000..08908e64e5 --- /dev/null +++ b/src/add-ons/kernel/drivers/video/usb_vision/tracing.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + * + */ + +#ifndef _USBVISION_TRACING_H_ + #define _USBVISION_TRACING_H_ + +void load_setting(); +void create_log(); +void usbvision_trace(bool b_force, char *fmt, ...); + +#define TRACE_ALWAYS(x...) usbvision_trace(true, x); +#define TRACE(x...) usbvision_trace(false, x); + +extern bool b_log_funcalls; +#define TRACE_FUNCALLS(x...)\ + { if(b_log_funcalls) usbvision_trace(false, x);} + +extern bool b_log_funcret; +#define TRACE_FUNCRET(x...)\ + { if(b_log_funcret) usbvision_trace(false, x);} + +extern bool b_log_funcres; +#define TRACE_FUNCRES(func, param)\ + { if(b_log_funcres) func(param);} + +void trace_reginfo(xet_nt100x_reg *reginfo); + +#endif /*_USBVISION_TRACING_H_*/ diff --git a/src/add-ons/kernel/drivers/video/usb_vision/uninstall.sh b/src/add-ons/kernel/drivers/video/usb_vision/uninstall.sh new file mode 100644 index 0000000000..6ccbaa68a9 --- /dev/null +++ b/src/add-ons/kernel/drivers/video/usb_vision/uninstall.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +DRIVER_TITLE="USBVision" +DRIVER_NAME=usbvision + +answer=`alert "Do you really want to uninstall the $DRIVER_TITLE driver?" "No" "Yes"` +if [ $answer == "No" ]; then + exit +fi + +rm ~/config/add-ons/kernel/drivers/bin/$DRIVER_NAME +rm ~/config/settings/kernel/drivers/$DRIVER_NAME +rm ~/config/add-ons/kernel/drivers/dev/video/$DRIVER_NAME + +rescan $DRIVER_NAME + +alert "The $DRIVER_TITLE driver has been removed from your system." diff --git a/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.c b/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.c new file mode 100644 index 0000000000..620f49cbfd --- /dev/null +++ b/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.c @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + * + */ + +#include +#include +#include + +#include +#include +#include /* strerror */ +#include /* strtol */ +#include /* sprintf */ + + +#include "usb_vision.h" +#include "tracing.h" + +#define BASENAME_LEN 0x10 /*must be synchronized with below !!!*/ +static const char *basename = "video/usb_vision/%u"; + +status_t usb_vision_device_added(const usb_device *dev, void **cookie); +status_t usb_vision_device_removed(void *cookie); + +static usb_notify_hooks notify_hooks = { + &usb_vision_device_added, + &usb_vision_device_removed +}; + +struct usb_module_info *usb; +usb_vision_device *usb_vision_devices[DEVICES_COUNT]; +char * usb_vision_names[DEVICES_COUNT + 1]; +sem_id usb_vision_lock = -1; + +struct usb_support_descriptor supported_devices[] = { + {0, 0, 0, 0x0573, 0x4d31}, +}; + +/* init_hardware - called once the first time the driver is loaded */ +status_t init_hardware (void){ + TRACE("init_hardware\n"); /*special case - no file-logging activated now*/ + return B_OK; +} + +/* init_driver - optional function - called every time the driver is loaded. */ +status_t init_driver (void){ + int i; + status_t status = B_OK; + load_setting(); + create_log(); + + TRACE_FUNCALLS("init_driver\n"); + + if((status = get_module(B_USB_MODULE_NAME, (module_info **)&usb)) == B_OK){ + if(usb){ + for(i = 0; i < DEVICES_COUNT; i++) + usb_vision_devices[i] = 0; + + usb_vision_names[0] = NULL; + load_driver_symbols(DRIVER_NAME); + + (*usb->register_driver)(DRIVER_NAME, supported_devices, SIZEOF(supported_devices), DRIVER_NAME); + (*usb->install_notify)(DRIVER_NAME, ¬ify_hooks); + + usb_vision_lock = create_sem(1, DRIVER_NAME"_devices_table_lock"); + }else{ + status = B_ERROR; + TRACE_ALWAYS("init_driver failed: usb:%08x", usb); + } + }else + TRACE_ALWAYS("init_driver failed:%lx cannot get a module %s", status, B_USB_MODULE_NAME); + + TRACE_FUNCRET("init_driver returns:%08x\n", status); + return status; +} + + +/* uninit_driver - optional function - called every time the driver is unloaded */ +void uninit_driver (void){ + int i; + TRACE_FUNCALLS("uninit_driver\n"); + + (*usb->uninstall_notify)(DRIVER_NAME); + acquire_sem(usb_vision_lock); + + for(i = 0; i < DEVICES_COUNT; i++) + if(usb_vision_devices[i]){ + free(usb_vision_devices[i]); + usb_vision_devices[i] = 0; + } + + release_sem_etc(usb_vision_lock, 1, B_DO_NOT_RESCHEDULE); + delete_sem(usb_vision_lock); + + for(i = 0; usb_vision_names[i]; i++) + free(usb_vision_names[i]); + + put_module(B_USB_MODULE_NAME); +} + + +/* usb_vision_open - handle open() calls */ + +static status_t usb_vision_open (const char *name, uint32 flags, void** cookie) +{ + int i; + status_t status = ENODEV; + TRACE_FUNCALLS("usb_vision_open:%s flags:%d cookie:%08x\n", name, flags, cookie); + + for(i = 0; i < DEVICES_COUNT; i++) + TRACE("%08x\n", usb_vision_devices[i]); + + *cookie = NULL; + i = strtol(name + BASENAME_LEN, NULL, 10); + if(i >= 0 && i < DEVICES_COUNT){ + acquire_sem(usb_vision_lock); + if(usb_vision_devices[i]){ + if(atomic_add(&usb_vision_devices[i]->open_count, 1) == 0){ + *cookie = usb_vision_devices[i]; + TRACE("cookie in open:%08x\n", *cookie); + status = B_OK; + }else{ + atomic_add(&usb_vision_devices[i]->open_count, -1); + status = B_BUSY; + } + } + release_sem(usb_vision_lock); + } + + TRACE_FUNCRET("usb_vision_open returns:%08x\n", status); + return status; +} + +/* usb_vision_read - handle read() calls */ + +static status_t usb_vision_read (void* cookie, off_t position, void *buf, size_t* num_bytes) +{ + *num_bytes = 0; /* tell caller nothing was read */ + return B_IO_ERROR; +} + + +/* usb_vision_write - handle write() calls */ + +static status_t usb_vision_write (void* cookie, off_t position, const void* buffer, size_t* num_bytes) +{ + *num_bytes = 0; /* tell caller nothing was written */ + return B_IO_ERROR; +} + +static status_t xet_nt_register(bool is_read, usb_vision_device *uvd, xet_nt100x_reg *ri) +{ + status_t status = B_ERROR; + uint8 req_type = USB_REQTYPE_VENDOR | (is_read ? USB_REQTYPE_DEVICE_IN : USB_REQTYPE_DEVICE_OUT); + + TRACE_FUNCALLS("set_nt_register:%08x, %08x\n", uvd, ri); + TRACE_FUNCRES(trace_reginfo, ri); + + //(*usb->send_request)(uvd->dev, req_type, + // ) + + TRACE_FUNCRET("set_nt_register returns:%08x\n", status); + return status; +} + +/* usb_vision_control - handle ioctl calls */ +static status_t usb_vision_control (void* cookie, uint32 op, void* arg, size_t len) +{ + status_t status = B_BAD_VALUE; + TRACE_FUNCALLS("usb_vision_control:%08x, %d, %08x, %d\n", cookie, op, arg, len); + switch(op){ + case NT_IOCTL_READ_REGISTER: + status = xet_nt_register(true, (usb_vision_device *)cookie, (xet_nt100x_reg *) arg); + break; + case NT_IOCTL_WRITE_REGISTER: + status = xet_nt_register(false, (usb_vision_device *)cookie, (xet_nt100x_reg *) arg); + break; + default: + break; + } + TRACE_FUNCRET("usb_vision_control returns:%08x\n", status); + return status; +} + +/* usb_vision_close - handle close() calls */ +static status_t usb_vision_close (void* cookie) +{ + status_t status = B_OK;//ENODEV; + TRACE_FUNCALLS("usb_vision_close:%08x\n", cookie); + + TRACE_FUNCRET("usb_vision_close returns:%08x\n", status); + return status; +} + + +/* usb_vision_free - called after the last device is closed, and after all i/o is complete. */ +static status_t usb_vision_free (void* cookie) +{ + status_t status = B_OK; + TRACE_FUNCALLS("usb_vision_free:%08x\n", cookie); + + if(cookie){ + usb_vision_device *uvd = (usb_vision_device *)cookie; + atomic_add(&uvd->open_count, -1); + } + + TRACE_FUNCRET("usb_vision_free returns:%08x\n", status); + return status; +} + +/* function pointers for the device hooks entry points */ +device_hooks usb_vision_hooks = { + usb_vision_open, /* -> open entry point */ + usb_vision_close, /* -> close entry point */ + usb_vision_free, /* -> free cookie */ + usb_vision_control, /* -> control entry point */ + usb_vision_read, /* -> read entry point */ + usb_vision_write /* -> write entry point */ +}; + +/* publish_devices - return a null-terminated array of devices + supported by this driver. */ + +const char** publish_devices(){ + int i, j; + TRACE_FUNCALLS("publish_devices\n"); + + for(i=0; usb_vision_names[i]; i++) + free(usb_vision_names[i]); + + acquire_sem(usb_vision_lock); + for(i=0, j=0; i < DEVICES_COUNT; i++){ + if(usb_vision_devices[i]){ + usb_vision_names[j] = malloc(strlen(basename + 2)); + if(usb_vision_names[j]){ + sprintf(usb_vision_names[j], basename, i); + j++; + } + else + TRACE_ALWAYS("publish_devices - NO MEMORY\n"); + } + } + usb_vision_names[j] = NULL; + release_sem(usb_vision_lock); + + return (const char **)&usb_vision_names[0]; +} + +/* find_device - return ptr to device hooks structure for a + given device name */ +device_hooks* find_device(const char* name){ + TRACE_FUNCALLS("find_device(%s)\n", name); + return &usb_vision_hooks; +} + +status_t create_add_device(usb_vision_device *uvd, const struct usb_configuration_info *uci, + struct usb_endpoint_info *control_epi, + struct usb_endpoint_info *data_epi){ +// char name[32]; + status_t status = ENODEV; +// size_t buf_len; + int i = 0; + + TRACE_FUNCALLS("create_add_device(%08x, %08x, %08x, %08x)\n", uvd, uci, control_epi, data_epi); + + acquire_sem(usb_vision_lock); + + for(i = 0; i < DEVICES_COUNT; i++){ + if(usb_vision_devices[i] != NULL) + continue; + + usb_vision_devices[i] = uvd; + /* + usd->active = 1; + usd->open = 0; + + sprintf(name, "usb_vision:%d:done_read", i ); + usd->done_read = create_sem(0, name); + + sprintf(name, "usb_vision:%d:done_write", i); + usd->done_write = create_sem(0, name); + + usd->tty = NULL; + + buf_len = usd->read_buffer_size + usd->write_buffer_size + usd->interrupt_buffer_size; + + usd->buffers_area = create_area("usb_serial:buffers_area", (void *)&usd->read_buffer, B_ANY_KERNEL_ADDRESS, + ROUNDUP(buf_len, B_PAGE_SIZE), + B_CONTIGUOUS, B_READ_AREA|B_WRITE_AREA); + + usd->write_buffer = usd->read_buffer + usd->read_buffer_size; + usd->interrupt_buffer = usd->write_buffer + usd->write_buffer_size; +*/ + (*usb->set_configuration)(uvd->dev, uci); + + uvd->control_pipe = control_epi->handle; + uvd->data_pipe = data_epi->handle; + + status = B_OK; + break; + } + release_sem(usb_vision_lock); + + TRACE_FUNCRET("add_device returns:%08x\n", status); + return status; +} + +status_t add_device(usb_vision_device *uvd, const usb_configuration_info *uci){ + usb_endpoint_info *control_epi = NULL; + usb_endpoint_info *data_epi = NULL; + status_t status = ENODEV; + int i = 0; + usb_interface_info *uii = uci->interface[0].active; + TRACE_FUNCALLS("> add_device(%08x, %08x)\n", uvd, uci); + + for(i=0; i < uii->endpoint_count; i++){ + if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_ISOCHRONOUS){ + if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN) == USB_EP_ADDR_DIR_IN){ + data_epi = &uii->endpoint[i]; + TRACE("iso_ep:%d\n", i); + } + } + if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_CONTROL){ + control_epi = &uii->endpoint[i]; + TRACE("cont_ep:%d\n", i); + } + if(control_epi && data_epi) + break; + } + + if(control_epi && data_epi){ + status = create_add_device(uvd, uci, control_epi, data_epi); + } + + TRACE_FUNCRET("< create_add_device returns:%08x\n", status); + return status; +} + +status_t usb_vision_device_added(const usb_device *dev, void **cookie){ + int dev_idx; + status_t status = B_OK; + const usb_device_descriptor *udd; + usb_vision_device *uvd = 0; + TRACE_FUNCALLS("usb_vision_device_added:%08x cookie:%08x\n", dev, cookie); + + udd = (*usb->get_device_descriptor)(dev); + TRACE_ALWAYS("Probing device: %08x/%08x\n", udd->vendor_id, udd->product_id); + + *cookie = 0; + for(dev_idx = 0; dev_idx < SIZEOF(supported_devices); dev_idx++) + if(supported_devices[dev_idx].vendor == udd->vendor_id + && supported_devices[dev_idx].product == udd->product_id){ + const usb_configuration_info *uci; + int cfg_idx; + for(cfg_idx = 0; (uci = (*usb->get_nth_configuration)(dev, cfg_idx)) != NULL; cfg_idx++){ + uvd = malloc(sizeof(usb_vision_device)); + if(uvd){ + memset(uvd, 0, sizeof(usb_vision_device)); + uvd->dev = dev; + if((status = add_device(uvd, uci)) == B_OK){ + *cookie = dev; + TRACE_ALWAYS("(%04x/%04x) added \n", supported_devices[dev_idx].vendor, + supported_devices[dev_idx].product); + break; + }else + free(uvd); + }else + status = B_NO_MEMORY; + } + break; + } + + TRACE_FUNCRET("usb_vision_device_added returns:%08x\n", status); + return status; +} + +status_t usb_vision_device_removed(void *cookie){ + int i; + status_t status = B_OK; + struct usb_device *ud = (struct usb_device *) cookie; + TRACE_FUNCALLS("usb_vision_device_removed:%08x\n", cookie); + + acquire_sem(usb_vision_lock); + + for(i = 0; i < DEVICES_COUNT; i++ ){ + usb_vision_device *uvd = usb_vision_devices[i]; + if(uvd){ + if(ud == uvd->dev){ + free(uvd); + usb_vision_devices[i] = 0; + } + } + } + + release_sem(usb_vision_lock); + + TRACE_FUNCRET("usb_vision_device_removed returns:%08x\n", status); + return status; +} diff --git a/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.h b/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.h new file mode 100644 index 0000000000..cfbd73517e --- /dev/null +++ b/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2003 by Siarzhuk Zharski + * Distributed under the terms of the MIT License. + * + */ + +#ifndef _USBVISION_DRIVER_H_ + #define _USBVISION_DRIVER_H_ + +#define DRIVER_NAME "usb_vision" + +#define DEVICES_COUNT 0x1f + +#include "nt100x.h" +#include "tracing.h" + +#define SIZEOF(array) (sizeof(array)/sizeof(array[0])) + +/* "forgotten" attributes etc ...*/ +#define USB_EP_ADDR_DIR_IN 0x80 +#define USB_EP_ADDR_DIR_OUT 0x00 + +#define USB_EP_ATTR_CONTROL 0x00 +#define USB_EP_ATTR_ISOCHRONOUS 0x01 +#define USB_EP_ATTR_BULK 0x02 +#define USB_EP_ATTR_INTERRUPT 0x03 + + +typedef struct{ + uint32 open_count; + const usb_device *dev; + usb_pipe *control_pipe; + usb_pipe *data_pipe; +} usb_vision_device; + +#endif//_USB_SERIAL_DRIVER_H_ diff --git a/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.settings.sample b/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.settings.sample new file mode 100644 index 0000000000..27a25a61c2 --- /dev/null +++ b/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.settings.sample @@ -0,0 +1,31 @@ +# +# The sample USBVision driver settings file +# +# Rename it to usbvision and put into +# /boot/home/config/settings/kernel/drivers/ +# After restarting your system the new settings will works. + +# Debug output - this is a possibility to view some kind of development related +# information - error and warning messages etc. + +# debug_output - activates debug output. The debug builds has debug output +# activated by default and this key has no effect on it. The release builds requires +# to activate this if you want to see debug messages in syslog or in private log file. +# +# debug_output true + +# debug_output_in_file - activates writing of debug messages into private log file. +# The name of this file is /boot/home/usbvision.log. If this key is set to true - no messages +# will be written into syslog. +# +# debug_output_in_file true + +# debug_output_file_rewrite - activates rewriting of private log file on +# calling driver_init() syscall. By default this set in false. +# +# debug_output_file_rewrite false + +# debug_trace_func_calls - the information about driver functions calls +# will be traced. Would you like to see internals? Then activate this. +# +# debug_trace_func_calls true diff --git a/src/add-ons/media/media-add-ons/Jamfile b/src/add-ons/media/media-add-ons/Jamfile index 73edbe465d..8949fd2788 100644 --- a/src/add-ons/media/media-add-ons/Jamfile +++ b/src/add-ons/media/media-add-ons/Jamfile @@ -8,5 +8,6 @@ SubInclude HAIKU_TOP src add-ons media media-add-ons mixer ; SubInclude HAIKU_TOP src add-ons media media-add-ons multi_audio ; SubInclude HAIKU_TOP src add-ons media media-add-ons radeon ; SubInclude HAIKU_TOP src add-ons media media-add-ons tone_producer_demo ; +SubInclude HAIKU_TOP src add-ons media media-add-ons usb_vision ; SubInclude HAIKU_TOP src add-ons media media-add-ons video_producer_demo ; diff --git a/src/add-ons/media/media-add-ons/usb_vision/AddOn.cpp b/src/add-ons/media/media-add-ons/usb_vision/AddOn.cpp new file mode 100644 index 0000000000..8280622cee --- /dev/null +++ b/src/add-ons/media/media-add-ons/usb_vision/AddOn.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2003 by Siarzuk Zharski + * + * This file may be used under the terms of the BSD License + * + * Skeletal part of this code was inherired from original BeOS sample code, + * that is distributed under the terms of the Be Sample Code License. + * + */ + +#include +#include +#include + +#include +#include +#include + +#include "AddOn.h" +#include "Producer.h" + +#include "nt100x.h" + +MediaAddOn::MediaAddOn(image_id imid) + : BMediaAddOn(imid) +{ + /* Customize these parameters to match those of your node */ + fFlavorInfo.name = "USB Vision"; + fFlavorInfo.info = "USB Vision"; + fFlavorInfo.kinds = B_BUFFER_PRODUCER | B_CONTROLLABLE | B_PHYSICAL_INPUT; + fFlavorInfo.flavor_flags = 0; + fFlavorInfo.internal_id = 0; + fFlavorInfo.possible_count = 1; + fFlavorInfo.in_format_count = 0; + fFlavorInfo.in_format_flags = 0; + fFlavorInfo.in_formats = NULL; + fFlavorInfo.out_format_count = 1; + fFlavorInfo.out_format_flags = 0; + fMediaFormat.type = B_MEDIA_RAW_VIDEO; + fMediaFormat.u.raw_video = media_raw_video_format::wildcard; + fMediaFormat.u.raw_video.interlace = 1; + fMediaFormat.u.raw_video.display.format = B_RGB32; + fFlavorInfo.out_formats = &fMediaFormat; + + fInitStatus = B_NO_INIT; + fDriverFD = -1; + if(USBVisionInit()){ + fInitStatus = B_OK; + } +} + +MediaAddOn::~MediaAddOn() +{ + if(fInitStatus == B_OK){ + USBVisionUninit(); + } +} + + +status_t +MediaAddOn::InitCheck(const char **out_failure_text) +{ + if (fInitStatus < B_OK) { + *out_failure_text = "Unknown error"; + return fInitStatus; + } + + return B_OK; +} + +int32 +MediaAddOn::CountFlavors() +{ + if (fInitStatus < B_OK) + return fInitStatus; + + /* This addon only supports a single flavor, as defined in the + * constructor */ + return 1; +} + +/* + * The pointer to the flavor received only needs to be valid between + * successive calls to BMediaAddOn::GetFlavorAt(). + */ +status_t +MediaAddOn::GetFlavorAt(int32 n, const flavor_info **out_info) +{ + if (fInitStatus < B_OK) + return fInitStatus; + + if (n != 0) + return B_BAD_INDEX; + + /* Return the flavor defined in the constructor */ + *out_info = &fFlavorInfo; + return B_OK; +} + +BMediaNode * +MediaAddOn::InstantiateNodeFor( + const flavor_info *info, BMessage *config, status_t *out_error) +{ + VideoProducer *node; + + if (fInitStatus < B_OK) + return NULL; + + if (info->internal_id != fFlavorInfo.internal_id) + return NULL; + + /* At most one instance of the node should be instantiated at any given + * time. The locking for this restriction may be found in the VideoProducer + * class. */ + node = new VideoProducer(this, fFlavorInfo.name, fFlavorInfo.internal_id); + if (node && (node->InitCheck() < B_OK)) { + delete node; + node = NULL; + } + + return node; +} + +BMediaAddOn * +make_media_addon(image_id imid) +{ + return new MediaAddOn(imid); +} + +bool MediaAddOn::USBVisionInit() +{ + //TODO - support for multiple devices !!! + fDriverFD = open("/dev/video/usb_vision/0", O_RDWR); + if(fDriverFD < 0) + fInitStatus = ENODEV; + return (fDriverFD >= 0); +} + +void MediaAddOn::USBVisionUninit() +{ //TODO - correct work on detach device from usb port ... + close(fDriverFD); +} + +status_t MediaAddOn::USBVisionWriteRegister(uint8 reg, uint8 *data, uint8 len /*= sizeof(uint8)*/) +{ + status_t status = ENODEV; + if(fDriverFD >= 0){ + xet_nt100x_reg ri = {reg, len}; + memcpy(ri.data, data, len); + status = ioctl(fDriverFD, NT_IOCTL_WRITE_REGISTER, &ri, sizeof(ri)); + } + return status; +} + +status_t MediaAddOn::USBVisionReadRegister(uint8 reg, uint8 *data, uint8 len /* = sizeof(uint8)*/) +{ + status_t status = ENODEV; + if(fDriverFD >= 0){ + xet_nt100x_reg ri = {reg, len}; + if((status = ioctl(fDriverFD, NT_IOCTL_READ_REGISTER, &ri, sizeof(ri))) == B_OK){ + memcpy(data, ri.data, ri.data_length); + } + } + return status; +} diff --git a/src/add-ons/media/media-add-ons/usb_vision/AddOn.h b/src/add-ons/media/media-add-ons/usb_vision/AddOn.h new file mode 100644 index 0000000000..d489d7f26e --- /dev/null +++ b/src/add-ons/media/media-add-ons/usb_vision/AddOn.h @@ -0,0 +1,59 @@ +/* + * This file is a part of BeOS USBVision driver project. + * Copyright (c) 2003 by Siarzuk Zharski + * + * This file may be used under the terms of the BSD License + * + * Skeletal part of this code was inherired from original BeOS sample code, + * that is distributed under the terms of the Be Sample Code License. + * + */ + +#ifndef _USBVISION_ADDON_H +#define _USBVISION_ADDON_H + +#include + +#define TOUCH(x) ((void)(x)) + +extern "C" _EXPORT BMediaAddOn *make_media_addon(image_id you); + +class MediaAddOn : public BMediaAddOn +{ +public: + MediaAddOn(image_id imid); + virtual ~MediaAddOn(); + + virtual status_t InitCheck(const char **out_failure_text); + + virtual int32 CountFlavors(); + virtual status_t GetFlavorAt(int32 n, const flavor_info ** out_info); + virtual BMediaNode *InstantiateNodeFor( + const flavor_info * info, + BMessage * config, + status_t * out_error); + + virtual status_t GetConfigurationFor(BMediaNode *node, BMessage *message) + { TOUCH(node); TOUCH(message); return B_OK; } + virtual status_t SaveConfigInfo(BMediaNode *node, BMessage *message) + { TOUCH(node); TOUCH(message); return B_OK; } + + virtual bool WantsAutoStart() { return false; } + virtual status_t AutoStart(int in_count, BMediaNode **out_node, + int32 *out_internal_id, bool *out_has_more) + { TOUCH(in_count); TOUCH(out_node); + TOUCH(out_internal_id); TOUCH(out_has_more); + return B_ERROR; } + bool USBVisionInit(); + void USBVisionUninit(); + status_t USBVisionWriteRegister(uint8 reg, uint8 *data, uint8 len = sizeof(uint8)); + status_t USBVisionReadRegister(uint8 reg, uint8 *data, uint8 len = sizeof(uint8)); + +private: + status_t fInitStatus; + flavor_info fFlavorInfo; + media_format fMediaFormat; + int fDriverFD; +}; + +#endif /*_USBVISION_ADDON_H*/ diff --git a/src/add-ons/media/media-add-ons/usb_vision/Channels.cpp b/src/add-ons/media/media-add-ons/usb_vision/Channels.cpp new file mode 100644 index 0000000000..262cab7178 --- /dev/null +++ b/src/add-ons/media/media-add-ons/usb_vision/Channels.cpp @@ -0,0 +1,582 @@ +/* + * This file is a part of BeOS USBVision driver project. + * Copyright (c) 2003 by Siarzuk Zharski + * + * This file may be used under the terms of the BSD License + * + */ + +/* TODO: Look for the following channel lists ... +Brazil Air +China Air +Europe Air +Europe Cable +France Air +France Cable +Great Britain Air +Great Britain Cable +FM Radio +UKW Radio +*/ + +struct Channel{ + const char *name; + float frequency; // in MHz +}; + +Channel Channels_US_Air[] = { + { "2", 55.25}, { "3", 61.25}, { "4", 67.25}, { "5", 77.25}, { "6", 83.25}, + { "7", 175.25}, { "8", 181.25}, { "9", 187.25}, { "10", 193.25}, { "11", 199.25}, + { "12", 205.25}, { "13", 211.25}, { "14", 471.25}, { "15", 477.25}, { "16", 483.25}, + { "17", 489.25}, { "18", 495.25}, { "19", 501.25}, { "20", 507.25}, { "21", 513.25}, + { "22", 519.25}, { "23", 525.25}, { "24", 531.25}, { "25", 537.25}, { "26", 543.25}, + { "27", 549.25}, { "28", 555.25}, { "29", 561.25}, { "30", 567.25}, { "31", 573.25}, + { "32", 579.25}, { "33", 585.25}, { "34", 591.25}, { "35", 597.25}, { "36", 603.25}, + { "37", 609.25}, { "38", 615.25}, { "39", 621.25}, { "40", 627.25}, { "41", 633.25}, + { "42", 639.25}, { "43", 645.25}, { "44", 651.25}, { "45", 657.25}, { "46", 663.25}, + { "47", 669.25}, { "48", 675.25}, { "49", 681.25}, { "50", 687.25}, { "51", 693.25}, + { "52", 699.25}, { "53", 705.25}, { "54", 711.25}, { "55", 717.25}, { "56", 723.25}, + { "57", 729.25}, { "58", 735.25}, { "59", 741.25}, { "60", 747.25}, { "61", 753.25}, + { "62", 759.25}, { "63", 765.25}, { "64", 771.25}, { "65", 777.25}, { "66", 783.25}, + { "67", 789.25}, { "68", 795.25}, { "69", 801.25} }; + +Channel Channels_US_Cable[] = { + { "4A", 73.25}, { "2", 55.25}, { "3", 61.25}, { "4", 67.25}, { "5", 77.25}, + { "6", 83.25}, { "7", 175.25}, { "8", 181.25}, { "9", 187.25}, { "10", 193.25}, + { "11", 199.25}, { "12", 205.25}, { "13", 211.25}, { "A", 121.25}, { "B", 127.25}, + { "C", 133.25}, { "D", 139.25}, { "E", 145.25}, { "F", 151.25}, { "G", 157.25}, + { "H", 163.25}, { "I", 169.25}, { "J", 217.25}, { "K", 223.25}, { "L", 229.25}, + { "M", 235.25}, { "N", 241.25}, { "O", 247.25}, { "P", 253.25}, { "Q", 259.25}, + { "R", 265.25}, { "S", 271.25}, { "T", 277.25}, { "U", 283.25}, { "V", 289.25}, + { "W", 295.25}, { "W+1", 301.25}, { "W+2", 307.25}, { "W+3", 313.25}, { "W+4", 319.25}, + { "W+5", 325.25}, { "W+6", 331.25}, { "W+7", 337.25}, { "W+8", 343.25}, { "W+9", 349.25}, + { "W+10", 355.25}, { "W+11", 361.25}, { "W+12", 367.25}, { "W+13", 373.25}, { "W+14", 379.25}, + { "W+15", 385.25}, { "W+16", 391.25}, { "W+17", 397.25}, { "W+18", 403.25}, { "W+19", 409.25}, + { "W+20", 415.25}, { "W+21", 421.25}, { "W+22", 427.25}, { "W+23", 433.25}, { "W+24", 439.25}, + { "W+25", 445.25}, { "W+26", 451.25}, { "W+27", 457.25}, { "W+28", 463.25}, { "65", 469.25}, + { "66", 475.25}, { "67", 481.25}, { "68", 487.25}, { "69", 493.25}, { "70", 499.25}, + { "71", 505.25}, { "72", 511.25}, { "73", 517.25}, { "74", 523.25}, { "75", 529.25}, + { "76", 535.25}, { "77", 541.25}, { "78", 547.25}, { "79", 553.25}, { "80", 559.25}, + { "81", 565.25}, { "82", 571.25}, { "83", 577.25}, { "84", 583.25}, { "85", 589.25}, + { "86", 595.25}, { "87", 601.25}, { "88", 607.25}, { "89", 613.25}, { "90", 619.25}, + { "91", 625.25}, { "92", 631.25}, { "93", 637.25}, { "94", 643.25}, { "A­5", 91.25 }, + { "A­4", 97.25 }, { "A­3", 103.25}, { "A­2", 109.25}, { "A-1", 115.25}, { "100", 649.25}, + { "101", 655.25}, { "102", 661.25}, { "103", 667.25}, { "104", 673.25}, { "105", 679.25}, + { "106", 685.25}, { "107", 691.25}, { "108", 697.25}, { "109", 703.25}, { "110", 709.25}, + { "111", 715.25}, { "112", 721.25}, { "113", 727.25}, { "114", 733.25}, { "115", 739.25}, + { "116", 745.25}, { "117", 751.25}, { "118", 757.25}, { "119", 763.25}, { "120", 769.25}, + { "121", 775.25}, { "122", 781.25}, { "123", 787.25}, { "124", 793.25}, { "125", 799.25} }; + +Channel Channels_US_Cable_HRC[] = { + { "2", 54.00}, { "3", 60.00}, { "4", 66.00}, { "5", 76.00}, + { "6", 82.00}, { "7", 174.00}, { "8", 180.00}, { "9", 186.00}, { "10", 192.00}, + { "11", 198.00}, { "12", 204.00}, { "13", 210.00}, { "A", 120.00}, { "B", 126.00}, + { "C", 132.00}, { "D", 138.00}, { "E", 144.00}, { "F", 150.00}, { "G", 156.00}, + { "H", 162.00}, { "I", 168.00}, { "J", 216.00}, { "K", 222.00}, { "L", 228.00}, + { "M", 234.00}, { "N", 240.00}, { "O", 246.00}, { "P", 252.00}, { "Q", 258.00}, + { "R", 264.00}, { "S", 270.00}, { "T", 276.00}, { "U", 282.00}, { "V", 288.00}, + { "W", 294.00}, { "W+1", 300.00}, { "W+2", 306.00}, { "W+3", 312.00}, { "W+4", 318.00}, + { "W+5", 324.00}, { "W+6", 330.00}, { "W+7", 336.00}, { "W+8", 342.00}, { "W+9", 348.00}, + { "W+10", 354.00}, { "W+11", 360.00}, { "W+12", 366.00}, { "W+13", 372.00}, { "W+14", 378.00}, + { "W+15", 384.00}, { "W+16", 390.00}, { "W+17", 396.00}, { "W+18", 402.00}, { "W+19", 408.00}, + { "W+20", 414.00}, { "W+21", 420.00}, { "W+22", 426.00}, { "W+23", 432.00}, { "W+24", 438.00}, + { "W+25", 444.00}, { "W+26", 450.00}, { "W+27", 456.00}, { "W+28", 462.00}, { "65", 468.00}, + { "66", 474.00}, { "67", 480.00}, { "68", 486.00}, { "69", 492.00}, { "70", 498.00}, + { "71", 504.00}, { "72", 510.00}, { "73", 516.00}, { "74", 522.00}, { "75", 528.00}, + { "76", 534.00}, { "77", 540.00}, { "78", 546.00}, { "79", 552.00}, { "80", 558.00}, + { "81", 564.00}, { "82", 570.00}, { "83", 576.00}, { "84", 582.00}, { "85", 588.00}, + { "86", 594.00}, { "87", 600.00}, { "88", 606.00}, { "89", 612.00}, { "90", 618.00}, + { "91", 624.00}, { "92", 630.00}, { "93", 636.00}, { "94", 642.00}, { "A­5", 90.00 }, + { "A­4", 96.00 }, { "A­3", 102.00}, { "A­2", 108.00}, { "A-1", 114.00}, { "100", 648.00}, + { "101", 654.00}, { "102", 660.00}, { "103", 666.00}, { "104", 672.00}, { "105", 678.00}, + { "106", 684.00}, { "107", 690.00}, { "108", 696.00}, { "109", 702.00}, { "110", 708.00}, + { "111", 714.00}, { "112", 720.00}, { "113", 726.00}, { "114", 732.00}, { "115", 738.00}, + { "116", 744.00}, { "117", 750.00}, { "118", 756.00}, { "119", 762.00}, { "120", 768.00}, + { "121", 774.00}, { "122", 780.00}, { "123", 786.00}, { "124", 792.00}, { "125", 798.00} }; + +Channel Japan_Air[]={ + { "1", 91.25}, { "2", 97.25}, { "3", 103.25}, { "4", 171.25}, { "5", 177.25}, + { "6", 183.25}, { "7", 189.25}, { "8", 193.25}, { "9", 199.25}, { "10", 205.25}, + { "11", 211.25}, { "12", 217.25}, { "13", 471.25}, { "14", 477.25}, { "15", 483.25}, + { "16", 489.25}, { "17", 495.25}, { "18", 501.25}, { "19", 507.25}, { "20", 513.25}, + { "21", 519.25}, { "22", 525.25}, { "23", 531.25}, { "24", 537.25}, { "25", 543.25}, + { "26", 549.25}, { "27", 555.25}, { "28", 561.25}, { "29", 567.25}, { "30", 573.25}, + { "31", 579.25}, { "32", 585.25}, { "33", 591.25}, { "34", 597.25}, { "35", 603.25}, + { "36", 609.25}, { "37", 615.25}, { "38", 621.25}, { "39", 627.25}, { "40", 633.25}, + { "41", 639.25}, { "42", 645.25}, { "43", 651.25}, { "44", 657.25}, { "45", 663.25}, + { "46", 669.25}, { "47", 675.25}, { "48", 681.25}, { "49", 687.25}, { "50", 693.25}, + { "51", 699.25}, { "52", 705.25}, { "53", 711.25}, { "54", 717.25}, { "55", 723.25}, + { "56", 729.25}, { "57", 735.25}, { "58", 741.25}, { "59", 747.25}, { "60", 753.25}, + { "61", 759.25}, { "62", 765.25} }; + +Channel Japan_Cable[]={ + { "1", 91.25}, { "2", 97.25}, { "3", 103.25}, { "4", 171.25}, { "5", 177.25}, + { "6", 183.25}, { "7", 189.25}, { "8", 193.25}, { "9", 199.25}, { "10", 205.25}, + { "11", 211.25}, { "12", 217.25}, { "C13", 109.25}, { "C14", 115.25}, { "C15", 121.25}, + { "C16", 127.25}, { "C17", 133.25}, { "C18", 139.25}, { "C19", 145.25}, { "C20", 151.25}, + { "C21", 157.25}, { "C22", 165.25}, { "C23", 223.25}, { "C24", 229.25}, { "C25", 235.25}, + { "C26", 241.25}, { "C27", 247.25}, { "C28", 253.25}, { "C29", 259.25}, { "C30", 265.25}, + { "C31", 271.25}, { "C32", 277.25}, { "C33", 293.25}, { "C34", 289.25}, { "C35", 295.25}, + { "C36", 301.25}, { "C37", 307.25}, { "C38", 313.25}, { "C39", 319.25}, { "C40", 325.25}, + { "C41", 331.25}, { "C42", 337.25}, { "C43", 343.25}, { "C44", 349.25}, { "C45", 355.25}, + { "C46", 361.25}, { "C47", 367.25}, { "C48", 373.25}, { "C49", 379.25}, { "C50", 385.25}, + { "C51", 391.25}, { "C52", 397.25}, { "C53", 403.25}, { "C54", 409.25}, { "C55", 415.25}, + { "C56", 421.25}, { "C57", 427.25}, { "C58", 433.25}, { "C59", 439.25}, { "C60", 445.25}, + { "C61", 451.25}, { "C62", 457.25}, { "C63", 463.25} }; + +International_Air +{ + E2 48.25 + E3 55.25 + E4 62.25 + E5 175.25 + E6 182.25 + E7 189.25 + E8 196.25 + E9 203.25 + E10 210.25 + E11 217.25 + E12 224.25 + IA 53.75 + IB 62.25 + IC 82.25 + ID 175.25 + IE 183.25 + IF 192.75 + IG 201.25 + IH 210.25 + 21 471.25 + 22 479.25 + 23 487.25 + 24 495.25 + 25 503.25 + 26 511.25 + 27 519.25 + 28 527.25 + 29 535.25 + + 30 543.25 C30 + 31 551.25 C31 + 32 559.25 C32 + 33 567.25 C33 + 34 575.25 C34 + 35 583.25 C35 + 36 591.25 C36 + 37 599.25 C37 + 38 607.25 C38 + 39 615.25 C39 + 40 623.25 C40 + 41 631.25 C41 + 42 639.25 C42 + 43 647.25 C43 + 44 655.25 C44 + 45 663.25 C45 + 46 671.25 C46 + 47 679.25 C47 + 48 687.25 C48 + 49 695.25 C49 + 50 703.25 C50 + 51 711.25 C51 + 52 719.25 C52 + 53 727.25 C53 + 54 735.25 C54 + 55 743.25 C55 + 56 751.25 C56 + 57 759.25 C57 + 58 767.25 C58 + 59 775.25 C59 + 60 783.25 C60 + 61 791.25 C61 + 62 799.25 C62 + 63 807.25 C63 + 64 815.25 C64 + 65 823.25 C65 + 66 831.25 C66 + 67 839.25 C67 + 68 847.25 C68 + 69 855.25 C69 + E2A 49.75 C70 + AS1 57.25 C71 + AS2 64.25 C72 + AS3 86.25 C73 + AS4 95.25 C74 + AS5 102.25 C75 + AS5A 138.25 + AS10 209.25 + AS11 216.25 + IH1 217.25 + IND2 55.25 + IND3 62.25 + IND4 175.25 + IND5 182.25 + IND6 189.25 + IND7 196.25 + IND8 203.25 + IND9 210.25 + IND10 217.25 + IND11 224.25 + +}; + +International_Cable +{ + Channel Freq + E2 48.25 + E3 55.25 + E4 62.25 + S01 69.25 + S02 76.25 + S03 83.25 + S1 105.25 + + S2 112.25 + S3 119.25 + S4 126.25 + S5 133.25 + S6 140.25 + S7 147.25 + S8 154.25 + S9 161.25 + S10 168.25 + E5 175.25 + E6 182.25 + E7 189.25 + E8 196.25 + E9 203.25 + E10 210.25 + E11 217.25 + E12 224.25 + S11 231.25 + S12 238.25 + S13 245.25 + S14 252.25 + S15 259.25 + S16 266.25 + S17 273.25 + S18 280.25 + S19 287.25 + S20 294.25 + S21 303.25 + S22 311.25 + S23 319.25 + S24 327.25 + S25 335.25 + S26 343.25 + S27 351.25 + S28 359.25 + S29 367.25 + S30 375.25 + S31 383.25 + S32 391.25 + S33 399.25 + S34 407.25 + S35 415.25 + S36 423.25 + S37 431.25 + S38 439.25 + S39 447.25 + S40 455.25 + S41 463.25 +}; + +Channel UK_Air[] = { + { "A", 45.75}, { "B", 53.75}, { "C", 61.75}, { "D", 175.25}, { "E", 183.25}, + { "F", 191.25}, { "G", 199.25}, { "H", 207.25}, { "J", 215.25}, { "C10", 223.25}, + { "C11", 231.25}, { "C13", 247.25}, { "B21", 471.25}, { "B22", 479.25}, { "B23", 487.25}, + { "B24", 495.25}, { "B25", 503.25}, { "B26", 511.25}, { "B27", 519.25}, { "B28", 527.25}, + { "B29", 535.25}, { "B30", 543.25}, { "B31", 551.25}, { "B32", 559.25}, { "B33", 567.25}, + { "B34", 575.25}, { "B35", 583.25}, { "B36", 591.25}, { "B37", 599.25}, { "B38", 607.25}, + { "B39", 615.25}, { "B40", 623.25}, { "B41", 631.25}, { "B42", 639.25}, { "B43", 647.25}, + { "B44", 655.25}, { "B45", 663.25}, { "B46", 671.25}, { "B47", 679.25}, { "B48", 687.25}, + { "B49", 695.25}, { "B50", 703.25}, { "B51", 711.25}, { "B52", 719.25}, { "B53", 727.25}, + { "B54", 735.25}, { "B55", 743.25}, { "B56", 751.25}, { "B57", 759.25}, { "B58", 767.25}, + { "B59", 775.25}, { "B60", 783.25}, { "B61", 791.25}, { "B62", 799.25}, { "B63", 807.25}, + { "B64", 815.25}, { "B65", 823.25}, { "B66", 831.25}, { "B67", 839.25}, { "B68", 847.25}, + { "B69", 855.25}, { "B1", 45.00 }, { "B2", 51.75 }, { "B3", 56.75 }, { "B4", 61.75 }, + { "B5", 66.75 }, { "B6", 179.75}, { "B7", 184.75}, { "B8", 189.75}, { "B9", 194.75}, + { "B10", 199.75}, { "B11", 204.75}, { "B12", 209.75}, { "B13", 214.75}, { "B14", 219.75} }; + +UK_Cable +{ + Channel Freq + A1 47.25 + A2 55.25 + + A3 63.25 + A4 71.25 + A5 79.25 + A6 87.25 + A7 95.25 + A8 103.25 + A9 111.25 + A10 119.25 + A11 127.25 + A12 135.25 + A13 143.25 + A14 151.25 + A15 159.25 + A16 167.25 + A17 175.25 + A18 183.25 + A19 191.25 + A20 199.25 + A21 207.25 + A22 215.25 + A23 223.25 + A24 231.25 + A25 239.25 + A26 247.25 + A27 255.25 + A28 263.25 + A29 271.25 + A30 279.25 + A31 287.25 + A32 295.25 + E2 48.25 + E3 55.25 + E4 62.25 + S01 69.25 + S02 76.25 + S03 83.25 + S1 105.25 + S2 112.25 + S3 119.25 + S4 126.25 + S5 133.25 + S6 140.25 + S7 147.25 + S8 154.25 + S9 161.25 + S10 168.25 + E5 175.25 + E6 182.25 + E7 189.25 + E8 196.25 + E9 203.25 + E10 210.25 + E11 217.25 + E12 224.25 + S11 231.25 + S12 238.25 + S13 245.25 + S14 252.25 + S15 259.25 + S16 266.25 + S17 273.25 + S18 280.25 + S19 287.25 + S20 294.25 + S21 303.25 + S22 311.25 + S23 319.25 + S24 327.25 + S25 335.25 + S26 343.25 + S27 351.25 + S28 359.25 + + S29 367.25 + S30 375.25 + S31 383.25 + S32 391.25 + S33 399.25 + S34 407.25 + S35 415.25 + S36 423.25 + S37 431.25 + S38 439.25 + S39 447.25 + S40 455.25 + S41 463.25 + +}; + +French_Air +{ + Channel Freq + FA 47.75 + L2 49.25 + L3 54.00 + FB 55.75 + L4 57.25 + FC1 60.50 + FC 63.75 + F1 176.00 + F2 184.00 + F3 192.00 + F4 200.00 + F5 208.00 + F6 216.00 + B21 471.25 + B22 479.25 + B23 487.25 + B24 495.25 + B25 503.25 + B26 511.25 + B27 519.25 + B28 527.25 + B29 535.25 + B30 543.25 + B31 551.25 + B32 559.25 + B33 567.25 + B34 575.25 + B35 583.25 + B36 591.25 + B37 599.25 + B38 607.25 + B39 615.25 + B40 623.25 + B41 631.25 + B42 639.25 + B43 647.25 + B44 655.25 + B45 663.25 + B46 671.25 + B47 679.25 + B48 687.25 + B49 695.25 + B50 703.25 + B51 711.25 + B52 719.25 + + + B53 727.25 + B54 735.25 + B55 743.25 + B56 751.25 + B57 759.25 + B58 767.25 + B59 775.25 + B60 783.25 + B61 791.25 + B62 799.25 + B63 807.25 + B64 815.25 + B65 823.25 + B66 831.25 + B67 839.25 + B68 847.25 + B69 855.25 + +}; + +French_Cable +{ + Channel Freq + E2 48.25 + E3 55.25 + E4 62.25 + S01 69.25 + S02 76.25 + S03 83.25 + S1 105.25 + S2 112.25 + S3 119.25 + S4 126.25 + S5 133.25 + S6 140.25 + S7 147.25 + S8 154.25 + S9 161.25 + S10 168.25 + E5 175.25 + E6 182.25 + E7 189.25 + E8 196.25 + E9 203.25 + E10 210.25 + E11 217.25 + E12 224.25 + S11 231.25 + S12 238.25 + S13 245.25 + S14 252.25 + S15 259.25 + S16 266.25 + S17 273.25 + S18 280.25 + S19 287.25 + S20 294.25 + S21 303.25 + S22 311.25 + S23 319.25 + S24 327.25 + S25 335.25 + S26 343.25 + S27 351.25 + S28 359.25 + S29 367.25 + S30 375.25 + S31 383.25 + S32 391.25 + S33 399.25 + S34 407.25 + S35 415.25 + S36 423.25 + + S37 431.25 + S38 439.25 + S39 447.25 + S40 455.25 + S41 463.25 + +}; + +Channel Channels_FMRadio[] = { +/*???*/ +}; + +Channel Channels_UKW_Radio[] = { +/*???*/ +}; + +Channel Channels_xUSSR_Air[] = { + {"1", 49.75}, {"2", 59.25}, {"3", 77.25}, {"4", 85.25}, {"5", 93.25}, + {"6", 175.25}, {"7", 183.25}, {"8", 191.25}, {"9", 199.25}, {"10", 207.25}, + {"11", 215.25}, {"12", 223.25}, + {"21", 471.25}, {"22", 479.25}, {"23", 487.25}, {"24", 495.25}, {"25", 503.25}, + {"26", 511.25}, {"27", 519.25}, {"28", 527.25}, {"29", 535.25}, {"30", 543.25}, + {"31", 551.25}, {"32", 559.25}, {"33", 567.25}, {"34", 575.25}, {"35", 583.25}, + {"36", 591.25}, {"37", 599.25}, {"38", 607.25}, {"39", 615.25}, {"40", 623.25}, + {"41", 631.25}, {"42", 639.25}, {"43", 647.25}, {"44", 655.25}, {"45", 663.25}, + {"46", 671.25}, {"47", 679.25}, {"48", 687.25}, {"49", 695.25}, {"50", 703.25}, + {"51", 711.25}, {"52", 719.25}, {"53", 727.25}, {"54", 735.25}, {"55", 743.25}, + {"56", 751.25}, {"57", 759.25}, {"58", 767.25}, {"59", 775.25}, {"60", 783.25}, + {"61", 791.25}, {"62", 799.25}, {"63", 807.25}, {"64", 815.25}, {"65", 823.25}, + {"66", 831.25}, {"67", 839.25}, {"68", 847.25}, {"69", 855.25}}; + +Channel Channels_xUSSR_Cable[] = { + {"70", 111.25}, {"71", 119.25}, {"72", 127.25}, {"73", 135.25}, {"74", 143.25}, + {"75", 141.25}, {"76", 159.25}, {"77", 167.25}, {"78", 231.25}, {"79", 239.25}, + {"80", 247.25}, {"81", 255.25}, {"82", 263.25}, {"83", 271.25}, {"84", 279.25}, + {"85", 287.25}, {"86", 295.25}, {"87", 303.25}, {"88", 311.25}, {"89", 319.25}, + {"90", 327.25}, {"91", 335.25}, {"92", 343.25}, {"93", 351.25}, {"94", 359.25}, + {"95", 367.25}, {"96", 375.25}, {"97", 383.25}, {"98", 391.25}, {"99", 399.25}, + {"100", 407.25}, {"101", 415.25}, {"102", 423.25}, {"103", 431.25}, {"104", 439.25}, + {"105", 447.25}, {"106", 455.25}, {"107", 463.25} }; + +Channel Channels_EuropeAir[] = { + {"", }, {"", }, {"", }, {"", }, {"", }, {"", }, +}; + +Channel Channels_EuropeCable[] = { + {"", }, {"", }, {"", }, {"", }, {"", }, {"", }, +}; + +Channel Channels_AustraliaAir[] = { + { "0", 46.25}, { "1", 57.25}, { "2", 64.25}, { "3", 86.25}, { "4", 95.25}, + { "5", 102.25}, { "5A", 138.25}, { "6", 175.25}, { "7", 182.25}, { "8", 189.25}, + { "9", 196.25}, { "10", 209.25}, { "11", 216.25}, { "28", 527.25}, { "29", 534.25}, + { "30", 541.25}, { "31", 548.25}, { "32", 555.25}, { "33", 562.25}, { "34", 569.25}, + { "35", 576.25}, { "39", 604.25}, { "40", 611.25}, { "41", 618.25}, { "42", 625.25}, + { "43", 632.25}, { "44", 639.25}, { "45", 646.25}, { "46", 653.25}, { "47", 660.25}, + { "48", 667.25}, { "49", 674.25}, { "50", 681.25}, { "51", 688.25}, { "52", 695.25}, + { "53", 702.25}, { "54", 709.25}, { "55", 716.25}, { "56", 723.25}, { "57", 730.25}, + { "58", 737.25}, { "59", 744.25}, { "60", 751.25}, { "61", 758.25}, { "62", 765.25}, + { "63", 772.25}, { "64", 779.25}, { "65", 786.25}, { "66", 793.25}, { "67", 800.25}, + { "68", 807.25}, { "69", 814.25} }; + +Channel Channels_IrelandAir[] = { + +}; diff --git a/src/add-ons/media/media-add-ons/usb_vision/Jamfile b/src/add-ons/media/media-add-ons/usb_vision/Jamfile new file mode 100644 index 0000000000..52088512de --- /dev/null +++ b/src/add-ons/media/media-add-ons/usb_vision/Jamfile @@ -0,0 +1,13 @@ +SubDir HAIKU_TOP src add-ons media media-add-ons usb_vision ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +UsePrivateHeaders usb_vision ; + +Addon usb_vision.media_addon : media : + AddOn.cpp + Producer.cpp + TunerLocale.cpp +; + +LinkAgainst usb_vision.media_addon : be media $(TARGET_LIBSTDC++) ; diff --git a/src/add-ons/media/media-add-ons/usb_vision/Producer.cpp b/src/add-ons/media/media-add-ons/usb_vision/Producer.cpp new file mode 100644 index 0000000000..5582de3f18 --- /dev/null +++ b/src/add-ons/media/media-add-ons/usb_vision/Producer.cpp @@ -0,0 +1,1173 @@ +/* + * This file is a part of BeOS USBVision driver project. + * Copyright (c) 2003 by Siarzuk Zharski + * + * This file may be used under the terms of the BSD License + * + * Skeletal part of this code was inherired from original BeOS sample code, + * that is distributed under the terms of the Be Sample Code License. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#define TOUCH(x) ((void)(x)) + +#define PRINTF(a,b) \ + do { \ + if (a < 2) { \ + printf("VideoProducer::"); \ + printf b; \ + } \ + } while (0) + +#include "Producer.h" + +#define FIELD_RATE 30.f + +const float kUSBBandWidthMin = 0.5f; +const float kUSBBandWidthMax = 7.5f; +const float kUSBBandWidthStep = 0.5f; + +const float kVScreenOffsetMin = 0.f; +const float kVScreenOffsetMax = 4.f; +const float kVScreenOffsetStep = 1.f; +const float kHScreenOffsetMin = 0.f; +const float kHScreenOffsetMax = 4.f; +const float kHScreenOffsetStep = 1.f; + +const float kEffectMin = 0.f; +const float kEffectMax = 31.f; +const float kEffectStep = 1.f; + +const float kBrightnessMin = kEffectMin; +const float kBrightnessMax = kEffectMax; +const float kBrightnessStep = kEffectStep; + +const float kContrastMin = kEffectMin; +const float kContrastMax = kEffectMax; +const float kContrastStep = kEffectStep; + +const float kHueMin = kEffectMin; +const float kHueMax = kEffectMax; +const float kHueStep = kEffectStep; + +const float kSaturationMin = kEffectMin; +const float kSaturationMax = kEffectMax; +const float kSaturationStep = kEffectStep; + +const uint32 kDefChannel = 0; +//const VideoInput kDefVideoInput = P_VI_TUNER; +const uint32 kDefAudioInput = 0; +const uint32 kDefBrightness = 20; +const uint32 kDefContrast = 22; +const uint32 kDefSaturation = 15; +const uint32 kDefHue = 20; +const uint32 kDefCaptureSize = 0; +const uint32 kDefCaptureFormat = 0; +//const VideoStandard kDefStandard = P_VF_PAL_BDGHI; +const float kDefBandwidth = 7.0; +const uint32 kDefLocale = 0; +const uint32 kDefVertOffset = 1; +const uint32 kDefHorzOffset = 2; + +int32 VideoProducer::fInstances = 0; + +VideoProducer::VideoProducer( + BMediaAddOn *addon, const char *name, int32 internal_id) + : BMediaNode(name), + BMediaEventLooper(), + BBufferProducer(B_MEDIA_RAW_VIDEO), + BControllable() +{ + status_t err; + + fInitStatus = B_NO_INIT; + + /* Only allow one instance of the node to exist at any time */ + if (atomic_add(&fInstances, 1) != 0) + return; + + fInternalID = internal_id; + fAddOn = addon; + + fBufferGroup = NULL; + + fThread = -1; + fFrameSync = -1; + fProcessingLatency = 0LL; + + fRunning = false; + fConnected = false; + fEnabled = false; + + fOutput.destination = media_destination::null; + + AddNodeKind(B_PHYSICAL_INPUT); + + fInitStatus = B_OK; + + //debugger("op-op"); + + status_t status = Locale::TunerLocale::LoadLocales(fLocales); + + printf("LoadLocales:%08x\n", status); + + fChannel = kDefChannel; + fVideoInput = P_VI_TUNER; + fAudioInput = kDefAudioInput; + fBrightness = kDefBrightness; + fContrast = kDefContrast; + fSaturation = kDefSaturation; + fHue = kDefHue; + fCaptureSize = kDefCaptureSize; + fCaptureFormat = kDefCaptureFormat; + fStandard = P_VF_PAL_BDGHI; + fLocale = kDefLocale; + fBandwidth = kDefBandwidth; + fVertOffset = kDefVertOffset; + fHorzOffset = kDefHorzOffset; + fColor = B_HOST_TO_LENDIAN_INT32(0x00ff0000); + + fLastChannelChange = + fLastVideoInputChange = + fLastAudioInputChange = + fLastBrightnessChange = + fLastContrastChange = + fLastSaturationChange = + fLastHueChange = + fLastCaptureSizeChange = + fLastCaptureFormatChange = + fLastStandardChange = + fLastLocaleChange = + fLastBandwidthChange = + fLastVertOffsetChange = + fLastHorzOffsetChange = + fLastColorChange = system_time(); + + return; +} + +VideoProducer::~VideoProducer() +{ + if (fInitStatus == B_OK) { + /* Clean up after ourselves, in case the application didn't make us + * do so. */ + if (fConnected) + Disconnect(fOutput.source, fOutput.destination); + if (fRunning) + HandleStop(); + } + + atomic_add(&fInstances, -1); + + Locale::TunerLocale::ReleaseLocales(fLocales); +} + +/* BMediaNode */ + +port_id +VideoProducer::ControlPort() const +{ + return BMediaNode::ControlPort(); +} + +BMediaAddOn * +VideoProducer::AddOn(int32 *internal_id) const +{ + if (internal_id) + *internal_id = fInternalID; + return fAddOn; +} + +status_t +VideoProducer::HandleMessage(int32 message, const void *data, size_t size) +{ + return B_ERROR; +} + +void +VideoProducer::Preroll() +{ + /* This hook may be called before the node is started to give the hardware + * a chance to start. */ +} + +void +VideoProducer::SetTimeSource(BTimeSource *time_source) +{ + /* Tell frame generation thread to recalculate delay value */ + release_sem(fFrameSync); +} + +status_t +VideoProducer::RequestCompleted(const media_request_info &info) +{ + return BMediaNode::RequestCompleted(info); +} + +/* BMediaEventLooper */ + +void +VideoProducer::NodeRegistered() +{ + if (fInitStatus != B_OK) { + ReportError(B_NODE_IN_DISTRESS); + return; + } + + /* After this call, the BControllable owns the BParameterWeb object and + * will delete it for you */ + SetParameterWeb(CreateParameterWeb()); + + fOutput.node = Node(); + fOutput.source.port = ControlPort(); + fOutput.source.id = 0; + fOutput.destination = media_destination::null; + strcpy(fOutput.name, Name()); + + /* Tailor these for the output of your device */ + fOutput.format.type = B_MEDIA_RAW_VIDEO; + fOutput.format.u.raw_video = media_raw_video_format::wildcard; + fOutput.format.u.raw_video.interlace = 1; + fOutput.format.u.raw_video.display.format = B_RGB32; + + /* Start the BMediaEventLooper control loop running */ + Run(); +} + +BParameterWeb *VideoProducer::CreateParameterWeb() +{ + /* Set up the parameter web */ + BParameterWeb *web = new BParameterWeb(); + + BParameterGroup *controls = web->MakeGroup("Controls"); + BParameterGroup *group = controls->MakeGroup("Main Controls"); + BDiscreteParameter *parameter = group->MakeDiscreteParameter( + P_CHANNEL, B_MEDIA_NO_TYPE, "Channel:", B_GENERIC); + for(int i = 0; i < fLocales[fLocale]->ChannelsCount(); i ++){ + parameter->AddItem(i, (fLocales[fLocale]->GetChannel(i)).Name().c_str()); + } + + parameter = group->MakeDiscreteParameter( + P_VIDEO_INPUT, B_MEDIA_NO_TYPE, "Video Input:", B_INPUT_MUX); + parameter->AddItem(P_VI_TUNER, "Tuner"); + parameter->AddItem(P_VI_COMPOSITE, "Composite"); + parameter->AddItem(P_VI_SVIDEO, "SVideo"); + + parameter = group->MakeDiscreteParameter( + P_AUDIO_INPUT, B_MEDIA_NO_TYPE, "Audio Input:", B_INPUT_MUX); + parameter->AddItem(1, "TODO"); + parameter->AddItem(2, "TODO"); + parameter->AddItem(3, "TODO"); + + group = controls->MakeGroup("Effect Controls"); + group->MakeContinuousParameter( + P_BRIGHTNESS, B_MEDIA_NO_TYPE, "Brightness", B_LEVEL, + "", kBrightnessMin, kBrightnessMax, kBrightnessStep); + + group->MakeContinuousParameter( + P_CONTRAST, B_MEDIA_NO_TYPE, "Contrast", B_LEVEL, + "", kContrastMin, kContrastMax, kContrastStep); + + group = controls->MakeGroup("Adv. Effect Controls"); + group->MakeContinuousParameter( + P_SATURATION, B_MEDIA_NO_TYPE, "Saturation", B_LEVEL, + "", kSaturationMin, kSaturationMax, kSaturationStep); + + group->MakeContinuousParameter( + P_HUE, B_MEDIA_NO_TYPE, "Hue", B_LEVEL, + "", kHueMin, kHueMax, kHueStep); + + BParameterGroup *options = web->MakeGroup("Options"); + group = options->MakeGroup("Capture Option"); + parameter = group->MakeDiscreteParameter( + P_CAPTURE_SIZE, B_MEDIA_NO_TYPE, "Capture Size:", B_RESOLUTION); + parameter->AddItem(1, "TODO"); + parameter->AddItem(2, "TODO"); + + parameter = group->MakeDiscreteParameter( + P_CAPTURE_FORMAT, B_MEDIA_NO_TYPE, "Capture Format:", B_COLOR_SPACE); + parameter->AddItem(1, "TODO"); + parameter->AddItem(2, "TODO"); + + BParameterGroup *hardware = web->MakeGroup("Hardware Setup"); + group = hardware->MakeGroup("Format"); + parameter = group->MakeDiscreteParameter( + P_STANDART, B_MEDIA_NO_TYPE, "Video Format:", B_VIDEO_FORMAT); + parameter->AddItem(P_VF_NTSC_M, "NTSC M"); + parameter->AddItem(P_VF_NTSC_MJ, "NTSC MJ"); + parameter->AddItem(P_VF_PAL_BDGHI, "PAL BDGHI"); + parameter->AddItem(P_VF_PAL_M, "PAL M"); + parameter->AddItem(P_VF_PAL_N, "PAL N"); + parameter->AddItem(P_VF_SECAM, "SECAM"); + + parameter = group->MakeDiscreteParameter( + P_LOCALE, B_MEDIA_NO_TYPE, "Tuner Locale:", B_GENERIC); + for(int i = 0; i < fLocales.size(); i++) + parameter->AddItem(i, fLocales[i]->Name().c_str()); + + group = hardware->MakeGroup("Format"); + + group->MakeContinuousParameter( + P_BANDWIDTH, B_MEDIA_NO_TYPE, "Max.Bandwidth", B_LEVEL, + "", kUSBBandWidthMin, kUSBBandWidthMax, kUSBBandWidthStep); + + group = hardware->MakeGroup("Offsets"); + + group->MakeContinuousParameter( + P_VERT_OFFSET, B_MEDIA_NO_TYPE, "Vertical Offset", B_LEVEL, + "", kVScreenOffsetMin, kVScreenOffsetMax, kVScreenOffsetStep); + + group->MakeContinuousParameter( + P_HORZ_OFFSET, B_MEDIA_NO_TYPE, "Horizontal Offset", B_LEVEL, + "", kHScreenOffsetMin, kHScreenOffsetMax, kHScreenOffsetStep); + + BParameterGroup *main = web->MakeGroup(Name()); + BDiscreteParameter *state = main->MakeDiscreteParameter( + P_COLOR, B_MEDIA_RAW_VIDEO, "Color", "Color"); + state->AddItem(B_HOST_TO_LENDIAN_INT32(0x00ff0000), "Red"); + state->AddItem(B_HOST_TO_LENDIAN_INT32(0x0000ff00), "Green"); + state->AddItem(B_HOST_TO_LENDIAN_INT32(0x000000ff), "Blue"); + + return web; +} + +void +VideoProducer::Start(bigtime_t performance_time) +{ + BMediaEventLooper::Start(performance_time); +} + +void +VideoProducer::Stop(bigtime_t performance_time, bool immediate) +{ + BMediaEventLooper::Stop(performance_time, immediate); +} + +void +VideoProducer::Seek(bigtime_t media_time, bigtime_t performance_time) +{ + BMediaEventLooper::Seek(media_time, performance_time); +} + +void +VideoProducer::TimeWarp(bigtime_t at_real_time, bigtime_t to_performance_time) +{ + BMediaEventLooper::TimeWarp(at_real_time, to_performance_time); +} + +status_t +VideoProducer::AddTimer(bigtime_t at_performance_time, int32 cookie) +{ + return BMediaEventLooper::AddTimer(at_performance_time, cookie); +} + +void +VideoProducer::SetRunMode(run_mode mode) +{ + BMediaEventLooper::SetRunMode(mode); +} + +void +VideoProducer::HandleEvent(const media_timed_event *event, + bigtime_t lateness, bool realTimeEvent) +{ + TOUCH(lateness); TOUCH(realTimeEvent); + + switch(event->type) + { + case BTimedEventQueue::B_START: + HandleStart(event->event_time); + break; + case BTimedEventQueue::B_STOP: + HandleStop(); + break; + case BTimedEventQueue::B_WARP: + HandleTimeWarp(event->bigdata); + break; + case BTimedEventQueue::B_SEEK: + HandleSeek(event->bigdata); + break; + case BTimedEventQueue::B_PARAMETER: + HandleParameter(event->data); + break; + case BTimedEventQueue::B_HANDLE_BUFFER: + case BTimedEventQueue::B_DATA_STATUS: + default: + PRINTF(-1, ("HandleEvent: Unhandled event -- %lx\n", event->type)); + break; + } +} + +void +VideoProducer::CleanUpEvent(const media_timed_event *event) +{ + BMediaEventLooper::CleanUpEvent(event); +} + +bigtime_t +VideoProducer::OfflineTime() +{ + return BMediaEventLooper::OfflineTime(); +} + +void +VideoProducer::ControlLoop() +{ + BMediaEventLooper::ControlLoop(); +} + +status_t +VideoProducer::DeleteHook(BMediaNode * node) +{ + return BMediaEventLooper::DeleteHook(node); +} + +/* BBufferProducer */ + +status_t +VideoProducer::FormatSuggestionRequested( + media_type type, int32 quality, media_format *format) +{ + if (type != B_MEDIA_ENCODED_VIDEO) + return B_MEDIA_BAD_FORMAT; + + TOUCH(quality); + + *format = fOutput.format; + return B_OK; +} + +status_t +VideoProducer::FormatProposal(const media_source &output, media_format *format) +{ + status_t err; + + if (!format) + return B_BAD_VALUE; + + if (output != fOutput.source) + return B_MEDIA_BAD_SOURCE; + + err = format_is_compatible(*format, fOutput.format) ? + B_OK : B_MEDIA_BAD_FORMAT; + *format = fOutput.format; + return err; + +} + +status_t +VideoProducer::FormatChangeRequested(const media_source &source, + const media_destination &destination, media_format *io_format, + int32 *_deprecated_) +{ + TOUCH(destination); TOUCH(io_format); TOUCH(_deprecated_); + if (source != fOutput.source) + return B_MEDIA_BAD_SOURCE; + + return B_ERROR; +} + +status_t +VideoProducer::GetNextOutput(int32 *cookie, media_output *out_output) +{ + if (!out_output) + return B_BAD_VALUE; + + if ((*cookie) != 0) + return B_BAD_INDEX; + + *out_output = fOutput; + (*cookie)++; + return B_OK; +} + +status_t +VideoProducer::DisposeOutputCookie(int32 cookie) +{ + TOUCH(cookie); + + return B_OK; +} + +status_t +VideoProducer::SetBufferGroup(const media_source &for_source, + BBufferGroup *group) +{ + TOUCH(for_source); TOUCH(group); + + return B_ERROR; +} + +status_t +VideoProducer::VideoClippingChanged(const media_source &for_source, + int16 num_shorts, int16 *clip_data, + const media_video_display_info &display, int32 *_deprecated_) +{ + TOUCH(for_source); TOUCH(num_shorts); TOUCH(clip_data); + TOUCH(display); TOUCH(_deprecated_); + + return B_ERROR; +} + +status_t +VideoProducer::GetLatency(bigtime_t *out_latency) +{ + *out_latency = EventLatency() + SchedulingLatency(); + return B_OK; +} + +status_t +VideoProducer::PrepareToConnect(const media_source &source, + const media_destination &destination, media_format *format, + media_source *out_source, char *out_name) +{ + status_t err; + + PRINTF(1, ("PrepareToConnect() %ldx%ld\n", \ + format->u.raw_video.display.line_width, \ + format->u.raw_video.display.line_count)); + + if (fConnected) { + PRINTF(0, ("PrepareToConnect: Already connected\n")); + return EALREADY; + } + + if (source != fOutput.source) + return B_MEDIA_BAD_SOURCE; + + if (fOutput.destination != media_destination::null) + return B_MEDIA_ALREADY_CONNECTED; + + /* The format parameter comes in with the suggested format, and may be + * specialized as desired by the node */ + if (!format_is_compatible(*format, fOutput.format)) { + *format = fOutput.format; + return B_MEDIA_BAD_FORMAT; + } + + if (format->u.raw_video.display.line_width == 0) + format->u.raw_video.display.line_width = 320; + if (format->u.raw_video.display.line_count == 0) + format->u.raw_video.display.line_count = 240; + if (format->u.raw_video.field_rate == 0) + format->u.raw_video.field_rate = 29.97f; + + *out_source = fOutput.source; + strcpy(out_name, fOutput.name); + + fOutput.destination = destination; + + return B_OK; +} + +void +VideoProducer::Connect(status_t error, const media_source &source, + const media_destination &destination, const media_format &format, + char *io_name) +{ + PRINTF(1, ("Connect() %ldx%ld\n", \ + format.u.raw_video.display.line_width, \ + format.u.raw_video.display.line_count)); + + if (fConnected) { + PRINTF(0, ("Connect: Already connected\n")); + return; + } + + if ( (source != fOutput.source) || (error < B_OK) || + !const_cast(&format)->Matches(&fOutput.format)) { + PRINTF(1, ("Connect: Connect error\n")); + return; + } + + fOutput.destination = destination; + strcpy(io_name, fOutput.name); + + if (fOutput.format.u.raw_video.field_rate != 0.0f) { + fPerformanceTimeBase = fPerformanceTimeBase + + (bigtime_t) + ((fFrame - fFrameBase) * + (1000000 / fOutput.format.u.raw_video.field_rate)); + fFrameBase = fFrame; + } + + fConnectedFormat = format.u.raw_video; + + /* get the latency */ + bigtime_t latency = 0; + media_node_id tsID = 0; + FindLatencyFor(fOutput.destination, &latency, &tsID); + #define NODE_LATENCY 1000 + SetEventLatency(latency + NODE_LATENCY); + + uint32 *buffer, *p, f = 3; + p = buffer = (uint32 *)malloc(4 * fConnectedFormat.display.line_count * + fConnectedFormat.display.line_width); + if (!buffer) { + PRINTF(0, ("Connect: Out of memory\n")); + return; + } + bigtime_t now = system_time(); + for (int y=0;yInitCheck() < B_OK) { + delete fBufferGroup; + fBufferGroup = NULL; + return; + } + + fConnected = true; + fEnabled = true; + + /* Tell frame generation thread to recalculate delay value */ + release_sem(fFrameSync); +} + +void +VideoProducer::Disconnect(const media_source &source, + const media_destination &destination) +{ + PRINTF(1, ("Disconnect()\n")); + + if (!fConnected) { + PRINTF(0, ("Disconnect: Not connected\n")); + return; + } + + if ((source != fOutput.source) || (destination != fOutput.destination)) { + PRINTF(0, ("Disconnect: Bad source and/or destination\n")); + return; + } + + fEnabled = false; + fOutput.destination = media_destination::null; + + fLock.Lock(); + delete fBufferGroup; + fBufferGroup = NULL; + fLock.Unlock(); + + fConnected = false; +} + +void +VideoProducer::LateNoticeReceived(const media_source &source, + bigtime_t how_much, bigtime_t performance_time) +{ + TOUCH(source); TOUCH(how_much); TOUCH(performance_time); +} + +void +VideoProducer::EnableOutput(const media_source &source, bool enabled, + int32 *_deprecated_) +{ + TOUCH(_deprecated_); + + if (source != fOutput.source) + return; + + fEnabled = enabled; +} + +status_t +VideoProducer::SetPlayRate(int32 numer, int32 denom) +{ + TOUCH(numer); TOUCH(denom); + + return B_ERROR; +} + +void +VideoProducer::AdditionalBufferRequested(const media_source &source, + media_buffer_id prev_buffer, bigtime_t prev_time, + const media_seek_tag *prev_tag) +{ + TOUCH(source); TOUCH(prev_buffer); TOUCH(prev_time); TOUCH(prev_tag); +} + +void +VideoProducer::LatencyChanged(const media_source &source, + const media_destination &destination, bigtime_t new_latency, + uint32 flags) +{ + TOUCH(source); TOUCH(destination); TOUCH(new_latency); TOUCH(flags); +} + +/* BControllable */ + +status_t +VideoProducer::GetParameterValue( + int32 id, bigtime_t *last_change, void *value, size_t *size) +{ + switch(id){ + case P_CHANNEL: + *last_change = fLastChannelChange; + *size = sizeof(uint32); + *((uint32*)value) = fChannel; + break; + case P_VIDEO_INPUT: + *last_change = fLastVideoInputChange; + *size = sizeof(uint32); + *((uint32*)value) = fVideoInput; + break; + case P_AUDIO_INPUT: + *last_change = fLastAudioInputChange; + *size = sizeof(uint32); + *((uint32*)value) = fAudioInput; + break; + case P_BRIGHTNESS: + *last_change = fLastBrightnessChange; + *size = sizeof(float); + *((float *)value) = fBrightness; + break; + case P_CONTRAST: + *last_change = fLastContrastChange; + *size = sizeof(float); + *((float*)value) = fContrast; + break; + case P_SATURATION: + *last_change = fLastSaturationChange; + *size = sizeof(float); + *((float*)value) = fSaturation; + break; + case P_HUE: + *last_change = fLastHueChange; + *size = sizeof(float); + *((float*)value) = fHue; + break; + case P_CAPTURE_SIZE: + *last_change = fLastCaptureSizeChange; + *size = sizeof(uint32); + *((uint32*)value) = fCaptureSize; + break; + case P_CAPTURE_FORMAT: + *last_change = fLastCaptureFormatChange; + *size = sizeof(uint32); + *((uint32*)value) = fCaptureFormat; + break; + case P_STANDART: + *last_change = fLastStandardChange; + *size = sizeof(uint32); + *((uint32*)value) = fStandard; + break; + case P_BANDWIDTH: + *last_change = fLastBandwidthChange; + *size = sizeof(float); + *((float *)value) = fBandwidth; + break; + case P_LOCALE: + *last_change = fLastLocaleChange; + *size = sizeof(uint32); + *((uint32*)value) = fLocale; + break; + case P_VERT_OFFSET: + *last_change = fLastVertOffsetChange; + *size = sizeof(float); + *((float*)value) = fVertOffset; + break; + case P_HORZ_OFFSET: + *last_change = fLastHorzOffsetChange; + *size = sizeof(float); + *((float*)value) = fHorzOffset; + break; + case P_COLOR: + *last_change = fLastColorChange; + *size = sizeof(uint32); + *((uint32 *)value) = fColor; + break; + default: + return B_BAD_VALUE; + } + return B_OK; +} + +void +VideoProducer::SetParameterValue( + int32 id, bigtime_t when, const void *value, size_t size) +{ + switch(id){ + case P_CHANNEL: + if (*(uint32 *)value != fChannel){ + fChannel = *(uint32 *)value; + fLastChannelChange = when; + BroadcastNewParameterValue( + fLastChannelChange, P_CHANNEL, &fChannel, sizeof(fChannel)); + } + break; + case P_VIDEO_INPUT: + if (*(uint32 *)value != fVideoInput){ + fVideoInput = *(uint32 *)value; + fLastVideoInputChange = when; + BroadcastNewParameterValue( + fLastVideoInputChange, P_VIDEO_INPUT, &fVideoInput, sizeof(fVideoInput)); + } + break; + case P_AUDIO_INPUT: + if (*(uint32 *)value != fAudioInput){ + fAudioInput = *(uint32 *)value; + fLastAudioInputChange = when; + BroadcastNewParameterValue( + fLastAudioInputChange, P_AUDIO_INPUT, &fAudioInput, sizeof(fAudioInput)); + } + break; + case P_BRIGHTNESS: + if (*(float *)value != fBrightness){ + fBrightness = *(float *)value; + fLastBrightnessChange = when; + BroadcastNewParameterValue( + fLastBrightnessChange, P_BRIGHTNESS, &fBrightness, sizeof(fBrightness)); + } + break; + case P_CONTRAST: + if (*(float *)value != fContrast){ + fContrast = *(float *)value; + fLastContrastChange = when; + BroadcastNewParameterValue( + fLastContrastChange, P_CONTRAST, &fContrast, sizeof(fContrast)); + } + break; + case P_SATURATION: + if (*(float *)value != fSaturation){ + fSaturation = *(float *)value; + fLastSaturationChange = when; + BroadcastNewParameterValue( + fLastSaturationChange, P_SATURATION, &fSaturation, sizeof(fSaturation)); + } + break; + case P_HUE: + if (*(float *)value != fHue){ + fHue = *(float *)value; + fLastHueChange = when; + BroadcastNewParameterValue( + fLastHueChange, P_HUE, &fHue, sizeof(fHue)); + } + break; + case P_CAPTURE_SIZE: + if (*(uint32 *)value != fCaptureSize){ + fCaptureSize = *(uint32*)value; + fLastCaptureSizeChange = when; + BroadcastNewParameterValue( + fLastCaptureSizeChange, P_CAPTURE_SIZE, &fCaptureSize, sizeof(fCaptureSize)); + } + break; + case P_CAPTURE_FORMAT: + if (*(uint32 *)value != fCaptureFormat){ + fCaptureFormat = *(uint32*)value; + fLastCaptureFormatChange = when; + BroadcastNewParameterValue( + fLastCaptureFormatChange, P_CAPTURE_FORMAT, &fCaptureFormat, sizeof(fCaptureFormat)); + } + break; + case P_STANDART: + if (*(uint32 *)value != fStandard){ + fStandard = *(uint32*)value; + fLastStandardChange = when; + BroadcastNewParameterValue( + fLastStandardChange, P_STANDART, &fStandard, sizeof(fStandard)); + } + break; + case P_BANDWIDTH: + if (*(float *)value != fBandwidth){ + fBandwidth = *(float *)value; + fLastBandwidthChange = when; + BroadcastNewParameterValue( + fLastBandwidthChange, P_BANDWIDTH, &fBandwidth, sizeof(fBandwidth)); + } + break; + case P_LOCALE: + if (*(uint32 *)value != fLocale){ + fLocale = *(uint32 *)value; + fLastLocaleChange = when; + BroadcastNewParameterValue( + fLastLocaleChange, P_LOCALE, &fLocale, sizeof(fLocale)); + } + break; + case P_VERT_OFFSET: + if (*(float*)value != fVertOffset){ + fVertOffset = *(float *)value; + fLastVertOffsetChange = when; + BroadcastNewParameterValue( + fLastVertOffsetChange, P_VERT_OFFSET, &fVertOffset, sizeof(fVertOffset)); + } + break; + case P_HORZ_OFFSET: + if (*(float*)value != fHorzOffset){ + fHorzOffset = *(float *)value; + fLastHorzOffsetChange = when; + BroadcastNewParameterValue( + fLastHorzOffsetChange, P_HORZ_OFFSET, &fHorzOffset, sizeof(fHorzOffset)); + } + break; + case P_COLOR: + if (*(int32 *)value != fColor){ + fColor = *(uint32 *)value; + fLastColorChange = when; + BroadcastNewParameterValue( + fLastColorChange, P_COLOR, &fColor, sizeof(fColor)); + } + break; + } + + EventQueue()->AddEvent(media_timed_event(when, + BTimedEventQueue::B_PARAMETER, NULL, + BTimedEventQueue::B_NO_CLEANUP, id, 0, NULL, 0)); + +} + +status_t +VideoProducer::StartControlPanel(BMessenger *out_messenger) +{ + return BControllable::StartControlPanel(out_messenger); +} + +/* VideoProducer */ + +void +VideoProducer::HandleStart(bigtime_t performance_time) +{ + /* Start producing frames, even if the output hasn't been connected yet. */ + + PRINTF(1, ("HandleStart(%Ld)\n", performance_time)); + + if (fRunning) { + PRINTF(-1, ("HandleStart: Node already started\n")); + return; + } + + fFrame = 0; + fFrameBase = 0; + fPerformanceTimeBase = performance_time; + + fFrameSync = create_sem(0, "frame synchronization"); + if (fFrameSync < B_OK) + goto err1; + + fThread = spawn_thread(_frame_generator_, "frame generator", + B_NORMAL_PRIORITY, this); + if (fThread < B_OK) + goto err2; + + resume_thread(fThread); + + fRunning = true; + return; + +err2: + delete_sem(fFrameSync); +err1: + return; +} + +void +VideoProducer::HandleStop(void) +{ + PRINTF(1, ("HandleStop()\n")); + + if (!fRunning) { + PRINTF(-1, ("HandleStop: Node isn't running\n")); + return; + } + + delete_sem(fFrameSync); + wait_for_thread(fThread, &fThread); + + fRunning = false; +} + +void +VideoProducer::HandleTimeWarp(bigtime_t performance_time) +{ + fPerformanceTimeBase = performance_time; + fFrameBase = fFrame; + + /* Tell frame generation thread to recalculate delay value */ + release_sem(fFrameSync); +} + +void +VideoProducer::HandleSeek(bigtime_t performance_time) +{ + fPerformanceTimeBase = performance_time; + fFrameBase = fFrame; + + /* Tell frame generation thread to recalculate delay value */ + release_sem(fFrameSync); +} + +void +VideoProducer::HandleParameter(uint32 parameter) +{ + switch(parameter){ + case P_CHANNEL: + break; + case P_VIDEO_INPUT: + break; + case P_AUDIO_INPUT: + break; + case P_BRIGHTNESS: + break; + case P_CONTRAST: + break; + case P_SATURATION: + break; + case P_HUE: + break; + case P_CAPTURE_SIZE: + break; + case P_CAPTURE_FORMAT: + break; + case P_STANDART: + break; + case P_BANDWIDTH: + break; + case P_LOCALE: + { + //debugger("stop"); + BParameterWeb *web = Web(); + int nCount = web->CountParameters(); + for(int idx = 0; idx < nCount; idx++){ + BParameter *parameter = web->ParameterAt(idx); + if(parameter && parameter->Type() == BParameter::B_DISCRETE_PARAMETER && + parameter->ID() == P_CHANNEL){ + BDiscreteParameter * d_parameter = dynamic_cast(parameter); + d_parameter->MakeEmpty(); + for(int i = 0; i < fLocales[fLocale]->ChannelsCount(); i ++){ + d_parameter->AddItem(i, (fLocales[fLocale]->GetChannel(i)).Name().c_str()); + } + /*status_t st = BroadcastChangedParameter(P_CHANNEL); + if(st != B_OK) + debugger("kk");*/ + break; + } + } + } + break; + case P_VERT_OFFSET: + break; + case P_HORZ_OFFSET: + break; + } +} + +/* The following functions form the thread that generates frames. You should + * replace this with the code that interfaces to your hardware. */ +int32 +VideoProducer::FrameGenerator() +{ + bigtime_t wait_until = system_time(); + + while (1) { + status_t err = acquire_sem_etc(fFrameSync, 1, B_ABSOLUTE_TIMEOUT, + wait_until); + + /* The only acceptable responses are B_OK and B_TIMED_OUT. Everything + * else means the thread should quit. Deleting the semaphore, as in + * VideoProducer::HandleStop(), will trigger this behavior. */ + if ((err != B_OK) && (err != B_TIMED_OUT)) + break; + + fFrame++; + + /* Recalculate the time until the thread should wake up to begin + * processing the next frame. Subtract fProcessingLatency so that + * the frame is sent in time. */ + wait_until = TimeSource()->RealTimeFor(fPerformanceTimeBase + + (bigtime_t) + ((fFrame - fFrameBase) * + (1000000 / fConnectedFormat.field_rate)), 0) - + fProcessingLatency; + + /* Drop frame if it's at least a frame late */ + if (wait_until < system_time()) + continue; + + /* If the semaphore was acquired successfully, it means something + * changed the timing information (see VideoProducer::Connect()) and + * so the thread should go back to sleep until the newly-calculated + * wait_until time. */ + if (err == B_OK) + continue; + + /* Send buffers only if the node is running and the output has been + * enabled */ + if (!fRunning || !fEnabled) + continue; + + BAutolock _(fLock); + + /* Fetch a buffer from the buffer group */ + BBuffer *buffer = fBufferGroup->RequestBuffer( + 4 * fConnectedFormat.display.line_width * + fConnectedFormat.display.line_count, 0LL); + if (!buffer) + continue; + + /* Fill out the details about this buffer. */ + media_header *h = buffer->Header(); + h->type = B_MEDIA_RAW_VIDEO; + h->time_source = TimeSource()->ID(); + h->size_used = 4 * fConnectedFormat.display.line_width * + fConnectedFormat.display.line_count; + /* For a buffer originating from a device, you might want to calculate + * this based on the PerformanceTimeFor the time your buffer arrived at + * the hardware (plus any applicable adjustments). */ + h->start_time = fPerformanceTimeBase + + (bigtime_t) + ((fFrame - fFrameBase) * + (1000000 / fConnectedFormat.field_rate)); + h->file_pos = 0; + h->orig_size = 0; + h->data_offset = 0; + h->u.raw_video.field_gamma = 1.0; + h->u.raw_video.field_sequence = fFrame; + h->u.raw_video.field_number = 0; + h->u.raw_video.pulldown_number = 0; + h->u.raw_video.first_active_line = 1; + h->u.raw_video.line_count = fConnectedFormat.display.line_count; + + /* Fill in a pattern */ + uint32 *p = (uint32 *)buffer->Data(); + for (int y=0;yRecycle(); + } + } + + return B_OK; +} + +int32 +VideoProducer::_frame_generator_(void *data) +{ + return ((VideoProducer *)data)->FrameGenerator(); +} diff --git a/src/add-ons/media/media-add-ons/usb_vision/Producer.h b/src/add-ons/media/media-add-ons/usb_vision/Producer.h new file mode 100644 index 0000000000..30ebd3a5c7 --- /dev/null +++ b/src/add-ons/media/media-add-ons/usb_vision/Producer.h @@ -0,0 +1,208 @@ +/* + * This file is a part of BeOS USBVision driver project. + * Copyright (c) 2003 by Siarzuk Zharski + * + * This file may be used under the terms of the BSD License + * + * Skeletal part of this code was inherired from original BeOS sample code, + * that is distributed under the terms of the Be Sample Code License. + * + */ + +#ifndef _USBVISION_PRODUCER_H +#define _USBVISION_PRODUCER_H + +#include +#include +#include +#include +#include +#include +#include + +#include "TunerLocale.h" + +class VideoProducer : + public virtual BMediaEventLooper, + public virtual BBufferProducer, + public virtual BControllable +{ +public: + VideoProducer(BMediaAddOn *addon, + const char *name, int32 internal_id); +virtual ~VideoProducer(); + +virtual status_t InitCheck() const { return fInitStatus; } + +/* BMediaNode */ +public: +virtual port_id ControlPort() const; +virtual BMediaAddOn *AddOn(int32 * internal_id) const; +virtual status_t HandleMessage(int32 message, const void *data, + size_t size); +protected: +virtual void Preroll(); +virtual void SetTimeSource(BTimeSource * time_source); +virtual status_t RequestCompleted(const media_request_info & info); + +/* BMediaEventLooper */ +protected: +virtual void NodeRegistered(); +virtual void Start(bigtime_t performance_time); +virtual void Stop(bigtime_t performance_time, bool immediate); +virtual void Seek(bigtime_t media_time, bigtime_t performance_time); +virtual void TimeWarp(bigtime_t at_real_time, + bigtime_t to_performance_time); +virtual status_t AddTimer(bigtime_t at_performance_time, int32 cookie); +virtual void SetRunMode(run_mode mode); +virtual void HandleEvent(const media_timed_event *event, + bigtime_t lateness, bool realTimeEvent = false); +virtual void CleanUpEvent(const media_timed_event *event); +virtual bigtime_t OfflineTime(); +virtual void ControlLoop(); +virtual status_t DeleteHook(BMediaNode * node); + +/* BBufferProducer */ +protected: +virtual status_t FormatSuggestionRequested(media_type type, int32 quality, + media_format * format); +virtual status_t FormatProposal(const media_source &output, + media_format *format); +virtual status_t FormatChangeRequested(const media_source &source, + const media_destination &destination, + media_format *io_format, int32 *_deprecated_); +virtual status_t GetNextOutput(int32 * cookie, media_output * out_output); +virtual status_t DisposeOutputCookie(int32 cookie); +virtual status_t SetBufferGroup(const media_source &for_source, + BBufferGroup * group); +virtual status_t VideoClippingChanged(const media_source &for_source, + int16 num_shorts, int16 *clip_data, + const media_video_display_info &display, + int32 * _deprecated_); +virtual status_t GetLatency(bigtime_t * out_latency); +virtual status_t PrepareToConnect(const media_source &what, + const media_destination &where, + media_format *format, + media_source *out_source, char *out_name); +virtual void Connect(status_t error, const media_source &source, + const media_destination &destination, + const media_format & format, char *io_name); +virtual void Disconnect(const media_source & what, + const media_destination & where); +virtual void LateNoticeReceived(const media_source & what, + bigtime_t how_much, bigtime_t performance_time); +virtual void EnableOutput(const media_source & what, bool enabled, + int32 * _deprecated_); +virtual status_t SetPlayRate(int32 numer,int32 denom); +virtual void AdditionalBufferRequested(const media_source & source, + media_buffer_id prev_buffer, bigtime_t prev_time, + const media_seek_tag * prev_tag); +virtual void LatencyChanged(const media_source & source, + const media_destination & destination, + bigtime_t new_latency, uint32 flags); + +/* BControllable */ +protected: +virtual status_t GetParameterValue(int32 id, bigtime_t *last_change, + void *value, size_t *size); +virtual void SetParameterValue(int32 id, bigtime_t when, + const void *value, size_t size); +virtual status_t StartControlPanel(BMessenger *out_messenger); + +/* state */ +private: + void HandleStart(bigtime_t performance_time); + void HandleStop(); + void HandleTimeWarp(bigtime_t performance_time); + void HandleSeek(bigtime_t performance_time); + void HandleParameter(uint32 parameter); + +static int32 fInstances; + + status_t fInitStatus; + + int32 fInternalID; + BMediaAddOn *fAddOn; + + BLocker fLock; + BBufferGroup *fBufferGroup; + + thread_id fThread; + sem_id fFrameSync; +static int32 _frame_generator_(void *data); + int32 FrameGenerator(); + + /* The remaining variables should be declared volatile, but they + * are not here to improve the legibility of the sample code. */ + uint32 fFrame; + uint32 fFrameBase; + bigtime_t fPerformanceTimeBase; + bigtime_t fProcessingLatency; + media_output fOutput; + media_raw_video_format fConnectedFormat; + bool fRunning; + bool fConnected; + bool fEnabled; + + enum { P_CHANNEL, + P_VIDEO_INPUT, + P_AUDIO_INPUT, + P_BRIGHTNESS, + P_CONTRAST, + P_SATURATION, + P_HUE, + P_CAPTURE_SIZE, + P_CAPTURE_FORMAT, + P_STANDART, + P_BANDWIDTH, + P_LOCALE, + P_VERT_OFFSET, + P_HORZ_OFFSET, + P_COLOR }; +enum { P_VI_TUNER, + P_VI_COMPOSITE, + P_VI_SVIDEO}; +enum { P_VF_NTSC_M, + P_VF_NTSC_MJ, + P_VF_PAL_BDGHI, + P_VF_PAL_M, + P_VF_PAL_N, + P_VF_SECAM}; + BParameterWeb *CreateParameterWeb(); + + uint32 fChannel; + bigtime_t fLastChannelChange; + uint32 fVideoInput; + bigtime_t fLastVideoInputChange; + uint32 fAudioInput; + bigtime_t fLastAudioInputChange; + float fBrightness; + bigtime_t fLastBrightnessChange; + float fContrast; + bigtime_t fLastContrastChange; + float fSaturation; + bigtime_t fLastSaturationChange; + float fHue; + bigtime_t fLastHueChange; + uint32 fCaptureSize; + bigtime_t fLastCaptureSizeChange; + uint32 fCaptureFormat; + bigtime_t fLastCaptureFormatChange; + uint32 fStandard; + bigtime_t fLastStandardChange; + float fBandwidth; + bigtime_t fLastBandwidthChange; + uint32 fLocale; + bigtime_t fLastLocaleChange; + float fVertOffset; + bigtime_t fLastVertOffsetChange; + float fHorzOffset; + bigtime_t fLastHorzOffsetChange; + + uint32 fColor; + bigtime_t fLastColorChange; + + Locale::Locales fLocales; +}; + +#endif /*_USBVISION_PRODUCER_H*/ diff --git a/src/add-ons/media/media-add-ons/usb_vision/TunerLocale.cpp b/src/add-ons/media/media-add-ons/usb_vision/TunerLocale.cpp new file mode 100644 index 0000000000..b60e1327cc --- /dev/null +++ b/src/add-ons/media/media-add-ons/usb_vision/TunerLocale.cpp @@ -0,0 +1,135 @@ +/* + * This file is a part of BeOS USBVision driver project. + * Copyright (c) 2003 by Siarzuk Zharski + * + * This file may be used under the terms of the BSD License + * + */ +#include +#include +#include +#include +#include + +#include "TunerLocale.h" + +using namespace Locale; + +const char *kLocalesSettings = "media/usb_vision/Locales"; + +Channel::Channel(string &str, uint32 frequency): + fName(str), fFrequency(frequency) +{ +} + +const string &Channel::Name() const +{ + return fName; +} +const uint32 Channel::Frequency() +{ + return fFrequency; +} + +TunerLocale::TunerLocale(BEntry &entry) +{ + fStatus = B_NO_INIT; + if(entry.IsFile()){ + BPath path; + if((fStatus = entry.GetPath(&path)) == B_OK){ + char name[B_FILE_NAME_LENGTH]; + if((fStatus = entry.GetName(name)) == B_OK){ + fName = name; + fStatus = LoadLocale(path.Path()); + } + } + } +} + +TunerLocale::~TunerLocale() +{ +} + +status_t TunerLocale::InitCheck() +{ + return fStatus; +} + +status_t TunerLocale::LoadLocale(const char *name) +{ + status_t status = B_OK; + ifstream ifs(name); + while(ifs.good() && !ifs.eof()){ + string str; + getline(ifs, str); + //TODO : validity check and parse strings ... + str.erase(0, str.find_first_not_of(" \t")); + str.erase(str.find_last_not_of(" \t") + 1); + switch(str[0]){ + case ';': continue; + case '@': + str.erase(0, 1); + fName = str; + break; + default: //TODO parse ... + Channel channel(str, 0); + fChannels.push_back(channel); + break; + } + } + return status; +} + +status_t TunerLocale::LoadLocales(vector &vector) +{ + status_t status = B_ERROR; + BPath path; + if((status = find_directory(B_USER_SETTINGS_DIRECTORY, &path)) != B_OK) + return status; + if((status = path.Append(kLocalesSettings)) != B_OK) + return status; + BDirectory directory(path.Path()); + if((status = directory.InitCheck()) != B_OK) + return status; + vector.clear(); + BEntry entry; + while((status = directory.GetNextEntry(&entry)) == B_OK){ + if(entry.IsFile()){ + TunerLocale *locale = new TunerLocale(entry); + if((status = locale->InitCheck()) == B_OK){ + vector.push_back(locale); + } + else + delete locale; + } + } + if(status == B_ENTRY_NOT_FOUND) //we reached the end of entries list ... + status = B_OK; + return status; +} + +status_t TunerLocale::ReleaseLocales(vector &vector) +{ + for(LocalesIterator locale = vector.begin(); + locale != vector.end(); locale ++){ + delete *locale; + } + return B_OK; +} + +const string &TunerLocale::Name() +{ + return fName; +} + +const Channel &TunerLocale::GetChannel(int idx) +{ + if(idx < 0) idx = 0; + if(idx >= (int)fChannels.size()) idx = (int)(fChannels.size() - 1); + return fChannels[idx]; +} + +uint32 TunerLocale::ChannelsCount() +{ + return fChannels.size(); +} diff --git a/src/add-ons/media/media-add-ons/usb_vision/TunerLocale.h b/src/add-ons/media/media-add-ons/usb_vision/TunerLocale.h new file mode 100644 index 0000000000..b2eff8f447 --- /dev/null +++ b/src/add-ons/media/media-add-ons/usb_vision/TunerLocale.h @@ -0,0 +1,51 @@ +/* + * This file is a part of BeOS USBVision driver project. + * Copyright (c) 2003 by Siarzuk Zharski + * + * This file may be used under the terms of the BSD License + * + */ +#ifndef _TUNER_LOCALE_H_ + #define _TUNER_LOCALE_H_ + +#include +#include + +namespace Locale{ + +class Channel +{ + string fName; + uint32 fFrequency; +public: + Channel(string &str, uint32 frequency); + const string &Name() const; + const uint32 Frequency(); +}; + +typedef vector Channels; +typedef vector::iterator ChannelsIterator; + +class TunerLocale +{ + status_t fStatus; + string fName; + Channels fChannels; + TunerLocale(BEntry &entry); + status_t LoadLocale(const char *file); +public: + ~TunerLocale(); + static status_t LoadLocales(vector &vector); + static status_t ReleaseLocales(vector &vector); + status_t InitCheck(); + const string &Name(); + const Channel &GetChannel(int idx); + uint32 ChannelsCount(); +}; + +typedef vector Locales; +typedef vector::iterator LocalesIterator; + +} //namespace Locale + +#endif//_TUNER_LOCALE_H_ diff --git a/src/add-ons/media/media-add-ons/video_producer_demo/Producer.cpp b/src/add-ons/media/media-add-ons/video_producer_demo/Producer.cpp index 13be6ba64a..76ce841f2f 100644 --- a/src/add-ons/media/media-add-ons/video_producer_demo/Producer.cpp +++ b/src/add-ons/media/media-add-ons/video_producer_demo/Producer.cpp @@ -656,10 +656,10 @@ VideoProducer::FrameGenerator() /* Recalculate the time until the thread should wake up to begin * processing the next frame. Subtract fProcessingLatency so that * the frame is sent in time. */ - wait_until = TimeSource()->RealTimeFor(fPerformanceTimeBase, 0) + + wait_until = TimeSource()->RealTimeFor(fPerformanceTimeBase + (bigtime_t) ((fFrame - fFrameBase) * - (1000000 / fConnectedFormat.field_rate)) - + (1000000 / fConnectedFormat.field_rate)), 0) - fProcessingLatency; /* Drop frame if it's at least a frame late */