0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 #include <linux/errno.h>
0040 #include <linux/module.h>
0041 #include <linux/slab.h>
0042
0043 #include <scsi/scsi.h>
0044 #include <scsi/scsi_cmnd.h>
0045
0046 #include "usb.h"
0047 #include "transport.h"
0048 #include "protocol.h"
0049 #include "debug.h"
0050 #include "scsiglue.h"
0051
0052 #define DRV_NAME "ums-datafab"
0053
0054 MODULE_DESCRIPTION("Driver for Datafab USB Compact Flash reader");
0055 MODULE_AUTHOR("Jimmie Mayfield <mayfield+datafab@sackheads.org>");
0056 MODULE_LICENSE("GPL");
0057 MODULE_IMPORT_NS(USB_STORAGE);
0058
0059 struct datafab_info {
0060 unsigned long sectors;
0061 unsigned long ssize;
0062 signed char lun;
0063
0064
0065 unsigned char sense_key;
0066 unsigned long sense_asc;
0067 unsigned long sense_ascq;
0068 };
0069
0070 static int datafab_determine_lun(struct us_data *us,
0071 struct datafab_info *info);
0072
0073
0074
0075
0076
0077 #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
0078 vendorName, productName, useProtocol, useTransport, \
0079 initFunction, flags) \
0080 { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
0081 .driver_info = (flags) }
0082
0083 static struct usb_device_id datafab_usb_ids[] = {
0084 # include "unusual_datafab.h"
0085 { }
0086 };
0087 MODULE_DEVICE_TABLE(usb, datafab_usb_ids);
0088
0089 #undef UNUSUAL_DEV
0090
0091
0092
0093
0094 #define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
0095 vendor_name, product_name, use_protocol, use_transport, \
0096 init_function, Flags) \
0097 { \
0098 .vendorName = vendor_name, \
0099 .productName = product_name, \
0100 .useProtocol = use_protocol, \
0101 .useTransport = use_transport, \
0102 .initFunction = init_function, \
0103 }
0104
0105 static struct us_unusual_dev datafab_unusual_dev_list[] = {
0106 # include "unusual_datafab.h"
0107 { }
0108 };
0109
0110 #undef UNUSUAL_DEV
0111
0112
0113 static inline int
0114 datafab_bulk_read(struct us_data *us, unsigned char *data, unsigned int len) {
0115 if (len == 0)
0116 return USB_STOR_XFER_GOOD;
0117
0118 usb_stor_dbg(us, "len = %d\n", len);
0119 return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
0120 data, len, NULL);
0121 }
0122
0123
0124 static inline int
0125 datafab_bulk_write(struct us_data *us, unsigned char *data, unsigned int len) {
0126 if (len == 0)
0127 return USB_STOR_XFER_GOOD;
0128
0129 usb_stor_dbg(us, "len = %d\n", len);
0130 return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
0131 data, len, NULL);
0132 }
0133
0134
0135 static int datafab_read_data(struct us_data *us,
0136 struct datafab_info *info,
0137 u32 sector,
0138 u32 sectors)
0139 {
0140 unsigned char *command = us->iobuf;
0141 unsigned char *buffer;
0142 unsigned char thistime;
0143 unsigned int totallen, alloclen;
0144 int len, result;
0145 unsigned int sg_offset = 0;
0146 struct scatterlist *sg = NULL;
0147
0148
0149
0150
0151
0152
0153 if (sectors > 0x0FFFFFFF)
0154 return USB_STOR_TRANSPORT_ERROR;
0155
0156 if (info->lun == -1) {
0157 result = datafab_determine_lun(us, info);
0158 if (result != USB_STOR_TRANSPORT_GOOD)
0159 return result;
0160 }
0161
0162 totallen = sectors * info->ssize;
0163
0164
0165
0166
0167
0168 alloclen = min(totallen, 65536u);
0169 buffer = kmalloc(alloclen, GFP_NOIO);
0170 if (buffer == NULL)
0171 return USB_STOR_TRANSPORT_ERROR;
0172
0173 do {
0174
0175
0176
0177 len = min(totallen, alloclen);
0178 thistime = (len / info->ssize) & 0xff;
0179
0180 command[0] = 0;
0181 command[1] = thistime;
0182 command[2] = sector & 0xFF;
0183 command[3] = (sector >> 8) & 0xFF;
0184 command[4] = (sector >> 16) & 0xFF;
0185
0186 command[5] = 0xE0 + (info->lun << 4);
0187 command[5] |= (sector >> 24) & 0x0F;
0188 command[6] = 0x20;
0189 command[7] = 0x01;
0190
0191
0192 result = datafab_bulk_write(us, command, 8);
0193 if (result != USB_STOR_XFER_GOOD)
0194 goto leave;
0195
0196
0197 result = datafab_bulk_read(us, buffer, len);
0198 if (result != USB_STOR_XFER_GOOD)
0199 goto leave;
0200
0201
0202 usb_stor_access_xfer_buf(buffer, len, us->srb,
0203 &sg, &sg_offset, TO_XFER_BUF);
0204
0205 sector += thistime;
0206 totallen -= len;
0207 } while (totallen > 0);
0208
0209 kfree(buffer);
0210 return USB_STOR_TRANSPORT_GOOD;
0211
0212 leave:
0213 kfree(buffer);
0214 return USB_STOR_TRANSPORT_ERROR;
0215 }
0216
0217
0218 static int datafab_write_data(struct us_data *us,
0219 struct datafab_info *info,
0220 u32 sector,
0221 u32 sectors)
0222 {
0223 unsigned char *command = us->iobuf;
0224 unsigned char *reply = us->iobuf;
0225 unsigned char *buffer;
0226 unsigned char thistime;
0227 unsigned int totallen, alloclen;
0228 int len, result;
0229 unsigned int sg_offset = 0;
0230 struct scatterlist *sg = NULL;
0231
0232
0233
0234
0235
0236
0237 if (sectors > 0x0FFFFFFF)
0238 return USB_STOR_TRANSPORT_ERROR;
0239
0240 if (info->lun == -1) {
0241 result = datafab_determine_lun(us, info);
0242 if (result != USB_STOR_TRANSPORT_GOOD)
0243 return result;
0244 }
0245
0246 totallen = sectors * info->ssize;
0247
0248
0249
0250
0251
0252 alloclen = min(totallen, 65536u);
0253 buffer = kmalloc(alloclen, GFP_NOIO);
0254 if (buffer == NULL)
0255 return USB_STOR_TRANSPORT_ERROR;
0256
0257 do {
0258
0259
0260
0261 len = min(totallen, alloclen);
0262 thistime = (len / info->ssize) & 0xff;
0263
0264
0265 usb_stor_access_xfer_buf(buffer, len, us->srb,
0266 &sg, &sg_offset, FROM_XFER_BUF);
0267
0268 command[0] = 0;
0269 command[1] = thistime;
0270 command[2] = sector & 0xFF;
0271 command[3] = (sector >> 8) & 0xFF;
0272 command[4] = (sector >> 16) & 0xFF;
0273
0274 command[5] = 0xE0 + (info->lun << 4);
0275 command[5] |= (sector >> 24) & 0x0F;
0276 command[6] = 0x30;
0277 command[7] = 0x02;
0278
0279
0280 result = datafab_bulk_write(us, command, 8);
0281 if (result != USB_STOR_XFER_GOOD)
0282 goto leave;
0283
0284
0285 result = datafab_bulk_write(us, buffer, len);
0286 if (result != USB_STOR_XFER_GOOD)
0287 goto leave;
0288
0289
0290 result = datafab_bulk_read(us, reply, 2);
0291 if (result != USB_STOR_XFER_GOOD)
0292 goto leave;
0293
0294 if (reply[0] != 0x50 && reply[1] != 0) {
0295 usb_stor_dbg(us, "Gah! write return code: %02x %02x\n",
0296 reply[0], reply[1]);
0297 goto leave;
0298 }
0299
0300 sector += thistime;
0301 totallen -= len;
0302 } while (totallen > 0);
0303
0304 kfree(buffer);
0305 return USB_STOR_TRANSPORT_GOOD;
0306
0307 leave:
0308 kfree(buffer);
0309 return USB_STOR_TRANSPORT_ERROR;
0310 }
0311
0312
0313 static int datafab_determine_lun(struct us_data *us,
0314 struct datafab_info *info)
0315 {
0316
0317
0318
0319
0320
0321
0322 static unsigned char scommand[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 };
0323 unsigned char *command = us->iobuf;
0324 unsigned char *buf;
0325 int count = 0, rc;
0326
0327 if (!info)
0328 return USB_STOR_TRANSPORT_ERROR;
0329
0330 memcpy(command, scommand, 8);
0331 buf = kmalloc(512, GFP_NOIO);
0332 if (!buf)
0333 return USB_STOR_TRANSPORT_ERROR;
0334
0335 usb_stor_dbg(us, "locating...\n");
0336
0337
0338
0339 while (count++ < 3) {
0340 command[5] = 0xa0;
0341
0342 rc = datafab_bulk_write(us, command, 8);
0343 if (rc != USB_STOR_XFER_GOOD) {
0344 rc = USB_STOR_TRANSPORT_ERROR;
0345 goto leave;
0346 }
0347
0348 rc = datafab_bulk_read(us, buf, 512);
0349 if (rc == USB_STOR_XFER_GOOD) {
0350 info->lun = 0;
0351 rc = USB_STOR_TRANSPORT_GOOD;
0352 goto leave;
0353 }
0354
0355 command[5] = 0xb0;
0356
0357 rc = datafab_bulk_write(us, command, 8);
0358 if (rc != USB_STOR_XFER_GOOD) {
0359 rc = USB_STOR_TRANSPORT_ERROR;
0360 goto leave;
0361 }
0362
0363 rc = datafab_bulk_read(us, buf, 512);
0364 if (rc == USB_STOR_XFER_GOOD) {
0365 info->lun = 1;
0366 rc = USB_STOR_TRANSPORT_GOOD;
0367 goto leave;
0368 }
0369
0370 msleep(20);
0371 }
0372
0373 rc = USB_STOR_TRANSPORT_ERROR;
0374
0375 leave:
0376 kfree(buf);
0377 return rc;
0378 }
0379
0380 static int datafab_id_device(struct us_data *us,
0381 struct datafab_info *info)
0382 {
0383
0384
0385
0386
0387 static unsigned char scommand[8] = { 0, 1, 0, 0, 0, 0xa0, 0xec, 1 };
0388 unsigned char *command = us->iobuf;
0389 unsigned char *reply;
0390 int rc;
0391
0392 if (!info)
0393 return USB_STOR_TRANSPORT_ERROR;
0394
0395 if (info->lun == -1) {
0396 rc = datafab_determine_lun(us, info);
0397 if (rc != USB_STOR_TRANSPORT_GOOD)
0398 return rc;
0399 }
0400
0401 memcpy(command, scommand, 8);
0402 reply = kmalloc(512, GFP_NOIO);
0403 if (!reply)
0404 return USB_STOR_TRANSPORT_ERROR;
0405
0406 command[5] += (info->lun << 4);
0407
0408 rc = datafab_bulk_write(us, command, 8);
0409 if (rc != USB_STOR_XFER_GOOD) {
0410 rc = USB_STOR_TRANSPORT_ERROR;
0411 goto leave;
0412 }
0413
0414
0415
0416 rc = datafab_bulk_read(us, reply, 512);
0417 if (rc == USB_STOR_XFER_GOOD) {
0418
0419
0420 info->sectors = ((u32)(reply[117]) << 24) |
0421 ((u32)(reply[116]) << 16) |
0422 ((u32)(reply[115]) << 8) |
0423 ((u32)(reply[114]) );
0424 rc = USB_STOR_TRANSPORT_GOOD;
0425 goto leave;
0426 }
0427
0428 rc = USB_STOR_TRANSPORT_ERROR;
0429
0430 leave:
0431 kfree(reply);
0432 return rc;
0433 }
0434
0435
0436 static int datafab_handle_mode_sense(struct us_data *us,
0437 struct scsi_cmnd * srb,
0438 int sense_6)
0439 {
0440 static unsigned char rw_err_page[12] = {
0441 0x1, 0xA, 0x21, 1, 0, 0, 0, 0, 1, 0, 0, 0
0442 };
0443 static unsigned char cache_page[12] = {
0444 0x8, 0xA, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0
0445 };
0446 static unsigned char rbac_page[12] = {
0447 0x1B, 0xA, 0, 0x81, 0, 0, 0, 0, 0, 0, 0, 0
0448 };
0449 static unsigned char timer_page[8] = {
0450 0x1C, 0x6, 0, 0, 0, 0
0451 };
0452 unsigned char pc, page_code;
0453 unsigned int i = 0;
0454 struct datafab_info *info = (struct datafab_info *) (us->extra);
0455 unsigned char *ptr = us->iobuf;
0456
0457
0458
0459
0460
0461
0462 pc = srb->cmnd[2] >> 6;
0463 page_code = srb->cmnd[2] & 0x3F;
0464
0465 switch (pc) {
0466 case 0x0:
0467 usb_stor_dbg(us, "Current values\n");
0468 break;
0469 case 0x1:
0470 usb_stor_dbg(us, "Changeable values\n");
0471 break;
0472 case 0x2:
0473 usb_stor_dbg(us, "Default values\n");
0474 break;
0475 case 0x3:
0476 usb_stor_dbg(us, "Saves values\n");
0477 break;
0478 }
0479
0480 memset(ptr, 0, 8);
0481 if (sense_6) {
0482 ptr[2] = 0x00;
0483 i = 4;
0484 } else {
0485 ptr[3] = 0x00;
0486 i = 8;
0487 }
0488
0489 switch (page_code) {
0490 default:
0491
0492 info->sense_key = 0x05;
0493 info->sense_asc = 0x24;
0494 info->sense_ascq = 0x00;
0495 return USB_STOR_TRANSPORT_FAILED;
0496
0497 case 0x1:
0498 memcpy(ptr + i, rw_err_page, sizeof(rw_err_page));
0499 i += sizeof(rw_err_page);
0500 break;
0501
0502 case 0x8:
0503 memcpy(ptr + i, cache_page, sizeof(cache_page));
0504 i += sizeof(cache_page);
0505 break;
0506
0507 case 0x1B:
0508 memcpy(ptr + i, rbac_page, sizeof(rbac_page));
0509 i += sizeof(rbac_page);
0510 break;
0511
0512 case 0x1C:
0513 memcpy(ptr + i, timer_page, sizeof(timer_page));
0514 i += sizeof(timer_page);
0515 break;
0516
0517 case 0x3F:
0518 memcpy(ptr + i, timer_page, sizeof(timer_page));
0519 i += sizeof(timer_page);
0520 memcpy(ptr + i, rbac_page, sizeof(rbac_page));
0521 i += sizeof(rbac_page);
0522 memcpy(ptr + i, cache_page, sizeof(cache_page));
0523 i += sizeof(cache_page);
0524 memcpy(ptr + i, rw_err_page, sizeof(rw_err_page));
0525 i += sizeof(rw_err_page);
0526 break;
0527 }
0528
0529 if (sense_6)
0530 ptr[0] = i - 1;
0531 else
0532 ((__be16 *) ptr)[0] = cpu_to_be16(i - 2);
0533 usb_stor_set_xfer_buf(ptr, i, srb);
0534
0535 return USB_STOR_TRANSPORT_GOOD;
0536 }
0537
0538 static void datafab_info_destructor(void *extra)
0539 {
0540
0541
0542 }
0543
0544
0545
0546
0547 static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
0548 {
0549 struct datafab_info *info;
0550 int rc;
0551 unsigned long block, blocks;
0552 unsigned char *ptr = us->iobuf;
0553 static unsigned char inquiry_reply[8] = {
0554 0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00
0555 };
0556
0557 if (!us->extra) {
0558 us->extra = kzalloc(sizeof(struct datafab_info), GFP_NOIO);
0559 if (!us->extra)
0560 return USB_STOR_TRANSPORT_ERROR;
0561
0562 us->extra_destructor = datafab_info_destructor;
0563 ((struct datafab_info *)us->extra)->lun = -1;
0564 }
0565
0566 info = (struct datafab_info *) (us->extra);
0567
0568 if (srb->cmnd[0] == INQUIRY) {
0569 usb_stor_dbg(us, "INQUIRY - Returning bogus response\n");
0570 memcpy(ptr, inquiry_reply, sizeof(inquiry_reply));
0571 fill_inquiry_response(us, ptr, 36);
0572 return USB_STOR_TRANSPORT_GOOD;
0573 }
0574
0575 if (srb->cmnd[0] == READ_CAPACITY) {
0576 info->ssize = 0x200;
0577 rc = datafab_id_device(us, info);
0578 if (rc != USB_STOR_TRANSPORT_GOOD)
0579 return rc;
0580
0581 usb_stor_dbg(us, "READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
0582 info->sectors, info->ssize);
0583
0584
0585
0586 ((__be32 *) ptr)[0] = cpu_to_be32(info->sectors - 1);
0587 ((__be32 *) ptr)[1] = cpu_to_be32(info->ssize);
0588 usb_stor_set_xfer_buf(ptr, 8, srb);
0589
0590 return USB_STOR_TRANSPORT_GOOD;
0591 }
0592
0593 if (srb->cmnd[0] == MODE_SELECT_10) {
0594 usb_stor_dbg(us, "Gah! MODE_SELECT_10\n");
0595 return USB_STOR_TRANSPORT_ERROR;
0596 }
0597
0598
0599
0600 if (srb->cmnd[0] == READ_10) {
0601 block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
0602 ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
0603
0604 blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
0605
0606 usb_stor_dbg(us, "READ_10: read block 0x%04lx count %ld\n",
0607 block, blocks);
0608 return datafab_read_data(us, info, block, blocks);
0609 }
0610
0611 if (srb->cmnd[0] == READ_12) {
0612
0613
0614 block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
0615 ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
0616
0617 blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
0618 ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
0619
0620 usb_stor_dbg(us, "READ_12: read block 0x%04lx count %ld\n",
0621 block, blocks);
0622 return datafab_read_data(us, info, block, blocks);
0623 }
0624
0625 if (srb->cmnd[0] == WRITE_10) {
0626 block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
0627 ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
0628
0629 blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
0630
0631 usb_stor_dbg(us, "WRITE_10: write block 0x%04lx count %ld\n",
0632 block, blocks);
0633 return datafab_write_data(us, info, block, blocks);
0634 }
0635
0636 if (srb->cmnd[0] == WRITE_12) {
0637
0638
0639 block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
0640 ((u32)(srb->cmnd[4]) << 8) | ((u32)(srb->cmnd[5]));
0641
0642 blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
0643 ((u32)(srb->cmnd[8]) << 8) | ((u32)(srb->cmnd[9]));
0644
0645 usb_stor_dbg(us, "WRITE_12: write block 0x%04lx count %ld\n",
0646 block, blocks);
0647 return datafab_write_data(us, info, block, blocks);
0648 }
0649
0650 if (srb->cmnd[0] == TEST_UNIT_READY) {
0651 usb_stor_dbg(us, "TEST_UNIT_READY\n");
0652 return datafab_id_device(us, info);
0653 }
0654
0655 if (srb->cmnd[0] == REQUEST_SENSE) {
0656 usb_stor_dbg(us, "REQUEST_SENSE - Returning faked response\n");
0657
0658
0659
0660
0661
0662 memset(ptr, 0, 18);
0663 ptr[0] = 0xF0;
0664 ptr[2] = info->sense_key;
0665 ptr[7] = 11;
0666 ptr[12] = info->sense_asc;
0667 ptr[13] = info->sense_ascq;
0668 usb_stor_set_xfer_buf(ptr, 18, srb);
0669
0670 return USB_STOR_TRANSPORT_GOOD;
0671 }
0672
0673 if (srb->cmnd[0] == MODE_SENSE) {
0674 usb_stor_dbg(us, "MODE_SENSE_6 detected\n");
0675 return datafab_handle_mode_sense(us, srb, 1);
0676 }
0677
0678 if (srb->cmnd[0] == MODE_SENSE_10) {
0679 usb_stor_dbg(us, "MODE_SENSE_10 detected\n");
0680 return datafab_handle_mode_sense(us, srb, 0);
0681 }
0682
0683 if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
0684
0685
0686
0687
0688 return USB_STOR_TRANSPORT_GOOD;
0689 }
0690
0691 if (srb->cmnd[0] == START_STOP) {
0692
0693
0694
0695
0696 usb_stor_dbg(us, "START_STOP\n");
0697
0698
0699
0700
0701 rc = datafab_id_device(us, info);
0702 if (rc == USB_STOR_TRANSPORT_GOOD) {
0703 info->sense_key = NO_SENSE;
0704 srb->result = SUCCESS;
0705 } else {
0706 info->sense_key = UNIT_ATTENTION;
0707 srb->result = SAM_STAT_CHECK_CONDITION;
0708 }
0709 return rc;
0710 }
0711
0712 usb_stor_dbg(us, "Gah! Unknown command: %d (0x%x)\n",
0713 srb->cmnd[0], srb->cmnd[0]);
0714 info->sense_key = 0x05;
0715 info->sense_asc = 0x20;
0716 info->sense_ascq = 0x00;
0717 return USB_STOR_TRANSPORT_FAILED;
0718 }
0719
0720 static struct scsi_host_template datafab_host_template;
0721
0722 static int datafab_probe(struct usb_interface *intf,
0723 const struct usb_device_id *id)
0724 {
0725 struct us_data *us;
0726 int result;
0727
0728 result = usb_stor_probe1(&us, intf, id,
0729 (id - datafab_usb_ids) + datafab_unusual_dev_list,
0730 &datafab_host_template);
0731 if (result)
0732 return result;
0733
0734 us->transport_name = "Datafab Bulk-Only";
0735 us->transport = datafab_transport;
0736 us->transport_reset = usb_stor_Bulk_reset;
0737 us->max_lun = 1;
0738
0739 result = usb_stor_probe2(us);
0740 return result;
0741 }
0742
0743 static struct usb_driver datafab_driver = {
0744 .name = DRV_NAME,
0745 .probe = datafab_probe,
0746 .disconnect = usb_stor_disconnect,
0747 .suspend = usb_stor_suspend,
0748 .resume = usb_stor_resume,
0749 .reset_resume = usb_stor_reset_resume,
0750 .pre_reset = usb_stor_pre_reset,
0751 .post_reset = usb_stor_post_reset,
0752 .id_table = datafab_usb_ids,
0753 .soft_unbind = 1,
0754 .no_dynamic_id = 1,
0755 };
0756
0757 module_usb_stor_driver(datafab_driver, datafab_host_template, DRV_NAME);