Changeset e017851 in thomson for elec/CrO2/software/device.cpp


Ignore:
Timestamp:
Jan 14, 2013, 11:05:27 PM (11 years ago)
Author:
Adrien Destugues <pulkomandy@…>
Branches:
main
Children:
6bd7144
Parents:
4a558d7
Message:

Port to Haiku. Untested.

git-svn-id: svn://localhost/thomson@28 85ae3b6b-dc8f-4344-a89d-598714f2e4e5

File:
1 edited

Legend:

Unmodified
Added
Removed
  • elec/CrO2/software/device.cpp

    r4a558d7 re017851  
    11/* CrO2 datassette emulator
    2  * Copyright 2012, Adrien Destugues <pulkomandy@pulkomandy.ath.cx>
     2 * Copyright 2013, Adrien Destugues <pulkomandy@pulkomandy.tk>
    33 *
    44 * Distributed under the terms of the MIT licence.
    55 *
    6  * Handles device communication through libusb
     6 * High-level device management functions shared by all implementations.
    77 */
    88
    99#include "device.h"
    1010#include "k5.h"
     11#include "Tape.h"
    1112
    1213#include <typeinfo>
     14#include <unistd.h>
     15
    1316
    1417bool Device::initOnce = false;
     
    1720const uint32_t Device::vid = 0x16C0;
    1821const uint32_t Device::pid = 0x05DC;
    19 const char* Device::vendor = "pulkomandy.ath.cx";
     22const char* Device::vendor = "pulkomandy.ath.cx"; // FIXME update
    2023const char* Device::product = "CrO2";
    21 
    22 /* These are the vendor specific commands implemented by our USB device */
    23 #define PSCMD_CONFIG  0
    24 #define PSCMD_GET   1
    25 #define PSCMD_PUT   2
    26 #define PSCMD_STATUS   3
    27 
    28 
    29 // Gets the device instance. Throws an error message if something bad happens.
    30 Device& Device::getDevice() throw(const char*)
    31 {
    32         // If Device constructor throws an exception, instance is not initialized.
    33         // So, the constructor will be called again at next getDevice call, until
    34         // it succeeds.
    35         if (instance == NULL)
    36                 instance = new Device();
    37 
    38         return *instance;
    39 }
    40 
    41 
    42 /* USB device lookup by VID and PID, then Vendor and Product strings, as we use
    43  * V-USB shared ID. */
    44 static int  usbGetStringAscii(usb_dev_handle *dev, int index, int langid,
    45         char *buf, int buflen)
    46 {
    47 char    buffer[256];
    48 int     rval, i;
    49 
    50     if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
    51                         (USB_DT_STRING << 8) + index, langid, buffer, sizeof(buffer), 1000)) < 0)
    52         return rval;
    53     if(buffer[1] != USB_DT_STRING)
    54         return 0;
    55     if((unsigned char)buffer[0] < rval)
    56         rval = (unsigned char)buffer[0];
    57     rval /= 2;
    58     /* lossy conversion to ISO Latin1 */
    59     for(i=1;i<rval;i++){
    60         if(i > buflen)  /* destination buffer overflow */
    61             break;
    62         buf[i-1] = buffer[2 * i];
    63         if(buffer[2 * i + 1] != 0)  /* outside of ISO Latin1 range */
    64             buf[i-1] = '?';
    65     }
    66     buf[i-1] = 0;
    67     return i-1;
    68 }
    69 
    70 Device::Device() throw(const char*)
    71 {
    72         handle = NULL;
    73 
    74         if (!initOnce)
    75         {
    76                 initOnce = true;
    77                 usb_init();
    78         }
    79 
    80     usb_find_busses();
    81     usb_find_devices();
    82 
    83     for(struct usb_bus* bus=usb_get_busses(); bus; bus=bus->next)
    84         {
    85                 for(struct usb_device* dev=bus->devices; dev; dev=dev->next)
    86                 {
    87                         if(dev->descriptor.idVendor != vid || dev->descriptor.idProduct != pid)
    88                                 continue;
    89 
    90                         // Found device with correct VID and PID. Now try to match the
    91                         // vendor and product strings
    92                         char    string[256];
    93                         int     len;
    94                         handle = usb_open(dev);
    95                                 /* we need to open the device in order to query strings */
    96                         if(!handle){
    97                                 continue;
    98                         }
    99                         /* now check whether the names match: */
    100                         len = usbGetStringAscii(handle, dev->descriptor.iManufacturer,
    101                                 0x0409, string, sizeof(string));
    102                         if(len >= 0)
    103                         {
    104                                 if(strcmp(string, vendor) == 0){
    105                                         len = usbGetStringAscii(handle, dev->descriptor.iProduct,
    106                                                 0x0409, string, sizeof(string));
    107                                         if(len >= 0){
    108                                                 if(strcmp(string, product) == 0)
    109                                                         break;
    110                                         }
    111                                 }
    112                         }
    113                         usb_close(handle);
    114                         handle = NULL;
    115                 }
    116                 if(handle)
    117                         break;
    118         }
    119 
    120         // At this point, either we have found a device and handle is pointing to it,
    121         // or we failed and handle is NULL.
    122         if (!handle)
    123                 throw "Device not found. Is the USB cable plugged correctly?";
    124 }
    125 
    126 
    127 Device::~Device()
    128 {
    129         usb_close(handle);
    130 }
    131 
    132 
    133 int Device::read(uint8_t* buffer, size_t max)
    134 {
    135         return usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
    136                 PSCMD_GET, 0,0, (char*)buffer, max, 5000);
    137 
    138 }
    139 
    140 
    141 int Device::write(const uint8_t* buffer, size_t size, int blktype)
    142 {
    143         int rqtype = (size == 0) ? USB_ENDPOINT_IN:USB_ENDPOINT_OUT;
    144         return usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | rqtype,
    145                 PSCMD_PUT, blktype,0 /*checksum*/, (char*)buffer, size, 5000);
    146 
    147 }
    14824
    14925
     
    15430                // wait for motor on
    15531                while (getStatus() & 8)
    156                         Sleep(1000);
     32                        usleep(1000 * 1000);
    15733
    15834                const Tape::Block& block = file.getBlock(k);
     
    16642
    16743                // TODO wait for correct time (read status from usb OR compute from size+type)
    168                 Sleep(1400);
     44                usleep(1400 * 1000);
    16945        }
    17046}
    17147
    172 uint8_t Device::getStatus()
    173 {
    174         uint8_t status;
    175         usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
    176                         PSCMD_STATUS, 0,0, (char*)&status, 1, 5000);
    177                 // TODO handle errors (return value)
    178         return status;
    179 }
Note: See TracChangeset for help on using the changeset viewer.