Exemple #1
0
static void do_charset(void) {

	// set the communication charset to PETSCII
	strcpy(outbuf, cconv_charsetname(current_charset));

        // prepare FS_CHARSET packet
        packet_set_filled(&outpack, FSFD_CMD, FS_CHARSET, strlen(outbuf)+1);

	// send the FS_CHARSET packet
        endpoint->provider->submit_call(endpoint->provdata, FSFD_CMD, &outpack, &outpack, out_callback);

	// must not wait, as we may be in callback from FS_RESET (from server),
	// so serial_lock is set
}
Exemple #2
0
void rtconfig_pullconfig(int argc, const char *argv[]) {

	for (int i = 0; i < argc; i++) {
		if (argv[i][0] == '-' && argv[i][1] == 'X') {
			do_setopt((char*)argv[i]+2, strlen(argv[i]+2));
		}
	}

        // prepare FS_RESET packet
        packet_set_filled(&buspack, FSFD_SETOPT, FS_RESET, 0);

        // send request, receive in same buffer we sent from
        endpoint->provider->submit_call(endpoint->provdata, FSFD_SETOPT, &buspack, &buspack, setopt_callback);

        debug_printf("sent reset packet on fd %d, charset=%d\n", FSFD_SETOPT, current_charset);

	// send charset command
	do_charset();
}
Exemple #3
0
uint8_t file_submit_call(uint8_t channel_no, uint8_t type, uint8_t *cmd_buffer,
                         errormsg_t *errormsg, rtconfig_t *rtconf,
                         void (*callback)(int8_t errnum, uint8_t *rxdata), uint8_t iscmd) {

    assert_not_null(errormsg, "file_submit_call: errormsg is null");
    assert_not_null(rtconf, "file_submit_call: rtconf is null");

    // check for default drive (here is the place to set the last used one)
    if (nameinfo.drive == NAMEINFO_LAST_DRIVE) {
        nameinfo.drive = rtconf->last_used_drive;
    }
    else if (nameinfo.drive == NAMEINFO_UNUSED_DRIVE) {
        // TODO: match CBM behavior
        nameinfo.drive = rtconf->last_used_drive;
    }
    else if (nameinfo.drive < MAX_DRIVES) {
        // only save real drive numbers as last used default
        rtconf->last_used_drive = nameinfo.drive;
    }

    // if second name does not have a drive, use drive from first,
    // but only if it is defined
    if (nameinfo.file[0].drive == NAMEINFO_UNUSED_DRIVE && nameinfo.drive != NAMEINFO_UNDEF_DRIVE) {
        nameinfo.file[0].drive = nameinfo.drive;
    }

    // here is the place to plug in other file system providers,
    // like SD-Card, or even an outgoing IEC or IEEE, to convert between
    // the two bus systems. This is done depending on the drive number
    // and managed with the ASSIGN call.
    //provider_t *provider = &serial_provider;
    endpoint_t *endpoint = NULL;
    if (type == FS_OPEN_DIRECT) {
        debug_printf("Getting direct endpoint provider for channel %d\n", channel_no);
        endpoint = direct_provider();
    } else {
        endpoint = provider_lookup(nameinfo.drive, (char*) nameinfo.drivename);
    }

    // convert from bus' PETSCII to provider
    // currently only up to the first zero byte is converted, options like file type
    // are still ASCII only
    // in the future the bus may have an own conversion option...
    cconv_converter(CHARSET_PETSCII, endpoint->provider->charset(endpoint->provdata))
    ((char*)nameinfo.name, strlen((char*)nameinfo.name),
     (char*)nameinfo.name, strlen((char*)nameinfo.name));
    for (uint8_t i=0 ; i < nameinfo.num_files ; ++i) {
        if (nameinfo.file[i].name != NULL) {
            cconv_converter(CHARSET_PETSCII, endpoint->provider->charset(endpoint->provdata))
            ((char*)nameinfo.file[i].name, strlen((char*)nameinfo.file[i].name),
             (char*)nameinfo.file[i].name, strlen((char*)nameinfo.file[i].name));
        }
    }

    if (type == FS_MOVE
            && nameinfo.file[0].drive != NAMEINFO_UNUSED_DRIVE 	// then use ep from first drive anyway
            && nameinfo.file[0].drive != nameinfo.drive) {		// no need to check if the same

        // two-name command(s) with possibly different drive numbers
        endpoint_t *endpoint2 = provider_lookup(nameinfo.file[0].drive, (char*) nameinfo.file[0].name);

        if (endpoint2 != endpoint) {
            debug_printf("ILLEGAL DRIVE COMBINATION: %d vs. %d\n", nameinfo.drive+0x30, nameinfo.file[0].drive+0x30);
            set_error_tsd(errormsg, CBM_ERROR_DRIVE_NOT_READY, 0, 0, nameinfo.drive);
            return -1;
        }
    }

    // check the validity of the drive (note that in general provider_lookup
    // returns a default provider - serial-over-USB to the PC, which then
    // may do further checks
    if (endpoint == NULL) {
        debug_puts("ILLEGAL DRIVE: ");
        debug_putc(0x30+nameinfo.drive);
        debug_putcrlf();
        set_error_tsd(errormsg, CBM_ERROR_DRIVE_NOT_READY, 0, 0, nameinfo.drive);
        return -1;
    }
    provider_t *provider = endpoint->provider;

    // find open slot
    //int8_t slot = -1;
    open_t *activeslot = NULL;
    for (uint8_t i = 0; i < MAX_ACTIVE_OPEN; i++) {
        if (active[i].channel_no < 0) {
            //slot = i;
            activeslot = (open_t*) &active[i];
            break;
        }
    }
    //if (slot < 0) {
    if (activeslot == NULL) {
        debug_puts("NO OPEN SLOT FOR OPEN!");
        debug_putcrlf();
        set_error_tsd(errormsg, CBM_ERROR_NO_CHANNEL, 0, 0, nameinfo.drive);
        return -1;
    }

    activeslot->endpoint = endpoint;

    uint8_t len = assemble_filename_packet(cmd_buffer, &nameinfo);
#ifdef DEBUG_FILE
    debug_printf("LEN AFTER ASSEMBLE=%d\n", len);
#endif
    packet_init(&activeslot->txbuf, len, cmd_buffer);

    // store pointer to runtime config in packet
    // used by providers running on the device
    activeslot->txbuf.rtc = rtconf;

    packet_set_filled(&activeslot->txbuf, channel_no, type, len);

    if (!iscmd) {
        // only for file opens
        // note: we need the provider for the dir converter,
        // so we can only do it in here.

        // open channel
        uint8_t writetype = WTYPE_READONLY;
        if (type == FS_OPEN_WR || type == FS_OPEN_AP || type == FS_OPEN_OW) {
            writetype = WTYPE_WRITEONLY;
        } else if (type == FS_OPEN_RW) {
            writetype = WTYPE_READWRITE;
        }
        if (nameinfo.options & NAMEOPT_NONBLOCKING) {
            writetype |= WTYPE_NONBLOCKING;
        }

        int8_t (*converter)(void *, packet_t*, uint8_t) =
            (type == FS_OPEN_DR) ? (provider->directory_converter) : NULL;


        // TODO: if provider->channel_* are not NULL, we should probably not allocate a channel
        // but that would break the FILE OPEN detection here.
        channel_t *channel = channel_find(channel_no);
        if (channel != NULL) {
            // clean up
            channel_close(channel_no);
            // Note: it seems possible to open the same channel multiple times
            // on a direct file
            if (type != FS_OPEN_DIRECT) {
                debug_puts("FILE OPEN ERROR");
                debug_putcrlf();
                set_error_tsd(errormsg, CBM_ERROR_NO_CHANNEL, 0, 0, nameinfo.drive);
                return -1;
            }
        }
        int8_t e = channel_open(channel_no, writetype, endpoint, converter, nameinfo.drive);
        if (e < 0) {
            debug_puts("E=");
            debug_puthex(e);
            debug_putcrlf();
            set_error_tsd(errormsg, CBM_ERROR_NO_CHANNEL, 0, 0, nameinfo.drive);
            return -1;
        }
    }

    activeslot->callback = callback;

    // no more error here, just the submit.
    // so callers can be sure if this function returns <0, they do not need
    // to close the channel, as it has not been opened
    // If this function returns 0, a callback must be received and handled,
    // and the channel is already opened.

    activeslot->channel_no = channel_no;

    // prepare response buffer
    packet_init(&activeslot->rxbuf, OPEN_RX_DATA_LEN, activeslot->rxdata);

    provider->submit_call(endpoint->provdata, channel_no, &activeslot->txbuf,
                          &activeslot->rxbuf, _file_open_callback);

    return 0;
}